binary_writer.hpp 57 KB

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