WPILibC++  2019.3.1
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Modules Pages
json.h
1 /*----------------------------------------------------------------------------*/
2 /* Modifications Copyright (c) 2017-2018 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 
166 // C++ language standard detection
167 #if (defined(__cplusplus) && __cplusplus >= 201703L) || (defined(_HAS_CXX17) && _HAS_CXX17 == 1) // fix for issue #464
168  #define JSON_HAS_CPP_17
169  #define JSON_HAS_CPP_14
170 #elif (defined(__cplusplus) && __cplusplus >= 201402L) || (defined(_HAS_CXX14) && _HAS_CXX14 == 1)
171  #define JSON_HAS_CPP_14
172 #endif
173 
184 #define NLOHMANN_JSON_HAS_HELPER(type) \
185  template<typename T> struct has_##type { \
186  private: \
187  template<typename U, typename = typename U::type> \
188  static int detect(U &&); \
189  static void detect(...); \
190  public: \
191  static constexpr bool value = \
192  std::is_integral<decltype(detect(std::declval<T>()))>::value; \
193  }
194 
195 namespace wpi
196 {
205 namespace detail
206 {
208 // helpers //
210 
211 template<typename> struct is_json : std::false_type {};
212 
213 template<> struct is_json<json> : std::true_type {};
214 
215 // alias templates to reduce boilerplate
216 template<bool B, typename T = void>
217 using enable_if_t = typename std::enable_if<B, T>::type;
218 
219 template<typename T>
220 using uncvref_t = typename std::remove_cv<typename std::remove_reference<T>::type>::type;
221 
222 // implementation of C++14 index_sequence and affiliates
223 // source: https://stackoverflow.com/a/32223343
224 template<std::size_t... Ints>
226 {
227  using type = index_sequence;
228  using value_type = std::size_t;
229  static constexpr std::size_t size() noexcept
230  {
231  return sizeof...(Ints);
232  }
233 };
234 
235 template<class Sequence1, class Sequence2>
237 
238 template<std::size_t... I1, std::size_t... I2>
240  : index_sequence < I1..., (sizeof...(I1) + I2)... > {};
241 
242 template<std::size_t N>
244  : merge_and_renumber < typename make_index_sequence < N / 2 >::type,
245  typename make_index_sequence < N - N / 2 >::type > {};
246 
247 template<> struct make_index_sequence<0> : index_sequence<> {};
248 template<> struct make_index_sequence<1> : index_sequence<0> {};
249 
250 template<typename... Ts>
251 using index_sequence_for = make_index_sequence<sizeof...(Ts)>;
252 
253 /*
254 Implementation of two C++17 constructs: conjunction, negation. This is needed
255 to avoid evaluating all the traits in a condition
256 
257 For example: not std::is_same<void, T>::value and has_value_type<T>::value
258 will not compile when T = void (on MSVC at least). Whereas
259 conjunction<negation<std::is_same<void, T>>, has_value_type<T>>::value will
260 stop evaluating if negation<...>::value == false
261 
262 Please note that those constructs must be used with caution, since symbols can
263 become very long quickly (which can slow down compilation and cause MSVC
264 internal compiler errors). Only use it when you have to (see example ahead).
265 */
266 template<class...> struct conjunction : std::true_type {};
267 template<class B1> struct conjunction<B1> : B1 {};
268 template<class B1, class... Bn>
269 struct conjunction<B1, Bn...> : std::conditional<bool(B1::value), conjunction<Bn...>, B1>::type {};
270 
271 template<class B> struct negation : std::integral_constant<bool, not B::value> {};
272 
273 // dispatch utility (taken from ranges-v3)
274 template<unsigned N> struct priority_tag : priority_tag < N - 1 > {};
275 template<> struct priority_tag<0> {};
276 
278 // has_/is_ functions //
280 
281 // source: https://stackoverflow.com/a/37193089/4116453
282 
283 template <typename T, typename = void>
284 struct is_complete_type : std::false_type {};
285 
286 template <typename T>
287 struct is_complete_type<T, decltype(void(sizeof(T)))> : std::true_type {};
288 
289 NLOHMANN_JSON_HAS_HELPER(mapped_type);
290 NLOHMANN_JSON_HAS_HELPER(key_type);
291 NLOHMANN_JSON_HAS_HELPER(value_type);
292 NLOHMANN_JSON_HAS_HELPER(iterator);
293 
294 template<bool B, class RealType, class CompatibleObjectType>
295 struct is_compatible_object_type_impl : std::false_type {};
296 
297 template<class RealType, class CompatibleObjectType>
298 struct is_compatible_object_type_impl<true, RealType, CompatibleObjectType>
299 {
300  static constexpr auto value =
301  std::is_constructible<StringRef, typename CompatibleObjectType::key_type>::value and
302  std::is_constructible<typename RealType::mapped_type, typename CompatibleObjectType::mapped_type>::value;
303 };
304 
305 template<class BasicJsonType, class CompatibleObjectType>
307 {
308  static auto constexpr value = is_compatible_object_type_impl <
310  has_mapped_type<CompatibleObjectType>,
311  has_key_type<CompatibleObjectType>>::value,
312  typename BasicJsonType::object_t, CompatibleObjectType >::value;
313 };
314 
315 template<typename BasicJsonType, typename T>
317 {
318  static auto constexpr value = std::is_same<T, typename BasicJsonType::iterator>::value or
319  std::is_same<T, typename BasicJsonType::const_iterator>::value or
320  std::is_same<T, typename BasicJsonType::reverse_iterator>::value or
321  std::is_same<T, typename BasicJsonType::const_reverse_iterator>::value;
322 };
323 
324 template<class BasicJsonType, class CompatibleArrayType>
326 {
327  static auto constexpr value =
330  BasicJsonType, CompatibleArrayType>>,
331  negation<std::is_constructible<StringRef,
332  CompatibleArrayType>>,
334  has_value_type<CompatibleArrayType>,
335  has_iterator<CompatibleArrayType>>::value;
336 };
337 
338 template<bool, typename, typename>
339 struct is_compatible_integer_type_impl : std::false_type {};
340 
341 template<typename RealIntegerType, typename CompatibleNumberIntegerType>
342 struct is_compatible_integer_type_impl<true, RealIntegerType, CompatibleNumberIntegerType>
343 {
344  // is there an assert somewhere on overflows?
345  using RealLimits = std::numeric_limits<RealIntegerType>;
346  using CompatibleLimits = std::numeric_limits<CompatibleNumberIntegerType>;
347 
348  static constexpr auto value =
349  std::is_constructible<RealIntegerType, CompatibleNumberIntegerType>::value and
350  CompatibleLimits::is_integer and
351  RealLimits::is_signed == CompatibleLimits::is_signed;
352 };
353 
354 template<typename RealIntegerType, typename CompatibleNumberIntegerType>
356 {
357  static constexpr auto value =
359  std::is_integral<CompatibleNumberIntegerType>::value and
360  not std::is_same<bool, CompatibleNumberIntegerType>::value,
361  RealIntegerType, CompatibleNumberIntegerType > ::value;
362 };
363 
364 // trait checking if JSONSerializer<T>::from_json(json const&, udt&) exists
365 template<typename BasicJsonType, typename T>
367 {
368  private:
369  // also check the return type of from_json
370  template<typename U, typename = enable_if_t<std::is_same<void, decltype(uncvref_t<U>::from_json(
371  std::declval<BasicJsonType>(), std::declval<T&>()))>::value>>
372  static int detect(U&&);
373  static void detect(...);
374 
375  public:
376  static constexpr bool value = std::is_integral<decltype(
377  detect(std::declval<typename BasicJsonType::template json_serializer<T, void>>()))>::value;
378 };
379 
380 // This trait checks if JSONSerializer<T>::from_json(json const&) exists
381 // this overload is used for non-default-constructible user-defined-types
382 template<typename BasicJsonType, typename T>
384 {
385  private:
386  template <
387  typename U,
388  typename = enable_if_t<std::is_same<
389  T, decltype(uncvref_t<U>::from_json(std::declval<BasicJsonType>()))>::value >>
390  static int detect(U&&);
391  static void detect(...);
392 
393  public:
394  static constexpr bool value = std::is_integral<decltype(detect(
395  std::declval<typename BasicJsonType::template json_serializer<T, void>>()))>::value;
396 };
397 
398 // This trait checks if BasicJsonType::json_serializer<T>::to_json exists
399 template<typename BasicJsonType, typename T>
401 {
402  private:
403  template<typename U, typename = decltype(uncvref_t<U>::to_json(
404  std::declval<BasicJsonType&>(), std::declval<T>()))>
405  static int detect(U&&);
406  static void detect(...);
407 
408  public:
409  static constexpr bool value = std::is_integral<decltype(detect(
410  std::declval<typename BasicJsonType::template json_serializer<T, void>>()))>::value;
411 };
412 
413 template <typename BasicJsonType, typename CompatibleCompleteType>
415 {
416  static constexpr bool value =
417  not std::is_base_of<std::istream, CompatibleCompleteType>::value and
421 };
422 
423 template <typename BasicJsonType, typename CompatibleType>
425  : conjunction<is_complete_type<CompatibleType>,
426  is_compatible_complete_type<BasicJsonType, CompatibleType>>
427 {
428 };
429 
430 // taken from ranges-v3
431 template<typename T>
433 {
434  static constexpr T value{};
435 };
436 
437 template<typename T>
438 constexpr T static_const<T>::value;
439 
441 // exceptions //
443 
472 class exception : public std::exception
473 {
474  public:
476  const char* what() const noexcept override
477  {
478  return m.what();
479  }
480 
482  const int id;
483 
484  protected:
485  exception(int id_, const Twine& what_arg);
486 
487  private:
489  std::runtime_error m;
490 };
491 
535 class parse_error : public exception
536 {
537  public:
546  static parse_error create(int id_, std::size_t byte_, const Twine& what_arg);
547 
557  const std::size_t byte;
558 
559  private:
560  parse_error(int id_, std::size_t byte_, const Twine& what_arg)
561  : exception(id_, what_arg), byte(byte_) {}
562 };
563 
602 {
603  public:
604  static invalid_iterator create(int id_, const Twine& what_arg);
605 
606  private:
607  invalid_iterator(int id_, const Twine& what_arg)
608  : exception(id_, what_arg) {}
609 };
610 
649 class type_error : public exception
650 {
651  public:
652  static type_error create(int id_, const Twine& what_arg);
653 
654  private:
655  type_error(int id_, const Twine& what_arg) : exception(id_, what_arg) {}
656 };
657 
690 class out_of_range : public exception
691 {
692  public:
693  static out_of_range create(int id_, const Twine& what_arg);
694 
695  private:
696  out_of_range(int id_, const Twine& what_arg) : exception(id_, what_arg) {}
697 };
698 
723 class other_error : public exception
724 {
725  public:
726  static other_error create(int id_, const Twine& what_arg);
727 
728  private:
729  other_error(int id_, const Twine& what_arg) : exception(id_, what_arg) {}
730 };
731 
733 // JSON type enumeration //
735 
760 enum class value_t : std::uint8_t
761 {
762  null,
763  object,
764  array,
765  string,
766  boolean,
769  number_float,
770  discarded
771 };
772 
783 inline bool operator<(const value_t lhs, const value_t rhs) noexcept
784 {
785  static constexpr std::array<std::uint8_t, 8> order = {{
786  0 /* null */, 3 /* object */, 4 /* array */, 5 /* string */,
787  1 /* boolean */, 2 /* integer */, 2 /* unsigned */, 2 /* float */
788  }
789  };
790 
791  const auto l_index = static_cast<std::size_t>(lhs);
792  const auto r_index = static_cast<std::size_t>(rhs);
793  return l_index < order.size() and r_index < order.size() and order[l_index] < order[r_index];
794 }
795 
796 // overloads for json template parameters
797 template<typename BasicJsonType, typename ArithmeticType,
798  enable_if_t<std::is_arithmetic<ArithmeticType>::value and
799  not std::is_same<ArithmeticType, bool>::value,
800  int> = 0>
801 void get_arithmetic_value(const BasicJsonType& j, ArithmeticType& val)
802 {
803  switch (static_cast<value_t>(j))
804  {
806  {
807  val = static_cast<ArithmeticType>(*j.template get_ptr<const uint64_t*>());
808  break;
809  }
811  {
812  val = static_cast<ArithmeticType>(*j.template get_ptr<const int64_t*>());
813  break;
814  }
816  {
817  val = static_cast<ArithmeticType>(*j.template get_ptr<const double*>());
818  break;
819  }
820 
821  default:
822  JSON_THROW(type_error::create(302, "type must be number, but is " + Twine(j.type_name())));
823  }
824 }
825 
826 template<typename BasicJsonType>
827 void from_json(const BasicJsonType& j, bool& b)
828 {
829  if (JSON_UNLIKELY(not j.is_boolean()))
830  {
831  JSON_THROW(type_error::create(302, "type must be boolean, but is " + Twine(j.type_name())));
832  }
833  b = *j.template get_ptr<const bool*>();
834 }
835 
836 template<typename BasicJsonType>
837 void from_json(const BasicJsonType& j, std::string& s)
838 {
839  if (JSON_UNLIKELY(not j.is_string()))
840  {
841  JSON_THROW(type_error::create(302, "type must be string, but is " + Twine(j.type_name())));
842  }
843  s = *j.template get_ptr<const std::string*>();
844 }
845 
846 template<typename BasicJsonType>
847 void from_json(const BasicJsonType& j, double& val)
848 {
849  get_arithmetic_value(j, val);
850 }
851 
852 template<typename BasicJsonType>
853 void from_json(const BasicJsonType& j, uint64_t& val)
854 {
855  get_arithmetic_value(j, val);
856 }
857 
858 template<typename BasicJsonType>
859 void from_json(const BasicJsonType& j, int64_t& val)
860 {
861  get_arithmetic_value(j, val);
862 }
863 
864 template<typename BasicJsonType, typename EnumType,
865  enable_if_t<std::is_enum<EnumType>::value, int> = 0>
866 void from_json(const BasicJsonType& j, EnumType& e)
867 {
868  typename std::underlying_type<EnumType>::type val;
869  get_arithmetic_value(j, val);
870  e = static_cast<EnumType>(val);
871 }
872 
873 template<typename BasicJsonType>
874 void from_json(const BasicJsonType& j, typename BasicJsonType::array_t& arr)
875 {
876  if (JSON_UNLIKELY(not j.is_array()))
877  {
878  JSON_THROW(type_error::create(302, "type must be array, but is " + Twine(j.type_name())));
879  }
880  arr = *j.template get_ptr<const typename BasicJsonType::array_t*>();
881 }
882 
883 template<typename BasicJsonType, typename CompatibleArrayType>
884 void from_json_array_impl(const BasicJsonType& j, CompatibleArrayType& arr, priority_tag<0> /*unused*/)
885 {
886  using std::end;
887 
888  std::transform(j.begin(), j.end(),
889  std::inserter(arr, end(arr)), [](const BasicJsonType & i)
890  {
891  // get<BasicJsonType>() returns *this, this won't call a from_json
892  // method when value_type is BasicJsonType
893  return i.template get<typename CompatibleArrayType::value_type>();
894  });
895 }
896 
897 template<typename BasicJsonType, typename CompatibleArrayType>
898 auto from_json_array_impl(const BasicJsonType& j, CompatibleArrayType& arr, priority_tag<1> /*unused*/)
899 -> decltype(
900  arr.reserve(std::declval<typename CompatibleArrayType::size_type>()),
901  void())
902 {
903  using std::end;
904 
905  arr.reserve(j.size());
906  std::transform(j.begin(), j.end(),
907  std::inserter(arr, end(arr)), [](const BasicJsonType & i)
908  {
909  // get<BasicJsonType>() returns *this, this won't call a from_json
910  // method when value_type is BasicJsonType
911  return i.template get<typename CompatibleArrayType::value_type>();
912  });
913 }
914 
915 template<typename BasicJsonType, typename T, std::size_t N>
916 void from_json_array_impl(const BasicJsonType& j, std::array<T, N>& arr, priority_tag<2> /*unused*/)
917 {
918  for (std::size_t i = 0; i < N; ++i)
919  {
920  arr[i] = j.at(i).template get<T>();
921  }
922 }
923 
924 template <
925  typename BasicJsonType, typename CompatibleArrayType,
926  enable_if_t <
927  is_compatible_array_type<BasicJsonType, CompatibleArrayType>::value and
928  not std::is_same<typename BasicJsonType::array_t,
929  CompatibleArrayType>::value and
930  std::is_constructible <
931  BasicJsonType, typename CompatibleArrayType::value_type >::value,
932  int > = 0 >
933 void from_json(const BasicJsonType& j, CompatibleArrayType& arr)
934 {
935  if (JSON_UNLIKELY(not j.is_array()))
936  {
937  JSON_THROW(type_error::create(302, "type must be array, but is " +
938  Twine(j.type_name())));
939  }
940 
941  from_json_array_impl(j, arr, priority_tag<2> {});
942 }
943 
944 template<typename BasicJsonType>
945 inline
946 void from_json(const BasicJsonType& j, typename BasicJsonType::object_t& obj)
947 {
948  if (!j.is_object())
949  {
950  JSON_THROW(type_error::create(302, "type must be object, but is " + Twine(j.type_name())));
951  }
952 
953  auto inner_object = j.template get_ptr<const typename BasicJsonType::object_t*>();
954  for (const auto& i : *inner_object) {
955  obj.try_emplace(i.first(), i.second);
956  }
957 }
958 
959 template<typename BasicJsonType, typename CompatibleObjectType,
960  enable_if_t<is_compatible_object_type<BasicJsonType, CompatibleObjectType>::value and
961  not std::is_same<typename BasicJsonType::object_t, CompatibleObjectType>::value, int> = 0>
962 void from_json(const BasicJsonType& j, CompatibleObjectType& obj)
963 {
964  if (JSON_UNLIKELY(not j.is_object()))
965  {
966  JSON_THROW(type_error::create(302, "type must be object, but is " + Twine(j.type_name())));
967  }
968 
969  auto inner_object = j.template get_ptr<const typename BasicJsonType::object_t*>();
970  using std::begin;
971  using std::end;
972  using value_type = typename CompatibleObjectType::value_type;
973  std::vector<value_type> v;
974  v.reserve(j.size());
975  for (const auto& p : *inner_object)
976  {
977  v.emplace_back(
978  p.first(),
979  p.second
980  .template get<typename CompatibleObjectType::mapped_type>());
981  }
982  // we could avoid the assignment, but this might require a for loop, which
983  // might be less efficient than the container constructor for some
984  // containers (would it?)
985  obj = CompatibleObjectType(std::make_move_iterator(begin(v)),
986  std::make_move_iterator(end(v)));
987 }
988 
989 // overload for arithmetic types, not chosen for json template arguments
990 // (BooleanType, etc..); note: Is it really necessary to provide explicit
991 // overloads for bool etc. in case of a custom BooleanType which is not
992 // an arithmetic type?
993 template<typename BasicJsonType, typename ArithmeticType,
994  enable_if_t <
995  std::is_arithmetic<ArithmeticType>::value and
996  not std::is_same<ArithmeticType, uint64_t>::value and
997  not std::is_same<ArithmeticType, int64_t>::value and
998  not std::is_same<ArithmeticType, double>::value and
999  not std::is_same<ArithmeticType, bool>::value,
1000  int> = 0>
1001 void from_json(const BasicJsonType& j, ArithmeticType& val)
1002 {
1003  switch (static_cast<value_t>(j))
1004  {
1006  {
1007  val = static_cast<ArithmeticType>(*j.template get_ptr<const uint64_t*>());
1008  break;
1009  }
1011  {
1012  val = static_cast<ArithmeticType>(*j.template get_ptr<const int64_t*>());
1013  break;
1014  }
1015  case value_t::number_float:
1016  {
1017  val = static_cast<ArithmeticType>(*j.template get_ptr<const double*>());
1018  break;
1019  }
1020  case value_t::boolean:
1021  {
1022  val = static_cast<ArithmeticType>(*j.template get_ptr<const bool*>());
1023  break;
1024  }
1025 
1026  default:
1027  JSON_THROW(type_error::create(302, "type must be number, but is " + Twine(j.type_name())));
1028  }
1029 }
1030 
1031 template<typename BasicJsonType, typename A1, typename A2>
1032 void from_json(const BasicJsonType& j, std::pair<A1, A2>& p)
1033 {
1034  p = {j.at(0).template get<A1>(), j.at(1).template get<A2>()};
1035 }
1036 
1037 template<typename BasicJsonType, typename Tuple, std::size_t... Idx>
1038 void from_json_tuple_impl(const BasicJsonType& j, Tuple& t, index_sequence<Idx...>)
1039 {
1040  t = std::make_tuple(j.at(Idx).template get<typename std::tuple_element<Idx, Tuple>::type>()...);
1041 }
1042 
1043 template<typename BasicJsonType, typename... Args>
1044 void from_json(const BasicJsonType& j, std::tuple<Args...>& t)
1045 {
1046  from_json_tuple_impl(j, t, index_sequence_for<Args...> {});
1047 }
1048 
1050 {
1051  private:
1052  template<typename BasicJsonType, typename T>
1053  auto call(const BasicJsonType& j, T& val, priority_tag<1> /*unused*/) const
1054  noexcept(noexcept(from_json(j, val)))
1055  -> decltype(from_json(j, val), void())
1056  {
1057  return from_json(j, val);
1058  }
1059 
1060  template<typename BasicJsonType, typename T>
1061  void call(const BasicJsonType& /*unused*/, T& /*unused*/, priority_tag<0> /*unused*/) const noexcept
1062  {
1063  static_assert(sizeof(BasicJsonType) == 0,
1064  "could not find from_json() method in T's namespace");
1065 #ifdef _MSC_VER
1066  // MSVC does not show a stacktrace for the above assert
1067  using decayed = uncvref_t<T>;
1068  static_assert(sizeof(typename decayed::force_msvc_stacktrace) == 0,
1069  "forcing MSVC stacktrace to show which T we're talking about.");
1070 #endif
1071  }
1072 
1073  public:
1074  template<typename BasicJsonType, typename T>
1075  void operator()(const BasicJsonType& j, T& val) const
1076  noexcept(noexcept(std::declval<from_json_fn>().call(j, val, priority_tag<1> {})))
1077  {
1078  return call(j, val, priority_tag<1> {});
1079  }
1080 };
1081 }
1082 
1083 // namespace to hold default `from_json` function
1084 // to see why this is required:
1085 // http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/n4381.html
1086 namespace
1087 {
1088 constexpr const auto& from_json = detail::static_const<detail::from_json_fn>::value;
1089 }
1090 
1091 namespace detail
1092 {
1094 // constructors //
1096 
1097 template<value_t> struct external_constructor;
1098 
1099 template<>
1101 {
1102  template<typename BasicJsonType>
1103  static void construct(BasicJsonType& j, bool b) noexcept
1104  {
1105  j.m_type = value_t::boolean;
1106  j.m_value = b;
1107  j.assert_invariant();
1108  }
1109 };
1110 
1111 template<>
1113 {
1114  template<typename BasicJsonType>
1115  static void construct(BasicJsonType& j, StringRef s)
1116  {
1117  j.m_type = value_t::string;
1118  j.m_value = s;
1119  j.assert_invariant();
1120  }
1121 
1122  template<typename BasicJsonType, typename T,
1123  enable_if_t<std::is_same<std::string, T>::value, int> = 0>
1124  static void construct(BasicJsonType& j, T&& s)
1125  {
1126  j.m_type = value_t::string;
1127  j.m_value = std::move(s);
1128  j.assert_invariant();
1129  }
1130 };
1131 
1132 template<>
1134 {
1135  template<typename BasicJsonType>
1136  static void construct(BasicJsonType& j, double val) noexcept
1137  {
1138  j.m_type = value_t::number_float;
1139  j.m_value = val;
1140  j.assert_invariant();
1141  }
1142 };
1143 
1144 template<>
1146 {
1147  template<typename BasicJsonType>
1148  static void construct(BasicJsonType& j, uint64_t val) noexcept
1149  {
1150  j.m_type = value_t::number_unsigned;
1151  j.m_value = val;
1152  j.assert_invariant();
1153  }
1154 };
1155 
1156 template<>
1158 {
1159  template<typename BasicJsonType>
1160  static void construct(BasicJsonType& j, int64_t val) noexcept
1161  {
1162  j.m_type = value_t::number_integer;
1163  j.m_value = val;
1164  j.assert_invariant();
1165  }
1166 };
1167 
1168 template<>
1170 {
1171  template<typename BasicJsonType>
1172  static void construct(BasicJsonType& j, const typename BasicJsonType::array_t& arr)
1173  {
1174  j.m_type = value_t::array;
1175  j.m_value = arr;
1176  j.assert_invariant();
1177  }
1178 
1179  template<typename BasicJsonType>
1180  static void construct(BasicJsonType& j, typename BasicJsonType::array_t&& arr)
1181  {
1182  j.m_type = value_t::array;
1183  j.m_value = std::move(arr);
1184  j.assert_invariant();
1185  }
1186 
1187  template<typename BasicJsonType, typename T>
1188  static void construct(BasicJsonType& j, ArrayRef<T> arr)
1189  {
1190  using std::begin;
1191  using std::end;
1192  j.m_type = value_t::array;
1193  j.m_value.array = j.template create<typename BasicJsonType::array_t>(begin(arr), end(arr));
1194  j.assert_invariant();
1195  }
1196 
1197  template<typename BasicJsonType, typename CompatibleArrayType,
1198  enable_if_t<not std::is_same<CompatibleArrayType, typename BasicJsonType::array_t>::value,
1199  int> = 0>
1200  static void construct(BasicJsonType& j, const CompatibleArrayType& arr)
1201  {
1202  using std::begin;
1203  using std::end;
1204  j.m_type = value_t::array;
1205  j.m_value.array = j.template create<typename BasicJsonType::array_t>(begin(arr), end(arr));
1206  j.assert_invariant();
1207  }
1208 
1209  template<typename BasicJsonType>
1210  static void construct(BasicJsonType& j, const std::vector<bool>& arr)
1211  {
1212  j.m_type = value_t::array;
1213  j.m_value = value_t::array;
1214  j.m_value.array->reserve(arr.size());
1215  for (const bool x : arr)
1216  {
1217  j.m_value.array->push_back(x);
1218  }
1219  j.assert_invariant();
1220  }
1221 };
1222 
1223 template<>
1225 {
1226  template<typename BasicJsonType>
1227  static void construct(BasicJsonType& j, const typename BasicJsonType::object_t& obj)
1228  {
1229  j.m_type = value_t::object;
1230  j.m_value = obj;
1231  j.assert_invariant();
1232  }
1233 
1234  template<typename BasicJsonType>
1235  static void construct(BasicJsonType& j, typename BasicJsonType::object_t&& obj)
1236  {
1237  j.m_type = value_t::object;
1238  j.m_value = std::move(obj);
1239  j.assert_invariant();
1240  }
1241 
1242  template<typename BasicJsonType, typename CompatibleObjectType,
1243  enable_if_t<not std::is_same<CompatibleObjectType, typename BasicJsonType::object_t>::value, int> = 0>
1244  static void construct(BasicJsonType& j, const CompatibleObjectType& obj)
1245  {
1246  j.m_type = value_t::object;
1247  j.m_value = value_t::object;
1248  for (const auto& x : obj)
1249  {
1250  j.m_value.object->try_emplace(x.first, x.second);
1251  }
1252  j.assert_invariant();
1253  }
1254 };
1255 
1257 // to_json //
1259 
1260 template<typename BasicJsonType, typename T,
1261  enable_if_t<std::is_same<T, bool>::value, int> = 0>
1262 void to_json(BasicJsonType& j, T b) noexcept
1263 {
1265 }
1266 
1267 template<typename BasicJsonType, typename CompatibleString,
1268  enable_if_t<std::is_constructible<StringRef, CompatibleString>::value, int> = 0>
1269 void to_json(BasicJsonType& j, const CompatibleString& s)
1270 {
1271  external_constructor<value_t::string>::construct(j, s);
1272 }
1273 
1274 template<typename BasicJsonType, typename T,
1275  enable_if_t<std::is_same<std::string, T>::value, int> = 0>
1276 void to_json(BasicJsonType& j, T&& s)
1277 {
1278  external_constructor<value_t::string>::construct(j, std::move(s));
1279 }
1280 
1281 template<typename BasicJsonType, typename FloatType,
1282  enable_if_t<std::is_floating_point<FloatType>::value, int> = 0>
1283 void to_json(BasicJsonType& j, FloatType val) noexcept
1284 {
1285  external_constructor<value_t::number_float>::construct(j, static_cast<double>(val));
1286 }
1287 
1288 template<typename BasicJsonType, typename CompatibleNumberUnsignedType,
1289  enable_if_t<is_compatible_integer_type<uint64_t, CompatibleNumberUnsignedType>::value, int> = 0>
1290 void to_json(BasicJsonType& j, CompatibleNumberUnsignedType val) noexcept
1291 {
1292  external_constructor<value_t::number_unsigned>::construct(j, static_cast<uint64_t>(val));
1293 }
1294 
1295 template<typename BasicJsonType, typename CompatibleNumberIntegerType,
1296  enable_if_t<is_compatible_integer_type<int64_t, CompatibleNumberIntegerType>::value, int> = 0>
1297 void to_json(BasicJsonType& j, CompatibleNumberIntegerType val) noexcept
1298 {
1299  external_constructor<value_t::number_integer>::construct(j, static_cast<int64_t>(val));
1300 }
1301 
1302 template<typename BasicJsonType, typename EnumType,
1303  enable_if_t<std::is_enum<EnumType>::value, int> = 0>
1304 void to_json(BasicJsonType& j, EnumType e) noexcept
1305 {
1306  using underlying_type = typename std::underlying_type<EnumType>::type;
1307  external_constructor<value_t::number_integer>::construct(j, static_cast<underlying_type>(e));
1308 }
1309 
1310 template<typename BasicJsonType>
1311 void to_json(BasicJsonType& j, const std::vector<bool>& e)
1312 {
1313  external_constructor<value_t::array>::construct(j, e);
1314 }
1315 
1316 template<typename BasicJsonType, typename CompatibleArrayType,
1317  enable_if_t<is_compatible_array_type<BasicJsonType, CompatibleArrayType>::value or
1318  std::is_same<typename BasicJsonType::array_t, CompatibleArrayType>::value,
1319  int> = 0>
1320 void to_json(BasicJsonType& j, const CompatibleArrayType& arr)
1321 {
1322  external_constructor<value_t::array>::construct(j, arr);
1323 }
1324 
1325 template<typename BasicJsonType>
1326 void to_json(BasicJsonType& j, typename BasicJsonType::array_t&& arr)
1327 {
1328  external_constructor<value_t::array>::construct(j, std::move(arr));
1329 }
1330 
1331 template<typename BasicJsonType, typename CompatibleObjectType,
1332  enable_if_t<is_compatible_object_type<BasicJsonType, CompatibleObjectType>::value, int> = 0>
1333 void to_json(BasicJsonType& j, const CompatibleObjectType& obj)
1334 {
1335  external_constructor<value_t::object>::construct(j, obj);
1336 }
1337 
1338 template<typename BasicJsonType>
1339 void to_json(BasicJsonType& j, typename BasicJsonType::object_t&& obj)
1340 {
1341  external_constructor<value_t::object>::construct(j, std::move(obj));
1342 }
1343 
1344 template<typename BasicJsonType, typename T, std::size_t N,
1345  enable_if_t<not std::is_constructible<StringRef, T (&)[N]>::value, int> = 0>
1346 void to_json(BasicJsonType& j, T (&arr)[N])
1347 {
1348  external_constructor<value_t::array>::construct(j, arr);
1349 }
1350 
1351 template<typename BasicJsonType, typename... Args>
1352 void to_json(BasicJsonType& j, const std::pair<Args...>& p)
1353 {
1354  j = {p.first, p.second};
1355 }
1356 
1357 template<typename BasicJsonType, typename Tuple, std::size_t... Idx>
1358 void to_json_tuple_impl(BasicJsonType& j, const Tuple& t, index_sequence<Idx...>)
1359 {
1360  j = {std::get<Idx>(t)...};
1361 }
1362 
1363 template<typename BasicJsonType, typename... Args>
1364 void to_json(BasicJsonType& j, const std::tuple<Args...>& t)
1365 {
1366  to_json_tuple_impl(j, t, index_sequence_for<Args...> {});
1367 }
1368 
1370 {
1371  private:
1372  template<typename BasicJsonType, typename T>
1373  auto call(BasicJsonType& j, T&& val, priority_tag<1> /*unused*/) const noexcept(noexcept(to_json(j, std::forward<T>(val))))
1374  -> decltype(to_json(j, std::forward<T>(val)), void())
1375  {
1376  return to_json(j, std::forward<T>(val));
1377  }
1378 
1379  template<typename BasicJsonType, typename T>
1380  void call(BasicJsonType& /*unused*/, T&& /*unused*/, priority_tag<0> /*unused*/) const noexcept
1381  {
1382  static_assert(sizeof(BasicJsonType) == 0,
1383  "could not find to_json() method in T's namespace");
1384 
1385 #ifdef _MSC_VER
1386  // MSVC does not show a stacktrace for the above assert
1387  using decayed = uncvref_t<T>;
1388  static_assert(sizeof(typename decayed::force_msvc_stacktrace) == 0,
1389  "forcing MSVC stacktrace to show which T we're talking about.");
1390 #endif
1391  }
1392 
1393  public:
1394  template<typename BasicJsonType, typename T>
1395  void operator()(BasicJsonType& j, T&& val) const
1396  noexcept(noexcept(std::declval<to_json_fn>().call(j, std::forward<T>(val), priority_tag<1> {})))
1397  {
1398  return call(j, std::forward<T>(val), priority_tag<1> {});
1399  }
1400 };
1401 }
1402 
1403 // namespace to hold default `to_json` function
1404 namespace
1405 {
1406 constexpr const auto& to_json = detail::static_const<detail::to_json_fn>::value;
1407 }
1408 
1409 namespace detail
1410 {
1411 /*
1412 @brief an iterator for primitive JSON types
1413 
1414 This class models an iterator for primitive JSON types (boolean, number,
1415 string). It's only purpose is to allow the iterator/const_iterator classes
1416 to "iterate" over primitive values. Internally, the iterator is modeled by
1417 a `difference_type` variable. Value begin_value (`0`) models the begin,
1418 end_value (`1`) models past the end.
1419 */
1421 {
1422  private:
1423  using difference_type = std::ptrdiff_t;
1424  static constexpr difference_type begin_value = 0;
1425  static constexpr difference_type end_value = begin_value + 1;
1426 
1428  difference_type m_it = (std::numeric_limits<std::ptrdiff_t>::min)();
1429 
1430  public:
1431  constexpr difference_type get_value() const noexcept
1432  {
1433  return m_it;
1434  }
1435 
1437  void set_begin() noexcept
1438  {
1439  m_it = begin_value;
1440  }
1441 
1443  void set_end() noexcept
1444  {
1445  m_it = end_value;
1446  }
1447 
1449  constexpr bool is_begin() const noexcept
1450  {
1451  return m_it == begin_value;
1452  }
1453 
1455  constexpr bool is_end() const noexcept
1456  {
1457  return m_it == end_value;
1458  }
1459 
1460  friend constexpr bool operator==(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept
1461  {
1462  return lhs.m_it == rhs.m_it;
1463  }
1464 
1465  friend constexpr bool operator<(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept
1466  {
1467  return lhs.m_it < rhs.m_it;
1468  }
1469 
1470  primitive_iterator_t operator+(difference_type n) noexcept
1471  {
1472  auto result = *this;
1473  result += n;
1474  return result;
1475  }
1476 
1477  friend constexpr difference_type operator-(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept
1478  {
1479  return lhs.m_it - rhs.m_it;
1480  }
1481 
1482  primitive_iterator_t& operator++() noexcept
1483  {
1484  ++m_it;
1485  return *this;
1486  }
1487 
1488  primitive_iterator_t const operator++(int) noexcept
1489  {
1490  auto result = *this;
1491  m_it++;
1492  return result;
1493  }
1494 
1495  primitive_iterator_t& operator--() noexcept
1496  {
1497  --m_it;
1498  return *this;
1499  }
1500 
1501  primitive_iterator_t const operator--(int) noexcept
1502  {
1503  auto result = *this;
1504  m_it--;
1505  return result;
1506  }
1507 
1508  primitive_iterator_t& operator+=(difference_type n) noexcept
1509  {
1510  m_it += n;
1511  return *this;
1512  }
1513 
1514  primitive_iterator_t& operator-=(difference_type n) noexcept
1515  {
1516  m_it -= n;
1517  return *this;
1518  }
1519 };
1520 
1527 template<typename BasicJsonType> struct internal_iterator
1528 {
1530  typename BasicJsonType::object_t::iterator object_iterator {};
1532  typename BasicJsonType::array_t::iterator array_iterator {};
1534  primitive_iterator_t primitive_iterator {};
1535 };
1536 
1537 // forward declare, to be able to friend it later on
1538 template<typename IteratorType> class iteration_proxy;
1539 
1560 template<typename BasicJsonType>
1562 {
1564  friend iter_impl<typename std::conditional<std::is_const<BasicJsonType>::value, typename std::remove_const<BasicJsonType>::type, const BasicJsonType>::type>;
1565  friend BasicJsonType;
1567  friend class ::wpi::JsonTest;
1568 
1569  using object_t = typename BasicJsonType::object_t;
1570  using array_t = typename BasicJsonType::array_t;
1571  // make sure BasicJsonType is json or const json
1572  static_assert(is_json<typename std::remove_const<BasicJsonType>::type>::value,
1573  "iter_impl only accepts (const) json");
1574 
1575  public:
1576 
1582  using iterator_category = std::bidirectional_iterator_tag;
1583 
1585  using value_type = typename BasicJsonType::value_type;
1587  using difference_type = typename BasicJsonType::difference_type;
1589  using pointer = typename std::conditional<std::is_const<BasicJsonType>::value,
1590  typename BasicJsonType::const_pointer,
1591  typename BasicJsonType::pointer>::type;
1593  using reference =
1594  typename std::conditional<std::is_const<BasicJsonType>::value,
1595  typename BasicJsonType::const_reference,
1596  typename BasicJsonType::reference>::type;
1597 
1599  iter_impl() = default;
1600 
1607  explicit iter_impl(pointer object) noexcept : m_object(object)
1608  {
1609  assert(m_object != nullptr);
1610 
1611  switch (m_object->m_type)
1612  {
1613  case value_t::object:
1614  {
1615  m_it.object_iterator = typename object_t::iterator();
1616  break;
1617  }
1618 
1619  case value_t::array:
1620  {
1621  m_it.array_iterator = typename array_t::iterator();
1622  break;
1623  }
1624 
1625  default:
1626  {
1627  m_it.primitive_iterator = primitive_iterator_t();
1628  break;
1629  }
1630  }
1631  }
1632 
1647  iter_impl(const iter_impl<typename std::remove_const<BasicJsonType>::type>& other) noexcept
1648  : m_object(other.m_object), m_it(other.m_it) {}
1649 
1656  iter_impl& operator=(const iter_impl<typename std::remove_const<BasicJsonType>::type>& other) noexcept
1657  {
1658  m_object = other.m_object;
1659  m_it = other.m_it;
1660  return *this;
1661  }
1662 
1663  private:
1668  void set_begin() noexcept
1669  {
1670  assert(m_object != nullptr);
1671 
1672  switch (m_object->m_type)
1673  {
1674  case value_t::object:
1675  {
1676  m_it.object_iterator = m_object->m_value.object->begin();
1677  break;
1678  }
1679 
1680  case value_t::array:
1681  {
1682  m_it.array_iterator = m_object->m_value.array->begin();
1683  break;
1684  }
1685 
1686  case value_t::null:
1687  {
1688  // set to end so begin()==end() is true: null is empty
1689  m_it.primitive_iterator.set_end();
1690  break;
1691  }
1692 
1693  default:
1694  {
1695  m_it.primitive_iterator.set_begin();
1696  break;
1697  }
1698  }
1699  }
1700 
1705  void set_end() noexcept
1706  {
1707  assert(m_object != nullptr);
1708 
1709  switch (m_object->m_type)
1710  {
1711  case value_t::object:
1712  {
1713  m_it.object_iterator = m_object->m_value.object->end();
1714  break;
1715  }
1716 
1717  case value_t::array:
1718  {
1719  m_it.array_iterator = m_object->m_value.array->end();
1720  break;
1721  }
1722 
1723  default:
1724  {
1725  m_it.primitive_iterator.set_end();
1726  break;
1727  }
1728  }
1729  }
1730 
1731  public:
1736  reference operator*() const
1737  {
1738  assert(m_object != nullptr);
1739 
1740  switch (m_object->m_type)
1741  {
1742  case value_t::object:
1743  {
1744  assert(m_it.object_iterator != m_object->m_value.object->end());
1745  return m_it.object_iterator->second;
1746  }
1747 
1748  case value_t::array:
1749  {
1750  assert(m_it.array_iterator != m_object->m_value.array->end());
1751  return *m_it.array_iterator;
1752  }
1753 
1754  case value_t::null:
1755  JSON_THROW(invalid_iterator::create(214, "cannot get value"));
1756 
1757  default:
1758  {
1759  if (JSON_LIKELY(m_it.primitive_iterator.is_begin()))
1760  {
1761  return *m_object;
1762  }
1763 
1764  JSON_THROW(invalid_iterator::create(214, "cannot get value"));
1765  }
1766  }
1767  }
1768 
1773  pointer operator->() const
1774  {
1775  assert(m_object != nullptr);
1776 
1777  switch (m_object->m_type)
1778  {
1779  case value_t::object:
1780  {
1781  assert(m_it.object_iterator != m_object->m_value.object->end());
1782  return &(m_it.object_iterator->second);
1783  }
1784 
1785  case value_t::array:
1786  {
1787  assert(m_it.array_iterator != m_object->m_value.array->end());
1788  return &*m_it.array_iterator;
1789  }
1790 
1791  default:
1792  {
1793  if (JSON_LIKELY(m_it.primitive_iterator.is_begin()))
1794  {
1795  return m_object;
1796  }
1797 
1798  JSON_THROW(invalid_iterator::create(214, "cannot get value"));
1799  }
1800  }
1801  }
1802 
1807  iter_impl const operator++(int)
1808  {
1809  auto result = *this;
1810  ++(*this);
1811  return result;
1812  }
1813 
1818  iter_impl& operator++()
1819  {
1820  assert(m_object != nullptr);
1821 
1822  switch (m_object->m_type)
1823  {
1824  case value_t::object:
1825  {
1826  ++m_it.object_iterator;
1827  break;
1828  }
1829 
1830  case value_t::array:
1831  {
1832  std::advance(m_it.array_iterator, 1);
1833  break;
1834  }
1835 
1836  default:
1837  {
1838  ++m_it.primitive_iterator;
1839  break;
1840  }
1841  }
1842 
1843  return *this;
1844  }
1845 
1850  iter_impl const operator--(int)
1851  {
1852  auto result = *this;
1853  --(*this);
1854  return result;
1855  }
1856 
1861  iter_impl& operator--()
1862  {
1863  assert(m_object != nullptr);
1864 
1865  switch (m_object->m_type)
1866  {
1867  case value_t::object:
1868  {
1869  --m_it.object_iterator;
1870  break;
1871  }
1872 
1873  case value_t::array:
1874  {
1875  std::advance(m_it.array_iterator, -1);
1876  break;
1877  }
1878 
1879  default:
1880  {
1881  --m_it.primitive_iterator;
1882  break;
1883  }
1884  }
1885 
1886  return *this;
1887  }
1888 
1893  bool operator==(const iter_impl& other) const
1894  {
1895  // if objects are not the same, the comparison is undefined
1896  if (JSON_UNLIKELY(m_object != other.m_object))
1897  {
1898  JSON_THROW(invalid_iterator::create(212, "cannot compare iterators of different containers"));
1899  }
1900 
1901  assert(m_object != nullptr);
1902 
1903  switch (m_object->m_type)
1904  {
1905  case value_t::object:
1906  return (m_it.object_iterator == other.m_it.object_iterator);
1907 
1908  case value_t::array:
1909  return (m_it.array_iterator == other.m_it.array_iterator);
1910 
1911  default:
1912  return (m_it.primitive_iterator == other.m_it.primitive_iterator);
1913  }
1914  }
1915 
1920  bool operator!=(const iter_impl& other) const
1921  {
1922  return not operator==(other);
1923  }
1924 
1929  bool operator<(const iter_impl& other) const
1930  {
1931  // if objects are not the same, the comparison is undefined
1932  if (JSON_UNLIKELY(m_object != other.m_object))
1933  {
1934  JSON_THROW(invalid_iterator::create(212, "cannot compare iterators of different containers"));
1935  }
1936 
1937  assert(m_object != nullptr);
1938 
1939  switch (m_object->m_type)
1940  {
1941  case value_t::object:
1942  JSON_THROW(invalid_iterator::create(213, "cannot compare order of object iterators"));
1943 
1944  case value_t::array:
1945  return (m_it.array_iterator < other.m_it.array_iterator);
1946 
1947  default:
1948  return (m_it.primitive_iterator < other.m_it.primitive_iterator);
1949  }
1950  }
1951 
1956  bool operator<=(const iter_impl& other) const
1957  {
1958  return not other.operator < (*this);
1959  }
1960 
1965  bool operator>(const iter_impl& other) const
1966  {
1967  return not operator<=(other);
1968  }
1969 
1974  bool operator>=(const iter_impl& other) const
1975  {
1976  return not operator<(other);
1977  }
1978 
1983  iter_impl& operator+=(difference_type i)
1984  {
1985  assert(m_object != nullptr);
1986 
1987  switch (m_object->m_type)
1988  {
1989  case value_t::object:
1990  JSON_THROW(invalid_iterator::create(209, "cannot use offsets with object iterators"));
1991 
1992  case value_t::array:
1993  {
1994  std::advance(m_it.array_iterator, i);
1995  break;
1996  }
1997 
1998  default:
1999  {
2000  m_it.primitive_iterator += i;
2001  break;
2002  }
2003  }
2004 
2005  return *this;
2006  }
2007 
2012  iter_impl& operator-=(difference_type i)
2013  {
2014  return operator+=(-i);
2015  }
2016 
2021  iter_impl operator+(difference_type i) const
2022  {
2023  auto result = *this;
2024  result += i;
2025  return result;
2026  }
2027 
2032  friend iter_impl operator+(difference_type i, const iter_impl& it)
2033  {
2034  auto result = it;
2035  result += i;
2036  return result;
2037  }
2038 
2043  iter_impl operator-(difference_type i) const
2044  {
2045  auto result = *this;
2046  result -= i;
2047  return result;
2048  }
2049 
2054  difference_type operator-(const iter_impl& other) const
2055  {
2056  assert(m_object != nullptr);
2057 
2058  switch (m_object->m_type)
2059  {
2060  case value_t::object:
2061  JSON_THROW(invalid_iterator::create(209, "cannot use offsets with object iterators"));
2062 
2063  case value_t::array:
2064  return m_it.array_iterator - other.m_it.array_iterator;
2065 
2066  default:
2067  return m_it.primitive_iterator - other.m_it.primitive_iterator;
2068  }
2069  }
2070 
2075  reference operator[](difference_type n) const
2076  {
2077  assert(m_object != nullptr);
2078 
2079  switch (m_object->m_type)
2080  {
2081  case value_t::object:
2082  JSON_THROW(invalid_iterator::create(208, "cannot use operator[] for object iterators"));
2083 
2084  case value_t::array:
2085  return *std::next(m_it.array_iterator, n);
2086 
2087  case value_t::null:
2088  JSON_THROW(invalid_iterator::create(214, "cannot get value"));
2089 
2090  default:
2091  {
2092  if (JSON_LIKELY(m_it.primitive_iterator.get_value() == -n))
2093  {
2094  return *m_object;
2095  }
2096 
2097  JSON_THROW(invalid_iterator::create(214, "cannot get value"));
2098  }
2099  }
2100  }
2101 
2106  StringRef key() const
2107  {
2108  assert(m_object != nullptr);
2109 
2110  if (JSON_LIKELY(m_object->is_object()))
2111  {
2112  return m_it.object_iterator->first();
2113  }
2114 
2115  JSON_THROW(invalid_iterator::create(207, "cannot use key() for non-object iterators"));
2116  }
2117 
2122  reference value() const
2123  {
2124  return operator*();
2125  }
2126 
2127  private:
2129  pointer m_object = nullptr;
2132 };
2133 
2135 template<typename IteratorType> class iteration_proxy
2136 {
2137  private:
2139  class iteration_proxy_internal
2140  {
2141  private:
2143  IteratorType anchor;
2145  std::size_t array_index = 0;
2146 
2147  public:
2148  explicit iteration_proxy_internal(IteratorType it) noexcept : anchor(it) {}
2149 
2151  iteration_proxy_internal& operator*()
2152  {
2153  return *this;
2154  }
2155 
2157  iteration_proxy_internal& operator++()
2158  {
2159  ++anchor;
2160  ++array_index;
2161 
2162  return *this;
2163  }
2164 
2166  bool operator!=(const iteration_proxy_internal& o) const noexcept
2167  {
2168  return anchor != o.anchor;
2169  }
2170 
2172  std::string key() const
2173  {
2174  assert(anchor.m_object != nullptr);
2175 
2176  switch (anchor.m_object->type())
2177  {
2178  // use integer array index as key
2179  case value_t::array:
2180  return std::to_string(array_index);
2181 
2182  // use key from the object
2183  case value_t::object:
2184  return anchor.key();
2185 
2186  // use an empty key for all primitive types
2187  default:
2188  return "";
2189  }
2190  }
2191 
2193  typename IteratorType::reference value() const
2194  {
2195  return anchor.value();
2196  }
2197  };
2198 
2200  typename IteratorType::reference container;
2201 
2202  public:
2204  explicit iteration_proxy(typename IteratorType::reference cont) noexcept
2205  : container(cont) {}
2206 
2208  iteration_proxy_internal begin() noexcept
2209  {
2210  return iteration_proxy_internal(container.begin());
2211  }
2212 
2214  iteration_proxy_internal end() noexcept
2215  {
2216  return iteration_proxy_internal(container.end());
2217  }
2218 };
2219 
2221 // reverse_iterator //
2223 
2242 template<typename Base>
2243 class json_reverse_iterator : public std::reverse_iterator<Base>
2244 {
2245  public:
2246  using difference_type = std::ptrdiff_t;
2248  using base_iterator = std::reverse_iterator<Base>;
2250  using reference = typename Base::reference;
2251 
2253  json_reverse_iterator(const typename base_iterator::iterator_type& it) noexcept
2254  : base_iterator(it) {}
2255 
2258 
2261  {
2262  return static_cast<json_reverse_iterator>(base_iterator::operator++(1));
2263  }
2264 
2267  {
2268  return static_cast<json_reverse_iterator&>(base_iterator::operator++());
2269  }
2270 
2273  {
2274  return static_cast<json_reverse_iterator>(base_iterator::operator--(1));
2275  }
2276 
2279  {
2280  return static_cast<json_reverse_iterator&>(base_iterator::operator--());
2281  }
2282 
2284  json_reverse_iterator& operator+=(difference_type i)
2285  {
2286  return static_cast<json_reverse_iterator&>(base_iterator::operator+=(i));
2287  }
2288 
2290  json_reverse_iterator operator+(difference_type i) const
2291  {
2292  return static_cast<json_reverse_iterator>(base_iterator::operator+(i));
2293  }
2294 
2296  json_reverse_iterator operator-(difference_type i) const
2297  {
2298  return static_cast<json_reverse_iterator>(base_iterator::operator-(i));
2299  }
2300 
2302  difference_type operator-(const json_reverse_iterator& other) const
2303  {
2304  return base_iterator(*this) - base_iterator(other);
2305  }
2306 
2308  reference operator[](difference_type n) const
2309  {
2310  return *(this->operator+(n));
2311  }
2312 
2314  auto key() const -> decltype(std::declval<Base>().key())
2315  {
2316  auto it = --this->base();
2317  return it.key();
2318  }
2319 
2322  {
2323  auto it = --this->base();
2324  return it.operator * ();
2325  }
2326 };
2327 
2328 template<typename BasicJsonType>
2330 {
2331  public:
2332  using value_type = BasicJsonType;
2333 
2334  json_ref(value_type&& value)
2335  : owned_value(std::move(value)), value_ref(&owned_value), is_rvalue(true)
2336  {}
2337 
2338  json_ref(const value_type& value)
2339  : value_ref(const_cast<value_type*>(&value)), is_rvalue(false)
2340  {}
2341 
2342  json_ref(std::initializer_list<json_ref> init)
2343  : owned_value(init), value_ref(&owned_value), is_rvalue(true)
2344  {}
2345 
2346  template<class... Args>
2347  json_ref(Args&& ... args)
2348  : owned_value(std::forward<Args>(args)...), value_ref(&owned_value), is_rvalue(true)
2349  {}
2350 
2351  // class should be movable only
2352  json_ref(json_ref&&) = default;
2353  json_ref(const json_ref&) = delete;
2354  json_ref& operator=(const json_ref&) = delete;
2355 
2356  value_type moved_or_copied() const
2357  {
2358  if (is_rvalue)
2359  {
2360  return std::move(*value_ref);
2361  }
2362  return *value_ref;
2363  }
2364 
2365  value_type const& operator*() const
2366  {
2367  return *static_cast<value_type const*>(value_ref);
2368  }
2369 
2370  value_type const* operator->() const
2371  {
2372  return static_cast<value_type const*>(value_ref);
2373  }
2374 
2375  private:
2376  mutable value_type owned_value = nullptr;
2377  value_type* value_ref = nullptr;
2378  const bool is_rvalue;
2379 };
2380 } // namespace detail
2381 
2383 {
2384  // allow json to access private members
2385  friend class json;
2386  friend class JsonTest;
2387 
2388  public:
2410  explicit json_pointer(const Twine& s = {})
2411  : reference_tokens(split(s))
2412  {}
2413 
2429  std::string to_string() const noexcept;
2430 
2432  operator std::string() const
2433  {
2434  return to_string();
2435  }
2436 
2444  static int array_index(const Twine& s);
2445 
2446  private:
2451  std::string pop_back()
2452  {
2453  if (JSON_UNLIKELY(is_root()))
2454  {
2455  JSON_THROW(detail::out_of_range::create(405, "JSON pointer has no parent"));
2456  }
2457 
2458  auto last = reference_tokens.back();
2459  reference_tokens.pop_back();
2460  return last;
2461  }
2462 
2464  bool is_root() const
2465  {
2466  return reference_tokens.empty();
2467  }
2468 
2469  json_pointer top() const
2470  {
2471  if (JSON_UNLIKELY(is_root()))
2472  {
2473  JSON_THROW(detail::out_of_range::create(405, "JSON pointer has no parent"));
2474  }
2475 
2476  json_pointer result = *this;
2477  result.reference_tokens = {reference_tokens[0]};
2478  return result;
2479  }
2480 
2489  json& get_and_create(json& j) const;
2490 
2510  json& get_unchecked(json* ptr) const;
2511 
2518  json& get_checked(json* ptr) const;
2519 
2533  const json& get_unchecked(const json* ptr) const;
2534 
2541  const json& get_checked(const json* ptr) const;
2542 
2552  static std::vector<std::string> split(const Twine& reference_string);
2553 
2567  static void replace_substring(std::string& s, const std::string& f,
2568  const std::string& t);
2569 
2571  static std::string escape(std::string s);
2572 
2574  static void unescape(std::string& s);
2575 
2583  static void flatten(const Twine& reference_string,
2584  const json& value,
2585  json& result);
2586 
2597  static json
2598  unflatten(const json& value);
2599 
2600  friend bool operator==(json_pointer const& lhs,
2601  json_pointer const& rhs) noexcept
2602  {
2603  return (lhs.reference_tokens == rhs.reference_tokens);
2604  }
2605 
2606  friend bool operator!=(json_pointer const& lhs,
2607  json_pointer const& rhs) noexcept
2608  {
2609  return not (lhs == rhs);
2610  }
2611 
2613  std::vector<std::string> reference_tokens;
2614 };
2615 
2616 template<typename, typename>
2617 struct adl_serializer
2618 {
2628  template<typename BasicJsonType, typename ValueType>
2629  static void from_json(BasicJsonType&& j, ValueType& val) noexcept(
2630  noexcept(::wpi::from_json(std::forward<BasicJsonType>(j), val)))
2631  {
2632  ::wpi::from_json(std::forward<BasicJsonType>(j), val);
2633  }
2634 
2644  template<typename BasicJsonType, typename ValueType>
2645  static void to_json(BasicJsonType& j, ValueType&& val) noexcept(
2646  noexcept(::wpi::to_json(j, std::forward<ValueType>(val))))
2647  {
2648  ::wpi::to_json(j, std::forward<ValueType>(val));
2649  }
2650 };
2651 
2714 class json
2715 {
2716  private:
2717  template<detail::value_t> friend struct detail::external_constructor;
2718  friend ::wpi::json_pointer;
2719  template<typename BasicJsonType>
2720  friend class ::wpi::detail::iter_impl;
2721  friend class JsonTest;
2722 
2724  using json_t = json;
2725 
2726  // convenience aliases for types residing in namespace detail;
2728  template<typename BasicJsonType>
2730  template<typename BasicJsonType>
2732  template<typename Iterator>
2734  template<typename Base> using json_reverse_iterator = ::wpi::detail::json_reverse_iterator<Base>;
2735 
2736  class binary_reader;
2737  class binary_writer;
2738  class lexer;
2739  class parser;
2740  class serializer;
2741 
2742  public:
2743  using value_t = detail::value_t;
2746  template<typename T, typename SFINAE>
2749  using initializer_list_t = std::initializer_list<detail::json_ref<json>>;
2750 
2752  // exceptions //
2754 
2758 
2771 
2773 
2774 
2776  // container types //
2778 
2783 
2785  using value_type = json;
2786 
2790  using const_reference = const value_type&;
2791 
2793  using difference_type = std::ptrdiff_t;
2795  using size_type = std::size_t;
2796 
2798  using allocator_type = std::allocator<json>;
2799 
2801  using pointer = json*;
2803  using const_pointer = const json*;
2804 
2813 
2815 
2816 
2821  {
2822  return allocator_type();
2823  }
2824 
2851  static json meta();
2852 
2853 
2855  // JSON value data types //
2857 
2862 
2863 #if defined(JSON_HAS_CPP_14)
2864  // Use transparent comparator if possible, combined with perfect forwarding
2865  // on find() and count() calls prevents unnecessary string construction.
2866  using object_comparator_t = std::less<>;
2867 #else
2868  using object_comparator_t = std::less<std::string>;
2869 #endif
2870 
2927 
2953  using array_t = std::vector<json>;
2954 
2956 
2957  private:
2958 
2960  template<typename T, typename... Args>
2961  static T* create(Args&& ... args)
2962  {
2963  std::allocator<T> alloc;
2964 
2965  auto deleter = [&](T * object)
2966  {
2967  alloc.deallocate(object, 1);
2968  };
2969  std::unique_ptr<T, decltype(deleter)> object(alloc.allocate(1), deleter);
2970  alloc.construct(object.get(), std::forward<Args>(args)...);
2971  assert(object != nullptr);
2972  return object.release();
2973  }
2974 
2976  // JSON value storage //
2978 
3003  union json_value
3004  {
3006  object_t* object;
3008  array_t* array;
3012  bool boolean;
3014  int64_t number_integer;
3016  uint64_t number_unsigned;
3018  double number_float;
3019 
3021  json_value() = default;
3023  json_value(bool v) noexcept : boolean(v) {}
3025  json_value(int64_t v) noexcept : number_integer(v) {}
3027  json_value(uint64_t v) noexcept : number_unsigned(v) {}
3029  json_value(double v) noexcept : number_float(v) {}
3031  json_value(value_t t);
3032 
3034  json_value(StringRef value)
3035  {
3036  string = create<std::string>(value);
3037  }
3038 
3040  json_value(const std::string& value)
3041  {
3042  string = create<std::string>(value);
3043  }
3044 
3046  json_value(std::string&& value)
3047  {
3048  string = create<std::string>(std::move(value));
3049  }
3050 
3052  json_value(const object_t& value)
3053  {
3054  object = create<object_t>(value);
3055  }
3056 
3058  json_value(object_t&& value)
3059  {
3060  object = create<object_t>(std::move(value));
3061  }
3062 
3064  json_value(const array_t& value)
3065  {
3066  array = create<array_t>(value);
3067  }
3068 
3070  json_value(array_t&& value)
3071  {
3072  array = create<array_t>(std::move(value));
3073  }
3074 
3075  void destroy(value_t t) noexcept;
3076  };
3077 
3087  void assert_invariant() const noexcept
3088  {
3089  assert(m_type != value_t::object or m_value.object != nullptr);
3090  assert(m_type != value_t::array or m_value.array != nullptr);
3091  assert(m_type != value_t::string or m_value.string != nullptr);
3092  }
3093 
3094  public:
3096  // JSON parser callback //
3098 
3114  enum class parse_event_t : uint8_t
3115  {
3117  object_start,
3119  object_end,
3121  array_start,
3123  array_end,
3125  key,
3127  value
3128  };
3129 
3179  using parser_callback_t =
3180  std::function<bool(int depth, parse_event_t event, json& parsed)>;
3181 
3182 
3184  // constructors //
3186 
3191 
3221  json(const value_t v)
3222  : m_type(v), m_value(v)
3223  {
3224  assert_invariant();
3225  }
3226 
3245  json(std::nullptr_t = nullptr) noexcept
3246  : json(value_t::null)
3247  {
3248  assert_invariant();
3249  }
3250 
3308  template <typename CompatibleType,
3309  typename U = detail::uncvref_t<CompatibleType>,
3310  detail::enable_if_t<
3312  json(CompatibleType && val) noexcept(noexcept(
3313  adl_serializer<U, void>::to_json(std::declval<json_t&>(),
3314  std::forward<CompatibleType>(val))))
3315  {
3316  adl_serializer<U, void>::to_json(*this, std::forward<CompatibleType>(val));
3317  assert_invariant();
3318  }
3319 
3394  json(initializer_list_t init,
3395  bool type_deduction = true,
3396  value_t manual_type = value_t::array);
3397 
3435  static json array(initializer_list_t init = {})
3436  {
3437  return json(init, false, value_t::array);
3438  }
3439 
3478  static json object(initializer_list_t init = {})
3479  {
3480  return json(init, false, value_t::object);
3481  }
3482 
3505  json(size_type cnt, const json& val);
3506 
3562  template<class InputIT, typename std::enable_if<
3563  std::is_same<InputIT, typename json_t::iterator>::value or
3564  std::is_same<InputIT, typename json_t::const_iterator>::value, int>::type = 0>
3565  json(InputIT first, InputIT last)
3566  {
3567  assert(first.m_object != nullptr);
3568  assert(last.m_object != nullptr);
3569 
3570  // make sure iterator fits the current value
3571  if (JSON_UNLIKELY(first.m_object != last.m_object))
3572  {
3573  JSON_THROW(invalid_iterator::create(201, "iterators are not compatible"));
3574  }
3575 
3576  // copy type from first iterator
3577  m_type = first.m_object->m_type;
3578 
3579  // check if iterator range is complete for primitive values
3580  switch (m_type)
3581  {
3582  case value_t::boolean:
3583  case value_t::number_float:
3586  case value_t::string:
3587  {
3588  if (JSON_UNLIKELY(not first.m_it.primitive_iterator.is_begin()
3589  or not last.m_it.primitive_iterator.is_end()))
3590  {
3591  JSON_THROW(invalid_iterator::create(204, "iterators out of range"));
3592  }
3593  break;
3594  }
3595 
3596  default:
3597  break;
3598  }
3599 
3600  switch (m_type)
3601  {
3603  {
3604  m_value.number_integer = first.m_object->m_value.number_integer;
3605  break;
3606  }
3607 
3609  {
3610  m_value.number_unsigned = first.m_object->m_value.number_unsigned;
3611  break;
3612  }
3613 
3614  case value_t::number_float:
3615  {
3616  m_value.number_float = first.m_object->m_value.number_float;
3617  break;
3618  }
3619 
3620  case value_t::boolean:
3621  {
3622  m_value.boolean = first.m_object->m_value.boolean;
3623  break;
3624  }
3625 
3626  case value_t::string:
3627  {
3628  m_value = *first.m_object->m_value.string;
3629  break;
3630  }
3631 
3632  case value_t::array:
3633  {
3634  m_value.array = create<array_t>(first.m_it.array_iterator,
3635  last.m_it.array_iterator);
3636  break;
3637  }
3638 
3639  default:
3640  JSON_THROW(invalid_iterator::create(206, "cannot construct with iterators from " +
3641  Twine(first.m_object->type_name())));
3642  }
3643 
3644  assert_invariant();
3645  }
3646 
3647 
3649  // other constructors and destructor //
3651 
3653  json(const detail::json_ref<json>& ref)
3654  : json(ref.moved_or_copied())
3655  {}
3656 
3682  json(const json& other);
3683 
3710  json(json&& other) noexcept
3711  : m_type(std::move(other.m_type)),
3712  m_value(std::move(other.m_value))
3713  {
3714  // check that passed value is valid
3715  other.assert_invariant();
3716 
3717  // invalidate payload
3718  other.m_type = value_t::null;
3719  other.m_value = {};
3720 
3721  assert_invariant();
3722  }
3723 
3747  reference& operator=(json other) noexcept (
3748  std::is_nothrow_move_constructible<value_t>::value and
3749  std::is_nothrow_move_assignable<value_t>::value and
3750  std::is_nothrow_move_constructible<json_value>::value and
3751  std::is_nothrow_move_assignable<json_value>::value
3752  )
3753  {
3754  // check that passed value is valid
3755  other.assert_invariant();
3756 
3757  using std::swap;
3758  swap(m_type, other.m_type);
3759  swap(m_value, other.m_value);
3760 
3761  assert_invariant();
3762  return *this;
3763  }
3764 
3780  ~json() noexcept
3781  {
3782  assert_invariant();
3783  m_value.destroy(m_type);
3784  }
3785 
3787 
3788  public:
3790  // object inspection //
3792 
3796 
3833  std::string dump(const int indent = -1, const char indent_char = ' ',
3834  const bool ensure_ascii = false) const;
3835 
3836  void dump(raw_ostream& os, int indent = -1, const char indent_char = ' ',
3837  const bool ensure_ascii = false) const;
3838 
3871  value_t type() const noexcept
3872  {
3873  return m_type;
3874  }
3875 
3901  bool is_primitive() const noexcept
3902  {
3903  return is_null() or is_string() or is_boolean() or is_number();
3904  }
3905 
3928  bool is_structured() const noexcept
3929  {
3930  return is_array() or is_object();
3931  }
3932 
3950  bool is_null() const noexcept
3951  {
3952  return (m_type == value_t::null);
3953  }
3954 
3972  bool is_boolean() const noexcept
3973  {
3974  return (m_type == value_t::boolean);
3975  }
3976 
4002  bool is_number() const noexcept
4003  {
4004  return is_number_integer() or is_number_float();
4005  }
4006 
4031  bool is_number_integer() const noexcept
4032  {
4033  return (m_type == value_t::number_integer or m_type == value_t::number_unsigned);
4034  }
4035 
4059  bool is_number_unsigned() const noexcept
4060  {
4061  return (m_type == value_t::number_unsigned);
4062  }
4063 
4087  bool is_number_float() const noexcept
4088  {
4089  return (m_type == value_t::number_float);
4090  }
4091 
4109  bool is_object() const noexcept
4110  {
4111  return (m_type == value_t::object);
4112  }
4113 
4131  bool is_array() const noexcept
4132  {
4133  return (m_type == value_t::array);
4134  }
4135 
4153  bool is_string() const noexcept
4154  {
4155  return (m_type == value_t::string);
4156  }
4157 
4180  bool is_discarded() const noexcept
4181  {
4182  return (m_type == value_t::discarded);
4183  }
4184 
4206  operator value_t() const noexcept
4207  {
4208  return m_type;
4209  }
4210 
4212 
4213  private:
4215  // value access //
4217 
4219  bool get_impl(bool* /*unused*/) const
4220  {
4221  if (JSON_LIKELY(is_boolean()))
4222  {
4223  return m_value.boolean;
4224  }
4225 
4226  JSON_THROW(type_error::create(302, "type must be boolean, but is " + Twine(type_name())));
4227  }
4228 
4230  object_t* get_impl_ptr(object_t* /*unused*/) noexcept
4231  {
4232  return is_object() ? m_value.object : nullptr;
4233  }
4234 
4236  const object_t* get_impl_ptr(const object_t* /*unused*/) const noexcept
4237  {
4238  return is_object() ? m_value.object : nullptr;
4239  }
4240 
4242  array_t* get_impl_ptr(array_t* /*unused*/) noexcept
4243  {
4244  return is_array() ? m_value.array : nullptr;
4245  }
4246 
4248  const array_t* get_impl_ptr(const array_t* /*unused*/) const noexcept
4249  {
4250  return is_array() ? m_value.array : nullptr;
4251  }
4252 
4254  std::string* get_impl_ptr(std::string* /*unused*/) noexcept
4255  {
4256  return is_string() ? m_value.string : nullptr;
4257  }
4258 
4260  const std::string* get_impl_ptr(const std::string* /*unused*/) const noexcept
4261  {
4262  return is_string() ? m_value.string : nullptr;
4263  }
4264 
4266  bool* get_impl_ptr(bool* /*unused*/) noexcept
4267  {
4268  return is_boolean() ? &m_value.boolean : nullptr;
4269  }
4270 
4272  const bool* get_impl_ptr(const bool* /*unused*/) const noexcept
4273  {
4274  return is_boolean() ? &m_value.boolean : nullptr;
4275  }
4276 
4278  int64_t* get_impl_ptr(int64_t* /*unused*/) noexcept
4279  {
4280  return is_number_integer() ? &m_value.number_integer : nullptr;
4281  }
4282 
4284  const int64_t* get_impl_ptr(const int64_t* /*unused*/) const noexcept
4285  {
4286  return is_number_integer() ? &m_value.number_integer : nullptr;
4287  }
4288 
4290  uint64_t* get_impl_ptr(uint64_t* /*unused*/) noexcept
4291  {
4292  return is_number_unsigned() ? &m_value.number_unsigned : nullptr;
4293  }
4294 
4296  const uint64_t* get_impl_ptr(const uint64_t* /*unused*/) const noexcept
4297  {
4298  return is_number_unsigned() ? &m_value.number_unsigned : nullptr;
4299  }
4300 
4302  double* get_impl_ptr(double* /*unused*/) noexcept
4303  {
4304  return is_number_float() ? &m_value.number_float : nullptr;
4305  }
4306 
4308  const double* get_impl_ptr(const double* /*unused*/) const noexcept
4309  {
4310  return is_number_float() ? &m_value.number_float : nullptr;
4311  }
4312 
4324  template<typename ReferenceType, typename ThisType>
4325  static ReferenceType get_ref_impl(ThisType& obj)
4326  {
4327  // delegate the call to get_ptr<>()
4328  auto ptr = obj.template get_ptr<typename std::add_pointer<ReferenceType>::type>();
4329 
4330  if (JSON_LIKELY(ptr != nullptr))
4331  {
4332  return *ptr;
4333  }
4334 
4335  JSON_THROW(type_error::create(303, "incompatible ReferenceType for get_ref, actual type is " + Twine(obj.type_name())));
4336  }
4337 
4338  public:
4342 
4357  template<typename BasicJsonType, detail::enable_if_t<
4358  std::is_same<typename std::remove_const<BasicJsonType>::type, json_t>::value,
4359  int> = 0>
4360  json get() const
4361  {
4362  return *this;
4363  }
4364 
4404  template<typename ValueTypeCV, typename ValueType = detail::uncvref_t<ValueTypeCV>,
4405  detail::enable_if_t <
4406  not detail::is_json<ValueType>::value and
4407  detail::has_from_json<json_t, ValueType>::value and
4408  not detail::has_non_default_from_json<json_t, ValueType>::value,
4409  int> = 0>
4410  ValueType get() const noexcept(noexcept(
4411  adl_serializer<ValueType, void>::from_json(std::declval<const json_t&>(), std::declval<ValueType&>())))
4412  {
4413  // we cannot static_assert on ValueTypeCV being non-const, because
4414  // there is support for get<const json_t>(), which is why we
4415  // still need the uncvref
4416  static_assert(not std::is_reference<ValueTypeCV>::value,
4417  "get() cannot be used with reference types, you might want to use get_ref()");
4418  static_assert(std::is_default_constructible<ValueType>::value,
4419  "types must be DefaultConstructible when used with get()");
4420 
4421  ValueType ret;
4423  return ret;
4424  }
4425 
4457  template<typename ValueTypeCV, typename ValueType = detail::uncvref_t<ValueTypeCV>,
4458  detail::enable_if_t<not std::is_same<json_t, ValueType>::value and
4459  detail::has_non_default_from_json<json_t, ValueType>::value,
4460  int> = 0>
4461  ValueType get() const noexcept(noexcept(
4462  adl_serializer<ValueTypeCV, void>::from_json(std::declval<const json_t&>())))
4463  {
4464  static_assert(not std::is_reference<ValueTypeCV>::value,
4465  "get() cannot be used with reference types, you might want to use get_ref()");
4467  }
4468 
4495  template<typename PointerType, typename std::enable_if<
4496  std::is_pointer<PointerType>::value, int>::type = 0>
4497  PointerType get() noexcept
4498  {
4499  // delegate the call to get_ptr
4500  return get_ptr<PointerType>();
4501  }
4502 
4507  template<typename PointerType, typename std::enable_if<
4508  std::is_pointer<PointerType>::value, int>::type = 0>
4509  const PointerType get() const noexcept
4510  {
4511  // delegate the call to get_ptr
4512  return get_ptr<PointerType>();
4513  }
4514 
4540  template<typename PointerType, typename std::enable_if<
4541  std::is_pointer<PointerType>::value, int>::type = 0>
4542  PointerType get_ptr() noexcept
4543  {
4544  // get the type of the PointerType (remove pointer and const)
4545  using pointee_t = typename std::remove_const<typename
4546  std::remove_pointer<typename
4547  std::remove_const<PointerType>::type>::type>::type;
4548  // make sure the type matches the allowed types
4549  static_assert(
4550  std::is_same<object_t, pointee_t>::value
4551  or std::is_same<array_t, pointee_t>::value
4552  or std::is_same<std::string, pointee_t>::value
4553  or std::is_same<bool, pointee_t>::value
4554  or std::is_same<int64_t, pointee_t>::value
4555  or std::is_same<uint64_t, pointee_t>::value
4556  or std::is_same<double, pointee_t>::value
4557  , "incompatible pointer type");
4558 
4559  // delegate the call to get_impl_ptr<>()
4560  return get_impl_ptr(static_cast<PointerType>(nullptr));
4561  }
4562 
4567  template<typename PointerType, typename std::enable_if<
4568  std::is_pointer<PointerType>::value and
4569  std::is_const<typename std::remove_pointer<PointerType>::type>::value, int>::type = 0>
4570  const PointerType get_ptr() const noexcept
4571  {
4572  // get the type of the PointerType (remove pointer and const)
4573  using pointee_t = typename std::remove_const<typename
4574  std::remove_pointer<typename
4575  std::remove_const<PointerType>::type>::type>::type;
4576  // make sure the type matches the allowed types
4577  static_assert(
4578  std::is_same<object_t, pointee_t>::value
4579  or std::is_same<array_t, pointee_t>::value
4580  or std::is_same<std::string, pointee_t>::value
4581  or std::is_same<bool, pointee_t>::value
4582  or std::is_same<int64_t, pointee_t>::value
4583  or std::is_same<uint64_t, pointee_t>::value
4584  or std::is_same<double, pointee_t>::value
4585  , "incompatible pointer type");
4586 
4587  // delegate the call to get_impl_ptr<>() const
4588  return get_impl_ptr(static_cast<PointerType>(nullptr));
4589  }
4590 
4617  template<typename ReferenceType, typename std::enable_if<
4618  std::is_reference<ReferenceType>::value, int>::type = 0>
4619  ReferenceType get_ref()
4620  {
4621  // delegate call to get_ref_impl
4622  return get_ref_impl<ReferenceType>(*this);
4623  }
4624 
4629  template<typename ReferenceType, typename std::enable_if<
4630  std::is_reference<ReferenceType>::value and
4631  std::is_const<typename std::remove_reference<ReferenceType>::type>::value, int>::type = 0>
4632  ReferenceType get_ref() const
4633  {
4634  // delegate call to get_ref_impl
4635  return get_ref_impl<ReferenceType>(*this);
4636  }
4637 
4667  template < typename ValueType, typename std::enable_if <
4668  not std::is_pointer<ValueType>::value and
4669  not std::is_same<ValueType, detail::json_ref<json>>::value and
4670  not std::is_same<ValueType, std::string::value_type>::value and
4672 #ifndef _MSC_VER // fix for issue #167 operator<< ambiguity under VS2015
4673  and not std::is_same<ValueType, std::initializer_list<std::string::value_type>>::value
4674 #endif
4675 #if defined(JSON_HAS_CPP_17)
4676  and not std::is_same<ValueType, typename std::string_view>::value
4677 #endif
4678  , int >::type = 0 >
4679  operator ValueType() const
4680  {
4681  // delegate the call to get<>() const
4682  return get<ValueType>();
4683  }
4684 
4686 
4687 
4689  // element access //
4691 
4695 
4722  reference at(size_type idx);
4723 
4750  const_reference at(size_type idx) const;
4751 
4782  reference at(StringRef key);
4783 
4814  const_reference at(StringRef key) const;
4815 
4841  reference operator[](size_type idx);
4842 
4862  const_reference operator[](size_type idx) const;
4863 
4891  reference operator[](StringRef key);
4892 
4923  const_reference operator[](StringRef key) const;
4924 
4952  template<typename T>
4954  {
4955  // implicitly convert null to object
4956  if (is_null())
4957  {
4958  m_type = value_t::object;
4959  m_value = value_t::object;
4960  assert_invariant();
4961  }
4962 
4963  // at only works for objects
4964  if (JSON_LIKELY(is_object()))
4965  {
4966  return m_value.object->operator[](key);
4967  }
4968 
4969  JSON_THROW(type_error::create(305, "cannot use operator[] with " + Twine(type_name())));
4970  }
4971 
5002  template<typename T>
5004  {
5005  // at only works for objects
5006  if (JSON_LIKELY(is_object()))
5007  {
5008  assert(m_value.object->find(key) != m_value.object->end());
5009  return m_value.object->find(key)->second;
5010  }
5011 
5012  JSON_THROW(type_error::create(305, "cannot use operator[] with " + Twine(type_name())));
5013  }
5014 
5063  template<class ValueType, typename std::enable_if<
5064  std::is_convertible<json_t, ValueType>::value, int>::type = 0>
5065  ValueType value(StringRef key, const ValueType& default_value) const
5066  {
5067  // at only works for objects
5068  if (JSON_LIKELY(is_object()))
5069  {
5070  // if key is found, return value and given default value otherwise
5071  const auto it = find(key);
5072  if (it != end())
5073  {
5074  return *it;
5075  }
5076 
5077  return default_value;
5078  }
5079 
5080  JSON_THROW(type_error::create(306, "cannot use value() with " + Twine(type_name())));
5081  }
5082 
5087  std::string value(StringRef key, const char* default_value) const
5088  {
5089  return value(key, std::string(default_value));
5090  }
5091 
5133  template<class ValueType, typename std::enable_if<
5134  std::is_convertible<json_t, ValueType>::value, int>::type = 0>
5135  ValueType value(const json_pointer& ptr, const ValueType& default_value) const
5136  {
5137  // at only works for objects
5138  if (JSON_LIKELY(is_object()))
5139  {
5140  // if pointer resolves a value, return it or use default value
5141  JSON_TRY
5142  {
5143  return ptr.get_checked(this);
5144  }
5145  JSON_CATCH (out_of_range&)
5146  {
5147  return default_value;
5148  }
5149  }
5150 
5151  JSON_THROW(type_error::create(306, "cannot use value() with " + Twine(type_name())));
5152  }
5153 
5158  std::string value(const json_pointer& ptr, const char* default_value) const
5159  {
5160  return value(ptr, std::string(default_value));
5161  }
5162 
5189  {
5190  return *begin();
5191  }
5192 
5197  {
5198  return *cbegin();
5199  }
5200 
5233  {
5234  auto tmp = end();
5235  --tmp;
5236  return *tmp;
5237  }
5238 
5243  {
5244  auto tmp = cend();
5245  --tmp;
5246  return *tmp;
5247  }
5248 
5293  template<class IteratorType, typename std::enable_if<
5294  std::is_same<IteratorType, typename json_t::iterator>::value or
5295  std::is_same<IteratorType, typename json_t::const_iterator>::value, int>::type
5296  = 0>
5297  void erase(IteratorType pos)
5298  {
5299  // make sure iterator fits the current value
5300  if (JSON_UNLIKELY(this != pos.m_object))
5301  {
5302  JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value"));
5303  }
5304 
5305  switch (m_type)
5306  {
5307  case value_t::boolean:
5308  case value_t::number_float:
5311  case value_t::string:
5312  {
5313  if (JSON_UNLIKELY(not pos.m_it.primitive_iterator.is_begin()))
5314  {
5315  JSON_THROW(invalid_iterator::create(205, "iterator out of range"));
5316  }
5317 
5318  if (is_string())
5319  {
5320  std::allocator<std::string> alloc;
5321  alloc.destroy(m_value.string);
5322  alloc.deallocate(m_value.string, 1);
5323  m_value.string = nullptr;
5324  }
5325 
5326  m_type = value_t::null;
5327  assert_invariant();
5328  break;
5329  }
5330 
5331  case value_t::object:
5332  {
5333  m_value.object->erase(pos.m_it.object_iterator);
5334  break;
5335  }
5336 
5337  case value_t::array:
5338  {
5339  m_value.array->erase(pos.m_it.array_iterator);
5340  break;
5341  }
5342 
5343  default:
5344  JSON_THROW(type_error::create(307, "cannot use erase() with " + Twine(type_name())));
5345  }
5346  }
5347 
5394  template<class IteratorType, typename std::enable_if<
5395  std::is_same<IteratorType, typename json_t::iterator>::value or
5396  std::is_same<IteratorType, typename json_t::const_iterator>::value, int>::type
5397  = 0>
5398  IteratorType erase(IteratorType first, IteratorType last)
5399  {
5400  // make sure iterator fits the current value
5401  if (JSON_UNLIKELY(this != first.m_object or this != last.m_object))
5402  {
5403  JSON_THROW(invalid_iterator::create(203, "iterators do not fit current value"));
5404  }
5405 
5406  IteratorType result = end();
5407 
5408  switch (m_type)
5409  {
5410  case value_t::boolean:
5411  case value_t::number_float:
5414  case value_t::string:
5415  {
5416  if (JSON_LIKELY(not first.m_it.primitive_iterator.is_begin()
5417  or not last.m_it.primitive_iterator.is_end()))
5418  {
5419  JSON_THROW(invalid_iterator::create(204, "iterators out of range"));
5420  }
5421 
5422  if (is_string())
5423  {
5424  std::allocator<std::string> alloc;
5425  alloc.destroy(m_value.string);
5426  alloc.deallocate(m_value.string, 1);
5427  m_value.string = nullptr;
5428  }
5429 
5430  m_type = value_t::null;
5431  assert_invariant();
5432  break;
5433  }
5434 
5435  case value_t::array:
5436  {
5437  result.m_it.array_iterator = m_value.array->erase(first.m_it.array_iterator,
5438  last.m_it.array_iterator);
5439  break;
5440  }
5441 
5442  default:
5443  JSON_THROW(type_error::create(307, "cannot use erase() with " + Twine(type_name())));
5444  }
5445 
5446  return result;
5447  }
5448 
5478  size_type erase(StringRef key);
5479 
5504  void erase(const size_type idx);
5505 
5507 
5508 
5510  // lookup //
5512 
5515 
5538  iterator find(StringRef key);
5539 
5544  const_iterator find(StringRef key) const;
5545 
5567  size_type count(StringRef key) const;
5568 
5570 
5571 
5573  // iterators //
5575 
5578 
5603  iterator begin() noexcept
5604  {
5605  iterator result(this);
5606  result.set_begin();
5607  return result;
5608  }
5609 
5613  const_iterator begin() const noexcept
5614  {
5615  return cbegin();
5616  }
5617 
5643  const_iterator cbegin() const noexcept
5644  {
5645  const_iterator result(this);
5646  result.set_begin();
5647  return result;
5648  }
5649 
5674  iterator end() noexcept
5675  {
5676  iterator result(this);
5677  result.set_end();
5678  return result;
5679  }
5680 
5684  const_iterator end() const noexcept
5685  {
5686  return cend();
5687  }
5688 
5714  const_iterator cend() const noexcept
5715  {
5716  const_iterator result(this);
5717  result.set_end();
5718  return result;
5719  }
5720 
5745  {
5746  return reverse_iterator(end());
5747  }
5748 
5753  {
5754  return crbegin();
5755  }
5756 
5782  {
5783  return reverse_iterator(begin());
5784  }
5785 
5789  const_reverse_iterator rend() const noexcept
5790  {
5791  return crend();
5792  }
5793 
5819  {
5820  return const_reverse_iterator(cend());
5821  }
5822 
5848  {
5849  return const_reverse_iterator(cbegin());
5850  }
5851 
5852  public:
5906  {
5907  return iteration_proxy<iterator>(*this);
5908  }
5909 
5914  {
5915  return iteration_proxy<const_iterator>(*this);
5916  }
5917 
5919 
5920 
5922  // capacity //
5924 
5927 
5969  bool empty() const noexcept;
5970 
6013  size_type size() const noexcept;
6014 
6055  size_type max_size() const noexcept;
6056 
6058 
6059 
6061  // modifiers //
6063 
6066 
6103  void clear() noexcept;
6104 
6125  void push_back(json&& val);
6126 
6131  reference operator+=(json&& val)
6132  {
6133  push_back(std::move(val));
6134  return *this;
6135  }
6136 
6141  void push_back(const json& val);
6142 
6148  {
6149  push_back(val);
6150  return *this;
6151  }
6152 
6173  template<typename T, typename U>
6174  void push_back(const std::pair<T, U>& val)
6175  {
6176  // push_back only works for null objects or objects
6177  if (JSON_UNLIKELY(not(is_null() or is_object())))
6178  {
6179  JSON_THROW(type_error::create(308, "cannot use push_back() with " + Twine(type_name())));
6180  }
6181 
6182  // transform null object into an object
6183  if (is_null())
6184  {
6185  m_type = value_t::object;
6186  m_value = value_t::object;
6187  assert_invariant();
6188  }
6189 
6190  // add element to array
6191  m_value.object->try_emplace(val.first, std::move(val.second));
6192  }
6193 
6198  template<typename T, typename U>
6199  reference operator+=(const std::pair<T, U>& val)
6200  {
6201  push_back(val);
6202  return *this;
6203  }
6204 
6230  void push_back(initializer_list_t init);
6231 
6237  {
6238  push_back(init);
6239  return *this;
6240  }
6241 
6263  template<class... Args>
6264  void emplace_back(Args&& ... args)
6265  {
6266  // emplace_back only works for null objects or arrays
6267  if (JSON_UNLIKELY(not(is_null() or is_array())))
6268  {
6269  JSON_THROW(type_error::create(311, "cannot use emplace_back() with " + Twine(type_name())));
6270  }
6271 
6272  // transform null object into an array
6273  if (is_null())
6274  {
6275  m_type = value_t::array;
6276  m_value = value_t::array;
6277  assert_invariant();
6278  }
6279 
6280  // add element to array (perfect forwarding)
6281  m_value.array->emplace_back(std::forward<Args>(args)...);
6282  }
6283 
6311  template<class... Args>
6312  std::pair<iterator, bool> emplace(StringRef key, Args&& ... args)
6313  {
6314  // emplace only works for null objects or arrays
6315  if (JSON_UNLIKELY(not(is_null() or is_object())))
6316  {
6317  JSON_THROW(type_error::create(311, "cannot use emplace() with " + Twine(type_name())));
6318  }
6319 
6320  // transform null object into an object
6321  if (is_null())
6322  {
6323  m_type = value_t::object;
6324  m_value = value_t::object;
6325  assert_invariant();
6326  }
6327 
6328  // add element to array (perfect forwarding)
6329  auto res = m_value.object->try_emplace(key, std::forward<Args>(args)...);
6330  // create result iterator and set iterator to the result of emplace
6331  auto it = begin();
6332  it.m_it.object_iterator = res.first;
6333 
6334  // return pair of iterator and boolean
6335  return {it, res.second};
6336  }
6337 
6360  iterator insert(const_iterator pos, const json& val);
6361 
6367  {
6368  return insert(pos, val);
6369  }
6370 
6395  iterator insert(const_iterator pos, size_type cnt, const json& val);
6396 
6427  iterator insert(const_iterator pos, const_iterator first, const_iterator last);
6428 
6453  iterator insert(const_iterator pos, initializer_list_t ilist);
6454 
6478  void insert(const_iterator first, const_iterator last);
6479 
6499  void update(const_reference j);
6500 
6527  void update(const_iterator first, const_iterator last);
6528 
6546  void swap(reference other) noexcept (
6547  std::is_nothrow_move_constructible<value_t>::value and
6548  std::is_nothrow_move_assignable<value_t>::value and
6549  std::is_nothrow_move_constructible<json_value>::value and
6550  std::is_nothrow_move_assignable<json_value>::value
6551  )
6552  {
6553  std::swap(m_type, other.m_type);
6554  std::swap(m_value, other.m_value);
6555  assert_invariant();
6556  }
6557 
6578  void swap(array_t& other)
6579  {
6580  // swap only works for arrays
6581  if (JSON_LIKELY(is_array()))
6582  {
6583  std::swap(*(m_value.array), other);
6584  }
6585  else
6586  {
6587  JSON_THROW(type_error::create(310, "cannot use swap() with " + Twine(type_name())));
6588  }
6589  }
6590 
6611  void swap(object_t& other)
6612  {
6613  // swap only works for objects
6614  if (JSON_LIKELY(is_object()))
6615  {
6616  std::swap(*(m_value.object), other);
6617  }
6618  else
6619  {
6620  JSON_THROW(type_error::create(310, "cannot use swap() with " + Twine(type_name())));
6621  }
6622  }
6623 
6644  void swap(std::string& other)
6645  {
6646  // swap only works for strings
6647  if (JSON_LIKELY(is_string()))
6648  {
6649  std::swap(*(m_value.string), other);
6650  }
6651  else
6652  {
6653  JSON_THROW(type_error::create(310, "cannot use swap() with " + Twine(type_name())));
6654  }
6655  }
6656 
6658 
6659  public:
6661  // lexicographical comparison operators //
6663 
6666 
6706  friend bool operator==(const_reference lhs, const_reference rhs) noexcept;
6707 
6712  template<typename ScalarType, typename std::enable_if<
6713  std::is_scalar<ScalarType>::value, int>::type = 0>
6714  friend bool operator==(const_reference lhs, const ScalarType rhs) noexcept
6715  {
6716  return (lhs == json(rhs));
6717  }
6718 
6723  template<typename ScalarType, typename std::enable_if<
6724  std::is_scalar<ScalarType>::value, int>::type = 0>
6725  friend bool operator==(const ScalarType lhs, const_reference rhs) noexcept
6726  {
6727  return (json(lhs) == rhs);
6728  }
6729 
6748  friend bool operator!=(const_reference lhs, const_reference rhs) noexcept
6749  {
6750  return not (lhs == rhs);
6751  }
6752 
6757  template<typename ScalarType, typename std::enable_if<
6758  std::is_scalar<ScalarType>::value, int>::type = 0>
6759  friend bool operator!=(const_reference lhs, const ScalarType rhs) noexcept
6760  {
6761  return (lhs != json(rhs));
6762  }
6763 
6768  template<typename ScalarType, typename std::enable_if<
6769  std::is_scalar<ScalarType>::value, int>::type = 0>
6770  friend bool operator!=(const ScalarType lhs, const_reference rhs) noexcept
6771  {
6772  return (json(lhs) != rhs);
6773  }
6774 
6801  friend bool operator<(const_reference lhs, const_reference rhs) noexcept;
6802 
6807  template<typename ScalarType, typename std::enable_if<
6808  std::is_scalar<ScalarType>::value, int>::type = 0>
6809  friend bool operator<(const_reference lhs, const ScalarType rhs) noexcept
6810  {
6811  return (lhs < json(rhs));
6812  }
6813 
6818  template<typename ScalarType, typename std::enable_if<
6819  std::is_scalar<ScalarType>::value, int>::type = 0>
6820  friend bool operator<(const ScalarType lhs, const_reference rhs) noexcept
6821  {
6822  return (json(lhs) < rhs);
6823  }
6824 
6844  friend bool operator<=(const_reference lhs, const_reference rhs) noexcept
6845  {
6846  return not (rhs < lhs);
6847  }
6848 
6853  template<typename ScalarType, typename std::enable_if<
6854  std::is_scalar<ScalarType>::value, int>::type = 0>
6855  friend bool operator<=(const_reference lhs, const ScalarType rhs) noexcept
6856  {
6857  return (lhs <= json(rhs));
6858  }
6859 
6864  template<typename ScalarType, typename std::enable_if<
6865  std::is_scalar<ScalarType>::value, int>::type = 0>
6866  friend bool operator<=(const ScalarType lhs, const_reference rhs) noexcept
6867  {
6868  return (json(lhs) <= rhs);
6869  }
6870 
6890  friend bool operator>(const_reference lhs, const_reference rhs) noexcept
6891  {
6892  return not (lhs <= rhs);
6893  }
6894 
6899  template<typename ScalarType, typename std::enable_if<
6900  std::is_scalar<ScalarType>::value, int>::type = 0>
6901  friend bool operator>(const_reference lhs, const ScalarType rhs) noexcept
6902  {
6903  return (lhs > json(rhs));
6904  }
6905 
6910  template<typename ScalarType, typename std::enable_if<
6911  std::is_scalar<ScalarType>::value, int>::type = 0>
6912  friend bool operator>(const ScalarType lhs, const_reference rhs) noexcept
6913  {
6914  return (json(lhs) > rhs);
6915  }
6916 
6936  friend bool operator>=(const_reference lhs, const_reference rhs) noexcept
6937  {
6938  return not (lhs < rhs);
6939  }
6940 
6945  template<typename ScalarType, typename std::enable_if<
6946  std::is_scalar<ScalarType>::value, int>::type = 0>
6947  friend bool operator>=(const_reference lhs, const ScalarType rhs) noexcept
6948  {
6949  return (lhs >= json(rhs));
6950  }
6951 
6956  template<typename ScalarType, typename std::enable_if<
6957  std::is_scalar<ScalarType>::value, int>::type = 0>
6958  friend bool operator>=(const ScalarType lhs, const_reference rhs) noexcept
6959  {
6960  return (json(lhs) >= rhs);
6961  }
6962 
6964 
6966  // serialization //
6968 
6971 
7003  friend raw_ostream& operator<<(raw_ostream& o, const json& j);
7004 
7006 
7007 
7009  // deserialization //
7011 
7014 
7077  static json parse(StringRef s,
7078  const parser_callback_t cb = nullptr,
7079  const bool allow_exceptions = true);
7080 
7081  static json parse(ArrayRef<uint8_t> arr,
7082  const parser_callback_t cb = nullptr,
7083  const bool allow_exceptions = true);
7084 
7088  static json parse(raw_istream& i,
7089  const parser_callback_t cb = nullptr,
7090  const bool allow_exceptions = true);
7091 
7092  static bool accept(StringRef s);
7093 
7094  static bool accept(ArrayRef<uint8_t> arr);
7095 
7096  static bool accept(raw_istream& i);
7097 
7123  friend raw_istream& operator>>(raw_istream& i, json& j);
7124 
7126 
7128  // convenience functions //
7130 
7161  const char* type_name() const noexcept;
7162 
7163 
7164  private:
7166  // member variables //
7168 
7170  value_t m_type = value_t::null;
7171 
7173  json_value m_value = {};
7174 
7176  // binary serialization/deserialization //
7178 
7181 
7182  public:
7271  static std::vector<uint8_t> to_cbor(const json& j);
7272  static ArrayRef<uint8_t> to_cbor(const json& j, std::vector<uint8_t>& buf);
7273  static ArrayRef<uint8_t> to_cbor(const json& j, SmallVectorImpl<uint8_t>& buf);
7274  static void to_cbor(raw_ostream& os, const json& j);
7275 
7356  static std::vector<uint8_t> to_msgpack(const json& j);
7357  static ArrayRef<uint8_t> to_msgpack(const json& j, std::vector<uint8_t>& buf);
7358  static ArrayRef<uint8_t> to_msgpack(const json& j, SmallVectorImpl<uint8_t>& buf);
7359  static void to_msgpack(raw_ostream& os, const json& j);
7360 
7441  static std::vector<uint8_t> to_ubjson(const json& j,
7442  const bool use_size = false,
7443  const bool use_type = false);
7444  static ArrayRef<uint8_t> to_ubjson(const json& j, std::vector<uint8_t>& buf,
7445  const bool use_size = false, const bool use_type = false);
7446  static ArrayRef<uint8_t> to_ubjson(const json& j, SmallVectorImpl<uint8_t>& buf,
7447  const bool use_size = false, const bool use_type = false);
7448  static void to_ubjson(raw_ostream& os, const json& j,
7449  const bool use_size = false, const bool use_type = false);
7450 
7544  static json from_cbor(raw_istream& is,
7545  const bool strict = true);
7546 
7550  static json from_cbor(ArrayRef<uint8_t> arr, const bool strict = true);
7551 
7625  static json from_msgpack(raw_istream& is,
7626  const bool strict = true);
7627 
7631  static json from_msgpack(ArrayRef<uint8_t> arr, const bool strict = true);
7632 
7686  static json from_ubjson(raw_istream& is,
7687  const bool strict = true);
7688 
7689  static json from_ubjson(ArrayRef<uint8_t> arr, const bool strict = true);
7690 
7692 
7694  // JSON Pointer support //
7696 
7699 
7734  {
7735  return ptr.get_unchecked(this);
7736  }
7737 
7762  {
7763  return ptr.get_unchecked(this);
7764  }
7765 
7805  {
7806  return ptr.get_checked(this);
7807  }
7808 
7847  const_reference at(const json_pointer& ptr) const
7848  {
7849  return ptr.get_checked(this);
7850  }
7851 
7874  json flatten() const
7875  {
7876  json result(value_t::object);
7877  json_pointer::flatten("", *this, result);
7878  return result;
7879  }
7880 
7911  json unflatten() const
7912  {
7913  return json_pointer::unflatten(*this);
7914  }
7915 
7917 
7919  // JSON Patch functions //
7921 
7924 
7972  json patch(const json& json_patch) const;
7973 
8007  static json diff(const json& source, const json& target,
8008  const std::string& path = "");
8009 
8011 
8013  // JSON Merge Patch functions //
8015 
8018 
8061  void merge_patch(const json& patch);
8062 
8064 };
8065 } // namespace wpi
8066 
8068 // nonmember support //
8070 
8071 // specialization of std::swap, and std::hash
8072 namespace std
8073 {
8079 template<>
8080 inline void swap(wpi::json& j1,
8081  wpi::json& j2) noexcept(
8082  is_nothrow_move_constructible<wpi::json>::value and
8083  is_nothrow_move_assignable<wpi::json>::value
8084  )
8085 {
8086  j1.swap(j2);
8087 }
8088 
8090 template<>
8091 struct hash<wpi::json>
8092 {
8098  std::size_t operator()(const wpi::json& j) const
8099  {
8100  // a naive hashing via the string representation
8101  const auto& h = hash<std::string>();
8102  return h(j.dump());
8103  }
8104 };
8105 
8109 template<>
8110 struct less< ::wpi::detail::value_t>
8111 {
8117  wpi::detail::value_t rhs) const noexcept
8118  {
8119  return wpi::detail::operator<(lhs, rhs);
8120  }
8121 };
8122 
8123 } // namespace std
8124 
8138 inline wpi::json operator "" _json(const char* s, std::size_t n)
8139 {
8140  return wpi::json::parse(wpi::StringRef(s, n));
8141 }
8142 
8156 inline wpi::json::json_pointer operator "" _json_pointer(const char* s, std::size_t n)
8157 {
8159 }
8160 
8161 #ifndef WPI_JSON_IMPLEMENTATION
8162 
8163 // restore GCC/clang diagnostic settings
8164 #if defined(__clang__) || defined(__GNUC__) || defined(__GNUG__)
8165  #pragma GCC diagnostic pop
8166 #endif
8167 #if defined(__clang__)
8168  #pragma GCC diagnostic pop
8169 #endif
8170 
8171 // clean up
8172 #undef JSON_CATCH
8173 #undef JSON_THROW
8174 #undef JSON_TRY
8175 #undef JSON_LIKELY
8176 #undef JSON_UNLIKELY
8177 #undef JSON_HAS_CPP_14
8178 #undef JSON_HAS_CPP_17
8179 #undef NLOHMANN_BASIC_JSON_TPL_DECLARATION
8180 #undef NLOHMANN_BASIC_JSON_TPL
8181 #undef NLOHMANN_JSON_HAS_HELPER
8182 
8183 #endif // WPI_JSON_IMPLEMENTATION
8184 
8185 #endif
iteration_proxy_internal end() noexcept
return iterator end (needed for range-based for)
Definition: json.h:2214
This class implements an extremely fast bulk output stream that can only output to a stream...
Definition: raw_ostream.h:45
static allocator_type get_allocator()
returns the allocator associated with the container
Definition: json.h:2820
friend bool operator==(const_reference lhs, const ScalarType rhs) noexcept
comparison: equal
Definition: json.h:6714
friend bool operator==(const ScalarType lhs, const_reference rhs) noexcept
comparison: equal
Definition: json.h:6725
IteratorType erase(IteratorType first, IteratorType last)
remove elements given an iterator range
Definition: json.h:5398
std::size_t operator()(const wpi::json &j) const
return a hash value for a JSON object
Definition: json.h:8098
iteration_proxy< const_iterator > items() const noexcept
helper to access iterator member functions in range-based for
Definition: json.h:5913
friend bool operator>(const_reference lhs, const_reference rhs) noexcept
comparison: greater than
Definition: json.h:6890
Definition: json.h:275
std::vector< json > array_t
a type for an array
Definition: json.h:2953
Definition: json.h:284
ValueType value(const json_pointer &ptr, const ValueType &default_value) const
access specified object element via JSON Pointer with default value
Definition: json.h:5135
const_reference operator[](T *key) const
read-only access specified object element
Definition: json.h:5003
::wpi::json_pointer json_pointer
Definition: json.h:2745
json_reverse_iterator operator+(difference_type i) const
add to iterator
Definition: json.h:2290
void swap(array_t &other)
exchanges the values
Definition: json.h:6578
reference front()
access the first element
Definition: json.h:5188
bool is_null() const noexcept
return whether value is null
Definition: json.h:3950
std::initializer_list< detail::json_ref< json >> initializer_list_t
helper type for initializer lists of json values
Definition: json.h:2749
value_t
the JSON type enumeration
Definition: json.h:760
reference operator+=(const json &val)
add an object to an array
Definition: json.h:6147
number value (signed integer)
bool is_discarded() const noexcept
return whether value is discarded
Definition: json.h:4180
iterator end() noexcept
returns an iterator to one past the last element
Definition: json.h:5674
default JSONSerializer template argument
Definition: json.h:83
void erase(IteratorType pos)
remove element given an iterator
Definition: json.h:5297
const_reference back() const
access the last element
Definition: json.h:5242
constexpr bool is_end() const noexcept
return whether the iterator is at end
Definition: json.h:1455
Definition: json.h:424
const_reference at(const json_pointer &ptr) const
access specified element via JSON Pointer
Definition: json.h:7847
bool operator()(wpi::detail::value_t lhs, wpi::detail::value_t rhs) const noexcept
compare two value_t enum values
Definition: json.h:8116
friend bool operator!=(const_reference lhs, const ScalarType rhs) noexcept
comparison: not equal
Definition: json.h:6759
const_iterator cbegin() const noexcept
returns a const iterator to the first element
Definition: json.h:5643
std::string value(const json_pointer &ptr, const char *default_value) const
overload for a default value of type const char*
Definition: json.h:5158
static json object(initializer_list_t init={})
explicitly create an object from an initializer list
Definition: json.h:3478
Definition: optional.h:885
friend bool operator<=(const ScalarType lhs, const_reference rhs) noexcept
comparison: less than or equal
Definition: json.h:6866
value_t type() const noexcept
return the type of the JSON value (explicit)
Definition: json.h:3871
bool is_structured() const noexcept
return whether type is structured
Definition: json.h:3928
iterator begin() noexcept
returns an iterator to the first element
Definition: json.h:5603
reference value() const
return the value of an iterator
Definition: json.h:2321
void push_back(const std::pair< T, U > &val)
add an object to an object
Definition: json.h:6174
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory)...
Definition: ArrayRef.h:41
reference operator[](T *key)
access specified object element
Definition: json.h:4953
friend bool operator>=(const ScalarType lhs, const_reference rhs) noexcept
comparison: greater than or equal
Definition: json.h:6958
bool is_number_integer() const noexcept
return whether value is an integer number
Definition: json.h:4031
reference operator+=(initializer_list_t init)
add an object to an object
Definition: json.h:6236
reference operator[](difference_type n) const
access to successor
Definition: json.h:2308
WPILib C++ utilities (wpiutil) namespace.
Definition: SmallString.h:21
const_iterator end() const noexcept
returns a const iterator to one past the last element
Definition: json.h:5684
const_reverse_iterator rend() const noexcept
returns a const reverse iterator to one before the first
Definition: json.h:5789
void swap(std::string &other)
exchanges the values
Definition: json.h:6644
constexpr bool is_begin() const noexcept
return whether the iterator can be dereferenced
Definition: json.h:1449
json(json &&other) noexcept
move constructor
Definition: json.h:3710
json_reverse_iterator const operator--(int)
post-decrement (it–)
Definition: json.h:2272
reference at(const json_pointer &ptr)
access specified element via JSON Pointer
Definition: json.h:7804
void swap(object_t &other)
exchanges the values
Definition: json.h:6611
bool is_boolean() const noexcept
return whether value is a boolean
Definition: json.h:3972
Definition: json.h:211
reverse_iterator rbegin() noexcept
returns an iterator to the reverse-beginning
Definition: json.h:5744
static json array(initializer_list_t init={})
explicitly create an array from an initializer list
Definition: json.h:3435
iterator insert(const_iterator pos, json &&val)
inserts element
Definition: json.h:6366
static json parse(StringRef s, const parser_callback_t cb=nullptr, const bool allow_exceptions=true)
deserialize from a compatible input
ReferenceType get_ref()
get a reference value (implicit)
Definition: json.h:4619
a template for a bidirectional iterator for the json class
Definition: json.h:1561
Definition: json.h:236
iteration_proxy< iterator > items() noexcept
helper to access iterator member functions in range-based for
Definition: json.h:5905
json_reverse_iterator(const base_iterator &it) noexcept
create reverse iterator from base class
Definition: json.h:2257
friend bool operator>(const_reference lhs, const ScalarType rhs) noexcept
comparison: greater than
Definition: json.h:6901
proxy class for the items() function
Definition: json.h:1538
PointerType get_ptr() noexcept
get a pointer value (implicit)
Definition: json.h:4542
Definition: json.h:271
iteration_proxy(typename IteratorType::reference cont) noexcept
construct iteration proxy from a container
Definition: json.h:2204
Definition: raw_istream.h:26
reference operator[](const json_pointer &ptr)
access specified element via JSON Pointer
Definition: json.h:7733
auto find(R &&Range, const T &Val) -> decltype(adl_begin(Range))
Provide wrappers to std::find which take ranges instead of having to pass begin/end explicitly...
Definition: STLExtras.h:896
reference operator+=(const std::pair< T, U > &val)
add an object to an object
Definition: json.h:6199
static parse_error create(int id_, std::size_t byte_, const Twine &what_arg)
create a parse error exception
const_reverse_iterator crbegin() const noexcept
returns a const reverse iterator to the last element
Definition: json.h:5818
bool is_array() const noexcept
return whether value is an array
Definition: json.h:4131
bool is_number_unsigned() const noexcept
return whether value is an unsigned integer number
Definition: json.h:4059
const int id
the id of the exception
Definition: json.h:482
number value (floating-point)
json(std::nullptr_t=nullptr) noexcept
create a null object
Definition: json.h:3245
friend bool operator<=(const_reference lhs, const ScalarType rhs) noexcept
comparison: less than or equal
Definition: json.h:6855
void set_end() noexcept
set iterator to a defined past the end
Definition: json.h:1443
exception indicating access out of the defined range
Definition: json.h:690
array (ordered collection of values)
ReferenceType get_ref() const
get a reference value (implicit)
Definition: json.h:4632
const_reverse_iterator rbegin() const noexcept
returns a const reverse iterator to the last element
Definition: json.h:5752
std::reverse_iterator< Base > base_iterator
shortcut to the reverse iterator adapter
Definition: json.h:2248
general exception of the json class
Definition: json.h:472
Definition: json.h:243
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:2645
Definition: json.h:1097
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:3312
json_pointer(const Twine &s={})
create JSON pointer
Definition: json.h:2410
Definition: json.h:1420
friend bool operator>=(const_reference lhs, const_reference rhs) noexcept
comparison: greater than or equal
Definition: json.h:6936
friend bool operator<=(const_reference lhs, const_reference rhs) noexcept
comparison: less than or equal
Definition: json.h:6844
Definition: json.h:274
bool operator<(const value_t lhs, const value_t rhs) noexcept
comparison operator for JSON types
Definition: json.h:783
Definition: json.h:400
bool is_string() const noexcept
return whether value is a string
Definition: json.h:4153
exception indicating other library errors
Definition: json.h:723
Definition: json.h:2382
std::string value(StringRef key, const char *default_value) const
overload for a default value of type const char*
Definition: json.h:5087
json_reverse_iterator operator-(difference_type i) const
subtract from iterator
Definition: json.h:2296
std::pair< iterator, bool > emplace(StringRef key, Args &&...args)
add an object to an object if key does not exist
Definition: json.h:6312
json(const value_t v)
create an empty value with a given type
Definition: json.h:3221
number value (unsigned integer)
Definition: json.h:1369
json(InputIT first, InputIT last)
construct a JSON container given an iterator range
Definition: json.h:3565
friend bool operator<(const_reference lhs, const ScalarType rhs) noexcept
comparison: less than
Definition: json.h:6809
an iterator value
Definition: json.h:1527
object (unordered set of name/value pairs)
auto key() const -> decltype(std::declval< Base >().key())
return the key of an object iterator
Definition: json.h:2314
friend bool operator!=(const ScalarType lhs, const_reference rhs) noexcept
comparison: not equal
Definition: json.h:6770
Definition: json.h:316
friend bool operator>(const ScalarType lhs, const_reference rhs) noexcept
comparison: greater than
Definition: json.h:6912
const std::size_t byte
byte index of the parse error
Definition: json.h:557
a class to store JSON values
Definition: json.h:2714
~json() noexcept
destructor
Definition: json.h:3780
Definition: json.h:2329
Definition: json.h:225
reference back()
access the last element
Definition: json.h:5232
typename Base::reference reference
the reference type for the pointed-to element
Definition: json.h:2250
auto size(R &&Range, typename std::enable_if< std::is_same< typename std::iterator_traits< decltype(Range.begin())>::iterator_category, std::random_access_iterator_tag >::value, void >::type *=nullptr) -> decltype(std::distance(Range.begin(), Range.end()))
Get the size of a range.
Definition: STLExtras.h:999
json_reverse_iterator & operator+=(difference_type i)
add to iterator
Definition: json.h:2284
Definition: json.h:432
iterator find(StringRef key)
find an element in a JSON object
bool is_number() const noexcept
return whether value is a number
Definition: json.h:4002
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:2629
exception indicating a parse error
Definition: json.h:535
exception indicating errors with iterators
Definition: json.h:601
bool is_number_float() const noexcept
return whether value is a floating-point number
Definition: json.h:4087
const PointerType get_ptr() const noexcept
get a pointer value (implicit)
Definition: json.h:4570
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:49
const char * what() const noexceptoverride
returns the explanatory string
Definition: json.h:476
iteration_proxy_internal begin() noexcept
return iterator begin (needed for range-based for)
Definition: json.h:2208
reference & operator=(json other) noexcept(std::is_nothrow_move_constructible< value_t >::value andstd::is_nothrow_move_assignable< value_t >::value andstd::is_nothrow_move_constructible< json_value >::value andstd::is_nothrow_move_assignable< json_value >::value)
copy assignment
Definition: json.h:3747
bool is_object() const noexcept
return whether value is an object
Definition: json.h:4109
std::size_t size_type
a type to represent container sizes
Definition: json.h:2795
friend bool operator>=(const_reference lhs, const ScalarType rhs) noexcept
comparison: greater than or equal
Definition: json.h:6947
json unflatten() const
unflatten a previously flattened JSON value
Definition: json.h:7911
auto count(R &&Range, const E &Element) -> typename std::iterator_traits< decltype(adl_begin(Range))>::difference_type
Wrapper function around std::count to count the number of times an element Element occurs in the give...
Definition: STLExtras.h:941
std::string dump(const int indent=-1, const char indent_char= ' ', const bool ensure_ascii=false) const
serialization
StringMap - This is an unconventional map that is specialized for handling keys that are "strings"...
Definition: StringMap.h:205
json_reverse_iterator const operator++(int)
post-increment (it++)
Definition: json.h:2260
exception indicating executing a member function with a wrong type
Definition: json.h:649
Definition: json.h:366
void swap(reference other) noexcept(std::is_nothrow_move_constructible< value_t >::value andstd::is_nothrow_move_assignable< value_t >::value andstd::is_nothrow_move_constructible< json_value >::value andstd::is_nothrow_move_assignable< json_value >::value)
exchanges the values
Definition: json.h:6546
ValueType value(StringRef key, const ValueType &default_value) const
access specified object element with default value
Definition: json.h:5065
const_reference operator[](const json_pointer &ptr) const
access specified element via JSON Pointer
Definition: json.h:7761
const_reference front() const
access the first element
Definition: json.h:5196
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
Definition: Twine.h:79
const_iterator cend() const noexcept
returns a const iterator to one past the last element
Definition: json.h:5714
json_reverse_iterator(const typename base_iterator::iterator_type &it) noexcept
create reverse iterator from iterator
Definition: json.h:2253
void emplace_back(Args &&...args)
add an object to an array
Definition: json.h:6264
reverse_iterator rend() noexcept
returns an iterator to the reverse-end
Definition: json.h:5781
json_reverse_iterator & operator--()
pre-decrement (–it)
Definition: json.h:2278
void set_begin() noexcept
set iterator to a defined beginning
Definition: json.h:1437
const_reverse_iterator crend() const noexcept
returns a const reverse iterator to one before the first
Definition: json.h:5847
Definition: json.h:266
parse_event_t
parser event types
Definition: json.h:3114
const_iterator begin() const noexcept
returns a const iterator to the first element
Definition: json.h:5613
Definition: json.h:1049
std::ptrdiff_t difference_type
a type to represent differences between iterators
Definition: json.h:2793
friend bool operator<(const ScalarType lhs, const_reference rhs) noexcept
comparison: less than
Definition: json.h:6820
discarded by the the parser callback function
difference_type operator-(const json_reverse_iterator &other) const
return difference
Definition: json.h:2302
std::allocator< json > allocator_type
the allocator type
Definition: json.h:2798
bool is_primitive() const noexcept
return whether type is primitive
Definition: json.h:3901
friend bool operator!=(const_reference lhs, const_reference rhs) noexcept
comparison: not equal
Definition: json.h:6748
json flatten() const
return flattened JSON value
Definition: json.h:7874
Definition: json.h:267
json_reverse_iterator & operator++()
pre-increment (++it)
Definition: json.h:2266
a template for a reverse iterator class
Definition: json.h:2243