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;
69 size_t indent_init_len = 512)
71 , loc(
std::localeconv())
72 , thousands_sep(loc->thousands_sep == nullptr ?
'\0' :
std::
char_traits<char>::to_char_type(* (loc->thousands_sep)))
73 , decimal_point(loc->decimal_point == nullptr ?
'\0' :
std::
char_traits<char>::to_char_type(* (loc->decimal_point)))
75 , indent_string(indent_init_len, indent_char)
76 , error_handler(error_handler_)
80 size_t indent_init_len = 512,
114 void dump(
const BasicJsonType& val,
115 const bool pretty_print,
116 const bool ensure_ascii,
117 const unsigned int indent_step,
118 const unsigned int current_indent = 0)
120 switch (val.m_data.m_type)
124 if (val.m_data.m_value.object->empty())
126 o->write_characters(
"{}", 2);
132 o->write_characters(
"{\n", 2);
135 const auto new_indent = current_indent + indent_step;
138 indent_string.resize(indent_string.size() * 2,
' ');
142 auto i = val.m_data.m_value.object->cbegin();
143 for (std::size_t cnt = 0; cnt < val.m_data.m_value.object->size() - 1; ++cnt, ++i)
145 o->write_characters(indent_string.c_str(), new_indent);
146 o->write_character(
'\"');
148 o->write_characters(
"\": ", 3);
149 dump(i->second,
true, ensure_ascii, indent_step, new_indent);
150 o->write_characters(
",\n", 2);
154 JSON_ASSERT(i != val.m_data.m_value.object->cend());
155 JSON_ASSERT(std::next(i) == val.m_data.m_value.object->cend());
156 o->write_characters(indent_string.c_str(), new_indent);
157 o->write_character(
'\"');
159 o->write_characters(
"\": ", 3);
160 dump(i->second,
true, ensure_ascii, indent_step, new_indent);
162 o->write_character(
'\n');
163 o->write_characters(indent_string.c_str(), current_indent);
164 o->write_character(
'}');
168 o->write_character(
'{');
171 auto i = val.m_data.m_value.object->cbegin();
172 for (std::size_t cnt = 0; cnt < val.m_data.m_value.object->size() - 1; ++cnt, ++i)
174 o->write_character(
'\"');
176 o->write_characters(
"\":", 2);
177 dump(i->second,
false, ensure_ascii, indent_step, current_indent);
178 o->write_character(
',');
182 JSON_ASSERT(i != val.m_data.m_value.object->cend());
183 JSON_ASSERT(std::next(i) == val.m_data.m_value.object->cend());
184 o->write_character(
'\"');
186 o->write_characters(
"\":", 2);
187 dump(i->second,
false, ensure_ascii, indent_step, current_indent);
189 o->write_character(
'}');
197 if (val.m_data.m_value.array->empty())
199 o->write_characters(
"[]", 2);
205 o->write_characters(
"[\n", 2);
208 const auto new_indent = current_indent + indent_step;
211 indent_string.resize(indent_string.size() * 2,
' ');
215 for (
auto i = val.m_data.m_value.array->cbegin();
216 i != val.m_data.m_value.array->cend() - 1; ++i)
218 o->write_characters(indent_string.c_str(), new_indent);
219 dump(*i,
true, ensure_ascii, indent_step, new_indent);
220 o->write_characters(
",\n", 2);
225 o->write_characters(indent_string.c_str(), new_indent);
226 dump(val.m_data.m_value.array->back(),
true, ensure_ascii, indent_step, new_indent);
228 o->write_character(
'\n');
229 o->write_characters(indent_string.c_str(), current_indent);
230 o->write_character(
']');
234 o->write_character(
'[');
237 for (
auto i = val.m_data.m_value.array->cbegin();
238 i != val.m_data.m_value.array->cend() - 1; ++i)
240 dump(*i,
false, ensure_ascii, indent_step, current_indent);
241 o->write_character(
',');
246 dump(val.m_data.m_value.array->back(),
false, ensure_ascii, indent_step, current_indent);
248 o->write_character(
']');
256 o->write_character(
'\"');
258 o->write_character(
'\"');
266 o->write_characters(
"{\n", 2);
269 const auto new_indent = current_indent + indent_step;
272 indent_string.resize(indent_string.size() * 2,
' ');
275 o->write_characters(indent_string.c_str(), new_indent);
277 o->write_characters(
"\"bytes\": [", 10);
279 if (!val.m_data.m_value.binary->empty())
281 for (
auto i = val.m_data.m_value.binary->cbegin();
282 i != val.m_data.m_value.binary->cend() - 1; ++i)
285 o->write_characters(
", ", 2);
290 o->write_characters(
"],\n", 3);
291 o->write_characters(indent_string.c_str(), new_indent);
293 o->write_characters(
"\"subtype\": ", 11);
294 if (val.m_data.m_value.binary->has_subtype())
300 o->write_characters(
"null", 4);
302 o->write_character(
'\n');
303 o->write_characters(indent_string.c_str(), current_indent);
304 o->write_character(
'}');
308 o->write_characters(
"{\"bytes\":[", 10);
310 if (!val.m_data.m_value.binary->empty())
312 for (
auto i = val.m_data.m_value.binary->cbegin();
313 i != val.m_data.m_value.binary->cend() - 1; ++i)
316 o->write_character(
',');
321 o->write_characters(
"],\"subtype\":", 12);
322 if (val.m_data.m_value.binary->has_subtype())
325 o->write_character(
'}');
329 o->write_characters(
"null}", 5);
337 if (val.m_data.m_value.boolean)
339 o->write_characters(
"true", 4);
343 o->write_characters(
"false", 5);
368 o->write_characters(
"<discarded>", 11);
374 o->write_characters(
"null", 4);
400 std::uint32_t codepoint{};
401 std::uint8_t
state = UTF8_ACCEPT;
402 std::size_t
bytes = 0;
405 std::size_t bytes_after_last_accept = 0;
406 std::size_t undumped_chars = 0;
408 for (std::size_t i = 0; i < s.size(); ++i)
410 const auto byte =
static_cast<std::uint8_t
>(s[i]);
412 switch (decode(
state, codepoint,
byte))
471 if ((codepoint <= 0x1F) || (ensure_ascii && (codepoint >= 0x7F)))
473 if (codepoint <= 0xFFFF)
477 static_cast<std::uint16_t
>(codepoint)));
484 static_cast<std::uint16_t
>(0xD7C0u + (codepoint >> 10u)),
485 static_cast<std::uint16_t
>(0xDC00u + (codepoint & 0x3FFu))));
509 bytes_after_last_accept =
bytes;
516 switch (error_handler)
530 if (undumped_chars > 0)
537 bytes = bytes_after_last_accept;
567 bytes_after_last_accept =
bytes;
608 switch (error_handler)
618 o->write_characters(
string_buffer.data(), bytes_after_last_accept);
625 o->write_characters(
string_buffer.data(), bytes_after_last_accept);
629 o->write_characters(
"\\ufffd", 6);
633 o->write_characters(
"\xEF\xBF\xBD", 3);
653 inline unsigned int count_digits(number_unsigned_t x)
noexcept
655 unsigned int n_digits = 1;
684 static std::string hex_bytes(std::uint8_t
byte)
686 std::string result =
"FF";
687 constexpr const char* nibble_to_hex =
"0123456789ABCDEF";
688 result[0] = nibble_to_hex[
byte / 16];
689 result[1] = nibble_to_hex[
byte % 16];
694 template <typename NumberType, enable_if_t<std::is_signed<NumberType>::value,
int> = 0>
695 bool is_negative_number(NumberType x)
700 template < typename NumberType, enable_if_t <std::is_unsigned<NumberType>::value,
int > = 0 >
701 bool is_negative_number(NumberType )
717 std::is_integral<NumberType>::value ||
718 std::is_same<NumberType, number_unsigned_t>::value ||
719 std::is_same<NumberType, number_integer_t>::value ||
720 std::is_same<NumberType, binary_char_t>::value,
724 static constexpr std::array<std::array<char, 2>, 100> digits_to_99
727 {{
'0',
'0'}}, {{
'0',
'1'}}, {{
'0',
'2'}}, {{
'0',
'3'}}, {{
'0',
'4'}}, {{
'0',
'5'}}, {{
'0',
'6'}}, {{
'0',
'7'}}, {{
'0',
'8'}}, {{
'0',
'9'}},
728 {{
'1',
'0'}}, {{
'1',
'1'}}, {{
'1',
'2'}}, {{
'1',
'3'}}, {{
'1',
'4'}}, {{
'1',
'5'}}, {{
'1',
'6'}}, {{
'1',
'7'}}, {{
'1',
'8'}}, {{
'1',
'9'}},
729 {{
'2',
'0'}}, {{
'2',
'1'}}, {{
'2',
'2'}}, {{
'2',
'3'}}, {{
'2',
'4'}}, {{
'2',
'5'}}, {{
'2',
'6'}}, {{
'2',
'7'}}, {{
'2',
'8'}}, {{
'2',
'9'}},
730 {{
'3',
'0'}}, {{
'3',
'1'}}, {{
'3',
'2'}}, {{
'3',
'3'}}, {{
'3',
'4'}}, {{
'3',
'5'}}, {{
'3',
'6'}}, {{
'3',
'7'}}, {{
'3',
'8'}}, {{
'3',
'9'}},
731 {{
'4',
'0'}}, {{
'4',
'1'}}, {{
'4',
'2'}}, {{
'4',
'3'}}, {{
'4',
'4'}}, {{
'4',
'5'}}, {{
'4',
'6'}}, {{
'4',
'7'}}, {{
'4',
'8'}}, {{
'4',
'9'}},
732 {{
'5',
'0'}}, {{
'5',
'1'}}, {{
'5',
'2'}}, {{
'5',
'3'}}, {{
'5',
'4'}}, {{
'5',
'5'}}, {{
'5',
'6'}}, {{
'5',
'7'}}, {{
'5',
'8'}}, {{
'5',
'9'}},
733 {{
'6',
'0'}}, {{
'6',
'1'}}, {{
'6',
'2'}}, {{
'6',
'3'}}, {{
'6',
'4'}}, {{
'6',
'5'}}, {{
'6',
'6'}}, {{
'6',
'7'}}, {{
'6',
'8'}}, {{
'6',
'9'}},
734 {{
'7',
'0'}}, {{
'7',
'1'}}, {{
'7',
'2'}}, {{
'7',
'3'}}, {{
'7',
'4'}}, {{
'7',
'5'}}, {{
'7',
'6'}}, {{
'7',
'7'}}, {{
'7',
'8'}}, {{
'7',
'9'}},
735 {{
'8',
'0'}}, {{
'8',
'1'}}, {{
'8',
'2'}}, {{
'8',
'3'}}, {{
'8',
'4'}}, {{
'8',
'5'}}, {{
'8',
'6'}}, {{
'8',
'7'}}, {{
'8',
'8'}}, {{
'8',
'9'}},
736 {{
'9',
'0'}}, {{
'9',
'1'}}, {{
'9',
'2'}}, {{
'9',
'3'}}, {{
'9',
'4'}}, {{
'9',
'5'}}, {{
'9',
'6'}}, {{
'9',
'7'}}, {{
'9',
'8'}}, {{
'9',
'9'}},
743 o->write_character(
'0');
748 auto buffer_ptr = number_buffer.begin();
750 number_unsigned_t abs_value;
752 unsigned int n_chars{};
754 if (is_negative_number(x))
757 abs_value = remove_sign(
static_cast<number_integer_t
>(x));
760 n_chars = 1 + count_digits(abs_value);
764 abs_value =
static_cast<number_unsigned_t
>(x);
765 n_chars = count_digits(abs_value);
773 buffer_ptr += n_chars;
777 while (abs_value >= 100)
779 const auto digits_index =
static_cast<unsigned>((abs_value % 100));
781 *(--buffer_ptr) = digits_to_99[digits_index][1];
782 *(--buffer_ptr) = digits_to_99[digits_index][0];
787 const auto digits_index =
static_cast<unsigned>(abs_value);
788 *(--buffer_ptr) = digits_to_99[digits_index][1];
789 *(--buffer_ptr) = digits_to_99[digits_index][0];
793 *(--buffer_ptr) =
static_cast<char>(
'0' + abs_value);
796 o->write_characters(number_buffer.data(), n_chars);
810 if (!std::isfinite(x))
812 o->write_characters(
"null", 4);
821 static constexpr bool is_ieee_single_or_double
822 = (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) ||
823 (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);
825 dump_float(x, std::integral_constant<bool, is_ieee_single_or_double>());
830 auto* begin = number_buffer.data();
831 auto* end = ::wpi::detail::to_chars(begin, begin + number_buffer.size(), x);
833 o->write_characters(begin,
static_cast<size_t>(end - begin));
839 static constexpr auto d = std::numeric_limits<number_float_t>::max_digits10;
843 std::ptrdiff_t len = (std::snprintf)(number_buffer.data(), number_buffer.size(),
"%.*g", d, x);
848 JSON_ASSERT(
static_cast<std::size_t
>(len) < number_buffer.size());
851 if (thousands_sep !=
'\0')
854 const auto end = std::remove(number_buffer.begin(), number_buffer.begin() + len, thousands_sep);
855 std::fill(end, number_buffer.end(),
'\0');
857 len = (end - number_buffer.begin());
861 if (decimal_point !=
'\0' && decimal_point !=
'.')
864 const auto dec_pos = std::find(number_buffer.begin(), number_buffer.end(), decimal_point);
865 if (dec_pos != number_buffer.end())
871 o->write_characters(number_buffer.data(),
static_cast<std::size_t
>(len));
874 const bool value_is_int_like =
875 std::none_of(number_buffer.begin(), number_buffer.begin() + len + 1,
878 return c ==
'.' || c ==
'e';
881 if (value_is_int_like)
883 o->write_characters(
".0", 2);
909 static std::uint8_t decode(std::uint8_t&
state, std::uint32_t& codep,
const std::uint8_t
byte)
noexcept
911 static const std::array<std::uint8_t, 400> utf8d =
914 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,
915 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,
916 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,
917 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,
918 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,
919 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,
920 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,
921 0xA, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x4, 0x3, 0x3,
922 0xB, 0x6, 0x6, 0x6, 0x5, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8,
923 0x0, 0x1, 0x2, 0x3, 0x5, 0x8, 0x7, 0x1, 0x1, 0x1, 0x4, 0x6, 0x1, 0x1, 0x1, 0x1,
924 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,
925 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,
926 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,
927 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
932 const std::uint8_t type = utf8d[byte];
934 codep = (
state != UTF8_ACCEPT)
935 ? (
byte & 0x3fu) | (codep << 6u)
936 : (0xFFu >> type) & (byte);
938 const std::size_t
index = 256u +
static_cast<size_t>(
state) * 16u +
static_cast<size_t>(
type);
949 number_unsigned_t remove_sign(number_unsigned_t x)
964 inline number_unsigned_t remove_sign(number_integer_t x)
noexcept
966 JSON_ASSERT(x < 0 && x < (std::numeric_limits<number_integer_t>::max)());
967 return static_cast<number_unsigned_t
>(-(x + 1)) + 1;
975 std::array<char, 64> number_buffer{{}};
978 const std::lconv* loc =
nullptr;
980 const char thousands_sep =
'\0';
982 const char decimal_point =
'\0';
988 const char indent_char;
990 string_t indent_string;