Update zmq::message_t::str with max_size (#665)

* Update zmq::message_t::str with an argument to set the maximum message size to put in a debug string

* Fix std::min on Windows and move byte variable to a lower scope

---------

Co-authored-by: Charles Cabergs <charles.cabergs@intellis.ch>
This commit is contained in:
Charles Cabergs
2025-09-22 08:53:55 +00:00
committed by GitHub
parent 3bcbd9dad2
commit 8bace31b3d
2 changed files with 40 additions and 21 deletions

View File

@@ -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]")
{

43
zmq.hpp
View File

@@ -691,39 +691,40 @@ 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>();
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)
is_ascii[0] = (*msg_data >= 32 && *msg_data < 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++;
<< std::setfill('0') << this->size() << "] (";
while (size_to_print--) {
const unsigned char byte = *msg_data++;
is_ascii[1] = (byte >= 32 && byte < 127);
if (is_ascii[1] != is_ascii[0])
os << " "; // Separate text/non text
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<short>(byte);
}
is_ascii[0] = is_ascii[1];
if (is_ascii[1]) {
os << byte;
} else {
os << std::hex << std::uppercase << std::setw(2) << std::setfill('0')
<< static_cast<short>(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();
}