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