JSON for Modern C++  2.1.0
json.hpp
1 /*
2  __ _____ _____ _____
3  __| | __| | | | JSON for Modern C++
4 | | |__ | | | | | | version 2.1.0
5 |_____|_____|_____|_|___| https://github.com/nlohmann/json
6 
7 Licensed under the MIT License <http://opensource.org/licenses/MIT>.
8 Copyright (c) 2013-2017 Niels Lohmann <http://nlohmann.me>.
9 
10 Permission is hereby granted, free of charge, to any person obtaining a copy
11 of this software and associated documentation files (the "Software"), to deal
12 in the Software without restriction, including without limitation the rights
13 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
14 copies of the Software, and to permit persons to whom the Software is
15 furnished to do so, subject to the following conditions:
16 
17 The above copyright notice and this permission notice shall be included in all
18 copies or substantial portions of the Software.
19 
20 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
23 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
25 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
26 SOFTWARE.
27 */
28 
29 #ifndef NLOHMANN_JSON_HPP
30 #define NLOHMANN_JSON_HPP
31 
32 #include <algorithm> // all_of, for_each, transform
33 #include <array> // array
34 #include <cassert> // assert
35 #include <cctype> // isdigit
36 #include <ciso646> // and, not, or
37 #include <cmath> // isfinite, ldexp, signbit
38 #include <cstddef> // nullptr_t, ptrdiff_t, size_t
39 #include <cstdint> // int64_t, uint64_t
40 #include <cstdlib> // strtod, strtof, strtold, strtoul
41 #include <cstring> // strlen
42 #include <forward_list> // forward_list
43 #include <functional> // function, hash, less
44 #include <initializer_list> // initializer_list
45 #include <iomanip> // setw
46 #include <iostream> // istream, ostream
47 #include <iterator> // advance, begin, bidirectional_iterator_tag, distance, end, inserter, iterator, iterator_traits, next, random_access_iterator_tag, reverse_iterator
48 #include <limits> // numeric_limits
49 #include <locale> // locale
50 #include <map> // map
51 #include <memory> // addressof, allocator, allocator_traits, unique_ptr
52 #include <numeric> // accumulate
53 #include <sstream> // stringstream
54 #include <stdexcept> // domain_error, invalid_argument, out_of_range
55 #include <string> // getline, stoi, string, to_string
56 #include <type_traits> // add_pointer, enable_if, is_arithmetic, is_base_of, is_const, is_constructible, is_convertible, is_floating_point, is_integral, is_nothrow_move_assignable, std::is_nothrow_move_constructible, std::is_pointer, std::is_reference, std::is_same, remove_const, remove_pointer, remove_reference
57 #include <utility> // declval, forward, make_pair, move, pair, swap
58 #include <vector> // vector
59 
60 // exclude unsupported compilers
61 #if defined(__clang__)
62  #if (__clang_major__ * 10000 + __clang_minor__ * 100 + __clang_patchlevel__) < 30400
63  #error "unsupported Clang version - see https://github.com/nlohmann/json#supported-compilers"
64  #endif
65 #elif defined(__GNUC__)
66  #if (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) < 40900
67  #error "unsupported GCC version - see https://github.com/nlohmann/json#supported-compilers"
68  #endif
69 #endif
70 
71 // disable float-equal warnings on GCC/clang
72 #if defined(__clang__) || defined(__GNUC__) || defined(__GNUG__)
73  #pragma GCC diagnostic push
74  #pragma GCC diagnostic ignored "-Wfloat-equal"
75 #endif
76 
77 // disable documentation warnings on clang
78 #if defined(__clang__)
79  #pragma GCC diagnostic push
80  #pragma GCC diagnostic ignored "-Wdocumentation"
81 #endif
82 
83 // allow for portable deprecation warnings
84 #if defined(__clang__) || defined(__GNUC__) || defined(__GNUG__)
85  #define JSON_DEPRECATED __attribute__((deprecated))
86 #elif defined(_MSC_VER)
87  #define JSON_DEPRECATED __declspec(deprecated)
88 #else
89  #define JSON_DEPRECATED
90 #endif
91 
92 // allow to disable exceptions
93 #if not defined(JSON_NOEXCEPTION) || defined(__EXCEPTIONS)
94  #define JSON_THROW(exception) throw exception
95  #define JSON_TRY try
96  #define JSON_CATCH(exception) catch(exception)
97 #else
98  #define JSON_THROW(exception) std::abort()
99  #define JSON_TRY if(true)
100  #define JSON_CATCH(exception) if(false)
101 #endif
102 
108 namespace nlohmann
109 {
110 
119 namespace detail
120 {
122 // JSON type enumeration //
124 
149 enum class value_t : uint8_t
150 {
151  null,
152  object,
153  array,
154  string,
155  boolean,
156  number_integer,
157  number_unsigned,
158  number_float,
159  discarded
160 };
161 
171 inline bool operator<(const value_t lhs, const value_t rhs) noexcept
172 {
173  static constexpr std::array<uint8_t, 8> order = {{
174  0, // null
175  3, // object
176  4, // array
177  5, // string
178  1, // boolean
179  2, // integer
180  2, // unsigned
181  2, // float
182  }
183  };
184 
185  // discarded values are not comparable
186  if (lhs == value_t::discarded or rhs == value_t::discarded)
187  {
188  return false;
189  }
190 
191  return order[static_cast<std::size_t>(lhs)] <
192  order[static_cast<std::size_t>(rhs)];
193 }
194 
195 
197 // helpers //
199 
200 // alias templates to reduce boilerplate
201 template<bool B, typename T = void>
202 using enable_if_t = typename std::enable_if<B, T>::type;
203 
204 template<typename T>
205 using uncvref_t = typename std::remove_cv<typename std::remove_reference<T>::type>::type;
206 
207 // taken from http://stackoverflow.com/a/26936864/266378
208 template<typename T>
209 using is_unscoped_enum =
210  std::integral_constant<bool, std::is_convertible<T, int>::value and
211  std::is_enum<T>::value>;
212 
213 /*
214 Implementation of two C++17 constructs: conjunction, negation. This is needed
215 to avoid evaluating all the traits in a condition
216 
217 For example: not std::is_same<void, T>::value and has_value_type<T>::value
218 will not compile when T = void (on MSVC at least). Whereas
219 conjunction<negation<std::is_same<void, T>>, has_value_type<T>>::value will
220 stop evaluating if negation<...>::value == false
221 
222 Please note that those constructs must be used with caution, since symbols can
223 become very long quickly (which can slow down compilation and cause MSVC
224 internal compiler errors). Only use it when you have to (see example ahead).
225 */
226 template<class...> struct conjunction : std::true_type {};
227 template<class B1> struct conjunction<B1> : B1 {};
228 template<class B1, class... Bn>
229 struct conjunction<B1, Bn...> : std::conditional<bool(B1::value), conjunction<Bn...>, B1>::type {};
230 
231 template<class B> struct negation : std::integral_constant < bool, !B::value > {};
232 
233 // dispatch utility (taken from ranges-v3)
234 template<unsigned N> struct priority_tag : priority_tag < N - 1 > {};
235 template<> struct priority_tag<0> {};
236 
237 
239 // constructors //
241 
242 template<value_t> struct external_constructor;
243 
244 template<>
245 struct external_constructor<value_t::boolean>
246 {
247  template<typename BasicJsonType>
248  static void construct(BasicJsonType& j, typename BasicJsonType::boolean_t b) noexcept
249  {
250  j.m_type = value_t::boolean;
251  j.m_value = b;
252  j.assert_invariant();
253  }
254 };
255 
256 template<>
257 struct external_constructor<value_t::string>
258 {
259  template<typename BasicJsonType>
260  static void construct(BasicJsonType& j, const typename BasicJsonType::string_t& s)
261  {
262  j.m_type = value_t::string;
263  j.m_value = s;
264  j.assert_invariant();
265  }
266 };
267 
268 template<>
269 struct external_constructor<value_t::number_float>
270 {
271  template<typename BasicJsonType>
272  static void construct(BasicJsonType& j, typename BasicJsonType::number_float_t val) noexcept
273  {
274  // replace infinity and NAN by null
275  if (not std::isfinite(val))
276  {
277  j = BasicJsonType{};
278  }
279  else
280  {
281  j.m_type = value_t::number_float;
282  j.m_value = val;
283  }
284  j.assert_invariant();
285  }
286 };
287 
288 template<>
289 struct external_constructor<value_t::number_unsigned>
290 {
291  template<typename BasicJsonType>
292  static void construct(BasicJsonType& j, typename BasicJsonType::number_unsigned_t val) noexcept
293  {
294  j.m_type = value_t::number_unsigned;
295  j.m_value = val;
296  j.assert_invariant();
297  }
298 };
299 
300 template<>
301 struct external_constructor<value_t::number_integer>
302 {
303  template<typename BasicJsonType>
304  static void construct(BasicJsonType& j, typename BasicJsonType::number_integer_t val) noexcept
305  {
306  j.m_type = value_t::number_integer;
307  j.m_value = val;
308  j.assert_invariant();
309  }
310 };
311 
312 template<>
313 struct external_constructor<value_t::array>
314 {
315  template<typename BasicJsonType>
316  static void construct(BasicJsonType& j, const typename BasicJsonType::array_t& arr)
317  {
318  j.m_type = value_t::array;
319  j.m_value = arr;
320  j.assert_invariant();
321  }
322 
323  template<typename BasicJsonType, typename CompatibleArrayType,
324  enable_if_t<not std::is_same<CompatibleArrayType,
325  typename BasicJsonType::array_t>::value,
326  int> = 0>
327  static void construct(BasicJsonType& j, const CompatibleArrayType& arr)
328  {
329  using std::begin;
330  using std::end;
331  j.m_type = value_t::array;
332  j.m_value.array = j.template create<typename BasicJsonType::array_t>(begin(arr), end(arr));
333  j.assert_invariant();
334  }
335 };
336 
337 template<>
338 struct external_constructor<value_t::object>
339 {
340  template<typename BasicJsonType>
341  static void construct(BasicJsonType& j, const typename BasicJsonType::object_t& obj)
342  {
343  j.m_type = value_t::object;
344  j.m_value = obj;
345  j.assert_invariant();
346  }
347 
348  template<typename BasicJsonType, typename CompatibleObjectType,
349  enable_if_t<not std::is_same<CompatibleObjectType,
350  typename BasicJsonType::object_t>::value,
351  int> = 0>
352  static void construct(BasicJsonType& j, const CompatibleObjectType& obj)
353  {
354  using std::begin;
355  using std::end;
356 
357  j.m_type = value_t::object;
358  j.m_value.object = j.template create<typename BasicJsonType::object_t>(begin(obj), end(obj));
359  j.assert_invariant();
360  }
361 };
362 
363 
365 // has_/is_ functions //
367 
378 #define NLOHMANN_JSON_HAS_HELPER(type) \
379  template<typename T> struct has_##type { \
380  private: \
381  template<typename U, typename = typename U::type> \
382  static int detect(U &&); \
383  static void detect(...); \
384  public: \
385  static constexpr bool value = \
386  std::is_integral<decltype(detect(std::declval<T>()))>::value; \
387  }
388 
389 NLOHMANN_JSON_HAS_HELPER(mapped_type);
390 NLOHMANN_JSON_HAS_HELPER(key_type);
391 NLOHMANN_JSON_HAS_HELPER(value_type);
392 NLOHMANN_JSON_HAS_HELPER(iterator);
393 
394 #undef NLOHMANN_JSON_HAS_HELPER
395 
396 
397 template<bool B, class RealType, class CompatibleObjectType>
398 struct is_compatible_object_type_impl : std::false_type {};
399 
400 template<class RealType, class CompatibleObjectType>
401 struct is_compatible_object_type_impl<true, RealType, CompatibleObjectType>
402 {
403  static constexpr auto value =
404  std::is_constructible<typename RealType::key_type,
405  typename CompatibleObjectType::key_type>::value and
406  std::is_constructible<typename RealType::mapped_type,
407  typename CompatibleObjectType::mapped_type>::value;
408 };
409 
410 template<class BasicJsonType, class CompatibleObjectType>
411 struct is_compatible_object_type
412 {
413  static auto constexpr value = is_compatible_object_type_impl <
414  conjunction<negation<std::is_same<void, CompatibleObjectType>>,
415  has_mapped_type<CompatibleObjectType>,
416  has_key_type<CompatibleObjectType>>::value,
417  typename BasicJsonType::object_t, CompatibleObjectType >::value;
418 };
419 
420 template<typename BasicJsonType, typename T>
421 struct is_basic_json_nested_type
422 {
423  static auto constexpr value = std::is_same<T, typename BasicJsonType::iterator>::value or
424  std::is_same<T, typename BasicJsonType::const_iterator>::value or
425  std::is_same<T, typename BasicJsonType::reverse_iterator>::value or
426  std::is_same<T, typename BasicJsonType::const_reverse_iterator>::value or
427  std::is_same<T, typename BasicJsonType::json_pointer>::value;
428 };
429 
430 template<class BasicJsonType, class CompatibleArrayType>
431 struct is_compatible_array_type
432 {
433  static auto constexpr value =
434  conjunction<negation<std::is_same<void, CompatibleArrayType>>,
435  negation<is_compatible_object_type<
436  BasicJsonType, CompatibleArrayType>>,
437  negation<std::is_constructible<typename BasicJsonType::string_t,
438  CompatibleArrayType>>,
439  negation<is_basic_json_nested_type<BasicJsonType, CompatibleArrayType>>,
440  has_value_type<CompatibleArrayType>,
441  has_iterator<CompatibleArrayType>>::value;
442 };
443 
444 template<bool, typename, typename>
445 struct is_compatible_integer_type_impl : std::false_type {};
446 
447 template<typename RealIntegerType, typename CompatibleNumberIntegerType>
448 struct is_compatible_integer_type_impl<true, RealIntegerType, CompatibleNumberIntegerType>
449 {
450  // is there an assert somewhere on overflows?
451  using RealLimits = std::numeric_limits<RealIntegerType>;
452  using CompatibleLimits = std::numeric_limits<CompatibleNumberIntegerType>;
453 
454  static constexpr auto value =
455  std::is_constructible<RealIntegerType,
456  CompatibleNumberIntegerType>::value and
457  CompatibleLimits::is_integer and
458  RealLimits::is_signed == CompatibleLimits::is_signed;
459 };
460 
461 template<typename RealIntegerType, typename CompatibleNumberIntegerType>
462 struct is_compatible_integer_type
463 {
464  static constexpr auto value =
465  is_compatible_integer_type_impl <
466  std::is_integral<CompatibleNumberIntegerType>::value and
467  not std::is_same<bool, CompatibleNumberIntegerType>::value,
468  RealIntegerType, CompatibleNumberIntegerType > ::value;
469 };
470 
471 
472 // trait checking if JSONSerializer<T>::from_json(json const&, udt&) exists
473 template<typename BasicJsonType, typename T>
474 struct has_from_json
475 {
476  private:
477  // also check the return type of from_json
478  template<typename U, typename = enable_if_t<std::is_same<void, decltype(uncvref_t<U>::from_json(
479  std::declval<BasicJsonType>(), std::declval<T&>()))>::value>>
480  static int detect(U&&);
481  static void detect(...);
482 
483  public:
484  static constexpr bool value = std::is_integral<decltype(
485  detect(std::declval<typename BasicJsonType::template json_serializer<T, void>>()))>::value;
486 };
487 
488 // This trait checks if JSONSerializer<T>::from_json(json const&) exists
489 // this overload is used for non-default-constructible user-defined-types
490 template<typename BasicJsonType, typename T>
491 struct has_non_default_from_json
492 {
493  private:
494  template <
495  typename U,
496  typename = enable_if_t<std::is_same<
497  T, decltype(uncvref_t<U>::from_json(std::declval<BasicJsonType>()))>::value >>
498  static int detect(U&&);
499  static void detect(...);
500 
501  public:
502  static constexpr bool value = std::is_integral<decltype(detect(
503  std::declval<typename BasicJsonType::template json_serializer<T, void>>()))>::value;
504 };
505 
506 // This trait checks if BasicJsonType::json_serializer<T>::to_json exists
507 template<typename BasicJsonType, typename T>
508 struct has_to_json
509 {
510  private:
511  template<typename U, typename = decltype(uncvref_t<U>::to_json(
512  std::declval<BasicJsonType&>(), std::declval<T>()))>
513  static int detect(U&&);
514  static void detect(...);
515 
516  public:
517  static constexpr bool value = std::is_integral<decltype(detect(
518  std::declval<typename BasicJsonType::template json_serializer<T, void>>()))>::value;
519 };
520 
521 
523 // to_json //
525 
526 template<typename BasicJsonType>
527 void to_json(BasicJsonType& j, typename BasicJsonType::boolean_t b) noexcept
528 {
529  external_constructor<value_t::boolean>::construct(j, b);
530 }
531 
532 template<typename BasicJsonType, typename CompatibleString,
533  enable_if_t<std::is_constructible<typename BasicJsonType::string_t,
534  CompatibleString>::value, int> = 0>
535 void to_json(BasicJsonType& j, const CompatibleString& s)
536 {
537  external_constructor<value_t::string>::construct(j, s);
538 }
539 
540 template<typename BasicJsonType, typename FloatType,
541  enable_if_t<std::is_floating_point<FloatType>::value, int> = 0>
542 void to_json(BasicJsonType& j, FloatType val) noexcept
543 {
544  external_constructor<value_t::number_float>::construct(j, static_cast<typename BasicJsonType::number_float_t>(val));
545 }
546 
547 template <
548  typename BasicJsonType, typename CompatibleNumberUnsignedType,
549  enable_if_t<is_compatible_integer_type<typename BasicJsonType::number_unsigned_t,
550  CompatibleNumberUnsignedType>::value, int> = 0 >
551 void to_json(BasicJsonType& j, CompatibleNumberUnsignedType val) noexcept
552 {
553  external_constructor<value_t::number_unsigned>::construct(j, static_cast<typename BasicJsonType::number_unsigned_t>(val));
554 }
555 
556 template <
557  typename BasicJsonType, typename CompatibleNumberIntegerType,
558  enable_if_t<is_compatible_integer_type<typename BasicJsonType::number_integer_t,
559  CompatibleNumberIntegerType>::value, int> = 0 >
560 void to_json(BasicJsonType& j, CompatibleNumberIntegerType val) noexcept
561 {
562  external_constructor<value_t::number_integer>::construct(j, static_cast<typename BasicJsonType::number_integer_t>(val));
563 }
564 
565 template<typename BasicJsonType, typename UnscopedEnumType,
566  enable_if_t<is_unscoped_enum<UnscopedEnumType>::value, int> = 0>
567 void to_json(BasicJsonType& j, UnscopedEnumType e) noexcept
568 {
569  external_constructor<value_t::number_integer>::construct(j, e);
570 }
571 
572 template <
573  typename BasicJsonType, typename CompatibleArrayType,
574  enable_if_t <
575  is_compatible_array_type<BasicJsonType, CompatibleArrayType>::value or
576  std::is_same<typename BasicJsonType::array_t, CompatibleArrayType>::value,
577  int > = 0 >
578 void to_json(BasicJsonType& j, const CompatibleArrayType& arr)
579 {
580  external_constructor<value_t::array>::construct(j, arr);
581 }
582 
583 template <
584  typename BasicJsonType, typename CompatibleObjectType,
585  enable_if_t<is_compatible_object_type<BasicJsonType, CompatibleObjectType>::value,
586  int> = 0 >
587 void to_json(BasicJsonType& j, const CompatibleObjectType& arr)
588 {
589  external_constructor<value_t::object>::construct(j, arr);
590 }
591 
592 
594 // from_json //
596 
597 // overloads for basic_json template parameters
598 template<typename BasicJsonType, typename ArithmeticType,
599  enable_if_t<std::is_arithmetic<ArithmeticType>::value and
600  not std::is_same<ArithmeticType,
601  typename BasicJsonType::boolean_t>::value,
602  int> = 0>
603 void get_arithmetic_value(const BasicJsonType& j, ArithmeticType& val)
604 {
605  switch (static_cast<value_t>(j))
606  {
607  case value_t::number_unsigned:
608  {
609  val = static_cast<ArithmeticType>(
610  *j.template get_ptr<const typename BasicJsonType::number_unsigned_t*>());
611  break;
612  }
613  case value_t::number_integer:
614  {
615  val = static_cast<ArithmeticType>(
616  *j.template get_ptr<const typename BasicJsonType::number_integer_t*>());
617  break;
618  }
619  case value_t::number_float:
620  {
621  val = static_cast<ArithmeticType>(
622  *j.template get_ptr<const typename BasicJsonType::number_float_t*>());
623  break;
624  }
625  default:
626  {
627  JSON_THROW(
628  std::domain_error("type must be number, but is " + j.type_name()));
629  }
630  }
631 }
632 
633 template<typename BasicJsonType>
634 void from_json(const BasicJsonType& j, typename BasicJsonType::boolean_t& b)
635 {
636  if (not j.is_boolean())
637  {
638  JSON_THROW(std::domain_error("type must be boolean, but is " + j.type_name()));
639  }
640  b = *j.template get_ptr<const typename BasicJsonType::boolean_t*>();
641 }
642 
643 template<typename BasicJsonType>
644 void from_json(const BasicJsonType& j, typename BasicJsonType::string_t& s)
645 {
646  if (not j.is_string())
647  {
648  JSON_THROW(std::domain_error("type must be string, but is " + j.type_name()));
649  }
650  s = *j.template get_ptr<const typename BasicJsonType::string_t*>();
651 }
652 
653 template<typename BasicJsonType>
654 void from_json(const BasicJsonType& j, typename BasicJsonType::number_float_t& val)
655 {
656  get_arithmetic_value(j, val);
657 }
658 
659 template<typename BasicJsonType>
660 void from_json(const BasicJsonType& j, typename BasicJsonType::number_unsigned_t& val)
661 {
662  get_arithmetic_value(j, val);
663 }
664 
665 template<typename BasicJsonType>
666 void from_json(const BasicJsonType& j, typename BasicJsonType::number_integer_t& val)
667 {
668  get_arithmetic_value(j, val);
669 }
670 
671 template<typename BasicJsonType, typename UnscopedEnumType,
672  enable_if_t<is_unscoped_enum<UnscopedEnumType>::value, int> = 0>
673 void from_json(const BasicJsonType& j, UnscopedEnumType& e)
674 {
675  typename std::underlying_type<UnscopedEnumType>::type val = e;
676  get_arithmetic_value(j, val);
677  e = static_cast<UnscopedEnumType>(val);
678 }
679 
680 template<typename BasicJsonType>
681 void from_json(const BasicJsonType& j, typename BasicJsonType::array_t& arr)
682 {
683  if (not j.is_array())
684  {
685  JSON_THROW(std::domain_error("type must be array, but is " + j.type_name()));
686  }
687  arr = *j.template get_ptr<const typename BasicJsonType::array_t*>();
688 }
689 
690 // forward_list doesn't have an insert method
691 template<typename BasicJsonType, typename T, typename Allocator>
692 void from_json(const BasicJsonType& j, std::forward_list<T, Allocator>& l)
693 {
694  // do not perform the check when user wants to retrieve jsons
695  // (except when it's null.. ?)
696  if (j.is_null())
697  {
698  JSON_THROW(std::domain_error("type must be array, but is " + j.type_name()));
699  }
700  if (not std::is_same<T, BasicJsonType>::value)
701  {
702  if (not j.is_array())
703  {
704  JSON_THROW(std::domain_error("type must be array, but is " + j.type_name()));
705  }
706  }
707  for (auto it = j.rbegin(), end = j.rend(); it != end; ++it)
708  {
709  l.push_front(it->template get<T>());
710  }
711 }
712 
713 template<typename BasicJsonType, typename CompatibleArrayType>
714 void from_json_array_impl(const BasicJsonType& j, CompatibleArrayType& arr, priority_tag<0>)
715 {
716  using std::begin;
717  using std::end;
718 
719  std::transform(j.begin(), j.end(),
720  std::inserter(arr, end(arr)), [](const BasicJsonType & i)
721  {
722  // get<BasicJsonType>() returns *this, this won't call a from_json
723  // method when value_type is BasicJsonType
724  return i.template get<typename CompatibleArrayType::value_type>();
725  });
726 }
727 
728 template<typename BasicJsonType, typename CompatibleArrayType>
729 auto from_json_array_impl(const BasicJsonType& j, CompatibleArrayType& arr, priority_tag<1>)
730 -> decltype(
731  arr.reserve(std::declval<typename CompatibleArrayType::size_type>()),
732  void())
733 {
734  using std::begin;
735  using std::end;
736 
737  arr.reserve(j.size());
738  std::transform(
739  j.begin(), j.end(), std::inserter(arr, end(arr)), [](const BasicJsonType & i)
740  {
741  // get<BasicJsonType>() returns *this, this won't call a from_json
742  // method when value_type is BasicJsonType
743  return i.template get<typename CompatibleArrayType::value_type>();
744  });
745 }
746 
747 template<typename BasicJsonType, typename CompatibleArrayType,
748  enable_if_t<is_compatible_array_type<BasicJsonType, CompatibleArrayType>::value and
749  not std::is_same<typename BasicJsonType::array_t, CompatibleArrayType>::value, int> = 0>
750 void from_json(const BasicJsonType& j, CompatibleArrayType& arr)
751 {
752  if (j.is_null())
753  {
754  JSON_THROW(std::domain_error("type must be array, but is " + j.type_name()));
755  }
756 
757  // when T == BasicJsonType, do not check if value_t is correct
758  if (not std::is_same<typename CompatibleArrayType::value_type, BasicJsonType>::value)
759  {
760  if (not j.is_array())
761  {
762  JSON_THROW(std::domain_error("type must be array, but is " + j.type_name()));
763  }
764  }
765  from_json_array_impl(j, arr, priority_tag<1> {});
766 }
767 
768 template<typename BasicJsonType, typename CompatibleObjectType,
769  enable_if_t<is_compatible_object_type<BasicJsonType, CompatibleObjectType>::value, int> = 0>
770 void from_json(const BasicJsonType& j, CompatibleObjectType& obj)
771 {
772  if (not j.is_object())
773  {
774  JSON_THROW(std::domain_error("type must be object, but is " + j.type_name()));
775  }
776 
777  auto inner_object = j.template get_ptr<const typename BasicJsonType::object_t*>();
778  using std::begin;
779  using std::end;
780  // we could avoid the assignment, but this might require a for loop, which
781  // might be less efficient than the container constructor for some
782  // containers (would it?)
783  obj = CompatibleObjectType(begin(*inner_object), end(*inner_object));
784 }
785 
786 // overload for arithmetic types, not chosen for basic_json template arguments
787 // (BooleanType, etc..); note: Is it really necessary to provide explicit
788 // overloads for boolean_t etc. in case of a custom BooleanType which is not
789 // an arithmetic type?
790 template<typename BasicJsonType, typename ArithmeticType,
791  enable_if_t <
792  std::is_arithmetic<ArithmeticType>::value and
793  not std::is_same<ArithmeticType, typename BasicJsonType::number_unsigned_t>::value and
794  not std::is_same<ArithmeticType, typename BasicJsonType::number_integer_t>::value and
795  not std::is_same<ArithmeticType, typename BasicJsonType::number_float_t>::value and
796  not std::is_same<ArithmeticType, typename BasicJsonType::boolean_t>::value,
797  int> = 0>
798 void from_json(const BasicJsonType& j, ArithmeticType& val)
799 {
800  switch (static_cast<value_t>(j))
801  {
802  case value_t::number_unsigned:
803  {
804  val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_unsigned_t*>());
805  break;
806  }
807  case value_t::number_integer:
808  {
809  val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_integer_t*>());
810  break;
811  }
812  case value_t::number_float:
813  {
814  val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_float_t*>());
815  break;
816  }
817  case value_t::boolean:
818  {
819  val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::boolean_t*>());
820  break;
821  }
822  default:
823  {
824  JSON_THROW(std::domain_error("type must be number, but is " + j.type_name()));
825  }
826  }
827 }
828 
829 struct to_json_fn
830 {
831  private:
832  template<typename BasicJsonType, typename T>
833  auto call(BasicJsonType& j, T&& val, priority_tag<1>) const noexcept(noexcept(to_json(j, std::forward<T>(val))))
834  -> decltype(to_json(j, std::forward<T>(val)), void())
835  {
836  return to_json(j, std::forward<T>(val));
837  }
838 
839  template<typename BasicJsonType, typename T>
840  void call(BasicJsonType&, T&&, priority_tag<0>) const noexcept
841  {
842  static_assert(sizeof(BasicJsonType) == 0,
843  "could not find to_json() method in T's namespace");
844  }
845 
846  public:
847  template<typename BasicJsonType, typename T>
848  void operator()(BasicJsonType& j, T&& val) const
849  noexcept(noexcept(std::declval<to_json_fn>().call(j, std::forward<T>(val), priority_tag<1> {})))
850  {
851  return call(j, std::forward<T>(val), priority_tag<1> {});
852  }
853 };
854 
855 struct from_json_fn
856 {
857  private:
858  template<typename BasicJsonType, typename T>
859  auto call(const BasicJsonType& j, T& val, priority_tag<1>) const
860  noexcept(noexcept(from_json(j, val)))
861  -> decltype(from_json(j, val), void())
862  {
863  return from_json(j, val);
864  }
865 
866  template<typename BasicJsonType, typename T>
867  void call(const BasicJsonType&, T&, priority_tag<0>) const noexcept
868  {
869  static_assert(sizeof(BasicJsonType) == 0,
870  "could not find from_json() method in T's namespace");
871  }
872 
873  public:
874  template<typename BasicJsonType, typename T>
875  void operator()(const BasicJsonType& j, T& val) const
876  noexcept(noexcept(std::declval<from_json_fn>().call(j, val, priority_tag<1> {})))
877  {
878  return call(j, val, priority_tag<1> {});
879  }
880 };
881 
882 // taken from ranges-v3
883 template<typename T>
884 struct static_const
885 {
886  static constexpr T value{};
887 };
888 
889 template<typename T>
890 constexpr T static_const<T>::value;
891 } // namespace detail
892 
893 
895 namespace
896 {
897 constexpr const auto& to_json = detail::static_const<detail::to_json_fn>::value;
898 constexpr const auto& from_json = detail::static_const<detail::from_json_fn>::value;
899 }
900 
901 
909 template<typename = void, typename = void>
911 {
921  template<typename BasicJsonType, typename ValueType>
922  static void from_json(BasicJsonType&& j, ValueType& val) noexcept(
923  noexcept(::nlohmann::from_json(std::forward<BasicJsonType>(j), val)))
924  {
925  ::nlohmann::from_json(std::forward<BasicJsonType>(j), val);
926  }
927 
937  template<typename BasicJsonType, typename ValueType>
938  static void to_json(BasicJsonType& j, ValueType&& val) noexcept(
939  noexcept(::nlohmann::to_json(j, std::forward<ValueType>(val))))
940  {
941  ::nlohmann::to_json(j, std::forward<ValueType>(val));
942  }
943 };
944 
945 
1027 template <
1028  template<typename U, typename V, typename... Args> class ObjectType = std::map,
1029  template<typename U, typename... Args> class ArrayType = std::vector,
1030  class StringType = std::string,
1031  class BooleanType = bool,
1032  class NumberIntegerType = std::int64_t,
1033  class NumberUnsignedType = std::uint64_t,
1034  class NumberFloatType = double,
1035  template<typename U> class AllocatorType = std::allocator,
1036  template<typename T, typename SFINAE = void> class JSONSerializer = adl_serializer
1037  >
1039 {
1040  private:
1041  template<detail::value_t> friend struct detail::external_constructor;
1043  using basic_json_t = basic_json<ObjectType, ArrayType, StringType,
1044  BooleanType, NumberIntegerType, NumberUnsignedType, NumberFloatType,
1045  AllocatorType, JSONSerializer>;
1046 
1047  public:
1048  using value_t = detail::value_t;
1049  // forward declarations
1050  template<typename U> class iter_impl;
1051  template<typename Base> class json_reverse_iterator;
1052  class json_pointer;
1053  template<typename T, typename SFINAE>
1054  using json_serializer = JSONSerializer<T, SFINAE>;
1055 
1057  // container types //
1059 
1064 
1067 
1071  using const_reference = const value_type&;
1072 
1074  using difference_type = std::ptrdiff_t;
1076  using size_type = std::size_t;
1077 
1079  using allocator_type = AllocatorType<basic_json>;
1080 
1082  using pointer = typename std::allocator_traits<allocator_type>::pointer;
1084  using const_pointer = typename std::allocator_traits<allocator_type>::const_pointer;
1085 
1094 
1096 
1097 
1102  {
1103  return allocator_type();
1104  }
1105 
1129  static basic_json meta()
1130  {
1131  basic_json result;
1132 
1133  result["copyright"] = "(C) 2013-2017 Niels Lohmann";
1134  result["name"] = "JSON for Modern C++";
1135  result["url"] = "https://github.com/nlohmann/json";
1136  result["version"] =
1137  {
1138  {"string", "2.1.0"},
1139  {"major", 2},
1140  {"minor", 1},
1141  {"patch", 0},
1142  };
1143 
1144 #ifdef _WIN32
1145  result["platform"] = "win32";
1146 #elif defined __linux__
1147  result["platform"] = "linux";
1148 #elif defined __APPLE__
1149  result["platform"] = "apple";
1150 #elif defined __unix__
1151  result["platform"] = "unix";
1152 #else
1153  result["platform"] = "unknown";
1154 #endif
1155 
1156 #if defined(__clang__)
1157  result["compiler"] = {{"family", "clang"}, {"version", __clang_version__}};
1158 #elif defined(__ICC) || defined(__INTEL_COMPILER)
1159  result["compiler"] = {{"family", "icc"}, {"version", __INTEL_COMPILER}};
1160 #elif defined(__GNUC__) || defined(__GNUG__)
1161  result["compiler"] = {{"family", "gcc"}, {"version", std::to_string(__GNUC__) + "." + std::to_string(__GNUC_MINOR__) + "." + std::to_string(__GNUC_PATCHLEVEL__)}};
1162 #elif defined(__HP_cc) || defined(__HP_aCC)
1163  result["compiler"] = "hp"
1164 #elif defined(__IBMCPP__)
1165  result["compiler"] = {{"family", "ilecpp"}, {"version", __IBMCPP__}};
1166 #elif defined(_MSC_VER)
1167  result["compiler"] = {{"family", "msvc"}, {"version", _MSC_VER}};
1168 #elif defined(__PGI)
1169  result["compiler"] = {{"family", "pgcpp"}, {"version", __PGI}};
1170 #elif defined(__SUNPRO_CC)
1171  result["compiler"] = {{"family", "sunpro"}, {"version", __SUNPRO_CC}};
1172 #else
1173  result["compiler"] = {{"family", "unknown"}, {"version", "unknown"}};
1174 #endif
1175 
1176 #ifdef __cplusplus
1177  result["compiler"]["c++"] = std::to_string(__cplusplus);
1178 #else
1179  result["compiler"]["c++"] = "unknown";
1180 #endif
1181  return result;
1182  }
1183 
1184 
1186  // JSON value data types //
1188 
1193 
1277  using object_t = ObjectType<StringType,
1278  basic_json,
1279  std::less<StringType>,
1280  AllocatorType<std::pair<const StringType,
1281  basic_json>>>;
1282 
1327  using array_t = ArrayType<basic_json, AllocatorType<basic_json>>;
1328 
1380  using string_t = StringType;
1381 
1406  using boolean_t = BooleanType;
1407 
1478  using number_integer_t = NumberIntegerType;
1479 
1549  using number_unsigned_t = NumberUnsignedType;
1550 
1617  using number_float_t = NumberFloatType;
1618 
1620 
1621  private:
1622 
1624  template<typename T, typename... Args>
1625  static T* create(Args&& ... args)
1626  {
1627  AllocatorType<T> alloc;
1628  auto deleter = [&](T * object)
1629  {
1630  alloc.deallocate(object, 1);
1631  };
1632  std::unique_ptr<T, decltype(deleter)> object(alloc.allocate(1), deleter);
1633  alloc.construct(object.get(), std::forward<Args>(args)...);
1634  assert(object != nullptr);
1635  return object.release();
1636  }
1637 
1639  // JSON value storage //
1641 
1666  union json_value
1667  {
1669  object_t* object;
1671  array_t* array;
1673  string_t* string;
1675  boolean_t boolean;
1677  number_integer_t number_integer;
1679  number_unsigned_t number_unsigned;
1681  number_float_t number_float;
1682 
1684  json_value() = default;
1686  json_value(boolean_t v) noexcept : boolean(v) {}
1688  json_value(number_integer_t v) noexcept : number_integer(v) {}
1690  json_value(number_unsigned_t v) noexcept : number_unsigned(v) {}
1692  json_value(number_float_t v) noexcept : number_float(v) {}
1694  json_value(value_t t)
1695  {
1696  switch (t)
1697  {
1698  case value_t::object:
1699  {
1700  object = create<object_t>();
1701  break;
1702  }
1703 
1704  case value_t::array:
1705  {
1706  array = create<array_t>();
1707  break;
1708  }
1709 
1710  case value_t::string:
1711  {
1712  string = create<string_t>("");
1713  break;
1714  }
1715 
1716  case value_t::boolean:
1717  {
1718  boolean = boolean_t(false);
1719  break;
1720  }
1721 
1722  case value_t::number_integer:
1723  {
1724  number_integer = number_integer_t(0);
1725  break;
1726  }
1727 
1728  case value_t::number_unsigned:
1729  {
1730  number_unsigned = number_unsigned_t(0);
1731  break;
1732  }
1733 
1734  case value_t::number_float:
1735  {
1736  number_float = number_float_t(0.0);
1737  break;
1738  }
1739 
1740  case value_t::null:
1741  {
1742  break;
1743  }
1744 
1745  default:
1746  {
1747  if (t == value_t::null)
1748  {
1749  JSON_THROW(std::domain_error("961c151d2e87f2686a955a9be24d316f1362bf21 2.1.0")); // LCOV_EXCL_LINE
1750  }
1751  break;
1752  }
1753  }
1754  }
1755 
1757  json_value(const string_t& value)
1758  {
1759  string = create<string_t>(value);
1760  }
1761 
1763  json_value(const object_t& value)
1764  {
1765  object = create<object_t>(value);
1766  }
1767 
1769  json_value(const array_t& value)
1770  {
1771  array = create<array_t>(value);
1772  }
1773  };
1774 
1784  void assert_invariant() const
1785  {
1786  assert(m_type != value_t::object or m_value.object != nullptr);
1787  assert(m_type != value_t::array or m_value.array != nullptr);
1788  assert(m_type != value_t::string or m_value.string != nullptr);
1789  }
1790 
1791  public:
1793  // JSON parser callback //
1795 
1806  enum class parse_event_t : uint8_t
1807  {
1809  object_start,
1811  object_end,
1813  array_start,
1815  array_end,
1817  key,
1819  value
1820  };
1821 
1874  using parser_callback_t = std::function<bool(int depth,
1875  parse_event_t event,
1876  basic_json& parsed)>;
1877 
1878 
1880  // constructors //
1882 
1887 
1915  basic_json(const value_t value_type)
1916  : m_type(value_type), m_value(value_type)
1917  {
1918  assert_invariant();
1919  }
1920 
1939  basic_json(std::nullptr_t = nullptr) noexcept
1940  : basic_json(value_t::null)
1941  {
1942  assert_invariant();
1943  }
1944 
1998  template<typename CompatibleType, typename U = detail::uncvref_t<CompatibleType>,
1999  detail::enable_if_t<not std::is_base_of<std::istream, U>::value and
2000  not std::is_same<U, basic_json_t>::value and
2001  not detail::is_basic_json_nested_type<
2002  basic_json_t, U>::value and
2003  detail::has_to_json<basic_json, U>::value,
2004  int> = 0>
2005  basic_json(CompatibleType && val) noexcept(noexcept(JSONSerializer<U>::to_json(
2006  std::declval<basic_json_t&>(), std::forward<CompatibleType>(val))))
2007  {
2008  JSONSerializer<U>::to_json(*this, std::forward<CompatibleType>(val));
2009  assert_invariant();
2010  }
2011 
2081  basic_json(std::initializer_list<basic_json> init,
2082  bool type_deduction = true,
2083  value_t manual_type = value_t::array)
2084  {
2085  // check if each element is an array with two elements whose first
2086  // element is a string
2087  bool is_an_object = std::all_of(init.begin(), init.end(),
2088  [](const basic_json & element)
2089  {
2090  return element.is_array() and element.size() == 2 and element[0].is_string();
2091  });
2092 
2093  // adjust type if type deduction is not wanted
2094  if (not type_deduction)
2095  {
2096  // if array is wanted, do not create an object though possible
2097  if (manual_type == value_t::array)
2098  {
2099  is_an_object = false;
2100  }
2101 
2102  // if object is wanted but impossible, throw an exception
2103  if (manual_type == value_t::object and not is_an_object)
2104  {
2105  JSON_THROW(std::domain_error("cannot create object from initializer list"));
2106  }
2107  }
2108 
2109  if (is_an_object)
2110  {
2111  // the initializer list is a list of pairs -> create object
2112  m_type = value_t::object;
2113  m_value = value_t::object;
2114 
2115  std::for_each(init.begin(), init.end(), [this](const basic_json & element)
2116  {
2117  m_value.object->emplace(*(element[0].m_value.string), element[1]);
2118  });
2119  }
2120  else
2121  {
2122  // the initializer list describes an array -> create array
2123  m_type = value_t::array;
2124  m_value.array = create<array_t>(init);
2125  }
2126 
2127  assert_invariant();
2128  }
2129 
2164  static basic_json array(std::initializer_list<basic_json> init =
2165  std::initializer_list<basic_json>())
2166  {
2167  return basic_json(init, false, value_t::array);
2168  }
2169 
2204  static basic_json object(std::initializer_list<basic_json> init =
2205  std::initializer_list<basic_json>())
2206  {
2207  return basic_json(init, false, value_t::object);
2208  }
2209 
2229  : m_type(value_t::array)
2230  {
2231  m_value.array = create<array_t>(cnt, val);
2232  assert_invariant();
2233  }
2234 
2272  template<class InputIT, typename std::enable_if<
2273  std::is_same<InputIT, typename basic_json_t::iterator>::value or
2274  std::is_same<InputIT, typename basic_json_t::const_iterator>::value, int>::type = 0>
2275  basic_json(InputIT first, InputIT last)
2276  {
2277  assert(first.m_object != nullptr);
2278  assert(last.m_object != nullptr);
2279 
2280  // make sure iterator fits the current value
2281  if (first.m_object != last.m_object)
2282  {
2283  JSON_THROW(std::domain_error("iterators are not compatible"));
2284  }
2285 
2286  // copy type from first iterator
2287  m_type = first.m_object->m_type;
2288 
2289  // check if iterator range is complete for primitive values
2290  switch (m_type)
2291  {
2292  case value_t::boolean:
2293  case value_t::number_float:
2294  case value_t::number_integer:
2295  case value_t::number_unsigned:
2296  case value_t::string:
2297  {
2298  if (not first.m_it.primitive_iterator.is_begin() or not last.m_it.primitive_iterator.is_end())
2299  {
2300  JSON_THROW(std::out_of_range("iterators out of range"));
2301  }
2302  break;
2303  }
2304 
2305  default:
2306  {
2307  break;
2308  }
2309  }
2310 
2311  switch (m_type)
2312  {
2313  case value_t::number_integer:
2314  {
2315  m_value.number_integer = first.m_object->m_value.number_integer;
2316  break;
2317  }
2318 
2319  case value_t::number_unsigned:
2320  {
2321  m_value.number_unsigned = first.m_object->m_value.number_unsigned;
2322  break;
2323  }
2324 
2325  case value_t::number_float:
2326  {
2327  m_value.number_float = first.m_object->m_value.number_float;
2328  break;
2329  }
2330 
2331  case value_t::boolean:
2332  {
2333  m_value.boolean = first.m_object->m_value.boolean;
2334  break;
2335  }
2336 
2337  case value_t::string:
2338  {
2339  m_value = *first.m_object->m_value.string;
2340  break;
2341  }
2342 
2343  case value_t::object:
2344  {
2345  m_value.object = create<object_t>(first.m_it.object_iterator,
2346  last.m_it.object_iterator);
2347  break;
2348  }
2349 
2350  case value_t::array:
2351  {
2352  m_value.array = create<array_t>(first.m_it.array_iterator,
2353  last.m_it.array_iterator);
2354  break;
2355  }
2356 
2357  default:
2358  {
2359  JSON_THROW(std::domain_error("cannot use construct with iterators from " + first.m_object->type_name()));
2360  }
2361  }
2362 
2363  assert_invariant();
2364  }
2365 
2394  JSON_DEPRECATED
2395  explicit basic_json(std::istream& i, const parser_callback_t cb = nullptr)
2396  {
2397  *this = parser(i, cb).parse();
2398  assert_invariant();
2399  }
2400 
2402  // other constructors and destructor //
2404 
2427  basic_json(const basic_json& other)
2428  : m_type(other.m_type)
2429  {
2430  // check of passed value is valid
2431  other.assert_invariant();
2432 
2433  switch (m_type)
2434  {
2435  case value_t::object:
2436  {
2437  m_value = *other.m_value.object;
2438  break;
2439  }
2440 
2441  case value_t::array:
2442  {
2443  m_value = *other.m_value.array;
2444  break;
2445  }
2446 
2447  case value_t::string:
2448  {
2449  m_value = *other.m_value.string;
2450  break;
2451  }
2452 
2453  case value_t::boolean:
2454  {
2455  m_value = other.m_value.boolean;
2456  break;
2457  }
2458 
2459  case value_t::number_integer:
2460  {
2461  m_value = other.m_value.number_integer;
2462  break;
2463  }
2464 
2465  case value_t::number_unsigned:
2466  {
2467  m_value = other.m_value.number_unsigned;
2468  break;
2469  }
2470 
2471  case value_t::number_float:
2472  {
2473  m_value = other.m_value.number_float;
2474  break;
2475  }
2476 
2477  default:
2478  {
2479  break;
2480  }
2481  }
2482 
2483  assert_invariant();
2484  }
2485 
2504  basic_json(basic_json&& other) noexcept
2505  : m_type(std::move(other.m_type)),
2506  m_value(std::move(other.m_value))
2507  {
2508  // check that passed value is valid
2509  other.assert_invariant();
2510 
2511  // invalidate payload
2512  other.m_type = value_t::null;
2513  other.m_value = {};
2514 
2515  assert_invariant();
2516  }
2517 
2541  reference& operator=(basic_json other) noexcept (
2542  std::is_nothrow_move_constructible<value_t>::value and
2543  std::is_nothrow_move_assignable<value_t>::value and
2544  std::is_nothrow_move_constructible<json_value>::value and
2545  std::is_nothrow_move_assignable<json_value>::value
2546  )
2547  {
2548  // check that passed value is valid
2549  other.assert_invariant();
2550 
2551  using std::swap;
2552  swap(m_type, other.m_type);
2553  swap(m_value, other.m_value);
2554 
2555  assert_invariant();
2556  return *this;
2557  }
2558 
2575  {
2576  assert_invariant();
2577 
2578  switch (m_type)
2579  {
2580  case value_t::object:
2581  {
2582  AllocatorType<object_t> alloc;
2583  alloc.destroy(m_value.object);
2584  alloc.deallocate(m_value.object, 1);
2585  break;
2586  }
2587 
2588  case value_t::array:
2589  {
2590  AllocatorType<array_t> alloc;
2591  alloc.destroy(m_value.array);
2592  alloc.deallocate(m_value.array, 1);
2593  break;
2594  }
2595 
2596  case value_t::string:
2597  {
2598  AllocatorType<string_t> alloc;
2599  alloc.destroy(m_value.string);
2600  alloc.deallocate(m_value.string, 1);
2601  break;
2602  }
2603 
2604  default:
2605  {
2606  // all other types need no specific destructor
2607  break;
2608  }
2609  }
2610  }
2611 
2613 
2614  public:
2616  // object inspection //
2618 
2622 
2646  string_t dump(const int indent = -1) const
2647  {
2648  std::stringstream ss;
2649  // fix locale problems
2650  ss.imbue(std::locale::classic());
2651 
2652  // 6, 15 or 16 digits of precision allows round-trip IEEE 754
2653  // string->float->string, string->double->string or string->long
2654  // double->string; to be safe, we read this value from
2655  // std::numeric_limits<number_float_t>::digits10
2656  ss.precision(std::numeric_limits<double>::digits10);
2657 
2658  if (indent >= 0)
2659  {
2660  dump(ss, true, static_cast<unsigned int>(indent));
2661  }
2662  else
2663  {
2664  dump(ss, false, 0);
2665  }
2666 
2667  return ss.str();
2668  }
2669 
2688  constexpr value_t type() const noexcept
2689  {
2690  return m_type;
2691  }
2692 
2718  constexpr bool is_primitive() const noexcept
2719  {
2720  return is_null() or is_string() or is_boolean() or is_number();
2721  }
2722 
2745  constexpr bool is_structured() const noexcept
2746  {
2747  return is_array() or is_object();
2748  }
2749 
2767  constexpr bool is_null() const noexcept
2768  {
2769  return m_type == value_t::null;
2770  }
2771 
2789  constexpr bool is_boolean() const noexcept
2790  {
2791  return m_type == value_t::boolean;
2792  }
2793 
2819  constexpr bool is_number() const noexcept
2820  {
2821  return is_number_integer() or is_number_float();
2822  }
2823 
2848  constexpr bool is_number_integer() const noexcept
2849  {
2850  return m_type == value_t::number_integer or m_type == value_t::number_unsigned;
2851  }
2852 
2876  constexpr bool is_number_unsigned() const noexcept
2877  {
2878  return m_type == value_t::number_unsigned;
2879  }
2880 
2904  constexpr bool is_number_float() const noexcept
2905  {
2906  return m_type == value_t::number_float;
2907  }
2908 
2926  constexpr bool is_object() const noexcept
2927  {
2928  return m_type == value_t::object;
2929  }
2930 
2948  constexpr bool is_array() const noexcept
2949  {
2950  return m_type == value_t::array;
2951  }
2952 
2970  constexpr bool is_string() const noexcept
2971  {
2972  return m_type == value_t::string;
2973  }
2974 
2997  constexpr bool is_discarded() const noexcept
2998  {
2999  return m_type == value_t::discarded;
3000  }
3001 
3020  constexpr operator value_t() const noexcept
3021  {
3022  return m_type;
3023  }
3024 
3026 
3027  private:
3029  // value access //
3031 
3033  boolean_t get_impl(boolean_t* /*unused*/) const
3034  {
3035  if (is_boolean())
3036  {
3037  return m_value.boolean;
3038  }
3039  else
3040  {
3041  JSON_THROW(std::domain_error("type must be boolean, but is " + type_name()));
3042  }
3043  }
3044 
3046  object_t* get_impl_ptr(object_t* /*unused*/) noexcept
3047  {
3048  return is_object() ? m_value.object : nullptr;
3049  }
3050 
3052  constexpr const object_t* get_impl_ptr(const object_t* /*unused*/) const noexcept
3053  {
3054  return is_object() ? m_value.object : nullptr;
3055  }
3056 
3058  array_t* get_impl_ptr(array_t* /*unused*/) noexcept
3059  {
3060  return is_array() ? m_value.array : nullptr;
3061  }
3062 
3064  constexpr const array_t* get_impl_ptr(const array_t* /*unused*/) const noexcept
3065  {
3066  return is_array() ? m_value.array : nullptr;
3067  }
3068 
3070  string_t* get_impl_ptr(string_t* /*unused*/) noexcept
3071  {
3072  return is_string() ? m_value.string : nullptr;
3073  }
3074 
3076  constexpr const string_t* get_impl_ptr(const string_t* /*unused*/) const noexcept
3077  {
3078  return is_string() ? m_value.string : nullptr;
3079  }
3080 
3082  boolean_t* get_impl_ptr(boolean_t* /*unused*/) noexcept
3083  {
3084  return is_boolean() ? &m_value.boolean : nullptr;
3085  }
3086 
3088  constexpr const boolean_t* get_impl_ptr(const boolean_t* /*unused*/) const noexcept
3089  {
3090  return is_boolean() ? &m_value.boolean : nullptr;
3091  }
3092 
3094  number_integer_t* get_impl_ptr(number_integer_t* /*unused*/) noexcept
3095  {
3096  return is_number_integer() ? &m_value.number_integer : nullptr;
3097  }
3098 
3100  constexpr const number_integer_t* get_impl_ptr(const number_integer_t* /*unused*/) const noexcept
3101  {
3102  return is_number_integer() ? &m_value.number_integer : nullptr;
3103  }
3104 
3106  number_unsigned_t* get_impl_ptr(number_unsigned_t* /*unused*/) noexcept
3107  {
3108  return is_number_unsigned() ? &m_value.number_unsigned : nullptr;
3109  }
3110 
3112  constexpr const number_unsigned_t* get_impl_ptr(const number_unsigned_t* /*unused*/) const noexcept
3113  {
3114  return is_number_unsigned() ? &m_value.number_unsigned : nullptr;
3115  }
3116 
3118  number_float_t* get_impl_ptr(number_float_t* /*unused*/) noexcept
3119  {
3120  return is_number_float() ? &m_value.number_float : nullptr;
3121  }
3122 
3124  constexpr const number_float_t* get_impl_ptr(const number_float_t* /*unused*/) const noexcept
3125  {
3126  return is_number_float() ? &m_value.number_float : nullptr;
3127  }
3128 
3140  template<typename ReferenceType, typename ThisType>
3141  static ReferenceType get_ref_impl(ThisType& obj)
3142  {
3143  // helper type
3144  using PointerType = typename std::add_pointer<ReferenceType>::type;
3145 
3146  // delegate the call to get_ptr<>()
3147  auto ptr = obj.template get_ptr<PointerType>();
3148 
3149  if (ptr != nullptr)
3150  {
3151  return *ptr;
3152  }
3153 
3154  throw std::domain_error("incompatible ReferenceType for get_ref, actual type is " +
3155  obj.type_name());
3156  }
3157 
3158  public:
3162 
3177  template <
3178  typename BasicJsonType,
3179  detail::enable_if_t<std::is_same<typename std::remove_const<BasicJsonType>::type,
3180  basic_json_t>::value,
3181  int> = 0 >
3182  basic_json get() const
3183  {
3184  return *this;
3185  }
3186 
3226  template <
3227  typename ValueTypeCV,
3228  typename ValueType = detail::uncvref_t<ValueTypeCV>,
3229  detail::enable_if_t <
3230  not std::is_same<basic_json_t, ValueType>::value and
3231  detail::has_from_json<basic_json_t, ValueType>::value and
3232  not detail::has_non_default_from_json<basic_json_t, ValueType>::value,
3233  int > = 0 >
3234  ValueType get() const noexcept(noexcept(
3235  JSONSerializer<ValueType>::from_json(std::declval<const basic_json_t&>(), std::declval<ValueType&>())))
3236  {
3237  // we cannot static_assert on ValueTypeCV being non-const, because
3238  // there is support for get<const basic_json_t>(), which is why we
3239  // still need the uncvref
3240  static_assert(not std::is_reference<ValueTypeCV>::value,
3241  "get() cannot be used with reference types, you might want to use get_ref()");
3242  static_assert(std::is_default_constructible<ValueType>::value,
3243  "types must be DefaultConstructible when used with get()");
3244 
3245  ValueType ret;
3246  JSONSerializer<ValueType>::from_json(*this, ret);
3247  return ret;
3248  }
3249 
3281  template <
3282  typename ValueTypeCV,
3283  typename ValueType = detail::uncvref_t<ValueTypeCV>,
3284  detail::enable_if_t<not std::is_same<basic_json_t, ValueType>::value and
3285  detail::has_non_default_from_json<basic_json_t,
3286  ValueType>::value, int> = 0 >
3287  ValueType get() const noexcept(noexcept(
3288  JSONSerializer<ValueTypeCV>::from_json(std::declval<const basic_json_t&>())))
3289  {
3290  static_assert(not std::is_reference<ValueTypeCV>::value,
3291  "get() cannot be used with reference types, you might want to use get_ref()");
3292  return JSONSerializer<ValueTypeCV>::from_json(*this);
3293  }
3294 
3322  template<typename PointerType, typename std::enable_if<
3323  std::is_pointer<PointerType>::value, int>::type = 0>
3324  PointerType get() noexcept
3325  {
3326  // delegate the call to get_ptr
3327  return get_ptr<PointerType>();
3328  }
3329 
3334  template<typename PointerType, typename std::enable_if<
3335  std::is_pointer<PointerType>::value, int>::type = 0>
3336  constexpr const PointerType get() const noexcept
3337  {
3338  // delegate the call to get_ptr
3339  return get_ptr<PointerType>();
3340  }
3341 
3368  template<typename PointerType, typename std::enable_if<
3369  std::is_pointer<PointerType>::value, int>::type = 0>
3370  PointerType get_ptr() noexcept
3371  {
3372  // get the type of the PointerType (remove pointer and const)
3373  using pointee_t = typename std::remove_const<typename
3374  std::remove_pointer<typename
3375  std::remove_const<PointerType>::type>::type>::type;
3376  // make sure the type matches the allowed types
3377  static_assert(
3378  std::is_same<object_t, pointee_t>::value
3379  or std::is_same<array_t, pointee_t>::value
3380  or std::is_same<string_t, pointee_t>::value
3381  or std::is_same<boolean_t, pointee_t>::value
3382  or std::is_same<number_integer_t, pointee_t>::value
3383  or std::is_same<number_unsigned_t, pointee_t>::value
3384  or std::is_same<number_float_t, pointee_t>::value
3385  , "incompatible pointer type");
3386 
3387  // delegate the call to get_impl_ptr<>()
3388  return get_impl_ptr(static_cast<PointerType>(nullptr));
3389  }
3390 
3395  template<typename PointerType, typename std::enable_if<
3396  std::is_pointer<PointerType>::value and
3397  std::is_const<typename std::remove_pointer<PointerType>::type>::value, int>::type = 0>
3398  constexpr const PointerType get_ptr() const noexcept
3399  {
3400  // get the type of the PointerType (remove pointer and const)
3401  using pointee_t = typename std::remove_const<typename
3402  std::remove_pointer<typename
3403  std::remove_const<PointerType>::type>::type>::type;
3404  // make sure the type matches the allowed types
3405  static_assert(
3406  std::is_same<object_t, pointee_t>::value
3407  or std::is_same<array_t, pointee_t>::value
3408  or std::is_same<string_t, pointee_t>::value
3409  or std::is_same<boolean_t, pointee_t>::value
3410  or std::is_same<number_integer_t, pointee_t>::value
3411  or std::is_same<number_unsigned_t, pointee_t>::value
3412  or std::is_same<number_float_t, pointee_t>::value
3413  , "incompatible pointer type");
3414 
3415  // delegate the call to get_impl_ptr<>() const
3416  return get_impl_ptr(static_cast<const PointerType>(nullptr));
3417  }
3418 
3445  template<typename ReferenceType, typename std::enable_if<
3446  std::is_reference<ReferenceType>::value, int>::type = 0>
3447  ReferenceType get_ref()
3448  {
3449  // delegate call to get_ref_impl
3450  return get_ref_impl<ReferenceType>(*this);
3451  }
3452 
3457  template<typename ReferenceType, typename std::enable_if<
3458  std::is_reference<ReferenceType>::value and
3459  std::is_const<typename std::remove_reference<ReferenceType>::type>::value, int>::type = 0>
3460  ReferenceType get_ref() const
3461  {
3462  // delegate call to get_ref_impl
3463  return get_ref_impl<ReferenceType>(*this);
3464  }
3465 
3494  template < typename ValueType, typename std::enable_if <
3495  not std::is_pointer<ValueType>::value and
3496  not std::is_same<ValueType, typename string_t::value_type>::value
3497 #ifndef _MSC_VER // fix for issue #167 operator<< abiguity under VS2015
3498  and not std::is_same<ValueType, std::initializer_list<typename string_t::value_type>>::value
3499 #endif
3500  , int >::type = 0 >
3501  operator ValueType() const
3502  {
3503  // delegate the call to get<>() const
3504  return get<ValueType>();
3505  }
3506 
3508 
3509 
3511  // element access //
3513 
3517 
3541  {
3542  // at only works for arrays
3543  if (is_array())
3544  {
3545  JSON_TRY
3546  {
3547  return m_value.array->at(idx);
3548  }
3549  JSON_CATCH (std::out_of_range&)
3550  {
3551  // create better exception explanation
3552  JSON_THROW(std::out_of_range("array index " + std::to_string(idx) + " is out of range"));
3553  }
3554  }
3555  else
3556  {
3557  JSON_THROW(std::domain_error("cannot use at() with " + type_name()));
3558  }
3559  }
3560 
3584  {
3585  // at only works for arrays
3586  if (is_array())
3587  {
3588  JSON_TRY
3589  {
3590  return m_value.array->at(idx);
3591  }
3592  JSON_CATCH (std::out_of_range&)
3593  {
3594  // create better exception explanation
3595  JSON_THROW(std::out_of_range("array index " + std::to_string(idx) + " is out of range"));
3596  }
3597  }
3598  else
3599  {
3600  JSON_THROW(std::domain_error("cannot use at() with " + type_name()));
3601  }
3602  }
3603 
3630  reference at(const typename object_t::key_type& key)
3631  {
3632  // at only works for objects
3633  if (is_object())
3634  {
3635  JSON_TRY
3636  {
3637  return m_value.object->at(key);
3638  }
3639  JSON_CATCH (std::out_of_range&)
3640  {
3641  // create better exception explanation
3642  JSON_THROW(std::out_of_range("key '" + key + "' not found"));
3643  }
3644  }
3645  else
3646  {
3647  JSON_THROW(std::domain_error("cannot use at() with " + type_name()));
3648  }
3649  }
3650 
3677  const_reference at(const typename object_t::key_type& key) const
3678  {
3679  // at only works for objects
3680  if (is_object())
3681  {
3682  JSON_TRY
3683  {
3684  return m_value.object->at(key);
3685  }
3686  JSON_CATCH (std::out_of_range&)
3687  {
3688  // create better exception explanation
3689  JSON_THROW(std::out_of_range("key '" + key + "' not found"));
3690  }
3691  }
3692  else
3693  {
3694  JSON_THROW(std::domain_error("cannot use at() with " + type_name()));
3695  }
3696  }
3697 
3724  {
3725  // implicitly convert null value to an empty array
3726  if (is_null())
3727  {
3728  m_type = value_t::array;
3729  m_value.array = create<array_t>();
3730  assert_invariant();
3731  }
3732 
3733  // operator[] only works for arrays
3734  if (is_array())
3735  {
3736  // fill up array with null values if given idx is outside range
3737  if (idx >= m_value.array->size())
3738  {
3739  m_value.array->insert(m_value.array->end(),
3740  idx - m_value.array->size() + 1,
3741  basic_json());
3742  }
3743 
3744  return m_value.array->operator[](idx);
3745  }
3746 
3747  JSON_THROW(std::domain_error("cannot use operator[] with " + type_name()));
3748  }
3749 
3770  {
3771  // const operator[] only works for arrays
3772  if (is_array())
3773  {
3774  return m_value.array->operator[](idx);
3775  }
3776 
3777  JSON_THROW(std::domain_error("cannot use operator[] with " + type_name()));
3778  }
3779 
3807  reference operator[](const typename object_t::key_type& key)
3808  {
3809  // implicitly convert null value to an empty object
3810  if (is_null())
3811  {
3812  m_type = value_t::object;
3813  m_value.object = create<object_t>();
3814  assert_invariant();
3815  }
3816 
3817  // operator[] only works for objects
3818  if (is_object())
3819  {
3820  return m_value.object->operator[](key);
3821  }
3822 
3823  JSON_THROW(std::domain_error("cannot use operator[] with " + type_name()));
3824  }
3825 
3856  const_reference operator[](const typename object_t::key_type& key) const
3857  {
3858  // const operator[] only works for objects
3859  if (is_object())
3860  {
3861  assert(m_value.object->find(key) != m_value.object->end());
3862  return m_value.object->find(key)->second;
3863  }
3864 
3865  JSON_THROW(std::domain_error("cannot use operator[] with " + type_name()));
3866  }
3867 
3895  template<typename T, std::size_t n>
3896  reference operator[](T * (&key)[n])
3897  {
3898  return operator[](static_cast<const T>(key));
3899  }
3900 
3930  template<typename T, std::size_t n>
3931  const_reference operator[](T * (&key)[n]) const
3932  {
3933  return operator[](static_cast<const T>(key));
3934  }
3935 
3963  template<typename T>
3965  {
3966  // implicitly convert null to object
3967  if (is_null())
3968  {
3969  m_type = value_t::object;
3970  m_value = value_t::object;
3971  assert_invariant();
3972  }
3973 
3974  // at only works for objects
3975  if (is_object())
3976  {
3977  return m_value.object->operator[](key);
3978  }
3979 
3980  JSON_THROW(std::domain_error("cannot use operator[] with " + type_name()));
3981  }
3982 
4013  template<typename T>
4015  {
4016  // at only works for objects
4017  if (is_object())
4018  {
4019  assert(m_value.object->find(key) != m_value.object->end());
4020  return m_value.object->find(key)->second;
4021  }
4022 
4023  JSON_THROW(std::domain_error("cannot use operator[] with " + type_name()));
4024  }
4025 
4074  template<class ValueType, typename std::enable_if<
4075  std::is_convertible<basic_json_t, ValueType>::value, int>::type = 0>
4076  ValueType value(const typename object_t::key_type& key, ValueType default_value) const
4077  {
4078  // at only works for objects
4079  if (is_object())
4080  {
4081  // if key is found, return value and given default value otherwise
4082  const auto it = find(key);
4083  if (it != end())
4084  {
4085  return *it;
4086  }
4087 
4088  return default_value;
4089  }
4090  else
4091  {
4092  JSON_THROW(std::domain_error("cannot use value() with " + type_name()));
4093  }
4094  }
4095 
4100  string_t value(const typename object_t::key_type& key, const char* default_value) const
4101  {
4102  return value(key, string_t(default_value));
4103  }
4104 
4146  template<class ValueType, typename std::enable_if<
4147  std::is_convertible<basic_json_t, ValueType>::value, int>::type = 0>
4148  ValueType value(const json_pointer& ptr, ValueType default_value) const
4149  {
4150  // at only works for objects
4151  if (is_object())
4152  {
4153  // if pointer resolves a value, return it or use default value
4154  JSON_TRY
4155  {
4156  return ptr.get_checked(this);
4157  }
4158  JSON_CATCH (std::out_of_range&)
4159  {
4160  return default_value;
4161  }
4162  }
4163 
4164  JSON_THROW(std::domain_error("cannot use value() with " + type_name()));
4165  }
4166 
4171  string_t value(const json_pointer& ptr, const char* default_value) const
4172  {
4173  return value(ptr, string_t(default_value));
4174  }
4175 
4202  {
4203  return *begin();
4204  }
4205 
4210  {
4211  return *cbegin();
4212  }
4213 
4245  {
4246  auto tmp = end();
4247  --tmp;
4248  return *tmp;
4249  }
4250 
4255  {
4256  auto tmp = cend();
4257  --tmp;
4258  return *tmp;
4259  }
4260 
4306  template<class IteratorType, typename std::enable_if<
4307  std::is_same<IteratorType, typename basic_json_t::iterator>::value or
4308  std::is_same<IteratorType, typename basic_json_t::const_iterator>::value, int>::type
4309  = 0>
4310  IteratorType erase(IteratorType pos)
4311  {
4312  // make sure iterator fits the current value
4313  if (this != pos.m_object)
4314  {
4315  JSON_THROW(std::domain_error("iterator does not fit current value"));
4316  }
4317 
4318  IteratorType result = end();
4319 
4320  switch (m_type)
4321  {
4322  case value_t::boolean:
4323  case value_t::number_float:
4324  case value_t::number_integer:
4325  case value_t::number_unsigned:
4326  case value_t::string:
4327  {
4328  if (not pos.m_it.primitive_iterator.is_begin())
4329  {
4330  JSON_THROW(std::out_of_range("iterator out of range"));
4331  }
4332 
4333  if (is_string())
4334  {
4335  AllocatorType<string_t> alloc;
4336  alloc.destroy(m_value.string);
4337  alloc.deallocate(m_value.string, 1);
4338  m_value.string = nullptr;
4339  }
4340 
4341  m_type = value_t::null;
4342  assert_invariant();
4343  break;
4344  }
4345 
4346  case value_t::object:
4347  {
4348  result.m_it.object_iterator = m_value.object->erase(pos.m_it.object_iterator);
4349  break;
4350  }
4351 
4352  case value_t::array:
4353  {
4354  result.m_it.array_iterator = m_value.array->erase(pos.m_it.array_iterator);
4355  break;
4356  }
4357 
4358  default:
4359  {
4360  JSON_THROW(std::domain_error("cannot use erase() with " + type_name()));
4361  }
4362  }
4363 
4364  return result;
4365  }
4366 
4413  template<class IteratorType, typename std::enable_if<
4414  std::is_same<IteratorType, typename basic_json_t::iterator>::value or
4415  std::is_same<IteratorType, typename basic_json_t::const_iterator>::value, int>::type
4416  = 0>
4417  IteratorType erase(IteratorType first, IteratorType last)
4418  {
4419  // make sure iterator fits the current value
4420  if (this != first.m_object or this != last.m_object)
4421  {
4422  JSON_THROW(std::domain_error("iterators do not fit current value"));
4423  }
4424 
4425  IteratorType result = end();
4426 
4427  switch (m_type)
4428  {
4429  case value_t::boolean:
4430  case value_t::number_float:
4431  case value_t::number_integer:
4432  case value_t::number_unsigned:
4433  case value_t::string:
4434  {
4435  if (not first.m_it.primitive_iterator.is_begin() or not last.m_it.primitive_iterator.is_end())
4436  {
4437  JSON_THROW(std::out_of_range("iterators out of range"));
4438  }
4439 
4440  if (is_string())
4441  {
4442  AllocatorType<string_t> alloc;
4443  alloc.destroy(m_value.string);
4444  alloc.deallocate(m_value.string, 1);
4445  m_value.string = nullptr;
4446  }
4447 
4448  m_type = value_t::null;
4449  assert_invariant();
4450  break;
4451  }
4452 
4453  case value_t::object:
4454  {
4455  result.m_it.object_iterator = m_value.object->erase(first.m_it.object_iterator,
4456  last.m_it.object_iterator);
4457  break;
4458  }
4459 
4460  case value_t::array:
4461  {
4462  result.m_it.array_iterator = m_value.array->erase(first.m_it.array_iterator,
4463  last.m_it.array_iterator);
4464  break;
4465  }
4466 
4467  default:
4468  {
4469  JSON_THROW(std::domain_error("cannot use erase() with " + type_name()));
4470  }
4471  }
4472 
4473  return result;
4474  }
4475 
4505  size_type erase(const typename object_t::key_type& key)
4506  {
4507  // this erase only works for objects
4508  if (is_object())
4509  {
4510  return m_value.object->erase(key);
4511  }
4512 
4513  JSON_THROW(std::domain_error("cannot use erase() with " + type_name()));
4514  }
4515 
4540  void erase(const size_type idx)
4541  {
4542  // this erase only works for arrays
4543  if (is_array())
4544  {
4545  if (idx >= size())
4546  {
4547  JSON_THROW(std::out_of_range("array index " + std::to_string(idx) + " is out of range"));
4548  }
4549 
4550  m_value.array->erase(m_value.array->begin() + static_cast<difference_type>(idx));
4551  }
4552  else
4553  {
4554  JSON_THROW(std::domain_error("cannot use erase() with " + type_name()));
4555  }
4556  }
4557 
4559 
4560 
4562  // lookup //
4564 
4567 
4590  iterator find(typename object_t::key_type key)
4591  {
4592  auto result = end();
4593 
4594  if (is_object())
4595  {
4596  result.m_it.object_iterator = m_value.object->find(key);
4597  }
4598 
4599  return result;
4600  }
4601 
4606  const_iterator find(typename object_t::key_type key) const
4607  {
4608  auto result = cend();
4609 
4610  if (is_object())
4611  {
4612  result.m_it.object_iterator = m_value.object->find(key);
4613  }
4614 
4615  return result;
4616  }
4617 
4639  size_type count(typename object_t::key_type key) const
4640  {
4641  // return 0 for all nonobject types
4642  return is_object() ? m_value.object->count(key) : 0;
4643  }
4644 
4646 
4647 
4649  // iterators //
4651 
4654 
4679  iterator begin() noexcept
4680  {
4681  iterator result(this);
4682  result.set_begin();
4683  return result;
4684  }
4685 
4689  const_iterator begin() const noexcept
4690  {
4691  return cbegin();
4692  }
4693 
4719  const_iterator cbegin() const noexcept
4720  {
4721  const_iterator result(this);
4722  result.set_begin();
4723  return result;
4724  }
4725 
4750  iterator end() noexcept
4751  {
4752  iterator result(this);
4753  result.set_end();
4754  return result;
4755  }
4756 
4760  const_iterator end() const noexcept
4761  {
4762  return cend();
4763  }
4764 
4790  const_iterator cend() const noexcept
4791  {
4792  const_iterator result(this);
4793  result.set_end();
4794  return result;
4795  }
4796 
4821  {
4822  return reverse_iterator(end());
4823  }
4824 
4829  {
4830  return crbegin();
4831  }
4832 
4858  {
4859  return reverse_iterator(begin());
4860  }
4861 
4865  const_reverse_iterator rend() const noexcept
4866  {
4867  return crend();
4868  }
4869 
4895  {
4896  return const_reverse_iterator(cend());
4897  }
4898 
4924  {
4925  return const_reverse_iterator(cbegin());
4926  }
4927 
4928  private:
4929  // forward declaration
4930  template<typename IteratorType> class iteration_proxy;
4931 
4932  public:
4944  static iteration_proxy<iterator> iterator_wrapper(reference cont)
4945  {
4946  return iteration_proxy<iterator>(cont);
4947  }
4948 
4952  static iteration_proxy<const_iterator> iterator_wrapper(const_reference cont)
4953  {
4954  return iteration_proxy<const_iterator>(cont);
4955  }
4956 
4958 
4959 
4961  // capacity //
4963 
4966 
5004  bool empty() const noexcept
5005  {
5006  switch (m_type)
5007  {
5008  case value_t::null:
5009  {
5010  // null values are empty
5011  return true;
5012  }
5013 
5014  case value_t::array:
5015  {
5016  // delegate call to array_t::empty()
5017  return m_value.array->empty();
5018  }
5019 
5020  case value_t::object:
5021  {
5022  // delegate call to object_t::empty()
5023  return m_value.object->empty();
5024  }
5025 
5026  default:
5027  {
5028  // all other types are nonempty
5029  return false;
5030  }
5031  }
5032  }
5033 
5072  size_type size() const noexcept
5073  {
5074  switch (m_type)
5075  {
5076  case value_t::null:
5077  {
5078  // null values are empty
5079  return 0;
5080  }
5081 
5082  case value_t::array:
5083  {
5084  // delegate call to array_t::size()
5085  return m_value.array->size();
5086  }
5087 
5088  case value_t::object:
5089  {
5090  // delegate call to object_t::size()
5091  return m_value.object->size();
5092  }
5093 
5094  default:
5095  {
5096  // all other types have size 1
5097  return 1;
5098  }
5099  }
5100  }
5101 
5138  size_type max_size() const noexcept
5139  {
5140  switch (m_type)
5141  {
5142  case value_t::array:
5143  {
5144  // delegate call to array_t::max_size()
5145  return m_value.array->max_size();
5146  }
5147 
5148  case value_t::object:
5149  {
5150  // delegate call to object_t::max_size()
5151  return m_value.object->max_size();
5152  }
5153 
5154  default:
5155  {
5156  // all other types have max_size() == size()
5157  return size();
5158  }
5159  }
5160  }
5161 
5163 
5164 
5166  // modifiers //
5168 
5171 
5194  void clear() noexcept
5195  {
5196  switch (m_type)
5197  {
5198  case value_t::number_integer:
5199  {
5200  m_value.number_integer = 0;
5201  break;
5202  }
5203 
5204  case value_t::number_unsigned:
5205  {
5206  m_value.number_unsigned = 0;
5207  break;
5208  }
5209 
5210  case value_t::number_float:
5211  {
5212  m_value.number_float = 0.0;
5213  break;
5214  }
5215 
5216  case value_t::boolean:
5217  {
5218  m_value.boolean = false;
5219  break;
5220  }
5221 
5222  case value_t::string:
5223  {
5224  m_value.string->clear();
5225  break;
5226  }
5227 
5228  case value_t::array:
5229  {
5230  m_value.array->clear();
5231  break;
5232  }
5233 
5234  case value_t::object:
5235  {
5236  m_value.object->clear();
5237  break;
5238  }
5239 
5240  default:
5241  {
5242  break;
5243  }
5244  }
5245  }
5246 
5267  void push_back(basic_json&& val)
5268  {
5269  // push_back only works for null objects or arrays
5270  if (not(is_null() or is_array()))
5271  {
5272  JSON_THROW(std::domain_error("cannot use push_back() with " + type_name()));
5273  }
5274 
5275  // transform null object into an array
5276  if (is_null())
5277  {
5278  m_type = value_t::array;
5279  m_value = value_t::array;
5280  assert_invariant();
5281  }
5282 
5283  // add element to array (move semantics)
5284  m_value.array->push_back(std::move(val));
5285  // invalidate object
5286  val.m_type = value_t::null;
5287  }
5288 
5294  {
5295  push_back(std::move(val));
5296  return *this;
5297  }
5298 
5303  void push_back(const basic_json& val)
5304  {
5305  // push_back only works for null objects or arrays
5306  if (not(is_null() or is_array()))
5307  {
5308  JSON_THROW(std::domain_error("cannot use push_back() with " + type_name()));
5309  }
5310 
5311  // transform null object into an array
5312  if (is_null())
5313  {
5314  m_type = value_t::array;
5315  m_value = value_t::array;
5316  assert_invariant();
5317  }
5318 
5319  // add element to array
5320  m_value.array->push_back(val);
5321  }
5322 
5328  {
5329  push_back(val);
5330  return *this;
5331  }
5332 
5353  void push_back(const typename object_t::value_type& val)
5354  {
5355  // push_back only works for null objects or objects
5356  if (not(is_null() or is_object()))
5357  {
5358  JSON_THROW(std::domain_error("cannot use push_back() with " + type_name()));
5359  }
5360 
5361  // transform null object into an object
5362  if (is_null())
5363  {
5364  m_type = value_t::object;
5365  m_value = value_t::object;
5366  assert_invariant();
5367  }
5368 
5369  // add element to array
5370  m_value.object->insert(val);
5371  }
5372 
5377  reference operator+=(const typename object_t::value_type& val)
5378  {
5379  push_back(val);
5380  return *this;
5381  }
5382 
5408  void push_back(std::initializer_list<basic_json> init)
5409  {
5410  if (is_object() and init.size() == 2 and init.begin()->is_string())
5411  {
5412  const string_t key = *init.begin();
5413  push_back(typename object_t::value_type(key, *(init.begin() + 1)));
5414  }
5415  else
5416  {
5417  push_back(basic_json(init));
5418  }
5419  }
5420 
5425  reference operator+=(std::initializer_list<basic_json> init)
5426  {
5427  push_back(init);
5428  return *this;
5429  }
5430 
5452  template<class... Args>
5453  void emplace_back(Args&& ... args)
5454  {
5455  // emplace_back only works for null objects or arrays
5456  if (not(is_null() or is_array()))
5457  {
5458  JSON_THROW(std::domain_error("cannot use emplace_back() with " + type_name()));
5459  }
5460 
5461  // transform null object into an array
5462  if (is_null())
5463  {
5464  m_type = value_t::array;
5465  m_value = value_t::array;
5466  assert_invariant();
5467  }
5468 
5469  // add element to array (perfect forwarding)
5470  m_value.array->emplace_back(std::forward<Args>(args)...);
5471  }
5472 
5500  template<class... Args>
5501  std::pair<iterator, bool> emplace(Args&& ... args)
5502  {
5503  // emplace only works for null objects or arrays
5504  if (not(is_null() or is_object()))
5505  {
5506  JSON_THROW(std::domain_error("cannot use emplace() with " + type_name()));
5507  }
5508 
5509  // transform null object into an object
5510  if (is_null())
5511  {
5512  m_type = value_t::object;
5513  m_value = value_t::object;
5514  assert_invariant();
5515  }
5516 
5517  // add element to array (perfect forwarding)
5518  auto res = m_value.object->emplace(std::forward<Args>(args)...);
5519  // create result iterator and set iterator to the result of emplace
5520  auto it = begin();
5521  it.m_it.object_iterator = res.first;
5522 
5523  // return pair of iterator and boolean
5524  return {it, res.second};
5525  }
5526 
5550  {
5551  // insert only works for arrays
5552  if (is_array())
5553  {
5554  // check if iterator pos fits to this JSON value
5555  if (pos.m_object != this)
5556  {
5557  JSON_THROW(std::domain_error("iterator does not fit current value"));
5558  }
5559 
5560  // insert to array and return iterator
5561  iterator result(this);
5562  result.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator, val);
5563  return result;
5564  }
5565 
5566  JSON_THROW(std::domain_error("cannot use insert() with " + type_name()));
5567  }
5568 
5574  {
5575  return insert(pos, val);
5576  }
5577 
5603  {
5604  // insert only works for arrays
5605  if (is_array())
5606  {
5607  // check if iterator pos fits to this JSON value
5608  if (pos.m_object != this)
5609  {
5610  JSON_THROW(std::domain_error("iterator does not fit current value"));
5611  }
5612 
5613  // insert to array and return iterator
5614  iterator result(this);
5615  result.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator, cnt, val);
5616  return result;
5617  }
5618 
5619  JSON_THROW(std::domain_error("cannot use insert() with " + type_name()));
5620  }
5621 
5653  {
5654  // insert only works for arrays
5655  if (not is_array())
5656  {
5657  JSON_THROW(std::domain_error("cannot use insert() with " + type_name()));
5658  }
5659 
5660  // check if iterator pos fits to this JSON value
5661  if (pos.m_object != this)
5662  {
5663  JSON_THROW(std::domain_error("iterator does not fit current value"));
5664  }
5665 
5666  // check if range iterators belong to the same JSON object
5667  if (first.m_object != last.m_object)
5668  {
5669  JSON_THROW(std::domain_error("iterators do not fit"));
5670  }
5671 
5672  if (first.m_object == this or last.m_object == this)
5673  {
5674  JSON_THROW(std::domain_error("passed iterators may not belong to container"));
5675  }
5676 
5677  // insert to array and return iterator
5678  iterator result(this);
5679  result.m_it.array_iterator = m_value.array->insert(
5680  pos.m_it.array_iterator,
5681  first.m_it.array_iterator,
5682  last.m_it.array_iterator);
5683  return result;
5684  }
5685 
5710  iterator insert(const_iterator pos, std::initializer_list<basic_json> ilist)
5711  {
5712  // insert only works for arrays
5713  if (not is_array())
5714  {
5715  JSON_THROW(std::domain_error("cannot use insert() with " + type_name()));
5716  }
5717 
5718  // check if iterator pos fits to this JSON value
5719  if (pos.m_object != this)
5720  {
5721  JSON_THROW(std::domain_error("iterator does not fit current value"));
5722  }
5723 
5724  // insert to array and return iterator
5725  iterator result(this);
5726  result.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator, ilist);
5727  return result;
5728  }
5729 
5747  void swap(reference other) noexcept (
5748  std::is_nothrow_move_constructible<value_t>::value and
5749  std::is_nothrow_move_assignable<value_t>::value and
5750  std::is_nothrow_move_constructible<json_value>::value and
5751  std::is_nothrow_move_assignable<json_value>::value
5752  )
5753  {
5754  std::swap(m_type, other.m_type);
5755  std::swap(m_value, other.m_value);
5756  assert_invariant();
5757  }
5758 
5779  void swap(array_t& other)
5780  {
5781  // swap only works for arrays
5782  if (is_array())
5783  {
5784  std::swap(*(m_value.array), other);
5785  }
5786  else
5787  {
5788  JSON_THROW(std::domain_error("cannot use swap() with " + type_name()));
5789  }
5790  }
5791 
5812  void swap(object_t& other)
5813  {
5814  // swap only works for objects
5815  if (is_object())
5816  {
5817  std::swap(*(m_value.object), other);
5818  }
5819  else
5820  {
5821  JSON_THROW(std::domain_error("cannot use swap() with " + type_name()));
5822  }
5823  }
5824 
5845  void swap(string_t& other)
5846  {
5847  // swap only works for strings
5848  if (is_string())
5849  {
5850  std::swap(*(m_value.string), other);
5851  }
5852  else
5853  {
5854  JSON_THROW(std::domain_error("cannot use swap() with " + type_name()));
5855  }
5856  }
5857 
5859 
5860  public:
5862  // lexicographical comparison operators //
5864 
5867 
5891  friend bool operator==(const_reference lhs, const_reference rhs) noexcept
5892  {
5893  const auto lhs_type = lhs.type();
5894  const auto rhs_type = rhs.type();
5895 
5896  if (lhs_type == rhs_type)
5897  {
5898  switch (lhs_type)
5899  {
5900  case value_t::array:
5901  {
5902  return *lhs.m_value.array == *rhs.m_value.array;
5903  }
5904  case value_t::object:
5905  {
5906  return *lhs.m_value.object == *rhs.m_value.object;
5907  }
5908  case value_t::null:
5909  {
5910  return true;
5911  }
5912  case value_t::string:
5913  {
5914  return *lhs.m_value.string == *rhs.m_value.string;
5915  }
5916  case value_t::boolean:
5917  {
5918  return lhs.m_value.boolean == rhs.m_value.boolean;
5919  }
5920  case value_t::number_integer:
5921  {
5922  return lhs.m_value.number_integer == rhs.m_value.number_integer;
5923  }
5924  case value_t::number_unsigned:
5925  {
5926  return lhs.m_value.number_unsigned == rhs.m_value.number_unsigned;
5927  }
5928  case value_t::number_float:
5929  {
5930  return lhs.m_value.number_float == rhs.m_value.number_float;
5931  }
5932  default:
5933  {
5934  return false;
5935  }
5936  }
5937  }
5938  else if (lhs_type == value_t::number_integer and rhs_type == value_t::number_float)
5939  {
5940  return static_cast<number_float_t>(lhs.m_value.number_integer) == rhs.m_value.number_float;
5941  }
5942  else if (lhs_type == value_t::number_float and rhs_type == value_t::number_integer)
5943  {
5944  return lhs.m_value.number_float == static_cast<number_float_t>(rhs.m_value.number_integer);
5945  }
5946  else if (lhs_type == value_t::number_unsigned and rhs_type == value_t::number_float)
5947  {
5948  return static_cast<number_float_t>(lhs.m_value.number_unsigned) == rhs.m_value.number_float;
5949  }
5950  else if (lhs_type == value_t::number_float and rhs_type == value_t::number_unsigned)
5951  {
5952  return lhs.m_value.number_float == static_cast<number_float_t>(rhs.m_value.number_unsigned);
5953  }
5954  else if (lhs_type == value_t::number_unsigned and rhs_type == value_t::number_integer)
5955  {
5956  return static_cast<number_integer_t>(lhs.m_value.number_unsigned) == rhs.m_value.number_integer;
5957  }
5958  else if (lhs_type == value_t::number_integer and rhs_type == value_t::number_unsigned)
5959  {
5960  return lhs.m_value.number_integer == static_cast<number_integer_t>(rhs.m_value.number_unsigned);
5961  }
5962 
5963  return false;
5964  }
5965 
5984  friend bool operator==(const_reference v, std::nullptr_t) noexcept
5985  {
5986  return v.is_null();
5987  }
5988 
5993  friend bool operator==(std::nullptr_t, const_reference v) noexcept
5994  {
5995  return v.is_null();
5996  }
5997 
6014  friend bool operator!=(const_reference lhs, const_reference rhs) noexcept
6015  {
6016  return not (lhs == rhs);
6017  }
6018 
6037  friend bool operator!=(const_reference v, std::nullptr_t) noexcept
6038  {
6039  return not v.is_null();
6040  }
6041 
6046  friend bool operator!=(std::nullptr_t, const_reference v) noexcept
6047  {
6048  return not v.is_null();
6049  }
6050 
6075  friend bool operator<(const_reference lhs, const_reference rhs) noexcept
6076  {
6077  const auto lhs_type = lhs.type();
6078  const auto rhs_type = rhs.type();
6079 
6080  if (lhs_type == rhs_type)
6081  {
6082  switch (lhs_type)
6083  {
6084  case value_t::array:
6085  {
6086  return *lhs.m_value.array < *rhs.m_value.array;
6087  }
6088  case value_t::object:
6089  {
6090  return *lhs.m_value.object < *rhs.m_value.object;
6091  }
6092  case value_t::null:
6093  {
6094  return false;
6095  }
6096  case value_t::string:
6097  {
6098  return *lhs.m_value.string < *rhs.m_value.string;
6099  }
6100  case value_t::boolean:
6101  {
6102  return lhs.m_value.boolean < rhs.m_value.boolean;
6103  }
6104  case value_t::number_integer:
6105  {
6106  return lhs.m_value.number_integer < rhs.m_value.number_integer;
6107  }
6108  case value_t::number_unsigned:
6109  {
6110  return lhs.m_value.number_unsigned < rhs.m_value.number_unsigned;
6111  }
6112  case value_t::number_float:
6113  {
6114  return lhs.m_value.number_float < rhs.m_value.number_float;
6115  }
6116  default:
6117  {
6118  return false;
6119  }
6120  }
6121  }
6122  else if (lhs_type == value_t::number_integer and rhs_type == value_t::number_float)
6123  {
6124  return static_cast<number_float_t>(lhs.m_value.number_integer) < rhs.m_value.number_float;
6125  }
6126  else if (lhs_type == value_t::number_float and rhs_type == value_t::number_integer)
6127  {
6128  return lhs.m_value.number_float < static_cast<number_float_t>(rhs.m_value.number_integer);
6129  }
6130  else if (lhs_type == value_t::number_unsigned and rhs_type == value_t::number_float)
6131  {
6132  return static_cast<number_float_t>(lhs.m_value.number_unsigned) < rhs.m_value.number_float;
6133  }
6134  else if (lhs_type == value_t::number_float and rhs_type == value_t::number_unsigned)
6135  {
6136  return lhs.m_value.number_float < static_cast<number_float_t>(rhs.m_value.number_unsigned);
6137  }
6138  else if (lhs_type == value_t::number_integer and rhs_type == value_t::number_unsigned)
6139  {
6140  return lhs.m_value.number_integer < static_cast<number_integer_t>(rhs.m_value.number_unsigned);
6141  }
6142  else if (lhs_type == value_t::number_unsigned and rhs_type == value_t::number_integer)
6143  {
6144  return static_cast<number_integer_t>(lhs.m_value.number_unsigned) < rhs.m_value.number_integer;
6145  }
6146 
6147  // We only reach this line if we cannot compare values. In that case,
6148  // we compare types. Note we have to call the operator explicitly,
6149  // because MSVC has problems otherwise.
6150  return operator<(lhs_type, rhs_type);
6151  }
6152 
6170  friend bool operator<=(const_reference lhs, const_reference rhs) noexcept
6171  {
6172  return not (rhs < lhs);
6173  }
6174 
6192  friend bool operator>(const_reference lhs, const_reference rhs) noexcept
6193  {
6194  return not (lhs <= rhs);
6195  }
6196 
6214  friend bool operator>=(const_reference lhs, const_reference rhs) noexcept
6215  {
6216  return not (lhs < rhs);
6217  }
6218 
6220 
6221 
6223  // serialization //
6225 
6228 
6255  friend std::ostream& operator<<(std::ostream& o, const basic_json& j)
6256  {
6257  // read width member and use it as indentation parameter if nonzero
6258  const bool pretty_print = (o.width() > 0);
6259  const auto indentation = (pretty_print ? o.width() : 0);
6260 
6261  // reset width to 0 for subsequent calls to this stream
6262  o.width(0);
6263 
6264  // fix locale problems
6265  const auto old_locale = o.imbue(std::locale::classic());
6266  // set precision
6267 
6268  // 6, 15 or 16 digits of precision allows round-trip IEEE 754
6269  // string->float->string, string->double->string or string->long
6270  // double->string; to be safe, we read this value from
6271  // std::numeric_limits<number_float_t>::digits10
6272  const auto old_precision = o.precision(std::numeric_limits<double>::digits10);
6273 
6274  // do the actual serialization
6275  j.dump(o, pretty_print, static_cast<unsigned int>(indentation));
6276 
6277  // reset locale and precision
6278  o.imbue(old_locale);
6279  o.precision(old_precision);
6280  return o;
6281  }
6282 
6287  friend std::ostream& operator>>(const basic_json& j, std::ostream& o)
6288  {
6289  return o << j;
6290  }
6291 
6293 
6294 
6296  // deserialization //
6298 
6301 
6329  template<class T, std::size_t N>
6330  static basic_json parse(T (&array)[N],
6331  const parser_callback_t cb = nullptr)
6332  {
6333  // delegate the call to the iterator-range parse overload
6334  return parse(std::begin(array), std::end(array), cb);
6335  }
6336 
6364  template<typename CharT, typename std::enable_if<
6365  std::is_pointer<CharT>::value and
6366  std::is_integral<typename std::remove_pointer<CharT>::type>::value and
6367  sizeof(typename std::remove_pointer<CharT>::type) == 1, int>::type = 0>
6368  static basic_json parse(const CharT s,
6369  const parser_callback_t cb = nullptr)
6370  {
6371  return parser(reinterpret_cast<const char*>(s), cb).parse();
6372  }
6373 
6398  static basic_json parse(std::istream& i,
6399  const parser_callback_t cb = nullptr)
6400  {
6401  return parser(i, cb).parse();
6402  }
6403 
6407  static basic_json parse(std::istream&& i,
6408  const parser_callback_t cb = nullptr)
6409  {
6410  return parser(i, cb).parse();
6411  }
6412 
6454  template<class IteratorType, typename std::enable_if<
6455  std::is_base_of<
6456  std::random_access_iterator_tag,
6457  typename std::iterator_traits<IteratorType>::iterator_category>::value, int>::type = 0>
6458  static basic_json parse(IteratorType first, IteratorType last,
6459  const parser_callback_t cb = nullptr)
6460  {
6461  // assertion to check that the iterator range is indeed contiguous,
6462  // see http://stackoverflow.com/a/35008842/266378 for more discussion
6463  assert(std::accumulate(first, last, std::pair<bool, int>(true, 0),
6464  [&first](std::pair<bool, int> res, decltype(*first) val)
6465  {
6466  res.first &= (val == *(std::next(std::addressof(*first), res.second++)));
6467  return res;
6468  }).first);
6469 
6470  // assertion to check that each element is 1 byte long
6471  static_assert(sizeof(typename std::iterator_traits<IteratorType>::value_type) == 1,
6472  "each element in the iterator range must have the size of 1 byte");
6473 
6474  // if iterator range is empty, create a parser with an empty string
6475  // to generate "unexpected EOF" error message
6476  if (std::distance(first, last) <= 0)
6477  {
6478  return parser("").parse();
6479  }
6480 
6481  return parser(first, last, cb).parse();
6482  }
6483 
6524  template<class ContiguousContainer, typename std::enable_if<
6525  not std::is_pointer<ContiguousContainer>::value and
6526  std::is_base_of<
6527  std::random_access_iterator_tag,
6528  typename std::iterator_traits<decltype(std::begin(std::declval<ContiguousContainer const>()))>::iterator_category>::value
6529  , int>::type = 0>
6530  static basic_json parse(const ContiguousContainer& c,
6531  const parser_callback_t cb = nullptr)
6532  {
6533  // delegate the call to the iterator-range parse overload
6534  return parse(std::begin(c), std::end(c), cb);
6535  }
6536 
6560  friend std::istream& operator<<(basic_json& j, std::istream& i)
6561  {
6562  j = parser(i).parse();
6563  return i;
6564  }
6565 
6570  friend std::istream& operator>>(std::istream& i, basic_json& j)
6571  {
6572  j = parser(i).parse();
6573  return i;
6574  }
6575 
6577 
6579  // binary serialization/deserialization //
6581 
6584 
6585  private:
6586  template<typename T>
6587  static void add_to_vector(std::vector<uint8_t>& vec, size_t bytes, const T number)
6588  {
6589  assert(bytes == 1 or bytes == 2 or bytes == 4 or bytes == 8);
6590 
6591  switch (bytes)
6592  {
6593  case 8:
6594  {
6595  vec.push_back(static_cast<uint8_t>((number >> 070) & 0xff));
6596  vec.push_back(static_cast<uint8_t>((number >> 060) & 0xff));
6597  vec.push_back(static_cast<uint8_t>((number >> 050) & 0xff));
6598  vec.push_back(static_cast<uint8_t>((number >> 040) & 0xff));
6599  // intentional fall-through
6600  }
6601 
6602  case 4:
6603  {
6604  vec.push_back(static_cast<uint8_t>((number >> 030) & 0xff));
6605  vec.push_back(static_cast<uint8_t>((number >> 020) & 0xff));
6606  // intentional fall-through
6607  }
6608 
6609  case 2:
6610  {
6611  vec.push_back(static_cast<uint8_t>((number >> 010) & 0xff));
6612  // intentional fall-through
6613  }
6614 
6615  case 1:
6616  {
6617  vec.push_back(static_cast<uint8_t>(number & 0xff));
6618  break;
6619  }
6620  }
6621  }
6622 
6659  template<typename T>
6660  static T get_from_vector(const std::vector<uint8_t>& vec, const size_t current_index)
6661  {
6662  if (current_index + sizeof(T) + 1 > vec.size())
6663  {
6664  JSON_THROW(std::out_of_range("cannot read " + std::to_string(sizeof(T)) + " bytes from vector"));
6665  }
6666 
6667  T result;
6668  auto* ptr = reinterpret_cast<uint8_t*>(&result);
6669  for (size_t i = 0; i < sizeof(T); ++i)
6670  {
6671  *ptr++ = vec[current_index + sizeof(T) - i];
6672  }
6673  return result;
6674  }
6675 
6686  static void to_msgpack_internal(const basic_json& j, std::vector<uint8_t>& v)
6687  {
6688  switch (j.type())
6689  {
6690  case value_t::null:
6691  {
6692  // nil
6693  v.push_back(0xc0);
6694  break;
6695  }
6696 
6697  case value_t::boolean:
6698  {
6699  // true and false
6700  v.push_back(j.m_value.boolean ? 0xc3 : 0xc2);
6701  break;
6702  }
6703 
6704  case value_t::number_integer:
6705  {
6706  if (j.m_value.number_integer >= 0)
6707  {
6708  // MessagePack does not differentiate between positive
6709  // signed integers and unsigned integers. Therefore, we
6710  // used the code from the value_t::number_unsigned case
6711  // here.
6712  if (j.m_value.number_unsigned < 128)
6713  {
6714  // positive fixnum
6715  add_to_vector(v, 1, j.m_value.number_unsigned);
6716  }
6717  else if (j.m_value.number_unsigned <= UINT8_MAX)
6718  {
6719  // uint 8
6720  v.push_back(0xcc);
6721  add_to_vector(v, 1, j.m_value.number_unsigned);
6722  }
6723  else if (j.m_value.number_unsigned <= UINT16_MAX)
6724  {
6725  // uint 16
6726  v.push_back(0xcd);
6727  add_to_vector(v, 2, j.m_value.number_unsigned);
6728  }
6729  else if (j.m_value.number_unsigned <= UINT32_MAX)
6730  {
6731  // uint 32
6732  v.push_back(0xce);
6733  add_to_vector(v, 4, j.m_value.number_unsigned);
6734  }
6735  else if (j.m_value.number_unsigned <= UINT64_MAX)
6736  {
6737  // uint 64
6738  v.push_back(0xcf);
6739  add_to_vector(v, 8, j.m_value.number_unsigned);
6740  }
6741  }
6742  else
6743  {
6744  if (j.m_value.number_integer >= -32)
6745  {
6746  // negative fixnum
6747  add_to_vector(v, 1, j.m_value.number_integer);
6748  }
6749  else if (j.m_value.number_integer >= INT8_MIN and j.m_value.number_integer <= INT8_MAX)
6750  {
6751  // int 8
6752  v.push_back(0xd0);
6753  add_to_vector(v, 1, j.m_value.number_integer);
6754  }
6755  else if (j.m_value.number_integer >= INT16_MIN and j.m_value.number_integer <= INT16_MAX)
6756  {
6757  // int 16
6758  v.push_back(0xd1);
6759  add_to_vector(v, 2, j.m_value.number_integer);
6760  }
6761  else if (j.m_value.number_integer >= INT32_MIN and j.m_value.number_integer <= INT32_MAX)
6762  {
6763  // int 32
6764  v.push_back(0xd2);
6765  add_to_vector(v, 4, j.m_value.number_integer);
6766  }
6767  else if (j.m_value.number_integer >= INT64_MIN and j.m_value.number_integer <= INT64_MAX)
6768  {
6769  // int 64
6770  v.push_back(0xd3);
6771  add_to_vector(v, 8, j.m_value.number_integer);
6772  }
6773  }
6774  break;
6775  }
6776 
6777  case value_t::number_unsigned:
6778  {
6779  if (j.m_value.number_unsigned < 128)
6780  {
6781  // positive fixnum
6782  add_to_vector(v, 1, j.m_value.number_unsigned);
6783  }
6784  else if (j.m_value.number_unsigned <= UINT8_MAX)
6785  {
6786  // uint 8
6787  v.push_back(0xcc);
6788  add_to_vector(v, 1, j.m_value.number_unsigned);
6789  }
6790  else if (j.m_value.number_unsigned <= UINT16_MAX)
6791  {
6792  // uint 16
6793  v.push_back(0xcd);
6794  add_to_vector(v, 2, j.m_value.number_unsigned);
6795  }
6796  else if (j.m_value.number_unsigned <= UINT32_MAX)
6797  {
6798  // uint 32
6799  v.push_back(0xce);
6800  add_to_vector(v, 4, j.m_value.number_unsigned);
6801  }
6802  else if (j.m_value.number_unsigned <= UINT64_MAX)
6803  {
6804  // uint 64
6805  v.push_back(0xcf);
6806  add_to_vector(v, 8, j.m_value.number_unsigned);
6807  }
6808  break;
6809  }
6810 
6811  case value_t::number_float:
6812  {
6813  // float 64
6814  v.push_back(0xcb);
6815  const auto* helper = reinterpret_cast<const uint8_t*>(&(j.m_value.number_float));
6816  for (size_t i = 0; i < 8; ++i)
6817  {
6818  v.push_back(helper[7 - i]);
6819  }
6820  break;
6821  }
6822 
6823  case value_t::string:
6824  {
6825  const auto N = j.m_value.string->size();
6826  if (N <= 31)
6827  {
6828  // fixstr
6829  v.push_back(static_cast<uint8_t>(0xa0 | N));
6830  }
6831  else if (N <= 255)
6832  {
6833  // str 8
6834  v.push_back(0xd9);
6835  add_to_vector(v, 1, N);
6836  }
6837  else if (N <= 65535)
6838  {
6839  // str 16
6840  v.push_back(0xda);
6841  add_to_vector(v, 2, N);
6842  }
6843  else if (N <= 4294967295)
6844  {
6845  // str 32
6846  v.push_back(0xdb);
6847  add_to_vector(v, 4, N);
6848  }
6849 
6850  // append string
6851  std::copy(j.m_value.string->begin(), j.m_value.string->end(),
6852  std::back_inserter(v));
6853  break;
6854  }
6855 
6856  case value_t::array:
6857  {
6858  const auto N = j.m_value.array->size();
6859  if (N <= 15)
6860  {
6861  // fixarray
6862  v.push_back(static_cast<uint8_t>(0x90 | N));
6863  }
6864  else if (N <= 0xffff)
6865  {
6866  // array 16
6867  v.push_back(0xdc);
6868  add_to_vector(v, 2, N);
6869  }
6870  else if (N <= 0xffffffff)
6871  {
6872  // array 32
6873  v.push_back(0xdd);
6874  add_to_vector(v, 4, N);
6875  }
6876 
6877  // append each element
6878  for (const auto& el : *j.m_value.array)
6879  {
6880  to_msgpack_internal(el, v);
6881  }
6882  break;
6883  }
6884 
6885  case value_t::object:
6886  {
6887  const auto N = j.m_value.object->size();
6888  if (N <= 15)
6889  {
6890  // fixmap
6891  v.push_back(static_cast<uint8_t>(0x80 | (N & 0xf)));
6892  }
6893  else if (N <= 65535)
6894  {
6895  // map 16
6896  v.push_back(0xde);
6897  add_to_vector(v, 2, N);
6898  }
6899  else if (N <= 4294967295)
6900  {
6901  // map 32
6902  v.push_back(0xdf);
6903  add_to_vector(v, 4, N);
6904  }
6905 
6906  // append each element
6907  for (const auto& el : *j.m_value.object)
6908  {
6909  to_msgpack_internal(el.first, v);
6910  to_msgpack_internal(el.second, v);
6911  }
6912  break;
6913  }
6914 
6915  default:
6916  {
6917  break;
6918  }
6919  }
6920  }
6921 
6932  static void to_cbor_internal(const basic_json& j, std::vector<uint8_t>& v)
6933  {
6934  switch (j.type())
6935  {
6936  case value_t::null:
6937  {
6938  v.push_back(0xf6);
6939  break;
6940  }
6941 
6942  case value_t::boolean:
6943  {
6944  v.push_back(j.m_value.boolean ? 0xf5 : 0xf4);
6945  break;
6946  }
6947 
6948  case value_t::number_integer:
6949  {
6950  if (j.m_value.number_integer >= 0)
6951  {
6952  // CBOR does not differentiate between positive signed
6953  // integers and unsigned integers. Therefore, we used the
6954  // code from the value_t::number_unsigned case here.
6955  if (j.m_value.number_integer <= 0x17)
6956  {
6957  add_to_vector(v, 1, j.m_value.number_integer);
6958  }
6959  else if (j.m_value.number_integer <= UINT8_MAX)
6960  {
6961  v.push_back(0x18);
6962  // one-byte uint8_t
6963  add_to_vector(v, 1, j.m_value.number_integer);
6964  }
6965  else if (j.m_value.number_integer <= UINT16_MAX)
6966  {
6967  v.push_back(0x19);
6968  // two-byte uint16_t
6969  add_to_vector(v, 2, j.m_value.number_integer);
6970  }
6971  else if (j.m_value.number_integer <= UINT32_MAX)
6972  {
6973  v.push_back(0x1a);
6974  // four-byte uint32_t
6975  add_to_vector(v, 4, j.m_value.number_integer);
6976  }
6977  else
6978  {
6979  v.push_back(0x1b);
6980  // eight-byte uint64_t
6981  add_to_vector(v, 8, j.m_value.number_integer);
6982  }
6983  }
6984  else
6985  {
6986  // The conversions below encode the sign in the first
6987  // byte, and the value is converted to a positive number.
6988  const auto positive_number = -1 - j.m_value.number_integer;
6989  if (j.m_value.number_integer >= -24)
6990  {
6991  v.push_back(static_cast<uint8_t>(0x20 + positive_number));
6992  }
6993  else if (positive_number <= UINT8_MAX)
6994  {
6995  // int 8
6996  v.push_back(0x38);
6997  add_to_vector(v, 1, positive_number);
6998  }
6999  else if (positive_number <= UINT16_MAX)
7000  {
7001  // int 16
7002  v.push_back(0x39);
7003  add_to_vector(v, 2, positive_number);
7004  }
7005  else if (positive_number <= UINT32_MAX)
7006  {
7007  // int 32
7008  v.push_back(0x3a);
7009  add_to_vector(v, 4, positive_number);
7010  }
7011  else
7012  {
7013  // int 64
7014  v.push_back(0x3b);
7015  add_to_vector(v, 8, positive_number);
7016  }
7017  }
7018  break;
7019  }
7020 
7021  case value_t::number_unsigned:
7022  {
7023  if (j.m_value.number_unsigned <= 0x17)
7024  {
7025  v.push_back(static_cast<uint8_t>(j.m_value.number_unsigned));
7026  }
7027  else if (j.m_value.number_unsigned <= 0xff)
7028  {
7029  v.push_back(0x18);
7030  // one-byte uint8_t
7031  add_to_vector(v, 1, j.m_value.number_unsigned);
7032  }
7033  else if (j.m_value.number_unsigned <= 0xffff)
7034  {
7035  v.push_back(0x19);
7036  // two-byte uint16_t
7037  add_to_vector(v, 2, j.m_value.number_unsigned);
7038  }
7039  else if (j.m_value.number_unsigned <= 0xffffffff)
7040  {
7041  v.push_back(0x1a);
7042  // four-byte uint32_t
7043  add_to_vector(v, 4, j.m_value.number_unsigned);
7044  }
7045  else if (j.m_value.number_unsigned <= 0xffffffffffffffff)
7046  {
7047  v.push_back(0x1b);
7048  // eight-byte uint64_t
7049  add_to_vector(v, 8, j.m_value.number_unsigned);
7050  }
7051  break;
7052  }
7053 
7054  case value_t::number_float:
7055  {
7056  // Double-Precision Float
7057  v.push_back(0xfb);
7058  const auto* helper = reinterpret_cast<const uint8_t*>(&(j.m_value.number_float));
7059  for (size_t i = 0; i < 8; ++i)
7060  {
7061  v.push_back(helper[7 - i]);
7062  }
7063  break;
7064  }
7065 
7066  case value_t::string:
7067  {
7068  const auto N = j.m_value.string->size();
7069  if (N <= 0x17)
7070  {
7071  v.push_back(0x60 + N); // 1 byte for string + size
7072  }
7073  else if (N <= 0xff)
7074  {
7075  v.push_back(0x78); // one-byte uint8_t for N
7076  add_to_vector(v, 1, N);
7077  }
7078  else if (N <= 0xffff)
7079  {
7080  v.push_back(0x79); // two-byte uint16_t for N
7081  add_to_vector(v, 2, N);
7082  }
7083  else if (N <= 0xffffffff)
7084  {
7085  v.push_back(0x7a); // four-byte uint32_t for N
7086  add_to_vector(v, 4, N);
7087  }
7088  // LCOV_EXCL_START
7089  else if (N <= 0xffffffffffffffff)
7090  {
7091  v.push_back(0x7b); // eight-byte uint64_t for N
7092  add_to_vector(v, 8, N);
7093  }
7094  // LCOV_EXCL_STOP
7095 
7096  // append string
7097  std::copy(j.m_value.string->begin(), j.m_value.string->end(),
7098  std::back_inserter(v));
7099  break;
7100  }
7101 
7102  case value_t::array:
7103  {
7104  const auto N = j.m_value.array->size();
7105  if (N <= 0x17)
7106  {
7107  v.push_back(0x80 + N); // 1 byte for array + size
7108  }
7109  else if (N <= 0xff)
7110  {
7111  v.push_back(0x98); // one-byte uint8_t for N
7112  add_to_vector(v, 1, N);
7113  }
7114  else if (N <= 0xffff)
7115  {
7116  v.push_back(0x99); // two-byte uint16_t for N
7117  add_to_vector(v, 2, N);
7118  }
7119  else if (N <= 0xffffffff)
7120  {
7121  v.push_back(0x9a); // four-byte uint32_t for N
7122  add_to_vector(v, 4, N);
7123  }
7124  // LCOV_EXCL_START
7125  else if (N <= 0xffffffffffffffff)
7126  {
7127  v.push_back(0x9b); // eight-byte uint64_t for N
7128  add_to_vector(v, 8, N);
7129  }
7130  // LCOV_EXCL_STOP
7131 
7132  // append each element
7133  for (const auto& el : *j.m_value.array)
7134  {
7135  to_cbor_internal(el, v);
7136  }
7137  break;
7138  }
7139 
7140  case value_t::object:
7141  {
7142  const auto N = j.m_value.object->size();
7143  if (N <= 0x17)
7144  {
7145  v.push_back(0xa0 + N); // 1 byte for object + size
7146  }
7147  else if (N <= 0xff)
7148  {
7149  v.push_back(0xb8);
7150  add_to_vector(v, 1, N); // one-byte uint8_t for N
7151  }
7152  else if (N <= 0xffff)
7153  {
7154  v.push_back(0xb9);
7155  add_to_vector(v, 2, N); // two-byte uint16_t for N
7156  }
7157  else if (N <= 0xffffffff)
7158  {
7159  v.push_back(0xba);
7160  add_to_vector(v, 4, N); // four-byte uint32_t for N
7161  }
7162  // LCOV_EXCL_START
7163  else if (N <= 0xffffffffffffffff)
7164  {
7165  v.push_back(0xbb);
7166  add_to_vector(v, 8, N); // eight-byte uint64_t for N
7167  }
7168  // LCOV_EXCL_STOP
7169 
7170  // append each element
7171  for (const auto& el : *j.m_value.object)
7172  {
7173  to_cbor_internal(el.first, v);
7174  to_cbor_internal(el.second, v);
7175  }
7176  break;
7177  }
7178 
7179  default:
7180  {
7181  break;
7182  }
7183  }
7184  }
7185 
7186 
7187  /*
7188  @brief checks if given lengths do not exceed the size of a given vector
7189 
7190  To secure the access to the byte vector during CBOR/MessagePack
7191  deserialization, bytes are copied from the vector into buffers. This
7192  function checks if the number of bytes to copy (@a len) does not exceed
7193  the size @s size of the vector. Additionally, an @a offset is given from
7194  where to start reading the bytes.
7195 
7196  This function checks whether reading the bytes is safe; that is, offset is
7197  a valid index in the vector, offset+len
7198 
7199  @param[in] size size of the byte vector
7200  @param[in] len number of bytes to read
7201  @param[in] offset offset where to start reading
7202 
7203  vec: x x x x x X X X X X
7204  ^ ^ ^
7205  0 offset len
7206 
7207  @throws out_of_range if `len > v.size()`
7208  */
7209  static void check_length(const size_t size, const size_t len, const size_t offset)
7210  {
7211  // simple case: requested length is greater than the vector's length
7212  if (len > size or offset > size)
7213  {
7214  JSON_THROW(std::out_of_range("len out of range"));
7215  }
7216 
7217  // second case: adding offset would result in overflow
7218  if ((size > (std::numeric_limits<size_t>::max() - offset)))
7219  {
7220  JSON_THROW(std::out_of_range("len+offset out of range"));
7221  }
7222 
7223  // last case: reading past the end of the vector
7224  if (len + offset > size)
7225  {
7226  JSON_THROW(std::out_of_range("len+offset out of range"));
7227  }
7228  }
7229 
7244  static basic_json from_msgpack_internal(const std::vector<uint8_t>& v, size_t& idx)
7245  {
7246  // make sure reading 1 byte is safe
7247  check_length(v.size(), 1, idx);
7248 
7249  // store and increment index
7250  const size_t current_idx = idx++;
7251 
7252  if (v[current_idx] <= 0xbf)
7253  {
7254  if (v[current_idx] <= 0x7f) // positive fixint
7255  {
7256  return v[current_idx];
7257  }
7258  if (v[current_idx] <= 0x8f) // fixmap
7259  {
7260  basic_json result = value_t::object;
7261  const size_t len = v[current_idx] & 0x0f;
7262  for (size_t i = 0; i < len; ++i)
7263  {
7264  std::string key = from_msgpack_internal(v, idx);
7265  result[key] = from_msgpack_internal(v, idx);
7266  }
7267  return result;
7268  }
7269  else if (v[current_idx] <= 0x9f) // fixarray
7270  {
7271  basic_json result = value_t::array;
7272  const size_t len = v[current_idx] & 0x0f;
7273  for (size_t i = 0; i < len; ++i)
7274  {
7275  result.push_back(from_msgpack_internal(v, idx));
7276  }
7277  return result;
7278  }
7279  else // fixstr
7280  {
7281  const size_t len = v[current_idx] & 0x1f;
7282  const size_t offset = current_idx + 1;
7283  idx += len; // skip content bytes
7284  check_length(v.size(), len, offset);
7285  return std::string(reinterpret_cast<const char*>(v.data()) + offset, len);
7286  }
7287  }
7288  else if (v[current_idx] >= 0xe0) // negative fixint
7289  {
7290  return static_cast<int8_t>(v[current_idx]);
7291  }
7292  else
7293  {
7294  switch (v[current_idx])
7295  {
7296  case 0xc0: // nil
7297  {
7298  return value_t::null;
7299  }
7300 
7301  case 0xc2: // false
7302  {
7303  return false;
7304  }
7305 
7306  case 0xc3: // true
7307  {
7308  return true;
7309  }
7310 
7311  case 0xca: // float 32
7312  {
7313  // copy bytes in reverse order into the double variable
7314  float res;
7315  for (size_t byte = 0; byte < sizeof(float); ++byte)
7316  {
7317  reinterpret_cast<uint8_t*>(&res)[sizeof(float) - byte - 1] = v.at(current_idx + 1 + byte);
7318  }
7319  idx += sizeof(float); // skip content bytes
7320  return res;
7321  }
7322 
7323  case 0xcb: // float 64
7324  {
7325  // copy bytes in reverse order into the double variable
7326  double res;
7327  for (size_t byte = 0; byte < sizeof(double); ++byte)
7328  {
7329  reinterpret_cast<uint8_t*>(&res)[sizeof(double) - byte - 1] = v.at(current_idx + 1 + byte);
7330  }
7331  idx += sizeof(double); // skip content bytes
7332  return res;
7333  }
7334 
7335  case 0xcc: // uint 8
7336  {
7337  idx += 1; // skip content byte
7338  return get_from_vector<uint8_t>(v, current_idx);
7339  }
7340 
7341  case 0xcd: // uint 16
7342  {
7343  idx += 2; // skip 2 content bytes
7344  return get_from_vector<uint16_t>(v, current_idx);
7345  }
7346 
7347  case 0xce: // uint 32
7348  {
7349  idx += 4; // skip 4 content bytes
7350  return get_from_vector<uint32_t>(v, current_idx);
7351  }
7352 
7353  case 0xcf: // uint 64
7354  {
7355  idx += 8; // skip 8 content bytes
7356  return get_from_vector<uint64_t>(v, current_idx);
7357  }
7358 
7359  case 0xd0: // int 8
7360  {
7361  idx += 1; // skip content byte
7362  return get_from_vector<int8_t>(v, current_idx);
7363  }
7364 
7365  case 0xd1: // int 16
7366  {
7367  idx += 2; // skip 2 content bytes
7368  return get_from_vector<int16_t>(v, current_idx);
7369  }
7370 
7371  case 0xd2: // int 32
7372  {
7373  idx += 4; // skip 4 content bytes
7374  return get_from_vector<int32_t>(v, current_idx);
7375  }
7376 
7377  case 0xd3: // int 64
7378  {
7379  idx += 8; // skip 8 content bytes
7380  return get_from_vector<int64_t>(v, current_idx);
7381  }
7382 
7383  case 0xd9: // str 8
7384  {
7385  const auto len = static_cast<size_t>(get_from_vector<uint8_t>(v, current_idx));
7386  const size_t offset = current_idx + 2;
7387  idx += len + 1; // skip size byte + content bytes
7388  check_length(v.size(), len, offset);
7389  return std::string(reinterpret_cast<const char*>(v.data()) + offset, len);
7390  }
7391 
7392  case 0xda: // str 16
7393  {
7394  const auto len = static_cast<size_t>(get_from_vector<uint16_t>(v, current_idx));
7395  const size_t offset = current_idx + 3;
7396  idx += len + 2; // skip 2 size bytes + content bytes
7397  check_length(v.size(), len, offset);
7398  return std::string(reinterpret_cast<const char*>(v.data()) + offset, len);
7399  }
7400 
7401  case 0xdb: // str 32
7402  {
7403  const auto len = static_cast<size_t>(get_from_vector<uint32_t>(v, current_idx));
7404  const size_t offset = current_idx + 5;
7405  idx += len + 4; // skip 4 size bytes + content bytes
7406  check_length(v.size(), len, offset);
7407  return std::string(reinterpret_cast<const char*>(v.data()) + offset, len);
7408  }
7409 
7410  case 0xdc: // array 16
7411  {
7412  basic_json result = value_t::array;
7413  const auto len = static_cast<size_t>(get_from_vector<uint16_t>(v, current_idx));
7414  idx += 2; // skip 2 size bytes
7415  for (size_t i = 0; i < len; ++i)
7416  {
7417  result.push_back(from_msgpack_internal(v, idx));
7418  }
7419  return result;
7420  }
7421 
7422  case 0xdd: // array 32
7423  {
7424  basic_json result = value_t::array;
7425  const auto len = static_cast<size_t>(get_from_vector<uint32_t>(v, current_idx));
7426  idx += 4; // skip 4 size bytes
7427  for (size_t i = 0; i < len; ++i)
7428  {
7429  result.push_back(from_msgpack_internal(v, idx));
7430  }
7431  return result;
7432  }
7433 
7434  case 0xde: // map 16
7435  {
7436  basic_json result = value_t::object;
7437  const auto len = static_cast<size_t>(get_from_vector<uint16_t>(v, current_idx));
7438  idx += 2; // skip 2 size bytes
7439  for (size_t i = 0; i < len; ++i)
7440  {
7441  std::string key = from_msgpack_internal(v, idx);
7442  result[key] = from_msgpack_internal(v, idx);
7443  }
7444  return result;
7445  }
7446 
7447  case 0xdf: // map 32
7448  {
7449  basic_json result = value_t::object;
7450  const auto len = static_cast<size_t>(get_from_vector<uint32_t>(v, current_idx));
7451  idx += 4; // skip 4 size bytes
7452  for (size_t i = 0; i < len; ++i)
7453  {
7454  std::string key = from_msgpack_internal(v, idx);
7455  result[key] = from_msgpack_internal(v, idx);
7456  }
7457  return result;
7458  }
7459 
7460  default:
7461  {
7462  JSON_THROW(std::invalid_argument("error parsing a msgpack @ " + std::to_string(current_idx) + ": " + std::to_string(static_cast<int>(v[current_idx]))));
7463  }
7464  }
7465  }
7466  }
7467 
7482  static basic_json from_cbor_internal(const std::vector<uint8_t>& v, size_t& idx)
7483  {
7484  // store and increment index
7485  const size_t current_idx = idx++;
7486 
7487  switch (v.at(current_idx))
7488  {
7489  // Integer 0x00..0x17 (0..23)
7490  case 0x00:
7491  case 0x01:
7492  case 0x02:
7493  case 0x03:
7494  case 0x04:
7495  case 0x05:
7496  case 0x06:
7497  case 0x07:
7498  case 0x08:
7499  case 0x09:
7500  case 0x0a:
7501  case 0x0b:
7502  case 0x0c:
7503  case 0x0d:
7504  case 0x0e:
7505  case 0x0f:
7506  case 0x10:
7507  case 0x11:
7508  case 0x12:
7509  case 0x13:
7510  case 0x14:
7511  case 0x15:
7512  case 0x16:
7513  case 0x17:
7514  {
7515  return v[current_idx];
7516  }
7517 
7518  case 0x18: // Unsigned integer (one-byte uint8_t follows)
7519  {
7520  idx += 1; // skip content byte
7521  return get_from_vector<uint8_t>(v, current_idx);
7522  }
7523 
7524  case 0x19: // Unsigned integer (two-byte uint16_t follows)
7525  {
7526  idx += 2; // skip 2 content bytes
7527  return get_from_vector<uint16_t>(v, current_idx);
7528  }
7529 
7530  case 0x1a: // Unsigned integer (four-byte uint32_t follows)
7531  {
7532  idx += 4; // skip 4 content bytes
7533  return get_from_vector<uint32_t>(v, current_idx);
7534  }
7535 
7536  case 0x1b: // Unsigned integer (eight-byte uint64_t follows)
7537  {
7538  idx += 8; // skip 8 content bytes
7539  return get_from_vector<uint64_t>(v, current_idx);
7540  }
7541 
7542  // Negative integer -1-0x00..-1-0x17 (-1..-24)
7543  case 0x20:
7544  case 0x21:
7545  case 0x22:
7546  case 0x23:
7547  case 0x24:
7548  case 0x25:
7549  case 0x26:
7550  case 0x27:
7551  case 0x28:
7552  case 0x29:
7553  case 0x2a:
7554  case 0x2b:
7555  case 0x2c:
7556  case 0x2d:
7557  case 0x2e:
7558  case 0x2f:
7559  case 0x30:
7560  case 0x31:
7561  case 0x32:
7562  case 0x33:
7563  case 0x34:
7564  case 0x35:
7565  case 0x36:
7566  case 0x37:
7567  {
7568  return static_cast<int8_t>(0x20 - 1 - v[current_idx]);
7569  }
7570 
7571  case 0x38: // Negative integer (one-byte uint8_t follows)
7572  {
7573  idx += 1; // skip content byte
7574  // must be uint8_t !
7575  return static_cast<number_integer_t>(-1) - get_from_vector<uint8_t>(v, current_idx);
7576  }
7577 
7578  case 0x39: // Negative integer -1-n (two-byte uint16_t follows)
7579  {
7580  idx += 2; // skip 2 content bytes
7581  return static_cast<number_integer_t>(-1) - get_from_vector<uint16_t>(v, current_idx);
7582  }
7583 
7584  case 0x3a: // Negative integer -1-n (four-byte uint32_t follows)
7585  {
7586  idx += 4; // skip 4 content bytes
7587  return static_cast<number_integer_t>(-1) - get_from_vector<uint32_t>(v, current_idx);
7588  }
7589 
7590  case 0x3b: // Negative integer -1-n (eight-byte uint64_t follows)
7591  {
7592  idx += 8; // skip 8 content bytes
7593  return static_cast<number_integer_t>(-1) - static_cast<number_integer_t>(get_from_vector<uint64_t>(v, current_idx));
7594  }
7595 
7596  // UTF-8 string (0x00..0x17 bytes follow)
7597  case 0x60:
7598  case 0x61:
7599  case 0x62:
7600  case 0x63:
7601  case 0x64:
7602  case 0x65:
7603  case 0x66:
7604  case 0x67:
7605  case 0x68:
7606  case 0x69:
7607  case 0x6a:
7608  case 0x6b:
7609  case 0x6c:
7610  case 0x6d:
7611  case 0x6e:
7612  case 0x6f:
7613  case 0x70:
7614  case 0x71:
7615  case 0x72:
7616  case 0x73:
7617  case 0x74:
7618  case 0x75:
7619  case 0x76:
7620  case 0x77:
7621  {
7622  const auto len = static_cast<size_t>(v[current_idx] - 0x60);
7623  const size_t offset = current_idx + 1;
7624  idx += len; // skip content bytes
7625  check_length(v.size(), len, offset);
7626  return std::string(reinterpret_cast<const char*>(v.data()) + offset, len);
7627  }
7628 
7629  case 0x78: // UTF-8 string (one-byte uint8_t for n follows)
7630  {
7631  const auto len = static_cast<size_t>(get_from_vector<uint8_t>(v, current_idx));
7632  const size_t offset = current_idx + 2;
7633  idx += len + 1; // skip size byte + content bytes
7634  check_length(v.size(), len, offset);
7635  return std::string(reinterpret_cast<const char*>(v.data()) + offset, len);
7636  }
7637 
7638  case 0x79: // UTF-8 string (two-byte uint16_t for n follow)
7639  {
7640  const auto len = static_cast<size_t>(get_from_vector<uint16_t>(v, current_idx));
7641  const size_t offset = current_idx + 3;
7642  idx += len + 2; // skip 2 size bytes + content bytes
7643  check_length(v.size(), len, offset);
7644  return std::string(reinterpret_cast<const char*>(v.data()) + offset, len);
7645  }
7646 
7647  case 0x7a: // UTF-8 string (four-byte uint32_t for n follow)
7648  {
7649  const auto len = static_cast<size_t>(get_from_vector<uint32_t>(v, current_idx));
7650  const size_t offset = current_idx + 5;
7651  idx += len + 4; // skip 4 size bytes + content bytes
7652  check_length(v.size(), len, offset);
7653  return std::string(reinterpret_cast<const char*>(v.data()) + offset, len);
7654  }
7655 
7656  case 0x7b: // UTF-8 string (eight-byte uint64_t for n follow)
7657  {
7658  const auto len = static_cast<size_t>(get_from_vector<uint64_t>(v, current_idx));
7659  const size_t offset = current_idx + 9;
7660  idx += len + 8; // skip 8 size bytes + content bytes
7661  check_length(v.size(), len, offset);
7662  return std::string(reinterpret_cast<const char*>(v.data()) + offset, len);
7663  }
7664 
7665  case 0x7f: // UTF-8 string (indefinite length)
7666  {
7667  std::string result;
7668  while (v.at(idx) != 0xff)
7669  {
7670  string_t s = from_cbor_internal(v, idx);
7671  result += s;
7672  }
7673  // skip break byte (0xFF)
7674  idx += 1;
7675  return result;
7676  }
7677 
7678  // array (0x00..0x17 data items follow)
7679  case 0x80:
7680  case 0x81:
7681  case 0x82:
7682  case 0x83:
7683  case 0x84:
7684  case 0x85:
7685  case 0x86:
7686  case 0x87:
7687  case 0x88:
7688  case 0x89:
7689  case 0x8a:
7690  case 0x8b:
7691  case 0x8c:
7692  case 0x8d:
7693  case 0x8e:
7694  case 0x8f:
7695  case 0x90:
7696  case 0x91:
7697  case 0x92:
7698  case 0x93:
7699  case 0x94:
7700  case 0x95:
7701  case 0x96:
7702  case 0x97:
7703  {
7704  basic_json result = value_t::array;
7705  const auto len = static_cast<size_t>(v[current_idx] - 0x80);
7706  for (size_t i = 0; i < len; ++i)
7707  {
7708  result.push_back(from_cbor_internal(v, idx));
7709  }
7710  return result;
7711  }
7712 
7713  case 0x98: // array (one-byte uint8_t for n follows)
7714  {
7715  basic_json result = value_t::array;
7716  const auto len = static_cast<size_t>(get_from_vector<uint8_t>(v, current_idx));
7717  idx += 1; // skip 1 size byte
7718  for (size_t i = 0; i < len; ++i)
7719  {
7720  result.push_back(from_cbor_internal(v, idx));
7721  }
7722  return result;
7723  }
7724 
7725  case 0x99: // array (two-byte uint16_t for n follow)
7726  {
7727  basic_json result = value_t::array;
7728  const auto len = static_cast<size_t>(get_from_vector<uint16_t>(v, current_idx));
7729  idx += 2; // skip 4 size bytes
7730  for (size_t i = 0; i < len; ++i)
7731  {
7732  result.push_back(from_cbor_internal(v, idx));
7733  }
7734  return result;
7735  }
7736 
7737  case 0x9a: // array (four-byte uint32_t for n follow)
7738  {
7739  basic_json result = value_t::array;
7740  const auto len = static_cast<size_t>(get_from_vector<uint32_t>(v, current_idx));
7741  idx += 4; // skip 4 size bytes
7742  for (size_t i = 0; i < len; ++i)
7743  {
7744  result.push_back(from_cbor_internal(v, idx));
7745  }
7746  return result;
7747  }
7748 
7749  case 0x9b: // array (eight-byte uint64_t for n follow)
7750  {
7751  basic_json result = value_t::array;
7752  const auto len = static_cast<size_t>(get_from_vector<uint64_t>(v, current_idx));
7753  idx += 8; // skip 8 size bytes
7754  for (size_t i = 0; i < len; ++i)
7755  {
7756  result.push_back(from_cbor_internal(v, idx));
7757  }
7758  return result;
7759  }
7760 
7761  case 0x9f: // array (indefinite length)
7762  {
7763  basic_json result = value_t::array;
7764  while (v.at(idx) != 0xff)
7765  {
7766  result.push_back(from_cbor_internal(v, idx));
7767  }
7768  // skip break byte (0xFF)
7769  idx += 1;
7770  return result;
7771  }
7772 
7773  // map (0x00..0x17 pairs of data items follow)
7774  case 0xa0:
7775  case 0xa1:
7776  case 0xa2:
7777  case 0xa3:
7778  case 0xa4:
7779  case 0xa5:
7780  case 0xa6:
7781  case 0xa7:
7782  case 0xa8:
7783  case 0xa9:
7784  case 0xaa:
7785  case 0xab:
7786  case 0xac:
7787  case 0xad:
7788  case 0xae:
7789  case 0xaf:
7790  case 0xb0:
7791  case 0xb1:
7792  case 0xb2:
7793  case 0xb3:
7794  case 0xb4:
7795  case 0xb5:
7796  case 0xb6:
7797  case 0xb7:
7798  {
7799  basic_json result = value_t::object;
7800  const auto len = static_cast<size_t>(v[current_idx] - 0xa0);
7801  for (size_t i = 0; i < len; ++i)
7802  {
7803  std::string key = from_cbor_internal(v, idx);
7804  result[key] = from_cbor_internal(v, idx);
7805  }
7806  return result;
7807  }
7808 
7809  case 0xb8: // map (one-byte uint8_t for n follows)
7810  {
7811  basic_json result = value_t::object;
7812  const auto len = static_cast<size_t>(get_from_vector<uint8_t>(v, current_idx));
7813  idx += 1; // skip 1 size byte
7814  for (size_t i = 0; i < len; ++i)
7815  {
7816  std::string key = from_cbor_internal(v, idx);
7817  result[key] = from_cbor_internal(v, idx);
7818  }
7819  return result;
7820  }
7821 
7822  case 0xb9: // map (two-byte uint16_t for n follow)
7823  {
7824  basic_json result = value_t::object;
7825  const auto len = static_cast<size_t>(get_from_vector<uint16_t>(v, current_idx));
7826  idx += 2; // skip 2 size bytes
7827  for (size_t i = 0; i < len; ++i)
7828  {
7829  std::string key = from_cbor_internal(v, idx);
7830  result[key] = from_cbor_internal(v, idx);
7831  }
7832  return result;
7833  }
7834 
7835  case 0xba: // map (four-byte uint32_t for n follow)
7836  {
7837  basic_json result = value_t::object;
7838  const auto len = static_cast<size_t>(get_from_vector<uint32_t>(v, current_idx));
7839  idx += 4; // skip 4 size bytes
7840  for (size_t i = 0; i < len; ++i)
7841  {
7842  std::string key = from_cbor_internal(v, idx);
7843  result[key] = from_cbor_internal(v, idx);
7844  }
7845  return result;
7846  }
7847 
7848  case 0xbb: // map (eight-byte uint64_t for n follow)
7849  {
7850  basic_json result = value_t::object;
7851  const auto len = static_cast<size_t>(get_from_vector<uint64_t>(v, current_idx));
7852  idx += 8; // skip 8 size bytes
7853  for (size_t i = 0; i < len; ++i)
7854  {
7855  std::string key = from_cbor_internal(v, idx);
7856  result[key] = from_cbor_internal(v, idx);
7857  }
7858  return result;
7859  }
7860 
7861  case 0xbf: // map (indefinite length)
7862  {
7863  basic_json result = value_t::object;
7864  while (v.at(idx) != 0xff)
7865  {
7866  std::string key = from_cbor_internal(v, idx);
7867  result[key] = from_cbor_internal(v, idx);
7868  }
7869  // skip break byte (0xFF)
7870  idx += 1;
7871  return result;
7872  }
7873 
7874  case 0xf4: // false
7875  {
7876  return false;
7877  }
7878 
7879  case 0xf5: // true
7880  {
7881  return true;
7882  }
7883 
7884  case 0xf6: // null
7885  {
7886  return value_t::null;
7887  }
7888 
7889  case 0xf9: // Half-Precision Float (two-byte IEEE 754)
7890  {
7891  idx += 2; // skip two content bytes
7892 
7893  // code from RFC 7049, Appendix D, Figure 3:
7894  // As half-precision floating-point numbers were only added to
7895  // IEEE 754 in 2008, today's programming platforms often still
7896  // only have limited support for them. It is very easy to
7897  // include at least decoding support for them even without such
7898  // support. An example of a small decoder for half-precision
7899  // floating-point numbers in the C language is shown in Fig. 3.
7900  const int half = (v.at(current_idx + 1) << 8) + v.at(current_idx + 2);
7901  const int exp = (half >> 10) & 0x1f;
7902  const int mant = half & 0x3ff;
7903  double val;
7904  if (exp == 0)
7905  {
7906  val = std::ldexp(mant, -24);
7907  }
7908  else if (exp != 31)
7909  {
7910  val = std::ldexp(mant + 1024, exp - 25);
7911  }
7912  else
7913  {
7914  val = mant == 0 ? INFINITY : NAN;
7915  }
7916  return (half & 0x8000) != 0 ? -val : val;
7917  }
7918 
7919  case 0xfa: // Single-Precision Float (four-byte IEEE 754)
7920  {
7921  // copy bytes in reverse order into the float variable
7922  float res;
7923  for (size_t byte = 0; byte < sizeof(float); ++byte)
7924  {
7925  reinterpret_cast<uint8_t*>(&res)[sizeof(float) - byte - 1] = v.at(current_idx + 1 + byte);
7926  }
7927  idx += sizeof(float); // skip content bytes
7928  return res;
7929  }
7930 
7931  case 0xfb: // Double-Precision Float (eight-byte IEEE 754)
7932  {
7933  // copy bytes in reverse order into the double variable
7934  double res;
7935  for (size_t byte = 0; byte < sizeof(double); ++byte)
7936  {
7937  reinterpret_cast<uint8_t*>(&res)[sizeof(double) - byte - 1] = v.at(current_idx + 1 + byte);
7938  }
7939  idx += sizeof(double); // skip content bytes
7940  return res;
7941  }
7942 
7943  default: // anything else (0xFF is handled inside the other types)
7944  {
7945  JSON_THROW(std::invalid_argument("error parsing a CBOR @ " + std::to_string(current_idx) + ": " + std::to_string(static_cast<int>(v[current_idx]))));
7946  }
7947  }
7948  }
7949 
7950  public:
7971  static std::vector<uint8_t> to_msgpack(const basic_json& j)
7972  {
7973  std::vector<uint8_t> result;
7974  to_msgpack_internal(j, result);
7975  return result;
7976  }
7977 
8000  static basic_json from_msgpack(const std::vector<uint8_t>& v)
8001  {
8002  size_t i = 0;
8003  return from_msgpack_internal(v, i);
8004  }
8005 
8027  static std::vector<uint8_t> to_cbor(const basic_json& j)
8028  {
8029  std::vector<uint8_t> result;
8030  to_cbor_internal(j, result);
8031  return result;
8032  }
8033 
8057  static basic_json from_cbor(const std::vector<uint8_t>& v)
8058  {
8059  size_t i = 0;
8060  return from_cbor_internal(v, i);
8061  }
8062 
8064 
8066  // convenience functions //
8068 
8084  std::string type_name() const
8085  {
8086  {
8087  switch (m_type)
8088  {
8089  case value_t::null:
8090  return "null";
8091  case value_t::object:
8092  return "object";
8093  case value_t::array:
8094  return "array";
8095  case value_t::string:
8096  return "string";
8097  case value_t::boolean:
8098  return "boolean";
8099  case value_t::discarded:
8100  return "discarded";
8101  default:
8102  return "number";
8103  }
8104  }
8105  }
8106 
8107  private:
8116  static std::size_t extra_space(const string_t& s) noexcept
8117  {
8118  return std::accumulate(s.begin(), s.end(), size_t{},
8119  [](size_t res, typename string_t::value_type c)
8120  {
8121  switch (c)
8122  {
8123  case '"':
8124  case '\\':
8125  case '\b':
8126  case '\f':
8127  case '\n':
8128  case '\r':
8129  case '\t':
8130  {
8131  // from c (1 byte) to \x (2 bytes)
8132  return res + 1;
8133  }
8134 
8135  default:
8136  {
8137  if (c >= 0x00 and c <= 0x1f)
8138  {
8139  // from c (1 byte) to \uxxxx (6 bytes)
8140  return res + 5;
8141  }
8142 
8143  return res;
8144  }
8145  }
8146  });
8147  }
8148 
8162  static string_t escape_string(const string_t& s)
8163  {
8164  const auto space = extra_space(s);
8165  if (space == 0)
8166  {
8167  return s;
8168  }
8169 
8170  // create a result string of necessary size
8171  string_t result(s.size() + space, '\\');
8172  std::size_t pos = 0;
8173 
8174  for (const auto& c : s)
8175  {
8176  switch (c)
8177  {
8178  // quotation mark (0x22)
8179  case '"':
8180  {
8181  result[pos + 1] = '"';
8182  pos += 2;
8183  break;
8184  }
8185 
8186  // reverse solidus (0x5c)
8187  case '\\':
8188  {
8189  // nothing to change
8190  pos += 2;
8191  break;
8192  }
8193 
8194  // backspace (0x08)
8195  case '\b':
8196  {
8197  result[pos + 1] = 'b';
8198  pos += 2;
8199  break;
8200  }
8201 
8202  // formfeed (0x0c)
8203  case '\f':
8204  {
8205  result[pos + 1] = 'f';
8206  pos += 2;
8207  break;
8208  }
8209 
8210  // newline (0x0a)
8211  case '\n':
8212  {
8213  result[pos + 1] = 'n';
8214  pos += 2;
8215  break;
8216  }
8217 
8218  // carriage return (0x0d)
8219  case '\r':
8220  {
8221  result[pos + 1] = 'r';
8222  pos += 2;
8223  break;
8224  }
8225 
8226  // horizontal tab (0x09)
8227  case '\t':
8228  {
8229  result[pos + 1] = 't';
8230  pos += 2;
8231  break;
8232  }
8233 
8234  default:
8235  {
8236  if (c >= 0x00 and c <= 0x1f)
8237  {
8238  // convert a number 0..15 to its hex representation
8239  // (0..f)
8240  static const char hexify[16] =
8241  {
8242  '0', '1', '2', '3', '4', '5', '6', '7',
8243  '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'
8244  };
8245 
8246  // print character c as \uxxxx
8247  for (const char m :
8248  { 'u', '0', '0', hexify[c >> 4], hexify[c & 0x0f]
8249  })
8250  {
8251  result[++pos] = m;
8252  }
8253 
8254  ++pos;
8255  }
8256  else
8257  {
8258  // all other characters are added as-is
8259  result[pos++] = c;
8260  }
8261  break;
8262  }
8263  }
8264  }
8265 
8266  return result;
8267  }
8268 
8286  void dump(std::ostream& o,
8287  const bool pretty_print,
8288  const unsigned int indent_step,
8289  const unsigned int current_indent = 0) const
8290  {
8291  // variable to hold indentation for recursive calls
8292  unsigned int new_indent = current_indent;
8293 
8294  switch (m_type)
8295  {
8296  case value_t::object:
8297  {
8298  if (m_value.object->empty())
8299  {
8300  o << "{}";
8301  return;
8302  }
8303 
8304  o << "{";
8305 
8306  // increase indentation
8307  if (pretty_print)
8308  {
8309  new_indent += indent_step;
8310  o << "\n";
8311  }
8312 
8313  for (auto i = m_value.object->cbegin(); i != m_value.object->cend(); ++i)
8314  {
8315  if (i != m_value.object->cbegin())
8316  {
8317  o << (pretty_print ? ",\n" : ",");
8318  }
8319  o << string_t(new_indent, ' ') << "\""
8320  << escape_string(i->first) << "\":"
8321  << (pretty_print ? " " : "");
8322  i->second.dump(o, pretty_print, indent_step, new_indent);
8323  }
8324 
8325  // decrease indentation
8326  if (pretty_print)
8327  {
8328  new_indent -= indent_step;
8329  o << "\n";
8330  }
8331 
8332  o << string_t(new_indent, ' ') + "}";
8333  return;
8334  }
8335 
8336  case value_t::array:
8337  {
8338  if (m_value.array->empty())
8339  {
8340  o << "[]";
8341  return;
8342  }
8343 
8344  o << "[";
8345 
8346  // increase indentation
8347  if (pretty_print)
8348  {
8349  new_indent += indent_step;
8350  o << "\n";
8351  }
8352 
8353  for (auto i = m_value.array->cbegin(); i != m_value.array->cend(); ++i)
8354  {
8355  if (i != m_value.array->cbegin())
8356  {
8357  o << (pretty_print ? ",\n" : ",");
8358  }
8359  o << string_t(new_indent, ' ');
8360  i->dump(o, pretty_print, indent_step, new_indent);
8361  }
8362 
8363  // decrease indentation
8364  if (pretty_print)
8365  {
8366  new_indent -= indent_step;
8367  o << "\n";
8368  }
8369 
8370  o << string_t(new_indent, ' ') << "]";
8371  return;
8372  }
8373 
8374  case value_t::string:
8375  {
8376  o << string_t("\"") << escape_string(*m_value.string) << "\"";
8377  return;
8378  }
8379 
8380  case value_t::boolean:
8381  {
8382  o << (m_value.boolean ? "true" : "false");
8383  return;
8384  }
8385 
8386  case value_t::number_integer:
8387  {
8388  o << m_value.number_integer;
8389  return;
8390  }
8391 
8392  case value_t::number_unsigned:
8393  {
8394  o << m_value.number_unsigned;
8395  return;
8396  }
8397 
8398  case value_t::number_float:
8399  {
8400  if (m_value.number_float == 0)
8401  {
8402  // special case for zero to get "0.0"/"-0.0"
8403  o << (std::signbit(m_value.number_float) ? "-0.0" : "0.0");
8404  }
8405  else
8406  {
8407  o << m_value.number_float;
8408  }
8409  return;
8410  }
8411 
8412  case value_t::discarded:
8413  {
8414  o << "<discarded>";
8415  return;
8416  }
8417 
8418  case value_t::null:
8419  {
8420  o << "null";
8421  return;
8422  }
8423  }
8424  }
8425 
8426  private:
8428  // member variables //
8430 
8432  value_t m_type = value_t::null;
8433 
8435  json_value m_value = {};
8436 
8437 
8438  private:
8440  // iterators //
8442 
8452  class primitive_iterator_t
8453  {
8454  public:
8455 
8456  difference_type get_value() const noexcept
8457  {
8458  return m_it;
8459  }
8461  void set_begin() noexcept
8462  {
8463  m_it = begin_value;
8464  }
8465 
8467  void set_end() noexcept
8468  {
8469  m_it = end_value;
8470  }
8471 
8473  constexpr bool is_begin() const noexcept
8474  {
8475  return (m_it == begin_value);
8476  }
8477 
8479  constexpr bool is_end() const noexcept
8480  {
8481  return (m_it == end_value);
8482  }
8483 
8484  friend constexpr bool operator==(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept
8485  {
8486  return lhs.m_it == rhs.m_it;
8487  }
8488 
8489  friend constexpr bool operator!=(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept
8490  {
8491  return !(lhs == rhs);
8492  }
8493 
8494  friend constexpr bool operator<(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept
8495  {
8496  return lhs.m_it < rhs.m_it;
8497  }
8498 
8499  friend constexpr bool operator<=(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept
8500  {
8501  return lhs.m_it <= rhs.m_it;
8502  }
8503 
8504  friend constexpr bool operator>(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept
8505  {
8506  return lhs.m_it > rhs.m_it;
8507  }
8508 
8509  friend constexpr bool operator>=(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept
8510  {
8511  return lhs.m_it >= rhs.m_it;
8512  }
8513 
8514  primitive_iterator_t operator+(difference_type i)
8515  {
8516  auto result = *this;
8517  result += i;
8518  return result;
8519  }
8520 
8521  friend constexpr difference_type operator-(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept
8522  {
8523  return lhs.m_it - rhs.m_it;
8524  }
8525 
8526  friend std::ostream& operator<<(std::ostream& os, primitive_iterator_t it)
8527  {
8528  return os << it.m_it;
8529  }
8530 
8531  primitive_iterator_t& operator++()
8532  {
8533  ++m_it;
8534  return *this;
8535  }
8536 
8537  primitive_iterator_t& operator++(int)
8538  {
8539  m_it++;
8540  return *this;
8541  }
8542 
8543  primitive_iterator_t& operator--()
8544  {
8545  --m_it;
8546  return *this;
8547  }
8548 
8549  primitive_iterator_t& operator--(int)
8550  {
8551  m_it--;
8552  return *this;
8553  }
8554 
8555  primitive_iterator_t& operator+=(difference_type n)
8556  {
8557  m_it += n;
8558  return *this;
8559  }
8560 
8561  primitive_iterator_t& operator-=(difference_type n)
8562  {
8563  m_it -= n;
8564  return *this;
8565  }
8566 
8567  private:
8568  static constexpr difference_type begin_value = 0;
8569  static constexpr difference_type end_value = begin_value + 1;
8570 
8572  difference_type m_it = std::numeric_limits<std::ptrdiff_t>::denorm_min();
8573  };
8574 
8582  struct internal_iterator
8583  {
8585  typename object_t::iterator object_iterator;
8587  typename array_t::iterator array_iterator;
8589  primitive_iterator_t primitive_iterator;
8590 
8592  internal_iterator() noexcept
8593  : object_iterator(), array_iterator(), primitive_iterator()
8594  {}
8595  };
8596 
8598  template<typename IteratorType>
8599  class iteration_proxy
8600  {
8601  private:
8603  class iteration_proxy_internal
8604  {
8605  private:
8607  IteratorType anchor;
8609  size_t array_index = 0;
8610 
8611  public:
8612  explicit iteration_proxy_internal(IteratorType it) noexcept
8613  : anchor(it)
8614  {}
8615 
8617  iteration_proxy_internal& operator*()
8618  {
8619  return *this;
8620  }
8621 
8623  iteration_proxy_internal& operator++()
8624  {
8625  ++anchor;
8626  ++array_index;
8627 
8628  return *this;
8629  }
8630 
8632  bool operator!= (const iteration_proxy_internal& o) const
8633  {
8634  return anchor != o.anchor;
8635  }
8636 
8638  typename basic_json::string_t key() const
8639  {
8640  assert(anchor.m_object != nullptr);
8641 
8642  switch (anchor.m_object->type())
8643  {
8644  // use integer array index as key
8645  case value_t::array:
8646  {
8647  return std::to_string(array_index);
8648  }
8649 
8650  // use key from the object
8651  case value_t::object:
8652  {
8653  return anchor.key();
8654  }
8655 
8656  // use an empty key for all primitive types
8657  default:
8658  {
8659  return "";
8660  }
8661  }
8662  }
8663 
8665  typename IteratorType::reference value() const
8666  {
8667  return anchor.value();
8668  }
8669  };
8670 
8672  typename IteratorType::reference container;
8673 
8674  public:
8676  explicit iteration_proxy(typename IteratorType::reference cont)
8677  : container(cont)
8678  {}
8679 
8681  iteration_proxy_internal begin() noexcept
8682  {
8683  return iteration_proxy_internal(container.begin());
8684  }
8685 
8687  iteration_proxy_internal end() noexcept
8688  {
8689  return iteration_proxy_internal(container.end());
8690  }
8691  };
8692 
8693  public:
8713  template<typename U>
8714  class iter_impl : public std::iterator<std::random_access_iterator_tag, U>
8715  {
8717  friend class basic_json;
8718 
8719  // make sure U is basic_json or const basic_json
8720  static_assert(std::is_same<U, basic_json>::value
8721  or std::is_same<U, const basic_json>::value,
8722  "iter_impl only accepts (const) basic_json");
8723 
8724  public:
8730  using pointer = typename std::conditional<std::is_const<U>::value,
8731  typename basic_json::const_pointer,
8732  typename basic_json::pointer>::type;
8734  using reference = typename std::conditional<std::is_const<U>::value,
8735  typename basic_json::const_reference,
8736  typename basic_json::reference>::type;
8738  using iterator_category = std::bidirectional_iterator_tag;
8739 
8741  iter_impl() = default;
8742 
8749  explicit iter_impl(pointer object) noexcept
8750  : m_object(object)
8751  {
8752  assert(m_object != nullptr);
8753 
8754  switch (m_object->m_type)
8755  {
8756  case basic_json::value_t::object:
8757  {
8758  m_it.object_iterator = typename object_t::iterator();
8759  break;
8760  }
8761 
8762  case basic_json::value_t::array:
8763  {
8764  m_it.array_iterator = typename array_t::iterator();
8765  break;
8766  }
8767 
8768  default:
8769  {
8770  m_it.primitive_iterator = primitive_iterator_t();
8771  break;
8772  }
8773  }
8774  }
8775 
8776  /*
8777  Use operator `const_iterator` instead of `const_iterator(const iterator&
8778  other) noexcept` to avoid two class definitions for @ref iterator and
8779  @ref const_iterator.
8780 
8781  This function is only called if this class is an @ref iterator. If this
8782  class is a @ref const_iterator this function is not called.
8783  */
8784  operator const_iterator() const
8785  {
8786  const_iterator ret;
8787 
8788  if (m_object)
8789  {
8790  ret.m_object = m_object;
8791  ret.m_it = m_it;
8792  }
8793 
8794  return ret;
8795  }
8796 
8802  iter_impl(const iter_impl& other) noexcept
8803  : m_object(other.m_object), m_it(other.m_it)
8804  {}
8805 
8811  iter_impl& operator=(iter_impl other) noexcept(
8812  std::is_nothrow_move_constructible<pointer>::value and
8813  std::is_nothrow_move_assignable<pointer>::value and
8814  std::is_nothrow_move_constructible<internal_iterator>::value and
8815  std::is_nothrow_move_assignable<internal_iterator>::value
8816  )
8817  {
8818  std::swap(m_object, other.m_object);
8819  std::swap(m_it, other.m_it);
8820  return *this;
8821  }
8822 
8823  private:
8828  void set_begin() noexcept
8829  {
8830  assert(m_object != nullptr);
8831 
8832  switch (m_object->m_type)
8833  {
8834  case basic_json::value_t::object:
8835  {
8836  m_it.object_iterator = m_object->m_value.object->begin();
8837  break;
8838  }
8839 
8840  case basic_json::value_t::array:
8841  {
8842  m_it.array_iterator = m_object->m_value.array->begin();
8843  break;
8844  }
8845 
8846  case basic_json::value_t::null:
8847  {
8848  // set to end so begin()==end() is true: null is empty
8849  m_it.primitive_iterator.set_end();
8850  break;
8851  }
8852 
8853  default:
8854  {
8855  m_it.primitive_iterator.set_begin();
8856  break;
8857  }
8858  }
8859  }
8860 
8865  void set_end() noexcept
8866  {
8867  assert(m_object != nullptr);
8868 
8869  switch (m_object->m_type)
8870  {
8871  case basic_json::value_t::object:
8872  {
8873  m_it.object_iterator = m_object->m_value.object->end();
8874  break;
8875  }
8876 
8877  case basic_json::value_t::array:
8878  {
8879  m_it.array_iterator = m_object->m_value.array->end();
8880  break;
8881  }
8882 
8883  default:
8884  {
8885  m_it.primitive_iterator.set_end();
8886  break;
8887  }
8888  }
8889  }
8890 
8891  public:
8897  {
8898  assert(m_object != nullptr);
8899 
8900  switch (m_object->m_type)
8901  {
8902  case basic_json::value_t::object:
8903  {
8904  assert(m_it.object_iterator != m_object->m_value.object->end());
8905  return m_it.object_iterator->second;
8906  }
8907 
8908  case basic_json::value_t::array:
8909  {
8910  assert(m_it.array_iterator != m_object->m_value.array->end());
8911  return *m_it.array_iterator;
8912  }
8913 
8914  case basic_json::value_t::null:
8915  {
8916  JSON_THROW(std::out_of_range("cannot get value"));
8917  }
8918 
8919  default:
8920  {
8921  if (m_it.primitive_iterator.is_begin())
8922  {
8923  return *m_object;
8924  }
8925 
8926  JSON_THROW(std::out_of_range("cannot get value"));
8927  }
8928  }
8929  }
8930 
8936  {
8937  assert(m_object != nullptr);
8938 
8939  switch (m_object->m_type)
8940  {
8941  case basic_json::value_t::object:
8942  {
8943  assert(m_it.object_iterator != m_object->m_value.object->end());
8944  return &(m_it.object_iterator->second);
8945  }
8946 
8947  case basic_json::value_t::array:
8948  {
8949  assert(m_it.array_iterator != m_object->m_value.array->end());
8950  return &*m_it.array_iterator;
8951  }
8952 
8953  default:
8954  {
8955  if (m_it.primitive_iterator.is_begin())
8956  {
8957  return m_object;
8958  }
8959 
8960  JSON_THROW(std::out_of_range("cannot get value"));
8961  }
8962  }
8963  }
8964 
8970  {
8971  auto result = *this;
8972  ++(*this);
8973  return result;
8974  }
8975 
8981  {
8982  assert(m_object != nullptr);
8983 
8984  switch (m_object->m_type)
8985  {
8986  case basic_json::value_t::object:
8987  {
8988  std::advance(m_it.object_iterator, 1);
8989  break;
8990  }
8991 
8992  case basic_json::value_t::array:
8993  {
8994  std::advance(m_it.array_iterator, 1);
8995  break;
8996  }
8997 
8998  default:
8999  {
9000  ++m_it.primitive_iterator;
9001  break;
9002  }
9003  }
9004 
9005  return *this;
9006  }
9007 
9013  {
9014  auto result = *this;
9015  --(*this);
9016  return result;
9017  }
9018 
9024  {
9025  assert(m_object != nullptr);
9026 
9027  switch (m_object->m_type)
9028  {
9029  case basic_json::value_t::object:
9030  {
9031  std::advance(m_it.object_iterator, -1);
9032  break;
9033  }
9034 
9035  case basic_json::value_t::array:
9036  {
9037  std::advance(m_it.array_iterator, -1);
9038  break;
9039  }
9040 
9041  default:
9042  {
9043  --m_it.primitive_iterator;
9044  break;
9045  }
9046  }
9047 
9048  return *this;
9049  }
9050 
9055  bool operator==(const iter_impl& other) const
9056  {
9057  // if objects are not the same, the comparison is undefined
9058  if (m_object != other.m_object)
9059  {
9060  JSON_THROW(std::domain_error("cannot compare iterators of different containers"));
9061  }
9062 
9063  assert(m_object != nullptr);
9064 
9065  switch (m_object->m_type)
9066  {
9067  case basic_json::value_t::object:
9068  {
9069  return (m_it.object_iterator == other.m_it.object_iterator);
9070  }
9071 
9072  case basic_json::value_t::array:
9073  {
9074  return (m_it.array_iterator == other.m_it.array_iterator);
9075  }
9076 
9077  default:
9078  {
9079  return (m_it.primitive_iterator == other.m_it.primitive_iterator);
9080  }
9081  }
9082  }
9083 
9088  bool operator!=(const iter_impl& other) const
9089  {
9090  return not operator==(other);
9091  }
9092 
9097  bool operator<(const iter_impl& other) const
9098  {
9099  // if objects are not the same, the comparison is undefined
9100  if (m_object != other.m_object)
9101  {
9102  JSON_THROW(std::domain_error("cannot compare iterators of different containers"));
9103  }
9104 
9105  assert(m_object != nullptr);
9106 
9107  switch (m_object->m_type)
9108  {
9109  case basic_json::value_t::object:
9110  {
9111  JSON_THROW(std::domain_error("cannot compare order of object iterators"));
9112  }
9113 
9114  case basic_json::value_t::array:
9115  {
9116  return (m_it.array_iterator < other.m_it.array_iterator);
9117  }
9118 
9119  default:
9120  {
9121  return (m_it.primitive_iterator < other.m_it.primitive_iterator);
9122  }
9123  }
9124  }
9125 
9130  bool operator<=(const iter_impl& other) const
9131  {
9132  return not other.operator < (*this);
9133  }
9134 
9139  bool operator>(const iter_impl& other) const
9140  {
9141  return not operator<=(other);
9142  }
9143 
9148  bool operator>=(const iter_impl& other) const
9149  {
9150  return not operator<(other);
9151  }
9152 
9158  {
9159  assert(m_object != nullptr);
9160 
9161  switch (m_object->m_type)
9162  {
9163  case basic_json::value_t::object:
9164  {
9165  JSON_THROW(std::domain_error("cannot use offsets with object iterators"));
9166  }
9167 
9168  case basic_json::value_t::array:
9169  {
9170  std::advance(m_it.array_iterator, i);
9171  break;
9172  }
9173 
9174  default:
9175  {
9176  m_it.primitive_iterator += i;
9177  break;
9178  }
9179  }
9180 
9181  return *this;
9182  }
9183 
9189  {
9190  return operator+=(-i);
9191  }
9192 
9198  {
9199  auto result = *this;
9200  result += i;
9201  return result;
9202  }
9203 
9209  {
9210  auto result = *this;
9211  result -= i;
9212  return result;
9213  }
9214 
9220  {
9221  assert(m_object != nullptr);
9222 
9223  switch (m_object->m_type)
9224  {
9225  case basic_json::value_t::object:
9226  {
9227  JSON_THROW(std::domain_error("cannot use offsets with object iterators"));
9228  }
9229 
9230  case basic_json::value_t::array:
9231  {
9232  return m_it.array_iterator - other.m_it.array_iterator;
9233  }
9234 
9235  default:
9236  {
9237  return m_it.primitive_iterator - other.m_it.primitive_iterator;
9238  }
9239  }
9240  }
9241 
9247  {
9248  assert(m_object != nullptr);
9249 
9250  switch (m_object->m_type)
9251  {
9252  case basic_json::value_t::object:
9253  {
9254  JSON_THROW(std::domain_error("cannot use operator[] for object iterators"));
9255  }
9256 
9257  case basic_json::value_t::array:
9258  {
9259  return *std::next(m_it.array_iterator, n);
9260  }
9261 
9262  case basic_json::value_t::null:
9263  {
9264  JSON_THROW(std::out_of_range("cannot get value"));
9265  }
9266 
9267  default:
9268  {
9269  if (m_it.primitive_iterator.get_value() == -n)
9270  {
9271  return *m_object;
9272  }
9273 
9274  JSON_THROW(std::out_of_range("cannot get value"));
9275  }
9276  }
9277  }
9278 
9283  typename object_t::key_type key() const
9284  {
9285  assert(m_object != nullptr);
9286 
9287  if (m_object->is_object())
9288  {
9289  return m_it.object_iterator->first;
9290  }
9291 
9292  JSON_THROW(std::domain_error("cannot use key() for non-object iterators"));
9293  }
9294 
9300  {
9301  return operator*();
9302  }
9303 
9304  private:
9306  pointer m_object = nullptr;
9308  internal_iterator m_it = internal_iterator();
9309  };
9310 
9328  template<typename Base>
9329  class json_reverse_iterator : public std::reverse_iterator<Base>
9330  {
9331  public:
9333  using base_iterator = std::reverse_iterator<Base>;
9335  using reference = typename Base::reference;
9336 
9338  json_reverse_iterator(const typename base_iterator::iterator_type& it) noexcept
9339  : base_iterator(it)
9340  {}
9341 
9344  : base_iterator(it)
9345  {}
9346 
9349  {
9350  return base_iterator::operator++(1);
9351  }
9352 
9355  {
9356  base_iterator::operator++();
9357  return *this;
9358  }
9359 
9362  {
9363  return base_iterator::operator--(1);
9364  }
9365 
9368  {
9369  base_iterator::operator--();
9370  return *this;
9371  }
9372 
9375  {
9376  base_iterator::operator+=(i);
9377  return *this;
9378  }
9379 
9382  {
9383  auto result = *this;
9384  result += i;
9385  return result;
9386  }
9387 
9390  {
9391  auto result = *this;
9392  result -= i;
9393  return result;
9394  }
9395 
9398  {
9399  return this->base() - other.base();
9400  }
9401 
9404  {
9405  return *(this->operator+(n));
9406  }
9407 
9409  typename object_t::key_type key() const
9410  {
9411  auto it = --this->base();
9412  return it.key();
9413  }
9414 
9417  {
9418  auto it = --this->base();
9419  return it.operator * ();
9420  }
9421  };
9422 
9423 
9424  private:
9426  // lexer and parser //
9428 
9436  class lexer
9437  {
9438  public:
9440  enum class token_type
9441  {
9442  uninitialized,
9443  literal_true,
9444  literal_false,
9445  literal_null,
9446  value_string,
9447  value_number,
9448  begin_array,
9449  begin_object,
9450  end_array,
9451  end_object,
9452  name_separator,
9453  value_separator,
9454  parse_error,
9455  end_of_input
9456  };
9457 
9459  using lexer_char_t = unsigned char;
9460 
9462  lexer(const lexer_char_t* buff, const size_t len) noexcept
9463  : m_content(buff)
9464  {
9465  assert(m_content != nullptr);
9466  m_start = m_cursor = m_content;
9467  m_limit = m_content + len;
9468  }
9469 
9471  explicit lexer(std::istream& s)
9472  : m_stream(&s), m_line_buffer()
9473  {
9474  // immediately abort if stream is erroneous
9475  if (s.fail())
9476  {
9477  JSON_THROW(std::invalid_argument("stream error"));
9478  }
9479 
9480  // fill buffer
9481  fill_line_buffer();
9482 
9483  // skip UTF-8 byte-order mark
9484  if (m_line_buffer.size() >= 3 and m_line_buffer.substr(0, 3) == "\xEF\xBB\xBF")
9485  {
9486  m_line_buffer[0] = ' ';
9487  m_line_buffer[1] = ' ';
9488  m_line_buffer[2] = ' ';
9489  }
9490  }
9491 
9492  // switch off unwanted functions (due to pointer members)
9493  lexer() = delete;
9494  lexer(const lexer&) = delete;
9495  lexer operator=(const lexer&) = delete;
9496 
9520  static string_t to_unicode(const std::size_t codepoint1,
9521  const std::size_t codepoint2 = 0)
9522  {
9523  // calculate the code point from the given code points
9524  std::size_t codepoint = codepoint1;
9525 
9526  // check if codepoint1 is a high surrogate
9527  if (codepoint1 >= 0xD800 and codepoint1 <= 0xDBFF)
9528  {
9529  // check if codepoint2 is a low surrogate
9530  if (codepoint2 >= 0xDC00 and codepoint2 <= 0xDFFF)
9531  {
9532  codepoint =
9533  // high surrogate occupies the most significant 22 bits
9534  (codepoint1 << 10)
9535  // low surrogate occupies the least significant 15 bits
9536  + codepoint2
9537  // there is still the 0xD800, 0xDC00 and 0x10000 noise
9538  // in the result so we have to subtract with:
9539  // (0xD800 << 10) + DC00 - 0x10000 = 0x35FDC00
9540  - 0x35FDC00;
9541  }
9542  else
9543  {
9544  JSON_THROW(std::invalid_argument("missing or wrong low surrogate"));
9545  }
9546  }
9547 
9548  string_t result;
9549 
9550  if (codepoint < 0x80)
9551  {
9552  // 1-byte characters: 0xxxxxxx (ASCII)
9553  result.append(1, static_cast<typename string_t::value_type>(codepoint));
9554  }
9555  else if (codepoint <= 0x7ff)
9556  {
9557  // 2-byte characters: 110xxxxx 10xxxxxx
9558  result.append(1, static_cast<typename string_t::value_type>(0xC0 | ((codepoint >> 6) & 0x1F)));
9559  result.append(1, static_cast<typename string_t::value_type>(0x80 | (codepoint & 0x3F)));
9560  }
9561  else if (codepoint <= 0xffff)
9562  {
9563  // 3-byte characters: 1110xxxx 10xxxxxx 10xxxxxx
9564  result.append(1, static_cast<typename string_t::value_type>(0xE0 | ((codepoint >> 12) & 0x0F)));
9565  result.append(1, static_cast<typename string_t::value_type>(0x80 | ((codepoint >> 6) & 0x3F)));
9566  result.append(1, static_cast<typename string_t::value_type>(0x80 | (codepoint & 0x3F)));
9567  }
9568  else if (codepoint <= 0x10ffff)
9569  {
9570  // 4-byte characters: 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
9571  result.append(1, static_cast<typename string_t::value_type>(0xF0 | ((codepoint >> 18) & 0x07)));
9572  result.append(1, static_cast<typename string_t::value_type>(0x80 | ((codepoint >> 12) & 0x3F)));
9573  result.append(1, static_cast<typename string_t::value_type>(0x80 | ((codepoint >> 6) & 0x3F)));
9574  result.append(1, static_cast<typename string_t::value_type>(0x80 | (codepoint & 0x3F)));
9575  }
9576  else
9577  {
9578  JSON_THROW(std::out_of_range("code points above 0x10FFFF are invalid"));
9579  }
9580 
9581  return result;
9582  }
9583 
9585  static std::string token_type_name(const token_type t)
9586  {
9587  switch (t)
9588  {
9589  case token_type::uninitialized:
9590  return "<uninitialized>";
9591  case token_type::literal_true:
9592  return "true literal";
9593  case token_type::literal_false:
9594  return "false literal";
9595  case token_type::literal_null:
9596  return "null literal";
9597  case token_type::value_string:
9598  return "string literal";
9599  case token_type::value_number:
9600  return "number literal";
9601  case token_type::begin_array:
9602  return "'['";
9603  case token_type::begin_object:
9604  return "'{'";
9605  case token_type::end_array:
9606  return "']'";
9607  case token_type::end_object:
9608  return "'}'";
9609  case token_type::name_separator:
9610  return "':'";
9611  case token_type::value_separator:
9612  return "','";
9613  case token_type::parse_error:
9614  return "<parse error>";
9615  case token_type::end_of_input:
9616  return "end of input";
9617  default:
9618  {
9619  // catch non-enum values
9620  return "unknown token"; // LCOV_EXCL_LINE
9621  }
9622  }
9623  }
9624 
9646  token_type scan()
9647  {
9648  while (true)
9649  {
9650  // pointer for backtracking information
9651  m_marker = nullptr;
9652 
9653  // remember the begin of the token
9654  m_start = m_cursor;
9655  assert(m_start != nullptr);
9656 
9657 
9658  {
9659  lexer_char_t yych;
9660  unsigned int yyaccept = 0;
9661  static const unsigned char yybm[] =
9662  {
9663  0, 0, 0, 0, 0, 0, 0, 0,
9664  0, 32, 32, 0, 0, 32, 0, 0,
9665  0, 0, 0, 0, 0, 0, 0, 0,
9666  0, 0, 0, 0, 0, 0, 0, 0,
9667  160, 128, 0, 128, 128, 128, 128, 128,
9668  128, 128, 128, 128, 128, 128, 128, 128,
9669  192, 192, 192, 192, 192, 192, 192, 192,
9670  192, 192, 128, 128, 128, 128, 128, 128,
9671  128, 128, 128, 128, 128, 128, 128, 128,
9672  128, 128, 128, 128, 128, 128, 128, 128,
9673  128, 128, 128, 128, 128, 128, 128, 128,
9674  128, 128, 128, 128, 0, 128, 128, 128,
9675  128, 128, 128, 128, 128, 128, 128, 128,
9676  128, 128, 128, 128, 128, 128, 128, 128,
9677  128, 128, 128, 128, 128, 128, 128, 128,
9678  128, 128, 128, 128, 128, 128, 128, 128,
9679  0, 0, 0, 0, 0, 0, 0, 0,
9680  0, 0, 0, 0, 0, 0, 0, 0,
9681  0, 0, 0, 0, 0, 0, 0, 0,
9682  0, 0, 0, 0, 0, 0, 0, 0,
9683  0, 0, 0, 0, 0, 0, 0, 0,
9684  0, 0, 0, 0, 0, 0, 0, 0,
9685  0, 0, 0, 0, 0, 0, 0, 0,
9686  0, 0, 0, 0, 0, 0, 0, 0,
9687  0, 0, 0, 0, 0, 0, 0, 0,
9688  0, 0, 0, 0, 0, 0, 0, 0,
9689  0, 0, 0, 0, 0, 0, 0, 0,
9690  0, 0, 0, 0, 0, 0, 0, 0,
9691  0, 0, 0, 0, 0, 0, 0, 0,
9692  0, 0, 0, 0, 0, 0, 0, 0,
9693  0, 0, 0, 0, 0, 0, 0, 0,
9694  0, 0, 0, 0, 0, 0, 0, 0,
9695  };
9696  if ((m_limit - m_cursor) < 5)
9697  {
9698  fill_line_buffer(5); // LCOV_EXCL_LINE
9699  }
9700  yych = *m_cursor;
9701  if (yybm[0 + yych] & 32)
9702  {
9703  goto basic_json_parser_6;
9704  }
9705  if (yych <= '[')
9706  {
9707  if (yych <= '-')
9708  {
9709  if (yych <= '"')
9710  {
9711  if (yych <= 0x00)
9712  {
9713  goto basic_json_parser_2;
9714  }
9715  if (yych <= '!')
9716  {
9717  goto basic_json_parser_4;
9718  }
9719  goto basic_json_parser_9;
9720  }
9721  else
9722  {
9723  if (yych <= '+')
9724  {
9725  goto basic_json_parser_4;
9726  }
9727  if (yych <= ',')
9728  {
9729  goto basic_json_parser_10;
9730  }
9731  goto basic_json_parser_12;
9732  }
9733  }
9734  else
9735  {
9736  if (yych <= '9')
9737  {
9738  if (yych <= '/')
9739  {
9740  goto basic_json_parser_4;
9741  }
9742  if (yych <= '0')
9743  {
9744  goto basic_json_parser_13;
9745  }
9746  goto basic_json_parser_15;
9747  }
9748  else
9749  {
9750  if (yych <= ':')
9751  {
9752  goto basic_json_parser_17;
9753  }
9754  if (yych <= 'Z')
9755  {
9756  goto basic_json_parser_4;
9757  }
9758  goto basic_json_parser_19;
9759  }
9760  }
9761  }
9762  else
9763  {
9764  if (yych <= 'n')
9765  {
9766  if (yych <= 'e')
9767  {
9768  if (yych == ']')
9769  {
9770  goto basic_json_parser_21;
9771  }
9772  goto basic_json_parser_4;
9773  }
9774  else
9775  {
9776  if (yych <= 'f')
9777  {
9778  goto basic_json_parser_23;
9779  }
9780  if (yych <= 'm')
9781  {
9782  goto basic_json_parser_4;
9783  }
9784  goto basic_json_parser_24;
9785  }
9786  }
9787  else
9788  {
9789  if (yych <= 'z')
9790  {
9791  if (yych == 't')
9792  {
9793  goto basic_json_parser_25;
9794  }
9795  goto basic_json_parser_4;
9796  }
9797  else
9798  {
9799  if (yych <= '{')
9800  {
9801  goto basic_json_parser_26;
9802  }
9803  if (yych == '}')
9804  {
9805  goto basic_json_parser_28;
9806  }
9807  goto basic_json_parser_4;
9808  }
9809  }
9810  }
9811 basic_json_parser_2:
9812  ++m_cursor;
9813  {
9814  last_token_type = token_type::end_of_input;
9815  break;
9816  }
9817 basic_json_parser_4:
9818  ++m_cursor;
9819 basic_json_parser_5:
9820  {
9821  last_token_type = token_type::parse_error;
9822  break;
9823  }
9824 basic_json_parser_6:
9825  ++m_cursor;
9826  if (m_limit <= m_cursor)
9827  {
9828  fill_line_buffer(1); // LCOV_EXCL_LINE
9829  }
9830  yych = *m_cursor;
9831  if (yybm[0 + yych] & 32)
9832  {
9833  goto basic_json_parser_6;
9834  }
9835  {
9836  continue;
9837  }
9838 basic_json_parser_9:
9839  yyaccept = 0;
9840  yych = *(m_marker = ++m_cursor);
9841  if (yych <= 0x1F)
9842  {
9843  goto basic_json_parser_5;
9844  }
9845  if (yych <= 0x7F)
9846  {
9847  goto basic_json_parser_31;
9848  }
9849  if (yych <= 0xC1)
9850  {
9851  goto basic_json_parser_5;
9852  }
9853  if (yych <= 0xF4)
9854  {
9855  goto basic_json_parser_31;
9856  }
9857  goto basic_json_parser_5;
9858 basic_json_parser_10:
9859  ++m_cursor;
9860  {
9861  last_token_type = token_type::value_separator;
9862  break;
9863  }
9864 basic_json_parser_12:
9865  yych = *++m_cursor;
9866  if (yych <= '/')
9867  {
9868  goto basic_json_parser_5;
9869  }
9870  if (yych <= '0')
9871  {
9872  goto basic_json_parser_13;
9873  }
9874  if (yych <= '9')
9875  {
9876  goto basic_json_parser_15;
9877  }
9878  goto basic_json_parser_5;
9879 basic_json_parser_13:
9880  yyaccept = 1;
9881  yych = *(m_marker = ++m_cursor);
9882  if (yych <= 'D')
9883  {
9884  if (yych == '.')
9885  {
9886  goto basic_json_parser_43;
9887  }
9888  }
9889  else
9890  {
9891  if (yych <= 'E')
9892  {
9893  goto basic_json_parser_44;
9894  }
9895  if (yych == 'e')
9896  {
9897  goto basic_json_parser_44;
9898  }
9899  }
9900 basic_json_parser_14:
9901  {
9902  last_token_type = token_type::value_number;
9903  break;
9904  }
9905 basic_json_parser_15:
9906  yyaccept = 1;
9907  m_marker = ++m_cursor;
9908  if ((m_limit - m_cursor) < 3)
9909  {
9910  fill_line_buffer(3); // LCOV_EXCL_LINE
9911  }
9912  yych = *m_cursor;
9913  if (yybm[0 + yych] & 64)
9914  {
9915  goto basic_json_parser_15;
9916  }
9917  if (yych <= 'D')
9918  {
9919  if (yych == '.')
9920  {
9921  goto basic_json_parser_43;
9922  }
9923  goto basic_json_parser_14;
9924  }
9925  else
9926  {
9927  if (yych <= 'E')
9928  {
9929  goto basic_json_parser_44;
9930  }
9931  if (yych == 'e')
9932  {
9933  goto basic_json_parser_44;
9934  }
9935  goto basic_json_parser_14;
9936  }
9937 basic_json_parser_17:
9938  ++m_cursor;
9939  {
9940  last_token_type = token_type::name_separator;
9941  break;
9942  }
9943 basic_json_parser_19:
9944  ++m_cursor;
9945  {
9946  last_token_type = token_type::begin_array;
9947  break;
9948  }
9949 basic_json_parser_21:
9950  ++m_cursor;
9951  {
9952  last_token_type = token_type::end_array;
9953  break;
9954  }
9955 basic_json_parser_23:
9956  yyaccept = 0;
9957  yych = *(m_marker = ++m_cursor);
9958  if (yych == 'a')
9959  {
9960  goto basic_json_parser_45;
9961  }
9962  goto basic_json_parser_5;
9963 basic_json_parser_24:
9964  yyaccept = 0;
9965  yych = *(m_marker = ++m_cursor);
9966  if (yych == 'u')
9967  {
9968  goto basic_json_parser_46;
9969  }
9970  goto basic_json_parser_5;
9971 basic_json_parser_25:
9972  yyaccept = 0;
9973  yych = *(m_marker = ++m_cursor);
9974  if (yych == 'r')
9975  {
9976  goto basic_json_parser_47;
9977  }
9978  goto basic_json_parser_5;
9979 basic_json_parser_26:
9980  ++m_cursor;
9981  {
9982  last_token_type = token_type::begin_object;
9983  break;
9984  }
9985 basic_json_parser_28:
9986  ++m_cursor;
9987  {
9988  last_token_type = token_type::end_object;
9989  break;
9990  }
9991 basic_json_parser_30:
9992  ++m_cursor;
9993  if (m_limit <= m_cursor)
9994  {
9995  fill_line_buffer(1); // LCOV_EXCL_LINE
9996  }
9997  yych = *m_cursor;
9998 basic_json_parser_31:
9999  if (yybm[0 + yych] & 128)
10000  {
10001  goto basic_json_parser_30;
10002  }
10003  if (yych <= 0xE0)
10004  {
10005  if (yych <= '\\')
10006  {
10007  if (yych <= 0x1F)
10008  {
10009  goto basic_json_parser_32;
10010  }
10011  if (yych <= '"')
10012  {
10013  goto basic_json_parser_33;
10014  }
10015  goto basic_json_parser_35;
10016  }
10017  else
10018  {
10019  if (yych <= 0xC1)
10020  {
10021  goto basic_json_parser_32;
10022  }
10023  if (yych <= 0xDF)
10024  {
10025  goto basic_json_parser_36;
10026  }
10027  goto basic_json_parser_37;
10028  }
10029  }
10030  else
10031  {
10032  if (yych <= 0xEF)
10033  {
10034  if (yych == 0xED)
10035  {
10036  goto basic_json_parser_39;
10037  }
10038  goto basic_json_parser_38;
10039  }
10040  else
10041  {
10042  if (yych <= 0xF0)
10043  {
10044  goto basic_json_parser_40;
10045  }
10046  if (yych <= 0xF3)
10047  {
10048  goto basic_json_parser_41;
10049  }
10050  if (yych <= 0xF4)
10051  {
10052  goto basic_json_parser_42;
10053  }
10054  }
10055  }
10056 basic_json_parser_32:
10057  m_cursor = m_marker;
10058  if (yyaccept == 0)
10059  {
10060  goto basic_json_parser_5;
10061  }
10062  else
10063  {
10064  goto basic_json_parser_14;
10065  }
10066 basic_json_parser_33:
10067  ++m_cursor;
10068  {
10069  last_token_type = token_type::value_string;
10070  break;
10071  }
10072 basic_json_parser_35:
10073  ++m_cursor;
10074  if (m_limit <= m_cursor)
10075  {
10076  fill_line_buffer(1); // LCOV_EXCL_LINE
10077  }
10078  yych = *m_cursor;
10079  if (yych <= 'e')
10080  {
10081  if (yych <= '/')
10082  {
10083  if (yych == '"')
10084  {
10085  goto basic_json_parser_30;
10086  }
10087  if (yych <= '.')
10088  {
10089  goto basic_json_parser_32;
10090  }
10091  goto basic_json_parser_30;
10092  }
10093  else
10094  {
10095  if (yych <= '\\')
10096  {
10097  if (yych <= '[')
10098  {
10099  goto basic_json_parser_32;
10100  }
10101  goto basic_json_parser_30;
10102  }
10103  else
10104  {
10105  if (yych == 'b')
10106  {
10107  goto basic_json_parser_30;
10108  }
10109  goto basic_json_parser_32;
10110  }
10111  }
10112  }
10113  else
10114  {
10115  if (yych <= 'q')
10116  {
10117  if (yych <= 'f')
10118  {
10119  goto basic_json_parser_30;
10120  }
10121  if (yych == 'n')
10122  {
10123  goto basic_json_parser_30;
10124  }
10125  goto basic_json_parser_32;
10126  }
10127  else
10128  {
10129  if (yych <= 's')
10130  {
10131  if (yych <= 'r')
10132  {
10133  goto basic_json_parser_30;
10134  }
10135  goto basic_json_parser_32;
10136  }
10137  else
10138  {
10139  if (yych <= 't')
10140  {
10141  goto basic_json_parser_30;
10142  }
10143  if (yych <= 'u')
10144  {
10145  goto basic_json_parser_48;
10146  }
10147  goto basic_json_parser_32;
10148  }
10149  }
10150  }
10151 basic_json_parser_36:
10152  ++m_cursor;
10153  if (m_limit <= m_cursor)
10154  {
10155  fill_line_buffer(1); // LCOV_EXCL_LINE
10156  }
10157  yych = *m_cursor;
10158  if (yych <= 0x7F)
10159  {
10160  goto basic_json_parser_32;
10161  }
10162  if (yych <= 0xBF)
10163  {
10164  goto basic_json_parser_30;
10165  }
10166  goto basic_json_parser_32;
10167 basic_json_parser_37:
10168  ++m_cursor;
10169  if (m_limit <= m_cursor)
10170  {
10171  fill_line_buffer(1); // LCOV_EXCL_LINE
10172  }
10173  yych = *m_cursor;
10174  if (yych <= 0x9F)
10175  {
10176  goto basic_json_parser_32;
10177  }
10178  if (yych <= 0xBF)
10179  {
10180  goto basic_json_parser_36;
10181  }
10182  goto basic_json_parser_32;
10183 basic_json_parser_38:
10184  ++m_cursor;
10185  if (m_limit <= m_cursor)
10186  {
10187  fill_line_buffer(1); // LCOV_EXCL_LINE
10188  }
10189  yych = *m_cursor;
10190  if (yych <= 0x7F)
10191  {
10192  goto basic_json_parser_32;
10193  }
10194  if (yych <= 0xBF)
10195  {
10196  goto basic_json_parser_36;
10197  }
10198  goto basic_json_parser_32;
10199 basic_json_parser_39:
10200  ++m_cursor;
10201  if (m_limit <= m_cursor)
10202  {
10203  fill_line_buffer(1); // LCOV_EXCL_LINE
10204  }
10205  yych = *m_cursor;
10206  if (yych <= 0x7F)
10207  {
10208  goto basic_json_parser_32;
10209  }
10210  if (yych <= 0x9F)
10211  {
10212  goto basic_json_parser_36;
10213  }
10214  goto basic_json_parser_32;
10215 basic_json_parser_40:
10216  ++m_cursor;
10217  if (m_limit <= m_cursor)
10218  {
10219  fill_line_buffer(1); // LCOV_EXCL_LINE
10220  }
10221  yych = *m_cursor;
10222  if (yych <= 0x8F)
10223  {
10224  goto basic_json_parser_32;
10225  }
10226  if (yych <= 0xBF)
10227  {
10228  goto basic_json_parser_38;
10229  }
10230  goto basic_json_parser_32;
10231 basic_json_parser_41:
10232  ++m_cursor;
10233  if (m_limit <= m_cursor)
10234  {
10235  fill_line_buffer(1); // LCOV_EXCL_LINE
10236  }
10237  yych = *m_cursor;
10238  if (yych <= 0x7F)
10239  {
10240  goto basic_json_parser_32;
10241  }
10242  if (yych <= 0xBF)
10243  {
10244  goto basic_json_parser_38;
10245  }
10246  goto basic_json_parser_32;
10247 basic_json_parser_42:
10248  ++m_cursor;
10249  if (m_limit <= m_cursor)
10250  {
10251  fill_line_buffer(1); // LCOV_EXCL_LINE
10252  }
10253  yych = *m_cursor;
10254  if (yych <= 0x7F)
10255  {
10256  goto basic_json_parser_32;
10257  }
10258  if (yych <= 0x8F)
10259  {
10260  goto basic_json_parser_38;
10261  }
10262  goto basic_json_parser_32;
10263 basic_json_parser_43:
10264  yych = *++m_cursor;
10265  if (yych <= '/')
10266  {
10267  goto basic_json_parser_32;
10268  }
10269  if (yych <= '9')
10270  {
10271  goto basic_json_parser_49;
10272  }
10273  goto basic_json_parser_32;
10274 basic_json_parser_44:
10275  yych = *++m_cursor;
10276  if (yych <= ',')
10277  {
10278  if (yych == '+')
10279  {
10280  goto basic_json_parser_51;
10281  }
10282  goto basic_json_parser_32;
10283  }
10284  else
10285  {
10286  if (yych <= '-')
10287  {
10288  goto basic_json_parser_51;
10289  }
10290  if (yych <= '/')
10291  {
10292  goto basic_json_parser_32;
10293  }
10294  if (yych <= '9')
10295  {
10296  goto basic_json_parser_52;
10297  }
10298  goto basic_json_parser_32;
10299  }
10300 basic_json_parser_45:
10301  yych = *++m_cursor;
10302  if (yych == 'l')
10303  {
10304  goto basic_json_parser_54;
10305  }
10306  goto basic_json_parser_32;
10307 basic_json_parser_46:
10308  yych = *++m_cursor;
10309  if (yych == 'l')
10310  {
10311  goto basic_json_parser_55;
10312  }
10313  goto basic_json_parser_32;
10314 basic_json_parser_47:
10315  yych = *++m_cursor;
10316  if (yych == 'u')
10317  {
10318  goto basic_json_parser_56;
10319  }
10320  goto basic_json_parser_32;
10321 basic_json_parser_48:
10322  ++m_cursor;
10323  if (m_limit <= m_cursor)
10324  {
10325  fill_line_buffer(1); // LCOV_EXCL_LINE
10326  }
10327  yych = *m_cursor;
10328  if (yych <= '@')
10329  {
10330  if (yych <= '/')
10331  {
10332  goto basic_json_parser_32;
10333  }
10334  if (yych <= '9')
10335  {
10336  goto basic_json_parser_57;
10337  }
10338  goto basic_json_parser_32;
10339  }
10340  else
10341  {
10342  if (yych <= 'F')
10343  {
10344  goto basic_json_parser_57;
10345  }
10346  if (yych <= '`')
10347  {
10348  goto basic_json_parser_32;
10349  }
10350  if (yych <= 'f')
10351  {
10352  goto basic_json_parser_57;
10353  }
10354  goto basic_json_parser_32;
10355  }
10356 basic_json_parser_49:
10357  yyaccept = 1;
10358  m_marker = ++m_cursor;
10359  if ((m_limit - m_cursor) < 3)
10360  {
10361  fill_line_buffer(3); // LCOV_EXCL_LINE
10362  }
10363  yych = *m_cursor;
10364  if (yych <= 'D')
10365  {
10366  if (yych <= '/')
10367  {
10368  goto basic_json_parser_14;
10369  }
10370  if (yych <= '9')
10371  {
10372  goto basic_json_parser_49;
10373  }
10374  goto basic_json_parser_14;
10375  }
10376  else
10377  {
10378  if (yych <= 'E')
10379  {
10380  goto basic_json_parser_44;
10381  }
10382  if (yych == 'e')
10383  {
10384  goto basic_json_parser_44;
10385  }
10386  goto basic_json_parser_14;
10387  }
10388 basic_json_parser_51:
10389  yych = *++m_cursor;
10390  if (yych <= '/')
10391  {
10392  goto basic_json_parser_32;
10393  }
10394  if (yych >= ':')
10395  {
10396  goto basic_json_parser_32;
10397  }
10398 basic_json_parser_52:
10399  ++m_cursor;
10400  if (m_limit <= m_cursor)
10401  {
10402  fill_line_buffer(1); // LCOV_EXCL_LINE
10403  }
10404  yych = *m_cursor;
10405  if (yych <= '/')
10406  {
10407  goto basic_json_parser_14;
10408  }
10409  if (yych <= '9')
10410  {
10411  goto basic_json_parser_52;
10412  }
10413  goto basic_json_parser_14;
10414 basic_json_parser_54:
10415  yych = *++m_cursor;
10416  if (yych == 's')
10417  {
10418  goto basic_json_parser_58;
10419  }
10420  goto basic_json_parser_32;
10421 basic_json_parser_55:
10422  yych = *++m_cursor;
10423  if (yych == 'l')
10424  {
10425  goto basic_json_parser_59;
10426  }
10427  goto basic_json_parser_32;
10428 basic_json_parser_56:
10429  yych = *++m_cursor;
10430  if (yych == 'e')
10431  {
10432  goto basic_json_parser_61;
10433  }
10434  goto basic_json_parser_32;
10435 basic_json_parser_57:
10436  ++m_cursor;
10437  if (m_limit <= m_cursor)
10438  {
10439  fill_line_buffer(1); // LCOV_EXCL_LINE
10440  }
10441  yych = *m_cursor;
10442  if (yych <= '@')
10443  {
10444  if (yych <= '/')
10445  {
10446  goto basic_json_parser_32;
10447  }
10448  if (yych <= '9')
10449  {
10450  goto basic_json_parser_63;
10451  }
10452  goto basic_json_parser_32;
10453  }
10454  else
10455  {
10456  if (yych <= 'F')
10457  {
10458  goto basic_json_parser_63;
10459  }
10460  if (yych <= '`')
10461  {
10462  goto basic_json_parser_32;
10463  }
10464  if (yych <= 'f')
10465  {
10466  goto basic_json_parser_63;
10467  }
10468  goto basic_json_parser_32;
10469  }
10470 basic_json_parser_58:
10471  yych = *++m_cursor;
10472  if (yych == 'e')
10473  {
10474  goto basic_json_parser_64;
10475  }
10476  goto basic_json_parser_32;
10477 basic_json_parser_59:
10478  ++m_cursor;
10479  {
10480  last_token_type = token_type::literal_null;
10481  break;
10482  }
10483 basic_json_parser_61:
10484  ++m_cursor;
10485  {
10486  last_token_type = token_type::literal_true;
10487  break;
10488  }
10489 basic_json_parser_63:
10490  ++m_cursor;
10491  if (m_limit <= m_cursor)
10492  {
10493  fill_line_buffer(1); // LCOV_EXCL_LINE
10494  }
10495  yych = *m_cursor;
10496  if (yych <= '@')
10497  {
10498  if (yych <= '/')
10499  {
10500  goto basic_json_parser_32;
10501  }
10502  if (yych <= '9')
10503  {
10504  goto basic_json_parser_66;
10505  }
10506  goto basic_json_parser_32;
10507  }
10508  else
10509  {
10510  if (yych <= 'F')
10511  {
10512  goto basic_json_parser_66;
10513  }
10514  if (yych <= '`')
10515  {
10516  goto basic_json_parser_32;
10517  }
10518  if (yych <= 'f')
10519  {
10520  goto basic_json_parser_66;
10521  }
10522  goto basic_json_parser_32;
10523  }
10524 basic_json_parser_64:
10525  ++m_cursor;
10526  {
10527  last_token_type = token_type::literal_false;
10528  break;
10529  }
10530 basic_json_parser_66:
10531  ++m_cursor;
10532  if (m_limit <= m_cursor)
10533  {
10534  fill_line_buffer(1); // LCOV_EXCL_LINE
10535  }
10536  yych = *m_cursor;
10537  if (yych <= '@')
10538  {
10539  if (yych <= '/')
10540  {
10541  goto basic_json_parser_32;
10542  }
10543  if (yych <= '9')
10544  {
10545  goto basic_json_parser_30;
10546  }
10547  goto basic_json_parser_32;
10548  }
10549  else
10550  {
10551  if (yych <= 'F')
10552  {
10553  goto basic_json_parser_30;
10554  }
10555  if (yych <= '`')
10556  {
10557  goto basic_json_parser_32;
10558  }
10559  if (yych <= 'f')
10560  {
10561  goto basic_json_parser_30;
10562  }
10563  goto basic_json_parser_32;
10564  }
10565  }
10566 
10567  }
10568 
10569  return last_token_type;
10570  }
10571 
10600  void fill_line_buffer(size_t n = 0)
10601  {
10602  // if line buffer is used, m_content points to its data
10603  assert(m_line_buffer.empty()
10604  or m_content == reinterpret_cast<const lexer_char_t*>(m_line_buffer.data()));
10605 
10606  // if line buffer is used, m_limit is set past the end of its data
10607  assert(m_line_buffer.empty()
10608  or m_limit == m_content + m_line_buffer.size());
10609 
10610  // pointer relationships
10611  assert(m_content <= m_start);
10612  assert(m_start <= m_cursor);
10613  assert(m_cursor <= m_limit);
10614  assert(m_marker == nullptr or m_marker <= m_limit);
10615 
10616  // number of processed characters (p)
10617  const auto num_processed_chars = static_cast<size_t>(m_start - m_content);
10618  // offset for m_marker wrt. to m_start
10619  const auto offset_marker = (m_marker == nullptr) ? 0 : m_marker - m_start;
10620  // number of unprocessed characters (u)
10621  const auto offset_cursor = m_cursor - m_start;
10622 
10623  // no stream is used or end of file is reached
10624  if (m_stream == nullptr or m_stream->eof())
10625  {
10626  // m_start may or may not be pointing into m_line_buffer at
10627  // this point. We trust the standand library to do the right
10628  // thing. See http://stackoverflow.com/q/28142011/266378
10629  m_line_buffer.assign(m_start, m_limit);
10630 
10631  // append n characters to make sure that there is sufficient
10632  // space between m_cursor and m_limit
10633  m_line_buffer.append(1, '\x00');
10634  if (n > 0)
10635  {
10636  m_line_buffer.append(n - 1, '\x01');
10637  }
10638  }
10639  else
10640  {
10641  // delete processed characters from line buffer
10642  m_line_buffer.erase(0, num_processed_chars);
10643  // read next line from input stream
10644  m_line_buffer_tmp.clear();
10645  std::getline(*m_stream, m_line_buffer_tmp, '\n');
10646 
10647  // add line with newline symbol to the line buffer
10648  m_line_buffer += m_line_buffer_tmp;
10649  m_line_buffer.push_back('\n');
10650  }
10651 
10652  // set pointers
10653  m_content = reinterpret_cast<const lexer_char_t*>(m_line_buffer.data());
10654  assert(m_content != nullptr);
10655  m_start = m_content;
10656  m_marker = m_start + offset_marker;
10657  m_cursor = m_start + offset_cursor;
10658  m_limit = m_start + m_line_buffer.size();
10659  }
10660 
10662  string_t get_token_string() const
10663  {
10664  assert(m_start != nullptr);
10665  return string_t(reinterpret_cast<typename string_t::const_pointer>(m_start),
10666  static_cast<size_t>(m_cursor - m_start));
10667  }
10668 
10726  string_t get_string() const
10727  {
10728  assert(m_cursor - m_start >= 2);
10729 
10730  string_t result;
10731  result.reserve(static_cast<size_t>(m_cursor - m_start - 2));
10732 
10733  // iterate the result between the quotes
10734  for (const lexer_char_t* i = m_start + 1; i < m_cursor - 1; ++i)
10735  {
10736  // find next escape character
10737  auto e = std::find(i, m_cursor - 1, '\\');
10738  if (e != i)
10739  {
10740  // see https://github.com/nlohmann/json/issues/365#issuecomment-262874705
10741  for (auto k = i; k < e; k++)
10742  {
10743  result.push_back(static_cast<typename string_t::value_type>(*k));
10744  }
10745  i = e - 1; // -1 because of ++i
10746  }
10747  else
10748  {
10749  // processing escaped character
10750  // read next character
10751  ++i;
10752 
10753  switch (*i)
10754  {
10755  // the default escapes
10756  case 't':
10757  {
10758  result += "\t";
10759  break;
10760  }
10761  case 'b':
10762  {
10763  result += "\b";
10764  break;
10765  }
10766  case 'f':
10767  {
10768  result += "\f";
10769  break;
10770  }
10771  case 'n':
10772  {
10773  result += "\n";
10774  break;
10775  }
10776  case 'r':
10777  {
10778  result += "\r";
10779  break;
10780  }
10781  case '\\':
10782  {
10783  result += "\\";
10784  break;
10785  }
10786  case '/':
10787  {
10788  result += "/";
10789  break;
10790  }
10791  case '"':
10792  {
10793  result += "\"";
10794  break;
10795  }
10796 
10797  // unicode
10798  case 'u':
10799  {
10800  // get code xxxx from uxxxx
10801  auto codepoint = std::strtoul(std::string(reinterpret_cast<typename string_t::const_pointer>(i + 1),
10802  4).c_str(), nullptr, 16);
10803 
10804  // check if codepoint is a high surrogate
10805  if (codepoint >= 0xD800 and codepoint <= 0xDBFF)
10806  {
10807  // make sure there is a subsequent unicode
10808  if ((i + 6 >= m_limit) or * (i + 5) != '\\' or * (i + 6) != 'u')
10809  {
10810  JSON_THROW(std::invalid_argument("missing low surrogate"));
10811  }
10812 
10813  // get code yyyy from uxxxx\uyyyy
10814  auto codepoint2 = std::strtoul(std::string(reinterpret_cast<typename string_t::const_pointer>
10815  (i + 7), 4).c_str(), nullptr, 16);
10816  result += to_unicode(codepoint, codepoint2);
10817  // skip the next 10 characters (xxxx\uyyyy)
10818  i += 10;
10819  }
10820  else if (codepoint >= 0xDC00 and codepoint <= 0xDFFF)
10821  {
10822  // we found a lone low surrogate
10823  JSON_THROW(std::invalid_argument("missing high surrogate"));
10824  }
10825  else
10826  {
10827  // add unicode character(s)
10828  result += to_unicode(codepoint);
10829  // skip the next four characters (xxxx)
10830  i += 4;
10831  }
10832  break;
10833  }
10834  }
10835  }
10836  }
10837 
10838  return result;
10839  }
10840 
10854  long double str_to_float_t(long double* /* type */, char** endptr) const
10855  {
10856  return std::strtold(reinterpret_cast<typename string_t::const_pointer>(m_start), endptr);
10857  }
10858 
10872  double str_to_float_t(double* /* type */, char** endptr) const
10873  {
10874  return std::strtod(reinterpret_cast<typename string_t::const_pointer>(m_start), endptr);
10875  }
10876 
10890  float str_to_float_t(float* /* type */, char** endptr) const
10891  {
10892  return std::strtof(reinterpret_cast<typename string_t::const_pointer>(m_start), endptr);
10893  }
10894 
10916  void get_number(basic_json& result) const
10917  {
10918  assert(m_start != nullptr);
10919 
10920  const lexer::lexer_char_t* curptr = m_start;
10921 
10922  // accumulate the integer conversion result (unsigned for now)
10923  number_unsigned_t value = 0;
10924 
10925  // maximum absolute value of the relevant integer type
10926  number_unsigned_t max;
10927 
10928  // temporarily store the type to avoid unecessary bitfield access
10929  value_t type;
10930 
10931  // look for sign
10932  if (*curptr == '-')
10933  {
10934  type = value_t::number_integer;
10935  max = static_cast<uint64_t>((std::numeric_limits<number_integer_t>::max)()) + 1;
10936  curptr++;
10937  }
10938  else
10939  {
10940  type = value_t::number_unsigned;
10941  max = static_cast<uint64_t>((std::numeric_limits<number_unsigned_t>::max)());
10942  }
10943 
10944  // count the significant figures
10945  for (; curptr < m_cursor; curptr++)
10946  {
10947  // quickly skip tests if a digit
10948  if (*curptr < '0' or* curptr > '9')
10949  {
10950  if (*curptr == '.')
10951  {
10952  // don't count '.' but change to float
10953  type = value_t::number_float;
10954  continue;
10955  }
10956  // assume exponent (if not then will fail parse): change to
10957  // float, stop counting and record exponent details
10958  type = value_t::number_float;
10959  break;
10960  }
10961 
10962  // skip if definitely not an integer
10963  if (type != value_t::number_float)
10964  {
10965  auto digit = static_cast<number_unsigned_t>(*curptr - '0');
10966 
10967  // overflow if value * 10 + digit > max, move terms around
10968  // to avoid overflow in intermediate values
10969  if (value > (max - digit) / 10)
10970  {
10971  // overflow
10972  type = value_t::number_float;
10973  }
10974  else
10975  {
10976  // no overflow
10977  value = value * 10 + digit;
10978  }
10979  }
10980  }
10981 
10982  // save the value (if not a float)
10983  if (type == value_t::number_unsigned)
10984  {
10985  result.m_value.number_unsigned = value;
10986  }
10987  else if (type == value_t::number_integer)
10988  {
10989  // invariant: if we parsed a '-', the absolute value is between
10990  // 0 (we allow -0) and max == -INT64_MIN
10991  assert(value >= 0);
10992  assert(value <= max);
10993 
10994  if (value == max)
10995  {
10996  // we cannot simply negate value (== max == -INT64_MIN),
10997  // see https://github.com/nlohmann/json/issues/389
10998  result.m_value.number_integer = static_cast<number_integer_t>(INT64_MIN);
10999  }
11000  else
11001  {
11002  // all other values can be negated safely
11003  result.m_value.number_integer = -static_cast<number_integer_t>(value);
11004  }
11005  }
11006  else
11007  {
11008  // parse with strtod
11009  result.m_value.number_float = str_to_float_t(static_cast<number_float_t*>(nullptr), nullptr);
11010 
11011  // replace infinity and NAN by null
11012  if (not std::isfinite(result.m_value.number_float))
11013  {
11014  type = value_t::null;
11015  result.m_value = basic_json::json_value();
11016  }
11017  }
11018 
11019  // save the type
11020  result.m_type = type;
11021  }
11022 
11023  private:
11025  std::istream* m_stream = nullptr;
11027  string_t m_line_buffer {};
11029  string_t m_line_buffer_tmp {};
11031  const lexer_char_t* m_content = nullptr;
11033  const lexer_char_t* m_start = nullptr;
11035  const lexer_char_t* m_marker = nullptr;
11037  const lexer_char_t* m_cursor = nullptr;
11039  const lexer_char_t* m_limit = nullptr;
11041  token_type last_token_type = token_type::end_of_input;
11042  };
11043 
11049  class parser
11050  {
11051  public:
11053  parser(const char* buff, const parser_callback_t cb = nullptr)
11054  : callback(cb),
11055  m_lexer(reinterpret_cast<const typename lexer::lexer_char_t*>(buff), std::strlen(buff))
11056  {}
11057 
11059  parser(std::istream& is, const parser_callback_t cb = nullptr)
11060  : callback(cb), m_lexer(is)
11061  {}
11062 
11064  template<class IteratorType, typename std::enable_if<
11065  std::is_same<typename std::iterator_traits<IteratorType>::iterator_category, std::random_access_iterator_tag>::value
11066  , int>::type
11067  = 0>
11068  parser(IteratorType first, IteratorType last, const parser_callback_t cb = nullptr)
11069  : callback(cb),
11070  m_lexer(reinterpret_cast<const typename lexer::lexer_char_t*>(&(*first)),
11071  static_cast<size_t>(std::distance(first, last)))
11072  {}
11073 
11075  basic_json parse()
11076  {
11077  // read first token
11078  get_token();
11079 
11080  basic_json result = parse_internal(true);
11081  result.assert_invariant();
11082 
11083  expect(lexer::token_type::end_of_input);
11084 
11085  // return parser result and replace it with null in case the
11086  // top-level value was discarded by the callback function
11087  return result.is_discarded() ? basic_json() : std::move(result);
11088  }
11089 
11090  private:
11092  basic_json parse_internal(bool keep)
11093  {
11094  auto result = basic_json(value_t::discarded);
11095 
11096  switch (last_token)
11097  {
11098  case lexer::token_type::begin_object:
11099  {
11100  if (keep and (not callback
11101  or ((keep = callback(depth++, parse_event_t::object_start, result)) != 0)))
11102  {
11103  // explicitly set result to object to cope with {}
11104  result.m_type = value_t::object;
11105  result.m_value = value_t::object;
11106  }
11107 
11108  // read next token
11109  get_token();
11110 
11111  // closing } -> we are done
11112  if (last_token == lexer::token_type::end_object)
11113  {
11114  get_token();
11115  if (keep and callback and not callback(--depth, parse_event_t::object_end, result))
11116  {
11117  result = basic_json(value_t::discarded);
11118  }
11119  return result;
11120  }
11121 
11122  // no comma is expected here
11123  unexpect(lexer::token_type::value_separator);
11124 
11125  // otherwise: parse key-value pairs
11126  do
11127  {
11128  // ugly, but could be fixed with loop reorganization
11129  if (last_token == lexer::token_type::value_separator)
11130  {
11131  get_token();
11132  }
11133 
11134  // store key
11135  expect(lexer::token_type::value_string);
11136  const auto key = m_lexer.get_string();
11137 
11138  bool keep_tag = false;
11139  if (keep)
11140  {
11141  if (callback)
11142  {
11143  basic_json k(key);
11144  keep_tag = callback(depth, parse_event_t::key, k);
11145  }
11146  else
11147  {
11148  keep_tag = true;
11149  }
11150  }
11151 
11152  // parse separator (:)
11153  get_token();
11154  expect(lexer::token_type::name_separator);
11155 
11156  // parse and add value
11157  get_token();
11158  auto value = parse_internal(keep);
11159  if (keep and keep_tag and not value.is_discarded())
11160  {
11161  result[key] = std::move(value);
11162  }
11163  }
11164  while (last_token == lexer::token_type::value_separator);
11165 
11166  // closing }
11167  expect(lexer::token_type::end_object);
11168  get_token();
11169  if (keep and callback and not callback(--depth, parse_event_t::object_end, result))
11170  {
11171  result = basic_json(value_t::discarded);
11172  }
11173 
11174  return result;
11175  }
11176 
11177  case lexer::token_type::begin_array:
11178  {
11179  if (keep and (not callback
11180  or ((keep = callback(depth++, parse_event_t::array_start, result)) != 0)))
11181  {
11182  // explicitly set result to object to cope with []
11183  result.m_type = value_t::array;
11184  result.m_value = value_t::array;
11185  }
11186 
11187  // read next token
11188  get_token();
11189 
11190  // closing ] -> we are done
11191  if (last_token == lexer::token_type::end_array)
11192  {
11193  get_token();
11194  if (callback and not callback(--depth, parse_event_t::array_end, result))
11195  {
11196  result = basic_json(value_t::discarded);
11197  }
11198  return result;
11199  }
11200 
11201  // no comma is expected here
11202  unexpect(lexer::token_type::value_separator);
11203 
11204  // otherwise: parse values
11205  do
11206  {
11207  // ugly, but could be fixed with loop reorganization
11208  if (last_token == lexer::token_type::value_separator)
11209  {
11210  get_token();
11211  }
11212 
11213  // parse value
11214  auto value = parse_internal(keep);
11215  if (keep and not value.is_discarded())
11216  {
11217  result.push_back(std::move(value));
11218  }
11219  }
11220  while (last_token == lexer::token_type::value_separator);
11221 
11222  // closing ]
11223  expect(lexer::token_type::end_array);
11224  get_token();
11225  if (keep and callback and not callback(--depth, parse_event_t::array_end, result))
11226  {
11227  result = basic_json(value_t::discarded);
11228  }
11229 
11230  return result;
11231  }
11232 
11233  case lexer::token_type::literal_null:
11234  {
11235  get_token();
11236  result.m_type = value_t::null;
11237  break;
11238  }
11239 
11240  case lexer::token_type::value_string:
11241  {
11242  const auto s = m_lexer.get_string();
11243  get_token();
11244  result = basic_json(s);
11245  break;
11246  }
11247 
11248  case lexer::token_type::literal_true:
11249  {
11250  get_token();
11251  result.m_type = value_t::boolean;
11252  result.m_value = true;
11253  break;
11254  }
11255 
11256  case lexer::token_type::literal_false:
11257  {
11258  get_token();
11259  result.m_type = value_t::boolean;
11260  result.m_value = false;
11261  break;
11262  }
11263 
11264  case lexer::token_type::value_number:
11265  {
11266  m_lexer.get_number(result);
11267  get_token();
11268  break;
11269  }
11270 
11271  default:
11272  {
11273  // the last token was unexpected
11274  unexpect(last_token);
11275  }
11276  }
11277 
11278  if (keep and callback and not callback(depth, parse_event_t::value, result))
11279  {
11280  result = basic_json(value_t::discarded);
11281  }
11282  return result;
11283  }
11284 
11286  typename lexer::token_type get_token()
11287  {
11288  last_token = m_lexer.scan();
11289  return last_token;
11290  }
11291 
11292  void expect(typename lexer::token_type t) const
11293  {
11294  if (t != last_token)
11295  {
11296  std::string error_msg = "parse error - unexpected ";
11297  error_msg += (last_token == lexer::token_type::parse_error ? ("'" + m_lexer.get_token_string() +
11298  "'") :
11299  lexer::token_type_name(last_token));
11300  error_msg += "; expected " + lexer::token_type_name(t);
11301  JSON_THROW(std::invalid_argument(error_msg));
11302  }
11303  }
11304 
11305  void unexpect(typename lexer::token_type t) const
11306  {
11307  if (t == last_token)
11308  {
11309  std::string error_msg = "parse error - unexpected ";
11310  error_msg += (last_token == lexer::token_type::parse_error ? ("'" + m_lexer.get_token_string() +
11311  "'") :
11312  lexer::token_type_name(last_token));
11313  JSON_THROW(std::invalid_argument(error_msg));
11314  }
11315  }
11316 
11317  private:
11319  int depth = 0;
11321  const parser_callback_t callback = nullptr;
11323  typename lexer::token_type last_token = lexer::token_type::uninitialized;
11325  lexer m_lexer;
11326  };
11327 
11328  public:
11341  {
11343  friend class basic_json;
11344 
11345  public:
11368  explicit json_pointer(const std::string& s = "")
11369  : reference_tokens(split(s))
11370  {}
11371 
11387  std::string to_string() const noexcept
11388  {
11389  return std::accumulate(reference_tokens.begin(),
11390  reference_tokens.end(), std::string{},
11391  [](const std::string & a, const std::string & b)
11392  {
11393  return a + "/" + escape(b);
11394  });
11395  }
11396 
11398  operator std::string() const
11399  {
11400  return to_string();
11401  }
11403  private:
11405  std::string pop_back()
11406  {
11407  if (is_root())
11408  {
11409  JSON_THROW(std::domain_error("JSON pointer has no parent"));
11410  }
11411 
11412  auto last = reference_tokens.back();
11413  reference_tokens.pop_back();
11414  return last;
11415  }
11416 
11418  bool is_root() const
11419  {
11420  return reference_tokens.empty();
11421  }
11422 
11423  json_pointer top() const
11424  {
11425  if (is_root())
11426  {
11427  JSON_THROW(std::domain_error("JSON pointer has no parent"));
11428  }
11429 
11430  json_pointer result = *this;
11431  result.reference_tokens = {reference_tokens[0]};
11432  return result;
11433  }
11434 
11440  reference get_and_create(reference j) const
11441  {
11442  pointer result = &j;
11443 
11444  // in case no reference tokens exist, return a reference to the
11445  // JSON value j which will be overwritten by a primitive value
11446  for (const auto& reference_token : reference_tokens)
11447  {
11448  switch (result->m_type)
11449  {
11450  case value_t::null:
11451  {
11452  if (reference_token == "0")
11453  {
11454  // start a new array if reference token is 0
11455  result = &result->operator[](0);
11456  }
11457  else
11458  {
11459  // start a new object otherwise
11460  result = &result->operator[](reference_token);
11461  }
11462  break;
11463  }
11464 
11465  case value_t::object:
11466  {
11467  // create an entry in the object
11468  result = &result->operator[](reference_token);
11469  break;
11470  }
11471 
11472  case value_t::array:
11473  {
11474  // create an entry in the array
11475  result = &result->operator[](static_cast<size_type>(std::stoi(reference_token)));
11476  break;
11477  }
11478 
11479  /*
11480  The following code is only reached if there exists a
11481  reference token _and_ the current value is primitive. In
11482  this case, we have an error situation, because primitive
11483  values may only occur as single value; that is, with an
11484  empty list of reference tokens.
11485  */
11486  default:
11487  {
11488  JSON_THROW(std::domain_error("invalid value to unflatten"));
11489  }
11490  }
11491  }
11492 
11493  return *result;
11494  }
11495 
11515  reference get_unchecked(pointer ptr) const
11516  {
11517  for (const auto& reference_token : reference_tokens)
11518  {
11519  // convert null values to arrays or objects before continuing
11520  if (ptr->m_type == value_t::null)
11521  {
11522  // check if reference token is a number
11523  const bool nums = std::all_of(reference_token.begin(),
11524  reference_token.end(),
11525  [](const char x)
11526  {
11527  return std::isdigit(x);
11528  });
11529 
11530  // change value to array for numbers or "-" or to object
11531  // otherwise
11532  if (nums or reference_token == "-")
11533  {
11534  *ptr = value_t::array;
11535  }
11536  else
11537  {
11538  *ptr = value_t::object;
11539  }
11540  }
11541 
11542  switch (ptr->m_type)
11543  {
11544  case value_t::object:
11545  {
11546  // use unchecked object access
11547  ptr = &ptr->operator[](reference_token);
11548  break;
11549  }
11550 
11551  case value_t::array:
11552  {
11553  // error condition (cf. RFC 6901, Sect. 4)
11554  if (reference_token.size() > 1 and reference_token[0] == '0')
11555  {
11556  JSON_THROW(std::domain_error("array index must not begin with '0'"));
11557  }
11558 
11559  if (reference_token == "-")
11560  {
11561  // explicityly treat "-" as index beyond the end
11562  ptr = &ptr->operator[](ptr->m_value.array->size());
11563  }
11564  else
11565  {
11566  // convert array index to number; unchecked access
11567  ptr = &ptr->operator[](static_cast<size_type>(std::stoi(reference_token)));
11568  }
11569  break;
11570  }
11571 
11572  default:
11573  {
11574  JSON_THROW(std::out_of_range("unresolved reference token '" + reference_token + "'"));
11575  }
11576  }
11577  }
11578 
11579  return *ptr;
11580  }
11581 
11582  reference get_checked(pointer ptr) const
11583  {
11584  for (const auto& reference_token : reference_tokens)
11585  {
11586  switch (ptr->m_type)
11587  {
11588  case value_t::object:
11589  {
11590  // note: at performs range check
11591  ptr = &ptr->at(reference_token);
11592  break;
11593  }
11594 
11595  case value_t::array:
11596  {
11597  if (reference_token == "-")
11598  {
11599  // "-" always fails the range check
11600  throw std::out_of_range("array index '-' (" +
11601  std::to_string(ptr->m_value.array->size()) +
11602  ") is out of range");
11603  }
11604 
11605  // error condition (cf. RFC 6901, Sect. 4)
11606  if (reference_token.size() > 1 and reference_token[0] == '0')
11607  {
11608  JSON_THROW(std::domain_error("array index must not begin with '0'"));
11609  }
11610 
11611  // note: at performs range check
11612  ptr = &ptr->at(static_cast<size_type>(std::stoi(reference_token)));
11613  break;
11614  }
11615 
11616  default:
11617  {
11618  JSON_THROW(std::out_of_range("unresolved reference token '" + reference_token + "'"));
11619  }
11620  }
11621  }
11622 
11623  return *ptr;
11624  }
11625 
11634  const_reference get_unchecked(const_pointer ptr) const
11635  {
11636  for (const auto& reference_token : reference_tokens)
11637  {
11638  switch (ptr->m_type)
11639  {
11640  case value_t::object:
11641  {
11642  // use unchecked object access
11643  ptr = &ptr->operator[](reference_token);
11644  break;
11645  }
11646 
11647  case value_t::array:
11648  {
11649  if (reference_token == "-")
11650  {
11651  // "-" cannot be used for const access
11652  throw std::out_of_range("array index '-' (" +
11653  std::to_string(ptr->m_value.array->size()) +
11654  ") is out of range");
11655  }
11656 
11657  // error condition (cf. RFC 6901, Sect. 4)
11658  if (reference_token.size() > 1 and reference_token[0] == '0')
11659  {
11660  JSON_THROW(std::domain_error("array index must not begin with '0'"));
11661  }
11662 
11663  // use unchecked array access
11664  ptr = &ptr->operator[](static_cast<size_type>(std::stoi(reference_token)));
11665  break;
11666  }
11667 
11668  default:
11669  {
11670  JSON_THROW(std::out_of_range("unresolved reference token '" + reference_token + "'"));
11671  }
11672  }
11673  }
11674 
11675  return *ptr;
11676  }
11677 
11678  const_reference get_checked(const_pointer ptr) const
11679  {
11680  for (const auto& reference_token : reference_tokens)
11681  {
11682  switch (ptr->m_type)
11683  {
11684  case value_t::object:
11685  {
11686  // note: at performs range check
11687  ptr = &ptr->at(reference_token);
11688  break;
11689  }
11690 
11691  case value_t::array:
11692  {
11693  if (reference_token == "-")
11694  {
11695  // "-" always fails the range check
11696  throw std::out_of_range("array index '-' (" +
11697  std::to_string(ptr->m_value.array->size()) +
11698  ") is out of range");
11699  }
11700 
11701  // error condition (cf. RFC 6901, Sect. 4)
11702  if (reference_token.size() > 1 and reference_token[0] == '0')
11703  {
11704  JSON_THROW(std::domain_error("array index must not begin with '0'"));
11705  }
11706 
11707  // note: at performs range check
11708  ptr = &ptr->at(static_cast<size_type>(std::stoi(reference_token)));
11709  break;
11710  }
11711 
11712  default:
11713  {
11714  JSON_THROW(std::out_of_range("unresolved reference token '" + reference_token + "'"));
11715  }
11716  }
11717  }
11718 
11719  return *ptr;
11720  }
11721 
11723  static std::vector<std::string> split(const std::string& reference_string)
11724  {
11725  std::vector<std::string> result;
11726 
11727  // special case: empty reference string -> no reference tokens
11728  if (reference_string.empty())
11729  {
11730  return result;
11731  }
11732 
11733  // check if nonempty reference string begins with slash
11734  if (reference_string[0] != '/')
11735  {
11736  JSON_THROW(std::domain_error("JSON pointer must be empty or begin with '/'"));
11737  }
11738 
11739  // extract the reference tokens:
11740  // - slash: position of the last read slash (or end of string)
11741  // - start: position after the previous slash
11742  for (
11743  // search for the first slash after the first character
11744  size_t slash = reference_string.find_first_of('/', 1),
11745  // set the beginning of the first reference token
11746  start = 1;
11747  // we can stop if start == string::npos+1 = 0
11748  start != 0;
11749  // set the beginning of the next reference token
11750  // (will eventually be 0 if slash == std::string::npos)
11751  start = slash + 1,
11752  // find next slash
11753  slash = reference_string.find_first_of('/', start))
11754  {
11755  // use the text between the beginning of the reference token
11756  // (start) and the last slash (slash).
11757  auto reference_token = reference_string.substr(start, slash - start);
11758 
11759  // check reference tokens are properly escaped
11760  for (size_t pos = reference_token.find_first_of('~');
11761  pos != std::string::npos;
11762  pos = reference_token.find_first_of('~', pos + 1))
11763  {
11764  assert(reference_token[pos] == '~');
11765 
11766  // ~ must be followed by 0 or 1
11767  if (pos == reference_token.size() - 1 or
11768  (reference_token[pos + 1] != '0' and
11769  reference_token[pos + 1] != '1'))
11770  {
11771  JSON_THROW(std::domain_error("escape error: '~' must be followed with '0' or '1'"));
11772  }
11773  }
11774 
11775  // finally, store the reference token
11776  unescape(reference_token);
11777  result.push_back(reference_token);
11778  }
11779 
11780  return result;
11781  }
11782 
11783  private:
11796  static void replace_substring(std::string& s,
11797  const std::string& f,
11798  const std::string& t)
11799  {
11800  assert(not f.empty());
11801 
11802  for (
11803  size_t pos = s.find(f); // find first occurrence of f
11804  pos != std::string::npos; // make sure f was found
11805  s.replace(pos, f.size(), t), // replace with t
11806  pos = s.find(f, pos + t.size()) // find next occurrence of f
11807  );
11808  }
11809 
11811  static std::string escape(std::string s)
11812  {
11813  // escape "~"" to "~0" and "/" to "~1"
11814  replace_substring(s, "~", "~0");
11815  replace_substring(s, "/", "~1");
11816  return s;
11817  }
11818 
11820  static void unescape(std::string& s)
11821  {
11822  // first transform any occurrence of the sequence '~1' to '/'
11823  replace_substring(s, "~1", "/");
11824  // then transform any occurrence of the sequence '~0' to '~'
11825  replace_substring(s, "~0", "~");
11826  }
11827 
11835  static void flatten(const std::string& reference_string,
11836  const basic_json& value,
11837  basic_json& result)
11838  {
11839  switch (value.m_type)
11840  {
11841  case value_t::array:
11842  {
11843  if (value.m_value.array->empty())
11844  {
11845  // flatten empty array as null
11846  result[reference_string] = nullptr;
11847  }
11848  else
11849  {
11850  // iterate array and use index as reference string
11851  for (size_t i = 0; i < value.m_value.array->size(); ++i)
11852  {
11853  flatten(reference_string + "/" + std::to_string(i),
11854  value.m_value.array->operator[](i), result);
11855  }
11856  }
11857  break;
11858  }
11859 
11860  case value_t::object:
11861  {
11862  if (value.m_value.object->empty())
11863  {
11864  // flatten empty object as null
11865  result[reference_string] = nullptr;
11866  }
11867  else
11868  {
11869  // iterate object and use keys as reference string
11870  for (const auto& element : *value.m_value.object)
11871  {
11872  flatten(reference_string + "/" + escape(element.first),
11873  element.second, result);
11874  }
11875  }
11876  break;
11877  }
11878 
11879  default:
11880  {
11881  // add primitive value with its reference string
11882  result[reference_string] = value;
11883  break;
11884  }
11885  }
11886  }
11887 
11893  static basic_json unflatten(const basic_json& value)
11894  {
11895  if (not value.is_object())
11896  {
11897  JSON_THROW(std::domain_error("only objects can be unflattened"));
11898  }
11899 
11900  basic_json result;
11901 
11902  // iterate the JSON object values
11903  for (const auto& element : *value.m_value.object)
11904  {
11905  if (not element.second.is_primitive())
11906  {
11907  JSON_THROW(std::domain_error("values in object must be primitive"));
11908  }
11909 
11910  // assign value to reference pointed to by JSON pointer; Note
11911  // that if the JSON pointer is "" (i.e., points to the whole
11912  // value), function get_and_create returns a reference to
11913  // result itself. An assignment will then create a primitive
11914  // value.
11915  json_pointer(element.first).get_and_create(result) = element.second;
11916  }
11917 
11918  return result;
11919  }
11920 
11921  private:
11922  friend bool operator==(json_pointer const& lhs,
11923  json_pointer const& rhs) noexcept
11924  {
11925  return lhs.reference_tokens == rhs.reference_tokens;
11926  }
11927 
11928  friend bool operator!=(json_pointer const& lhs,
11929  json_pointer const& rhs) noexcept
11930  {
11931  return !(lhs == rhs);
11932  }
11933 
11935  std::vector<std::string> reference_tokens {};
11936  };
11937 
11939  // JSON Pointer support //
11941 
11944 
11978  reference operator[](const json_pointer& ptr)
11979  {
11980  return ptr.get_unchecked(this);
11981  }
12005  const_reference operator[](const json_pointer& ptr) const
12006  {
12007  return ptr.get_unchecked(this);
12008  }
12030  reference at(const json_pointer& ptr)
12031  {
12032  return ptr.get_checked(this);
12033  }
12055  const_reference at(const json_pointer& ptr) const
12056  {
12057  return ptr.get_checked(this);
12058  }
12082  basic_json flatten() const
12083  {
12084  basic_json result(value_t::object);
12085  json_pointer::flatten("", *this, result);
12086  return result;
12087  }
12088 
12116  basic_json unflatten() const
12117  {
12118  return json_pointer::unflatten(*this);
12119  }
12122 
12124  // JSON Patch functions //
12126 
12129 
12166  basic_json patch(const basic_json& json_patch) const
12167  {
12168  // make a working copy to apply the patch to
12169  basic_json result = *this;
12171  // the valid JSON Patch operations
12172  enum class patch_operations {add, remove, replace, move, copy, test, invalid};
12173 
12174  const auto get_op = [](const std::string op)
12175  {
12176  if (op == "add")
12177  {
12178  return patch_operations::add;
12179  }
12180  if (op == "remove")
12181  {
12182  return patch_operations::remove;
12183  }
12184  if (op == "replace")
12185  {
12186  return patch_operations::replace;
12187  }
12188  if (op == "move")
12189  {
12190  return patch_operations::move;
12191  }
12192  if (op == "copy")
12193  {
12194  return patch_operations::copy;
12195  }
12196  if (op == "test")
12197  {
12198  return patch_operations::test;
12199  }
12200 
12201  return patch_operations::invalid;
12202  };
12203 
12204  // wrapper for "add" operation; add value at ptr
12205  const auto operation_add = [&result](json_pointer & ptr, basic_json val)
12206  {
12207  // adding to the root of the target document means replacing it
12208  if (ptr.is_root())
12209  {
12210  result = val;
12211  }
12212  else
12213  {
12214  // make sure the top element of the pointer exists
12215  json_pointer top_pointer = ptr.top();
12216  if (top_pointer != ptr)
12217  {
12218  result.at(top_pointer);
12219  }
12220 
12221  // get reference to parent of JSON pointer ptr
12222  const auto last_path = ptr.pop_back();
12223  basic_json& parent = result[ptr];
12224 
12225  switch (parent.m_type)
12226  {
12227  case value_t::null:
12228  case value_t::object:
12229  {
12230  // use operator[] to add value
12231  parent[last_path] = val;
12232  break;
12233  }
12234 
12235  case value_t::array:
12236  {
12237  if (last_path == "-")
12238  {
12239  // special case: append to back
12240  parent.push_back(val);
12241  }
12242  else
12243  {
12244  const auto idx = std::stoi(last_path);
12245  if (static_cast<size_type>(idx) > parent.size())
12246  {
12247  // avoid undefined behavior
12248  JSON_THROW(std::out_of_range("array index " + std::to_string(idx) + " is out of range"));
12249  }
12250  else
12251  {
12252  // default case: insert add offset
12253  parent.insert(parent.begin() + static_cast<difference_type>(idx), val);
12254  }
12255  }
12256  break;
12257  }
12258 
12259  default:
12260  {
12261  // if there exists a parent it cannot be primitive
12262  assert(false); // LCOV_EXCL_LINE
12263  }
12264  }
12265  }
12266  };
12267 
12268  // wrapper for "remove" operation; remove value at ptr
12269  const auto operation_remove = [&result](json_pointer & ptr)
12270  {
12271  // get reference to parent of JSON pointer ptr
12272  const auto last_path = ptr.pop_back();
12273  basic_json& parent = result.at(ptr);
12274 
12275  // remove child
12276  if (parent.is_object())
12277  {
12278  // perform range check
12279  auto it = parent.find(last_path);
12280  if (it != parent.end())
12281  {
12282  parent.erase(it);
12283  }
12284  else
12285  {
12286  JSON_THROW(std::out_of_range("key '" + last_path + "' not found"));
12287  }
12288  }
12289  else if (parent.is_array())
12290  {
12291  // note erase performs range check
12292  parent.erase(static_cast<size_type>(std::stoi(last_path)));
12293  }
12294  };
12295 
12296  // type check
12297  if (not json_patch.is_array())
12298  {
12299  // a JSON patch must be an array of objects
12300  JSON_THROW(std::invalid_argument("JSON patch must be an array of objects"));
12301  }
12302 
12303  // iterate and apply th eoperations
12304  for (const auto& val : json_patch)
12305  {
12306  // wrapper to get a value for an operation
12307  const auto get_value = [&val](const std::string & op,
12308  const std::string & member,
12309  bool string_type) -> basic_json&
12310  {
12311  // find value
12312  auto it = val.m_value.object->find(member);
12313 
12314  // context-sensitive error message
12315  const auto error_msg = (op == "op") ? "operation" : "operation '" + op + "'";
12316 
12317  // check if desired value is present
12318  if (it == val.m_value.object->end())
12319  {
12320  JSON_THROW(std::invalid_argument(error_msg + " must have member '" + member + "'"));
12321  }
12322 
12323  // check if result is of type string
12324  if (string_type and not it->second.is_string())
12325  {
12326  JSON_THROW(std::invalid_argument(error_msg + " must have string member '" + member + "'"));
12327  }
12328 
12329  // no error: return value
12330  return it->second;
12331  };
12332 
12333  // type check
12334  if (not val.is_object())
12335  {
12336  JSON_THROW(std::invalid_argument("JSON patch must be an array of objects"));
12337  }
12338 
12339  // collect mandatory members
12340  const std::string op = get_value("op", "op", true);
12341  const std::string path = get_value(op, "path", true);
12342  json_pointer ptr(path);
12343 
12344  switch (get_op(op))
12345  {
12346  case patch_operations::add:
12347  {
12348  operation_add(ptr, get_value("add", "value", false));
12349  break;
12350  }
12351 
12352  case patch_operations::remove:
12353  {
12354  operation_remove(ptr);
12355  break;
12356  }
12357 
12358  case patch_operations::replace:
12359  {
12360  // the "path" location must exist - use at()
12361  result.at(ptr) = get_value("replace", "value", false);
12362  break;
12363  }
12364 
12365  case patch_operations::move:
12366  {
12367  const std::string from_path = get_value("move", "from", true);
12368  json_pointer from_ptr(from_path);
12369 
12370  // the "from" location must exist - use at()
12371  basic_json v = result.at(from_ptr);
12372 
12373  // The move operation is functionally identical to a
12374  // "remove" operation on the "from" location, followed
12375  // immediately by an "add" operation at the target
12376  // location with the value that was just removed.
12377  operation_remove(from_ptr);
12378  operation_add(ptr, v);
12379  break;
12380  }
12381 
12382  case patch_operations::copy:
12383  {
12384  const std::string from_path = get_value("copy", "from", true);;
12385  const json_pointer from_ptr(from_path);
12386 
12387  // the "from" location must exist - use at()
12388  result[ptr] = result.at(from_ptr);
12389  break;
12390  }
12391 
12392  case patch_operations::test:
12393  {
12394  bool success = false;
12395  JSON_TRY
12396  {
12397  // check if "value" matches the one at "path"
12398  // the "path" location must exist - use at()
12399  success = (result.at(ptr) == get_value("test", "value", false));
12400  }
12401  JSON_CATCH (std::out_of_range&)
12402  {
12403  // ignore out of range errors: success remains false
12404  }
12405 
12406  // throw an exception if test fails
12407  if (not success)
12408  {
12409  JSON_THROW(std::domain_error("unsuccessful: " + val.dump()));
12410  }
12411 
12412  break;
12413  }
12414 
12415  case patch_operations::invalid:
12416  {
12417  // op must be "add", "remove", "replace", "move", "copy", or
12418  // "test"
12419  JSON_THROW(std::invalid_argument("operation value '" + op + "' is invalid"));
12420  }
12421  }
12422  }
12423 
12424  return result;
12425  }
12426 
12459  static basic_json diff(const basic_json& source,
12460  const basic_json& target,
12461  const std::string& path = "")
12462  {
12463  // the patch
12464  basic_json result(value_t::array);
12465 
12466  // if the values are the same, return empty patch
12467  if (source == target)
12468  {
12469  return result;
12470  }
12471 
12472  if (source.type() != target.type())
12473  {
12474  // different types: replace value
12475  result.push_back(
12476  {
12477  {"op", "replace"},
12478  {"path", path},
12479  {"value", target}
12480  });
12481  }
12482  else
12483  {
12484  switch (source.type())
12485  {
12486  case value_t::array:
12487  {
12488  // first pass: traverse common elements
12489  size_t i = 0;
12490  while (i < source.size() and i < target.size())
12491  {
12492  // recursive call to compare array values at index i
12493  auto temp_diff = diff(source[i], target[i], path + "/" + std::to_string(i));
12494  result.insert(result.end(), temp_diff.begin(), temp_diff.end());
12495  ++i;
12496  }
12497 
12498  // i now reached the end of at least one array
12499  // in a second pass, traverse the remaining elements
12500 
12501  // remove my remaining elements
12502  const auto end_index = static_cast<difference_type>(result.size());
12503  while (i < source.size())
12504  {
12505  // add operations in reverse order to avoid invalid
12506  // indices
12507  result.insert(result.begin() + end_index, object(
12508  {
12509  {"op", "remove"},
12510  {"path", path + "/" + std::to_string(i)}
12511  }));
12512  ++i;
12513  }
12514 
12515  // add other remaining elements
12516  while (i < target.size())
12517  {
12518  result.push_back(
12519  {
12520  {"op", "add"},
12521  {"path", path + "/" + std::to_string(i)},
12522  {"value", target[i]}
12523  });
12524  ++i;
12525  }
12526 
12527  break;
12528  }
12529 
12530  case value_t::object:
12531  {
12532  // first pass: traverse this object's elements
12533  for (auto it = source.begin(); it != source.end(); ++it)
12534  {
12535  // escape the key name to be used in a JSON patch
12536  const auto key = json_pointer::escape(it.key());
12537 
12538  if (target.find(it.key()) != target.end())
12539  {
12540  // recursive call to compare object values at key it
12541  auto temp_diff = diff(it.value(), target[it.key()], path + "/" + key);
12542  result.insert(result.end(), temp_diff.begin(), temp_diff.end());
12543  }
12544  else
12545  {
12546  // found a key that is not in o -> remove it
12547  result.push_back(object(
12548  {
12549  {"op", "remove"},
12550  {"path", path + "/" + key}
12551  }));
12552  }
12553  }
12554 
12555  // second pass: traverse other object's elements
12556  for (auto it = target.begin(); it != target.end(); ++it)
12557  {
12558  if (source.find(it.key()) == source.end())
12559  {
12560  // found a key that is not in this -> add it
12561  const auto key = json_pointer::escape(it.key());
12562  result.push_back(
12563  {
12564  {"op", "add"},
12565  {"path", path + "/" + key},
12566  {"value", it.value()}
12567  });
12568  }
12569  }
12570 
12571  break;
12572  }
12573 
12574  default:
12575  {
12576  // both primitive type: replace value
12577  result.push_back(
12578  {
12579  {"op", "replace"},
12580  {"path", path},
12581  {"value", target}
12582  });
12583  break;
12584  }
12585  }
12586  }
12587 
12588  return result;
12589  }
12590 
12592 };
12593 
12595 // presets //
12597 
12606 using json = basic_json<>;
12607 } // namespace nlohmann
12608 
12609 
12611 // nonmember support //
12613 
12614 // specialization of std::swap, and std::hash
12615 namespace std
12616 {
12622 template<>
12623 inline void swap(nlohmann::json& j1,
12624  nlohmann::json& j2) noexcept(
12625  is_nothrow_move_constructible<nlohmann::json>::value and
12626  is_nothrow_move_assignable<nlohmann::json>::value
12627  )
12628 {
12629  j1.swap(j2);
12630 }
12631 
12633 template<>
12634 struct hash<nlohmann::json>
12635 {
12641  std::size_t operator()(const nlohmann::json& j) const
12642  {
12643  // a naive hashing via the string representation
12644  const auto& h = hash<nlohmann::json::string_t>();
12645  return h(j.dump());
12646  }
12647 };
12648 } // namespace std
12649 
12663 inline nlohmann::json operator "" _json(const char* s, std::size_t n)
12664 {
12665  return nlohmann::json::parse(s, s + n);
12666 }
12667 
12681 inline nlohmann::json::json_pointer operator "" _json_pointer(const char* s, std::size_t n)
12682 {
12683  return nlohmann::json::json_pointer(std::string(s, n));
12684 }
12685 
12686 // restore GCC/clang diagnostic settings
12687 #if defined(__clang__) || defined(__GNUC__) || defined(__GNUG__)
12688  #pragma GCC diagnostic pop
12689 #endif
12690 
12691 // clean up
12692 #undef JSON_THROW
12693 #undef JSON_TRY
12694 #undef JSON_CATCH
12695 #undef JSON_DEPRECATED
12696 
12697 #endif
typename std::allocator_traits< allocator_type >::pointer pointer
the type of an element pointer
Definition: json.hpp:1082
friend bool operator<=(const_reference lhs, const_reference rhs) noexcept
comparison: less than or equal
Definition: json.hpp:6170
const_reference front() const
access the first element
Definition: json.hpp:4209
JSONSerializer< T, SFINAE > json_serializer
Definition: json.hpp:1054
NumberFloatType number_float_t
a type for a number (floating-point)
Definition: json.hpp:1617
static basic_json from_msgpack(const std::vector< uint8_t > &v)
create a JSON value from a byte vector in MessagePack format
Definition: json.hpp:8000
BooleanType boolean_t
a type for a boolean
Definition: json.hpp:1406
typename basic_json::value_type value_type
the type of the values when the iterator is dereferenced
Definition: json.hpp:8726
friend std::istream & operator>>(std::istream &i, basic_json &j)
deserialize from stream
Definition: json.hpp:6570
static iteration_proxy< const_iterator > iterator_wrapper(const_reference cont)
wrapper to access iterator member functions in range-based for
Definition: json.hpp:4952
const_reference operator[](size_type idx) const
access specified array element
Definition: json.hpp:3769
std::reverse_iterator< Base > base_iterator
shortcut to the reverse iterator adaptor
Definition: json.hpp:9333
const_reverse_iterator crend() const noexcept
returns a const reverse iterator to one before the first
Definition: json.hpp:4923
iterator begin() noexcept
returns an iterator to the first element
Definition: json.hpp:4679
static basic_json parse(const CharT s, const parser_callback_t cb=nullptr)
deserialize from string literal
Definition: json.hpp:6368
difference_type operator-(const iter_impl &other) const
return difference
Definition: json.hpp:9219
iterator end() noexcept
returns an iterator to one past the last element
Definition: json.hpp:4750
constexpr value_t type() const noexcept
return the type of the JSON value (explicit)
Definition: json.hpp:2688
reference operator+=(const basic_json &val)
add an object to an array
Definition: json.hpp:5327
IteratorType erase(IteratorType first, IteratorType last)
remove elements given an iterator range
Definition: json.hpp:4417
basic_json(std::nullptr_t=nullptr) noexcept
create a null object
Definition: json.hpp:1939
static basic_json object(std::initializer_list< basic_json > init=std::initializer_list< basic_json >())
explicitly create an object from an initializer list
Definition: json.hpp:2204
string_t value(const json_pointer &ptr, const char *default_value) const
overload for a default value of type const char*
Definition: json.hpp:4171
friend bool operator!=(const_reference lhs, const_reference rhs) noexcept
comparison: not equal
Definition: json.hpp:6014
bool operator>=(const iter_impl &other) const
comparison: greater than or equal
Definition: json.hpp:9148
iter_impl(const iter_impl &other) noexcept
copy constructor
Definition: json.hpp:8802
basic_json(InputIT first, InputIT last)
construct a JSON container given an iterator range
Definition: json.hpp:2275
ReferenceType get_ref()
get a reference value (implicit)
Definition: json.hpp:3447
void push_back(std::initializer_list< basic_json > init)
add an object to an object
Definition: json.hpp:5408
a class to store JSON values
Definition: json.hpp:1038
iterator insert(const_iterator pos, std::initializer_list< basic_json > ilist)
inserts elements
Definition: json.hpp:5710
void erase(const size_type idx)
remove element from a JSON array given an index
Definition: json.hpp:4540
friend bool operator==(std::nullptr_t, const_reference v) noexcept
comparison: equal
Definition: json.hpp:5993
typename std::conditional< std::is_const< U >::value, typename basic_json::const_pointer, typename basic_json::pointer >::type pointer
defines a pointer to the type iterated over (value_type)
Definition: json.hpp:8732
const_iterator end() const noexcept
returns a const iterator to one past the last element
Definition: json.hpp:4760
const_iterator find(typename object_t::key_type key) const
find an element in a JSON object
Definition: json.hpp:4606
static allocator_type get_allocator()
returns the allocator associated with the container
Definition: json.hpp:1101
reference operator[](size_type idx)
access specified array element
Definition: json.hpp:3723
default JSONSerializer template argument
Definition: json.hpp:910
json_reverse_iterator operator-(difference_type i) const
subtract from iterator
Definition: json.hpp:9389
iterator find(typename object_t::key_type key)
find an element in a JSON object
Definition: json.hpp:4590
constexpr bool is_structured() const noexcept
return whether type is structured
Definition: json.hpp:2745
ObjectType< StringType, basic_json, std::less< StringType >, AllocatorType< std::pair< const StringType, basic_json > >> object_t
a type for an object
Definition: json.hpp:1281
static basic_json from_cbor(const std::vector< uint8_t > &v)
create a JSON value from a byte vector in CBOR format
Definition: json.hpp:8057
static basic_json parse(T(&array)[N], const parser_callback_t cb=nullptr)
deserialize from an array
Definition: json.hpp:6330
bool operator!=(const iter_impl &other) const
comparison: not equal
Definition: json.hpp:9088
typename std::conditional< std::is_const< U >::value, typename basic_json::const_reference, typename basic_json::reference >::type reference
defines a reference to the type iterated over (value_type)
Definition: json.hpp:8736
~basic_json()
destructor
Definition: json.hpp:2574
reference & operator=(basic_json other) noexcept(std::is_nothrow_move_constructible< value_t >::value and std::is_nothrow_move_assignable< value_t >::value and std::is_nothrow_move_constructible< json_value >::value and std::is_nothrow_move_assignable< json_value >::value)
copy assignment
Definition: json.hpp:2541
void swap(string_t &other)
exchanges the values
Definition: json.hpp:5845
void swap(object_t &other)
exchanges the values
Definition: json.hpp:5812
static basic_json parse(std::istream &i, const parser_callback_t cb=nullptr)
deserialize from stream
Definition: json.hpp:6398
STL namespace.
reference operator+=(std::initializer_list< basic_json > init)
add an object to an object
Definition: json.hpp:5425
size_type count(typename object_t::key_type key) const
returns the number of occurrences of a key in a JSON object
Definition: json.hpp:4639
object_t::key_type key() const
return the key of an object iterator
Definition: json.hpp:9409
json_reverse_iterator & operator--()
pre-decrement (–it)
Definition: json.hpp:9367
std::bidirectional_iterator_tag iterator_category
the category of the iterator
Definition: json.hpp:8738
json_reverse_iterator operator--(int)
post-decrement (it–)
Definition: json.hpp:9361
iter_impl operator-(difference_type i)
subtract from iterator
Definition: json.hpp:9208
size_type max_size() const noexcept
returns the maximum possible number of elements
Definition: json.hpp:5138
basic_json(std::initializer_list< basic_json > init, bool type_deduction=true, value_t manual_type=value_t::array)
create a container (array or object) from an initializer list
Definition: json.hpp:2081
reference at(size_type idx)
access specified array element with bounds checking
Definition: json.hpp:3540
JSON_DEPRECATED basic_json(std::istream &i, const parser_callback_t cb=nullptr)
construct a JSON value given an input stream
Definition: json.hpp:2395
friend class basic_json
allow basic_json to access private members
Definition: json.hpp:8717
reference operator[](difference_type n) const
access to successor
Definition: json.hpp:9246
constexpr bool is_number() const noexcept
return whether value is a number
Definition: json.hpp:2819
const value_type & const_reference
the type of an element const reference
Definition: json.hpp:1071
bool operator==(const iter_impl &other) const
comparison: equal
Definition: json.hpp:9055
constexpr bool is_primitive() const noexcept
return whether type is primitive
Definition: json.hpp:2718
reference front()
access the first element
Definition: json.hpp:4201
reference operator*() const
return a reference to the value pointed to by the iterator
Definition: json.hpp:8896
const_reverse_iterator crbegin() const noexcept
returns a const reverse iterator to the last element
Definition: json.hpp:4894
const_reference operator[](T *(&key)[n]) const
read-only access specified object element
Definition: json.hpp:3931
std::size_t size_type
a type to represent container sizes
Definition: json.hpp:1076
const_iterator begin() const noexcept
returns a const iterator to the first element
Definition: json.hpp:4689
ReferenceType get_ref() const
get a reference value (implicit)
Definition: json.hpp:3460
iter_impl & operator++()
pre-increment (++it)
Definition: json.hpp:8980
reference operator[](const typename object_t::key_type &key)
access specified object element
Definition: json.hpp:3807
static iteration_proxy< iterator > iterator_wrapper(reference cont)
wrapper to access iterator member functions in range-based for
Definition: json.hpp:4944
static void from_json(BasicJsonType &&j, ValueType &val) noexcept(noexcept(::nlohmann::from_json(std::forward< BasicJsonType >(j), val)))
convert a JSON value to any value type
Definition: json.hpp:922
iter_impl operator+(difference_type i)
add to iterator
Definition: json.hpp:9197
NumberIntegerType number_integer_t
a type for a number (integer)
Definition: json.hpp:1478
constexpr bool is_array() const noexcept
return whether value is an array
Definition: json.hpp:2948
const_reference at(size_type idx) const
access specified array element with bounds checking
Definition: json.hpp:3583
NumberUnsignedType number_unsigned_t
a type for a number (unsigned)
Definition: json.hpp:1549
friend bool operator>=(const_reference lhs, const_reference rhs) noexcept
comparison: greater than or equal
Definition: json.hpp:6214
friend bool operator<(const_reference lhs, const_reference rhs) noexcept
comparison: less than
Definition: json.hpp:6075
size_type size() const noexcept
returns the number of elements
Definition: json.hpp:5072
json_reverse_iterator(const typename base_iterator::iterator_type &it) noexcept
create reverse iterator from iterator
Definition: json.hpp:9338
const_iterator cbegin() const noexcept
returns a const iterator to the first element
Definition: json.hpp:4719
reference operator[](T *key)
access specified object element
Definition: json.hpp:3964
static basic_json meta()
returns version information on the library
Definition: json.hpp:1129
static basic_json parse(std::istream &&i, const parser_callback_t cb=nullptr)
deserialize from stream
Definition: json.hpp:6407
ValueType value(const json_pointer &ptr, ValueType default_value) const
access specified object element via JSON Pointer with default value
Definition: json.hpp:4148
basic_json(size_type cnt, const basic_json &val)
construct an array with count copies of given value
Definition: json.hpp:2228
json_reverse_iterator operator++(int)
post-increment (it++)
Definition: json.hpp:9348
constexpr const auto & from_json
Definition: json.hpp:898
reference value() const
return the value of an iterator
Definition: json.hpp:9416
constexpr bool is_boolean() const noexcept
return whether value is a boolean
Definition: json.hpp:2789
friend std::ostream & operator>>(const basic_json &j, std::ostream &o)
serialize to stream
Definition: json.hpp:6287
reference at(const typename object_t::key_type &key)
access specified object element with bounds checking
Definition: json.hpp:3630
PointerType get_ptr() noexcept
get a pointer value (implicit)
Definition: json.hpp:3370
namespace for Niels Lohmann
Definition: json.hpp:108
constexpr bool is_number_integer() const noexcept
return whether value is an integer number
Definition: json.hpp:2848
basic_json(const value_t value_type)
create an empty value with a given type
Definition: json.hpp:1915
json_reverse_iterator(const base_iterator &it) noexcept
create reverse iterator from base class
Definition: json.hpp:9343
reference operator+=(const typename object_t::value_type &val)
add an object to an object
Definition: json.hpp:5377
constexpr bool is_object() const noexcept
return whether value is an object
Definition: json.hpp:2926
reference operator+=(basic_json &&val)
add an object to an array
Definition: json.hpp:5293
difference_type operator-(const json_reverse_iterator &other) const
return difference
Definition: json.hpp:9397
constexpr bool is_number_float() const noexcept
return whether value is a floating-point number
Definition: json.hpp:2904
static basic_json parse(IteratorType first, IteratorType last, const parser_callback_t cb=nullptr)
deserialize from an iterator range with contiguous storage
Definition: json.hpp:6458
json_reverse_iterator & operator+=(difference_type i)
add to iterator
Definition: json.hpp:9374
iter_impl operator++(int)
post-increment (it++)
Definition: json.hpp:8969
bool operator<=(const iter_impl &other) const
comparison: less than or equal
Definition: json.hpp:9130
iter_impl operator--(int)
post-decrement (it–)
Definition: json.hpp:9012
iter_impl & operator--()
pre-decrement (–it)
Definition: json.hpp:9023
reverse_iterator rbegin() noexcept
returns an iterator to the reverse-beginning
Definition: json.hpp:4820
reference back()
access the last element
Definition: json.hpp:4244
iterator insert(const_iterator pos, size_type cnt, const basic_json &val)
inserts elements
Definition: json.hpp:5602
static void to_json(BasicJsonType &j, ValueType &&val) noexcept(noexcept(::nlohmann::to_json(j, std::forward< ValueType >(val))))
convert any value type to a JSON value
Definition: json.hpp:938
iter_impl(pointer object) noexcept
constructor for a given JSON instance
Definition: json.hpp:8749
iterator insert(const_iterator pos, const_iterator first, const_iterator last)
inserts elements
Definition: json.hpp:5652
std::function< bool(int depth, parse_event_t event, basic_json &parsed)> parser_callback_t
per-element parser callback type
Definition: json.hpp:1876
void emplace_back(Args &&... args)
add an object to an array
Definition: json.hpp:5453
constexpr bool is_string() const noexcept
return whether value is a string
Definition: json.hpp:2970
json_reverse_iterator operator+(difference_type i) const
add to iterator
Definition: json.hpp:9381
const_iterator cend() const noexcept
returns a const iterator to one past the last element
Definition: json.hpp:4790
friend bool operator==(const_reference lhs, const_reference rhs) noexcept
comparison: equal
Definition: json.hpp:5891
void push_back(const basic_json &val)
add an object to an array
Definition: json.hpp:5303
void push_back(const typename object_t::value_type &val)
add an object to an object
Definition: json.hpp:5353
void swap(array_t &other)
exchanges the values
Definition: json.hpp:5779
size_type erase(const typename object_t::key_type &key)
remove element from a JSON object given a key
Definition: json.hpp:4505
constexpr const auto & to_json
Definition: json.hpp:897
bool empty() const noexcept
checks whether the container is empty
Definition: json.hpp:5004
const_reference back() const
access the last element
Definition: json.hpp:4254
const_reverse_iterator rbegin() const noexcept
returns a const reverse iterator to the last element
Definition: json.hpp:4828
ArrayType< basic_json, AllocatorType< basic_json > > array_t
a type for an array
Definition: json.hpp:1327
bool operator<(const iter_impl &other) const
comparison: smaller
Definition: json.hpp:9097
friend bool operator!=(const_reference v, std::nullptr_t) noexcept
comparison: not equal
Definition: json.hpp:6037
pointer operator->() const
dereference the iterator
Definition: json.hpp:8935
string_t dump(const int indent=-1) const
serialization
Definition: json.hpp:2646
ValueType value(const typename object_t::key_type &key, ValueType default_value) const
access specified object element with default value
Definition: json.hpp:4076
iter_impl & operator=(iter_impl other) noexcept(std::is_nothrow_move_constructible< pointer >::value and std::is_nothrow_move_assignable< pointer >::value and std::is_nothrow_move_constructible< internal_iterator >::value and std::is_nothrow_move_assignable< internal_iterator >::value)
copy assignment
Definition: json.hpp:8811
std::ptrdiff_t difference_type
a type to represent differences between iterators
Definition: json.hpp:1074
static basic_json parse(const ContiguousContainer &c, const parser_callback_t cb=nullptr)
deserialize from a container with contiguous storage
Definition: json.hpp:6530
AllocatorType< basic_json > allocator_type
the allocator type
Definition: json.hpp:1079
json_pointer(const std::string &s="")
create JSON pointer
Definition: json.hpp:11368
string_t value(const typename object_t::key_type &key, const char *default_value) const
overload for a default value of type const char*
Definition: json.hpp:4100
friend bool operator!=(std::nullptr_t, const_reference v) noexcept
comparison: not equal
Definition: json.hpp:6046
reference value() const
return the value of an iterator
Definition: json.hpp:9299
iterator insert(const_iterator pos, basic_json &&val)
inserts element
Definition: json.hpp:5573
const_reference at(const typename object_t::key_type &key) const
access specified object element with bounds checking
Definition: json.hpp:3677
const_reverse_iterator rend() const noexcept
returns a const reverse iterator to one before the first
Definition: json.hpp:4865
basic_json(CompatibleType &&val) noexcept(noexcept(JSONSerializer< U >::to_json(std::declval< basic_json_t &>(), std::forward< CompatibleType >(val))))
create a JSON value
Definition: json.hpp:2005
const_reference operator[](const typename object_t::key_type &key) const
read-only access specified object element
Definition: json.hpp:3856
constexpr bool is_null() const noexcept
return whether value is null
Definition: json.hpp:2767
static std::vector< uint8_t > to_msgpack(const basic_json &j)
create a MessagePack serialization of a given JSON value
Definition: json.hpp:7971
typename std::allocator_traits< allocator_type >::const_pointer const_pointer
the type of an element const pointer
Definition: json.hpp:1084
StringType string_t
a type for a string
Definition: json.hpp:1380
reference operator[](difference_type n) const
access to successor
Definition: json.hpp:9403
static basic_json array(std::initializer_list< basic_json > init=std::initializer_list< basic_json >())
explicitly create an array from an initializer list
Definition: json.hpp:2164
basic_json(basic_json &&other) noexcept
move constructor
Definition: json.hpp:2504
friend bool operator>(const_reference lhs, const_reference rhs) noexcept
comparison: greater than
Definition: json.hpp:6192
constexpr bool is_number_unsigned() const noexcept
return whether value is an unsigned integer number
Definition: json.hpp:2876
typename basic_json::difference_type difference_type
a type to represent differences between iterators
Definition: json.hpp:8728
constexpr const PointerType get_ptr() const noexcept
get a pointer value (implicit)
Definition: json.hpp:3398
iter_impl & operator-=(difference_type i)
subtract from iterator
Definition: json.hpp:9188
typename Base::reference reference
the reference type for the pointed-to element
Definition: json.hpp:9335
a template for a reverse iterator class
Definition: json.hpp:1051
void push_back(basic_json &&val)
add an object to an array
Definition: json.hpp:5267
iterator insert(const_iterator pos, const basic_json &val)
inserts element
Definition: json.hpp:5549
void clear() noexcept
clears the contents
Definition: json.hpp:5194
static std::vector< uint8_t > to_cbor(const basic_json &j)
create a MessagePack serialization of a given JSON value
Definition: json.hpp:8027
friend bool operator==(const_reference v, std::nullptr_t) noexcept
comparison: equal
Definition: json.hpp:5984
basic_json value_type
the type of elements in a basic_json container
Definition: json.hpp:1066
iter_impl & operator+=(difference_type i)
add to iterator
Definition: json.hpp:9157
object_t::key_type key() const
return the key of an object iterator
Definition: json.hpp:9283
void swap(reference other) noexcept(std::is_nothrow_move_constructible< value_t >::value and std::is_nothrow_move_assignable< value_t >::value and std::is_nothrow_move_constructible< json_value >::value and std::is_nothrow_move_assignable< json_value >::value)
exchanges the values
Definition: json.hpp:5747
friend std::istream & operator<<(basic_json &j, std::istream &i)
deserialize from stream
Definition: json.hpp:6560
const_reference operator[](T *key) const
read-only access specified object element
Definition: json.hpp:4014
std::pair< iterator, bool > emplace(Args &&... args)
add an object to an object if key does not exist
Definition: json.hpp:5501
basic_json(const basic_json &other)
copy constructor
Definition: json.hpp:2427
bool operator>(const iter_impl &other) const
comparison: greater than
Definition: json.hpp:9139
friend std::ostream & operator<<(std::ostream &o, const basic_json &j)
serialize to stream
Definition: json.hpp:6255
IteratorType erase(IteratorType pos)
remove element given an iterator
Definition: json.hpp:4310
a template for a random access iterator for the basic_json class
Definition: json.hpp:1050
json_reverse_iterator & operator++()
pre-increment (++it)
Definition: json.hpp:9354
constexpr bool is_discarded() const noexcept
return whether value is discarded
Definition: json.hpp:2997
parse_event_t
JSON callback events.
Definition: json.hpp:1806
reference operator[](T *(&key)[n])
access specified object element
Definition: json.hpp:3896
reverse_iterator rend() noexcept
returns an iterator to the reverse-end
Definition: json.hpp:4857