1 // __ _____ _____ _____ 2 // __| | __| | | | JSON for Modern C++ 3 // | | |__ | | | | | | version 3.11.2 4 // |_____|_____|_____|_|___| https://github.com/nlohmann/json 5 // 6 // SPDX-FileCopyrightText: 2008-2009 Björn Hoehrmann <bjoern@hoehrmann.de> 7 // SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me> 8 // SPDX-License-Identifier: MIT 9 10 #pragma once 11 12 #include <algorithm> // reverse, remove, fill, find, none_of 13 #include <array> // array 14 #include <clocale> // localeconv, lconv 15 #include <cmath> // labs, isfinite, isnan, signbit 16 #include <cstddef> // size_t, ptrdiff_t 17 #include <cstdint> // uint8_t 18 #include <cstdio> // snprintf 19 #include <limits> // numeric_limits 20 #include <string> // string, char_traits 21 #include <iomanip> // setfill, setw 22 #include <type_traits> // is_same 23 #include <utility> // move 24 25 #include <nlohmann/detail/conversions/to_chars.hpp> 26 #include <nlohmann/detail/exceptions.hpp> 27 #include <nlohmann/detail/macro_scope.hpp> 28 #include <nlohmann/detail/meta/cpp_future.hpp> 29 #include <nlohmann/detail/output/binary_writer.hpp> 30 #include <nlohmann/detail/output/output_adapters.hpp> 31 #include <nlohmann/detail/string_concat.hpp> 32 #include <nlohmann/detail/value_t.hpp> 33 34 NLOHMANN_JSON_NAMESPACE_BEGIN 35 namespace detail 36 { 37 38 /////////////////// 39 // serialization // 40 /////////////////// 41 42 /// how to treat decoding errors 43 enum class error_handler_t 44 { 45 strict, ///< throw a type_error exception in case of invalid UTF-8 46 replace, ///< replace invalid UTF-8 sequences with U+FFFD 47 ignore ///< ignore invalid UTF-8 sequences 48 }; 49 50 template<typename BasicJsonType> 51 class serializer 52 { 53 using string_t = typename BasicJsonType::string_t; 54 using number_float_t = typename BasicJsonType::number_float_t; 55 using number_integer_t = typename BasicJsonType::number_integer_t; 56 using number_unsigned_t = typename BasicJsonType::number_unsigned_t; 57 using binary_char_t = typename BasicJsonType::binary_t::value_type; 58 static constexpr std::uint8_t UTF8_ACCEPT = 0; 59 static constexpr std::uint8_t UTF8_REJECT = 1; 60 61 public: 62 /*! 63 @param[in] s output stream to serialize to 64 @param[in] ichar indentation character to use 65 @param[in] error_handler_ how to react on decoding errors 66 */ serializer(output_adapter_t<char> s,const char ichar,error_handler_t error_handler_=error_handler_t::strict)67 serializer(output_adapter_t<char> s, const char ichar, 68 error_handler_t error_handler_ = error_handler_t::strict) 69 : o(std::move(s)) 70 , loc(std::localeconv()) 71 , thousands_sep(loc->thousands_sep == nullptr ? '\0' : std::char_traits<char>::to_char_type(* (loc->thousands_sep))) 72 , decimal_point(loc->decimal_point == nullptr ? '\0' : std::char_traits<char>::to_char_type(* (loc->decimal_point))) 73 , indent_char(ichar) 74 , indent_string(512, indent_char) 75 , error_handler(error_handler_) 76 {} 77 78 // delete because of pointer members 79 serializer(const serializer&) = delete; 80 serializer& operator=(const serializer&) = delete; 81 serializer(serializer&&) = delete; 82 serializer& operator=(serializer&&) = delete; 83 ~serializer() = default; 84 85 /*! 86 @brief internal implementation of the serialization function 87 88 This function is called by the public member function dump and organizes 89 the serialization internally. The indentation level is propagated as 90 additional parameter. In case of arrays and objects, the function is 91 called recursively. 92 93 - strings and object keys are escaped using `escape_string()` 94 - integer numbers are converted implicitly via `operator<<` 95 - floating-point numbers are converted to a string using `"%g"` format 96 - binary values are serialized as objects containing the subtype and the 97 byte array 98 99 @param[in] val value to serialize 100 @param[in] pretty_print whether the output shall be pretty-printed 101 @param[in] ensure_ascii If @a ensure_ascii is true, all non-ASCII characters 102 in the output are escaped with `\uXXXX` sequences, and the result consists 103 of ASCII characters only. 104 @param[in] indent_step the indent level 105 @param[in] current_indent the current indent level (only used internally) 106 */ dump(const BasicJsonType & val,const bool pretty_print,const bool ensure_ascii,const unsigned int indent_step,const unsigned int current_indent=0)107 void dump(const BasicJsonType& val, 108 const bool pretty_print, 109 const bool ensure_ascii, 110 const unsigned int indent_step, 111 const unsigned int current_indent = 0) 112 { 113 switch (val.m_type) 114 { 115 case value_t::object: 116 { 117 if (val.m_value.object->empty()) 118 { 119 o->write_characters("{}", 2); 120 return; 121 } 122 123 if (pretty_print) 124 { 125 o->write_characters("{\n", 2); 126 127 // variable to hold indentation for recursive calls 128 const auto new_indent = current_indent + indent_step; 129 if (JSON_HEDLEY_UNLIKELY(indent_string.size() < new_indent)) 130 { 131 indent_string.resize(indent_string.size() * 2, ' '); 132 } 133 134 // first n-1 elements 135 auto i = val.m_value.object->cbegin(); 136 for (std::size_t cnt = 0; cnt < val.m_value.object->size() - 1; ++cnt, ++i) 137 { 138 o->write_characters(indent_string.c_str(), new_indent); 139 o->write_character('\"'); 140 dump_escaped(i->first, ensure_ascii); 141 o->write_characters("\": ", 3); 142 dump(i->second, true, ensure_ascii, indent_step, new_indent); 143 o->write_characters(",\n", 2); 144 } 145 146 // last element 147 JSON_ASSERT(i != val.m_value.object->cend()); 148 JSON_ASSERT(std::next(i) == val.m_value.object->cend()); 149 o->write_characters(indent_string.c_str(), new_indent); 150 o->write_character('\"'); 151 dump_escaped(i->first, ensure_ascii); 152 o->write_characters("\": ", 3); 153 dump(i->second, true, ensure_ascii, indent_step, new_indent); 154 155 o->write_character('\n'); 156 o->write_characters(indent_string.c_str(), current_indent); 157 o->write_character('}'); 158 } 159 else 160 { 161 o->write_character('{'); 162 163 // first n-1 elements 164 auto i = val.m_value.object->cbegin(); 165 for (std::size_t cnt = 0; cnt < val.m_value.object->size() - 1; ++cnt, ++i) 166 { 167 o->write_character('\"'); 168 dump_escaped(i->first, ensure_ascii); 169 o->write_characters("\":", 2); 170 dump(i->second, false, ensure_ascii, indent_step, current_indent); 171 o->write_character(','); 172 } 173 174 // last element 175 JSON_ASSERT(i != val.m_value.object->cend()); 176 JSON_ASSERT(std::next(i) == val.m_value.object->cend()); 177 o->write_character('\"'); 178 dump_escaped(i->first, ensure_ascii); 179 o->write_characters("\":", 2); 180 dump(i->second, false, ensure_ascii, indent_step, current_indent); 181 182 o->write_character('}'); 183 } 184 185 return; 186 } 187 188 case value_t::array: 189 { 190 if (val.m_value.array->empty()) 191 { 192 o->write_characters("[]", 2); 193 return; 194 } 195 196 if (pretty_print) 197 { 198 o->write_characters("[\n", 2); 199 200 // variable to hold indentation for recursive calls 201 const auto new_indent = current_indent + indent_step; 202 if (JSON_HEDLEY_UNLIKELY(indent_string.size() < new_indent)) 203 { 204 indent_string.resize(indent_string.size() * 2, ' '); 205 } 206 207 // first n-1 elements 208 for (auto i = val.m_value.array->cbegin(); 209 i != val.m_value.array->cend() - 1; ++i) 210 { 211 o->write_characters(indent_string.c_str(), new_indent); 212 dump(*i, true, ensure_ascii, indent_step, new_indent); 213 o->write_characters(",\n", 2); 214 } 215 216 // last element 217 JSON_ASSERT(!val.m_value.array->empty()); 218 o->write_characters(indent_string.c_str(), new_indent); 219 dump(val.m_value.array->back(), true, ensure_ascii, indent_step, new_indent); 220 221 o->write_character('\n'); 222 o->write_characters(indent_string.c_str(), current_indent); 223 o->write_character(']'); 224 } 225 else 226 { 227 o->write_character('['); 228 229 // first n-1 elements 230 for (auto i = val.m_value.array->cbegin(); 231 i != val.m_value.array->cend() - 1; ++i) 232 { 233 dump(*i, false, ensure_ascii, indent_step, current_indent); 234 o->write_character(','); 235 } 236 237 // last element 238 JSON_ASSERT(!val.m_value.array->empty()); 239 dump(val.m_value.array->back(), false, ensure_ascii, indent_step, current_indent); 240 241 o->write_character(']'); 242 } 243 244 return; 245 } 246 247 case value_t::string: 248 { 249 o->write_character('\"'); 250 dump_escaped(*val.m_value.string, ensure_ascii); 251 o->write_character('\"'); 252 return; 253 } 254 255 case value_t::binary: 256 { 257 if (pretty_print) 258 { 259 o->write_characters("{\n", 2); 260 261 // variable to hold indentation for recursive calls 262 const auto new_indent = current_indent + indent_step; 263 if (JSON_HEDLEY_UNLIKELY(indent_string.size() < new_indent)) 264 { 265 indent_string.resize(indent_string.size() * 2, ' '); 266 } 267 268 o->write_characters(indent_string.c_str(), new_indent); 269 270 o->write_characters("\"bytes\": [", 10); 271 272 if (!val.m_value.binary->empty()) 273 { 274 for (auto i = val.m_value.binary->cbegin(); 275 i != val.m_value.binary->cend() - 1; ++i) 276 { 277 dump_integer(*i); 278 o->write_characters(", ", 2); 279 } 280 dump_integer(val.m_value.binary->back()); 281 } 282 283 o->write_characters("],\n", 3); 284 o->write_characters(indent_string.c_str(), new_indent); 285 286 o->write_characters("\"subtype\": ", 11); 287 if (val.m_value.binary->has_subtype()) 288 { 289 dump_integer(val.m_value.binary->subtype()); 290 } 291 else 292 { 293 o->write_characters("null", 4); 294 } 295 o->write_character('\n'); 296 o->write_characters(indent_string.c_str(), current_indent); 297 o->write_character('}'); 298 } 299 else 300 { 301 o->write_characters("{\"bytes\":[", 10); 302 303 if (!val.m_value.binary->empty()) 304 { 305 for (auto i = val.m_value.binary->cbegin(); 306 i != val.m_value.binary->cend() - 1; ++i) 307 { 308 dump_integer(*i); 309 o->write_character(','); 310 } 311 dump_integer(val.m_value.binary->back()); 312 } 313 314 o->write_characters("],\"subtype\":", 12); 315 if (val.m_value.binary->has_subtype()) 316 { 317 dump_integer(val.m_value.binary->subtype()); 318 o->write_character('}'); 319 } 320 else 321 { 322 o->write_characters("null}", 5); 323 } 324 } 325 return; 326 } 327 328 case value_t::boolean: 329 { 330 if (val.m_value.boolean) 331 { 332 o->write_characters("true", 4); 333 } 334 else 335 { 336 o->write_characters("false", 5); 337 } 338 return; 339 } 340 341 case value_t::number_integer: 342 { 343 dump_integer(val.m_value.number_integer); 344 return; 345 } 346 347 case value_t::number_unsigned: 348 { 349 dump_integer(val.m_value.number_unsigned); 350 return; 351 } 352 353 case value_t::number_float: 354 { 355 dump_float(val.m_value.number_float); 356 return; 357 } 358 359 case value_t::discarded: 360 { 361 o->write_characters("<discarded>", 11); 362 return; 363 } 364 365 case value_t::null: 366 { 367 o->write_characters("null", 4); 368 return; 369 } 370 371 default: // LCOV_EXCL_LINE 372 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE 373 } 374 } 375 376 JSON_PRIVATE_UNLESS_TESTED: 377 /*! 378 @brief dump escaped string 379 380 Escape a string by replacing certain special characters by a sequence of an 381 escape character (backslash) and another character and other control 382 characters by a sequence of "\u" followed by a four-digit hex 383 representation. The escaped string is written to output stream @a o. 384 385 @param[in] s the string to escape 386 @param[in] ensure_ascii whether to escape non-ASCII characters with 387 \uXXXX sequences 388 389 @complexity Linear in the length of string @a s. 390 */ 391 void dump_escaped(const string_t& s, const bool ensure_ascii) 392 { 393 std::uint32_t codepoint{}; 394 std::uint8_t state = UTF8_ACCEPT; 395 std::size_t bytes = 0; // number of bytes written to string_buffer 396 397 // number of bytes written at the point of the last valid byte 398 std::size_t bytes_after_last_accept = 0; 399 std::size_t undumped_chars = 0; 400 401 for (std::size_t i = 0; i < s.size(); ++i) 402 { 403 const auto byte = static_cast<std::uint8_t>(s[i]); 404 405 switch (decode(state, codepoint, byte)) 406 { 407 case UTF8_ACCEPT: // decode found a new code point 408 { 409 switch (codepoint) 410 { 411 case 0x08: // backspace 412 { 413 string_buffer[bytes++] = '\\'; 414 string_buffer[bytes++] = 'b'; 415 break; 416 } 417 418 case 0x09: // horizontal tab 419 { 420 string_buffer[bytes++] = '\\'; 421 string_buffer[bytes++] = 't'; 422 break; 423 } 424 425 case 0x0A: // newline 426 { 427 string_buffer[bytes++] = '\\'; 428 string_buffer[bytes++] = 'n'; 429 break; 430 } 431 432 case 0x0C: // formfeed 433 { 434 string_buffer[bytes++] = '\\'; 435 string_buffer[bytes++] = 'f'; 436 break; 437 } 438 439 case 0x0D: // carriage return 440 { 441 string_buffer[bytes++] = '\\'; 442 string_buffer[bytes++] = 'r'; 443 break; 444 } 445 446 case 0x22: // quotation mark 447 { 448 string_buffer[bytes++] = '\\'; 449 string_buffer[bytes++] = '\"'; 450 break; 451 } 452 453 case 0x5C: // reverse solidus 454 { 455 string_buffer[bytes++] = '\\'; 456 string_buffer[bytes++] = '\\'; 457 break; 458 } 459 460 default: 461 { 462 // escape control characters (0x00..0x1F) or, if 463 // ensure_ascii parameter is used, non-ASCII characters 464 if ((codepoint <= 0x1F) || (ensure_ascii && (codepoint >= 0x7F))) 465 { 466 if (codepoint <= 0xFFFF) 467 { 468 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg,hicpp-vararg) 469 static_cast<void>((std::snprintf)(string_buffer.data() + bytes, 7, "\\u%04x", 470 static_cast<std::uint16_t>(codepoint))); 471 bytes += 6; 472 } 473 else 474 { 475 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg,hicpp-vararg) 476 static_cast<void>((std::snprintf)(string_buffer.data() + bytes, 13, "\\u%04x\\u%04x", 477 static_cast<std::uint16_t>(0xD7C0u + (codepoint >> 10u)), 478 static_cast<std::uint16_t>(0xDC00u + (codepoint & 0x3FFu)))); 479 bytes += 12; 480 } 481 } 482 else 483 { 484 // copy byte to buffer (all previous bytes 485 // been copied have in default case above) 486 string_buffer[bytes++] = s[i]; 487 } 488 break; 489 } 490 } 491 492 // write buffer and reset index; there must be 13 bytes 493 // left, as this is the maximal number of bytes to be 494 // written ("\uxxxx\uxxxx\0") for one code point 495 if (string_buffer.size() - bytes < 13) 496 { 497 o->write_characters(string_buffer.data(), bytes); 498 bytes = 0; 499 } 500 501 // remember the byte position of this accept 502 bytes_after_last_accept = bytes; 503 undumped_chars = 0; 504 break; 505 } 506 507 case UTF8_REJECT: // decode found invalid UTF-8 byte 508 { 509 switch (error_handler) 510 { 511 case error_handler_t::strict: 512 { 513 JSON_THROW(type_error::create(316, concat("invalid UTF-8 byte at index ", std::to_string(i), ": 0x", hex_bytes(byte | 0)), nullptr)); 514 } 515 516 case error_handler_t::ignore: 517 case error_handler_t::replace: 518 { 519 // in case we saw this character the first time, we 520 // would like to read it again, because the byte 521 // may be OK for itself, but just not OK for the 522 // previous sequence 523 if (undumped_chars > 0) 524 { 525 --i; 526 } 527 528 // reset length buffer to the last accepted index; 529 // thus removing/ignoring the invalid characters 530 bytes = bytes_after_last_accept; 531 532 if (error_handler == error_handler_t::replace) 533 { 534 // add a replacement character 535 if (ensure_ascii) 536 { 537 string_buffer[bytes++] = '\\'; 538 string_buffer[bytes++] = 'u'; 539 string_buffer[bytes++] = 'f'; 540 string_buffer[bytes++] = 'f'; 541 string_buffer[bytes++] = 'f'; 542 string_buffer[bytes++] = 'd'; 543 } 544 else 545 { 546 string_buffer[bytes++] = detail::binary_writer<BasicJsonType, char>::to_char_type('\xEF'); 547 string_buffer[bytes++] = detail::binary_writer<BasicJsonType, char>::to_char_type('\xBF'); 548 string_buffer[bytes++] = detail::binary_writer<BasicJsonType, char>::to_char_type('\xBD'); 549 } 550 551 // write buffer and reset index; there must be 13 bytes 552 // left, as this is the maximal number of bytes to be 553 // written ("\uxxxx\uxxxx\0") for one code point 554 if (string_buffer.size() - bytes < 13) 555 { 556 o->write_characters(string_buffer.data(), bytes); 557 bytes = 0; 558 } 559 560 bytes_after_last_accept = bytes; 561 } 562 563 undumped_chars = 0; 564 565 // continue processing the string 566 state = UTF8_ACCEPT; 567 break; 568 } 569 570 default: // LCOV_EXCL_LINE 571 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE 572 } 573 break; 574 } 575 576 default: // decode found yet incomplete multi-byte code point 577 { 578 if (!ensure_ascii) 579 { 580 // code point will not be escaped - copy byte to buffer 581 string_buffer[bytes++] = s[i]; 582 } 583 ++undumped_chars; 584 break; 585 } 586 } 587 } 588 589 // we finished processing the string 590 if (JSON_HEDLEY_LIKELY(state == UTF8_ACCEPT)) 591 { 592 // write buffer 593 if (bytes > 0) 594 { 595 o->write_characters(string_buffer.data(), bytes); 596 } 597 } 598 else 599 { 600 // we finish reading, but do not accept: string was incomplete 601 switch (error_handler) 602 { 603 case error_handler_t::strict: 604 { 605 JSON_THROW(type_error::create(316, concat("incomplete UTF-8 string; last byte: 0x", hex_bytes(static_cast<std::uint8_t>(s.back() | 0))), nullptr)); 606 } 607 608 case error_handler_t::ignore: 609 { 610 // write all accepted bytes 611 o->write_characters(string_buffer.data(), bytes_after_last_accept); 612 break; 613 } 614 615 case error_handler_t::replace: 616 { 617 // write all accepted bytes 618 o->write_characters(string_buffer.data(), bytes_after_last_accept); 619 // add a replacement character 620 if (ensure_ascii) 621 { 622 o->write_characters("\\ufffd", 6); 623 } 624 else 625 { 626 o->write_characters("\xEF\xBF\xBD", 3); 627 } 628 break; 629 } 630 631 default: // LCOV_EXCL_LINE 632 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE 633 } 634 } 635 } 636 637 private: 638 /*! 639 @brief count digits 640 641 Count the number of decimal (base 10) digits for an input unsigned integer. 642 643 @param[in] x unsigned integer number to count its digits 644 @return number of decimal digits 645 */ count_digits(number_unsigned_t x)646 inline unsigned int count_digits(number_unsigned_t x) noexcept 647 { 648 unsigned int n_digits = 1; 649 for (;;) 650 { 651 if (x < 10) 652 { 653 return n_digits; 654 } 655 if (x < 100) 656 { 657 return n_digits + 1; 658 } 659 if (x < 1000) 660 { 661 return n_digits + 2; 662 } 663 if (x < 10000) 664 { 665 return n_digits + 3; 666 } 667 x = x / 10000u; 668 n_digits += 4; 669 } 670 } 671 672 /*! 673 * @brief convert a byte to a uppercase hex representation 674 * @param[in] byte byte to represent 675 * @return representation ("00".."FF") 676 */ hex_bytes(std::uint8_t byte)677 static std::string hex_bytes(std::uint8_t byte) 678 { 679 std::string result = "FF"; 680 constexpr const char* nibble_to_hex = "0123456789ABCDEF"; 681 result[0] = nibble_to_hex[byte / 16]; 682 result[1] = nibble_to_hex[byte % 16]; 683 return result; 684 } 685 686 // templates to avoid warnings about useless casts 687 template <typename NumberType, enable_if_t<std::is_signed<NumberType>::value, int> = 0> is_negative_number(NumberType x)688 bool is_negative_number(NumberType x) 689 { 690 return x < 0; 691 } 692 693 template < typename NumberType, enable_if_t <std::is_unsigned<NumberType>::value, int > = 0 > is_negative_number(NumberType)694 bool is_negative_number(NumberType /*unused*/) 695 { 696 return false; 697 } 698 699 /*! 700 @brief dump an integer 701 702 Dump a given integer to output stream @a o. Works internally with 703 @a number_buffer. 704 705 @param[in] x integer number (signed or unsigned) to dump 706 @tparam NumberType either @a number_integer_t or @a number_unsigned_t 707 */ 708 template < typename NumberType, detail::enable_if_t < 709 std::is_integral<NumberType>::value || 710 std::is_same<NumberType, number_unsigned_t>::value || 711 std::is_same<NumberType, number_integer_t>::value || 712 std::is_same<NumberType, binary_char_t>::value, 713 int > = 0 > dump_integer(NumberType x)714 void dump_integer(NumberType x) 715 { 716 static constexpr std::array<std::array<char, 2>, 100> digits_to_99 717 { 718 { 719 {{'0', '0'}}, {{'0', '1'}}, {{'0', '2'}}, {{'0', '3'}}, {{'0', '4'}}, {{'0', '5'}}, {{'0', '6'}}, {{'0', '7'}}, {{'0', '8'}}, {{'0', '9'}}, 720 {{'1', '0'}}, {{'1', '1'}}, {{'1', '2'}}, {{'1', '3'}}, {{'1', '4'}}, {{'1', '5'}}, {{'1', '6'}}, {{'1', '7'}}, {{'1', '8'}}, {{'1', '9'}}, 721 {{'2', '0'}}, {{'2', '1'}}, {{'2', '2'}}, {{'2', '3'}}, {{'2', '4'}}, {{'2', '5'}}, {{'2', '6'}}, {{'2', '7'}}, {{'2', '8'}}, {{'2', '9'}}, 722 {{'3', '0'}}, {{'3', '1'}}, {{'3', '2'}}, {{'3', '3'}}, {{'3', '4'}}, {{'3', '5'}}, {{'3', '6'}}, {{'3', '7'}}, {{'3', '8'}}, {{'3', '9'}}, 723 {{'4', '0'}}, {{'4', '1'}}, {{'4', '2'}}, {{'4', '3'}}, {{'4', '4'}}, {{'4', '5'}}, {{'4', '6'}}, {{'4', '7'}}, {{'4', '8'}}, {{'4', '9'}}, 724 {{'5', '0'}}, {{'5', '1'}}, {{'5', '2'}}, {{'5', '3'}}, {{'5', '4'}}, {{'5', '5'}}, {{'5', '6'}}, {{'5', '7'}}, {{'5', '8'}}, {{'5', '9'}}, 725 {{'6', '0'}}, {{'6', '1'}}, {{'6', '2'}}, {{'6', '3'}}, {{'6', '4'}}, {{'6', '5'}}, {{'6', '6'}}, {{'6', '7'}}, {{'6', '8'}}, {{'6', '9'}}, 726 {{'7', '0'}}, {{'7', '1'}}, {{'7', '2'}}, {{'7', '3'}}, {{'7', '4'}}, {{'7', '5'}}, {{'7', '6'}}, {{'7', '7'}}, {{'7', '8'}}, {{'7', '9'}}, 727 {{'8', '0'}}, {{'8', '1'}}, {{'8', '2'}}, {{'8', '3'}}, {{'8', '4'}}, {{'8', '5'}}, {{'8', '6'}}, {{'8', '7'}}, {{'8', '8'}}, {{'8', '9'}}, 728 {{'9', '0'}}, {{'9', '1'}}, {{'9', '2'}}, {{'9', '3'}}, {{'9', '4'}}, {{'9', '5'}}, {{'9', '6'}}, {{'9', '7'}}, {{'9', '8'}}, {{'9', '9'}}, 729 } 730 }; 731 732 // special case for "0" 733 if (x == 0) 734 { 735 o->write_character('0'); 736 return; 737 } 738 739 // use a pointer to fill the buffer 740 auto buffer_ptr = number_buffer.begin(); // NOLINT(llvm-qualified-auto,readability-qualified-auto,cppcoreguidelines-pro-type-vararg,hicpp-vararg) 741 742 number_unsigned_t abs_value; 743 744 unsigned int n_chars{}; 745 746 if (is_negative_number(x)) 747 { 748 *buffer_ptr = '-'; 749 abs_value = remove_sign(static_cast<number_integer_t>(x)); 750 751 // account one more byte for the minus sign 752 n_chars = 1 + count_digits(abs_value); 753 } 754 else 755 { 756 abs_value = static_cast<number_unsigned_t>(x); 757 n_chars = count_digits(abs_value); 758 } 759 760 // spare 1 byte for '\0' 761 JSON_ASSERT(n_chars < number_buffer.size() - 1); 762 763 // jump to the end to generate the string from backward, 764 // so we later avoid reversing the result 765 buffer_ptr += n_chars; 766 767 // Fast int2ascii implementation inspired by "Fastware" talk by Andrei Alexandrescu 768 // See: https://www.youtube.com/watch?v=o4-CwDo2zpg 769 while (abs_value >= 100) 770 { 771 const auto digits_index = static_cast<unsigned>((abs_value % 100)); 772 abs_value /= 100; 773 *(--buffer_ptr) = digits_to_99[digits_index][1]; 774 *(--buffer_ptr) = digits_to_99[digits_index][0]; 775 } 776 777 if (abs_value >= 10) 778 { 779 const auto digits_index = static_cast<unsigned>(abs_value); 780 *(--buffer_ptr) = digits_to_99[digits_index][1]; 781 *(--buffer_ptr) = digits_to_99[digits_index][0]; 782 } 783 else 784 { 785 *(--buffer_ptr) = static_cast<char>('0' + abs_value); 786 } 787 788 o->write_characters(number_buffer.data(), n_chars); 789 } 790 791 /*! 792 @brief dump a floating-point number 793 794 Dump a given floating-point number to output stream @a o. Works internally 795 with @a number_buffer. 796 797 @param[in] x floating-point number to dump 798 */ dump_float(number_float_t x)799 void dump_float(number_float_t x) 800 { 801 // NaN / inf 802 if (!std::isfinite(x)) 803 { 804 o->write_characters("null", 4); 805 return; 806 } 807 808 // If number_float_t is an IEEE-754 single or double precision number, 809 // use the Grisu2 algorithm to produce short numbers which are 810 // guaranteed to round-trip, using strtof and strtod, resp. 811 // 812 // NB: The test below works if <long double> == <double>. 813 static constexpr bool is_ieee_single_or_double 814 = (std::numeric_limits<number_float_t>::is_iec559 && std::numeric_limits<number_float_t>::digits == 24 && std::numeric_limits<number_float_t>::max_exponent == 128) || 815 (std::numeric_limits<number_float_t>::is_iec559 && std::numeric_limits<number_float_t>::digits == 53 && std::numeric_limits<number_float_t>::max_exponent == 1024); 816 817 dump_float(x, std::integral_constant<bool, is_ieee_single_or_double>()); 818 } 819 dump_float(number_float_t x,std::true_type)820 void dump_float(number_float_t x, std::true_type /*is_ieee_single_or_double*/) 821 { 822 auto* begin = number_buffer.data(); 823 auto* end = ::nlohmann::detail::to_chars(begin, begin + number_buffer.size(), x); 824 825 o->write_characters(begin, static_cast<size_t>(end - begin)); 826 } 827 dump_float(number_float_t x,std::false_type)828 void dump_float(number_float_t x, std::false_type /*is_ieee_single_or_double*/) 829 { 830 // get number of digits for a float -> text -> float round-trip 831 static constexpr auto d = std::numeric_limits<number_float_t>::max_digits10; 832 833 // the actual conversion 834 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg,hicpp-vararg) 835 std::ptrdiff_t len = (std::snprintf)(number_buffer.data(), number_buffer.size(), "%.*g", d, x); 836 837 // negative value indicates an error 838 JSON_ASSERT(len > 0); 839 // check if buffer was large enough 840 JSON_ASSERT(static_cast<std::size_t>(len) < number_buffer.size()); 841 842 // erase thousands separator 843 if (thousands_sep != '\0') 844 { 845 // NOLINTNEXTLINE(readability-qualified-auto,llvm-qualified-auto): std::remove returns an iterator, see https://github.com/nlohmann/json/issues/3081 846 const auto end = std::remove(number_buffer.begin(), number_buffer.begin() + len, thousands_sep); 847 std::fill(end, number_buffer.end(), '\0'); 848 JSON_ASSERT((end - number_buffer.begin()) <= len); 849 len = (end - number_buffer.begin()); 850 } 851 852 // convert decimal point to '.' 853 if (decimal_point != '\0' && decimal_point != '.') 854 { 855 // NOLINTNEXTLINE(readability-qualified-auto,llvm-qualified-auto): std::find returns an iterator, see https://github.com/nlohmann/json/issues/3081 856 const auto dec_pos = std::find(number_buffer.begin(), number_buffer.end(), decimal_point); 857 if (dec_pos != number_buffer.end()) 858 { 859 *dec_pos = '.'; 860 } 861 } 862 863 o->write_characters(number_buffer.data(), static_cast<std::size_t>(len)); 864 865 // determine if we need to append ".0" 866 const bool value_is_int_like = 867 std::none_of(number_buffer.begin(), number_buffer.begin() + len + 1, 868 [](char c) 869 { 870 return c == '.' || c == 'e'; 871 }); 872 873 if (value_is_int_like) 874 { 875 o->write_characters(".0", 2); 876 } 877 } 878 879 /*! 880 @brief check whether a string is UTF-8 encoded 881 882 The function checks each byte of a string whether it is UTF-8 encoded. The 883 result of the check is stored in the @a state parameter. The function must 884 be called initially with state 0 (accept). State 1 means the string must 885 be rejected, because the current byte is not allowed. If the string is 886 completely processed, but the state is non-zero, the string ended 887 prematurely; that is, the last byte indicated more bytes should have 888 followed. 889 890 @param[in,out] state the state of the decoding 891 @param[in,out] codep codepoint (valid only if resulting state is UTF8_ACCEPT) 892 @param[in] byte next byte to decode 893 @return new state 894 895 @note The function has been edited: a std::array is used. 896 897 @copyright Copyright (c) 2008-2009 Bjoern Hoehrmann <bjoern@hoehrmann.de> 898 @sa http://bjoern.hoehrmann.de/utf-8/decoder/dfa/ 899 */ decode(std::uint8_t & state,std::uint32_t & codep,const std::uint8_t byte)900 static std::uint8_t decode(std::uint8_t& state, std::uint32_t& codep, const std::uint8_t byte) noexcept 901 { 902 static const std::array<std::uint8_t, 400> utf8d = 903 { 904 { 905 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 00..1F 906 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 20..3F 907 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 40..5F 908 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 60..7F 909 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, // 80..9F 910 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, // A0..BF 911 8, 8, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, // C0..DF 912 0xA, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x4, 0x3, 0x3, // E0..EF 913 0xB, 0x6, 0x6, 0x6, 0x5, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, // F0..FF 914 0x0, 0x1, 0x2, 0x3, 0x5, 0x8, 0x7, 0x1, 0x1, 0x1, 0x4, 0x6, 0x1, 0x1, 0x1, 0x1, // s0..s0 915 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, // s1..s2 916 1, 2, 1, 1, 1, 1, 1, 2, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, // s3..s4 917 1, 2, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 1, 3, 1, 1, 1, 1, 1, 1, // s5..s6 918 1, 3, 1, 1, 1, 1, 1, 3, 1, 3, 1, 1, 1, 1, 1, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 // s7..s8 919 } 920 }; 921 922 JSON_ASSERT(byte < utf8d.size()); 923 const std::uint8_t type = utf8d[byte]; 924 925 codep = (state != UTF8_ACCEPT) 926 ? (byte & 0x3fu) | (codep << 6u) 927 : (0xFFu >> type) & (byte); 928 929 std::size_t index = 256u + static_cast<size_t>(state) * 16u + static_cast<size_t>(type); 930 JSON_ASSERT(index < 400); 931 state = utf8d[index]; 932 return state; 933 } 934 935 /* 936 * Overload to make the compiler happy while it is instantiating 937 * dump_integer for number_unsigned_t. 938 * Must never be called. 939 */ remove_sign(number_unsigned_t x)940 number_unsigned_t remove_sign(number_unsigned_t x) 941 { 942 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE 943 return x; // LCOV_EXCL_LINE 944 } 945 946 /* 947 * Helper function for dump_integer 948 * 949 * This function takes a negative signed integer and returns its absolute 950 * value as unsigned integer. The plus/minus shuffling is necessary as we can 951 * not directly remove the sign of an arbitrary signed integer as the 952 * absolute values of INT_MIN and INT_MAX are usually not the same. See 953 * #1708 for details. 954 */ remove_sign(number_integer_t x)955 inline number_unsigned_t remove_sign(number_integer_t x) noexcept 956 { 957 JSON_ASSERT(x < 0 && x < (std::numeric_limits<number_integer_t>::max)()); // NOLINT(misc-redundant-expression) 958 return static_cast<number_unsigned_t>(-(x + 1)) + 1; 959 } 960 961 private: 962 /// the output of the serializer 963 output_adapter_t<char> o = nullptr; 964 965 /// a (hopefully) large enough character buffer 966 std::array<char, 64> number_buffer{{}}; 967 968 /// the locale 969 const std::lconv* loc = nullptr; 970 /// the locale's thousand separator character 971 const char thousands_sep = '\0'; 972 /// the locale's decimal point character 973 const char decimal_point = '\0'; 974 975 /// string buffer 976 std::array<char, 512> string_buffer{{}}; 977 978 /// the indentation character 979 const char indent_char; 980 /// the indentation string 981 string_t indent_string; 982 983 /// error_handler how to react on decoding errors 984 const error_handler_t error_handler; 985 }; 986 987 } // namespace detail 988 NLOHMANN_JSON_NAMESPACE_END 989