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 
1376  basic_json(std::initializer_list<basic_json> init,
1377  bool type_deduction = true,
1378  value_t manual_type = value_t::array)
1379  {
1380  // the initializer list could describe an object
1381  bool is_an_object = true;
1382 
1383  // check if each element is an array with two elements whose first
1384  // element is a string
1385  for (const auto& element : init)
1386  {
1387  if (not element.is_array() or element.size() != 2
1388  or not element[0].is_string())
1389  {
1390  // we found an element that makes it impossible to use the
1391  // initializer list as object
1392  is_an_object = false;
1393  break;
1394  }
1395  }
1396 
1397  // adjust type if type deduction is not wanted
1398  if (not type_deduction)
1399  {
1400  // if array is wanted, do not create an object though possible
1401  if (manual_type == value_t::array)
1402  {
1403  is_an_object = false;
1404  }
1405 
1406  // if object is wanted but impossible, throw an exception
1407  if (manual_type == value_t::object and not is_an_object)
1408  {
1409  throw std::domain_error("cannot create object from initializer list");
1410  }
1411  }
1412 
1413  if (is_an_object)
1414  {
1415  // the initializer list is a list of pairs -> create object
1416  m_type = value_t::object;
1417  m_value = value_t::object;
1418 
1419  for (auto& element : init)
1420  {
1421  m_value.object->emplace(std::move(*(element[0].m_value.string)), std::move(element[1]));
1422  }
1423  }
1424  else
1425  {
1426  // the initializer list describes an array -> create array
1427  m_type = value_t::array;
1428  m_value.array = create<array_t>(std::move(init));
1429  }
1430  }
1431 
1466  static basic_json array(std::initializer_list<basic_json> init =
1467  std::initializer_list<basic_json>())
1468  {
1469  return basic_json(init, false, value_t::array);
1470  }
1471 
1506  static basic_json object(std::initializer_list<basic_json> init =
1507  std::initializer_list<basic_json>())
1508  {
1509  return basic_json(init, false, value_t::object);
1510  }
1511 
1530  basic_json(size_type cnt, const basic_json& val)
1531  : m_type(value_t::array)
1532  {
1533  m_value.array = create<array_t>(cnt, val);
1534  }
1535 
1568  template <class InputIT, typename
1569  std::enable_if<
1570  std::is_same<InputIT, typename basic_json_t::iterator>::value or
1571  std::is_same<InputIT, typename basic_json_t::const_iterator>::value
1572  , int>::type
1573  = 0>
1574  basic_json(InputIT first, InputIT last) : m_type(first.m_object->m_type)
1575  {
1576  // make sure iterator fits the current value
1577  if (first.m_object != last.m_object)
1578  {
1579  throw std::domain_error("iterators are not compatible");
1580  }
1581 
1582  // check if iterator range is complete for primitive values
1583  switch (m_type)
1584  {
1585  case value_t::boolean:
1586  case value_t::number_float:
1588  case value_t::string:
1589  {
1590  if (not first.m_it.primitive_iterator.is_begin() or not last.m_it.primitive_iterator.is_end())
1591  {
1592  throw std::out_of_range("iterators out of range");
1593  }
1594  break;
1595  }
1596 
1597  default:
1598  {
1599  break;
1600  }
1601  }
1602 
1603  switch (m_type)
1604  {
1606  {
1607  m_value.number_integer = first.m_object->m_value.number_integer;
1608  break;
1609  }
1610 
1611  case value_t::number_float:
1612  {
1613  m_value.number_float = first.m_object->m_value.number_float;
1614  break;
1615  }
1616 
1617  case value_t::boolean:
1618  {
1619  m_value.boolean = first.m_object->m_value.boolean;
1620  break;
1621  }
1622 
1623  case value_t::string:
1624  {
1625  m_value = *first.m_object->m_value.string;
1626  break;
1627  }
1628 
1629  case value_t::object:
1630  {
1631  m_value.object = create<object_t>(first.m_it.object_iterator, last.m_it.object_iterator);
1632  break;
1633  }
1634 
1635  case value_t::array:
1636  {
1637  m_value.array = create<array_t>(first.m_it.array_iterator, last.m_it.array_iterator);
1638  break;
1639  }
1640 
1641  default:
1642  {
1643  throw std::domain_error("cannot use construct with iterators from " + first.m_object->type_name());
1644  }
1645  }
1646  }
1647 
1649  // other constructors and destructor //
1651 
1672  basic_json(const basic_json& other)
1673  : m_type(other.m_type)
1674  {
1675  switch (m_type)
1676  {
1677  case value_t::object:
1678  {
1679  m_value = *other.m_value.object;
1680  break;
1681  }
1682 
1683  case value_t::array:
1684  {
1685  m_value = *other.m_value.array;
1686  break;
1687  }
1688 
1689  case value_t::string:
1690  {
1691  m_value = *other.m_value.string;
1692  break;
1693  }
1694 
1695  case value_t::boolean:
1696  {
1697  m_value = other.m_value.boolean;
1698  break;
1699  }
1700 
1702  {
1703  m_value = other.m_value.number_integer;
1704  break;
1705  }
1706 
1707  case value_t::number_float:
1708  {
1709  m_value = other.m_value.number_float;
1710  break;
1711  }
1712 
1713  default:
1714  {
1715  break;
1716  }
1717  }
1718  }
1719 
1738  basic_json(basic_json&& other) noexcept
1739  : m_type(std::move(other.m_type)),
1740  m_value(std::move(other.m_value))
1741  {
1742  // invalidate payload
1743  other.m_type = value_t::null;
1744  other.m_value = {};
1745  }
1746 
1768  reference& operator=(basic_json other) noexcept (
1769  std::is_nothrow_move_constructible<value_t>::value and
1770  std::is_nothrow_move_assignable<value_t>::value and
1771  std::is_nothrow_move_constructible<json_value>::value and
1772  std::is_nothrow_move_assignable<json_value>::value
1773  )
1774  {
1775  using std::swap;
1776  swap(m_type, other.m_type);
1777  swap(m_value, other.m_value);
1778  return *this;
1779  }
1780 
1795  {
1796  switch (m_type)
1797  {
1798  case value_t::object:
1799  {
1800  AllocatorType<object_t> alloc;
1801  alloc.destroy(m_value.object);
1802  alloc.deallocate(m_value.object, 1);
1803  break;
1804  }
1805 
1806  case value_t::array:
1807  {
1808  AllocatorType<array_t> alloc;
1809  alloc.destroy(m_value.array);
1810  alloc.deallocate(m_value.array, 1);
1811  break;
1812  }
1813 
1814  case value_t::string:
1815  {
1816  AllocatorType<string_t> alloc;
1817  alloc.destroy(m_value.string);
1818  alloc.deallocate(m_value.string, 1);
1819  break;
1820  }
1821 
1822  default:
1823  {
1824  // all other types need no specific destructor
1825  break;
1826  }
1827  }
1828  }
1829 
1831 
1832  public:
1834  // object inspection //
1836 
1839 
1863  string_t dump(const int indent = -1) const
1864  {
1865  std::stringstream ss;
1866 
1867  if (indent >= 0)
1868  {
1869  dump(ss, true, static_cast<unsigned int>(indent));
1870  }
1871  else
1872  {
1873  dump(ss, false, 0);
1874  }
1875 
1876  return ss.str();
1877  }
1878 
1894  value_t type() const noexcept
1895  {
1896  return m_type;
1897  }
1898 
1915  bool is_primitive() const noexcept
1916  {
1917  return is_null() or is_string() or is_boolean() or is_number();
1918  }
1919 
1935  bool is_structured() const noexcept
1936  {
1937  return is_array() or is_object();
1938  }
1939 
1954  bool is_null() const noexcept
1955  {
1956  return m_type == value_t::null;
1957  }
1958 
1973  bool is_boolean() const noexcept
1974  {
1975  return m_type == value_t::boolean;
1976  }
1977 
1997  bool is_number() const noexcept
1998  {
1999  return is_number_integer() or is_number_float();
2000  }
2001 
2020  bool is_number_integer() const noexcept
2021  {
2022  return m_type == value_t::number_integer;
2023  }
2024 
2043  bool is_number_float() const noexcept
2044  {
2045  return m_type == value_t::number_float;
2046  }
2047 
2062  bool is_object() const noexcept
2063  {
2064  return m_type == value_t::object;
2065  }
2066 
2081  bool is_array() const noexcept
2082  {
2083  return m_type == value_t::array;
2084  }
2085 
2100  bool is_string() const noexcept
2101  {
2102  return m_type == value_t::string;
2103  }
2104 
2124  bool is_discarded() const noexcept
2125  {
2126  return m_type == value_t::discarded;
2127  }
2128 
2144  operator value_t() const noexcept
2145  {
2146  return m_type;
2147  }
2148 
2150 
2151  private:
2153  // value access //
2155 
2157  template <class T, typename
2158  std::enable_if<
2159  std::is_convertible<typename object_t::key_type, typename T::key_type>::value and
2160  std::is_convertible<basic_json_t, typename T::mapped_type>::value
2161  , int>::type = 0>
2162  T get_impl(T*) const
2163  {
2164  if (is_object())
2165  {
2166  return T(m_value.object->begin(), m_value.object->end());
2167  }
2168  else
2169  {
2170  throw std::domain_error("type must be object, but is " + type_name());
2171  }
2172  }
2173 
2175  object_t get_impl(object_t*) const
2176  {
2177  if (is_object())
2178  {
2179  return *(m_value.object);
2180  }
2181  else
2182  {
2183  throw std::domain_error("type must be object, but is " + type_name());
2184  }
2185  }
2186 
2188  template <class T, typename
2189  std::enable_if<
2190  std::is_convertible<basic_json_t, typename T::value_type>::value and
2191  not std::is_same<basic_json_t, typename T::value_type>::value and
2192  not std::is_arithmetic<T>::value and
2193  not std::is_convertible<std::string, T>::value and
2194  not has_mapped_type<T>::value
2195  , int>::type = 0>
2196  T get_impl(T*) const
2197  {
2198  if (is_array())
2199  {
2200  T to_vector;
2201  std::transform(m_value.array->begin(), m_value.array->end(),
2202  std::inserter(to_vector, to_vector.end()), [](basic_json i)
2203  {
2204  return i.get<typename T::value_type>();
2205  });
2206  return to_vector;
2207  }
2208  else
2209  {
2210  throw std::domain_error("type must be array, but is " + type_name());
2211  }
2212  }
2213 
2215  template <class T, typename
2216  std::enable_if<
2217  std::is_convertible<basic_json_t, T>::value and
2218  not std::is_same<basic_json_t, T>::value
2219  , int>::type = 0>
2220  std::vector<T> get_impl(std::vector<T>*) const
2221  {
2222  if (is_array())
2223  {
2224  std::vector<T> to_vector;
2225  to_vector.reserve(m_value.array->size());
2226  std::transform(m_value.array->begin(), m_value.array->end(),
2227  std::inserter(to_vector, to_vector.end()), [](basic_json i)
2228  {
2229  return i.get<T>();
2230  });
2231  return to_vector;
2232  }
2233  else
2234  {
2235  throw std::domain_error("type must be array, but is " + type_name());
2236  }
2237  }
2238 
2240  template <class T, typename
2241  std::enable_if<
2242  std::is_same<basic_json, typename T::value_type>::value and
2243  not has_mapped_type<T>::value
2244  , int>::type = 0>
2245  T get_impl(T*) const
2246  {
2247  if (is_array())
2248  {
2249  return T(m_value.array->begin(), m_value.array->end());
2250  }
2251  else
2252  {
2253  throw std::domain_error("type must be array, but is " + type_name());
2254  }
2255  }
2256 
2258  array_t get_impl(array_t*) const
2259  {
2260  if (is_array())
2261  {
2262  return *(m_value.array);
2263  }
2264  else
2265  {
2266  throw std::domain_error("type must be array, but is " + type_name());
2267  }
2268  }
2269 
2271  template <typename T, typename
2272  std::enable_if<
2273  std::is_convertible<string_t, T>::value
2274  , int>::type = 0>
2275  T get_impl(T*) const
2276  {
2277  if (is_string())
2278  {
2279  return *m_value.string;
2280  }
2281  else
2282  {
2283  throw std::domain_error("type must be string, but is " + type_name());
2284  }
2285  }
2286 
2288  template<typename T, typename
2289  std::enable_if<
2290  std::is_arithmetic<T>::value
2291  , int>::type = 0>
2292  T get_impl(T*) const
2293  {
2294  switch (m_type)
2295  {
2297  {
2298  return static_cast<T>(m_value.number_integer);
2299  }
2300 
2301  case value_t::number_float:
2302  {
2303  return static_cast<T>(m_value.number_float);
2304  }
2305 
2306  default:
2307  {
2308  throw std::domain_error("type must be number, but is " + type_name());
2309  }
2310  }
2311  }
2312 
2314  boolean_t get_impl(boolean_t*) const
2315  {
2316  if (is_boolean())
2317  {
2318  return m_value.boolean;
2319  }
2320  else
2321  {
2322  throw std::domain_error("type must be boolean, but is " + type_name());
2323  }
2324  }
2325 
2327  object_t* get_impl_ptr(object_t*) noexcept
2328  {
2329  return is_object() ? m_value.object : nullptr;
2330  }
2331 
2333  const object_t* get_impl_ptr(const object_t*) const noexcept
2334  {
2335  return is_object() ? m_value.object : nullptr;
2336  }
2337 
2339  array_t* get_impl_ptr(array_t*) noexcept
2340  {
2341  return is_array() ? m_value.array : nullptr;
2342  }
2343 
2345  const array_t* get_impl_ptr(const array_t*) const noexcept
2346  {
2347  return is_array() ? m_value.array : nullptr;
2348  }
2349 
2351  string_t* get_impl_ptr(string_t*) noexcept
2352  {
2353  return is_string() ? m_value.string : nullptr;
2354  }
2355 
2357  const string_t* get_impl_ptr(const string_t*) const noexcept
2358  {
2359  return is_string() ? m_value.string : nullptr;
2360  }
2361 
2363  boolean_t* get_impl_ptr(boolean_t*) noexcept
2364  {
2365  return is_boolean() ? &m_value.boolean : nullptr;
2366  }
2367 
2369  const boolean_t* get_impl_ptr(const boolean_t*) const noexcept
2370  {
2371  return is_boolean() ? &m_value.boolean : nullptr;
2372  }
2373 
2375  number_integer_t* get_impl_ptr(number_integer_t*) noexcept
2376  {
2377  return is_number_integer() ? &m_value.number_integer : nullptr;
2378  }
2379 
2381  const number_integer_t* get_impl_ptr(const number_integer_t*) const noexcept
2382  {
2383  return is_number_integer() ? &m_value.number_integer : nullptr;
2384  }
2385 
2387  number_float_t* get_impl_ptr(number_float_t*) noexcept
2388  {
2389  return is_number_float() ? &m_value.number_float : nullptr;
2390  }
2391 
2393  const number_float_t* get_impl_ptr(const number_float_t*) const noexcept
2394  {
2395  return is_number_float() ? &m_value.number_float : nullptr;
2396  }
2397 
2398  public:
2399 
2402 
2436  template<typename ValueType, typename
2437  std::enable_if<
2438  not std::is_pointer<ValueType>::value
2439  , int>::type = 0>
2440  ValueType get() const
2441  {
2442  return get_impl(static_cast<ValueType*>(nullptr));
2443  }
2444 
2471  template<typename PointerType, typename
2472  std::enable_if<
2473  std::is_pointer<PointerType>::value
2474  , int>::type = 0>
2475  PointerType get() noexcept
2476  {
2477  // delegate the call to get_ptr
2478  return get_ptr<PointerType>();
2479  }
2480 
2485  template<typename PointerType, typename
2486  std::enable_if<
2487  std::is_pointer<PointerType>::value
2488  , int>::type = 0>
2489  const PointerType get() const noexcept
2490  {
2491  // delegate the call to get_ptr
2492  return get_ptr<PointerType>();
2493  }
2494 
2520  template<typename PointerType, typename
2521  std::enable_if<
2522  std::is_pointer<PointerType>::value
2523  , int>::type = 0>
2524  PointerType get_ptr() noexcept
2525  {
2526  // delegate the call to get_impl_ptr<>()
2527  return get_impl_ptr(static_cast<PointerType>(nullptr));
2528  }
2529 
2534  template<typename PointerType, typename
2535  std::enable_if<
2536  std::is_pointer<PointerType>::value
2537  and std::is_const<typename std::remove_pointer<PointerType>::type>::value
2538  , int>::type = 0>
2539  const PointerType get_ptr() const noexcept
2540  {
2541  // delegate the call to get_impl_ptr<>() const
2542  return get_impl_ptr(static_cast<const PointerType>(nullptr));
2543  }
2544 
2573  template<typename ValueType, typename
2574  std::enable_if<
2575  not std::is_pointer<ValueType>::value
2576  and not std::is_same<ValueType, typename string_t::value_type>::value
2577  and not std::is_same<ValueType, std::initializer_list<typename string_t::value_type>>::value
2578  , int>::type = 0>
2579  operator ValueType() const
2580  {
2581  // delegate the call to get<>() const
2582  return get<ValueType>();
2583  }
2584 
2586 
2587 
2589  // element access //
2591 
2594 
2618  {
2619  // at only works for arrays
2620  if (is_array())
2621  {
2622  try
2623  {
2624  return m_value.array->at(idx);
2625  }
2626  catch (std::out_of_range& e)
2627  {
2628  // create better exception explanation
2629  throw std::out_of_range("array index " + std::to_string(idx) + " is out of range");
2630  }
2631  }
2632  else
2633  {
2634  throw std::domain_error("cannot use at() with " + type_name());
2635  }
2636  }
2637 
2661  {
2662  // at only works for arrays
2663  if (is_array())
2664  {
2665  try
2666  {
2667  return m_value.array->at(idx);
2668  }
2669  catch (std::out_of_range& e)
2670  {
2671  // create better exception explanation
2672  throw std::out_of_range("array index " + std::to_string(idx) + " is out of range");
2673  }
2674  }
2675  else
2676  {
2677  throw std::domain_error("cannot use at() with " + type_name());
2678  }
2679  }
2680 
2707  reference at(const typename object_t::key_type& key)
2708  {
2709  // at only works for objects
2710  if (is_object())
2711  {
2712  try
2713  {
2714  return m_value.object->at(key);
2715  }
2716  catch (std::out_of_range& e)
2717  {
2718  // create better exception explanation
2719  throw std::out_of_range("key '" + key + "' not found");
2720  }
2721  }
2722  else
2723  {
2724  throw std::domain_error("cannot use at() with " + type_name());
2725  }
2726  }
2727 
2754  const_reference at(const typename object_t::key_type& key) const
2755  {
2756  // at only works for objects
2757  if (is_object())
2758  {
2759  try
2760  {
2761  return m_value.object->at(key);
2762  }
2763  catch (std::out_of_range& e)
2764  {
2765  // create better exception explanation
2766  throw std::out_of_range("key '" + key + "' not found");
2767  }
2768  }
2769  else
2770  {
2771  throw std::domain_error("cannot use at() with " + type_name());
2772  }
2773  }
2774 
2800  {
2801  // implicitly convert null to object
2802  if (is_null())
2803  {
2804  m_type = value_t::array;
2805  m_value.array = create<array_t>();
2806  }
2807 
2808  // [] only works for arrays
2809  if (is_array())
2810  {
2811  for (size_t i = m_value.array->size(); i <= idx; ++i)
2812  {
2813  m_value.array->push_back(basic_json());
2814  }
2815 
2816  return m_value.array->operator[](idx);
2817  }
2818  else
2819  {
2820  throw std::domain_error("cannot use operator[] with " + type_name());
2821  }
2822  }
2823 
2843  {
2844  // at only works for arrays
2845  if (is_array())
2846  {
2847  return m_value.array->operator[](idx);
2848  }
2849  else
2850  {
2851  throw std::domain_error("cannot use operator[] with " + type_name());
2852  }
2853  }
2854 
2881  reference operator[](const typename object_t::key_type& key)
2882  {
2883  // implicitly convert null to object
2884  if (is_null())
2885  {
2886  m_type = value_t::object;
2887  m_value.object = create<object_t>();
2888  }
2889 
2890  // [] only works for objects
2891  if (is_object())
2892  {
2893  return m_value.object->operator[](key);
2894  }
2895  else
2896  {
2897  throw std::domain_error("cannot use operator[] with " + type_name());
2898  }
2899  }
2900 
2927  const_reference operator[](const typename object_t::key_type& key) const
2928  {
2929  // [] only works for objects
2930  if (is_object())
2931  {
2932  return m_value.object->find(key)->second;
2933  }
2934  else
2935  {
2936  throw std::domain_error("cannot use operator[] with " + type_name());
2937  }
2938  }
2939 
2968  template<typename T, std::size_t n>
2969  reference operator[](const T (&key)[n])
2970  {
2971  // implicitly convert null to object
2972  if (is_null())
2973  {
2974  m_type = value_t::object;
2975  m_value = value_t::object;
2976  }
2977 
2978  // at only works for objects
2979  if (is_object())
2980  {
2981  return m_value.object->operator[](key);
2982  }
2983  else
2984  {
2985  throw std::domain_error("cannot use operator[] with " + type_name());
2986  }
2987  }
2988 
3017  template<typename T, std::size_t n>
3018  const_reference operator[](const T (&key)[n]) const
3019  {
3020  // at only works for objects
3021  if (is_object())
3022  {
3023  return m_value.object->find(key)->second;
3024  }
3025  else
3026  {
3027  throw std::domain_error("cannot use operator[] with " + type_name());
3028  }
3029  }
3030 
3078  template <class ValueType, typename
3079  std::enable_if<
3080  std::is_convertible<basic_json_t, ValueType>::value
3081  , int>::type = 0>
3082  ValueType value(const typename object_t::key_type& key, ValueType default_value) const
3083  {
3084  // at only works for objects
3085  if (is_object())
3086  {
3087  // if key is found, return value and given default value otherwise
3088  const auto it = find(key);
3089  if (it != end())
3090  {
3091  return *it;
3092  }
3093  else
3094  {
3095  return default_value;
3096  }
3097  }
3098  else
3099  {
3100  throw std::domain_error("cannot use value() with " + type_name());
3101  }
3102  }
3103 
3108  string_t value(const typename object_t::key_type& key, const char* default_value) const
3109  {
3110  return value(key, string_t(default_value));
3111  }
3112 
3134  {
3135  return *begin();
3136  }
3137 
3142  {
3143  return *cbegin();
3144  }
3145 
3168  {
3169  auto tmp = end();
3170  --tmp;
3171  return *tmp;
3172  }
3173 
3178  {
3179  auto tmp = cend();
3180  --tmp;
3181  return *tmp;
3182  }
3183 
3226  template <class InteratorType, typename
3227  std::enable_if<
3228  std::is_same<InteratorType, typename basic_json_t::iterator>::value or
3229  std::is_same<InteratorType, typename basic_json_t::const_iterator>::value
3230  , int>::type
3231  = 0>
3232  InteratorType erase(InteratorType pos)
3233  {
3234  // make sure iterator fits the current value
3235  if (this != pos.m_object)
3236  {
3237  throw std::domain_error("iterator does not fit current value");
3238  }
3239 
3240  InteratorType result = end();
3241 
3242  switch (m_type)
3243  {
3244  case value_t::boolean:
3245  case value_t::number_float:
3247  case value_t::string:
3248  {
3249  if (not pos.m_it.primitive_iterator.is_begin())
3250  {
3251  throw std::out_of_range("iterator out of range");
3252  }
3253 
3254  if (is_string())
3255  {
3256  delete m_value.string;
3257  m_value.string = nullptr;
3258  }
3259 
3260  m_type = value_t::null;
3261  break;
3262  }
3263 
3264  case value_t::object:
3265  {
3266  result.m_it.object_iterator = m_value.object->erase(pos.m_it.object_iterator);
3267  break;
3268  }
3269 
3270  case value_t::array:
3271  {
3272  result.m_it.array_iterator = m_value.array->erase(pos.m_it.array_iterator);
3273  break;
3274  }
3275 
3276  default:
3277  {
3278  throw std::domain_error("cannot use erase() with " + type_name());
3279  }
3280  }
3281 
3282  return result;
3283  }
3284 
3327  template <class InteratorType, typename
3328  std::enable_if<
3329  std::is_same<InteratorType, typename basic_json_t::iterator>::value or
3330  std::is_same<InteratorType, typename basic_json_t::const_iterator>::value
3331  , int>::type
3332  = 0>
3333  InteratorType erase(InteratorType first, InteratorType last)
3334  {
3335  // make sure iterator fits the current value
3336  if (this != first.m_object or this != last.m_object)
3337  {
3338  throw std::domain_error("iterators do not fit current value");
3339  }
3340 
3341  InteratorType result = end();
3342 
3343  switch (m_type)
3344  {
3345  case value_t::boolean:
3346  case value_t::number_float:
3348  case value_t::string:
3349  {
3350  if (not first.m_it.primitive_iterator.is_begin() or not last.m_it.primitive_iterator.is_end())
3351  {
3352  throw std::out_of_range("iterators out of range");
3353  }
3354 
3355  if (is_string())
3356  {
3357  delete m_value.string;
3358  m_value.string = nullptr;
3359  }
3360 
3361  m_type = value_t::null;
3362  break;
3363  }
3364 
3365  case value_t::object:
3366  {
3367  result.m_it.object_iterator = m_value.object->erase(first.m_it.object_iterator,
3368  last.m_it.object_iterator);
3369  break;
3370  }
3371 
3372  case value_t::array:
3373  {
3374  result.m_it.array_iterator = m_value.array->erase(first.m_it.array_iterator,
3375  last.m_it.array_iterator);
3376  break;
3377  }
3378 
3379  default:
3380  {
3381  throw std::domain_error("cannot use erase with " + type_name());
3382  }
3383  }
3384 
3385  return result;
3386  }
3387 
3413  size_type erase(const typename object_t::key_type& key)
3414  {
3415  // this erase only works for objects
3416  if (is_object())
3417  {
3418  return m_value.object->erase(key);
3419  }
3420  else
3421  {
3422  throw std::domain_error("cannot use erase() with " + type_name());
3423  }
3424  }
3425 
3448  void erase(const size_type idx)
3449  {
3450  // this erase only works for arrays
3451  if (is_array())
3452  {
3453  if (idx >= size())
3454  {
3455  throw std::out_of_range("index out of range");
3456  }
3457 
3458  m_value.array->erase(m_value.array->begin() + static_cast<difference_type>(idx));
3459  }
3460  else
3461  {
3462  throw std::domain_error("cannot use erase() with " + type_name());
3463  }
3464  }
3465 
3483  iterator find(typename object_t::key_type key)
3484  {
3485  auto result = end();
3486 
3487  if (is_object())
3488  {
3489  result.m_it.object_iterator = m_value.object->find(key);
3490  }
3491 
3492  return result;
3493  }
3494 
3499  const_iterator find(typename object_t::key_type key) const
3500  {
3501  auto result = cend();
3502 
3503  if (is_object())
3504  {
3505  result.m_it.object_iterator = m_value.object->find(key);
3506  }
3507 
3508  return result;
3509  }
3510 
3529  size_type count(typename object_t::key_type key) const
3530  {
3531  // return 0 for all nonobject types
3532  return is_object() ? m_value.object->count(key) : 0;
3533  }
3534 
3536 
3537 
3539  // iterators //
3541 
3544 
3564  {
3565  iterator result(this);
3566  result.set_begin();
3567  return result;
3568  }
3569 
3574  {
3575  return cbegin();
3576  }
3577 
3598  {
3599  const_iterator result(this);
3600  result.set_begin();
3601  return result;
3602  }
3603 
3623  {
3624  iterator result(this);
3625  result.set_end();
3626  return result;
3627  }
3628 
3633  {
3634  return cend();
3635  }
3636 
3657  {
3658  const_iterator result(this);
3659  result.set_end();
3660  return result;
3661  }
3662 
3681  {
3682  return reverse_iterator(end());
3683  }
3684 
3689  {
3690  return crbegin();
3691  }
3692 
3712  {
3713  return reverse_iterator(begin());
3714  }
3715 
3720  {
3721  return crend();
3722  }
3723 
3743  {
3744  return const_reverse_iterator(cend());
3745  }
3746 
3766  {
3767  return const_reverse_iterator(cbegin());
3768  }
3769 
3771 
3772 
3774  // capacity //
3776 
3779 
3809  bool empty() const noexcept
3810  {
3811  switch (m_type)
3812  {
3813  case value_t::null:
3814  {
3815  // null values are empty
3816  return true;
3817  }
3818 
3819  case value_t::array:
3820  {
3821  return m_value.array->empty();
3822  }
3823 
3824  case value_t::object:
3825  {
3826  return m_value.object->empty();
3827  }
3828 
3829  default:
3830  {
3831  // all other types are nonempty
3832  return false;
3833  }
3834  }
3835  }
3836 
3866  size_type size() const noexcept
3867  {
3868  switch (m_type)
3869  {
3870  case value_t::null:
3871  {
3872  // null values are empty
3873  return 0;
3874  }
3875 
3876  case value_t::array:
3877  {
3878  return m_value.array->size();
3879  }
3880 
3881  case value_t::object:
3882  {
3883  return m_value.object->size();
3884  }
3885 
3886  default:
3887  {
3888  // all other types have size 1
3889  return 1;
3890  }
3891  }
3892  }
3893 
3926  size_type max_size() const noexcept
3927  {
3928  switch (m_type)
3929  {
3930  case value_t::array:
3931  {
3932  return m_value.array->max_size();
3933  }
3934 
3935  case value_t::object:
3936  {
3937  return m_value.object->max_size();
3938  }
3939 
3940  default:
3941  {
3942  // all other types have max_size() == size()
3943  return size();
3944  }
3945  }
3946  }
3947 
3949 
3950 
3952  // modifiers //
3954 
3957 
3983  void clear() noexcept
3984  {
3985  switch (m_type)
3986  {
3988  {
3989  m_value.number_integer = 0;
3990  break;
3991  }
3992 
3993  case value_t::number_float:
3994  {
3995  m_value.number_float = 0.0;
3996  break;
3997  }
3998 
3999  case value_t::boolean:
4000  {
4001  m_value.boolean = false;
4002  break;
4003  }
4004 
4005  case value_t::string:
4006  {
4007  m_value.string->clear();
4008  break;
4009  }
4010 
4011  case value_t::array:
4012  {
4013  m_value.array->clear();
4014  break;
4015  }
4016 
4017  case value_t::object:
4018  {
4019  m_value.object->clear();
4020  break;
4021  }
4022 
4023  default:
4024  {
4025  break;
4026  }
4027  }
4028  }
4029 
4049  void push_back(basic_json&& val)
4050  {
4051  // push_back only works for null objects or arrays
4052  if (not(is_null() or is_array()))
4053  {
4054  throw std::domain_error("cannot use push_back() with " + type_name());
4055  }
4056 
4057  // transform null object into an array
4058  if (is_null())
4059  {
4060  m_type = value_t::array;
4061  m_value = value_t::array;
4062  }
4063 
4064  // add element to array (move semantics)
4065  m_value.array->push_back(std::move(val));
4066  // invalidate object
4067  val.m_type = value_t::null;
4068  }
4069 
4074  reference operator+=(basic_json&& val)
4075  {
4076  push_back(std::move(val));
4077  return *this;
4078  }
4079 
4084  void push_back(const basic_json& val)
4085  {
4086  // push_back only works for null objects or arrays
4087  if (not(is_null() or is_array()))
4088  {
4089  throw std::domain_error("cannot use push_back() with " + type_name());
4090  }
4091 
4092  // transform null object into an array
4093  if (is_null())
4094  {
4095  m_type = value_t::array;
4096  m_value = value_t::array;
4097  }
4098 
4099  // add element to array
4100  m_value.array->push_back(val);
4101  }
4102 
4107  reference operator+=(const basic_json& val)
4108  {
4109  push_back(val);
4110  return *this;
4111  }
4112 
4133  void push_back(const typename object_t::value_type& val)
4134  {
4135  // push_back only works for null objects or objects
4136  if (not(is_null() or is_object()))
4137  {
4138  throw std::domain_error("cannot use push_back() with " + type_name());
4139  }
4140 
4141  // transform null object into an object
4142  if (is_null())
4143  {
4144  m_type = value_t::object;
4145  m_value = value_t::object;
4146  }
4147 
4148  // add element to array
4149  m_value.object->insert(val);
4150  }
4151 
4156  reference operator+=(const typename object_t::value_type& val)
4157  {
4158  push_back(val);
4159  return operator[](val.first);
4160  }
4161 
4182  iterator insert(const_iterator pos, const basic_json& val)
4183  {
4184  // insert only works for arrays
4185  if (is_array())
4186  {
4187  // check if iterator pos fits to this JSON value
4188  if (pos.m_object != this)
4189  {
4190  throw std::domain_error("iterator does not fit current value");
4191  }
4192 
4193  // insert to array and return iterator
4194  iterator result(this);
4195  result.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator, val);
4196  return result;
4197  }
4198  else
4199  {
4200  throw std::domain_error("cannot use insert() with " + type_name());
4201  }
4202  }
4203 
4208  iterator insert(const_iterator pos, basic_json&& val)
4209  {
4210  return insert(pos, val);
4211  }
4212 
4235  iterator insert(const_iterator pos, size_type cnt, const basic_json& val)
4236  {
4237  // insert only works for arrays
4238  if (is_array())
4239  {
4240  // check if iterator pos fits to this JSON value
4241  if (pos.m_object != this)
4242  {
4243  throw std::domain_error("iterator does not fit current value");
4244  }
4245 
4246  // insert to array and return iterator
4247  iterator result(this);
4248  result.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator, cnt, val);
4249  return result;
4250  }
4251  else
4252  {
4253  throw std::domain_error("cannot use insert() with " + type_name());
4254  }
4255  }
4256 
4284  {
4285  // insert only works for arrays
4286  if (not is_array())
4287  {
4288  throw std::domain_error("cannot use insert() with " + type_name());
4289  }
4290 
4291  // check if iterator pos fits to this JSON value
4292  if (pos.m_object != this)
4293  {
4294  throw std::domain_error("iterator does not fit current value");
4295  }
4296 
4297  if (first.m_object != last.m_object)
4298  {
4299  throw std::domain_error("iterators do not fit");
4300  }
4301 
4302  if (first.m_object == this or last.m_object == this)
4303  {
4304  throw std::domain_error("passed iterators may not belong to container");
4305  }
4306 
4307  // insert to array and return iterator
4308  iterator result(this);
4309  result.m_it.array_iterator = m_value.array->insert(
4310  pos.m_it.array_iterator,
4311  first.m_it.array_iterator,
4312  last.m_it.array_iterator);
4313  return result;
4314  }
4315 
4337  iterator insert(const_iterator pos, std::initializer_list<basic_json> ilist)
4338  {
4339  // insert only works for arrays
4340  if (not is_array())
4341  {
4342  throw std::domain_error("cannot use insert() with " + type_name());
4343  }
4344 
4345  // check if iterator pos fits to this JSON value
4346  if (pos.m_object != this)
4347  {
4348  throw std::domain_error("iterator does not fit current value");
4349  }
4350 
4351  // insert to array and return iterator
4352  iterator result(this);
4353  result.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator, ilist);
4354  return result;
4355  }
4356 
4374  void swap(reference other) noexcept (
4375  std::is_nothrow_move_constructible<value_t>::value and
4376  std::is_nothrow_move_assignable<value_t>::value and
4377  std::is_nothrow_move_constructible<json_value>::value and
4378  std::is_nothrow_move_assignable<json_value>::value
4379  )
4380  {
4381  std::swap(m_type, other.m_type);
4382  std::swap(m_value, other.m_value);
4383  }
4384 
4404  void swap(array_t& other)
4405  {
4406  // swap only works for arrays
4407  if (is_array())
4408  {
4409  std::swap(*(m_value.array), other);
4410  }
4411  else
4412  {
4413  throw std::domain_error("cannot use swap() with " + type_name());
4414  }
4415  }
4416 
4436  void swap(object_t& other)
4437  {
4438  // swap only works for objects
4439  if (is_object())
4440  {
4441  std::swap(*(m_value.object), other);
4442  }
4443  else
4444  {
4445  throw std::domain_error("cannot use swap() with " + type_name());
4446  }
4447  }
4448 
4468  void swap(string_t& other)
4469  {
4470  // swap only works for strings
4471  if (is_string())
4472  {
4473  std::swap(*(m_value.string), other);
4474  }
4475  else
4476  {
4477  throw std::domain_error("cannot use swap() with " + type_name());
4478  }
4479  }
4480 
4482 
4483 
4485  // lexicographical comparison operators //
4487 
4490 
4491  private:
4501  friend bool operator<(const value_t lhs, const value_t rhs)
4502  {
4503  static constexpr std::array<uint8_t, 7> order = {{
4504  0, // null
4505  3, // object
4506  4, // array
4507  5, // string
4508  1, // boolean
4509  2, // integer
4510  2 // float
4511  }
4512  };
4513 
4514  // discarded values are not comparable
4515  if (lhs == value_t::discarded or rhs == value_t::discarded)
4516  {
4517  return false;
4518  }
4519 
4520  return order[static_cast<std::size_t>(lhs)] < order[static_cast<std::size_t>(rhs)];
4521  }
4522 
4523  public:
4547  friend bool operator==(const_reference lhs, const_reference rhs) noexcept
4548  {
4549  const auto lhs_type = lhs.type();
4550  const auto rhs_type = rhs.type();
4551 
4552  if (lhs_type == rhs_type)
4553  {
4554  switch (lhs_type)
4555  {
4556  case value_t::array:
4557  return *lhs.m_value.array == *rhs.m_value.array;
4558  case value_t::object:
4559  return *lhs.m_value.object == *rhs.m_value.object;
4560  case value_t::null:
4561  return true;
4562  case value_t::string:
4563  return *lhs.m_value.string == *rhs.m_value.string;
4564  case value_t::boolean:
4565  return lhs.m_value.boolean == rhs.m_value.boolean;
4567  return lhs.m_value.number_integer == rhs.m_value.number_integer;
4568  case value_t::number_float:
4569  return approx(lhs.m_value.number_float, rhs.m_value.number_float);
4570  default:
4571  return false;
4572  }
4573  }
4574  else if (lhs_type == value_t::number_integer and rhs_type == value_t::number_float)
4575  {
4576  return approx(static_cast<number_float_t>(lhs.m_value.number_integer),
4577  rhs.m_value.number_float);
4578  }
4579  else if (lhs_type == value_t::number_float and rhs_type == value_t::number_integer)
4580  {
4581  return approx(lhs.m_value.number_float,
4582  static_cast<number_float_t>(rhs.m_value.number_integer));
4583  }
4584  return false;
4585  }
4586 
4605  friend bool operator==(const_reference v, std::nullptr_t) noexcept
4606  {
4607  return v.is_null();
4608  }
4609 
4614  friend bool operator==(std::nullptr_t, const_reference v) noexcept
4615  {
4616  return v.is_null();
4617  }
4618 
4635  friend bool operator!=(const_reference lhs, const_reference rhs) noexcept
4636  {
4637  return not (lhs == rhs);
4638  }
4639 
4658  friend bool operator!=(const_reference v, std::nullptr_t) noexcept
4659  {
4660  return not v.is_null();
4661  }
4662 
4667  friend bool operator!=(std::nullptr_t, const_reference v) noexcept
4668  {
4669  return not v.is_null();
4670  }
4671 
4696  friend bool operator<(const_reference lhs, const_reference rhs) noexcept
4697  {
4698  const auto lhs_type = lhs.type();
4699  const auto rhs_type = rhs.type();
4700 
4701  if (lhs_type == rhs_type)
4702  {
4703  switch (lhs_type)
4704  {
4705  case value_t::array:
4706  return *lhs.m_value.array < *rhs.m_value.array;
4707  case value_t::object:
4708  return *lhs.m_value.object < *rhs.m_value.object;
4709  case value_t::null:
4710  return false;
4711  case value_t::string:
4712  return *lhs.m_value.string < *rhs.m_value.string;
4713  case value_t::boolean:
4714  return lhs.m_value.boolean < rhs.m_value.boolean;
4716  return lhs.m_value.number_integer < rhs.m_value.number_integer;
4717  case value_t::number_float:
4718  return lhs.m_value.number_float < rhs.m_value.number_float;
4719  default:
4720  return false;
4721  }
4722  }
4723  else if (lhs_type == value_t::number_integer and rhs_type == value_t::number_float)
4724  {
4725  return static_cast<number_float_t>(lhs.m_value.number_integer) <
4726  rhs.m_value.number_float;
4727  }
4728  else if (lhs_type == value_t::number_float and rhs_type == value_t::number_integer)
4729  {
4730  return lhs.m_value.number_float <
4731  static_cast<number_float_t>(rhs.m_value.number_integer);
4732  }
4733 
4734  // We only reach this line if we cannot compare values. In that case,
4735  // we compare types. Note we have to call the operator explicitly,
4736  // because MSVC has problems otherwise.
4737  return operator<(lhs_type, rhs_type);
4738  }
4739 
4757  friend bool operator<=(const_reference lhs, const_reference rhs) noexcept
4758  {
4759  return not (rhs < lhs);
4760  }
4761 
4779  friend bool operator>(const_reference lhs, const_reference rhs) noexcept
4780  {
4781  return not (lhs <= rhs);
4782  }
4783 
4801  friend bool operator>=(const_reference lhs, const_reference rhs) noexcept
4802  {
4803  return not (lhs < rhs);
4804  }
4805 
4807 
4808 
4810  // serialization //
4812 
4815 
4838  friend std::ostream& operator<<(std::ostream& o, const basic_json& j)
4839  {
4840  // read width member and use it as indentation parameter if nonzero
4841  const bool pretty_print = (o.width() > 0);
4842  const auto indentation = (pretty_print ? o.width() : 0);
4843 
4844  // reset width to 0 for subsequent calls to this stream
4845  o.width(0);
4846 
4847  // do the actual serialization
4848  j.dump(o, pretty_print, static_cast<unsigned int>(indentation));
4849  return o;
4850  }
4851 
4856  friend std::ostream& operator>>(const basic_json& j, std::ostream& o)
4857  {
4858  return o << j;
4859  }
4860 
4862 
4863 
4865  // deserialization //
4867 
4870 
4895  static basic_json parse(const string_t& s, parser_callback_t cb = nullptr)
4896  {
4897  return parser(s, cb).parse();
4898  }
4899 
4924  static basic_json parse(std::istream& i, parser_callback_t cb = nullptr)
4925  {
4926  return parser(i, cb).parse();
4927  }
4928 
4932  static basic_json parse(std::istream&& i, parser_callback_t cb = nullptr)
4933  {
4934  return parser(i, cb).parse();
4935  }
4936 
4960  friend std::istream& operator<<(basic_json& j, std::istream& i)
4961  {
4962  j = parser(i).parse();
4963  return i;
4964  }
4965 
4970  friend std::istream& operator>>(std::istream& i, basic_json& j)
4971  {
4972  j = parser(i).parse();
4973  return i;
4974  }
4975 
4977 
4978 
4979  private:
4981  // convenience functions //
4983 
4985  string_t type_name() const
4986  {
4987  switch (m_type)
4988  {
4989  case value_t::null:
4990  return "null";
4991  case value_t::object:
4992  return "object";
4993  case value_t::array:
4994  return "array";
4995  case value_t::string:
4996  return "string";
4997  case value_t::boolean:
4998  return "boolean";
4999  case value_t::discarded:
5000  return "discarded";
5001  default:
5002  return "number";
5003  }
5004  }
5005 
5014  static std::size_t extra_space(const string_t& s) noexcept
5015  {
5016  std::size_t result = 0;
5017 
5018  for (const auto& c : s)
5019  {
5020  switch (c)
5021  {
5022  case '"':
5023  case '\\':
5024  case '\b':
5025  case '\f':
5026  case '\n':
5027  case '\r':
5028  case '\t':
5029  {
5030  // from c (1 byte) to \x (2 bytes)
5031  result += 1;
5032  break;
5033  }
5034 
5035  default:
5036  {
5037  if (c >= 0x00 and c <= 0x1f)
5038  {
5039  // from c (1 byte) to \uxxxx (6 bytes)
5040  result += 5;
5041  }
5042  break;
5043  }
5044  }
5045  }
5046 
5047  return result;
5048  }
5049 
5063  static string_t escape_string(const string_t& s) noexcept
5064  {
5065  const auto space = extra_space(s);
5066  if (space == 0)
5067  {
5068  return s;
5069  }
5070 
5071  // create a result string of necessary size
5072  string_t result(s.size() + space, '\\');
5073  std::size_t pos = 0;
5074 
5075  for (const auto& c : s)
5076  {
5077  switch (c)
5078  {
5079  // quotation mark (0x22)
5080  case '"':
5081  {
5082  result[pos + 1] = '"';
5083  pos += 2;
5084  break;
5085  }
5086 
5087  // reverse solidus (0x5c)
5088  case '\\':
5089  {
5090  // nothing to change
5091  pos += 2;
5092  break;
5093  }
5094 
5095  // backspace (0x08)
5096  case '\b':
5097  {
5098  result[pos + 1] = 'b';
5099  pos += 2;
5100  break;
5101  }
5102 
5103  // formfeed (0x0c)
5104  case '\f':
5105  {
5106  result[pos + 1] = 'f';
5107  pos += 2;
5108  break;
5109  }
5110 
5111  // newline (0x0a)
5112  case '\n':
5113  {
5114  result[pos + 1] = 'n';
5115  pos += 2;
5116  break;
5117  }
5118 
5119  // carriage return (0x0d)
5120  case '\r':
5121  {
5122  result[pos + 1] = 'r';
5123  pos += 2;
5124  break;
5125  }
5126 
5127  // horizontal tab (0x09)
5128  case '\t':
5129  {
5130  result[pos + 1] = 't';
5131  pos += 2;
5132  break;
5133  }
5134 
5135  default:
5136  {
5137  if (c >= 0x00 and c <= 0x1f)
5138  {
5139  // convert a number 0..15 to its hex representation (0..f)
5140  auto hexify = [](const char v) -> char
5141  {
5142  return (v < 10) ? ('0' + v) : ('a' + v - 10);
5143  };
5144 
5145  // print character c as \uxxxx
5146  for (const char m :
5147  { 'u', '0', '0', hexify(c >> 4), hexify(c & 0x0f)
5148  })
5149  {
5150  result[++pos] = m;
5151  }
5152 
5153  ++pos;
5154  }
5155  else
5156  {
5157  // all other characters are added as-is
5158  result[pos++] = c;
5159  }
5160  break;
5161  }
5162  }
5163  }
5164 
5165  return result;
5166  }
5167 
5185  void dump(std::ostream& o,
5186  const bool pretty_print,
5187  const unsigned int indent_step,
5188  const unsigned int current_indent = 0) const
5189  {
5190  // variable to hold indentation for recursive calls
5191  unsigned int new_indent = current_indent;
5192 
5193  switch (m_type)
5194  {
5195  case value_t::object:
5196  {
5197  if (m_value.object->empty())
5198  {
5199  o << "{}";
5200  return;
5201  }
5202 
5203  o << "{";
5204 
5205  // increase indentation
5206  if (pretty_print)
5207  {
5208  new_indent += indent_step;
5209  o << "\n";
5210  }
5211 
5212  for (auto i = m_value.object->cbegin(); i != m_value.object->cend(); ++i)
5213  {
5214  if (i != m_value.object->cbegin())
5215  {
5216  o << (pretty_print ? ",\n" : ",");
5217  }
5218  o << string_t(new_indent, ' ') << "\""
5219  << escape_string(i->first) << "\":"
5220  << (pretty_print ? " " : "");
5221  i->second.dump(o, pretty_print, indent_step, new_indent);
5222  }
5223 
5224  // decrease indentation
5225  if (pretty_print)
5226  {
5227  new_indent -= indent_step;
5228  o << "\n";
5229  }
5230 
5231  o << string_t(new_indent, ' ') + "}";
5232  return;
5233  }
5234 
5235  case value_t::array:
5236  {
5237  if (m_value.array->empty())
5238  {
5239  o << "[]";
5240  return;
5241  }
5242 
5243  o << "[";
5244 
5245  // increase indentation
5246  if (pretty_print)
5247  {
5248  new_indent += indent_step;
5249  o << "\n";
5250  }
5251 
5252  for (auto i = m_value.array->cbegin(); i != m_value.array->cend(); ++i)
5253  {
5254  if (i != m_value.array->cbegin())
5255  {
5256  o << (pretty_print ? ",\n" : ",");
5257  }
5258  o << string_t(new_indent, ' ');
5259  i->dump(o, pretty_print, indent_step, new_indent);
5260  }
5261 
5262  // decrease indentation
5263  if (pretty_print)
5264  {
5265  new_indent -= indent_step;
5266  o << "\n";
5267  }
5268 
5269  o << string_t(new_indent, ' ') << "]";
5270  return;
5271  }
5272 
5273  case value_t::string:
5274  {
5275  o << string_t("\"") << escape_string(*m_value.string) << "\"";
5276  return;
5277  }
5278 
5279  case value_t::boolean:
5280  {
5281  o << (m_value.boolean ? "true" : "false");
5282  return;
5283  }
5284 
5286  {
5287  o << m_value.number_integer;
5288  return;
5289  }
5290 
5291  case value_t::number_float:
5292  {
5293  // 15 digits of precision allows round-trip IEEE 754
5294  // string->double->string; to be safe, we read this value from
5295  // std::numeric_limits<number_float_t>::digits10
5296  o << std::setprecision(std::numeric_limits<number_float_t>::digits10) << m_value.number_float;
5297  return;
5298  }
5299 
5300  case value_t::discarded:
5301  {
5302  o << "<discarded>";
5303  return;
5304  }
5305 
5306  case value_t::null:
5307  {
5308  o << "null";
5309  return;
5310  }
5311  }
5312  }
5313 
5314  private:
5316  // member variables //
5318 
5320  value_t m_type = value_t::null;
5321 
5323  json_value m_value = {};
5324 
5325 
5326  private:
5328  // iterators //
5330 
5340  class primitive_iterator_t
5341  {
5342  public:
5344  void set_begin()
5345  {
5346  m_it = begin_value;
5347  }
5348 
5350  void set_end()
5351  {
5352  m_it = end_value;
5353  }
5354 
5356  bool is_begin() const
5357  {
5358  return (m_it == begin_value);
5359  }
5360 
5362  bool is_end() const
5363  {
5364  return (m_it == end_value);
5365  }
5366 
5368  operator difference_type& ()
5369  {
5370  return m_it;
5371  }
5372 
5374  operator difference_type () const
5375  {
5376  return m_it;
5377  }
5378 
5379  private:
5380  static constexpr difference_type begin_value = 0;
5381  static constexpr difference_type end_value = begin_value + 1;
5382 
5384  difference_type m_it = std::numeric_limits<std::ptrdiff_t>::denorm_min();
5385  };
5386 
5394  struct internal_iterator
5395  {
5397  typename object_t::iterator object_iterator;
5399  typename array_t::iterator array_iterator;
5401  primitive_iterator_t primitive_iterator;
5402 
5404  internal_iterator()
5405  : object_iterator(), array_iterator(), primitive_iterator()
5406  {}
5407  };
5408 
5409  public:
5423  class const_iterator : public std::iterator<std::random_access_iterator_tag, const basic_json>
5424  {
5426  friend class basic_json;
5427 
5428  public:
5438  using iterator_category = std::bidirectional_iterator_tag;
5439 
5441  const_iterator() = default;
5442 
5444  const_iterator(pointer object) : m_object(object)
5445  {
5446  switch (m_object->m_type)
5447  {
5449  {
5450  m_it.object_iterator = typename object_t::iterator();
5451  break;
5452  }
5453 
5455  {
5456  m_it.array_iterator = typename array_t::iterator();
5457  break;
5458  }
5459 
5460  default:
5461  {
5462  m_it.primitive_iterator = primitive_iterator_t();
5463  break;
5464  }
5465  }
5466  }
5467 
5469  const_iterator(const iterator& other) : m_object(other.m_object)
5470  {
5471  switch (m_object->m_type)
5472  {
5474  {
5475  m_it.object_iterator = other.m_it.object_iterator;
5476  break;
5477  }
5478 
5480  {
5481  m_it.array_iterator = other.m_it.array_iterator;
5482  break;
5483  }
5484 
5485  default:
5486  {
5487  m_it.primitive_iterator = other.m_it.primitive_iterator;
5488  break;
5489  }
5490  }
5491  }
5492 
5494  const_iterator(const const_iterator& other) noexcept
5495  : m_object(other.m_object), m_it(other.m_it)
5496  {}
5497 
5500  std::is_nothrow_move_constructible<pointer>::value and
5501  std::is_nothrow_move_assignable<pointer>::value and
5502  std::is_nothrow_move_constructible<internal_iterator>::value and
5503  std::is_nothrow_move_assignable<internal_iterator>::value
5504  )
5505  {
5506  std::swap(m_object, other.m_object);
5507  std::swap(m_it, other.m_it);
5508  return *this;
5509  }
5510 
5511  private:
5513  void set_begin()
5514  {
5515  switch (m_object->m_type)
5516  {
5518  {
5519  m_it.object_iterator = m_object->m_value.object->begin();
5520  break;
5521  }
5522 
5524  {
5525  m_it.array_iterator = m_object->m_value.array->begin();
5526  break;
5527  }
5528 
5530  {
5531  // set to end so begin()==end() is true: null is empty
5532  m_it.primitive_iterator.set_end();
5533  break;
5534  }
5535 
5536  default:
5537  {
5538  m_it.primitive_iterator.set_begin();
5539  break;
5540  }
5541  }
5542  }
5543 
5545  void set_end()
5546  {
5547  switch (m_object->m_type)
5548  {
5550  {
5551  m_it.object_iterator = m_object->m_value.object->end();
5552  break;
5553  }
5554 
5556  {
5557  m_it.array_iterator = m_object->m_value.array->end();
5558  break;
5559  }
5560 
5561  default:
5562  {
5563  m_it.primitive_iterator.set_end();
5564  break;
5565  }
5566  }
5567  }
5568 
5569  public:
5572  {
5573  switch (m_object->m_type)
5574  {
5576  {
5577  return m_it.object_iterator->second;
5578  }
5579 
5581  {
5582  return *m_it.array_iterator;
5583  }
5584 
5586  {
5587  throw std::out_of_range("cannot get value");
5588  }
5589 
5590  default:
5591  {
5592  if (m_it.primitive_iterator.is_begin())
5593  {
5594  return *m_object;
5595  }
5596  else
5597  {
5598  throw std::out_of_range("cannot get value");
5599  }
5600  }
5601  }
5602  }
5603 
5606  {
5607  switch (m_object->m_type)
5608  {
5610  {
5611  return &(m_it.object_iterator->second);
5612  }
5613 
5615  {
5616  return &*m_it.array_iterator;
5617  }
5618 
5619  default:
5620  {
5621  if (m_it.primitive_iterator.is_begin())
5622  {
5623  return m_object;
5624  }
5625  else
5626  {
5627  throw std::out_of_range("cannot get value");
5628  }
5629  }
5630  }
5631  }
5632 
5635  {
5636  auto result = *this;
5637  ++(*this);
5638  return result;
5639  }
5640 
5643  {
5644  switch (m_object->m_type)
5645  {
5647  {
5648  ++m_it.object_iterator;
5649  break;
5650  }
5651 
5653  {
5654  ++m_it.array_iterator;
5655  break;
5656  }
5657 
5658  default:
5659  {
5660  ++m_it.primitive_iterator;
5661  break;
5662  }
5663  }
5664 
5665  return *this;
5666  }
5667 
5670  {
5671  auto result = *this;
5672  --(*this);
5673  return result;
5674  }
5675 
5678  {
5679  switch (m_object->m_type)
5680  {
5682  {
5683  --m_it.object_iterator;
5684  break;
5685  }
5686 
5688  {
5689  --m_it.array_iterator;
5690  break;
5691  }
5692 
5693  default:
5694  {
5695  --m_it.primitive_iterator;
5696  break;
5697  }
5698  }
5699 
5700  return *this;
5701  }
5702 
5704  bool operator==(const const_iterator& other) const
5705  {
5706  // if objects are not the same, the comparison is undefined
5707  if (m_object != other.m_object)
5708  {
5709  throw std::domain_error("cannot compare iterators of different containers");
5710  }
5711 
5712  switch (m_object->m_type)
5713  {
5715  {
5716  return (m_it.object_iterator == other.m_it.object_iterator);
5717  }
5718 
5720  {
5721  return (m_it.array_iterator == other.m_it.array_iterator);
5722  }
5723 
5724  default:
5725  {
5726  return (m_it.primitive_iterator == other.m_it.primitive_iterator);
5727  }
5728  }
5729  }
5730 
5732  bool operator!=(const const_iterator& other) const
5733  {
5734  return not operator==(other);
5735  }
5736 
5738  bool operator<(const const_iterator& other) const
5739  {
5740  // if objects are not the same, the comparison is undefined
5741  if (m_object != other.m_object)
5742  {
5743  throw std::domain_error("cannot compare iterators of different containers");
5744  }
5745 
5746  switch (m_object->m_type)
5747  {
5749  {
5750  throw std::domain_error("cannot use operator< for object iterators");
5751  }
5752 
5754  {
5755  return (m_it.array_iterator < other.m_it.array_iterator);
5756  }
5757 
5758  default:
5759  {
5760  return (m_it.primitive_iterator < other.m_it.primitive_iterator);
5761  }
5762  }
5763  }
5764 
5766  bool operator<=(const const_iterator& other) const
5767  {
5768  return not other.operator < (*this);
5769  }
5770 
5772  bool operator>(const const_iterator& other) const
5773  {
5774  return not operator<=(other);
5775  }
5776 
5778  bool operator>=(const const_iterator& other) const
5779  {
5780  return not operator<(other);
5781  }
5782 
5785  {
5786  switch (m_object->m_type)
5787  {
5789  {
5790  throw std::domain_error("cannot use operator+= for object iterators");
5791  }
5792 
5794  {
5795  m_it.array_iterator += i;
5796  break;
5797  }
5798 
5799  default:
5800  {
5801  m_it.primitive_iterator += i;
5802  break;
5803  }
5804  }
5805 
5806  return *this;
5807  }
5808 
5811  {
5812  return operator+=(-i);
5813  }
5814 
5817  {
5818  auto result = *this;
5819  result += i;
5820  return result;
5821  }
5822 
5825  {
5826  auto result = *this;
5827  result -= i;
5828  return result;
5829  }
5830 
5833  {
5834  switch (m_object->m_type)
5835  {
5837  {
5838  throw std::domain_error("cannot use operator- for object iterators");
5839  }
5840 
5842  {
5843  return m_it.array_iterator - other.m_it.array_iterator;
5844  }
5845 
5846  default:
5847  {
5848  return m_it.primitive_iterator - other.m_it.primitive_iterator;
5849  }
5850  }
5851  }
5852 
5855  {
5856  switch (m_object->m_type)
5857  {
5859  {
5860  throw std::domain_error("cannot use operator[] for object iterators");
5861  }
5862 
5864  {
5865  return *(m_it.array_iterator + n);
5866  }
5867 
5869  {
5870  throw std::out_of_range("cannot get value");
5871  }
5872 
5873  default:
5874  {
5875  if (m_it.primitive_iterator == -n)
5876  {
5877  return *m_object;
5878  }
5879  else
5880  {
5881  throw std::out_of_range("cannot get value");
5882  }
5883  }
5884  }
5885  }
5886 
5888  typename object_t::key_type key() const
5889  {
5890  if (m_object->is_object())
5891  {
5892  return m_it.object_iterator->first;
5893  }
5894  else
5895  {
5896  throw std::domain_error("cannot use key() for non-object iterators");
5897  }
5898  }
5899 
5902  {
5903  return operator*();
5904  }
5905 
5906  private:
5908  pointer m_object = nullptr;
5910  internal_iterator m_it = internal_iterator();
5911  };
5912 
5925  class iterator : public const_iterator
5926  {
5927  public:
5929  using pointer = typename basic_json::pointer;
5931 
5933  iterator() = default;
5934 
5936  iterator(pointer object) noexcept : base_iterator(object)
5937  {}
5938 
5940  iterator(const iterator& other) noexcept
5941  : base_iterator(other)
5942  {}
5943 
5945  iterator& operator=(iterator other) noexcept(
5946  std::is_nothrow_move_constructible<pointer>::value and
5947  std::is_nothrow_move_assignable<pointer>::value and
5948  std::is_nothrow_move_constructible<internal_iterator>::value and
5949  std::is_nothrow_move_assignable<internal_iterator>::value
5950  )
5951  {
5952  base_iterator::operator=(other);
5953  return *this;
5954  }
5955 
5958  {
5959  return const_cast<reference>(base_iterator::operator*());
5960  }
5961 
5964  {
5965  return const_cast<pointer>(base_iterator::operator->());
5966  }
5967 
5970  {
5971  iterator result = *this;
5973  return result;
5974  }
5975 
5978  {
5980  return *this;
5981  }
5982 
5985  {
5986  iterator result = *this;
5988  return result;
5989  }
5990 
5993  {
5995  return *this;
5996  }
5997 
6000  {
6002  return *this;
6003  }
6004 
6007  {
6009  return *this;
6010  }
6011 
6014  {
6015  auto result = *this;
6016  result += i;
6017  return result;
6018  }
6019 
6022  {
6023  auto result = *this;
6024  result -= i;
6025  return result;
6026  }
6027 
6028  difference_type operator-(const iterator& other) const
6029  {
6030  return base_iterator::operator-(other);
6031  }
6032 
6035  {
6036  return const_cast<reference>(base_iterator::operator[](n));
6037  }
6038 
6041  {
6042  return const_cast<reference>(base_iterator::value());
6043  }
6044  };
6045 
6063  template<typename Base>
6064  class json_reverse_iterator : public std::reverse_iterator<Base>
6065  {
6066  public:
6068  using base_iterator = std::reverse_iterator<Base>;
6070  using reference = typename Base::reference;
6071 
6073  json_reverse_iterator(const typename base_iterator::iterator_type& it)
6074  : base_iterator(it) {}
6075 
6078 
6081  {
6082  return base_iterator::operator++(1);
6083  }
6084 
6087  {
6088  base_iterator::operator++();
6089  return *this;
6090  }
6091 
6094  {
6095  return base_iterator::operator--(1);
6096  }
6097 
6100  {
6101  base_iterator::operator--();
6102  return *this;
6103  }
6104 
6107  {
6108  base_iterator::operator+=(i);
6109  return *this;
6110  }
6111 
6114  {
6115  auto result = *this;
6116  result += i;
6117  return result;
6118  }
6119 
6122  {
6123  auto result = *this;
6124  result -= i;
6125  return result;
6126  }
6127 
6130  {
6131  return this->base() - other.base();
6132  }
6133 
6136  {
6137  return *(this->operator+(n));
6138  }
6139 
6141  typename object_t::key_type key() const
6142  {
6143  auto it = --this->base();
6144  return it.key();
6145  }
6146 
6149  {
6150  auto it = --this->base();
6151  return it.operator * ();
6152  }
6153  };
6154 
6155 
6156  private:
6158  template<typename IteratorType>
6159  class iteration_proxy
6160  {
6161  private:
6163  class iteration_proxy_internal
6164  {
6165  private:
6167  IteratorType anchor;
6169  size_t array_index = 0;
6170 
6171  public:
6172  iteration_proxy_internal(IteratorType it)
6173  : anchor(it)
6174  {}
6175 
6177  iteration_proxy_internal& operator*()
6178  {
6179  return *this;
6180  }
6181 
6183  iteration_proxy_internal& operator++()
6184  {
6185  ++anchor;
6186  ++array_index;
6187 
6188  return *this;
6189  }
6190 
6192  bool operator!= (const iteration_proxy_internal& o)
6193  {
6194  return anchor != o.anchor;
6195  }
6196 
6198  typename basic_json::string_t key() const
6199  {
6200  switch (anchor.m_object->type())
6201  {
6202  // use integer array index as key
6203  case value_t::array:
6204  {
6205  return std::to_string(array_index);
6206  }
6207 
6208  // use key from the object
6209  case value_t::object:
6210  {
6211  return anchor.key();
6212  }
6213 
6214  // use an empty key for all primitive types
6215  default:
6216  {
6217  return "";
6218  }
6219  }
6220  }
6221 
6223  typename IteratorType::reference value() const
6224  {
6225  return anchor.value();
6226  }
6227  };
6228 
6230  typename IteratorType::reference container;
6231 
6232  public:
6234  iteration_proxy(typename IteratorType::reference cont)
6235  : container(cont)
6236  {}
6237 
6239  iteration_proxy_internal begin()
6240  {
6241  return iteration_proxy_internal(container.begin());
6242  }
6243 
6245  iteration_proxy_internal end()
6246  {
6247  return iteration_proxy_internal(container.end());
6248  }
6249  };
6250 
6251  public:
6260  static iteration_proxy<iterator> iterator_wrapper(reference cont)
6261  {
6262  return iteration_proxy<iterator>(cont);
6263  }
6264 
6268  static iteration_proxy<const_iterator> iterator_wrapper(const_reference cont)
6269  {
6270  return iteration_proxy<const_iterator>(cont);
6271  }
6272 
6273 
6274  private:
6276  // lexer and parser //
6278 
6286  class lexer
6287  {
6288  public:
6290  enum class token_type
6291  {
6292  uninitialized,
6293  literal_true,
6294  literal_false,
6295  literal_null,
6296  value_string,
6297  value_number,
6298  begin_array,
6299  begin_object,
6300  end_array,
6301  end_object,
6302  name_separator,
6303  value_separator,
6304  parse_error,
6305  end_of_input
6306  };
6307 
6309  using lexer_char_t = unsigned char;
6310 
6312  explicit lexer(const string_t& s) noexcept
6313  : m_stream(nullptr), m_buffer(s)
6314  {
6315  m_content = reinterpret_cast<const lexer_char_t*>(s.c_str());
6316  m_start = m_cursor = m_content;
6317  m_limit = m_content + s.size();
6318  }
6319  explicit lexer(std::istream* s) noexcept
6320  : m_stream(s), m_buffer()
6321  {
6322  getline(*m_stream, m_buffer);
6323  m_content = reinterpret_cast<const lexer_char_t*>(m_buffer.c_str());
6324  m_start = m_cursor = m_content;
6325  m_limit = m_content + m_buffer.size();
6326  }
6327 
6329  lexer() = default;
6330 
6331  // switch of unwanted functions
6332  lexer(const lexer&) = delete;
6333  lexer operator=(const lexer&) = delete;
6334 
6346  static string_t to_unicode(const std::size_t codepoint1,
6347  const std::size_t codepoint2 = 0)
6348  {
6349  string_t result;
6350 
6351  // calculate the codepoint from the given code points
6352  std::size_t codepoint = codepoint1;
6353 
6354  // check if codepoint1 is a high surrogate
6355  if (codepoint1 >= 0xD800 and codepoint1 <= 0xDBFF)
6356  {
6357  // check if codepoint2 is a low surrogate
6358  if (codepoint2 >= 0xDC00 and codepoint2 <= 0xDFFF)
6359  {
6360  codepoint =
6361  // high surrogate occupies the most significant 22 bits
6362  (codepoint1 << 10)
6363  // low surrogate occupies the least significant 15 bits
6364  + codepoint2
6365  // there is still the 0xD800, 0xDC00 and 0x10000 noise
6366  // in the result so we have to substract with:
6367  // (0xD800 << 10) + DC00 - 0x10000 = 0x35FDC00
6368  - 0x35FDC00;
6369  }
6370  else
6371  {
6372  throw std::invalid_argument("missing or wrong low surrogate");
6373  }
6374  }
6375 
6376  if (codepoint < 0x80)
6377  {
6378  // 1-byte characters: 0xxxxxxx (ASCII)
6379  result.append(1, static_cast<typename string_t::value_type>(codepoint));
6380  }
6381  else if (codepoint <= 0x7ff)
6382  {
6383  // 2-byte characters: 110xxxxx 10xxxxxx
6384  result.append(1, static_cast<typename string_t::value_type>(0xC0 | ((codepoint >> 6) & 0x1F)));
6385  result.append(1, static_cast<typename string_t::value_type>(0x80 | (codepoint & 0x3F)));
6386  }
6387  else if (codepoint <= 0xffff)
6388  {
6389  // 3-byte characters: 1110xxxx 10xxxxxx 10xxxxxx
6390  result.append(1, static_cast<typename string_t::value_type>(0xE0 | ((codepoint >> 12) & 0x0F)));
6391  result.append(1, static_cast<typename string_t::value_type>(0x80 | ((codepoint >> 6) & 0x3F)));
6392  result.append(1, static_cast<typename string_t::value_type>(0x80 | (codepoint & 0x3F)));
6393  }
6394  else if (codepoint <= 0x10ffff)
6395  {
6396  // 4-byte characters: 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
6397  result.append(1, static_cast<typename string_t::value_type>(0xF0 | ((codepoint >> 18) & 0x07)));
6398  result.append(1, static_cast<typename string_t::value_type>(0x80 | ((codepoint >> 12) & 0x3F)));
6399  result.append(1, static_cast<typename string_t::value_type>(0x80 | ((codepoint >> 6) & 0x3F)));
6400  result.append(1, static_cast<typename string_t::value_type>(0x80 | (codepoint & 0x3F)));
6401  }
6402  else
6403  {
6404  throw std::out_of_range("code points above 0x10FFFF are invalid");
6405  }
6406 
6407  return result;
6408  }
6409 
6411  static std::string token_type_name(token_type t)
6412  {
6413  switch (t)
6414  {
6415  case token_type::uninitialized:
6416  return "<uninitialized>";
6417  case token_type::literal_true:
6418  return "true literal";
6419  case token_type::literal_false:
6420  return "false literal";
6421  case token_type::literal_null:
6422  return "null literal";
6423  case token_type::value_string:
6424  return "string literal";
6425  case token_type::value_number:
6426  return "number literal";
6427  case token_type::begin_array:
6428  return "[";
6429  case token_type::begin_object:
6430  return "{";
6431  case token_type::end_array:
6432  return "]";
6433  case token_type::end_object:
6434  return "}";
6435  case token_type::name_separator:
6436  return ":";
6437  case token_type::value_separator:
6438  return ",";
6439  case token_type::parse_error:
6440  return "<parse error>";
6441  case token_type::end_of_input:
6442  return "<end of input>";
6443  default:
6444  {
6445  // catch non-enum values
6446  return "unknown token"; // LCOV_EXCL_LINE
6447  }
6448  }
6449  }
6450 
6461  token_type scan() noexcept
6462  {
6463  // pointer for backtracking information
6464  m_marker = nullptr;
6465 
6466  // remember the begin of the token
6467  m_start = m_cursor;
6468 
6469 
6470  {
6471  lexer_char_t yych;
6472  unsigned int yyaccept = 0;
6473  static const unsigned char yybm[] =
6474  {
6475  0, 0, 0, 0, 0, 0, 0, 0,
6476  0, 32, 32, 0, 0, 32, 0, 0,
6477  64, 64, 64, 64, 64, 64, 64, 64,
6478  64, 64, 64, 64, 64, 64, 64, 64,
6479  96, 64, 0, 64, 64, 64, 64, 64,
6480  64, 64, 64, 64, 64, 64, 64, 64,
6481  192, 192, 192, 192, 192, 192, 192, 192,
6482  192, 192, 64, 64, 64, 64, 64, 64,
6483  64, 64, 64, 64, 64, 64, 64, 64,
6484  64, 64, 64, 64, 64, 64, 64, 64,
6485  64, 64, 64, 64, 64, 64, 64, 64,
6486  64, 64, 64, 64, 0, 64, 64, 64,
6487  64, 64, 64, 64, 64, 64, 64, 64,
6488  64, 64, 64, 64, 64, 64, 64, 64,
6489  64, 64, 64, 64, 64, 64, 64, 64,
6490  64, 64, 64, 64, 64, 64, 64, 64,
6491  64, 64, 64, 64, 64, 64, 64, 64,
6492  64, 64, 64, 64, 64, 64, 64, 64,
6493  64, 64, 64, 64, 64, 64, 64, 64,
6494  64, 64, 64, 64, 64, 64, 64, 64,
6495  64, 64, 64, 64, 64, 64, 64, 64,
6496  64, 64, 64, 64, 64, 64, 64, 64,
6497  64, 64, 64, 64, 64, 64, 64, 64,
6498  64, 64, 64, 64, 64, 64, 64, 64,
6499  64, 64, 64, 64, 64, 64, 64, 64,
6500  64, 64, 64, 64, 64, 64, 64, 64,
6501  64, 64, 64, 64, 64, 64, 64, 64,
6502  64, 64, 64, 64, 64, 64, 64, 64,
6503  64, 64, 64, 64, 64, 64, 64, 64,
6504  64, 64, 64, 64, 64, 64, 64, 64,
6505  64, 64, 64, 64, 64, 64, 64, 64,
6506  64, 64, 64, 64, 64, 64, 64, 64,
6507  };
6508  if ((m_limit - m_cursor) < 5)
6509  {
6510  yyfill(); // LCOV_EXCL_LINE;
6511  }
6512  yych = *m_cursor;
6513  if (yych <= ':')
6514  {
6515  if (yych <= ' ')
6516  {
6517  if (yych <= '\n')
6518  {
6519  if (yych <= 0x00)
6520  {
6521  goto basic_json_parser_28;
6522  }
6523  if (yych <= 0x08)
6524  {
6525  goto basic_json_parser_30;
6526  }
6527  if (yych >= '\n')
6528  {
6529  goto basic_json_parser_4;
6530  }
6531  }
6532  else
6533  {
6534  if (yych == '\r')
6535  {
6536  goto basic_json_parser_2;
6537  }
6538  if (yych <= 0x1F)
6539  {
6540  goto basic_json_parser_30;
6541  }
6542  }
6543  }
6544  else
6545  {
6546  if (yych <= ',')
6547  {
6548  if (yych == '"')
6549  {
6550  goto basic_json_parser_27;
6551  }
6552  if (yych <= '+')
6553  {
6554  goto basic_json_parser_30;
6555  }
6556  goto basic_json_parser_16;
6557  }
6558  else
6559  {
6560  if (yych <= '/')
6561  {
6562  if (yych <= '-')
6563  {
6564  goto basic_json_parser_23;
6565  }
6566  goto basic_json_parser_30;
6567  }
6568  else
6569  {
6570  if (yych <= '0')
6571  {
6572  goto basic_json_parser_24;
6573  }
6574  if (yych <= '9')
6575  {
6576  goto basic_json_parser_26;
6577  }
6578  goto basic_json_parser_18;
6579  }
6580  }
6581  }
6582  }
6583  else
6584  {
6585  if (yych <= 'n')
6586  {
6587  if (yych <= ']')
6588  {
6589  if (yych == '[')
6590  {
6591  goto basic_json_parser_8;
6592  }
6593  if (yych <= '\\')
6594  {
6595  goto basic_json_parser_30;
6596  }
6597  goto basic_json_parser_10;
6598  }
6599  else
6600  {
6601  if (yych == 'f')
6602  {
6603  goto basic_json_parser_22;
6604  }
6605  if (yych <= 'm')
6606  {
6607  goto basic_json_parser_30;
6608  }
6609  goto basic_json_parser_20;
6610  }
6611  }
6612  else
6613  {
6614  if (yych <= '{')
6615  {
6616  if (yych == 't')
6617  {
6618  goto basic_json_parser_21;
6619  }
6620  if (yych <= 'z')
6621  {
6622  goto basic_json_parser_30;
6623  }
6624  goto basic_json_parser_12;
6625  }
6626  else
6627  {
6628  if (yych <= '}')
6629  {
6630  if (yych <= '|')
6631  {
6632  goto basic_json_parser_30;
6633  }
6634  goto basic_json_parser_14;
6635  }
6636  else
6637  {
6638  if (yych == 0xEF)
6639  {
6640  goto basic_json_parser_6;
6641  }
6642  goto basic_json_parser_30;
6643  }
6644  }
6645  }
6646  }
6647 basic_json_parser_2:
6648  ++m_cursor;
6649  yych = *m_cursor;
6650  goto basic_json_parser_5;
6651 basic_json_parser_3:
6652  {
6653  return scan();
6654  }
6655 basic_json_parser_4:
6656  ++m_cursor;
6657  if (m_limit <= m_cursor)
6658  {
6659  yyfill(); // LCOV_EXCL_LINE;
6660  }
6661  yych = *m_cursor;
6662 basic_json_parser_5:
6663  if (yybm[0 + yych] & 32)
6664  {
6665  goto basic_json_parser_4;
6666  }
6667  goto basic_json_parser_3;
6668 basic_json_parser_6:
6669  yyaccept = 0;
6670  yych = *(m_marker = ++m_cursor);
6671  if (yych == 0xBB)
6672  {
6673  goto basic_json_parser_64;
6674  }
6675 basic_json_parser_7:
6676  {
6677  return token_type::parse_error;
6678  }
6679 basic_json_parser_8:
6680  ++m_cursor;
6681  {
6682  return token_type::begin_array;
6683  }
6684 basic_json_parser_10:
6685  ++m_cursor;
6686  {
6687  return token_type::end_array;
6688  }
6689 basic_json_parser_12:
6690  ++m_cursor;
6691  {
6692  return token_type::begin_object;
6693  }
6694 basic_json_parser_14:
6695  ++m_cursor;
6696  {
6697  return token_type::end_object;
6698  }
6699 basic_json_parser_16:
6700  ++m_cursor;
6701  {
6702  return token_type::value_separator;
6703  }
6704 basic_json_parser_18:
6705  ++m_cursor;
6706  {
6707  return token_type::name_separator;
6708  }
6709 basic_json_parser_20:
6710  yyaccept = 0;
6711  yych = *(m_marker = ++m_cursor);
6712  if (yych == 'u')
6713  {
6714  goto basic_json_parser_60;
6715  }
6716  goto basic_json_parser_7;
6717 basic_json_parser_21:
6718  yyaccept = 0;
6719  yych = *(m_marker = ++m_cursor);
6720  if (yych == 'r')
6721  {
6722  goto basic_json_parser_56;
6723  }
6724  goto basic_json_parser_7;
6725 basic_json_parser_22:
6726  yyaccept = 0;
6727  yych = *(m_marker = ++m_cursor);
6728  if (yych == 'a')
6729  {
6730  goto basic_json_parser_51;
6731  }
6732  goto basic_json_parser_7;
6733 basic_json_parser_23:
6734  yych = *++m_cursor;
6735  if (yych <= '/')
6736  {
6737  goto basic_json_parser_7;
6738  }
6739  if (yych <= '0')
6740  {
6741  goto basic_json_parser_50;
6742  }
6743  if (yych <= '9')
6744  {
6745  goto basic_json_parser_41;
6746  }
6747  goto basic_json_parser_7;
6748 basic_json_parser_24:
6749  yyaccept = 1;
6750  yych = *(m_marker = ++m_cursor);
6751  if (yych <= 'D')
6752  {
6753  if (yych == '.')
6754  {
6755  goto basic_json_parser_43;
6756  }
6757  }
6758  else
6759  {
6760  if (yych <= 'E')
6761  {
6762  goto basic_json_parser_44;
6763  }
6764  if (yych == 'e')
6765  {
6766  goto basic_json_parser_44;
6767  }
6768  }
6769 basic_json_parser_25:
6770  {
6771  return token_type::value_number;
6772  }
6773 basic_json_parser_26:
6774  yyaccept = 1;
6775  yych = *(m_marker = ++m_cursor);
6776  goto basic_json_parser_42;
6777 basic_json_parser_27:
6778  yyaccept = 0;
6779  yych = *(m_marker = ++m_cursor);
6780  if (yych <= 0x0F)
6781  {
6782  goto basic_json_parser_7;
6783  }
6784  goto basic_json_parser_32;
6785 basic_json_parser_28:
6786  ++m_cursor;
6787  {
6788  return token_type::end_of_input;
6789  }
6790 basic_json_parser_30:
6791  yych = *++m_cursor;
6792  goto basic_json_parser_7;
6793 basic_json_parser_31:
6794  ++m_cursor;
6795  if (m_limit <= m_cursor)
6796  {
6797  yyfill(); // LCOV_EXCL_LINE;
6798  }
6799  yych = *m_cursor;
6800 basic_json_parser_32:
6801  if (yybm[0 + yych] & 64)
6802  {
6803  goto basic_json_parser_31;
6804  }
6805  if (yych <= 0x0F)
6806  {
6807  goto basic_json_parser_33;
6808  }
6809  if (yych <= '"')
6810  {
6811  goto basic_json_parser_35;
6812  }
6813  goto basic_json_parser_34;
6814 basic_json_parser_33:
6815  m_cursor = m_marker;
6816  if (yyaccept == 0)
6817  {
6818  goto basic_json_parser_7;
6819  }
6820  else
6821  {
6822  goto basic_json_parser_25;
6823  }
6824 basic_json_parser_34:
6825  ++m_cursor;
6826  if (m_limit <= m_cursor)
6827  {
6828  yyfill(); // LCOV_EXCL_LINE;
6829  }
6830  yych = *m_cursor;
6831  if (yych <= 'e')
6832  {
6833  if (yych <= '/')
6834  {
6835  if (yych == '"')
6836  {
6837  goto basic_json_parser_31;
6838  }
6839  if (yych <= '.')
6840  {
6841  goto basic_json_parser_33;
6842  }
6843  goto basic_json_parser_31;
6844  }
6845  else
6846  {
6847  if (yych <= '\\')
6848  {
6849  if (yych <= '[')
6850  {
6851  goto basic_json_parser_33;
6852  }
6853  goto basic_json_parser_31;
6854  }
6855  else
6856  {
6857  if (yych == 'b')
6858  {
6859  goto basic_json_parser_31;
6860  }
6861  goto basic_json_parser_33;
6862  }
6863  }
6864  }
6865  else
6866  {
6867  if (yych <= 'q')
6868  {
6869  if (yych <= 'f')
6870  {
6871  goto basic_json_parser_31;
6872  }
6873  if (yych == 'n')
6874  {
6875  goto basic_json_parser_31;
6876  }
6877  goto basic_json_parser_33;
6878  }
6879  else
6880  {
6881  if (yych <= 's')
6882  {
6883  if (yych <= 'r')
6884  {
6885  goto basic_json_parser_31;
6886  }
6887  goto basic_json_parser_33;
6888  }
6889  else
6890  {
6891  if (yych <= 't')
6892  {
6893  goto basic_json_parser_31;
6894  }
6895  if (yych <= 'u')
6896  {
6897  goto basic_json_parser_37;
6898  }
6899  goto basic_json_parser_33;
6900  }
6901  }
6902  }
6903 basic_json_parser_35:
6904  ++m_cursor;
6905  {
6906  return token_type::value_string;
6907  }
6908 basic_json_parser_37:
6909  ++m_cursor;
6910  if (m_limit <= m_cursor)
6911  {
6912  yyfill(); // LCOV_EXCL_LINE;
6913  }
6914  yych = *m_cursor;
6915  if (yych <= '@')
6916  {
6917  if (yych <= '/')
6918  {
6919  goto basic_json_parser_33;
6920  }
6921  if (yych >= ':')
6922  {
6923  goto basic_json_parser_33;
6924  }
6925  }
6926  else
6927  {
6928  if (yych <= 'F')
6929  {
6930  goto basic_json_parser_38;
6931  }
6932  if (yych <= '`')
6933  {
6934  goto basic_json_parser_33;
6935  }
6936  if (yych >= 'g')
6937  {
6938  goto basic_json_parser_33;
6939  }
6940  }
6941 basic_json_parser_38:
6942  ++m_cursor;
6943  if (m_limit <= m_cursor)
6944  {
6945  yyfill(); // LCOV_EXCL_LINE;
6946  }
6947  yych = *m_cursor;
6948  if (yych <= '@')
6949  {
6950  if (yych <= '/')
6951  {
6952  goto basic_json_parser_33;
6953  }
6954  if (yych >= ':')
6955  {
6956  goto basic_json_parser_33;
6957  }
6958  }
6959  else
6960  {
6961  if (yych <= 'F')
6962  {
6963  goto basic_json_parser_39;
6964  }
6965  if (yych <= '`')
6966  {
6967  goto basic_json_parser_33;
6968  }
6969  if (yych >= 'g')
6970  {
6971  goto basic_json_parser_33;
6972  }
6973  }
6974 basic_json_parser_39:
6975  ++m_cursor;
6976  if (m_limit <= m_cursor)
6977  {
6978  yyfill(); // LCOV_EXCL_LINE;
6979  }
6980  yych = *m_cursor;
6981  if (yych <= '@')
6982  {
6983  if (yych <= '/')
6984  {
6985  goto basic_json_parser_33;
6986  }
6987  if (yych >= ':')
6988  {
6989  goto basic_json_parser_33;
6990  }
6991  }
6992  else
6993  {
6994  if (yych <= 'F')
6995  {
6996  goto basic_json_parser_40;
6997  }
6998  if (yych <= '`')
6999  {
7000  goto basic_json_parser_33;
7001  }
7002  if (yych >= 'g')
7003  {
7004  goto basic_json_parser_33;
7005  }
7006  }
7007 basic_json_parser_40:
7008  ++m_cursor;
7009  if (m_limit <= m_cursor)
7010  {
7011  yyfill(); // LCOV_EXCL_LINE;
7012  }
7013  yych = *m_cursor;
7014  if (yych <= '@')
7015  {
7016  if (yych <= '/')
7017  {
7018  goto basic_json_parser_33;
7019  }
7020  if (yych <= '9')
7021  {
7022  goto basic_json_parser_31;
7023  }
7024  goto basic_json_parser_33;
7025  }
7026  else
7027  {
7028  if (yych <= 'F')
7029  {
7030  goto basic_json_parser_31;
7031  }
7032  if (yych <= '`')
7033  {
7034  goto basic_json_parser_33;
7035  }
7036  if (yych <= 'f')
7037  {
7038  goto basic_json_parser_31;
7039  }
7040  goto basic_json_parser_33;
7041  }
7042 basic_json_parser_41:
7043  yyaccept = 1;
7044  m_marker = ++m_cursor;
7045  if ((m_limit - m_cursor) < 3)
7046  {
7047  yyfill(); // LCOV_EXCL_LINE;
7048  }
7049  yych = *m_cursor;
7050 basic_json_parser_42:
7051  if (yybm[0 + yych] & 128)
7052  {
7053  goto basic_json_parser_41;
7054  }
7055  if (yych <= 'D')
7056  {
7057  if (yych != '.')
7058  {
7059  goto basic_json_parser_25;
7060  }
7061  }
7062  else
7063  {
7064  if (yych <= 'E')
7065  {
7066  goto basic_json_parser_44;
7067  }
7068  if (yych == 'e')
7069  {
7070  goto basic_json_parser_44;
7071  }
7072  goto basic_json_parser_25;
7073  }
7074 basic_json_parser_43:
7075  yych = *++m_cursor;
7076  if (yych <= '/')
7077  {
7078  goto basic_json_parser_33;
7079  }
7080  if (yych <= '9')
7081  {
7082  goto basic_json_parser_48;
7083  }
7084  goto basic_json_parser_33;
7085 basic_json_parser_44:
7086  yych = *++m_cursor;
7087  if (yych <= ',')
7088  {
7089  if (yych != '+')
7090  {
7091  goto basic_json_parser_33;
7092  }
7093  }
7094  else
7095  {
7096  if (yych <= '-')
7097  {
7098  goto basic_json_parser_45;
7099  }
7100  if (yych <= '/')
7101  {
7102  goto basic_json_parser_33;
7103  }
7104  if (yych <= '9')
7105  {
7106  goto basic_json_parser_46;
7107  }
7108  goto basic_json_parser_33;
7109  }
7110 basic_json_parser_45:
7111  yych = *++m_cursor;
7112  if (yych <= '/')
7113  {
7114  goto basic_json_parser_33;
7115  }
7116  if (yych >= ':')
7117  {
7118  goto basic_json_parser_33;
7119  }
7120 basic_json_parser_46:
7121  ++m_cursor;
7122  if (m_limit <= m_cursor)
7123  {
7124  yyfill(); // LCOV_EXCL_LINE;
7125  }
7126  yych = *m_cursor;
7127  if (yych <= '/')
7128  {
7129  goto basic_json_parser_25;
7130  }
7131  if (yych <= '9')
7132  {
7133  goto basic_json_parser_46;
7134  }
7135  goto basic_json_parser_25;
7136 basic_json_parser_48:
7137  yyaccept = 1;
7138  m_marker = ++m_cursor;
7139  if ((m_limit - m_cursor) < 3)
7140  {
7141  yyfill(); // LCOV_EXCL_LINE;
7142  }
7143  yych = *m_cursor;
7144  if (yych <= 'D')
7145  {
7146  if (yych <= '/')
7147  {
7148  goto basic_json_parser_25;
7149  }
7150  if (yych <= '9')
7151  {
7152  goto basic_json_parser_48;
7153  }
7154  goto basic_json_parser_25;
7155  }
7156  else
7157  {
7158  if (yych <= 'E')
7159  {
7160  goto basic_json_parser_44;
7161  }
7162  if (yych == 'e')
7163  {
7164  goto basic_json_parser_44;
7165  }
7166  goto basic_json_parser_25;
7167  }
7168 basic_json_parser_50:
7169  yyaccept = 1;
7170  yych = *(m_marker = ++m_cursor);
7171  if (yych <= 'D')
7172  {
7173  if (yych == '.')
7174  {
7175  goto basic_json_parser_43;
7176  }
7177  goto basic_json_parser_25;
7178  }
7179  else
7180  {
7181  if (yych <= 'E')
7182  {
7183  goto basic_json_parser_44;
7184  }
7185  if (yych == 'e')
7186  {
7187  goto basic_json_parser_44;
7188  }
7189  goto basic_json_parser_25;
7190  }
7191 basic_json_parser_51:
7192  yych = *++m_cursor;
7193  if (yych != 'l')
7194  {
7195  goto basic_json_parser_33;
7196  }
7197  yych = *++m_cursor;
7198  if (yych != 's')
7199  {
7200  goto basic_json_parser_33;
7201  }
7202  yych = *++m_cursor;
7203  if (yych != 'e')
7204  {
7205  goto basic_json_parser_33;
7206  }
7207  ++m_cursor;
7208  {
7209  return token_type::literal_false;
7210  }
7211 basic_json_parser_56:
7212  yych = *++m_cursor;
7213  if (yych != 'u')
7214  {
7215  goto basic_json_parser_33;
7216  }
7217  yych = *++m_cursor;
7218  if (yych != 'e')
7219  {
7220  goto basic_json_parser_33;
7221  }
7222  ++m_cursor;
7223  {
7224  return token_type::literal_true;
7225  }
7226 basic_json_parser_60:
7227  yych = *++m_cursor;
7228  if (yych != 'l')
7229  {
7230  goto basic_json_parser_33;
7231  }
7232  yych = *++m_cursor;
7233  if (yych != 'l')
7234  {
7235  goto basic_json_parser_33;
7236  }
7237  ++m_cursor;
7238  {
7239  return token_type::literal_null;
7240  }
7241 basic_json_parser_64:
7242  yych = *++m_cursor;
7243  if (yych != 0xBF)
7244  {
7245  goto basic_json_parser_33;
7246  }
7247  ++m_cursor;
7248  {
7249  return scan();
7250  }
7251  }
7252 
7253 
7254  }
7255 
7257  void yyfill() noexcept
7258  {
7259  if (not m_stream or not * m_stream)
7260  {
7261  return;
7262  }
7263 
7264  const ssize_t offset_start = m_start - m_content;
7265  const ssize_t offset_marker = m_marker - m_start;
7266  const ssize_t offset_cursor = m_cursor - m_start;
7267 
7268  m_buffer.erase(0, static_cast<size_t>(offset_start));
7269  std::string line;
7270  std::getline(*m_stream, line);
7271  m_buffer += "\n" + line; // add line with newline symbol
7272 
7273  m_content = reinterpret_cast<const lexer_char_t*>(m_buffer.c_str());
7274  m_start = m_content;
7275  m_marker = m_start + offset_marker;
7276  m_cursor = m_start + offset_cursor;
7277  m_limit = m_start + m_buffer.size() - 1;
7278  }
7279 
7281  string_t get_token() const noexcept
7282  {
7283  return string_t(reinterpret_cast<typename string_t::const_pointer>(m_start),
7284  static_cast<size_t>(m_cursor - m_start));
7285  }
7286 
7308  string_t get_string() const
7309  {
7310  string_t result;
7311  result.reserve(static_cast<size_t>(m_cursor - m_start - 2));
7312 
7313  // iterate the result between the quotes
7314  for (const lexer_char_t* i = m_start + 1; i < m_cursor - 1; ++i)
7315  {
7316  // process escaped characters
7317  if (*i == '\\')
7318  {
7319  // read next character
7320  ++i;
7321 
7322  switch (*i)
7323  {
7324  // the default escapes
7325  case 't':
7326  {
7327  result += "\t";
7328  break;
7329  }
7330  case 'b':
7331  {
7332  result += "\b";
7333  break;
7334  }
7335  case 'f':
7336  {
7337  result += "\f";
7338  break;
7339  }
7340  case 'n':
7341  {
7342  result += "\n";
7343  break;
7344  }
7345  case 'r':
7346  {
7347  result += "\r";
7348  break;
7349  }
7350  case '\\':
7351  {
7352  result += "\\";
7353  break;
7354  }
7355  case '/':
7356  {
7357  result += "/";
7358  break;
7359  }
7360  case '"':
7361  {
7362  result += "\"";
7363  break;
7364  }
7365 
7366  // unicode
7367  case 'u':
7368  {
7369  // get code xxxx from uxxxx
7370  auto codepoint = std::strtoul(std::string(reinterpret_cast<typename string_t::const_pointer>(i + 1),
7371  4).c_str(), nullptr, 16);
7372 
7373  // check if codepoint is a high surrogate
7374  if (codepoint >= 0xD800 and codepoint <= 0xDBFF)
7375  {
7376  // make sure there is a subsequent unicode
7377  if ((i + 6 >= m_limit) or * (i + 5) != '\\' or * (i + 6) != 'u')
7378  {
7379  throw std::invalid_argument("missing low surrogate");
7380  }
7381 
7382  // get code yyyy from uxxxx\uyyyy
7383  auto codepoint2 = std::strtoul(std::string(reinterpret_cast<typename string_t::const_pointer>
7384  (i + 7), 4).c_str(), nullptr, 16);
7385  result += to_unicode(codepoint, codepoint2);
7386  // skip the next 10 characters (xxxx\uyyyy)
7387  i += 10;
7388  }
7389  else
7390  {
7391  // add unicode character(s)
7392  result += to_unicode(codepoint);
7393  // skip the next four characters (xxxx)
7394  i += 4;
7395  }
7396  break;
7397  }
7398  }
7399  }
7400  else
7401  {
7402  // all other characters are just copied to the end of the
7403  // string
7404  result.append(1, static_cast<typename string_t::value_type>(*i));
7405  }
7406  }
7407 
7408  return result;
7409  }
7410 
7428  long double get_number() const
7429  {
7430  // conversion
7431  typename string_t::value_type* endptr;
7432  const auto float_val = std::strtold(reinterpret_cast<typename string_t::const_pointer>(m_start),
7433  &endptr);
7434 
7435  // return float_val if the whole number was translated and NAN
7436  // otherwise
7437  return (reinterpret_cast<lexer_char_t*>(endptr) == m_cursor) ? float_val : NAN;
7438  }
7439 
7440  private:
7442  std::istream* m_stream;
7444  string_t m_buffer;
7446  const lexer_char_t* m_content = nullptr;
7448  const lexer_char_t* m_start = nullptr;
7450  const lexer_char_t* m_marker = nullptr;
7452  const lexer_char_t* m_cursor = nullptr;
7454  const lexer_char_t* m_limit = nullptr;
7455  };
7456 
7462  class parser
7463  {
7464  public:
7466  parser(const string_t& s, parser_callback_t cb = nullptr)
7467  : callback(cb), m_lexer(s)
7468  {
7469  // read first token
7470  get_token();
7471  }
7472 
7474  parser(std::istream& _is, parser_callback_t cb = nullptr)
7475  : callback(cb), m_lexer(&_is)
7476  {
7477  // read first token
7478  get_token();
7479  }
7480 
7482  basic_json parse()
7483  {
7484  basic_json result = parse_internal(true);
7485 
7486  expect(lexer::token_type::end_of_input);
7487 
7488  // return parser result and replace it with null in case the
7489  // top-level value was discarded by the callback function
7490  return result.is_discarded() ? basic_json() : result;
7491  }
7492 
7493  private:
7495  basic_json parse_internal(bool keep)
7496  {
7497  auto result = basic_json(value_t::discarded);
7498 
7499  switch (last_token)
7500  {
7501  case lexer::token_type::begin_object:
7502  {
7503  if (keep and (not callback or (keep = callback(depth++, parse_event_t::object_start, result))))
7504  {
7505  // explicitly set result to object to cope with {}
7506  result.m_type = value_t::object;
7507  result.m_value = json_value(value_t::object);
7508  }
7509 
7510  // read next token
7511  get_token();
7512 
7513  // closing } -> we are done
7514  if (last_token == lexer::token_type::end_object)
7515  {
7516  get_token();
7517  if (keep and callback and not callback(--depth, parse_event_t::object_end, result))
7518  {
7519  result = basic_json(value_t::discarded);
7520  }
7521  return result;
7522  }
7523 
7524  // no comma is expected here
7525  unexpect(lexer::token_type::value_separator);
7526 
7527  // otherwise: parse key-value pairs
7528  do
7529  {
7530  // ugly, but could be fixed with loop reorganization
7531  if (last_token == lexer::token_type::value_separator)
7532  {
7533  get_token();
7534  }
7535 
7536  // store key
7537  expect(lexer::token_type::value_string);
7538  const auto key = m_lexer.get_string();
7539 
7540  bool keep_tag = false;
7541  if (keep)
7542  {
7543  if (callback)
7544  {
7545  basic_json k(key);
7546  keep_tag = callback(depth, parse_event_t::key, k);
7547  }
7548  else
7549  {
7550  keep_tag = true;
7551  }
7552  }
7553 
7554  // parse separator (:)
7555  get_token();
7556  expect(lexer::token_type::name_separator);
7557 
7558  // parse and add value
7559  get_token();
7560  auto value = parse_internal(keep);
7561  if (keep and keep_tag and not value.is_discarded())
7562  {
7563  result[key] = std::move(value);
7564  }
7565  }
7566  while (last_token == lexer::token_type::value_separator);
7567 
7568  // closing }
7569  expect(lexer::token_type::end_object);
7570  get_token();
7571  if (keep and callback and not callback(--depth, parse_event_t::object_end, result))
7572  {
7573  result = basic_json(value_t::discarded);
7574  }
7575 
7576  return result;
7577  }
7578 
7579  case lexer::token_type::begin_array:
7580  {
7581  if (keep and (not callback or (keep = callback(depth++, parse_event_t::array_start, result))))
7582  {
7583  // explicitly set result to object to cope with []
7584  result.m_type = value_t::array;
7585  result.m_value = json_value(value_t::array);
7586  }
7587 
7588  // read next token
7589  get_token();
7590 
7591  // closing ] -> we are done
7592  if (last_token == lexer::token_type::end_array)
7593  {
7594  get_token();
7595  if (callback and not callback(--depth, parse_event_t::array_end, result))
7596  {
7597  result = basic_json(value_t::discarded);
7598  }
7599  return result;
7600  }
7601 
7602  // no comma is expected here
7603  unexpect(lexer::token_type::value_separator);
7604 
7605  // otherwise: parse values
7606  do
7607  {
7608  // ugly, but could be fixed with loop reorganization
7609  if (last_token == lexer::token_type::value_separator)
7610  {
7611  get_token();
7612  }
7613 
7614  // parse value
7615  auto value = parse_internal(keep);
7616  if (keep and not value.is_discarded())
7617  {
7618  result.push_back(std::move(value));
7619  }
7620  }
7621  while (last_token == lexer::token_type::value_separator);
7622 
7623  // closing ]
7624  expect(lexer::token_type::end_array);
7625  get_token();
7626  if (keep and callback and not callback(--depth, parse_event_t::array_end, result))
7627  {
7628  result = basic_json(value_t::discarded);
7629  }
7630 
7631  return result;
7632  }
7633 
7634  case lexer::token_type::literal_null:
7635  {
7636  get_token();
7637  result.m_type = value_t::null;
7638  break;
7639  }
7640 
7641  case lexer::token_type::value_string:
7642  {
7643  const auto s = m_lexer.get_string();
7644  get_token();
7645  result = basic_json(s);
7646  break;
7647  }
7648 
7649  case lexer::token_type::literal_true:
7650  {
7651  get_token();
7652  result.m_type = value_t::boolean;
7653  result.m_value = true;
7654  break;
7655  }
7656 
7657  case lexer::token_type::literal_false:
7658  {
7659  get_token();
7660  result.m_type = value_t::boolean;
7661  result.m_value = false;
7662  break;
7663  }
7664 
7665  case lexer::token_type::value_number:
7666  {
7667  auto float_val = m_lexer.get_number();
7668 
7669  // NAN is returned if token could not be translated
7670  // completely
7671  if (std::isnan(float_val))
7672  {
7673  throw std::invalid_argument(std::string("parse error - ") +
7674  m_lexer.get_token() + " is not a number");
7675  }
7676 
7677  get_token();
7678 
7679  // check if conversion loses precision
7680  const auto int_val = static_cast<number_integer_t>(float_val);
7681  if (approx(float_val, static_cast<long double>(int_val)))
7682  {
7683  // we would not lose precision -> return int
7684  result.m_type = value_t::number_integer;
7685  result.m_value = int_val;
7686  }
7687  else
7688  {
7689  // we would lose precision -> return float
7690  result.m_type = value_t::number_float;
7691  result.m_value = static_cast<number_float_t>(float_val);
7692  }
7693  break;
7694  }
7695 
7696  default:
7697  {
7698  // the last token was unexpected
7699  unexpect(last_token);
7700  }
7701  }
7702 
7703  if (keep and callback and not callback(depth, parse_event_t::value, result))
7704  {
7705  result = basic_json(value_t::discarded);
7706  }
7707  return result;
7708  }
7709 
7711  typename lexer::token_type get_token()
7712  {
7713  last_token = m_lexer.scan();
7714  return last_token;
7715  }
7716 
7717  void expect(typename lexer::token_type t) const
7718  {
7719  if (t != last_token)
7720  {
7721  std::string error_msg = "parse error - unexpected \'";
7722  error_msg += m_lexer.get_token();
7723  error_msg += "\' (" + lexer::token_type_name(last_token);
7724  error_msg += "); expected " + lexer::token_type_name(t);
7725  throw std::invalid_argument(error_msg);
7726  }
7727  }
7728 
7729  void unexpect(typename lexer::token_type t) const
7730  {
7731  if (t == last_token)
7732  {
7733  std::string error_msg = "parse error - unexpected \'";
7734  error_msg += m_lexer.get_token();
7735  error_msg += "\' (";
7736  error_msg += lexer::token_type_name(last_token) + ")";
7737  throw std::invalid_argument(error_msg);
7738  }
7739  }
7740 
7741  private:
7743  int depth = 0;
7745  parser_callback_t callback;
7747  typename lexer::token_type last_token = lexer::token_type::uninitialized;
7749  lexer m_lexer;
7750  };
7751 };
7752 
7753 
7755 // presets //
7757 
7767 }
7768 
7769 
7771 // nonmember functions //
7773 
7774 // specialization of std::swap, and std::hash
7775 namespace std
7776 {
7782 template <>
7783 inline void swap(nlohmann::json& j1,
7784  nlohmann::json& j2) noexcept(
7785  is_nothrow_move_constructible<nlohmann::json>::value and
7786  is_nothrow_move_assignable<nlohmann::json>::value
7787  )
7788 {
7789  j1.swap(j2);
7790 }
7791 
7793 template <>
7794 struct hash<nlohmann::json>
7795 {
7801  std::size_t operator()(const nlohmann::json& j) const
7802  {
7803  // a naive hashing via the string representation
7804  const auto& h = hash<nlohmann::json::string_t>();
7805  return h(j.dump());
7806  }
7807 };
7808 }
7809 
7822 inline nlohmann::json operator "" _json(const char* s, std::size_t)
7823 {
7824  return nlohmann::json::parse(reinterpret_cast<nlohmann::json::string_t::value_type*>
7825  (const_cast<char*>(s)));
7826 }
7827 
7828 #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:5732
iterator insert(const_iterator pos, basic_json &&val)
inserts element
Definition: json.hpp:4208
iterator operator++(int)
post-increment (it++)
Definition: json.hpp:5969
friend bool operator<=(const_reference lhs, const_reference rhs) noexcept
comparison: less than or equal
Definition: json.hpp:4757
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:6121
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:1506
const_reference operator[](size_type idx) const
access specified array element
Definition: json.hpp:2842
reference operator[](const T(&key)[n])
access specified object element
Definition: json.hpp:2969
typename basic_json::const_pointer pointer
defines a pointer to the type iterated over (value_type)
Definition: json.hpp:5434
static iteration_proxy< iterator > iterator_wrapper(reference cont)
wrapper to access iterator member functions in range-based for
Definition: json.hpp:6260
const_iterator & operator--()
pre-decrement (–it)
Definition: json.hpp:5677
friend std::istream & operator>>(std::istream &i, basic_json &j)
deserialize from stream
Definition: json.hpp:4970
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:5499
typename basic_json::value_type value_type
the type of the values when the iterator is dereferenced
Definition: json.hpp:5430
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:1768
iterator insert(const_iterator pos, const_iterator first, const_iterator last)
inserts elements
Definition: json.hpp:4283
iterator insert(const_iterator pos, size_type cnt, const basic_json &val)
inserts elements
Definition: json.hpp:4235
json_reverse_iterator operator--(int)
post-decrement (it–)
Definition: json.hpp:6093
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:4133
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:1466
iterator & operator++()
pre-increment (++it)
Definition: json.hpp:5977
friend bool operator!=(const_reference lhs, const_reference rhs) noexcept
comparison: not equal
Definition: json.hpp:4635
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:5642
difference_type operator-(const json_reverse_iterator &other) const
return difference
Definition: json.hpp:6129
basic_json<> json
default JSON class
Definition: json.hpp:7766
reference front()
access the first element
Definition: json.hpp:3133
bool is_array() const noexcept
return whether value is an array
Definition: json.hpp:2081
const_iterator find(typename object_t::key_type key) const
find an element in a JSON object
Definition: json.hpp:3499
std::reverse_iterator< Base > base_iterator
shortcut to the reverse iterator adaptor
Definition: json.hpp:6068
json_reverse_iterator(const typename base_iterator::iterator_type &it)
create reverse iterator from iterator
Definition: json.hpp:6073
a class to store JSON values
Definition: json.hpp:187
json_reverse_iterator & operator--()
pre-decrement (–it)
Definition: json.hpp:6099
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:4614
void push_back(basic_json &&val)
add an object to an array
Definition: json.hpp:4049
const_iterator cbegin() const
returns a const iterator to the first element
Definition: json.hpp:3597
bool is_string() const noexcept
return whether value is a string
Definition: json.hpp:2100
iterator & operator+=(difference_type i)
add to iterator
Definition: json.hpp:5999
const PointerType get_ptr() const noexcept
get a pointer value (implicit)
Definition: json.hpp:2539
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:5928
reference operator+=(basic_json &&val)
add an object to an array
Definition: json.hpp:4074
basic_json(size_type cnt, const basic_json &val)
construct an array with count copies of given value
Definition: json.hpp:1530
a mutable random access iterator for the basic_json class
Definition: json.hpp:5925
iterator & operator-=(difference_type i)
subtract from iterator
Definition: json.hpp:6006
static basic_json parse(std::istream &&i, parser_callback_t cb=nullptr)
deserialize from stream
Definition: json.hpp:4932
reference operator[](const typename object_t::key_type &key)
access specified object element
Definition: json.hpp:2881
STL namespace.
difference_type operator-(const iterator &other) const
Definition: json.hpp:6028
reference value() const
return the value of an iterator
Definition: json.hpp:5901
static iteration_proxy< const_iterator > iterator_wrapper(const_reference cont)
wrapper to access iterator member functions in range-based for
Definition: json.hpp:6268
const_iterator end() const
returns a const iterator to one past the last element
Definition: json.hpp:3632
const_iterator(const const_iterator &other) noexcept
copy constructor
Definition: json.hpp:5494
reference at(const typename object_t::key_type &key)
access specified object element with bounds checking
Definition: json.hpp:2707
object_t::key_type key() const
return the key of an object iterator
Definition: json.hpp:5888
iterator end()
returns an iterator to one past the last element
Definition: json.hpp:3622
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:5957
reverse_iterator rend()
returns an iterator to the reverse-end
Definition: json.hpp:3711
bool is_object() const noexcept
return whether value is an object
Definition: json.hpp:2062
const_iterator operator-(difference_type i)
subtract from iterator
Definition: json.hpp:5824
bool is_discarded() const noexcept
return whether value is discarded
Definition: json.hpp:2124
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:5436
const_reverse_iterator rend() const
returns a const reverse iterator to one before the first
Definition: json.hpp:3719
size_type erase(const typename object_t::key_type &key)
remove element from a JSON object given a key
Definition: json.hpp:3413
bool is_boolean() const noexcept
return whether value is a boolean
Definition: json.hpp:1973
iterator begin()
returns an iterator to the first element
Definition: json.hpp:3563
const_reference at(const typename object_t::key_type &key) const
access specified object element with bounds checking
Definition: json.hpp:2754
reference operator+=(const basic_json &val)
add an object to an array
Definition: json.hpp:4107
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:2020
iterator operator+(difference_type i)
add to iterator
Definition: json.hpp:6013
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:3483
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:4801
iterator & operator--()
pre-decrement (–it)
Definition: json.hpp:5992
friend bool operator<(const_reference lhs, const_reference rhs) noexcept
comparison: less than
Definition: json.hpp:4696
pointer operator->() const
dereference the iterator
Definition: json.hpp:5605
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:2927
const_iterator cend() const
returns a const iterator to one past the last element
Definition: json.hpp:3656
typename Base::reference reference
the reference type for the pointed-to element
Definition: json.hpp:6070
size_type size() const noexcept
returns the number of elements
Definition: json.hpp:3866
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:2617
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:6077
value_t type() const noexcept
return the type of the JSON value (explicit)
Definition: json.hpp:1894
friend std::ostream & operator>>(const basic_json &j, std::ostream &o)
serialize to stream
Definition: json.hpp:4856
ValueType value(const typename object_t::key_type &key, ValueType default_value) const
access specified object element with default value
Definition: json.hpp:3082
object_t::key_type key() const
return the key of an object iterator
Definition: json.hpp:6141
bool is_structured() const noexcept
return whether type is structured
Definition: json.hpp:1935
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:5432
void swap(array_t &other)
exchanges the values
Definition: json.hpp:4404
reverse_iterator rbegin()
returns an iterator to the reverse-beginning
Definition: json.hpp:3680
reference operator+=(const typename object_t::value_type &val)
add an object to an object
Definition: json.hpp:4156
reference operator[](difference_type n) const
access to successor
Definition: json.hpp:6034
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:3688
~basic_json()
destructor
Definition: json.hpp:1794
basic_json(const basic_json &other)
copy constructor
Definition: json.hpp:1672
const_iterator operator+(difference_type i)
add to iterator
Definition: json.hpp:5816
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:1954
void swap(string_t &other)
exchanges the values
Definition: json.hpp:4468
reference value() const
return the value of an iterator
Definition: json.hpp:6040
const_iterator operator--(int)
post-decrement (it–)
Definition: json.hpp:5669
void erase(const size_type idx)
remove element from a JSON array given an index
Definition: json.hpp:3448
void clear() noexcept
clears the contents
Definition: json.hpp:3983
pointer operator->()
dereference the iterator
Definition: json.hpp:5963
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:3141
bool operator>=(const const_iterator &other) const
comparison: greater than or equal
Definition: json.hpp:5778
iterator insert(const_iterator pos, std::initializer_list< basic_json > ilist)
inserts elements
Definition: json.hpp:4337
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:5784
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:1376
difference_type operator-(const const_iterator &other) const
return difference
Definition: json.hpp:5832
friend bool operator==(const_reference lhs, const_reference rhs) noexcept
comparison: equal
Definition: json.hpp:4547
bool is_number() const noexcept
return whether value is a number
Definition: json.hpp:1997
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:3765
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:3809
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:3108
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:4374
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:3742
reference value() const
return the value of an iterator
Definition: json.hpp:6148
const_iterator(pointer object)
constructor for a given JSON instance
Definition: json.hpp:5444
friend bool operator<(const value_t lhs, const value_t rhs)
comparison operator for JSON types
Definition: json.hpp:4501
iterator(pointer object) noexcept
constructor for a given JSON instance
Definition: json.hpp:5936
bool operator<(const const_iterator &other) const
comparison: smaller
Definition: json.hpp:5738
string_t dump(const int indent=-1) const
serialization
Definition: json.hpp:1863
friend bool operator!=(const_reference v, std::nullptr_t) noexcept
comparison: not equal
Definition: json.hpp:4658
const_iterator & operator-=(difference_type i)
subtract from iterator
Definition: json.hpp:5810
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:4895
InteratorType erase(InteratorType first, InteratorType last)
remove elements given an iterator range
Definition: json.hpp:3333
json_reverse_iterator operator++(int)
post-increment (it++)
Definition: json.hpp:6080
PointerType get_ptr() noexcept
get a pointer value (implicit)
Definition: json.hpp:2524
const_iterator(const iterator &other)
copy constructor given a nonconst iterator
Definition: json.hpp:5469
friend bool operator!=(std::nullptr_t, const_reference v) noexcept
comparison: not equal
Definition: json.hpp:4667
InteratorType erase(InteratorType pos)
remove element given an iterator
Definition: json.hpp:3232
bool operator<=(const const_iterator &other) const
comparison: less than or equal
Definition: json.hpp:5766
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:3167
bool is_number_float() const noexcept
return whether value is a floating-point number
Definition: json.hpp:2043
the parser read { and started to process a JSON object
const_iterator operator++(int)
post-increment (it++)
Definition: json.hpp:5634
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:5940
const_reference back() const
access the last element
Definition: json.hpp:3177
basic_json(InputIT first, InputIT last)
construct a JSON container given an iterator range
Definition: json.hpp:1574
static basic_json parse(std::istream &i, parser_callback_t cb=nullptr)
deserialize from stream
Definition: json.hpp:4924
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:3529
size_type max_size() const noexcept
returns the maximum possible number of elements
Definition: json.hpp:3926
void push_back(const basic_json &val)
add an object to an array
Definition: json.hpp:4084
bool operator==(const const_iterator &other) const
comparison: equal
Definition: json.hpp:5704
json_reverse_iterator & operator++()
pre-increment (++it)
Definition: json.hpp:6086
bool operator>(const const_iterator &other) const
comparison: greater than
Definition: json.hpp:5772
friend bool operator>(const_reference lhs, const_reference rhs) noexcept
comparison: greater than
Definition: json.hpp:4779
basic_json(basic_json &&other) noexcept
move constructor
Definition: json.hpp:1738
const_reference operator[](const T(&key)[n]) const
read-only access specified object element
Definition: json.hpp:3018
const_iterator begin() const
returns a const iterator to the first element
Definition: json.hpp:3573
const_reference at(size_type idx) const
access specified array element with bounds checking
Definition: json.hpp:2660
json_reverse_iterator & operator+=(difference_type i)
add to iterator
Definition: json.hpp:6106
a const random access iterator for the basic_json class
Definition: json.hpp:5423
a template for a reverse iterator class
Definition: json.hpp:232
void swap(object_t &other)
exchanges the values
Definition: json.hpp:4436
std::bidirectional_iterator_tag iterator_category
the category of the iterator
Definition: json.hpp:5438
bool is_primitive() const noexcept
return whether type is primitive
Definition: json.hpp:1915
iterator insert(const_iterator pos, const basic_json &val)
inserts element
Definition: json.hpp:4182
friend bool operator==(const_reference v, std::nullptr_t) noexcept
comparison: equal
Definition: json.hpp:4605
reference operator[](difference_type n) const
access to successor
Definition: json.hpp:6135
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:5854
reference operator*() const
return a reference to the value pointed to by the iterator
Definition: json.hpp:5571
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:4960
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:7801
friend std::ostream & operator<<(std::ostream &o, const basic_json &j)
serialize to stream
Definition: json.hpp:4838
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:5945
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:2799
iterator operator--(int)
post-decrement (it–)
Definition: json.hpp:5984
json_reverse_iterator operator+(difference_type i) const
add to iterator
Definition: json.hpp:6113
parse_event_t
JSON callback events.
Definition: json.hpp:754
iterator operator-(difference_type i)
subtract from iterator
Definition: json.hpp:6021