42 using string_t =
typename BasicJsonType::string_t;
43 using number_float_t =
typename BasicJsonType::number_float_t;
44 using number_integer_t =
typename BasicJsonType::number_integer_t;
45 using number_unsigned_t =
typename BasicJsonType::number_unsigned_t;
46 using binary_char_t =
typename BasicJsonType::binary_t::value_type;
47 static constexpr std::uint8_t UTF8_ACCEPT = 0;
48 static constexpr std::uint8_t UTF8_REJECT = 1;
59 ,
loc(std::localeconv())
96 void dump(
const BasicJsonType& val,
97 const bool pretty_print,
98 const bool ensure_ascii,
99 const unsigned int indent_step,
100 const unsigned int current_indent = 0)
106 if (val.m_value.object->empty())
108 o->write_characters(
"{}", 2);
114 o->write_characters(
"{\n", 2);
117 const auto new_indent = current_indent + indent_step;
124 auto i = val.m_value.object->cbegin();
125 for (std::size_t cnt = 0; cnt < val.m_value.object->size() - 1; ++cnt, ++i)
128 o->write_character(
'\"');
129 dump_escaped(i->first, ensure_ascii);
130 o->write_characters(
"\": ", 3);
131 dump(i->second,
true, ensure_ascii, indent_step, new_indent);
132 o->write_characters(
",\n", 2);
136 JSON_ASSERT(i != val.m_value.object->cend());
137 JSON_ASSERT(std::next(i) == val.m_value.object->cend());
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);
144 o->write_character(
'\n');
146 o->write_character(
'}');
150 o->write_character(
'{');
153 auto i = val.m_value.object->cbegin();
154 for (std::size_t cnt = 0; cnt < val.m_value.object->size() - 1; ++cnt, ++i)
156 o->write_character(
'\"');
157 dump_escaped(i->first, ensure_ascii);
158 o->write_characters(
"\":", 2);
159 dump(i->second,
false, ensure_ascii, indent_step, current_indent);
160 o->write_character(
',');
164 JSON_ASSERT(i != val.m_value.object->cend());
165 JSON_ASSERT(std::next(i) == val.m_value.object->cend());
166 o->write_character(
'\"');
167 dump_escaped(i->first, ensure_ascii);
168 o->write_characters(
"\":", 2);
169 dump(i->second,
false, ensure_ascii, indent_step, current_indent);
171 o->write_character(
'}');
179 if (val.m_value.array->empty())
181 o->write_characters(
"[]", 2);
187 o->write_characters(
"[\n", 2);
190 const auto new_indent = current_indent + indent_step;
197 for (
auto i = val.m_value.array->cbegin();
198 i != val.m_value.array->cend() - 1; ++i)
201 dump(*i,
true, ensure_ascii, indent_step, new_indent);
202 o->write_characters(
",\n", 2);
206 JSON_ASSERT(!val.m_value.array->empty());
208 dump(val.m_value.array->back(),
true, ensure_ascii, indent_step, new_indent);
210 o->write_character(
'\n');
212 o->write_character(
']');
216 o->write_character(
'[');
219 for (
auto i = val.m_value.array->cbegin();
220 i != val.m_value.array->cend() - 1; ++i)
222 dump(*i,
false, ensure_ascii, indent_step, current_indent);
223 o->write_character(
',');
227 JSON_ASSERT(!val.m_value.array->empty());
228 dump(val.m_value.array->back(),
false, ensure_ascii, indent_step, current_indent);
230 o->write_character(
']');
238 o->write_character(
'\"');
239 dump_escaped(*val.m_value.string, ensure_ascii);
240 o->write_character(
'\"');
248 o->write_characters(
"{\n", 2);
251 const auto new_indent = current_indent + indent_step;
259 o->write_characters(
"\"bytes\": [", 10);
261 if (!val.m_value.binary->empty())
263 for (
auto i = val.m_value.binary->cbegin();
264 i != val.m_value.binary->cend() - 1; ++i)
267 o->write_characters(
", ", 2);
269 dump_integer(val.m_value.binary->back());
272 o->write_characters(
"],\n", 3);
275 o->write_characters(
"\"subtype\": ", 11);
276 if (val.m_value.binary->has_subtype())
278 dump_integer(val.m_value.binary->subtype());
282 o->write_characters(
"null", 4);
284 o->write_character(
'\n');
286 o->write_character(
'}');
290 o->write_characters(
"{\"bytes\":[", 10);
292 if (!val.m_value.binary->empty())
294 for (
auto i = val.m_value.binary->cbegin();
295 i != val.m_value.binary->cend() - 1; ++i)
298 o->write_character(
',');
300 dump_integer(val.m_value.binary->back());
303 o->write_characters(
"],\"subtype\":", 12);
304 if (val.m_value.binary->has_subtype())
306 dump_integer(val.m_value.binary->subtype());
307 o->write_character(
'}');
311 o->write_characters(
"null}", 5);
319 if (val.m_value.boolean)
321 o->write_characters(
"true", 4);
325 o->write_characters(
"false", 5);
332 dump_integer(val.m_value.number_integer);
338 dump_integer(val.m_value.number_unsigned);
344 dump_float(val.m_value.number_float);
350 o->write_characters(
"<discarded>", 11);
356 o->write_characters(
"null", 4);
365 JSON_PRIVATE_UNLESS_TESTED:
380 void dump_escaped(
const string_t& s,
const bool ensure_ascii)
382 std::uint32_t codepoint{};
383 std::uint8_t state = UTF8_ACCEPT;
384 std::size_t bytes = 0;
387 std::size_t bytes_after_last_accept = 0;
388 std::size_t undumped_chars = 0;
390 for (std::size_t i = 0; i < s.size(); ++i)
392 const auto byte =
static_cast<std::uint8_t
>(s[i]);
394 switch (decode(state, codepoint,
byte))
453 if ((codepoint <= 0x1F) || (ensure_ascii && (codepoint >= 0x7F)))
455 if (codepoint <= 0xFFFF)
459 static_cast<std::uint16_t
>(codepoint));
465 (std::snprintf)(
string_buffer.data() + bytes, 13,
"\\u%04x\\u%04x",
466 static_cast<std::uint16_t
>(0xD7C0u + (codepoint >> 10u)),
467 static_cast<std::uint16_t
>(0xDC00u + (codepoint & 0x3FFu)));
491 bytes_after_last_accept = bytes;
502 std::string sn(9,
'\0');
504 (std::snprintf)(&sn[0], sn.size(),
"%.2X", byte);
505 JSON_THROW(type_error::create(316,
"invalid UTF-8 byte at index " + std::to_string(i) +
": 0x" + sn, BasicJsonType()));
515 if (undumped_chars > 0)
522 bytes = bytes_after_last_accept;
538 string_buffer[bytes++] = detail::binary_writer<BasicJsonType, char>::to_char_type(
'\xEF');
539 string_buffer[bytes++] = detail::binary_writer<BasicJsonType, char>::to_char_type(
'\xBF');
540 string_buffer[bytes++] = detail::binary_writer<BasicJsonType, char>::to_char_type(
'\xBD');
552 bytes_after_last_accept = bytes;
582 if (JSON_HEDLEY_LIKELY(state == UTF8_ACCEPT))
597 std::string sn(9,
'\0');
599 (std::snprintf)(&sn[0], sn.size(),
"%.2X",
static_cast<std::uint8_t
>(s.back()));
600 JSON_THROW(type_error::create(316,
"incomplete UTF-8 string; last byte: 0x" + sn, BasicJsonType()));
606 o->write_characters(
string_buffer.data(), bytes_after_last_accept);
613 o->write_characters(
string_buffer.data(), bytes_after_last_accept);
617 o->write_characters(
"\\ufffd", 6);
621 o->write_characters(
"\xEF\xBF\xBD", 3);
641 inline unsigned int count_digits(number_unsigned_t x)
noexcept
643 unsigned int n_digits = 1;
676 template <
typename NumberType, detail::enable_if_t <
677 std::is_integral<NumberType>::value ||
678 std::is_same<NumberType, number_unsigned_t>::value ||
679 std::is_same<NumberType, number_integer_t>::value ||
680 std::is_same<NumberType, binary_char_t>::value,
682 void dump_integer(NumberType x)
684 static constexpr std::array<std::array<char, 2>, 100> digits_to_99
687 {{
'0',
'0'}}, {{
'0',
'1'}}, {{
'0',
'2'}}, {{
'0',
'3'}}, {{
'0',
'4'}}, {{
'0',
'5'}}, {{
'0',
'6'}}, {{
'0',
'7'}}, {{
'0',
'8'}}, {{
'0',
'9'}},
688 {{
'1',
'0'}}, {{
'1',
'1'}}, {{
'1',
'2'}}, {{
'1',
'3'}}, {{
'1',
'4'}}, {{
'1',
'5'}}, {{
'1',
'6'}}, {{
'1',
'7'}}, {{
'1',
'8'}}, {{
'1',
'9'}},
689 {{
'2',
'0'}}, {{
'2',
'1'}}, {{
'2',
'2'}}, {{
'2',
'3'}}, {{
'2',
'4'}}, {{
'2',
'5'}}, {{
'2',
'6'}}, {{
'2',
'7'}}, {{
'2',
'8'}}, {{
'2',
'9'}},
690 {{
'3',
'0'}}, {{
'3',
'1'}}, {{
'3',
'2'}}, {{
'3',
'3'}}, {{
'3',
'4'}}, {{
'3',
'5'}}, {{
'3',
'6'}}, {{
'3',
'7'}}, {{
'3',
'8'}}, {{
'3',
'9'}},
691 {{
'4',
'0'}}, {{
'4',
'1'}}, {{
'4',
'2'}}, {{
'4',
'3'}}, {{
'4',
'4'}}, {{
'4',
'5'}}, {{
'4',
'6'}}, {{
'4',
'7'}}, {{
'4',
'8'}}, {{
'4',
'9'}},
692 {{
'5',
'0'}}, {{
'5',
'1'}}, {{
'5',
'2'}}, {{
'5',
'3'}}, {{
'5',
'4'}}, {{
'5',
'5'}}, {{
'5',
'6'}}, {{
'5',
'7'}}, {{
'5',
'8'}}, {{
'5',
'9'}},
693 {{
'6',
'0'}}, {{
'6',
'1'}}, {{
'6',
'2'}}, {{
'6',
'3'}}, {{
'6',
'4'}}, {{
'6',
'5'}}, {{
'6',
'6'}}, {{
'6',
'7'}}, {{
'6',
'8'}}, {{
'6',
'9'}},
694 {{
'7',
'0'}}, {{
'7',
'1'}}, {{
'7',
'2'}}, {{
'7',
'3'}}, {{
'7',
'4'}}, {{
'7',
'5'}}, {{
'7',
'6'}}, {{
'7',
'7'}}, {{
'7',
'8'}}, {{
'7',
'9'}},
695 {{
'8',
'0'}}, {{
'8',
'1'}}, {{
'8',
'2'}}, {{
'8',
'3'}}, {{
'8',
'4'}}, {{
'8',
'5'}}, {{
'8',
'6'}}, {{
'8',
'7'}}, {{
'8',
'8'}}, {{
'8',
'9'}},
696 {{
'9',
'0'}}, {{
'9',
'1'}}, {{
'9',
'2'}}, {{
'9',
'3'}}, {{
'9',
'4'}}, {{
'9',
'5'}}, {{
'9',
'6'}}, {{
'9',
'7'}}, {{
'9',
'8'}}, {{
'9',
'9'}},
703 o->write_character(
'0');
710 const bool is_negative = std::is_signed<NumberType>::value && !(x >= 0);
711 number_unsigned_t abs_value;
713 unsigned int n_chars{};
718 abs_value = remove_sign(
static_cast<number_integer_t
>(x));
721 n_chars = 1 + count_digits(abs_value);
725 abs_value =
static_cast<number_unsigned_t
>(x);
726 n_chars = count_digits(abs_value);
734 buffer_ptr += n_chars;
738 while (abs_value >= 100)
740 const auto digits_index =
static_cast<unsigned>((abs_value % 100));
742 *(--buffer_ptr) = digits_to_99[digits_index][1];
743 *(--buffer_ptr) = digits_to_99[digits_index][0];
748 const auto digits_index =
static_cast<unsigned>(abs_value);
749 *(--buffer_ptr) = digits_to_99[digits_index][1];
750 *(--buffer_ptr) = digits_to_99[digits_index][0];
754 *(--buffer_ptr) =
static_cast<char>(
'0' + abs_value);
768 void dump_float(number_float_t x)
771 if (!std::isfinite(x))
773 o->write_characters(
"null", 4);
782 static constexpr bool is_ieee_single_or_double
783 = (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) ||
784 (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);
786 dump_float(x, std::integral_constant<bool, is_ieee_single_or_double>());
789 void dump_float(number_float_t x, std::true_type )
794 o->write_characters(begin,
static_cast<size_t>(end - begin));
797 void dump_float(number_float_t x, std::false_type )
800 static constexpr auto d = std::numeric_limits<number_float_t>::max_digits10;
807 JSON_ASSERT(len > 0);
809 JSON_ASSERT(
static_cast<std::size_t
>(len) <
number_buffer.size());
831 o->write_characters(
number_buffer.data(),
static_cast<std::size_t
>(len));
834 const bool value_is_int_like =
838 return c ==
'.' || c ==
'e';
841 if (value_is_int_like)
843 o->write_characters(
".0", 2);
868 static std::uint8_t decode(std::uint8_t& state, std::uint32_t& codep,
const std::uint8_t
byte)
noexcept
870 static const std::array<std::uint8_t, 400> utf8d =
873 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,
874 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,
875 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,
876 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,
877 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,
878 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,
879 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,
880 0xA, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x4, 0x3, 0x3,
881 0xB, 0x6, 0x6, 0x6, 0x5, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8,
882 0x0, 0x1, 0x2, 0x3, 0x5, 0x8, 0x7, 0x1, 0x1, 0x1, 0x4, 0x6, 0x1, 0x1, 0x1, 0x1,
883 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,
884 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,
885 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,
886 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
890 JSON_ASSERT(
byte < utf8d.size());
891 const std::uint8_t type = utf8d[byte];
893 codep = (state != UTF8_ACCEPT)
894 ? (
byte & 0x3fu) | (codep << 6u)
895 : (0xFFu >> type) & (byte);
897 std::size_t index = 256u +
static_cast<size_t>(state) * 16u +
static_cast<size_t>(type);
898 JSON_ASSERT(index < 400);
899 state = utf8d[index];
908 number_unsigned_t remove_sign(number_unsigned_t x)
923 inline number_unsigned_t remove_sign(number_integer_t x)
noexcept
925 JSON_ASSERT(x < 0 && x < (std::numeric_limits<number_integer_t>::max)());
926 return static_cast<number_unsigned_t
>(-(x + 1)) + 1;
931 output_adapter_t<char> o =
nullptr;
937 const std::lconv*
loc =
nullptr;