12 #include <type_traits>
15 #include <nlohmann/detail/conversions/to_chars.hpp>
16 #include <nlohmann/detail/exceptions.hpp>
17 #include <nlohmann/detail/macro_scope.hpp>
18 #include <nlohmann/detail/meta/cpp_future.hpp>
19 #include <nlohmann/detail/output/binary_writer.hpp>
20 #include <nlohmann/detail/output/output_adapters.hpp>
21 #include <nlohmann/detail/value_t.hpp>
39 template<
typename BasicJsonType>
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;
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)
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)
394 switch (decode(state, codepoint,
byte))
453 if ((codepoint <= 0x1F) || (ensure_ascii && (codepoint >= 0x7F)))
455 if (codepoint <= 0xFFFF)
465 (std::snprintf)(
string_buffer.data() + bytes, 13,
"\\u%04x\\u%04x",
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 )
792 auto* end = ::nlohmann::detail::to_chars(begin, begin +
number_buffer.size(), x);
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);
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());
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;
Definition: serializer.hpp:41
const error_handler_t error_handler
error_handler how to react on decoding errors
Definition: serializer.hpp:952
const std::lconv * loc
the locale
Definition: serializer.hpp:937
std::array< char, 64 > number_buffer
a (hopefully) large enough character buffer
Definition: serializer.hpp:934
const char decimal_point
the locale's decimal point character
Definition: serializer.hpp:941
const char thousands_sep
the locale's thousand separator character
Definition: serializer.hpp:939
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.hpp:96
const char indent_char
the indentation character
Definition: serializer.hpp:947
std::array< char, 512 > string_buffer
string buffer
Definition: serializer.hpp:944
serializer(output_adapter_t< char > s, const char ichar, error_handler_t error_handler_=error_handler_t::strict)
Definition: serializer.hpp:56
string_t indent_string
the indentation string
Definition: serializer.hpp:949
zip_uint32_t uint32_t
zip_uint32_t typedef.
Definition: zip.hpp:98
zip_uint8_t uint8_t
zip_uint8_t typedef.
Definition: zip.hpp:78
zip_uint16_t uint16_t
zip_uint16_t typedef.
Definition: zip.hpp:88
@ 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)
error_handler_t
how to treat decoding errors
Definition: serializer.hpp:33
@ 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
std::shared_ptr< output_adapter_protocol< CharType > > output_adapter_t
a type to simplify interfaces
Definition: output_adapters.hpp:37
namespace for Niels Lohmann
Definition: adl_serializer.hpp:12