JSON for Modern C++  2.0.2
json.hpp
1 /*
2  __ _____ _____ _____
3  __| | __| | | | JSON for Modern C++
4 | | |__ | | | | | | version 2.0.2
5 |_____|_____|_____|_|___| https://github.com/nlohmann/json
6 
7 Licensed under the MIT License <http://opensource.org/licenses/MIT>.
8 Copyright (c) 2013-2016 Niels Lohmann <http://nlohmann.me>.
9 
10 Permission is hereby granted, free of charge, to any person obtaining a copy
11 of this software and associated documentation files (the "Software"), to deal
12 in the Software without restriction, including without limitation the rights
13 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
14 copies of the Software, and to permit persons to whom the Software is
15 furnished to do so, subject to the following conditions:
16 
17 The above copyright notice and this permission notice shall be included in all
18 copies or substantial portions of the Software.
19 
20 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
23 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
25 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
26 SOFTWARE.
27 */
28 
29 #ifndef NLOHMANN_JSON_HPP
30 #define NLOHMANN_JSON_HPP
31 
32 #include <algorithm>
33 #include <array>
34 #include <cassert>
35 #include <ciso646>
36 #include <cmath>
37 #include <cstddef>
38 #include <cstdint>
39 #include <cstdlib>
40 #include <functional>
41 #include <initializer_list>
42 #include <iomanip>
43 #include <iostream>
44 #include <iterator>
45 #include <limits>
46 #include <locale>
47 #include <map>
48 #include <memory>
49 #include <numeric>
50 #include <sstream>
51 #include <stdexcept>
52 #include <string>
53 #include <type_traits>
54 #include <utility>
55 #include <vector>
56 
57 // exclude unsupported compilers
58 #if defined(__clang__)
59  #define CLANG_VERSION (__clang_major__ * 10000 + __clang_minor__ * 100 + __clang_patchlevel__)
60  #if CLANG_VERSION < 30400
61  #error "unsupported Clang version - see https://github.com/nlohmann/json#supported-compilers"
62  #endif
63 #elif defined(__GNUC__)
64  #define GCC_VERSION (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__)
65  #if GCC_VERSION < 40900
66  #error "unsupported GCC version - see https://github.com/nlohmann/json#supported-compilers"
67  #endif
68 #endif
69 
70 // disable float-equal warnings on GCC/clang
71 #if defined(__clang__) || defined(__GNUC__) || defined(__GNUG__)
72  #pragma GCC diagnostic push
73  #pragma GCC diagnostic ignored "-Wfloat-equal"
74 #endif
75 
81 namespace nlohmann
82 {
83 
84 
89 namespace
90 {
101 template<typename T>
102 struct has_mapped_type
103 {
104  private:
105  template<typename C> static char test(typename C::mapped_type*);
106  template<typename C> static char (&test(...))[2];
107  public:
108  static constexpr bool value = sizeof(test<T>(0)) == 1;
109 };
110 
123 struct DecimalSeparator : std::numpunct<char>
124 {
125  char do_decimal_point() const
126  {
127  return '.';
128  }
129 };
130 
131 }
132 
211 template <
212  template<typename U, typename V, typename... Args> class ObjectType = std::map,
213  template<typename U, typename... Args> class ArrayType = std::vector,
214  class StringType = std::string,
215  class BooleanType = bool,
216  class NumberIntegerType = std::int64_t,
217  class NumberUnsignedType = std::uint64_t,
218  class NumberFloatType = double,
219  template<typename U> class AllocatorType = std::allocator
220  >
222 {
223  private:
225  using basic_json_t = basic_json<ObjectType, ArrayType, StringType,
226  BooleanType, NumberIntegerType, NumberUnsignedType, NumberFloatType,
227  AllocatorType>;
228 
229  public:
230  // forward declarations
231  template<typename Base> class json_reverse_iterator;
232  class json_pointer;
233 
235  // container types //
237 
242 
245 
249  using const_reference = const value_type&;
250 
252  using difference_type = std::ptrdiff_t;
254  using size_type = std::size_t;
255 
257  using allocator_type = AllocatorType<basic_json>;
258 
260  using pointer = typename std::allocator_traits<allocator_type>::pointer;
262  using const_pointer = typename std::allocator_traits<allocator_type>::const_pointer;
263 
265  class iterator;
267  class const_iterator;
272 
274 
275 
280  {
281  return allocator_type();
282  }
283 
284 
286  // JSON value data types //
288 
293 
377  using object_t = ObjectType<StringType,
378  basic_json,
379  std::less<StringType>,
380  AllocatorType<std::pair<const StringType,
381  basic_json>>>;
382 
427  using array_t = ArrayType<basic_json, AllocatorType<basic_json>>;
428 
474  using string_t = StringType;
475 
500  using boolean_t = BooleanType;
501 
572  using number_integer_t = NumberIntegerType;
573 
643  using number_unsigned_t = NumberUnsignedType;
644 
711  using number_float_t = NumberFloatType;
712 
714 
715 
717  // JSON type enumeration //
719 
742  enum class value_t : uint8_t
743  {
744  null,
745  object,
746  array,
747  string,
748  boolean,
749  number_integer,
750  number_unsigned,
751  number_float,
752  discarded
753  };
754 
755 
756  private:
757 
759  template<typename T, typename... Args>
760  static T* create(Args&& ... args)
761  {
762  AllocatorType<T> alloc;
763  auto deleter = [&](T * object)
764  {
765  alloc.deallocate(object, 1);
766  };
767  std::unique_ptr<T, decltype(deleter)> object(alloc.allocate(1), deleter);
768  alloc.construct(object.get(), std::forward<Args>(args)...);
769  assert(object.get() != nullptr);
770  return object.release();
771  }
772 
774  // JSON value storage //
776 
801  union json_value
802  {
804  object_t* object;
806  array_t* array;
808  string_t* string;
810  boolean_t boolean;
812  number_integer_t number_integer;
814  number_unsigned_t number_unsigned;
816  number_float_t number_float;
817 
819  json_value() = default;
821  json_value(boolean_t v) noexcept : boolean(v) {}
823  json_value(number_integer_t v) noexcept : number_integer(v) {}
825  json_value(number_unsigned_t v) noexcept : number_unsigned(v) {}
827  json_value(number_float_t v) noexcept : number_float(v) {}
829  json_value(value_t t)
830  {
831  switch (t)
832  {
833  case value_t::object:
834  {
835  object = create<object_t>();
836  break;
837  }
838 
839  case value_t::array:
840  {
841  array = create<array_t>();
842  break;
843  }
844 
845  case value_t::string:
846  {
847  string = create<string_t>("");
848  break;
849  }
850 
851  case value_t::boolean:
852  {
853  boolean = boolean_t(false);
854  break;
855  }
856 
857  case value_t::number_integer:
858  {
859  number_integer = number_integer_t(0);
860  break;
861  }
862 
863  case value_t::number_unsigned:
864  {
865  number_unsigned = number_unsigned_t(0);
866  break;
867  }
868 
869  case value_t::number_float:
870  {
871  number_float = number_float_t(0.0);
872  break;
873  }
874 
875  default:
876  {
877  break;
878  }
879  }
880  }
881 
883  json_value(const string_t& value)
884  {
885  string = create<string_t>(value);
886  }
887 
889  json_value(const object_t& value)
890  {
891  object = create<object_t>(value);
892  }
893 
895  json_value(const array_t& value)
896  {
897  array = create<array_t>(value);
898  }
899  };
900 
910  void assert_invariant() const
911  {
912  assert(m_type != value_t::object or m_value.object != nullptr);
913  assert(m_type != value_t::array or m_value.array != nullptr);
914  assert(m_type != value_t::string or m_value.string != nullptr);
915  }
916 
917  public:
919  // JSON parser callback //
921 
932  enum class parse_event_t : uint8_t
933  {
935  object_start,
937  object_end,
939  array_start,
941  array_end,
943  key,
945  value
946  };
947 
1000  using parser_callback_t = std::function<bool(int depth,
1001  parse_event_t event,
1002  basic_json& parsed)>;
1003 
1004 
1006  // constructors //
1008 
1013 
1054  : m_type(value_type), m_value(value_type)
1055  {
1056  assert_invariant();
1057  }
1058 
1086  basic_json() = default;
1087 
1110  basic_json(std::nullptr_t) noexcept
1111  : basic_json(value_t::null)
1112  {
1113  assert_invariant();
1114  }
1115 
1135  basic_json(const object_t& val)
1136  : m_type(value_t::object), m_value(val)
1137  {
1138  assert_invariant();
1139  }
1140 
1167  template <class CompatibleObjectType, typename
1168  std::enable_if<
1169  std::is_constructible<typename object_t::key_type, typename CompatibleObjectType::key_type>::value and
1170  std::is_constructible<basic_json, typename CompatibleObjectType::mapped_type>::value, int>::type
1171  = 0>
1172  basic_json(const CompatibleObjectType& val)
1173  : m_type(value_t::object)
1174  {
1175  using std::begin;
1176  using std::end;
1177  m_value.object = create<object_t>(begin(val), end(val));
1178  assert_invariant();
1179  }
1180 
1200  basic_json(const array_t& val)
1201  : m_type(value_t::array), m_value(val)
1202  {
1203  assert_invariant();
1204  }
1205 
1232  template <class CompatibleArrayType, typename
1233  std::enable_if<
1234  not std::is_same<CompatibleArrayType, typename basic_json_t::iterator>::value and
1235  not std::is_same<CompatibleArrayType, typename basic_json_t::const_iterator>::value and
1236  not std::is_same<CompatibleArrayType, typename basic_json_t::reverse_iterator>::value and
1237  not std::is_same<CompatibleArrayType, typename basic_json_t::const_reverse_iterator>::value and
1238  not std::is_same<CompatibleArrayType, typename array_t::iterator>::value and
1239  not std::is_same<CompatibleArrayType, typename array_t::const_iterator>::value and
1240  std::is_constructible<basic_json, typename CompatibleArrayType::value_type>::value, int>::type
1241  = 0>
1242  basic_json(const CompatibleArrayType& val)
1243  : m_type(value_t::array)
1244  {
1245  using std::begin;
1246  using std::end;
1247  m_value.array = create<array_t>(begin(val), end(val));
1248  assert_invariant();
1249  }
1250 
1272  basic_json(const string_t& val)
1273  : m_type(value_t::string), m_value(val)
1274  {
1275  assert_invariant();
1276  }
1277 
1298  basic_json(const typename string_t::value_type* val)
1299  : basic_json(string_t(val))
1300  {
1301  assert_invariant();
1302  }
1303 
1327  template <class CompatibleStringType, typename
1328  std::enable_if<
1329  std::is_constructible<string_t, CompatibleStringType>::value, int>::type
1330  = 0>
1331  basic_json(const CompatibleStringType& val)
1332  : basic_json(string_t(val))
1333  {
1334  assert_invariant();
1335  }
1336 
1351  basic_json(boolean_t val) noexcept
1352  : m_type(value_t::boolean), m_value(val)
1353  {
1354  assert_invariant();
1355  }
1356 
1380  template<typename T,
1381  typename std::enable_if<
1382  not (std::is_same<T, int>::value)
1383  and std::is_same<T, number_integer_t>::value
1384  , int>::type
1385  = 0>
1386  basic_json(const number_integer_t val) noexcept
1387  : m_type(value_t::number_integer), m_value(val)
1388  {
1389  assert_invariant();
1390  }
1391 
1417  basic_json(const int val) noexcept
1418  : m_type(value_t::number_integer),
1419  m_value(static_cast<number_integer_t>(val))
1420  {
1421  assert_invariant();
1422  }
1423 
1449  template<typename CompatibleNumberIntegerType, typename
1450  std::enable_if<
1451  std::is_constructible<number_integer_t, CompatibleNumberIntegerType>::value and
1452  std::numeric_limits<CompatibleNumberIntegerType>::is_integer and
1453  std::numeric_limits<CompatibleNumberIntegerType>::is_signed,
1454  CompatibleNumberIntegerType>::type
1455  = 0>
1456  basic_json(const CompatibleNumberIntegerType val) noexcept
1457  : m_type(value_t::number_integer),
1458  m_value(static_cast<number_integer_t>(val))
1459  {
1460  assert_invariant();
1461  }
1462 
1480  template<typename T,
1481  typename std::enable_if<
1482  not (std::is_same<T, int>::value)
1483  and std::is_same<T, number_unsigned_t>::value
1484  , int>::type
1485  = 0>
1486  basic_json(const number_unsigned_t val) noexcept
1487  : m_type(value_t::number_unsigned), m_value(val)
1488  {
1489  assert_invariant();
1490  }
1491 
1512  template <typename CompatibleNumberUnsignedType, typename
1513  std::enable_if <
1514  std::is_constructible<number_unsigned_t, CompatibleNumberUnsignedType>::value and
1515  std::numeric_limits<CompatibleNumberUnsignedType>::is_integer and
1516  not std::numeric_limits<CompatibleNumberUnsignedType>::is_signed,
1517  CompatibleNumberUnsignedType>::type
1518  = 0>
1519  basic_json(const CompatibleNumberUnsignedType val) noexcept
1520  : m_type(value_t::number_unsigned),
1521  m_value(static_cast<number_unsigned_t>(val))
1522  {
1523  assert_invariant();
1524  }
1525 
1550  basic_json(const number_float_t val) noexcept
1551  : m_type(value_t::number_float), m_value(val)
1552  {
1553  // replace infinity and NAN by null
1554  if (not std::isfinite(val))
1555  {
1556  m_type = value_t::null;
1557  m_value = json_value();
1558  }
1559 
1560  assert_invariant();
1561  }
1562 
1594  template<typename CompatibleNumberFloatType, typename = typename
1595  std::enable_if<
1596  std::is_constructible<number_float_t, CompatibleNumberFloatType>::value and
1597  std::is_floating_point<CompatibleNumberFloatType>::value>::type
1598  >
1599  basic_json(const CompatibleNumberFloatType val) noexcept
1600  : basic_json(number_float_t(val))
1601  {
1602  assert_invariant();
1603  }
1604 
1674  basic_json(std::initializer_list<basic_json> init,
1675  bool type_deduction = true,
1676  value_t manual_type = value_t::array)
1677  {
1678  // check if each element is an array with two elements whose first
1679  // element is a string
1680  bool is_an_object = std::all_of(init.begin(), init.end(),
1681  [](const basic_json & element)
1682  {
1683  return element.is_array() and element.size() == 2 and element[0].is_string();
1684  });
1685 
1686  // adjust type if type deduction is not wanted
1687  if (not type_deduction)
1688  {
1689  // if array is wanted, do not create an object though possible
1690  if (manual_type == value_t::array)
1691  {
1692  is_an_object = false;
1693  }
1694 
1695  // if object is wanted but impossible, throw an exception
1696  if (manual_type == value_t::object and not is_an_object)
1697  {
1698  throw std::domain_error("cannot create object from initializer list");
1699  }
1700  }
1701 
1702  if (is_an_object)
1703  {
1704  // the initializer list is a list of pairs -> create object
1705  m_type = value_t::object;
1706  m_value = value_t::object;
1707 
1708  std::for_each(init.begin(), init.end(), [this](const basic_json & element)
1709  {
1710  m_value.object->emplace(*(element[0].m_value.string), element[1]);
1711  });
1712  }
1713  else
1714  {
1715  // the initializer list describes an array -> create array
1716  m_type = value_t::array;
1717  m_value.array = create<array_t>(init);
1718  }
1719 
1720  assert_invariant();
1721  }
1722 
1757  static basic_json array(std::initializer_list<basic_json> init =
1758  std::initializer_list<basic_json>())
1759  {
1760  return basic_json(init, false, value_t::array);
1761  }
1762 
1797  static basic_json object(std::initializer_list<basic_json> init =
1798  std::initializer_list<basic_json>())
1799  {
1800  return basic_json(init, false, value_t::object);
1801  }
1802 
1822  : m_type(value_t::array)
1823  {
1824  m_value.array = create<array_t>(cnt, val);
1825  assert_invariant();
1826  }
1827 
1864  template <class InputIT, typename
1865  std::enable_if<
1866  std::is_same<InputIT, typename basic_json_t::iterator>::value or
1867  std::is_same<InputIT, typename basic_json_t::const_iterator>::value
1868  , int>::type
1869  = 0>
1870  basic_json(InputIT first, InputIT last)
1871  {
1872  assert(first.m_object != nullptr);
1873  assert(last.m_object != nullptr);
1874 
1875  // make sure iterator fits the current value
1876  if (first.m_object != last.m_object)
1877  {
1878  throw std::domain_error("iterators are not compatible");
1879  }
1880 
1881  // copy type from first iterator
1882  m_type = first.m_object->m_type;
1883 
1884  // check if iterator range is complete for primitive values
1885  switch (m_type)
1886  {
1887  case value_t::boolean:
1888  case value_t::number_float:
1889  case value_t::number_integer:
1890  case value_t::number_unsigned:
1891  case value_t::string:
1892  {
1893  if (not first.m_it.primitive_iterator.is_begin() or not last.m_it.primitive_iterator.is_end())
1894  {
1895  throw std::out_of_range("iterators out of range");
1896  }
1897  break;
1898  }
1899 
1900  default:
1901  {
1902  break;
1903  }
1904  }
1905 
1906  switch (m_type)
1907  {
1908  case value_t::number_integer:
1909  {
1910  m_value.number_integer = first.m_object->m_value.number_integer;
1911  break;
1912  }
1913 
1914  case value_t::number_unsigned:
1915  {
1916  m_value.number_unsigned = first.m_object->m_value.number_unsigned;
1917  break;
1918  }
1919 
1920  case value_t::number_float:
1921  {
1922  m_value.number_float = first.m_object->m_value.number_float;
1923  break;
1924  }
1925 
1926  case value_t::boolean:
1927  {
1928  m_value.boolean = first.m_object->m_value.boolean;
1929  break;
1930  }
1931 
1932  case value_t::string:
1933  {
1934  m_value = *first.m_object->m_value.string;
1935  break;
1936  }
1937 
1938  case value_t::object:
1939  {
1940  m_value.object = create<object_t>(first.m_it.object_iterator, last.m_it.object_iterator);
1941  break;
1942  }
1943 
1944  case value_t::array:
1945  {
1946  m_value.array = create<array_t>(first.m_it.array_iterator, last.m_it.array_iterator);
1947  break;
1948  }
1949 
1950  default:
1951  {
1952  throw std::domain_error("cannot use construct with iterators from " + first.m_object->type_name());
1953  }
1954  }
1955 
1956  assert_invariant();
1957  }
1958 
1979  explicit basic_json(std::istream& i, const parser_callback_t cb = nullptr)
1980  {
1981  *this = parser(i, cb).parse();
1982  assert_invariant();
1983  }
1984 
1986  // other constructors and destructor //
1988 
2011  basic_json(const basic_json& other)
2012  : m_type(other.m_type)
2013  {
2014  // check of passed value is valid
2015  other.assert_invariant();
2016 
2017  switch (m_type)
2018  {
2019  case value_t::object:
2020  {
2021  m_value = *other.m_value.object;
2022  break;
2023  }
2024 
2025  case value_t::array:
2026  {
2027  m_value = *other.m_value.array;
2028  break;
2029  }
2030 
2031  case value_t::string:
2032  {
2033  m_value = *other.m_value.string;
2034  break;
2035  }
2036 
2037  case value_t::boolean:
2038  {
2039  m_value = other.m_value.boolean;
2040  break;
2041  }
2042 
2043  case value_t::number_integer:
2044  {
2045  m_value = other.m_value.number_integer;
2046  break;
2047  }
2048 
2049  case value_t::number_unsigned:
2050  {
2051  m_value = other.m_value.number_unsigned;
2052  break;
2053  }
2054 
2055  case value_t::number_float:
2056  {
2057  m_value = other.m_value.number_float;
2058  break;
2059  }
2060 
2061  default:
2062  {
2063  break;
2064  }
2065  }
2066 
2067  assert_invariant();
2068  }
2069 
2088  basic_json(basic_json&& other) noexcept
2089  : m_type(std::move(other.m_type)),
2090  m_value(std::move(other.m_value))
2091  {
2092  // check that passed value is valid
2093  other.assert_invariant();
2094 
2095  // invalidate payload
2096  other.m_type = value_t::null;
2097  other.m_value = {};
2098 
2099  assert_invariant();
2100  }
2101 
2125  reference& operator=(basic_json other) noexcept (
2126  std::is_nothrow_move_constructible<value_t>::value and
2127  std::is_nothrow_move_assignable<value_t>::value and
2128  std::is_nothrow_move_constructible<json_value>::value and
2129  std::is_nothrow_move_assignable<json_value>::value
2130  )
2131  {
2132  // check that passed value is valid
2133  other.assert_invariant();
2134 
2135  using std::swap;
2136  swap(m_type, other.m_type);
2137  swap(m_value, other.m_value);
2138 
2139  assert_invariant();
2140  return *this;
2141  }
2142 
2159  {
2160  assert_invariant();
2161 
2162  switch (m_type)
2163  {
2164  case value_t::object:
2165  {
2166  AllocatorType<object_t> alloc;
2167  alloc.destroy(m_value.object);
2168  alloc.deallocate(m_value.object, 1);
2169  break;
2170  }
2171 
2172  case value_t::array:
2173  {
2174  AllocatorType<array_t> alloc;
2175  alloc.destroy(m_value.array);
2176  alloc.deallocate(m_value.array, 1);
2177  break;
2178  }
2179 
2180  case value_t::string:
2181  {
2182  AllocatorType<string_t> alloc;
2183  alloc.destroy(m_value.string);
2184  alloc.deallocate(m_value.string, 1);
2185  break;
2186  }
2187 
2188  default:
2189  {
2190  // all other types need no specific destructor
2191  break;
2192  }
2193  }
2194  }
2195 
2197 
2198  public:
2200  // object inspection //
2202 
2206 
2230  string_t dump(const int indent = -1) const
2231  {
2232  std::stringstream ss;
2233  // fix locale problems
2234  ss.imbue(std::locale(std::locale(), new DecimalSeparator));
2235 
2236  // 6, 15 or 16 digits of precision allows round-trip IEEE 754
2237  // string->float->string, string->double->string or string->long
2238  // double->string; to be safe, we read this value from
2239  // std::numeric_limits<number_float_t>::digits10
2240  ss.precision(std::numeric_limits<double>::digits10);
2241 
2242  if (indent >= 0)
2243  {
2244  dump(ss, true, static_cast<unsigned int>(indent));
2245  }
2246  else
2247  {
2248  dump(ss, false, 0);
2249  }
2250 
2251  return ss.str();
2252  }
2253 
2272  constexpr value_t type() const noexcept
2273  {
2274  return m_type;
2275  }
2276 
2302  constexpr bool is_primitive() const noexcept
2303  {
2304  return is_null() or is_string() or is_boolean() or is_number();
2305  }
2306 
2329  constexpr bool is_structured() const noexcept
2330  {
2331  return is_array() or is_object();
2332  }
2333 
2351  constexpr bool is_null() const noexcept
2352  {
2353  return m_type == value_t::null;
2354  }
2355 
2373  constexpr bool is_boolean() const noexcept
2374  {
2375  return m_type == value_t::boolean;
2376  }
2377 
2403  constexpr bool is_number() const noexcept
2404  {
2405  return is_number_integer() or is_number_float();
2406  }
2407 
2432  constexpr bool is_number_integer() const noexcept
2433  {
2434  return m_type == value_t::number_integer or m_type == value_t::number_unsigned;
2435  }
2436 
2460  constexpr bool is_number_unsigned() const noexcept
2461  {
2462  return m_type == value_t::number_unsigned;
2463  }
2464 
2488  constexpr bool is_number_float() const noexcept
2489  {
2490  return m_type == value_t::number_float;
2491  }
2492 
2510  constexpr bool is_object() const noexcept
2511  {
2512  return m_type == value_t::object;
2513  }
2514 
2532  constexpr bool is_array() const noexcept
2533  {
2534  return m_type == value_t::array;
2535  }
2536 
2554  constexpr bool is_string() const noexcept
2555  {
2556  return m_type == value_t::string;
2557  }
2558 
2581  constexpr bool is_discarded() const noexcept
2582  {
2583  return m_type == value_t::discarded;
2584  }
2585 
2604  constexpr operator value_t() const noexcept
2605  {
2606  return m_type;
2607  }
2608 
2610 
2611  private:
2613  // value access //
2615 
2617  template <class T, typename
2618  std::enable_if<
2619  std::is_convertible<typename object_t::key_type, typename T::key_type>::value and
2620  std::is_convertible<basic_json_t, typename T::mapped_type>::value
2621  , int>::type = 0>
2622  T get_impl(T*) const
2623  {
2624  if (is_object())
2625  {
2626  return T(m_value.object->begin(), m_value.object->end());
2627  }
2628  else
2629  {
2630  throw std::domain_error("type must be object, but is " + type_name());
2631  }
2632  }
2633 
2635  object_t get_impl(object_t*) const
2636  {
2637  if (is_object())
2638  {
2639  return *(m_value.object);
2640  }
2641  else
2642  {
2643  throw std::domain_error("type must be object, but is " + type_name());
2644  }
2645  }
2646 
2648  template <class T, typename
2649  std::enable_if<
2650  std::is_convertible<basic_json_t, typename T::value_type>::value and
2651  not std::is_same<basic_json_t, typename T::value_type>::value and
2652  not std::is_arithmetic<T>::value and
2653  not std::is_convertible<std::string, T>::value and
2654  not has_mapped_type<T>::value
2655  , int>::type = 0>
2656  T get_impl(T*) const
2657  {
2658  if (is_array())
2659  {
2660  T to_vector;
2661  std::transform(m_value.array->begin(), m_value.array->end(),
2662  std::inserter(to_vector, to_vector.end()), [](basic_json i)
2663  {
2664  return i.get<typename T::value_type>();
2665  });
2666  return to_vector;
2667  }
2668  else
2669  {
2670  throw std::domain_error("type must be array, but is " + type_name());
2671  }
2672  }
2673 
2675  template <class T, typename
2676  std::enable_if<
2677  std::is_convertible<basic_json_t, T>::value and
2678  not std::is_same<basic_json_t, T>::value
2679  , int>::type = 0>
2680  std::vector<T> get_impl(std::vector<T>*) const
2681  {
2682  if (is_array())
2683  {
2684  std::vector<T> to_vector;
2685  to_vector.reserve(m_value.array->size());
2686  std::transform(m_value.array->begin(), m_value.array->end(),
2687  std::inserter(to_vector, to_vector.end()), [](basic_json i)
2688  {
2689  return i.get<T>();
2690  });
2691  return to_vector;
2692  }
2693  else
2694  {
2695  throw std::domain_error("type must be array, but is " + type_name());
2696  }
2697  }
2698 
2700  template <class T, typename
2701  std::enable_if<
2702  std::is_same<basic_json, typename T::value_type>::value and
2703  not has_mapped_type<T>::value
2704  , int>::type = 0>
2705  T get_impl(T*) const
2706  {
2707  if (is_array())
2708  {
2709  return T(m_value.array->begin(), m_value.array->end());
2710  }
2711  else
2712  {
2713  throw std::domain_error("type must be array, but is " + type_name());
2714  }
2715  }
2716 
2718  array_t get_impl(array_t*) const
2719  {
2720  if (is_array())
2721  {
2722  return *(m_value.array);
2723  }
2724  else
2725  {
2726  throw std::domain_error("type must be array, but is " + type_name());
2727  }
2728  }
2729 
2731  template <typename T, typename
2732  std::enable_if<
2733  std::is_convertible<string_t, T>::value
2734  , int>::type = 0>
2735  T get_impl(T*) const
2736  {
2737  if (is_string())
2738  {
2739  return *m_value.string;
2740  }
2741  else
2742  {
2743  throw std::domain_error("type must be string, but is " + type_name());
2744  }
2745  }
2746 
2748  template<typename T, typename
2749  std::enable_if<
2750  std::is_arithmetic<T>::value
2751  , 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());
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
2941  std::enable_if<
2942  not std::is_pointer<ValueType>::value
2943  , int>::type = 0>
2944  ValueType get() const
2945  {
2946  return get_impl(static_cast<ValueType*>(nullptr));
2947  }
2948 
2976  template<typename PointerType, typename
2977  std::enable_if<
2978  std::is_pointer<PointerType>::value
2979  , int>::type = 0>
2980  PointerType get() noexcept
2981  {
2982  // delegate the call to get_ptr
2983  return get_ptr<PointerType>();
2984  }
2985 
2990  template<typename PointerType, typename
2991  std::enable_if<
2992  std::is_pointer<PointerType>::value
2993  , int>::type = 0>
2994  constexpr const PointerType get() const noexcept
2995  {
2996  // delegate the call to get_ptr
2997  return get_ptr<PointerType>();
2998  }
2999 
3026  template<typename PointerType, typename
3027  std::enable_if<
3028  std::is_pointer<PointerType>::value
3029  , int>::type = 0>
3030  PointerType get_ptr() noexcept
3031  {
3032  // get the type of the PointerType (remove pointer and const)
3033  using pointee_t = typename std::remove_const<typename
3034  std::remove_pointer<typename
3035  std::remove_const<PointerType>::type>::type>::type;
3036  // make sure the type matches the allowed types
3037  static_assert(
3038  std::is_same<object_t, pointee_t>::value
3039  or std::is_same<array_t, pointee_t>::value
3040  or std::is_same<string_t, pointee_t>::value
3041  or std::is_same<boolean_t, pointee_t>::value
3042  or std::is_same<number_integer_t, pointee_t>::value
3043  or std::is_same<number_unsigned_t, pointee_t>::value
3044  or std::is_same<number_float_t, pointee_t>::value
3045  , "incompatible pointer type");
3046 
3047  // delegate the call to get_impl_ptr<>()
3048  return get_impl_ptr(static_cast<PointerType>(nullptr));
3049  }
3050 
3055  template<typename PointerType, typename
3056  std::enable_if<
3057  std::is_pointer<PointerType>::value
3058  and std::is_const<typename std::remove_pointer<PointerType>::type>::value
3059  , int>::type = 0>
3060  constexpr const PointerType get_ptr() const noexcept
3061  {
3062  // get the type of the PointerType (remove pointer and const)
3063  using pointee_t = typename std::remove_const<typename
3064  std::remove_pointer<typename
3065  std::remove_const<PointerType>::type>::type>::type;
3066  // make sure the type matches the allowed types
3067  static_assert(
3068  std::is_same<object_t, pointee_t>::value
3069  or std::is_same<array_t, pointee_t>::value
3070  or std::is_same<string_t, pointee_t>::value
3071  or std::is_same<boolean_t, pointee_t>::value
3072  or std::is_same<number_integer_t, pointee_t>::value
3073  or std::is_same<number_unsigned_t, pointee_t>::value
3074  or std::is_same<number_float_t, pointee_t>::value
3075  , "incompatible pointer type");
3076 
3077  // delegate the call to get_impl_ptr<>() const
3078  return get_impl_ptr(static_cast<const PointerType>(nullptr));
3079  }
3080 
3107  template<typename ReferenceType, typename
3108  std::enable_if<
3109  std::is_reference<ReferenceType>::value
3110  , int>::type = 0>
3111  ReferenceType get_ref()
3112  {
3113  // delegate call to get_ref_impl
3114  return get_ref_impl<ReferenceType>(*this);
3115  }
3116 
3121  template<typename ReferenceType, typename
3122  std::enable_if<
3123  std::is_reference<ReferenceType>::value
3124  and std::is_const<typename std::remove_reference<ReferenceType>::type>::value
3125  , int>::type = 0>
3126  ReferenceType get_ref() const
3127  {
3128  // delegate call to get_ref_impl
3129  return get_ref_impl<ReferenceType>(*this);
3130  }
3131 
3160  template < typename ValueType, typename
3161  std::enable_if <
3162  not std::is_pointer<ValueType>::value
3163  and not std::is_same<ValueType, typename string_t::value_type>::value
3164 #ifndef _MSC_VER // Fix for issue #167 operator<< abiguity under VS2015
3165  and not std::is_same<ValueType, std::initializer_list<typename string_t::value_type>>::value
3166 #endif
3167  , int >::type = 0 >
3168  operator ValueType() const
3169  {
3170  // delegate the call to get<>() const
3171  return get<ValueType>();
3172  }
3173 
3175 
3176 
3178  // element access //
3180 
3184 
3208  {
3209  // at only works for arrays
3210  if (is_array())
3211  {
3212  try
3213  {
3214  return m_value.array->at(idx);
3215  }
3216  catch (std::out_of_range&)
3217  {
3218  // create better exception explanation
3219  throw std::out_of_range("array index " + std::to_string(idx) + " is out of range");
3220  }
3221  }
3222  else
3223  {
3224  throw std::domain_error("cannot use at() with " + type_name());
3225  }
3226  }
3227 
3251  {
3252  // at only works for arrays
3253  if (is_array())
3254  {
3255  try
3256  {
3257  return m_value.array->at(idx);
3258  }
3259  catch (std::out_of_range&)
3260  {
3261  // create better exception explanation
3262  throw std::out_of_range("array index " + std::to_string(idx) + " is out of range");
3263  }
3264  }
3265  else
3266  {
3267  throw std::domain_error("cannot use at() with " + type_name());
3268  }
3269  }
3270 
3297  reference at(const typename object_t::key_type& key)
3298  {
3299  // at only works for objects
3300  if (is_object())
3301  {
3302  try
3303  {
3304  return m_value.object->at(key);
3305  }
3306  catch (std::out_of_range&)
3307  {
3308  // create better exception explanation
3309  throw std::out_of_range("key '" + key + "' not found");
3310  }
3311  }
3312  else
3313  {
3314  throw std::domain_error("cannot use at() with " + type_name());
3315  }
3316  }
3317 
3344  const_reference at(const typename object_t::key_type& key) const
3345  {
3346  // at only works for objects
3347  if (is_object())
3348  {
3349  try
3350  {
3351  return m_value.object->at(key);
3352  }
3353  catch (std::out_of_range&)
3354  {
3355  // create better exception explanation
3356  throw std::out_of_range("key '" + key + "' not found");
3357  }
3358  }
3359  else
3360  {
3361  throw std::domain_error("cannot use at() with " + type_name());
3362  }
3363  }
3364 
3391  {
3392  // implicitly convert null value to an empty array
3393  if (is_null())
3394  {
3395  m_type = value_t::array;
3396  m_value.array = create<array_t>();
3397  assert_invariant();
3398  }
3399 
3400  // operator[] only works for arrays
3401  if (is_array())
3402  {
3403  // fill up array with null values if given idx is outside range
3404  if (idx >= m_value.array->size())
3405  {
3406  m_value.array->insert(m_value.array->end(),
3407  idx - m_value.array->size() + 1,
3408  basic_json());
3409  }
3410 
3411  return m_value.array->operator[](idx);
3412  }
3413  else
3414  {
3415  throw std::domain_error("cannot use operator[] with " + type_name());
3416  }
3417  }
3418 
3439  {
3440  // const operator[] only works for arrays
3441  if (is_array())
3442  {
3443  return m_value.array->operator[](idx);
3444  }
3445  else
3446  {
3447  throw std::domain_error("cannot use operator[] with " + type_name());
3448  }
3449  }
3450 
3478  reference operator[](const typename object_t::key_type& key)
3479  {
3480  // implicitly convert null value to an empty object
3481  if (is_null())
3482  {
3483  m_type = value_t::object;
3484  m_value.object = create<object_t>();
3485  assert_invariant();
3486  }
3487 
3488  // operator[] only works for objects
3489  if (is_object())
3490  {
3491  return m_value.object->operator[](key);
3492  }
3493  else
3494  {
3495  throw std::domain_error("cannot use operator[] with " + type_name());
3496  }
3497  }
3498 
3526  const_reference operator[](const typename object_t::key_type& key) const
3527  {
3528  // const operator[] only works for objects
3529  if (is_object())
3530  {
3531  assert(m_value.object->find(key) != m_value.object->end());
3532  return m_value.object->find(key)->second;
3533  }
3534  else
3535  {
3536  throw std::domain_error("cannot use operator[] with " + type_name());
3537  }
3538  }
3539 
3567  template<typename T, std::size_t n>
3568  reference operator[](T * (&key)[n])
3569  {
3570  return operator[](static_cast<const T>(key));
3571  }
3572 
3602  template<typename T, std::size_t n>
3603  const_reference operator[](T * (&key)[n]) const
3604  {
3605  return operator[](static_cast<const T>(key));
3606  }
3607 
3635  template<typename T>
3637  {
3638  // implicitly convert null to object
3639  if (is_null())
3640  {
3641  m_type = value_t::object;
3642  m_value = value_t::object;
3643  assert_invariant();
3644  }
3645 
3646  // at only works for objects
3647  if (is_object())
3648  {
3649  return m_value.object->operator[](key);
3650  }
3651  else
3652  {
3653  throw std::domain_error("cannot use operator[] with " + type_name());
3654  }
3655  }
3656 
3684  template<typename T>
3686  {
3687  // at only works for objects
3688  if (is_object())
3689  {
3690  assert(m_value.object->find(key) != m_value.object->end());
3691  return m_value.object->find(key)->second;
3692  }
3693  else
3694  {
3695  throw std::domain_error("cannot use operator[] with " + type_name());
3696  }
3697  }
3698 
3747  template <class ValueType, typename
3748  std::enable_if<
3749  std::is_convertible<basic_json_t, ValueType>::value
3750  , int>::type = 0>
3751  ValueType value(const typename object_t::key_type& key, ValueType default_value) const
3752  {
3753  // at only works for objects
3754  if (is_object())
3755  {
3756  // if key is found, return value and given default value otherwise
3757  const auto it = find(key);
3758  if (it != end())
3759  {
3760  return *it;
3761  }
3762  else
3763  {
3764  return default_value;
3765  }
3766  }
3767  else
3768  {
3769  throw std::domain_error("cannot use value() with " + type_name());
3770  }
3771  }
3772 
3777  string_t value(const typename object_t::key_type& key, const char* default_value) const
3778  {
3779  return value(key, string_t(default_value));
3780  }
3781 
3823  template <class ValueType, typename
3824  std::enable_if<
3825  std::is_convertible<basic_json_t, ValueType>::value
3826  , int>::type = 0>
3827  ValueType value(const json_pointer& ptr, ValueType default_value) const
3828  {
3829  // at only works for objects
3830  if (is_object())
3831  {
3832  // if pointer resolves a value, return it or use default value
3833  try
3834  {
3835  return ptr.get_checked(this);
3836  }
3837  catch (std::out_of_range&)
3838  {
3839  return default_value;
3840  }
3841  }
3842  else
3843  {
3844  throw std::domain_error("cannot use value() with " + type_name());
3845  }
3846  }
3847 
3852  string_t value(const json_pointer& ptr, const char* default_value) const
3853  {
3854  return value(ptr, string_t(default_value));
3855  }
3856 
3882  {
3883  return *begin();
3884  }
3885 
3890  {
3891  return *cbegin();
3892  }
3893 
3924  {
3925  auto tmp = end();
3926  --tmp;
3927  return *tmp;
3928  }
3929 
3934  {
3935  auto tmp = cend();
3936  --tmp;
3937  return *tmp;
3938  }
3939 
3985  template <class InteratorType, typename
3986  std::enable_if<
3987  std::is_same<InteratorType, typename basic_json_t::iterator>::value or
3988  std::is_same<InteratorType, typename basic_json_t::const_iterator>::value
3989  , int>::type
3990  = 0>
3991  InteratorType erase(InteratorType pos)
3992  {
3993  // make sure iterator fits the current value
3994  if (this != pos.m_object)
3995  {
3996  throw std::domain_error("iterator does not fit current value");
3997  }
3998 
3999  InteratorType result = end();
4000 
4001  switch (m_type)
4002  {
4003  case value_t::boolean:
4004  case value_t::number_float:
4005  case value_t::number_integer:
4006  case value_t::number_unsigned:
4007  case value_t::string:
4008  {
4009  if (not pos.m_it.primitive_iterator.is_begin())
4010  {
4011  throw std::out_of_range("iterator out of range");
4012  }
4013 
4014  if (is_string())
4015  {
4016  AllocatorType<string_t> alloc;
4017  alloc.destroy(m_value.string);
4018  alloc.deallocate(m_value.string, 1);
4019  m_value.string = nullptr;
4020  }
4021 
4022  m_type = value_t::null;
4023  assert_invariant();
4024  break;
4025  }
4026 
4027  case value_t::object:
4028  {
4029  result.m_it.object_iterator = m_value.object->erase(pos.m_it.object_iterator);
4030  break;
4031  }
4032 
4033  case value_t::array:
4034  {
4035  result.m_it.array_iterator = m_value.array->erase(pos.m_it.array_iterator);
4036  break;
4037  }
4038 
4039  default:
4040  {
4041  throw std::domain_error("cannot use erase() with " + type_name());
4042  }
4043  }
4044 
4045  return result;
4046  }
4047 
4094  template <class InteratorType, typename
4095  std::enable_if<
4096  std::is_same<InteratorType, typename basic_json_t::iterator>::value or
4097  std::is_same<InteratorType, typename basic_json_t::const_iterator>::value
4098  , int>::type
4099  = 0>
4100  InteratorType erase(InteratorType first, InteratorType last)
4101  {
4102  // make sure iterator fits the current value
4103  if (this != first.m_object or this != last.m_object)
4104  {
4105  throw std::domain_error("iterators do not fit current value");
4106  }
4107 
4108  InteratorType result = end();
4109 
4110  switch (m_type)
4111  {
4112  case value_t::boolean:
4113  case value_t::number_float:
4114  case value_t::number_integer:
4115  case value_t::number_unsigned:
4116  case value_t::string:
4117  {
4118  if (not first.m_it.primitive_iterator.is_begin() or not last.m_it.primitive_iterator.is_end())
4119  {
4120  throw std::out_of_range("iterators out of range");
4121  }
4122 
4123  if (is_string())
4124  {
4125  AllocatorType<string_t> alloc;
4126  alloc.destroy(m_value.string);
4127  alloc.deallocate(m_value.string, 1);
4128  m_value.string = nullptr;
4129  }
4130 
4131  m_type = value_t::null;
4132  assert_invariant();
4133  break;
4134  }
4135 
4136  case value_t::object:
4137  {
4138  result.m_it.object_iterator = m_value.object->erase(first.m_it.object_iterator,
4139  last.m_it.object_iterator);
4140  break;
4141  }
4142 
4143  case value_t::array:
4144  {
4145  result.m_it.array_iterator = m_value.array->erase(first.m_it.array_iterator,
4146  last.m_it.array_iterator);
4147  break;
4148  }
4149 
4150  default:
4151  {
4152  throw std::domain_error("cannot use erase() with " + type_name());
4153  }
4154  }
4155 
4156  return result;
4157  }
4158 
4188  size_type erase(const typename object_t::key_type& key)
4189  {
4190  // this erase only works for objects
4191  if (is_object())
4192  {
4193  return m_value.object->erase(key);
4194  }
4195  else
4196  {
4197  throw std::domain_error("cannot use erase() with " + type_name());
4198  }
4199  }
4200 
4225  void erase(const size_type idx)
4226  {
4227  // this erase only works for arrays
4228  if (is_array())
4229  {
4230  if (idx >= size())
4231  {
4232  throw std::out_of_range("array index " + std::to_string(idx) + " is out of range");
4233  }
4234 
4235  m_value.array->erase(m_value.array->begin() + static_cast<difference_type>(idx));
4236  }
4237  else
4238  {
4239  throw std::domain_error("cannot use erase() with " + type_name());
4240  }
4241  }
4242 
4244 
4245 
4247  // lookup //
4249 
4252 
4271  iterator find(typename object_t::key_type key)
4272  {
4273  auto result = end();
4274 
4275  if (is_object())
4276  {
4277  result.m_it.object_iterator = m_value.object->find(key);
4278  }
4279 
4280  return result;
4281  }
4282 
4287  const_iterator find(typename object_t::key_type key) const
4288  {
4289  auto result = cend();
4290 
4291  if (is_object())
4292  {
4293  result.m_it.object_iterator = m_value.object->find(key);
4294  }
4295 
4296  return result;
4297  }
4298 
4317  size_type count(typename object_t::key_type key) const
4318  {
4319  // return 0 for all nonobject types
4320  return is_object() ? m_value.object->count(key) : 0;
4321  }
4322 
4324 
4325 
4327  // iterators //
4329 
4332 
4357  iterator begin() noexcept
4358  {
4359  iterator result(this);
4360  result.set_begin();
4361  return result;
4362  }
4363 
4367  const_iterator begin() const noexcept
4368  {
4369  return cbegin();
4370  }
4371 
4397  const_iterator cbegin() const noexcept
4398  {
4399  const_iterator result(this);
4400  result.set_begin();
4401  return result;
4402  }
4403 
4428  iterator end() noexcept
4429  {
4430  iterator result(this);
4431  result.set_end();
4432  return result;
4433  }
4434 
4438  const_iterator end() const noexcept
4439  {
4440  return cend();
4441  }
4442 
4468  const_iterator cend() const noexcept
4469  {
4470  const_iterator result(this);
4471  result.set_end();
4472  return result;
4473  }
4474 
4499  {
4500  return reverse_iterator(end());
4501  }
4502 
4507  {
4508  return crbegin();
4509  }
4510 
4536  {
4537  return reverse_iterator(begin());
4538  }
4539 
4543  const_reverse_iterator rend() const noexcept
4544  {
4545  return crend();
4546  }
4547 
4573  {
4574  return const_reverse_iterator(cend());
4575  }
4576 
4602  {
4603  return const_reverse_iterator(cbegin());
4604  }
4605 
4606  private:
4607  // forward declaration
4608  template<typename IteratorType> class iteration_proxy;
4609 
4610  public:
4622  static iteration_proxy<iterator> iterator_wrapper(reference cont)
4623  {
4624  return iteration_proxy<iterator>(cont);
4625  }
4626 
4630  static iteration_proxy<const_iterator> iterator_wrapper(const_reference cont)
4631  {
4632  return iteration_proxy<const_iterator>(cont);
4633  }
4634 
4636 
4637 
4639  // capacity //
4641 
4644 
4682  bool empty() const noexcept
4683  {
4684  switch (m_type)
4685  {
4686  case value_t::null:
4687  {
4688  // null values are empty
4689  return true;
4690  }
4691 
4692  case value_t::array:
4693  {
4694  // delegate call to array_t::empty()
4695  return m_value.array->empty();
4696  }
4697 
4698  case value_t::object:
4699  {
4700  // delegate call to object_t::empty()
4701  return m_value.object->empty();
4702  }
4703 
4704  default:
4705  {
4706  // all other types are nonempty
4707  return false;
4708  }
4709  }
4710  }
4711 
4750  size_type size() const noexcept
4751  {
4752  switch (m_type)
4753  {
4754  case value_t::null:
4755  {
4756  // null values are empty
4757  return 0;
4758  }
4759 
4760  case value_t::array:
4761  {
4762  // delegate call to array_t::size()
4763  return m_value.array->size();
4764  }
4765 
4766  case value_t::object:
4767  {
4768  // delegate call to object_t::size()
4769  return m_value.object->size();
4770  }
4771 
4772  default:
4773  {
4774  // all other types have size 1
4775  return 1;
4776  }
4777  }
4778  }
4779 
4816  size_type max_size() const noexcept
4817  {
4818  switch (m_type)
4819  {
4820  case value_t::array:
4821  {
4822  // delegate call to array_t::max_size()
4823  return m_value.array->max_size();
4824  }
4825 
4826  case value_t::object:
4827  {
4828  // delegate call to object_t::max_size()
4829  return m_value.object->max_size();
4830  }
4831 
4832  default:
4833  {
4834  // all other types have max_size() == size()
4835  return size();
4836  }
4837  }
4838  }
4839 
4841 
4842 
4844  // modifiers //
4846 
4849 
4875  void clear() noexcept
4876  {
4877  switch (m_type)
4878  {
4879  case value_t::number_integer:
4880  {
4881  m_value.number_integer = 0;
4882  break;
4883  }
4884 
4885  case value_t::number_unsigned:
4886  {
4887  m_value.number_unsigned = 0;
4888  break;
4889  }
4890 
4891  case value_t::number_float:
4892  {
4893  m_value.number_float = 0.0;
4894  break;
4895  }
4896 
4897  case value_t::boolean:
4898  {
4899  m_value.boolean = false;
4900  break;
4901  }
4902 
4903  case value_t::string:
4904  {
4905  m_value.string->clear();
4906  break;
4907  }
4908 
4909  case value_t::array:
4910  {
4911  m_value.array->clear();
4912  break;
4913  }
4914 
4915  case value_t::object:
4916  {
4917  m_value.object->clear();
4918  break;
4919  }
4920 
4921  default:
4922  {
4923  break;
4924  }
4925  }
4926  }
4927 
4948  void push_back(basic_json&& val)
4949  {
4950  // push_back only works for null objects or arrays
4951  if (not(is_null() or is_array()))
4952  {
4953  throw std::domain_error("cannot use push_back() with " + type_name());
4954  }
4955 
4956  // transform null object into an array
4957  if (is_null())
4958  {
4959  m_type = value_t::array;
4960  m_value = value_t::array;
4961  assert_invariant();
4962  }
4963 
4964  // add element to array (move semantics)
4965  m_value.array->push_back(std::move(val));
4966  // invalidate object
4967  val.m_type = value_t::null;
4968  }
4969 
4975  {
4976  push_back(std::move(val));
4977  return *this;
4978  }
4979 
4984  void push_back(const basic_json& val)
4985  {
4986  // push_back only works for null objects or arrays
4987  if (not(is_null() or is_array()))
4988  {
4989  throw std::domain_error("cannot use push_back() with " + type_name());
4990  }
4991 
4992  // transform null object into an array
4993  if (is_null())
4994  {
4995  m_type = value_t::array;
4996  m_value = value_t::array;
4997  assert_invariant();
4998  }
4999 
5000  // add element to array
5001  m_value.array->push_back(val);
5002  }
5003 
5009  {
5010  push_back(val);
5011  return *this;
5012  }
5013 
5034  void push_back(const typename object_t::value_type& val)
5035  {
5036  // push_back only works for null objects or objects
5037  if (not(is_null() or is_object()))
5038  {
5039  throw std::domain_error("cannot use push_back() with " + type_name());
5040  }
5041 
5042  // transform null object into an object
5043  if (is_null())
5044  {
5045  m_type = value_t::object;
5046  m_value = value_t::object;
5047  assert_invariant();
5048  }
5049 
5050  // add element to array
5051  m_value.object->insert(val);
5052  }
5053 
5058  reference operator+=(const typename object_t::value_type& val)
5059  {
5060  push_back(val);
5061  return *this;
5062  }
5063 
5089  void push_back(std::initializer_list<basic_json> init)
5090  {
5091  if (is_object() and init.size() == 2 and init.begin()->is_string())
5092  {
5093  const string_t key = *init.begin();
5094  push_back(typename object_t::value_type(key, *(init.begin() + 1)));
5095  }
5096  else
5097  {
5098  push_back(basic_json(init));
5099  }
5100  }
5101 
5106  reference operator+=(std::initializer_list<basic_json> init)
5107  {
5108  push_back(init);
5109  return *this;
5110  }
5111 
5135  {
5136  // insert only works for arrays
5137  if (is_array())
5138  {
5139  // check if iterator pos fits to this JSON value
5140  if (pos.m_object != this)
5141  {
5142  throw std::domain_error("iterator does not fit current value");
5143  }
5144 
5145  // insert to array and return iterator
5146  iterator result(this);
5147  result.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator, val);
5148  return result;
5149  }
5150  else
5151  {
5152  throw std::domain_error("cannot use insert() with " + type_name());
5153  }
5154  }
5155 
5161  {
5162  return insert(pos, val);
5163  }
5164 
5190  {
5191  // insert only works for arrays
5192  if (is_array())
5193  {
5194  // check if iterator pos fits to this JSON value
5195  if (pos.m_object != this)
5196  {
5197  throw std::domain_error("iterator does not fit current value");
5198  }
5199 
5200  // insert to array and return iterator
5201  iterator result(this);
5202  result.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator, cnt, val);
5203  return result;
5204  }
5205  else
5206  {
5207  throw std::domain_error("cannot use insert() with " + type_name());
5208  }
5209  }
5210 
5242  {
5243  // insert only works for arrays
5244  if (not is_array())
5245  {
5246  throw std::domain_error("cannot use insert() with " + type_name());
5247  }
5248 
5249  // check if iterator pos fits to this JSON value
5250  if (pos.m_object != this)
5251  {
5252  throw std::domain_error("iterator does not fit current value");
5253  }
5254 
5255  // check if range iterators belong to the same JSON object
5256  if (first.m_object != last.m_object)
5257  {
5258  throw std::domain_error("iterators do not fit");
5259  }
5260 
5261  if (first.m_object == this or last.m_object == this)
5262  {
5263  throw std::domain_error("passed iterators may not belong to container");
5264  }
5265 
5266  // insert to array and return iterator
5267  iterator result(this);
5268  result.m_it.array_iterator = m_value.array->insert(
5269  pos.m_it.array_iterator,
5270  first.m_it.array_iterator,
5271  last.m_it.array_iterator);
5272  return result;
5273  }
5274 
5299  iterator insert(const_iterator pos, std::initializer_list<basic_json> ilist)
5300  {
5301  // insert only works for arrays
5302  if (not is_array())
5303  {
5304  throw std::domain_error("cannot use insert() with " + type_name());
5305  }
5306 
5307  // check if iterator pos fits to this JSON value
5308  if (pos.m_object != this)
5309  {
5310  throw std::domain_error("iterator does not fit current value");
5311  }
5312 
5313  // insert to array and return iterator
5314  iterator result(this);
5315  result.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator, ilist);
5316  return result;
5317  }
5318 
5336  void swap(reference other) noexcept (
5337  std::is_nothrow_move_constructible<value_t>::value and
5338  std::is_nothrow_move_assignable<value_t>::value and
5339  std::is_nothrow_move_constructible<json_value>::value and
5340  std::is_nothrow_move_assignable<json_value>::value
5341  )
5342  {
5343  std::swap(m_type, other.m_type);
5344  std::swap(m_value, other.m_value);
5345  assert_invariant();
5346  }
5347 
5368  void swap(array_t& other)
5369  {
5370  // swap only works for arrays
5371  if (is_array())
5372  {
5373  std::swap(*(m_value.array), other);
5374  }
5375  else
5376  {
5377  throw std::domain_error("cannot use swap() with " + type_name());
5378  }
5379  }
5380 
5401  void swap(object_t& other)
5402  {
5403  // swap only works for objects
5404  if (is_object())
5405  {
5406  std::swap(*(m_value.object), other);
5407  }
5408  else
5409  {
5410  throw std::domain_error("cannot use swap() with " + type_name());
5411  }
5412  }
5413 
5434  void swap(string_t& other)
5435  {
5436  // swap only works for strings
5437  if (is_string())
5438  {
5439  std::swap(*(m_value.string), other);
5440  }
5441  else
5442  {
5443  throw std::domain_error("cannot use swap() with " + type_name());
5444  }
5445  }
5446 
5448 
5449 
5451  // lexicographical comparison operators //
5453 
5456 
5457  private:
5467  friend bool operator<(const value_t lhs, const value_t rhs) noexcept
5468  {
5469  static constexpr std::array<uint8_t, 8> order = {{
5470  0, // null
5471  3, // object
5472  4, // array
5473  5, // string
5474  1, // boolean
5475  2, // integer
5476  2, // unsigned
5477  2, // float
5478  }
5479  };
5480 
5481  // discarded values are not comparable
5482  if (lhs == value_t::discarded or rhs == value_t::discarded)
5483  {
5484  return false;
5485  }
5486 
5487  return order[static_cast<std::size_t>(lhs)] < order[static_cast<std::size_t>(rhs)];
5488  }
5489 
5490  public:
5514  friend bool operator==(const_reference lhs, const_reference rhs) noexcept
5515  {
5516  const auto lhs_type = lhs.type();
5517  const auto rhs_type = rhs.type();
5518 
5519  if (lhs_type == rhs_type)
5520  {
5521  switch (lhs_type)
5522  {
5523  case value_t::array:
5524  {
5525  return *lhs.m_value.array == *rhs.m_value.array;
5526  }
5527  case value_t::object:
5528  {
5529  return *lhs.m_value.object == *rhs.m_value.object;
5530  }
5531  case value_t::null:
5532  {
5533  return true;
5534  }
5535  case value_t::string:
5536  {
5537  return *lhs.m_value.string == *rhs.m_value.string;
5538  }
5539  case value_t::boolean:
5540  {
5541  return lhs.m_value.boolean == rhs.m_value.boolean;
5542  }
5543  case value_t::number_integer:
5544  {
5545  return lhs.m_value.number_integer == rhs.m_value.number_integer;
5546  }
5547  case value_t::number_unsigned:
5548  {
5549  return lhs.m_value.number_unsigned == rhs.m_value.number_unsigned;
5550  }
5551  case value_t::number_float:
5552  {
5553  return lhs.m_value.number_float == rhs.m_value.number_float;
5554  }
5555  default:
5556  {
5557  return false;
5558  }
5559  }
5560  }
5561  else if (lhs_type == value_t::number_integer and rhs_type == value_t::number_float)
5562  {
5563  return static_cast<number_float_t>(lhs.m_value.number_integer) == rhs.m_value.number_float;
5564  }
5565  else if (lhs_type == value_t::number_float and rhs_type == value_t::number_integer)
5566  {
5567  return lhs.m_value.number_float == static_cast<number_float_t>(rhs.m_value.number_integer);
5568  }
5569  else if (lhs_type == value_t::number_unsigned and rhs_type == value_t::number_float)
5570  {
5571  return static_cast<number_float_t>(lhs.m_value.number_unsigned) == rhs.m_value.number_float;
5572  }
5573  else if (lhs_type == value_t::number_float and rhs_type == value_t::number_unsigned)
5574  {
5575  return lhs.m_value.number_float == static_cast<number_float_t>(rhs.m_value.number_unsigned);
5576  }
5577  else if (lhs_type == value_t::number_unsigned and rhs_type == value_t::number_integer)
5578  {
5579  return static_cast<number_integer_t>(lhs.m_value.number_unsigned) == rhs.m_value.number_integer;
5580  }
5581  else if (lhs_type == value_t::number_integer and rhs_type == value_t::number_unsigned)
5582  {
5583  return lhs.m_value.number_integer == static_cast<number_integer_t>(rhs.m_value.number_unsigned);
5584  }
5585 
5586  return false;
5587  }
5588 
5607  friend bool operator==(const_reference v, std::nullptr_t) noexcept
5608  {
5609  return v.is_null();
5610  }
5611 
5616  friend bool operator==(std::nullptr_t, const_reference v) noexcept
5617  {
5618  return v.is_null();
5619  }
5620 
5637  friend bool operator!=(const_reference lhs, const_reference rhs) noexcept
5638  {
5639  return not (lhs == rhs);
5640  }
5641 
5660  friend bool operator!=(const_reference v, std::nullptr_t) noexcept
5661  {
5662  return not v.is_null();
5663  }
5664 
5669  friend bool operator!=(std::nullptr_t, const_reference v) noexcept
5670  {
5671  return not v.is_null();
5672  }
5673 
5698  friend bool operator<(const_reference lhs, const_reference rhs) noexcept
5699  {
5700  const auto lhs_type = lhs.type();
5701  const auto rhs_type = rhs.type();
5702 
5703  if (lhs_type == rhs_type)
5704  {
5705  switch (lhs_type)
5706  {
5707  case value_t::array:
5708  {
5709  return *lhs.m_value.array < *rhs.m_value.array;
5710  }
5711  case value_t::object:
5712  {
5713  return *lhs.m_value.object < *rhs.m_value.object;
5714  }
5715  case value_t::null:
5716  {
5717  return false;
5718  }
5719  case value_t::string:
5720  {
5721  return *lhs.m_value.string < *rhs.m_value.string;
5722  }
5723  case value_t::boolean:
5724  {
5725  return lhs.m_value.boolean < rhs.m_value.boolean;
5726  }
5727  case value_t::number_integer:
5728  {
5729  return lhs.m_value.number_integer < rhs.m_value.number_integer;
5730  }
5731  case value_t::number_unsigned:
5732  {
5733  return lhs.m_value.number_unsigned < rhs.m_value.number_unsigned;
5734  }
5735  case value_t::number_float:
5736  {
5737  return lhs.m_value.number_float < rhs.m_value.number_float;
5738  }
5739  default:
5740  {
5741  return false;
5742  }
5743  }
5744  }
5745  else if (lhs_type == value_t::number_integer and rhs_type == value_t::number_float)
5746  {
5747  return static_cast<number_float_t>(lhs.m_value.number_integer) < rhs.m_value.number_float;
5748  }
5749  else if (lhs_type == value_t::number_float and rhs_type == value_t::number_integer)
5750  {
5751  return lhs.m_value.number_float < static_cast<number_float_t>(rhs.m_value.number_integer);
5752  }
5753  else if (lhs_type == value_t::number_unsigned and rhs_type == value_t::number_float)
5754  {
5755  return static_cast<number_float_t>(lhs.m_value.number_unsigned) < rhs.m_value.number_float;
5756  }
5757  else if (lhs_type == value_t::number_float and rhs_type == value_t::number_unsigned)
5758  {
5759  return lhs.m_value.number_float < static_cast<number_float_t>(rhs.m_value.number_unsigned);
5760  }
5761  else if (lhs_type == value_t::number_integer and rhs_type == value_t::number_unsigned)
5762  {
5763  return lhs.m_value.number_integer < static_cast<number_integer_t>(rhs.m_value.number_unsigned);
5764  }
5765  else if (lhs_type == value_t::number_unsigned and rhs_type == value_t::number_integer)
5766  {
5767  return static_cast<number_integer_t>(lhs.m_value.number_unsigned) < rhs.m_value.number_integer;
5768  }
5769 
5770  // We only reach this line if we cannot compare values. In that case,
5771  // we compare types. Note we have to call the operator explicitly,
5772  // because MSVC has problems otherwise.
5773  return operator<(lhs_type, rhs_type);
5774  }
5775 
5793  friend bool operator<=(const_reference lhs, const_reference rhs) noexcept
5794  {
5795  return not (rhs < lhs);
5796  }
5797 
5815  friend bool operator>(const_reference lhs, const_reference rhs) noexcept
5816  {
5817  return not (lhs <= rhs);
5818  }
5819 
5837  friend bool operator>=(const_reference lhs, const_reference rhs) noexcept
5838  {
5839  return not (lhs < rhs);
5840  }
5841 
5843 
5844 
5846  // serialization //
5848 
5851 
5878  friend std::ostream& operator<<(std::ostream& o, const basic_json& j)
5879  {
5880  // read width member and use it as indentation parameter if nonzero
5881  const bool pretty_print = (o.width() > 0);
5882  const auto indentation = (pretty_print ? o.width() : 0);
5883 
5884  // reset width to 0 for subsequent calls to this stream
5885  o.width(0);
5886 
5887  // fix locale problems
5888  const auto old_locale = o.imbue(std::locale(std::locale(), new DecimalSeparator));
5889  // set precision
5890 
5891  // 6, 15 or 16 digits of precision allows round-trip IEEE 754
5892  // string->float->string, string->double->string or string->long
5893  // double->string; to be safe, we read this value from
5894  // std::numeric_limits<number_float_t>::digits10
5895  const auto old_precision = o.precision(std::numeric_limits<double>::digits10);
5896 
5897  // do the actual serialization
5898  j.dump(o, pretty_print, static_cast<unsigned int>(indentation));
5899 
5900  // reset locale and precision
5901  o.imbue(old_locale);
5902  o.precision(old_precision);
5903  return o;
5904  }
5905 
5910  friend std::ostream& operator>>(const basic_json& j, std::ostream& o)
5911  {
5912  return o << j;
5913  }
5914 
5916 
5917 
5919  // deserialization //
5921 
5924 
5949  static basic_json parse(const string_t& s,
5950  const parser_callback_t cb = nullptr)
5951  {
5952  return parser(s, cb).parse();
5953  }
5954 
5979  static basic_json parse(std::istream& i,
5980  const parser_callback_t cb = nullptr)
5981  {
5982  return parser(i, cb).parse();
5983  }
5984 
5988  static basic_json parse(std::istream&& i,
5989  const parser_callback_t cb = nullptr)
5990  {
5991  return parser(i, cb).parse();
5992  }
5993 
6017  friend std::istream& operator<<(basic_json& j, std::istream& i)
6018  {
6019  j = parser(i).parse();
6020  return i;
6021  }
6022 
6027  friend std::istream& operator>>(std::istream& i, basic_json& j)
6028  {
6029  j = parser(i).parse();
6030  return i;
6031  }
6032 
6034 
6035 
6036  private:
6038  // convenience functions //
6040 
6053  std::string type_name() const
6054  {
6055  switch (m_type)
6056  {
6057  case value_t::null:
6058  return "null";
6059  case value_t::object:
6060  return "object";
6061  case value_t::array:
6062  return "array";
6063  case value_t::string:
6064  return "string";
6065  case value_t::boolean:
6066  return "boolean";
6067  case value_t::discarded:
6068  return "discarded";
6069  default:
6070  return "number";
6071  }
6072  }
6073 
6082  static std::size_t extra_space(const string_t& s) noexcept
6083  {
6084  return std::accumulate(s.begin(), s.end(), size_t{},
6085  [](size_t res, typename string_t::value_type c)
6086  {
6087  switch (c)
6088  {
6089  case '"':
6090  case '\\':
6091  case '\b':
6092  case '\f':
6093  case '\n':
6094  case '\r':
6095  case '\t':
6096  {
6097  // from c (1 byte) to \x (2 bytes)
6098  return res + 1;
6099  }
6100 
6101  default:
6102  {
6103  if (c >= 0x00 and c <= 0x1f)
6104  {
6105  // from c (1 byte) to \uxxxx (6 bytes)
6106  return res + 5;
6107  }
6108  else
6109  {
6110  return res;
6111  }
6112  }
6113  }
6114  });
6115  }
6116 
6130  static string_t escape_string(const string_t& s)
6131  {
6132  const auto space = extra_space(s);
6133  if (space == 0)
6134  {
6135  return s;
6136  }
6137 
6138  // create a result string of necessary size
6139  string_t result(s.size() + space, '\\');
6140  std::size_t pos = 0;
6141 
6142  for (const auto& c : s)
6143  {
6144  switch (c)
6145  {
6146  // quotation mark (0x22)
6147  case '"':
6148  {
6149  result[pos + 1] = '"';
6150  pos += 2;
6151  break;
6152  }
6153 
6154  // reverse solidus (0x5c)
6155  case '\\':
6156  {
6157  // nothing to change
6158  pos += 2;
6159  break;
6160  }
6161 
6162  // backspace (0x08)
6163  case '\b':
6164  {
6165  result[pos + 1] = 'b';
6166  pos += 2;
6167  break;
6168  }
6169 
6170  // formfeed (0x0c)
6171  case '\f':
6172  {
6173  result[pos + 1] = 'f';
6174  pos += 2;
6175  break;
6176  }
6177 
6178  // newline (0x0a)
6179  case '\n':
6180  {
6181  result[pos + 1] = 'n';
6182  pos += 2;
6183  break;
6184  }
6185 
6186  // carriage return (0x0d)
6187  case '\r':
6188  {
6189  result[pos + 1] = 'r';
6190  pos += 2;
6191  break;
6192  }
6193 
6194  // horizontal tab (0x09)
6195  case '\t':
6196  {
6197  result[pos + 1] = 't';
6198  pos += 2;
6199  break;
6200  }
6201 
6202  default:
6203  {
6204  if (c >= 0x00 and c <= 0x1f)
6205  {
6206  // convert a number 0..15 to its hex representation
6207  // (0..f)
6208  static const char hexify[16] =
6209  {
6210  '0', '1', '2', '3', '4', '5', '6', '7',
6211  '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'
6212  };
6213 
6214  // print character c as \uxxxx
6215  for (const char m :
6216  { 'u', '0', '0', hexify[c >> 4], hexify[c & 0x0f]
6217  })
6218  {
6219  result[++pos] = m;
6220  }
6221 
6222  ++pos;
6223  }
6224  else
6225  {
6226  // all other characters are added as-is
6227  result[pos++] = c;
6228  }
6229  break;
6230  }
6231  }
6232  }
6233 
6234  return result;
6235  }
6236 
6254  void dump(std::ostream& o,
6255  const bool pretty_print,
6256  const unsigned int indent_step,
6257  const unsigned int current_indent = 0) const
6258  {
6259  // variable to hold indentation for recursive calls
6260  unsigned int new_indent = current_indent;
6261 
6262  switch (m_type)
6263  {
6264  case value_t::object:
6265  {
6266  if (m_value.object->empty())
6267  {
6268  o << "{}";
6269  return;
6270  }
6271 
6272  o << "{";
6273 
6274  // increase indentation
6275  if (pretty_print)
6276  {
6277  new_indent += indent_step;
6278  o << "\n";
6279  }
6280 
6281  for (auto i = m_value.object->cbegin(); i != m_value.object->cend(); ++i)
6282  {
6283  if (i != m_value.object->cbegin())
6284  {
6285  o << (pretty_print ? ",\n" : ",");
6286  }
6287  o << string_t(new_indent, ' ') << "\""
6288  << escape_string(i->first) << "\":"
6289  << (pretty_print ? " " : "");
6290  i->second.dump(o, pretty_print, indent_step, new_indent);
6291  }
6292 
6293  // decrease indentation
6294  if (pretty_print)
6295  {
6296  new_indent -= indent_step;
6297  o << "\n";
6298  }
6299 
6300  o << string_t(new_indent, ' ') + "}";
6301  return;
6302  }
6303 
6304  case value_t::array:
6305  {
6306  if (m_value.array->empty())
6307  {
6308  o << "[]";
6309  return;
6310  }
6311 
6312  o << "[";
6313 
6314  // increase indentation
6315  if (pretty_print)
6316  {
6317  new_indent += indent_step;
6318  o << "\n";
6319  }
6320 
6321  for (auto i = m_value.array->cbegin(); i != m_value.array->cend(); ++i)
6322  {
6323  if (i != m_value.array->cbegin())
6324  {
6325  o << (pretty_print ? ",\n" : ",");
6326  }
6327  o << string_t(new_indent, ' ');
6328  i->dump(o, pretty_print, indent_step, new_indent);
6329  }
6330 
6331  // decrease indentation
6332  if (pretty_print)
6333  {
6334  new_indent -= indent_step;
6335  o << "\n";
6336  }
6337 
6338  o << string_t(new_indent, ' ') << "]";
6339  return;
6340  }
6341 
6342  case value_t::string:
6343  {
6344  o << string_t("\"") << escape_string(*m_value.string) << "\"";
6345  return;
6346  }
6347 
6348  case value_t::boolean:
6349  {
6350  o << (m_value.boolean ? "true" : "false");
6351  return;
6352  }
6353 
6354  case value_t::number_integer:
6355  {
6356  o << m_value.number_integer;
6357  return;
6358  }
6359 
6360  case value_t::number_unsigned:
6361  {
6362  o << m_value.number_unsigned;
6363  return;
6364  }
6365 
6366  case value_t::number_float:
6367  {
6368  if (m_value.number_float == 0)
6369  {
6370  // special case for zero to get "0.0"/"-0.0"
6371  o << (std::signbit(m_value.number_float) ? "-0.0" : "0.0");
6372  }
6373  else
6374  {
6375  o << m_value.number_float;
6376  }
6377  return;
6378  }
6379 
6380  case value_t::discarded:
6381  {
6382  o << "<discarded>";
6383  return;
6384  }
6385 
6386  case value_t::null:
6387  {
6388  o << "null";
6389  return;
6390  }
6391  }
6392  }
6393 
6394  private:
6396  // member variables //
6398 
6400  value_t m_type = value_t::null;
6401 
6403  json_value m_value = {};
6404 
6405 
6406  private:
6408  // iterators //
6410 
6420  class primitive_iterator_t
6421  {
6422  public:
6424  void set_begin() noexcept
6425  {
6426  m_it = begin_value;
6427  }
6428 
6430  void set_end() noexcept
6431  {
6432  m_it = end_value;
6433  }
6434 
6436  constexpr bool is_begin() const noexcept
6437  {
6438  return (m_it == begin_value);
6439  }
6440 
6442  constexpr bool is_end() const noexcept
6443  {
6444  return (m_it == end_value);
6445  }
6446 
6448  operator difference_type& () noexcept
6449  {
6450  return m_it;
6451  }
6452 
6454  constexpr operator difference_type () const noexcept
6455  {
6456  return m_it;
6457  }
6458 
6459  private:
6460  static constexpr difference_type begin_value = 0;
6461  static constexpr difference_type end_value = begin_value + 1;
6462 
6464  difference_type m_it = std::numeric_limits<std::ptrdiff_t>::denorm_min();
6465  };
6466 
6474  struct internal_iterator
6475  {
6477  typename object_t::iterator object_iterator;
6479  typename array_t::iterator array_iterator;
6481  primitive_iterator_t primitive_iterator;
6482 
6484  internal_iterator() noexcept
6485  : object_iterator(), array_iterator(), primitive_iterator()
6486  {}
6487  };
6488 
6490  template<typename IteratorType>
6491  class iteration_proxy
6492  {
6493  private:
6495  class iteration_proxy_internal
6496  {
6497  private:
6499  IteratorType anchor;
6501  size_t array_index = 0;
6502 
6503  public:
6504  explicit iteration_proxy_internal(IteratorType it) noexcept
6505  : anchor(it)
6506  {}
6507 
6509  iteration_proxy_internal& operator*()
6510  {
6511  return *this;
6512  }
6513 
6515  iteration_proxy_internal& operator++()
6516  {
6517  ++anchor;
6518  ++array_index;
6519 
6520  return *this;
6521  }
6522 
6524  bool operator!= (const iteration_proxy_internal& o) const
6525  {
6526  return anchor != o.anchor;
6527  }
6528 
6530  typename basic_json::string_t key() const
6531  {
6532  assert(anchor.m_object != nullptr);
6533 
6534  switch (anchor.m_object->type())
6535  {
6536  // use integer array index as key
6537  case value_t::array:
6538  {
6539  return std::to_string(array_index);
6540  }
6541 
6542  // use key from the object
6543  case value_t::object:
6544  {
6545  return anchor.key();
6546  }
6547 
6548  // use an empty key for all primitive types
6549  default:
6550  {
6551  return "";
6552  }
6553  }
6554  }
6555 
6557  typename IteratorType::reference value() const
6558  {
6559  return anchor.value();
6560  }
6561  };
6562 
6564  typename IteratorType::reference container;
6565 
6566  public:
6568  explicit iteration_proxy(typename IteratorType::reference cont)
6569  : container(cont)
6570  {}
6571 
6573  iteration_proxy_internal begin() noexcept
6574  {
6575  return iteration_proxy_internal(container.begin());
6576  }
6577 
6579  iteration_proxy_internal end() noexcept
6580  {
6581  return iteration_proxy_internal(container.end());
6582  }
6583  };
6584 
6585  public:
6605  class const_iterator : public std::iterator<std::random_access_iterator_tag, const basic_json>
6606  {
6608  friend class basic_json;
6609 
6610  public:
6620  using iterator_category = std::bidirectional_iterator_tag;
6621 
6623  const_iterator() = default;
6624 
6631  explicit const_iterator(pointer object) noexcept
6632  : m_object(object)
6633  {
6634  assert(m_object != nullptr);
6635 
6636  switch (m_object->m_type)
6637  {
6639  {
6640  m_it.object_iterator = typename object_t::iterator();
6641  break;
6642  }
6643 
6645  {
6646  m_it.array_iterator = typename array_t::iterator();
6647  break;
6648  }
6649 
6650  default:
6651  {
6652  m_it.primitive_iterator = primitive_iterator_t();
6653  break;
6654  }
6655  }
6656  }
6657 
6663  explicit const_iterator(const iterator& other) noexcept
6664  : m_object(other.m_object)
6665  {
6666  if (m_object != nullptr)
6667  {
6668  switch (m_object->m_type)
6669  {
6671  {
6672  m_it.object_iterator = other.m_it.object_iterator;
6673  break;
6674  }
6675 
6677  {
6678  m_it.array_iterator = other.m_it.array_iterator;
6679  break;
6680  }
6681 
6682  default:
6683  {
6684  m_it.primitive_iterator = other.m_it.primitive_iterator;
6685  break;
6686  }
6687  }
6688  }
6689  }
6690 
6696  const_iterator(const const_iterator& other) noexcept
6697  : m_object(other.m_object), m_it(other.m_it)
6698  {}
6699 
6706  std::is_nothrow_move_constructible<pointer>::value and
6707  std::is_nothrow_move_assignable<pointer>::value and
6708  std::is_nothrow_move_constructible<internal_iterator>::value and
6709  std::is_nothrow_move_assignable<internal_iterator>::value
6710  )
6711  {
6712  std::swap(m_object, other.m_object);
6713  std::swap(m_it, other.m_it);
6714  return *this;
6715  }
6716 
6717  private:
6722  void set_begin() noexcept
6723  {
6724  assert(m_object != nullptr);
6725 
6726  switch (m_object->m_type)
6727  {
6729  {
6730  m_it.object_iterator = m_object->m_value.object->begin();
6731  break;
6732  }
6733 
6735  {
6736  m_it.array_iterator = m_object->m_value.array->begin();
6737  break;
6738  }
6739 
6741  {
6742  // set to end so begin()==end() is true: null is empty
6743  m_it.primitive_iterator.set_end();
6744  break;
6745  }
6746 
6747  default:
6748  {
6749  m_it.primitive_iterator.set_begin();
6750  break;
6751  }
6752  }
6753  }
6754 
6759  void set_end() noexcept
6760  {
6761  assert(m_object != nullptr);
6762 
6763  switch (m_object->m_type)
6764  {
6766  {
6767  m_it.object_iterator = m_object->m_value.object->end();
6768  break;
6769  }
6770 
6772  {
6773  m_it.array_iterator = m_object->m_value.array->end();
6774  break;
6775  }
6776 
6777  default:
6778  {
6779  m_it.primitive_iterator.set_end();
6780  break;
6781  }
6782  }
6783  }
6784 
6785  public:
6791  {
6792  assert(m_object != nullptr);
6793 
6794  switch (m_object->m_type)
6795  {
6797  {
6798  assert(m_it.object_iterator != m_object->m_value.object->end());
6799  return m_it.object_iterator->second;
6800  }
6801 
6803  {
6804  assert(m_it.array_iterator != m_object->m_value.array->end());
6805  return *m_it.array_iterator;
6806  }
6807 
6809  {
6810  throw std::out_of_range("cannot get value");
6811  }
6812 
6813  default:
6814  {
6815  if (m_it.primitive_iterator.is_begin())
6816  {
6817  return *m_object;
6818  }
6819  else
6820  {
6821  throw std::out_of_range("cannot get value");
6822  }
6823  }
6824  }
6825  }
6826 
6832  {
6833  assert(m_object != nullptr);
6834 
6835  switch (m_object->m_type)
6836  {
6838  {
6839  assert(m_it.object_iterator != m_object->m_value.object->end());
6840  return &(m_it.object_iterator->second);
6841  }
6842 
6844  {
6845  assert(m_it.array_iterator != m_object->m_value.array->end());
6846  return &*m_it.array_iterator;
6847  }
6848 
6849  default:
6850  {
6851  if (m_it.primitive_iterator.is_begin())
6852  {
6853  return m_object;
6854  }
6855  else
6856  {
6857  throw std::out_of_range("cannot get value");
6858  }
6859  }
6860  }
6861  }
6862 
6868  {
6869  auto result = *this;
6870  ++(*this);
6871  return result;
6872  }
6873 
6879  {
6880  assert(m_object != nullptr);
6881 
6882  switch (m_object->m_type)
6883  {
6885  {
6886  std::advance(m_it.object_iterator, 1);
6887  break;
6888  }
6889 
6891  {
6892  std::advance(m_it.array_iterator, 1);
6893  break;
6894  }
6895 
6896  default:
6897  {
6898  ++m_it.primitive_iterator;
6899  break;
6900  }
6901  }
6902 
6903  return *this;
6904  }
6905 
6911  {
6912  auto result = *this;
6913  --(*this);
6914  return result;
6915  }
6916 
6922  {
6923  assert(m_object != nullptr);
6924 
6925  switch (m_object->m_type)
6926  {
6928  {
6929  std::advance(m_it.object_iterator, -1);
6930  break;
6931  }
6932 
6934  {
6935  std::advance(m_it.array_iterator, -1);
6936  break;
6937  }
6938 
6939  default:
6940  {
6941  --m_it.primitive_iterator;
6942  break;
6943  }
6944  }
6945 
6946  return *this;
6947  }
6948 
6953  bool operator==(const const_iterator& other) const
6954  {
6955  // if objects are not the same, the comparison is undefined
6956  if (m_object != other.m_object)
6957  {
6958  throw std::domain_error("cannot compare iterators of different containers");
6959  }
6960 
6961  assert(m_object != nullptr);
6962 
6963  switch (m_object->m_type)
6964  {
6966  {
6967  return (m_it.object_iterator == other.m_it.object_iterator);
6968  }
6969 
6971  {
6972  return (m_it.array_iterator == other.m_it.array_iterator);
6973  }
6974 
6975  default:
6976  {
6977  return (m_it.primitive_iterator == other.m_it.primitive_iterator);
6978  }
6979  }
6980  }
6981 
6986  bool operator!=(const const_iterator& other) const
6987  {
6988  return not operator==(other);
6989  }
6990 
6995  bool operator<(const const_iterator& other) const
6996  {
6997  // if objects are not the same, the comparison is undefined
6998  if (m_object != other.m_object)
6999  {
7000  throw std::domain_error("cannot compare iterators of different containers");
7001  }
7002 
7003  assert(m_object != nullptr);
7004 
7005  switch (m_object->m_type)
7006  {
7008  {
7009  throw std::domain_error("cannot compare order of object iterators");
7010  }
7011 
7013  {
7014  return (m_it.array_iterator < other.m_it.array_iterator);
7015  }
7016 
7017  default:
7018  {
7019  return (m_it.primitive_iterator < other.m_it.primitive_iterator);
7020  }
7021  }
7022  }
7023 
7028  bool operator<=(const const_iterator& other) const
7029  {
7030  return not other.operator < (*this);
7031  }
7032 
7037  bool operator>(const const_iterator& other) const
7038  {
7039  return not operator<=(other);
7040  }
7041 
7046  bool operator>=(const const_iterator& other) const
7047  {
7048  return not operator<(other);
7049  }
7050 
7056  {
7057  assert(m_object != nullptr);
7058 
7059  switch (m_object->m_type)
7060  {
7062  {
7063  throw std::domain_error("cannot use offsets with object iterators");
7064  }
7065 
7067  {
7068  std::advance(m_it.array_iterator, i);
7069  break;
7070  }
7071 
7072  default:
7073  {
7074  m_it.primitive_iterator += i;
7075  break;
7076  }
7077  }
7078 
7079  return *this;
7080  }
7081 
7087  {
7088  return operator+=(-i);
7089  }
7090 
7096  {
7097  auto result = *this;
7098  result += i;
7099  return result;
7100  }
7101 
7107  {
7108  auto result = *this;
7109  result -= i;
7110  return result;
7111  }
7112 
7118  {
7119  assert(m_object != nullptr);
7120 
7121  switch (m_object->m_type)
7122  {
7124  {
7125  throw std::domain_error("cannot use offsets with object iterators");
7126  }
7127 
7129  {
7130  return m_it.array_iterator - other.m_it.array_iterator;
7131  }
7132 
7133  default:
7134  {
7135  return m_it.primitive_iterator - other.m_it.primitive_iterator;
7136  }
7137  }
7138  }
7139 
7145  {
7146  assert(m_object != nullptr);
7147 
7148  switch (m_object->m_type)
7149  {
7151  {
7152  throw std::domain_error("cannot use operator[] for object iterators");
7153  }
7154 
7156  {
7157  return *std::next(m_it.array_iterator, n);
7158  }
7159 
7161  {
7162  throw std::out_of_range("cannot get value");
7163  }
7164 
7165  default:
7166  {
7167  if (m_it.primitive_iterator == -n)
7168  {
7169  return *m_object;
7170  }
7171  else
7172  {
7173  throw std::out_of_range("cannot get value");
7174  }
7175  }
7176  }
7177  }
7178 
7183  typename object_t::key_type key() const
7184  {
7185  assert(m_object != nullptr);
7186 
7187  if (m_object->is_object())
7188  {
7189  return m_it.object_iterator->first;
7190  }
7191  else
7192  {
7193  throw std::domain_error("cannot use key() for non-object iterators");
7194  }
7195  }
7196 
7202  {
7203  return operator*();
7204  }
7205 
7206  private:
7208  pointer m_object = nullptr;
7210  internal_iterator m_it = internal_iterator();
7211  };
7212 
7225  class iterator : public const_iterator
7226  {
7227  public:
7229  using pointer = typename basic_json::pointer;
7231 
7233  iterator() = default;
7234 
7236  explicit iterator(pointer object) noexcept
7237  : base_iterator(object)
7238  {}
7239 
7241  iterator(const iterator& other) noexcept
7242  : base_iterator(other)
7243  {}
7244 
7246  iterator& operator=(iterator other) noexcept(
7247  std::is_nothrow_move_constructible<pointer>::value and
7248  std::is_nothrow_move_assignable<pointer>::value and
7249  std::is_nothrow_move_constructible<internal_iterator>::value and
7250  std::is_nothrow_move_assignable<internal_iterator>::value
7251  )
7252  {
7253  base_iterator::operator=(other);
7254  return *this;
7255  }
7256 
7259  {
7260  return const_cast<reference>(base_iterator::operator*());
7261  }
7262 
7265  {
7266  return const_cast<pointer>(base_iterator::operator->());
7267  }
7268 
7271  {
7272  iterator result = *this;
7273  base_iterator::operator++();
7274  return result;
7275  }
7276 
7279  {
7280  base_iterator::operator++();
7281  return *this;
7282  }
7283 
7286  {
7287  iterator result = *this;
7288  base_iterator::operator--();
7289  return result;
7290  }
7291 
7294  {
7295  base_iterator::operator--();
7296  return *this;
7297  }
7298 
7301  {
7302  base_iterator::operator+=(i);
7303  return *this;
7304  }
7305 
7308  {
7309  base_iterator::operator-=(i);
7310  return *this;
7311  }
7312 
7315  {
7316  auto result = *this;
7317  result += i;
7318  return result;
7319  }
7320 
7323  {
7324  auto result = *this;
7325  result -= i;
7326  return result;
7327  }
7328 
7330  difference_type operator-(const iterator& other) const
7331  {
7332  return base_iterator::operator-(other);
7333  }
7334 
7337  {
7338  return const_cast<reference>(base_iterator::operator[](n));
7339  }
7340 
7343  {
7344  return const_cast<reference>(base_iterator::value());
7345  }
7346  };
7347 
7365  template<typename Base>
7366  class json_reverse_iterator : public std::reverse_iterator<Base>
7367  {
7368  public:
7370  using base_iterator = std::reverse_iterator<Base>;
7372  using reference = typename Base::reference;
7373 
7375  json_reverse_iterator(const typename base_iterator::iterator_type& it) noexcept
7376  : base_iterator(it)
7377  {}
7378 
7381  : base_iterator(it)
7382  {}
7383 
7386  {
7387  return base_iterator::operator++(1);
7388  }
7389 
7392  {
7393  base_iterator::operator++();
7394  return *this;
7395  }
7396 
7399  {
7400  return base_iterator::operator--(1);
7401  }
7402 
7405  {
7406  base_iterator::operator--();
7407  return *this;
7408  }
7409 
7412  {
7413  base_iterator::operator+=(i);
7414  return *this;
7415  }
7416 
7419  {
7420  auto result = *this;
7421  result += i;
7422  return result;
7423  }
7424 
7427  {
7428  auto result = *this;
7429  result -= i;
7430  return result;
7431  }
7432 
7435  {
7436  return this->base() - other.base();
7437  }
7438 
7441  {
7442  return *(this->operator+(n));
7443  }
7444 
7446  typename object_t::key_type key() const
7447  {
7448  auto it = --this->base();
7449  return it.key();
7450  }
7451 
7454  {
7455  auto it = --this->base();
7456  return it.operator * ();
7457  }
7458  };
7459 
7460 
7461  private:
7463  // lexer and parser //
7465 
7473  class lexer
7474  {
7475  public:
7477  enum class token_type
7478  {
7479  uninitialized,
7480  literal_true,
7481  literal_false,
7482  literal_null,
7483  value_string,
7484  value_number,
7485  begin_array,
7486  begin_object,
7487  end_array,
7488  end_object,
7489  name_separator,
7490  value_separator,
7491  parse_error,
7492  end_of_input
7493  };
7494 
7496  using lexer_char_t = unsigned char;
7497 
7499  explicit lexer(const string_t& s) noexcept
7500  : m_stream(nullptr), m_buffer(s)
7501  {
7502  m_content = reinterpret_cast<const lexer_char_t*>(m_buffer.c_str());
7503  assert(m_content != nullptr);
7504  m_start = m_cursor = m_content;
7505  m_limit = m_content + s.size();
7506  }
7507 
7509  explicit lexer(std::istream* s) noexcept
7510  : m_stream(s), m_buffer()
7511  {
7512  assert(m_stream != nullptr);
7513  std::getline(*m_stream, m_buffer);
7514  m_content = reinterpret_cast<const lexer_char_t*>(m_buffer.c_str());
7515  assert(m_content != nullptr);
7516  m_start = m_cursor = m_content;
7517  m_limit = m_content + m_buffer.size();
7518  }
7519 
7521  lexer() = default;
7522 
7523  // switch off unwanted functions
7524  lexer(const lexer&) = delete;
7525  lexer operator=(const lexer&) = delete;
7526 
7550  static string_t to_unicode(const std::size_t codepoint1,
7551  const std::size_t codepoint2 = 0)
7552  {
7553  // calculate the code point from the given code points
7554  std::size_t codepoint = codepoint1;
7555 
7556  // check if codepoint1 is a high surrogate
7557  if (codepoint1 >= 0xD800 and codepoint1 <= 0xDBFF)
7558  {
7559  // check if codepoint2 is a low surrogate
7560  if (codepoint2 >= 0xDC00 and codepoint2 <= 0xDFFF)
7561  {
7562  codepoint =
7563  // high surrogate occupies the most significant 22 bits
7564  (codepoint1 << 10)
7565  // low surrogate occupies the least significant 15 bits
7566  + codepoint2
7567  // there is still the 0xD800, 0xDC00 and 0x10000 noise
7568  // in the result so we have to subtract with:
7569  // (0xD800 << 10) + DC00 - 0x10000 = 0x35FDC00
7570  - 0x35FDC00;
7571  }
7572  else
7573  {
7574  throw std::invalid_argument("missing or wrong low surrogate");
7575  }
7576  }
7577 
7578  string_t result;
7579 
7580  if (codepoint < 0x80)
7581  {
7582  // 1-byte characters: 0xxxxxxx (ASCII)
7583  result.append(1, static_cast<typename string_t::value_type>(codepoint));
7584  }
7585  else if (codepoint <= 0x7ff)
7586  {
7587  // 2-byte characters: 110xxxxx 10xxxxxx
7588  result.append(1, static_cast<typename string_t::value_type>(0xC0 | ((codepoint >> 6) & 0x1F)));
7589  result.append(1, static_cast<typename string_t::value_type>(0x80 | (codepoint & 0x3F)));
7590  }
7591  else if (codepoint <= 0xffff)
7592  {
7593  // 3-byte characters: 1110xxxx 10xxxxxx 10xxxxxx
7594  result.append(1, static_cast<typename string_t::value_type>(0xE0 | ((codepoint >> 12) & 0x0F)));
7595  result.append(1, static_cast<typename string_t::value_type>(0x80 | ((codepoint >> 6) & 0x3F)));
7596  result.append(1, static_cast<typename string_t::value_type>(0x80 | (codepoint & 0x3F)));
7597  }
7598  else if (codepoint <= 0x10ffff)
7599  {
7600  // 4-byte characters: 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
7601  result.append(1, static_cast<typename string_t::value_type>(0xF0 | ((codepoint >> 18) & 0x07)));
7602  result.append(1, static_cast<typename string_t::value_type>(0x80 | ((codepoint >> 12) & 0x3F)));
7603  result.append(1, static_cast<typename string_t::value_type>(0x80 | ((codepoint >> 6) & 0x3F)));
7604  result.append(1, static_cast<typename string_t::value_type>(0x80 | (codepoint & 0x3F)));
7605  }
7606  else
7607  {
7608  throw std::out_of_range("code points above 0x10FFFF are invalid");
7609  }
7610 
7611  return result;
7612  }
7613 
7615  static std::string token_type_name(const token_type t)
7616  {
7617  switch (t)
7618  {
7619  case token_type::uninitialized:
7620  return "<uninitialized>";
7621  case token_type::literal_true:
7622  return "true literal";
7623  case token_type::literal_false:
7624  return "false literal";
7625  case token_type::literal_null:
7626  return "null literal";
7627  case token_type::value_string:
7628  return "string literal";
7629  case token_type::value_number:
7630  return "number literal";
7631  case token_type::begin_array:
7632  return "'['";
7633  case token_type::begin_object:
7634  return "'{'";
7635  case token_type::end_array:
7636  return "']'";
7637  case token_type::end_object:
7638  return "'}'";
7639  case token_type::name_separator:
7640  return "':'";
7641  case token_type::value_separator:
7642  return "','";
7643  case token_type::parse_error:
7644  return "<parse error>";
7645  case token_type::end_of_input:
7646  return "end of input";
7647  default:
7648  {
7649  // catch non-enum values
7650  return "unknown token"; // LCOV_EXCL_LINE
7651  }
7652  }
7653  }
7654 
7676  token_type scan() noexcept
7677  {
7678  while (true)
7679  {
7680  // pointer for backtracking information
7681  m_marker = nullptr;
7682 
7683  // remember the begin of the token
7684  m_start = m_cursor;
7685  assert(m_start != nullptr);
7686 
7687 
7688  {
7689  lexer_char_t yych;
7690  unsigned int yyaccept = 0;
7691  static const unsigned char yybm[] =
7692  {
7693  0, 0, 0, 0, 0, 0, 0, 0,
7694  0, 32, 32, 0, 0, 32, 0, 0,
7695  0, 0, 0, 0, 0, 0, 0, 0,
7696  0, 0, 0, 0, 0, 0, 0, 0,
7697  160, 128, 0, 128, 128, 128, 128, 128,
7698  128, 128, 128, 128, 128, 128, 128, 128,
7699  192, 192, 192, 192, 192, 192, 192, 192,
7700  192, 192, 128, 128, 128, 128, 128, 128,
7701  128, 128, 128, 128, 128, 128, 128, 128,
7702  128, 128, 128, 128, 128, 128, 128, 128,
7703  128, 128, 128, 128, 128, 128, 128, 128,
7704  128, 128, 128, 128, 0, 128, 128, 128,
7705  128, 128, 128, 128, 128, 128, 128, 128,
7706  128, 128, 128, 128, 128, 128, 128, 128,
7707  128, 128, 128, 128, 128, 128, 128, 128,
7708  128, 128, 128, 128, 128, 128, 128, 128,
7709  128, 128, 128, 128, 128, 128, 128, 128,
7710  128, 128, 128, 128, 128, 128, 128, 128,
7711  128, 128, 128, 128, 128, 128, 128, 128,
7712  128, 128, 128, 128, 128, 128, 128, 128,
7713  128, 128, 128, 128, 128, 128, 128, 128,
7714  128, 128, 128, 128, 128, 128, 128, 128,
7715  128, 128, 128, 128, 128, 128, 128, 128,
7716  128, 128, 128, 128, 128, 128, 128, 128,
7717  128, 128, 128, 128, 128, 128, 128, 128,
7718  128, 128, 128, 128, 128, 128, 128, 128,
7719  128, 128, 128, 128, 128, 128, 128, 128,
7720  128, 128, 128, 128, 128, 128, 128, 128,
7721  128, 128, 128, 128, 128, 128, 128, 128,
7722  128, 128, 128, 128, 128, 128, 128, 128,
7723  128, 128, 128, 128, 128, 128, 128, 128,
7724  128, 128, 128, 128, 128, 128, 128, 128,
7725  };
7726  if ((m_limit - m_cursor) < 5)
7727  {
7728  yyfill(); // LCOV_EXCL_LINE;
7729  }
7730  yych = *m_cursor;
7731  if (yybm[0 + yych] & 32)
7732  {
7733  goto basic_json_parser_6;
7734  }
7735  if (yych <= '\\')
7736  {
7737  if (yych <= '-')
7738  {
7739  if (yych <= '"')
7740  {
7741  if (yych <= 0x00)
7742  {
7743  goto basic_json_parser_2;
7744  }
7745  if (yych <= '!')
7746  {
7747  goto basic_json_parser_4;
7748  }
7749  goto basic_json_parser_9;
7750  }
7751  else
7752  {
7753  if (yych <= '+')
7754  {
7755  goto basic_json_parser_4;
7756  }
7757  if (yych <= ',')
7758  {
7759  goto basic_json_parser_10;
7760  }
7761  goto basic_json_parser_12;
7762  }
7763  }
7764  else
7765  {
7766  if (yych <= '9')
7767  {
7768  if (yych <= '/')
7769  {
7770  goto basic_json_parser_4;
7771  }
7772  if (yych <= '0')
7773  {
7774  goto basic_json_parser_13;
7775  }
7776  goto basic_json_parser_15;
7777  }
7778  else
7779  {
7780  if (yych <= ':')
7781  {
7782  goto basic_json_parser_17;
7783  }
7784  if (yych == '[')
7785  {
7786  goto basic_json_parser_19;
7787  }
7788  goto basic_json_parser_4;
7789  }
7790  }
7791  }
7792  else
7793  {
7794  if (yych <= 't')
7795  {
7796  if (yych <= 'f')
7797  {
7798  if (yych <= ']')
7799  {
7800  goto basic_json_parser_21;
7801  }
7802  if (yych <= 'e')
7803  {
7804  goto basic_json_parser_4;
7805  }
7806  goto basic_json_parser_23;
7807  }
7808  else
7809  {
7810  if (yych == 'n')
7811  {
7812  goto basic_json_parser_24;
7813  }
7814  if (yych <= 's')
7815  {
7816  goto basic_json_parser_4;
7817  }
7818  goto basic_json_parser_25;
7819  }
7820  }
7821  else
7822  {
7823  if (yych <= '|')
7824  {
7825  if (yych == '{')
7826  {
7827  goto basic_json_parser_26;
7828  }
7829  goto basic_json_parser_4;
7830  }
7831  else
7832  {
7833  if (yych <= '}')
7834  {
7835  goto basic_json_parser_28;
7836  }
7837  if (yych == 0xEF)
7838  {
7839  goto basic_json_parser_30;
7840  }
7841  goto basic_json_parser_4;
7842  }
7843  }
7844  }
7845 basic_json_parser_2:
7846  ++m_cursor;
7847  {
7848  last_token_type = token_type::end_of_input;
7849  break;
7850  }
7851 basic_json_parser_4:
7852  ++m_cursor;
7853 basic_json_parser_5:
7854  {
7855  last_token_type = token_type::parse_error;
7856  break;
7857  }
7858 basic_json_parser_6:
7859  ++m_cursor;
7860  if (m_limit <= m_cursor)
7861  {
7862  yyfill(); // LCOV_EXCL_LINE;
7863  }
7864  yych = *m_cursor;
7865  if (yybm[0 + yych] & 32)
7866  {
7867  goto basic_json_parser_6;
7868  }
7869  {
7870  continue;
7871  }
7872 basic_json_parser_9:
7873  yyaccept = 0;
7874  yych = *(m_marker = ++m_cursor);
7875  if (yych <= 0x1F)
7876  {
7877  goto basic_json_parser_5;
7878  }
7879  goto basic_json_parser_32;
7880 basic_json_parser_10:
7881  ++m_cursor;
7882  {
7883  last_token_type = token_type::value_separator;
7884  break;
7885  }
7886 basic_json_parser_12:
7887  yych = *++m_cursor;
7888  if (yych <= '/')
7889  {
7890  goto basic_json_parser_5;
7891  }
7892  if (yych <= '0')
7893  {
7894  goto basic_json_parser_13;
7895  }
7896  if (yych <= '9')
7897  {
7898  goto basic_json_parser_15;
7899  }
7900  goto basic_json_parser_5;
7901 basic_json_parser_13:
7902  yyaccept = 1;
7903  yych = *(m_marker = ++m_cursor);
7904  if (yych <= 'D')
7905  {
7906  if (yych == '.')
7907  {
7908  goto basic_json_parser_37;
7909  }
7910  }
7911  else
7912  {
7913  if (yych <= 'E')
7914  {
7915  goto basic_json_parser_38;
7916  }
7917  if (yych == 'e')
7918  {
7919  goto basic_json_parser_38;
7920  }
7921  }
7922 basic_json_parser_14:
7923  {
7924  last_token_type = token_type::value_number;
7925  break;
7926  }
7927 basic_json_parser_15:
7928  yyaccept = 1;
7929  m_marker = ++m_cursor;
7930  if ((m_limit - m_cursor) < 3)
7931  {
7932  yyfill(); // LCOV_EXCL_LINE;
7933  }
7934  yych = *m_cursor;
7935  if (yybm[0 + yych] & 64)
7936  {
7937  goto basic_json_parser_15;
7938  }
7939  if (yych <= 'D')
7940  {
7941  if (yych == '.')
7942  {
7943  goto basic_json_parser_37;
7944  }
7945  goto basic_json_parser_14;
7946  }
7947  else
7948  {
7949  if (yych <= 'E')
7950  {
7951  goto basic_json_parser_38;
7952  }
7953  if (yych == 'e')
7954  {
7955  goto basic_json_parser_38;
7956  }
7957  goto basic_json_parser_14;
7958  }
7959 basic_json_parser_17:
7960  ++m_cursor;
7961  {
7962  last_token_type = token_type::name_separator;
7963  break;
7964  }
7965 basic_json_parser_19:
7966  ++m_cursor;
7967  {
7968  last_token_type = token_type::begin_array;
7969  break;
7970  }
7971 basic_json_parser_21:
7972  ++m_cursor;
7973  {
7974  last_token_type = token_type::end_array;
7975  break;
7976  }
7977 basic_json_parser_23:
7978  yyaccept = 0;
7979  yych = *(m_marker = ++m_cursor);
7980  if (yych == 'a')
7981  {
7982  goto basic_json_parser_39;
7983  }
7984  goto basic_json_parser_5;
7985 basic_json_parser_24:
7986  yyaccept = 0;
7987  yych = *(m_marker = ++m_cursor);
7988  if (yych == 'u')
7989  {
7990  goto basic_json_parser_40;
7991  }
7992  goto basic_json_parser_5;
7993 basic_json_parser_25:
7994  yyaccept = 0;
7995  yych = *(m_marker = ++m_cursor);
7996  if (yych == 'r')
7997  {
7998  goto basic_json_parser_41;
7999  }
8000  goto basic_json_parser_5;
8001 basic_json_parser_26:
8002  ++m_cursor;
8003  {
8004  last_token_type = token_type::begin_object;
8005  break;
8006  }
8007 basic_json_parser_28:
8008  ++m_cursor;
8009  {
8010  last_token_type = token_type::end_object;
8011  break;
8012  }
8013 basic_json_parser_30:
8014  yyaccept = 0;
8015  yych = *(m_marker = ++m_cursor);
8016  if (yych == 0xBB)
8017  {
8018  goto basic_json_parser_42;
8019  }
8020  goto basic_json_parser_5;
8021 basic_json_parser_31:
8022  ++m_cursor;
8023  if (m_limit <= m_cursor)
8024  {
8025  yyfill(); // LCOV_EXCL_LINE;
8026  }
8027  yych = *m_cursor;
8028 basic_json_parser_32:
8029  if (yybm[0 + yych] & 128)
8030  {
8031  goto basic_json_parser_31;
8032  }
8033  if (yych <= 0x1F)
8034  {
8035  goto basic_json_parser_33;
8036  }
8037  if (yych <= '"')
8038  {
8039  goto basic_json_parser_34;
8040  }
8041  goto basic_json_parser_36;
8042 basic_json_parser_33:
8043  m_cursor = m_marker;
8044  if (yyaccept == 0)
8045  {
8046  goto basic_json_parser_5;
8047  }
8048  else
8049  {
8050  goto basic_json_parser_14;
8051  }
8052 basic_json_parser_34:
8053  ++m_cursor;
8054  {
8055  last_token_type = token_type::value_string;
8056  break;
8057  }
8058 basic_json_parser_36:
8059  ++m_cursor;
8060  if (m_limit <= m_cursor)
8061  {
8062  yyfill(); // LCOV_EXCL_LINE;
8063  }
8064  yych = *m_cursor;
8065  if (yych <= 'e')
8066  {
8067  if (yych <= '/')
8068  {
8069  if (yych == '"')
8070  {
8071  goto basic_json_parser_31;
8072  }
8073  if (yych <= '.')
8074  {
8075  goto basic_json_parser_33;
8076  }
8077  goto basic_json_parser_31;
8078  }
8079  else
8080  {
8081  if (yych <= '\\')
8082  {
8083  if (yych <= '[')
8084  {
8085  goto basic_json_parser_33;
8086  }
8087  goto basic_json_parser_31;
8088  }
8089  else
8090  {
8091  if (yych == 'b')
8092  {
8093  goto basic_json_parser_31;
8094  }
8095  goto basic_json_parser_33;
8096  }
8097  }
8098  }
8099  else
8100  {
8101  if (yych <= 'q')
8102  {
8103  if (yych <= 'f')
8104  {
8105  goto basic_json_parser_31;
8106  }
8107  if (yych == 'n')
8108  {
8109  goto basic_json_parser_31;
8110  }
8111  goto basic_json_parser_33;
8112  }
8113  else
8114  {
8115  if (yych <= 's')
8116  {
8117  if (yych <= 'r')
8118  {
8119  goto basic_json_parser_31;
8120  }
8121  goto basic_json_parser_33;
8122  }
8123  else
8124  {
8125  if (yych <= 't')
8126  {
8127  goto basic_json_parser_31;
8128  }
8129  if (yych <= 'u')
8130  {
8131  goto basic_json_parser_43;
8132  }
8133  goto basic_json_parser_33;
8134  }
8135  }
8136  }
8137 basic_json_parser_37:
8138  yych = *++m_cursor;
8139  if (yych <= '/')
8140  {
8141  goto basic_json_parser_33;
8142  }
8143  if (yych <= '9')
8144  {
8145  goto basic_json_parser_44;
8146  }
8147  goto basic_json_parser_33;
8148 basic_json_parser_38:
8149  yych = *++m_cursor;
8150  if (yych <= ',')
8151  {
8152  if (yych == '+')
8153  {
8154  goto basic_json_parser_46;
8155  }
8156  goto basic_json_parser_33;
8157  }
8158  else
8159  {
8160  if (yych <= '-')
8161  {
8162  goto basic_json_parser_46;
8163  }
8164  if (yych <= '/')
8165  {
8166  goto basic_json_parser_33;
8167  }
8168  if (yych <= '9')
8169  {
8170  goto basic_json_parser_47;
8171  }
8172  goto basic_json_parser_33;
8173  }
8174 basic_json_parser_39:
8175  yych = *++m_cursor;
8176  if (yych == 'l')
8177  {
8178  goto basic_json_parser_49;
8179  }
8180  goto basic_json_parser_33;
8181 basic_json_parser_40:
8182  yych = *++m_cursor;
8183  if (yych == 'l')
8184  {
8185  goto basic_json_parser_50;
8186  }
8187  goto basic_json_parser_33;
8188 basic_json_parser_41:
8189  yych = *++m_cursor;
8190  if (yych == 'u')
8191  {
8192  goto basic_json_parser_51;
8193  }
8194  goto basic_json_parser_33;
8195 basic_json_parser_42:
8196  yych = *++m_cursor;
8197  if (yych == 0xBF)
8198  {
8199  goto basic_json_parser_52;
8200  }
8201  goto basic_json_parser_33;
8202 basic_json_parser_43:
8203  ++m_cursor;
8204  if (m_limit <= m_cursor)
8205  {
8206  yyfill(); // LCOV_EXCL_LINE;
8207  }
8208  yych = *m_cursor;
8209  if (yych <= '@')
8210  {
8211  if (yych <= '/')
8212  {
8213  goto basic_json_parser_33;
8214  }
8215  if (yych <= '9')
8216  {
8217  goto basic_json_parser_54;
8218  }
8219  goto basic_json_parser_33;
8220  }
8221  else
8222  {
8223  if (yych <= 'F')
8224  {
8225  goto basic_json_parser_54;
8226  }
8227  if (yych <= '`')
8228  {
8229  goto basic_json_parser_33;
8230  }
8231  if (yych <= 'f')
8232  {
8233  goto basic_json_parser_54;
8234  }
8235  goto basic_json_parser_33;
8236  }
8237 basic_json_parser_44:
8238  yyaccept = 1;
8239  m_marker = ++m_cursor;
8240  if ((m_limit - m_cursor) < 3)
8241  {
8242  yyfill(); // LCOV_EXCL_LINE;
8243  }
8244  yych = *m_cursor;
8245  if (yych <= 'D')
8246  {
8247  if (yych <= '/')
8248  {
8249  goto basic_json_parser_14;
8250  }
8251  if (yych <= '9')
8252  {
8253  goto basic_json_parser_44;
8254  }
8255  goto basic_json_parser_14;
8256  }
8257  else
8258  {
8259  if (yych <= 'E')
8260  {
8261  goto basic_json_parser_38;
8262  }
8263  if (yych == 'e')
8264  {
8265  goto basic_json_parser_38;
8266  }
8267  goto basic_json_parser_14;
8268  }
8269 basic_json_parser_46:
8270  yych = *++m_cursor;
8271  if (yych <= '/')
8272  {
8273  goto basic_json_parser_33;
8274  }
8275  if (yych >= ':')
8276  {
8277  goto basic_json_parser_33;
8278  }
8279 basic_json_parser_47:
8280  ++m_cursor;
8281  if (m_limit <= m_cursor)
8282  {
8283  yyfill(); // LCOV_EXCL_LINE;
8284  }
8285  yych = *m_cursor;
8286  if (yych <= '/')
8287  {
8288  goto basic_json_parser_14;
8289  }
8290  if (yych <= '9')
8291  {
8292  goto basic_json_parser_47;
8293  }
8294  goto basic_json_parser_14;
8295 basic_json_parser_49:
8296  yych = *++m_cursor;
8297  if (yych == 's')
8298  {
8299  goto basic_json_parser_55;
8300  }
8301  goto basic_json_parser_33;
8302 basic_json_parser_50:
8303  yych = *++m_cursor;
8304  if (yych == 'l')
8305  {
8306  goto basic_json_parser_56;
8307  }
8308  goto basic_json_parser_33;
8309 basic_json_parser_51:
8310  yych = *++m_cursor;
8311  if (yych == 'e')
8312  {
8313  goto basic_json_parser_58;
8314  }
8315  goto basic_json_parser_33;
8316 basic_json_parser_52:
8317  ++m_cursor;
8318  {
8319  continue;
8320  }
8321 basic_json_parser_54:
8322  ++m_cursor;
8323  if (m_limit <= m_cursor)
8324  {
8325  yyfill(); // LCOV_EXCL_LINE;
8326  }
8327  yych = *m_cursor;
8328  if (yych <= '@')
8329  {
8330  if (yych <= '/')
8331  {
8332  goto basic_json_parser_33;
8333  }
8334  if (yych <= '9')
8335  {
8336  goto basic_json_parser_60;
8337  }
8338  goto basic_json_parser_33;
8339  }
8340  else
8341  {
8342  if (yych <= 'F')
8343  {
8344  goto basic_json_parser_60;
8345  }
8346  if (yych <= '`')
8347  {
8348  goto basic_json_parser_33;
8349  }
8350  if (yych <= 'f')
8351  {
8352  goto basic_json_parser_60;
8353  }
8354  goto basic_json_parser_33;
8355  }
8356 basic_json_parser_55:
8357  yych = *++m_cursor;
8358  if (yych == 'e')
8359  {
8360  goto basic_json_parser_61;
8361  }
8362  goto basic_json_parser_33;
8363 basic_json_parser_56:
8364  ++m_cursor;
8365  {
8366  last_token_type = token_type::literal_null;
8367  break;
8368  }
8369 basic_json_parser_58:
8370  ++m_cursor;
8371  {
8372  last_token_type = token_type::literal_true;
8373  break;
8374  }
8375 basic_json_parser_60:
8376  ++m_cursor;
8377  if (m_limit <= m_cursor)
8378  {
8379  yyfill(); // LCOV_EXCL_LINE;
8380  }
8381  yych = *m_cursor;
8382  if (yych <= '@')
8383  {
8384  if (yych <= '/')
8385  {
8386  goto basic_json_parser_33;
8387  }
8388  if (yych <= '9')
8389  {
8390  goto basic_json_parser_63;
8391  }
8392  goto basic_json_parser_33;
8393  }
8394  else
8395  {
8396  if (yych <= 'F')
8397  {
8398  goto basic_json_parser_63;
8399  }
8400  if (yych <= '`')
8401  {
8402  goto basic_json_parser_33;
8403  }
8404  if (yych <= 'f')
8405  {
8406  goto basic_json_parser_63;
8407  }
8408  goto basic_json_parser_33;
8409  }
8410 basic_json_parser_61:
8411  ++m_cursor;
8412  {
8413  last_token_type = token_type::literal_false;
8414  break;
8415  }
8416 basic_json_parser_63:
8417  ++m_cursor;
8418  if (m_limit <= m_cursor)
8419  {
8420  yyfill(); // LCOV_EXCL_LINE;
8421  }
8422  yych = *m_cursor;
8423  if (yych <= '@')
8424  {
8425  if (yych <= '/')
8426  {
8427  goto basic_json_parser_33;
8428  }
8429  if (yych <= '9')
8430  {
8431  goto basic_json_parser_31;
8432  }
8433  goto basic_json_parser_33;
8434  }
8435  else
8436  {
8437  if (yych <= 'F')
8438  {
8439  goto basic_json_parser_31;
8440  }
8441  if (yych <= '`')
8442  {
8443  goto basic_json_parser_33;
8444  }
8445  if (yych <= 'f')
8446  {
8447  goto basic_json_parser_31;
8448  }
8449  goto basic_json_parser_33;
8450  }
8451  }
8452 
8453  }
8454 
8455  return last_token_type;
8456  }
8457 
8459  void yyfill() noexcept
8460  {
8461  if (m_stream == nullptr or not * m_stream)
8462  {
8463  return;
8464  }
8465 
8466  const auto offset_start = m_start - m_content;
8467  const auto offset_marker = m_marker - m_start;
8468  const auto offset_cursor = m_cursor - m_start;
8469 
8470  m_buffer.erase(0, static_cast<size_t>(offset_start));
8471  std::string line;
8472  assert(m_stream != nullptr);
8473  std::getline(*m_stream, line);
8474  m_buffer += "\n" + line; // add line with newline symbol
8475 
8476  m_content = reinterpret_cast<const lexer_char_t*>(m_buffer.c_str());
8477  assert(m_content != nullptr);
8478  m_start = m_content;
8479  m_marker = m_start + offset_marker;
8480  m_cursor = m_start + offset_cursor;
8481  m_limit = m_start + m_buffer.size() - 1;
8482  }
8483 
8485  string_t get_token_string() const
8486  {
8487  assert(m_start != nullptr);
8488  return string_t(reinterpret_cast<typename string_t::const_pointer>(m_start),
8489  static_cast<size_t>(m_cursor - m_start));
8490  }
8491 
8549  string_t get_string() const
8550  {
8551  assert(m_cursor - m_start >= 2);
8552 
8553  string_t result;
8554  result.reserve(static_cast<size_t>(m_cursor - m_start - 2));
8555 
8556  // iterate the result between the quotes
8557  for (const lexer_char_t* i = m_start + 1; i < m_cursor - 1; ++i)
8558  {
8559  // process escaped characters
8560  if (*i == '\\')
8561  {
8562  // read next character
8563  ++i;
8564 
8565  switch (*i)
8566  {
8567  // the default escapes
8568  case 't':
8569  {
8570  result += "\t";
8571  break;
8572  }
8573  case 'b':
8574  {
8575  result += "\b";
8576  break;
8577  }
8578  case 'f':
8579  {
8580  result += "\f";
8581  break;
8582  }
8583  case 'n':
8584  {
8585  result += "\n";
8586  break;
8587  }
8588  case 'r':
8589  {
8590  result += "\r";
8591  break;
8592  }
8593  case '\\':
8594  {
8595  result += "\\";
8596  break;
8597  }
8598  case '/':
8599  {
8600  result += "/";
8601  break;
8602  }
8603  case '"':
8604  {
8605  result += "\"";
8606  break;
8607  }
8608 
8609  // unicode
8610  case 'u':
8611  {
8612  // get code xxxx from uxxxx
8613  auto codepoint = std::strtoul(std::string(reinterpret_cast<typename string_t::const_pointer>(i + 1),
8614  4).c_str(), nullptr, 16);
8615 
8616  // check if codepoint is a high surrogate
8617  if (codepoint >= 0xD800 and codepoint <= 0xDBFF)
8618  {
8619  // make sure there is a subsequent unicode
8620  if ((i + 6 >= m_limit) or * (i + 5) != '\\' or * (i + 6) != 'u')
8621  {
8622  throw std::invalid_argument("missing low surrogate");
8623  }
8624 
8625  // get code yyyy from uxxxx\uyyyy
8626  auto codepoint2 = std::strtoul(std::string(reinterpret_cast<typename string_t::const_pointer>
8627  (i + 7), 4).c_str(), nullptr, 16);
8628  result += to_unicode(codepoint, codepoint2);
8629  // skip the next 10 characters (xxxx\uyyyy)
8630  i += 10;
8631  }
8632  else
8633  {
8634  // add unicode character(s)
8635  result += to_unicode(codepoint);
8636  // skip the next four characters (xxxx)
8637  i += 4;
8638  }
8639  break;
8640  }
8641  }
8642  }
8643  else
8644  {
8645  // all other characters are just copied to the end of the
8646  // string
8647  result.append(1, static_cast<typename string_t::value_type>(*i));
8648  }
8649  }
8650 
8651  return result;
8652  }
8653 
8669  long double str_to_float_t(long double* /* type */, char** endptr) const
8670  {
8671  return std::strtold(reinterpret_cast<typename string_t::const_pointer>(m_start), endptr);
8672  }
8673 
8689  double str_to_float_t(double* /* type */, char** endptr) const
8690  {
8691  return std::strtod(reinterpret_cast<typename string_t::const_pointer>(m_start), endptr);
8692  }
8693 
8709  float str_to_float_t(float* /* type */, char** endptr) const
8710  {
8711  return std::strtof(reinterpret_cast<typename string_t::const_pointer>(m_start), endptr);
8712  }
8713 
8735  void get_number(basic_json& result) const
8736  {
8737  assert(m_start != nullptr);
8738 
8739  const lexer::lexer_char_t* curptr = m_start;
8740 
8741  // accumulate the integer conversion result (unsigned for now)
8742  number_unsigned_t value = 0;
8743 
8744  // maximum absolute value of the relevant integer type
8745  number_unsigned_t max;
8746 
8747  // temporarily store the type to avoid unecessary bitfield access
8748  value_t type;
8749 
8750  // look for sign
8751  if (*curptr == '-')
8752  {
8753  type = value_t::number_integer;
8754  max = static_cast<uint64_t>((std::numeric_limits<number_integer_t>::max)()) + 1;
8755  curptr++;
8756  }
8757  else
8758  {
8759  type = value_t::number_unsigned;
8760  max = static_cast<uint64_t>((std::numeric_limits<number_unsigned_t>::max)());
8761  }
8762 
8763  // count the significant figures
8764  for (; curptr < m_cursor; curptr++)
8765  {
8766  // quickly skip tests if a digit
8767  if (*curptr < '0' || *curptr > '9')
8768  {
8769  if (*curptr == '.')
8770  {
8771  // don't count '.' but change to float
8772  type = value_t::number_float;
8773  continue;
8774  }
8775  // assume exponent (if not then will fail parse): change to
8776  // float, stop counting and record exponent details
8777  type = value_t::number_float;
8778  break;
8779  }
8780 
8781  // skip if definitely not an integer
8782  if (type != value_t::number_float)
8783  {
8784  // multiply last value by ten and add the new digit
8785  auto temp = value * 10 + *curptr - '0';
8786 
8787  // test for overflow
8788  if (temp < value || temp > max)
8789  {
8790  // overflow
8791  type = value_t::number_float;
8792  }
8793  else
8794  {
8795  // no overflow - save it
8796  value = temp;
8797  }
8798  }
8799  }
8800 
8801  // save the value (if not a float)
8802  if (type == value_t::number_unsigned)
8803  {
8804  result.m_value.number_unsigned = value;
8805  }
8806  else if (type == value_t::number_integer)
8807  {
8808  result.m_value.number_integer = -static_cast<number_integer_t>(value);
8809  }
8810  else
8811  {
8812  // parse with strtod
8813  result.m_value.number_float = str_to_float_t(static_cast<number_float_t*>(nullptr), NULL);
8814  }
8815 
8816  // save the type
8817  result.m_type = type;
8818  }
8819 
8820  private:
8822  std::istream* m_stream = nullptr;
8824  string_t m_buffer;
8826  const lexer_char_t* m_content = nullptr;
8828  const lexer_char_t* m_start = nullptr;
8830  const lexer_char_t* m_marker = nullptr;
8832  const lexer_char_t* m_cursor = nullptr;
8834  const lexer_char_t* m_limit = nullptr;
8836  token_type last_token_type = token_type::end_of_input;
8837  };
8838 
8844  class parser
8845  {
8846  public:
8848  parser(const string_t& s, const parser_callback_t cb = nullptr) noexcept
8849  : callback(cb), m_lexer(s)
8850  {
8851  // read first token
8852  get_token();
8853  }
8854 
8856  parser(std::istream& _is, const parser_callback_t cb = nullptr) noexcept
8857  : callback(cb), m_lexer(&_is)
8858  {
8859  // read first token
8860  get_token();
8861  }
8862 
8864  basic_json parse()
8865  {
8866  basic_json result = parse_internal(true);
8867  result.assert_invariant();
8868 
8869  expect(lexer::token_type::end_of_input);
8870 
8871  // return parser result and replace it with null in case the
8872  // top-level value was discarded by the callback function
8873  return result.is_discarded() ? basic_json() : std::move(result);
8874  }
8875 
8876  private:
8878  basic_json parse_internal(bool keep)
8879  {
8880  auto result = basic_json(value_t::discarded);
8881 
8882  switch (last_token)
8883  {
8884  case lexer::token_type::begin_object:
8885  {
8886  if (keep and (not callback or (keep = callback(depth++, parse_event_t::object_start, result))))
8887  {
8888  // explicitly set result to object to cope with {}
8889  result.m_type = value_t::object;
8890  result.m_value = value_t::object;
8891  }
8892 
8893  // read next token
8894  get_token();
8895 
8896  // closing } -> we are done
8897  if (last_token == lexer::token_type::end_object)
8898  {
8899  get_token();
8900  if (keep and callback and not callback(--depth, parse_event_t::object_end, result))
8901  {
8902  result = basic_json(value_t::discarded);
8903  }
8904  return result;
8905  }
8906 
8907  // no comma is expected here
8908  unexpect(lexer::token_type::value_separator);
8909 
8910  // otherwise: parse key-value pairs
8911  do
8912  {
8913  // ugly, but could be fixed with loop reorganization
8914  if (last_token == lexer::token_type::value_separator)
8915  {
8916  get_token();
8917  }
8918 
8919  // store key
8920  expect(lexer::token_type::value_string);
8921  const auto key = m_lexer.get_string();
8922 
8923  bool keep_tag = false;
8924  if (keep)
8925  {
8926  if (callback)
8927  {
8928  basic_json k(key);
8929  keep_tag = callback(depth, parse_event_t::key, k);
8930  }
8931  else
8932  {
8933  keep_tag = true;
8934  }
8935  }
8936 
8937  // parse separator (:)
8938  get_token();
8939  expect(lexer::token_type::name_separator);
8940 
8941  // parse and add value
8942  get_token();
8943  auto value = parse_internal(keep);
8944  if (keep and keep_tag and not value.is_discarded())
8945  {
8946  result[key] = std::move(value);
8947  }
8948  }
8949  while (last_token == lexer::token_type::value_separator);
8950 
8951  // closing }
8952  expect(lexer::token_type::end_object);
8953  get_token();
8954  if (keep and callback and not callback(--depth, parse_event_t::object_end, result))
8955  {
8956  result = basic_json(value_t::discarded);
8957  }
8958 
8959  return result;
8960  }
8961 
8962  case lexer::token_type::begin_array:
8963  {
8964  if (keep and (not callback or (keep = callback(depth++, parse_event_t::array_start, result))))
8965  {
8966  // explicitly set result to object to cope with []
8967  result.m_type = value_t::array;
8968  result.m_value = value_t::array;
8969  }
8970 
8971  // read next token
8972  get_token();
8973 
8974  // closing ] -> we are done
8975  if (last_token == lexer::token_type::end_array)
8976  {
8977  get_token();
8978  if (callback and not callback(--depth, parse_event_t::array_end, result))
8979  {
8980  result = basic_json(value_t::discarded);
8981  }
8982  return result;
8983  }
8984 
8985  // no comma is expected here
8986  unexpect(lexer::token_type::value_separator);
8987 
8988  // otherwise: parse values
8989  do
8990  {
8991  // ugly, but could be fixed with loop reorganization
8992  if (last_token == lexer::token_type::value_separator)
8993  {
8994  get_token();
8995  }
8996 
8997  // parse value
8998  auto value = parse_internal(keep);
8999  if (keep and not value.is_discarded())
9000  {
9001  result.push_back(std::move(value));
9002  }
9003  }
9004  while (last_token == lexer::token_type::value_separator);
9005 
9006  // closing ]
9007  expect(lexer::token_type::end_array);
9008  get_token();
9009  if (keep and callback and not callback(--depth, parse_event_t::array_end, result))
9010  {
9011  result = basic_json(value_t::discarded);
9012  }
9013 
9014  return result;
9015  }
9016 
9017  case lexer::token_type::literal_null:
9018  {
9019  get_token();
9020  result.m_type = value_t::null;
9021  break;
9022  }
9023 
9024  case lexer::token_type::value_string:
9025  {
9026  const auto s = m_lexer.get_string();
9027  get_token();
9028  result = basic_json(s);
9029  break;
9030  }
9031 
9032  case lexer::token_type::literal_true:
9033  {
9034  get_token();
9035  result.m_type = value_t::boolean;
9036  result.m_value = true;
9037  break;
9038  }
9039 
9040  case lexer::token_type::literal_false:
9041  {
9042  get_token();
9043  result.m_type = value_t::boolean;
9044  result.m_value = false;
9045  break;
9046  }
9047 
9048  case lexer::token_type::value_number:
9049  {
9050  m_lexer.get_number(result);
9051  get_token();
9052  break;
9053  }
9054 
9055  default:
9056  {
9057  // the last token was unexpected
9058  unexpect(last_token);
9059  }
9060  }
9061 
9062  if (keep and callback and not callback(depth, parse_event_t::value, result))
9063  {
9064  result = basic_json(value_t::discarded);
9065  }
9066  return result;
9067  }
9068 
9070  typename lexer::token_type get_token() noexcept
9071  {
9072  last_token = m_lexer.scan();
9073  return last_token;
9074  }
9075 
9076  void expect(typename lexer::token_type t) const
9077  {
9078  if (t != last_token)
9079  {
9080  std::string error_msg = "parse error - unexpected ";
9081  error_msg += (last_token == lexer::token_type::parse_error ? ("'" + m_lexer.get_token_string() +
9082  "'") :
9083  lexer::token_type_name(last_token));
9084  error_msg += "; expected " + lexer::token_type_name(t);
9085  throw std::invalid_argument(error_msg);
9086  }
9087  }
9088 
9089  void unexpect(typename lexer::token_type t) const
9090  {
9091  if (t == last_token)
9092  {
9093  std::string error_msg = "parse error - unexpected ";
9094  error_msg += (last_token == lexer::token_type::parse_error ? ("'" + m_lexer.get_token_string() +
9095  "'") :
9096  lexer::token_type_name(last_token));
9097  throw std::invalid_argument(error_msg);
9098  }
9099  }
9100 
9101  private:
9103  int depth = 0;
9105  const parser_callback_t callback = nullptr;
9107  typename lexer::token_type last_token = lexer::token_type::uninitialized;
9109  lexer m_lexer;
9110  };
9111 
9112  public:
9125  {
9127  friend class basic_json;
9128 
9129  public:
9152  explicit json_pointer(const std::string& s = "")
9153  : reference_tokens(split(s))
9154  {}
9155 
9171  std::string to_string() const noexcept
9172  {
9173  return std::accumulate(reference_tokens.begin(),
9174  reference_tokens.end(), std::string{},
9175  [](const std::string & a, const std::string & b)
9176  {
9177  return a + "/" + escape(b);
9178  });
9179  }
9180 
9182  operator std::string() const
9183  {
9184  return to_string();
9185  }
9187  private:
9189  std::string pop_back()
9190  {
9191  if (is_root())
9192  {
9193  throw std::domain_error("JSON pointer has no parent");
9194  }
9195 
9196  auto last = reference_tokens.back();
9197  reference_tokens.pop_back();
9198  return last;
9199  }
9200 
9202  bool is_root() const
9203  {
9204  return reference_tokens.empty();
9205  }
9206 
9207  json_pointer top() const
9208  {
9209  if (is_root())
9210  {
9211  throw std::domain_error("JSON pointer has no parent");
9212  }
9213 
9214  json_pointer result = *this;
9215  result.reference_tokens = {reference_tokens[0]};
9216  return result;
9217  }
9218 
9224  reference get_and_create(reference j) const
9225  {
9226  pointer result = &j;
9227 
9228  // in case no reference tokens exist, return a reference to the
9229  // JSON value j which will be overwritten by a primitive value
9230  for (const auto& reference_token : reference_tokens)
9231  {
9232  switch (result->m_type)
9233  {
9234  case value_t::null:
9235  {
9236  if (reference_token == "0")
9237  {
9238  // start a new array if reference token is 0
9239  result = &result->operator[](0);
9240  }
9241  else
9242  {
9243  // start a new object otherwise
9244  result = &result->operator[](reference_token);
9245  }
9246  break;
9247  }
9248 
9249  case value_t::object:
9250  {
9251  // create an entry in the object
9252  result = &result->operator[](reference_token);
9253  break;
9254  }
9255 
9256  case value_t::array:
9257  {
9258  // create an entry in the array
9259  result = &result->operator[](static_cast<size_type>(std::stoi(reference_token)));
9260  break;
9261  }
9262 
9263  /*
9264  The following code is only reached if there exists a
9265  reference token _and_ the current value is primitive. In
9266  this case, we have an error situation, because primitive
9267  values may only occur as single value; that is, with an
9268  empty list of reference tokens.
9269  */
9270  default:
9271  {
9272  throw std::domain_error("invalid value to unflatten");
9273  }
9274  }
9275  }
9276 
9277  return *result;
9278  }
9279 
9293  reference get_unchecked(pointer ptr) const
9294  {
9295  for (const auto& reference_token : reference_tokens)
9296  {
9297  switch (ptr->m_type)
9298  {
9299  case value_t::object:
9300  {
9301  // use unchecked object access
9302  ptr = &ptr->operator[](reference_token);
9303  break;
9304  }
9305 
9306  case value_t::array:
9307  {
9308  // error condition (cf. RFC 6901, Sect. 4)
9309  if (reference_token.size() > 1 and reference_token[0] == '0')
9310  {
9311  throw std::domain_error("array index must not begin with '0'");
9312  }
9313 
9314  if (reference_token == "-")
9315  {
9316  // explicityly treat "-" as index beyond the end
9317  ptr = &ptr->operator[](ptr->m_value.array->size());
9318  }
9319  else
9320  {
9321  // convert array index to number; unchecked access
9322  ptr = &ptr->operator[](static_cast<size_type>(std::stoi(reference_token)));
9323  }
9324  break;
9325  }
9326 
9327  default:
9328  {
9329  throw std::out_of_range("unresolved reference token '" + reference_token + "'");
9330  }
9331  }
9332  }
9333 
9334  return *ptr;
9335  }
9336 
9337  reference get_checked(pointer ptr) const
9338  {
9339  for (const auto& reference_token : reference_tokens)
9340  {
9341  switch (ptr->m_type)
9342  {
9343  case value_t::object:
9344  {
9345  // note: at performs range check
9346  ptr = &ptr->at(reference_token);
9347  break;
9348  }
9349 
9350  case value_t::array:
9351  {
9352  if (reference_token == "-")
9353  {
9354  // "-" always fails the range check
9355  throw std::out_of_range("array index '-' (" +
9356  std::to_string(ptr->m_value.array->size()) +
9357  ") is out of range");
9358  }
9359 
9360  // error condition (cf. RFC 6901, Sect. 4)
9361  if (reference_token.size() > 1 and reference_token[0] == '0')
9362  {
9363  throw std::domain_error("array index must not begin with '0'");
9364  }
9365 
9366  // note: at performs range check
9367  ptr = &ptr->at(static_cast<size_type>(std::stoi(reference_token)));
9368  break;
9369  }
9370 
9371  default:
9372  {
9373  throw std::out_of_range("unresolved reference token '" + reference_token + "'");
9374  }
9375  }
9376  }
9377 
9378  return *ptr;
9379  }
9380 
9389  const_reference get_unchecked(const_pointer ptr) const
9390  {
9391  for (const auto& reference_token : reference_tokens)
9392  {
9393  switch (ptr->m_type)
9394  {
9395  case value_t::object:
9396  {
9397  // use unchecked object access
9398  ptr = &ptr->operator[](reference_token);
9399  break;
9400  }
9401 
9402  case value_t::array:
9403  {
9404  if (reference_token == "-")
9405  {
9406  // "-" cannot be used for const access
9407  throw std::out_of_range("array index '-' (" +
9408  std::to_string(ptr->m_value.array->size()) +
9409  ") is out of range");
9410  }
9411 
9412  // error condition (cf. RFC 6901, Sect. 4)
9413  if (reference_token.size() > 1 and reference_token[0] == '0')
9414  {
9415  throw std::domain_error("array index must not begin with '0'");
9416  }
9417 
9418  // use unchecked array access
9419  ptr = &ptr->operator[](static_cast<size_type>(std::stoi(reference_token)));
9420  break;
9421  }
9422 
9423  default:
9424  {
9425  throw std::out_of_range("unresolved reference token '" + reference_token + "'");
9426  }
9427  }
9428  }
9429 
9430  return *ptr;
9431  }
9432 
9433  const_reference get_checked(const_pointer ptr) const
9434  {
9435  for (const auto& reference_token : reference_tokens)
9436  {
9437  switch (ptr->m_type)
9438  {
9439  case value_t::object:
9440  {
9441  // note: at performs range check
9442  ptr = &ptr->at(reference_token);
9443  break;
9444  }
9445 
9446  case value_t::array:
9447  {
9448  if (reference_token == "-")
9449  {
9450  // "-" always fails the range check
9451  throw std::out_of_range("array index '-' (" +
9452  std::to_string(ptr->m_value.array->size()) +
9453  ") is out of range");
9454  }
9455 
9456  // error condition (cf. RFC 6901, Sect. 4)
9457  if (reference_token.size() > 1 and reference_token[0] == '0')
9458  {
9459  throw std::domain_error("array index must not begin with '0'");
9460  }
9461 
9462  // note: at performs range check
9463  ptr = &ptr->at(static_cast<size_type>(std::stoi(reference_token)));
9464  break;
9465  }
9466 
9467  default:
9468  {
9469  throw std::out_of_range("unresolved reference token '" + reference_token + "'");
9470  }
9471  }
9472  }
9473 
9474  return *ptr;
9475  }
9476 
9478  static std::vector<std::string> split(std::string reference_string)
9479  {
9480  std::vector<std::string> result;
9481 
9482  // special case: empty reference string -> no reference tokens
9483  if (reference_string.empty())
9484  {
9485  return result;
9486  }
9487 
9488  // check if nonempty reference string begins with slash
9489  if (reference_string[0] != '/')
9490  {
9491  throw std::domain_error("JSON pointer must be empty or begin with '/'");
9492  }
9493 
9494  // extract the reference tokens:
9495  // - slash: position of the last read slash (or end of string)
9496  // - start: position after the previous slash
9497  for (
9498  // search for the first slash after the first character
9499  size_t slash = reference_string.find_first_of("/", 1),
9500  // set the beginning of the first reference token
9501  start = 1;
9502  // we can stop if start == string::npos+1 = 0
9503  start != 0;
9504  // set the beginning of the next reference token
9505  // (will eventually be 0 if slash == std::string::npos)
9506  start = slash + 1,
9507  // find next slash
9508  slash = reference_string.find_first_of("/", start))
9509  {
9510  // use the text between the beginning of the reference token
9511  // (start) and the last slash (slash).
9512  auto reference_token = reference_string.substr(start, slash - start);
9513 
9514  // check reference tokens are properly escaped
9515  for (size_t pos = reference_token.find_first_of("~");
9516  pos != std::string::npos;
9517  pos = reference_token.find_first_of("~", pos + 1))
9518  {
9519  assert(reference_token[pos] == '~');
9520 
9521  // ~ must be followed by 0 or 1
9522  if (pos == reference_token.size() - 1 or
9523  (reference_token[pos + 1] != '0' and
9524  reference_token[pos + 1] != '1'))
9525  {
9526  throw std::domain_error("escape error: '~' must be followed with '0' or '1'");
9527  }
9528  }
9529 
9530  // finally, store the reference token
9531  unescape(reference_token);
9532  result.push_back(reference_token);
9533  }
9534 
9535  return result;
9536  }
9537 
9538  private:
9553  static void replace_substring(std::string& s,
9554  const std::string& f,
9555  const std::string& t)
9556  {
9557  assert(not f.empty());
9558 
9559  for (
9560  size_t pos = s.find(f); // find first occurrence of f
9561  pos != std::string::npos; // make sure f was found
9562  s.replace(pos, f.size(), t), // replace with t
9563  pos = s.find(f, pos + t.size()) // find next occurrence of f
9564  );
9565  }
9566 
9568  static std::string escape(std::string s)
9569  {
9570  // escape "~"" to "~0" and "/" to "~1"
9571  replace_substring(s, "~", "~0");
9572  replace_substring(s, "/", "~1");
9573  return s;
9574  }
9575 
9577  static void unescape(std::string& s)
9578  {
9579  // first transform any occurrence of the sequence '~1' to '/'
9580  replace_substring(s, "~1", "/");
9581  // then transform any occurrence of the sequence '~0' to '~'
9582  replace_substring(s, "~0", "~");
9583  }
9584 
9592  static void flatten(const std::string& reference_string,
9593  const basic_json& value,
9594  basic_json& result)
9595  {
9596  switch (value.m_type)
9597  {
9598  case value_t::array:
9599  {
9600  if (value.m_value.array->empty())
9601  {
9602  // flatten empty array as null
9603  result[reference_string] = nullptr;
9604  }
9605  else
9606  {
9607  // iterate array and use index as reference string
9608  for (size_t i = 0; i < value.m_value.array->size(); ++i)
9609  {
9610  flatten(reference_string + "/" + std::to_string(i),
9611  value.m_value.array->operator[](i), result);
9612  }
9613  }
9614  break;
9615  }
9616 
9617  case value_t::object:
9618  {
9619  if (value.m_value.object->empty())
9620  {
9621  // flatten empty object as null
9622  result[reference_string] = nullptr;
9623  }
9624  else
9625  {
9626  // iterate object and use keys as reference string
9627  for (const auto& element : *value.m_value.object)
9628  {
9629  flatten(reference_string + "/" + escape(element.first),
9630  element.second, result);
9631  }
9632  }
9633  break;
9634  }
9635 
9636  default:
9637  {
9638  // add primitive value with its reference string
9639  result[reference_string] = value;
9640  break;
9641  }
9642  }
9643  }
9644 
9650  static basic_json unflatten(const basic_json& value)
9651  {
9652  if (not value.is_object())
9653  {
9654  throw std::domain_error("only objects can be unflattened");
9655  }
9656 
9657  basic_json result;
9658 
9659  // iterate the JSON object values
9660  for (const auto& element : *value.m_value.object)
9661  {
9662  if (not element.second.is_primitive())
9663  {
9664  throw std::domain_error("values in object must be primitive");
9665  }
9666 
9667  // assign value to reference pointed to by JSON pointer; Note
9668  // that if the JSON pointer is "" (i.e., points to the whole
9669  // value), function get_and_create returns a reference to
9670  // result itself. An assignment will then create a primitive
9671  // value.
9672  json_pointer(element.first).get_and_create(result) = element.second;
9673  }
9674 
9675  return result;
9676  }
9677 
9678  private:
9680  std::vector<std::string> reference_tokens {};
9681  };
9682 
9684  // JSON Pointer support //
9686 
9689 
9723  reference operator[](const json_pointer& ptr)
9724  {
9725  return ptr.get_unchecked(this);
9726  }
9750  const_reference operator[](const json_pointer& ptr) const
9751  {
9752  return ptr.get_unchecked(this);
9753  }
9775  reference at(const json_pointer& ptr)
9776  {
9777  return ptr.get_checked(this);
9778  }
9800  const_reference at(const json_pointer& ptr) const
9801  {
9802  return ptr.get_checked(this);
9803  }
9827  basic_json flatten() const
9828  {
9829  basic_json result(value_t::object);
9830  json_pointer::flatten("", *this, result);
9831  return result;
9832  }
9833 
9861  basic_json unflatten() const
9862  {
9863  return json_pointer::unflatten(*this);
9864  }
9867 
9869  // JSON Patch functions //
9871 
9874 
9911  basic_json patch(const basic_json& json_patch) const
9912  {
9913  // make a working copy to apply the patch to
9914  basic_json result = *this;
9916  // the valid JSON Patch operations
9917  enum class patch_operations {add, remove, replace, move, copy, test, invalid};
9918 
9919  const auto get_op = [](const std::string op)
9920  {
9921  if (op == "add")
9922  {
9923  return patch_operations::add;
9924  }
9925  if (op == "remove")
9926  {
9927  return patch_operations::remove;
9928  }
9929  if (op == "replace")
9930  {
9931  return patch_operations::replace;
9932  }
9933  if (op == "move")
9934  {
9935  return patch_operations::move;
9936  }
9937  if (op == "copy")
9938  {
9939  return patch_operations::copy;
9940  }
9941  if (op == "test")
9942  {
9943  return patch_operations::test;
9944  }
9945 
9946  return patch_operations::invalid;
9947  };
9948 
9949  // wrapper for "add" operation; add value at ptr
9950  const auto operation_add = [&result](json_pointer & ptr, basic_json val)
9951  {
9952  // adding to the root of the target document means replacing it
9953  if (ptr.is_root())
9954  {
9955  result = val;
9956  }
9957  else
9958  {
9959  // make sure the top element of the pointer exists
9960  json_pointer top_pointer = ptr.top();
9961  if (top_pointer != ptr)
9962  {
9963  basic_json& x = result.at(top_pointer);
9964  }
9965 
9966  // get reference to parent of JSON pointer ptr
9967  const auto last_path = ptr.pop_back();
9968  basic_json& parent = result[ptr];
9969 
9970  switch (parent.m_type)
9971  {
9972  case value_t::null:
9973  case value_t::object:
9974  {
9975  // use operator[] to add value
9976  parent[last_path] = val;
9977  break;
9978  }
9979 
9980  case value_t::array:
9981  {
9982  if (last_path == "-")
9983  {
9984  // special case: append to back
9985  parent.push_back(val);
9986  }
9987  else
9988  {
9989  const auto idx = std::stoi(last_path);
9990  if (static_cast<size_type>(idx) > parent.size())
9991  {
9992  // avoid undefined behavior
9993  throw std::out_of_range("array index " + std::to_string(idx) + " is out of range");
9994  }
9995  else
9996  {
9997  // default case: insert add offset
9998  parent.insert(parent.begin() + static_cast<difference_type>(idx), val);
9999  }
10000  }
10001  break;
10002  }
10003 
10004  default:
10005  {
10006  // if there exists a parent it cannot be primitive
10007  assert(false); // LCOV_EXCL_LINE
10008  }
10009  }
10010  }
10011  };
10012 
10013  // wrapper for "remove" operation; remove value at ptr
10014  const auto operation_remove = [&result](json_pointer & ptr)
10015  {
10016  // get reference to parent of JSON pointer ptr
10017  const auto last_path = ptr.pop_back();
10018  basic_json& parent = result.at(ptr);
10019 
10020  // remove child
10021  if (parent.is_object())
10022  {
10023  // perform range check
10024  auto it = parent.find(last_path);
10025  if (it != parent.end())
10026  {
10027  parent.erase(it);
10028  }
10029  else
10030  {
10031  throw std::out_of_range("key '" + last_path + "' not found");
10032  }
10033  }
10034  else if (parent.is_array())
10035  {
10036  // note erase performs range check
10037  parent.erase(static_cast<size_type>(std::stoi(last_path)));
10038  }
10039  };
10040 
10041  // type check
10042  if (not json_patch.is_array())
10043  {
10044  // a JSON patch must be an array of objects
10045  throw std::invalid_argument("JSON patch must be an array of objects");
10046  }
10047 
10048  // iterate and apply th eoperations
10049  for (const auto& val : json_patch)
10050  {
10051  // wrapper to get a value for an operation
10052  const auto get_value = [&val](const std::string & op,
10053  const std::string & member,
10054  bool string_type) -> basic_json&
10055  {
10056  // find value
10057  auto it = val.m_value.object->find(member);
10058 
10059  // context-sensitive error message
10060  const auto error_msg = (op == "op") ? "operation" : "operation '" + op + "'";
10061 
10062  // check if desired value is present
10063  if (it == val.m_value.object->end())
10064  {
10065  throw std::invalid_argument(error_msg + " must have member '" + member + "'");
10066  }
10067 
10068  // check if result is of type string
10069  if (string_type and not it->second.is_string())
10070  {
10071  throw std::invalid_argument(error_msg + " must have string member '" + member + "'");
10072  }
10073 
10074  // no error: return value
10075  return it->second;
10076  };
10077 
10078  // type check
10079  if (not val.is_object())
10080  {
10081  throw std::invalid_argument("JSON patch must be an array of objects");
10082  }
10083 
10084  // collect mandatory members
10085  const std::string op = get_value("op", "op", true);
10086  const std::string path = get_value(op, "path", true);
10087  json_pointer ptr(path);
10088 
10089  switch (get_op(op))
10090  {
10091  case patch_operations::add:
10092  {
10093  operation_add(ptr, get_value("add", "value", false));
10094  break;
10095  }
10096 
10097  case patch_operations::remove:
10098  {
10099  operation_remove(ptr);
10100  break;
10101  }
10102 
10103  case patch_operations::replace:
10104  {
10105  // the "path" location must exist - use at()
10106  result.at(ptr) = get_value("replace", "value", false);
10107  break;
10108  }
10109 
10110  case patch_operations::move:
10111  {
10112  const std::string from_path = get_value("move", "from", true);
10113  json_pointer from_ptr(from_path);
10114 
10115  // the "from" location must exist - use at()
10116  basic_json v = result.at(from_ptr);
10117 
10118  // The move operation is functionally identical to a
10119  // "remove" operation on the "from" location, followed
10120  // immediately by an "add" operation at the target
10121  // location with the value that was just removed.
10122  operation_remove(from_ptr);
10123  operation_add(ptr, v);
10124  break;
10125  }
10126 
10127  case patch_operations::copy:
10128  {
10129  const std::string from_path = get_value("copy", "from", true);;
10130  const json_pointer from_ptr(from_path);
10131 
10132  // the "from" location must exist - use at()
10133  result[ptr] = result.at(from_ptr);
10134  break;
10135  }
10136 
10137  case patch_operations::test:
10138  {
10139  bool success = false;
10140  try
10141  {
10142  // check if "value" matches the one at "path"
10143  // the "path" location must exist - use at()
10144  success = (result.at(ptr) == get_value("test", "value", false));
10145  }
10146  catch (std::out_of_range&)
10147  {
10148  // ignore out of range errors: success remains false
10149  }
10150 
10151  // throw an exception if test fails
10152  if (not success)
10153  {
10154  throw std::domain_error("unsuccessful: " + val.dump());
10155  }
10156 
10157  break;
10158  }
10159 
10160  case patch_operations::invalid:
10161  {
10162  // op must be "add", "remove", "replace", "move", "copy", or
10163  // "test"
10164  throw std::invalid_argument("operation value '" + op + "' is invalid");
10165  }
10166  }
10167  }
10168 
10169  return result;
10170  }
10171 
10204  static basic_json diff(const basic_json& source,
10205  const basic_json& target,
10206  std::string path = "")
10207  {
10208  // the patch
10209  basic_json result(value_t::array);
10210 
10211  // if the values are the same, return empty patch
10212  if (source == target)
10213  {
10214  return result;
10215  }
10216 
10217  if (source.type() != target.type())
10218  {
10219  // different types: replace value
10220  result.push_back(
10221  {
10222  {"op", "replace"},
10223  {"path", path},
10224  {"value", target}
10225  });
10226  }
10227  else
10228  {
10229  switch (source.type())
10230  {
10231  case value_t::array:
10232  {
10233  // first pass: traverse common elements
10234  size_t i = 0;
10235  while (i < source.size() and i < target.size())
10236  {
10237  // recursive call to compare array values at index i
10238  auto temp_diff = diff(source[i], target[i], path + "/" + std::to_string(i));
10239  result.insert(result.end(), temp_diff.begin(), temp_diff.end());
10240  ++i;
10241  }
10242 
10243  // i now reached the end of at least one array
10244  // in a second pass, traverse the remaining elements
10245 
10246  // remove my remaining elements
10247  const auto end_index = static_cast<difference_type>(result.size());
10248  while (i < source.size())
10249  {
10250  // add operations in reverse order to avoid invalid
10251  // indices
10252  result.insert(result.begin() + end_index, object(
10253  {
10254  {"op", "remove"},
10255  {"path", path + "/" + std::to_string(i)}
10256  }));
10257  ++i;
10258  }
10259 
10260  // add other remaining elements
10261  while (i < target.size())
10262  {
10263  result.push_back(
10264  {
10265  {"op", "add"},
10266  {"path", path + "/" + std::to_string(i)},
10267  {"value", target[i]}
10268  });
10269  ++i;
10270  }
10271 
10272  break;
10273  }
10274 
10275  case value_t::object:
10276  {
10277  // first pass: traverse this object's elements
10278  for (auto it = source.begin(); it != source.end(); ++it)
10279  {
10280  // escape the key name to be used in a JSON patch
10281  const auto key = json_pointer::escape(it.key());
10282 
10283  if (target.find(it.key()) != target.end())
10284  {
10285  // recursive call to compare object values at key it
10286  auto temp_diff = diff(it.value(), target[it.key()], path + "/" + key);
10287  result.insert(result.end(), temp_diff.begin(), temp_diff.end());
10288  }
10289  else
10290  {
10291  // found a key that is not in o -> remove it
10292  result.push_back(object(
10293  {
10294  {"op", "remove"},
10295  {"path", path + "/" + key}
10296  }));
10297  }
10298  }
10299 
10300  // second pass: traverse other object's elements
10301  for (auto it = target.begin(); it != target.end(); ++it)
10302  {
10303  if (source.find(it.key()) == source.end())
10304  {
10305  // found a key that is not in this -> add it
10306  const auto key = json_pointer::escape(it.key());
10307  result.push_back(
10308  {
10309  {"op", "add"},
10310  {"path", path + "/" + key},
10311  {"value", it.value()}
10312  });
10313  }
10314  }
10315 
10316  break;
10317  }
10318 
10319  default:
10320  {
10321  // both primitive type: replace value
10322  result.push_back(
10323  {
10324  {"op", "replace"},
10325  {"path", path},
10326  {"value", target}
10327  });
10328  break;
10329  }
10330  }
10331  }
10332 
10333  return result;
10334  }
10335 
10337 };
10338 
10339 
10341 // presets //
10343 
10352 using json = basic_json<>;
10353 }
10354 
10355 
10357 // nonmember support //
10359 
10360 // specialization of std::swap, and std::hash
10361 namespace std
10362 {
10368 template <>
10369 inline void swap(nlohmann::json& j1,
10370  nlohmann::json& j2) noexcept(
10371  is_nothrow_move_constructible<nlohmann::json>::value and
10372  is_nothrow_move_assignable<nlohmann::json>::value
10373  )
10374 {
10375  j1.swap(j2);
10376 }
10377 
10379 template <>
10380 struct hash<nlohmann::json>
10381 {
10387  std::size_t operator()(const nlohmann::json& j) const
10388  {
10389  // a naive hashing via the string representation
10390  const auto& h = hash<nlohmann::json::string_t>();
10391  return h(j.dump());
10392  }
10393 };
10394 }
10395 
10408 inline nlohmann::json operator "" _json(const char* s, std::size_t)
10409 {
10410  return nlohmann::json::parse(reinterpret_cast<const nlohmann::json::string_t::value_type*>(s));
10411 }
10412 
10425 inline nlohmann::json::json_pointer operator "" _json_pointer(const char* s, std::size_t)
10426 {
10427  return nlohmann::json::json_pointer(s);
10428 }
10429 
10430 // restore GCC/clang diagnostic settings
10431 #if defined(__clang__) || defined(__GNUC__) || defined(__GNUG__)
10432  #pragma GCC diagnostic pop
10433 #endif
10434 
10435 #endif
const_iterator(pointer object) noexcept
constructor for a given JSON instance
Definition: json.hpp:6631
friend bool operator<=(const_reference lhs, const_reference rhs) noexcept
comparison: less than or equal
Definition: json.hpp:5793
basic_json(const value_t value_type)
create an empty value with a given type
Definition: json.hpp:1053
basic_json(const array_t &val)
create an array (explicit)
Definition: json.hpp:1200
static basic_json parse(const string_t &s, const parser_callback_t cb=nullptr)
deserialize from string
Definition: json.hpp:5949
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:4317
const_reference operator[](size_type idx) const
access specified array element
Definition: json.hpp:3438
reference value() const
return the value of an iterator
Definition: json.hpp:7342
json_reverse_iterator & operator--()
pre-decrement (–it)
Definition: json.hpp:7404
void clear() noexcept
clears the contents
Definition: json.hpp:4875
bool operator==(const const_iterator &other) const
comparison: equal
Definition: json.hpp:6953
json_reverse_iterator operator--(int)
post-decrement (it–)
Definition: json.hpp:7398
reference operator[](T *(&key)[n])
access specified object element
Definition: json.hpp:3568
friend std::istream & operator>>(std::istream &i, basic_json &j)
deserialize from stream
Definition: json.hpp:6027
constexpr bool is_number_float() const noexcept
return whether value is a floating-point number
Definition: json.hpp:2488
const_reverse_iterator rend() const noexcept
returns a const reverse iterator to one before the first
Definition: json.hpp:4543
iterator & operator+=(difference_type i)
add to iterator
Definition: json.hpp:7300
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:1797
const_iterator operator-(difference_type i)
subtract from iterator
Definition: json.hpp:7106
BooleanType boolean_t
a type for a boolean
Definition: json.hpp:500
const_iterator cbegin() const noexcept
returns a const iterator to the first element
Definition: json.hpp:4397
reference operator+=(const typename object_t::value_type &val)
add an object to an object
Definition: json.hpp:5058
reference operator*() const
return a reference to the value pointed to by the iterator
Definition: json.hpp:7258
basic_json(const typename string_t::value_type *val)
create a string (explicit)
Definition: json.hpp:1298
reference operator[](difference_type n) const
access to successor
Definition: json.hpp:7440
iterator find(typename object_t::key_type key)
find an element in a JSON object
Definition: json.hpp:4271
friend bool operator!=(const_reference lhs, const_reference rhs) noexcept
comparison: not equal
Definition: json.hpp:5637
basic_json(const string_t &val)
create a string (explicit)
Definition: json.hpp:1272
void push_back(const basic_json &val)
add an object to an array
Definition: json.hpp:4984
void erase(const size_type idx)
remove element from a JSON array given an index
Definition: json.hpp:4225
ArrayType< basic_json, AllocatorType< basic_json >> array_t
a type for an array
Definition: json.hpp:427
reference front()
access the first element
Definition: json.hpp:3881
void swap(object_t &other)
exchanges the values
Definition: json.hpp:5401
json_reverse_iterator operator-(difference_type i) const
subtract from iterator
Definition: json.hpp:7426
const_iterator & operator+=(difference_type i)
add to iterator
Definition: json.hpp:7055
a class to store JSON values
Definition: json.hpp:221
basic_json(const int val) noexcept
create an integer number from an enum type (explicit)
Definition: json.hpp:1417
reference value() const
return the value of an iterator
Definition: json.hpp:7453
friend bool operator==(std::nullptr_t, const_reference v) noexcept
comparison: equal
Definition: json.hpp:5616
NumberIntegerType number_integer_t
a type for a number (integer)
Definition: json.hpp:572
iterator insert(const_iterator pos, size_type cnt, const basic_json &val)
inserts elements
Definition: json.hpp:5189
const_reference at(const typename object_t::key_type &key) const
access specified object element with bounds checking
Definition: json.hpp:3344
const_iterator operator+(difference_type i)
add to iterator
Definition: json.hpp:7095
constexpr bool is_object() const noexcept
return whether value is an object
Definition: json.hpp:2510
constexpr bool is_number_integer() const noexcept
return whether value is an integer number
Definition: json.hpp:2432
a mutable random access iterator for the basic_json class
Definition: json.hpp:7225
const_iterator operator++(int)
post-increment (it++)
Definition: json.hpp:6867
const_iterator cend() const noexcept
returns a const iterator to one past the last element
Definition: json.hpp:4468
ObjectType< StringType, basic_json, std::less< StringType >, AllocatorType< std::pair< const StringType, basic_json >>> object_t
a type for an object
Definition: json.hpp:381
STL namespace.
NumberUnsignedType number_unsigned_t
a type for a number (unsigned)
Definition: json.hpp:643
typename std::allocator_traits< allocator_type >::const_pointer const_pointer
the type of an element const pointer
Definition: json.hpp:262
static basic_json parse(std::istream &&i, const parser_callback_t cb=nullptr)
deserialize from stream
Definition: json.hpp:5988
basic_json(const number_integer_t val) noexcept
create an integer number (explicit)
Definition: json.hpp:1386
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:1757
static iteration_proxy< const_iterator > iterator_wrapper(const_reference cont)
wrapper to access iterator member functions in range-based for
Definition: json.hpp:4630
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:2125
constexpr value_t type() const noexcept
return the type of the JSON value (explicit)
Definition: json.hpp:2272
typename basic_json::value_type value_type
the type of the values when the iterator is dereferenced
Definition: json.hpp:6612
json_reverse_iterator(const typename base_iterator::iterator_type &it) noexcept
create reverse iterator from iterator
Definition: json.hpp:7375
PointerType get_ptr() noexcept
get a pointer value (implicit)
Definition: json.hpp:3030
constexpr bool is_string() const noexcept
return whether value is a string
Definition: json.hpp:2554
reference back()
access the last element
Definition: json.hpp:3923
basic_json(std::istream &i, const parser_callback_t cb=nullptr)
construct a JSON value given an input stream
Definition: json.hpp:1979
const value_type & const_reference
the type of an element const reference
Definition: json.hpp:249
typename basic_json::const_pointer pointer
defines a pointer to the type iterated over (value_type)
Definition: json.hpp:6616
void push_back(const typename object_t::value_type &val)
add an object to an object
Definition: json.hpp:5034
void push_back(std::initializer_list< basic_json > init)
add an object to an object
Definition: json.hpp:5089
json_pointer(const std::string &s="")
create JSON pointer
Definition: json.hpp:9152
const_reference operator[](T *(&key)[n]) const
read-only access specified object element
Definition: json.hpp:3603
iterator insert(const_iterator pos, const_iterator first, const_iterator last)
inserts elements
Definition: json.hpp:5241
basic_json(std::nullptr_t) noexcept
create a null object (explicitly)
Definition: json.hpp:1110
basic_json(InputIT first, InputIT last)
construct a JSON container given an iterator range
Definition: json.hpp:1870
reference operator[](difference_type n) const
access to successor
Definition: json.hpp:7336
static allocator_type get_allocator()
returns the allocator associated with the container
Definition: json.hpp:279
const_reference operator[](const typename object_t::key_type &key) const
read-only access specified object element
Definition: json.hpp:3526
const_reference operator[](T *key) const
read-only access specified object element
Definition: json.hpp:3685
json_reverse_iterator operator+(difference_type i) const
add to iterator
Definition: json.hpp:7418
bool empty() const noexcept
checks whether the container is empty
Definition: json.hpp:4682
std::size_t size_type
a type to represent container sizes
Definition: json.hpp:254
object_t::key_type key() const
return the key of an object iterator
Definition: json.hpp:7446
const_iterator(const iterator &other) noexcept
copy constructor given a non-const iterator
Definition: json.hpp:6663
basic_json(const CompatibleArrayType &val)
create an array (implicit)
Definition: json.hpp:1242
constexpr bool is_boolean() const noexcept
return whether value is a boolean
Definition: json.hpp:2373
const_reference at(size_type idx) const
access specified array element with bounds checking
Definition: json.hpp:3250
basic_json(size_type cnt, const basic_json &val)
construct an array with count copies of given value
Definition: json.hpp:1821
std::reverse_iterator< Base > base_iterator
shortcut to the reverse iterator adaptor
Definition: json.hpp:7370
const_reverse_iterator crbegin() const noexcept
returns a const reverse iterator to the last element
Definition: json.hpp:4572
iterator insert(const_iterator pos, std::initializer_list< basic_json > ilist)
inserts elements
Definition: json.hpp:5299
typename std::allocator_traits< allocator_type >::pointer pointer
the type of an element pointer
Definition: json.hpp:260
iterator insert(const_iterator pos, const basic_json &val)
inserts element
Definition: json.hpp:5134
friend bool operator>=(const_reference lhs, const_reference rhs) noexcept
comparison: greater than or equal
Definition: json.hpp:5837
friend bool operator<(const_reference lhs, const_reference rhs) noexcept
comparison: less than
Definition: json.hpp:5698
iterator & operator++()
pre-increment (++it)
Definition: json.hpp:7278
bool operator<(const const_iterator &other) const
comparison: smaller
Definition: json.hpp:6995
iterator operator++(int)
post-increment (it++)
Definition: json.hpp:7270
basic_json(basic_json &&other) noexcept
move constructor
Definition: json.hpp:2088
const_iterator operator--(int)
post-decrement (it–)
Definition: json.hpp:6910
reference at(const typename object_t::key_type &key)
access specified object element with bounds checking
Definition: json.hpp:3297
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:7246
object (unordered set of name/value pairs)
size_type max_size() const noexcept
returns the maximum possible number of elements
Definition: json.hpp:4816
~basic_json()
destructor
Definition: json.hpp:2158
iterator operator--(int)
post-decrement (it–)
Definition: json.hpp:7285
iterator operator-(difference_type i)
subtract from iterator
Definition: json.hpp:7322
string_t value(const json_pointer &ptr, const char *default_value) const
overload for a default value of type const char*
Definition: json.hpp:3852
const_iterator & operator--()
pre-decrement (–it)
Definition: json.hpp:6921
string_t dump(const int indent=-1) const
serialization
Definition: json.hpp:2230
basic_json value_type
the type of elements in a basic_json container
Definition: json.hpp:244
std::function< bool(int depth, parse_event_t event, basic_json &parsed)> parser_callback_t
per-element parser callback type
Definition: json.hpp:1002
AllocatorType< basic_json > allocator_type
the allocator type
Definition: json.hpp:257
StringType string_t
a type for a string
Definition: json.hpp:474
reference operator+=(const basic_json &val)
add an object to an array
Definition: json.hpp:5008
reference operator+=(std::initializer_list< basic_json > init)
add an object to an object
Definition: json.hpp:5106
difference_type operator-(const const_iterator &other) const
return difference
Definition: json.hpp:7117
value_type & reference
the type of an element reference
Definition: json.hpp:247
const_reverse_iterator rbegin() const noexcept
returns a const reverse iterator to the last element
Definition: json.hpp:4506
friend std::ostream & operator>>(const basic_json &j, std::ostream &o)
serialize to stream
Definition: json.hpp:5910
constexpr bool is_discarded() const noexcept
return whether value is discarded
Definition: json.hpp:2581
const_iterator begin() const noexcept
returns a const iterator to the first element
Definition: json.hpp:4367
difference_type operator-(const iterator &other) const
return difference
Definition: json.hpp:7330
constexpr bool is_array() const noexcept
return whether value is an array
Definition: json.hpp:2532
iterator(const iterator &other) noexcept
copy constructor
Definition: json.hpp:7241
namespace for Niels Lohmann
Definition: json.hpp:81
typename basic_json::difference_type difference_type
a type to represent differences between iterators
Definition: json.hpp:6614
void swap(string_t &other)
exchanges the values
Definition: json.hpp:5434
basic_json(const CompatibleNumberIntegerType val) noexcept
create an integer number (implicit)
Definition: json.hpp:1456
const_reference front() const
access the first element
Definition: json.hpp:3889
bool operator>(const const_iterator &other) const
comparison: greater than
Definition: json.hpp:7037
constexpr const PointerType get_ptr() const noexcept
get a pointer value (implicit)
Definition: json.hpp:3060
pointer operator->() const
dereference the iterator
Definition: json.hpp:6831
NumberFloatType number_float_t
a type for a number (floating-point)
Definition: json.hpp:711
const_reverse_iterator crend() const noexcept
returns a const reverse iterator to one before the first
Definition: json.hpp:4601
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:5336
value_t
the JSON type enumeration
Definition: json.hpp:742
reverse_iterator rbegin() noexcept
returns an iterator to the reverse-beginning
Definition: json.hpp:4498
constexpr bool is_null() const noexcept
return whether value is null
Definition: json.hpp:2351
std::ptrdiff_t difference_type
a type to represent differences between iterators
Definition: json.hpp:252
ValueType get() const
get a value (explicit)
Definition: json.hpp:2944
void swap(array_t &other)
exchanges the values
Definition: json.hpp:5368
InteratorType erase(InteratorType first, InteratorType last)
remove elements given an iterator range
Definition: json.hpp:4100
ValueType value(const typename object_t::key_type &key, ValueType default_value) const
access specified object element with default value
Definition: json.hpp:3751
typename Base::reference reference
the reference type for the pointed-to element
Definition: json.hpp:7372
const_reference back() const
access the last element
Definition: json.hpp:3933
void push_back(basic_json &&val)
add an object to an array
Definition: json.hpp:4948
array (ordered collection of values)
constexpr bool is_number_unsigned() const noexcept
return whether value is an unsigned integer number
Definition: json.hpp:2460
json_reverse_iterator & operator++()
pre-increment (++it)
Definition: json.hpp:7391
friend bool operator==(const_reference lhs, const_reference rhs) noexcept
comparison: equal
Definition: json.hpp:5514
static basic_json parse(std::istream &i, const parser_callback_t cb=nullptr)
deserialize from stream
Definition: json.hpp:5979
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:3777
ReferenceType get_ref() const
get a reference value (implicit)
Definition: json.hpp:3126
basic_json(const CompatibleNumberUnsignedType val) noexcept
create an unsigned number (implicit)
Definition: json.hpp:1519
reference operator*() const
return a reference to the value pointed to by the iterator
Definition: json.hpp:6790
ValueType value(const json_pointer &ptr, ValueType default_value) const
access specified object element via JSON Pointer with default value
Definition: json.hpp:3827
friend bool operator<(const value_t lhs, const value_t rhs) noexcept
comparison operator for JSON types
Definition: json.hpp:5467
basic_json(const number_float_t val) noexcept
create a floating-point number (explicit)
Definition: json.hpp:1550
friend bool operator!=(const_reference v, std::nullptr_t) noexcept
comparison: not equal
Definition: json.hpp:5660
iterator operator+(difference_type i)
add to iterator
Definition: json.hpp:7314
basic_json(const CompatibleNumberFloatType val) noexcept
create an floating-point number (implicit)
Definition: json.hpp:1599
bool operator<=(const const_iterator &other) const
comparison: less than or equal
Definition: json.hpp:7028
InteratorType erase(InteratorType pos)
remove element given an iterator
Definition: json.hpp:3991
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:1674
iterator(pointer object) noexcept
constructor for a given JSON instance
Definition: json.hpp:7236
friend bool operator!=(std::nullptr_t, const_reference v) noexcept
comparison: not equal
Definition: json.hpp:5669
constexpr bool is_primitive() const noexcept
return whether type is primitive
Definition: json.hpp:2302
const_iterator & operator++()
pre-increment (++it)
Definition: json.hpp:6878
pointer operator->() const
dereference the iterator
Definition: json.hpp:7264
reference value() const
return the value of an iterator
Definition: json.hpp:7201
constexpr bool is_structured() const noexcept
return whether type is structured
Definition: json.hpp:2329
std::bidirectional_iterator_tag iterator_category
the category of the iterator
Definition: json.hpp:6620
basic_json(boolean_t val) noexcept
create a boolean (explicit)
Definition: json.hpp:1351
iterator end() noexcept
returns an iterator to one past the last element
Definition: json.hpp:4428
reverse_iterator rend() noexcept
returns an iterator to the reverse-end
Definition: json.hpp:4535
difference_type operator-(const json_reverse_iterator &other) const
return difference
Definition: json.hpp:7434
const_iterator find(typename object_t::key_type key) const
find an element in a JSON object
Definition: json.hpp:4287
iterator begin() noexcept
returns an iterator to the first element
Definition: json.hpp:4357
basic_json(const CompatibleObjectType &val)
create an object (implicit)
Definition: json.hpp:1172
const_iterator end() const noexcept
returns a const iterator to one past the last element
Definition: json.hpp:4438
friend bool operator>(const_reference lhs, const_reference rhs) noexcept
comparison: greater than
Definition: json.hpp:5815
bool operator>=(const const_iterator &other) const
comparison: greater than or equal
Definition: json.hpp:7046
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:6705
size_type erase(const typename object_t::key_type &key)
remove element from a JSON object given a key
Definition: json.hpp:4188
reference operator[](const typename object_t::key_type &key)
access specified object element
Definition: json.hpp:3478
object_t::key_type key() const
return the key of an object iterator
Definition: json.hpp:7183
reference operator+=(basic_json &&val)
add an object to an array
Definition: json.hpp:4974
reference operator[](difference_type n) const
access to successor
Definition: json.hpp:7144
a const random access iterator for the basic_json class
Definition: json.hpp:6605
constexpr bool is_number() const noexcept
return whether value is a number
Definition: json.hpp:2403
a template for a reverse iterator class
Definition: json.hpp:231
typename basic_json::const_reference reference
defines a reference to the type iterated over (value_type)
Definition: json.hpp:6618
json_reverse_iterator operator++(int)
post-increment (it++)
Definition: json.hpp:7385
friend bool operator==(const_reference v, std::nullptr_t) noexcept
comparison: equal
Definition: json.hpp:5607
reference operator[](size_type idx)
access specified array element
Definition: json.hpp:3390
bool operator!=(const const_iterator &other) const
comparison: not equal
Definition: json.hpp:6986
json_reverse_iterator & operator+=(difference_type i)
add to iterator
Definition: json.hpp:7411
reference at(size_type idx)
access specified array element with bounds checking
Definition: json.hpp:3207
size_type size() const noexcept
returns the number of elements
Definition: json.hpp:4750
static iteration_proxy< iterator > iterator_wrapper(reference cont)
wrapper to access iterator member functions in range-based for
Definition: json.hpp:4622
iterator & operator-=(difference_type i)
subtract from iterator
Definition: json.hpp:7307
basic_json(const object_t &val)
create an object (explicit)
Definition: json.hpp:1135
basic_json(const number_unsigned_t val) noexcept
create an unsigned integer number (explicit)
Definition: json.hpp:1486
friend std::istream & operator<<(basic_json &j, std::istream &i)
deserialize from stream
Definition: json.hpp:6017
json_reverse_iterator(const base_iterator &it) noexcept
create reverse iterator from base class
Definition: json.hpp:7380
friend std::ostream & operator<<(std::ostream &o, const basic_json &j)
serialize to stream
Definition: json.hpp:5878
const_iterator(const const_iterator &other) noexcept
copy constructor
Definition: json.hpp:6696
iterator & operator--()
pre-decrement (–it)
Definition: json.hpp:7293
iterator insert(const_iterator pos, basic_json &&val)
inserts element
Definition: json.hpp:5160
ReferenceType get_ref()
get a reference value (implicit)
Definition: json.hpp:3111
const_iterator & operator-=(difference_type i)
subtract from iterator
Definition: json.hpp:7086
basic_json(const CompatibleStringType &val)
create a string (implicit)
Definition: json.hpp:1331
basic_json(const basic_json &other)
copy constructor
Definition: json.hpp:2011
reference operator[](T *key)
access specified object element
Definition: json.hpp:3636
parse_event_t
JSON callback events.
Definition: json.hpp:932