diff --git a/.gitignore b/.gitignore index ca7c4606..4d2aace3 100644 --- a/.gitignore +++ b/.gitignore @@ -75,6 +75,8 @@ spdlogConfigVersion.cmake # idea .idea/ +.cache/ +.vscode/ cmake-build-*/ *.db *.ipch diff --git a/INSTALL b/INSTALL index 787bc3fb..afe22193 100644 --- a/INSTALL +++ b/INSTALL @@ -12,7 +12,7 @@ CMake: add_executable(example example.cpp) target_link_libraries(example spdlog::spdlog) -Or copy src/spdlog.cpp to your build tree and pass the -DSPDLOG_COMPILED_LIB to the compiler. +Or copy files src/*.cpp to your build tree and pass the -DSPDLOG_COMPILED_LIB to the compiler. Tested on: gcc 4.8.1 and above diff --git a/README.md b/README.md index 35c03422..6ce32fb6 100644 --- a/README.md +++ b/README.md @@ -293,7 +293,7 @@ void multi_sink_example2() template<> struct fmt::formatter : fmt::formatter { - auto format(my_type my, format_context &ctx) -> decltype(ctx.out()) + auto format(my_type my, format_context &ctx) const -> decltype(ctx.out()) { return format_to(ctx.out(), "[my_type i={}]", my.i); } diff --git a/example/example.cpp b/example/example.cpp index ec31baaa..d6609ed5 100644 --- a/example/example.cpp +++ b/example/example.cpp @@ -31,6 +31,7 @@ void replace_default_logger_example(); #include "spdlog/cfg/env.h" // support for loading levels from the environment variable #include "spdlog/fmt/ostr.h" // support for user defined types + int main(int, char *[]) { // Log levels can be loaded from argv/env using "SPDLOG_LEVEL" @@ -183,6 +184,7 @@ void async_example() // {:p} - don't print the position on each line start. // {:n} - don't split the output to lines. +#if !defined SPDLOG_USE_STD_FORMAT || defined(_MSC_VER) #include "spdlog/fmt/bin_to_hex.h" void binary_example() { @@ -200,6 +202,11 @@ void binary_example() // logger->info("hexdump style: {:a}", spdlog::to_hex(buf)); // logger->info("hexdump style, 20 chars per line {:a}", spdlog::to_hex(buf, 20)); } +#else +void binary_example() { + // not supported with std::format yet +} +#endif // Log a vector of numbers #ifndef SPDLOG_USE_STD_FORMAT @@ -287,7 +294,7 @@ struct fmt::formatter : fmt::formatter template<> struct std::formatter : std::formatter { - auto format(my_type my, format_context &ctx) -> decltype(ctx.out()) + auto format(my_type my, format_context &ctx) const -> decltype(ctx.out()) { return format_to(ctx.out(), "[my_type i={}]", my.i); } diff --git a/include/spdlog/details/tcp_client-windows.h b/include/spdlog/details/tcp_client-windows.h index 9d3647aa..968b2570 100644 --- a/include/spdlog/details/tcp_client-windows.h +++ b/include/spdlog/details/tcp_client-windows.h @@ -83,7 +83,7 @@ public: {}; ZeroMemory(&hints, sizeof(hints)); - hints.ai_family = AF_INET; // IPv4 + hints.ai_family = AF_UNSPEC; // To work with IPv4, IPv6, and so on hints.ai_socktype = SOCK_STREAM; // TCP hints.ai_flags = AI_NUMERICSERV; // port passed as as numeric value hints.ai_protocol = 0; diff --git a/include/spdlog/details/tcp_client.h b/include/spdlog/details/tcp_client.h index e4d7a48e..8b11dfd2 100644 --- a/include/spdlog/details/tcp_client.h +++ b/include/spdlog/details/tcp_client.h @@ -58,7 +58,7 @@ public: struct addrinfo hints {}; memset(&hints, 0, sizeof(struct addrinfo)); - hints.ai_family = AF_INET; // IPv4 + hints.ai_family = AF_UNSPEC; // To work with IPv4, IPv6, and so on hints.ai_socktype = SOCK_STREAM; // TCP hints.ai_flags = AI_NUMERICSERV; // port passed as as numeric value hints.ai_protocol = 0; diff --git a/include/spdlog/details/udp_client.h b/include/spdlog/details/udp_client.h index 2db5b89e..e8c2cccf 100644 --- a/include/spdlog/details/udp_client.h +++ b/include/spdlog/details/udp_client.h @@ -12,7 +12,7 @@ #include #include - +#include #include #include #include diff --git a/include/spdlog/fmt/bin_to_hex.h b/include/spdlog/fmt/bin_to_hex.h index 1cb51ce6..3bf003d4 100644 --- a/include/spdlog/fmt/bin_to_hex.h +++ b/include/spdlog/fmt/bin_to_hex.h @@ -156,7 +156,7 @@ struct formatter, char> // format the given bytes range as hex template - auto format(const spdlog::details::dump_info &the_range, FormatContext &ctx) -> decltype(ctx.out()) + auto format(const spdlog::details::dump_info &the_range, FormatContext &ctx) const -> decltype(ctx.out()) { SPDLOG_CONSTEXPR const char *hex_upper = "0123456789ABCDEF"; SPDLOG_CONSTEXPR const char *hex_lower = "0123456789abcdef"; @@ -232,7 +232,7 @@ struct formatter, char> // put newline(and position header) template - void put_newline(It inserter, std::size_t pos) + void put_newline(It inserter, std::size_t pos) const { #ifdef _WIN32 *inserter++ = '\r'; diff --git a/include/spdlog/sinks/android_sink.h b/include/spdlog/sinks/android_sink.h index 8e79638b..0087e953 100644 --- a/include/spdlog/sinks/android_sink.h +++ b/include/spdlog/sinks/android_sink.h @@ -56,6 +56,10 @@ protected: // See system/core/liblog/logger_write.c for explanation of return value int ret = android_log(priority, tag_.c_str(), msg_output); + if (ret == -EPERM) + { + return; // !__android_log_is_loggable + } int retry_count = 0; while ((ret == -11 /*EAGAIN*/) && (retry_count < SPDLOG_ANDROID_RETRIES)) { diff --git a/include/spdlog/sinks/qt_sinks.h b/include/spdlog/sinks/qt_sinks.h index 14a95bcc..f801ac34 100644 --- a/include/spdlog/sinks/qt_sinks.h +++ b/include/spdlog/sinks/qt_sinks.h @@ -30,10 +30,14 @@ template class qt_sink : public base_sink { public: - qt_sink(QObject *qt_object, const std::string &meta_method) + qt_sink(QObject *qt_object, std::string meta_method) + : qt_object_(qt_object) + , meta_method_(std::move(meta_method)) { - qt_object_ = qt_object; - meta_method_ = meta_method; + if (!qt_object_) + { + throw_spdlog_ex("qt_sink: qt_object is null"); + } } ~qt_sink() @@ -46,7 +50,7 @@ protected: { memory_buf_t formatted; base_sink::formatter_->format(msg, formatted); - string_view_t str = string_view_t(formatted.data(), formatted.size()); + const 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())); } @@ -63,169 +67,165 @@ private: // Colors can be modified if needed using sink->set_color(level, qtTextCharFormat). // max_lines is the maximum number of lines that the sink will hold before removing the oldest lines. // Note: Only ascii (latin1) is supported by this sink. - template - class qt_color_sink : public base_sink +template +class qt_color_sink : public base_sink +{ +public: + qt_color_sink(QTextEdit *qt_text_edit, int max_lines) + : qt_text_edit_(qt_text_edit) + , max_lines_(max_lines) { - public: - qt_color_sink(QTextEdit *qt_text_edit, int max_lines) - : qt_text_edit_(qt_text_edit), max_lines_(max_lines) + if (!qt_text_edit_) { - if (!qt_text_edit_) - { - throw_spdlog_ex("qt_color_text_sink: text_edit is null"); - } - - default_color_ = qt_text_edit_->currentCharFormat(); - // set colors - QTextCharFormat format; - // trace - format.setForeground(Qt::gray); - colors_.at(level::trace) = format; - // debug - format.setForeground(Qt::cyan); - colors_.at(level::debug) = format; - // info - format.setForeground(Qt::green); - colors_.at(level::info) = format; - // warn - format.setForeground(Qt::yellow); - colors_.at(level::warn) = format; - // err - format.setForeground(Qt::red); - colors_.at(level::err) = format; - // critical - format.setForeground(Qt::white); - format.setBackground(Qt::red); - colors_.at(level::critical) = format; + throw_spdlog_ex("qt_color_text_sink: text_edit is null"); } - ~qt_color_sink() - { - flush_(); - } + default_color_ = qt_text_edit_->currentCharFormat(); + // set colors + QTextCharFormat format; + // trace + format.setForeground(Qt::gray); + colors_.at(level::trace) = format; + // debug + format.setForeground(Qt::cyan); + colors_.at(level::debug) = format; + // info + format.setForeground(Qt::green); + colors_.at(level::info) = format; + // warn + format.setForeground(Qt::yellow); + colors_.at(level::warn) = format; + // err + format.setForeground(Qt::red); + colors_.at(level::err) = format; + // critical + format.setForeground(Qt::white); + format.setBackground(Qt::red); + colors_.at(level::critical) = format; + } - void set_default_color(QTextCharFormat format) - { - // std::lock_guard lock(base_sink::mutex_); - default_color_ = format; - } + ~qt_color_sink() + { + flush_(); + } - void set_level_color(level::level_enum color_level, QTextCharFormat format) - { - // std::lock_guard lock(base_sink::mutex_); - colors_.at(static_cast(color_level)) = format; - } + void set_default_color(QTextCharFormat format) + { + // std::lock_guard lock(base_sink::mutex_); + default_color_ = format; + } - QTextCharFormat &get_level_color(level::level_enum color_level) - { - std::lock_guard lock(base_sink::mutex_); - return colors_.at(static_cast(color_level)); - } + void set_level_color(level::level_enum color_level, QTextCharFormat format) + { + // std::lock_guard lock(base_sink::mutex_); + colors_.at(static_cast(color_level)) = format; + } - QTextCharFormat &get_default_color() - { - std::lock_guard lock(base_sink::mutex_); - return default_color_; - } + QTextCharFormat &get_level_color(level::level_enum color_level) + { + std::lock_guard lock(base_sink::mutex_); + return colors_.at(static_cast(color_level)); + } - protected: - struct invoke_params - { - invoke_params(int max_lines, QTextEdit *q_text_edit, QString payload, QTextCharFormat default_color, - QTextCharFormat level_color, int color_range_start, int color_range_end) - : max_lines(max_lines), - q_text_edit(q_text_edit), - payload(std::move(payload)), - default_color(default_color), - level_color(level_color), - color_range_start(color_range_start), - color_range_end(color_range_end) - { - } - int max_lines; - QTextEdit *q_text_edit; - QString payload; - QTextCharFormat default_color; - QTextCharFormat level_color; - int color_range_start; - int color_range_end; - }; - void sink_it_(const details::log_msg &msg) override - { + QTextCharFormat &get_default_color() + { + std::lock_guard lock(base_sink::mutex_); + return default_color_; + } - using this_type = qt_color_sink; - memory_buf_t formatted; - base_sink::formatter_->format(msg, formatted); +protected: + struct invoke_params + { + invoke_params(int max_lines, QTextEdit *q_text_edit, QString payload, QTextCharFormat default_color, QTextCharFormat level_color, + int color_range_start, int color_range_end) + : max_lines(max_lines) + , q_text_edit(q_text_edit) + , payload(std::move(payload)) + , default_color(default_color) + , level_color(level_color) + , color_range_start(color_range_start) + , color_range_end(color_range_end) + {} + int max_lines; + QTextEdit *q_text_edit; + QString payload; + QTextCharFormat default_color; + QTextCharFormat level_color; + int color_range_start; + int color_range_end; + }; - const string_view_t str = string_view_t(formatted.data(), formatted.size()); - // apply the color to the color range in the formatted message. - auto payload = QString::fromLatin1(str.data(), static_cast(str.size())); + void sink_it_(const details::log_msg &msg) override + { + memory_buf_t formatted; + base_sink::formatter_->format(msg, formatted); - invoke_params params { - max_lines_, // max lines - qt_text_edit_, // text edit to append to - std::move(payload), // text to append - default_color_, // default color - colors_.at(msg.level), // color to apply - msg.color_range_start, // color range start - msg.color_range_end}; // color range end + const string_view_t str = string_view_t(formatted.data(), formatted.size()); + // apply the color to the color range in the formatted message. + auto payload = QString::fromLatin1(str.data(), static_cast(str.size())); - QMetaObject::invokeMethod( - qt_text_edit_, - [params]() {invoke_method_(params);}, - Qt::AutoConnection); + invoke_params params{max_lines_, // max lines + qt_text_edit_, // text edit to append to + std::move(payload), // text to append + default_color_, // default color + colors_.at(msg.level), // color to apply + static_cast(msg.color_range_start), // color range start + static_cast(msg.color_range_end)}; // color range end - } + QMetaObject::invokeMethod( + qt_text_edit_, [params]() { invoke_method_(params); }, Qt::AutoConnection); + } + + void flush_() override {} - void flush_() override {} + // Add colored text to the text edit widget. This method is invoked in the GUI thread. + // It is a static method to ensure that it is handled correctly even if the sink is destroyed prematurely + // before it is invoked. - // Add colored text to the text edit widget. This method is invoked in the GUI thread. - // It is a static method to ensure that it is handled correctly even if the sink is destroyed prematurely - // before it is invoked. + static void invoke_method_(invoke_params params) + { + auto *document = params.q_text_edit->document(); + QTextCursor cursor(document); - static void invoke_method_(invoke_params params) + // remove first blocks if number of blocks exceeds max_lines + while (document->blockCount() > params.max_lines) { - auto *document = params.q_text_edit->document(); - QTextCursor cursor(document); - - // remove first blocks if number of blocks exceeds max_lines - while(document->blockCount() > params.max_lines) - { - cursor.select(QTextCursor::BlockUnderCursor); - cursor.removeSelectedText(); - cursor.deleteChar(); // delete the newline after the block - } - - cursor.movePosition(QTextCursor::End); - cursor.setCharFormat(params.default_color); - - // if color range not specified or not not valid, just append the text with default color - if(params.color_range_end <= params.color_range_start) - { - cursor.insertText(params.payload); - return; - } - - // insert the text before the color range - cursor.insertText(params.payload.left(params.color_range_start)); - - // insert the colorized text - cursor.setCharFormat(params.level_color); - cursor.insertText(params.payload.mid(params.color_range_start, params.color_range_end - params.color_range_start)); - - // insert the text after the color range with default format - cursor.setCharFormat(params.default_color); - cursor.insertText(params.payload.mid(params.color_range_end)); + cursor.select(QTextCursor::BlockUnderCursor); + cursor.removeSelectedText(); + cursor.deleteChar(); // delete the newline after the block } - QTextEdit *qt_text_edit_; - int max_lines_; - QTextCharFormat default_color_; - std::array colors_; - }; + cursor.movePosition(QTextCursor::End); + cursor.setCharFormat(params.default_color); + + // if color range not specified or not not valid, just append the text with default color + if (params.color_range_end <= params.color_range_start) + { + cursor.insertText(params.payload); + return; + } + + // insert the text before the color range + cursor.insertText(params.payload.left(params.color_range_start)); + + // insert the colorized text + cursor.setCharFormat(params.level_color); + cursor.insertText(params.payload.mid(params.color_range_start, params.color_range_end - params.color_range_start)); + + // insert the text after the color range with default format + cursor.setCharFormat(params.default_color); + cursor.insertText(params.payload.mid(params.color_range_end)); + } + + QTextEdit *qt_text_edit_; + int max_lines_; + QTextCharFormat default_color_; + std::array colors_; +}; #include "spdlog/details/null_mutex.h" #include + using qt_sink_mt = qt_sink; using qt_sink_st = qt_sink; using qt_color_sink_mt = qt_color_sink; @@ -280,13 +280,13 @@ inline std::shared_ptr qt_logger_st(const std::string &logger_name, QObj template inline std::shared_ptr qt_color_logger_mt(const std::string &logger_name, QTextEdit *qt_text_edit, int max_lines) { - return Factory::template create(logger_name, qt_text_edit, max_lines); + return Factory::template create(logger_name, qt_text_edit, max_lines); } template inline std::shared_ptr qt_color_logger_st(const std::string &logger_name, QTextEdit *qt_text_edit, int max_lines) { - return Factory::template create(logger_name, qt_text_edit, max_lines); + return Factory::template create(logger_name, qt_text_edit, max_lines); } } // namespace spdlog diff --git a/include/spdlog/stopwatch.h b/include/spdlog/stopwatch.h index 5d1f2dc5..bea7b8a7 100644 --- a/include/spdlog/stopwatch.h +++ b/include/spdlog/stopwatch.h @@ -61,7 +61,7 @@ template<> struct formatter : formatter { template - auto format(const spdlog::stopwatch &sw, FormatContext &ctx) -> decltype(ctx.out()) + auto format(const spdlog::stopwatch &sw, FormatContext &ctx) const -> decltype(ctx.out()) { return formatter::format(sw.elapsed().count(), ctx); } diff --git a/include/spdlog/version.h b/include/spdlog/version.h index 5717bead..633cddc7 100644 --- a/include/spdlog/version.h +++ b/include/spdlog/version.h @@ -4,7 +4,7 @@ #pragma once #define SPDLOG_VER_MAJOR 1 -#define SPDLOG_VER_MINOR 11 +#define SPDLOG_VER_MINOR 12 #define SPDLOG_VER_PATCH 0 #define SPDLOG_VERSION (SPDLOG_VER_MAJOR * 10000 + SPDLOG_VER_MINOR * 100 + SPDLOG_VER_PATCH) diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 942ec519..176578ad 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -54,6 +54,10 @@ if(systemd_FOUND) list(APPEND SPDLOG_UTESTS_SOURCES test_systemd.cpp) endif() +if(NOT SPDLOG_USE_STD_FORMAT) + list(APPEND SPDLOG_UTESTS_SOURCES test_bin_to_hex.cpp) +endif() + enable_testing() function(spdlog_prepare_test test_target spdlog_lib) diff --git a/tests/test_bin_to_hex.cpp b/tests/test_bin_to_hex.cpp new file mode 100644 index 00000000..3c50c74a --- /dev/null +++ b/tests/test_bin_to_hex.cpp @@ -0,0 +1,93 @@ +#include "includes.h" +#include "test_sink.h" +#include "spdlog/fmt/bin_to_hex.h" + +TEST_CASE("to_hex", "[to_hex]") +{ + std::ostringstream oss; + auto oss_sink = std::make_shared(oss); + spdlog::logger oss_logger("oss", oss_sink); + + std::vector v{9, 0xa, 0xb, 0xc, 0xff, 0xff}; + oss_logger.info("{}", spdlog::to_hex(v)); + + auto output = oss.str(); + REQUIRE(ends_with(output, "0000: 09 0a 0b 0c ff ff" + std::string(spdlog::details::os::default_eol))); +} + +TEST_CASE("to_hex_upper", "[to_hex]") +{ + std::ostringstream oss; + auto oss_sink = std::make_shared(oss); + spdlog::logger oss_logger("oss", oss_sink); + + std::vector v{9, 0xa, 0xb, 0xc, 0xff, 0xff}; + oss_logger.info("{:X}", spdlog::to_hex(v)); + + auto output = oss.str(); + REQUIRE(ends_with(output, "0000: 09 0A 0B 0C FF FF" + std::string(spdlog::details::os::default_eol))); +} + +TEST_CASE("to_hex_no_delimiter", "[to_hex]") +{ + std::ostringstream oss; + auto oss_sink = std::make_shared(oss); + spdlog::logger oss_logger("oss", oss_sink); + + std::vector v{9, 0xa, 0xb, 0xc, 0xff, 0xff}; + oss_logger.info("{:sX}", spdlog::to_hex(v)); + + auto output = oss.str(); + REQUIRE(ends_with(output, "0000: 090A0B0CFFFF" + std::string(spdlog::details::os::default_eol))); +} + +TEST_CASE("to_hex_show_ascii", "[to_hex]") +{ + std::ostringstream oss; + auto oss_sink = std::make_shared(oss); + spdlog::logger oss_logger("oss", oss_sink); + + std::vector v{9, 0xa, 0xb, 0x41, 0xc, 0x4b, 0xff, 0xff}; + oss_logger.info("{:Xsa}", spdlog::to_hex(v, 8)); + + REQUIRE(ends_with(oss.str(), "0000: 090A0B410C4BFFFF ...A.K.." + std::string(spdlog::details::os::default_eol))); +} + +TEST_CASE("to_hex_different_size_per_line", "[to_hex]") +{ + std::ostringstream oss; + auto oss_sink = std::make_shared(oss); + spdlog::logger oss_logger("oss", oss_sink); + + std::vector v{9, 0xa, 0xb, 0x41, 0xc, 0x4b, 0xff, 0xff}; + + oss_logger.info("{:Xsa}", spdlog::to_hex(v, 10)); + REQUIRE(ends_with(oss.str(), "0000: 090A0B410C4BFFFF ...A.K.." + std::string(spdlog::details::os::default_eol))); + + oss_logger.info("{:Xs}", spdlog::to_hex(v, 10)); + REQUIRE(ends_with(oss.str(), "0000: 090A0B410C4BFFFF" + std::string(spdlog::details::os::default_eol))); + + oss_logger.info("{:Xsa}", spdlog::to_hex(v, 6)); + REQUIRE(ends_with(oss.str(), "0000: 090A0B410C4B ...A.K" + std::string(spdlog::details::os::default_eol) + "0006: FFFF .." + + std::string(spdlog::details::os::default_eol))); + + oss_logger.info("{:Xs}", spdlog::to_hex(v, 6)); + REQUIRE(ends_with(oss.str(), "0000: 090A0B410C4B" + std::string(spdlog::details::os::default_eol) + "0006: FFFF" + + std::string(spdlog::details::os::default_eol))); +} + +TEST_CASE("to_hex_no_ascii", "[to_hex]") +{ + std::ostringstream oss; + auto oss_sink = std::make_shared(oss); + spdlog::logger oss_logger("oss", oss_sink); + + std::vector v{9, 0xa, 0xb, 0x41, 0xc, 0x4b, 0xff, 0xff}; + oss_logger.info("{:Xs}", spdlog::to_hex(v, 8)); + + REQUIRE(ends_with(oss.str(), "0000: 090A0B410C4BFFFF" + std::string(spdlog::details::os::default_eol))); + + oss_logger.info("{:Xsna}", spdlog::to_hex(v, 8)); + + REQUIRE(ends_with(oss.str(), "090A0B410C4BFFFF" + std::string(spdlog::details::os::default_eol))); +} diff --git a/tests/test_misc.cpp b/tests/test_misc.cpp index b6807154..9f3cb174 100644 --- a/tests/test_misc.cpp +++ b/tests/test_misc.cpp @@ -1,6 +1,5 @@ #include "includes.h" #include "test_sink.h" -#include "spdlog/fmt/bin_to_hex.h" template std::string log_info(const T &what, spdlog::level::level_enum logger_level = spdlog::level::info) @@ -140,96 +139,6 @@ TEST_CASE("clone async", "[clone]") spdlog::drop_all(); } -TEST_CASE("to_hex", "[to_hex]") -{ - std::ostringstream oss; - auto oss_sink = std::make_shared(oss); - spdlog::logger oss_logger("oss", oss_sink); - - std::vector v{9, 0xa, 0xb, 0xc, 0xff, 0xff}; - oss_logger.info("{}", spdlog::to_hex(v)); - - auto output = oss.str(); - REQUIRE(ends_with(output, "0000: 09 0a 0b 0c ff ff" + std::string(spdlog::details::os::default_eol))); -} - -TEST_CASE("to_hex_upper", "[to_hex]") -{ - std::ostringstream oss; - auto oss_sink = std::make_shared(oss); - spdlog::logger oss_logger("oss", oss_sink); - - std::vector v{9, 0xa, 0xb, 0xc, 0xff, 0xff}; - oss_logger.info("{:X}", spdlog::to_hex(v)); - - auto output = oss.str(); - REQUIRE(ends_with(output, "0000: 09 0A 0B 0C FF FF" + std::string(spdlog::details::os::default_eol))); -} - -TEST_CASE("to_hex_no_delimiter", "[to_hex]") -{ - std::ostringstream oss; - auto oss_sink = std::make_shared(oss); - spdlog::logger oss_logger("oss", oss_sink); - - std::vector v{9, 0xa, 0xb, 0xc, 0xff, 0xff}; - oss_logger.info("{:sX}", spdlog::to_hex(v)); - - auto output = oss.str(); - REQUIRE(ends_with(output, "0000: 090A0B0CFFFF" + std::string(spdlog::details::os::default_eol))); -} - -TEST_CASE("to_hex_show_ascii", "[to_hex]") -{ - std::ostringstream oss; - auto oss_sink = std::make_shared(oss); - spdlog::logger oss_logger("oss", oss_sink); - - std::vector v{9, 0xa, 0xb, 0x41, 0xc, 0x4b, 0xff, 0xff}; - oss_logger.info("{:Xsa}", spdlog::to_hex(v, 8)); - - REQUIRE(ends_with(oss.str(), "0000: 090A0B410C4BFFFF ...A.K.." + std::string(spdlog::details::os::default_eol))); -} - -TEST_CASE("to_hex_different_size_per_line", "[to_hex]") -{ - std::ostringstream oss; - auto oss_sink = std::make_shared(oss); - spdlog::logger oss_logger("oss", oss_sink); - - std::vector v{9, 0xa, 0xb, 0x41, 0xc, 0x4b, 0xff, 0xff}; - - oss_logger.info("{:Xsa}", spdlog::to_hex(v, 10)); - REQUIRE(ends_with(oss.str(), "0000: 090A0B410C4BFFFF ...A.K.." + std::string(spdlog::details::os::default_eol))); - - oss_logger.info("{:Xs}", spdlog::to_hex(v, 10)); - REQUIRE(ends_with(oss.str(), "0000: 090A0B410C4BFFFF" + std::string(spdlog::details::os::default_eol))); - - oss_logger.info("{:Xsa}", spdlog::to_hex(v, 6)); - REQUIRE(ends_with(oss.str(), "0000: 090A0B410C4B ...A.K" + std::string(spdlog::details::os::default_eol) + "0006: FFFF .." + - std::string(spdlog::details::os::default_eol))); - - oss_logger.info("{:Xs}", spdlog::to_hex(v, 6)); - REQUIRE(ends_with(oss.str(), "0000: 090A0B410C4B" + std::string(spdlog::details::os::default_eol) + "0006: FFFF" + - std::string(spdlog::details::os::default_eol))); -} - -TEST_CASE("to_hex_no_ascii", "[to_hex]") -{ - std::ostringstream oss; - auto oss_sink = std::make_shared(oss); - spdlog::logger oss_logger("oss", oss_sink); - - std::vector v{9, 0xa, 0xb, 0x41, 0xc, 0x4b, 0xff, 0xff}; - oss_logger.info("{:Xs}", spdlog::to_hex(v, 8)); - - REQUIRE(ends_with(oss.str(), "0000: 090A0B410C4BFFFF" + std::string(spdlog::details::os::default_eol))); - - oss_logger.info("{:Xsna}", spdlog::to_hex(v, 8)); - - REQUIRE(ends_with(oss.str(), "090A0B410C4BFFFF" + std::string(spdlog::details::os::default_eol))); -} - TEST_CASE("default logger API", "[default logger]") { std::ostringstream oss;