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