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 
176 #define NX_SAVE_STR(FILENAME, STR) \
177  ::nx::kit::debug::detail::saveStr( \
178  NX_KIT_DEBUG_DETAIL_PRINT_FUNC, (NX_DEBUG_SAVE_DIR), (FILENAME), #STR, (STR))
179 
180 //-------------------------------------------------------------------------------------------------
181 // Time
182 
183 #if !defined(NX_DEBUG_ENABLE_TIME)
184 
185  #define NX_DEBUG_ENABLE_TIME NX_DEBUG_INI enableTime
186 #endif
187 
191 #define NX_TIME_BEGIN(TAG) \
192  ::nx::kit::debug::detail::Timer nxTimer_##TAG( \
193  (NX_DEBUG_ENABLE_TIME), NX_KIT_DEBUG_DETAIL_PRINT_FUNC, #TAG)
194 
199 #define NX_TIME_MARK(TAG, MARK) do \
200 { \
201  if (NX_DEBUG_ENABLE_TIME) \
202  nxTimer_##TAG.mark((MARK)); \
203 } while (0)
204 
208 #define NX_TIME_END(TAG) do \
209 { \
210  if (NX_DEBUG_ENABLE_TIME) \
211  nxTimer_##TAG.finish(); \
212 } while (0)
213 
214 //-------------------------------------------------------------------------------------------------
215 // Fps
216 
217 #if !defined(NX_DEBUG_ENABLE_FPS)
218 
219  #define NX_DEBUG_ENABLE_FPS NX_DEBUG_INI enableFps
220 #endif
221 
226 #define NX_FPS(TAG, /*OPTIONAL_MARK*/...) do \
227 { \
228  if (NX_KIT_DEBUG_DETAIL_CONCAT(NX_DEBUG_ENABLE_FPS, TAG)) \
229  { \
230  static ::nx::kit::debug::detail::Fps fps( \
231  NX_KIT_DEBUG_DETAIL_PRINT_FUNC, #TAG); \
232  fps.mark(__VA_ARGS__); \
233  } \
234 } while (0)
235 
236 //-------------------------------------------------------------------------------------------------
237 // Implementation
238 
239 namespace detail {
240 
241 typedef std::function<void(const char*)> PrintFunc;
242 
243 #define NX_KIT_DEBUG_DETAIL_PRINT_FUNC ([&](const char* message) { NX_PRINT << message; })
244 
249 #define NX_KIT_DEBUG_DETAIL_MSVC_EXPAND(ARG) ARG
250 
252 #define NX_KIT_DEBUG_DETAIL_GET_3RD_ARG(ARG1, ARG2, ARG3, ...) ARG3
253 
254 #define NX_KIT_DEBUG_DETAIL_ASSERT1(CONDITION) \
255  ::nx::kit::debug::detail::doAssert( \
256  !!(CONDITION), NX_KIT_DEBUG_DETAIL_PRINT_FUNC, #CONDITION, "", __FILE__, __LINE__)
257 
258 #define NX_KIT_DEBUG_DETAIL_ASSERT2(CONDITION, MESSAGE) \
259  ::nx::kit::debug::detail::doAssert( \
260  !!(CONDITION), NX_KIT_DEBUG_DETAIL_PRINT_FUNC, #CONDITION, MESSAGE, __FILE__, __LINE__)
261 
262 NX_KIT_API void assertionFailed(
263  PrintFunc printFunc, const char* conditionStr, const std::string& message,
264  const char* file, int line);
265 
266 inline bool doAssert(
267  bool condition, PrintFunc printFunc, const char* conditionStr, const std::string& message,
268  const char* file, int line)
269 {
270  if (!condition)
271  assertionFailed(printFunc, conditionStr, message, file, line);
272  return condition;
273 }
274 
275 #define NX_KIT_DEBUG_DETAIL_CONCAT(X, Y) NX_KIT_DEBUG_DETAIL_CONCAT2(X, Y)
276 #define NX_KIT_DEBUG_DETAIL_CONCAT2(X, Y) X##Y
277 
279 NX_KIT_API std::string printPrefix(const char* file);
280 
281 class NX_KIT_API Timer
282 {
283 public:
284  Timer(bool enabled, PrintFunc printFunc, const char* tag);
285  ~Timer();
286  void mark(const char* markStr);
287  void finish();
288 
289 private:
290  struct Impl;
291  Impl* const d;
292 };
293 
294 class NX_KIT_API Fps
295 {
296 public:
297  Fps(PrintFunc printFunc, const char* tag);
298  ~Fps();
299  void mark(const char* markStr = nullptr);
300 
301 private:
302  struct Impl;
303  Impl* const d;
304 };
305 
306 NX_KIT_API void printHexDump(
307  PrintFunc printFunc, const char* caption, const char* bytes, int size);
308 
309 NX_KIT_API void saveStr(
310  PrintFunc printFunc,
311  const char* originDir,
312  const char* filename,
313  const char* strCaption,
314  const std::string& str);
315 
316 } // namespace detail
317 
318 } // namespace debug
319 } // namespace kit
320 } // namespace nx
321 
322 #if defined(__linux__)
323  #include <pthread.h>
324  #define NX_KIT_DEBUG_DETAIL_THREAD_ID() \
325  ::nx::kit::utils::format(", thread %llx", (long long) pthread_self())
326 #elif defined(QT_CORE_LIB)
327  #include <QtCore/QThread>
328  #define NX_KIT_DEBUG_DETAIL_THREAD_ID() \
329  ::nx::kit::utils::format(", thread %llx", (long long) QThread::currentThreadId())
330 #else
331  // No threading libs available - do not print thread id.
332  #define NX_KIT_DEBUG_DETAIL_THREAD_ID() ""
333 #endif
Definition: debug.h:294
Definition: debug.cpp:314
Definition: debug.cpp:239
Definition: apple_utils.h:6
Definition: debug.h:281