50template<
typename BasicJsonType>
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)
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)
124 if (val.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_value.object->cbegin();
143 for (std::size_t cnt = 0; cnt < val.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);
155 JSON_ASSERT(std::next(i) == val.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_value.object->cbegin();
172 for (std::size_t cnt = 0; cnt < val.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(
',');
183 JSON_ASSERT(std::next(i) == val.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_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_value.array->cbegin();
216 i != val.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_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_value.array->cbegin();
238 i != val.m_value.array->cend() - 1; ++i)
240 dump(*i,
false, ensure_ascii, indent_step, current_indent);
241 o->write_character(
',');
246 dump(val.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_value.binary->empty())
281 for (
auto i = val.m_value.binary->cbegin();
282 i != val.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_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_value.binary->empty())
312 for (
auto i = val.m_value.binary->cbegin();
313 i != val.m_value.binary->cend() - 1; ++i)
316 o->write_character(
',');
321 o->write_characters(
"],\"subtype\":", 12);
322 if (val.m_value.binary->has_subtype())
325 o->write_character(
'}');
329 o->write_characters(
"null}", 5);
337 if (val.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))
420 string_buffer[
bytes++] =
'\\';
421 string_buffer[
bytes++] =
'b';
427 string_buffer[
bytes++] =
'\\';
428 string_buffer[
bytes++] =
't';
434 string_buffer[
bytes++] =
'\\';
435 string_buffer[
bytes++] =
'n';
441 string_buffer[
bytes++] =
'\\';
442 string_buffer[
bytes++] =
'f';
448 string_buffer[
bytes++] =
'\\';
449 string_buffer[
bytes++] =
'r';
455 string_buffer[
bytes++] =
'\\';
456 string_buffer[
bytes++] =
'\"';
462 string_buffer[
bytes++] =
'\\';
463 string_buffer[
bytes++] =
'\\';
471 if ((codepoint <= 0x1F) || (ensure_ascii && (codepoint >= 0x7F)))
473 if (codepoint <= 0xFFFF)
476 static_cast<void>((std::snprintf)(string_buffer.data() +
bytes, 7,
"\\u%04x",
477 static_cast<std::uint16_t
>(codepoint)));
483 static_cast<void>((std::snprintf)(string_buffer.data() +
bytes, 13,
"\\u%04x\\u%04x",
484 static_cast<std::uint16_t
>(0xD7C0u + (codepoint >> 10u)),
485 static_cast<std::uint16_t
>(0xDC00u + (codepoint & 0x3FFu))));
493 string_buffer[
bytes++] = s[i];
502 if (string_buffer.size() -
bytes < 13)
504 o->write_characters(string_buffer.data(),
bytes);
509 bytes_after_last_accept =
bytes;
530 if (undumped_chars > 0)
537 bytes = bytes_after_last_accept;
544 string_buffer[
bytes++] =
'\\';
545 string_buffer[
bytes++] =
'u';
546 string_buffer[
bytes++] =
'f';
547 string_buffer[
bytes++] =
'f';
548 string_buffer[
bytes++] =
'f';
549 string_buffer[
bytes++] =
'd';
561 if (string_buffer.size() -
bytes < 13)
563 o->write_characters(string_buffer.data(),
bytes);
567 bytes_after_last_accept =
bytes;
588 string_buffer[
bytes++] = s[i];
602 o->write_characters(string_buffer.data(),
bytes);
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);
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();
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 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
967 return static_cast<number_unsigned_t
>(-(x + 1)) + 1;
972 output_adapter_t<char> o =
nullptr;
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';
985 std::array<char, 512> string_buffer{{}};
988 const char indent_char;
990 string_t indent_string;
#define WPI_JSON_NAMESPACE_END
Definition: abi_macros.h:59
#define WPI_JSON_NAMESPACE_BEGIN
Definition: abi_macros.h:53
Definition: format.h:4134
static constexpr CharType to_char_type(std::uint8_t x) noexcept
Definition: binary_writer.h:1795
Definition: output_adapters.h:146
Definition: serializer.h:52
serializer & operator=(const serializer &)=delete
void dump_escaped(std::string_view s, const bool ensure_ascii)
dump escaped string
Definition: serializer.h:398
void dump_float(number_float_t x)
dump a floating-point number
Definition: serializer.h:807
serializer(raw_ostream &os, const char ichar, size_t indent_init_len=512, error_handler_t error_handler_=error_handler_t::strict)
Definition: serializer.h:79
serializer & operator=(serializer &&)=delete
serializer(output_adapter_t< char > s, const char ichar, error_handler_t error_handler_=error_handler_t::strict, size_t indent_init_len=512)
Definition: serializer.h:67
void dump_float(number_float_t x, std::false_type)
Definition: serializer.h:836
void dump_integer(NumberType x)
dump an integer
Definition: serializer.h:722
void dump_float(number_float_t x, std::true_type)
Definition: serializer.h:828
void dump(const BasicJsonType &val, const bool pretty_print, const bool ensure_ascii, const unsigned int indent_step, const unsigned int current_indent=0)
internal implementation of the serialization function
Definition: serializer.h:114
serializer(const serializer &)=delete
serializer(serializer &&)=delete
static type_error create(int id_, const std::string &what_arg, BasicJsonContext context)
Definition: exceptions.h:209
basic_string_view< char > string_view
Definition: core.h:501
#define JSON_HEDLEY_LIKELY(expr)
Definition: hedley.h:1395
#define JSON_HEDLEY_UNLIKELY(expr)
Definition: hedley.h:1396
#define JSON_ASSERT(x)
Definition: macro_scope.h:192
#define JSON_THROW(exception)
Definition: macro_scope.h:163
detail namespace with internal helper functions
Definition: xchar.h:20
std::shared_ptr< output_adapter_protocol< CharType > > output_adapter_t
a type to simplify interfaces
Definition: output_adapters.h:47
OutStringType concat(Args &&... args)
Definition: string_concat.h:137
JSON_HEDLEY_RETURNS_NON_NULL char * to_chars(char *first, const char *last, FloatType value)
generates a decimal representation of the floating-point number value in [first, last).
Definition: to_chars.h:1065
FMT_NOINLINE FMT_CONSTEXPR auto fill(OutputIt it, size_t n, const fill_t< Char > &fill) -> OutputIt
Definition: format.h:1779
typename std::enable_if< B, T >::type enable_if_t
Definition: cpp_future.h:38
FMT_CONSTEXPR auto find(Ptr first, Ptr last, T value, Ptr &out) -> bool
Definition: core.h:2120
@ number_integer
number value (signed integer)
@ discarded
discarded by the parser callback function
@ binary
binary array (ordered collection of bytes)
@ object
object (unordered set of name/value pairs)
@ number_float
number value (floating-point)
@ number_unsigned
number value (unsigned integer)
@ array
array (ordered collection of values)
bool isfinite(T)
Definition: chrono.h:1600
error_handler_t
how to treat decoding errors
Definition: serializer.h:44
@ strict
throw a type_error exception in case of invalid UTF-8
@ ignore
ignore invalid UTF-8 sequences
@ replace
replace invalid UTF-8 sequences with U+FFFD
state
Definition: core.h:2271
type
Definition: core.h:556
static constexpr const velocity::meters_per_second_t c(299792458.0)
Speed of light in vacuum.
std::string to_string(const T &t)
Definition: base.h:92
UnitTypeLhs() max(const UnitTypeLhs &lhs, const UnitTypeRhs &rhs)
Definition: base.h:3417