1 // __ _____ _____ _____
2 // __| | __| | | | JSON for Modern C++ (supporting code)
3 // | | |__ | | | | | | version 3.11.2
4 // |_____|_____|_____|_|___| https://github.com/nlohmann/json
5 //
6 // SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
7 // SPDX-License-Identifier: MIT
8
9 #include "doctest_compatibility.h"
10
11 #define JSON_TESTS_PRIVATE
12 #include <nlohmann/json.hpp>
13 using nlohmann::json;
14
15 #include <algorithm>
16 #include <climits>
17 #include <limits>
18 #include <iostream>
19 #include <fstream>
20 #include <set>
21 #include "make_test_data_available.hpp"
22 #include "test_utils.hpp"
23
24 namespace
25 {
26 class SaxCountdown
27 {
28 public:
SaxCountdown(const int count)29 explicit SaxCountdown(const int count) : events_left(count)
30 {}
31
null()32 bool null()
33 {
34 return events_left-- > 0;
35 }
36
boolean(bool)37 bool boolean(bool /*unused*/)
38 {
39 return events_left-- > 0;
40 }
41
number_integer(json::number_integer_t)42 bool number_integer(json::number_integer_t /*unused*/)
43 {
44 return events_left-- > 0;
45 }
46
number_unsigned(json::number_unsigned_t)47 bool number_unsigned(json::number_unsigned_t /*unused*/)
48 {
49 return events_left-- > 0;
50 }
51
number_float(json::number_float_t,const std::string &)52 bool number_float(json::number_float_t /*unused*/, const std::string& /*unused*/)
53 {
54 return events_left-- > 0;
55 }
56
string(std::string &)57 bool string(std::string& /*unused*/)
58 {
59 return events_left-- > 0;
60 }
61
binary(std::vector<std::uint8_t> &)62 bool binary(std::vector<std::uint8_t>& /*unused*/)
63 {
64 return events_left-- > 0;
65 }
66
start_object(std::size_t)67 bool start_object(std::size_t /*unused*/)
68 {
69 return events_left-- > 0;
70 }
71
key(std::string &)72 bool key(std::string& /*unused*/)
73 {
74 return events_left-- > 0;
75 }
76
end_object()77 bool end_object()
78 {
79 return events_left-- > 0;
80 }
81
start_array(std::size_t)82 bool start_array(std::size_t /*unused*/)
83 {
84 return events_left-- > 0;
85 }
86
end_array()87 bool end_array()
88 {
89 return events_left-- > 0;
90 }
91
parse_error(std::size_t,const std::string &,const json::exception &)92 bool parse_error(std::size_t /*unused*/, const std::string& /*unused*/, const json::exception& /*unused*/) // NOLINT(readability-convert-member-functions-to-static)
93 {
94 return false;
95 }
96
97 private:
98 int events_left = 0;
99 };
100 } // namespace
101
102 // at some point in the future, a unit test dedicated to type traits might be a good idea
103 template <typename OfType, typename T, bool MinInRange, bool MaxInRange>
104 struct trait_test_arg
105 {
106 using of_type = OfType;
107 using type = T;
108 static constexpr bool min_in_range = MinInRange;
109 static constexpr bool max_in_range = MaxInRange;
110 };
111
112 TEST_CASE_TEMPLATE_DEFINE("value_in_range_of trait", T, value_in_range_of_test)
113 {
114 using nlohmann::detail::value_in_range_of;
115
116 using of_type = typename T::of_type;
117 using type = typename T::type;
118 constexpr bool min_in_range = T::min_in_range;
119 constexpr bool max_in_range = T::max_in_range;
120
121 type val_min = std::numeric_limits<type>::min();
122 type val_min2 = val_min + 1;
123 type val_max = std::numeric_limits<type>::max();
124 type val_max2 = val_max - 1;
125
126 REQUIRE(CHAR_BIT == 8);
127
128 std::string of_type_str;
129 if (std::is_unsigned<of_type>::value)
130 {
131 of_type_str += "u";
132 }
133 of_type_str += "int";
134 of_type_str += std::to_string(sizeof(of_type) * 8);
135
136 INFO("of_type := ", of_type_str);
137
138 std::string type_str;
139 if (std::is_unsigned<type>::value)
140 {
141 type_str += "u";
142 }
143 type_str += "int";
144 type_str += std::to_string(sizeof(type) * 8);
145
146 INFO("type := ", type_str);
147
148 CAPTURE(val_min);
149 CAPTURE(min_in_range);
150 CAPTURE(val_max);
151 CAPTURE(max_in_range);
152
153 if (min_in_range)
154 {
155 CHECK(value_in_range_of<of_type>(val_min));
156 CHECK(value_in_range_of<of_type>(val_min2));
157 }
158 else
159 {
160 CHECK_FALSE(value_in_range_of<of_type>(val_min));
161 CHECK_FALSE(value_in_range_of<of_type>(val_min2));
162 }
163
164 if (max_in_range)
165 {
166 CHECK(value_in_range_of<of_type>(val_max));
167 CHECK(value_in_range_of<of_type>(val_max2));
168 }
169 else
170 {
171 CHECK_FALSE(value_in_range_of<of_type>(val_max));
172 CHECK_FALSE(value_in_range_of<of_type>(val_max2));
173 }
174 }
175
176 TEST_CASE_TEMPLATE_INVOKE(value_in_range_of_test, \
177 trait_test_arg<std::int32_t, std::int32_t, true, true>, \
178 trait_test_arg<std::int32_t, std::uint32_t, true, false>, \
179 trait_test_arg<std::uint32_t, std::int32_t, false, true>, \
180 trait_test_arg<std::uint32_t, std::uint32_t, true, true>, \
181 trait_test_arg<std::int32_t, std::int64_t, false, false>, \
182 trait_test_arg<std::int32_t, std::uint64_t, true, false>, \
183 trait_test_arg<std::uint32_t, std::int64_t, false, false>, \
184 trait_test_arg<std::uint32_t, std::uint64_t, true, false>, \
185 trait_test_arg<std::int64_t, std::int32_t, true, true>, \
186 trait_test_arg<std::int64_t, std::uint32_t, true, true>, \
187 trait_test_arg<std::uint64_t, std::int32_t, false, true>, \
188 trait_test_arg<std::uint64_t, std::uint32_t, true, true>, \
189 trait_test_arg<std::int64_t, std::int64_t, true, true>, \
190 trait_test_arg<std::int64_t, std::uint64_t, true, false>, \
191 trait_test_arg<std::uint64_t, std::int64_t, false, true>, \
192 trait_test_arg<std::uint64_t, std::uint64_t, true, true>);
193
194 #if SIZE_MAX == 0xffffffff
195 TEST_CASE_TEMPLATE_INVOKE(value_in_range_of_test, \
196 trait_test_arg<std::size_t, std::int32_t, false, true>, \
197 trait_test_arg<std::size_t, std::uint32_t, true, true>, \
198 trait_test_arg<std::size_t, std::int64_t, false, false>, \
199 trait_test_arg<std::size_t, std::uint64_t, true, false>);
200 #else
201 TEST_CASE_TEMPLATE_INVOKE(value_in_range_of_test, \
202 trait_test_arg<std::size_t, std::int32_t, false, true>, \
203 trait_test_arg<std::size_t, std::uint32_t, true, true>, \
204 trait_test_arg<std::size_t, std::int64_t, false, true>, \
205 trait_test_arg<std::size_t, std::uint64_t, true, true>);
206 #endif
207
208 TEST_CASE("BJData")
209 {
210 SECTION("binary_reader BJData LUT arrays are sorted")
211 {
212 std::vector<std::uint8_t> data;
213 auto ia = nlohmann::detail::input_adapter(data);
214 // NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg)
215 nlohmann::detail::binary_reader<json, decltype(ia)> br{std::move(ia), json::input_format_t::bjdata};
216
217 CHECK(std::is_sorted(br.bjd_optimized_type_markers.begin(), br.bjd_optimized_type_markers.end()));
218 CHECK(std::is_sorted(br.bjd_types_map.begin(), br.bjd_types_map.end()));
219 }
220
221 SECTION("individual values")
222 {
223 SECTION("discarded")
224 {
225 // discarded values are not serialized
226 json j = json::value_t::discarded;
227 const auto result = json::to_bjdata(j);
228 CHECK(result.empty());
229 }
230
231 SECTION("null")
232 {
233 json j = nullptr;
234 std::vector<uint8_t> expected = {'Z'};
235 const auto result = json::to_bjdata(j);
236 CHECK(result == expected);
237
238 // roundtrip
239 CHECK(json::from_bjdata(result) == j);
240 CHECK(json::from_bjdata(result, true, false) == j);
241 }
242
243 SECTION("boolean")
244 {
245 SECTION("true")
246 {
247 json j = true;
248 std::vector<uint8_t> expected = {'T'};
249 const auto result = json::to_bjdata(j);
250 CHECK(result == expected);
251
252 // roundtrip
253 CHECK(json::from_bjdata(result) == j);
254 CHECK(json::from_bjdata(result, true, false) == j);
255 }
256
257 SECTION("false")
258 {
259 json j = false;
260 std::vector<uint8_t> expected = {'F'};
261 const auto result = json::to_bjdata(j);
262 CHECK(result == expected);
263
264 // roundtrip
265 CHECK(json::from_bjdata(result) == j);
266 CHECK(json::from_bjdata(result, true, false) == j);
267 }
268 }
269
270 SECTION("number")
271 {
272 SECTION("signed")
273 {
274 SECTION("-9223372036854775808..-2147483649 (int64)")
275 {
276 std::vector<int64_t> numbers;
277 numbers.push_back((std::numeric_limits<int64_t>::min)());
278 numbers.push_back(-1000000000000000000LL);
279 numbers.push_back(-100000000000000000LL);
280 numbers.push_back(-10000000000000000LL);
281 numbers.push_back(-1000000000000000LL);
282 numbers.push_back(-100000000000000LL);
283 numbers.push_back(-10000000000000LL);
284 numbers.push_back(-1000000000000LL);
285 numbers.push_back(-100000000000LL);
286 numbers.push_back(-10000000000LL);
287 numbers.push_back(-2147483649LL);
288 for (auto i : numbers)
289 {
290 CAPTURE(i)
291
292 // create JSON value with integer number
293 json j = i;
294
295 // check type
296 CHECK(j.is_number_integer());
297
298 // create expected byte vector
299 std::vector<uint8_t> expected;
300 expected.push_back(static_cast<uint8_t>('L'));
301 expected.push_back(static_cast<uint8_t>(i & 0xff));
302 expected.push_back(static_cast<uint8_t>((i >> 8) & 0xff));
303 expected.push_back(static_cast<uint8_t>((i >> 16) & 0xff));
304 expected.push_back(static_cast<uint8_t>((i >> 24) & 0xff));
305 expected.push_back(static_cast<uint8_t>((i >> 32) & 0xff));
306 expected.push_back(static_cast<uint8_t>((i >> 40) & 0xff));
307 expected.push_back(static_cast<uint8_t>((i >> 48) & 0xff));
308 expected.push_back(static_cast<uint8_t>((i >> 56) & 0xff));
309
310 // compare result + size
311 const auto result = json::to_bjdata(j);
312 CHECK(result == expected);
313 CHECK(result.size() == 9);
314
315 // check individual bytes
316 CHECK(result[0] == 'L');
317 int64_t restored = (static_cast<int64_t>(result[8]) << 070) +
318 (static_cast<int64_t>(result[7]) << 060) +
319 (static_cast<int64_t>(result[6]) << 050) +
320 (static_cast<int64_t>(result[5]) << 040) +
321 (static_cast<int64_t>(result[4]) << 030) +
322 (static_cast<int64_t>(result[3]) << 020) +
323 (static_cast<int64_t>(result[2]) << 010) +
324 static_cast<int64_t>(result[1]);
325 CHECK(restored == i);
326
327 // roundtrip
328 CHECK(json::from_bjdata(result) == j);
329 CHECK(json::from_bjdata(result, true, false) == j);
330 }
331 }
332
333 SECTION("-2147483648..-32769 (int32)")
334 {
335 std::vector<int32_t> numbers;
336 numbers.push_back(-32769);
337 numbers.push_back(-100000);
338 numbers.push_back(-1000000);
339 numbers.push_back(-10000000);
340 numbers.push_back(-100000000);
341 numbers.push_back(-1000000000);
342 numbers.push_back(-2147483647 - 1); // https://stackoverflow.com/a/29356002/266378
343 for (auto i : numbers)
344 {
345 CAPTURE(i)
346
347 // create JSON value with integer number
348 json j = i;
349
350 // check type
351 CHECK(j.is_number_integer());
352
353 // create expected byte vector
354 std::vector<uint8_t> expected;
355 expected.push_back(static_cast<uint8_t>('l'));
356 expected.push_back(static_cast<uint8_t>(i & 0xff));
357 expected.push_back(static_cast<uint8_t>((i >> 8) & 0xff));
358 expected.push_back(static_cast<uint8_t>((i >> 16) & 0xff));
359 expected.push_back(static_cast<uint8_t>((i >> 24) & 0xff));
360
361 // compare result + size
362 const auto result = json::to_bjdata(j);
363 CHECK(result == expected);
364 CHECK(result.size() == 5);
365
366 // check individual bytes
367 CHECK(result[0] == 'l');
368 int32_t restored = (static_cast<int32_t>(result[4]) << 030) +
369 (static_cast<int32_t>(result[3]) << 020) +
370 (static_cast<int32_t>(result[2]) << 010) +
371 static_cast<int32_t>(result[1]);
372 CHECK(restored == i);
373
374 // roundtrip
375 CHECK(json::from_bjdata(result) == j);
376 CHECK(json::from_bjdata(result, true, false) == j);
377 }
378 }
379
380 SECTION("-32768..-129 (int16)")
381 {
382 for (int32_t i = -32768; i <= -129; ++i)
383 {
384 CAPTURE(i)
385
386 // create JSON value with integer number
387 json j = i;
388
389 // check type
390 CHECK(j.is_number_integer());
391
392 // create expected byte vector
393 std::vector<uint8_t> expected;
394 expected.push_back(static_cast<uint8_t>('I'));
395 expected.push_back(static_cast<uint8_t>(i & 0xff));
396 expected.push_back(static_cast<uint8_t>((i >> 8) & 0xff));
397
398 // compare result + size
399 const auto result = json::to_bjdata(j);
400 CHECK(result == expected);
401 CHECK(result.size() == 3);
402
403 // check individual bytes
404 CHECK(result[0] == 'I');
405 auto restored = static_cast<int16_t>(((result[2] << 8) + result[1]));
406 CHECK(restored == i);
407
408 // roundtrip
409 CHECK(json::from_bjdata(result) == j);
410 CHECK(json::from_bjdata(result, true, false) == j);
411 }
412 }
413
414 SECTION("-9263 (int16)")
415 {
416 json j = -9263;
417 std::vector<uint8_t> expected = {'I', 0xd1, 0xdb};
418
419 // compare result + size
420 const auto result = json::to_bjdata(j);
421 CHECK(result == expected);
422 CHECK(result.size() == 3);
423
424 // check individual bytes
425 CHECK(result[0] == 'I');
426 auto restored = static_cast<int16_t>(((result[2] << 8) + result[1]));
427 CHECK(restored == -9263);
428
429 // roundtrip
430 CHECK(json::from_bjdata(result) == j);
431 CHECK(json::from_bjdata(result, true, false) == j);
432 }
433
434 SECTION("-128..-1 (int8)")
435 {
436 for (auto i = -128; i <= -1; ++i)
437 {
438 CAPTURE(i)
439
440 // create JSON value with integer number
441 json j = i;
442
443 // check type
444 CHECK(j.is_number_integer());
445
446 // create expected byte vector
447 std::vector<uint8_t> expected;
448 expected.push_back('i');
449 expected.push_back(static_cast<uint8_t>(i));
450
451 // compare result + size
452 const auto result = json::to_bjdata(j);
453 CHECK(result == expected);
454 CHECK(result.size() == 2);
455
456 // check individual bytes
457 CHECK(result[0] == 'i');
458 CHECK(static_cast<int8_t>(result[1]) == i);
459
460 // roundtrip
461 CHECK(json::from_bjdata(result) == j);
462 CHECK(json::from_bjdata(result, true, false) == j);
463 }
464 }
465
466 SECTION("0..127 (int8)")
467 {
468 for (size_t i = 0; i <= 127; ++i)
469 {
470 CAPTURE(i)
471
472 // create JSON value with integer number
473 json j = -1;
474 j.get_ref<json::number_integer_t&>() = static_cast<json::number_integer_t>(i);
475
476 // check type
477 CHECK(j.is_number_integer());
478
479 // create expected byte vector
480 std::vector<uint8_t> expected;
481 expected.push_back(static_cast<uint8_t>('i'));
482 expected.push_back(static_cast<uint8_t>(i));
483
484 // compare result + size
485 const auto result = json::to_bjdata(j);
486 CHECK(result == expected);
487 CHECK(result.size() == 2);
488
489 // check individual bytes
490 CHECK(result[0] == 'i');
491 CHECK(result[1] == i);
492
493 // roundtrip
494 CHECK(json::from_bjdata(result) == j);
495 CHECK(json::from_bjdata(result, true, false) == j);
496 }
497 }
498
499 SECTION("128..255 (uint8)")
500 {
501 for (size_t i = 128; i <= 255; ++i)
502 {
503 CAPTURE(i)
504
505 // create JSON value with integer number
506 json j = -1;
507 j.get_ref<json::number_integer_t&>() = static_cast<json::number_integer_t>(i);
508
509 // check type
510 CHECK(j.is_number_integer());
511
512 // create expected byte vector
513 std::vector<uint8_t> expected;
514 expected.push_back(static_cast<uint8_t>('U'));
515 expected.push_back(static_cast<uint8_t>(i));
516
517 // compare result + size
518 const auto result = json::to_bjdata(j);
519 CHECK(result == expected);
520 CHECK(result.size() == 2);
521
522 // check individual bytes
523 CHECK(result[0] == 'U');
524 CHECK(result[1] == i);
525
526 // roundtrip
527 CHECK(json::from_bjdata(result) == j);
528 CHECK(json::from_bjdata(result, true, false) == j);
529 }
530 }
531
532 SECTION("256..32767 (int16)")
533 {
534 for (size_t i = 256; i <= 32767; ++i)
535 {
536 CAPTURE(i)
537
538 // create JSON value with integer number
539 json j = -1;
540 j.get_ref<json::number_integer_t&>() = static_cast<json::number_integer_t>(i);
541
542 // check type
543 CHECK(j.is_number_integer());
544
545 // create expected byte vector
546 std::vector<uint8_t> expected;
547 expected.push_back(static_cast<uint8_t>('I'));
548 expected.push_back(static_cast<uint8_t>(i & 0xff));
549 expected.push_back(static_cast<uint8_t>((i >> 8) & 0xff));
550
551 // compare result + size
552 const auto result = json::to_bjdata(j);
553 CHECK(result == expected);
554 CHECK(result.size() == 3);
555
556 // check individual bytes
557 CHECK(result[0] == 'I');
558 auto restored = static_cast<uint16_t>(static_cast<uint8_t>(result[2]) * 256 + static_cast<uint8_t>(result[1]));
559 CHECK(restored == i);
560
561 // roundtrip
562 CHECK(json::from_bjdata(result) == j);
563 CHECK(json::from_bjdata(result, true, false) == j);
564 }
565 }
566
567 SECTION("32768..65535 (uint16)")
568 {
569 for (uint32_t i :
570 {
571 32768u, 55555u, 65535u
572 })
573 {
574 CAPTURE(i)
575
576 // create JSON value with integer number
577 json j = -1;
578 j.get_ref<json::number_integer_t&>() = static_cast<json::number_integer_t>(i);
579
580 // check type
581 CHECK(j.is_number_integer());
582
583 // create expected byte vector
584 std::vector<uint8_t> expected;
585 expected.push_back(static_cast<uint8_t>('u'));
586 expected.push_back(static_cast<uint8_t>(i & 0xff));
587 expected.push_back(static_cast<uint8_t>((i >> 8) & 0xff));
588
589 // compare result + size
590 const auto result = json::to_bjdata(j);
591 CHECK(result == expected);
592 CHECK(result.size() == 3);
593
594 // check individual bytes
595 CHECK(result[0] == 'u');
596 auto restored = static_cast<uint16_t>(static_cast<uint8_t>(result[2]) * 256 + static_cast<uint8_t>(result[1]));
597 CHECK(restored == i);
598
599 // roundtrip
600 CHECK(json::from_bjdata(result) == j);
601 CHECK(json::from_bjdata(result, true, false) == j);
602 }
603 }
604
605 SECTION("65536..2147483647 (int32)")
606 {
607 for (uint32_t i :
608 {
609 65536u, 77777u, 2147483647u
610 })
611 {
612 CAPTURE(i)
613
614 // create JSON value with integer number
615 json j = -1;
616 j.get_ref<json::number_integer_t&>() = static_cast<json::number_integer_t>(i);
617
618 // check type
619 CHECK(j.is_number_integer());
620
621 // create expected byte vector
622 std::vector<uint8_t> expected;
623 expected.push_back('l');
624 expected.push_back(static_cast<uint8_t>(i & 0xff));
625 expected.push_back(static_cast<uint8_t>((i >> 8) & 0xff));
626 expected.push_back(static_cast<uint8_t>((i >> 16) & 0xff));
627 expected.push_back(static_cast<uint8_t>((i >> 24) & 0xff));
628
629 // compare result + size
630 const auto result = json::to_bjdata(j);
631 CHECK(result == expected);
632 CHECK(result.size() == 5);
633
634 // check individual bytes
635 CHECK(result[0] == 'l');
636 uint32_t restored = (static_cast<uint32_t>(result[4]) << 030) +
637 (static_cast<uint32_t>(result[3]) << 020) +
638 (static_cast<uint32_t>(result[2]) << 010) +
639 static_cast<uint32_t>(result[1]);
640 CHECK(restored == i);
641
642 // roundtrip
643 CHECK(json::from_bjdata(result) == j);
644 CHECK(json::from_bjdata(result, true, false) == j);
645 }
646 }
647
648 SECTION("2147483648..4294967295 (uint32)")
649 {
650 for (uint32_t i :
651 {
652 2147483648u, 3333333333u, 4294967295u
653 })
654 {
655 CAPTURE(i)
656
657 // create JSON value with integer number
658 json j = -1;
659 j.get_ref<json::number_integer_t&>() = static_cast<json::number_integer_t>(i);
660
661 // check type
662 CHECK(j.is_number_integer());
663
664 // create expected byte vector
665 std::vector<uint8_t> expected;
666 expected.push_back('m');
667 expected.push_back(static_cast<uint8_t>(i & 0xff));
668 expected.push_back(static_cast<uint8_t>((i >> 8) & 0xff));
669 expected.push_back(static_cast<uint8_t>((i >> 16) & 0xff));
670 expected.push_back(static_cast<uint8_t>((i >> 24) & 0xff));
671
672 // compare result + size
673 const auto result = json::to_bjdata(j);
674 CHECK(result == expected);
675 CHECK(result.size() == 5);
676
677 // check individual bytes
678 CHECK(result[0] == 'm');
679 uint32_t restored = (static_cast<uint32_t>(result[4]) << 030) +
680 (static_cast<uint32_t>(result[3]) << 020) +
681 (static_cast<uint32_t>(result[2]) << 010) +
682 static_cast<uint32_t>(result[1]);
683 CHECK(restored == i);
684
685 // roundtrip
686 CHECK(json::from_bjdata(result) == j);
687 CHECK(json::from_bjdata(result, true, false) == j);
688 }
689 }
690
691 SECTION("4294967296..9223372036854775807 (int64)")
692 {
693 std::vector<uint64_t> v = {4294967296LU, 9223372036854775807LU};
694 for (uint64_t i : v)
695 {
696 CAPTURE(i)
697
698 // create JSON value with integer number
699 json j = -1;
700 j.get_ref<json::number_integer_t&>() = static_cast<json::number_integer_t>(i);
701
702 // check type
703 CHECK(j.is_number_integer());
704
705 // create expected byte vector
706 std::vector<uint8_t> expected;
707 expected.push_back('L');
708 expected.push_back(static_cast<uint8_t>(i & 0xff));
709 expected.push_back(static_cast<uint8_t>((i >> 010) & 0xff));
710 expected.push_back(static_cast<uint8_t>((i >> 020) & 0xff));
711 expected.push_back(static_cast<uint8_t>((i >> 030) & 0xff));
712 expected.push_back(static_cast<uint8_t>((i >> 040) & 0xff));
713 expected.push_back(static_cast<uint8_t>((i >> 050) & 0xff));
714 expected.push_back(static_cast<uint8_t>((i >> 060) & 0xff));
715 expected.push_back(static_cast<uint8_t>((i >> 070) & 0xff));
716
717 // compare result + size
718 const auto result = json::to_bjdata(j);
719 CHECK(result == expected);
720 CHECK(result.size() == 9);
721
722 // check individual bytes
723 CHECK(result[0] == 'L');
724 uint64_t restored = (static_cast<uint64_t>(result[8]) << 070) +
725 (static_cast<uint64_t>(result[7]) << 060) +
726 (static_cast<uint64_t>(result[6]) << 050) +
727 (static_cast<uint64_t>(result[5]) << 040) +
728 (static_cast<uint64_t>(result[4]) << 030) +
729 (static_cast<uint64_t>(result[3]) << 020) +
730 (static_cast<uint64_t>(result[2]) << 010) +
731 static_cast<uint64_t>(result[1]);
732 CHECK(restored == i);
733
734 // roundtrip
735 CHECK(json::from_bjdata(result) == j);
736 CHECK(json::from_bjdata(result, true, false) == j);
737 }
738 }
739
740 SECTION("9223372036854775808..18446744073709551615 (uint64)")
741 {
742 std::vector<uint64_t> v = {9223372036854775808ull, 18446744073709551615ull};
743 for (uint64_t i : v)
744 {
745 CAPTURE(i)
746
747 // create JSON value with integer number
748 json j = i;
749
750 // check type
751 CHECK(j.is_number_unsigned());
752
753 // create expected byte vector
754 std::vector<uint8_t> expected;
755 expected.push_back('M');
756 expected.push_back(static_cast<uint8_t>(i & 0xff));
757 expected.push_back(static_cast<uint8_t>((i >> 010) & 0xff));
758 expected.push_back(static_cast<uint8_t>((i >> 020) & 0xff));
759 expected.push_back(static_cast<uint8_t>((i >> 030) & 0xff));
760 expected.push_back(static_cast<uint8_t>((i >> 040) & 0xff));
761 expected.push_back(static_cast<uint8_t>((i >> 050) & 0xff));
762 expected.push_back(static_cast<uint8_t>((i >> 060) & 0xff));
763 expected.push_back(static_cast<uint8_t>((i >> 070) & 0xff));
764
765 // compare result + size
766 const auto result = json::to_bjdata(j);
767 CHECK(result == expected);
768 CHECK(result.size() == 9);
769
770 // check individual bytes
771 CHECK(result[0] == 'M');
772 uint64_t restored = (static_cast<uint64_t>(result[8]) << 070) +
773 (static_cast<uint64_t>(result[7]) << 060) +
774 (static_cast<uint64_t>(result[6]) << 050) +
775 (static_cast<uint64_t>(result[5]) << 040) +
776 (static_cast<uint64_t>(result[4]) << 030) +
777 (static_cast<uint64_t>(result[3]) << 020) +
778 (static_cast<uint64_t>(result[2]) << 010) +
779 static_cast<uint64_t>(result[1]);
780 CHECK(restored == i);
781
782 // roundtrip
783 CHECK(json::from_bjdata(result) == j);
784 CHECK(json::from_bjdata(result, true, false) == j);
785 }
786 }
787 }
788
789 SECTION("unsigned")
790 {
791 SECTION("0..127 (int8)")
792 {
793 for (size_t i = 0; i <= 127; ++i)
794 {
795 CAPTURE(i)
796
797 // create JSON value with unsigned integer number
798 json j = i;
799
800 // check type
801 CHECK(j.is_number_unsigned());
802
803 // create expected byte vector
804 std::vector<uint8_t> expected;
805 expected.push_back('i');
806 expected.push_back(static_cast<uint8_t>(i));
807
808 // compare result + size
809 const auto result = json::to_bjdata(j);
810 CHECK(result == expected);
811 CHECK(result.size() == 2);
812
813 // check individual bytes
814 CHECK(result[0] == 'i');
815 auto restored = static_cast<uint8_t>(result[1]);
816 CHECK(restored == i);
817
818 // roundtrip
819 CHECK(json::from_bjdata(result) == j);
820 CHECK(json::from_bjdata(result, true, false) == j);
821 }
822 }
823
824 SECTION("128..255 (uint8)")
825 {
826 for (size_t i = 128; i <= 255; ++i)
827 {
828 CAPTURE(i)
829
830 // create JSON value with unsigned integer number
831 json j = i;
832
833 // check type
834 CHECK(j.is_number_unsigned());
835
836 // create expected byte vector
837 std::vector<uint8_t> expected;
838 expected.push_back('U');
839 expected.push_back(static_cast<uint8_t>(i));
840
841 // compare result + size
842 const auto result = json::to_bjdata(j);
843 CHECK(result == expected);
844 CHECK(result.size() == 2);
845
846 // check individual bytes
847 CHECK(result[0] == 'U');
848 auto restored = static_cast<uint8_t>(result[1]);
849 CHECK(restored == i);
850
851 // roundtrip
852 CHECK(json::from_bjdata(result) == j);
853 CHECK(json::from_bjdata(result, true, false) == j);
854 }
855 }
856
857 SECTION("256..32767 (int16)")
858 {
859 for (size_t i = 256; i <= 32767; ++i)
860 {
861 CAPTURE(i)
862
863 // create JSON value with unsigned integer number
864 json j = i;
865
866 // check type
867 CHECK(j.is_number_unsigned());
868
869 // create expected byte vector
870 std::vector<uint8_t> expected;
871 expected.push_back('I');
872 expected.push_back(static_cast<uint8_t>(i & 0xff));
873 expected.push_back(static_cast<uint8_t>((i >> 8) & 0xff));
874
875 // compare result + size
876 const auto result = json::to_bjdata(j);
877 CHECK(result == expected);
878 CHECK(result.size() == 3);
879
880 // check individual bytes
881 CHECK(result[0] == 'I');
882 auto restored = static_cast<uint16_t>(static_cast<uint8_t>(result[2]) * 256 + static_cast<uint8_t>(result[1]));
883 CHECK(restored == i);
884
885 // roundtrip
886 CHECK(json::from_bjdata(result) == j);
887 CHECK(json::from_bjdata(result, true, false) == j);
888 }
889 }
890
891 SECTION("32768..65535 (uint16)")
892 {
893 for (uint32_t i :
894 {
895 32768u, 55555u, 65535u
896 })
897 {
898 CAPTURE(i)
899
900 // create JSON value with unsigned integer number
901 json j = i;
902
903 // check type
904 CHECK(j.is_number_unsigned());
905
906 // create expected byte vector
907 std::vector<uint8_t> expected;
908 expected.push_back('u');
909 expected.push_back(static_cast<uint8_t>(i & 0xff));
910 expected.push_back(static_cast<uint8_t>((i >> 8) & 0xff));
911
912 // compare result + size
913 const auto result = json::to_bjdata(j);
914 CHECK(result == expected);
915 CHECK(result.size() == 3);
916
917 // check individual bytes
918 CHECK(result[0] == 'u');
919 auto restored = static_cast<uint16_t>(static_cast<uint8_t>(result[2]) * 256 + static_cast<uint8_t>(result[1]));
920 CHECK(restored == i);
921
922 // roundtrip
923 CHECK(json::from_bjdata(result) == j);
924 CHECK(json::from_bjdata(result, true, false) == j);
925 }
926 }
927 SECTION("65536..2147483647 (int32)")
928 {
929 for (uint32_t i :
930 {
931 65536u, 77777u, 2147483647u
932 })
933 {
934 CAPTURE(i)
935
936 // create JSON value with unsigned integer number
937 json j = i;
938
939 // check type
940 CHECK(j.is_number_unsigned());
941
942 // create expected byte vector
943 std::vector<uint8_t> expected;
944 expected.push_back('l');
945 expected.push_back(static_cast<uint8_t>(i & 0xff));
946 expected.push_back(static_cast<uint8_t>((i >> 8) & 0xff));
947 expected.push_back(static_cast<uint8_t>((i >> 16) & 0xff));
948 expected.push_back(static_cast<uint8_t>((i >> 24) & 0xff));
949
950 // compare result + size
951 const auto result = json::to_bjdata(j);
952 CHECK(result == expected);
953 CHECK(result.size() == 5);
954
955 // check individual bytes
956 CHECK(result[0] == 'l');
957 uint32_t restored = (static_cast<uint32_t>(result[4]) << 030) +
958 (static_cast<uint32_t>(result[3]) << 020) +
959 (static_cast<uint32_t>(result[2]) << 010) +
960 static_cast<uint32_t>(result[1]);
961 CHECK(restored == i);
962
963 // roundtrip
964 CHECK(json::from_bjdata(result) == j);
965 CHECK(json::from_bjdata(result, true, false) == j);
966 }
967 }
968
969 SECTION("2147483648..4294967295 (uint32)")
970 {
971 for (uint32_t i :
972 {
973 2147483648u, 3333333333u, 4294967295u
974 })
975 {
976 CAPTURE(i)
977
978 // create JSON value with unsigned integer number
979 json j = i;
980
981 // check type
982 CHECK(j.is_number_unsigned());
983
984 // create expected byte vector
985 std::vector<uint8_t> expected;
986 expected.push_back('m');
987 expected.push_back(static_cast<uint8_t>(i & 0xff));
988 expected.push_back(static_cast<uint8_t>((i >> 8) & 0xff));
989 expected.push_back(static_cast<uint8_t>((i >> 16) & 0xff));
990 expected.push_back(static_cast<uint8_t>((i >> 24) & 0xff));
991
992 // compare result + size
993 const auto result = json::to_bjdata(j);
994 CHECK(result == expected);
995 CHECK(result.size() == 5);
996
997 // check individual bytes
998 CHECK(result[0] == 'm');
999 uint32_t restored = (static_cast<uint32_t>(result[4]) << 030) +
1000 (static_cast<uint32_t>(result[3]) << 020) +
1001 (static_cast<uint32_t>(result[2]) << 010) +
1002 static_cast<uint32_t>(result[1]);
1003 CHECK(restored == i);
1004
1005 // roundtrip
1006 CHECK(json::from_bjdata(result) == j);
1007 CHECK(json::from_bjdata(result, true, false) == j);
1008 }
1009 }
1010
1011 SECTION("4294967296..9223372036854775807 (int64)")
1012 {
1013 std::vector<uint64_t> v = {4294967296ul, 9223372036854775807ul};
1014 for (uint64_t i : v)
1015 {
1016 CAPTURE(i)
1017
1018 // create JSON value with integer number
1019 json j = i;
1020
1021 // check type
1022 CHECK(j.is_number_unsigned());
1023
1024 // create expected byte vector
1025 std::vector<uint8_t> expected;
1026 expected.push_back('L');
1027 expected.push_back(static_cast<uint8_t>(i & 0xff));
1028 expected.push_back(static_cast<uint8_t>((i >> 010) & 0xff));
1029 expected.push_back(static_cast<uint8_t>((i >> 020) & 0xff));
1030 expected.push_back(static_cast<uint8_t>((i >> 030) & 0xff));
1031 expected.push_back(static_cast<uint8_t>((i >> 040) & 0xff));
1032 expected.push_back(static_cast<uint8_t>((i >> 050) & 0xff));
1033 expected.push_back(static_cast<uint8_t>((i >> 060) & 0xff));
1034 expected.push_back(static_cast<uint8_t>((i >> 070) & 0xff));
1035
1036 // compare result + size
1037 const auto result = json::to_bjdata(j);
1038 CHECK(result == expected);
1039 CHECK(result.size() == 9);
1040
1041 // check individual bytes
1042 CHECK(result[0] == 'L');
1043 uint64_t restored = (static_cast<uint64_t>(result[8]) << 070) +
1044 (static_cast<uint64_t>(result[7]) << 060) +
1045 (static_cast<uint64_t>(result[6]) << 050) +
1046 (static_cast<uint64_t>(result[5]) << 040) +
1047 (static_cast<uint64_t>(result[4]) << 030) +
1048 (static_cast<uint64_t>(result[3]) << 020) +
1049 (static_cast<uint64_t>(result[2]) << 010) +
1050 static_cast<uint64_t>(result[1]);
1051 CHECK(restored == i);
1052
1053 // roundtrip
1054 CHECK(json::from_bjdata(result) == j);
1055 CHECK(json::from_bjdata(result, true, false) == j);
1056 }
1057 }
1058
1059 SECTION("9223372036854775808..18446744073709551615 (uint64)")
1060 {
1061 std::vector<uint64_t> v = {9223372036854775808ull, 18446744073709551615ull};
1062 for (uint64_t i : v)
1063 {
1064 CAPTURE(i)
1065
1066 // create JSON value with integer number
1067 json j = i;
1068
1069 // check type
1070 CHECK(j.is_number_unsigned());
1071
1072 // create expected byte vector
1073 std::vector<uint8_t> expected;
1074 expected.push_back('M');
1075 expected.push_back(static_cast<uint8_t>(i & 0xff));
1076 expected.push_back(static_cast<uint8_t>((i >> 010) & 0xff));
1077 expected.push_back(static_cast<uint8_t>((i >> 020) & 0xff));
1078 expected.push_back(static_cast<uint8_t>((i >> 030) & 0xff));
1079 expected.push_back(static_cast<uint8_t>((i >> 040) & 0xff));
1080 expected.push_back(static_cast<uint8_t>((i >> 050) & 0xff));
1081 expected.push_back(static_cast<uint8_t>((i >> 060) & 0xff));
1082 expected.push_back(static_cast<uint8_t>((i >> 070) & 0xff));
1083
1084 // compare result + size
1085 const auto result = json::to_bjdata(j);
1086 CHECK(result == expected);
1087 CHECK(result.size() == 9);
1088
1089 // check individual bytes
1090 CHECK(result[0] == 'M');
1091 uint64_t restored = (static_cast<uint64_t>(result[8]) << 070) +
1092 (static_cast<uint64_t>(result[7]) << 060) +
1093 (static_cast<uint64_t>(result[6]) << 050) +
1094 (static_cast<uint64_t>(result[5]) << 040) +
1095 (static_cast<uint64_t>(result[4]) << 030) +
1096 (static_cast<uint64_t>(result[3]) << 020) +
1097 (static_cast<uint64_t>(result[2]) << 010) +
1098 static_cast<uint64_t>(result[1]);
1099 CHECK(restored == i);
1100
1101 // roundtrip
1102 CHECK(json::from_bjdata(result) == j);
1103 CHECK(json::from_bjdata(result, true, false) == j);
1104 }
1105 }
1106 }
1107 SECTION("float64")
1108 {
1109 SECTION("3.1415925")
1110 {
1111 double v = 3.1415925;
1112 json j = v;
1113 std::vector<uint8_t> expected =
1114 {
1115 'D', 0xfc, 0xde, 0xa6, 0x3f, 0xfb, 0x21, 0x09, 0x40
1116 };
1117 const auto result = json::to_bjdata(j);
1118 CHECK(result == expected);
1119
1120 // roundtrip
1121 CHECK(json::from_bjdata(result) == j);
1122 CHECK(json::from_bjdata(result) == v);
1123 CHECK(json::from_bjdata(result, true, false) == j);
1124 }
1125 }
1126
1127 SECTION("half-precision float")
1128 {
1129 SECTION("simple half floats")
1130 {
1131 CHECK(json::parse("0.0") == json::from_bjdata(std::vector<uint8_t>({'h', 0x00, 0x00})));
1132 CHECK(json::parse("-0.0") == json::from_bjdata(std::vector<uint8_t>({'h', 0x00, 0x80})));
1133 CHECK(json::parse("1.0") == json::from_bjdata(std::vector<uint8_t>({'h', 0x00, 0x3c})));
1134 CHECK(json::parse("1.5") == json::from_bjdata(std::vector<uint8_t>({'h', 0x00, 0x3e})));
1135 CHECK(json::parse("65504.0") == json::from_bjdata(std::vector<uint8_t>({'h', 0xff, 0x7b})));
1136 }
1137
1138 SECTION("errors")
1139 {
1140 SECTION("no byte follows")
1141 {
1142 json _;
1143 std::vector<uint8_t> vec0 = {'h'};
1144 CHECK_THROWS_WITH_AS(_ = json::from_bjdata(vec0), "[json.exception.parse_error.110] parse error at byte 2: syntax error while parsing BJData number: unexpected end of input", json::parse_error&);
1145 CHECK(json::from_bjdata(vec0, true, false).is_discarded());
1146 }
1147
1148 SECTION("only one byte follows")
1149 {
1150 json _;
1151 std::vector<uint8_t> vec1 = {'h', 0x00};
1152 CHECK_THROWS_WITH_AS(_ = json::from_bjdata(vec1), "[json.exception.parse_error.110] parse error at byte 3: syntax error while parsing BJData number: unexpected end of input", json::parse_error&);
1153 CHECK(json::from_bjdata(vec1, true, false).is_discarded());
1154 }
1155 }
1156 }
1157
1158 SECTION("half-precision float (edge cases)")
1159 {
1160 SECTION("exp = 0b00000")
1161 {
1162 SECTION("0 (0 00000 0000000000)")
1163 {
1164 json j = json::from_bjdata(std::vector<uint8_t>({'h', 0x00, 0x00}));
1165 json::number_float_t d{j};
1166 CHECK(d == 0.0);
1167 }
1168
1169 SECTION("-0 (1 00000 0000000000)")
1170 {
1171 json j = json::from_bjdata(std::vector<uint8_t>({'h', 0x00, 0x80}));
1172 json::number_float_t d{j};
1173 CHECK(d == -0.0);
1174 }
1175
1176 SECTION("2**-24 (0 00000 0000000001)")
1177 {
1178 json j = json::from_bjdata(std::vector<uint8_t>({'h', 0x01, 0x00}));
1179 json::number_float_t d{j};
1180 CHECK(d == std::pow(2.0, -24.0));
1181 }
1182 }
1183
1184 SECTION("exp = 0b11111")
1185 {
1186 SECTION("infinity (0 11111 0000000000)")
1187 {
1188 json j = json::from_bjdata(std::vector<uint8_t>({'h', 0x00, 0x7c}));
1189 json::number_float_t d{j};
1190 CHECK(d == std::numeric_limits<json::number_float_t>::infinity());
1191 CHECK(j.dump() == "null");
1192 }
1193
1194 SECTION("-infinity (1 11111 0000000000)")
1195 {
1196 json j = json::from_bjdata(std::vector<uint8_t>({'h', 0x00, 0xfc}));
1197 json::number_float_t d{j};
1198 CHECK(d == -std::numeric_limits<json::number_float_t>::infinity());
1199 CHECK(j.dump() == "null");
1200 }
1201 }
1202
1203 SECTION("other values from https://en.wikipedia.org/wiki/Half-precision_floating-point_format")
1204 {
1205 SECTION("1 (0 01111 0000000000)")
1206 {
1207 json j = json::from_bjdata(std::vector<uint8_t>({'h', 0x00, 0x3c}));
1208 json::number_float_t d{j};
1209 CHECK(d == 1);
1210 }
1211
1212 SECTION("-2 (1 10000 0000000000)")
1213 {
1214 json j = json::from_bjdata(std::vector<uint8_t>({'h', 0x00, 0xc0}));
1215 json::number_float_t d{j};
1216 CHECK(d == -2);
1217 }
1218
1219 SECTION("65504 (0 11110 1111111111)")
1220 {
1221 json j = json::from_bjdata(std::vector<uint8_t>({'h', 0xff, 0x7b}));
1222 json::number_float_t d{j};
1223 CHECK(d == 65504);
1224 }
1225 }
1226
1227 SECTION("infinity")
1228 {
1229 json j = json::from_bjdata(std::vector<uint8_t>({'h', 0x00, 0x7c}));
1230 json::number_float_t d{j};
1231 CHECK_FALSE(std::isfinite(d));
1232 CHECK(j.dump() == "null");
1233 }
1234
1235 SECTION("NaN")
1236 {
1237 json j = json::from_bjdata(std::vector<uint8_t>({'h', 0x00, 0x7e }));
1238 json::number_float_t d{j};
1239 CHECK(std::isnan(d));
1240 CHECK(j.dump() == "null");
1241 }
1242 }
1243
1244 SECTION("high-precision number")
1245 {
1246 SECTION("unsigned integer number")
1247 {
1248 std::vector<uint8_t> vec = {'H', 'i', 0x14, '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0'};
1249 const auto j = json::from_bjdata(vec);
1250 CHECK(j.is_number_unsigned());
1251 CHECK(j.dump() == "12345678901234567890");
1252 }
1253
1254 SECTION("signed integer number")
1255 {
1256 std::vector<uint8_t> vec = {'H', 'i', 0x13, '-', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8'};
1257 const auto j = json::from_bjdata(vec);
1258 CHECK(j.is_number_integer());
1259 CHECK(j.dump() == "-123456789012345678");
1260 }
1261
1262 SECTION("floating-point number")
1263 {
1264 std::vector<uint8_t> vec = {'H', 'i', 0x16, '3', '.', '1', '4', '1', '5', '9', '2', '6', '5', '3', '5', '8', '9', '7', '9', '3', '2', '3', '8', '4', '6'};
1265 const auto j = json::from_bjdata(vec);
1266 CHECK(j.is_number_float());
1267 CHECK(j.dump() == "3.141592653589793");
1268 }
1269
1270 SECTION("errors")
1271 {
1272 // error while parsing length
1273 std::vector<uint8_t> vec0 = {'H', 'i'};
1274 CHECK(json::from_bjdata(vec0, true, false).is_discarded());
1275 // error while parsing string
1276 std::vector<uint8_t> vec1 = {'H', 'i', '1'};
1277 CHECK(json::from_bjdata(vec1, true, false).is_discarded());
1278
1279 json _;
1280 std::vector<uint8_t> vec2 = {'H', 'i', 2, '1', 'A', '3'};
1281 CHECK_THROWS_WITH_AS(_ = json::from_bjdata(vec2), "[json.exception.parse_error.115] parse error at byte 5: syntax error while parsing BJData high-precision number: invalid number text: 1A", json::parse_error);
1282 std::vector<uint8_t> vec3 = {'H', 'i', 2, '1', '.'};
1283 CHECK_THROWS_WITH_AS(_ = json::from_bjdata(vec3), "[json.exception.parse_error.115] parse error at byte 5: syntax error while parsing BJData high-precision number: invalid number text: 1.", json::parse_error);
1284 std::vector<uint8_t> vec4 = {'H', 2, '1', '0'};
1285 CHECK_THROWS_WITH_AS(_ = json::from_bjdata(vec4), "[json.exception.parse_error.113] parse error at byte 2: syntax error while parsing BJData size: expected length type specification (U, i, u, I, m, l, M, L) after '#'; last byte: 0x02", json::parse_error);
1286 }
1287 }
1288 }
1289
1290 SECTION("string")
1291 {
1292 SECTION("N = 0..127")
1293 {
1294 for (size_t N = 0; N <= 127; ++N)
1295 {
1296 CAPTURE(N)
1297
1298 // create JSON value with string containing of N * 'x'
1299 const auto s = std::string(N, 'x');
1300 json j = s;
1301
1302 // create expected byte vector
1303 std::vector<uint8_t> expected;
1304 expected.push_back('S');
1305 expected.push_back('i');
1306 expected.push_back(static_cast<uint8_t>(N));
1307 for (size_t i = 0; i < N; ++i)
1308 {
1309 expected.push_back('x');
1310 }
1311
1312 // compare result + size
1313 const auto result = json::to_bjdata(j);
1314 CHECK(result == expected);
1315 CHECK(result.size() == N + 3);
1316 // check that no null byte is appended
1317 if (N > 0)
1318 {
1319 CHECK(result.back() != '\x00');
1320 }
1321
1322 // roundtrip
1323 CHECK(json::from_bjdata(result) == j);
1324 CHECK(json::from_bjdata(result, true, false) == j);
1325 }
1326 }
1327
1328 SECTION("N = 128..255")
1329 {
1330 for (size_t N = 128; N <= 255; ++N)
1331 {
1332 CAPTURE(N)
1333
1334 // create JSON value with string containing of N * 'x'
1335 const auto s = std::string(N, 'x');
1336 json j = s;
1337
1338 // create expected byte vector
1339 std::vector<uint8_t> expected;
1340 expected.push_back('S');
1341 expected.push_back('U');
1342 expected.push_back(static_cast<uint8_t>(N));
1343 for (size_t i = 0; i < N; ++i)
1344 {
1345 expected.push_back('x');
1346 }
1347
1348 // compare result + size
1349 const auto result = json::to_bjdata(j);
1350 CHECK(result == expected);
1351 CHECK(result.size() == N + 3);
1352 // check that no null byte is appended
1353 CHECK(result.back() != '\x00');
1354
1355 // roundtrip
1356 CHECK(json::from_bjdata(result) == j);
1357 CHECK(json::from_bjdata(result, true, false) == j);
1358 }
1359 }
1360
1361 SECTION("N = 256..32767")
1362 {
1363 for (size_t N :
1364 {
1365 256u, 999u, 1025u, 3333u, 2048u, 32767u
1366 })
1367 {
1368 CAPTURE(N)
1369
1370 // create JSON value with string containing of N * 'x'
1371 const auto s = std::string(N, 'x');
1372 json j = s;
1373
1374 // create expected byte vector (hack: create string first)
1375 std::vector<uint8_t> expected(N, 'x');
1376 // reverse order of commands, because we insert at begin()
1377 expected.insert(expected.begin(), static_cast<uint8_t>((N >> 8) & 0xff));
1378 expected.insert(expected.begin(), static_cast<uint8_t>(N & 0xff));
1379 expected.insert(expected.begin(), 'I');
1380 expected.insert(expected.begin(), 'S');
1381
1382 // compare result + size
1383 const auto result = json::to_bjdata(j);
1384 CHECK(result == expected);
1385 CHECK(result.size() == N + 4);
1386 // check that no null byte is appended
1387 CHECK(result.back() != '\x00');
1388
1389 // roundtrip
1390 CHECK(json::from_bjdata(result) == j);
1391 CHECK(json::from_bjdata(result, true, false) == j);
1392 }
1393 }
1394
1395 SECTION("N = 32768..65535")
1396 {
1397 for (size_t N :
1398 {
1399 32768u, 55555u, 65535u
1400 })
1401 {
1402 CAPTURE(N)
1403
1404 // create JSON value with string containing of N * 'x'
1405 const auto s = std::string(N, 'x');
1406 json j = s;
1407
1408 // create expected byte vector (hack: create string first)
1409 std::vector<uint8_t> expected(N, 'x');
1410 // reverse order of commands, because we insert at begin()
1411 expected.insert(expected.begin(), static_cast<uint8_t>((N >> 8) & 0xff));
1412 expected.insert(expected.begin(), static_cast<uint8_t>(N & 0xff));
1413 expected.insert(expected.begin(), 'u');
1414 expected.insert(expected.begin(), 'S');
1415
1416 // compare result + size
1417 const auto result = json::to_bjdata(j);
1418 CHECK(result == expected);
1419 CHECK(result.size() == N + 4);
1420 // check that no null byte is appended
1421 CHECK(result.back() != '\x00');
1422
1423 // roundtrip
1424 CHECK(json::from_bjdata(result) == j);
1425 CHECK(json::from_bjdata(result, true, false) == j);
1426 }
1427 }
1428
1429 SECTION("N = 65536..2147483647")
1430 {
1431 for (size_t N :
1432 {
1433 65536u, 77777u, 1048576u
1434 })
1435 {
1436 CAPTURE(N)
1437
1438 // create JSON value with string containing of N * 'x'
1439 const auto s = std::string(N, 'x');
1440 json j = s;
1441
1442 // create expected byte vector (hack: create string first)
1443 std::vector<uint8_t> expected(N, 'x');
1444 // reverse order of commands, because we insert at begin()
1445 expected.insert(expected.begin(), static_cast<uint8_t>((N >> 24) & 0xff));
1446 expected.insert(expected.begin(), static_cast<uint8_t>((N >> 16) & 0xff));
1447 expected.insert(expected.begin(), static_cast<uint8_t>((N >> 8) & 0xff));
1448 expected.insert(expected.begin(), static_cast<uint8_t>(N & 0xff));
1449 expected.insert(expected.begin(), 'l');
1450 expected.insert(expected.begin(), 'S');
1451
1452 // compare result + size
1453 const auto result = json::to_bjdata(j);
1454 CHECK(result == expected);
1455 CHECK(result.size() == N + 6);
1456 // check that no null byte is appended
1457 CHECK(result.back() != '\x00');
1458
1459 // roundtrip
1460 CHECK(json::from_bjdata(result) == j);
1461 CHECK(json::from_bjdata(result, true, false) == j);
1462 }
1463 }
1464 }
1465
1466
1467 SECTION("binary")
1468 {
1469 SECTION("N = 0..127")
1470 {
1471 for (std::size_t N = 0; N <= 127; ++N)
1472 {
1473 CAPTURE(N)
1474
1475 // create JSON value with byte array containing of N * 'x'
1476 const auto s = std::vector<std::uint8_t>(N, 'x');
1477 json j = json::binary(s);
1478
1479 // create expected byte vector
1480 std::vector<std::uint8_t> expected;
1481 expected.push_back(static_cast<std::uint8_t>('['));
1482 if (N != 0)
1483 {
1484 expected.push_back(static_cast<std::uint8_t>('$'));
1485 expected.push_back(static_cast<std::uint8_t>('U'));
1486 }
1487 expected.push_back(static_cast<std::uint8_t>('#'));
1488 expected.push_back(static_cast<std::uint8_t>('i'));
1489 expected.push_back(static_cast<std::uint8_t>(N));
1490 for (size_t i = 0; i < N; ++i)
1491 {
1492 expected.push_back(0x78);
1493 }
1494
1495 // compare result + size
1496 const auto result = json::to_bjdata(j, true, true);
1497 CHECK(result == expected);
1498 if (N == 0)
1499 {
1500 CHECK(result.size() == N + 4);
1501 }
1502 else
1503 {
1504 CHECK(result.size() == N + 6);
1505 }
1506
1507 // check that no null byte is appended
1508 if (N > 0)
1509 {
1510 CHECK(result.back() != '\x00');
1511 }
1512
1513 // roundtrip only works to an array of numbers
1514 json j_out = s;
1515 CHECK(json::from_bjdata(result) == j_out);
1516 CHECK(json::from_bjdata(result, true, false) == j_out);
1517 }
1518 }
1519
1520 SECTION("N = 128..255")
1521 {
1522 for (std::size_t N = 128; N <= 255; ++N)
1523 {
1524 CAPTURE(N)
1525
1526 // create JSON value with byte array containing of N * 'x'
1527 const auto s = std::vector<std::uint8_t>(N, 'x');
1528 json j = json::binary(s);
1529
1530 // create expected byte vector
1531 std::vector<uint8_t> expected;
1532 expected.push_back(static_cast<std::uint8_t>('['));
1533 expected.push_back(static_cast<std::uint8_t>('$'));
1534 expected.push_back(static_cast<std::uint8_t>('U'));
1535 expected.push_back(static_cast<std::uint8_t>('#'));
1536 expected.push_back(static_cast<std::uint8_t>('U'));
1537 expected.push_back(static_cast<std::uint8_t>(N));
1538 for (size_t i = 0; i < N; ++i)
1539 {
1540 expected.push_back(0x78);
1541 }
1542
1543 // compare result + size
1544 const auto result = json::to_bjdata(j, true, true);
1545 CHECK(result == expected);
1546 CHECK(result.size() == N + 6);
1547 // check that no null byte is appended
1548 CHECK(result.back() != '\x00');
1549
1550 // roundtrip only works to an array of numbers
1551 json j_out = s;
1552 CHECK(json::from_bjdata(result) == j_out);
1553 CHECK(json::from_bjdata(result, true, false) == j_out);
1554 }
1555 }
1556
1557 SECTION("N = 256..32767")
1558 {
1559 for (std::size_t N :
1560 {
1561 256u, 999u, 1025u, 3333u, 2048u, 32767u
1562 })
1563 {
1564 CAPTURE(N)
1565
1566 // create JSON value with byte array containing of N * 'x'
1567 const auto s = std::vector<std::uint8_t>(N, 'x');
1568 json j = json::binary(s);
1569
1570 // create expected byte vector
1571 std::vector<std::uint8_t> expected(N + 7, 'x');
1572 expected[0] = '[';
1573 expected[1] = '$';
1574 expected[2] = 'U';
1575 expected[3] = '#';
1576 expected[4] = 'I';
1577 expected[5] = static_cast<std::uint8_t>(N & 0xFF);
1578 expected[6] = static_cast<std::uint8_t>((N >> 8) & 0xFF);
1579
1580 // compare result + size
1581 const auto result = json::to_bjdata(j, true, true);
1582 CHECK(result == expected);
1583 CHECK(result.size() == N + 7);
1584 // check that no null byte is appended
1585 CHECK(result.back() != '\x00');
1586
1587 // roundtrip only works to an array of numbers
1588 json j_out = s;
1589 CHECK(json::from_bjdata(result) == j_out);
1590 CHECK(json::from_bjdata(result, true, false) == j_out);
1591 }
1592 }
1593
1594 SECTION("N = 32768..65535")
1595 {
1596 for (std::size_t N :
1597 {
1598 32768u, 55555u, 65535u
1599 })
1600 {
1601 CAPTURE(N)
1602
1603 // create JSON value with byte array containing of N * 'x'
1604 const auto s = std::vector<std::uint8_t>(N, 'x');
1605 json j = json::binary(s);
1606
1607 // create expected byte vector
1608 std::vector<std::uint8_t> expected(N + 7, 'x');
1609 expected[0] = '[';
1610 expected[1] = '$';
1611 expected[2] = 'U';
1612 expected[3] = '#';
1613 expected[4] = 'u';
1614 expected[5] = static_cast<std::uint8_t>(N & 0xFF);
1615 expected[6] = static_cast<std::uint8_t>((N >> 8) & 0xFF);
1616
1617 // compare result + size
1618 const auto result = json::to_bjdata(j, true, true);
1619 CHECK(result == expected);
1620 CHECK(result.size() == N + 7);
1621 // check that no null byte is appended
1622 CHECK(result.back() != '\x00');
1623
1624 // roundtrip only works to an array of numbers
1625 json j_out = s;
1626 CHECK(json::from_bjdata(result) == j_out);
1627 CHECK(json::from_bjdata(result, true, false) == j_out);
1628 }
1629 }
1630
1631 SECTION("N = 65536..2147483647")
1632 {
1633 for (std::size_t N :
1634 {
1635 65536u, 77777u, 1048576u
1636 })
1637 {
1638 CAPTURE(N)
1639
1640 // create JSON value with byte array containing of N * 'x'
1641 const auto s = std::vector<std::uint8_t>(N, 'x');
1642 json j = json::binary(s);
1643
1644 // create expected byte vector
1645 std::vector<std::uint8_t> expected(N + 9, 'x');
1646 expected[0] = '[';
1647 expected[1] = '$';
1648 expected[2] = 'U';
1649 expected[3] = '#';
1650 expected[4] = 'l';
1651 expected[5] = static_cast<std::uint8_t>(N & 0xFF);
1652 expected[6] = static_cast<std::uint8_t>((N >> 8) & 0xFF);
1653 expected[7] = static_cast<std::uint8_t>((N >> 16) & 0xFF);
1654 expected[8] = static_cast<std::uint8_t>((N >> 24) & 0xFF);
1655
1656 // compare result + size
1657 const auto result = json::to_bjdata(j, true, true);
1658 CHECK(result == expected);
1659 CHECK(result.size() == N + 9);
1660 // check that no null byte is appended
1661 CHECK(result.back() != '\x00');
1662
1663 // roundtrip only works to an array of numbers
1664 json j_out = s;
1665 CHECK(json::from_bjdata(result) == j_out);
1666 CHECK(json::from_bjdata(result, true, false) == j_out);
1667 }
1668 }
1669
1670 SECTION("Other Serializations")
1671 {
1672 const std::size_t N = 10;
1673 const auto s = std::vector<std::uint8_t>(N, 'x');
1674 json j = json::binary(s);
1675
1676 SECTION("No Count No Type")
1677 {
1678 std::vector<uint8_t> expected;
1679 expected.push_back(static_cast<std::uint8_t>('['));
1680 for (std::size_t i = 0; i < N; ++i)
1681 {
1682 expected.push_back(static_cast<std::uint8_t>('U'));
1683 expected.push_back(static_cast<std::uint8_t>(0x78));
1684 }
1685 expected.push_back(static_cast<std::uint8_t>(']'));
1686
1687 // compare result + size
1688 const auto result = json::to_bjdata(j, false, false);
1689 CHECK(result == expected);
1690 CHECK(result.size() == N + 12);
1691 // check that no null byte is appended
1692 CHECK(result.back() != '\x00');
1693
1694 // roundtrip only works to an array of numbers
1695 json j_out = s;
1696 CHECK(json::from_bjdata(result) == j_out);
1697 CHECK(json::from_bjdata(result, true, false) == j_out);
1698 }
1699
1700 SECTION("Yes Count No Type")
1701 {
1702 std::vector<std::uint8_t> expected;
1703 expected.push_back(static_cast<std::uint8_t>('['));
1704 expected.push_back(static_cast<std::uint8_t>('#'));
1705 expected.push_back(static_cast<std::uint8_t>('i'));
1706 expected.push_back(static_cast<std::uint8_t>(N));
1707
1708 for (size_t i = 0; i < N; ++i)
1709 {
1710 expected.push_back(static_cast<std::uint8_t>('U'));
1711 expected.push_back(static_cast<std::uint8_t>(0x78));
1712 }
1713
1714 // compare result + size
1715 const auto result = json::to_bjdata(j, true, false);
1716 CHECK(result == expected);
1717 CHECK(result.size() == N + 14);
1718 // check that no null byte is appended
1719 CHECK(result.back() != '\x00');
1720
1721 // roundtrip only works to an array of numbers
1722 json j_out = s;
1723 CHECK(json::from_bjdata(result) == j_out);
1724 CHECK(json::from_bjdata(result, true, false) == j_out);
1725 }
1726 }
1727 }
1728 SECTION("array")
1729 {
1730 SECTION("empty")
1731 {
1732 SECTION("size=false type=false")
1733 {
1734 json j = json::array();
1735 std::vector<uint8_t> expected = {'[', ']'};
1736 const auto result = json::to_bjdata(j);
1737 CHECK(result == expected);
1738
1739 // roundtrip
1740 CHECK(json::from_bjdata(result) == j);
1741 CHECK(json::from_bjdata(result, true, false) == j);
1742 }
1743
1744 SECTION("size=true type=false")
1745 {
1746 json j = json::array();
1747 std::vector<uint8_t> expected = {'[', '#', 'i', 0};
1748 const auto result = json::to_bjdata(j, true);
1749 CHECK(result == expected);
1750
1751 // roundtrip
1752 CHECK(json::from_bjdata(result) == j);
1753 CHECK(json::from_bjdata(result, true, false) == j);
1754 }
1755
1756 SECTION("size=true type=true")
1757 {
1758 json j = json::array();
1759 std::vector<uint8_t> expected = {'[', '#', 'i', 0};
1760 const auto result = json::to_bjdata(j, true, true);
1761 CHECK(result == expected);
1762
1763 // roundtrip
1764 CHECK(json::from_bjdata(result) == j);
1765 CHECK(json::from_bjdata(result, true, false) == j);
1766 }
1767 }
1768
1769 SECTION("[null]")
1770 {
1771 SECTION("size=false type=false")
1772 {
1773 json j = {nullptr};
1774 std::vector<uint8_t> expected = {'[', 'Z', ']'};
1775 const auto result = json::to_bjdata(j);
1776 CHECK(result == expected);
1777
1778 // roundtrip
1779 CHECK(json::from_bjdata(result) == j);
1780 CHECK(json::from_bjdata(result, true, false) == j);
1781 }
1782
1783 SECTION("size=true type=false")
1784 {
1785 json j = {nullptr};
1786 std::vector<uint8_t> expected = {'[', '#', 'i', 1, 'Z'};
1787 const auto result = json::to_bjdata(j, true);
1788 CHECK(result == expected);
1789
1790 // roundtrip
1791 CHECK(json::from_bjdata(result) == j);
1792 CHECK(json::from_bjdata(result, true, false) == j);
1793 }
1794
1795 SECTION("size=true type=true")
1796 {
1797 json j = {nullptr};
1798 std::vector<uint8_t> expected = {'[', '#', 'i', 1, 'Z'};
1799 const auto result = json::to_bjdata(j, true, true);
1800 CHECK(result == expected);
1801
1802 // roundtrip
1803 CHECK(json::from_bjdata(result) == j);
1804 CHECK(json::from_bjdata(result, true, false) == j);
1805 }
1806 }
1807
1808 SECTION("[1,2,3,4,5]")
1809 {
1810 SECTION("size=false type=false")
1811 {
1812 json j = json::parse("[1,2,3,4,5]");
1813 std::vector<uint8_t> expected = {'[', 'i', 1, 'i', 2, 'i', 3, 'i', 4, 'i', 5, ']'};
1814 const auto result = json::to_bjdata(j);
1815 CHECK(result == expected);
1816
1817 // roundtrip
1818 CHECK(json::from_bjdata(result) == j);
1819 CHECK(json::from_bjdata(result, true, false) == j);
1820 }
1821
1822 SECTION("size=true type=false")
1823 {
1824 json j = json::parse("[1,2,3,4,5]");
1825 std::vector<uint8_t> expected = {'[', '#', 'i', 5, 'i', 1, 'i', 2, 'i', 3, 'i', 4, 'i', 5};
1826 const auto result = json::to_bjdata(j, true);
1827 CHECK(result == expected);
1828
1829 // roundtrip
1830 CHECK(json::from_bjdata(result) == j);
1831 CHECK(json::from_bjdata(result, true, false) == j);
1832 }
1833
1834 SECTION("size=true type=true")
1835 {
1836 json j = json::parse("[1,2,3,4,5]");
1837 std::vector<uint8_t> expected = {'[', '$', 'i', '#', 'i', 5, 1, 2, 3, 4, 5};
1838 const auto result = json::to_bjdata(j, true, true);
1839 CHECK(result == expected);
1840
1841 // roundtrip
1842 CHECK(json::from_bjdata(result) == j);
1843 CHECK(json::from_bjdata(result, true, false) == j);
1844 }
1845 }
1846
1847 SECTION("[[[[]]]]")
1848 {
1849 SECTION("size=false type=false")
1850 {
1851 json j = json::parse("[[[[]]]]");
1852 std::vector<uint8_t> expected = {'[', '[', '[', '[', ']', ']', ']', ']'};
1853 const auto result = json::to_bjdata(j);
1854 CHECK(result == expected);
1855
1856 // roundtrip
1857 CHECK(json::from_bjdata(result) == j);
1858 CHECK(json::from_bjdata(result, true, false) == j);
1859 }
1860
1861 SECTION("size=true type=false")
1862 {
1863 json j = json::parse("[[[[]]]]");
1864 std::vector<uint8_t> expected = {'[', '#', 'i', 1, '[', '#', 'i', 1, '[', '#', 'i', 1, '[', '#', 'i', 0};
1865 const auto result = json::to_bjdata(j, true);
1866 CHECK(result == expected);
1867
1868 // roundtrip
1869 CHECK(json::from_bjdata(result) == j);
1870 CHECK(json::from_bjdata(result, true, false) == j);
1871 }
1872
1873 SECTION("size=true type=true")
1874 {
1875 json j = json::parse("[[[[]]]]");
1876 std::vector<uint8_t> expected = {'[', '#', 'i', 1, '[', '#', 'i', 1, '[', '#', 'i', 1, '[', '#', 'i', 0};
1877 const auto result = json::to_bjdata(j, true, true);
1878 CHECK(result == expected);
1879
1880 // roundtrip
1881 CHECK(json::from_bjdata(result) == j);
1882 CHECK(json::from_bjdata(result, true, false) == j);
1883 }
1884 }
1885
1886 SECTION("array with int16_t elements")
1887 {
1888 SECTION("size=false type=false")
1889 {
1890 json j(257, nullptr);
1891 std::vector<uint8_t> expected(j.size() + 2, 'Z'); // all null
1892 expected[0] = '['; // opening array
1893 expected[258] = ']'; // closing array
1894 const auto result = json::to_bjdata(j);
1895 CHECK(result == expected);
1896
1897 // roundtrip
1898 CHECK(json::from_bjdata(result) == j);
1899 CHECK(json::from_bjdata(result, true, false) == j);
1900 }
1901
1902 SECTION("size=true type=false")
1903 {
1904 json j(257, nullptr);
1905 std::vector<uint8_t> expected(j.size() + 5, 'Z'); // all null
1906 expected[0] = '['; // opening array
1907 expected[1] = '#'; // array size
1908 expected[2] = 'I'; // int16
1909 expected[3] = 0x01; // 0x0101, first byte
1910 expected[4] = 0x01; // 0x0101, second byte
1911 const auto result = json::to_bjdata(j, true);
1912 CHECK(result == expected);
1913
1914 // roundtrip
1915 CHECK(json::from_bjdata(result) == j);
1916 CHECK(json::from_bjdata(result, true, false) == j);
1917 }
1918 }
1919
1920 SECTION("array with uint16_t elements")
1921 {
1922 SECTION("size=false type=false")
1923 {
1924 json j(32768, nullptr);
1925 std::vector<uint8_t> expected(j.size() + 2, 'Z'); // all null
1926 expected[0] = '['; // opening array
1927 expected[32769] = ']'; // closing array
1928 const auto result = json::to_bjdata(j);
1929 CHECK(result == expected);
1930
1931 // roundtrip
1932 CHECK(json::from_bjdata(result) == j);
1933 CHECK(json::from_bjdata(result, true, false) == j);
1934 }
1935
1936 SECTION("size=true type=false")
1937 {
1938 json j(32768, nullptr);
1939 std::vector<uint8_t> expected(j.size() + 5, 'Z'); // all null
1940 expected[0] = '['; // opening array
1941 expected[1] = '#'; // array size
1942 expected[2] = 'u'; // int16
1943 expected[3] = 0x00; // 0x0101, first byte
1944 expected[4] = 0x80; // 0x0101, second byte
1945 const auto result = json::to_bjdata(j, true);
1946 CHECK(result == expected);
1947
1948 // roundtrip
1949 CHECK(json::from_bjdata(result) == j);
1950 CHECK(json::from_bjdata(result, true, false) == j);
1951 }
1952 }
1953
1954 SECTION("array with int32_t elements")
1955 {
1956 SECTION("size=false type=false")
1957 {
1958 json j(65793, nullptr);
1959 std::vector<uint8_t> expected(j.size() + 2, 'Z'); // all null
1960 expected[0] = '['; // opening array
1961 expected[65794] = ']'; // closing array
1962 const auto result = json::to_bjdata(j);
1963 CHECK(result == expected);
1964
1965 // roundtrip
1966 CHECK(json::from_bjdata(result) == j);
1967 CHECK(json::from_bjdata(result, true, false) == j);
1968 }
1969
1970 SECTION("size=true type=false")
1971 {
1972 json j(65793, nullptr);
1973 std::vector<uint8_t> expected(j.size() + 7, 'Z'); // all null
1974 expected[0] = '['; // opening array
1975 expected[1] = '#'; // array size
1976 expected[2] = 'l'; // int32
1977 expected[3] = 0x01; // 0x00010101, fourth byte
1978 expected[4] = 0x01; // 0x00010101, third byte
1979 expected[5] = 0x01; // 0x00010101, second byte
1980 expected[6] = 0x00; // 0x00010101, first byte
1981 const auto result = json::to_bjdata(j, true);
1982 CHECK(result == expected);
1983
1984 // roundtrip
1985 CHECK(json::from_bjdata(result) == j);
1986 CHECK(json::from_bjdata(result, true, false) == j);
1987 }
1988 }
1989 }
1990
1991 SECTION("object")
1992 {
1993 SECTION("empty")
1994 {
1995 SECTION("size=false type=false")
1996 {
1997 json j = json::object();
1998 std::vector<uint8_t> expected = {'{', '}'};
1999 const auto result = json::to_bjdata(j);
2000 CHECK(result == expected);
2001
2002 // roundtrip
2003 CHECK(json::from_bjdata(result) == j);
2004 CHECK(json::from_bjdata(result, true, false) == j);
2005 }
2006
2007 SECTION("size=true type=false")
2008 {
2009 json j = json::object();
2010 std::vector<uint8_t> expected = {'{', '#', 'i', 0};
2011 const auto result = json::to_bjdata(j, true);
2012 CHECK(result == expected);
2013
2014 // roundtrip
2015 CHECK(json::from_bjdata(result) == j);
2016 CHECK(json::from_bjdata(result, true, false) == j);
2017 }
2018
2019 SECTION("size=true type=true")
2020 {
2021 json j = json::object();
2022 std::vector<uint8_t> expected = {'{', '#', 'i', 0};
2023 const auto result = json::to_bjdata(j, true, true);
2024 CHECK(result == expected);
2025
2026 // roundtrip
2027 CHECK(json::from_bjdata(result) == j);
2028 CHECK(json::from_bjdata(result, true, false) == j);
2029 }
2030 }
2031
2032 SECTION("{\"\":null}")
2033 {
2034 SECTION("size=false type=false")
2035 {
2036 json j = {{"", nullptr}};
2037 std::vector<uint8_t> expected = {'{', 'i', 0, 'Z', '}'};
2038 const auto result = json::to_bjdata(j);
2039 CHECK(result == expected);
2040
2041 // roundtrip
2042 CHECK(json::from_bjdata(result) == j);
2043 CHECK(json::from_bjdata(result, true, false) == j);
2044 }
2045
2046 SECTION("size=true type=false")
2047 {
2048 json j = {{"", nullptr}};
2049 std::vector<uint8_t> expected = {'{', '#', 'i', 1, 'i', 0, 'Z'};
2050 const auto result = json::to_bjdata(j, true);
2051 CHECK(result == expected);
2052
2053 // roundtrip
2054 CHECK(json::from_bjdata(result) == j);
2055 CHECK(json::from_bjdata(result, true, false) == j);
2056 }
2057 }
2058
2059 SECTION("{\"a\": {\"b\": {\"c\": {}}}}")
2060 {
2061 SECTION("size=false type=false")
2062 {
2063 json j = json::parse(R"({"a": {"b": {"c": {}}}})");
2064 std::vector<uint8_t> expected =
2065 {
2066 '{', 'i', 1, 'a', '{', 'i', 1, 'b', '{', 'i', 1, 'c', '{', '}', '}', '}', '}'
2067 };
2068 const auto result = json::to_bjdata(j);
2069 CHECK(result == expected);
2070
2071 // roundtrip
2072 CHECK(json::from_bjdata(result) == j);
2073 CHECK(json::from_bjdata(result, true, false) == j);
2074 }
2075
2076 SECTION("size=true type=false")
2077 {
2078 json j = json::parse(R"({"a": {"b": {"c": {}}}})");
2079 std::vector<uint8_t> expected =
2080 {
2081 '{', '#', 'i', 1, 'i', 1, 'a', '{', '#', 'i', 1, 'i', 1, 'b', '{', '#', 'i', 1, 'i', 1, 'c', '{', '#', 'i', 0
2082 };
2083 const auto result = json::to_bjdata(j, true);
2084 CHECK(result == expected);
2085
2086 // roundtrip
2087 CHECK(json::from_bjdata(result) == j);
2088 CHECK(json::from_bjdata(result, true, false) == j);
2089 }
2090
2091 SECTION("size=true type=true ignore object type marker")
2092 {
2093 json j = json::parse(R"({"a": {"b": {"c": {}}}})");
2094 std::vector<uint8_t> expected =
2095 {
2096 '{', '#', 'i', 1, 'i', 1, 'a', '{', '#', 'i', 1, 'i', 1, 'b', '{', '#', 'i', 1, 'i', 1, 'c', '{', '#', 'i', 0
2097 };
2098 const auto result = json::to_bjdata(j, true, true);
2099 CHECK(result == expected);
2100
2101 // roundtrip
2102 CHECK(json::from_bjdata(result) == j);
2103 CHECK(json::from_bjdata(result, true, false) == j);
2104 }
2105 }
2106 }
2107 }
2108
2109 SECTION("errors")
2110 {
2111 SECTION("strict mode")
2112 {
2113 std::vector<uint8_t> vec = {'Z', 'Z'};
2114 SECTION("non-strict mode")
2115 {
2116 const auto result = json::from_bjdata(vec, false);
2117 CHECK(result == json());
2118 }
2119
2120 SECTION("strict mode")
2121 {
2122 json _;
2123 CHECK_THROWS_WITH_AS(_ = json::from_bjdata(vec),
2124 "[json.exception.parse_error.110] parse error at byte 2: syntax error while parsing BJData value: expected end of input; last byte: 0x5A", json::parse_error&);
2125 }
2126 }
2127 }
2128
2129 SECTION("SAX aborts")
2130 {
2131 SECTION("start_array()")
2132 {
2133 std::vector<uint8_t> v = {'[', 'T', 'F', ']'};
2134 SaxCountdown scp(0);
2135 CHECK_FALSE(json::sax_parse(v, &scp, json::input_format_t::bjdata));
2136 }
2137
2138 SECTION("start_object()")
2139 {
2140 std::vector<uint8_t> v = {'{', 'i', 3, 'f', 'o', 'o', 'F', '}'};
2141 SaxCountdown scp(0);
2142 CHECK_FALSE(json::sax_parse(v, &scp, json::input_format_t::bjdata));
2143 }
2144
2145 SECTION("key() in object")
2146 {
2147 std::vector<uint8_t> v = {'{', 'i', 3, 'f', 'o', 'o', 'F', '}'};
2148 SaxCountdown scp(1);
2149 CHECK_FALSE(json::sax_parse(v, &scp, json::input_format_t::bjdata));
2150 }
2151
2152 SECTION("start_array(len)")
2153 {
2154 std::vector<uint8_t> v = {'[', '#', 'i', '2', 'T', 'F'};
2155 SaxCountdown scp(0);
2156 CHECK_FALSE(json::sax_parse(v, &scp, json::input_format_t::bjdata));
2157 }
2158
2159 SECTION("start_object(len)")
2160 {
2161 std::vector<uint8_t> v = {'{', '#', 'i', '1', 3, 'f', 'o', 'o', 'F'};
2162 SaxCountdown scp(0);
2163 CHECK_FALSE(json::sax_parse(v, &scp, json::input_format_t::bjdata));
2164 }
2165
2166 SECTION("key() in object with length")
2167 {
2168 std::vector<uint8_t> v = {'{', 'i', 3, 'f', 'o', 'o', 'F', '}'};
2169 SaxCountdown scp(1);
2170 CHECK_FALSE(json::sax_parse(v, &scp, json::input_format_t::bjdata));
2171 }
2172
2173 SECTION("start_array() in ndarray _ArraySize_")
2174 {
2175 std::vector<uint8_t> v = {'[', '$', 'i', '#', '[', '$', 'i', '#', 'i', 2, 2, 1, 1, 2};
2176 SaxCountdown scp(2);
2177 CHECK_FALSE(json::sax_parse(v, &scp, json::input_format_t::bjdata));
2178 }
2179
2180 SECTION("number_integer() in ndarray _ArraySize_")
2181 {
2182 std::vector<uint8_t> v = {'[', '$', 'U', '#', '[', '$', 'i', '#', 'i', 2, 2, 1, 1, 2};
2183 SaxCountdown scp(3);
2184 CHECK_FALSE(json::sax_parse(v, &scp, json::input_format_t::bjdata));
2185 }
2186
2187 SECTION("key() in ndarray _ArrayType_")
2188 {
2189 std::vector<uint8_t> v = {'[', '$', 'U', '#', '[', '$', 'U', '#', 'i', 2, 2, 2, 1, 2, 3, 4};
2190 SaxCountdown scp(6);
2191 CHECK_FALSE(json::sax_parse(v, &scp, json::input_format_t::bjdata));
2192 }
2193
2194 SECTION("string() in ndarray _ArrayType_")
2195 {
2196 std::vector<uint8_t> v = {'[', '$', 'U', '#', '[', '$', 'U', '#', 'i', 2, 2, 2, 1, 2, 3, 4};
2197 SaxCountdown scp(7);
2198 CHECK_FALSE(json::sax_parse(v, &scp, json::input_format_t::bjdata));
2199 }
2200
2201 SECTION("key() in ndarray _ArrayData_")
2202 {
2203 std::vector<uint8_t> v = {'[', '$', 'U', '#', '[', '$', 'U', '#', 'i', 2, 2, 2, 1, 2, 3, 4};
2204 SaxCountdown scp(8);
2205 CHECK_FALSE(json::sax_parse(v, &scp, json::input_format_t::bjdata));
2206 }
2207
2208 SECTION("string() in ndarray _ArrayData_")
2209 {
2210 std::vector<uint8_t> v = {'[', '$', 'U', '#', '[', '$', 'U', '#', 'i', 2, 2, 2, 1, 2, 3, 4};
2211 SaxCountdown scp(9);
2212 CHECK_FALSE(json::sax_parse(v, &scp, json::input_format_t::bjdata));
2213 }
2214
2215 SECTION("string() in ndarray _ArrayType_")
2216 {
2217 std::vector<uint8_t> v = {'[', '$', 'U', '#', '[', '$', 'i', '#', 'i', 2, 3, 2, 6, 5, 4, 3, 2, 1};
2218 SaxCountdown scp(11);
2219 CHECK_FALSE(json::sax_parse(v, &scp, json::input_format_t::bjdata));
2220 }
2221
2222 SECTION("start_array() in ndarray _ArrayData_")
2223 {
2224 std::vector<uint8_t> v = {'[', '$', 'U', '#', '[', 'i', 2, 'i', 3, ']', 6, 5, 4, 3, 2, 1};
2225 SaxCountdown scp(13);
2226 CHECK_FALSE(json::sax_parse(v, &scp, json::input_format_t::bjdata));
2227 }
2228 }
2229
2230 SECTION("parsing values")
2231 {
2232 SECTION("strings")
2233 {
2234 // create a single-character string for all number types
2235 std::vector<uint8_t> s_i = {'S', 'i', 1, 'a'};
2236 std::vector<uint8_t> s_U = {'S', 'U', 1, 'a'};
2237 std::vector<uint8_t> s_I = {'S', 'I', 1, 0, 'a'};
2238 std::vector<uint8_t> s_u = {'S', 'u', 1, 0, 'a'};
2239 std::vector<uint8_t> s_l = {'S', 'l', 1, 0, 0, 0, 'a'};
2240 std::vector<uint8_t> s_m = {'S', 'm', 1, 0, 0, 0, 'a'};
2241 std::vector<uint8_t> s_L = {'S', 'L', 1, 0, 0, 0, 0, 0, 0, 0, 'a'};
2242 std::vector<uint8_t> s_M = {'S', 'M', 1, 0, 0, 0, 0, 0, 0, 0, 'a'};
2243
2244 // check if string is parsed correctly to "a"
2245 CHECK(json::from_bjdata(s_i) == "a");
2246 CHECK(json::from_bjdata(s_U) == "a");
2247 CHECK(json::from_bjdata(s_I) == "a");
2248 CHECK(json::from_bjdata(s_u) == "a");
2249 CHECK(json::from_bjdata(s_l) == "a");
2250 CHECK(json::from_bjdata(s_m) == "a");
2251 CHECK(json::from_bjdata(s_L) == "a");
2252 CHECK(json::from_bjdata(s_M) == "a");
2253
2254 // roundtrip: output should be optimized
2255 CHECK(json::to_bjdata(json::from_bjdata(s_i)) == s_i);
2256 CHECK(json::to_bjdata(json::from_bjdata(s_U)) == s_i);
2257 CHECK(json::to_bjdata(json::from_bjdata(s_I)) == s_i);
2258 CHECK(json::to_bjdata(json::from_bjdata(s_u)) == s_i);
2259 CHECK(json::to_bjdata(json::from_bjdata(s_l)) == s_i);
2260 CHECK(json::to_bjdata(json::from_bjdata(s_m)) == s_i);
2261 CHECK(json::to_bjdata(json::from_bjdata(s_L)) == s_i);
2262 CHECK(json::to_bjdata(json::from_bjdata(s_M)) == s_i);
2263 }
2264
2265 SECTION("number")
2266 {
2267 SECTION("float")
2268 {
2269 // float32
2270 std::vector<uint8_t> v_d = {'d', 0xd0, 0x0f, 0x49, 0x40};
2271 CHECK(json::from_bjdata(v_d) == 3.14159f);
2272
2273 // float64
2274 std::vector<uint8_t> v_D = {'D', 0x6e, 0x86, 0x1b, 0xf0, 0xf9, 0x21, 0x09, 0x40};
2275 CHECK(json::from_bjdata(v_D) == 3.14159);
2276
2277 // float32 is serialized as float64 as the library does not support float32
2278 CHECK(json::to_bjdata(json::from_bjdata(v_d)) == json::to_bjdata(3.14159f));
2279 }
2280 }
2281
2282 SECTION("array")
2283 {
2284 SECTION("optimized version (length only)")
2285 {
2286 // create vector with two elements of the same type
2287 std::vector<uint8_t> v_TU = {'[', '#', 'U', 2, 'T', 'T'};
2288 std::vector<uint8_t> v_T = {'[', '#', 'i', 2, 'T', 'T'};
2289 std::vector<uint8_t> v_F = {'[', '#', 'i', 2, 'F', 'F'};
2290 std::vector<uint8_t> v_Z = {'[', '#', 'i', 2, 'Z', 'Z'};
2291 std::vector<uint8_t> v_i = {'[', '#', 'i', 2, 'i', 0x7F, 'i', 0x7F};
2292 std::vector<uint8_t> v_U = {'[', '#', 'i', 2, 'U', 0xFF, 'U', 0xFF};
2293 std::vector<uint8_t> v_I = {'[', '#', 'i', 2, 'I', 0xFF, 0x7F, 'I', 0xFF, 0x7F};
2294 std::vector<uint8_t> v_u = {'[', '#', 'i', 2, 'u', 0x0F, 0xA7, 'u', 0x0F, 0xA7};
2295 std::vector<uint8_t> v_l = {'[', '#', 'i', 2, 'l', 0xFF, 0xFF, 0xFF, 0x7F, 'l', 0xFF, 0xFF, 0xFF, 0x7F};
2296 std::vector<uint8_t> v_m = {'[', '#', 'i', 2, 'm', 0xFF, 0xC9, 0x9A, 0xBB, 'm', 0xFF, 0xC9, 0x9A, 0xBB};
2297 std::vector<uint8_t> v_L = {'[', '#', 'i', 2, 'L', 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 'L', 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F};
2298 std::vector<uint8_t> v_M = {'[', '#', 'i', 2, 'M', 0xFF, 0xFF, 0x63, 0xA7, 0xB3, 0xB6, 0xE0, 0x8D, 'M', 0xFF, 0xFF, 0x63, 0xA7, 0xB3, 0xB6, 0xE0, 0x8D};
2299 std::vector<uint8_t> v_D = {'[', '#', 'i', 2, 'D', 0x4a, 0xd8, 0x12, 0x4d, 0xfb, 0x21, 0x09, 0x40, 'D', 0x4a, 0xd8, 0x12, 0x4d, 0xfb, 0x21, 0x09, 0x40};
2300 std::vector<uint8_t> v_S = {'[', '#', 'i', 2, 'S', 'i', 1, 'a', 'S', 'i', 1, 'a'};
2301 std::vector<uint8_t> v_C = {'[', '#', 'i', 2, 'C', 'a', 'C', 'a'};
2302
2303 // check if vector is parsed correctly
2304 CHECK(json::from_bjdata(v_TU) == json({true, true}));
2305 CHECK(json::from_bjdata(v_T) == json({true, true}));
2306 CHECK(json::from_bjdata(v_F) == json({false, false}));
2307 CHECK(json::from_bjdata(v_Z) == json({nullptr, nullptr}));
2308 CHECK(json::from_bjdata(v_i) == json({127, 127}));
2309 CHECK(json::from_bjdata(v_U) == json({255, 255}));
2310 CHECK(json::from_bjdata(v_I) == json({32767, 32767}));
2311 CHECK(json::from_bjdata(v_u) == json({42767, 42767}));
2312 CHECK(json::from_bjdata(v_l) == json({2147483647, 2147483647}));
2313 CHECK(json::from_bjdata(v_m) == json({3147483647, 3147483647}));
2314 CHECK(json::from_bjdata(v_L) == json({9223372036854775807, 9223372036854775807}));
2315 CHECK(json::from_bjdata(v_M) == json({10223372036854775807ull, 10223372036854775807ull}));
2316 CHECK(json::from_bjdata(v_D) == json({3.1415926, 3.1415926}));
2317 CHECK(json::from_bjdata(v_S) == json({"a", "a"}));
2318 CHECK(json::from_bjdata(v_C) == json({"a", "a"}));
2319
2320 // roundtrip: output should be optimized
2321 CHECK(json::to_bjdata(json::from_bjdata(v_T), true) == v_T);
2322 CHECK(json::to_bjdata(json::from_bjdata(v_F), true) == v_F);
2323 CHECK(json::to_bjdata(json::from_bjdata(v_Z), true) == v_Z);
2324 CHECK(json::to_bjdata(json::from_bjdata(v_i), true) == v_i);
2325 CHECK(json::to_bjdata(json::from_bjdata(v_U), true) == v_U);
2326 CHECK(json::to_bjdata(json::from_bjdata(v_I), true) == v_I);
2327 CHECK(json::to_bjdata(json::from_bjdata(v_u), true) == v_u);
2328 CHECK(json::to_bjdata(json::from_bjdata(v_l), true) == v_l);
2329 CHECK(json::to_bjdata(json::from_bjdata(v_m), true) == v_m);
2330 CHECK(json::to_bjdata(json::from_bjdata(v_L), true) == v_L);
2331 CHECK(json::to_bjdata(json::from_bjdata(v_M), true) == v_M);
2332 CHECK(json::to_bjdata(json::from_bjdata(v_D), true) == v_D);
2333 CHECK(json::to_bjdata(json::from_bjdata(v_S), true) == v_S);
2334 CHECK(json::to_bjdata(json::from_bjdata(v_C), true) == v_S); // char is serialized to string
2335 }
2336
2337 SECTION("optimized version (type and length)")
2338 {
2339 // create vector with two elements of the same type
2340 std::vector<uint8_t> v_i = {'[', '$', 'i', '#', 'i', 2, 0x7F, 0x7F};
2341 std::vector<uint8_t> v_U = {'[', '$', 'U', '#', 'i', 2, 0xFF, 0xFF};
2342 std::vector<uint8_t> v_I = {'[', '$', 'I', '#', 'i', 2, 0xFF, 0x7F, 0xFF, 0x7F};
2343 std::vector<uint8_t> v_u = {'[', '$', 'u', '#', 'i', 2, 0x0F, 0xA7, 0x0F, 0xA7};
2344 std::vector<uint8_t> v_l = {'[', '$', 'l', '#', 'i', 2, 0xFF, 0xFF, 0xFF, 0x7F, 0xFF, 0xFF, 0xFF, 0x7F};
2345 std::vector<uint8_t> v_m = {'[', '$', 'm', '#', 'i', 2, 0xFF, 0xC9, 0x9A, 0xBB, 0xFF, 0xC9, 0x9A, 0xBB};
2346 std::vector<uint8_t> v_L = {'[', '$', 'L', '#', 'i', 2, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F};
2347 std::vector<uint8_t> v_M = {'[', '$', 'M', '#', 'i', 2, 0xFF, 0xFF, 0x63, 0xA7, 0xB3, 0xB6, 0xE0, 0x8D, 0xFF, 0xFF, 0x63, 0xA7, 0xB3, 0xB6, 0xE0, 0x8D};
2348 std::vector<uint8_t> v_D = {'[', '$', 'D', '#', 'i', 2, 0x4a, 0xd8, 0x12, 0x4d, 0xfb, 0x21, 0x09, 0x40, 0x4a, 0xd8, 0x12, 0x4d, 0xfb, 0x21, 0x09, 0x40};
2349 std::vector<uint8_t> v_S = {'[', '#', 'i', 2, 'S', 'i', 1, 'a', 'S', 'i', 1, 'a'};
2350 std::vector<uint8_t> v_C = {'[', '$', 'C', '#', 'i', 2, 'a', 'a'};
2351
2352 // check if vector is parsed correctly
2353 CHECK(json::from_bjdata(v_i) == json({127, 127}));
2354 CHECK(json::from_bjdata(v_U) == json({255, 255}));
2355 CHECK(json::from_bjdata(v_I) == json({32767, 32767}));
2356 CHECK(json::from_bjdata(v_u) == json({42767, 42767}));
2357 CHECK(json::from_bjdata(v_l) == json({2147483647, 2147483647}));
2358 CHECK(json::from_bjdata(v_m) == json({3147483647, 3147483647}));
2359 CHECK(json::from_bjdata(v_L) == json({9223372036854775807, 9223372036854775807}));
2360 CHECK(json::from_bjdata(v_M) == json({10223372036854775807ull, 10223372036854775807ull}));
2361 CHECK(json::from_bjdata(v_D) == json({3.1415926, 3.1415926}));
2362 CHECK(json::from_bjdata(v_S) == json({"a", "a"}));
2363 CHECK(json::from_bjdata(v_C) == json({"a", "a"}));
2364
2365 // roundtrip: output should be optimized
2366 std::vector<uint8_t> v_empty = {'[', '#', 'i', 0};
2367 CHECK(json::to_bjdata(json::from_bjdata(v_i), true, true) == v_i);
2368 CHECK(json::to_bjdata(json::from_bjdata(v_U), true, true) == v_U);
2369 CHECK(json::to_bjdata(json::from_bjdata(v_I), true, true) == v_I);
2370 CHECK(json::to_bjdata(json::from_bjdata(v_u), true, true) == v_u);
2371 CHECK(json::to_bjdata(json::from_bjdata(v_l), true, true) == v_l);
2372 CHECK(json::to_bjdata(json::from_bjdata(v_m), true, true) == v_m);
2373 CHECK(json::to_bjdata(json::from_bjdata(v_L), true, true) == v_L);
2374 CHECK(json::to_bjdata(json::from_bjdata(v_M), true, true) == v_M);
2375 CHECK(json::to_bjdata(json::from_bjdata(v_D), true, true) == v_D);
2376 CHECK(json::to_bjdata(json::from_bjdata(v_S), true, true) == v_S);
2377 CHECK(json::to_bjdata(json::from_bjdata(v_C), true, true) == v_S); // char is serialized to string
2378 }
2379
2380 SECTION("optimized ndarray (type and vector-size as optimized 1D array)")
2381 {
2382 // create vector with two elements of the same type
2383 std::vector<uint8_t> v_0 = {'[', '$', 'i', '#', '[', '$', 'i', '#', 'i', 1, 0};
2384 std::vector<uint8_t> v_1 = {'[', '$', 'i', '#', '[', '$', 'i', '#', 'i', 1, 2, 0x7F, 0x7F};
2385 std::vector<uint8_t> v_i = {'[', '$', 'i', '#', '[', '$', 'i', '#', 'i', 2, 1, 2, 0x7F, 0x7F};
2386 std::vector<uint8_t> v_U = {'[', '$', 'U', '#', '[', '$', 'i', '#', 'i', 2, 1, 2, 0xFF, 0xFF};
2387 std::vector<uint8_t> v_I = {'[', '$', 'I', '#', '[', '$', 'i', '#', 'i', 2, 1, 2, 0xFF, 0x7F, 0xFF, 0x7F};
2388 std::vector<uint8_t> v_u = {'[', '$', 'u', '#', '[', '$', 'i', '#', 'i', 2, 1, 2, 0x0F, 0xA7, 0x0F, 0xA7};
2389 std::vector<uint8_t> v_l = {'[', '$', 'l', '#', '[', '$', 'i', '#', 'i', 2, 1, 2, 0xFF, 0xFF, 0xFF, 0x7F, 0xFF, 0xFF, 0xFF, 0x7F};
2390 std::vector<uint8_t> v_m = {'[', '$', 'm', '#', '[', '$', 'i', '#', 'i', 2, 1, 2, 0xFF, 0xC9, 0x9A, 0xBB, 0xFF, 0xC9, 0x9A, 0xBB};
2391 std::vector<uint8_t> v_L = {'[', '$', 'L', '#', '[', '$', 'i', '#', 'i', 2, 1, 2, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F};
2392 std::vector<uint8_t> v_M = {'[', '$', 'M', '#', '[', '$', 'i', '#', 'i', 2, 1, 2, 0xFF, 0xFF, 0x63, 0xA7, 0xB3, 0xB6, 0xE0, 0x8D, 0xFF, 0xFF, 0x63, 0xA7, 0xB3, 0xB6, 0xE0, 0x8D};
2393 std::vector<uint8_t> v_D = {'[', '$', 'D', '#', '[', '$', 'i', '#', 'i', 2, 1, 2, 0x4a, 0xd8, 0x12, 0x4d, 0xfb, 0x21, 0x09, 0x40, 0x4a, 0xd8, 0x12, 0x4d, 0xfb, 0x21, 0x09, 0x40};
2394 std::vector<uint8_t> v_S = {'[', '#', '[', '$', 'i', '#', 'i', 2, 1, 2, 'S', 'i', 1, 'a', 'S', 'i', 1, 'a'};
2395 std::vector<uint8_t> v_C = {'[', '$', 'C', '#', '[', '$', 'i', '#', 'i', 2, 1, 2, 'a', 'a'};
2396
2397 // check if vector is parsed correctly
2398 CHECK(json::from_bjdata(v_0) == json::array());
2399 CHECK(json::from_bjdata(v_1) == json({127, 127}));
2400 CHECK(json::from_bjdata(v_i) == json({127, 127}));
2401 CHECK(json::from_bjdata(v_U) == json({255, 255}));
2402 CHECK(json::from_bjdata(v_I) == json({32767, 32767}));
2403 CHECK(json::from_bjdata(v_u) == json({42767, 42767}));
2404 CHECK(json::from_bjdata(v_l) == json({2147483647, 2147483647}));
2405 CHECK(json::from_bjdata(v_m) == json({3147483647, 3147483647}));
2406 CHECK(json::from_bjdata(v_L) == json({9223372036854775807, 9223372036854775807}));
2407 CHECK(json::from_bjdata(v_M) == json({10223372036854775807ull, 10223372036854775807ull}));
2408 CHECK(json::from_bjdata(v_D) == json({3.1415926, 3.1415926}));
2409 CHECK(json::from_bjdata(v_S) == json({"a", "a"}));
2410 CHECK(json::from_bjdata(v_C) == json({"a", "a"}));
2411 }
2412
2413 SECTION("optimized ndarray (type and vector-size ndarray with JData annotations)")
2414 {
2415 // create vector with 0, 1, 2 elements of the same type
2416 std::vector<uint8_t> v_e = {'[', '$', 'U', '#', '[', '$', 'i', '#', 'i', 2, 2, 1, 0xFE, 0xFF};
2417 std::vector<uint8_t> v_U = {'[', '$', 'U', '#', '[', '$', 'i', '#', 'i', 2, 2, 3, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06};
2418 std::vector<uint8_t> v_i = {'[', '$', 'i', '#', '[', '$', 'i', '#', 'i', 2, 2, 3, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06};
2419 std::vector<uint8_t> v_u = {'[', '$', 'u', '#', '[', '$', 'i', '#', 'i', 2, 2, 3, 0x01, 0x00, 0x02, 0x00, 0x03, 0x00, 0x04, 0x00, 0x05, 0x00, 0x06, 0x00};
2420 std::vector<uint8_t> v_I = {'[', '$', 'I', '#', '[', '$', 'i', '#', 'i', 2, 2, 3, 0x01, 0x00, 0x02, 0x00, 0x03, 0x00, 0x04, 0x00, 0x05, 0x00, 0x06, 0x00};
2421 std::vector<uint8_t> v_m = {'[', '$', 'm', '#', '[', '$', 'i', '#', 'i', 2, 2, 3, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00};
2422 std::vector<uint8_t> v_l = {'[', '$', 'l', '#', '[', '$', 'i', '#', 'i', 2, 2, 3, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00};
2423 std::vector<uint8_t> v_M = {'[', '$', 'M', '#', '[', '$', 'i', '#', 'i', 2, 2, 3, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
2424 std::vector<uint8_t> v_L = {'[', '$', 'L', '#', '[', '$', 'i', '#', 'i', 2, 2, 3, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
2425 std::vector<uint8_t> v_d = {'[', '$', 'd', '#', '[', '$', 'i', '#', 'i', 2, 2, 3, 0x00, 0x00, 0x80, 0x3F, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x40, 0x40, 0x00, 0x00, 0x80, 0x40, 0x00, 0x00, 0xA0, 0x40, 0x00, 0x00, 0xC0, 0x40};
2426 std::vector<uint8_t> v_D = {'[', '$', 'D', '#', '[', '$', 'i', '#', 'i', 2, 2, 3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0x3F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x40};
2427 std::vector<uint8_t> v_C = {'[', '$', 'C', '#', '[', '$', 'i', '#', 'i', 2, 2, 3, 'a', 'b', 'c', 'd', 'e', 'f'};
2428
2429 // check if vector is parsed correctly
2430 CHECK(json::from_bjdata(v_e) == json({{"_ArrayData_", {254, 255}}, {"_ArraySize_", {2, 1}}, {"_ArrayType_", "uint8"}}));
2431 CHECK(json::from_bjdata(v_U) == json({{"_ArrayData_", {1, 2, 3, 4, 5, 6}}, {"_ArraySize_", {2, 3}}, {"_ArrayType_", "uint8"}}));
2432 CHECK(json::from_bjdata(v_i) == json({{"_ArrayData_", {1, 2, 3, 4, 5, 6}}, {"_ArraySize_", {2, 3}}, {"_ArrayType_", "int8"}}));
2433 CHECK(json::from_bjdata(v_i) == json({{"_ArrayData_", {1, 2, 3, 4, 5, 6}}, {"_ArraySize_", {2, 3}}, {"_ArrayType_", "int8"}}));
2434 CHECK(json::from_bjdata(v_u) == json({{"_ArrayData_", {1, 2, 3, 4, 5, 6}}, {"_ArraySize_", {2, 3}}, {"_ArrayType_", "uint16"}}));
2435 CHECK(json::from_bjdata(v_I) == json({{"_ArrayData_", {1, 2, 3, 4, 5, 6}}, {"_ArraySize_", {2, 3}}, {"_ArrayType_", "int16"}}));
2436 CHECK(json::from_bjdata(v_m) == json({{"_ArrayData_", {1, 2, 3, 4, 5, 6}}, {"_ArraySize_", {2, 3}}, {"_ArrayType_", "uint32"}}));
2437 CHECK(json::from_bjdata(v_l) == json({{"_ArrayData_", {1, 2, 3, 4, 5, 6}}, {"_ArraySize_", {2, 3}}, {"_ArrayType_", "int32"}}));
2438 CHECK(json::from_bjdata(v_M) == json({{"_ArrayData_", {1, 2, 3, 4, 5, 6}}, {"_ArraySize_", {2, 3}}, {"_ArrayType_", "uint64"}}));
2439 CHECK(json::from_bjdata(v_L) == json({{"_ArrayData_", {1, 2, 3, 4, 5, 6}}, {"_ArraySize_", {2, 3}}, {"_ArrayType_", "int64"}}));
2440 CHECK(json::from_bjdata(v_d) == json({{"_ArrayData_", {1.f, 2.f, 3.f, 4.f, 5.f, 6.f}}, {"_ArraySize_", {2, 3}}, {"_ArrayType_", "single"}}));
2441 CHECK(json::from_bjdata(v_D) == json({{"_ArrayData_", {1., 2., 3., 4., 5., 6.}}, {"_ArraySize_", {2, 3}}, {"_ArrayType_", "double"}}));
2442 CHECK(json::from_bjdata(v_C) == json({{"_ArrayData_", {'a', 'b', 'c', 'd', 'e', 'f'}}, {"_ArraySize_", {2, 3}}, {"_ArrayType_", "char"}}));
2443
2444 // roundtrip: output should be optimized
2445 CHECK(json::to_bjdata(json::from_bjdata(v_e), true, true) == v_e);
2446 CHECK(json::to_bjdata(json::from_bjdata(v_U), true, true) == v_U);
2447 CHECK(json::to_bjdata(json::from_bjdata(v_i), true, true) == v_i);
2448 CHECK(json::to_bjdata(json::from_bjdata(v_u), true, true) == v_u);
2449 CHECK(json::to_bjdata(json::from_bjdata(v_I), true, true) == v_I);
2450 CHECK(json::to_bjdata(json::from_bjdata(v_m), true, true) == v_m);
2451 CHECK(json::to_bjdata(json::from_bjdata(v_l), true, true) == v_l);
2452 CHECK(json::to_bjdata(json::from_bjdata(v_M), true, true) == v_M);
2453 CHECK(json::to_bjdata(json::from_bjdata(v_L), true, true) == v_L);
2454 CHECK(json::to_bjdata(json::from_bjdata(v_d), true, true) == v_d);
2455 CHECK(json::to_bjdata(json::from_bjdata(v_D), true, true) == v_D);
2456 CHECK(json::to_bjdata(json::from_bjdata(v_C), true, true) == v_C);
2457 }
2458
2459 SECTION("optimized ndarray (type and vector-size as 1D array)")
2460 {
2461 // create vector with two elements of the same type
2462 std::vector<uint8_t> v_0 = {'[', '$', 'i', '#', '[', ']'};
2463 std::vector<uint8_t> v_E = {'[', '$', 'i', '#', '[', 'i', 2, 'i', 0, ']'};
2464 std::vector<uint8_t> v_i = {'[', '$', 'i', '#', '[', 'i', 1, 'i', 2, ']', 0x7F, 0x7F};
2465 std::vector<uint8_t> v_U = {'[', '$', 'U', '#', '[', 'i', 1, 'i', 2, ']', 0xFF, 0xFF};
2466 std::vector<uint8_t> v_I = {'[', '$', 'I', '#', '[', 'i', 1, 'i', 2, ']', 0xFF, 0x7F, 0xFF, 0x7F};
2467 std::vector<uint8_t> v_u = {'[', '$', 'u', '#', '[', 'i', 1, 'i', 2, ']', 0x0F, 0xA7, 0x0F, 0xA7};
2468 std::vector<uint8_t> v_l = {'[', '$', 'l', '#', '[', 'i', 1, 'i', 2, ']', 0xFF, 0xFF, 0xFF, 0x7F, 0xFF, 0xFF, 0xFF, 0x7F};
2469 std::vector<uint8_t> v_m = {'[', '$', 'm', '#', '[', 'i', 1, 'i', 2, ']', 0xFF, 0xC9, 0x9A, 0xBB, 0xFF, 0xC9, 0x9A, 0xBB};
2470 std::vector<uint8_t> v_L = {'[', '$', 'L', '#', '[', 'i', 1, 'i', 2, ']', 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F};
2471 std::vector<uint8_t> v_M = {'[', '$', 'M', '#', '[', 'i', 1, 'i', 2, ']', 0xFF, 0xFF, 0x63, 0xA7, 0xB3, 0xB6, 0xE0, 0x8D, 0xFF, 0xFF, 0x63, 0xA7, 0xB3, 0xB6, 0xE0, 0x8D};
2472 std::vector<uint8_t> v_D = {'[', '$', 'D', '#', '[', 'i', 1, 'i', 2, ']', 0x4a, 0xd8, 0x12, 0x4d, 0xfb, 0x21, 0x09, 0x40, 0x4a, 0xd8, 0x12, 0x4d, 0xfb, 0x21, 0x09, 0x40};
2473 std::vector<uint8_t> v_S = {'[', '#', '[', 'i', 1, 'i', 2, ']', 'S', 'i', 1, 'a', 'S', 'i', 1, 'a'};
2474 std::vector<uint8_t> v_C = {'[', '$', 'C', '#', '[', 'i', 1, 'i', 2, ']', 'a', 'a'};
2475 std::vector<uint8_t> v_R = {'[', '#', '[', 'i', 2, ']', 'i', 6, 'U', 7};
2476
2477 // check if vector is parsed correctly
2478 CHECK(json::from_bjdata(v_0) == json::array());
2479 CHECK(json::from_bjdata(v_E) == json::array());
2480 CHECK(json::from_bjdata(v_i) == json({127, 127}));
2481 CHECK(json::from_bjdata(v_U) == json({255, 255}));
2482 CHECK(json::from_bjdata(v_I) == json({32767, 32767}));
2483 CHECK(json::from_bjdata(v_u) == json({42767, 42767}));
2484 CHECK(json::from_bjdata(v_l) == json({2147483647, 2147483647}));
2485 CHECK(json::from_bjdata(v_m) == json({3147483647, 3147483647}));
2486 CHECK(json::from_bjdata(v_L) == json({9223372036854775807, 9223372036854775807}));
2487 CHECK(json::from_bjdata(v_M) == json({10223372036854775807ull, 10223372036854775807ull}));
2488 CHECK(json::from_bjdata(v_D) == json({3.1415926, 3.1415926}));
2489 CHECK(json::from_bjdata(v_S) == json({"a", "a"}));
2490 CHECK(json::from_bjdata(v_C) == json({"a", "a"}));
2491 CHECK(json::from_bjdata(v_R) == json({6, 7}));
2492 }
2493
2494 SECTION("optimized ndarray (type and vector-size as size-optimized array)")
2495 {
2496 // create vector with two elements of the same type
2497 std::vector<uint8_t> v_i = {'[', '$', 'i', '#', '[', '#', 'i', 2, 'i', 1, 'i', 2, 0x7F, 0x7F};
2498 std::vector<uint8_t> v_U = {'[', '$', 'U', '#', '[', '#', 'i', 2, 'i', 1, 'i', 2, 0xFF, 0xFF};
2499 std::vector<uint8_t> v_I = {'[', '$', 'I', '#', '[', '#', 'i', 2, 'i', 1, 'i', 2, 0xFF, 0x7F, 0xFF, 0x7F};
2500 std::vector<uint8_t> v_u = {'[', '$', 'u', '#', '[', '#', 'i', 2, 'i', 1, 'i', 2, 0x0F, 0xA7, 0x0F, 0xA7};
2501 std::vector<uint8_t> v_l = {'[', '$', 'l', '#', '[', '#', 'i', 2, 'i', 1, 'i', 2, 0xFF, 0xFF, 0xFF, 0x7F, 0xFF, 0xFF, 0xFF, 0x7F};
2502 std::vector<uint8_t> v_m = {'[', '$', 'm', '#', '[', '#', 'i', 2, 'i', 1, 'i', 2, 0xFF, 0xC9, 0x9A, 0xBB, 0xFF, 0xC9, 0x9A, 0xBB};
2503 std::vector<uint8_t> v_L = {'[', '$', 'L', '#', '[', '#', 'i', 2, 'i', 1, 'i', 2, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F};
2504 std::vector<uint8_t> v_M = {'[', '$', 'M', '#', '[', '#', 'i', 2, 'i', 1, 'i', 2, 0xFF, 0xFF, 0x63, 0xA7, 0xB3, 0xB6, 0xE0, 0x8D, 0xFF, 0xFF, 0x63, 0xA7, 0xB3, 0xB6, 0xE0, 0x8D};
2505 std::vector<uint8_t> v_D = {'[', '$', 'D', '#', '[', '#', 'i', 2, 'i', 1, 'i', 2, 0x4a, 0xd8, 0x12, 0x4d, 0xfb, 0x21, 0x09, 0x40, 0x4a, 0xd8, 0x12, 0x4d, 0xfb, 0x21, 0x09, 0x40};
2506 std::vector<uint8_t> v_S = {'[', '#', '[', '#', 'i', 2, 'i', 1, 'i', 2, 'S', 'i', 1, 'a', 'S', 'i', 1, 'a'};
2507 std::vector<uint8_t> v_C = {'[', '$', 'C', '#', '[', '#', 'i', 2, 'i', 1, 'i', 2, 'a', 'a'};
2508
2509 // check if vector is parsed correctly
2510 CHECK(json::from_bjdata(v_i) == json({127, 127}));
2511 CHECK(json::from_bjdata(v_U) == json({255, 255}));
2512 CHECK(json::from_bjdata(v_I) == json({32767, 32767}));
2513 CHECK(json::from_bjdata(v_u) == json({42767, 42767}));
2514 CHECK(json::from_bjdata(v_l) == json({2147483647, 2147483647}));
2515 CHECK(json::from_bjdata(v_m) == json({3147483647, 3147483647}));
2516 CHECK(json::from_bjdata(v_L) == json({9223372036854775807, 9223372036854775807}));
2517 CHECK(json::from_bjdata(v_M) == json({10223372036854775807ull, 10223372036854775807ull}));
2518 CHECK(json::from_bjdata(v_D) == json({3.1415926, 3.1415926}));
2519 CHECK(json::from_bjdata(v_S) == json({"a", "a"}));
2520 CHECK(json::from_bjdata(v_C) == json({"a", "a"}));
2521 }
2522
2523 SECTION("invalid ndarray annotations remains as object")
2524 {
2525 // check if invalid ND array annotations stay as object
2526 json j_type = json({{"_ArrayData_", {1, 2, 3, 4, 5, 6}}, {"_ArraySize_", {2, 3}}, {"_ArrayType_", "invalidtype"}});
2527 json j_size = json({{"_ArrayData_", {1, 2, 3, 4, 5}}, {"_ArraySize_", {2, 3}}, {"_ArrayType_", "uint8"}});
2528
2529 // roundtrip: output should stay as object
2530 CHECK(json::from_bjdata(json::to_bjdata(j_type), true, true) == j_type);
2531 CHECK(json::from_bjdata(json::to_bjdata(j_size), true, true) == j_size);
2532 }
2533 }
2534 }
2535
2536 SECTION("parse errors")
2537 {
2538 SECTION("empty byte vector")
2539 {
2540 json _;
2541 CHECK_THROWS_WITH_AS(_ = json::from_bjdata(std::vector<uint8_t>()),
2542 "[json.exception.parse_error.110] parse error at byte 1: syntax error while parsing BJData value: unexpected end of input", json::parse_error&);
2543 }
2544
2545 SECTION("char")
2546 {
2547 SECTION("eof after C byte")
2548 {
2549 std::vector<uint8_t> v = {'C'};
2550 json _;
2551 CHECK_THROWS_WITH_AS(_ = json::from_bjdata(v), "[json.exception.parse_error.110] parse error at byte 2: syntax error while parsing BJData char: unexpected end of input", json::parse_error&);
2552 }
2553
2554 SECTION("byte out of range")
2555 {
2556 std::vector<uint8_t> v = {'C', 130};
2557 json _;
2558 CHECK_THROWS_WITH(_ = json::from_bjdata(v), "[json.exception.parse_error.113] parse error at byte 2: syntax error while parsing BJData char: byte after 'C' must be in range 0x00..0x7F; last byte: 0x82");
2559 }
2560 }
2561
2562 SECTION("strings")
2563 {
2564 SECTION("eof after S byte")
2565 {
2566 std::vector<uint8_t> v = {'S'};
2567 json _;
2568 CHECK_THROWS_WITH_AS(_ = json::from_bjdata(v), "[json.exception.parse_error.110] parse error at byte 2: syntax error while parsing BJData value: unexpected end of input", json::parse_error&);
2569 }
2570
2571 SECTION("invalid byte")
2572 {
2573 std::vector<uint8_t> v = {'S', '1', 'a'};
2574 json _;
2575 CHECK_THROWS_WITH_AS(_ = json::from_bjdata(v), "[json.exception.parse_error.113] parse error at byte 2: syntax error while parsing BJData string: expected length type specification (U, i, u, I, m, l, M, L); last byte: 0x31", json::parse_error&);
2576 }
2577
2578 SECTION("parse bjdata markers in ubjson")
2579 {
2580 // create a single-character string for all number types
2581 std::vector<uint8_t> s_u = {'S', 'u', 1, 0, 'a'};
2582 std::vector<uint8_t> s_m = {'S', 'm', 1, 0, 0, 0, 'a'};
2583 std::vector<uint8_t> s_M = {'S', 'M', 1, 0, 0, 0, 0, 0, 0, 0, 'a'};
2584
2585 json _;
2586 // check if string is parsed correctly to "a"
2587 CHECK_THROWS_WITH_AS(_ = json::from_ubjson(s_u), "[json.exception.parse_error.113] parse error at byte 2: syntax error while parsing UBJSON string: expected length type specification (U, i, I, l, L); last byte: 0x75", json::parse_error&);
2588 CHECK_THROWS_WITH_AS(_ = json::from_ubjson(s_m), "[json.exception.parse_error.113] parse error at byte 2: syntax error while parsing UBJSON string: expected length type specification (U, i, I, l, L); last byte: 0x6D", json::parse_error&);
2589 CHECK_THROWS_WITH_AS(_ = json::from_ubjson(s_M), "[json.exception.parse_error.113] parse error at byte 2: syntax error while parsing UBJSON string: expected length type specification (U, i, I, l, L); last byte: 0x4D", json::parse_error&);
2590 }
2591 }
2592
2593 SECTION("array")
2594 {
2595 SECTION("optimized array: no size following type")
2596 {
2597 std::vector<uint8_t> v = {'[', '$', 'i', 2};
2598 json _;
2599 CHECK_THROWS_WITH_AS(_ = json::from_bjdata(v), "[json.exception.parse_error.112] parse error at byte 4: syntax error while parsing BJData size: expected '#' after type information; last byte: 0x02", json::parse_error&);
2600 }
2601
2602 SECTION("optimized array: negative size")
2603 {
2604 std::vector<uint8_t> v1 = {'[', '#', 'i', 0xF1};
2605 std::vector<uint8_t> v2 = {'[', '$', 'I', '#', 'i', 0xF2};
2606 std::vector<uint8_t> v3 = {'[', '$', 'I', '#', '[', 'i', 0xF4, 'i', 0x02, ']'};
2607 std::vector<uint8_t> v4 = {'[', '$', 0xF6, '#', 'i', 0xF7};
2608 std::vector<uint8_t> v5 = {'[', '$', 'I', '#', '[', 'i', 0xF5, 'i', 0xF1, ']'};
2609 std::vector<uint8_t> v6 = {'[', '#', '[', 'i', 0xF3, 'i', 0x02, ']'};
2610
2611 std::vector<uint8_t> vI = {'[', '#', 'I', 0x00, 0xF1};
2612 std::vector<uint8_t> vl = {'[', '#', 'l', 0x00, 0x00, 0x00, 0xF2};
2613 std::vector<uint8_t> vL = {'[', '#', 'L', 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF3};
2614 std::vector<uint8_t> vM = {'[', '$', 'M', '#', '[', 'I', 0x00, 0x20, 'M', 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0xFF, ']'};
2615 std::vector<uint8_t> vMX = {'[', '$', 'U', '#', '[', 'M', 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 'U', 0x01, ']'};
2616
2617 json _;
2618 CHECK_THROWS_WITH_AS(_ = json::from_bjdata(v1), "[json.exception.parse_error.113] parse error at byte 4: syntax error while parsing BJData size: count in an optimized container must be positive", json::parse_error&);
2619 CHECK(json::from_bjdata(v1, true, false).is_discarded());
2620
2621 CHECK_THROWS_WITH_AS(_ = json::from_bjdata(v2), "[json.exception.parse_error.113] parse error at byte 6: syntax error while parsing BJData size: count in an optimized container must be positive", json::parse_error&);
2622 CHECK(json::from_bjdata(v2, true, false).is_discarded());
2623
2624 CHECK_THROWS_WITH_AS(_ = json::from_bjdata(v3), "[json.exception.parse_error.113] parse error at byte 7: syntax error while parsing BJData size: count in an optimized container must be positive", json::parse_error&);
2625 CHECK(json::from_bjdata(v3, true, false).is_discarded());
2626
2627 CHECK_THROWS_WITH_AS(_ = json::from_bjdata(v4), "[json.exception.parse_error.113] parse error at byte 6: syntax error while parsing BJData size: count in an optimized container must be positive", json::parse_error&);
2628 CHECK(json::from_bjdata(v4, true, false).is_discarded());
2629
2630 CHECK_THROWS_WITH_AS(_ = json::from_bjdata(v5), "[json.exception.parse_error.113] parse error at byte 7: syntax error while parsing BJData size: count in an optimized container must be positive", json::parse_error&);
2631 CHECK(json::from_bjdata(v5, true, false).is_discarded());
2632
2633 CHECK_THROWS_WITH_AS(_ = json::from_bjdata(v6), "[json.exception.parse_error.113] parse error at byte 5: syntax error while parsing BJData size: count in an optimized container must be positive", json::parse_error&);
2634 CHECK(json::from_bjdata(v6, true, false).is_discarded());
2635
2636 CHECK_THROWS_WITH_AS(_ = json::from_bjdata(vI), "[json.exception.parse_error.113] parse error at byte 5: syntax error while parsing BJData size: count in an optimized container must be positive", json::parse_error&);
2637 CHECK(json::from_bjdata(vI, true, false).is_discarded());
2638
2639 CHECK_THROWS_WITH_AS(_ = json::from_bjdata(vl), "[json.exception.parse_error.113] parse error at byte 7: syntax error while parsing BJData size: count in an optimized container must be positive", json::parse_error&);
2640 CHECK(json::from_bjdata(vl, true, false).is_discarded());
2641
2642 CHECK_THROWS_WITH_AS(_ = json::from_bjdata(vL), "[json.exception.parse_error.113] parse error at byte 11: syntax error while parsing BJData size: count in an optimized container must be positive", json::parse_error&);
2643 CHECK(json::from_bjdata(vL, true, false).is_discarded());
2644
2645 #if SIZE_MAX != 0xffffffff
2646 CHECK_THROWS_WITH_AS(_ = json::from_bjdata(vM), "[json.exception.out_of_range.408] syntax error while parsing BJData size: excessive ndarray size caused overflow", json::out_of_range&);
2647 #else
2648 CHECK_THROWS_WITH_AS(_ = json::from_bjdata(vM), "[json.exception.out_of_range.408] syntax error while parsing BJData size: integer value overflow", json::out_of_range&);
2649 #endif
2650 CHECK(json::from_bjdata(vM, true, false).is_discarded());
2651
2652 #if SIZE_MAX != 0xffffffff
2653 CHECK_THROWS_WITH_AS(_ = json::from_bjdata(vMX), "[json.exception.out_of_range.408] syntax error while parsing BJData size: excessive ndarray size caused overflow", json::out_of_range&);
2654 #else
2655 CHECK_THROWS_WITH_AS(_ = json::from_bjdata(vMX), "[json.exception.out_of_range.408] syntax error while parsing BJData size: integer value overflow", json::out_of_range&);
2656 #endif
2657 CHECK(json::from_bjdata(vMX, true, false).is_discarded());
2658 }
2659
2660 SECTION("optimized array: integer value overflow")
2661 {
2662 std::vector<uint8_t> vL = {'[', '#', 'L', 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F};
2663 std::vector<uint8_t> vM = {'[', '$', 'M', '#', '[', 'I', 0x00, 0x20, 'M', 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0xFF, ']'};
2664
2665 json _;
2666 #if SIZE_MAX == 0xffffffff
2667 CHECK_THROWS_WITH_AS(_ = json::from_bjdata(vL), "[json.exception.out_of_range.408] syntax error while parsing BJData size: integer value overflow", json::out_of_range&);
2668 CHECK(json::from_bjdata(vL, true, false).is_discarded());
2669 #endif
2670
2671 #if SIZE_MAX == 0xffffffff
2672 CHECK_THROWS_WITH_AS(_ = json::from_bjdata(vM), "[json.exception.out_of_range.408] syntax error while parsing BJData size: integer value overflow", json::out_of_range&);
2673 CHECK(json::from_bjdata(vM, true, false).is_discarded());
2674 #endif
2675 }
2676
2677 SECTION("do not accept NTFZ markers in ndarray optimized type (with count)")
2678 {
2679 json _;
2680 std::vector<uint8_t> v_N = {'[', '$', 'N', '#', '[', '#', 'i', 2, 'i', 1, 'i', 2};
2681 std::vector<uint8_t> v_T = {'[', '$', 'T', '#', '[', '#', 'i', 2, 'i', 1, 'i', 2};
2682 std::vector<uint8_t> v_F = {'[', '$', 'F', '#', '[', '#', 'i', 2, 'i', 1, 'i', 2};
2683 std::vector<uint8_t> v_Z = {'[', '$', 'Z', '#', '[', '#', 'i', 2, 'i', 1, 'i', 2};
2684
2685 CHECK_THROWS_WITH_AS(_ = json::from_bjdata(v_N), "[json.exception.parse_error.112] parse error at byte 3: syntax error while parsing BJData type: marker 0x4E is not a permitted optimized array type", json::parse_error&);
2686 CHECK(json::from_bjdata(v_N, true, false).is_discarded());
2687
2688 CHECK_THROWS_WITH_AS(_ = json::from_bjdata(v_T), "[json.exception.parse_error.112] parse error at byte 3: syntax error while parsing BJData type: marker 0x54 is not a permitted optimized array type", json::parse_error&);
2689 CHECK(json::from_bjdata(v_T, true, false).is_discarded());
2690
2691 CHECK_THROWS_WITH_AS(_ = json::from_bjdata(v_F), "[json.exception.parse_error.112] parse error at byte 3: syntax error while parsing BJData type: marker 0x46 is not a permitted optimized array type", json::parse_error&);
2692 CHECK(json::from_bjdata(v_F, true, false).is_discarded());
2693
2694 CHECK_THROWS_WITH_AS(_ = json::from_bjdata(v_Z), "[json.exception.parse_error.112] parse error at byte 3: syntax error while parsing BJData type: marker 0x5A is not a permitted optimized array type", json::parse_error&);
2695 CHECK(json::from_bjdata(v_Z, true, false).is_discarded());
2696 }
2697
2698 SECTION("do not accept NTFZ markers in ndarray optimized type (without count)")
2699 {
2700 json _;
2701 std::vector<uint8_t> v_N = {'[', '$', 'N', '#', '[', 'i', 1, 'i', 2, ']'};
2702 std::vector<uint8_t> v_T = {'[', '$', 'T', '#', '[', 'i', 1, 'i', 2, ']'};
2703 std::vector<uint8_t> v_F = {'[', '$', 'F', '#', '[', 'i', 1, 'i', 2, ']'};
2704 std::vector<uint8_t> v_Z = {'[', '$', 'Z', '#', '[', 'i', 1, 'i', 2, ']'};
2705
2706 CHECK_THROWS_WITH_AS(_ = json::from_bjdata(v_N), "[json.exception.parse_error.112] parse error at byte 3: syntax error while parsing BJData type: marker 0x4E is not a permitted optimized array type", json::parse_error&);
2707 CHECK(json::from_bjdata(v_N, true, false).is_discarded());
2708
2709 CHECK_THROWS_WITH_AS(_ = json::from_bjdata(v_T), "[json.exception.parse_error.112] parse error at byte 3: syntax error while parsing BJData type: marker 0x54 is not a permitted optimized array type", json::parse_error&);
2710 CHECK(json::from_bjdata(v_T, true, false).is_discarded());
2711
2712 CHECK_THROWS_WITH_AS(_ = json::from_bjdata(v_F), "[json.exception.parse_error.112] parse error at byte 3: syntax error while parsing BJData type: marker 0x46 is not a permitted optimized array type", json::parse_error&);
2713 CHECK(json::from_bjdata(v_F, true, false).is_discarded());
2714
2715 CHECK_THROWS_WITH_AS(_ = json::from_bjdata(v_Z), "[json.exception.parse_error.112] parse error at byte 3: syntax error while parsing BJData type: marker 0x5A is not a permitted optimized array type", json::parse_error&);
2716 CHECK(json::from_bjdata(v_Z, true, false).is_discarded());
2717 }
2718 }
2719
2720 SECTION("strings")
2721 {
2722 std::vector<uint8_t> vS = {'S'};
2723 json _;
2724 CHECK_THROWS_WITH_AS(_ = json::from_bjdata(vS), "[json.exception.parse_error.110] parse error at byte 2: syntax error while parsing BJData value: unexpected end of input", json::parse_error&);
2725 CHECK(json::from_bjdata(vS, true, false).is_discarded());
2726
2727 std::vector<uint8_t> v = {'S', 'i', '2', 'a'};
2728 CHECK_THROWS_WITH_AS(_ = json::from_bjdata(v), "[json.exception.parse_error.110] parse error at byte 5: syntax error while parsing BJData string: unexpected end of input", json::parse_error&);
2729 CHECK(json::from_bjdata(v, true, false).is_discarded());
2730
2731 std::vector<uint8_t> vC = {'C'};
2732 CHECK_THROWS_WITH_AS(_ = json::from_bjdata(vC), "[json.exception.parse_error.110] parse error at byte 2: syntax error while parsing BJData char: unexpected end of input", json::parse_error&);
2733 CHECK(json::from_bjdata(vC, true, false).is_discarded());
2734 }
2735
2736 SECTION("sizes")
2737 {
2738 std::vector<uint8_t> vU = {'[', '#', 'U'};
2739 json _;
2740 CHECK_THROWS_WITH_AS(_ = json::from_bjdata(vU), "[json.exception.parse_error.110] parse error at byte 4: syntax error while parsing BJData number: unexpected end of input", json::parse_error&);
2741 CHECK(json::from_bjdata(vU, true, false).is_discarded());
2742
2743 std::vector<uint8_t> vi = {'[', '#', 'i'};
2744 CHECK_THROWS_WITH_AS(_ = json::from_bjdata(vi), "[json.exception.parse_error.110] parse error at byte 4: syntax error while parsing BJData number: unexpected end of input", json::parse_error&);
2745 CHECK(json::from_bjdata(vi, true, false).is_discarded());
2746
2747 std::vector<uint8_t> vI = {'[', '#', 'I'};
2748 CHECK_THROWS_WITH_AS(_ = json::from_bjdata(vI), "[json.exception.parse_error.110] parse error at byte 4: syntax error while parsing BJData number: unexpected end of input", json::parse_error&);
2749 CHECK(json::from_bjdata(vI, true, false).is_discarded());
2750
2751 std::vector<uint8_t> vu = {'[', '#', 'u'};
2752 CHECK_THROWS_WITH_AS(_ = json::from_bjdata(vu), "[json.exception.parse_error.110] parse error at byte 4: syntax error while parsing BJData number: unexpected end of input", json::parse_error&);
2753 CHECK(json::from_bjdata(vu, true, false).is_discarded());
2754
2755 std::vector<uint8_t> vl = {'[', '#', 'l'};
2756 CHECK_THROWS_WITH_AS(_ = json::from_bjdata(vl), "[json.exception.parse_error.110] parse error at byte 4: syntax error while parsing BJData number: unexpected end of input", json::parse_error&);
2757 CHECK(json::from_bjdata(vl, true, false).is_discarded());
2758
2759 std::vector<uint8_t> vm = {'[', '#', 'm'};
2760 CHECK_THROWS_WITH_AS(_ = json::from_bjdata(vm), "[json.exception.parse_error.110] parse error at byte 4: syntax error while parsing BJData number: unexpected end of input", json::parse_error&);
2761 CHECK(json::from_bjdata(vm, true, false).is_discarded());
2762
2763 std::vector<uint8_t> vL = {'[', '#', 'L'};
2764 CHECK_THROWS_WITH_AS(_ = json::from_bjdata(vL), "[json.exception.parse_error.110] parse error at byte 4: syntax error while parsing BJData number: unexpected end of input", json::parse_error&);
2765 CHECK(json::from_bjdata(vL, true, false).is_discarded());
2766
2767 std::vector<uint8_t> vM = {'[', '#', 'M'};
2768 CHECK_THROWS_WITH_AS(_ = json::from_bjdata(vM), "[json.exception.parse_error.110] parse error at byte 4: syntax error while parsing BJData number: unexpected end of input", json::parse_error&);
2769 CHECK(json::from_bjdata(vM, true, false).is_discarded());
2770
2771 std::vector<uint8_t> v0 = {'[', '#', 'T', ']'};
2772 CHECK_THROWS_WITH(_ = json::from_bjdata(v0), "[json.exception.parse_error.113] parse error at byte 3: syntax error while parsing BJData size: expected length type specification (U, i, u, I, m, l, M, L) after '#'; last byte: 0x54");
2773 CHECK(json::from_bjdata(v0, true, false).is_discarded());
2774 }
2775
2776 SECTION("parse bjdata markers as array size in ubjson")
2777 {
2778 json _;
2779 std::vector<uint8_t> vu = {'[', '#', 'u'};
2780 CHECK_THROWS_WITH_AS(_ = json::from_ubjson(vu), "[json.exception.parse_error.113] parse error at byte 3: syntax error while parsing UBJSON size: expected length type specification (U, i, I, l, L) after '#'; last byte: 0x75", json::parse_error&);
2781 CHECK(json::from_ubjson(vu, true, false).is_discarded());
2782
2783 std::vector<uint8_t> vm = {'[', '#', 'm'};
2784 CHECK_THROWS_WITH_AS(_ = json::from_ubjson(vm), "[json.exception.parse_error.113] parse error at byte 3: syntax error while parsing UBJSON size: expected length type specification (U, i, I, l, L) after '#'; last byte: 0x6D", json::parse_error&);
2785 CHECK(json::from_ubjson(vm, true, false).is_discarded());
2786
2787 std::vector<uint8_t> vM = {'[', '#', 'M'};
2788 CHECK_THROWS_WITH_AS(_ = json::from_ubjson(vM), "[json.exception.parse_error.113] parse error at byte 3: syntax error while parsing UBJSON size: expected length type specification (U, i, I, l, L) after '#'; last byte: 0x4D", json::parse_error&);
2789 CHECK(json::from_ubjson(vM, true, false).is_discarded());
2790
2791 std::vector<uint8_t> v0 = {'[', '#', '['};
2792 CHECK_THROWS_WITH_AS(_ = json::from_ubjson(v0), "[json.exception.parse_error.113] parse error at byte 3: syntax error while parsing UBJSON size: expected length type specification (U, i, I, l, L) after '#'; last byte: 0x5B", json::parse_error&);
2793 CHECK(json::from_ubjson(v0, true, false).is_discarded());
2794 }
2795
2796 SECTION("types")
2797 {
2798 std::vector<uint8_t> v0 = {'[', '$'};
2799 json _;
2800 CHECK_THROWS_WITH_AS(_ = json::from_bjdata(v0), "[json.exception.parse_error.110] parse error at byte 3: syntax error while parsing BJData type: unexpected end of input", json::parse_error&);
2801 CHECK(json::from_bjdata(v0, true, false).is_discarded());
2802
2803 std::vector<uint8_t> vi = {'[', '$', '#'};
2804 CHECK_THROWS_WITH_AS(_ = json::from_bjdata(vi), "[json.exception.parse_error.110] parse error at byte 4: syntax error while parsing BJData value: unexpected end of input", json::parse_error&);
2805 CHECK(json::from_bjdata(vi, true, false).is_discarded());
2806
2807 std::vector<uint8_t> vU = {'[', '$', 'U'};
2808 CHECK_THROWS_WITH_AS(_ = json::from_bjdata(vU), "[json.exception.parse_error.110] parse error at byte 4: syntax error while parsing BJData value: unexpected end of input", json::parse_error&);
2809 CHECK(json::from_bjdata(vU, true, false).is_discarded());
2810
2811 std::vector<uint8_t> v1 = {'[', '$', '['};
2812 CHECK_THROWS_WITH_AS(_ = json::from_bjdata(v1), "[json.exception.parse_error.112] parse error at byte 3: syntax error while parsing BJData type: marker 0x5B is not a permitted optimized array type", json::parse_error&);
2813 CHECK(json::from_bjdata(v1, true, false).is_discarded());
2814 }
2815
2816 SECTION("arrays")
2817 {
2818 std::vector<uint8_t> vST = {'[', '$', 'i', '#', 'i', 2, 1};
2819 json _;
2820 CHECK_THROWS_WITH_AS(_ = json::from_bjdata(vST), "[json.exception.parse_error.110] parse error at byte 8: syntax error while parsing BJData number: unexpected end of input", json::parse_error&);
2821 CHECK(json::from_bjdata(vST, true, false).is_discarded());
2822
2823 std::vector<uint8_t> vS = {'[', '#', 'i', 2, 'i', 1};
2824 CHECK_THROWS_WITH_AS(_ = json::from_bjdata(vS), "[json.exception.parse_error.110] parse error at byte 7: syntax error while parsing BJData value: unexpected end of input", json::parse_error&);
2825 CHECK(json::from_bjdata(vS, true, false).is_discarded());
2826
2827 std::vector<uint8_t> v = {'[', 'i', 2, 'i', 1};
2828 CHECK_THROWS_WITH_AS(_ = json::from_bjdata(v), "[json.exception.parse_error.110] parse error at byte 6: syntax error while parsing BJData value: unexpected end of input", json::parse_error&);
2829 CHECK(json::from_bjdata(v, true, false).is_discarded());
2830 }
2831
2832 SECTION("ndarrays")
2833 {
2834 std::vector<uint8_t> vST = {'[', '$', 'i', '#', '[', '$', 'i', '#'};
2835 json _;
2836 CHECK_THROWS_WITH_AS(_ = json::from_bjdata(vST), "[json.exception.parse_error.113] parse error at byte 9: syntax error while parsing BJData size: expected length type specification (U, i, u, I, m, l, M, L) after '#'; last byte: 0xFF", json::parse_error&);
2837 CHECK(json::from_bjdata(vST, true, false).is_discarded());
2838
2839 std::vector<uint8_t> v = {'[', '$', 'i', '#', '[', '$', 'i', '#', 'i', 2, 1, 2};
2840 CHECK_THROWS_WITH_AS(_ = json::from_bjdata(v), "[json.exception.parse_error.110] parse error at byte 13: syntax error while parsing BJData number: unexpected end of input", json::parse_error&);
2841 CHECK(json::from_bjdata(v, true, false).is_discarded());
2842
2843 std::vector<uint8_t> vS0 = {'[', '$', 'i', '#', '[', '$', 'i', '#', 'i', 2, 1};
2844 CHECK_THROWS_WITH_AS(_ = json::from_bjdata(vS0), "[json.exception.parse_error.110] parse error at byte 12: syntax error while parsing BJData number: unexpected end of input", json::parse_error&);
2845 CHECK(json::from_bjdata(vS0, true, false).is_discarded());
2846
2847 std::vector<uint8_t> vS = {'[', '$', 'i', '#', '[', '#', 'i', 2, 1, 2, 1};
2848 CHECK_THROWS_WITH_AS(_ = json::from_bjdata(vS), "[json.exception.parse_error.113] parse error at byte 9: syntax error while parsing BJData size: expected length type specification (U, i, u, I, m, l, M, L) after '#'; last byte: 0x01", json::parse_error&);
2849 CHECK(json::from_bjdata(vS, true, false).is_discarded());
2850
2851 std::vector<uint8_t> vT = {'[', '$', 'i', '#', '[', 'i', 2, 'i'};
2852 CHECK_THROWS_WITH_AS(_ = json::from_bjdata(vT), "[json.exception.parse_error.110] parse error at byte 9: syntax error while parsing BJData number: unexpected end of input", json::parse_error&);
2853 CHECK(json::from_bjdata(vT, true, false).is_discarded());
2854
2855 std::vector<uint8_t> vT0 = {'[', '$', 'i', '#', '[', 'i'};
2856 CHECK_THROWS_WITH_AS(_ = json::from_bjdata(vT0), "[json.exception.parse_error.110] parse error at byte 7: syntax error while parsing BJData number: unexpected end of input", json::parse_error&);
2857 CHECK(json::from_bjdata(vT0, true, false).is_discarded());
2858
2859 std::vector<uint8_t> vu = {'[', '$', 'i', '#', '[', '$', 'i', '#', 'u', 1, 0};
2860 CHECK_THROWS_WITH_AS(_ = json::from_bjdata(vu), "[json.exception.parse_error.110] parse error at byte 12: syntax error while parsing BJData number: unexpected end of input", json::parse_error&);
2861 CHECK(json::from_bjdata(vu, true, false).is_discarded());
2862
2863 std::vector<uint8_t> vm = {'[', '$', 'i', '#', '[', '$', 'i', '#', 'm', 1, 0, 0, 0};
2864 CHECK_THROWS_WITH_AS(_ = json::from_bjdata(vm), "[json.exception.parse_error.110] parse error at byte 14: syntax error while parsing BJData number: unexpected end of input", json::parse_error&);
2865 CHECK(json::from_bjdata(vm, true, false).is_discarded());
2866
2867 std::vector<uint8_t> vM = {'[', '$', 'i', '#', '[', '$', 'i', '#', 'M', 1, 0, 0, 0, 0, 0, 0, 0};
2868 CHECK_THROWS_WITH_AS(_ = json::from_bjdata(vM), "[json.exception.parse_error.110] parse error at byte 18: syntax error while parsing BJData number: unexpected end of input", json::parse_error&);
2869 CHECK(json::from_bjdata(vM, true, false).is_discarded());
2870
2871 std::vector<uint8_t> vU = {'[', '$', 'U', '#', '[', '$', 'i', '#', 'i', 2, 2, 3, 1, 2, 3, 4, 5};
2872 CHECK_THROWS_WITH_AS(_ = json::from_bjdata(vU), "[json.exception.parse_error.110] parse error at byte 18: syntax error while parsing BJData number: unexpected end of input", json::parse_error&);
2873 CHECK(json::from_bjdata(vU, true, false).is_discarded());
2874
2875 std::vector<uint8_t> vT1 = {'[', '$', 'T', '#', '[', '$', 'i', '#', 'i', 2, 2, 3};
2876 CHECK(json::from_bjdata(vT1, true, false).is_discarded());
2877
2878 std::vector<uint8_t> vh = {'[', '$', 'h', '#', '[', '$', 'i', '#', 'i', 2, 2, 3};
2879 CHECK(json::from_bjdata(vh, true, false).is_discarded());
2880
2881 std::vector<uint8_t> vR = {'[', '$', 'i', '#', '[', 'i', 1, '[', ']', ']', 1};
2882 CHECK_THROWS_WITH_AS(_ = json::from_bjdata(vR), "[json.exception.parse_error.113] parse error at byte 8: syntax error while parsing BJData size: ndarray dimentional vector is not allowed", json::parse_error&);
2883 CHECK(json::from_bjdata(vR, true, false).is_discarded());
2884
2885 std::vector<uint8_t> vRo = {'[', '$', 'i', '#', '[', 'i', 0, '{', '}', ']', 1};
2886 CHECK_THROWS_WITH_AS(_ = json::from_bjdata(vRo), "[json.exception.parse_error.113] parse error at byte 8: syntax error while parsing BJData size: expected length type specification (U, i, u, I, m, l, M, L) after '#'; last byte: 0x7B", json::parse_error&);
2887 CHECK(json::from_bjdata(vRo, true, false).is_discarded());
2888
2889 std::vector<uint8_t> vR1 = {'[', '$', 'i', '#', '[', '[', 'i', 1, ']', ']', 1};
2890 CHECK_THROWS_WITH_AS(_ = json::from_bjdata(vR1), "[json.exception.parse_error.113] parse error at byte 6: syntax error while parsing BJData size: ndarray dimentional vector is not allowed", json::parse_error&);
2891 CHECK(json::from_bjdata(vR1, true, false).is_discarded());
2892
2893 std::vector<uint8_t> vR2 = {'[', '$', 'i', '#', '[', '#', '[', 'i', 1, ']', ']', 1};
2894 CHECK_THROWS_WITH_AS(_ = json::from_bjdata(vR2), "[json.exception.parse_error.113] parse error at byte 11: syntax error while parsing BJData size: expected length type specification (U, i, u, I, m, l, M, L) after '#'; last byte: 0x5D", json::parse_error&);
2895 CHECK(json::from_bjdata(vR2, true, false).is_discarded());
2896
2897 std::vector<uint8_t> vR3 = {'[', '#', '[', 'i', '2', 'i', 2, ']'};
2898 CHECK_THROWS_WITH_AS(_ = json::from_bjdata(vR3), "[json.exception.parse_error.112] parse error at byte 8: syntax error while parsing BJData size: ndarray requires both type and size", json::parse_error&);
2899 CHECK(json::from_bjdata(vR3, true, false).is_discarded());
2900
2901 std::vector<uint8_t> vR4 = {'[', '$', 'i', '#', '[', '$', 'i', '#', '[', 'i', 1, ']', 1};
2902 CHECK_THROWS_WITH_AS(_ = json::from_bjdata(vR4), "[json.exception.parse_error.110] parse error at byte 14: syntax error while parsing BJData number: unexpected end of input", json::parse_error&);
2903 CHECK(json::from_bjdata(vR4, true, false).is_discarded());
2904
2905 std::vector<uint8_t> vR5 = {'[', '$', 'i', '#', '[', '[', '[', ']', ']', ']'};
2906 CHECK_THROWS_WITH_AS(_ = json::from_bjdata(vR5), "[json.exception.parse_error.113] parse error at byte 6: syntax error while parsing BJData size: ndarray dimentional vector is not allowed", json::parse_error&);
2907 CHECK(json::from_bjdata(vR5, true, false).is_discarded());
2908
2909 std::vector<uint8_t> vR6 = {'[', '$', 'i', '#', '[', '$', 'i', '#', '[', 'i', '2', 'i', 2, ']'};
2910 CHECK_THROWS_WITH_AS(_ = json::from_bjdata(vR6), "[json.exception.parse_error.112] parse error at byte 14: syntax error while parsing BJData size: ndarray can not be recursive", json::parse_error&);
2911 CHECK(json::from_bjdata(vR6, true, false).is_discarded());
2912
2913 std::vector<uint8_t> vH = {'[', 'H', '[', '#', '[', '$', 'i', '#', '[', 'i', '2', 'i', 2, ']'};
2914 CHECK_THROWS_WITH_AS(_ = json::from_bjdata(vH), "[json.exception.parse_error.113] parse error at byte 3: syntax error while parsing BJData size: ndarray dimentional vector is not allowed", json::parse_error&);
2915 CHECK(json::from_bjdata(vH, true, false).is_discarded());
2916 }
2917
2918 SECTION("objects")
2919 {
2920 std::vector<uint8_t> vST = {'{', '$', 'i', '#', 'i', 2, 'i', 1, 'a', 1};
2921 json _;
2922 CHECK_THROWS_WITH_AS(_ = json::from_bjdata(vST), "[json.exception.parse_error.110] parse error at byte 11: syntax error while parsing BJData value: unexpected end of input", json::parse_error&);
2923 CHECK(json::from_bjdata(vST, true, false).is_discarded());
2924
2925 std::vector<uint8_t> vT = {'{', '$', 'i', 'i', 1, 'a', 1};
2926 CHECK_THROWS_WITH(_ = json::from_bjdata(vT), "[json.exception.parse_error.112] parse error at byte 4: syntax error while parsing BJData size: expected '#' after type information; last byte: 0x69");
2927 CHECK(json::from_bjdata(vT, true, false).is_discarded());
2928
2929 std::vector<uint8_t> vS = {'{', '#', 'i', 2, 'i', 1, 'a', 'i', 1};
2930 CHECK_THROWS_WITH_AS(_ = json::from_bjdata(vS), "[json.exception.parse_error.110] parse error at byte 10: syntax error while parsing BJData value: unexpected end of input", json::parse_error&);
2931 CHECK(json::from_bjdata(vS, true, false).is_discarded());
2932
2933 std::vector<uint8_t> v = {'{', 'i', 1, 'a', 'i', 1};
2934 CHECK_THROWS_WITH_AS(_ = json::from_bjdata(v), "[json.exception.parse_error.110] parse error at byte 7: syntax error while parsing BJData value: unexpected end of input", json::parse_error&);
2935 CHECK(json::from_bjdata(v, true, false).is_discarded());
2936
2937 std::vector<uint8_t> v2 = {'{', 'i', 1, 'a', 'i', 1, 'i'};
2938 CHECK_THROWS_WITH_AS(_ = json::from_bjdata(v2), "[json.exception.parse_error.110] parse error at byte 8: syntax error while parsing BJData number: unexpected end of input", json::parse_error&);
2939 CHECK(json::from_bjdata(v2, true, false).is_discarded());
2940
2941 std::vector<uint8_t> v3 = {'{', 'i', 1, 'a'};
2942 CHECK_THROWS_WITH_AS(_ = json::from_bjdata(v3), "[json.exception.parse_error.110] parse error at byte 5: syntax error while parsing BJData value: unexpected end of input", json::parse_error&);
2943 CHECK(json::from_bjdata(v3, true, false).is_discarded());
2944
2945 std::vector<uint8_t> vST1 = {'{', '$', 'd', '#', 'i', 2, 'i', 1, 'a'};
2946 CHECK_THROWS_WITH_AS(_ = json::from_bjdata(vST1), "[json.exception.parse_error.110] parse error at byte 10: syntax error while parsing BJData number: unexpected end of input", json::parse_error&);
2947 CHECK(json::from_bjdata(vST1, true, false).is_discarded());
2948
2949 std::vector<uint8_t> vST2 = {'{', '#', 'i', 2, 'i', 1, 'a'};
2950 CHECK_THROWS_WITH_AS(_ = json::from_bjdata(vST2), "[json.exception.parse_error.110] parse error at byte 8: syntax error while parsing BJData value: unexpected end of input", json::parse_error&);
2951 CHECK(json::from_bjdata(vST2, true, false).is_discarded());
2952
2953 std::vector<uint8_t> vO = {'{', '#', '[', 'i', 2, 'i', 1, ']', 'i', 1, 'a', 'i', 1, 'i', 1, 'b', 'i', 2};
2954 CHECK_THROWS_WITH_AS(_ = json::from_bjdata(vO), "[json.exception.parse_error.112] parse error at byte 8: syntax error while parsing BJData size: ndarray requires both type and size", json::parse_error&);
2955 CHECK(json::from_bjdata(vO, true, false).is_discarded());
2956
2957 std::vector<uint8_t> vO2 = {'{', '$', 'i', '#', '[', 'i', 2, 'i', 1, ']', 'i', 1, 'a', 1, 'i', 1, 'b', 2};
2958 CHECK_THROWS_WITH_AS(_ = json::from_bjdata(vO2), "[json.exception.parse_error.112] parse error at byte 10: syntax error while parsing BJData object: BJData object does not support ND-array size in optimized format", json::parse_error&);
2959 CHECK(json::from_bjdata(vO2, true, false).is_discarded());
2960 }
2961 }
2962
2963 SECTION("writing optimized values")
2964 {
2965 SECTION("integer")
2966 {
2967 SECTION("array of i")
2968 {
2969 json j = {1, -1};
2970 std::vector<uint8_t> expected = {'[', '$', 'i', '#', 'i', 2, 1, 0xff};
2971 CHECK(json::to_bjdata(j, true, true) == expected);
2972 }
2973
2974 SECTION("array of U")
2975 {
2976 json j = {200, 201};
2977 std::vector<uint8_t> expected = {'[', '$', 'U', '#', 'i', 2, 0xC8, 0xC9};
2978 CHECK(json::to_bjdata(j, true, true) == expected);
2979 }
2980
2981 SECTION("array of I")
2982 {
2983 json j = {30000, -30000};
2984 std::vector<uint8_t> expected = {'[', '$', 'I', '#', 'i', 2, 0x30, 0x75, 0xd0, 0x8a};
2985 CHECK(json::to_bjdata(j, true, true) == expected);
2986 }
2987
2988 SECTION("array of u")
2989 {
2990 json j = {50000, 50001};
2991 std::vector<uint8_t> expected = {'[', '$', 'u', '#', 'i', 2, 0x50, 0xC3, 0x51, 0xC3};
2992 CHECK(json::to_bjdata(j, true, true) == expected);
2993 }
2994
2995 SECTION("array of l")
2996 {
2997 json j = {70000, -70000};
2998 std::vector<uint8_t> expected = {'[', '$', 'l', '#', 'i', 2, 0x70, 0x11, 0x01, 0x00, 0x90, 0xEE, 0xFE, 0xFF};
2999 CHECK(json::to_bjdata(j, true, true) == expected);
3000 }
3001
3002 SECTION("array of m")
3003 {
3004 json j = {3147483647, 3147483648};
3005 std::vector<uint8_t> expected = {'[', '$', 'm', '#', 'i', 2, 0xFF, 0xC9, 0x9A, 0xBB, 0x00, 0xCA, 0x9A, 0xBB};
3006 CHECK(json::to_bjdata(j, true, true) == expected);
3007 }
3008
3009 SECTION("array of L")
3010 {
3011 json j = {5000000000, -5000000000};
3012 std::vector<uint8_t> expected = {'[', '$', 'L', '#', 'i', 2, 0x00, 0xF2, 0x05, 0x2A, 0x01, 0x00, 0x00, 0x00, 0x00, 0x0E, 0xFA, 0xD5, 0xFE, 0xFF, 0xFF, 0xFF};
3013 CHECK(json::to_bjdata(j, true, true) == expected);
3014 }
3015 }
3016
3017 SECTION("unsigned integer")
3018 {
3019 SECTION("array of i")
3020 {
3021 json j = {1u, 2u};
3022 std::vector<uint8_t> expected = {'[', '$', 'i', '#', 'i', 2, 1, 2};
3023 std::vector<uint8_t> expected_size = {'[', '#', 'i', 2, 'i', 1, 'i', 2};
3024 CHECK(json::to_bjdata(j, true, true) == expected);
3025 CHECK(json::to_bjdata(j, true) == expected_size);
3026 }
3027
3028 SECTION("array of U")
3029 {
3030 json j = {200u, 201u};
3031 std::vector<uint8_t> expected = {'[', '$', 'U', '#', 'i', 2, 0xC8, 0xC9};
3032 std::vector<uint8_t> expected_size = {'[', '#', 'i', 2, 'U', 0xC8, 'U', 0xC9};
3033 CHECK(json::to_bjdata(j, true, true) == expected);
3034 CHECK(json::to_bjdata(j, true) == expected_size);
3035 }
3036
3037 SECTION("array of I")
3038 {
3039 json j = {30000u, 30001u};
3040 std::vector<uint8_t> expected = {'[', '$', 'I', '#', 'i', 2, 0x30, 0x75, 0x31, 0x75};
3041 std::vector<uint8_t> expected_size = {'[', '#', 'i', 2, 'I', 0x30, 0x75, 'I', 0x31, 0x75};
3042 CHECK(json::to_bjdata(j, true, true) == expected);
3043 CHECK(json::to_bjdata(j, true) == expected_size);
3044 }
3045
3046 SECTION("array of u")
3047 {
3048 json j = {50000u, 50001u};
3049 std::vector<uint8_t> expected = {'[', '$', 'u', '#', 'i', 2, 0x50, 0xC3, 0x51, 0xC3};
3050 std::vector<uint8_t> expected_size = {'[', '#', 'i', 2, 'u', 0x50, 0xC3, 'u', 0x51, 0xC3};
3051 CHECK(json::to_bjdata(j, true, true) == expected);
3052 CHECK(json::to_bjdata(j, true) == expected_size);
3053 }
3054
3055 SECTION("array of l")
3056 {
3057 json j = {70000u, 70001u};
3058 std::vector<uint8_t> expected = {'[', '$', 'l', '#', 'i', 2, 0x70, 0x11, 0x01, 0x00, 0x71, 0x11, 0x01, 0x00};
3059 std::vector<uint8_t> expected_size = {'[', '#', 'i', 2, 'l', 0x70, 0x11, 0x01, 0x00, 'l', 0x71, 0x11, 0x01, 0x00};
3060 CHECK(json::to_bjdata(j, true, true) == expected);
3061 CHECK(json::to_bjdata(j, true) == expected_size);
3062 }
3063
3064 SECTION("array of m")
3065 {
3066 json j = {3147483647u, 3147483648u};
3067 std::vector<uint8_t> expected = {'[', '$', 'm', '#', 'i', 2, 0xFF, 0xC9, 0x9A, 0xBB, 0x00, 0xCA, 0x9A, 0xBB};
3068 std::vector<uint8_t> expected_size = {'[', '#', 'i', 2, 'm', 0xFF, 0xC9, 0x9A, 0xBB, 'm', 0x00, 0xCA, 0x9A, 0xBB};
3069 CHECK(json::to_bjdata(j, true, true) == expected);
3070 CHECK(json::to_bjdata(j, true) == expected_size);
3071 }
3072
3073 SECTION("array of L")
3074 {
3075 json j = {5000000000u, 5000000001u};
3076 std::vector<uint8_t> expected = {'[', '$', 'L', '#', 'i', 2, 0x00, 0xF2, 0x05, 0x2A, 0x01, 0x00, 0x00, 0x00, 0x01, 0xF2, 0x05, 0x2A, 0x01, 0x00, 0x00, 0x00};
3077 std::vector<uint8_t> expected_size = {'[', '#', 'i', 2, 'L', 0x00, 0xF2, 0x05, 0x2A, 0x01, 0x00, 0x00, 0x00, 'L', 0x01, 0xF2, 0x05, 0x2A, 0x01, 0x00, 0x00, 0x00};
3078 CHECK(json::to_bjdata(j, true, true) == expected);
3079 CHECK(json::to_bjdata(j, true) == expected_size);
3080 }
3081
3082 SECTION("array of M")
3083 {
3084 json j = {10223372036854775807ull, 10223372036854775808ull};
3085 std::vector<uint8_t> expected = {'[', '$', 'M', '#', 'i', 2, 0xFF, 0xFF, 0x63, 0xA7, 0xB3, 0xB6, 0xE0, 0x8D, 0x00, 0x00, 0x64, 0xA7, 0xB3, 0xB6, 0xE0, 0x8D};
3086 std::vector<uint8_t> expected_size = {'[', '#', 'i', 2, 'M', 0xFF, 0xFF, 0x63, 0xA7, 0xB3, 0xB6, 0xE0, 0x8D, 'M', 0x00, 0x00, 0x64, 0xA7, 0xB3, 0xB6, 0xE0, 0x8D};
3087 CHECK(json::to_bjdata(j, true, true) == expected);
3088 CHECK(json::to_bjdata(j, true) == expected_size);
3089 }
3090 }
3091 }
3092 }
3093
3094 TEST_CASE("Universal Binary JSON Specification Examples 1")
3095 {
3096 SECTION("Null Value")
3097 {
3098 json j = {{"passcode", nullptr}};
3099 std::vector<uint8_t> v = {'{', 'i', 8, 'p', 'a', 's', 's', 'c', 'o', 'd', 'e', 'Z', '}'};
3100 CHECK(json::to_bjdata(j) == v);
3101 CHECK(json::from_bjdata(v) == j);
3102 }
3103
3104 SECTION("No-Op Value")
3105 {
3106 json j = {"foo", "bar", "baz"};
3107 std::vector<uint8_t> v = {'[', 'S', 'i', 3, 'f', 'o', 'o',
3108 'S', 'i', 3, 'b', 'a', 'r',
3109 'S', 'i', 3, 'b', 'a', 'z', ']'
3110 };
3111 std::vector<uint8_t> v2 = {'[', 'S', 'i', 3, 'f', 'o', 'o', 'N',
3112 'S', 'i', 3, 'b', 'a', 'r', 'N', 'N', 'N',
3113 'S', 'i', 3, 'b', 'a', 'z', 'N', 'N', ']'
3114 };
3115 CHECK(json::to_bjdata(j) == v);
3116 CHECK(json::from_bjdata(v) == j);
3117 CHECK(json::from_bjdata(v2) == j);
3118 }
3119
3120 SECTION("Boolean Types")
3121 {
3122 json j = {{"authorized", true}, {"verified", false}};
3123 std::vector<uint8_t> v = {'{', 'i', 10, 'a', 'u', 't', 'h', 'o', 'r', 'i', 'z', 'e', 'd', 'T',
3124 'i', 8, 'v', 'e', 'r', 'i', 'f', 'i', 'e', 'd', 'F', '}'
3125 };
3126 CHECK(json::to_bjdata(j) == v);
3127 CHECK(json::from_bjdata(v) == j);
3128 }
3129
3130 SECTION("Numeric Types")
3131 {
3132 json j =
3133 {
3134 {"int8", 16},
3135 {"uint8", 255},
3136 {"int16", 32767},
3137 {"uint16", 42767},
3138 {"int32", 2147483647},
3139 {"uint32", 3147483647},
3140 {"int64", 9223372036854775807},
3141 {"uint64", 10223372036854775807ull},
3142 {"float64", 113243.7863123}
3143 };
3144 std::vector<uint8_t> v = {'{',
3145 'i', 7, 'f', 'l', 'o', 'a', 't', '6', '4', 'D', 0xcf, 0x34, 0xbc, 0x94, 0xbc, 0xa5, 0xfb, 0x40,
3146 'i', 5, 'i', 'n', 't', '1', '6', 'I', 0xff, 0x7f,
3147 'i', 5, 'i', 'n', 't', '3', '2', 'l', 0xff, 0xff, 0xff, 0x7f,
3148 'i', 5, 'i', 'n', 't', '6', '4', 'L', 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f,
3149 'i', 4, 'i', 'n', 't', '8', 'i', 16,
3150 'i', 6, 'u', 'i', 'n', 't', '1', '6', 'u', 0x0F, 0xA7,
3151 'i', 6, 'u', 'i', 'n', 't', '3', '2', 'm', 0xFF, 0xC9, 0x9A, 0xBB,
3152 'i', 6, 'u', 'i', 'n', 't', '6', '4', 'M', 0xFF, 0xFF, 0x63, 0xA7, 0xB3, 0xB6, 0xE0, 0x8D,
3153 'i', 5, 'u', 'i', 'n', 't', '8', 'U', 0xff,
3154 '}'
3155 };
3156 CHECK(json::to_bjdata(j) == v);
3157 CHECK(json::from_bjdata(v) == j);
3158 }
3159
3160 SECTION("Char Type")
3161 {
3162 json j = {{"rolecode", "a"}, {"delim", ";"}};
3163 std::vector<uint8_t> v = {'{', 'i', 5, 'd', 'e', 'l', 'i', 'm', 'C', ';', 'i', 8, 'r', 'o', 'l', 'e', 'c', 'o', 'd', 'e', 'C', 'a', '}'};
3164 //CHECK(json::to_bjdata(j) == v);
3165 CHECK(json::from_bjdata(v) == j);
3166 }
3167
3168 SECTION("String Type")
3169 {
3170 SECTION("English")
3171 {
3172 json j = "hello";
3173 std::vector<uint8_t> v = {'S', 'i', 5, 'h', 'e', 'l', 'l', 'o'};
3174 CHECK(json::to_bjdata(j) == v);
3175 CHECK(json::from_bjdata(v) == j);
3176 }
3177
3178 SECTION("Russian")
3179 {
3180 json j = "привет";
3181 std::vector<uint8_t> v = {'S', 'i', 12, 0xD0, 0xBF, 0xD1, 0x80, 0xD0, 0xB8, 0xD0, 0xB2, 0xD0, 0xB5, 0xD1, 0x82};
3182 CHECK(json::to_bjdata(j) == v);
3183 CHECK(json::from_bjdata(v) == j);
3184 }
3185
3186 SECTION("Russian")
3187 {
3188 json j = "مرحبا";
3189 std::vector<uint8_t> v = {'S', 'i', 10, 0xD9, 0x85, 0xD8, 0xB1, 0xD8, 0xAD, 0xD8, 0xA8, 0xD8, 0xA7};
3190 CHECK(json::to_bjdata(j) == v);
3191 CHECK(json::from_bjdata(v) == j);
3192 }
3193 }
3194
3195 SECTION("Array Type")
3196 {
3197 SECTION("size=false type=false")
3198 {
3199 // note the float has been replaced by a double
3200 json j = {nullptr, true, false, 4782345193, 153.132, "ham"};
3201 std::vector<uint8_t> v = {'[', 'Z', 'T', 'F', 'L', 0xE9, 0xCB, 0x0C, 0x1D, 0x01, 0x00, 0x00, 0x00, 'D', 0x4e, 0x62, 0x10, 0x58, 0x39, 0x24, 0x63, 0x40, 'S', 'i', 3, 'h', 'a', 'm', ']'};
3202 CHECK(json::to_bjdata(j) == v);
3203 CHECK(json::from_bjdata(v) == j);
3204 }
3205
3206 SECTION("size=true type=false")
3207 {
3208 // note the float has been replaced by a double
3209 json j = {nullptr, true, false, 4782345193, 153.132, "ham"};
3210 std::vector<uint8_t> v = {'[', '#', 'i', 6, 'Z', 'T', 'F', 'L', 0xE9, 0xCB, 0x0C, 0x1D, 0x01, 0x00, 0x00, 0x00, 'D', 0x4e, 0x62, 0x10, 0x58, 0x39, 0x24, 0x63, 0x40, 'S', 'i', 3, 'h', 'a', 'm'};
3211 CHECK(json::to_bjdata(j, true) == v);
3212 CHECK(json::from_bjdata(v) == j);
3213 }
3214
3215 SECTION("size=true type=true")
3216 {
3217 // note the float has been replaced by a double
3218 json j = {nullptr, true, false, 4782345193, 153.132, "ham"};
3219 std::vector<uint8_t> v = {'[', '#', 'i', 6, 'Z', 'T', 'F', 'L', 0xE9, 0xCB, 0x0C, 0x1D, 0x01, 0x00, 0x00, 0x00, 'D', 0x4e, 0x62, 0x10, 0x58, 0x39, 0x24, 0x63, 0x40, 'S', 'i', 3, 'h', 'a', 'm'};
3220 CHECK(json::to_bjdata(j, true, true) == v);
3221 CHECK(json::from_bjdata(v) == j);
3222 }
3223 }
3224
3225 SECTION("Object Type")
3226 {
3227 SECTION("size=false type=false")
3228 {
3229 json j =
3230 {
3231 {
3232 "post", {
3233 {"id", 1137},
3234 {"author", "rkalla"},
3235 {"timestamp", 1364482090592},
3236 {"body", "I totally agree!"}
3237 }
3238 }
3239 };
3240 std::vector<uint8_t> v = {'{', 'i', 4, 'p', 'o', 's', 't', '{',
3241 'i', 6, 'a', 'u', 't', 'h', 'o', 'r', 'S', 'i', 6, 'r', 'k', 'a', 'l', 'l', 'a',
3242 'i', 4, 'b', 'o', 'd', 'y', 'S', 'i', 16, 'I', ' ', 't', 'o', 't', 'a', 'l', 'l', 'y', ' ', 'a', 'g', 'r', 'e', 'e', '!',
3243 'i', 2, 'i', 'd', 'I', 0x71, 0x04,
3244 'i', 9, 't', 'i', 'm', 'e', 's', 't', 'a', 'm', 'p', 'L', 0x60, 0x66, 0x78, 0xB1, 0x3D, 0x01, 0x00, 0x00,
3245 '}', '}'
3246 };
3247 CHECK(json::to_bjdata(j) == v);
3248 CHECK(json::from_bjdata(v) == j);
3249 }
3250
3251 SECTION("size=true type=false")
3252 {
3253 json j =
3254 {
3255 {
3256 "post", {
3257 {"id", 1137},
3258 {"author", "rkalla"},
3259 {"timestamp", 1364482090592},
3260 {"body", "I totally agree!"}
3261 }
3262 }
3263 };
3264 std::vector<uint8_t> v = {'{', '#', 'i', 1, 'i', 4, 'p', 'o', 's', 't', '{', '#', 'i', 4,
3265 'i', 6, 'a', 'u', 't', 'h', 'o', 'r', 'S', 'i', 6, 'r', 'k', 'a', 'l', 'l', 'a',
3266 'i', 4, 'b', 'o', 'd', 'y', 'S', 'i', 16, 'I', ' ', 't', 'o', 't', 'a', 'l', 'l', 'y', ' ', 'a', 'g', 'r', 'e', 'e', '!',
3267 'i', 2, 'i', 'd', 'I', 0x71, 0x04,
3268 'i', 9, 't', 'i', 'm', 'e', 's', 't', 'a', 'm', 'p', 'L', 0x60, 0x66, 0x78, 0xB1, 0x3D, 0x01, 0x00, 0x00,
3269 };
3270 CHECK(json::to_bjdata(j, true) == v);
3271 CHECK(json::from_bjdata(v) == j);
3272 }
3273
3274 SECTION("size=true type=true")
3275 {
3276 json j =
3277 {
3278 {
3279 "post", {
3280 {"id", 1137},
3281 {"author", "rkalla"},
3282 {"timestamp", 1364482090592},
3283 {"body", "I totally agree!"}
3284 }
3285 }
3286 };
3287 std::vector<uint8_t> v = {'{', '#', 'i', 1, 'i', 4, 'p', 'o', 's', 't', '{', '#', 'i', 4,
3288 'i', 6, 'a', 'u', 't', 'h', 'o', 'r', 'S', 'i', 6, 'r', 'k', 'a', 'l', 'l', 'a',
3289 'i', 4, 'b', 'o', 'd', 'y', 'S', 'i', 16, 'I', ' ', 't', 'o', 't', 'a', 'l', 'l', 'y', ' ', 'a', 'g', 'r', 'e', 'e', '!',
3290 'i', 2, 'i', 'd', 'I', 0x71, 0x04,
3291 'i', 9, 't', 'i', 'm', 'e', 's', 't', 'a', 'm', 'p', 'L', 0x60, 0x66, 0x78, 0xB1, 0x3D, 0x01, 0x00, 0x00,
3292 };
3293 CHECK(json::to_bjdata(j, true, true) == v);
3294 CHECK(json::from_bjdata(v) == j);
3295 }
3296 }
3297
3298 SECTION("Optimized Format")
3299 {
3300 SECTION("Array Example")
3301 {
3302 SECTION("No Optimization")
3303 {
3304 // note the floats have been replaced by doubles
3305 json j = {29.97, 31.13, 67.0, 2.113, 23.888};
3306 std::vector<uint8_t> v = {'[',
3307 'D', 0xb8, 0x1e, 0x85, 0xeb, 0x51, 0xf8, 0x3d, 0x40,
3308 'D', 0xe1, 0x7a, 0x14, 0xae, 0x47, 0x21, 0x3f, 0x40,
3309 'D', 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x50, 0x40,
3310 'D', 0x81, 0x95, 0x43, 0x8b, 0x6c, 0xe7, 0x00, 0x40,
3311 'D', 0x17, 0xd9, 0xce, 0xf7, 0x53, 0xe3, 0x37, 0x40,
3312 ']'
3313 };
3314 CHECK(json::to_bjdata(j) == v);
3315 CHECK(json::from_bjdata(v) == j);
3316 }
3317
3318 SECTION("Optimized with count")
3319 {
3320 // note the floats have been replaced by doubles
3321 json j = {29.97, 31.13, 67.0, 2.113, 23.888};
3322 std::vector<uint8_t> v = {'[', '#', 'i', 5,
3323 'D', 0xb8, 0x1e, 0x85, 0xeb, 0x51, 0xf8, 0x3d, 0x40,
3324 'D', 0xe1, 0x7a, 0x14, 0xae, 0x47, 0x21, 0x3f, 0x40,
3325 'D', 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x50, 0x40,
3326 'D', 0x81, 0x95, 0x43, 0x8b, 0x6c, 0xe7, 0x00, 0x40,
3327 'D', 0x17, 0xd9, 0xce, 0xf7, 0x53, 0xe3, 0x37, 0x40,
3328 };
3329 CHECK(json::to_bjdata(j, true) == v);
3330 CHECK(json::from_bjdata(v) == j);
3331 }
3332
3333 SECTION("Optimized with type & count")
3334 {
3335 // note the floats have been replaced by doubles
3336 json j = {29.97, 31.13, 67.0, 2.113, 23.888};
3337 std::vector<uint8_t> v = {'[', '$', 'D', '#', 'i', 5,
3338 0xb8, 0x1e, 0x85, 0xeb, 0x51, 0xf8, 0x3d, 0x40,
3339 0xe1, 0x7a, 0x14, 0xae, 0x47, 0x21, 0x3f, 0x40,
3340 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x50, 0x40,
3341 0x81, 0x95, 0x43, 0x8b, 0x6c, 0xe7, 0x00, 0x40,
3342 0x17, 0xd9, 0xce, 0xf7, 0x53, 0xe3, 0x37, 0x40,
3343 };
3344 CHECK(json::to_bjdata(j, true, true) == v);
3345 CHECK(json::from_bjdata(v) == j);
3346 }
3347 }
3348
3349 SECTION("Object Example")
3350 {
3351 SECTION("No Optimization")
3352 {
3353 // note the floats have been replaced by doubles
3354 json j = { {"lat", 29.976}, {"long", 31.131}, {"alt", 67.0} };
3355 std::vector<uint8_t> v = {'{',
3356 'i', 3, 'a', 'l', 't', 'D', 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x50, 0x40,
3357 'i', 3, 'l', 'a', 't', 'D', 0x60, 0xe5, 0xd0, 0x22, 0xdb, 0xf9, 0x3d, 0x40,
3358 'i', 4, 'l', 'o', 'n', 'g', 'D', 0xa8, 0xc6, 0x4b, 0x37, 0x89, 0x21, 0x3f, 0x40,
3359 '}'
3360 };
3361 CHECK(json::to_bjdata(j) == v);
3362 CHECK(json::from_bjdata(v) == j);
3363 }
3364
3365 SECTION("Optimized with count")
3366 {
3367 // note the floats have been replaced by doubles
3368 json j = { {"lat", 29.976}, {"long", 31.131}, {"alt", 67.0} };
3369 std::vector<uint8_t> v = {'{', '#', 'i', 3,
3370 'i', 3, 'a', 'l', 't', 'D', 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x50, 0x40,
3371 'i', 3, 'l', 'a', 't', 'D', 0x60, 0xe5, 0xd0, 0x22, 0xdb, 0xf9, 0x3d, 0x40,
3372 'i', 4, 'l', 'o', 'n', 'g', 'D', 0xa8, 0xc6, 0x4b, 0x37, 0x89, 0x21, 0x3f, 0x40,
3373 };
3374 CHECK(json::to_bjdata(j, true) == v);
3375 CHECK(json::from_bjdata(v) == j);
3376 }
3377
3378 SECTION("Optimized with type & count")
3379 {
3380 // note the floats have been replaced by doubles
3381 json j = { {"lat", 29.976}, {"long", 31.131}, {"alt", 67.0} };
3382 std::vector<uint8_t> v = {'{', '$', 'D', '#', 'i', 3,
3383 'i', 3, 'a', 'l', 't', 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x50, 0x40,
3384 'i', 3, 'l', 'a', 't', 0x60, 0xe5, 0xd0, 0x22, 0xdb, 0xf9, 0x3d, 0x40,
3385 'i', 4, 'l', 'o', 'n', 'g', 0xa8, 0xc6, 0x4b, 0x37, 0x89, 0x21, 0x3f, 0x40,
3386 };
3387 CHECK(json::to_bjdata(j, true, true) == v);
3388 CHECK(json::from_bjdata(v) == j);
3389 }
3390 }
3391
3392 SECTION("Special Cases (Null, No-Op and Boolean)")
3393 {
3394 SECTION("Array")
3395 {
3396 json _;
3397 std::vector<uint8_t> v = {'[', '$', 'N', '#', 'I', 0x00, 0x02};
3398 CHECK_THROWS_WITH_AS(_ = json::from_bjdata(v), "[json.exception.parse_error.112] parse error at byte 3: syntax error while parsing BJData type: marker 0x4E is not a permitted optimized array type", json::parse_error&);
3399 CHECK(json::from_bjdata(v, true, false).is_discarded());
3400 }
3401
3402 SECTION("Object")
3403 {
3404 json _;
3405 std::vector<uint8_t> v = {'{', '$', 'Z', '#', 'i', 3, 'i', 4, 'n', 'a', 'm', 'e', 'i', 8, 'p', 'a', 's', 's', 'w', 'o', 'r', 'd', 'i', 5, 'e', 'm', 'a', 'i', 'l'};
3406 CHECK_THROWS_WITH_AS(_ = json::from_bjdata(v), "[json.exception.parse_error.112] parse error at byte 3: syntax error while parsing BJData type: marker 0x5A is not a permitted optimized array type", json::parse_error&);
3407 CHECK(json::from_bjdata(v, true, false).is_discarded());
3408 }
3409 }
3410 }
3411 }
3412
3413 #if !defined(JSON_NOEXCEPTION)
3414 TEST_CASE("all BJData first bytes")
3415 {
3416 // these bytes will fail immediately with exception parse_error.112
3417 std::set<uint8_t> supported =
3418 {
3419 'T', 'F', 'Z', 'U', 'i', 'I', 'l', 'L', 'd', 'D', 'C', 'S', '[', '{', 'N', 'H', 'u', 'm', 'M', 'h'
3420 };
3421
3422 for (auto i = 0; i < 256; ++i)
3423 {
3424 const auto byte = static_cast<uint8_t>(i);
CAPTURE(byte)3425 CAPTURE(byte)
3426
3427 try
3428 {
3429 auto res = json::from_bjdata(std::vector<uint8_t>(1, byte));
3430 }
3431 catch (const json::parse_error& e)
3432 {
3433 // check that parse_error.112 is only thrown if the
3434 // first byte is not in the supported set
3435 INFO_WITH_TEMP(e.what());
3436 if (supported.find(byte) == supported.end())
3437 {
3438 CHECK(e.id == 112);
3439 }
3440 else
3441 {
3442 CHECK(e.id != 112);
3443 }
3444 }
3445 }
3446 }
3447 #endif
3448
skip()3449 TEST_CASE("BJData roundtrips" * doctest::skip())
3450 {
3451 SECTION("input from self-generated BJData files")
3452 {
3453 for (std::string filename :
3454 {
3455 TEST_DATA_DIRECTORY "/json_nlohmann_tests/all_unicode.json",
3456 TEST_DATA_DIRECTORY "/json.org/1.json",
3457 TEST_DATA_DIRECTORY "/json.org/2.json",
3458 TEST_DATA_DIRECTORY "/json.org/3.json",
3459 TEST_DATA_DIRECTORY "/json.org/4.json",
3460 TEST_DATA_DIRECTORY "/json.org/5.json",
3461 TEST_DATA_DIRECTORY "/json_roundtrip/roundtrip01.json",
3462 TEST_DATA_DIRECTORY "/json_roundtrip/roundtrip02.json",
3463 TEST_DATA_DIRECTORY "/json_roundtrip/roundtrip03.json",
3464 TEST_DATA_DIRECTORY "/json_roundtrip/roundtrip04.json",
3465 TEST_DATA_DIRECTORY "/json_roundtrip/roundtrip05.json",
3466 TEST_DATA_DIRECTORY "/json_roundtrip/roundtrip06.json",
3467 TEST_DATA_DIRECTORY "/json_roundtrip/roundtrip07.json",
3468 TEST_DATA_DIRECTORY "/json_roundtrip/roundtrip08.json",
3469 TEST_DATA_DIRECTORY "/json_roundtrip/roundtrip09.json",
3470 TEST_DATA_DIRECTORY "/json_roundtrip/roundtrip10.json",
3471 TEST_DATA_DIRECTORY "/json_roundtrip/roundtrip11.json",
3472 TEST_DATA_DIRECTORY "/json_roundtrip/roundtrip12.json",
3473 TEST_DATA_DIRECTORY "/json_roundtrip/roundtrip13.json",
3474 TEST_DATA_DIRECTORY "/json_roundtrip/roundtrip14.json",
3475 TEST_DATA_DIRECTORY "/json_roundtrip/roundtrip15.json",
3476 TEST_DATA_DIRECTORY "/json_roundtrip/roundtrip16.json",
3477 TEST_DATA_DIRECTORY "/json_roundtrip/roundtrip17.json",
3478 TEST_DATA_DIRECTORY "/json_roundtrip/roundtrip18.json",
3479 TEST_DATA_DIRECTORY "/json_roundtrip/roundtrip19.json",
3480 TEST_DATA_DIRECTORY "/json_roundtrip/roundtrip20.json",
3481 TEST_DATA_DIRECTORY "/json_roundtrip/roundtrip21.json",
3482 TEST_DATA_DIRECTORY "/json_roundtrip/roundtrip22.json",
3483 TEST_DATA_DIRECTORY "/json_roundtrip/roundtrip23.json",
3484 TEST_DATA_DIRECTORY "/json_roundtrip/roundtrip24.json",
3485 TEST_DATA_DIRECTORY "/json_roundtrip/roundtrip25.json",
3486 TEST_DATA_DIRECTORY "/json_roundtrip/roundtrip26.json",
3487 TEST_DATA_DIRECTORY "/json_roundtrip/roundtrip27.json",
3488 TEST_DATA_DIRECTORY "/json_roundtrip/roundtrip28.json",
3489 TEST_DATA_DIRECTORY "/json_roundtrip/roundtrip29.json",
3490 TEST_DATA_DIRECTORY "/json_roundtrip/roundtrip30.json",
3491 TEST_DATA_DIRECTORY "/json_roundtrip/roundtrip31.json",
3492 TEST_DATA_DIRECTORY "/json_roundtrip/roundtrip32.json",
3493 TEST_DATA_DIRECTORY "/json_testsuite/sample.json",
3494 TEST_DATA_DIRECTORY "/json_tests/pass1.json",
3495 TEST_DATA_DIRECTORY "/json_tests/pass2.json",
3496 TEST_DATA_DIRECTORY "/json_tests/pass3.json"
3497 })
3498 {
3499 CAPTURE(filename)
3500
3501 {
3502 INFO_WITH_TEMP(filename + ": std::vector<uint8_t>");
3503 // parse JSON file
3504 std::ifstream f_json(filename);
3505 json j1 = json::parse(f_json);
3506
3507 // parse BJData file
3508 auto packed = utils::read_binary_file(filename + ".bjdata");
3509 json j2;
3510 CHECK_NOTHROW(j2 = json::from_bjdata(packed));
3511
3512 // compare parsed JSON values
3513 CHECK(j1 == j2);
3514 }
3515
3516 {
3517 INFO_WITH_TEMP(filename + ": std::ifstream");
3518 // parse JSON file
3519 std::ifstream f_json(filename);
3520 json j1 = json::parse(f_json);
3521
3522 // parse BJData file
3523 std::ifstream f_bjdata(filename + ".bjdata", std::ios::binary);
3524 json j2;
3525 CHECK_NOTHROW(j2 = json::from_bjdata(f_bjdata));
3526
3527 // compare parsed JSON values
3528 CHECK(j1 == j2);
3529 }
3530
3531 {
3532 INFO_WITH_TEMP(filename + ": output to output adapters");
3533 // parse JSON file
3534 std::ifstream f_json(filename);
3535 json j1 = json::parse(f_json);
3536
3537 // parse BJData file
3538 auto packed = utils::read_binary_file(filename + ".bjdata");
3539
3540 {
3541 INFO_WITH_TEMP(filename + ": output adapters: std::vector<uint8_t>");
3542 std::vector<uint8_t> vec;
3543 json::to_bjdata(j1, vec);
3544 CHECK(vec == packed);
3545 }
3546 }
3547 }
3548 }
3549 }
3550