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