nx_server_plugin_sdk 1.0 Server Plugin SDK

debug.h
Go to the documentation of this file.
1 // Copyright 2018-present Network Optix, Inc. Licensed under MPL 2.0: www.mozilla.org/MPL/2.0/
2
3 #pragma once
4
12 #include <iostream>
13 #include <stdint.h>
14 #include <functional>
15 #include <sstream>
16 #include <memory>
17
18 #include <nx/kit/utils.h>
19
20 #if !defined(NX_KIT_API)
21 #define NX_KIT_API /*empty*/
22 #endif
23
24 namespace nx {
25 namespace kit {
26 namespace debug {
27
28 //-------------------------------------------------------------------------------------------------
29 // Tools
30
34 NX_KIT_API std::string srcFileRelativePath(const std::string& file);
35
39 NX_KIT_API std::string srcFileBaseNameWithoutExt(const std::string& file);
40
41 //-------------------------------------------------------------------------------------------------
42 // Output
43
45 #if defined(NX_PRINT_TO_QDEBUG)
46 #define NX_DEBUG_STREAM qDebug().nospace().noquote()
47 #define NX_DEBUG_ENDL ""
48 static inline QDebug operator<<(QDebug d, const std::string& s)
49 {
50 return d << QString::fromStdString(s);
51 }
52 #endif
53
54 #if !defined(NX_DEBUG_INI)
55
56 #define NX_DEBUG_INI ini().
57 #endif
58
59 #if !defined(NX_DEBUG_ENABLE_OUTPUT)
60
61 #define NX_DEBUG_ENABLE_OUTPUT NX_DEBUG_INI enableOutput
62 #endif
63
64 #if !defined(NX_PRINT_PREFIX)
65
66 #define NX_PRINT_PREFIX ::nx::kit::debug::detail::printPrefix(__FILE__)
67 #endif
68
69 #if !defined(NX_DEBUG_STREAM)
70
71 #define NX_DEBUG_STREAM *::nx::kit::debug::stream()
72 #endif
73
74 #if !defined(NX_DEBUG_ENDL)
75
76 #define NX_DEBUG_ENDL "\n"
77 #endif
78
83 NX_KIT_API std::ostream*& stream();
84
85 #if !defined(NX_PRINT)
86
90 #define NX_PRINT /* << args... */ \
91 nx::kit::debug::detail::Print(&(NX_DEBUG_STREAM), NX_DEBUG_ENDL) << NX_PRINT_PREFIX
92 #endif
93
97 #define NX_OUTPUT /* << args... */ \
98 for (/* Executed either once or never; `for` instead of `if` gives no warnings. */ \
99 int NX_KIT_DEBUG_DETAIL_CONCAT(nxOutput_, __line__) = 0; \
100 NX_KIT_DEBUG_DETAIL_CONCAT(nxOutput_, __line__) != 1 && (NX_DEBUG_ENABLE_OUTPUT); \
101 ++NX_KIT_DEBUG_DETAIL_CONCAT(nxOutput_, __line__) \
102 ) NX_PRINT
103
104 //-------------------------------------------------------------------------------------------------
105 // Assertions
106
122 #define NX_KIT_ASSERT(/* CONDITION, MESSAGE = "" */ ...) \
123 NX_KIT_DEBUG_DETAIL_MSVC_EXPAND(NX_KIT_DEBUG_DETAIL_GET_3RD_ARG( \
124 __VA_ARGS__, NX_KIT_DEBUG_DETAIL_ASSERT2, NX_KIT_DEBUG_DETAIL_ASSERT1, \
125 /* Helps to generate a reasonable compiler error. */ args_required)(__VA_ARGS__))
126
131 NX_KIT_API void intentionallyCrash(const char* message);
132
133 //-------------------------------------------------------------------------------------------------
134 // Print info
135
139 #define LL \
140 NX_PRINT << "####### LL line " + ::nx::kit::utils::toString(__LINE__) \
141 + NX_KIT_DEBUG_DETAIL_THREAD_ID \
142 + ", " + ::nx::kit::debug::srcFileRelativePath(__FILE__) \
143 /* The final semicolon allows to use this macro as a line prefix. */;
144
148 #define NX_PRINT_VALUE(VALUE) \
149 NX_PRINT << "####### " #VALUE ": " + ::nx::kit::utils::toString(VALUE)
150
154 #define NX_PRINT_HEX_DUMP(CAPTION, BYTES, SIZE) \
155 ::nx::kit::debug::detail::printHexDump( \
156 NX_KIT_DEBUG_DETAIL_PRINT_FUNC, (CAPTION), (const char*) (BYTES), (int) (SIZE))
157
161 NX_KIT_API std::string hexDumpLine(const char* bytes, int size, int bytesPerLine = 0);
162
163 #if !defined(NX_DEBUG_SAVE_DIR)
164
165 #define NX_DEBUG_SAVE_DIR ::nx::kit::IniConfig::iniFilesDir()
166 #endif
167
173 #define NX_SAVE_STR(FILENAME, STR) \
174 ::nx::kit::debug::detail::saveStr( \
175 NX_KIT_DEBUG_DETAIL_PRINT_FUNC, (NX_DEBUG_SAVE_DIR), (FILENAME), #STR, (STR))
176
180 #define NX_SAVE_BIN(FILENAME, BYTES, SIZE) \
181 ::nx::kit::debug::detail::saveBin( \
182 NX_KIT_DEBUG_DETAIL_PRINT_FUNC, (NX_DEBUG_SAVE_DIR), (FILENAME), (BYTES), (SIZE))
183
184 //-------------------------------------------------------------------------------------------------
185 // Time
186
187 #if !defined(NX_DEBUG_ENABLE_TIME)
188
189 #define NX_DEBUG_ENABLE_TIME NX_DEBUG_INI enableTime
190 #endif
191
195 #define NX_TIME_BEGIN(TAG) \
196 ::nx::kit::debug::detail::Timer nxTimer_##TAG( \
197 (NX_DEBUG_ENABLE_TIME), NX_KIT_DEBUG_DETAIL_PRINT_FUNC, #TAG)
198
203 #define NX_TIME_MARK(TAG, MARK) do \
204 { \
205 if (NX_DEBUG_ENABLE_TIME) \
206 nxTimer_##TAG.mark((MARK)); \
207 } while (0)
208
212 #define NX_TIME_END(TAG) do \
213 { \
214 if (NX_DEBUG_ENABLE_TIME) \
215 nxTimer_##TAG.finish(); \
216 } while (0)
217
218 //-------------------------------------------------------------------------------------------------
219 // Fps
220
221 #if !defined(NX_DEBUG_ENABLE_FPS)
222
223 #define NX_DEBUG_ENABLE_FPS NX_DEBUG_INI enableFps
224 #endif
225
230 #define NX_FPS(TAG, /*OPTIONAL_MARK*/...) do \
231 { \
232 if (NX_KIT_DEBUG_DETAIL_CONCAT(NX_DEBUG_ENABLE_FPS, TAG)) \
233 { \
234 static ::nx::kit::debug::detail::Fps fps( \
235 NX_KIT_DEBUG_DETAIL_PRINT_FUNC, #TAG); \
236 fps.mark(__VA_ARGS__); \
237 } \
238 } while (0)
239
240 //-------------------------------------------------------------------------------------------------
241 // Implementation
242
243 namespace detail {
244
246 class Print: public std::ostringstream
247 {
248 public:
249 Print(std::ostream* outputStream, const char* const newline):
250 m_outputStream(outputStream), m_newline(newline)
251 {
252 }
253
254 ~Print()
255 {
256 (*this) << m_newline;
257 *m_outputStream << (*this).str(); //< Perform the actual output.
258 }
259
260 private:
261 std::ostream* m_outputStream;
262 const char* const m_newline;
263 };
264
265 typedef std::function<void(const char*)> PrintFunc;
266
267 #define NX_KIT_DEBUG_DETAIL_PRINT_FUNC ([&](const char* message) { NX_PRINT << message; })
268
273 #define NX_KIT_DEBUG_DETAIL_MSVC_EXPAND(ARG) ARG
274
276 #define NX_KIT_DEBUG_DETAIL_GET_3RD_ARG(ARG1, ARG2, ARG3, ...) ARG3
277
278 #define NX_KIT_DEBUG_DETAIL_ASSERT1(CONDITION) \
279 ::nx::kit::debug::detail::doAssert( \
280 !!(CONDITION), NX_KIT_DEBUG_DETAIL_PRINT_FUNC, #CONDITION, "", __FILE__, __LINE__)
281
282 #define NX_KIT_DEBUG_DETAIL_ASSERT2(CONDITION, MESSAGE) \
283 ::nx::kit::debug::detail::doAssert( \
284 !!(CONDITION), NX_KIT_DEBUG_DETAIL_PRINT_FUNC, #CONDITION, MESSAGE, __FILE__, __LINE__)
285
286 NX_KIT_API void assertionFailed(
287 PrintFunc printFunc, const char* conditionStr, const std::string& message,
288 const char* file, int line);
289
290 inline bool doAssert(
291 bool condition, PrintFunc printFunc, const char* conditionStr, const std::string& message,
292 const char* file, int line)
293 {
294 if (!condition)
295 assertionFailed(printFunc, conditionStr, message, file, line);
296 return condition;
297 }
298
299 #define NX_KIT_DEBUG_DETAIL_CONCAT(X, Y) NX_KIT_DEBUG_DETAIL_CONCAT2(X, Y)
300 #define NX_KIT_DEBUG_DETAIL_CONCAT2(X, Y) X##Y
301
303 NX_KIT_API std::string printPrefix(const char* file);
304
305 class NX_KIT_API Timer
306 {
307 public:
308 Timer(bool enabled, PrintFunc printFunc, const char* tag);
309 ~Timer();
310 void mark(const char* markStr);
311 void finish();
312
313 private:
314 struct Impl;
315 Impl* const d;
316 };
317
318 class NX_KIT_API Fps
319 {
320 public:
321 Fps(PrintFunc printFunc, const char* tag);
322 ~Fps();
323 void mark(const char* markStr = nullptr);
324
325 private:
326 struct Impl;
327 Impl* const d;
328 };
329
330 NX_KIT_API void printHexDump(
331 PrintFunc printFunc, const char* caption, const char* bytes, int size);
332
333 NX_KIT_API void saveStr(
334 PrintFunc printFunc,
335 const char* originDir,
336 const char* filename,
337 const char* strCaption,
338 const std::string& str);
339
340 NX_KIT_API void saveBin(
341 PrintFunc printFunc,
342 const char* originDir,
343 const char* filename,
344 const char* bytes,
345 int size);
346
347 } // namespace detail
348
349 } // namespace debug
350 } // namespace kit
351 } // namespace nx
352
353 // Define NX_KIT_DEBUG_DETAIL_THREAD_ID.
354 #if defined(__linux__)
355 #if defined(__has_include) //< This C++17 feature was available in GCC/Clang long before.
356 #if __has_include(<pthread.h>)
357 #include <pthread.h>
358 #define NX_KIT_DEBUG_DETAIL_THREAD_ID \
359 ::nx::kit::utils::format(", thread %llx", (long long) pthread_self())
360 #endif
361 #endif
362 #elif defined(QT_CORE_LIB)
363 #include <QtCore/QThread>
364 #define NX_KIT_DEBUG_DETAIL_THREAD_ID \
365 ::nx::kit::utils::format(", thread %llx", (long long) QThread::currentThreadId())
366 #endif
367 #if !defined(NX_KIT_DEBUG_DETAIL_THREAD_ID)
368 // No threading libs available - do not print thread id.
369 #define NX_KIT_DEBUG_DETAIL_THREAD_ID ""
370 #endif
nx::kit::debug::detail::Fps
Definition: debug.h:318
utils.h
nx::kit::debug::detail::Fps::Impl
Definition: debug.cpp:309
nx::kit::debug::detail::Timer::Impl
Definition: debug.cpp:234
nx
Definition: apple_utils.h:6
nx::kit::debug::detail::Print
Definition: debug.h:246
nx::kit::debug::detail::Timer
Definition: debug.h:305