JSON for Modern C++  2.0.6
json.hpp
1 /*
2  __ _____ _____ _____
3  __| | __| | | | JSON for Modern C++
4 | | |__ | | | | | | version 2.0.6
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 <cctype>
36 #include <ciso646>
37 #include <cmath>
38 #include <cstddef>
39 #include <cstdint>
40 #include <cstdlib>
41 #include <cstring>
42 #include <functional>
43 #include <initializer_list>
44 #include <iomanip>
45 #include <iostream>
46 #include <iterator>
47 #include <limits>
48 #include <locale>
49 #include <map>
50 #include <memory>
51 #include <numeric>
52 #include <sstream>
53 #include <stdexcept>
54 #include <string>
55 #include <type_traits>
56 #include <utility>
57 #include <vector>
58 
59 // exclude unsupported compilers
60 #if defined(__clang__)
61  #define CLANG_VERSION (__clang_major__ * 10000 + __clang_minor__ * 100 + __clang_patchlevel__)
62  #if CLANG_VERSION < 30400
63  #error "unsupported Clang version - see https://github.com/nlohmann/json#supported-compilers"
64  #endif
65 #elif defined(__GNUC__)
66  #define GCC_VERSION (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__)
67  #if GCC_VERSION < 40900
68  #error "unsupported GCC version - see https://github.com/nlohmann/json#supported-compilers"
69  #endif
70 #endif
71 
72 // disable float-equal warnings on GCC/clang
73 #if defined(__clang__) || defined(__GNUC__) || defined(__GNUG__)
74  #pragma GCC diagnostic push
75  #pragma GCC diagnostic ignored "-Wfloat-equal"
76 #endif
77 
78 // allow for portable deprecation warnings
79 #if defined(__clang__) || defined(__GNUC__) || defined(__GNUG__)
80  #define JSON_DEPRECATED __attribute__((deprecated))
81 #elif defined(_MSC_VER)
82  #define JSON_DEPRECATED __declspec(deprecated)
83 #else
84  #define JSON_DEPRECATED
85 #endif
86 
92 namespace nlohmann
93 {
94 
95 
100 namespace
101 {
112 template<typename T>
113 struct has_mapped_type
114 {
115  private:
116  template <typename U, typename = typename U::mapped_type>
117  static int detect(U&&);
118 
119  static void detect(...);
120  public:
121  static constexpr bool value =
122  std::is_integral<decltype(detect(std::declval<T>()))>::value;
123 };
124 
137 struct DecimalSeparator : std::numpunct<char>
138 {
139  char do_decimal_point() const
140  {
141  return '.';
142  }
143 };
144 
145 }
146 
225 template <
226  template<typename U, typename V, typename... Args> class ObjectType = std::map,
227  template<typename U, typename... Args> class ArrayType = std::vector,
228  class StringType = std::string,
229  class BooleanType = bool,
230  class NumberIntegerType = std::int64_t,
231  class NumberUnsignedType = std::uint64_t,
232  class NumberFloatType = double,
233  template<typename U> class AllocatorType = std::allocator
234  >
236 {
237  private:
239  using basic_json_t = basic_json<ObjectType, ArrayType, StringType,
240  BooleanType, NumberIntegerType, NumberUnsignedType, NumberFloatType,
241  AllocatorType>;
242 
243  public:
244  // forward declarations
245  template<typename Base> class json_reverse_iterator;
246  class json_pointer;
247 
249  // container types //
251 
256 
259 
263  using const_reference = const value_type&;
264 
266  using difference_type = std::ptrdiff_t;
268  using size_type = std::size_t;
269 
271  using allocator_type = AllocatorType<basic_json>;
272 
274  using pointer = typename std::allocator_traits<allocator_type>::pointer;
276  using const_pointer = typename std::allocator_traits<allocator_type>::const_pointer;
277 
279  class iterator;
281  class const_iterator;
286 
288 
289 
294  {
295  return allocator_type();
296  }
297 
298 
300  // JSON value data types //
302 
307 
391  using object_t = ObjectType<StringType,
392  basic_json,
393  std::less<StringType>,
394  AllocatorType<std::pair<const StringType,
395  basic_json>>>;
396 
441  using array_t = ArrayType<basic_json, AllocatorType<basic_json>>;
442 
488  using string_t = StringType;
489 
514  using boolean_t = BooleanType;
515 
586  using number_integer_t = NumberIntegerType;
587 
657  using number_unsigned_t = NumberUnsignedType;
658 
725  using number_float_t = NumberFloatType;
726 
728 
729 
731  // JSON type enumeration //
733 
756  enum class value_t : uint8_t
757  {
758  null,
759  object,
760  array,
761  string,
762  boolean,
763  number_integer,
764  number_unsigned,
765  number_float,
766  discarded
767  };
768 
769 
770  private:
771 
773  template<typename T, typename... Args>
774  static T* create(Args&& ... args)
775  {
776  AllocatorType<T> alloc;
777  auto deleter = [&](T * object)
778  {
779  alloc.deallocate(object, 1);
780  };
781  std::unique_ptr<T, decltype(deleter)> object(alloc.allocate(1), deleter);
782  alloc.construct(object.get(), std::forward<Args>(args)...);
783  assert(object.get() != nullptr);
784  return object.release();
785  }
786 
788  // JSON value storage //
790 
815  union json_value
816  {
818  object_t* object;
820  array_t* array;
822  string_t* string;
824  boolean_t boolean;
826  number_integer_t number_integer;
828  number_unsigned_t number_unsigned;
830  number_float_t number_float;
831 
833  json_value() = default;
835  json_value(boolean_t v) noexcept : boolean(v) {}
837  json_value(number_integer_t v) noexcept : number_integer(v) {}
839  json_value(number_unsigned_t v) noexcept : number_unsigned(v) {}
841  json_value(number_float_t v) noexcept : number_float(v) {}
843  json_value(value_t t)
844  {
845  switch (t)
846  {
847  case value_t::object:
848  {
849  object = create<object_t>();
850  break;
851  }
852 
853  case value_t::array:
854  {
855  array = create<array_t>();
856  break;
857  }
858 
859  case value_t::string:
860  {
861  string = create<string_t>("");
862  break;
863  }
864 
865  case value_t::boolean:
866  {
867  boolean = boolean_t(false);
868  break;
869  }
870 
871  case value_t::number_integer:
872  {
873  number_integer = number_integer_t(0);
874  break;
875  }
876 
877  case value_t::number_unsigned:
878  {
879  number_unsigned = number_unsigned_t(0);
880  break;
881  }
882 
883  case value_t::number_float:
884  {
885  number_float = number_float_t(0.0);
886  break;
887  }
888 
889  default:
890  {
891  break;
892  }
893  }
894  }
895 
897  json_value(const string_t& value)
898  {
899  string = create<string_t>(value);
900  }
901 
903  json_value(const object_t& value)
904  {
905  object = create<object_t>(value);
906  }
907 
909  json_value(const array_t& value)
910  {
911  array = create<array_t>(value);
912  }
913  };
914 
924  void assert_invariant() const
925  {
926  assert(m_type != value_t::object or m_value.object != nullptr);
927  assert(m_type != value_t::array or m_value.array != nullptr);
928  assert(m_type != value_t::string or m_value.string != nullptr);
929  }
930 
931  public:
933  // JSON parser callback //
935 
946  enum class parse_event_t : uint8_t
947  {
949  object_start,
951  object_end,
953  array_start,
955  array_end,
957  key,
959  value
960  };
961 
1014  using parser_callback_t = std::function<bool(int depth,
1015  parse_event_t event,
1016  basic_json& parsed)>;
1017 
1018 
1020  // constructors //
1022 
1027 
1068  : m_type(value_type), m_value(value_type)
1069  {
1070  assert_invariant();
1071  }
1072 
1091  basic_json(std::nullptr_t = nullptr) noexcept
1092  : basic_json(value_t::null)
1093  {
1094  assert_invariant();
1095  }
1096 
1116  basic_json(const object_t& val)
1117  : m_type(value_t::object), m_value(val)
1118  {
1119  assert_invariant();
1120  }
1121 
1148  template<class CompatibleObjectType, typename std::enable_if<
1149  std::is_constructible<typename object_t::key_type, typename CompatibleObjectType::key_type>::value and
1150  std::is_constructible<basic_json, typename CompatibleObjectType::mapped_type>::value, int>::type = 0>
1151  basic_json(const CompatibleObjectType& val)
1152  : m_type(value_t::object)
1153  {
1154  using std::begin;
1155  using std::end;
1156  m_value.object = create<object_t>(begin(val), end(val));
1157  assert_invariant();
1158  }
1159 
1179  basic_json(const array_t& val)
1180  : m_type(value_t::array), m_value(val)
1181  {
1182  assert_invariant();
1183  }
1184 
1211  template<class CompatibleArrayType, typename std::enable_if<
1212  not std::is_same<CompatibleArrayType, typename basic_json_t::iterator>::value and
1213  not std::is_same<CompatibleArrayType, typename basic_json_t::const_iterator>::value and
1214  not std::is_same<CompatibleArrayType, typename basic_json_t::reverse_iterator>::value and
1215  not std::is_same<CompatibleArrayType, typename basic_json_t::const_reverse_iterator>::value and
1216  not std::is_same<CompatibleArrayType, typename array_t::iterator>::value and
1217  not std::is_same<CompatibleArrayType, typename array_t::const_iterator>::value and
1218  std::is_constructible<basic_json, typename CompatibleArrayType::value_type>::value, int>::type = 0>
1219  basic_json(const CompatibleArrayType& val)
1220  : m_type(value_t::array)
1221  {
1222  using std::begin;
1223  using std::end;
1224  m_value.array = create<array_t>(begin(val), end(val));
1225  assert_invariant();
1226  }
1227 
1249  basic_json(const string_t& val)
1250  : m_type(value_t::string), m_value(val)
1251  {
1252  assert_invariant();
1253  }
1254 
1275  basic_json(const typename string_t::value_type* val)
1276  : basic_json(string_t(val))
1277  {
1278  assert_invariant();
1279  }
1280 
1304  template<class CompatibleStringType, typename std::enable_if<
1305  std::is_constructible<string_t, CompatibleStringType>::value, int>::type = 0>
1306  basic_json(const CompatibleStringType& val)
1307  : basic_json(string_t(val))
1308  {
1309  assert_invariant();
1310  }
1311 
1326  basic_json(boolean_t val) noexcept
1327  : m_type(value_t::boolean), m_value(val)
1328  {
1329  assert_invariant();
1330  }
1331 
1355  template<typename T, typename std::enable_if<
1356  not (std::is_same<T, int>::value) and
1357  std::is_same<T, number_integer_t>::value, int>::type = 0>
1358  basic_json(const number_integer_t val) noexcept
1359  : m_type(value_t::number_integer), m_value(val)
1360  {
1361  assert_invariant();
1362  }
1363 
1389  basic_json(const int val) noexcept
1390  : m_type(value_t::number_integer),
1391  m_value(static_cast<number_integer_t>(val))
1392  {
1393  assert_invariant();
1394  }
1395 
1421  template<typename CompatibleNumberIntegerType, typename std::enable_if<
1422  std::is_constructible<number_integer_t, CompatibleNumberIntegerType>::value and
1423  std::numeric_limits<CompatibleNumberIntegerType>::is_integer and
1424  std::numeric_limits<CompatibleNumberIntegerType>::is_signed,
1425  CompatibleNumberIntegerType>::type = 0>
1426  basic_json(const CompatibleNumberIntegerType val) noexcept
1427  : m_type(value_t::number_integer),
1428  m_value(static_cast<number_integer_t>(val))
1429  {
1430  assert_invariant();
1431  }
1432 
1450  template<typename T, typename std::enable_if<
1451  not (std::is_same<T, int>::value) and
1452  std::is_same<T, number_unsigned_t>::value, int>::type = 0>
1453  basic_json(const number_unsigned_t val) noexcept
1454  : m_type(value_t::number_unsigned), m_value(val)
1455  {
1456  assert_invariant();
1457  }
1458 
1479  template<typename CompatibleNumberUnsignedType, typename std::enable_if <
1480  std::is_constructible<number_unsigned_t, CompatibleNumberUnsignedType>::value and
1481  std::numeric_limits<CompatibleNumberUnsignedType>::is_integer and
1482  not std::numeric_limits<CompatibleNumberUnsignedType>::is_signed,
1483  CompatibleNumberUnsignedType>::type = 0>
1484  basic_json(const CompatibleNumberUnsignedType val) noexcept
1485  : m_type(value_t::number_unsigned),
1486  m_value(static_cast<number_unsigned_t>(val))
1487  {
1488  assert_invariant();
1489  }
1490 
1515  basic_json(const number_float_t val) noexcept
1516  : m_type(value_t::number_float), m_value(val)
1517  {
1518  // replace infinity and NAN by null
1519  if (not std::isfinite(val))
1520  {
1521  m_type = value_t::null;
1522  m_value = json_value();
1523  }
1524 
1525  assert_invariant();
1526  }
1527 
1559  template<typename CompatibleNumberFloatType, typename = typename std::enable_if<
1560  std::is_constructible<number_float_t, CompatibleNumberFloatType>::value and
1561  std::is_floating_point<CompatibleNumberFloatType>::value>::type>
1562  basic_json(const CompatibleNumberFloatType val) noexcept
1563  : basic_json(number_float_t(val))
1564  {
1565  assert_invariant();
1566  }
1567 
1637  basic_json(std::initializer_list<basic_json> init,
1638  bool type_deduction = true,
1639  value_t manual_type = value_t::array)
1640  {
1641  // check if each element is an array with two elements whose first
1642  // element is a string
1643  bool is_an_object = std::all_of(init.begin(), init.end(),
1644  [](const basic_json & element)
1645  {
1646  return element.is_array() and element.size() == 2 and element[0].is_string();
1647  });
1648 
1649  // adjust type if type deduction is not wanted
1650  if (not type_deduction)
1651  {
1652  // if array is wanted, do not create an object though possible
1653  if (manual_type == value_t::array)
1654  {
1655  is_an_object = false;
1656  }
1657 
1658  // if object is wanted but impossible, throw an exception
1659  if (manual_type == value_t::object and not is_an_object)
1660  {
1661  throw std::domain_error("cannot create object from initializer list");
1662  }
1663  }
1664 
1665  if (is_an_object)
1666  {
1667  // the initializer list is a list of pairs -> create object
1668  m_type = value_t::object;
1669  m_value = value_t::object;
1670 
1671  std::for_each(init.begin(), init.end(), [this](const basic_json & element)
1672  {
1673  m_value.object->emplace(*(element[0].m_value.string), element[1]);
1674  });
1675  }
1676  else
1677  {
1678  // the initializer list describes an array -> create array
1679  m_type = value_t::array;
1680  m_value.array = create<array_t>(init);
1681  }
1682 
1683  assert_invariant();
1684  }
1685 
1720  static basic_json array(std::initializer_list<basic_json> init =
1721  std::initializer_list<basic_json>())
1722  {
1723  return basic_json(init, false, value_t::array);
1724  }
1725 
1760  static basic_json object(std::initializer_list<basic_json> init =
1761  std::initializer_list<basic_json>())
1762  {
1763  return basic_json(init, false, value_t::object);
1764  }
1765 
1785  : m_type(value_t::array)
1786  {
1787  m_value.array = create<array_t>(cnt, val);
1788  assert_invariant();
1789  }
1790 
1828  template<class InputIT, typename std::enable_if<
1829  std::is_same<InputIT, typename basic_json_t::iterator>::value or
1830  std::is_same<InputIT, typename basic_json_t::const_iterator>::value, int>::type = 0>
1831  basic_json(InputIT first, InputIT last)
1832  {
1833  assert(first.m_object != nullptr);
1834  assert(last.m_object != nullptr);
1835 
1836  // make sure iterator fits the current value
1837  if (first.m_object != last.m_object)
1838  {
1839  throw std::domain_error("iterators are not compatible");
1840  }
1841 
1842  // copy type from first iterator
1843  m_type = first.m_object->m_type;
1844 
1845  // check if iterator range is complete for primitive values
1846  switch (m_type)
1847  {
1848  case value_t::boolean:
1849  case value_t::number_float:
1850  case value_t::number_integer:
1851  case value_t::number_unsigned:
1852  case value_t::string:
1853  {
1854  if (not first.m_it.primitive_iterator.is_begin() or not last.m_it.primitive_iterator.is_end())
1855  {
1856  throw std::out_of_range("iterators out of range");
1857  }
1858  break;
1859  }
1860 
1861  default:
1862  {
1863  break;
1864  }
1865  }
1866 
1867  switch (m_type)
1868  {
1869  case value_t::number_integer:
1870  {
1871  m_value.number_integer = first.m_object->m_value.number_integer;
1872  break;
1873  }
1874 
1875  case value_t::number_unsigned:
1876  {
1877  m_value.number_unsigned = first.m_object->m_value.number_unsigned;
1878  break;
1879  }
1880 
1881  case value_t::number_float:
1882  {
1883  m_value.number_float = first.m_object->m_value.number_float;
1884  break;
1885  }
1886 
1887  case value_t::boolean:
1888  {
1889  m_value.boolean = first.m_object->m_value.boolean;
1890  break;
1891  }
1892 
1893  case value_t::string:
1894  {
1895  m_value = *first.m_object->m_value.string;
1896  break;
1897  }
1898 
1899  case value_t::object:
1900  {
1901  m_value.object = create<object_t>(first.m_it.object_iterator, last.m_it.object_iterator);
1902  break;
1903  }
1904 
1905  case value_t::array:
1906  {
1907  m_value.array = create<array_t>(first.m_it.array_iterator, last.m_it.array_iterator);
1908  break;
1909  }
1910 
1911  default:
1912  {
1913  throw std::domain_error("cannot use construct with iterators from " + first.m_object->type_name());
1914  }
1915  }
1916 
1917  assert_invariant();
1918  }
1919 
1948  JSON_DEPRECATED
1949  explicit basic_json(std::istream& i, const parser_callback_t cb = nullptr)
1950  {
1951  *this = parser(i, cb).parse();
1952  assert_invariant();
1953  }
1954 
1956  // other constructors and destructor //
1958 
1981  basic_json(const basic_json& other)
1982  : m_type(other.m_type)
1983  {
1984  // check of passed value is valid
1985  other.assert_invariant();
1986 
1987  switch (m_type)
1988  {
1989  case value_t::object:
1990  {
1991  m_value = *other.m_value.object;
1992  break;
1993  }
1994 
1995  case value_t::array:
1996  {
1997  m_value = *other.m_value.array;
1998  break;
1999  }
2000 
2001  case value_t::string:
2002  {
2003  m_value = *other.m_value.string;
2004  break;
2005  }
2006 
2007  case value_t::boolean:
2008  {
2009  m_value = other.m_value.boolean;
2010  break;
2011  }
2012 
2013  case value_t::number_integer:
2014  {
2015  m_value = other.m_value.number_integer;
2016  break;
2017  }
2018 
2019  case value_t::number_unsigned:
2020  {
2021  m_value = other.m_value.number_unsigned;
2022  break;
2023  }
2024 
2025  case value_t::number_float:
2026  {
2027  m_value = other.m_value.number_float;
2028  break;
2029  }
2030 
2031  default:
2032  {
2033  break;
2034  }
2035  }
2036 
2037  assert_invariant();
2038  }
2039 
2058  basic_json(basic_json&& other) noexcept
2059  : m_type(std::move(other.m_type)),
2060  m_value(std::move(other.m_value))
2061  {
2062  // check that passed value is valid
2063  other.assert_invariant();
2064 
2065  // invalidate payload
2066  other.m_type = value_t::null;
2067  other.m_value = {};
2068 
2069  assert_invariant();
2070  }
2071 
2095  reference& operator=(basic_json other) noexcept (
2096  std::is_nothrow_move_constructible<value_t>::value and
2097  std::is_nothrow_move_assignable<value_t>::value and
2098  std::is_nothrow_move_constructible<json_value>::value and
2099  std::is_nothrow_move_assignable<json_value>::value
2100  )
2101  {
2102  // check that passed value is valid
2103  other.assert_invariant();
2104 
2105  using std::swap;
2106  swap(m_type, other.m_type);
2107  swap(m_value, other.m_value);
2108 
2109  assert_invariant();
2110  return *this;
2111  }
2112 
2129  {
2130  assert_invariant();
2131 
2132  switch (m_type)
2133  {
2134  case value_t::object:
2135  {
2136  AllocatorType<object_t> alloc;
2137  alloc.destroy(m_value.object);
2138  alloc.deallocate(m_value.object, 1);
2139  break;
2140  }
2141 
2142  case value_t::array:
2143  {
2144  AllocatorType<array_t> alloc;
2145  alloc.destroy(m_value.array);
2146  alloc.deallocate(m_value.array, 1);
2147  break;
2148  }
2149 
2150  case value_t::string:
2151  {
2152  AllocatorType<string_t> alloc;
2153  alloc.destroy(m_value.string);
2154  alloc.deallocate(m_value.string, 1);
2155  break;
2156  }
2157 
2158  default:
2159  {
2160  // all other types need no specific destructor
2161  break;
2162  }
2163  }
2164  }
2165 
2167 
2168  public:
2170  // object inspection //
2172 
2176 
2200  string_t dump(const int indent = -1) const
2201  {
2202  std::stringstream ss;
2203  // fix locale problems
2204  const static std::locale loc(std::locale(), new DecimalSeparator);
2205  ss.imbue(loc);
2206 
2207  // 6, 15 or 16 digits of precision allows round-trip IEEE 754
2208  // string->float->string, string->double->string or string->long
2209  // double->string; to be safe, we read this value from
2210  // std::numeric_limits<number_float_t>::digits10
2211  ss.precision(std::numeric_limits<double>::digits10);
2212 
2213  if (indent >= 0)
2214  {
2215  dump(ss, true, static_cast<unsigned int>(indent));
2216  }
2217  else
2218  {
2219  dump(ss, false, 0);
2220  }
2221 
2222  return ss.str();
2223  }
2224 
2243  constexpr value_t type() const noexcept
2244  {
2245  return m_type;
2246  }
2247 
2273  constexpr bool is_primitive() const noexcept
2274  {
2275  return is_null() or is_string() or is_boolean() or is_number();
2276  }
2277 
2300  constexpr bool is_structured() const noexcept
2301  {
2302  return is_array() or is_object();
2303  }
2304 
2322  constexpr bool is_null() const noexcept
2323  {
2324  return m_type == value_t::null;
2325  }
2326 
2344  constexpr bool is_boolean() const noexcept
2345  {
2346  return m_type == value_t::boolean;
2347  }
2348 
2374  constexpr bool is_number() const noexcept
2375  {
2376  return is_number_integer() or is_number_float();
2377  }
2378 
2403  constexpr bool is_number_integer() const noexcept
2404  {
2405  return m_type == value_t::number_integer or m_type == value_t::number_unsigned;
2406  }
2407 
2431  constexpr bool is_number_unsigned() const noexcept
2432  {
2433  return m_type == value_t::number_unsigned;
2434  }
2435 
2459  constexpr bool is_number_float() const noexcept
2460  {
2461  return m_type == value_t::number_float;
2462  }
2463 
2481  constexpr bool is_object() const noexcept
2482  {
2483  return m_type == value_t::object;
2484  }
2485 
2503  constexpr bool is_array() const noexcept
2504  {
2505  return m_type == value_t::array;
2506  }
2507 
2525  constexpr bool is_string() const noexcept
2526  {
2527  return m_type == value_t::string;
2528  }
2529 
2552  constexpr bool is_discarded() const noexcept
2553  {
2554  return m_type == value_t::discarded;
2555  }
2556 
2575  constexpr operator value_t() const noexcept
2576  {
2577  return m_type;
2578  }
2579 
2581 
2582  private:
2584  // value access //
2586 
2588  template<class T, typename std::enable_if<
2589  std::is_convertible<typename object_t::key_type, typename T::key_type>::value and
2590  std::is_convertible<basic_json_t, typename T::mapped_type>::value, int>::type = 0>
2591  T get_impl(T*) const
2592  {
2593  if (is_object())
2594  {
2595  return T(m_value.object->begin(), m_value.object->end());
2596  }
2597  else
2598  {
2599  throw std::domain_error("type must be object, but is " + type_name());
2600  }
2601  }
2602 
2604  object_t get_impl(object_t*) const
2605  {
2606  if (is_object())
2607  {
2608  return *(m_value.object);
2609  }
2610  else
2611  {
2612  throw std::domain_error("type must be object, but is " + type_name());
2613  }
2614  }
2615 
2617  template<class T, typename std::enable_if<
2618  std::is_convertible<basic_json_t, typename T::value_type>::value and
2619  not std::is_same<basic_json_t, typename T::value_type>::value and
2620  not std::is_arithmetic<T>::value and
2621  not std::is_convertible<std::string, T>::value and
2622  not has_mapped_type<T>::value, int>::type = 0>
2623  T get_impl(T*) const
2624  {
2625  if (is_array())
2626  {
2627  T to_vector;
2628  std::transform(m_value.array->begin(), m_value.array->end(),
2629  std::inserter(to_vector, to_vector.end()), [](basic_json i)
2630  {
2631  return i.get<typename T::value_type>();
2632  });
2633  return to_vector;
2634  }
2635  else
2636  {
2637  throw std::domain_error("type must be array, but is " + type_name());
2638  }
2639  }
2640 
2642  template<class T, typename std::enable_if<
2643  std::is_convertible<basic_json_t, T>::value and
2644  not std::is_same<basic_json_t, T>::value, int>::type = 0>
2645  std::vector<T> get_impl(std::vector<T>*) const
2646  {
2647  if (is_array())
2648  {
2649  std::vector<T> to_vector;
2650  to_vector.reserve(m_value.array->size());
2651  std::transform(m_value.array->begin(), m_value.array->end(),
2652  std::inserter(to_vector, to_vector.end()), [](basic_json i)
2653  {
2654  return i.get<T>();
2655  });
2656  return to_vector;
2657  }
2658  else
2659  {
2660  throw std::domain_error("type must be array, but is " + type_name());
2661  }
2662  }
2663 
2665  template<class T, typename std::enable_if<
2666  std::is_same<basic_json, typename T::value_type>::value and
2667  not has_mapped_type<T>::value, int>::type = 0>
2668  T get_impl(T*) const
2669  {
2670  if (is_array())
2671  {
2672  return T(m_value.array->begin(), m_value.array->end());
2673  }
2674  else
2675  {
2676  throw std::domain_error("type must be array, but is " + type_name());
2677  }
2678  }
2679 
2681  array_t get_impl(array_t*) const
2682  {
2683  if (is_array())
2684  {
2685  return *(m_value.array);
2686  }
2687  else
2688  {
2689  throw std::domain_error("type must be array, but is " + type_name());
2690  }
2691  }
2692 
2694  template<typename T, typename std::enable_if<
2695  std::is_convertible<string_t, T>::value, int>::type = 0>
2696  T get_impl(T*) const
2697  {
2698  if (is_string())
2699  {
2700  return *m_value.string;
2701  }
2702  else
2703  {
2704  throw std::domain_error("type must be string, but is " + type_name());
2705  }
2706  }
2707 
2709  template<typename T, typename std::enable_if<
2710  std::is_arithmetic<T>::value, int>::type = 0>
2711  T get_impl(T*) const
2712  {
2713  switch (m_type)
2714  {
2715  case value_t::number_integer:
2716  {
2717  return static_cast<T>(m_value.number_integer);
2718  }
2719 
2720  case value_t::number_unsigned:
2721  {
2722  return static_cast<T>(m_value.number_unsigned);
2723  }
2724 
2725  case value_t::number_float:
2726  {
2727  return static_cast<T>(m_value.number_float);
2728  }
2729 
2730  default:
2731  {
2732  throw std::domain_error("type must be number, but is " + type_name());
2733  }
2734  }
2735  }
2736 
2738  constexpr boolean_t get_impl(boolean_t*) const
2739  {
2740  return is_boolean()
2741  ? m_value.boolean
2742  : throw std::domain_error("type must be boolean, but is " + type_name());
2743  }
2744 
2746  object_t* get_impl_ptr(object_t*) noexcept
2747  {
2748  return is_object() ? m_value.object : nullptr;
2749  }
2750 
2752  constexpr const object_t* get_impl_ptr(const object_t*) const noexcept
2753  {
2754  return is_object() ? m_value.object : nullptr;
2755  }
2756 
2758  array_t* get_impl_ptr(array_t*) noexcept
2759  {
2760  return is_array() ? m_value.array : nullptr;
2761  }
2762 
2764  constexpr const array_t* get_impl_ptr(const array_t*) const noexcept
2765  {
2766  return is_array() ? m_value.array : nullptr;
2767  }
2768 
2770  string_t* get_impl_ptr(string_t*) noexcept
2771  {
2772  return is_string() ? m_value.string : nullptr;
2773  }
2774 
2776  constexpr const string_t* get_impl_ptr(const string_t*) const noexcept
2777  {
2778  return is_string() ? m_value.string : nullptr;
2779  }
2780 
2782  boolean_t* get_impl_ptr(boolean_t*) noexcept
2783  {
2784  return is_boolean() ? &m_value.boolean : nullptr;
2785  }
2786 
2788  constexpr const boolean_t* get_impl_ptr(const boolean_t*) const noexcept
2789  {
2790  return is_boolean() ? &m_value.boolean : nullptr;
2791  }
2792 
2794  number_integer_t* get_impl_ptr(number_integer_t*) noexcept
2795  {
2796  return is_number_integer() ? &m_value.number_integer : nullptr;
2797  }
2798 
2800  constexpr const number_integer_t* get_impl_ptr(const number_integer_t*) const noexcept
2801  {
2802  return is_number_integer() ? &m_value.number_integer : nullptr;
2803  }
2804 
2806  number_unsigned_t* get_impl_ptr(number_unsigned_t*) noexcept
2807  {
2808  return is_number_unsigned() ? &m_value.number_unsigned : nullptr;
2809  }
2810 
2812  constexpr const number_unsigned_t* get_impl_ptr(const number_unsigned_t*) const noexcept
2813  {
2814  return is_number_unsigned() ? &m_value.number_unsigned : nullptr;
2815  }
2816 
2818  number_float_t* get_impl_ptr(number_float_t*) noexcept
2819  {
2820  return is_number_float() ? &m_value.number_float : nullptr;
2821  }
2822 
2824  constexpr const number_float_t* get_impl_ptr(const number_float_t*) const noexcept
2825  {
2826  return is_number_float() ? &m_value.number_float : nullptr;
2827  }
2828 
2840  template<typename ReferenceType, typename ThisType>
2841  static ReferenceType get_ref_impl(ThisType& obj)
2842  {
2843  // helper type
2844  using PointerType = typename std::add_pointer<ReferenceType>::type;
2845 
2846  // delegate the call to get_ptr<>()
2847  auto ptr = obj.template get_ptr<PointerType>();
2848 
2849  if (ptr != nullptr)
2850  {
2851  return *ptr;
2852  }
2853  else
2854  {
2855  throw std::domain_error("incompatible ReferenceType for get_ref, actual type is " +
2856  obj.type_name());
2857  }
2858  }
2859 
2860  public:
2861 
2865 
2899  template<typename ValueType, typename std::enable_if<
2900  not std::is_pointer<ValueType>::value, int>::type = 0>
2901  ValueType get() const
2902  {
2903  return get_impl(static_cast<ValueType*>(nullptr));
2904  }
2905 
2933  template<typename PointerType, typename std::enable_if<
2934  std::is_pointer<PointerType>::value, int>::type = 0>
2935  PointerType get() noexcept
2936  {
2937  // delegate the call to get_ptr
2938  return get_ptr<PointerType>();
2939  }
2940 
2945  template<typename PointerType, typename std::enable_if<
2946  std::is_pointer<PointerType>::value, int>::type = 0>
2947  constexpr const PointerType get() const noexcept
2948  {
2949  // delegate the call to get_ptr
2950  return get_ptr<PointerType>();
2951  }
2952 
2979  template<typename PointerType, typename std::enable_if<
2980  std::is_pointer<PointerType>::value, int>::type = 0>
2981  PointerType get_ptr() noexcept
2982  {
2983  // get the type of the PointerType (remove pointer and const)
2984  using pointee_t = typename std::remove_const<typename
2985  std::remove_pointer<typename
2986  std::remove_const<PointerType>::type>::type>::type;
2987  // make sure the type matches the allowed types
2988  static_assert(
2989  std::is_same<object_t, pointee_t>::value
2990  or std::is_same<array_t, pointee_t>::value
2991  or std::is_same<string_t, pointee_t>::value
2992  or std::is_same<boolean_t, pointee_t>::value
2993  or std::is_same<number_integer_t, pointee_t>::value
2994  or std::is_same<number_unsigned_t, pointee_t>::value
2995  or std::is_same<number_float_t, pointee_t>::value
2996  , "incompatible pointer type");
2997 
2998  // delegate the call to get_impl_ptr<>()
2999  return get_impl_ptr(static_cast<PointerType>(nullptr));
3000  }
3001 
3006  template<typename PointerType, typename std::enable_if<
3007  std::is_pointer<PointerType>::value and
3008  std::is_const<typename std::remove_pointer<PointerType>::type>::value, int>::type = 0>
3009  constexpr const PointerType get_ptr() const noexcept
3010  {
3011  // get the type of the PointerType (remove pointer and const)
3012  using pointee_t = typename std::remove_const<typename
3013  std::remove_pointer<typename
3014  std::remove_const<PointerType>::type>::type>::type;
3015  // make sure the type matches the allowed types
3016  static_assert(
3017  std::is_same<object_t, pointee_t>::value
3018  or std::is_same<array_t, pointee_t>::value
3019  or std::is_same<string_t, pointee_t>::value
3020  or std::is_same<boolean_t, pointee_t>::value
3021  or std::is_same<number_integer_t, pointee_t>::value
3022  or std::is_same<number_unsigned_t, pointee_t>::value
3023  or std::is_same<number_float_t, pointee_t>::value
3024  , "incompatible pointer type");
3025 
3026  // delegate the call to get_impl_ptr<>() const
3027  return get_impl_ptr(static_cast<const PointerType>(nullptr));
3028  }
3029 
3056  template<typename ReferenceType, typename std::enable_if<
3057  std::is_reference<ReferenceType>::value, int>::type = 0>
3058  ReferenceType get_ref()
3059  {
3060  // delegate call to get_ref_impl
3061  return get_ref_impl<ReferenceType>(*this);
3062  }
3063 
3068  template<typename ReferenceType, typename std::enable_if<
3069  std::is_reference<ReferenceType>::value and
3070  std::is_const<typename std::remove_reference<ReferenceType>::type>::value, int>::type = 0>
3071  ReferenceType get_ref() const
3072  {
3073  // delegate call to get_ref_impl
3074  return get_ref_impl<ReferenceType>(*this);
3075  }
3076 
3105  template < typename ValueType, typename std::enable_if <
3106  not std::is_pointer<ValueType>::value and
3107  not std::is_same<ValueType, typename string_t::value_type>::value
3108 #ifndef _MSC_VER // Fix for issue #167 operator<< abiguity under VS2015
3109  and not std::is_same<ValueType, std::initializer_list<typename string_t::value_type>>::value
3110 #endif
3111  , int >::type = 0 >
3112  operator ValueType() const
3113  {
3114  // delegate the call to get<>() const
3115  return get<ValueType>();
3116  }
3117 
3119 
3120 
3122  // element access //
3124 
3128 
3152  {
3153  // at only works for arrays
3154  if (is_array())
3155  {
3156  try
3157  {
3158  return m_value.array->at(idx);
3159  }
3160  catch (std::out_of_range&)
3161  {
3162  // create better exception explanation
3163  throw std::out_of_range("array index " + std::to_string(idx) + " is out of range");
3164  }
3165  }
3166  else
3167  {
3168  throw std::domain_error("cannot use at() with " + type_name());
3169  }
3170  }
3171 
3195  {
3196  // at only works for arrays
3197  if (is_array())
3198  {
3199  try
3200  {
3201  return m_value.array->at(idx);
3202  }
3203  catch (std::out_of_range&)
3204  {
3205  // create better exception explanation
3206  throw std::out_of_range("array index " + std::to_string(idx) + " is out of range");
3207  }
3208  }
3209  else
3210  {
3211  throw std::domain_error("cannot use at() with " + type_name());
3212  }
3213  }
3214 
3241  reference at(const typename object_t::key_type& key)
3242  {
3243  // at only works for objects
3244  if (is_object())
3245  {
3246  try
3247  {
3248  return m_value.object->at(key);
3249  }
3250  catch (std::out_of_range&)
3251  {
3252  // create better exception explanation
3253  throw std::out_of_range("key '" + key + "' not found");
3254  }
3255  }
3256  else
3257  {
3258  throw std::domain_error("cannot use at() with " + type_name());
3259  }
3260  }
3261 
3288  const_reference at(const typename object_t::key_type& key) const
3289  {
3290  // at only works for objects
3291  if (is_object())
3292  {
3293  try
3294  {
3295  return m_value.object->at(key);
3296  }
3297  catch (std::out_of_range&)
3298  {
3299  // create better exception explanation
3300  throw std::out_of_range("key '" + key + "' not found");
3301  }
3302  }
3303  else
3304  {
3305  throw std::domain_error("cannot use at() with " + type_name());
3306  }
3307  }
3308 
3335  {
3336  // implicitly convert null value to an empty array
3337  if (is_null())
3338  {
3339  m_type = value_t::array;
3340  m_value.array = create<array_t>();
3341  assert_invariant();
3342  }
3343 
3344  // operator[] only works for arrays
3345  if (is_array())
3346  {
3347  // fill up array with null values if given idx is outside range
3348  if (idx >= m_value.array->size())
3349  {
3350  m_value.array->insert(m_value.array->end(),
3351  idx - m_value.array->size() + 1,
3352  basic_json());
3353  }
3354 
3355  return m_value.array->operator[](idx);
3356  }
3357  else
3358  {
3359  throw std::domain_error("cannot use operator[] with " + type_name());
3360  }
3361  }
3362 
3383  {
3384  // const operator[] only works for arrays
3385  if (is_array())
3386  {
3387  return m_value.array->operator[](idx);
3388  }
3389  else
3390  {
3391  throw std::domain_error("cannot use operator[] with " + type_name());
3392  }
3393  }
3394 
3422  reference operator[](const typename object_t::key_type& key)
3423  {
3424  // implicitly convert null value to an empty object
3425  if (is_null())
3426  {
3427  m_type = value_t::object;
3428  m_value.object = create<object_t>();
3429  assert_invariant();
3430  }
3431 
3432  // operator[] only works for objects
3433  if (is_object())
3434  {
3435  return m_value.object->operator[](key);
3436  }
3437  else
3438  {
3439  throw std::domain_error("cannot use operator[] with " + type_name());
3440  }
3441  }
3442 
3473  const_reference operator[](const typename object_t::key_type& key) const
3474  {
3475  // const operator[] only works for objects
3476  if (is_object())
3477  {
3478  assert(m_value.object->find(key) != m_value.object->end());
3479  return m_value.object->find(key)->second;
3480  }
3481  else
3482  {
3483  throw std::domain_error("cannot use operator[] with " + type_name());
3484  }
3485  }
3486 
3514  template<typename T, std::size_t n>
3515  reference operator[](T * (&key)[n])
3516  {
3517  return operator[](static_cast<const T>(key));
3518  }
3519 
3549  template<typename T, std::size_t n>
3550  const_reference operator[](T * (&key)[n]) const
3551  {
3552  return operator[](static_cast<const T>(key));
3553  }
3554 
3582  template<typename T>
3584  {
3585  // implicitly convert null to object
3586  if (is_null())
3587  {
3588  m_type = value_t::object;
3589  m_value = value_t::object;
3590  assert_invariant();
3591  }
3592 
3593  // at only works for objects
3594  if (is_object())
3595  {
3596  return m_value.object->operator[](key);
3597  }
3598  else
3599  {
3600  throw std::domain_error("cannot use operator[] with " + type_name());
3601  }
3602  }
3603 
3634  template<typename T>
3636  {
3637  // at only works for objects
3638  if (is_object())
3639  {
3640  assert(m_value.object->find(key) != m_value.object->end());
3641  return m_value.object->find(key)->second;
3642  }
3643  else
3644  {
3645  throw std::domain_error("cannot use operator[] with " + type_name());
3646  }
3647  }
3648 
3697  template<class ValueType, typename std::enable_if<
3698  std::is_convertible<basic_json_t, ValueType>::value, int>::type = 0>
3699  ValueType value(const typename object_t::key_type& key, ValueType default_value) const
3700  {
3701  // at only works for objects
3702  if (is_object())
3703  {
3704  // if key is found, return value and given default value otherwise
3705  const auto it = find(key);
3706  if (it != end())
3707  {
3708  return *it;
3709  }
3710  else
3711  {
3712  return default_value;
3713  }
3714  }
3715  else
3716  {
3717  throw std::domain_error("cannot use value() with " + type_name());
3718  }
3719  }
3720 
3725  string_t value(const typename object_t::key_type& key, const char* default_value) const
3726  {
3727  return value(key, string_t(default_value));
3728  }
3729 
3771  template<class ValueType, typename std::enable_if<
3772  std::is_convertible<basic_json_t, ValueType>::value, int>::type = 0>
3773  ValueType value(const json_pointer& ptr, ValueType default_value) const
3774  {
3775  // at only works for objects
3776  if (is_object())
3777  {
3778  // if pointer resolves a value, return it or use default value
3779  try
3780  {
3781  return ptr.get_checked(this);
3782  }
3783  catch (std::out_of_range&)
3784  {
3785  return default_value;
3786  }
3787  }
3788  else
3789  {
3790  throw std::domain_error("cannot use value() with " + type_name());
3791  }
3792  }
3793 
3798  string_t value(const json_pointer& ptr, const char* default_value) const
3799  {
3800  return value(ptr, string_t(default_value));
3801  }
3802 
3829  {
3830  return *begin();
3831  }
3832 
3837  {
3838  return *cbegin();
3839  }
3840 
3872  {
3873  auto tmp = end();
3874  --tmp;
3875  return *tmp;
3876  }
3877 
3882  {
3883  auto tmp = cend();
3884  --tmp;
3885  return *tmp;
3886  }
3887 
3933  template<class IteratorType, typename std::enable_if<
3934  std::is_same<IteratorType, typename basic_json_t::iterator>::value or
3935  std::is_same<IteratorType, typename basic_json_t::const_iterator>::value, int>::type
3936  = 0>
3937  IteratorType erase(IteratorType pos)
3938  {
3939  // make sure iterator fits the current value
3940  if (this != pos.m_object)
3941  {
3942  throw std::domain_error("iterator does not fit current value");
3943  }
3944 
3945  IteratorType result = end();
3946 
3947  switch (m_type)
3948  {
3949  case value_t::boolean:
3950  case value_t::number_float:
3951  case value_t::number_integer:
3952  case value_t::number_unsigned:
3953  case value_t::string:
3954  {
3955  if (not pos.m_it.primitive_iterator.is_begin())
3956  {
3957  throw std::out_of_range("iterator out of range");
3958  }
3959 
3960  if (is_string())
3961  {
3962  AllocatorType<string_t> alloc;
3963  alloc.destroy(m_value.string);
3964  alloc.deallocate(m_value.string, 1);
3965  m_value.string = nullptr;
3966  }
3967 
3968  m_type = value_t::null;
3969  assert_invariant();
3970  break;
3971  }
3972 
3973  case value_t::object:
3974  {
3975  result.m_it.object_iterator = m_value.object->erase(pos.m_it.object_iterator);
3976  break;
3977  }
3978 
3979  case value_t::array:
3980  {
3981  result.m_it.array_iterator = m_value.array->erase(pos.m_it.array_iterator);
3982  break;
3983  }
3984 
3985  default:
3986  {
3987  throw std::domain_error("cannot use erase() with " + type_name());
3988  }
3989  }
3990 
3991  return result;
3992  }
3993 
4040  template<class IteratorType, typename std::enable_if<
4041  std::is_same<IteratorType, typename basic_json_t::iterator>::value or
4042  std::is_same<IteratorType, typename basic_json_t::const_iterator>::value, int>::type
4043  = 0>
4044  IteratorType erase(IteratorType first, IteratorType last)
4045  {
4046  // make sure iterator fits the current value
4047  if (this != first.m_object or this != last.m_object)
4048  {
4049  throw std::domain_error("iterators do not fit current value");
4050  }
4051 
4052  IteratorType result = end();
4053 
4054  switch (m_type)
4055  {
4056  case value_t::boolean:
4057  case value_t::number_float:
4058  case value_t::number_integer:
4059  case value_t::number_unsigned:
4060  case value_t::string:
4061  {
4062  if (not first.m_it.primitive_iterator.is_begin() or not last.m_it.primitive_iterator.is_end())
4063  {
4064  throw std::out_of_range("iterators out of range");
4065  }
4066 
4067  if (is_string())
4068  {
4069  AllocatorType<string_t> alloc;
4070  alloc.destroy(m_value.string);
4071  alloc.deallocate(m_value.string, 1);
4072  m_value.string = nullptr;
4073  }
4074 
4075  m_type = value_t::null;
4076  assert_invariant();
4077  break;
4078  }
4079 
4080  case value_t::object:
4081  {
4082  result.m_it.object_iterator = m_value.object->erase(first.m_it.object_iterator,
4083  last.m_it.object_iterator);
4084  break;
4085  }
4086 
4087  case value_t::array:
4088  {
4089  result.m_it.array_iterator = m_value.array->erase(first.m_it.array_iterator,
4090  last.m_it.array_iterator);
4091  break;
4092  }
4093 
4094  default:
4095  {
4096  throw std::domain_error("cannot use erase() with " + type_name());
4097  }
4098  }
4099 
4100  return result;
4101  }
4102 
4132  size_type erase(const typename object_t::key_type& key)
4133  {
4134  // this erase only works for objects
4135  if (is_object())
4136  {
4137  return m_value.object->erase(key);
4138  }
4139  else
4140  {
4141  throw std::domain_error("cannot use erase() with " + type_name());
4142  }
4143  }
4144 
4169  void erase(const size_type idx)
4170  {
4171  // this erase only works for arrays
4172  if (is_array())
4173  {
4174  if (idx >= size())
4175  {
4176  throw std::out_of_range("array index " + std::to_string(idx) + " is out of range");
4177  }
4178 
4179  m_value.array->erase(m_value.array->begin() + static_cast<difference_type>(idx));
4180  }
4181  else
4182  {
4183  throw std::domain_error("cannot use erase() with " + type_name());
4184  }
4185  }
4186 
4188 
4189 
4191  // lookup //
4193 
4196 
4215  iterator find(typename object_t::key_type key)
4216  {
4217  auto result = end();
4218 
4219  if (is_object())
4220  {
4221  result.m_it.object_iterator = m_value.object->find(key);
4222  }
4223 
4224  return result;
4225  }
4226 
4231  const_iterator find(typename object_t::key_type key) const
4232  {
4233  auto result = cend();
4234 
4235  if (is_object())
4236  {
4237  result.m_it.object_iterator = m_value.object->find(key);
4238  }
4239 
4240  return result;
4241  }
4242 
4261  size_type count(typename object_t::key_type key) const
4262  {
4263  // return 0 for all nonobject types
4264  return is_object() ? m_value.object->count(key) : 0;
4265  }
4266 
4268 
4269 
4271  // iterators //
4273 
4276 
4301  iterator begin() noexcept
4302  {
4303  iterator result(this);
4304  result.set_begin();
4305  return result;
4306  }
4307 
4311  const_iterator begin() const noexcept
4312  {
4313  return cbegin();
4314  }
4315 
4341  const_iterator cbegin() const noexcept
4342  {
4343  const_iterator result(this);
4344  result.set_begin();
4345  return result;
4346  }
4347 
4372  iterator end() noexcept
4373  {
4374  iterator result(this);
4375  result.set_end();
4376  return result;
4377  }
4378 
4382  const_iterator end() const noexcept
4383  {
4384  return cend();
4385  }
4386 
4412  const_iterator cend() const noexcept
4413  {
4414  const_iterator result(this);
4415  result.set_end();
4416  return result;
4417  }
4418 
4443  {
4444  return reverse_iterator(end());
4445  }
4446 
4451  {
4452  return crbegin();
4453  }
4454 
4480  {
4481  return reverse_iterator(begin());
4482  }
4483 
4487  const_reverse_iterator rend() const noexcept
4488  {
4489  return crend();
4490  }
4491 
4517  {
4518  return const_reverse_iterator(cend());
4519  }
4520 
4546  {
4547  return const_reverse_iterator(cbegin());
4548  }
4549 
4550  private:
4551  // forward declaration
4552  template<typename IteratorType> class iteration_proxy;
4553 
4554  public:
4566  static iteration_proxy<iterator> iterator_wrapper(reference cont)
4567  {
4568  return iteration_proxy<iterator>(cont);
4569  }
4570 
4574  static iteration_proxy<const_iterator> iterator_wrapper(const_reference cont)
4575  {
4576  return iteration_proxy<const_iterator>(cont);
4577  }
4578 
4580 
4581 
4583  // capacity //
4585 
4588 
4626  bool empty() const noexcept
4627  {
4628  switch (m_type)
4629  {
4630  case value_t::null:
4631  {
4632  // null values are empty
4633  return true;
4634  }
4635 
4636  case value_t::array:
4637  {
4638  // delegate call to array_t::empty()
4639  return m_value.array->empty();
4640  }
4641 
4642  case value_t::object:
4643  {
4644  // delegate call to object_t::empty()
4645  return m_value.object->empty();
4646  }
4647 
4648  default:
4649  {
4650  // all other types are nonempty
4651  return false;
4652  }
4653  }
4654  }
4655 
4694  size_type size() const noexcept
4695  {
4696  switch (m_type)
4697  {
4698  case value_t::null:
4699  {
4700  // null values are empty
4701  return 0;
4702  }
4703 
4704  case value_t::array:
4705  {
4706  // delegate call to array_t::size()
4707  return m_value.array->size();
4708  }
4709 
4710  case value_t::object:
4711  {
4712  // delegate call to object_t::size()
4713  return m_value.object->size();
4714  }
4715 
4716  default:
4717  {
4718  // all other types have size 1
4719  return 1;
4720  }
4721  }
4722  }
4723 
4760  size_type max_size() const noexcept
4761  {
4762  switch (m_type)
4763  {
4764  case value_t::array:
4765  {
4766  // delegate call to array_t::max_size()
4767  return m_value.array->max_size();
4768  }
4769 
4770  case value_t::object:
4771  {
4772  // delegate call to object_t::max_size()
4773  return m_value.object->max_size();
4774  }
4775 
4776  default:
4777  {
4778  // all other types have max_size() == size()
4779  return size();
4780  }
4781  }
4782  }
4783 
4785 
4786 
4788  // modifiers //
4790 
4793 
4819  void clear() noexcept
4820  {
4821  switch (m_type)
4822  {
4823  case value_t::number_integer:
4824  {
4825  m_value.number_integer = 0;
4826  break;
4827  }
4828 
4829  case value_t::number_unsigned:
4830  {
4831  m_value.number_unsigned = 0;
4832  break;
4833  }
4834 
4835  case value_t::number_float:
4836  {
4837  m_value.number_float = 0.0;
4838  break;
4839  }
4840 
4841  case value_t::boolean:
4842  {
4843  m_value.boolean = false;
4844  break;
4845  }
4846 
4847  case value_t::string:
4848  {
4849  m_value.string->clear();
4850  break;
4851  }
4852 
4853  case value_t::array:
4854  {
4855  m_value.array->clear();
4856  break;
4857  }
4858 
4859  case value_t::object:
4860  {
4861  m_value.object->clear();
4862  break;
4863  }
4864 
4865  default:
4866  {
4867  break;
4868  }
4869  }
4870  }
4871 
4892  void push_back(basic_json&& val)
4893  {
4894  // push_back only works for null objects or arrays
4895  if (not(is_null() or is_array()))
4896  {
4897  throw std::domain_error("cannot use push_back() with " + type_name());
4898  }
4899 
4900  // transform null object into an array
4901  if (is_null())
4902  {
4903  m_type = value_t::array;
4904  m_value = value_t::array;
4905  assert_invariant();
4906  }
4907 
4908  // add element to array (move semantics)
4909  m_value.array->push_back(std::move(val));
4910  // invalidate object
4911  val.m_type = value_t::null;
4912  }
4913 
4919  {
4920  push_back(std::move(val));
4921  return *this;
4922  }
4923 
4928  void push_back(const basic_json& val)
4929  {
4930  // push_back only works for null objects or arrays
4931  if (not(is_null() or is_array()))
4932  {
4933  throw std::domain_error("cannot use push_back() with " + type_name());
4934  }
4935 
4936  // transform null object into an array
4937  if (is_null())
4938  {
4939  m_type = value_t::array;
4940  m_value = value_t::array;
4941  assert_invariant();
4942  }
4943 
4944  // add element to array
4945  m_value.array->push_back(val);
4946  }
4947 
4953  {
4954  push_back(val);
4955  return *this;
4956  }
4957 
4978  void push_back(const typename object_t::value_type& val)
4979  {
4980  // push_back only works for null objects or objects
4981  if (not(is_null() or is_object()))
4982  {
4983  throw std::domain_error("cannot use push_back() with " + type_name());
4984  }
4985 
4986  // transform null object into an object
4987  if (is_null())
4988  {
4989  m_type = value_t::object;
4990  m_value = value_t::object;
4991  assert_invariant();
4992  }
4993 
4994  // add element to array
4995  m_value.object->insert(val);
4996  }
4997 
5002  reference operator+=(const typename object_t::value_type& val)
5003  {
5004  push_back(val);
5005  return *this;
5006  }
5007 
5033  void push_back(std::initializer_list<basic_json> init)
5034  {
5035  if (is_object() and init.size() == 2 and init.begin()->is_string())
5036  {
5037  const string_t key = *init.begin();
5038  push_back(typename object_t::value_type(key, *(init.begin() + 1)));
5039  }
5040  else
5041  {
5042  push_back(basic_json(init));
5043  }
5044  }
5045 
5050  reference operator+=(std::initializer_list<basic_json> init)
5051  {
5052  push_back(init);
5053  return *this;
5054  }
5055 
5079  {
5080  // insert only works for arrays
5081  if (is_array())
5082  {
5083  // check if iterator pos fits to this JSON value
5084  if (pos.m_object != this)
5085  {
5086  throw std::domain_error("iterator does not fit current value");
5087  }
5088 
5089  // insert to array and return iterator
5090  iterator result(this);
5091  result.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator, val);
5092  return result;
5093  }
5094  else
5095  {
5096  throw std::domain_error("cannot use insert() with " + type_name());
5097  }
5098  }
5099 
5105  {
5106  return insert(pos, val);
5107  }
5108 
5134  {
5135  // insert only works for arrays
5136  if (is_array())
5137  {
5138  // check if iterator pos fits to this JSON value
5139  if (pos.m_object != this)
5140  {
5141  throw std::domain_error("iterator does not fit current value");
5142  }
5143 
5144  // insert to array and return iterator
5145  iterator result(this);
5146  result.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator, cnt, val);
5147  return result;
5148  }
5149  else
5150  {
5151  throw std::domain_error("cannot use insert() with " + type_name());
5152  }
5153  }
5154 
5186  {
5187  // insert only works for arrays
5188  if (not is_array())
5189  {
5190  throw std::domain_error("cannot use insert() with " + type_name());
5191  }
5192 
5193  // check if iterator pos fits to this JSON value
5194  if (pos.m_object != this)
5195  {
5196  throw std::domain_error("iterator does not fit current value");
5197  }
5198 
5199  // check if range iterators belong to the same JSON object
5200  if (first.m_object != last.m_object)
5201  {
5202  throw std::domain_error("iterators do not fit");
5203  }
5204 
5205  if (first.m_object == this or last.m_object == this)
5206  {
5207  throw std::domain_error("passed iterators may not belong to container");
5208  }
5209 
5210  // insert to array and return iterator
5211  iterator result(this);
5212  result.m_it.array_iterator = m_value.array->insert(
5213  pos.m_it.array_iterator,
5214  first.m_it.array_iterator,
5215  last.m_it.array_iterator);
5216  return result;
5217  }
5218 
5243  iterator insert(const_iterator pos, std::initializer_list<basic_json> ilist)
5244  {
5245  // insert only works for arrays
5246  if (not is_array())
5247  {
5248  throw std::domain_error("cannot use insert() with " + type_name());
5249  }
5250 
5251  // check if iterator pos fits to this JSON value
5252  if (pos.m_object != this)
5253  {
5254  throw std::domain_error("iterator does not fit current value");
5255  }
5256 
5257  // insert to array and return iterator
5258  iterator result(this);
5259  result.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator, ilist);
5260  return result;
5261  }
5262 
5280  void swap(reference other) noexcept (
5281  std::is_nothrow_move_constructible<value_t>::value and
5282  std::is_nothrow_move_assignable<value_t>::value and
5283  std::is_nothrow_move_constructible<json_value>::value and
5284  std::is_nothrow_move_assignable<json_value>::value
5285  )
5286  {
5287  std::swap(m_type, other.m_type);
5288  std::swap(m_value, other.m_value);
5289  assert_invariant();
5290  }
5291 
5312  void swap(array_t& other)
5313  {
5314  // swap only works for arrays
5315  if (is_array())
5316  {
5317  std::swap(*(m_value.array), other);
5318  }
5319  else
5320  {
5321  throw std::domain_error("cannot use swap() with " + type_name());
5322  }
5323  }
5324 
5345  void swap(object_t& other)
5346  {
5347  // swap only works for objects
5348  if (is_object())
5349  {
5350  std::swap(*(m_value.object), other);
5351  }
5352  else
5353  {
5354  throw std::domain_error("cannot use swap() with " + type_name());
5355  }
5356  }
5357 
5378  void swap(string_t& other)
5379  {
5380  // swap only works for strings
5381  if (is_string())
5382  {
5383  std::swap(*(m_value.string), other);
5384  }
5385  else
5386  {
5387  throw std::domain_error("cannot use swap() with " + type_name());
5388  }
5389  }
5390 
5392 
5393 
5395  // lexicographical comparison operators //
5397 
5400 
5401  private:
5411  friend bool operator<(const value_t lhs, const value_t rhs) noexcept
5412  {
5413  static constexpr std::array<uint8_t, 8> order = {{
5414  0, // null
5415  3, // object
5416  4, // array
5417  5, // string
5418  1, // boolean
5419  2, // integer
5420  2, // unsigned
5421  2, // float
5422  }
5423  };
5424 
5425  // discarded values are not comparable
5426  if (lhs == value_t::discarded or rhs == value_t::discarded)
5427  {
5428  return false;
5429  }
5430 
5431  return order[static_cast<std::size_t>(lhs)] < order[static_cast<std::size_t>(rhs)];
5432  }
5433 
5434  public:
5458  friend bool operator==(const_reference lhs, const_reference rhs) noexcept
5459  {
5460  const auto lhs_type = lhs.type();
5461  const auto rhs_type = rhs.type();
5462 
5463  if (lhs_type == rhs_type)
5464  {
5465  switch (lhs_type)
5466  {
5467  case value_t::array:
5468  {
5469  return *lhs.m_value.array == *rhs.m_value.array;
5470  }
5471  case value_t::object:
5472  {
5473  return *lhs.m_value.object == *rhs.m_value.object;
5474  }
5475  case value_t::null:
5476  {
5477  return true;
5478  }
5479  case value_t::string:
5480  {
5481  return *lhs.m_value.string == *rhs.m_value.string;
5482  }
5483  case value_t::boolean:
5484  {
5485  return lhs.m_value.boolean == rhs.m_value.boolean;
5486  }
5487  case value_t::number_integer:
5488  {
5489  return lhs.m_value.number_integer == rhs.m_value.number_integer;
5490  }
5491  case value_t::number_unsigned:
5492  {
5493  return lhs.m_value.number_unsigned == rhs.m_value.number_unsigned;
5494  }
5495  case value_t::number_float:
5496  {
5497  return lhs.m_value.number_float == rhs.m_value.number_float;
5498  }
5499  default:
5500  {
5501  return false;
5502  }
5503  }
5504  }
5505  else if (lhs_type == value_t::number_integer and rhs_type == value_t::number_float)
5506  {
5507  return static_cast<number_float_t>(lhs.m_value.number_integer) == rhs.m_value.number_float;
5508  }
5509  else if (lhs_type == value_t::number_float and rhs_type == value_t::number_integer)
5510  {
5511  return lhs.m_value.number_float == static_cast<number_float_t>(rhs.m_value.number_integer);
5512  }
5513  else if (lhs_type == value_t::number_unsigned and rhs_type == value_t::number_float)
5514  {
5515  return static_cast<number_float_t>(lhs.m_value.number_unsigned) == rhs.m_value.number_float;
5516  }
5517  else if (lhs_type == value_t::number_float and rhs_type == value_t::number_unsigned)
5518  {
5519  return lhs.m_value.number_float == static_cast<number_float_t>(rhs.m_value.number_unsigned);
5520  }
5521  else if (lhs_type == value_t::number_unsigned and rhs_type == value_t::number_integer)
5522  {
5523  return static_cast<number_integer_t>(lhs.m_value.number_unsigned) == rhs.m_value.number_integer;
5524  }
5525  else if (lhs_type == value_t::number_integer and rhs_type == value_t::number_unsigned)
5526  {
5527  return lhs.m_value.number_integer == static_cast<number_integer_t>(rhs.m_value.number_unsigned);
5528  }
5529 
5530  return false;
5531  }
5532 
5551  friend bool operator==(const_reference v, std::nullptr_t) noexcept
5552  {
5553  return v.is_null();
5554  }
5555 
5560  friend bool operator==(std::nullptr_t, const_reference v) noexcept
5561  {
5562  return v.is_null();
5563  }
5564 
5581  friend bool operator!=(const_reference lhs, const_reference rhs) noexcept
5582  {
5583  return not (lhs == rhs);
5584  }
5585 
5604  friend bool operator!=(const_reference v, std::nullptr_t) noexcept
5605  {
5606  return not v.is_null();
5607  }
5608 
5613  friend bool operator!=(std::nullptr_t, const_reference v) noexcept
5614  {
5615  return not v.is_null();
5616  }
5617 
5642  friend bool operator<(const_reference lhs, const_reference rhs) noexcept
5643  {
5644  const auto lhs_type = lhs.type();
5645  const auto rhs_type = rhs.type();
5646 
5647  if (lhs_type == rhs_type)
5648  {
5649  switch (lhs_type)
5650  {
5651  case value_t::array:
5652  {
5653  return *lhs.m_value.array < *rhs.m_value.array;
5654  }
5655  case value_t::object:
5656  {
5657  return *lhs.m_value.object < *rhs.m_value.object;
5658  }
5659  case value_t::null:
5660  {
5661  return false;
5662  }
5663  case value_t::string:
5664  {
5665  return *lhs.m_value.string < *rhs.m_value.string;
5666  }
5667  case value_t::boolean:
5668  {
5669  return lhs.m_value.boolean < rhs.m_value.boolean;
5670  }
5671  case value_t::number_integer:
5672  {
5673  return lhs.m_value.number_integer < rhs.m_value.number_integer;
5674  }
5675  case value_t::number_unsigned:
5676  {
5677  return lhs.m_value.number_unsigned < rhs.m_value.number_unsigned;
5678  }
5679  case value_t::number_float:
5680  {
5681  return lhs.m_value.number_float < rhs.m_value.number_float;
5682  }
5683  default:
5684  {
5685  return false;
5686  }
5687  }
5688  }
5689  else if (lhs_type == value_t::number_integer and rhs_type == value_t::number_float)
5690  {
5691  return static_cast<number_float_t>(lhs.m_value.number_integer) < rhs.m_value.number_float;
5692  }
5693  else if (lhs_type == value_t::number_float and rhs_type == value_t::number_integer)
5694  {
5695  return lhs.m_value.number_float < static_cast<number_float_t>(rhs.m_value.number_integer);
5696  }
5697  else if (lhs_type == value_t::number_unsigned and rhs_type == value_t::number_float)
5698  {
5699  return static_cast<number_float_t>(lhs.m_value.number_unsigned) < rhs.m_value.number_float;
5700  }
5701  else if (lhs_type == value_t::number_float and rhs_type == value_t::number_unsigned)
5702  {
5703  return lhs.m_value.number_float < static_cast<number_float_t>(rhs.m_value.number_unsigned);
5704  }
5705  else if (lhs_type == value_t::number_integer and rhs_type == value_t::number_unsigned)
5706  {
5707  return lhs.m_value.number_integer < static_cast<number_integer_t>(rhs.m_value.number_unsigned);
5708  }
5709  else if (lhs_type == value_t::number_unsigned and rhs_type == value_t::number_integer)
5710  {
5711  return static_cast<number_integer_t>(lhs.m_value.number_unsigned) < rhs.m_value.number_integer;
5712  }
5713 
5714  // We only reach this line if we cannot compare values. In that case,
5715  // we compare types. Note we have to call the operator explicitly,
5716  // because MSVC has problems otherwise.
5717  return operator<(lhs_type, rhs_type);
5718  }
5719 
5737  friend bool operator<=(const_reference lhs, const_reference rhs) noexcept
5738  {
5739  return not (rhs < lhs);
5740  }
5741 
5759  friend bool operator>(const_reference lhs, const_reference rhs) noexcept
5760  {
5761  return not (lhs <= rhs);
5762  }
5763 
5781  friend bool operator>=(const_reference lhs, const_reference rhs) noexcept
5782  {
5783  return not (lhs < rhs);
5784  }
5785 
5787 
5788 
5790  // serialization //
5792 
5795 
5822  friend std::ostream& operator<<(std::ostream& o, const basic_json& j)
5823  {
5824  // read width member and use it as indentation parameter if nonzero
5825  const bool pretty_print = (o.width() > 0);
5826  const auto indentation = (pretty_print ? o.width() : 0);
5827 
5828  // reset width to 0 for subsequent calls to this stream
5829  o.width(0);
5830 
5831  // fix locale problems
5832  const auto old_locale = o.imbue(std::locale(std::locale(), new DecimalSeparator));
5833  // set precision
5834 
5835  // 6, 15 or 16 digits of precision allows round-trip IEEE 754
5836  // string->float->string, string->double->string or string->long
5837  // double->string; to be safe, we read this value from
5838  // std::numeric_limits<number_float_t>::digits10
5839  const auto old_precision = o.precision(std::numeric_limits<double>::digits10);
5840 
5841  // do the actual serialization
5842  j.dump(o, pretty_print, static_cast<unsigned int>(indentation));
5843 
5844  // reset locale and precision
5845  o.imbue(old_locale);
5846  o.precision(old_precision);
5847  return o;
5848  }
5849 
5854  friend std::ostream& operator>>(const basic_json& j, std::ostream& o)
5855  {
5856  return o << j;
5857  }
5858 
5860 
5861 
5863  // deserialization //
5865 
5868 
5896  template<class T, std::size_t N>
5897  static basic_json parse(T (&array)[N],
5898  const parser_callback_t cb = nullptr)
5899  {
5900  // delegate the call to the iterator-range parse overload
5901  return parse(std::begin(array), std::end(array), cb);
5902  }
5903 
5931  template<typename CharPT, typename std::enable_if<
5932  std::is_pointer<CharPT>::value and
5933  std::is_integral<typename std::remove_pointer<CharPT>::type>::value and
5934  sizeof(typename std::remove_pointer<CharPT>::type) == 1, int>::type = 0>
5935  static basic_json parse(const CharPT s,
5936  const parser_callback_t cb = nullptr)
5937  {
5938  return parser(reinterpret_cast<const char*>(s), cb).parse();
5939  }
5940 
5965  static basic_json parse(std::istream& i,
5966  const parser_callback_t cb = nullptr)
5967  {
5968  return parser(i, cb).parse();
5969  }
5970 
5974  static basic_json parse(std::istream&& i,
5975  const parser_callback_t cb = nullptr)
5976  {
5977  return parser(i, cb).parse();
5978  }
5979 
6021  template<class IteratorType, typename std::enable_if<
6022  std::is_base_of<
6023  std::random_access_iterator_tag,
6024  typename std::iterator_traits<IteratorType>::iterator_category>::value, int>::type = 0>
6025  static basic_json parse(IteratorType first, IteratorType last,
6026  const parser_callback_t cb = nullptr)
6027  {
6028  // assertion to check that the iterator range is indeed contiguous,
6029  // see http://stackoverflow.com/a/35008842/266378 for more discussion
6030  assert(std::accumulate(first, last, std::make_pair<bool, int>(true, 0),
6031  [&first](std::pair<bool, int> res, decltype(*first) val)
6032  {
6033  res.first &= (val == *(std::next(std::addressof(*first), res.second++)));
6034  return res;
6035  }).first);
6036 
6037  // assertion to check that each element is 1 byte long
6038  static_assert(sizeof(typename std::iterator_traits<IteratorType>::value_type) == 1,
6039  "each element in the iterator range must have the size of 1 byte");
6040 
6041  // if iterator range is empty, create a parser with an empty string
6042  // to generate "unexpected EOF" error message
6043  if (std::distance(first, last) <= 0)
6044  {
6045  return parser("").parse();
6046  }
6047 
6048  return parser(first, last, cb).parse();
6049  }
6050 
6091  template<class ContiguousContainer, typename std::enable_if<
6092  not std::is_pointer<ContiguousContainer>::value and
6093  std::is_base_of<
6094  std::random_access_iterator_tag,
6095  typename std::iterator_traits<decltype(std::begin(std::declval<ContiguousContainer const>()))>::iterator_category>::value
6096  , int>::type = 0>
6097  static basic_json parse(const ContiguousContainer& c,
6098  const parser_callback_t cb = nullptr)
6099  {
6100  // delegate the call to the iterator-range parse overload
6101  return parse(std::begin(c), std::end(c), cb);
6102  }
6103 
6127  friend std::istream& operator<<(basic_json& j, std::istream& i)
6128  {
6129  j = parser(i).parse();
6130  return i;
6131  }
6132 
6137  friend std::istream& operator>>(std::istream& i, basic_json& j)
6138  {
6139  j = parser(i).parse();
6140  return i;
6141  }
6142 
6144 
6145 
6146  private:
6148  // convenience functions //
6150 
6163  std::string type_name() const
6164  {
6165  switch (m_type)
6166  {
6167  case value_t::null:
6168  return "null";
6169  case value_t::object:
6170  return "object";
6171  case value_t::array:
6172  return "array";
6173  case value_t::string:
6174  return "string";
6175  case value_t::boolean:
6176  return "boolean";
6177  case value_t::discarded:
6178  return "discarded";
6179  default:
6180  return "number";
6181  }
6182  }
6183 
6192  static std::size_t extra_space(const string_t& s) noexcept
6193  {
6194  return std::accumulate(s.begin(), s.end(), size_t{},
6195  [](size_t res, typename string_t::value_type c)
6196  {
6197  switch (c)
6198  {
6199  case '"':
6200  case '\\':
6201  case '\b':
6202  case '\f':
6203  case '\n':
6204  case '\r':
6205  case '\t':
6206  {
6207  // from c (1 byte) to \x (2 bytes)
6208  return res + 1;
6209  }
6210 
6211  default:
6212  {
6213  if (c >= 0x00 and c <= 0x1f)
6214  {
6215  // from c (1 byte) to \uxxxx (6 bytes)
6216  return res + 5;
6217  }
6218  else
6219  {
6220  return res;
6221  }
6222  }
6223  }
6224  });
6225  }
6226 
6240  static string_t escape_string(const string_t& s)
6241  {
6242  const auto space = extra_space(s);
6243  if (space == 0)
6244  {
6245  return s;
6246  }
6247 
6248  // create a result string of necessary size
6249  string_t result(s.size() + space, '\\');
6250  std::size_t pos = 0;
6251 
6252  for (const auto& c : s)
6253  {
6254  switch (c)
6255  {
6256  // quotation mark (0x22)
6257  case '"':
6258  {
6259  result[pos + 1] = '"';
6260  pos += 2;
6261  break;
6262  }
6263 
6264  // reverse solidus (0x5c)
6265  case '\\':
6266  {
6267  // nothing to change
6268  pos += 2;
6269  break;
6270  }
6271 
6272  // backspace (0x08)
6273  case '\b':
6274  {
6275  result[pos + 1] = 'b';
6276  pos += 2;
6277  break;
6278  }
6279 
6280  // formfeed (0x0c)
6281  case '\f':
6282  {
6283  result[pos + 1] = 'f';
6284  pos += 2;
6285  break;
6286  }
6287 
6288  // newline (0x0a)
6289  case '\n':
6290  {
6291  result[pos + 1] = 'n';
6292  pos += 2;
6293  break;
6294  }
6295 
6296  // carriage return (0x0d)
6297  case '\r':
6298  {
6299  result[pos + 1] = 'r';
6300  pos += 2;
6301  break;
6302  }
6303 
6304  // horizontal tab (0x09)
6305  case '\t':
6306  {
6307  result[pos + 1] = 't';
6308  pos += 2;
6309  break;
6310  }
6311 
6312  default:
6313  {
6314  if (c >= 0x00 and c <= 0x1f)
6315  {
6316  // convert a number 0..15 to its hex representation
6317  // (0..f)
6318  static const char hexify[16] =
6319  {
6320  '0', '1', '2', '3', '4', '5', '6', '7',
6321  '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'
6322  };
6323 
6324  // print character c as \uxxxx
6325  for (const char m :
6326  { 'u', '0', '0', hexify[c >> 4], hexify[c & 0x0f]
6327  })
6328  {
6329  result[++pos] = m;
6330  }
6331 
6332  ++pos;
6333  }
6334  else
6335  {
6336  // all other characters are added as-is
6337  result[pos++] = c;
6338  }
6339  break;
6340  }
6341  }
6342  }
6343 
6344  return result;
6345  }
6346 
6364  void dump(std::ostream& o,
6365  const bool pretty_print,
6366  const unsigned int indent_step,
6367  const unsigned int current_indent = 0) const
6368  {
6369  // variable to hold indentation for recursive calls
6370  unsigned int new_indent = current_indent;
6371 
6372  switch (m_type)
6373  {
6374  case value_t::object:
6375  {
6376  if (m_value.object->empty())
6377  {
6378  o << "{}";
6379  return;
6380  }
6381 
6382  o << "{";
6383 
6384  // increase indentation
6385  if (pretty_print)
6386  {
6387  new_indent += indent_step;
6388  o << "\n";
6389  }
6390 
6391  for (auto i = m_value.object->cbegin(); i != m_value.object->cend(); ++i)
6392  {
6393  if (i != m_value.object->cbegin())
6394  {
6395  o << (pretty_print ? ",\n" : ",");
6396  }
6397  o << string_t(new_indent, ' ') << "\""
6398  << escape_string(i->first) << "\":"
6399  << (pretty_print ? " " : "");
6400  i->second.dump(o, pretty_print, indent_step, new_indent);
6401  }
6402 
6403  // decrease indentation
6404  if (pretty_print)
6405  {
6406  new_indent -= indent_step;
6407  o << "\n";
6408  }
6409 
6410  o << string_t(new_indent, ' ') + "}";
6411  return;
6412  }
6413 
6414  case value_t::array:
6415  {
6416  if (m_value.array->empty())
6417  {
6418  o << "[]";
6419  return;
6420  }
6421 
6422  o << "[";
6423 
6424  // increase indentation
6425  if (pretty_print)
6426  {
6427  new_indent += indent_step;
6428  o << "\n";
6429  }
6430 
6431  for (auto i = m_value.array->cbegin(); i != m_value.array->cend(); ++i)
6432  {
6433  if (i != m_value.array->cbegin())
6434  {
6435  o << (pretty_print ? ",\n" : ",");
6436  }
6437  o << string_t(new_indent, ' ');
6438  i->dump(o, pretty_print, indent_step, new_indent);
6439  }
6440 
6441  // decrease indentation
6442  if (pretty_print)
6443  {
6444  new_indent -= indent_step;
6445  o << "\n";
6446  }
6447 
6448  o << string_t(new_indent, ' ') << "]";
6449  return;
6450  }
6451 
6452  case value_t::string:
6453  {
6454  o << string_t("\"") << escape_string(*m_value.string) << "\"";
6455  return;
6456  }
6457 
6458  case value_t::boolean:
6459  {
6460  o << (m_value.boolean ? "true" : "false");
6461  return;
6462  }
6463 
6464  case value_t::number_integer:
6465  {
6466  o << m_value.number_integer;
6467  return;
6468  }
6469 
6470  case value_t::number_unsigned:
6471  {
6472  o << m_value.number_unsigned;
6473  return;
6474  }
6475 
6476  case value_t::number_float:
6477  {
6478  if (m_value.number_float == 0)
6479  {
6480  // special case for zero to get "0.0"/"-0.0"
6481  o << (std::signbit(m_value.number_float) ? "-0.0" : "0.0");
6482  }
6483  else
6484  {
6485  o << m_value.number_float;
6486  }
6487  return;
6488  }
6489 
6490  case value_t::discarded:
6491  {
6492  o << "<discarded>";
6493  return;
6494  }
6495 
6496  case value_t::null:
6497  {
6498  o << "null";
6499  return;
6500  }
6501  }
6502  }
6503 
6504  private:
6506  // member variables //
6508 
6510  value_t m_type = value_t::null;
6511 
6513  json_value m_value = {};
6514 
6515 
6516  private:
6518  // iterators //
6520 
6530  class primitive_iterator_t
6531  {
6532  public:
6534  void set_begin() noexcept
6535  {
6536  m_it = begin_value;
6537  }
6538 
6540  void set_end() noexcept
6541  {
6542  m_it = end_value;
6543  }
6544 
6546  constexpr bool is_begin() const noexcept
6547  {
6548  return (m_it == begin_value);
6549  }
6550 
6552  constexpr bool is_end() const noexcept
6553  {
6554  return (m_it == end_value);
6555  }
6556 
6558  operator difference_type& () noexcept
6559  {
6560  return m_it;
6561  }
6562 
6564  constexpr operator difference_type () const noexcept
6565  {
6566  return m_it;
6567  }
6568 
6569  private:
6570  static constexpr difference_type begin_value = 0;
6571  static constexpr difference_type end_value = begin_value + 1;
6572 
6574  difference_type m_it = std::numeric_limits<std::ptrdiff_t>::denorm_min();
6575  };
6576 
6584  struct internal_iterator
6585  {
6587  typename object_t::iterator object_iterator;
6589  typename array_t::iterator array_iterator;
6591  primitive_iterator_t primitive_iterator;
6592 
6594  internal_iterator() noexcept
6595  : object_iterator(), array_iterator(), primitive_iterator()
6596  {}
6597  };
6598 
6600  template<typename IteratorType>
6601  class iteration_proxy
6602  {
6603  private:
6605  class iteration_proxy_internal
6606  {
6607  private:
6609  IteratorType anchor;
6611  size_t array_index = 0;
6612 
6613  public:
6614  explicit iteration_proxy_internal(IteratorType it) noexcept
6615  : anchor(it)
6616  {}
6617 
6619  iteration_proxy_internal& operator*()
6620  {
6621  return *this;
6622  }
6623 
6625  iteration_proxy_internal& operator++()
6626  {
6627  ++anchor;
6628  ++array_index;
6629 
6630  return *this;
6631  }
6632 
6634  bool operator!= (const iteration_proxy_internal& o) const
6635  {
6636  return anchor != o.anchor;
6637  }
6638 
6640  typename basic_json::string_t key() const
6641  {
6642  assert(anchor.m_object != nullptr);
6643 
6644  switch (anchor.m_object->type())
6645  {
6646  // use integer array index as key
6647  case value_t::array:
6648  {
6649  return std::to_string(array_index);
6650  }
6651 
6652  // use key from the object
6653  case value_t::object:
6654  {
6655  return anchor.key();
6656  }
6657 
6658  // use an empty key for all primitive types
6659  default:
6660  {
6661  return "";
6662  }
6663  }
6664  }
6665 
6667  typename IteratorType::reference value() const
6668  {
6669  return anchor.value();
6670  }
6671  };
6672 
6674  typename IteratorType::reference container;
6675 
6676  public:
6678  explicit iteration_proxy(typename IteratorType::reference cont)
6679  : container(cont)
6680  {}
6681 
6683  iteration_proxy_internal begin() noexcept
6684  {
6685  return iteration_proxy_internal(container.begin());
6686  }
6687 
6689  iteration_proxy_internal end() noexcept
6690  {
6691  return iteration_proxy_internal(container.end());
6692  }
6693  };
6694 
6695  public:
6715  class const_iterator : public std::iterator<std::random_access_iterator_tag, const basic_json>
6716  {
6718  friend class basic_json;
6719 
6720  public:
6730  using iterator_category = std::bidirectional_iterator_tag;
6731 
6733  const_iterator() = default;
6734 
6741  explicit const_iterator(pointer object) noexcept
6742  : m_object(object)
6743  {
6744  assert(m_object != nullptr);
6745 
6746  switch (m_object->m_type)
6747  {
6749  {
6750  m_it.object_iterator = typename object_t::iterator();
6751  break;
6752  }
6753 
6755  {
6756  m_it.array_iterator = typename array_t::iterator();
6757  break;
6758  }
6759 
6760  default:
6761  {
6762  m_it.primitive_iterator = primitive_iterator_t();
6763  break;
6764  }
6765  }
6766  }
6767 
6773  explicit const_iterator(const iterator& other) noexcept
6774  : m_object(other.m_object)
6775  {
6776  if (m_object != nullptr)
6777  {
6778  switch (m_object->m_type)
6779  {
6781  {
6782  m_it.object_iterator = other.m_it.object_iterator;
6783  break;
6784  }
6785 
6787  {
6788  m_it.array_iterator = other.m_it.array_iterator;
6789  break;
6790  }
6791 
6792  default:
6793  {
6794  m_it.primitive_iterator = other.m_it.primitive_iterator;
6795  break;
6796  }
6797  }
6798  }
6799  }
6800 
6806  const_iterator(const const_iterator& other) noexcept
6807  : m_object(other.m_object), m_it(other.m_it)
6808  {}
6809 
6816  std::is_nothrow_move_constructible<pointer>::value and
6817  std::is_nothrow_move_assignable<pointer>::value and
6818  std::is_nothrow_move_constructible<internal_iterator>::value and
6819  std::is_nothrow_move_assignable<internal_iterator>::value
6820  )
6821  {
6822  std::swap(m_object, other.m_object);
6823  std::swap(m_it, other.m_it);
6824  return *this;
6825  }
6826 
6827  private:
6832  void set_begin() noexcept
6833  {
6834  assert(m_object != nullptr);
6835 
6836  switch (m_object->m_type)
6837  {
6839  {
6840  m_it.object_iterator = m_object->m_value.object->begin();
6841  break;
6842  }
6843 
6845  {
6846  m_it.array_iterator = m_object->m_value.array->begin();
6847  break;
6848  }
6849 
6851  {
6852  // set to end so begin()==end() is true: null is empty
6853  m_it.primitive_iterator.set_end();
6854  break;
6855  }
6856 
6857  default:
6858  {
6859  m_it.primitive_iterator.set_begin();
6860  break;
6861  }
6862  }
6863  }
6864 
6869  void set_end() noexcept
6870  {
6871  assert(m_object != nullptr);
6872 
6873  switch (m_object->m_type)
6874  {
6876  {
6877  m_it.object_iterator = m_object->m_value.object->end();
6878  break;
6879  }
6880 
6882  {
6883  m_it.array_iterator = m_object->m_value.array->end();
6884  break;
6885  }
6886 
6887  default:
6888  {
6889  m_it.primitive_iterator.set_end();
6890  break;
6891  }
6892  }
6893  }
6894 
6895  public:
6901  {
6902  assert(m_object != nullptr);
6903 
6904  switch (m_object->m_type)
6905  {
6907  {
6908  assert(m_it.object_iterator != m_object->m_value.object->end());
6909  return m_it.object_iterator->second;
6910  }
6911 
6913  {
6914  assert(m_it.array_iterator != m_object->m_value.array->end());
6915  return *m_it.array_iterator;
6916  }
6917 
6919  {
6920  throw std::out_of_range("cannot get value");
6921  }
6922 
6923  default:
6924  {
6925  if (m_it.primitive_iterator.is_begin())
6926  {
6927  return *m_object;
6928  }
6929  else
6930  {
6931  throw std::out_of_range("cannot get value");
6932  }
6933  }
6934  }
6935  }
6936 
6942  {
6943  assert(m_object != nullptr);
6944 
6945  switch (m_object->m_type)
6946  {
6948  {
6949  assert(m_it.object_iterator != m_object->m_value.object->end());
6950  return &(m_it.object_iterator->second);
6951  }
6952 
6954  {
6955  assert(m_it.array_iterator != m_object->m_value.array->end());
6956  return &*m_it.array_iterator;
6957  }
6958 
6959  default:
6960  {
6961  if (m_it.primitive_iterator.is_begin())
6962  {
6963  return m_object;
6964  }
6965  else
6966  {
6967  throw std::out_of_range("cannot get value");
6968  }
6969  }
6970  }
6971  }
6972 
6978  {
6979  auto result = *this;
6980  ++(*this);
6981  return result;
6982  }
6983 
6989  {
6990  assert(m_object != nullptr);
6991 
6992  switch (m_object->m_type)
6993  {
6995  {
6996  std::advance(m_it.object_iterator, 1);
6997  break;
6998  }
6999 
7001  {
7002  std::advance(m_it.array_iterator, 1);
7003  break;
7004  }
7005 
7006  default:
7007  {
7008  ++m_it.primitive_iterator;
7009  break;
7010  }
7011  }
7012 
7013  return *this;
7014  }
7015 
7021  {
7022  auto result = *this;
7023  --(*this);
7024  return result;
7025  }
7026 
7032  {
7033  assert(m_object != nullptr);
7034 
7035  switch (m_object->m_type)
7036  {
7038  {
7039  std::advance(m_it.object_iterator, -1);
7040  break;
7041  }
7042 
7044  {
7045  std::advance(m_it.array_iterator, -1);
7046  break;
7047  }
7048 
7049  default:
7050  {
7051  --m_it.primitive_iterator;
7052  break;
7053  }
7054  }
7055 
7056  return *this;
7057  }
7058 
7063  bool operator==(const const_iterator& other) const
7064  {
7065  // if objects are not the same, the comparison is undefined
7066  if (m_object != other.m_object)
7067  {
7068  throw std::domain_error("cannot compare iterators of different containers");
7069  }
7070 
7071  assert(m_object != nullptr);
7072 
7073  switch (m_object->m_type)
7074  {
7076  {
7077  return (m_it.object_iterator == other.m_it.object_iterator);
7078  }
7079 
7081  {
7082  return (m_it.array_iterator == other.m_it.array_iterator);
7083  }
7084 
7085  default:
7086  {
7087  return (m_it.primitive_iterator == other.m_it.primitive_iterator);
7088  }
7089  }
7090  }
7091 
7096  bool operator!=(const const_iterator& other) const
7097  {
7098  return not operator==(other);
7099  }
7100 
7105  bool operator<(const const_iterator& other) const
7106  {
7107  // if objects are not the same, the comparison is undefined
7108  if (m_object != other.m_object)
7109  {
7110  throw std::domain_error("cannot compare iterators of different containers");
7111  }
7112 
7113  assert(m_object != nullptr);
7114 
7115  switch (m_object->m_type)
7116  {
7118  {
7119  throw std::domain_error("cannot compare order of object iterators");
7120  }
7121 
7123  {
7124  return (m_it.array_iterator < other.m_it.array_iterator);
7125  }
7126 
7127  default:
7128  {
7129  return (m_it.primitive_iterator < other.m_it.primitive_iterator);
7130  }
7131  }
7132  }
7133 
7138  bool operator<=(const const_iterator& other) const
7139  {
7140  return not other.operator < (*this);
7141  }
7142 
7147  bool operator>(const const_iterator& other) const
7148  {
7149  return not operator<=(other);
7150  }
7151 
7156  bool operator>=(const const_iterator& other) const
7157  {
7158  return not operator<(other);
7159  }
7160 
7166  {
7167  assert(m_object != nullptr);
7168 
7169  switch (m_object->m_type)
7170  {
7172  {
7173  throw std::domain_error("cannot use offsets with object iterators");
7174  }
7175 
7177  {
7178  std::advance(m_it.array_iterator, i);
7179  break;
7180  }
7181 
7182  default:
7183  {
7184  m_it.primitive_iterator += i;
7185  break;
7186  }
7187  }
7188 
7189  return *this;
7190  }
7191 
7197  {
7198  return operator+=(-i);
7199  }
7200 
7206  {
7207  auto result = *this;
7208  result += i;
7209  return result;
7210  }
7211 
7217  {
7218  auto result = *this;
7219  result -= i;
7220  return result;
7221  }
7222 
7228  {
7229  assert(m_object != nullptr);
7230 
7231  switch (m_object->m_type)
7232  {
7234  {
7235  throw std::domain_error("cannot use offsets with object iterators");
7236  }
7237 
7239  {
7240  return m_it.array_iterator - other.m_it.array_iterator;
7241  }
7242 
7243  default:
7244  {
7245  return m_it.primitive_iterator - other.m_it.primitive_iterator;
7246  }
7247  }
7248  }
7249 
7255  {
7256  assert(m_object != nullptr);
7257 
7258  switch (m_object->m_type)
7259  {
7261  {
7262  throw std::domain_error("cannot use operator[] for object iterators");
7263  }
7264 
7266  {
7267  return *std::next(m_it.array_iterator, n);
7268  }
7269 
7271  {
7272  throw std::out_of_range("cannot get value");
7273  }
7274 
7275  default:
7276  {
7277  if (m_it.primitive_iterator == -n)
7278  {
7279  return *m_object;
7280  }
7281  else
7282  {
7283  throw std::out_of_range("cannot get value");
7284  }
7285  }
7286  }
7287  }
7288 
7293  typename object_t::key_type key() const
7294  {
7295  assert(m_object != nullptr);
7296 
7297  if (m_object->is_object())
7298  {
7299  return m_it.object_iterator->first;
7300  }
7301  else
7302  {
7303  throw std::domain_error("cannot use key() for non-object iterators");
7304  }
7305  }
7306 
7312  {
7313  return operator*();
7314  }
7315 
7316  private:
7318  pointer m_object = nullptr;
7320  internal_iterator m_it = internal_iterator();
7321  };
7322 
7335  class iterator : public const_iterator
7336  {
7337  public:
7339  using pointer = typename basic_json::pointer;
7341 
7343  iterator() = default;
7344 
7346  explicit iterator(pointer object) noexcept
7347  : base_iterator(object)
7348  {}
7349 
7351  iterator(const iterator& other) noexcept
7352  : base_iterator(other)
7353  {}
7354 
7356  iterator& operator=(iterator other) noexcept(
7357  std::is_nothrow_move_constructible<pointer>::value and
7358  std::is_nothrow_move_assignable<pointer>::value and
7359  std::is_nothrow_move_constructible<internal_iterator>::value and
7360  std::is_nothrow_move_assignable<internal_iterator>::value
7361  )
7362  {
7363  base_iterator::operator=(other);
7364  return *this;
7365  }
7366 
7369  {
7370  return const_cast<reference>(base_iterator::operator*());
7371  }
7372 
7375  {
7376  return const_cast<pointer>(base_iterator::operator->());
7377  }
7378 
7381  {
7382  iterator result = *this;
7383  base_iterator::operator++();
7384  return result;
7385  }
7386 
7389  {
7390  base_iterator::operator++();
7391  return *this;
7392  }
7393 
7396  {
7397  iterator result = *this;
7398  base_iterator::operator--();
7399  return result;
7400  }
7401 
7404  {
7405  base_iterator::operator--();
7406  return *this;
7407  }
7408 
7411  {
7412  base_iterator::operator+=(i);
7413  return *this;
7414  }
7415 
7418  {
7419  base_iterator::operator-=(i);
7420  return *this;
7421  }
7422 
7425  {
7426  auto result = *this;
7427  result += i;
7428  return result;
7429  }
7430 
7433  {
7434  auto result = *this;
7435  result -= i;
7436  return result;
7437  }
7438 
7440  difference_type operator-(const iterator& other) const
7441  {
7442  return base_iterator::operator-(other);
7443  }
7444 
7447  {
7448  return const_cast<reference>(base_iterator::operator[](n));
7449  }
7450 
7453  {
7454  return const_cast<reference>(base_iterator::value());
7455  }
7456  };
7457 
7475  template<typename Base>
7476  class json_reverse_iterator : public std::reverse_iterator<Base>
7477  {
7478  public:
7480  using base_iterator = std::reverse_iterator<Base>;
7482  using reference = typename Base::reference;
7483 
7485  json_reverse_iterator(const typename base_iterator::iterator_type& it) noexcept
7486  : base_iterator(it)
7487  {}
7488 
7491  : base_iterator(it)
7492  {}
7493 
7496  {
7497  return base_iterator::operator++(1);
7498  }
7499 
7502  {
7503  base_iterator::operator++();
7504  return *this;
7505  }
7506 
7509  {
7510  return base_iterator::operator--(1);
7511  }
7512 
7515  {
7516  base_iterator::operator--();
7517  return *this;
7518  }
7519 
7522  {
7523  base_iterator::operator+=(i);
7524  return *this;
7525  }
7526 
7529  {
7530  auto result = *this;
7531  result += i;
7532  return result;
7533  }
7534 
7537  {
7538  auto result = *this;
7539  result -= i;
7540  return result;
7541  }
7542 
7545  {
7546  return this->base() - other.base();
7547  }
7548 
7551  {
7552  return *(this->operator+(n));
7553  }
7554 
7556  typename object_t::key_type key() const
7557  {
7558  auto it = --this->base();
7559  return it.key();
7560  }
7561 
7564  {
7565  auto it = --this->base();
7566  return it.operator * ();
7567  }
7568  };
7569 
7570 
7571  private:
7573  // lexer and parser //
7575 
7583  class lexer
7584  {
7585  public:
7587  enum class token_type
7588  {
7589  uninitialized,
7590  literal_true,
7591  literal_false,
7592  literal_null,
7593  value_string,
7594  value_number,
7595  begin_array,
7596  begin_object,
7597  end_array,
7598  end_object,
7599  name_separator,
7600  value_separator,
7601  parse_error,
7602  end_of_input
7603  };
7604 
7606  using lexer_char_t = unsigned char;
7607 
7609  lexer(const lexer_char_t* buff, const size_t len) noexcept
7610  : m_content(buff)
7611  {
7612  assert(m_content != nullptr);
7613  m_start = m_cursor = m_content;
7614  m_limit = m_content + len;
7615  }
7616 
7618  explicit lexer(std::istream& s)
7619  : m_stream(&s), m_line_buffer()
7620  {
7621  // fill buffer
7622  fill_line_buffer();
7623  }
7624 
7625  // switch off unwanted functions (due to pointer members)
7626  lexer() = delete;
7627  lexer(const lexer&) = delete;
7628  lexer operator=(const lexer&) = delete;
7629 
7653  static string_t to_unicode(const std::size_t codepoint1,
7654  const std::size_t codepoint2 = 0)
7655  {
7656  // calculate the code point from the given code points
7657  std::size_t codepoint = codepoint1;
7658 
7659  // check if codepoint1 is a high surrogate
7660  if (codepoint1 >= 0xD800 and codepoint1 <= 0xDBFF)
7661  {
7662  // check if codepoint2 is a low surrogate
7663  if (codepoint2 >= 0xDC00 and codepoint2 <= 0xDFFF)
7664  {
7665  codepoint =
7666  // high surrogate occupies the most significant 22 bits
7667  (codepoint1 << 10)
7668  // low surrogate occupies the least significant 15 bits
7669  + codepoint2
7670  // there is still the 0xD800, 0xDC00 and 0x10000 noise
7671  // in the result so we have to subtract with:
7672  // (0xD800 << 10) + DC00 - 0x10000 = 0x35FDC00
7673  - 0x35FDC00;
7674  }
7675  else
7676  {
7677  throw std::invalid_argument("missing or wrong low surrogate");
7678  }
7679  }
7680 
7681  string_t result;
7682 
7683  if (codepoint < 0x80)
7684  {
7685  // 1-byte characters: 0xxxxxxx (ASCII)
7686  result.append(1, static_cast<typename string_t::value_type>(codepoint));
7687  }
7688  else if (codepoint <= 0x7ff)
7689  {
7690  // 2-byte characters: 110xxxxx 10xxxxxx
7691  result.append(1, static_cast<typename string_t::value_type>(0xC0 | ((codepoint >> 6) & 0x1F)));
7692  result.append(1, static_cast<typename string_t::value_type>(0x80 | (codepoint & 0x3F)));
7693  }
7694  else if (codepoint <= 0xffff)
7695  {
7696  // 3-byte characters: 1110xxxx 10xxxxxx 10xxxxxx
7697  result.append(1, static_cast<typename string_t::value_type>(0xE0 | ((codepoint >> 12) & 0x0F)));
7698  result.append(1, static_cast<typename string_t::value_type>(0x80 | ((codepoint >> 6) & 0x3F)));
7699  result.append(1, static_cast<typename string_t::value_type>(0x80 | (codepoint & 0x3F)));
7700  }
7701  else if (codepoint <= 0x10ffff)
7702  {
7703  // 4-byte characters: 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
7704  result.append(1, static_cast<typename string_t::value_type>(0xF0 | ((codepoint >> 18) & 0x07)));
7705  result.append(1, static_cast<typename string_t::value_type>(0x80 | ((codepoint >> 12) & 0x3F)));
7706  result.append(1, static_cast<typename string_t::value_type>(0x80 | ((codepoint >> 6) & 0x3F)));
7707  result.append(1, static_cast<typename string_t::value_type>(0x80 | (codepoint & 0x3F)));
7708  }
7709  else
7710  {
7711  throw std::out_of_range("code points above 0x10FFFF are invalid");
7712  }
7713 
7714  return result;
7715  }
7716 
7718  static std::string token_type_name(const token_type t)
7719  {
7720  switch (t)
7721  {
7722  case token_type::uninitialized:
7723  return "<uninitialized>";
7724  case token_type::literal_true:
7725  return "true literal";
7726  case token_type::literal_false:
7727  return "false literal";
7728  case token_type::literal_null:
7729  return "null literal";
7730  case token_type::value_string:
7731  return "string literal";
7732  case token_type::value_number:
7733  return "number literal";
7734  case token_type::begin_array:
7735  return "'['";
7736  case token_type::begin_object:
7737  return "'{'";
7738  case token_type::end_array:
7739  return "']'";
7740  case token_type::end_object:
7741  return "'}'";
7742  case token_type::name_separator:
7743  return "':'";
7744  case token_type::value_separator:
7745  return "','";
7746  case token_type::parse_error:
7747  return "<parse error>";
7748  case token_type::end_of_input:
7749  return "end of input";
7750  default:
7751  {
7752  // catch non-enum values
7753  return "unknown token"; // LCOV_EXCL_LINE
7754  }
7755  }
7756  }
7757 
7779  token_type scan()
7780  {
7781  while (true)
7782  {
7783  // pointer for backtracking information
7784  m_marker = nullptr;
7785 
7786  // remember the begin of the token
7787  m_start = m_cursor;
7788  assert(m_start != nullptr);
7789 
7790 
7791  {
7792  lexer_char_t yych;
7793  unsigned int yyaccept = 0;
7794  static const unsigned char yybm[] = {
7795  0, 0, 0, 0, 0, 0, 0, 0,
7796  0, 32, 32, 0, 0, 32, 0, 0,
7797  0, 0, 0, 0, 0, 0, 0, 0,
7798  0, 0, 0, 0, 0, 0, 0, 0,
7799  160, 128, 0, 128, 128, 128, 128, 128,
7800  128, 128, 128, 128, 128, 128, 128, 128,
7801  192, 192, 192, 192, 192, 192, 192, 192,
7802  192, 192, 128, 128, 128, 128, 128, 128,
7803  128, 128, 128, 128, 128, 128, 128, 128,
7804  128, 128, 128, 128, 128, 128, 128, 128,
7805  128, 128, 128, 128, 128, 128, 128, 128,
7806  128, 128, 128, 128, 0, 128, 128, 128,
7807  128, 128, 128, 128, 128, 128, 128, 128,
7808  128, 128, 128, 128, 128, 128, 128, 128,
7809  128, 128, 128, 128, 128, 128, 128, 128,
7810  128, 128, 128, 128, 128, 128, 128, 128,
7811  128, 128, 128, 128, 128, 128, 128, 128,
7812  128, 128, 128, 128, 128, 128, 128, 128,
7813  128, 128, 128, 128, 128, 128, 128, 128,
7814  128, 128, 128, 128, 128, 128, 128, 128,
7815  128, 128, 128, 128, 128, 128, 128, 128,
7816  128, 128, 128, 128, 128, 128, 128, 128,
7817  128, 128, 128, 128, 128, 128, 128, 128,
7818  128, 128, 128, 128, 128, 128, 128, 128,
7819  128, 128, 128, 128, 128, 128, 128, 128,
7820  128, 128, 128, 128, 128, 128, 128, 128,
7821  128, 128, 128, 128, 128, 128, 128, 128,
7822  128, 128, 128, 128, 128, 128, 128, 128,
7823  128, 128, 128, 128, 128, 128, 128, 128,
7824  128, 128, 128, 128, 128, 128, 128, 128,
7825  128, 128, 128, 128, 128, 128, 128, 128,
7826  128, 128, 128, 128, 128, 128, 128, 128,
7827  };
7828  if ((m_limit - m_cursor) < 5) fill_line_buffer();
7829  yych = *m_cursor;
7830  if (yybm[0+yych] & 32) {
7831  goto basic_json_parser_6;
7832  }
7833  if (yych <= '\\') {
7834  if (yych <= '-') {
7835  if (yych <= '"') {
7836  if (yych <= 0x00) goto basic_json_parser_2;
7837  if (yych <= '!') goto basic_json_parser_4;
7838  goto basic_json_parser_9;
7839  } else {
7840  if (yych <= '+') goto basic_json_parser_4;
7841  if (yych <= ',') goto basic_json_parser_10;
7842  goto basic_json_parser_12;
7843  }
7844  } else {
7845  if (yych <= '9') {
7846  if (yych <= '/') goto basic_json_parser_4;
7847  if (yych <= '0') goto basic_json_parser_13;
7848  goto basic_json_parser_15;
7849  } else {
7850  if (yych <= ':') goto basic_json_parser_17;
7851  if (yych == '[') goto basic_json_parser_19;
7852  goto basic_json_parser_4;
7853  }
7854  }
7855  } else {
7856  if (yych <= 't') {
7857  if (yych <= 'f') {
7858  if (yych <= ']') goto basic_json_parser_21;
7859  if (yych <= 'e') goto basic_json_parser_4;
7860  goto basic_json_parser_23;
7861  } else {
7862  if (yych == 'n') goto basic_json_parser_24;
7863  if (yych <= 's') goto basic_json_parser_4;
7864  goto basic_json_parser_25;
7865  }
7866  } else {
7867  if (yych <= '|') {
7868  if (yych == '{') goto basic_json_parser_26;
7869  goto basic_json_parser_4;
7870  } else {
7871  if (yych <= '}') goto basic_json_parser_28;
7872  if (yych == 0xEF) goto basic_json_parser_30;
7873  goto basic_json_parser_4;
7874  }
7875  }
7876  }
7877 basic_json_parser_2:
7878  ++m_cursor;
7879  { last_token_type = token_type::end_of_input; break; }
7880 basic_json_parser_4:
7881  ++m_cursor;
7882 basic_json_parser_5:
7883  { last_token_type = token_type::parse_error; break; }
7884 basic_json_parser_6:
7885  ++m_cursor;
7886  if (m_limit <= m_cursor) fill_line_buffer();
7887  yych = *m_cursor;
7888  if (yybm[0+yych] & 32) {
7889  goto basic_json_parser_6;
7890  }
7891  { continue; }
7892 basic_json_parser_9:
7893  yyaccept = 0;
7894  yych = *(m_marker = ++m_cursor);
7895  if (yych <= 0x1F) goto basic_json_parser_5;
7896  goto basic_json_parser_32;
7897 basic_json_parser_10:
7898  ++m_cursor;
7899  { last_token_type = token_type::value_separator; break; }
7900 basic_json_parser_12:
7901  yych = *++m_cursor;
7902  if (yych <= '/') goto basic_json_parser_5;
7903  if (yych <= '0') goto basic_json_parser_13;
7904  if (yych <= '9') goto basic_json_parser_15;
7905  goto basic_json_parser_5;
7906 basic_json_parser_13:
7907  yyaccept = 1;
7908  yych = *(m_marker = ++m_cursor);
7909  if (yych <= 'D') {
7910  if (yych == '.') goto basic_json_parser_37;
7911  } else {
7912  if (yych <= 'E') goto basic_json_parser_38;
7913  if (yych == 'e') goto basic_json_parser_38;
7914  }
7915 basic_json_parser_14:
7916  { last_token_type = token_type::value_number; break; }
7917 basic_json_parser_15:
7918  yyaccept = 1;
7919  m_marker = ++m_cursor;
7920  if ((m_limit - m_cursor) < 3) fill_line_buffer();
7921  yych = *m_cursor;
7922  if (yybm[0+yych] & 64) {
7923  goto basic_json_parser_15;
7924  }
7925  if (yych <= 'D') {
7926  if (yych == '.') goto basic_json_parser_37;
7927  goto basic_json_parser_14;
7928  } else {
7929  if (yych <= 'E') goto basic_json_parser_38;
7930  if (yych == 'e') goto basic_json_parser_38;
7931  goto basic_json_parser_14;
7932  }
7933 basic_json_parser_17:
7934  ++m_cursor;
7935  { last_token_type = token_type::name_separator; break; }
7936 basic_json_parser_19:
7937  ++m_cursor;
7938  { last_token_type = token_type::begin_array; break; }
7939 basic_json_parser_21:
7940  ++m_cursor;
7941  { last_token_type = token_type::end_array; break; }
7942 basic_json_parser_23:
7943  yyaccept = 0;
7944  yych = *(m_marker = ++m_cursor);
7945  if (yych == 'a') goto basic_json_parser_39;
7946  goto basic_json_parser_5;
7947 basic_json_parser_24:
7948  yyaccept = 0;
7949  yych = *(m_marker = ++m_cursor);
7950  if (yych == 'u') goto basic_json_parser_40;
7951  goto basic_json_parser_5;
7952 basic_json_parser_25:
7953  yyaccept = 0;
7954  yych = *(m_marker = ++m_cursor);
7955  if (yych == 'r') goto basic_json_parser_41;
7956  goto basic_json_parser_5;
7957 basic_json_parser_26:
7958  ++m_cursor;
7959  { last_token_type = token_type::begin_object; break; }
7960 basic_json_parser_28:
7961  ++m_cursor;
7962  { last_token_type = token_type::end_object; break; }
7963 basic_json_parser_30:
7964  yyaccept = 0;
7965  yych = *(m_marker = ++m_cursor);
7966  if (yych == 0xBB) goto basic_json_parser_42;
7967  goto basic_json_parser_5;
7968 basic_json_parser_31:
7969  ++m_cursor;
7970  if (m_limit <= m_cursor) fill_line_buffer();
7971  yych = *m_cursor;
7972 basic_json_parser_32:
7973  if (yybm[0+yych] & 128) {
7974  goto basic_json_parser_31;
7975  }
7976  if (yych <= 0x1F) goto basic_json_parser_33;
7977  if (yych <= '"') goto basic_json_parser_34;
7978  goto basic_json_parser_36;
7979 basic_json_parser_33:
7980  m_cursor = m_marker;
7981  if (yyaccept == 0) {
7982  goto basic_json_parser_5;
7983  } else {
7984  goto basic_json_parser_14;
7985  }
7986 basic_json_parser_34:
7987  ++m_cursor;
7988  { last_token_type = token_type::value_string; break; }
7989 basic_json_parser_36:
7990  ++m_cursor;
7991  if (m_limit <= m_cursor) fill_line_buffer();
7992  yych = *m_cursor;
7993  if (yych <= 'e') {
7994  if (yych <= '/') {
7995  if (yych == '"') goto basic_json_parser_31;
7996  if (yych <= '.') goto basic_json_parser_33;
7997  goto basic_json_parser_31;
7998  } else {
7999  if (yych <= '\\') {
8000  if (yych <= '[') goto basic_json_parser_33;
8001  goto basic_json_parser_31;
8002  } else {
8003  if (yych == 'b') goto basic_json_parser_31;
8004  goto basic_json_parser_33;
8005  }
8006  }
8007  } else {
8008  if (yych <= 'q') {
8009  if (yych <= 'f') goto basic_json_parser_31;
8010  if (yych == 'n') goto basic_json_parser_31;
8011  goto basic_json_parser_33;
8012  } else {
8013  if (yych <= 's') {
8014  if (yych <= 'r') goto basic_json_parser_31;
8015  goto basic_json_parser_33;
8016  } else {
8017  if (yych <= 't') goto basic_json_parser_31;
8018  if (yych <= 'u') goto basic_json_parser_43;
8019  goto basic_json_parser_33;
8020  }
8021  }
8022  }
8023 basic_json_parser_37:
8024  yych = *++m_cursor;
8025  if (yych <= '/') goto basic_json_parser_33;
8026  if (yych <= '9') goto basic_json_parser_44;
8027  goto basic_json_parser_33;
8028 basic_json_parser_38:
8029  yych = *++m_cursor;
8030  if (yych <= ',') {
8031  if (yych == '+') goto basic_json_parser_46;
8032  goto basic_json_parser_33;
8033  } else {
8034  if (yych <= '-') goto basic_json_parser_46;
8035  if (yych <= '/') goto basic_json_parser_33;
8036  if (yych <= '9') goto basic_json_parser_47;
8037  goto basic_json_parser_33;
8038  }
8039 basic_json_parser_39:
8040  yych = *++m_cursor;
8041  if (yych == 'l') goto basic_json_parser_49;
8042  goto basic_json_parser_33;
8043 basic_json_parser_40:
8044  yych = *++m_cursor;
8045  if (yych == 'l') goto basic_json_parser_50;
8046  goto basic_json_parser_33;
8047 basic_json_parser_41:
8048  yych = *++m_cursor;
8049  if (yych == 'u') goto basic_json_parser_51;
8050  goto basic_json_parser_33;
8051 basic_json_parser_42:
8052  yych = *++m_cursor;
8053  if (yych == 0xBF) goto basic_json_parser_52;
8054  goto basic_json_parser_33;
8055 basic_json_parser_43:
8056  ++m_cursor;
8057  if (m_limit <= m_cursor) fill_line_buffer();
8058  yych = *m_cursor;
8059  if (yych <= '@') {
8060  if (yych <= '/') goto basic_json_parser_33;
8061  if (yych <= '9') goto basic_json_parser_54;
8062  goto basic_json_parser_33;
8063  } else {
8064  if (yych <= 'F') goto basic_json_parser_54;
8065  if (yych <= '`') goto basic_json_parser_33;
8066  if (yych <= 'f') goto basic_json_parser_54;
8067  goto basic_json_parser_33;
8068  }
8069 basic_json_parser_44:
8070  yyaccept = 1;
8071  m_marker = ++m_cursor;
8072  if ((m_limit - m_cursor) < 3) fill_line_buffer();
8073  yych = *m_cursor;
8074  if (yych <= 'D') {
8075  if (yych <= '/') goto basic_json_parser_14;
8076  if (yych <= '9') goto basic_json_parser_44;
8077  goto basic_json_parser_14;
8078  } else {
8079  if (yych <= 'E') goto basic_json_parser_38;
8080  if (yych == 'e') goto basic_json_parser_38;
8081  goto basic_json_parser_14;
8082  }
8083 basic_json_parser_46:
8084  yych = *++m_cursor;
8085  if (yych <= '/') goto basic_json_parser_33;
8086  if (yych >= ':') goto basic_json_parser_33;
8087 basic_json_parser_47:
8088  ++m_cursor;
8089  if (m_limit <= m_cursor) fill_line_buffer();
8090  yych = *m_cursor;
8091  if (yych <= '/') goto basic_json_parser_14;
8092  if (yych <= '9') goto basic_json_parser_47;
8093  goto basic_json_parser_14;
8094 basic_json_parser_49:
8095  yych = *++m_cursor;
8096  if (yych == 's') goto basic_json_parser_55;
8097  goto basic_json_parser_33;
8098 basic_json_parser_50:
8099  yych = *++m_cursor;
8100  if (yych == 'l') goto basic_json_parser_56;
8101  goto basic_json_parser_33;
8102 basic_json_parser_51:
8103  yych = *++m_cursor;
8104  if (yych == 'e') goto basic_json_parser_58;
8105  goto basic_json_parser_33;
8106 basic_json_parser_52:
8107  ++m_cursor;
8108  { continue; }
8109 basic_json_parser_54:
8110  ++m_cursor;
8111  if (m_limit <= m_cursor) fill_line_buffer();
8112  yych = *m_cursor;
8113  if (yych <= '@') {
8114  if (yych <= '/') goto basic_json_parser_33;
8115  if (yych <= '9') goto basic_json_parser_60;
8116  goto basic_json_parser_33;
8117  } else {
8118  if (yych <= 'F') goto basic_json_parser_60;
8119  if (yych <= '`') goto basic_json_parser_33;
8120  if (yych <= 'f') goto basic_json_parser_60;
8121  goto basic_json_parser_33;
8122  }
8123 basic_json_parser_55:
8124  yych = *++m_cursor;
8125  if (yych == 'e') goto basic_json_parser_61;
8126  goto basic_json_parser_33;
8127 basic_json_parser_56:
8128  ++m_cursor;
8129  { last_token_type = token_type::literal_null; break; }
8130 basic_json_parser_58:
8131  ++m_cursor;
8132  { last_token_type = token_type::literal_true; break; }
8133 basic_json_parser_60:
8134  ++m_cursor;
8135  if (m_limit <= m_cursor) fill_line_buffer();
8136  yych = *m_cursor;
8137  if (yych <= '@') {
8138  if (yych <= '/') goto basic_json_parser_33;
8139  if (yych <= '9') goto basic_json_parser_63;
8140  goto basic_json_parser_33;
8141  } else {
8142  if (yych <= 'F') goto basic_json_parser_63;
8143  if (yych <= '`') goto basic_json_parser_33;
8144  if (yych <= 'f') goto basic_json_parser_63;
8145  goto basic_json_parser_33;
8146  }
8147 basic_json_parser_61:
8148  ++m_cursor;
8149  { last_token_type = token_type::literal_false; break; }
8150 basic_json_parser_63:
8151  ++m_cursor;
8152  if (m_limit <= m_cursor) fill_line_buffer();
8153  yych = *m_cursor;
8154  if (yych <= '@') {
8155  if (yych <= '/') goto basic_json_parser_33;
8156  if (yych <= '9') goto basic_json_parser_31;
8157  goto basic_json_parser_33;
8158  } else {
8159  if (yych <= 'F') goto basic_json_parser_31;
8160  if (yych <= '`') goto basic_json_parser_33;
8161  if (yych <= 'f') goto basic_json_parser_31;
8162  goto basic_json_parser_33;
8163  }
8164  }
8165 
8166  }
8167 
8168  return last_token_type;
8169  }
8170 
8199  void fill_line_buffer()
8200  {
8201  // number of processed characters (p)
8202  const auto offset_start = m_start - m_content;
8203  // offset for m_marker wrt. to m_start
8204  const auto offset_marker = (m_marker == nullptr) ? 0 : m_marker - m_start;
8205  // number of unprocessed characters (u)
8206  const auto offset_cursor = m_cursor - m_start;
8207 
8208  // no stream is used or end of file is reached
8209  if (m_stream == nullptr or m_stream->eof())
8210  {
8211  // copy unprocessed characters to line buffer
8212  m_line_buffer.clear();
8213  for (m_cursor = m_start; m_cursor != m_limit; ++m_cursor)
8214  {
8215  m_line_buffer.append(1, static_cast<const char>(*m_cursor));
8216  }
8217 
8218  // append 5 characters (size of longest keyword "false") to
8219  // make sure that there is sufficient space between m_cursor
8220  // and m_limit
8221  m_line_buffer.append(5, '\0');
8222  }
8223  else
8224  {
8225  // delete processed characters from line buffer
8226  m_line_buffer.erase(0, static_cast<size_t>(offset_start));
8227  // read next line from input stream
8228  std::string line;
8229  std::getline(*m_stream, line);
8230  // add line with newline symbol to the line buffer
8231  m_line_buffer += line + "\n";
8232  }
8233 
8234  // set pointers
8235  m_content = reinterpret_cast<const lexer_char_t*>(m_line_buffer.c_str());
8236  assert(m_content != nullptr);
8237  m_start = m_content;
8238  m_marker = m_start + offset_marker;
8239  m_cursor = m_start + offset_cursor;
8240  m_limit = m_start + m_line_buffer.size();
8241  }
8242 
8244  string_t get_token_string() const
8245  {
8246  assert(m_start != nullptr);
8247  return string_t(reinterpret_cast<typename string_t::const_pointer>(m_start),
8248  static_cast<size_t>(m_cursor - m_start));
8249  }
8250 
8308  string_t get_string() const
8309  {
8310  assert(m_cursor - m_start >= 2);
8311 
8312  string_t result;
8313  result.reserve(static_cast<size_t>(m_cursor - m_start - 2));
8314 
8315  // iterate the result between the quotes
8316  for (const lexer_char_t* i = m_start + 1; i < m_cursor - 1; ++i)
8317  {
8318  // process escaped characters
8319  if (*i == '\\')
8320  {
8321  // read next character
8322  ++i;
8323 
8324  switch (*i)
8325  {
8326  // the default escapes
8327  case 't':
8328  {
8329  result += "\t";
8330  break;
8331  }
8332  case 'b':
8333  {
8334  result += "\b";
8335  break;
8336  }
8337  case 'f':
8338  {
8339  result += "\f";
8340  break;
8341  }
8342  case 'n':
8343  {
8344  result += "\n";
8345  break;
8346  }
8347  case 'r':
8348  {
8349  result += "\r";
8350  break;
8351  }
8352  case '\\':
8353  {
8354  result += "\\";
8355  break;
8356  }
8357  case '/':
8358  {
8359  result += "/";
8360  break;
8361  }
8362  case '"':
8363  {
8364  result += "\"";
8365  break;
8366  }
8367 
8368  // unicode
8369  case 'u':
8370  {
8371  // get code xxxx from uxxxx
8372  auto codepoint = std::strtoul(std::string(reinterpret_cast<typename string_t::const_pointer>(i + 1),
8373  4).c_str(), nullptr, 16);
8374 
8375  // check if codepoint is a high surrogate
8376  if (codepoint >= 0xD800 and codepoint <= 0xDBFF)
8377  {
8378  // make sure there is a subsequent unicode
8379  if ((i + 6 >= m_limit) or * (i + 5) != '\\' or * (i + 6) != 'u')
8380  {
8381  throw std::invalid_argument("missing low surrogate");
8382  }
8383 
8384  // get code yyyy from uxxxx\uyyyy
8385  auto codepoint2 = std::strtoul(std::string(reinterpret_cast<typename string_t::const_pointer>
8386  (i + 7), 4).c_str(), nullptr, 16);
8387  result += to_unicode(codepoint, codepoint2);
8388  // skip the next 10 characters (xxxx\uyyyy)
8389  i += 10;
8390  }
8391  else
8392  {
8393  // add unicode character(s)
8394  result += to_unicode(codepoint);
8395  // skip the next four characters (xxxx)
8396  i += 4;
8397  }
8398  break;
8399  }
8400  }
8401  }
8402  else
8403  {
8404  // all other characters are just copied to the end of the
8405  // string
8406  result.append(1, static_cast<typename string_t::value_type>(*i));
8407  }
8408  }
8409 
8410  return result;
8411  }
8412 
8428  long double str_to_float_t(long double* /* type */, char** endptr) const
8429  {
8430  return std::strtold(reinterpret_cast<typename string_t::const_pointer>(m_start), endptr);
8431  }
8432 
8448  double str_to_float_t(double* /* type */, char** endptr) const
8449  {
8450  return std::strtod(reinterpret_cast<typename string_t::const_pointer>(m_start), endptr);
8451  }
8452 
8468  float str_to_float_t(float* /* type */, char** endptr) const
8469  {
8470  return std::strtof(reinterpret_cast<typename string_t::const_pointer>(m_start), endptr);
8471  }
8472 
8494  void get_number(basic_json& result) const
8495  {
8496  assert(m_start != nullptr);
8497 
8498  const lexer::lexer_char_t* curptr = m_start;
8499 
8500  // accumulate the integer conversion result (unsigned for now)
8501  number_unsigned_t value = 0;
8502 
8503  // maximum absolute value of the relevant integer type
8504  number_unsigned_t max;
8505 
8506  // temporarily store the type to avoid unecessary bitfield access
8507  value_t type;
8508 
8509  // look for sign
8510  if (*curptr == '-')
8511  {
8512  type = value_t::number_integer;
8513  max = static_cast<uint64_t>((std::numeric_limits<number_integer_t>::max)()) + 1;
8514  curptr++;
8515  }
8516  else
8517  {
8518  type = value_t::number_unsigned;
8519  max = static_cast<uint64_t>((std::numeric_limits<number_unsigned_t>::max)());
8520  }
8521 
8522  // count the significant figures
8523  for (; curptr < m_cursor; curptr++)
8524  {
8525  // quickly skip tests if a digit
8526  if (*curptr < '0' || *curptr > '9')
8527  {
8528  if (*curptr == '.')
8529  {
8530  // don't count '.' but change to float
8531  type = value_t::number_float;
8532  continue;
8533  }
8534  // assume exponent (if not then will fail parse): change to
8535  // float, stop counting and record exponent details
8536  type = value_t::number_float;
8537  break;
8538  }
8539 
8540  // skip if definitely not an integer
8541  if (type != value_t::number_float)
8542  {
8543  // multiply last value by ten and add the new digit
8544  auto temp = value * 10 + *curptr - '0';
8545 
8546  // test for overflow
8547  if (temp < value || temp > max)
8548  {
8549  // overflow
8550  type = value_t::number_float;
8551  }
8552  else
8553  {
8554  // no overflow - save it
8555  value = temp;
8556  }
8557  }
8558  }
8559 
8560  // save the value (if not a float)
8561  if (type == value_t::number_unsigned)
8562  {
8563  result.m_value.number_unsigned = value;
8564  }
8565  else if (type == value_t::number_integer)
8566  {
8567  result.m_value.number_integer = -static_cast<number_integer_t>(value);
8568  }
8569  else
8570  {
8571  // parse with strtod
8572  result.m_value.number_float = str_to_float_t(static_cast<number_float_t*>(nullptr), NULL);
8573  }
8574 
8575  // save the type
8576  result.m_type = type;
8577  }
8578 
8579  private:
8581  std::istream* m_stream = nullptr;
8583  string_t m_line_buffer {};
8585  const lexer_char_t* m_content = nullptr;
8587  const lexer_char_t* m_start = nullptr;
8589  const lexer_char_t* m_marker = nullptr;
8591  const lexer_char_t* m_cursor = nullptr;
8593  const lexer_char_t* m_limit = nullptr;
8595  token_type last_token_type = token_type::end_of_input;
8596  };
8597 
8603  class parser
8604  {
8605  public:
8607  parser(const char* buff, const parser_callback_t cb = nullptr)
8608  : callback(cb),
8609  m_lexer(reinterpret_cast<const typename lexer::lexer_char_t*>(buff), strlen(buff))
8610  {}
8611 
8613  parser(std::istream& is, const parser_callback_t cb = nullptr)
8614  : callback(cb), m_lexer(is)
8615  {}
8616 
8618  template<class IteratorType, typename std::enable_if<
8619  std::is_same<typename std::iterator_traits<IteratorType>::iterator_category, std::random_access_iterator_tag>::value
8620  , int>::type
8621  = 0>
8622  parser(IteratorType first, IteratorType last, const parser_callback_t cb = nullptr)
8623  : callback(cb),
8624  m_lexer(reinterpret_cast<const typename lexer::lexer_char_t*>(&(*first)),
8625  static_cast<size_t>(std::distance(first, last)))
8626  {}
8627 
8629  basic_json parse()
8630  {
8631  // read first token
8632  get_token();
8633 
8634  basic_json result = parse_internal(true);
8635  result.assert_invariant();
8636 
8637  expect(lexer::token_type::end_of_input);
8638 
8639  // return parser result and replace it with null in case the
8640  // top-level value was discarded by the callback function
8641  return result.is_discarded() ? basic_json() : std::move(result);
8642  }
8643 
8644  private:
8646  basic_json parse_internal(bool keep)
8647  {
8648  auto result = basic_json(value_t::discarded);
8649 
8650  switch (last_token)
8651  {
8652  case lexer::token_type::begin_object:
8653  {
8654  if (keep and (not callback
8655  or ((keep = callback(depth++, parse_event_t::object_start, result)) != 0)))
8656  {
8657  // explicitly set result to object to cope with {}
8658  result.m_type = value_t::object;
8659  result.m_value = value_t::object;
8660  }
8661 
8662  // read next token
8663  get_token();
8664 
8665  // closing } -> we are done
8666  if (last_token == lexer::token_type::end_object)
8667  {
8668  get_token();
8669  if (keep and callback and not callback(--depth, parse_event_t::object_end, result))
8670  {
8671  result = basic_json(value_t::discarded);
8672  }
8673  return result;
8674  }
8675 
8676  // no comma is expected here
8677  unexpect(lexer::token_type::value_separator);
8678 
8679  // otherwise: parse key-value pairs
8680  do
8681  {
8682  // ugly, but could be fixed with loop reorganization
8683  if (last_token == lexer::token_type::value_separator)
8684  {
8685  get_token();
8686  }
8687 
8688  // store key
8689  expect(lexer::token_type::value_string);
8690  const auto key = m_lexer.get_string();
8691 
8692  bool keep_tag = false;
8693  if (keep)
8694  {
8695  if (callback)
8696  {
8697  basic_json k(key);
8698  keep_tag = callback(depth, parse_event_t::key, k);
8699  }
8700  else
8701  {
8702  keep_tag = true;
8703  }
8704  }
8705 
8706  // parse separator (:)
8707  get_token();
8708  expect(lexer::token_type::name_separator);
8709 
8710  // parse and add value
8711  get_token();
8712  auto value = parse_internal(keep);
8713  if (keep and keep_tag and not value.is_discarded())
8714  {
8715  result[key] = std::move(value);
8716  }
8717  }
8718  while (last_token == lexer::token_type::value_separator);
8719 
8720  // closing }
8721  expect(lexer::token_type::end_object);
8722  get_token();
8723  if (keep and callback and not callback(--depth, parse_event_t::object_end, result))
8724  {
8725  result = basic_json(value_t::discarded);
8726  }
8727 
8728  return result;
8729  }
8730 
8731  case lexer::token_type::begin_array:
8732  {
8733  if (keep and (not callback
8734  or ((keep = callback(depth++, parse_event_t::array_start, result)) != 0)))
8735  {
8736  // explicitly set result to object to cope with []
8737  result.m_type = value_t::array;
8738  result.m_value = value_t::array;
8739  }
8740 
8741  // read next token
8742  get_token();
8743 
8744  // closing ] -> we are done
8745  if (last_token == lexer::token_type::end_array)
8746  {
8747  get_token();
8748  if (callback and not callback(--depth, parse_event_t::array_end, result))
8749  {
8750  result = basic_json(value_t::discarded);
8751  }
8752  return result;
8753  }
8754 
8755  // no comma is expected here
8756  unexpect(lexer::token_type::value_separator);
8757 
8758  // otherwise: parse values
8759  do
8760  {
8761  // ugly, but could be fixed with loop reorganization
8762  if (last_token == lexer::token_type::value_separator)
8763  {
8764  get_token();
8765  }
8766 
8767  // parse value
8768  auto value = parse_internal(keep);
8769  if (keep and not value.is_discarded())
8770  {
8771  result.push_back(std::move(value));
8772  }
8773  }
8774  while (last_token == lexer::token_type::value_separator);
8775 
8776  // closing ]
8777  expect(lexer::token_type::end_array);
8778  get_token();
8779  if (keep and callback and not callback(--depth, parse_event_t::array_end, result))
8780  {
8781  result = basic_json(value_t::discarded);
8782  }
8783 
8784  return result;
8785  }
8786 
8787  case lexer::token_type::literal_null:
8788  {
8789  get_token();
8790  result.m_type = value_t::null;
8791  break;
8792  }
8793 
8794  case lexer::token_type::value_string:
8795  {
8796  const auto s = m_lexer.get_string();
8797  get_token();
8798  result = basic_json(s);
8799  break;
8800  }
8801 
8802  case lexer::token_type::literal_true:
8803  {
8804  get_token();
8805  result.m_type = value_t::boolean;
8806  result.m_value = true;
8807  break;
8808  }
8809 
8810  case lexer::token_type::literal_false:
8811  {
8812  get_token();
8813  result.m_type = value_t::boolean;
8814  result.m_value = false;
8815  break;
8816  }
8817 
8818  case lexer::token_type::value_number:
8819  {
8820  m_lexer.get_number(result);
8821  get_token();
8822  break;
8823  }
8824 
8825  default:
8826  {
8827  // the last token was unexpected
8828  unexpect(last_token);
8829  }
8830  }
8831 
8832  if (keep and callback and not callback(depth, parse_event_t::value, result))
8833  {
8834  result = basic_json(value_t::discarded);
8835  }
8836  return result;
8837  }
8838 
8840  typename lexer::token_type get_token()
8841  {
8842  last_token = m_lexer.scan();
8843  return last_token;
8844  }
8845 
8846  void expect(typename lexer::token_type t) const
8847  {
8848  if (t != last_token)
8849  {
8850  std::string error_msg = "parse error - unexpected ";
8851  error_msg += (last_token == lexer::token_type::parse_error ? ("'" + m_lexer.get_token_string() +
8852  "'") :
8853  lexer::token_type_name(last_token));
8854  error_msg += "; expected " + lexer::token_type_name(t);
8855  throw std::invalid_argument(error_msg);
8856  }
8857  }
8858 
8859  void unexpect(typename lexer::token_type t) const
8860  {
8861  if (t == last_token)
8862  {
8863  std::string error_msg = "parse error - unexpected ";
8864  error_msg += (last_token == lexer::token_type::parse_error ? ("'" + m_lexer.get_token_string() +
8865  "'") :
8866  lexer::token_type_name(last_token));
8867  throw std::invalid_argument(error_msg);
8868  }
8869  }
8870 
8871  private:
8873  int depth = 0;
8875  const parser_callback_t callback = nullptr;
8877  typename lexer::token_type last_token = lexer::token_type::uninitialized;
8879  lexer m_lexer;
8880  };
8881 
8882  public:
8895  {
8897  friend class basic_json;
8898 
8899  public:
8922  explicit json_pointer(const std::string& s = "")
8923  : reference_tokens(split(s))
8924  {}
8925 
8941  std::string to_string() const noexcept
8942  {
8943  return std::accumulate(reference_tokens.begin(),
8944  reference_tokens.end(), std::string{},
8945  [](const std::string & a, const std::string & b)
8946  {
8947  return a + "/" + escape(b);
8948  });
8949  }
8950 
8952  operator std::string() const
8953  {
8954  return to_string();
8955  }
8957  private:
8959  std::string pop_back()
8960  {
8961  if (is_root())
8962  {
8963  throw std::domain_error("JSON pointer has no parent");
8964  }
8965 
8966  auto last = reference_tokens.back();
8967  reference_tokens.pop_back();
8968  return last;
8969  }
8970 
8972  bool is_root() const
8973  {
8974  return reference_tokens.empty();
8975  }
8976 
8977  json_pointer top() const
8978  {
8979  if (is_root())
8980  {
8981  throw std::domain_error("JSON pointer has no parent");
8982  }
8983 
8984  json_pointer result = *this;
8985  result.reference_tokens = {reference_tokens[0]};
8986  return result;
8987  }
8988 
8994  reference get_and_create(reference j) const
8995  {
8996  pointer result = &j;
8997 
8998  // in case no reference tokens exist, return a reference to the
8999  // JSON value j which will be overwritten by a primitive value
9000  for (const auto& reference_token : reference_tokens)
9001  {
9002  switch (result->m_type)
9003  {
9004  case value_t::null:
9005  {
9006  if (reference_token == "0")
9007  {
9008  // start a new array if reference token is 0
9009  result = &result->operator[](0);
9010  }
9011  else
9012  {
9013  // start a new object otherwise
9014  result = &result->operator[](reference_token);
9015  }
9016  break;
9017  }
9018 
9019  case value_t::object:
9020  {
9021  // create an entry in the object
9022  result = &result->operator[](reference_token);
9023  break;
9024  }
9025 
9026  case value_t::array:
9027  {
9028  // create an entry in the array
9029  result = &result->operator[](static_cast<size_type>(std::stoi(reference_token)));
9030  break;
9031  }
9032 
9033  /*
9034  The following code is only reached if there exists a
9035  reference token _and_ the current value is primitive. In
9036  this case, we have an error situation, because primitive
9037  values may only occur as single value; that is, with an
9038  empty list of reference tokens.
9039  */
9040  default:
9041  {
9042  throw std::domain_error("invalid value to unflatten");
9043  }
9044  }
9045  }
9046 
9047  return *result;
9048  }
9049 
9069  reference get_unchecked(pointer ptr) const
9070  {
9071  for (const auto& reference_token : reference_tokens)
9072  {
9073  // convert null values to arrays or objects before continuing
9074  if (ptr->m_type == value_t::null)
9075  {
9076  // check if reference token is a number
9077  const bool nums = std::all_of(reference_token.begin(),
9078  reference_token.end(),
9079  [](const char x)
9080  {
9081  return std::isdigit(x);
9082  });
9083 
9084  // change value to array for numbers or "-" or to object
9085  // otherwise
9086  if (nums or reference_token == "-")
9087  {
9088  *ptr = value_t::array;
9089  }
9090  else
9091  {
9092  *ptr = value_t::object;
9093  }
9094  }
9095 
9096  switch (ptr->m_type)
9097  {
9098  case value_t::object:
9099  {
9100  // use unchecked object access
9101  ptr = &ptr->operator[](reference_token);
9102  break;
9103  }
9104 
9105  case value_t::array:
9106  {
9107  // error condition (cf. RFC 6901, Sect. 4)
9108  if (reference_token.size() > 1 and reference_token[0] == '0')
9109  {
9110  throw std::domain_error("array index must not begin with '0'");
9111  }
9112 
9113  if (reference_token == "-")
9114  {
9115  // explicityly treat "-" as index beyond the end
9116  ptr = &ptr->operator[](ptr->m_value.array->size());
9117  }
9118  else
9119  {
9120  // convert array index to number; unchecked access
9121  ptr = &ptr->operator[](static_cast<size_type>(std::stoi(reference_token)));
9122  }
9123  break;
9124  }
9125 
9126  default:
9127  {
9128  throw std::out_of_range("unresolved reference token '" + reference_token + "'");
9129  }
9130  }
9131  }
9132 
9133  return *ptr;
9134  }
9135 
9136  reference get_checked(pointer ptr) const
9137  {
9138  for (const auto& reference_token : reference_tokens)
9139  {
9140  switch (ptr->m_type)
9141  {
9142  case value_t::object:
9143  {
9144  // note: at performs range check
9145  ptr = &ptr->at(reference_token);
9146  break;
9147  }
9148 
9149  case value_t::array:
9150  {
9151  if (reference_token == "-")
9152  {
9153  // "-" always fails the range check
9154  throw std::out_of_range("array index '-' (" +
9155  std::to_string(ptr->m_value.array->size()) +
9156  ") is out of range");
9157  }
9158 
9159  // error condition (cf. RFC 6901, Sect. 4)
9160  if (reference_token.size() > 1 and reference_token[0] == '0')
9161  {
9162  throw std::domain_error("array index must not begin with '0'");
9163  }
9164 
9165  // note: at performs range check
9166  ptr = &ptr->at(static_cast<size_type>(std::stoi(reference_token)));
9167  break;
9168  }
9169 
9170  default:
9171  {
9172  throw std::out_of_range("unresolved reference token '" + reference_token + "'");
9173  }
9174  }
9175  }
9176 
9177  return *ptr;
9178  }
9179 
9188  const_reference get_unchecked(const_pointer ptr) const
9189  {
9190  for (const auto& reference_token : reference_tokens)
9191  {
9192  switch (ptr->m_type)
9193  {
9194  case value_t::object:
9195  {
9196  // use unchecked object access
9197  ptr = &ptr->operator[](reference_token);
9198  break;
9199  }
9200 
9201  case value_t::array:
9202  {
9203  if (reference_token == "-")
9204  {
9205  // "-" cannot be used for const access
9206  throw std::out_of_range("array index '-' (" +
9207  std::to_string(ptr->m_value.array->size()) +
9208  ") is out of range");
9209  }
9210 
9211  // error condition (cf. RFC 6901, Sect. 4)
9212  if (reference_token.size() > 1 and reference_token[0] == '0')
9213  {
9214  throw std::domain_error("array index must not begin with '0'");
9215  }
9216 
9217  // use unchecked array access
9218  ptr = &ptr->operator[](static_cast<size_type>(std::stoi(reference_token)));
9219  break;
9220  }
9221 
9222  default:
9223  {
9224  throw std::out_of_range("unresolved reference token '" + reference_token + "'");
9225  }
9226  }
9227  }
9228 
9229  return *ptr;
9230  }
9231 
9232  const_reference get_checked(const_pointer ptr) const
9233  {
9234  for (const auto& reference_token : reference_tokens)
9235  {
9236  switch (ptr->m_type)
9237  {
9238  case value_t::object:
9239  {
9240  // note: at performs range check
9241  ptr = &ptr->at(reference_token);
9242  break;
9243  }
9244 
9245  case value_t::array:
9246  {
9247  if (reference_token == "-")
9248  {
9249  // "-" always fails the range check
9250  throw std::out_of_range("array index '-' (" +
9251  std::to_string(ptr->m_value.array->size()) +
9252  ") is out of range");
9253  }
9254 
9255  // error condition (cf. RFC 6901, Sect. 4)
9256  if (reference_token.size() > 1 and reference_token[0] == '0')
9257  {
9258  throw std::domain_error("array index must not begin with '0'");
9259  }
9260 
9261  // note: at performs range check
9262  ptr = &ptr->at(static_cast<size_type>(std::stoi(reference_token)));
9263  break;
9264  }
9265 
9266  default:
9267  {
9268  throw std::out_of_range("unresolved reference token '" + reference_token + "'");
9269  }
9270  }
9271  }
9272 
9273  return *ptr;
9274  }
9275 
9277  static std::vector<std::string> split(const std::string& reference_string)
9278  {
9279  std::vector<std::string> result;
9280 
9281  // special case: empty reference string -> no reference tokens
9282  if (reference_string.empty())
9283  {
9284  return result;
9285  }
9286 
9287  // check if nonempty reference string begins with slash
9288  if (reference_string[0] != '/')
9289  {
9290  throw std::domain_error("JSON pointer must be empty or begin with '/'");
9291  }
9292 
9293  // extract the reference tokens:
9294  // - slash: position of the last read slash (or end of string)
9295  // - start: position after the previous slash
9296  for (
9297  // search for the first slash after the first character
9298  size_t slash = reference_string.find_first_of("/", 1),
9299  // set the beginning of the first reference token
9300  start = 1;
9301  // we can stop if start == string::npos+1 = 0
9302  start != 0;
9303  // set the beginning of the next reference token
9304  // (will eventually be 0 if slash == std::string::npos)
9305  start = slash + 1,
9306  // find next slash
9307  slash = reference_string.find_first_of("/", start))
9308  {
9309  // use the text between the beginning of the reference token
9310  // (start) and the last slash (slash).
9311  auto reference_token = reference_string.substr(start, slash - start);
9312 
9313  // check reference tokens are properly escaped
9314  for (size_t pos = reference_token.find_first_of("~");
9315  pos != std::string::npos;
9316  pos = reference_token.find_first_of("~", pos + 1))
9317  {
9318  assert(reference_token[pos] == '~');
9319 
9320  // ~ must be followed by 0 or 1
9321  if (pos == reference_token.size() - 1 or
9322  (reference_token[pos + 1] != '0' and
9323  reference_token[pos + 1] != '1'))
9324  {
9325  throw std::domain_error("escape error: '~' must be followed with '0' or '1'");
9326  }
9327  }
9328 
9329  // finally, store the reference token
9330  unescape(reference_token);
9331  result.push_back(reference_token);
9332  }
9333 
9334  return result;
9335  }
9336 
9337  private:
9352  static void replace_substring(std::string& s,
9353  const std::string& f,
9354  const std::string& t)
9355  {
9356  assert(not f.empty());
9357 
9358  for (
9359  size_t pos = s.find(f); // find first occurrence of f
9360  pos != std::string::npos; // make sure f was found
9361  s.replace(pos, f.size(), t), // replace with t
9362  pos = s.find(f, pos + t.size()) // find next occurrence of f
9363  );
9364  }
9365 
9367  static std::string escape(std::string s)
9368  {
9369  // escape "~"" to "~0" and "/" to "~1"
9370  replace_substring(s, "~", "~0");
9371  replace_substring(s, "/", "~1");
9372  return s;
9373  }
9374 
9376  static void unescape(std::string& s)
9377  {
9378  // first transform any occurrence of the sequence '~1' to '/'
9379  replace_substring(s, "~1", "/");
9380  // then transform any occurrence of the sequence '~0' to '~'
9381  replace_substring(s, "~0", "~");
9382  }
9383 
9391  static void flatten(const std::string& reference_string,
9392  const basic_json& value,
9393  basic_json& result)
9394  {
9395  switch (value.m_type)
9396  {
9397  case value_t::array:
9398  {
9399  if (value.m_value.array->empty())
9400  {
9401  // flatten empty array as null
9402  result[reference_string] = nullptr;
9403  }
9404  else
9405  {
9406  // iterate array and use index as reference string
9407  for (size_t i = 0; i < value.m_value.array->size(); ++i)
9408  {
9409  flatten(reference_string + "/" + std::to_string(i),
9410  value.m_value.array->operator[](i), result);
9411  }
9412  }
9413  break;
9414  }
9415 
9416  case value_t::object:
9417  {
9418  if (value.m_value.object->empty())
9419  {
9420  // flatten empty object as null
9421  result[reference_string] = nullptr;
9422  }
9423  else
9424  {
9425  // iterate object and use keys as reference string
9426  for (const auto& element : *value.m_value.object)
9427  {
9428  flatten(reference_string + "/" + escape(element.first),
9429  element.second, result);
9430  }
9431  }
9432  break;
9433  }
9434 
9435  default:
9436  {
9437  // add primitive value with its reference string
9438  result[reference_string] = value;
9439  break;
9440  }
9441  }
9442  }
9443 
9449  static basic_json unflatten(const basic_json& value)
9450  {
9451  if (not value.is_object())
9452  {
9453  throw std::domain_error("only objects can be unflattened");
9454  }
9455 
9456  basic_json result;
9457 
9458  // iterate the JSON object values
9459  for (const auto& element : *value.m_value.object)
9460  {
9461  if (not element.second.is_primitive())
9462  {
9463  throw std::domain_error("values in object must be primitive");
9464  }
9465 
9466  // assign value to reference pointed to by JSON pointer; Note
9467  // that if the JSON pointer is "" (i.e., points to the whole
9468  // value), function get_and_create returns a reference to
9469  // result itself. An assignment will then create a primitive
9470  // value.
9471  json_pointer(element.first).get_and_create(result) = element.second;
9472  }
9473 
9474  return result;
9475  }
9476 
9477  private:
9479  std::vector<std::string> reference_tokens {};
9480  };
9481 
9483  // JSON Pointer support //
9485 
9488 
9522  reference operator[](const json_pointer& ptr)
9523  {
9524  return ptr.get_unchecked(this);
9525  }
9549  const_reference operator[](const json_pointer& ptr) const
9550  {
9551  return ptr.get_unchecked(this);
9552  }
9574  reference at(const json_pointer& ptr)
9575  {
9576  return ptr.get_checked(this);
9577  }
9599  const_reference at(const json_pointer& ptr) const
9600  {
9601  return ptr.get_checked(this);
9602  }
9626  basic_json flatten() const
9627  {
9628  basic_json result(value_t::object);
9629  json_pointer::flatten("", *this, result);
9630  return result;
9631  }
9632 
9660  basic_json unflatten() const
9661  {
9662  return json_pointer::unflatten(*this);
9663  }
9666 
9668  // JSON Patch functions //
9670 
9673 
9710  basic_json patch(const basic_json& json_patch) const
9711  {
9712  // make a working copy to apply the patch to
9713  basic_json result = *this;
9715  // the valid JSON Patch operations
9716  enum class patch_operations {add, remove, replace, move, copy, test, invalid};
9717 
9718  const auto get_op = [](const std::string op)
9719  {
9720  if (op == "add")
9721  {
9722  return patch_operations::add;
9723  }
9724  if (op == "remove")
9725  {
9726  return patch_operations::remove;
9727  }
9728  if (op == "replace")
9729  {
9730  return patch_operations::replace;
9731  }
9732  if (op == "move")
9733  {
9734  return patch_operations::move;
9735  }
9736  if (op == "copy")
9737  {
9738  return patch_operations::copy;
9739  }
9740  if (op == "test")
9741  {
9742  return patch_operations::test;
9743  }
9744 
9745  return patch_operations::invalid;
9746  };
9747 
9748  // wrapper for "add" operation; add value at ptr
9749  const auto operation_add = [&result](json_pointer & ptr, basic_json val)
9750  {
9751  // adding to the root of the target document means replacing it
9752  if (ptr.is_root())
9753  {
9754  result = val;
9755  }
9756  else
9757  {
9758  // make sure the top element of the pointer exists
9759  json_pointer top_pointer = ptr.top();
9760  if (top_pointer != ptr)
9761  {
9762  result.at(top_pointer);
9763  }
9764 
9765  // get reference to parent of JSON pointer ptr
9766  const auto last_path = ptr.pop_back();
9767  basic_json& parent = result[ptr];
9768 
9769  switch (parent.m_type)
9770  {
9771  case value_t::null:
9772  case value_t::object:
9773  {
9774  // use operator[] to add value
9775  parent[last_path] = val;
9776  break;
9777  }
9778 
9779  case value_t::array:
9780  {
9781  if (last_path == "-")
9782  {
9783  // special case: append to back
9784  parent.push_back(val);
9785  }
9786  else
9787  {
9788  const auto idx = std::stoi(last_path);
9789  if (static_cast<size_type>(idx) > parent.size())
9790  {
9791  // avoid undefined behavior
9792  throw std::out_of_range("array index " + std::to_string(idx) + " is out of range");
9793  }
9794  else
9795  {
9796  // default case: insert add offset
9797  parent.insert(parent.begin() + static_cast<difference_type>(idx), val);
9798  }
9799  }
9800  break;
9801  }
9802 
9803  default:
9804  {
9805  // if there exists a parent it cannot be primitive
9806  assert(false); // LCOV_EXCL_LINE
9807  }
9808  }
9809  }
9810  };
9811 
9812  // wrapper for "remove" operation; remove value at ptr
9813  const auto operation_remove = [&result](json_pointer & ptr)
9814  {
9815  // get reference to parent of JSON pointer ptr
9816  const auto last_path = ptr.pop_back();
9817  basic_json& parent = result.at(ptr);
9818 
9819  // remove child
9820  if (parent.is_object())
9821  {
9822  // perform range check
9823  auto it = parent.find(last_path);
9824  if (it != parent.end())
9825  {
9826  parent.erase(it);
9827  }
9828  else
9829  {
9830  throw std::out_of_range("key '" + last_path + "' not found");
9831  }
9832  }
9833  else if (parent.is_array())
9834  {
9835  // note erase performs range check
9836  parent.erase(static_cast<size_type>(std::stoi(last_path)));
9837  }
9838  };
9839 
9840  // type check
9841  if (not json_patch.is_array())
9842  {
9843  // a JSON patch must be an array of objects
9844  throw std::invalid_argument("JSON patch must be an array of objects");
9845  }
9846 
9847  // iterate and apply th eoperations
9848  for (const auto& val : json_patch)
9849  {
9850  // wrapper to get a value for an operation
9851  const auto get_value = [&val](const std::string & op,
9852  const std::string & member,
9853  bool string_type) -> basic_json&
9854  {
9855  // find value
9856  auto it = val.m_value.object->find(member);
9857 
9858  // context-sensitive error message
9859  const auto error_msg = (op == "op") ? "operation" : "operation '" + op + "'";
9860 
9861  // check if desired value is present
9862  if (it == val.m_value.object->end())
9863  {
9864  throw std::invalid_argument(error_msg + " must have member '" + member + "'");
9865  }
9866 
9867  // check if result is of type string
9868  if (string_type and not it->second.is_string())
9869  {
9870  throw std::invalid_argument(error_msg + " must have string member '" + member + "'");
9871  }
9872 
9873  // no error: return value
9874  return it->second;
9875  };
9876 
9877  // type check
9878  if (not val.is_object())
9879  {
9880  throw std::invalid_argument("JSON patch must be an array of objects");
9881  }
9882 
9883  // collect mandatory members
9884  const std::string op = get_value("op", "op", true);
9885  const std::string path = get_value(op, "path", true);
9886  json_pointer ptr(path);
9887 
9888  switch (get_op(op))
9889  {
9890  case patch_operations::add:
9891  {
9892  operation_add(ptr, get_value("add", "value", false));
9893  break;
9894  }
9895 
9896  case patch_operations::remove:
9897  {
9898  operation_remove(ptr);
9899  break;
9900  }
9901 
9902  case patch_operations::replace:
9903  {
9904  // the "path" location must exist - use at()
9905  result.at(ptr) = get_value("replace", "value", false);
9906  break;
9907  }
9908 
9909  case patch_operations::move:
9910  {
9911  const std::string from_path = get_value("move", "from", true);
9912  json_pointer from_ptr(from_path);
9913 
9914  // the "from" location must exist - use at()
9915  basic_json v = result.at(from_ptr);
9916 
9917  // The move operation is functionally identical to a
9918  // "remove" operation on the "from" location, followed
9919  // immediately by an "add" operation at the target
9920  // location with the value that was just removed.
9921  operation_remove(from_ptr);
9922  operation_add(ptr, v);
9923  break;
9924  }
9925 
9926  case patch_operations::copy:
9927  {
9928  const std::string from_path = get_value("copy", "from", true);;
9929  const json_pointer from_ptr(from_path);
9930 
9931  // the "from" location must exist - use at()
9932  result[ptr] = result.at(from_ptr);
9933  break;
9934  }
9935 
9936  case patch_operations::test:
9937  {
9938  bool success = false;
9939  try
9940  {
9941  // check if "value" matches the one at "path"
9942  // the "path" location must exist - use at()
9943  success = (result.at(ptr) == get_value("test", "value", false));
9944  }
9945  catch (std::out_of_range&)
9946  {
9947  // ignore out of range errors: success remains false
9948  }
9949 
9950  // throw an exception if test fails
9951  if (not success)
9952  {
9953  throw std::domain_error("unsuccessful: " + val.dump());
9954  }
9955 
9956  break;
9957  }
9958 
9959  case patch_operations::invalid:
9960  {
9961  // op must be "add", "remove", "replace", "move", "copy", or
9962  // "test"
9963  throw std::invalid_argument("operation value '" + op + "' is invalid");
9964  }
9965  }
9966  }
9967 
9968  return result;
9969  }
9970 
10003  static basic_json diff(const basic_json& source,
10004  const basic_json& target,
10005  const std::string& path = "")
10006  {
10007  // the patch
10008  basic_json result(value_t::array);
10009 
10010  // if the values are the same, return empty patch
10011  if (source == target)
10012  {
10013  return result;
10014  }
10015 
10016  if (source.type() != target.type())
10017  {
10018  // different types: replace value
10019  result.push_back(
10020  {
10021  {"op", "replace"},
10022  {"path", path},
10023  {"value", target}
10024  });
10025  }
10026  else
10027  {
10028  switch (source.type())
10029  {
10030  case value_t::array:
10031  {
10032  // first pass: traverse common elements
10033  size_t i = 0;
10034  while (i < source.size() and i < target.size())
10035  {
10036  // recursive call to compare array values at index i
10037  auto temp_diff = diff(source[i], target[i], path + "/" + std::to_string(i));
10038  result.insert(result.end(), temp_diff.begin(), temp_diff.end());
10039  ++i;
10040  }
10041 
10042  // i now reached the end of at least one array
10043  // in a second pass, traverse the remaining elements
10044 
10045  // remove my remaining elements
10046  const auto end_index = static_cast<difference_type>(result.size());
10047  while (i < source.size())
10048  {
10049  // add operations in reverse order to avoid invalid
10050  // indices
10051  result.insert(result.begin() + end_index, object(
10052  {
10053  {"op", "remove"},
10054  {"path", path + "/" + std::to_string(i)}
10055  }));
10056  ++i;
10057  }
10058 
10059  // add other remaining elements
10060  while (i < target.size())
10061  {
10062  result.push_back(
10063  {
10064  {"op", "add"},
10065  {"path", path + "/" + std::to_string(i)},
10066  {"value", target[i]}
10067  });
10068  ++i;
10069  }
10070 
10071  break;
10072  }
10073 
10074  case value_t::object:
10075  {
10076  // first pass: traverse this object's elements
10077  for (auto it = source.begin(); it != source.end(); ++it)
10078  {
10079  // escape the key name to be used in a JSON patch
10080  const auto key = json_pointer::escape(it.key());
10081 
10082  if (target.find(it.key()) != target.end())
10083  {
10084  // recursive call to compare object values at key it
10085  auto temp_diff = diff(it.value(), target[it.key()], path + "/" + key);
10086  result.insert(result.end(), temp_diff.begin(), temp_diff.end());
10087  }
10088  else
10089  {
10090  // found a key that is not in o -> remove it
10091  result.push_back(object(
10092  {
10093  {"op", "remove"},
10094  {"path", path + "/" + key}
10095  }));
10096  }
10097  }
10098 
10099  // second pass: traverse other object's elements
10100  for (auto it = target.begin(); it != target.end(); ++it)
10101  {
10102  if (source.find(it.key()) == source.end())
10103  {
10104  // found a key that is not in this -> add it
10105  const auto key = json_pointer::escape(it.key());
10106  result.push_back(
10107  {
10108  {"op", "add"},
10109  {"path", path + "/" + key},
10110  {"value", it.value()}
10111  });
10112  }
10113  }
10114 
10115  break;
10116  }
10117 
10118  default:
10119  {
10120  // both primitive type: replace value
10121  result.push_back(
10122  {
10123  {"op", "replace"},
10124  {"path", path},
10125  {"value", target}
10126  });
10127  break;
10128  }
10129  }
10130  }
10131 
10132  return result;
10133  }
10134 
10136 };
10137 
10138 
10140 // presets //
10142 
10151 using json = basic_json<>;
10152 }
10153 
10154 
10156 // nonmember support //
10158 
10159 // specialization of std::swap, and std::hash
10160 namespace std
10161 {
10167 template<>
10168 inline void swap(nlohmann::json& j1,
10169  nlohmann::json& j2) noexcept(
10170  is_nothrow_move_constructible<nlohmann::json>::value and
10171  is_nothrow_move_assignable<nlohmann::json>::value
10172  )
10173 {
10174  j1.swap(j2);
10175 }
10176 
10178 template<>
10179 struct hash<nlohmann::json>
10180 {
10186  std::size_t operator()(const nlohmann::json& j) const
10187  {
10188  // a naive hashing via the string representation
10189  const auto& h = hash<nlohmann::json::string_t>();
10190  return h(j.dump());
10191  }
10192 };
10193 }
10194 
10207 inline nlohmann::json operator "" _json(const char* s, std::size_t)
10208 {
10209  return nlohmann::json::parse(s);
10210 }
10211 
10224 inline nlohmann::json::json_pointer operator "" _json_pointer(const char* s, std::size_t)
10225 {
10226  return nlohmann::json::json_pointer(s);
10227 }
10228 
10229 // restore GCC/clang diagnostic settings
10230 #if defined(__clang__) || defined(__GNUC__) || defined(__GNUG__)
10231  #pragma GCC diagnostic pop
10232 #endif
10233 
10234 #endif
const_iterator(pointer object) noexcept
constructor for a given JSON instance
Definition: json.hpp:6741
size_type max_size() const noexcept
returns the maximum possible number of elements
Definition: json.hpp:4760
friend bool operator<=(const_reference lhs, const_reference rhs) noexcept
comparison: less than or equal
Definition: json.hpp:5737
constexpr value_t type() const noexcept
return the type of the JSON value (explicit)
Definition: json.hpp:2243
constexpr bool is_array() const noexcept
return whether value is an array
Definition: json.hpp:2503
const_reference at(const typename object_t::key_type &key) const
access specified object element with bounds checking
Definition: json.hpp:3288
basic_json(const value_t value_type)
create an empty value with a given type
Definition: json.hpp:1067
basic_json(const array_t &val)
create an array (explicit)
Definition: json.hpp:1179
reference value() const
return the value of an iterator
Definition: json.hpp:7563
const_iterator end() const noexcept
returns a const iterator to one past the last element
Definition: json.hpp:4382
constexpr bool is_primitive() const noexcept
return whether type is primitive
Definition: json.hpp:2273
constexpr bool is_null() const noexcept
return whether value is null
Definition: json.hpp:2322
ValueType get() const
get a value (explicit)
Definition: json.hpp:2901
const_reverse_iterator rend() const noexcept
returns a const reverse iterator to one before the first
Definition: json.hpp:4487
constexpr bool is_structured() const noexcept
return whether type is structured
Definition: json.hpp:2300
json_reverse_iterator & operator--()
pre-decrement (–it)
Definition: json.hpp:7514
void clear() noexcept
clears the contents
Definition: json.hpp:4819
const_reference operator[](size_type idx) const
access specified array element
Definition: json.hpp:3382
static basic_json parse(const CharPT s, const parser_callback_t cb=nullptr)
deserialize from string literal
Definition: json.hpp:5935
json_reverse_iterator operator--(int)
post-decrement (it–)
Definition: json.hpp:7508
reference operator[](T *(&key)[n])
access specified object element
Definition: json.hpp:3515
friend std::istream & operator>>(std::istream &i, basic_json &j)
deserialize from stream
Definition: json.hpp:6137
iterator & operator+=(difference_type i)
add to iterator
Definition: json.hpp:7410
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:1760
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:4261
static basic_json parse(IteratorType first, IteratorType last, const parser_callback_t cb=nullptr)
deserialize from an iterator range with contiguous storage
Definition: json.hpp:6025
constexpr bool is_number_unsigned() const noexcept
return whether value is an unsigned integer number
Definition: json.hpp:2431
const_iterator operator-(difference_type i)
subtract from iterator
Definition: json.hpp:7216
BooleanType boolean_t
a type for a boolean
Definition: json.hpp:514
reference operator+=(const typename object_t::value_type &val)
add an object to an object
Definition: json.hpp:5002
basic_json(const typename string_t::value_type *val)
create a string (explicit)
Definition: json.hpp:1275
object_t::key_type key() const
return the key of an object iterator
Definition: json.hpp:7293
iterator find(typename object_t::key_type key)
find an element in a JSON object
Definition: json.hpp:4215
friend bool operator!=(const_reference lhs, const_reference rhs) noexcept
comparison: not equal
Definition: json.hpp:5581
basic_json(const string_t &val)
create a string (explicit)
Definition: json.hpp:1249
reference operator*() const
return a reference to the value pointed to by the iterator
Definition: json.hpp:7368
void push_back(const basic_json &val)
add an object to an array
Definition: json.hpp:4928
void erase(const size_type idx)
remove element from a JSON array given an index
Definition: json.hpp:4169
ArrayType< basic_json, AllocatorType< basic_json >> array_t
a type for an array
Definition: json.hpp:441
reference front()
access the first element
Definition: json.hpp:3828
void swap(object_t &other)
exchanges the values
Definition: json.hpp:5345
const_iterator & operator+=(difference_type i)
add to iterator
Definition: json.hpp:7165
a class to store JSON values
Definition: json.hpp:235
basic_json(const int val) noexcept
create an integer number from an enum type (explicit)
Definition: json.hpp:1389
static basic_json parse(T(&array)[N], const parser_callback_t cb=nullptr)
deserialize from an array
Definition: json.hpp:5897
constexpr bool is_object() const noexcept
return whether value is an object
Definition: json.hpp:2481
friend bool operator==(std::nullptr_t, const_reference v) noexcept
comparison: equal
Definition: json.hpp:5560
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:3725
NumberIntegerType number_integer_t
a type for a number (integer)
Definition: json.hpp:586
iterator insert(const_iterator pos, size_type cnt, const basic_json &val)
inserts elements
Definition: json.hpp:5133
const_iterator operator+(difference_type i)
add to iterator
Definition: json.hpp:7205
a mutable random access iterator for the basic_json class
Definition: json.hpp:7335
const_iterator operator++(int)
post-increment (it++)
Definition: json.hpp:6977
constexpr bool is_number_integer() const noexcept
return whether value is an integer number
Definition: json.hpp:2403
ObjectType< StringType, basic_json, std::less< StringType >, AllocatorType< std::pair< const StringType, basic_json >>> object_t
a type for an object
Definition: json.hpp:395
STL namespace.
NumberUnsignedType number_unsigned_t
a type for a number (unsigned)
Definition: json.hpp:657
json_reverse_iterator operator-(difference_type i) const
subtract from iterator
Definition: json.hpp:7536
typename std::allocator_traits< allocator_type >::const_pointer const_pointer
the type of an element const pointer
Definition: json.hpp:276
static basic_json parse(std::istream &&i, const parser_callback_t cb=nullptr)
deserialize from stream
Definition: json.hpp:5974
pointer operator->() const
dereference the iterator
Definition: json.hpp:7374
bool operator>=(const const_iterator &other) const
comparison: greater than or equal
Definition: json.hpp:7156
basic_json(const number_integer_t val) noexcept
create an integer number (explicit)
Definition: json.hpp:1358
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:1720
static iteration_proxy< const_iterator > iterator_wrapper(const_reference cont)
wrapper to access iterator member functions in range-based for
Definition: json.hpp:4574
const_reference front() const
access the first element
Definition: json.hpp:3836
typename basic_json::value_type value_type
the type of the values when the iterator is dereferenced
Definition: json.hpp:6722
json_reverse_iterator(const typename base_iterator::iterator_type &it) noexcept
create reverse iterator from iterator
Definition: json.hpp:7485
PointerType get_ptr() noexcept
get a pointer value (implicit)
Definition: json.hpp:2981
const_iterator cbegin() const noexcept
returns a const iterator to the first element
Definition: json.hpp:4341
reference back()
access the last element
Definition: json.hpp:3871
const value_type & const_reference
the type of an element const reference
Definition: json.hpp:263
typename basic_json::const_pointer pointer
defines a pointer to the type iterated over (value_type)
Definition: json.hpp:6726
IteratorType erase(IteratorType first, IteratorType last)
remove elements given an iterator range
Definition: json.hpp:4044
void push_back(const typename object_t::value_type &val)
add an object to an object
Definition: json.hpp:4978
bool empty() const noexcept
checks whether the container is empty
Definition: json.hpp:4626
void push_back(std::initializer_list< basic_json > init)
add an object to an object
Definition: json.hpp:5033
json_pointer(const std::string &s="")
create JSON pointer
Definition: json.hpp:8922
iterator insert(const_iterator pos, const_iterator first, const_iterator last)
inserts elements
Definition: json.hpp:5185
constexpr const PointerType get_ptr() const noexcept
get a pointer value (implicit)
Definition: json.hpp:3009
constexpr bool is_number_float() const noexcept
return whether value is a floating-point number
Definition: json.hpp:2459
basic_json(InputIT first, InputIT last)
construct a JSON container given an iterator range
Definition: json.hpp:1831
basic_json(std::nullptr_t=nullptr) noexcept
create a null object
Definition: json.hpp:1091
IteratorType erase(IteratorType pos)
remove element given an iterator
Definition: json.hpp:3937
static allocator_type get_allocator()
returns the allocator associated with the container
Definition: json.hpp:293
json_reverse_iterator operator+(difference_type i) const
add to iterator
Definition: json.hpp:7528
string_t dump(const int indent=-1) const
serialization
Definition: json.hpp:2200
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:2095
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:5280
std::size_t size_type
a type to represent container sizes
Definition: json.hpp:268
JSON_DEPRECATED basic_json(std::istream &i, const parser_callback_t cb=nullptr)
construct a JSON value given an input stream
Definition: json.hpp:1949
const_iterator(const iterator &other) noexcept
copy constructor given a non-const iterator
Definition: json.hpp:6773
basic_json(const CompatibleArrayType &val)
create an array (implicit)
Definition: json.hpp:1219
basic_json(size_type cnt, const basic_json &val)
construct an array with count copies of given value
Definition: json.hpp:1784
std::reverse_iterator< Base > base_iterator
shortcut to the reverse iterator adaptor
Definition: json.hpp:7480
object_t::key_type key() const
return the key of an object iterator
Definition: json.hpp:7556
iterator insert(const_iterator pos, std::initializer_list< basic_json > ilist)
inserts elements
Definition: json.hpp:5243
typename std::allocator_traits< allocator_type >::pointer pointer
the type of an element pointer
Definition: json.hpp:274
iterator insert(const_iterator pos, const basic_json &val)
inserts element
Definition: json.hpp:5078
friend bool operator>=(const_reference lhs, const_reference rhs) noexcept
comparison: greater than or equal
Definition: json.hpp:5781
friend bool operator<(const_reference lhs, const_reference rhs) noexcept
comparison: less than
Definition: json.hpp:5642
iterator & operator++()
pre-increment (++it)
Definition: json.hpp:7388
iterator operator++(int)
post-increment (it++)
Definition: json.hpp:7380
const_reverse_iterator rbegin() const noexcept
returns a const reverse iterator to the last element
Definition: json.hpp:4450
basic_json(basic_json &&other) noexcept
move constructor
Definition: json.hpp:2058
const_iterator operator--(int)
post-decrement (it–)
Definition: json.hpp:7020
reference at(const typename object_t::key_type &key)
access specified object element with bounds checking
Definition: json.hpp:3241
object (unordered set of name/value pairs)
~basic_json()
destructor
Definition: json.hpp:2128
iterator operator--(int)
post-decrement (it–)
Definition: json.hpp:7395
iterator operator-(difference_type i)
subtract from iterator
Definition: json.hpp:7432
const_iterator & operator--()
pre-decrement (–it)
Definition: json.hpp:7031
basic_json value_type
the type of elements in a basic_json container
Definition: json.hpp:258
std::function< bool(int depth, parse_event_t event, basic_json &parsed)> parser_callback_t
per-element parser callback type
Definition: json.hpp:1016
AllocatorType< basic_json > allocator_type
the allocator type
Definition: json.hpp:271
StringType string_t
a type for a string
Definition: json.hpp:488
reference operator+=(const basic_json &val)
add an object to an array
Definition: json.hpp:4952
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:6815
static basic_json parse(const ContiguousContainer &c, const parser_callback_t cb=nullptr)
deserialize from a container with contiguous storage
Definition: json.hpp:6097
reference operator+=(std::initializer_list< basic_json > init)
add an object to an object
Definition: json.hpp:5050
value_type & reference
the type of an element reference
Definition: json.hpp:261
pointer operator->() const
dereference the iterator
Definition: json.hpp:6941
ReferenceType get_ref() const
get a reference value (implicit)
Definition: json.hpp:3071
reference value() const
return the value of an iterator
Definition: json.hpp:7452
friend std::ostream & operator>>(const basic_json &j, std::ostream &o)
serialize to stream
Definition: json.hpp:5854
size_type size() const noexcept
returns the number of elements
Definition: json.hpp:4694
iterator(const iterator &other) noexcept
copy constructor
Definition: json.hpp:7351
namespace for Niels Lohmann
Definition: json.hpp:92
typename basic_json::difference_type difference_type
a type to represent differences between iterators
Definition: json.hpp:6724
constexpr bool is_string() const noexcept
return whether value is a string
Definition: json.hpp:2525
void swap(string_t &other)
exchanges the values
Definition: json.hpp:5378
reference operator[](difference_type n) const
access to successor
Definition: json.hpp:7550
basic_json(const CompatibleNumberIntegerType val) noexcept
create an integer number (implicit)
Definition: json.hpp:1426
const_reference at(size_type idx) const
access specified array element with bounds checking
Definition: json.hpp:3194
reference value() const
return the value of an iterator
Definition: json.hpp:7311
ValueType value(const typename object_t::key_type &key, ValueType default_value) const
access specified object element with default value
Definition: json.hpp:3699
const_reference operator[](T *key) const
read-only access specified object element
Definition: json.hpp:3635
NumberFloatType number_float_t
a type for a number (floating-point)
Definition: json.hpp:725
value_t
the JSON type enumeration
Definition: json.hpp:756
reverse_iterator rbegin() noexcept
returns an iterator to the reverse-beginning
Definition: json.hpp:4442
std::ptrdiff_t difference_type
a type to represent differences between iterators
Definition: json.hpp:266
difference_type operator-(const const_iterator &other) const
return difference
Definition: json.hpp:7227
void swap(array_t &other)
exchanges the values
Definition: json.hpp:5312
reference operator[](difference_type n) const
access to successor
Definition: json.hpp:7446
typename Base::reference reference
the reference type for the pointed-to element
Definition: json.hpp:7482
void push_back(basic_json &&val)
add an object to an array
Definition: json.hpp:4892
array (ordered collection of values)
json_reverse_iterator & operator++()
pre-increment (++it)
Definition: json.hpp:7501
difference_type operator-(const iterator &other) const
return difference
Definition: json.hpp:7440
friend bool operator==(const_reference lhs, const_reference rhs) noexcept
comparison: equal
Definition: json.hpp:5458
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:7356
static basic_json parse(std::istream &i, const parser_callback_t cb=nullptr)
deserialize from stream
Definition: json.hpp:5965
ValueType value(const json_pointer &ptr, ValueType default_value) const
access specified object element via JSON Pointer with default value
Definition: json.hpp:3773
const_reference operator[](const typename object_t::key_type &key) const
read-only access specified object element
Definition: json.hpp:3473
bool operator!=(const const_iterator &other) const
comparison: not equal
Definition: json.hpp:7096
basic_json(const CompatibleNumberUnsignedType val) noexcept
create an unsigned number (implicit)
Definition: json.hpp:1484
constexpr bool is_boolean() const noexcept
return whether value is a boolean
Definition: json.hpp:2344
bool operator==(const const_iterator &other) const
comparison: equal
Definition: json.hpp:7063
bool operator<=(const const_iterator &other) const
comparison: less than or equal
Definition: json.hpp:7138
const_reverse_iterator crbegin() const noexcept
returns a const reverse iterator to the last element
Definition: json.hpp:4516
string_t value(const json_pointer &ptr, const char *default_value) const
overload for a default value of type const char*
Definition: json.hpp:3798
friend class basic_json
allow basic_json to access private members
Definition: json.hpp:6718
reference operator[](difference_type n) const
access to successor
Definition: json.hpp:7254
friend bool operator<(const value_t lhs, const value_t rhs) noexcept
comparison operator for JSON types
Definition: json.hpp:5411
basic_json(const number_float_t val) noexcept
create a floating-point number (explicit)
Definition: json.hpp:1515
friend bool operator!=(const_reference v, std::nullptr_t) noexcept
comparison: not equal
Definition: json.hpp:5604
iterator operator+(difference_type i)
add to iterator
Definition: json.hpp:7424
basic_json(const CompatibleNumberFloatType val) noexcept
create an floating-point number (implicit)
Definition: json.hpp:1562
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:1637
iterator(pointer object) noexcept
constructor for a given JSON instance
Definition: json.hpp:7346
friend bool operator!=(std::nullptr_t, const_reference v) noexcept
comparison: not equal
Definition: json.hpp:5613
difference_type operator-(const json_reverse_iterator &other) const
return difference
Definition: json.hpp:7544
const_reference back() const
access the last element
Definition: json.hpp:3881
const_iterator & operator++()
pre-increment (++it)
Definition: json.hpp:6988
constexpr bool is_number() const noexcept
return whether value is a number
Definition: json.hpp:2374
const_iterator find(typename object_t::key_type key) const
find an element in a JSON object
Definition: json.hpp:4231
const_iterator begin() const noexcept
returns a const iterator to the first element
Definition: json.hpp:4311
bool operator>(const const_iterator &other) const
comparison: greater than
Definition: json.hpp:7147
std::bidirectional_iterator_tag iterator_category
the category of the iterator
Definition: json.hpp:6730
basic_json(boolean_t val) noexcept
create a boolean (explicit)
Definition: json.hpp:1326
iterator end() noexcept
returns an iterator to one past the last element
Definition: json.hpp:4372
reverse_iterator rend() noexcept
returns an iterator to the reverse-end
Definition: json.hpp:4479
iterator begin() noexcept
returns an iterator to the first element
Definition: json.hpp:4301
const_iterator cend() const noexcept
returns a const iterator to one past the last element
Definition: json.hpp:4412
basic_json(const CompatibleObjectType &val)
create an object (implicit)
Definition: json.hpp:1151
friend bool operator>(const_reference lhs, const_reference rhs) noexcept
comparison: greater than
Definition: json.hpp:5759
size_type erase(const typename object_t::key_type &key)
remove element from a JSON object given a key
Definition: json.hpp:4132
reference operator[](const typename object_t::key_type &key)
access specified object element
Definition: json.hpp:3422
reference operator+=(basic_json &&val)
add an object to an array
Definition: json.hpp:4918
a const random access iterator for the basic_json class
Definition: json.hpp:6715
a template for a reverse iterator class
Definition: json.hpp:245
typename basic_json::const_reference reference
defines a reference to the type iterated over (value_type)
Definition: json.hpp:6728
json_reverse_iterator operator++(int)
post-increment (it++)
Definition: json.hpp:7495
friend bool operator==(const_reference v, std::nullptr_t) noexcept
comparison: equal
Definition: json.hpp:5551
reference operator[](size_type idx)
access specified array element
Definition: json.hpp:3334
json_reverse_iterator & operator+=(difference_type i)
add to iterator
Definition: json.hpp:7521
reference at(size_type idx)
access specified array element with bounds checking
Definition: json.hpp:3151
static iteration_proxy< iterator > iterator_wrapper(reference cont)
wrapper to access iterator member functions in range-based for
Definition: json.hpp:4566
constexpr bool is_discarded() const noexcept
return whether value is discarded
Definition: json.hpp:2552
const_reverse_iterator crend() const noexcept
returns a const reverse iterator to one before the first
Definition: json.hpp:4545
iterator & operator-=(difference_type i)
subtract from iterator
Definition: json.hpp:7417
basic_json(const object_t &val)
create an object (explicit)
Definition: json.hpp:1116
basic_json(const number_unsigned_t val) noexcept
create an unsigned integer number (explicit)
Definition: json.hpp:1453
friend std::istream & operator<<(basic_json &j, std::istream &i)
deserialize from stream
Definition: json.hpp:6127
json_reverse_iterator(const base_iterator &it) noexcept
create reverse iterator from base class
Definition: json.hpp:7490
const_reference operator[](T *(&key)[n]) const
read-only access specified object element
Definition: json.hpp:3550
friend std::ostream & operator<<(std::ostream &o, const basic_json &j)
serialize to stream
Definition: json.hpp:5822
const_iterator(const const_iterator &other) noexcept
copy constructor
Definition: json.hpp:6806
iterator & operator--()
pre-decrement (–it)
Definition: json.hpp:7403
reference operator*() const
return a reference to the value pointed to by the iterator
Definition: json.hpp:6900
iterator insert(const_iterator pos, basic_json &&val)
inserts element
Definition: json.hpp:5104
ReferenceType get_ref()
get a reference value (implicit)
Definition: json.hpp:3058
const_iterator & operator-=(difference_type i)
subtract from iterator
Definition: json.hpp:7196
basic_json(const CompatibleStringType &val)
create a string (implicit)
Definition: json.hpp:1306
basic_json(const basic_json &other)
copy constructor
Definition: json.hpp:1981
bool operator<(const const_iterator &other) const
comparison: smaller
Definition: json.hpp:7105
reference operator[](T *key)
access specified object element
Definition: json.hpp:3583
parse_event_t
JSON callback events.
Definition: json.hpp:946