binary_writer.hpp 35 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949
  1. #pragma once
  2. #include <algorithm> // reverse
  3. #include <array> // array
  4. #include <cstdint> // uint8_t, uint16_t, uint32_t, uint64_t
  5. #include <cstring> // memcpy
  6. #include <limits> // numeric_limits
  7. #include <nlohmann/detail/input/binary_reader.hpp>
  8. #include <nlohmann/detail/output/output_adapters.hpp>
  9. namespace nlohmann
  10. {
  11. namespace detail
  12. {
  13. ///////////////////
  14. // binary writer //
  15. ///////////////////
  16. /*!
  17. @brief serialization to CBOR and MessagePack values
  18. */
  19. template<typename BasicJsonType, typename CharType>
  20. class binary_writer
  21. {
  22. public:
  23. /*!
  24. @brief create a binary writer
  25. @param[in] adapter output adapter to write to
  26. */
  27. explicit binary_writer(output_adapter_t<CharType> adapter) : oa(adapter)
  28. {
  29. assert(oa);
  30. }
  31. /*!
  32. @brief[in] j JSON value to serialize
  33. */
  34. void write_cbor(const BasicJsonType& j)
  35. {
  36. switch (j.type())
  37. {
  38. case value_t::null:
  39. {
  40. oa->write_character(static_cast<CharType>(0xF6));
  41. break;
  42. }
  43. case value_t::boolean:
  44. {
  45. oa->write_character(j.m_value.boolean
  46. ? static_cast<CharType>(0xF5)
  47. : static_cast<CharType>(0xF4));
  48. break;
  49. }
  50. case value_t::number_integer:
  51. {
  52. if (j.m_value.number_integer >= 0)
  53. {
  54. // CBOR does not differentiate between positive signed
  55. // integers and unsigned integers. Therefore, we used the
  56. // code from the value_t::number_unsigned case here.
  57. if (j.m_value.number_integer <= 0x17)
  58. {
  59. write_number(static_cast<uint8_t>(j.m_value.number_integer));
  60. }
  61. else if (j.m_value.number_integer <= (std::numeric_limits<uint8_t>::max)())
  62. {
  63. oa->write_character(static_cast<CharType>(0x18));
  64. write_number(static_cast<uint8_t>(j.m_value.number_integer));
  65. }
  66. else if (j.m_value.number_integer <= (std::numeric_limits<uint16_t>::max)())
  67. {
  68. oa->write_character(static_cast<CharType>(0x19));
  69. write_number(static_cast<uint16_t>(j.m_value.number_integer));
  70. }
  71. else if (j.m_value.number_integer <= (std::numeric_limits<uint32_t>::max)())
  72. {
  73. oa->write_character(static_cast<CharType>(0x1A));
  74. write_number(static_cast<uint32_t>(j.m_value.number_integer));
  75. }
  76. else
  77. {
  78. oa->write_character(static_cast<CharType>(0x1B));
  79. write_number(static_cast<uint64_t>(j.m_value.number_integer));
  80. }
  81. }
  82. else
  83. {
  84. // The conversions below encode the sign in the first
  85. // byte, and the value is converted to a positive number.
  86. const auto positive_number = -1 - j.m_value.number_integer;
  87. if (j.m_value.number_integer >= -24)
  88. {
  89. write_number(static_cast<uint8_t>(0x20 + positive_number));
  90. }
  91. else if (positive_number <= (std::numeric_limits<uint8_t>::max)())
  92. {
  93. oa->write_character(static_cast<CharType>(0x38));
  94. write_number(static_cast<uint8_t>(positive_number));
  95. }
  96. else if (positive_number <= (std::numeric_limits<uint16_t>::max)())
  97. {
  98. oa->write_character(static_cast<CharType>(0x39));
  99. write_number(static_cast<uint16_t>(positive_number));
  100. }
  101. else if (positive_number <= (std::numeric_limits<uint32_t>::max)())
  102. {
  103. oa->write_character(static_cast<CharType>(0x3A));
  104. write_number(static_cast<uint32_t>(positive_number));
  105. }
  106. else
  107. {
  108. oa->write_character(static_cast<CharType>(0x3B));
  109. write_number(static_cast<uint64_t>(positive_number));
  110. }
  111. }
  112. break;
  113. }
  114. case value_t::number_unsigned:
  115. {
  116. if (j.m_value.number_unsigned <= 0x17)
  117. {
  118. write_number(static_cast<uint8_t>(j.m_value.number_unsigned));
  119. }
  120. else if (j.m_value.number_unsigned <= (std::numeric_limits<uint8_t>::max)())
  121. {
  122. oa->write_character(static_cast<CharType>(0x18));
  123. write_number(static_cast<uint8_t>(j.m_value.number_unsigned));
  124. }
  125. else if (j.m_value.number_unsigned <= (std::numeric_limits<uint16_t>::max)())
  126. {
  127. oa->write_character(static_cast<CharType>(0x19));
  128. write_number(static_cast<uint16_t>(j.m_value.number_unsigned));
  129. }
  130. else if (j.m_value.number_unsigned <= (std::numeric_limits<uint32_t>::max)())
  131. {
  132. oa->write_character(static_cast<CharType>(0x1A));
  133. write_number(static_cast<uint32_t>(j.m_value.number_unsigned));
  134. }
  135. else
  136. {
  137. oa->write_character(static_cast<CharType>(0x1B));
  138. write_number(static_cast<uint64_t>(j.m_value.number_unsigned));
  139. }
  140. break;
  141. }
  142. case value_t::number_float:
  143. {
  144. oa->write_character(get_cbor_float_prefix(j.m_value.number_float));
  145. write_number(j.m_value.number_float);
  146. break;
  147. }
  148. case value_t::string:
  149. {
  150. // step 1: write control byte and the string length
  151. const auto N = j.m_value.string->size();
  152. if (N <= 0x17)
  153. {
  154. write_number(static_cast<uint8_t>(0x60 + N));
  155. }
  156. else if (N <= (std::numeric_limits<uint8_t>::max)())
  157. {
  158. oa->write_character(static_cast<CharType>(0x78));
  159. write_number(static_cast<uint8_t>(N));
  160. }
  161. else if (N <= (std::numeric_limits<uint16_t>::max)())
  162. {
  163. oa->write_character(static_cast<CharType>(0x79));
  164. write_number(static_cast<uint16_t>(N));
  165. }
  166. else if (N <= (std::numeric_limits<uint32_t>::max)())
  167. {
  168. oa->write_character(static_cast<CharType>(0x7A));
  169. write_number(static_cast<uint32_t>(N));
  170. }
  171. // LCOV_EXCL_START
  172. else if (N <= (std::numeric_limits<uint64_t>::max)())
  173. {
  174. oa->write_character(static_cast<CharType>(0x7B));
  175. write_number(static_cast<uint64_t>(N));
  176. }
  177. // LCOV_EXCL_STOP
  178. // step 2: write the string
  179. oa->write_characters(
  180. reinterpret_cast<const CharType*>(j.m_value.string->c_str()),
  181. j.m_value.string->size());
  182. break;
  183. }
  184. case value_t::array:
  185. {
  186. // step 1: write control byte and the array size
  187. const auto N = j.m_value.array->size();
  188. if (N <= 0x17)
  189. {
  190. write_number(static_cast<uint8_t>(0x80 + N));
  191. }
  192. else if (N <= (std::numeric_limits<uint8_t>::max)())
  193. {
  194. oa->write_character(static_cast<CharType>(0x98));
  195. write_number(static_cast<uint8_t>(N));
  196. }
  197. else if (N <= (std::numeric_limits<uint16_t>::max)())
  198. {
  199. oa->write_character(static_cast<CharType>(0x99));
  200. write_number(static_cast<uint16_t>(N));
  201. }
  202. else if (N <= (std::numeric_limits<uint32_t>::max)())
  203. {
  204. oa->write_character(static_cast<CharType>(0x9A));
  205. write_number(static_cast<uint32_t>(N));
  206. }
  207. // LCOV_EXCL_START
  208. else if (N <= (std::numeric_limits<uint64_t>::max)())
  209. {
  210. oa->write_character(static_cast<CharType>(0x9B));
  211. write_number(static_cast<uint64_t>(N));
  212. }
  213. // LCOV_EXCL_STOP
  214. // step 2: write each element
  215. for (const auto& el : *j.m_value.array)
  216. {
  217. write_cbor(el);
  218. }
  219. break;
  220. }
  221. case value_t::object:
  222. {
  223. // step 1: write control byte and the object size
  224. const auto N = j.m_value.object->size();
  225. if (N <= 0x17)
  226. {
  227. write_number(static_cast<uint8_t>(0xA0 + N));
  228. }
  229. else if (N <= (std::numeric_limits<uint8_t>::max)())
  230. {
  231. oa->write_character(static_cast<CharType>(0xB8));
  232. write_number(static_cast<uint8_t>(N));
  233. }
  234. else if (N <= (std::numeric_limits<uint16_t>::max)())
  235. {
  236. oa->write_character(static_cast<CharType>(0xB9));
  237. write_number(static_cast<uint16_t>(N));
  238. }
  239. else if (N <= (std::numeric_limits<uint32_t>::max)())
  240. {
  241. oa->write_character(static_cast<CharType>(0xBA));
  242. write_number(static_cast<uint32_t>(N));
  243. }
  244. // LCOV_EXCL_START
  245. else if (N <= (std::numeric_limits<uint64_t>::max)())
  246. {
  247. oa->write_character(static_cast<CharType>(0xBB));
  248. write_number(static_cast<uint64_t>(N));
  249. }
  250. // LCOV_EXCL_STOP
  251. // step 2: write each element
  252. for (const auto& el : *j.m_value.object)
  253. {
  254. write_cbor(el.first);
  255. write_cbor(el.second);
  256. }
  257. break;
  258. }
  259. default:
  260. break;
  261. }
  262. }
  263. /*!
  264. @brief[in] j JSON value to serialize
  265. */
  266. void write_msgpack(const BasicJsonType& j)
  267. {
  268. switch (j.type())
  269. {
  270. case value_t::null: // nil
  271. {
  272. oa->write_character(static_cast<CharType>(0xC0));
  273. break;
  274. }
  275. case value_t::boolean: // true and false
  276. {
  277. oa->write_character(j.m_value.boolean
  278. ? static_cast<CharType>(0xC3)
  279. : static_cast<CharType>(0xC2));
  280. break;
  281. }
  282. case value_t::number_integer:
  283. {
  284. if (j.m_value.number_integer >= 0)
  285. {
  286. // MessagePack does not differentiate between positive
  287. // signed integers and unsigned integers. Therefore, we used
  288. // the code from the value_t::number_unsigned case here.
  289. if (j.m_value.number_unsigned < 128)
  290. {
  291. // positive fixnum
  292. write_number(static_cast<uint8_t>(j.m_value.number_integer));
  293. }
  294. else if (j.m_value.number_unsigned <= (std::numeric_limits<uint8_t>::max)())
  295. {
  296. // uint 8
  297. oa->write_character(static_cast<CharType>(0xCC));
  298. write_number(static_cast<uint8_t>(j.m_value.number_integer));
  299. }
  300. else if (j.m_value.number_unsigned <= (std::numeric_limits<uint16_t>::max)())
  301. {
  302. // uint 16
  303. oa->write_character(static_cast<CharType>(0xCD));
  304. write_number(static_cast<uint16_t>(j.m_value.number_integer));
  305. }
  306. else if (j.m_value.number_unsigned <= (std::numeric_limits<uint32_t>::max)())
  307. {
  308. // uint 32
  309. oa->write_character(static_cast<CharType>(0xCE));
  310. write_number(static_cast<uint32_t>(j.m_value.number_integer));
  311. }
  312. else if (j.m_value.number_unsigned <= (std::numeric_limits<uint64_t>::max)())
  313. {
  314. // uint 64
  315. oa->write_character(static_cast<CharType>(0xCF));
  316. write_number(static_cast<uint64_t>(j.m_value.number_integer));
  317. }
  318. }
  319. else
  320. {
  321. if (j.m_value.number_integer >= -32)
  322. {
  323. // negative fixnum
  324. write_number(static_cast<int8_t>(j.m_value.number_integer));
  325. }
  326. else if (j.m_value.number_integer >= (std::numeric_limits<int8_t>::min)() and
  327. j.m_value.number_integer <= (std::numeric_limits<int8_t>::max)())
  328. {
  329. // int 8
  330. oa->write_character(static_cast<CharType>(0xD0));
  331. write_number(static_cast<int8_t>(j.m_value.number_integer));
  332. }
  333. else if (j.m_value.number_integer >= (std::numeric_limits<int16_t>::min)() and
  334. j.m_value.number_integer <= (std::numeric_limits<int16_t>::max)())
  335. {
  336. // int 16
  337. oa->write_character(static_cast<CharType>(0xD1));
  338. write_number(static_cast<int16_t>(j.m_value.number_integer));
  339. }
  340. else if (j.m_value.number_integer >= (std::numeric_limits<int32_t>::min)() and
  341. j.m_value.number_integer <= (std::numeric_limits<int32_t>::max)())
  342. {
  343. // int 32
  344. oa->write_character(static_cast<CharType>(0xD2));
  345. write_number(static_cast<int32_t>(j.m_value.number_integer));
  346. }
  347. else if (j.m_value.number_integer >= (std::numeric_limits<int64_t>::min)() and
  348. j.m_value.number_integer <= (std::numeric_limits<int64_t>::max)())
  349. {
  350. // int 64
  351. oa->write_character(static_cast<CharType>(0xD3));
  352. write_number(static_cast<int64_t>(j.m_value.number_integer));
  353. }
  354. }
  355. break;
  356. }
  357. case value_t::number_unsigned:
  358. {
  359. if (j.m_value.number_unsigned < 128)
  360. {
  361. // positive fixnum
  362. write_number(static_cast<uint8_t>(j.m_value.number_integer));
  363. }
  364. else if (j.m_value.number_unsigned <= (std::numeric_limits<uint8_t>::max)())
  365. {
  366. // uint 8
  367. oa->write_character(static_cast<CharType>(0xCC));
  368. write_number(static_cast<uint8_t>(j.m_value.number_integer));
  369. }
  370. else if (j.m_value.number_unsigned <= (std::numeric_limits<uint16_t>::max)())
  371. {
  372. // uint 16
  373. oa->write_character(static_cast<CharType>(0xCD));
  374. write_number(static_cast<uint16_t>(j.m_value.number_integer));
  375. }
  376. else if (j.m_value.number_unsigned <= (std::numeric_limits<uint32_t>::max)())
  377. {
  378. // uint 32
  379. oa->write_character(static_cast<CharType>(0xCE));
  380. write_number(static_cast<uint32_t>(j.m_value.number_integer));
  381. }
  382. else if (j.m_value.number_unsigned <= (std::numeric_limits<uint64_t>::max)())
  383. {
  384. // uint 64
  385. oa->write_character(static_cast<CharType>(0xCF));
  386. write_number(static_cast<uint64_t>(j.m_value.number_integer));
  387. }
  388. break;
  389. }
  390. case value_t::number_float:
  391. {
  392. oa->write_character(get_msgpack_float_prefix(j.m_value.number_float));
  393. write_number(j.m_value.number_float);
  394. break;
  395. }
  396. case value_t::string:
  397. {
  398. // step 1: write control byte and the string length
  399. const auto N = j.m_value.string->size();
  400. if (N <= 31)
  401. {
  402. // fixstr
  403. write_number(static_cast<uint8_t>(0xA0 | N));
  404. }
  405. else if (N <= (std::numeric_limits<uint8_t>::max)())
  406. {
  407. // str 8
  408. oa->write_character(static_cast<CharType>(0xD9));
  409. write_number(static_cast<uint8_t>(N));
  410. }
  411. else if (N <= (std::numeric_limits<uint16_t>::max)())
  412. {
  413. // str 16
  414. oa->write_character(static_cast<CharType>(0xDA));
  415. write_number(static_cast<uint16_t>(N));
  416. }
  417. else if (N <= (std::numeric_limits<uint32_t>::max)())
  418. {
  419. // str 32
  420. oa->write_character(static_cast<CharType>(0xDB));
  421. write_number(static_cast<uint32_t>(N));
  422. }
  423. // step 2: write the string
  424. oa->write_characters(
  425. reinterpret_cast<const CharType*>(j.m_value.string->c_str()),
  426. j.m_value.string->size());
  427. break;
  428. }
  429. case value_t::array:
  430. {
  431. // step 1: write control byte and the array size
  432. const auto N = j.m_value.array->size();
  433. if (N <= 15)
  434. {
  435. // fixarray
  436. write_number(static_cast<uint8_t>(0x90 | N));
  437. }
  438. else if (N <= (std::numeric_limits<uint16_t>::max)())
  439. {
  440. // array 16
  441. oa->write_character(static_cast<CharType>(0xDC));
  442. write_number(static_cast<uint16_t>(N));
  443. }
  444. else if (N <= (std::numeric_limits<uint32_t>::max)())
  445. {
  446. // array 32
  447. oa->write_character(static_cast<CharType>(0xDD));
  448. write_number(static_cast<uint32_t>(N));
  449. }
  450. // step 2: write each element
  451. for (const auto& el : *j.m_value.array)
  452. {
  453. write_msgpack(el);
  454. }
  455. break;
  456. }
  457. case value_t::object:
  458. {
  459. // step 1: write control byte and the object size
  460. const auto N = j.m_value.object->size();
  461. if (N <= 15)
  462. {
  463. // fixmap
  464. write_number(static_cast<uint8_t>(0x80 | (N & 0xF)));
  465. }
  466. else if (N <= (std::numeric_limits<uint16_t>::max)())
  467. {
  468. // map 16
  469. oa->write_character(static_cast<CharType>(0xDE));
  470. write_number(static_cast<uint16_t>(N));
  471. }
  472. else if (N <= (std::numeric_limits<uint32_t>::max)())
  473. {
  474. // map 32
  475. oa->write_character(static_cast<CharType>(0xDF));
  476. write_number(static_cast<uint32_t>(N));
  477. }
  478. // step 2: write each element
  479. for (const auto& el : *j.m_value.object)
  480. {
  481. write_msgpack(el.first);
  482. write_msgpack(el.second);
  483. }
  484. break;
  485. }
  486. default:
  487. break;
  488. }
  489. }
  490. /*!
  491. @param[in] j JSON value to serialize
  492. @param[in] use_count whether to use '#' prefixes (optimized format)
  493. @param[in] use_type whether to use '$' prefixes (optimized format)
  494. @param[in] add_prefix whether prefixes need to be used for this value
  495. */
  496. void write_ubjson(const BasicJsonType& j, const bool use_count,
  497. const bool use_type, const bool add_prefix = true)
  498. {
  499. switch (j.type())
  500. {
  501. case value_t::null:
  502. {
  503. if (add_prefix)
  504. {
  505. oa->write_character(static_cast<CharType>('Z'));
  506. }
  507. break;
  508. }
  509. case value_t::boolean:
  510. {
  511. if (add_prefix)
  512. oa->write_character(j.m_value.boolean
  513. ? static_cast<CharType>('T')
  514. : static_cast<CharType>('F'));
  515. break;
  516. }
  517. case value_t::number_integer:
  518. {
  519. write_number_with_ubjson_prefix(j.m_value.number_integer, add_prefix);
  520. break;
  521. }
  522. case value_t::number_unsigned:
  523. {
  524. write_number_with_ubjson_prefix(j.m_value.number_unsigned, add_prefix);
  525. break;
  526. }
  527. case value_t::number_float:
  528. {
  529. write_number_with_ubjson_prefix(j.m_value.number_float, add_prefix);
  530. break;
  531. }
  532. case value_t::string:
  533. {
  534. if (add_prefix)
  535. {
  536. oa->write_character(static_cast<CharType>('S'));
  537. }
  538. write_number_with_ubjson_prefix(j.m_value.string->size(), true);
  539. oa->write_characters(
  540. reinterpret_cast<const CharType*>(j.m_value.string->c_str()),
  541. j.m_value.string->size());
  542. break;
  543. }
  544. case value_t::array:
  545. {
  546. if (add_prefix)
  547. {
  548. oa->write_character(static_cast<CharType>('['));
  549. }
  550. bool prefix_required = true;
  551. if (use_type and not j.m_value.array->empty())
  552. {
  553. assert(use_count);
  554. const CharType first_prefix = ubjson_prefix(j.front());
  555. const bool same_prefix = std::all_of(j.begin() + 1, j.end(),
  556. [this, first_prefix](const BasicJsonType & v)
  557. {
  558. return ubjson_prefix(v) == first_prefix;
  559. });
  560. if (same_prefix)
  561. {
  562. prefix_required = false;
  563. oa->write_character(static_cast<CharType>('$'));
  564. oa->write_character(first_prefix);
  565. }
  566. }
  567. if (use_count)
  568. {
  569. oa->write_character(static_cast<CharType>('#'));
  570. write_number_with_ubjson_prefix(j.m_value.array->size(), true);
  571. }
  572. for (const auto& el : *j.m_value.array)
  573. {
  574. write_ubjson(el, use_count, use_type, prefix_required);
  575. }
  576. if (not use_count)
  577. {
  578. oa->write_character(static_cast<CharType>(']'));
  579. }
  580. break;
  581. }
  582. case value_t::object:
  583. {
  584. if (add_prefix)
  585. {
  586. oa->write_character(static_cast<CharType>('{'));
  587. }
  588. bool prefix_required = true;
  589. if (use_type and not j.m_value.object->empty())
  590. {
  591. assert(use_count);
  592. const CharType first_prefix = ubjson_prefix(j.front());
  593. const bool same_prefix = std::all_of(j.begin(), j.end(),
  594. [this, first_prefix](const BasicJsonType & v)
  595. {
  596. return ubjson_prefix(v) == first_prefix;
  597. });
  598. if (same_prefix)
  599. {
  600. prefix_required = false;
  601. oa->write_character(static_cast<CharType>('$'));
  602. oa->write_character(first_prefix);
  603. }
  604. }
  605. if (use_count)
  606. {
  607. oa->write_character(static_cast<CharType>('#'));
  608. write_number_with_ubjson_prefix(j.m_value.object->size(), true);
  609. }
  610. for (const auto& el : *j.m_value.object)
  611. {
  612. write_number_with_ubjson_prefix(el.first.size(), true);
  613. oa->write_characters(
  614. reinterpret_cast<const CharType*>(el.first.c_str()),
  615. el.first.size());
  616. write_ubjson(el.second, use_count, use_type, prefix_required);
  617. }
  618. if (not use_count)
  619. {
  620. oa->write_character(static_cast<CharType>('}'));
  621. }
  622. break;
  623. }
  624. default:
  625. break;
  626. }
  627. }
  628. private:
  629. /*
  630. @brief write a number to output input
  631. @param[in] n number of type @a NumberType
  632. @tparam NumberType the type of the number
  633. @note This function needs to respect the system's endianess, because bytes
  634. in CBOR, MessagePack, and UBJSON are stored in network order (big
  635. endian) and therefore need reordering on little endian systems.
  636. */
  637. template<typename NumberType>
  638. void write_number(const NumberType n)
  639. {
  640. // step 1: write number to array of length NumberType
  641. std::array<CharType, sizeof(NumberType)> vec;
  642. std::memcpy(vec.data(), &n, sizeof(NumberType));
  643. // step 2: write array to output (with possible reordering)
  644. if (is_little_endian)
  645. {
  646. // reverse byte order prior to conversion if necessary
  647. std::reverse(vec.begin(), vec.end());
  648. }
  649. oa->write_characters(vec.data(), sizeof(NumberType));
  650. }
  651. // UBJSON: write number (floating point)
  652. template<typename NumberType, typename std::enable_if<
  653. std::is_floating_point<NumberType>::value, int>::type = 0>
  654. void write_number_with_ubjson_prefix(const NumberType n,
  655. const bool add_prefix)
  656. {
  657. if (add_prefix)
  658. {
  659. oa->write_character(get_ubjson_float_prefix(n));
  660. }
  661. write_number(n);
  662. }
  663. // UBJSON: write number (unsigned integer)
  664. template<typename NumberType, typename std::enable_if<
  665. std::is_unsigned<NumberType>::value, int>::type = 0>
  666. void write_number_with_ubjson_prefix(const NumberType n,
  667. const bool add_prefix)
  668. {
  669. if (n <= static_cast<uint64_t>((std::numeric_limits<int8_t>::max)()))
  670. {
  671. if (add_prefix)
  672. {
  673. oa->write_character(static_cast<CharType>('i')); // int8
  674. }
  675. write_number(static_cast<uint8_t>(n));
  676. }
  677. else if (n <= (std::numeric_limits<uint8_t>::max)())
  678. {
  679. if (add_prefix)
  680. {
  681. oa->write_character(static_cast<CharType>('U')); // uint8
  682. }
  683. write_number(static_cast<uint8_t>(n));
  684. }
  685. else if (n <= static_cast<uint64_t>((std::numeric_limits<int16_t>::max)()))
  686. {
  687. if (add_prefix)
  688. {
  689. oa->write_character(static_cast<CharType>('I')); // int16
  690. }
  691. write_number(static_cast<int16_t>(n));
  692. }
  693. else if (n <= static_cast<uint64_t>((std::numeric_limits<int32_t>::max)()))
  694. {
  695. if (add_prefix)
  696. {
  697. oa->write_character(static_cast<CharType>('l')); // int32
  698. }
  699. write_number(static_cast<int32_t>(n));
  700. }
  701. else if (n <= static_cast<uint64_t>((std::numeric_limits<int64_t>::max)()))
  702. {
  703. if (add_prefix)
  704. {
  705. oa->write_character(static_cast<CharType>('L')); // int64
  706. }
  707. write_number(static_cast<int64_t>(n));
  708. }
  709. else
  710. {
  711. JSON_THROW(out_of_range::create(407, "number overflow serializing " + std::to_string(n)));
  712. }
  713. }
  714. // UBJSON: write number (signed integer)
  715. template<typename NumberType, typename std::enable_if<
  716. std::is_signed<NumberType>::value and
  717. not std::is_floating_point<NumberType>::value, int>::type = 0>
  718. void write_number_with_ubjson_prefix(const NumberType n,
  719. const bool add_prefix)
  720. {
  721. if ((std::numeric_limits<int8_t>::min)() <= n and n <= (std::numeric_limits<int8_t>::max)())
  722. {
  723. if (add_prefix)
  724. {
  725. oa->write_character(static_cast<CharType>('i')); // int8
  726. }
  727. write_number(static_cast<int8_t>(n));
  728. }
  729. else if (static_cast<int64_t>((std::numeric_limits<uint8_t>::min)()) <= n and n <= static_cast<int64_t>((std::numeric_limits<uint8_t>::max)()))
  730. {
  731. if (add_prefix)
  732. {
  733. oa->write_character(static_cast<CharType>('U')); // uint8
  734. }
  735. write_number(static_cast<uint8_t>(n));
  736. }
  737. else if ((std::numeric_limits<int16_t>::min)() <= n and n <= (std::numeric_limits<int16_t>::max)())
  738. {
  739. if (add_prefix)
  740. {
  741. oa->write_character(static_cast<CharType>('I')); // int16
  742. }
  743. write_number(static_cast<int16_t>(n));
  744. }
  745. else if ((std::numeric_limits<int32_t>::min)() <= n and n <= (std::numeric_limits<int32_t>::max)())
  746. {
  747. if (add_prefix)
  748. {
  749. oa->write_character(static_cast<CharType>('l')); // int32
  750. }
  751. write_number(static_cast<int32_t>(n));
  752. }
  753. else if ((std::numeric_limits<int64_t>::min)() <= n and n <= (std::numeric_limits<int64_t>::max)())
  754. {
  755. if (add_prefix)
  756. {
  757. oa->write_character(static_cast<CharType>('L')); // int64
  758. }
  759. write_number(static_cast<int64_t>(n));
  760. }
  761. // LCOV_EXCL_START
  762. else
  763. {
  764. JSON_THROW(out_of_range::create(407, "number overflow serializing " + std::to_string(n)));
  765. }
  766. // LCOV_EXCL_STOP
  767. }
  768. /*!
  769. @brief determine the type prefix of container values
  770. @note This function does not need to be 100% accurate when it comes to
  771. integer limits. In case a number exceeds the limits of int64_t,
  772. this will be detected by a later call to function
  773. write_number_with_ubjson_prefix. Therefore, we return 'L' for any
  774. value that does not fit the previous limits.
  775. */
  776. CharType ubjson_prefix(const BasicJsonType& j) const noexcept
  777. {
  778. switch (j.type())
  779. {
  780. case value_t::null:
  781. return 'Z';
  782. case value_t::boolean:
  783. return j.m_value.boolean ? 'T' : 'F';
  784. case value_t::number_integer:
  785. {
  786. if ((std::numeric_limits<int8_t>::min)() <= j.m_value.number_integer and j.m_value.number_integer <= (std::numeric_limits<int8_t>::max)())
  787. {
  788. return 'i';
  789. }
  790. else if ((std::numeric_limits<uint8_t>::min)() <= j.m_value.number_integer and j.m_value.number_integer <= (std::numeric_limits<uint8_t>::max)())
  791. {
  792. return 'U';
  793. }
  794. else if ((std::numeric_limits<int16_t>::min)() <= j.m_value.number_integer and j.m_value.number_integer <= (std::numeric_limits<int16_t>::max)())
  795. {
  796. return 'I';
  797. }
  798. else if ((std::numeric_limits<int32_t>::min)() <= j.m_value.number_integer and j.m_value.number_integer <= (std::numeric_limits<int32_t>::max)())
  799. {
  800. return 'l';
  801. }
  802. else // no check and assume int64_t (see note above)
  803. {
  804. return 'L';
  805. }
  806. }
  807. case value_t::number_unsigned:
  808. {
  809. if (j.m_value.number_unsigned <= (std::numeric_limits<int8_t>::max)())
  810. {
  811. return 'i';
  812. }
  813. else if (j.m_value.number_unsigned <= (std::numeric_limits<uint8_t>::max)())
  814. {
  815. return 'U';
  816. }
  817. else if (j.m_value.number_unsigned <= (std::numeric_limits<int16_t>::max)())
  818. {
  819. return 'I';
  820. }
  821. else if (j.m_value.number_unsigned <= (std::numeric_limits<int32_t>::max)())
  822. {
  823. return 'l';
  824. }
  825. else // no check and assume int64_t (see note above)
  826. {
  827. return 'L';
  828. }
  829. }
  830. case value_t::number_float:
  831. return get_ubjson_float_prefix(j.m_value.number_float);
  832. case value_t::string:
  833. return 'S';
  834. case value_t::array:
  835. return '[';
  836. case value_t::object:
  837. return '{';
  838. default: // discarded values
  839. return 'N';
  840. }
  841. }
  842. static constexpr CharType get_cbor_float_prefix(float)
  843. {
  844. return static_cast<CharType>(0xFA); // Single-Precision Float
  845. }
  846. static constexpr CharType get_cbor_float_prefix(double)
  847. {
  848. return static_cast<CharType>(0xFB); // Double-Precision Float
  849. }
  850. static constexpr CharType get_msgpack_float_prefix(float)
  851. {
  852. return static_cast<CharType>(0xCA); // float 32
  853. }
  854. static constexpr CharType get_msgpack_float_prefix(double)
  855. {
  856. return static_cast<CharType>(0xCB); // float 64
  857. }
  858. static constexpr CharType get_ubjson_float_prefix(float)
  859. {
  860. return 'd'; // float 32
  861. }
  862. static constexpr CharType get_ubjson_float_prefix(double)
  863. {
  864. return 'D'; // float 64
  865. }
  866. private:
  867. /// whether we can assume little endianess
  868. const bool is_little_endian = binary_reader<BasicJsonType>::little_endianess();
  869. /// the output
  870. output_adapter_t<CharType> oa = nullptr;
  871. };
  872. }
  873. }