File indexing completed on 2025-01-18 10:02:20
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010 #pragma once
0011
0012 #include <algorithm> // reverse, remove, fill, find, none_of
0013 #include <array> // array
0014 #include <clocale> // localeconv, lconv
0015 #include <cmath> // labs, isfinite, isnan, signbit
0016 #include <cstddef> // size_t, ptrdiff_t
0017 #include <cstdint> // uint8_t
0018 #include <cstdio> // snprintf
0019 #include <limits> // numeric_limits
0020 #include <string> // string, char_traits
0021 #include <iomanip> // setfill, setw
0022 #include <type_traits> // is_same
0023 #include <utility> // move
0024
0025 #include <nlohmann/detail/conversions/to_chars.hpp>
0026 #include <nlohmann/detail/exceptions.hpp>
0027 #include <nlohmann/detail/macro_scope.hpp>
0028 #include <nlohmann/detail/meta/cpp_future.hpp>
0029 #include <nlohmann/detail/output/binary_writer.hpp>
0030 #include <nlohmann/detail/output/output_adapters.hpp>
0031 #include <nlohmann/detail/string_concat.hpp>
0032 #include <nlohmann/detail/value_t.hpp>
0033
0034 NLOHMANN_JSON_NAMESPACE_BEGIN
0035 namespace detail
0036 {
0037
0038
0039
0040
0041
0042
0043 enum class error_handler_t
0044 {
0045 strict,
0046 replace,
0047 ignore
0048 };
0049
0050 template<typename BasicJsonType>
0051 class serializer
0052 {
0053 using string_t = typename BasicJsonType::string_t;
0054 using number_float_t = typename BasicJsonType::number_float_t;
0055 using number_integer_t = typename BasicJsonType::number_integer_t;
0056 using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
0057 using binary_char_t = typename BasicJsonType::binary_t::value_type;
0058 static constexpr std::uint8_t UTF8_ACCEPT = 0;
0059 static constexpr std::uint8_t UTF8_REJECT = 1;
0060
0061 public:
0062
0063
0064
0065
0066
0067 serializer(output_adapter_t<char> s, const char ichar,
0068 error_handler_t error_handler_ = error_handler_t::strict)
0069 : o(std::move(s))
0070 , loc(std::localeconv())
0071 , thousands_sep(loc->thousands_sep == nullptr ? '\0' : std::char_traits<char>::to_char_type(* (loc->thousands_sep)))
0072 , decimal_point(loc->decimal_point == nullptr ? '\0' : std::char_traits<char>::to_char_type(* (loc->decimal_point)))
0073 , indent_char(ichar)
0074 , indent_string(512, indent_char)
0075 , error_handler(error_handler_)
0076 {}
0077
0078
0079 serializer(const serializer&) = delete;
0080 serializer& operator=(const serializer&) = delete;
0081 serializer(serializer&&) = delete;
0082 serializer& operator=(serializer&&) = delete;
0083 ~serializer() = default;
0084
0085
0086
0087
0088
0089
0090
0091
0092
0093
0094
0095
0096
0097
0098
0099
0100
0101
0102
0103
0104
0105
0106
0107 void dump(const BasicJsonType& val,
0108 const bool pretty_print,
0109 const bool ensure_ascii,
0110 const unsigned int indent_step,
0111 const unsigned int current_indent = 0)
0112 {
0113 switch (val.m_type)
0114 {
0115 case value_t::object:
0116 {
0117 if (val.m_value.object->empty())
0118 {
0119 o->write_characters("{}", 2);
0120 return;
0121 }
0122
0123 if (pretty_print)
0124 {
0125 o->write_characters("{\n", 2);
0126
0127
0128 const auto new_indent = current_indent + indent_step;
0129 if (JSON_HEDLEY_UNLIKELY(indent_string.size() < new_indent))
0130 {
0131 indent_string.resize(indent_string.size() * 2, ' ');
0132 }
0133
0134
0135 auto i = val.m_value.object->cbegin();
0136 for (std::size_t cnt = 0; cnt < val.m_value.object->size() - 1; ++cnt, ++i)
0137 {
0138 o->write_characters(indent_string.c_str(), new_indent);
0139 o->write_character('\"');
0140 dump_escaped(i->first, ensure_ascii);
0141 o->write_characters("\": ", 3);
0142 dump(i->second, true, ensure_ascii, indent_step, new_indent);
0143 o->write_characters(",\n", 2);
0144 }
0145
0146
0147 JSON_ASSERT(i != val.m_value.object->cend());
0148 JSON_ASSERT(std::next(i) == val.m_value.object->cend());
0149 o->write_characters(indent_string.c_str(), new_indent);
0150 o->write_character('\"');
0151 dump_escaped(i->first, ensure_ascii);
0152 o->write_characters("\": ", 3);
0153 dump(i->second, true, ensure_ascii, indent_step, new_indent);
0154
0155 o->write_character('\n');
0156 o->write_characters(indent_string.c_str(), current_indent);
0157 o->write_character('}');
0158 }
0159 else
0160 {
0161 o->write_character('{');
0162
0163
0164 auto i = val.m_value.object->cbegin();
0165 for (std::size_t cnt = 0; cnt < val.m_value.object->size() - 1; ++cnt, ++i)
0166 {
0167 o->write_character('\"');
0168 dump_escaped(i->first, ensure_ascii);
0169 o->write_characters("\":", 2);
0170 dump(i->second, false, ensure_ascii, indent_step, current_indent);
0171 o->write_character(',');
0172 }
0173
0174
0175 JSON_ASSERT(i != val.m_value.object->cend());
0176 JSON_ASSERT(std::next(i) == val.m_value.object->cend());
0177 o->write_character('\"');
0178 dump_escaped(i->first, ensure_ascii);
0179 o->write_characters("\":", 2);
0180 dump(i->second, false, ensure_ascii, indent_step, current_indent);
0181
0182 o->write_character('}');
0183 }
0184
0185 return;
0186 }
0187
0188 case value_t::array:
0189 {
0190 if (val.m_value.array->empty())
0191 {
0192 o->write_characters("[]", 2);
0193 return;
0194 }
0195
0196 if (pretty_print)
0197 {
0198 o->write_characters("[\n", 2);
0199
0200
0201 const auto new_indent = current_indent + indent_step;
0202 if (JSON_HEDLEY_UNLIKELY(indent_string.size() < new_indent))
0203 {
0204 indent_string.resize(indent_string.size() * 2, ' ');
0205 }
0206
0207
0208 for (auto i = val.m_value.array->cbegin();
0209 i != val.m_value.array->cend() - 1; ++i)
0210 {
0211 o->write_characters(indent_string.c_str(), new_indent);
0212 dump(*i, true, ensure_ascii, indent_step, new_indent);
0213 o->write_characters(",\n", 2);
0214 }
0215
0216
0217 JSON_ASSERT(!val.m_value.array->empty());
0218 o->write_characters(indent_string.c_str(), new_indent);
0219 dump(val.m_value.array->back(), true, ensure_ascii, indent_step, new_indent);
0220
0221 o->write_character('\n');
0222 o->write_characters(indent_string.c_str(), current_indent);
0223 o->write_character(']');
0224 }
0225 else
0226 {
0227 o->write_character('[');
0228
0229
0230 for (auto i = val.m_value.array->cbegin();
0231 i != val.m_value.array->cend() - 1; ++i)
0232 {
0233 dump(*i, false, ensure_ascii, indent_step, current_indent);
0234 o->write_character(',');
0235 }
0236
0237
0238 JSON_ASSERT(!val.m_value.array->empty());
0239 dump(val.m_value.array->back(), false, ensure_ascii, indent_step, current_indent);
0240
0241 o->write_character(']');
0242 }
0243
0244 return;
0245 }
0246
0247 case value_t::string:
0248 {
0249 o->write_character('\"');
0250 dump_escaped(*val.m_value.string, ensure_ascii);
0251 o->write_character('\"');
0252 return;
0253 }
0254
0255 case value_t::binary:
0256 {
0257 if (pretty_print)
0258 {
0259 o->write_characters("{\n", 2);
0260
0261
0262 const auto new_indent = current_indent + indent_step;
0263 if (JSON_HEDLEY_UNLIKELY(indent_string.size() < new_indent))
0264 {
0265 indent_string.resize(indent_string.size() * 2, ' ');
0266 }
0267
0268 o->write_characters(indent_string.c_str(), new_indent);
0269
0270 o->write_characters("\"bytes\": [", 10);
0271
0272 if (!val.m_value.binary->empty())
0273 {
0274 for (auto i = val.m_value.binary->cbegin();
0275 i != val.m_value.binary->cend() - 1; ++i)
0276 {
0277 dump_integer(*i);
0278 o->write_characters(", ", 2);
0279 }
0280 dump_integer(val.m_value.binary->back());
0281 }
0282
0283 o->write_characters("],\n", 3);
0284 o->write_characters(indent_string.c_str(), new_indent);
0285
0286 o->write_characters("\"subtype\": ", 11);
0287 if (val.m_value.binary->has_subtype())
0288 {
0289 dump_integer(val.m_value.binary->subtype());
0290 }
0291 else
0292 {
0293 o->write_characters("null", 4);
0294 }
0295 o->write_character('\n');
0296 o->write_characters(indent_string.c_str(), current_indent);
0297 o->write_character('}');
0298 }
0299 else
0300 {
0301 o->write_characters("{\"bytes\":[", 10);
0302
0303 if (!val.m_value.binary->empty())
0304 {
0305 for (auto i = val.m_value.binary->cbegin();
0306 i != val.m_value.binary->cend() - 1; ++i)
0307 {
0308 dump_integer(*i);
0309 o->write_character(',');
0310 }
0311 dump_integer(val.m_value.binary->back());
0312 }
0313
0314 o->write_characters("],\"subtype\":", 12);
0315 if (val.m_value.binary->has_subtype())
0316 {
0317 dump_integer(val.m_value.binary->subtype());
0318 o->write_character('}');
0319 }
0320 else
0321 {
0322 o->write_characters("null}", 5);
0323 }
0324 }
0325 return;
0326 }
0327
0328 case value_t::boolean:
0329 {
0330 if (val.m_value.boolean)
0331 {
0332 o->write_characters("true", 4);
0333 }
0334 else
0335 {
0336 o->write_characters("false", 5);
0337 }
0338 return;
0339 }
0340
0341 case value_t::number_integer:
0342 {
0343 dump_integer(val.m_value.number_integer);
0344 return;
0345 }
0346
0347 case value_t::number_unsigned:
0348 {
0349 dump_integer(val.m_value.number_unsigned);
0350 return;
0351 }
0352
0353 case value_t::number_float:
0354 {
0355 dump_float(val.m_value.number_float);
0356 return;
0357 }
0358
0359 case value_t::discarded:
0360 {
0361 o->write_characters("<discarded>", 11);
0362 return;
0363 }
0364
0365 case value_t::null:
0366 {
0367 o->write_characters("null", 4);
0368 return;
0369 }
0370
0371 default:
0372 JSON_ASSERT(false);
0373 }
0374 }
0375
0376 JSON_PRIVATE_UNLESS_TESTED:
0377
0378
0379
0380
0381
0382
0383
0384
0385
0386
0387
0388
0389
0390
0391 void dump_escaped(const string_t& s, const bool ensure_ascii)
0392 {
0393 std::uint32_t codepoint{};
0394 std::uint8_t state = UTF8_ACCEPT;
0395 std::size_t bytes = 0;
0396
0397
0398 std::size_t bytes_after_last_accept = 0;
0399 std::size_t undumped_chars = 0;
0400
0401 for (std::size_t i = 0; i < s.size(); ++i)
0402 {
0403 const auto byte = static_cast<std::uint8_t>(s[i]);
0404
0405 switch (decode(state, codepoint, byte))
0406 {
0407 case UTF8_ACCEPT:
0408 {
0409 switch (codepoint)
0410 {
0411 case 0x08:
0412 {
0413 string_buffer[bytes++] = '\\';
0414 string_buffer[bytes++] = 'b';
0415 break;
0416 }
0417
0418 case 0x09:
0419 {
0420 string_buffer[bytes++] = '\\';
0421 string_buffer[bytes++] = 't';
0422 break;
0423 }
0424
0425 case 0x0A:
0426 {
0427 string_buffer[bytes++] = '\\';
0428 string_buffer[bytes++] = 'n';
0429 break;
0430 }
0431
0432 case 0x0C:
0433 {
0434 string_buffer[bytes++] = '\\';
0435 string_buffer[bytes++] = 'f';
0436 break;
0437 }
0438
0439 case 0x0D:
0440 {
0441 string_buffer[bytes++] = '\\';
0442 string_buffer[bytes++] = 'r';
0443 break;
0444 }
0445
0446 case 0x22:
0447 {
0448 string_buffer[bytes++] = '\\';
0449 string_buffer[bytes++] = '\"';
0450 break;
0451 }
0452
0453 case 0x5C:
0454 {
0455 string_buffer[bytes++] = '\\';
0456 string_buffer[bytes++] = '\\';
0457 break;
0458 }
0459
0460 default:
0461 {
0462
0463
0464 if ((codepoint <= 0x1F) || (ensure_ascii && (codepoint >= 0x7F)))
0465 {
0466 if (codepoint <= 0xFFFF)
0467 {
0468
0469 static_cast<void>((std::snprintf)(string_buffer.data() + bytes, 7, "\\u%04x",
0470 static_cast<std::uint16_t>(codepoint)));
0471 bytes += 6;
0472 }
0473 else
0474 {
0475
0476 static_cast<void>((std::snprintf)(string_buffer.data() + bytes, 13, "\\u%04x\\u%04x",
0477 static_cast<std::uint16_t>(0xD7C0u + (codepoint >> 10u)),
0478 static_cast<std::uint16_t>(0xDC00u + (codepoint & 0x3FFu))));
0479 bytes += 12;
0480 }
0481 }
0482 else
0483 {
0484
0485
0486 string_buffer[bytes++] = s[i];
0487 }
0488 break;
0489 }
0490 }
0491
0492
0493
0494
0495 if (string_buffer.size() - bytes < 13)
0496 {
0497 o->write_characters(string_buffer.data(), bytes);
0498 bytes = 0;
0499 }
0500
0501
0502 bytes_after_last_accept = bytes;
0503 undumped_chars = 0;
0504 break;
0505 }
0506
0507 case UTF8_REJECT:
0508 {
0509 switch (error_handler)
0510 {
0511 case error_handler_t::strict:
0512 {
0513 JSON_THROW(type_error::create(316, concat("invalid UTF-8 byte at index ", std::to_string(i), ": 0x", hex_bytes(byte | 0)), nullptr));
0514 }
0515
0516 case error_handler_t::ignore:
0517 case error_handler_t::replace:
0518 {
0519
0520
0521
0522
0523 if (undumped_chars > 0)
0524 {
0525 --i;
0526 }
0527
0528
0529
0530 bytes = bytes_after_last_accept;
0531
0532 if (error_handler == error_handler_t::replace)
0533 {
0534
0535 if (ensure_ascii)
0536 {
0537 string_buffer[bytes++] = '\\';
0538 string_buffer[bytes++] = 'u';
0539 string_buffer[bytes++] = 'f';
0540 string_buffer[bytes++] = 'f';
0541 string_buffer[bytes++] = 'f';
0542 string_buffer[bytes++] = 'd';
0543 }
0544 else
0545 {
0546 string_buffer[bytes++] = detail::binary_writer<BasicJsonType, char>::to_char_type('\xEF');
0547 string_buffer[bytes++] = detail::binary_writer<BasicJsonType, char>::to_char_type('\xBF');
0548 string_buffer[bytes++] = detail::binary_writer<BasicJsonType, char>::to_char_type('\xBD');
0549 }
0550
0551
0552
0553
0554 if (string_buffer.size() - bytes < 13)
0555 {
0556 o->write_characters(string_buffer.data(), bytes);
0557 bytes = 0;
0558 }
0559
0560 bytes_after_last_accept = bytes;
0561 }
0562
0563 undumped_chars = 0;
0564
0565
0566 state = UTF8_ACCEPT;
0567 break;
0568 }
0569
0570 default:
0571 JSON_ASSERT(false);
0572 }
0573 break;
0574 }
0575
0576 default:
0577 {
0578 if (!ensure_ascii)
0579 {
0580
0581 string_buffer[bytes++] = s[i];
0582 }
0583 ++undumped_chars;
0584 break;
0585 }
0586 }
0587 }
0588
0589
0590 if (JSON_HEDLEY_LIKELY(state == UTF8_ACCEPT))
0591 {
0592
0593 if (bytes > 0)
0594 {
0595 o->write_characters(string_buffer.data(), bytes);
0596 }
0597 }
0598 else
0599 {
0600
0601 switch (error_handler)
0602 {
0603 case error_handler_t::strict:
0604 {
0605 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));
0606 }
0607
0608 case error_handler_t::ignore:
0609 {
0610
0611 o->write_characters(string_buffer.data(), bytes_after_last_accept);
0612 break;
0613 }
0614
0615 case error_handler_t::replace:
0616 {
0617
0618 o->write_characters(string_buffer.data(), bytes_after_last_accept);
0619
0620 if (ensure_ascii)
0621 {
0622 o->write_characters("\\ufffd", 6);
0623 }
0624 else
0625 {
0626 o->write_characters("\xEF\xBF\xBD", 3);
0627 }
0628 break;
0629 }
0630
0631 default:
0632 JSON_ASSERT(false);
0633 }
0634 }
0635 }
0636
0637 private:
0638
0639
0640
0641
0642
0643
0644
0645
0646 inline unsigned int count_digits(number_unsigned_t x) noexcept
0647 {
0648 unsigned int n_digits = 1;
0649 for (;;)
0650 {
0651 if (x < 10)
0652 {
0653 return n_digits;
0654 }
0655 if (x < 100)
0656 {
0657 return n_digits + 1;
0658 }
0659 if (x < 1000)
0660 {
0661 return n_digits + 2;
0662 }
0663 if (x < 10000)
0664 {
0665 return n_digits + 3;
0666 }
0667 x = x / 10000u;
0668 n_digits += 4;
0669 }
0670 }
0671
0672
0673
0674
0675
0676
0677 static std::string hex_bytes(std::uint8_t byte)
0678 {
0679 std::string result = "FF";
0680 constexpr const char* nibble_to_hex = "0123456789ABCDEF";
0681 result[0] = nibble_to_hex[byte / 16];
0682 result[1] = nibble_to_hex[byte % 16];
0683 return result;
0684 }
0685
0686
0687 template <typename NumberType, enable_if_t<std::is_signed<NumberType>::value, int> = 0>
0688 bool is_negative_number(NumberType x)
0689 {
0690 return x < 0;
0691 }
0692
0693 template < typename NumberType, enable_if_t <std::is_unsigned<NumberType>::value, int > = 0 >
0694 bool is_negative_number(NumberType )
0695 {
0696 return false;
0697 }
0698
0699
0700
0701
0702
0703
0704
0705
0706
0707
0708 template < typename NumberType, detail::enable_if_t <
0709 std::is_integral<NumberType>::value ||
0710 std::is_same<NumberType, number_unsigned_t>::value ||
0711 std::is_same<NumberType, number_integer_t>::value ||
0712 std::is_same<NumberType, binary_char_t>::value,
0713 int > = 0 >
0714 void dump_integer(NumberType x)
0715 {
0716 static constexpr std::array<std::array<char, 2>, 100> digits_to_99
0717 {
0718 {
0719 {{'0', '0'}}, {{'0', '1'}}, {{'0', '2'}}, {{'0', '3'}}, {{'0', '4'}}, {{'0', '5'}}, {{'0', '6'}}, {{'0', '7'}}, {{'0', '8'}}, {{'0', '9'}},
0720 {{'1', '0'}}, {{'1', '1'}}, {{'1', '2'}}, {{'1', '3'}}, {{'1', '4'}}, {{'1', '5'}}, {{'1', '6'}}, {{'1', '7'}}, {{'1', '8'}}, {{'1', '9'}},
0721 {{'2', '0'}}, {{'2', '1'}}, {{'2', '2'}}, {{'2', '3'}}, {{'2', '4'}}, {{'2', '5'}}, {{'2', '6'}}, {{'2', '7'}}, {{'2', '8'}}, {{'2', '9'}},
0722 {{'3', '0'}}, {{'3', '1'}}, {{'3', '2'}}, {{'3', '3'}}, {{'3', '4'}}, {{'3', '5'}}, {{'3', '6'}}, {{'3', '7'}}, {{'3', '8'}}, {{'3', '9'}},
0723 {{'4', '0'}}, {{'4', '1'}}, {{'4', '2'}}, {{'4', '3'}}, {{'4', '4'}}, {{'4', '5'}}, {{'4', '6'}}, {{'4', '7'}}, {{'4', '8'}}, {{'4', '9'}},
0724 {{'5', '0'}}, {{'5', '1'}}, {{'5', '2'}}, {{'5', '3'}}, {{'5', '4'}}, {{'5', '5'}}, {{'5', '6'}}, {{'5', '7'}}, {{'5', '8'}}, {{'5', '9'}},
0725 {{'6', '0'}}, {{'6', '1'}}, {{'6', '2'}}, {{'6', '3'}}, {{'6', '4'}}, {{'6', '5'}}, {{'6', '6'}}, {{'6', '7'}}, {{'6', '8'}}, {{'6', '9'}},
0726 {{'7', '0'}}, {{'7', '1'}}, {{'7', '2'}}, {{'7', '3'}}, {{'7', '4'}}, {{'7', '5'}}, {{'7', '6'}}, {{'7', '7'}}, {{'7', '8'}}, {{'7', '9'}},
0727 {{'8', '0'}}, {{'8', '1'}}, {{'8', '2'}}, {{'8', '3'}}, {{'8', '4'}}, {{'8', '5'}}, {{'8', '6'}}, {{'8', '7'}}, {{'8', '8'}}, {{'8', '9'}},
0728 {{'9', '0'}}, {{'9', '1'}}, {{'9', '2'}}, {{'9', '3'}}, {{'9', '4'}}, {{'9', '5'}}, {{'9', '6'}}, {{'9', '7'}}, {{'9', '8'}}, {{'9', '9'}},
0729 }
0730 };
0731
0732
0733 if (x == 0)
0734 {
0735 o->write_character('0');
0736 return;
0737 }
0738
0739
0740 auto buffer_ptr = number_buffer.begin();
0741
0742 number_unsigned_t abs_value;
0743
0744 unsigned int n_chars{};
0745
0746 if (is_negative_number(x))
0747 {
0748 *buffer_ptr = '-';
0749 abs_value = remove_sign(static_cast<number_integer_t>(x));
0750
0751
0752 n_chars = 1 + count_digits(abs_value);
0753 }
0754 else
0755 {
0756 abs_value = static_cast<number_unsigned_t>(x);
0757 n_chars = count_digits(abs_value);
0758 }
0759
0760
0761 JSON_ASSERT(n_chars < number_buffer.size() - 1);
0762
0763
0764
0765 buffer_ptr += n_chars;
0766
0767
0768
0769 while (abs_value >= 100)
0770 {
0771 const auto digits_index = static_cast<unsigned>((abs_value % 100));
0772 abs_value /= 100;
0773 *(--buffer_ptr) = digits_to_99[digits_index][1];
0774 *(--buffer_ptr) = digits_to_99[digits_index][0];
0775 }
0776
0777 if (abs_value >= 10)
0778 {
0779 const auto digits_index = static_cast<unsigned>(abs_value);
0780 *(--buffer_ptr) = digits_to_99[digits_index][1];
0781 *(--buffer_ptr) = digits_to_99[digits_index][0];
0782 }
0783 else
0784 {
0785 *(--buffer_ptr) = static_cast<char>('0' + abs_value);
0786 }
0787
0788 o->write_characters(number_buffer.data(), n_chars);
0789 }
0790
0791
0792
0793
0794
0795
0796
0797
0798
0799 void dump_float(number_float_t x)
0800 {
0801
0802 if (!std::isfinite(x))
0803 {
0804 o->write_characters("null", 4);
0805 return;
0806 }
0807
0808
0809
0810
0811
0812
0813 static constexpr bool is_ieee_single_or_double
0814 = (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) ||
0815 (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);
0816
0817 dump_float(x, std::integral_constant<bool, is_ieee_single_or_double>());
0818 }
0819
0820 void dump_float(number_float_t x, std::true_type )
0821 {
0822 auto* begin = number_buffer.data();
0823 auto* end = ::nlohmann::detail::to_chars(begin, begin + number_buffer.size(), x);
0824
0825 o->write_characters(begin, static_cast<size_t>(end - begin));
0826 }
0827
0828 void dump_float(number_float_t x, std::false_type )
0829 {
0830
0831 static constexpr auto d = std::numeric_limits<number_float_t>::max_digits10;
0832
0833
0834
0835 std::ptrdiff_t len = (std::snprintf)(number_buffer.data(), number_buffer.size(), "%.*g", d, x);
0836
0837
0838 JSON_ASSERT(len > 0);
0839
0840 JSON_ASSERT(static_cast<std::size_t>(len) < number_buffer.size());
0841
0842
0843 if (thousands_sep != '\0')
0844 {
0845
0846 const auto end = std::remove(number_buffer.begin(), number_buffer.begin() + len, thousands_sep);
0847 std::fill(end, number_buffer.end(), '\0');
0848 JSON_ASSERT((end - number_buffer.begin()) <= len);
0849 len = (end - number_buffer.begin());
0850 }
0851
0852
0853 if (decimal_point != '\0' && decimal_point != '.')
0854 {
0855
0856 const auto dec_pos = std::find(number_buffer.begin(), number_buffer.end(), decimal_point);
0857 if (dec_pos != number_buffer.end())
0858 {
0859 *dec_pos = '.';
0860 }
0861 }
0862
0863 o->write_characters(number_buffer.data(), static_cast<std::size_t>(len));
0864
0865
0866 const bool value_is_int_like =
0867 std::none_of(number_buffer.begin(), number_buffer.begin() + len + 1,
0868 [](char c)
0869 {
0870 return c == '.' || c == 'e';
0871 });
0872
0873 if (value_is_int_like)
0874 {
0875 o->write_characters(".0", 2);
0876 }
0877 }
0878
0879
0880
0881
0882
0883
0884
0885
0886
0887
0888
0889
0890
0891
0892
0893
0894
0895
0896
0897
0898
0899
0900 static std::uint8_t decode(std::uint8_t& state, std::uint32_t& codep, const std::uint8_t byte) noexcept
0901 {
0902 static const std::array<std::uint8_t, 400> utf8d =
0903 {
0904 {
0905 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,
0906 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,
0907 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,
0908 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,
0909 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,
0910 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,
0911 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,
0912 0xA, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x4, 0x3, 0x3,
0913 0xB, 0x6, 0x6, 0x6, 0x5, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8,
0914 0x0, 0x1, 0x2, 0x3, 0x5, 0x8, 0x7, 0x1, 0x1, 0x1, 0x4, 0x6, 0x1, 0x1, 0x1, 0x1,
0915 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,
0916 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,
0917 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,
0918 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
0919 }
0920 };
0921
0922 JSON_ASSERT(byte < utf8d.size());
0923 const std::uint8_t type = utf8d[byte];
0924
0925 codep = (state != UTF8_ACCEPT)
0926 ? (byte & 0x3fu) | (codep << 6u)
0927 : (0xFFu >> type) & (byte);
0928
0929 std::size_t index = 256u + static_cast<size_t>(state) * 16u + static_cast<size_t>(type);
0930 JSON_ASSERT(index < 400);
0931 state = utf8d[index];
0932 return state;
0933 }
0934
0935
0936
0937
0938
0939
0940 number_unsigned_t remove_sign(number_unsigned_t x)
0941 {
0942 JSON_ASSERT(false);
0943 return x;
0944 }
0945
0946
0947
0948
0949
0950
0951
0952
0953
0954
0955 inline number_unsigned_t remove_sign(number_integer_t x) noexcept
0956 {
0957 JSON_ASSERT(x < 0 && x < (std::numeric_limits<number_integer_t>::max)());
0958 return static_cast<number_unsigned_t>(-(x + 1)) + 1;
0959 }
0960
0961 private:
0962
0963 output_adapter_t<char> o = nullptr;
0964
0965
0966 std::array<char, 64> number_buffer{{}};
0967
0968
0969 const std::lconv* loc = nullptr;
0970
0971 const char thousands_sep = '\0';
0972
0973 const char decimal_point = '\0';
0974
0975
0976 std::array<char, 512> string_buffer{{}};
0977
0978
0979 const char indent_char;
0980
0981 string_t indent_string;
0982
0983
0984 const error_handler_t error_handler;
0985 };
0986
0987 }
0988 NLOHMANN_JSON_NAMESPACE_END