nx_metadata_sdk 1.0 Metadata 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
32 NX_KIT_API char pathSeparator();
33
34 NX_KIT_API size_t commonPrefixSize(const std::string& s1, const std::string& s2);
35
40 NX_KIT_API const char* relativeSrcFilename(const char* file);
41
42 NX_KIT_API std::string fileBaseNameWithoutExt(const char* file);
43
44 //-------------------------------------------------------------------------------------------------
45 // Output
46
48 #if defined(NX_PRINT_TO_QDEBUG)
49 #define NX_DEBUG_STREAM qDebug().nospace().noquote()
50 #define NX_DEBUG_ENDL /*empty*/
51 static inline QDebug operator<<(QDebug d, const std::string& s)
52 {
53 return d << QString::fromStdString(s);
54 }
55 #endif
56
57 #if !defined(NX_DEBUG_INI)
58
59 #define NX_DEBUG_INI ini().
60 #endif
61
62 #if !defined(NX_DEBUG_ENABLE_OUTPUT)
63
64 #define NX_DEBUG_ENABLE_OUTPUT NX_DEBUG_INI enableOutput
65 #endif
66
67 #if !defined(NX_PRINT_PREFIX)
68
69 #define NX_PRINT_PREFIX ::nx::kit::debug::detail::printPrefix(__FILE__)
70 #endif
71
72 #if !defined(NX_DEBUG_STREAM)
73
74 #define NX_DEBUG_STREAM *::nx::kit::debug::stream()
75 #endif
76
77 #if !defined(NX_DEBUG_ENDL)
78
79 #define NX_DEBUG_ENDL << std::endl
80 #endif
81
86 NX_KIT_API std::ostream*& stream();
87
88 #if !defined(NX_PRINT)
89
93 #define NX_PRINT /* << args... */ \
94 /* Allocate a temp value, which prints endl in its destructor, in the "<<" expression. */ \
95 ( []() { struct Endl { ~Endl() { NX_DEBUG_STREAM NX_DEBUG_ENDL; } }; \
96 return std::make_shared<Endl>(); }() ) /*operator,*/, \
97 NX_DEBUG_STREAM << NX_PRINT_PREFIX
98 #endif
99
103 #define NX_OUTPUT /* << args... */ \
104 for (/* Executed either once or never; `for` instead of `if` gives no warnings. */ \
105 int NX_KIT_DEBUG_DETAIL_CONCAT(nxOutput_, __line__) = 0; \
106 NX_KIT_DEBUG_DETAIL_CONCAT(nxOutput_, __line__) != 1 && (NX_DEBUG_ENABLE_OUTPUT); \
107 ++NX_KIT_DEBUG_DETAIL_CONCAT(nxOutput_, __line__) \
108 ) NX_PRINT
109
110 //-------------------------------------------------------------------------------------------------
111 // Assertions
112
128 #define NX_KIT_ASSERT(/* CONDITION, MESSAGE = "" */ ...) \
129 NX_KIT_DEBUG_DETAIL_MSVC_EXPAND(NX_KIT_DEBUG_DETAIL_GET_3RD_ARG( \
130 __VA_ARGS__, NX_KIT_DEBUG_DETAIL_ASSERT2, NX_KIT_DEBUG_DETAIL_ASSERT1, \
131 /* Helps to generate a reasonable compiler error. */ args_required)(__VA_ARGS__))
132
137 NX_KIT_API void intentionallyCrash(const char* message);
138
139 //-------------------------------------------------------------------------------------------------
140 // Print info
141
145 #define LL \
146 NX_PRINT << "####### LL line " + ::nx::kit::utils::toString(__LINE__) \
147 + NX_KIT_DEBUG_DETAIL_THREAD_ID() \
148 + ", file " + ::nx::kit::debug::relativeSrcFilename(__FILE__);
149
153 #define NX_PRINT_VALUE(VALUE) \
154 NX_PRINT << "####### " #VALUE ": " + ::nx::kit::utils::toString(VALUE)
155
159 #define NX_PRINT_HEX_DUMP(CAPTION, BYTES, SIZE) \
160 ::nx::kit::debug::detail::printHexDump( \
161 NX_KIT_DEBUG_DETAIL_PRINT_FUNC, (CAPTION), (const char*) (BYTES), (int) (SIZE))
162
166 NX_KIT_API std::string hexDumpLine(const char* bytes, int size, int bytesPerLine = 0);
167
168 #if !defined(NX_DEBUG_SAVE_DIR)
169
170 #define NX_DEBUG_SAVE_DIR ::nx::kit::IniConfig::iniFilesDir()
171 #endif
172
178 #define NX_SAVE_STR(FILENAME, STR) \
179 ::nx::kit::debug::detail::saveStr( \
180 NX_KIT_DEBUG_DETAIL_PRINT_FUNC, (NX_DEBUG_SAVE_DIR), (FILENAME), #STR, (STR))
181
185 #define NX_SAVE_BIN(FILENAME, BYTES, SIZE) \
186 ::nx::kit::debug::detail::saveBin( \
187 NX_KIT_DEBUG_DETAIL_PRINT_FUNC, (NX_DEBUG_SAVE_DIR), (FILENAME), (BYTES), (SIZE))
188
189 //-------------------------------------------------------------------------------------------------
190 // Time
191
192 #if !defined(NX_DEBUG_ENABLE_TIME)
193
194 #define NX_DEBUG_ENABLE_TIME NX_DEBUG_INI enableTime
195 #endif
196
200 #define NX_TIME_BEGIN(TAG) \
201 ::nx::kit::debug::detail::Timer nxTimer_##TAG( \
202 (NX_DEBUG_ENABLE_TIME), NX_KIT_DEBUG_DETAIL_PRINT_FUNC, #TAG)
203
208 #define NX_TIME_MARK(TAG, MARK) do \
209 { \
210 if (NX_DEBUG_ENABLE_TIME) \
211 nxTimer_##TAG.mark((MARK)); \
212 } while (0)
213
217 #define NX_TIME_END(TAG) do \
218 { \
219 if (NX_DEBUG_ENABLE_TIME) \
220 nxTimer_##TAG.finish(); \
221 } while (0)
222
223 //-------------------------------------------------------------------------------------------------
224 // Fps
225
226 #if !defined(NX_DEBUG_ENABLE_FPS)
227
228 #define NX_DEBUG_ENABLE_FPS NX_DEBUG_INI enableFps
229 #endif
230
235 #define NX_FPS(TAG, /*OPTIONAL_MARK*/...) do \
236 { \
237 if (NX_KIT_DEBUG_DETAIL_CONCAT(NX_DEBUG_ENABLE_FPS, TAG)) \
238 { \
239 static ::nx::kit::debug::detail::Fps fps( \
240 NX_KIT_DEBUG_DETAIL_PRINT_FUNC, #TAG); \
241 fps.mark(__VA_ARGS__); \
242 } \
243 } while (0)
244
245 //-------------------------------------------------------------------------------------------------
246 // Implementation
247
248 namespace detail {
249
250 typedef std::function<void(const char*)> PrintFunc;
251
252 #define NX_KIT_DEBUG_DETAIL_PRINT_FUNC ([&](const char* message) { NX_PRINT << message; })
253
258 #define NX_KIT_DEBUG_DETAIL_MSVC_EXPAND(ARG) ARG
259
261 #define NX_KIT_DEBUG_DETAIL_GET_3RD_ARG(ARG1, ARG2, ARG3, ...) ARG3
262
263 #define NX_KIT_DEBUG_DETAIL_ASSERT1(CONDITION) \
264 ::nx::kit::debug::detail::doAssert( \
265 !!(CONDITION), NX_KIT_DEBUG_DETAIL_PRINT_FUNC, #CONDITION, "", __FILE__, __LINE__)
266
267 #define NX_KIT_DEBUG_DETAIL_ASSERT2(CONDITION, MESSAGE) \
268 ::nx::kit::debug::detail::doAssert( \
269 !!(CONDITION), NX_KIT_DEBUG_DETAIL_PRINT_FUNC, #CONDITION, MESSAGE, __FILE__, __LINE__)
270
271 NX_KIT_API void assertionFailed(
272 PrintFunc printFunc, const char* conditionStr, const std::string& message,
273 const char* file, int line);
274
275 inline bool doAssert(
276 bool condition, PrintFunc printFunc, const char* conditionStr, const std::string& message,
277 const char* file, int line)
278 {
279 if (!condition)
280 assertionFailed(printFunc, conditionStr, message, file, line);
281 return condition;
282 }
283
284 #define NX_KIT_DEBUG_DETAIL_CONCAT(X, Y) NX_KIT_DEBUG_DETAIL_CONCAT2(X, Y)
285 #define NX_KIT_DEBUG_DETAIL_CONCAT2(X, Y) X##Y
286
288 NX_KIT_API std::string printPrefix(const char* file);
289
290 class NX_KIT_API Timer
291 {
292 public:
293 Timer(bool enabled, PrintFunc printFunc, const char* tag);
294 ~Timer();
295 void mark(const char* markStr);
296 void finish();
297
298 private:
299 struct Impl;
300 Impl* const d;
301 };
302
303 class NX_KIT_API Fps
304 {
305 public:
306 Fps(PrintFunc printFunc, const char* tag);
307 ~Fps();
308 void mark(const char* markStr = nullptr);
309
310 private:
311 struct Impl;
312 Impl* const d;
313 };
314
315 NX_KIT_API void printHexDump(
316 PrintFunc printFunc, const char* caption, const char* bytes, int size);
317
318 NX_KIT_API void saveStr(
319 PrintFunc printFunc,
320 const char* originDir,
321 const char* filename,
322 const char* strCaption,
323 const std::string& str);
324
325 NX_KIT_API void saveBin(
326 PrintFunc printFunc,
327 const char* originDir,
328 const char* filename,
329 const char* bytes,
330 int size);
331
332 } // namespace detail
333
334 } // namespace debug
335 } // namespace kit
336 } // namespace nx
337
338 #if defined(__linux__)
339 #include <pthread.h>
340 #define NX_KIT_DEBUG_DETAIL_THREAD_ID() \
341 ::nx::kit::utils::format(", thread %llx", (long long) pthread_self())
342 #elif defined(QT_CORE_LIB)
343 #include <QtCore/QThread>
344 #define NX_KIT_DEBUG_DETAIL_THREAD_ID() \
345 ::nx::kit::utils::format(", thread %llx", (long long) QThread::currentThreadId())
346 #else
347 // No threading libs available - do not print thread id.
348 #define NX_KIT_DEBUG_DETAIL_THREAD_ID() ""
349 #endif
nx::kit::debug::detail::Fps
Definition: debug.h:303
utils.h
nx::kit::debug::detail::Fps::Impl
Definition: debug.cpp:339
nx::kit::debug::detail::Timer::Impl
Definition: debug.cpp:264
nx
Definition: apple_utils.h:6
nx::kit::debug::detail::Timer
Definition: debug.h:290