WPILibC++  unspecified
json.h
1 /*----------------------------------------------------------------------------*/
2 /* Modifications Copyright (c) FIRST 2017. All Rights Reserved. */
3 /* Open Source Software - may be modified and shared by FRC teams. The code */
4 /* must be accompanied by the FIRST BSD license file in the root directory of */
5 /* the project. */
6 /*----------------------------------------------------------------------------*/
7 /*
8  __ _____ _____ _____
9  __| | __| | | | JSON for Modern C++
10 | | |__ | | | | | | version 2.1.1
11 |_____|_____|_____|_|___| https://github.com/nlohmann/json
12 
13 Licensed under the MIT License <http://opensource.org/licenses/MIT>.
14 Copyright (c) 2013-2017 Niels Lohmann <http://nlohmann.me>.
15 
16 Permission is hereby granted, free of charge, to any person obtaining a copy
17 of this software and associated documentation files (the "Software"), to deal
18 in the Software without restriction, including without limitation the rights
19 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
20 copies of the Software, and to permit persons to whom the Software is
21 furnished to do so, subject to the following conditions:
22 
23 The above copyright notice and this permission notice shall be included in all
24 copies or substantial portions of the Software.
25 
26 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
27 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
28 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
29 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
30 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
31 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
32 SOFTWARE.
33 */
34 
35 #ifndef WPI_SUPPORT_JSON_H_
36 #define WPI_SUPPORT_JSON_H_
37 
38 #include <cassert> // assert
39 #include <cmath> // isfinite, labs, ldexp, signbit
40 #include <cstddef> // nullptr_t, ptrdiff_t, size_t
41 #include <cstdint> // int64_t, uint64_t
42 #include <cstdlib> // abort, strtod, strtof, strtold, strtoul, strtoll, strtoull
43 #include <cstring> // memcpy, strlen
44 #include <functional> // function, hash, less
45 #include <initializer_list> // initializer_list
46 #include <iterator> // advance, begin, back_inserter, bidirectional_iterator_tag, distance, end, inserter, iterator, iterator_traits, next, random_access_iterator_tag
47 #include <limits> // numeric_limits
48 #include <memory> // addressof, allocator, allocator_traits, unique_ptr
49 #include <string> // getline, stoi, string, to_string
50 #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
51 #include <utility> // declval, forward, make_pair, move, pair, swap
52 #include <vector> // vector
53 
54 #include "llvm/ArrayRef.h"
55 #include "llvm/raw_ostream.h"
56 #include "llvm/StringMap.h"
57 #include "llvm/StringRef.h"
58 
59 // exclude unsupported compilers
60 #if defined(__clang__)
61  #if (__clang_major__ * 10000 + __clang_minor__ * 100 + __clang_patchlevel__) < 30400
62  #error "unsupported Clang version - see https://github.com/nlohmann/json#supported-compilers"
63  #endif
64 #elif defined(__GNUC__)
65  #if (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) < 40800
66  #error "unsupported GCC version - see https://github.com/nlohmann/json#supported-compilers"
67  #endif
68 #endif
69 
70 // disable float-equal warnings on GCC/clang
71 #if defined(__clang__) || defined(__GNUC__) || defined(__GNUG__)
72  #pragma GCC diagnostic push
73  #pragma GCC diagnostic ignored "-Wfloat-equal"
74  #pragma GCC diagnostic ignored "-Wtype-limits"
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  #pragma GCC diagnostic ignored "-Wtautological-constant-out-of-range-compare"
82 #endif
83 
84 // allow to disable exceptions
85 #if (defined(__cpp_exceptions) || defined(__EXCEPTIONS) || defined(_CPPUNWIND)) && !defined(JSON_NOEXCEPTION)
86  #define JSON_THROW(exception) throw exception
87  #define JSON_TRY try
88  #define JSON_CATCH(exception) catch(exception)
89 #else
90  #define JSON_THROW(exception) std::abort()
91  #define JSON_TRY if(true)
92  #define JSON_CATCH(exception) if(false)
93 #endif
94 
95 // manual branch prediction
96 #if defined(__clang__) || defined(__GNUC__) || defined(__GNUG__)
97  #define JSON_LIKELY(x) __builtin_expect(!!(x), 1)
98  #define JSON_UNLIKELY(x) __builtin_expect(!!(x), 0)
99 #else
100  #define JSON_LIKELY(x) x
101  #define JSON_UNLIKELY(x) x
102 #endif
103 
104 namespace wpi
105 {
106 
107 class raw_istream;
108 
117 namespace detail
118 {
120 // exceptions //
122 
135 class exception : public std::exception
136 {
137  public:
139  virtual const char* what() const noexcept override
140  {
141  return m.what();
142  }
143 
145  const int id;
146 
147  protected:
148  exception(int id_, const char* what_arg)
149  : id(id_), m(what_arg)
150  {}
151 
152  static std::string name(const std::string& ename, int id);
153 
154  private:
156  std::runtime_error m;
157 };
158 
194 class parse_error : public exception
195 {
196  public:
205  static parse_error create(int id, size_t byte_, const std::string& what_arg);
206 
217  const size_t byte;
218 
219  private:
220  parse_error(int id_, size_t byte_, const char* what_arg)
221  : exception(id_, what_arg), byte(byte_)
222  {}
223 };
224 
250 {
251  public:
252  static invalid_iterator create(int id, const std::string& what_arg);
253 
254  private:
255  invalid_iterator(int id_, const char* what_arg)
256  : exception(id_, what_arg)
257  {}
258 };
259 
284 class type_error : public exception
285 {
286  public:
287  static type_error create(int id, const std::string& what_arg);
288 
289  private:
290  type_error(int id_, const char* what_arg)
291  : exception(id_, what_arg)
292  {}
293 };
294 
311 class out_of_range : public exception
312 {
313  public:
314  static out_of_range create(int id, const std::string& what_arg);
315 
316  private:
317  out_of_range(int id_, const char* what_arg)
318  : exception(id_, what_arg)
319  {}
320 };
321 
334 class other_error : public exception
335 {
336  public:
337  static other_error create(int id, const std::string& what_arg);
338 
339  private:
340  other_error(int id_, const char* what_arg)
341  : exception(id_, what_arg)
342  {}
343 };
344 
345 
346 
348 // JSON type enumeration //
350 
375 enum class value_t : uint8_t
376 {
377  null,
378  object,
379  array,
380  string,
381  boolean,
384  number_float,
385  discarded
386 };
387 
397 inline bool operator<(const value_t lhs, const value_t rhs) noexcept
398 {
399  static constexpr uint8_t order[] = {
400  0, // null
401  3, // object
402  4, // array
403  5, // string
404  1, // boolean
405  2, // integer
406  2, // unsigned
407  2, // float
408  };
409 
410  // discarded values are not comparable
411  if (lhs == value_t::discarded || rhs == value_t::discarded)
412  {
413  return false;
414  }
415 
416  return order[static_cast<std::size_t>(lhs)] <
417  order[static_cast<std::size_t>(rhs)];
418 }
419 
420 
422 // helpers //
424 
425 // alias templates to reduce boilerplate
426 template<bool B, typename T = void>
427 using enable_if_t = typename std::enable_if<B, T>::type;
428 
429 template<typename T>
430 using uncvref_t = typename std::remove_cv<typename std::remove_reference<T>::type>::type;
431 
432 /*
433 Implementation of two C++17 constructs: conjunction, negation. This is needed
434 to avoid evaluating all the traits in a condition
435 
436 For example: !std::is_same<void, T>::value && has_value_type<T>::value
437 will not compile when T = void (on MSVC at least). Whereas
438 conjunction<negation<std::is_same<void, T>>, has_value_type<T>>::value will
439 stop evaluating if negation<...>::value == false
440 
441 Please note that those constructs must be used with caution, since symbols can
442 become very long quickly (which can slow down compilation and cause MSVC
443 internal compiler errors). Only use it when you have to (see example ahead).
444 */
445 template<class...> struct conjunction : std::true_type {};
446 template<class B1> struct conjunction<B1> : B1 {};
447 template<class B1, class... Bn>
448 struct conjunction<B1, Bn...> : std::conditional<bool(B1::value), conjunction<Bn...>, B1>::type {};
449 
450 template<class B> struct negation : std::integral_constant < bool, !B::value > {};
451 
452 // dispatch utility (taken from ranges-v3)
453 template<unsigned N> struct priority_tag : priority_tag < N - 1 > {};
454 template<> struct priority_tag<0> {};
455 
456 
458 // constructors //
460 
461 template<value_t> struct external_constructor;
462 
463 template<>
465 {
466  template<typename BasicJsonType>
467  static void construct(BasicJsonType& j, bool b) noexcept
468  {
469  j.m_type = value_t::boolean;
470  j.m_value = b;
471  j.assert_invariant();
472  }
473 };
474 
475 template<>
477 {
478  template<typename BasicJsonType>
479  static void construct(BasicJsonType& j, llvm::StringRef s)
480  {
481  j.m_type = value_t::string;
482  j.m_value = s;
483  j.assert_invariant();
484  }
485 };
486 
487 template<>
489 {
490  template<typename BasicJsonType>
491  static void construct(BasicJsonType& j, double val) noexcept
492  {
493  j.m_type = value_t::number_float;
494  j.m_value = val;
495  j.assert_invariant();
496  }
497 };
498 
499 template<>
501 {
502  template<typename BasicJsonType>
503  static void construct(BasicJsonType& j, std::uint64_t val) noexcept
504  {
505  j.m_type = value_t::number_unsigned;
506  j.m_value = val;
507  j.assert_invariant();
508  }
509 };
510 
511 template<>
513 {
514  template<typename BasicJsonType>
515  static void construct(BasicJsonType& j, std::int64_t val) noexcept
516  {
517  j.m_type = value_t::number_integer;
518  j.m_value = val;
519  j.assert_invariant();
520  }
521 };
522 
523 template<>
525 {
526  template<typename BasicJsonType>
527  static void construct(BasicJsonType& j, const typename BasicJsonType::array_t& arr)
528  {
529  j.m_type = value_t::array;
530  j.m_value = arr;
531  j.assert_invariant();
532  }
533 
534  template<typename BasicJsonType, typename T>
535  static void construct(BasicJsonType& j, llvm::ArrayRef<T> arr)
536  {
537  using std::begin;
538  using std::end;
539  j.m_type = value_t::array;
540  j.m_value.array = j.template create<typename BasicJsonType::array_t>(begin(arr), end(arr));
541  j.assert_invariant();
542  }
543 
544  template<typename BasicJsonType, typename CompatibleArrayType,
545  enable_if_t<!std::is_same<CompatibleArrayType,
546  typename BasicJsonType::array_t>::value,
547  int> = 0>
548  static void construct(BasicJsonType& j, const CompatibleArrayType& arr)
549  {
550  using std::begin;
551  using std::end;
552  j.m_type = value_t::array;
553  j.m_value.array = j.template create<typename BasicJsonType::array_t>(begin(arr), end(arr));
554  j.assert_invariant();
555  }
556 
557  template<typename BasicJsonType>
558  static void construct(BasicJsonType& j, const std::vector<bool>& arr)
559  {
560  j.m_type = value_t::array;
561  j.m_value = value_t::array;
562  j.m_value.array->reserve(arr.size());
563  for (bool x : arr)
564  {
565  j.m_value.array->push_back(x);
566  }
567  j.assert_invariant();
568  }
569 };
570 
571 template<>
573 {
574  template<typename BasicJsonType>
575  static void construct(BasicJsonType& j, const typename BasicJsonType::object_t& obj)
576  {
577  j.m_type = value_t::object;
578  j.m_value = obj;
579  j.assert_invariant();
580  }
581 
582  template<typename BasicJsonType, typename CompatibleObjectType,
583  enable_if_t<!std::is_same<CompatibleObjectType,
584  typename BasicJsonType::object_t>::value,
585  int> = 0>
586  static void construct(BasicJsonType& j, const CompatibleObjectType& obj)
587  {
588  j.m_type = value_t::object;
589  j.m_value = value_t::object;
590  for (const auto& x : obj)
591  {
592  j.m_value.object->emplace_second(x.first, x.second);
593  }
594  j.assert_invariant();
595  }
596 };
597 
598 
600 // has_/is_ functions //
602 
613 #define WPI_JSON_HAS_HELPER(type) \
614  template<typename T> struct has_##type { \
615  private: \
616  template<typename U, typename = typename U::type> \
617  static int detect(U &&); \
618  static void detect(...); \
619  public: \
620  static constexpr bool value = \
621  std::is_integral<decltype(detect(std::declval<T>()))>::value; \
622  }
623 
624 WPI_JSON_HAS_HELPER(mapped_type);
625 WPI_JSON_HAS_HELPER(key_type);
626 WPI_JSON_HAS_HELPER(value_type);
627 WPI_JSON_HAS_HELPER(iterator);
628 
629 #undef WPI_JSON_HAS_HELPER
630 
631 
632 template<bool B, class RealType, class CompatibleObjectType>
633 struct is_compatible_object_type_impl : std::false_type {};
634 
635 template<class RealType, class CompatibleObjectType>
636 struct is_compatible_object_type_impl<true, RealType, CompatibleObjectType>
637 {
638  static constexpr auto value =
639  std::is_constructible<llvm::StringRef,
640  typename CompatibleObjectType::key_type>::value &&
641  std::is_constructible<typename RealType::mapped_type,
642  typename CompatibleObjectType::mapped_type>::value;
643 };
644 
645 template<typename BasicJsonType, class CompatibleObjectType>
647 {
648  static auto constexpr value = is_compatible_object_type_impl <
650  has_mapped_type<CompatibleObjectType>,
651  has_key_type<CompatibleObjectType>>::value,
652  typename BasicJsonType::object_t, CompatibleObjectType >::value;
653 };
654 
655 template<typename BasicJsonType, typename T>
657 {
658  static auto constexpr value = std::is_same<T, typename BasicJsonType::iterator>::value ||
659  std::is_same<T, typename BasicJsonType::const_iterator>::value ||
660  std::is_same<T, typename BasicJsonType::json_pointer>::value;
661 };
662 
663 template<typename BasicJsonType, class CompatibleArrayType>
665 {
666  static auto constexpr value =
671  has_value_type<CompatibleArrayType>,
672  has_iterator<CompatibleArrayType>>::value;
673 };
674 
675 template<bool, typename, typename>
676 struct is_compatible_integer_type_impl : std::false_type {};
677 
678 template<typename RealIntegerType, typename CompatibleNumberIntegerType>
679 struct is_compatible_integer_type_impl<true, RealIntegerType, CompatibleNumberIntegerType>
680 {
681  // is there an assert somewhere on overflows?
682  using RealLimits = std::numeric_limits<RealIntegerType>;
683  using CompatibleLimits = std::numeric_limits<CompatibleNumberIntegerType>;
684 
685  static constexpr auto value =
686  std::is_constructible<RealIntegerType,
687  CompatibleNumberIntegerType>::value &&
688  CompatibleLimits::is_integer &&
689  RealLimits::is_signed == CompatibleLimits::is_signed;
690 };
691 
692 template<typename RealIntegerType, typename CompatibleNumberIntegerType>
694 {
695  static constexpr auto value =
697  std::is_integral<CompatibleNumberIntegerType>::value &&
698  !std::is_same<bool, CompatibleNumberIntegerType>::value,
699  RealIntegerType, CompatibleNumberIntegerType > ::value;
700 };
701 
703 // to_json //
705 
706 template<typename BasicJsonType, typename T, enable_if_t<
707  std::is_same<T, bool>::value, int> = 0>
708 inline
709 void to_json(BasicJsonType& j, T b) noexcept
710 {
712 }
713 
714 template<typename BasicJsonType, typename CompatibleString,
715  enable_if_t<std::is_constructible<llvm::StringRef,
716  CompatibleString>::value, int> = 0>
717 inline
718 void to_json(BasicJsonType& j, const CompatibleString& s)
719 {
721 }
722 
723 template<typename BasicJsonType, typename FloatType,
724  enable_if_t<std::is_floating_point<FloatType>::value, int> = 0>
725 inline
726 void to_json(BasicJsonType& j, FloatType val) noexcept
727 {
728  external_constructor<value_t::number_float>::construct(j, static_cast<double>(val));
729 }
730 
731 template <
732  typename BasicJsonType, typename CompatibleNumberUnsignedType,
733  enable_if_t<is_compatible_integer_type<std::uint64_t,
734  CompatibleNumberUnsignedType>::value, int> = 0 >
735 inline
736 void to_json(BasicJsonType& j, CompatibleNumberUnsignedType val) noexcept
737 {
738  external_constructor<value_t::number_unsigned>::construct(j, static_cast<std::uint64_t>(val));
739 }
740 
741 template <
742  typename BasicJsonType, typename CompatibleNumberIntegerType,
743  enable_if_t<is_compatible_integer_type<std::int64_t,
744  CompatibleNumberIntegerType>::value, int> = 0 >
745 inline
746 void to_json(BasicJsonType& j, CompatibleNumberIntegerType val) noexcept
747 {
748  external_constructor<value_t::number_integer>::construct(j, static_cast<std::int64_t>(val));
749 }
750 
751 template<typename BasicJsonType, typename EnumType,
752  enable_if_t<std::is_enum<EnumType>::value, int> = 0>
753 inline
754 void to_json(BasicJsonType& j, EnumType e) noexcept
755 {
756  using underlying_type = typename std::underlying_type<EnumType>::type;
757  external_constructor<value_t::number_integer>::construct(j, static_cast<underlying_type>(e));
758 }
759 
760 template<typename BasicJsonType>
761 inline
762 void to_json(BasicJsonType& j, const std::vector<bool>& e)
763 {
765 }
766 
767 template<typename BasicJsonType, typename T>
768 inline
769 void to_json(BasicJsonType& j, llvm::ArrayRef<T> arr)
770 {
772 }
773 
774 template <
775  typename BasicJsonType, typename CompatibleArrayType,
776  enable_if_t <
778  std::is_same<typename BasicJsonType::array_t, CompatibleArrayType>::value,
779  int > = 0 >
780 inline
781 void to_json(BasicJsonType& j, const CompatibleArrayType& arr)
782 {
784 }
785 
786 template <
787  typename BasicJsonType, typename CompatibleObjectType,
788  enable_if_t<is_compatible_object_type<BasicJsonType, CompatibleObjectType>::value,
789  int> = 0 >
790 inline
791 void to_json(BasicJsonType& j, const CompatibleObjectType& arr)
792 {
794 }
795 
796 template <typename BasicJsonType, typename T, std::size_t N,
797  enable_if_t<!std::is_constructible<
798  llvm::StringRef, T (&)[N]>::value,
799  int> = 0>
800 inline
801 void to_json(BasicJsonType& j, T (&arr)[N])
802 {
804 }
805 
806 template <typename BasicJsonType, typename CompatibleString, typename T,
807  enable_if_t<std::is_constructible<llvm::StringRef,
808  CompatibleString>::value, int> = 0>
809 inline
810 void to_json(BasicJsonType& j, std::pair<CompatibleString, T> const& p)
811 {
812  j[p.first] = p.second;
813 }
814 
816 // from_json //
818 
819 // overloads for json template parameters
820 template<typename BasicJsonType, typename ArithmeticType,
821  enable_if_t<std::is_arithmetic<ArithmeticType>::value &&
822  !std::is_same<ArithmeticType, bool>::value,
823  int> = 0>
824 void get_arithmetic_value(const BasicJsonType& j, ArithmeticType& val)
825 {
826  switch (static_cast<value_t>(j))
827  {
829  {
830  val = static_cast<ArithmeticType>(
831  *j.template get_ptr<const std::uint64_t*>());
832  break;
833  }
835  {
836  val = static_cast<ArithmeticType>(
837  *j.template get_ptr<const std::int64_t*>());
838  break;
839  }
841  {
842  val = static_cast<ArithmeticType>(
843  *j.template get_ptr<const double*>());
844  break;
845  }
846  default:
847  {
848  JSON_THROW(type_error::create(302, "type must be number, but is " + j.type_name()));
849  }
850  }
851 }
852 
853 template<typename BasicJsonType>
854 inline
855 void from_json(const BasicJsonType& j, bool& b)
856 {
857  if (!j.is_boolean())
858  {
859  JSON_THROW(type_error::create(302, "type must be boolean, but is " + j.type_name()));
860  }
861  b = *j.template get_ptr<const bool*>();
862 }
863 
864 template<typename BasicJsonType>
865 inline
866 void from_json(const BasicJsonType& j, std::string& s)
867 {
868  if (!j.is_string())
869  {
870  JSON_THROW(detail::type_error::create(302, "type must be string, but is " + j.type_name()));
871  }
872  s = *j.template get_ptr<const std::string*>();
873 }
874 
875 template<typename BasicJsonType>
876 inline
877 void from_json(const BasicJsonType& j, double& val)
878 {
879  get_arithmetic_value(j, val);
880 }
881 
882 template<typename BasicJsonType>
883 inline
884 void from_json(const BasicJsonType& j, std::uint64_t& val)
885 {
886  get_arithmetic_value(j, val);
887 }
888 
889 template<typename BasicJsonType>
890 inline
891 void from_json(const BasicJsonType& j, std::int64_t& val)
892 {
893  get_arithmetic_value(j, val);
894 }
895 
896 template<typename BasicJsonType, typename EnumType,
897  enable_if_t<std::is_enum<EnumType>::value, int> = 0>
898 inline
899 void from_json(const BasicJsonType& j, EnumType& e)
900 {
901  typename std::underlying_type<EnumType>::type val;
902  get_arithmetic_value(j, val);
903  e = static_cast<EnumType>(val);
904 }
905 
906 template<typename BasicJsonType>
907 inline
908 void from_json(const BasicJsonType& j, typename BasicJsonType::array_t& arr)
909 {
910  if (!j.is_array())
911  {
912  JSON_THROW(type_error::create(302, "type must be array, but is " + j.type_name()));
913  }
914  arr = *j.template get_ptr<const typename BasicJsonType::array_t*>();
915 }
916 
917 template<typename BasicJsonType, typename CompatibleArrayType>
918 void from_json_array_impl(const BasicJsonType& j, CompatibleArrayType& arr, detail::priority_tag<0>)
919 {
920  using std::begin;
921  using std::end;
922 
923  std::transform(j.begin(), j.end(),
924  std::inserter(arr, end(arr)), [](const BasicJsonType & i)
925  {
926  // get<BasicJsonType>() returns *this, this won't call a from_json
927  // method when value_type is BasicJsonType
928  return i.template get<typename CompatibleArrayType::value_type>();
929  });
930 }
931 
932 template<typename BasicJsonType, typename CompatibleArrayType>
933 auto from_json_array_impl(const BasicJsonType& j, CompatibleArrayType& arr, detail::priority_tag<1>)
934 -> decltype(
935  arr.reserve(std::declval<typename CompatibleArrayType::size_type>()),
936  void())
937 {
938  using std::begin;
939  using std::end;
940 
941  arr.reserve(j.size());
942  std::transform(j.begin(), j.end(),
943  std::inserter(arr, end(arr)), [](const BasicJsonType & i)
944  {
945  // get<BasicJsonType>() returns *this, this won't call a from_json
946  // method when value_type is BasicJsonType
947  return i.template get<typename CompatibleArrayType::value_type>();
948  });
949 }
950 
951 template<typename BasicJsonType, typename CompatibleArrayType,
952  enable_if_t<is_compatible_array_type<BasicJsonType, CompatibleArrayType>::value &&
953  std::is_convertible<BasicJsonType, typename CompatibleArrayType::value_type>::value &&
954  !std::is_same<typename BasicJsonType::array_t, CompatibleArrayType>::value, int> = 0>
955 void from_json(const BasicJsonType& j, CompatibleArrayType& arr)
956 {
957  if (!j.is_array())
958  {
959  JSON_THROW(type_error::create(302, "type must be array, but is " + j.type_name()));
960  }
961 
962  from_json_array_impl(j, arr, priority_tag<1> {});
963 }
964 
965 template<typename BasicJsonType>
966 inline
967 void from_json(const BasicJsonType& j, typename BasicJsonType::object_t& obj)
968 {
969  if (!j.is_object())
970  {
971  JSON_THROW(type_error::create(302, "type must be object, but is " + j.type_name()));
972  }
973 
974  auto inner_object = j.template get_ptr<const typename BasicJsonType::object_t*>();
975  for (const auto& i : *inner_object) {
976  obj.emplace_second(i.first(), i.second);
977  }
978 }
979 
980 template<typename BasicJsonType, typename CompatibleObjectType,
981  enable_if_t<is_compatible_object_type<BasicJsonType, CompatibleObjectType>::value &&
982  !std::is_same<typename BasicJsonType::object_t, CompatibleObjectType>::value, int> = 0>
983 void from_json(const BasicJsonType& j, CompatibleObjectType& obj)
984 {
985  if (!j.is_object())
986  {
987  JSON_THROW(type_error::create(302, "type must be object, but is " + j.type_name()));
988  }
989 
990  auto inner_object = j.template get_ptr<const typename BasicJsonType::object_t*>();
991  using std::begin;
992  using std::end;
993  using value_type = typename CompatibleObjectType::value_type;
994  std::vector<value_type> v;
995  v.reserve(j.size());
996  for (const auto& p : *inner_object)
997  {
998  v.emplace_back(
999  p.first(),
1000  p.second
1001  .template get<typename CompatibleObjectType::mapped_type>());
1002  }
1003  // we could avoid the assignment, but this might require a for loop, which
1004  // might be less efficient than the container constructor for some
1005  // containers (would it?)
1006  obj = CompatibleObjectType(std::make_move_iterator(begin(v)),
1007  std::make_move_iterator(end(v)));
1008 }
1009 
1010 // overload for arithmetic types, not chosen for json template arguments;
1011 template<typename BasicJsonType, typename ArithmeticType,
1012  enable_if_t <
1013  std::is_arithmetic<ArithmeticType>::value &&
1014  !std::is_same<ArithmeticType, std::uint64_t>::value &&
1015  !std::is_same<ArithmeticType, std::int64_t>::value &&
1016  !std::is_same<ArithmeticType, double>::value &&
1017  !std::is_same<ArithmeticType, bool>::value,
1018  int> = 0>
1019 void from_json(const BasicJsonType& j, ArithmeticType& val)
1020 {
1021  switch (static_cast<value_t>(j))
1022  {
1024  {
1025  val = static_cast<ArithmeticType>(*j.template get_ptr<const std::uint64_t*>());
1026  break;
1027  }
1029  {
1030  val = static_cast<ArithmeticType>(*j.template get_ptr<const std::int64_t*>());
1031  break;
1032  }
1033  case value_t::number_float:
1034  {
1035  val = static_cast<ArithmeticType>(*j.template get_ptr<const double*>());
1036  break;
1037  }
1038  case value_t::boolean:
1039  {
1040  val = static_cast<ArithmeticType>(*j.template get_ptr<const bool*>());
1041  break;
1042  }
1043  default:
1044  {
1045  JSON_THROW(type_error::create(302, "type must be number, but is " + j.type_name()));
1046  }
1047  }
1048 }
1049 
1050 template <typename BasicJsonType, typename CompatibleString, typename T,
1051  enable_if_t<std::is_constructible<llvm::StringRef,
1052  CompatibleString>::value, int> = 0>
1053 void from_json(const BasicJsonType& j, std::pair<CompatibleString, T>& p)
1054 {
1055  if (!j.is_object())
1056  {
1057  JSON_THROW(type_error::create(302, "type must be object, but is " + j.type_name()));
1058  }
1059 
1060  auto const inner_object = j.template get_ptr<const typename BasicJsonType::object_t*>();
1061  auto const size = inner_object->size();
1062  if (size != 1)
1063  {
1064  JSON_THROW(other_error::create(502, "conversion to std::pair requires the object to have exactly one field, but it has " + std::to_string(size)));
1065  }
1066  auto const& obj = *inner_object->begin();
1067  // cannot use *inner_object, need to convert both members
1068  p = std::make_pair(CompatibleString(obj.first()), obj.second.template get<T>());
1069 }
1070 
1072 {
1073  private:
1074  template<typename BasicJsonType, typename T>
1075  auto call(BasicJsonType& j, T&& val, priority_tag<1>) const noexcept(noexcept(to_json(j, std::forward<T>(val))))
1076  -> decltype(to_json(j, std::forward<T>(val)), void())
1077  {
1078  return to_json(j, std::forward<T>(val));
1079  }
1080 
1081  template<typename BasicJsonType, typename T>
1082  void call(BasicJsonType&, T&&, priority_tag<0>) const noexcept
1083  {
1084  static_assert(sizeof(BasicJsonType) == 0,
1085  "could not find to_json() method in T's namespace");
1086  }
1087 
1088  public:
1089  template<typename BasicJsonType, typename T>
1090  void operator()(BasicJsonType& j, T&& val) const
1091  noexcept(noexcept(std::declval<to_json_fn>().call(j, std::forward<T>(val), priority_tag<1> {})))
1092  {
1093  return call(j, std::forward<T>(val), priority_tag<1> {});
1094  }
1095 };
1096 
1098 {
1099  private:
1100  template<typename BasicJsonType, typename T>
1101  auto call(const BasicJsonType& j, T& val, priority_tag<1>) const
1102  noexcept(noexcept(from_json(j, val)))
1103  -> decltype(from_json(j, val), void())
1104  {
1105  return from_json(j, val);
1106  }
1107 
1108  template<typename BasicJsonType, typename T>
1109  void call(const BasicJsonType&, T&, priority_tag<0>) const noexcept
1110  {
1111  static_assert(sizeof(BasicJsonType) == 0,
1112  "could not find from_json() method in T's namespace");
1113  }
1114 
1115  public:
1116  template<typename BasicJsonType, typename T>
1117  void operator()(const BasicJsonType& j, T& val) const
1118  noexcept(noexcept(std::declval<from_json_fn>().call(j, val, priority_tag<1> {})))
1119  {
1120  return call(j, val, priority_tag<1> {});
1121  }
1122 };
1123 
1124 // taken from ranges-v3
1125 template<typename T>
1127 {
1128  static constexpr T value{};
1129 };
1130 
1131 template<typename T>
1132 constexpr T static_const<T>::value;
1133 } // namespace detail
1134 
1135 
1137 namespace
1138 {
1139 constexpr const auto& to_json = detail::static_const<detail::to_json_fn>::value;
1140 constexpr const auto& from_json = detail::static_const<detail::from_json_fn>::value;
1141 }
1142 
1201 class json
1202 {
1203  private:
1204  template<detail::value_t> friend struct detail::external_constructor;
1205  friend class JsonTest;
1206 
1207  public:
1208  using value_t = detail::value_t;
1209  // forward declarations
1210  template<typename U> class iter_impl;
1211  class json_pointer;
1212 
1213  class parser;
1214  class serializer;
1215  class binary_writer;
1216 
1218  // exceptions //
1220 
1224 
1237 
1239 
1240 
1242  // container types //
1244 
1249 
1251  using value_type = json;
1252 
1256  using const_reference = const value_type&;
1257 
1259  using difference_type = std::ptrdiff_t;
1261  using size_type = std::size_t;
1262 
1264  using pointer = json*;
1266  using const_pointer = const json*;
1267 
1272 
1274 
1298  static json meta();
1299 
1301  // JSON value data types //
1303 
1308 
1367 
1406  using array_t = std::vector<json>;
1407 
1456 
1477  using boolean_t = bool;
1478 
1545  using number_integer_t = int64_t;
1546 
1612  using number_unsigned_t = uint64_t;
1613 
1676  using number_float_t = double;
1677 
1679 
1680  private:
1681 
1683  template<typename T, typename... Args>
1684  static T* create(Args&& ... args)
1685  {
1686  std::allocator<T> alloc;
1687  auto deleter = [&](T * object)
1688  {
1689  alloc.deallocate(object, 1);
1690  };
1691  std::unique_ptr<T, decltype(deleter)> object(alloc.allocate(1), deleter);
1692  alloc.construct(object.get(), std::forward<Args>(args)...);
1693  assert(object != nullptr);
1694  return object.release();
1695  }
1696 
1698  // JSON value storage //
1700 
1701  public:
1727  {
1735  bool boolean;
1737  std::int64_t number_integer;
1739  std::uint64_t number_unsigned;
1742 
1744  json_value() = default;
1746  json_value(bool v) noexcept : boolean(v) {}
1748  json_value(std::int64_t v) noexcept : number_integer(v) {}
1750  json_value(std::uint64_t v) noexcept : number_unsigned(v) {}
1752  json_value(double v) noexcept : number_float(v) {}
1754  json_value(value_t t);
1755 
1757  json_value(llvm::StringRef value);
1758  json_value(const std::string& value);
1759 
1761  json_value(const object_t& value);
1762 
1764  json_value(const array_t& value);
1765  };
1766 
1767  private:
1777  void assert_invariant() const
1778  {
1779  assert(m_type != value_t::object || m_value.object != nullptr);
1780  assert(m_type != value_t::array || m_value.array != nullptr);
1781  assert(m_type != value_t::string || m_value.string != nullptr);
1782  }
1783 
1784  public:
1786  // JSON parser callback //
1788 
1799  enum class parse_event_t : uint8_t
1800  {
1802  object_start,
1804  object_end,
1806  array_start,
1808  array_end,
1810  key,
1812  value
1813  };
1814 
1867  using parser_callback_t = std::function<bool(int depth,
1868  parse_event_t event,
1869  json& parsed)>;
1870 
1871 
1873  // constructors //
1875 
1880 
1906  : m_type(value_type), m_value(value_type)
1907  {
1908  assert_invariant();
1909  }
1910 
1929  json(std::nullptr_t = nullptr) noexcept
1930  : json(value_t::null)
1931  {
1932  assert_invariant();
1933  }
1934 
1988  template<typename CompatibleType, typename U = detail::uncvref_t<CompatibleType>,
1989  detail::enable_if_t<!std::is_base_of<wpi::raw_istream, U>::value &&
1990  !std::is_same<U, json>::value &&
1991  !detail::is_json_nested_type<json, U>::value,
1992  int> = 0>
1993  json(CompatibleType && val)
1994  {
1995  to_json(*this, std::forward<CompatibleType>(val));
1996  assert_invariant();
1997  }
1998 
2070  json(std::initializer_list<json> init,
2071  bool type_deduction = true,
2072  value_t manual_type = value_t::array);
2073 
2108  static json array(std::initializer_list<json> init =
2109  std::initializer_list<json>())
2110  {
2111  return json(init, false, value_t::array);
2112  }
2113 
2149  static json object(std::initializer_list<json> init =
2150  std::initializer_list<json>())
2151  {
2152  return json(init, false, value_t::object);
2153  }
2154 
2173  json(size_type cnt, const json& val);
2174 
2217  template<class InputIT, typename std::enable_if<
2218  std::is_same<InputIT, json::iterator>::value ||
2219  std::is_same<InputIT, json::const_iterator>::value, int>::type = 0>
2220  json(InputIT first, InputIT last)
2221  {
2222  assert(first.m_object != nullptr);
2223  assert(last.m_object != nullptr);
2224 
2225  // make sure iterator fits the current value
2226  if (first.m_object != last.m_object)
2227  {
2228  JSON_THROW(invalid_iterator::create(201, "iterators are not compatible"));
2229  }
2230 
2231  // copy type from first iterator
2232  m_type = first.m_object->m_type;
2233 
2234  // check if iterator range is complete for primitive values
2235  switch (m_type)
2236  {
2237  case value_t::boolean:
2238  case value_t::number_float:
2241  case value_t::string:
2242  {
2243  if (!first.m_it.primitive_iterator.is_begin() || !last.m_it.primitive_iterator.is_end())
2244  {
2245  JSON_THROW(invalid_iterator::create(204, "iterators out of range"));
2246  }
2247  break;
2248  }
2249 
2250  default:
2251  {
2252  break;
2253  }
2254  }
2255 
2256  switch (m_type)
2257  {
2259  {
2260  m_value.number_integer = first.m_object->m_value.number_integer;
2261  break;
2262  }
2263 
2265  {
2266  m_value.number_unsigned = first.m_object->m_value.number_unsigned;
2267  break;
2268  }
2269 
2270  case value_t::number_float:
2271  {
2272  m_value.number_float = first.m_object->m_value.number_float;
2273  break;
2274  }
2275 
2276  case value_t::boolean:
2277  {
2278  m_value.boolean = first.m_object->m_value.boolean;
2279  break;
2280  }
2281 
2282  case value_t::string:
2283  {
2284  m_value = *first.m_object->m_value.string;
2285  break;
2286  }
2287 
2288  case value_t::array:
2289  {
2290  m_value.array = create<array_t>(first.m_it.array_iterator,
2291  last.m_it.array_iterator);
2292  break;
2293  }
2294 
2295  default:
2296  {
2297  JSON_THROW(invalid_iterator::create(206, "cannot construct with iterators from " +
2298  first.m_object->type_name()));
2299  }
2300  }
2301 
2302  assert_invariant();
2303  }
2304 
2305 
2307  // other constructors and destructor //
2309 
2330  json(const json& other);
2331 
2350  json(json&& other) noexcept
2351  : m_type(std::move(other.m_type)),
2352  m_value(std::move(other.m_value))
2353  {
2354  // check that passed value is valid
2355  other.assert_invariant();
2356 
2357  // invalidate payload
2358  other.m_type = value_t::null;
2359  other.m_value = {};
2360 
2361  assert_invariant();
2362  }
2363 
2387  reference& operator=(json other) noexcept (
2388  std::is_nothrow_move_constructible<value_t>::value &&
2389  std::is_nothrow_move_assignable<value_t>::value &&
2390  std::is_nothrow_move_constructible<json_value>::value &&
2391  std::is_nothrow_move_assignable<json_value>::value
2392  )
2393  {
2394  // check that passed value is valid
2395  other.assert_invariant();
2396 
2397  using std::swap;
2398  swap(m_type, other.m_type);
2399  swap(m_value, other.m_value);
2400 
2401  assert_invariant();
2402  return *this;
2403  }
2404 
2420  ~json();
2421 
2423 
2424  public:
2426  // object inspection //
2428 
2432 
2456  std::string dump(const int indent = -1) const;
2457 
2480  void dump(llvm::raw_ostream& os, int indent = -1) const;
2481 
2500  value_t type() const noexcept
2501  {
2502  return m_type;
2503  }
2504 
2530  bool is_primitive() const noexcept
2531  {
2532  return is_null() || is_string() || is_boolean() || is_number();
2533  }
2534 
2557  bool is_structured() const noexcept
2558  {
2559  return is_array() || is_object();
2560  }
2561 
2579  bool is_null() const noexcept
2580  {
2581  return m_type == value_t::null;
2582  }
2583 
2601  bool is_boolean() const noexcept
2602  {
2603  return m_type == value_t::boolean;
2604  }
2605 
2631  bool is_number() const noexcept
2632  {
2633  return is_number_integer() || is_number_float();
2634  }
2635 
2660  bool is_number_integer() const noexcept
2661  {
2662  return m_type == value_t::number_integer || m_type == value_t::number_unsigned;
2663  }
2664 
2688  bool is_number_unsigned() const noexcept
2689  {
2690  return m_type == value_t::number_unsigned;
2691  }
2692 
2716  bool is_number_float() const noexcept
2717  {
2718  return m_type == value_t::number_float;
2719  }
2720 
2738  bool is_object() const noexcept
2739  {
2740  return m_type == value_t::object;
2741  }
2742 
2760  bool is_array() const noexcept
2761  {
2762  return m_type == value_t::array;
2763  }
2764 
2782  bool is_string() const noexcept
2783  {
2784  return m_type == value_t::string;
2785  }
2786 
2809  bool is_discarded() const noexcept
2810  {
2811  return m_type == value_t::discarded;
2812  }
2813 
2832  operator value_t() const noexcept
2833  {
2834  return m_type;
2835  }
2836 
2838 
2839  private:
2841  // value access //
2843 
2845  bool get_impl(bool* /*unused*/) const
2846  {
2847  if (is_boolean())
2848  {
2849  return m_value.boolean;
2850  }
2851 
2852  JSON_THROW(type_error::create(302, "type must be boolean, but is " + type_name()));
2853  }
2854 
2856  object_t* get_impl_ptr(object_t* /*unused*/) noexcept
2857  {
2858  return is_object() ? m_value.object : nullptr;
2859  }
2860 
2862  const object_t* get_impl_ptr(const object_t* /*unused*/) const noexcept
2863  {
2864  return is_object() ? m_value.object : nullptr;
2865  }
2866 
2868  array_t* get_impl_ptr(array_t* /*unused*/) noexcept
2869  {
2870  return is_array() ? m_value.array : nullptr;
2871  }
2872 
2874  const array_t* get_impl_ptr(const array_t* /*unused*/) const noexcept
2875  {
2876  return is_array() ? m_value.array : nullptr;
2877  }
2878 
2880  std::string* get_impl_ptr(std::string* /*unused*/) noexcept
2881  {
2882  return is_string() ? m_value.string : nullptr;
2883  }
2884 
2886  const std::string* get_impl_ptr(const std::string* /*unused*/) const noexcept
2887  {
2888  return is_string() ? m_value.string : nullptr;
2889  }
2890 
2892  bool* get_impl_ptr(bool* /*unused*/) noexcept
2893  {
2894  return is_boolean() ? &m_value.boolean : nullptr;
2895  }
2896 
2898  const bool* get_impl_ptr(const bool* /*unused*/) const noexcept
2899  {
2900  return is_boolean() ? &m_value.boolean : nullptr;
2901  }
2902 
2904  std::int64_t* get_impl_ptr(std::int64_t* /*unused*/) noexcept
2905  {
2906  return is_number_integer() ? &m_value.number_integer : nullptr;
2907  }
2908 
2910  const std::int64_t* get_impl_ptr(const std::int64_t* /*unused*/) const noexcept
2911  {
2912  return is_number_integer() ? &m_value.number_integer : nullptr;
2913  }
2914 
2916  std::uint64_t* get_impl_ptr(std::uint64_t* /*unused*/) noexcept
2917  {
2918  return is_number_unsigned() ? &m_value.number_unsigned : nullptr;
2919  }
2920 
2922  const std::uint64_t* get_impl_ptr(const std::uint64_t* /*unused*/) const noexcept
2923  {
2924  return is_number_unsigned() ? &m_value.number_unsigned : nullptr;
2925  }
2926 
2928  double* get_impl_ptr(double* /*unused*/) noexcept
2929  {
2930  return is_number_float() ? &m_value.number_float : nullptr;
2931  }
2932 
2934  const double* get_impl_ptr(const double* /*unused*/) const noexcept
2935  {
2936  return is_number_float() ? &m_value.number_float : nullptr;
2937  }
2938 
2950  template<typename ReferenceType, typename ThisType>
2951  static ReferenceType get_ref_impl(ThisType& obj)
2952  {
2953  // helper type
2954  using PointerType = typename std::add_pointer<ReferenceType>::type;
2955 
2956  // delegate the call to get_ptr<>()
2957  auto ptr = obj.template get_ptr<PointerType>();
2958 
2959  if (ptr != nullptr)
2960  {
2961  return *ptr;
2962  }
2963 
2964  JSON_THROW(type_error::create(303, "incompatible ReferenceType for get_ref, actual type is " + obj.type_name()));
2965  }
2966 
2967  public:
2971 
2986  template <
2987  typename BasicJsonType,
2988  detail::enable_if_t<std::is_same<typename std::remove_const<BasicJsonType>::type,
2989  json>::value,
2990  int> = 0 >
2991  json get() const
2992  {
2993  return *this;
2994  }
2995 
3035  template <
3036  typename ValueTypeCV,
3037  typename ValueType = detail::uncvref_t<ValueTypeCV>,
3038  detail::enable_if_t < !std::is_same<json, ValueType>::value, int > = 0 >
3039  ValueType get() const
3040  {
3041  // we cannot static_assert on ValueTypeCV being non-const, because
3042  // there is support for get<const json>(), which is why we
3043  // still need the uncvref
3044  static_assert(!std::is_reference<ValueTypeCV>::value,
3045  "get() cannot be used with reference types, you might want to use get_ref()");
3046  static_assert(std::is_default_constructible<ValueType>::value,
3047  "types must be DefaultConstructible when used with get()");
3048 
3049  ValueType ret;
3050  from_json(*this, ret);
3051  return ret;
3052  }
3053 
3081  template<typename PointerType, typename std::enable_if<
3082  std::is_pointer<PointerType>::value, int>::type = 0>
3083  PointerType get() noexcept
3084  {
3085  // delegate the call to get_ptr
3086  return get_ptr<PointerType>();
3087  }
3088 
3093  template<typename PointerType, typename std::enable_if<
3094  std::is_pointer<PointerType>::value, int>::type = 0>
3095  const PointerType get() const noexcept
3096  {
3097  // delegate the call to get_ptr
3098  return get_ptr<PointerType>();
3099  }
3100 
3127  template<typename PointerType, typename std::enable_if<
3128  std::is_pointer<PointerType>::value, int>::type = 0>
3129  PointerType get_ptr() noexcept
3130  {
3131  // get the type of the PointerType (remove pointer and const)
3132  using pointee_t = typename std::remove_const<typename
3133  std::remove_pointer<typename
3134  std::remove_const<PointerType>::type>::type>::type;
3135  // make sure the type matches the allowed types
3136  static_assert(
3137  std::is_same<object_t, pointee_t>::value
3138  || std::is_same<array_t, pointee_t>::value
3139  || std::is_same<std::string, pointee_t>::value
3140  || std::is_same<bool, pointee_t>::value
3141  || std::is_same<std::int64_t, pointee_t>::value
3142  || std::is_same<std::uint64_t, pointee_t>::value
3143  || std::is_same<double, pointee_t>::value
3144  , "incompatible pointer type");
3145 
3146  // delegate the call to get_impl_ptr<>()
3147  return get_impl_ptr(static_cast<PointerType>(nullptr));
3148  }
3149 
3154  template<typename PointerType, typename std::enable_if<
3155  std::is_pointer<PointerType>::value &&
3156  std::is_const<typename std::remove_pointer<PointerType>::type>::value, int>::type = 0>
3157  const PointerType get_ptr() const noexcept
3158  {
3159  // get the type of the PointerType (remove pointer and const)
3160  using pointee_t = typename std::remove_const<typename
3161  std::remove_pointer<typename
3162  std::remove_const<PointerType>::type>::type>::type;
3163  // make sure the type matches the allowed types
3164  static_assert(
3165  std::is_same<object_t, pointee_t>::value
3166  || std::is_same<array_t, pointee_t>::value
3167  || std::is_same<std::string, pointee_t>::value
3168  || std::is_same<bool, pointee_t>::value
3169  || std::is_same<std::int64_t, pointee_t>::value
3170  || std::is_same<std::uint64_t, pointee_t>::value
3171  || std::is_same<double, pointee_t>::value
3172  , "incompatible pointer type");
3173 
3174  // delegate the call to get_impl_ptr<>() const
3175  return get_impl_ptr(static_cast<const PointerType>(nullptr));
3176  }
3177 
3204  template<typename ReferenceType, typename std::enable_if<
3205  std::is_reference<ReferenceType>::value, int>::type = 0>
3206  ReferenceType get_ref()
3207  {
3208  // delegate call to get_ref_impl
3209  return get_ref_impl<ReferenceType>(*this);
3210  }
3211 
3216  template<typename ReferenceType, typename std::enable_if<
3217  std::is_reference<ReferenceType>::value &&
3218  std::is_const<typename std::remove_reference<ReferenceType>::type>::value, int>::type = 0>
3219  ReferenceType get_ref() const
3220  {
3221  // delegate call to get_ref_impl
3222  return get_ref_impl<ReferenceType>(*this);
3223  }
3224 
3254  template < typename ValueType, typename std::enable_if <
3255  !std::is_pointer<ValueType>::value &&
3256  !std::is_same<ValueType, std::string::value_type>::value
3257 #ifndef _MSC_VER // fix for issue #167 operator<< ambiguity under VS2015
3258  && !std::is_same<ValueType, std::initializer_list<std::string::value_type>>::value
3259 #endif
3260 #if (defined(__cplusplus) && __cplusplus >= 201703L) || (defined(_MSC_VER) && _MSC_VER >1900 && defined(_HAS_CXX17) && _HAS_CXX17 == 1) // fix for issue #464
3261  && !std::is_same<ValueType, typename std::string_view>::value
3262 #endif
3263  , int >::type = 0 >
3264  operator ValueType() const
3265  {
3266  // delegate the call to get<>() const
3267  return get<ValueType>();
3268  }
3269 
3271 
3272 
3274  // element access //
3276 
3280 
3307  reference at(size_type idx);
3308 
3335  const_reference at(size_type idx) const;
3336 
3367  reference at(llvm::StringRef key);
3368 
3399  const_reference at(llvm::StringRef key) const;
3400 
3426  reference operator[](size_type idx);
3427 
3447  const_reference operator[](size_type idx) const;
3448 
3476  reference operator[](llvm::StringRef key);
3477 
3508  const_reference operator[](llvm::StringRef key) const;
3509 
3537  template<typename T, std::size_t n>
3538  reference operator[](T * (&key)[n])
3539  {
3540  return operator[](static_cast<const T>(key));
3541  }
3542 
3572  template<typename T, std::size_t n>
3573  const_reference operator[](T * (&key)[n]) const
3574  {
3575  return operator[](static_cast<const T>(key));
3576  }
3577 
3605  template<typename T>
3607  {
3608  return this->operator[](llvm::StringRef(key));
3609  }
3610 
3641  template<typename T>
3643  {
3644  return this->operator[](llvm::StringRef(key));
3645  }
3646 
3695  template<class ValueType, typename std::enable_if<
3696  std::is_convertible<json, ValueType>::value, int>::type = 0>
3697  ValueType value(llvm::StringRef key, ValueType default_value) const
3698  {
3699  // at only works for objects
3700  if (is_object())
3701  {
3702  // if key is found, return value and given default value otherwise
3703  const auto it = find(key);
3704  if (it != end())
3705  {
3706  return *it;
3707  }
3708 
3709  return default_value;
3710  }
3711  else
3712  {
3713  JSON_THROW(type_error::create(306, "cannot use value() with " + type_name()));
3714  }
3715  }
3716 
3721  std::string value(llvm::StringRef key, const char* default_value) const
3722  {
3723  return value(key, std::string(default_value));
3724  }
3725 
3767  template<class ValueType, typename std::enable_if<
3768  std::is_convertible<json, ValueType>::value, int>::type = 0>
3769  ValueType value(const json_pointer& ptr, ValueType default_value) const
3770  {
3771  // at only works for objects
3772  if (is_object())
3773  {
3774  // if pointer resolves a value, return it or use default value
3775  JSON_TRY
3776  {
3777  return ptr.get_checked(this);
3778  }
3779  JSON_CATCH (out_of_range&)
3780  {
3781  return default_value;
3782  }
3783  }
3784 
3785  JSON_THROW(type_error::create(306, "cannot use value() with " + type_name()));
3786  }
3787 
3792  std::string value(const json_pointer& ptr, const char* default_value) const
3793  {
3794  return value(ptr, std::string(default_value));
3795  }
3796 
3823  {
3824  return *begin();
3825  }
3826 
3831  {
3832  return *cbegin();
3833  }
3834 
3866  reference back();
3867 
3871  const_reference back() const;
3872 
3917  template<class IteratorType, typename std::enable_if<
3918  std::is_same<IteratorType, json::iterator>::value ||
3919  std::is_same<IteratorType, json::const_iterator>::value, int>::type
3920  = 0>
3921  void erase(IteratorType pos)
3922  {
3923  // make sure iterator fits the current value
3924  if (this != pos.m_object)
3925  {
3926  JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value"));
3927  }
3928 
3929  switch (m_type)
3930  {
3931  case value_t::boolean:
3932  case value_t::number_float:
3935  case value_t::string:
3936  {
3937  if (!pos.m_it.primitive_iterator.is_begin())
3938  {
3939  JSON_THROW(invalid_iterator::create(205, "iterator out of range"));
3940  }
3941 
3942  if (is_string())
3943  {
3944  std::allocator<std::string> alloc;
3945  alloc.destroy(m_value.string);
3946  alloc.deallocate(m_value.string, 1);
3947  m_value.string = nullptr;
3948  }
3949 
3950  m_type = value_t::null;
3951  assert_invariant();
3952  break;
3953  }
3954 
3955  case value_t::object:
3956  {
3957  m_value.object->erase(pos.m_it.object_iterator);
3958  break;
3959  }
3960 
3961  case value_t::array:
3962  {
3963  m_value.array->erase(pos.m_it.array_iterator);
3964  break;
3965  }
3966 
3967  default:
3968  {
3969  JSON_THROW(type_error::create(307, "cannot use erase() with " + type_name()));
3970  }
3971  }
3972  }
3973 
4020  template<class IteratorType, typename std::enable_if<
4021  std::is_same<IteratorType, json::iterator>::value ||
4022  std::is_same<IteratorType, json::const_iterator>::value, int>::type
4023  = 0>
4024  void erase(IteratorType first, IteratorType last)
4025  {
4026  // make sure iterator fits the current value
4027  if (this != first.m_object || this != last.m_object)
4028  {
4029  JSON_THROW(invalid_iterator::create(203, "iterators do not fit current value"));
4030  }
4031 
4032  switch (m_type)
4033  {
4034  case value_t::boolean:
4035  case value_t::number_float:
4038  case value_t::string:
4039  {
4040  if (!first.m_it.primitive_iterator.is_begin() || !last.m_it.primitive_iterator.is_end())
4041  {
4042  JSON_THROW(invalid_iterator::create(204, "iterators out of range"));
4043  }
4044 
4045  if (is_string())
4046  {
4047  std::allocator<std::string> alloc;
4048  alloc.destroy(m_value.string);
4049  alloc.deallocate(m_value.string, 1);
4050  m_value.string = nullptr;
4051  }
4052 
4053  m_type = value_t::null;
4054  assert_invariant();
4055  break;
4056  }
4057 
4058  case value_t::array:
4059  {
4060  m_value.array->erase(first.m_it.array_iterator,
4061  last.m_it.array_iterator);
4062  break;
4063  }
4064 
4065  default:
4066  {
4067  JSON_THROW(type_error::create(307, "cannot use erase() with " + type_name()));
4068  }
4069  }
4070  }
4071 
4101  size_type erase(llvm::StringRef key);
4102 
4127  void erase(const size_type idx);
4128 
4130 
4131 
4133  // lookup //
4135 
4138 
4161  iterator find(llvm::StringRef key);
4162 
4167  const_iterator find(llvm::StringRef key) const;
4168 
4191  {
4192  // return 0 for all nonobject types
4193  return is_object() ? m_value.object->count(key) : 0;
4194  }
4195 
4197 
4198 
4200  // iterators //
4202 
4205 
4230  iterator begin() noexcept
4231  {
4232  iterator result(this);
4233  result.set_begin();
4234  return result;
4235  }
4236 
4240  const_iterator begin() const noexcept
4241  {
4242  return cbegin();
4243  }
4244 
4270  const_iterator cbegin() const noexcept
4271  {
4272  const_iterator result(this);
4273  result.set_begin();
4274  return result;
4275  }
4276 
4301  iterator end() noexcept
4302  {
4303  iterator result(this);
4304  result.set_end();
4305  return result;
4306  }
4307 
4311  const_iterator end() const noexcept
4312  {
4313  return cend();
4314  }
4315 
4341  const_iterator cend() const noexcept
4342  {
4343  const_iterator result(this);
4344  result.set_end();
4345  return result;
4346  }
4347 
4348  private:
4349  // forward declaration
4350  template<typename IteratorType> class iteration_proxy;
4351 
4352  public:
4366  static iteration_proxy<iterator> iterator_wrapper(reference cont)
4367  {
4368  return iteration_proxy<iterator>(cont);
4369  }
4370 
4374  static iteration_proxy<const_iterator> iterator_wrapper(const_reference cont)
4375  {
4376  return iteration_proxy<const_iterator>(cont);
4377  }
4378 
4380 
4381 
4383  // capacity //
4385 
4388 
4426  bool empty() const noexcept;
4427 
4466  size_type size() const noexcept;
4467 
4504  size_type max_size() const noexcept;
4505 
4507 
4508 
4510  // modifiers //
4512 
4515 
4538  void clear() noexcept;
4539 
4560  void push_back(json&& val);
4561 
4567  {
4568  push_back(std::move(val));
4569  return *this;
4570  }
4571 
4576  void push_back(const json& val);
4577 
4583  {
4584  push_back(val);
4585  return *this;
4586  }
4587 
4608  void push_back(const std::pair<llvm::StringRef, json>& val);
4609 
4614  reference operator+=(const std::pair<llvm::StringRef, json>& val)
4615  {
4616  push_back(val);
4617  return *this;
4618  }
4619 
4645  void push_back(std::initializer_list<json> init);
4646 
4651  reference operator+=(std::initializer_list<json> init)
4652  {
4653  push_back(init);
4654  return *this;
4655  }
4656 
4678  template<class... Args>
4679  void emplace_back(Args&& ... args)
4680  {
4681  // emplace_back only works for null objects or arrays
4682  if (!(is_null() || is_array()))
4683  {
4684  JSON_THROW(type_error::create(311, "cannot use emplace_back() with " + type_name()));
4685  }
4686 
4687  // transform null object into an array
4688  if (is_null())
4689  {
4690  m_type = value_t::array;
4691  m_value = value_t::array;
4692  assert_invariant();
4693  }
4694 
4695  // add element to array (perfect forwarding)
4696  m_value.array->emplace_back(std::forward<Args>(args)...);
4697  }
4698 
4726  template<class... Args>
4727  std::pair<iterator, bool> emplace(llvm::StringRef key, Args&& ... args)
4728  {
4729  // emplace only works for null objects or arrays
4730  if (!(is_null() || is_object()))
4731  {
4732  JSON_THROW(type_error::create(311, "cannot use emplace() with " + type_name()));
4733  }
4734 
4735  // transform null object into an object
4736  if (is_null())
4737  {
4738  m_type = value_t::object;
4739  m_value = value_t::object;
4740  assert_invariant();
4741  }
4742 
4743  // add element to array (perfect forwarding)
4744  auto res = m_value.object->emplace_second(key, std::forward<Args>(args)...);
4745  // create result iterator and set iterator to the result of emplace
4746  auto it = begin();
4747  it.m_it.object_iterator = res.first;
4748 
4749  // return pair of iterator and boolean
4750  return {it, res.second};
4751  }
4752 
4775  iterator insert(const_iterator pos, const json& val);
4776 
4782  {
4783  return insert(pos, val);
4784  }
4785 
4810  iterator insert(const_iterator pos, size_type cnt, const json& val);
4811 
4842  iterator insert(const_iterator pos, const_iterator first, const_iterator last);
4843 
4868  iterator insert(const_iterator pos, std::initializer_list<json> ilist);
4869 
4893  void insert(const_iterator first, const_iterator last);
4894 
4912  void swap(reference other) noexcept (
4913  std::is_nothrow_move_constructible<value_t>::value &&
4914  std::is_nothrow_move_assignable<value_t>::value &&
4915  std::is_nothrow_move_constructible<json_value>::value &&
4916  std::is_nothrow_move_assignable<json_value>::value
4917  )
4918  {
4919  std::swap(m_type, other.m_type);
4920  std::swap(m_value, other.m_value);
4921  assert_invariant();
4922  }
4923 
4944  void swap(array_t& other)
4945  {
4946  // swap only works for arrays
4947  if (is_array())
4948  {
4949  std::swap(*(m_value.array), other);
4950  }
4951  else
4952  {
4953  JSON_THROW(type_error::create(310, "cannot use swap() with " + type_name()));
4954  }
4955  }
4956 
4977  void swap(object_t& other)
4978  {
4979  // swap only works for objects
4980  if (is_object())
4981  {
4982  std::swap(*(m_value.object), other);
4983  }
4984  else
4985  {
4986  JSON_THROW(type_error::create(310, "cannot use swap() with " + type_name()));
4987  }
4988  }
4989 
5010  void swap(std::string& other)
5011  {
5012  // swap only works for strings
5013  if (is_string())
5014  {
5015  std::swap(*(m_value.string), other);
5016  }
5017  else
5018  {
5019  JSON_THROW(type_error::create(310, "cannot use swap() with " + type_name()));
5020  }
5021  }
5022 
5024 
5025  public:
5027  // lexicographical comparison operators //
5029 
5032 
5060  friend bool operator==(const_reference lhs, const_reference rhs) noexcept;
5061 
5066  template<typename ScalarType, typename std::enable_if<
5067  std::is_scalar<ScalarType>::value, int>::type = 0>
5068  friend bool operator==(const_reference lhs, const ScalarType rhs) noexcept
5069  {
5070  return (lhs == json(rhs));
5071  }
5072 
5077  template<typename ScalarType, typename std::enable_if<
5078  std::is_scalar<ScalarType>::value, int>::type = 0>
5079  friend bool operator==(const ScalarType lhs, const_reference rhs) noexcept
5080  {
5081  return (json(lhs) == rhs);
5082  }
5083 
5100  friend bool operator!=(const_reference lhs, const_reference rhs) noexcept
5101  {
5102  return !(lhs == rhs);
5103  }
5104 
5109  template<typename ScalarType, typename std::enable_if<
5110  std::is_scalar<ScalarType>::value, int>::type = 0>
5111  friend bool operator!=(const_reference lhs, const ScalarType rhs) noexcept
5112  {
5113  return (lhs != json(rhs));
5114  }
5115 
5120  template<typename ScalarType, typename std::enable_if<
5121  std::is_scalar<ScalarType>::value, int>::type = 0>
5122  friend bool operator!=(const ScalarType lhs, const_reference rhs) noexcept
5123  {
5124  return (json(lhs) != rhs);
5125  }
5126 
5151  friend bool operator<(const_reference lhs, const_reference rhs) noexcept;
5152 
5157  template<typename ScalarType, typename std::enable_if<
5158  std::is_scalar<ScalarType>::value, int>::type = 0>
5159  friend bool operator<(const_reference lhs, const ScalarType rhs) noexcept
5160  {
5161  return (lhs < json(rhs));
5162  }
5163 
5168  template<typename ScalarType, typename std::enable_if<
5169  std::is_scalar<ScalarType>::value, int>::type = 0>
5170  friend bool operator<(const ScalarType lhs, const_reference rhs) noexcept
5171  {
5172  return (json(lhs) < rhs);
5173  }
5174 
5192  friend bool operator<=(const_reference lhs, const_reference rhs) noexcept
5193  {
5194  return !(rhs < lhs);
5195  }
5196 
5201  template<typename ScalarType, typename std::enable_if<
5202  std::is_scalar<ScalarType>::value, int>::type = 0>
5203  friend bool operator<=(const_reference lhs, const ScalarType rhs) noexcept
5204  {
5205  return (lhs <= json(rhs));
5206  }
5207 
5212  template<typename ScalarType, typename std::enable_if<
5213  std::is_scalar<ScalarType>::value, int>::type = 0>
5214  friend bool operator<=(const ScalarType lhs, const_reference rhs) noexcept
5215  {
5216  return (json(lhs) <= rhs);
5217  }
5218 
5236  friend bool operator>(const_reference lhs, const_reference rhs) noexcept
5237  {
5238  return !(lhs <= rhs);
5239  }
5240 
5245  template<typename ScalarType, typename std::enable_if<
5246  std::is_scalar<ScalarType>::value, int>::type = 0>
5247  friend bool operator>(const_reference lhs, const ScalarType rhs) noexcept
5248  {
5249  return (lhs > json(rhs));
5250  }
5251 
5256  template<typename ScalarType, typename std::enable_if<
5257  std::is_scalar<ScalarType>::value, int>::type = 0>
5258  friend bool operator>(const ScalarType lhs, const_reference rhs) noexcept
5259  {
5260  return (json(lhs) > rhs);
5261  }
5262 
5280  friend bool operator>=(const_reference lhs, const_reference rhs) noexcept
5281  {
5282  return !(lhs < rhs);
5283  }
5284 
5289  template<typename ScalarType, typename std::enable_if<
5290  std::is_scalar<ScalarType>::value, int>::type = 0>
5291  friend bool operator>=(const_reference lhs, const ScalarType rhs) noexcept
5292  {
5293  return (lhs >= json(rhs));
5294  }
5295 
5300  template<typename ScalarType, typename std::enable_if<
5301  std::is_scalar<ScalarType>::value, int>::type = 0>
5302  friend bool operator>=(const ScalarType lhs, const_reference rhs) noexcept
5303  {
5304  return (json(lhs) >= rhs);
5305  }
5306 
5308 
5310  // serialization //
5312 
5315 
5316  public:
5345  friend llvm::raw_ostream& operator<<(llvm::raw_ostream& o, const json& j);
5346 
5348 
5349 
5351  // deserialization //
5353 
5356 
5388  static json parse(llvm::StringRef s,
5389  const parser_callback_t cb = nullptr);
5390 
5420  static json parse(wpi::raw_istream& i,
5421  const parser_callback_t cb = nullptr);
5422 
5449  friend wpi::raw_istream& operator>>(wpi::raw_istream& i, json& j);
5450 
5452 
5454  // convenience functions //
5456 
5472  std::string type_name() const;
5473 
5474  private:
5476  // member variables //
5478 
5480  value_t m_type = value_t::null;
5481 
5483  json_value m_value = {};
5484 
5485 
5486  private:
5488  // iterators //
5490 
5500  class primitive_iterator_t
5501  {
5502  public:
5503 
5504  difference_type get_value() const noexcept
5505  {
5506  return m_it;
5507  }
5509  void set_begin() noexcept
5510  {
5511  m_it = begin_value;
5512  }
5513 
5515  void set_end() noexcept
5516  {
5517  m_it = end_value;
5518  }
5519 
5521  constexpr bool is_begin() const noexcept
5522  {
5523  return (m_it == begin_value);
5524  }
5525 
5527  constexpr bool is_end() const noexcept
5528  {
5529  return (m_it == end_value);
5530  }
5531 
5532  friend constexpr bool operator==(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept
5533  {
5534  return lhs.m_it == rhs.m_it;
5535  }
5536 
5537  friend constexpr bool operator!=(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept
5538  {
5539  return !(lhs == rhs);
5540  }
5541 
5542  friend constexpr bool operator<(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept
5543  {
5544  return lhs.m_it < rhs.m_it;
5545  }
5546 
5547  friend constexpr bool operator<=(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept
5548  {
5549  return lhs.m_it <= rhs.m_it;
5550  }
5551 
5552  friend constexpr bool operator>(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept
5553  {
5554  return lhs.m_it > rhs.m_it;
5555  }
5556 
5557  friend constexpr bool operator>=(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept
5558  {
5559  return lhs.m_it >= rhs.m_it;
5560  }
5561 
5562  primitive_iterator_t operator+(difference_type i)
5563  {
5564  auto result = *this;
5565  result += i;
5566  return result;
5567  }
5568 
5569  friend constexpr difference_type operator-(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept
5570  {
5571  return lhs.m_it - rhs.m_it;
5572  }
5573 
5574  friend llvm::raw_ostream& operator<<(llvm::raw_ostream& os, primitive_iterator_t it)
5575  {
5576  return os << it.m_it;
5577  }
5578 
5579  primitive_iterator_t& operator++()
5580  {
5581  ++m_it;
5582  return *this;
5583  }
5584 
5585  primitive_iterator_t operator++(int)
5586  {
5587  auto result = *this;
5588  m_it++;
5589  return result;
5590  }
5591 
5592  primitive_iterator_t& operator--()
5593  {
5594  --m_it;
5595  return *this;
5596  }
5597 
5598  primitive_iterator_t operator--(int)
5599  {
5600  auto result = *this;
5601  m_it--;
5602  return result;
5603  }
5604 
5605  primitive_iterator_t& operator+=(difference_type n)
5606  {
5607  m_it += n;
5608  return *this;
5609  }
5610 
5611  primitive_iterator_t& operator-=(difference_type n)
5612  {
5613  m_it -= n;
5614  return *this;
5615  }
5616 
5617  private:
5618  static constexpr difference_type begin_value = 0;
5619  static constexpr difference_type end_value = begin_value + 1;
5620 
5622  difference_type m_it = std::numeric_limits<std::ptrdiff_t>::denorm_min();
5623  };
5624 
5632  struct internal_iterator
5633  {
5635  typename object_t::iterator object_iterator;
5637  typename array_t::iterator array_iterator;
5639  primitive_iterator_t primitive_iterator;
5640 
5642  internal_iterator() noexcept
5643  : object_iterator(), array_iterator(), primitive_iterator()
5644  {}
5645  };
5646 
5648  template<typename IteratorType>
5649  class iteration_proxy
5650  {
5651  private:
5653  class iteration_proxy_internal
5654  {
5655  private:
5657  IteratorType anchor;
5659  size_t array_index = 0;
5660 
5661  public:
5662  explicit iteration_proxy_internal(IteratorType it) noexcept
5663  : anchor(it)
5664  {}
5665 
5667  iteration_proxy_internal& operator*()
5668  {
5669  return *this;
5670  }
5671 
5673  iteration_proxy_internal& operator++()
5674  {
5675  ++anchor;
5676  ++array_index;
5677 
5678  return *this;
5679  }
5680 
5682  bool operator!= (const iteration_proxy_internal& o) const
5683  {
5684  return anchor != o.anchor;
5685  }
5686 
5688  std::string key() const
5689  {
5690  assert(anchor.m_object != nullptr);
5691 
5692  switch (anchor.m_object->type())
5693  {
5694  // use integer array index as key
5695  case value_t::array:
5696  {
5697  return std::to_string(array_index);
5698  }
5699 
5700  // use key from the object
5701  case value_t::object:
5702  {
5703  return anchor.key();
5704  }
5705 
5706  // use an empty key for all primitive types
5707  default:
5708  {
5709  return "";
5710  }
5711  }
5712  }
5713 
5715  typename IteratorType::reference value() const
5716  {
5717  return anchor.value();
5718  }
5719  };
5720 
5722  typename IteratorType::reference container;
5723 
5724  public:
5726  explicit iteration_proxy(typename IteratorType::reference cont)
5727  : container(cont)
5728  {}
5729 
5731  iteration_proxy_internal begin() noexcept
5732  {
5733  return iteration_proxy_internal(container.begin());
5734  }
5735 
5737  iteration_proxy_internal end() noexcept
5738  {
5739  return iteration_proxy_internal(container.end());
5740  }
5741  };
5742 
5743  public:
5763  template<typename U>
5764  class iter_impl : public std::iterator<std::random_access_iterator_tag, U>
5765  {
5767  friend class json;
5768  friend class JsonTest;
5769 
5770  // make sure U is json or const json
5771  static_assert(std::is_same<U, json>::value
5772  || std::is_same<U, const json>::value,
5773  "iter_impl only accepts (const) json");
5774 
5775  public:
5777  using value_type = typename json::value_type;
5781  using pointer = typename std::conditional<std::is_const<U>::value,
5782  typename json::const_pointer,
5783  typename json::pointer>::type;
5785  using reference = typename std::conditional<std::is_const<U>::value,
5786  typename json::const_reference,
5787  typename json::reference>::type;
5789  using iterator_category = std::bidirectional_iterator_tag;
5790 
5792  iter_impl() noexcept : m_object(nullptr) {}
5793 
5800  explicit iter_impl(pointer object) noexcept
5801  : m_object(object)
5802  {
5803  assert(m_object != nullptr);
5804 
5805  switch (m_object->m_type)
5806  {
5807  case json::value_t::object:
5808  {
5809  m_it.object_iterator = typename object_t::iterator();
5810  break;
5811  }
5812 
5813  case json::value_t::array:
5814  {
5815  m_it.array_iterator = typename array_t::iterator();
5816  break;
5817  }
5818 
5819  default:
5820  {
5821  m_it.primitive_iterator = primitive_iterator_t();
5822  break;
5823  }
5824  }
5825  }
5826 
5842  iter_impl(const iter_impl<json>& other) noexcept
5843  : m_object(other.m_object), m_it(other.m_it)
5844  {}
5845 
5852  iter_impl& operator=(const iter_impl<json>& other) noexcept
5853  {
5854  m_object = other.m_object;
5855  m_it = other.m_it;
5856  return *this;
5857  }
5858 
5859  private:
5864  void set_begin() noexcept
5865  {
5866  assert(m_object != nullptr);
5867 
5868  switch (m_object->m_type)
5869  {
5870  case json::value_t::object:
5871  {
5872  m_it.object_iterator = m_object->m_value.object->begin();
5873  break;
5874  }
5875 
5876  case json::value_t::array:
5877  {
5878  m_it.array_iterator = m_object->m_value.array->begin();
5879  break;
5880  }
5881 
5882  case json::value_t::null:
5883  {
5884  // set to end so begin()==end() is true: null is empty
5885  m_it.primitive_iterator.set_end();
5886  break;
5887  }
5888 
5889  default:
5890  {
5891  m_it.primitive_iterator.set_begin();
5892  break;
5893  }
5894  }
5895  }
5896 
5901  void set_end() noexcept
5902  {
5903  assert(m_object != nullptr);
5904 
5905  switch (m_object->m_type)
5906  {
5907  case json::value_t::object:
5908  {
5909  m_it.object_iterator = m_object->m_value.object->end();
5910  break;
5911  }
5912 
5913  case json::value_t::array:
5914  {
5915  m_it.array_iterator = m_object->m_value.array->end();
5916  break;
5917  }
5918 
5919  default:
5920  {
5921  m_it.primitive_iterator.set_end();
5922  break;
5923  }
5924  }
5925  }
5926 
5927  public:
5933  {
5934  assert(m_object != nullptr);
5935 
5936  switch (m_object->m_type)
5937  {
5938  case json::value_t::object:
5939  {
5940  assert(m_it.object_iterator != m_object->m_value.object->end());
5941  return m_it.object_iterator->second;
5942  }
5943 
5944  case json::value_t::array:
5945  {
5946  assert(m_it.array_iterator != m_object->m_value.array->end());
5947  return *m_it.array_iterator;
5948  }
5949 
5950  case json::value_t::null:
5951  {
5952  JSON_THROW(invalid_iterator::create(214, "cannot get value"));
5953  }
5954 
5955  default:
5956  {
5957  if (m_it.primitive_iterator.is_begin())
5958  {
5959  return *m_object;
5960  }
5961 
5962  JSON_THROW(invalid_iterator::create(214, "cannot get value"));
5963  }
5964  }
5965  }
5966 
5972  {
5973  assert(m_object != nullptr);
5974 
5975  switch (m_object->m_type)
5976  {
5977  case json::value_t::object:
5978  {
5979  assert(m_it.object_iterator != m_object->m_value.object->end());
5980  return &(m_it.object_iterator->second);
5981  }
5982 
5983  case json::value_t::array:
5984  {
5985  assert(m_it.array_iterator != m_object->m_value.array->end());
5986  return &*m_it.array_iterator;
5987  }
5988 
5989  default:
5990  {
5991  if (m_it.primitive_iterator.is_begin())
5992  {
5993  return m_object;
5994  }
5995 
5996  JSON_THROW(invalid_iterator::create(214, "cannot get value"));
5997  }
5998  }
5999  }
6000 
6006  {
6007  auto result = *this;
6008  ++(*this);
6009  return result;
6010  }
6011 
6017  {
6018  assert(m_object != nullptr);
6019 
6020  switch (m_object->m_type)
6021  {
6022  case json::value_t::object:
6023  {
6024  ++m_it.object_iterator;
6025  break;
6026  }
6027 
6028  case json::value_t::array:
6029  {
6030  ++m_it.array_iterator;
6031  break;
6032  }
6033 
6034  default:
6035  {
6036  ++m_it.primitive_iterator;
6037  break;
6038  }
6039  }
6040 
6041  return *this;
6042  }
6043 
6049  {
6050  auto result = *this;
6051  --(*this);
6052  return result;
6053  }
6054 
6060  {
6061  assert(m_object != nullptr);
6062 
6063  switch (m_object->m_type)
6064  {
6065  case json::value_t::object:
6066  {
6067  JSON_THROW(invalid_iterator::create(209, "cannot decrement object iterators"));
6068  break;
6069  }
6070 
6071  case json::value_t::array:
6072  {
6073  std::advance(m_it.array_iterator, -1);
6074  break;
6075  }
6076 
6077  default:
6078  {
6079  --m_it.primitive_iterator;
6080  break;
6081  }
6082  }
6083 
6084  return *this;
6085  }
6086 
6091  bool operator==(const iter_impl& other) const
6092  {
6093  // if objects are not the same, the comparison is undefined
6094  if (m_object != other.m_object)
6095  {
6096  JSON_THROW(invalid_iterator::create(212, "cannot compare iterators of different containers"));
6097  }
6098 
6099  assert(m_object != nullptr);
6100 
6101  switch (m_object->m_type)
6102  {
6103  case json::value_t::object:
6104  {
6105  return (m_it.object_iterator == other.m_it.object_iterator);
6106  }
6107 
6108  case json::value_t::array:
6109  {
6110  return (m_it.array_iterator == other.m_it.array_iterator);
6111  }
6112 
6113  default:
6114  {
6115  return (m_it.primitive_iterator == other.m_it.primitive_iterator);
6116  }
6117  }
6118  }
6119 
6124  bool operator!=(const iter_impl& other) const
6125  {
6126  return !operator==(other);
6127  }
6128 
6133  bool operator<(const iter_impl& other) const
6134  {
6135  // if objects are not the same, the comparison is undefined
6136  if (m_object != other.m_object)
6137  {
6138  JSON_THROW(invalid_iterator::create(212, "cannot compare iterators of different containers"));
6139  }
6140 
6141  assert(m_object != nullptr);
6142 
6143  switch (m_object->m_type)
6144  {
6145  case json::value_t::object:
6146  {
6147  JSON_THROW(invalid_iterator::create(213, "cannot compare order of object iterators"));
6148  }
6149 
6150  case json::value_t::array:
6151  {
6152  return (m_it.array_iterator < other.m_it.array_iterator);
6153  }
6154 
6155  default:
6156  {
6157  return (m_it.primitive_iterator < other.m_it.primitive_iterator);
6158  }
6159  }
6160  }
6161 
6166  bool operator<=(const iter_impl& other) const
6167  {
6168  return !(other.operator < (*this));
6169  }
6170 
6175  bool operator>(const iter_impl& other) const
6176  {
6177  return !operator<=(other);
6178  }
6179 
6184  bool operator>=(const iter_impl& other) const
6185  {
6186  return !operator<(other);
6187  }
6188 
6194  {
6195  assert(m_object != nullptr);
6196 
6197  switch (m_object->m_type)
6198  {
6199  case json::value_t::object:
6200  {
6201  JSON_THROW(invalid_iterator::create(209, "cannot use offsets with object iterators"));
6202  }
6203 
6204  case json::value_t::array:
6205  {
6206  std::advance(m_it.array_iterator, i);
6207  break;
6208  }
6209 
6210  default:
6211  {
6212  m_it.primitive_iterator += i;
6213  break;
6214  }
6215  }
6216 
6217  return *this;
6218  }
6219 
6225  {
6226  return operator+=(-i);
6227  }
6228 
6234  {
6235  auto result = *this;
6236  result += i;
6237  return result;
6238  }
6239 
6245  {
6246  auto result = it;
6247  result += i;
6248  return result;
6249  }
6250 
6256  {
6257  auto result = *this;
6258  result -= i;
6259  return result;
6260  }
6261 
6267  {
6268  assert(m_object != nullptr);
6269 
6270  switch (m_object->m_type)
6271  {
6272  case json::value_t::object:
6273  {
6274  JSON_THROW(invalid_iterator::create(209, "cannot use offsets with object iterators"));
6275  }
6276 
6277  case json::value_t::array:
6278  {
6279  return m_it.array_iterator - other.m_it.array_iterator;
6280  }
6281 
6282  default:
6283  {
6284  return m_it.primitive_iterator - other.m_it.primitive_iterator;
6285  }
6286  }
6287  }
6288 
6294  {
6295  assert(m_object != nullptr);
6296 
6297  switch (m_object->m_type)
6298  {
6299  case json::value_t::object:
6300  {
6301  JSON_THROW(invalid_iterator::create(208, "cannot use operator[] for object iterators"));
6302  }
6303 
6304  case json::value_t::array:
6305  {
6306  return *std::next(m_it.array_iterator, n);
6307  }
6308 
6309  case json::value_t::null:
6310  {
6311  JSON_THROW(invalid_iterator::create(214, "cannot get value"));
6312  }
6313 
6314  default:
6315  {
6316  if (m_it.primitive_iterator.get_value() == -n)
6317  {
6318  return *m_object;
6319  }
6320 
6321  JSON_THROW(invalid_iterator::create(214, "cannot get value"));
6322  }
6323  }
6324  }
6325 
6331  {
6332  assert(m_object != nullptr);
6333 
6334  if (m_object->is_object())
6335  {
6336  return m_it.object_iterator->first();
6337  }
6338 
6339  JSON_THROW(invalid_iterator::create(207, "cannot use key() for non-object iterators"));
6340  }
6341 
6347  {
6348  return operator*();
6349  }
6350 
6351  private:
6353  pointer m_object;
6355  struct internal_iterator m_it = internal_iterator();
6356  };
6357 
6359  // binary serialization/deserialization //
6361 
6364 
6365  public:
6448  static void to_cbor(llvm::raw_ostream& os, const json& j);
6449  static llvm::StringRef to_cbor(const json& j, llvm::SmallVectorImpl<char> buf);
6450  static std::string to_cbor(const json& j);
6451 
6526  static void to_msgpack(llvm::raw_ostream& os, const json& j);
6527  static llvm::StringRef to_msgpack(const json& j, llvm::SmallVectorImpl<char> buf);
6528  static std::string to_msgpack(const json& j);
6529 
6616  static json from_cbor(wpi::raw_istream& is);
6617  static json from_cbor(llvm::StringRef s);
6618 
6685  static json from_msgpack(wpi::raw_istream& is);
6686  static json from_msgpack(llvm::StringRef s);
6687 
6689 
6690  public:
6703  {
6705  friend class json;
6706  friend class JsonTest;
6707 
6708  public:
6731  explicit json_pointer(const std::string& s = "")
6732  : reference_tokens(split(s))
6733  {}
6734 
6750  std::string to_string() const noexcept;
6751 
6753  operator std::string() const
6754  {
6755  return to_string();
6756  }
6757 
6758  private:
6763  std::string pop_back()
6764  {
6765  if (is_root())
6766  {
6767  JSON_THROW(out_of_range::create(405, "JSON pointer has no parent"));
6768  }
6769 
6770  auto last = reference_tokens.back();
6771  reference_tokens.pop_back();
6772  return last;
6773  }
6774 
6776  bool is_root() const
6777  {
6778  return reference_tokens.empty();
6779  }
6780 
6781  json_pointer top() const
6782  {
6783  if (is_root())
6784  {
6785  JSON_THROW(out_of_range::create(405, "JSON pointer has no parent"));
6786  }
6787 
6788  json_pointer result = *this;
6789  result.reference_tokens = {reference_tokens[0]};
6790  return result;
6791  }
6792 
6801  reference get_and_create(reference j) const;
6802 
6822  reference get_unchecked(pointer ptr) const;
6823 
6830  reference get_checked(pointer ptr) const;
6831 
6845  const_reference get_unchecked(const_pointer ptr) const;
6846 
6853  const_reference get_checked(const_pointer ptr) const;
6854 
6864  static std::vector<std::string> split(const std::string& reference_string);
6865 
6879  static void replace_substring(std::string& s,
6880  const std::string& f,
6881  const std::string& t);
6882 
6884  static std::string escape(std::string s);
6885 
6887  static void unescape(std::string& s);
6888 
6896  static void flatten(const std::string& reference_string,
6897  const json& value,
6898  json& result);
6899 
6910  static json unflatten(const json& value);
6911 
6912  friend bool operator==(json_pointer const& lhs,
6913  json_pointer const& rhs) noexcept
6914  {
6915  return lhs.reference_tokens == rhs.reference_tokens;
6916  }
6917 
6918  friend bool operator!=(json_pointer const& lhs,
6919  json_pointer const& rhs) noexcept
6920  {
6921  return !(lhs == rhs);
6922  }
6923 
6925  std::vector<std::string> reference_tokens {};
6926  };
6927 
6929  // JSON Pointer support //
6931 
6934 
6969  {
6970  return ptr.get_unchecked(this);
6971  }
6972 
6997  {
6998  return ptr.get_unchecked(this);
6999  }
7000 
7037  {
7038  return ptr.get_checked(this);
7039  }
7040 
7076  const_reference at(const json_pointer& ptr) const
7077  {
7078  return ptr.get_checked(this);
7079  }
7080 
7103  json flatten() const
7104  {
7105  json result(value_t::object);
7106  json_pointer::flatten("", *this, result);
7107  return result;
7108  }
7109 
7140  json unflatten() const
7141  {
7142  return json_pointer::unflatten(*this);
7143  }
7144 
7146 };
7147 
7148 } // namespace wpi
7149 
7150 
7152 // nonmember support //
7154 
7155 // specialization of std::swap, and std::hash
7156 namespace std
7157 {
7163 template<>
7164 inline void swap(wpi::json& j1,
7165  wpi::json& j2) noexcept(
7166  is_nothrow_move_constructible<wpi::json>::value &&
7167  is_nothrow_move_assignable<wpi::json>::value
7168  )
7169 {
7170  j1.swap(j2);
7171 }
7172 
7174 template<>
7175 struct hash<wpi::json>
7176 {
7182  std::size_t operator()(const wpi::json& j) const;
7183 };
7184 
7186 template <>
7187 struct less<::wpi::detail::value_t>
7188 {
7194  wpi::detail::value_t rhs) const noexcept
7195  {
7196  return wpi::detail::operator<(lhs, rhs);
7197  }
7198 };
7199 
7200 } // namespace std
7201 
7215 inline wpi::json operator "" _json(const char* s, std::size_t n)
7216 {
7217  return wpi::json::parse(llvm::StringRef(s, n));
7218 }
7219 
7233 inline wpi::json::json_pointer operator "" _json_pointer(const char* s, std::size_t n)
7234 {
7235  return wpi::json::json_pointer(std::string(s, n));
7236 }
7237 
7238 #ifndef WPI_JSON_IMPLEMENTATION
7239 
7240 // restore GCC/clang diagnostic settings
7241 #if defined(__clang__) || defined(__GNUC__) || defined(__GNUG__)
7242  #pragma GCC diagnostic pop
7243 #endif
7244 #if defined(__clang__)
7245  #pragma GCC diagnostic pop
7246 #endif
7247 
7248 // clean up
7249 #undef JSON_CATCH
7250 #undef JSON_THROW
7251 #undef JSON_TRY
7252 #undef JSON_LIKELY
7253 #undef JSON_UNLIKELY
7254 
7255 #endif // WPI_JSON_IMPLEMENTATION
7256 
7257 #endif
friend bool operator==(const_reference lhs, const ScalarType rhs) noexcept
comparison: equal
Definition: json.h:5068
friend bool operator==(const ScalarType lhs, const_reference rhs) noexcept
comparison: equal
Definition: json.h:5079
friend bool operator>(const_reference lhs, const_reference rhs) noexcept
comparison: greater than
Definition: json.h:5236
Definition: json.h:454
std::vector< json > array_t
a type for an array
Definition: json.h:1406
const_reference operator[](T *key) const
read-only access specified object element
Definition: json.h:3642
void swap(array_t &other)
exchanges the values
Definition: json.h:4944
reference front()
access the first element
Definition: json.h:3822
iter_impl & operator++()
pre-increment (++it)
Definition: json.h:6016
bool is_null() const noexcept
return whether value is null
Definition: json.h:2579
std::uint64_t number_unsigned
number (unsigned integer)
Definition: json.h:1739
static json array(std::initializer_list< json > init=std::initializer_list< json >())
explicitly create an array from an initializer list
Definition: json.h:2108
serialization to CBOR and MessagePack values
Definition: json_binary_writer.cpp:51
reference operator+=(const json &val)
add an object to an array
Definition: json.h:4582
iter_impl operator--(int)
post-decrement (it–)
Definition: json.h:6048
bool is_discarded() const noexcept
return whether value is discarded
Definition: json.h:2809
static json parse(llvm::StringRef s, const parser_callback_t cb=nullptr)
deserialize from string literal
Definition: json_parser.cpp:2076
json(const value_t value_type)
create an empty value with a given type
Definition: json.h:1905
iterator end() noexcept
returns an iterator to one past the last element
Definition: json.h:4301
void erase(IteratorType pos)
remove element given an iterator
Definition: json.h:3921
bool operator!=(const iter_impl &other) const
comparison: not equal
Definition: json.h:6124
bool operator==(const iter_impl &other) const
comparison: equal
Definition: json.h:6091
llvm::StringRef key() const
return the key of an object iterator
Definition: json.h:6330
ValueType value(llvm::StringRef key, ValueType default_value) const
access specified object element with default value
Definition: json.h:3697
typename std::conditional< std::is_const< U >::value, typename json::const_pointer, typename json::pointer >::type pointer
defines a pointer to the type iterated over (value_type)
Definition: json.h:5783
const_reference at(const json_pointer &ptr) const
access specified element via JSON Pointer
Definition: json.h:7076
json(CompatibleType &&val)
create a JSON value
Definition: json.h:1993
void erase(IteratorType first, IteratorType last)
remove elements given an iterator range
Definition: json.h:4024
syntax analysis
Definition: json_parser.cpp:1603
iter_impl & operator--()
pre-decrement (–it)
Definition: json.h:6059
reference operator[](difference_type n) const
access to successor
Definition: json.h:6293
friend bool operator!=(const_reference lhs, const ScalarType rhs) noexcept
comparison: not equal
Definition: json.h:5111
const_iterator cbegin() const noexcept
returns a const iterator to the first element
Definition: json.h:4270
iter_impl(pointer object) noexcept
constructor for a given JSON instance
Definition: json.h:5800
const value_type & const_reference
the type of an element const reference
Definition: json.h:1256
std::string value(const json_pointer &ptr, const char *default_value) const
overload for a default value of type const char*
Definition: json.h:3792
number value (unsigned integer)
Definition: json.cpp:1170
friend bool operator<=(const ScalarType lhs, const_reference rhs) noexcept
comparison: less than or equal
Definition: json.h:5214
value_t type() const noexcept
return the type of the JSON value (explicit)
Definition: json.h:2500
bool is_structured() const noexcept
return whether type is structured
Definition: json.h:2557
iterator begin() noexcept
returns an iterator to the first element
Definition: json.h:4230
std::pair< iterator, bool > emplace(llvm::StringRef key, Args &&...args)
add an object to an object if key does not exist
Definition: json.h:4727
discarded by the the parser callback function
std::string value(llvm::StringRef key, const char *default_value) const
overload for a default value of type const char*
Definition: json.h:3721
reference operator[](T *key)
access specified object element
Definition: json.h:3606
friend bool operator>=(const ScalarType lhs, const_reference rhs) noexcept
comparison: greater than or equal
Definition: json.h:5302
bool is_number_integer() const noexcept
return whether value is an integer number
Definition: json.h:2660
Definition: SocketError.cpp:17
const_iterator end() const noexcept
returns a const iterator to one past the last element
Definition: json.h:4311
reference & operator=(json other) noexcept(std::is_nothrow_move_constructible< value_t >::value &&std::is_nothrow_move_assignable< value_t >::value &&std::is_nothrow_move_constructible< json_value >::value &&std::is_nothrow_move_assignable< json_value >::value)
copy assignment
Definition: json.h:2387
a JSON value
Definition: json.h:1726
json value_type
the type of elements in a json container
Definition: json.h:1251
void swap(std::string &other)
exchanges the values
Definition: json.h:5010
virtual const char * what() const noexceptoverride
returns the explanatory string
Definition: json.h:139
json(json &&other) noexcept
move constructor
Definition: json.h:2350
reference at(const json_pointer &ptr)
access specified element via JSON Pointer
Definition: json.h:7036
void swap(object_t &other)
exchanges the values
Definition: json.h:4977
bool is_boolean() const noexcept
return whether value is a boolean
Definition: json.h:2601
typename std::conditional< std::is_const< U >::value, typename json::const_reference, typename json::reference >::type reference
defines a reference to the type iterated over (value_type)
Definition: json.h:5787
iterator insert(const_iterator pos, json &&val)
inserts element
Definition: json.h:4781
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory)...
Definition: ArrayRef.h:32
iter_impl operator+(difference_type i) const
add to iterator
Definition: json.h:6233
ReferenceType get_ref()
get a reference value (implicit)
Definition: json.h:3206
typename json::difference_type difference_type
a type to represent differences between iterators
Definition: json.h:5779
bool operator<=(const iter_impl &other) const
comparison: less than or equal
Definition: json.h:6166
json_value(std::uint64_t v) noexcept
constructor for numbers (unsigned)
Definition: json.h:1750
friend bool operator>(const_reference lhs, const ScalarType rhs) noexcept
comparison: greater than
Definition: json.h:5247
PointerType get_ptr() noexcept
get a pointer value (implicit)
Definition: json.h:3129
Definition: json.h:450
std::string * string
string (stored with pointer to save storage)
Definition: json.h:1733
Definition: raw_istream.h:21
bool operator>=(const iter_impl &other) const
comparison: greater than or equal
Definition: json.h:6184
reference operator[](const json_pointer &ptr)
access specified element via JSON Pointer
Definition: json.h:6968
wrapper around the serialization functions
Definition: json_serializer.h:46
std::bidirectional_iterator_tag iterator_category
the category of the iterator
Definition: json.h:5789
reference operator*() const
return a reference to the value pointed to by the iterator
Definition: json.h:5932
bool is_array() const noexcept
return whether value is an array
Definition: json.h:2760
const size_t byte
byte index of the parse error
Definition: json.h:217
bool is_number_unsigned() const noexcept
return whether value is an unsigned integer number
Definition: json.h:2688
static json object(std::initializer_list< json > init=std::initializer_list< json >())
explicitly create an object from an initializer list
Definition: json.h:2149
const int id
the id of the exception
Definition: json.h:145
json(std::nullptr_t=nullptr) noexcept
create a null object
Definition: json.h:1929
friend bool operator<=(const_reference lhs, const ScalarType rhs) noexcept
comparison: less than or equal
Definition: json.h:5203
friend iter_impl operator+(difference_type i, const iter_impl &it)
addition of distance and iterator
Definition: json.h:6244
iter_impl operator-(difference_type i) const
subtract from iterator
Definition: json.h:6255
object (unordered set of name/value pairs)
exception indicating access out of the defined range
Definition: json.h:311
number value (signed integer)
ReferenceType get_ref() const
get a reference value (implicit)
Definition: json.h:3219
bool operator<(const iter_impl &other) const
comparison: smaller
Definition: json.h:6133
general exception of the json class
Definition: json.h:135
array (ordered collection of values)
reference operator+=(json &&val)
add an object to an array
Definition: json.h:4566
Definition: json.h:461
static iteration_proxy< iterator > iterator_wrapper(reference cont)
wrapper to access iterator member functions in range-based for
Definition: json.h:4366
friend bool operator>=(const_reference lhs, const_reference rhs) noexcept
comparison: greater than or equal
Definition: json.h:5280
friend bool operator<=(const_reference lhs, const_reference rhs) noexcept
comparison: less than or equal
Definition: json.h:5192
Definition: json.h:453
uint64_t number_unsigned_t
a type for a number (unsigned)
Definition: json.h:1612
bool operator<(const value_t lhs, const value_t rhs) noexcept
comparison operator for JSON types
Definition: json.h:397
void swap(reference other) noexcept(std::is_nothrow_move_constructible< value_t >::value &&std::is_nothrow_move_assignable< value_t >::value &&std::is_nothrow_move_constructible< json_value >::value &&std::is_nothrow_move_assignable< json_value >::value)
exchanges the values
Definition: json.h:4912
size_type count(llvm::StringRef key) const
returns the number of occurrences of a key in a JSON object
Definition: json.h:4190
bool is_string() const noexcept
return whether value is a string
Definition: json.h:2782
exception indicating other errors
Definition: json.h:334
const json * const_pointer
the type of an element const pointer
Definition: json.h:1266
iter_impl & operator+=(difference_type i)
add to iterator
Definition: json.h:6193
std::string string_t
a type for a string
Definition: json.h:1455
Definition: json.h:1071
bool boolean
boolean
Definition: json.h:1735
json(InputIT first, InputIT last)
construct a JSON container given an iterator range
Definition: json.h:2220
friend bool operator<(const_reference lhs, const ScalarType rhs) noexcept
comparison: less than
Definition: json.h:5159
static iteration_proxy< const_iterator > iterator_wrapper(const_reference cont)
wrapper to access iterator member functions in range-based for
Definition: json.h:4374
std::function< bool(int depth, parse_event_t event, json &parsed)> parser_callback_t
per-element parser callback type
Definition: json.h:1869
friend bool operator!=(const ScalarType lhs, const_reference rhs) noexcept
comparison: not equal
Definition: json.h:5122
int64_t number_integer_t
a type for a number (integer)
Definition: json.h:1545
Definition: json.h:656
double number_float_t
a type for a number (floating-point)
Definition: json.h:1676
ValueType value(const json_pointer &ptr, ValueType default_value) const
access specified object element via JSON Pointer with default value
Definition: json.h:3769
friend bool operator>(const ScalarType lhs, const_reference rhs) noexcept
comparison: greater than
Definition: json.h:5258
a class to store JSON values
Definition: json.h:1201
StringMap - This is an unconventional map that is specialized for handling keys that are "strings"...
Definition: StringMap.h:202
double number_float
number (floating-point)
Definition: json.h:1741
Definition: json.h:1126
bool is_number() const noexcept
return whether value is a number
Definition: json.h:2631
exception indicating a parse error
Definition: json.h:194
exception indicating errors with iterators
Definition: json.h:249
bool is_number_float() const noexcept
return whether value is a floating-point number
Definition: json.h:2716
iter_impl() noexcept
default constructor
Definition: json.h:5792
const PointerType get_ptr() const noexcept
get a pointer value (implicit)
Definition: json.h:3157
iter_impl & operator=(const iter_impl< json > &other) noexcept
converting assignment
Definition: json.h:5852
bool is_object() const noexcept
return whether value is an object
Definition: json.h:2738
std::size_t size_type
a type to represent container sizes
Definition: json.h:1261
iter_impl & operator-=(difference_type i)
subtract from iterator
Definition: json.h:6224
reference operator[](T *(&key)[n])
access specified object element
Definition: json.h:3538
friend bool operator>=(const_reference lhs, const ScalarType rhs) noexcept
comparison: greater than or equal
Definition: json.h:5291
json unflatten() const
unflatten a previously flattened JSON value
Definition: json.h:7140
JSON Pointer.
Definition: json.h:6702
const_reference operator[](T *(&key)[n]) const
read-only access specified object element
Definition: json.h:3573
array_t * array
array (stored with pointer to save storage)
Definition: json.h:1731
Definition: StringMap.h:29
json_pointer(const std::string &s="")
create JSON pointer
Definition: json.h:6731
json_value(bool v) noexcept
constructor for booleans
Definition: json.h:1746
iter_impl operator++(int)
post-increment (it++)
Definition: json.h:6005
exception indicating executing a member function with a wrong type
Definition: json.h:284
reference operator+=(const std::pair< llvm::StringRef, json > &val)
add an object to an object
Definition: json.h:4614
iter_impl(const iter_impl< json > &other) noexcept
converting constructor
Definition: json.h:5842
std::int64_t number_integer
number (integer)
Definition: json.h:1737
difference_type operator-(const iter_impl &other) const
return difference
Definition: json.h:6266
bool boolean_t
a type for a boolean
Definition: json.h:1477
const_reference operator[](const json_pointer &ptr) const
access specified element via JSON Pointer
Definition: json.h:6996
value_t
the JSON type enumeration
Definition: json.h:375
bool operator>(const iter_impl &other) const
comparison: greater than
Definition: json.h:6175
json_value(double v) noexcept
constructor for numbers (floating-point)
Definition: json.h:1752
const_reference front() const
access the first element
Definition: json.h:3830
reference value() const
return the value of an iterator
Definition: json.h:6346
pointer operator->() const
dereference the iterator
Definition: json.h:5971
const_iterator cend() const noexcept
returns a const iterator to one past the last element
Definition: json.h:4341
void emplace_back(Args &&...args)
add an object to an array
Definition: json.h:4679
This class implements an extremely fast bulk output stream that can only output to a stream...
Definition: raw_ostream.h:33
json_value(std::int64_t v) noexcept
constructor for numbers (integer)
Definition: json.h:1748
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:42
Definition: json.h:445
parse_event_t
JSON callback events.
Definition: json.h:1799
const_iterator begin() const noexcept
returns a const iterator to the first element
Definition: json.h:4240
Definition: json.h:1097
std::ptrdiff_t difference_type
a type to represent differences between iterators
Definition: json.h:1259
friend bool operator<(const ScalarType lhs, const_reference rhs) noexcept
comparison: less than
Definition: json.h:5170
a template for a random access iterator for the json class
Definition: json.h:1210
number value (floating-point)
typename json::value_type value_type
the type of the values when the iterator is dereferenced
Definition: json.h:5777
reference operator+=(std::initializer_list< json > init)
add an object to an object
Definition: json.h:4651
bool is_primitive() const noexcept
return whether type is primitive
Definition: json.h:2530
friend bool operator!=(const_reference lhs, const_reference rhs) noexcept
comparison: not equal
Definition: json.h:5100
json flatten() const
return flattened JSON value
Definition: json.h:7103
Definition: json.h:446
bool operator()(wpi::detail::value_t lhs, wpi::detail::value_t rhs) const noexcept
compare two value_t enum values
Definition: json.h:7193
object_t * object
object (stored with pointer to save storage)
Definition: json.h:1729