binary_writer.hpp 56 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549
  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 <string> // string
  8. #include <nlohmann/detail/input/binary_reader.hpp>
  9. #include <nlohmann/detail/macro_scope.hpp>
  10. #include <nlohmann/detail/output/output_adapters.hpp>
  11. namespace nlohmann
  12. {
  13. namespace detail
  14. {
  15. ///////////////////
  16. // binary writer //
  17. ///////////////////
  18. /*!
  19. @brief serialization to CBOR and MessagePack values
  20. */
  21. template<typename BasicJsonType, typename CharType>
  22. class binary_writer
  23. {
  24. using string_t = typename BasicJsonType::string_t;
  25. using internal_binary_t = typename BasicJsonType::internal_binary_t;
  26. public:
  27. /*!
  28. @brief create a binary writer
  29. @param[in] adapter output adapter to write to
  30. */
  31. explicit binary_writer(output_adapter_t<CharType> adapter) : oa(adapter)
  32. {
  33. assert(oa);
  34. }
  35. /*!
  36. @param[in] j JSON value to serialize
  37. @pre j.type() == value_t::object
  38. */
  39. void write_bson(const BasicJsonType& j)
  40. {
  41. switch (j.type())
  42. {
  43. case value_t::object:
  44. {
  45. write_bson_object(*j.m_value.object);
  46. break;
  47. }
  48. default:
  49. {
  50. JSON_THROW(type_error::create(317, "to serialize to BSON, top-level type must be object, but is " + std::string(j.type_name())));
  51. }
  52. }
  53. }
  54. /*!
  55. @param[in] j JSON value to serialize
  56. */
  57. void write_cbor(const BasicJsonType& j)
  58. {
  59. switch (j.type())
  60. {
  61. case value_t::null:
  62. {
  63. oa->write_character(to_char_type(0xF6));
  64. break;
  65. }
  66. case value_t::boolean:
  67. {
  68. oa->write_character(j.m_value.boolean
  69. ? to_char_type(0xF5)
  70. : to_char_type(0xF4));
  71. break;
  72. }
  73. case value_t::number_integer:
  74. {
  75. if (j.m_value.number_integer >= 0)
  76. {
  77. // CBOR does not differentiate between positive signed
  78. // integers and unsigned integers. Therefore, we used the
  79. // code from the value_t::number_unsigned case here.
  80. if (j.m_value.number_integer <= 0x17)
  81. {
  82. write_number(static_cast<std::uint8_t>(j.m_value.number_integer));
  83. }
  84. else if (j.m_value.number_integer <= (std::numeric_limits<std::uint8_t>::max)())
  85. {
  86. oa->write_character(to_char_type(0x18));
  87. write_number(static_cast<std::uint8_t>(j.m_value.number_integer));
  88. }
  89. else if (j.m_value.number_integer <= (std::numeric_limits<std::uint16_t>::max)())
  90. {
  91. oa->write_character(to_char_type(0x19));
  92. write_number(static_cast<std::uint16_t>(j.m_value.number_integer));
  93. }
  94. else if (j.m_value.number_integer <= (std::numeric_limits<std::uint32_t>::max)())
  95. {
  96. oa->write_character(to_char_type(0x1A));
  97. write_number(static_cast<std::uint32_t>(j.m_value.number_integer));
  98. }
  99. else
  100. {
  101. oa->write_character(to_char_type(0x1B));
  102. write_number(static_cast<std::uint64_t>(j.m_value.number_integer));
  103. }
  104. }
  105. else
  106. {
  107. // The conversions below encode the sign in the first
  108. // byte, and the value is converted to a positive number.
  109. const auto positive_number = -1 - j.m_value.number_integer;
  110. if (j.m_value.number_integer >= -24)
  111. {
  112. write_number(static_cast<std::uint8_t>(0x20 + positive_number));
  113. }
  114. else if (positive_number <= (std::numeric_limits<std::uint8_t>::max)())
  115. {
  116. oa->write_character(to_char_type(0x38));
  117. write_number(static_cast<std::uint8_t>(positive_number));
  118. }
  119. else if (positive_number <= (std::numeric_limits<std::uint16_t>::max)())
  120. {
  121. oa->write_character(to_char_type(0x39));
  122. write_number(static_cast<std::uint16_t>(positive_number));
  123. }
  124. else if (positive_number <= (std::numeric_limits<std::uint32_t>::max)())
  125. {
  126. oa->write_character(to_char_type(0x3A));
  127. write_number(static_cast<std::uint32_t>(positive_number));
  128. }
  129. else
  130. {
  131. oa->write_character(to_char_type(0x3B));
  132. write_number(static_cast<std::uint64_t>(positive_number));
  133. }
  134. }
  135. break;
  136. }
  137. case value_t::number_unsigned:
  138. {
  139. if (j.m_value.number_unsigned <= 0x17)
  140. {
  141. write_number(static_cast<std::uint8_t>(j.m_value.number_unsigned));
  142. }
  143. else if (j.m_value.number_unsigned <= (std::numeric_limits<std::uint8_t>::max)())
  144. {
  145. oa->write_character(to_char_type(0x18));
  146. write_number(static_cast<std::uint8_t>(j.m_value.number_unsigned));
  147. }
  148. else if (j.m_value.number_unsigned <= (std::numeric_limits<std::uint16_t>::max)())
  149. {
  150. oa->write_character(to_char_type(0x19));
  151. write_number(static_cast<std::uint16_t>(j.m_value.number_unsigned));
  152. }
  153. else if (j.m_value.number_unsigned <= (std::numeric_limits<std::uint32_t>::max)())
  154. {
  155. oa->write_character(to_char_type(0x1A));
  156. write_number(static_cast<std::uint32_t>(j.m_value.number_unsigned));
  157. }
  158. else
  159. {
  160. oa->write_character(to_char_type(0x1B));
  161. write_number(static_cast<std::uint64_t>(j.m_value.number_unsigned));
  162. }
  163. break;
  164. }
  165. case value_t::number_float:
  166. {
  167. oa->write_character(get_cbor_float_prefix(j.m_value.number_float));
  168. write_number(j.m_value.number_float);
  169. break;
  170. }
  171. case value_t::string:
  172. {
  173. // step 1: write control byte and the string length
  174. const auto N = j.m_value.string->size();
  175. if (N <= 0x17)
  176. {
  177. write_number(static_cast<std::uint8_t>(0x60 + N));
  178. }
  179. else if (N <= (std::numeric_limits<std::uint8_t>::max)())
  180. {
  181. oa->write_character(to_char_type(0x78));
  182. write_number(static_cast<std::uint8_t>(N));
  183. }
  184. else if (N <= (std::numeric_limits<std::uint16_t>::max)())
  185. {
  186. oa->write_character(to_char_type(0x79));
  187. write_number(static_cast<std::uint16_t>(N));
  188. }
  189. else if (N <= (std::numeric_limits<std::uint32_t>::max)())
  190. {
  191. oa->write_character(to_char_type(0x7A));
  192. write_number(static_cast<std::uint32_t>(N));
  193. }
  194. // LCOV_EXCL_START
  195. else if (N <= (std::numeric_limits<std::uint64_t>::max)())
  196. {
  197. oa->write_character(to_char_type(0x7B));
  198. write_number(static_cast<std::uint64_t>(N));
  199. }
  200. // LCOV_EXCL_STOP
  201. // step 2: write the string
  202. oa->write_characters(
  203. reinterpret_cast<const CharType*>(j.m_value.string->c_str()),
  204. j.m_value.string->size());
  205. break;
  206. }
  207. case value_t::array:
  208. {
  209. // step 1: write control byte and the array size
  210. const auto N = j.m_value.array->size();
  211. if (N <= 0x17)
  212. {
  213. write_number(static_cast<std::uint8_t>(0x80 + N));
  214. }
  215. else if (N <= (std::numeric_limits<std::uint8_t>::max)())
  216. {
  217. oa->write_character(to_char_type(0x98));
  218. write_number(static_cast<std::uint8_t>(N));
  219. }
  220. else if (N <= (std::numeric_limits<std::uint16_t>::max)())
  221. {
  222. oa->write_character(to_char_type(0x99));
  223. write_number(static_cast<std::uint16_t>(N));
  224. }
  225. else if (N <= (std::numeric_limits<std::uint32_t>::max)())
  226. {
  227. oa->write_character(to_char_type(0x9A));
  228. write_number(static_cast<std::uint32_t>(N));
  229. }
  230. // LCOV_EXCL_START
  231. else if (N <= (std::numeric_limits<std::uint64_t>::max)())
  232. {
  233. oa->write_character(to_char_type(0x9B));
  234. write_number(static_cast<std::uint64_t>(N));
  235. }
  236. // LCOV_EXCL_STOP
  237. // step 2: write each element
  238. for (const auto& el : *j.m_value.array)
  239. {
  240. write_cbor(el);
  241. }
  242. break;
  243. }
  244. case value_t::binary:
  245. {
  246. // step 1: write control byte and the binary array size
  247. const auto N = j.m_value.binary->size();
  248. if (N <= 0x17)
  249. {
  250. write_number(static_cast<std::uint8_t>(0x40 + N));
  251. }
  252. else if (N <= (std::numeric_limits<std::uint8_t>::max)())
  253. {
  254. oa->write_character(to_char_type(0x58));
  255. write_number(static_cast<std::uint8_t>(N));
  256. }
  257. else if (N <= (std::numeric_limits<std::uint16_t>::max)())
  258. {
  259. oa->write_character(to_char_type(0x59));
  260. write_number(static_cast<std::uint16_t>(N));
  261. }
  262. else if (N <= (std::numeric_limits<std::uint32_t>::max)())
  263. {
  264. oa->write_character(to_char_type(0x5A));
  265. write_number(static_cast<std::uint32_t>(N));
  266. }
  267. // LCOV_EXCL_START
  268. else if (N <= (std::numeric_limits<std::uint64_t>::max)())
  269. {
  270. oa->write_character(to_char_type(0x5B));
  271. write_number(static_cast<std::uint64_t>(N));
  272. }
  273. // LCOV_EXCL_STOP
  274. // step 2: write each element
  275. oa->write_characters(
  276. reinterpret_cast<const CharType*>(j.m_value.binary->data()),
  277. N);
  278. break;
  279. }
  280. case value_t::object:
  281. {
  282. // step 1: write control byte and the object size
  283. const auto N = j.m_value.object->size();
  284. if (N <= 0x17)
  285. {
  286. write_number(static_cast<std::uint8_t>(0xA0 + N));
  287. }
  288. else if (N <= (std::numeric_limits<std::uint8_t>::max)())
  289. {
  290. oa->write_character(to_char_type(0xB8));
  291. write_number(static_cast<std::uint8_t>(N));
  292. }
  293. else if (N <= (std::numeric_limits<std::uint16_t>::max)())
  294. {
  295. oa->write_character(to_char_type(0xB9));
  296. write_number(static_cast<std::uint16_t>(N));
  297. }
  298. else if (N <= (std::numeric_limits<std::uint32_t>::max)())
  299. {
  300. oa->write_character(to_char_type(0xBA));
  301. write_number(static_cast<std::uint32_t>(N));
  302. }
  303. // LCOV_EXCL_START
  304. else if (N <= (std::numeric_limits<std::uint64_t>::max)())
  305. {
  306. oa->write_character(to_char_type(0xBB));
  307. write_number(static_cast<std::uint64_t>(N));
  308. }
  309. // LCOV_EXCL_STOP
  310. // step 2: write each element
  311. for (const auto& el : *j.m_value.object)
  312. {
  313. write_cbor(el.first);
  314. write_cbor(el.second);
  315. }
  316. break;
  317. }
  318. default:
  319. break;
  320. }
  321. }
  322. /*!
  323. @param[in] j JSON value to serialize
  324. */
  325. void write_msgpack(const BasicJsonType& j)
  326. {
  327. switch (j.type())
  328. {
  329. case value_t::null: // nil
  330. {
  331. oa->write_character(to_char_type(0xC0));
  332. break;
  333. }
  334. case value_t::boolean: // true and false
  335. {
  336. oa->write_character(j.m_value.boolean
  337. ? to_char_type(0xC3)
  338. : to_char_type(0xC2));
  339. break;
  340. }
  341. case value_t::number_integer:
  342. {
  343. if (j.m_value.number_integer >= 0)
  344. {
  345. // MessagePack does not differentiate between positive
  346. // signed integers and unsigned integers. Therefore, we used
  347. // the code from the value_t::number_unsigned case here.
  348. if (j.m_value.number_unsigned < 128)
  349. {
  350. // positive fixnum
  351. write_number(static_cast<std::uint8_t>(j.m_value.number_integer));
  352. }
  353. else if (j.m_value.number_unsigned <= (std::numeric_limits<std::uint8_t>::max)())
  354. {
  355. // uint 8
  356. oa->write_character(to_char_type(0xCC));
  357. write_number(static_cast<std::uint8_t>(j.m_value.number_integer));
  358. }
  359. else if (j.m_value.number_unsigned <= (std::numeric_limits<std::uint16_t>::max)())
  360. {
  361. // uint 16
  362. oa->write_character(to_char_type(0xCD));
  363. write_number(static_cast<std::uint16_t>(j.m_value.number_integer));
  364. }
  365. else if (j.m_value.number_unsigned <= (std::numeric_limits<std::uint32_t>::max)())
  366. {
  367. // uint 32
  368. oa->write_character(to_char_type(0xCE));
  369. write_number(static_cast<std::uint32_t>(j.m_value.number_integer));
  370. }
  371. else if (j.m_value.number_unsigned <= (std::numeric_limits<std::uint64_t>::max)())
  372. {
  373. // uint 64
  374. oa->write_character(to_char_type(0xCF));
  375. write_number(static_cast<std::uint64_t>(j.m_value.number_integer));
  376. }
  377. }
  378. else
  379. {
  380. if (j.m_value.number_integer >= -32)
  381. {
  382. // negative fixnum
  383. write_number(static_cast<std::int8_t>(j.m_value.number_integer));
  384. }
  385. else if (j.m_value.number_integer >= (std::numeric_limits<std::int8_t>::min)() and
  386. j.m_value.number_integer <= (std::numeric_limits<std::int8_t>::max)())
  387. {
  388. // int 8
  389. oa->write_character(to_char_type(0xD0));
  390. write_number(static_cast<std::int8_t>(j.m_value.number_integer));
  391. }
  392. else if (j.m_value.number_integer >= (std::numeric_limits<std::int16_t>::min)() and
  393. j.m_value.number_integer <= (std::numeric_limits<std::int16_t>::max)())
  394. {
  395. // int 16
  396. oa->write_character(to_char_type(0xD1));
  397. write_number(static_cast<std::int16_t>(j.m_value.number_integer));
  398. }
  399. else if (j.m_value.number_integer >= (std::numeric_limits<std::int32_t>::min)() and
  400. j.m_value.number_integer <= (std::numeric_limits<std::int32_t>::max)())
  401. {
  402. // int 32
  403. oa->write_character(to_char_type(0xD2));
  404. write_number(static_cast<std::int32_t>(j.m_value.number_integer));
  405. }
  406. else if (j.m_value.number_integer >= (std::numeric_limits<std::int64_t>::min)() and
  407. j.m_value.number_integer <= (std::numeric_limits<std::int64_t>::max)())
  408. {
  409. // int 64
  410. oa->write_character(to_char_type(0xD3));
  411. write_number(static_cast<std::int64_t>(j.m_value.number_integer));
  412. }
  413. }
  414. break;
  415. }
  416. case value_t::number_unsigned:
  417. {
  418. if (j.m_value.number_unsigned < 128)
  419. {
  420. // positive fixnum
  421. write_number(static_cast<std::uint8_t>(j.m_value.number_integer));
  422. }
  423. else if (j.m_value.number_unsigned <= (std::numeric_limits<std::uint8_t>::max)())
  424. {
  425. // uint 8
  426. oa->write_character(to_char_type(0xCC));
  427. write_number(static_cast<std::uint8_t>(j.m_value.number_integer));
  428. }
  429. else if (j.m_value.number_unsigned <= (std::numeric_limits<std::uint16_t>::max)())
  430. {
  431. // uint 16
  432. oa->write_character(to_char_type(0xCD));
  433. write_number(static_cast<std::uint16_t>(j.m_value.number_integer));
  434. }
  435. else if (j.m_value.number_unsigned <= (std::numeric_limits<std::uint32_t>::max)())
  436. {
  437. // uint 32
  438. oa->write_character(to_char_type(0xCE));
  439. write_number(static_cast<std::uint32_t>(j.m_value.number_integer));
  440. }
  441. else if (j.m_value.number_unsigned <= (std::numeric_limits<std::uint64_t>::max)())
  442. {
  443. // uint 64
  444. oa->write_character(to_char_type(0xCF));
  445. write_number(static_cast<std::uint64_t>(j.m_value.number_integer));
  446. }
  447. break;
  448. }
  449. case value_t::number_float:
  450. {
  451. oa->write_character(get_msgpack_float_prefix(j.m_value.number_float));
  452. write_number(j.m_value.number_float);
  453. break;
  454. }
  455. case value_t::string:
  456. {
  457. // step 1: write control byte and the string length
  458. const auto N = j.m_value.string->size();
  459. if (N <= 31)
  460. {
  461. // fixstr
  462. write_number(static_cast<std::uint8_t>(0xA0 | N));
  463. }
  464. else if (N <= (std::numeric_limits<std::uint8_t>::max)())
  465. {
  466. // str 8
  467. oa->write_character(to_char_type(0xD9));
  468. write_number(static_cast<std::uint8_t>(N));
  469. }
  470. else if (N <= (std::numeric_limits<std::uint16_t>::max)())
  471. {
  472. // str 16
  473. oa->write_character(to_char_type(0xDA));
  474. write_number(static_cast<std::uint16_t>(N));
  475. }
  476. else if (N <= (std::numeric_limits<std::uint32_t>::max)())
  477. {
  478. // str 32
  479. oa->write_character(to_char_type(0xDB));
  480. write_number(static_cast<std::uint32_t>(N));
  481. }
  482. // step 2: write the string
  483. oa->write_characters(
  484. reinterpret_cast<const CharType*>(j.m_value.string->c_str()),
  485. j.m_value.string->size());
  486. break;
  487. }
  488. case value_t::array:
  489. {
  490. // step 1: write control byte and the array size
  491. const auto N = j.m_value.array->size();
  492. if (N <= 15)
  493. {
  494. // fixarray
  495. write_number(static_cast<std::uint8_t>(0x90 | N));
  496. }
  497. else if (N <= (std::numeric_limits<std::uint16_t>::max)())
  498. {
  499. // array 16
  500. oa->write_character(to_char_type(0xDC));
  501. write_number(static_cast<std::uint16_t>(N));
  502. }
  503. else if (N <= (std::numeric_limits<std::uint32_t>::max)())
  504. {
  505. // array 32
  506. oa->write_character(to_char_type(0xDD));
  507. write_number(static_cast<std::uint32_t>(N));
  508. }
  509. // step 2: write each element
  510. for (const auto& el : *j.m_value.array)
  511. {
  512. write_msgpack(el);
  513. }
  514. break;
  515. }
  516. case value_t::binary:
  517. {
  518. // step 0: determine if the binary type has a set subtype to
  519. // determine whether or not to use the ext or fixext types
  520. const bool use_ext = j.m_value.binary->has_subtype;
  521. // step 1: write control byte and the byte string length
  522. const auto N = j.m_value.binary->size();
  523. if (N <= (std::numeric_limits<std::uint8_t>::max)())
  524. {
  525. std::uint8_t output_type;
  526. bool fixed = true;
  527. if (use_ext)
  528. {
  529. switch (N)
  530. {
  531. case 1:
  532. output_type = 0xD4; // fixext 1
  533. break;
  534. case 2:
  535. output_type = 0xD5; // fixext 2
  536. break;
  537. case 4:
  538. output_type = 0xD6; // fixext 4
  539. break;
  540. case 8:
  541. output_type = 0xD7; // fixext 8
  542. break;
  543. case 16:
  544. output_type = 0xD8; // fixext 16
  545. break;
  546. default:
  547. output_type = 0xC7; // ext 8
  548. fixed = false;
  549. break;
  550. }
  551. }
  552. else
  553. {
  554. output_type = 0xC4; // bin 8
  555. fixed = false;
  556. }
  557. oa->write_character(to_char_type(output_type));
  558. if (not fixed)
  559. {
  560. write_number(static_cast<std::uint8_t>(N));
  561. }
  562. }
  563. else if (N <= (std::numeric_limits<std::uint16_t>::max)())
  564. {
  565. std::uint8_t output_type;
  566. if (use_ext)
  567. {
  568. output_type = 0xC8; // ext 16
  569. }
  570. else
  571. {
  572. output_type = 0xC5; // bin 16
  573. }
  574. oa->write_character(to_char_type(output_type));
  575. write_number(static_cast<std::uint16_t>(N));
  576. }
  577. else if (N <= (std::numeric_limits<std::uint32_t>::max)())
  578. {
  579. std::uint8_t output_type;
  580. if (use_ext)
  581. {
  582. output_type = 0xC9; // ext 32
  583. }
  584. else
  585. {
  586. output_type = 0xC6; // bin 32
  587. }
  588. oa->write_character(to_char_type(output_type));
  589. write_number(static_cast<std::uint32_t>(N));
  590. }
  591. // step 1.5: if this is an ext type, write the subtype
  592. if (use_ext)
  593. {
  594. write_number(j.m_value.binary->subtype);
  595. }
  596. // step 2: write the byte string
  597. oa->write_characters(
  598. reinterpret_cast<const CharType*>(j.m_value.binary->data()),
  599. N);
  600. break;
  601. }
  602. case value_t::object:
  603. {
  604. // step 1: write control byte and the object size
  605. const auto N = j.m_value.object->size();
  606. if (N <= 15)
  607. {
  608. // fixmap
  609. write_number(static_cast<std::uint8_t>(0x80 | (N & 0xF)));
  610. }
  611. else if (N <= (std::numeric_limits<std::uint16_t>::max)())
  612. {
  613. // map 16
  614. oa->write_character(to_char_type(0xDE));
  615. write_number(static_cast<std::uint16_t>(N));
  616. }
  617. else if (N <= (std::numeric_limits<std::uint32_t>::max)())
  618. {
  619. // map 32
  620. oa->write_character(to_char_type(0xDF));
  621. write_number(static_cast<std::uint32_t>(N));
  622. }
  623. // step 2: write each element
  624. for (const auto& el : *j.m_value.object)
  625. {
  626. write_msgpack(el.first);
  627. write_msgpack(el.second);
  628. }
  629. break;
  630. }
  631. default:
  632. break;
  633. }
  634. }
  635. /*!
  636. @param[in] j JSON value to serialize
  637. @param[in] use_count whether to use '#' prefixes (optimized format)
  638. @param[in] use_type whether to use '$' prefixes (optimized format)
  639. @param[in] add_prefix whether prefixes need to be used for this value
  640. */
  641. void write_ubjson(const BasicJsonType& j, const bool use_count,
  642. const bool use_type, const bool add_prefix = true)
  643. {
  644. switch (j.type())
  645. {
  646. case value_t::null:
  647. {
  648. if (add_prefix)
  649. {
  650. oa->write_character(to_char_type('Z'));
  651. }
  652. break;
  653. }
  654. case value_t::boolean:
  655. {
  656. if (add_prefix)
  657. {
  658. oa->write_character(j.m_value.boolean
  659. ? to_char_type('T')
  660. : to_char_type('F'));
  661. }
  662. break;
  663. }
  664. case value_t::number_integer:
  665. {
  666. write_number_with_ubjson_prefix(j.m_value.number_integer, add_prefix);
  667. break;
  668. }
  669. case value_t::number_unsigned:
  670. {
  671. write_number_with_ubjson_prefix(j.m_value.number_unsigned, add_prefix);
  672. break;
  673. }
  674. case value_t::number_float:
  675. {
  676. write_number_with_ubjson_prefix(j.m_value.number_float, add_prefix);
  677. break;
  678. }
  679. case value_t::string:
  680. {
  681. if (add_prefix)
  682. {
  683. oa->write_character(to_char_type('S'));
  684. }
  685. write_number_with_ubjson_prefix(j.m_value.string->size(), true);
  686. oa->write_characters(
  687. reinterpret_cast<const CharType*>(j.m_value.string->c_str()),
  688. j.m_value.string->size());
  689. break;
  690. }
  691. case value_t::array:
  692. {
  693. if (add_prefix)
  694. {
  695. oa->write_character(to_char_type('['));
  696. }
  697. bool prefix_required = true;
  698. if (use_type and not j.m_value.array->empty())
  699. {
  700. assert(use_count);
  701. const CharType first_prefix = ubjson_prefix(j.front());
  702. const bool same_prefix = std::all_of(j.begin() + 1, j.end(),
  703. [this, first_prefix](const BasicJsonType & v)
  704. {
  705. return ubjson_prefix(v) == first_prefix;
  706. });
  707. if (same_prefix)
  708. {
  709. prefix_required = false;
  710. oa->write_character(to_char_type('$'));
  711. oa->write_character(first_prefix);
  712. }
  713. }
  714. if (use_count)
  715. {
  716. oa->write_character(to_char_type('#'));
  717. write_number_with_ubjson_prefix(j.m_value.array->size(), true);
  718. }
  719. for (const auto& el : *j.m_value.array)
  720. {
  721. write_ubjson(el, use_count, use_type, prefix_required);
  722. }
  723. if (not use_count)
  724. {
  725. oa->write_character(to_char_type(']'));
  726. }
  727. break;
  728. }
  729. case value_t::binary:
  730. {
  731. if (add_prefix)
  732. {
  733. oa->write_character(to_char_type('['));
  734. }
  735. if (use_type and not j.m_value.binary->empty())
  736. {
  737. assert(use_count);
  738. oa->write_character(to_char_type('$'));
  739. oa->write_character('U');
  740. }
  741. if (use_count)
  742. {
  743. oa->write_character(to_char_type('#'));
  744. write_number_with_ubjson_prefix(j.m_value.binary->size(), true);
  745. }
  746. if (use_type)
  747. {
  748. oa->write_characters(
  749. reinterpret_cast<const CharType*>(j.m_value.binary->data()),
  750. j.m_value.binary->size());
  751. }
  752. else
  753. {
  754. for (size_t i = 0; i < j.m_value.binary->size(); ++i)
  755. {
  756. oa->write_character(to_char_type('U'));
  757. oa->write_character(j.m_value.binary->data()[i]);
  758. }
  759. }
  760. if (not use_count)
  761. {
  762. oa->write_character(to_char_type(']'));
  763. }
  764. break;
  765. }
  766. case value_t::object:
  767. {
  768. if (add_prefix)
  769. {
  770. oa->write_character(to_char_type('{'));
  771. }
  772. bool prefix_required = true;
  773. if (use_type and not j.m_value.object->empty())
  774. {
  775. assert(use_count);
  776. const CharType first_prefix = ubjson_prefix(j.front());
  777. const bool same_prefix = std::all_of(j.begin(), j.end(),
  778. [this, first_prefix](const BasicJsonType & v)
  779. {
  780. return ubjson_prefix(v) == first_prefix;
  781. });
  782. if (same_prefix)
  783. {
  784. prefix_required = false;
  785. oa->write_character(to_char_type('$'));
  786. oa->write_character(first_prefix);
  787. }
  788. }
  789. if (use_count)
  790. {
  791. oa->write_character(to_char_type('#'));
  792. write_number_with_ubjson_prefix(j.m_value.object->size(), true);
  793. }
  794. for (const auto& el : *j.m_value.object)
  795. {
  796. write_number_with_ubjson_prefix(el.first.size(), true);
  797. oa->write_characters(
  798. reinterpret_cast<const CharType*>(el.first.c_str()),
  799. el.first.size());
  800. write_ubjson(el.second, use_count, use_type, prefix_required);
  801. }
  802. if (not use_count)
  803. {
  804. oa->write_character(to_char_type('}'));
  805. }
  806. break;
  807. }
  808. default:
  809. break;
  810. }
  811. }
  812. private:
  813. //////////
  814. // BSON //
  815. //////////
  816. /*!
  817. @return The size of a BSON document entry header, including the id marker
  818. and the entry name size (and its null-terminator).
  819. */
  820. static std::size_t calc_bson_entry_header_size(const string_t& name)
  821. {
  822. const auto it = name.find(static_cast<typename string_t::value_type>(0));
  823. if (JSON_HEDLEY_UNLIKELY(it != BasicJsonType::string_t::npos))
  824. {
  825. JSON_THROW(out_of_range::create(409,
  826. "BSON key cannot contain code point U+0000 (at byte " + std::to_string(it) + ")"));
  827. }
  828. return /*id*/ 1ul + name.size() + /*zero-terminator*/1u;
  829. }
  830. /*!
  831. @brief Writes the given @a element_type and @a name to the output adapter
  832. */
  833. void write_bson_entry_header(const string_t& name,
  834. const std::uint8_t element_type)
  835. {
  836. oa->write_character(to_char_type(element_type)); // boolean
  837. oa->write_characters(
  838. reinterpret_cast<const CharType*>(name.c_str()),
  839. name.size() + 1u);
  840. }
  841. /*!
  842. @brief Writes a BSON element with key @a name and boolean value @a value
  843. */
  844. void write_bson_boolean(const string_t& name,
  845. const bool value)
  846. {
  847. write_bson_entry_header(name, 0x08);
  848. oa->write_character(value ? to_char_type(0x01) : to_char_type(0x00));
  849. }
  850. /*!
  851. @brief Writes a BSON element with key @a name and double value @a value
  852. */
  853. void write_bson_double(const string_t& name,
  854. const double value)
  855. {
  856. write_bson_entry_header(name, 0x01);
  857. write_number<double, true>(value);
  858. }
  859. /*!
  860. @return The size of the BSON-encoded string in @a value
  861. */
  862. static std::size_t calc_bson_string_size(const string_t& value)
  863. {
  864. return sizeof(std::int32_t) + value.size() + 1ul;
  865. }
  866. /*!
  867. @brief Writes a BSON element with key @a name and string value @a value
  868. */
  869. void write_bson_string(const string_t& name,
  870. const string_t& value)
  871. {
  872. write_bson_entry_header(name, 0x02);
  873. write_number<std::int32_t, true>(static_cast<std::int32_t>(value.size() + 1ul));
  874. oa->write_characters(
  875. reinterpret_cast<const CharType*>(value.c_str()),
  876. value.size() + 1);
  877. }
  878. /*!
  879. @brief Writes a BSON element with key @a name and null value
  880. */
  881. void write_bson_null(const string_t& name)
  882. {
  883. write_bson_entry_header(name, 0x0A);
  884. }
  885. /*!
  886. @return The size of the BSON-encoded integer @a value
  887. */
  888. static std::size_t calc_bson_integer_size(const std::int64_t value)
  889. {
  890. return (std::numeric_limits<std::int32_t>::min)() <= value and value <= (std::numeric_limits<std::int32_t>::max)()
  891. ? sizeof(std::int32_t)
  892. : sizeof(std::int64_t);
  893. }
  894. /*!
  895. @brief Writes a BSON element with key @a name and integer @a value
  896. */
  897. void write_bson_integer(const string_t& name,
  898. const std::int64_t value)
  899. {
  900. if ((std::numeric_limits<std::int32_t>::min)() <= value and value <= (std::numeric_limits<std::int32_t>::max)())
  901. {
  902. write_bson_entry_header(name, 0x10); // int32
  903. write_number<std::int32_t, true>(static_cast<std::int32_t>(value));
  904. }
  905. else
  906. {
  907. write_bson_entry_header(name, 0x12); // int64
  908. write_number<std::int64_t, true>(static_cast<std::int64_t>(value));
  909. }
  910. }
  911. /*!
  912. @return The size of the BSON-encoded unsigned integer in @a j
  913. */
  914. static constexpr std::size_t calc_bson_unsigned_size(const std::uint64_t value) noexcept
  915. {
  916. return (value <= static_cast<std::uint64_t>((std::numeric_limits<std::int32_t>::max)()))
  917. ? sizeof(std::int32_t)
  918. : sizeof(std::int64_t);
  919. }
  920. /*!
  921. @brief Writes a BSON element with key @a name and unsigned @a value
  922. */
  923. void write_bson_unsigned(const string_t& name,
  924. const std::uint64_t value)
  925. {
  926. if (value <= static_cast<std::uint64_t>((std::numeric_limits<std::int32_t>::max)()))
  927. {
  928. write_bson_entry_header(name, 0x10 /* int32 */);
  929. write_number<std::int32_t, true>(static_cast<std::int32_t>(value));
  930. }
  931. else if (value <= static_cast<std::uint64_t>((std::numeric_limits<std::int64_t>::max)()))
  932. {
  933. write_bson_entry_header(name, 0x12 /* int64 */);
  934. write_number<std::int64_t, true>(static_cast<std::int64_t>(value));
  935. }
  936. else
  937. {
  938. JSON_THROW(out_of_range::create(407, "integer number " + std::to_string(value) + " cannot be represented by BSON as it does not fit int64"));
  939. }
  940. }
  941. /*!
  942. @brief Writes a BSON element with key @a name and object @a value
  943. */
  944. void write_bson_object_entry(const string_t& name,
  945. const typename BasicJsonType::object_t& value)
  946. {
  947. write_bson_entry_header(name, 0x03); // object
  948. write_bson_object(value);
  949. }
  950. /*!
  951. @return The size of the BSON-encoded array @a value
  952. */
  953. static std::size_t calc_bson_array_size(const typename BasicJsonType::array_t& value)
  954. {
  955. std::size_t array_index = 0ul;
  956. const std::size_t embedded_document_size = std::accumulate(std::begin(value), std::end(value), std::size_t(0), [&array_index](std::size_t result, const typename BasicJsonType::array_t::value_type & el)
  957. {
  958. return result + calc_bson_element_size(std::to_string(array_index++), el);
  959. });
  960. return sizeof(std::int32_t) + embedded_document_size + 1ul;
  961. }
  962. /*!
  963. @return The size of the BSON-encoded binary array @a value
  964. */
  965. static std::size_t calc_bson_binary_size(const typename BasicJsonType::internal_binary_t& value)
  966. {
  967. return sizeof(std::int32_t) + value.size() + 1ul;
  968. }
  969. /*!
  970. @brief Writes a BSON element with key @a name and array @a value
  971. */
  972. void write_bson_array(const string_t& name,
  973. const typename BasicJsonType::array_t& value)
  974. {
  975. write_bson_entry_header(name, 0x04); // array
  976. write_number<std::int32_t, true>(static_cast<std::int32_t>(calc_bson_array_size(value)));
  977. std::size_t array_index = 0ul;
  978. for (const auto& el : value)
  979. {
  980. write_bson_element(std::to_string(array_index++), el);
  981. }
  982. oa->write_character(to_char_type(0x00));
  983. }
  984. /*!
  985. @brief Writes a BSON element with key @a name and binary value @a value
  986. */
  987. void write_bson_binary(const string_t& name,
  988. const internal_binary_t& value)
  989. {
  990. write_bson_entry_header(name, 0x05);
  991. write_number<std::int32_t, true>(static_cast<std::int32_t>(value.size()));
  992. std::uint8_t subtype = 0x00; // Generic Binary Subtype
  993. if (value.has_subtype)
  994. {
  995. subtype = value.subtype;
  996. }
  997. write_number(subtype);
  998. oa->write_characters(
  999. reinterpret_cast<const CharType*>(value.data()),
  1000. value.size());
  1001. }
  1002. /*!
  1003. @brief Calculates the size necessary to serialize the JSON value @a j with its @a name
  1004. @return The calculated size for the BSON document entry for @a j with the given @a name.
  1005. */
  1006. static std::size_t calc_bson_element_size(const string_t& name,
  1007. const BasicJsonType& j)
  1008. {
  1009. const auto header_size = calc_bson_entry_header_size(name);
  1010. switch (j.type())
  1011. {
  1012. case value_t::object:
  1013. return header_size + calc_bson_object_size(*j.m_value.object);
  1014. case value_t::array:
  1015. return header_size + calc_bson_array_size(*j.m_value.array);
  1016. case value_t::binary:
  1017. return header_size + calc_bson_binary_size(*j.m_value.binary);
  1018. case value_t::boolean:
  1019. return header_size + 1ul;
  1020. case value_t::number_float:
  1021. return header_size + 8ul;
  1022. case value_t::number_integer:
  1023. return header_size + calc_bson_integer_size(j.m_value.number_integer);
  1024. case value_t::number_unsigned:
  1025. return header_size + calc_bson_unsigned_size(j.m_value.number_unsigned);
  1026. case value_t::string:
  1027. return header_size + calc_bson_string_size(*j.m_value.string);
  1028. case value_t::null:
  1029. return header_size + 0ul;
  1030. // LCOV_EXCL_START
  1031. default:
  1032. assert(false);
  1033. return 0ul;
  1034. // LCOV_EXCL_STOP
  1035. }
  1036. }
  1037. /*!
  1038. @brief Serializes the JSON value @a j to BSON and associates it with the
  1039. key @a name.
  1040. @param name The name to associate with the JSON entity @a j within the
  1041. current BSON document
  1042. @return The size of the BSON entry
  1043. */
  1044. void write_bson_element(const string_t& name,
  1045. const BasicJsonType& j)
  1046. {
  1047. switch (j.type())
  1048. {
  1049. case value_t::object:
  1050. return write_bson_object_entry(name, *j.m_value.object);
  1051. case value_t::array:
  1052. return write_bson_array(name, *j.m_value.array);
  1053. case value_t::binary:
  1054. return write_bson_binary(name, *j.m_value.binary);
  1055. case value_t::boolean:
  1056. return write_bson_boolean(name, j.m_value.boolean);
  1057. case value_t::number_float:
  1058. return write_bson_double(name, j.m_value.number_float);
  1059. case value_t::number_integer:
  1060. return write_bson_integer(name, j.m_value.number_integer);
  1061. case value_t::number_unsigned:
  1062. return write_bson_unsigned(name, j.m_value.number_unsigned);
  1063. case value_t::string:
  1064. return write_bson_string(name, *j.m_value.string);
  1065. case value_t::null:
  1066. return write_bson_null(name);
  1067. // LCOV_EXCL_START
  1068. default:
  1069. assert(false);
  1070. return;
  1071. // LCOV_EXCL_STOP
  1072. }
  1073. }
  1074. /*!
  1075. @brief Calculates the size of the BSON serialization of the given
  1076. JSON-object @a j.
  1077. @param[in] j JSON value to serialize
  1078. @pre j.type() == value_t::object
  1079. */
  1080. static std::size_t calc_bson_object_size(const typename BasicJsonType::object_t& value)
  1081. {
  1082. std::size_t document_size = std::accumulate(value.begin(), value.end(), std::size_t(0),
  1083. [](size_t result, const typename BasicJsonType::object_t::value_type & el)
  1084. {
  1085. return result += calc_bson_element_size(el.first, el.second);
  1086. });
  1087. return sizeof(std::int32_t) + document_size + 1ul;
  1088. }
  1089. /*!
  1090. @param[in] j JSON value to serialize
  1091. @pre j.type() == value_t::object
  1092. */
  1093. void write_bson_object(const typename BasicJsonType::object_t& value)
  1094. {
  1095. write_number<std::int32_t, true>(static_cast<std::int32_t>(calc_bson_object_size(value)));
  1096. for (const auto& el : value)
  1097. {
  1098. write_bson_element(el.first, el.second);
  1099. }
  1100. oa->write_character(to_char_type(0x00));
  1101. }
  1102. //////////
  1103. // CBOR //
  1104. //////////
  1105. static constexpr CharType get_cbor_float_prefix(float /*unused*/)
  1106. {
  1107. return to_char_type(0xFA); // Single-Precision Float
  1108. }
  1109. static constexpr CharType get_cbor_float_prefix(double /*unused*/)
  1110. {
  1111. return to_char_type(0xFB); // Double-Precision Float
  1112. }
  1113. /////////////
  1114. // MsgPack //
  1115. /////////////
  1116. static constexpr CharType get_msgpack_float_prefix(float /*unused*/)
  1117. {
  1118. return to_char_type(0xCA); // float 32
  1119. }
  1120. static constexpr CharType get_msgpack_float_prefix(double /*unused*/)
  1121. {
  1122. return to_char_type(0xCB); // float 64
  1123. }
  1124. ////////////
  1125. // UBJSON //
  1126. ////////////
  1127. // UBJSON: write number (floating point)
  1128. template<typename NumberType, typename std::enable_if<
  1129. std::is_floating_point<NumberType>::value, int>::type = 0>
  1130. void write_number_with_ubjson_prefix(const NumberType n,
  1131. const bool add_prefix)
  1132. {
  1133. if (add_prefix)
  1134. {
  1135. oa->write_character(get_ubjson_float_prefix(n));
  1136. }
  1137. write_number(n);
  1138. }
  1139. // UBJSON: write number (unsigned integer)
  1140. template<typename NumberType, typename std::enable_if<
  1141. std::is_unsigned<NumberType>::value, int>::type = 0>
  1142. void write_number_with_ubjson_prefix(const NumberType n,
  1143. const bool add_prefix)
  1144. {
  1145. if (n <= static_cast<std::uint64_t>((std::numeric_limits<std::int8_t>::max)()))
  1146. {
  1147. if (add_prefix)
  1148. {
  1149. oa->write_character(to_char_type('i')); // int8
  1150. }
  1151. write_number(static_cast<std::uint8_t>(n));
  1152. }
  1153. else if (n <= (std::numeric_limits<std::uint8_t>::max)())
  1154. {
  1155. if (add_prefix)
  1156. {
  1157. oa->write_character(to_char_type('U')); // uint8
  1158. }
  1159. write_number(static_cast<std::uint8_t>(n));
  1160. }
  1161. else if (n <= static_cast<std::uint64_t>((std::numeric_limits<std::int16_t>::max)()))
  1162. {
  1163. if (add_prefix)
  1164. {
  1165. oa->write_character(to_char_type('I')); // int16
  1166. }
  1167. write_number(static_cast<std::int16_t>(n));
  1168. }
  1169. else if (n <= static_cast<std::uint64_t>((std::numeric_limits<std::int32_t>::max)()))
  1170. {
  1171. if (add_prefix)
  1172. {
  1173. oa->write_character(to_char_type('l')); // int32
  1174. }
  1175. write_number(static_cast<std::int32_t>(n));
  1176. }
  1177. else if (n <= static_cast<std::uint64_t>((std::numeric_limits<std::int64_t>::max)()))
  1178. {
  1179. if (add_prefix)
  1180. {
  1181. oa->write_character(to_char_type('L')); // int64
  1182. }
  1183. write_number(static_cast<std::int64_t>(n));
  1184. }
  1185. else
  1186. {
  1187. JSON_THROW(out_of_range::create(407, "integer number " + std::to_string(n) + " cannot be represented by UBJSON as it does not fit int64"));
  1188. }
  1189. }
  1190. // UBJSON: write number (signed integer)
  1191. template<typename NumberType, typename std::enable_if<
  1192. std::is_signed<NumberType>::value and
  1193. not std::is_floating_point<NumberType>::value, int>::type = 0>
  1194. void write_number_with_ubjson_prefix(const NumberType n,
  1195. const bool add_prefix)
  1196. {
  1197. if ((std::numeric_limits<std::int8_t>::min)() <= n and n <= (std::numeric_limits<std::int8_t>::max)())
  1198. {
  1199. if (add_prefix)
  1200. {
  1201. oa->write_character(to_char_type('i')); // int8
  1202. }
  1203. write_number(static_cast<std::int8_t>(n));
  1204. }
  1205. else if (static_cast<std::int64_t>((std::numeric_limits<std::uint8_t>::min)()) <= n and n <= static_cast<std::int64_t>((std::numeric_limits<std::uint8_t>::max)()))
  1206. {
  1207. if (add_prefix)
  1208. {
  1209. oa->write_character(to_char_type('U')); // uint8
  1210. }
  1211. write_number(static_cast<std::uint8_t>(n));
  1212. }
  1213. else if ((std::numeric_limits<std::int16_t>::min)() <= n and n <= (std::numeric_limits<std::int16_t>::max)())
  1214. {
  1215. if (add_prefix)
  1216. {
  1217. oa->write_character(to_char_type('I')); // int16
  1218. }
  1219. write_number(static_cast<std::int16_t>(n));
  1220. }
  1221. else if ((std::numeric_limits<std::int32_t>::min)() <= n and n <= (std::numeric_limits<std::int32_t>::max)())
  1222. {
  1223. if (add_prefix)
  1224. {
  1225. oa->write_character(to_char_type('l')); // int32
  1226. }
  1227. write_number(static_cast<std::int32_t>(n));
  1228. }
  1229. else if ((std::numeric_limits<std::int64_t>::min)() <= n and n <= (std::numeric_limits<std::int64_t>::max)())
  1230. {
  1231. if (add_prefix)
  1232. {
  1233. oa->write_character(to_char_type('L')); // int64
  1234. }
  1235. write_number(static_cast<std::int64_t>(n));
  1236. }
  1237. // LCOV_EXCL_START
  1238. else
  1239. {
  1240. JSON_THROW(out_of_range::create(407, "integer number " + std::to_string(n) + " cannot be represented by UBJSON as it does not fit int64"));
  1241. }
  1242. // LCOV_EXCL_STOP
  1243. }
  1244. /*!
  1245. @brief determine the type prefix of container values
  1246. @note This function does not need to be 100% accurate when it comes to
  1247. integer limits. In case a number exceeds the limits of int64_t,
  1248. this will be detected by a later call to function
  1249. write_number_with_ubjson_prefix. Therefore, we return 'L' for any
  1250. value that does not fit the previous limits.
  1251. */
  1252. CharType ubjson_prefix(const BasicJsonType& j) const noexcept
  1253. {
  1254. switch (j.type())
  1255. {
  1256. case value_t::null:
  1257. return 'Z';
  1258. case value_t::boolean:
  1259. return j.m_value.boolean ? 'T' : 'F';
  1260. case value_t::number_integer:
  1261. {
  1262. if ((std::numeric_limits<std::int8_t>::min)() <= j.m_value.number_integer and j.m_value.number_integer <= (std::numeric_limits<std::int8_t>::max)())
  1263. {
  1264. return 'i';
  1265. }
  1266. if ((std::numeric_limits<std::uint8_t>::min)() <= j.m_value.number_integer and j.m_value.number_integer <= (std::numeric_limits<std::uint8_t>::max)())
  1267. {
  1268. return 'U';
  1269. }
  1270. if ((std::numeric_limits<std::int16_t>::min)() <= j.m_value.number_integer and j.m_value.number_integer <= (std::numeric_limits<std::int16_t>::max)())
  1271. {
  1272. return 'I';
  1273. }
  1274. if ((std::numeric_limits<std::int32_t>::min)() <= j.m_value.number_integer and j.m_value.number_integer <= (std::numeric_limits<std::int32_t>::max)())
  1275. {
  1276. return 'l';
  1277. }
  1278. // no check and assume int64_t (see note above)
  1279. return 'L';
  1280. }
  1281. case value_t::number_unsigned:
  1282. {
  1283. if (j.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::int8_t>::max)()))
  1284. {
  1285. return 'i';
  1286. }
  1287. if (j.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::uint8_t>::max)()))
  1288. {
  1289. return 'U';
  1290. }
  1291. if (j.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::int16_t>::max)()))
  1292. {
  1293. return 'I';
  1294. }
  1295. if (j.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::int32_t>::max)()))
  1296. {
  1297. return 'l';
  1298. }
  1299. // no check and assume int64_t (see note above)
  1300. return 'L';
  1301. }
  1302. case value_t::number_float:
  1303. return get_ubjson_float_prefix(j.m_value.number_float);
  1304. case value_t::string:
  1305. return 'S';
  1306. case value_t::array: // fallthrough
  1307. case value_t::binary:
  1308. return '[';
  1309. case value_t::object:
  1310. return '{';
  1311. default: // discarded values
  1312. return 'N';
  1313. }
  1314. }
  1315. static constexpr CharType get_ubjson_float_prefix(float /*unused*/)
  1316. {
  1317. return 'd'; // float 32
  1318. }
  1319. static constexpr CharType get_ubjson_float_prefix(double /*unused*/)
  1320. {
  1321. return 'D'; // float 64
  1322. }
  1323. ///////////////////////
  1324. // Utility functions //
  1325. ///////////////////////
  1326. /*
  1327. @brief write a number to output input
  1328. @param[in] n number of type @a NumberType
  1329. @tparam NumberType the type of the number
  1330. @tparam OutputIsLittleEndian Set to true if output data is
  1331. required to be little endian
  1332. @note This function needs to respect the system's endianess, because bytes
  1333. in CBOR, MessagePack, and UBJSON are stored in network order (big
  1334. endian) and therefore need reordering on little endian systems.
  1335. */
  1336. template<typename NumberType, bool OutputIsLittleEndian = false>
  1337. void write_number(const NumberType n)
  1338. {
  1339. // step 1: write number to array of length NumberType
  1340. std::array<CharType, sizeof(NumberType)> vec;
  1341. std::memcpy(vec.data(), &n, sizeof(NumberType));
  1342. // step 2: write array to output (with possible reordering)
  1343. if (is_little_endian != OutputIsLittleEndian)
  1344. {
  1345. // reverse byte order prior to conversion if necessary
  1346. std::reverse(vec.begin(), vec.end());
  1347. }
  1348. oa->write_characters(vec.data(), sizeof(NumberType));
  1349. }
  1350. public:
  1351. // The following to_char_type functions are implement the conversion
  1352. // between uint8_t and CharType. In case CharType is not unsigned,
  1353. // such a conversion is required to allow values greater than 128.
  1354. // See <https://github.com/nlohmann/json/issues/1286> for a discussion.
  1355. template < typename C = CharType,
  1356. enable_if_t < std::is_signed<C>::value and std::is_signed<char>::value > * = nullptr >
  1357. static constexpr CharType to_char_type(std::uint8_t x) noexcept
  1358. {
  1359. return *reinterpret_cast<char*>(&x);
  1360. }
  1361. template < typename C = CharType,
  1362. enable_if_t < std::is_signed<C>::value and std::is_unsigned<char>::value > * = nullptr >
  1363. static CharType to_char_type(std::uint8_t x) noexcept
  1364. {
  1365. static_assert(sizeof(std::uint8_t) == sizeof(CharType), "size of CharType must be equal to std::uint8_t");
  1366. static_assert(std::is_trivial<CharType>::value, "CharType must be trivial");
  1367. CharType result;
  1368. std::memcpy(&result, &x, sizeof(x));
  1369. return result;
  1370. }
  1371. template<typename C = CharType,
  1372. enable_if_t<std::is_unsigned<C>::value>* = nullptr>
  1373. static constexpr CharType to_char_type(std::uint8_t x) noexcept
  1374. {
  1375. return x;
  1376. }
  1377. template < typename InputCharType, typename C = CharType,
  1378. enable_if_t <
  1379. std::is_signed<C>::value and
  1380. std::is_signed<char>::value and
  1381. std::is_same<char, typename std::remove_cv<InputCharType>::type>::value
  1382. > * = nullptr >
  1383. static constexpr CharType to_char_type(InputCharType x) noexcept
  1384. {
  1385. return x;
  1386. }
  1387. private:
  1388. /// whether we can assume little endianess
  1389. const bool is_little_endian = binary_reader<BasicJsonType>::little_endianess();
  1390. /// the output
  1391. output_adapter_t<CharType> oa = nullptr;
  1392. };
  1393. } // namespace detail
  1394. } // namespace nlohmann