Horizon
binary_reader.hpp
1 #pragma once
2 
3 #include <algorithm> // generate_n
4 #include <array> // array
5 #include <cassert> // assert
6 #include <cmath> // ldexp
7 #include <cstddef> // size_t
8 #include <cstdint> // uint8_t, uint16_t, uint32_t, uint64_t
9 #include <cstring> // memcpy
10 #include <iomanip> // setw, setfill
11 #include <ios> // hex
12 #include <iterator> // back_inserter
13 #include <limits> // numeric_limits
14 #include <sstream> // stringstream
15 #include <string> // char_traits, string
16 #include <utility> // make_pair, move
17 
18 #include <nlohmann/detail/input/input_adapters.hpp>
19 #include <nlohmann/detail/exceptions.hpp>
20 #include <nlohmann/detail/macro_scope.hpp>
21 #include <nlohmann/detail/value_t.hpp>
22 
23 namespace nlohmann
24 {
25 namespace detail
26 {
28 // binary reader //
30 
34 template<typename BasicJsonType>
36 {
37  using number_integer_t = typename BasicJsonType::number_integer_t;
38  using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
39  using string_t = typename BasicJsonType::string_t;
40 
41  public:
47  explicit binary_reader(input_adapter_t adapter) : ia(std::move(adapter))
48  {
49  assert(ia);
50  }
51 
62  BasicJsonType parse_cbor(const bool strict)
63  {
64  const auto res = parse_cbor_internal();
65  if (strict)
66  {
67  get();
68  expect_eof();
69  }
70  return res;
71  }
72 
83  BasicJsonType parse_msgpack(const bool strict)
84  {
85  const auto res = parse_msgpack_internal();
86  if (strict)
87  {
88  get();
89  expect_eof();
90  }
91  return res;
92  }
93 
104  BasicJsonType parse_ubjson(const bool strict)
105  {
106  const auto res = parse_ubjson_internal();
107  if (strict)
108  {
109  get_ignore_noop();
110  expect_eof();
111  }
112  return res;
113  }
114 
122  static constexpr bool little_endianess(int num = 1) noexcept
123  {
124  return (*reinterpret_cast<char*>(&num) == 1);
125  }
126 
127  private:
133  BasicJsonType parse_cbor_internal(const bool get_char = true)
134  {
135  switch (get_char ? get() : current)
136  {
137  // EOF
138  case std::char_traits<char>::eof():
139  JSON_THROW(parse_error::create(110, chars_read, "unexpected end of input"));
140 
141  // Integer 0x00..0x17 (0..23)
142  case 0x00:
143  case 0x01:
144  case 0x02:
145  case 0x03:
146  case 0x04:
147  case 0x05:
148  case 0x06:
149  case 0x07:
150  case 0x08:
151  case 0x09:
152  case 0x0A:
153  case 0x0B:
154  case 0x0C:
155  case 0x0D:
156  case 0x0E:
157  case 0x0F:
158  case 0x10:
159  case 0x11:
160  case 0x12:
161  case 0x13:
162  case 0x14:
163  case 0x15:
164  case 0x16:
165  case 0x17:
166  return static_cast<number_unsigned_t>(current);
167 
168  case 0x18: // Unsigned integer (one-byte uint8_t follows)
169  return get_number<uint8_t>();
170 
171  case 0x19: // Unsigned integer (two-byte uint16_t follows)
172  return get_number<uint16_t>();
173 
174  case 0x1A: // Unsigned integer (four-byte uint32_t follows)
175  return get_number<uint32_t>();
176 
177  case 0x1B: // Unsigned integer (eight-byte uint64_t follows)
178  return get_number<uint64_t>();
179 
180  // Negative integer -1-0x00..-1-0x17 (-1..-24)
181  case 0x20:
182  case 0x21:
183  case 0x22:
184  case 0x23:
185  case 0x24:
186  case 0x25:
187  case 0x26:
188  case 0x27:
189  case 0x28:
190  case 0x29:
191  case 0x2A:
192  case 0x2B:
193  case 0x2C:
194  case 0x2D:
195  case 0x2E:
196  case 0x2F:
197  case 0x30:
198  case 0x31:
199  case 0x32:
200  case 0x33:
201  case 0x34:
202  case 0x35:
203  case 0x36:
204  case 0x37:
205  return static_cast<int8_t>(0x20 - 1 - current);
206 
207  case 0x38: // Negative integer (one-byte uint8_t follows)
208  {
209  return static_cast<number_integer_t>(-1) - get_number<uint8_t>();
210  }
211 
212  case 0x39: // Negative integer -1-n (two-byte uint16_t follows)
213  {
214  return static_cast<number_integer_t>(-1) - get_number<uint16_t>();
215  }
216 
217  case 0x3A: // Negative integer -1-n (four-byte uint32_t follows)
218  {
219  return static_cast<number_integer_t>(-1) - get_number<uint32_t>();
220  }
221 
222  case 0x3B: // Negative integer -1-n (eight-byte uint64_t follows)
223  {
224  return static_cast<number_integer_t>(-1) -
225  static_cast<number_integer_t>(get_number<uint64_t>());
226  }
227 
228  // UTF-8 string (0x00..0x17 bytes follow)
229  case 0x60:
230  case 0x61:
231  case 0x62:
232  case 0x63:
233  case 0x64:
234  case 0x65:
235  case 0x66:
236  case 0x67:
237  case 0x68:
238  case 0x69:
239  case 0x6A:
240  case 0x6B:
241  case 0x6C:
242  case 0x6D:
243  case 0x6E:
244  case 0x6F:
245  case 0x70:
246  case 0x71:
247  case 0x72:
248  case 0x73:
249  case 0x74:
250  case 0x75:
251  case 0x76:
252  case 0x77:
253  case 0x78: // UTF-8 string (one-byte uint8_t for n follows)
254  case 0x79: // UTF-8 string (two-byte uint16_t for n follow)
255  case 0x7A: // UTF-8 string (four-byte uint32_t for n follow)
256  case 0x7B: // UTF-8 string (eight-byte uint64_t for n follow)
257  case 0x7F: // UTF-8 string (indefinite length)
258  {
259  return get_cbor_string();
260  }
261 
262  // array (0x00..0x17 data items follow)
263  case 0x80:
264  case 0x81:
265  case 0x82:
266  case 0x83:
267  case 0x84:
268  case 0x85:
269  case 0x86:
270  case 0x87:
271  case 0x88:
272  case 0x89:
273  case 0x8A:
274  case 0x8B:
275  case 0x8C:
276  case 0x8D:
277  case 0x8E:
278  case 0x8F:
279  case 0x90:
280  case 0x91:
281  case 0x92:
282  case 0x93:
283  case 0x94:
284  case 0x95:
285  case 0x96:
286  case 0x97:
287  {
288  return get_cbor_array(current & 0x1F);
289  }
290 
291  case 0x98: // array (one-byte uint8_t for n follows)
292  {
293  return get_cbor_array(get_number<uint8_t>());
294  }
295 
296  case 0x99: // array (two-byte uint16_t for n follow)
297  {
298  return get_cbor_array(get_number<uint16_t>());
299  }
300 
301  case 0x9A: // array (four-byte uint32_t for n follow)
302  {
303  return get_cbor_array(get_number<uint32_t>());
304  }
305 
306  case 0x9B: // array (eight-byte uint64_t for n follow)
307  {
308  return get_cbor_array(get_number<uint64_t>());
309  }
310 
311  case 0x9F: // array (indefinite length)
312  {
313  BasicJsonType result = value_t::array;
314  while (get() != 0xFF)
315  {
316  result.push_back(parse_cbor_internal(false));
317  }
318  return result;
319  }
320 
321  // map (0x00..0x17 pairs of data items follow)
322  case 0xA0:
323  case 0xA1:
324  case 0xA2:
325  case 0xA3:
326  case 0xA4:
327  case 0xA5:
328  case 0xA6:
329  case 0xA7:
330  case 0xA8:
331  case 0xA9:
332  case 0xAA:
333  case 0xAB:
334  case 0xAC:
335  case 0xAD:
336  case 0xAE:
337  case 0xAF:
338  case 0xB0:
339  case 0xB1:
340  case 0xB2:
341  case 0xB3:
342  case 0xB4:
343  case 0xB5:
344  case 0xB6:
345  case 0xB7:
346  {
347  return get_cbor_object(current & 0x1F);
348  }
349 
350  case 0xB8: // map (one-byte uint8_t for n follows)
351  {
352  return get_cbor_object(get_number<uint8_t>());
353  }
354 
355  case 0xB9: // map (two-byte uint16_t for n follow)
356  {
357  return get_cbor_object(get_number<uint16_t>());
358  }
359 
360  case 0xBA: // map (four-byte uint32_t for n follow)
361  {
362  return get_cbor_object(get_number<uint32_t>());
363  }
364 
365  case 0xBB: // map (eight-byte uint64_t for n follow)
366  {
367  return get_cbor_object(get_number<uint64_t>());
368  }
369 
370  case 0xBF: // map (indefinite length)
371  {
372  BasicJsonType result = value_t::object;
373  while (get() != 0xFF)
374  {
375  auto key = get_cbor_string();
376  result[key] = parse_cbor_internal();
377  }
378  return result;
379  }
380 
381  case 0xF4: // false
382  {
383  return false;
384  }
385 
386  case 0xF5: // true
387  {
388  return true;
389  }
390 
391  case 0xF6: // null
392  {
393  return value_t::null;
394  }
395 
396  case 0xF9: // Half-Precision Float (two-byte IEEE 754)
397  {
398  const int byte1 = get();
399  unexpect_eof();
400  const int byte2 = get();
401  unexpect_eof();
402 
403  // code from RFC 7049, Appendix D, Figure 3:
404  // As half-precision floating-point numbers were only added
405  // to IEEE 754 in 2008, today's programming platforms often
406  // still only have limited support for them. It is very
407  // easy to include at least decoding support for them even
408  // without such support. An example of a small decoder for
409  // half-precision floating-point numbers in the C language
410  // is shown in Fig. 3.
411  const int half = (byte1 << 8) + byte2;
412  const int exp = (half >> 10) & 0x1F;
413  const int mant = half & 0x3FF;
414  double val;
415  if (exp == 0)
416  {
417  val = std::ldexp(mant, -24);
418  }
419  else if (exp != 31)
420  {
421  val = std::ldexp(mant + 1024, exp - 25);
422  }
423  else
424  {
425  val = (mant == 0) ? std::numeric_limits<double>::infinity()
426  : std::numeric_limits<double>::quiet_NaN();
427  }
428  return (half & 0x8000) != 0 ? -val : val;
429  }
430 
431  case 0xFA: // Single-Precision Float (four-byte IEEE 754)
432  {
433  return get_number<float>();
434  }
435 
436  case 0xFB: // Double-Precision Float (eight-byte IEEE 754)
437  {
438  return get_number<double>();
439  }
440 
441  default: // anything else (0xFF is handled inside the other types)
442  {
443  std::stringstream ss;
444  ss << std::setw(2) << std::uppercase << std::setfill('0') << std::hex << current;
445  JSON_THROW(parse_error::create(112, chars_read, "error reading CBOR; last byte: 0x" + ss.str()));
446  }
447  }
448  }
449 
450  BasicJsonType parse_msgpack_internal()
451  {
452  switch (get())
453  {
454  // EOF
455  case std::char_traits<char>::eof():
456  JSON_THROW(parse_error::create(110, chars_read, "unexpected end of input"));
457 
458  // positive fixint
459  case 0x00:
460  case 0x01:
461  case 0x02:
462  case 0x03:
463  case 0x04:
464  case 0x05:
465  case 0x06:
466  case 0x07:
467  case 0x08:
468  case 0x09:
469  case 0x0A:
470  case 0x0B:
471  case 0x0C:
472  case 0x0D:
473  case 0x0E:
474  case 0x0F:
475  case 0x10:
476  case 0x11:
477  case 0x12:
478  case 0x13:
479  case 0x14:
480  case 0x15:
481  case 0x16:
482  case 0x17:
483  case 0x18:
484  case 0x19:
485  case 0x1A:
486  case 0x1B:
487  case 0x1C:
488  case 0x1D:
489  case 0x1E:
490  case 0x1F:
491  case 0x20:
492  case 0x21:
493  case 0x22:
494  case 0x23:
495  case 0x24:
496  case 0x25:
497  case 0x26:
498  case 0x27:
499  case 0x28:
500  case 0x29:
501  case 0x2A:
502  case 0x2B:
503  case 0x2C:
504  case 0x2D:
505  case 0x2E:
506  case 0x2F:
507  case 0x30:
508  case 0x31:
509  case 0x32:
510  case 0x33:
511  case 0x34:
512  case 0x35:
513  case 0x36:
514  case 0x37:
515  case 0x38:
516  case 0x39:
517  case 0x3A:
518  case 0x3B:
519  case 0x3C:
520  case 0x3D:
521  case 0x3E:
522  case 0x3F:
523  case 0x40:
524  case 0x41:
525  case 0x42:
526  case 0x43:
527  case 0x44:
528  case 0x45:
529  case 0x46:
530  case 0x47:
531  case 0x48:
532  case 0x49:
533  case 0x4A:
534  case 0x4B:
535  case 0x4C:
536  case 0x4D:
537  case 0x4E:
538  case 0x4F:
539  case 0x50:
540  case 0x51:
541  case 0x52:
542  case 0x53:
543  case 0x54:
544  case 0x55:
545  case 0x56:
546  case 0x57:
547  case 0x58:
548  case 0x59:
549  case 0x5A:
550  case 0x5B:
551  case 0x5C:
552  case 0x5D:
553  case 0x5E:
554  case 0x5F:
555  case 0x60:
556  case 0x61:
557  case 0x62:
558  case 0x63:
559  case 0x64:
560  case 0x65:
561  case 0x66:
562  case 0x67:
563  case 0x68:
564  case 0x69:
565  case 0x6A:
566  case 0x6B:
567  case 0x6C:
568  case 0x6D:
569  case 0x6E:
570  case 0x6F:
571  case 0x70:
572  case 0x71:
573  case 0x72:
574  case 0x73:
575  case 0x74:
576  case 0x75:
577  case 0x76:
578  case 0x77:
579  case 0x78:
580  case 0x79:
581  case 0x7A:
582  case 0x7B:
583  case 0x7C:
584  case 0x7D:
585  case 0x7E:
586  case 0x7F:
587  return static_cast<number_unsigned_t>(current);
588 
589  // fixmap
590  case 0x80:
591  case 0x81:
592  case 0x82:
593  case 0x83:
594  case 0x84:
595  case 0x85:
596  case 0x86:
597  case 0x87:
598  case 0x88:
599  case 0x89:
600  case 0x8A:
601  case 0x8B:
602  case 0x8C:
603  case 0x8D:
604  case 0x8E:
605  case 0x8F:
606  {
607  return get_msgpack_object(current & 0x0F);
608  }
609 
610  // fixarray
611  case 0x90:
612  case 0x91:
613  case 0x92:
614  case 0x93:
615  case 0x94:
616  case 0x95:
617  case 0x96:
618  case 0x97:
619  case 0x98:
620  case 0x99:
621  case 0x9A:
622  case 0x9B:
623  case 0x9C:
624  case 0x9D:
625  case 0x9E:
626  case 0x9F:
627  {
628  return get_msgpack_array(current & 0x0F);
629  }
630 
631  // fixstr
632  case 0xA0:
633  case 0xA1:
634  case 0xA2:
635  case 0xA3:
636  case 0xA4:
637  case 0xA5:
638  case 0xA6:
639  case 0xA7:
640  case 0xA8:
641  case 0xA9:
642  case 0xAA:
643  case 0xAB:
644  case 0xAC:
645  case 0xAD:
646  case 0xAE:
647  case 0xAF:
648  case 0xB0:
649  case 0xB1:
650  case 0xB2:
651  case 0xB3:
652  case 0xB4:
653  case 0xB5:
654  case 0xB6:
655  case 0xB7:
656  case 0xB8:
657  case 0xB9:
658  case 0xBA:
659  case 0xBB:
660  case 0xBC:
661  case 0xBD:
662  case 0xBE:
663  case 0xBF:
664  return get_msgpack_string();
665 
666  case 0xC0: // nil
667  return value_t::null;
668 
669  case 0xC2: // false
670  return false;
671 
672  case 0xC3: // true
673  return true;
674 
675  case 0xCA: // float 32
676  return get_number<float>();
677 
678  case 0xCB: // float 64
679  return get_number<double>();
680 
681  case 0xCC: // uint 8
682  return get_number<uint8_t>();
683 
684  case 0xCD: // uint 16
685  return get_number<uint16_t>();
686 
687  case 0xCE: // uint 32
688  return get_number<uint32_t>();
689 
690  case 0xCF: // uint 64
691  return get_number<uint64_t>();
692 
693  case 0xD0: // int 8
694  return get_number<int8_t>();
695 
696  case 0xD1: // int 16
697  return get_number<int16_t>();
698 
699  case 0xD2: // int 32
700  return get_number<int32_t>();
701 
702  case 0xD3: // int 64
703  return get_number<int64_t>();
704 
705  case 0xD9: // str 8
706  case 0xDA: // str 16
707  case 0xDB: // str 32
708  return get_msgpack_string();
709 
710  case 0xDC: // array 16
711  {
712  return get_msgpack_array(get_number<uint16_t>());
713  }
714 
715  case 0xDD: // array 32
716  {
717  return get_msgpack_array(get_number<uint32_t>());
718  }
719 
720  case 0xDE: // map 16
721  {
722  return get_msgpack_object(get_number<uint16_t>());
723  }
724 
725  case 0xDF: // map 32
726  {
727  return get_msgpack_object(get_number<uint32_t>());
728  }
729 
730  // positive fixint
731  case 0xE0:
732  case 0xE1:
733  case 0xE2:
734  case 0xE3:
735  case 0xE4:
736  case 0xE5:
737  case 0xE6:
738  case 0xE7:
739  case 0xE8:
740  case 0xE9:
741  case 0xEA:
742  case 0xEB:
743  case 0xEC:
744  case 0xED:
745  case 0xEE:
746  case 0xEF:
747  case 0xF0:
748  case 0xF1:
749  case 0xF2:
750  case 0xF3:
751  case 0xF4:
752  case 0xF5:
753  case 0xF6:
754  case 0xF7:
755  case 0xF8:
756  case 0xF9:
757  case 0xFA:
758  case 0xFB:
759  case 0xFC:
760  case 0xFD:
761  case 0xFE:
762  case 0xFF:
763  return static_cast<int8_t>(current);
764 
765  default: // anything else
766  {
767  std::stringstream ss;
768  ss << std::setw(2) << std::uppercase << std::setfill('0') << std::hex << current;
769  JSON_THROW(parse_error::create(112, chars_read,
770  "error reading MessagePack; last byte: 0x" + ss.str()));
771  }
772  }
773  }
774 
780  BasicJsonType parse_ubjson_internal(const bool get_char = true)
781  {
782  return get_ubjson_value(get_char ? get_ignore_noop() : current);
783  }
784 
794  int get()
795  {
796  ++chars_read;
797  return (current = ia->get_character());
798  }
799 
803  int get_ignore_noop()
804  {
805  do
806  {
807  get();
808  }
809  while (current == 'N');
810 
811  return current;
812  }
813 
814  /*
815  @brief read a number from the input
816 
817  @tparam NumberType the type of the number
818 
819  @return number of type @a NumberType
820 
821  @note This function needs to respect the system's endianess, because
822  bytes in CBOR and MessagePack are stored in network order (big
823  endian) and therefore need reordering on little endian systems.
824 
825  @throw parse_error.110 if input has less than `sizeof(NumberType)` bytes
826  */
827  template<typename NumberType> NumberType get_number()
828  {
829  // step 1: read input into array with system's byte order
830  std::array<uint8_t, sizeof(NumberType)> vec;
831  for (std::size_t i = 0; i < sizeof(NumberType); ++i)
832  {
833  get();
834  unexpect_eof();
835 
836  // reverse byte order prior to conversion if necessary
837  if (is_little_endian)
838  {
839  vec[sizeof(NumberType) - i - 1] = static_cast<uint8_t>(current);
840  }
841  else
842  {
843  vec[i] = static_cast<uint8_t>(current); // LCOV_EXCL_LINE
844  }
845  }
846 
847  // step 2: convert array into number of type T and return
848  NumberType result;
849  std::memcpy(&result, vec.data(), sizeof(NumberType));
850  return result;
851  }
852 
866  template<typename NumberType>
867  string_t get_string(const NumberType len)
868  {
869  string_t result;
870  std::generate_n(std::back_inserter(result), len, [this]()
871  {
872  get();
873  unexpect_eof();
874  return static_cast<char>(current);
875  });
876  return result;
877  }
878 
891  string_t get_cbor_string()
892  {
893  unexpect_eof();
894 
895  switch (current)
896  {
897  // UTF-8 string (0x00..0x17 bytes follow)
898  case 0x60:
899  case 0x61:
900  case 0x62:
901  case 0x63:
902  case 0x64:
903  case 0x65:
904  case 0x66:
905  case 0x67:
906  case 0x68:
907  case 0x69:
908  case 0x6A:
909  case 0x6B:
910  case 0x6C:
911  case 0x6D:
912  case 0x6E:
913  case 0x6F:
914  case 0x70:
915  case 0x71:
916  case 0x72:
917  case 0x73:
918  case 0x74:
919  case 0x75:
920  case 0x76:
921  case 0x77:
922  {
923  return get_string(current & 0x1F);
924  }
925 
926  case 0x78: // UTF-8 string (one-byte uint8_t for n follows)
927  {
928  return get_string(get_number<uint8_t>());
929  }
930 
931  case 0x79: // UTF-8 string (two-byte uint16_t for n follow)
932  {
933  return get_string(get_number<uint16_t>());
934  }
935 
936  case 0x7A: // UTF-8 string (four-byte uint32_t for n follow)
937  {
938  return get_string(get_number<uint32_t>());
939  }
940 
941  case 0x7B: // UTF-8 string (eight-byte uint64_t for n follow)
942  {
943  return get_string(get_number<uint64_t>());
944  }
945 
946  case 0x7F: // UTF-8 string (indefinite length)
947  {
948  string_t result;
949  while (get() != 0xFF)
950  {
951  unexpect_eof();
952  result.push_back(static_cast<char>(current));
953  }
954  return result;
955  }
956 
957  default:
958  {
959  std::stringstream ss;
960  ss << std::setw(2) << std::uppercase << std::setfill('0') << std::hex << current;
961  JSON_THROW(parse_error::create(113, chars_read, "expected a CBOR string; last byte: 0x" + ss.str()));
962  }
963  }
964  }
965 
966  template<typename NumberType>
967  BasicJsonType get_cbor_array(const NumberType len)
968  {
969  BasicJsonType result = value_t::array;
970  std::generate_n(std::back_inserter(*result.m_value.array), len, [this]()
971  {
972  return parse_cbor_internal();
973  });
974  return result;
975  }
976 
977  template<typename NumberType>
978  BasicJsonType get_cbor_object(const NumberType len)
979  {
980  BasicJsonType result = value_t::object;
981  std::generate_n(std::inserter(*result.m_value.object,
982  result.m_value.object->end()),
983  len, [this]()
984  {
985  get();
986  auto key = get_cbor_string();
987  auto val = parse_cbor_internal();
988  return std::make_pair(std::move(key), std::move(val));
989  });
990  return result;
991  }
992 
1004  string_t get_msgpack_string()
1005  {
1006  unexpect_eof();
1007 
1008  switch (current)
1009  {
1010  // fixstr
1011  case 0xA0:
1012  case 0xA1:
1013  case 0xA2:
1014  case 0xA3:
1015  case 0xA4:
1016  case 0xA5:
1017  case 0xA6:
1018  case 0xA7:
1019  case 0xA8:
1020  case 0xA9:
1021  case 0xAA:
1022  case 0xAB:
1023  case 0xAC:
1024  case 0xAD:
1025  case 0xAE:
1026  case 0xAF:
1027  case 0xB0:
1028  case 0xB1:
1029  case 0xB2:
1030  case 0xB3:
1031  case 0xB4:
1032  case 0xB5:
1033  case 0xB6:
1034  case 0xB7:
1035  case 0xB8:
1036  case 0xB9:
1037  case 0xBA:
1038  case 0xBB:
1039  case 0xBC:
1040  case 0xBD:
1041  case 0xBE:
1042  case 0xBF:
1043  {
1044  return get_string(current & 0x1F);
1045  }
1046 
1047  case 0xD9: // str 8
1048  {
1049  return get_string(get_number<uint8_t>());
1050  }
1051 
1052  case 0xDA: // str 16
1053  {
1054  return get_string(get_number<uint16_t>());
1055  }
1056 
1057  case 0xDB: // str 32
1058  {
1059  return get_string(get_number<uint32_t>());
1060  }
1061 
1062  default:
1063  {
1064  std::stringstream ss;
1065  ss << std::setw(2) << std::uppercase << std::setfill('0') << std::hex << current;
1066  JSON_THROW(parse_error::create(113, chars_read,
1067  "expected a MessagePack string; last byte: 0x" + ss.str()));
1068  }
1069  }
1070  }
1071 
1072  template<typename NumberType>
1073  BasicJsonType get_msgpack_array(const NumberType len)
1074  {
1075  BasicJsonType result = value_t::array;
1076  std::generate_n(std::back_inserter(*result.m_value.array), len, [this]()
1077  {
1078  return parse_msgpack_internal();
1079  });
1080  return result;
1081  }
1082 
1083  template<typename NumberType>
1084  BasicJsonType get_msgpack_object(const NumberType len)
1085  {
1086  BasicJsonType result = value_t::object;
1087  std::generate_n(std::inserter(*result.m_value.object,
1088  result.m_value.object->end()),
1089  len, [this]()
1090  {
1091  get();
1092  auto key = get_msgpack_string();
1093  auto val = parse_msgpack_internal();
1094  return std::make_pair(std::move(key), std::move(val));
1095  });
1096  return result;
1097  }
1098 
1115  string_t get_ubjson_string(const bool get_char = true)
1116  {
1117  if (get_char)
1118  {
1119  get(); // TODO: may we ignore N here?
1120  }
1121 
1122  unexpect_eof();
1123 
1124  switch (current)
1125  {
1126  case 'U':
1127  return get_string(get_number<uint8_t>());
1128  case 'i':
1129  return get_string(get_number<int8_t>());
1130  case 'I':
1131  return get_string(get_number<int16_t>());
1132  case 'l':
1133  return get_string(get_number<int32_t>());
1134  case 'L':
1135  return get_string(get_number<int64_t>());
1136  default:
1137  std::stringstream ss;
1138  ss << std::setw(2) << std::uppercase << std::setfill('0') << std::hex << current;
1139  JSON_THROW(parse_error::create(113, chars_read,
1140  "expected a UBJSON string; last byte: 0x" + ss.str()));
1141  }
1142  }
1143 
1152  std::pair<std::size_t, int> get_ubjson_size_type()
1153  {
1154  std::size_t sz = string_t::npos;
1155  int tc = 0;
1156 
1157  get_ignore_noop();
1158 
1159  if (current == '$')
1160  {
1161  tc = get(); // must not ignore 'N', because 'N' maybe the type
1162  unexpect_eof();
1163 
1164  get_ignore_noop();
1165  if (current != '#')
1166  {
1167  std::stringstream ss;
1168  ss << std::setw(2) << std::uppercase << std::setfill('0') << std::hex << current;
1169  JSON_THROW(parse_error::create(112, chars_read,
1170  "expected '#' after UBJSON type information; last byte: 0x" + ss.str()));
1171  }
1172  sz = parse_ubjson_internal();
1173  }
1174  else if (current == '#')
1175  {
1176  sz = parse_ubjson_internal();
1177  }
1178 
1179  return std::make_pair(sz, tc);
1180  }
1181 
1182  BasicJsonType get_ubjson_value(const int prefix)
1183  {
1184  switch (prefix)
1185  {
1186  case std::char_traits<char>::eof(): // EOF
1187  JSON_THROW(parse_error::create(110, chars_read, "unexpected end of input"));
1188 
1189  case 'T': // true
1190  return true;
1191  case 'F': // false
1192  return false;
1193 
1194  case 'Z': // null
1195  return nullptr;
1196 
1197  case 'U':
1198  return get_number<uint8_t>();
1199  case 'i':
1200  return get_number<int8_t>();
1201  case 'I':
1202  return get_number<int16_t>();
1203  case 'l':
1204  return get_number<int32_t>();
1205  case 'L':
1206  return get_number<int64_t>();
1207  case 'd':
1208  return get_number<float>();
1209  case 'D':
1210  return get_number<double>();
1211 
1212  case 'C': // char
1213  {
1214  get();
1215  unexpect_eof();
1216  if (JSON_UNLIKELY(current > 127))
1217  {
1218  std::stringstream ss;
1219  ss << std::setw(2) << std::uppercase << std::setfill('0') << std::hex << current;
1220  JSON_THROW(parse_error::create(113, chars_read,
1221  "byte after 'C' must be in range 0x00..0x7F; last byte: 0x" + ss.str()));
1222  }
1223  return string_t(1, static_cast<char>(current));
1224  }
1225 
1226  case 'S': // string
1227  return get_ubjson_string();
1228 
1229  case '[': // array
1230  return get_ubjson_array();
1231 
1232  case '{': // object
1233  return get_ubjson_object();
1234 
1235  default: // anything else
1236  std::stringstream ss;
1237  ss << std::setw(2) << std::uppercase << std::setfill('0') << std::hex << current;
1238  JSON_THROW(parse_error::create(112, chars_read,
1239  "error reading UBJSON; last byte: 0x" + ss.str()));
1240  }
1241  }
1242 
1243  BasicJsonType get_ubjson_array()
1244  {
1245  BasicJsonType result = value_t::array;
1246  const auto size_and_type = get_ubjson_size_type();
1247 
1248  if (size_and_type.first != string_t::npos)
1249  {
1250  if (size_and_type.second != 0)
1251  {
1252  if (size_and_type.second != 'N')
1253  std::generate_n(std::back_inserter(*result.m_value.array),
1254  size_and_type.first, [this, size_and_type]()
1255  {
1256  return get_ubjson_value(size_and_type.second);
1257  });
1258  }
1259  else
1260  {
1261  std::generate_n(std::back_inserter(*result.m_value.array),
1262  size_and_type.first, [this]()
1263  {
1264  return parse_ubjson_internal();
1265  });
1266  }
1267  }
1268  else
1269  {
1270  while (current != ']')
1271  {
1272  result.push_back(parse_ubjson_internal(false));
1273  get_ignore_noop();
1274  }
1275  }
1276 
1277  return result;
1278  }
1279 
1280  BasicJsonType get_ubjson_object()
1281  {
1282  BasicJsonType result = value_t::object;
1283  const auto size_and_type = get_ubjson_size_type();
1284 
1285  if (size_and_type.first != string_t::npos)
1286  {
1287  if (size_and_type.second != 0)
1288  {
1289  std::generate_n(std::inserter(*result.m_value.object,
1290  result.m_value.object->end()),
1291  size_and_type.first, [this, size_and_type]()
1292  {
1293  auto key = get_ubjson_string();
1294  auto val = get_ubjson_value(size_and_type.second);
1295  return std::make_pair(std::move(key), std::move(val));
1296  });
1297  }
1298  else
1299  {
1300  std::generate_n(std::inserter(*result.m_value.object,
1301  result.m_value.object->end()),
1302  size_and_type.first, [this]()
1303  {
1304  auto key = get_ubjson_string();
1305  auto val = parse_ubjson_internal();
1306  return std::make_pair(std::move(key), std::move(val));
1307  });
1308  }
1309  }
1310  else
1311  {
1312  while (current != '}')
1313  {
1314  auto key = get_ubjson_string(false);
1315  result[std::move(key)] = parse_ubjson_internal();
1316  get_ignore_noop();
1317  }
1318  }
1319 
1320  return result;
1321  }
1322 
1327  void expect_eof() const
1328  {
1329  if (JSON_UNLIKELY(current != std::char_traits<char>::eof()))
1330  {
1331  JSON_THROW(parse_error::create(110, chars_read, "expected end of input"));
1332  }
1333  }
1334 
1339  void unexpect_eof() const
1340  {
1341  if (JSON_UNLIKELY(current == std::char_traits<char>::eof()))
1342  {
1343  JSON_THROW(parse_error::create(110, chars_read, "unexpected end of input"));
1344  }
1345  }
1346 
1347  private:
1349  input_adapter_t ia = nullptr;
1350 
1352  int current = std::char_traits<char>::eof();
1353 
1355  std::size_t chars_read = 0;
1356 
1358  const bool is_little_endian = little_endianess();
1359 };
1360 }
1361 }
nlohmann::detail::value_t::null
null value
nlohmann::detail::value_t::object
object (unordered set of name/value pairs)
libzip::uint8_t
zip_uint8_t uint8_t
zip_uint8_t typedef.
Definition: zip.hpp:78
nlohmann::detail::binary_reader::parse_ubjson
BasicJsonType parse_ubjson(const bool strict)
create a JSON value from UBJSON input
Definition: binary_reader.hpp:104
nlohmann::detail::binary_reader::little_endianess
static constexpr bool little_endianess(int num=1) noexcept
determine system byte order
Definition: binary_reader.hpp:122
nlohmann
namespace for Niels Lohmann
Definition: adl_serializer.hpp:8
nlohmann::detail::binary_reader::parse_cbor
BasicJsonType parse_cbor(const bool strict)
create a JSON value from CBOR input
Definition: binary_reader.hpp:62
nlohmann::detail::parse_error
exception indicating a parse error
Definition: exceptions.hpp:111
nlohmann::detail::input_adapter_t
std::shared_ptr< input_adapter_protocol > input_adapter_t
a type to simplify interfaces
Definition: input_adapters.hpp:48
nlohmann::detail::parse_error::create
static parse_error create(int id_, std::size_t byte_, const std::string &what_arg)
create a parse error exception
Definition: exceptions.hpp:122
nlohmann::detail::binary_reader::parse_msgpack
BasicJsonType parse_msgpack(const bool strict)
create a JSON value from MessagePack input
Definition: binary_reader.hpp:83
nlohmann::detail::binary_reader
deserialization of CBOR and MessagePack values
Definition: binary_reader.hpp:35
nlohmann::detail::value_t::array
array (ordered collection of values)
nlohmann::detail::binary_reader::binary_reader
binary_reader(input_adapter_t adapter)
create a binary reader
Definition: binary_reader.hpp:47