aboutsummaryrefslogtreecommitdiff
path: root/include/util/io.h
blob: 6fb2a29d424d19d6fed5f716a93b12aaf18e1f0b (plain)
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

#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 "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);

}