1 /* 2 Loguru logging library for C++, by Emil Ernerfeldt. 3 www.github.com/emilk/loguru 4 If you find Loguru useful, please let me know on twitter or in a mail! 5 Twitter: @ernerfeldt 6 Mail: emil.ernerfeldt@gmail.com 7 Website: www.ilikebigbits.com 8 9 # License 10 This software is in the public domain. Where that dedication is not 11 recognized, you are granted a perpetual, irrevocable license to 12 copy, modify and distribute it as you see fit. 13 14 # Inspiration 15 Much of Loguru was inspired by GLOG, https://code.google.com/p/google-glog/. 16 The choice of public domain is fully due Sean T. Barrett 17 and his wonderful stb libraries at https://github.com/nothings/stb. 18 19 # Version history 20 * Version 0.1.0 - 2015-03-22 - Works great on Mac. 21 * Version 0.2.0 - 2015-09-17 - Removed the only dependency. 22 * Version 0.3.0 - 2015-10-02 - Drop-in replacement for most of GLOG 23 * Version 0.4.0 - 2015-10-07 - Single-file! 24 * Version 0.5.0 - 2015-10-17 - Improved file logging 25 * Version 0.6.0 - 2015-10-24 - Add stack traces 26 * Version 0.7.0 - 2015-10-27 - Signals 27 * Version 0.8.0 - 2015-10-30 - Color logging. 28 * Version 0.9.0 - 2015-11-26 - ABORT_S and proper handling of FATAL 29 * Version 1.0.0 - 2016-02-14 - ERROR_CONTEXT 30 * Version 1.1.0 - 2016-02-19 - -v OFF, -v INFO etc 31 * Version 1.1.1 - 2016-02-20 - textprintf vs strprintf 32 * Version 1.1.2 - 2016-02-22 - Remove g_alsologtostderr 33 * Version 1.1.3 - 2016-02-29 - ERROR_CONTEXT as linked list 34 * Version 1.2.0 - 2016-03-19 - Add get_thread_name() 35 * Version 1.2.1 - 2016-03-20 - Minor fixes 36 * Version 1.2.2 - 2016-03-29 - Fix issues with set_fatal_handler throwing an exception 37 * Version 1.2.3 - 2016-05-16 - Log current working directory in loguru::init(). 38 * Version 1.2.4 - 2016-05-18 - Custom replacement for -v in loguru::init() by bjoernpollex 39 * Version 1.2.5 - 2016-05-18 - Add ability to print ERROR_CONTEXT of parent thread. 40 * Version 1.2.6 - 2016-05-19 - Bug fix regarding VLOG verbosity argument lacking (). 41 * Version 1.2.7 - 2016-05-23 - Fix PATH_MAX problem. 42 * Version 1.2.8 - 2016-05-26 - Add shutdown() and remove_all_callbacks() 43 * Version 1.2.9 - 2016-06-09 - Use a monotonic clock for uptime. 44 * Version 1.3.0 - 2016-07-20 - Fix issues with callback flush/close not being called. 45 * Version 1.3.1 - 2016-07-20 - Add LOGURU_UNSAFE_SIGNAL_HANDLER to toggle stacktrace on signals. 46 * Version 1.3.2 - 2016-07-20 - Add loguru::arguments() 47 * Version 1.4.0 - 2016-09-15 - Semantic versioning + add loguru::create_directories 48 * Version 1.4.1 - 2016-09-29 - Customize formating with LOGURU_FILENAME_WIDTH 49 * Version 1.5.0 - 2016-12-22 - LOGURU_USE_FMTLIB by kolis and LOGURU_WITH_FILEABS by scinart 50 * Version 1.5.1 - 2017-08-08 - Terminal colors on Windows 10 thanks to looki 51 * Version 1.6.0 - 2018-01-03 - Add LOGURU_RTTI and LOGURU_STACKTRACES settings 52 * Version 1.7.0 - 2018-01-03 - Add ability to turn off the preamble with loguru::g_preamble 53 * Version 1.7.1 - 2018-04-05 - Add function get_fatal_handler 54 * Version 1.7.2 - 2018-04-22 - Fix a bug where large file names could cause stack corruption (thanks @ccamporesi) 55 * Version 1.8.0 - 2018-04-23 - Shorten long file names to keep preamble fixed width 56 * Version 1.9.0 - 2018-09-22 - Adjust terminal colors, add LOGURU_VERBOSE_SCOPE_ENDINGS, add LOGURU_SCOPE_TIME_PRECISION, add named log levels 57 * Version 2.0.0 - 2018-09-22 - Split loguru.hpp into loguru.hpp and loguru.cpp 58 * Version 2.1.0 - 2019-09-23 - Update fmtlib + add option to loguru::init to NOT set main thread name. 59 60 # Compiling 61 Just include <loguru.hpp> where you want to use Loguru. 62 Then, in one .cpp file #include <loguru.cpp> 63 Make sure you compile with -std=c++11 -lstdc++ -lpthread -ldl 64 65 # Usage 66 For details, please see the official documentation at emilk.github.io/loguru 67 68 #include <loguru.hpp> 69 70 int main(int argc, char* argv[]) { 71 loguru::init(argc, argv); 72 73 // Put every log message in "everything.log": 74 loguru::add_file("everything.log", loguru::Append, loguru::Verbosity_MAX); 75 76 LOG_F(INFO, "The magic number is %d", 42); 77 } 78 79 */ 80 81 // XXX(kitware): // include exports header 82 #include "vtkloguru_export.h" 83 // XXX(kitware): // mangle 84 #define loguru vtkloguru 85 // XXX(kitware): // vtk config defaults 86 #define LOGURU_WITH_STREAMS 1 87 88 #if defined(LOGURU_IMPLEMENTATION) 89 #error "You are defining LOGURU_IMPLEMENTATION. This is for older versions of Loguru. You should now instead include loguru.cpp (or build it and link with it)" 90 #endif 91 92 // Disable all warnings from gcc/clang: 93 #if defined(__clang__) 94 #pragma clang system_header 95 #elif defined(__GNUC__) 96 #pragma GCC system_header 97 #endif 98 99 #ifndef LOGURU_HAS_DECLARED_FORMAT_HEADER 100 #define LOGURU_HAS_DECLARED_FORMAT_HEADER 101 102 // Semantic versioning. Loguru version can be printed with printf("%d.%d.%d", LOGURU_VERSION_MAJOR, LOGURU_VERSION_MINOR, LOGURU_VERSION_PATCH); 103 #define LOGURU_VERSION_MAJOR 2 104 #define LOGURU_VERSION_MINOR 1 105 #define LOGURU_VERSION_PATCH 0 106 107 #if defined(_MSC_VER) 108 #include <sal.h> // Needed for _In_z_ etc annotations 109 #endif 110 111 // ---------------------------------------------------------------------------- 112 113 #ifndef LOGURU_EXPORT 114 // Define to your project's export declaration if needed for use in a shared library. 115 #define LOGURU_EXPORT 116 #endif 117 118 #ifndef LOGURU_SCOPE_TEXT_SIZE 119 // Maximum length of text that can be printed by a LOG_SCOPE. 120 // This should be long enough to get most things, but short enough not to clutter the stack. 121 #define LOGURU_SCOPE_TEXT_SIZE 196 122 #endif 123 124 #ifndef LOGURU_FILENAME_WIDTH 125 // Width of the column containing the file name 126 #define LOGURU_FILENAME_WIDTH 23 127 #endif 128 129 #ifndef LOGURU_THREADNAME_WIDTH 130 // Width of the column containing the thread name 131 #define LOGURU_THREADNAME_WIDTH 16 132 #endif 133 134 #ifndef LOGURU_SCOPE_TIME_PRECISION 135 // Resolution of scope timers. 3=ms, 6=us, 9=ns 136 #define LOGURU_SCOPE_TIME_PRECISION 3 137 #endif 138 139 #ifndef LOGURU_CATCH_SIGABRT 140 // Should Loguru catch SIGABRT to print stack trace etc? 141 #define LOGURU_CATCH_SIGABRT 1 142 #endif 143 144 #ifndef LOGURU_VERBOSE_SCOPE_ENDINGS 145 // Show milliseconds and scope name at end of scope. 146 #define LOGURU_VERBOSE_SCOPE_ENDINGS 1 147 #endif 148 149 #ifndef LOGURU_REDEFINE_ASSERT 150 #define LOGURU_REDEFINE_ASSERT 0 151 #endif 152 153 #ifndef LOGURU_WITH_STREAMS 154 #define LOGURU_WITH_STREAMS 0 155 #endif 156 157 #ifndef LOGURU_REPLACE_GLOG 158 #define LOGURU_REPLACE_GLOG 0 159 #endif 160 161 #if LOGURU_REPLACE_GLOG 162 #undef LOGURU_WITH_STREAMS 163 #define LOGURU_WITH_STREAMS 1 164 #endif 165 166 #if defined(LOGURU_UNSAFE_SIGNAL_HANDLER) 167 #error "You are defining LOGURU_UNSAFE_SIGNAL_HANDLER. This is for older versions of Loguru. You should now instead set the unsafe_signal_handler option when you call loguru::init." 168 #endif 169 170 #if LOGURU_IMPLEMENTATION 171 #undef LOGURU_WITH_STREAMS 172 #define LOGURU_WITH_STREAMS 1 173 #endif 174 175 #ifndef LOGURU_USE_FMTLIB 176 #define LOGURU_USE_FMTLIB 0 177 #endif 178 179 #ifndef LOGURU_WITH_FILEABS 180 #define LOGURU_WITH_FILEABS 0 181 #endif 182 183 #ifndef LOGURU_RTTI 184 #if defined(__clang__) 185 #if __has_feature(cxx_rtti) 186 #define LOGURU_RTTI 1 187 #endif 188 #elif defined(__GNUG__) 189 #if defined(__GXX_RTTI) 190 #define LOGURU_RTTI 1 191 #endif 192 #elif defined(_MSC_VER) 193 #if defined(_CPPRTTI) 194 #define LOGURU_RTTI 1 195 #endif 196 #endif 197 #endif 198 199 // -------------------------------------------------------------------- 200 // Utility macros 201 202 #define LOGURU_CONCATENATE_IMPL(s1, s2) s1 ## s2 203 #define LOGURU_CONCATENATE(s1, s2) LOGURU_CONCATENATE_IMPL(s1, s2) 204 205 #ifdef __COUNTER__ 206 # define LOGURU_ANONYMOUS_VARIABLE(str) LOGURU_CONCATENATE(str, __COUNTER__) 207 #else 208 # define LOGURU_ANONYMOUS_VARIABLE(str) LOGURU_CONCATENATE(str, __LINE__) 209 #endif 210 211 #if defined(__clang__) || defined(__GNUC__) 212 // Helper macro for declaring functions as having similar signature to printf. 213 // This allows the compiler to catch format errors at compile-time. 214 #define LOGURU_PRINTF_LIKE(fmtarg, firstvararg) __attribute__((__format__ (__printf__, fmtarg, firstvararg))) 215 #define LOGURU_FORMAT_STRING_TYPE const char* 216 #elif defined(_MSC_VER) 217 #define LOGURU_PRINTF_LIKE(fmtarg, firstvararg) 218 #define LOGURU_FORMAT_STRING_TYPE _In_z_ _Printf_format_string_ const char* 219 #else 220 #define LOGURU_PRINTF_LIKE(fmtarg, firstvararg) 221 #define LOGURU_FORMAT_STRING_TYPE const char* 222 #endif 223 224 // Used to mark log_and_abort for the benefit of the static analyzer and optimizer. 225 #if defined(_MSC_VER) 226 #define LOGURU_NORETURN __declspec(noreturn) 227 #else 228 #define LOGURU_NORETURN __attribute__((noreturn)) 229 #endif 230 231 #if defined(_MSC_VER) 232 #define LOGURU_PREDICT_FALSE(x) (x) 233 #define LOGURU_PREDICT_TRUE(x) (x) 234 #else 235 #define LOGURU_PREDICT_FALSE(x) (__builtin_expect(x, 0)) 236 #define LOGURU_PREDICT_TRUE(x) (__builtin_expect(!!(x), 1)) 237 #endif 238 239 #if LOGURU_USE_FMTLIB 240 #include <fmt/format.h> 241 #define LOGURU_FMT(x) "{:" #x "}" 242 #else 243 #define LOGURU_FMT(x) "%" #x 244 #endif 245 246 #ifdef _WIN32 247 #define STRDUP(str) _strdup(str) 248 #else 249 #define STRDUP(str) strdup(str) 250 #endif 251 252 // -------------------------------------------------------------------- 253 254 namespace loguru 255 { 256 // Simple RAII ownership of a char*. 257 class LOGURU_EXPORT Text 258 { 259 public: Text(char * owned_str)260 explicit Text(char* owned_str) : _str(owned_str) {} 261 ~Text(); Text(Text && t)262 Text(Text&& t) 263 { 264 _str = t._str; 265 t._str = nullptr; 266 } 267 Text(Text& t) = delete; 268 Text& operator=(Text& t) = delete; 269 void operator=(Text&& t) = delete; 270 c_str() const271 const char* c_str() const { return _str; } empty() const272 bool empty() const { return _str == nullptr || *_str == '\0'; } 273 release()274 char* release() 275 { 276 auto result = _str; 277 _str = nullptr; 278 return result; 279 } 280 281 private: 282 char* _str; 283 }; 284 285 // Like printf, but returns the formated text. 286 #if LOGURU_USE_FMTLIB 287 LOGURU_EXPORT 288 Text vtextprintf(const char* format, fmt::format_args args); 289 290 template<typename... Args> 291 LOGURU_EXPORT textprintf(LOGURU_FORMAT_STRING_TYPE format,const Args &...args)292 Text textprintf(LOGURU_FORMAT_STRING_TYPE format, const Args&... args) { 293 return vtextprintf(format, fmt::make_format_args(args...)); 294 } 295 #else 296 LOGURU_EXPORT 297 Text textprintf(LOGURU_FORMAT_STRING_TYPE format, ...) LOGURU_PRINTF_LIKE(1, 2); 298 #endif 299 300 // Overloaded for variadic template matching. 301 LOGURU_EXPORT 302 Text textprintf(); 303 304 using Verbosity = int; 305 306 #undef FATAL 307 #undef ERROR 308 #undef WARNING 309 #undef INFO 310 #undef MAX 311 312 enum NamedVerbosity : Verbosity 313 { 314 // Used to mark an invalid verbosity. Do not log to this level. 315 Verbosity_INVALID = -10, // Never do LOG_F(INVALID) 316 317 // You may use Verbosity_OFF on g_stderr_verbosity, but for nothing else! 318 Verbosity_OFF = -9, // Never do LOG_F(OFF) 319 320 // Prefer to use ABORT_F or ABORT_S over LOG_F(FATAL) or LOG_S(FATAL). 321 Verbosity_FATAL = -3, 322 Verbosity_ERROR = -2, 323 Verbosity_WARNING = -1, 324 325 // Normal messages. By default written to stderr. 326 Verbosity_INFO = 0, 327 328 // Same as Verbosity_INFO in every way. 329 Verbosity_0 = 0, 330 331 // Verbosity levels 1-9 are generally not written to stderr, but are written to file. 332 Verbosity_1 = +1, 333 Verbosity_2 = +2, 334 Verbosity_3 = +3, 335 Verbosity_4 = +4, 336 Verbosity_5 = +5, 337 Verbosity_6 = +6, 338 Verbosity_7 = +7, 339 Verbosity_8 = +8, 340 Verbosity_9 = +9, 341 342 // Don not use higher verbosity levels, as that will make grepping log files harder. 343 Verbosity_MAX = +9, 344 }; 345 346 struct Message 347 { 348 // You would generally print a Message by just concating the buffers without spacing. 349 // Optionally, ignore preamble and indentation. 350 Verbosity verbosity; // Already part of preamble 351 const char* filename; // Already part of preamble 352 unsigned line; // Already part of preamble 353 const char* preamble; // Date, time, uptime, thread, file:line, verbosity. 354 const char* indentation; // Just a bunch of spacing. 355 const char* prefix; // Assertion failure info goes here (or ""). 356 const char* message; // User message goes here. 357 }; 358 359 /* Everything with a verbosity equal or greater than g_stderr_verbosity will be 360 written to stderr. You can set this in code or via the -v argument. 361 Set to loguru::Verbosity_OFF to write nothing to stderr. 362 Default is 0, i.e. only log ERROR, WARNING and INFO are written to stderr. 363 */ 364 LOGURU_EXPORT extern Verbosity g_stderr_verbosity; 365 LOGURU_EXPORT extern bool g_colorlogtostderr; // True by default. 366 LOGURU_EXPORT extern unsigned g_flush_interval_ms; // 0 (unbuffered) by default. 367 LOGURU_EXPORT extern bool g_preamble; // Prefix each log line with date, time etc? True by default. 368 369 /* Specify the verbosity used by loguru to log its info messages including the header 370 logged when logged::init() is called or on exit. Default is 0 (INFO). 371 */ 372 LOGURU_EXPORT extern Verbosity g_internal_verbosity; 373 374 // Turn off individual parts of the preamble 375 LOGURU_EXPORT extern bool g_preamble_date; // The date field 376 LOGURU_EXPORT extern bool g_preamble_time; // The time of the current day 377 LOGURU_EXPORT extern bool g_preamble_uptime; // The time since init call 378 LOGURU_EXPORT extern bool g_preamble_thread; // The logging thread 379 LOGURU_EXPORT extern bool g_preamble_file; // The file from which the log originates from 380 LOGURU_EXPORT extern bool g_preamble_verbose; // The verbosity field 381 LOGURU_EXPORT extern bool g_preamble_pipe; // The pipe symbol right before the message 382 383 // May not throw! 384 typedef void (*log_handler_t)(void* user_data, const Message& message); 385 typedef void (*close_handler_t)(void* user_data); 386 typedef void (*flush_handler_t)(void* user_data); 387 388 // May throw if that's how you'd like to handle your errors. 389 typedef void (*fatal_handler_t)(const Message& message); 390 391 // Given a verbosity level, return the level's name or nullptr. 392 typedef const char* (*verbosity_to_name_t)(Verbosity verbosity); 393 394 // Given a verbosity level name, return the verbosity level or 395 // Verbosity_INVALID if name is not recognized. 396 typedef Verbosity (*name_to_verbosity_t)(const char* name); 397 398 // Runtime options passed to loguru::init 399 struct Options 400 { 401 // This allows you to use something else instead of "-v" via verbosity_flag. 402 // Set to nullptr to if you don't want Loguru to parse verbosity from the args.' 403 const char* verbosity_flag = "-v"; 404 405 // loguru::init will set the name of the calling thread to this. 406 // If you don't want Loguru to set the name of the main thread, 407 // set this to nullptr. 408 // NOTE: on SOME platforms loguru::init will only overwrite the thread name 409 // if a thread name has not already been set. 410 // To always set a thread name, use loguru::set_thread_name instead. 411 const char* main_thread_name = "main thread"; 412 413 // Make Loguru try to do unsafe but useful things, 414 // like printing a stack trace, when catching signals. 415 // This may lead to bad things like deadlocks in certain situations. 416 bool unsafe_signal_handler = true; 417 }; 418 419 /* Should be called from the main thread. 420 You don't *need* to call this, but if you do you get: 421 * Signal handlers installed 422 * Program arguments logged 423 * Working dir logged 424 * Optional -v verbosity flag parsed 425 * Main thread name set to "main thread" 426 * Explanation of the preamble (date, threanmae etc) logged 427 428 loguru::init() will look for arguments meant for loguru and remove them. 429 Arguments meant for loguru are: 430 -v n Set loguru::g_stderr_verbosity level. Examples: 431 -v 3 Show verbosity level 3 and lower. 432 -v 0 Only show INFO, WARNING, ERROR, FATAL (default). 433 -v INFO Only show INFO, WARNING, ERROR, FATAL (default). 434 -v WARNING Only show WARNING, ERROR, FATAL. 435 -v ERROR Only show ERROR, FATAL. 436 -v FATAL Only show FATAL. 437 -v OFF Turn off logging to stderr. 438 439 Tip: You can set g_stderr_verbosity before calling loguru::init. 440 That way you can set the default but have the user override it with the -v flag. 441 Note that -v does not affect file logging (see loguru::add_file). 442 443 You can you something other than the -v flag by setting the verbosity_flag option. 444 */ 445 LOGURU_EXPORT 446 void init(int& argc, char* argv[], const Options& options = {}); 447 448 // Will call remove_all_callbacks(). After calling this, logging will still go to stderr. 449 // You generally don't need to call this. 450 LOGURU_EXPORT 451 void shutdown(); 452 453 // What ~ will be replaced with, e.g. "/home/your_user_name/" 454 LOGURU_EXPORT 455 const char* home_dir(); 456 457 /* Returns the name of the app as given in argv[0] but without leading path. 458 That is, if argv[0] is "../foo/app" this will return "app". 459 */ 460 LOGURU_EXPORT 461 const char* argv0_filename(); 462 463 // Returns all arguments given to loguru::init(), but escaped with a single space as separator. 464 LOGURU_EXPORT 465 const char* arguments(); 466 467 // Returns the path to the current working dir when loguru::init() was called. 468 LOGURU_EXPORT 469 const char* current_dir(); 470 471 // Returns the part of the path after the last / or \ (if any). 472 LOGURU_EXPORT 473 const char* filename(const char* path); 474 475 // e.g. "foo/bar/baz.ext" will create the directories "foo/" and "foo/bar/" 476 LOGURU_EXPORT 477 bool create_directories(const char* file_path_const); 478 479 // Writes date and time with millisecond precision, e.g. "20151017_161503.123" 480 LOGURU_EXPORT 481 void write_date_time(char* buff, unsigned buff_size); 482 483 // Helper: thread-safe version strerror 484 LOGURU_EXPORT 485 Text errno_as_text(); 486 487 /* Given a prefix of e.g. "~/loguru/" this might return 488 "/home/your_username/loguru/app_name/20151017_161503.123.log" 489 490 where "app_name" is a sanitized version of argv[0]. 491 */ 492 LOGURU_EXPORT 493 void suggest_log_path(const char* prefix, char* buff, unsigned buff_size); 494 495 enum FileMode { Truncate, Append }; 496 497 /* Will log to a file at the given path. 498 Any logging message with a verbosity lower or equal to 499 the given verbosity will be included. 500 The function will create all directories in 'path' if needed. 501 If path starts with a ~, it will be replaced with loguru::home_dir() 502 To stop the file logging, just call loguru::remove_callback(path) with the same path. 503 */ 504 LOGURU_EXPORT 505 bool add_file(const char* path, FileMode mode, Verbosity verbosity); 506 507 /* Will be called right before abort(). 508 You can for instance use this to print custom error messages, or throw an exception. 509 Feel free to call LOG:ing function from this, but not FATAL ones! */ 510 LOGURU_EXPORT 511 void set_fatal_handler(fatal_handler_t handler); 512 513 // Get the current fatal handler, if any. Default value is nullptr. 514 LOGURU_EXPORT 515 fatal_handler_t get_fatal_handler(); 516 517 /* Will be called on each log messages with a verbosity less or equal to the given one. 518 Useful for displaying messages on-screen in a game, for example. 519 The given on_close is also expected to flush (if desired). 520 */ 521 LOGURU_EXPORT 522 void add_callback( 523 const char* id, 524 log_handler_t callback, 525 void* user_data, 526 Verbosity verbosity, 527 close_handler_t on_close = nullptr, 528 flush_handler_t on_flush = nullptr); 529 530 /* Set a callback that returns custom verbosity level names. If callback 531 is nullptr or returns nullptr, default log names will be used. 532 */ 533 LOGURU_EXPORT 534 void set_verbosity_to_name_callback(verbosity_to_name_t callback); 535 536 /* Set a callback that returns the verbosity level matching a name. The 537 callback should return Verbosity_INVALID if the name is not 538 recognized. 539 */ 540 LOGURU_EXPORT 541 void set_name_to_verbosity_callback(name_to_verbosity_t callback); 542 543 /* Get a custom name for a specific verbosity, if one exists, or nullptr. */ 544 LOGURU_EXPORT 545 const char* get_verbosity_name(Verbosity verbosity); 546 547 /* Get the verbosity enum value from a custom 4-character level name, if one exists. 548 If the name does not match a custom level name, Verbosity_INVALID is returned. 549 */ 550 LOGURU_EXPORT 551 Verbosity get_verbosity_from_name(const char* name); 552 553 // Returns true iff the callback was found (and removed). 554 LOGURU_EXPORT 555 bool remove_callback(const char* id); 556 557 // Shut down all file logging and any other callback hooks installed. 558 LOGURU_EXPORT 559 void remove_all_callbacks(); 560 561 // Returns the maximum of g_stderr_verbosity and all file/custom outputs. 562 LOGURU_EXPORT 563 Verbosity current_verbosity_cutoff(); 564 565 #if LOGURU_USE_FMTLIB 566 // Internal functions 567 void vlog(Verbosity verbosity, const char* file, unsigned line, LOGURU_FORMAT_STRING_TYPE format, fmt::format_args args); 568 void raw_vlog(Verbosity verbosity, const char* file, unsigned line, LOGURU_FORMAT_STRING_TYPE format, fmt::format_args args); 569 570 // Actual logging function. Use the LOG macro instead of calling this directly. 571 template <typename... Args> 572 LOGURU_EXPORT log(Verbosity verbosity,const char * file,unsigned line,LOGURU_FORMAT_STRING_TYPE format,const Args &...args)573 void log(Verbosity verbosity, const char* file, unsigned line, LOGURU_FORMAT_STRING_TYPE format, const Args &... args) { 574 vlog(verbosity, file, line, format, fmt::make_format_args(args...)); 575 } 576 577 // Log without any preamble or indentation. 578 template <typename... Args> 579 LOGURU_EXPORT raw_log(Verbosity verbosity,const char * file,unsigned line,LOGURU_FORMAT_STRING_TYPE format,const Args &...args)580 void raw_log(Verbosity verbosity, const char* file, unsigned line, LOGURU_FORMAT_STRING_TYPE format, const Args &... args) { 581 raw_vlog(verbosity, file, line, format, fmt::make_format_args(args...)); 582 } 583 #else // LOGURU_USE_FMTLIB? 584 // Actual logging function. Use the LOG macro instead of calling this directly. 585 LOGURU_EXPORT 586 void log(Verbosity verbosity, const char* file, unsigned line, LOGURU_FORMAT_STRING_TYPE format, ...) LOGURU_PRINTF_LIKE(4, 5); 587 588 // Log without any preamble or indentation. 589 LOGURU_EXPORT 590 void raw_log(Verbosity verbosity, const char* file, unsigned line, LOGURU_FORMAT_STRING_TYPE format, ...) LOGURU_PRINTF_LIKE(4, 5); 591 #endif // !LOGURU_USE_FMTLIB 592 593 // Helper class for LOG_SCOPE_F 594 class LOGURU_EXPORT LogScopeRAII 595 { 596 public: LogScopeRAII()597 LogScopeRAII() : _file(nullptr) {} // No logging 598 LogScopeRAII(Verbosity verbosity, const char* file, unsigned line, LOGURU_FORMAT_STRING_TYPE format, ...) LOGURU_PRINTF_LIKE(5, 6); 599 ~LogScopeRAII(); 600 601 #if defined(_MSC_VER) && _MSC_VER > 1800 602 // older MSVC default move ctors close the scope on move. See 603 // issue #43 LogScopeRAII(LogScopeRAII && other)604 LogScopeRAII(LogScopeRAII&& other) 605 : _verbosity(other._verbosity) 606 , _file(other._file) 607 , _line(other._line) 608 , _indent_stderr(other._indent_stderr) 609 , _start_time_ns(other._start_time_ns) 610 { 611 // Make sure the tmp object's destruction doesn't close the scope: 612 other._file = nullptr; 613 614 for (unsigned int i = 0; i < LOGURU_SCOPE_TEXT_SIZE; ++i) { 615 _name[i] = other._name[i]; 616 } 617 } 618 #else 619 LogScopeRAII(LogScopeRAII&&) = default; 620 #endif 621 622 private: 623 LogScopeRAII(const LogScopeRAII&) = delete; 624 LogScopeRAII& operator=(const LogScopeRAII&) = delete; 625 void operator=(LogScopeRAII&&) = delete; 626 627 Verbosity _verbosity; 628 const char* _file; // Set to null if we are disabled due to verbosity 629 unsigned _line; 630 bool _indent_stderr; // Did we? 631 long long _start_time_ns; 632 char _name[LOGURU_SCOPE_TEXT_SIZE]; 633 }; 634 635 // Marked as 'noreturn' for the benefit of the static analyzer and optimizer. 636 // stack_trace_skip is the number of extrace stack frames to skip above log_and_abort. 637 #if LOGURU_USE_FMTLIB 638 LOGURU_EXPORT 639 LOGURU_NORETURN void vlog_and_abort(int stack_trace_skip, const char* expr, const char* file, unsigned line, LOGURU_FORMAT_STRING_TYPE format, fmt::format_args); 640 template <typename... Args> 641 LOGURU_EXPORT log_and_abort(int stack_trace_skip,const char * expr,const char * file,unsigned line,LOGURU_FORMAT_STRING_TYPE format,const Args &...args)642 LOGURU_NORETURN void log_and_abort(int stack_trace_skip, const char* expr, const char* file, unsigned line, LOGURU_FORMAT_STRING_TYPE format, const Args&... args) { 643 vlog_and_abort(stack_trace_skip, expr, file, line, format, fmt::make_format_args(args...)); 644 } 645 #else 646 LOGURU_EXPORT 647 LOGURU_NORETURN void log_and_abort(int stack_trace_skip, const char* expr, const char* file, unsigned line, LOGURU_FORMAT_STRING_TYPE format, ...) LOGURU_PRINTF_LIKE(5, 6); 648 #endif 649 LOGURU_EXPORT 650 LOGURU_NORETURN void log_and_abort(int stack_trace_skip, const char* expr, const char* file, unsigned line); 651 652 // Flush output to stderr and files. 653 // If g_flush_interval_ms is set to non-zero, this will be called automatically this often. 654 // If not set, you do not need to call this at all. 655 LOGURU_EXPORT 656 void flush(); 657 format_value(const T &)658 template<class T> inline Text format_value(const T&) { return textprintf("N/A"); } format_value(const char & v)659 template<> inline Text format_value(const char& v) { return textprintf(LOGURU_FMT(c), v); } format_value(const int & v)660 template<> inline Text format_value(const int& v) { return textprintf(LOGURU_FMT(d), v); } format_value(const unsigned int & v)661 template<> inline Text format_value(const unsigned int& v) { return textprintf(LOGURU_FMT(u), v); } format_value(const long & v)662 template<> inline Text format_value(const long& v) { return textprintf(LOGURU_FMT(lu), v); } format_value(const unsigned long & v)663 template<> inline Text format_value(const unsigned long& v) { return textprintf(LOGURU_FMT(ld), v); } format_value(const long long & v)664 template<> inline Text format_value(const long long& v) { return textprintf(LOGURU_FMT(llu), v); } format_value(const unsigned long long & v)665 template<> inline Text format_value(const unsigned long long& v) { return textprintf(LOGURU_FMT(lld), v); } format_value(const float & v)666 template<> inline Text format_value(const float& v) { return textprintf(LOGURU_FMT(f), v); } format_value(const double & v)667 template<> inline Text format_value(const double& v) { return textprintf(LOGURU_FMT(f), v); } 668 669 /* Thread names can be set for the benefit of readable logs. 670 If you do not set the thread name, a hex id will be shown instead. 671 These thread names may or may not be the same as the system thread names, 672 depending on the system. 673 Try to limit the thread name to 15 characters or less. */ 674 LOGURU_EXPORT 675 void set_thread_name(const char* name); 676 677 /* Returns the thread name for this thread. 678 On OSX this will return the system thread name (settable from both within and without Loguru). 679 On other systems it will return whatever you set in set_thread_name(); 680 If no thread name is set, this will return a hexadecimal thread id. 681 length should be the number of bytes available in the buffer. 682 17 is a good number for length. 683 right_align_hext_id means any hexadecimal thread id will be written to the end of buffer. 684 */ 685 LOGURU_EXPORT 686 void get_thread_name(char* buffer, unsigned long long length, bool right_align_hext_id); 687 688 /* Generates a readable stacktrace as a string. 689 'skip' specifies how many stack frames to skip. 690 For instance, the default skip (1) means: 691 don't include the call to loguru::stacktrace in the stack trace. */ 692 LOGURU_EXPORT 693 Text stacktrace(int skip = 1); 694 695 /* Add a string to be replaced with something else in the stack output. 696 697 For instance, instead of having a stack trace look like this: 698 0x41f541 some_function(std::basic_ofstream<char, std::char_traits<char> >&) 699 You can clean it up with: 700 auto verbose_type_name = loguru::demangle(typeid(std::ofstream).name()); 701 loguru::add_stack_cleanup(verbose_type_name.c_str(); "std::ofstream"); 702 So the next time you will instead see: 703 0x41f541 some_function(std::ofstream&) 704 705 `replace_with_this` must be shorter than `find_this`. 706 */ 707 LOGURU_EXPORT 708 void add_stack_cleanup(const char* find_this, const char* replace_with_this); 709 710 // Example: demangle(typeid(std::ofstream).name()) -> "std::basic_ofstream<char, std::char_traits<char> >" 711 LOGURU_EXPORT 712 Text demangle(const char* name); 713 714 // ------------------------------------------------------------------------ 715 /* 716 Not all terminals support colors, but if they do, and g_colorlogtostderr 717 is set, Loguru will write them to stderr to make errors in red, etc. 718 719 You also have the option to manually use them, via the function below. 720 721 Note, however, that if you do, the color codes could end up in your logfile! 722 723 This means if you intend to use them functions you should either: 724 * Use them on the stderr/stdout directly (bypass Loguru). 725 * Don't add file outputs to Loguru. 726 * Expect some \e[1m things in your logfile. 727 728 Usage: 729 printf("%sRed%sGreen%sBold green%sClear again\n", 730 loguru::terminal_red(), loguru::terminal_green(), 731 loguru::terminal_bold(), loguru::terminal_reset()); 732 733 If the terminal at hand does not support colors the above output 734 will just not have funky \e[1m things showing. 735 */ 736 737 // Do the output terminal support colors? 738 LOGURU_EXPORT 739 bool terminal_has_color(); 740 741 // Colors 742 LOGURU_EXPORT const char* terminal_black(); 743 LOGURU_EXPORT const char* terminal_red(); 744 LOGURU_EXPORT const char* terminal_green(); 745 LOGURU_EXPORT const char* terminal_yellow(); 746 LOGURU_EXPORT const char* terminal_blue(); 747 LOGURU_EXPORT const char* terminal_purple(); 748 LOGURU_EXPORT const char* terminal_cyan(); 749 LOGURU_EXPORT const char* terminal_light_gray(); 750 LOGURU_EXPORT const char* terminal_light_red(); 751 LOGURU_EXPORT const char* terminal_white(); 752 753 // Formating 754 LOGURU_EXPORT const char* terminal_bold(); 755 LOGURU_EXPORT const char* terminal_underline(); 756 757 // You should end each line with this! 758 LOGURU_EXPORT const char* terminal_reset(); 759 760 // -------------------------------------------------------------------- 761 // Error context related: 762 763 struct StringStream; 764 765 // Use this in your EcEntryBase::print_value overload. 766 LOGURU_EXPORT 767 void stream_print(StringStream& out_string_stream, const char* text); 768 769 class LOGURU_EXPORT EcEntryBase 770 { 771 public: 772 EcEntryBase(const char* file, unsigned line, const char* descr); 773 ~EcEntryBase(); 774 EcEntryBase(const EcEntryBase&) = delete; 775 EcEntryBase(EcEntryBase&&) = delete; 776 EcEntryBase& operator=(const EcEntryBase&) = delete; 777 EcEntryBase& operator=(EcEntryBase&&) = delete; 778 779 virtual void print_value(StringStream& out_string_stream) const = 0; 780 previous() const781 EcEntryBase* previous() const { return _previous; } 782 783 // private: 784 const char* _file; 785 unsigned _line; 786 const char* _descr; 787 EcEntryBase* _previous; 788 }; 789 790 template<typename T> 791 class EcEntryData : public EcEntryBase 792 { 793 public: 794 using Printer = Text(*)(T data); 795 EcEntryData(const char * file,unsigned line,const char * descr,T data,Printer && printer)796 EcEntryData(const char* file, unsigned line, const char* descr, T data, Printer&& printer) 797 : EcEntryBase(file, line, descr), _data(data), _printer(printer) {} 798 print_value(StringStream & out_string_stream) const799 virtual void print_value(StringStream& out_string_stream) const override 800 { 801 const auto str = _printer(_data); 802 stream_print(out_string_stream, str.c_str()); 803 } 804 805 private: 806 T _data; 807 Printer _printer; 808 }; 809 810 // template<typename Printer> 811 // class EcEntryLambda : public EcEntryBase 812 // { 813 // public: 814 // EcEntryLambda(const char* file, unsigned line, const char* descr, Printer&& printer) 815 // : EcEntryBase(file, line, descr), _printer(std::move(printer)) {} 816 817 // virtual void print_value(StringStream& out_string_stream) const override 818 // { 819 // const auto str = _printer(); 820 // stream_print(out_string_stream, str.c_str()); 821 // } 822 823 // private: 824 // Printer _printer; 825 // }; 826 827 // template<typename Printer> 828 // EcEntryLambda<Printer> make_ec_entry_lambda(const char* file, unsigned line, const char* descr, Printer&& printer) 829 // { 830 // return {file, line, descr, std::move(printer)}; 831 // } 832 833 template <class T> 834 struct decay_char_array { using type = T; }; 835 836 template <unsigned long long N> 837 struct decay_char_array<const char(&)[N]> { using type = const char*; }; 838 839 template <class T> 840 struct make_const_ptr { using type = T; }; 841 842 template <class T> 843 struct make_const_ptr<T*> { using type = const T*; }; 844 845 template <class T> 846 struct make_ec_type { using type = typename make_const_ptr<typename decay_char_array<T>::type>::type; }; 847 848 /* A stack trace gives you the names of the function at the point of a crash. 849 With ERROR_CONTEXT, you can also get the values of select local variables. 850 Usage: 851 852 void process_customers(const std::string& filename) 853 { 854 ERROR_CONTEXT("Processing file", filename.c_str()); 855 for (int customer_index : ...) 856 { 857 ERROR_CONTEXT("Customer index", customer_index); 858 ... 859 } 860 } 861 862 The context is in effect during the scope of the ERROR_CONTEXT. 863 Use loguru::get_error_context() to get the contents of the active error contexts. 864 865 Example result: 866 867 ------------------------------------------------ 868 [ErrorContext] main.cpp:416 Processing file: "customers.json" 869 [ErrorContext] main.cpp:417 Customer index: 42 870 ------------------------------------------------ 871 872 Error contexts are printed automatically on crashes, and only on crashes. 873 This makes them much faster than logging the value of a variable. 874 */ 875 #define ERROR_CONTEXT(descr, data) \ 876 const loguru::EcEntryData<loguru::make_ec_type<decltype(data)>::type> \ 877 LOGURU_ANONYMOUS_VARIABLE(error_context_scope_)( \ 878 __FILE__, __LINE__, descr, data, \ 879 static_cast<loguru::EcEntryData<loguru::make_ec_type<decltype(data)>::type>::Printer>(loguru::ec_to_text) ) // For better error messages 880 881 /* 882 #define ERROR_CONTEXT(descr, data) \ 883 const auto LOGURU_ANONYMOUS_VARIABLE(error_context_scope_)( \ 884 loguru::make_ec_entry_lambda(__FILE__, __LINE__, descr, \ 885 [=](){ return loguru::ec_to_text(data); })) 886 */ 887 888 using EcHandle = const EcEntryBase*; 889 890 /* 891 Get a light-weight handle to the error context stack on this thread. 892 The handle is valid as long as the current thread has no changes to its error context stack. 893 You can pass the handle to loguru::get_error_context on another thread. 894 This can be very useful for when you have a parent thread spawning several working threads, 895 and you want the error context of the parent thread to get printed (too) when there is an 896 error on the child thread. You can accomplish this thusly: 897 898 void foo(const char* parameter) 899 { 900 ERROR_CONTEXT("parameter", parameter) 901 const auto parent_ec_handle = loguru::get_thread_ec_handle(); 902 903 std::thread([=]{ 904 loguru::set_thread_name("child thread"); 905 ERROR_CONTEXT("parent context", parent_ec_handle); 906 dangerous_code(); 907 }.join(); 908 } 909 910 */ 911 LOGURU_EXPORT 912 EcHandle get_thread_ec_handle(); 913 914 // Get a string describing the current stack of error context. Empty string if there is none. 915 LOGURU_EXPORT 916 Text get_error_context(); 917 918 // Get a string describing the error context of the given thread handle. 919 LOGURU_EXPORT 920 Text get_error_context_for(EcHandle ec_handle); 921 922 // ------------------------------------------------------------------------ 923 924 LOGURU_EXPORT Text ec_to_text(const char* data); 925 LOGURU_EXPORT Text ec_to_text(char data); 926 LOGURU_EXPORT Text ec_to_text(int data); 927 LOGURU_EXPORT Text ec_to_text(unsigned int data); 928 LOGURU_EXPORT Text ec_to_text(long data); 929 LOGURU_EXPORT Text ec_to_text(unsigned long data); 930 LOGURU_EXPORT Text ec_to_text(long long data); 931 LOGURU_EXPORT Text ec_to_text(unsigned long long data); 932 LOGURU_EXPORT Text ec_to_text(float data); 933 LOGURU_EXPORT Text ec_to_text(double data); 934 LOGURU_EXPORT Text ec_to_text(long double data); 935 LOGURU_EXPORT Text ec_to_text(EcHandle); 936 937 /* 938 You can add ERROR_CONTEXT support for your own types by overloading ec_to_text. Here's how: 939 940 some.hpp: 941 namespace loguru { 942 Text ec_to_text(MySmallType data) 943 Text ec_to_text(const MyBigType* data) 944 } // namespace loguru 945 946 some.cpp: 947 namespace loguru { 948 Text ec_to_text(MySmallType small_value) 949 { 950 // Called only when needed, i.e. on a crash. 951 std::string str = small_value.as_string(); // Format 'small_value' here somehow. 952 return Text{STRDUP(str.c_str())}; 953 } 954 955 Text ec_to_text(const MyBigType* big_value) 956 { 957 // Called only when needed, i.e. on a crash. 958 std::string str = big_value->as_string(); // Format 'big_value' here somehow. 959 return Text{STRDUP(str.c_str())}; 960 } 961 } // namespace loguru 962 963 Any file that include some.hpp: 964 void foo(MySmallType small, const MyBigType& big) 965 { 966 ERROR_CONTEXT("Small", small); // Copy ´small` by value. 967 ERROR_CONTEXT("Big", &big); // `big` should not change during this scope! 968 .... 969 } 970 */ 971 } // namespace loguru 972 973 // -------------------------------------------------------------------- 974 // Logging macros 975 976 // LOG_F(2, "Only logged if verbosity is 2 or higher: %d", some_number); 977 #define VLOG_F(verbosity, ...) \ 978 ((verbosity) > loguru::current_verbosity_cutoff()) ? (void)0 \ 979 : loguru::log(verbosity, __FILE__, __LINE__, __VA_ARGS__) 980 981 // LOG_F(INFO, "Foo: %d", some_number); 982 #define LOG_F(verbosity_name, ...) VLOG_F(loguru::Verbosity_ ## verbosity_name, __VA_ARGS__) 983 984 #define VLOG_IF_F(verbosity, cond, ...) \ 985 ((verbosity) > loguru::current_verbosity_cutoff() || (cond) == false) \ 986 ? (void)0 \ 987 : loguru::log(verbosity, __FILE__, __LINE__, __VA_ARGS__) 988 989 #define LOG_IF_F(verbosity_name, cond, ...) \ 990 VLOG_IF_F(loguru::Verbosity_ ## verbosity_name, cond, __VA_ARGS__) 991 992 #define VLOG_SCOPE_F(verbosity, ...) \ 993 loguru::LogScopeRAII LOGURU_ANONYMOUS_VARIABLE(error_context_RAII_) = \ 994 ((verbosity) > loguru::current_verbosity_cutoff()) ? loguru::LogScopeRAII() : \ 995 loguru::LogScopeRAII(verbosity, __FILE__, __LINE__, __VA_ARGS__) 996 997 // Raw logging - no preamble, no indentation. Slightly faster than full logging. 998 #define RAW_VLOG_F(verbosity, ...) \ 999 ((verbosity) > loguru::current_verbosity_cutoff()) ? (void)0 \ 1000 : loguru::raw_log(verbosity, __FILE__, __LINE__, __VA_ARGS__) 1001 1002 #define RAW_LOG_F(verbosity_name, ...) RAW_VLOG_F(loguru::Verbosity_ ## verbosity_name, __VA_ARGS__) 1003 1004 // Use to book-end a scope. Affects logging on all threads. 1005 #define LOG_SCOPE_F(verbosity_name, ...) \ 1006 VLOG_SCOPE_F(loguru::Verbosity_ ## verbosity_name, __VA_ARGS__) 1007 1008 #define LOG_SCOPE_FUNCTION(verbosity_name) LOG_SCOPE_F(verbosity_name, __func__) 1009 1010 // ----------------------------------------------- 1011 // ABORT_F macro. Usage: ABORT_F("Cause of error: %s", error_str); 1012 1013 // Message is optional 1014 #define ABORT_F(...) loguru::log_and_abort(0, "ABORT: ", __FILE__, __LINE__, __VA_ARGS__) 1015 1016 // -------------------------------------------------------------------- 1017 // CHECK_F macros: 1018 1019 #define CHECK_WITH_INFO_F(test, info, ...) \ 1020 LOGURU_PREDICT_TRUE((test) == true) ? (void)0 : loguru::log_and_abort(0, "CHECK FAILED: " info " ", __FILE__, \ 1021 __LINE__, ##__VA_ARGS__) 1022 1023 /* Checked at runtime too. Will print error, then call fatal_handler (if any), then 'abort'. 1024 Note that the test must be boolean. 1025 CHECK_F(ptr); will not compile, but CHECK_F(ptr != nullptr); will. */ 1026 #define CHECK_F(test, ...) CHECK_WITH_INFO_F(test, #test, ##__VA_ARGS__) 1027 1028 #define CHECK_NOTNULL_F(x, ...) CHECK_WITH_INFO_F((x) != nullptr, #x " != nullptr", ##__VA_ARGS__) 1029 1030 #define CHECK_OP_F(expr_left, expr_right, op, ...) \ 1031 do \ 1032 { \ 1033 auto val_left = expr_left; \ 1034 auto val_right = expr_right; \ 1035 if (! LOGURU_PREDICT_TRUE(val_left op val_right)) \ 1036 { \ 1037 auto str_left = loguru::format_value(val_left); \ 1038 auto str_right = loguru::format_value(val_right); \ 1039 auto fail_info = loguru::textprintf("CHECK FAILED: " LOGURU_FMT(s) " " LOGURU_FMT(s) " " LOGURU_FMT(s) " (" LOGURU_FMT(s) " " LOGURU_FMT(s) " " LOGURU_FMT(s) ") ", \ 1040 #expr_left, #op, #expr_right, str_left.c_str(), #op, str_right.c_str()); \ 1041 auto user_msg = loguru::textprintf(__VA_ARGS__); \ 1042 loguru::log_and_abort(0, fail_info.c_str(), __FILE__, __LINE__, \ 1043 LOGURU_FMT(s), user_msg.c_str()); \ 1044 } \ 1045 } while (false) 1046 1047 #ifndef LOGURU_DEBUG_LOGGING 1048 #ifndef NDEBUG 1049 #define LOGURU_DEBUG_LOGGING 1 1050 #else 1051 #define LOGURU_DEBUG_LOGGING 0 1052 #endif 1053 #endif 1054 1055 #if LOGURU_DEBUG_LOGGING 1056 // Debug logging enabled: 1057 #define DLOG_F(verbosity_name, ...) LOG_F(verbosity_name, __VA_ARGS__) 1058 #define DVLOG_F(verbosity, ...) VLOG_F(verbosity, __VA_ARGS__) 1059 #define DLOG_IF_F(verbosity_name, ...) LOG_IF_F(verbosity_name, __VA_ARGS__) 1060 #define DVLOG_IF_F(verbosity, ...) VLOG_IF_F(verbosity, __VA_ARGS__) 1061 #define DRAW_LOG_F(verbosity_name, ...) RAW_LOG_F(verbosity_name, __VA_ARGS__) 1062 #define DRAW_VLOG_F(verbosity, ...) RAW_VLOG_F(verbosity, __VA_ARGS__) 1063 #else 1064 // Debug logging disabled: 1065 #define DLOG_F(verbosity_name, ...) 1066 #define DVLOG_F(verbosity, ...) 1067 #define DLOG_IF_F(verbosity_name, ...) 1068 #define DVLOG_IF_F(verbosity, ...) 1069 #define DRAW_LOG_F(verbosity_name, ...) 1070 #define DRAW_VLOG_F(verbosity, ...) 1071 #endif 1072 1073 #define CHECK_EQ_F(a, b, ...) CHECK_OP_F(a, b, ==, ##__VA_ARGS__) 1074 #define CHECK_NE_F(a, b, ...) CHECK_OP_F(a, b, !=, ##__VA_ARGS__) 1075 #define CHECK_LT_F(a, b, ...) CHECK_OP_F(a, b, < , ##__VA_ARGS__) 1076 #define CHECK_GT_F(a, b, ...) CHECK_OP_F(a, b, > , ##__VA_ARGS__) 1077 #define CHECK_LE_F(a, b, ...) CHECK_OP_F(a, b, <=, ##__VA_ARGS__) 1078 #define CHECK_GE_F(a, b, ...) CHECK_OP_F(a, b, >=, ##__VA_ARGS__) 1079 1080 #ifndef LOGURU_DEBUG_CHECKS 1081 #ifndef NDEBUG 1082 #define LOGURU_DEBUG_CHECKS 1 1083 #else 1084 #define LOGURU_DEBUG_CHECKS 0 1085 #endif 1086 #endif 1087 1088 #if LOGURU_DEBUG_CHECKS 1089 // Debug checks enabled: 1090 #define DCHECK_F(test, ...) CHECK_F(test, ##__VA_ARGS__) 1091 #define DCHECK_NOTNULL_F(x, ...) CHECK_NOTNULL_F(x, ##__VA_ARGS__) 1092 #define DCHECK_EQ_F(a, b, ...) CHECK_EQ_F(a, b, ##__VA_ARGS__) 1093 #define DCHECK_NE_F(a, b, ...) CHECK_NE_F(a, b, ##__VA_ARGS__) 1094 #define DCHECK_LT_F(a, b, ...) CHECK_LT_F(a, b, ##__VA_ARGS__) 1095 #define DCHECK_LE_F(a, b, ...) CHECK_LE_F(a, b, ##__VA_ARGS__) 1096 #define DCHECK_GT_F(a, b, ...) CHECK_GT_F(a, b, ##__VA_ARGS__) 1097 #define DCHECK_GE_F(a, b, ...) CHECK_GE_F(a, b, ##__VA_ARGS__) 1098 #else 1099 // Debug checks disabled: 1100 #define DCHECK_F(test, ...) 1101 #define DCHECK_NOTNULL_F(x, ...) 1102 #define DCHECK_EQ_F(a, b, ...) 1103 #define DCHECK_NE_F(a, b, ...) 1104 #define DCHECK_LT_F(a, b, ...) 1105 #define DCHECK_LE_F(a, b, ...) 1106 #define DCHECK_GT_F(a, b, ...) 1107 #define DCHECK_GE_F(a, b, ...) 1108 #endif // NDEBUG 1109 1110 1111 #if LOGURU_REDEFINE_ASSERT 1112 #undef assert 1113 #ifndef NDEBUG 1114 // Debug: 1115 #define assert(test) CHECK_WITH_INFO_F(!!(test), #test) // HACK 1116 #else 1117 #define assert(test) 1118 #endif 1119 #endif // LOGURU_REDEFINE_ASSERT 1120 1121 #endif // LOGURU_HAS_DECLARED_FORMAT_HEADER 1122 1123 // ---------------------------------------------------------------------------- 1124 // .dP"Y8 888888 88""Yb 888888 db 8b d8 .dP"Y8 1125 // `Ybo." 88 88__dP 88__ dPYb 88b d88 `Ybo." 1126 // o.`Y8b 88 88"Yb 88"" dP__Yb 88YbdP88 o.`Y8b 1127 // 8bodP' 88 88 Yb 888888 dP""""Yb 88 YY 88 8bodP' 1128 1129 #if LOGURU_WITH_STREAMS 1130 #ifndef LOGURU_HAS_DECLARED_STREAMS_HEADER 1131 #define LOGURU_HAS_DECLARED_STREAMS_HEADER 1132 1133 /* This file extends loguru to enable std::stream-style logging, a la Glog. 1134 It's an optional feature behind the LOGURU_WITH_STREAMS settings 1135 because including it everywhere will slow down compilation times. 1136 */ 1137 1138 #include <cstdarg> 1139 #include <sstream> // Adds about 38 kLoC on clang. 1140 #include <string> 1141 1142 namespace loguru 1143 { 1144 // Like sprintf, but returns the formated text. 1145 LOGURU_EXPORT 1146 std::string strprintf(LOGURU_FORMAT_STRING_TYPE format, ...) LOGURU_PRINTF_LIKE(1, 2); 1147 1148 // Like vsprintf, but returns the formated text. 1149 LOGURU_EXPORT 1150 std::string vstrprintf(LOGURU_FORMAT_STRING_TYPE format, va_list) LOGURU_PRINTF_LIKE(1, 0); 1151 1152 class LOGURU_EXPORT StreamLogger 1153 { 1154 public: StreamLogger(Verbosity verbosity,const char * file,unsigned line)1155 StreamLogger(Verbosity verbosity, const char* file, unsigned line) : _verbosity(verbosity), _file(file), _line(line) {} 1156 ~StreamLogger() noexcept(false); 1157 1158 template<typename T> operator <<(const T & t)1159 StreamLogger& operator<<(const T& t) 1160 { 1161 _ss << t; 1162 return *this; 1163 } 1164 1165 // std::endl and other iomanip:s. operator <<(std::ostream & (* f)(std::ostream &))1166 StreamLogger& operator<<(std::ostream&(*f)(std::ostream&)) 1167 { 1168 f(_ss); 1169 return *this; 1170 } 1171 1172 private: 1173 Verbosity _verbosity; 1174 const char* _file; 1175 unsigned _line; 1176 std::ostringstream _ss; 1177 }; 1178 1179 class LOGURU_EXPORT AbortLogger 1180 { 1181 public: AbortLogger(const char * expr,const char * file,unsigned line)1182 AbortLogger(const char* expr, const char* file, unsigned line) : _expr(expr), _file(file), _line(line) { } 1183 LOGURU_NORETURN ~AbortLogger() noexcept(false); 1184 1185 template<typename T> operator <<(const T & t)1186 AbortLogger& operator<<(const T& t) 1187 { 1188 _ss << t; 1189 return *this; 1190 } 1191 1192 // std::endl and other iomanip:s. operator <<(std::ostream & (* f)(std::ostream &))1193 AbortLogger& operator<<(std::ostream&(*f)(std::ostream&)) 1194 { 1195 f(_ss); 1196 return *this; 1197 } 1198 1199 private: 1200 const char* _expr; 1201 const char* _file; 1202 unsigned _line; 1203 std::ostringstream _ss; 1204 }; 1205 1206 class LOGURU_EXPORT Voidify 1207 { 1208 public: Voidify()1209 Voidify() {} 1210 // This has to be an operator with a precedence lower than << but higher than ?: operator &(const StreamLogger &)1211 void operator&(const StreamLogger&) { } operator &(const AbortLogger &)1212 void operator&(const AbortLogger&) { } 1213 }; 1214 1215 /* Helper functions for CHECK_OP_S macro. 1216 GLOG trick: The (int, int) specialization works around the issue that the compiler 1217 will not instantiate the template version of the function on values of unnamed enum type. */ 1218 #define DEFINE_CHECK_OP_IMPL(name, op) \ 1219 template <typename T1, typename T2> \ 1220 inline std::string* name(const char* expr, const T1& v1, const char* op_str, const T2& v2) \ 1221 { \ 1222 if (LOGURU_PREDICT_TRUE(v1 op v2)) { return NULL; } \ 1223 std::ostringstream ss; \ 1224 ss << "CHECK FAILED: " << expr << " (" << v1 << " " << op_str << " " << v2 << ") "; \ 1225 return new std::string(ss.str()); \ 1226 } \ 1227 inline std::string* name(const char* expr, int v1, const char* op_str, int v2) \ 1228 { \ 1229 return name<int, int>(expr, v1, op_str, v2); \ 1230 } 1231 1232 DEFINE_CHECK_OP_IMPL(check_EQ_impl, ==) 1233 DEFINE_CHECK_OP_IMPL(check_NE_impl, !=) 1234 DEFINE_CHECK_OP_IMPL(check_LE_impl, <=) 1235 DEFINE_CHECK_OP_IMPL(check_LT_impl, < ) 1236 DEFINE_CHECK_OP_IMPL(check_GE_impl, >=) 1237 DEFINE_CHECK_OP_IMPL(check_GT_impl, > ) 1238 #undef DEFINE_CHECK_OP_IMPL 1239 1240 /* GLOG trick: Function is overloaded for integral types to allow static const integrals 1241 declared in classes and not defined to be used as arguments to CHECK* macros. */ 1242 template <class T> referenceable_value(const T & t)1243 inline const T& referenceable_value(const T& t) { return t; } referenceable_value(char t)1244 inline char referenceable_value(char t) { return t; } referenceable_value(unsigned char t)1245 inline unsigned char referenceable_value(unsigned char t) { return t; } referenceable_value(signed char t)1246 inline signed char referenceable_value(signed char t) { return t; } referenceable_value(short t)1247 inline short referenceable_value(short t) { return t; } referenceable_value(unsigned short t)1248 inline unsigned short referenceable_value(unsigned short t) { return t; } referenceable_value(int t)1249 inline int referenceable_value(int t) { return t; } referenceable_value(unsigned int t)1250 inline unsigned int referenceable_value(unsigned int t) { return t; } referenceable_value(long t)1251 inline long referenceable_value(long t) { return t; } referenceable_value(unsigned long t)1252 inline unsigned long referenceable_value(unsigned long t) { return t; } referenceable_value(long long t)1253 inline long long referenceable_value(long long t) { return t; } referenceable_value(unsigned long long t)1254 inline unsigned long long referenceable_value(unsigned long long t) { return t; } 1255 } // namespace loguru 1256 1257 // ----------------------------------------------- 1258 // Logging macros: 1259 1260 // usage: LOG_STREAM(INFO) << "Foo " << std::setprecision(10) << some_value; 1261 #define VLOG_IF_S(verbosity, cond) \ 1262 ((verbosity) > loguru::current_verbosity_cutoff() || (cond) == false) \ 1263 ? (void)0 \ 1264 : loguru::Voidify() & loguru::StreamLogger(verbosity, __FILE__, __LINE__) 1265 #define LOG_IF_S(verbosity_name, cond) VLOG_IF_S(loguru::Verbosity_ ## verbosity_name, cond) 1266 #define VLOG_S(verbosity) VLOG_IF_S(verbosity, true) 1267 #define LOG_S(verbosity_name) VLOG_S(loguru::Verbosity_ ## verbosity_name) 1268 1269 // ----------------------------------------------- 1270 // ABORT_S macro. Usage: ABORT_S() << "Causo of error: " << details; 1271 1272 #define ABORT_S() loguru::Voidify() & loguru::AbortLogger("ABORT: ", __FILE__, __LINE__) 1273 1274 // ----------------------------------------------- 1275 // CHECK_S macros: 1276 1277 #define CHECK_WITH_INFO_S(cond, info) \ 1278 LOGURU_PREDICT_TRUE((cond) == true) \ 1279 ? (void)0 \ 1280 : loguru::Voidify() & loguru::AbortLogger("CHECK FAILED: " info " ", __FILE__, __LINE__) 1281 1282 #define CHECK_S(cond) CHECK_WITH_INFO_S(cond, #cond) 1283 #define CHECK_NOTNULL_S(x) CHECK_WITH_INFO_S((x) != nullptr, #x " != nullptr") 1284 1285 #define CHECK_OP_S(function_name, expr1, op, expr2) \ 1286 while (auto error_string = loguru::function_name(#expr1 " " #op " " #expr2, \ 1287 loguru::referenceable_value(expr1), #op, \ 1288 loguru::referenceable_value(expr2))) \ 1289 loguru::AbortLogger(error_string->c_str(), __FILE__, __LINE__) 1290 1291 #define CHECK_EQ_S(expr1, expr2) CHECK_OP_S(check_EQ_impl, expr1, ==, expr2) 1292 #define CHECK_NE_S(expr1, expr2) CHECK_OP_S(check_NE_impl, expr1, !=, expr2) 1293 #define CHECK_LE_S(expr1, expr2) CHECK_OP_S(check_LE_impl, expr1, <=, expr2) 1294 #define CHECK_LT_S(expr1, expr2) CHECK_OP_S(check_LT_impl, expr1, < , expr2) 1295 #define CHECK_GE_S(expr1, expr2) CHECK_OP_S(check_GE_impl, expr1, >=, expr2) 1296 #define CHECK_GT_S(expr1, expr2) CHECK_OP_S(check_GT_impl, expr1, > , expr2) 1297 1298 #if LOGURU_DEBUG_LOGGING 1299 // Debug logging enabled: 1300 #define DVLOG_IF_S(verbosity, cond) VLOG_IF_S(verbosity, cond) 1301 #define DLOG_IF_S(verbosity_name, cond) LOG_IF_S(verbosity_name, cond) 1302 #define DVLOG_S(verbosity) VLOG_S(verbosity) 1303 #define DLOG_S(verbosity_name) LOG_S(verbosity_name) 1304 #else 1305 // Debug logging disabled: 1306 #define DVLOG_IF_S(verbosity, cond) \ 1307 (true || (verbosity) > loguru::current_verbosity_cutoff() || (cond) == false) \ 1308 ? (void)0 \ 1309 : loguru::Voidify() & loguru::StreamLogger(verbosity, __FILE__, __LINE__) 1310 1311 #define DLOG_IF_S(verbosity_name, cond) DVLOG_IF_S(loguru::Verbosity_ ## verbosity_name, cond) 1312 #define DVLOG_S(verbosity) DVLOG_IF_S(verbosity, true) 1313 #define DLOG_S(verbosity_name) DVLOG_S(loguru::Verbosity_ ## verbosity_name) 1314 #endif 1315 1316 #if LOGURU_DEBUG_CHECKS 1317 // Debug checks enabled: 1318 #define DCHECK_S(cond) CHECK_S(cond) 1319 #define DCHECK_NOTNULL_S(x) CHECK_NOTNULL_S(x) 1320 #define DCHECK_EQ_S(a, b) CHECK_EQ_S(a, b) 1321 #define DCHECK_NE_S(a, b) CHECK_NE_S(a, b) 1322 #define DCHECK_LT_S(a, b) CHECK_LT_S(a, b) 1323 #define DCHECK_LE_S(a, b) CHECK_LE_S(a, b) 1324 #define DCHECK_GT_S(a, b) CHECK_GT_S(a, b) 1325 #define DCHECK_GE_S(a, b) CHECK_GE_S(a, b) 1326 #else 1327 // Debug checks disabled: 1328 #define DCHECK_S(cond) CHECK_S(true || (cond)) 1329 #define DCHECK_NOTNULL_S(x) CHECK_S(true || (x) != nullptr) 1330 #define DCHECK_EQ_S(a, b) CHECK_S(true || (a) == (b)) 1331 #define DCHECK_NE_S(a, b) CHECK_S(true || (a) != (b)) 1332 #define DCHECK_LT_S(a, b) CHECK_S(true || (a) < (b)) 1333 #define DCHECK_LE_S(a, b) CHECK_S(true || (a) <= (b)) 1334 #define DCHECK_GT_S(a, b) CHECK_S(true || (a) > (b)) 1335 #define DCHECK_GE_S(a, b) CHECK_S(true || (a) >= (b)) 1336 #endif 1337 1338 #if LOGURU_REPLACE_GLOG 1339 #undef LOG 1340 #undef VLOG 1341 #undef LOG_IF 1342 #undef VLOG_IF 1343 #undef CHECK 1344 #undef CHECK_NOTNULL 1345 #undef CHECK_EQ 1346 #undef CHECK_NE 1347 #undef CHECK_LT 1348 #undef CHECK_LE 1349 #undef CHECK_GT 1350 #undef CHECK_GE 1351 #undef DLOG 1352 #undef DVLOG 1353 #undef DLOG_IF 1354 #undef DVLOG_IF 1355 #undef DCHECK 1356 #undef DCHECK_NOTNULL 1357 #undef DCHECK_EQ 1358 #undef DCHECK_NE 1359 #undef DCHECK_LT 1360 #undef DCHECK_LE 1361 #undef DCHECK_GT 1362 #undef DCHECK_GE 1363 #undef VLOG_IS_ON 1364 1365 #define LOG LOG_S 1366 #define VLOG VLOG_S 1367 #define LOG_IF LOG_IF_S 1368 #define VLOG_IF VLOG_IF_S 1369 #define CHECK(cond) CHECK_S(!!(cond)) 1370 #define CHECK_NOTNULL CHECK_NOTNULL_S 1371 #define CHECK_EQ CHECK_EQ_S 1372 #define CHECK_NE CHECK_NE_S 1373 #define CHECK_LT CHECK_LT_S 1374 #define CHECK_LE CHECK_LE_S 1375 #define CHECK_GT CHECK_GT_S 1376 #define CHECK_GE CHECK_GE_S 1377 #define DLOG DLOG_S 1378 #define DVLOG DVLOG_S 1379 #define DLOG_IF DLOG_IF_S 1380 #define DVLOG_IF DVLOG_IF_S 1381 #define DCHECK DCHECK_S 1382 #define DCHECK_NOTNULL DCHECK_NOTNULL_S 1383 #define DCHECK_EQ DCHECK_EQ_S 1384 #define DCHECK_NE DCHECK_NE_S 1385 #define DCHECK_LT DCHECK_LT_S 1386 #define DCHECK_LE DCHECK_LE_S 1387 #define DCHECK_GT DCHECK_GT_S 1388 #define DCHECK_GE DCHECK_GE_S 1389 #define VLOG_IS_ON(verbosity) ((verbosity) <= loguru::current_verbosity_cutoff()) 1390 1391 #endif // LOGURU_REPLACE_GLOG 1392 1393 #endif // LOGURU_WITH_STREAMS 1394 1395 #endif // LOGURU_HAS_DECLARED_STREAMS_HEADER 1396