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())
60 , thousands_sep(loc->thousands_sep == nullptr ?
'\0' : std::char_traits<char>::to_char_type(* (loc->thousands_sep)))
61 , decimal_point(loc->decimal_point == nullptr ?
'\0' : std::char_traits<char>::to_char_type(* (loc->decimal_point)))
63 , indent_string(512, indent_char)
64 , error_handler(error_handler_)
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;
118 if (JSON_HEDLEY_UNLIKELY(indent_string.size() < new_indent))
120 indent_string.resize(indent_string.size() * 2,
' ');
124 auto i = val.m_value.object->cbegin();
125 for (std::size_t cnt = 0; cnt < val.m_value.object->size() - 1; ++cnt, ++i)
127 o->write_characters(indent_string.c_str(), new_indent);
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());
138 o->write_characters(indent_string.c_str(), new_indent);
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');
145 o->write_characters(indent_string.c_str(), current_indent);
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;
191 if (JSON_HEDLEY_UNLIKELY(indent_string.size() < new_indent))
193 indent_string.resize(indent_string.size() * 2,
' ');
197 for (
auto i = val.m_value.array->cbegin();
198 i != val.m_value.array->cend() - 1; ++i)
200 o->write_characters(indent_string.c_str(), new_indent);
201 dump(*i,
true, ensure_ascii, indent_step, new_indent);
202 o->write_characters(
",\n", 2);
206 JSON_ASSERT(!val.m_value.array->empty());
207 o->write_characters(indent_string.c_str(), new_indent);
208 dump(val.m_value.array->back(),
true, ensure_ascii, indent_step, new_indent);
210 o->write_character(
'\n');
211 o->write_characters(indent_string.c_str(), current_indent);
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;
252 if (JSON_HEDLEY_UNLIKELY(indent_string.size() < new_indent))
254 indent_string.resize(indent_string.size() * 2,
' ');
257 o->write_characters(indent_string.c_str(), new_indent);
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);
273 o->write_characters(indent_string.c_str(), new_indent);
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');
285 o->write_characters(indent_string.c_str(), current_indent);
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);
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)
392 const auto byte =
static_cast<uint8_t>(s[i]);
394 switch (decode(state, codepoint,
byte))
402 string_buffer[bytes++] =
'\\';
403 string_buffer[bytes++] =
'b';
409 string_buffer[bytes++] =
'\\';
410 string_buffer[bytes++] =
't';
416 string_buffer[bytes++] =
'\\';
417 string_buffer[bytes++] =
'n';
423 string_buffer[bytes++] =
'\\';
424 string_buffer[bytes++] =
'f';
430 string_buffer[bytes++] =
'\\';
431 string_buffer[bytes++] =
'r';
437 string_buffer[bytes++] =
'\\';
438 string_buffer[bytes++] =
'\"';
444 string_buffer[bytes++] =
'\\';
445 string_buffer[bytes++] =
'\\';
453 if ((codepoint <= 0x1F) || (ensure_ascii && (codepoint >= 0x7F)))
455 if (codepoint <= 0xFFFF)
457 (std::snprintf)(string_buffer.data() + bytes, 7,
"\\u%04x",
463 (std::snprintf)(string_buffer.data() + bytes, 13,
"\\u%04x\\u%04x",
473 string_buffer[bytes++] = s[i];
482 if (string_buffer.size() - bytes < 13)
484 o->write_characters(string_buffer.data(), bytes);
489 bytes_after_last_accept = bytes;
496 switch (error_handler)
500 std::string sn(3,
'\0');
501 (std::snprintf)(&sn[0], sn.size(),
"%.2X", byte);
502 JSON_THROW(type_error::create(316,
"invalid UTF-8 byte at index " + std::to_string(i) +
": 0x" + sn));
512 if (undumped_chars > 0)
519 bytes = bytes_after_last_accept;
526 string_buffer[bytes++] =
'\\';
527 string_buffer[bytes++] =
'u';
528 string_buffer[bytes++] =
'f';
529 string_buffer[bytes++] =
'f';
530 string_buffer[bytes++] =
'f';
531 string_buffer[bytes++] =
'd';
535 string_buffer[bytes++] = detail::binary_writer<BasicJsonType, char>::to_char_type(
'\xEF');
536 string_buffer[bytes++] = detail::binary_writer<BasicJsonType, char>::to_char_type(
'\xBF');
537 string_buffer[bytes++] = detail::binary_writer<BasicJsonType, char>::to_char_type(
'\xBD');
543 if (string_buffer.size() - bytes < 13)
545 o->write_characters(string_buffer.data(), bytes);
549 bytes_after_last_accept = bytes;
570 string_buffer[bytes++] = s[i];
579 if (JSON_HEDLEY_LIKELY(state == UTF8_ACCEPT))
584 o->write_characters(string_buffer.data(), bytes);
590 switch (error_handler)
594 std::string sn(3,
'\0');
595 (std::snprintf)(&sn[0], sn.size(),
"%.2X",
static_cast<std::uint8_t>(s.back()));
596 JSON_THROW(type_error::create(316,
"incomplete UTF-8 string; last byte: 0x" + sn));
602 o->write_characters(string_buffer.data(), bytes_after_last_accept);
609 o->write_characters(string_buffer.data(), bytes_after_last_accept);
613 o->write_characters(
"\\ufffd", 6);
617 o->write_characters(
"\xEF\xBF\xBD", 3);
636 inline unsigned int count_digits(number_unsigned_t x) noexcept
638 unsigned int n_digits = 1;
671 template <
typename NumberType, detail::enable_if_t <
672 std::is_same<NumberType, number_unsigned_t>::value ||
673 std::is_same<NumberType, number_integer_t>::value ||
674 std::is_same<NumberType, binary_char_t>::value,
676 void dump_integer(NumberType x)
678 static constexpr std::array<std::array<char, 2>, 100> digits_to_99
681 {{
'0',
'0'}}, {{
'0',
'1'}}, {{
'0',
'2'}}, {{
'0',
'3'}}, {{
'0',
'4'}}, {{
'0',
'5'}}, {{
'0',
'6'}}, {{
'0',
'7'}}, {{
'0',
'8'}}, {{
'0',
'9'}},
682 {{
'1',
'0'}}, {{
'1',
'1'}}, {{
'1',
'2'}}, {{
'1',
'3'}}, {{
'1',
'4'}}, {{
'1',
'5'}}, {{
'1',
'6'}}, {{
'1',
'7'}}, {{
'1',
'8'}}, {{
'1',
'9'}},
683 {{
'2',
'0'}}, {{
'2',
'1'}}, {{
'2',
'2'}}, {{
'2',
'3'}}, {{
'2',
'4'}}, {{
'2',
'5'}}, {{
'2',
'6'}}, {{
'2',
'7'}}, {{
'2',
'8'}}, {{
'2',
'9'}},
684 {{
'3',
'0'}}, {{
'3',
'1'}}, {{
'3',
'2'}}, {{
'3',
'3'}}, {{
'3',
'4'}}, {{
'3',
'5'}}, {{
'3',
'6'}}, {{
'3',
'7'}}, {{
'3',
'8'}}, {{
'3',
'9'}},
685 {{
'4',
'0'}}, {{
'4',
'1'}}, {{
'4',
'2'}}, {{
'4',
'3'}}, {{
'4',
'4'}}, {{
'4',
'5'}}, {{
'4',
'6'}}, {{
'4',
'7'}}, {{
'4',
'8'}}, {{
'4',
'9'}},
686 {{
'5',
'0'}}, {{
'5',
'1'}}, {{
'5',
'2'}}, {{
'5',
'3'}}, {{
'5',
'4'}}, {{
'5',
'5'}}, {{
'5',
'6'}}, {{
'5',
'7'}}, {{
'5',
'8'}}, {{
'5',
'9'}},
687 {{
'6',
'0'}}, {{
'6',
'1'}}, {{
'6',
'2'}}, {{
'6',
'3'}}, {{
'6',
'4'}}, {{
'6',
'5'}}, {{
'6',
'6'}}, {{
'6',
'7'}}, {{
'6',
'8'}}, {{
'6',
'9'}},
688 {{
'7',
'0'}}, {{
'7',
'1'}}, {{
'7',
'2'}}, {{
'7',
'3'}}, {{
'7',
'4'}}, {{
'7',
'5'}}, {{
'7',
'6'}}, {{
'7',
'7'}}, {{
'7',
'8'}}, {{
'7',
'9'}},
689 {{
'8',
'0'}}, {{
'8',
'1'}}, {{
'8',
'2'}}, {{
'8',
'3'}}, {{
'8',
'4'}}, {{
'8',
'5'}}, {{
'8',
'6'}}, {{
'8',
'7'}}, {{
'8',
'8'}}, {{
'8',
'9'}},
690 {{
'9',
'0'}}, {{
'9',
'1'}}, {{
'9',
'2'}}, {{
'9',
'3'}}, {{
'9',
'4'}}, {{
'9',
'5'}}, {{
'9',
'6'}}, {{
'9',
'7'}}, {{
'9',
'8'}}, {{
'9',
'9'}},
697 o->write_character(
'0');
702 auto buffer_ptr = number_buffer.begin();
704 const bool is_negative = std::is_same<NumberType, number_integer_t>::value && !(x >= 0);
705 number_unsigned_t abs_value;
707 unsigned int n_chars;
712 abs_value = remove_sign(
static_cast<number_integer_t
>(x));
715 n_chars = 1 + count_digits(abs_value);
719 abs_value =
static_cast<number_unsigned_t
>(x);
720 n_chars = count_digits(abs_value);
724 JSON_ASSERT(n_chars < number_buffer.size() - 1);
728 buffer_ptr += n_chars;
732 while (abs_value >= 100)
734 const auto digits_index =
static_cast<unsigned>((abs_value % 100));
736 *(--buffer_ptr) = digits_to_99[digits_index][1];
737 *(--buffer_ptr) = digits_to_99[digits_index][0];
742 const auto digits_index =
static_cast<unsigned>(abs_value);
743 *(--buffer_ptr) = digits_to_99[digits_index][1];
744 *(--buffer_ptr) = digits_to_99[digits_index][0];
748 *(--buffer_ptr) =
static_cast<char>(
'0' + abs_value);
751 o->write_characters(number_buffer.data(), n_chars);
762 void dump_float(number_float_t x)
765 if (!std::isfinite(x))
767 o->write_characters(
"null", 4);
776 static constexpr
bool is_ieee_single_or_double
777 = (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) ||
778 (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);
780 dump_float(x, std::integral_constant<bool, is_ieee_single_or_double>());
783 void dump_float(number_float_t x, std::true_type )
785 char* begin = number_buffer.data();
786 char* end = ::nlohmann::detail::to_chars(begin, begin + number_buffer.size(), x);
788 o->write_characters(begin,
static_cast<size_t>(end - begin));
791 void dump_float(number_float_t x, std::false_type )
794 static constexpr
auto d = std::numeric_limits<number_float_t>::max_digits10;
797 std::ptrdiff_t len = (std::snprintf)(number_buffer.data(), number_buffer.size(),
"%.*g", d, x);
800 JSON_ASSERT(len > 0);
802 JSON_ASSERT(
static_cast<std::size_t
>(len) < number_buffer.size());
805 if (thousands_sep !=
'\0')
807 const auto end = std::remove(number_buffer.begin(),
808 number_buffer.begin() + len, thousands_sep);
809 std::fill(end, number_buffer.end(),
'\0');
810 JSON_ASSERT((end - number_buffer.begin()) <= len);
811 len = (end - number_buffer.begin());
815 if (decimal_point !=
'\0' && decimal_point !=
'.')
817 const auto dec_pos = std::find(number_buffer.begin(), number_buffer.end(), decimal_point);
818 if (dec_pos != number_buffer.end())
824 o->write_characters(number_buffer.data(),
static_cast<std::size_t
>(len));
827 const bool value_is_int_like =
828 std::none_of(number_buffer.begin(), number_buffer.begin() + len + 1,
831 return c ==
'.' || c ==
'e';
834 if (value_is_int_like)
836 o->write_characters(
".0", 2);
863 static const std::array<std::uint8_t, 400> utf8d =
866 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,
867 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,
868 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,
869 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,
870 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,
871 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,
872 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,
873 0xA, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x4, 0x3, 0x3,
874 0xB, 0x6, 0x6, 0x6, 0x5, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8,
875 0x0, 0x1, 0x2, 0x3, 0x5, 0x8, 0x7, 0x1, 0x1, 0x1, 0x4, 0x6, 0x1, 0x1, 0x1, 0x1,
876 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,
877 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,
878 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,
879 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
885 codep = (state != UTF8_ACCEPT)
886 ? (
byte & 0x3fu) | (codep << 6u)
887 : (0xFFu >> type) & (byte);
889 std::size_t index = 256u +
static_cast<size_t>(state) * 16u +
static_cast<size_t>(type);
890 JSON_ASSERT(index < 400);
891 state = utf8d[index];
900 number_unsigned_t remove_sign(number_unsigned_t x)
915 inline number_unsigned_t remove_sign(number_integer_t x) noexcept
917 JSON_ASSERT(x < 0 && x < (std::numeric_limits<number_integer_t>::max)());
918 return static_cast<number_unsigned_t
>(-(x + 1)) + 1;
923 output_adapter_t<char> o =
nullptr;
926 std::array<char, 64> number_buffer{{}};
929 const std::lconv* loc =
nullptr;
931 const char thousands_sep =
'\0';
933 const char decimal_point =
'\0';
936 std::array<char, 512> string_buffer{{}};
939 const char indent_char;
941 string_t indent_string;
Definition: serializer.hpp:41
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
serializer(output_adapter_t< char > s, const char ichar, error_handler_t error_handler_=error_handler_t::strict)
Definition: serializer.hpp:56
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:27
namespace for Niels Lohmann
Definition: adl_serializer.hpp:9