14 #include <type_traits>
17 #include <nlohmann/detail/conversions/to_chars.hpp>
18 #include <nlohmann/detail/exceptions.hpp>
19 #include <nlohmann/detail/macro_scope.hpp>
20 #include <nlohmann/detail/meta/cpp_future.hpp>
21 #include <nlohmann/detail/output/binary_writer.hpp>
22 #include <nlohmann/detail/output/output_adapters.hpp>
23 #include <nlohmann/detail/value_t.hpp>
41 template<
typename BasicJsonType>
44 using string_t =
typename BasicJsonType::string_t;
45 using number_float_t =
typename BasicJsonType::number_float_t;
46 using number_integer_t =
typename BasicJsonType::number_integer_t;
47 using number_unsigned_t =
typename BasicJsonType::number_unsigned_t;
60 , loc(std::localeconv())
61 , thousands_sep(loc->thousands_sep == nullptr ?
'\0' : * (loc->thousands_sep))
62 , decimal_point(loc->decimal_point == nullptr ?
'\0' : * (loc->decimal_point))
64 , indent_string(512, indent_char)
65 , error_handler(error_handler_)
92 void dump(
const BasicJsonType& val,
const bool pretty_print,
93 const bool ensure_ascii,
94 const unsigned int indent_step,
95 const unsigned int current_indent = 0)
101 if (val.m_value.object->empty())
103 o->write_characters(
"{}", 2);
109 o->write_characters(
"{\n", 2);
112 const auto new_indent = current_indent + indent_step;
113 if (JSON_HEDLEY_UNLIKELY(indent_string.size() < new_indent))
115 indent_string.resize(indent_string.size() * 2,
' ');
119 auto i = val.m_value.object->cbegin();
120 for (std::size_t cnt = 0; cnt < val.m_value.object->size() - 1; ++cnt, ++i)
122 o->write_characters(indent_string.c_str(), new_indent);
123 o->write_character(
'\"');
124 dump_escaped(i->first, ensure_ascii);
125 o->write_characters(
"\": ", 3);
126 dump(i->second,
true, ensure_ascii, indent_step, new_indent);
127 o->write_characters(
",\n", 2);
131 assert(i != val.m_value.object->cend());
132 assert(std::next(i) == val.m_value.object->cend());
133 o->write_characters(indent_string.c_str(), new_indent);
134 o->write_character(
'\"');
135 dump_escaped(i->first, ensure_ascii);
136 o->write_characters(
"\": ", 3);
137 dump(i->second,
true, ensure_ascii, indent_step, new_indent);
139 o->write_character(
'\n');
140 o->write_characters(indent_string.c_str(), current_indent);
141 o->write_character(
'}');
145 o->write_character(
'{');
148 auto i = val.m_value.object->cbegin();
149 for (std::size_t cnt = 0; cnt < val.m_value.object->size() - 1; ++cnt, ++i)
151 o->write_character(
'\"');
152 dump_escaped(i->first, ensure_ascii);
153 o->write_characters(
"\":", 2);
154 dump(i->second,
false, ensure_ascii, indent_step, current_indent);
155 o->write_character(
',');
159 assert(i != val.m_value.object->cend());
160 assert(std::next(i) == val.m_value.object->cend());
161 o->write_character(
'\"');
162 dump_escaped(i->first, ensure_ascii);
163 o->write_characters(
"\":", 2);
164 dump(i->second,
false, ensure_ascii, indent_step, current_indent);
166 o->write_character(
'}');
174 if (val.m_value.array->empty())
176 o->write_characters(
"[]", 2);
182 o->write_characters(
"[\n", 2);
185 const auto new_indent = current_indent + indent_step;
186 if (JSON_HEDLEY_UNLIKELY(indent_string.size() < new_indent))
188 indent_string.resize(indent_string.size() * 2,
' ');
192 for (
auto i = val.m_value.array->cbegin();
193 i != val.m_value.array->cend() - 1; ++i)
195 o->write_characters(indent_string.c_str(), new_indent);
196 dump(*i,
true, ensure_ascii, indent_step, new_indent);
197 o->write_characters(
",\n", 2);
201 assert(not val.m_value.array->empty());
202 o->write_characters(indent_string.c_str(), new_indent);
203 dump(val.m_value.array->back(),
true, ensure_ascii, indent_step, new_indent);
205 o->write_character(
'\n');
206 o->write_characters(indent_string.c_str(), current_indent);
207 o->write_character(
']');
211 o->write_character(
'[');
214 for (
auto i = val.m_value.array->cbegin();
215 i != val.m_value.array->cend() - 1; ++i)
217 dump(*i,
false, ensure_ascii, indent_step, current_indent);
218 o->write_character(
',');
222 assert(not val.m_value.array->empty());
223 dump(val.m_value.array->back(),
false, ensure_ascii, indent_step, current_indent);
225 o->write_character(
']');
233 o->write_character(
'\"');
234 dump_escaped(*val.m_value.string, ensure_ascii);
235 o->write_character(
'\"');
241 if (val.m_value.boolean)
243 o->write_characters(
"true", 4);
247 o->write_characters(
"false", 5);
254 dump_integer(val.m_value.number_integer);
260 dump_integer(val.m_value.number_unsigned);
266 dump_float(val.m_value.number_float);
272 o->write_characters(
"<discarded>", 11);
278 o->write_characters(
"null", 4);
302 void dump_escaped(
const string_t& s,
const bool ensure_ascii)
306 std::size_t bytes = 0;
309 std::size_t bytes_after_last_accept = 0;
310 std::size_t undumped_chars = 0;
312 for (std::size_t i = 0; i < s.size(); ++i)
314 const auto byte =
static_cast<uint8_t>(s[i]);
316 switch (decode(state, codepoint,
byte))
324 string_buffer[bytes++] =
'\\';
325 string_buffer[bytes++] =
'b';
331 string_buffer[bytes++] =
'\\';
332 string_buffer[bytes++] =
't';
338 string_buffer[bytes++] =
'\\';
339 string_buffer[bytes++] =
'n';
345 string_buffer[bytes++] =
'\\';
346 string_buffer[bytes++] =
'f';
352 string_buffer[bytes++] =
'\\';
353 string_buffer[bytes++] =
'r';
359 string_buffer[bytes++] =
'\\';
360 string_buffer[bytes++] =
'\"';
366 string_buffer[bytes++] =
'\\';
367 string_buffer[bytes++] =
'\\';
375 if ((codepoint <= 0x1F) or (ensure_ascii and (codepoint >= 0x7F)))
377 if (codepoint <= 0xFFFF)
379 (std::snprintf)(string_buffer.data() + bytes, 7,
"\\u%04x",
385 (std::snprintf)(string_buffer.data() + bytes, 13,
"\\u%04x\\u%04x",
395 string_buffer[bytes++] = s[i];
404 if (string_buffer.size() - bytes < 13)
406 o->write_characters(string_buffer.data(), bytes);
411 bytes_after_last_accept = bytes;
418 switch (error_handler)
422 std::string sn(3,
'\0');
423 (std::snprintf)(&sn[0], sn.size(),
"%.2X", byte);
424 JSON_THROW(type_error::create(316,
"invalid UTF-8 byte at index " + std::to_string(i) +
": 0x" + sn));
434 if (undumped_chars > 0)
441 bytes = bytes_after_last_accept;
448 string_buffer[bytes++] =
'\\';
449 string_buffer[bytes++] =
'u';
450 string_buffer[bytes++] =
'f';
451 string_buffer[bytes++] =
'f';
452 string_buffer[bytes++] =
'f';
453 string_buffer[bytes++] =
'd';
457 string_buffer[bytes++] = detail::binary_writer<BasicJsonType, char>::to_char_type(
'\xEF');
458 string_buffer[bytes++] = detail::binary_writer<BasicJsonType, char>::to_char_type(
'\xBF');
459 string_buffer[bytes++] = detail::binary_writer<BasicJsonType, char>::to_char_type(
'\xBD');
465 if (string_buffer.size() - bytes < 13)
467 o->write_characters(string_buffer.data(), bytes);
471 bytes_after_last_accept = bytes;
489 if (not ensure_ascii)
492 string_buffer[bytes++] = s[i];
501 if (JSON_HEDLEY_LIKELY(state == UTF8_ACCEPT))
506 o->write_characters(string_buffer.data(), bytes);
512 switch (error_handler)
516 std::string sn(3,
'\0');
517 (std::snprintf)(&sn[0], sn.size(),
"%.2X",
static_cast<std::uint8_t>(s.back()));
518 JSON_THROW(type_error::create(316,
"incomplete UTF-8 string; last byte: 0x" + sn));
524 o->write_characters(string_buffer.data(), bytes_after_last_accept);
531 o->write_characters(string_buffer.data(), bytes_after_last_accept);
535 o->write_characters(
"\\ufffd", 6);
539 o->write_characters(
"\xEF\xBF\xBD", 3);
558 inline unsigned int count_digits(number_unsigned_t x) noexcept
560 unsigned int n_digits = 1;
593 template<
typename NumberType, detail::enable_if_t<
594 std::is_same<NumberType, number_unsigned_t>::value or
595 std::is_same<NumberType, number_integer_t>::value,
597 void dump_integer(NumberType x)
599 static constexpr std::array<std::array<char, 2>, 100> digits_to_99
602 {{
'0',
'0'}}, {{
'0',
'1'}}, {{
'0',
'2'}}, {{
'0',
'3'}}, {{
'0',
'4'}}, {{
'0',
'5'}}, {{
'0',
'6'}}, {{
'0',
'7'}}, {{
'0',
'8'}}, {{
'0',
'9'}},
603 {{
'1',
'0'}}, {{
'1',
'1'}}, {{
'1',
'2'}}, {{
'1',
'3'}}, {{
'1',
'4'}}, {{
'1',
'5'}}, {{
'1',
'6'}}, {{
'1',
'7'}}, {{
'1',
'8'}}, {{
'1',
'9'}},
604 {{
'2',
'0'}}, {{
'2',
'1'}}, {{
'2',
'2'}}, {{
'2',
'3'}}, {{
'2',
'4'}}, {{
'2',
'5'}}, {{
'2',
'6'}}, {{
'2',
'7'}}, {{
'2',
'8'}}, {{
'2',
'9'}},
605 {{
'3',
'0'}}, {{
'3',
'1'}}, {{
'3',
'2'}}, {{
'3',
'3'}}, {{
'3',
'4'}}, {{
'3',
'5'}}, {{
'3',
'6'}}, {{
'3',
'7'}}, {{
'3',
'8'}}, {{
'3',
'9'}},
606 {{
'4',
'0'}}, {{
'4',
'1'}}, {{
'4',
'2'}}, {{
'4',
'3'}}, {{
'4',
'4'}}, {{
'4',
'5'}}, {{
'4',
'6'}}, {{
'4',
'7'}}, {{
'4',
'8'}}, {{
'4',
'9'}},
607 {{
'5',
'0'}}, {{
'5',
'1'}}, {{
'5',
'2'}}, {{
'5',
'3'}}, {{
'5',
'4'}}, {{
'5',
'5'}}, {{
'5',
'6'}}, {{
'5',
'7'}}, {{
'5',
'8'}}, {{
'5',
'9'}},
608 {{
'6',
'0'}}, {{
'6',
'1'}}, {{
'6',
'2'}}, {{
'6',
'3'}}, {{
'6',
'4'}}, {{
'6',
'5'}}, {{
'6',
'6'}}, {{
'6',
'7'}}, {{
'6',
'8'}}, {{
'6',
'9'}},
609 {{
'7',
'0'}}, {{
'7',
'1'}}, {{
'7',
'2'}}, {{
'7',
'3'}}, {{
'7',
'4'}}, {{
'7',
'5'}}, {{
'7',
'6'}}, {{
'7',
'7'}}, {{
'7',
'8'}}, {{
'7',
'9'}},
610 {{
'8',
'0'}}, {{
'8',
'1'}}, {{
'8',
'2'}}, {{
'8',
'3'}}, {{
'8',
'4'}}, {{
'8',
'5'}}, {{
'8',
'6'}}, {{
'8',
'7'}}, {{
'8',
'8'}}, {{
'8',
'9'}},
611 {{
'9',
'0'}}, {{
'9',
'1'}}, {{
'9',
'2'}}, {{
'9',
'3'}}, {{
'9',
'4'}}, {{
'9',
'5'}}, {{
'9',
'6'}}, {{
'9',
'7'}}, {{
'9',
'8'}}, {{
'9',
'9'}},
618 o->write_character(
'0');
623 auto buffer_ptr = number_buffer.begin();
625 const bool is_negative = std::is_same<NumberType, number_integer_t>::value and not(x >= 0);
626 number_unsigned_t abs_value;
628 unsigned int n_chars;
633 abs_value = remove_sign(x);
636 n_chars = 1 + count_digits(abs_value);
640 abs_value =
static_cast<number_unsigned_t
>(x);
641 n_chars = count_digits(abs_value);
645 assert(n_chars < number_buffer.size() - 1);
649 buffer_ptr += n_chars;
653 while (abs_value >= 100)
655 const auto digits_index =
static_cast<unsigned>((abs_value % 100));
657 *(--buffer_ptr) = digits_to_99[digits_index][1];
658 *(--buffer_ptr) = digits_to_99[digits_index][0];
663 const auto digits_index =
static_cast<unsigned>(abs_value);
664 *(--buffer_ptr) = digits_to_99[digits_index][1];
665 *(--buffer_ptr) = digits_to_99[digits_index][0];
669 *(--buffer_ptr) =
static_cast<char>(
'0' + abs_value);
672 o->write_characters(number_buffer.data(), n_chars);
683 void dump_float(number_float_t x)
686 if (not std::isfinite(x))
688 o->write_characters(
"null", 4);
697 static constexpr
bool is_ieee_single_or_double
698 = (std::numeric_limits<number_float_t>::is_iec559 and std::numeric_limits<number_float_t>::digits == 24 and std::numeric_limits<number_float_t>::max_exponent == 128) or
699 (std::numeric_limits<number_float_t>::is_iec559 and std::numeric_limits<number_float_t>::digits == 53 and std::numeric_limits<number_float_t>::max_exponent == 1024);
701 dump_float(x, std::integral_constant<bool, is_ieee_single_or_double>());
704 void dump_float(number_float_t x, std::true_type )
706 char* begin = number_buffer.data();
707 char* end = ::nlohmann::detail::to_chars(begin, begin + number_buffer.size(), x);
709 o->write_characters(begin,
static_cast<size_t>(end - begin));
712 void dump_float(number_float_t x, std::false_type )
715 static constexpr
auto d = std::numeric_limits<number_float_t>::max_digits10;
718 std::ptrdiff_t len = (std::snprintf)(number_buffer.data(), number_buffer.size(),
"%.*g", d, x);
723 assert(
static_cast<std::size_t
>(len) < number_buffer.size());
726 if (thousands_sep !=
'\0')
728 const auto end = std::remove(number_buffer.begin(),
729 number_buffer.begin() + len, thousands_sep);
730 std::fill(end, number_buffer.end(),
'\0');
731 assert((end - number_buffer.begin()) <= len);
732 len = (end - number_buffer.begin());
736 if (decimal_point !=
'\0' and decimal_point !=
'.')
738 const auto dec_pos = std::find(number_buffer.begin(), number_buffer.end(), decimal_point);
739 if (dec_pos != number_buffer.end())
745 o->write_characters(number_buffer.data(),
static_cast<std::size_t
>(len));
748 const bool value_is_int_like =
749 std::none_of(number_buffer.begin(), number_buffer.begin() + len + 1,
752 return c ==
'.' or c ==
'e';
755 if (value_is_int_like)
757 o->write_characters(
".0", 2);
784 static const std::array<std::uint8_t, 400> utf8d =
787 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,
788 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,
789 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,
790 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,
791 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,
792 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,
793 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,
794 0xA, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x4, 0x3, 0x3,
795 0xB, 0x6, 0x6, 0x6, 0x5, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8,
796 0x0, 0x1, 0x2, 0x3, 0x5, 0x8, 0x7, 0x1, 0x1, 0x1, 0x4, 0x6, 0x1, 0x1, 0x1, 0x1,
797 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,
798 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,
799 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,
800 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
806 codep = (state != UTF8_ACCEPT)
807 ? (
byte & 0x3fu) | (codep << 6u)
808 : (0xFFu >> type) & (byte);
810 state = utf8d[256u + state * 16u + type];
819 number_unsigned_t remove_sign(number_unsigned_t x)
834 inline number_unsigned_t remove_sign(number_integer_t x) noexcept
836 assert(x < 0 and x < (std::numeric_limits<number_integer_t>::max)());
837 return static_cast<number_unsigned_t
>(-(x + 1)) + 1;
842 output_adapter_t<char> o =
nullptr;
845 std::array<char, 64> number_buffer{{}};
848 const std::lconv* loc =
nullptr;
850 const char thousands_sep =
'\0';
852 const char decimal_point =
'\0';
855 std::array<char, 512> string_buffer{{}};
858 const char indent_char;
860 string_t indent_string;
Definition: serializer.hpp:43
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:92
serializer(output_adapter_t< char > s, const char ichar, error_handler_t error_handler_=error_handler_t::strict)
Definition: serializer.hpp:57
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 the parser callback function
@ 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:35
@ 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