diff -Nru spdlog-1.9.2+ds/appveyor.yml spdlog-1.10.0+ds/appveyor.yml --- spdlog-1.9.2+ds/appveyor.yml 2021-08-12 11:10:50.000000000 +0000 +++ spdlog-1.10.0+ds/appveyor.yml 2022-04-04 13:48:58.000000000 +0000 @@ -8,55 +8,91 @@ WCHAR: 'OFF' WCHAR_FILES: 'OFF' BUILD_EXAMPLE: 'ON' + USE_STD_FORMAT: 'OFF' + CXX_STANDARD: 11 - GENERATOR: '"Visual Studio 14 2015"' BUILD_TYPE: Release BUILD_SHARED: 'OFF' WCHAR: 'ON' WCHAR_FILES: 'OFF' BUILD_EXAMPLE: 'ON' + USE_STD_FORMAT: 'OFF' + CXX_STANDARD: 11 - GENERATOR: '"Visual Studio 14 2015 Win64"' BUILD_TYPE: Debug BUILD_SHARED: 'OFF' WCHAR: 'ON' WCHAR_FILES: 'OFF' BUILD_EXAMPLE: 'ON' + USE_STD_FORMAT: 'OFF' + CXX_STANDARD: 11 - GENERATOR: '"Visual Studio 14 2015 Win64"' BUILD_TYPE: Release BUILD_SHARED: 'OFF' WCHAR: 'ON' WCHAR_FILES: 'OFF' BUILD_EXAMPLE: 'ON' + USE_STD_FORMAT: 'OFF' + CXX_STANDARD: 11 - GENERATOR: '"Visual Studio 15 2017 Win64"' BUILD_TYPE: Debug BUILD_SHARED: 'OFF' WCHAR: 'ON' WCHAR_FILES: 'OFF' BUILD_EXAMPLE: 'ON' + USE_STD_FORMAT: 'OFF' + CXX_STANDARD: 11 - GENERATOR: '"Visual Studio 15 2017 Win64"' BUILD_TYPE: Release BUILD_SHARED: 'OFF' WCHAR: 'OFF' WCHAR_FILES: 'OFF' BUILD_EXAMPLE: 'ON' + USE_STD_FORMAT: 'OFF' + CXX_STANDARD: 11 - GENERATOR: '"Visual Studio 15 2017 Win64"' BUILD_TYPE: Release BUILD_SHARED: 'ON' WCHAR: 'OFF' WCHAR_FILES: 'OFF' BUILD_EXAMPLE: 'ON' + USE_STD_FORMAT: 'OFF' + CXX_STANDARD: 11 - GENERATOR: '"Visual Studio 15 2017 Win64"' BUILD_TYPE: Release BUILD_SHARED: 'ON' WCHAR: 'ON' WCHAR_FILES: 'ON' BUILD_EXAMPLE: 'OFF' + USE_STD_FORMAT: 'OFF' + CXX_STANDARD: 11 - GENERATOR: '"Visual Studio 16 2019" -A x64' BUILD_TYPE: Release BUILD_SHARED: 'ON' WCHAR: 'OFF' WCHAR_FILES: 'OFF' BUILD_EXAMPLE: 'OFF' + USE_STD_FORMAT: 'OFF' + CXX_STANDARD: 17 APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2019 + - GENERATOR: '"Visual Studio 17 2022" -A x64' + BUILD_TYPE: Release + BUILD_SHARED: 'ON' + WCHAR: 'OFF' + WCHAR_FILES: 'OFF' + BUILD_EXAMPLE: 'OFF' + USE_STD_FORMAT: 'ON' + CXX_STANDARD: 23 # std::format is only available with /std:c++latest at the moment. + APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2022 + - GENERATOR: '"Visual Studio 17 2022" -A x64' + BUILD_TYPE: Release + BUILD_SHARED: 'ON' + WCHAR: 'ON' + WCHAR_FILES: 'ON' + BUILD_EXAMPLE: 'OFF' + USE_STD_FORMAT: 'ON' + CXX_STANDARD: 23 # std::format is only available with /std:c++latest at the moment. + APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2022 build_script: - cmd: >- set @@ -67,7 +103,7 @@ set PATH=%PATH%;C:\Program Files\Git\usr\bin - cmake -G %GENERATOR% -D CMAKE_BUILD_TYPE=%BUILD_TYPE% -D BUILD_SHARED_LIBS=%BUILD_SHARED% -D SPDLOG_WCHAR_SUPPORT=%WCHAR% -D SPDLOG_WCHAR_FILENAMES=%WCHAR_FILES% -D SPDLOG_BUILD_EXAMPLE=%BUILD_EXAMPLE% -D SPDLOG_BUILD_EXAMPLE_HO=%BUILD_EXAMPLE% -D SPDLOG_BUILD_TESTS=ON -D SPDLOG_BUILD_TESTS_HO=OFF -D SPDLOG_BUILD_WARNINGS=ON .. + cmake -G %GENERATOR% -D CMAKE_BUILD_TYPE=%BUILD_TYPE% -D BUILD_SHARED_LIBS=%BUILD_SHARED% -D SPDLOG_WCHAR_SUPPORT=%WCHAR% -D SPDLOG_WCHAR_FILENAMES=%WCHAR_FILES% -D SPDLOG_BUILD_EXAMPLE=%BUILD_EXAMPLE% -D SPDLOG_BUILD_EXAMPLE_HO=%BUILD_EXAMPLE% -D SPDLOG_BUILD_TESTS=ON -D SPDLOG_BUILD_TESTS_HO=OFF -D SPDLOG_BUILD_WARNINGS=ON -D SPDLOG_USE_STD_FORMAT=%USE_STD_FORMAT% -D CMAKE_CXX_STANDARD=%CXX_STANDARD% .. cmake --build . --config %BUILD_TYPE% diff -Nru spdlog-1.9.2+ds/bench/async_bench.cpp spdlog-1.10.0+ds/bench/async_bench.cpp --- spdlog-1.9.2+ds/bench/async_bench.cpp 2021-08-12 11:10:50.000000000 +0000 +++ spdlog-1.10.0+ds/bench/async_bench.cpp 2022-04-04 13:48:58.000000000 +0000 @@ -10,7 +10,9 @@ #include "spdlog/async.h" #include "spdlog/sinks/basic_file_sink.h" -#ifdef SPDLOG_FMT_EXTERNAL +#if defined(SPDLOG_USE_STD_FORMAT) +# include +#elif defined(SPDLOG_FMT_EXTERNAL) # include #else # include "spdlog/fmt/bundled/format.h" @@ -160,7 +162,7 @@ void bench_mt(int howmany, std::shared_ptr logger, int thread_count) { using std::chrono::high_resolution_clock; - vector threads; + vector threads; auto start = high_resolution_clock::now(); int msgs_per_thread = howmany / thread_count; diff -Nru spdlog-1.9.2+ds/bench/bench.cpp spdlog-1.10.0+ds/bench/bench.cpp --- spdlog-1.9.2+ds/bench/bench.cpp 2021-08-12 11:10:50.000000000 +0000 +++ spdlog-1.10.0+ds/bench/bench.cpp 2022-04-04 13:48:58.000000000 +0000 @@ -12,7 +12,9 @@ #include "spdlog/sinks/null_sink.h" #include "spdlog/sinks/rotating_file_sink.h" -#ifdef SPDLOG_FMT_EXTERNAL +#if defined(SPDLOG_USE_STD_FORMAT) +# include +#elif defined(SPDLOG_FMT_EXTERNAL) # include #else # include "spdlog/fmt/bundled/format.h" @@ -38,7 +40,7 @@ void bench_threaded_logging(size_t threads, int iters) { spdlog::info("**************************************************************"); - spdlog::info(fmt::format(std::locale("en_US.UTF-8"), "Multi threaded: {:L} threads, {:L} messages", threads, iters)); + spdlog::info(spdlog::fmt_lib::format(std::locale("en_US.UTF-8"), "Multi threaded: {:L} threads, {:L} messages", threads, iters)); spdlog::info("**************************************************************"); auto basic_mt = spdlog::basic_logger_mt("basic_mt", "logs/basic_mt.log", true); @@ -74,7 +76,7 @@ void bench_single_threaded(int iters) { spdlog::info("**************************************************************"); - spdlog::info(fmt::format(std::locale("en_US.UTF-8"), "Single threaded: {} messages", iters)); + spdlog::info(spdlog::fmt_lib::format(std::locale("en_US.UTF-8"), "Single threaded: {} messages", iters)); spdlog::info("**************************************************************"); auto basic_st = spdlog::basic_logger_st("basic_st", "logs/basic_st.log", true); @@ -128,7 +130,7 @@ if (threads > max_threads) { - throw std::runtime_error(fmt::format("Number of threads exceeds maximum({})", max_threads)); + throw std::runtime_error(spdlog::fmt_lib::format("Number of threads exceeds maximum({})", max_threads)); } bench_single_threaded(iters); @@ -158,8 +160,8 @@ auto delta = high_resolution_clock::now() - start; auto delta_d = duration_cast>(delta).count(); - spdlog::info( - fmt::format(std::locale("en_US.UTF-8"), "{:<30} Elapsed: {:0.2f} secs {:>16L}/sec", log->name(), delta_d, int(howmany / delta_d))); + spdlog::info(spdlog::fmt_lib::format( + std::locale("en_US.UTF-8"), "{:<30} Elapsed: {:0.2f} secs {:>16L}/sec", log->name(), delta_d, int(howmany / delta_d))); spdlog::drop(log->name()); } @@ -189,8 +191,8 @@ auto delta = high_resolution_clock::now() - start; auto delta_d = duration_cast>(delta).count(); - spdlog::info( - fmt::format(std::locale("en_US.UTF-8"), "{:<30} Elapsed: {:0.2f} secs {:>16L}/sec", log->name(), delta_d, int(howmany / delta_d))); + spdlog::info(spdlog::fmt_lib::format( + std::locale("en_US.UTF-8"), "{:<30} Elapsed: {:0.2f} secs {:>16L}/sec", log->name(), delta_d, int(howmany / delta_d))); spdlog::drop(log->name()); } diff -Nru spdlog-1.9.2+ds/bench/CMakeLists.txt spdlog-1.10.0+ds/bench/CMakeLists.txt --- spdlog-1.9.2+ds/bench/CMakeLists.txt 2021-08-12 11:10:50.000000000 +0000 +++ spdlog-1.10.0+ds/bench/CMakeLists.txt 2022-04-04 13:48:58.000000000 +0000 @@ -16,10 +16,11 @@ # User can fetch googlebenchmark message(STATUS "Downloading GoogleBenchmark") include(FetchContent) - set(BENCHMARK_ENABLE_GTEST_TESTS OFF CACHE INTERNAL "") - # Do not build and run googlebenchmark tests - FetchContent_Declare(googlebenchmark GIT_REPOSITORY https://github.com/google/benchmark.git GIT_TAG v1.5.2) + # disable tests + set(BENCHMARK_ENABLE_TESTING OFF CACHE INTERNAL "") + # Do not build and run googlebenchmark tests + FetchContent_Declare(googlebenchmark GIT_REPOSITORY https://github.com/google/benchmark.git GIT_TAG v1.6.0) FetchContent_MakeAvailable(googlebenchmark) else() message(FATAL_ERROR "GoogleBenchmark is missing. Use CMake >= 3.11 or download it") diff -Nru spdlog-1.9.2+ds/cmake/spdlogConfig.cmake.in spdlog-1.10.0+ds/cmake/spdlogConfig.cmake.in --- spdlog-1.9.2+ds/cmake/spdlogConfig.cmake.in 2021-08-12 11:10:50.000000000 +0000 +++ spdlog-1.10.0+ds/cmake/spdlogConfig.cmake.in 2022-04-04 13:48:58.000000000 +0000 @@ -6,9 +6,10 @@ find_package(Threads REQUIRED) set(SPDLOG_FMT_EXTERNAL @SPDLOG_FMT_EXTERNAL@) +set(SPDLOG_FMT_EXTERNAL_HO @SPDLOG_FMT_EXTERNAL_HO@) set(config_targets_file @config_targets_file@) -if(SPDLOG_FMT_EXTERNAL) +if(SPDLOG_FMT_EXTERNAL OR SPDLOG_FMT_EXTERNAL_HO) include(CMakeFindDependencyMacro) find_dependency(fmt CONFIG) endif() @@ -16,4 +17,4 @@ include("${CMAKE_CURRENT_LIST_DIR}/${config_targets_file}") -check_required_components(spdlog) \ No newline at end of file +check_required_components(spdlog) diff -Nru spdlog-1.9.2+ds/CMakeLists.txt spdlog-1.10.0+ds/CMakeLists.txt --- spdlog-1.9.2+ds/CMakeLists.txt 2021-08-12 11:10:50.000000000 +0000 +++ spdlog-1.10.0+ds/CMakeLists.txt 2022-04-04 13:48:58.000000000 +0000 @@ -1,6 +1,6 @@ # Copyright(c) 2019 spdlog authors Distributed under the MIT License (http://opensource.org/licenses/MIT) -cmake_minimum_required(VERSION 3.10) +cmake_minimum_required(VERSION 3.10...3.21) # --------------------------------------------------------------------------------------- # Start spdlog project @@ -16,13 +16,6 @@ include(GNUInstallDirs) # --------------------------------------------------------------------------------------- -# Set CMake policies to support later version behaviour -# --------------------------------------------------------------------------------------- -if(POLICY CMP0077) - cmake_policy(SET CMP0077 NEW) # option() honors variables already set -endif() - -# --------------------------------------------------------------------------------------- # Set default build to release # --------------------------------------------------------------------------------------- if(NOT CMAKE_BUILD_TYPE) @@ -87,6 +80,7 @@ # install options option(SPDLOG_INSTALL "Generate the install target" ${SPDLOG_MASTER_PROJECT}) +option(SPDLOG_USE_STD_FORMAT "Use std::format instead of fmt library. No compile-time format string checking." OFF) option(SPDLOG_FMT_EXTERNAL "Use external fmt library instead of bundled" OFF) option(SPDLOG_FMT_EXTERNAL_HO "Use external fmt header-only library instead of bundled" OFF) option(SPDLOG_NO_EXCEPTIONS "Compile with -fno-exceptions. Call abort() on any spdlog exceptions" OFF) @@ -95,6 +89,14 @@ message(FATAL_ERROR "SPDLOG_FMT_EXTERNAL and SPDLOG_FMT_EXTERNAL_HO are mutually exclusive") endif() +if(SPDLOG_USE_STD_FORMAT AND SPDLOG_FMT_EXTERNAL_HO) + message(FATAL_ERROR "SPDLOG_USE_STD_FORMAT and SPDLOG_FMT_EXTERNAL_HO are mutually exclusive") +endif() + +if(SPDLOG_USE_STD_FORMAT AND SPDLOG_FMT_EXTERNAL) + message(FATAL_ERROR "SPDLOG_USE_STD_FORMAT and SPDLOG_FMT_EXTERNAL are mutually exclusive") +endif() + # misc tweakme options if(WIN32) option(SPDLOG_WCHAR_SUPPORT "Support wchar api" OFF) @@ -137,7 +139,7 @@ # --------------------------------------------------------------------------------------- set(SPDLOG_SRCS src/spdlog.cpp src/stdout_sinks.cpp src/color_sinks.cpp src/file_sinks.cpp src/async.cpp src/cfg.cpp) -if(NOT SPDLOG_FMT_EXTERNAL AND NOT SPDLOG_FMT_EXTERNAL_HO) +if(NOT SPDLOG_USE_STD_FORMAT AND NOT SPDLOG_FMT_EXTERNAL AND NOT SPDLOG_FMT_EXTERNAL_HO) list(APPEND SPDLOG_SRCS src/fmt.cpp) endif() @@ -152,7 +154,7 @@ target_compile_options(spdlog PUBLIC $<$,$>>:/wd4251 /wd4275>) endif() - if(NOT SPDLOG_FMT_EXTERNAL AND NOT SPDLOG_FMT_EXTERNAL_HO) + if(NOT SPDLOG_USE_STD_FORMAT AND NOT SPDLOG_FMT_EXTERNAL AND NOT SPDLOG_FMT_EXTERNAL_HO) target_compile_definitions(spdlog PRIVATE FMT_EXPORT PUBLIC FMT_SHARED) endif() else() @@ -229,7 +231,8 @@ SPDLOG_NO_THREAD_ID SPDLOG_NO_TLS SPDLOG_NO_ATOMIC_LEVELS - SPDLOG_DISABLE_DEFAULT_LOGGER) + SPDLOG_DISABLE_DEFAULT_LOGGER + SPDLOG_USE_STD_FORMAT) if(${SPDLOG_OPTION}) target_compile_definitions(spdlog PUBLIC ${SPDLOG_OPTION}) target_compile_definitions(spdlog_header_only INTERFACE ${SPDLOG_OPTION}) @@ -287,7 +290,7 @@ ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}) - if(NOT SPDLOG_FMT_EXTERNAL AND NOT SPDLOG_FMT_EXTERNAL_HO) + if(NOT SPDLOG_USE_STD_FORMAT AND NOT SPDLOG_FMT_EXTERNAL AND NOT SPDLOG_FMT_EXTERNAL_HO) install(DIRECTORY include/${PROJECT_NAME}/fmt/bundled/ DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}/${PROJECT_NAME}/fmt/bundled/") endif() diff -Nru spdlog-1.9.2+ds/debian/changelog spdlog-1.10.0+ds/debian/changelog --- spdlog-1.9.2+ds/debian/changelog 2021-12-18 16:37:10.000000000 +0000 +++ spdlog-1.10.0+ds/debian/changelog 2022-07-28 14:46:40.000000000 +0000 @@ -1,9 +1,37 @@ -spdlog (1:1.9.2+ds-0.2) unstable; urgency=medium +spdlog (1:1.10.0+ds-0.1) unstable; urgency=medium * Non-maintainer upload. - * Upload to unstable. + * Upload to unstable. (Closes: #1014568) - -- Boyuan Yang Sat, 18 Dec 2021 11:37:10 -0500 + -- Shengjing Zhu Thu, 28 Jul 2022 22:46:40 +0800 + +spdlog (1:1.10.0+ds-0.1~exp2) experimental; urgency=medium + + * Team upload. + * Rebuild without library symbols which are unsupportable for + c++ library. + * debian/libspdlog1.symbols: Dropped. + + -- Boyuan Yang Sat, 11 Jun 2022 09:24:35 -0400 + +spdlog (1:1.10.0+ds-0.1~exp1) experimental; urgency=medium + + * Non-maintainer upload coordinated with maintainer team. (#1012566) + + [ xiao sheng wen ] + * New upstream version 1.10.0+ds (Closes: #1012566) + * d/patches/use-external-fmt.patch: update for New upstream version 1.10.0+ds + + [ Andreas Tille ] + * Add symbols file + * Standards-Version: 4.6.1 (routine-update) + + [ Boyuan Yang ] + * debian/libspdlog1.symbols: Add Build-Depends-Package field. + * debian/libspdlog1.symbols: Activate SymbolsHelper for a test + experimental build. + + -- Boyuan Yang Fri, 10 Jun 2022 20:25:58 -0400 spdlog (1:1.9.2+ds-0.1) experimental; urgency=medium diff -Nru spdlog-1.9.2+ds/debian/control spdlog-1.10.0+ds/debian/control --- spdlog-1.9.2+ds/debian/control 2021-12-18 16:37:00.000000000 +0000 +++ spdlog-1.10.0+ds/debian/control 2022-07-28 14:46:40.000000000 +0000 @@ -10,7 +10,7 @@ libfmt-dev (>= 8.0.1), pkg-kde-tools, catch2 -Standards-Version: 4.6.0 +Standards-Version: 4.6.1 Vcs-Browser: https://salsa.debian.org/med-team/spdlog Vcs-Git: https://salsa.debian.org/med-team/spdlog.git Homepage: https://github.com/gabime/spdlog diff -Nru spdlog-1.9.2+ds/debian/patches/use-external-fmt.patch spdlog-1.10.0+ds/debian/patches/use-external-fmt.patch --- spdlog-1.9.2+ds/debian/patches/use-external-fmt.patch 2021-12-18 16:37:00.000000000 +0000 +++ spdlog-1.10.0+ds/debian/patches/use-external-fmt.patch 2022-07-28 14:46:40.000000000 +0000 @@ -1,29 +1,23 @@ Author: Nilesh Patra + xiao sheng wen Description: Use external libfmt by default -Last-Changed: Sun, May, 14 2020 +Last-Changed: Fri, 10 Jun 2022 Forwarded: not-needed +diff --git a/CMakeLists.txt b/CMakeLists.txt +index 21577e5..ddfc018 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt -@@ -87,7 +87,7 @@ option(SPDLOG_BUILD_WARNINGS "Enable com - +@@ -81,7 +81,7 @@ option(SPDLOG_BUILD_WARNINGS "Enable compiler warnings" OFF) # install options option(SPDLOG_INSTALL "Generate the install target" ${SPDLOG_MASTER_PROJECT}) + option(SPDLOG_USE_STD_FORMAT "Use std::format instead of fmt library. No compile-time format string checking." OFF) -option(SPDLOG_FMT_EXTERNAL "Use external fmt library instead of bundled" OFF) +option(SPDLOG_FMT_EXTERNAL "Use external fmt library instead of bundled" ON) option(SPDLOG_FMT_EXTERNAL_HO "Use external fmt header-only library instead of bundled" OFF) option(SPDLOG_NO_EXCEPTIONS "Compile with -fno-exceptions. Call abort() on any spdlog exceptions" OFF) ---- a/include/spdlog/tweakme.h -+++ b/include/spdlog/tweakme.h -@@ -71,7 +71,7 @@ - // In this case spdlog will try to include so set your -I flag - // accordingly. - // --// #define SPDLOG_FMT_EXTERNAL -+#define SPDLOG_FMT_EXTERNAL 1 - /////////////////////////////////////////////////////////////////////////////// - - /////////////////////////////////////////////////////////////////////////////// +diff --git a/include/spdlog/fmt/bin_to_hex.h b/include/spdlog/fmt/bin_to_hex.h +index 93e5c28..6f8e2fb 100644 --- a/include/spdlog/fmt/bin_to_hex.h +++ b/include/spdlog/fmt/bin_to_hex.h @@ -5,6 +5,7 @@ @@ -34,6 +28,8 @@ #include #include +diff --git a/include/spdlog/fmt/fmt.h b/include/spdlog/fmt/fmt.h +index fa4a2a8..682fda0 100644 --- a/include/spdlog/fmt/fmt.h +++ b/include/spdlog/fmt/fmt.h @@ -4,7 +4,7 @@ @@ -45,17 +41,33 @@ // // Include a bundled header-only copy of fmtlib or an external one. // By default spdlog include its own copy. +diff --git a/include/spdlog/fmt/ostr.h b/include/spdlog/fmt/ostr.h +index 7588034..19d2e0b 100644 --- a/include/spdlog/fmt/ostr.h +++ b/include/spdlog/fmt/ostr.h -@@ -7,7 +7,7 @@ - // +@@ -8,6 +8,7 @@ // include bundled or external copy of fmtlib's ostream support // -- + +#include - #if !defined(SPDLOG_FMT_EXTERNAL) - # ifdef SPDLOG_HEADER_ONLY - # ifndef FMT_HEADER_ONLY + #if !defined(SPDLOG_USE_STD_FORMAT) + # if !defined(SPDLOG_FMT_EXTERNAL) + # ifdef SPDLOG_HEADER_ONLY +diff --git a/include/spdlog/tweakme.h b/include/spdlog/tweakme.h +index 8fa60e4..8d6508f 100644 +--- a/include/spdlog/tweakme.h ++++ b/include/spdlog/tweakme.h +@@ -71,7 +71,7 @@ + // In this case spdlog will try to include so set your -I flag + // accordingly. + // +-// #define SPDLOG_FMT_EXTERNAL ++#define SPDLOG_FMT_EXTERNAL 1 + /////////////////////////////////////////////////////////////////////////////// + + /////////////////////////////////////////////////////////////////////////////// +diff --git a/src/fmt.cpp b/src/fmt.cpp +index 8caa18d..cb043b3 100644 --- a/src/fmt.cpp +++ b/src/fmt.cpp @@ -6,6 +6,7 @@ @@ -63,6 +75,7 @@ #endif +#include - #if !defined(SPDLOG_FMT_EXTERNAL) + #if !defined(SPDLOG_FMT_EXTERNAL) && !defined(SPDLOG_USE_STD_FORMAT) # include + diff -Nru spdlog-1.9.2+ds/example/example.cpp spdlog-1.10.0+ds/example/example.cpp --- spdlog-1.9.2+ds/example/example.cpp 2021-08-12 11:10:50.000000000 +0000 +++ spdlog-1.10.0+ds/example/example.cpp 2022-04-04 13:48:58.000000000 +0000 @@ -5,6 +5,7 @@ // spdlog usage example #include +#include void load_levels_example(); void stdout_logger_example(); @@ -13,13 +14,17 @@ void daily_example(); void async_example(); void binary_example(); +void vector_example(); void stopwatch_example(); void trace_example(); void multi_sink_example(); void user_defined_example(); void err_handler_example(); void syslog_example(); +void udp_example(); void custom_flags_example(); +void file_events_example(); +void replace_default_logger_example(); #include "spdlog/spdlog.h" #include "spdlog/cfg/env.h" // support for loading levels from the environment variable @@ -69,12 +74,16 @@ daily_example(); async_example(); binary_example(); + vector_example(); multi_sink_example(); user_defined_example(); err_handler_example(); trace_example(); stopwatch_example(); + udp_example(); custom_flags_example(); + file_events_example(); + replace_default_logger_example(); // Flush all *registered* loggers using a worker thread every 3 seconds. // note: registered loggers *must* be thread safe for this to work correctly! @@ -110,7 +119,7 @@ void basic_example() { // Create basic file logger (not rotated). - auto my_logger = spdlog::basic_logger_mt("file_logger", "logs/basic-log.txt"); + auto my_logger = spdlog::basic_logger_mt("file_logger", "logs/basic-log.txt", true); } #include "spdlog/sinks/rotating_file_sink.h" @@ -181,6 +190,21 @@ // logger->info("hexdump style, 20 chars per line {:a}", spdlog::to_hex(buf, 20)); } +// Log a vector of numbers +#ifndef SPDLOG_USE_STD_FORMAT +# include "spdlog/fmt/ranges.h" +void vector_example() +{ + std::vector vec = {1, 2, 3}; + spdlog::info("Vector example: {}", vec); +} + +#else +void vector_example() {} +#endif + +// ! DSPDLOG_USE_STD_FORMAT + // Compile time log levels. // define SPDLOG_ACTIVE_LEVEL to required level (e.g. SPDLOG_LEVEL_TRACE) void trace_example() @@ -205,6 +229,15 @@ spdlog::info("Stopwatch: {} seconds", sw); } +#include "spdlog/sinks/udp_sink.h" +void udp_example() +{ + spdlog::sinks::udp_sink_config cfg("127.0.0.1", 11091); + auto my_logger = spdlog::udp_logger_mt("udplog", cfg); + my_logger->set_level(spdlog::level::debug); + my_logger->info("hello world"); +} + // A logger with multiple sinks (stdout and file) - each with a different format and log level. void multi_sink_example() { @@ -221,20 +254,27 @@ logger.info("this message should not appear in the console, only in the file"); } -// User defined types logging by implementing operator<< +// User defined types logging struct my_type { - int i; - template - friend OStream &operator<<(OStream &os, const my_type &c) + int i = 0; + explicit my_type(int i) + : i(i){}; +}; + +namespace fmt_lib = spdlog::fmt_lib; +template<> +struct fmt_lib::formatter : fmt_lib::formatter +{ + auto format(my_type my, format_context &ctx) -> decltype(ctx.out()) { - return os << "[my_type i=" << c.i << "]"; + return fmt_lib::format_to(ctx.out(), "[my_type i={}]", my.i); } }; void user_defined_example() { - spdlog::info("user defined type: {}", my_type{14}); + spdlog::info("user defined type: {}", my_type(14)); } // Custom error handler. Will be triggered on log failure. @@ -290,5 +330,40 @@ using spdlog::details::make_unique; // for pre c++14 auto formatter = make_unique(); formatter->add_flag('*').set_pattern("[%n] [%*] [%^%l%$] %v"); - spdlog::set_formatter(std::move(formatter)); + // set the new formatter using spdlog::set_formatter(formatter) or logger->set_formatter(formatter) + // spdlog::set_formatter(std::move(formatter)); +} + +void file_events_example() +{ + // pass the spdlog::file_event_handlers to file sinks for open/close log file notifications + spdlog::file_event_handlers handlers; + handlers.before_open = [](spdlog::filename_t filename) { spdlog::info("Before opening {}", filename); }; + handlers.after_open = [](spdlog::filename_t filename, std::FILE *fstream) { + spdlog::info("After opening {}", filename); + fputs("After opening\n", fstream); + }; + handlers.before_close = [](spdlog::filename_t filename, std::FILE *fstream) { + spdlog::info("Before closing {}", filename); + fputs("Before closing\n", fstream); + }; + handlers.after_close = [](spdlog::filename_t filename) { spdlog::info("After closing {}", filename); }; + auto file_sink = std::make_shared("logs/events-sample.txt", true, handlers); + spdlog::logger my_logger("some_logger", file_sink); + my_logger.info("Some log line"); +} + +void replace_default_logger_example() +{ + // store the old logger so we don't break other examples. + auto old_logger = spdlog::default_logger(); + + auto new_logger = spdlog::basic_logger_mt("new_default_logger", "logs/new-default-log.txt", true); + spdlog::set_default_logger(new_logger); + spdlog::set_level(spdlog::level::info); + spdlog::debug("This message should not be displayed!"); + spdlog::set_level(spdlog::level::trace); + spdlog::debug("This message should be displayed.."); + + spdlog::set_default_logger(old_logger); } diff -Nru spdlog-1.9.2+ds/.gitignore spdlog-1.10.0+ds/.gitignore --- spdlog-1.9.2+ds/.gitignore 2021-08-12 11:10:50.000000000 +0000 +++ spdlog-1.10.0+ds/.gitignore 2022-04-04 13:48:58.000000000 +0000 @@ -1,4 +1,6 @@ # Auto generated files +[Dd]ebug/ +[Rr]elease/ build/* *.slo *.lo @@ -55,6 +57,7 @@ # generated files generated +version.rc # Cmake CMakeCache.txt @@ -67,6 +70,8 @@ /tests/tests.VC.db /tests/tests /tests/logs/* +spdlogConfig.cmake +spdlogConfigVersion.cmake # idea .idea/ @@ -81,3 +86,7 @@ *.tcl *.user *.sln + +# macos +*.DS_store +*.xcodeproj/ diff -Nru spdlog-1.9.2+ds/include/spdlog/async.h spdlog-1.10.0+ds/include/spdlog/async.h --- spdlog-1.9.2+ds/include/spdlog/async.h 2021-08-12 11:10:50.000000000 +0000 +++ spdlog-1.10.0+ds/include/spdlog/async.h 2022-04-04 13:48:58.000000000 +0000 @@ -35,7 +35,7 @@ struct async_factory_impl { template - static std::shared_ptr create(std::string logger_name, SinkArgs &&...args) + static std::shared_ptr create(std::string logger_name, SinkArgs &&... args) { auto ®istry_inst = details::registry::instance(); @@ -61,28 +61,34 @@ using async_factory_nonblock = async_factory_impl; template -inline std::shared_ptr create_async(std::string logger_name, SinkArgs &&...sink_args) +inline std::shared_ptr create_async(std::string logger_name, SinkArgs &&... sink_args) { return async_factory::create(std::move(logger_name), std::forward(sink_args)...); } template -inline std::shared_ptr create_async_nb(std::string logger_name, SinkArgs &&...sink_args) +inline std::shared_ptr create_async_nb(std::string logger_name, SinkArgs &&... sink_args) { return async_factory_nonblock::create(std::move(logger_name), std::forward(sink_args)...); } // set global thread pool. -inline void init_thread_pool(size_t q_size, size_t thread_count, std::function on_thread_start) +inline void init_thread_pool( + size_t q_size, size_t thread_count, std::function on_thread_start, std::function on_thread_stop) { - auto tp = std::make_shared(q_size, thread_count, on_thread_start); + auto tp = std::make_shared(q_size, thread_count, on_thread_start, on_thread_stop); details::registry::instance().set_tp(std::move(tp)); } -// set global thread pool. +inline void init_thread_pool(size_t q_size, size_t thread_count, std::function on_thread_start) +{ + init_thread_pool(q_size, thread_count, on_thread_start, [] {}); +} + inline void init_thread_pool(size_t q_size, size_t thread_count) { - init_thread_pool(q_size, thread_count, [] {}); + init_thread_pool( + q_size, thread_count, [] {}, [] {}); } // get the global thread pool. diff -Nru spdlog-1.9.2+ds/include/spdlog/async_logger-inl.h spdlog-1.10.0+ds/include/spdlog/async_logger-inl.h --- spdlog-1.9.2+ds/include/spdlog/async_logger-inl.h 2021-08-12 11:10:50.000000000 +0000 +++ spdlog-1.10.0+ds/include/spdlog/async_logger-inl.h 2022-04-04 13:48:58.000000000 +0000 @@ -62,7 +62,7 @@ { sink->log(msg); } - SPDLOG_LOGGER_CATCH() + SPDLOG_LOGGER_CATCH(msg.source) } } @@ -80,7 +80,7 @@ { sink->flush(); } - SPDLOG_LOGGER_CATCH() + SPDLOG_LOGGER_CATCH(source_loc()) } } diff -Nru spdlog-1.9.2+ds/include/spdlog/common.h spdlog-1.10.0+ds/include/spdlog/common.h --- spdlog-1.9.2+ds/include/spdlog/common.h 2021-08-12 11:10:50.000000000 +0000 +++ spdlog-1.10.0+ds/include/spdlog/common.h 2022-04-04 13:48:58.000000000 +0000 @@ -14,16 +14,25 @@ #include #include #include +#include + +#ifdef SPDLOG_USE_STD_FORMAT +# include +#endif #ifdef SPDLOG_COMPILED_LIB # undef SPDLOG_HEADER_ONLY -# if defined(_WIN32) && defined(SPDLOG_SHARED_LIB) -# ifdef spdlog_EXPORTS -# define SPDLOG_API __declspec(dllexport) -# else -# define SPDLOG_API __declspec(dllimport) +# if defined(SPDLOG_SHARED_LIB) +# if defined(_WIN32) +# ifdef spdlog_EXPORTS +# define SPDLOG_API __declspec(dllexport) +# else // !spdlog_EXPORTS +# define SPDLOG_API __declspec(dllimport) +# endif +# else // !defined(_WIN32) +# define SPDLOG_API __attribute__((visibility("default"))) # endif -# else // !defined(_WIN32) || !defined(SPDLOG_SHARED_LIB) +# else // !defined(SPDLOG_SHARED_LIB) # define SPDLOG_API # endif # define SPDLOG_INLINE @@ -35,23 +44,30 @@ #include -// backward compatibility with fmt versions older than 8 -#if FMT_VERSION >= 80000 -# define SPDLOG_FMT_RUNTIME(format_string) fmt::runtime(format_string) -# if defined(SPDLOG_WCHAR_FILENAMES) || defined(SPDLOG_WCHAR_TO_UTF8_SUPPORT) -# include +#ifndef SPDLOG_USE_STD_FORMAT +# if FMT_VERSION >= 80000 // backward compatibility with fmt versions older than 8 +# define SPDLOG_FMT_RUNTIME(format_string) fmt::runtime(format_string) +# if defined(SPDLOG_WCHAR_FILENAMES) || defined(SPDLOG_WCHAR_TO_UTF8_SUPPORT) +# include +# endif +# else +# define SPDLOG_FMT_RUNTIME(format_string) format_string # endif -#else -# define SPDLOG_FMT_RUNTIME(format_string) format_string #endif -// visual studio upto 2013 does not support noexcept nor constexpr +// visual studio up to 2013 does not support noexcept nor constexpr #if defined(_MSC_VER) && (_MSC_VER < 1900) # define SPDLOG_NOEXCEPT _NOEXCEPT # define SPDLOG_CONSTEXPR +# define SPDLOG_CONSTEXPR_FUNC #else # define SPDLOG_NOEXCEPT noexcept # define SPDLOG_CONSTEXPR constexpr +# if __cplusplus >= 201402L +# define SPDLOG_CONSTEXPR_FUNC constexpr +# else +# define SPDLOG_CONSTEXPR_FUNC +# endif #endif #if defined(__GNUC__) || defined(__clang__) @@ -111,10 +127,35 @@ using sink_ptr = std::shared_ptr; using sinks_init_list = std::initializer_list; using err_handler = std::function; +#ifdef SPDLOG_USE_STD_FORMAT +namespace fmt_lib = std; + +using string_view_t = std::string_view; +using memory_buf_t = std::string; + +template +using format_string_t = std::string_view; + +template +struct is_convertible_to_basic_format_string : std::integral_constant>::value> +{}; + +# if defined(SPDLOG_WCHAR_FILENAMES) || defined(SPDLOG_WCHAR_TO_UTF8_SUPPORT) +using wstring_view_t = std::wstring_view; +using wmemory_buf_t = std::wstring; + +template +using wformat_string_t = std::wstring_view; +# endif + +#else // use fmt lib instead of std::format +namespace fmt_lib = fmt; + using string_view_t = fmt::basic_string_view; -using wstring_view_t = fmt::basic_string_view; using memory_buf_t = fmt::basic_memory_buffer; -using wmemory_buf_t = fmt::basic_memory_buffer; + +template +using format_string_t = fmt::format_string; template using remove_cvref_t = typename std::remove_cv::type>::type; @@ -127,6 +168,15 @@ std::is_convertible>::value || std::is_same, fmt::basic_runtime>::value> {}; +# if defined(SPDLOG_WCHAR_FILENAMES) || defined(SPDLOG_WCHAR_TO_UTF8_SUPPORT) +using wstring_view_t = fmt::basic_string_view; +using wmemory_buf_t = fmt::basic_memory_buffer; + +template +using wformat_string_t = fmt::wformat_string; +# endif +#endif + #ifdef SPDLOG_WCHAR_TO_UTF8_SUPPORT # ifndef _WIN32 # error SPDLOG_WCHAR_TO_UTF8_SUPPORT only supported on windows @@ -158,7 +208,7 @@ // Log level enum namespace level { -enum level_enum +enum level_enum : int { trace = SPDLOG_LEVEL_TRACE, debug = SPDLOG_LEVEL_DEBUG, @@ -255,19 +305,52 @@ const char *funcname{nullptr}; }; +struct file_event_handlers +{ + std::function before_open; + std::function after_open; + std::function before_close; + std::function after_close; + file_event_handlers() + : before_open{nullptr} + , after_open{nullptr} + , before_close{nullptr} + , after_close{nullptr} + {} +}; + namespace details { + // make_unique support for pre c++14 #if __cplusplus >= 201402L // C++14 and beyond +using std::enable_if_t; using std::make_unique; #else +template +using enable_if_t = typename std::enable_if::type; + template -std::unique_ptr make_unique(Args &&...args) +std::unique_ptr make_unique(Args &&... args) { static_assert(!std::is_array::value, "arrays not supported"); return std::unique_ptr(new T(std::forward(args)...)); } #endif + +// to avoid useless casts (see https://github.com/nlohmann/json/issues/2893#issuecomment-889152324) +template::value, int> = 0> +constexpr T conditional_static_cast(U value) +{ + return static_cast(value); +} + +template::value, int> = 0> +constexpr T conditional_static_cast(U value) +{ + return value; +} + } // namespace details } // namespace spdlog diff -Nru spdlog-1.9.2+ds/include/spdlog/common-inl.h spdlog-1.10.0+ds/include/spdlog/common-inl.h --- spdlog-1.9.2+ds/include/spdlog/common-inl.h 2021-08-12 11:10:50.000000000 +0000 +++ spdlog-1.10.0+ds/include/spdlog/common-inl.h 2022-04-04 13:48:58.000000000 +0000 @@ -55,9 +55,13 @@ SPDLOG_INLINE spdlog_ex::spdlog_ex(const std::string &msg, int last_errno) { +#ifdef SPDLOG_USE_STD_FORMAT + msg_ = std::system_error(std::error_code(last_errno, std::generic_category()), msg).what(); +#else memory_buf_t outbuf; fmt::format_system_error(outbuf, last_errno, msg.c_str()); msg_ = fmt::to_string(outbuf); +#endif } SPDLOG_INLINE const char *spdlog_ex::what() const SPDLOG_NOEXCEPT diff -Nru spdlog-1.9.2+ds/include/spdlog/details/file_helper.h spdlog-1.10.0+ds/include/spdlog/details/file_helper.h --- spdlog-1.9.2+ds/include/spdlog/details/file_helper.h 2021-08-12 11:10:50.000000000 +0000 +++ spdlog-1.10.0+ds/include/spdlog/details/file_helper.h 2022-04-04 13:48:58.000000000 +0000 @@ -16,7 +16,8 @@ class SPDLOG_API file_helper { public: - explicit file_helper() = default; + file_helper() = default; + explicit file_helper(const file_event_handlers &event_handlers); file_helper(const file_helper &) = delete; file_helper &operator=(const file_helper &) = delete; @@ -50,6 +51,7 @@ const unsigned int open_interval_ = 10; std::FILE *fd_{nullptr}; filename_t filename_; + file_event_handlers event_handlers_; }; } // namespace details } // namespace spdlog diff -Nru spdlog-1.9.2+ds/include/spdlog/details/file_helper-inl.h spdlog-1.10.0+ds/include/spdlog/details/file_helper-inl.h --- spdlog-1.9.2+ds/include/spdlog/details/file_helper-inl.h 2021-08-12 11:10:50.000000000 +0000 +++ spdlog-1.10.0+ds/include/spdlog/details/file_helper-inl.h 2022-04-04 13:48:58.000000000 +0000 @@ -20,6 +20,10 @@ namespace spdlog { namespace details { +SPDLOG_INLINE file_helper::file_helper(const file_event_handlers &event_handlers) + : event_handlers_(event_handlers) +{} + SPDLOG_INLINE file_helper::~file_helper() { close(); @@ -33,6 +37,10 @@ auto *mode = SPDLOG_FILENAME_T("ab"); auto *trunc_mode = SPDLOG_FILENAME_T("wb"); + if (event_handlers_.before_open) + { + event_handlers_.before_open(filename_); + } for (int tries = 0; tries < open_tries_; ++tries) { // create containing folder if not exists already. @@ -52,6 +60,10 @@ } if (!os::fopen_s(&fd_, fname, mode)) { + if (event_handlers_.after_open) + { + event_handlers_.after_open(filename_, fd_); + } return; } @@ -72,15 +84,28 @@ SPDLOG_INLINE void file_helper::flush() { - std::fflush(fd_); + if (std::fflush(fd_) != 0) + { + throw_spdlog_ex("Failed flush to file " + os::filename_to_str(filename_), errno); + } } SPDLOG_INLINE void file_helper::close() { if (fd_ != nullptr) { + if (event_handlers_.before_close) + { + event_handlers_.before_close(filename_, fd_); + } + std::fclose(fd_); fd_ = nullptr; + + if (event_handlers_.after_close) + { + event_handlers_.after_close(filename_); + } } } diff -Nru spdlog-1.9.2+ds/include/spdlog/details/fmt_helper.h spdlog-1.10.0+ds/include/spdlog/details/fmt_helper.h --- spdlog-1.9.2+ds/include/spdlog/details/fmt_helper.h 2021-08-12 11:10:50.000000000 +0000 +++ spdlog-1.10.0+ds/include/spdlog/details/fmt_helper.h 2022-04-04 13:48:58.000000000 +0000 @@ -8,6 +8,11 @@ #include #include +#ifdef SPDLOG_USE_STD_FORMAT +# include +# include +#endif + // Some fmt helpers to efficiently format and pad ints and strings namespace spdlog { namespace details { @@ -24,26 +29,73 @@ dest.append(buf_ptr, buf_ptr + view.size()); } +#ifdef SPDLOG_USE_STD_FORMAT +template +inline void append_int(T n, memory_buf_t &dest) +{ + // Buffer should be large enough to hold all digits (digits10 + 1) and a sign + SPDLOG_CONSTEXPR const auto BUF_SIZE = std::numeric_limits::digits10 + 2; + char buf[BUF_SIZE]; + + auto [ptr, ec] = std::to_chars(buf, buf + BUF_SIZE, n, 10); + if (ec == std::errc()) + { + dest.append(buf, ptr); + } + else + { + throw_spdlog_ex("Failed to format int", static_cast(ec)); + } +} +#else template inline void append_int(T n, memory_buf_t &dest) { fmt::format_int i(n); dest.append(i.data(), i.data() + i.size()); } +#endif + +template +SPDLOG_CONSTEXPR_FUNC unsigned int count_digits_fallback(T n) +{ + // taken from fmt: https://github.com/fmtlib/fmt/blob/8.0.1/include/fmt/format.h#L899-L912 + unsigned int count = 1; + for (;;) + { + // Integer division is slow so do it for a group of four digits instead + // of for every digit. The idea comes from the talk by Alexandrescu + // "Three Optimization Tips for C++". See speed-test for a comparison. + if (n < 10) + return count; + if (n < 100) + return count + 1; + if (n < 1000) + return count + 2; + if (n < 10000) + return count + 3; + n /= 10000u; + count += 4; + } +} template inline unsigned int count_digits(T n) { using count_type = typename std::conditional<(sizeof(T) > sizeof(uint32_t)), uint64_t, uint32_t>::type; +#ifdef SPDLOG_USE_STD_FORMAT + return count_digits_fallback(static_cast(n)); +#else return static_cast(fmt:: // fmt 7.0.0 renamed the internal namespace to detail. // See: https://github.com/fmtlib/fmt/issues/1538 -#if FMT_VERSION < 70000 +# if FMT_VERSION < 70000 internal -#else +# else detail -#endif +# endif ::count_digits(static_cast(n))); +#endif } inline void pad2(int n, memory_buf_t &dest) @@ -55,7 +107,7 @@ } else // unlikely, but just in case, let fmt deal with it { - fmt::format_to(std::back_inserter(dest), SPDLOG_FMT_RUNTIME("{:02}"), n); + fmt_lib::format_to(std::back_inserter(dest), "{:02}", n); } } diff -Nru spdlog-1.9.2+ds/include/spdlog/details/mpmc_blocking_q.h spdlog-1.10.0+ds/include/spdlog/details/mpmc_blocking_q.h --- spdlog-1.9.2+ds/include/spdlog/details/mpmc_blocking_q.h 2021-08-12 11:10:50.000000000 +0000 +++ spdlog-1.10.0+ds/include/spdlog/details/mpmc_blocking_q.h 2022-04-04 13:48:58.000000000 +0000 @@ -49,7 +49,7 @@ push_cv_.notify_one(); } - // try to dequeue item. if no item found. wait upto timeout and try again + // try to dequeue item. if no item found. wait up to timeout and try again // Return true, if succeeded dequeue item, false otherwise bool dequeue_for(T &popped_item, std::chrono::milliseconds wait_duration) { @@ -87,7 +87,7 @@ push_cv_.notify_one(); } - // try to dequeue item. if no item found. wait upto timeout and try again + // try to dequeue item. if no item found. wait up to timeout and try again // Return true, if succeeded dequeue item, false otherwise bool dequeue_for(T &popped_item, std::chrono::milliseconds wait_duration) { diff -Nru spdlog-1.9.2+ds/include/spdlog/details/os.h spdlog-1.10.0+ds/include/spdlog/details/os.h --- spdlog-1.9.2+ds/include/spdlog/details/os.h 2021-08-12 11:10:50.000000000 +0000 +++ spdlog-1.10.0+ds/include/spdlog/details/os.h 2022-04-04 13:48:58.000000000 +0000 @@ -99,11 +99,11 @@ // "abc/" => "abc" // "abc" => "" // "abc///" => "abc//" -SPDLOG_API filename_t dir_name(filename_t path); +SPDLOG_API filename_t dir_name(const filename_t &path); // Create a dir from the given path. // Return true if succeeded or if this dir already exists. -SPDLOG_API bool create_dir(filename_t path); +SPDLOG_API bool create_dir(const filename_t &path); // non thread safe, cross platform getenv/getenv_s // return empty string if field not found diff -Nru spdlog-1.9.2+ds/include/spdlog/details/os-inl.h spdlog-1.10.0+ds/include/spdlog/details/os-inl.h --- spdlog-1.9.2+ds/include/spdlog/details/os-inl.h 2021-08-12 11:10:50.000000000 +0000 +++ spdlog-1.10.0+ds/include/spdlog/details/os-inl.h 2022-04-04 13:48:58.000000000 +0000 @@ -46,7 +46,7 @@ # include //Use gettid() syscall under linux to get thread id # elif defined(_AIX) -# include // for pthread_getthreadid_np +# include // for pthread_getthrds_np # elif defined(__DragonFly__) || defined(__FreeBSD__) # include // for pthread_getthreadid_np @@ -145,7 +145,7 @@ const int fd = ::open((filename.c_str()), O_CREAT | O_WRONLY | O_CLOEXEC | mode_flag, mode_t(0644)); if (fd == -1) { - return false; + return true; } *fp = ::fdopen(fd, mode.c_str()); if (*fp == nullptr) @@ -230,8 +230,8 @@ # endif #else // unix -// OpenBSD doesn't compile with :: before the fileno(..) -# if defined(__OpenBSD__) +// OpenBSD and AIX doesn't compile with :: before the fileno(..) +# if defined(__OpenBSD__) || defined(_AIX) int fd = fileno(f); # else int fd = ::fileno(f); @@ -305,7 +305,7 @@ ((local_year / 100 >> 2) - (gmt_year / 100 >> 2)) // + difference in years * 365 */ - + (long int)(local_year - gmt_year) * 365); + + static_cast(local_year - gmt_year) * 365); long int hours = (24 * days) + (localtm.tm_hour - gmtm.tm_hour); long int mins = (60 * hours) + (localtm.tm_min - gmtm.tm_min); @@ -336,7 +336,14 @@ # define SYS_gettid __NR_gettid # endif return static_cast(::syscall(SYS_gettid)); -#elif defined(_AIX) || defined(__DragonFly__) || defined(__FreeBSD__) +#elif defined(_AIX) + struct __pthrdsinfo buf; + int reg_size = 0; + pthread_t pt = pthread_self(); + int retval = pthread_getthrds_np(&pt, PTHRDSINFO_QUERY_TID, &buf, sizeof(buf), NULL, ®_size); + int tid = (!retval) ? buf.__pi_tid : 0; + return static_cast(tid); +#elif defined(__DragonFly__) || defined(__FreeBSD__) return static_cast(::pthread_getthreadid_np()); #elif defined(__NetBSD__) return static_cast(::_lwp_self()); @@ -381,7 +388,11 @@ { memory_buf_t buf; wstr_to_utf8buf(filename, buf); +# ifdef SPDLOG_USE_STD_FORMAT + return buf; +# else return fmt::to_string(buf); +# endif } #else SPDLOG_INLINE std::string filename_to_str(const filename_t &filename) @@ -394,9 +405,9 @@ { #ifdef _WIN32 - return static_cast(::GetCurrentProcessId()); + return conditional_static_cast(::GetCurrentProcessId()); #else - return static_cast(::getpid()); + return conditional_static_cast(::getpid()); #endif } @@ -476,7 +487,7 @@ } } - throw_spdlog_ex(fmt::format("WideCharToMultiByte failed. Last error: {}", ::GetLastError())); + throw_spdlog_ex(fmt_lib::format("WideCharToMultiByte failed. Last error: {}", ::GetLastError())); } SPDLOG_INLINE void utf8_to_wstrbuf(string_view_t str, wmemory_buf_t &target) @@ -511,7 +522,7 @@ } } - throw_spdlog_ex(fmt::format("MultiByteToWideChar failed. Last error: {}", ::GetLastError())); + throw_spdlog_ex(fmt_lib::format("MultiByteToWideChar failed. Last error: {}", ::GetLastError())); } #endif // (defined(SPDLOG_WCHAR_TO_UTF8_SUPPORT) || defined(SPDLOG_WCHAR_FILENAMES)) && defined(_WIN32) @@ -531,7 +542,7 @@ // create the given directory - and all directories leading to it // return true on success or if the directory already exists -SPDLOG_INLINE bool create_dir(filename_t path) +SPDLOG_INLINE bool create_dir(const filename_t &path) { if (path_exists(path)) { @@ -570,7 +581,7 @@ // "abc/" => "abc" // "abc" => "" // "abc///" => "abc//" -SPDLOG_INLINE filename_t dir_name(filename_t path) +SPDLOG_INLINE filename_t dir_name(const filename_t &path) { auto pos = path.find_last_of(folder_seps_filename); return pos != filename_t::npos ? path.substr(0, pos) : filename_t{}; diff -Nru spdlog-1.9.2+ds/include/spdlog/details/synchronous_factory.h spdlog-1.10.0+ds/include/spdlog/details/synchronous_factory.h --- spdlog-1.9.2+ds/include/spdlog/details/synchronous_factory.h 2021-08-12 11:10:50.000000000 +0000 +++ spdlog-1.10.0+ds/include/spdlog/details/synchronous_factory.h 2022-04-04 13:48:58.000000000 +0000 @@ -13,7 +13,7 @@ struct synchronous_factory { template - static std::shared_ptr create(std::string logger_name, SinkArgs &&...args) + static std::shared_ptr create(std::string logger_name, SinkArgs &&... args) { auto sink = std::make_shared(std::forward(args)...); auto new_logger = std::make_shared(std::move(logger_name), std::move(sink)); diff -Nru spdlog-1.9.2+ds/include/spdlog/details/tcp_client.h spdlog-1.10.0+ds/include/spdlog/details/tcp_client.h --- spdlog-1.9.2+ds/include/spdlog/details/tcp_client.h 2021-08-12 11:10:50.000000000 +0000 +++ spdlog-1.10.0+ds/include/spdlog/details/tcp_client.h 2022-04-04 13:48:58.000000000 +0000 @@ -67,8 +67,7 @@ auto rv = ::getaddrinfo(host.c_str(), port_str.c_str(), &hints, &addrinfo_result); if (rv != 0) { - auto msg = fmt::format("::getaddrinfo failed: {}", gai_strerror(rv)); - throw_spdlog_ex(msg); + throw_spdlog_ex(fmt_lib::format("::getaddrinfo failed: {}", gai_strerror(rv))); } // Try each address until we successfully connect(2). diff -Nru spdlog-1.9.2+ds/include/spdlog/details/tcp_client-windows.h spdlog-1.10.0+ds/include/spdlog/details/tcp_client-windows.h --- spdlog-1.9.2+ds/include/spdlog/details/tcp_client-windows.h 2021-08-12 11:10:50.000000000 +0000 +++ spdlog-1.10.0+ds/include/spdlog/details/tcp_client-windows.h 2022-04-04 13:48:58.000000000 +0000 @@ -25,20 +25,6 @@ { SOCKET socket_ = INVALID_SOCKET; - static bool winsock_initialized_() - { - SOCKET s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); - if (s == INVALID_SOCKET) - { - return false; - } - else - { - closesocket(s); - return true; - } - } - static void init_winsock_() { WSADATA wsaData; @@ -52,13 +38,24 @@ static void throw_winsock_error_(const std::string &msg, int last_error) { char buf[512]; - ::FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, last_error, + ::FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, last_error, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), buf, (sizeof(buf) / sizeof(char)), NULL); - throw_spdlog_ex(fmt::format("tcp_sink - {}: {}", msg, buf)); + throw_spdlog_ex(fmt_lib::format("tcp_sink - {}: {}", msg, buf)); } public: + tcp_client() + { + init_winsock_(); + } + + ~tcp_client() + { + close(); + ::WSACleanup(); + } + bool is_connected() const { return socket_ != INVALID_SOCKET; @@ -68,7 +65,6 @@ { ::closesocket(socket_); socket_ = INVALID_SOCKET; - WSACleanup(); } SOCKET fd() const @@ -76,20 +72,9 @@ return socket_; } - ~tcp_client() - { - close(); - } - // try to connect or throw on failure void connect(const std::string &host, int port) { - // initialize winsock if needed - if (!winsock_initialized_()) - { - init_winsock_(); - } - if (is_connected()) { close(); diff -Nru spdlog-1.9.2+ds/include/spdlog/details/thread_pool.h spdlog-1.10.0+ds/include/spdlog/details/thread_pool.h --- spdlog-1.9.2+ds/include/spdlog/details/thread_pool.h 2021-08-12 11:10:50.000000000 +0000 +++ spdlog-1.10.0+ds/include/spdlog/details/thread_pool.h 2022-04-04 13:48:58.000000000 +0000 @@ -84,10 +84,11 @@ using item_type = async_msg; using q_type = details::mpmc_blocking_queue; + thread_pool(size_t q_max_items, size_t threads_n, std::function on_thread_start, std::function on_thread_stop); thread_pool(size_t q_max_items, size_t threads_n, std::function on_thread_start); thread_pool(size_t q_max_items, size_t threads_n); - // message all threads to terminate gracefully join them + // message all threads to terminate gracefully and join them ~thread_pool(); thread_pool(const thread_pool &) = delete; diff -Nru spdlog-1.9.2+ds/include/spdlog/details/thread_pool-inl.h spdlog-1.10.0+ds/include/spdlog/details/thread_pool-inl.h --- spdlog-1.9.2+ds/include/spdlog/details/thread_pool-inl.h 2021-08-12 11:10:50.000000000 +0000 +++ spdlog-1.10.0+ds/include/spdlog/details/thread_pool-inl.h 2022-04-04 13:48:58.000000000 +0000 @@ -13,7 +13,8 @@ namespace spdlog { namespace details { -SPDLOG_INLINE thread_pool::thread_pool(size_t q_max_items, size_t threads_n, std::function on_thread_start) +SPDLOG_INLINE thread_pool::thread_pool( + size_t q_max_items, size_t threads_n, std::function on_thread_start, std::function on_thread_stop) : q_(q_max_items) { if (threads_n == 0 || threads_n > 1000) @@ -23,15 +24,21 @@ } for (size_t i = 0; i < threads_n; i++) { - threads_.emplace_back([this, on_thread_start] { + threads_.emplace_back([this, on_thread_start, on_thread_stop] { on_thread_start(); this->thread_pool::worker_loop_(); + on_thread_stop(); }); } } +SPDLOG_INLINE thread_pool::thread_pool(size_t q_max_items, size_t threads_n, std::function on_thread_start) + : thread_pool(q_max_items, threads_n, on_thread_start, [] {}) +{} + SPDLOG_INLINE thread_pool::thread_pool(size_t q_max_items, size_t threads_n) - : thread_pool(q_max_items, threads_n, [] {}) + : thread_pool( + q_max_items, threads_n, [] {}, [] {}) {} // message all threads to terminate gracefully join them diff -Nru spdlog-1.9.2+ds/include/spdlog/details/udp_client.h spdlog-1.10.0+ds/include/spdlog/details/udp_client.h --- spdlog-1.9.2+ds/include/spdlog/details/udp_client.h 1970-01-01 00:00:00.000000000 +0000 +++ spdlog-1.10.0+ds/include/spdlog/details/udp_client.h 2022-04-04 13:48:58.000000000 +0000 @@ -0,0 +1,94 @@ +// Copyright(c) 2015-present, Gabi Melman & spdlog contributors. +// Distributed under the MIT License (http://opensource.org/licenses/MIT) + +#pragma once + +// Helper RAII over unix udp client socket. +// Will throw on construction if the socket creation failed. + +#ifdef _WIN32 +# error "include udp_client-windows.h instead" +#endif + +#include +#include + +#include +#include +#include +#include +#include +#include + +#include + +namespace spdlog { +namespace details { + +class udp_client +{ + static constexpr int TX_BUFFER_SIZE = 1024 * 10; + int socket_ = -1; + struct sockaddr_in sockAddr_; + + void cleanup_() + { + if (socket_ != -1) + { + ::close(socket_); + socket_ = -1; + } + } + +public: + udp_client(const std::string &host, uint16_t port) + { + socket_ = ::socket(PF_INET, SOCK_DGRAM, 0); + if (socket_ < 0) + { + throw_spdlog_ex("error: Create Socket Failed!"); + } + + int option_value = TX_BUFFER_SIZE; + if (::setsockopt(socket_, SOL_SOCKET, SO_SNDBUF, reinterpret_cast(&option_value), sizeof(option_value)) < 0) + { + cleanup_(); + throw_spdlog_ex("error: setsockopt(SO_SNDBUF) Failed!"); + } + + sockAddr_.sin_family = AF_INET; + sockAddr_.sin_port = htons(port); + + if (::inet_aton(host.c_str(), &sockAddr_.sin_addr) == 0) + { + cleanup_(); + throw_spdlog_ex("error: Invalid address!"); + } + + ::memset(sockAddr_.sin_zero, 0x00, sizeof(sockAddr_.sin_zero)); + } + + ~udp_client() + { + cleanup_(); + } + + int fd() const + { + return socket_; + } + + // Send exactly n_bytes of the given data. + // On error close the connection and throw. + void send(const char *data, size_t n_bytes) + { + ssize_t toslen = 0; + socklen_t tolen = sizeof(struct sockaddr); + if ((toslen = ::sendto(socket_, data, n_bytes, 0, (struct sockaddr *)&sockAddr_, tolen)) == -1) + { + throw_spdlog_ex("sendto(2) failed", errno); + } + } +}; +} // namespace details +} // namespace spdlog diff -Nru spdlog-1.9.2+ds/include/spdlog/details/udp_client-windows.h spdlog-1.10.0+ds/include/spdlog/details/udp_client-windows.h --- spdlog-1.9.2+ds/include/spdlog/details/udp_client-windows.h 1970-01-01 00:00:00.000000000 +0000 +++ spdlog-1.10.0+ds/include/spdlog/details/udp_client-windows.h 2022-04-04 13:48:58.000000000 +0000 @@ -0,0 +1,111 @@ +// Copyright(c) 2015-present, Gabi Melman & spdlog contributors. +// Distributed under the MIT License (http://opensource.org/licenses/MIT) + +#pragma once + +// Helper RAII over winsock udp client socket. +// Will throw on construction if socket creation failed. + +#include +#include +#include +#include +#include +#include +#include +#include + +#pragma comment(lib, "Ws2_32.lib") +#pragma comment(lib, "Mswsock.lib") +#pragma comment(lib, "AdvApi32.lib") + +namespace spdlog { +namespace details { +class udp_client +{ + static constexpr int TX_BUFFER_SIZE = 1024 * 10; + SOCKET socket_ = INVALID_SOCKET; + sockaddr_in addr_ = {0}; + + static void init_winsock_() + { + WSADATA wsaData; + auto rv = ::WSAStartup(MAKEWORD(2, 2), &wsaData); + if (rv != 0) + { + throw_winsock_error_("WSAStartup failed", ::WSAGetLastError()); + } + } + + static void throw_winsock_error_(const std::string &msg, int last_error) + { + char buf[512]; + ::FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, last_error, + MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), buf, (sizeof(buf) / sizeof(char)), NULL); + + throw_spdlog_ex(fmt_lib::format("udp_sink - {}: {}", msg, buf)); + } + + void cleanup_() + { + if (socket_ != INVALID_SOCKET) + { + ::closesocket(socket_); + } + socket_ = INVALID_SOCKET; + ::WSACleanup(); + } + +public: + udp_client(const std::string &host, uint16_t port) + { + init_winsock_(); + + addr_.sin_family = PF_INET; + addr_.sin_port = htons(port); + addr_.sin_addr.s_addr = INADDR_ANY; + if (InetPtonA(PF_INET, host.c_str(), &addr_.sin_addr.s_addr) != 1) + { + int last_error = ::WSAGetLastError(); + ::WSACleanup(); + throw_winsock_error_("error: Invalid address!", last_error); + } + + socket_ = ::socket(PF_INET, SOCK_DGRAM, 0); + if (socket_ == INVALID_SOCKET) + { + int last_error = ::WSAGetLastError(); + ::WSACleanup(); + throw_winsock_error_("error: Create Socket failed", last_error); + } + + int option_value = TX_BUFFER_SIZE; + if (::setsockopt(socket_, SOL_SOCKET, SO_SNDBUF, reinterpret_cast(&option_value), sizeof(option_value)) < 0) + { + int last_error = ::WSAGetLastError(); + cleanup_(); + throw_winsock_error_("error: setsockopt(SO_SNDBUF) Failed!", last_error); + } + } + + ~udp_client() + { + cleanup_(); + } + + SOCKET fd() const + { + return socket_; + } + + void send(const char *data, size_t n_bytes) + { + socklen_t tolen = sizeof(struct sockaddr); + if (::sendto(socket_, data, static_cast(n_bytes), 0, (struct sockaddr *)&addr_, tolen) == -1) + { + throw_spdlog_ex("sendto(2) failed", errno); + } + } +}; +} // namespace details +} // namespace spdlog diff -Nru spdlog-1.9.2+ds/include/spdlog/fmt/bin_to_hex.h spdlog-1.10.0+ds/include/spdlog/fmt/bin_to_hex.h --- spdlog-1.9.2+ds/include/spdlog/fmt/bin_to_hex.h 2021-08-12 11:10:50.000000000 +0000 +++ spdlog-1.10.0+ds/include/spdlog/fmt/bin_to_hex.h 2022-04-04 13:48:58.000000000 +0000 @@ -8,9 +8,17 @@ #include #include +#if defined(__has_include) && __has_include() +# include +#endif + +#if __cpp_lib_span >= 202002L +# include +#endif + // // Support for logging binary data as hex -// format flags, any combination of the followng: +// format flags, any combination of the following: // {:X} - print in uppercase. // {:s} - don't separate each byte with space. // {:p} - don't print the position on each line start. @@ -39,11 +47,12 @@ , size_per_line_(size_per_line) {} - It begin() const + // do not use begin() and end() to avoid collision with fmt/ranges + It get_begin() const { return begin_; } - It end() const + It get_end() const { return end_; } @@ -67,6 +76,20 @@ return details::dump_info(std::begin(container), std::end(container), size_per_line); } +#if __cpp_lib_span >= 202002L + +template +inline details::dump_info::iterator> to_hex( + const std::span &container, size_t size_per_line = 32) +{ + using Container = std::span; + static_assert(sizeof(typename Container::value_type) == 1, "sizeof(Container::value_type) != 1"); + using Iter = typename Container::iterator; + return details::dump_info(std::begin(container), std::end(container), size_per_line); +} + +#endif + // create dump_info from ranges template inline details::dump_info to_hex(const It range_begin, const It range_end, size_t size_per_line = 32) @@ -76,10 +99,16 @@ } // namespace spdlog -namespace fmt { +namespace +#ifdef SPDLOG_USE_STD_FORMAT + std +#else + fmt +#endif +{ template -struct formatter> +struct formatter, char> { const char delimiter = ' '; bool put_newlines = true; @@ -90,7 +119,7 @@ // parse the format string flags template - FMT_CONSTEXPR auto parse(ParseContext &ctx) -> decltype(ctx.begin()) + SPDLOG_CONSTEXPR_FUNC auto parse(ParseContext &ctx) -> decltype(ctx.begin()) { auto it = ctx.begin(); while (it != ctx.end() && *it != '}') @@ -131,21 +160,21 @@ SPDLOG_CONSTEXPR const char *hex_lower = "0123456789abcdef"; const char *hex_chars = use_uppercase ? hex_upper : hex_lower; -#if FMT_VERSION < 60000 +#if !defined(SPDLOG_USE_STD_FORMAT) && FMT_VERSION < 60000 auto inserter = ctx.begin(); #else auto inserter = ctx.out(); #endif int size_per_line = static_cast(the_range.size_per_line()); - auto start_of_line = the_range.begin(); - for (auto i = the_range.begin(); i != the_range.end(); i++) + auto start_of_line = the_range.get_begin(); + for (auto i = the_range.get_begin(); i != the_range.get_end(); i++) { auto ch = static_cast(*i); - if (put_newlines && (i == the_range.begin() || i - start_of_line >= size_per_line)) + if (put_newlines && (i == the_range.get_begin() || i - start_of_line >= size_per_line)) { - if (show_ascii && i != the_range.begin()) + if (show_ascii && i != the_range.get_begin()) { *inserter++ = delimiter; *inserter++ = delimiter; @@ -156,7 +185,7 @@ } } - put_newline(inserter, static_cast(i - the_range.begin())); + put_newline(inserter, static_cast(i - the_range.get_begin())); // put first byte without delimiter in front of it *inserter++ = hex_chars[(ch >> 4) & 0x0f]; @@ -175,9 +204,9 @@ } if (show_ascii) // add ascii to last line { - if (the_range.end() - the_range.begin() > size_per_line) + if (the_range.get_end() - the_range.get_begin() > size_per_line) { - auto blank_num = size_per_line - (the_range.end() - start_of_line); + auto blank_num = size_per_line - (the_range.get_end() - start_of_line); while (blank_num-- > 0) { *inserter++ = delimiter; @@ -190,7 +219,7 @@ } *inserter++ = delimiter; *inserter++ = delimiter; - for (auto j = start_of_line; j != the_range.end(); j++) + for (auto j = start_of_line; j != the_range.get_end(); j++) { auto pc = static_cast(*j); *inserter++ = std::isprint(pc) ? static_cast(*j) : '.'; @@ -210,8 +239,8 @@ if (put_positions) { - fmt::format_to(inserter, "{:04X}: ", pos); + spdlog::fmt_lib::format_to(inserter, "{:04X}: ", pos); } } }; -} // namespace fmt +} // namespace std diff -Nru spdlog-1.9.2+ds/include/spdlog/fmt/chrono.h spdlog-1.10.0+ds/include/spdlog/fmt/chrono.h --- spdlog-1.9.2+ds/include/spdlog/fmt/chrono.h 2021-08-12 11:10:50.000000000 +0000 +++ spdlog-1.10.0+ds/include/spdlog/fmt/chrono.h 2022-04-04 13:48:58.000000000 +0000 @@ -8,13 +8,15 @@ // include bundled or external copy of fmtlib's chrono support // -#if !defined(SPDLOG_FMT_EXTERNAL) -# ifdef SPDLOG_HEADER_ONLY -# ifndef FMT_HEADER_ONLY -# define FMT_HEADER_ONLY +#if !defined(SPDLOG_USE_STD_FORMAT) +# if !defined(SPDLOG_FMT_EXTERNAL) +# ifdef SPDLOG_HEADER_ONLY +# ifndef FMT_HEADER_ONLY +# define FMT_HEADER_ONLY +# endif # endif +# include +# else +# include # endif -# include -#else -# include #endif diff -Nru spdlog-1.9.2+ds/include/spdlog/fmt/compile.h spdlog-1.10.0+ds/include/spdlog/fmt/compile.h --- spdlog-1.9.2+ds/include/spdlog/fmt/compile.h 2021-08-12 11:10:50.000000000 +0000 +++ spdlog-1.10.0+ds/include/spdlog/fmt/compile.h 2022-04-04 13:48:58.000000000 +0000 @@ -5,16 +5,18 @@ #pragma once // -// include bundled or external copy of fmtlib's ostream support +// include bundled or external copy of fmtlib's compile-time support // -#if !defined(SPDLOG_FMT_EXTERNAL) -# ifdef SPDLOG_HEADER_ONLY -# ifndef FMT_HEADER_ONLY -# define FMT_HEADER_ONLY +#if !defined(SPDLOG_USE_STD_FORMAT) +# if !defined(SPDLOG_FMT_EXTERNAL) +# ifdef SPDLOG_HEADER_ONLY +# ifndef FMT_HEADER_ONLY +# define FMT_HEADER_ONLY +# endif # endif +# include +# else +# include # endif -# include -#else -# include #endif diff -Nru spdlog-1.9.2+ds/include/spdlog/fmt/fmt.h spdlog-1.10.0+ds/include/spdlog/fmt/fmt.h --- spdlog-1.9.2+ds/include/spdlog/fmt/fmt.h 2021-08-12 11:10:50.000000000 +0000 +++ spdlog-1.10.0+ds/include/spdlog/fmt/fmt.h 2022-04-04 13:48:58.000000000 +0000 @@ -10,7 +10,9 @@ // By default spdlog include its own copy. // -#if !defined(SPDLOG_FMT_EXTERNAL) +#if defined(SPDLOG_USE_STD_FORMAT) // SPDLOG_USE_STD_FORMAT is defined - use std::format +# include +#elif !defined(SPDLOG_FMT_EXTERNAL) # if !defined(SPDLOG_COMPILED_LIB) && !defined(FMT_HEADER_ONLY) # define FMT_HEADER_ONLY # endif diff -Nru spdlog-1.9.2+ds/include/spdlog/fmt/ostr.h spdlog-1.10.0+ds/include/spdlog/fmt/ostr.h --- spdlog-1.9.2+ds/include/spdlog/fmt/ostr.h 2021-08-12 11:10:50.000000000 +0000 +++ spdlog-1.10.0+ds/include/spdlog/fmt/ostr.h 2022-04-04 13:48:58.000000000 +0000 @@ -8,13 +8,15 @@ // include bundled or external copy of fmtlib's ostream support // -#if !defined(SPDLOG_FMT_EXTERNAL) -# ifdef SPDLOG_HEADER_ONLY -# ifndef FMT_HEADER_ONLY -# define FMT_HEADER_ONLY +#if !defined(SPDLOG_USE_STD_FORMAT) +# if !defined(SPDLOG_FMT_EXTERNAL) +# ifdef SPDLOG_HEADER_ONLY +# ifndef FMT_HEADER_ONLY +# define FMT_HEADER_ONLY +# endif # endif +# include +# else +# include # endif -# include -#else -# include #endif diff -Nru spdlog-1.9.2+ds/include/spdlog/fmt/ranges.h spdlog-1.10.0+ds/include/spdlog/fmt/ranges.h --- spdlog-1.9.2+ds/include/spdlog/fmt/ranges.h 1970-01-01 00:00:00.000000000 +0000 +++ spdlog-1.10.0+ds/include/spdlog/fmt/ranges.h 2022-04-04 13:48:58.000000000 +0000 @@ -0,0 +1,22 @@ +// +// Copyright(c) 2016 Gabi Melman. +// Distributed under the MIT License (http://opensource.org/licenses/MIT) +// + +#pragma once +// +// include bundled or external copy of fmtlib's ranges support +// + +#if !defined(SPDLOG_USE_STD_FORMAT) +# if !defined(SPDLOG_FMT_EXTERNAL) +# ifdef SPDLOG_HEADER_ONLY +# ifndef FMT_HEADER_ONLY +# define FMT_HEADER_ONLY +# endif +# endif +# include +# else +# include +# endif +#endif diff -Nru spdlog-1.9.2+ds/include/spdlog/fmt/xchar.h spdlog-1.10.0+ds/include/spdlog/fmt/xchar.h --- spdlog-1.9.2+ds/include/spdlog/fmt/xchar.h 2021-08-12 11:10:50.000000000 +0000 +++ spdlog-1.10.0+ds/include/spdlog/fmt/xchar.h 2022-04-04 13:48:58.000000000 +0000 @@ -5,16 +5,18 @@ #pragma once // -// include bundled or external copy of fmtlib's ostream support +// include bundled or external copy of fmtlib's xchar support // -#if !defined(SPDLOG_FMT_EXTERNAL) -# ifdef SPDLOG_HEADER_ONLY -# ifndef FMT_HEADER_ONLY -# define FMT_HEADER_ONLY +#if !defined(SPDLOG_USE_STD_FORMAT) +# if !defined(SPDLOG_FMT_EXTERNAL) +# ifdef SPDLOG_HEADER_ONLY +# ifndef FMT_HEADER_ONLY +# define FMT_HEADER_ONLY +# endif # endif +# include +# else +# include # endif -# include -#else -# include #endif diff -Nru spdlog-1.9.2+ds/include/spdlog/fwd.h spdlog-1.10.0+ds/include/spdlog/fwd.h --- spdlog-1.9.2+ds/include/spdlog/fwd.h 2021-08-12 11:10:50.000000000 +0000 +++ spdlog-1.10.0+ds/include/spdlog/fwd.h 2022-04-04 13:48:58.000000000 +0000 @@ -11,4 +11,8 @@ class sink; } +namespace level { +enum level_enum : int; +} + } // namespace spdlog diff -Nru spdlog-1.9.2+ds/include/spdlog/logger.h spdlog-1.10.0+ds/include/spdlog/logger.h --- spdlog-1.9.2+ds/include/spdlog/logger.h 2021-08-12 11:10:50.000000000 +0000 +++ spdlog-1.10.0+ds/include/spdlog/logger.h 2022-04-04 13:48:58.000000000 +0000 @@ -28,10 +28,17 @@ #include #ifndef SPDLOG_NO_EXCEPTIONS -# define SPDLOG_LOGGER_CATCH() \ +# define SPDLOG_LOGGER_CATCH(location) \ catch (const std::exception &ex) \ { \ - err_handler_(ex.what()); \ + if (location.filename) \ + { \ + err_handler_(fmt_lib::format("{} [{}({})]", ex.what(), location.filename, location.line)); \ + } \ + else \ + { \ + err_handler_(ex.what()); \ + } \ } \ catch (...) \ { \ @@ -39,7 +46,7 @@ throw; \ } #else -# define SPDLOG_LOGGER_CATCH() +# define SPDLOG_LOGGER_CATCH(location) #endif namespace spdlog { @@ -78,13 +85,13 @@ void swap(spdlog::logger &other) SPDLOG_NOEXCEPT; template - void log(source_loc loc, level::level_enum lvl, fmt::format_string fmt, Args &&...args) + void log(source_loc loc, level::level_enum lvl, format_string_t fmt, Args &&... args) { log_(loc, lvl, fmt, std::forward(args)...); } template - void log(level::level_enum lvl, fmt::format_string fmt, Args &&...args) + void log(level::level_enum lvl, format_string_t fmt, Args &&... args) { log(source_loc{}, lvl, fmt, std::forward(args)...); } @@ -95,14 +102,7 @@ log(source_loc{}, lvl, msg); } - // T can be statically converted to string_view - template::value, int>::type = 0> - void log(source_loc loc, level::level_enum lvl, const T &msg) - { - log(loc, lvl, string_view_t{msg}); - } - - // T cannot be statically converted to format string (including string_view) + // T cannot be statically converted to format string (including string_view/wstring_view) template::value, int>::type = 0> void log(source_loc loc, level::level_enum lvl, const T &msg) { @@ -141,86 +141,121 @@ } template - void trace(fmt::format_string fmt, Args &&...args) + void trace(format_string_t fmt, Args &&... args) { log(level::trace, fmt, std::forward(args)...); } template - void debug(fmt::format_string fmt, Args &&...args) + void debug(format_string_t fmt, Args &&... args) { log(level::debug, fmt, std::forward(args)...); } template - void info(fmt::format_string fmt, Args &&...args) + void info(format_string_t fmt, Args &&... args) { log(level::info, fmt, std::forward(args)...); } template - void warn(fmt::format_string fmt, Args &&...args) + void warn(format_string_t fmt, Args &&... args) { log(level::warn, fmt, std::forward(args)...); } template - void error(fmt::format_string fmt, Args &&...args) + void error(format_string_t fmt, Args &&... args) { log(level::err, fmt, std::forward(args)...); } template - void critical(fmt::format_string fmt, Args &&...args) + void critical(format_string_t fmt, Args &&... args) { log(level::critical, fmt, std::forward(args)...); } #ifdef SPDLOG_WCHAR_TO_UTF8_SUPPORT template - void log(level::level_enum lvl, fmt::wformat_string fmt, Args &&...args) + void log(source_loc loc, level::level_enum lvl, wformat_string_t fmt, Args &&... args) { - log(source_loc{}, lvl, fmt, std::forward(args)...); + log_(loc, lvl, fmt, std::forward(args)...); } template - void log(source_loc loc, level::level_enum lvl, fmt::wformat_string fmt, Args &&...args) + void log(level::level_enum lvl, wformat_string_t fmt, Args &&... args) { - log_(loc, lvl, fmt, std::forward(args)...); + log(source_loc{}, lvl, fmt, std::forward(args)...); + } + + void log(log_clock::time_point log_time, source_loc loc, level::level_enum lvl, wstring_view_t msg) + { + bool log_enabled = should_log(lvl); + bool traceback_enabled = tracer_.enabled(); + if (!log_enabled && !traceback_enabled) + { + return; + } + + memory_buf_t buf; + details::os::wstr_to_utf8buf(wstring_view_t(msg.data(), msg.size()), buf); + details::log_msg log_msg(log_time, loc, name_, lvl, string_view_t(buf.data(), buf.size())); + log_it_(log_msg, log_enabled, traceback_enabled); + } + + void log(source_loc loc, level::level_enum lvl, wstring_view_t msg) + { + bool log_enabled = should_log(lvl); + bool traceback_enabled = tracer_.enabled(); + if (!log_enabled && !traceback_enabled) + { + return; + } + + memory_buf_t buf; + details::os::wstr_to_utf8buf(wstring_view_t(msg.data(), msg.size()), buf); + details::log_msg log_msg(loc, name_, lvl, string_view_t(buf.data(), buf.size())); + log_it_(log_msg, log_enabled, traceback_enabled); + } + + void log(level::level_enum lvl, wstring_view_t msg) + { + log(source_loc{}, lvl, msg); } template - void trace(fmt::wformat_string fmt, Args &&...args) + void trace(wformat_string_t fmt, Args &&... args) { log(level::trace, fmt, std::forward(args)...); } template - void debug(fmt::wformat_string fmt, Args &&...args) + void debug(wformat_string_t fmt, Args &&... args) { log(level::debug, fmt, std::forward(args)...); } template - void info(fmt::wformat_string fmt, Args &&...args) + void info(wformat_string_t fmt, Args &&... args) { log(level::info, fmt, std::forward(args)...); } template - void warn(fmt::wformat_string fmt, Args &&...args) + void warn(wformat_string_t fmt, Args &&... args) { log(level::warn, fmt, std::forward(args)...); } template - void error(fmt::wformat_string fmt, Args &&...args) + void error(wformat_string_t fmt, Args &&... args) { log(level::err, fmt, std::forward(args)...); } template - void critical(fmt::wformat_string fmt, Args &&...args) + void critical(wformat_string_t fmt, Args &&... args) { log(level::critical, fmt, std::forward(args)...); } @@ -318,7 +353,7 @@ // common implementation for after templated public api has been resolved template - void log_(source_loc loc, level::level_enum lvl, string_view_t fmt, Args &&...args) + void log_(source_loc loc, level::level_enum lvl, string_view_t fmt, Args &&... args) { bool log_enabled = should_log(lvl); bool traceback_enabled = tracer_.enabled(); @@ -328,17 +363,21 @@ } SPDLOG_TRY { +#ifdef SPDLOG_USE_STD_FORMAT + memory_buf_t buf = std::vformat(fmt, std::make_format_args(std::forward(args)...)); +#else memory_buf_t buf; - fmt::detail::vformat_to(buf, fmt, fmt::make_format_args(args...)); + fmt::detail::vformat_to(buf, fmt, fmt::make_format_args(std::forward(args)...)); +#endif details::log_msg log_msg(loc, name_, lvl, string_view_t(buf.data(), buf.size())); log_it_(log_msg, log_enabled, traceback_enabled); } - SPDLOG_LOGGER_CATCH() + SPDLOG_LOGGER_CATCH(loc) } #ifdef SPDLOG_WCHAR_TO_UTF8_SUPPORT template - void log_(source_loc loc, level::level_enum lvl, wstring_view_t fmt, Args &&...args) + void log_(source_loc loc, level::level_enum lvl, wstring_view_t fmt, Args &&... args) { bool log_enabled = should_log(lvl); bool traceback_enabled = tracer_.enabled(); @@ -349,14 +388,19 @@ SPDLOG_TRY { // format to wmemory_buffer and convert to utf8 - fmt::wmemory_buffer wbuf; - fmt::detail::vformat_to(wbuf, fmt, fmt::make_format_args(args...)); + ; +# ifdef SPDLOG_USE_STD_FORMAT + wmemory_buf_t wbuf = std::vformat(fmt, std::make_wformat_args(std::forward(args)...)); +# else + wmemory_buf_t wbuf; + fmt::detail::vformat_to(wbuf, fmt, fmt::make_format_args(std::forward(args)...)); +# endif memory_buf_t buf; details::os::wstr_to_utf8buf(wstring_view_t(wbuf.data(), wbuf.size()), buf); details::log_msg log_msg(loc, name_, lvl, string_view_t(buf.data(), buf.size())); log_it_(log_msg, log_enabled, traceback_enabled); } - SPDLOG_LOGGER_CATCH() + SPDLOG_LOGGER_CATCH(loc) } // T can be statically converted to wstring_view, and no formatting needed. @@ -376,7 +420,7 @@ details::log_msg log_msg(loc, name_, lvl, string_view_t(buf.data(), buf.size())); log_it_(log_msg, log_enabled, traceback_enabled); } - SPDLOG_LOGGER_CATCH() + SPDLOG_LOGGER_CATCH(loc) } #endif // SPDLOG_WCHAR_TO_UTF8_SUPPORT diff -Nru spdlog-1.9.2+ds/include/spdlog/logger-inl.h spdlog-1.10.0+ds/include/spdlog/logger-inl.h --- spdlog-1.9.2+ds/include/spdlog/logger-inl.h 2021-08-12 11:10:50.000000000 +0000 +++ spdlog-1.10.0+ds/include/spdlog/logger-inl.h 2022-04-04 13:48:58.000000000 +0000 @@ -185,7 +185,7 @@ { sink->log(msg); } - SPDLOG_LOGGER_CATCH() + SPDLOG_LOGGER_CATCH(msg.source) } } @@ -203,7 +203,7 @@ { sink->flush(); } - SPDLOG_LOGGER_CATCH() + SPDLOG_LOGGER_CATCH(source_loc()) } } diff -Nru spdlog-1.9.2+ds/include/spdlog/pattern_formatter.h spdlog-1.10.0+ds/include/spdlog/pattern_formatter.h --- spdlog-1.9.2+ds/include/spdlog/pattern_formatter.h 2021-08-12 11:10:50.000000000 +0000 +++ spdlog-1.10.0+ds/include/spdlog/pattern_formatter.h 2022-04-04 13:48:58.000000000 +0000 @@ -68,7 +68,7 @@ public: virtual std::unique_ptr clone() const = 0; - void set_padding_info(details::padding_info padding) + void set_padding_info(const details::padding_info &padding) { flag_formatter::padinfo_ = padding; } @@ -92,7 +92,7 @@ void format(const details::log_msg &msg, memory_buf_t &dest) override; template - pattern_formatter &add_flag(char flag, Args &&...args) + pattern_formatter &add_flag(char flag, Args &&... args) { custom_handlers_[flag] = details::make_unique(std::forward(args)...); return *this; @@ -103,6 +103,7 @@ std::string pattern_; std::string eol_; pattern_time_type pattern_time_type_; + bool need_localtime_; std::tm cached_tm_; std::chrono::seconds last_log_secs_; std::vector> formatters_; diff -Nru spdlog-1.9.2+ds/include/spdlog/pattern_formatter-inl.h spdlog-1.10.0+ds/include/spdlog/pattern_formatter-inl.h --- spdlog-1.9.2+ds/include/spdlog/pattern_formatter-inl.h 2021-08-12 11:10:50.000000000 +0000 +++ spdlog-1.10.0+ds/include/spdlog/pattern_formatter-inl.h 2022-04-04 13:48:58.000000000 +0000 @@ -766,6 +766,7 @@ { if (msg.source.empty()) { + ScopedPadder p(0, padinfo_, dest); return; } @@ -800,6 +801,7 @@ { if (msg.source.empty()) { + ScopedPadder p(0, padinfo_, dest); return; } size_t text_size = padinfo_.enabled() ? std::char_traits::length(msg.source.filename) : 0; @@ -846,6 +848,7 @@ { if (msg.source.empty()) { + ScopedPadder p(0, padinfo_, dest); return; } auto filename = basename(msg.source.filename); @@ -867,6 +870,7 @@ { if (msg.source.empty()) { + ScopedPadder p(0, padinfo_, dest); return; } @@ -889,6 +893,7 @@ { if (msg.source.empty()) { + ScopedPadder p(0, padinfo_, dest); return; } size_t text_size = padinfo_.enabled() ? std::char_traits::length(msg.source.funcname) : 0; @@ -1019,6 +1024,7 @@ : pattern_(std::move(pattern)) , eol_(std::move(eol)) , pattern_time_type_(time_type) + , need_localtime_(false) , last_log_secs_(0) , custom_handlers_(std::move(custom_user_flags)) { @@ -1031,6 +1037,7 @@ : pattern_("%+") , eol_(std::move(eol)) , pattern_time_type_(time_type) + , need_localtime_(true) , last_log_secs_(0) { std::memset(&cached_tm_, 0, sizeof(cached_tm_)); @@ -1049,11 +1056,14 @@ SPDLOG_INLINE void pattern_formatter::format(const details::log_msg &msg, memory_buf_t &dest) { - auto secs = std::chrono::duration_cast(msg.time.time_since_epoch()); - if (secs != last_log_secs_) + if (need_localtime_) { - cached_tm_ = get_time_(msg); - last_log_secs_ = secs; + const auto secs = std::chrono::duration_cast(msg.time.time_since_epoch()); + if (secs != last_log_secs_) + { + cached_tm_ = get_time_(msg); + last_log_secs_ = secs; + } } for (auto &f : formatters_) @@ -1067,6 +1077,7 @@ SPDLOG_INLINE void pattern_formatter::set_pattern(std::string pattern) { pattern_ = std::move(pattern); + need_localtime_ = false; compile_pattern_(pattern_); } @@ -1097,6 +1108,7 @@ { case ('+'): // default formatter formatters_.push_back(details::make_unique(padding)); + need_localtime_ = true; break; case 'n': // logger name @@ -1121,60 +1133,74 @@ case ('a'): // weekday formatters_.push_back(details::make_unique>(padding)); + need_localtime_ = true; break; case ('A'): // short weekday formatters_.push_back(details::make_unique>(padding)); + need_localtime_ = true; break; case ('b'): case ('h'): // month formatters_.push_back(details::make_unique>(padding)); + need_localtime_ = true; break; case ('B'): // short month formatters_.push_back(details::make_unique>(padding)); + need_localtime_ = true; break; case ('c'): // datetime formatters_.push_back(details::make_unique>(padding)); + need_localtime_ = true; break; case ('C'): // year 2 digits formatters_.push_back(details::make_unique>(padding)); + need_localtime_ = true; break; case ('Y'): // year 4 digits formatters_.push_back(details::make_unique>(padding)); + need_localtime_ = true; break; case ('D'): case ('x'): // datetime MM/DD/YY formatters_.push_back(details::make_unique>(padding)); + need_localtime_ = true; break; case ('m'): // month 1-12 formatters_.push_back(details::make_unique>(padding)); + need_localtime_ = true; break; case ('d'): // day of month 1-31 formatters_.push_back(details::make_unique>(padding)); + need_localtime_ = true; break; case ('H'): // hours 24 formatters_.push_back(details::make_unique>(padding)); + need_localtime_ = true; break; case ('I'): // hours 12 formatters_.push_back(details::make_unique>(padding)); + need_localtime_ = true; break; case ('M'): // minutes formatters_.push_back(details::make_unique>(padding)); + need_localtime_ = true; break; case ('S'): // seconds formatters_.push_back(details::make_unique>(padding)); + need_localtime_ = true; break; case ('e'): // milliseconds @@ -1195,23 +1221,28 @@ case ('p'): // am/pm formatters_.push_back(details::make_unique>(padding)); + need_localtime_ = true; break; case ('r'): // 12 hour clock 02:55:02 pm formatters_.push_back(details::make_unique>(padding)); + need_localtime_ = true; break; case ('R'): // 24-hour HH:MM time formatters_.push_back(details::make_unique>(padding)); + need_localtime_ = true; break; case ('T'): case ('X'): // ISO 8601 time format (HH:MM:SS) formatters_.push_back(details::make_unique>(padding)); + need_localtime_ = true; break; case ('z'): // timezone formatters_.push_back(details::make_unique>(padding)); + need_localtime_ = true; break; case ('P'): // pid @@ -1342,7 +1373,6 @@ { truncate = false; } - return details::padding_info{std::min(width, max_width), side, truncate}; } diff -Nru spdlog-1.9.2+ds/include/spdlog/sinks/ansicolor_sink-inl.h spdlog-1.10.0+ds/include/spdlog/sinks/ansicolor_sink-inl.h --- spdlog-1.9.2+ds/include/spdlog/sinks/ansicolor_sink-inl.h 2021-08-12 11:10:50.000000000 +0000 +++ spdlog-1.10.0+ds/include/spdlog/sinks/ansicolor_sink-inl.h 2022-04-04 13:48:58.000000000 +0000 @@ -34,7 +34,7 @@ SPDLOG_INLINE void ansicolor_sink::set_color(level::level_enum color_level, string_view_t color) { std::lock_guard lock(mutex_); - colors_[color_level] = to_string_(color); + colors_[static_cast(color_level)] = to_string_(color); } template @@ -52,7 +52,7 @@ // before color range print_range_(formatted, 0, msg.color_range_start); // in color range - print_ccode_(colors_[msg.level]); + print_ccode_(colors_[static_cast(msg.level)]); print_range_(formatted, msg.color_range_start, msg.color_range_end); print_ccode_(reset); // after color range diff -Nru spdlog-1.9.2+ds/include/spdlog/sinks/base_sink.h spdlog-1.10.0+ds/include/spdlog/sinks/base_sink.h --- spdlog-1.9.2+ds/include/spdlog/sinks/base_sink.h 2021-08-12 11:10:50.000000000 +0000 +++ spdlog-1.10.0+ds/include/spdlog/sinks/base_sink.h 2022-04-04 13:48:58.000000000 +0000 @@ -16,7 +16,7 @@ namespace spdlog { namespace sinks { template -class base_sink : public sink +class SPDLOG_API base_sink : public sink { public: base_sink(); @@ -37,7 +37,7 @@ protected: // sink formatter std::unique_ptr formatter_; - mutable Mutex mutex_; + Mutex mutex_; virtual void sink_it_(const details::log_msg &msg) = 0; virtual void flush_() = 0; diff -Nru spdlog-1.9.2+ds/include/spdlog/sinks/basic_file_sink.h spdlog-1.10.0+ds/include/spdlog/sinks/basic_file_sink.h --- spdlog-1.9.2+ds/include/spdlog/sinks/basic_file_sink.h 2021-08-12 11:10:50.000000000 +0000 +++ spdlog-1.10.0+ds/include/spdlog/sinks/basic_file_sink.h 2022-04-04 13:48:58.000000000 +0000 @@ -20,7 +20,7 @@ class basic_file_sink final : public base_sink { public: - explicit basic_file_sink(const filename_t &filename, bool truncate = false); + explicit basic_file_sink(const filename_t &filename, bool truncate = false, const file_event_handlers &event_handlers = {}); const filename_t &filename() const; protected: @@ -40,15 +40,17 @@ // factory functions // template -inline std::shared_ptr basic_logger_mt(const std::string &logger_name, const filename_t &filename, bool truncate = false) +inline std::shared_ptr basic_logger_mt( + const std::string &logger_name, const filename_t &filename, bool truncate = false, const file_event_handlers &event_handlers = {}) { - return Factory::template create(logger_name, filename, truncate); + return Factory::template create(logger_name, filename, truncate, event_handlers); } template -inline std::shared_ptr basic_logger_st(const std::string &logger_name, const filename_t &filename, bool truncate = false) +inline std::shared_ptr basic_logger_st( + const std::string &logger_name, const filename_t &filename, bool truncate = false, const file_event_handlers &event_handlers = {}) { - return Factory::template create(logger_name, filename, truncate); + return Factory::template create(logger_name, filename, truncate, event_handlers); } } // namespace spdlog diff -Nru spdlog-1.9.2+ds/include/spdlog/sinks/basic_file_sink-inl.h spdlog-1.10.0+ds/include/spdlog/sinks/basic_file_sink-inl.h --- spdlog-1.9.2+ds/include/spdlog/sinks/basic_file_sink-inl.h 2021-08-12 11:10:50.000000000 +0000 +++ spdlog-1.10.0+ds/include/spdlog/sinks/basic_file_sink-inl.h 2022-04-04 13:48:58.000000000 +0000 @@ -14,7 +14,8 @@ namespace sinks { template -SPDLOG_INLINE basic_file_sink::basic_file_sink(const filename_t &filename, bool truncate) +SPDLOG_INLINE basic_file_sink::basic_file_sink(const filename_t &filename, bool truncate, const file_event_handlers &event_handlers) + : file_helper_{event_handlers} { file_helper_.open(filename, truncate); } diff -Nru spdlog-1.9.2+ds/include/spdlog/sinks/daily_file_sink.h spdlog-1.10.0+ds/include/spdlog/sinks/daily_file_sink.h --- spdlog-1.9.2+ds/include/spdlog/sinks/daily_file_sink.h 2021-08-12 11:10:50.000000000 +0000 +++ spdlog-1.10.0+ds/include/spdlog/sinks/daily_file_sink.h 2022-04-04 13:48:58.000000000 +0000 @@ -32,7 +32,7 @@ { filename_t basename, ext; std::tie(basename, ext) = details::file_helper::split_by_extension(filename); - return fmt::format( + return fmt_lib::format( SPDLOG_FILENAME_T("{}_{:04d}-{:02d}-{:02d}{}"), basename, now_tm.tm_year + 1900, now_tm.tm_mon + 1, now_tm.tm_mday, ext); } }; @@ -48,14 +48,62 @@ { static filename_t calc_filename(const filename_t &filename, const tm &now_tm) { +#ifdef SPDLOG_USE_STD_FORMAT + // adapted from fmtlib: https://github.com/fmtlib/fmt/blob/8.0.1/include/fmt/chrono.h#L522-L546 + + filename_t tm_format; + tm_format.append(filename); + // By appending an extra space we can distinguish an empty result that + // indicates insufficient buffer size from a guaranteed non-empty result + // https://github.com/fmtlib/fmt/issues/2238 + tm_format.push_back(' '); + + const size_t MIN_SIZE = 10; + filename_t buf; + buf.resize(MIN_SIZE); + for (;;) + { + size_t count = strftime(buf.data(), buf.size(), tm_format.c_str(), &now_tm); + if (count != 0) + { + // Remove the extra space. + buf.resize(count - 1); + break; + } + buf.resize(buf.size() * 2); + } + + return buf; +#else // generate fmt datetime format string, e.g. {:%Y-%m-%d}. filename_t fmt_filename = fmt::format(SPDLOG_FILENAME_T("{{:{}}}"), filename); -#if defined(_MSC_VER) && defined(SPDLOG_WCHAR_FILENAMES) // for some reason msvc doesnt allow fmt::runtime(..) with wchar here +# if defined(_MSC_VER) && defined(SPDLOG_WCHAR_FILENAMES) // for some reason msvc doesn't allow fmt::runtime(..) with wchar here return fmt::format(fmt_filename, now_tm); -#else +# else return fmt::format(SPDLOG_FMT_RUNTIME(fmt_filename), now_tm); +# endif +#endif + } + +private: +#if defined __GNUC__ +# pragma GCC diagnostic push +# pragma GCC diagnostic ignored "-Wformat-nonliteral" #endif + + static size_t strftime(char *str, size_t count, const char *format, const std::tm *time) + { + return std::strftime(str, count, format, time); } + + static size_t strftime(wchar_t *str, size_t count, const wchar_t *format, const std::tm *time) + { + return std::wcsftime(str, count, format, time); + } + +#if defined(__GNUC__) +# pragma GCC diagnostic pop +#endif }; /* @@ -68,10 +116,12 @@ { public: // create daily file sink which rotates on given time - daily_file_sink(filename_t base_filename, int rotation_hour, int rotation_minute, bool truncate = false, uint16_t max_files = 0) + daily_file_sink(filename_t base_filename, int rotation_hour, int rotation_minute, bool truncate = false, uint16_t max_files = 0, + const file_event_handlers &event_handlers = {}) : base_filename_(std::move(base_filename)) , rotation_h_(rotation_hour) , rotation_m_(rotation_minute) + , file_helper_{event_handlers} , truncate_(truncate) , max_files_(max_files) , filenames_q_() @@ -213,30 +263,32 @@ // factory functions // template -inline std::shared_ptr daily_logger_mt( - const std::string &logger_name, const filename_t &filename, int hour = 0, int minute = 0, bool truncate = false, uint16_t max_files = 0) +inline std::shared_ptr daily_logger_mt(const std::string &logger_name, const filename_t &filename, int hour = 0, int minute = 0, + bool truncate = false, uint16_t max_files = 0, const file_event_handlers &event_handlers = {}) { - return Factory::template create(logger_name, filename, hour, minute, truncate, max_files); + return Factory::template create(logger_name, filename, hour, minute, truncate, max_files, event_handlers); } template -inline std::shared_ptr daily_logger_format_mt( - const std::string &logger_name, const filename_t &filename, int hour = 0, int minute = 0, bool truncate = false, uint16_t max_files = 0) +inline std::shared_ptr daily_logger_format_mt(const std::string &logger_name, const filename_t &filename, int hour = 0, + int minute = 0, bool truncate = false, uint16_t max_files = 0, const file_event_handlers &event_handlers = {}) { - return Factory::template create(logger_name, filename, hour, minute, truncate, max_files); + return Factory::template create( + logger_name, filename, hour, minute, truncate, max_files, event_handlers); } template -inline std::shared_ptr daily_logger_st( - const std::string &logger_name, const filename_t &filename, int hour = 0, int minute = 0, bool truncate = false, uint16_t max_files = 0) +inline std::shared_ptr daily_logger_st(const std::string &logger_name, const filename_t &filename, int hour = 0, int minute = 0, + bool truncate = false, uint16_t max_files = 0, const file_event_handlers &event_handlers = {}) { - return Factory::template create(logger_name, filename, hour, minute, truncate, max_files); + return Factory::template create(logger_name, filename, hour, minute, truncate, max_files, event_handlers); } template -inline std::shared_ptr daily_logger_format_st( - const std::string &logger_name, const filename_t &filename, int hour = 0, int minute = 0, bool truncate = false, uint16_t max_files = 0) +inline std::shared_ptr daily_logger_format_st(const std::string &logger_name, const filename_t &filename, int hour = 0, + int minute = 0, bool truncate = false, uint16_t max_files = 0, const file_event_handlers &event_handlers = {}) { - return Factory::template create(logger_name, filename, hour, minute, truncate, max_files); + return Factory::template create( + logger_name, filename, hour, minute, truncate, max_files, event_handlers); } } // namespace spdlog diff -Nru spdlog-1.9.2+ds/include/spdlog/sinks/hourly_file_sink.h spdlog-1.10.0+ds/include/spdlog/sinks/hourly_file_sink.h --- spdlog-1.9.2+ds/include/spdlog/sinks/hourly_file_sink.h 2021-08-12 11:10:50.000000000 +0000 +++ spdlog-1.10.0+ds/include/spdlog/sinks/hourly_file_sink.h 2022-04-04 13:48:58.000000000 +0000 @@ -31,7 +31,7 @@ { filename_t basename, ext; std::tie(basename, ext) = details::file_helper::split_by_extension(filename); - return fmt::format(SPDLOG_FILENAME_T("{}_{:04d}{:02d}{:02d}_{:02d}{}"), basename, now_tm.tm_year + 1900, now_tm.tm_mon + 1, + return fmt_lib::format(SPDLOG_FILENAME_T("{}_{:04d}-{:02d}-{:02d}_{:02d}{}"), basename, now_tm.tm_year + 1900, now_tm.tm_mon + 1, now_tm.tm_mday, now_tm.tm_hour, ext); } }; @@ -46,8 +46,10 @@ { public: // create hourly file sink which rotates on given time - hourly_file_sink(filename_t base_filename, bool truncate = false, uint16_t max_files = 0) + hourly_file_sink( + filename_t base_filename, bool truncate = false, uint16_t max_files = 0, const file_event_handlers &event_handlers = {}) : base_filename_(std::move(base_filename)) + , file_helper_{event_handlers} , truncate_(truncate) , max_files_(max_files) , filenames_q_() @@ -179,16 +181,16 @@ // factory functions // template -inline std::shared_ptr hourly_logger_mt( - const std::string &logger_name, const filename_t &filename, bool truncate = false, uint16_t max_files = 0) +inline std::shared_ptr hourly_logger_mt(const std::string &logger_name, const filename_t &filename, bool truncate = false, + uint16_t max_files = 0, const file_event_handlers &event_handlers = {}) { - return Factory::template create(logger_name, filename, truncate, max_files); + return Factory::template create(logger_name, filename, truncate, max_files, event_handlers); } template -inline std::shared_ptr hourly_logger_st( - const std::string &logger_name, const filename_t &filename, bool truncate = false, uint16_t max_files = 0) +inline std::shared_ptr hourly_logger_st(const std::string &logger_name, const filename_t &filename, bool truncate = false, + uint16_t max_files = 0, const file_event_handlers &event_handlers = {}) { - return Factory::template create(logger_name, filename, truncate, max_files); + return Factory::template create(logger_name, filename, truncate, max_files, event_handlers); } } // namespace spdlog diff -Nru spdlog-1.9.2+ds/include/spdlog/sinks/mongo_sink.h spdlog-1.10.0+ds/include/spdlog/sinks/mongo_sink.h --- spdlog-1.9.2+ds/include/spdlog/sinks/mongo_sink.h 2021-08-12 11:10:50.000000000 +0000 +++ spdlog-1.10.0+ds/include/spdlog/sinks/mongo_sink.h 2022-04-04 13:48:58.000000000 +0000 @@ -72,6 +72,7 @@ std::string coll_name_; std::unique_ptr client_ = nullptr; }; +template<> mongocxx::instance mongo_sink::instance_{}; #include "spdlog/details/null_mutex.h" diff -Nru spdlog-1.9.2+ds/include/spdlog/sinks/msvc_sink.h spdlog-1.10.0+ds/include/spdlog/sinks/msvc_sink.h --- spdlog-1.9.2+ds/include/spdlog/sinks/msvc_sink.h 2021-08-12 11:10:50.000000000 +0000 +++ spdlog-1.10.0+ds/include/spdlog/sinks/msvc_sink.h 2022-04-04 13:48:58.000000000 +0000 @@ -30,7 +30,11 @@ { memory_buf_t formatted; base_sink::formatter_->format(msg, formatted); +# ifdef SPDLOG_USE_STD_FORMAT + OutputDebugStringA(formatted.c_str()); +# else OutputDebugStringA(fmt::to_string(formatted).c_str()); +# endif } void flush_() override {} diff -Nru spdlog-1.9.2+ds/include/spdlog/sinks/qt_sinks.h spdlog-1.10.0+ds/include/spdlog/sinks/qt_sinks.h --- spdlog-1.9.2+ds/include/spdlog/sinks/qt_sinks.h 2021-08-12 11:10:50.000000000 +0000 +++ spdlog-1.10.0+ds/include/spdlog/sinks/qt_sinks.h 2022-04-04 13:48:58.000000000 +0000 @@ -21,29 +21,36 @@ // namespace spdlog { namespace sinks { -template class qt_sink : public base_sink { +template +class qt_sink : public base_sink +{ public: - qt_sink(QObject *qt_object = nullptr, const std::string &meta_method = "") { - qt_object_ = qt_object; - meta_method_ = meta_method; - } - - ~qt_sink() { flush_(); } + qt_sink(QObject *qt_object, const std::string &meta_method) + { + qt_object_ = qt_object; + meta_method_ = meta_method; + } + + ~qt_sink() + { + flush_(); + } protected: - void sink_it_(const details::log_msg &msg) override { - memory_buf_t formatted; - base_sink::formatter_->format(msg, formatted); - string_view_t str = string_view_t(formatted.data(), formatted.size()); - QMetaObject::invokeMethod(qt_object_, meta_method_.c_str(), Qt::AutoConnection, - Q_ARG(QString, QString::fromUtf8(str.data(), static_cast(str.size())).trimmed())); - } + void sink_it_(const details::log_msg &msg) override + { + memory_buf_t formatted; + base_sink::formatter_->format(msg, formatted); + string_view_t str = string_view_t(formatted.data(), formatted.size()); + QMetaObject::invokeMethod(qt_object_, meta_method_.c_str(), Qt::AutoConnection, + Q_ARG(QString, QString::fromUtf8(str.data(), static_cast(str.size())).trimmed())); + } - void flush_() override {} + void flush_() override {} private: - QObject *qt_object_ = nullptr; - std::string meta_method_; + QObject *qt_object_ = nullptr; + std::string meta_method_; }; #include "spdlog/details/null_mutex.h" @@ -55,39 +62,41 @@ // // Factory functions // -template -inline std::shared_ptr -qt_logger_mt(const std::string &logger_name, QTextEdit* qt_object, const std::string &meta_method = "append") { - return Factory::template create(logger_name, qt_object, meta_method); +template +inline std::shared_ptr qt_logger_mt(const std::string &logger_name, QTextEdit *qt_object, const std::string &meta_method = "append") +{ + return Factory::template create(logger_name, qt_object, meta_method); } -template -inline std::shared_ptr -qt_logger_st(const std::string &logger_name, QTextEdit* qt_object, const std::string &meta_method = "append") { - return Factory::template create(logger_name, qt_object, meta_method); +template +inline std::shared_ptr qt_logger_st(const std::string &logger_name, QTextEdit *qt_object, const std::string &meta_method = "append") +{ + return Factory::template create(logger_name, qt_object, meta_method); } -template -inline std::shared_ptr -qt_logger_mt(const std::string &logger_name, QPlainTextEdit* qt_object , const std::string &meta_method = "appendPlainText") { +template +inline std::shared_ptr qt_logger_mt( + const std::string &logger_name, QPlainTextEdit *qt_object, const std::string &meta_method = "appendPlainText") +{ return Factory::template create(logger_name, qt_object, meta_method); } -template -inline std::shared_ptr -qt_logger_st(const std::string &logger_name, QPlainTextEdit* qt_object, const std::string &meta_method = "appendPlainText") { +template +inline std::shared_ptr qt_logger_st( + const std::string &logger_name, QPlainTextEdit *qt_object, const std::string &meta_method = "appendPlainText") +{ return Factory::template create(logger_name, qt_object, meta_method); } -template -inline std::shared_ptr -qt_logger_mt(const std::string &logger_name, QObject* qt_object, const std::string &meta_method) { +template +inline std::shared_ptr qt_logger_mt(const std::string &logger_name, QObject *qt_object, const std::string &meta_method) +{ return Factory::template create(logger_name, qt_object, meta_method); } -template -inline std::shared_ptr -qt_logger_st(const std::string &logger_name, QObject* qt_object, const std::string &meta_method) { +template +inline std::shared_ptr qt_logger_st(const std::string &logger_name, QObject *qt_object, const std::string &meta_method) +{ return Factory::template create(logger_name, qt_object, meta_method); } } // namespace spdlog diff -Nru spdlog-1.9.2+ds/include/spdlog/sinks/ringbuffer_sink.h spdlog-1.10.0+ds/include/spdlog/sinks/ringbuffer_sink.h --- spdlog-1.9.2+ds/include/spdlog/sinks/ringbuffer_sink.h 2021-08-12 11:10:50.000000000 +0000 +++ spdlog-1.10.0+ds/include/spdlog/sinks/ringbuffer_sink.h 2022-04-04 13:48:58.000000000 +0000 @@ -50,7 +50,11 @@ { memory_buf_t formatted; base_sink::formatter_->format(q_.at(i), formatted); +#ifdef SPDLOG_USE_STD_FORMAT + ret.push_back(std::move(formatted)); +#else ret.push_back(fmt::to_string(formatted)); +#endif } return ret; } diff -Nru spdlog-1.9.2+ds/include/spdlog/sinks/rotating_file_sink.h spdlog-1.10.0+ds/include/spdlog/sinks/rotating_file_sink.h --- spdlog-1.9.2+ds/include/spdlog/sinks/rotating_file_sink.h 2021-08-12 11:10:50.000000000 +0000 +++ spdlog-1.10.0+ds/include/spdlog/sinks/rotating_file_sink.h 2022-04-04 13:48:58.000000000 +0000 @@ -22,7 +22,8 @@ class rotating_file_sink final : public base_sink { public: - rotating_file_sink(filename_t base_filename, std::size_t max_size, std::size_t max_files, bool rotate_on_open = false); + rotating_file_sink(filename_t base_filename, std::size_t max_size, std::size_t max_files, bool rotate_on_open = false, + const file_event_handlers &event_handlers = {}); static filename_t calc_filename(const filename_t &filename, std::size_t index); filename_t filename(); @@ -59,17 +60,19 @@ // template -inline std::shared_ptr rotating_logger_mt( - const std::string &logger_name, const filename_t &filename, size_t max_file_size, size_t max_files, bool rotate_on_open = false) +inline std::shared_ptr rotating_logger_mt(const std::string &logger_name, const filename_t &filename, size_t max_file_size, + size_t max_files, bool rotate_on_open = false, const file_event_handlers &event_handlers = {}) { - return Factory::template create(logger_name, filename, max_file_size, max_files, rotate_on_open); + return Factory::template create( + logger_name, filename, max_file_size, max_files, rotate_on_open, event_handlers); } template -inline std::shared_ptr rotating_logger_st( - const std::string &logger_name, const filename_t &filename, size_t max_file_size, size_t max_files, bool rotate_on_open = false) +inline std::shared_ptr rotating_logger_st(const std::string &logger_name, const filename_t &filename, size_t max_file_size, + size_t max_files, bool rotate_on_open = false, const file_event_handlers &event_handlers = {}) { - return Factory::template create(logger_name, filename, max_file_size, max_files, rotate_on_open); + return Factory::template create( + logger_name, filename, max_file_size, max_files, rotate_on_open, event_handlers); } } // namespace spdlog diff -Nru spdlog-1.9.2+ds/include/spdlog/sinks/rotating_file_sink-inl.h spdlog-1.10.0+ds/include/spdlog/sinks/rotating_file_sink-inl.h --- spdlog-1.9.2+ds/include/spdlog/sinks/rotating_file_sink-inl.h 2021-08-12 11:10:50.000000000 +0000 +++ spdlog-1.10.0+ds/include/spdlog/sinks/rotating_file_sink-inl.h 2022-04-04 13:48:58.000000000 +0000 @@ -25,16 +25,27 @@ template SPDLOG_INLINE rotating_file_sink::rotating_file_sink( - filename_t base_filename, std::size_t max_size, std::size_t max_files, bool rotate_on_open) + filename_t base_filename, std::size_t max_size, std::size_t max_files, bool rotate_on_open, const file_event_handlers &event_handlers) : base_filename_(std::move(base_filename)) , max_size_(max_size) , max_files_(max_files) + , file_helper_{event_handlers} { + if (max_size == 0) + { + throw_spdlog_ex("rotating sink constructor: max_size arg cannot be zero"); + } + + if (max_files > 200000) + { + throw_spdlog_ex("rotating sink constructor: max_files arg cannot exceed 200000"); + } file_helper_.open(calc_filename(base_filename_, 0)); current_size_ = file_helper_.size(); // expensive. called only once if (rotate_on_open && current_size_ > 0) { rotate_(); + current_size_ = 0; } } @@ -50,7 +61,7 @@ filename_t basename, ext; std::tie(basename, ext) = details::file_helper::split_by_extension(filename); - return fmt::format(SPDLOG_FILENAME_T("{}.{}{}"), basename, index, ext); + return fmt_lib::format(SPDLOG_FILENAME_T("{}.{}{}"), basename, index, ext); } template @@ -65,13 +76,22 @@ { memory_buf_t formatted; base_sink::formatter_->format(msg, formatted); - current_size_ += formatted.size(); - if (current_size_ > max_size_) + auto new_size = current_size_ + formatted.size(); + + // rotate if the new estimated file size exceeds max size. + // rotate only if the real size > 0 to better deal with full disk (see issue #2261). + // we only check the real size when new_size > max_size_ because it is relatively expensive. + if (new_size > max_size_) { - rotate_(); - current_size_ = formatted.size(); + file_helper_.flush(); + if (file_helper_.size() > 0) + { + rotate_(); + new_size = formatted.size(); + } } file_helper_.write(formatted); + current_size_ = new_size; } template @@ -90,6 +110,7 @@ { using details::os::filename_to_str; using details::os::path_exists; + file_helper_.close(); for (auto i = max_files_; i > 0; --i) { diff -Nru spdlog-1.9.2+ds/include/spdlog/sinks/stdout_sinks-inl.h spdlog-1.10.0+ds/include/spdlog/sinks/stdout_sinks-inl.h --- spdlog-1.9.2+ds/include/spdlog/sinks/stdout_sinks-inl.h 2021-08-12 11:10:50.000000000 +0000 +++ spdlog-1.10.0+ds/include/spdlog/sinks/stdout_sinks-inl.h 2022-04-04 13:48:58.000000000 +0000 @@ -16,7 +16,7 @@ // so instead we use ::FileWrite # include -# ifndef _USING_V110_SDK71_ // fileapi.h doesnt exist in winxp +# ifndef _USING_V110_SDK71_ // fileapi.h doesn't exist in winxp # include // WriteFile (..) # endif @@ -37,7 +37,7 @@ #ifdef _WIN32 // get windows handle from the FILE* object - handle_ = (HANDLE)::_get_osfhandle(::_fileno(file_)); + handle_ = reinterpret_cast(::_get_osfhandle(::_fileno(file_))); // don't throw to support cases where no console is attached, // and let the log method to do nothing if (handle_ == INVALID_HANDLE_VALUE). @@ -60,7 +60,7 @@ std::lock_guard lock(mutex_); memory_buf_t formatted; formatter_->format(msg, formatted); - ::fflush(file_); // flush in case there is somthing in this file_ already + ::fflush(file_); // flush in case there is something in this file_ already auto size = static_cast(formatted.size()); DWORD bytes_written = 0; bool ok = ::WriteFile(handle_, formatted.data(), size, &bytes_written, nullptr) != 0; diff -Nru spdlog-1.9.2+ds/include/spdlog/sinks/systemd_sink.h spdlog-1.10.0+ds/include/spdlog/sinks/systemd_sink.h --- spdlog-1.9.2+ds/include/spdlog/sinks/systemd_sink.h 2021-08-12 11:10:50.000000000 +0000 +++ spdlog-1.10.0+ds/include/spdlog/sinks/systemd_sink.h 2022-04-04 13:48:58.000000000 +0000 @@ -18,16 +18,15 @@ /** * Sink that write to systemd journal using the `sd_journal_send()` library call. - * - * Locking is not needed, as `sd_journal_send()` itself is thread-safe. */ template class systemd_sink : public base_sink { public: - // - systemd_sink() - : syslog_levels_{{/* spdlog::level::trace */ LOG_DEBUG, + systemd_sink(std::string ident = "", bool enable_formatting = false) + : ident_{std::move(ident)} + , enable_formatting_{enable_formatting} + , syslog_levels_{{/* spdlog::level::trace */ LOG_DEBUG, /* spdlog::level::debug */ LOG_DEBUG, /* spdlog::level::info */ LOG_INFO, /* spdlog::level::warn */ LOG_WARNING, @@ -42,31 +41,46 @@ systemd_sink &operator=(const systemd_sink &) = delete; protected: + const std::string ident_; + bool enable_formatting_ = false; using levels_array = std::array; levels_array syslog_levels_; void sink_it_(const details::log_msg &msg) override { int err; + string_view_t payload; + memory_buf_t formatted; + if (enable_formatting_) + { + base_sink::formatter_->format(msg, formatted); + payload = string_view_t(formatted.data(), formatted.size()); + } + else + { + payload = msg.payload; + } - size_t length = msg.payload.size(); + size_t length = payload.size(); // limit to max int if (length > static_cast(std::numeric_limits::max())) { length = static_cast(std::numeric_limits::max()); } + const string_view_t syslog_identifier = ident_.empty() ? msg.logger_name : ident_; + // Do not send source location if not available if (msg.source.empty()) { // Note: function call inside '()' to avoid macro expansion - err = (sd_journal_send)("MESSAGE=%.*s", static_cast(length), msg.payload.data(), "PRIORITY=%d", syslog_level(msg.level), - "SYSLOG_IDENTIFIER=%.*s", static_cast(msg.logger_name.size()), msg.logger_name.data(), nullptr); + err = (sd_journal_send)("MESSAGE=%.*s", static_cast(length), payload.data(), "PRIORITY=%d", syslog_level(msg.level), + "SYSLOG_IDENTIFIER=%.*s", static_cast(syslog_identifier.size()), syslog_identifier.data(), nullptr); } else { - err = (sd_journal_send)("MESSAGE=%.*s", static_cast(length), msg.payload.data(), "PRIORITY=%d", syslog_level(msg.level), - "SYSLOG_IDENTIFIER=%.*s", static_cast(msg.logger_name.size()), msg.logger_name.data(), "CODE_FILE=%s", + err = (sd_journal_send)("MESSAGE=%.*s", static_cast(length), payload.data(), "PRIORITY=%d", syslog_level(msg.level), + "SYSLOG_IDENTIFIER=%.*s", static_cast(syslog_identifier.size()), syslog_identifier.data(), "CODE_FILE=%s", msg.source.filename, "CODE_LINE=%d", msg.source.line, "CODE_FUNC=%s", msg.source.funcname, nullptr); } @@ -90,14 +104,16 @@ // Create and register a syslog logger template -inline std::shared_ptr systemd_logger_mt(const std::string &logger_name) +inline std::shared_ptr systemd_logger_mt( + const std::string &logger_name, const std::string &ident = "", bool enable_formatting = false) { - return Factory::template create(logger_name); + return Factory::template create(logger_name, ident, enable_formatting); } template -inline std::shared_ptr systemd_logger_st(const std::string &logger_name) +inline std::shared_ptr systemd_logger_st( + const std::string &logger_name, const std::string &ident = "", bool enable_formatting = false) { - return Factory::template create(logger_name); + return Factory::template create(logger_name, ident, enable_formatting); } } // namespace spdlog diff -Nru spdlog-1.9.2+ds/include/spdlog/sinks/udp_sink.h spdlog-1.10.0+ds/include/spdlog/sinks/udp_sink.h --- spdlog-1.9.2+ds/include/spdlog/sinks/udp_sink.h 1970-01-01 00:00:00.000000000 +0000 +++ spdlog-1.10.0+ds/include/spdlog/sinks/udp_sink.h 2022-04-04 13:48:58.000000000 +0000 @@ -0,0 +1,74 @@ +// Copyright(c) 2015-present, Gabi Melman & spdlog contributors. +// Distributed under the MIT License (http://opensource.org/licenses/MIT) + +#pragma once + +#include +#include +#include +#ifdef _WIN32 +# include +#else +# include +#endif + +#include +#include +#include +#include + +// Simple udp client sink +// Sends formatted log via udp + +namespace spdlog { +namespace sinks { + +struct udp_sink_config +{ + std::string server_host; + uint16_t server_port; + + udp_sink_config(std::string host, uint16_t port) + : server_host{std::move(host)} + , server_port{port} + {} +}; + +template +class udp_sink : public spdlog::sinks::base_sink +{ +public: + // host can be hostname or ip address + explicit udp_sink(udp_sink_config sink_config) + : client_{sink_config.server_host, sink_config.server_port} + {} + + ~udp_sink() override = default; + +protected: + void sink_it_(const spdlog::details::log_msg &msg) override + { + spdlog::memory_buf_t formatted; + spdlog::sinks::base_sink::formatter_->format(msg, formatted); + client_.send(formatted.data(), formatted.size()); + } + + void flush_() override {} + details::udp_client client_; +}; + +using udp_sink_mt = udp_sink; +using udp_sink_st = udp_sink; + +} // namespace sinks + +// +// factory functions +// +template +inline std::shared_ptr udp_logger_mt(const std::string &logger_name, sinks::udp_sink_config skin_config) +{ + return Factory::template create(logger_name, skin_config); +} + +} // namespace spdlog diff -Nru spdlog-1.9.2+ds/include/spdlog/sinks/win_eventlog_sink.h spdlog-1.10.0+ds/include/spdlog/sinks/win_eventlog_sink.h --- spdlog-1.9.2+ds/include/spdlog/sinks/win_eventlog_sink.h 2021-08-12 11:10:50.000000000 +0000 +++ spdlog-1.10.0+ds/include/spdlog/sinks/win_eventlog_sink.h 2022-04-04 13:48:58.000000000 +0000 @@ -47,6 +47,24 @@ namespace internal { +struct local_alloc_t +{ + HLOCAL hlocal_; + + SPDLOG_CONSTEXPR local_alloc_t() SPDLOG_NOEXCEPT : hlocal_(nullptr) {} + + local_alloc_t(local_alloc_t const &) = delete; + local_alloc_t &operator=(local_alloc_t const &) = delete; + + ~local_alloc_t() SPDLOG_NOEXCEPT + { + if (hlocal_) + { + LocalFree(hlocal_); + } + } +}; + /** Windows error */ struct win32_error : public spdlog_ex { @@ -55,22 +73,17 @@ { std::string system_message; - LPSTR format_message_result{}; + local_alloc_t format_message_result{}; auto format_message_succeeded = ::FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, nullptr, - error_code, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPSTR)&format_message_result, 0, nullptr); - - if (format_message_succeeded && format_message_result) - { - system_message = fmt::format(" ({})", format_message_result); - } + error_code, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPSTR)&format_message_result.hlocal_, 0, nullptr); - if (format_message_result) + if (format_message_succeeded && format_message_result.hlocal_) { - LocalFree((HLOCAL)format_message_result); + system_message = fmt_lib::format(" ({})", (LPSTR)format_message_result.hlocal_); } - return fmt::format("{}: {}{}", user_message, error_code, system_message); + return fmt_lib::format("{}: {}{}", user_message, error_code, system_message); } explicit win32_error(std::string const &func_name, DWORD error = GetLastError()) diff -Nru spdlog-1.9.2+ds/include/spdlog/spdlog.h spdlog-1.10.0+ds/include/spdlog/spdlog.h --- spdlog-1.9.2+ds/include/spdlog/spdlog.h 2021-08-12 11:10:50.000000000 +0000 +++ spdlog-1.10.0+ds/include/spdlog/spdlog.h 2022-04-04 13:48:58.000000000 +0000 @@ -31,7 +31,7 @@ // Example: // spdlog::create("logger_name", "dailylog_filename", 11, 59); template -inline std::shared_ptr create(std::string logger_name, SinkArgs &&...sink_args) +inline std::shared_ptr create(std::string logger_name, SinkArgs &&... sink_args) { return default_factory::create(std::move(logger_name), std::forward(sink_args)...); } @@ -128,49 +128,49 @@ SPDLOG_API void set_default_logger(std::shared_ptr default_logger); template -inline void log(source_loc source, level::level_enum lvl, fmt::format_string fmt, Args &&...args) +inline void log(source_loc source, level::level_enum lvl, format_string_t fmt, Args &&... args) { default_logger_raw()->log(source, lvl, fmt, std::forward(args)...); } template -inline void log(level::level_enum lvl, fmt::format_string fmt, Args &&...args) +inline void log(level::level_enum lvl, format_string_t fmt, Args &&... args) { default_logger_raw()->log(source_loc{}, lvl, fmt, std::forward(args)...); } template -inline void trace(fmt::format_string fmt, Args &&...args) +inline void trace(format_string_t fmt, Args &&... args) { default_logger_raw()->trace(fmt, std::forward(args)...); } template -inline void debug(fmt::format_string fmt, Args &&...args) +inline void debug(format_string_t fmt, Args &&... args) { default_logger_raw()->debug(fmt, std::forward(args)...); } template -inline void info(fmt::format_string fmt, Args &&...args) +inline void info(format_string_t fmt, Args &&... args) { default_logger_raw()->info(fmt, std::forward(args)...); } template -inline void warn(fmt::format_string fmt, Args &&...args) +inline void warn(format_string_t fmt, Args &&... args) { default_logger_raw()->warn(fmt, std::forward(args)...); } template -inline void error(fmt::format_string fmt, Args &&...args) +inline void error(format_string_t fmt, Args &&... args) { default_logger_raw()->error(fmt, std::forward(args)...); } template -inline void critical(fmt::format_string fmt, Args &&...args) +inline void critical(format_string_t fmt, Args &&... args) { default_logger_raw()->critical(fmt, std::forward(args)...); } @@ -189,49 +189,49 @@ #ifdef SPDLOG_WCHAR_TO_UTF8_SUPPORT template -inline void log(source_loc source, level::level_enum lvl, fmt::wformat_string fmt, Args &&...args) +inline void log(source_loc source, level::level_enum lvl, wformat_string_t fmt, Args &&... args) { default_logger_raw()->log(source, lvl, fmt, std::forward(args)...); } template -inline void log(level::level_enum lvl, fmt::wformat_string fmt, Args &&...args) +inline void log(level::level_enum lvl, wformat_string_t fmt, Args &&... args) { default_logger_raw()->log(source_loc{}, lvl, fmt, std::forward(args)...); } template -inline void trace(fmt::wformat_string fmt, Args &&...args) +inline void trace(wformat_string_t fmt, Args &&... args) { default_logger_raw()->trace(fmt, std::forward(args)...); } template -inline void debug(fmt::wformat_string fmt, Args &&...args) +inline void debug(wformat_string_t fmt, Args &&... args) { default_logger_raw()->debug(fmt, std::forward(args)...); } template -inline void info(fmt::wformat_string fmt, Args &&...args) +inline void info(wformat_string_t fmt, Args &&... args) { default_logger_raw()->info(fmt, std::forward(args)...); } template -inline void warn(fmt::wformat_string fmt, Args &&...args) +inline void warn(wformat_string_t fmt, Args &&... args) { default_logger_raw()->warn(fmt, std::forward(args)...); } template -inline void error(fmt::wformat_string fmt, Args &&...args) +inline void error(wformat_string_t fmt, Args &&... args) { default_logger_raw()->error(fmt, std::forward(args)...); } template -inline void critical(fmt::wformat_string fmt, Args &&...args) +inline void critical(wformat_string_t fmt, Args &&... args) { default_logger_raw()->critical(fmt, std::forward(args)...); } diff -Nru spdlog-1.9.2+ds/include/spdlog/stopwatch.h spdlog-1.10.0+ds/include/spdlog/stopwatch.h --- spdlog-1.9.2+ds/include/spdlog/stopwatch.h 2021-08-12 11:10:50.000000000 +0000 +++ spdlog-1.10.0+ds/include/spdlog/stopwatch.h 2022-04-04 13:48:58.000000000 +0000 @@ -42,13 +42,20 @@ void reset() { - start_tp_ = clock ::now(); + start_tp_ = clock::now(); } }; } // namespace spdlog // Support for fmt formatting (e.g. "{:012.9}" or just "{}") -namespace fmt { +namespace +#ifdef SPDLOG_USE_STD_FORMAT + std +#else + fmt +#endif +{ + template<> struct formatter : formatter { @@ -58,4 +65,4 @@ return formatter::format(sw.elapsed().count(), ctx); } }; -} // namespace fmt +} // namespace std diff -Nru spdlog-1.9.2+ds/include/spdlog/tweakme.h spdlog-1.10.0+ds/include/spdlog/tweakme.h --- spdlog-1.9.2+ds/include/spdlog/tweakme.h 2021-08-12 11:10:50.000000000 +0000 +++ spdlog-1.10.0+ds/include/spdlog/tweakme.h 2022-04-04 13:48:58.000000000 +0000 @@ -75,6 +75,13 @@ /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// +// Uncomment to use C++20 std::format instead of fmt. This removes compile +// time checking of format strings, but doesn't depend on the fmt library. +// +// #define SPDLOG_USE_STD_FORMAT +/////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////// // Uncomment to enable wchar_t support (convert to utf8) // // #define SPDLOG_WCHAR_TO_UTF8_SUPPORT @@ -89,8 +96,7 @@ /////////////////////////////////////////////////////////////////////////////// // Uncomment to customize level names (e.g. "MY TRACE") // -// #define SPDLOG_LEVEL_NAMES { "MY TRACE", "MY DEBUG", "MY INFO", "MY WARNING", -// "MY ERROR", "MY CRITICAL", "OFF" } +// #define SPDLOG_LEVEL_NAMES { "MY TRACE", "MY DEBUG", "MY INFO", "MY WARNING", "MY ERROR", "MY CRITICAL", "OFF" } /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// @@ -120,5 +126,9 @@ // __PRETTY_FUNCTION__ might be nicer in clang/gcc, and __FUNCTION__ in msvc. // Defaults to __FUNCTION__ (should work on all compilers) if not defined. // -// #define SPDLOG_FUNCTION __PRETTY_FUNCTION__ +// #ifdef __PRETTY_FUNCTION__ +// # define SPDLOG_FUNCTION __PRETTY_FUNCTION__ +// #else +// # define SPDLOG_FUNCTION __FUNCTION__ +// #endif /////////////////////////////////////////////////////////////////////////////// diff -Nru spdlog-1.9.2+ds/include/spdlog/version.h spdlog-1.10.0+ds/include/spdlog/version.h --- spdlog-1.9.2+ds/include/spdlog/version.h 2021-08-12 11:10:50.000000000 +0000 +++ spdlog-1.10.0+ds/include/spdlog/version.h 2022-04-04 13:48:58.000000000 +0000 @@ -4,7 +4,7 @@ #pragma once #define SPDLOG_VER_MAJOR 1 -#define SPDLOG_VER_MINOR 9 -#define SPDLOG_VER_PATCH 2 +#define SPDLOG_VER_MINOR 10 +#define SPDLOG_VER_PATCH 0 #define SPDLOG_VERSION (SPDLOG_VER_MAJOR * 10000 + SPDLOG_VER_MINOR * 100 + SPDLOG_VER_PATCH) diff -Nru spdlog-1.9.2+ds/README.md spdlog-1.10.0+ds/README.md --- spdlog-1.9.2+ds/README.md 2021-08-12 11:10:50.000000000 +0000 +++ spdlog-1.10.0+ds/README.md 2022-04-04 13:48:58.000000000 +0000 @@ -1,6 +1,6 @@ # spdlog -Very fast, header-only/compiled, C++ logging library. [![Build Status](https://travis-ci.com/gabime/spdlog.svg?branch=v1.x)](https://travis-ci.com/gabime/spdlog)  [![Build status](https://ci.appveyor.com/api/projects/status/d2jnxclg20vd0o50?svg=true)](https://ci.appveyor.com/project/gabime/spdlog) [![Release](https://img.shields.io/github/release/gabime/spdlog.svg)](https://github.com/gabime/spdlog/releases/latest) +Very fast, header-only/compiled, C++ logging library. [![Build Status](https://app.travis-ci.com/gabime/spdlog.svg?branch=v1.x)](https://app.travis-ci.com/gabime/spdlog)  [![Build status](https://ci.appveyor.com/api/projects/status/d2jnxclg20vd0o50?svg=true&branch=v1.x)](https://ci.appveyor.com/project/gabime/spdlog) [![Release](https://img.shields.io/github/release/gabime/spdlog.svg)](https://github.com/gabime/spdlog/releases/latest) ## Install #### Header only version @@ -22,9 +22,10 @@ * Android ## Package managers: +* Debian: `sudo apt install libspdlog-dev` * Homebrew: `brew install spdlog` * MacPorts: `sudo port install spdlog` -* FreeBSD: `cd /usr/ports/devel/spdlog/ && make install clean` +* FreeBSD: `pkg install spdlog` * Fedora: `dnf install spdlog` * Gentoo: `emerge dev-libs/spdlog` * Arch Linux: `pacman -S spdlog` @@ -34,7 +35,6 @@ * build2: ```depends: spdlog ^1.8.2``` - ## Features * Very fast (see [benchmarks](#benchmarks) below). * Headers only or compiled @@ -373,6 +373,35 @@ $ ./example ``` + +--- +#### Log file open/close event handlers +```c++ +// You can get callbacks from spdlog before/after log file has been opened or closed. +// This is useful for cleanup procedures or for adding someting the start/end of the log files. +void file_events_example() +{ + // pass the spdlog::file_event_handlers to file sinks for open/close log file notifications + spdlog::file_event_handlers handlers; + handlers.before_open = [](spdlog::filename_t filename) { spdlog::info("Before opening {}", filename); }; + handlers.after_open = [](spdlog::filename_t filename, std::FILE *fstream) { fputs("After opening\n", fstream); }; + handlers.before_close = [](spdlog::filename_t filename, std::FILE *fstream) { fputs("Before closing\n", fstream); }; + handlers.after_close = [](spdlog::filename_t filename) { spdlog::info("After closing {}", filename); }; + auto my_logger = spdlog::basic_logger_st("some_logger", "logs/events-sample.txt", true, handlers); +} +``` + +--- +#### Replace the Default Logger +```c++ +void replace_default_logger_example() +{ + auto new_logger = spdlog::basic_logger_mt("new_default_logger", "logs/new-default-log.txt", true); + spdlog::set_default_logger(new_logger); + spdlog::info("new logger log message"); +} +``` + --- ## Benchmarks diff -Nru spdlog-1.9.2+ds/src/fmt.cpp spdlog-1.10.0+ds/src/fmt.cpp --- spdlog-1.9.2+ds/src/fmt.cpp 2021-08-12 11:10:50.000000000 +0000 +++ spdlog-1.10.0+ds/src/fmt.cpp 2022-04-04 13:48:58.000000000 +0000 @@ -6,12 +6,54 @@ # error Please define SPDLOG_COMPILED_LIB to compile this file. #endif -#if !defined(SPDLOG_FMT_EXTERNAL) +#if !defined(SPDLOG_FMT_EXTERNAL) && !defined(SPDLOG_USE_STD_FORMAT) # include FMT_BEGIN_NAMESPACE namespace detail { +// DEPRECATED! +template +struct basic_data +{ + FMT_API static constexpr const char digits[100][2] = {{'0', '0'}, {'0', '1'}, {'0', '2'}, {'0', '3'}, {'0', '4'}, {'0', '5'}, + {'0', '6'}, {'0', '7'}, {'0', '8'}, {'0', '9'}, {'1', '0'}, {'1', '1'}, {'1', '2'}, {'1', '3'}, {'1', '4'}, {'1', '5'}, {'1', '6'}, + {'1', '7'}, {'1', '8'}, {'1', '9'}, {'2', '0'}, {'2', '1'}, {'2', '2'}, {'2', '3'}, {'2', '4'}, {'2', '5'}, {'2', '6'}, {'2', '7'}, + {'2', '8'}, {'2', '9'}, {'3', '0'}, {'3', '1'}, {'3', '2'}, {'3', '3'}, {'3', '4'}, {'3', '5'}, {'3', '6'}, {'3', '7'}, {'3', '8'}, + {'3', '9'}, {'4', '0'}, {'4', '1'}, {'4', '2'}, {'4', '3'}, {'4', '4'}, {'4', '5'}, {'4', '6'}, {'4', '7'}, {'4', '8'}, {'4', '9'}, + {'5', '0'}, {'5', '1'}, {'5', '2'}, {'5', '3'}, {'5', '4'}, {'5', '5'}, {'5', '6'}, {'5', '7'}, {'5', '8'}, {'5', '9'}, {'6', '0'}, + {'6', '1'}, {'6', '2'}, {'6', '3'}, {'6', '4'}, {'6', '5'}, {'6', '6'}, {'6', '7'}, {'6', '8'}, {'6', '9'}, {'7', '0'}, {'7', '1'}, + {'7', '2'}, {'7', '3'}, {'7', '4'}, {'7', '5'}, {'7', '6'}, {'7', '7'}, {'7', '8'}, {'7', '9'}, {'8', '0'}, {'8', '1'}, {'8', '2'}, + {'8', '3'}, {'8', '4'}, {'8', '5'}, {'8', '6'}, {'8', '7'}, {'8', '8'}, {'8', '9'}, {'9', '0'}, {'9', '1'}, {'9', '2'}, {'9', '3'}, + {'9', '4'}, {'9', '5'}, {'9', '6'}, {'9', '7'}, {'9', '8'}, {'9', '9'}}; + FMT_API static constexpr const char hex_digits[] = "0123456789abcdef"; + FMT_API static constexpr const char signs[4] = {0, '-', '+', ' '}; + FMT_API static constexpr const char left_padding_shifts[5] = {31, 31, 0, 1, 0}; + FMT_API static constexpr const char right_padding_shifts[5] = {0, 31, 0, 1, 0}; + FMT_API static constexpr const unsigned prefixes[4] = {0, 0, 0x1000000u | '+', 0x1000000u | ' '}; +}; + +# ifdef FMT_SHARED +// Required for -flto, -fivisibility=hidden and -shared to work +extern template struct basic_data; +# endif + +# if __cplusplus < 201703L +// DEPRECATED! These are here only for ABI compatiblity. +template +constexpr const char basic_data::digits[][2]; +template +constexpr const char basic_data::hex_digits[]; +template +constexpr const char basic_data::signs[]; +template +constexpr const char basic_data::left_padding_shifts[]; +template +constexpr const char basic_data::right_padding_shifts[]; +template +constexpr const unsigned basic_data::prefixes[]; +# endif + template int format_float(char *buf, std::size_t size, const char *format, int precision, T value) { diff -Nru spdlog-1.9.2+ds/tests/catch.hpp spdlog-1.10.0+ds/tests/catch.hpp --- spdlog-1.9.2+ds/tests/catch.hpp 2021-08-12 11:10:50.000000000 +0000 +++ spdlog-1.10.0+ds/tests/catch.hpp 2022-04-04 13:48:58.000000000 +0000 @@ -1,9 +1,9 @@ /* - * Catch v2.8.0 - * Generated: 2019-05-26 21:29:22.235281 + * Catch v2.13.7 + * Generated: 2021-07-28 20:29:27.753164 * ---------------------------------------------------------- * This file has been merged from multiple headers. Please don't edit it directly - * Copyright (c) 2019 Two Blue Cubes Ltd. All rights reserved. + * Copyright (c) 2021 Two Blue Cubes Ltd. All rights reserved. * * Distributed under the Boost Software License, Version 1.0. (See accompanying * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -14,8 +14,8 @@ #define CATCH_VERSION_MAJOR 2 -#define CATCH_VERSION_MINOR 8 -#define CATCH_VERSION_PATCH 0 +#define CATCH_VERSION_MINOR 13 +#define CATCH_VERSION_PATCH 7 #ifdef __clang__ # pragma clang system_header @@ -66,13 +66,16 @@ #if !defined(CATCH_CONFIG_IMPL_ONLY) // start catch_platform.h +// See e.g.: +// https://opensource.apple.com/source/CarbonHeaders/CarbonHeaders-18.1/TargetConditionals.h.auto.html #ifdef __APPLE__ -# include -# if TARGET_OS_OSX == 1 -# define CATCH_PLATFORM_MAC -# elif TARGET_OS_IPHONE == 1 -# define CATCH_PLATFORM_IPHONE -# endif +# include +# if (defined(TARGET_OS_OSX) && TARGET_OS_OSX == 1) || \ + (defined(TARGET_OS_MAC) && TARGET_OS_MAC == 1) +# define CATCH_PLATFORM_MAC +# elif (defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE == 1) +# define CATCH_PLATFORM_IPHONE +# endif #elif defined(linux) || defined(__linux) || defined(__linux__) # define CATCH_PLATFORM_LINUX @@ -132,36 +135,51 @@ #endif -#if defined(CATCH_CPP17_OR_GREATER) -# define CATCH_INTERNAL_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS +// Only GCC compiler should be used in this block, so other compilers trying to +// mask themselves as GCC should be ignored. +#if defined(__GNUC__) && !defined(__clang__) && !defined(__ICC) && !defined(__CUDACC__) && !defined(__LCC__) +# define CATCH_INTERNAL_START_WARNINGS_SUPPRESSION _Pragma( "GCC diagnostic push" ) +# define CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION _Pragma( "GCC diagnostic pop" ) + +# define CATCH_INTERNAL_IGNORE_BUT_WARN(...) (void)__builtin_constant_p(__VA_ARGS__) + #endif -#ifdef __clang__ +#if defined(__clang__) + +# define CATCH_INTERNAL_START_WARNINGS_SUPPRESSION _Pragma( "clang diagnostic push" ) +# define CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION _Pragma( "clang diagnostic pop" ) + +// As of this writing, IBM XL's implementation of __builtin_constant_p has a bug +// which results in calls to destructors being emitted for each temporary, +// without a matching initialization. In practice, this can result in something +// like `std::string::~string` being called on an uninitialized value. +// +// For example, this code will likely segfault under IBM XL: +// ``` +// REQUIRE(std::string("12") + "34" == "1234") +// ``` +// +// Therefore, `CATCH_INTERNAL_IGNORE_BUT_WARN` is not implemented. +# if !defined(__ibmxl__) && !defined(__CUDACC__) +# define CATCH_INTERNAL_IGNORE_BUT_WARN(...) (void)__builtin_constant_p(__VA_ARGS__) /* NOLINT(cppcoreguidelines-pro-type-vararg, hicpp-vararg) */ +# endif + +# define CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \ + _Pragma( "clang diagnostic ignored \"-Wexit-time-destructors\"" ) \ + _Pragma( "clang diagnostic ignored \"-Wglobal-constructors\"") + +# define CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS \ + _Pragma( "clang diagnostic ignored \"-Wparentheses\"" ) + +# define CATCH_INTERNAL_SUPPRESS_UNUSED_WARNINGS \ + _Pragma( "clang diagnostic ignored \"-Wunused-variable\"" ) + +# define CATCH_INTERNAL_SUPPRESS_ZERO_VARIADIC_WARNINGS \ + _Pragma( "clang diagnostic ignored \"-Wgnu-zero-variadic-macro-arguments\"" ) -# define CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \ - _Pragma( "clang diagnostic push" ) \ - _Pragma( "clang diagnostic ignored \"-Wexit-time-destructors\"" ) \ - _Pragma( "clang diagnostic ignored \"-Wglobal-constructors\"") -# define CATCH_INTERNAL_UNSUPPRESS_GLOBALS_WARNINGS \ - _Pragma( "clang diagnostic pop" ) - -# define CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS \ - _Pragma( "clang diagnostic push" ) \ - _Pragma( "clang diagnostic ignored \"-Wparentheses\"" ) -# define CATCH_INTERNAL_UNSUPPRESS_PARENTHESES_WARNINGS \ - _Pragma( "clang diagnostic pop" ) - -# define CATCH_INTERNAL_SUPPRESS_UNUSED_WARNINGS \ - _Pragma( "clang diagnostic push" ) \ - _Pragma( "clang diagnostic ignored \"-Wunused-variable\"" ) -# define CATCH_INTERNAL_UNSUPPRESS_UNUSED_WARNINGS \ - _Pragma( "clang diagnostic pop" ) - -# define CATCH_INTERNAL_SUPPRESS_ZERO_VARIADIC_WARNINGS \ - _Pragma( "clang diagnostic push" ) \ - _Pragma( "clang diagnostic ignored \"-Wgnu-zero-variadic-macro-arguments\"" ) -# define CATCH_INTERNAL_UNSUPPRESS_ZERO_VARIADIC_WARNINGS \ - _Pragma( "clang diagnostic pop" ) +# define CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS \ + _Pragma( "clang diagnostic ignored \"-Wunused-template\"" ) #endif // __clang__ @@ -186,6 +204,7 @@ // Android somehow still does not support std::to_string #if defined(__ANDROID__) # define CATCH_INTERNAL_CONFIG_NO_CPP11_TO_STRING +# define CATCH_INTERNAL_CONFIG_ANDROID_LOGWRITE #endif //////////////////////////////////////////////////////////////////////////////// @@ -210,20 +229,19 @@ // some versions of cygwin (most) do not support std::to_string. Use the libstd check. // https://gcc.gnu.org/onlinedocs/gcc-4.8.2/libstdc++/api/a01053_source.html line 2812-2813 # if !((__cplusplus >= 201103L) && defined(_GLIBCXX_USE_C99) \ - && !defined(_GLIBCXX_HAVE_BROKEN_VSWPRINTF)) + && !defined(_GLIBCXX_HAVE_BROKEN_VSWPRINTF)) -# define CATCH_INTERNAL_CONFIG_NO_CPP11_TO_STRING +# define CATCH_INTERNAL_CONFIG_NO_CPP11_TO_STRING # endif #endif // __CYGWIN__ //////////////////////////////////////////////////////////////////////////////// // Visual C++ -#ifdef _MSC_VER +#if defined(_MSC_VER) -# if _MSC_VER >= 1900 // Visual Studio 2015 or newer -# define CATCH_INTERNAL_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS -# endif +# define CATCH_INTERNAL_START_WARNINGS_SUPPRESSION __pragma( warning(push) ) +# define CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION __pragma( warning(pop) ) // Universal Windows platform does not support SEH // Or console colours (or console at all...) @@ -236,10 +254,17 @@ // MSVC traditional preprocessor needs some workaround for __VA_ARGS__ // _MSVC_TRADITIONAL == 0 means new conformant preprocessor // _MSVC_TRADITIONAL == 1 means old traditional non-conformant preprocessor -# if !defined(_MSVC_TRADITIONAL) || (defined(_MSVC_TRADITIONAL) && _MSVC_TRADITIONAL) -# define CATCH_INTERNAL_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR -# endif +# if !defined(__clang__) // Handle Clang masquerading for msvc +# if !defined(_MSVC_TRADITIONAL) || (defined(_MSVC_TRADITIONAL) && _MSVC_TRADITIONAL) +# define CATCH_INTERNAL_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR +# endif // MSVC_TRADITIONAL +# endif // __clang__ + +#endif // _MSC_VER +#if defined(_REENTRANT) || defined(_MSC_VER) +// Enable async processing, as -pthread is specified or no additional linking is required +# define CATCH_INTERNAL_CONFIG_USE_ASYNC #endif // _MSC_VER //////////////////////////////////////////////////////////////////////////////// @@ -272,40 +297,56 @@ #endif //////////////////////////////////////////////////////////////////////////////// -// Check if string_view is available and usable -// The check is split apart to work around v140 (VS2015) preprocessor issue... -#if defined(__has_include) -#if __has_include() && defined(CATCH_CPP17_OR_GREATER) -# define CATCH_INTERNAL_CONFIG_CPP17_STRING_VIEW -#endif + +// RTX is a special version of Windows that is real time. +// This means that it is detected as Windows, but does not provide +// the same set of capabilities as real Windows does. +#if defined(UNDER_RTSS) || defined(RTX64_BUILD) + #define CATCH_INTERNAL_CONFIG_NO_WINDOWS_SEH + #define CATCH_INTERNAL_CONFIG_NO_ASYNC + #define CATCH_CONFIG_COLOUR_NONE #endif -//////////////////////////////////////////////////////////////////////////////// -// Check if optional is available and usable -#if defined(__has_include) -# if __has_include() && defined(CATCH_CPP17_OR_GREATER) -# define CATCH_INTERNAL_CONFIG_CPP17_OPTIONAL -# endif // __has_include() && defined(CATCH_CPP17_OR_GREATER) -#endif // __has_include +#if !defined(_GLIBCXX_USE_C99_MATH_TR1) +#define CATCH_INTERNAL_CONFIG_GLOBAL_NEXTAFTER +#endif -//////////////////////////////////////////////////////////////////////////////// -// Check if variant is available and usable +// Various stdlib support checks that require __has_include #if defined(__has_include) -# if __has_include() && defined(CATCH_CPP17_OR_GREATER) -# if defined(__clang__) && (__clang_major__ < 8) - // work around clang bug with libstdc++ https://bugs.llvm.org/show_bug.cgi?id=31852 - // fix should be in clang 8, workaround in libstdc++ 8.2 -# include -# if defined(__GLIBCXX__) && defined(_GLIBCXX_RELEASE) && (_GLIBCXX_RELEASE < 9) -# define CATCH_CONFIG_NO_CPP17_VARIANT -# else -# define CATCH_INTERNAL_CONFIG_CPP17_VARIANT -# endif // defined(__GLIBCXX__) && defined(_GLIBCXX_RELEASE) && (_GLIBCXX_RELEASE < 9) -# else -# define CATCH_INTERNAL_CONFIG_CPP17_VARIANT -# endif // defined(__clang__) && (__clang_major__ < 8) -# endif // __has_include() && defined(CATCH_CPP17_OR_GREATER) -#endif // __has_include + // Check if string_view is available and usable + #if __has_include() && defined(CATCH_CPP17_OR_GREATER) + # define CATCH_INTERNAL_CONFIG_CPP17_STRING_VIEW + #endif + + // Check if optional is available and usable + # if __has_include() && defined(CATCH_CPP17_OR_GREATER) + # define CATCH_INTERNAL_CONFIG_CPP17_OPTIONAL + # endif // __has_include() && defined(CATCH_CPP17_OR_GREATER) + + // Check if byte is available and usable + # if __has_include() && defined(CATCH_CPP17_OR_GREATER) + # include + # if defined(__cpp_lib_byte) && (__cpp_lib_byte > 0) + # define CATCH_INTERNAL_CONFIG_CPP17_BYTE + # endif + # endif // __has_include() && defined(CATCH_CPP17_OR_GREATER) + + // Check if variant is available and usable + # if __has_include() && defined(CATCH_CPP17_OR_GREATER) + # if defined(__clang__) && (__clang_major__ < 8) + // work around clang bug with libstdc++ https://bugs.llvm.org/show_bug.cgi?id=31852 + // fix should be in clang 8, workaround in libstdc++ 8.2 + # include + # if defined(__GLIBCXX__) && defined(_GLIBCXX_RELEASE) && (_GLIBCXX_RELEASE < 9) + # define CATCH_CONFIG_NO_CPP17_VARIANT + # else + # define CATCH_INTERNAL_CONFIG_CPP17_VARIANT + # endif // defined(__GLIBCXX__) && defined(_GLIBCXX_RELEASE) && (_GLIBCXX_RELEASE < 9) + # else + # define CATCH_INTERNAL_CONFIG_CPP17_VARIANT + # endif // defined(__clang__) && (__clang_major__ < 8) + # endif // __has_include() && defined(CATCH_CPP17_OR_GREATER) +#endif // defined(__has_include) #if defined(CATCH_INTERNAL_CONFIG_COUNTER) && !defined(CATCH_CONFIG_NO_COUNTER) && !defined(CATCH_CONFIG_COUNTER) # define CATCH_CONFIG_COUNTER @@ -330,10 +371,6 @@ # define CATCH_CONFIG_CPP17_OPTIONAL #endif -#if defined(CATCH_INTERNAL_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS) && !defined(CATCH_CONFIG_NO_CPP17_UNCAUGHT_EXCEPTIONS) && !defined(CATCH_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS) -# define CATCH_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS -#endif - #if defined(CATCH_INTERNAL_CONFIG_CPP17_STRING_VIEW) && !defined(CATCH_CONFIG_NO_CPP17_STRING_VIEW) && !defined(CATCH_CONFIG_CPP17_STRING_VIEW) # define CATCH_CONFIG_CPP17_STRING_VIEW #endif @@ -342,6 +379,10 @@ # define CATCH_CONFIG_CPP17_VARIANT #endif +#if defined(CATCH_INTERNAL_CONFIG_CPP17_BYTE) && !defined(CATCH_CONFIG_NO_CPP17_BYTE) && !defined(CATCH_CONFIG_CPP17_BYTE) +# define CATCH_CONFIG_CPP17_BYTE +#endif + #if defined(CATCH_CONFIG_EXPERIMENTAL_REDIRECT) # define CATCH_INTERNAL_CONFIG_NEW_CAPTURE #endif @@ -358,21 +399,53 @@ # define CATCH_CONFIG_POLYFILL_ISNAN #endif +#if defined(CATCH_INTERNAL_CONFIG_USE_ASYNC) && !defined(CATCH_INTERNAL_CONFIG_NO_ASYNC) && !defined(CATCH_CONFIG_NO_USE_ASYNC) && !defined(CATCH_CONFIG_USE_ASYNC) +# define CATCH_CONFIG_USE_ASYNC +#endif + +#if defined(CATCH_INTERNAL_CONFIG_ANDROID_LOGWRITE) && !defined(CATCH_CONFIG_NO_ANDROID_LOGWRITE) && !defined(CATCH_CONFIG_ANDROID_LOGWRITE) +# define CATCH_CONFIG_ANDROID_LOGWRITE +#endif + +#if defined(CATCH_INTERNAL_CONFIG_GLOBAL_NEXTAFTER) && !defined(CATCH_CONFIG_NO_GLOBAL_NEXTAFTER) && !defined(CATCH_CONFIG_GLOBAL_NEXTAFTER) +# define CATCH_CONFIG_GLOBAL_NEXTAFTER +#endif + +// Even if we do not think the compiler has that warning, we still have +// to provide a macro that can be used by the code. +#if !defined(CATCH_INTERNAL_START_WARNINGS_SUPPRESSION) +# define CATCH_INTERNAL_START_WARNINGS_SUPPRESSION +#endif +#if !defined(CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION) +# define CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION +#endif #if !defined(CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS) # define CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS -# define CATCH_INTERNAL_UNSUPPRESS_PARENTHESES_WARNINGS #endif #if !defined(CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS) # define CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS -# define CATCH_INTERNAL_UNSUPPRESS_GLOBALS_WARNINGS #endif #if !defined(CATCH_INTERNAL_SUPPRESS_UNUSED_WARNINGS) # define CATCH_INTERNAL_SUPPRESS_UNUSED_WARNINGS -# define CATCH_INTERNAL_UNSUPPRESS_UNUSED_WARNINGS #endif #if !defined(CATCH_INTERNAL_SUPPRESS_ZERO_VARIADIC_WARNINGS) # define CATCH_INTERNAL_SUPPRESS_ZERO_VARIADIC_WARNINGS -# define CATCH_INTERNAL_UNSUPPRESS_ZERO_VARIADIC_WARNINGS +#endif + +// The goal of this macro is to avoid evaluation of the arguments, but +// still have the compiler warn on problems inside... +#if !defined(CATCH_INTERNAL_IGNORE_BUT_WARN) +# define CATCH_INTERNAL_IGNORE_BUT_WARN(...) +#endif + +#if defined(__APPLE__) && defined(__apple_build_version__) && (__clang_major__ < 10) +# undef CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS +#elif defined(__clang__) && (__clang_major__ < 5) +# undef CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS +#endif + +#if !defined(CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS) +# define CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS #endif #if defined(CATCH_CONFIG_DISABLE_EXCEPTIONS) @@ -437,7 +510,7 @@ SourceLineInfo( SourceLineInfo&& ) noexcept = default; SourceLineInfo& operator = ( SourceLineInfo&& ) noexcept = default; - bool empty() const noexcept; + bool empty() const noexcept { return file[0] == '\0'; } bool operator == ( SourceLineInfo const& other ) const noexcept; bool operator < ( SourceLineInfo const& other ) const noexcept; @@ -478,9 +551,10 @@ } // end namespace Catch #define CATCH_REGISTER_TAG_ALIAS( alias, spec ) \ + CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \ CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \ namespace{ Catch::RegistrarForTagAliases INTERNAL_CATCH_UNIQUE_NAME( AutoRegisterTagAlias )( alias, spec, CATCH_INTERNAL_LINEINFO ); } \ - CATCH_INTERNAL_UNSUPPRESS_GLOBALS_WARNINGS + CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION // end catch_tag_alias_autoregistrar.h // start catch_test_registry.h @@ -507,6 +581,7 @@ virtual std::vector const& getAllTestsSorted( IConfig const& config ) const = 0; }; + bool isThrowSafe( TestCase const& testCase, IConfig const& config ); bool matchTest( TestCase const& testCase, TestSpec const& testSpec, IConfig const& config ); std::vector filterTests( std::vector const& testCases, TestSpec const& testSpec, IConfig const& config ); std::vector const& getAllTestCasesSorted( IConfig const& config ); @@ -519,53 +594,30 @@ #include #include #include +#include namespace Catch { /// A non-owning string class (similar to the forthcoming std::string_view) /// Note that, because a StringRef may be a substring of another string, - /// it may not be null terminated. c_str() must return a null terminated - /// string, however, and so the StringRef will internally take ownership - /// (taking a copy), if necessary. In theory this ownership is not externally - /// visible - but it does mean (substring) StringRefs should not be shared between - /// threads. + /// it may not be null terminated. class StringRef { public: using size_type = std::size_t; + using const_iterator = const char*; private: - friend struct StringRefTestAccess; - - char const* m_start; - size_type m_size; - - char* m_data = nullptr; - - void takeOwnership(); - static constexpr char const* const s_empty = ""; - public: // construction/ assignment - StringRef() noexcept - : StringRef( s_empty, 0 ) - {} - - StringRef( StringRef const& other ) noexcept - : m_start( other.m_start ), - m_size( other.m_size ) - {} + char const* m_start = s_empty; + size_type m_size = 0; - StringRef( StringRef&& other ) noexcept - : m_start( other.m_start ), - m_size( other.m_size ), - m_data( other.m_data ) - { - other.m_data = nullptr; - } + public: // construction + constexpr StringRef() noexcept = default; StringRef( char const* rawChars ) noexcept; - StringRef( char const* rawChars, size_type size ) noexcept + constexpr StringRef( char const* rawChars, size_type size ) noexcept : m_start( rawChars ), m_size( size ) {} @@ -575,101 +627,64 @@ m_size( stdString.size() ) {} - ~StringRef() noexcept { - delete[] m_data; - } - - auto operator = ( StringRef const &other ) noexcept -> StringRef& { - delete[] m_data; - m_data = nullptr; - m_start = other.m_start; - m_size = other.m_size; - return *this; + explicit operator std::string() const { + return std::string(m_start, m_size); } - operator std::string() const; - - void swap( StringRef& other ) noexcept; - public: // operators auto operator == ( StringRef const& other ) const noexcept -> bool; - auto operator != ( StringRef const& other ) const noexcept -> bool; + auto operator != (StringRef const& other) const noexcept -> bool { + return !(*this == other); + } - auto operator[] ( size_type index ) const noexcept -> char; + auto operator[] ( size_type index ) const noexcept -> char { + assert(index < m_size); + return m_start[index]; + } public: // named queries - auto empty() const noexcept -> bool { + constexpr auto empty() const noexcept -> bool { return m_size == 0; } - auto size() const noexcept -> size_type { + constexpr auto size() const noexcept -> size_type { return m_size; } - auto numberOfCharacters() const noexcept -> size_type; + // Returns the current start pointer. If the StringRef is not + // null-terminated, throws std::domain_exception auto c_str() const -> char const*; public: // substrings and searches - auto substr( size_type start, size_type size ) const noexcept -> StringRef; + // Returns a substring of [start, start + length). + // If start + length > size(), then the substring is [start, size()). + // If start > size(), then the substring is empty. + auto substr( size_type start, size_type length ) const noexcept -> StringRef; - // Returns the current start pointer. - // Note that the pointer can change when if the StringRef is a substring - auto currentData() const noexcept -> char const*; + // Returns the current start pointer. May not be null-terminated. + auto data() const noexcept -> char const*; - private: // ownership queries - may not be consistent between calls - auto isOwned() const noexcept -> bool; - auto isSubstring() const noexcept -> bool; - }; + constexpr auto isNullTerminated() const noexcept -> bool { + return m_start[m_size] == '\0'; + } - auto operator + ( StringRef const& lhs, StringRef const& rhs ) -> std::string; - auto operator + ( StringRef const& lhs, char const* rhs ) -> std::string; - auto operator + ( char const* lhs, StringRef const& rhs ) -> std::string; + public: // iterators + constexpr const_iterator begin() const { return m_start; } + constexpr const_iterator end() const { return m_start + m_size; } + }; auto operator += ( std::string& lhs, StringRef const& sr ) -> std::string&; auto operator << ( std::ostream& os, StringRef const& sr ) -> std::ostream&; - inline auto operator "" _sr( char const* rawChars, std::size_t size ) noexcept -> StringRef { + constexpr auto operator "" _sr( char const* rawChars, std::size_t size ) noexcept -> StringRef { return StringRef( rawChars, size ); } - } // namespace Catch -inline auto operator "" _catch_sr( char const* rawChars, std::size_t size ) noexcept -> Catch::StringRef { +constexpr auto operator "" _catch_sr( char const* rawChars, std::size_t size ) noexcept -> Catch::StringRef { return Catch::StringRef( rawChars, size ); } // end catch_stringref.h -// start catch_type_traits.hpp - - -#include - -namespace Catch{ - -#ifdef CATCH_CPP17_OR_GREATER - template - inline constexpr auto is_unique = std::true_type{}; - - template - inline constexpr auto is_unique = std::bool_constant< - (!std::is_same_v && ...) && is_unique - >{}; -#else - -template -struct is_unique : std::true_type{}; - -template -struct is_unique : std::integral_constant -::value - && is_unique::value - && is_unique::value ->{}; - -#endif -} - -// end catch_type_traits.hpp // start catch_preprocessor.hpp @@ -754,7 +769,7 @@ #define INTERNAL_CATCH_REMOVE_PARENS_4_ARG(_0, _1, _2, _3) INTERNAL_CATCH_REMOVE_PARENS(_0), INTERNAL_CATCH_REMOVE_PARENS_3_ARG(_1, _2, _3) #define INTERNAL_CATCH_REMOVE_PARENS_5_ARG(_0, _1, _2, _3, _4) INTERNAL_CATCH_REMOVE_PARENS(_0), INTERNAL_CATCH_REMOVE_PARENS_4_ARG(_1, _2, _3, _4) #define INTERNAL_CATCH_REMOVE_PARENS_6_ARG(_0, _1, _2, _3, _4, _5) INTERNAL_CATCH_REMOVE_PARENS(_0), INTERNAL_CATCH_REMOVE_PARENS_5_ARG(_1, _2, _3, _4, _5) -#define INTERNAL_CATCH_REMOVE_PARENS_7_ARG(_0, _1, _2, _3, _4, _5, _6) INTERNAL_CATCH_REMOVE_PARENS(_0), INTERNAL_CATCH_REMOVE_PARENS_6_ARG(_1, _2, _4, _5, _6) +#define INTERNAL_CATCH_REMOVE_PARENS_7_ARG(_0, _1, _2, _3, _4, _5, _6) INTERNAL_CATCH_REMOVE_PARENS(_0), INTERNAL_CATCH_REMOVE_PARENS_6_ARG(_1, _2, _3, _4, _5, _6) #define INTERNAL_CATCH_REMOVE_PARENS_8_ARG(_0, _1, _2, _3, _4, _5, _6, _7) INTERNAL_CATCH_REMOVE_PARENS(_0), INTERNAL_CATCH_REMOVE_PARENS_7_ARG(_1, _2, _3, _4, _5, _6, _7) #define INTERNAL_CATCH_REMOVE_PARENS_9_ARG(_0, _1, _2, _3, _4, _5, _6, _7, _8) INTERNAL_CATCH_REMOVE_PARENS(_0), INTERNAL_CATCH_REMOVE_PARENS_8_ARG(_1, _2, _3, _4, _5, _6, _7, _8) #define INTERNAL_CATCH_REMOVE_PARENS_10_ARG(_0, _1, _2, _3, _4, _5, _6, _7, _8, _9) INTERNAL_CATCH_REMOVE_PARENS(_0), INTERNAL_CATCH_REMOVE_PARENS_9_ARG(_1, _2, _3, _4, _5, _6, _7, _8, _9) @@ -766,31 +781,49 @@ template struct TypeList {};\ template\ constexpr auto get_wrapper() noexcept -> TypeList { return {}; }\ + template class...> struct TemplateTypeList{};\ + template class...Cs>\ + constexpr auto get_wrapper() noexcept -> TemplateTypeList { return {}; }\ + template\ + struct append;\ + template\ + struct rewrap;\ + template class, typename...>\ + struct create;\ + template class, typename>\ + struct convert;\ \ - template class L1, typename...E1, template class L2, typename...E2> \ - constexpr auto append(L1, L2) noexcept -> L1 { return {}; }\ + template \ + struct append { using type = T; };\ template< template class L1, typename...E1, template class L2, typename...E2, typename...Rest>\ - constexpr auto append(L1, L2, Rest...) noexcept -> decltype(append(L1{}, Rest{}...)) { return {}; }\ + struct append, L2, Rest...> { using type = typename append, Rest...>::type; };\ + template< template class L1, typename...E1, typename...Rest>\ + struct append, TypeList, Rest...> { using type = L1; };\ \ template< template class Container, template class List, typename...elems>\ - constexpr auto rewrap(List) noexcept -> TypeList> { return {}; }\ + struct rewrap, List> { using type = TypeList>; };\ template< template class Container, template class List, class...Elems, typename...Elements>\ - constexpr auto rewrap(List,Elements...) noexcept -> decltype(append(TypeList>{}, rewrap(Elements{}...))) { return {}; }\ + struct rewrap, List, Elements...> { using type = typename append>, typename rewrap, Elements...>::type>::type; };\ \ template