Skip to content

Commit 380a1ac

Browse files
authored
Merge pull request #890 from redboltz/fix_binary
Refined binary buffer operation.
2 parents f150654 + a398f8f commit 380a1ac

File tree

4 files changed

+68
-7
lines changed

4 files changed

+68
-7
lines changed

include/mqtt/property.hpp

+50-1
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@
1111
#include <vector>
1212
#include <memory>
1313
#include <algorithm>
14+
#include <iosfwd>
15+
#include <iomanip>
1416

1517
#include <boost/asio/buffer.hpp>
1618
#include <boost/numeric/conversion/cast.hpp>
@@ -46,6 +48,7 @@ enum class ostream_format {
4648
int_cast,
4749
key_val,
4850
binary_string,
51+
json_like
4952
};
5053

5154
template <std::size_t N>
@@ -176,7 +179,7 @@ struct binary_property {
176179
return buf_;
177180
}
178181

179-
static constexpr ostream_format const of_ = ostream_format::direct;
182+
static constexpr ostream_format const of_ = ostream_format::json_like;
180183
property::id id_;
181184
buffer buf_;
182185
boost::container::static_vector<char, 2> length_;
@@ -734,6 +737,52 @@ operator<<(std::ostream& o, Property const& p) {
734737
return o;
735738
}
736739

740+
template <typename Property>
741+
std::enable_if_t< Property::of_ == detail::ostream_format::json_like, std::ostream& >
742+
operator<<(std::ostream& o, Property const& p) {
743+
auto const& v = p.val();
744+
for (auto const c : v) {
745+
switch (c) {
746+
case '\\':
747+
o << "\\\\";
748+
break;
749+
case '"':
750+
o << "\\\"";
751+
break;
752+
case '/':
753+
o << "\\/";
754+
break;
755+
case '\b':
756+
o << "\\b";
757+
break;
758+
case '\f':
759+
o << "\\f";
760+
break;
761+
case '\n':
762+
o << "\\n";
763+
break;
764+
case '\r':
765+
o << "\\r";
766+
break;
767+
case '\t':
768+
o << "\\t";
769+
break;
770+
default: {
771+
unsigned int code = static_cast<unsigned int>(c);
772+
if (code < 0x20 || code >= 0x7f) {
773+
std::ios::fmtflags flags(o.flags());
774+
o << "\\u" << std::hex << std::setw(4) << std::setfill('0') << (code & 0xff);
775+
o.flags(flags);
776+
}
777+
else {
778+
o << c;
779+
}
780+
} break;
781+
}
782+
}
783+
return o;
784+
}
785+
737786

738787
} // namespace property
739788
} // namespace v5

test/system/st_pubsub_1.cpp

+3-3
Original file line numberDiff line numberDiff line change
@@ -3083,6 +3083,7 @@ BOOST_AUTO_TEST_CASE( publish_dup_function_buffer ) {
30833083
}
30843084

30853085
BOOST_AUTO_TEST_CASE( pub_sub_prop ) {
3086+
using namespace std::literals::string_literals;
30863087
auto test = [](boost::asio::io_context& ioc, auto& cs, auto finish, auto& /*b*/) {
30873088
auto& c = cs[0];
30883089
clear_ordered();
@@ -3109,14 +3110,13 @@ BOOST_AUTO_TEST_CASE( pub_sub_prop ) {
31093110
// disconnect
31103111
cont("h_close"),
31113112
};
3112-
std::string correlation_data_str = "correlation \0data"; //binary including 0
31133113
MQTT_NS::v5::properties ps {
31143114
MQTT_NS::v5::property::payload_format_indicator(MQTT_NS::v5::property::payload_format_indicator::string),
31153115
MQTT_NS::v5::property::message_expiry_interval(0x12345678UL),
31163116
MQTT_NS::v5::property::content_type("content type"_mb),
31173117
MQTT_NS::v5::property::topic_alias(0x1234U),
31183118
MQTT_NS::v5::property::response_topic("response topic"_mb),
3119-
MQTT_NS::v5::property::correlation_data(MQTT_NS::buffer(MQTT_NS::string_view(correlation_data_str))),
3119+
MQTT_NS::v5::property::correlation_data("correlation \0data"_mb),
31203120
MQTT_NS::v5::property::user_property("key1"_mb, "val1"_mb),
31213121
MQTT_NS::v5::property::user_property("key2"_mb, "val2"_mb),
31223122
};
@@ -3209,7 +3209,7 @@ BOOST_AUTO_TEST_CASE( pub_sub_prop ) {
32093209
BOOST_TEST(t.val() == "response topic");
32103210
},
32113211
[&](MQTT_NS::v5::property::correlation_data const& t) {
3212-
BOOST_TEST(t.val() == std::string("correlation \0data"));
3212+
BOOST_TEST(t.val() == std::string("correlation \0data"s));
32133213
},
32143214
[&](MQTT_NS::v5::property::user_property const& t) {
32153215
switch (user_prop_count++) {

test/unit/ut_buffer.cpp

+12
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,18 @@ BOOST_AUTO_TEST_CASE( allocate2 ) {
4343
BOOST_TEST(ss2.has_life());
4444
}
4545

46+
BOOST_AUTO_TEST_CASE( literals ) {
47+
using namespace MQTT_NS::literals;
48+
using namespace std::literals::string_literals;
49+
auto buf1 = "abcde"_mb;
50+
BOOST_TEST(buf1.size() == 5);
51+
BOOST_TEST(buf1 == "abcde"s);
52+
53+
auto buf2 = "ab\0cde"_mb;
54+
BOOST_TEST(buf2.size() == 6);
55+
BOOST_TEST(buf2 == "ab\0cde"s);
56+
}
57+
4658
#if 0
4759
// CI doesn't work due to -std=c++1z.
4860
// I couldn't set -std=c++17 on CI

test/unit/ut_property.cpp

+3-3
Original file line numberDiff line numberDiff line change
@@ -136,9 +136,9 @@ BOOST_AUTO_TEST_CASE( response_topic ) {
136136
}
137137

138138
BOOST_AUTO_TEST_CASE( correlation_data ) {
139-
std::string s = "a\0bc";
140-
MQTT_NS::v5::property::correlation_data v1 { MQTT_NS::buffer(MQTT_NS::string_view(s)) };
141-
BOOST_TEST(v1.val() == std::string("a\0bc"));
139+
using namespace std::literals::string_literals;
140+
MQTT_NS::v5::property::correlation_data v1 { "a\0bc"_mb };
141+
BOOST_TEST(v1.val() == "a\0bc"s);
142142
}
143143

144144
BOOST_AUTO_TEST_CASE( assigned_client_identifier ) {

0 commit comments

Comments
 (0)