WPILibC++  2020.3.2-60-g3011ebe
json.h
1 /*----------------------------------------------------------------------------*/
2 /* Modifications Copyright (c) 2017-2019 FIRST. 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 3.1.2
11 |_____|_____|_____|_|___| https://github.com/nlohmann/json
12 
13 Licensed under the MIT License <http://opensource.org/licenses/MIT>.
14 Copyright (c) 2013-2018 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 WPIUTIL_JSON_H
36 #define WPIUTIL_JSON_H
37 
38 #define NLOHMANN_JSON_VERSION_MAJOR 3
39 #define NLOHMANN_JSON_VERSION_MINOR 1
40 #define NLOHMANN_JSON_VERSION_PATCH 2
41 
42 
43 #include <algorithm> // all_of, copy, find, for_each, generate_n, min, reverse, remove, fill, none_of, transform
44 #include <array> // array
45 #include <cassert> // assert
46 #include <ciso646> // and, not, or
47 #include <cstddef> // nullptr_t, ptrdiff_t, size_t
48 #include <cstdint> // uint8_t, uint16_t, uint32_t, uint64_t
49 #include <exception> // exception
50 #include <functional> // function, hash, less
51 #include <initializer_list> // initializer_list
52 #include <iterator>
53 #include <limits> // numeric_limits
54 #include <memory> // allocator, shared_ptr, make_shared, addressof
55 #include <stdexcept> // runtime_error
56 #include <string> // string, char_traits, stoi, to_string
57 #include <tuple> // tuple, get, make_tuple
58 #include <type_traits>
59 #include <utility>
60 #include <vector> // vector
61 
62 #include "wpi/ArrayRef.h"
63 #include "wpi/StringMap.h"
64 #include "wpi/StringRef.h"
65 #include "wpi/Twine.h"
66 
67 namespace wpi
68 {
69 
70 class raw_istream;
71 class raw_ostream;
72 
73 class JsonTest;
74 
82 template<typename = void, typename = void>
84 
96 class json_pointer;
97 
106 class json;
107 }
108 
109 // exclude unsupported compilers
110 #if defined(__clang__)
111  #if (__clang_major__ * 10000 + __clang_minor__ * 100 + __clang_patchlevel__) < 30400
112  #error "unsupported Clang version - see https://github.com/nlohmann/json#supported-compilers"
113  #endif
114 #elif defined(__GNUC__) && !(defined(__ICC) || defined(__INTEL_COMPILER))
115  #if (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) < 40900
116  #error "unsupported GCC version - see https://github.com/nlohmann/json#supported-compilers"
117  #endif
118 #endif
119 
120 // disable float-equal warnings on GCC/clang
121 #if defined(__clang__) || defined(__GNUC__) || defined(__GNUG__)
122  #pragma GCC diagnostic push
123  #pragma GCC diagnostic ignored "-Wfloat-equal"
124 #endif
125 
126 // disable documentation warnings on clang
127 #if defined(__clang__)
128  #pragma GCC diagnostic push
129  #pragma GCC diagnostic ignored "-Wdocumentation"
130 #endif
131 
132 // allow to disable exceptions
133 #if (defined(__cpp_exceptions) || defined(__EXCEPTIONS) || defined(_CPPUNWIND)) && !defined(JSON_NOEXCEPTION)
134  #define JSON_THROW(exception) throw exception
135  #define JSON_TRY try
136  #define JSON_CATCH(exception) catch(exception)
137 #else
138  #define JSON_THROW(exception) std::abort()
139  #define JSON_TRY if(true)
140  #define JSON_CATCH(exception) if(false)
141 #endif
142 
143 // override exception macros
144 #if defined(JSON_THROW_USER)
145  #undef JSON_THROW
146  #define JSON_THROW JSON_THROW_USER
147 #endif
148 #if defined(JSON_TRY_USER)
149  #undef JSON_TRY
150  #define JSON_TRY JSON_TRY_USER
151 #endif
152 #if defined(JSON_CATCH_USER)
153  #undef JSON_CATCH
154  #define JSON_CATCH JSON_CATCH_USER
155 #endif
156 
157 // manual branch prediction
158 #if defined(__clang__) || defined(__GNUC__) || defined(__GNUG__)
159  #define JSON_LIKELY(x) __builtin_expect(!!(x), 1)
160  #define JSON_UNLIKELY(x) __builtin_expect(!!(x), 0)
161 #else
162  #define JSON_LIKELY(x) x
163  #define JSON_UNLIKELY(x) x
164 #endif
165 
176 #define NLOHMANN_JSON_HAS_HELPER(type) \
177  template<typename T> struct has_##type { \
178  private: \
179  template<typename U, typename = typename U::type> \
180  static int detect(U &&); \
181  static void detect(...); \
182  public: \
183  static constexpr bool value = \
184  std::is_integral<decltype(detect(std::declval<T>()))>::value; \
185  }
186 
187 namespace wpi
188 {
197 namespace detail
198 {
200 // helpers //
202 
203 template<typename> struct is_json : std::false_type {};
204 
205 template<> struct is_json<json> : std::true_type {};
206 
207 // alias templates to reduce boilerplate
208 template<bool B, typename T = void>
209 using enable_if_t = typename std::enable_if<B, T>::type;
210 
211 template<typename T>
212 using uncvref_t = typename std::remove_cv<typename std::remove_reference<T>::type>::type;
213 
214 // dispatch utility (taken from ranges-v3)
215 template<unsigned N> struct priority_tag : priority_tag < N - 1 > {};
216 template<> struct priority_tag<0> {};
217 
219 // has_/is_ functions //
221 
222 // source: https://stackoverflow.com/a/37193089/4116453
223 
224 template <typename T, typename = void>
225 struct is_complete_type : std::false_type {};
226 
227 template <typename T>
228 struct is_complete_type<T, decltype(void(sizeof(T)))> : std::true_type {};
229 
230 NLOHMANN_JSON_HAS_HELPER(mapped_type);
231 NLOHMANN_JSON_HAS_HELPER(key_type);
232 NLOHMANN_JSON_HAS_HELPER(value_type);
233 NLOHMANN_JSON_HAS_HELPER(iterator);
234 
235 template<bool B, class RealType, class CompatibleObjectType>
236 struct is_compatible_object_type_impl : std::false_type {};
237 
238 template<class RealType, class CompatibleObjectType>
239 struct is_compatible_object_type_impl<true, RealType, CompatibleObjectType>
240 {
241  static constexpr auto value =
242  std::is_constructible<StringRef, typename CompatibleObjectType::key_type>::value and
243  std::is_constructible<typename RealType::mapped_type, typename CompatibleObjectType::mapped_type>::value;
244 };
245 
246 template<class BasicJsonType, class CompatibleObjectType>
248 {
249  static auto constexpr value = is_compatible_object_type_impl <
250  std::conjunction<std::negation<std::is_same<void, CompatibleObjectType>>,
251  has_mapped_type<CompatibleObjectType>,
252  has_key_type<CompatibleObjectType>>::value,
253  typename BasicJsonType::object_t, CompatibleObjectType >::value;
254 };
255 
256 template<typename BasicJsonType, typename T>
258 {
259  static auto constexpr value = std::is_same<T, typename BasicJsonType::iterator>::value or
260  std::is_same<T, typename BasicJsonType::const_iterator>::value or
261  std::is_same<T, typename BasicJsonType::reverse_iterator>::value or
262  std::is_same<T, typename BasicJsonType::const_reverse_iterator>::value;
263 };
264 
265 template<class BasicJsonType, class CompatibleArrayType>
267 {
268  static auto constexpr value =
269  std::conjunction<std::negation<std::is_same<void, CompatibleArrayType>>,
270  std::negation<is_compatible_object_type<
271  BasicJsonType, CompatibleArrayType>>,
272  std::negation<std::is_constructible<StringRef,
273  CompatibleArrayType>>,
274  std::negation<is_json_nested_type<BasicJsonType, CompatibleArrayType>>,
275  has_value_type<CompatibleArrayType>,
276  has_iterator<CompatibleArrayType>>::value;
277 };
278 
279 template<bool, typename, typename>
280 struct is_compatible_integer_type_impl : std::false_type {};
281 
282 template<typename RealIntegerType, typename CompatibleNumberIntegerType>
283 struct is_compatible_integer_type_impl<true, RealIntegerType, CompatibleNumberIntegerType>
284 {
285  // is there an assert somewhere on overflows?
286  using RealLimits = std::numeric_limits<RealIntegerType>;
287  using CompatibleLimits = std::numeric_limits<CompatibleNumberIntegerType>;
288 
289  static constexpr auto value =
290  std::is_constructible<RealIntegerType, CompatibleNumberIntegerType>::value and
291  CompatibleLimits::is_integer and
292  RealLimits::is_signed == CompatibleLimits::is_signed;
293 };
294 
295 template<typename RealIntegerType, typename CompatibleNumberIntegerType>
297 {
298  static constexpr auto value =
300  std::is_integral<CompatibleNumberIntegerType>::value and
301  not std::is_same<bool, CompatibleNumberIntegerType>::value,
302  RealIntegerType, CompatibleNumberIntegerType > ::value;
303 };
304 
305 // trait checking if JSONSerializer<T>::from_json(json const&, udt&) exists
306 template<typename BasicJsonType, typename T>
308 {
309  private:
310  // also check the return type of from_json
311  template<typename U, typename = enable_if_t<std::is_same<void, decltype(uncvref_t<U>::from_json(
312  std::declval<BasicJsonType>(), std::declval<T&>()))>::value>>
313  static int detect(U&&);
314  static void detect(...);
315 
316  public:
317  static constexpr bool value = std::is_integral<decltype(
318  detect(std::declval<typename BasicJsonType::template json_serializer<T, void>>()))>::value;
319 };
320 
321 // This trait checks if JSONSerializer<T>::from_json(json const&) exists
322 // this overload is used for non-default-constructible user-defined-types
323 template<typename BasicJsonType, typename T>
325 {
326  private:
327  template <
328  typename U,
329  typename = enable_if_t<std::is_same<
330  T, decltype(uncvref_t<U>::from_json(std::declval<BasicJsonType>()))>::value >>
331  static int detect(U&&);
332  static void detect(...);
333 
334  public:
335  static constexpr bool value = std::is_integral<decltype(detect(
336  std::declval<typename BasicJsonType::template json_serializer<T, void>>()))>::value;
337 };
338 
339 // This trait checks if BasicJsonType::json_serializer<T>::to_json exists
340 template<typename BasicJsonType, typename T>
342 {
343  private:
344  template<typename U, typename = decltype(uncvref_t<U>::to_json(
345  std::declval<BasicJsonType&>(), std::declval<T>()))>
346  static int detect(U&&);
347  static void detect(...);
348 
349  public:
350  static constexpr bool value = std::is_integral<decltype(detect(
351  std::declval<typename BasicJsonType::template json_serializer<T, void>>()))>::value;
352 };
353 
354 template <typename BasicJsonType, typename CompatibleCompleteType>
356 {
357  static constexpr bool value =
358  not std::is_base_of<std::istream, CompatibleCompleteType>::value and
362 };
363 
364 template <typename BasicJsonType, typename CompatibleType>
366  : std::conjunction<is_complete_type<CompatibleType>,
367  is_compatible_complete_type<BasicJsonType, CompatibleType>>
368 {
369 };
370 
371 // taken from ranges-v3
372 template<typename T>
374 {
375  static constexpr T value{};
376 };
377 
378 template<typename T>
379 constexpr T static_const<T>::value;
380 
382 // exceptions //
384 
413 class exception : public std::exception
414 {
415  public:
417  const char* what() const noexcept override
418  {
419  return m.what();
420  }
421 
423  const int id;
424 
425  protected:
426  exception(int id_, const Twine& what_arg);
427 
428  private:
430  std::runtime_error m;
431 };
432 
476 class parse_error : public exception
477 {
478  public:
487  static parse_error create(int id_, std::size_t byte_, const Twine& what_arg);
488 
498  const std::size_t byte;
499 
500  private:
501  parse_error(int id_, std::size_t byte_, const Twine& what_arg)
502  : exception(id_, what_arg), byte(byte_) {}
503 };
504 
543 {
544  public:
545  static invalid_iterator create(int id_, const Twine& what_arg);
546 
547  private:
548  invalid_iterator(int id_, const Twine& what_arg)
549  : exception(id_, what_arg) {}
550 };
551 
590 class type_error : public exception
591 {
592  public:
593  static type_error create(int id_, const Twine& what_arg);
594 
595  private:
596  type_error(int id_, const Twine& what_arg) : exception(id_, what_arg) {}
597 };
598 
631 class out_of_range : public exception
632 {
633  public:
634  static out_of_range create(int id_, const Twine& what_arg);
635 
636  private:
637  out_of_range(int id_, const Twine& what_arg) : exception(id_, what_arg) {}
638 };
639 
664 class other_error : public exception
665 {
666  public:
667  static other_error create(int id_, const Twine& what_arg);
668 
669  private:
670  other_error(int id_, const Twine& what_arg) : exception(id_, what_arg) {}
671 };
672 
674 // JSON type enumeration //
676 
701 enum class value_t : std::uint8_t
702 {
703  null,
704  object,
705  array,
706  string,
707  boolean,
710  number_float,
711  discarded
712 };
713 
724 inline bool operator<(const value_t lhs, const value_t rhs) noexcept
725 {
726  static constexpr std::array<std::uint8_t, 8> order = {{
727  0 /* null */, 3 /* object */, 4 /* array */, 5 /* string */,
728  1 /* boolean */, 2 /* integer */, 2 /* unsigned */, 2 /* float */
729  }
730  };
731 
732  const auto l_index = static_cast<std::size_t>(lhs);
733  const auto r_index = static_cast<std::size_t>(rhs);
734  return l_index < order.size() and r_index < order.size() and order[l_index] < order[r_index];
735 }
736 
737 // overloads for json template parameters
738 template<typename BasicJsonType, typename ArithmeticType,
739  enable_if_t<std::is_arithmetic<ArithmeticType>::value and
740  not std::is_same<ArithmeticType, bool>::value,
741  int> = 0>
742 void get_arithmetic_value(const BasicJsonType& j, ArithmeticType& val)
743 {
744  switch (static_cast<value_t>(j))
745  {
747  {
748  val = static_cast<ArithmeticType>(*j.template get_ptr<const uint64_t*>());
749  break;
750  }
752  {
753  val = static_cast<ArithmeticType>(*j.template get_ptr<const int64_t*>());
754  break;
755  }
757  {
758  val = static_cast<ArithmeticType>(*j.template get_ptr<const double*>());
759  break;
760  }
761 
762  default:
763  JSON_THROW(type_error::create(302, "type must be number, but is " + Twine(j.type_name())));
764  }
765 }
766 
767 template<typename BasicJsonType>
768 void from_json(const BasicJsonType& j, bool& b)
769 {
770  if (JSON_UNLIKELY(not j.is_boolean()))
771  {
772  JSON_THROW(type_error::create(302, "type must be boolean, but is " + Twine(j.type_name())));
773  }
774  b = *j.template get_ptr<const bool*>();
775 }
776 
777 template<typename BasicJsonType>
778 void from_json(const BasicJsonType& j, std::string& s)
779 {
780  if (JSON_UNLIKELY(not j.is_string()))
781  {
782  JSON_THROW(type_error::create(302, "type must be string, but is " + Twine(j.type_name())));
783  }
784  s = *j.template get_ptr<const std::string*>();
785 }
786 
787 template<typename BasicJsonType>
788 void from_json(const BasicJsonType& j, double& val)
789 {
790  get_arithmetic_value(j, val);
791 }
792 
793 template<typename BasicJsonType>
794 void from_json(const BasicJsonType& j, uint64_t& val)
795 {
796  get_arithmetic_value(j, val);
797 }
798 
799 template<typename BasicJsonType>
800 void from_json(const BasicJsonType& j, int64_t& val)
801 {
802  get_arithmetic_value(j, val);
803 }
804 
805 template<typename BasicJsonType, typename EnumType,
806  enable_if_t<std::is_enum<EnumType>::value, int> = 0>
807 void from_json(const BasicJsonType& j, EnumType& e)
808 {
809  typename std::underlying_type<EnumType>::type val;
810  get_arithmetic_value(j, val);
811  e = static_cast<EnumType>(val);
812 }
813 
814 template<typename BasicJsonType>
815 void from_json(const BasicJsonType& j, typename BasicJsonType::array_t& arr)
816 {
817  if (JSON_UNLIKELY(not j.is_array()))
818  {
819  JSON_THROW(type_error::create(302, "type must be array, but is " + Twine(j.type_name())));
820  }
821  arr = *j.template get_ptr<const typename BasicJsonType::array_t*>();
822 }
823 
824 template<typename BasicJsonType, typename CompatibleArrayType>
825 void from_json_array_impl(const BasicJsonType& j, CompatibleArrayType& arr, priority_tag<0> /*unused*/)
826 {
827  using std::end;
828 
829  std::transform(j.begin(), j.end(),
830  std::inserter(arr, end(arr)), [](const BasicJsonType & i)
831  {
832  // get<BasicJsonType>() returns *this, this won't call a from_json
833  // method when value_type is BasicJsonType
834  return i.template get<typename CompatibleArrayType::value_type>();
835  });
836 }
837 
838 template<typename BasicJsonType, typename CompatibleArrayType>
839 auto from_json_array_impl(const BasicJsonType& j, CompatibleArrayType& arr, priority_tag<1> /*unused*/)
840 -> decltype(
841  arr.reserve(std::declval<typename CompatibleArrayType::size_type>()),
842  void())
843 {
844  using std::end;
845 
846  arr.reserve(j.size());
847  std::transform(j.begin(), j.end(),
848  std::inserter(arr, end(arr)), [](const BasicJsonType & i)
849  {
850  // get<BasicJsonType>() returns *this, this won't call a from_json
851  // method when value_type is BasicJsonType
852  return i.template get<typename CompatibleArrayType::value_type>();
853  });
854 }
855 
856 template<typename BasicJsonType, typename T, std::size_t N>
857 void from_json_array_impl(const BasicJsonType& j, std::array<T, N>& arr, priority_tag<2> /*unused*/)
858 {
859  for (std::size_t i = 0; i < N; ++i)
860  {
861  arr[i] = j.at(i).template get<T>();
862  }
863 }
864 
865 template <
866  typename BasicJsonType, typename CompatibleArrayType,
867  enable_if_t <
868  is_compatible_array_type<BasicJsonType, CompatibleArrayType>::value and
869  not std::is_same<typename BasicJsonType::array_t,
870  CompatibleArrayType>::value and
871  std::is_constructible <
872  BasicJsonType, typename CompatibleArrayType::value_type >::value,
873  int > = 0 >
874 void from_json(const BasicJsonType& j, CompatibleArrayType& arr)
875 {
876  if (JSON_UNLIKELY(not j.is_array()))
877  {
878  JSON_THROW(type_error::create(302, "type must be array, but is " +
879  Twine(j.type_name())));
880  }
881 
882  from_json_array_impl(j, arr, priority_tag<2> {});
883 }
884 
885 template<typename BasicJsonType>
886 inline
887 void from_json(const BasicJsonType& j, typename BasicJsonType::object_t& obj)
888 {
889  if (!j.is_object())
890  {
891  JSON_THROW(type_error::create(302, "type must be object, but is " + Twine(j.type_name())));
892  }
893 
894  auto inner_object = j.template get_ptr<const typename BasicJsonType::object_t*>();
895  for (const auto& i : *inner_object) {
896  obj.try_emplace(i.first(), i.second);
897  }
898 }
899 
900 template<typename BasicJsonType, typename CompatibleObjectType,
901  enable_if_t<is_compatible_object_type<BasicJsonType, CompatibleObjectType>::value and
902  not std::is_same<typename BasicJsonType::object_t, CompatibleObjectType>::value, int> = 0>
903 void from_json(const BasicJsonType& j, CompatibleObjectType& obj)
904 {
905  if (JSON_UNLIKELY(not j.is_object()))
906  {
907  JSON_THROW(type_error::create(302, "type must be object, but is " + Twine(j.type_name())));
908  }
909 
910  auto inner_object = j.template get_ptr<const typename BasicJsonType::object_t*>();
911  using std::begin;
912  using std::end;
913  using value_type = typename CompatibleObjectType::value_type;
914  std::vector<value_type> v;
915  v.reserve(j.size());
916  for (const auto& p : *inner_object)
917  {
918  v.emplace_back(
919  p.first(),
920  p.second
921  .template get<typename CompatibleObjectType::mapped_type>());
922  }
923  // we could avoid the assignment, but this might require a for loop, which
924  // might be less efficient than the container constructor for some
925  // containers (would it?)
926  obj = CompatibleObjectType(std::make_move_iterator(begin(v)),
927  std::make_move_iterator(end(v)));
928 }
929 
930 // overload for arithmetic types, not chosen for json template arguments
931 // (BooleanType, etc..); note: Is it really necessary to provide explicit
932 // overloads for bool etc. in case of a custom BooleanType which is not
933 // an arithmetic type?
934 template<typename BasicJsonType, typename ArithmeticType,
935  enable_if_t <
936  std::is_arithmetic<ArithmeticType>::value and
937  not std::is_same<ArithmeticType, uint64_t>::value and
938  not std::is_same<ArithmeticType, int64_t>::value and
939  not std::is_same<ArithmeticType, double>::value and
940  not std::is_same<ArithmeticType, bool>::value,
941  int> = 0>
942 void from_json(const BasicJsonType& j, ArithmeticType& val)
943 {
944  switch (static_cast<value_t>(j))
945  {
947  {
948  val = static_cast<ArithmeticType>(*j.template get_ptr<const uint64_t*>());
949  break;
950  }
952  {
953  val = static_cast<ArithmeticType>(*j.template get_ptr<const int64_t*>());
954  break;
955  }
957  {
958  val = static_cast<ArithmeticType>(*j.template get_ptr<const double*>());
959  break;
960  }
961  case value_t::boolean:
962  {
963  val = static_cast<ArithmeticType>(*j.template get_ptr<const bool*>());
964  break;
965  }
966 
967  default:
968  JSON_THROW(type_error::create(302, "type must be number, but is " + Twine(j.type_name())));
969  }
970 }
971 
972 template<typename BasicJsonType, typename A1, typename A2>
973 void from_json(const BasicJsonType& j, std::pair<A1, A2>& p)
974 {
975  p = {j.at(0).template get<A1>(), j.at(1).template get<A2>()};
976 }
977 
978 template<typename BasicJsonType, typename Tuple, std::size_t... Idx>
979 void from_json_tuple_impl(const BasicJsonType& j, Tuple& t, std::index_sequence<Idx...>)
980 {
981  t = std::make_tuple(j.at(Idx).template get<typename std::tuple_element<Idx, Tuple>::type>()...);
982 }
983 
984 template<typename BasicJsonType, typename... Args>
985 void from_json(const BasicJsonType& j, std::tuple<Args...>& t)
986 {
987  from_json_tuple_impl(j, t, std::index_sequence_for<Args...> {});
988 }
989 
991 {
992  private:
993  template<typename BasicJsonType, typename T>
994  auto call(const BasicJsonType& j, T& val, priority_tag<1> /*unused*/) const
995  noexcept(noexcept(from_json(j, val)))
996  -> decltype(from_json(j, val), void())
997  {
998  return from_json(j, val);
999  }
1000 
1001  template<typename BasicJsonType, typename T>
1002  void call(const BasicJsonType& /*unused*/, T& /*unused*/, priority_tag<0> /*unused*/) const noexcept
1003  {
1004  static_assert(sizeof(BasicJsonType) == 0,
1005  "could not find from_json() method in T's namespace");
1006 #ifdef _MSC_VER
1007  // MSVC does not show a stacktrace for the above assert
1008  using decayed = uncvref_t<T>;
1009  static_assert(sizeof(typename decayed::force_msvc_stacktrace) == 0,
1010  "forcing MSVC stacktrace to show which T we're talking about.");
1011 #endif
1012  }
1013 
1014  public:
1015  template<typename BasicJsonType, typename T>
1016  void operator()(const BasicJsonType& j, T& val) const
1017  noexcept(noexcept(std::declval<from_json_fn>().call(j, val, priority_tag<1> {})))
1018  {
1019  return call(j, val, priority_tag<1> {});
1020  }
1021 };
1022 }
1023 
1024 // namespace to hold default `from_json` function
1025 // to see why this is required:
1026 // http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/n4381.html
1027 namespace
1028 {
1029 constexpr const auto& from_json = detail::static_const<detail::from_json_fn>::value;
1030 }
1031 
1032 namespace detail
1033 {
1035 // constructors //
1037 
1038 template<value_t> struct external_constructor;
1039 
1040 template<>
1042 {
1043  template<typename BasicJsonType>
1044  static void construct(BasicJsonType& j, bool b) noexcept
1045  {
1046  j.m_type = value_t::boolean;
1047  j.m_value = b;
1048  j.assert_invariant();
1049  }
1050 };
1051 
1052 template<>
1054 {
1055  template<typename BasicJsonType>
1056  static void construct(BasicJsonType& j, StringRef s)
1057  {
1058  j.m_type = value_t::string;
1059  j.m_value = s;
1060  j.assert_invariant();
1061  }
1062 
1063  template<typename BasicJsonType, typename T,
1064  enable_if_t<std::is_same<std::string, T>::value, int> = 0>
1065  static void construct(BasicJsonType& j, T&& s)
1066  {
1067  j.m_type = value_t::string;
1068  j.m_value = std::move(s);
1069  j.assert_invariant();
1070  }
1071 };
1072 
1073 template<>
1075 {
1076  template<typename BasicJsonType>
1077  static void construct(BasicJsonType& j, double val) noexcept
1078  {
1079  j.m_type = value_t::number_float;
1080  j.m_value = val;
1081  j.assert_invariant();
1082  }
1083 };
1084 
1085 template<>
1087 {
1088  template<typename BasicJsonType>
1089  static void construct(BasicJsonType& j, uint64_t val) noexcept
1090  {
1091  j.m_type = value_t::number_unsigned;
1092  j.m_value = val;
1093  j.assert_invariant();
1094  }
1095 };
1096 
1097 template<>
1099 {
1100  template<typename BasicJsonType>
1101  static void construct(BasicJsonType& j, int64_t val) noexcept
1102  {
1103  j.m_type = value_t::number_integer;
1104  j.m_value = val;
1105  j.assert_invariant();
1106  }
1107 };
1108 
1109 template<>
1111 {
1112  template<typename BasicJsonType>
1113  static void construct(BasicJsonType& j, const typename BasicJsonType::array_t& arr)
1114  {
1115  j.m_type = value_t::array;
1116  j.m_value = arr;
1117  j.assert_invariant();
1118  }
1119 
1120  template<typename BasicJsonType>
1121  static void construct(BasicJsonType& j, typename BasicJsonType::array_t&& arr)
1122  {
1123  j.m_type = value_t::array;
1124  j.m_value = std::move(arr);
1125  j.assert_invariant();
1126  }
1127 
1128  template<typename BasicJsonType, typename T>
1129  static void construct(BasicJsonType& j, ArrayRef<T> arr)
1130  {
1131  using std::begin;
1132  using std::end;
1133  j.m_type = value_t::array;
1134  j.m_value.array = j.template create<typename BasicJsonType::array_t>(begin(arr), end(arr));
1135  j.assert_invariant();
1136  }
1137 
1138  template<typename BasicJsonType, typename CompatibleArrayType,
1139  enable_if_t<not std::is_same<CompatibleArrayType, typename BasicJsonType::array_t>::value,
1140  int> = 0>
1141  static void construct(BasicJsonType& j, const CompatibleArrayType& arr)
1142  {
1143  using std::begin;
1144  using std::end;
1145  j.m_type = value_t::array;
1146  j.m_value.array = j.template create<typename BasicJsonType::array_t>(begin(arr), end(arr));
1147  j.assert_invariant();
1148  }
1149 
1150  template<typename BasicJsonType>
1151  static void construct(BasicJsonType& j, const std::vector<bool>& arr)
1152  {
1153  j.m_type = value_t::array;
1154  j.m_value = value_t::array;
1155  j.m_value.array->reserve(arr.size());
1156  for (const bool x : arr)
1157  {
1158  j.m_value.array->push_back(x);
1159  }
1160  j.assert_invariant();
1161  }
1162 };
1163 
1164 template<>
1166 {
1167  template<typename BasicJsonType>
1168  static void construct(BasicJsonType& j, const typename BasicJsonType::object_t& obj)
1169  {
1170  j.m_type = value_t::object;
1171  j.m_value = obj;
1172  j.assert_invariant();
1173  }
1174 
1175  template<typename BasicJsonType>
1176  static void construct(BasicJsonType& j, typename BasicJsonType::object_t&& obj)
1177  {
1178  j.m_type = value_t::object;
1179  j.m_value = std::move(obj);
1180  j.assert_invariant();
1181  }
1182 
1183  template<typename BasicJsonType, typename CompatibleObjectType,
1184  enable_if_t<not std::is_same<CompatibleObjectType, typename BasicJsonType::object_t>::value, int> = 0>
1185  static void construct(BasicJsonType& j, const CompatibleObjectType& obj)
1186  {
1187  j.m_type = value_t::object;
1188  j.m_value = value_t::object;
1189  for (const auto& x : obj)
1190  {
1191  j.m_value.object->try_emplace(x.first, x.second);
1192  }
1193  j.assert_invariant();
1194  }
1195 };
1196 
1198 // to_json //
1200 
1201 template<typename BasicJsonType, typename T,
1202  enable_if_t<std::is_same<T, bool>::value, int> = 0>
1203 void to_json(BasicJsonType& j, T b) noexcept
1204 {
1206 }
1207 
1208 template<typename BasicJsonType, typename CompatibleString,
1209  enable_if_t<std::is_constructible<StringRef, CompatibleString>::value, int> = 0>
1210 void to_json(BasicJsonType& j, const CompatibleString& s)
1211 {
1212  external_constructor<value_t::string>::construct(j, s);
1213 }
1214 
1215 template<typename BasicJsonType, typename T,
1216  enable_if_t<std::is_same<std::string, T>::value, int> = 0>
1217 void to_json(BasicJsonType& j, T&& s)
1218 {
1219  external_constructor<value_t::string>::construct(j, std::move(s));
1220 }
1221 
1222 template<typename BasicJsonType, typename FloatType,
1223  enable_if_t<std::is_floating_point<FloatType>::value, int> = 0>
1224 void to_json(BasicJsonType& j, FloatType val) noexcept
1225 {
1226  external_constructor<value_t::number_float>::construct(j, static_cast<double>(val));
1227 }
1228 
1229 template<typename BasicJsonType, typename CompatibleNumberUnsignedType,
1230  enable_if_t<is_compatible_integer_type<uint64_t, CompatibleNumberUnsignedType>::value, int> = 0>
1231 void to_json(BasicJsonType& j, CompatibleNumberUnsignedType val) noexcept
1232 {
1233  external_constructor<value_t::number_unsigned>::construct(j, static_cast<uint64_t>(val));
1234 }
1235 
1236 template<typename BasicJsonType, typename CompatibleNumberIntegerType,
1237  enable_if_t<is_compatible_integer_type<int64_t, CompatibleNumberIntegerType>::value, int> = 0>
1238 void to_json(BasicJsonType& j, CompatibleNumberIntegerType val) noexcept
1239 {
1240  external_constructor<value_t::number_integer>::construct(j, static_cast<int64_t>(val));
1241 }
1242 
1243 template<typename BasicJsonType, typename EnumType,
1244  enable_if_t<std::is_enum<EnumType>::value, int> = 0>
1245 void to_json(BasicJsonType& j, EnumType e) noexcept
1246 {
1247  using underlying_type = typename std::underlying_type<EnumType>::type;
1248  external_constructor<value_t::number_integer>::construct(j, static_cast<underlying_type>(e));
1249 }
1250 
1251 template<typename BasicJsonType>
1252 void to_json(BasicJsonType& j, const std::vector<bool>& e)
1253 {
1254  external_constructor<value_t::array>::construct(j, e);
1255 }
1256 
1257 template<typename BasicJsonType, typename CompatibleArrayType,
1258  enable_if_t<is_compatible_array_type<BasicJsonType, CompatibleArrayType>::value or
1259  std::is_same<typename BasicJsonType::array_t, CompatibleArrayType>::value,
1260  int> = 0>
1261 void to_json(BasicJsonType& j, const CompatibleArrayType& arr)
1262 {
1263  external_constructor<value_t::array>::construct(j, arr);
1264 }
1265 
1266 template<typename BasicJsonType>
1267 void to_json(BasicJsonType& j, typename BasicJsonType::array_t&& arr)
1268 {
1269  external_constructor<value_t::array>::construct(j, std::move(arr));
1270 }
1271 
1272 template<typename BasicJsonType, typename CompatibleObjectType,
1273  enable_if_t<is_compatible_object_type<BasicJsonType, CompatibleObjectType>::value, int> = 0>
1274 void to_json(BasicJsonType& j, const CompatibleObjectType& obj)
1275 {
1276  external_constructor<value_t::object>::construct(j, obj);
1277 }
1278 
1279 template<typename BasicJsonType>
1280 void to_json(BasicJsonType& j, typename BasicJsonType::object_t&& obj)
1281 {
1282  external_constructor<value_t::object>::construct(j, std::move(obj));
1283 }
1284 
1285 template<typename BasicJsonType, typename T, std::size_t N,
1286  enable_if_t<not std::is_constructible<StringRef, T (&)[N]>::value, int> = 0>
1287 void to_json(BasicJsonType& j, T (&arr)[N])
1288 {
1289  external_constructor<value_t::array>::construct(j, arr);
1290 }
1291 
1292 template<typename BasicJsonType, typename... Args>
1293 void to_json(BasicJsonType& j, const std::pair<Args...>& p)
1294 {
1295  j = {p.first, p.second};
1296 }
1297 
1298 template<typename BasicJsonType, typename Tuple, std::size_t... Idx>
1299 void to_json_tuple_impl(BasicJsonType& j, const Tuple& t, std::index_sequence<Idx...>)
1300 {
1301  j = {std::get<Idx>(t)...};
1302 }
1303 
1304 template<typename BasicJsonType, typename... Args>
1305 void to_json(BasicJsonType& j, const std::tuple<Args...>& t)
1306 {
1307  to_json_tuple_impl(j, t, std::index_sequence_for<Args...> {});
1308 }
1309 
1311 {
1312  private:
1313  template<typename BasicJsonType, typename T>
1314  auto call(BasicJsonType& j, T&& val, priority_tag<1> /*unused*/) const noexcept(noexcept(to_json(j, std::forward<T>(val))))
1315  -> decltype(to_json(j, std::forward<T>(val)), void())
1316  {
1317  return to_json(j, std::forward<T>(val));
1318  }
1319 
1320  template<typename BasicJsonType, typename T>
1321  void call(BasicJsonType& /*unused*/, T&& /*unused*/, priority_tag<0> /*unused*/) const noexcept
1322  {
1323  static_assert(sizeof(BasicJsonType) == 0,
1324  "could not find to_json() method in T's namespace");
1325 
1326 #ifdef _MSC_VER
1327  // MSVC does not show a stacktrace for the above assert
1328  using decayed = uncvref_t<T>;
1329  static_assert(sizeof(typename decayed::force_msvc_stacktrace) == 0,
1330  "forcing MSVC stacktrace to show which T we're talking about.");
1331 #endif
1332  }
1333 
1334  public:
1335  template<typename BasicJsonType, typename T>
1336  void operator()(BasicJsonType& j, T&& val) const
1337  noexcept(noexcept(std::declval<to_json_fn>().call(j, std::forward<T>(val), priority_tag<1> {})))
1338  {
1339  return call(j, std::forward<T>(val), priority_tag<1> {});
1340  }
1341 };
1342 }
1343 
1344 // namespace to hold default `to_json` function
1345 namespace
1346 {
1347 constexpr const auto& to_json = detail::static_const<detail::to_json_fn>::value;
1348 }
1349 
1350 namespace detail
1351 {
1352 /*
1353 @brief an iterator for primitive JSON types
1354 
1355 This class models an iterator for primitive JSON types (boolean, number,
1356 string). It's only purpose is to allow the iterator/const_iterator classes
1357 to "iterate" over primitive values. Internally, the iterator is modeled by
1358 a `difference_type` variable. Value begin_value (`0`) models the begin,
1359 end_value (`1`) models past the end.
1360 */
1362 {
1363  private:
1364  using difference_type = std::ptrdiff_t;
1365  static constexpr difference_type begin_value = 0;
1366  static constexpr difference_type end_value = begin_value + 1;
1367 
1369  difference_type m_it = (std::numeric_limits<std::ptrdiff_t>::min)();
1370 
1371  public:
1372  constexpr difference_type get_value() const noexcept
1373  {
1374  return m_it;
1375  }
1376 
1378  void set_begin() noexcept
1379  {
1380  m_it = begin_value;
1381  }
1382 
1384  void set_end() noexcept
1385  {
1386  m_it = end_value;
1387  }
1388 
1390  constexpr bool is_begin() const noexcept
1391  {
1392  return m_it == begin_value;
1393  }
1394 
1396  constexpr bool is_end() const noexcept
1397  {
1398  return m_it == end_value;
1399  }
1400 
1401  friend constexpr bool operator==(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept
1402  {
1403  return lhs.m_it == rhs.m_it;
1404  }
1405 
1406  friend constexpr bool operator<(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept
1407  {
1408  return lhs.m_it < rhs.m_it;
1409  }
1410 
1411  primitive_iterator_t operator+(difference_type n) noexcept
1412  {
1413  auto result = *this;
1414  result += n;
1415  return result;
1416  }
1417 
1418  friend constexpr difference_type operator-(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept
1419  {
1420  return lhs.m_it - rhs.m_it;
1421  }
1422 
1423  primitive_iterator_t& operator++() noexcept
1424  {
1425  ++m_it;
1426  return *this;
1427  }
1428 
1429  primitive_iterator_t const operator++(int) noexcept
1430  {
1431  auto result = *this;
1432  m_it++;
1433  return result;
1434  }
1435 
1436  primitive_iterator_t& operator--() noexcept
1437  {
1438  --m_it;
1439  return *this;
1440  }
1441 
1442  primitive_iterator_t const operator--(int) noexcept
1443  {
1444  auto result = *this;
1445  m_it--;
1446  return result;
1447  }
1448 
1449  primitive_iterator_t& operator+=(difference_type n) noexcept
1450  {
1451  m_it += n;
1452  return *this;
1453  }
1454 
1455  primitive_iterator_t& operator-=(difference_type n) noexcept
1456  {
1457  m_it -= n;
1458  return *this;
1459  }
1460 };
1461 
1468 template<typename BasicJsonType> struct internal_iterator
1469 {
1471  typename BasicJsonType::object_t::iterator object_iterator {};
1473  typename BasicJsonType::array_t::iterator array_iterator {};
1476 };
1477 
1478 // forward declare, to be able to friend it later on
1479 template<typename IteratorType> class iteration_proxy;
1480 
1501 template<typename BasicJsonType>
1503 {
1505  friend iter_impl<typename std::conditional<std::is_const<BasicJsonType>::value, typename std::remove_const<BasicJsonType>::type, const BasicJsonType>::type>;
1506  friend BasicJsonType;
1508  friend class ::wpi::JsonTest;
1509 
1510  using object_t = typename BasicJsonType::object_t;
1511  using array_t = typename BasicJsonType::array_t;
1512  // make sure BasicJsonType is json or const json
1513  static_assert(is_json<typename std::remove_const<BasicJsonType>::type>::value,
1514  "iter_impl only accepts (const) json");
1515 
1516  public:
1517 
1523  using iterator_category = std::bidirectional_iterator_tag;
1524 
1526  using value_type = typename BasicJsonType::value_type;
1528  using difference_type = typename BasicJsonType::difference_type;
1530  using pointer = typename std::conditional<std::is_const<BasicJsonType>::value,
1531  typename BasicJsonType::const_pointer,
1532  typename BasicJsonType::pointer>::type;
1534  using reference =
1535  typename std::conditional<std::is_const<BasicJsonType>::value,
1536  typename BasicJsonType::const_reference,
1537  typename BasicJsonType::reference>::type;
1538 
1540  iter_impl() = default;
1541 
1548  explicit iter_impl(pointer object) noexcept : m_object(object)
1549  {
1550  assert(m_object != nullptr);
1551 
1552  switch (m_object->m_type)
1553  {
1554  case value_t::object:
1555  {
1556  m_it.object_iterator = typename object_t::iterator();
1557  break;
1558  }
1559 
1560  case value_t::array:
1561  {
1562  m_it.array_iterator = typename array_t::iterator();
1563  break;
1564  }
1565 
1566  default:
1567  {
1569  break;
1570  }
1571  }
1572  }
1573 
1588  iter_impl(const iter_impl<typename std::remove_const<BasicJsonType>::type>& other) noexcept
1589  : m_object(other.m_object), m_it(other.m_it) {}
1590 
1597  iter_impl& operator=(const iter_impl<typename std::remove_const<BasicJsonType>::type>& other) noexcept
1598  {
1599  m_object = other.m_object;
1600  m_it = other.m_it;
1601  return *this;
1602  }
1603 
1604  private:
1609  void set_begin() noexcept
1610  {
1611  assert(m_object != nullptr);
1612 
1613  switch (m_object->m_type)
1614  {
1615  case value_t::object:
1616  {
1617  m_it.object_iterator = m_object->m_value.object->begin();
1618  break;
1619  }
1620 
1621  case value_t::array:
1622  {
1623  m_it.array_iterator = m_object->m_value.array->begin();
1624  break;
1625  }
1626 
1627  case value_t::null:
1628  {
1629  // set to end so begin()==end() is true: null is empty
1630  m_it.primitive_iterator.set_end();
1631  break;
1632  }
1633 
1634  default:
1635  {
1637  break;
1638  }
1639  }
1640  }
1641 
1646  void set_end() noexcept
1647  {
1648  assert(m_object != nullptr);
1649 
1650  switch (m_object->m_type)
1651  {
1652  case value_t::object:
1653  {
1654  m_it.object_iterator = m_object->m_value.object->end();
1655  break;
1656  }
1657 
1658  case value_t::array:
1659  {
1660  m_it.array_iterator = m_object->m_value.array->end();
1661  break;
1662  }
1663 
1664  default:
1665  {
1666  m_it.primitive_iterator.set_end();
1667  break;
1668  }
1669  }
1670  }
1671 
1672  public:
1678  {
1679  assert(m_object != nullptr);
1680 
1681  switch (m_object->m_type)
1682  {
1683  case value_t::object:
1684  {
1685  assert(m_it.object_iterator != m_object->m_value.object->end());
1686  return m_it.object_iterator->second;
1687  }
1688 
1689  case value_t::array:
1690  {
1691  assert(m_it.array_iterator != m_object->m_value.array->end());
1692  return *m_it.array_iterator;
1693  }
1694 
1695  case value_t::null:
1696  JSON_THROW(invalid_iterator::create(214, "cannot get value"));
1697 
1698  default:
1699  {
1700  if (JSON_LIKELY(m_it.primitive_iterator.is_begin()))
1701  {
1702  return *m_object;
1703  }
1704 
1705  JSON_THROW(invalid_iterator::create(214, "cannot get value"));
1706  }
1707  }
1708  }
1709 
1715  {
1716  assert(m_object != nullptr);
1717 
1718  switch (m_object->m_type)
1719  {
1720  case value_t::object:
1721  {
1722  assert(m_it.object_iterator != m_object->m_value.object->end());
1723  return &(m_it.object_iterator->second);
1724  }
1725 
1726  case value_t::array:
1727  {
1728  assert(m_it.array_iterator != m_object->m_value.array->end());
1729  return &*m_it.array_iterator;
1730  }
1731 
1732  default:
1733  {
1734  if (JSON_LIKELY(m_it.primitive_iterator.is_begin()))
1735  {
1736  return m_object;
1737  }
1738 
1739  JSON_THROW(invalid_iterator::create(214, "cannot get value"));
1740  }
1741  }
1742  }
1743 
1749  {
1750  auto result = *this;
1751  ++(*this);
1752  return result;
1753  }
1754 
1760  {
1761  assert(m_object != nullptr);
1762 
1763  switch (m_object->m_type)
1764  {
1765  case value_t::object:
1766  {
1767  ++m_it.object_iterator;
1768  break;
1769  }
1770 
1771  case value_t::array:
1772  {
1773  std::advance(m_it.array_iterator, 1);
1774  break;
1775  }
1776 
1777  default:
1778  {
1779  ++m_it.primitive_iterator;
1780  break;
1781  }
1782  }
1783 
1784  return *this;
1785  }
1786 
1792  {
1793  auto result = *this;
1794  --(*this);
1795  return result;
1796  }
1797 
1803  {
1804  assert(m_object != nullptr);
1805 
1806  switch (m_object->m_type)
1807  {
1808  case value_t::object:
1809  {
1810  --m_it.object_iterator;
1811  break;
1812  }
1813 
1814  case value_t::array:
1815  {
1816  std::advance(m_it.array_iterator, -1);
1817  break;
1818  }
1819 
1820  default:
1821  {
1822  --m_it.primitive_iterator;
1823  break;
1824  }
1825  }
1826 
1827  return *this;
1828  }
1829 
1834  bool operator==(const iter_impl& other) const
1835  {
1836  // if objects are not the same, the comparison is undefined
1837  if (JSON_UNLIKELY(m_object != other.m_object))
1838  {
1839  JSON_THROW(invalid_iterator::create(212, "cannot compare iterators of different containers"));
1840  }
1841 
1842  assert(m_object != nullptr);
1843 
1844  switch (m_object->m_type)
1845  {
1846  case value_t::object:
1847  return (m_it.object_iterator == other.m_it.object_iterator);
1848 
1849  case value_t::array:
1850  return (m_it.array_iterator == other.m_it.array_iterator);
1851 
1852  default:
1853  return (m_it.primitive_iterator == other.m_it.primitive_iterator);
1854  }
1855  }
1856 
1861  bool operator!=(const iter_impl& other) const
1862  {
1863  return not operator==(other);
1864  }
1865 
1870  bool operator<(const iter_impl& other) const
1871  {
1872  // if objects are not the same, the comparison is undefined
1873  if (JSON_UNLIKELY(m_object != other.m_object))
1874  {
1875  JSON_THROW(invalid_iterator::create(212, "cannot compare iterators of different containers"));
1876  }
1877 
1878  assert(m_object != nullptr);
1879 
1880  switch (m_object->m_type)
1881  {
1882  case value_t::object:
1883  JSON_THROW(invalid_iterator::create(213, "cannot compare order of object iterators"));
1884 
1885  case value_t::array:
1886  return (m_it.array_iterator < other.m_it.array_iterator);
1887 
1888  default:
1889  return (m_it.primitive_iterator < other.m_it.primitive_iterator);
1890  }
1891  }
1892 
1897  bool operator<=(const iter_impl& other) const
1898  {
1899  return not other.operator < (*this);
1900  }
1901 
1906  bool operator>(const iter_impl& other) const
1907  {
1908  return not operator<=(other);
1909  }
1910 
1915  bool operator>=(const iter_impl& other) const
1916  {
1917  return not operator<(other);
1918  }
1919 
1925  {
1926  assert(m_object != nullptr);
1927 
1928  switch (m_object->m_type)
1929  {
1930  case value_t::object:
1931  JSON_THROW(invalid_iterator::create(209, "cannot use offsets with object iterators"));
1932 
1933  case value_t::array:
1934  {
1935  std::advance(m_it.array_iterator, i);
1936  break;
1937  }
1938 
1939  default:
1940  {
1941  m_it.primitive_iterator += i;
1942  break;
1943  }
1944  }
1945 
1946  return *this;
1947  }
1948 
1954  {
1955  return operator+=(-i);
1956  }
1957 
1963  {
1964  auto result = *this;
1965  result += i;
1966  return result;
1967  }
1968 
1974  {
1975  auto result = it;
1976  result += i;
1977  return result;
1978  }
1979 
1985  {
1986  auto result = *this;
1987  result -= i;
1988  return result;
1989  }
1990 
1996  {
1997  assert(m_object != nullptr);
1998 
1999  switch (m_object->m_type)
2000  {
2001  case value_t::object:
2002  JSON_THROW(invalid_iterator::create(209, "cannot use offsets with object iterators"));
2003 
2004  case value_t::array:
2005  return m_it.array_iterator - other.m_it.array_iterator;
2006 
2007  default:
2008  return m_it.primitive_iterator - other.m_it.primitive_iterator;
2009  }
2010  }
2011 
2017  {
2018  assert(m_object != nullptr);
2019 
2020  switch (m_object->m_type)
2021  {
2022  case value_t::object:
2023  JSON_THROW(invalid_iterator::create(208, "cannot use operator[] for object iterators"));
2024 
2025  case value_t::array:
2026  return *std::next(m_it.array_iterator, n);
2027 
2028  case value_t::null:
2029  JSON_THROW(invalid_iterator::create(214, "cannot get value"));
2030 
2031  default:
2032  {
2033  if (JSON_LIKELY(m_it.primitive_iterator.get_value() == -n))
2034  {
2035  return *m_object;
2036  }
2037 
2038  JSON_THROW(invalid_iterator::create(214, "cannot get value"));
2039  }
2040  }
2041  }
2042 
2047  StringRef key() const
2048  {
2049  assert(m_object != nullptr);
2050 
2051  if (JSON_LIKELY(m_object->is_object()))
2052  {
2053  return m_it.object_iterator->first();
2054  }
2055 
2056  JSON_THROW(invalid_iterator::create(207, "cannot use key() for non-object iterators"));
2057  }
2058 
2064  {
2065  return operator*();
2066  }
2067 
2068  private:
2070  pointer m_object = nullptr;
2073 };
2074 
2076 template<typename IteratorType> class iteration_proxy
2077 {
2078  private:
2080  class iteration_proxy_internal
2081  {
2082  private:
2084  IteratorType anchor;
2086  std::size_t array_index = 0;
2087 
2088  public:
2089  explicit iteration_proxy_internal(IteratorType it) noexcept : anchor(it) {}
2090 
2092  iteration_proxy_internal& operator*()
2093  {
2094  return *this;
2095  }
2096 
2098  iteration_proxy_internal& operator++()
2099  {
2100  ++anchor;
2101  ++array_index;
2102 
2103  return *this;
2104  }
2105 
2107  bool operator!=(const iteration_proxy_internal& o) const noexcept
2108  {
2109  return anchor != o.anchor;
2110  }
2111 
2113  std::string key() const
2114  {
2115  assert(anchor.m_object != nullptr);
2116 
2117  switch (anchor.m_object->type())
2118  {
2119  // use integer array index as key
2120  case value_t::array:
2121  return std::to_string(array_index);
2122 
2123  // use key from the object
2124  case value_t::object:
2125  return anchor.key();
2126 
2127  // use an empty key for all primitive types
2128  default:
2129  return "";
2130  }
2131  }
2132 
2134  typename IteratorType::reference value() const
2135  {
2136  return anchor.value();
2137  }
2138  };
2139 
2141  typename IteratorType::reference container;
2142 
2143  public:
2145  explicit iteration_proxy(typename IteratorType::reference cont) noexcept
2146  : container(cont) {}
2147 
2149  iteration_proxy_internal begin() noexcept
2150  {
2151  return iteration_proxy_internal(container.begin());
2152  }
2153 
2155  iteration_proxy_internal end() noexcept
2156  {
2157  return iteration_proxy_internal(container.end());
2158  }
2159 };
2160 
2162 // reverse_iterator //
2164 
2183 template<typename Base>
2184 class json_reverse_iterator : public std::reverse_iterator<Base>
2185 {
2186  public:
2187  using difference_type = std::ptrdiff_t;
2189  using base_iterator = std::reverse_iterator<Base>;
2191  using reference = typename Base::reference;
2192 
2194  json_reverse_iterator(const typename base_iterator::iterator_type& it) noexcept
2195  : base_iterator(it) {}
2196 
2199 
2202  {
2203  return static_cast<json_reverse_iterator>(base_iterator::operator++(1));
2204  }
2205 
2208  {
2209  return static_cast<json_reverse_iterator&>(base_iterator::operator++());
2210  }
2211 
2214  {
2215  return static_cast<json_reverse_iterator>(base_iterator::operator--(1));
2216  }
2217 
2220  {
2221  return static_cast<json_reverse_iterator&>(base_iterator::operator--());
2222  }
2223 
2225  json_reverse_iterator& operator+=(difference_type i)
2226  {
2227  return static_cast<json_reverse_iterator&>(base_iterator::operator+=(i));
2228  }
2229 
2231  json_reverse_iterator operator+(difference_type i) const
2232  {
2233  return static_cast<json_reverse_iterator>(base_iterator::operator+(i));
2234  }
2235 
2237  json_reverse_iterator operator-(difference_type i) const
2238  {
2239  return static_cast<json_reverse_iterator>(base_iterator::operator-(i));
2240  }
2241 
2243  difference_type operator-(const json_reverse_iterator& other) const
2244  {
2245  return base_iterator(*this) - base_iterator(other);
2246  }
2247 
2249  reference operator[](difference_type n) const
2250  {
2251  return *(this->operator+(n));
2252  }
2253 
2255  auto key() const -> decltype(std::declval<Base>().key())
2256  {
2257  auto it = --this->base();
2258  return it.key();
2259  }
2260 
2263  {
2264  auto it = --this->base();
2265  return it.operator * ();
2266  }
2267 };
2268 
2269 template<typename BasicJsonType>
2271 {
2272  public:
2273  using value_type = BasicJsonType;
2274 
2275  json_ref(value_type&& value)
2276  : owned_value(std::move(value)), value_ref(&owned_value), is_rvalue(true)
2277  {}
2278 
2279  json_ref(const value_type& value)
2280  : value_ref(const_cast<value_type*>(&value)), is_rvalue(false)
2281  {}
2282 
2283  json_ref(std::initializer_list<json_ref> init)
2284  : owned_value(init), value_ref(&owned_value), is_rvalue(true)
2285  {}
2286 
2287  template<class... Args>
2288  json_ref(Args&& ... args)
2289  : owned_value(std::forward<Args>(args)...), value_ref(&owned_value), is_rvalue(true)
2290  {}
2291 
2292  // class should be movable only
2293  json_ref(json_ref&&) = default;
2294  json_ref(const json_ref&) = delete;
2295  json_ref& operator=(const json_ref&) = delete;
2296 
2297  value_type moved_or_copied() const
2298  {
2299  if (is_rvalue)
2300  {
2301  return std::move(*value_ref);
2302  }
2303  return *value_ref;
2304  }
2305 
2306  value_type const& operator*() const
2307  {
2308  return *static_cast<value_type const*>(value_ref);
2309  }
2310 
2311  value_type const* operator->() const
2312  {
2313  return static_cast<value_type const*>(value_ref);
2314  }
2315 
2316  private:
2317  mutable value_type owned_value = nullptr;
2318  value_type* value_ref = nullptr;
2319  const bool is_rvalue;
2320 };
2321 } // namespace detail
2322 
2324 {
2325  // allow json to access private members
2326  friend class json;
2327  friend class JsonTest;
2328 
2329  public:
2351  explicit json_pointer(const Twine& s = {})
2352  : reference_tokens(split(s))
2353  {}
2354 
2370  std::string to_string() const noexcept;
2371 
2373  operator std::string() const
2374  {
2375  return to_string();
2376  }
2377 
2385  static int array_index(const Twine& s);
2386 
2387  private:
2392  std::string pop_back()
2393  {
2394  if (JSON_UNLIKELY(is_root()))
2395  {
2396  JSON_THROW(detail::out_of_range::create(405, "JSON pointer has no parent"));
2397  }
2398 
2399  auto last = reference_tokens.back();
2400  reference_tokens.pop_back();
2401  return last;
2402  }
2403 
2405  bool is_root() const
2406  {
2407  return reference_tokens.empty();
2408  }
2409 
2410  json_pointer top() const
2411  {
2412  if (JSON_UNLIKELY(is_root()))
2413  {
2414  JSON_THROW(detail::out_of_range::create(405, "JSON pointer has no parent"));
2415  }
2416 
2417  json_pointer result = *this;
2418  result.reference_tokens = {reference_tokens[0]};
2419  return result;
2420  }
2421 
2430  json& get_and_create(json& j) const;
2431 
2451  json& get_unchecked(json* ptr) const;
2452 
2459  json& get_checked(json* ptr) const;
2460 
2474  const json& get_unchecked(const json* ptr) const;
2475 
2482  const json& get_checked(const json* ptr) const;
2483 
2493  static std::vector<std::string> split(const Twine& reference_string);
2494 
2508  static void replace_substring(std::string& s, const std::string& f,
2509  const std::string& t);
2510 
2512  static std::string escape(std::string s);
2513 
2515  static void unescape(std::string& s);
2516 
2524  static void flatten(const Twine& reference_string,
2525  const json& value,
2526  json& result);
2527 
2538  static json
2539  unflatten(const json& value);
2540 
2541  friend bool operator==(json_pointer const& lhs,
2542  json_pointer const& rhs) noexcept
2543  {
2544  return (lhs.reference_tokens == rhs.reference_tokens);
2545  }
2546 
2547  friend bool operator!=(json_pointer const& lhs,
2548  json_pointer const& rhs) noexcept
2549  {
2550  return not (lhs == rhs);
2551  }
2552 
2554  std::vector<std::string> reference_tokens;
2555 };
2556 
2557 template<typename, typename>
2558 struct adl_serializer
2559 {
2569  template<typename BasicJsonType, typename ValueType>
2570  static void from_json(BasicJsonType&& j, ValueType& val) noexcept(
2571  noexcept(::wpi::from_json(std::forward<BasicJsonType>(j), val)))
2572  {
2573  ::wpi::from_json(std::forward<BasicJsonType>(j), val);
2574  }
2575 
2585  template<typename BasicJsonType, typename ValueType>
2586  static void to_json(BasicJsonType& j, ValueType&& val) noexcept(
2587  noexcept(::wpi::to_json(j, std::forward<ValueType>(val))))
2588  {
2589  ::wpi::to_json(j, std::forward<ValueType>(val));
2590  }
2591 };
2592 
2655 class json
2656 {
2657  private:
2658  template<detail::value_t> friend struct detail::external_constructor;
2659  friend ::wpi::json_pointer;
2660  template<typename BasicJsonType>
2661  friend class ::wpi::detail::iter_impl;
2662  friend class JsonTest;
2663 
2665  using json_t = json;
2666 
2667  // convenience aliases for types residing in namespace detail;
2669  template<typename BasicJsonType>
2671  template<typename BasicJsonType>
2673  template<typename Iterator>
2675  template<typename Base> using json_reverse_iterator = ::wpi::detail::json_reverse_iterator<Base>;
2676 
2677  class binary_reader;
2678  class binary_writer;
2679  class lexer;
2680  class parser;
2681  class serializer;
2682 
2683  public:
2684  using value_t = detail::value_t;
2687  template<typename T, typename SFINAE>
2690  using initializer_list_t = std::initializer_list<detail::json_ref<json>>;
2691 
2693  // exceptions //
2695 
2699 
2712 
2714 
2715 
2717  // container types //
2719 
2724 
2726  using value_type = json;
2727 
2731  using const_reference = const value_type&;
2732 
2734  using difference_type = std::ptrdiff_t;
2736  using size_type = std::size_t;
2737 
2739  using allocator_type = std::allocator<json>;
2740 
2742  using pointer = json*;
2744  using const_pointer = const json*;
2745 
2754 
2756 
2757 
2762  {
2763  return allocator_type();
2764  }
2765 
2792  static json meta();
2793 
2794 
2796  // JSON value data types //
2798 
2803 
2804  // Use transparent comparator if possible, combined with perfect forwarding
2805  // on find() and count() calls prevents unnecessary string construction.
2806  using object_comparator_t = std::less<>;
2807 
2864 
2890  using array_t = std::vector<json>;
2891 
2893 
2894  private:
2895 
2897  template<typename T, typename... Args>
2898  static T* create(Args&& ... args)
2899  {
2900  std::allocator<T> alloc;
2901 
2902  using AllocatorTraits = std::allocator_traits<std::allocator<T>>;
2903 
2904  auto deleter = [&](T * object)
2905  {
2906  AllocatorTraits::deallocate(alloc, object, 1);
2907  };
2908  std::unique_ptr<T, decltype(deleter)> object(AllocatorTraits::allocate(alloc, 1), deleter);
2909  AllocatorTraits::construct(alloc, object.get(), std::forward<Args>(args)...);
2910  assert(object != nullptr);
2911  return object.release();
2912  }
2913 
2915  // JSON value storage //
2917 
2942  union json_value
2943  {
2945  object_t* object;
2947  array_t* array;
2949  std::string* string;
2951  bool boolean;
2953  int64_t number_integer;
2955  uint64_t number_unsigned;
2957  double number_float;
2958 
2960  json_value() = default;
2962  json_value(bool v) noexcept : boolean(v) {}
2964  json_value(int64_t v) noexcept : number_integer(v) {}
2966  json_value(uint64_t v) noexcept : number_unsigned(v) {}
2968  json_value(double v) noexcept : number_float(v) {}
2970  json_value(value_t t);
2971 
2973  json_value(StringRef value)
2974  {
2975  string = create<std::string>(value);
2976  }
2977 
2979  json_value(const std::string& value)
2980  {
2981  string = create<std::string>(value);
2982  }
2983 
2985  json_value(std::string&& value)
2986  {
2987  string = create<std::string>(std::move(value));
2988  }
2989 
2991  json_value(const object_t& value)
2992  {
2993  object = create<object_t>(value);
2994  }
2995 
2997  json_value(object_t&& value)
2998  {
2999  object = create<object_t>(std::move(value));
3000  }
3001 
3003  json_value(const array_t& value)
3004  {
3005  array = create<array_t>(value);
3006  }
3007 
3009  json_value(array_t&& value)
3010  {
3011  array = create<array_t>(std::move(value));
3012  }
3013 
3014  void destroy(value_t t) noexcept;
3015  };
3016 
3026  void assert_invariant() const noexcept
3027  {
3028  assert(m_type != value_t::object or m_value.object != nullptr);
3029  assert(m_type != value_t::array or m_value.array != nullptr);
3030  assert(m_type != value_t::string or m_value.string != nullptr);
3031  }
3032 
3033  public:
3035  // JSON parser callback //
3037 
3053  enum class parse_event_t : uint8_t
3054  {
3056  object_start,
3058  object_end,
3060  array_start,
3062  array_end,
3064  key,
3066  value
3067  };
3068 
3118  using parser_callback_t =
3119  std::function<bool(int depth, parse_event_t event, json& parsed)>;
3120 
3121 
3123  // constructors //
3125 
3130 
3160  json(const value_t v)
3161  : m_type(v), m_value(v)
3162  {
3163  assert_invariant();
3164  }
3165 
3184  json(std::nullptr_t = nullptr) noexcept
3185  : json(value_t::null)
3186  {
3187  assert_invariant();
3188  }
3189 
3247  template <typename CompatibleType,
3248  typename U = detail::uncvref_t<CompatibleType>,
3249  detail::enable_if_t<
3251  json(CompatibleType && val) noexcept(noexcept(
3252  adl_serializer<U, void>::to_json(std::declval<json_t&>(),
3253  std::forward<CompatibleType>(val))))
3254  {
3255  adl_serializer<U, void>::to_json(*this, std::forward<CompatibleType>(val));
3256  assert_invariant();
3257  }
3258 
3333  json(initializer_list_t init,
3334  bool type_deduction = true,
3335  value_t manual_type = value_t::array);
3336 
3374  static json array(initializer_list_t init = {})
3375  {
3376  return json(init, false, value_t::array);
3377  }
3378 
3417  static json object(initializer_list_t init = {})
3418  {
3419  return json(init, false, value_t::object);
3420  }
3421 
3444  json(size_type cnt, const json& val);
3445 
3501  template<class InputIT, typename std::enable_if<
3502  std::is_same<InputIT, typename json_t::iterator>::value or
3503  std::is_same<InputIT, typename json_t::const_iterator>::value, int>::type = 0>
3504  json(InputIT first, InputIT last)
3505  {
3506  assert(first.m_object != nullptr);
3507  assert(last.m_object != nullptr);
3508 
3509  // make sure iterator fits the current value
3510  if (JSON_UNLIKELY(first.m_object != last.m_object))
3511  {
3512  JSON_THROW(invalid_iterator::create(201, "iterators are not compatible"));
3513  }
3514 
3515  // copy type from first iterator
3516  m_type = first.m_object->m_type;
3517 
3518  // check if iterator range is complete for primitive values
3519  switch (m_type)
3520  {
3521  case value_t::boolean:
3522  case value_t::number_float:
3525  case value_t::string:
3526  {
3527  if (JSON_UNLIKELY(not first.m_it.primitive_iterator.is_begin()
3528  or not last.m_it.primitive_iterator.is_end()))
3529  {
3530  JSON_THROW(invalid_iterator::create(204, "iterators out of range"));
3531  }
3532  break;
3533  }
3534 
3535  default:
3536  break;
3537  }
3538 
3539  switch (m_type)
3540  {
3542  {
3543  m_value.number_integer = first.m_object->m_value.number_integer;
3544  break;
3545  }
3546 
3548  {
3549  m_value.number_unsigned = first.m_object->m_value.number_unsigned;
3550  break;
3551  }
3552 
3553  case value_t::number_float:
3554  {
3555  m_value.number_float = first.m_object->m_value.number_float;
3556  break;
3557  }
3558 
3559  case value_t::boolean:
3560  {
3561  m_value.boolean = first.m_object->m_value.boolean;
3562  break;
3563  }
3564 
3565  case value_t::string:
3566  {
3567  m_value = *first.m_object->m_value.string;
3568  break;
3569  }
3570 
3571  case value_t::array:
3572  {
3573  m_value.array = create<array_t>(first.m_it.array_iterator,
3574  last.m_it.array_iterator);
3575  break;
3576  }
3577 
3578  default:
3579  JSON_THROW(invalid_iterator::create(206, "cannot construct with iterators from " +
3580  Twine(first.m_object->type_name())));
3581  }
3582 
3583  assert_invariant();
3584  }
3585 
3586 
3588  // other constructors and destructor //
3590 
3592  json(const detail::json_ref<json>& ref)
3593  : json(ref.moved_or_copied())
3594  {}
3595 
3621  json(const json& other);
3622 
3649  json(json&& other) noexcept
3650  : m_type(std::move(other.m_type)),
3651  m_value(std::move(other.m_value))
3652  {
3653  // check that passed value is valid
3654  other.assert_invariant();
3655 
3656  // invalidate payload
3657  other.m_type = value_t::null;
3658  other.m_value = {};
3659 
3660  assert_invariant();
3661  }
3662 
3686  reference& operator=(json other) noexcept (
3687  std::is_nothrow_move_constructible<value_t>::value and
3688  std::is_nothrow_move_assignable<value_t>::value and
3689  std::is_nothrow_move_constructible<json_value>::value and
3690  std::is_nothrow_move_assignable<json_value>::value
3691  )
3692  {
3693  // check that passed value is valid
3694  other.assert_invariant();
3695 
3696  using std::swap;
3697  swap(m_type, other.m_type);
3698  swap(m_value, other.m_value);
3699 
3700  assert_invariant();
3701  return *this;
3702  }
3703 
3719  ~json() noexcept
3720  {
3721  assert_invariant();
3722  m_value.destroy(m_type);
3723  }
3724 
3726 
3727  public:
3729  // object inspection //
3731 
3735 
3772  std::string dump(const int indent = -1, const char indent_char = ' ',
3773  const bool ensure_ascii = false) const;
3774 
3775  void dump(raw_ostream& os, int indent = -1, const char indent_char = ' ',
3776  const bool ensure_ascii = false) const;
3777 
3810  value_t type() const noexcept
3811  {
3812  return m_type;
3813  }
3814 
3840  bool is_primitive() const noexcept
3841  {
3842  return is_null() or is_string() or is_boolean() or is_number();
3843  }
3844 
3867  bool is_structured() const noexcept
3868  {
3869  return is_array() or is_object();
3870  }
3871 
3889  bool is_null() const noexcept
3890  {
3891  return (m_type == value_t::null);
3892  }
3893 
3911  bool is_boolean() const noexcept
3912  {
3913  return (m_type == value_t::boolean);
3914  }
3915 
3941  bool is_number() const noexcept
3942  {
3943  return is_number_integer() or is_number_float();
3944  }
3945 
3970  bool is_number_integer() const noexcept
3971  {
3972  return (m_type == value_t::number_integer or m_type == value_t::number_unsigned);
3973  }
3974 
3998  bool is_number_unsigned() const noexcept
3999  {
4000  return (m_type == value_t::number_unsigned);
4001  }
4002 
4026  bool is_number_float() const noexcept
4027  {
4028  return (m_type == value_t::number_float);
4029  }
4030 
4048  bool is_object() const noexcept
4049  {
4050  return (m_type == value_t::object);
4051  }
4052 
4070  bool is_array() const noexcept
4071  {
4072  return (m_type == value_t::array);
4073  }
4074 
4092  bool is_string() const noexcept
4093  {
4094  return (m_type == value_t::string);
4095  }
4096 
4119  bool is_discarded() const noexcept
4120  {
4121  return (m_type == value_t::discarded);
4122  }
4123 
4145  operator value_t() const noexcept
4146  {
4147  return m_type;
4148  }
4149 
4151 
4152  private:
4154  // value access //
4156 
4158  bool get_impl(bool* /*unused*/) const
4159  {
4160  if (JSON_LIKELY(is_boolean()))
4161  {
4162  return m_value.boolean;
4163  }
4164 
4165  JSON_THROW(type_error::create(302, "type must be boolean, but is " + Twine(type_name())));
4166  }
4167 
4169  object_t* get_impl_ptr(object_t* /*unused*/) noexcept
4170  {
4171  return is_object() ? m_value.object : nullptr;
4172  }
4173 
4175  const object_t* get_impl_ptr(const object_t* /*unused*/) const noexcept
4176  {
4177  return is_object() ? m_value.object : nullptr;
4178  }
4179 
4181  array_t* get_impl_ptr(array_t* /*unused*/) noexcept
4182  {
4183  return is_array() ? m_value.array : nullptr;
4184  }
4185 
4187  const array_t* get_impl_ptr(const array_t* /*unused*/) const noexcept
4188  {
4189  return is_array() ? m_value.array : nullptr;
4190  }
4191 
4193  std::string* get_impl_ptr(std::string* /*unused*/) noexcept
4194  {
4195  return is_string() ? m_value.string : nullptr;
4196  }
4197 
4199  const std::string* get_impl_ptr(const std::string* /*unused*/) const noexcept
4200  {
4201  return is_string() ? m_value.string : nullptr;
4202  }
4203 
4205  bool* get_impl_ptr(bool* /*unused*/) noexcept
4206  {
4207  return is_boolean() ? &m_value.boolean : nullptr;
4208  }
4209 
4211  const bool* get_impl_ptr(const bool* /*unused*/) const noexcept
4212  {
4213  return is_boolean() ? &m_value.boolean : nullptr;
4214  }
4215 
4217  int64_t* get_impl_ptr(int64_t* /*unused*/) noexcept
4218  {
4219  return is_number_integer() ? &m_value.number_integer : nullptr;
4220  }
4221 
4223  const int64_t* get_impl_ptr(const int64_t* /*unused*/) const noexcept
4224  {
4225  return is_number_integer() ? &m_value.number_integer : nullptr;
4226  }
4227 
4229  uint64_t* get_impl_ptr(uint64_t* /*unused*/) noexcept
4230  {
4231  return is_number_unsigned() ? &m_value.number_unsigned : nullptr;
4232  }
4233 
4235  const uint64_t* get_impl_ptr(const uint64_t* /*unused*/) const noexcept
4236  {
4237  return is_number_unsigned() ? &m_value.number_unsigned : nullptr;
4238  }
4239 
4241  double* get_impl_ptr(double* /*unused*/) noexcept
4242  {
4243  return is_number_float() ? &m_value.number_float : nullptr;
4244  }
4245 
4247  const double* get_impl_ptr(const double* /*unused*/) const noexcept
4248  {
4249  return is_number_float() ? &m_value.number_float : nullptr;
4250  }
4251 
4263  template<typename ReferenceType, typename ThisType>
4264  static ReferenceType get_ref_impl(ThisType& obj)
4265  {
4266  // delegate the call to get_ptr<>()
4267  auto ptr = obj.template get_ptr<typename std::add_pointer<ReferenceType>::type>();
4268 
4269  if (JSON_LIKELY(ptr != nullptr))
4270  {
4271  return *ptr;
4272  }
4273 
4274  JSON_THROW(type_error::create(303, "incompatible ReferenceType for get_ref, actual type is " + Twine(obj.type_name())));
4275  }
4276 
4277  public:
4281 
4296  template<typename BasicJsonType, detail::enable_if_t<
4297  std::is_same<typename std::remove_const<BasicJsonType>::type, json_t>::value,
4298  int> = 0>
4299  json get() const
4300  {
4301  return *this;
4302  }
4303 
4343  template<typename ValueTypeCV, typename ValueType = detail::uncvref_t<ValueTypeCV>,
4344  detail::enable_if_t <
4345  not detail::is_json<ValueType>::value and
4346  detail::has_from_json<json_t, ValueType>::value and
4347  not detail::has_non_default_from_json<json_t, ValueType>::value,
4348  int> = 0>
4349  ValueType get() const noexcept(noexcept(
4350  adl_serializer<ValueType, void>::from_json(std::declval<const json_t&>(), std::declval<ValueType&>())))
4351  {
4352  // we cannot static_assert on ValueTypeCV being non-const, because
4353  // there is support for get<const json_t>(), which is why we
4354  // still need the uncvref
4355  static_assert(not std::is_reference<ValueTypeCV>::value,
4356  "get() cannot be used with reference types, you might want to use get_ref()");
4357  static_assert(std::is_default_constructible<ValueType>::value,
4358  "types must be DefaultConstructible when used with get()");
4359 
4360  ValueType ret;
4362  return ret;
4363  }
4364 
4396  template<typename ValueTypeCV, typename ValueType = detail::uncvref_t<ValueTypeCV>,
4397  detail::enable_if_t<not std::is_same<json_t, ValueType>::value and
4398  detail::has_non_default_from_json<json_t, ValueType>::value,
4399  int> = 0>
4400  ValueType get() const noexcept(noexcept(
4401  adl_serializer<ValueTypeCV, void>::from_json(std::declval<const json_t&>())))
4402  {
4403  static_assert(not std::is_reference<ValueTypeCV>::value,
4404  "get() cannot be used with reference types, you might want to use get_ref()");
4406  }
4407 
4434  template<typename PointerType, typename std::enable_if<
4435  std::is_pointer<PointerType>::value, int>::type = 0>
4436  PointerType get() noexcept
4437  {
4438  // delegate the call to get_ptr
4439  return get_ptr<PointerType>();
4440  }
4441 
4446  template<typename PointerType, typename std::enable_if<
4447  std::is_pointer<PointerType>::value, int>::type = 0>
4448  const PointerType get() const noexcept
4449  {
4450  // delegate the call to get_ptr
4451  return get_ptr<PointerType>();
4452  }
4453 
4479  template<typename PointerType, typename std::enable_if<
4480  std::is_pointer<PointerType>::value, int>::type = 0>
4481  PointerType get_ptr() noexcept
4482  {
4483  // get the type of the PointerType (remove pointer and const)
4484  using pointee_t = typename std::remove_const<typename
4485  std::remove_pointer<typename
4486  std::remove_const<PointerType>::type>::type>::type;
4487  // make sure the type matches the allowed types
4488  static_assert(
4489  std::is_same<object_t, pointee_t>::value
4490  or std::is_same<array_t, pointee_t>::value
4491  or std::is_same<std::string, pointee_t>::value
4492  or std::is_same<bool, pointee_t>::value
4493  or std::is_same<int64_t, pointee_t>::value
4494  or std::is_same<uint64_t, pointee_t>::value
4495  or std::is_same<double, pointee_t>::value
4496  , "incompatible pointer type");
4497 
4498  // delegate the call to get_impl_ptr<>()
4499  return get_impl_ptr(static_cast<PointerType>(nullptr));
4500  }
4501 
4506  template<typename PointerType, typename std::enable_if<
4507  std::is_pointer<PointerType>::value and
4508  std::is_const<typename std::remove_pointer<PointerType>::type>::value, int>::type = 0>
4509  const PointerType get_ptr() const noexcept
4510  {
4511  // get the type of the PointerType (remove pointer and const)
4512  using pointee_t = typename std::remove_const<typename
4513  std::remove_pointer<typename
4514  std::remove_const<PointerType>::type>::type>::type;
4515  // make sure the type matches the allowed types
4516  static_assert(
4517  std::is_same<object_t, pointee_t>::value
4518  or std::is_same<array_t, pointee_t>::value
4519  or std::is_same<std::string, pointee_t>::value
4520  or std::is_same<bool, pointee_t>::value
4521  or std::is_same<int64_t, pointee_t>::value
4522  or std::is_same<uint64_t, pointee_t>::value
4523  or std::is_same<double, pointee_t>::value
4524  , "incompatible pointer type");
4525 
4526  // delegate the call to get_impl_ptr<>() const
4527  return get_impl_ptr(static_cast<PointerType>(nullptr));
4528  }
4529 
4556  template<typename ReferenceType, typename std::enable_if<
4557  std::is_reference<ReferenceType>::value, int>::type = 0>
4558  ReferenceType get_ref()
4559  {
4560  // delegate call to get_ref_impl
4561  return get_ref_impl<ReferenceType>(*this);
4562  }
4563 
4568  template<typename ReferenceType, typename std::enable_if<
4569  std::is_reference<ReferenceType>::value and
4570  std::is_const<typename std::remove_reference<ReferenceType>::type>::value, int>::type = 0>
4571  ReferenceType get_ref() const
4572  {
4573  // delegate call to get_ref_impl
4574  return get_ref_impl<ReferenceType>(*this);
4575  }
4576 
4606  template < typename ValueType, typename std::enable_if <
4607  not std::is_pointer<ValueType>::value and
4608  not std::is_same<ValueType, detail::json_ref<json>>::value and
4609  not std::is_same<ValueType, std::string::value_type>::value and
4611 #ifndef _MSC_VER // fix for issue #167 operator<< ambiguity under VS2015
4612  and not std::is_same<ValueType, std::initializer_list<std::string::value_type>>::value
4613 #endif
4614  and not std::is_same<ValueType, typename std::string_view>::value
4615  , int >::type = 0 >
4616  operator ValueType() const
4617  {
4618  // delegate the call to get<>() const
4619  return get<ValueType>();
4620  }
4621 
4623 
4624 
4626  // element access //
4628 
4632 
4659  reference at(size_type idx);
4660 
4687  const_reference at(size_type idx) const;
4688 
4719  reference at(StringRef key);
4720 
4751  const_reference at(StringRef key) const;
4752 
4779 
4800 
4829 
4861 
4889  template<typename T>
4891  {
4892  // implicitly convert null to object
4893  if (is_null())
4894  {
4895  m_type = value_t::object;
4896  m_value = value_t::object;
4897  assert_invariant();
4898  }
4899 
4900  // at only works for objects
4901  if (JSON_LIKELY(is_object()))
4902  {
4903  return m_value.object->operator[](key);
4904  }
4905 
4906  JSON_THROW(type_error::create(305, "cannot use operator[] with " + Twine(type_name())));
4907  }
4908 
4939  template<typename T>
4941  {
4942  // at only works for objects
4943  if (JSON_LIKELY(is_object()))
4944  {
4945  assert(m_value.object->find(key) != m_value.object->end());
4946  return m_value.object->find(key)->second;
4947  }
4948 
4949  JSON_THROW(type_error::create(305, "cannot use operator[] with " + Twine(type_name())));
4950  }
4951 
5000  template<class ValueType, typename std::enable_if<
5001  std::is_convertible<json_t, ValueType>::value, int>::type = 0>
5002  ValueType value(StringRef key, const ValueType& default_value) const
5003  {
5004  // at only works for objects
5005  if (JSON_LIKELY(is_object()))
5006  {
5007  // if key is found, return value and given default value otherwise
5008  const auto it = find(key);
5009  if (it != end())
5010  {
5011  return *it;
5012  }
5013 
5014  return default_value;
5015  }
5016 
5017  JSON_THROW(type_error::create(306, "cannot use value() with " + Twine(type_name())));
5018  }
5019 
5024  std::string value(StringRef key, const char* default_value) const
5025  {
5026  return value(key, std::string(default_value));
5027  }
5028 
5070  template<class ValueType, typename std::enable_if<
5071  std::is_convertible<json_t, ValueType>::value, int>::type = 0>
5072  ValueType value(const json_pointer& ptr, const ValueType& default_value) const
5073  {
5074  // at only works for objects
5075  if (JSON_LIKELY(is_object()))
5076  {
5077  // if pointer resolves a value, return it or use default value
5078  JSON_TRY
5079  {
5080  return ptr.get_checked(this);
5081  }
5082  JSON_CATCH (out_of_range&)
5083  {
5084  return default_value;
5085  }
5086  }
5087 
5088  JSON_THROW(type_error::create(306, "cannot use value() with " + Twine(type_name())));
5089  }
5090 
5095  std::string value(const json_pointer& ptr, const char* default_value) const
5096  {
5097  return value(ptr, std::string(default_value));
5098  }
5099 
5126  {
5127  return *begin();
5128  }
5129 
5134  {
5135  return *cbegin();
5136  }
5137 
5170  {
5171  auto tmp = end();
5172  --tmp;
5173  return *tmp;
5174  }
5175 
5180  {
5181  auto tmp = cend();
5182  --tmp;
5183  return *tmp;
5184  }
5185 
5230  template<class IteratorType, typename std::enable_if<
5231  std::is_same<IteratorType, typename json_t::iterator>::value or
5232  std::is_same<IteratorType, typename json_t::const_iterator>::value, int>::type
5233  = 0>
5234  void erase(IteratorType pos)
5235  {
5236  // make sure iterator fits the current value
5237  if (JSON_UNLIKELY(this != pos.m_object))
5238  {
5239  JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value"));
5240  }
5241 
5242  switch (m_type)
5243  {
5244  case value_t::boolean:
5245  case value_t::number_float:
5248  case value_t::string:
5249  {
5250  if (JSON_UNLIKELY(not pos.m_it.primitive_iterator.is_begin()))
5251  {
5252  JSON_THROW(invalid_iterator::create(205, "iterator out of range"));
5253  }
5254 
5255  if (is_string())
5256  {
5257  std::allocator<std::string> alloc;
5258  std::allocator_traits<decltype(alloc)>::destroy(alloc, m_value.string);
5259  std::allocator_traits<decltype(alloc)>::deallocate(alloc, m_value.string, 1);
5260  m_value.string = nullptr;
5261  }
5262 
5263  m_type = value_t::null;
5264  assert_invariant();
5265  break;
5266  }
5267 
5268  case value_t::object:
5269  {
5270  m_value.object->erase(pos.m_it.object_iterator);
5271  break;
5272  }
5273 
5274  case value_t::array:
5275  {
5276  m_value.array->erase(pos.m_it.array_iterator);
5277  break;
5278  }
5279 
5280  default:
5281  JSON_THROW(type_error::create(307, "cannot use erase() with " + Twine(type_name())));
5282  }
5283  }
5284 
5331  template<class IteratorType, typename std::enable_if<
5332  std::is_same<IteratorType, typename json_t::iterator>::value or
5333  std::is_same<IteratorType, typename json_t::const_iterator>::value, int>::type
5334  = 0>
5335  IteratorType erase(IteratorType first, IteratorType last)
5336  {
5337  // make sure iterator fits the current value
5338  if (JSON_UNLIKELY(this != first.m_object or this != last.m_object))
5339  {
5340  JSON_THROW(invalid_iterator::create(203, "iterators do not fit current value"));
5341  }
5342 
5343  IteratorType result = end();
5344 
5345  switch (m_type)
5346  {
5347  case value_t::boolean:
5348  case value_t::number_float:
5351  case value_t::string:
5352  {
5353  if (JSON_LIKELY(not first.m_it.primitive_iterator.is_begin()
5354  or not last.m_it.primitive_iterator.is_end()))
5355  {
5356  JSON_THROW(invalid_iterator::create(204, "iterators out of range"));
5357  }
5358 
5359  if (is_string())
5360  {
5361  std::allocator<std::string> alloc;
5362  std::allocator_traits<decltype(alloc)>::destroy(alloc, m_value.string);
5363  std::allocator_traits<decltype(alloc)>::deallocate(alloc, m_value.string, 1);
5364  m_value.string = nullptr;
5365  }
5366 
5367  m_type = value_t::null;
5368  assert_invariant();
5369  break;
5370  }
5371 
5372  case value_t::array:
5373  {
5374  result.m_it.array_iterator = m_value.array->erase(first.m_it.array_iterator,
5375  last.m_it.array_iterator);
5376  break;
5377  }
5378 
5379  default:
5380  JSON_THROW(type_error::create(307, "cannot use erase() with " + Twine(type_name())));
5381  }
5382 
5383  return result;
5384  }
5385 
5415  size_type erase(StringRef key);
5416 
5441  void erase(const size_type idx);
5442 
5444 
5445 
5447  // lookup //
5449 
5452 
5475  iterator find(StringRef key);
5476 
5481  const_iterator find(StringRef key) const;
5482 
5504  size_type count(StringRef key) const;
5505 
5507 
5508 
5510  // iterators //
5512 
5515 
5540  iterator begin() noexcept
5541  {
5542  iterator result(this);
5543  result.set_begin();
5544  return result;
5545  }
5546 
5550  const_iterator begin() const noexcept
5551  {
5552  return cbegin();
5553  }
5554 
5580  const_iterator cbegin() const noexcept
5581  {
5582  const_iterator result(this);
5583  result.set_begin();
5584  return result;
5585  }
5586 
5611  iterator end() noexcept
5612  {
5613  iterator result(this);
5614  result.set_end();
5615  return result;
5616  }
5617 
5621  const_iterator end() const noexcept
5622  {
5623  return cend();
5624  }
5625 
5651  const_iterator cend() const noexcept
5652  {
5653  const_iterator result(this);
5654  result.set_end();
5655  return result;
5656  }
5657 
5682  {
5683  return reverse_iterator(end());
5684  }
5685 
5690  {
5691  return crbegin();
5692  }
5693 
5719  {
5720  return reverse_iterator(begin());
5721  }
5722 
5726  const_reverse_iterator rend() const noexcept
5727  {
5728  return crend();
5729  }
5730 
5756  {
5757  return const_reverse_iterator(cend());
5758  }
5759 
5785  {
5786  return const_reverse_iterator(cbegin());
5787  }
5788 
5789  public:
5843  {
5844  return iteration_proxy<iterator>(*this);
5845  }
5846 
5851  {
5852  return iteration_proxy<const_iterator>(*this);
5853  }
5854 
5856 
5857 
5859  // capacity //
5861 
5864 
5906  bool empty() const noexcept;
5907 
5950  size_type size() const noexcept;
5951 
5992  size_type max_size() const noexcept;
5993 
5995 
5996 
5998  // modifiers //
6000 
6003 
6040  void clear() noexcept;
6041 
6062  void push_back(json&& val);
6063 
6068  reference operator+=(json&& val)
6069  {
6070  push_back(std::move(val));
6071  return *this;
6072  }
6073 
6078  void push_back(const json& val);
6079 
6085  {
6086  push_back(val);
6087  return *this;
6088  }
6089 
6110  template<typename T, typename U>
6111  void push_back(const std::pair<T, U>& val)
6112  {
6113  // push_back only works for null objects or objects
6114  if (JSON_UNLIKELY(not(is_null() or is_object())))
6115  {
6116  JSON_THROW(type_error::create(308, "cannot use push_back() with " + Twine(type_name())));
6117  }
6118 
6119  // transform null object into an object
6120  if (is_null())
6121  {
6122  m_type = value_t::object;
6123  m_value = value_t::object;
6124  assert_invariant();
6125  }
6126 
6127  // add element to array
6128  m_value.object->try_emplace(val.first, std::move(val.second));
6129  }
6130 
6135  template<typename T, typename U>
6136  reference operator+=(const std::pair<T, U>& val)
6137  {
6138  push_back(val);
6139  return *this;
6140  }
6141 
6167  void push_back(initializer_list_t init);
6168 
6174  {
6175  push_back(init);
6176  return *this;
6177  }
6178 
6200  template<class... Args>
6201  void emplace_back(Args&& ... args)
6202  {
6203  // emplace_back only works for null objects or arrays
6204  if (JSON_UNLIKELY(not(is_null() or is_array())))
6205  {
6206  JSON_THROW(type_error::create(311, "cannot use emplace_back() with " + Twine(type_name())));
6207  }
6208 
6209  // transform null object into an array
6210  if (is_null())
6211  {
6212  m_type = value_t::array;
6213  m_value = value_t::array;
6214  assert_invariant();
6215  }
6216 
6217  // add element to array (perfect forwarding)
6218  m_value.array->emplace_back(std::forward<Args>(args)...);
6219  }
6220 
6248  template<class... Args>
6249  std::pair<iterator, bool> emplace(StringRef key, Args&& ... args)
6250  {
6251  // emplace only works for null objects or arrays
6252  if (JSON_UNLIKELY(not(is_null() or is_object())))
6253  {
6254  JSON_THROW(type_error::create(311, "cannot use emplace() with " + Twine(type_name())));
6255  }
6256 
6257  // transform null object into an object
6258  if (is_null())
6259  {
6260  m_type = value_t::object;
6261  m_value = value_t::object;
6262  assert_invariant();
6263  }
6264 
6265  // add element to array (perfect forwarding)
6266  auto res = m_value.object->try_emplace(key, std::forward<Args>(args)...);
6267  // create result iterator and set iterator to the result of emplace
6268  auto it = begin();
6269  it.m_it.object_iterator = res.first;
6270 
6271  // return pair of iterator and boolean
6272  return {it, res.second};
6273  }
6274 
6297  iterator insert(const_iterator pos, const json& val);
6298 
6304  {
6305  return insert(pos, val);
6306  }
6307 
6332  iterator insert(const_iterator pos, size_type cnt, const json& val);
6333 
6365 
6391 
6415  void insert(const_iterator first, const_iterator last);
6416 
6436  void update(const_reference j);
6437 
6464  void update(const_iterator first, const_iterator last);
6465 
6483  void swap(reference other) noexcept (
6484  std::is_nothrow_move_constructible<value_t>::value and
6485  std::is_nothrow_move_assignable<value_t>::value and
6486  std::is_nothrow_move_constructible<json_value>::value and
6487  std::is_nothrow_move_assignable<json_value>::value
6488  )
6489  {
6490  std::swap(m_type, other.m_type);
6491  std::swap(m_value, other.m_value);
6492  assert_invariant();
6493  }
6494 
6515  void swap(array_t& other)
6516  {
6517  // swap only works for arrays
6518  if (JSON_LIKELY(is_array()))
6519  {
6520  std::swap(*(m_value.array), other);
6521  }
6522  else
6523  {
6524  JSON_THROW(type_error::create(310, "cannot use swap() with " + Twine(type_name())));
6525  }
6526  }
6527 
6548  void swap(object_t& other)
6549  {
6550  // swap only works for objects
6551  if (JSON_LIKELY(is_object()))
6552  {
6553  std::swap(*(m_value.object), other);
6554  }
6555  else
6556  {
6557  JSON_THROW(type_error::create(310, "cannot use swap() with " + Twine(type_name())));
6558  }
6559  }
6560 
6581  void swap(std::string& other)
6582  {
6583  // swap only works for strings
6584  if (JSON_LIKELY(is_string()))
6585  {
6586  std::swap(*(m_value.string), other);
6587  }
6588  else
6589  {
6590  JSON_THROW(type_error::create(310, "cannot use swap() with " + Twine(type_name())));
6591  }
6592  }
6593 
6595 
6596  public:
6598  // lexicographical comparison operators //
6600 
6603 
6643  friend bool operator==(const_reference lhs, const_reference rhs) noexcept;
6644 
6649  template<typename ScalarType, typename std::enable_if<
6650  std::is_scalar<ScalarType>::value, int>::type = 0>
6651  friend bool operator==(const_reference lhs, const ScalarType rhs) noexcept
6652  {
6653  return (lhs == json(rhs));
6654  }
6655 
6660  template<typename ScalarType, typename std::enable_if<
6661  std::is_scalar<ScalarType>::value, int>::type = 0>
6662  friend bool operator==(const ScalarType lhs, const_reference rhs) noexcept
6663  {
6664  return (json(lhs) == rhs);
6665  }
6666 
6685  friend bool operator!=(const_reference lhs, const_reference rhs) noexcept
6686  {
6687  return not (lhs == rhs);
6688  }
6689 
6694  template<typename ScalarType, typename std::enable_if<
6695  std::is_scalar<ScalarType>::value, int>::type = 0>
6696  friend bool operator!=(const_reference lhs, const ScalarType rhs) noexcept
6697  {
6698  return (lhs != json(rhs));
6699  }
6700 
6705  template<typename ScalarType, typename std::enable_if<
6706  std::is_scalar<ScalarType>::value, int>::type = 0>
6707  friend bool operator!=(const ScalarType lhs, const_reference rhs) noexcept
6708  {
6709  return (json(lhs) != rhs);
6710  }
6711 
6738  friend bool operator<(const_reference lhs, const_reference rhs) noexcept;
6739 
6744  template<typename ScalarType, typename std::enable_if<
6745  std::is_scalar<ScalarType>::value, int>::type = 0>
6746  friend bool operator<(const_reference lhs, const ScalarType rhs) noexcept
6747  {
6748  return (lhs < json(rhs));
6749  }
6750 
6755  template<typename ScalarType, typename std::enable_if<
6756  std::is_scalar<ScalarType>::value, int>::type = 0>
6757  friend bool operator<(const ScalarType lhs, const_reference rhs) noexcept
6758  {
6759  return (json(lhs) < rhs);
6760  }
6761 
6781  friend bool operator<=(const_reference lhs, const_reference rhs) noexcept
6782  {
6783  return not (rhs < lhs);
6784  }
6785 
6790  template<typename ScalarType, typename std::enable_if<
6791  std::is_scalar<ScalarType>::value, int>::type = 0>
6792  friend bool operator<=(const_reference lhs, const ScalarType rhs) noexcept
6793  {
6794  return (lhs <= json(rhs));
6795  }
6796 
6801  template<typename ScalarType, typename std::enable_if<
6802  std::is_scalar<ScalarType>::value, int>::type = 0>
6803  friend bool operator<=(const ScalarType lhs, const_reference rhs) noexcept
6804  {
6805  return (json(lhs) <= rhs);
6806  }
6807 
6827  friend bool operator>(const_reference lhs, const_reference rhs) noexcept
6828  {
6829  return not (lhs <= rhs);
6830  }
6831 
6836  template<typename ScalarType, typename std::enable_if<
6837  std::is_scalar<ScalarType>::value, int>::type = 0>
6838  friend bool operator>(const_reference lhs, const ScalarType rhs) noexcept
6839  {
6840  return (lhs > json(rhs));
6841  }
6842 
6847  template<typename ScalarType, typename std::enable_if<
6848  std::is_scalar<ScalarType>::value, int>::type = 0>
6849  friend bool operator>(const ScalarType lhs, const_reference rhs) noexcept
6850  {
6851  return (json(lhs) > rhs);
6852  }
6853 
6873  friend bool operator>=(const_reference lhs, const_reference rhs) noexcept
6874  {
6875  return not (lhs < rhs);
6876  }
6877 
6882  template<typename ScalarType, typename std::enable_if<
6883  std::is_scalar<ScalarType>::value, int>::type = 0>
6884  friend bool operator>=(const_reference lhs, const ScalarType rhs) noexcept
6885  {
6886  return (lhs >= json(rhs));
6887  }
6888 
6893  template<typename ScalarType, typename std::enable_if<
6894  std::is_scalar<ScalarType>::value, int>::type = 0>
6895  friend bool operator>=(const ScalarType lhs, const_reference rhs) noexcept
6896  {
6897  return (json(lhs) >= rhs);
6898  }
6899 
6901 
6903  // serialization //
6905 
6908 
6940  friend raw_ostream& operator<<(raw_ostream& o, const json& j);
6941 
6943 
6944 
6946  // deserialization //
6948 
6951 
7014  static json parse(StringRef s,
7015  const parser_callback_t cb = nullptr,
7016  const bool allow_exceptions = true);
7017 
7018  static json parse(ArrayRef<uint8_t> arr,
7019  const parser_callback_t cb = nullptr,
7020  const bool allow_exceptions = true);
7021 
7025  static json parse(raw_istream& i,
7026  const parser_callback_t cb = nullptr,
7027  const bool allow_exceptions = true);
7028 
7029  static bool accept(StringRef s);
7030 
7031  static bool accept(ArrayRef<uint8_t> arr);
7032 
7033  static bool accept(raw_istream& i);
7034 
7060  friend raw_istream& operator>>(raw_istream& i, json& j);
7061 
7063 
7065  // convenience functions //
7067 
7098  const char* type_name() const noexcept;
7099 
7100 
7101  private:
7103  // member variables //
7105 
7107  value_t m_type = value_t::null;
7108 
7110  json_value m_value = {};
7111 
7113  // binary serialization/deserialization //
7115 
7118 
7119  public:
7208  static std::vector<uint8_t> to_cbor(const json& j);
7209  static ArrayRef<uint8_t> to_cbor(const json& j, std::vector<uint8_t>& buf);
7210  static ArrayRef<uint8_t> to_cbor(const json& j, SmallVectorImpl<uint8_t>& buf);
7211  static void to_cbor(raw_ostream& os, const json& j);
7212 
7293  static std::vector<uint8_t> to_msgpack(const json& j);
7294  static ArrayRef<uint8_t> to_msgpack(const json& j, std::vector<uint8_t>& buf);
7295  static ArrayRef<uint8_t> to_msgpack(const json& j, SmallVectorImpl<uint8_t>& buf);
7296  static void to_msgpack(raw_ostream& os, const json& j);
7297 
7378  static std::vector<uint8_t> to_ubjson(const json& j,
7379  const bool use_size = false,
7380  const bool use_type = false);
7381  static ArrayRef<uint8_t> to_ubjson(const json& j, std::vector<uint8_t>& buf,
7382  const bool use_size = false, const bool use_type = false);
7383  static ArrayRef<uint8_t> to_ubjson(const json& j, SmallVectorImpl<uint8_t>& buf,
7384  const bool use_size = false, const bool use_type = false);
7385  static void to_ubjson(raw_ostream& os, const json& j,
7386  const bool use_size = false, const bool use_type = false);
7387 
7481  static json from_cbor(raw_istream& is,
7482  const bool strict = true);
7483 
7487  static json from_cbor(ArrayRef<uint8_t> arr, const bool strict = true);
7488 
7562  static json from_msgpack(raw_istream& is,
7563  const bool strict = true);
7564 
7568  static json from_msgpack(ArrayRef<uint8_t> arr, const bool strict = true);
7569 
7623  static json from_ubjson(raw_istream& is,
7624  const bool strict = true);
7625 
7626  static json from_ubjson(ArrayRef<uint8_t> arr, const bool strict = true);
7627 
7629 
7631  // JSON Pointer support //
7633 
7636 
7671  {
7672  return ptr.get_unchecked(this);
7673  }
7674 
7699  {
7700  return ptr.get_unchecked(this);
7701  }
7702 
7742  {
7743  return ptr.get_checked(this);
7744  }
7745 
7784  const_reference at(const json_pointer& ptr) const
7785  {
7786  return ptr.get_checked(this);
7787  }
7788 
7811  json flatten() const
7812  {
7813  json result(value_t::object);
7814  json_pointer::flatten("", *this, result);
7815  return result;
7816  }
7817 
7848  json unflatten() const
7849  {
7850  return json_pointer::unflatten(*this);
7851  }
7852 
7854 
7856  // JSON Patch functions //
7858 
7861 
7909  json patch(const json& json_patch) const;
7910 
7944  static json diff(const json& source, const json& target,
7945  const std::string& path = "");
7946 
7948 
7950  // JSON Merge Patch functions //
7952 
7955 
7998  void merge_patch(const json& patch);
7999 
8001 };
8002 } // namespace wpi
8003 
8005 // nonmember support //
8007 
8008 // specialization of std::swap, and std::hash
8009 namespace std
8010 {
8016 template<>
8017 inline void swap<wpi::json>(wpi::json& j1,
8018  wpi::json& j2) noexcept(
8019  is_nothrow_move_constructible<wpi::json>::value and
8020  is_nothrow_move_assignable<wpi::json>::value
8021  )
8022 {
8023  j1.swap(j2);
8024 }
8025 
8027 template<>
8028 struct hash<wpi::json>
8029 {
8035  std::size_t operator()(const wpi::json& j) const
8036  {
8037  // a naive hashing via the string representation
8038  const auto& h = hash<std::string>();
8039  return h(j.dump());
8040  }
8041 };
8042 
8046 template<>
8047 struct less< ::wpi::detail::value_t>
8048 {
8054  wpi::detail::value_t rhs) const noexcept
8055  {
8056  return wpi::detail::operator<(lhs, rhs);
8057  }
8058 };
8059 
8060 } // namespace std
8061 
8075 inline wpi::json operator "" _json(const char* s, std::size_t n)
8076 {
8077  return wpi::json::parse(wpi::StringRef(s, n));
8078 }
8079 
8093 inline wpi::json::json_pointer operator "" _json_pointer(const char* s, std::size_t n)
8094 {
8096 }
8097 
8098 #ifndef WPI_JSON_IMPLEMENTATION
8099 
8100 // restore GCC/clang diagnostic settings
8101 #if defined(__clang__) || defined(__GNUC__) || defined(__GNUG__)
8102  #pragma GCC diagnostic pop
8103 #endif
8104 #if defined(__clang__)
8105  #pragma GCC diagnostic pop
8106 #endif
8107 
8108 // clean up
8109 #undef JSON_CATCH
8110 #undef JSON_THROW
8111 #undef JSON_TRY
8112 #undef JSON_LIKELY
8113 #undef JSON_UNLIKELY
8114 #undef NLOHMANN_BASIC_JSON_TPL_DECLARATION
8115 #undef NLOHMANN_BASIC_JSON_TPL
8116 #undef NLOHMANN_JSON_HAS_HELPER
8117 
8118 #endif // WPI_JSON_IMPLEMENTATION
8119 
8120 #endif
wpi::json::value
ValueType value(const json_pointer &ptr, const ValueType &default_value) const
access specified object element via JSON Pointer with default value
Definition: json.h:5072
wpi::json::cend
const_iterator cend() const noexcept
returns a const iterator to one past the last element
Definition: json.h:5651
wpi::json
a class to store JSON values
Definition: json.h:2655
wpi::json::const_iterator
iter_impl< const json > const_iterator
a const iterator for a json container
Definition: json.h:2749
wpi::json::array_t
std::vector< json > array_t
a type for an array
Definition: json.h:2890
wpi::detail::iter_impl::iter_impl
iter_impl(const iter_impl< typename std::remove_const< BasicJsonType >::type > &other) noexcept
converting constructor
Definition: json.h:1588
wpi::json::get_allocator
static allocator_type get_allocator()
returns the allocator associated with the container
Definition: json.h:2761
wpi::detail::value_t
value_t
the JSON type enumeration
Definition: json.h:701
wpi::adl_serializer
default JSONSerializer template argument
Definition: json.h:83
wpi::detail::json_reverse_iterator::base_iterator
std::reverse_iterator< Base > base_iterator
shortcut to the reverse iterator adapter
Definition: json.h:2189
wpi::detail::value_t::null
null value
wpi::json::parse_event_t::object_end
the parser read } and finished processing a JSON object
wpi::operator!=
bool operator!=(const DenseMapBase< DerivedT, KeyT, ValueT, KeyInfoT, BucketT > &LHS, const DenseMapBase< DerivedT, KeyT, ValueT, KeyInfoT, BucketT > &RHS)
Inequality comparison for DenseMap.
Definition: DenseMap.h:659
wpi::json::type
value_t type() const noexcept
return the type of the JSON value (explicit)
Definition: json.h:3810
wpi::json::operator<=
friend bool operator<=(const ScalarType lhs, const_reference rhs) noexcept
comparison: less than or equal
Definition: json.h:6803
wpi::json::difference_type
std::ptrdiff_t difference_type
a type to represent differences between iterators
Definition: json.h:2734
wpi::json::get
const PointerType get() const noexcept
get a pointer value (explicit)
Definition: json.h:4448
wpi::json::begin
iterator begin() noexcept
returns an iterator to the first element
Definition: json.h:5540
wpi::detail::json_reverse_iterator::key
auto key() const -> decltype(std::declval< Base >().key())
return the key of an object iterator
Definition: json.h:2255
wpi::json::parse_event_t::object_start
the parser read { and started to process a JSON object
wpi::detail::value_t::number_unsigned
number value (unsigned integer)
wpi::detail::iter_impl::iter_impl
iter_impl()=default
default constructor
Definition: json.h:1505
wpi::detail::iter_impl::operator-=
iter_impl & operator-=(difference_type i)
subtract from iterator
Definition: json.h:1953
wpi::json::operator>
friend bool operator>(const_reference lhs, const_reference rhs) noexcept
comparison: greater than
Definition: json.h:6827
wpi::json::flatten
json flatten() const
return flattened JSON value
Definition: json.h:7811
wpi::json::operator!=
friend bool operator!=(const_reference lhs, const ScalarType rhs) noexcept
comparison: not equal
Definition: json.h:6696
wpi::json::is_discarded
bool is_discarded() const noexcept
return whether value is discarded
Definition: json.h:4119
wpi::json::operator!=
friend bool operator!=(const_reference lhs, const_reference rhs) noexcept
comparison: not equal
Definition: json.h:6685
std::hash< wpi::json >::operator()
std::size_t operator()(const wpi::json &j) const
return a hash value for a JSON object
Definition: json.h:8035
wpi::detail::value_t::boolean
boolean value
wpi::json::end
const_iterator end() const noexcept
returns a const iterator to one past the last element
Definition: json.h:5621
wpi::detail::internal_iterator
an iterator value
Definition: json.h:1468
wpi::json::swap
void swap(object_t &other)
exchanges the values
Definition: json.h:6548
wpi::json::swap
void swap(array_t &other)
exchanges the values
Definition: json.h:6515
wpi::json::is_primitive
bool is_primitive() const noexcept
return whether type is primitive
Definition: json.h:3840
wpi::detail::json_reverse_iterator::operator-
json_reverse_iterator operator-(difference_type i) const
subtract from iterator
Definition: json.h:2237
wpi::json::cbegin
const_iterator cbegin() const noexcept
returns a const iterator to the first element
Definition: json.h:5580
wpi::json::erase
IteratorType erase(IteratorType first, IteratorType last)
remove elements given an iterator range
Definition: json.h:5335
wpi::detail::parse_error::create
static parse_error create(int id_, std::size_t byte_, const Twine &what_arg)
create a parse error exception
wpi::detail::primitive_iterator_t::set_end
void set_end() noexcept
set iterator to a defined past the end
Definition: json.h:1384
wpi::json::from_msgpack
static json from_msgpack(raw_istream &is, const bool strict=true)
create a JSON value from an input in MessagePack format
wpi::json::value
std::string value(const json_pointer &ptr, const char *default_value) const
overload for a default value of type const char*
Definition: json.h:5095
wpi::json::front
const_reference front() const
access the first element
Definition: json.h:5133
wpi::detail::invalid_iterator
exception indicating errors with iterators
Definition: json.h:542
wpi::json::insert
iterator insert(const_iterator pos, json &&val)
inserts element
Definition: json.h:6303
wpi::json::operator>=
friend bool operator>=(const ScalarType lhs, const_reference rhs) noexcept
comparison: greater than or equal
Definition: json.h:6895
wpi::detail::iter_impl::operator>=
bool operator>=(const iter_impl &other) const
comparison: greater than or equal
Definition: json.h:1915
wpi::json::swap
void swap(std::string &other)
exchanges the values
Definition: json.h:6581
wpi::json::end
iterator end() noexcept
returns an iterator to one past the last element
Definition: json.h:5611
wpi::detail::json_reverse_iterator::reference
typename Base::reference reference
the reference type for the pointed-to element
Definition: json.h:2191
wpi::detail::exception::what
const char * what() const noexcept override
returns the explanatory string
Definition: json.h:417
wpi::detail::json_reverse_iterator::operator+=
json_reverse_iterator & operator+=(difference_type i)
add to iterator
Definition: json.h:2225
wpi::json::operator+=
reference operator+=(initializer_list_t init)
add an object to an object
Definition: json.h:6173
wpi::detail::is_compatible_integer_type
Definition: json.h:296
wpi::json::json
json(json &&other) noexcept
move constructor
Definition: json.h:3649
wpi::json::parse_event_t::value
the parser finished reading a JSON value
wpi::detail::iter_impl::operator--
const iter_impl operator--(int)
post-decrement (it–)
Definition: json.h:1791
wpi::detail::iteration_proxy::end
iteration_proxy_internal end() noexcept
return iterator end (needed for range-based for)
Definition: json.h:2155
wpi::detail::value_t::discarded
discarded by the the parser callback function
wpi::detail::iter_impl::iter_impl
iter_impl(pointer object) noexcept
constructor for a given JSON instance
Definition: json.h:1548
wpi::detail::json_reverse_iterator::operator++
const json_reverse_iterator operator++(int)
post-increment (it++)
Definition: json.h:2201
wpi::json::const_reference
const value_type & const_reference
the type of an element const reference
Definition: json.h:2731
wpi::json::to_cbor
static std::vector< uint8_t > to_cbor(const json &j)
create a CBOR serialization of a given JSON value
wpi::detail::iter_impl::reference
typename std::conditional< std::is_const< BasicJsonType >::value, typename BasicJsonType::const_reference, typename BasicJsonType::reference >::type reference
defines a reference to the type iterated over (value_type)
Definition: json.h:1537
wpi::ArrayRef
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
Definition: ArrayRef.h:42
wpi::json::is_null
bool is_null() const noexcept
return whether value is null
Definition: json.h:3889
wpi::json::front
reference front()
access the first element
Definition: json.h:5125
wpi::detail::to_json_fn
Definition: json.h:1310
wpi::json::operator+=
reference operator+=(const json &val)
add an object to an array
Definition: json.h:6084
wpi::json::rend
const_reverse_iterator rend() const noexcept
returns a const reverse iterator to one before the first
Definition: json.h:5726
wpi::detail::iter_impl::operator*
reference operator*() const
return a reference to the value pointed to by the iterator
Definition: json.h:1677
wpi::json::operator>
friend bool operator>(const_reference lhs, const ScalarType rhs) noexcept
comparison: greater than
Definition: json.h:6838
wpi::detail::iteration_proxy
proxy class for the items() function
Definition: json.h:1479
wpi::json::merge_patch
void merge_patch(const json &patch)
applies a JSON Merge Patch
wpi::detail::json_reverse_iterator::value
reference value() const
return the value of an iterator
Definition: json.h:2262
wpi::json::array
static json array(initializer_list_t init={})
explicitly create an array from an initializer list
Definition: json.h:3374
wpi::detail::from_json_fn
Definition: json.h:990
wpi::json::parse_event_t::array_end
the parser read ] and finished processing a JSON array
wpi::detail::is_compatible_type
Definition: json.h:365
wpi::detail::internal_iterator::object_iterator
BasicJsonType::object_t::iterator object_iterator
iterator for JSON objects
Definition: json.h:1471
wpi::raw_istream
Definition: raw_istream.h:26
wpi::json::is_boolean
bool is_boolean() const noexcept
return whether value is a boolean
Definition: json.h:3911
wpi::json::update
void update(const_reference j)
updates a JSON object from another object, overwriting existing keys
wpi::detail::json_reverse_iterator
a template for a reverse iterator class
Definition: json.h:2184
wpi::json::parse
static json parse(StringRef s, const parser_callback_t cb=nullptr, const bool allow_exceptions=true)
deserialize from a compatible input
wpi::detail::primitive_iterator_t
Definition: json.h:1361
wpi::detail::json_reverse_iterator::json_reverse_iterator
json_reverse_iterator(const typename base_iterator::iterator_type &it) noexcept
create reverse iterator from iterator
Definition: json.h:2194
wpi::detail::exception
general exception of the json class
Definition: json.h:413
wpi::json::at
reference at(const json_pointer &ptr)
access specified element via JSON Pointer
Definition: json.h:7741
wpi::detail::value_t::string
string value
wpi::json::is_structured
bool is_structured() const noexcept
return whether type is structured
Definition: json.h:3867
wpi::json::object
static json object(initializer_list_t init={})
explicitly create an object from an initializer list
Definition: json.h:3417
wpi::detail::out_of_range
exception indicating access out of the defined range
Definition: json.h:631
wpi::detail::priority_tag< 0 >
Definition: json.h:216
wpi::json::count
size_type count(StringRef key) const
returns the number of occurrences of a key in a JSON object
wpi::json::max_size
size_type max_size() const noexcept
returns the maximum possible number of elements
wpi::json::get_ptr
PointerType get_ptr() noexcept
get a pointer value (implicit)
Definition: json.h:4481
wpi::json::operator[]
reference operator[](const json_pointer &ptr)
access specified element via JSON Pointer
Definition: json.h:7670
wpi::json::is_number_integer
bool is_number_integer() const noexcept
return whether value is an integer number
Definition: json.h:3970
wpi::json::parse_event_t::key
the parser read a key of a value in an object
wpi::json::rbegin
const_reverse_iterator rbegin() const noexcept
returns a const reverse iterator to the last element
Definition: json.h:5689
wpi::detail::primitive_iterator_t::is_begin
constexpr bool is_begin() const noexcept
return whether the iterator can be dereferenced
Definition: json.h:1390
wpi::json::rbegin
reverse_iterator rbegin() noexcept
returns an iterator to the reverse-beginning
Definition: json.h:5681
wpi::detail::iter_impl::value_type
typename BasicJsonType::value_type value_type
the type of the values when the iterator is dereferenced
Definition: json.h:1526
wpi::json::items
iteration_proxy< iterator > items() noexcept
helper to access iterator member functions in range-based for
Definition: json.h:5842
wpi::detail::json_reverse_iterator::operator--
json_reverse_iterator & operator--()
pre-decrement (–it)
Definition: json.h:2219
wpi::detail::has_to_json
Definition: json.h:341
wpi::json::emplace_back
void emplace_back(Args &&... args)
add an object to an array
Definition: json.h:6201
wpi::json::operator<=
friend bool operator<=(const_reference lhs, const ScalarType rhs) noexcept
comparison: less than or equal
Definition: json.h:6792
wpi::json::operator>=
friend bool operator>=(const_reference lhs, const_reference rhs) noexcept
comparison: greater than or equal
Definition: json.h:6873
wpi::json::from_ubjson
static json from_ubjson(raw_istream &is, const bool strict=true)
create a JSON value from an input in UBJSON format
wpi::detail::is_compatible_array_type
Definition: json.h:266
wpi::json::is_array
bool is_array() const noexcept
return whether value is an array
Definition: json.h:4070
wpi
WPILib C++ utilities (wpiutil) namespace.
Definition: Endian.h:31
wpi::json::at
reference at(size_type idx)
access specified array element with bounds checking
wpi::json::push_back
void push_back(const std::pair< T, U > &val)
add an object to an object
Definition: json.h:6111
wpi::detail::iteration_proxy::begin
iteration_proxy_internal begin() noexcept
return iterator begin (needed for range-based for)
Definition: json.h:2149
wpi::adl_serializer::from_json
static void from_json(BasicJsonType &&j, ValueType &val) noexcept(noexcept(::wpi::from_json(std::forward< BasicJsonType >(j), val)))
convert a JSON value to any value type
Definition: json.h:2570
wpi::detail::has_non_default_from_json
Definition: json.h:324
wpi::json::operator[]
reference operator[](T *key)
access specified object element
Definition: json.h:4890
wpi::detail::exception::id
const int id
the id of the exception
Definition: json.h:423
wpi::detail::value_t::array
array (ordered collection of values)
wpi::json::iterator
iter_impl< json > iterator
an iterator for a json container
Definition: json.h:2747
wpi::json::is_number_unsigned
bool is_number_unsigned() const noexcept
return whether value is an unsigned integer number
Definition: json.h:3998
wpi::detail::iter_impl::operator-
difference_type operator-(const iter_impl &other) const
return difference
Definition: json.h:1995
wpi::detail::operator<
bool operator<(const value_t lhs, const value_t rhs) noexcept
comparison operator for JSON types
Definition: json.h:724
wpi::detail::external_constructor
Definition: json.h:1038
wpi::json::operator+=
reference operator+=(const std::pair< T, U > &val)
add an object to an object
Definition: json.h:6136
wpi::detail::static_const
Definition: json.h:373
wpi::json::value
ValueType value(StringRef key, const ValueType &default_value) const
access specified object element with default value
Definition: json.h:5002
wpi::detail::is_compatible_complete_type
Definition: json.h:355
wpi::json::insert
iterator insert(const_iterator pos, const json &val)
inserts element
wpi::detail::iter_impl
a template for a bidirectional iterator for the json class
Definition: json.h:1502
wpi::detail::json_reverse_iterator::operator++
json_reverse_iterator & operator++()
pre-increment (++it)
Definition: json.h:2207
wpi::json::get_ref
ReferenceType get_ref()
get a reference value (implicit)
Definition: json.h:4558
wpi::json::to_ubjson
static std::vector< uint8_t > to_ubjson(const json &j, const bool use_size=false, const bool use_type=false)
create a UBJSON serialization of a given JSON value
wpi::detail::iter_impl::operator+=
iter_impl & operator+=(difference_type i)
add to iterator
Definition: json.h:1924
wpi::detail::is_complete_type
Definition: json.h:225
wpi::detail::iter_impl::operator+
iter_impl operator+(difference_type i) const
add to iterator
Definition: json.h:1962
wpi::json::back
reference back()
access the last element
Definition: json.h:5169
wpi::json::crbegin
const_reverse_iterator crbegin() const noexcept
returns a const reverse iterator to the last element
Definition: json.h:5755
wpi::json_pointer::json_pointer
json_pointer(const Twine &s={})
create JSON pointer
Definition: json.h:2351
wpi::detail::json_reverse_iterator::operator--
const json_reverse_iterator operator--(int)
post-decrement (it–)
Definition: json.h:2213
wpi::detail::value_t::object
object (unordered set of name/value pairs)
wpi::detail::iter_impl::operator++
const iter_impl operator++(int)
post-increment (it++)
Definition: json.h:1748
wpi::detail::iteration_proxy::iteration_proxy
iteration_proxy(typename IteratorType::reference cont) noexcept
construct iteration proxy from a container
Definition: json.h:2145
wpi::detail::value_t::number_float
number value (floating-point)
wpi::StringRef
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:49
wpi::json::at
const_reference at(const json_pointer &ptr) const
access specified element via JSON Pointer
Definition: json.h:7784
wpi::json_pointer::array_index
static int array_index(const Twine &s)
wpi::json::size_type
std::size_t size_type
a type to represent container sizes
Definition: json.h:2736
wpi::json::operator<<
friend raw_ostream & operator<<(raw_ostream &o, const json &j)
serialize to stream
wpi::json::json
json(const value_t v)
create an empty value with a given type
Definition: json.h:3160
wpi::json::operator[]
const_reference operator[](const json_pointer &ptr) const
access specified element via JSON Pointer
Definition: json.h:7698
wpi::detail::iter_impl::value
reference value() const
return the value of an iterator
Definition: json.h:2063
wpi::json::emplace
std::pair< iterator, bool > emplace(StringRef key, Args &&... args)
add an object to an object if key does not exist
Definition: json.h:6249
wpi::json::const_reverse_iterator
json_reverse_iterator< typename json::const_iterator > const_reverse_iterator
a const reverse iterator for a json container
Definition: json.h:2753
wpi::json::unflatten
json unflatten() const
unflatten a previously flattened JSON value
Definition: json.h:7848
wpi::detail::iter_impl::operator+
friend iter_impl operator+(difference_type i, const iter_impl &it)
addition of distance and iterator
Definition: json.h:1973
wpi::detail::is_json_nested_type
Definition: json.h:257
wpi::detail::is_compatible_integer_type_impl
Definition: json.h:280
wpi::json::clear
void clear() noexcept
clears the contents
wpi::json::find
iterator find(StringRef key)
find an element in a JSON object
wpi::detail::internal_iterator::primitive_iterator
primitive_iterator_t primitive_iterator
generic iterator for all other types
Definition: json.h:1475
wpi::detail::primitive_iterator_t::set_begin
void set_begin() noexcept
set iterator to a defined beginning
Definition: json.h:1378
wpi::json::json
json(std::nullptr_t=nullptr) noexcept
create a null object
Definition: json.h:3184
wpi::detail::parse_error
exception indicating a parse error
Definition: json.h:476
wpi::detail::iter_impl::operator-
iter_impl operator-(difference_type i) const
subtract from iterator
Definition: json.h:1984
wpi::json::meta
static json meta()
returns version information on the library
wpi::detail::iter_impl::operator=
iter_impl & operator=(const iter_impl< typename std::remove_const< BasicJsonType >::type > &other) noexcept
converting assignment
Definition: json.h:1597
wpi::json::get_ref
ReferenceType get_ref() const
get a reference value (implicit)
Definition: json.h:4571
wpi::detail::iter_impl::difference_type
typename BasicJsonType::difference_type difference_type
a type to represent differences between iterators
Definition: json.h:1528
wpi::detail::is_compatible_object_type_impl
Definition: json.h:236
wpi::detail::iter_impl::iterator_category
std::bidirectional_iterator_tag iterator_category
The std::iterator class template (used as a base class to provide typedefs) is deprecated in C++17.
Definition: json.h:1523
wpi::json::operator<=
friend bool operator<=(const_reference lhs, const_reference rhs) noexcept
comparison: less than or equal
Definition: json.h:6781
wpi::json::get
json get() const
get special-case overload
Definition: json.h:4299
wpi::detail::priority_tag
Definition: json.h:215
wpi::json::operator>
friend bool operator>(const ScalarType lhs, const_reference rhs) noexcept
comparison: greater than
Definition: json.h:6849
wpi::json::empty
bool empty() const noexcept
checks whether the container is empty.
wpi::detail::json_ref
Definition: json.h:2270
wpi::detail::iter_impl::operator->
pointer operator->() const
dereference the iterator
Definition: json.h:1714
wpi::json::get
ValueType get() const noexcept(noexcept(adl_serializer< ValueType, void >::from_json(std::declval< const json_t & >(), std::declval< ValueType & >())))
get a value (explicit)
Definition: json.h:4349
wpi::json::operator==
friend bool operator==(const_reference lhs, const_reference rhs) noexcept
comparison: equal
wpi::StringMap
StringMap - This is an unconventional map that is specialized for handling keys that are "strings",...
Definition: StringMap.h:206
wpi::json::push_back
void push_back(json &&val)
add an object to an array
wpi::json::parser_callback_t
std::function< bool(int depth, parse_event_t event, json &parsed)> parser_callback_t
per-element parser callback type
Definition: json.h:3119
wpi::json::~json
~json() noexcept
destructor
Definition: json.h:3719
wpi::json::json
json(CompatibleType &&val) noexcept(noexcept(adl_serializer< U, void >::to_json(std::declval< json_t & >(), std::forward< CompatibleType >(val))))
create a JSON value
Definition: json.h:3251
wpi::json::is_number
bool is_number() const noexcept
return whether value is a number
Definition: json.h:3941
wpi::detail::iter_impl::operator<
bool operator<(const iter_impl &other) const
comparison: smaller
Definition: json.h:1870
wpi::json_pointer::to_string
std::string to_string() const noexcept
return a string representation of the JSON pointer
wpi::json::initializer_list_t
std::initializer_list< detail::json_ref< json > > initializer_list_t
helper type for initializer lists of json values
Definition: json.h:2690
wpi::detail::iter_impl::operator>
bool operator>(const iter_impl &other) const
comparison: greater than
Definition: json.h:1906
wpi::json::operator<
friend bool operator<(const_reference lhs, const ScalarType rhs) noexcept
comparison: less than
Definition: json.h:6746
wpi::json::reference
value_type & reference
the type of an element reference
Definition: json.h:2729
wpi::json::get
PointerType get() noexcept
get a pointer value (explicit)
Definition: json.h:4436
wpi::json::is_string
bool is_string() const noexcept
return whether value is a string
Definition: json.h:4092
wpi::json::crend
const_reverse_iterator crend() const noexcept
returns a const reverse iterator to one before the first
Definition: json.h:5784
wpi::json::to_msgpack
static std::vector< uint8_t > to_msgpack(const json &j)
create a MessagePack serialization of a given JSON value
wpi::detail::iter_impl::operator--
iter_impl & operator--()
pre-decrement (–it)
Definition: json.h:1802
wpi::detail::iter_impl::operator!=
bool operator!=(const iter_impl &other) const
comparison: not equal
Definition: json.h:1861
wpi::json::operator[]
const_reference operator[](T *key) const
read-only access specified object element
Definition: json.h:4940
wpi::detail::iter_impl::key
StringRef key() const
return the key of an object iterator
Definition: json.h:2047
wpi::json::parse_event_t
parse_event_t
parser event types
Definition: json.h:3053
wpi::json::back
const_reference back() const
access the last element
Definition: json.h:5179
wpi::json::get_ptr
const PointerType get_ptr() const noexcept
get a pointer value (implicit)
Definition: json.h:4509
wpi::json::operator!=
friend bool operator!=(const ScalarType lhs, const_reference rhs) noexcept
comparison: not equal
Definition: json.h:6707
wpi::json::rend
reverse_iterator rend() noexcept
returns an iterator to the reverse-end
Definition: json.h:5718
wpi::json::get
ValueType get() const noexcept(noexcept(adl_serializer< ValueTypeCV, void >::from_json(std::declval< const json_t & >())))
get a value (explicit); special case
Definition: json.h:4400
wpi::json::is_number_float
bool is_number_float() const noexcept
return whether value is a floating-point number
Definition: json.h:4026
wpi::detail::type_error
exception indicating executing a member function with a wrong type
Definition: json.h:590
wpi::detail::json_reverse_iterator::operator-
difference_type operator-(const json_reverse_iterator &other) const
return difference
Definition: json.h:2243
wpi::json::json_pointer
::wpi::json_pointer json_pointer
Definition: json.h:2686
wpi::json::operator=
reference & operator=(json other) noexcept(std::is_nothrow_move_constructible< value_t >::value and std::is_nothrow_move_assignable< value_t >::value and std::is_nothrow_move_constructible< json_value >::value and std::is_nothrow_move_assignable< json_value >::value)
copy assignment
Definition: json.h:3686
wpi::json::is_object
bool is_object() const noexcept
return whether value is an object
Definition: json.h:4048
wpi::detail::parse_error::byte
const std::size_t byte
byte index of the parse error
Definition: json.h:498
wpi::json::json
json(InputIT first, InputIT last)
construct a JSON container given an iterator range
Definition: json.h:3504
wpi::detail::internal_iterator::array_iterator
BasicJsonType::array_t::iterator array_iterator
iterator for JSON arrays
Definition: json.h:1473
wpi::json::patch
json patch(const json &json_patch) const
applies a JSON patch
wpi::json::operator>>
friend raw_istream & operator>>(raw_istream &i, json &j)
deserialize from stream
wpi::detail::is_compatible_object_type
Definition: json.h:247
wpi::json_pointer
Definition: json.h:2323
wpi::json::reverse_iterator
json_reverse_iterator< typename json::iterator > reverse_iterator
a reverse iterator for a json container
Definition: json.h:2751
wpi::json::operator[]
reference operator[](size_type idx)
access specified array element
wpi::detail::has_from_json
Definition: json.h:307
wpi::json::from_cbor
static json from_cbor(raw_istream &is, const bool strict=true)
create a JSON value from an input in CBOR format
wpi::raw_ostream
This class implements an extremely fast bulk output stream that can only output to a stream.
Definition: raw_ostream.h:47
wpi::json::parse_event_t::array_start
the parser read [ and started to process a JSON array
wpi::detail::json_reverse_iterator::operator+
json_reverse_iterator operator+(difference_type i) const
add to iterator
Definition: json.h:2231
wpi::json::items
iteration_proxy< const_iterator > items() const noexcept
helper to access iterator member functions in range-based for
Definition: json.h:5850
wpi::detail::other_error
exception indicating other library errors
Definition: json.h:664
wpi::Twine
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
Definition: Twine.h:85
wpi::detail::value_t::number_integer
number value (signed integer)
wpi::json::begin
const_iterator begin() const noexcept
returns a const iterator to the first element
Definition: json.h:5550
wpi::json::value
std::string value(StringRef key, const char *default_value) const
overload for a default value of type const char*
Definition: json.h:5024
wpi::detail::iter_impl::operator==
bool operator==(const iter_impl &other) const
comparison: equal
Definition: json.h:1834
wpi::detail::iter_impl::operator[]
reference operator[](difference_type n) const
access to successor
Definition: json.h:2016
wpi::json::operator<
friend bool operator<(const_reference lhs, const_reference rhs) noexcept
comparison: less than
wpi::json::operator==
friend bool operator==(const_reference lhs, const ScalarType rhs) noexcept
comparison: equal
Definition: json.h:6651
wpi::detail::json_reverse_iterator::operator[]
reference operator[](difference_type n) const
access to successor
Definition: json.h:2249
wpi::detail::iter_impl::operator<=
bool operator<=(const iter_impl &other) const
comparison: less than or equal
Definition: json.h:1897
wpi::json::swap
void swap(reference other) noexcept(std::is_nothrow_move_constructible< value_t >::value and std::is_nothrow_move_assignable< value_t >::value and std::is_nothrow_move_constructible< json_value >::value and std::is_nothrow_move_assignable< json_value >::value)
exchanges the values
Definition: json.h:6483
wpi::json::object_t
StringMap< json > object_t
a type for an object
Definition: json.h:2863
wpi::json::allocator_type
std::allocator< json > allocator_type
the allocator type
Definition: json.h:2739
wpi::json::dump
std::string dump(const int indent=-1, const char indent_char=' ', const bool ensure_ascii=false) const
serialization
wpi::json::erase
void erase(IteratorType pos)
remove element given an iterator
Definition: json.h:5234
wpi::json::operator>=
friend bool operator>=(const_reference lhs, const ScalarType rhs) noexcept
comparison: greater than or equal
Definition: json.h:6884
wpi::detail::iter_impl::pointer
typename std::conditional< std::is_const< BasicJsonType >::value, typename BasicJsonType::const_pointer, typename BasicJsonType::pointer >::type pointer
defines a pointer to the type iterated over (value_type)
Definition: json.h:1532
wpi::detail::json_reverse_iterator::json_reverse_iterator
json_reverse_iterator(const base_iterator &it) noexcept
create reverse iterator from base class
Definition: json.h:2198
wpi::json::operator<
friend bool operator<(const ScalarType lhs, const_reference rhs) noexcept
comparison: less than
Definition: json.h:6757
wpi::json::diff
static json diff(const json &source, const json &target, const std::string &path="")
creates a diff as a JSON patch
wpi::detail::primitive_iterator_t::is_end
constexpr bool is_end() const noexcept
return whether the iterator is at end
Definition: json.h:1396
wpi::adl_serializer::to_json
static void to_json(BasicJsonType &j, ValueType &&val) noexcept(noexcept(::wpi::to_json(j, std::forward< ValueType >(val))))
convert any value type to a JSON value
Definition: json.h:2586
wpi::json::operator==
friend bool operator==(const ScalarType lhs, const_reference rhs) noexcept
comparison: equal
Definition: json.h:6662
wpi::detail::is_json
Definition: json.h:203
wpi::detail::iter_impl::operator++
iter_impl & operator++()
pre-increment (++it)
Definition: json.h:1759
wpi::json::size
size_type size() const noexcept
returns the number of elements
std::less< ::wpi::detail::value_t >::operator()
bool operator()(wpi::detail::value_t lhs, wpi::detail::value_t rhs) const noexcept
compare two value_t enum values
Definition: json.h:8053
wpi::json::type_name
const char * type_name() const noexcept
return the type as string