nx_cloud_storage_sdk  1.0
Cloud Storage 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 /*empty*/
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 << std::endl
77 #endif
78 
83 NX_KIT_API std::ostream*& stream();
84 
85 #if !defined(NX_PRINT)
86 
90  #define NX_PRINT /* << args... */ \
91  /* Allocate a temp value, which prints endl in its destructor, in the "<<" expression. */ \
92  ( []() { struct Endl { ~Endl() { NX_DEBUG_STREAM NX_DEBUG_ENDL; } }; \
93  return std::make_shared<Endl>(); }() ) /*operator,*/, \
94  NX_DEBUG_STREAM << NX_PRINT_PREFIX
95 #endif
96 
100 #define NX_OUTPUT /* << args... */ \
101  for (/* Executed either once or never; `for` instead of `if` gives no warnings. */ \
102  int NX_KIT_DEBUG_DETAIL_CONCAT(nxOutput_, __line__) = 0; \
103  NX_KIT_DEBUG_DETAIL_CONCAT(nxOutput_, __line__) != 1 && (NX_DEBUG_ENABLE_OUTPUT); \
104  ++NX_KIT_DEBUG_DETAIL_CONCAT(nxOutput_, __line__) \
105  ) NX_PRINT
106 
107 //-------------------------------------------------------------------------------------------------
108 // Assertions
109 
125 #define NX_KIT_ASSERT(/* CONDITION, MESSAGE = "" */ ...) \
126  NX_KIT_DEBUG_DETAIL_MSVC_EXPAND(NX_KIT_DEBUG_DETAIL_GET_3RD_ARG( \
127  __VA_ARGS__, NX_KIT_DEBUG_DETAIL_ASSERT2, NX_KIT_DEBUG_DETAIL_ASSERT1, \
128  /* Helps to generate a reasonable compiler error. */ args_required)(__VA_ARGS__))
129 
134 NX_KIT_API void intentionallyCrash(const char* message);
135 
136 //-------------------------------------------------------------------------------------------------
137 // Print info
138 
142 #define LL \
143  NX_PRINT << "####### LL line " + ::nx::kit::utils::toString(__LINE__) \
144  + NX_KIT_DEBUG_DETAIL_THREAD_ID \
145  + ", " + ::nx::kit::debug::srcFileRelativePath(__FILE__) \
146  /* The final semicolon allows to use this macro as a line prefix. */;
147 
151 #define NX_PRINT_VALUE(VALUE) \
152  NX_PRINT << "####### " #VALUE ": " + ::nx::kit::utils::toString(VALUE)
153 
157 #define NX_PRINT_HEX_DUMP(CAPTION, BYTES, SIZE) \
158  ::nx::kit::debug::detail::printHexDump( \
159  NX_KIT_DEBUG_DETAIL_PRINT_FUNC, (CAPTION), (const char*) (BYTES), (int) (SIZE))
160 
164 NX_KIT_API std::string hexDumpLine(const char* bytes, int size, int bytesPerLine = 0);
165 
166 #if !defined(NX_DEBUG_SAVE_DIR)
167 
168  #define NX_DEBUG_SAVE_DIR ::nx::kit::IniConfig::iniFilesDir()
169 #endif
170 
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 
183 #define NX_SAVE_BIN(FILENAME, BYTES, SIZE) \
184  ::nx::kit::debug::detail::saveBin( \
185  NX_KIT_DEBUG_DETAIL_PRINT_FUNC, (NX_DEBUG_SAVE_DIR), (FILENAME), (BYTES), (SIZE))
186 
187 //-------------------------------------------------------------------------------------------------
188 // Time
189 
190 #if !defined(NX_DEBUG_ENABLE_TIME)
191 
192  #define NX_DEBUG_ENABLE_TIME NX_DEBUG_INI enableTime
193 #endif
194 
198 #define NX_TIME_BEGIN(TAG) \
199  ::nx::kit::debug::detail::Timer nxTimer_##TAG( \
200  (NX_DEBUG_ENABLE_TIME), NX_KIT_DEBUG_DETAIL_PRINT_FUNC, #TAG)
201 
206 #define NX_TIME_MARK(TAG, MARK) do \
207 { \
208  if (NX_DEBUG_ENABLE_TIME) \
209  nxTimer_##TAG.mark((MARK)); \
210 } while (0)
211 
215 #define NX_TIME_END(TAG) do \
216 { \
217  if (NX_DEBUG_ENABLE_TIME) \
218  nxTimer_##TAG.finish(); \
219 } while (0)
220 
221 //-------------------------------------------------------------------------------------------------
222 // Fps
223 
224 #if !defined(NX_DEBUG_ENABLE_FPS)
225 
226  #define NX_DEBUG_ENABLE_FPS NX_DEBUG_INI enableFps
227 #endif
228 
233 #define NX_FPS(TAG, /*OPTIONAL_MARK*/...) do \
234 { \
235  if (NX_KIT_DEBUG_DETAIL_CONCAT(NX_DEBUG_ENABLE_FPS, TAG)) \
236  { \
237  static ::nx::kit::debug::detail::Fps fps( \
238  NX_KIT_DEBUG_DETAIL_PRINT_FUNC, #TAG); \
239  fps.mark(__VA_ARGS__); \
240  } \
241 } while (0)
242 
243 //-------------------------------------------------------------------------------------------------
244 // Implementation
245 
246 namespace detail {
247 
248 typedef std::function<void(const char*)> PrintFunc;
249 
250 #define NX_KIT_DEBUG_DETAIL_PRINT_FUNC ([&](const char* message) { NX_PRINT << message; })
251 
256 #define NX_KIT_DEBUG_DETAIL_MSVC_EXPAND(ARG) ARG
257 
259 #define NX_KIT_DEBUG_DETAIL_GET_3RD_ARG(ARG1, ARG2, ARG3, ...) ARG3
260 
261 #define NX_KIT_DEBUG_DETAIL_ASSERT1(CONDITION) \
262  ::nx::kit::debug::detail::doAssert( \
263  !!(CONDITION), NX_KIT_DEBUG_DETAIL_PRINT_FUNC, #CONDITION, "", __FILE__, __LINE__)
264 
265 #define NX_KIT_DEBUG_DETAIL_ASSERT2(CONDITION, MESSAGE) \
266  ::nx::kit::debug::detail::doAssert( \
267  !!(CONDITION), NX_KIT_DEBUG_DETAIL_PRINT_FUNC, #CONDITION, MESSAGE, __FILE__, __LINE__)
268 
269 NX_KIT_API void assertionFailed(
270  PrintFunc printFunc, const char* conditionStr, const std::string& message,
271  const char* file, int line);
272 
273 inline bool doAssert(
274  bool condition, PrintFunc printFunc, const char* conditionStr, const std::string& message,
275  const char* file, int line)
276 {
277  if (!condition)
278  assertionFailed(printFunc, conditionStr, message, file, line);
279  return condition;
280 }
281 
282 #define NX_KIT_DEBUG_DETAIL_CONCAT(X, Y) NX_KIT_DEBUG_DETAIL_CONCAT2(X, Y)
283 #define NX_KIT_DEBUG_DETAIL_CONCAT2(X, Y) X##Y
284 
286 NX_KIT_API std::string printPrefix(const char* file);
287 
288 class NX_KIT_API Timer
289 {
290 public:
291  Timer(bool enabled, PrintFunc printFunc, const char* tag);
292  ~Timer();
293  void mark(const char* markStr);
294  void finish();
295 
296 private:
297  struct Impl;
298  Impl* const d;
299 };
300 
301 class NX_KIT_API Fps
302 {
303 public:
304  Fps(PrintFunc printFunc, const char* tag);
305  ~Fps();
306  void mark(const char* markStr = nullptr);
307 
308 private:
309  struct Impl;
310  Impl* const d;
311 };
312 
313 NX_KIT_API void printHexDump(
314  PrintFunc printFunc, const char* caption, const char* bytes, int size);
315 
316 NX_KIT_API void saveStr(
317  PrintFunc printFunc,
318  const char* originDir,
319  const char* filename,
320  const char* strCaption,
321  const std::string& str);
322 
323 NX_KIT_API void saveBin(
324  PrintFunc printFunc,
325  const char* originDir,
326  const char* filename,
327  const char* bytes,
328  int size);
329 
330 } // namespace detail
331 
332 } // namespace debug
333 } // namespace kit
334 } // namespace nx
335 
336 // Define NX_KIT_DEBUG_DETAIL_THREAD_ID.
337 #if defined(__linux__)
338  #if defined(__has_include) //< This C++17 feature was available in GCC/Clang long before.
339  #if __has_include(<pthread.h>)
340  #include <pthread.h>
341  #define NX_KIT_DEBUG_DETAIL_THREAD_ID \
342  ::nx::kit::utils::format(", thread %llx", (long long) pthread_self())
343  #endif
344  #endif
345 #elif defined(QT_CORE_LIB)
346  #include <QtCore/QThread>
347  #define NX_KIT_DEBUG_DETAIL_THREAD_ID \
348  ::nx::kit::utils::format(", thread %llx", (long long) QThread::currentThreadId())
349 #endif
350 #if !defined(NX_KIT_DEBUG_DETAIL_THREAD_ID)
351  // No threading libs available - do not print thread id.
352  #define NX_KIT_DEBUG_DETAIL_THREAD_ID ""
353 #endif
Definition: debug.h:301
Definition: debug.cpp:309
Definition: debug.cpp:234
Definition: apple_utils.h:6
Definition: debug.h:288