-
Notifications
You must be signed in to change notification settings - Fork 4
/
tracer.hpp
124 lines (101 loc) · 4.38 KB
/
tracer.hpp
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
/* SPDX-License-Identifier: Apache-2.0
* Copyright (C) 2019 Constantine Shulyupin
* Original: https://gitlab.com/makelinux/lib/blob/master/tracer.hpp
*/
#pragma once
#include <string>
#include <sstream>
#include <iostream>
#include <string.h>
#if __cplusplus >= 201103
#include <chrono>
#endif
/** \cond */
#ifndef __file__
#define ctracer_cut_path(fn) (fn[0] != '/' ? fn : (strrchr(fn, '/') + 1))
#define __file__ ctracer_cut_path(__FILE__)
#endif
#define file_line() (std::string(__file__) + ":" + std::to_string(__LINE__) + ": " + __func__ + " ")
#define _strlen(s) std::char_traits<char>::length(s)
namespace tracer
{
static inline const std::string to_string() {return "";}
static inline const std::string to_string(const std::string &s) {return '"' + s + '"';}
static inline const std::string to_string(void * const p) {std::stringstream s; s << p; return s.str();}
// for char *
static inline const std::string to_string(const char * c) {return '"' + std::string(c) + '"';}
// for const char x[]
static inline const std::string to_string(char * const c) {return '"' + std::string(c) + '"';}
#if __cplusplus >= 201103
template <typename T>
static inline const std::string to_string(const T &s) {return std::to_string(s);}
#endif
template <typename T>
static inline const std::string to_string(T * const p) {return to_string((void *)p);}
#ifndef log_str
#define log_str(a) do { std::cerr << a << std::endl; } while (0)
#endif
#ifdef __cpp_if_constexpr
#define _IF(x) if constexpr (x)
#else
#define _IF(x) if (x)
#endif
// prints name=value or just raw value for literal strings
#define _v(a) ({auto as = tracer::to_string(a); _strlen(#a) ? \
/* if it is literal */ \
(as == #a) ? \
/* Assuming string literal within '"'. */ \
/* Getting just content of string literal. */ \
std::string(#a).substr(1, std::string(#a).length() - 2) + " " \
/* else */ \
: std::string(#a) + "=" + as + " " : ""; })
#define _trace2(s, a, args...) do { s << _v(a); _IF (!!_strlen(#args)) s << _v(args); } while (0)
#define _trace3(s, a, args...) do { s << _v(a); _IF (!!_strlen(#args)) _trace2(s, args); } while (0)
#define _trace4(s, a, args...) do { s << _v(a); _IF (!!_strlen(#args)) _trace3(s, args); } while (0)
#define _trace5(s, a, args...) do { s << _v(a); _IF (!!_strlen(#args)) _trace4(s, args); } while (0)
#define _trace6(s, a, args...) do { s << _v(a); _IF (!!_strlen(#args)) _trace5(s, args); } while (0)
#define _trace7(s, a, args...) do { s << _v(a); _IF (!!_strlen(#args)) _trace6(s, args); } while (0)
#define _trace8(s, a, args...) do { s << _v(a); _IF (!!_strlen(#args)) _trace7(s, args); } while (0)
#define _trace9(s, a, args...) do { s << _v(a); _IF (!!_strlen(#args)) _trace8(s, args); } while (0)
#define _traceA(s, a, args...) do { s << _v(a); _IF (!!_strlen(#args)) _trace9(s, args); } while (0)
#define _traceB(s, a, args...) do { s << _v(a); _IF (!!_strlen(#args)) _traceA(s, args); } while (0)
#define _traceC(s, a, args...) do { s << _v(a); _IF (!!_strlen(#args)) _traceB(s, args); } while (0)
#define _traceD(s, a, args...) do { s << _v(a); _IF (!!_strlen(#args)) _traceC(s, args); } while (0)
#define _traceE(s, a, args...) do { s << _v(a); _IF (!!_strlen(#args)) _traceD(s, args); } while (0)
#define _traceF(s, a, args...) do { s << _v(a); _IF (!!_strlen(#args)) _traceE(s, args); } while (0)
/** \endcond */
/**
* \brief Universal C++ tracing function
*
* Accepts from none to 16 arguments.
* Prints file and line number, arguments names and values.
*
* Example source code:
* trace(i, s);
*
* Output:
* tracer-hpp-test.cpp:33:main i=-123 s="string value"
*
* See file tracer-hpp-test.cpp for more examples.
*/
#define trace(a, args...) \
do { std::stringstream log; \
log << file_line() << _v(a); \
_IF(!!_strlen(#args)) \
_traceF(log, args); \
log_str(log.str()); \
} while (0)
#if __cplusplus >= 201103
static inline double duration(std::chrono::time_point<std::chrono::steady_clock> start)
{
return std::chrono::duration<double> {std::chrono::steady_clock::now() - start}.count();
}
struct _duration {
std::chrono::time_point<std::chrono::steady_clock> start;
std::string file_line;
explicit _duration(std::string fl) { file_line = fl; start = std::chrono::steady_clock::now(); }
~_duration() {log_str(file_line + "duration = " + to_string(duration(start)));}
};
#define measure_block_duration() tracer::_duration _block_duration(file_line());
#endif
} // namespace tracer