Compare commits
	
		
			10 Commits
		
	
	
		
			37b847692e
			...
			5ebfc92730
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
|   | 5ebfc92730 | ||
|   | 885b5473e2 | ||
|   | d276069a6e | ||
|   | eeb22c13bb | ||
|   | c3aed4b683 | ||
|   | 27cb4c7670 | ||
|   | 2d4acf8cc3 | ||
|   | 3b4fd93bd0 | ||
|   | 2122eb2194 | ||
|   | 22b0f4fc06 | 
| @@ -34,7 +34,7 @@ elseif(NOT CMAKE_CXX_STANDARD) | ||||
| endif() | ||||
|  | ||||
| # make sure __cplusplus is defined when using msvc and enable parallel build | ||||
| if(MSVC) | ||||
| if(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC") | ||||
|     string(APPEND CMAKE_CXX_FLAGS " /Zc:__cplusplus /MP") | ||||
| endif() | ||||
|  | ||||
| @@ -108,9 +108,11 @@ endif() | ||||
| if(WIN32) | ||||
|     option(SPDLOG_WCHAR_SUPPORT "Support wchar api" OFF) | ||||
|     option(SPDLOG_WCHAR_FILENAMES "Support wchar filenames" OFF) | ||||
|     option(SPDLOG_WCHAR_CONSOLE "Support wchar output to console" OFF) | ||||
| else() | ||||
|     set(SPDLOG_WCHAR_SUPPORT OFF CACHE BOOL "non supported option" FORCE) | ||||
|     set(SPDLOG_WCHAR_FILENAMES OFF CACHE BOOL "non supported option" FORCE) | ||||
|     set(SPDLOG_WCHAR_CONSOLE OFF CACHE BOOL "non supported option" FORCE) | ||||
| endif() | ||||
|  | ||||
| if(${CMAKE_SYSTEM_NAME} STREQUAL "Linux") | ||||
| @@ -159,7 +161,7 @@ if(SPDLOG_BUILD_SHARED OR BUILD_SHARED_LIBS) | ||||
|     endif() | ||||
|     add_library(spdlog SHARED ${SPDLOG_SRCS} ${SPDLOG_ALL_HEADERS}) | ||||
|     target_compile_definitions(spdlog PUBLIC SPDLOG_SHARED_LIB) | ||||
|     if(MSVC) | ||||
|     if(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC") | ||||
|         target_compile_options(spdlog PUBLIC $<$<AND:$<CXX_COMPILER_ID:MSVC>,$<NOT:$<COMPILE_LANGUAGE:CUDA>>>:/wd4251 | ||||
|                                              /wd4275>) | ||||
|     endif() | ||||
| @@ -237,9 +239,11 @@ endif() | ||||
| # Misc definitions according to tweak options | ||||
| # --------------------------------------------------------------------------------------- | ||||
| set(SPDLOG_WCHAR_TO_UTF8_SUPPORT ${SPDLOG_WCHAR_SUPPORT}) | ||||
| set(SPDLOG_UTF8_TO_WCHAR_CONSOLE ${SPDLOG_WCHAR_CONSOLE}) | ||||
| foreach( | ||||
|     SPDLOG_OPTION | ||||
|     SPDLOG_WCHAR_TO_UTF8_SUPPORT | ||||
|     SPDLOG_UTF8_TO_WCHAR_CONSOLE | ||||
|     SPDLOG_WCHAR_FILENAMES | ||||
|     SPDLOG_NO_EXCEPTIONS | ||||
|     SPDLOG_CLOCK_COARSE | ||||
|   | ||||
							
								
								
									
										15
									
								
								README.md
									
									
									
									
									
								
							
							
						
						
									
										15
									
								
								README.md
									
									
									
									
									
								
							| @@ -437,7 +437,22 @@ MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) | ||||
|     logger->info("Some info message"); | ||||
| } | ||||
| ``` | ||||
| --- | ||||
|  | ||||
| #### Mapped Diagnostic Context | ||||
| ```c++ | ||||
| // Mapped Diagnostic Context (MDC) is a map that stores key-value pairs (string values) in thread local storage. | ||||
| // Each thread maintains its own MDC, which loggers use to append diagnostic information to log outputs. | ||||
| // Note: it is not supported in asynchronous mode due to its reliance on thread-local storage. | ||||
| #include "spdlog/mdc.h" | ||||
| void mdc_example() | ||||
| { | ||||
|     spdlog::mdc::put("key1", "value1"); | ||||
|     spdlog::mdc::put("key2", "value2"); | ||||
|     // if not using the default format, use the %& formatter to print mdc data | ||||
|     // spdlog::set_pattern("[%H:%M:%S %z] [%^%L%$] [%&] %v"); | ||||
| } | ||||
| ``` | ||||
| --- | ||||
| ## Benchmarks | ||||
|  | ||||
|   | ||||
| @@ -26,6 +26,7 @@ void udp_example(); | ||||
| void custom_flags_example(); | ||||
| void file_events_example(); | ||||
| void replace_default_logger_example(); | ||||
| void mdc_example(); | ||||
|  | ||||
| #include "spdlog/spdlog.h" | ||||
| #include "spdlog/cfg/env.h"   // support for loading levels from the environment variable | ||||
| @@ -84,6 +85,7 @@ int main(int, char *[]) { | ||||
|         custom_flags_example(); | ||||
|         file_events_example(); | ||||
|         replace_default_logger_example(); | ||||
|         mdc_example(); | ||||
|  | ||||
|         // Flush all *registered* loggers using a worker thread every 3 seconds. | ||||
|         // note: registered loggers *must* be thread safe for this to work correctly! | ||||
| @@ -270,7 +272,7 @@ struct my_type { | ||||
| #ifndef SPDLOG_USE_STD_FORMAT  // when using fmtlib | ||||
| template <> | ||||
| struct fmt::formatter<my_type> : fmt::formatter<std::string> { | ||||
|     auto format(my_type my, format_context &ctx) -> decltype(ctx.out()) { | ||||
|     auto format(my_type my, format_context &ctx) const -> decltype(ctx.out()) { | ||||
|         return fmt::format_to(ctx.out(), "[my_type i={}]", my.i); | ||||
|     } | ||||
| }; | ||||
| @@ -376,3 +378,16 @@ void replace_default_logger_example() { | ||||
|  | ||||
|     spdlog::set_default_logger(old_logger); | ||||
| } | ||||
|  | ||||
| // Mapped Diagnostic Context (MDC) is a map that stores key-value pairs (string values) in thread local storage. | ||||
| // Each thread maintains its own MDC, which loggers use to append diagnostic information to log outputs. | ||||
| // Note: it is not supported in asynchronous mode due to its reliance on thread-local storage. | ||||
| #include "spdlog/mdc.h" | ||||
| void mdc_example() | ||||
| { | ||||
|     spdlog::mdc::put("key1", "value1"); | ||||
|     spdlog::mdc::put("key2", "value2"); | ||||
|     // if not using the default format, you can use the %& formatter to print mdc data as well | ||||
|     spdlog::set_pattern("[%H:%M:%S %z] [%^%L%$] [%&] %v"); | ||||
|     spdlog::info("Some log message with context"); | ||||
| } | ||||
|   | ||||
| @@ -81,7 +81,7 @@ | ||||
|     #if FMT_USE_CONSTEXPR | ||||
|         #define SPDLOG_CONSTEXPR_FUNC FMT_CONSTEXPR | ||||
|     #else | ||||
| 	#define SPDLOG_CONSTEXPR_FUNC inline | ||||
|         #define SPDLOG_CONSTEXPR_FUNC inline | ||||
|     #endif | ||||
| #endif | ||||
|  | ||||
|   | ||||
| @@ -98,7 +98,7 @@ SPDLOG_INLINE void file_helper::close() { | ||||
| } | ||||
|  | ||||
| SPDLOG_INLINE void file_helper::write(const memory_buf_t &buf) { | ||||
|     if(fd_ == nullptr) return; | ||||
|     if (fd_ == nullptr) return; | ||||
|     size_t msg_size = buf.size(); | ||||
|     auto data = buf.data(); | ||||
|     if (std::fwrite(data, 1, msg_size, fd_) != msg_size) { | ||||
|   | ||||
| @@ -535,7 +535,7 @@ SPDLOG_INLINE bool create_dir(const filename_t &path) { | ||||
|  | ||||
|         auto subdir = path.substr(0, token_pos); | ||||
| #ifdef _WIN32 | ||||
|         // if subdir is just a drive letter, add a slash e.g. "c:"=>"c:\",  | ||||
|         // if subdir is just a drive letter, add a slash e.g. "c:"=>"c:\", | ||||
|         // otherwise path_exists(subdir) returns false (issue #3079) | ||||
|         const bool is_drive = subdir.length() == 2 && subdir[1] == ':'; | ||||
|         if (is_drive) { | ||||
|   | ||||
| @@ -84,7 +84,6 @@ SPDLOG_INLINE std::shared_ptr<logger> registry::get(const std::string &logger_na | ||||
|     return found == loggers_.end() ? nullptr : found->second; | ||||
| } | ||||
|  | ||||
|  | ||||
| SPDLOG_INLINE std::shared_ptr<logger> registry::default_logger() { | ||||
|     std::lock_guard<std::mutex> lock(logger_map_mutex_); | ||||
|     return default_logger_; | ||||
| @@ -99,7 +98,7 @@ SPDLOG_INLINE logger *registry::get_default_raw() { return default_logger_.get() | ||||
| // set default logger. | ||||
| // default logger is stored in default_logger_ (for faster retrieval) and in the loggers_ map. | ||||
| SPDLOG_INLINE void registry::set_default_logger(std::shared_ptr<logger> new_default_logger) { | ||||
|     std::lock_guard<std::mutex> lock(logger_map_mutex_);     | ||||
|     std::lock_guard<std::mutex> lock(logger_map_mutex_); | ||||
|     if (new_default_logger != nullptr) { | ||||
|         loggers_[new_default_logger->name()] = new_default_logger; | ||||
|     } | ||||
|   | ||||
| @@ -44,7 +44,8 @@ public: | ||||
|  | ||||
|     // set default logger and add it to the registry if not registered already. | ||||
|     // default logger is stored in default_logger_ (for faster retrieval) and in the loggers_ map. | ||||
|     // Note: Make sure to unregister it when no longer needed or before calling again with a new logger. | ||||
|     // Note: Make sure to unregister it when no longer needed or before calling again with a new | ||||
|     // logger. | ||||
|     void set_default_logger(std::shared_ptr<logger> new_default_logger); | ||||
|  | ||||
|     void set_tp(std::shared_ptr<thread_pool> tp); | ||||
| @@ -70,8 +71,8 @@ public: | ||||
|     } | ||||
|  | ||||
|     std::unique_ptr<periodic_worker> &get_flusher() { | ||||
|         std::lock_guard<std::mutex> lock(flusher_mutex_);  | ||||
|         return periodic_flusher_;  | ||||
|         std::lock_guard<std::mutex> lock(flusher_mutex_); | ||||
|         return periodic_flusher_; | ||||
|     } | ||||
|  | ||||
|     void set_error_handler(err_handler handler); | ||||
|   | ||||
| @@ -67,9 +67,7 @@ struct async_msg : log_msg_buffer { | ||||
|           worker_ptr{std::move(worker)}, | ||||
|           flush_promise{} {} | ||||
|  | ||||
|     async_msg(async_logger_ptr &&worker, | ||||
|               async_msg_type the_type, | ||||
|               std::promise<void> &&promise) | ||||
|     async_msg(async_logger_ptr &&worker, async_msg_type the_type, std::promise<void> &&promise) | ||||
|         : log_msg_buffer{}, | ||||
|           msg_type{the_type}, | ||||
|           worker_ptr{std::move(worker)}, | ||||
|   | ||||
| @@ -20,7 +20,7 @@ | ||||
|     #ifndef FMT_USE_WINDOWS_H | ||||
|         #define FMT_USE_WINDOWS_H 0 | ||||
|     #endif | ||||
|      | ||||
|  | ||||
|     #include <spdlog/fmt/bundled/core.h> | ||||
|     #include <spdlog/fmt/bundled/format.h> | ||||
|  | ||||
|   | ||||
| @@ -1,3 +1,6 @@ | ||||
| // Copyright(c) 2015-present, Gabi Melman & spdlog contributors. | ||||
| // Distributed under the MIT License (http://opensource.org/licenses/MIT) | ||||
|  | ||||
| #pragma once | ||||
|  | ||||
| #include <map> | ||||
| @@ -5,32 +8,39 @@ | ||||
|  | ||||
| #include <spdlog/common.h> | ||||
|  | ||||
| // MDC is a simple map of key->string values stored in thread local storage whose content will be printed by the loggers. | ||||
| // Note: Not supported in async mode (thread local storage - so the async thread pool have different copy). | ||||
| // | ||||
| // Usage example: | ||||
| // spdlog::mdc::put("mdc_key_1", "mdc_value_1"); | ||||
| // spdlog::info("Hello, {}", "World!");  // => [2024-04-26 02:08:05.040] [info] [mdc_key_1:mdc_value_1] Hello, World! | ||||
|  | ||||
| namespace spdlog { | ||||
|     class SPDLOG_API mdc { | ||||
|     public: | ||||
|         using mdc_map_t = std::map<std::string, std::string>; | ||||
| class SPDLOG_API mdc { | ||||
| public: | ||||
|     using mdc_map_t = std::map<std::string, std::string>; | ||||
|  | ||||
|         static void put(const std::string &key, const std::string &value) { | ||||
|             get_context()[key] = value; | ||||
|     static void put(const std::string &key, const std::string &value) { | ||||
|         get_context()[key] = value; | ||||
|     } | ||||
|  | ||||
|     static std::string get(const std::string &key) { | ||||
|         auto &context = get_context(); | ||||
|         auto it = context.find(key); | ||||
|         if (it != context.end()) { | ||||
|             return it->second; | ||||
|         } | ||||
|         return ""; | ||||
|     } | ||||
|  | ||||
|         static std::string get(const std::string &key) { | ||||
|             auto &context = get_context(); | ||||
|             auto it = context.find(key); | ||||
|             if (it != context.end()) { | ||||
|                 return it->second; | ||||
|             } | ||||
|             return ""; | ||||
|         } | ||||
|     static void remove(const std::string &key) { get_context().erase(key); } | ||||
|  | ||||
|         static void remove(const std::string &key) { get_context().erase(key); } | ||||
|     static void clear() { get_context().clear(); } | ||||
|  | ||||
|         static void clear() { get_context().clear(); } | ||||
|  | ||||
|         static mdc_map_t &get_context() { | ||||
|             static thread_local mdc_map_t context; | ||||
|             return context; | ||||
|         } | ||||
|     }; | ||||
|     static mdc_map_t &get_context() { | ||||
|         static thread_local mdc_map_t context; | ||||
|         return context; | ||||
|     } | ||||
| }; | ||||
|  | ||||
| }  // namespace spdlog | ||||
|   | ||||
| @@ -790,7 +790,7 @@ template <typename ScopedPadder> | ||||
| class mdc_formatter : public flag_formatter { | ||||
| public: | ||||
|     explicit mdc_formatter(padding_info padinfo) | ||||
|             : flag_formatter(padinfo) {} | ||||
|         : flag_formatter(padinfo) {} | ||||
|  | ||||
|     void format(const details::log_msg &, const std::tm &, memory_buf_t &dest) override { | ||||
|         auto &mdc_map = mdc::get_context(); | ||||
| @@ -802,7 +802,7 @@ public: | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     void format_mdc(const mdc::mdc_map_t &mdc_map, memory_buf_t &dest){ | ||||
|     void format_mdc(const mdc::mdc_map_t &mdc_map, memory_buf_t &dest) { | ||||
|         auto last_element = --mdc_map.end(); | ||||
|         for (auto it = mdc_map.begin(); it != mdc_map.end(); ++it) { | ||||
|             auto &pair = *it; | ||||
| @@ -825,8 +825,6 @@ public: | ||||
|     } | ||||
| }; | ||||
|  | ||||
|  | ||||
|  | ||||
| // Full info formatter | ||||
| // pattern: [%Y-%m-%d %H:%M:%S.%e] [%n] [%l] [%s:%#] %v | ||||
| class full_formatter final : public flag_formatter { | ||||
| @@ -921,8 +919,6 @@ private: | ||||
|     mdc_formatter<null_scoped_padder> mdc_formatter_{padding_info{}}; | ||||
| }; | ||||
|  | ||||
|  | ||||
|  | ||||
| }  // namespace details | ||||
|  | ||||
| SPDLOG_INLINE pattern_formatter::pattern_formatter(std::string pattern, | ||||
|   | ||||
| @@ -60,7 +60,7 @@ SPDLOG_INLINE filename_t rotating_file_sink<Mutex>::calc_filename(const filename | ||||
|  | ||||
|     filename_t basename, ext; | ||||
|     std::tie(basename, ext) = details::file_helper::split_by_extension(filename); | ||||
|     return fmt_lib::format(SPDLOG_FILENAME_T("{}.{}{}"), basename, index, ext); | ||||
|     return fmt_lib::format(SPDLOG_FMT_STRING(SPDLOG_FILENAME_T("{}.{}{}")), basename, index, ext); | ||||
| } | ||||
|  | ||||
| template <typename Mutex> | ||||
|   | ||||
| @@ -64,13 +64,14 @@ protected: | ||||
|     // | ||||
|     // Simply maps spdlog's log level to syslog priority level. | ||||
|     // | ||||
|     int syslog_prio_from_level(const details::log_msg &msg) const { | ||||
|     virtual int syslog_prio_from_level(const details::log_msg &msg) const { | ||||
|         return syslog_levels_.at(static_cast<levels_array::size_type>(msg.level)); | ||||
|     } | ||||
|  | ||||
| private: | ||||
|     using levels_array = std::array<int, 7>; | ||||
|     levels_array syslog_levels_; | ||||
|  | ||||
| private: | ||||
|     // must store the ident because the man says openlog might use the pointer as | ||||
|     // is and not a string copy | ||||
|     const std::string ident_; | ||||
|   | ||||
| @@ -134,9 +134,18 @@ void SPDLOG_INLINE wincolor_sink<ConsoleMutex>::print_range_(const memory_buf_t | ||||
|                                                              size_t start, | ||||
|                                                              size_t end) { | ||||
|     if (end > start) { | ||||
| #if defined(SPDLOG_UTF8_TO_WCHAR_CONSOLE) | ||||
|         wmemory_buf_t wformatted; | ||||
|         details::os::utf8_to_wstrbuf(string_view_t(formatted.data() + start, end - start), | ||||
|             wformatted); | ||||
|         auto size = static_cast<DWORD>(wformatted.size()); | ||||
|         auto ignored = ::WriteConsoleW(static_cast<HANDLE>(out_handle_), wformatted.data(), size, | ||||
|             nullptr, nullptr); | ||||
| #else | ||||
|         auto size = static_cast<DWORD>(end - start); | ||||
|         auto ignored = ::WriteConsoleA(static_cast<HANDLE>(out_handle_), formatted.data() + start, | ||||
|                                        size, nullptr, nullptr); | ||||
| #endif | ||||
|         (void)(ignored); | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -20,7 +20,6 @@ SPDLOG_INLINE std::shared_ptr<logger> get(const std::string &name) { | ||||
|     return details::registry::instance().get(name); | ||||
| } | ||||
|  | ||||
|  | ||||
| SPDLOG_INLINE void set_formatter(std::unique_ptr<spdlog::formatter> formatter) { | ||||
|     details::registry::instance().set_formatter(std::move(formatter)); | ||||
| } | ||||
|   | ||||
| @@ -5,7 +5,7 @@ | ||||
|  | ||||
| #define SPDLOG_VER_MAJOR 1 | ||||
| #define SPDLOG_VER_MINOR 14 | ||||
| #define SPDLOG_VER_PATCH 0 | ||||
| #define SPDLOG_VER_PATCH 1 | ||||
|  | ||||
| #define SPDLOG_TO_VERSION(major, minor, patch) (major * 10000 + minor * 100 + patch) | ||||
| #define SPDLOG_VERSION SPDLOG_TO_VERSION(SPDLOG_VER_MAJOR, SPDLOG_VER_MINOR, SPDLOG_VER_PATCH) | ||||
|   | ||||
| @@ -132,8 +132,8 @@ TEST_CASE("multithread flush", "[async]") { | ||||
|     } | ||||
|     REQUIRE(test_sink->flush_counter() >= 1); | ||||
|     REQUIRE(test_sink->flush_counter() + errmsgs.size() == n_threads * flush_count); | ||||
|     if (errmsgs.size() > 0) {  | ||||
|         REQUIRE(errmsgs[0] == "Broken promise");  | ||||
|     if (errmsgs.size() > 0) { | ||||
|         REQUIRE(errmsgs[0] == "Broken promise"); | ||||
|     } | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -84,23 +84,23 @@ TEST_CASE("dir_name", "[create_dir]") { | ||||
|  | ||||
| #ifdef _WIN32 | ||||
|  | ||||
| // | ||||
| // test windows cases when drive letter is given e.g. C:\\some-folder | ||||
| // | ||||
| #include <windows.h> | ||||
| #include <fileapi.h> | ||||
|     // | ||||
|     // test windows cases when drive letter is given e.g. C:\\some-folder | ||||
|     // | ||||
|     #include <windows.h> | ||||
|     #include <fileapi.h> | ||||
|  | ||||
| std::string get_full_path(const std::string &relative_folder_path) { | ||||
|     char full_path[MAX_PATH]; | ||||
|  | ||||
|     DWORD result = ::GetFullPathNameA(relative_folder_path.c_str(), MAX_PATH, full_path, nullptr); | ||||
|     // Return an empty string if failed to get full path | ||||
|     return result > 0 && result < MAX_PATH ? std::string(full_path) : std::string();     | ||||
|     return result > 0 && result < MAX_PATH ? std::string(full_path) : std::string(); | ||||
| } | ||||
|  | ||||
| std::wstring get_full_path(const std::wstring &relative_folder_path) { | ||||
|     wchar_t full_path[MAX_PATH]; | ||||
|     DWORD result = ::GetFullPathNameW(relative_folder_path.c_str(), MAX_PATH, full_path, nullptr);     | ||||
|     DWORD result = ::GetFullPathNameW(relative_folder_path.c_str(), MAX_PATH, full_path, nullptr); | ||||
|     return result > 0 && result < MAX_PATH ? std::wstring(full_path) : std::wstring(); | ||||
| } | ||||
|  | ||||
| @@ -109,16 +109,16 @@ spdlog::filename_t::value_type find_non_existing_drive() { | ||||
|         std::string root_path = std::string(1, drive) + ":\\"; | ||||
|         UINT drive_type = GetDriveTypeA(root_path.c_str()); | ||||
|         if (drive_type == DRIVE_NO_ROOT_DIR) { | ||||
|             return static_cast <spdlog::filename_t::value_type>(drive); | ||||
|             return static_cast<spdlog::filename_t::value_type>(drive); | ||||
|         } | ||||
|     } | ||||
|     return '\0';  // No available drive found | ||||
| } | ||||
|  | ||||
| TEST_CASE("create_abs_path1", "[create_dir]") { | ||||
|     prepare_logdir();     | ||||
|     prepare_logdir(); | ||||
|     auto abs_path = get_full_path(SPDLOG_FILENAME_T("test_logs\\logdir1")); | ||||
|     REQUIRE(!abs_path.empty());             | ||||
|     REQUIRE(!abs_path.empty()); | ||||
|     REQUIRE(create_dir(abs_path) == true); | ||||
| } | ||||
|  | ||||
| @@ -126,20 +126,19 @@ TEST_CASE("create_abs_path2", "[create_dir]") { | ||||
|     prepare_logdir(); | ||||
|     auto abs_path = get_full_path(SPDLOG_FILENAME_T("test_logs/logdir2")); | ||||
|     REQUIRE(!abs_path.empty()); | ||||
|     REQUIRE(create_dir(abs_path) == true);         | ||||
|     REQUIRE(create_dir(abs_path) == true); | ||||
| } | ||||
|  | ||||
| TEST_CASE("non_existing_drive", "[create_dir]") {     | ||||
|     prepare_logdir();         | ||||
| TEST_CASE("non_existing_drive", "[create_dir]") { | ||||
|     prepare_logdir(); | ||||
|     spdlog::filename_t path; | ||||
|      | ||||
|  | ||||
|     auto non_existing_drive = find_non_existing_drive(); | ||||
|     path += non_existing_drive ; | ||||
|     path += SPDLOG_FILENAME_T(":\\");     | ||||
|     REQUIRE(create_dir(path) == false);     | ||||
|     path += non_existing_drive; | ||||
|     path += SPDLOG_FILENAME_T(":\\"); | ||||
|     REQUIRE(create_dir(path) == false); | ||||
|     path += SPDLOG_FILENAME_T("subdir"); | ||||
|     REQUIRE(create_dir(path) == false); | ||||
|              | ||||
| } | ||||
| //#endif  // SPDLOG_WCHAR_FILENAMES | ||||
| // #endif  // SPDLOG_WCHAR_FILENAMES | ||||
| #endif  // _WIN32 | ||||
|   | ||||
		Reference in New Issue
	
	Block a user