JSON for Modern C++  1.0.0
json.hpp
1 
38 #ifndef NLOHMANN_JSON_HPP
39 #define NLOHMANN_JSON_HPP
40 
41 #include <algorithm>
42 #include <array>
43 #include <ciso646>
44 #include <cmath>
45 #include <cstdio>
46 #include <functional>
47 #include <initializer_list>
48 #include <iomanip>
49 #include <iostream>
50 #include <iterator>
51 #include <limits>
52 #include <map>
53 #include <memory>
54 #include <sstream>
55 #include <string>
56 #include <type_traits>
57 #include <utility>
58 #include <vector>
59 
60 // enable ssize_t on MinGW
61 #ifdef __GNUC__
62  #ifdef __MINGW32__
63  #include <sys/types.h>
64  #endif
65 #endif
66 
67 // enable ssize_t for MSVC
68 #ifdef _MSC_VER
69  #include <basetsd.h>
70  using ssize_t = SSIZE_T;
71 #endif
72 
78 namespace nlohmann
79 {
80 
81 
86 namespace
87 {
92 template<typename T>
93 struct has_mapped_type
94 {
95  private:
96  template<typename C> static char test(typename C::mapped_type*);
97  template<typename C> static int test(...);
98  public:
99  enum { value = sizeof(test<T>(0)) == sizeof(char) };
100 };
101 
103 template<typename T>
104 static bool approx(const T a, const T b)
105 {
106  return not (a > b or a < b);
107 }
108 }
109 
178 template <
179  template<typename U, typename V, typename... Args> class ObjectType = std::map,
180  template<typename U, typename... Args> class ArrayType = std::vector,
181  class StringType = std::string,
182  class BooleanType = bool,
183  class NumberIntegerType = int64_t,
184  class NumberFloatType = double,
185  template<typename U> class AllocatorType = std::allocator
186  >
188 {
189  private:
191  using basic_json_t = basic_json<ObjectType,
192  ArrayType,
193  StringType,
194  BooleanType,
195  NumberIntegerType,
196  NumberFloatType,
197  AllocatorType>;
198 
199  public:
200 
202  // container types //
204 
207 
210 
213 
215  using const_reference = const value_type&;
216 
218  using difference_type = std::ptrdiff_t;
219 
221  using size_type = std::size_t;
222 
224  using allocator_type = AllocatorType<basic_json>;
225 
227  using pointer = typename std::allocator_traits<allocator_type>::pointer;
229  using const_pointer = typename std::allocator_traits<allocator_type>::const_pointer;
230 
231  // forward declaration
232  template<typename Base> class json_reverse_iterator;
233 
235  class iterator;
237  class const_iterator;
242 
244 
245 
250  {
251  return allocator_type();
252  }
253 
254 
256  // JSON value data types //
258 
261 
336  using object_t = ObjectType<StringType,
337  basic_json,
338  std::less<StringType>,
339  AllocatorType<std::pair<const StringType,
340  basic_json>>>;
341 
386  using array_t = ArrayType<basic_json, AllocatorType<basic_json>>;
387 
433  using string_t = StringType;
434 
459  using boolean_t = BooleanType;
460 
527  using number_integer_t = NumberIntegerType;
528 
592  using number_float_t = NumberFloatType;
593 
595 
596 
598  // JSON type enumeration //
600 
611  enum class value_t : uint8_t
612  {
613  null,
614  object,
615  array,
616  string,
617  boolean,
619  number_float,
620  discarded
621  };
622 
623 
624  private:
626  template<typename T, typename... Args>
627  static T* create(Args&& ... args)
628  {
629  AllocatorType<T> alloc;
630  auto deleter = [&](T * object)
631  {
632  alloc.deallocate(object, 1);
633  };
634  std::unique_ptr<T, decltype(deleter)> object(alloc.allocate(1), deleter);
635  alloc.construct(object.get(), std::forward<Args>(args)...);
636  return object.release();
637  }
638 
640  // JSON value storage //
642 
650  union json_value
651  {
653  object_t* object;
655  array_t* array;
657  string_t* string;
659  boolean_t boolean;
661  number_integer_t number_integer;
663  number_float_t number_float;
664 
666  json_value() noexcept = default;
668  json_value(boolean_t v) noexcept : boolean(v) {}
670  json_value(number_integer_t v) noexcept : number_integer(v) {}
672  json_value(number_float_t v) noexcept : number_float(v) {}
674  json_value(value_t t)
675  {
676  switch (t)
677  {
678  case value_t::object:
679  {
680  object = create<object_t>();
681  break;
682  }
683 
684  case value_t::array:
685  {
686  array = create<array_t>();
687  break;
688  }
689 
690  case value_t::string:
691  {
692  string = create<string_t>("");
693  break;
694  }
695 
696  case value_t::boolean:
697  {
698  boolean = boolean_t(false);
699  break;
700  }
701 
703  {
704  number_integer = number_integer_t(0);
705  break;
706  }
707 
709  {
710  number_float = number_float_t(0.0);
711  break;
712  }
713 
714  default:
715  {
716  break;
717  }
718  }
719  }
720 
722  json_value(const string_t& value)
723  {
724  string = create<string_t>(value);
725  }
726 
728  json_value(const object_t& value)
729  {
730  object = create<object_t>(value);
731  }
732 
734  json_value(const array_t& value)
735  {
736  array = create<array_t>(value);
737  }
738  };
739 
740 
741  public:
743  // JSON parser callback //
745 
754  enum class parse_event_t : uint8_t
755  {
757  object_start,
759  object_end,
761  array_start,
763  array_end,
765  key,
767  value
768  };
769 
819  using parser_callback_t = std::function<bool(int depth, parse_event_t event, basic_json& parsed)>;
820 
821 
823  // constructors //
825 
828 
867  : m_type(value_type), m_value(value_type)
868  {}
869 
889  basic_json() noexcept = default;
890 
910  basic_json(std::nullptr_t) noexcept
911  : basic_json(value_t::null)
912  {}
913 
933  basic_json(const object_t& val)
934  : m_type(value_t::object), m_value(val)
935  {}
936 
960  template <class CompatibleObjectType, typename
961  std::enable_if<
962  std::is_constructible<typename object_t::key_type, typename CompatibleObjectType::key_type>::value and
963  std::is_constructible<basic_json, typename CompatibleObjectType::mapped_type>::value, int>::type
964  = 0>
965  basic_json(const CompatibleObjectType& val)
966  : m_type(value_t::object)
967  {
968  using std::begin;
969  using std::end;
970  m_value.object = create<object_t>(begin(val), end(val));
971  }
972 
992  basic_json(const array_t& val)
993  : m_type(value_t::array), m_value(val)
994  {}
995 
1019  template <class CompatibleArrayType, typename
1020  std::enable_if<
1021  not std::is_same<CompatibleArrayType, typename basic_json_t::iterator>::value and
1022  not std::is_same<CompatibleArrayType, typename basic_json_t::const_iterator>::value and
1023  not std::is_same<CompatibleArrayType, typename basic_json_t::reverse_iterator>::value and
1024  not std::is_same<CompatibleArrayType, typename basic_json_t::const_reverse_iterator>::value and
1025  not std::is_same<CompatibleArrayType, typename array_t::iterator>::value and
1026  not std::is_same<CompatibleArrayType, typename array_t::const_iterator>::value and
1027  std::is_constructible<basic_json, typename CompatibleArrayType::value_type>::value, int>::type
1028  = 0>
1029  basic_json(const CompatibleArrayType& val)
1030  : m_type(value_t::array)
1031  {
1032  using std::begin;
1033  using std::end;
1034  m_value.array = create<array_t>(begin(val), end(val));
1035  }
1036 
1058  basic_json(const string_t& val)
1059  : m_type(value_t::string), m_value(val)
1060  {}
1061 
1082  basic_json(const typename string_t::value_type* val)
1083  : basic_json(string_t(val))
1084  {}
1085 
1109  template <class CompatibleStringType, typename
1110  std::enable_if<
1111  std::is_constructible<string_t, CompatibleStringType>::value, int>::type
1112  = 0>
1113  basic_json(const CompatibleStringType& val)
1114  : basic_json(string_t(val))
1115  {}
1116 
1132  : m_type(value_t::boolean), m_value(val)
1133  {}
1134 
1160  template<typename T,
1161  typename std::enable_if<
1162  not (std::is_same<T, int>::value)
1163  and std::is_same<T, number_integer_t>::value
1164  , int>::type = 0>
1165  basic_json(const number_integer_t val)
1166  : m_type(value_t::number_integer), m_value(val)
1167  {}
1168 
1194  basic_json(const int val)
1195  : m_type(value_t::number_integer),
1196  m_value(static_cast<number_integer_t>(val))
1197  {}
1198 
1224  template<typename CompatibleNumberIntegerType, typename
1225  std::enable_if<
1226  std::is_constructible<number_integer_t, CompatibleNumberIntegerType>::value and
1227  std::numeric_limits<CompatibleNumberIntegerType>::is_integer, CompatibleNumberIntegerType>::type
1228  = 0>
1229  basic_json(const CompatibleNumberIntegerType val) noexcept
1230  : m_type(value_t::number_integer),
1231  m_value(static_cast<number_integer_t>(val))
1232  {}
1233 
1259  : m_type(value_t::number_float), m_value(val)
1260  {
1261  // replace infinity and NAN by null
1262  if (not std::isfinite(val))
1263  {
1264  m_type = value_t::null;
1265  m_value = json_value();
1266  }
1267  }
1268 
1299  template<typename CompatibleNumberFloatType, typename = typename
1300  std::enable_if<
1301  std::is_constructible<number_float_t, CompatibleNumberFloatType>::value and
1302  std::is_floating_point<CompatibleNumberFloatType>::value>::type
1303  >
1304  basic_json(const CompatibleNumberFloatType val) noexcept
1305  : basic_json(number_float_t(val))
1306  {}
1307 
1377  basic_json(std::initializer_list<basic_json> init,
1378  bool type_deduction = true,
1379  value_t manual_type = value_t::array)
1380  {
1381  // the initializer list could describe an object
1382  bool is_an_object = true;
1383 
1384  // check if each element is an array with two elements whose first
1385  // element is a string
1386  for (const auto& element : init)
1387  {
1388  if (not element.is_array() or element.size() != 2
1389  or not element[0].is_string())
1390  {
1391  // we found an element that makes it impossible to use the
1392  // initializer list as object
1393  is_an_object = false;
1394  break;
1395  }
1396  }
1397 
1398  // adjust type if type deduction is not wanted
1399  if (not type_deduction)
1400  {
1401  // if array is wanted, do not create an object though possible
1402  if (manual_type == value_t::array)
1403  {
1404  is_an_object = false;
1405  }
1406 
1407  // if object is wanted but impossible, throw an exception
1408  if (manual_type == value_t::object and not is_an_object)
1409  {
1410  throw std::domain_error("cannot create object from initializer list");
1411  }
1412  }
1413 
1414  if (is_an_object)
1415  {
1416  // the initializer list is a list of pairs -> create object
1417  m_type = value_t::object;
1418  m_value = value_t::object;
1419 
1420  for (auto& element : init)
1421  {
1422  m_value.object->emplace(std::move(*(element[0].m_value.string)), std::move(element[1]));
1423  }
1424  }
1425  else
1426  {
1427  // the initializer list describes an array -> create array
1428  m_type = value_t::array;
1429  m_value.array = create<array_t>(std::move(init));
1430  }
1431  }
1432 
1467  static basic_json array(std::initializer_list<basic_json> init =
1468  std::initializer_list<basic_json>())
1469  {
1470  return basic_json(init, false, value_t::array);
1471  }
1472 
1507  static basic_json object(std::initializer_list<basic_json> init =
1508  std::initializer_list<basic_json>())
1509  {
1510  return basic_json(init, false, value_t::object);
1511  }
1512 
1531  basic_json(size_type cnt, const basic_json& val)
1532  : m_type(value_t::array)
1533  {
1534  m_value.array = create<array_t>(cnt, val);
1535  }
1536 
1571  template <class InputIT, typename
1572  std::enable_if<
1573  std::is_same<InputIT, typename basic_json_t::iterator>::value or
1574  std::is_same<InputIT, typename basic_json_t::const_iterator>::value
1575  , int>::type
1576  = 0>
1577  basic_json(InputIT first, InputIT last) : m_type(first.m_object->m_type)
1578  {
1579  // make sure iterator fits the current value
1580  if (first.m_object != last.m_object)
1581  {
1582  throw std::domain_error("iterators are not compatible");
1583  }
1584 
1585  // check if iterator range is complete for primitive values
1586  switch (m_type)
1587  {
1588  case value_t::boolean:
1589  case value_t::number_float:
1591  case value_t::string:
1592  {
1593  if (not first.m_it.primitive_iterator.is_begin() or not last.m_it.primitive_iterator.is_end())
1594  {
1595  throw std::out_of_range("iterators out of range");
1596  }
1597  break;
1598  }
1599 
1600  default:
1601  {
1602  break;
1603  }
1604  }
1605 
1606  switch (m_type)
1607  {
1609  {
1610  m_value.number_integer = first.m_object->m_value.number_integer;
1611  break;
1612  }
1613 
1614  case value_t::number_float:
1615  {
1616  m_value.number_float = first.m_object->m_value.number_float;
1617  break;
1618  }
1619 
1620  case value_t::boolean:
1621  {
1622  m_value.boolean = first.m_object->m_value.boolean;
1623  break;
1624  }
1625 
1626  case value_t::string:
1627  {
1628  m_value = *first.m_object->m_value.string;
1629  break;
1630  }
1631 
1632  case value_t::object:
1633  {
1634  m_value.object = create<object_t>(first.m_it.object_iterator, last.m_it.object_iterator);
1635  break;
1636  }
1637 
1638  case value_t::array:
1639  {
1640  m_value.array = create<array_t>(first.m_it.array_iterator, last.m_it.array_iterator);
1641  break;
1642  }
1643 
1644  default:
1645  {
1646  throw std::domain_error("cannot use construct with iterators from " + first.m_object->type_name());
1647  }
1648  }
1649  }
1650 
1652  // other constructors and destructor //
1654 
1675  basic_json(const basic_json& other)
1676  : m_type(other.m_type)
1677  {
1678  switch (m_type)
1679  {
1680  case value_t::object:
1681  {
1682  m_value = *other.m_value.object;
1683  break;
1684  }
1685 
1686  case value_t::array:
1687  {
1688  m_value = *other.m_value.array;
1689  break;
1690  }
1691 
1692  case value_t::string:
1693  {
1694  m_value = *other.m_value.string;
1695  break;
1696  }
1697 
1698  case value_t::boolean:
1699  {
1700  m_value = other.m_value.boolean;
1701  break;
1702  }
1703 
1705  {
1706  m_value = other.m_value.number_integer;
1707  break;
1708  }
1709 
1710  case value_t::number_float:
1711  {
1712  m_value = other.m_value.number_float;
1713  break;
1714  }
1715 
1716  default:
1717  {
1718  break;
1719  }
1720  }
1721  }
1722 
1741  basic_json(basic_json&& other) noexcept
1742  : m_type(std::move(other.m_type)),
1743  m_value(std::move(other.m_value))
1744  {
1745  // invalidate payload
1746  other.m_type = value_t::null;
1747  other.m_value = {};
1748  }
1749 
1771  reference& operator=(basic_json other) noexcept (
1772  std::is_nothrow_move_constructible<value_t>::value and
1773  std::is_nothrow_move_assignable<value_t>::value and
1774  std::is_nothrow_move_constructible<json_value>::value and
1775  std::is_nothrow_move_assignable<json_value>::value
1776  )
1777  {
1778  using std::swap;
1779  swap(m_type, other.m_type);
1780  swap(m_value, other.m_value);
1781  return *this;
1782  }
1783 
1798  {
1799  switch (m_type)
1800  {
1801  case value_t::object:
1802  {
1803  AllocatorType<object_t> alloc;
1804  alloc.destroy(m_value.object);
1805  alloc.deallocate(m_value.object, 1);
1806  break;
1807  }
1808 
1809  case value_t::array:
1810  {
1811  AllocatorType<array_t> alloc;
1812  alloc.destroy(m_value.array);
1813  alloc.deallocate(m_value.array, 1);
1814  break;
1815  }
1816 
1817  case value_t::string:
1818  {
1819  AllocatorType<string_t> alloc;
1820  alloc.destroy(m_value.string);
1821  alloc.deallocate(m_value.string, 1);
1822  break;
1823  }
1824 
1825  default:
1826  {
1827  // all other types need no specific destructor
1828  break;
1829  }
1830  }
1831  }
1832 
1834 
1835  public:
1837  // object inspection //
1839 
1842 
1866  string_t dump(const int indent = -1) const
1867  {
1868  std::stringstream ss;
1869 
1870  if (indent >= 0)
1871  {
1872  dump(ss, true, static_cast<unsigned int>(indent));
1873  }
1874  else
1875  {
1876  dump(ss, false, 0);
1877  }
1878 
1879  return ss.str();
1880  }
1881 
1897  value_t type() const noexcept
1898  {
1899  return m_type;
1900  }
1901 
1918  bool is_primitive() const noexcept
1919  {
1920  return is_null() or is_string() or is_boolean() or is_number();
1921  }
1922 
1938  bool is_structured() const noexcept
1939  {
1940  return is_array() or is_object();
1941  }
1942 
1957  bool is_null() const noexcept
1958  {
1959  return m_type == value_t::null;
1960  }
1961 
1976  bool is_boolean() const noexcept
1977  {
1978  return m_type == value_t::boolean;
1979  }
1980 
2000  bool is_number() const noexcept
2001  {
2002  return is_number_integer() or is_number_float();
2003  }
2004 
2023  bool is_number_integer() const noexcept
2024  {
2025  return m_type == value_t::number_integer;
2026  }
2027 
2046  bool is_number_float() const noexcept
2047  {
2048  return m_type == value_t::number_float;
2049  }
2050 
2065  bool is_object() const noexcept
2066  {
2067  return m_type == value_t::object;
2068  }
2069 
2084  bool is_array() const noexcept
2085  {
2086  return m_type == value_t::array;
2087  }
2088 
2103  bool is_string() const noexcept
2104  {
2105  return m_type == value_t::string;
2106  }
2107 
2127  bool is_discarded() const noexcept
2128  {
2129  return m_type == value_t::discarded;
2130  }
2131 
2147  operator value_t() const noexcept
2148  {
2149  return m_type;
2150  }
2151 
2153 
2154  private:
2156  // value access //
2158 
2160  template <class T, typename
2161  std::enable_if<
2162  std::is_convertible<typename object_t::key_type, typename T::key_type>::value and
2163  std::is_convertible<basic_json_t, typename T::mapped_type>::value
2164  , int>::type = 0>
2165  T get_impl(T*) const
2166  {
2167  if (is_object())
2168  {
2169  return T(m_value.object->begin(), m_value.object->end());
2170  }
2171  else
2172  {
2173  throw std::domain_error("type must be object, but is " + type_name());
2174  }
2175  }
2176 
2178  object_t get_impl(object_t*) const
2179  {
2180  if (is_object())
2181  {
2182  return *(m_value.object);
2183  }
2184  else
2185  {
2186  throw std::domain_error("type must be object, but is " + type_name());
2187  }
2188  }
2189 
2191  template <class T, typename
2192  std::enable_if<
2193  std::is_convertible<basic_json_t, typename T::value_type>::value and
2194  not std::is_same<basic_json_t, typename T::value_type>::value and
2195  not std::is_arithmetic<T>::value and
2196  not std::is_convertible<std::string, T>::value and
2197  not has_mapped_type<T>::value
2198  , int>::type = 0>
2199  T get_impl(T*) const
2200  {
2201  if (is_array())
2202  {
2203  T to_vector;
2204  std::transform(m_value.array->begin(), m_value.array->end(),
2205  std::inserter(to_vector, to_vector.end()), [](basic_json i)
2206  {
2207  return i.get<typename T::value_type>();
2208  });
2209  return to_vector;
2210  }
2211  else
2212  {
2213  throw std::domain_error("type must be array, but is " + type_name());
2214  }
2215  }
2216 
2218  template <class T, typename
2219  std::enable_if<
2220  std::is_convertible<basic_json_t, T>::value and
2221  not std::is_same<basic_json_t, T>::value
2222  , int>::type = 0>
2223  std::vector<T> get_impl(std::vector<T>*) const
2224  {
2225  if (is_array())
2226  {
2227  std::vector<T> to_vector;
2228  to_vector.reserve(m_value.array->size());
2229  std::transform(m_value.array->begin(), m_value.array->end(),
2230  std::inserter(to_vector, to_vector.end()), [](basic_json i)
2231  {
2232  return i.get<T>();
2233  });
2234  return to_vector;
2235  }
2236  else
2237  {
2238  throw std::domain_error("type must be array, but is " + type_name());
2239  }
2240  }
2241 
2243  template <class T, typename
2244  std::enable_if<
2245  std::is_same<basic_json, typename T::value_type>::value and
2246  not has_mapped_type<T>::value
2247  , int>::type = 0>
2248  T get_impl(T*) const
2249  {
2250  if (is_array())
2251  {
2252  return T(m_value.array->begin(), m_value.array->end());
2253  }
2254  else
2255  {
2256  throw std::domain_error("type must be array, but is " + type_name());
2257  }
2258  }
2259 
2261  array_t get_impl(array_t*) const
2262  {
2263  if (is_array())
2264  {
2265  return *(m_value.array);
2266  }
2267  else
2268  {
2269  throw std::domain_error("type must be array, but is " + type_name());
2270  }
2271  }
2272 
2274  template <typename T, typename
2275  std::enable_if<
2276  std::is_convertible<string_t, T>::value
2277  , int>::type = 0>
2278  T get_impl(T*) const
2279  {
2280  if (is_string())
2281  {
2282  return *m_value.string;
2283  }
2284  else
2285  {
2286  throw std::domain_error("type must be string, but is " + type_name());
2287  }
2288  }
2289 
2291  template<typename T, typename
2292  std::enable_if<
2293  std::is_arithmetic<T>::value
2294  , int>::type = 0>
2295  T get_impl(T*) const
2296  {
2297  switch (m_type)
2298  {
2300  {
2301  return static_cast<T>(m_value.number_integer);
2302  }
2303 
2304  case value_t::number_float:
2305  {
2306  return static_cast<T>(m_value.number_float);
2307  }
2308 
2309  default:
2310  {
2311  throw std::domain_error("type must be number, but is " + type_name());
2312  }
2313  }
2314  }
2315 
2317  boolean_t get_impl(boolean_t*) const
2318  {
2319  if (is_boolean())
2320  {
2321  return m_value.boolean;
2322  }
2323  else
2324  {
2325  throw std::domain_error("type must be boolean, but is " + type_name());
2326  }
2327  }
2328 
2330  object_t* get_impl_ptr(object_t*) noexcept
2331  {
2332  return is_object() ? m_value.object : nullptr;
2333  }
2334 
2336  const object_t* get_impl_ptr(const object_t*) const noexcept
2337  {
2338  return is_object() ? m_value.object : nullptr;
2339  }
2340 
2342  array_t* get_impl_ptr(array_t*) noexcept
2343  {
2344  return is_array() ? m_value.array : nullptr;
2345  }
2346 
2348  const array_t* get_impl_ptr(const array_t*) const noexcept
2349  {
2350  return is_array() ? m_value.array : nullptr;
2351  }
2352 
2354  string_t* get_impl_ptr(string_t*) noexcept
2355  {
2356  return is_string() ? m_value.string : nullptr;
2357  }
2358 
2360  const string_t* get_impl_ptr(const string_t*) const noexcept
2361  {
2362  return is_string() ? m_value.string : nullptr;
2363  }
2364 
2366  boolean_t* get_impl_ptr(boolean_t*) noexcept
2367  {
2368  return is_boolean() ? &m_value.boolean : nullptr;
2369  }
2370 
2372  const boolean_t* get_impl_ptr(const boolean_t*) const noexcept
2373  {
2374  return is_boolean() ? &m_value.boolean : nullptr;
2375  }
2376 
2378  number_integer_t* get_impl_ptr(number_integer_t*) noexcept
2379  {
2380  return is_number_integer() ? &m_value.number_integer : nullptr;
2381  }
2382 
2384  const number_integer_t* get_impl_ptr(const number_integer_t*) const noexcept
2385  {
2386  return is_number_integer() ? &m_value.number_integer : nullptr;
2387  }
2388 
2390  number_float_t* get_impl_ptr(number_float_t*) noexcept
2391  {
2392  return is_number_float() ? &m_value.number_float : nullptr;
2393  }
2394 
2396  const number_float_t* get_impl_ptr(const number_float_t*) const noexcept
2397  {
2398  return is_number_float() ? &m_value.number_float : nullptr;
2399  }
2400 
2401  public:
2402 
2405 
2439  template<typename ValueType, typename
2440  std::enable_if<
2441  not std::is_pointer<ValueType>::value
2442  , int>::type = 0>
2443  ValueType get() const
2444  {
2445  return get_impl(static_cast<ValueType*>(nullptr));
2446  }
2447 
2474  template<typename PointerType, typename
2475  std::enable_if<
2476  std::is_pointer<PointerType>::value
2477  , int>::type = 0>
2478  PointerType get() noexcept
2479  {
2480  // delegate the call to get_ptr
2481  return get_ptr<PointerType>();
2482  }
2483 
2488  template<typename PointerType, typename
2489  std::enable_if<
2490  std::is_pointer<PointerType>::value
2491  , int>::type = 0>
2492  const PointerType get() const noexcept
2493  {
2494  // delegate the call to get_ptr
2495  return get_ptr<PointerType>();
2496  }
2497 
2523  template<typename PointerType, typename
2524  std::enable_if<
2525  std::is_pointer<PointerType>::value
2526  , int>::type = 0>
2527  PointerType get_ptr() noexcept
2528  {
2529  // delegate the call to get_impl_ptr<>()
2530  return get_impl_ptr(static_cast<PointerType>(nullptr));
2531  }
2532 
2537  template<typename PointerType, typename
2538  std::enable_if<
2539  std::is_pointer<PointerType>::value
2540  and std::is_const<typename std::remove_pointer<PointerType>::type>::value
2541  , int>::type = 0>
2542  const PointerType get_ptr() const noexcept
2543  {
2544  // delegate the call to get_impl_ptr<>() const
2545  return get_impl_ptr(static_cast<const PointerType>(nullptr));
2546  }
2547 
2576  template<typename ValueType, typename
2577  std::enable_if<
2578  not std::is_pointer<ValueType>::value
2579  and not std::is_same<ValueType, typename string_t::value_type>::value
2580  and not std::is_same<ValueType, std::initializer_list<typename string_t::value_type>>::value
2581  , int>::type = 0>
2582  operator ValueType() const
2583  {
2584  // delegate the call to get<>() const
2585  return get<ValueType>();
2586  }
2587 
2589 
2590 
2592  // element access //
2594 
2597 
2621  {
2622  // at only works for arrays
2623  if (is_array())
2624  {
2625  try
2626  {
2627  return m_value.array->at(idx);
2628  }
2629  catch (std::out_of_range& e)
2630  {
2631  // create better exception explanation
2632  throw std::out_of_range("array index " + std::to_string(idx) + " is out of range");
2633  }
2634  }
2635  else
2636  {
2637  throw std::domain_error("cannot use at() with " + type_name());
2638  }
2639  }
2640 
2664  {
2665  // at only works for arrays
2666  if (is_array())
2667  {
2668  try
2669  {
2670  return m_value.array->at(idx);
2671  }
2672  catch (std::out_of_range& e)
2673  {
2674  // create better exception explanation
2675  throw std::out_of_range("array index " + std::to_string(idx) + " is out of range");
2676  }
2677  }
2678  else
2679  {
2680  throw std::domain_error("cannot use at() with " + type_name());
2681  }
2682  }
2683 
2710  reference at(const typename object_t::key_type& key)
2711  {
2712  // at only works for objects
2713  if (is_object())
2714  {
2715  try
2716  {
2717  return m_value.object->at(key);
2718  }
2719  catch (std::out_of_range& e)
2720  {
2721  // create better exception explanation
2722  throw std::out_of_range("key '" + key + "' not found");
2723  }
2724  }
2725  else
2726  {
2727  throw std::domain_error("cannot use at() with " + type_name());
2728  }
2729  }
2730 
2757  const_reference at(const typename object_t::key_type& key) const
2758  {
2759  // at only works for objects
2760  if (is_object())
2761  {
2762  try
2763  {
2764  return m_value.object->at(key);
2765  }
2766  catch (std::out_of_range& e)
2767  {
2768  // create better exception explanation
2769  throw std::out_of_range("key '" + key + "' not found");
2770  }
2771  }
2772  else
2773  {
2774  throw std::domain_error("cannot use at() with " + type_name());
2775  }
2776  }
2777 
2804  {
2805  // implicitly convert null to object
2806  if (is_null())
2807  {
2808  m_type = value_t::array;
2809  m_value.array = create<array_t>();
2810  }
2811 
2812  // [] only works for arrays
2813  if (is_array())
2814  {
2815  for (size_t i = m_value.array->size(); i <= idx; ++i)
2816  {
2817  m_value.array->push_back(basic_json());
2818  }
2819 
2820  return m_value.array->operator[](idx);
2821  }
2822  else
2823  {
2824  throw std::domain_error("cannot use operator[] with " + type_name());
2825  }
2826  }
2827 
2848  {
2849  // at only works for arrays
2850  if (is_array())
2851  {
2852  return m_value.array->operator[](idx);
2853  }
2854  else
2855  {
2856  throw std::domain_error("cannot use operator[] with " + type_name());
2857  }
2858  }
2859 
2887  reference operator[](const typename object_t::key_type& key)
2888  {
2889  // implicitly convert null to object
2890  if (is_null())
2891  {
2892  m_type = value_t::object;
2893  m_value.object = create<object_t>();
2894  }
2895 
2896  // [] only works for objects
2897  if (is_object())
2898  {
2899  return m_value.object->operator[](key);
2900  }
2901  else
2902  {
2903  throw std::domain_error("cannot use operator[] with " + type_name());
2904  }
2905  }
2906 
2934  const_reference operator[](const typename object_t::key_type& key) const
2935  {
2936  // [] only works for objects
2937  if (is_object())
2938  {
2939  return m_value.object->find(key)->second;
2940  }
2941  else
2942  {
2943  throw std::domain_error("cannot use operator[] with " + type_name());
2944  }
2945  }
2946 
2976  template<typename T, std::size_t n>
2977  reference operator[](const T (&key)[n])
2978  {
2979  // implicitly convert null to object
2980  if (is_null())
2981  {
2982  m_type = value_t::object;
2983  m_value = value_t::object;
2984  }
2985 
2986  // at only works for objects
2987  if (is_object())
2988  {
2989  return m_value.object->operator[](key);
2990  }
2991  else
2992  {
2993  throw std::domain_error("cannot use operator[] with " + type_name());
2994  }
2995  }
2996 
3026  template<typename T, std::size_t n>
3027  const_reference operator[](const T (&key)[n]) const
3028  {
3029  // at only works for objects
3030  if (is_object())
3031  {
3032  return m_value.object->find(key)->second;
3033  }
3034  else
3035  {
3036  throw std::domain_error("cannot use operator[] with " + type_name());
3037  }
3038  }
3039 
3088  template <class ValueType, typename
3089  std::enable_if<
3090  std::is_convertible<basic_json_t, ValueType>::value
3091  , int>::type = 0>
3092  ValueType value(const typename object_t::key_type& key, ValueType default_value) const
3093  {
3094  // at only works for objects
3095  if (is_object())
3096  {
3097  // if key is found, return value and given default value otherwise
3098  const auto it = find(key);
3099  if (it != end())
3100  {
3101  return *it;
3102  }
3103  else
3104  {
3105  return default_value;
3106  }
3107  }
3108  else
3109  {
3110  throw std::domain_error("cannot use value() with " + type_name());
3111  }
3112  }
3113 
3118  string_t value(const typename object_t::key_type& key, const char* default_value) const
3119  {
3120  return value(key, string_t(default_value));
3121  }
3122 
3144  {
3145  return *begin();
3146  }
3147 
3152  {
3153  return *cbegin();
3154  }
3155 
3178  {
3179  auto tmp = end();
3180  --tmp;
3181  return *tmp;
3182  }
3183 
3188  {
3189  auto tmp = cend();
3190  --tmp;
3191  return *tmp;
3192  }
3193 
3238  template <class InteratorType, typename
3239  std::enable_if<
3240  std::is_same<InteratorType, typename basic_json_t::iterator>::value or
3241  std::is_same<InteratorType, typename basic_json_t::const_iterator>::value
3242  , int>::type
3243  = 0>
3244  InteratorType erase(InteratorType pos)
3245  {
3246  // make sure iterator fits the current value
3247  if (this != pos.m_object)
3248  {
3249  throw std::domain_error("iterator does not fit current value");
3250  }
3251 
3252  InteratorType result = end();
3253 
3254  switch (m_type)
3255  {
3256  case value_t::boolean:
3257  case value_t::number_float:
3259  case value_t::string:
3260  {
3261  if (not pos.m_it.primitive_iterator.is_begin())
3262  {
3263  throw std::out_of_range("iterator out of range");
3264  }
3265 
3266  if (is_string())
3267  {
3268  delete m_value.string;
3269  m_value.string = nullptr;
3270  }
3271 
3272  m_type = value_t::null;
3273  break;
3274  }
3275 
3276  case value_t::object:
3277  {
3278  result.m_it.object_iterator = m_value.object->erase(pos.m_it.object_iterator);
3279  break;
3280  }
3281 
3282  case value_t::array:
3283  {
3284  result.m_it.array_iterator = m_value.array->erase(pos.m_it.array_iterator);
3285  break;
3286  }
3287 
3288  default:
3289  {
3290  throw std::domain_error("cannot use erase() with " + type_name());
3291  }
3292  }
3293 
3294  return result;
3295  }
3296 
3341  template <class InteratorType, typename
3342  std::enable_if<
3343  std::is_same<InteratorType, typename basic_json_t::iterator>::value or
3344  std::is_same<InteratorType, typename basic_json_t::const_iterator>::value
3345  , int>::type
3346  = 0>
3347  InteratorType erase(InteratorType first, InteratorType last)
3348  {
3349  // make sure iterator fits the current value
3350  if (this != first.m_object or this != last.m_object)
3351  {
3352  throw std::domain_error("iterators do not fit current value");
3353  }
3354 
3355  InteratorType result = end();
3356 
3357  switch (m_type)
3358  {
3359  case value_t::boolean:
3360  case value_t::number_float:
3362  case value_t::string:
3363  {
3364  if (not first.m_it.primitive_iterator.is_begin() or not last.m_it.primitive_iterator.is_end())
3365  {
3366  throw std::out_of_range("iterators out of range");
3367  }
3368 
3369  if (is_string())
3370  {
3371  delete m_value.string;
3372  m_value.string = nullptr;
3373  }
3374 
3375  m_type = value_t::null;
3376  break;
3377  }
3378 
3379  case value_t::object:
3380  {
3381  result.m_it.object_iterator = m_value.object->erase(first.m_it.object_iterator,
3382  last.m_it.object_iterator);
3383  break;
3384  }
3385 
3386  case value_t::array:
3387  {
3388  result.m_it.array_iterator = m_value.array->erase(first.m_it.array_iterator,
3389  last.m_it.array_iterator);
3390  break;
3391  }
3392 
3393  default:
3394  {
3395  throw std::domain_error("cannot use erase() with " + type_name());
3396  }
3397  }
3398 
3399  return result;
3400  }
3401 
3428  size_type erase(const typename object_t::key_type& key)
3429  {
3430  // this erase only works for objects
3431  if (is_object())
3432  {
3433  return m_value.object->erase(key);
3434  }
3435  else
3436  {
3437  throw std::domain_error("cannot use erase() with " + type_name());
3438  }
3439  }
3440 
3465  void erase(const size_type idx)
3466  {
3467  // this erase only works for arrays
3468  if (is_array())
3469  {
3470  if (idx >= size())
3471  {
3472  throw std::out_of_range("index out of range");
3473  }
3474 
3475  m_value.array->erase(m_value.array->begin() + static_cast<difference_type>(idx));
3476  }
3477  else
3478  {
3479  throw std::domain_error("cannot use erase() with " + type_name());
3480  }
3481  }
3482 
3500  iterator find(typename object_t::key_type key)
3501  {
3502  auto result = end();
3503 
3504  if (is_object())
3505  {
3506  result.m_it.object_iterator = m_value.object->find(key);
3507  }
3508 
3509  return result;
3510  }
3511 
3516  const_iterator find(typename object_t::key_type key) const
3517  {
3518  auto result = cend();
3519 
3520  if (is_object())
3521  {
3522  result.m_it.object_iterator = m_value.object->find(key);
3523  }
3524 
3525  return result;
3526  }
3527 
3546  size_type count(typename object_t::key_type key) const
3547  {
3548  // return 0 for all nonobject types
3549  return is_object() ? m_value.object->count(key) : 0;
3550  }
3551 
3553 
3554 
3556  // iterators //
3558 
3561 
3581  {
3582  iterator result(this);
3583  result.set_begin();
3584  return result;
3585  }
3586 
3591  {
3592  return cbegin();
3593  }
3594 
3615  {
3616  const_iterator result(this);
3617  result.set_begin();
3618  return result;
3619  }
3620 
3640  {
3641  iterator result(this);
3642  result.set_end();
3643  return result;
3644  }
3645 
3650  {
3651  return cend();
3652  }
3653 
3674  {
3675  const_iterator result(this);
3676  result.set_end();
3677  return result;
3678  }
3679 
3698  {
3699  return reverse_iterator(end());
3700  }
3701 
3706  {
3707  return crbegin();
3708  }
3709 
3729  {
3730  return reverse_iterator(begin());
3731  }
3732 
3737  {
3738  return crend();
3739  }
3740 
3760  {
3761  return const_reverse_iterator(cend());
3762  }
3763 
3783  {
3784  return const_reverse_iterator(cbegin());
3785  }
3786 
3787  private:
3788  // forward declaration
3789  template<typename IteratorType> class iteration_proxy;
3790 
3791  public:
3803  static iteration_proxy<iterator> iterator_wrapper(reference cont)
3804  {
3805  return iteration_proxy<iterator>(cont);
3806  }
3807 
3811  static iteration_proxy<const_iterator> iterator_wrapper(const_reference cont)
3812  {
3813  return iteration_proxy<const_iterator>(cont);
3814  }
3815 
3817 
3818 
3820  // capacity //
3822 
3825 
3855  bool empty() const noexcept
3856  {
3857  switch (m_type)
3858  {
3859  case value_t::null:
3860  {
3861  // null values are empty
3862  return true;
3863  }
3864 
3865  case value_t::array:
3866  {
3867  return m_value.array->empty();
3868  }
3869 
3870  case value_t::object:
3871  {
3872  return m_value.object->empty();
3873  }
3874 
3875  default:
3876  {
3877  // all other types are nonempty
3878  return false;
3879  }
3880  }
3881  }
3882 
3911  size_type size() const noexcept
3912  {
3913  switch (m_type)
3914  {
3915  case value_t::null:
3916  {
3917  // null values are empty
3918  return 0;
3919  }
3920 
3921  case value_t::array:
3922  {
3923  return m_value.array->size();
3924  }
3925 
3926  case value_t::object:
3927  {
3928  return m_value.object->size();
3929  }
3930 
3931  default:
3932  {
3933  // all other types have size 1
3934  return 1;
3935  }
3936  }
3937  }
3938 
3971  size_type max_size() const noexcept
3972  {
3973  switch (m_type)
3974  {
3975  case value_t::array:
3976  {
3977  return m_value.array->max_size();
3978  }
3979 
3980  case value_t::object:
3981  {
3982  return m_value.object->max_size();
3983  }
3984 
3985  default:
3986  {
3987  // all other types have max_size() == size()
3988  return size();
3989  }
3990  }
3991  }
3992 
3994 
3995 
3997  // modifiers //
3999 
4002 
4028  void clear() noexcept
4029  {
4030  switch (m_type)
4031  {
4033  {
4034  m_value.number_integer = 0;
4035  break;
4036  }
4037 
4038  case value_t::number_float:
4039  {
4040  m_value.number_float = 0.0;
4041  break;
4042  }
4043 
4044  case value_t::boolean:
4045  {
4046  m_value.boolean = false;
4047  break;
4048  }
4049 
4050  case value_t::string:
4051  {
4052  m_value.string->clear();
4053  break;
4054  }
4055 
4056  case value_t::array:
4057  {
4058  m_value.array->clear();
4059  break;
4060  }
4061 
4062  case value_t::object:
4063  {
4064  m_value.object->clear();
4065  break;
4066  }
4067 
4068  default:
4069  {
4070  break;
4071  }
4072  }
4073  }
4074 
4095  void push_back(basic_json&& val)
4096  {
4097  // push_back only works for null objects or arrays
4098  if (not(is_null() or is_array()))
4099  {
4100  throw std::domain_error("cannot use push_back() with " + type_name());
4101  }
4102 
4103  // transform null object into an array
4104  if (is_null())
4105  {
4106  m_type = value_t::array;
4107  m_value = value_t::array;
4108  }
4109 
4110  // add element to array (move semantics)
4111  m_value.array->push_back(std::move(val));
4112  // invalidate object
4113  val.m_type = value_t::null;
4114  }
4115 
4120  reference operator+=(basic_json&& val)
4121  {
4122  push_back(std::move(val));
4123  return *this;
4124  }
4125 
4130  void push_back(const basic_json& val)
4131  {
4132  // push_back only works for null objects or arrays
4133  if (not(is_null() or is_array()))
4134  {
4135  throw std::domain_error("cannot use push_back() with " + type_name());
4136  }
4137 
4138  // transform null object into an array
4139  if (is_null())
4140  {
4141  m_type = value_t::array;
4142  m_value = value_t::array;
4143  }
4144 
4145  // add element to array
4146  m_value.array->push_back(val);
4147  }
4148 
4153  reference operator+=(const basic_json& val)
4154  {
4155  push_back(val);
4156  return *this;
4157  }
4158 
4179  void push_back(const typename object_t::value_type& val)
4180  {
4181  // push_back only works for null objects or objects
4182  if (not(is_null() or is_object()))
4183  {
4184  throw std::domain_error("cannot use push_back() with " + type_name());
4185  }
4186 
4187  // transform null object into an object
4188  if (is_null())
4189  {
4190  m_type = value_t::object;
4191  m_value = value_t::object;
4192  }
4193 
4194  // add element to array
4195  m_value.object->insert(val);
4196  }
4197 
4202  reference operator+=(const typename object_t::value_type& val)
4203  {
4204  push_back(val);
4205  return operator[](val.first);
4206  }
4207 
4230  iterator insert(const_iterator pos, const basic_json& val)
4231  {
4232  // insert only works for arrays
4233  if (is_array())
4234  {
4235  // check if iterator pos fits to this JSON value
4236  if (pos.m_object != this)
4237  {
4238  throw std::domain_error("iterator does not fit current value");
4239  }
4240 
4241  // insert to array and return iterator
4242  iterator result(this);
4243  result.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator, val);
4244  return result;
4245  }
4246  else
4247  {
4248  throw std::domain_error("cannot use insert() with " + type_name());
4249  }
4250  }
4251 
4256  iterator insert(const_iterator pos, basic_json&& val)
4257  {
4258  return insert(pos, val);
4259  }
4260 
4285  iterator insert(const_iterator pos, size_type cnt, const basic_json& val)
4286  {
4287  // insert only works for arrays
4288  if (is_array())
4289  {
4290  // check if iterator pos fits to this JSON value
4291  if (pos.m_object != this)
4292  {
4293  throw std::domain_error("iterator does not fit current value");
4294  }
4295 
4296  // insert to array and return iterator
4297  iterator result(this);
4298  result.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator, cnt, val);
4299  return result;
4300  }
4301  else
4302  {
4303  throw std::domain_error("cannot use insert() with " + type_name());
4304  }
4305  }
4306 
4338  {
4339  // insert only works for arrays
4340  if (not is_array())
4341  {
4342  throw std::domain_error("cannot use insert() with " + type_name());
4343  }
4344 
4345  // check if iterator pos fits to this JSON value
4346  if (pos.m_object != this)
4347  {
4348  throw std::domain_error("iterator does not fit current value");
4349  }
4350 
4351  if (first.m_object != last.m_object)
4352  {
4353  throw std::domain_error("iterators do not fit");
4354  }
4355 
4356  if (first.m_object == this or last.m_object == this)
4357  {
4358  throw std::domain_error("passed iterators may not belong to container");
4359  }
4360 
4361  // insert to array and return iterator
4362  iterator result(this);
4363  result.m_it.array_iterator = m_value.array->insert(
4364  pos.m_it.array_iterator,
4365  first.m_it.array_iterator,
4366  last.m_it.array_iterator);
4367  return result;
4368  }
4369 
4394  iterator insert(const_iterator pos, std::initializer_list<basic_json> ilist)
4395  {
4396  // insert only works for arrays
4397  if (not is_array())
4398  {
4399  throw std::domain_error("cannot use insert() with " + type_name());
4400  }
4401 
4402  // check if iterator pos fits to this JSON value
4403  if (pos.m_object != this)
4404  {
4405  throw std::domain_error("iterator does not fit current value");
4406  }
4407 
4408  // insert to array and return iterator
4409  iterator result(this);
4410  result.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator, ilist);
4411  return result;
4412  }
4413 
4431  void swap(reference other) noexcept (
4432  std::is_nothrow_move_constructible<value_t>::value and
4433  std::is_nothrow_move_assignable<value_t>::value and
4434  std::is_nothrow_move_constructible<json_value>::value and
4435  std::is_nothrow_move_assignable<json_value>::value
4436  )
4437  {
4438  std::swap(m_type, other.m_type);
4439  std::swap(m_value, other.m_value);
4440  }
4441 
4462  void swap(array_t& other)
4463  {
4464  // swap only works for arrays
4465  if (is_array())
4466  {
4467  std::swap(*(m_value.array), other);
4468  }
4469  else
4470  {
4471  throw std::domain_error("cannot use swap() with " + type_name());
4472  }
4473  }
4474 
4495  void swap(object_t& other)
4496  {
4497  // swap only works for objects
4498  if (is_object())
4499  {
4500  std::swap(*(m_value.object), other);
4501  }
4502  else
4503  {
4504  throw std::domain_error("cannot use swap() with " + type_name());
4505  }
4506  }
4507 
4528  void swap(string_t& other)
4529  {
4530  // swap only works for strings
4531  if (is_string())
4532  {
4533  std::swap(*(m_value.string), other);
4534  }
4535  else
4536  {
4537  throw std::domain_error("cannot use swap() with " + type_name());
4538  }
4539  }
4540 
4542 
4543 
4545  // lexicographical comparison operators //
4547 
4550 
4551  private:
4561  friend bool operator<(const value_t lhs, const value_t rhs)
4562  {
4563  static constexpr std::array<uint8_t, 7> order = {{
4564  0, // null
4565  3, // object
4566  4, // array
4567  5, // string
4568  1, // boolean
4569  2, // integer
4570  2 // float
4571  }
4572  };
4573 
4574  // discarded values are not comparable
4575  if (lhs == value_t::discarded or rhs == value_t::discarded)
4576  {
4577  return false;
4578  }
4579 
4580  return order[static_cast<std::size_t>(lhs)] < order[static_cast<std::size_t>(rhs)];
4581  }
4582 
4583  public:
4607  friend bool operator==(const_reference lhs, const_reference rhs) noexcept
4608  {
4609  const auto lhs_type = lhs.type();
4610  const auto rhs_type = rhs.type();
4611 
4612  if (lhs_type == rhs_type)
4613  {
4614  switch (lhs_type)
4615  {
4616  case value_t::array:
4617  return *lhs.m_value.array == *rhs.m_value.array;
4618  case value_t::object:
4619  return *lhs.m_value.object == *rhs.m_value.object;
4620  case value_t::null:
4621  return true;
4622  case value_t::string:
4623  return *lhs.m_value.string == *rhs.m_value.string;
4624  case value_t::boolean:
4625  return lhs.m_value.boolean == rhs.m_value.boolean;
4627  return lhs.m_value.number_integer == rhs.m_value.number_integer;
4628  case value_t::number_float:
4629  return approx(lhs.m_value.number_float, rhs.m_value.number_float);
4630  default:
4631  return false;
4632  }
4633  }
4634  else if (lhs_type == value_t::number_integer and rhs_type == value_t::number_float)
4635  {
4636  return approx(static_cast<number_float_t>(lhs.m_value.number_integer),
4637  rhs.m_value.number_float);
4638  }
4639  else if (lhs_type == value_t::number_float and rhs_type == value_t::number_integer)
4640  {
4641  return approx(lhs.m_value.number_float,
4642  static_cast<number_float_t>(rhs.m_value.number_integer));
4643  }
4644  return false;
4645  }
4646 
4665  friend bool operator==(const_reference v, std::nullptr_t) noexcept
4666  {
4667  return v.is_null();
4668  }
4669 
4674  friend bool operator==(std::nullptr_t, const_reference v) noexcept
4675  {
4676  return v.is_null();
4677  }
4678 
4695  friend bool operator!=(const_reference lhs, const_reference rhs) noexcept
4696  {
4697  return not (lhs == rhs);
4698  }
4699 
4718  friend bool operator!=(const_reference v, std::nullptr_t) noexcept
4719  {
4720  return not v.is_null();
4721  }
4722 
4727  friend bool operator!=(std::nullptr_t, const_reference v) noexcept
4728  {
4729  return not v.is_null();
4730  }
4731 
4756  friend bool operator<(const_reference lhs, const_reference rhs) noexcept
4757  {
4758  const auto lhs_type = lhs.type();
4759  const auto rhs_type = rhs.type();
4760 
4761  if (lhs_type == rhs_type)
4762  {
4763  switch (lhs_type)
4764  {
4765  case value_t::array:
4766  return *lhs.m_value.array < *rhs.m_value.array;
4767  case value_t::object:
4768  return *lhs.m_value.object < *rhs.m_value.object;
4769  case value_t::null:
4770  return false;
4771  case value_t::string:
4772  return *lhs.m_value.string < *rhs.m_value.string;
4773  case value_t::boolean:
4774  return lhs.m_value.boolean < rhs.m_value.boolean;
4776  return lhs.m_value.number_integer < rhs.m_value.number_integer;
4777  case value_t::number_float:
4778  return lhs.m_value.number_float < rhs.m_value.number_float;
4779  default:
4780  return false;
4781  }
4782  }
4783  else if (lhs_type == value_t::number_integer and rhs_type == value_t::number_float)
4784  {
4785  return static_cast<number_float_t>(lhs.m_value.number_integer) <
4786  rhs.m_value.number_float;
4787  }
4788  else if (lhs_type == value_t::number_float and rhs_type == value_t::number_integer)
4789  {
4790  return lhs.m_value.number_float <
4791  static_cast<number_float_t>(rhs.m_value.number_integer);
4792  }
4793 
4794  // We only reach this line if we cannot compare values. In that case,
4795  // we compare types. Note we have to call the operator explicitly,
4796  // because MSVC has problems otherwise.
4797  return operator<(lhs_type, rhs_type);
4798  }
4799 
4817  friend bool operator<=(const_reference lhs, const_reference rhs) noexcept
4818  {
4819  return not (rhs < lhs);
4820  }
4821 
4839  friend bool operator>(const_reference lhs, const_reference rhs) noexcept
4840  {
4841  return not (lhs <= rhs);
4842  }
4843 
4861  friend bool operator>=(const_reference lhs, const_reference rhs) noexcept
4862  {
4863  return not (lhs < rhs);
4864  }
4865 
4867 
4868 
4870  // serialization //
4872 
4875 
4898  friend std::ostream& operator<<(std::ostream& o, const basic_json& j)
4899  {
4900  // read width member and use it as indentation parameter if nonzero
4901  const bool pretty_print = (o.width() > 0);
4902  const auto indentation = (pretty_print ? o.width() : 0);
4903 
4904  // reset width to 0 for subsequent calls to this stream
4905  o.width(0);
4906 
4907  // do the actual serialization
4908  j.dump(o, pretty_print, static_cast<unsigned int>(indentation));
4909  return o;
4910  }
4911 
4916  friend std::ostream& operator>>(const basic_json& j, std::ostream& o)
4917  {
4918  return o << j;
4919  }
4920 
4922 
4923 
4925  // deserialization //
4927 
4930 
4955  static basic_json parse(const string_t& s, parser_callback_t cb = nullptr)
4956  {
4957  return parser(s, cb).parse();
4958  }
4959 
4984  static basic_json parse(std::istream& i, parser_callback_t cb = nullptr)
4985  {
4986  return parser(i, cb).parse();
4987  }
4988 
4992  static basic_json parse(std::istream&& i, parser_callback_t cb = nullptr)
4993  {
4994  return parser(i, cb).parse();
4995  }
4996 
5020  friend std::istream& operator<<(basic_json& j, std::istream& i)
5021  {
5022  j = parser(i).parse();
5023  return i;
5024  }
5025 
5030  friend std::istream& operator>>(std::istream& i, basic_json& j)
5031  {
5032  j = parser(i).parse();
5033  return i;
5034  }
5035 
5037 
5038 
5039  private:
5041  // convenience functions //
5043 
5045  string_t type_name() const
5046  {
5047  switch (m_type)
5048  {
5049  case value_t::null:
5050  return "null";
5051  case value_t::object:
5052  return "object";
5053  case value_t::array:
5054  return "array";
5055  case value_t::string:
5056  return "string";
5057  case value_t::boolean:
5058  return "boolean";
5059  case value_t::discarded:
5060  return "discarded";
5061  default:
5062  return "number";
5063  }
5064  }
5065 
5074  static std::size_t extra_space(const string_t& s) noexcept
5075  {
5076  std::size_t result = 0;
5077 
5078  for (const auto& c : s)
5079  {
5080  switch (c)
5081  {
5082  case '"':
5083  case '\\':
5084  case '\b':
5085  case '\f':
5086  case '\n':
5087  case '\r':
5088  case '\t':
5089  {
5090  // from c (1 byte) to \x (2 bytes)
5091  result += 1;
5092  break;
5093  }
5094 
5095  default:
5096  {
5097  if (c >= 0x00 and c <= 0x1f)
5098  {
5099  // from c (1 byte) to \uxxxx (6 bytes)
5100  result += 5;
5101  }
5102  break;
5103  }
5104  }
5105  }
5106 
5107  return result;
5108  }
5109 
5123  static string_t escape_string(const string_t& s) noexcept
5124  {
5125  const auto space = extra_space(s);
5126  if (space == 0)
5127  {
5128  return s;
5129  }
5130 
5131  // create a result string of necessary size
5132  string_t result(s.size() + space, '\\');
5133  std::size_t pos = 0;
5134 
5135  for (const auto& c : s)
5136  {
5137  switch (c)
5138  {
5139  // quotation mark (0x22)
5140  case '"':
5141  {
5142  result[pos + 1] = '"';
5143  pos += 2;
5144  break;
5145  }
5146 
5147  // reverse solidus (0x5c)
5148  case '\\':
5149  {
5150  // nothing to change
5151  pos += 2;
5152  break;
5153  }
5154 
5155  // backspace (0x08)
5156  case '\b':
5157  {
5158  result[pos + 1] = 'b';
5159  pos += 2;
5160  break;
5161  }
5162 
5163  // formfeed (0x0c)
5164  case '\f':
5165  {
5166  result[pos + 1] = 'f';
5167  pos += 2;
5168  break;
5169  }
5170 
5171  // newline (0x0a)
5172  case '\n':
5173  {
5174  result[pos + 1] = 'n';
5175  pos += 2;
5176  break;
5177  }
5178 
5179  // carriage return (0x0d)
5180  case '\r':
5181  {
5182  result[pos + 1] = 'r';
5183  pos += 2;
5184  break;
5185  }
5186 
5187  // horizontal tab (0x09)
5188  case '\t':
5189  {
5190  result[pos + 1] = 't';
5191  pos += 2;
5192  break;
5193  }
5194 
5195  default:
5196  {
5197  if (c >= 0x00 and c <= 0x1f)
5198  {
5199  // convert a number 0..15 to its hex representation (0..f)
5200  auto hexify = [](const char v) -> char
5201  {
5202  return (v < 10) ? ('0' + v) : ('a' + v - 10);
5203  };
5204 
5205  // print character c as \uxxxx
5206  for (const char m :
5207  { 'u', '0', '0', hexify(c >> 4), hexify(c & 0x0f)
5208  })
5209  {
5210  result[++pos] = m;
5211  }
5212 
5213  ++pos;
5214  }
5215  else
5216  {
5217  // all other characters are added as-is
5218  result[pos++] = c;
5219  }
5220  break;
5221  }
5222  }
5223  }
5224 
5225  return result;
5226  }
5227 
5245  void dump(std::ostream& o,
5246  const bool pretty_print,
5247  const unsigned int indent_step,
5248  const unsigned int current_indent = 0) const
5249  {
5250  // variable to hold indentation for recursive calls
5251  unsigned int new_indent = current_indent;
5252 
5253  switch (m_type)
5254  {
5255  case value_t::object:
5256  {
5257  if (m_value.object->empty())
5258  {
5259  o << "{}";
5260  return;
5261  }
5262 
5263  o << "{";
5264 
5265  // increase indentation
5266  if (pretty_print)
5267  {
5268  new_indent += indent_step;
5269  o << "\n";
5270  }
5271 
5272  for (auto i = m_value.object->cbegin(); i != m_value.object->cend(); ++i)
5273  {
5274  if (i != m_value.object->cbegin())
5275  {
5276  o << (pretty_print ? ",\n" : ",");
5277  }
5278  o << string_t(new_indent, ' ') << "\""
5279  << escape_string(i->first) << "\":"
5280  << (pretty_print ? " " : "");
5281  i->second.dump(o, pretty_print, indent_step, new_indent);
5282  }
5283 
5284  // decrease indentation
5285  if (pretty_print)
5286  {
5287  new_indent -= indent_step;
5288  o << "\n";
5289  }
5290 
5291  o << string_t(new_indent, ' ') + "}";
5292  return;
5293  }
5294 
5295  case value_t::array:
5296  {
5297  if (m_value.array->empty())
5298  {
5299  o << "[]";
5300  return;
5301  }
5302 
5303  o << "[";
5304 
5305  // increase indentation
5306  if (pretty_print)
5307  {
5308  new_indent += indent_step;
5309  o << "\n";
5310  }
5311 
5312  for (auto i = m_value.array->cbegin(); i != m_value.array->cend(); ++i)
5313  {
5314  if (i != m_value.array->cbegin())
5315  {
5316  o << (pretty_print ? ",\n" : ",");
5317  }
5318  o << string_t(new_indent, ' ');
5319  i->dump(o, pretty_print, indent_step, new_indent);
5320  }
5321 
5322  // decrease indentation
5323  if (pretty_print)
5324  {
5325  new_indent -= indent_step;
5326  o << "\n";
5327  }
5328 
5329  o << string_t(new_indent, ' ') << "]";
5330  return;
5331  }
5332 
5333  case value_t::string:
5334  {
5335  o << string_t("\"") << escape_string(*m_value.string) << "\"";
5336  return;
5337  }
5338 
5339  case value_t::boolean:
5340  {
5341  o << (m_value.boolean ? "true" : "false");
5342  return;
5343  }
5344 
5346  {
5347  o << m_value.number_integer;
5348  return;
5349  }
5350 
5351  case value_t::number_float:
5352  {
5353  // 15 digits of precision allows round-trip IEEE 754
5354  // string->double->string; to be safe, we read this value from
5355  // std::numeric_limits<number_float_t>::digits10
5356  o << std::setprecision(std::numeric_limits<number_float_t>::digits10) << m_value.number_float;
5357  return;
5358  }
5359 
5360  case value_t::discarded:
5361  {
5362  o << "<discarded>";
5363  return;
5364  }
5365 
5366  case value_t::null:
5367  {
5368  o << "null";
5369  return;
5370  }
5371  }
5372  }
5373 
5374  private:
5376  // member variables //
5378 
5380  value_t m_type = value_t::null;
5381 
5383  json_value m_value = {};
5384 
5385 
5386  private:
5388  // iterators //
5390 
5400  class primitive_iterator_t
5401  {
5402  public:
5404  void set_begin()
5405  {
5406  m_it = begin_value;
5407  }
5408 
5410  void set_end()
5411  {
5412  m_it = end_value;
5413  }
5414 
5416  bool is_begin() const
5417  {
5418  return (m_it == begin_value);
5419  }
5420 
5422  bool is_end() const
5423  {
5424  return (m_it == end_value);
5425  }
5426 
5428  operator difference_type& ()
5429  {
5430  return m_it;
5431  }
5432 
5434  operator difference_type () const
5435  {
5436  return m_it;
5437  }
5438 
5439  private:
5440  static constexpr difference_type begin_value = 0;
5441  static constexpr difference_type end_value = begin_value + 1;
5442 
5444  difference_type m_it = std::numeric_limits<std::ptrdiff_t>::denorm_min();
5445  };
5446 
5454  struct internal_iterator
5455  {
5457  typename object_t::iterator object_iterator;
5459  typename array_t::iterator array_iterator;
5461  primitive_iterator_t primitive_iterator;
5462 
5464  internal_iterator()
5465  : object_iterator(), array_iterator(), primitive_iterator()
5466  {}
5467  };
5468 
5470  template<typename IteratorType>
5471  class iteration_proxy
5472  {
5473  private:
5475  class iteration_proxy_internal
5476  {
5477  private:
5479  IteratorType anchor;
5481  size_t array_index = 0;
5482 
5483  public:
5484  iteration_proxy_internal(IteratorType it)
5485  : anchor(it)
5486  {}
5487 
5489  iteration_proxy_internal& operator*()
5490  {
5491  return *this;
5492  }
5493 
5495  iteration_proxy_internal& operator++()
5496  {
5497  ++anchor;
5498  ++array_index;
5499 
5500  return *this;
5501  }
5502 
5504  bool operator!= (const iteration_proxy_internal& o) const
5505  {
5506  return anchor != o.anchor;
5507  }
5508 
5510  typename basic_json::string_t key() const
5511  {
5512  switch (anchor.m_object->type())
5513  {
5514  // use integer array index as key
5515  case value_t::array:
5516  {
5517  return std::to_string(array_index);
5518  }
5519 
5520  // use key from the object
5521  case value_t::object:
5522  {
5523  return anchor.key();
5524  }
5525 
5526  // use an empty key for all primitive types
5527  default:
5528  {
5529  return "";
5530  }
5531  }
5532  }
5533 
5535  typename IteratorType::reference value() const
5536  {
5537  return anchor.value();
5538  }
5539  };
5540 
5542  typename IteratorType::reference container;
5543 
5544  public:
5546  iteration_proxy(typename IteratorType::reference cont)
5547  : container(cont)
5548  {}
5549 
5551  iteration_proxy_internal begin()
5552  {
5553  return iteration_proxy_internal(container.begin());
5554  }
5555 
5557  iteration_proxy_internal end()
5558  {
5559  return iteration_proxy_internal(container.end());
5560  }
5561  };
5562 
5563  public:
5577  class const_iterator : public std::iterator<std::random_access_iterator_tag, const basic_json>
5578  {
5580  friend class basic_json;
5581 
5582  public:
5592  using iterator_category = std::bidirectional_iterator_tag;
5593 
5595  const_iterator() = default;
5596 
5598  const_iterator(pointer object) : m_object(object)
5599  {
5600  switch (m_object->m_type)
5601  {
5603  {
5604  m_it.object_iterator = typename object_t::iterator();
5605  break;
5606  }
5607 
5609  {
5610  m_it.array_iterator = typename array_t::iterator();
5611  break;
5612  }
5613 
5614  default:
5615  {
5616  m_it.primitive_iterator = primitive_iterator_t();
5617  break;
5618  }
5619  }
5620  }
5621 
5623  const_iterator(const iterator& other) : m_object(other.m_object)
5624  {
5625  switch (m_object->m_type)
5626  {
5628  {
5629  m_it.object_iterator = other.m_it.object_iterator;
5630  break;
5631  }
5632 
5634  {
5635  m_it.array_iterator = other.m_it.array_iterator;
5636  break;
5637  }
5638 
5639  default:
5640  {
5641  m_it.primitive_iterator = other.m_it.primitive_iterator;
5642  break;
5643  }
5644  }
5645  }
5646 
5648  const_iterator(const const_iterator& other) noexcept
5649  : m_object(other.m_object), m_it(other.m_it)
5650  {}
5651 
5654  std::is_nothrow_move_constructible<pointer>::value and
5655  std::is_nothrow_move_assignable<pointer>::value and
5656  std::is_nothrow_move_constructible<internal_iterator>::value and
5657  std::is_nothrow_move_assignable<internal_iterator>::value
5658  )
5659  {
5660  std::swap(m_object, other.m_object);
5661  std::swap(m_it, other.m_it);
5662  return *this;
5663  }
5664 
5665  private:
5667  void set_begin()
5668  {
5669  switch (m_object->m_type)
5670  {
5672  {
5673  m_it.object_iterator = m_object->m_value.object->begin();
5674  break;
5675  }
5676 
5678  {
5679  m_it.array_iterator = m_object->m_value.array->begin();
5680  break;
5681  }
5682 
5684  {
5685  // set to end so begin()==end() is true: null is empty
5686  m_it.primitive_iterator.set_end();
5687  break;
5688  }
5689 
5690  default:
5691  {
5692  m_it.primitive_iterator.set_begin();
5693  break;
5694  }
5695  }
5696  }
5697 
5699  void set_end()
5700  {
5701  switch (m_object->m_type)
5702  {
5704  {
5705  m_it.object_iterator = m_object->m_value.object->end();
5706  break;
5707  }
5708 
5710  {
5711  m_it.array_iterator = m_object->m_value.array->end();
5712  break;
5713  }
5714 
5715  default:
5716  {
5717  m_it.primitive_iterator.set_end();
5718  break;
5719  }
5720  }
5721  }
5722 
5723  public:
5726  {
5727  switch (m_object->m_type)
5728  {
5730  {
5731  return m_it.object_iterator->second;
5732  }
5733 
5735  {
5736  return *m_it.array_iterator;
5737  }
5738 
5740  {
5741  throw std::out_of_range("cannot get value");
5742  }
5743 
5744  default:
5745  {
5746  if (m_it.primitive_iterator.is_begin())
5747  {
5748  return *m_object;
5749  }
5750  else
5751  {
5752  throw std::out_of_range("cannot get value");
5753  }
5754  }
5755  }
5756  }
5757 
5760  {
5761  switch (m_object->m_type)
5762  {
5764  {
5765  return &(m_it.object_iterator->second);
5766  }
5767 
5769  {
5770  return &*m_it.array_iterator;
5771  }
5772 
5773  default:
5774  {
5775  if (m_it.primitive_iterator.is_begin())
5776  {
5777  return m_object;
5778  }
5779  else
5780  {
5781  throw std::out_of_range("cannot get value");
5782  }
5783  }
5784  }
5785  }
5786 
5789  {
5790  auto result = *this;
5791  ++(*this);
5792  return result;
5793  }
5794 
5797  {
5798  switch (m_object->m_type)
5799  {
5801  {
5802  ++m_it.object_iterator;
5803  break;
5804  }
5805 
5807  {
5808  ++m_it.array_iterator;
5809  break;
5810  }
5811 
5812  default:
5813  {
5814  ++m_it.primitive_iterator;
5815  break;
5816  }
5817  }
5818 
5819  return *this;
5820  }
5821 
5824  {
5825  auto result = *this;
5826  --(*this);
5827  return result;
5828  }
5829 
5832  {
5833  switch (m_object->m_type)
5834  {
5836  {
5837  --m_it.object_iterator;
5838  break;
5839  }
5840 
5842  {
5843  --m_it.array_iterator;
5844  break;
5845  }
5846 
5847  default:
5848  {
5849  --m_it.primitive_iterator;
5850  break;
5851  }
5852  }
5853 
5854  return *this;
5855  }
5856 
5858  bool operator==(const const_iterator& other) const
5859  {
5860  // if objects are not the same, the comparison is undefined
5861  if (m_object != other.m_object)
5862  {
5863  throw std::domain_error("cannot compare iterators of different containers");
5864  }
5865 
5866  switch (m_object->m_type)
5867  {
5869  {
5870  return (m_it.object_iterator == other.m_it.object_iterator);
5871  }
5872 
5874  {
5875  return (m_it.array_iterator == other.m_it.array_iterator);
5876  }
5877 
5878  default:
5879  {
5880  return (m_it.primitive_iterator == other.m_it.primitive_iterator);
5881  }
5882  }
5883  }
5884 
5886  bool operator!=(const const_iterator& other) const
5887  {
5888  return not operator==(other);
5889  }
5890 
5892  bool operator<(const const_iterator& other) const
5893  {
5894  // if objects are not the same, the comparison is undefined
5895  if (m_object != other.m_object)
5896  {
5897  throw std::domain_error("cannot compare iterators of different containers");
5898  }
5899 
5900  switch (m_object->m_type)
5901  {
5903  {
5904  throw std::domain_error("cannot compare order of object iterators");
5905  }
5906 
5908  {
5909  return (m_it.array_iterator < other.m_it.array_iterator);
5910  }
5911 
5912  default:
5913  {
5914  return (m_it.primitive_iterator < other.m_it.primitive_iterator);
5915  }
5916  }
5917  }
5918 
5920  bool operator<=(const const_iterator& other) const
5921  {
5922  return not other.operator < (*this);
5923  }
5924 
5926  bool operator>(const const_iterator& other) const
5927  {
5928  return not operator<=(other);
5929  }
5930 
5932  bool operator>=(const const_iterator& other) const
5933  {
5934  return not operator<(other);
5935  }
5936 
5939  {
5940  switch (m_object->m_type)
5941  {
5943  {
5944  throw std::domain_error("cannot use offsets with object iterators");
5945  }
5946 
5948  {
5949  m_it.array_iterator += i;
5950  break;
5951  }
5952 
5953  default:
5954  {
5955  m_it.primitive_iterator += i;
5956  break;
5957  }
5958  }
5959 
5960  return *this;
5961  }
5962 
5965  {
5966  return operator+=(-i);
5967  }
5968 
5971  {
5972  auto result = *this;
5973  result += i;
5974  return result;
5975  }
5976 
5979  {
5980  auto result = *this;
5981  result -= i;
5982  return result;
5983  }
5984 
5987  {
5988  switch (m_object->m_type)
5989  {
5991  {
5992  throw std::domain_error("cannot use offsets with object iterators");
5993  }
5994 
5996  {
5997  return m_it.array_iterator - other.m_it.array_iterator;
5998  }
5999 
6000  default:
6001  {
6002  return m_it.primitive_iterator - other.m_it.primitive_iterator;
6003  }
6004  }
6005  }
6006 
6009  {
6010  switch (m_object->m_type)
6011  {
6013  {
6014  throw std::domain_error("cannot use operator[] for object iterators");
6015  }
6016 
6018  {
6019  return *(m_it.array_iterator + n);
6020  }
6021 
6023  {
6024  throw std::out_of_range("cannot get value");
6025  }
6026 
6027  default:
6028  {
6029  if (m_it.primitive_iterator == -n)
6030  {
6031  return *m_object;
6032  }
6033  else
6034  {
6035  throw std::out_of_range("cannot get value");
6036  }
6037  }
6038  }
6039  }
6040 
6042  typename object_t::key_type key() const
6043  {
6044  if (m_object->is_object())
6045  {
6046  return m_it.object_iterator->first;
6047  }
6048  else
6049  {
6050  throw std::domain_error("cannot use key() for non-object iterators");
6051  }
6052  }
6053 
6056  {
6057  return operator*();
6058  }
6059 
6060  private:
6062  pointer m_object = nullptr;
6064  internal_iterator m_it = internal_iterator();
6065  };
6066 
6079  class iterator : public const_iterator
6080  {
6081  public:
6083  using pointer = typename basic_json::pointer;
6085 
6087  iterator() = default;
6088 
6090  iterator(pointer object) noexcept
6091  : base_iterator(object)
6092  {}
6093 
6095  iterator(const iterator& other) noexcept
6096  : base_iterator(other)
6097  {}
6098 
6100  iterator& operator=(iterator other) noexcept(
6101  std::is_nothrow_move_constructible<pointer>::value and
6102  std::is_nothrow_move_assignable<pointer>::value and
6103  std::is_nothrow_move_constructible<internal_iterator>::value and
6104  std::is_nothrow_move_assignable<internal_iterator>::value
6105  )
6106  {
6107  base_iterator::operator=(other);
6108  return *this;
6109  }
6110 
6113  {
6114  return const_cast<reference>(base_iterator::operator*());
6115  }
6116 
6119  {
6120  return const_cast<pointer>(base_iterator::operator->());
6121  }
6122 
6125  {
6126  iterator result = *this;
6128  return result;
6129  }
6130 
6133  {
6135  return *this;
6136  }
6137 
6140  {
6141  iterator result = *this;
6143  return result;
6144  }
6145 
6148  {
6150  return *this;
6151  }
6152 
6155  {
6157  return *this;
6158  }
6159 
6162  {
6164  return *this;
6165  }
6166 
6169  {
6170  auto result = *this;
6171  result += i;
6172  return result;
6173  }
6174 
6177  {
6178  auto result = *this;
6179  result -= i;
6180  return result;
6181  }
6182 
6183  difference_type operator-(const iterator& other) const
6184  {
6185  return base_iterator::operator-(other);
6186  }
6187 
6190  {
6191  return const_cast<reference>(base_iterator::operator[](n));
6192  }
6193 
6196  {
6197  return const_cast<reference>(base_iterator::value());
6198  }
6199  };
6200 
6218  template<typename Base>
6219  class json_reverse_iterator : public std::reverse_iterator<Base>
6220  {
6221  public:
6223  using base_iterator = std::reverse_iterator<Base>;
6225  using reference = typename Base::reference;
6226 
6228  json_reverse_iterator(const typename base_iterator::iterator_type& it)
6229  : base_iterator(it)
6230  {}
6231 
6234  : base_iterator(it)
6235  {}
6236 
6239  {
6240  return base_iterator::operator++(1);
6241  }
6242 
6245  {
6246  base_iterator::operator++();
6247  return *this;
6248  }
6249 
6252  {
6253  return base_iterator::operator--(1);
6254  }
6255 
6258  {
6259  base_iterator::operator--();
6260  return *this;
6261  }
6262 
6265  {
6266  base_iterator::operator+=(i);
6267  return *this;
6268  }
6269 
6272  {
6273  auto result = *this;
6274  result += i;
6275  return result;
6276  }
6277 
6280  {
6281  auto result = *this;
6282  result -= i;
6283  return result;
6284  }
6285 
6288  {
6289  return this->base() - other.base();
6290  }
6291 
6294  {
6295  return *(this->operator+(n));
6296  }
6297 
6299  typename object_t::key_type key() const
6300  {
6301  auto it = --this->base();
6302  return it.key();
6303  }
6304 
6307  {
6308  auto it = --this->base();
6309  return it.operator * ();
6310  }
6311  };
6312 
6313 
6314  private:
6316  // lexer and parser //
6318 
6326  class lexer
6327  {
6328  public:
6330  enum class token_type
6331  {
6332  uninitialized,
6333  literal_true,
6334  literal_false,
6335  literal_null,
6336  value_string,
6337  value_number,
6338  begin_array,
6339  begin_object,
6340  end_array,
6341  end_object,
6342  name_separator,
6343  value_separator,
6344  parse_error,
6345  end_of_input
6346  };
6347 
6349  using lexer_char_t = unsigned char;
6350 
6352  explicit lexer(const string_t& s) noexcept
6353  : m_stream(nullptr), m_buffer(s)
6354  {
6355  m_content = reinterpret_cast<const lexer_char_t*>(s.c_str());
6356  m_start = m_cursor = m_content;
6357  m_limit = m_content + s.size();
6358  }
6359 
6361  explicit lexer(std::istream* s) noexcept
6362  : m_stream(s), m_buffer()
6363  {
6364  getline(*m_stream, m_buffer);
6365  m_content = reinterpret_cast<const lexer_char_t*>(m_buffer.c_str());
6366  m_start = m_cursor = m_content;
6367  m_limit = m_content + m_buffer.size();
6368  }
6369 
6371  lexer() = default;
6372 
6373  // switch off unwanted functions
6374  lexer(const lexer&) = delete;
6375  lexer operator=(const lexer&) = delete;
6376 
6392  static string_t to_unicode(const std::size_t codepoint1,
6393  const std::size_t codepoint2 = 0)
6394  {
6395  string_t result;
6396 
6397  // calculate the codepoint from the given code points
6398  std::size_t codepoint = codepoint1;
6399 
6400  // check if codepoint1 is a high surrogate
6401  if (codepoint1 >= 0xD800 and codepoint1 <= 0xDBFF)
6402  {
6403  // check if codepoint2 is a low surrogate
6404  if (codepoint2 >= 0xDC00 and codepoint2 <= 0xDFFF)
6405  {
6406  codepoint =
6407  // high surrogate occupies the most significant 22 bits
6408  (codepoint1 << 10)
6409  // low surrogate occupies the least significant 15 bits
6410  + codepoint2
6411  // there is still the 0xD800, 0xDC00 and 0x10000 noise
6412  // in the result so we have to substract with:
6413  // (0xD800 << 10) + DC00 - 0x10000 = 0x35FDC00
6414  - 0x35FDC00;
6415  }
6416  else
6417  {
6418  throw std::invalid_argument("missing or wrong low surrogate");
6419  }
6420  }
6421 
6422  if (codepoint < 0x80)
6423  {
6424  // 1-byte characters: 0xxxxxxx (ASCII)
6425  result.append(1, static_cast<typename string_t::value_type>(codepoint));
6426  }
6427  else if (codepoint <= 0x7ff)
6428  {
6429  // 2-byte characters: 110xxxxx 10xxxxxx
6430  result.append(1, static_cast<typename string_t::value_type>(0xC0 | ((codepoint >> 6) & 0x1F)));
6431  result.append(1, static_cast<typename string_t::value_type>(0x80 | (codepoint & 0x3F)));
6432  }
6433  else if (codepoint <= 0xffff)
6434  {
6435  // 3-byte characters: 1110xxxx 10xxxxxx 10xxxxxx
6436  result.append(1, static_cast<typename string_t::value_type>(0xE0 | ((codepoint >> 12) & 0x0F)));
6437  result.append(1, static_cast<typename string_t::value_type>(0x80 | ((codepoint >> 6) & 0x3F)));
6438  result.append(1, static_cast<typename string_t::value_type>(0x80 | (codepoint & 0x3F)));
6439  }
6440  else if (codepoint <= 0x10ffff)
6441  {
6442  // 4-byte characters: 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
6443  result.append(1, static_cast<typename string_t::value_type>(0xF0 | ((codepoint >> 18) & 0x07)));
6444  result.append(1, static_cast<typename string_t::value_type>(0x80 | ((codepoint >> 12) & 0x3F)));
6445  result.append(1, static_cast<typename string_t::value_type>(0x80 | ((codepoint >> 6) & 0x3F)));
6446  result.append(1, static_cast<typename string_t::value_type>(0x80 | (codepoint & 0x3F)));
6447  }
6448  else
6449  {
6450  throw std::out_of_range("code points above 0x10FFFF are invalid");
6451  }
6452 
6453  return result;
6454  }
6455 
6457  static std::string token_type_name(token_type t)
6458  {
6459  switch (t)
6460  {
6461  case token_type::uninitialized:
6462  return "<uninitialized>";
6463  case token_type::literal_true:
6464  return "true literal";
6465  case token_type::literal_false:
6466  return "false literal";
6467  case token_type::literal_null:
6468  return "null literal";
6469  case token_type::value_string:
6470  return "string literal";
6471  case token_type::value_number:
6472  return "number literal";
6473  case token_type::begin_array:
6474  return "'['";
6475  case token_type::begin_object:
6476  return "'{'";
6477  case token_type::end_array:
6478  return "']'";
6479  case token_type::end_object:
6480  return "'}'";
6481  case token_type::name_separator:
6482  return "':'";
6483  case token_type::value_separator:
6484  return "','";
6485  case token_type::parse_error:
6486  return "<parse error>";
6487  case token_type::end_of_input:
6488  return "end of input";
6489  default:
6490  {
6491  // catch non-enum values
6492  return "unknown token"; // LCOV_EXCL_LINE
6493  }
6494  }
6495  }
6496 
6507  token_type scan() noexcept
6508  {
6509  // pointer for backtracking information
6510  m_marker = nullptr;
6511 
6512  // remember the begin of the token
6513  m_start = m_cursor;
6514 
6515 
6516  {
6517  lexer_char_t yych;
6518  unsigned int yyaccept = 0;
6519  static const unsigned char yybm[] =
6520  {
6521  0, 0, 0, 0, 0, 0, 0, 0,
6522  0, 32, 32, 0, 0, 32, 0, 0,
6523  64, 64, 64, 64, 64, 64, 64, 64,
6524  64, 64, 64, 64, 64, 64, 64, 64,
6525  96, 64, 0, 64, 64, 64, 64, 64,
6526  64, 64, 64, 64, 64, 64, 64, 64,
6527  192, 192, 192, 192, 192, 192, 192, 192,
6528  192, 192, 64, 64, 64, 64, 64, 64,
6529  64, 64, 64, 64, 64, 64, 64, 64,
6530  64, 64, 64, 64, 64, 64, 64, 64,
6531  64, 64, 64, 64, 64, 64, 64, 64,
6532  64, 64, 64, 64, 0, 64, 64, 64,
6533  64, 64, 64, 64, 64, 64, 64, 64,
6534  64, 64, 64, 64, 64, 64, 64, 64,
6535  64, 64, 64, 64, 64, 64, 64, 64,
6536  64, 64, 64, 64, 64, 64, 64, 64,
6537  64, 64, 64, 64, 64, 64, 64, 64,
6538  64, 64, 64, 64, 64, 64, 64, 64,
6539  64, 64, 64, 64, 64, 64, 64, 64,
6540  64, 64, 64, 64, 64, 64, 64, 64,
6541  64, 64, 64, 64, 64, 64, 64, 64,
6542  64, 64, 64, 64, 64, 64, 64, 64,
6543  64, 64, 64, 64, 64, 64, 64, 64,
6544  64, 64, 64, 64, 64, 64, 64, 64,
6545  64, 64, 64, 64, 64, 64, 64, 64,
6546  64, 64, 64, 64, 64, 64, 64, 64,
6547  64, 64, 64, 64, 64, 64, 64, 64,
6548  64, 64, 64, 64, 64, 64, 64, 64,
6549  64, 64, 64, 64, 64, 64, 64, 64,
6550  64, 64, 64, 64, 64, 64, 64, 64,
6551  64, 64, 64, 64, 64, 64, 64, 64,
6552  64, 64, 64, 64, 64, 64, 64, 64,
6553  };
6554  if ((m_limit - m_cursor) < 5)
6555  {
6556  yyfill(); // LCOV_EXCL_LINE;
6557  }
6558  yych = *m_cursor;
6559  if (yych <= ':')
6560  {
6561  if (yych <= ' ')
6562  {
6563  if (yych <= '\n')
6564  {
6565  if (yych <= 0x00)
6566  {
6567  goto basic_json_parser_28;
6568  }
6569  if (yych <= 0x08)
6570  {
6571  goto basic_json_parser_30;
6572  }
6573  if (yych >= '\n')
6574  {
6575  goto basic_json_parser_4;
6576  }
6577  }
6578  else
6579  {
6580  if (yych == '\r')
6581  {
6582  goto basic_json_parser_2;
6583  }
6584  if (yych <= 0x1F)
6585  {
6586  goto basic_json_parser_30;
6587  }
6588  }
6589  }
6590  else
6591  {
6592  if (yych <= ',')
6593  {
6594  if (yych == '"')
6595  {
6596  goto basic_json_parser_27;
6597  }
6598  if (yych <= '+')
6599  {
6600  goto basic_json_parser_30;
6601  }
6602  goto basic_json_parser_16;
6603  }
6604  else
6605  {
6606  if (yych <= '/')
6607  {
6608  if (yych <= '-')
6609  {
6610  goto basic_json_parser_23;
6611  }
6612  goto basic_json_parser_30;
6613  }
6614  else
6615  {
6616  if (yych <= '0')
6617  {
6618  goto basic_json_parser_24;
6619  }
6620  if (yych <= '9')
6621  {
6622  goto basic_json_parser_26;
6623  }
6624  goto basic_json_parser_18;
6625  }
6626  }
6627  }
6628  }
6629  else
6630  {
6631  if (yych <= 'n')
6632  {
6633  if (yych <= ']')
6634  {
6635  if (yych == '[')
6636  {
6637  goto basic_json_parser_8;
6638  }
6639  if (yych <= '\\')
6640  {
6641  goto basic_json_parser_30;
6642  }
6643  goto basic_json_parser_10;
6644  }
6645  else
6646  {
6647  if (yych == 'f')
6648  {
6649  goto basic_json_parser_22;
6650  }
6651  if (yych <= 'm')
6652  {
6653  goto basic_json_parser_30;
6654  }
6655  goto basic_json_parser_20;
6656  }
6657  }
6658  else
6659  {
6660  if (yych <= '{')
6661  {
6662  if (yych == 't')
6663  {
6664  goto basic_json_parser_21;
6665  }
6666  if (yych <= 'z')
6667  {
6668  goto basic_json_parser_30;
6669  }
6670  goto basic_json_parser_12;
6671  }
6672  else
6673  {
6674  if (yych <= '}')
6675  {
6676  if (yych <= '|')
6677  {
6678  goto basic_json_parser_30;
6679  }
6680  goto basic_json_parser_14;
6681  }
6682  else
6683  {
6684  if (yych == 0xEF)
6685  {
6686  goto basic_json_parser_6;
6687  }
6688  goto basic_json_parser_30;
6689  }
6690  }
6691  }
6692  }
6693 basic_json_parser_2:
6694  ++m_cursor;
6695  yych = *m_cursor;
6696  goto basic_json_parser_5;
6697 basic_json_parser_3:
6698  {
6699  return scan();
6700  }
6701 basic_json_parser_4:
6702  ++m_cursor;
6703  if (m_limit <= m_cursor)
6704  {
6705  yyfill(); // LCOV_EXCL_LINE;
6706  }
6707  yych = *m_cursor;
6708 basic_json_parser_5:
6709  if (yybm[0 + yych] & 32)
6710  {
6711  goto basic_json_parser_4;
6712  }
6713  goto basic_json_parser_3;
6714 basic_json_parser_6:
6715  yyaccept = 0;
6716  yych = *(m_marker = ++m_cursor);
6717  if (yych == 0xBB)
6718  {
6719  goto basic_json_parser_64;
6720  }
6721 basic_json_parser_7:
6722  {
6723  return token_type::parse_error;
6724  }
6725 basic_json_parser_8:
6726  ++m_cursor;
6727  {
6728  return token_type::begin_array;
6729  }
6730 basic_json_parser_10:
6731  ++m_cursor;
6732  {
6733  return token_type::end_array;
6734  }
6735 basic_json_parser_12:
6736  ++m_cursor;
6737  {
6738  return token_type::begin_object;
6739  }
6740 basic_json_parser_14:
6741  ++m_cursor;
6742  {
6743  return token_type::end_object;
6744  }
6745 basic_json_parser_16:
6746  ++m_cursor;
6747  {
6748  return token_type::value_separator;
6749  }
6750 basic_json_parser_18:
6751  ++m_cursor;
6752  {
6753  return token_type::name_separator;
6754  }
6755 basic_json_parser_20:
6756  yyaccept = 0;
6757  yych = *(m_marker = ++m_cursor);
6758  if (yych == 'u')
6759  {
6760  goto basic_json_parser_60;
6761  }
6762  goto basic_json_parser_7;
6763 basic_json_parser_21:
6764  yyaccept = 0;
6765  yych = *(m_marker = ++m_cursor);
6766  if (yych == 'r')
6767  {
6768  goto basic_json_parser_56;
6769  }
6770  goto basic_json_parser_7;
6771 basic_json_parser_22:
6772  yyaccept = 0;
6773  yych = *(m_marker = ++m_cursor);
6774  if (yych == 'a')
6775  {
6776  goto basic_json_parser_51;
6777  }
6778  goto basic_json_parser_7;
6779 basic_json_parser_23:
6780  yych = *++m_cursor;
6781  if (yych <= '/')
6782  {
6783  goto basic_json_parser_7;
6784  }
6785  if (yych <= '0')
6786  {
6787  goto basic_json_parser_50;
6788  }
6789  if (yych <= '9')
6790  {
6791  goto basic_json_parser_41;
6792  }
6793  goto basic_json_parser_7;
6794 basic_json_parser_24:
6795  yyaccept = 1;
6796  yych = *(m_marker = ++m_cursor);
6797  if (yych <= 'D')
6798  {
6799  if (yych == '.')
6800  {
6801  goto basic_json_parser_43;
6802  }
6803  }
6804  else
6805  {
6806  if (yych <= 'E')
6807  {
6808  goto basic_json_parser_44;
6809  }
6810  if (yych == 'e')
6811  {
6812  goto basic_json_parser_44;
6813  }
6814  }
6815 basic_json_parser_25:
6816  {
6817  return token_type::value_number;
6818  }
6819 basic_json_parser_26:
6820  yyaccept = 1;
6821  yych = *(m_marker = ++m_cursor);
6822  goto basic_json_parser_42;
6823 basic_json_parser_27:
6824  yyaccept = 0;
6825  yych = *(m_marker = ++m_cursor);
6826  if (yych <= 0x0F)
6827  {
6828  goto basic_json_parser_7;
6829  }
6830  goto basic_json_parser_32;
6831 basic_json_parser_28:
6832  ++m_cursor;
6833  {
6834  return token_type::end_of_input;
6835  }
6836 basic_json_parser_30:
6837  yych = *++m_cursor;
6838  goto basic_json_parser_7;
6839 basic_json_parser_31:
6840  ++m_cursor;
6841  if (m_limit <= m_cursor)
6842  {
6843  yyfill(); // LCOV_EXCL_LINE;
6844  }
6845  yych = *m_cursor;
6846 basic_json_parser_32:
6847  if (yybm[0 + yych] & 64)
6848  {
6849  goto basic_json_parser_31;
6850  }
6851  if (yych <= 0x0F)
6852  {
6853  goto basic_json_parser_33;
6854  }
6855  if (yych <= '"')
6856  {
6857  goto basic_json_parser_35;
6858  }
6859  goto basic_json_parser_34;
6860 basic_json_parser_33:
6861  m_cursor = m_marker;
6862  if (yyaccept == 0)
6863  {
6864  goto basic_json_parser_7;
6865  }
6866  else
6867  {
6868  goto basic_json_parser_25;
6869  }
6870 basic_json_parser_34:
6871  ++m_cursor;
6872  if (m_limit <= m_cursor)
6873  {
6874  yyfill(); // LCOV_EXCL_LINE;
6875  }
6876  yych = *m_cursor;
6877  if (yych <= 'e')
6878  {
6879  if (yych <= '/')
6880  {
6881  if (yych == '"')
6882  {
6883  goto basic_json_parser_31;
6884  }
6885  if (yych <= '.')
6886  {
6887  goto basic_json_parser_33;
6888  }
6889  goto basic_json_parser_31;
6890  }
6891  else
6892  {
6893  if (yych <= '\\')
6894  {
6895  if (yych <= '[')
6896  {
6897  goto basic_json_parser_33;
6898  }
6899  goto basic_json_parser_31;
6900  }
6901  else
6902  {
6903  if (yych == 'b')
6904  {
6905  goto basic_json_parser_31;
6906  }
6907  goto basic_json_parser_33;
6908  }
6909  }
6910  }
6911  else
6912  {
6913  if (yych <= 'q')
6914  {
6915  if (yych <= 'f')
6916  {
6917  goto basic_json_parser_31;
6918  }
6919  if (yych == 'n')
6920  {
6921  goto basic_json_parser_31;
6922  }
6923  goto basic_json_parser_33;
6924  }
6925  else
6926  {
6927  if (yych <= 's')
6928  {
6929  if (yych <= 'r')
6930  {
6931  goto basic_json_parser_31;
6932  }
6933  goto basic_json_parser_33;
6934  }
6935  else
6936  {
6937  if (yych <= 't')
6938  {
6939  goto basic_json_parser_31;
6940  }
6941  if (yych <= 'u')
6942  {
6943  goto basic_json_parser_37;
6944  }
6945  goto basic_json_parser_33;
6946  }
6947  }
6948  }
6949 basic_json_parser_35:
6950  ++m_cursor;
6951  {
6952  return token_type::value_string;
6953  }
6954 basic_json_parser_37:
6955  ++m_cursor;
6956  if (m_limit <= m_cursor)
6957  {
6958  yyfill(); // LCOV_EXCL_LINE;
6959  }
6960  yych = *m_cursor;
6961  if (yych <= '@')
6962  {
6963  if (yych <= '/')
6964  {
6965  goto basic_json_parser_33;
6966  }
6967  if (yych >= ':')
6968  {
6969  goto basic_json_parser_33;
6970  }
6971  }
6972  else
6973  {
6974  if (yych <= 'F')
6975  {
6976  goto basic_json_parser_38;
6977  }
6978  if (yych <= '`')
6979  {
6980  goto basic_json_parser_33;
6981  }
6982  if (yych >= 'g')
6983  {
6984  goto basic_json_parser_33;
6985  }
6986  }
6987 basic_json_parser_38:
6988  ++m_cursor;
6989  if (m_limit <= m_cursor)
6990  {
6991  yyfill(); // LCOV_EXCL_LINE;
6992  }
6993  yych = *m_cursor;
6994  if (yych <= '@')
6995  {
6996  if (yych <= '/')
6997  {
6998  goto basic_json_parser_33;
6999  }
7000  if (yych >= ':')
7001  {
7002  goto basic_json_parser_33;
7003  }
7004  }
7005  else
7006  {
7007  if (yych <= 'F')
7008  {
7009  goto basic_json_parser_39;
7010  }
7011  if (yych <= '`')
7012  {
7013  goto basic_json_parser_33;
7014  }
7015  if (yych >= 'g')
7016  {
7017  goto basic_json_parser_33;
7018  }
7019  }
7020 basic_json_parser_39:
7021  ++m_cursor;
7022  if (m_limit <= m_cursor)
7023  {
7024  yyfill(); // LCOV_EXCL_LINE;
7025  }
7026  yych = *m_cursor;
7027  if (yych <= '@')
7028  {
7029  if (yych <= '/')
7030  {
7031  goto basic_json_parser_33;
7032  }
7033  if (yych >= ':')
7034  {
7035  goto basic_json_parser_33;
7036  }
7037  }
7038  else
7039  {
7040  if (yych <= 'F')
7041  {
7042  goto basic_json_parser_40;
7043  }
7044  if (yych <= '`')
7045  {
7046  goto basic_json_parser_33;
7047  }
7048  if (yych >= 'g')
7049  {
7050  goto basic_json_parser_33;
7051  }
7052  }
7053 basic_json_parser_40:
7054  ++m_cursor;
7055  if (m_limit <= m_cursor)
7056  {
7057  yyfill(); // LCOV_EXCL_LINE;
7058  }
7059  yych = *m_cursor;
7060  if (yych <= '@')
7061  {
7062  if (yych <= '/')
7063  {
7064  goto basic_json_parser_33;
7065  }
7066  if (yych <= '9')
7067  {
7068  goto basic_json_parser_31;
7069  }
7070  goto basic_json_parser_33;
7071  }
7072  else
7073  {
7074  if (yych <= 'F')
7075  {
7076  goto basic_json_parser_31;
7077  }
7078  if (yych <= '`')
7079  {
7080  goto basic_json_parser_33;
7081  }
7082  if (yych <= 'f')
7083  {
7084  goto basic_json_parser_31;
7085  }
7086  goto basic_json_parser_33;
7087  }
7088 basic_json_parser_41:
7089  yyaccept = 1;
7090  m_marker = ++m_cursor;
7091  if ((m_limit - m_cursor) < 3)
7092  {
7093  yyfill(); // LCOV_EXCL_LINE;
7094  }
7095  yych = *m_cursor;
7096 basic_json_parser_42:
7097  if (yybm[0 + yych] & 128)
7098  {
7099  goto basic_json_parser_41;
7100  }
7101  if (yych <= 'D')
7102  {
7103  if (yych != '.')
7104  {
7105  goto basic_json_parser_25;
7106  }
7107  }
7108  else
7109  {
7110  if (yych <= 'E')
7111  {
7112  goto basic_json_parser_44;
7113  }
7114  if (yych == 'e')
7115  {
7116  goto basic_json_parser_44;
7117  }
7118  goto basic_json_parser_25;
7119  }
7120 basic_json_parser_43:
7121  yych = *++m_cursor;
7122  if (yych <= '/')
7123  {
7124  goto basic_json_parser_33;
7125  }
7126  if (yych <= '9')
7127  {
7128  goto basic_json_parser_48;
7129  }
7130  goto basic_json_parser_33;
7131 basic_json_parser_44:
7132  yych = *++m_cursor;
7133  if (yych <= ',')
7134  {
7135  if (yych != '+')
7136  {
7137  goto basic_json_parser_33;
7138  }
7139  }
7140  else
7141  {
7142  if (yych <= '-')
7143  {
7144  goto basic_json_parser_45;
7145  }
7146  if (yych <= '/')
7147  {
7148  goto basic_json_parser_33;
7149  }
7150  if (yych <= '9')
7151  {
7152  goto basic_json_parser_46;
7153  }
7154  goto basic_json_parser_33;
7155  }
7156 basic_json_parser_45:
7157  yych = *++m_cursor;
7158  if (yych <= '/')
7159  {
7160  goto basic_json_parser_33;
7161  }
7162  if (yych >= ':')
7163  {
7164  goto basic_json_parser_33;
7165  }
7166 basic_json_parser_46:
7167  ++m_cursor;
7168  if (m_limit <= m_cursor)
7169  {
7170  yyfill(); // LCOV_EXCL_LINE;
7171  }
7172  yych = *m_cursor;
7173  if (yych <= '/')
7174  {
7175  goto basic_json_parser_25;
7176  }
7177  if (yych <= '9')
7178  {
7179  goto basic_json_parser_46;
7180  }
7181  goto basic_json_parser_25;
7182 basic_json_parser_48:
7183  yyaccept = 1;
7184  m_marker = ++m_cursor;
7185  if ((m_limit - m_cursor) < 3)
7186  {
7187  yyfill(); // LCOV_EXCL_LINE;
7188  }
7189  yych = *m_cursor;
7190  if (yych <= 'D')
7191  {
7192  if (yych <= '/')
7193  {
7194  goto basic_json_parser_25;
7195  }
7196  if (yych <= '9')
7197  {
7198  goto basic_json_parser_48;
7199  }
7200  goto basic_json_parser_25;
7201  }
7202  else
7203  {
7204  if (yych <= 'E')
7205  {
7206  goto basic_json_parser_44;
7207  }
7208  if (yych == 'e')
7209  {
7210  goto basic_json_parser_44;
7211  }
7212  goto basic_json_parser_25;
7213  }
7214 basic_json_parser_50:
7215  yyaccept = 1;
7216  yych = *(m_marker = ++m_cursor);
7217  if (yych <= 'D')
7218  {
7219  if (yych == '.')
7220  {
7221  goto basic_json_parser_43;
7222  }
7223  goto basic_json_parser_25;
7224  }
7225  else
7226  {
7227  if (yych <= 'E')
7228  {
7229  goto basic_json_parser_44;
7230  }
7231  if (yych == 'e')
7232  {
7233  goto basic_json_parser_44;
7234  }
7235  goto basic_json_parser_25;
7236  }
7237 basic_json_parser_51:
7238  yych = *++m_cursor;
7239  if (yych != 'l')
7240  {
7241  goto basic_json_parser_33;
7242  }
7243  yych = *++m_cursor;
7244  if (yych != 's')
7245  {
7246  goto basic_json_parser_33;
7247  }
7248  yych = *++m_cursor;
7249  if (yych != 'e')
7250  {
7251  goto basic_json_parser_33;
7252  }
7253  ++m_cursor;
7254  {
7255  return token_type::literal_false;
7256  }
7257 basic_json_parser_56:
7258  yych = *++m_cursor;
7259  if (yych != 'u')
7260  {
7261  goto basic_json_parser_33;
7262  }
7263  yych = *++m_cursor;
7264  if (yych != 'e')
7265  {
7266  goto basic_json_parser_33;
7267  }
7268  ++m_cursor;
7269  {
7270  return token_type::literal_true;
7271  }
7272 basic_json_parser_60:
7273  yych = *++m_cursor;
7274  if (yych != 'l')
7275  {
7276  goto basic_json_parser_33;
7277  }
7278  yych = *++m_cursor;
7279  if (yych != 'l')
7280  {
7281  goto basic_json_parser_33;
7282  }
7283  ++m_cursor;
7284  {
7285  return token_type::literal_null;
7286  }
7287 basic_json_parser_64:
7288  yych = *++m_cursor;
7289  if (yych != 0xBF)
7290  {
7291  goto basic_json_parser_33;
7292  }
7293  ++m_cursor;
7294  {
7295  return scan();
7296  }
7297  }
7298 
7299 
7300  }
7301 
7303  void yyfill() noexcept
7304  {
7305  if (not m_stream or not * m_stream)
7306  {
7307  return;
7308  }
7309 
7310  const ssize_t offset_start = m_start - m_content;
7311  const ssize_t offset_marker = m_marker - m_start;
7312  const ssize_t offset_cursor = m_cursor - m_start;
7313 
7314  m_buffer.erase(0, static_cast<size_t>(offset_start));
7315  std::string line;
7316  std::getline(*m_stream, line);
7317  m_buffer += "\n" + line; // add line with newline symbol
7318 
7319  m_content = reinterpret_cast<const lexer_char_t*>(m_buffer.c_str());
7320  m_start = m_content;
7321  m_marker = m_start + offset_marker;
7322  m_cursor = m_start + offset_cursor;
7323  m_limit = m_start + m_buffer.size() - 1;
7324  }
7325 
7327  string_t get_token() const noexcept
7328  {
7329  return string_t(reinterpret_cast<typename string_t::const_pointer>(m_start),
7330  static_cast<size_t>(m_cursor - m_start));
7331  }
7332 
7354  string_t get_string() const
7355  {
7356  string_t result;
7357  result.reserve(static_cast<size_t>(m_cursor - m_start - 2));
7358 
7359  // iterate the result between the quotes
7360  for (const lexer_char_t* i = m_start + 1; i < m_cursor - 1; ++i)
7361  {
7362  // process escaped characters
7363  if (*i == '\\')
7364  {
7365  // read next character
7366  ++i;
7367 
7368  switch (*i)
7369  {
7370  // the default escapes
7371  case 't':
7372  {
7373  result += "\t";
7374  break;
7375  }
7376  case 'b':
7377  {
7378  result += "\b";
7379  break;
7380  }
7381  case 'f':
7382  {
7383  result += "\f";
7384  break;
7385  }
7386  case 'n':
7387  {
7388  result += "\n";
7389  break;
7390  }
7391  case 'r':
7392  {
7393  result += "\r";
7394  break;
7395  }
7396  case '\\':
7397  {
7398  result += "\\";
7399  break;
7400  }
7401  case '/':
7402  {
7403  result += "/";
7404  break;
7405  }
7406  case '"':
7407  {
7408  result += "\"";
7409  break;
7410  }
7411 
7412  // unicode
7413  case 'u':
7414  {
7415  // get code xxxx from uxxxx
7416  auto codepoint = std::strtoul(std::string(reinterpret_cast<typename string_t::const_pointer>(i + 1),
7417  4).c_str(), nullptr, 16);
7418 
7419  // check if codepoint is a high surrogate
7420  if (codepoint >= 0xD800 and codepoint <= 0xDBFF)
7421  {
7422  // make sure there is a subsequent unicode
7423  if ((i + 6 >= m_limit) or * (i + 5) != '\\' or * (i + 6) != 'u')
7424  {
7425  throw std::invalid_argument("missing low surrogate");
7426  }
7427 
7428  // get code yyyy from uxxxx\uyyyy
7429  auto codepoint2 = std::strtoul(std::string(reinterpret_cast<typename string_t::const_pointer>
7430  (i + 7), 4).c_str(), nullptr, 16);
7431  result += to_unicode(codepoint, codepoint2);
7432  // skip the next 10 characters (xxxx\uyyyy)
7433  i += 10;
7434  }
7435  else
7436  {
7437  // add unicode character(s)
7438  result += to_unicode(codepoint);
7439  // skip the next four characters (xxxx)
7440  i += 4;
7441  }
7442  break;
7443  }
7444  }
7445  }
7446  else
7447  {
7448  // all other characters are just copied to the end of the
7449  // string
7450  result.append(1, static_cast<typename string_t::value_type>(*i));
7451  }
7452  }
7453 
7454  return result;
7455  }
7456 
7474  long double get_number() const
7475  {
7476  // conversion
7477  typename string_t::value_type* endptr;
7478  const auto float_val = std::strtold(reinterpret_cast<typename string_t::const_pointer>(m_start),
7479  &endptr);
7480 
7481  // return float_val if the whole number was translated and NAN
7482  // otherwise
7483  return (reinterpret_cast<lexer_char_t*>(endptr) == m_cursor) ? float_val : NAN;
7484  }
7485 
7486  private:
7488  std::istream* m_stream;
7490  string_t m_buffer;
7492  const lexer_char_t* m_content = nullptr;
7494  const lexer_char_t* m_start = nullptr;
7496  const lexer_char_t* m_marker = nullptr;
7498  const lexer_char_t* m_cursor = nullptr;
7500  const lexer_char_t* m_limit = nullptr;
7501  };
7502 
7508  class parser
7509  {
7510  public:
7512  parser(const string_t& s, parser_callback_t cb = nullptr)
7513  : callback(cb), m_lexer(s)
7514  {
7515  // read first token
7516  get_token();
7517  }
7518 
7520  parser(std::istream& _is, parser_callback_t cb = nullptr)
7521  : callback(cb), m_lexer(&_is)
7522  {
7523  // read first token
7524  get_token();
7525  }
7526 
7528  basic_json parse()
7529  {
7530  basic_json result = parse_internal(true);
7531 
7532  expect(lexer::token_type::end_of_input);
7533 
7534  // return parser result and replace it with null in case the
7535  // top-level value was discarded by the callback function
7536  return result.is_discarded() ? basic_json() : result;
7537  }
7538 
7539  private:
7541  basic_json parse_internal(bool keep)
7542  {
7543  auto result = basic_json(value_t::discarded);
7544 
7545  switch (last_token)
7546  {
7547  case lexer::token_type::begin_object:
7548  {
7549  if (keep and (not callback or (keep = callback(depth++, parse_event_t::object_start, result))))
7550  {
7551  // explicitly set result to object to cope with {}
7552  result.m_type = value_t::object;
7553  result.m_value = json_value(value_t::object);
7554  }
7555 
7556  // read next token
7557  get_token();
7558 
7559  // closing } -> we are done
7560  if (last_token == lexer::token_type::end_object)
7561  {
7562  get_token();
7563  if (keep and callback and not callback(--depth, parse_event_t::object_end, result))
7564  {
7565  result = basic_json(value_t::discarded);
7566  }
7567  return result;
7568  }
7569 
7570  // no comma is expected here
7571  unexpect(lexer::token_type::value_separator);
7572 
7573  // otherwise: parse key-value pairs
7574  do
7575  {
7576  // ugly, but could be fixed with loop reorganization
7577  if (last_token == lexer::token_type::value_separator)
7578  {
7579  get_token();
7580  }
7581 
7582  // store key
7583  expect(lexer::token_type::value_string);
7584  const auto key = m_lexer.get_string();
7585 
7586  bool keep_tag = false;
7587  if (keep)
7588  {
7589  if (callback)
7590  {
7591  basic_json k(key);
7592  keep_tag = callback(depth, parse_event_t::key, k);
7593  }
7594  else
7595  {
7596  keep_tag = true;
7597  }
7598  }
7599 
7600  // parse separator (:)
7601  get_token();
7602  expect(lexer::token_type::name_separator);
7603 
7604  // parse and add value
7605  get_token();
7606  auto value = parse_internal(keep);
7607  if (keep and keep_tag and not value.is_discarded())
7608  {
7609  result[key] = std::move(value);
7610  }
7611  }
7612  while (last_token == lexer::token_type::value_separator);
7613 
7614  // closing }
7615  expect(lexer::token_type::end_object);
7616  get_token();
7617  if (keep and callback and not callback(--depth, parse_event_t::object_end, result))
7618  {
7619  result = basic_json(value_t::discarded);
7620  }
7621 
7622  return result;
7623  }
7624 
7625  case lexer::token_type::begin_array:
7626  {
7627  if (keep and (not callback or (keep = callback(depth++, parse_event_t::array_start, result))))
7628  {
7629  // explicitly set result to object to cope with []
7630  result.m_type = value_t::array;
7631  result.m_value = json_value(value_t::array);
7632  }
7633 
7634  // read next token
7635  get_token();
7636 
7637  // closing ] -> we are done
7638  if (last_token == lexer::token_type::end_array)
7639  {
7640  get_token();
7641  if (callback and not callback(--depth, parse_event_t::array_end, result))
7642  {
7643  result = basic_json(value_t::discarded);
7644  }
7645  return result;
7646  }
7647 
7648  // no comma is expected here
7649  unexpect(lexer::token_type::value_separator);
7650 
7651  // otherwise: parse values
7652  do
7653  {
7654  // ugly, but could be fixed with loop reorganization
7655  if (last_token == lexer::token_type::value_separator)
7656  {
7657  get_token();
7658  }
7659 
7660  // parse value
7661  auto value = parse_internal(keep);
7662  if (keep and not value.is_discarded())
7663  {
7664  result.push_back(std::move(value));
7665  }
7666  }
7667  while (last_token == lexer::token_type::value_separator);
7668 
7669  // closing ]
7670  expect(lexer::token_type::end_array);
7671  get_token();
7672  if (keep and callback and not callback(--depth, parse_event_t::array_end, result))
7673  {
7674  result = basic_json(value_t::discarded);
7675  }
7676 
7677  return result;
7678  }
7679 
7680  case lexer::token_type::literal_null:
7681  {
7682  get_token();
7683  result.m_type = value_t::null;
7684  break;
7685  }
7686 
7687  case lexer::token_type::value_string:
7688  {
7689  const auto s = m_lexer.get_string();
7690  get_token();
7691  result = basic_json(s);
7692  break;
7693  }
7694 
7695  case lexer::token_type::literal_true:
7696  {
7697  get_token();
7698  result.m_type = value_t::boolean;
7699  result.m_value = true;
7700  break;
7701  }
7702 
7703  case lexer::token_type::literal_false:
7704  {
7705  get_token();
7706  result.m_type = value_t::boolean;
7707  result.m_value = false;
7708  break;
7709  }
7710 
7711  case lexer::token_type::value_number:
7712  {
7713  auto float_val = m_lexer.get_number();
7714 
7715  // NAN is returned if token could not be translated
7716  // completely
7717  if (std::isnan(float_val))
7718  {
7719  throw std::invalid_argument(std::string("parse error - ") +
7720  m_lexer.get_token() + " is not a number");
7721  }
7722 
7723  get_token();
7724 
7725  // check if conversion loses precision
7726  const auto int_val = static_cast<number_integer_t>(float_val);
7727  if (approx(float_val, static_cast<long double>(int_val)))
7728  {
7729  // we would not lose precision -> return int
7730  result.m_type = value_t::number_integer;
7731  result.m_value = int_val;
7732  }
7733  else
7734  {
7735  // we would lose precision -> return float
7736  result.m_type = value_t::number_float;
7737  result.m_value = static_cast<number_float_t>(float_val);
7738  }
7739  break;
7740  }
7741 
7742  default:
7743  {
7744  // the last token was unexpected
7745  unexpect(last_token);
7746  }
7747  }
7748 
7749  if (keep and callback and not callback(depth, parse_event_t::value, result))
7750  {
7751  result = basic_json(value_t::discarded);
7752  }
7753  return result;
7754  }
7755 
7757  typename lexer::token_type get_token()
7758  {
7759  last_token = m_lexer.scan();
7760  return last_token;
7761  }
7762 
7763  void expect(typename lexer::token_type t) const
7764  {
7765  if (t != last_token)
7766  {
7767  std::string error_msg = "parse error - unexpected ";
7768  error_msg += (last_token == lexer::token_type::parse_error ? ("'" + m_lexer.get_token() + "'") :
7769  lexer::token_type_name(last_token));
7770  error_msg += "; expected " + lexer::token_type_name(t);
7771  throw std::invalid_argument(error_msg);
7772  }
7773  }
7774 
7775  void unexpect(typename lexer::token_type t) const
7776  {
7777  if (t == last_token)
7778  {
7779  std::string error_msg = "parse error - unexpected ";
7780  error_msg += (last_token == lexer::token_type::parse_error ? ("'" + m_lexer.get_token() + "'") :
7781  lexer::token_type_name(last_token));
7782  throw std::invalid_argument(error_msg);
7783  }
7784  }
7785 
7786  private:
7788  int depth = 0;
7790  parser_callback_t callback;
7792  typename lexer::token_type last_token = lexer::token_type::uninitialized;
7794  lexer m_lexer;
7795  };
7796 };
7797 
7798 
7800 // presets //
7802 
7812 }
7813 
7814 
7816 // nonmember functions //
7818 
7819 // specialization of std::swap, and std::hash
7820 namespace std
7821 {
7827 template <>
7828 inline void swap(nlohmann::json& j1,
7829  nlohmann::json& j2) noexcept(
7830  is_nothrow_move_constructible<nlohmann::json>::value and
7831  is_nothrow_move_assignable<nlohmann::json>::value
7832  )
7833 {
7834  j1.swap(j2);
7835 }
7836 
7838 template <>
7839 struct hash<nlohmann::json>
7840 {
7846  std::size_t operator()(const nlohmann::json& j) const
7847  {
7848  // a naive hashing via the string representation
7849  const auto& h = hash<nlohmann::json::string_t>();
7850  return h(j.dump());
7851  }
7852 };
7853 }
7854 
7867 inline nlohmann::json operator "" _json(const char* s, std::size_t)
7868 {
7869  return nlohmann::json::parse(reinterpret_cast<nlohmann::json::string_t::value_type*>
7870  (const_cast<char*>(s)));
7871 }
7872 
7873 #endif
json_reverse_iterator< typename basic_json::iterator > reverse_iterator
a reverse iterator for a basic_json container
Definition: json.hpp:239
bool operator!=(const const_iterator &other) const
comparison: not equal
Definition: json.hpp:5886
iterator insert(const_iterator pos, basic_json &&val)
inserts element
Definition: json.hpp:4256
iterator operator++(int)
post-increment (it++)
Definition: json.hpp:6124
friend bool operator<=(const_reference lhs, const_reference rhs) noexcept
comparison: less than or equal
Definition: json.hpp:4817
typename std::allocator_traits< allocator_type >::pointer pointer
the type of an element pointer
Definition: json.hpp:227
json_reverse_iterator operator-(difference_type i) const
subtract from iterator
Definition: json.hpp:6279
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:1507
const_reference operator[](size_type idx) const
access specified array element
Definition: json.hpp:2847
reference operator[](const T(&key)[n])
access specified object element
Definition: json.hpp:2977
typename basic_json::const_pointer pointer
defines a pointer to the type iterated over (value_type)
Definition: json.hpp:5588
static iteration_proxy< iterator > iterator_wrapper(reference cont)
wrapper to access iterator member functions in range-based for
Definition: json.hpp:3803
const_iterator & operator--()
pre-decrement (–it)
Definition: json.hpp:5831
friend std::istream & operator>>(std::istream &i, basic_json &j)
deserialize from stream
Definition: json.hpp:5030
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:5653
typename basic_json::value_type value_type
the type of the values when the iterator is dereferenced
Definition: json.hpp:5584
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:1771
iterator insert(const_iterator pos, const_iterator first, const_iterator last)
inserts elements
Definition: json.hpp:4337
iterator insert(const_iterator pos, size_type cnt, const basic_json &val)
inserts elements
Definition: json.hpp:4285
json_reverse_iterator operator--(int)
post-decrement (it–)
Definition: json.hpp:6251
StringType string_t
a type for a string
Definition: json.hpp:433
void push_back(const typename object_t::value_type &val)
add an object to an object
Definition: json.hpp:4179
basic_json(boolean_t val)
create a boolean (explicit)
Definition: json.hpp:1131
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:1467
iterator & operator++()
pre-increment (++it)
Definition: json.hpp:6132
friend bool operator!=(const_reference lhs, const_reference rhs) noexcept
comparison: not equal
Definition: json.hpp:4695
ArrayType< basic_json, AllocatorType< basic_json >> array_t
a type for an array
Definition: json.hpp:386
const_iterator & operator++()
pre-increment (++it)
Definition: json.hpp:5796
difference_type operator-(const json_reverse_iterator &other) const
return difference
Definition: json.hpp:6287
basic_json<> json
default JSON class
Definition: json.hpp:7811
reference front()
access the first element
Definition: json.hpp:3143
bool is_array() const noexcept
return whether value is an array
Definition: json.hpp:2084
const_iterator find(typename object_t::key_type key) const
find an element in a JSON object
Definition: json.hpp:3516
std::reverse_iterator< Base > base_iterator
shortcut to the reverse iterator adaptor
Definition: json.hpp:6223
json_reverse_iterator(const typename base_iterator::iterator_type &it)
create reverse iterator from iterator
Definition: json.hpp:6228
a class to store JSON values
Definition: json.hpp:187
json_reverse_iterator & operator--()
pre-decrement (–it)
Definition: json.hpp:6257
basic_json(const object_t &val)
create an object (explicit)
Definition: json.hpp:933
friend bool operator==(std::nullptr_t, const_reference v) noexcept
comparison: equal
Definition: json.hpp:4674
void push_back(basic_json &&val)
add an object to an array
Definition: json.hpp:4095
const_iterator cbegin() const
returns a const iterator to the first element
Definition: json.hpp:3614
bool is_string() const noexcept
return whether value is a string
Definition: json.hpp:2103
iterator & operator+=(difference_type i)
add to iterator
Definition: json.hpp:6154
const PointerType get_ptr() const noexcept
get a pointer value (implicit)
Definition: json.hpp:2542
basic_json(const CompatibleStringType &val)
create a string (implicit)
Definition: json.hpp:1113
the parser read ] and finished processing a JSON array
const_iterator base_iterator
Definition: json.hpp:6082
reference operator+=(basic_json &&val)
add an object to an array
Definition: json.hpp:4120
basic_json(size_type cnt, const basic_json &val)
construct an array with count copies of given value
Definition: json.hpp:1531
a mutable random access iterator for the basic_json class
Definition: json.hpp:6079
iterator & operator-=(difference_type i)
subtract from iterator
Definition: json.hpp:6161
static basic_json parse(std::istream &&i, parser_callback_t cb=nullptr)
deserialize from stream
Definition: json.hpp:4992
reference operator[](const typename object_t::key_type &key)
access specified object element
Definition: json.hpp:2887
STL namespace.
difference_type operator-(const iterator &other) const
Definition: json.hpp:6183
reference value() const
return the value of an iterator
Definition: json.hpp:6055
static iteration_proxy< const_iterator > iterator_wrapper(const_reference cont)
wrapper to access iterator member functions in range-based for
Definition: json.hpp:3811
const_iterator end() const
returns a const iterator to one past the last element
Definition: json.hpp:3649
const_iterator(const const_iterator &other) noexcept
copy constructor
Definition: json.hpp:5648
reference at(const typename object_t::key_type &key)
access specified object element with bounds checking
Definition: json.hpp:2710
object_t::key_type key() const
return the key of an object iterator
Definition: json.hpp:6042
iterator end()
returns an iterator to one past the last element
Definition: json.hpp:3639
ObjectType< StringType, basic_json, std::less< StringType >, AllocatorType< std::pair< const StringType, basic_json >>> object_t
a type for an object
Definition: json.hpp:340
reference operator*()
return a reference to the value pointed to by the iterator
Definition: json.hpp:6112
reverse_iterator rend()
returns an iterator to the reverse-end
Definition: json.hpp:3728
bool is_object() const noexcept
return whether value is an object
Definition: json.hpp:2065
const_iterator operator-(difference_type i)
subtract from iterator
Definition: json.hpp:5978
bool is_discarded() const noexcept
return whether value is discarded
Definition: json.hpp:2127
basic_json(const CompatibleArrayType &val)
create an array (implicit)
Definition: json.hpp:1029
typename basic_json::const_reference reference
defines a reference to the type iterated over (value_type)
Definition: json.hpp:5590
const_reverse_iterator rend() const
returns a const reverse iterator to one before the first
Definition: json.hpp:3736
size_type erase(const typename object_t::key_type &key)
remove element from a JSON object given a key
Definition: json.hpp:3428
bool is_boolean() const noexcept
return whether value is a boolean
Definition: json.hpp:1976
iterator begin()
returns an iterator to the first element
Definition: json.hpp:3580
const_reference at(const typename object_t::key_type &key) const
access specified object element with bounds checking
Definition: json.hpp:2757
reference operator+=(const basic_json &val)
add an object to an array
Definition: json.hpp:4153
AllocatorType< basic_json > allocator_type
the allocator type
Definition: json.hpp:224
basic_json(const number_float_t val)
create a floating-point number (explicit)
Definition: json.hpp:1258
bool is_number_integer() const noexcept
return whether value is an integer number
Definition: json.hpp:2023
iterator operator+(difference_type i)
add to iterator
Definition: json.hpp:6168
std::function< bool(int depth, parse_event_t event, basic_json &parsed)> parser_callback_t
per-element parser callback type
Definition: json.hpp:819
basic_json(const typename string_t::value_type *val)
create a string (explicit)
Definition: json.hpp:1082
const_iterator()=default
default constructor
the parser read [ and started to process a JSON array
iterator find(typename object_t::key_type key)
find an element in a JSON object
Definition: json.hpp:3500
basic_json(const value_t value_type)
create an empty value with a given type
Definition: json.hpp:866
friend bool operator>=(const_reference lhs, const_reference rhs) noexcept
comparison: greater than or equal
Definition: json.hpp:4861
iterator & operator--()
pre-decrement (–it)
Definition: json.hpp:6147
friend bool operator<(const_reference lhs, const_reference rhs) noexcept
comparison: less than
Definition: json.hpp:4756
pointer operator->() const
dereference the iterator
Definition: json.hpp:5759
discarded by the the parser callback function
const_reference operator[](const typename object_t::key_type &key) const
read-only access specified object element
Definition: json.hpp:2934
const_iterator cend() const
returns a const iterator to one past the last element
Definition: json.hpp:3673
typename Base::reference reference
the reference type for the pointed-to element
Definition: json.hpp:6225
size_type size() const noexcept
returns the number of elements
Definition: json.hpp:3911
static allocator_type get_allocator()
returns the allocator associated with the container
Definition: json.hpp:249
object (unordered set of name/value pairs)
reference at(size_type idx)
access specified array element with bounds checking
Definition: json.hpp:2620
the parser read } and finished processing a JSON object
iterator()=default
default constructor
json_reverse_iterator(const base_iterator &it)
create reverse iterator from base class
Definition: json.hpp:6233
value_t type() const noexcept
return the type of the JSON value (explicit)
Definition: json.hpp:1897
friend std::ostream & operator>>(const basic_json &j, std::ostream &o)
serialize to stream
Definition: json.hpp:4916
ValueType value(const typename object_t::key_type &key, ValueType default_value) const
access specified object element with default value
Definition: json.hpp:3092
object_t::key_type key() const
return the key of an object iterator
Definition: json.hpp:6299
bool is_structured() const noexcept
return whether type is structured
Definition: json.hpp:1938
namespace for Niels Lohmann
Definition: json.hpp:78
typename basic_json::difference_type difference_type
a type to represent differences between iterators
Definition: json.hpp:5586
void swap(array_t &other)
exchanges the values
Definition: json.hpp:4462
reverse_iterator rbegin()
returns an iterator to the reverse-beginning
Definition: json.hpp:3697
reference operator+=(const typename object_t::value_type &val)
add an object to an object
Definition: json.hpp:4202
reference operator[](difference_type n) const
access to successor
Definition: json.hpp:6189
std::size_t size_type
a type to represent container sizes
Definition: json.hpp:221
const_reverse_iterator rbegin() const
returns a const reverse iterator to the last element
Definition: json.hpp:3705
~basic_json()
destructor
Definition: json.hpp:1797
basic_json(const basic_json &other)
copy constructor
Definition: json.hpp:1675
const_iterator operator+(difference_type i)
add to iterator
Definition: json.hpp:5970
value_t
the JSON type enumeration
Definition: json.hpp:611
const value_type & const_reference
the type of an element const reference
Definition: json.hpp:215
basic_json(const CompatibleNumberIntegerType val) noexcept
create an integer number (implicit)
Definition: json.hpp:1229
bool is_null() const noexcept
return whether value is null
Definition: json.hpp:1957
void swap(string_t &other)
exchanges the values
Definition: json.hpp:4528
reference value() const
return the value of an iterator
Definition: json.hpp:6195
const_iterator operator--(int)
post-decrement (it–)
Definition: json.hpp:5823
void erase(const size_type idx)
remove element from a JSON array given an index
Definition: json.hpp:3465
void clear() noexcept
clears the contents
Definition: json.hpp:4028
pointer operator->()
dereference the iterator
Definition: json.hpp:6118
basic_json value_type
the type of elements in a basic_json container
Definition: json.hpp:209
array (ordered collection of values)
const_reference front() const
access the first element
Definition: json.hpp:3151
bool operator>=(const const_iterator &other) const
comparison: greater than or equal
Definition: json.hpp:5932
iterator insert(const_iterator pos, std::initializer_list< basic_json > ilist)
inserts elements
Definition: json.hpp:4394
std::ptrdiff_t difference_type
a type to represent differences between iterators
Definition: json.hpp:218
const_iterator & operator+=(difference_type i)
add to iterator
Definition: json.hpp:5938
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:1377
difference_type operator-(const const_iterator &other) const
return difference
Definition: json.hpp:5986
friend bool operator==(const_reference lhs, const_reference rhs) noexcept
comparison: equal
Definition: json.hpp:4607
bool is_number() const noexcept
return whether value is a number
Definition: json.hpp:2000
BooleanType boolean_t
a type for a boolean
Definition: json.hpp:459
const_reverse_iterator crend() const
returns a const reverse iterator to one before the first
Definition: json.hpp:3782
basic_json() noexcept=default
create a null object (implicitly)
the parser read a key of a value in an object
bool empty() const noexcept
checks whether the container is empty
Definition: json.hpp:3855
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:3118
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:4431
json_reverse_iterator< typename basic_json::const_iterator > const_reverse_iterator
a const reverse iterator for a basic_json container
Definition: json.hpp:241
const_reverse_iterator crbegin() const
returns a const reverse iterator to the last element
Definition: json.hpp:3759
reference value() const
return the value of an iterator
Definition: json.hpp:6306
const_iterator(pointer object)
constructor for a given JSON instance
Definition: json.hpp:5598
friend bool operator<(const value_t lhs, const value_t rhs)
comparison operator for JSON types
Definition: json.hpp:4561
iterator(pointer object) noexcept
constructor for a given JSON instance
Definition: json.hpp:6090
bool operator<(const const_iterator &other) const
comparison: smaller
Definition: json.hpp:5892
string_t dump(const int indent=-1) const
serialization
Definition: json.hpp:1866
friend bool operator!=(const_reference v, std::nullptr_t) noexcept
comparison: not equal
Definition: json.hpp:4718
const_iterator & operator-=(difference_type i)
subtract from iterator
Definition: json.hpp:5964
basic_json(const int val)
create an integer number from an enum type (explicit)
Definition: json.hpp:1194
basic_json(const array_t &val)
create an array (explicit)
Definition: json.hpp:992
number value (floating-point)
static basic_json parse(const string_t &s, parser_callback_t cb=nullptr)
deserialize from string
Definition: json.hpp:4955
InteratorType erase(InteratorType first, InteratorType last)
remove elements given an iterator range
Definition: json.hpp:3347
json_reverse_iterator operator++(int)
post-increment (it++)
Definition: json.hpp:6238
PointerType get_ptr() noexcept
get a pointer value (implicit)
Definition: json.hpp:2527
const_iterator(const iterator &other)
copy constructor given a nonconst iterator
Definition: json.hpp:5623
friend bool operator!=(std::nullptr_t, const_reference v) noexcept
comparison: not equal
Definition: json.hpp:4727
InteratorType erase(InteratorType pos)
remove element given an iterator
Definition: json.hpp:3244
bool operator<=(const const_iterator &other) const
comparison: less than or equal
Definition: json.hpp:5920
basic_json(const CompatibleNumberFloatType val) noexcept
create an floating-point number (implicit)
Definition: json.hpp:1304
reference back()
access the last element
Definition: json.hpp:3177
bool is_number_float() const noexcept
return whether value is a floating-point number
Definition: json.hpp:2046
the parser read { and started to process a JSON object
const_iterator operator++(int)
post-increment (it++)
Definition: json.hpp:5788
typename std::allocator_traits< allocator_type >::const_pointer const_pointer
the type of an element const pointer
Definition: json.hpp:229
basic_json(const string_t &val)
create a string (explicit)
Definition: json.hpp:1058
iterator(const iterator &other) noexcept
copy constructor
Definition: json.hpp:6095
const_reference back() const
access the last element
Definition: json.hpp:3187
basic_json(InputIT first, InputIT last)
construct a JSON container given an iterator range
Definition: json.hpp:1577
static basic_json parse(std::istream &i, parser_callback_t cb=nullptr)
deserialize from stream
Definition: json.hpp:4984
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:3546
size_type max_size() const noexcept
returns the maximum possible number of elements
Definition: json.hpp:3971
void push_back(const basic_json &val)
add an object to an array
Definition: json.hpp:4130
bool operator==(const const_iterator &other) const
comparison: equal
Definition: json.hpp:5858
json_reverse_iterator & operator++()
pre-increment (++it)
Definition: json.hpp:6244
bool operator>(const const_iterator &other) const
comparison: greater than
Definition: json.hpp:5926
friend bool operator>(const_reference lhs, const_reference rhs) noexcept
comparison: greater than
Definition: json.hpp:4839
basic_json(basic_json &&other) noexcept
move constructor
Definition: json.hpp:1741
const_reference operator[](const T(&key)[n]) const
read-only access specified object element
Definition: json.hpp:3027
const_iterator begin() const
returns a const iterator to the first element
Definition: json.hpp:3590
const_reference at(size_type idx) const
access specified array element with bounds checking
Definition: json.hpp:2663
json_reverse_iterator & operator+=(difference_type i)
add to iterator
Definition: json.hpp:6264
a const random access iterator for the basic_json class
Definition: json.hpp:5577
a template for a reverse iterator class
Definition: json.hpp:232
void swap(object_t &other)
exchanges the values
Definition: json.hpp:4495
std::bidirectional_iterator_tag iterator_category
the category of the iterator
Definition: json.hpp:5592
bool is_primitive() const noexcept
return whether type is primitive
Definition: json.hpp:1918
iterator insert(const_iterator pos, const basic_json &val)
inserts element
Definition: json.hpp:4230
friend bool operator==(const_reference v, std::nullptr_t) noexcept
comparison: equal
Definition: json.hpp:4665
reference operator[](difference_type n) const
access to successor
Definition: json.hpp:6293
NumberIntegerType number_integer_t
a type for a number (integer)
Definition: json.hpp:527
reference operator[](difference_type n) const
access to successor
Definition: json.hpp:6008
reference operator*() const
return a reference to the value pointed to by the iterator
Definition: json.hpp:5725
value_type & reference
the type of an element reference
Definition: json.hpp:212
friend std::istream & operator<<(basic_json &j, std::istream &i)
deserialize from stream
Definition: json.hpp:5020
the parser finished reading a JSON value
NumberFloatType number_float_t
a type for a number (floating-point)
Definition: json.hpp:592
std::size_t operator()(const nlohmann::json &j) const
return a hash value for a JSON object
Definition: json.hpp:7846
friend std::ostream & operator<<(std::ostream &o, const basic_json &j)
serialize to stream
Definition: json.hpp:4898
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:6100
basic_json(const CompatibleObjectType &val)
create an object (implicit)
Definition: json.hpp:965
reference operator[](size_type idx)
access specified array element
Definition: json.hpp:2803
iterator operator--(int)
post-decrement (it–)
Definition: json.hpp:6139
json_reverse_iterator operator+(difference_type i) const
add to iterator
Definition: json.hpp:6271
parse_event_t
JSON callback events.
Definition: json.hpp:754
iterator operator-(difference_type i)
subtract from iterator
Definition: json.hpp:6176