1 #pragma once 2 3 #include <algorithm> // reverse 4 #include <array> // array 5 #include <cstdint> // uint8_t, uint16_t, uint32_t, uint64_t 6 #include <cstring> // memcpy 7 #include <limits> // numeric_limits 8 #include <string> // string 9 10 #include <nlohmann/detail/input/binary_reader.hpp> 11 #include <nlohmann/detail/output/output_adapters.hpp> 12 13 namespace nlohmann 14 { 15 namespace detail 16 { 17 /////////////////// 18 // binary writer // 19 /////////////////// 20 21 /*! 22 @brief serialization to CBOR and MessagePack values 23 */ 24 template<typename BasicJsonType, typename CharType> 25 class binary_writer 26 { 27 using string_t = typename BasicJsonType::string_t; 28 29 public: 30 /*! 31 @brief create a binary writer 32 33 @param[in] adapter output adapter to write to 34 */ binary_writer(output_adapter_t<CharType> adapter)35 explicit binary_writer(output_adapter_t<CharType> adapter) : oa(adapter) 36 { 37 assert(oa); 38 } 39 40 /*! 41 @param[in] j JSON value to serialize 42 @pre j.type() == value_t::object 43 */ write_bson(const BasicJsonType & j)44 void write_bson(const BasicJsonType& j) 45 { 46 switch (j.type()) 47 { 48 case value_t::object: 49 { 50 write_bson_object(*j.m_value.object); 51 break; 52 } 53 54 default: 55 { 56 JSON_THROW(type_error::create(317, "to serialize to BSON, top-level type must be object, but is " + std::string(j.type_name()))); 57 } 58 } 59 } 60 61 /*! 62 @param[in] j JSON value to serialize 63 */ write_cbor(const BasicJsonType & j)64 void write_cbor(const BasicJsonType& j) 65 { 66 switch (j.type()) 67 { 68 case value_t::null: 69 { 70 oa->write_character(to_char_type(0xF6)); 71 break; 72 } 73 74 case value_t::boolean: 75 { 76 oa->write_character(j.m_value.boolean 77 ? to_char_type(0xF5) 78 : to_char_type(0xF4)); 79 break; 80 } 81 82 case value_t::number_integer: 83 { 84 if (j.m_value.number_integer >= 0) 85 { 86 // CBOR does not differentiate between positive signed 87 // integers and unsigned integers. Therefore, we used the 88 // code from the value_t::number_unsigned case here. 89 if (j.m_value.number_integer <= 0x17) 90 { 91 write_number(static_cast<std::uint8_t>(j.m_value.number_integer)); 92 } 93 else if (j.m_value.number_integer <= (std::numeric_limits<std::uint8_t>::max)()) 94 { 95 oa->write_character(to_char_type(0x18)); 96 write_number(static_cast<std::uint8_t>(j.m_value.number_integer)); 97 } 98 else if (j.m_value.number_integer <= (std::numeric_limits<std::uint16_t>::max)()) 99 { 100 oa->write_character(to_char_type(0x19)); 101 write_number(static_cast<std::uint16_t>(j.m_value.number_integer)); 102 } 103 else if (j.m_value.number_integer <= (std::numeric_limits<std::uint32_t>::max)()) 104 { 105 oa->write_character(to_char_type(0x1A)); 106 write_number(static_cast<std::uint32_t>(j.m_value.number_integer)); 107 } 108 else 109 { 110 oa->write_character(to_char_type(0x1B)); 111 write_number(static_cast<std::uint64_t>(j.m_value.number_integer)); 112 } 113 } 114 else 115 { 116 // The conversions below encode the sign in the first 117 // byte, and the value is converted to a positive number. 118 const auto positive_number = -1 - j.m_value.number_integer; 119 if (j.m_value.number_integer >= -24) 120 { 121 write_number(static_cast<std::uint8_t>(0x20 + positive_number)); 122 } 123 else if (positive_number <= (std::numeric_limits<std::uint8_t>::max)()) 124 { 125 oa->write_character(to_char_type(0x38)); 126 write_number(static_cast<std::uint8_t>(positive_number)); 127 } 128 else if (positive_number <= (std::numeric_limits<std::uint16_t>::max)()) 129 { 130 oa->write_character(to_char_type(0x39)); 131 write_number(static_cast<std::uint16_t>(positive_number)); 132 } 133 else if (positive_number <= (std::numeric_limits<std::uint32_t>::max)()) 134 { 135 oa->write_character(to_char_type(0x3A)); 136 write_number(static_cast<std::uint32_t>(positive_number)); 137 } 138 else 139 { 140 oa->write_character(to_char_type(0x3B)); 141 write_number(static_cast<std::uint64_t>(positive_number)); 142 } 143 } 144 break; 145 } 146 147 case value_t::number_unsigned: 148 { 149 if (j.m_value.number_unsigned <= 0x17) 150 { 151 write_number(static_cast<std::uint8_t>(j.m_value.number_unsigned)); 152 } 153 else if (j.m_value.number_unsigned <= (std::numeric_limits<std::uint8_t>::max)()) 154 { 155 oa->write_character(to_char_type(0x18)); 156 write_number(static_cast<std::uint8_t>(j.m_value.number_unsigned)); 157 } 158 else if (j.m_value.number_unsigned <= (std::numeric_limits<std::uint16_t>::max)()) 159 { 160 oa->write_character(to_char_type(0x19)); 161 write_number(static_cast<std::uint16_t>(j.m_value.number_unsigned)); 162 } 163 else if (j.m_value.number_unsigned <= (std::numeric_limits<std::uint32_t>::max)()) 164 { 165 oa->write_character(to_char_type(0x1A)); 166 write_number(static_cast<std::uint32_t>(j.m_value.number_unsigned)); 167 } 168 else 169 { 170 oa->write_character(to_char_type(0x1B)); 171 write_number(static_cast<std::uint64_t>(j.m_value.number_unsigned)); 172 } 173 break; 174 } 175 176 case value_t::number_float: 177 { 178 oa->write_character(get_cbor_float_prefix(j.m_value.number_float)); 179 write_number(j.m_value.number_float); 180 break; 181 } 182 183 case value_t::string: 184 { 185 // step 1: write control byte and the string length 186 const auto N = j.m_value.string->size(); 187 if (N <= 0x17) 188 { 189 write_number(static_cast<std::uint8_t>(0x60 + N)); 190 } 191 else if (N <= (std::numeric_limits<std::uint8_t>::max)()) 192 { 193 oa->write_character(to_char_type(0x78)); 194 write_number(static_cast<std::uint8_t>(N)); 195 } 196 else if (N <= (std::numeric_limits<std::uint16_t>::max)()) 197 { 198 oa->write_character(to_char_type(0x79)); 199 write_number(static_cast<std::uint16_t>(N)); 200 } 201 else if (N <= (std::numeric_limits<std::uint32_t>::max)()) 202 { 203 oa->write_character(to_char_type(0x7A)); 204 write_number(static_cast<std::uint32_t>(N)); 205 } 206 // LCOV_EXCL_START 207 else if (N <= (std::numeric_limits<std::uint64_t>::max)()) 208 { 209 oa->write_character(to_char_type(0x7B)); 210 write_number(static_cast<std::uint64_t>(N)); 211 } 212 // LCOV_EXCL_STOP 213 214 // step 2: write the string 215 oa->write_characters( 216 reinterpret_cast<const CharType*>(j.m_value.string->c_str()), 217 j.m_value.string->size()); 218 break; 219 } 220 221 case value_t::array: 222 { 223 // step 1: write control byte and the array size 224 const auto N = j.m_value.array->size(); 225 if (N <= 0x17) 226 { 227 write_number(static_cast<std::uint8_t>(0x80 + N)); 228 } 229 else if (N <= (std::numeric_limits<std::uint8_t>::max)()) 230 { 231 oa->write_character(to_char_type(0x98)); 232 write_number(static_cast<std::uint8_t>(N)); 233 } 234 else if (N <= (std::numeric_limits<std::uint16_t>::max)()) 235 { 236 oa->write_character(to_char_type(0x99)); 237 write_number(static_cast<std::uint16_t>(N)); 238 } 239 else if (N <= (std::numeric_limits<std::uint32_t>::max)()) 240 { 241 oa->write_character(to_char_type(0x9A)); 242 write_number(static_cast<std::uint32_t>(N)); 243 } 244 // LCOV_EXCL_START 245 else if (N <= (std::numeric_limits<std::uint64_t>::max)()) 246 { 247 oa->write_character(to_char_type(0x9B)); 248 write_number(static_cast<std::uint64_t>(N)); 249 } 250 // LCOV_EXCL_STOP 251 252 // step 2: write each element 253 for (const auto& el : *j.m_value.array) 254 { 255 write_cbor(el); 256 } 257 break; 258 } 259 260 case value_t::object: 261 { 262 // step 1: write control byte and the object size 263 const auto N = j.m_value.object->size(); 264 if (N <= 0x17) 265 { 266 write_number(static_cast<std::uint8_t>(0xA0 + N)); 267 } 268 else if (N <= (std::numeric_limits<std::uint8_t>::max)()) 269 { 270 oa->write_character(to_char_type(0xB8)); 271 write_number(static_cast<std::uint8_t>(N)); 272 } 273 else if (N <= (std::numeric_limits<std::uint16_t>::max)()) 274 { 275 oa->write_character(to_char_type(0xB9)); 276 write_number(static_cast<std::uint16_t>(N)); 277 } 278 else if (N <= (std::numeric_limits<std::uint32_t>::max)()) 279 { 280 oa->write_character(to_char_type(0xBA)); 281 write_number(static_cast<std::uint32_t>(N)); 282 } 283 // LCOV_EXCL_START 284 else if (N <= (std::numeric_limits<std::uint64_t>::max)()) 285 { 286 oa->write_character(to_char_type(0xBB)); 287 write_number(static_cast<std::uint64_t>(N)); 288 } 289 // LCOV_EXCL_STOP 290 291 // step 2: write each element 292 for (const auto& el : *j.m_value.object) 293 { 294 write_cbor(el.first); 295 write_cbor(el.second); 296 } 297 break; 298 } 299 300 default: 301 break; 302 } 303 } 304 305 /*! 306 @param[in] j JSON value to serialize 307 */ write_msgpack(const BasicJsonType & j)308 void write_msgpack(const BasicJsonType& j) 309 { 310 switch (j.type()) 311 { 312 case value_t::null: // nil 313 { 314 oa->write_character(to_char_type(0xC0)); 315 break; 316 } 317 318 case value_t::boolean: // true and false 319 { 320 oa->write_character(j.m_value.boolean 321 ? to_char_type(0xC3) 322 : to_char_type(0xC2)); 323 break; 324 } 325 326 case value_t::number_integer: 327 { 328 if (j.m_value.number_integer >= 0) 329 { 330 // MessagePack does not differentiate between positive 331 // signed integers and unsigned integers. Therefore, we used 332 // the code from the value_t::number_unsigned case here. 333 if (j.m_value.number_unsigned < 128) 334 { 335 // positive fixnum 336 write_number(static_cast<std::uint8_t>(j.m_value.number_integer)); 337 } 338 else if (j.m_value.number_unsigned <= (std::numeric_limits<std::uint8_t>::max)()) 339 { 340 // uint 8 341 oa->write_character(to_char_type(0xCC)); 342 write_number(static_cast<std::uint8_t>(j.m_value.number_integer)); 343 } 344 else if (j.m_value.number_unsigned <= (std::numeric_limits<std::uint16_t>::max)()) 345 { 346 // uint 16 347 oa->write_character(to_char_type(0xCD)); 348 write_number(static_cast<std::uint16_t>(j.m_value.number_integer)); 349 } 350 else if (j.m_value.number_unsigned <= (std::numeric_limits<std::uint32_t>::max)()) 351 { 352 // uint 32 353 oa->write_character(to_char_type(0xCE)); 354 write_number(static_cast<std::uint32_t>(j.m_value.number_integer)); 355 } 356 else if (j.m_value.number_unsigned <= (std::numeric_limits<std::uint64_t>::max)()) 357 { 358 // uint 64 359 oa->write_character(to_char_type(0xCF)); 360 write_number(static_cast<std::uint64_t>(j.m_value.number_integer)); 361 } 362 } 363 else 364 { 365 if (j.m_value.number_integer >= -32) 366 { 367 // negative fixnum 368 write_number(static_cast<std::int8_t>(j.m_value.number_integer)); 369 } 370 else if (j.m_value.number_integer >= (std::numeric_limits<std::int8_t>::min)() and 371 j.m_value.number_integer <= (std::numeric_limits<std::int8_t>::max)()) 372 { 373 // int 8 374 oa->write_character(to_char_type(0xD0)); 375 write_number(static_cast<std::int8_t>(j.m_value.number_integer)); 376 } 377 else if (j.m_value.number_integer >= (std::numeric_limits<std::int16_t>::min)() and 378 j.m_value.number_integer <= (std::numeric_limits<std::int16_t>::max)()) 379 { 380 // int 16 381 oa->write_character(to_char_type(0xD1)); 382 write_number(static_cast<std::int16_t>(j.m_value.number_integer)); 383 } 384 else if (j.m_value.number_integer >= (std::numeric_limits<std::int32_t>::min)() and 385 j.m_value.number_integer <= (std::numeric_limits<std::int32_t>::max)()) 386 { 387 // int 32 388 oa->write_character(to_char_type(0xD2)); 389 write_number(static_cast<std::int32_t>(j.m_value.number_integer)); 390 } 391 else if (j.m_value.number_integer >= (std::numeric_limits<std::int64_t>::min)() and 392 j.m_value.number_integer <= (std::numeric_limits<std::int64_t>::max)()) 393 { 394 // int 64 395 oa->write_character(to_char_type(0xD3)); 396 write_number(static_cast<std::int64_t>(j.m_value.number_integer)); 397 } 398 } 399 break; 400 } 401 402 case value_t::number_unsigned: 403 { 404 if (j.m_value.number_unsigned < 128) 405 { 406 // positive fixnum 407 write_number(static_cast<std::uint8_t>(j.m_value.number_integer)); 408 } 409 else if (j.m_value.number_unsigned <= (std::numeric_limits<std::uint8_t>::max)()) 410 { 411 // uint 8 412 oa->write_character(to_char_type(0xCC)); 413 write_number(static_cast<std::uint8_t>(j.m_value.number_integer)); 414 } 415 else if (j.m_value.number_unsigned <= (std::numeric_limits<std::uint16_t>::max)()) 416 { 417 // uint 16 418 oa->write_character(to_char_type(0xCD)); 419 write_number(static_cast<std::uint16_t>(j.m_value.number_integer)); 420 } 421 else if (j.m_value.number_unsigned <= (std::numeric_limits<std::uint32_t>::max)()) 422 { 423 // uint 32 424 oa->write_character(to_char_type(0xCE)); 425 write_number(static_cast<std::uint32_t>(j.m_value.number_integer)); 426 } 427 else if (j.m_value.number_unsigned <= (std::numeric_limits<std::uint64_t>::max)()) 428 { 429 // uint 64 430 oa->write_character(to_char_type(0xCF)); 431 write_number(static_cast<std::uint64_t>(j.m_value.number_integer)); 432 } 433 break; 434 } 435 436 case value_t::number_float: 437 { 438 oa->write_character(get_msgpack_float_prefix(j.m_value.number_float)); 439 write_number(j.m_value.number_float); 440 break; 441 } 442 443 case value_t::string: 444 { 445 // step 1: write control byte and the string length 446 const auto N = j.m_value.string->size(); 447 if (N <= 31) 448 { 449 // fixstr 450 write_number(static_cast<std::uint8_t>(0xA0 | N)); 451 } 452 else if (N <= (std::numeric_limits<std::uint8_t>::max)()) 453 { 454 // str 8 455 oa->write_character(to_char_type(0xD9)); 456 write_number(static_cast<std::uint8_t>(N)); 457 } 458 else if (N <= (std::numeric_limits<std::uint16_t>::max)()) 459 { 460 // str 16 461 oa->write_character(to_char_type(0xDA)); 462 write_number(static_cast<std::uint16_t>(N)); 463 } 464 else if (N <= (std::numeric_limits<std::uint32_t>::max)()) 465 { 466 // str 32 467 oa->write_character(to_char_type(0xDB)); 468 write_number(static_cast<std::uint32_t>(N)); 469 } 470 471 // step 2: write the string 472 oa->write_characters( 473 reinterpret_cast<const CharType*>(j.m_value.string->c_str()), 474 j.m_value.string->size()); 475 break; 476 } 477 478 case value_t::array: 479 { 480 // step 1: write control byte and the array size 481 const auto N = j.m_value.array->size(); 482 if (N <= 15) 483 { 484 // fixarray 485 write_number(static_cast<std::uint8_t>(0x90 | N)); 486 } 487 else if (N <= (std::numeric_limits<std::uint16_t>::max)()) 488 { 489 // array 16 490 oa->write_character(to_char_type(0xDC)); 491 write_number(static_cast<std::uint16_t>(N)); 492 } 493 else if (N <= (std::numeric_limits<std::uint32_t>::max)()) 494 { 495 // array 32 496 oa->write_character(to_char_type(0xDD)); 497 write_number(static_cast<std::uint32_t>(N)); 498 } 499 500 // step 2: write each element 501 for (const auto& el : *j.m_value.array) 502 { 503 write_msgpack(el); 504 } 505 break; 506 } 507 508 case value_t::object: 509 { 510 // step 1: write control byte and the object size 511 const auto N = j.m_value.object->size(); 512 if (N <= 15) 513 { 514 // fixmap 515 write_number(static_cast<std::uint8_t>(0x80 | (N & 0xF))); 516 } 517 else if (N <= (std::numeric_limits<std::uint16_t>::max)()) 518 { 519 // map 16 520 oa->write_character(to_char_type(0xDE)); 521 write_number(static_cast<std::uint16_t>(N)); 522 } 523 else if (N <= (std::numeric_limits<std::uint32_t>::max)()) 524 { 525 // map 32 526 oa->write_character(to_char_type(0xDF)); 527 write_number(static_cast<std::uint32_t>(N)); 528 } 529 530 // step 2: write each element 531 for (const auto& el : *j.m_value.object) 532 { 533 write_msgpack(el.first); 534 write_msgpack(el.second); 535 } 536 break; 537 } 538 539 default: 540 break; 541 } 542 } 543 544 /*! 545 @param[in] j JSON value to serialize 546 @param[in] use_count whether to use '#' prefixes (optimized format) 547 @param[in] use_type whether to use '$' prefixes (optimized format) 548 @param[in] add_prefix whether prefixes need to be used for this value 549 */ write_ubjson(const BasicJsonType & j,const bool use_count,const bool use_type,const bool add_prefix=true)550 void write_ubjson(const BasicJsonType& j, const bool use_count, 551 const bool use_type, const bool add_prefix = true) 552 { 553 switch (j.type()) 554 { 555 case value_t::null: 556 { 557 if (add_prefix) 558 { 559 oa->write_character(to_char_type('Z')); 560 } 561 break; 562 } 563 564 case value_t::boolean: 565 { 566 if (add_prefix) 567 { 568 oa->write_character(j.m_value.boolean 569 ? to_char_type('T') 570 : to_char_type('F')); 571 } 572 break; 573 } 574 575 case value_t::number_integer: 576 { 577 write_number_with_ubjson_prefix(j.m_value.number_integer, add_prefix); 578 break; 579 } 580 581 case value_t::number_unsigned: 582 { 583 write_number_with_ubjson_prefix(j.m_value.number_unsigned, add_prefix); 584 break; 585 } 586 587 case value_t::number_float: 588 { 589 write_number_with_ubjson_prefix(j.m_value.number_float, add_prefix); 590 break; 591 } 592 593 case value_t::string: 594 { 595 if (add_prefix) 596 { 597 oa->write_character(to_char_type('S')); 598 } 599 write_number_with_ubjson_prefix(j.m_value.string->size(), true); 600 oa->write_characters( 601 reinterpret_cast<const CharType*>(j.m_value.string->c_str()), 602 j.m_value.string->size()); 603 break; 604 } 605 606 case value_t::array: 607 { 608 if (add_prefix) 609 { 610 oa->write_character(to_char_type('[')); 611 } 612 613 bool prefix_required = true; 614 if (use_type and not j.m_value.array->empty()) 615 { 616 assert(use_count); 617 const CharType first_prefix = ubjson_prefix(j.front()); 618 const bool same_prefix = std::all_of(j.begin() + 1, j.end(), 619 [this, first_prefix](const BasicJsonType & v) 620 { 621 return ubjson_prefix(v) == first_prefix; 622 }); 623 624 if (same_prefix) 625 { 626 prefix_required = false; 627 oa->write_character(to_char_type('$')); 628 oa->write_character(first_prefix); 629 } 630 } 631 632 if (use_count) 633 { 634 oa->write_character(to_char_type('#')); 635 write_number_with_ubjson_prefix(j.m_value.array->size(), true); 636 } 637 638 for (const auto& el : *j.m_value.array) 639 { 640 write_ubjson(el, use_count, use_type, prefix_required); 641 } 642 643 if (not use_count) 644 { 645 oa->write_character(to_char_type(']')); 646 } 647 648 break; 649 } 650 651 case value_t::object: 652 { 653 if (add_prefix) 654 { 655 oa->write_character(to_char_type('{')); 656 } 657 658 bool prefix_required = true; 659 if (use_type and not j.m_value.object->empty()) 660 { 661 assert(use_count); 662 const CharType first_prefix = ubjson_prefix(j.front()); 663 const bool same_prefix = std::all_of(j.begin(), j.end(), 664 [this, first_prefix](const BasicJsonType & v) 665 { 666 return ubjson_prefix(v) == first_prefix; 667 }); 668 669 if (same_prefix) 670 { 671 prefix_required = false; 672 oa->write_character(to_char_type('$')); 673 oa->write_character(first_prefix); 674 } 675 } 676 677 if (use_count) 678 { 679 oa->write_character(to_char_type('#')); 680 write_number_with_ubjson_prefix(j.m_value.object->size(), true); 681 } 682 683 for (const auto& el : *j.m_value.object) 684 { 685 write_number_with_ubjson_prefix(el.first.size(), true); 686 oa->write_characters( 687 reinterpret_cast<const CharType*>(el.first.c_str()), 688 el.first.size()); 689 write_ubjson(el.second, use_count, use_type, prefix_required); 690 } 691 692 if (not use_count) 693 { 694 oa->write_character(to_char_type('}')); 695 } 696 697 break; 698 } 699 700 default: 701 break; 702 } 703 } 704 705 private: 706 ////////// 707 // BSON // 708 ////////// 709 710 /*! 711 @return The size of a BSON document entry header, including the id marker 712 and the entry name size (and its null-terminator). 713 */ calc_bson_entry_header_size(const string_t & name)714 static std::size_t calc_bson_entry_header_size(const string_t& name) 715 { 716 const auto it = name.find(static_cast<typename string_t::value_type>(0)); 717 if (JSON_UNLIKELY(it != BasicJsonType::string_t::npos)) 718 { 719 JSON_THROW(out_of_range::create(409, 720 "BSON key cannot contain code point U+0000 (at byte " + std::to_string(it) + ")")); 721 } 722 723 return /*id*/ 1ul + name.size() + /*zero-terminator*/1u; 724 } 725 726 /*! 727 @brief Writes the given @a element_type and @a name to the output adapter 728 */ write_bson_entry_header(const string_t & name,const std::uint8_t element_type)729 void write_bson_entry_header(const string_t& name, 730 const std::uint8_t element_type) 731 { 732 oa->write_character(to_char_type(element_type)); // boolean 733 oa->write_characters( 734 reinterpret_cast<const CharType*>(name.c_str()), 735 name.size() + 1u); 736 } 737 738 /*! 739 @brief Writes a BSON element with key @a name and boolean value @a value 740 */ write_bson_boolean(const string_t & name,const bool value)741 void write_bson_boolean(const string_t& name, 742 const bool value) 743 { 744 write_bson_entry_header(name, 0x08); 745 oa->write_character(value ? to_char_type(0x01) : to_char_type(0x00)); 746 } 747 748 /*! 749 @brief Writes a BSON element with key @a name and double value @a value 750 */ write_bson_double(const string_t & name,const double value)751 void write_bson_double(const string_t& name, 752 const double value) 753 { 754 write_bson_entry_header(name, 0x01); 755 write_number<double, true>(value); 756 } 757 758 /*! 759 @return The size of the BSON-encoded string in @a value 760 */ calc_bson_string_size(const string_t & value)761 static std::size_t calc_bson_string_size(const string_t& value) 762 { 763 return sizeof(std::int32_t) + value.size() + 1ul; 764 } 765 766 /*! 767 @brief Writes a BSON element with key @a name and string value @a value 768 */ write_bson_string(const string_t & name,const string_t & value)769 void write_bson_string(const string_t& name, 770 const string_t& value) 771 { 772 write_bson_entry_header(name, 0x02); 773 774 write_number<std::int32_t, true>(static_cast<std::int32_t>(value.size() + 1ul)); 775 oa->write_characters( 776 reinterpret_cast<const CharType*>(value.c_str()), 777 value.size() + 1); 778 } 779 780 /*! 781 @brief Writes a BSON element with key @a name and null value 782 */ write_bson_null(const string_t & name)783 void write_bson_null(const string_t& name) 784 { 785 write_bson_entry_header(name, 0x0A); 786 } 787 788 /*! 789 @return The size of the BSON-encoded integer @a value 790 */ calc_bson_integer_size(const std::int64_t value)791 static std::size_t calc_bson_integer_size(const std::int64_t value) 792 { 793 return (std::numeric_limits<std::int32_t>::min)() <= value and value <= (std::numeric_limits<std::int32_t>::max)() 794 ? sizeof(std::int32_t) 795 : sizeof(std::int64_t); 796 } 797 798 /*! 799 @brief Writes a BSON element with key @a name and integer @a value 800 */ write_bson_integer(const string_t & name,const std::int64_t value)801 void write_bson_integer(const string_t& name, 802 const std::int64_t value) 803 { 804 if ((std::numeric_limits<std::int32_t>::min)() <= value and value <= (std::numeric_limits<std::int32_t>::max)()) 805 { 806 write_bson_entry_header(name, 0x10); // int32 807 write_number<std::int32_t, true>(static_cast<std::int32_t>(value)); 808 } 809 else 810 { 811 write_bson_entry_header(name, 0x12); // int64 812 write_number<std::int64_t, true>(static_cast<std::int64_t>(value)); 813 } 814 } 815 816 /*! 817 @return The size of the BSON-encoded unsigned integer in @a j 818 */ calc_bson_unsigned_size(const std::uint64_t value)819 static constexpr std::size_t calc_bson_unsigned_size(const std::uint64_t value) noexcept 820 { 821 return (value <= static_cast<std::uint64_t>((std::numeric_limits<std::int32_t>::max)())) 822 ? sizeof(std::int32_t) 823 : sizeof(std::int64_t); 824 } 825 826 /*! 827 @brief Writes a BSON element with key @a name and unsigned @a value 828 */ write_bson_unsigned(const string_t & name,const std::uint64_t value)829 void write_bson_unsigned(const string_t& name, 830 const std::uint64_t value) 831 { 832 if (value <= static_cast<std::uint64_t>((std::numeric_limits<std::int32_t>::max)())) 833 { 834 write_bson_entry_header(name, 0x10 /* int32 */); 835 write_number<std::int32_t, true>(static_cast<std::int32_t>(value)); 836 } 837 else if (value <= static_cast<std::uint64_t>((std::numeric_limits<std::int64_t>::max)())) 838 { 839 write_bson_entry_header(name, 0x12 /* int64 */); 840 write_number<std::int64_t, true>(static_cast<std::int64_t>(value)); 841 } 842 else 843 { 844 JSON_THROW(out_of_range::create(407, "integer number " + std::to_string(value) + " cannot be represented by BSON as it does not fit int64")); 845 } 846 } 847 848 /*! 849 @brief Writes a BSON element with key @a name and object @a value 850 */ write_bson_object_entry(const string_t & name,const typename BasicJsonType::object_t & value)851 void write_bson_object_entry(const string_t& name, 852 const typename BasicJsonType::object_t& value) 853 { 854 write_bson_entry_header(name, 0x03); // object 855 write_bson_object(value); 856 } 857 858 /*! 859 @return The size of the BSON-encoded array @a value 860 */ calc_bson_array_size(const typename BasicJsonType::array_t & value)861 static std::size_t calc_bson_array_size(const typename BasicJsonType::array_t& value) 862 { 863 std::size_t embedded_document_size = 0ul; 864 std::size_t array_index = 0ul; 865 866 for (const auto& el : value) 867 { 868 embedded_document_size += calc_bson_element_size(std::to_string(array_index++), el); 869 } 870 871 return sizeof(std::int32_t) + embedded_document_size + 1ul; 872 } 873 874 /*! 875 @brief Writes a BSON element with key @a name and array @a value 876 */ write_bson_array(const string_t & name,const typename BasicJsonType::array_t & value)877 void write_bson_array(const string_t& name, 878 const typename BasicJsonType::array_t& value) 879 { 880 write_bson_entry_header(name, 0x04); // array 881 write_number<std::int32_t, true>(static_cast<std::int32_t>(calc_bson_array_size(value))); 882 883 std::size_t array_index = 0ul; 884 885 for (const auto& el : value) 886 { 887 write_bson_element(std::to_string(array_index++), el); 888 } 889 890 oa->write_character(to_char_type(0x00)); 891 } 892 893 /*! 894 @brief Calculates the size necessary to serialize the JSON value @a j with its @a name 895 @return The calculated size for the BSON document entry for @a j with the given @a name. 896 */ calc_bson_element_size(const string_t & name,const BasicJsonType & j)897 static std::size_t calc_bson_element_size(const string_t& name, 898 const BasicJsonType& j) 899 { 900 const auto header_size = calc_bson_entry_header_size(name); 901 switch (j.type()) 902 { 903 case value_t::object: 904 return header_size + calc_bson_object_size(*j.m_value.object); 905 906 case value_t::array: 907 return header_size + calc_bson_array_size(*j.m_value.array); 908 909 case value_t::boolean: 910 return header_size + 1ul; 911 912 case value_t::number_float: 913 return header_size + 8ul; 914 915 case value_t::number_integer: 916 return header_size + calc_bson_integer_size(j.m_value.number_integer); 917 918 case value_t::number_unsigned: 919 return header_size + calc_bson_unsigned_size(j.m_value.number_unsigned); 920 921 case value_t::string: 922 return header_size + calc_bson_string_size(*j.m_value.string); 923 924 case value_t::null: 925 return header_size + 0ul; 926 927 // LCOV_EXCL_START 928 default: 929 assert(false); 930 return 0ul; 931 // LCOV_EXCL_STOP 932 } 933 } 934 935 /*! 936 @brief Serializes the JSON value @a j to BSON and associates it with the 937 key @a name. 938 @param name The name to associate with the JSON entity @a j within the 939 current BSON document 940 @return The size of the BSON entry 941 */ write_bson_element(const string_t & name,const BasicJsonType & j)942 void write_bson_element(const string_t& name, 943 const BasicJsonType& j) 944 { 945 switch (j.type()) 946 { 947 case value_t::object: 948 return write_bson_object_entry(name, *j.m_value.object); 949 950 case value_t::array: 951 return write_bson_array(name, *j.m_value.array); 952 953 case value_t::boolean: 954 return write_bson_boolean(name, j.m_value.boolean); 955 956 case value_t::number_float: 957 return write_bson_double(name, j.m_value.number_float); 958 959 case value_t::number_integer: 960 return write_bson_integer(name, j.m_value.number_integer); 961 962 case value_t::number_unsigned: 963 return write_bson_unsigned(name, j.m_value.number_unsigned); 964 965 case value_t::string: 966 return write_bson_string(name, *j.m_value.string); 967 968 case value_t::null: 969 return write_bson_null(name); 970 971 // LCOV_EXCL_START 972 default: 973 assert(false); 974 return; 975 // LCOV_EXCL_STOP 976 } 977 } 978 979 /*! 980 @brief Calculates the size of the BSON serialization of the given 981 JSON-object @a j. 982 @param[in] j JSON value to serialize 983 @pre j.type() == value_t::object 984 */ calc_bson_object_size(const typename BasicJsonType::object_t & value)985 static std::size_t calc_bson_object_size(const typename BasicJsonType::object_t& value) 986 { 987 std::size_t document_size = std::accumulate(value.begin(), value.end(), 0ul, 988 [](size_t result, const typename BasicJsonType::object_t::value_type & el) 989 { 990 return result += calc_bson_element_size(el.first, el.second); 991 }); 992 993 return sizeof(std::int32_t) + document_size + 1ul; 994 } 995 996 /*! 997 @param[in] j JSON value to serialize 998 @pre j.type() == value_t::object 999 */ write_bson_object(const typename BasicJsonType::object_t & value)1000 void write_bson_object(const typename BasicJsonType::object_t& value) 1001 { 1002 write_number<std::int32_t, true>(static_cast<std::int32_t>(calc_bson_object_size(value))); 1003 1004 for (const auto& el : value) 1005 { 1006 write_bson_element(el.first, el.second); 1007 } 1008 1009 oa->write_character(to_char_type(0x00)); 1010 } 1011 1012 ////////// 1013 // CBOR // 1014 ////////// 1015 get_cbor_float_prefix(float)1016 static constexpr CharType get_cbor_float_prefix(float /*unused*/) 1017 { 1018 return to_char_type(0xFA); // Single-Precision Float 1019 } 1020 get_cbor_float_prefix(double)1021 static constexpr CharType get_cbor_float_prefix(double /*unused*/) 1022 { 1023 return to_char_type(0xFB); // Double-Precision Float 1024 } 1025 1026 ///////////// 1027 // MsgPack // 1028 ///////////// 1029 get_msgpack_float_prefix(float)1030 static constexpr CharType get_msgpack_float_prefix(float /*unused*/) 1031 { 1032 return to_char_type(0xCA); // float 32 1033 } 1034 get_msgpack_float_prefix(double)1035 static constexpr CharType get_msgpack_float_prefix(double /*unused*/) 1036 { 1037 return to_char_type(0xCB); // float 64 1038 } 1039 1040 //////////// 1041 // UBJSON // 1042 //////////// 1043 1044 // UBJSON: write number (floating point) 1045 template<typename NumberType, typename std::enable_if< 1046 std::is_floating_point<NumberType>::value, int>::type = 0> write_number_with_ubjson_prefix(const NumberType n,const bool add_prefix)1047 void write_number_with_ubjson_prefix(const NumberType n, 1048 const bool add_prefix) 1049 { 1050 if (add_prefix) 1051 { 1052 oa->write_character(get_ubjson_float_prefix(n)); 1053 } 1054 write_number(n); 1055 } 1056 1057 // UBJSON: write number (unsigned integer) 1058 template<typename NumberType, typename std::enable_if< 1059 std::is_unsigned<NumberType>::value, int>::type = 0> write_number_with_ubjson_prefix(const NumberType n,const bool add_prefix)1060 void write_number_with_ubjson_prefix(const NumberType n, 1061 const bool add_prefix) 1062 { 1063 if (n <= static_cast<std::uint64_t>((std::numeric_limits<std::int8_t>::max)())) 1064 { 1065 if (add_prefix) 1066 { 1067 oa->write_character(to_char_type('i')); // int8 1068 } 1069 write_number(static_cast<std::uint8_t>(n)); 1070 } 1071 else if (n <= (std::numeric_limits<std::uint8_t>::max)()) 1072 { 1073 if (add_prefix) 1074 { 1075 oa->write_character(to_char_type('U')); // uint8 1076 } 1077 write_number(static_cast<std::uint8_t>(n)); 1078 } 1079 else if (n <= static_cast<std::uint64_t>((std::numeric_limits<std::int16_t>::max)())) 1080 { 1081 if (add_prefix) 1082 { 1083 oa->write_character(to_char_type('I')); // int16 1084 } 1085 write_number(static_cast<std::int16_t>(n)); 1086 } 1087 else if (n <= static_cast<std::uint64_t>((std::numeric_limits<std::int32_t>::max)())) 1088 { 1089 if (add_prefix) 1090 { 1091 oa->write_character(to_char_type('l')); // int32 1092 } 1093 write_number(static_cast<std::int32_t>(n)); 1094 } 1095 else if (n <= static_cast<std::uint64_t>((std::numeric_limits<std::int64_t>::max)())) 1096 { 1097 if (add_prefix) 1098 { 1099 oa->write_character(to_char_type('L')); // int64 1100 } 1101 write_number(static_cast<std::int64_t>(n)); 1102 } 1103 else 1104 { 1105 JSON_THROW(out_of_range::create(407, "integer number " + std::to_string(n) + " cannot be represented by UBJSON as it does not fit int64")); 1106 } 1107 } 1108 1109 // UBJSON: write number (signed integer) 1110 template<typename NumberType, typename std::enable_if< 1111 std::is_signed<NumberType>::value and 1112 not std::is_floating_point<NumberType>::value, int>::type = 0> write_number_with_ubjson_prefix(const NumberType n,const bool add_prefix)1113 void write_number_with_ubjson_prefix(const NumberType n, 1114 const bool add_prefix) 1115 { 1116 if ((std::numeric_limits<std::int8_t>::min)() <= n and n <= (std::numeric_limits<std::int8_t>::max)()) 1117 { 1118 if (add_prefix) 1119 { 1120 oa->write_character(to_char_type('i')); // int8 1121 } 1122 write_number(static_cast<std::int8_t>(n)); 1123 } 1124 else if (static_cast<std::int64_t>((std::numeric_limits<std::uint8_t>::min)()) <= n and n <= static_cast<std::int64_t>((std::numeric_limits<std::uint8_t>::max)())) 1125 { 1126 if (add_prefix) 1127 { 1128 oa->write_character(to_char_type('U')); // uint8 1129 } 1130 write_number(static_cast<std::uint8_t>(n)); 1131 } 1132 else if ((std::numeric_limits<std::int16_t>::min)() <= n and n <= (std::numeric_limits<std::int16_t>::max)()) 1133 { 1134 if (add_prefix) 1135 { 1136 oa->write_character(to_char_type('I')); // int16 1137 } 1138 write_number(static_cast<std::int16_t>(n)); 1139 } 1140 else if ((std::numeric_limits<std::int32_t>::min)() <= n and n <= (std::numeric_limits<std::int32_t>::max)()) 1141 { 1142 if (add_prefix) 1143 { 1144 oa->write_character(to_char_type('l')); // int32 1145 } 1146 write_number(static_cast<std::int32_t>(n)); 1147 } 1148 else if ((std::numeric_limits<std::int64_t>::min)() <= n and n <= (std::numeric_limits<std::int64_t>::max)()) 1149 { 1150 if (add_prefix) 1151 { 1152 oa->write_character(to_char_type('L')); // int64 1153 } 1154 write_number(static_cast<std::int64_t>(n)); 1155 } 1156 // LCOV_EXCL_START 1157 else 1158 { 1159 JSON_THROW(out_of_range::create(407, "integer number " + std::to_string(n) + " cannot be represented by UBJSON as it does not fit int64")); 1160 } 1161 // LCOV_EXCL_STOP 1162 } 1163 1164 /*! 1165 @brief determine the type prefix of container values 1166 1167 @note This function does not need to be 100% accurate when it comes to 1168 integer limits. In case a number exceeds the limits of int64_t, 1169 this will be detected by a later call to function 1170 write_number_with_ubjson_prefix. Therefore, we return 'L' for any 1171 value that does not fit the previous limits. 1172 */ ubjson_prefix(const BasicJsonType & j) const1173 CharType ubjson_prefix(const BasicJsonType& j) const noexcept 1174 { 1175 switch (j.type()) 1176 { 1177 case value_t::null: 1178 return 'Z'; 1179 1180 case value_t::boolean: 1181 return j.m_value.boolean ? 'T' : 'F'; 1182 1183 case value_t::number_integer: 1184 { 1185 if ((std::numeric_limits<std::int8_t>::min)() <= j.m_value.number_integer and j.m_value.number_integer <= (std::numeric_limits<std::int8_t>::max)()) 1186 { 1187 return 'i'; 1188 } 1189 if ((std::numeric_limits<std::uint8_t>::min)() <= j.m_value.number_integer and j.m_value.number_integer <= (std::numeric_limits<std::uint8_t>::max)()) 1190 { 1191 return 'U'; 1192 } 1193 if ((std::numeric_limits<std::int16_t>::min)() <= j.m_value.number_integer and j.m_value.number_integer <= (std::numeric_limits<std::int16_t>::max)()) 1194 { 1195 return 'I'; 1196 } 1197 if ((std::numeric_limits<std::int32_t>::min)() <= j.m_value.number_integer and j.m_value.number_integer <= (std::numeric_limits<std::int32_t>::max)()) 1198 { 1199 return 'l'; 1200 } 1201 // no check and assume int64_t (see note above) 1202 return 'L'; 1203 } 1204 1205 case value_t::number_unsigned: 1206 { 1207 if (j.m_value.number_unsigned <= (std::numeric_limits<std::int8_t>::max)()) 1208 { 1209 return 'i'; 1210 } 1211 if (j.m_value.number_unsigned <= (std::numeric_limits<std::uint8_t>::max)()) 1212 { 1213 return 'U'; 1214 } 1215 if (j.m_value.number_unsigned <= (std::numeric_limits<std::int16_t>::max)()) 1216 { 1217 return 'I'; 1218 } 1219 if (j.m_value.number_unsigned <= (std::numeric_limits<std::int32_t>::max)()) 1220 { 1221 return 'l'; 1222 } 1223 // no check and assume int64_t (see note above) 1224 return 'L'; 1225 } 1226 1227 case value_t::number_float: 1228 return get_ubjson_float_prefix(j.m_value.number_float); 1229 1230 case value_t::string: 1231 return 'S'; 1232 1233 case value_t::array: 1234 return '['; 1235 1236 case value_t::object: 1237 return '{'; 1238 1239 default: // discarded values 1240 return 'N'; 1241 } 1242 } 1243 get_ubjson_float_prefix(float)1244 static constexpr CharType get_ubjson_float_prefix(float /*unused*/) 1245 { 1246 return 'd'; // float 32 1247 } 1248 get_ubjson_float_prefix(double)1249 static constexpr CharType get_ubjson_float_prefix(double /*unused*/) 1250 { 1251 return 'D'; // float 64 1252 } 1253 1254 /////////////////////// 1255 // Utility functions // 1256 /////////////////////// 1257 1258 /* 1259 @brief write a number to output input 1260 @param[in] n number of type @a NumberType 1261 @tparam NumberType the type of the number 1262 @tparam OutputIsLittleEndian Set to true if output data is 1263 required to be little endian 1264 1265 @note This function needs to respect the system's endianess, because bytes 1266 in CBOR, MessagePack, and UBJSON are stored in network order (big 1267 endian) and therefore need reordering on little endian systems. 1268 */ 1269 template<typename NumberType, bool OutputIsLittleEndian = false> write_number(const NumberType n)1270 void write_number(const NumberType n) 1271 { 1272 // step 1: write number to array of length NumberType 1273 std::array<CharType, sizeof(NumberType)> vec; 1274 std::memcpy(vec.data(), &n, sizeof(NumberType)); 1275 1276 // step 2: write array to output (with possible reordering) 1277 if (is_little_endian != OutputIsLittleEndian) 1278 { 1279 // reverse byte order prior to conversion if necessary 1280 std::reverse(vec.begin(), vec.end()); 1281 } 1282 1283 oa->write_characters(vec.data(), sizeof(NumberType)); 1284 } 1285 1286 public: 1287 // The following to_char_type functions are implement the conversion 1288 // between uint8_t and CharType. In case CharType is not unsigned, 1289 // such a conversion is required to allow values greater than 128. 1290 // See <https://github.com/nlohmann/json/issues/1286> for a discussion. 1291 template < typename C = CharType, 1292 enable_if_t < std::is_signed<C>::value and std::is_signed<char>::value > * = nullptr > to_char_type(std::uint8_t x)1293 static constexpr CharType to_char_type(std::uint8_t x) noexcept 1294 { 1295 return *reinterpret_cast<char*>(&x); 1296 } 1297 1298 template < typename C = CharType, 1299 enable_if_t < std::is_signed<C>::value and std::is_unsigned<char>::value > * = nullptr > to_char_type(std::uint8_t x)1300 static CharType to_char_type(std::uint8_t x) noexcept 1301 { 1302 static_assert(sizeof(std::uint8_t) == sizeof(CharType), "size of CharType must be equal to std::uint8_t"); 1303 static_assert(std::is_pod<CharType>::value, "CharType must be POD"); 1304 CharType result; 1305 std::memcpy(&result, &x, sizeof(x)); 1306 return result; 1307 } 1308 1309 template<typename C = CharType, 1310 enable_if_t<std::is_unsigned<C>::value>* = nullptr> to_char_type(std::uint8_t x)1311 static constexpr CharType to_char_type(std::uint8_t x) noexcept 1312 { 1313 return x; 1314 } 1315 1316 template < typename InputCharType, typename C = CharType, 1317 enable_if_t < 1318 std::is_signed<C>::value and 1319 std::is_signed<char>::value and 1320 std::is_same<char, typename std::remove_cv<InputCharType>::type>::value 1321 > * = nullptr > to_char_type(InputCharType x)1322 static constexpr CharType to_char_type(InputCharType x) noexcept 1323 { 1324 return x; 1325 } 1326 1327 private: 1328 /// whether we can assume little endianess 1329 const bool is_little_endian = binary_reader<BasicJsonType>::little_endianess(); 1330 1331 /// the output 1332 output_adapter_t<CharType> oa = nullptr; 1333 }; 1334 } // namespace detail 1335 } // namespace nlohmann 1336