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;
70 ,
loc(std::localeconv())
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)
113 switch (val.m_data.m_type)
117 if (val.m_data.m_value.object->empty())
119 o->write_characters(
"{}", 2);
125 o->write_characters(
"{\n", 2);
128 const auto new_indent = current_indent + indent_step;
135 auto i = val.m_data.m_value.object->cbegin();
136 for (std::size_t cnt = 0; cnt < val.m_data.m_value.object->size() - 1; ++cnt, ++i)
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);
147 JSON_ASSERT(i != val.m_data.m_value.object->cend());
148 JSON_ASSERT(std::next(i) == val.m_data.m_value.object->cend());
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);
155 o->write_character(
'\n');
157 o->write_character(
'}');
161 o->write_character(
'{');
164 auto i = val.m_data.m_value.object->cbegin();
165 for (std::size_t cnt = 0; cnt < val.m_data.m_value.object->size() - 1; ++cnt, ++i)
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(
',');
175 JSON_ASSERT(i != val.m_data.m_value.object->cend());
176 JSON_ASSERT(std::next(i) == val.m_data.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);
182 o->write_character(
'}');
190 if (val.m_data.m_value.array->empty())
192 o->write_characters(
"[]", 2);
198 o->write_characters(
"[\n", 2);
201 const auto new_indent = current_indent + indent_step;
208 for (
auto i = val.m_data.m_value.array->cbegin();
209 i != val.m_data.m_value.array->cend() - 1; ++i)
212 dump(*i,
true, ensure_ascii, indent_step, new_indent);
213 o->write_characters(
",\n", 2);
217 JSON_ASSERT(!val.m_data.m_value.array->empty());
219 dump(val.m_data.m_value.array->back(),
true, ensure_ascii, indent_step, new_indent);
221 o->write_character(
'\n');
223 o->write_character(
']');
227 o->write_character(
'[');
230 for (
auto i = val.m_data.m_value.array->cbegin();
231 i != val.m_data.m_value.array->cend() - 1; ++i)
233 dump(*i,
false, ensure_ascii, indent_step, current_indent);
234 o->write_character(
',');
238 JSON_ASSERT(!val.m_data.m_value.array->empty());
239 dump(val.m_data.m_value.array->back(),
false, ensure_ascii, indent_step, current_indent);
241 o->write_character(
']');
249 o->write_character(
'\"');
250 dump_escaped(*val.m_data.m_value.string, ensure_ascii);
251 o->write_character(
'\"');
259 o->write_characters(
"{\n", 2);
262 const auto new_indent = current_indent + indent_step;
270 o->write_characters(
"\"bytes\": [", 10);
272 if (!val.m_data.m_value.binary->empty())
274 for (
auto i = val.m_data.m_value.binary->cbegin();
275 i != val.m_data.m_value.binary->cend() - 1; ++i)
278 o->write_characters(
", ", 2);
280 dump_integer(val.m_data.m_value.binary->back());
283 o->write_characters(
"],\n", 3);
286 o->write_characters(
"\"subtype\": ", 11);
287 if (val.m_data.m_value.binary->has_subtype())
289 dump_integer(val.m_data.m_value.binary->subtype());
293 o->write_characters(
"null", 4);
295 o->write_character(
'\n');
297 o->write_character(
'}');
301 o->write_characters(
"{\"bytes\":[", 10);
303 if (!val.m_data.m_value.binary->empty())
305 for (
auto i = val.m_data.m_value.binary->cbegin();
306 i != val.m_data.m_value.binary->cend() - 1; ++i)
309 o->write_character(
',');
311 dump_integer(val.m_data.m_value.binary->back());
314 o->write_characters(
"],\"subtype\":", 12);
315 if (val.m_data.m_value.binary->has_subtype())
317 dump_integer(val.m_data.m_value.binary->subtype());
318 o->write_character(
'}');
322 o->write_characters(
"null}", 5);
330 if (val.m_data.m_value.boolean)
332 o->write_characters(
"true", 4);
336 o->write_characters(
"false", 5);
343 dump_integer(val.m_data.m_value.number_integer);
349 dump_integer(val.m_data.m_value.number_unsigned);
355 dump_float(val.m_data.m_value.number_float);
361 o->write_characters(
"<discarded>", 11);
367 o->write_characters(
"null", 4);
376 JSON_PRIVATE_UNLESS_TESTED:
391 void dump_escaped(
const string_t& s,
const bool ensure_ascii)
393 std::uint32_t codepoint{};
394 std::uint8_t state = UTF8_ACCEPT;
395 std::size_t bytes = 0;
398 std::size_t bytes_after_last_accept = 0;
399 std::size_t undumped_chars = 0;
401 for (std::size_t i = 0; i < s.size(); ++i)
403 const auto byte =
static_cast<std::uint8_t
>(s[i]);
405 switch (decode(state, codepoint,
byte))
464 if ((codepoint <= 0x1F) || (ensure_ascii && (codepoint >= 0x7F)))
466 if (codepoint <= 0xFFFF)
469 static_cast<void>((std::snprintf)(
string_buffer.data() + bytes, 7,
"\\u%04x",
470 static_cast<std::uint16_t
>(codepoint)));
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))));
502 bytes_after_last_accept = bytes;
513 JSON_THROW(type_error::create(316, concat(
"invalid UTF-8 byte at index ", std::to_string(i),
": 0x", hex_bytes(
byte | 0)),
nullptr));
523 if (undumped_chars > 0)
530 bytes = bytes_after_last_accept;
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');
560 bytes_after_last_accept = bytes;
590 if (JSON_HEDLEY_LIKELY(state == UTF8_ACCEPT))
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));
611 o->write_characters(
string_buffer.data(), bytes_after_last_accept);
618 o->write_characters(
string_buffer.data(), bytes_after_last_accept);
622 o->write_characters(
"\\ufffd", 6);
626 o->write_characters(
"\xEF\xBF\xBD", 3);
646 unsigned int count_digits(number_unsigned_t x)
noexcept
648 unsigned int n_digits = 1;
677 static std::string hex_bytes(std::uint8_t
byte)
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];
687 template <typename NumberType, enable_if_t<std::is_signed<NumberType>::value,
int> = 0>
688 bool is_negative_number(NumberType x)
693 template < typename NumberType, enable_if_t <std::is_unsigned<NumberType>::value,
int > = 0 >
694 bool is_negative_number(NumberType )
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,
714 void dump_integer(NumberType x)
716 static constexpr std::array<std::array<char, 2>, 100> digits_to_99
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'}},
735 o->write_character(
'0');
742 number_unsigned_t abs_value;
744 unsigned int n_chars{};
746 if (is_negative_number(x))
749 abs_value = remove_sign(
static_cast<number_integer_t
>(x));
752 n_chars = 1 + count_digits(abs_value);
756 abs_value =
static_cast<number_unsigned_t
>(x);
757 n_chars = count_digits(abs_value);
765 buffer_ptr +=
static_cast<typename decltype(
number_buffer)::difference_type
>(n_chars);
769 while (abs_value >= 100)
771 const auto digits_index =
static_cast<unsigned>((abs_value % 100));
773 *(--buffer_ptr) = digits_to_99[digits_index][1];
774 *(--buffer_ptr) = digits_to_99[digits_index][0];
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];
785 *(--buffer_ptr) =
static_cast<char>(
'0' + abs_value);
799 void dump_float(number_float_t x)
802 if (!std::isfinite(x))
804 o->write_characters(
"null", 4);
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);
817 dump_float(x, std::integral_constant<bool, is_ieee_single_or_double>());
820 void dump_float(number_float_t x, std::true_type )
823 auto* end = ::nlohmann::detail::to_chars(begin, begin +
number_buffer.size(), x);
825 o->write_characters(begin,
static_cast<size_t>(end - begin));
828 void dump_float(number_float_t x, std::false_type )
831 static constexpr auto d = std::numeric_limits<number_float_t>::max_digits10;
838 JSON_ASSERT(len > 0);
840 JSON_ASSERT(
static_cast<std::size_t
>(len) <
number_buffer.size());
863 o->write_characters(
number_buffer.data(),
static_cast<std::size_t
>(len));
866 const bool value_is_int_like =
870 return c ==
'.' || c ==
'e';
873 if (value_is_int_like)
875 o->write_characters(
".0", 2);
900 static std::uint8_t decode(std::uint8_t& state, std::uint32_t& codep,
const std::uint8_t
byte)
noexcept
902 static const std::array<std::uint8_t, 400> utf8d =
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,
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,
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,
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,
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,
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,
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,
912 0xA, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x4, 0x3, 0x3,
913 0xB, 0x6, 0x6, 0x6, 0x5, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8,
914 0x0, 0x1, 0x2, 0x3, 0x5, 0x8, 0x7, 0x1, 0x1, 0x1, 0x4, 0x6, 0x1, 0x1, 0x1, 0x1,
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,
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,
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,
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
922 JSON_ASSERT(
byte < utf8d.size());
923 const std::uint8_t type = utf8d[byte];
925 codep = (state != UTF8_ACCEPT)
926 ? (
byte & 0x3fu) | (codep << 6u)
927 : (0xFFu >> type) & (byte);
929 const std::size_t index = 256u + (
static_cast<size_t>(state) * 16u) +
static_cast<size_t>(type);
930 JSON_ASSERT(index < utf8d.size());
931 state = utf8d[index];
940 number_unsigned_t remove_sign(number_unsigned_t x)
955 number_unsigned_t remove_sign(number_integer_t x)
noexcept
957 JSON_ASSERT(x < 0 && x < (std::numeric_limits<number_integer_t>::max)());
958 return static_cast<number_unsigned_t
>(-(x + 1)) + 1;
969 const std::lconv*
loc =
nullptr;