JSON for Modern C++  1.0.0-rc1
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 
3912  size_type size() const noexcept
3913  {
3914  switch (m_type)
3915  {
3916  case value_t::null:
3917  {
3918  // null values are empty
3919  return 0;
3920  }
3921 
3922  case value_t::array:
3923  {
3924  return m_value.array->size();
3925  }
3926 
3927  case value_t::object:
3928  {
3929  return m_value.object->size();
3930  }
3931 
3932  default:
3933  {
3934  // all other types have size 1
3935  return 1;
3936  }
3937  }
3938  }
3939 
3972  size_type max_size() const noexcept
3973  {
3974  switch (m_type)
3975  {
3976  case value_t::array:
3977  {
3978  return m_value.array->max_size();
3979  }
3980 
3981  case value_t::object:
3982  {
3983  return m_value.object->max_size();
3984  }
3985 
3986  default:
3987  {
3988  // all other types have max_size() == size()
3989  return size();
3990  }
3991  }
3992  }
3993 
3995 
3996 
3998  // modifiers //
4000 
4003 
4029  void clear() noexcept
4030  {
4031  switch (m_type)
4032  {
4034  {
4035  m_value.number_integer = 0;
4036  break;
4037  }
4038 
4039  case value_t::number_float:
4040  {
4041  m_value.number_float = 0.0;
4042  break;
4043  }
4044 
4045  case value_t::boolean:
4046  {
4047  m_value.boolean = false;
4048  break;
4049  }
4050 
4051  case value_t::string:
4052  {
4053  m_value.string->clear();
4054  break;
4055  }
4056 
4057  case value_t::array:
4058  {
4059  m_value.array->clear();
4060  break;
4061  }
4062 
4063  case value_t::object:
4064  {
4065  m_value.object->clear();
4066  break;
4067  }
4068 
4069  default:
4070  {
4071  break;
4072  }
4073  }
4074  }
4075 
4096  void push_back(basic_json&& val)
4097  {
4098  // push_back only works for null objects or arrays
4099  if (not(is_null() or is_array()))
4100  {
4101  throw std::domain_error("cannot use push_back() with " + type_name());
4102  }
4103 
4104  // transform null object into an array
4105  if (is_null())
4106  {
4107  m_type = value_t::array;
4108  m_value = value_t::array;
4109  }
4110 
4111  // add element to array (move semantics)
4112  m_value.array->push_back(std::move(val));
4113  // invalidate object
4114  val.m_type = value_t::null;
4115  }
4116 
4121  reference operator+=(basic_json&& val)
4122  {
4123  push_back(std::move(val));
4124  return *this;
4125  }
4126 
4131  void push_back(const basic_json& val)
4132  {
4133  // push_back only works for null objects or arrays
4134  if (not(is_null() or is_array()))
4135  {
4136  throw std::domain_error("cannot use push_back() with " + type_name());
4137  }
4138 
4139  // transform null object into an array
4140  if (is_null())
4141  {
4142  m_type = value_t::array;
4143  m_value = value_t::array;
4144  }
4145 
4146  // add element to array
4147  m_value.array->push_back(val);
4148  }
4149 
4154  reference operator+=(const basic_json& val)
4155  {
4156  push_back(val);
4157  return *this;
4158  }
4159 
4180  void push_back(const typename object_t::value_type& val)
4181  {
4182  // push_back only works for null objects or objects
4183  if (not(is_null() or is_object()))
4184  {
4185  throw std::domain_error("cannot use push_back() with " + type_name());
4186  }
4187 
4188  // transform null object into an object
4189  if (is_null())
4190  {
4191  m_type = value_t::object;
4192  m_value = value_t::object;
4193  }
4194 
4195  // add element to array
4196  m_value.object->insert(val);
4197  }
4198 
4203  reference operator+=(const typename object_t::value_type& val)
4204  {
4205  push_back(val);
4206  return operator[](val.first);
4207  }
4208 
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 
4284  iterator insert(const_iterator pos, size_type cnt, const basic_json& val)
4285  {
4286  // insert only works for arrays
4287  if (is_array())
4288  {
4289  // check if iterator pos fits to this JSON value
4290  if (pos.m_object != this)
4291  {
4292  throw std::domain_error("iterator does not fit current value");
4293  }
4294 
4295  // insert to array and return iterator
4296  iterator result(this);
4297  result.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator, cnt, val);
4298  return result;
4299  }
4300  else
4301  {
4302  throw std::domain_error("cannot use insert() with " + type_name());
4303  }
4304  }
4305 
4336  {
4337  // insert only works for arrays
4338  if (not is_array())
4339  {
4340  throw std::domain_error("cannot use insert() with " + type_name());
4341  }
4342 
4343  // check if iterator pos fits to this JSON value
4344  if (pos.m_object != this)
4345  {
4346  throw std::domain_error("iterator does not fit current value");
4347  }
4348 
4349  if (first.m_object != last.m_object)
4350  {
4351  throw std::domain_error("iterators do not fit");
4352  }
4353 
4354  if (first.m_object == this or last.m_object == this)
4355  {
4356  throw std::domain_error("passed iterators may not belong to container");
4357  }
4358 
4359  // insert to array and return iterator
4360  iterator result(this);
4361  result.m_it.array_iterator = m_value.array->insert(
4362  pos.m_it.array_iterator,
4363  first.m_it.array_iterator,
4364  last.m_it.array_iterator);
4365  return result;
4366  }
4367 
4390  iterator insert(const_iterator pos, std::initializer_list<basic_json> ilist)
4391  {
4392  // insert only works for arrays
4393  if (not is_array())
4394  {
4395  throw std::domain_error("cannot use insert() with " + type_name());
4396  }
4397 
4398  // check if iterator pos fits to this JSON value
4399  if (pos.m_object != this)
4400  {
4401  throw std::domain_error("iterator does not fit current value");
4402  }
4403 
4404  // insert to array and return iterator
4405  iterator result(this);
4406  result.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator, ilist);
4407  return result;
4408  }
4409 
4427  void swap(reference other) noexcept (
4428  std::is_nothrow_move_constructible<value_t>::value and
4429  std::is_nothrow_move_assignable<value_t>::value and
4430  std::is_nothrow_move_constructible<json_value>::value and
4431  std::is_nothrow_move_assignable<json_value>::value
4432  )
4433  {
4434  std::swap(m_type, other.m_type);
4435  std::swap(m_value, other.m_value);
4436  }
4437 
4457  void swap(array_t& other)
4458  {
4459  // swap only works for arrays
4460  if (is_array())
4461  {
4462  std::swap(*(m_value.array), other);
4463  }
4464  else
4465  {
4466  throw std::domain_error("cannot use swap() with " + type_name());
4467  }
4468  }
4469 
4489  void swap(object_t& other)
4490  {
4491  // swap only works for objects
4492  if (is_object())
4493  {
4494  std::swap(*(m_value.object), other);
4495  }
4496  else
4497  {
4498  throw std::domain_error("cannot use swap() with " + type_name());
4499  }
4500  }
4501 
4521  void swap(string_t& other)
4522  {
4523  // swap only works for strings
4524  if (is_string())
4525  {
4526  std::swap(*(m_value.string), other);
4527  }
4528  else
4529  {
4530  throw std::domain_error("cannot use swap() with " + type_name());
4531  }
4532  }
4533 
4535 
4536 
4538  // lexicographical comparison operators //
4540 
4543 
4544  private:
4554  friend bool operator<(const value_t lhs, const value_t rhs)
4555  {
4556  static constexpr std::array<uint8_t, 7> order = {{
4557  0, // null
4558  3, // object
4559  4, // array
4560  5, // string
4561  1, // boolean
4562  2, // integer
4563  2 // float
4564  }
4565  };
4566 
4567  // discarded values are not comparable
4568  if (lhs == value_t::discarded or rhs == value_t::discarded)
4569  {
4570  return false;
4571  }
4572 
4573  return order[static_cast<std::size_t>(lhs)] < order[static_cast<std::size_t>(rhs)];
4574  }
4575 
4576  public:
4600  friend bool operator==(const_reference lhs, const_reference rhs) noexcept
4601  {
4602  const auto lhs_type = lhs.type();
4603  const auto rhs_type = rhs.type();
4604 
4605  if (lhs_type == rhs_type)
4606  {
4607  switch (lhs_type)
4608  {
4609  case value_t::array:
4610  return *lhs.m_value.array == *rhs.m_value.array;
4611  case value_t::object:
4612  return *lhs.m_value.object == *rhs.m_value.object;
4613  case value_t::null:
4614  return true;
4615  case value_t::string:
4616  return *lhs.m_value.string == *rhs.m_value.string;
4617  case value_t::boolean:
4618  return lhs.m_value.boolean == rhs.m_value.boolean;
4620  return lhs.m_value.number_integer == rhs.m_value.number_integer;
4621  case value_t::number_float:
4622  return approx(lhs.m_value.number_float, rhs.m_value.number_float);
4623  default:
4624  return false;
4625  }
4626  }
4627  else if (lhs_type == value_t::number_integer and rhs_type == value_t::number_float)
4628  {
4629  return approx(static_cast<number_float_t>(lhs.m_value.number_integer),
4630  rhs.m_value.number_float);
4631  }
4632  else if (lhs_type == value_t::number_float and rhs_type == value_t::number_integer)
4633  {
4634  return approx(lhs.m_value.number_float,
4635  static_cast<number_float_t>(rhs.m_value.number_integer));
4636  }
4637  return false;
4638  }
4639 
4658  friend bool operator==(const_reference v, std::nullptr_t) noexcept
4659  {
4660  return v.is_null();
4661  }
4662 
4667  friend bool operator==(std::nullptr_t, const_reference v) noexcept
4668  {
4669  return v.is_null();
4670  }
4671 
4688  friend bool operator!=(const_reference lhs, const_reference rhs) noexcept
4689  {
4690  return not (lhs == rhs);
4691  }
4692 
4711  friend bool operator!=(const_reference v, std::nullptr_t) noexcept
4712  {
4713  return not v.is_null();
4714  }
4715 
4720  friend bool operator!=(std::nullptr_t, const_reference v) noexcept
4721  {
4722  return not v.is_null();
4723  }
4724 
4749  friend bool operator<(const_reference lhs, const_reference rhs) noexcept
4750  {
4751  const auto lhs_type = lhs.type();
4752  const auto rhs_type = rhs.type();
4753 
4754  if (lhs_type == rhs_type)
4755  {
4756  switch (lhs_type)
4757  {
4758  case value_t::array:
4759  return *lhs.m_value.array < *rhs.m_value.array;
4760  case value_t::object:
4761  return *lhs.m_value.object < *rhs.m_value.object;
4762  case value_t::null:
4763  return false;
4764  case value_t::string:
4765  return *lhs.m_value.string < *rhs.m_value.string;
4766  case value_t::boolean:
4767  return lhs.m_value.boolean < rhs.m_value.boolean;
4769  return lhs.m_value.number_integer < rhs.m_value.number_integer;
4770  case value_t::number_float:
4771  return lhs.m_value.number_float < rhs.m_value.number_float;
4772  default:
4773  return false;
4774  }
4775  }
4776  else if (lhs_type == value_t::number_integer and rhs_type == value_t::number_float)
4777  {
4778  return static_cast<number_float_t>(lhs.m_value.number_integer) <
4779  rhs.m_value.number_float;
4780  }
4781  else if (lhs_type == value_t::number_float and rhs_type == value_t::number_integer)
4782  {
4783  return lhs.m_value.number_float <
4784  static_cast<number_float_t>(rhs.m_value.number_integer);
4785  }
4786 
4787  // We only reach this line if we cannot compare values. In that case,
4788  // we compare types. Note we have to call the operator explicitly,
4789  // because MSVC has problems otherwise.
4790  return operator<(lhs_type, rhs_type);
4791  }
4792 
4810  friend bool operator<=(const_reference lhs, const_reference rhs) noexcept
4811  {
4812  return not (rhs < lhs);
4813  }
4814 
4832  friend bool operator>(const_reference lhs, const_reference rhs) noexcept
4833  {
4834  return not (lhs <= rhs);
4835  }
4836 
4854  friend bool operator>=(const_reference lhs, const_reference rhs) noexcept
4855  {
4856  return not (lhs < rhs);
4857  }
4858 
4860 
4861 
4863  // serialization //
4865 
4868 
4891  friend std::ostream& operator<<(std::ostream& o, const basic_json& j)
4892  {
4893  // read width member and use it as indentation parameter if nonzero
4894  const bool pretty_print = (o.width() > 0);
4895  const auto indentation = (pretty_print ? o.width() : 0);
4896 
4897  // reset width to 0 for subsequent calls to this stream
4898  o.width(0);
4899 
4900  // do the actual serialization
4901  j.dump(o, pretty_print, static_cast<unsigned int>(indentation));
4902  return o;
4903  }
4904 
4909  friend std::ostream& operator>>(const basic_json& j, std::ostream& o)
4910  {
4911  return o << j;
4912  }
4913 
4915 
4916 
4918  // deserialization //
4920 
4923 
4948  static basic_json parse(const string_t& s, parser_callback_t cb = nullptr)
4949  {
4950  return parser(s, cb).parse();
4951  }
4952 
4977  static basic_json parse(std::istream& i, parser_callback_t cb = nullptr)
4978  {
4979  return parser(i, cb).parse();
4980  }
4981 
4985  static basic_json parse(std::istream&& i, parser_callback_t cb = nullptr)
4986  {
4987  return parser(i, cb).parse();
4988  }
4989 
5013  friend std::istream& operator<<(basic_json& j, std::istream& i)
5014  {
5015  j = parser(i).parse();
5016  return i;
5017  }
5018 
5023  friend std::istream& operator>>(std::istream& i, basic_json& j)
5024  {
5025  j = parser(i).parse();
5026  return i;
5027  }
5028 
5030 
5031 
5032  private:
5034  // convenience functions //
5036 
5038  string_t type_name() const
5039  {
5040  switch (m_type)
5041  {
5042  case value_t::null:
5043  return "null";
5044  case value_t::object:
5045  return "object";
5046  case value_t::array:
5047  return "array";
5048  case value_t::string:
5049  return "string";
5050  case value_t::boolean:
5051  return "boolean";
5052  case value_t::discarded:
5053  return "discarded";
5054  default:
5055  return "number";
5056  }
5057  }
5058 
5067  static std::size_t extra_space(const string_t& s) noexcept
5068  {
5069  std::size_t result = 0;
5070 
5071  for (const auto& c : s)
5072  {
5073  switch (c)
5074  {
5075  case '"':
5076  case '\\':
5077  case '\b':
5078  case '\f':
5079  case '\n':
5080  case '\r':
5081  case '\t':
5082  {
5083  // from c (1 byte) to \x (2 bytes)
5084  result += 1;
5085  break;
5086  }
5087 
5088  default:
5089  {
5090  if (c >= 0x00 and c <= 0x1f)
5091  {
5092  // from c (1 byte) to \uxxxx (6 bytes)
5093  result += 5;
5094  }
5095  break;
5096  }
5097  }
5098  }
5099 
5100  return result;
5101  }
5102 
5116  static string_t escape_string(const string_t& s) noexcept
5117  {
5118  const auto space = extra_space(s);
5119  if (space == 0)
5120  {
5121  return s;
5122  }
5123 
5124  // create a result string of necessary size
5125  string_t result(s.size() + space, '\\');
5126  std::size_t pos = 0;
5127 
5128  for (const auto& c : s)
5129  {
5130  switch (c)
5131  {
5132  // quotation mark (0x22)
5133  case '"':
5134  {
5135  result[pos + 1] = '"';
5136  pos += 2;
5137  break;
5138  }
5139 
5140  // reverse solidus (0x5c)
5141  case '\\':
5142  {
5143  // nothing to change
5144  pos += 2;
5145  break;
5146  }
5147 
5148  // backspace (0x08)
5149  case '\b':
5150  {
5151  result[pos + 1] = 'b';
5152  pos += 2;
5153  break;
5154  }
5155 
5156  // formfeed (0x0c)
5157  case '\f':
5158  {
5159  result[pos + 1] = 'f';
5160  pos += 2;
5161  break;
5162  }
5163 
5164  // newline (0x0a)
5165  case '\n':
5166  {
5167  result[pos + 1] = 'n';
5168  pos += 2;
5169  break;
5170  }
5171 
5172  // carriage return (0x0d)
5173  case '\r':
5174  {
5175  result[pos + 1] = 'r';
5176  pos += 2;
5177  break;
5178  }
5179 
5180  // horizontal tab (0x09)
5181  case '\t':
5182  {
5183  result[pos + 1] = 't';
5184  pos += 2;
5185  break;
5186  }
5187 
5188  default:
5189  {
5190  if (c >= 0x00 and c <= 0x1f)
5191  {
5192  // convert a number 0..15 to its hex representation (0..f)
5193  auto hexify = [](const char v) -> char
5194  {
5195  return (v < 10) ? ('0' + v) : ('a' + v - 10);
5196  };
5197 
5198  // print character c as \uxxxx
5199  for (const char m :
5200  { 'u', '0', '0', hexify(c >> 4), hexify(c & 0x0f)
5201  })
5202  {
5203  result[++pos] = m;
5204  }
5205 
5206  ++pos;
5207  }
5208  else
5209  {
5210  // all other characters are added as-is
5211  result[pos++] = c;
5212  }
5213  break;
5214  }
5215  }
5216  }
5217 
5218  return result;
5219  }
5220 
5238  void dump(std::ostream& o,
5239  const bool pretty_print,
5240  const unsigned int indent_step,
5241  const unsigned int current_indent = 0) const
5242  {
5243  // variable to hold indentation for recursive calls
5244  unsigned int new_indent = current_indent;
5245 
5246  switch (m_type)
5247  {
5248  case value_t::object:
5249  {
5250  if (m_value.object->empty())
5251  {
5252  o << "{}";
5253  return;
5254  }
5255 
5256  o << "{";
5257 
5258  // increase indentation
5259  if (pretty_print)
5260  {
5261  new_indent += indent_step;
5262  o << "\n";
5263  }
5264 
5265  for (auto i = m_value.object->cbegin(); i != m_value.object->cend(); ++i)
5266  {
5267  if (i != m_value.object->cbegin())
5268  {
5269  o << (pretty_print ? ",\n" : ",");
5270  }
5271  o << string_t(new_indent, ' ') << "\""
5272  << escape_string(i->first) << "\":"
5273  << (pretty_print ? " " : "");
5274  i->second.dump(o, pretty_print, indent_step, new_indent);
5275  }
5276 
5277  // decrease indentation
5278  if (pretty_print)
5279  {
5280  new_indent -= indent_step;
5281  o << "\n";
5282  }
5283 
5284  o << string_t(new_indent, ' ') + "}";
5285  return;
5286  }
5287 
5288  case value_t::array:
5289  {
5290  if (m_value.array->empty())
5291  {
5292  o << "[]";
5293  return;
5294  }
5295 
5296  o << "[";
5297 
5298  // increase indentation
5299  if (pretty_print)
5300  {
5301  new_indent += indent_step;
5302  o << "\n";
5303  }
5304 
5305  for (auto i = m_value.array->cbegin(); i != m_value.array->cend(); ++i)
5306  {
5307  if (i != m_value.array->cbegin())
5308  {
5309  o << (pretty_print ? ",\n" : ",");
5310  }
5311  o << string_t(new_indent, ' ');
5312  i->dump(o, pretty_print, indent_step, new_indent);
5313  }
5314 
5315  // decrease indentation
5316  if (pretty_print)
5317  {
5318  new_indent -= indent_step;
5319  o << "\n";
5320  }
5321 
5322  o << string_t(new_indent, ' ') << "]";
5323  return;
5324  }
5325 
5326  case value_t::string:
5327  {
5328  o << string_t("\"") << escape_string(*m_value.string) << "\"";
5329  return;
5330  }
5331 
5332  case value_t::boolean:
5333  {
5334  o << (m_value.boolean ? "true" : "false");
5335  return;
5336  }
5337 
5339  {
5340  o << m_value.number_integer;
5341  return;
5342  }
5343 
5344  case value_t::number_float:
5345  {
5346  // 15 digits of precision allows round-trip IEEE 754
5347  // string->double->string; to be safe, we read this value from
5348  // std::numeric_limits<number_float_t>::digits10
5349  o << std::setprecision(std::numeric_limits<number_float_t>::digits10) << m_value.number_float;
5350  return;
5351  }
5352 
5353  case value_t::discarded:
5354  {
5355  o << "<discarded>";
5356  return;
5357  }
5358 
5359  case value_t::null:
5360  {
5361  o << "null";
5362  return;
5363  }
5364  }
5365  }
5366 
5367  private:
5369  // member variables //
5371 
5373  value_t m_type = value_t::null;
5374 
5376  json_value m_value = {};
5377 
5378 
5379  private:
5381  // iterators //
5383 
5393  class primitive_iterator_t
5394  {
5395  public:
5397  void set_begin()
5398  {
5399  m_it = begin_value;
5400  }
5401 
5403  void set_end()
5404  {
5405  m_it = end_value;
5406  }
5407 
5409  bool is_begin() const
5410  {
5411  return (m_it == begin_value);
5412  }
5413 
5415  bool is_end() const
5416  {
5417  return (m_it == end_value);
5418  }
5419 
5421  operator difference_type& ()
5422  {
5423  return m_it;
5424  }
5425 
5427  operator difference_type () const
5428  {
5429  return m_it;
5430  }
5431 
5432  private:
5433  static constexpr difference_type begin_value = 0;
5434  static constexpr difference_type end_value = begin_value + 1;
5435 
5437  difference_type m_it = std::numeric_limits<std::ptrdiff_t>::denorm_min();
5438  };
5439 
5447  struct internal_iterator
5448  {
5450  typename object_t::iterator object_iterator;
5452  typename array_t::iterator array_iterator;
5454  primitive_iterator_t primitive_iterator;
5455 
5457  internal_iterator()
5458  : object_iterator(), array_iterator(), primitive_iterator()
5459  {}
5460  };
5461 
5463  template<typename IteratorType>
5464  class iteration_proxy
5465  {
5466  private:
5468  class iteration_proxy_internal
5469  {
5470  private:
5472  IteratorType anchor;
5474  size_t array_index = 0;
5475 
5476  public:
5477  iteration_proxy_internal(IteratorType it)
5478  : anchor(it)
5479  {}
5480 
5482  iteration_proxy_internal& operator*()
5483  {
5484  return *this;
5485  }
5486 
5488  iteration_proxy_internal& operator++()
5489  {
5490  ++anchor;
5491  ++array_index;
5492 
5493  return *this;
5494  }
5495 
5497  bool operator!= (const iteration_proxy_internal& o)
5498  {
5499  return anchor != o.anchor;
5500  }
5501 
5503  typename basic_json::string_t key() const
5504  {
5505  switch (anchor.m_object->type())
5506  {
5507  // use integer array index as key
5508  case value_t::array:
5509  {
5510  return std::to_string(array_index);
5511  }
5512 
5513  // use key from the object
5514  case value_t::object:
5515  {
5516  return anchor.key();
5517  }
5518 
5519  // use an empty key for all primitive types
5520  default:
5521  {
5522  return "";
5523  }
5524  }
5525  }
5526 
5528  typename IteratorType::reference value() const
5529  {
5530  return anchor.value();
5531  }
5532  };
5533 
5535  typename IteratorType::reference container;
5536 
5537  public:
5539  iteration_proxy(typename IteratorType::reference cont)
5540  : container(cont)
5541  {}
5542 
5544  iteration_proxy_internal begin()
5545  {
5546  return iteration_proxy_internal(container.begin());
5547  }
5548 
5550  iteration_proxy_internal end()
5551  {
5552  return iteration_proxy_internal(container.end());
5553  }
5554  };
5555 
5556  public:
5570  class const_iterator : public std::iterator<std::random_access_iterator_tag, const basic_json>
5571  {
5573  friend class basic_json;
5574 
5575  public:
5585  using iterator_category = std::bidirectional_iterator_tag;
5586 
5588  const_iterator() = default;
5589 
5591  const_iterator(pointer object) : m_object(object)
5592  {
5593  switch (m_object->m_type)
5594  {
5596  {
5597  m_it.object_iterator = typename object_t::iterator();
5598  break;
5599  }
5600 
5602  {
5603  m_it.array_iterator = typename array_t::iterator();
5604  break;
5605  }
5606 
5607  default:
5608  {
5609  m_it.primitive_iterator = primitive_iterator_t();
5610  break;
5611  }
5612  }
5613  }
5614 
5616  const_iterator(const iterator& other) : m_object(other.m_object)
5617  {
5618  switch (m_object->m_type)
5619  {
5621  {
5622  m_it.object_iterator = other.m_it.object_iterator;
5623  break;
5624  }
5625 
5627  {
5628  m_it.array_iterator = other.m_it.array_iterator;
5629  break;
5630  }
5631 
5632  default:
5633  {
5634  m_it.primitive_iterator = other.m_it.primitive_iterator;
5635  break;
5636  }
5637  }
5638  }
5639 
5641  const_iterator(const const_iterator& other) noexcept
5642  : m_object(other.m_object), m_it(other.m_it)
5643  {}
5644 
5647  std::is_nothrow_move_constructible<pointer>::value and
5648  std::is_nothrow_move_assignable<pointer>::value and
5649  std::is_nothrow_move_constructible<internal_iterator>::value and
5650  std::is_nothrow_move_assignable<internal_iterator>::value
5651  )
5652  {
5653  std::swap(m_object, other.m_object);
5654  std::swap(m_it, other.m_it);
5655  return *this;
5656  }
5657 
5658  private:
5660  void set_begin()
5661  {
5662  switch (m_object->m_type)
5663  {
5665  {
5666  m_it.object_iterator = m_object->m_value.object->begin();
5667  break;
5668  }
5669 
5671  {
5672  m_it.array_iterator = m_object->m_value.array->begin();
5673  break;
5674  }
5675 
5677  {
5678  // set to end so begin()==end() is true: null is empty
5679  m_it.primitive_iterator.set_end();
5680  break;
5681  }
5682 
5683  default:
5684  {
5685  m_it.primitive_iterator.set_begin();
5686  break;
5687  }
5688  }
5689  }
5690 
5692  void set_end()
5693  {
5694  switch (m_object->m_type)
5695  {
5697  {
5698  m_it.object_iterator = m_object->m_value.object->end();
5699  break;
5700  }
5701 
5703  {
5704  m_it.array_iterator = m_object->m_value.array->end();
5705  break;
5706  }
5707 
5708  default:
5709  {
5710  m_it.primitive_iterator.set_end();
5711  break;
5712  }
5713  }
5714  }
5715 
5716  public:
5719  {
5720  switch (m_object->m_type)
5721  {
5723  {
5724  return m_it.object_iterator->second;
5725  }
5726 
5728  {
5729  return *m_it.array_iterator;
5730  }
5731 
5733  {
5734  throw std::out_of_range("cannot get value");
5735  }
5736 
5737  default:
5738  {
5739  if (m_it.primitive_iterator.is_begin())
5740  {
5741  return *m_object;
5742  }
5743  else
5744  {
5745  throw std::out_of_range("cannot get value");
5746  }
5747  }
5748  }
5749  }
5750 
5753  {
5754  switch (m_object->m_type)
5755  {
5757  {
5758  return &(m_it.object_iterator->second);
5759  }
5760 
5762  {
5763  return &*m_it.array_iterator;
5764  }
5765 
5766  default:
5767  {
5768  if (m_it.primitive_iterator.is_begin())
5769  {
5770  return m_object;
5771  }
5772  else
5773  {
5774  throw std::out_of_range("cannot get value");
5775  }
5776  }
5777  }
5778  }
5779 
5782  {
5783  auto result = *this;
5784  ++(*this);
5785  return result;
5786  }
5787 
5790  {
5791  switch (m_object->m_type)
5792  {
5794  {
5795  ++m_it.object_iterator;
5796  break;
5797  }
5798 
5800  {
5801  ++m_it.array_iterator;
5802  break;
5803  }
5804 
5805  default:
5806  {
5807  ++m_it.primitive_iterator;
5808  break;
5809  }
5810  }
5811 
5812  return *this;
5813  }
5814 
5817  {
5818  auto result = *this;
5819  --(*this);
5820  return result;
5821  }
5822 
5825  {
5826  switch (m_object->m_type)
5827  {
5829  {
5830  --m_it.object_iterator;
5831  break;
5832  }
5833 
5835  {
5836  --m_it.array_iterator;
5837  break;
5838  }
5839 
5840  default:
5841  {
5842  --m_it.primitive_iterator;
5843  break;
5844  }
5845  }
5846 
5847  return *this;
5848  }
5849 
5851  bool operator==(const const_iterator& other) const
5852  {
5853  // if objects are not the same, the comparison is undefined
5854  if (m_object != other.m_object)
5855  {
5856  throw std::domain_error("cannot compare iterators of different containers");
5857  }
5858 
5859  switch (m_object->m_type)
5860  {
5862  {
5863  return (m_it.object_iterator == other.m_it.object_iterator);
5864  }
5865 
5867  {
5868  return (m_it.array_iterator == other.m_it.array_iterator);
5869  }
5870 
5871  default:
5872  {
5873  return (m_it.primitive_iterator == other.m_it.primitive_iterator);
5874  }
5875  }
5876  }
5877 
5879  bool operator!=(const const_iterator& other) const
5880  {
5881  return not operator==(other);
5882  }
5883 
5885  bool operator<(const const_iterator& other) const
5886  {
5887  // if objects are not the same, the comparison is undefined
5888  if (m_object != other.m_object)
5889  {
5890  throw std::domain_error("cannot compare iterators of different containers");
5891  }
5892 
5893  switch (m_object->m_type)
5894  {
5896  {
5897  throw std::domain_error("cannot compare order of object iterators");
5898  }
5899 
5901  {
5902  return (m_it.array_iterator < other.m_it.array_iterator);
5903  }
5904 
5905  default:
5906  {
5907  return (m_it.primitive_iterator < other.m_it.primitive_iterator);
5908  }
5909  }
5910  }
5911 
5913  bool operator<=(const const_iterator& other) const
5914  {
5915  return not other.operator < (*this);
5916  }
5917 
5919  bool operator>(const const_iterator& other) const
5920  {
5921  return not operator<=(other);
5922  }
5923 
5925  bool operator>=(const const_iterator& other) const
5926  {
5927  return not operator<(other);
5928  }
5929 
5932  {
5933  switch (m_object->m_type)
5934  {
5936  {
5937  throw std::domain_error("cannot use offsets with object iterators");
5938  }
5939 
5941  {
5942  m_it.array_iterator += i;
5943  break;
5944  }
5945 
5946  default:
5947  {
5948  m_it.primitive_iterator += i;
5949  break;
5950  }
5951  }
5952 
5953  return *this;
5954  }
5955 
5958  {
5959  return operator+=(-i);
5960  }
5961 
5964  {
5965  auto result = *this;
5966  result += i;
5967  return result;
5968  }
5969 
5972  {
5973  auto result = *this;
5974  result -= i;
5975  return result;
5976  }
5977 
5980  {
5981  switch (m_object->m_type)
5982  {
5984  {
5985  throw std::domain_error("cannot use offsets with object iterators");
5986  }
5987 
5989  {
5990  return m_it.array_iterator - other.m_it.array_iterator;
5991  }
5992 
5993  default:
5994  {
5995  return m_it.primitive_iterator - other.m_it.primitive_iterator;
5996  }
5997  }
5998  }
5999 
6002  {
6003  switch (m_object->m_type)
6004  {
6006  {
6007  throw std::domain_error("cannot use operator[] for object iterators");
6008  }
6009 
6011  {
6012  return *(m_it.array_iterator + n);
6013  }
6014 
6016  {
6017  throw std::out_of_range("cannot get value");
6018  }
6019 
6020  default:
6021  {
6022  if (m_it.primitive_iterator == -n)
6023  {
6024  return *m_object;
6025  }
6026  else
6027  {
6028  throw std::out_of_range("cannot get value");
6029  }
6030  }
6031  }
6032  }
6033 
6035  typename object_t::key_type key() const
6036  {
6037  if (m_object->is_object())
6038  {
6039  return m_it.object_iterator->first;
6040  }
6041  else
6042  {
6043  throw std::domain_error("cannot use key() for non-object iterators");
6044  }
6045  }
6046 
6049  {
6050  return operator*();
6051  }
6052 
6053  private:
6055  pointer m_object = nullptr;
6057  internal_iterator m_it = internal_iterator();
6058  };
6059 
6072  class iterator : public const_iterator
6073  {
6074  public:
6076  using pointer = typename basic_json::pointer;
6078 
6080  iterator() = default;
6081 
6083  iterator(pointer object) noexcept
6084  : base_iterator(object)
6085  {}
6086 
6088  iterator(const iterator& other) noexcept
6089  : base_iterator(other)
6090  {}
6091 
6093  iterator& operator=(iterator other) noexcept(
6094  std::is_nothrow_move_constructible<pointer>::value and
6095  std::is_nothrow_move_assignable<pointer>::value and
6096  std::is_nothrow_move_constructible<internal_iterator>::value and
6097  std::is_nothrow_move_assignable<internal_iterator>::value
6098  )
6099  {
6100  base_iterator::operator=(other);
6101  return *this;
6102  }
6103 
6106  {
6107  return const_cast<reference>(base_iterator::operator*());
6108  }
6109 
6112  {
6113  return const_cast<pointer>(base_iterator::operator->());
6114  }
6115 
6118  {
6119  iterator result = *this;
6121  return result;
6122  }
6123 
6126  {
6128  return *this;
6129  }
6130 
6133  {
6134  iterator result = *this;
6136  return result;
6137  }
6138 
6141  {
6143  return *this;
6144  }
6145 
6148  {
6150  return *this;
6151  }
6152 
6155  {
6157  return *this;
6158  }
6159 
6162  {
6163  auto result = *this;
6164  result += i;
6165  return result;
6166  }
6167 
6170  {
6171  auto result = *this;
6172  result -= i;
6173  return result;
6174  }
6175 
6176  difference_type operator-(const iterator& other) const
6177  {
6178  return base_iterator::operator-(other);
6179  }
6180 
6183  {
6184  return const_cast<reference>(base_iterator::operator[](n));
6185  }
6186 
6189  {
6190  return const_cast<reference>(base_iterator::value());
6191  }
6192  };
6193 
6211  template<typename Base>
6212  class json_reverse_iterator : public std::reverse_iterator<Base>
6213  {
6214  public:
6216  using base_iterator = std::reverse_iterator<Base>;
6218  using reference = typename Base::reference;
6219 
6221  json_reverse_iterator(const typename base_iterator::iterator_type& it)
6222  : base_iterator(it)
6223  {}
6224 
6227  : base_iterator(it)
6228  {}
6229 
6232  {
6233  return base_iterator::operator++(1);
6234  }
6235 
6238  {
6239  base_iterator::operator++();
6240  return *this;
6241  }
6242 
6245  {
6246  return base_iterator::operator--(1);
6247  }
6248 
6251  {
6252  base_iterator::operator--();
6253  return *this;
6254  }
6255 
6258  {
6259  base_iterator::operator+=(i);
6260  return *this;
6261  }
6262 
6265  {
6266  auto result = *this;
6267  result += i;
6268  return result;
6269  }
6270 
6273  {
6274  auto result = *this;
6275  result -= i;
6276  return result;
6277  }
6278 
6281  {
6282  return this->base() - other.base();
6283  }
6284 
6287  {
6288  return *(this->operator+(n));
6289  }
6290 
6292  typename object_t::key_type key() const
6293  {
6294  auto it = --this->base();
6295  return it.key();
6296  }
6297 
6300  {
6301  auto it = --this->base();
6302  return it.operator * ();
6303  }
6304  };
6305 
6306 
6307  private:
6309  // lexer and parser //
6311 
6319  class lexer
6320  {
6321  public:
6323  enum class token_type
6324  {
6325  uninitialized,
6326  literal_true,
6327  literal_false,
6328  literal_null,
6329  value_string,
6330  value_number,
6331  begin_array,
6332  begin_object,
6333  end_array,
6334  end_object,
6335  name_separator,
6336  value_separator,
6337  parse_error,
6338  end_of_input
6339  };
6340 
6342  using lexer_char_t = unsigned char;
6343 
6345  explicit lexer(const string_t& s) noexcept
6346  : m_stream(nullptr), m_buffer(s)
6347  {
6348  m_content = reinterpret_cast<const lexer_char_t*>(s.c_str());
6349  m_start = m_cursor = m_content;
6350  m_limit = m_content + s.size();
6351  }
6352  explicit lexer(std::istream* s) noexcept
6353  : m_stream(s), m_buffer()
6354  {
6355  getline(*m_stream, m_buffer);
6356  m_content = reinterpret_cast<const lexer_char_t*>(m_buffer.c_str());
6357  m_start = m_cursor = m_content;
6358  m_limit = m_content + m_buffer.size();
6359  }
6360 
6362  lexer() = default;
6363 
6364  // switch of unwanted functions
6365  lexer(const lexer&) = delete;
6366  lexer operator=(const lexer&) = delete;
6367 
6380  static string_t to_unicode(const std::size_t codepoint1,
6381  const std::size_t codepoint2 = 0)
6382  {
6383  string_t result;
6384 
6385  // calculate the codepoint from the given code points
6386  std::size_t codepoint = codepoint1;
6387 
6388  // check if codepoint1 is a high surrogate
6389  if (codepoint1 >= 0xD800 and codepoint1 <= 0xDBFF)
6390  {
6391  // check if codepoint2 is a low surrogate
6392  if (codepoint2 >= 0xDC00 and codepoint2 <= 0xDFFF)
6393  {
6394  codepoint =
6395  // high surrogate occupies the most significant 22 bits
6396  (codepoint1 << 10)
6397  // low surrogate occupies the least significant 15 bits
6398  + codepoint2
6399  // there is still the 0xD800, 0xDC00 and 0x10000 noise
6400  // in the result so we have to substract with:
6401  // (0xD800 << 10) + DC00 - 0x10000 = 0x35FDC00
6402  - 0x35FDC00;
6403  }
6404  else
6405  {
6406  throw std::invalid_argument("missing or wrong low surrogate");
6407  }
6408  }
6409 
6410  if (codepoint < 0x80)
6411  {
6412  // 1-byte characters: 0xxxxxxx (ASCII)
6413  result.append(1, static_cast<typename string_t::value_type>(codepoint));
6414  }
6415  else if (codepoint <= 0x7ff)
6416  {
6417  // 2-byte characters: 110xxxxx 10xxxxxx
6418  result.append(1, static_cast<typename string_t::value_type>(0xC0 | ((codepoint >> 6) & 0x1F)));
6419  result.append(1, static_cast<typename string_t::value_type>(0x80 | (codepoint & 0x3F)));
6420  }
6421  else if (codepoint <= 0xffff)
6422  {
6423  // 3-byte characters: 1110xxxx 10xxxxxx 10xxxxxx
6424  result.append(1, static_cast<typename string_t::value_type>(0xE0 | ((codepoint >> 12) & 0x0F)));
6425  result.append(1, static_cast<typename string_t::value_type>(0x80 | ((codepoint >> 6) & 0x3F)));
6426  result.append(1, static_cast<typename string_t::value_type>(0x80 | (codepoint & 0x3F)));
6427  }
6428  else if (codepoint <= 0x10ffff)
6429  {
6430  // 4-byte characters: 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
6431  result.append(1, static_cast<typename string_t::value_type>(0xF0 | ((codepoint >> 18) & 0x07)));
6432  result.append(1, static_cast<typename string_t::value_type>(0x80 | ((codepoint >> 12) & 0x3F)));
6433  result.append(1, static_cast<typename string_t::value_type>(0x80 | ((codepoint >> 6) & 0x3F)));
6434  result.append(1, static_cast<typename string_t::value_type>(0x80 | (codepoint & 0x3F)));
6435  }
6436  else
6437  {
6438  throw std::out_of_range("code points above 0x10FFFF are invalid");
6439  }
6440 
6441  return result;
6442  }
6443 
6445  static std::string token_type_name(token_type t)
6446  {
6447  switch (t)
6448  {
6449  case token_type::uninitialized:
6450  return "<uninitialized>";
6451  case token_type::literal_true:
6452  return "true literal";
6453  case token_type::literal_false:
6454  return "false literal";
6455  case token_type::literal_null:
6456  return "null literal";
6457  case token_type::value_string:
6458  return "string literal";
6459  case token_type::value_number:
6460  return "number literal";
6461  case token_type::begin_array:
6462  return "'['";
6463  case token_type::begin_object:
6464  return "'{'";
6465  case token_type::end_array:
6466  return "']'";
6467  case token_type::end_object:
6468  return "'}'";
6469  case token_type::name_separator:
6470  return "':'";
6471  case token_type::value_separator:
6472  return "','";
6473  case token_type::parse_error:
6474  return "<parse error>";
6475  case token_type::end_of_input:
6476  return "end of input";
6477  default:
6478  {
6479  // catch non-enum values
6480  return "unknown token"; // LCOV_EXCL_LINE
6481  }
6482  }
6483  }
6484 
6495  token_type scan() noexcept
6496  {
6497  // pointer for backtracking information
6498  m_marker = nullptr;
6499 
6500  // remember the begin of the token
6501  m_start = m_cursor;
6502 
6503 
6504  {
6505  lexer_char_t yych;
6506  unsigned int yyaccept = 0;
6507  static const unsigned char yybm[] =
6508  {
6509  0, 0, 0, 0, 0, 0, 0, 0,
6510  0, 32, 32, 0, 0, 32, 0, 0,
6511  64, 64, 64, 64, 64, 64, 64, 64,
6512  64, 64, 64, 64, 64, 64, 64, 64,
6513  96, 64, 0, 64, 64, 64, 64, 64,
6514  64, 64, 64, 64, 64, 64, 64, 64,
6515  192, 192, 192, 192, 192, 192, 192, 192,
6516  192, 192, 64, 64, 64, 64, 64, 64,
6517  64, 64, 64, 64, 64, 64, 64, 64,
6518  64, 64, 64, 64, 64, 64, 64, 64,
6519  64, 64, 64, 64, 64, 64, 64, 64,
6520  64, 64, 64, 64, 0, 64, 64, 64,
6521  64, 64, 64, 64, 64, 64, 64, 64,
6522  64, 64, 64, 64, 64, 64, 64, 64,
6523  64, 64, 64, 64, 64, 64, 64, 64,
6524  64, 64, 64, 64, 64, 64, 64, 64,
6525  64, 64, 64, 64, 64, 64, 64, 64,
6526  64, 64, 64, 64, 64, 64, 64, 64,
6527  64, 64, 64, 64, 64, 64, 64, 64,
6528  64, 64, 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, 64, 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  };
6542  if ((m_limit - m_cursor) < 5)
6543  {
6544  yyfill(); // LCOV_EXCL_LINE;
6545  }
6546  yych = *m_cursor;
6547  if (yych <= ':')
6548  {
6549  if (yych <= ' ')
6550  {
6551  if (yych <= '\n')
6552  {
6553  if (yych <= 0x00)
6554  {
6555  goto basic_json_parser_28;
6556  }
6557  if (yych <= 0x08)
6558  {
6559  goto basic_json_parser_30;
6560  }
6561  if (yych >= '\n')
6562  {
6563  goto basic_json_parser_4;
6564  }
6565  }
6566  else
6567  {
6568  if (yych == '\r')
6569  {
6570  goto basic_json_parser_2;
6571  }
6572  if (yych <= 0x1F)
6573  {
6574  goto basic_json_parser_30;
6575  }
6576  }
6577  }
6578  else
6579  {
6580  if (yych <= ',')
6581  {
6582  if (yych == '"')
6583  {
6584  goto basic_json_parser_27;
6585  }
6586  if (yych <= '+')
6587  {
6588  goto basic_json_parser_30;
6589  }
6590  goto basic_json_parser_16;
6591  }
6592  else
6593  {
6594  if (yych <= '/')
6595  {
6596  if (yych <= '-')
6597  {
6598  goto basic_json_parser_23;
6599  }
6600  goto basic_json_parser_30;
6601  }
6602  else
6603  {
6604  if (yych <= '0')
6605  {
6606  goto basic_json_parser_24;
6607  }
6608  if (yych <= '9')
6609  {
6610  goto basic_json_parser_26;
6611  }
6612  goto basic_json_parser_18;
6613  }
6614  }
6615  }
6616  }
6617  else
6618  {
6619  if (yych <= 'n')
6620  {
6621  if (yych <= ']')
6622  {
6623  if (yych == '[')
6624  {
6625  goto basic_json_parser_8;
6626  }
6627  if (yych <= '\\')
6628  {
6629  goto basic_json_parser_30;
6630  }
6631  goto basic_json_parser_10;
6632  }
6633  else
6634  {
6635  if (yych == 'f')
6636  {
6637  goto basic_json_parser_22;
6638  }
6639  if (yych <= 'm')
6640  {
6641  goto basic_json_parser_30;
6642  }
6643  goto basic_json_parser_20;
6644  }
6645  }
6646  else
6647  {
6648  if (yych <= '{')
6649  {
6650  if (yych == 't')
6651  {
6652  goto basic_json_parser_21;
6653  }
6654  if (yych <= 'z')
6655  {
6656  goto basic_json_parser_30;
6657  }
6658  goto basic_json_parser_12;
6659  }
6660  else
6661  {
6662  if (yych <= '}')
6663  {
6664  if (yych <= '|')
6665  {
6666  goto basic_json_parser_30;
6667  }
6668  goto basic_json_parser_14;
6669  }
6670  else
6671  {
6672  if (yych == 0xEF)
6673  {
6674  goto basic_json_parser_6;
6675  }
6676  goto basic_json_parser_30;
6677  }
6678  }
6679  }
6680  }
6681 basic_json_parser_2:
6682  ++m_cursor;
6683  yych = *m_cursor;
6684  goto basic_json_parser_5;
6685 basic_json_parser_3:
6686  {
6687  return scan();
6688  }
6689 basic_json_parser_4:
6690  ++m_cursor;
6691  if (m_limit <= m_cursor)
6692  {
6693  yyfill(); // LCOV_EXCL_LINE;
6694  }
6695  yych = *m_cursor;
6696 basic_json_parser_5:
6697  if (yybm[0 + yych] & 32)
6698  {
6699  goto basic_json_parser_4;
6700  }
6701  goto basic_json_parser_3;
6702 basic_json_parser_6:
6703  yyaccept = 0;
6704  yych = *(m_marker = ++m_cursor);
6705  if (yych == 0xBB)
6706  {
6707  goto basic_json_parser_64;
6708  }
6709 basic_json_parser_7:
6710  {
6711  return token_type::parse_error;
6712  }
6713 basic_json_parser_8:
6714  ++m_cursor;
6715  {
6716  return token_type::begin_array;
6717  }
6718 basic_json_parser_10:
6719  ++m_cursor;
6720  {
6721  return token_type::end_array;
6722  }
6723 basic_json_parser_12:
6724  ++m_cursor;
6725  {
6726  return token_type::begin_object;
6727  }
6728 basic_json_parser_14:
6729  ++m_cursor;
6730  {
6731  return token_type::end_object;
6732  }
6733 basic_json_parser_16:
6734  ++m_cursor;
6735  {
6736  return token_type::value_separator;
6737  }
6738 basic_json_parser_18:
6739  ++m_cursor;
6740  {
6741  return token_type::name_separator;
6742  }
6743 basic_json_parser_20:
6744  yyaccept = 0;
6745  yych = *(m_marker = ++m_cursor);
6746  if (yych == 'u')
6747  {
6748  goto basic_json_parser_60;
6749  }
6750  goto basic_json_parser_7;
6751 basic_json_parser_21:
6752  yyaccept = 0;
6753  yych = *(m_marker = ++m_cursor);
6754  if (yych == 'r')
6755  {
6756  goto basic_json_parser_56;
6757  }
6758  goto basic_json_parser_7;
6759 basic_json_parser_22:
6760  yyaccept = 0;
6761  yych = *(m_marker = ++m_cursor);
6762  if (yych == 'a')
6763  {
6764  goto basic_json_parser_51;
6765  }
6766  goto basic_json_parser_7;
6767 basic_json_parser_23:
6768  yych = *++m_cursor;
6769  if (yych <= '/')
6770  {
6771  goto basic_json_parser_7;
6772  }
6773  if (yych <= '0')
6774  {
6775  goto basic_json_parser_50;
6776  }
6777  if (yych <= '9')
6778  {
6779  goto basic_json_parser_41;
6780  }
6781  goto basic_json_parser_7;
6782 basic_json_parser_24:
6783  yyaccept = 1;
6784  yych = *(m_marker = ++m_cursor);
6785  if (yych <= 'D')
6786  {
6787  if (yych == '.')
6788  {
6789  goto basic_json_parser_43;
6790  }
6791  }
6792  else
6793  {
6794  if (yych <= 'E')
6795  {
6796  goto basic_json_parser_44;
6797  }
6798  if (yych == 'e')
6799  {
6800  goto basic_json_parser_44;
6801  }
6802  }
6803 basic_json_parser_25:
6804  {
6805  return token_type::value_number;
6806  }
6807 basic_json_parser_26:
6808  yyaccept = 1;
6809  yych = *(m_marker = ++m_cursor);
6810  goto basic_json_parser_42;
6811 basic_json_parser_27:
6812  yyaccept = 0;
6813  yych = *(m_marker = ++m_cursor);
6814  if (yych <= 0x0F)
6815  {
6816  goto basic_json_parser_7;
6817  }
6818  goto basic_json_parser_32;
6819 basic_json_parser_28:
6820  ++m_cursor;
6821  {
6822  return token_type::end_of_input;
6823  }
6824 basic_json_parser_30:
6825  yych = *++m_cursor;
6826  goto basic_json_parser_7;
6827 basic_json_parser_31:
6828  ++m_cursor;
6829  if (m_limit <= m_cursor)
6830  {
6831  yyfill(); // LCOV_EXCL_LINE;
6832  }
6833  yych = *m_cursor;
6834 basic_json_parser_32:
6835  if (yybm[0 + yych] & 64)
6836  {
6837  goto basic_json_parser_31;
6838  }
6839  if (yych <= 0x0F)
6840  {
6841  goto basic_json_parser_33;
6842  }
6843  if (yych <= '"')
6844  {
6845  goto basic_json_parser_35;
6846  }
6847  goto basic_json_parser_34;
6848 basic_json_parser_33:
6849  m_cursor = m_marker;
6850  if (yyaccept == 0)
6851  {
6852  goto basic_json_parser_7;
6853  }
6854  else
6855  {
6856  goto basic_json_parser_25;
6857  }
6858 basic_json_parser_34:
6859  ++m_cursor;
6860  if (m_limit <= m_cursor)
6861  {
6862  yyfill(); // LCOV_EXCL_LINE;
6863  }
6864  yych = *m_cursor;
6865  if (yych <= 'e')
6866  {
6867  if (yych <= '/')
6868  {
6869  if (yych == '"')
6870  {
6871  goto basic_json_parser_31;
6872  }
6873  if (yych <= '.')
6874  {
6875  goto basic_json_parser_33;
6876  }
6877  goto basic_json_parser_31;
6878  }
6879  else
6880  {
6881  if (yych <= '\\')
6882  {
6883  if (yych <= '[')
6884  {
6885  goto basic_json_parser_33;
6886  }
6887  goto basic_json_parser_31;
6888  }
6889  else
6890  {
6891  if (yych == 'b')
6892  {
6893  goto basic_json_parser_31;
6894  }
6895  goto basic_json_parser_33;
6896  }
6897  }
6898  }
6899  else
6900  {
6901  if (yych <= 'q')
6902  {
6903  if (yych <= 'f')
6904  {
6905  goto basic_json_parser_31;
6906  }
6907  if (yych == 'n')
6908  {
6909  goto basic_json_parser_31;
6910  }
6911  goto basic_json_parser_33;
6912  }
6913  else
6914  {
6915  if (yych <= 's')
6916  {
6917  if (yych <= 'r')
6918  {
6919  goto basic_json_parser_31;
6920  }
6921  goto basic_json_parser_33;
6922  }
6923  else
6924  {
6925  if (yych <= 't')
6926  {
6927  goto basic_json_parser_31;
6928  }
6929  if (yych <= 'u')
6930  {
6931  goto basic_json_parser_37;
6932  }
6933  goto basic_json_parser_33;
6934  }
6935  }
6936  }
6937 basic_json_parser_35:
6938  ++m_cursor;
6939  {
6940  return token_type::value_string;
6941  }
6942 basic_json_parser_37:
6943  ++m_cursor;
6944  if (m_limit <= m_cursor)
6945  {
6946  yyfill(); // LCOV_EXCL_LINE;
6947  }
6948  yych = *m_cursor;
6949  if (yych <= '@')
6950  {
6951  if (yych <= '/')
6952  {
6953  goto basic_json_parser_33;
6954  }
6955  if (yych >= ':')
6956  {
6957  goto basic_json_parser_33;
6958  }
6959  }
6960  else
6961  {
6962  if (yych <= 'F')
6963  {
6964  goto basic_json_parser_38;
6965  }
6966  if (yych <= '`')
6967  {
6968  goto basic_json_parser_33;
6969  }
6970  if (yych >= 'g')
6971  {
6972  goto basic_json_parser_33;
6973  }
6974  }
6975 basic_json_parser_38:
6976  ++m_cursor;
6977  if (m_limit <= m_cursor)
6978  {
6979  yyfill(); // LCOV_EXCL_LINE;
6980  }
6981  yych = *m_cursor;
6982  if (yych <= '@')
6983  {
6984  if (yych <= '/')
6985  {
6986  goto basic_json_parser_33;
6987  }
6988  if (yych >= ':')
6989  {
6990  goto basic_json_parser_33;
6991  }
6992  }
6993  else
6994  {
6995  if (yych <= 'F')
6996  {
6997  goto basic_json_parser_39;
6998  }
6999  if (yych <= '`')
7000  {
7001  goto basic_json_parser_33;
7002  }
7003  if (yych >= 'g')
7004  {
7005  goto basic_json_parser_33;
7006  }
7007  }
7008 basic_json_parser_39:
7009  ++m_cursor;
7010  if (m_limit <= m_cursor)
7011  {
7012  yyfill(); // LCOV_EXCL_LINE;
7013  }
7014  yych = *m_cursor;
7015  if (yych <= '@')
7016  {
7017  if (yych <= '/')
7018  {
7019  goto basic_json_parser_33;
7020  }
7021  if (yych >= ':')
7022  {
7023  goto basic_json_parser_33;
7024  }
7025  }
7026  else
7027  {
7028  if (yych <= 'F')
7029  {
7030  goto basic_json_parser_40;
7031  }
7032  if (yych <= '`')
7033  {
7034  goto basic_json_parser_33;
7035  }
7036  if (yych >= 'g')
7037  {
7038  goto basic_json_parser_33;
7039  }
7040  }
7041 basic_json_parser_40:
7042  ++m_cursor;
7043  if (m_limit <= m_cursor)
7044  {
7045  yyfill(); // LCOV_EXCL_LINE;
7046  }
7047  yych = *m_cursor;
7048  if (yych <= '@')
7049  {
7050  if (yych <= '/')
7051  {
7052  goto basic_json_parser_33;
7053  }
7054  if (yych <= '9')
7055  {
7056  goto basic_json_parser_31;
7057  }
7058  goto basic_json_parser_33;
7059  }
7060  else
7061  {
7062  if (yych <= 'F')
7063  {
7064  goto basic_json_parser_31;
7065  }
7066  if (yych <= '`')
7067  {
7068  goto basic_json_parser_33;
7069  }
7070  if (yych <= 'f')
7071  {
7072  goto basic_json_parser_31;
7073  }
7074  goto basic_json_parser_33;
7075  }
7076 basic_json_parser_41:
7077  yyaccept = 1;
7078  m_marker = ++m_cursor;
7079  if ((m_limit - m_cursor) < 3)
7080  {
7081  yyfill(); // LCOV_EXCL_LINE;
7082  }
7083  yych = *m_cursor;
7084 basic_json_parser_42:
7085  if (yybm[0 + yych] & 128)
7086  {
7087  goto basic_json_parser_41;
7088  }
7089  if (yych <= 'D')
7090  {
7091  if (yych != '.')
7092  {
7093  goto basic_json_parser_25;
7094  }
7095  }
7096  else
7097  {
7098  if (yych <= 'E')
7099  {
7100  goto basic_json_parser_44;
7101  }
7102  if (yych == 'e')
7103  {
7104  goto basic_json_parser_44;
7105  }
7106  goto basic_json_parser_25;
7107  }
7108 basic_json_parser_43:
7109  yych = *++m_cursor;
7110  if (yych <= '/')
7111  {
7112  goto basic_json_parser_33;
7113  }
7114  if (yych <= '9')
7115  {
7116  goto basic_json_parser_48;
7117  }
7118  goto basic_json_parser_33;
7119 basic_json_parser_44:
7120  yych = *++m_cursor;
7121  if (yych <= ',')
7122  {
7123  if (yych != '+')
7124  {
7125  goto basic_json_parser_33;
7126  }
7127  }
7128  else
7129  {
7130  if (yych <= '-')
7131  {
7132  goto basic_json_parser_45;
7133  }
7134  if (yych <= '/')
7135  {
7136  goto basic_json_parser_33;
7137  }
7138  if (yych <= '9')
7139  {
7140  goto basic_json_parser_46;
7141  }
7142  goto basic_json_parser_33;
7143  }
7144 basic_json_parser_45:
7145  yych = *++m_cursor;
7146  if (yych <= '/')
7147  {
7148  goto basic_json_parser_33;
7149  }
7150  if (yych >= ':')
7151  {
7152  goto basic_json_parser_33;
7153  }
7154 basic_json_parser_46:
7155  ++m_cursor;
7156  if (m_limit <= m_cursor)
7157  {
7158  yyfill(); // LCOV_EXCL_LINE;
7159  }
7160  yych = *m_cursor;
7161  if (yych <= '/')
7162  {
7163  goto basic_json_parser_25;
7164  }
7165  if (yych <= '9')
7166  {
7167  goto basic_json_parser_46;
7168  }
7169  goto basic_json_parser_25;
7170 basic_json_parser_48:
7171  yyaccept = 1;
7172  m_marker = ++m_cursor;
7173  if ((m_limit - m_cursor) < 3)
7174  {
7175  yyfill(); // LCOV_EXCL_LINE;
7176  }
7177  yych = *m_cursor;
7178  if (yych <= 'D')
7179  {
7180  if (yych <= '/')
7181  {
7182  goto basic_json_parser_25;
7183  }
7184  if (yych <= '9')
7185  {
7186  goto basic_json_parser_48;
7187  }
7188  goto basic_json_parser_25;
7189  }
7190  else
7191  {
7192  if (yych <= 'E')
7193  {
7194  goto basic_json_parser_44;
7195  }
7196  if (yych == 'e')
7197  {
7198  goto basic_json_parser_44;
7199  }
7200  goto basic_json_parser_25;
7201  }
7202 basic_json_parser_50:
7203  yyaccept = 1;
7204  yych = *(m_marker = ++m_cursor);
7205  if (yych <= 'D')
7206  {
7207  if (yych == '.')
7208  {
7209  goto basic_json_parser_43;
7210  }
7211  goto basic_json_parser_25;
7212  }
7213  else
7214  {
7215  if (yych <= 'E')
7216  {
7217  goto basic_json_parser_44;
7218  }
7219  if (yych == 'e')
7220  {
7221  goto basic_json_parser_44;
7222  }
7223  goto basic_json_parser_25;
7224  }
7225 basic_json_parser_51:
7226  yych = *++m_cursor;
7227  if (yych != 'l')
7228  {
7229  goto basic_json_parser_33;
7230  }
7231  yych = *++m_cursor;
7232  if (yych != 's')
7233  {
7234  goto basic_json_parser_33;
7235  }
7236  yych = *++m_cursor;
7237  if (yych != 'e')
7238  {
7239  goto basic_json_parser_33;
7240  }
7241  ++m_cursor;
7242  {
7243  return token_type::literal_false;
7244  }
7245 basic_json_parser_56:
7246  yych = *++m_cursor;
7247  if (yych != 'u')
7248  {
7249  goto basic_json_parser_33;
7250  }
7251  yych = *++m_cursor;
7252  if (yych != 'e')
7253  {
7254  goto basic_json_parser_33;
7255  }
7256  ++m_cursor;
7257  {
7258  return token_type::literal_true;
7259  }
7260 basic_json_parser_60:
7261  yych = *++m_cursor;
7262  if (yych != 'l')
7263  {
7264  goto basic_json_parser_33;
7265  }
7266  yych = *++m_cursor;
7267  if (yych != 'l')
7268  {
7269  goto basic_json_parser_33;
7270  }
7271  ++m_cursor;
7272  {
7273  return token_type::literal_null;
7274  }
7275 basic_json_parser_64:
7276  yych = *++m_cursor;
7277  if (yych != 0xBF)
7278  {
7279  goto basic_json_parser_33;
7280  }
7281  ++m_cursor;
7282  {
7283  return scan();
7284  }
7285  }
7286 
7287 
7288  }
7289 
7291  void yyfill() noexcept
7292  {
7293  if (not m_stream or not * m_stream)
7294  {
7295  return;
7296  }
7297 
7298  const ssize_t offset_start = m_start - m_content;
7299  const ssize_t offset_marker = m_marker - m_start;
7300  const ssize_t offset_cursor = m_cursor - m_start;
7301 
7302  m_buffer.erase(0, static_cast<size_t>(offset_start));
7303  std::string line;
7304  std::getline(*m_stream, line);
7305  m_buffer += "\n" + line; // add line with newline symbol
7306 
7307  m_content = reinterpret_cast<const lexer_char_t*>(m_buffer.c_str());
7308  m_start = m_content;
7309  m_marker = m_start + offset_marker;
7310  m_cursor = m_start + offset_cursor;
7311  m_limit = m_start + m_buffer.size() - 1;
7312  }
7313 
7315  string_t get_token() const noexcept
7316  {
7317  return string_t(reinterpret_cast<typename string_t::const_pointer>(m_start),
7318  static_cast<size_t>(m_cursor - m_start));
7319  }
7320 
7342  string_t get_string() const
7343  {
7344  string_t result;
7345  result.reserve(static_cast<size_t>(m_cursor - m_start - 2));
7346 
7347  // iterate the result between the quotes
7348  for (const lexer_char_t* i = m_start + 1; i < m_cursor - 1; ++i)
7349  {
7350  // process escaped characters
7351  if (*i == '\\')
7352  {
7353  // read next character
7354  ++i;
7355 
7356  switch (*i)
7357  {
7358  // the default escapes
7359  case 't':
7360  {
7361  result += "\t";
7362  break;
7363  }
7364  case 'b':
7365  {
7366  result += "\b";
7367  break;
7368  }
7369  case 'f':
7370  {
7371  result += "\f";
7372  break;
7373  }
7374  case 'n':
7375  {
7376  result += "\n";
7377  break;
7378  }
7379  case 'r':
7380  {
7381  result += "\r";
7382  break;
7383  }
7384  case '\\':
7385  {
7386  result += "\\";
7387  break;
7388  }
7389  case '/':
7390  {
7391  result += "/";
7392  break;
7393  }
7394  case '"':
7395  {
7396  result += "\"";
7397  break;
7398  }
7399 
7400  // unicode
7401  case 'u':
7402  {
7403  // get code xxxx from uxxxx
7404  auto codepoint = std::strtoul(std::string(reinterpret_cast<typename string_t::const_pointer>(i + 1),
7405  4).c_str(), nullptr, 16);
7406 
7407  // check if codepoint is a high surrogate
7408  if (codepoint >= 0xD800 and codepoint <= 0xDBFF)
7409  {
7410  // make sure there is a subsequent unicode
7411  if ((i + 6 >= m_limit) or * (i + 5) != '\\' or * (i + 6) != 'u')
7412  {
7413  throw std::invalid_argument("missing low surrogate");
7414  }
7415 
7416  // get code yyyy from uxxxx\uyyyy
7417  auto codepoint2 = std::strtoul(std::string(reinterpret_cast<typename string_t::const_pointer>
7418  (i + 7), 4).c_str(), nullptr, 16);
7419  result += to_unicode(codepoint, codepoint2);
7420  // skip the next 10 characters (xxxx\uyyyy)
7421  i += 10;
7422  }
7423  else
7424  {
7425  // add unicode character(s)
7426  result += to_unicode(codepoint);
7427  // skip the next four characters (xxxx)
7428  i += 4;
7429  }
7430  break;
7431  }
7432  }
7433  }
7434  else
7435  {
7436  // all other characters are just copied to the end of the
7437  // string
7438  result.append(1, static_cast<typename string_t::value_type>(*i));
7439  }
7440  }
7441 
7442  return result;
7443  }
7444 
7462  long double get_number() const
7463  {
7464  // conversion
7465  typename string_t::value_type* endptr;
7466  const auto float_val = std::strtold(reinterpret_cast<typename string_t::const_pointer>(m_start),
7467  &endptr);
7468 
7469  // return float_val if the whole number was translated and NAN
7470  // otherwise
7471  return (reinterpret_cast<lexer_char_t*>(endptr) == m_cursor) ? float_val : NAN;
7472  }
7473 
7474  private:
7476  std::istream* m_stream;
7478  string_t m_buffer;
7480  const lexer_char_t* m_content = nullptr;
7482  const lexer_char_t* m_start = nullptr;
7484  const lexer_char_t* m_marker = nullptr;
7486  const lexer_char_t* m_cursor = nullptr;
7488  const lexer_char_t* m_limit = nullptr;
7489  };
7490 
7496  class parser
7497  {
7498  public:
7500  parser(const string_t& s, parser_callback_t cb = nullptr)
7501  : callback(cb), m_lexer(s)
7502  {
7503  // read first token
7504  get_token();
7505  }
7506 
7508  parser(std::istream& _is, parser_callback_t cb = nullptr)
7509  : callback(cb), m_lexer(&_is)
7510  {
7511  // read first token
7512  get_token();
7513  }
7514 
7516  basic_json parse()
7517  {
7518  basic_json result = parse_internal(true);
7519 
7520  expect(lexer::token_type::end_of_input);
7521 
7522  // return parser result and replace it with null in case the
7523  // top-level value was discarded by the callback function
7524  return result.is_discarded() ? basic_json() : result;
7525  }
7526 
7527  private:
7529  basic_json parse_internal(bool keep)
7530  {
7531  auto result = basic_json(value_t::discarded);
7532 
7533  switch (last_token)
7534  {
7535  case lexer::token_type::begin_object:
7536  {
7537  if (keep and (not callback or (keep = callback(depth++, parse_event_t::object_start, result))))
7538  {
7539  // explicitly set result to object to cope with {}
7540  result.m_type = value_t::object;
7541  result.m_value = json_value(value_t::object);
7542  }
7543 
7544  // read next token
7545  get_token();
7546 
7547  // closing } -> we are done
7548  if (last_token == lexer::token_type::end_object)
7549  {
7550  get_token();
7551  if (keep and callback and not callback(--depth, parse_event_t::object_end, result))
7552  {
7553  result = basic_json(value_t::discarded);
7554  }
7555  return result;
7556  }
7557 
7558  // no comma is expected here
7559  unexpect(lexer::token_type::value_separator);
7560 
7561  // otherwise: parse key-value pairs
7562  do
7563  {
7564  // ugly, but could be fixed with loop reorganization
7565  if (last_token == lexer::token_type::value_separator)
7566  {
7567  get_token();
7568  }
7569 
7570  // store key
7571  expect(lexer::token_type::value_string);
7572  const auto key = m_lexer.get_string();
7573 
7574  bool keep_tag = false;
7575  if (keep)
7576  {
7577  if (callback)
7578  {
7579  basic_json k(key);
7580  keep_tag = callback(depth, parse_event_t::key, k);
7581  }
7582  else
7583  {
7584  keep_tag = true;
7585  }
7586  }
7587 
7588  // parse separator (:)
7589  get_token();
7590  expect(lexer::token_type::name_separator);
7591 
7592  // parse and add value
7593  get_token();
7594  auto value = parse_internal(keep);
7595  if (keep and keep_tag and not value.is_discarded())
7596  {
7597  result[key] = std::move(value);
7598  }
7599  }
7600  while (last_token == lexer::token_type::value_separator);
7601 
7602  // closing }
7603  expect(lexer::token_type::end_object);
7604  get_token();
7605  if (keep and callback and not callback(--depth, parse_event_t::object_end, result))
7606  {
7607  result = basic_json(value_t::discarded);
7608  }
7609 
7610  return result;
7611  }
7612 
7613  case lexer::token_type::begin_array:
7614  {
7615  if (keep and (not callback or (keep = callback(depth++, parse_event_t::array_start, result))))
7616  {
7617  // explicitly set result to object to cope with []
7618  result.m_type = value_t::array;
7619  result.m_value = json_value(value_t::array);
7620  }
7621 
7622  // read next token
7623  get_token();
7624 
7625  // closing ] -> we are done
7626  if (last_token == lexer::token_type::end_array)
7627  {
7628  get_token();
7629  if (callback and not callback(--depth, parse_event_t::array_end, result))
7630  {
7631  result = basic_json(value_t::discarded);
7632  }
7633  return result;
7634  }
7635 
7636  // no comma is expected here
7637  unexpect(lexer::token_type::value_separator);
7638 
7639  // otherwise: parse values
7640  do
7641  {
7642  // ugly, but could be fixed with loop reorganization
7643  if (last_token == lexer::token_type::value_separator)
7644  {
7645  get_token();
7646  }
7647 
7648  // parse value
7649  auto value = parse_internal(keep);
7650  if (keep and not value.is_discarded())
7651  {
7652  result.push_back(std::move(value));
7653  }
7654  }
7655  while (last_token == lexer::token_type::value_separator);
7656 
7657  // closing ]
7658  expect(lexer::token_type::end_array);
7659  get_token();
7660  if (keep and callback and not callback(--depth, parse_event_t::array_end, result))
7661  {
7662  result = basic_json(value_t::discarded);
7663  }
7664 
7665  return result;
7666  }
7667 
7668  case lexer::token_type::literal_null:
7669  {
7670  get_token();
7671  result.m_type = value_t::null;
7672  break;
7673  }
7674 
7675  case lexer::token_type::value_string:
7676  {
7677  const auto s = m_lexer.get_string();
7678  get_token();
7679  result = basic_json(s);
7680  break;
7681  }
7682 
7683  case lexer::token_type::literal_true:
7684  {
7685  get_token();
7686  result.m_type = value_t::boolean;
7687  result.m_value = true;
7688  break;
7689  }
7690 
7691  case lexer::token_type::literal_false:
7692  {
7693  get_token();
7694  result.m_type = value_t::boolean;
7695  result.m_value = false;
7696  break;
7697  }
7698 
7699  case lexer::token_type::value_number:
7700  {
7701  auto float_val = m_lexer.get_number();
7702 
7703  // NAN is returned if token could not be translated
7704  // completely
7705  if (std::isnan(float_val))
7706  {
7707  throw std::invalid_argument(std::string("parse error - ") +
7708  m_lexer.get_token() + " is not a number");
7709  }
7710 
7711  get_token();
7712 
7713  // check if conversion loses precision
7714  const auto int_val = static_cast<number_integer_t>(float_val);
7715  if (approx(float_val, static_cast<long double>(int_val)))
7716  {
7717  // we would not lose precision -> return int
7718  result.m_type = value_t::number_integer;
7719  result.m_value = int_val;
7720  }
7721  else
7722  {
7723  // we would lose precision -> return float
7724  result.m_type = value_t::number_float;
7725  result.m_value = static_cast<number_float_t>(float_val);
7726  }
7727  break;
7728  }
7729 
7730  default:
7731  {
7732  // the last token was unexpected
7733  unexpect(last_token);
7734  }
7735  }
7736 
7737  if (keep and callback and not callback(depth, parse_event_t::value, result))
7738  {
7739  result = basic_json(value_t::discarded);
7740  }
7741  return result;
7742  }
7743 
7745  typename lexer::token_type get_token()
7746  {
7747  last_token = m_lexer.scan();
7748  return last_token;
7749  }
7750 
7751  void expect(typename lexer::token_type t) const
7752  {
7753  if (t != last_token)
7754  {
7755  std::string error_msg = "parse error - unexpected ";
7756  error_msg += (last_token == lexer::token_type::parse_error ? ("'" + m_lexer.get_token() + "'") :
7757  lexer::token_type_name(last_token));
7758  error_msg += "; expected " + lexer::token_type_name(t);
7759  throw std::invalid_argument(error_msg);
7760  }
7761  }
7762 
7763  void unexpect(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  throw std::invalid_argument(error_msg);
7771  }
7772  }
7773 
7774  private:
7776  int depth = 0;
7778  parser_callback_t callback;
7780  typename lexer::token_type last_token = lexer::token_type::uninitialized;
7782  lexer m_lexer;
7783  };
7784 };
7785 
7786 
7788 // presets //
7790 
7800 }
7801 
7802 
7804 // nonmember functions //
7806 
7807 // specialization of std::swap, and std::hash
7808 namespace std
7809 {
7815 template <>
7816 inline void swap(nlohmann::json& j1,
7817  nlohmann::json& j2) noexcept(
7818  is_nothrow_move_constructible<nlohmann::json>::value and
7819  is_nothrow_move_assignable<nlohmann::json>::value
7820  )
7821 {
7822  j1.swap(j2);
7823 }
7824 
7826 template <>
7827 struct hash<nlohmann::json>
7828 {
7834  std::size_t operator()(const nlohmann::json& j) const
7835  {
7836  // a naive hashing via the string representation
7837  const auto& h = hash<nlohmann::json::string_t>();
7838  return h(j.dump());
7839  }
7840 };
7841 }
7842 
7855 inline nlohmann::json operator "" _json(const char* s, std::size_t)
7856 {
7857  return nlohmann::json::parse(reinterpret_cast<nlohmann::json::string_t::value_type*>
7858  (const_cast<char*>(s)));
7859 }
7860 
7861 #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:5879
iterator insert(const_iterator pos, basic_json &&val)
inserts element
Definition: json.hpp:4256
iterator operator++(int)
post-increment (it++)
Definition: json.hpp:6117
friend bool operator<=(const_reference lhs, const_reference rhs) noexcept
comparison: less than or equal
Definition: json.hpp:4810
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:6272
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:5581
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:5824
friend std::istream & operator>>(std::istream &i, basic_json &j)
deserialize from stream
Definition: json.hpp:5023
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:5646
typename basic_json::value_type value_type
the type of the values when the iterator is dereferenced
Definition: json.hpp:5577
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:4335
iterator insert(const_iterator pos, size_type cnt, const basic_json &val)
inserts elements
Definition: json.hpp:4284
json_reverse_iterator operator--(int)
post-decrement (it–)
Definition: json.hpp:6244
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:4180
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:6125
friend bool operator!=(const_reference lhs, const_reference rhs) noexcept
comparison: not equal
Definition: json.hpp:4688
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:5789
difference_type operator-(const json_reverse_iterator &other) const
return difference
Definition: json.hpp:6280
basic_json<> json
default JSON class
Definition: json.hpp:7799
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:6216
json_reverse_iterator(const typename base_iterator::iterator_type &it)
create reverse iterator from iterator
Definition: json.hpp:6221
a class to store JSON values
Definition: json.hpp:187
json_reverse_iterator & operator--()
pre-decrement (–it)
Definition: json.hpp:6250
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:4667
void push_back(basic_json &&val)
add an object to an array
Definition: json.hpp:4096
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:6147
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:6075
reference operator+=(basic_json &&val)
add an object to an array
Definition: json.hpp:4121
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:6072
iterator & operator-=(difference_type i)
subtract from iterator
Definition: json.hpp:6154
static basic_json parse(std::istream &&i, parser_callback_t cb=nullptr)
deserialize from stream
Definition: json.hpp:4985
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:6176
reference value() const
return the value of an iterator
Definition: json.hpp:6048
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:5641
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:6035
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:6105
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:5971
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:5583
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:4154
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:6161
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:4854
iterator & operator--()
pre-decrement (–it)
Definition: json.hpp:6140
friend bool operator<(const_reference lhs, const_reference rhs) noexcept
comparison: less than
Definition: json.hpp:4749
pointer operator->() const
dereference the iterator
Definition: json.hpp:5752
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:6218
size_type size() const noexcept
returns the number of elements
Definition: json.hpp:3912
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:6226
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:4909
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:6292
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:5579
void swap(array_t &other)
exchanges the values
Definition: json.hpp:4457
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:4203
reference operator[](difference_type n) const
access to successor
Definition: json.hpp:6182
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:5963
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:4521
reference value() const
return the value of an iterator
Definition: json.hpp:6188
const_iterator operator--(int)
post-decrement (it–)
Definition: json.hpp:5816
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:4029
pointer operator->()
dereference the iterator
Definition: json.hpp:6111
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:5925
iterator insert(const_iterator pos, std::initializer_list< basic_json > ilist)
inserts elements
Definition: json.hpp:4390
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:5931
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:5979
friend bool operator==(const_reference lhs, const_reference rhs) noexcept
comparison: equal
Definition: json.hpp:4600
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:4427
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:6299
const_iterator(pointer object)
constructor for a given JSON instance
Definition: json.hpp:5591
friend bool operator<(const value_t lhs, const value_t rhs)
comparison operator for JSON types
Definition: json.hpp:4554
iterator(pointer object) noexcept
constructor for a given JSON instance
Definition: json.hpp:6083
bool operator<(const const_iterator &other) const
comparison: smaller
Definition: json.hpp:5885
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:4711
const_iterator & operator-=(difference_type i)
subtract from iterator
Definition: json.hpp:5957
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:4948
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:6231
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:5616
friend bool operator!=(std::nullptr_t, const_reference v) noexcept
comparison: not equal
Definition: json.hpp:4720
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:5913
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:5781
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:6088
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:4977
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:3972
void push_back(const basic_json &val)
add an object to an array
Definition: json.hpp:4131
bool operator==(const const_iterator &other) const
comparison: equal
Definition: json.hpp:5851
json_reverse_iterator & operator++()
pre-increment (++it)
Definition: json.hpp:6237
bool operator>(const const_iterator &other) const
comparison: greater than
Definition: json.hpp:5919
friend bool operator>(const_reference lhs, const_reference rhs) noexcept
comparison: greater than
Definition: json.hpp:4832
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:6257
a const random access iterator for the basic_json class
Definition: json.hpp:5570
a template for a reverse iterator class
Definition: json.hpp:232
void swap(object_t &other)
exchanges the values
Definition: json.hpp:4489
std::bidirectional_iterator_tag iterator_category
the category of the iterator
Definition: json.hpp:5585
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:4658
reference operator[](difference_type n) const
access to successor
Definition: json.hpp:6286
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:6001
reference operator*() const
return a reference to the value pointed to by the iterator
Definition: json.hpp:5718
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:5013
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:7834
friend std::ostream & operator<<(std::ostream &o, const basic_json &j)
serialize to stream
Definition: json.hpp:4891
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:6093
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:6132
json_reverse_iterator operator+(difference_type i) const
add to iterator
Definition: json.hpp:6264
parse_event_t
JSON callback events.
Definition: json.hpp:754
iterator operator-(difference_type i)
subtract from iterator
Definition: json.hpp:6169