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