Direct-BT  2.3.1
Direct-BT - Direct Bluetooth Programming.
debug.hpp
Go to the documentation of this file.
1 /*
2  * Author: Sven Gothel <sgothel@jausoft.com>
3  * Copyright (c) 2020 Gothel Software e.K.
4  * Copyright (c) 2020 ZAFENA AB
5  *
6  * Permission is hereby granted, free of charge, to any person obtaining
7  * a copy of this software and associated documentation files (the
8  * "Software"), to deal in the Software without restriction, including
9  * without limitation the rights to use, copy, modify, merge, publish,
10  * distribute, sublicense, and/or sell copies of the Software, and to
11  * permit persons to whom the Software is furnished to do so, subject to
12  * the following conditions:
13  *
14  * The above copyright notice and this permission notice shall be
15  * included in all copies or substantial portions of the Software.
16  *
17  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
20  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
21  * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
22  * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
23  * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24  */
25 
26 #ifndef JAU_DEBUG_HPP_
27 #define JAU_DEBUG_HPP_
28 
29 #include <memory>
30 
31 #include <cstdint>
32 #include <cinttypes>
33 #include <cstring>
34 #include <string>
35 #include <cstdio>
36 #include <cstdarg>
37 
38 extern "C" {
39  #include <errno.h>
40 }
41 
42 #include <jau/environment.hpp>
43 
44 // #define PERF_PRINT_ON 1
45 
46 namespace jau {
47 
48  /**
49  * Returns a de-mangled backtrace string separated by newline excluding this function.
50  * <p>
51  * Returns one line per stack frame, each with
52  * <pre>
53  * - stack frame number
54  * - demangled function name + offset (sp)
55  * - the instruction pointer (pc)
56  * - the stack pointer (sp)
57  * </pre>
58  * </p>
59  * @param skip_anon_frames if true, skip all frames w/o proc-name
60  * @param skip_frames number of stack frames to skip, default is one frame for this function.
61  * @param max_frames number of stack frames to be printed or -1 for unlimited, defaults to -1
62  * @return the de-mangled backtrace, separated by newline
63  */
64  std::string get_backtrace(const bool skip_anon_frames, const jau::snsize_t max_frames=-1, const jau::nsize_t skip_frames=1) noexcept;
65 
66  /**
67  * Prints the de-mangled backtrace string separated by newline excluding this function to stderr, using get_backtrace().
68  * @param skip_anon_frames if true, skip all frames w/o proc-name
69  * @param max_frames number of stack frames to be printed or -1 for unlimited, defaults to -1
70  * @param skip_frames number of stack frames to skip, default is two frames for this function and for get_backtrace().
71  * @see get_backtrace()
72  */
73  void print_backtrace(const bool skip_anon_frames, const jau::snsize_t max_frames=-1, const jau::nsize_t skip_frames=2) noexcept;
74 
75  void DBG_PRINT_impl(const char * format, ...) noexcept;
76 
77  /** Use for environment-variable environment::DEBUG conditional debug messages, prefix '[elapsed_time] Debug: '. */
78  #define DBG_PRINT(...) { if( jau::environment::get().debug ) { jau::DBG_PRINT_impl(__VA_ARGS__); } }
79 
80  /** Use for environment-variable environment::DEBUG_JNI conditional debug messages, prefix '[elapsed_time] Debug: '. */
81  #define DBG_JNI_PRINT(...) { if( jau::environment::get().debug_jni ) { jau::DBG_PRINT_impl(__VA_ARGS__); } }
82 
83  void WORDY_PRINT_impl(const char * format, ...) noexcept;
84 
85  /**
86  * Use for environment-variable environment::VERBOSE conditional verbose messages, prefix '[elapsed_time] Wordy: '.
87  * <p>
88  * 'Wordy' is the shorter English form of the Latin word 'verbosus', from which the word 'verbosity' is sourced.
89  * </p>
90  */
91  #define WORDY_PRINT(...) { if( jau::environment::get().verbose ) { jau::WORDY_PRINT_impl(__VA_ARGS__); } }
92 
93 
94  #define PERF_TS_T0_BASE() const uint64_t _t0 = jau::getCurrentMilliseconds()
95 
96  #define PERF_TS_TD_BASE(m) { const uint64_t _td = jau::getCurrentMilliseconds() - _t0; \
97  fprintf(stderr, "[%'9" PRIu64 "] PERF %s done in %d ms,\n", jau::environment::getElapsedMillisecond(), (m), (int)_td); }
98  #ifdef PERF_PRINT_ON
99  #define PERF_TS_T0() PERF_TS_T0_BASE()
100  #define PERF_TS_TD(m) PERF_TS_TD_BASE(m)
101  #else
102  #define PERF_TS_T0()
103  #define PERF_TS_TD(m)
104  #endif
105  #ifdef PERF2_PRINT_ON
106  #define PERF2_TS_T0() PERF_TS_T0_BASE()
107  #define PERF2_TS_TD(m) PERF_TS_TD_BASE(m)
108  #else
109  #define PERF2_TS_T0()
110  #define PERF2_TS_TD(m)
111  #endif
112  #ifdef PERF3_PRINT_ON
113  #define PERF3_TS_T0() PERF_TS_T0_BASE()
114  #define PERF3_TS_TD(m) PERF_TS_TD_BASE(m)
115  #else
116  #define PERF3_TS_T0()
117  #define PERF3_TS_TD(m)
118  #endif
119 
120  /** Use for unconditional ::abort() call with given messages, prefix '[elapsed_time] ABORT @ file:line: '. Function also appends last errno and strerror(errno). */
121  void ABORT_impl(const char *func, const char *file, const int line, const char * format, ...) noexcept;
122 
123  /** Use for unconditional ::abort() call with given messages, prefix '[elapsed_time] ABORT @ FILE:LINE: '. Function also appends last errno and strerror(errno). */
124  #define ABORT(...) { jau::ABORT_impl(__func__, __FILE__, __LINE__, __VA_ARGS__); }
125 
126  /** Use for unconditional error messages, prefix '[elapsed_time] Error @ file:line: '. Function also appends last errno and strerror(errno). */
127  void ERR_PRINTv(const char *func, const char *file, const int line, const char * format, va_list args) noexcept;
128 
129  void ERR_PRINT_impl(const char *prefix, const bool backtrace, const char *func, const char *file, const int line, const char * format, ...) noexcept;
130 
131  /** Use for unconditional error messages, prefix '[elapsed_time] Error @ FILE:LINE: '. Function also appends last errno, strerror(errno) and full backtrace*/
132  #define ERR_PRINT(...) { jau::ERR_PRINT_impl("Error", true /* backtrace */, __func__, __FILE__, __LINE__, __VA_ARGS__); }
133 
134  /** Use for unconditional error messages, prefix '[elapsed_time] Error @ FILE:LINE: '. Function also appends last errno and strerror(errno). No backtrace. */
135  #define ERR_PRINT2(...) { jau::ERR_PRINT_impl("Error", false /* backtrace */, __func__, __FILE__, __LINE__, __VA_ARGS__); }
136 
137  /** Use for unconditional interruption messages, prefix '[elapsed_time] Interrupted @ FILE:LINE: '. Function also appends last errno and strerror(errno). */
138  #define IRQ_PRINT(...) { jau::ERR_PRINT_impl("Interrupted", false /* backtrace */, __func__, __FILE__, __LINE__, __VA_ARGS__); }
139 
140  /** Use for unconditional warning messages, prefix '[elapsed_time] Warning @ file:line: ' */
141  void WARN_PRINTv(const char *func, const char *file, const int line, const char * format, va_list args) noexcept;
142 
143  void WARN_PRINT_impl(const char *func, const char *file, const int line, const char * format, ...) noexcept;
144 
145  /** Use for unconditional warning messages, prefix '[elapsed_time] Warning @ FILE:LINE: ' */
146  #define WARN_PRINT(...) { jau::WARN_PRINT_impl(__func__, __FILE__, __LINE__, __VA_ARGS__); }
147 
148  /** Use for unconditional informal messages, prefix '[elapsed_time] Info: '. */
149  void INFO_PRINT(const char * format, ...) noexcept;
150 
151  /** Use for unconditional plain messages, prefix '[elapsed_time] ' if printPrefix == true. */
152  void PLAIN_PRINT(const bool printPrefix, const char * format, ...) noexcept;
153 
154  /**
155  * Convenient fprintf() invocation, prepending the environment::getElapsedMillisecond() timestamp.
156  * @param stream the output stream
157  * @param format the format
158  * @param args the optional arguments
159  */
160  int fprintf_td(FILE* stream, const char * format, ...) noexcept;
161 
162  void COND_PRINT_impl(const char * format, ...) noexcept;
163 
164  /** Use for conditional plain messages, prefix '[elapsed_time] '. */
165  #define COND_PRINT(C, ...) { if( C ) { jau::COND_PRINT_impl(__VA_ARGS__); } }
166 
167 
168  template<class List>
169  inline void printSharedPtrList(std::string prefix, List & list) noexcept {
170  fprintf(stderr, "%s: Start: %zu elements\n", prefix.c_str(), (size_t)list.size());
171  int idx = 0;
172  for (auto it = list.begin(); it != list.end(); idx++) {
173  typename List::value_type & e = *it;
174  if ( nullptr != e ) {
175  fprintf(stderr, "%s[%d]: useCount %zu, mem %p\n", prefix.c_str(), idx, (size_t)e.use_count(), e.get());
176  } else {
177  fprintf(stderr, "%s[%d]: NULL\n", prefix.c_str(), idx);
178  }
179  ++it;
180  }
181  }
182 
183 } // namespace jau
184 
185 #endif /* JAU_DEBUG_HPP_ */
jau::print_backtrace
void print_backtrace(const bool skip_anon_frames, const jau::snsize_t max_frames=-1, const jau::nsize_t skip_frames=2) noexcept
Prints the de-mangled backtrace string separated by newline excluding this function to stderr,...
Definition: debug.cpp:91
jau
Definition: basic_algos.hpp:34
jau::WORDY_PRINT_impl
void WORDY_PRINT_impl(const char *format,...) noexcept
Definition: debug.cpp:106
jau::get_backtrace
std::string get_backtrace(const bool skip_anon_frames, const jau::snsize_t max_frames=-1, const jau::nsize_t skip_frames=1) noexcept
Returns a de-mangled backtrace string separated by newline excluding this function.
Definition: debug.cpp:36
jau::ERR_PRINTv
void ERR_PRINTv(const char *func, const char *file, const int line, const char *format, va_list args) noexcept
Use for unconditional error messages, prefix '[elapsed_time] Error @ file:line: '.
Definition: debug.cpp:128
jau::fprintf_td
int fprintf_td(FILE *stream, const char *format,...) noexcept
Convenient fprintf() invocation, prepending the environment::getElapsedMillisecond() timestamp.
Definition: debug.cpp:188
jau::INFO_PRINT
void INFO_PRINT(const char *format,...) noexcept
Use for unconditional informal messages, prefix '[elapsed_time] Info: '.
Definition: debug.cpp:166
jau::WARN_PRINT_impl
void WARN_PRINT_impl(const char *func, const char *file, const int line, const char *format,...) noexcept
Definition: debug.cpp:156
jau::PLAIN_PRINT
void PLAIN_PRINT(const bool printPrefix, const char *format,...) noexcept
Use for unconditional plain messages, prefix '[elapsed_time] ' if printPrefix == true.
Definition: debug.cpp:176
jau::snsize_t
int_fast32_t snsize_t
Natural 'ssize_t' alternative using int_fast32_t as its natural sized type.
Definition: int_types.hpp:56
jau::nsize_t
uint_fast32_t nsize_t
Natural 'size_t' alternative using uint_fast32_t as its natural sized type.
Definition: int_types.hpp:44
jau::ERR_PRINT_impl
void ERR_PRINT_impl(const char *prefix, const bool backtrace, const char *func, const char *file, const int line, const char *format,...) noexcept
Definition: debug.cpp:136
jau::WARN_PRINTv
void WARN_PRINTv(const char *func, const char *file, const int line, const char *format, va_list args) noexcept
Use for unconditional warning messages, prefix '[elapsed_time] Warning @ file:line: '.
Definition: debug.cpp:149
jau::printSharedPtrList
void printSharedPtrList(std::string prefix, List &list) noexcept
Definition: debug.hpp:169
jau::ABORT_impl
void ABORT_impl(const char *func, const char *file, const int line, const char *format,...) noexcept
Use for unconditional ::abort() call with given messages, prefix '[elapsed_time] ABORT @ file:line: '...
Definition: debug.cpp:116
jau::COND_PRINT_impl
void COND_PRINT_impl(const char *format,...) noexcept
Definition: debug.cpp:197
environment.hpp
jau::DBG_PRINT_impl
void DBG_PRINT_impl(const char *format,...) noexcept
Definition: debug.cpp:96