Skip to content

Commit c5dadff

Browse files
author
me
committed
- added std::vector<char> to value variant so we explicitly support binary array
- removed remaining() from source_base. no need - value::unpack done but not thoroughly tested
1 parent df99d10 commit c5dadff

File tree

6 files changed

+89
-54
lines changed

6 files changed

+89
-54
lines changed

src/msgpack.cpp

Lines changed: 69 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ namespace msgpackcpp
1818
value::value(const char* v) : val(std::string(v)) {}
1919
value::value(std::string_view v) : val(std::string(v)) {}
2020
value::value(std::string v) : val{std::move(v)} {}
21+
value::value(std::vector<char> v) : val{std::move(v)} {}
2122
value::value(std::vector<value> v) : val{std::move(v)} {}
2223
value::value(std::map<std::string, value> v) : val{std::move(v)} {}
2324

@@ -42,6 +43,7 @@ namespace msgpackcpp
4243
size_t value::size() const noexcept
4344
{
4445
return std::visit(overloaded{
46+
[&](const std::vector<char>& v) {return v.size();},
4547
[&](const std::vector<value>& v) {return v.size();},
4648
[&](const std::map<std::string, value>& v) {return v.size();},
4749
[&](std::nullptr_t) {return (size_t)0;},
@@ -56,6 +58,7 @@ namespace msgpackcpp
5658
bool value::is_int() const noexcept {return std::holds_alternative<int64_t>(val) || std::holds_alternative<uint64_t>(val);}
5759
bool value::is_real() const noexcept {return std::holds_alternative<double>(val);}
5860
bool value::is_str() const noexcept {return std::holds_alternative<std::string>(val);}
61+
bool value::is_binary() const noexcept {return std::holds_alternative<std::vector<char>>(val);}
5962
bool value::is_array() const noexcept {return std::holds_alternative<std::vector<value>>(val);}
6063
bool value::is_object() const noexcept {return std::holds_alternative<std::map<std::string, value>>(val);}
6164

@@ -71,6 +74,8 @@ namespace msgpackcpp
7174
auto value::as_real() -> double& {return std::get<double>(val);}
7275
auto value::as_str() const -> const std::string& {return std::get<std::string>(val);}
7376
auto value::as_str() -> std::string& {return std::get<std::string>(val);}
77+
auto value::as_bin() const -> const std::vector<char>& {return std::get<std::vector<char>>(val);}
78+
auto value::as_bin() -> std::vector<char>& {return std::get<std::vector<char>>(val);}
7479
auto value::as_array() const -> const std::vector<value>& {return std::get<std::vector<value>>(val);}
7580
auto value::as_array() -> std::vector<value>& {return std::get<std::vector<value>>(val);}
7681
auto value::as_object() const -> const std::map<std::string, value>& {return std::get<std::map<std::string, value>>(val);}
@@ -150,41 +155,74 @@ namespace msgpackcpp
150155

151156
void value::unpack(source_base& in)
152157
{
153-
while (in.remaining())
158+
const uint8_t format = in.peak();
159+
160+
if (format == MSGPACK_NIL)
154161
{
155-
const uint8_t format = in.peak();
156-
157-
if (format == MSGPACK_NIL)
158-
{
159-
deserialize(in, nullptr);
160-
}
161-
else if (format == MSGPACK_FALSE || format == MSGPACK_TRUE)
162-
{
163-
bool v{};
164-
deserialize(in, v);
165-
val = v;
166-
}
167-
else if (format == MSGPACK_F32 || format == MSGPACK_F64)
168-
{
169-
double v{};
170-
deserialize(in, v);
171-
val = v;
172-
}
173-
else if (format < MSGPACK_FIXINT_POS || format == MSGPACK_U8 || format == MSGPACK_U16 || format == MSGPACK_U32 || format == MSGPACK_U64)
174-
{
175-
uint64_t v{};
176-
deserialize(in, v);
177-
val = v;
178-
}
179-
else if ((format & 0b11100000) == MSGPACK_FIXINT_NEG || format == MSGPACK_I8 || format == MSGPACK_I16 || format == MSGPACK_I32 || format == MSGPACK_I64)
162+
deserialize(in, nullptr);
163+
}
164+
else if (format == MSGPACK_FALSE || format == MSGPACK_TRUE)
165+
{
166+
bool v{};
167+
deserialize(in, v);
168+
val = v;
169+
}
170+
else if (format == MSGPACK_F32 || format == MSGPACK_F64)
171+
{
172+
double v{};
173+
deserialize(in, v);
174+
val = v;
175+
}
176+
else if (format < MSGPACK_FIXINT_POS || format == MSGPACK_U8 || format == MSGPACK_U16 || format == MSGPACK_U32 || format == MSGPACK_U64)
177+
{
178+
uint64_t v{};
179+
deserialize(in, v);
180+
val = v;
181+
}
182+
else if ((format & 0b11100000) == MSGPACK_FIXINT_NEG || format == MSGPACK_I8 || format == MSGPACK_I16 || format == MSGPACK_I32 || format == MSGPACK_I64)
183+
{
184+
int64_t v{};
185+
deserialize(in, v);
186+
val = v;
187+
}
188+
else if ((format & 0b11100000) == MSGPACK_FIXSTR || format == MSGPACK_STR8 || format == MSGPACK_STR16 || format == MSGPACK_STR32)
189+
{
190+
std::string v;
191+
deserialize(in, v);
192+
val = std::move(v);
193+
}
194+
else if (format == MSGPACK_BIN8 || format == MSGPACK_BIN16 || format == MSGPACK_BIN32)
195+
{
196+
std::vector<char> v;
197+
deserialize(in, v);
198+
val = std::move(v);
199+
}
200+
else if ((format & 0b11110000) == MSGPACK_FIXARR || format == MSGPACK_ARR16 || format == MSGPACK_ARR32)
201+
{
202+
uint32_t size{};
203+
deserialize_array_size(in, size);
204+
std::vector<value> v(size);
205+
for (auto& el : v)
206+
el.unpack(in);
207+
val = std::move(v);
208+
}
209+
else if ((format & 0b11110000) == MSGPACK_FIXMAP || format == MSGPACK_MAP16 || format == MSGPACK_MAP32)
210+
{
211+
uint32_t size{};
212+
deserialize_map_size(in, size);
213+
std::map<std::string, value> m;
214+
for (size_t i{0} ; i < size ; ++i)
180215
{
181-
int64_t v{};
182-
deserialize(in, v);
183-
val = v;
216+
std::string k;
217+
value v;
218+
deserialize(in, k);
219+
v.unpack(in);
220+
m.emplace(std::make_pair(std::move(k), std::move(v)));
184221
}
185-
else
186-
throw std::system_error(BAD_FORMAT);
222+
val = std::move(m);
187223
}
224+
else
225+
throw std::system_error(BAD_FORMAT);
188226
}
189227

190228
value value::unpack_static(source_base& in)

src/msgpack.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,6 @@ namespace msgpackcpp
3232
{
3333
virtual void read(char* buf, size_t nbytes) = 0;
3434
virtual uint8_t peak() = 0;
35-
virtual size_t remaining() const = 0;
3635
};
3736

3837
//----------------------------------------------------------------------------------------------------------------
@@ -71,6 +70,7 @@ namespace msgpackcpp
7170
uint64_t,
7271
double,
7372
std::string,
73+
std::vector<char>,
7474
std::vector<value>,
7575
std::map<std::string, value>> val;
7676

@@ -96,6 +96,7 @@ namespace msgpackcpp
9696
value(const char* v);
9797
value(std::string_view v);
9898
value(std::string v);
99+
value(std::vector<char> v);
99100
value(std::vector<value> v);
100101
value(std::map<std::string, value> v);
101102
value(std::initializer_list<value> v);
@@ -107,6 +108,7 @@ namespace msgpackcpp
107108
bool is_int() const noexcept;
108109
bool is_real() const noexcept;
109110
bool is_str() const noexcept;
111+
bool is_binary() const noexcept;
110112
bool is_array() const noexcept;
111113
bool is_object() const noexcept;
112114

@@ -120,6 +122,8 @@ namespace msgpackcpp
120122
auto as_real() -> double&;
121123
auto as_str() const -> const std::string&;
122124
auto as_str() -> std::string&;
125+
auto as_bin() const -> const std::vector<char>&;
126+
auto as_bin() -> std::vector<char>&;
123127
auto as_array() const -> const std::vector<value>&;
124128
auto as_array() -> std::vector<value>&;
125129
auto as_object() const -> const std::map<std::string, value>&;

src/msgpack_sinks.h

Lines changed: 2 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -44,13 +44,10 @@ namespace msgpackcpp
4444

4545
uint8_t peak() override final
4646
{
47+
if (offset >= data.size())
48+
throw std::system_error(OUT_OF_DATA);
4749
return static_cast<uint8_t>(data[offset]);
4850
}
49-
50-
size_t remaining() const override final
51-
{
52-
return data.size() - offset;
53-
}
5451
};
5552

5653
template<class Byte, class Alloc, check_byte<Byte> = true>
@@ -95,15 +92,6 @@ namespace msgpackcpp
9592
throw std::system_error(OUT_OF_DATA);
9693
return b;
9794
}
98-
99-
size_t remaining() const override final
100-
{
101-
const auto pos = in.tellg();
102-
in.seekg(0, std::ios::end );
103-
const auto len = in.tellg() - pos;
104-
in.seekg( pos );
105-
return len;
106-
}
10795
};
10896

10997
inline auto sink(std::ostream& out) { return ostream_sink{out}; }

tests/CMakeLists.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ add_executable(tests
3636
target_compile_features(tests PRIVATE cxx_std_17)
3737
target_compile_options(tests PRIVATE $<${IS_NOT_MSVC}:-Wall -Wextra -Werror>)
3838
target_link_options(tests PRIVATE $<$<AND:$<CONFIG:RELEASE>,${IS_NOT_MSVC}>:-s>)
39-
set_target_properties(tests PROPERTIES INTERPROCEDURAL_OPTIMIZATION TRUE)
39+
set_target_properties(tests PROPERTIES INTERPROCEDURAL_OPTIMIZATION_RELEASE TRUE)
4040
# target_compile_options(tests PRIVATE $<${IS_MSVC}:/Wall /WX>)
4141
target_include_directories(tests PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/../src)
4242
target_link_libraries(tests PRIVATE Boost::describe PRIVATE msgpack-cxx)

tests/pack.cpp

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -208,7 +208,6 @@ TEST_SUITE("[PACK]")
208208
REQUIRE(h == hh);
209209
REQUIRE(i == ii);
210210
REQUIRE(j == jj);
211-
REQUIRE(in.remaining() == 0);
212211
}
213212

214213
buf1.clear();
@@ -350,7 +349,6 @@ TEST_SUITE("[PACK]")
350349
REQUIRE(num_errors(w, ww) == 0);
351350
REQUIRE(num_errors(x, xx) == 0);
352351
REQUIRE(num_errors(y, yy) == 0);
353-
REQUIRE(in.remaining() == 0);
354352
}
355353
}
356354

tests/value.cpp

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ value niels_data()
1414
{"name", "Niels"},
1515
{"nothing", nullptr},
1616
{"answer", {
17-
{"everything", 42}
17+
{"everything", -42}
1818
}},
1919
{"list", {1, 0, 2}},
2020
{"object", {
@@ -32,7 +32,7 @@ void check_niels(value& jv)
3232
REQUIRE(jv.at("happy").as_bool() == true);
3333
REQUIRE(jv.at("name").as_str() == "Niels");
3434
REQUIRE(jv.at("nothing").is_null());
35-
REQUIRE(jv.at("answer").at("everything").as_int64() == 42);
35+
REQUIRE(jv.at("answer").at("everything").as_int64() == -42);
3636
REQUIRE(jv.at("list").as_array().size() == 3);
3737
REQUIRE(jv.at("object").at("currency").as_str() == "USD");
3838
REQUIRE(jv.at("object").at("value").as_real() == 42.99);
@@ -107,6 +107,11 @@ TEST_SUITE("[VALUE]")
107107
REQUIRE(el.size() == 2);
108108
}
109109

110+
jv = std::vector<char>{1,0,1,0,1,0,1,0,1,0,1,0,1,0,1};
111+
REQUIRE(jv.is_binary());
112+
REQUIRE(jv.size() == 15);
113+
REQUIRE(jv.as_bin().size() == 15);
114+
110115
jv = niels_data();
111116
check_niels(jv);
112117
}
@@ -116,12 +121,14 @@ TEST_SUITE("[VALUE]")
116121
value jv1 = niels_data();
117122
check_niels(jv1);
118123

124+
// pack
119125
std::vector<char> buf0;
120126
auto out0 = sink(buf0);
121127
jv1.pack(out0);
122-
// auto in0 = source(buf0);
123128

124-
// value jv2 = value::unpack(in0);
125-
// check_niels(jv2);
129+
// unpack
130+
auto in0 = source(buf0);
131+
value jv2 = value::unpack_static(in0);
132+
check_niels(jv2);
126133
}
127134
}

0 commit comments

Comments
 (0)