serializer.hpp 39 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988
  1. // __ _____ _____ _____
  2. // __| | __| | | | JSON for Modern C++
  3. // | | |__ | | | | | | version 3.11.3
  4. // |_____|_____|_____|_|___| https://github.com/nlohmann/json
  5. //
  6. // SPDX-FileCopyrightText: 2008-2009 Björn Hoehrmann <bjoern@hoehrmann.de>
  7. // SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
  8. // SPDX-License-Identifier: MIT
  9. #pragma once
  10. #include <algorithm> // reverse, remove, fill, find, none_of
  11. #include <array> // array
  12. #include <clocale> // localeconv, lconv
  13. #include <cmath> // labs, isfinite, isnan, signbit
  14. #include <cstddef> // size_t, ptrdiff_t
  15. #include <cstdint> // uint8_t
  16. #include <cstdio> // snprintf
  17. #include <limits> // numeric_limits
  18. #include <string> // string, char_traits
  19. #include <iomanip> // setfill, setw
  20. #include <type_traits> // is_same
  21. #include <utility> // move
  22. #include <nlohmann/detail/conversions/to_chars.hpp>
  23. #include <nlohmann/detail/exceptions.hpp>
  24. #include <nlohmann/detail/macro_scope.hpp>
  25. #include <nlohmann/detail/meta/cpp_future.hpp>
  26. #include <nlohmann/detail/output/binary_writer.hpp>
  27. #include <nlohmann/detail/output/output_adapters.hpp>
  28. #include <nlohmann/detail/string_concat.hpp>
  29. #include <nlohmann/detail/value_t.hpp>
  30. NLOHMANN_JSON_NAMESPACE_BEGIN
  31. namespace detail
  32. {
  33. ///////////////////
  34. // serialization //
  35. ///////////////////
  36. /// how to treat decoding errors
  37. enum class error_handler_t
  38. {
  39. strict, ///< throw a type_error exception in case of invalid UTF-8
  40. replace, ///< replace invalid UTF-8 sequences with U+FFFD
  41. ignore ///< ignore invalid UTF-8 sequences
  42. };
  43. template<typename BasicJsonType>
  44. class serializer
  45. {
  46. using string_t = typename BasicJsonType::string_t;
  47. using number_float_t = typename BasicJsonType::number_float_t;
  48. using number_integer_t = typename BasicJsonType::number_integer_t;
  49. using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
  50. using binary_char_t = typename BasicJsonType::binary_t::value_type;
  51. static constexpr std::uint8_t UTF8_ACCEPT = 0;
  52. static constexpr std::uint8_t UTF8_REJECT = 1;
  53. public:
  54. /*!
  55. @param[in] s output stream to serialize to
  56. @param[in] ichar indentation character to use
  57. @param[in] error_handler_ how to react on decoding errors
  58. */
  59. serializer(output_adapter_t<char> s, const char ichar,
  60. error_handler_t error_handler_ = error_handler_t::strict)
  61. : o(std::move(s))
  62. , loc(std::localeconv())
  63. , thousands_sep(loc->thousands_sep == nullptr ? '\0' : std::char_traits<char>::to_char_type(* (loc->thousands_sep)))
  64. , decimal_point(loc->decimal_point == nullptr ? '\0' : std::char_traits<char>::to_char_type(* (loc->decimal_point)))
  65. , indent_char(ichar)
  66. , indent_string(512, indent_char)
  67. , error_handler(error_handler_)
  68. {}
  69. // delete because of pointer members
  70. serializer(const serializer&) = delete;
  71. serializer& operator=(const serializer&) = delete;
  72. serializer(serializer&&) = delete;
  73. serializer& operator=(serializer&&) = delete;
  74. ~serializer() = default;
  75. /*!
  76. @brief internal implementation of the serialization function
  77. This function is called by the public member function dump and organizes
  78. the serialization internally. The indentation level is propagated as
  79. additional parameter. In case of arrays and objects, the function is
  80. called recursively.
  81. - strings and object keys are escaped using `escape_string()`
  82. - integer numbers are converted implicitly via `operator<<`
  83. - floating-point numbers are converted to a string using `"%g"` format
  84. - binary values are serialized as objects containing the subtype and the
  85. byte array
  86. @param[in] val value to serialize
  87. @param[in] pretty_print whether the output shall be pretty-printed
  88. @param[in] ensure_ascii If @a ensure_ascii is true, all non-ASCII characters
  89. in the output are escaped with `\uXXXX` sequences, and the result consists
  90. of ASCII characters only.
  91. @param[in] indent_step the indent level
  92. @param[in] current_indent the current indent level (only used internally)
  93. */
  94. void dump(const BasicJsonType& val,
  95. const bool pretty_print,
  96. const bool ensure_ascii,
  97. const unsigned int indent_step,
  98. const unsigned int current_indent = 0)
  99. {
  100. switch (val.m_data.m_type)
  101. {
  102. case value_t::object:
  103. {
  104. if (val.m_data.m_value.object->empty())
  105. {
  106. o->write_characters("{}", 2);
  107. return;
  108. }
  109. if (pretty_print)
  110. {
  111. o->write_characters("{\n", 2);
  112. // variable to hold indentation for recursive calls
  113. const auto new_indent = current_indent + indent_step;
  114. if (JSON_HEDLEY_UNLIKELY(indent_string.size() < new_indent))
  115. {
  116. indent_string.resize(indent_string.size() * 2, ' ');
  117. }
  118. // first n-1 elements
  119. auto i = val.m_data.m_value.object->cbegin();
  120. for (std::size_t cnt = 0; cnt < val.m_data.m_value.object->size() - 1; ++cnt, ++i)
  121. {
  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);
  128. }
  129. // last element
  130. JSON_ASSERT(i != val.m_data.m_value.object->cend());
  131. JSON_ASSERT(std::next(i) == val.m_data.m_value.object->cend());
  132. o->write_characters(indent_string.c_str(), new_indent);
  133. o->write_character('\"');
  134. dump_escaped(i->first, ensure_ascii);
  135. o->write_characters("\": ", 3);
  136. dump(i->second, true, ensure_ascii, indent_step, new_indent);
  137. o->write_character('\n');
  138. o->write_characters(indent_string.c_str(), current_indent);
  139. o->write_character('}');
  140. }
  141. else
  142. {
  143. o->write_character('{');
  144. // first n-1 elements
  145. auto i = val.m_data.m_value.object->cbegin();
  146. for (std::size_t cnt = 0; cnt < val.m_data.m_value.object->size() - 1; ++cnt, ++i)
  147. {
  148. o->write_character('\"');
  149. dump_escaped(i->first, ensure_ascii);
  150. o->write_characters("\":", 2);
  151. dump(i->second, false, ensure_ascii, indent_step, current_indent);
  152. o->write_character(',');
  153. }
  154. // last element
  155. JSON_ASSERT(i != val.m_data.m_value.object->cend());
  156. JSON_ASSERT(std::next(i) == val.m_data.m_value.object->cend());
  157. o->write_character('\"');
  158. dump_escaped(i->first, ensure_ascii);
  159. o->write_characters("\":", 2);
  160. dump(i->second, false, ensure_ascii, indent_step, current_indent);
  161. o->write_character('}');
  162. }
  163. return;
  164. }
  165. case value_t::array:
  166. {
  167. if (val.m_data.m_value.array->empty())
  168. {
  169. o->write_characters("[]", 2);
  170. return;
  171. }
  172. if (pretty_print)
  173. {
  174. o->write_characters("[\n", 2);
  175. // variable to hold indentation for recursive calls
  176. const auto new_indent = current_indent + indent_step;
  177. if (JSON_HEDLEY_UNLIKELY(indent_string.size() < new_indent))
  178. {
  179. indent_string.resize(indent_string.size() * 2, ' ');
  180. }
  181. // first n-1 elements
  182. for (auto i = val.m_data.m_value.array->cbegin();
  183. i != val.m_data.m_value.array->cend() - 1; ++i)
  184. {
  185. o->write_characters(indent_string.c_str(), new_indent);
  186. dump(*i, true, ensure_ascii, indent_step, new_indent);
  187. o->write_characters(",\n", 2);
  188. }
  189. // last element
  190. JSON_ASSERT(!val.m_data.m_value.array->empty());
  191. o->write_characters(indent_string.c_str(), new_indent);
  192. dump(val.m_data.m_value.array->back(), true, ensure_ascii, indent_step, new_indent);
  193. o->write_character('\n');
  194. o->write_characters(indent_string.c_str(), current_indent);
  195. o->write_character(']');
  196. }
  197. else
  198. {
  199. o->write_character('[');
  200. // first n-1 elements
  201. for (auto i = val.m_data.m_value.array->cbegin();
  202. i != val.m_data.m_value.array->cend() - 1; ++i)
  203. {
  204. dump(*i, false, ensure_ascii, indent_step, current_indent);
  205. o->write_character(',');
  206. }
  207. // last element
  208. JSON_ASSERT(!val.m_data.m_value.array->empty());
  209. dump(val.m_data.m_value.array->back(), false, ensure_ascii, indent_step, current_indent);
  210. o->write_character(']');
  211. }
  212. return;
  213. }
  214. case value_t::string:
  215. {
  216. o->write_character('\"');
  217. dump_escaped(*val.m_data.m_value.string, ensure_ascii);
  218. o->write_character('\"');
  219. return;
  220. }
  221. case value_t::binary:
  222. {
  223. if (pretty_print)
  224. {
  225. o->write_characters("{\n", 2);
  226. // variable to hold indentation for recursive calls
  227. const auto new_indent = current_indent + indent_step;
  228. if (JSON_HEDLEY_UNLIKELY(indent_string.size() < new_indent))
  229. {
  230. indent_string.resize(indent_string.size() * 2, ' ');
  231. }
  232. o->write_characters(indent_string.c_str(), new_indent);
  233. o->write_characters("\"bytes\": [", 10);
  234. if (!val.m_data.m_value.binary->empty())
  235. {
  236. for (auto i = val.m_data.m_value.binary->cbegin();
  237. i != val.m_data.m_value.binary->cend() - 1; ++i)
  238. {
  239. dump_integer(*i);
  240. o->write_characters(", ", 2);
  241. }
  242. dump_integer(val.m_data.m_value.binary->back());
  243. }
  244. o->write_characters("],\n", 3);
  245. o->write_characters(indent_string.c_str(), new_indent);
  246. o->write_characters("\"subtype\": ", 11);
  247. if (val.m_data.m_value.binary->has_subtype())
  248. {
  249. dump_integer(val.m_data.m_value.binary->subtype());
  250. }
  251. else
  252. {
  253. o->write_characters("null", 4);
  254. }
  255. o->write_character('\n');
  256. o->write_characters(indent_string.c_str(), current_indent);
  257. o->write_character('}');
  258. }
  259. else
  260. {
  261. o->write_characters("{\"bytes\":[", 10);
  262. if (!val.m_data.m_value.binary->empty())
  263. {
  264. for (auto i = val.m_data.m_value.binary->cbegin();
  265. i != val.m_data.m_value.binary->cend() - 1; ++i)
  266. {
  267. dump_integer(*i);
  268. o->write_character(',');
  269. }
  270. dump_integer(val.m_data.m_value.binary->back());
  271. }
  272. o->write_characters("],\"subtype\":", 12);
  273. if (val.m_data.m_value.binary->has_subtype())
  274. {
  275. dump_integer(val.m_data.m_value.binary->subtype());
  276. o->write_character('}');
  277. }
  278. else
  279. {
  280. o->write_characters("null}", 5);
  281. }
  282. }
  283. return;
  284. }
  285. case value_t::boolean:
  286. {
  287. if (val.m_data.m_value.boolean)
  288. {
  289. o->write_characters("true", 4);
  290. }
  291. else
  292. {
  293. o->write_characters("false", 5);
  294. }
  295. return;
  296. }
  297. case value_t::number_integer:
  298. {
  299. dump_integer(val.m_data.m_value.number_integer);
  300. return;
  301. }
  302. case value_t::number_unsigned:
  303. {
  304. dump_integer(val.m_data.m_value.number_unsigned);
  305. return;
  306. }
  307. case value_t::number_float:
  308. {
  309. dump_float(val.m_data.m_value.number_float);
  310. return;
  311. }
  312. case value_t::discarded:
  313. {
  314. o->write_characters("<discarded>", 11);
  315. return;
  316. }
  317. case value_t::null:
  318. {
  319. o->write_characters("null", 4);
  320. return;
  321. }
  322. default: // LCOV_EXCL_LINE
  323. JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
  324. }
  325. }
  326. JSON_PRIVATE_UNLESS_TESTED:
  327. /*!
  328. @brief dump escaped string
  329. Escape a string by replacing certain special characters by a sequence of an
  330. escape character (backslash) and another character and other control
  331. characters by a sequence of "\u" followed by a four-digit hex
  332. representation. The escaped string is written to output stream @a o.
  333. @param[in] s the string to escape
  334. @param[in] ensure_ascii whether to escape non-ASCII characters with
  335. \uXXXX sequences
  336. @complexity Linear in the length of string @a s.
  337. */
  338. void dump_escaped(const string_t& s, const bool ensure_ascii)
  339. {
  340. std::uint32_t codepoint{};
  341. std::uint8_t state = UTF8_ACCEPT;
  342. std::size_t bytes = 0; // number of bytes written to string_buffer
  343. // number of bytes written at the point of the last valid byte
  344. std::size_t bytes_after_last_accept = 0;
  345. std::size_t undumped_chars = 0;
  346. for (std::size_t i = 0; i < s.size(); ++i)
  347. {
  348. const auto byte = static_cast<std::uint8_t>(s[i]);
  349. switch (decode(state, codepoint, byte))
  350. {
  351. case UTF8_ACCEPT: // decode found a new code point
  352. {
  353. switch (codepoint)
  354. {
  355. case 0x08: // backspace
  356. {
  357. string_buffer[bytes++] = '\\';
  358. string_buffer[bytes++] = 'b';
  359. break;
  360. }
  361. case 0x09: // horizontal tab
  362. {
  363. string_buffer[bytes++] = '\\';
  364. string_buffer[bytes++] = 't';
  365. break;
  366. }
  367. case 0x0A: // newline
  368. {
  369. string_buffer[bytes++] = '\\';
  370. string_buffer[bytes++] = 'n';
  371. break;
  372. }
  373. case 0x0C: // formfeed
  374. {
  375. string_buffer[bytes++] = '\\';
  376. string_buffer[bytes++] = 'f';
  377. break;
  378. }
  379. case 0x0D: // carriage return
  380. {
  381. string_buffer[bytes++] = '\\';
  382. string_buffer[bytes++] = 'r';
  383. break;
  384. }
  385. case 0x22: // quotation mark
  386. {
  387. string_buffer[bytes++] = '\\';
  388. string_buffer[bytes++] = '\"';
  389. break;
  390. }
  391. case 0x5C: // reverse solidus
  392. {
  393. string_buffer[bytes++] = '\\';
  394. string_buffer[bytes++] = '\\';
  395. break;
  396. }
  397. default:
  398. {
  399. // escape control characters (0x00..0x1F) or, if
  400. // ensure_ascii parameter is used, non-ASCII characters
  401. if ((codepoint <= 0x1F) || (ensure_ascii && (codepoint >= 0x7F)))
  402. {
  403. if (codepoint <= 0xFFFF)
  404. {
  405. // NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg,hicpp-vararg)
  406. static_cast<void>((std::snprintf)(string_buffer.data() + bytes, 7, "\\u%04x",
  407. static_cast<std::uint16_t>(codepoint)));
  408. bytes += 6;
  409. }
  410. else
  411. {
  412. // NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg,hicpp-vararg)
  413. static_cast<void>((std::snprintf)(string_buffer.data() + bytes, 13, "\\u%04x\\u%04x",
  414. static_cast<std::uint16_t>(0xD7C0u + (codepoint >> 10u)),
  415. static_cast<std::uint16_t>(0xDC00u + (codepoint & 0x3FFu))));
  416. bytes += 12;
  417. }
  418. }
  419. else
  420. {
  421. // copy byte to buffer (all previous bytes
  422. // been copied have in default case above)
  423. string_buffer[bytes++] = s[i];
  424. }
  425. break;
  426. }
  427. }
  428. // write buffer and reset index; there must be 13 bytes
  429. // left, as this is the maximal number of bytes to be
  430. // written ("\uxxxx\uxxxx\0") for one code point
  431. if (string_buffer.size() - bytes < 13)
  432. {
  433. o->write_characters(string_buffer.data(), bytes);
  434. bytes = 0;
  435. }
  436. // remember the byte position of this accept
  437. bytes_after_last_accept = bytes;
  438. undumped_chars = 0;
  439. break;
  440. }
  441. case UTF8_REJECT: // decode found invalid UTF-8 byte
  442. {
  443. switch (error_handler)
  444. {
  445. case error_handler_t::strict:
  446. {
  447. JSON_THROW(type_error::create(316, concat("invalid UTF-8 byte at index ", std::to_string(i), ": 0x", hex_bytes(byte | 0)), nullptr));
  448. }
  449. case error_handler_t::ignore:
  450. case error_handler_t::replace:
  451. {
  452. // in case we saw this character the first time, we
  453. // would like to read it again, because the byte
  454. // may be OK for itself, but just not OK for the
  455. // previous sequence
  456. if (undumped_chars > 0)
  457. {
  458. --i;
  459. }
  460. // reset length buffer to the last accepted index;
  461. // thus removing/ignoring the invalid characters
  462. bytes = bytes_after_last_accept;
  463. if (error_handler == error_handler_t::replace)
  464. {
  465. // add a replacement character
  466. if (ensure_ascii)
  467. {
  468. string_buffer[bytes++] = '\\';
  469. string_buffer[bytes++] = 'u';
  470. string_buffer[bytes++] = 'f';
  471. string_buffer[bytes++] = 'f';
  472. string_buffer[bytes++] = 'f';
  473. string_buffer[bytes++] = 'd';
  474. }
  475. else
  476. {
  477. string_buffer[bytes++] = detail::binary_writer<BasicJsonType, char>::to_char_type('\xEF');
  478. string_buffer[bytes++] = detail::binary_writer<BasicJsonType, char>::to_char_type('\xBF');
  479. string_buffer[bytes++] = detail::binary_writer<BasicJsonType, char>::to_char_type('\xBD');
  480. }
  481. // write buffer and reset index; there must be 13 bytes
  482. // left, as this is the maximal number of bytes to be
  483. // written ("\uxxxx\uxxxx\0") for one code point
  484. if (string_buffer.size() - bytes < 13)
  485. {
  486. o->write_characters(string_buffer.data(), bytes);
  487. bytes = 0;
  488. }
  489. bytes_after_last_accept = bytes;
  490. }
  491. undumped_chars = 0;
  492. // continue processing the string
  493. state = UTF8_ACCEPT;
  494. break;
  495. }
  496. default: // LCOV_EXCL_LINE
  497. JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
  498. }
  499. break;
  500. }
  501. default: // decode found yet incomplete multi-byte code point
  502. {
  503. if (!ensure_ascii)
  504. {
  505. // code point will not be escaped - copy byte to buffer
  506. string_buffer[bytes++] = s[i];
  507. }
  508. ++undumped_chars;
  509. break;
  510. }
  511. }
  512. }
  513. // we finished processing the string
  514. if (JSON_HEDLEY_LIKELY(state == UTF8_ACCEPT))
  515. {
  516. // write buffer
  517. if (bytes > 0)
  518. {
  519. o->write_characters(string_buffer.data(), bytes);
  520. }
  521. }
  522. else
  523. {
  524. // we finish reading, but do not accept: string was incomplete
  525. switch (error_handler)
  526. {
  527. case error_handler_t::strict:
  528. {
  529. JSON_THROW(type_error::create(316, concat("incomplete UTF-8 string; last byte: 0x", hex_bytes(static_cast<std::uint8_t>(s.back() | 0))), nullptr));
  530. }
  531. case error_handler_t::ignore:
  532. {
  533. // write all accepted bytes
  534. o->write_characters(string_buffer.data(), bytes_after_last_accept);
  535. break;
  536. }
  537. case error_handler_t::replace:
  538. {
  539. // write all accepted bytes
  540. o->write_characters(string_buffer.data(), bytes_after_last_accept);
  541. // add a replacement character
  542. if (ensure_ascii)
  543. {
  544. o->write_characters("\\ufffd", 6);
  545. }
  546. else
  547. {
  548. o->write_characters("\xEF\xBF\xBD", 3);
  549. }
  550. break;
  551. }
  552. default: // LCOV_EXCL_LINE
  553. JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
  554. }
  555. }
  556. }
  557. private:
  558. /*!
  559. @brief count digits
  560. Count the number of decimal (base 10) digits for an input unsigned integer.
  561. @param[in] x unsigned integer number to count its digits
  562. @return number of decimal digits
  563. */
  564. inline unsigned int count_digits(number_unsigned_t x) noexcept
  565. {
  566. unsigned int n_digits = 1;
  567. for (;;)
  568. {
  569. if (x < 10)
  570. {
  571. return n_digits;
  572. }
  573. if (x < 100)
  574. {
  575. return n_digits + 1;
  576. }
  577. if (x < 1000)
  578. {
  579. return n_digits + 2;
  580. }
  581. if (x < 10000)
  582. {
  583. return n_digits + 3;
  584. }
  585. x = x / 10000u;
  586. n_digits += 4;
  587. }
  588. }
  589. /*!
  590. * @brief convert a byte to a uppercase hex representation
  591. * @param[in] byte byte to represent
  592. * @return representation ("00".."FF")
  593. */
  594. static std::string hex_bytes(std::uint8_t byte)
  595. {
  596. std::string result = "FF";
  597. constexpr const char* nibble_to_hex = "0123456789ABCDEF";
  598. result[0] = nibble_to_hex[byte / 16];
  599. result[1] = nibble_to_hex[byte % 16];
  600. return result;
  601. }
  602. // templates to avoid warnings about useless casts
  603. template <typename NumberType, enable_if_t<std::is_signed<NumberType>::value, int> = 0>
  604. bool is_negative_number(NumberType x)
  605. {
  606. return x < 0;
  607. }
  608. template < typename NumberType, enable_if_t <std::is_unsigned<NumberType>::value, int > = 0 >
  609. bool is_negative_number(NumberType /*unused*/)
  610. {
  611. return false;
  612. }
  613. /*!
  614. @brief dump an integer
  615. Dump a given integer to output stream @a o. Works internally with
  616. @a number_buffer.
  617. @param[in] x integer number (signed or unsigned) to dump
  618. @tparam NumberType either @a number_integer_t or @a number_unsigned_t
  619. */
  620. template < typename NumberType, detail::enable_if_t <
  621. std::is_integral<NumberType>::value ||
  622. std::is_same<NumberType, number_unsigned_t>::value ||
  623. std::is_same<NumberType, number_integer_t>::value ||
  624. std::is_same<NumberType, binary_char_t>::value,
  625. int > = 0 >
  626. void dump_integer(NumberType x)
  627. {
  628. static constexpr std::array<std::array<char, 2>, 100> digits_to_99
  629. {
  630. {
  631. {{'0', '0'}}, {{'0', '1'}}, {{'0', '2'}}, {{'0', '3'}}, {{'0', '4'}}, {{'0', '5'}}, {{'0', '6'}}, {{'0', '7'}}, {{'0', '8'}}, {{'0', '9'}},
  632. {{'1', '0'}}, {{'1', '1'}}, {{'1', '2'}}, {{'1', '3'}}, {{'1', '4'}}, {{'1', '5'}}, {{'1', '6'}}, {{'1', '7'}}, {{'1', '8'}}, {{'1', '9'}},
  633. {{'2', '0'}}, {{'2', '1'}}, {{'2', '2'}}, {{'2', '3'}}, {{'2', '4'}}, {{'2', '5'}}, {{'2', '6'}}, {{'2', '7'}}, {{'2', '8'}}, {{'2', '9'}},
  634. {{'3', '0'}}, {{'3', '1'}}, {{'3', '2'}}, {{'3', '3'}}, {{'3', '4'}}, {{'3', '5'}}, {{'3', '6'}}, {{'3', '7'}}, {{'3', '8'}}, {{'3', '9'}},
  635. {{'4', '0'}}, {{'4', '1'}}, {{'4', '2'}}, {{'4', '3'}}, {{'4', '4'}}, {{'4', '5'}}, {{'4', '6'}}, {{'4', '7'}}, {{'4', '8'}}, {{'4', '9'}},
  636. {{'5', '0'}}, {{'5', '1'}}, {{'5', '2'}}, {{'5', '3'}}, {{'5', '4'}}, {{'5', '5'}}, {{'5', '6'}}, {{'5', '7'}}, {{'5', '8'}}, {{'5', '9'}},
  637. {{'6', '0'}}, {{'6', '1'}}, {{'6', '2'}}, {{'6', '3'}}, {{'6', '4'}}, {{'6', '5'}}, {{'6', '6'}}, {{'6', '7'}}, {{'6', '8'}}, {{'6', '9'}},
  638. {{'7', '0'}}, {{'7', '1'}}, {{'7', '2'}}, {{'7', '3'}}, {{'7', '4'}}, {{'7', '5'}}, {{'7', '6'}}, {{'7', '7'}}, {{'7', '8'}}, {{'7', '9'}},
  639. {{'8', '0'}}, {{'8', '1'}}, {{'8', '2'}}, {{'8', '3'}}, {{'8', '4'}}, {{'8', '5'}}, {{'8', '6'}}, {{'8', '7'}}, {{'8', '8'}}, {{'8', '9'}},
  640. {{'9', '0'}}, {{'9', '1'}}, {{'9', '2'}}, {{'9', '3'}}, {{'9', '4'}}, {{'9', '5'}}, {{'9', '6'}}, {{'9', '7'}}, {{'9', '8'}}, {{'9', '9'}},
  641. }
  642. };
  643. // special case for "0"
  644. if (x == 0)
  645. {
  646. o->write_character('0');
  647. return;
  648. }
  649. // use a pointer to fill the buffer
  650. auto buffer_ptr = number_buffer.begin(); // NOLINT(llvm-qualified-auto,readability-qualified-auto,cppcoreguidelines-pro-type-vararg,hicpp-vararg)
  651. number_unsigned_t abs_value;
  652. unsigned int n_chars{};
  653. if (is_negative_number(x))
  654. {
  655. *buffer_ptr = '-';
  656. abs_value = remove_sign(static_cast<number_integer_t>(x));
  657. // account one more byte for the minus sign
  658. n_chars = 1 + count_digits(abs_value);
  659. }
  660. else
  661. {
  662. abs_value = static_cast<number_unsigned_t>(x);
  663. n_chars = count_digits(abs_value);
  664. }
  665. // spare 1 byte for '\0'
  666. JSON_ASSERT(n_chars < number_buffer.size() - 1);
  667. // jump to the end to generate the string from backward,
  668. // so we later avoid reversing the result
  669. buffer_ptr += n_chars;
  670. // Fast int2ascii implementation inspired by "Fastware" talk by Andrei Alexandrescu
  671. // See: https://www.youtube.com/watch?v=o4-CwDo2zpg
  672. while (abs_value >= 100)
  673. {
  674. const auto digits_index = static_cast<unsigned>((abs_value % 100));
  675. abs_value /= 100;
  676. *(--buffer_ptr) = digits_to_99[digits_index][1];
  677. *(--buffer_ptr) = digits_to_99[digits_index][0];
  678. }
  679. if (abs_value >= 10)
  680. {
  681. const auto digits_index = static_cast<unsigned>(abs_value);
  682. *(--buffer_ptr) = digits_to_99[digits_index][1];
  683. *(--buffer_ptr) = digits_to_99[digits_index][0];
  684. }
  685. else
  686. {
  687. *(--buffer_ptr) = static_cast<char>('0' + abs_value);
  688. }
  689. o->write_characters(number_buffer.data(), n_chars);
  690. }
  691. /*!
  692. @brief dump a floating-point number
  693. Dump a given floating-point number to output stream @a o. Works internally
  694. with @a number_buffer.
  695. @param[in] x floating-point number to dump
  696. */
  697. void dump_float(number_float_t x)
  698. {
  699. // NaN / inf
  700. if (!std::isfinite(x))
  701. {
  702. o->write_characters("null", 4);
  703. return;
  704. }
  705. // If number_float_t is an IEEE-754 single or double precision number,
  706. // use the Grisu2 algorithm to produce short numbers which are
  707. // guaranteed to round-trip, using strtof and strtod, resp.
  708. //
  709. // NB: The test below works if <long double> == <double>.
  710. static constexpr bool is_ieee_single_or_double
  711. = (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) ||
  712. (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);
  713. dump_float(x, std::integral_constant<bool, is_ieee_single_or_double>());
  714. }
  715. void dump_float(number_float_t x, std::true_type /*is_ieee_single_or_double*/)
  716. {
  717. auto* begin = number_buffer.data();
  718. auto* end = ::nlohmann::detail::to_chars(begin, begin + number_buffer.size(), x);
  719. o->write_characters(begin, static_cast<size_t>(end - begin));
  720. }
  721. void dump_float(number_float_t x, std::false_type /*is_ieee_single_or_double*/)
  722. {
  723. // get number of digits for a float -> text -> float round-trip
  724. static constexpr auto d = std::numeric_limits<number_float_t>::max_digits10;
  725. // the actual conversion
  726. // NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg,hicpp-vararg)
  727. std::ptrdiff_t len = (std::snprintf)(number_buffer.data(), number_buffer.size(), "%.*g", d, x);
  728. // negative value indicates an error
  729. JSON_ASSERT(len > 0);
  730. // check if buffer was large enough
  731. JSON_ASSERT(static_cast<std::size_t>(len) < number_buffer.size());
  732. // erase thousands separator
  733. if (thousands_sep != '\0')
  734. {
  735. // NOLINTNEXTLINE(readability-qualified-auto,llvm-qualified-auto): std::remove returns an iterator, see https://github.com/nlohmann/json/issues/3081
  736. const auto end = std::remove(number_buffer.begin(), number_buffer.begin() + len, thousands_sep);
  737. std::fill(end, number_buffer.end(), '\0');
  738. JSON_ASSERT((end - number_buffer.begin()) <= len);
  739. len = (end - number_buffer.begin());
  740. }
  741. // convert decimal point to '.'
  742. if (decimal_point != '\0' && decimal_point != '.')
  743. {
  744. // NOLINTNEXTLINE(readability-qualified-auto,llvm-qualified-auto): std::find returns an iterator, see https://github.com/nlohmann/json/issues/3081
  745. const auto dec_pos = std::find(number_buffer.begin(), number_buffer.end(), decimal_point);
  746. if (dec_pos != number_buffer.end())
  747. {
  748. *dec_pos = '.';
  749. }
  750. }
  751. o->write_characters(number_buffer.data(), static_cast<std::size_t>(len));
  752. // determine if we need to append ".0"
  753. const bool value_is_int_like =
  754. std::none_of(number_buffer.begin(), number_buffer.begin() + len + 1,
  755. [](char c)
  756. {
  757. return c == '.' || c == 'e';
  758. });
  759. if (value_is_int_like)
  760. {
  761. o->write_characters(".0", 2);
  762. }
  763. }
  764. /*!
  765. @brief check whether a string is UTF-8 encoded
  766. The function checks each byte of a string whether it is UTF-8 encoded. The
  767. result of the check is stored in the @a state parameter. The function must
  768. be called initially with state 0 (accept). State 1 means the string must
  769. be rejected, because the current byte is not allowed. If the string is
  770. completely processed, but the state is non-zero, the string ended
  771. prematurely; that is, the last byte indicated more bytes should have
  772. followed.
  773. @param[in,out] state the state of the decoding
  774. @param[in,out] codep codepoint (valid only if resulting state is UTF8_ACCEPT)
  775. @param[in] byte next byte to decode
  776. @return new state
  777. @note The function has been edited: a std::array is used.
  778. @copyright Copyright (c) 2008-2009 Bjoern Hoehrmann <bjoern@hoehrmann.de>
  779. @sa http://bjoern.hoehrmann.de/utf-8/decoder/dfa/
  780. */
  781. static std::uint8_t decode(std::uint8_t& state, std::uint32_t& codep, const std::uint8_t byte) noexcept
  782. {
  783. static const std::array<std::uint8_t, 400> utf8d =
  784. {
  785. {
  786. 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, // 00..1F
  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, // 20..3F
  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, // 40..5F
  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, // 60..7F
  790. 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, // 80..9F
  791. 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, // A0..BF
  792. 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, // C0..DF
  793. 0xA, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x4, 0x3, 0x3, // E0..EF
  794. 0xB, 0x6, 0x6, 0x6, 0x5, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, // F0..FF
  795. 0x0, 0x1, 0x2, 0x3, 0x5, 0x8, 0x7, 0x1, 0x1, 0x1, 0x4, 0x6, 0x1, 0x1, 0x1, 0x1, // s0..s0
  796. 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, // s1..s2
  797. 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, // s3..s4
  798. 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, // s5..s6
  799. 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 // s7..s8
  800. }
  801. };
  802. JSON_ASSERT(byte < utf8d.size());
  803. const std::uint8_t type = utf8d[byte];
  804. codep = (state != UTF8_ACCEPT)
  805. ? (byte & 0x3fu) | (codep << 6u)
  806. : (0xFFu >> type) & (byte);
  807. const std::size_t index = 256u + static_cast<size_t>(state) * 16u + static_cast<size_t>(type);
  808. JSON_ASSERT(index < utf8d.size());
  809. state = utf8d[index];
  810. return state;
  811. }
  812. /*
  813. * Overload to make the compiler happy while it is instantiating
  814. * dump_integer for number_unsigned_t.
  815. * Must never be called.
  816. */
  817. number_unsigned_t remove_sign(number_unsigned_t x)
  818. {
  819. JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
  820. return x; // LCOV_EXCL_LINE
  821. }
  822. /*
  823. * Helper function for dump_integer
  824. *
  825. * This function takes a negative signed integer and returns its absolute
  826. * value as unsigned integer. The plus/minus shuffling is necessary as we can
  827. * not directly remove the sign of an arbitrary signed integer as the
  828. * absolute values of INT_MIN and INT_MAX are usually not the same. See
  829. * #1708 for details.
  830. */
  831. inline number_unsigned_t remove_sign(number_integer_t x) noexcept
  832. {
  833. JSON_ASSERT(x < 0 && x < (std::numeric_limits<number_integer_t>::max)()); // NOLINT(misc-redundant-expression)
  834. return static_cast<number_unsigned_t>(-(x + 1)) + 1;
  835. }
  836. private:
  837. /// the output of the serializer
  838. output_adapter_t<char> o = nullptr;
  839. /// a (hopefully) large enough character buffer
  840. std::array<char, 64> number_buffer{{}};
  841. /// the locale
  842. const std::lconv* loc = nullptr;
  843. /// the locale's thousand separator character
  844. const char thousands_sep = '\0';
  845. /// the locale's decimal point character
  846. const char decimal_point = '\0';
  847. /// string buffer
  848. std::array<char, 512> string_buffer{{}};
  849. /// the indentation character
  850. const char indent_char;
  851. /// the indentation string
  852. string_t indent_string;
  853. /// error_handler how to react on decoding errors
  854. const error_handler_t error_handler;
  855. };
  856. } // namespace detail
  857. NLOHMANN_JSON_NAMESPACE_END