From 51bf5307a56dd996d0e1efbe66f76c39b8df0946 Mon Sep 17 00:00:00 2001 From: Charles Cabergs Date: Thu, 18 Sep 2025 22:19:21 +0200 Subject: [PATCH 1/2] Update zmq::message_t::str with an argument to set the maximum message size to put in a debug string --- tests/message.cpp | 18 ++++++++++++++++++ zmq.hpp | 48 +++++++++++++++++++++++++---------------------- 2 files changed, 44 insertions(+), 22 deletions(-) diff --git a/tests/message.cpp b/tests/message.cpp index 23718bd0..645d8065 100644 --- a/tests/message.cpp +++ b/tests/message.cpp @@ -196,6 +196,24 @@ TEST_CASE("message to string", "[message]") #endif } +TEST_CASE("message to debug string", "[message]") +{ + const zmq::message_t a; + const zmq::message_t b("Foo", 3); + const zmq::message_t c("ascii\x01\x02\x03%%%\x04\x05\x06###", 17); + const zmq::message_t d("\x01\x02\x03|||", 6); + CHECK(a.str() == "zmq::message_t [size 000] ()"); + CHECK(b.str() == "zmq::message_t [size 003] (Foo)"); + CHECK(c.str() == "zmq::message_t [size 017] (ascii 010203 %%% 040506 ###)"); + CHECK(d.str() == "zmq::message_t [size 006] (010203 |||)"); + // With max_size + CHECK(a.str(100) == "zmq::message_t [size 000] ()"); + CHECK(b.str(2) == "zmq::message_t [size 003] (Fo... too big to print)"); + CHECK(c.str(10) + == "zmq::message_t [size 017] (ascii 010203 %%... too big to print)"); + CHECK(d.str(2) == "zmq::message_t [size 006] (0102... too big to print)"); +} + #if defined(ZMQ_BUILD_DRAFT_API) && ZMQ_VERSION >= ZMQ_MAKE_VERSION(4, 2, 0) TEST_CASE("message routing id persists", "[message]") { diff --git a/zmq.hpp b/zmq.hpp index cfd8e92e..58cbe76a 100644 --- a/zmq.hpp +++ b/zmq.hpp @@ -691,39 +691,43 @@ class message_t * Use to_string() or to_string_view() for * interpreting the message as a string. */ - std::string str() const + std::string str(size_t max_size = 1000) const { // Partly mutuated from the same method in zmq::multipart_t std::stringstream os; const unsigned char *msg_data = this->data(); unsigned char byte; - size_t size = this->size(); + size_t size_to_print = std::min(this->size(), max_size); int is_ascii[2] = {0, 0}; + // Set is_ascii for the first character + if (size_to_print > 0) { + byte = *msg_data; + is_ascii[0] = (byte >= 32 && byte < 127); + } os << "zmq::message_t [size " << std::dec << std::setw(3) - << std::setfill('0') << size << "] ("; - // Totally arbitrary - if (size >= 1000) { - os << "... too big to print)"; - } else { - while (size--) { - byte = *msg_data++; - - is_ascii[1] = (byte >= 32 && byte < 127); - if (is_ascii[1] != is_ascii[0]) - os << " "; // Separate text/non text - - if (is_ascii[1]) { - os << byte; - } else { - os << std::hex << std::uppercase << std::setw(2) - << std::setfill('0') << static_cast(byte); - } - is_ascii[0] = is_ascii[1]; + << std::setfill('0') << this->size() << "] ("; + while (size_to_print--) { + byte = *msg_data++; + + is_ascii[1] = (byte >= 32 && byte < 127); + if (is_ascii[1] != is_ascii[0]) + os << " "; // Separate text/non text + + if (is_ascii[1]) { + os << byte; + } else { + os << std::hex << std::uppercase << std::setw(2) << std::setfill('0') + << static_cast(byte); } - os << ")"; + is_ascii[0] = is_ascii[1]; } + // Elide the rest if the message is too large + if (max_size < this->size()) + os << "... too big to print)"; + else + os << ")"; return os.str(); } From dcfc77e578a975babacbefdcbabceaf1b58102d6 Mon Sep 17 00:00:00 2001 From: Charles Cabergs Date: Fri, 19 Sep 2025 15:08:06 +0200 Subject: [PATCH 2/2] Fix std::min on Windows and move byte variable to a lower scope --- zmq.hpp | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/zmq.hpp b/zmq.hpp index 58cbe76a..ad0509e8 100644 --- a/zmq.hpp +++ b/zmq.hpp @@ -697,19 +697,16 @@ class message_t std::stringstream os; const unsigned char *msg_data = this->data(); - unsigned char byte; - size_t size_to_print = std::min(this->size(), max_size); + size_t size_to_print = (std::min)(this->size(), max_size); int is_ascii[2] = {0, 0}; // Set is_ascii for the first character - if (size_to_print > 0) { - byte = *msg_data; - is_ascii[0] = (byte >= 32 && byte < 127); - } + if (size_to_print > 0) + is_ascii[0] = (*msg_data >= 32 && *msg_data < 127); os << "zmq::message_t [size " << std::dec << std::setw(3) << std::setfill('0') << this->size() << "] ("; while (size_to_print--) { - byte = *msg_data++; + const unsigned char byte = *msg_data++; is_ascii[1] = (byte >= 32 && byte < 127); if (is_ascii[1] != is_ascii[0])