JSON for Modern C++  2.1.1
json.hpp
1 /*
2  __ _____ _____ _____
3  __| | __| | | | JSON for Modern C++
4 | | |__ | | | | | | version 2.1.1
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, copy, fill, find, for_each, none_of, remove, reverse, transform
33 #include <array> // array
34 #include <cassert> // assert
35 #include <cctype> // isdigit
36 #include <ciso646> // and, not, or
37 #include <cmath> // isfinite, labs, ldexp, signbit
38 #include <cstddef> // nullptr_t, ptrdiff_t, size_t
39 #include <cstdint> // int64_t, uint64_t
40 #include <cstdlib> // abort, strtod, strtof, strtold, strtoul, strtoll, strtoull
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, back_inserter, 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, conditional, decay, enable_if, false_type, integral_constant, is_arithmetic, is_base_of, is_const, is_constructible, is_convertible, is_default_constructible, is_enum, is_floating_point, is_integral, is_nothrow_move_assignable, is_nothrow_move_constructible, is_pointer, is_reference, is_same, is_scalar, is_signed, remove_const, remove_cv, remove_pointer, remove_reference, true_type, underlying_type
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, typename T, enable_if_t<
527  std::is_same<T, typename BasicJsonType::boolean_t>::value, int> = 0>
528 void to_json(BasicJsonType& j, T b) noexcept
529 {
530  external_constructor<value_t::boolean>::construct(j, b);
531 }
532 
533 template<typename BasicJsonType, typename CompatibleString,
534  enable_if_t<std::is_constructible<typename BasicJsonType::string_t,
535  CompatibleString>::value, int> = 0>
536 void to_json(BasicJsonType& j, const CompatibleString& s)
537 {
538  external_constructor<value_t::string>::construct(j, s);
539 }
540 
541 template<typename BasicJsonType, typename FloatType,
542  enable_if_t<std::is_floating_point<FloatType>::value, int> = 0>
543 void to_json(BasicJsonType& j, FloatType val) noexcept
544 {
545  external_constructor<value_t::number_float>::construct(j, static_cast<typename BasicJsonType::number_float_t>(val));
546 }
547 
548 template <
549  typename BasicJsonType, typename CompatibleNumberUnsignedType,
550  enable_if_t<is_compatible_integer_type<typename BasicJsonType::number_unsigned_t,
551  CompatibleNumberUnsignedType>::value, int> = 0 >
552 void to_json(BasicJsonType& j, CompatibleNumberUnsignedType val) noexcept
553 {
554  external_constructor<value_t::number_unsigned>::construct(j, static_cast<typename BasicJsonType::number_unsigned_t>(val));
555 }
556 
557 template <
558  typename BasicJsonType, typename CompatibleNumberIntegerType,
559  enable_if_t<is_compatible_integer_type<typename BasicJsonType::number_integer_t,
560  CompatibleNumberIntegerType>::value, int> = 0 >
561 void to_json(BasicJsonType& j, CompatibleNumberIntegerType val) noexcept
562 {
563  external_constructor<value_t::number_integer>::construct(j, static_cast<typename BasicJsonType::number_integer_t>(val));
564 }
565 
566 template<typename BasicJsonType, typename UnscopedEnumType,
567  enable_if_t<is_unscoped_enum<UnscopedEnumType>::value, int> = 0>
568 void to_json(BasicJsonType& j, UnscopedEnumType e) noexcept
569 {
570  external_constructor<value_t::number_integer>::construct(j, e);
571 }
572 
573 template <
574  typename BasicJsonType, typename CompatibleArrayType,
575  enable_if_t <
576  is_compatible_array_type<BasicJsonType, CompatibleArrayType>::value or
577  std::is_same<typename BasicJsonType::array_t, CompatibleArrayType>::value,
578  int > = 0 >
579 void to_json(BasicJsonType& j, const CompatibleArrayType& arr)
580 {
581  external_constructor<value_t::array>::construct(j, arr);
582 }
583 
584 template <
585  typename BasicJsonType, typename CompatibleObjectType,
586  enable_if_t<is_compatible_object_type<BasicJsonType, CompatibleObjectType>::value,
587  int> = 0 >
588 void to_json(BasicJsonType& j, const CompatibleObjectType& arr)
589 {
590  external_constructor<value_t::object>::construct(j, arr);
591 }
592 
593 
595 // from_json //
597 
598 // overloads for basic_json template parameters
599 template<typename BasicJsonType, typename ArithmeticType,
600  enable_if_t<std::is_arithmetic<ArithmeticType>::value and
601  not std::is_same<ArithmeticType,
602  typename BasicJsonType::boolean_t>::value,
603  int> = 0>
604 void get_arithmetic_value(const BasicJsonType& j, ArithmeticType& val)
605 {
606  switch (static_cast<value_t>(j))
607  {
608  case value_t::number_unsigned:
609  {
610  val = static_cast<ArithmeticType>(
611  *j.template get_ptr<const typename BasicJsonType::number_unsigned_t*>());
612  break;
613  }
614  case value_t::number_integer:
615  {
616  val = static_cast<ArithmeticType>(
617  *j.template get_ptr<const typename BasicJsonType::number_integer_t*>());
618  break;
619  }
620  case value_t::number_float:
621  {
622  val = static_cast<ArithmeticType>(
623  *j.template get_ptr<const typename BasicJsonType::number_float_t*>());
624  break;
625  }
626  default:
627  {
628  JSON_THROW(
629  std::domain_error("type must be number, but is " + j.type_name()));
630  }
631  }
632 }
633 
634 template<typename BasicJsonType>
635 void from_json(const BasicJsonType& j, typename BasicJsonType::boolean_t& b)
636 {
637  if (not j.is_boolean())
638  {
639  JSON_THROW(std::domain_error("type must be boolean, but is " + j.type_name()));
640  }
641  b = *j.template get_ptr<const typename BasicJsonType::boolean_t*>();
642 }
643 
644 template<typename BasicJsonType>
645 void from_json(const BasicJsonType& j, typename BasicJsonType::string_t& s)
646 {
647  if (not j.is_string())
648  {
649  JSON_THROW(std::domain_error("type must be string, but is " + j.type_name()));
650  }
651  s = *j.template get_ptr<const typename BasicJsonType::string_t*>();
652 }
653 
654 template<typename BasicJsonType>
655 void from_json(const BasicJsonType& j, typename BasicJsonType::number_float_t& val)
656 {
657  get_arithmetic_value(j, val);
658 }
659 
660 template<typename BasicJsonType>
661 void from_json(const BasicJsonType& j, typename BasicJsonType::number_unsigned_t& val)
662 {
663  get_arithmetic_value(j, val);
664 }
665 
666 template<typename BasicJsonType>
667 void from_json(const BasicJsonType& j, typename BasicJsonType::number_integer_t& val)
668 {
669  get_arithmetic_value(j, val);
670 }
671 
672 template<typename BasicJsonType, typename UnscopedEnumType,
673  enable_if_t<is_unscoped_enum<UnscopedEnumType>::value, int> = 0>
674 void from_json(const BasicJsonType& j, UnscopedEnumType& e)
675 {
676  typename std::underlying_type<UnscopedEnumType>::type val;
677  get_arithmetic_value(j, val);
678  e = static_cast<UnscopedEnumType>(val);
679 }
680 
681 template<typename BasicJsonType>
682 void from_json(const BasicJsonType& j, typename BasicJsonType::array_t& arr)
683 {
684  if (not j.is_array())
685  {
686  JSON_THROW(std::domain_error("type must be array, but is " + j.type_name()));
687  }
688  arr = *j.template get_ptr<const typename BasicJsonType::array_t*>();
689 }
690 
691 // forward_list doesn't have an insert method
692 template<typename BasicJsonType, typename T, typename Allocator>
693 void from_json(const BasicJsonType& j, std::forward_list<T, Allocator>& l)
694 {
695  // do not perform the check when user wants to retrieve jsons
696  // (except when it's null.. ?)
697  if (j.is_null())
698  {
699  JSON_THROW(std::domain_error("type must be array, but is " + j.type_name()));
700  }
701  if (not std::is_same<T, BasicJsonType>::value)
702  {
703  if (not j.is_array())
704  {
705  JSON_THROW(std::domain_error("type must be array, but is " + j.type_name()));
706  }
707  }
708  for (auto it = j.rbegin(), end = j.rend(); it != end; ++it)
709  {
710  l.push_front(it->template get<T>());
711  }
712 }
713 
714 template<typename BasicJsonType, typename CompatibleArrayType>
715 void from_json_array_impl(const BasicJsonType& j, CompatibleArrayType& arr, priority_tag<0>)
716 {
717  using std::begin;
718  using std::end;
719 
720  std::transform(j.begin(), j.end(),
721  std::inserter(arr, end(arr)), [](const BasicJsonType & i)
722  {
723  // get<BasicJsonType>() returns *this, this won't call a from_json
724  // method when value_type is BasicJsonType
725  return i.template get<typename CompatibleArrayType::value_type>();
726  });
727 }
728 
729 template<typename BasicJsonType, typename CompatibleArrayType>
730 auto from_json_array_impl(const BasicJsonType& j, CompatibleArrayType& arr, priority_tag<1>)
731 -> decltype(
732  arr.reserve(std::declval<typename CompatibleArrayType::size_type>()),
733  void())
734 {
735  using std::begin;
736  using std::end;
737 
738  arr.reserve(j.size());
739  std::transform(
740  j.begin(), j.end(), std::inserter(arr, end(arr)), [](const BasicJsonType & i)
741  {
742  // get<BasicJsonType>() returns *this, this won't call a from_json
743  // method when value_type is BasicJsonType
744  return i.template get<typename CompatibleArrayType::value_type>();
745  });
746 }
747 
748 template<typename BasicJsonType, typename CompatibleArrayType,
749  enable_if_t<is_compatible_array_type<BasicJsonType, CompatibleArrayType>::value and
750  not std::is_same<typename BasicJsonType::array_t, CompatibleArrayType>::value, int> = 0>
751 void from_json(const BasicJsonType& j, CompatibleArrayType& arr)
752 {
753  if (j.is_null())
754  {
755  JSON_THROW(std::domain_error("type must be array, but is " + j.type_name()));
756  }
757 
758  // when T == BasicJsonType, do not check if value_t is correct
759  if (not std::is_same<typename CompatibleArrayType::value_type, BasicJsonType>::value)
760  {
761  if (not j.is_array())
762  {
763  JSON_THROW(std::domain_error("type must be array, but is " + j.type_name()));
764  }
765  }
766  from_json_array_impl(j, arr, priority_tag<1> {});
767 }
768 
769 template<typename BasicJsonType, typename CompatibleObjectType,
770  enable_if_t<is_compatible_object_type<BasicJsonType, CompatibleObjectType>::value, int> = 0>
771 void from_json(const BasicJsonType& j, CompatibleObjectType& obj)
772 {
773  if (not j.is_object())
774  {
775  JSON_THROW(std::domain_error("type must be object, but is " + j.type_name()));
776  }
777 
778  auto inner_object = j.template get_ptr<const typename BasicJsonType::object_t*>();
779  using std::begin;
780  using std::end;
781  // we could avoid the assignment, but this might require a for loop, which
782  // might be less efficient than the container constructor for some
783  // containers (would it?)
784  obj = CompatibleObjectType(begin(*inner_object), end(*inner_object));
785 }
786 
787 // overload for arithmetic types, not chosen for basic_json template arguments
788 // (BooleanType, etc..); note: Is it really necessary to provide explicit
789 // overloads for boolean_t etc. in case of a custom BooleanType which is not
790 // an arithmetic type?
791 template<typename BasicJsonType, typename ArithmeticType,
792  enable_if_t <
793  std::is_arithmetic<ArithmeticType>::value and
794  not std::is_same<ArithmeticType, typename BasicJsonType::number_unsigned_t>::value and
795  not std::is_same<ArithmeticType, typename BasicJsonType::number_integer_t>::value and
796  not std::is_same<ArithmeticType, typename BasicJsonType::number_float_t>::value and
797  not std::is_same<ArithmeticType, typename BasicJsonType::boolean_t>::value,
798  int> = 0>
799 void from_json(const BasicJsonType& j, ArithmeticType& val)
800 {
801  switch (static_cast<value_t>(j))
802  {
803  case value_t::number_unsigned:
804  {
805  val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_unsigned_t*>());
806  break;
807  }
808  case value_t::number_integer:
809  {
810  val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_integer_t*>());
811  break;
812  }
813  case value_t::number_float:
814  {
815  val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_float_t*>());
816  break;
817  }
818  case value_t::boolean:
819  {
820  val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::boolean_t*>());
821  break;
822  }
823  default:
824  {
825  JSON_THROW(std::domain_error("type must be number, but is " + j.type_name()));
826  }
827  }
828 }
829 
830 struct to_json_fn
831 {
832  private:
833  template<typename BasicJsonType, typename T>
834  auto call(BasicJsonType& j, T&& val, priority_tag<1>) const noexcept(noexcept(to_json(j, std::forward<T>(val))))
835  -> decltype(to_json(j, std::forward<T>(val)), void())
836  {
837  return to_json(j, std::forward<T>(val));
838  }
839 
840  template<typename BasicJsonType, typename T>
841  void call(BasicJsonType&, T&&, priority_tag<0>) const noexcept
842  {
843  static_assert(sizeof(BasicJsonType) == 0,
844  "could not find to_json() method in T's namespace");
845  }
846 
847  public:
848  template<typename BasicJsonType, typename T>
849  void operator()(BasicJsonType& j, T&& val) const
850  noexcept(noexcept(std::declval<to_json_fn>().call(j, std::forward<T>(val), priority_tag<1> {})))
851  {
852  return call(j, std::forward<T>(val), priority_tag<1> {});
853  }
854 };
855 
856 struct from_json_fn
857 {
858  private:
859  template<typename BasicJsonType, typename T>
860  auto call(const BasicJsonType& j, T& val, priority_tag<1>) const
861  noexcept(noexcept(from_json(j, val)))
862  -> decltype(from_json(j, val), void())
863  {
864  return from_json(j, val);
865  }
866 
867  template<typename BasicJsonType, typename T>
868  void call(const BasicJsonType&, T&, priority_tag<0>) const noexcept
869  {
870  static_assert(sizeof(BasicJsonType) == 0,
871  "could not find from_json() method in T's namespace");
872  }
873 
874  public:
875  template<typename BasicJsonType, typename T>
876  void operator()(const BasicJsonType& j, T& val) const
877  noexcept(noexcept(std::declval<from_json_fn>().call(j, val, priority_tag<1> {})))
878  {
879  return call(j, val, priority_tag<1> {});
880  }
881 };
882 
883 // taken from ranges-v3
884 template<typename T>
885 struct static_const
886 {
887  static constexpr T value{};
888 };
889 
890 template<typename T>
891 constexpr T static_const<T>::value;
892 } // namespace detail
893 
894 
896 namespace
897 {
898 constexpr const auto& to_json = detail::static_const<detail::to_json_fn>::value;
899 constexpr const auto& from_json = detail::static_const<detail::from_json_fn>::value;
900 }
901 
902 
910 template<typename = void, typename = void>
912 {
922  template<typename BasicJsonType, typename ValueType>
923  static void from_json(BasicJsonType&& j, ValueType& val) noexcept(
924  noexcept(::nlohmann::from_json(std::forward<BasicJsonType>(j), val)))
925  {
926  ::nlohmann::from_json(std::forward<BasicJsonType>(j), val);
927  }
928 
938  template<typename BasicJsonType, typename ValueType>
939  static void to_json(BasicJsonType& j, ValueType&& val) noexcept(
940  noexcept(::nlohmann::to_json(j, std::forward<ValueType>(val))))
941  {
942  ::nlohmann::to_json(j, std::forward<ValueType>(val));
943  }
944 };
945 
946 
1028 template <
1029  template<typename U, typename V, typename... Args> class ObjectType = std::map,
1030  template<typename U, typename... Args> class ArrayType = std::vector,
1031  class StringType = std::string,
1032  class BooleanType = bool,
1033  class NumberIntegerType = std::int64_t,
1034  class NumberUnsignedType = std::uint64_t,
1035  class NumberFloatType = double,
1036  template<typename U> class AllocatorType = std::allocator,
1037  template<typename T, typename SFINAE = void> class JSONSerializer = adl_serializer
1038  >
1040 {
1041  private:
1042  template<detail::value_t> friend struct detail::external_constructor;
1044  using basic_json_t = basic_json<ObjectType, ArrayType, StringType,
1045  BooleanType, NumberIntegerType, NumberUnsignedType, NumberFloatType,
1046  AllocatorType, JSONSerializer>;
1047 
1048  public:
1049  using value_t = detail::value_t;
1050  // forward declarations
1051  template<typename U> class iter_impl;
1052  template<typename Base> class json_reverse_iterator;
1053  class json_pointer;
1054  template<typename T, typename SFINAE>
1055  using json_serializer = JSONSerializer<T, SFINAE>;
1056 
1058  // container types //
1060 
1065 
1068 
1072  using const_reference = const value_type&;
1073 
1075  using difference_type = std::ptrdiff_t;
1077  using size_type = std::size_t;
1078 
1080  using allocator_type = AllocatorType<basic_json>;
1081 
1083  using pointer = typename std::allocator_traits<allocator_type>::pointer;
1085  using const_pointer = typename std::allocator_traits<allocator_type>::const_pointer;
1086 
1095 
1097 
1098 
1103  {
1104  return allocator_type();
1105  }
1106 
1130  static basic_json meta()
1131  {
1132  basic_json result;
1133 
1134  result["copyright"] = "(C) 2013-2017 Niels Lohmann";
1135  result["name"] = "JSON for Modern C++";
1136  result["url"] = "https://github.com/nlohmann/json";
1137  result["version"] =
1138  {
1139  {"string", "2.1.1"},
1140  {"major", 2},
1141  {"minor", 1},
1142  {"patch", 1}
1143  };
1144 
1145 #ifdef _WIN32
1146  result["platform"] = "win32";
1147 #elif defined __linux__
1148  result["platform"] = "linux";
1149 #elif defined __APPLE__
1150  result["platform"] = "apple";
1151 #elif defined __unix__
1152  result["platform"] = "unix";
1153 #else
1154  result["platform"] = "unknown";
1155 #endif
1156 
1157 #if defined(__clang__)
1158  result["compiler"] = {{"family", "clang"}, {"version", __clang_version__}};
1159 #elif defined(__ICC) || defined(__INTEL_COMPILER)
1160  result["compiler"] = {{"family", "icc"}, {"version", __INTEL_COMPILER}};
1161 #elif defined(__GNUC__) || defined(__GNUG__)
1162  result["compiler"] = {{"family", "gcc"}, {"version", std::to_string(__GNUC__) + "." + std::to_string(__GNUC_MINOR__) + "." + std::to_string(__GNUC_PATCHLEVEL__)}};
1163 #elif defined(__HP_cc) || defined(__HP_aCC)
1164  result["compiler"] = "hp"
1165 #elif defined(__IBMCPP__)
1166  result["compiler"] = {{"family", "ilecpp"}, {"version", __IBMCPP__}};
1167 #elif defined(_MSC_VER)
1168  result["compiler"] = {{"family", "msvc"}, {"version", _MSC_VER}};
1169 #elif defined(__PGI)
1170  result["compiler"] = {{"family", "pgcpp"}, {"version", __PGI}};
1171 #elif defined(__SUNPRO_CC)
1172  result["compiler"] = {{"family", "sunpro"}, {"version", __SUNPRO_CC}};
1173 #else
1174  result["compiler"] = {{"family", "unknown"}, {"version", "unknown"}};
1175 #endif
1176 
1177 #ifdef __cplusplus
1178  result["compiler"]["c++"] = std::to_string(__cplusplus);
1179 #else
1180  result["compiler"]["c++"] = "unknown";
1181 #endif
1182  return result;
1183  }
1184 
1185 
1187  // JSON value data types //
1189 
1194 
1278  using object_t = ObjectType<StringType,
1279  basic_json,
1280  std::less<StringType>,
1281  AllocatorType<std::pair<const StringType,
1282  basic_json>>>;
1283 
1328  using array_t = ArrayType<basic_json, AllocatorType<basic_json>>;
1329 
1381  using string_t = StringType;
1382 
1407  using boolean_t = BooleanType;
1408 
1479  using number_integer_t = NumberIntegerType;
1480 
1550  using number_unsigned_t = NumberUnsignedType;
1551 
1618  using number_float_t = NumberFloatType;
1619 
1621 
1622  private:
1623 
1625  template<typename T, typename... Args>
1626  static T* create(Args&& ... args)
1627  {
1628  AllocatorType<T> alloc;
1629  auto deleter = [&](T * object)
1630  {
1631  alloc.deallocate(object, 1);
1632  };
1633  std::unique_ptr<T, decltype(deleter)> object(alloc.allocate(1), deleter);
1634  alloc.construct(object.get(), std::forward<Args>(args)...);
1635  assert(object != nullptr);
1636  return object.release();
1637  }
1638 
1640  // JSON value storage //
1642 
1667  union json_value
1668  {
1670  object_t* object;
1672  array_t* array;
1674  string_t* string;
1676  boolean_t boolean;
1678  number_integer_t number_integer;
1680  number_unsigned_t number_unsigned;
1682  number_float_t number_float;
1683 
1685  json_value() = default;
1687  json_value(boolean_t v) noexcept : boolean(v) {}
1689  json_value(number_integer_t v) noexcept : number_integer(v) {}
1691  json_value(number_unsigned_t v) noexcept : number_unsigned(v) {}
1693  json_value(number_float_t v) noexcept : number_float(v) {}
1695  json_value(value_t t)
1696  {
1697  switch (t)
1698  {
1699  case value_t::object:
1700  {
1701  object = create<object_t>();
1702  break;
1703  }
1704 
1705  case value_t::array:
1706  {
1707  array = create<array_t>();
1708  break;
1709  }
1710 
1711  case value_t::string:
1712  {
1713  string = create<string_t>("");
1714  break;
1715  }
1716 
1717  case value_t::boolean:
1718  {
1719  boolean = boolean_t(false);
1720  break;
1721  }
1722 
1723  case value_t::number_integer:
1724  {
1725  number_integer = number_integer_t(0);
1726  break;
1727  }
1728 
1729  case value_t::number_unsigned:
1730  {
1731  number_unsigned = number_unsigned_t(0);
1732  break;
1733  }
1734 
1735  case value_t::number_float:
1736  {
1737  number_float = number_float_t(0.0);
1738  break;
1739  }
1740 
1741  case value_t::null:
1742  {
1743  break;
1744  }
1745 
1746  default:
1747  {
1748  if (t == value_t::null)
1749  {
1750  JSON_THROW(std::domain_error("961c151d2e87f2686a955a9be24d316f1362bf21 2.1.1")); // LCOV_EXCL_LINE
1751  }
1752  break;
1753  }
1754  }
1755  }
1756 
1758  json_value(const string_t& value)
1759  {
1760  string = create<string_t>(value);
1761  }
1762 
1764  json_value(const object_t& value)
1765  {
1766  object = create<object_t>(value);
1767  }
1768 
1770  json_value(const array_t& value)
1771  {
1772  array = create<array_t>(value);
1773  }
1774  };
1775 
1785  void assert_invariant() const
1786  {
1787  assert(m_type != value_t::object or m_value.object != nullptr);
1788  assert(m_type != value_t::array or m_value.array != nullptr);
1789  assert(m_type != value_t::string or m_value.string != nullptr);
1790  }
1791 
1792  public:
1794  // JSON parser callback //
1796 
1807  enum class parse_event_t : uint8_t
1808  {
1810  object_start,
1812  object_end,
1814  array_start,
1816  array_end,
1818  key,
1820  value
1821  };
1822 
1875  using parser_callback_t = std::function<bool(int depth,
1876  parse_event_t event,
1877  basic_json& parsed)>;
1878 
1879 
1881  // constructors //
1883 
1888 
1916  basic_json(const value_t value_type)
1917  : m_type(value_type), m_value(value_type)
1918  {
1919  assert_invariant();
1920  }
1921 
1940  basic_json(std::nullptr_t = nullptr) noexcept
1941  : basic_json(value_t::null)
1942  {
1943  assert_invariant();
1944  }
1945 
1999  template<typename CompatibleType, typename U = detail::uncvref_t<CompatibleType>,
2000  detail::enable_if_t<not std::is_base_of<std::istream, U>::value and
2001  not std::is_same<U, basic_json_t>::value and
2002  not detail::is_basic_json_nested_type<
2003  basic_json_t, U>::value and
2004  detail::has_to_json<basic_json, U>::value,
2005  int> = 0>
2006  basic_json(CompatibleType && val) noexcept(noexcept(JSONSerializer<U>::to_json(
2007  std::declval<basic_json_t&>(), std::forward<CompatibleType>(val))))
2008  {
2009  JSONSerializer<U>::to_json(*this, std::forward<CompatibleType>(val));
2010  assert_invariant();
2011  }
2012 
2082  basic_json(std::initializer_list<basic_json> init,
2083  bool type_deduction = true,
2084  value_t manual_type = value_t::array)
2085  {
2086  // check if each element is an array with two elements whose first
2087  // element is a string
2088  bool is_an_object = std::all_of(init.begin(), init.end(),
2089  [](const basic_json & element)
2090  {
2091  return element.is_array() and element.size() == 2 and element[0].is_string();
2092  });
2093 
2094  // adjust type if type deduction is not wanted
2095  if (not type_deduction)
2096  {
2097  // if array is wanted, do not create an object though possible
2098  if (manual_type == value_t::array)
2099  {
2100  is_an_object = false;
2101  }
2102 
2103  // if object is wanted but impossible, throw an exception
2104  if (manual_type == value_t::object and not is_an_object)
2105  {
2106  JSON_THROW(std::domain_error("cannot create object from initializer list"));
2107  }
2108  }
2109 
2110  if (is_an_object)
2111  {
2112  // the initializer list is a list of pairs -> create object
2113  m_type = value_t::object;
2114  m_value = value_t::object;
2115 
2116  std::for_each(init.begin(), init.end(), [this](const basic_json & element)
2117  {
2118  m_value.object->emplace(*(element[0].m_value.string), element[1]);
2119  });
2120  }
2121  else
2122  {
2123  // the initializer list describes an array -> create array
2124  m_type = value_t::array;
2125  m_value.array = create<array_t>(init);
2126  }
2127 
2128  assert_invariant();
2129  }
2130 
2165  static basic_json array(std::initializer_list<basic_json> init =
2166  std::initializer_list<basic_json>())
2167  {
2168  return basic_json(init, false, value_t::array);
2169  }
2170 
2205  static basic_json object(std::initializer_list<basic_json> init =
2206  std::initializer_list<basic_json>())
2207  {
2208  return basic_json(init, false, value_t::object);
2209  }
2210 
2230  : m_type(value_t::array)
2231  {
2232  m_value.array = create<array_t>(cnt, val);
2233  assert_invariant();
2234  }
2235 
2273  template<class InputIT, typename std::enable_if<
2274  std::is_same<InputIT, typename basic_json_t::iterator>::value or
2275  std::is_same<InputIT, typename basic_json_t::const_iterator>::value, int>::type = 0>
2276  basic_json(InputIT first, InputIT last)
2277  {
2278  assert(first.m_object != nullptr);
2279  assert(last.m_object != nullptr);
2280 
2281  // make sure iterator fits the current value
2282  if (first.m_object != last.m_object)
2283  {
2284  JSON_THROW(std::domain_error("iterators are not compatible"));
2285  }
2286 
2287  // copy type from first iterator
2288  m_type = first.m_object->m_type;
2289 
2290  // check if iterator range is complete for primitive values
2291  switch (m_type)
2292  {
2293  case value_t::boolean:
2294  case value_t::number_float:
2295  case value_t::number_integer:
2296  case value_t::number_unsigned:
2297  case value_t::string:
2298  {
2299  if (not first.m_it.primitive_iterator.is_begin() or not last.m_it.primitive_iterator.is_end())
2300  {
2301  JSON_THROW(std::out_of_range("iterators out of range"));
2302  }
2303  break;
2304  }
2305 
2306  default:
2307  {
2308  break;
2309  }
2310  }
2311 
2312  switch (m_type)
2313  {
2314  case value_t::number_integer:
2315  {
2316  m_value.number_integer = first.m_object->m_value.number_integer;
2317  break;
2318  }
2319 
2320  case value_t::number_unsigned:
2321  {
2322  m_value.number_unsigned = first.m_object->m_value.number_unsigned;
2323  break;
2324  }
2325 
2326  case value_t::number_float:
2327  {
2328  m_value.number_float = first.m_object->m_value.number_float;
2329  break;
2330  }
2331 
2332  case value_t::boolean:
2333  {
2334  m_value.boolean = first.m_object->m_value.boolean;
2335  break;
2336  }
2337 
2338  case value_t::string:
2339  {
2340  m_value = *first.m_object->m_value.string;
2341  break;
2342  }
2343 
2344  case value_t::object:
2345  {
2346  m_value.object = create<object_t>(first.m_it.object_iterator,
2347  last.m_it.object_iterator);
2348  break;
2349  }
2350 
2351  case value_t::array:
2352  {
2353  m_value.array = create<array_t>(first.m_it.array_iterator,
2354  last.m_it.array_iterator);
2355  break;
2356  }
2357 
2358  default:
2359  {
2360  JSON_THROW(std::domain_error("cannot use construct with iterators from " + first.m_object->type_name()));
2361  }
2362  }
2363 
2364  assert_invariant();
2365  }
2366 
2395  JSON_DEPRECATED
2396  explicit basic_json(std::istream& i, const parser_callback_t cb = nullptr)
2397  {
2398  *this = parser(i, cb).parse();
2399  assert_invariant();
2400  }
2401 
2403  // other constructors and destructor //
2405 
2428  basic_json(const basic_json& other)
2429  : m_type(other.m_type)
2430  {
2431  // check of passed value is valid
2432  other.assert_invariant();
2433 
2434  switch (m_type)
2435  {
2436  case value_t::object:
2437  {
2438  m_value = *other.m_value.object;
2439  break;
2440  }
2441 
2442  case value_t::array:
2443  {
2444  m_value = *other.m_value.array;
2445  break;
2446  }
2447 
2448  case value_t::string:
2449  {
2450  m_value = *other.m_value.string;
2451  break;
2452  }
2453 
2454  case value_t::boolean:
2455  {
2456  m_value = other.m_value.boolean;
2457  break;
2458  }
2459 
2460  case value_t::number_integer:
2461  {
2462  m_value = other.m_value.number_integer;
2463  break;
2464  }
2465 
2466  case value_t::number_unsigned:
2467  {
2468  m_value = other.m_value.number_unsigned;
2469  break;
2470  }
2471 
2472  case value_t::number_float:
2473  {
2474  m_value = other.m_value.number_float;
2475  break;
2476  }
2477 
2478  default:
2479  {
2480  break;
2481  }
2482  }
2483 
2484  assert_invariant();
2485  }
2486 
2505  basic_json(basic_json&& other) noexcept
2506  : m_type(std::move(other.m_type)),
2507  m_value(std::move(other.m_value))
2508  {
2509  // check that passed value is valid
2510  other.assert_invariant();
2511 
2512  // invalidate payload
2513  other.m_type = value_t::null;
2514  other.m_value = {};
2515 
2516  assert_invariant();
2517  }
2518 
2542  reference& operator=(basic_json other) noexcept (
2543  std::is_nothrow_move_constructible<value_t>::value and
2544  std::is_nothrow_move_assignable<value_t>::value and
2545  std::is_nothrow_move_constructible<json_value>::value and
2546  std::is_nothrow_move_assignable<json_value>::value
2547  )
2548  {
2549  // check that passed value is valid
2550  other.assert_invariant();
2551 
2552  using std::swap;
2553  swap(m_type, other.m_type);
2554  swap(m_value, other.m_value);
2555 
2556  assert_invariant();
2557  return *this;
2558  }
2559 
2576  {
2577  assert_invariant();
2578 
2579  switch (m_type)
2580  {
2581  case value_t::object:
2582  {
2583  AllocatorType<object_t> alloc;
2584  alloc.destroy(m_value.object);
2585  alloc.deallocate(m_value.object, 1);
2586  break;
2587  }
2588 
2589  case value_t::array:
2590  {
2591  AllocatorType<array_t> alloc;
2592  alloc.destroy(m_value.array);
2593  alloc.deallocate(m_value.array, 1);
2594  break;
2595  }
2596 
2597  case value_t::string:
2598  {
2599  AllocatorType<string_t> alloc;
2600  alloc.destroy(m_value.string);
2601  alloc.deallocate(m_value.string, 1);
2602  break;
2603  }
2604 
2605  default:
2606  {
2607  // all other types need no specific destructor
2608  break;
2609  }
2610  }
2611  }
2612 
2614 
2615  public:
2617  // object inspection //
2619 
2623 
2647  string_t dump(const int indent = -1) const
2648  {
2649  std::stringstream ss;
2650 
2651  if (indent >= 0)
2652  {
2653  dump(ss, true, static_cast<unsigned int>(indent));
2654  }
2655  else
2656  {
2657  dump(ss, false, 0);
2658  }
2659 
2660  return ss.str();
2661  }
2662 
2681  constexpr value_t type() const noexcept
2682  {
2683  return m_type;
2684  }
2685 
2711  constexpr bool is_primitive() const noexcept
2712  {
2713  return is_null() or is_string() or is_boolean() or is_number();
2714  }
2715 
2738  constexpr bool is_structured() const noexcept
2739  {
2740  return is_array() or is_object();
2741  }
2742 
2760  constexpr bool is_null() const noexcept
2761  {
2762  return m_type == value_t::null;
2763  }
2764 
2782  constexpr bool is_boolean() const noexcept
2783  {
2784  return m_type == value_t::boolean;
2785  }
2786 
2812  constexpr bool is_number() const noexcept
2813  {
2814  return is_number_integer() or is_number_float();
2815  }
2816 
2841  constexpr bool is_number_integer() const noexcept
2842  {
2843  return m_type == value_t::number_integer or m_type == value_t::number_unsigned;
2844  }
2845 
2869  constexpr bool is_number_unsigned() const noexcept
2870  {
2871  return m_type == value_t::number_unsigned;
2872  }
2873 
2897  constexpr bool is_number_float() const noexcept
2898  {
2899  return m_type == value_t::number_float;
2900  }
2901 
2919  constexpr bool is_object() const noexcept
2920  {
2921  return m_type == value_t::object;
2922  }
2923 
2941  constexpr bool is_array() const noexcept
2942  {
2943  return m_type == value_t::array;
2944  }
2945 
2963  constexpr bool is_string() const noexcept
2964  {
2965  return m_type == value_t::string;
2966  }
2967 
2990  constexpr bool is_discarded() const noexcept
2991  {
2992  return m_type == value_t::discarded;
2993  }
2994 
3013  constexpr operator value_t() const noexcept
3014  {
3015  return m_type;
3016  }
3017 
3019 
3020  private:
3022  // value access //
3024 
3026  boolean_t get_impl(boolean_t* /*unused*/) const
3027  {
3028  if (is_boolean())
3029  {
3030  return m_value.boolean;
3031  }
3032 
3033  JSON_THROW(std::domain_error("type must be boolean, but is " + type_name()));
3034  }
3035 
3037  object_t* get_impl_ptr(object_t* /*unused*/) noexcept
3038  {
3039  return is_object() ? m_value.object : nullptr;
3040  }
3041 
3043  constexpr const object_t* get_impl_ptr(const object_t* /*unused*/) const noexcept
3044  {
3045  return is_object() ? m_value.object : nullptr;
3046  }
3047 
3049  array_t* get_impl_ptr(array_t* /*unused*/) noexcept
3050  {
3051  return is_array() ? m_value.array : nullptr;
3052  }
3053 
3055  constexpr const array_t* get_impl_ptr(const array_t* /*unused*/) const noexcept
3056  {
3057  return is_array() ? m_value.array : nullptr;
3058  }
3059 
3061  string_t* get_impl_ptr(string_t* /*unused*/) noexcept
3062  {
3063  return is_string() ? m_value.string : nullptr;
3064  }
3065 
3067  constexpr const string_t* get_impl_ptr(const string_t* /*unused*/) const noexcept
3068  {
3069  return is_string() ? m_value.string : nullptr;
3070  }
3071 
3073  boolean_t* get_impl_ptr(boolean_t* /*unused*/) noexcept
3074  {
3075  return is_boolean() ? &m_value.boolean : nullptr;
3076  }
3077 
3079  constexpr const boolean_t* get_impl_ptr(const boolean_t* /*unused*/) const noexcept
3080  {
3081  return is_boolean() ? &m_value.boolean : nullptr;
3082  }
3083 
3085  number_integer_t* get_impl_ptr(number_integer_t* /*unused*/) noexcept
3086  {
3087  return is_number_integer() ? &m_value.number_integer : nullptr;
3088  }
3089 
3091  constexpr const number_integer_t* get_impl_ptr(const number_integer_t* /*unused*/) const noexcept
3092  {
3093  return is_number_integer() ? &m_value.number_integer : nullptr;
3094  }
3095 
3097  number_unsigned_t* get_impl_ptr(number_unsigned_t* /*unused*/) noexcept
3098  {
3099  return is_number_unsigned() ? &m_value.number_unsigned : nullptr;
3100  }
3101 
3103  constexpr const number_unsigned_t* get_impl_ptr(const number_unsigned_t* /*unused*/) const noexcept
3104  {
3105  return is_number_unsigned() ? &m_value.number_unsigned : nullptr;
3106  }
3107 
3109  number_float_t* get_impl_ptr(number_float_t* /*unused*/) noexcept
3110  {
3111  return is_number_float() ? &m_value.number_float : nullptr;
3112  }
3113 
3115  constexpr const number_float_t* get_impl_ptr(const number_float_t* /*unused*/) const noexcept
3116  {
3117  return is_number_float() ? &m_value.number_float : nullptr;
3118  }
3119 
3131  template<typename ReferenceType, typename ThisType>
3132  static ReferenceType get_ref_impl(ThisType& obj)
3133  {
3134  // helper type
3135  using PointerType = typename std::add_pointer<ReferenceType>::type;
3136 
3137  // delegate the call to get_ptr<>()
3138  auto ptr = obj.template get_ptr<PointerType>();
3139 
3140  if (ptr != nullptr)
3141  {
3142  return *ptr;
3143  }
3144 
3145  JSON_THROW(std::domain_error("incompatible ReferenceType for get_ref, actual type is " +
3146  obj.type_name()));
3147  }
3148 
3149  public:
3153 
3168  template <
3169  typename BasicJsonType,
3170  detail::enable_if_t<std::is_same<typename std::remove_const<BasicJsonType>::type,
3171  basic_json_t>::value,
3172  int> = 0 >
3173  basic_json get() const
3174  {
3175  return *this;
3176  }
3177 
3217  template <
3218  typename ValueTypeCV,
3219  typename ValueType = detail::uncvref_t<ValueTypeCV>,
3220  detail::enable_if_t <
3221  not std::is_same<basic_json_t, ValueType>::value and
3222  detail::has_from_json<basic_json_t, ValueType>::value and
3223  not detail::has_non_default_from_json<basic_json_t, ValueType>::value,
3224  int > = 0 >
3225  ValueType get() const noexcept(noexcept(
3226  JSONSerializer<ValueType>::from_json(std::declval<const basic_json_t&>(), std::declval<ValueType&>())))
3227  {
3228  // we cannot static_assert on ValueTypeCV being non-const, because
3229  // there is support for get<const basic_json_t>(), which is why we
3230  // still need the uncvref
3231  static_assert(not std::is_reference<ValueTypeCV>::value,
3232  "get() cannot be used with reference types, you might want to use get_ref()");
3233  static_assert(std::is_default_constructible<ValueType>::value,
3234  "types must be DefaultConstructible when used with get()");
3235 
3236  ValueType ret;
3237  JSONSerializer<ValueType>::from_json(*this, ret);
3238  return ret;
3239  }
3240 
3272  template <
3273  typename ValueTypeCV,
3274  typename ValueType = detail::uncvref_t<ValueTypeCV>,
3275  detail::enable_if_t<not std::is_same<basic_json_t, ValueType>::value and
3276  detail::has_non_default_from_json<basic_json_t,
3277  ValueType>::value, int> = 0 >
3278  ValueType get() const noexcept(noexcept(
3279  JSONSerializer<ValueTypeCV>::from_json(std::declval<const basic_json_t&>())))
3280  {
3281  static_assert(not std::is_reference<ValueTypeCV>::value,
3282  "get() cannot be used with reference types, you might want to use get_ref()");
3283  return JSONSerializer<ValueTypeCV>::from_json(*this);
3284  }
3285 
3313  template<typename PointerType, typename std::enable_if<
3314  std::is_pointer<PointerType>::value, int>::type = 0>
3315  PointerType get() noexcept
3316  {
3317  // delegate the call to get_ptr
3318  return get_ptr<PointerType>();
3319  }
3320 
3325  template<typename PointerType, typename std::enable_if<
3326  std::is_pointer<PointerType>::value, int>::type = 0>
3327  constexpr const PointerType get() const noexcept
3328  {
3329  // delegate the call to get_ptr
3330  return get_ptr<PointerType>();
3331  }
3332 
3359  template<typename PointerType, typename std::enable_if<
3360  std::is_pointer<PointerType>::value, int>::type = 0>
3361  PointerType get_ptr() noexcept
3362  {
3363  // get the type of the PointerType (remove pointer and const)
3364  using pointee_t = typename std::remove_const<typename
3365  std::remove_pointer<typename
3366  std::remove_const<PointerType>::type>::type>::type;
3367  // make sure the type matches the allowed types
3368  static_assert(
3369  std::is_same<object_t, pointee_t>::value
3370  or std::is_same<array_t, pointee_t>::value
3371  or std::is_same<string_t, pointee_t>::value
3372  or std::is_same<boolean_t, pointee_t>::value
3373  or std::is_same<number_integer_t, pointee_t>::value
3374  or std::is_same<number_unsigned_t, pointee_t>::value
3375  or std::is_same<number_float_t, pointee_t>::value
3376  , "incompatible pointer type");
3377 
3378  // delegate the call to get_impl_ptr<>()
3379  return get_impl_ptr(static_cast<PointerType>(nullptr));
3380  }
3381 
3386  template<typename PointerType, typename std::enable_if<
3387  std::is_pointer<PointerType>::value and
3388  std::is_const<typename std::remove_pointer<PointerType>::type>::value, int>::type = 0>
3389  constexpr const PointerType get_ptr() const noexcept
3390  {
3391  // get the type of the PointerType (remove pointer and const)
3392  using pointee_t = typename std::remove_const<typename
3393  std::remove_pointer<typename
3394  std::remove_const<PointerType>::type>::type>::type;
3395  // make sure the type matches the allowed types
3396  static_assert(
3397  std::is_same<object_t, pointee_t>::value
3398  or std::is_same<array_t, pointee_t>::value
3399  or std::is_same<string_t, pointee_t>::value
3400  or std::is_same<boolean_t, pointee_t>::value
3401  or std::is_same<number_integer_t, pointee_t>::value
3402  or std::is_same<number_unsigned_t, pointee_t>::value
3403  or std::is_same<number_float_t, pointee_t>::value
3404  , "incompatible pointer type");
3405 
3406  // delegate the call to get_impl_ptr<>() const
3407  return get_impl_ptr(static_cast<const PointerType>(nullptr));
3408  }
3409 
3436  template<typename ReferenceType, typename std::enable_if<
3437  std::is_reference<ReferenceType>::value, int>::type = 0>
3438  ReferenceType get_ref()
3439  {
3440  // delegate call to get_ref_impl
3441  return get_ref_impl<ReferenceType>(*this);
3442  }
3443 
3448  template<typename ReferenceType, typename std::enable_if<
3449  std::is_reference<ReferenceType>::value and
3450  std::is_const<typename std::remove_reference<ReferenceType>::type>::value, int>::type = 0>
3451  ReferenceType get_ref() const
3452  {
3453  // delegate call to get_ref_impl
3454  return get_ref_impl<ReferenceType>(*this);
3455  }
3456 
3485  template < typename ValueType, typename std::enable_if <
3486  not std::is_pointer<ValueType>::value and
3487  not std::is_same<ValueType, typename string_t::value_type>::value
3488 #ifndef _MSC_VER // fix for issue #167 operator<< ambiguity under VS2015
3489  and not std::is_same<ValueType, std::initializer_list<typename string_t::value_type>>::value
3490 #endif
3491  , int >::type = 0 >
3492  operator ValueType() const
3493  {
3494  // delegate the call to get<>() const
3495  return get<ValueType>();
3496  }
3497 
3499 
3500 
3502  // element access //
3504 
3508 
3532  {
3533  // at only works for arrays
3534  if (is_array())
3535  {
3536  JSON_TRY
3537  {
3538  return m_value.array->at(idx);
3539  }
3540  JSON_CATCH (std::out_of_range&)
3541  {
3542  // create better exception explanation
3543  JSON_THROW(std::out_of_range("array index " + std::to_string(idx) + " is out of range"));
3544  }
3545  }
3546  else
3547  {
3548  JSON_THROW(std::domain_error("cannot use at() with " + type_name()));
3549  }
3550  }
3551 
3575  {
3576  // at only works for arrays
3577  if (is_array())
3578  {
3579  JSON_TRY
3580  {
3581  return m_value.array->at(idx);
3582  }
3583  JSON_CATCH (std::out_of_range&)
3584  {
3585  // create better exception explanation
3586  JSON_THROW(std::out_of_range("array index " + std::to_string(idx) + " is out of range"));
3587  }
3588  }
3589  else
3590  {
3591  JSON_THROW(std::domain_error("cannot use at() with " + type_name()));
3592  }
3593  }
3594 
3621  reference at(const typename object_t::key_type& key)
3622  {
3623  // at only works for objects
3624  if (is_object())
3625  {
3626  JSON_TRY
3627  {
3628  return m_value.object->at(key);
3629  }
3630  JSON_CATCH (std::out_of_range&)
3631  {
3632  // create better exception explanation
3633  JSON_THROW(std::out_of_range("key '" + key + "' not found"));
3634  }
3635  }
3636  else
3637  {
3638  JSON_THROW(std::domain_error("cannot use at() with " + type_name()));
3639  }
3640  }
3641 
3668  const_reference at(const typename object_t::key_type& key) const
3669  {
3670  // at only works for objects
3671  if (is_object())
3672  {
3673  JSON_TRY
3674  {
3675  return m_value.object->at(key);
3676  }
3677  JSON_CATCH (std::out_of_range&)
3678  {
3679  // create better exception explanation
3680  JSON_THROW(std::out_of_range("key '" + key + "' not found"));
3681  }
3682  }
3683  else
3684  {
3685  JSON_THROW(std::domain_error("cannot use at() with " + type_name()));
3686  }
3687  }
3688 
3715  {
3716  // implicitly convert null value to an empty array
3717  if (is_null())
3718  {
3719  m_type = value_t::array;
3720  m_value.array = create<array_t>();
3721  assert_invariant();
3722  }
3723 
3724  // operator[] only works for arrays
3725  if (is_array())
3726  {
3727  // fill up array with null values if given idx is outside range
3728  if (idx >= m_value.array->size())
3729  {
3730  m_value.array->insert(m_value.array->end(),
3731  idx - m_value.array->size() + 1,
3732  basic_json());
3733  }
3734 
3735  return m_value.array->operator[](idx);
3736  }
3737 
3738  JSON_THROW(std::domain_error("cannot use operator[] with " + type_name()));
3739  }
3740 
3761  {
3762  // const operator[] only works for arrays
3763  if (is_array())
3764  {
3765  return m_value.array->operator[](idx);
3766  }
3767 
3768  JSON_THROW(std::domain_error("cannot use operator[] with " + type_name()));
3769  }
3770 
3798  reference operator[](const typename object_t::key_type& key)
3799  {
3800  // implicitly convert null value to an empty object
3801  if (is_null())
3802  {
3803  m_type = value_t::object;
3804  m_value.object = create<object_t>();
3805  assert_invariant();
3806  }
3807 
3808  // operator[] only works for objects
3809  if (is_object())
3810  {
3811  return m_value.object->operator[](key);
3812  }
3813 
3814  JSON_THROW(std::domain_error("cannot use operator[] with " + type_name()));
3815  }
3816 
3847  const_reference operator[](const typename object_t::key_type& key) const
3848  {
3849  // const operator[] only works for objects
3850  if (is_object())
3851  {
3852  assert(m_value.object->find(key) != m_value.object->end());
3853  return m_value.object->find(key)->second;
3854  }
3855 
3856  JSON_THROW(std::domain_error("cannot use operator[] with " + type_name()));
3857  }
3858 
3886  template<typename T, std::size_t n>
3887  reference operator[](T * (&key)[n])
3888  {
3889  return operator[](static_cast<const T>(key));
3890  }
3891 
3921  template<typename T, std::size_t n>
3922  const_reference operator[](T * (&key)[n]) const
3923  {
3924  return operator[](static_cast<const T>(key));
3925  }
3926 
3954  template<typename T>
3956  {
3957  // implicitly convert null to object
3958  if (is_null())
3959  {
3960  m_type = value_t::object;
3961  m_value = value_t::object;
3962  assert_invariant();
3963  }
3964 
3965  // at only works for objects
3966  if (is_object())
3967  {
3968  return m_value.object->operator[](key);
3969  }
3970 
3971  JSON_THROW(std::domain_error("cannot use operator[] with " + type_name()));
3972  }
3973 
4004  template<typename T>
4006  {
4007  // at only works for objects
4008  if (is_object())
4009  {
4010  assert(m_value.object->find(key) != m_value.object->end());
4011  return m_value.object->find(key)->second;
4012  }
4013 
4014  JSON_THROW(std::domain_error("cannot use operator[] with " + type_name()));
4015  }
4016 
4065  template<class ValueType, typename std::enable_if<
4066  std::is_convertible<basic_json_t, ValueType>::value, int>::type = 0>
4067  ValueType value(const typename object_t::key_type& key, ValueType default_value) const
4068  {
4069  // at only works for objects
4070  if (is_object())
4071  {
4072  // if key is found, return value and given default value otherwise
4073  const auto it = find(key);
4074  if (it != end())
4075  {
4076  return *it;
4077  }
4078 
4079  return default_value;
4080  }
4081  else
4082  {
4083  JSON_THROW(std::domain_error("cannot use value() with " + type_name()));
4084  }
4085  }
4086 
4091  string_t value(const typename object_t::key_type& key, const char* default_value) const
4092  {
4093  return value(key, string_t(default_value));
4094  }
4095 
4137  template<class ValueType, typename std::enable_if<
4138  std::is_convertible<basic_json_t, ValueType>::value, int>::type = 0>
4139  ValueType value(const json_pointer& ptr, ValueType default_value) const
4140  {
4141  // at only works for objects
4142  if (is_object())
4143  {
4144  // if pointer resolves a value, return it or use default value
4145  JSON_TRY
4146  {
4147  return ptr.get_checked(this);
4148  }
4149  JSON_CATCH (std::out_of_range&)
4150  {
4151  return default_value;
4152  }
4153  }
4154 
4155  JSON_THROW(std::domain_error("cannot use value() with " + type_name()));
4156  }
4157 
4162  string_t value(const json_pointer& ptr, const char* default_value) const
4163  {
4164  return value(ptr, string_t(default_value));
4165  }
4166 
4193  {
4194  return *begin();
4195  }
4196 
4201  {
4202  return *cbegin();
4203  }
4204 
4236  {
4237  auto tmp = end();
4238  --tmp;
4239  return *tmp;
4240  }
4241 
4246  {
4247  auto tmp = cend();
4248  --tmp;
4249  return *tmp;
4250  }
4251 
4297  template<class IteratorType, typename std::enable_if<
4298  std::is_same<IteratorType, typename basic_json_t::iterator>::value or
4299  std::is_same<IteratorType, typename basic_json_t::const_iterator>::value, int>::type
4300  = 0>
4301  IteratorType erase(IteratorType pos)
4302  {
4303  // make sure iterator fits the current value
4304  if (this != pos.m_object)
4305  {
4306  JSON_THROW(std::domain_error("iterator does not fit current value"));
4307  }
4308 
4309  IteratorType result = end();
4310 
4311  switch (m_type)
4312  {
4313  case value_t::boolean:
4314  case value_t::number_float:
4315  case value_t::number_integer:
4316  case value_t::number_unsigned:
4317  case value_t::string:
4318  {
4319  if (not pos.m_it.primitive_iterator.is_begin())
4320  {
4321  JSON_THROW(std::out_of_range("iterator out of range"));
4322  }
4323 
4324  if (is_string())
4325  {
4326  AllocatorType<string_t> alloc;
4327  alloc.destroy(m_value.string);
4328  alloc.deallocate(m_value.string, 1);
4329  m_value.string = nullptr;
4330  }
4331 
4332  m_type = value_t::null;
4333  assert_invariant();
4334  break;
4335  }
4336 
4337  case value_t::object:
4338  {
4339  result.m_it.object_iterator = m_value.object->erase(pos.m_it.object_iterator);
4340  break;
4341  }
4342 
4343  case value_t::array:
4344  {
4345  result.m_it.array_iterator = m_value.array->erase(pos.m_it.array_iterator);
4346  break;
4347  }
4348 
4349  default:
4350  {
4351  JSON_THROW(std::domain_error("cannot use erase() with " + type_name()));
4352  }
4353  }
4354 
4355  return result;
4356  }
4357 
4404  template<class IteratorType, typename std::enable_if<
4405  std::is_same<IteratorType, typename basic_json_t::iterator>::value or
4406  std::is_same<IteratorType, typename basic_json_t::const_iterator>::value, int>::type
4407  = 0>
4408  IteratorType erase(IteratorType first, IteratorType last)
4409  {
4410  // make sure iterator fits the current value
4411  if (this != first.m_object or this != last.m_object)
4412  {
4413  JSON_THROW(std::domain_error("iterators do not fit current value"));
4414  }
4415 
4416  IteratorType result = end();
4417 
4418  switch (m_type)
4419  {
4420  case value_t::boolean:
4421  case value_t::number_float:
4422  case value_t::number_integer:
4423  case value_t::number_unsigned:
4424  case value_t::string:
4425  {
4426  if (not first.m_it.primitive_iterator.is_begin() or not last.m_it.primitive_iterator.is_end())
4427  {
4428  JSON_THROW(std::out_of_range("iterators out of range"));
4429  }
4430 
4431  if (is_string())
4432  {
4433  AllocatorType<string_t> alloc;
4434  alloc.destroy(m_value.string);
4435  alloc.deallocate(m_value.string, 1);
4436  m_value.string = nullptr;
4437  }
4438 
4439  m_type = value_t::null;
4440  assert_invariant();
4441  break;
4442  }
4443 
4444  case value_t::object:
4445  {
4446  result.m_it.object_iterator = m_value.object->erase(first.m_it.object_iterator,
4447  last.m_it.object_iterator);
4448  break;
4449  }
4450 
4451  case value_t::array:
4452  {
4453  result.m_it.array_iterator = m_value.array->erase(first.m_it.array_iterator,
4454  last.m_it.array_iterator);
4455  break;
4456  }
4457 
4458  default:
4459  {
4460  JSON_THROW(std::domain_error("cannot use erase() with " + type_name()));
4461  }
4462  }
4463 
4464  return result;
4465  }
4466 
4496  size_type erase(const typename object_t::key_type& key)
4497  {
4498  // this erase only works for objects
4499  if (is_object())
4500  {
4501  return m_value.object->erase(key);
4502  }
4503 
4504  JSON_THROW(std::domain_error("cannot use erase() with " + type_name()));
4505  }
4506 
4531  void erase(const size_type idx)
4532  {
4533  // this erase only works for arrays
4534  if (is_array())
4535  {
4536  if (idx >= size())
4537  {
4538  JSON_THROW(std::out_of_range("array index " + std::to_string(idx) + " is out of range"));
4539  }
4540 
4541  m_value.array->erase(m_value.array->begin() + static_cast<difference_type>(idx));
4542  }
4543  else
4544  {
4545  JSON_THROW(std::domain_error("cannot use erase() with " + type_name()));
4546  }
4547  }
4548 
4550 
4551 
4553  // lookup //
4555 
4558 
4581  iterator find(typename object_t::key_type key)
4582  {
4583  auto result = end();
4584 
4585  if (is_object())
4586  {
4587  result.m_it.object_iterator = m_value.object->find(key);
4588  }
4589 
4590  return result;
4591  }
4592 
4597  const_iterator find(typename object_t::key_type key) const
4598  {
4599  auto result = cend();
4600 
4601  if (is_object())
4602  {
4603  result.m_it.object_iterator = m_value.object->find(key);
4604  }
4605 
4606  return result;
4607  }
4608 
4630  size_type count(typename object_t::key_type key) const
4631  {
4632  // return 0 for all nonobject types
4633  return is_object() ? m_value.object->count(key) : 0;
4634  }
4635 
4637 
4638 
4640  // iterators //
4642 
4645 
4670  iterator begin() noexcept
4671  {
4672  iterator result(this);
4673  result.set_begin();
4674  return result;
4675  }
4676 
4680  const_iterator begin() const noexcept
4681  {
4682  return cbegin();
4683  }
4684 
4710  const_iterator cbegin() const noexcept
4711  {
4712  const_iterator result(this);
4713  result.set_begin();
4714  return result;
4715  }
4716 
4741  iterator end() noexcept
4742  {
4743  iterator result(this);
4744  result.set_end();
4745  return result;
4746  }
4747 
4751  const_iterator end() const noexcept
4752  {
4753  return cend();
4754  }
4755 
4781  const_iterator cend() const noexcept
4782  {
4783  const_iterator result(this);
4784  result.set_end();
4785  return result;
4786  }
4787 
4812  {
4813  return reverse_iterator(end());
4814  }
4815 
4820  {
4821  return crbegin();
4822  }
4823 
4849  {
4850  return reverse_iterator(begin());
4851  }
4852 
4856  const_reverse_iterator rend() const noexcept
4857  {
4858  return crend();
4859  }
4860 
4886  {
4887  return const_reverse_iterator(cend());
4888  }
4889 
4915  {
4916  return const_reverse_iterator(cbegin());
4917  }
4918 
4919  private:
4920  // forward declaration
4921  template<typename IteratorType> class iteration_proxy;
4922 
4923  public:
4935  static iteration_proxy<iterator> iterator_wrapper(reference cont)
4936  {
4937  return iteration_proxy<iterator>(cont);
4938  }
4939 
4943  static iteration_proxy<const_iterator> iterator_wrapper(const_reference cont)
4944  {
4945  return iteration_proxy<const_iterator>(cont);
4946  }
4947 
4949 
4950 
4952  // capacity //
4954 
4957 
4995  bool empty() const noexcept
4996  {
4997  switch (m_type)
4998  {
4999  case value_t::null:
5000  {
5001  // null values are empty
5002  return true;
5003  }
5004 
5005  case value_t::array:
5006  {
5007  // delegate call to array_t::empty()
5008  return m_value.array->empty();
5009  }
5010 
5011  case value_t::object:
5012  {
5013  // delegate call to object_t::empty()
5014  return m_value.object->empty();
5015  }
5016 
5017  default:
5018  {
5019  // all other types are nonempty
5020  return false;
5021  }
5022  }
5023  }
5024 
5063  size_type size() const noexcept
5064  {
5065  switch (m_type)
5066  {
5067  case value_t::null:
5068  {
5069  // null values are empty
5070  return 0;
5071  }
5072 
5073  case value_t::array:
5074  {
5075  // delegate call to array_t::size()
5076  return m_value.array->size();
5077  }
5078 
5079  case value_t::object:
5080  {
5081  // delegate call to object_t::size()
5082  return m_value.object->size();
5083  }
5084 
5085  default:
5086  {
5087  // all other types have size 1
5088  return 1;
5089  }
5090  }
5091  }
5092 
5129  size_type max_size() const noexcept
5130  {
5131  switch (m_type)
5132  {
5133  case value_t::array:
5134  {
5135  // delegate call to array_t::max_size()
5136  return m_value.array->max_size();
5137  }
5138 
5139  case value_t::object:
5140  {
5141  // delegate call to object_t::max_size()
5142  return m_value.object->max_size();
5143  }
5144 
5145  default:
5146  {
5147  // all other types have max_size() == size()
5148  return size();
5149  }
5150  }
5151  }
5152 
5154 
5155 
5157  // modifiers //
5159 
5162 
5185  void clear() noexcept
5186  {
5187  switch (m_type)
5188  {
5189  case value_t::number_integer:
5190  {
5191  m_value.number_integer = 0;
5192  break;
5193  }
5194 
5195  case value_t::number_unsigned:
5196  {
5197  m_value.number_unsigned = 0;
5198  break;
5199  }
5200 
5201  case value_t::number_float:
5202  {
5203  m_value.number_float = 0.0;
5204  break;
5205  }
5206 
5207  case value_t::boolean:
5208  {
5209  m_value.boolean = false;
5210  break;
5211  }
5212 
5213  case value_t::string:
5214  {
5215  m_value.string->clear();
5216  break;
5217  }
5218 
5219  case value_t::array:
5220  {
5221  m_value.array->clear();
5222  break;
5223  }
5224 
5225  case value_t::object:
5226  {
5227  m_value.object->clear();
5228  break;
5229  }
5230 
5231  default:
5232  {
5233  break;
5234  }
5235  }
5236  }
5237 
5258  void push_back(basic_json&& val)
5259  {
5260  // push_back only works for null objects or arrays
5261  if (not(is_null() or is_array()))
5262  {
5263  JSON_THROW(std::domain_error("cannot use push_back() with " + type_name()));
5264  }
5265 
5266  // transform null object into an array
5267  if (is_null())
5268  {
5269  m_type = value_t::array;
5270  m_value = value_t::array;
5271  assert_invariant();
5272  }
5273 
5274  // add element to array (move semantics)
5275  m_value.array->push_back(std::move(val));
5276  // invalidate object
5277  val.m_type = value_t::null;
5278  }
5279 
5285  {
5286  push_back(std::move(val));
5287  return *this;
5288  }
5289 
5294  void push_back(const basic_json& val)
5295  {
5296  // push_back only works for null objects or arrays
5297  if (not(is_null() or is_array()))
5298  {
5299  JSON_THROW(std::domain_error("cannot use push_back() with " + type_name()));
5300  }
5301 
5302  // transform null object into an array
5303  if (is_null())
5304  {
5305  m_type = value_t::array;
5306  m_value = value_t::array;
5307  assert_invariant();
5308  }
5309 
5310  // add element to array
5311  m_value.array->push_back(val);
5312  }
5313 
5319  {
5320  push_back(val);
5321  return *this;
5322  }
5323 
5344  void push_back(const typename object_t::value_type& val)
5345  {
5346  // push_back only works for null objects or objects
5347  if (not(is_null() or is_object()))
5348  {
5349  JSON_THROW(std::domain_error("cannot use push_back() with " + type_name()));
5350  }
5351 
5352  // transform null object into an object
5353  if (is_null())
5354  {
5355  m_type = value_t::object;
5356  m_value = value_t::object;
5357  assert_invariant();
5358  }
5359 
5360  // add element to array
5361  m_value.object->insert(val);
5362  }
5363 
5368  reference operator+=(const typename object_t::value_type& val)
5369  {
5370  push_back(val);
5371  return *this;
5372  }
5373 
5399  void push_back(std::initializer_list<basic_json> init)
5400  {
5401  if (is_object() and init.size() == 2 and init.begin()->is_string())
5402  {
5403  const string_t key = *init.begin();
5404  push_back(typename object_t::value_type(key, *(init.begin() + 1)));
5405  }
5406  else
5407  {
5408  push_back(basic_json(init));
5409  }
5410  }
5411 
5416  reference operator+=(std::initializer_list<basic_json> init)
5417  {
5418  push_back(init);
5419  return *this;
5420  }
5421 
5443  template<class... Args>
5444  void emplace_back(Args&& ... args)
5445  {
5446  // emplace_back only works for null objects or arrays
5447  if (not(is_null() or is_array()))
5448  {
5449  JSON_THROW(std::domain_error("cannot use emplace_back() with " + type_name()));
5450  }
5451 
5452  // transform null object into an array
5453  if (is_null())
5454  {
5455  m_type = value_t::array;
5456  m_value = value_t::array;
5457  assert_invariant();
5458  }
5459 
5460  // add element to array (perfect forwarding)
5461  m_value.array->emplace_back(std::forward<Args>(args)...);
5462  }
5463 
5491  template<class... Args>
5492  std::pair<iterator, bool> emplace(Args&& ... args)
5493  {
5494  // emplace only works for null objects or arrays
5495  if (not(is_null() or is_object()))
5496  {
5497  JSON_THROW(std::domain_error("cannot use emplace() with " + type_name()));
5498  }
5499 
5500  // transform null object into an object
5501  if (is_null())
5502  {
5503  m_type = value_t::object;
5504  m_value = value_t::object;
5505  assert_invariant();
5506  }
5507 
5508  // add element to array (perfect forwarding)
5509  auto res = m_value.object->emplace(std::forward<Args>(args)...);
5510  // create result iterator and set iterator to the result of emplace
5511  auto it = begin();
5512  it.m_it.object_iterator = res.first;
5513 
5514  // return pair of iterator and boolean
5515  return {it, res.second};
5516  }
5517 
5541  {
5542  // insert only works for arrays
5543  if (is_array())
5544  {
5545  // check if iterator pos fits to this JSON value
5546  if (pos.m_object != this)
5547  {
5548  JSON_THROW(std::domain_error("iterator does not fit current value"));
5549  }
5550 
5551  // insert to array and return iterator
5552  iterator result(this);
5553  result.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator, val);
5554  return result;
5555  }
5556 
5557  JSON_THROW(std::domain_error("cannot use insert() with " + type_name()));
5558  }
5559 
5565  {
5566  return insert(pos, val);
5567  }
5568 
5594  {
5595  // insert only works for arrays
5596  if (is_array())
5597  {
5598  // check if iterator pos fits to this JSON value
5599  if (pos.m_object != this)
5600  {
5601  JSON_THROW(std::domain_error("iterator does not fit current value"));
5602  }
5603 
5604  // insert to array and return iterator
5605  iterator result(this);
5606  result.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator, cnt, val);
5607  return result;
5608  }
5609 
5610  JSON_THROW(std::domain_error("cannot use insert() with " + type_name()));
5611  }
5612 
5644  {
5645  // insert only works for arrays
5646  if (not is_array())
5647  {
5648  JSON_THROW(std::domain_error("cannot use insert() with " + type_name()));
5649  }
5650 
5651  // check if iterator pos fits to this JSON value
5652  if (pos.m_object != this)
5653  {
5654  JSON_THROW(std::domain_error("iterator does not fit current value"));
5655  }
5656 
5657  // check if range iterators belong to the same JSON object
5658  if (first.m_object != last.m_object)
5659  {
5660  JSON_THROW(std::domain_error("iterators do not fit"));
5661  }
5662 
5663  if (first.m_object == this or last.m_object == this)
5664  {
5665  JSON_THROW(std::domain_error("passed iterators may not belong to container"));
5666  }
5667 
5668  // insert to array and return iterator
5669  iterator result(this);
5670  result.m_it.array_iterator = m_value.array->insert(
5671  pos.m_it.array_iterator,
5672  first.m_it.array_iterator,
5673  last.m_it.array_iterator);
5674  return result;
5675  }
5676 
5701  iterator insert(const_iterator pos, std::initializer_list<basic_json> ilist)
5702  {
5703  // insert only works for arrays
5704  if (not is_array())
5705  {
5706  JSON_THROW(std::domain_error("cannot use insert() with " + type_name()));
5707  }
5708 
5709  // check if iterator pos fits to this JSON value
5710  if (pos.m_object != this)
5711  {
5712  JSON_THROW(std::domain_error("iterator does not fit current value"));
5713  }
5714 
5715  // insert to array and return iterator
5716  iterator result(this);
5717  result.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator, ilist);
5718  return result;
5719  }
5720 
5738  void swap(reference other) noexcept (
5739  std::is_nothrow_move_constructible<value_t>::value and
5740  std::is_nothrow_move_assignable<value_t>::value and
5741  std::is_nothrow_move_constructible<json_value>::value and
5742  std::is_nothrow_move_assignable<json_value>::value
5743  )
5744  {
5745  std::swap(m_type, other.m_type);
5746  std::swap(m_value, other.m_value);
5747  assert_invariant();
5748  }
5749 
5770  void swap(array_t& other)
5771  {
5772  // swap only works for arrays
5773  if (is_array())
5774  {
5775  std::swap(*(m_value.array), other);
5776  }
5777  else
5778  {
5779  JSON_THROW(std::domain_error("cannot use swap() with " + type_name()));
5780  }
5781  }
5782 
5803  void swap(object_t& other)
5804  {
5805  // swap only works for objects
5806  if (is_object())
5807  {
5808  std::swap(*(m_value.object), other);
5809  }
5810  else
5811  {
5812  JSON_THROW(std::domain_error("cannot use swap() with " + type_name()));
5813  }
5814  }
5815 
5836  void swap(string_t& other)
5837  {
5838  // swap only works for strings
5839  if (is_string())
5840  {
5841  std::swap(*(m_value.string), other);
5842  }
5843  else
5844  {
5845  JSON_THROW(std::domain_error("cannot use swap() with " + type_name()));
5846  }
5847  }
5848 
5850 
5851  public:
5853  // lexicographical comparison operators //
5855 
5858 
5882  friend bool operator==(const_reference lhs, const_reference rhs) noexcept
5883  {
5884  const auto lhs_type = lhs.type();
5885  const auto rhs_type = rhs.type();
5886 
5887  if (lhs_type == rhs_type)
5888  {
5889  switch (lhs_type)
5890  {
5891  case value_t::array:
5892  {
5893  return *lhs.m_value.array == *rhs.m_value.array;
5894  }
5895  case value_t::object:
5896  {
5897  return *lhs.m_value.object == *rhs.m_value.object;
5898  }
5899  case value_t::null:
5900  {
5901  return true;
5902  }
5903  case value_t::string:
5904  {
5905  return *lhs.m_value.string == *rhs.m_value.string;
5906  }
5907  case value_t::boolean:
5908  {
5909  return lhs.m_value.boolean == rhs.m_value.boolean;
5910  }
5911  case value_t::number_integer:
5912  {
5913  return lhs.m_value.number_integer == rhs.m_value.number_integer;
5914  }
5915  case value_t::number_unsigned:
5916  {
5917  return lhs.m_value.number_unsigned == rhs.m_value.number_unsigned;
5918  }
5919  case value_t::number_float:
5920  {
5921  return lhs.m_value.number_float == rhs.m_value.number_float;
5922  }
5923  default:
5924  {
5925  return false;
5926  }
5927  }
5928  }
5929  else if (lhs_type == value_t::number_integer and rhs_type == value_t::number_float)
5930  {
5931  return static_cast<number_float_t>(lhs.m_value.number_integer) == rhs.m_value.number_float;
5932  }
5933  else if (lhs_type == value_t::number_float and rhs_type == value_t::number_integer)
5934  {
5935  return lhs.m_value.number_float == static_cast<number_float_t>(rhs.m_value.number_integer);
5936  }
5937  else if (lhs_type == value_t::number_unsigned and rhs_type == value_t::number_float)
5938  {
5939  return static_cast<number_float_t>(lhs.m_value.number_unsigned) == rhs.m_value.number_float;
5940  }
5941  else if (lhs_type == value_t::number_float and rhs_type == value_t::number_unsigned)
5942  {
5943  return lhs.m_value.number_float == static_cast<number_float_t>(rhs.m_value.number_unsigned);
5944  }
5945  else if (lhs_type == value_t::number_unsigned and rhs_type == value_t::number_integer)
5946  {
5947  return static_cast<number_integer_t>(lhs.m_value.number_unsigned) == rhs.m_value.number_integer;
5948  }
5949  else if (lhs_type == value_t::number_integer and rhs_type == value_t::number_unsigned)
5950  {
5951  return lhs.m_value.number_integer == static_cast<number_integer_t>(rhs.m_value.number_unsigned);
5952  }
5953 
5954  return false;
5955  }
5956 
5961  template<typename ScalarType, typename std::enable_if<
5962  std::is_scalar<ScalarType>::value, int>::type = 0>
5963  friend bool operator==(const_reference lhs, const ScalarType rhs) noexcept
5964  {
5965  return (lhs == basic_json(rhs));
5966  }
5967 
5972  template<typename ScalarType, typename std::enable_if<
5973  std::is_scalar<ScalarType>::value, int>::type = 0>
5974  friend bool operator==(const ScalarType lhs, const_reference rhs) noexcept
5975  {
5976  return (basic_json(lhs) == rhs);
5977  }
5978 
5995  friend bool operator!=(const_reference lhs, const_reference rhs) noexcept
5996  {
5997  return not (lhs == rhs);
5998  }
5999 
6004  template<typename ScalarType, typename std::enable_if<
6005  std::is_scalar<ScalarType>::value, int>::type = 0>
6006  friend bool operator!=(const_reference lhs, const ScalarType rhs) noexcept
6007  {
6008  return (lhs != basic_json(rhs));
6009  }
6010 
6015  template<typename ScalarType, typename std::enable_if<
6016  std::is_scalar<ScalarType>::value, int>::type = 0>
6017  friend bool operator!=(const ScalarType lhs, const_reference rhs) noexcept
6018  {
6019  return (basic_json(lhs) != rhs);
6020  }
6021 
6046  friend bool operator<(const_reference lhs, const_reference rhs) noexcept
6047  {
6048  const auto lhs_type = lhs.type();
6049  const auto rhs_type = rhs.type();
6050 
6051  if (lhs_type == rhs_type)
6052  {
6053  switch (lhs_type)
6054  {
6055  case value_t::array:
6056  {
6057  return *lhs.m_value.array < *rhs.m_value.array;
6058  }
6059  case value_t::object:
6060  {
6061  return *lhs.m_value.object < *rhs.m_value.object;
6062  }
6063  case value_t::null:
6064  {
6065  return false;
6066  }
6067  case value_t::string:
6068  {
6069  return *lhs.m_value.string < *rhs.m_value.string;
6070  }
6071  case value_t::boolean:
6072  {
6073  return lhs.m_value.boolean < rhs.m_value.boolean;
6074  }
6075  case value_t::number_integer:
6076  {
6077  return lhs.m_value.number_integer < rhs.m_value.number_integer;
6078  }
6079  case value_t::number_unsigned:
6080  {
6081  return lhs.m_value.number_unsigned < rhs.m_value.number_unsigned;
6082  }
6083  case value_t::number_float:
6084  {
6085  return lhs.m_value.number_float < rhs.m_value.number_float;
6086  }
6087  default:
6088  {
6089  return false;
6090  }
6091  }
6092  }
6093  else if (lhs_type == value_t::number_integer and rhs_type == value_t::number_float)
6094  {
6095  return static_cast<number_float_t>(lhs.m_value.number_integer) < rhs.m_value.number_float;
6096  }
6097  else if (lhs_type == value_t::number_float and rhs_type == value_t::number_integer)
6098  {
6099  return lhs.m_value.number_float < static_cast<number_float_t>(rhs.m_value.number_integer);
6100  }
6101  else if (lhs_type == value_t::number_unsigned and rhs_type == value_t::number_float)
6102  {
6103  return static_cast<number_float_t>(lhs.m_value.number_unsigned) < rhs.m_value.number_float;
6104  }
6105  else if (lhs_type == value_t::number_float and rhs_type == value_t::number_unsigned)
6106  {
6107  return lhs.m_value.number_float < static_cast<number_float_t>(rhs.m_value.number_unsigned);
6108  }
6109  else if (lhs_type == value_t::number_integer and rhs_type == value_t::number_unsigned)
6110  {
6111  return lhs.m_value.number_integer < static_cast<number_integer_t>(rhs.m_value.number_unsigned);
6112  }
6113  else if (lhs_type == value_t::number_unsigned and rhs_type == value_t::number_integer)
6114  {
6115  return static_cast<number_integer_t>(lhs.m_value.number_unsigned) < rhs.m_value.number_integer;
6116  }
6117 
6118  // We only reach this line if we cannot compare values. In that case,
6119  // we compare types. Note we have to call the operator explicitly,
6120  // because MSVC has problems otherwise.
6121  return operator<(lhs_type, rhs_type);
6122  }
6123 
6141  friend bool operator<=(const_reference lhs, const_reference rhs) noexcept
6142  {
6143  return not (rhs < lhs);
6144  }
6145 
6163  friend bool operator>(const_reference lhs, const_reference rhs) noexcept
6164  {
6165  return not (lhs <= rhs);
6166  }
6167 
6185  friend bool operator>=(const_reference lhs, const_reference rhs) noexcept
6186  {
6187  return not (lhs < rhs);
6188  }
6189 
6191 
6192 
6194  // serialization //
6196 
6199 
6222  friend std::ostream& operator<<(std::ostream& o, const basic_json& j)
6223  {
6224  // read width member and use it as indentation parameter if nonzero
6225  const bool pretty_print = (o.width() > 0);
6226  const auto indentation = (pretty_print ? o.width() : 0);
6227 
6228  // reset width to 0 for subsequent calls to this stream
6229  o.width(0);
6230 
6231  // do the actual serialization
6232  j.dump(o, pretty_print, static_cast<unsigned int>(indentation));
6233 
6234  return o;
6235  }
6236 
6241  friend std::ostream& operator>>(const basic_json& j, std::ostream& o)
6242  {
6243  return o << j;
6244  }
6245 
6247 
6248 
6250  // deserialization //
6252 
6255 
6283  template<class T, std::size_t N>
6284  static basic_json parse(T (&array)[N],
6285  const parser_callback_t cb = nullptr)
6286  {
6287  // delegate the call to the iterator-range parse overload
6288  return parse(std::begin(array), std::end(array), cb);
6289  }
6290 
6318  template<typename CharT, typename std::enable_if<
6319  std::is_pointer<CharT>::value and
6320  std::is_integral<typename std::remove_pointer<CharT>::type>::value and
6321  sizeof(typename std::remove_pointer<CharT>::type) == 1, int>::type = 0>
6322  static basic_json parse(const CharT s,
6323  const parser_callback_t cb = nullptr)
6324  {
6325  return parser(reinterpret_cast<const char*>(s), cb).parse();
6326  }
6327 
6352  static basic_json parse(std::istream& i,
6353  const parser_callback_t cb = nullptr)
6354  {
6355  return parser(i, cb).parse();
6356  }
6357 
6361  static basic_json parse(std::istream&& i,
6362  const parser_callback_t cb = nullptr)
6363  {
6364  return parser(i, cb).parse();
6365  }
6366 
6408  template<class IteratorType, typename std::enable_if<
6409  std::is_base_of<
6410  std::random_access_iterator_tag,
6411  typename std::iterator_traits<IteratorType>::iterator_category>::value, int>::type = 0>
6412  static basic_json parse(IteratorType first, IteratorType last,
6413  const parser_callback_t cb = nullptr)
6414  {
6415  // assertion to check that the iterator range is indeed contiguous,
6416  // see http://stackoverflow.com/a/35008842/266378 for more discussion
6417  assert(std::accumulate(first, last, std::pair<bool, int>(true, 0),
6418  [&first](std::pair<bool, int> res, decltype(*first) val)
6419  {
6420  res.first &= (val == *(std::next(std::addressof(*first), res.second++)));
6421  return res;
6422  }).first);
6423 
6424  // assertion to check that each element is 1 byte long
6425  static_assert(sizeof(typename std::iterator_traits<IteratorType>::value_type) == 1,
6426  "each element in the iterator range must have the size of 1 byte");
6427 
6428  // if iterator range is empty, create a parser with an empty string
6429  // to generate "unexpected EOF" error message
6430  if (std::distance(first, last) <= 0)
6431  {
6432  return parser("").parse();
6433  }
6434 
6435  return parser(first, last, cb).parse();
6436  }
6437 
6478  template<class ContiguousContainer, typename std::enable_if<
6479  not std::is_pointer<ContiguousContainer>::value and
6480  std::is_base_of<
6481  std::random_access_iterator_tag,
6482  typename std::iterator_traits<decltype(std::begin(std::declval<ContiguousContainer const>()))>::iterator_category>::value
6483  , int>::type = 0>
6484  static basic_json parse(const ContiguousContainer& c,
6485  const parser_callback_t cb = nullptr)
6486  {
6487  // delegate the call to the iterator-range parse overload
6488  return parse(std::begin(c), std::end(c), cb);
6489  }
6490 
6514  friend std::istream& operator<<(basic_json& j, std::istream& i)
6515  {
6516  j = parser(i).parse();
6517  return i;
6518  }
6519 
6524  friend std::istream& operator>>(std::istream& i, basic_json& j)
6525  {
6526  j = parser(i).parse();
6527  return i;
6528  }
6529 
6531 
6533  // binary serialization/deserialization //
6535 
6538 
6539  private:
6545  template<typename T>
6546  static void add_to_vector(std::vector<uint8_t>& vec, size_t bytes, const T number)
6547  {
6548  assert(bytes == 1 or bytes == 2 or bytes == 4 or bytes == 8);
6549 
6550  switch (bytes)
6551  {
6552  case 8:
6553  {
6554  vec.push_back(static_cast<uint8_t>((static_cast<uint64_t>(number) >> 070) & 0xff));
6555  vec.push_back(static_cast<uint8_t>((static_cast<uint64_t>(number) >> 060) & 0xff));
6556  vec.push_back(static_cast<uint8_t>((static_cast<uint64_t>(number) >> 050) & 0xff));
6557  vec.push_back(static_cast<uint8_t>((static_cast<uint64_t>(number) >> 040) & 0xff));
6558  vec.push_back(static_cast<uint8_t>((number >> 030) & 0xff));
6559  vec.push_back(static_cast<uint8_t>((number >> 020) & 0xff));
6560  vec.push_back(static_cast<uint8_t>((number >> 010) & 0xff));
6561  vec.push_back(static_cast<uint8_t>(number & 0xff));
6562  break;
6563  }
6564 
6565  case 4:
6566  {
6567  vec.push_back(static_cast<uint8_t>((number >> 030) & 0xff));
6568  vec.push_back(static_cast<uint8_t>((number >> 020) & 0xff));
6569  vec.push_back(static_cast<uint8_t>((number >> 010) & 0xff));
6570  vec.push_back(static_cast<uint8_t>(number & 0xff));
6571  break;
6572  }
6573 
6574  case 2:
6575  {
6576  vec.push_back(static_cast<uint8_t>((number >> 010) & 0xff));
6577  vec.push_back(static_cast<uint8_t>(number & 0xff));
6578  break;
6579  }
6580 
6581  case 1:
6582  {
6583  vec.push_back(static_cast<uint8_t>(number & 0xff));
6584  break;
6585  }
6586  }
6587  }
6588 
6625  template<typename T>
6626  static T get_from_vector(const std::vector<uint8_t>& vec, const size_t current_index)
6627  {
6628  if (current_index + sizeof(T) + 1 > vec.size())
6629  {
6630  JSON_THROW(std::out_of_range("cannot read " + std::to_string(sizeof(T)) + " bytes from vector"));
6631  }
6632 
6633  T result;
6634  auto* ptr = reinterpret_cast<uint8_t*>(&result);
6635  for (size_t i = 0; i < sizeof(T); ++i)
6636  {
6637  *ptr++ = vec[current_index + sizeof(T) - i];
6638  }
6639  return result;
6640  }
6641 
6652  static void to_msgpack_internal(const basic_json& j, std::vector<uint8_t>& v)
6653  {
6654  switch (j.type())
6655  {
6656  case value_t::null:
6657  {
6658  // nil
6659  v.push_back(0xc0);
6660  break;
6661  }
6662 
6663  case value_t::boolean:
6664  {
6665  // true and false
6666  v.push_back(j.m_value.boolean ? 0xc3 : 0xc2);
6667  break;
6668  }
6669 
6670  case value_t::number_integer:
6671  {
6672  if (j.m_value.number_integer >= 0)
6673  {
6674  // MessagePack does not differentiate between positive
6675  // signed integers and unsigned integers. Therefore, we
6676  // used the code from the value_t::number_unsigned case
6677  // here.
6678  if (j.m_value.number_unsigned < 128)
6679  {
6680  // positive fixnum
6681  add_to_vector(v, 1, j.m_value.number_unsigned);
6682  }
6683  else if (j.m_value.number_unsigned <= std::numeric_limits<uint8_t>::max())
6684  {
6685  // uint 8
6686  v.push_back(0xcc);
6687  add_to_vector(v, 1, j.m_value.number_unsigned);
6688  }
6689  else if (j.m_value.number_unsigned <= std::numeric_limits<uint16_t>::max())
6690  {
6691  // uint 16
6692  v.push_back(0xcd);
6693  add_to_vector(v, 2, j.m_value.number_unsigned);
6694  }
6695  else if (j.m_value.number_unsigned <= std::numeric_limits<uint32_t>::max())
6696  {
6697  // uint 32
6698  v.push_back(0xce);
6699  add_to_vector(v, 4, j.m_value.number_unsigned);
6700  }
6701  else if (j.m_value.number_unsigned <= std::numeric_limits<uint64_t>::max())
6702  {
6703  // uint 64
6704  v.push_back(0xcf);
6705  add_to_vector(v, 8, j.m_value.number_unsigned);
6706  }
6707  }
6708  else
6709  {
6710  if (j.m_value.number_integer >= -32)
6711  {
6712  // negative fixnum
6713  add_to_vector(v, 1, j.m_value.number_integer);
6714  }
6715  else if (j.m_value.number_integer >= std::numeric_limits<int8_t>::min() and j.m_value.number_integer <= std::numeric_limits<int8_t>::max())
6716  {
6717  // int 8
6718  v.push_back(0xd0);
6719  add_to_vector(v, 1, j.m_value.number_integer);
6720  }
6721  else if (j.m_value.number_integer >= std::numeric_limits<int16_t>::min() and j.m_value.number_integer <= std::numeric_limits<int16_t>::max())
6722  {
6723  // int 16
6724  v.push_back(0xd1);
6725  add_to_vector(v, 2, j.m_value.number_integer);
6726  }
6727  else if (j.m_value.number_integer >= std::numeric_limits<int32_t>::min() and j.m_value.number_integer <= std::numeric_limits<int32_t>::max())
6728  {
6729  // int 32
6730  v.push_back(0xd2);
6731  add_to_vector(v, 4, j.m_value.number_integer);
6732  }
6733  else if (j.m_value.number_integer >= std::numeric_limits<int64_t>::min() and j.m_value.number_integer <= std::numeric_limits<int64_t>::max())
6734  {
6735  // int 64
6736  v.push_back(0xd3);
6737  add_to_vector(v, 8, j.m_value.number_integer);
6738  }
6739  }
6740  break;
6741  }
6742 
6743  case value_t::number_unsigned:
6744  {
6745  if (j.m_value.number_unsigned < 128)
6746  {
6747  // positive fixnum
6748  add_to_vector(v, 1, j.m_value.number_unsigned);
6749  }
6750  else if (j.m_value.number_unsigned <= std::numeric_limits<uint8_t>::max())
6751  {
6752  // uint 8
6753  v.push_back(0xcc);
6754  add_to_vector(v, 1, j.m_value.number_unsigned);
6755  }
6756  else if (j.m_value.number_unsigned <= std::numeric_limits<uint16_t>::max())
6757  {
6758  // uint 16
6759  v.push_back(0xcd);
6760  add_to_vector(v, 2, j.m_value.number_unsigned);
6761  }
6762  else if (j.m_value.number_unsigned <= std::numeric_limits<uint32_t>::max())
6763  {
6764  // uint 32
6765  v.push_back(0xce);
6766  add_to_vector(v, 4, j.m_value.number_unsigned);
6767  }
6768  else if (j.m_value.number_unsigned <= std::numeric_limits<uint64_t>::max())
6769  {
6770  // uint 64
6771  v.push_back(0xcf);
6772  add_to_vector(v, 8, j.m_value.number_unsigned);
6773  }
6774  break;
6775  }
6776 
6777  case value_t::number_float:
6778  {
6779  // float 64
6780  v.push_back(0xcb);
6781  const auto* helper = reinterpret_cast<const uint8_t*>(&(j.m_value.number_float));
6782  for (size_t i = 0; i < 8; ++i)
6783  {
6784  v.push_back(helper[7 - i]);
6785  }
6786  break;
6787  }
6788 
6789  case value_t::string:
6790  {
6791  const auto N = j.m_value.string->size();
6792  if (N <= 31)
6793  {
6794  // fixstr
6795  v.push_back(static_cast<uint8_t>(0xa0 | N));
6796  }
6797  else if (N <= 255)
6798  {
6799  // str 8
6800  v.push_back(0xd9);
6801  add_to_vector(v, 1, N);
6802  }
6803  else if (N <= 65535)
6804  {
6805  // str 16
6806  v.push_back(0xda);
6807  add_to_vector(v, 2, N);
6808  }
6809  else if (N <= 4294967295)
6810  {
6811  // str 32
6812  v.push_back(0xdb);
6813  add_to_vector(v, 4, N);
6814  }
6815 
6816  // append string
6817  std::copy(j.m_value.string->begin(), j.m_value.string->end(),
6818  std::back_inserter(v));
6819  break;
6820  }
6821 
6822  case value_t::array:
6823  {
6824  const auto N = j.m_value.array->size();
6825  if (N <= 15)
6826  {
6827  // fixarray
6828  v.push_back(static_cast<uint8_t>(0x90 | N));
6829  }
6830  else if (N <= 0xffff)
6831  {
6832  // array 16
6833  v.push_back(0xdc);
6834  add_to_vector(v, 2, N);
6835  }
6836  else if (N <= 0xffffffff)
6837  {
6838  // array 32
6839  v.push_back(0xdd);
6840  add_to_vector(v, 4, N);
6841  }
6842 
6843  // append each element
6844  for (const auto& el : *j.m_value.array)
6845  {
6846  to_msgpack_internal(el, v);
6847  }
6848  break;
6849  }
6850 
6851  case value_t::object:
6852  {
6853  const auto N = j.m_value.object->size();
6854  if (N <= 15)
6855  {
6856  // fixmap
6857  v.push_back(static_cast<uint8_t>(0x80 | (N & 0xf)));
6858  }
6859  else if (N <= 65535)
6860  {
6861  // map 16
6862  v.push_back(0xde);
6863  add_to_vector(v, 2, N);
6864  }
6865  else if (N <= 4294967295)
6866  {
6867  // map 32
6868  v.push_back(0xdf);
6869  add_to_vector(v, 4, N);
6870  }
6871 
6872  // append each element
6873  for (const auto& el : *j.m_value.object)
6874  {
6875  to_msgpack_internal(el.first, v);
6876  to_msgpack_internal(el.second, v);
6877  }
6878  break;
6879  }
6880 
6881  default:
6882  {
6883  break;
6884  }
6885  }
6886  }
6887 
6898  static void to_cbor_internal(const basic_json& j, std::vector<uint8_t>& v)
6899  {
6900  switch (j.type())
6901  {
6902  case value_t::null:
6903  {
6904  v.push_back(0xf6);
6905  break;
6906  }
6907 
6908  case value_t::boolean:
6909  {
6910  v.push_back(j.m_value.boolean ? 0xf5 : 0xf4);
6911  break;
6912  }
6913 
6914  case value_t::number_integer:
6915  {
6916  if (j.m_value.number_integer >= 0)
6917  {
6918  // CBOR does not differentiate between positive signed
6919  // integers and unsigned integers. Therefore, we used the
6920  // code from the value_t::number_unsigned case here.
6921  if (j.m_value.number_integer <= 0x17)
6922  {
6923  add_to_vector(v, 1, j.m_value.number_integer);
6924  }
6925  else if (j.m_value.number_integer <= std::numeric_limits<uint8_t>::max())
6926  {
6927  v.push_back(0x18);
6928  // one-byte uint8_t
6929  add_to_vector(v, 1, j.m_value.number_integer);
6930  }
6931  else if (j.m_value.number_integer <= std::numeric_limits<uint16_t>::max())
6932  {
6933  v.push_back(0x19);
6934  // two-byte uint16_t
6935  add_to_vector(v, 2, j.m_value.number_integer);
6936  }
6937  else if (j.m_value.number_integer <= std::numeric_limits<uint32_t>::max())
6938  {
6939  v.push_back(0x1a);
6940  // four-byte uint32_t
6941  add_to_vector(v, 4, j.m_value.number_integer);
6942  }
6943  else
6944  {
6945  v.push_back(0x1b);
6946  // eight-byte uint64_t
6947  add_to_vector(v, 8, j.m_value.number_integer);
6948  }
6949  }
6950  else
6951  {
6952  // The conversions below encode the sign in the first
6953  // byte, and the value is converted to a positive number.
6954  const auto positive_number = -1 - j.m_value.number_integer;
6955  if (j.m_value.number_integer >= -24)
6956  {
6957  v.push_back(static_cast<uint8_t>(0x20 + positive_number));
6958  }
6959  else if (positive_number <= std::numeric_limits<uint8_t>::max())
6960  {
6961  // int 8
6962  v.push_back(0x38);
6963  add_to_vector(v, 1, positive_number);
6964  }
6965  else if (positive_number <= std::numeric_limits<uint16_t>::max())
6966  {
6967  // int 16
6968  v.push_back(0x39);
6969  add_to_vector(v, 2, positive_number);
6970  }
6971  else if (positive_number <= std::numeric_limits<uint32_t>::max())
6972  {
6973  // int 32
6974  v.push_back(0x3a);
6975  add_to_vector(v, 4, positive_number);
6976  }
6977  else
6978  {
6979  // int 64
6980  v.push_back(0x3b);
6981  add_to_vector(v, 8, positive_number);
6982  }
6983  }
6984  break;
6985  }
6986 
6987  case value_t::number_unsigned:
6988  {
6989  if (j.m_value.number_unsigned <= 0x17)
6990  {
6991  v.push_back(static_cast<uint8_t>(j.m_value.number_unsigned));
6992  }
6993  else if (j.m_value.number_unsigned <= 0xff)
6994  {
6995  v.push_back(0x18);
6996  // one-byte uint8_t
6997  add_to_vector(v, 1, j.m_value.number_unsigned);
6998  }
6999  else if (j.m_value.number_unsigned <= 0xffff)
7000  {
7001  v.push_back(0x19);
7002  // two-byte uint16_t
7003  add_to_vector(v, 2, j.m_value.number_unsigned);
7004  }
7005  else if (j.m_value.number_unsigned <= 0xffffffff)
7006  {
7007  v.push_back(0x1a);
7008  // four-byte uint32_t
7009  add_to_vector(v, 4, j.m_value.number_unsigned);
7010  }
7011  else if (j.m_value.number_unsigned <= 0xffffffffffffffff)
7012  {
7013  v.push_back(0x1b);
7014  // eight-byte uint64_t
7015  add_to_vector(v, 8, j.m_value.number_unsigned);
7016  }
7017  break;
7018  }
7019 
7020  case value_t::number_float:
7021  {
7022  // Double-Precision Float
7023  v.push_back(0xfb);
7024  const auto* helper = reinterpret_cast<const uint8_t*>(&(j.m_value.number_float));
7025  for (size_t i = 0; i < 8; ++i)
7026  {
7027  v.push_back(helper[7 - i]);
7028  }
7029  break;
7030  }
7031 
7032  case value_t::string:
7033  {
7034  const auto N = j.m_value.string->size();
7035  if (N <= 0x17)
7036  {
7037  v.push_back(0x60 + static_cast<uint8_t>(N)); // 1 byte for string + size
7038  }
7039  else if (N <= 0xff)
7040  {
7041  v.push_back(0x78); // one-byte uint8_t for N
7042  add_to_vector(v, 1, N);
7043  }
7044  else if (N <= 0xffff)
7045  {
7046  v.push_back(0x79); // two-byte uint16_t for N
7047  add_to_vector(v, 2, N);
7048  }
7049  else if (N <= 0xffffffff)
7050  {
7051  v.push_back(0x7a); // four-byte uint32_t for N
7052  add_to_vector(v, 4, N);
7053  }
7054  // LCOV_EXCL_START
7055  else if (N <= 0xffffffffffffffff)
7056  {
7057  v.push_back(0x7b); // eight-byte uint64_t for N
7058  add_to_vector(v, 8, N);
7059  }
7060  // LCOV_EXCL_STOP
7061 
7062  // append string
7063  std::copy(j.m_value.string->begin(), j.m_value.string->end(),
7064  std::back_inserter(v));
7065  break;
7066  }
7067 
7068  case value_t::array:
7069  {
7070  const auto N = j.m_value.array->size();
7071  if (N <= 0x17)
7072  {
7073  v.push_back(0x80 + static_cast<uint8_t>(N)); // 1 byte for array + size
7074  }
7075  else if (N <= 0xff)
7076  {
7077  v.push_back(0x98); // one-byte uint8_t for N
7078  add_to_vector(v, 1, N);
7079  }
7080  else if (N <= 0xffff)
7081  {
7082  v.push_back(0x99); // two-byte uint16_t for N
7083  add_to_vector(v, 2, N);
7084  }
7085  else if (N <= 0xffffffff)
7086  {
7087  v.push_back(0x9a); // four-byte uint32_t for N
7088  add_to_vector(v, 4, N);
7089  }
7090  // LCOV_EXCL_START
7091  else if (N <= 0xffffffffffffffff)
7092  {
7093  v.push_back(0x9b); // eight-byte uint64_t for N
7094  add_to_vector(v, 8, N);
7095  }
7096  // LCOV_EXCL_STOP
7097 
7098  // append each element
7099  for (const auto& el : *j.m_value.array)
7100  {
7101  to_cbor_internal(el, v);
7102  }
7103  break;
7104  }
7105 
7106  case value_t::object:
7107  {
7108  const auto N = j.m_value.object->size();
7109  if (N <= 0x17)
7110  {
7111  v.push_back(0xa0 + static_cast<uint8_t>(N)); // 1 byte for object + size
7112  }
7113  else if (N <= 0xff)
7114  {
7115  v.push_back(0xb8);
7116  add_to_vector(v, 1, N); // one-byte uint8_t for N
7117  }
7118  else if (N <= 0xffff)
7119  {
7120  v.push_back(0xb9);
7121  add_to_vector(v, 2, N); // two-byte uint16_t for N
7122  }
7123  else if (N <= 0xffffffff)
7124  {
7125  v.push_back(0xba);
7126  add_to_vector(v, 4, N); // four-byte uint32_t for N
7127  }
7128  // LCOV_EXCL_START
7129  else if (N <= 0xffffffffffffffff)
7130  {
7131  v.push_back(0xbb);
7132  add_to_vector(v, 8, N); // eight-byte uint64_t for N
7133  }
7134  // LCOV_EXCL_STOP
7135 
7136  // append each element
7137  for (const auto& el : *j.m_value.object)
7138  {
7139  to_cbor_internal(el.first, v);
7140  to_cbor_internal(el.second, v);
7141  }
7142  break;
7143  }
7144 
7145  default:
7146  {
7147  break;
7148  }
7149  }
7150  }
7151 
7152 
7153  /*
7154  @brief checks if given lengths do not exceed the size of a given vector
7155 
7156  To secure the access to the byte vector during CBOR/MessagePack
7157  deserialization, bytes are copied from the vector into buffers. This
7158  function checks if the number of bytes to copy (@a len) does not exceed
7159  the size @s size of the vector. Additionally, an @a offset is given from
7160  where to start reading the bytes.
7161 
7162  This function checks whether reading the bytes is safe; that is, offset is
7163  a valid index in the vector, offset+len
7164 
7165  @param[in] size size of the byte vector
7166  @param[in] len number of bytes to read
7167  @param[in] offset offset where to start reading
7168 
7169  vec: x x x x x X X X X X
7170  ^ ^ ^
7171  0 offset len
7172 
7173  @throws out_of_range if `len > v.size()`
7174  */
7175  static void check_length(const size_t size, const size_t len, const size_t offset)
7176  {
7177  // simple case: requested length is greater than the vector's length
7178  if (len > size or offset > size)
7179  {
7180  JSON_THROW(std::out_of_range("len out of range"));
7181  }
7182 
7183  // second case: adding offset would result in overflow
7184  if ((size > (std::numeric_limits<size_t>::max() - offset)))
7185  {
7186  JSON_THROW(std::out_of_range("len+offset out of range"));
7187  }
7188 
7189  // last case: reading past the end of the vector
7190  if (len + offset > size)
7191  {
7192  JSON_THROW(std::out_of_range("len+offset out of range"));
7193  }
7194  }
7195 
7210  static basic_json from_msgpack_internal(const std::vector<uint8_t>& v, size_t& idx)
7211  {
7212  // make sure reading 1 byte is safe
7213  check_length(v.size(), 1, idx);
7214 
7215  // store and increment index
7216  const size_t current_idx = idx++;
7217 
7218  if (v[current_idx] <= 0xbf)
7219  {
7220  if (v[current_idx] <= 0x7f) // positive fixint
7221  {
7222  return v[current_idx];
7223  }
7224  if (v[current_idx] <= 0x8f) // fixmap
7225  {
7226  basic_json result = value_t::object;
7227  const size_t len = v[current_idx] & 0x0f;
7228  for (size_t i = 0; i < len; ++i)
7229  {
7230  std::string key = from_msgpack_internal(v, idx);
7231  result[key] = from_msgpack_internal(v, idx);
7232  }
7233  return result;
7234  }
7235  else if (v[current_idx] <= 0x9f) // fixarray
7236  {
7237  basic_json result = value_t::array;
7238  const size_t len = v[current_idx] & 0x0f;
7239  for (size_t i = 0; i < len; ++i)
7240  {
7241  result.push_back(from_msgpack_internal(v, idx));
7242  }
7243  return result;
7244  }
7245  else // fixstr
7246  {
7247  const size_t len = v[current_idx] & 0x1f;
7248  const size_t offset = current_idx + 1;
7249  idx += len; // skip content bytes
7250  check_length(v.size(), len, offset);
7251  return std::string(reinterpret_cast<const char*>(v.data()) + offset, len);
7252  }
7253  }
7254  else if (v[current_idx] >= 0xe0) // negative fixint
7255  {
7256  return static_cast<int8_t>(v[current_idx]);
7257  }
7258  else
7259  {
7260  switch (v[current_idx])
7261  {
7262  case 0xc0: // nil
7263  {
7264  return value_t::null;
7265  }
7266 
7267  case 0xc2: // false
7268  {
7269  return false;
7270  }
7271 
7272  case 0xc3: // true
7273  {
7274  return true;
7275  }
7276 
7277  case 0xca: // float 32
7278  {
7279  // copy bytes in reverse order into the double variable
7280  float res;
7281  for (size_t byte = 0; byte < sizeof(float); ++byte)
7282  {
7283  reinterpret_cast<uint8_t*>(&res)[sizeof(float) - byte - 1] = v.at(current_idx + 1 + byte);
7284  }
7285  idx += sizeof(float); // skip content bytes
7286  return res;
7287  }
7288 
7289  case 0xcb: // float 64
7290  {
7291  // copy bytes in reverse order into the double variable
7292  double res;
7293  for (size_t byte = 0; byte < sizeof(double); ++byte)
7294  {
7295  reinterpret_cast<uint8_t*>(&res)[sizeof(double) - byte - 1] = v.at(current_idx + 1 + byte);
7296  }
7297  idx += sizeof(double); // skip content bytes
7298  return res;
7299  }
7300 
7301  case 0xcc: // uint 8
7302  {
7303  idx += 1; // skip content byte
7304  return get_from_vector<uint8_t>(v, current_idx);
7305  }
7306 
7307  case 0xcd: // uint 16
7308  {
7309  idx += 2; // skip 2 content bytes
7310  return get_from_vector<uint16_t>(v, current_idx);
7311  }
7312 
7313  case 0xce: // uint 32
7314  {
7315  idx += 4; // skip 4 content bytes
7316  return get_from_vector<uint32_t>(v, current_idx);
7317  }
7318 
7319  case 0xcf: // uint 64
7320  {
7321  idx += 8; // skip 8 content bytes
7322  return get_from_vector<uint64_t>(v, current_idx);
7323  }
7324 
7325  case 0xd0: // int 8
7326  {
7327  idx += 1; // skip content byte
7328  return get_from_vector<int8_t>(v, current_idx);
7329  }
7330 
7331  case 0xd1: // int 16
7332  {
7333  idx += 2; // skip 2 content bytes
7334  return get_from_vector<int16_t>(v, current_idx);
7335  }
7336 
7337  case 0xd2: // int 32
7338  {
7339  idx += 4; // skip 4 content bytes
7340  return get_from_vector<int32_t>(v, current_idx);
7341  }
7342 
7343  case 0xd3: // int 64
7344  {
7345  idx += 8; // skip 8 content bytes
7346  return get_from_vector<int64_t>(v, current_idx);
7347  }
7348 
7349  case 0xd9: // str 8
7350  {
7351  const auto len = static_cast<size_t>(get_from_vector<uint8_t>(v, current_idx));
7352  const size_t offset = current_idx + 2;
7353  idx += len + 1; // skip size byte + content bytes
7354  check_length(v.size(), len, offset);
7355  return std::string(reinterpret_cast<const char*>(v.data()) + offset, len);
7356  }
7357 
7358  case 0xda: // str 16
7359  {
7360  const auto len = static_cast<size_t>(get_from_vector<uint16_t>(v, current_idx));
7361  const size_t offset = current_idx + 3;
7362  idx += len + 2; // skip 2 size bytes + content bytes
7363  check_length(v.size(), len, offset);
7364  return std::string(reinterpret_cast<const char*>(v.data()) + offset, len);
7365  }
7366 
7367  case 0xdb: // str 32
7368  {
7369  const auto len = static_cast<size_t>(get_from_vector<uint32_t>(v, current_idx));
7370  const size_t offset = current_idx + 5;
7371  idx += len + 4; // skip 4 size bytes + content bytes
7372  check_length(v.size(), len, offset);
7373  return std::string(reinterpret_cast<const char*>(v.data()) + offset, len);
7374  }
7375 
7376  case 0xdc: // array 16
7377  {
7378  basic_json result = value_t::array;
7379  const auto len = static_cast<size_t>(get_from_vector<uint16_t>(v, current_idx));
7380  idx += 2; // skip 2 size bytes
7381  for (size_t i = 0; i < len; ++i)
7382  {
7383  result.push_back(from_msgpack_internal(v, idx));
7384  }
7385  return result;
7386  }
7387 
7388  case 0xdd: // array 32
7389  {
7390  basic_json result = value_t::array;
7391  const auto len = static_cast<size_t>(get_from_vector<uint32_t>(v, current_idx));
7392  idx += 4; // skip 4 size bytes
7393  for (size_t i = 0; i < len; ++i)
7394  {
7395  result.push_back(from_msgpack_internal(v, idx));
7396  }
7397  return result;
7398  }
7399 
7400  case 0xde: // map 16
7401  {
7402  basic_json result = value_t::object;
7403  const auto len = static_cast<size_t>(get_from_vector<uint16_t>(v, current_idx));
7404  idx += 2; // skip 2 size bytes
7405  for (size_t i = 0; i < len; ++i)
7406  {
7407  std::string key = from_msgpack_internal(v, idx);
7408  result[key] = from_msgpack_internal(v, idx);
7409  }
7410  return result;
7411  }
7412 
7413  case 0xdf: // map 32
7414  {
7415  basic_json result = value_t::object;
7416  const auto len = static_cast<size_t>(get_from_vector<uint32_t>(v, current_idx));
7417  idx += 4; // skip 4 size bytes
7418  for (size_t i = 0; i < len; ++i)
7419  {
7420  std::string key = from_msgpack_internal(v, idx);
7421  result[key] = from_msgpack_internal(v, idx);
7422  }
7423  return result;
7424  }
7425 
7426  default:
7427  {
7428  JSON_THROW(std::invalid_argument("error parsing a msgpack @ " + std::to_string(current_idx) + ": " + std::to_string(static_cast<int>(v[current_idx]))));
7429  }
7430  }
7431  }
7432  }
7433 
7448  static basic_json from_cbor_internal(const std::vector<uint8_t>& v, size_t& idx)
7449  {
7450  // store and increment index
7451  const size_t current_idx = idx++;
7452 
7453  switch (v.at(current_idx))
7454  {
7455  // Integer 0x00..0x17 (0..23)
7456  case 0x00:
7457  case 0x01:
7458  case 0x02:
7459  case 0x03:
7460  case 0x04:
7461  case 0x05:
7462  case 0x06:
7463  case 0x07:
7464  case 0x08:
7465  case 0x09:
7466  case 0x0a:
7467  case 0x0b:
7468  case 0x0c:
7469  case 0x0d:
7470  case 0x0e:
7471  case 0x0f:
7472  case 0x10:
7473  case 0x11:
7474  case 0x12:
7475  case 0x13:
7476  case 0x14:
7477  case 0x15:
7478  case 0x16:
7479  case 0x17:
7480  {
7481  return v[current_idx];
7482  }
7483 
7484  case 0x18: // Unsigned integer (one-byte uint8_t follows)
7485  {
7486  idx += 1; // skip content byte
7487  return get_from_vector<uint8_t>(v, current_idx);
7488  }
7489 
7490  case 0x19: // Unsigned integer (two-byte uint16_t follows)
7491  {
7492  idx += 2; // skip 2 content bytes
7493  return get_from_vector<uint16_t>(v, current_idx);
7494  }
7495 
7496  case 0x1a: // Unsigned integer (four-byte uint32_t follows)
7497  {
7498  idx += 4; // skip 4 content bytes
7499  return get_from_vector<uint32_t>(v, current_idx);
7500  }
7501 
7502  case 0x1b: // Unsigned integer (eight-byte uint64_t follows)
7503  {
7504  idx += 8; // skip 8 content bytes
7505  return get_from_vector<uint64_t>(v, current_idx);
7506  }
7507 
7508  // Negative integer -1-0x00..-1-0x17 (-1..-24)
7509  case 0x20:
7510  case 0x21:
7511  case 0x22:
7512  case 0x23:
7513  case 0x24:
7514  case 0x25:
7515  case 0x26:
7516  case 0x27:
7517  case 0x28:
7518  case 0x29:
7519  case 0x2a:
7520  case 0x2b:
7521  case 0x2c:
7522  case 0x2d:
7523  case 0x2e:
7524  case 0x2f:
7525  case 0x30:
7526  case 0x31:
7527  case 0x32:
7528  case 0x33:
7529  case 0x34:
7530  case 0x35:
7531  case 0x36:
7532  case 0x37:
7533  {
7534  return static_cast<int8_t>(0x20 - 1 - v[current_idx]);
7535  }
7536 
7537  case 0x38: // Negative integer (one-byte uint8_t follows)
7538  {
7539  idx += 1; // skip content byte
7540  // must be uint8_t !
7541  return static_cast<number_integer_t>(-1) - get_from_vector<uint8_t>(v, current_idx);
7542  }
7543 
7544  case 0x39: // Negative integer -1-n (two-byte uint16_t follows)
7545  {
7546  idx += 2; // skip 2 content bytes
7547  return static_cast<number_integer_t>(-1) - get_from_vector<uint16_t>(v, current_idx);
7548  }
7549 
7550  case 0x3a: // Negative integer -1-n (four-byte uint32_t follows)
7551  {
7552  idx += 4; // skip 4 content bytes
7553  return static_cast<number_integer_t>(-1) - get_from_vector<uint32_t>(v, current_idx);
7554  }
7555 
7556  case 0x3b: // Negative integer -1-n (eight-byte uint64_t follows)
7557  {
7558  idx += 8; // skip 8 content bytes
7559  return static_cast<number_integer_t>(-1) - static_cast<number_integer_t>(get_from_vector<uint64_t>(v, current_idx));
7560  }
7561 
7562  // UTF-8 string (0x00..0x17 bytes follow)
7563  case 0x60:
7564  case 0x61:
7565  case 0x62:
7566  case 0x63:
7567  case 0x64:
7568  case 0x65:
7569  case 0x66:
7570  case 0x67:
7571  case 0x68:
7572  case 0x69:
7573  case 0x6a:
7574  case 0x6b:
7575  case 0x6c:
7576  case 0x6d:
7577  case 0x6e:
7578  case 0x6f:
7579  case 0x70:
7580  case 0x71:
7581  case 0x72:
7582  case 0x73:
7583  case 0x74:
7584  case 0x75:
7585  case 0x76:
7586  case 0x77:
7587  {
7588  const auto len = static_cast<size_t>(v[current_idx] - 0x60);
7589  const size_t offset = current_idx + 1;
7590  idx += len; // skip content bytes
7591  check_length(v.size(), len, offset);
7592  return std::string(reinterpret_cast<const char*>(v.data()) + offset, len);
7593  }
7594 
7595  case 0x78: // UTF-8 string (one-byte uint8_t for n follows)
7596  {
7597  const auto len = static_cast<size_t>(get_from_vector<uint8_t>(v, current_idx));
7598  const size_t offset = current_idx + 2;
7599  idx += len + 1; // skip size byte + content bytes
7600  check_length(v.size(), len, offset);
7601  return std::string(reinterpret_cast<const char*>(v.data()) + offset, len);
7602  }
7603 
7604  case 0x79: // UTF-8 string (two-byte uint16_t for n follow)
7605  {
7606  const auto len = static_cast<size_t>(get_from_vector<uint16_t>(v, current_idx));
7607  const size_t offset = current_idx + 3;
7608  idx += len + 2; // skip 2 size bytes + content bytes
7609  check_length(v.size(), len, offset);
7610  return std::string(reinterpret_cast<const char*>(v.data()) + offset, len);
7611  }
7612 
7613  case 0x7a: // UTF-8 string (four-byte uint32_t for n follow)
7614  {
7615  const auto len = static_cast<size_t>(get_from_vector<uint32_t>(v, current_idx));
7616  const size_t offset = current_idx + 5;
7617  idx += len + 4; // skip 4 size bytes + content bytes
7618  check_length(v.size(), len, offset);
7619  return std::string(reinterpret_cast<const char*>(v.data()) + offset, len);
7620  }
7621 
7622  case 0x7b: // UTF-8 string (eight-byte uint64_t for n follow)
7623  {
7624  const auto len = static_cast<size_t>(get_from_vector<uint64_t>(v, current_idx));
7625  const size_t offset = current_idx + 9;
7626  idx += len + 8; // skip 8 size bytes + content bytes
7627  check_length(v.size(), len, offset);
7628  return std::string(reinterpret_cast<const char*>(v.data()) + offset, len);
7629  }
7630 
7631  case 0x7f: // UTF-8 string (indefinite length)
7632  {
7633  std::string result;
7634  while (v.at(idx) != 0xff)
7635  {
7636  string_t s = from_cbor_internal(v, idx);
7637  result += s;
7638  }
7639  // skip break byte (0xFF)
7640  idx += 1;
7641  return result;
7642  }
7643 
7644  // array (0x00..0x17 data items follow)
7645  case 0x80:
7646  case 0x81:
7647  case 0x82:
7648  case 0x83:
7649  case 0x84:
7650  case 0x85:
7651  case 0x86:
7652  case 0x87:
7653  case 0x88:
7654  case 0x89:
7655  case 0x8a:
7656  case 0x8b:
7657  case 0x8c:
7658  case 0x8d:
7659  case 0x8e:
7660  case 0x8f:
7661  case 0x90:
7662  case 0x91:
7663  case 0x92:
7664  case 0x93:
7665  case 0x94:
7666  case 0x95:
7667  case 0x96:
7668  case 0x97:
7669  {
7670  basic_json result = value_t::array;
7671  const auto len = static_cast<size_t>(v[current_idx] - 0x80);
7672  for (size_t i = 0; i < len; ++i)
7673  {
7674  result.push_back(from_cbor_internal(v, idx));
7675  }
7676  return result;
7677  }
7678 
7679  case 0x98: // array (one-byte uint8_t for n follows)
7680  {
7681  basic_json result = value_t::array;
7682  const auto len = static_cast<size_t>(get_from_vector<uint8_t>(v, current_idx));
7683  idx += 1; // skip 1 size byte
7684  for (size_t i = 0; i < len; ++i)
7685  {
7686  result.push_back(from_cbor_internal(v, idx));
7687  }
7688  return result;
7689  }
7690 
7691  case 0x99: // array (two-byte uint16_t for n follow)
7692  {
7693  basic_json result = value_t::array;
7694  const auto len = static_cast<size_t>(get_from_vector<uint16_t>(v, current_idx));
7695  idx += 2; // skip 4 size bytes
7696  for (size_t i = 0; i < len; ++i)
7697  {
7698  result.push_back(from_cbor_internal(v, idx));
7699  }
7700  return result;
7701  }
7702 
7703  case 0x9a: // array (four-byte uint32_t for n follow)
7704  {
7705  basic_json result = value_t::array;
7706  const auto len = static_cast<size_t>(get_from_vector<uint32_t>(v, current_idx));
7707  idx += 4; // skip 4 size bytes
7708  for (size_t i = 0; i < len; ++i)
7709  {
7710  result.push_back(from_cbor_internal(v, idx));
7711  }
7712  return result;
7713  }
7714 
7715  case 0x9b: // array (eight-byte uint64_t for n follow)
7716  {
7717  basic_json result = value_t::array;
7718  const auto len = static_cast<size_t>(get_from_vector<uint64_t>(v, current_idx));
7719  idx += 8; // skip 8 size bytes
7720  for (size_t i = 0; i < len; ++i)
7721  {
7722  result.push_back(from_cbor_internal(v, idx));
7723  }
7724  return result;
7725  }
7726 
7727  case 0x9f: // array (indefinite length)
7728  {
7729  basic_json result = value_t::array;
7730  while (v.at(idx) != 0xff)
7731  {
7732  result.push_back(from_cbor_internal(v, idx));
7733  }
7734  // skip break byte (0xFF)
7735  idx += 1;
7736  return result;
7737  }
7738 
7739  // map (0x00..0x17 pairs of data items follow)
7740  case 0xa0:
7741  case 0xa1:
7742  case 0xa2:
7743  case 0xa3:
7744  case 0xa4:
7745  case 0xa5:
7746  case 0xa6:
7747  case 0xa7:
7748  case 0xa8:
7749  case 0xa9:
7750  case 0xaa:
7751  case 0xab:
7752  case 0xac:
7753  case 0xad:
7754  case 0xae:
7755  case 0xaf:
7756  case 0xb0:
7757  case 0xb1:
7758  case 0xb2:
7759  case 0xb3:
7760  case 0xb4:
7761  case 0xb5:
7762  case 0xb6:
7763  case 0xb7:
7764  {
7765  basic_json result = value_t::object;
7766  const auto len = static_cast<size_t>(v[current_idx] - 0xa0);
7767  for (size_t i = 0; i < len; ++i)
7768  {
7769  std::string key = from_cbor_internal(v, idx);
7770  result[key] = from_cbor_internal(v, idx);
7771  }
7772  return result;
7773  }
7774 
7775  case 0xb8: // map (one-byte uint8_t for n follows)
7776  {
7777  basic_json result = value_t::object;
7778  const auto len = static_cast<size_t>(get_from_vector<uint8_t>(v, current_idx));
7779  idx += 1; // skip 1 size byte
7780  for (size_t i = 0; i < len; ++i)
7781  {
7782  std::string key = from_cbor_internal(v, idx);
7783  result[key] = from_cbor_internal(v, idx);
7784  }
7785  return result;
7786  }
7787 
7788  case 0xb9: // map (two-byte uint16_t for n follow)
7789  {
7790  basic_json result = value_t::object;
7791  const auto len = static_cast<size_t>(get_from_vector<uint16_t>(v, current_idx));
7792  idx += 2; // skip 2 size bytes
7793  for (size_t i = 0; i < len; ++i)
7794  {
7795  std::string key = from_cbor_internal(v, idx);
7796  result[key] = from_cbor_internal(v, idx);
7797  }
7798  return result;
7799  }
7800 
7801  case 0xba: // map (four-byte uint32_t for n follow)
7802  {
7803  basic_json result = value_t::object;
7804  const auto len = static_cast<size_t>(get_from_vector<uint32_t>(v, current_idx));
7805  idx += 4; // skip 4 size bytes
7806  for (size_t i = 0; i < len; ++i)
7807  {
7808  std::string key = from_cbor_internal(v, idx);
7809  result[key] = from_cbor_internal(v, idx);
7810  }
7811  return result;
7812  }
7813 
7814  case 0xbb: // map (eight-byte uint64_t for n follow)
7815  {
7816  basic_json result = value_t::object;
7817  const auto len = static_cast<size_t>(get_from_vector<uint64_t>(v, current_idx));
7818  idx += 8; // skip 8 size bytes
7819  for (size_t i = 0; i < len; ++i)
7820  {
7821  std::string key = from_cbor_internal(v, idx);
7822  result[key] = from_cbor_internal(v, idx);
7823  }
7824  return result;
7825  }
7826 
7827  case 0xbf: // map (indefinite length)
7828  {
7829  basic_json result = value_t::object;
7830  while (v.at(idx) != 0xff)
7831  {
7832  std::string key = from_cbor_internal(v, idx);
7833  result[key] = from_cbor_internal(v, idx);
7834  }
7835  // skip break byte (0xFF)
7836  idx += 1;
7837  return result;
7838  }
7839 
7840  case 0xf4: // false
7841  {
7842  return false;
7843  }
7844 
7845  case 0xf5: // true
7846  {
7847  return true;
7848  }
7849 
7850  case 0xf6: // null
7851  {
7852  return value_t::null;
7853  }
7854 
7855  case 0xf9: // Half-Precision Float (two-byte IEEE 754)
7856  {
7857  idx += 2; // skip two content bytes
7858 
7859  // code from RFC 7049, Appendix D, Figure 3:
7860  // As half-precision floating-point numbers were only added to
7861  // IEEE 754 in 2008, today's programming platforms often still
7862  // only have limited support for them. It is very easy to
7863  // include at least decoding support for them even without such
7864  // support. An example of a small decoder for half-precision
7865  // floating-point numbers in the C language is shown in Fig. 3.
7866  const int half = (v.at(current_idx + 1) << 8) + v.at(current_idx + 2);
7867  const int exp = (half >> 10) & 0x1f;
7868  const int mant = half & 0x3ff;
7869  double val;
7870  if (exp == 0)
7871  {
7872  val = std::ldexp(mant, -24);
7873  }
7874  else if (exp != 31)
7875  {
7876  val = std::ldexp(mant + 1024, exp - 25);
7877  }
7878  else
7879  {
7880  val = mant == 0
7881  ? std::numeric_limits<double>::infinity()
7882  : std::numeric_limits<double>::quiet_NaN();
7883  }
7884  return (half & 0x8000) != 0 ? -val : val;
7885  }
7886 
7887  case 0xfa: // Single-Precision Float (four-byte IEEE 754)
7888  {
7889  // copy bytes in reverse order into the float variable
7890  float res;
7891  for (size_t byte = 0; byte < sizeof(float); ++byte)
7892  {
7893  reinterpret_cast<uint8_t*>(&res)[sizeof(float) - byte - 1] = v.at(current_idx + 1 + byte);
7894  }
7895  idx += sizeof(float); // skip content bytes
7896  return res;
7897  }
7898 
7899  case 0xfb: // Double-Precision Float (eight-byte IEEE 754)
7900  {
7901  // copy bytes in reverse order into the double variable
7902  double res;
7903  for (size_t byte = 0; byte < sizeof(double); ++byte)
7904  {
7905  reinterpret_cast<uint8_t*>(&res)[sizeof(double) - byte - 1] = v.at(current_idx + 1 + byte);
7906  }
7907  idx += sizeof(double); // skip content bytes
7908  return res;
7909  }
7910 
7911  default: // anything else (0xFF is handled inside the other types)
7912  {
7913  JSON_THROW(std::invalid_argument("error parsing a CBOR @ " + std::to_string(current_idx) + ": " + std::to_string(static_cast<int>(v[current_idx]))));
7914  }
7915  }
7916  }
7917 
7918  public:
7941  static std::vector<uint8_t> to_msgpack(const basic_json& j)
7942  {
7943  std::vector<uint8_t> result;
7944  to_msgpack_internal(j, result);
7945  return result;
7946  }
7947 
7974  static basic_json from_msgpack(const std::vector<uint8_t>& v,
7975  const size_t start_index = 0)
7976  {
7977  size_t i = start_index;
7978  return from_msgpack_internal(v, i);
7979  }
7980 
8004  static std::vector<uint8_t> to_cbor(const basic_json& j)
8005  {
8006  std::vector<uint8_t> result;
8007  to_cbor_internal(j, result);
8008  return result;
8009  }
8010 
8037  static basic_json from_cbor(const std::vector<uint8_t>& v,
8038  const size_t start_index = 0)
8039  {
8040  size_t i = start_index;
8041  return from_cbor_internal(v, i);
8042  }
8043 
8045 
8047  // convenience functions //
8049 
8065  std::string type_name() const
8066  {
8067  {
8068  switch (m_type)
8069  {
8070  case value_t::null:
8071  return "null";
8072  case value_t::object:
8073  return "object";
8074  case value_t::array:
8075  return "array";
8076  case value_t::string:
8077  return "string";
8078  case value_t::boolean:
8079  return "boolean";
8080  case value_t::discarded:
8081  return "discarded";
8082  default:
8083  return "number";
8084  }
8085  }
8086  }
8087 
8088  private:
8097  static std::size_t extra_space(const string_t& s) noexcept
8098  {
8099  return std::accumulate(s.begin(), s.end(), size_t{},
8100  [](size_t res, typename string_t::value_type c)
8101  {
8102  switch (c)
8103  {
8104  case '"':
8105  case '\\':
8106  case '\b':
8107  case '\f':
8108  case '\n':
8109  case '\r':
8110  case '\t':
8111  {
8112  // from c (1 byte) to \x (2 bytes)
8113  return res + 1;
8114  }
8115 
8116  default:
8117  {
8118  if (c >= 0x00 and c <= 0x1f)
8119  {
8120  // from c (1 byte) to \uxxxx (6 bytes)
8121  return res + 5;
8122  }
8123 
8124  return res;
8125  }
8126  }
8127  });
8128  }
8129 
8143  static string_t escape_string(const string_t& s)
8144  {
8145  const auto space = extra_space(s);
8146  if (space == 0)
8147  {
8148  return s;
8149  }
8150 
8151  // create a result string of necessary size
8152  string_t result(s.size() + space, '\\');
8153  std::size_t pos = 0;
8154 
8155  for (const auto& c : s)
8156  {
8157  switch (c)
8158  {
8159  // quotation mark (0x22)
8160  case '"':
8161  {
8162  result[pos + 1] = '"';
8163  pos += 2;
8164  break;
8165  }
8166 
8167  // reverse solidus (0x5c)
8168  case '\\':
8169  {
8170  // nothing to change
8171  pos += 2;
8172  break;
8173  }
8174 
8175  // backspace (0x08)
8176  case '\b':
8177  {
8178  result[pos + 1] = 'b';
8179  pos += 2;
8180  break;
8181  }
8182 
8183  // formfeed (0x0c)
8184  case '\f':
8185  {
8186  result[pos + 1] = 'f';
8187  pos += 2;
8188  break;
8189  }
8190 
8191  // newline (0x0a)
8192  case '\n':
8193  {
8194  result[pos + 1] = 'n';
8195  pos += 2;
8196  break;
8197  }
8198 
8199  // carriage return (0x0d)
8200  case '\r':
8201  {
8202  result[pos + 1] = 'r';
8203  pos += 2;
8204  break;
8205  }
8206 
8207  // horizontal tab (0x09)
8208  case '\t':
8209  {
8210  result[pos + 1] = 't';
8211  pos += 2;
8212  break;
8213  }
8214 
8215  default:
8216  {
8217  if (c >= 0x00 and c <= 0x1f)
8218  {
8219  // convert a number 0..15 to its hex representation
8220  // (0..f)
8221  static const char hexify[16] =
8222  {
8223  '0', '1', '2', '3', '4', '5', '6', '7',
8224  '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'
8225  };
8226 
8227  // print character c as \uxxxx
8228  for (const char m :
8229  { 'u', '0', '0', hexify[c >> 4], hexify[c & 0x0f]
8230  })
8231  {
8232  result[++pos] = m;
8233  }
8234 
8235  ++pos;
8236  }
8237  else
8238  {
8239  // all other characters are added as-is
8240  result[pos++] = c;
8241  }
8242  break;
8243  }
8244  }
8245  }
8246 
8247  return result;
8248  }
8249 
8250 
8254  struct numtostr
8255  {
8256  public:
8257  template<typename NumberType>
8258  numtostr(NumberType value)
8259  {
8260  x_write(value, std::is_integral<NumberType>());
8261  }
8262 
8263  const char* c_str() const
8264  {
8265  return m_buf.data();
8266  }
8267 
8268  private:
8270  std::array < char, 64 > m_buf{{}};
8271 
8272  template<typename NumberType>
8273  void x_write(NumberType x, /*is_integral=*/std::true_type)
8274  {
8275  // special case for "0"
8276  if (x == 0)
8277  {
8278  m_buf[0] = '0';
8279  return;
8280  }
8281 
8282  const bool is_negative = x < 0;
8283  size_t i = 0;
8284 
8285  // spare 1 byte for '\0'
8286  while (x != 0 and i < m_buf.size() - 1)
8287  {
8288  const auto digit = std::labs(static_cast<long>(x % 10));
8289  m_buf[i++] = static_cast<char>('0' + digit);
8290  x /= 10;
8291  }
8292 
8293  // make sure the number has been processed completely
8294  assert(x == 0);
8295 
8296  if (is_negative)
8297  {
8298  // make sure there is capacity for the '-'
8299  assert(i < m_buf.size() - 2);
8300  m_buf[i++] = '-';
8301  }
8302 
8303  std::reverse(m_buf.begin(), m_buf.begin() + i);
8304  }
8305 
8306  template<typename NumberType>
8307  void x_write(NumberType x, /*is_integral=*/std::false_type)
8308  {
8309  // special case for 0.0 and -0.0
8310  if (x == 0)
8311  {
8312  size_t i = 0;
8313  if (std::signbit(x))
8314  {
8315  m_buf[i++] = '-';
8316  }
8317  m_buf[i++] = '0';
8318  m_buf[i++] = '.';
8319  m_buf[i] = '0';
8320  return;
8321  }
8322 
8323  // get number of digits for a text -> float -> text round-trip
8324  static constexpr auto d = std::numeric_limits<NumberType>::digits10;
8325 
8326  // the actual conversion
8327  const auto written_bytes = snprintf(m_buf.data(), m_buf.size(), "%.*g", d, x);
8328 
8329  // negative value indicates an error
8330  assert(written_bytes > 0);
8331  // check if buffer was large enough
8332  assert(static_cast<size_t>(written_bytes) < m_buf.size());
8333 
8334  // read information from locale
8335  const auto loc = localeconv();
8336  assert(loc != nullptr);
8337  const char thousands_sep = !loc->thousands_sep ? '\0'
8338  : loc->thousands_sep[0];
8339 
8340  const char decimal_point = !loc->decimal_point ? '\0'
8341  : loc->decimal_point[0];
8342 
8343  // erase thousands separator
8344  if (thousands_sep != '\0')
8345  {
8346  const auto end = std::remove(m_buf.begin(), m_buf.begin() + written_bytes, thousands_sep);
8347  std::fill(end, m_buf.end(), '\0');
8348  }
8349 
8350  // convert decimal point to '.'
8351  if (decimal_point != '\0' and decimal_point != '.')
8352  {
8353  for (auto& c : m_buf)
8354  {
8355  if (c == decimal_point)
8356  {
8357  c = '.';
8358  break;
8359  }
8360  }
8361  }
8362 
8363  // determine if need to append ".0"
8364  size_t i = 0;
8365  bool value_is_int_like = true;
8366  for (i = 0; i < m_buf.size(); ++i)
8367  {
8368  // break when end of number is reached
8369  if (m_buf[i] == '\0')
8370  {
8371  break;
8372  }
8373 
8374  // check if we find non-int character
8375  value_is_int_like = value_is_int_like and m_buf[i] != '.' and
8376  m_buf[i] != 'e' and m_buf[i] != 'E';
8377  }
8378 
8379  if (value_is_int_like)
8380  {
8381  // there must be 2 bytes left for ".0"
8382  assert((i + 2) < m_buf.size());
8383  // we write to the end of the number
8384  assert(m_buf[i] == '\0');
8385  assert(m_buf[i - 1] != '\0');
8386 
8387  // add ".0"
8388  m_buf[i] = '.';
8389  m_buf[i + 1] = '0';
8390 
8391  // the resulting string is properly terminated
8392  assert(m_buf[i + 2] == '\0');
8393  }
8394  }
8395  };
8396 
8397 
8415  void dump(std::ostream& o,
8416  const bool pretty_print,
8417  const unsigned int indent_step,
8418  const unsigned int current_indent = 0) const
8419  {
8420  // variable to hold indentation for recursive calls
8421  unsigned int new_indent = current_indent;
8422 
8423  switch (m_type)
8424  {
8425  case value_t::object:
8426  {
8427  if (m_value.object->empty())
8428  {
8429  o << "{}";
8430  return;
8431  }
8432 
8433  o << "{";
8434 
8435  // increase indentation
8436  if (pretty_print)
8437  {
8438  new_indent += indent_step;
8439  o << "\n";
8440  }
8441 
8442  for (auto i = m_value.object->cbegin(); i != m_value.object->cend(); ++i)
8443  {
8444  if (i != m_value.object->cbegin())
8445  {
8446  o << (pretty_print ? ",\n" : ",");
8447  }
8448  o << string_t(new_indent, ' ') << "\""
8449  << escape_string(i->first) << "\":"
8450  << (pretty_print ? " " : "");
8451  i->second.dump(o, pretty_print, indent_step, new_indent);
8452  }
8453 
8454  // decrease indentation
8455  if (pretty_print)
8456  {
8457  new_indent -= indent_step;
8458  o << "\n";
8459  }
8460 
8461  o << string_t(new_indent, ' ') + "}";
8462  return;
8463  }
8464 
8465  case value_t::array:
8466  {
8467  if (m_value.array->empty())
8468  {
8469  o << "[]";
8470  return;
8471  }
8472 
8473  o << "[";
8474 
8475  // increase indentation
8476  if (pretty_print)
8477  {
8478  new_indent += indent_step;
8479  o << "\n";
8480  }
8481 
8482  for (auto i = m_value.array->cbegin(); i != m_value.array->cend(); ++i)
8483  {
8484  if (i != m_value.array->cbegin())
8485  {
8486  o << (pretty_print ? ",\n" : ",");
8487  }
8488  o << string_t(new_indent, ' ');
8489  i->dump(o, pretty_print, indent_step, new_indent);
8490  }
8491 
8492  // decrease indentation
8493  if (pretty_print)
8494  {
8495  new_indent -= indent_step;
8496  o << "\n";
8497  }
8498 
8499  o << string_t(new_indent, ' ') << "]";
8500  return;
8501  }
8502 
8503  case value_t::string:
8504  {
8505  o << string_t("\"") << escape_string(*m_value.string) << "\"";
8506  return;
8507  }
8508 
8509  case value_t::boolean:
8510  {
8511  o << (m_value.boolean ? "true" : "false");
8512  return;
8513  }
8514 
8515  case value_t::number_integer:
8516  {
8517  o << numtostr(m_value.number_integer).c_str();
8518  return;
8519  }
8520 
8521  case value_t::number_unsigned:
8522  {
8523  o << numtostr(m_value.number_unsigned).c_str();
8524  return;
8525  }
8526 
8527  case value_t::number_float:
8528  {
8529  o << numtostr(m_value.number_float).c_str();
8530  return;
8531  }
8532 
8533  case value_t::discarded:
8534  {
8535  o << "<discarded>";
8536  return;
8537  }
8538 
8539  case value_t::null:
8540  {
8541  o << "null";
8542  return;
8543  }
8544  }
8545  }
8546 
8547  private:
8549  // member variables //
8551 
8553  value_t m_type = value_t::null;
8554 
8556  json_value m_value = {};
8557 
8558 
8559  private:
8561  // iterators //
8563 
8573  class primitive_iterator_t
8574  {
8575  public:
8576 
8577  difference_type get_value() const noexcept
8578  {
8579  return m_it;
8580  }
8582  void set_begin() noexcept
8583  {
8584  m_it = begin_value;
8585  }
8586 
8588  void set_end() noexcept
8589  {
8590  m_it = end_value;
8591  }
8592 
8594  constexpr bool is_begin() const noexcept
8595  {
8596  return (m_it == begin_value);
8597  }
8598 
8600  constexpr bool is_end() const noexcept
8601  {
8602  return (m_it == end_value);
8603  }
8604 
8605  friend constexpr bool operator==(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept
8606  {
8607  return lhs.m_it == rhs.m_it;
8608  }
8609 
8610  friend constexpr bool operator!=(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept
8611  {
8612  return !(lhs == rhs);
8613  }
8614 
8615  friend constexpr bool operator<(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept
8616  {
8617  return lhs.m_it < rhs.m_it;
8618  }
8619 
8620  friend constexpr bool operator<=(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept
8621  {
8622  return lhs.m_it <= rhs.m_it;
8623  }
8624 
8625  friend constexpr bool operator>(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept
8626  {
8627  return lhs.m_it > rhs.m_it;
8628  }
8629 
8630  friend constexpr bool operator>=(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept
8631  {
8632  return lhs.m_it >= rhs.m_it;
8633  }
8634 
8635  primitive_iterator_t operator+(difference_type i)
8636  {
8637  auto result = *this;
8638  result += i;
8639  return result;
8640  }
8641 
8642  friend constexpr difference_type operator-(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept
8643  {
8644  return lhs.m_it - rhs.m_it;
8645  }
8646 
8647  friend std::ostream& operator<<(std::ostream& os, primitive_iterator_t it)
8648  {
8649  return os << it.m_it;
8650  }
8651 
8652  primitive_iterator_t& operator++()
8653  {
8654  ++m_it;
8655  return *this;
8656  }
8657 
8658  primitive_iterator_t operator++(int)
8659  {
8660  auto result = *this;
8661  m_it++;
8662  return result;
8663  }
8664 
8665  primitive_iterator_t& operator--()
8666  {
8667  --m_it;
8668  return *this;
8669  }
8670 
8671  primitive_iterator_t operator--(int)
8672  {
8673  auto result = *this;
8674  m_it--;
8675  return result;
8676  }
8677 
8678  primitive_iterator_t& operator+=(difference_type n)
8679  {
8680  m_it += n;
8681  return *this;
8682  }
8683 
8684  primitive_iterator_t& operator-=(difference_type n)
8685  {
8686  m_it -= n;
8687  return *this;
8688  }
8689 
8690  private:
8691  static constexpr difference_type begin_value = 0;
8692  static constexpr difference_type end_value = begin_value + 1;
8693 
8695  difference_type m_it = std::numeric_limits<std::ptrdiff_t>::denorm_min();
8696  };
8697 
8705  struct internal_iterator
8706  {
8708  typename object_t::iterator object_iterator;
8710  typename array_t::iterator array_iterator;
8712  primitive_iterator_t primitive_iterator;
8713 
8715  internal_iterator() noexcept
8716  : object_iterator(), array_iterator(), primitive_iterator()
8717  {}
8718  };
8719 
8721  template<typename IteratorType>
8722  class iteration_proxy
8723  {
8724  private:
8726  class iteration_proxy_internal
8727  {
8728  private:
8730  IteratorType anchor;
8732  size_t array_index = 0;
8733 
8734  public:
8735  explicit iteration_proxy_internal(IteratorType it) noexcept
8736  : anchor(it)
8737  {}
8738 
8740  iteration_proxy_internal& operator*()
8741  {
8742  return *this;
8743  }
8744 
8746  iteration_proxy_internal& operator++()
8747  {
8748  ++anchor;
8749  ++array_index;
8750 
8751  return *this;
8752  }
8753 
8755  bool operator!= (const iteration_proxy_internal& o) const
8756  {
8757  return anchor != o.anchor;
8758  }
8759 
8761  typename basic_json::string_t key() const
8762  {
8763  assert(anchor.m_object != nullptr);
8764 
8765  switch (anchor.m_object->type())
8766  {
8767  // use integer array index as key
8768  case value_t::array:
8769  {
8770  return std::to_string(array_index);
8771  }
8772 
8773  // use key from the object
8774  case value_t::object:
8775  {
8776  return anchor.key();
8777  }
8778 
8779  // use an empty key for all primitive types
8780  default:
8781  {
8782  return "";
8783  }
8784  }
8785  }
8786 
8788  typename IteratorType::reference value() const
8789  {
8790  return anchor.value();
8791  }
8792  };
8793 
8795  typename IteratorType::reference container;
8796 
8797  public:
8799  explicit iteration_proxy(typename IteratorType::reference cont)
8800  : container(cont)
8801  {}
8802 
8804  iteration_proxy_internal begin() noexcept
8805  {
8806  return iteration_proxy_internal(container.begin());
8807  }
8808 
8810  iteration_proxy_internal end() noexcept
8811  {
8812  return iteration_proxy_internal(container.end());
8813  }
8814  };
8815 
8816  public:
8836  template<typename U>
8837  class iter_impl : public std::iterator<std::random_access_iterator_tag, U>
8838  {
8840  friend class basic_json;
8841 
8842  // make sure U is basic_json or const basic_json
8843  static_assert(std::is_same<U, basic_json>::value
8844  or std::is_same<U, const basic_json>::value,
8845  "iter_impl only accepts (const) basic_json");
8846 
8847  public:
8853  using pointer = typename std::conditional<std::is_const<U>::value,
8854  typename basic_json::const_pointer,
8855  typename basic_json::pointer>::type;
8857  using reference = typename std::conditional<std::is_const<U>::value,
8858  typename basic_json::const_reference,
8859  typename basic_json::reference>::type;
8861  using iterator_category = std::bidirectional_iterator_tag;
8862 
8864  iter_impl() = default;
8865 
8872  explicit iter_impl(pointer object) noexcept
8873  : m_object(object)
8874  {
8875  assert(m_object != nullptr);
8876 
8877  switch (m_object->m_type)
8878  {
8879  case basic_json::value_t::object:
8880  {
8881  m_it.object_iterator = typename object_t::iterator();
8882  break;
8883  }
8884 
8885  case basic_json::value_t::array:
8886  {
8887  m_it.array_iterator = typename array_t::iterator();
8888  break;
8889  }
8890 
8891  default:
8892  {
8893  m_it.primitive_iterator = primitive_iterator_t();
8894  break;
8895  }
8896  }
8897  }
8898 
8899  /*
8900  Use operator `const_iterator` instead of `const_iterator(const iterator&
8901  other) noexcept` to avoid two class definitions for @ref iterator and
8902  @ref const_iterator.
8903 
8904  This function is only called if this class is an @ref iterator. If this
8905  class is a @ref const_iterator this function is not called.
8906  */
8907  operator const_iterator() const
8908  {
8909  const_iterator ret;
8910 
8911  if (m_object)
8912  {
8913  ret.m_object = m_object;
8914  ret.m_it = m_it;
8915  }
8916 
8917  return ret;
8918  }
8919 
8925  iter_impl(const iter_impl& other) noexcept
8926  : m_object(other.m_object), m_it(other.m_it)
8927  {}
8928 
8934  iter_impl& operator=(iter_impl other) noexcept(
8935  std::is_nothrow_move_constructible<pointer>::value and
8936  std::is_nothrow_move_assignable<pointer>::value and
8937  std::is_nothrow_move_constructible<internal_iterator>::value and
8938  std::is_nothrow_move_assignable<internal_iterator>::value
8939  )
8940  {
8941  std::swap(m_object, other.m_object);
8942  std::swap(m_it, other.m_it);
8943  return *this;
8944  }
8945 
8946  private:
8951  void set_begin() noexcept
8952  {
8953  assert(m_object != nullptr);
8954 
8955  switch (m_object->m_type)
8956  {
8957  case basic_json::value_t::object:
8958  {
8959  m_it.object_iterator = m_object->m_value.object->begin();
8960  break;
8961  }
8962 
8963  case basic_json::value_t::array:
8964  {
8965  m_it.array_iterator = m_object->m_value.array->begin();
8966  break;
8967  }
8968 
8969  case basic_json::value_t::null:
8970  {
8971  // set to end so begin()==end() is true: null is empty
8972  m_it.primitive_iterator.set_end();
8973  break;
8974  }
8975 
8976  default:
8977  {
8978  m_it.primitive_iterator.set_begin();
8979  break;
8980  }
8981  }
8982  }
8983 
8988  void set_end() noexcept
8989  {
8990  assert(m_object != nullptr);
8991 
8992  switch (m_object->m_type)
8993  {
8994  case basic_json::value_t::object:
8995  {
8996  m_it.object_iterator = m_object->m_value.object->end();
8997  break;
8998  }
8999 
9000  case basic_json::value_t::array:
9001  {
9002  m_it.array_iterator = m_object->m_value.array->end();
9003  break;
9004  }
9005 
9006  default:
9007  {
9008  m_it.primitive_iterator.set_end();
9009  break;
9010  }
9011  }
9012  }
9013 
9014  public:
9020  {
9021  assert(m_object != nullptr);
9022 
9023  switch (m_object->m_type)
9024  {
9025  case basic_json::value_t::object:
9026  {
9027  assert(m_it.object_iterator != m_object->m_value.object->end());
9028  return m_it.object_iterator->second;
9029  }
9030 
9031  case basic_json::value_t::array:
9032  {
9033  assert(m_it.array_iterator != m_object->m_value.array->end());
9034  return *m_it.array_iterator;
9035  }
9036 
9037  case basic_json::value_t::null:
9038  {
9039  JSON_THROW(std::out_of_range("cannot get value"));
9040  }
9041 
9042  default:
9043  {
9044  if (m_it.primitive_iterator.is_begin())
9045  {
9046  return *m_object;
9047  }
9048 
9049  JSON_THROW(std::out_of_range("cannot get value"));
9050  }
9051  }
9052  }
9053 
9059  {
9060  assert(m_object != nullptr);
9061 
9062  switch (m_object->m_type)
9063  {
9064  case basic_json::value_t::object:
9065  {
9066  assert(m_it.object_iterator != m_object->m_value.object->end());
9067  return &(m_it.object_iterator->second);
9068  }
9069 
9070  case basic_json::value_t::array:
9071  {
9072  assert(m_it.array_iterator != m_object->m_value.array->end());
9073  return &*m_it.array_iterator;
9074  }
9075 
9076  default:
9077  {
9078  if (m_it.primitive_iterator.is_begin())
9079  {
9080  return m_object;
9081  }
9082 
9083  JSON_THROW(std::out_of_range("cannot get value"));
9084  }
9085  }
9086  }
9087 
9093  {
9094  auto result = *this;
9095  ++(*this);
9096  return result;
9097  }
9098 
9104  {
9105  assert(m_object != nullptr);
9106 
9107  switch (m_object->m_type)
9108  {
9109  case basic_json::value_t::object:
9110  {
9111  std::advance(m_it.object_iterator, 1);
9112  break;
9113  }
9114 
9115  case basic_json::value_t::array:
9116  {
9117  std::advance(m_it.array_iterator, 1);
9118  break;
9119  }
9120 
9121  default:
9122  {
9123  ++m_it.primitive_iterator;
9124  break;
9125  }
9126  }
9127 
9128  return *this;
9129  }
9130 
9136  {
9137  auto result = *this;
9138  --(*this);
9139  return result;
9140  }
9141 
9147  {
9148  assert(m_object != nullptr);
9149 
9150  switch (m_object->m_type)
9151  {
9152  case basic_json::value_t::object:
9153  {
9154  std::advance(m_it.object_iterator, -1);
9155  break;
9156  }
9157 
9158  case basic_json::value_t::array:
9159  {
9160  std::advance(m_it.array_iterator, -1);
9161  break;
9162  }
9163 
9164  default:
9165  {
9166  --m_it.primitive_iterator;
9167  break;
9168  }
9169  }
9170 
9171  return *this;
9172  }
9173 
9178  bool operator==(const iter_impl& other) const
9179  {
9180  // if objects are not the same, the comparison is undefined
9181  if (m_object != other.m_object)
9182  {
9183  JSON_THROW(std::domain_error("cannot compare iterators of different containers"));
9184  }
9185 
9186  assert(m_object != nullptr);
9187 
9188  switch (m_object->m_type)
9189  {
9190  case basic_json::value_t::object:
9191  {
9192  return (m_it.object_iterator == other.m_it.object_iterator);
9193  }
9194 
9195  case basic_json::value_t::array:
9196  {
9197  return (m_it.array_iterator == other.m_it.array_iterator);
9198  }
9199 
9200  default:
9201  {
9202  return (m_it.primitive_iterator == other.m_it.primitive_iterator);
9203  }
9204  }
9205  }
9206 
9211  bool operator!=(const iter_impl& other) const
9212  {
9213  return not operator==(other);
9214  }
9215 
9220  bool operator<(const iter_impl& other) const
9221  {
9222  // if objects are not the same, the comparison is undefined
9223  if (m_object != other.m_object)
9224  {
9225  JSON_THROW(std::domain_error("cannot compare iterators of different containers"));
9226  }
9227 
9228  assert(m_object != nullptr);
9229 
9230  switch (m_object->m_type)
9231  {
9232  case basic_json::value_t::object:
9233  {
9234  JSON_THROW(std::domain_error("cannot compare order of object iterators"));
9235  }
9236 
9237  case basic_json::value_t::array:
9238  {
9239  return (m_it.array_iterator < other.m_it.array_iterator);
9240  }
9241 
9242  default:
9243  {
9244  return (m_it.primitive_iterator < other.m_it.primitive_iterator);
9245  }
9246  }
9247  }
9248 
9253  bool operator<=(const iter_impl& other) const
9254  {
9255  return not other.operator < (*this);
9256  }
9257 
9262  bool operator>(const iter_impl& other) const
9263  {
9264  return not operator<=(other);
9265  }
9266 
9271  bool operator>=(const iter_impl& other) const
9272  {
9273  return not operator<(other);
9274  }
9275 
9281  {
9282  assert(m_object != nullptr);
9283 
9284  switch (m_object->m_type)
9285  {
9286  case basic_json::value_t::object:
9287  {
9288  JSON_THROW(std::domain_error("cannot use offsets with object iterators"));
9289  }
9290 
9291  case basic_json::value_t::array:
9292  {
9293  std::advance(m_it.array_iterator, i);
9294  break;
9295  }
9296 
9297  default:
9298  {
9299  m_it.primitive_iterator += i;
9300  break;
9301  }
9302  }
9303 
9304  return *this;
9305  }
9306 
9312  {
9313  return operator+=(-i);
9314  }
9315 
9321  {
9322  auto result = *this;
9323  result += i;
9324  return result;
9325  }
9326 
9332  {
9333  auto result = *this;
9334  result -= i;
9335  return result;
9336  }
9337 
9343  {
9344  assert(m_object != nullptr);
9345 
9346  switch (m_object->m_type)
9347  {
9348  case basic_json::value_t::object:
9349  {
9350  JSON_THROW(std::domain_error("cannot use offsets with object iterators"));
9351  }
9352 
9353  case basic_json::value_t::array:
9354  {
9355  return m_it.array_iterator - other.m_it.array_iterator;
9356  }
9357 
9358  default:
9359  {
9360  return m_it.primitive_iterator - other.m_it.primitive_iterator;
9361  }
9362  }
9363  }
9364 
9370  {
9371  assert(m_object != nullptr);
9372 
9373  switch (m_object->m_type)
9374  {
9375  case basic_json::value_t::object:
9376  {
9377  JSON_THROW(std::domain_error("cannot use operator[] for object iterators"));
9378  }
9379 
9380  case basic_json::value_t::array:
9381  {
9382  return *std::next(m_it.array_iterator, n);
9383  }
9384 
9385  case basic_json::value_t::null:
9386  {
9387  JSON_THROW(std::out_of_range("cannot get value"));
9388  }
9389 
9390  default:
9391  {
9392  if (m_it.primitive_iterator.get_value() == -n)
9393  {
9394  return *m_object;
9395  }
9396 
9397  JSON_THROW(std::out_of_range("cannot get value"));
9398  }
9399  }
9400  }
9401 
9406  typename object_t::key_type key() const
9407  {
9408  assert(m_object != nullptr);
9409 
9410  if (m_object->is_object())
9411  {
9412  return m_it.object_iterator->first;
9413  }
9414 
9415  JSON_THROW(std::domain_error("cannot use key() for non-object iterators"));
9416  }
9417 
9423  {
9424  return operator*();
9425  }
9426 
9427  private:
9429  pointer m_object = nullptr;
9431  internal_iterator m_it = internal_iterator();
9432  };
9433 
9451  template<typename Base>
9452  class json_reverse_iterator : public std::reverse_iterator<Base>
9453  {
9454  public:
9456  using base_iterator = std::reverse_iterator<Base>;
9458  using reference = typename Base::reference;
9459 
9461  json_reverse_iterator(const typename base_iterator::iterator_type& it) noexcept
9462  : base_iterator(it)
9463  {}
9464 
9467  : base_iterator(it)
9468  {}
9469 
9472  {
9473  return base_iterator::operator++(1);
9474  }
9475 
9478  {
9479  base_iterator::operator++();
9480  return *this;
9481  }
9482 
9485  {
9486  return base_iterator::operator--(1);
9487  }
9488 
9491  {
9492  base_iterator::operator--();
9493  return *this;
9494  }
9495 
9498  {
9499  base_iterator::operator+=(i);
9500  return *this;
9501  }
9502 
9505  {
9506  auto result = *this;
9507  result += i;
9508  return result;
9509  }
9510 
9513  {
9514  auto result = *this;
9515  result -= i;
9516  return result;
9517  }
9518 
9521  {
9522  return this->base() - other.base();
9523  }
9524 
9527  {
9528  return *(this->operator+(n));
9529  }
9530 
9532  typename object_t::key_type key() const
9533  {
9534  auto it = --this->base();
9535  return it.key();
9536  }
9537 
9540  {
9541  auto it = --this->base();
9542  return it.operator * ();
9543  }
9544  };
9545 
9546 
9547  private:
9549  // lexer and parser //
9551 
9559  class lexer
9560  {
9561  public:
9563  enum class token_type
9564  {
9565  uninitialized,
9566  literal_true,
9567  literal_false,
9568  literal_null,
9569  value_string,
9570  value_unsigned,
9571  value_integer,
9572  value_float,
9573  begin_array,
9574  begin_object,
9575  end_array,
9576  end_object,
9577  name_separator,
9578  value_separator,
9579  parse_error,
9580  end_of_input
9581  };
9582 
9584  using lexer_char_t = unsigned char;
9585 
9587  lexer(const lexer_char_t* buff, const size_t len) noexcept
9588  : m_content(buff)
9589  {
9590  assert(m_content != nullptr);
9591  m_start = m_cursor = m_content;
9592  m_limit = m_content + len;
9593  }
9594 
9596  explicit lexer(std::istream& s)
9597  : m_stream(&s), m_line_buffer()
9598  {
9599  // immediately abort if stream is erroneous
9600  if (s.fail())
9601  {
9602  JSON_THROW(std::invalid_argument("stream error"));
9603  }
9604 
9605  // fill buffer
9606  fill_line_buffer();
9607 
9608  // skip UTF-8 byte-order mark
9609  if (m_line_buffer.size() >= 3 and m_line_buffer.substr(0, 3) == "\xEF\xBB\xBF")
9610  {
9611  m_line_buffer[0] = ' ';
9612  m_line_buffer[1] = ' ';
9613  m_line_buffer[2] = ' ';
9614  }
9615  }
9616 
9617  // switch off unwanted functions (due to pointer members)
9618  lexer() = delete;
9619  lexer(const lexer&) = delete;
9620  lexer operator=(const lexer&) = delete;
9621 
9645  static string_t to_unicode(const std::size_t codepoint1,
9646  const std::size_t codepoint2 = 0)
9647  {
9648  // calculate the code point from the given code points
9649  std::size_t codepoint = codepoint1;
9650 
9651  // check if codepoint1 is a high surrogate
9652  if (codepoint1 >= 0xD800 and codepoint1 <= 0xDBFF)
9653  {
9654  // check if codepoint2 is a low surrogate
9655  if (codepoint2 >= 0xDC00 and codepoint2 <= 0xDFFF)
9656  {
9657  codepoint =
9658  // high surrogate occupies the most significant 22 bits
9659  (codepoint1 << 10)
9660  // low surrogate occupies the least significant 15 bits
9661  + codepoint2
9662  // there is still the 0xD800, 0xDC00 and 0x10000 noise
9663  // in the result so we have to subtract with:
9664  // (0xD800 << 10) + DC00 - 0x10000 = 0x35FDC00
9665  - 0x35FDC00;
9666  }
9667  else
9668  {
9669  JSON_THROW(std::invalid_argument("missing or wrong low surrogate"));
9670  }
9671  }
9672 
9673  string_t result;
9674 
9675  if (codepoint < 0x80)
9676  {
9677  // 1-byte characters: 0xxxxxxx (ASCII)
9678  result.append(1, static_cast<typename string_t::value_type>(codepoint));
9679  }
9680  else if (codepoint <= 0x7ff)
9681  {
9682  // 2-byte characters: 110xxxxx 10xxxxxx
9683  result.append(1, static_cast<typename string_t::value_type>(0xC0 | ((codepoint >> 6) & 0x1F)));
9684  result.append(1, static_cast<typename string_t::value_type>(0x80 | (codepoint & 0x3F)));
9685  }
9686  else if (codepoint <= 0xffff)
9687  {
9688  // 3-byte characters: 1110xxxx 10xxxxxx 10xxxxxx
9689  result.append(1, static_cast<typename string_t::value_type>(0xE0 | ((codepoint >> 12) & 0x0F)));
9690  result.append(1, static_cast<typename string_t::value_type>(0x80 | ((codepoint >> 6) & 0x3F)));
9691  result.append(1, static_cast<typename string_t::value_type>(0x80 | (codepoint & 0x3F)));
9692  }
9693  else if (codepoint <= 0x10ffff)
9694  {
9695  // 4-byte characters: 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
9696  result.append(1, static_cast<typename string_t::value_type>(0xF0 | ((codepoint >> 18) & 0x07)));
9697  result.append(1, static_cast<typename string_t::value_type>(0x80 | ((codepoint >> 12) & 0x3F)));
9698  result.append(1, static_cast<typename string_t::value_type>(0x80 | ((codepoint >> 6) & 0x3F)));
9699  result.append(1, static_cast<typename string_t::value_type>(0x80 | (codepoint & 0x3F)));
9700  }
9701  else
9702  {
9703  JSON_THROW(std::out_of_range("code points above 0x10FFFF are invalid"));
9704  }
9705 
9706  return result;
9707  }
9708 
9710  static std::string token_type_name(const token_type t)
9711  {
9712  switch (t)
9713  {
9714  case token_type::uninitialized:
9715  return "<uninitialized>";
9716  case token_type::literal_true:
9717  return "true literal";
9718  case token_type::literal_false:
9719  return "false literal";
9720  case token_type::literal_null:
9721  return "null literal";
9722  case token_type::value_string:
9723  return "string literal";
9724  case lexer::token_type::value_unsigned:
9725  case lexer::token_type::value_integer:
9726  case lexer::token_type::value_float:
9727  return "number literal";
9728  case token_type::begin_array:
9729  return "'['";
9730  case token_type::begin_object:
9731  return "'{'";
9732  case token_type::end_array:
9733  return "']'";
9734  case token_type::end_object:
9735  return "'}'";
9736  case token_type::name_separator:
9737  return "':'";
9738  case token_type::value_separator:
9739  return "','";
9740  case token_type::parse_error:
9741  return "<parse error>";
9742  case token_type::end_of_input:
9743  return "end of input";
9744  default:
9745  {
9746  // catch non-enum values
9747  return "unknown token"; // LCOV_EXCL_LINE
9748  }
9749  }
9750  }
9751 
9773  token_type scan()
9774  {
9775  while (true)
9776  {
9777  // pointer for backtracking information
9778  m_marker = nullptr;
9779 
9780  // remember the begin of the token
9781  m_start = m_cursor;
9782  assert(m_start != nullptr);
9783 
9784 
9785  {
9786  lexer_char_t yych;
9787  unsigned int yyaccept = 0;
9788  static const unsigned char yybm[] = {
9789  0, 0, 0, 0, 0, 0, 0, 0,
9790  0, 32, 32, 0, 0, 32, 0, 0,
9791  0, 0, 0, 0, 0, 0, 0, 0,
9792  0, 0, 0, 0, 0, 0, 0, 0,
9793  160, 128, 0, 128, 128, 128, 128, 128,
9794  128, 128, 128, 128, 128, 128, 128, 128,
9795  192, 192, 192, 192, 192, 192, 192, 192,
9796  192, 192, 128, 128, 128, 128, 128, 128,
9797  128, 128, 128, 128, 128, 128, 128, 128,
9798  128, 128, 128, 128, 128, 128, 128, 128,
9799  128, 128, 128, 128, 128, 128, 128, 128,
9800  128, 128, 128, 128, 0, 128, 128, 128,
9801  128, 128, 128, 128, 128, 128, 128, 128,
9802  128, 128, 128, 128, 128, 128, 128, 128,
9803  128, 128, 128, 128, 128, 128, 128, 128,
9804  128, 128, 128, 128, 128, 128, 128, 128,
9805  0, 0, 0, 0, 0, 0, 0, 0,
9806  0, 0, 0, 0, 0, 0, 0, 0,
9807  0, 0, 0, 0, 0, 0, 0, 0,
9808  0, 0, 0, 0, 0, 0, 0, 0,
9809  0, 0, 0, 0, 0, 0, 0, 0,
9810  0, 0, 0, 0, 0, 0, 0, 0,
9811  0, 0, 0, 0, 0, 0, 0, 0,
9812  0, 0, 0, 0, 0, 0, 0, 0,
9813  0, 0, 0, 0, 0, 0, 0, 0,
9814  0, 0, 0, 0, 0, 0, 0, 0,
9815  0, 0, 0, 0, 0, 0, 0, 0,
9816  0, 0, 0, 0, 0, 0, 0, 0,
9817  0, 0, 0, 0, 0, 0, 0, 0,
9818  0, 0, 0, 0, 0, 0, 0, 0,
9819  0, 0, 0, 0, 0, 0, 0, 0,
9820  0, 0, 0, 0, 0, 0, 0, 0,
9821  };
9822  if ((m_limit - m_cursor) < 5) fill_line_buffer(5); // LCOV_EXCL_LINE
9823  yych = *m_cursor;
9824  if (yybm[0+yych] & 32) {
9825  goto basic_json_parser_6;
9826  }
9827  if (yych <= '[') {
9828  if (yych <= '-') {
9829  if (yych <= '"') {
9830  if (yych <= 0x00) goto basic_json_parser_2;
9831  if (yych <= '!') goto basic_json_parser_4;
9832  goto basic_json_parser_9;
9833  } else {
9834  if (yych <= '+') goto basic_json_parser_4;
9835  if (yych <= ',') goto basic_json_parser_10;
9836  goto basic_json_parser_12;
9837  }
9838  } else {
9839  if (yych <= '9') {
9840  if (yych <= '/') goto basic_json_parser_4;
9841  if (yych <= '0') goto basic_json_parser_13;
9842  goto basic_json_parser_15;
9843  } else {
9844  if (yych <= ':') goto basic_json_parser_17;
9845  if (yych <= 'Z') goto basic_json_parser_4;
9846  goto basic_json_parser_19;
9847  }
9848  }
9849  } else {
9850  if (yych <= 'n') {
9851  if (yych <= 'e') {
9852  if (yych == ']') goto basic_json_parser_21;
9853  goto basic_json_parser_4;
9854  } else {
9855  if (yych <= 'f') goto basic_json_parser_23;
9856  if (yych <= 'm') goto basic_json_parser_4;
9857  goto basic_json_parser_24;
9858  }
9859  } else {
9860  if (yych <= 'z') {
9861  if (yych == 't') goto basic_json_parser_25;
9862  goto basic_json_parser_4;
9863  } else {
9864  if (yych <= '{') goto basic_json_parser_26;
9865  if (yych == '}') goto basic_json_parser_28;
9866  goto basic_json_parser_4;
9867  }
9868  }
9869  }
9870 basic_json_parser_2:
9871  ++m_cursor;
9872  { last_token_type = token_type::end_of_input; break; }
9873 basic_json_parser_4:
9874  ++m_cursor;
9875 basic_json_parser_5:
9876  { last_token_type = token_type::parse_error; break; }
9877 basic_json_parser_6:
9878  ++m_cursor;
9879  if (m_limit <= m_cursor) fill_line_buffer(1); // LCOV_EXCL_LINE
9880  yych = *m_cursor;
9881  if (yybm[0+yych] & 32) {
9882  goto basic_json_parser_6;
9883  }
9884  { continue; }
9885 basic_json_parser_9:
9886  yyaccept = 0;
9887  yych = *(m_marker = ++m_cursor);
9888  if (yych <= 0x1F) goto basic_json_parser_5;
9889  if (yych <= 0x7F) goto basic_json_parser_31;
9890  if (yych <= 0xC1) goto basic_json_parser_5;
9891  if (yych <= 0xF4) goto basic_json_parser_31;
9892  goto basic_json_parser_5;
9893 basic_json_parser_10:
9894  ++m_cursor;
9895  { last_token_type = token_type::value_separator; break; }
9896 basic_json_parser_12:
9897  yych = *++m_cursor;
9898  if (yych <= '/') goto basic_json_parser_5;
9899  if (yych <= '0') goto basic_json_parser_43;
9900  if (yych <= '9') goto basic_json_parser_45;
9901  goto basic_json_parser_5;
9902 basic_json_parser_13:
9903  yyaccept = 1;
9904  yych = *(m_marker = ++m_cursor);
9905  if (yych <= '9') {
9906  if (yych == '.') goto basic_json_parser_47;
9907  if (yych >= '0') goto basic_json_parser_48;
9908  } else {
9909  if (yych <= 'E') {
9910  if (yych >= 'E') goto basic_json_parser_51;
9911  } else {
9912  if (yych == 'e') goto basic_json_parser_51;
9913  }
9914  }
9915 basic_json_parser_14:
9916  { last_token_type = token_type::value_unsigned; break; }
9917 basic_json_parser_15:
9918  yyaccept = 1;
9919  m_marker = ++m_cursor;
9920  if ((m_limit - m_cursor) < 3) fill_line_buffer(3); // LCOV_EXCL_LINE
9921  yych = *m_cursor;
9922  if (yybm[0+yych] & 64) {
9923  goto basic_json_parser_15;
9924  }
9925  if (yych <= 'D') {
9926  if (yych == '.') goto basic_json_parser_47;
9927  goto basic_json_parser_14;
9928  } else {
9929  if (yych <= 'E') goto basic_json_parser_51;
9930  if (yych == 'e') goto basic_json_parser_51;
9931  goto basic_json_parser_14;
9932  }
9933 basic_json_parser_17:
9934  ++m_cursor;
9935  { last_token_type = token_type::name_separator; break; }
9936 basic_json_parser_19:
9937  ++m_cursor;
9938  { last_token_type = token_type::begin_array; break; }
9939 basic_json_parser_21:
9940  ++m_cursor;
9941  { last_token_type = token_type::end_array; break; }
9942 basic_json_parser_23:
9943  yyaccept = 0;
9944  yych = *(m_marker = ++m_cursor);
9945  if (yych == 'a') goto basic_json_parser_52;
9946  goto basic_json_parser_5;
9947 basic_json_parser_24:
9948  yyaccept = 0;
9949  yych = *(m_marker = ++m_cursor);
9950  if (yych == 'u') goto basic_json_parser_53;
9951  goto basic_json_parser_5;
9952 basic_json_parser_25:
9953  yyaccept = 0;
9954  yych = *(m_marker = ++m_cursor);
9955  if (yych == 'r') goto basic_json_parser_54;
9956  goto basic_json_parser_5;
9957 basic_json_parser_26:
9958  ++m_cursor;
9959  { last_token_type = token_type::begin_object; break; }
9960 basic_json_parser_28:
9961  ++m_cursor;
9962  { last_token_type = token_type::end_object; break; }
9963 basic_json_parser_30:
9964  ++m_cursor;
9965  if (m_limit <= m_cursor) fill_line_buffer(1); // LCOV_EXCL_LINE
9966  yych = *m_cursor;
9967 basic_json_parser_31:
9968  if (yybm[0+yych] & 128) {
9969  goto basic_json_parser_30;
9970  }
9971  if (yych <= 0xE0) {
9972  if (yych <= '\\') {
9973  if (yych <= 0x1F) goto basic_json_parser_32;
9974  if (yych <= '"') goto basic_json_parser_33;
9975  goto basic_json_parser_35;
9976  } else {
9977  if (yych <= 0xC1) goto basic_json_parser_32;
9978  if (yych <= 0xDF) goto basic_json_parser_36;
9979  goto basic_json_parser_37;
9980  }
9981  } else {
9982  if (yych <= 0xEF) {
9983  if (yych == 0xED) goto basic_json_parser_39;
9984  goto basic_json_parser_38;
9985  } else {
9986  if (yych <= 0xF0) goto basic_json_parser_40;
9987  if (yych <= 0xF3) goto basic_json_parser_41;
9988  if (yych <= 0xF4) goto basic_json_parser_42;
9989  }
9990  }
9991 basic_json_parser_32:
9992  m_cursor = m_marker;
9993  if (yyaccept <= 1) {
9994  if (yyaccept == 0) {
9995  goto basic_json_parser_5;
9996  } else {
9997  goto basic_json_parser_14;
9998  }
9999  } else {
10000  if (yyaccept == 2) {
10001  goto basic_json_parser_44;
10002  } else {
10003  goto basic_json_parser_58;
10004  }
10005  }
10006 basic_json_parser_33:
10007  ++m_cursor;
10008  { last_token_type = token_type::value_string; break; }
10009 basic_json_parser_35:
10010  ++m_cursor;
10011  if (m_limit <= m_cursor) fill_line_buffer(1); // LCOV_EXCL_LINE
10012  yych = *m_cursor;
10013  if (yych <= 'e') {
10014  if (yych <= '/') {
10015  if (yych == '"') goto basic_json_parser_30;
10016  if (yych <= '.') goto basic_json_parser_32;
10017  goto basic_json_parser_30;
10018  } else {
10019  if (yych <= '\\') {
10020  if (yych <= '[') goto basic_json_parser_32;
10021  goto basic_json_parser_30;
10022  } else {
10023  if (yych == 'b') goto basic_json_parser_30;
10024  goto basic_json_parser_32;
10025  }
10026  }
10027  } else {
10028  if (yych <= 'q') {
10029  if (yych <= 'f') goto basic_json_parser_30;
10030  if (yych == 'n') goto basic_json_parser_30;
10031  goto basic_json_parser_32;
10032  } else {
10033  if (yych <= 's') {
10034  if (yych <= 'r') goto basic_json_parser_30;
10035  goto basic_json_parser_32;
10036  } else {
10037  if (yych <= 't') goto basic_json_parser_30;
10038  if (yych <= 'u') goto basic_json_parser_55;
10039  goto basic_json_parser_32;
10040  }
10041  }
10042  }
10043 basic_json_parser_36:
10044  ++m_cursor;
10045  if (m_limit <= m_cursor) fill_line_buffer(1); // LCOV_EXCL_LINE
10046  yych = *m_cursor;
10047  if (yych <= 0x7F) goto basic_json_parser_32;
10048  if (yych <= 0xBF) goto basic_json_parser_30;
10049  goto basic_json_parser_32;
10050 basic_json_parser_37:
10051  ++m_cursor;
10052  if (m_limit <= m_cursor) fill_line_buffer(1); // LCOV_EXCL_LINE
10053  yych = *m_cursor;
10054  if (yych <= 0x9F) goto basic_json_parser_32;
10055  if (yych <= 0xBF) goto basic_json_parser_36;
10056  goto basic_json_parser_32;
10057 basic_json_parser_38:
10058  ++m_cursor;
10059  if (m_limit <= m_cursor) fill_line_buffer(1); // LCOV_EXCL_LINE
10060  yych = *m_cursor;
10061  if (yych <= 0x7F) goto basic_json_parser_32;
10062  if (yych <= 0xBF) goto basic_json_parser_36;
10063  goto basic_json_parser_32;
10064 basic_json_parser_39:
10065  ++m_cursor;
10066  if (m_limit <= m_cursor) fill_line_buffer(1); // LCOV_EXCL_LINE
10067  yych = *m_cursor;
10068  if (yych <= 0x7F) goto basic_json_parser_32;
10069  if (yych <= 0x9F) goto basic_json_parser_36;
10070  goto basic_json_parser_32;
10071 basic_json_parser_40:
10072  ++m_cursor;
10073  if (m_limit <= m_cursor) fill_line_buffer(1); // LCOV_EXCL_LINE
10074  yych = *m_cursor;
10075  if (yych <= 0x8F) goto basic_json_parser_32;
10076  if (yych <= 0xBF) goto basic_json_parser_38;
10077  goto basic_json_parser_32;
10078 basic_json_parser_41:
10079  ++m_cursor;
10080  if (m_limit <= m_cursor) fill_line_buffer(1); // LCOV_EXCL_LINE
10081  yych = *m_cursor;
10082  if (yych <= 0x7F) goto basic_json_parser_32;
10083  if (yych <= 0xBF) goto basic_json_parser_38;
10084  goto basic_json_parser_32;
10085 basic_json_parser_42:
10086  ++m_cursor;
10087  if (m_limit <= m_cursor) fill_line_buffer(1); // LCOV_EXCL_LINE
10088  yych = *m_cursor;
10089  if (yych <= 0x7F) goto basic_json_parser_32;
10090  if (yych <= 0x8F) goto basic_json_parser_38;
10091  goto basic_json_parser_32;
10092 basic_json_parser_43:
10093  yyaccept = 2;
10094  yych = *(m_marker = ++m_cursor);
10095  if (yych <= '9') {
10096  if (yych == '.') goto basic_json_parser_47;
10097  if (yych >= '0') goto basic_json_parser_48;
10098  } else {
10099  if (yych <= 'E') {
10100  if (yych >= 'E') goto basic_json_parser_51;
10101  } else {
10102  if (yych == 'e') goto basic_json_parser_51;
10103  }
10104  }
10105 basic_json_parser_44:
10106  { last_token_type = token_type::value_integer; break; }
10107 basic_json_parser_45:
10108  yyaccept = 2;
10109  m_marker = ++m_cursor;
10110  if ((m_limit - m_cursor) < 3) fill_line_buffer(3); // LCOV_EXCL_LINE
10111  yych = *m_cursor;
10112  if (yych <= '9') {
10113  if (yych == '.') goto basic_json_parser_47;
10114  if (yych <= '/') goto basic_json_parser_44;
10115  goto basic_json_parser_45;
10116  } else {
10117  if (yych <= 'E') {
10118  if (yych <= 'D') goto basic_json_parser_44;
10119  goto basic_json_parser_51;
10120  } else {
10121  if (yych == 'e') goto basic_json_parser_51;
10122  goto basic_json_parser_44;
10123  }
10124  }
10125 basic_json_parser_47:
10126  yych = *++m_cursor;
10127  if (yych <= '/') goto basic_json_parser_32;
10128  if (yych <= '9') goto basic_json_parser_56;
10129  goto basic_json_parser_32;
10130 basic_json_parser_48:
10131  ++m_cursor;
10132  if (m_limit <= m_cursor) fill_line_buffer(1); // LCOV_EXCL_LINE
10133  yych = *m_cursor;
10134  if (yych <= '/') goto basic_json_parser_50;
10135  if (yych <= '9') goto basic_json_parser_48;
10136 basic_json_parser_50:
10137  { last_token_type = token_type::parse_error; break; }
10138 basic_json_parser_51:
10139  yych = *++m_cursor;
10140  if (yych <= ',') {
10141  if (yych == '+') goto basic_json_parser_59;
10142  goto basic_json_parser_32;
10143  } else {
10144  if (yych <= '-') goto basic_json_parser_59;
10145  if (yych <= '/') goto basic_json_parser_32;
10146  if (yych <= '9') goto basic_json_parser_60;
10147  goto basic_json_parser_32;
10148  }
10149 basic_json_parser_52:
10150  yych = *++m_cursor;
10151  if (yych == 'l') goto basic_json_parser_62;
10152  goto basic_json_parser_32;
10153 basic_json_parser_53:
10154  yych = *++m_cursor;
10155  if (yych == 'l') goto basic_json_parser_63;
10156  goto basic_json_parser_32;
10157 basic_json_parser_54:
10158  yych = *++m_cursor;
10159  if (yych == 'u') goto basic_json_parser_64;
10160  goto basic_json_parser_32;
10161 basic_json_parser_55:
10162  ++m_cursor;
10163  if (m_limit <= m_cursor) fill_line_buffer(1); // LCOV_EXCL_LINE
10164  yych = *m_cursor;
10165  if (yych <= '@') {
10166  if (yych <= '/') goto basic_json_parser_32;
10167  if (yych <= '9') goto basic_json_parser_65;
10168  goto basic_json_parser_32;
10169  } else {
10170  if (yych <= 'F') goto basic_json_parser_65;
10171  if (yych <= '`') goto basic_json_parser_32;
10172  if (yych <= 'f') goto basic_json_parser_65;
10173  goto basic_json_parser_32;
10174  }
10175 basic_json_parser_56:
10176  yyaccept = 3;
10177  m_marker = ++m_cursor;
10178  if ((m_limit - m_cursor) < 3) fill_line_buffer(3); // LCOV_EXCL_LINE
10179  yych = *m_cursor;
10180  if (yych <= 'D') {
10181  if (yych <= '/') goto basic_json_parser_58;
10182  if (yych <= '9') goto basic_json_parser_56;
10183  } else {
10184  if (yych <= 'E') goto basic_json_parser_51;
10185  if (yych == 'e') goto basic_json_parser_51;
10186  }
10187 basic_json_parser_58:
10188  { last_token_type = token_type::value_float; break; }
10189 basic_json_parser_59:
10190  yych = *++m_cursor;
10191  if (yych <= '/') goto basic_json_parser_32;
10192  if (yych >= ':') goto basic_json_parser_32;
10193 basic_json_parser_60:
10194  ++m_cursor;
10195  if (m_limit <= m_cursor) fill_line_buffer(1); // LCOV_EXCL_LINE
10196  yych = *m_cursor;
10197  if (yych <= '/') goto basic_json_parser_58;
10198  if (yych <= '9') goto basic_json_parser_60;
10199  goto basic_json_parser_58;
10200 basic_json_parser_62:
10201  yych = *++m_cursor;
10202  if (yych == 's') goto basic_json_parser_66;
10203  goto basic_json_parser_32;
10204 basic_json_parser_63:
10205  yych = *++m_cursor;
10206  if (yych == 'l') goto basic_json_parser_67;
10207  goto basic_json_parser_32;
10208 basic_json_parser_64:
10209  yych = *++m_cursor;
10210  if (yych == 'e') goto basic_json_parser_69;
10211  goto basic_json_parser_32;
10212 basic_json_parser_65:
10213  ++m_cursor;
10214  if (m_limit <= m_cursor) fill_line_buffer(1); // LCOV_EXCL_LINE
10215  yych = *m_cursor;
10216  if (yych <= '@') {
10217  if (yych <= '/') goto basic_json_parser_32;
10218  if (yych <= '9') goto basic_json_parser_71;
10219  goto basic_json_parser_32;
10220  } else {
10221  if (yych <= 'F') goto basic_json_parser_71;
10222  if (yych <= '`') goto basic_json_parser_32;
10223  if (yych <= 'f') goto basic_json_parser_71;
10224  goto basic_json_parser_32;
10225  }
10226 basic_json_parser_66:
10227  yych = *++m_cursor;
10228  if (yych == 'e') goto basic_json_parser_72;
10229  goto basic_json_parser_32;
10230 basic_json_parser_67:
10231  ++m_cursor;
10232  { last_token_type = token_type::literal_null; break; }
10233 basic_json_parser_69:
10234  ++m_cursor;
10235  { last_token_type = token_type::literal_true; break; }
10236 basic_json_parser_71:
10237  ++m_cursor;
10238  if (m_limit <= m_cursor) fill_line_buffer(1); // LCOV_EXCL_LINE
10239  yych = *m_cursor;
10240  if (yych <= '@') {
10241  if (yych <= '/') goto basic_json_parser_32;
10242  if (yych <= '9') goto basic_json_parser_74;
10243  goto basic_json_parser_32;
10244  } else {
10245  if (yych <= 'F') goto basic_json_parser_74;
10246  if (yych <= '`') goto basic_json_parser_32;
10247  if (yych <= 'f') goto basic_json_parser_74;
10248  goto basic_json_parser_32;
10249  }
10250 basic_json_parser_72:
10251  ++m_cursor;
10252  { last_token_type = token_type::literal_false; break; }
10253 basic_json_parser_74:
10254  ++m_cursor;
10255  if (m_limit <= m_cursor) fill_line_buffer(1); // LCOV_EXCL_LINE
10256  yych = *m_cursor;
10257  if (yych <= '@') {
10258  if (yych <= '/') goto basic_json_parser_32;
10259  if (yych <= '9') goto basic_json_parser_30;
10260  goto basic_json_parser_32;
10261  } else {
10262  if (yych <= 'F') goto basic_json_parser_30;
10263  if (yych <= '`') goto basic_json_parser_32;
10264  if (yych <= 'f') goto basic_json_parser_30;
10265  goto basic_json_parser_32;
10266  }
10267  }
10268 
10269  }
10270 
10271  return last_token_type;
10272  }
10273 
10302  void fill_line_buffer(size_t n = 0)
10303  {
10304  // if line buffer is used, m_content points to its data
10305  assert(m_line_buffer.empty()
10306  or m_content == reinterpret_cast<const lexer_char_t*>(m_line_buffer.data()));
10307 
10308  // if line buffer is used, m_limit is set past the end of its data
10309  assert(m_line_buffer.empty()
10310  or m_limit == m_content + m_line_buffer.size());
10311 
10312  // pointer relationships
10313  assert(m_content <= m_start);
10314  assert(m_start <= m_cursor);
10315  assert(m_cursor <= m_limit);
10316  assert(m_marker == nullptr or m_marker <= m_limit);
10317 
10318  // number of processed characters (p)
10319  const auto num_processed_chars = static_cast<size_t>(m_start - m_content);
10320  // offset for m_marker wrt. to m_start
10321  const auto offset_marker = (m_marker == nullptr) ? 0 : m_marker - m_start;
10322  // number of unprocessed characters (u)
10323  const auto offset_cursor = m_cursor - m_start;
10324 
10325  // no stream is used or end of file is reached
10326  if (m_stream == nullptr or m_stream->eof())
10327  {
10328  // m_start may or may not be pointing into m_line_buffer at
10329  // this point. We trust the standard library to do the right
10330  // thing. See http://stackoverflow.com/q/28142011/266378
10331  m_line_buffer.assign(m_start, m_limit);
10332 
10333  // append n characters to make sure that there is sufficient
10334  // space between m_cursor and m_limit
10335  m_line_buffer.append(1, '\x00');
10336  if (n > 0)
10337  {
10338  m_line_buffer.append(n - 1, '\x01');
10339  }
10340  }
10341  else
10342  {
10343  // delete processed characters from line buffer
10344  m_line_buffer.erase(0, num_processed_chars);
10345  // read next line from input stream
10346  m_line_buffer_tmp.clear();
10347  std::getline(*m_stream, m_line_buffer_tmp, '\n');
10348 
10349  // add line with newline symbol to the line buffer
10350  m_line_buffer += m_line_buffer_tmp;
10351  m_line_buffer.push_back('\n');
10352  }
10353 
10354  // set pointers
10355  m_content = reinterpret_cast<const lexer_char_t*>(m_line_buffer.data());
10356  assert(m_content != nullptr);
10357  m_start = m_content;
10358  m_marker = m_start + offset_marker;
10359  m_cursor = m_start + offset_cursor;
10360  m_limit = m_start + m_line_buffer.size();
10361  }
10362 
10364  string_t get_token_string() const
10365  {
10366  assert(m_start != nullptr);
10367  return string_t(reinterpret_cast<typename string_t::const_pointer>(m_start),
10368  static_cast<size_t>(m_cursor - m_start));
10369  }
10370 
10428  string_t get_string() const
10429  {
10430  assert(m_cursor - m_start >= 2);
10431 
10432  string_t result;
10433  result.reserve(static_cast<size_t>(m_cursor - m_start - 2));
10434 
10435  // iterate the result between the quotes
10436  for (const lexer_char_t* i = m_start + 1; i < m_cursor - 1; ++i)
10437  {
10438  // find next escape character
10439  auto e = std::find(i, m_cursor - 1, '\\');
10440  if (e != i)
10441  {
10442  // see https://github.com/nlohmann/json/issues/365#issuecomment-262874705
10443  for (auto k = i; k < e; k++)
10444  {
10445  result.push_back(static_cast<typename string_t::value_type>(*k));
10446  }
10447  i = e - 1; // -1 because of ++i
10448  }
10449  else
10450  {
10451  // processing escaped character
10452  // read next character
10453  ++i;
10454 
10455  switch (*i)
10456  {
10457  // the default escapes
10458  case 't':
10459  {
10460  result += "\t";
10461  break;
10462  }
10463  case 'b':
10464  {
10465  result += "\b";
10466  break;
10467  }
10468  case 'f':
10469  {
10470  result += "\f";
10471  break;
10472  }
10473  case 'n':
10474  {
10475  result += "\n";
10476  break;
10477  }
10478  case 'r':
10479  {
10480  result += "\r";
10481  break;
10482  }
10483  case '\\':
10484  {
10485  result += "\\";
10486  break;
10487  }
10488  case '/':
10489  {
10490  result += "/";
10491  break;
10492  }
10493  case '"':
10494  {
10495  result += "\"";
10496  break;
10497  }
10498 
10499  // unicode
10500  case 'u':
10501  {
10502  // get code xxxx from uxxxx
10503  auto codepoint = std::strtoul(std::string(reinterpret_cast<typename string_t::const_pointer>(i + 1),
10504  4).c_str(), nullptr, 16);
10505 
10506  // check if codepoint is a high surrogate
10507  if (codepoint >= 0xD800 and codepoint <= 0xDBFF)
10508  {
10509  // make sure there is a subsequent unicode
10510  if ((i + 6 >= m_limit) or * (i + 5) != '\\' or * (i + 6) != 'u')
10511  {
10512  JSON_THROW(std::invalid_argument("missing low surrogate"));
10513  }
10514 
10515  // get code yyyy from uxxxx\uyyyy
10516  auto codepoint2 = std::strtoul(std::string(reinterpret_cast<typename string_t::const_pointer>
10517  (i + 7), 4).c_str(), nullptr, 16);
10518  result += to_unicode(codepoint, codepoint2);
10519  // skip the next 10 characters (xxxx\uyyyy)
10520  i += 10;
10521  }
10522  else if (codepoint >= 0xDC00 and codepoint <= 0xDFFF)
10523  {
10524  // we found a lone low surrogate
10525  JSON_THROW(std::invalid_argument("missing high surrogate"));
10526  }
10527  else
10528  {
10529  // add unicode character(s)
10530  result += to_unicode(codepoint);
10531  // skip the next four characters (xxxx)
10532  i += 4;
10533  }
10534  break;
10535  }
10536  }
10537  }
10538  }
10539 
10540  return result;
10541  }
10542 
10543 
10553  struct strtonum
10554  {
10555  public:
10556  strtonum(const char* start, const char* end)
10557  : m_start(start), m_end(end)
10558  {}
10559 
10566  template<typename T, typename = typename std::enable_if<std::is_arithmetic<T>::value>::type>
10567  bool to(T& val) const
10568  {
10569  return parse(val, std::is_integral<T>());
10570  }
10571 
10572  private:
10573  const char* const m_start = nullptr;
10574  const char* const m_end = nullptr;
10575 
10576  // floating-point conversion
10577 
10578  // overloaded wrappers for strtod/strtof/strtold
10579  // that will be called from parse<floating_point_t>
10580  static void strtof(float& f, const char* str, char** endptr)
10581  {
10582  f = std::strtof(str, endptr);
10583  }
10584 
10585  static void strtof(double& f, const char* str, char** endptr)
10586  {
10587  f = std::strtod(str, endptr);
10588  }
10589 
10590  static void strtof(long double& f, const char* str, char** endptr)
10591  {
10592  f = std::strtold(str, endptr);
10593  }
10594 
10595  template<typename T>
10596  bool parse(T& value, /*is_integral=*/std::false_type) const
10597  {
10598  // replace decimal separator with locale-specific version,
10599  // when necessary; data will point to either the original
10600  // string, or buf, or tempstr containing the fixed string.
10601  std::string tempstr;
10602  std::array<char, 64> buf;
10603  const size_t len = static_cast<size_t>(m_end - m_start);
10604 
10605  // lexer will reject empty numbers
10606  assert(len > 0);
10607 
10608  // since dealing with strtod family of functions, we're
10609  // getting the decimal point char from the C locale facilities
10610  // instead of C++'s numpunct facet of the current std::locale
10611  const auto loc = localeconv();
10612  assert(loc != nullptr);
10613  const char decimal_point_char = (loc->decimal_point == nullptr) ? '.' : loc->decimal_point[0];
10614 
10615  const char* data = m_start;
10616 
10617  if (decimal_point_char != '.')
10618  {
10619  const size_t ds_pos = static_cast<size_t>(std::find(m_start, m_end, '.') - m_start);
10620 
10621  if (ds_pos != len)
10622  {
10623  // copy the data into the local buffer or tempstr, if
10624  // buffer is too small; replace decimal separator, and
10625  // update data to point to the modified bytes
10626  if ((len + 1) < buf.size())
10627  {
10628  std::copy(m_start, m_end, buf.begin());
10629  buf[len] = 0;
10630  buf[ds_pos] = decimal_point_char;
10631  data = buf.data();
10632  }
10633  else
10634  {
10635  tempstr.assign(m_start, m_end);
10636  tempstr[ds_pos] = decimal_point_char;
10637  data = tempstr.c_str();
10638  }
10639  }
10640  }
10641 
10642  char* endptr = nullptr;
10643  value = 0;
10644  // this calls appropriate overload depending on T
10645  strtof(value, data, &endptr);
10646 
10647  // parsing was successful iff strtof parsed exactly the number
10648  // of characters determined by the lexer (len)
10649  const bool ok = (endptr == (data + len));
10650 
10651  if (ok and (value == static_cast<T>(0.0)) and (*data == '-'))
10652  {
10653  // some implementations forget to negate the zero
10654  value = -0.0;
10655  }
10656 
10657  return ok;
10658  }
10659 
10660  // integral conversion
10661 
10662  signed long long parse_integral(char** endptr, /*is_signed*/std::true_type) const
10663  {
10664  return std::strtoll(m_start, endptr, 10);
10665  }
10666 
10667  unsigned long long parse_integral(char** endptr, /*is_signed*/std::false_type) const
10668  {
10669  return std::strtoull(m_start, endptr, 10);
10670  }
10671 
10672  template<typename T>
10673  bool parse(T& value, /*is_integral=*/std::true_type) const
10674  {
10675  char* endptr = nullptr;
10676  errno = 0; // these are thread-local
10677  const auto x = parse_integral(&endptr, std::is_signed<T>());
10678 
10679  // called right overload?
10680  static_assert(std::is_signed<T>() == std::is_signed<decltype(x)>(), "");
10681 
10682  value = static_cast<T>(x);
10683 
10684  return (x == static_cast<decltype(x)>(value)) // x fits into destination T
10685  and (x < 0) == (value < 0) // preserved sign
10686  //and ((x != 0) or is_integral()) // strto[u]ll did nto fail
10687  and (errno == 0) // strto[u]ll did not overflow
10688  and (m_start < m_end) // token was not empty
10689  and (endptr == m_end); // parsed entire token exactly
10690  }
10691  };
10692 
10712  bool get_number(basic_json& result, const token_type token) const
10713  {
10714  assert(m_start != nullptr);
10715  assert(m_start < m_cursor);
10716  assert((token == token_type::value_unsigned) or
10717  (token == token_type::value_integer) or
10718  (token == token_type::value_float));
10719 
10720  strtonum num_converter(reinterpret_cast<const char*>(m_start),
10721  reinterpret_cast<const char*>(m_cursor));
10722 
10723  switch (token)
10724  {
10725  case lexer::token_type::value_unsigned:
10726  {
10727  number_unsigned_t val;
10728  if (num_converter.to(val))
10729  {
10730  // parsing successful
10731  result.m_type = value_t::number_unsigned;
10732  result.m_value = val;
10733  return true;
10734  }
10735  break;
10736  }
10737 
10738  case lexer::token_type::value_integer:
10739  {
10740  number_integer_t val;
10741  if (num_converter.to(val))
10742  {
10743  // parsing successful
10744  result.m_type = value_t::number_integer;
10745  result.m_value = val;
10746  return true;
10747  }
10748  break;
10749  }
10750 
10751  default:
10752  {
10753  break;
10754  }
10755  }
10756 
10757  // parse float (either explicitly or because a previous conversion
10758  // failed)
10759  number_float_t val;
10760  if (num_converter.to(val))
10761  {
10762  // parsing successful
10763  result.m_type = value_t::number_float;
10764  result.m_value = val;
10765 
10766  // replace infinity and NAN by null
10767  if (not std::isfinite(result.m_value.number_float))
10768  {
10769  result.m_type = value_t::null;
10770  result.m_value = basic_json::json_value();
10771  }
10772 
10773  return true;
10774  }
10775 
10776  // couldn't parse number in any format
10777  return false;
10778  }
10779 
10780  private:
10782  std::istream* m_stream = nullptr;
10784  string_t m_line_buffer {};
10786  string_t m_line_buffer_tmp {};
10788  const lexer_char_t* m_content = nullptr;
10790  const lexer_char_t* m_start = nullptr;
10792  const lexer_char_t* m_marker = nullptr;
10794  const lexer_char_t* m_cursor = nullptr;
10796  const lexer_char_t* m_limit = nullptr;
10798  token_type last_token_type = token_type::end_of_input;
10799  };
10800 
10806  class parser
10807  {
10808  public:
10810  parser(const char* buff, const parser_callback_t cb = nullptr)
10811  : callback(cb),
10812  m_lexer(reinterpret_cast<const typename lexer::lexer_char_t*>(buff), std::strlen(buff))
10813  {}
10814 
10816  parser(std::istream& is, const parser_callback_t cb = nullptr)
10817  : callback(cb), m_lexer(is)
10818  {}
10819 
10821  template<class IteratorType, typename std::enable_if<
10822  std::is_same<typename std::iterator_traits<IteratorType>::iterator_category, std::random_access_iterator_tag>::value
10823  , int>::type
10824  = 0>
10825  parser(IteratorType first, IteratorType last, const parser_callback_t cb = nullptr)
10826  : callback(cb),
10827  m_lexer(reinterpret_cast<const typename lexer::lexer_char_t*>(&(*first)),
10828  static_cast<size_t>(std::distance(first, last)))
10829  {}
10830 
10832  basic_json parse()
10833  {
10834  // read first token
10835  get_token();
10836 
10837  basic_json result = parse_internal(true);
10838  result.assert_invariant();
10839 
10840  expect(lexer::token_type::end_of_input);
10841 
10842  // return parser result and replace it with null in case the
10843  // top-level value was discarded by the callback function
10844  return result.is_discarded() ? basic_json() : std::move(result);
10845  }
10846 
10847  private:
10849  basic_json parse_internal(bool keep)
10850  {
10851  auto result = basic_json(value_t::discarded);
10852 
10853  switch (last_token)
10854  {
10855  case lexer::token_type::begin_object:
10856  {
10857  if (keep and (not callback
10858  or ((keep = callback(depth++, parse_event_t::object_start, result)) != 0)))
10859  {
10860  // explicitly set result to object to cope with {}
10861  result.m_type = value_t::object;
10862  result.m_value = value_t::object;
10863  }
10864 
10865  // read next token
10866  get_token();
10867 
10868  // closing } -> we are done
10869  if (last_token == lexer::token_type::end_object)
10870  {
10871  get_token();
10872  if (keep and callback and not callback(--depth, parse_event_t::object_end, result))
10873  {
10874  result = basic_json(value_t::discarded);
10875  }
10876  return result;
10877  }
10878 
10879  // no comma is expected here
10880  unexpect(lexer::token_type::value_separator);
10881 
10882  // otherwise: parse key-value pairs
10883  do
10884  {
10885  // ugly, but could be fixed with loop reorganization
10886  if (last_token == lexer::token_type::value_separator)
10887  {
10888  get_token();
10889  }
10890 
10891  // store key
10892  expect(lexer::token_type::value_string);
10893  const auto key = m_lexer.get_string();
10894 
10895  bool keep_tag = false;
10896  if (keep)
10897  {
10898  if (callback)
10899  {
10900  basic_json k(key);
10901  keep_tag = callback(depth, parse_event_t::key, k);
10902  }
10903  else
10904  {
10905  keep_tag = true;
10906  }
10907  }
10908 
10909  // parse separator (:)
10910  get_token();
10911  expect(lexer::token_type::name_separator);
10912 
10913  // parse and add value
10914  get_token();
10915  auto value = parse_internal(keep);
10916  if (keep and keep_tag and not value.is_discarded())
10917  {
10918  result[key] = std::move(value);
10919  }
10920  }
10921  while (last_token == lexer::token_type::value_separator);
10922 
10923  // closing }
10924  expect(lexer::token_type::end_object);
10925  get_token();
10926  if (keep and callback and not callback(--depth, parse_event_t::object_end, result))
10927  {
10928  result = basic_json(value_t::discarded);
10929  }
10930 
10931  return result;
10932  }
10933 
10934  case lexer::token_type::begin_array:
10935  {
10936  if (keep and (not callback
10937  or ((keep = callback(depth++, parse_event_t::array_start, result)) != 0)))
10938  {
10939  // explicitly set result to object to cope with []
10940  result.m_type = value_t::array;
10941  result.m_value = value_t::array;
10942  }
10943 
10944  // read next token
10945  get_token();
10946 
10947  // closing ] -> we are done
10948  if (last_token == lexer::token_type::end_array)
10949  {
10950  get_token();
10951  if (callback and not callback(--depth, parse_event_t::array_end, result))
10952  {
10953  result = basic_json(value_t::discarded);
10954  }
10955  return result;
10956  }
10957 
10958  // no comma is expected here
10959  unexpect(lexer::token_type::value_separator);
10960 
10961  // otherwise: parse values
10962  do
10963  {
10964  // ugly, but could be fixed with loop reorganization
10965  if (last_token == lexer::token_type::value_separator)
10966  {
10967  get_token();
10968  }
10969 
10970  // parse value
10971  auto value = parse_internal(keep);
10972  if (keep and not value.is_discarded())
10973  {
10974  result.push_back(std::move(value));
10975  }
10976  }
10977  while (last_token == lexer::token_type::value_separator);
10978 
10979  // closing ]
10980  expect(lexer::token_type::end_array);
10981  get_token();
10982  if (keep and callback and not callback(--depth, parse_event_t::array_end, result))
10983  {
10984  result = basic_json(value_t::discarded);
10985  }
10986 
10987  return result;
10988  }
10989 
10990  case lexer::token_type::literal_null:
10991  {
10992  get_token();
10993  result.m_type = value_t::null;
10994  break;
10995  }
10996 
10997  case lexer::token_type::value_string:
10998  {
10999  const auto s = m_lexer.get_string();
11000  get_token();
11001  result = basic_json(s);
11002  break;
11003  }
11004 
11005  case lexer::token_type::literal_true:
11006  {
11007  get_token();
11008  result.m_type = value_t::boolean;
11009  result.m_value = true;
11010  break;
11011  }
11012 
11013  case lexer::token_type::literal_false:
11014  {
11015  get_token();
11016  result.m_type = value_t::boolean;
11017  result.m_value = false;
11018  break;
11019  }
11020 
11021  case lexer::token_type::value_unsigned:
11022  case lexer::token_type::value_integer:
11023  case lexer::token_type::value_float:
11024  {
11025  m_lexer.get_number(result, last_token);
11026  get_token();
11027  break;
11028  }
11029 
11030  default:
11031  {
11032  // the last token was unexpected
11033  unexpect(last_token);
11034  }
11035  }
11036 
11037  if (keep and callback and not callback(depth, parse_event_t::value, result))
11038  {
11039  result = basic_json(value_t::discarded);
11040  }
11041  return result;
11042  }
11043 
11045  typename lexer::token_type get_token()
11046  {
11047  last_token = m_lexer.scan();
11048  return last_token;
11049  }
11050 
11051  void expect(typename lexer::token_type t) const
11052  {
11053  if (t != last_token)
11054  {
11055  std::string error_msg = "parse error - unexpected ";
11056  error_msg += (last_token == lexer::token_type::parse_error ? ("'" + m_lexer.get_token_string() +
11057  "'") :
11058  lexer::token_type_name(last_token));
11059  error_msg += "; expected " + lexer::token_type_name(t);
11060  JSON_THROW(std::invalid_argument(error_msg));
11061  }
11062  }
11063 
11064  void unexpect(typename lexer::token_type t) const
11065  {
11066  if (t == last_token)
11067  {
11068  std::string error_msg = "parse error - unexpected ";
11069  error_msg += (last_token == lexer::token_type::parse_error ? ("'" + m_lexer.get_token_string() +
11070  "'") :
11071  lexer::token_type_name(last_token));
11072  JSON_THROW(std::invalid_argument(error_msg));
11073  }
11074  }
11075 
11076  private:
11078  int depth = 0;
11080  const parser_callback_t callback = nullptr;
11082  typename lexer::token_type last_token = lexer::token_type::uninitialized;
11084  lexer m_lexer;
11085  };
11086 
11087  public:
11100  {
11102  friend class basic_json;
11103 
11104  public:
11127  explicit json_pointer(const std::string& s = "")
11128  : reference_tokens(split(s))
11129  {}
11130 
11146  std::string to_string() const noexcept
11147  {
11148  return std::accumulate(reference_tokens.begin(),
11149  reference_tokens.end(), std::string{},
11150  [](const std::string & a, const std::string & b)
11151  {
11152  return a + "/" + escape(b);
11153  });
11154  }
11155 
11157  operator std::string() const
11158  {
11159  return to_string();
11160  }
11162  private:
11164  std::string pop_back()
11165  {
11166  if (is_root())
11167  {
11168  JSON_THROW(std::domain_error("JSON pointer has no parent"));
11169  }
11170 
11171  auto last = reference_tokens.back();
11172  reference_tokens.pop_back();
11173  return last;
11174  }
11175 
11177  bool is_root() const
11178  {
11179  return reference_tokens.empty();
11180  }
11181 
11182  json_pointer top() const
11183  {
11184  if (is_root())
11185  {
11186  JSON_THROW(std::domain_error("JSON pointer has no parent"));
11187  }
11188 
11189  json_pointer result = *this;
11190  result.reference_tokens = {reference_tokens[0]};
11191  return result;
11192  }
11193 
11199  reference get_and_create(reference j) const
11200  {
11201  pointer result = &j;
11202 
11203  // in case no reference tokens exist, return a reference to the
11204  // JSON value j which will be overwritten by a primitive value
11205  for (const auto& reference_token : reference_tokens)
11206  {
11207  switch (result->m_type)
11208  {
11209  case value_t::null:
11210  {
11211  if (reference_token == "0")
11212  {
11213  // start a new array if reference token is 0
11214  result = &result->operator[](0);
11215  }
11216  else
11217  {
11218  // start a new object otherwise
11219  result = &result->operator[](reference_token);
11220  }
11221  break;
11222  }
11223 
11224  case value_t::object:
11225  {
11226  // create an entry in the object
11227  result = &result->operator[](reference_token);
11228  break;
11229  }
11230 
11231  case value_t::array:
11232  {
11233  // create an entry in the array
11234  result = &result->operator[](static_cast<size_type>(std::stoi(reference_token)));
11235  break;
11236  }
11237 
11238  /*
11239  The following code is only reached if there exists a
11240  reference token _and_ the current value is primitive. In
11241  this case, we have an error situation, because primitive
11242  values may only occur as single value; that is, with an
11243  empty list of reference tokens.
11244  */
11245  default:
11246  {
11247  JSON_THROW(std::domain_error("invalid value to unflatten"));
11248  }
11249  }
11250  }
11251 
11252  return *result;
11253  }
11254 
11274  reference get_unchecked(pointer ptr) const
11275  {
11276  for (const auto& reference_token : reference_tokens)
11277  {
11278  // convert null values to arrays or objects before continuing
11279  if (ptr->m_type == value_t::null)
11280  {
11281  // check if reference token is a number
11282  const bool nums = std::all_of(reference_token.begin(),
11283  reference_token.end(),
11284  [](const char x)
11285  {
11286  return std::isdigit(x);
11287  });
11288 
11289  // change value to array for numbers or "-" or to object
11290  // otherwise
11291  if (nums or reference_token == "-")
11292  {
11293  *ptr = value_t::array;
11294  }
11295  else
11296  {
11297  *ptr = value_t::object;
11298  }
11299  }
11300 
11301  switch (ptr->m_type)
11302  {
11303  case value_t::object:
11304  {
11305  // use unchecked object access
11306  ptr = &ptr->operator[](reference_token);
11307  break;
11308  }
11309 
11310  case value_t::array:
11311  {
11312  // error condition (cf. RFC 6901, Sect. 4)
11313  if (reference_token.size() > 1 and reference_token[0] == '0')
11314  {
11315  JSON_THROW(std::domain_error("array index must not begin with '0'"));
11316  }
11317 
11318  if (reference_token == "-")
11319  {
11320  // explicitly treat "-" as index beyond the end
11321  ptr = &ptr->operator[](ptr->m_value.array->size());
11322  }
11323  else
11324  {
11325  // convert array index to number; unchecked access
11326  ptr = &ptr->operator[](static_cast<size_type>(std::stoi(reference_token)));
11327  }
11328  break;
11329  }
11330 
11331  default:
11332  {
11333  JSON_THROW(std::out_of_range("unresolved reference token '" + reference_token + "'"));
11334  }
11335  }
11336  }
11337 
11338  return *ptr;
11339  }
11340 
11341  reference get_checked(pointer ptr) const
11342  {
11343  for (const auto& reference_token : reference_tokens)
11344  {
11345  switch (ptr->m_type)
11346  {
11347  case value_t::object:
11348  {
11349  // note: at performs range check
11350  ptr = &ptr->at(reference_token);
11351  break;
11352  }
11353 
11354  case value_t::array:
11355  {
11356  if (reference_token == "-")
11357  {
11358  // "-" always fails the range check
11359  JSON_THROW(std::out_of_range("array index '-' (" +
11360  std::to_string(ptr->m_value.array->size()) +
11361  ") is out of range"));
11362  }
11363 
11364  // error condition (cf. RFC 6901, Sect. 4)
11365  if (reference_token.size() > 1 and reference_token[0] == '0')
11366  {
11367  JSON_THROW(std::domain_error("array index must not begin with '0'"));
11368  }
11369 
11370  // note: at performs range check
11371  ptr = &ptr->at(static_cast<size_type>(std::stoi(reference_token)));
11372  break;
11373  }
11374 
11375  default:
11376  {
11377  JSON_THROW(std::out_of_range("unresolved reference token '" + reference_token + "'"));
11378  }
11379  }
11380  }
11381 
11382  return *ptr;
11383  }
11384 
11393  const_reference get_unchecked(const_pointer ptr) const
11394  {
11395  for (const auto& reference_token : reference_tokens)
11396  {
11397  switch (ptr->m_type)
11398  {
11399  case value_t::object:
11400  {
11401  // use unchecked object access
11402  ptr = &ptr->operator[](reference_token);
11403  break;
11404  }
11405 
11406  case value_t::array:
11407  {
11408  if (reference_token == "-")
11409  {
11410  // "-" cannot be used for const access
11411  JSON_THROW(std::out_of_range("array index '-' (" +
11412  std::to_string(ptr->m_value.array->size()) +
11413  ") is out of range"));
11414  }
11415 
11416  // error condition (cf. RFC 6901, Sect. 4)
11417  if (reference_token.size() > 1 and reference_token[0] == '0')
11418  {
11419  JSON_THROW(std::domain_error("array index must not begin with '0'"));
11420  }
11421 
11422  // use unchecked array access
11423  ptr = &ptr->operator[](static_cast<size_type>(std::stoi(reference_token)));
11424  break;
11425  }
11426 
11427  default:
11428  {
11429  JSON_THROW(std::out_of_range("unresolved reference token '" + reference_token + "'"));
11430  }
11431  }
11432  }
11433 
11434  return *ptr;
11435  }
11436 
11437  const_reference get_checked(const_pointer ptr) const
11438  {
11439  for (const auto& reference_token : reference_tokens)
11440  {
11441  switch (ptr->m_type)
11442  {
11443  case value_t::object:
11444  {
11445  // note: at performs range check
11446  ptr = &ptr->at(reference_token);
11447  break;
11448  }
11449 
11450  case value_t::array:
11451  {
11452  if (reference_token == "-")
11453  {
11454  // "-" always fails the range check
11455  JSON_THROW(std::out_of_range("array index '-' (" +
11456  std::to_string(ptr->m_value.array->size()) +
11457  ") is out of range"));
11458  }
11459 
11460  // error condition (cf. RFC 6901, Sect. 4)
11461  if (reference_token.size() > 1 and reference_token[0] == '0')
11462  {
11463  JSON_THROW(std::domain_error("array index must not begin with '0'"));
11464  }
11465 
11466  // note: at performs range check
11467  ptr = &ptr->at(static_cast<size_type>(std::stoi(reference_token)));
11468  break;
11469  }
11470 
11471  default:
11472  {
11473  JSON_THROW(std::out_of_range("unresolved reference token '" + reference_token + "'"));
11474  }
11475  }
11476  }
11477 
11478  return *ptr;
11479  }
11480 
11482  static std::vector<std::string> split(const std::string& reference_string)
11483  {
11484  std::vector<std::string> result;
11485 
11486  // special case: empty reference string -> no reference tokens
11487  if (reference_string.empty())
11488  {
11489  return result;
11490  }
11491 
11492  // check if nonempty reference string begins with slash
11493  if (reference_string[0] != '/')
11494  {
11495  JSON_THROW(std::domain_error("JSON pointer must be empty or begin with '/'"));
11496  }
11497 
11498  // extract the reference tokens:
11499  // - slash: position of the last read slash (or end of string)
11500  // - start: position after the previous slash
11501  for (
11502  // search for the first slash after the first character
11503  size_t slash = reference_string.find_first_of('/', 1),
11504  // set the beginning of the first reference token
11505  start = 1;
11506  // we can stop if start == string::npos+1 = 0
11507  start != 0;
11508  // set the beginning of the next reference token
11509  // (will eventually be 0 if slash == std::string::npos)
11510  start = slash + 1,
11511  // find next slash
11512  slash = reference_string.find_first_of('/', start))
11513  {
11514  // use the text between the beginning of the reference token
11515  // (start) and the last slash (slash).
11516  auto reference_token = reference_string.substr(start, slash - start);
11517 
11518  // check reference tokens are properly escaped
11519  for (size_t pos = reference_token.find_first_of('~');
11520  pos != std::string::npos;
11521  pos = reference_token.find_first_of('~', pos + 1))
11522  {
11523  assert(reference_token[pos] == '~');
11524 
11525  // ~ must be followed by 0 or 1
11526  if (pos == reference_token.size() - 1 or
11527  (reference_token[pos + 1] != '0' and
11528  reference_token[pos + 1] != '1'))
11529  {
11530  JSON_THROW(std::domain_error("escape error: '~' must be followed with '0' or '1'"));
11531  }
11532  }
11533 
11534  // finally, store the reference token
11535  unescape(reference_token);
11536  result.push_back(reference_token);
11537  }
11538 
11539  return result;
11540  }
11541 
11542  private:
11555  static void replace_substring(std::string& s,
11556  const std::string& f,
11557  const std::string& t)
11558  {
11559  assert(not f.empty());
11560 
11561  for (
11562  size_t pos = s.find(f); // find first occurrence of f
11563  pos != std::string::npos; // make sure f was found
11564  s.replace(pos, f.size(), t), // replace with t
11565  pos = s.find(f, pos + t.size()) // find next occurrence of f
11566  );
11567  }
11568 
11570  static std::string escape(std::string s)
11571  {
11572  // escape "~"" to "~0" and "/" to "~1"
11573  replace_substring(s, "~", "~0");
11574  replace_substring(s, "/", "~1");
11575  return s;
11576  }
11577 
11579  static void unescape(std::string& s)
11580  {
11581  // first transform any occurrence of the sequence '~1' to '/'
11582  replace_substring(s, "~1", "/");
11583  // then transform any occurrence of the sequence '~0' to '~'
11584  replace_substring(s, "~0", "~");
11585  }
11586 
11594  static void flatten(const std::string& reference_string,
11595  const basic_json& value,
11596  basic_json& result)
11597  {
11598  switch (value.m_type)
11599  {
11600  case value_t::array:
11601  {
11602  if (value.m_value.array->empty())
11603  {
11604  // flatten empty array as null
11605  result[reference_string] = nullptr;
11606  }
11607  else
11608  {
11609  // iterate array and use index as reference string
11610  for (size_t i = 0; i < value.m_value.array->size(); ++i)
11611  {
11612  flatten(reference_string + "/" + std::to_string(i),
11613  value.m_value.array->operator[](i), result);
11614  }
11615  }
11616  break;
11617  }
11618 
11619  case value_t::object:
11620  {
11621  if (value.m_value.object->empty())
11622  {
11623  // flatten empty object as null
11624  result[reference_string] = nullptr;
11625  }
11626  else
11627  {
11628  // iterate object and use keys as reference string
11629  for (const auto& element : *value.m_value.object)
11630  {
11631  flatten(reference_string + "/" + escape(element.first),
11632  element.second, result);
11633  }
11634  }
11635  break;
11636  }
11637 
11638  default:
11639  {
11640  // add primitive value with its reference string
11641  result[reference_string] = value;
11642  break;
11643  }
11644  }
11645  }
11646 
11652  static basic_json unflatten(const basic_json& value)
11653  {
11654  if (not value.is_object())
11655  {
11656  JSON_THROW(std::domain_error("only objects can be unflattened"));
11657  }
11658 
11659  basic_json result;
11660 
11661  // iterate the JSON object values
11662  for (const auto& element : *value.m_value.object)
11663  {
11664  if (not element.second.is_primitive())
11665  {
11666  JSON_THROW(std::domain_error("values in object must be primitive"));
11667  }
11668 
11669  // assign value to reference pointed to by JSON pointer; Note
11670  // that if the JSON pointer is "" (i.e., points to the whole
11671  // value), function get_and_create returns a reference to
11672  // result itself. An assignment will then create a primitive
11673  // value.
11674  json_pointer(element.first).get_and_create(result) = element.second;
11675  }
11676 
11677  return result;
11678  }
11679 
11680  private:
11681  friend bool operator==(json_pointer const& lhs,
11682  json_pointer const& rhs) noexcept
11683  {
11684  return lhs.reference_tokens == rhs.reference_tokens;
11685  }
11686 
11687  friend bool operator!=(json_pointer const& lhs,
11688  json_pointer const& rhs) noexcept
11689  {
11690  return !(lhs == rhs);
11691  }
11692 
11694  std::vector<std::string> reference_tokens {};
11695  };
11696 
11698  // JSON Pointer support //
11700 
11703 
11737  reference operator[](const json_pointer& ptr)
11738  {
11739  return ptr.get_unchecked(this);
11740  }
11764  const_reference operator[](const json_pointer& ptr) const
11765  {
11766  return ptr.get_unchecked(this);
11767  }
11789  reference at(const json_pointer& ptr)
11790  {
11791  return ptr.get_checked(this);
11792  }
11814  const_reference at(const json_pointer& ptr) const
11815  {
11816  return ptr.get_checked(this);
11817  }
11841  basic_json flatten() const
11842  {
11843  basic_json result(value_t::object);
11844  json_pointer::flatten("", *this, result);
11845  return result;
11846  }
11847 
11875  basic_json unflatten() const
11876  {
11877  return json_pointer::unflatten(*this);
11878  }
11881 
11883  // JSON Patch functions //
11885 
11888 
11925  basic_json patch(const basic_json& json_patch) const
11926  {
11927  // make a working copy to apply the patch to
11928  basic_json result = *this;
11930  // the valid JSON Patch operations
11931  enum class patch_operations {add, remove, replace, move, copy, test, invalid};
11932 
11933  const auto get_op = [](const std::string op)
11934  {
11935  if (op == "add")
11936  {
11937  return patch_operations::add;
11938  }
11939  if (op == "remove")
11940  {
11941  return patch_operations::remove;
11942  }
11943  if (op == "replace")
11944  {
11945  return patch_operations::replace;
11946  }
11947  if (op == "move")
11948  {
11949  return patch_operations::move;
11950  }
11951  if (op == "copy")
11952  {
11953  return patch_operations::copy;
11954  }
11955  if (op == "test")
11956  {
11957  return patch_operations::test;
11958  }
11959 
11960  return patch_operations::invalid;
11961  };
11962 
11963  // wrapper for "add" operation; add value at ptr
11964  const auto operation_add = [&result](json_pointer & ptr, basic_json val)
11965  {
11966  // adding to the root of the target document means replacing it
11967  if (ptr.is_root())
11968  {
11969  result = val;
11970  }
11971  else
11972  {
11973  // make sure the top element of the pointer exists
11974  json_pointer top_pointer = ptr.top();
11975  if (top_pointer != ptr)
11976  {
11977  result.at(top_pointer);
11978  }
11979 
11980  // get reference to parent of JSON pointer ptr
11981  const auto last_path = ptr.pop_back();
11982  basic_json& parent = result[ptr];
11983 
11984  switch (parent.m_type)
11985  {
11986  case value_t::null:
11987  case value_t::object:
11988  {
11989  // use operator[] to add value
11990  parent[last_path] = val;
11991  break;
11992  }
11993 
11994  case value_t::array:
11995  {
11996  if (last_path == "-")
11997  {
11998  // special case: append to back
11999  parent.push_back(val);
12000  }
12001  else
12002  {
12003  const auto idx = std::stoi(last_path);
12004  if (static_cast<size_type>(idx) > parent.size())
12005  {
12006  // avoid undefined behavior
12007  JSON_THROW(std::out_of_range("array index " + std::to_string(idx) + " is out of range"));
12008  }
12009  else
12010  {
12011  // default case: insert add offset
12012  parent.insert(parent.begin() + static_cast<difference_type>(idx), val);
12013  }
12014  }
12015  break;
12016  }
12017 
12018  default:
12019  {
12020  // if there exists a parent it cannot be primitive
12021  assert(false); // LCOV_EXCL_LINE
12022  }
12023  }
12024  }
12025  };
12026 
12027  // wrapper for "remove" operation; remove value at ptr
12028  const auto operation_remove = [&result](json_pointer & ptr)
12029  {
12030  // get reference to parent of JSON pointer ptr
12031  const auto last_path = ptr.pop_back();
12032  basic_json& parent = result.at(ptr);
12033 
12034  // remove child
12035  if (parent.is_object())
12036  {
12037  // perform range check
12038  auto it = parent.find(last_path);
12039  if (it != parent.end())
12040  {
12041  parent.erase(it);
12042  }
12043  else
12044  {
12045  JSON_THROW(std::out_of_range("key '" + last_path + "' not found"));
12046  }
12047  }
12048  else if (parent.is_array())
12049  {
12050  // note erase performs range check
12051  parent.erase(static_cast<size_type>(std::stoi(last_path)));
12052  }
12053  };
12054 
12055  // type check
12056  if (not json_patch.is_array())
12057  {
12058  // a JSON patch must be an array of objects
12059  JSON_THROW(std::invalid_argument("JSON patch must be an array of objects"));
12060  }
12061 
12062  // iterate and apply the operations
12063  for (const auto& val : json_patch)
12064  {
12065  // wrapper to get a value for an operation
12066  const auto get_value = [&val](const std::string & op,
12067  const std::string & member,
12068  bool string_type) -> basic_json&
12069  {
12070  // find value
12071  auto it = val.m_value.object->find(member);
12072 
12073  // context-sensitive error message
12074  const auto error_msg = (op == "op") ? "operation" : "operation '" + op + "'";
12075 
12076  // check if desired value is present
12077  if (it == val.m_value.object->end())
12078  {
12079  JSON_THROW(std::invalid_argument(error_msg + " must have member '" + member + "'"));
12080  }
12081 
12082  // check if result is of type string
12083  if (string_type and not it->second.is_string())
12084  {
12085  JSON_THROW(std::invalid_argument(error_msg + " must have string member '" + member + "'"));
12086  }
12087 
12088  // no error: return value
12089  return it->second;
12090  };
12091 
12092  // type check
12093  if (not val.is_object())
12094  {
12095  JSON_THROW(std::invalid_argument("JSON patch must be an array of objects"));
12096  }
12097 
12098  // collect mandatory members
12099  const std::string op = get_value("op", "op", true);
12100  const std::string path = get_value(op, "path", true);
12101  json_pointer ptr(path);
12102 
12103  switch (get_op(op))
12104  {
12105  case patch_operations::add:
12106  {
12107  operation_add(ptr, get_value("add", "value", false));
12108  break;
12109  }
12110 
12111  case patch_operations::remove:
12112  {
12113  operation_remove(ptr);
12114  break;
12115  }
12116 
12117  case patch_operations::replace:
12118  {
12119  // the "path" location must exist - use at()
12120  result.at(ptr) = get_value("replace", "value", false);
12121  break;
12122  }
12123 
12124  case patch_operations::move:
12125  {
12126  const std::string from_path = get_value("move", "from", true);
12127  json_pointer from_ptr(from_path);
12128 
12129  // the "from" location must exist - use at()
12130  basic_json v = result.at(from_ptr);
12131 
12132  // The move operation is functionally identical to a
12133  // "remove" operation on the "from" location, followed
12134  // immediately by an "add" operation at the target
12135  // location with the value that was just removed.
12136  operation_remove(from_ptr);
12137  operation_add(ptr, v);
12138  break;
12139  }
12140 
12141  case patch_operations::copy:
12142  {
12143  const std::string from_path = get_value("copy", "from", true);;
12144  const json_pointer from_ptr(from_path);
12145 
12146  // the "from" location must exist - use at()
12147  result[ptr] = result.at(from_ptr);
12148  break;
12149  }
12150 
12151  case patch_operations::test:
12152  {
12153  bool success = false;
12154  JSON_TRY
12155  {
12156  // check if "value" matches the one at "path"
12157  // the "path" location must exist - use at()
12158  success = (result.at(ptr) == get_value("test", "value", false));
12159  }
12160  JSON_CATCH (std::out_of_range&)
12161  {
12162  // ignore out of range errors: success remains false
12163  }
12164 
12165  // throw an exception if test fails
12166  if (not success)
12167  {
12168  JSON_THROW(std::domain_error("unsuccessful: " + val.dump()));
12169  }
12170 
12171  break;
12172  }
12173 
12174  case patch_operations::invalid:
12175  {
12176  // op must be "add", "remove", "replace", "move", "copy", or
12177  // "test"
12178  JSON_THROW(std::invalid_argument("operation value '" + op + "' is invalid"));
12179  }
12180  }
12181  }
12182 
12183  return result;
12184  }
12185 
12218  static basic_json diff(const basic_json& source,
12219  const basic_json& target,
12220  const std::string& path = "")
12221  {
12222  // the patch
12223  basic_json result(value_t::array);
12224 
12225  // if the values are the same, return empty patch
12226  if (source == target)
12227  {
12228  return result;
12229  }
12230 
12231  if (source.type() != target.type())
12232  {
12233  // different types: replace value
12234  result.push_back(
12235  {
12236  {"op", "replace"},
12237  {"path", path},
12238  {"value", target}
12239  });
12240  }
12241  else
12242  {
12243  switch (source.type())
12244  {
12245  case value_t::array:
12246  {
12247  // first pass: traverse common elements
12248  size_t i = 0;
12249  while (i < source.size() and i < target.size())
12250  {
12251  // recursive call to compare array values at index i
12252  auto temp_diff = diff(source[i], target[i], path + "/" + std::to_string(i));
12253  result.insert(result.end(), temp_diff.begin(), temp_diff.end());
12254  ++i;
12255  }
12256 
12257  // i now reached the end of at least one array
12258  // in a second pass, traverse the remaining elements
12259 
12260  // remove my remaining elements
12261  const auto end_index = static_cast<difference_type>(result.size());
12262  while (i < source.size())
12263  {
12264  // add operations in reverse order to avoid invalid
12265  // indices
12266  result.insert(result.begin() + end_index, object(
12267  {
12268  {"op", "remove"},
12269  {"path", path + "/" + std::to_string(i)}
12270  }));
12271  ++i;
12272  }
12273 
12274  // add other remaining elements
12275  while (i < target.size())
12276  {
12277  result.push_back(
12278  {
12279  {"op", "add"},
12280  {"path", path + "/" + std::to_string(i)},
12281  {"value", target[i]}
12282  });
12283  ++i;
12284  }
12285 
12286  break;
12287  }
12288 
12289  case value_t::object:
12290  {
12291  // first pass: traverse this object's elements
12292  for (auto it = source.begin(); it != source.end(); ++it)
12293  {
12294  // escape the key name to be used in a JSON patch
12295  const auto key = json_pointer::escape(it.key());
12296 
12297  if (target.find(it.key()) != target.end())
12298  {
12299  // recursive call to compare object values at key it
12300  auto temp_diff = diff(it.value(), target[it.key()], path + "/" + key);
12301  result.insert(result.end(), temp_diff.begin(), temp_diff.end());
12302  }
12303  else
12304  {
12305  // found a key that is not in o -> remove it
12306  result.push_back(object(
12307  {
12308  {"op", "remove"},
12309  {"path", path + "/" + key}
12310  }));
12311  }
12312  }
12313 
12314  // second pass: traverse other object's elements
12315  for (auto it = target.begin(); it != target.end(); ++it)
12316  {
12317  if (source.find(it.key()) == source.end())
12318  {
12319  // found a key that is not in this -> add it
12320  const auto key = json_pointer::escape(it.key());
12321  result.push_back(
12322  {
12323  {"op", "add"},
12324  {"path", path + "/" + key},
12325  {"value", it.value()}
12326  });
12327  }
12328  }
12329 
12330  break;
12331  }
12332 
12333  default:
12334  {
12335  // both primitive type: replace value
12336  result.push_back(
12337  {
12338  {"op", "replace"},
12339  {"path", path},
12340  {"value", target}
12341  });
12342  break;
12343  }
12344  }
12345  }
12346 
12347  return result;
12348  }
12349 
12351 };
12352 
12354 // presets //
12356 
12365 using json = basic_json<>;
12366 } // namespace nlohmann
12367 
12368 
12370 // nonmember support //
12372 
12373 // specialization of std::swap, and std::hash
12374 namespace std
12375 {
12381 template<>
12382 inline void swap(nlohmann::json& j1,
12383  nlohmann::json& j2) noexcept(
12384  is_nothrow_move_constructible<nlohmann::json>::value and
12385  is_nothrow_move_assignable<nlohmann::json>::value
12386  )
12387 {
12388  j1.swap(j2);
12389 }
12390 
12392 template<>
12393 struct hash<nlohmann::json>
12394 {
12400  std::size_t operator()(const nlohmann::json& j) const
12401  {
12402  // a naive hashing via the string representation
12403  const auto& h = hash<nlohmann::json::string_t>();
12404  return h(j.dump());
12405  }
12406 };
12407 } // namespace std
12408 
12422 inline nlohmann::json operator "" _json(const char* s, std::size_t n)
12423 {
12424  return nlohmann::json::parse(s, s + n);
12425 }
12426 
12440 inline nlohmann::json::json_pointer operator "" _json_pointer(const char* s, std::size_t n)
12441 {
12442  return nlohmann::json::json_pointer(std::string(s, n));
12443 }
12444 
12445 // restore GCC/clang diagnostic settings
12446 #if defined(__clang__) || defined(__GNUC__) || defined(__GNUG__)
12447  #pragma GCC diagnostic pop
12448 #endif
12449 
12450 // clean up
12451 #undef JSON_CATCH
12452 #undef JSON_DEPRECATED
12453 #undef JSON_THROW
12454 #undef JSON_TRY
12455 
12456 #endif
typename std::allocator_traits< allocator_type >::pointer pointer
the type of an element pointer
Definition: json.hpp:1083
friend bool operator<=(const_reference lhs, const_reference rhs) noexcept
comparison: less than or equal
Definition: json.hpp:6141
const_reference front() const
access the first element
Definition: json.hpp:4200
JSONSerializer< T, SFINAE > json_serializer
Definition: json.hpp:1055
NumberFloatType number_float_t
a type for a number (floating-point)
Definition: json.hpp:1618
BooleanType boolean_t
a type for a boolean
Definition: json.hpp:1407
typename basic_json::value_type value_type
the type of the values when the iterator is dereferenced
Definition: json.hpp:8849
friend std::istream & operator>>(std::istream &i, basic_json &j)
deserialize from stream
Definition: json.hpp:6524
static iteration_proxy< const_iterator > iterator_wrapper(const_reference cont)
wrapper to access iterator member functions in range-based for
Definition: json.hpp:4943
const_reference operator[](size_type idx) const
access specified array element
Definition: json.hpp:3760
std::reverse_iterator< Base > base_iterator
shortcut to the reverse iterator adaptor
Definition: json.hpp:9456
const_reverse_iterator crend() const noexcept
returns a const reverse iterator to one before the first
Definition: json.hpp:4914
iterator begin() noexcept
returns an iterator to the first element
Definition: json.hpp:4670
static basic_json parse(const CharT s, const parser_callback_t cb=nullptr)
deserialize from string literal
Definition: json.hpp:6322
difference_type operator-(const iter_impl &other) const
return difference
Definition: json.hpp:9342
iterator end() noexcept
returns an iterator to one past the last element
Definition: json.hpp:4741
constexpr value_t type() const noexcept
return the type of the JSON value (explicit)
Definition: json.hpp:2681
reference operator+=(const basic_json &val)
add an object to an array
Definition: json.hpp:5318
IteratorType erase(IteratorType first, IteratorType last)
remove elements given an iterator range
Definition: json.hpp:4408
friend bool operator!=(const ScalarType lhs, const_reference rhs) noexcept
comparison: not equal
Definition: json.hpp:6017
basic_json(std::nullptr_t=nullptr) noexcept
create a null object
Definition: json.hpp:1940
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:2205
string_t value(const json_pointer &ptr, const char *default_value) const
overload for a default value of type const char*
Definition: json.hpp:4162
friend bool operator!=(const_reference lhs, const_reference rhs) noexcept
comparison: not equal
Definition: json.hpp:5995
bool operator>=(const iter_impl &other) const
comparison: greater than or equal
Definition: json.hpp:9271
iter_impl(const iter_impl &other) noexcept
copy constructor
Definition: json.hpp:8925
basic_json(InputIT first, InputIT last)
construct a JSON container given an iterator range
Definition: json.hpp:2276
ReferenceType get_ref()
get a reference value (implicit)
Definition: json.hpp:3438
void push_back(std::initializer_list< basic_json > init)
add an object to an object
Definition: json.hpp:5399
a class to store JSON values
Definition: json.hpp:1039
iterator insert(const_iterator pos, std::initializer_list< basic_json > ilist)
inserts elements
Definition: json.hpp:5701
void erase(const size_type idx)
remove element from a JSON array given an index
Definition: json.hpp:4531
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:8855
const_iterator end() const noexcept
returns a const iterator to one past the last element
Definition: json.hpp:4751
const_iterator find(typename object_t::key_type key) const
find an element in a JSON object
Definition: json.hpp:4597
static allocator_type get_allocator()
returns the allocator associated with the container
Definition: json.hpp:1102
friend bool operator==(const ScalarType lhs, const_reference rhs) noexcept
comparison: equal
Definition: json.hpp:5974
reference operator[](size_type idx)
access specified array element
Definition: json.hpp:3714
default JSONSerializer template argument
Definition: json.hpp:911
json_reverse_iterator operator-(difference_type i) const
subtract from iterator
Definition: json.hpp:9512
iterator find(typename object_t::key_type key)
find an element in a JSON object
Definition: json.hpp:4581
constexpr bool is_structured() const noexcept
return whether type is structured
Definition: json.hpp:2738
ObjectType< StringType, basic_json, std::less< StringType >, AllocatorType< std::pair< const StringType, basic_json > >> object_t
a type for an object
Definition: json.hpp:1282
static basic_json parse(T(&array)[N], const parser_callback_t cb=nullptr)
deserialize from an array
Definition: json.hpp:6284
bool operator!=(const iter_impl &other) const
comparison: not equal
Definition: json.hpp:9211
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:8859
~basic_json()
destructor
Definition: json.hpp:2575
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:2542
void swap(string_t &other)
exchanges the values
Definition: json.hpp:5836
void swap(object_t &other)
exchanges the values
Definition: json.hpp:5803
static basic_json parse(std::istream &i, const parser_callback_t cb=nullptr)
deserialize from stream
Definition: json.hpp:6352
STL namespace.
reference operator+=(std::initializer_list< basic_json > init)
add an object to an object
Definition: json.hpp:5416
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:4630
object_t::key_type key() const
return the key of an object iterator
Definition: json.hpp:9532
json_reverse_iterator & operator--()
pre-decrement (–it)
Definition: json.hpp:9490
std::bidirectional_iterator_tag iterator_category
the category of the iterator
Definition: json.hpp:8861
json_reverse_iterator operator--(int)
post-decrement (it–)
Definition: json.hpp:9484
iter_impl operator-(difference_type i)
subtract from iterator
Definition: json.hpp:9331
size_type max_size() const noexcept
returns the maximum possible number of elements
Definition: json.hpp:5129
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:2082
reference at(size_type idx)
access specified array element with bounds checking
Definition: json.hpp:3531
JSON_DEPRECATED basic_json(std::istream &i, const parser_callback_t cb=nullptr)
construct a JSON value given an input stream
Definition: json.hpp:2396
friend class basic_json
allow basic_json to access private members
Definition: json.hpp:8840
reference operator[](difference_type n) const
access to successor
Definition: json.hpp:9369
constexpr bool is_number() const noexcept
return whether value is a number
Definition: json.hpp:2812
const value_type & const_reference
the type of an element const reference
Definition: json.hpp:1072
strtonum(const char *start, const char *end)
Definition: json.hpp:10556
bool operator==(const iter_impl &other) const
comparison: equal
Definition: json.hpp:9178
constexpr bool is_primitive() const noexcept
return whether type is primitive
Definition: json.hpp:2711
reference front()
access the first element
Definition: json.hpp:4192
reference operator*() const
return a reference to the value pointed to by the iterator
Definition: json.hpp:9019
const_reverse_iterator crbegin() const noexcept
returns a const reverse iterator to the last element
Definition: json.hpp:4885
const_reference operator[](T *(&key)[n]) const
read-only access specified object element
Definition: json.hpp:3922
std::size_t size_type
a type to represent container sizes
Definition: json.hpp:1077
const_iterator begin() const noexcept
returns a const iterator to the first element
Definition: json.hpp:4680
ReferenceType get_ref() const
get a reference value (implicit)
Definition: json.hpp:3451
iter_impl & operator++()
pre-increment (++it)
Definition: json.hpp:9103
reference operator[](const typename object_t::key_type &key)
access specified object element
Definition: json.hpp:3798
static iteration_proxy< iterator > iterator_wrapper(reference cont)
wrapper to access iterator member functions in range-based for
Definition: json.hpp:4935
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:923
static basic_json from_msgpack(const std::vector< uint8_t > &v, const size_t start_index=0)
create a JSON value from a byte vector in MessagePack format
Definition: json.hpp:7974
iter_impl operator+(difference_type i)
add to iterator
Definition: json.hpp:9320
NumberIntegerType number_integer_t
a type for a number (integer)
Definition: json.hpp:1479
constexpr bool is_array() const noexcept
return whether value is an array
Definition: json.hpp:2941
const_reference at(size_type idx) const
access specified array element with bounds checking
Definition: json.hpp:3574
NumberUnsignedType number_unsigned_t
a type for a number (unsigned)
Definition: json.hpp:1550
friend bool operator==(const_reference lhs, const ScalarType rhs) noexcept
comparison: equal
Definition: json.hpp:5963
friend bool operator>=(const_reference lhs, const_reference rhs) noexcept
comparison: greater than or equal
Definition: json.hpp:6185
friend bool operator<(const_reference lhs, const_reference rhs) noexcept
comparison: less than
Definition: json.hpp:6046
size_type size() const noexcept
returns the number of elements
Definition: json.hpp:5063
json_reverse_iterator(const typename base_iterator::iterator_type &it) noexcept
create reverse iterator from iterator
Definition: json.hpp:9461
parse string into a built-in arithmetic type as if the current locale is POSIX.
Definition: json.hpp:10553
const_iterator cbegin() const noexcept
returns a const iterator to the first element
Definition: json.hpp:4710
reference operator[](T *key)
access specified object element
Definition: json.hpp:3955
static basic_json meta()
returns version information on the library
Definition: json.hpp:1130
static basic_json parse(std::istream &&i, const parser_callback_t cb=nullptr)
deserialize from stream
Definition: json.hpp:6361
ValueType value(const json_pointer &ptr, ValueType default_value) const
access specified object element via JSON Pointer with default value
Definition: json.hpp:4139
basic_json(size_type cnt, const basic_json &val)
construct an array with count copies of given value
Definition: json.hpp:2229
json_reverse_iterator operator++(int)
post-increment (it++)
Definition: json.hpp:9471
constexpr const auto & from_json
Definition: json.hpp:899
reference value() const
return the value of an iterator
Definition: json.hpp:9539
constexpr bool is_boolean() const noexcept
return whether value is a boolean
Definition: json.hpp:2782
friend std::ostream & operator>>(const basic_json &j, std::ostream &o)
serialize to stream
Definition: json.hpp:6241
reference at(const typename object_t::key_type &key)
access specified object element with bounds checking
Definition: json.hpp:3621
PointerType get_ptr() noexcept
get a pointer value (implicit)
Definition: json.hpp:3361
friend bool operator!=(const_reference lhs, const ScalarType rhs) noexcept
comparison: not equal
Definition: json.hpp:6006
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:2841
basic_json(const value_t value_type)
create an empty value with a given type
Definition: json.hpp:1916
json_reverse_iterator(const base_iterator &it) noexcept
create reverse iterator from base class
Definition: json.hpp:9466
reference operator+=(const typename object_t::value_type &val)
add an object to an object
Definition: json.hpp:5368
constexpr bool is_object() const noexcept
return whether value is an object
Definition: json.hpp:2919
reference operator+=(basic_json &&val)
add an object to an array
Definition: json.hpp:5284
difference_type operator-(const json_reverse_iterator &other) const
return difference
Definition: json.hpp:9520
constexpr bool is_number_float() const noexcept
return whether value is a floating-point number
Definition: json.hpp:2897
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:6412
json_reverse_iterator & operator+=(difference_type i)
add to iterator
Definition: json.hpp:9497
iter_impl operator++(int)
post-increment (it++)
Definition: json.hpp:9092
bool operator<=(const iter_impl &other) const
comparison: less than or equal
Definition: json.hpp:9253
iter_impl operator--(int)
post-decrement (it–)
Definition: json.hpp:9135
iter_impl & operator--()
pre-decrement (–it)
Definition: json.hpp:9146
reverse_iterator rbegin() noexcept
returns an iterator to the reverse-beginning
Definition: json.hpp:4811
reference back()
access the last element
Definition: json.hpp:4235
iterator insert(const_iterator pos, size_type cnt, const basic_json &val)
inserts elements
Definition: json.hpp:5593
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:939
iter_impl(pointer object) noexcept
constructor for a given JSON instance
Definition: json.hpp:8872
iterator insert(const_iterator pos, const_iterator first, const_iterator last)
inserts elements
Definition: json.hpp:5643
std::function< bool(int depth, parse_event_t event, basic_json &parsed)> parser_callback_t
per-element parser callback type
Definition: json.hpp:1877
void emplace_back(Args &&... args)
add an object to an array
Definition: json.hpp:5444
constexpr bool is_string() const noexcept
return whether value is a string
Definition: json.hpp:2963
json_reverse_iterator operator+(difference_type i) const
add to iterator
Definition: json.hpp:9504
const_iterator cend() const noexcept
returns a const iterator to one past the last element
Definition: json.hpp:4781
friend bool operator==(const_reference lhs, const_reference rhs) noexcept
comparison: equal
Definition: json.hpp:5882
void push_back(const basic_json &val)
add an object to an array
Definition: json.hpp:5294
void push_back(const typename object_t::value_type &val)
add an object to an object
Definition: json.hpp:5344
void swap(array_t &other)
exchanges the values
Definition: json.hpp:5770
size_type erase(const typename object_t::key_type &key)
remove element from a JSON object given a key
Definition: json.hpp:4496
constexpr const auto & to_json
Definition: json.hpp:898
bool empty() const noexcept
checks whether the container is empty
Definition: json.hpp:4995
const_reference back() const
access the last element
Definition: json.hpp:4245
const_reverse_iterator rbegin() const noexcept
returns a const reverse iterator to the last element
Definition: json.hpp:4819
ArrayType< basic_json, AllocatorType< basic_json > > array_t
a type for an array
Definition: json.hpp:1328
bool operator<(const iter_impl &other) const
comparison: smaller
Definition: json.hpp:9220
static basic_json from_cbor(const std::vector< uint8_t > &v, const size_t start_index=0)
create a JSON value from a byte vector in CBOR format
Definition: json.hpp:8037
pointer operator->() const
dereference the iterator
Definition: json.hpp:9058
string_t dump(const int indent=-1) const
serialization
Definition: json.hpp:2647
ValueType value(const typename object_t::key_type &key, ValueType default_value) const
access specified object element with default value
Definition: json.hpp:4067
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:8934
std::ptrdiff_t difference_type
a type to represent differences between iterators
Definition: json.hpp:1075
static basic_json parse(const ContiguousContainer &c, const parser_callback_t cb=nullptr)
deserialize from a container with contiguous storage
Definition: json.hpp:6484
AllocatorType< basic_json > allocator_type
the allocator type
Definition: json.hpp:1080
json_pointer(const std::string &s="")
create JSON pointer
Definition: json.hpp:11127
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:4091
reference value() const
return the value of an iterator
Definition: json.hpp:9422
iterator insert(const_iterator pos, basic_json &&val)
inserts element
Definition: json.hpp:5564
const_reference at(const typename object_t::key_type &key) const
access specified object element with bounds checking
Definition: json.hpp:3668
const_reverse_iterator rend() const noexcept
returns a const reverse iterator to one before the first
Definition: json.hpp:4856
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:2006
const_reference operator[](const typename object_t::key_type &key) const
read-only access specified object element
Definition: json.hpp:3847
constexpr bool is_null() const noexcept
return whether value is null
Definition: json.hpp:2760
static std::vector< uint8_t > to_msgpack(const basic_json &j)
create a MessagePack serialization of a given JSON value
Definition: json.hpp:7941
typename std::allocator_traits< allocator_type >::const_pointer const_pointer
the type of an element const pointer
Definition: json.hpp:1085
StringType string_t
a type for a string
Definition: json.hpp:1381
reference operator[](difference_type n) const
access to successor
Definition: json.hpp:9526
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:2165
basic_json(basic_json &&other) noexcept
move constructor
Definition: json.hpp:2505
friend bool operator>(const_reference lhs, const_reference rhs) noexcept
comparison: greater than
Definition: json.hpp:6163
constexpr bool is_number_unsigned() const noexcept
return whether value is an unsigned integer number
Definition: json.hpp:2869
typename basic_json::difference_type difference_type
a type to represent differences between iterators
Definition: json.hpp:8851
constexpr const PointerType get_ptr() const noexcept
get a pointer value (implicit)
Definition: json.hpp:3389
iter_impl & operator-=(difference_type i)
subtract from iterator
Definition: json.hpp:9311
typename Base::reference reference
the reference type for the pointed-to element
Definition: json.hpp:9458
a template for a reverse iterator class
Definition: json.hpp:1052
void push_back(basic_json &&val)
add an object to an array
Definition: json.hpp:5258
iterator insert(const_iterator pos, const basic_json &val)
inserts element
Definition: json.hpp:5540
void clear() noexcept
clears the contents
Definition: json.hpp:5185
static std::vector< uint8_t > to_cbor(const basic_json &j)
create a MessagePack serialization of a given JSON value
Definition: json.hpp:8004
basic_json value_type
the type of elements in a basic_json container
Definition: json.hpp:1067
iter_impl & operator+=(difference_type i)
add to iterator
Definition: json.hpp:9280
object_t::key_type key() const
return the key of an object iterator
Definition: json.hpp:9406
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:5738
friend std::istream & operator<<(basic_json &j, std::istream &i)
deserialize from stream
Definition: json.hpp:6514
const_reference operator[](T *key) const
read-only access specified object element
Definition: json.hpp:4005
std::pair< iterator, bool > emplace(Args &&... args)
add an object to an object if key does not exist
Definition: json.hpp:5492
basic_json(const basic_json &other)
copy constructor
Definition: json.hpp:2428
bool operator>(const iter_impl &other) const
comparison: greater than
Definition: json.hpp:9262
friend std::ostream & operator<<(std::ostream &o, const basic_json &j)
serialize to stream
Definition: json.hpp:6222
IteratorType erase(IteratorType pos)
remove element given an iterator
Definition: json.hpp:4301
a template for a random access iterator for the basic_json class
Definition: json.hpp:1051
json_reverse_iterator & operator++()
pre-increment (++it)
Definition: json.hpp:9477
constexpr bool is_discarded() const noexcept
return whether value is discarded
Definition: json.hpp:2990
parse_event_t
JSON callback events.
Definition: json.hpp:1807
reference operator[](T *(&key)[n])
access specified object element
Definition: json.hpp:3887
reverse_iterator rend() noexcept
returns an iterator to the reverse-end
Definition: json.hpp:4848