1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
|
#pragma once
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <ctype.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <errno.h>
#include <iostream>
#include <vector>
#include <string>
#include <type_traits>
#include <print>
#include "global.h"
#define LOG !(ov4::GLOBAL_DEBUG && verbose) ? (void)0 : ov4::LogVoidify() & std::clog
namespace ov4
{
struct LogVoidify { void operator&(std::ostream&) const {} };
inline constexpr int DECIMAL = 10;
inline constexpr int NUMBER_LENGTH = 70; // even enough for binary
// async-signal-safe
void safe_print(const char *s, bool ignore_wrap = false);
// async-signal-safe
void safe_print(int x);
// async-signal-safe
void safe_debug(const char *s, bool ignore_wrap = false);
// async-signal-safe
void safe_debug(int x);
// async-signal-safe
bool isnum(const char *s);
// async-signal-safe
void reverse(char *str, int length);
// async-signal-safe
char *itoa(int num, char* str, int base);
// async-signal-safe
// remove '\n' from the string
// when replacemen = '\0', '\n' is deleted (instead of really replacing by '\0' )
void wrap_eliminator(char *s, char replacement = '\0');
// async-signal-safe
void _write_helper(const char *s);
template <typename T>
void _safe_output_handler(T x)
{
int errno_old = errno;
if constexpr (std::is_same_v<T, int>) // int
{
char buffer[MAXLINE];
itoa(x, buffer, DECIMAL);
_write_helper(buffer);
}
else if constexpr (std::is_same_v<T, char*> || std::is_same_v<T, const char*>) // C-style string
{
_write_helper(x);
}
else // ???
{
static_assert(false, "_safe_output_handler: unsopported type");
}
errno = errno_old;
}
inline void safe_output()
{
; // empty
}
// async-signal-safe output function
// example:
// safe_output("string", 123, variable);
template <typename T, typename ...T_arg>
void safe_output(T x, T_arg ...arg)
{
int errno_old = errno;
_safe_output_handler(x);
safe_output(arg...);
errno = errno_old;
}
void unix_error(const char *msg);
void app_error(const char *msg);
template<class ...Args>
void logger(std::format_string<Args...> fmt, Args&&... args)
{
if constexpr (GLOBAL_DEBUG)
{
if (verbose)
{
print(std::clog, fmt, std::forward<Args>(args)...);
std::clog.flush();
}
}
}
template<class ...Args>
void loggerln(std::format_string<Args...> fmt, Args&&... args)
{
if constexpr (GLOBAL_DEBUG)
{
if (verbose)
{
println(std::clog, fmt, std::forward<Args>(args)...);
std::clog.flush();
}
}
}
}
|