webkit  2cdf99a9e3038c7e01b3c37e8ad903ecbe5eecf1
https://github.com/WebKit/webkit
json.hpp
Go to the documentation of this file.
1 /*
2  * **************************************************************************
3  *
4  * DO NOT USE THIS JSON LIBRARY!
5  *
6  * This JSON library exists as a temporary facility for reading and writing
7  * JSON files. Ultimately, we should be using the JSON facilities that are in
8  * JavaScriptCore. However, those are too heavy-weight for what we want in the
9  * NetworkProcess. The NetworkProcess currently doesn't use JavaScriptCore and
10  * doesn't allocate the data structures and memory-handling facilities that JSC
11  * requires. All we want is something that will do the simple streaming and
12  * parsing of JSON. To ultimately achieve this, we will be modifying the
13  * JSONParse in JSC to be lighter-weight, performing just the streaming or
14  * parsing and leaving the memory management and object creation to the caller.
15  * This will be similar to howe YarrParser works. The new JSONParse will be
16  * used here and in other places like in ContextExtensionParser. Until then, we
17  * use this library.
18  *
19  * In that context, this library should not be used by anyone else. It will be
20  * going away. Also, it has not been vetted for security issues that might
21  * arise if it were used in a context where customer data is being manipulated.
22  *
23  * DO NOT USE THIS JSON LIBRARY!
24  *
25  * **************************************************************************
26  *
27  * This file was taken from <https://github.com/nlohmann/json> at revision
28  * e717492019687bf0edf2b884b51bf37db4831a6f and modified as follows for
29  * inclusion in WebKit:
30  *
31  * * Exceptions are disabled in WebKit, so all 'throw' statements were
32  * converted into a call to a Throw function. This function can be enabled
33  * to invoke 'throw' as before, but by default asserts and crashes.
34  * * try/catch statements are also disallowed, so these were converted into
35  * simple if/then checks where possible. Where not possible, the try/catch
36  * statements were simply removed with the expectation that no code paths
37  * would trigger the anticipated exceptions.
38  * * For efficiency, a basic_json constructor that takes a
39  * string_t::value_type* and a count was added.
40  *
41  * **************************************************************************
42  */
43 
44 /*
45  __ _____ _____ _____
46  __| | __| | | | JSON for Modern C++
47 | | |__ | | | | | | version 2.0.7
48 |_____|_____|_____|_|___| https://github.com/nlohmann/json
49 
50 Licensed under the MIT License <http://opensource.org/licenses/MIT>.
51 Copyright (c) 2013-2016 Niels Lohmann <http://nlohmann.me>.
52 
53 Permission is hereby granted, free of charge, to any person obtaining a copy
54 of this software and associated documentation files (the "Software"), to deal
55 in the Software without restriction, including without limitation the rights
56 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
57 copies of the Software, and to permit persons to whom the Software is
58 furnished to do so, subject to the following conditions:
59 
60 The above copyright notice and this permission notice shall be included in all
61 copies or substantial portions of the Software.
62 
63 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
64 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
65 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
66 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
67 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
68 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
69 SOFTWARE.
70 */
71 
72 #ifndef NLOHMANN_JSON_HPP
73 #define NLOHMANN_JSON_HPP
74 
75 #include <algorithm> // all_of, for_each, transform
76 #include <array> // array
77 #include <cassert> // assert
78 #include <cctype> // isdigit
79 #include <ciso646> // and, not, or
80 #include <cmath> // isfinite, signbit
81 #include <cstddef> // nullptr_t, ptrdiff_t, size_t
82 #include <cstdint> // int64_t, uint64_t
83 #include <cstdlib> // strtod, strtof, strtold, strtoul
84 #include <cstring> // strlen
85 #include <functional> // function, hash, less
86 #include <initializer_list> // initializer_list
87 #include <iomanip> // setw
88 #include <iostream> // istream, ostream
89 #include <iterator> // advance, begin, bidirectional_iterator_tag, distance, end, inserter, iterator, iterator_traits, next, random_access_iterator_tag, reverse_iterator
90 #include <limits> // numeric_limits
91 #include <locale> // locale
92 #include <map> // map
93 #include <memory> // addressof, allocator, allocator_traits, unique_ptr
94 #include <numeric> // accumulate
95 #include <sstream> // stringstream
96 #include <stdexcept> // domain_error, invalid_argument, out_of_range
97 #include <string> // getline, stoi, string, to_string
98 #include <type_traits> // add_pointer, enable_if, is_arithmetic, is_base_of, is_const, is_constructible, is_convertible, is_floating_point, is_integral, is_nothrow_move_assignable, std::is_nothrow_move_constructible, std::is_pointer, std::is_reference, std::is_same, remove_const, remove_pointer, remove_reference
99 #include <utility> // declval, forward, make_pair, move, pair, swap
100 #include <vector> // vector
101 
102 #include <wtf/Assertions.h> // ASSERT
103 #include <wtf/Compiler.h> // NO_RETURN
104 
105 // exclude unsupported compilers
106 #if defined(__clang__)
107  #define CLANG_VERSION (__clang_major__ * 10000 + __clang_minor__ * 100 + __clang_patchlevel__)
108  #if CLANG_VERSION < 30400
109  #error "unsupported Clang version - see https://github.com/nlohmann/json#supported-compilers"
110  #endif
111 #elif defined(__GNUC__)
112  #define GCC_VERSION (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__)
113  #if GCC_VERSION < 40900
114  #error "unsupported GCC version - see https://github.com/nlohmann/json#supported-compilers"
115  #endif
116 #endif
117 
118 // disable float-equal warnings on GCC/clang
119 #if defined(__clang__) || defined(__GNUC__) || defined(__GNUG__)
120  #pragma GCC diagnostic push
121  #pragma GCC diagnostic ignored "-Wfloat-equal"
122 #endif
123 
124 // allow for portable deprecation warnings
125 #if defined(__clang__) || defined(__GNUC__) || defined(__GNUG__)
126  #define JSON_DEPRECATED __attribute__((deprecated))
127 #elif defined(_MSC_VER)
128  #define JSON_DEPRECATED __declspec(deprecated)
129 #else
130  #define JSON_DEPRECATED
131 #endif
132 
138 namespace nlohmann
139 {
140 
141 
146 namespace
147 {
158 template<typename T>
159 struct has_mapped_type
160 {
161  private:
162  template <typename U, typename = typename U::mapped_type>
163  static int detect(U&&);
164 
165  static void detect(...);
166  public:
167  static constexpr bool value =
168  std::is_integral<decltype(detect(std::declval<T>()))>::value;
169 };
170 
171 template <typename T, typename ... Types>
172 NO_RETURN void Throw(Types ... args)
173 {
174 #if 0
175  throw T(std::forward<Types>(args)...);
176 #else
177  ASSERT(false);
178  WTFCrash();
179 #endif
180 }
181 }
182 
261 template <
262  template<typename U, typename V, typename... Args> class ObjectType = std::map,
263  template<typename U, typename... Args> class ArrayType = std::vector,
264  class StringType = std::string,
265  class BooleanType = bool,
266  class NumberIntegerType = std::int64_t,
267  class NumberUnsignedType = std::uint64_t,
268  class NumberFloatType = double,
269  template<typename U> class AllocatorType = std::allocator
270  >
272 {
273  private:
276  BooleanType, NumberIntegerType, NumberUnsignedType, NumberFloatType,
277  AllocatorType>;
278 
279  public:
280  // forward declarations
281  template<typename Base> class json_reverse_iterator;
282  class json_pointer;
283 
285  // container types //
287 
292 
295 
299  using const_reference = const value_type&;
300 
305 
307  using allocator_type = AllocatorType<basic_json>;
308 
312  using const_pointer = typename std::allocator_traits<allocator_type>::const_pointer;
313 
315  class iterator;
317  class const_iterator;
322 
324 
325 
330  {
331  return allocator_type();
332  }
333 
334 
336  // JSON value data types //
338 
343 
427  using object_t = ObjectType<StringType,
428  basic_json,
429  std::less<StringType>,
430  AllocatorType<std::pair<const StringType,
431  basic_json>>>;
432 
477  using array_t = ArrayType<basic_json, AllocatorType<basic_json>>;
478 
525 
551 
622  using number_integer_t = NumberIntegerType;
623 
693  using number_unsigned_t = NumberUnsignedType;
694 
761  using number_float_t = NumberFloatType;
762 
764 
765 
767  // JSON type enumeration //
769 
792  enum class value_t : uint8_t
793  {
794  null,
795  object,
796  array,
797  string,
798  boolean,
799  number_integer,
800  number_unsigned,
801  number_float,
802  discarded
803  };
804 
805 
806  private:
807 
809  template<typename T, typename... Args>
810  static T* create(Args&& ... args)
811  {
812  AllocatorType<T> alloc;
813  auto deleter = [&](T * object)
814  {
815  alloc.deallocate(object, 1);
816  };
817  std::unique_ptr<T, decltype(deleter)> object(alloc.allocate(1), deleter);
818  alloc.construct(object.get(), std::forward<Args>(args)...);
819  assert(object.get() != nullptr);
820  return object.release();
821  }
822 
824  // JSON value storage //
826 
851  union json_value
852  {
854  object_t* object;
856  array_t* array;
858  string_t* string;
862  number_integer_t number_integer;
864  number_unsigned_t number_unsigned;
866  number_float_t number_float;
867 
869  json_value() = default;
871  json_value(boolean_t v) noexcept : boolean(v) {}
873  json_value(number_integer_t v) noexcept : number_integer(v) {}
875  json_value(number_unsigned_t v) noexcept : number_unsigned(v) {}
877  json_value(number_float_t v) noexcept : number_float(v) {}
879  json_value(value_t t)
880  {
881  switch (t)
882  {
883  case value_t::object:
884  {
885  object = create<object_t>();
886  break;
887  }
888 
889  case value_t::array:
890  {
891  array = create<array_t>();
892  break;
893  }
894 
895  case value_t::string:
896  {
897  string = create<string_t>("");
898  break;
899  }
900 
901  case value_t::boolean:
902  {
903  boolean = boolean_t(false);
904  break;
905  }
906 
907  case value_t::number_integer:
908  {
909  number_integer = number_integer_t(0);
910  break;
911  }
912 
913  case value_t::number_unsigned:
914  {
915  number_unsigned = number_unsigned_t(0);
916  break;
917  }
918 
919  case value_t::number_float:
920  {
921  number_float = number_float_t(0.0);
922  break;
923  }
924 
925  default:
926  {
927  break;
928  }
929  }
930  }
931 
933  json_value(const string_t& value)
934  {
935  string = create<string_t>(value);
936  }
937 
939  json_value(const object_t& value)
940  {
941  object = create<object_t>(value);
942  }
943 
945  json_value(const array_t& value)
946  {
947  array = create<array_t>(value);
948  }
949  };
950 
960  void assert_invariant() const
961  {
962  assert(m_type != value_t::object or m_value.object != nullptr);
963  assert(m_type != value_t::array or m_value.array != nullptr);
964  assert(m_type != value_t::string or m_value.string != nullptr);
965  }
966 
967  public:
969  // JSON parser callback //
971 
982  enum class parse_event_t : uint8_t
983  {
985  object_start,
987  object_end,
989  array_start,
991  array_end,
993  key,
995  value
996  };
997 
1050  using parser_callback_t = std::function<bool(int depth,
1051  parse_event_t event,
1052  basic_json& parsed)>;
1053 
1054 
1056  // constructors //
1058 
1063 
1104  : m_type(value_type), m_value(value_type)
1105  {
1106  assert_invariant();
1107  }
1108 
1127  basic_json(std::nullptr_t = nullptr) noexcept
1128  : basic_json(value_t::null)
1129  {
1130  assert_invariant();
1131  }
1132 
1153  : m_type(value_t::object), m_value(val)
1154  {
1155  assert_invariant();
1156  }
1157 
1184  template<class CompatibleObjectType, typename std::enable_if<
1185  std::is_constructible<typename object_t::key_type, typename CompatibleObjectType::key_type>::value and
1186  std::is_constructible<basic_json, typename CompatibleObjectType::mapped_type>::value, int>::type = 0>
1187  basic_json(const CompatibleObjectType& val)
1188  : m_type(value_t::object)
1189  {
1190  using std::begin;
1191  using std::end;
1192  m_value.object = create<object_t>(begin(val), end(val));
1193  assert_invariant();
1194  }
1195 
1216  : m_type(value_t::array), m_value(val)
1217  {
1218  assert_invariant();
1219  }
1220 
1247  template<class CompatibleArrayType, typename std::enable_if<
1248  not std::is_same<CompatibleArrayType, typename basic_json_t::iterator>::value and
1249  not std::is_same<CompatibleArrayType, typename basic_json_t::const_iterator>::value and
1250  not std::is_same<CompatibleArrayType, typename basic_json_t::reverse_iterator>::value and
1251  not std::is_same<CompatibleArrayType, typename basic_json_t::const_reverse_iterator>::value and
1252  not std::is_same<CompatibleArrayType, typename array_t::iterator>::value and
1253  not std::is_same<CompatibleArrayType, typename array_t::const_iterator>::value and
1254  std::is_constructible<basic_json, typename CompatibleArrayType::value_type>::value, int>::type = 0>
1255  basic_json(const CompatibleArrayType& val)
1256  : m_type(value_t::array)
1257  {
1258  using std::begin;
1259  using std::end;
1260  m_value.array = create<array_t>(begin(val), end(val));
1261  assert_invariant();
1262  }
1263 
1286  : m_type(value_t::string), m_value(val)
1287  {
1288  assert_invariant();
1289  }
1290 
1311  basic_json(const typename string_t::value_type* val)
1312  : basic_json(string_t(val))
1313  {
1314  assert_invariant();
1315  }
1316 
1317  basic_json(const typename string_t::value_type* val, typename string_t::size_type count)
1318  : basic_json(string_t(val, count))
1319  {
1320  assert_invariant();
1321  }
1322 
1346  template<class CompatibleStringType, typename std::enable_if<
1347  std::is_constructible<string_t, CompatibleStringType>::value, int>::type = 0>
1348  basic_json(const CompatibleStringType& val)
1349  : basic_json(string_t(val))
1350  {
1351  assert_invariant();
1352  }
1353 
1369  : m_type(value_t::boolean), m_value(val)
1370  {
1371  assert_invariant();
1372  }
1373 
1397  template<typename T, typename std::enable_if<
1398  not (std::is_same<T, int>::value) and
1399  std::is_same<T, number_integer_t>::value, int>::type = 0>
1401  : m_type(value_t::number_integer), m_value(val)
1402  {
1403  assert_invariant();
1404  }
1405 
1431  basic_json(const int val) noexcept
1432  : m_type(value_t::number_integer),
1433  m_value(static_cast<number_integer_t>(val))
1434  {
1435  assert_invariant();
1436  }
1437 
1463  template<typename CompatibleNumberIntegerType, typename std::enable_if<
1464  std::is_constructible<number_integer_t, CompatibleNumberIntegerType>::value and
1465  std::numeric_limits<CompatibleNumberIntegerType>::is_integer and
1466  std::numeric_limits<CompatibleNumberIntegerType>::is_signed,
1467  CompatibleNumberIntegerType>::type = 0>
1468  basic_json(const CompatibleNumberIntegerType val) noexcept
1469  : m_type(value_t::number_integer),
1470  m_value(static_cast<number_integer_t>(val))
1471  {
1472  assert_invariant();
1473  }
1474 
1492  template<typename T, typename std::enable_if<
1493  not (std::is_same<T, int>::value) and
1494  std::is_same<T, number_unsigned_t>::value, int>::type = 0>
1496  : m_type(value_t::number_unsigned), m_value(val)
1497  {
1498  assert_invariant();
1499  }
1500 
1521  template<typename CompatibleNumberUnsignedType, typename std::enable_if <
1522  std::is_constructible<number_unsigned_t, CompatibleNumberUnsignedType>::value and
1523  std::numeric_limits<CompatibleNumberUnsignedType>::is_integer and
1524  not std::numeric_limits<CompatibleNumberUnsignedType>::is_signed,
1525  CompatibleNumberUnsignedType>::type = 0>
1526  basic_json(const CompatibleNumberUnsignedType val) noexcept
1527  : m_type(value_t::number_unsigned),
1528  m_value(static_cast<number_unsigned_t>(val))
1529  {
1530  assert_invariant();
1531  }
1532 
1558  : m_type(value_t::number_float), m_value(val)
1559  {
1560  // replace infinity and NAN by null
1561  if (not std::isfinite(val))
1562  {
1563  m_type = value_t::null;
1564  m_value = json_value();
1565  }
1566 
1567  assert_invariant();
1568  }
1569 
1601  template<typename CompatibleNumberFloatType, typename = typename std::enable_if<
1602  std::is_constructible<number_float_t, CompatibleNumberFloatType>::value and
1603  std::is_floating_point<CompatibleNumberFloatType>::value>::type>
1604  basic_json(const CompatibleNumberFloatType val) noexcept
1606  {
1607  assert_invariant();
1608  }
1609 
1679  basic_json(std::initializer_list<basic_json> init,
1680  bool type_deduction = true,
1681  value_t manual_type = value_t::array)
1682  {
1683  // check if each element is an array with two elements whose first
1684  // element is a string
1685  bool is_an_object = std::all_of(init.begin(), init.end(),
1686  [](const basic_json & element)
1687  {
1688  return element.is_array() and element.size() == 2 and element[0].is_string();
1689  });
1690 
1691  // adjust type if type deduction is not wanted
1692  if (not type_deduction)
1693  {
1694  // if array is wanted, do not create an object though possible
1695  if (manual_type == value_t::array)
1696  {
1697  is_an_object = false;
1698  }
1699 
1700  // if object is wanted but impossible, throw an exception
1701  if (manual_type == value_t::object and not is_an_object)
1702  {
1703  Throw<std::domain_error>("cannot create object from initializer list");
1704  }
1705  }
1706 
1707  if (is_an_object)
1708  {
1709  // the initializer list is a list of pairs -> create object
1711  m_value = value_t::object;
1712 
1713  std::for_each(init.begin(), init.end(), [this](const basic_json & element)
1714  {
1715  m_value.object->emplace(*(element[0].m_value.string), element[1]);
1716  });
1717  }
1718  else
1719  {
1720  // the initializer list describes an array -> create array
1722  m_value.array = create<array_t>(init);
1723  }
1724 
1725  assert_invariant();
1726  }
1727 
1762  static basic_json array(std::initializer_list<basic_json> init =
1763  std::initializer_list<basic_json>())
1764  {
1765  return basic_json(init, false, value_t::array);
1766  }
1767 
1802  static basic_json object(std::initializer_list<basic_json> init =
1803  std::initializer_list<basic_json>())
1804  {
1805  return basic_json(init, false, value_t::object);
1806  }
1807 
1827  : m_type(value_t::array)
1828  {
1829  m_value.array = create<array_t>(cnt, val);
1830  assert_invariant();
1831  }
1832 
1870  template<class InputIT, typename std::enable_if<
1871  std::is_same<InputIT, typename basic_json_t::iterator>::value or
1872  std::is_same<InputIT, typename basic_json_t::const_iterator>::value, int>::type = 0>
1873  basic_json(InputIT first, InputIT last)
1874  {
1875  assert(first.m_object != nullptr);
1876  assert(last.m_object != nullptr);
1877 
1878  // make sure iterator fits the current value
1879  if (first.m_object != last.m_object)
1880  {
1881  Throw<std::domain_error>("iterators are not compatible");
1882  }
1883 
1884  // copy type from first iterator
1885  m_type = first.m_object->m_type;
1886 
1887  // check if iterator range is complete for primitive values
1888  switch (m_type)
1889  {
1890  case value_t::boolean:
1891  case value_t::number_float:
1892  case value_t::number_integer:
1893  case value_t::number_unsigned:
1894  case value_t::string:
1895  {
1896  if (not first.m_it.primitive_iterator.is_begin() or not last.m_it.primitive_iterator.is_end())
1897  {
1898  Throw<std::out_of_range>("iterators out of range");
1899  }
1900  break;
1901  }
1902 
1903  default:
1904  {
1905  break;
1906  }
1907  }
1908 
1909  switch (m_type)
1910  {
1911  case value_t::number_integer:
1912  {
1913  m_value.number_integer = first.m_object->m_value.number_integer;
1914  break;
1915  }
1916 
1917  case value_t::number_unsigned:
1918  {
1919  m_value.number_unsigned = first.m_object->m_value.number_unsigned;
1920  break;
1921  }
1922 
1923  case value_t::number_float:
1924  {
1925  m_value.number_float = first.m_object->m_value.number_float;
1926  break;
1927  }
1928 
1929  case value_t::boolean:
1930  {
1931  m_value.boolean = first.m_object->m_value.boolean;
1932  break;
1933  }
1934 
1935  case value_t::string:
1936  {
1937  m_value = *first.m_object->m_value.string;
1938  break;
1939  }
1940 
1941  case value_t::object:
1942  {
1943  m_value.object = create<object_t>(first.m_it.object_iterator, last.m_it.object_iterator);
1944  break;
1945  }
1946 
1947  case value_t::array:
1948  {
1949  m_value.array = create<array_t>(first.m_it.array_iterator, last.m_it.array_iterator);
1950  break;
1951  }
1952 
1953  default:
1954  {
1955  Throw<std::domain_error>("cannot use construct with iterators from " + first.m_object->type_name());
1956  }
1957  }
1958 
1959  assert_invariant();
1960  }
1961 
1991  explicit basic_json(std::istream& i, const parser_callback_t cb = nullptr)
1992  {
1993  *this = parser(i, cb).parse();
1994  assert_invariant();
1995  }
1996 
1998  // other constructors and destructor //
2000 
2023  basic_json(const basic_json& other)
2024  : m_type(other.m_type)
2025  {
2026  // check of passed value is valid
2027  other.assert_invariant();
2028 
2029  switch (m_type)
2030  {
2031  case value_t::object:
2032  {
2033  m_value = *other.m_value.object;
2034  break;
2035  }
2036 
2037  case value_t::array:
2038  {
2039  m_value = *other.m_value.array;
2040  break;
2041  }
2042 
2043  case value_t::string:
2044  {
2045  m_value = *other.m_value.string;
2046  break;
2047  }
2048 
2049  case value_t::boolean:
2050  {
2051  m_value = other.m_value.boolean;
2052  break;
2053  }
2054 
2055  case value_t::number_integer:
2056  {
2057  m_value = other.m_value.number_integer;
2058  break;
2059  }
2060 
2061  case value_t::number_unsigned:
2062  {
2063  m_value = other.m_value.number_unsigned;
2064  break;
2065  }
2066 
2067  case value_t::number_float:
2068  {
2069  m_value = other.m_value.number_float;
2070  break;
2071  }
2072 
2073  default:
2074  {
2075  break;
2076  }
2077  }
2078 
2079  assert_invariant();
2080  }
2081 
2100  basic_json(basic_json&& other) noexcept
2101  : m_type(std::move(other.m_type)),
2102  m_value(std::move(other.m_value))
2103  {
2104  // check that passed value is valid
2105  other.assert_invariant();
2106 
2107  // invalidate payload
2108  other.m_type = value_t::null;
2109  other.m_value = {};
2110 
2111  assert_invariant();
2112  }
2113 
2137  reference& operator=(basic_json other) noexcept (
2138  std::is_nothrow_move_constructible<value_t>::value and
2139  std::is_nothrow_move_assignable<value_t>::value and
2140  std::is_nothrow_move_constructible<json_value>::value and
2141  std::is_nothrow_move_assignable<json_value>::value
2142  )
2143  {
2144  // check that passed value is valid
2145  other.assert_invariant();
2146 
2147  using std::swap;
2148  swap(m_type, other.m_type);
2149  swap(m_value, other.m_value);
2150 
2151  assert_invariant();
2152  return *this;
2153  }
2154 
2171  {
2172  assert_invariant();
2173 
2174  switch (m_type)
2175  {
2176  case value_t::object:
2177  {
2178  AllocatorType<object_t> alloc;
2179  alloc.destroy(m_value.object);
2180  alloc.deallocate(m_value.object, 1);
2181  break;
2182  }
2183 
2184  case value_t::array:
2185  {
2186  AllocatorType<array_t> alloc;
2187  alloc.destroy(m_value.array);
2188  alloc.deallocate(m_value.array, 1);
2189  break;
2190  }
2191 
2192  case value_t::string:
2193  {
2194  AllocatorType<string_t> alloc;
2195  alloc.destroy(m_value.string);
2196  alloc.deallocate(m_value.string, 1);
2197  break;
2198  }
2199 
2200  default:
2201  {
2202  // all other types need no specific destructor
2203  break;
2204  }
2205  }
2206  }
2207 
2209 
2210  public:
2212  // object inspection //
2214 
2218 
2242  string_t dump(const int indent = -1) const
2243  {
2244  std::stringstream ss;
2245  // fix locale problems
2246  ss.imbue(std::locale::classic());
2247 
2248  // 6, 15 or 16 digits of precision allows round-trip IEEE 754
2249  // string->float->string, string->double->string or string->long
2250  // double->string; to be safe, we read this value from
2251  // std::numeric_limits<number_float_t>::digits10
2252  ss.precision(std::numeric_limits<double>::digits10);
2253 
2254  if (indent >= 0)
2255  {
2256  dump(ss, true, static_cast<unsigned int>(indent));
2257  }
2258  else
2259  {
2260  dump(ss, false, 0);
2261  }
2262 
2263  return ss.str();
2264  }
2265 
2284  constexpr value_t type() const noexcept
2285  {
2286  return m_type;
2287  }
2288 
2314  constexpr bool is_primitive() const noexcept
2315  {
2316  return is_null() or is_string() or is_boolean() or is_number();
2317  }
2318 
2341  constexpr bool is_structured() const noexcept
2342  {
2343  return is_array() or is_object();
2344  }
2345 
2363  constexpr bool is_null() const noexcept
2364  {
2365  return m_type == value_t::null;
2366  }
2367 
2385  constexpr bool is_boolean() const noexcept
2386  {
2387  return m_type == value_t::boolean;
2388  }
2389 
2415  constexpr bool is_number() const noexcept
2416  {
2417  return is_number_integer() or is_number_float();
2418  }
2419 
2444  constexpr bool is_number_integer() const noexcept
2445  {
2446  return m_type == value_t::number_integer or m_type == value_t::number_unsigned;
2447  }
2448 
2472  constexpr bool is_number_unsigned() const noexcept
2473  {
2474  return m_type == value_t::number_unsigned;
2475  }
2476 
2500  constexpr bool is_number_float() const noexcept
2501  {
2502  return m_type == value_t::number_float;
2503  }
2504 
2522  constexpr bool is_object() const noexcept
2523  {
2524  return m_type == value_t::object;
2525  }
2526 
2544  constexpr bool is_array() const noexcept
2545  {
2546  return m_type == value_t::array;
2547  }
2548 
2566  constexpr bool is_string() const noexcept
2567  {
2568  return m_type == value_t::string;
2569  }
2570 
2593  constexpr bool is_discarded() const noexcept
2594  {
2595  return m_type == value_t::discarded;
2596  }
2597 
2616  constexpr operator value_t() const noexcept
2617  {
2618  return m_type;
2619  }
2620 
2622 
2623  private:
2625  // value access //
2627 
2629  template<class T, typename std::enable_if<
2630  std::is_convertible<typename object_t::key_type, typename T::key_type>::value and
2631  std::is_convertible<basic_json_t, typename T::mapped_type>::value, int>::type = 0>
2632  T get_impl(T*) const
2633  {
2634  if (is_object())
2635  {
2636  return T(m_value.object->begin(), m_value.object->end());
2637  }
2638  else
2639  {
2640  Throw<std::domain_error>("type must be object, but is " + type_name());
2641  }
2642  }
2643 
2645  object_t get_impl(object_t*) const
2646  {
2647  if (is_object())
2648  {
2649  return *(m_value.object);
2650  }
2651  else
2652  {
2653  Throw<std::domain_error>("type must be object, but is " + type_name());
2654  }
2655  }
2656 
2658  template<class T, typename std::enable_if<
2659  std::is_convertible<basic_json_t, typename T::value_type>::value and
2660  not std::is_same<basic_json_t, typename T::value_type>::value and
2661  not std::is_arithmetic<T>::value and
2662  not std::is_convertible<std::string, T>::value and
2663  not has_mapped_type<T>::value, int>::type = 0>
2664  T get_impl(T*) const
2665  {
2666  if (is_array())
2667  {
2668  T to_vector;
2669  std::transform(m_value.array->begin(), m_value.array->end(),
2670  std::inserter(to_vector, to_vector.end()), [](basic_json i)
2671  {
2672  return i.get<typename T::value_type>();
2673  });
2674  return to_vector;
2675  }
2676  else
2677  {
2678  Throw<std::domain_error>("type must be array, but is " + type_name());
2679  }
2680  }
2681 
2683  template<class T, typename std::enable_if<
2684  std::is_convertible<basic_json_t, T>::value and
2685  not std::is_same<basic_json_t, T>::value, int>::type = 0>
2686  std::vector<T> get_impl(std::vector<T>*) const
2687  {
2688  if (is_array())
2689  {
2690  std::vector<T> to_vector;
2691  to_vector.reserve(m_value.array->size());
2692  std::transform(m_value.array->begin(), m_value.array->end(),
2693  std::inserter(to_vector, to_vector.end()), [](basic_json i)
2694  {
2695  return i.get<T>();
2696  });
2697  return to_vector;
2698  }
2699  else
2700  {
2701  Throw<std::domain_error>("type must be array, but is " + type_name());
2702  }
2703  }
2704 
2706  template<class T, typename std::enable_if<
2707  std::is_same<basic_json, typename T::value_type>::value and
2708  not has_mapped_type<T>::value, int>::type = 0>
2709  T get_impl(T*) const
2710  {
2711  if (is_array())
2712  {
2713  return T(m_value.array->begin(), m_value.array->end());
2714  }
2715  else
2716  {
2717  Throw<std::domain_error>("type must be array, but is " + type_name());
2718  }
2719  }
2720 
2722  array_t get_impl(array_t*) const
2723  {
2724  if (is_array())
2725  {
2726  return *(m_value.array);
2727  }
2728  else
2729  {
2730  Throw<std::domain_error>("type must be array, but is " + type_name());
2731  }
2732  }
2733 
2735  template<typename T, typename std::enable_if<
2736  std::is_convertible<string_t, T>::value, int>::type = 0>
2737  T get_impl(T*) const
2738  {
2739  if (is_string())
2740  {
2741  return *m_value.string;
2742  }
2743  else
2744  {
2745  Throw<std::domain_error>("type must be string, but is " + type_name());
2746  }
2747  }
2748 
2750  template<typename T, typename std::enable_if<
2751  std::is_arithmetic<T>::value, int>::type = 0>
2752  T get_impl(T*) const
2753  {
2754  switch (m_type)
2755  {
2756  case value_t::number_integer:
2757  {
2758  return static_cast<T>(m_value.number_integer);
2759  }
2760 
2761  case value_t::number_unsigned:
2762  {
2763  return static_cast<T>(m_value.number_unsigned);
2764  }
2765 
2766  case value_t::number_float:
2767  {
2768  return static_cast<T>(m_value.number_float);
2769  }
2770 
2771  default:
2772  {
2773  Throw<std::domain_error>("type must be number, but is " + type_name());
2774  }
2775  }
2776  }
2777 
2779  constexpr boolean_t get_impl(boolean_t*) const
2780  {
2781  return is_boolean()
2782  ? m_value.boolean
2783  : Throw<std::domain_error>("type must be boolean, but is " + type_name()), false;
2784  }
2785 
2787  object_t* get_impl_ptr(object_t*) noexcept
2788  {
2789  return is_object() ? m_value.object : nullptr;
2790  }
2791 
2793  constexpr const object_t* get_impl_ptr(const object_t*) const noexcept
2794  {
2795  return is_object() ? m_value.object : nullptr;
2796  }
2797 
2799  array_t* get_impl_ptr(array_t*) noexcept
2800  {
2801  return is_array() ? m_value.array : nullptr;
2802  }
2803 
2805  constexpr const array_t* get_impl_ptr(const array_t*) const noexcept
2806  {
2807  return is_array() ? m_value.array : nullptr;
2808  }
2809 
2811  string_t* get_impl_ptr(string_t*) noexcept
2812  {
2813  return is_string() ? m_value.string : nullptr;
2814  }
2815 
2817  constexpr const string_t* get_impl_ptr(const string_t*) const noexcept
2818  {
2819  return is_string() ? m_value.string : nullptr;
2820  }
2821 
2823  boolean_t* get_impl_ptr(boolean_t*) noexcept
2824  {
2825  return is_boolean() ? &m_value.boolean : nullptr;
2826  }
2827 
2829  constexpr const boolean_t* get_impl_ptr(const boolean_t*) const noexcept
2830  {
2831  return is_boolean() ? &m_value.boolean : nullptr;
2832  }
2833 
2835  number_integer_t* get_impl_ptr(number_integer_t*) noexcept
2836  {
2837  return is_number_integer() ? &m_value.number_integer : nullptr;
2838  }
2839 
2841  constexpr const number_integer_t* get_impl_ptr(const number_integer_t*) const noexcept
2842  {
2843  return is_number_integer() ? &m_value.number_integer : nullptr;
2844  }
2845 
2847  number_unsigned_t* get_impl_ptr(number_unsigned_t*) noexcept
2848  {
2849  return is_number_unsigned() ? &m_value.number_unsigned : nullptr;
2850  }
2851 
2853  constexpr const number_unsigned_t* get_impl_ptr(const number_unsigned_t*) const noexcept
2854  {
2855  return is_number_unsigned() ? &m_value.number_unsigned : nullptr;
2856  }
2857 
2859  number_float_t* get_impl_ptr(number_float_t*) noexcept
2860  {
2861  return is_number_float() ? &m_value.number_float : nullptr;
2862  }
2863 
2865  constexpr const number_float_t* get_impl_ptr(const number_float_t*) const noexcept
2866  {
2867  return is_number_float() ? &m_value.number_float : nullptr;
2868  }
2869 
2881  template<typename ReferenceType, typename ThisType>
2882  static ReferenceType get_ref_impl(ThisType& obj)
2883  {
2884  // helper type
2885  using PointerType = typename std::add_pointer<ReferenceType>::type;
2886 
2887  // delegate the call to get_ptr<>()
2888  auto ptr = obj.template get_ptr<PointerType>();
2889 
2890  if (ptr != nullptr)
2891  {
2892  return *ptr;
2893  }
2894  else
2895  {
2896  Throw<std::domain_error>("incompatible ReferenceType for get_ref, actual type is " +
2897  obj.type_name());
2898  }
2899  }
2900 
2901  public:
2902 
2906 
2940  template<typename ValueType, typename std::enable_if<
2941  not std::is_pointer<ValueType>::value, int>::type = 0>
2942  ValueType get() const
2943  {
2944  return get_impl(static_cast<ValueType*>(nullptr));
2945  }
2946 
2974  template<typename PointerType, typename std::enable_if<
2975  std::is_pointer<PointerType>::value, int>::type = 0>
2976  PointerType get() noexcept
2977  {
2978  // delegate the call to get_ptr
2979  return get_ptr<PointerType>();
2980  }
2981 
2986  template<typename PointerType, typename std::enable_if<
2987  std::is_pointer<PointerType>::value, int>::type = 0>
2988  constexpr const PointerType get() const noexcept
2989  {
2990  // delegate the call to get_ptr
2991  return get_ptr<PointerType>();
2992  }
2993 
3020  template<typename PointerType, typename std::enable_if<
3021  std::is_pointer<PointerType>::value, int>::type = 0>
3022  PointerType get_ptr() noexcept
3023  {
3024  // get the type of the PointerType (remove pointer and const)
3025  using pointee_t = typename std::remove_const<typename
3026  std::remove_pointer<typename
3028  // make sure the type matches the allowed types
3029  static_assert(
3030  std::is_same<object_t, pointee_t>::value
3031  or std::is_same<array_t, pointee_t>::value
3032  or std::is_same<string_t, pointee_t>::value
3033  or std::is_same<boolean_t, pointee_t>::value
3034  or std::is_same<number_integer_t, pointee_t>::value
3035  or std::is_same<number_unsigned_t, pointee_t>::value
3036  or std::is_same<number_float_t, pointee_t>::value
3037  , "incompatible pointer type");
3038 
3039  // delegate the call to get_impl_ptr<>()
3040  return get_impl_ptr(static_cast<PointerType>(nullptr));
3041  }
3042 
3047  template<typename PointerType, typename std::enable_if<
3048  std::is_pointer<PointerType>::value and
3050  constexpr const PointerType get_ptr() const noexcept
3051  {
3052  // get the type of the PointerType (remove pointer and const)
3053  using pointee_t = typename std::remove_const<typename
3054  std::remove_pointer<typename
3056  // make sure the type matches the allowed types
3057  static_assert(
3058  std::is_same<object_t, pointee_t>::value
3059  or std::is_same<array_t, pointee_t>::value
3060  or std::is_same<string_t, pointee_t>::value
3061  or std::is_same<boolean_t, pointee_t>::value
3062  or std::is_same<number_integer_t, pointee_t>::value
3063  or std::is_same<number_unsigned_t, pointee_t>::value
3064  or std::is_same<number_float_t, pointee_t>::value
3065  , "incompatible pointer type");
3066 
3067  // delegate the call to get_impl_ptr<>() const
3068  return get_impl_ptr(static_cast<const PointerType>(nullptr));
3069  }
3070 
3097  template<typename ReferenceType, typename std::enable_if<
3098  std::is_reference<ReferenceType>::value, int>::type = 0>
3099  ReferenceType get_ref()
3100  {
3101  // delegate call to get_ref_impl
3102  return get_ref_impl<ReferenceType>(*this);
3103  }
3104 
3109  template<typename ReferenceType, typename std::enable_if<
3110  std::is_reference<ReferenceType>::value and
3112  ReferenceType get_ref() const
3113  {
3114  // delegate call to get_ref_impl
3115  return get_ref_impl<ReferenceType>(*this);
3116  }
3117 
3146  template < typename ValueType, typename std::enable_if <
3147  not std::is_pointer<ValueType>::value and
3148  not std::is_same<ValueType, typename string_t::value_type>::value
3149 #ifndef _MSC_VER // Fix for issue #167 operator<< abiguity under VS2015
3150  and not std::is_same<ValueType, std::initializer_list<typename string_t::value_type>>::value
3151 #endif
3152  , int >::type = 0 >
3153  operator ValueType() const
3154  {
3155  // delegate the call to get<>() const
3156  return get<ValueType>();
3157  }
3158 
3160 
3161 
3163  // element access //
3165 
3169 
3193  {
3194  // at only works for arrays
3195  if (is_array())
3196  {
3197  if (idx < m_value.array->size())
3198  return m_value.array->at(idx);
3199  Throw<std::out_of_range>("array index " + std::to_string(idx) + " is out of range");
3200  }
3201  else
3202  {
3203  Throw<std::domain_error>("cannot use at() with " + type_name());
3204  }
3205  }
3206 
3230  {
3231  // at only works for arrays
3232  if (is_array())
3233  {
3234  if (idx < m_value.array->size())
3235  return m_value.array->at(idx);
3236  Throw<std::out_of_range>("array index " + std::to_string(idx) + " is out of range");
3237  }
3238  else
3239  {
3240  Throw<std::domain_error>("cannot use at() with " + type_name());
3241  }
3242  }
3243 
3271  {
3272  // at only works for objects
3273  if (is_object())
3274  {
3275  if (m_value.object->count(key) > 0)
3276  return m_value.object->at(key);
3277  Throw<std::out_of_range>("key '" + key + "' not found");
3278  }
3279  else
3280  {
3281  Throw<std::domain_error>("cannot use at() with " + type_name());
3282  }
3283  }
3284 
3311  const_reference at(const typename object_t::key_type& key) const
3312  {
3313  // at only works for objects
3314  if (is_object())
3315  {
3316  if (m_value.object->count(key) > 0)
3317  return m_value.object->at(key);
3318  Throw<std::out_of_range>("key '" + key + "' not found");
3319  }
3320  else
3321  {
3322  Throw<std::domain_error>("cannot use at() with " + type_name());
3323  }
3324  }
3325 
3352  {
3353  // implicitly convert null value to an empty array
3354  if (is_null())
3355  {
3357  m_value.array = create<array_t>();
3358  assert_invariant();
3359  }
3360 
3361  // operator[] only works for arrays
3362  if (is_array())
3363  {
3364  // fill up array with null values if given idx is outside range
3365  if (idx >= m_value.array->size())
3366  {
3367  m_value.array->insert(m_value.array->end(),
3368  idx - m_value.array->size() + 1,
3369  basic_json());
3370  }
3371 
3372  return m_value.array->operator[](idx);
3373  }
3374  else
3375  {
3376  Throw<std::domain_error>("cannot use operator[] with " + type_name());
3377  }
3378  }
3379 
3400  {
3401  // const operator[] only works for arrays
3402  if (is_array())
3403  {
3404  return m_value.array->operator[](idx);
3405  }
3406  else
3407  {
3408  Throw<std::domain_error>("cannot use operator[] with " + type_name());
3409  }
3410  }
3411 
3440  {
3441  // implicitly convert null value to an empty object
3442  if (is_null())
3443  {
3445  m_value.object = create<object_t>();
3446  assert_invariant();
3447  }
3448 
3449  // operator[] only works for objects
3450  if (is_object())
3451  {
3452  return m_value.object->operator[](key);
3453  }
3454  else
3455  {
3456  Throw<std::domain_error>("cannot use operator[] with " + type_name());
3457  }
3458  }
3459 
3491  {
3492  // const operator[] only works for objects
3493  if (is_object())
3494  {
3495  assert(m_value.object->find(key) != m_value.object->end());
3496  return m_value.object->find(key)->second;
3497  }
3498  else
3499  {
3500  Throw<std::domain_error>("cannot use operator[] with " + type_name());
3501  }
3502  }
3503 
3531  template<typename T, std::size_t n>
3533  {
3534  return operator[](static_cast<const T>(key));
3535  }
3536 
3566  template<typename T, std::size_t n>
3568  {
3569  return operator[](static_cast<const T>(key));
3570  }
3571 
3599  template<typename T>
3601  {
3602  // implicitly convert null to object
3603  if (is_null())
3604  {
3606  m_value = value_t::object;
3607  assert_invariant();
3608  }
3609 
3610  // at only works for objects
3611  if (is_object())
3612  {
3613  return m_value.object->operator[](key);
3614  }
3615  else
3616  {
3617  Throw<std::domain_error>("cannot use operator[] with " + type_name());
3618  }
3619  }
3620 
3651  template<typename T>
3653  {
3654  // at only works for objects
3655  if (is_object())
3656  {
3657  assert(m_value.object->find(key) != m_value.object->end());
3658  return m_value.object->find(key)->second;
3659  }
3660  else
3661  {
3662  Throw<std::domain_error>("cannot use operator[] with " + type_name());
3663  }
3664  }
3665 
3714  template<class ValueType, typename std::enable_if<
3715  std::is_convertible<basic_json_t, ValueType>::value, int>::type = 0>
3716  ValueType value(const typename object_t::key_type& key, ValueType default_value) const
3717  {
3718  // at only works for objects
3719  if (is_object())
3720  {
3721  // if key is found, return value and given default value otherwise
3722  const auto it = find(key);
3723  if (it != end())
3724  {
3725  return *it;
3726  }
3727  else
3728  {
3729  return default_value;
3730  }
3731  }
3732  else
3733  {
3734  Throw<std::domain_error>("cannot use value() with " + type_name());
3735  }
3736  }
3737 
3742  string_t value(const typename object_t::key_type& key, const char* default_value) const
3743  {
3744  return value(key, string_t(default_value));
3745  }
3746 
3788  template<class ValueType, typename std::enable_if<
3789  std::is_convertible<basic_json_t, ValueType>::value, int>::type = 0>
3790  ValueType value(const json_pointer& ptr, ValueType default_value) const
3791  {
3792  // at only works for objects
3793  if (is_object())
3794  {
3795  return ptr.get_checked(this);
3796  }
3797  else
3798  {
3799  Throw<std::domain_error>("cannot use value() with " + type_name());
3800  }
3801  }
3802 
3807  string_t value(const json_pointer& ptr, const char* default_value) const
3808  {
3809  return value(ptr, string_t(default_value));
3810  }
3811 
3838  {
3839  return *begin();
3840  }
3841 
3846  {
3847  return *cbegin();
3848  }
3849 
3881  {
3882  auto tmp = end();
3883  --tmp;
3884  return *tmp;
3885  }
3886 
3891  {
3892  auto tmp = cend();
3893  --tmp;
3894  return *tmp;
3895  }
3896 
3942  template<class IteratorType, typename std::enable_if<
3943  std::is_same<IteratorType, typename basic_json_t::iterator>::value or
3944  std::is_same<IteratorType, typename basic_json_t::const_iterator>::value, int>::type
3945  = 0>
3946  IteratorType erase(IteratorType pos)
3947  {
3948  // make sure iterator fits the current value
3949  if (this != pos.m_object)
3950  {
3951  Throw<std::domain_error>("iterator does not fit current value");
3952  }
3953 
3954  IteratorType result = end();
3955 
3956  switch (m_type)
3957  {
3958  case value_t::boolean:
3959  case value_t::number_float:
3960  case value_t::number_integer:
3961  case value_t::number_unsigned:
3962  case value_t::string:
3963  {
3964  if (not pos.m_it.primitive_iterator.is_begin())
3965  {
3966  Throw<std::out_of_range>("iterator out of range");
3967  }
3968 
3969  if (is_string())
3970  {
3971  AllocatorType<string_t> alloc;
3972  alloc.destroy(m_value.string);
3973  alloc.deallocate(m_value.string, 1);
3974  m_value.string = nullptr;
3975  }
3976 
3977  m_type = value_t::null;
3978  assert_invariant();
3979  break;
3980  }
3981 
3982  case value_t::object:
3983  {
3984  result.m_it.object_iterator = m_value.object->erase(pos.m_it.object_iterator);
3985  break;
3986  }
3987 
3988  case value_t::array:
3989  {
3990  result.m_it.array_iterator = m_value.array->erase(pos.m_it.array_iterator);
3991  break;
3992  }
3993 
3994  default:
3995  {
3996  Throw<std::domain_error>("cannot use erase() with " + type_name());
3997  }
3998  }
3999 
4000  return result;
4001  }
4002 
4049  template<class IteratorType, typename std::enable_if<
4050  std::is_same<IteratorType, typename basic_json_t::iterator>::value or
4051  std::is_same<IteratorType, typename basic_json_t::const_iterator>::value, int>::type
4052  = 0>
4053  IteratorType erase(IteratorType first, IteratorType last)
4054  {
4055  // make sure iterator fits the current value
4056  if (this != first.m_object or this != last.m_object)
4057  {
4058  Throw<std::domain_error>("iterators do not fit current value");
4059  }
4060 
4061  IteratorType result = end();
4062 
4063  switch (m_type)
4064  {
4065  case value_t::boolean:
4066  case value_t::number_float:
4067  case value_t::number_integer:
4068  case value_t::number_unsigned:
4069  case value_t::string:
4070  {
4071  if (not first.m_it.primitive_iterator.is_begin() or not last.m_it.primitive_iterator.is_end())
4072  {
4073  Throw<std::out_of_range>("iterators out of range");
4074  }
4075 
4076  if (is_string())
4077  {
4078  AllocatorType<string_t> alloc;
4079  alloc.destroy(m_value.string);
4080  alloc.deallocate(m_value.string, 1);
4081  m_value.string = nullptr;
4082  }
4083 
4084  m_type = value_t::null;
4085  assert_invariant();
4086  break;
4087  }
4088 
4089  case value_t::object:
4090  {
4091  result.m_it.object_iterator = m_value.object->erase(first.m_it.object_iterator,
4092  last.m_it.object_iterator);
4093  break;
4094  }
4095 
4096  case value_t::array:
4097  {
4098  result.m_it.array_iterator = m_value.array->erase(first.m_it.array_iterator,
4099  last.m_it.array_iterator);
4100  break;
4101  }
4102 
4103  default:
4104  {
4105  Throw<std::domain_error>("cannot use erase() with " + type_name());
4106  }
4107  }
4108 
4109  return result;
4110  }
4111 
4142  {
4143  // this erase only works for objects
4144  if (is_object())
4145  {
4146  return m_value.object->erase(key);
4147  }
4148  else
4149  {
4150  Throw<std::domain_error>("cannot use erase() with " + type_name());
4151  }
4152  }
4153 
4178  void erase(const size_type idx)
4179  {
4180  // this erase only works for arrays
4181  if (is_array())
4182  {
4183  if (idx >= size())
4184  {
4185  Throw<std::out_of_range>("array index " + std::to_string(idx) + " is out of range");
4186  }
4187 
4188  m_value.array->erase(m_value.array->begin() + static_cast<difference_type>(idx));
4189  }
4190  else
4191  {
4192  Throw<std::domain_error>("cannot use erase() with " + type_name());
4193  }
4194  }
4195 
4197 
4198 
4200  // lookup //
4202 
4205 
4225  {
4226  auto result = end();
4227 
4228  if (is_object())
4229  {
4230  result.m_it.object_iterator = m_value.object->find(key);
4231  }
4232 
4233  return result;
4234  }
4235 
4241  {
4242  auto result = cend();
4243 
4244  if (is_object())
4245  {
4246  result.m_it.object_iterator = m_value.object->find(key);
4247  }
4248 
4249  return result;
4250  }
4251 
4271  {
4272  // return 0 for all nonobject types
4273  return is_object() ? m_value.object->count(key) : 0;
4274  }
4275 
4277 
4278 
4280  // iterators //
4282 
4285 
4310  iterator begin() noexcept
4311  {
4312  iterator result(this);
4313  result.set_begin();
4314  return result;
4315  }
4316 
4321  {
4322  return cbegin();
4323  }
4324 
4351  {
4352  const_iterator result(this);
4353  result.set_begin();
4354  return result;
4355  }
4356 
4381  iterator end() noexcept
4382  {
4383  iterator result(this);
4384  result.set_end();
4385  return result;
4386  }
4387 
4392  {
4393  return cend();
4394  }
4395 
4422  {
4423  const_iterator result(this);
4424  result.set_end();
4425  return result;
4426  }
4427 
4452  {
4453  return reverse_iterator(end());
4454  }
4455 
4460  {
4461  return crbegin();
4462  }
4463 
4489  {
4490  return reverse_iterator(begin());
4491  }
4492 
4497  {
4498  return crend();
4499  }
4500 
4526  {
4527  return const_reverse_iterator(cend());
4528  }
4529 
4555  {
4556  return const_reverse_iterator(cbegin());
4557  }
4558 
4559  private:
4560  // forward declaration
4561  template<typename IteratorType> class iteration_proxy;
4562 
4563  public:
4575  static iteration_proxy<iterator> iterator_wrapper(reference cont)
4576  {
4577  return iteration_proxy<iterator>(cont);
4578  }
4579 
4583  static iteration_proxy<const_iterator> iterator_wrapper(const_reference cont)
4584  {
4585  return iteration_proxy<const_iterator>(cont);
4586  }
4587 
4589 
4590 
4592  // capacity //
4594 
4597 
4635  bool empty() const noexcept
4636  {
4637  switch (m_type)
4638  {
4639  case value_t::null:
4640  {
4641  // null values are empty
4642  return true;
4643  }
4644 
4645  case value_t::array:
4646  {
4647  // delegate call to array_t::empty()
4648  return m_value.array->empty();
4649  }
4650 
4651  case value_t::object:
4652  {
4653  // delegate call to object_t::empty()
4654  return m_value.object->empty();
4655  }
4656 
4657  default:
4658  {
4659  // all other types are nonempty
4660  return false;
4661  }
4662  }
4663  }
4664 
4703  size_type size() const noexcept
4704  {
4705  switch (m_type)
4706  {
4707  case value_t::null:
4708  {
4709  // null values are empty
4710  return 0;
4711  }
4712 
4713  case value_t::array:
4714  {
4715  // delegate call to array_t::size()
4716  return m_value.array->size();
4717  }
4718 
4719  case value_t::object:
4720  {
4721  // delegate call to object_t::size()
4722  return m_value.object->size();
4723  }
4724 
4725  default:
4726  {
4727  // all other types have size 1
4728  return 1;
4729  }
4730  }
4731  }
4732 
4770  {
4771  switch (m_type)
4772  {
4773  case value_t::array:
4774  {
4775  // delegate call to array_t::max_size()
4776  return m_value.array->max_size();
4777  }
4778 
4779  case value_t::object:
4780  {
4781  // delegate call to object_t::max_size()
4782  return m_value.object->max_size();
4783  }
4784 
4785  default:
4786  {
4787  // all other types have max_size() == size()
4788  return size();
4789  }
4790  }
4791  }
4792 
4794 
4795 
4797  // modifiers //
4799 
4802 
4828  void clear() noexcept
4829  {
4830  switch (m_type)
4831  {
4832  case value_t::number_integer:
4833  {
4834  m_value.number_integer = 0;
4835  break;
4836  }
4837 
4838  case value_t::number_unsigned:
4839  {
4840  m_value.number_unsigned = 0;
4841  break;
4842  }
4843 
4844  case value_t::number_float:
4845  {
4846  m_value.number_float = 0.0;
4847  break;
4848  }
4849 
4850  case value_t::boolean:
4851  {
4852  m_value.boolean = false;
4853  break;
4854  }
4855 
4856  case value_t::string:
4857  {
4858  m_value.string->clear();
4859  break;
4860  }
4861 
4862  case value_t::array:
4863  {
4864  m_value.array->clear();
4865  break;
4866  }
4867 
4868  case value_t::object:
4869  {
4870  m_value.object->clear();
4871  break;
4872  }
4873 
4874  default:
4875  {
4876  break;
4877  }
4878  }
4879  }
4880 
4902  {
4903  // push_back only works for null objects or arrays
4904  if (not(is_null() or is_array()))
4905  {
4906  Throw<std::domain_error>("cannot use push_back() with " + type_name());
4907  }
4908 
4909  // transform null object into an array
4910  if (is_null())
4911  {
4913  m_value = value_t::array;
4914  assert_invariant();
4915  }
4916 
4917  // add element to array (move semantics)
4918  m_value.array->push_back(std::move(val));
4919  // invalidate object
4920  val.m_type = value_t::null;
4921  }
4922 
4928  {
4930  return *this;
4931  }
4932 
4937  void push_back(const basic_json& val)
4938  {
4939  // push_back only works for null objects or arrays
4940  if (not(is_null() or is_array()))
4941  {
4942  Throw<std::domain_error>("cannot use push_back() with " + type_name());
4943  }
4944 
4945  // transform null object into an array
4946  if (is_null())
4947  {
4949  m_value = value_t::array;
4950  assert_invariant();
4951  }
4952 
4953  // add element to array
4954  m_value.array->push_back(val);
4955  }
4956 
4962  {
4963  push_back(val);
4964  return *this;
4965  }
4966 
4987  void push_back(const typename object_t::value_type& val)
4988  {
4989  // push_back only works for null objects or objects
4990  if (not(is_null() or is_object()))
4991  {
4992  Throw<std::domain_error>("cannot use push_back() with " + type_name());
4993  }
4994 
4995  // transform null object into an object
4996  if (is_null())
4997  {
4999  m_value = value_t::object;
5000  assert_invariant();
5001  }
5002 
5003  // add element to array
5004  m_value.object->insert(val);
5005  }
5006 
5011  reference operator+=(const typename object_t::value_type& val)
5012  {
5013  push_back(val);
5014  return *this;
5015  }
5016 
5042  void push_back(std::initializer_list<basic_json> init)
5043  {
5044  if (is_object() and init.size() == 2 and init.begin()->is_string())
5045  {
5046  const string_t key = *init.begin();
5047  push_back(typename object_t::value_type(key, *(init.begin() + 1)));
5048  }
5049  else
5050  {
5051  push_back(basic_json(init));
5052  }
5053  }
5054 
5059  reference operator+=(std::initializer_list<basic_json> init)
5060  {
5061  push_back(init);
5062  return *this;
5063  }
5064 
5088  {
5089  // insert only works for arrays
5090  if (is_array())
5091  {
5092  // check if iterator pos fits to this JSON value
5093  if (pos.m_object != this)
5094  {
5095  Throw<std::domain_error>("iterator does not fit current value");
5096  }
5097 
5098  // insert to array and return iterator
5099  iterator result(this);
5100  result.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator, val);
5101  return result;
5102  }
5103  else
5104  {
5105  Throw<std::domain_error>("cannot use insert() with " + type_name());
5106  }
5107  }
5108 
5114  {
5115  return insert(pos, val);
5116  }
5117 
5143  {
5144  // insert only works for arrays
5145  if (is_array())
5146  {
5147  // check if iterator pos fits to this JSON value
5148  if (pos.m_object != this)
5149  {
5150  Throw<std::domain_error>("iterator does not fit current value");
5151  }
5152 
5153  // insert to array and return iterator
5154  iterator result(this);
5155  result.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator, cnt, val);
5156  return result;
5157  }
5158  else
5159  {
5160  Throw<std::domain_error>("cannot use insert() with " + type_name());
5161  }
5162  }
5163 
5195  {
5196  // insert only works for arrays
5197  if (not is_array())
5198  {
5199  Throw<std::domain_error>("cannot use insert() with " + type_name());
5200  }
5201 
5202  // check if iterator pos fits to this JSON value
5203  if (pos.m_object != this)
5204  {
5205  Throw<std::domain_error>("iterator does not fit current value");
5206  }
5207 
5208  // check if range iterators belong to the same JSON object
5209  if (first.m_object != last.m_object)
5210  {
5211  Throw<std::domain_error>("iterators do not fit");
5212  }
5213 
5214  if (first.m_object == this or last.m_object == this)
5215  {
5216  Throw<std::domain_error>("passed iterators may not belong to container");
5217  }
5218 
5219  // insert to array and return iterator
5220  iterator result(this);
5221  result.m_it.array_iterator = m_value.array->insert(
5222  pos.m_it.array_iterator,
5223  first.m_it.array_iterator,
5224  last.m_it.array_iterator);
5225  return result;
5226  }
5227 
5252  iterator insert(const_iterator pos, std::initializer_list<basic_json> ilist)
5253  {
5254  // insert only works for arrays
5255  if (not is_array())
5256  {
5257  Throw<std::domain_error>("cannot use insert() with " + type_name());
5258  }
5259 
5260  // check if iterator pos fits to this JSON value
5261  if (pos.m_object != this)
5262  {
5263  Throw<std::domain_error>("iterator does not fit current value");
5264  }
5265 
5266  // insert to array and return iterator
5267  iterator result(this);
5268  result.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator, ilist);
5269  return result;
5270  }
5271 
5289  void swap(reference other) noexcept (
5290  std::is_nothrow_move_constructible<value_t>::value and
5291  std::is_nothrow_move_assignable<value_t>::value and
5292  std::is_nothrow_move_constructible<json_value>::value and
5293  std::is_nothrow_move_assignable<json_value>::value
5294  )
5295  {
5296  std::swap(m_type, other.m_type);
5297  std::swap(m_value, other.m_value);
5298  assert_invariant();
5299  }
5300 
5321  void swap(array_t& other)
5322  {
5323  // swap only works for arrays
5324  if (is_array())
5325  {
5326  std::swap(*(m_value.array), other);
5327  }
5328  else
5329  {
5330  Throw<std::domain_error>("cannot use swap() with " + type_name());
5331  }
5332  }
5333 
5354  void swap(object_t& other)
5355  {
5356  // swap only works for objects
5357  if (is_object())
5358  {
5359  std::swap(*(m_value.object), other);
5360  }
5361  else
5362  {
5363  Throw<std::domain_error>("cannot use swap() with " + type_name());
5364  }
5365  }
5366 
5387  void swap(string_t& other)
5388  {
5389  // swap only works for strings
5390  if (is_string())
5391  {
5392  std::swap(*(m_value.string), other);
5393  }
5394  else
5395  {
5396  Throw<std::domain_error>("cannot use swap() with " + type_name());
5397  }
5398  }
5399 
5401 
5402 
5404  // lexicographical comparison operators //
5406 
5409 
5410  private:
5420  friend bool operator<(const value_t lhs, const value_t rhs) noexcept
5421  {
5422  static constexpr std::array<uint8_t, 8> order = {{
5423  0, // null
5424  3, // object
5425  4, // array
5426  5, // string
5427  1, // boolean
5428  2, // integer
5429  2, // unsigned
5430  2, // float
5431  }
5432  };
5433 
5434  // discarded values are not comparable
5435  if (lhs == value_t::discarded or rhs == value_t::discarded)
5436  {
5437  return false;
5438  }
5439 
5440  return order[static_cast<std::size_t>(lhs)] < order[static_cast<std::size_t>(rhs)];
5441  }
5442 
5443  public:
5467  friend bool operator==(const_reference lhs, const_reference rhs) noexcept
5468  {
5469  const auto lhs_type = lhs.type();
5470  const auto rhs_type = rhs.type();
5471 
5472  if (lhs_type == rhs_type)
5473  {
5474  switch (lhs_type)
5475  {
5476  case value_t::array:
5477  {
5478  return *lhs.m_value.array == *rhs.m_value.array;
5479  }
5480  case value_t::object:
5481  {
5482  return *lhs.m_value.object == *rhs.m_value.object;
5483  }
5484  case value_t::null:
5485  {
5486  return true;
5487  }
5488  case value_t::string:
5489  {
5490  return *lhs.m_value.string == *rhs.m_value.string;
5491  }
5492  case value_t::boolean:
5493  {
5494  return lhs.m_value.boolean == rhs.m_value.boolean;
5495  }
5496  case value_t::number_integer:
5497  {
5498  return lhs.m_value.number_integer == rhs.m_value.number_integer;
5499  }
5500  case value_t::number_unsigned:
5501  {
5502  return lhs.m_value.number_unsigned == rhs.m_value.number_unsigned;
5503  }
5504  case value_t::number_float:
5505  {
5506  return lhs.m_value.number_float == rhs.m_value.number_float;
5507  }
5508  default:
5509  {
5510  return false;
5511  }
5512  }
5513  }
5514  else if (lhs_type == value_t::number_integer and rhs_type == value_t::number_float)
5515  {
5516  return static_cast<number_float_t>(lhs.m_value.number_integer) == rhs.m_value.number_float;
5517  }
5518  else if (lhs_type == value_t::number_float and rhs_type == value_t::number_integer)
5519  {
5520  return lhs.m_value.number_float == static_cast<number_float_t>(rhs.m_value.number_integer);
5521  }
5522  else if (lhs_type == value_t::number_unsigned and rhs_type == value_t::number_float)
5523  {
5524  return static_cast<number_float_t>(lhs.m_value.number_unsigned) == rhs.m_value.number_float;
5525  }
5526  else if (lhs_type == value_t::number_float and rhs_type == value_t::number_unsigned)
5527  {
5528  return lhs.m_value.number_float == static_cast<number_float_t>(rhs.m_value.number_unsigned);
5529  }
5530  else if (lhs_type == value_t::number_unsigned and rhs_type == value_t::number_integer)
5531  {
5532  return static_cast<number_integer_t>(lhs.m_value.number_unsigned) == rhs.m_value.number_integer;
5533  }
5534  else if (lhs_type == value_t::number_integer and rhs_type == value_t::number_unsigned)
5535  {
5536  return lhs.m_value.number_integer == static_cast<number_integer_t>(rhs.m_value.number_unsigned);
5537  }
5538 
5539  return false;
5540  }
5541 
5560  friend bool operator==(const_reference v, std::nullptr_t) noexcept
5561  {
5562  return v.is_null();
5563  }
5564 
5569  friend bool operator==(std::nullptr_t, const_reference v) noexcept
5570  {
5571  return v.is_null();
5572  }
5573 
5590  friend bool operator!=(const_reference lhs, const_reference rhs) noexcept
5591  {
5592  return not (lhs == rhs);
5593  }
5594 
5613  friend bool operator!=(const_reference v, std::nullptr_t) noexcept
5614  {
5615  return not v.is_null();
5616  }
5617 
5622  friend bool operator!=(std::nullptr_t, const_reference v) noexcept
5623  {
5624  return not v.is_null();
5625  }
5626 
5651  friend bool operator<(const_reference lhs, const_reference rhs) noexcept
5652  {
5653  const auto lhs_type = lhs.type();
5654  const auto rhs_type = rhs.type();
5655 
5656  if (lhs_type == rhs_type)
5657  {
5658  switch (lhs_type)
5659  {
5660  case value_t::array:
5661  {
5662  return *lhs.m_value.array < *rhs.m_value.array;
5663  }
5664  case value_t::object:
5665  {
5666  return *lhs.m_value.object < *rhs.m_value.object;
5667  }
5668  case value_t::null:
5669  {
5670  return false;
5671  }
5672  case value_t::string:
5673  {
5674  return *lhs.m_value.string < *rhs.m_value.string;
5675  }
5676  case value_t::boolean:
5677  {
5678  return lhs.m_value.boolean < rhs.m_value.boolean;
5679  }
5680  case value_t::number_integer:
5681  {
5682  return lhs.m_value.number_integer < rhs.m_value.number_integer;
5683  }
5684  case value_t::number_unsigned:
5685  {
5686  return lhs.m_value.number_unsigned < rhs.m_value.number_unsigned;
5687  }
5688  case value_t::number_float:
5689  {
5690  return lhs.m_value.number_float < rhs.m_value.number_float;
5691  }
5692  default:
5693  {
5694  return false;
5695  }
5696  }
5697  }
5698  else if (lhs_type == value_t::number_integer and rhs_type == value_t::number_float)
5699  {
5700  return static_cast<number_float_t>(lhs.m_value.number_integer) < rhs.m_value.number_float;
5701  }
5702  else if (lhs_type == value_t::number_float and rhs_type == value_t::number_integer)
5703  {
5704  return lhs.m_value.number_float < static_cast<number_float_t>(rhs.m_value.number_integer);
5705  }
5706  else if (lhs_type == value_t::number_unsigned and rhs_type == value_t::number_float)
5707  {
5708  return static_cast<number_float_t>(lhs.m_value.number_unsigned) < rhs.m_value.number_float;
5709  }
5710  else if (lhs_type == value_t::number_float and rhs_type == value_t::number_unsigned)
5711  {
5712  return lhs.m_value.number_float < static_cast<number_float_t>(rhs.m_value.number_unsigned);
5713  }
5714  else if (lhs_type == value_t::number_integer and rhs_type == value_t::number_unsigned)
5715  {
5716  return lhs.m_value.number_integer < static_cast<number_integer_t>(rhs.m_value.number_unsigned);
5717  }
5718  else if (lhs_type == value_t::number_unsigned and rhs_type == value_t::number_integer)
5719  {
5720  return static_cast<number_integer_t>(lhs.m_value.number_unsigned) < rhs.m_value.number_integer;
5721  }
5722 
5723  // We only reach this line if we cannot compare values. In that case,
5724  // we compare types. Note we have to call the operator explicitly,
5725  // because MSVC has problems otherwise.
5726  return operator<(lhs_type, rhs_type);
5727  }
5728 
5746  friend bool operator<=(const_reference lhs, const_reference rhs) noexcept
5747  {
5748  return not (rhs < lhs);
5749  }
5750 
5768  friend bool operator>(const_reference lhs, const_reference rhs) noexcept
5769  {
5770  return not (lhs <= rhs);
5771  }
5772 
5790  friend bool operator>=(const_reference lhs, const_reference rhs) noexcept
5791  {
5792  return not (lhs < rhs);
5793  }
5794 
5796 
5797 
5799  // serialization //
5801 
5804 
5831  friend std::ostream& operator<<(std::ostream& o, const basic_json& j)
5832  {
5833  // read width member and use it as indentation parameter if nonzero
5834  const bool pretty_print = (o.width() > 0);
5835  const auto indentation = (pretty_print ? o.width() : 0);
5836 
5837  // reset width to 0 for subsequent calls to this stream
5838  o.width(0);
5839 
5840  // fix locale problems
5841  const auto old_locale = o.imbue(std::locale::classic());
5842  // set precision
5843 
5844  // 6, 15 or 16 digits of precision allows round-trip IEEE 754
5845  // string->float->string, string->double->string or string->long
5846  // double->string; to be safe, we read this value from
5847  // std::numeric_limits<number_float_t>::digits10
5848  const auto old_precision = o.precision(std::numeric_limits<double>::digits10);
5849 
5850  // do the actual serialization
5851  j.dump(o, pretty_print, static_cast<unsigned int>(indentation));
5852 
5853  // reset locale and precision
5854  o.imbue(old_locale);
5855  o.precision(old_precision);
5856  return o;
5857  }
5858 
5863  friend std::ostream& operator>>(const basic_json& j, std::ostream& o)
5864  {
5865  return o << j;
5866  }
5867 
5869 
5870 
5872  // deserialization //
5874 
5877 
5905  template<class T, std::size_t N>
5906  static basic_json parse(T (&array)[N],
5907  const parser_callback_t cb = nullptr)
5908  {
5909  // delegate the call to the iterator-range parse overload
5910  return parse(std::begin(array), std::end(array), cb);
5911  }
5912 
5940  template<typename CharPT, typename std::enable_if<
5941  std::is_pointer<CharPT>::value and
5943  sizeof(typename std::remove_pointer<CharPT>::type) == 1, int>::type = 0>
5944  static basic_json parse(const CharPT s,
5945  const parser_callback_t cb = nullptr)
5946  {
5947  return parser(reinterpret_cast<const char*>(s), cb).parse();
5948  }
5949 
5974  static basic_json parse(std::istream& i,
5975  const parser_callback_t cb = nullptr)
5976  {
5977  return parser(i, cb).parse();
5978  }
5979 
5983  static basic_json parse(std::istream&& i,
5984  const parser_callback_t cb = nullptr)
5985  {
5986  return parser(i, cb).parse();
5987  }
5988 
6030  template<class IteratorType, typename std::enable_if<
6031  std::is_base_of<
6032  std::random_access_iterator_tag,
6033  typename std::iterator_traits<IteratorType>::iterator_category>::value, int>::type = 0>
6034  static basic_json parse(IteratorType first, IteratorType last,
6035  const parser_callback_t cb = nullptr)
6036  {
6037  // assertion to check that the iterator range is indeed contiguous,
6038  // see http://stackoverflow.com/a/35008842/266378 for more discussion
6039  assert(std::accumulate(first, last, std::make_pair<bool, int>(true, 0),
6040  [&first](std::pair<bool, int> res, decltype(*first) val)
6041  {
6042  res.first &= (val == *(std::next(std::addressof(*first), res.second++)));
6043  return res;
6044  }).first);
6045 
6046  // assertion to check that each element is 1 byte long
6047  static_assert(sizeof(typename std::iterator_traits<IteratorType>::value_type) == 1,
6048  "each element in the iterator range must have the size of 1 byte");
6049 
6050  // if iterator range is empty, create a parser with an empty string
6051  // to generate "unexpected EOF" error message
6052  if (std::distance(first, last) <= 0)
6053  {
6054  return parser("").parse();
6055  }
6056 
6057  return parser(first, last, cb).parse();
6058  }
6059 
6100  template<class ContiguousContainer, typename std::enable_if<
6101  not std::is_pointer<ContiguousContainer>::value and
6102  std::is_base_of<
6103  std::random_access_iterator_tag,
6104  typename std::iterator_traits<decltype(std::begin(std::declval<ContiguousContainer const>()))>::iterator_category>::value
6105  , int>::type = 0>
6106  static basic_json parse(const ContiguousContainer& c,
6107  const parser_callback_t cb = nullptr)
6108  {
6109  // delegate the call to the iterator-range parse overload
6110  return parse(std::begin(c), std::end(c), cb);
6111  }
6112 
6136  friend std::istream& operator<<(basic_json& j, std::istream& i)
6137  {
6138  j = parser(i).parse();
6139  return i;
6140  }
6141 
6146  friend std::istream& operator>>(std::istream& i, basic_json& j)
6147  {
6148  j = parser(i).parse();
6149  return i;
6150  }
6151 
6153 
6154 
6155  private:
6157  // convenience functions //
6159 
6172  std::string type_name() const
6173  {
6174  switch (m_type)
6175  {
6176  case value_t::null:
6177  return "null";
6178  case value_t::object:
6179  return "object";
6180  case value_t::array:
6181  return "array";
6182  case value_t::string:
6183  return "string";
6184  case value_t::boolean:
6185  return "boolean";
6186  case value_t::discarded:
6187  return "discarded";
6188  default:
6189  return "number";
6190  }
6191  }
6192 
6201  static std::size_t extra_space(const string_t& s) noexcept
6202  {
6203  return std::accumulate(s.begin(), s.end(), size_t{},
6204  [](size_t res, typename string_t::value_type c)
6205  {
6206  switch (c)
6207  {
6208  case '"':
6209  case '\\':
6210  case '\b':
6211  case '\f':
6212  case '\n':
6213  case '\r':
6214  case '\t':
6215  {
6216  // from c (1 byte) to \x (2 bytes)
6217  return res + 1;
6218  }
6219 
6220  default:
6221  {
6222  if (c >= 0x00 and c <= 0x1f)
6223  {
6224  // from c (1 byte) to \uxxxx (6 bytes)
6225  return res + 5;
6226  }
6227  else
6228  {
6229  return res;
6230  }
6231  }
6232  }
6233  });
6234  }
6235 
6249  static string_t escape_string(const string_t& s)
6250  {
6251  const auto space = extra_space(s);
6252  if (space == 0)
6253  {
6254  return s;
6255  }
6256 
6257  // create a result string of necessary size
6258  string_t result(s.size() + space, '\\');
6259  std::size_t pos = 0;
6260 
6261  for (const auto& c : s)
6262  {
6263  switch (c)
6264  {
6265  // quotation mark (0x22)
6266  case '"':
6267  {
6268  result[pos + 1] = '"';
6269  pos += 2;
6270  break;
6271  }
6272 
6273  // reverse solidus (0x5c)
6274  case '\\':
6275  {
6276  // nothing to change
6277  pos += 2;
6278  break;
6279  }
6280 
6281  // backspace (0x08)
6282  case '\b':
6283  {
6284  result[pos + 1] = 'b';
6285  pos += 2;
6286  break;
6287  }
6288 
6289  // formfeed (0x0c)
6290  case '\f':
6291  {
6292  result[pos + 1] = 'f';
6293  pos += 2;
6294  break;
6295  }
6296 
6297  // newline (0x0a)
6298  case '\n':
6299  {
6300  result[pos + 1] = 'n';
6301  pos += 2;
6302  break;
6303  }
6304 
6305  // carriage return (0x0d)
6306  case '\r':
6307  {
6308  result[pos + 1] = 'r';
6309  pos += 2;
6310  break;
6311  }
6312 
6313  // horizontal tab (0x09)
6314  case '\t':
6315  {
6316  result[pos + 1] = 't';
6317  pos += 2;
6318  break;
6319  }
6320 
6321  default:
6322  {
6323  if (c >= 0x00 and c <= 0x1f)
6324  {
6325  // convert a number 0..15 to its hex representation
6326  // (0..f)
6327  static const char hexify[16] =
6328  {
6329  '0', '1', '2', '3', '4', '5', '6', '7',
6330  '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'
6331  };
6332 
6333  // print character c as \uxxxx
6334  for (const char m :
6335  { 'u', '0', '0', hexify[c >> 4], hexify[c & 0x0f]
6336  })
6337  {
6338  result[++pos] = m;
6339  }
6340 
6341  ++pos;
6342  }
6343  else
6344  {
6345  // all other characters are added as-is
6346  result[pos++] = c;
6347  }
6348  break;
6349  }
6350  }
6351  }
6352 
6353  return result;
6354  }
6355 
6373  void dump(std::ostream& o,
6374  const bool pretty_print,
6375  const unsigned int indent_step,
6376  const unsigned int current_indent = 0) const
6377  {
6378  // variable to hold indentation for recursive calls
6379  unsigned int new_indent = current_indent;
6380 
6381  switch (m_type)
6382  {
6383  case value_t::object:
6384  {
6385  if (m_value.object->empty())
6386  {
6387  o << "{}";
6388  return;
6389  }
6390 
6391  o << "{";
6392 
6393  // increase indentation
6394  if (pretty_print)
6395  {
6396  new_indent += indent_step;
6397  o << "\n";
6398  }
6399 
6400  for (auto i = m_value.object->cbegin(); i != m_value.object->cend(); ++i)
6401  {
6402  if (i != m_value.object->cbegin())
6403  {
6404  o << (pretty_print ? ",\n" : ",");
6405  }
6406  o << string_t(new_indent, ' ') << "\""
6407  << escape_string(i->first) << "\":"
6408  << (pretty_print ? " " : "");
6409  i->second.dump(o, pretty_print, indent_step, new_indent);
6410  }
6411 
6412  // decrease indentation
6413  if (pretty_print)
6414  {
6415  new_indent -= indent_step;
6416  o << "\n";
6417  }
6418 
6419  o << string_t(new_indent, ' ') + "}";
6420  return;
6421  }
6422 
6423  case value_t::array:
6424  {
6425  if (m_value.array->empty())
6426  {
6427  o << "[]";
6428  return;
6429  }
6430 
6431  o << "[";
6432 
6433  // increase indentation
6434  if (pretty_print)
6435  {
6436  new_indent += indent_step;
6437  o << "\n";
6438  }
6439 
6440  for (auto i = m_value.array->cbegin(); i != m_value.array->cend(); ++i)
6441  {
6442  if (i != m_value.array->cbegin())
6443  {
6444  o << (pretty_print ? ",\n" : ",");
6445  }
6446  o << string_t(new_indent, ' ');
6447  i->dump(o, pretty_print, indent_step, new_indent);
6448  }
6449 
6450  // decrease indentation
6451  if (pretty_print)
6452  {
6453  new_indent -= indent_step;
6454  o << "\n";
6455  }
6456 
6457  o << string_t(new_indent, ' ') << "]";
6458  return;
6459  }
6460 
6461  case value_t::string:
6462  {
6463  o << string_t("\"") << escape_string(*m_value.string) << "\"";
6464  return;
6465  }
6466 
6467  case value_t::boolean:
6468  {
6469  o << (m_value.boolean ? "true" : "false");
6470  return;
6471  }
6472 
6473  case value_t::number_integer:
6474  {
6475  o << m_value.number_integer;
6476  return;
6477  }
6478 
6479  case value_t::number_unsigned:
6480  {
6481  o << m_value.number_unsigned;
6482  return;
6483  }
6484 
6485  case value_t::number_float:
6486  {
6487  if (m_value.number_float == 0)
6488  {
6489  // special case for zero to get "0.0"/"-0.0"
6490  o << (std::signbit(m_value.number_float) ? "-0.0" : "0.0");
6491  }
6492  else
6493  {
6494  o << m_value.number_float;
6495  }
6496  return;
6497  }
6498 
6499  case value_t::discarded:
6500  {
6501  o << "<discarded>";
6502  return;
6503  }
6504 
6505  case value_t::null:
6506  {
6507  o << "null";
6508  return;
6509  }
6510  }
6511  }
6512 
6513  private:
6515  // member variables //
6517 
6519  value_t m_type = value_t::null;
6520 
6522  json_value m_value = {};
6523 
6524 
6525  private:
6527  // iterators //
6529 
6539  class primitive_iterator_t
6540  {
6541  public:
6543  void set_begin() noexcept
6544  {
6545  m_it = begin_value;
6546  }
6547 
6549  void set_end() noexcept
6550  {
6551  m_it = end_value;
6552  }
6553 
6555  constexpr bool is_begin() const noexcept
6556  {
6557  return (m_it == begin_value);
6558  }
6559 
6561  constexpr bool is_end() const noexcept
6562  {
6563  return (m_it == end_value);
6564  }
6565 
6567  operator difference_type& () noexcept
6568  {
6569  return m_it;
6570  }
6571 
6573  constexpr operator difference_type () const noexcept
6574  {
6575  return m_it;
6576  }
6577 
6578  private:
6579  static constexpr difference_type begin_value = 0;
6580  static constexpr difference_type end_value = begin_value + 1;
6581 
6583  difference_type m_it = std::numeric_limits<std::ptrdiff_t>::denorm_min();
6584  };
6585 
6593  struct internal_iterator
6594  {
6596  typename object_t::iterator object_iterator;
6598  typename array_t::iterator array_iterator;
6600  primitive_iterator_t primitive_iterator;
6601 
6603  internal_iterator() noexcept
6604  : object_iterator(), array_iterator(), primitive_iterator()
6605  {}
6606  };
6607 
6609  template<typename IteratorType>
6610  class iteration_proxy
6611  {
6612  private:
6614  class iteration_proxy_internal
6615  {
6616  private:
6618  IteratorType anchor;
6620  size_t array_index = 0;
6621 
6622  public:
6623  explicit iteration_proxy_internal(IteratorType it) noexcept
6624  : anchor(it)
6625  {}
6626 
6628  iteration_proxy_internal& operator*()
6629  {
6630  return *this;
6631  }
6632 
6634  iteration_proxy_internal& operator++()
6635  {
6636  ++anchor;
6637  ++array_index;
6638 
6639  return *this;
6640  }
6641 
6643  bool operator!= (const iteration_proxy_internal& o) const
6644  {
6645  return anchor != o.anchor;
6646  }
6647 
6649  typename basic_json::string_t key() const
6650  {
6651  assert(anchor.m_object != nullptr);
6652 
6653  switch (anchor.m_object->type())
6654  {
6655  // use integer array index as key
6656  case value_t::array:
6657  {
6658  return std::to_string(array_index);
6659  }
6660 
6661  // use key from the object
6662  case value_t::object:
6663  {
6664  return anchor.key();
6665  }
6666 
6667  // use an empty key for all primitive types
6668  default:
6669  {
6670  return "";
6671  }
6672  }
6673  }
6674 
6676  typename IteratorType::reference value() const
6677  {
6678  return anchor.value();
6679  }
6680  };
6681 
6683  typename IteratorType::reference container;
6684 
6685  public:
6687  explicit iteration_proxy(typename IteratorType::reference cont)
6688  : container(cont)
6689  {}
6690 
6692  iteration_proxy_internal begin() noexcept
6693  {
6694  return iteration_proxy_internal(container.begin());
6695  }
6696 
6698  iteration_proxy_internal end() noexcept
6699  {
6700  return iteration_proxy_internal(container.end());
6701  }
6702  };
6703 
6704  public:
6724  class const_iterator : public std::iterator<std::random_access_iterator_tag, const basic_json>
6725  {
6727  friend class basic_json;
6728 
6729  public:
6739  using iterator_category = std::bidirectional_iterator_tag;
6740 
6742  const_iterator() = default;
6743 
6750  explicit const_iterator(pointer object) noexcept
6751  : m_object(object)
6752  {
6753  assert(m_object != nullptr);
6754 
6755  switch (m_object->m_type)
6756  {
6758  {
6759  m_it.object_iterator = typename object_t::iterator();
6760  break;
6761  }
6762 
6764  {
6765  m_it.array_iterator = typename array_t::iterator();
6766  break;
6767  }
6768 
6769  default:
6770  {
6771  m_it.primitive_iterator = primitive_iterator_t();
6772  break;
6773  }
6774  }
6775  }
6776 
6782  explicit const_iterator(const iterator& other) noexcept
6783  : m_object(other.m_object)
6784  {
6785  if (m_object != nullptr)
6786  {
6787  switch (m_object->m_type)
6788  {
6790  {
6791  m_it.object_iterator = other.m_it.object_iterator;
6792  break;
6793  }
6794 
6796  {
6797  m_it.array_iterator = other.m_it.array_iterator;
6798  break;
6799  }
6800 
6801  default:
6802  {
6803  m_it.primitive_iterator = other.m_it.primitive_iterator;
6804  break;
6805  }
6806  }
6807  }
6808  }
6809 
6815  const_iterator(const const_iterator& other) noexcept
6816  : m_object(other.m_object), m_it(other.m_it)
6817  {}
6818 
6825  std::is_nothrow_move_constructible<pointer>::value and
6826  std::is_nothrow_move_assignable<pointer>::value and
6827  std::is_nothrow_move_constructible<internal_iterator>::value and
6828  std::is_nothrow_move_assignable<internal_iterator>::value
6829  )
6830  {
6831  std::swap(m_object, other.m_object);
6832  std::swap(m_it, other.m_it);
6833  return *this;
6834  }
6835 
6836  private:
6841  void set_begin() noexcept
6842  {
6843  assert(m_object != nullptr);
6844 
6845  switch (m_object->m_type)
6846  {
6848  {
6849  m_it.object_iterator = m_object->m_value.object->begin();
6850  break;
6851  }
6852 
6854  {
6855  m_it.array_iterator = m_object->m_value.array->begin();
6856  break;
6857  }
6858 
6860  {
6861  // set to end so begin()==end() is true: null is empty
6862  m_it.primitive_iterator.set_end();
6863  break;
6864  }
6865 
6866  default:
6867  {
6868  m_it.primitive_iterator.set_begin();
6869  break;
6870  }
6871  }
6872  }
6873 
6878  void set_end() noexcept
6879  {
6880  assert(m_object != nullptr);
6881 
6882  switch (m_object->m_type)
6883  {
6885  {
6886  m_it.object_iterator = m_object->m_value.object->end();
6887  break;
6888  }
6889 
6891  {
6892  m_it.array_iterator = m_object->m_value.array->end();
6893  break;
6894  }
6895 
6896  default:
6897  {
6898  m_it.primitive_iterator.set_end();
6899  break;
6900  }
6901  }
6902  }
6903 
6904  public:
6910  {
6911  assert(m_object != nullptr);
6912 
6913  switch (m_object->m_type)
6914  {
6916  {
6917  assert(m_it.object_iterator != m_object->m_value.object->end());
6918  return m_it.object_iterator->second;
6919  }
6920 
6922  {
6923  assert(m_it.array_iterator != m_object->m_value.array->end());
6924  return *m_it.array_iterator;
6925  }
6926 
6928  {
6929  Throw<std::out_of_range>("cannot get value");
6930  }
6931 
6932  default:
6933  {
6934  if (m_it.primitive_iterator.is_begin())
6935  {
6936  return *m_object;
6937  }
6938  else
6939  {
6940  Throw<std::out_of_range>("cannot get value");
6941  }
6942  }
6943  }
6944  }
6945 
6951  {
6952  assert(m_object != nullptr);
6953 
6954  switch (m_object->m_type)
6955  {
6957  {
6958  assert(m_it.object_iterator != m_object->m_value.object->end());
6959  return &(m_it.object_iterator->second);
6960  }
6961 
6963  {
6964  assert(m_it.array_iterator != m_object->m_value.array->end());
6965  return &*m_it.array_iterator;
6966  }
6967 
6968  default:
6969  {
6970  if (m_it.primitive_iterator.is_begin())
6971  {
6972  return m_object;
6973  }
6974  else
6975  {
6976  Throw<std::out_of_range>("cannot get value");
6977  }
6978  }
6979  }
6980  }
6981 
6987  {
6988  auto result = *this;
6989  ++(*this);
6990  return result;
6991  }
6992 
6998  {
6999  assert(m_object != nullptr);
7000 
7001  switch (m_object->m_type)
7002  {
7004  {
7005  std::advance(m_it.object_iterator, 1);
7006  break;
7007  }
7008 
7010  {
7011  std::advance(m_it.array_iterator, 1);
7012  break;
7013  }
7014 
7015  default:
7016  {
7017  ++m_it.primitive_iterator;
7018  break;
7019  }
7020  }
7021 
7022  return *this;
7023  }
7024 
7030  {
7031  auto result = *this;
7032  --(*this);
7033  return result;
7034  }
7035 
7041  {
7042  assert(m_object != nullptr);
7043 
7044  switch (m_object->m_type)
7045  {
7047  {
7048  std::advance(m_it.object_iterator, -1);
7049  break;
7050  }
7051 
7053  {
7054  std::advance(m_it.array_iterator, -1);
7055  break;
7056  }
7057 
7058  default:
7059  {
7060  --m_it.primitive_iterator;
7061  break;
7062  }
7063  }
7064 
7065  return *this;
7066  }
7067 
7072  bool operator==(const const_iterator& other) const
7073  {
7074  // if objects are not the same, the comparison is undefined
7075  if (m_object != other.m_object)
7076  {
7077  Throw<std::domain_error>("cannot compare iterators of different containers");
7078  }
7079 
7080  assert(m_object != nullptr);
7081 
7082  switch (m_object->m_type)
7083  {
7085  {
7086  return (m_it.object_iterator == other.m_it.object_iterator);
7087  }
7088 
7090  {
7091  return (m_it.array_iterator == other.m_it.array_iterator);
7092  }
7093 
7094  default:
7095  {
7096  return (m_it.primitive_iterator == other.m_it.primitive_iterator);
7097  }
7098  }
7099  }
7100 
7105  bool operator!=(const const_iterator& other) const
7106  {
7107  return not operator==(other);
7108  }
7109 
7114  bool operator<(const const_iterator& other) const
7115  {
7116  // if objects are not the same, the comparison is undefined
7117  if (m_object != other.m_object)
7118  {
7119  Throw<std::domain_error>("cannot compare iterators of different containers");
7120  }
7121 
7122  assert(m_object != nullptr);
7123 
7124  switch (m_object->m_type)
7125  {
7127  {
7128  Throw<std::domain_error>("cannot compare order of object iterators");
7129  }
7130 
7132  {
7133  return (m_it.array_iterator < other.m_it.array_iterator);
7134  }
7135 
7136  default:
7137  {
7138  return (m_it.primitive_iterator < other.m_it.primitive_iterator);
7139  }
7140  }
7141  }
7142 
7147  bool operator<=(const const_iterator& other) const
7148  {
7149  return not other.operator < (*this);
7150  }
7151 
7156  bool operator>(const const_iterator& other) const
7157  {
7158  return not operator<=(other);
7159  }
7160 
7165  bool operator>=(const const_iterator& other) const
7166  {
7167  return not operator<(other);
7168  }
7169 
7175  {
7176  assert(m_object != nullptr);
7177 
7178  switch (m_object->m_type)
7179  {
7181  {
7182  Throw<std::domain_error>("cannot use offsets with object iterators");
7183  }
7184 
7186  {
7187  std::advance(m_it.array_iterator, i);
7188  break;
7189  }
7190 
7191  default:
7192  {
7193  m_it.primitive_iterator += i;
7194  break;
7195  }
7196  }
7197 
7198  return *this;
7199  }
7200 
7206  {
7207  return operator+=(-i);
7208  }
7209 
7215  {
7216  auto result = *this;
7217  result += i;
7218  return result;
7219  }
7220 
7226  {
7227  auto result = *this;
7228  result -= i;
7229  return result;
7230  }
7231 
7237  {
7238  assert(m_object != nullptr);
7239 
7240  switch (m_object->m_type)
7241  {
7243  {
7244  Throw<std::domain_error>("cannot use offsets with object iterators");
7245  }
7246 
7248  {
7249  return m_it.array_iterator - other.m_it.array_iterator;
7250  }
7251 
7252  default:
7253  {
7254  return m_it.primitive_iterator - other.m_it.primitive_iterator;
7255  }
7256  }
7257  }
7258 
7264  {
7265  assert(m_object != nullptr);
7266 
7267  switch (m_object->m_type)
7268  {
7270  {
7271  Throw<std::domain_error>("cannot use operator[] for object iterators");
7272  }
7273 
7275  {
7276  return *std::next(m_it.array_iterator, n);
7277  }
7278 
7280  {
7281  Throw<std::out_of_range>("cannot get value");
7282  }
7283 
7284  default:
7285  {
7286  if (m_it.primitive_iterator == -n)
7287  {
7288  return *m_object;
7289  }
7290  else
7291  {
7292  Throw<std::out_of_range>("cannot get value");
7293  }
7294  }
7295  }
7296  }
7297 
7302  typename object_t::key_type key() const
7303  {
7304  assert(m_object != nullptr);
7305 
7306  if (m_object->is_object())
7307  {
7308  return m_it.object_iterator->first;
7309  }
7310  else
7311  {
7312  Throw<std::domain_error>("cannot use key() for non-object iterators");
7313  }
7314  }
7315 
7321  {
7322  return operator*();
7323  }
7324 
7325  private:
7327  pointer m_object = nullptr;
7329  internal_iterator m_it = internal_iterator();
7330  };
7331 
7344  class iterator : public const_iterator
7345  {
7346  public:
7348  using pointer = typename basic_json::pointer;
7350 
7352  iterator() = default;
7353 
7355  explicit iterator(pointer object) noexcept
7356  : base_iterator(object)
7357  {}
7358 
7360  iterator(const iterator& other) noexcept
7361  : base_iterator(other)
7362  {}
7363 
7365  iterator& operator=(iterator other) noexcept(
7366  std::is_nothrow_move_constructible<pointer>::value and
7367  std::is_nothrow_move_assignable<pointer>::value and
7368  std::is_nothrow_move_constructible<internal_iterator>::value and
7369  std::is_nothrow_move_assignable<internal_iterator>::value
7370  )
7371  {
7372  base_iterator::operator=(other);
7373  return *this;
7374  }
7375 
7378  {
7379  return const_cast<reference>(base_iterator::operator*());
7380  }
7381 
7384  {
7385  return const_cast<pointer>(base_iterator::operator->());
7386  }
7387 
7390  {
7391  iterator result = *this;
7393  return result;
7394  }
7395 
7398  {
7400  return *this;
7401  }
7402 
7405  {
7406  iterator result = *this;
7408  return result;
7409  }
7410 
7413  {
7415  return *this;
7416  }
7417 
7420  {
7422  return *this;
7423  }
7424 
7427  {
7429  return *this;
7430  }
7431 
7434  {
7435  auto result = *this;
7436  result += i;
7437  return result;
7438  }
7439 
7442  {
7443  auto result = *this;
7444  result -= i;
7445  return result;
7446  }
7447 
7449  difference_type operator-(const iterator& other) const
7450  {
7451  return base_iterator::operator-(other);
7452  }
7453 
7456  {
7457  return const_cast<reference>(base_iterator::operator[](n));
7458  }
7459 
7462  {
7463  return const_cast<reference>(base_iterator::value());
7464  }
7465  };
7466 
7484  template<typename Base>
7485  class json_reverse_iterator : public std::reverse_iterator<Base>
7486  {
7487  public:
7489  using base_iterator = std::reverse_iterator<Base>;
7491  using reference = typename Base::reference;
7492 
7494  json_reverse_iterator(const typename base_iterator::iterator_type& it) noexcept
7495  : base_iterator(it)
7496  {}
7497 
7500  : base_iterator(it)
7501  {}
7502 
7505  {
7506  return base_iterator::operator++(1);
7507  }
7508 
7511  {
7513  return *this;
7514  }
7515 
7518  {
7519  return base_iterator::operator--(1);
7520  }
7521 
7524  {
7526  return *this;
7527  }
7528 
7531  {
7533  return *this;
7534  }
7535 
7538  {
7539  auto result = *this;
7540  result += i;
7541  return result;
7542  }
7543 
7546  {
7547  auto result = *this;
7548  result -= i;
7549  return result;
7550  }
7551 
7554  {
7555  return this->base() - other.base();
7556  }
7557 
7560  {
7561  return *(this->operator+(n));
7562  }
7563 
7565  typename object_t::key_type key() const
7566  {
7567  auto it = --this->base();
7568  return it.key();
7569  }
7570 
7573  {
7574  auto it = --this->base();
7575  return it.operator * ();
7576  }
7577  };
7578 
7579 
7580  private:
7582  // lexer and parser //
7584 
7592  class lexer
7593  {
7594  public:
7596  enum class token_type
7597  {
7598  uninitialized,
7599  literal_true,
7600  literal_false,
7601  literal_null,
7602  value_string,
7603  value_number,
7604  begin_array,
7605  begin_object,
7606  end_array,
7607  end_object,
7608  name_separator,
7609  value_separator,
7610  parse_error,
7611  end_of_input
7612  };
7613 
7615  using lexer_char_t = unsigned char;
7616 
7618  lexer(const lexer_char_t* buff, const size_t len) noexcept
7619  : m_content(buff)
7620  {
7621  assert(m_content != nullptr);
7622  m_start = m_cursor = m_content;
7623  m_limit = m_content + len;
7624  }
7625 
7627  explicit lexer(std::istream& s)
7628  : m_stream(&s), m_line_buffer()
7629  {
7630  // immediately abort if stream is erroneous
7631  if (s.fail())
7632  {
7633  Throw<std::invalid_argument>("stream error: " + std::string(strerror(errno)));
7634  }
7635 
7636  // fill buffer
7637  fill_line_buffer();
7638 
7639  // skip UTF-8 byte-order mark
7640  if (m_line_buffer.size() >= 3 and m_line_buffer.substr(0, 3) == "\xEF\xBB\xBF")
7641  {
7642  m_line_buffer[0] = ' ';
7643  m_line_buffer[1] = ' ';
7644  m_line_buffer[2] = ' ';
7645  }
7646  }
7647 
7648  // switch off unwanted functions (due to pointer members)
7649  lexer() = delete;
7650  lexer(const lexer&) = delete;
7651  lexer operator=(const lexer&) = delete;
7652 
7676  static string_t to_unicode(const std::size_t codepoint1,
7677  const std::size_t codepoint2 = 0)
7678  {
7679  // calculate the code point from the given code points
7680  std::size_t codepoint = codepoint1;
7681 
7682  // check if codepoint1 is a high surrogate
7683  if (codepoint1 >= 0xD800 and codepoint1 <= 0xDBFF)
7684  {
7685  // check if codepoint2 is a low surrogate
7686  if (codepoint2 >= 0xDC00 and codepoint2 <= 0xDFFF)
7687  {
7688  codepoint =
7689  // high surrogate occupies the most significant 22 bits
7690  (codepoint1 << 10)
7691  // low surrogate occupies the least significant 15 bits
7692  + codepoint2
7693  // there is still the 0xD800, 0xDC00 and 0x10000 noise
7694  // in the result so we have to subtract with:
7695  // (0xD800 << 10) + DC00 - 0x10000 = 0x35FDC00
7696  - 0x35FDC00;
7697  }
7698  else
7699  {
7700  Throw<std::invalid_argument>("missing or wrong low surrogate");
7701  }
7702  }
7703 
7704  string_t result;
7705 
7706  if (codepoint < 0x80)
7707  {
7708  // 1-byte characters: 0xxxxxxx (ASCII)
7709  result.append(1, static_cast<typename string_t::value_type>(codepoint));
7710  }
7711  else if (codepoint <= 0x7ff)
7712  {
7713  // 2-byte characters: 110xxxxx 10xxxxxx
7714  result.append(1, static_cast<typename string_t::value_type>(0xC0 | ((codepoint >> 6) & 0x1F)));
7715  result.append(1, static_cast<typename string_t::value_type>(0x80 | (codepoint & 0x3F)));
7716  }
7717  else if (codepoint <= 0xffff)
7718  {
7719  // 3-byte characters: 1110xxxx 10xxxxxx 10xxxxxx
7720  result.append(1, static_cast<typename string_t::value_type>(0xE0 | ((codepoint >> 12) & 0x0F)));
7721  result.append(1, static_cast<typename string_t::value_type>(0x80 | ((codepoint >> 6) & 0x3F)));
7722  result.append(1, static_cast<typename string_t::value_type>(0x80 | (codepoint & 0x3F)));
7723  }
7724  else if (codepoint <= 0x10ffff)
7725  {
7726  // 4-byte characters: 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
7727  result.append(1, static_cast<typename string_t::value_type>(0xF0 | ((codepoint >> 18) & 0x07)));
7728  result.append(1, static_cast<typename string_t::value_type>(0x80 | ((codepoint >> 12) & 0x3F)));
7729  result.append(1, static_cast<typename string_t::value_type>(0x80 | ((codepoint >> 6) & 0x3F)));
7730  result.append(1, static_cast<typename string_t::value_type>(0x80 | (codepoint & 0x3F)));
7731  }
7732  else
7733  {
7734  Throw<std::out_of_range>("code points above 0x10FFFF are invalid");
7735  }
7736 
7737  return result;
7738  }
7739 
7741  static std::string token_type_name(const token_type t)
7742  {
7743  switch (t)
7744  {
7745  case token_type::uninitialized:
7746  return "<uninitialized>";
7747  case token_type::literal_true:
7748  return "true literal";
7749  case token_type::literal_false:
7750  return "false literal";
7751  case token_type::literal_null:
7752  return "null literal";
7753  case token_type::value_string:
7754  return "string literal";
7755  case token_type::value_number:
7756  return "number literal";
7757  case token_type::begin_array:
7758  return "'['";
7759  case token_type::begin_object:
7760  return "'{'";
7761  case token_type::end_array:
7762  return "']'";
7763  case token_type::end_object:
7764  return "'}'";
7765  case token_type::name_separator:
7766  return "':'";
7767  case token_type::value_separator:
7768  return "','";
7769  case token_type::parse_error:
7770  return "<parse error>";
7771  case token_type::end_of_input:
7772  return "end of input";
7773  default:
7774  {
7775  // catch non-enum values
7776  return "unknown token"; // LCOV_EXCL_LINE
7777  }
7778  }
7779  }
7780 
7802  token_type scan()
7803  {
7804  while (true)
7805  {
7806  // pointer for backtracking information
7807  m_marker = nullptr;
7808 
7809  // remember the begin of the token
7810  m_start = m_cursor;
7811  assert(m_start != nullptr);
7812 
7813 
7814  {
7815  lexer_char_t yych;
7816  unsigned int yyaccept = 0;
7817  static const unsigned char yybm[] =
7818  {
7819  0, 0, 0, 0, 0, 0, 0, 0,
7820  0, 32, 32, 0, 0, 32, 0, 0,
7821  0, 0, 0, 0, 0, 0, 0, 0,
7822  0, 0, 0, 0, 0, 0, 0, 0,
7823  160, 128, 0, 128, 128, 128, 128, 128,
7824  128, 128, 128, 128, 128, 128, 128, 128,
7825  192, 192, 192, 192, 192, 192, 192, 192,
7826  192, 192, 128, 128, 128, 128, 128, 128,
7827  128, 128, 128, 128, 128, 128, 128, 128,
7828  128, 128, 128, 128, 128, 128, 128, 128,
7829  128, 128, 128, 128, 128, 128, 128, 128,
7830  128, 128, 128, 128, 0, 128, 128, 128,
7831  128, 128, 128, 128, 128, 128, 128, 128,
7832  128, 128, 128, 128, 128, 128, 128, 128,
7833  128, 128, 128, 128, 128, 128, 128, 128,
7834  128, 128, 128, 128, 128, 128, 128, 128,
7835  0, 0, 0, 0, 0, 0, 0, 0,
7836  0, 0, 0, 0, 0, 0, 0, 0,
7837  0, 0, 0, 0, 0, 0, 0, 0,
7838  0, 0, 0, 0, 0, 0, 0, 0,
7839  0, 0, 0, 0, 0, 0, 0, 0,
7840  0, 0, 0, 0, 0, 0, 0, 0,
7841  0, 0, 0, 0, 0, 0, 0, 0,
7842  0, 0, 0, 0, 0, 0, 0, 0,
7843  0, 0, 0, 0, 0, 0, 0, 0,
7844  0, 0, 0, 0, 0, 0, 0, 0,
7845  0, 0, 0, 0, 0, 0, 0, 0,
7846  0, 0, 0, 0, 0, 0, 0, 0,
7847  0, 0, 0, 0, 0, 0, 0, 0,
7848  0, 0, 0, 0, 0, 0, 0, 0,
7849  0, 0, 0, 0, 0, 0, 0, 0,
7850  0, 0, 0, 0, 0, 0, 0, 0,
7851  };
7852  if ((m_limit - m_cursor) < 5)
7853  {
7854  fill_line_buffer(5); // LCOV_EXCL_LINE
7855  }
7856  yych = *m_cursor;
7857  if (yybm[0 + yych] & 32)
7858  {
7859  goto basic_json_parser_6;
7860  }
7861  if (yych <= '[')
7862  {
7863  if (yych <= '-')
7864  {
7865  if (yych <= '"')
7866  {
7867  if (yych <= 0x00)
7868  {
7869  goto basic_json_parser_2;
7870  }
7871  if (yych <= '!')
7872  {
7873  goto basic_json_parser_4;
7874  }
7875  goto basic_json_parser_9;
7876  }
7877  else
7878  {
7879  if (yych <= '+')
7880  {
7881  goto basic_json_parser_4;
7882  }
7883  if (yych <= ',')
7884  {
7885  goto basic_json_parser_10;
7886  }
7887  goto basic_json_parser_12;
7888  }
7889  }
7890  else
7891  {
7892  if (yych <= '9')
7893  {
7894  if (yych <= '/')
7895  {
7896  goto basic_json_parser_4;
7897  }
7898  if (yych <= '0')
7899  {
7900  goto basic_json_parser_13;
7901  }
7902  goto basic_json_parser_15;
7903  }
7904  else
7905  {
7906  if (yych <= ':')
7907  {
7908  goto basic_json_parser_17;
7909  }
7910  if (yych <= 'Z')
7911  {
7912  goto basic_json_parser_4;
7913  }
7914  goto basic_json_parser_19;
7915  }
7916  }
7917  }
7918  else
7919  {
7920  if (yych <= 'n')
7921  {
7922  if (yych <= 'e')
7923  {
7924  if (yych == ']')
7925  {
7926  goto basic_json_parser_21;
7927  }
7928  goto basic_json_parser_4;
7929  }
7930  else
7931  {
7932  if (yych <= 'f')
7933  {
7934  goto basic_json_parser_23;
7935  }
7936  if (yych <= 'm')
7937  {
7938  goto basic_json_parser_4;
7939  }
7940  goto basic_json_parser_24;
7941  }
7942  }
7943  else
7944  {
7945  if (yych <= 'z')
7946  {
7947  if (yych == 't')
7948  {
7949  goto basic_json_parser_25;
7950  }
7951  goto basic_json_parser_4;
7952  }
7953  else
7954  {
7955  if (yych <= '{')
7956  {
7957  goto basic_json_parser_26;
7958  }
7959  if (yych == '}')
7960  {
7961  goto basic_json_parser_28;
7962  }
7963  goto basic_json_parser_4;
7964  }
7965  }
7966  }
7967 basic_json_parser_2:
7968  ++m_cursor;
7969  {
7970  last_token_type = token_type::end_of_input;
7971  break;
7972  }
7973 basic_json_parser_4:
7974  ++m_cursor;
7975 basic_json_parser_5:
7976  {
7977  last_token_type = token_type::parse_error;
7978  break;
7979  }
7980 basic_json_parser_6:
7981  ++m_cursor;
7982  if (m_limit <= m_cursor)
7983  {
7984  fill_line_buffer(1); // LCOV_EXCL_LINE
7985  }
7986  yych = *m_cursor;
7987  if (yybm[0 + yych] & 32)
7988  {
7989  goto basic_json_parser_6;
7990  }
7991  {
7992  continue;
7993  }
7994 basic_json_parser_9:
7995  yyaccept = 0;
7996  yych = *(m_marker = ++m_cursor);
7997  if (yych <= 0x1F)
7998  {
7999  goto basic_json_parser_5;
8000  }
8001  if (yych <= 0x7F)
8002  {
8003  goto basic_json_parser_31;
8004  }
8005  if (yych <= 0xC1)
8006  {
8007  goto basic_json_parser_5;
8008  }
8009  if (yych <= 0xF4)
8010  {
8011  goto basic_json_parser_31;
8012  }
8013  goto basic_json_parser_5;
8014 basic_json_parser_10:
8015  ++m_cursor;
8016  {
8017  last_token_type = token_type::value_separator;
8018  break;
8019  }
8020 basic_json_parser_12:
8021  yych = *++m_cursor;
8022  if (yych <= '/')
8023  {
8024  goto basic_json_parser_5;
8025  }
8026  if (yych <= '0')
8027  {
8028  goto basic_json_parser_13;
8029  }
8030  if (yych <= '9')
8031  {
8032  goto basic_json_parser_15;
8033  }
8034  goto basic_json_parser_5;
8035 basic_json_parser_13:
8036  yyaccept = 1;
8037  yych = *(m_marker = ++m_cursor);
8038  if (yych <= 'D')
8039  {
8040  if (yych == '.')
8041  {
8042  goto basic_json_parser_43;
8043  }
8044  }
8045  else
8046  {
8047  if (yych <= 'E')
8048  {
8049  goto basic_json_parser_44;
8050  }
8051  if (yych == 'e')
8052  {
8053  goto basic_json_parser_44;
8054  }
8055  }
8056 basic_json_parser_14:
8057  {
8058  last_token_type = token_type::value_number;
8059  break;
8060  }
8061 basic_json_parser_15:
8062  yyaccept = 1;
8063  m_marker = ++m_cursor;
8064  if ((m_limit - m_cursor) < 3)
8065  {
8066  fill_line_buffer(3); // LCOV_EXCL_LINE
8067  }
8068  yych = *m_cursor;
8069  if (yybm[0 + yych] & 64)
8070  {
8071  goto basic_json_parser_15;
8072  }
8073  if (yych <= 'D')
8074  {
8075  if (yych == '.')
8076  {
8077  goto basic_json_parser_43;
8078  }
8079  goto basic_json_parser_14;
8080  }
8081  else
8082  {
8083  if (yych <= 'E')
8084  {
8085  goto basic_json_parser_44;
8086  }
8087  if (yych == 'e')
8088  {
8089  goto basic_json_parser_44;
8090  }
8091  goto basic_json_parser_14;
8092  }
8093 basic_json_parser_17:
8094  ++m_cursor;
8095  {
8096  last_token_type = token_type::name_separator;
8097  break;
8098  }
8099 basic_json_parser_19:
8100  ++m_cursor;
8101  {
8102  last_token_type = token_type::begin_array;
8103  break;
8104  }
8105 basic_json_parser_21:
8106  ++m_cursor;
8107  {
8108  last_token_type = token_type::end_array;
8109  break;
8110  }
8111 basic_json_parser_23:
8112  yyaccept = 0;
8113  yych = *(m_marker = ++m_cursor);
8114  if (yych == 'a')
8115  {
8116  goto basic_json_parser_45;
8117  }
8118  goto basic_json_parser_5;
8119 basic_json_parser_24:
8120  yyaccept = 0;
8121  yych = *(m_marker = ++m_cursor);
8122  if (yych == 'u')
8123  {
8124  goto basic_json_parser_46;
8125  }
8126  goto basic_json_parser_5;
8127 basic_json_parser_25:
8128  yyaccept = 0;
8129  yych = *(m_marker = ++m_cursor);
8130  if (yych == 'r')
8131  {
8132  goto basic_json_parser_47;
8133  }
8134  goto basic_json_parser_5;
8135 basic_json_parser_26:
8136  ++m_cursor;
8137  {
8138  last_token_type = token_type::begin_object;
8139  break;
8140  }
8141 basic_json_parser_28:
8142  ++m_cursor;
8143  {
8144  last_token_type = token_type::end_object;
8145  break;
8146  }
8147 basic_json_parser_30:
8148  ++m_cursor;
8149  if (m_limit <= m_cursor)
8150  {
8151  fill_line_buffer(1); // LCOV_EXCL_LINE
8152  }
8153  yych = *m_cursor;
8154 basic_json_parser_31:
8155  if (yybm[0 + yych] & 128)
8156  {
8157  goto basic_json_parser_30;
8158  }
8159  if (yych <= 0xE0)
8160  {
8161  if (yych <= '\\')
8162  {
8163  if (yych <= 0x1F)
8164  {
8165  goto basic_json_parser_32;
8166  }
8167  if (yych <= '"')
8168  {
8169  goto basic_json_parser_33;
8170  }
8171  goto basic_json_parser_35;
8172  }
8173  else
8174  {
8175  if (yych <= 0xC1)
8176  {
8177  goto basic_json_parser_32;
8178  }
8179  if (yych <= 0xDF)
8180  {
8181  goto basic_json_parser_36;
8182  }
8183  goto basic_json_parser_37;
8184  }
8185  }
8186  else
8187  {
8188  if (yych <= 0xEF)
8189  {
8190  if (yych == 0xED)
8191  {
8192  goto basic_json_parser_39;
8193  }
8194  goto basic_json_parser_38;
8195  }
8196  else
8197  {
8198  if (yych <= 0xF0)
8199  {
8200  goto basic_json_parser_40;
8201  }
8202  if (yych <= 0xF3)
8203  {
8204  goto basic_json_parser_41;
8205  }
8206  if (yych <= 0xF4)
8207  {
8208  goto basic_json_parser_42;
8209  }
8210  }
8211  }
8212 basic_json_parser_32:
8213  m_cursor = m_marker;
8214  if (yyaccept == 0)
8215  {
8216  goto basic_json_parser_5;
8217  }
8218  else
8219  {
8220  goto basic_json_parser_14;
8221  }
8222 basic_json_parser_33:
8223  ++m_cursor;
8224  {
8225  last_token_type = token_type::value_string;
8226  break;
8227  }
8228 basic_json_parser_35:
8229  ++m_cursor;
8230  if (m_limit <= m_cursor)
8231  {
8232  fill_line_buffer(1); // LCOV_EXCL_LINE
8233  }
8234  yych = *m_cursor;
8235  if (yych <= 'e')
8236  {
8237  if (yych <= '/')
8238  {
8239  if (yych == '"')
8240  {
8241  goto basic_json_parser_30;
8242  }
8243  if (yych <= '.')
8244  {
8245  goto basic_json_parser_32;
8246  }
8247  goto basic_json_parser_30;
8248  }
8249  else
8250  {
8251  if (yych <= '\\')
8252  {
8253  if (yych <= '[')
8254  {
8255  goto basic_json_parser_32;
8256  }
8257  goto basic_json_parser_30;
8258  }
8259  else
8260  {
8261  if (yych == 'b')
8262  {
8263  goto basic_json_parser_30;
8264  }
8265  goto basic_json_parser_32;
8266  }
8267  }
8268  }
8269  else
8270  {
8271  if (yych <= 'q')
8272  {
8273  if (yych <= 'f')
8274  {
8275  goto basic_json_parser_30;
8276  }
8277  if (yych == 'n')
8278  {
8279  goto basic_json_parser_30;
8280  }
8281  goto basic_json_parser_32;
8282  }
8283  else
8284  {
8285  if (yych <= 's')
8286  {
8287  if (yych <= 'r')
8288  {
8289  goto basic_json_parser_30;
8290  }
8291  goto basic_json_parser_32;
8292  }
8293  else
8294  {
8295  if (yych <= 't')
8296  {
8297  goto basic_json_parser_30;
8298  }
8299  if (yych <= 'u')
8300  {
8301  goto basic_json_parser_48;
8302  }
8303  goto basic_json_parser_32;
8304  }
8305  }
8306  }
8307 basic_json_parser_36:
8308  ++m_cursor;
8309  if (m_limit <= m_cursor)
8310  {
8311  fill_line_buffer(1); // LCOV_EXCL_LINE
8312  }
8313  yych = *m_cursor;
8314  if (yych <= 0x7F)
8315  {
8316  goto basic_json_parser_32;
8317  }
8318  if (yych <= 0xBF)
8319  {
8320  goto basic_json_parser_30;
8321  }
8322  goto basic_json_parser_32;
8323 basic_json_parser_37:
8324  ++m_cursor;
8325  if (m_limit <= m_cursor)
8326  {
8327  fill_line_buffer(1); // LCOV_EXCL_LINE
8328  }
8329  yych = *m_cursor;
8330  if (yych <= 0x9F)
8331  {
8332  goto basic_json_parser_32;
8333  }
8334  if (yych <= 0xBF)
8335  {
8336  goto basic_json_parser_36;
8337  }
8338  goto basic_json_parser_32;
8339 basic_json_parser_38:
8340  ++m_cursor;
8341  if (m_limit <= m_cursor)
8342  {
8343  fill_line_buffer(1); // LCOV_EXCL_LINE
8344  }
8345  yych = *m_cursor;
8346  if (yych <= 0x7F)
8347  {
8348  goto basic_json_parser_32;
8349  }
8350  if (yych <= 0xBF)
8351  {
8352  goto basic_json_parser_36;
8353  }
8354  goto basic_json_parser_32;
8355 basic_json_parser_39:
8356  ++m_cursor;
8357  if (m_limit <= m_cursor)
8358  {
8359  fill_line_buffer(1); // LCOV_EXCL_LINE
8360  }
8361  yych = *m_cursor;
8362  if (yych <= 0x7F)
8363  {
8364  goto basic_json_parser_32;
8365  }
8366  if (yych <= 0x9F)
8367  {
8368  goto basic_json_parser_36;
8369  }
8370  goto basic_json_parser_32;
8371 basic_json_parser_40:
8372  ++m_cursor;
8373  if (m_limit <= m_cursor)
8374  {
8375  fill_line_buffer(1); // LCOV_EXCL_LINE
8376  }
8377  yych = *m_cursor;
8378  if (yych <= 0x8F)
8379  {
8380  goto basic_json_parser_32;
8381  }
8382  if (yych <= 0xBF)
8383  {
8384  goto basic_json_parser_38;
8385  }
8386  goto basic_json_parser_32;
8387 basic_json_parser_41:
8388  ++m_cursor;
8389  if (m_limit <= m_cursor)
8390  {
8391  fill_line_buffer(1); // LCOV_EXCL_LINE
8392  }
8393  yych = *m_cursor;
8394  if (yych <= 0x7F)
8395  {
8396  goto basic_json_parser_32;
8397  }
8398  if (yych <= 0xBF)
8399  {
8400  goto basic_json_parser_38;
8401  }
8402  goto basic_json_parser_32;
8403 basic_json_parser_42:
8404  ++m_cursor;
8405  if (m_limit <= m_cursor)
8406  {
8407  fill_line_buffer(1); // LCOV_EXCL_LINE
8408  }
8409  yych = *m_cursor;
8410  if (yych <= 0x7F)
8411  {
8412  goto basic_json_parser_32;
8413  }
8414  if (yych <= 0x8F)
8415  {
8416  goto basic_json_parser_38;
8417  }
8418  goto basic_json_parser_32;
8419 basic_json_parser_43:
8420  yych = *++m_cursor;
8421  if (yych <= '/')
8422  {
8423  goto basic_json_parser_32;
8424  }
8425  if (yych <= '9')
8426  {
8427  goto basic_json_parser_49;
8428  }
8429  goto basic_json_parser_32;
8430 basic_json_parser_44:
8431  yych = *++m_cursor;
8432  if (yych <= ',')
8433  {
8434  if (yych == '+')
8435  {
8436  goto basic_json_parser_51;
8437  }
8438  goto basic_json_parser_32;
8439  }
8440  else
8441  {
8442  if (yych <= '-')
8443  {
8444  goto basic_json_parser_51;
8445  }
8446  if (yych <= '/')
8447  {
8448  goto basic_json_parser_32;
8449  }
8450  if (yych <= '9')
8451  {
8452  goto basic_json_parser_52;
8453  }
8454  goto basic_json_parser_32;
8455  }
8456 basic_json_parser_45:
8457  yych = *++m_cursor;
8458  if (yych == 'l')
8459  {
8460  goto basic_json_parser_54;
8461  }
8462  goto basic_json_parser_32;
8463 basic_json_parser_46:
8464  yych = *++m_cursor;
8465  if (yych == 'l')
8466  {
8467  goto basic_json_parser_55;
8468  }
8469  goto basic_json_parser_32;
8470 basic_json_parser_47:
8471  yych = *++m_cursor;
8472  if (yych == 'u')
8473  {
8474  goto basic_json_parser_56;
8475  }
8476  goto basic_json_parser_32;
8477 basic_json_parser_48:
8478  ++m_cursor;
8479  if (m_limit <= m_cursor)
8480  {
8481  fill_line_buffer(1); // LCOV_EXCL_LINE
8482  }
8483  yych = *m_cursor;
8484  if (yych <= '@')
8485  {
8486  if (yych <= '/')
8487  {
8488  goto basic_json_parser_32;
8489  }
8490  if (yych <= '9')
8491  {
8492  goto basic_json_parser_57;
8493  }
8494  goto basic_json_parser_32;
8495  }
8496  else
8497  {
8498  if (yych <= 'F')
8499  {
8500  goto basic_json_parser_57;
8501  }
8502  if (yych <= '`')
8503  {
8504  goto basic_json_parser_32;
8505  }
8506  if (yych <= 'f')
8507  {
8508  goto basic_json_parser_57;
8509  }
8510  goto basic_json_parser_32;
8511  }
8512 basic_json_parser_49:
8513  yyaccept = 1;
8514  m_marker = ++m_cursor;
8515  if ((m_limit - m_cursor) < 3)
8516  {
8517  fill_line_buffer(3); // LCOV_EXCL_LINE
8518  }
8519  yych = *m_cursor;
8520  if (yych <= 'D')
8521  {
8522  if (yych <= '/')
8523  {
8524  goto basic_json_parser_14;
8525  }
8526  if (yych <= '9')
8527  {
8528  goto basic_json_parser_49;
8529  }
8530  goto basic_json_parser_14;
8531  }
8532  else
8533  {
8534  if (yych <= 'E')
8535  {
8536  goto basic_json_parser_44;
8537  }
8538  if (yych == 'e')
8539  {
8540  goto basic_json_parser_44;
8541  }
8542  goto basic_json_parser_14;
8543  }
8544 basic_json_parser_51:
8545  yych = *++m_cursor;
8546  if (yych <= '/')
8547  {
8548  goto basic_json_parser_32;
8549  }
8550  if (yych >= ':')
8551  {
8552  goto basic_json_parser_32;
8553  }
8554 basic_json_parser_52:
8555  ++m_cursor;
8556  if (m_limit <= m_cursor)
8557  {
8558  fill_line_buffer(1); // LCOV_EXCL_LINE
8559  }
8560  yych = *m_cursor;
8561  if (yych <= '/')
8562  {
8563  goto basic_json_parser_14;
8564  }
8565  if (yych <= '9')
8566  {
8567  goto basic_json_parser_52;
8568  }
8569  goto basic_json_parser_14;
8570 basic_json_parser_54:
8571  yych = *++m_cursor;
8572  if (yych == 's')
8573  {
8574  goto basic_json_parser_58;
8575  }
8576  goto basic_json_parser_32;
8577 basic_json_parser_55:
8578  yych = *++m_cursor;
8579  if (yych == 'l')
8580  {
8581  goto basic_json_parser_59;
8582  }
8583  goto basic_json_parser_32;
8584 basic_json_parser_56:
8585  yych = *++m_cursor;
8586  if (yych == 'e')
8587  {
8588  goto basic_json_parser_61;
8589  }
8590  goto basic_json_parser_32;
8591 basic_json_parser_57:
8592  ++m_cursor;
8593  if (m_limit <= m_cursor)
8594  {
8595  fill_line_buffer(1); // LCOV_EXCL_LINE
8596  }
8597  yych = *m_cursor;
8598  if (yych <= '@')
8599  {
8600  if (yych <= '/')
8601  {
8602  goto basic_json_parser_32;
8603  }
8604  if (yych <= '9')
8605  {
8606  goto basic_json_parser_63;
8607  }
8608  goto basic_json_parser_32;
8609  }
8610  else
8611  {
8612  if (yych <= 'F')
8613  {
8614  goto basic_json_parser_63;
8615  }
8616  if (yych <= '`')
8617  {
8618  goto basic_json_parser_32;
8619  }
8620  if (yych <= 'f')
8621  {
8622  goto basic_json_parser_63;
8623  }
8624  goto basic_json_parser_32;
8625  }
8626 basic_json_parser_58:
8627  yych = *++m_cursor;
8628  if (yych == 'e')
8629  {
8630  goto basic_json_parser_64;
8631  }
8632  goto basic_json_parser_32;
8633 basic_json_parser_59:
8634  ++m_cursor;
8635  {
8636  last_token_type = token_type::literal_null;
8637  break;
8638  }
8639 basic_json_parser_61:
8640  ++m_cursor;
8641  {
8642  last_token_type = token_type::literal_true;
8643  break;
8644  }
8645 basic_json_parser_63:
8646  ++m_cursor;
8647  if (m_limit <= m_cursor)
8648  {
8649  fill_line_buffer(1); // LCOV_EXCL_LINE
8650  }
8651  yych = *m_cursor;
8652  if (yych <= '@')
8653  {
8654  if (yych <= '/')
8655  {
8656  goto basic_json_parser_32;
8657  }
8658  if (yych <= '9')
8659  {
8660  goto basic_json_parser_66;
8661  }
8662  goto basic_json_parser_32;
8663  }
8664  else
8665  {
8666  if (yych <= 'F')
8667  {
8668  goto basic_json_parser_66;
8669  }
8670  if (yych <= '`')
8671  {
8672  goto basic_json_parser_32;
8673  }
8674  if (yych <= 'f')
8675  {
8676  goto basic_json_parser_66;
8677  }
8678  goto basic_json_parser_32;
8679  }
8680 basic_json_parser_64:
8681  ++m_cursor;
8682  {
8683  last_token_type = token_type::literal_false;
8684  break;
8685  }
8686 basic_json_parser_66:
8687  ++m_cursor;
8688  if (m_limit <= m_cursor)
8689  {
8690  fill_line_buffer(1); // LCOV_EXCL_LINE
8691  }
8692  yych = *m_cursor;
8693  if (yych <= '@')
8694  {
8695  if (yych <= '/')
8696  {
8697  goto basic_json_parser_32;
8698  }
8699  if (yych <= '9')
8700  {
8701  goto basic_json_parser_30;
8702  }
8703  goto basic_json_parser_32;
8704  }
8705  else
8706  {
8707  if (yych <= 'F')
8708  {
8709  goto basic_json_parser_30;
8710  }
8711  if (yych <= '`')
8712  {
8713  goto basic_json_parser_32;
8714  }
8715  if (yych <= 'f')
8716  {
8717  goto basic_json_parser_30;
8718  }
8719  goto basic_json_parser_32;
8720  }
8721  }
8722 
8723  }
8724 
8725  return last_token_type;
8726  }
8727 
8756  void fill_line_buffer(size_t n = 0)
8757  {
8758  // if line buffer is used, m_content points to its data
8759  assert(m_line_buffer.empty()
8760  or m_content == reinterpret_cast<const lexer_char_t*>(m_line_buffer.data()));
8761 
8762  // if line buffer is used, m_limit is set past the end of its data
8763  assert(m_line_buffer.empty()
8764  or m_limit == m_content + m_line_buffer.size());
8765 
8766  // pointer relationships
8767  assert(m_content <= m_start);
8768  assert(m_start <= m_cursor);
8769  assert(m_cursor <= m_limit);
8770  assert(m_marker == nullptr or m_marker <= m_limit);
8771 
8772  // number of processed characters (p)
8773  const size_t num_processed_chars = static_cast<size_t>(m_start - m_content);
8774  // offset for m_marker wrt. to m_start
8775  const auto offset_marker = (m_marker == nullptr) ? 0 : m_marker - m_start;
8776  // number of unprocessed characters (u)
8777  const auto offset_cursor = m_cursor - m_start;
8778 
8779  // no stream is used or end of file is reached
8780  if (m_stream == nullptr or m_stream->eof())
8781  {
8782  // m_start may or may not be pointing into m_line_buffer at
8783  // this point. We trust the standand library to do the right
8784  // thing. See http://stackoverflow.com/q/28142011/266378
8785  m_line_buffer.assign(m_start, m_limit);
8786 
8787  // append n characters to make sure that there is sufficient
8788  // space between m_cursor and m_limit
8789  m_line_buffer.append(1, '\x00');
8790  if (n > 0)
8791  {
8792  m_line_buffer.append(n - 1, '\x01');
8793  }
8794  }
8795  else
8796  {
8797  // delete processed characters from line buffer
8798  m_line_buffer.erase(0, num_processed_chars);
8799  // read next line from input stream
8800  m_line_buffer_tmp.clear();
8801  std::getline(*m_stream, m_line_buffer_tmp, '\n');
8802 
8803  // add line with newline symbol to the line buffer
8804  m_line_buffer += m_line_buffer_tmp;
8805  m_line_buffer.push_back('\n');
8806  }
8807 
8808  // set pointers
8809  m_content = reinterpret_cast<const lexer_char_t*>(m_line_buffer.data());
8810  assert(m_content != nullptr);
8811  m_start = m_content;
8812  m_marker = m_start + offset_marker;
8813  m_cursor = m_start + offset_cursor;
8814  m_limit = m_start + m_line_buffer.size();
8815  }
8816 
8818  string_t get_token_string() const
8819  {
8820  assert(m_start != nullptr);
8821  return string_t(reinterpret_cast<typename string_t::const_pointer>(m_start),
8822  static_cast<size_t>(m_cursor - m_start));
8823  }
8824 
8882  string_t get_string() const
8883  {
8884  assert(m_cursor - m_start >= 2);
8885 
8886  string_t result;
8887  result.reserve(static_cast<size_t>(m_cursor - m_start - 2));
8888 
8889  // iterate the result between the quotes
8890  for (const lexer_char_t* i = m_start + 1; i < m_cursor - 1; ++i)
8891  {
8892  // find next escape character
8893  auto e = std::find(i, m_cursor - 1, '\\');
8894  if (e != i)
8895  {
8896  // see https://github.com/nlohmann/json/issues/365#issuecomment-262874705
8897  for (auto k = i; k < e; k++)
8898  {
8899  result.push_back(static_cast<typename string_t::value_type>(*k));
8900  }
8901  i = e - 1; // -1 because of ++i
8902  }
8903  else
8904  {
8905  // processing escaped character
8906  // read next character
8907  ++i;
8908 
8909  switch (*i)
8910  {
8911  // the default escapes
8912  case 't':
8913  {
8914  result += "\t";
8915  break;
8916  }
8917  case 'b':
8918  {
8919  result += "\b";
8920  break;
8921  }
8922  case 'f':
8923  {
8924  result += "\f";
8925  break;
8926  }
8927  case 'n':
8928  {
8929  result += "\n";
8930  break;
8931  }
8932  case 'r':
8933  {
8934  result += "\r";
8935  break;
8936  }
8937  case '\\':
8938  {
8939  result += "\\";
8940  break;
8941  }
8942  case '/':
8943  {
8944  result += "/";
8945  break;
8946  }
8947  case '"':
8948  {
8949  result += "\"";
8950  break;
8951  }
8952 
8953  // unicode
8954  case 'u':
8955  {
8956  // get code xxxx from uxxxx
8957  auto codepoint = std::strtoul(std::string(reinterpret_cast<typename string_t::const_pointer>(i + 1),
8958  4).c_str(), nullptr, 16);
8959 
8960  // check if codepoint is a high surrogate
8961  if (codepoint >= 0xD800 and codepoint <= 0xDBFF)
8962  {
8963  // make sure there is a subsequent unicode
8964  if ((i + 6 >= m_limit) or * (i + 5) != '\\' or * (i + 6) != 'u')
8965  {
8966  Throw<std::invalid_argument>("missing low surrogate");
8967  }
8968 
8969  // get code yyyy from uxxxx\uyyyy
8970  auto codepoint2 = std::strtoul(std::string(reinterpret_cast<typename string_t::const_pointer>
8971  (i + 7), 4).c_str(), nullptr, 16);
8972  result += to_unicode(codepoint, codepoint2);
8973  // skip the next 10 characters (xxxx\uyyyy)
8974  i += 10;
8975  }
8976  else if (codepoint >= 0xDC00 and codepoint <= 0xDFFF)
8977  {
8978  // we found a lone low surrogate
8979  Throw<std::invalid_argument>("missing high surrogate");
8980  }
8981  else
8982  {
8983  // add unicode character(s)
8984  result += to_unicode(codepoint);
8985  // skip the next four characters (xxxx)
8986  i += 4;
8987  }
8988  break;
8989  }
8990  }
8991  }
8992  }
8993 
8994  return result;
8995  }
8996 
9012  long double str_to_float_t(long double* /* type */, char** endptr) const
9013  {
9014  return std::strtold(reinterpret_cast<typename string_t::const_pointer>(m_start), endptr);
9015  }
9016 
9032  double str_to_float_t(double* /* type */, char** endptr) const
9033  {
9034  return std::strtod(reinterpret_cast<typename string_t::const_pointer>(m_start), endptr);
9035  }
9036 
9052  float str_to_float_t(float* /* type */, char** endptr) const
9053  {
9054  return std::strtof(reinterpret_cast<typename string_t::const_pointer>(m_start), endptr);
9055  }
9056 
9078  void get_number(basic_json& result) const
9079  {
9080  assert(m_start != nullptr);
9081 
9082  const lexer::lexer_char_t* curptr = m_start;
9083 
9084  // accumulate the integer conversion result (unsigned for now)
9086 
9087  // maximum absolute value of the relevant integer type
9089 
9090  // temporarily store the type to avoid unecessary bitfield access
9091  value_t type;
9092 
9093  // look for sign
9094  if (*curptr == '-')
9095  {
9096  type = value_t::number_integer;
9097  max = static_cast<uint64_t>((std::numeric_limits<number_integer_t>::max)()) + 1;
9098  curptr++;
9099  }
9100  else
9101  {
9102  type = value_t::number_unsigned;
9103  max = static_cast<uint64_t>((std::numeric_limits<number_unsigned_t>::max)());
9104  }
9105 
9106  // count the significant figures
9107  for (; curptr < m_cursor; curptr++)
9108  {
9109  // quickly skip tests if a digit
9110  if (*curptr < '0' || *curptr > '9')
9111  {
9112  if (*curptr == '.')
9113  {
9114  // don't count '.' but change to float
9115  type = value_t::number_float;
9116  continue;
9117  }
9118  // assume exponent (if not then will fail parse): change to
9119  // float, stop counting and record exponent details
9120  type = value_t::number_float;
9121  break;
9122  }
9123 
9124  // skip if definitely not an integer
9125  if (type != value_t::number_float)
9126  {
9127  // multiply last value by ten and add the new digit
9128  auto temp = value * 10 + *curptr - '0';
9129 
9130  // test for overflow
9131  if (temp < value || temp > max)
9132  {
9133  // overflow
9134  type = value_t::number_float;
9135  }
9136  else
9137  {
9138  // no overflow - save it
9139  value = temp;
9140  }
9141  }
9142  }
9143 
9144  // save the value (if not a float)
9145  if (type == value_t::number_unsigned)
9146  {
9147  result.m_value.number_unsigned = value;
9148  }
9149  else if (type == value_t::number_integer)
9150  {
9151  result.m_value.number_integer = -static_cast<number_integer_t>(value);
9152  }
9153  else
9154  {
9155  // parse with strtod
9156  result.m_value.number_float = str_to_float_t(static_cast<number_float_t*>(nullptr), NULL);
9157 
9158  // replace infinity and NAN by null
9159  if (not std::isfinite(result.m_value.number_float))
9160  {
9161  type = value_t::null;
9162  result.m_value = basic_json::json_value();
9163  }
9164  }
9165 
9166  // save the type
9167  result.m_type = type;
9168  }
9169 
9170  private:
9172  std::istream* m_stream = nullptr;
9174  string_t m_line_buffer {};
9176  string_t m_line_buffer_tmp {};
9178  const lexer_char_t* m_content = nullptr;
9180  const lexer_char_t* m_start = nullptr;
9182  const lexer_char_t* m_marker = nullptr;
9184  const lexer_char_t* m_cursor = nullptr;
9186  const lexer_char_t* m_limit = nullptr;
9188  token_type last_token_type = token_type::end_of_input;
9189  };
9190 
9196  class parser
9197  {
9198  public:
9200  parser(const char* buff, const parser_callback_t cb = nullptr)
9201  : callback(cb),
9202  m_lexer(reinterpret_cast<const typename lexer::lexer_char_t*>(buff), std::strlen(buff))
9203  {}
9204 
9206  parser(std::istream& is, const parser_callback_t cb = nullptr)
9207  : callback(cb), m_lexer(is)
9208  {}
9209 
9211  template<class IteratorType, typename std::enable_if<
9212  std::is_same<typename std::iterator_traits<IteratorType>::iterator_category, std::random_access_iterator_tag>::value
9213  , int>::type
9214  = 0>
9215  parser(IteratorType first, IteratorType last, const parser_callback_t cb = nullptr)
9216  : callback(cb),
9217  m_lexer(reinterpret_cast<const typename lexer::lexer_char_t*>(&(*first)),
9218  static_cast<size_t>(std::distance(first, last)))
9219  {}
9220 
9222  basic_json parse()
9223  {
9224  // read first token
9225  get_token();
9226 
9227  basic_json result = parse_internal(true);
9228  result.assert_invariant();
9229 
9230  expect(lexer::token_type::end_of_input);
9231 
9232  // return parser result and replace it with null in case the
9233  // top-level value was discarded by the callback function
9234  return result.is_discarded() ? basic_json() : std::move(result);
9235  }
9236 
9237  private:
9239  basic_json parse_internal(bool keep)
9240  {
9241  auto result = basic_json(value_t::discarded);
9242 
9243  switch (last_token)
9244  {
9245  case lexer::token_type::begin_object:
9246  {
9247  if (keep and (not callback
9248  or ((keep = callback(depth++, parse_event_t::object_start, result)) != 0)))
9249  {
9250  // explicitly set result to object to cope with {}
9251  result.m_type = value_t::object;
9252  result.m_value = value_t::object;
9253  }
9254 
9255  // read next token
9256  get_token();
9257 
9258  // closing } -> we are done
9259  if (last_token == lexer::token_type::end_object)
9260  {
9261  get_token();
9262  if (keep and callback and not callback(--depth, parse_event_t::object_end, result))
9263  {
9264  result = basic_json(value_t::discarded);
9265  }
9266  return result;
9267  }
9268 
9269  // no comma is expected here
9270  unexpect(lexer::token_type::value_separator);
9271 
9272  // otherwise: parse key-value pairs
9273  do
9274  {
9275  // ugly, but could be fixed with loop reorganization
9276  if (last_token == lexer::token_type::value_separator)
9277  {
9278  get_token();
9279  }
9280 
9281  // store key
9282  expect(lexer::token_type::value_string);
9283  const auto key = m_lexer.get_string();
9284 
9285  bool keep_tag = false;
9286  if (keep)
9287  {
9288  if (callback)
9289  {
9290  basic_json k(key);
9291  keep_tag = callback(depth, parse_event_t::key, k);
9292  }
9293  else
9294  {
9295  keep_tag = true;
9296  }
9297  }
9298 
9299  // parse separator (:)
9300  get_token();
9301  expect(lexer::token_type::name_separator);
9302 
9303  // parse and add value
9304  get_token();
9305  auto value = parse_internal(keep);
9306  if (keep and keep_tag and not value.is_discarded())
9307  {
9308  result[key] = std::move(value);
9309  }
9310  }
9311  while (last_token == lexer::token_type::value_separator);
9312 
9313  // closing }
9314  expect(lexer::token_type::end_object);
9315  get_token();
9316  if (keep and callback and not callback(--depth, parse_event_t::object_end, result))
9317  {
9318  result = basic_json(value_t::discarded);
9319  }
9320 
9321  return result;
9322  }
9323 
9324  case lexer::token_type::begin_array:
9325  {
9326  if (keep and (not callback
9327  or ((keep = callback(depth++, parse_event_t::array_start, result)) != 0)))
9328  {
9329  // explicitly set result to object to cope with []
9330  result.m_type = value_t::array;
9331  result.m_value = value_t::array;
9332  }
9333 
9334  // read next token
9335  get_token();
9336 
9337  // closing ] -> we are done
9338  if (last_token == lexer::token_type::end_array)
9339  {
9340  get_token();
9341  if (callback and not callback(--depth, parse_event_t::array_end, result))
9342  {
9343  result = basic_json(value_t::discarded);
9344  }
9345  return result;
9346  }
9347 
9348  // no comma is expected here
9349  unexpect(lexer::token_type::value_separator);
9350 
9351  // otherwise: parse values
9352  do
9353  {
9354  // ugly, but could be fixed with loop reorganization
9355  if (last_token == lexer::token_type::value_separator)
9356  {
9357  get_token();
9358  }
9359 
9360  // parse value
9361  auto value = parse_internal(keep);
9362  if (keep and not value.is_discarded())
9363  {
9364  result.push_back(std::move(value));
9365  }
9366  }
9367  while (last_token == lexer::token_type::value_separator);
9368 
9369  // closing ]
9370  expect(lexer::token_type::end_array);
9371  get_token();
9372  if (keep and callback and not callback(--depth, parse_event_t::array_end, result))
9373  {
9374  result = basic_json(value_t::discarded);
9375  }
9376 
9377  return result;
9378  }
9379 
9380  case lexer::token_type::literal_null:
9381  {
9382  get_token();
9383  result.m_type = value_t::null;
9384  break;
9385  }
9386 
9387  case lexer::token_type::value_string:
9388  {
9389  const auto s = m_lexer.get_string();
9390  get_token();
9391  result = basic_json(s);
9392  break;
9393  }
9394 
9395  case lexer::token_type::literal_true:
9396  {
9397  get_token();
9398  result.m_type = value_t::boolean;
9399  result.m_value = true;
9400  break;
9401  }
9402 
9403  case lexer::token_type::literal_false:
9404  {
9405  get_token();
9406  result.m_type = value_t::boolean;
9407  result.m_value = false;
9408  break;
9409  }
9410 
9411  case lexer::token_type::value_number:
9412  {
9413  m_lexer.get_number(result);
9414  get_token();
9415  break;
9416  }
9417 
9418  default:
9419  {
9420  // the last token was unexpected
9421  unexpect(last_token);
9422  }
9423  }
9424 
9425  if (keep and callback and not callback(depth, parse_event_t::value, result))
9426  {
9427  result = basic_json(value_t::discarded);
9428  }
9429  return result;
9430  }
9431 
9433  typename lexer::token_type get_token()
9434  {
9435  last_token = m_lexer.scan();
9436  return last_token;
9437  }
9438 
9439  void expect(typename lexer::token_type t) const
9440  {
9441  if (t != last_token)
9442  {
9443  std::string error_msg = "parse error - unexpected ";
9444  error_msg += (last_token == lexer::token_type::parse_error ? ("'" + m_lexer.get_token_string() +
9445  "'") :
9446  lexer::token_type_name(last_token));
9447  error_msg += "; expected " + lexer::token_type_name(t);
9448  Throw<std::invalid_argument>(error_msg);
9449  }
9450  }
9451 
9452  void unexpect(typename lexer::token_type t) const
9453  {
9454  if (t == last_token)
9455  {
9456  std::string error_msg = "parse error - unexpected ";
9457  error_msg += (last_token == lexer::token_type::parse_error ? ("'" + m_lexer.get_token_string() +
9458  "'") :
9459  lexer::token_type_name(last_token));
9460  Throw<std::invalid_argument>(error_msg);
9461  }
9462  }
9463 
9464  private:
9466  int depth = 0;
9468  const parser_callback_t callback = nullptr;
9470  typename lexer::token_type last_token = lexer::token_type::uninitialized;
9472  lexer m_lexer;
9473  };
9474 
9475  public:
9488  {
9490  friend class basic_json;
9491 
9492  public:
9515  explicit json_pointer(const std::string& s = "")
9516  : reference_tokens(split(s))
9517  {}
9518 
9535  {
9536  return std::accumulate(reference_tokens.begin(),
9537  reference_tokens.end(), std::string{},
9538  [](const std::string & a, const std::string & b)
9539  {
9540  return a + "/" + escape(b);
9541  });
9542  }
9543 
9545  operator std::string() const
9546  {
9547  return to_string();
9548  }
9549 
9550  private:
9553  {
9554  if (is_root())
9555  {
9556  Throw<std::domain_error>("JSON pointer has no parent");
9557  }
9558 
9559  auto last = reference_tokens.back();
9560  reference_tokens.pop_back();
9561  return last;
9562  }
9563 
9565  bool is_root() const
9566  {
9567  return reference_tokens.empty();
9568  }
9569 
9570  json_pointer top() const
9571  {
9572  if (is_root())
9573  {
9574  Throw<std::domain_error>("JSON pointer has no parent");
9575  }
9576 
9577  json_pointer result = *this;
9578  result.reference_tokens = {reference_tokens[0]};
9579  return result;
9580  }
9581 
9587  reference get_and_create(reference j) const
9588  {
9589  pointer result = &j;
9590 
9591  // in case no reference tokens exist, return a reference to the
9592  // JSON value j which will be overwritten by a primitive value
9593  for (const auto& reference_token : reference_tokens)
9594  {
9595  switch (result->m_type)
9596  {
9597  case value_t::null:
9598  {
9599  if (reference_token == "0")
9600  {
9601  // start a new array if reference token is 0
9602  result = &result->operator[](0);
9603  }
9604  else
9605  {
9606  // start a new object otherwise
9607  result = &result->operator[](reference_token);
9608  }
9609  break;
9610  }
9611 
9612  case value_t::object:
9613  {
9614  // create an entry in the object
9615  result = &result->operator[](reference_token);
9616  break;
9617  }
9618 
9619  case value_t::array:
9620  {
9621  // create an entry in the array
9622  result = &result->operator[](static_cast<size_type>(std::stoi(reference_token)));
9623  break;
9624  }
9625 
9626  /*
9627  The following code is only reached if there exists a
9628  reference token _and_ the current value is primitive. In
9629  this case, we have an error situation, because primitive
9630  values may only occur as single value; that is, with an
9631  empty list of reference tokens.
9632  */
9633  default:
9634  {
9635  Throw<std::domain_error>("invalid value to unflatten");
9636  }
9637  }
9638  }
9639 
9640  return *result;
9641  }
9642 
9662  reference get_unchecked(pointer ptr) const
9663  {
9664  for (const auto& reference_token : reference_tokens)
9665  {
9666  // convert null values to arrays or objects before continuing
9667  if (ptr->m_type == value_t::null)
9668  {
9669  // check if reference token is a number
9670  const bool nums = std::all_of(reference_token.begin(),
9671  reference_token.end(),
9672  [](const char x)
9673  {
9674  return std::isdigit(x);
9675  });
9676 
9677  // change value to array for numbers or "-" or to object
9678  // otherwise
9679  if (nums or reference_token == "-")
9680  {
9681  *ptr = value_t::array;
9682  }
9683  else
9684  {
9685  *ptr = value_t::object;
9686  }
9687  }
9688 
9689  switch (ptr->m_type)
9690  {
9691  case value_t::object:
9692  {
9693  // use unchecked object access
9694  ptr = &ptr->operator[](reference_token);
9695  break;
9696  }
9697 
9698  case value_t::array:
9699  {
9700  // error condition (cf. RFC 6901, Sect. 4)
9701  if (reference_token.size() > 1 and reference_token[0] == '0')
9702  {
9703  Throw<std::domain_error>("array index must not begin with '0'");
9704  }
9705 
9706  if (reference_token == "-")
9707  {
9708  // explicityly treat "-" as index beyond the end
9709  ptr = &ptr->operator[](ptr->m_value.array->size());
9710  }
9711  else
9712  {
9713  // convert array index to number; unchecked access
9714  ptr = &ptr->operator[](static_cast<size_type>(std::stoi(reference_token)));
9715  }
9716  break;
9717  }
9718 
9719  default:
9720  {
9721  Throw<std::out_of_range>("unresolved reference token '" + reference_token + "'");
9722  }
9723  }
9724  }
9725 
9726  return *ptr;
9727  }
9728 
9729  reference get_checked(pointer ptr) const
9730  {
9731  for (const auto& reference_token : reference_tokens)
9732  {
9733  switch (ptr->m_type)
9734  {
9735  case value_t::object:
9736  {
9737  // note: at performs range check
9738  ptr = &ptr->at(reference_token);
9739  break;
9740  }
9741 
9742  case value_t::array:
9743  {
9744  if (reference_token == "-")
9745  {
9746  // "-" always fails the range check
9747  Throw<std::out_of_range>("array index '-' (" +
9748  std::to_string(ptr->m_value.array->size()) +
9749  ") is out of range");
9750  }
9751 
9752  // error condition (cf. RFC 6901, Sect. 4)
9753  if (reference_token.size() > 1 and reference_token[0] == '0')
9754  {
9755  Throw<std::domain_error>("array index must not begin with '0'");
9756  }
9757 
9758  // note: at performs range check
9759  ptr = &ptr->at(static_cast<size_type>(std::stoi(reference_token)));
9760  break;
9761  }
9762 
9763  default:
9764  {
9765  Throw<std::out_of_range>("unresolved reference token '" + reference_token + "'");
9766  }
9767  }
9768  }
9769 
9770  return *ptr;
9771  }
9772 
9781  const_reference get_unchecked(const_pointer ptr) const
9782  {
9783  for (const auto& reference_token : reference_tokens)
9784  {
9785  switch (ptr->m_type)
9786  {
9787  case value_t::object:
9788  {
9789  // use unchecked object access
9790  ptr = &ptr->operator[](reference_token);
9791  break;
9792  }
9793 
9794  case value_t::array:
9795  {
9796  if (reference_token == "-")
9797  {
9798  // "-" cannot be used for const access
9799  Throw<std::out_of_range>("array index '-' (" +
9800  std::to_string(ptr->m_value.array->size()) +
9801  ") is out of range");
9802  }
9803 
9804  // error condition (cf. RFC 6901, Sect. 4)
9805  if (reference_token.size() > 1 and reference_token[0] == '0')
9806  {
9807  Throw<std::domain_error>("array index must not begin with '0'");
9808  }
9809 
9810  // use unchecked array access
9811  ptr = &ptr->operator[](static_cast<size_type>(std::stoi(reference_token)));
9812  break;
9813  }
9814 
9815  default:
9816  {
9817  Throw<std::out_of_range>("unresolved reference token '" + reference_token + "'");
9818  }
9819  }
9820  }
9821 
9822  return *ptr;
9823  }
9824 
9825  const_reference get_checked(const_pointer ptr) const
9826  {
9827  for (const auto& reference_token : reference_tokens)
9828  {
9829  switch (ptr->m_type)
9830  {
9831  case value_t::object:
9832  {
9833  // note: at performs range check
9834  ptr = &ptr->at(reference_token);
9835  break;
9836  }
9837 
9838  case value_t::array:
9839  {
9840  if (reference_token == "-")
9841  {
9842  // "-" always fails the range check
9843  Throw<std::out_of_range>("array index '-' (" +
9844  std::to_string(ptr->m_value.array->size()) +
9845  ") is out of range");
9846  }
9847 
9848  // error condition (cf. RFC 6901, Sect. 4)
9849  if (reference_token.size() > 1 and reference_token[0] == '0')
9850  {
9851  Throw<std::domain_error>("array index must not begin with '0'");
9852  }
9853 
9854  // note: at performs range check
9855  ptr = &ptr->at(static_cast<size_type>(std::stoi(reference_token)));
9856  break;
9857  }
9858 
9859  default:
9860  {
9861  Throw<std::out_of_range>("unresolved reference token '" + reference_token + "'");
9862  }
9863  }
9864  }
9865 
9866  return *ptr;
9867  }
9868 
9870  static std::vector<std::string> split(const std::string& reference_string)
9871  {
9872  std::vector<std::string> result;
9873 
9874  // special case: empty reference string -> no reference tokens
9875  if (reference_string.empty())
9876  {
9877  return result;
9878  }
9879 
9880  // check if nonempty reference string begins with slash
9881  if (reference_string[0] != '/')
9882  {
9883  Throw<std::domain_error>("JSON pointer must be empty or begin with '/'");
9884  }
9885 
9886  // extract the reference tokens:
9887  // - slash: position of the last read slash (or end of string)
9888  // - start: position after the previous slash
9889  for (
9890  // search for the first slash after the first character
9891  size_t slash = reference_string.find_first_of("/", 1),
9892  // set the beginning of the first reference token
9893  start = 1;
9894  // we can stop if start == string::npos+1 = 0
9895  start != 0;
9896  // set the beginning of the next reference token
9897  // (will eventually be 0 if slash == std::string::npos)
9898  start = slash + 1,
9899  // find next slash
9900  slash = reference_string.find_first_of("/", start))
9901  {
9902  // use the text between the beginning of the reference token
9903  // (start) and the last slash (slash).
9904  auto reference_token = reference_string.substr(start, slash - start);
9905 
9906  // check reference tokens are properly escaped
9907  for (size_t pos = reference_token.find_first_of("~");
9908  pos != std::string::npos;
9909  pos = reference_token.find_first_of("~", pos + 1))
9910  {
9911  assert(reference_token[pos] == '~');
9912 
9913  // ~ must be followed by 0 or 1
9914  if (pos == reference_token.size() - 1 or
9915  (reference_token[pos + 1] != '0' and
9916  reference_token[pos + 1] != '1'))
9917  {
9918  Throw<std::domain_error>("escape error: '~' must be followed with '0' or '1'");
9919  }
9920  }
9921 
9922  // finally, store the reference token
9923  unescape(reference_token);
9924  result.push_back(reference_token);
9925  }
9926 
9927  return result;
9928  }
9929 
9930  private:
9945  static void replace_substring(std::string& s,
9946  const std::string& f,
9947  const std::string& t)
9948  {
9949  assert(not f.empty());
9950 
9951  for (
9952  size_t pos = s.find(f); // find first occurrence of f
9953  pos != std::string::npos; // make sure f was found
9954  s.replace(pos, f.size(), t), // replace with t
9955  pos = s.find(f, pos + t.size()) // find next occurrence of f
9956  );
9957  }
9958 
9960  static std::string escape(std::string s)
9961  {
9962  // escape "~"" to "~0" and "/" to "~1"
9963  replace_substring(s, "~", "~0");
9964  replace_substring(s, "/", "~1");
9965  return s;
9966  }
9967 
9969  static void unescape(std::string& s)
9970  {
9971  // first transform any occurrence of the sequence '~1' to '/'
9972  replace_substring(s, "~1", "/");
9973  // then transform any occurrence of the sequence '~0' to '~'
9974  replace_substring(s, "~0", "~");
9975  }
9976 
9984  static void flatten(const std::string& reference_string,
9985  const basic_json& value,
9986  basic_json& result)
9987  {
9988  switch (value.m_type)
9989  {
9990  case value_t::array:
9991  {
9992  if (value.m_value.array->empty())
9993  {
9994  // flatten empty array as null
9995  result[reference_string] = nullptr;
9996  }
9997  else
9998  {
9999  // iterate array and use index as reference string
10000  for (size_t i = 0; i < value.m_value.array->size(); ++i)
10001  {
10002  flatten(reference_string + "/" + std::to_string(i),
10003  value.m_value.array->operator[](i), result);
10004  }
10005  }
10006  break;
10007  }
10008 
10009  case value_t::object:
10010  {
10011  if (value.m_value.object->empty())
10012  {
10013  // flatten empty object as null
10014  result[reference_string] = nullptr;
10015  }
10016  else
10017  {
10018  // iterate object and use keys as reference string
10019  for (const auto& element : *value.m_value.object)
10020  {
10021  flatten(reference_string + "/" + escape(element.first),
10022  element.second, result);
10023  }
10024  }
10025  break;
10026  }
10027 
10028  default:
10029  {
10030  // add primitive value with its reference string
10031  result[reference_string] = value;
10032  break;
10033  }
10034  }
10035  }
10036 
10042  static basic_json unflatten(const basic_json& value)
10043  {
10044  if (not value.is_object())
10045  {
10046  Throw<std::domain_error>("only objects can be unflattened");
10047  }
10048 
10050 
10051  // iterate the JSON object values
10052  for (const auto& element : *value.m_value.object)
10053  {
10054  if (not element.second.is_primitive())
10055  {
10056  Throw<std::domain_error>("values in object must be primitive");
10057  }
10058 
10059  // assign value to reference pointed to by JSON pointer; Note
10060  // that if the JSON pointer is "" (i.e., points to the whole
10061  // value), function get_and_create returns a reference to
10062  // result itself. An assignment will then create a primitive
10063  // value.
10064  json_pointer(element.first).get_and_create(result) = element.second;
10065  }
10066 
10067  return result;
10068  }
10069 
10070  private:
10072  std::vector<std::string> reference_tokens {};
10073  };
10074 
10076  // JSON Pointer support //
10078 
10081 
10116  {
10117  return ptr.get_unchecked(this);
10118  }
10119 
10143  {
10144  return ptr.get_unchecked(this);
10145  }
10146 
10168  {
10169  return ptr.get_checked(this);
10170  }
10171 
10192  const_reference at(const json_pointer& ptr) const
10193  {
10194  return ptr.get_checked(this);
10195  }
10196 
10220  {
10222  json_pointer::flatten("", *this, result);
10223  return result;
10224  }
10225 
10254  {
10255  return json_pointer::unflatten(*this);
10256  }
10257 
10259 
10261  // JSON Patch functions //
10263 
10266 
10303  basic_json patch(const basic_json& json_patch) const
10304  {
10305  // make a working copy to apply the patch to
10306  basic_json result = *this;
10307 
10308  // the valid JSON Patch operations
10309  enum class patch_operations {add, remove, replace, move, copy, test, invalid};
10310 
10311  const auto get_op = [](const std::string op)
10312  {
10313  if (op == "add")
10314  {
10315  return patch_operations::add;
10316  }
10317  if (op == "remove")
10318  {
10319  return patch_operations::remove;
10320  }
10321  if (op == "replace")
10322  {
10324  }
10325  if (op == "move")
10326  {
10327  return patch_operations::move;
10328  }
10329  if (op == "copy")
10330  {
10331  return patch_operations::copy;
10332  }
10333  if (op == "test")
10334  {
10335  return patch_operations::test;
10336  }
10337 
10339  };
10340 
10341  // wrapper for "add" operation; add value at ptr
10342  const auto operation_add = [&result](json_pointer & ptr, basic_json val)
10343  {
10344  // adding to the root of the target document means replacing it
10345  if (ptr.is_root())
10346  {
10347  result = val;
10348  }
10349  else
10350  {
10351  // make sure the top element of the pointer exists
10352  json_pointer top_pointer = ptr.top();
10353  if (top_pointer != ptr)
10354  {
10355  result.at(top_pointer);
10356  }
10357 
10358  // get reference to parent of JSON pointer ptr
10359  const auto last_path = ptr.pop_back();
10360  basic_json& parent = result[ptr];
10361 
10362  switch (parent.m_type)
10363  {
10364  case value_t::null:
10365  case value_t::object:
10366  {
10367  // use operator[] to add value
10368  parent[last_path] = val;
10369  break;
10370  }
10371 
10372  case value_t::array:
10373  {
10374  if (last_path == "-")
10375  {
10376  // special case: append to back
10377  parent.push_back(val);
10378  }
10379  else
10380  {
10381  const auto idx = std::stoi(last_path);
10382  if (static_cast<size_type>(idx) > parent.size())
10383  {
10384  // avoid undefined behavior
10385  Throw<std::out_of_range>("array index " + std::to_string(idx) + " is out of range");
10386  }
10387  else
10388  {
10389  // default case: insert add offset
10390  parent.insert(parent.begin() + static_cast<difference_type>(idx), val);
10391  }
10392  }
10393  break;
10394  }
10395 
10396  default:
10397  {
10398  // if there exists a parent it cannot be primitive
10399  assert(false); // LCOV_EXCL_LINE
10400  }
10401  }
10402  }
10403  };
10404 
10405  // wrapper for "remove" operation; remove value at ptr
10406  const auto operation_remove = [&result](json_pointer & ptr)
10407  {
10408  // get reference to parent of JSON pointer ptr
10409  const auto last_path = ptr.pop_back();
10410  basic_json& parent = result.at(ptr);
10411 
10412  // remove child
10413  if (parent.is_object())
10414  {
10415  // perform range check
10416  auto it = parent.find(last_path);
10417  if (it != parent.end())
10418  {
10419  parent.erase(it);
10420  }
10421  else
10422  {
10423  Throw<std::out_of_range>("key '" + last_path + "' not found");
10424  }
10425  }
10426  else if (parent.is_array())
10427  {
10428  // note erase performs range check
10429  parent.erase(static_cast<size_type>(std::stoi(last_path)));
10430  }
10431  };
10432 
10433  // type check
10434  if (not json_patch.is_array())
10435  {
10436  // a JSON patch must be an array of objects
10437  Throw<std::invalid_argument>("JSON patch must be an array of objects");
10438  }
10439 
10440  // iterate and apply th eoperations
10441  for (const auto& val : json_patch)
10442  {
10443  // wrapper to get a value for an operation
10444  const auto get_value = [&val](const std::string & op,
10445  const std::string & member,
10446  bool string_type) -> basic_json&
10447  {
10448  // find value
10449  auto it = val.m_value.object->find(member);
10450 
10451  // context-sensitive error message
10452  const auto error_msg = (op == "op") ? "operation" : "operation '" + op + "'";
10453 
10454  // check if desired value is present
10455  if (it == val.m_value.object->end())
10456  {
10457  Throw<std::invalid_argument>(error_msg + " must have member '" + member + "'");
10458  }
10459 
10460  // check if result is of type string
10461  if (string_type and not it->second.is_string())
10462  {
10463  Throw<std::invalid_argument>(error_msg + " must have string member '" + member + "'");
10464  }
10465 
10466  // no error: return value
10467  return it->second;
10468  };
10469 
10470  // type check
10471  if (not val.is_object())
10472  {
10473  Throw<std::invalid_argument>("JSON patch must be an array of objects");
10474  }
10475 
10476  // collect mandatory members
10477  const std::string op = get_value("op", "op", true);
10478  const std::string path = get_value(op, "path", true);
10479  json_pointer ptr(path);
10480 
10481  switch (get_op(op))
10482  {
10483  case patch_operations::add:
10484  {
10485  operation_add(ptr, get_value("add", "value", false));
10486  break;
10487  }
10488 
10490  {
10491  operation_remove(ptr);
10492  break;
10493  }
10494 
10496  {
10497  // the "path" location must exist - use at()
10498  result.at(ptr) = get_value("replace", "value", false);
10499  break;
10500  }
10501 
10503  {
10504  const std::string from_path = get_value("move", "from", true);
10505  json_pointer from_ptr(from_path);
10506 
10507  // the "from" location must exist - use at()
10508  basic_json v = result.at(from_ptr);
10509 
10510  // The move operation is functionally identical to a
10511  // "remove" operation on the "from" location, followed
10512  // immediately by an "add" operation at the target
10513  // location with the value that was just removed.
10514  operation_remove(from_ptr);
10515  operation_add(ptr, v);
10516  break;
10517  }
10518 
10520  {
10521  const std::string from_path = get_value("copy", "from", true);;
10522  const json_pointer from_ptr(from_path);
10523 
10524  // the "from" location must exist - use at()
10525  result[ptr] = result.at(from_ptr);
10526  break;
10527  }
10528 
10530  {
10531  // check if "value" matches the one at "path"
10532  // the "path" location must exist - use at()
10533  bool success = (result.at(ptr) == get_value("test", "value", false));
10534 
10535  // throw an exception if test fails
10536  if (not success)
10537  {
10538  Throw<std::domain_error>("unsuccessful: " + val.dump());
10539  }
10540 
10541  break;
10542  }
10543 
10545  {
10546  // op must be "add", "remove", "replace", "move", "copy", or
10547  // "test"
10548  Throw<std::invalid_argument>("operation value '" + op + "' is invalid");
10549  }
10550  }
10551  }
10552 
10553  return result;
10554  }
10555 
10589  const basic_json& target,
10590  const std::string& path = "")
10591  {
10592  // the patch
10594 
10595  // if the values are the same, return empty patch
10596  if (source == target)
10597  {
10598  return result;
10599  }
10600 
10601  if (source.type() != target.type())
10602  {
10603  // different types: replace value
10604  result.push_back(
10605  {
10606  {"op", "replace"},
10607  {"path", path},
10608  {"value", target}
10609  });
10610  }
10611  else
10612  {
10613  switch (source.type())
10614  {
10615  case value_t::array:
10616  {
10617  // first pass: traverse common elements
10618  size_t i = 0;
10619  while (i < source.size() and i < target.size())
10620  {
10621  // recursive call to compare array values at index i
10622  auto temp_diff = diff(source[i], target[i], path + "/" + std::to_string(i));
10623  result.insert(result.end(), temp_diff.begin(), temp_diff.end());
10624  ++i;
10625  }
10626 
10627  // i now reached the end of at least one array
10628  // in a second pass, traverse the remaining elements
10629 
10630  // remove my remaining elements
10631  const auto end_index = static_cast<difference_type>(result.size());
10632  while (i < source.size())
10633  {
10634  // add operations in reverse order to avoid invalid
10635  // indices
10636  result.insert(result.begin() + end_index, object(
10637  {
10638  {"op", "remove"},
10639  {"path", path + "/" + std::to_string(i)}
10640  }));
10641  ++i;
10642  }
10643 
10644  // add other remaining elements
10645  while (i < target.size())
10646  {
10647  result.push_back(
10648  {
10649  {"op", "add"},
10650  {"path", path + "/" + std::to_string(i)},
10651  {"value", target[i]}
10652  });
10653  ++i;
10654  }
10655 
10656  break;
10657  }
10658 
10659  case value_t::object:
10660  {
10661  // first pass: traverse this object's elements
10662  for (auto it = source.begin(); it != source.end(); ++it)
10663  {
10664  // escape the key name to be used in a JSON patch
10665  const auto key = json_pointer::escape(it.key());
10666 
10667  if (target.find(it.key()) != target.end())
10668  {
10669  // recursive call to compare object values at key it
10670  auto temp_diff = diff(it.value(), target[it.key()], path + "/" + key);
10671  result.insert(result.end(), temp_diff.begin(), temp_diff.end());
10672  }
10673  else
10674  {
10675  // found a key that is not in o -> remove it
10676  result.push_back(object(
10677  {
10678  {"op", "remove"},
10679  {"path", path + "/" + key}
10680  }));
10681  }
10682  }
10683 
10684  // second pass: traverse other object's elements
10685  for (auto it = target.begin(); it != target.end(); ++it)
10686  {
10687  if (source.find(it.key()) == source.end())
10688  {
10689  // found a key that is not in this -> add it
10690  const auto key = json_pointer::escape(it.key());
10691  result.push_back(
10692  {
10693  {"op", "add"},
10694  {"path", path + "/" + key},
10695  {"value", it.value()}
10696  });
10697  }
10698  }
10699 
10700  break;
10701  }
10702 
10703  default:
10704  {
10705  // both primitive type: replace value
10706  result.push_back(
10707  {
10708  {"op", "replace"},
10709  {"path", path},
10710  {"value", target}
10711  });
10712  break;
10713  }
10714  }
10715  }
10716 
10717  return result;
10718  }
10719 
10721 };
10722 
10723 
10725 // presets //
10727 
10737 }
10738 
10739 
10741 // nonmember support //
10743 
10744 // specialization of std::swap, and std::hash
10745 namespace std
10746 {
10752 template<>
10753 inline void swap(nlohmann::json& j1,
10754  nlohmann::json& j2) noexcept(
10755  is_nothrow_move_constructible<nlohmann::json>::value and
10756  is_nothrow_move_assignable<nlohmann::json>::value
10757  )
10758 {
10759  j1.swap(j2);
10760 }
10761 
10763 template<>
10765 {
10772  {
10773  // a naive hashing via the string representation
10774  const auto& h = hash<nlohmann::json::string_t>();
10775  return h(j.dump());
10776  }
10777 };
10778 }
10779 
10793 inline nlohmann::json operator "" _json(const char* s, std::size_t n)
10794 {
10795  return nlohmann::json::parse(s, s + n);
10796 }
10797 
10811 inline nlohmann::json::json_pointer operator "" _json_pointer(const char* s, std::size_t n)
10812 {
10814 }
10815 
10816 // restore GCC/clang diagnostic settings
10817 #if defined(__clang__) || defined(__GNUC__) || defined(__GNUG__)
10818  #pragma GCC diagnostic pop
10819 #endif
10820 
10821 #endif
const_iterator & operator+=(difference_type i)
add to iterator
Definition: json.hpp:7174
difference_type operator-(const json_reverse_iterator &other) const
return difference
Definition: json.hpp:7553
iterator operator++(int)
post-increment (it++)
Definition: json.hpp:7389
while not(ended) signal
reference at(const typename object_t::key_type &key)
access specified object element with bounds checking
Definition: json.hpp:3270
iterator & operator+=(difference_type i)
add to iterator
Definition: json.hpp:7419
json_reverse_iterator & operator--()
pre-decrement (–it)
Definition: json.hpp:7523
void swap(string_t &other)
exchanges the values
Definition: json.hpp:5387
GLint GLsizei count
Definition: gl2.h:421
const_iterator end() const noexcept
returns a const iterator to one past the last element
Definition: json.hpp:4391
size_type max_size() const noexcept
returns the maximum possible number of elements
Definition: json.hpp:4769
reference & operator=(basic_json other) noexcept(std::is_nothrow_move_constructible< value_t >::value and std::is_nothrow_move_assignable< value_t >::value and std::is_nothrow_move_constructible< json_value >::value and std::is_nothrow_move_assignable< json_value >::value)
copy assignment
Definition: json.hpp:2137
const value_type & const_reference
the type of an element const reference
Definition: json.hpp:299
bool operator<(const const_iterator &other) const
comparison: smaller
Definition: json.hpp:7114
iterator insert(const_iterator pos, const_iterator first, const_iterator last)
inserts elements
Definition: json.hpp:5194
typename basic_json::difference_type difference_type
a type to represent differences between iterators
Definition: json.hpp:6733
std::bidirectional_iterator_tag iterator_category
the category of the iterator
Definition: json.hpp:6739
#define size
Definition: float-mm.c:27
unsigned long long uint64_t
Definition: ptypes.h:120
constexpr bool is_structured() const noexcept
return whether type is structured
Definition: json.hpp:2341
json_reverse_iterator operator--(int)
post-decrement (it–)
Definition: json.hpp:7517
GLsizei GLsizei GLchar * source
Definition: gl2.h:451
iterator insert(const_iterator pos, const basic_json &val)
inserts element
Definition: json.hpp:5087
const_iterator & operator=(const_iterator other) noexcept(std::is_nothrow_move_constructible< pointer >::value and std::is_nothrow_move_assignable< pointer >::value and std::is_nothrow_move_constructible< internal_iterator >::value and std::is_nothrow_move_assignable< internal_iterator >::value)
copy assignment
Definition: json.hpp:6824
json_reverse_iterator operator+(difference_type i) const
add to iterator
Definition: json.hpp:7537
friend bool operator<(const_reference lhs, const_reference rhs) noexcept
comparison: less than
Definition: json.hpp:5651
GLint first
Definition: gl2.h:421
required HashAlgorithmIdentifier hash
Definition: WebCryptoAPI.idl:276
FloatPoint & operator+=(FloatPoint &a, const FloatSize &b)
Definition: FloatPoint.h:184
std::vector< TraceArg > args
Definition: event_tracer.cc:256
std::ptrdiff_t difference_type
a type to represent differences between iterators
Definition: json.hpp:302
ALWAYS_INLINE constexpr remove_reference< T >::type && move(T &&value)
Definition: StdLibExtras.h:464
json_reverse_iterator(const base_iterator &it) noexcept
create reverse iterator from base class
Definition: json.hpp:7499
front< split_at< L, std::integral_constant< std::size_t, size< L >::value - N::value > >> pop_back
Definition: Brigand.h:674
iterator & operator--()
pre-decrement (–it)
Definition: json.hpp:7412
object_t::key_type key() const
return the key of an object iterator
Definition: json.hpp:7302
const_iterator(pointer object) noexcept
constructor for a given JSON instance
Definition: json.hpp:6750
int c
Definition: cpp_unittests.cpp:275
constexpr bool is_primitive() const noexcept
return whether type is primitive
Definition: json.hpp:2314
OPENSSL_EXPORT pem_password_cb * cb
Definition: pem.h:398
bool operator>=(const const_iterator &other) const
comparison: greater than or equal
Definition: json.hpp:7165
GLuint GLuint end
Definition: gl2ext.h:323
FloatPoint & operator-=(FloatPoint &a, const FloatSize &b)
Definition: FloatPoint.h:196
static basic_json parse(T(&array)[N], const parser_callback_t cb=nullptr)
deserialize from an array
Definition: json.hpp:5906
AllocatorType< basic_json > allocator_type
the allocator type
Definition: json.hpp:307
void push_back(const basic_json &val)
add an object to an array
Definition: json.hpp:4937
basic_json(const number_float_t val) noexcept
create a floating-point number (explicit)
Definition: json.hpp:1557
ResourceLoadPriority & operator--(ResourceLoadPriority &priority)
Definition: ResourceLoadPriority.h:49
IteratorType erase(IteratorType first, IteratorType last)
remove elements given an iterator range
Definition: json.hpp:4053
const_reference operator[](const typename object_t::key_type &key) const
read-only access specified object element
Definition: json.hpp:3490
const_iterator cend() const noexcept
returns a const iterator to one past the last element
Definition: json.hpp:4421
ValueType get() const
get a value (explicit)
Definition: json.hpp:2942
rtc::KeyType key_type
Definition: peerconnection_jni.cc:1854
a class to store JSON values
Definition: json.hpp:271
typename detail::push_back_impl< L, T... >::type push_back
Definition: Brigand.h:670
basic_json(const CompatibleStringType &val)
create a string (implicit)
Definition: json.hpp:1348
basic_json unflatten() const
unflatten a previously flattened JSON value
Definition: json.hpp:10253
basic_json(InputIT first, InputIT last)
construct a JSON container given an iterator range
Definition: json.hpp:1873
Functor for_each(Functor f)
Definition: Brigand.h:1335
typename detail::make_map< Ts... >::type map
Definition: Brigand.h:223
constexpr bool is_discarded() const noexcept
return whether value is discarded
Definition: json.hpp:2593
typename detail::transform< sizeof...(OpSeq2), Sequence1, OpSeq1, OpSeq2... >::type transform
Definition: Brigand.h:757
TimeDelta operator*(T a, TimeDelta td)
Definition: timedelta.h:123
constexpr const PointerType get_ptr() const noexcept
get a pointer value (implicit)
Definition: json.hpp:3050
reference value() const
return the value of an iterator
Definition: json.hpp:7320
EGLContext EGLenum target
Definition: eglext.h:192
ReferenceType get_ref() const
get a reference value (implicit)
Definition: json.hpp:3112
AVCFAssetRef CFArrayRef AVCFAssetLoadValuesCompletionCallback callback
Definition: AVFoundationCFSoftLinking.h:99
friend std::ostream & operator<<(std::ostream &o, const basic_json &j)
serialize to stream
Definition: json.hpp:5831
reference value() const
return the value of an iterator
Definition: json.hpp:7572
bool t
Definition: UpdateContents.py:37
constexpr bool is_number_unsigned() const noexcept
return whether value is an unsigned integer number
Definition: json.hpp:2472
iterator(pointer object) noexcept
constructor for a given JSON instance
Definition: json.hpp:7355
path
Definition: generate.py:74
a mutable random access iterator for the basic_json class
Definition: json.hpp:7344
void swap(nlohmann::json &j1, nlohmann::json &j2) noexcept(is_nothrow_move_constructible< nlohmann::json >::value and is_nothrow_move_assignable< nlohmann::json >::value)
exchanges the values of two JSON objects
Definition: json.hpp:10753
constexpr bool is_object() const noexcept
return whether value is an object
Definition: json.hpp:2522
isnan(s.arrival find()
PointerType get_ptr() noexcept
get a pointer value (implicit)
Definition: json.hpp:3022
double U(int64_t x, double alpha)
Definition: metric_recorder.cc:414
std::unique_ptr< Layout > create(RenderBlockFlow &)
Definition: SimpleLineLayout.cpp:861
Definition: videoengine_unittest.h:62
iterator & operator-=(difference_type i)
subtract from iterator
Definition: json.hpp:7426
const_iterator & operator-=(difference_type i)
subtract from iterator
Definition: json.hpp:7205
basic_json(std::nullptr_t=nullptr) noexcept
create a null object
Definition: json.hpp:1127
const GLfloat * m
Definition: gl2ext.h:850
reference at(const json_pointer &ptr)
access specified element via JSON Pointer
Definition: json.hpp:10167
size_type size() const noexcept
returns the number of elements
Definition: json.hpp:4703
replace_if< Sequence, std::is_same< _1, pin< OldType > >, NewType > replace
Definition: Brigand.h:1632
static allocator_type get_allocator()
returns the allocator associated with the container
Definition: json.hpp:329
constexpr bool is_array() const noexcept
return whether value is an array
Definition: json.hpp:2544
const_iterator operator-(difference_type i)
subtract from iterator
Definition: json.hpp:7225
basic_json(const CompatibleObjectType &val)
create an object (implicit)
Definition: json.hpp:1187
function[delay_struct, delayvalues]
Definition: plot_neteq_delay.m:1
basic_json(const CompatibleNumberFloatType val) noexcept
create an floating-point number (implicit)
Definition: json.hpp:1604
CFArrayRef array
Definition: AVFoundationCFSoftLinking.h:129
friend bool operator==(const_reference v, std::nullptr_t) noexcept
comparison: equal
Definition: json.hpp:5560
size_t escape(char *buffer, size_t buflen, const char *source, size_t srclen, const char *illegal, char escape)
Definition: stringencode.cc:25
std::integral_constant< std::int64_t, V > int64_t
Definition: Brigand.h:443
const_reference operator[](const json_pointer &ptr) const
access specified element via JSON Pointer
Definition: json.hpp:10142
basic_json(const typename string_t::value_type *val, typename string_t::size_type count)
Definition: json.hpp:1317
std::integral_constant< std::size_t, V > size_t
Definition: Brigand.h:447
OPENSSL_EXPORT const ASN1_OBJECT * obj
Definition: x509.h:1053
std::integral_constant< std::uint64_t, V > uint64_t
Definition: Brigand.h:445
ObjectType
Definition: ObjectType.h:34
reference operator+=(std::initializer_list< basic_json > init)
add an object to an object
Definition: json.hpp:5059
iterator end() noexcept
returns an iterator to one past the last element
Definition: json.hpp:4381
const_iterator operator--(int)
post-decrement (it–)
Definition: json.hpp:7029
basic_json(const int val) noexcept
create an integer number from an enum type (explicit)
Definition: json.hpp:1431
basic_json(const CompatibleArrayType &val)
create an array (implicit)
Definition: json.hpp:1255
reference operator*() const
return a reference to the value pointed to by the iterator
Definition: json.hpp:7377
reference back()
access the last element
Definition: json.hpp:3880
reverse_iterator rend() noexcept
returns an iterator to the reverse-end
Definition: json.hpp:4488
json_reverse_iterator(const typename base_iterator::iterator_type &it) noexcept
create reverse iterator from iterator
Definition: json.hpp:7494
const UChar space
Definition: CharacterNames.h:87
static basic_json object(std::initializer_list< basic_json > init=std::initializer_list< basic_json >())
explicitly create an object from an initializer list
Definition: json.hpp:1802
bool operator!=(const Handle< T > &a, const Handle< U > &b)
Definition: Handle.h:159
friend class basic_json
allow basic_json to access private members
Definition: json.hpp:6727
reference operator+=(const basic_json &val)
add an object to an array
Definition: json.hpp:4961
static iteration_proxy< const_iterator > iterator_wrapper(const_reference cont)
wrapper to access iterator member functions in range-based for
Definition: json.hpp:4583
NumberFloatType number_float_t
a type for a number (floating-point)
Definition: json.hpp:761
static basic_json parse(std::istream &&i, const parser_callback_t cb=nullptr)
deserialize from stream
Definition: json.hpp:5983
Definition: float-mm.c:54
Definition: base64_test.cc:36
WEBCORE_EXPORT Node * last(const ContainerNode &)
Definition: NodeTraversal.cpp:106
typename basic_json::const_pointer pointer
defines a pointer to the type iterated over (value_type)
Definition: json.hpp:6735
basic_json(const value_t value_type)
create an empty value with a given type
Definition: json.hpp:1103
size_type count(typename object_t::key_type key) const
returns the number of occurrences of a key in a JSON object
Definition: json.hpp:4270
GLuint start
Definition: gl2ext.h:323
bool operator!=(const const_iterator &other) const
comparison: not equal
Definition: json.hpp:7105
static basic_json parse(const ContiguousContainer &c, const parser_callback_t cb=nullptr)
deserialize from a container with contiguous storage
Definition: json.hpp:6106
EGLStreamKHR EGLint n
Definition: eglext.h:984
json_reverse_iterator & operator+=(difference_type i)
add to iterator
Definition: json.hpp:7530
const_reverse_iterator rend() const noexcept
returns a const reverse iterator to one before the first
Definition: json.hpp:4496
bool operator>(const const_iterator &other) const
comparison: greater than
Definition: json.hpp:7156
EGLSetBlobFuncANDROID EGLGetBlobFuncANDROID get
Definition: eglext.h:426
static basic_json parse(const CharPT s, const parser_callback_t cb=nullptr)
deserialize from string literal
Definition: json.hpp:5944
const_reference at(const typename object_t::key_type &key) const
access specified object element with bounds checking
Definition: json.hpp:3311
basic_json(const object_t &val)
create an object (explicit)
Definition: json.hpp:1152
#define JSON_DEPRECATED
Definition: json.hpp:130
reverse_iterator rbegin() noexcept
returns an iterator to the reverse-beginning
Definition: json.hpp:4451
basic_json(const string_t &val)
create a string (explicit)
Definition: json.hpp:1285
WTF_EXPORT_PRIVATE NO_RETURN_DUE_TO_CRASH void WTFCrash()
Definition: Assertions.cpp:317
int top
Definition: float-mm.c:109
OPENSSL_EXPORT const ASN1_OBJECT int const unsigned char int len
Definition: x509.h:1053
DOMString k
Definition: WebCryptoAPI.idl:122
TestSubObjConstructor T
Definition: TestTypedefs.idl:84
reference operator[](difference_type n) const
access to successor
Definition: json.hpp:7455
iterator find(typename object_t::key_type key)
find an element in a JSON object
Definition: json.hpp:4224
constexpr bool is_number() const noexcept
return whether value is a number
Definition: json.hpp:2415
void dump()
Definition: DumpRenderTree.mm:1676
EGLSurface EGLint x
Definition: eglext.h:950
#define isfinite
Definition: jsoncpp.cpp:4014
void swap(object_t &other)
exchanges the values
Definition: json.hpp:5354
BooleanType boolean_t
a type for a boolean
Definition: json.hpp:550
const_reference operator[](T *key) const
read-only access specified object element
Definition: json.hpp:3652
Definition: interfaces.idl:172
reference operator[](T *(&key)[n])
access specified object element
Definition: json.hpp:3532
pointer operator->() const
dereference the iterator
Definition: json.hpp:7383
const_iterator(const iterator &other) noexcept
copy constructor given a non-const iterator
Definition: json.hpp:6782
EGLAttrib * value
Definition: eglext.h:120
json_reverse_iterator & operator++()
pre-increment (++it)
Definition: json.hpp:7510
namespace for Niels Lohmann
Definition: json.hpp:138
parse_event_t
JSON callback events.
Definition: json.hpp:982
constexpr value_t type() const noexcept
return the type of the JSON value (explicit)
Definition: json.hpp:2284
unsigned char uint8_t
Definition: ptypes.h:89
Definition: RTCStatsReport.idl:41
basic_json(size_type cnt, const basic_json &val)
construct an array with count copies of given value
Definition: json.hpp:1826
size_t unescape(char *buffer, size_t buflen, const char *source, size_t srclen, char escape)
Definition: stringencode.cc:47
const_reverse_iterator crend() const noexcept
returns a const reverse iterator to one before the first
Definition: json.hpp:4554
const_reference operator[](T *(&key)[n]) const
read-only access specified object element
Definition: json.hpp:3567
std::function< bool(int depth, parse_event_t event, basic_json &parsed)> parser_callback_t
per-element parser callback type
Definition: json.hpp:1052
typename detail::flatten_impl< Sequence > flatten
Definition: Brigand.h:1120
const_iterator & operator--()
pre-decrement (–it)
Definition: json.hpp:7040
constexpr bool is_string() const noexcept
return whether value is a string
Definition: json.hpp:2566
void advance(int nbodies, struct planet *bodies, double dt)
Definition: n-body.c:23
ValueType
Definition: WebKitPluginHostTypes.h:51
difference_type operator-(const iterator &other) const
return difference
Definition: json.hpp:7449
basic_json value_type
the type of elements in a basic_json container
Definition: json.hpp:294
basic_json(boolean_t val) noexcept
create a boolean (explicit)
Definition: json.hpp:1368
std::string to_string() const noexcept
return a string representation of the JSON pointer
Definition: json.hpp:9534
basic_json(basic_json &&other) noexcept
move constructor
Definition: json.hpp:2100
static basic_json array(std::initializer_list< basic_json > init=std::initializer_list< basic_json >())
explicitly create an array from an initializer list
Definition: json.hpp:1762
void test(int32_t count, function< MediaTime(int32_t)> generator)
Definition: main.cpp:57
friend std::istream & operator>>(std::istream &i, basic_json &j)
deserialize from stream
Definition: json.hpp:6146
basic_json(const typename string_t::value_type *val)
create a string (explicit)
Definition: json.hpp:1311
friend bool operator==(const_reference lhs, const_reference rhs) noexcept
comparison: equal
Definition: json.hpp:5467
JSON Pointer.
Definition: json.hpp:9487
friend std::ostream & operator>>(const basic_json &j, std::ostream &o)
serialize to stream
Definition: json.hpp:5863
friend std::istream & operator<<(basic_json &j, std::istream &i)
deserialize from stream
Definition: json.hpp:6136
ValueType value(const typename object_t::key_type &key, ValueType default_value) const
access specified object element with default value
Definition: json.hpp:3716
void swap(reference other) noexcept(std::is_nothrow_move_constructible< value_t >::value and std::is_nothrow_move_assignable< value_t >::value and std::is_nothrow_move_constructible< json_value >::value and std::is_nothrow_move_assignable< json_value >::value)
exchanges the values
Definition: json.hpp:5289
reference operator[](difference_type n) const
access to successor
Definition: json.hpp:7559
reference operator+=(const typename object_t::value_type &val)
add an object to an object
Definition: json.hpp:5011
std::size_t size_type
a type to represent container sizes
Definition: json.hpp:304
static iteration_proxy< iterator > iterator_wrapper(reference cont)
wrapper to access iterator member functions in range-based for
Definition: json.hpp:4575
reference operator+=(basic_json &&val)
add an object to an array
Definition: json.hpp:4927
reference operator[](size_type idx)
access specified array element
Definition: json.hpp:3351
const_iterator begin() const noexcept
returns a const iterator to the first element
Definition: json.hpp:4320
friend bool operator!=(const_reference v, std::nullptr_t) noexcept
comparison: not equal
Definition: json.hpp:5613
typename basic_json::value_type value_type
the type of the values when the iterator is dereferenced
Definition: json.hpp:6731
GLboolean GLboolean GLboolean GLboolean a
Definition: gl2ext.h:306
reference operator[](difference_type n) const
access to successor
Definition: json.hpp:7263
GLint GLenum GLsizei GLsizei GLsizei depth
Definition: gl2ext.h:572
const_reverse_iterator crbegin() const noexcept
returns a const reverse iterator to the last element
Definition: json.hpp:4525
constexpr bool is_number_float() const noexcept
return whether value is a floating-point number
Definition: json.hpp:2500
string_t dump(const int indent=-1) const
serialization
Definition: json.hpp:2242
GLenum void ** pointer
Definition: gl2.h:460
const_iterator cbegin() const noexcept
returns a const iterator to the first element
Definition: json.hpp:4350
Definition: JSType.h:34
std::size_t operator()(const nlohmann::json &j) const
return a hash value for a JSON object
Definition: json.hpp:10771
GLint reference
Definition: gl2ext.h:922
array (ordered collection of values)
constexpr bool is_number_integer() const noexcept
return whether value is an integer number
Definition: json.hpp:2444
#define N
Definition: gcc-loops.cpp:14
basic_json(const CompatibleNumberUnsignedType val) noexcept
create an unsigned number (implicit)
Definition: json.hpp:1526
static basic_json diff(const basic_json &source, const basic_json &target, const std::string &path="")
creates a diff as a JSON patch
Definition: json.hpp:10588
json_reverse_iterator operator++(int)
post-increment (it++)
Definition: json.hpp:7504
GLfloat f
Definition: gl2.h:417
const_reference back() const
access the last element
Definition: json.hpp:3890
constexpr bool is_boolean() const noexcept
return whether value is a boolean
Definition: json.hpp:2385
detail::split_helper< TList, TDelim > split
Definition: Brigand.h:1696
const GLfloat * v
Definition: gl2.h:514
void push_back(basic_json &&val)
add an object to an array
Definition: json.hpp:4901
typename std::allocator_traits< allocator_type >::const_pointer const_pointer
the type of an element const pointer
Definition: json.hpp:312
ReferenceType get_ref()
get a reference value (implicit)
Definition: json.hpp:3099
friend bool operator>(const_reference lhs, const_reference rhs) noexcept
comparison: greater than
Definition: json.hpp:5768
const_reverse_iterator rbegin() const noexcept
returns a const reverse iterator to the last element
Definition: json.hpp:4459
int boolean
Definition: dry.c:154
NumberIntegerType number_integer_t
a type for a number (integer)
Definition: json.hpp:622
iterator operator--(int)
post-decrement (it–)
Definition: json.hpp:7404
bool operator==(const Handle< T > &a, const Handle< U > &b)
Definition: Handle.h:144
basic_json patch(const basic_json &json_patch) const
applies a JSON patch
Definition: json.hpp:10303
Definition: safe_conversions.h:16
basic_json(const number_unsigned_t val) noexcept
create an unsigned integer number (explicit)
Definition: json.hpp:1495
iterator insert(const_iterator pos, basic_json &&val)
inserts element
Definition: json.hpp:5113
bool empty() const noexcept
checks whether the container is empty
Definition: json.hpp:4635
EGLenum type
Definition: eglext.h:63
def hexify(s)
Definition: util.py:149
JSON_DEPRECATED basic_json(std::istream &i, const parser_callback_t cb=nullptr)
construct a JSON value given an input stream
Definition: json.hpp:1991
basic_json(const number_integer_t val) noexcept
create an integer number (explicit)
Definition: json.hpp:1400
Definition: JSType.h:28
GLsizei const GLchar *const * string
Definition: gl2.h:479
constexpr bool is_null() const noexcept
return whether value is null
Definition: json.hpp:2363
result
Definition: target-blank-opener-post-window.php:5
void init()
Definition: HTMLNames.cpp:1637
iterator operator+(difference_type i)
add to iterator
Definition: json.hpp:7433
double max
Definition: DeviceProximityEvent.idl:32
const_iterator find(typename object_t::key_type key) const
find an element in a JSON object
Definition: json.hpp:4240
GLfloat GLfloat GLfloat GLfloat h
Definition: gl2ext.h:3060
basic_json(std::initializer_list< basic_json > init, bool type_deduction=true, value_t manual_type=value_t::array)
create a container (array or object) from an initializer list
Definition: json.hpp:1679
typename std::allocator_traits< allocator_type >::pointer pointer
the type of an element pointer
Definition: json.hpp:310
bool is(Ref< ArgType > &source)
Definition: Ref.h:220
reference operator[](const json_pointer &ptr)
access specified element via JSON Pointer
Definition: json.hpp:10115
std::integral_constant< std::ptrdiff_t, V > ptrdiff_t
Definition: Brigand.h:449
#define m_type
Definition: user_mbuf.h:248
const_reference at(const json_pointer &ptr) const
access specified element via JSON Pointer
Definition: json.hpp:10192
for i
Definition: complexityMeasures.m:24
const_reference front() const
access the first element
Definition: json.hpp:3845
value_t
the JSON type enumeration
Definition: json.hpp:792
struct A s
constexpr bool operator<=(const UnexpectedType< E > &lhs, const UnexpectedType< E > &rhs)
Definition: Expected.h:61
IteratorType erase(IteratorType pos)
remove element given an iterator
Definition: json.hpp:3946
const_reference at(size_type idx) const
access specified array element with bounds checking
Definition: json.hpp:3229
iterator & operator++()
pre-increment (++it)
Definition: json.hpp:7397
json_pointer(const std::string &s="")
create JSON pointer
Definition: json.hpp:9515
reference at(size_type idx)
access specified array element with bounds checking
Definition: json.hpp:3192
difference_type operator-(const const_iterator &other) const
return difference
Definition: json.hpp:7236
GLsizei GLsizei GLfloat distance
Definition: gl2ext.h:2866
Definition: JSType.h:69
basic_json(const CompatibleNumberIntegerType val) noexcept
create an integer number (implicit)
Definition: json.hpp:1468
const
Definition: upload.py:398
object_t::key_type key() const
return the key of an object iterator
Definition: json.hpp:7565
#define NULL
Definition: common_types.h:41
void push_back(const typename object_t::value_type &val)
add an object to an object
Definition: json.hpp:4987
iterator operator-(difference_type i)
subtract from iterator
Definition: json.hpp:7441
static basic_json parse(std::istream &i, const parser_callback_t cb=nullptr)
deserialize from stream
Definition: json.hpp:5974
object (unordered set of name/value pairs)
string_t value(const json_pointer &ptr, const char *default_value) const
overload for a default value of type const char*
Definition: json.hpp:3807
DOMString e
Definition: WebCryptoAPI.idl:115
friend bool operator<(const value_t lhs, const value_t rhs) noexcept
comparison operator for JSON types
Definition: json.hpp:5420
EGLenum EGLObjectKHR object
Definition: eglext.h:121
const_iterator & operator++()
pre-increment (++it)
Definition: json.hpp:6997
basic_json(const array_t &val)
create an array (explicit)
Definition: json.hpp:1215
string_t value(const typename object_t::key_type &key, const char *default_value) const
overload for a default value of type const char*
Definition: json.hpp:3742
reference operator*() const
return a reference to the value pointed to by the iterator
Definition: json.hpp:6909
ValueType value(const json_pointer &ptr, ValueType default_value) const
access specified object element via JSON Pointer with default value
Definition: json.hpp:3790
std::unique_ptr< ParsedNode > parse(VM *vm, const SourceCode &source, const Identifier &name, JSParserBuiltinMode builtinMode, JSParserStrictMode strictMode, JSParserScriptMode scriptMode, SourceParseMode parseMode, SuperBinding superBinding, ParserError &error, JSTextPosition *positionBeforeLastNewline=nullptr, ConstructorKind defaultConstructorKind=ConstructorKind::None, DerivedContextType derivedContextType=DerivedContextType::None, EvalContextType evalContextType=EvalContextType::None, DebuggerParseData *debuggerParseData=nullptr)
Definition: Parser.h:1887
GLboolean GLboolean GLboolean b
Definition: gl2ext.h:306
typename basic_json::const_reference reference
defines a reference to the type iterated over (value_type)
Definition: json.hpp:6737
iterator(const iterator &other) noexcept
copy constructor
Definition: json.hpp:7360
pointer operator->() const
dereference the iterator
Definition: json.hpp:6950
reference value() const
return the value of an iterator
Definition: json.hpp:7461
constexpr bool operator<(const UnexpectedType< E > &lhs, const UnexpectedType< E > &rhs)
Definition: Expected.h:59
basic_json<> json
default JSON class
Definition: json.hpp:10736
iterator insert(const_iterator pos, std::initializer_list< basic_json > ilist)
inserts elements
Definition: json.hpp:5252
typename detail::insert_impl< L, T >::type insert
Definition: Brigand.h:2317
bool operator<=(const const_iterator &other) const
comparison: less than or equal
Definition: json.hpp:7147
res
Definition: harness.py:111
#define NO_RETURN
Definition: typedefs.h:108
size_type erase(const typename object_t::key_type &key)
remove element from a JSON object given a key
Definition: json.hpp:4141
void erase(const size_type idx)
remove element from a JSON array given an index
Definition: json.hpp:4178
ArrayType< basic_json, AllocatorType< basic_json > > array_t
a type for an array
Definition: json.hpp:477
void clear() noexcept
clears the contents
Definition: json.hpp:4828
a const random access iterator for the basic_json class
Definition: json.hpp:6724
a template for a reverse iterator class
Definition: json.hpp:281
NumberUnsignedType number_unsigned_t
a type for a number (unsigned)
Definition: json.hpp:693
#define ASSERT(assertion)
Definition: Assertions.h:283
std::reverse_iterator< Base > base_iterator
shortcut to the reverse iterator adaptor
Definition: json.hpp:7489
CFArrayRef CFTypeRef key
Definition: AVFoundationCFSoftLinking.h:129
const_iterator operator++(int)
post-increment (it++)
Definition: json.hpp:6986
SubsamplingLevel & operator++(SubsamplingLevel &subsamplingLevel)
Definition: ImageFrame.h:51
reference operator[](T *key)
access specified object element
Definition: json.hpp:3600
friend bool operator!=(std::nullptr_t, const_reference v) noexcept
comparison: not equal
Definition: json.hpp:5622
Parser & parser
Definition: XPathGrammar.cpp:1193
typename Base::reference reference
the reference type for the pointed-to element
Definition: json.hpp:7491
iterator & operator=(iterator other) noexcept(std::is_nothrow_move_constructible< pointer >::value and std::is_nothrow_move_assignable< pointer >::value and std::is_nothrow_move_constructible< internal_iterator >::value and std::is_nothrow_move_assignable< internal_iterator >::value)
copy assignment
Definition: json.hpp:7365
friend bool operator<=(const_reference lhs, const_reference rhs) noexcept
comparison: less than or equal
Definition: json.hpp:5746
for for j
Definition: complexityMeasures.m:25
temp
Definition: parse_delay_file.m:64
GLuint GLsizei GLsizei GLfloat * val
Definition: gl2ext.h:3301
void swap(optional< T > &x, optional< T > &y) __NOEXCEPT_(__NOEXCEPT_(x.swap(y)))
Definition: Optional.h:1047
friend bool operator>=(const_reference lhs, const_reference rhs) noexcept
comparison: greater than or equal
Definition: json.hpp:5790
const_iterator operator+(difference_type i)
add to iterator
Definition: json.hpp:7214
friend bool operator!=(const_reference lhs, const_reference rhs) noexcept
comparison: not equal
Definition: json.hpp:5590
const_reference operator[](size_type idx) const
access specified array element
Definition: json.hpp:3399
bool operator==(const const_iterator &other) const
comparison: equal
Definition: json.hpp:7072
iterator begin() noexcept
returns an iterator to the first element
Definition: json.hpp:4310
StringType string_t
a type for a string
Definition: json.hpp:524
static basic_json parse(IteratorType first, IteratorType last, const parser_callback_t cb=nullptr)
deserialize from an iterator range with contiguous storage
Definition: json.hpp:6034
json_reverse_iterator operator-(difference_type i) const
subtract from iterator
Definition: json.hpp:7545
reference front()
access the first element
Definition: json.hpp:3837
iterator insert(const_iterator pos, size_type cnt, const basic_json &val)
inserts elements
Definition: json.hpp:5142
friend bool operator==(std::nullptr_t, const_reference v) noexcept
comparison: equal
Definition: json.hpp:5569
ObjectType< StringType, basic_json, std::less< StringType >, AllocatorType< std::pair< const StringType, basic_json > >> object_t
a type for an object
Definition: json.hpp:431
value_type & reference
the type of an element reference
Definition: json.hpp:297
basic_json(const basic_json &other)
copy constructor
Definition: json.hpp:2023
#define T(a)
Definition: row_common.cc:1964
~basic_json()
destructor
Definition: json.hpp:2170
basic_json flatten() const
return flattened JSON value
Definition: json.hpp:10219
void push_back(std::initializer_list< basic_json > init)
add an object to an object
Definition: json.hpp:5042
const_iterator(const const_iterator &other) noexcept
copy constructor
Definition: json.hpp:6815
typename lazy::remove< L, T >::type remove
Definition: Brigand.h:1595
void swap(array_t &other)
exchanges the values
Definition: json.hpp:5321
reference operator[](const typename object_t::key_type &key)
access specified object element
Definition: json.hpp:3439