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 
3770  private:
3771  // forward declaration
3772  template<typename IteratorType> class iteration_proxy;
3773 
3774  public:
3783  static iteration_proxy<iterator> iterator_wrapper(reference cont)
3784  {
3785  return iteration_proxy<iterator>(cont);
3786  }
3787 
3791  static iteration_proxy<const_iterator> iterator_wrapper(const_reference cont)
3792  {
3793  return iteration_proxy<const_iterator>(cont);
3794  }
3795 
3797 
3798 
3800  // capacity //
3802 
3805 
3835  bool empty() const noexcept
3836  {
3837  switch (m_type)
3838  {
3839  case value_t::null:
3840  {
3841  // null values are empty
3842  return true;
3843  }
3844 
3845  case value_t::array:
3846  {
3847  return m_value.array->empty();
3848  }
3849 
3850  case value_t::object:
3851  {
3852  return m_value.object->empty();
3853  }
3854 
3855  default:
3856  {
3857  // all other types are nonempty
3858  return false;
3859  }
3860  }
3861  }
3862 
3892  size_type size() const noexcept
3893  {
3894  switch (m_type)
3895  {
3896  case value_t::null:
3897  {
3898  // null values are empty
3899  return 0;
3900  }
3901 
3902  case value_t::array:
3903  {
3904  return m_value.array->size();
3905  }
3906 
3907  case value_t::object:
3908  {
3909  return m_value.object->size();
3910  }
3911 
3912  default:
3913  {
3914  // all other types have size 1
3915  return 1;
3916  }
3917  }
3918  }
3919 
3952  size_type max_size() const noexcept
3953  {
3954  switch (m_type)
3955  {
3956  case value_t::array:
3957  {
3958  return m_value.array->max_size();
3959  }
3960 
3961  case value_t::object:
3962  {
3963  return m_value.object->max_size();
3964  }
3965 
3966  default:
3967  {
3968  // all other types have max_size() == size()
3969  return size();
3970  }
3971  }
3972  }
3973 
3975 
3976 
3978  // modifiers //
3980 
3983 
4009  void clear() noexcept
4010  {
4011  switch (m_type)
4012  {
4014  {
4015  m_value.number_integer = 0;
4016  break;
4017  }
4018 
4019  case value_t::number_float:
4020  {
4021  m_value.number_float = 0.0;
4022  break;
4023  }
4024 
4025  case value_t::boolean:
4026  {
4027  m_value.boolean = false;
4028  break;
4029  }
4030 
4031  case value_t::string:
4032  {
4033  m_value.string->clear();
4034  break;
4035  }
4036 
4037  case value_t::array:
4038  {
4039  m_value.array->clear();
4040  break;
4041  }
4042 
4043  case value_t::object:
4044  {
4045  m_value.object->clear();
4046  break;
4047  }
4048 
4049  default:
4050  {
4051  break;
4052  }
4053  }
4054  }
4055 
4075  void push_back(basic_json&& val)
4076  {
4077  // push_back only works for null objects or arrays
4078  if (not(is_null() or is_array()))
4079  {
4080  throw std::domain_error("cannot use push_back() with " + type_name());
4081  }
4082 
4083  // transform null object into an array
4084  if (is_null())
4085  {
4086  m_type = value_t::array;
4087  m_value = value_t::array;
4088  }
4089 
4090  // add element to array (move semantics)
4091  m_value.array->push_back(std::move(val));
4092  // invalidate object
4093  val.m_type = value_t::null;
4094  }
4095 
4100  reference operator+=(basic_json&& val)
4101  {
4102  push_back(std::move(val));
4103  return *this;
4104  }
4105 
4110  void push_back(const basic_json& val)
4111  {
4112  // push_back only works for null objects or arrays
4113  if (not(is_null() or is_array()))
4114  {
4115  throw std::domain_error("cannot use push_back() with " + type_name());
4116  }
4117 
4118  // transform null object into an array
4119  if (is_null())
4120  {
4121  m_type = value_t::array;
4122  m_value = value_t::array;
4123  }
4124 
4125  // add element to array
4126  m_value.array->push_back(val);
4127  }
4128 
4133  reference operator+=(const basic_json& val)
4134  {
4135  push_back(val);
4136  return *this;
4137  }
4138 
4159  void push_back(const typename object_t::value_type& val)
4160  {
4161  // push_back only works for null objects or objects
4162  if (not(is_null() or is_object()))
4163  {
4164  throw std::domain_error("cannot use push_back() with " + type_name());
4165  }
4166 
4167  // transform null object into an object
4168  if (is_null())
4169  {
4170  m_type = value_t::object;
4171  m_value = value_t::object;
4172  }
4173 
4174  // add element to array
4175  m_value.object->insert(val);
4176  }
4177 
4182  reference operator+=(const typename object_t::value_type& val)
4183  {
4184  push_back(val);
4185  return operator[](val.first);
4186  }
4187 
4208  iterator insert(const_iterator pos, const basic_json& val)
4209  {
4210  // insert only works for arrays
4211  if (is_array())
4212  {
4213  // check if iterator pos fits to this JSON value
4214  if (pos.m_object != this)
4215  {
4216  throw std::domain_error("iterator does not fit current value");
4217  }
4218 
4219  // insert to array and return iterator
4220  iterator result(this);
4221  result.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator, val);
4222  return result;
4223  }
4224  else
4225  {
4226  throw std::domain_error("cannot use insert() with " + type_name());
4227  }
4228  }
4229 
4234  iterator insert(const_iterator pos, basic_json&& val)
4235  {
4236  return insert(pos, val);
4237  }
4238 
4261  iterator insert(const_iterator pos, size_type cnt, const basic_json& val)
4262  {
4263  // insert only works for arrays
4264  if (is_array())
4265  {
4266  // check if iterator pos fits to this JSON value
4267  if (pos.m_object != this)
4268  {
4269  throw std::domain_error("iterator does not fit current value");
4270  }
4271 
4272  // insert to array and return iterator
4273  iterator result(this);
4274  result.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator, cnt, val);
4275  return result;
4276  }
4277  else
4278  {
4279  throw std::domain_error("cannot use insert() with " + type_name());
4280  }
4281  }
4282 
4310  {
4311  // insert only works for arrays
4312  if (not is_array())
4313  {
4314  throw std::domain_error("cannot use insert() with " + type_name());
4315  }
4316 
4317  // check if iterator pos fits to this JSON value
4318  if (pos.m_object != this)
4319  {
4320  throw std::domain_error("iterator does not fit current value");
4321  }
4322 
4323  if (first.m_object != last.m_object)
4324  {
4325  throw std::domain_error("iterators do not fit");
4326  }
4327 
4328  if (first.m_object == this or last.m_object == this)
4329  {
4330  throw std::domain_error("passed iterators may not belong to container");
4331  }
4332 
4333  // insert to array and return iterator
4334  iterator result(this);
4335  result.m_it.array_iterator = m_value.array->insert(
4336  pos.m_it.array_iterator,
4337  first.m_it.array_iterator,
4338  last.m_it.array_iterator);
4339  return result;
4340  }
4341 
4363  iterator insert(const_iterator pos, std::initializer_list<basic_json> ilist)
4364  {
4365  // insert only works for arrays
4366  if (not is_array())
4367  {
4368  throw std::domain_error("cannot use insert() with " + type_name());
4369  }
4370 
4371  // check if iterator pos fits to this JSON value
4372  if (pos.m_object != this)
4373  {
4374  throw std::domain_error("iterator does not fit current value");
4375  }
4376 
4377  // insert to array and return iterator
4378  iterator result(this);
4379  result.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator, ilist);
4380  return result;
4381  }
4382 
4400  void swap(reference other) noexcept (
4401  std::is_nothrow_move_constructible<value_t>::value and
4402  std::is_nothrow_move_assignable<value_t>::value and
4403  std::is_nothrow_move_constructible<json_value>::value and
4404  std::is_nothrow_move_assignable<json_value>::value
4405  )
4406  {
4407  std::swap(m_type, other.m_type);
4408  std::swap(m_value, other.m_value);
4409  }
4410 
4430  void swap(array_t& other)
4431  {
4432  // swap only works for arrays
4433  if (is_array())
4434  {
4435  std::swap(*(m_value.array), other);
4436  }
4437  else
4438  {
4439  throw std::domain_error("cannot use swap() with " + type_name());
4440  }
4441  }
4442 
4462  void swap(object_t& other)
4463  {
4464  // swap only works for objects
4465  if (is_object())
4466  {
4467  std::swap(*(m_value.object), other);
4468  }
4469  else
4470  {
4471  throw std::domain_error("cannot use swap() with " + type_name());
4472  }
4473  }
4474 
4494  void swap(string_t& other)
4495  {
4496  // swap only works for strings
4497  if (is_string())
4498  {
4499  std::swap(*(m_value.string), other);
4500  }
4501  else
4502  {
4503  throw std::domain_error("cannot use swap() with " + type_name());
4504  }
4505  }
4506 
4508 
4509 
4511  // lexicographical comparison operators //
4513 
4516 
4517  private:
4527  friend bool operator<(const value_t lhs, const value_t rhs)
4528  {
4529  static constexpr std::array<uint8_t, 7> order = {{
4530  0, // null
4531  3, // object
4532  4, // array
4533  5, // string
4534  1, // boolean
4535  2, // integer
4536  2 // float
4537  }
4538  };
4539 
4540  // discarded values are not comparable
4541  if (lhs == value_t::discarded or rhs == value_t::discarded)
4542  {
4543  return false;
4544  }
4545 
4546  return order[static_cast<std::size_t>(lhs)] < order[static_cast<std::size_t>(rhs)];
4547  }
4548 
4549  public:
4573  friend bool operator==(const_reference lhs, const_reference rhs) noexcept
4574  {
4575  const auto lhs_type = lhs.type();
4576  const auto rhs_type = rhs.type();
4577 
4578  if (lhs_type == rhs_type)
4579  {
4580  switch (lhs_type)
4581  {
4582  case value_t::array:
4583  return *lhs.m_value.array == *rhs.m_value.array;
4584  case value_t::object:
4585  return *lhs.m_value.object == *rhs.m_value.object;
4586  case value_t::null:
4587  return true;
4588  case value_t::string:
4589  return *lhs.m_value.string == *rhs.m_value.string;
4590  case value_t::boolean:
4591  return lhs.m_value.boolean == rhs.m_value.boolean;
4593  return lhs.m_value.number_integer == rhs.m_value.number_integer;
4594  case value_t::number_float:
4595  return approx(lhs.m_value.number_float, rhs.m_value.number_float);
4596  default:
4597  return false;
4598  }
4599  }
4600  else if (lhs_type == value_t::number_integer and rhs_type == value_t::number_float)
4601  {
4602  return approx(static_cast<number_float_t>(lhs.m_value.number_integer),
4603  rhs.m_value.number_float);
4604  }
4605  else if (lhs_type == value_t::number_float and rhs_type == value_t::number_integer)
4606  {
4607  return approx(lhs.m_value.number_float,
4608  static_cast<number_float_t>(rhs.m_value.number_integer));
4609  }
4610  return false;
4611  }
4612 
4631  friend bool operator==(const_reference v, std::nullptr_t) noexcept
4632  {
4633  return v.is_null();
4634  }
4635 
4640  friend bool operator==(std::nullptr_t, const_reference v) noexcept
4641  {
4642  return v.is_null();
4643  }
4644 
4661  friend bool operator!=(const_reference lhs, const_reference rhs) noexcept
4662  {
4663  return not (lhs == rhs);
4664  }
4665 
4684  friend bool operator!=(const_reference v, std::nullptr_t) noexcept
4685  {
4686  return not v.is_null();
4687  }
4688 
4693  friend bool operator!=(std::nullptr_t, const_reference v) noexcept
4694  {
4695  return not v.is_null();
4696  }
4697 
4722  friend bool operator<(const_reference lhs, const_reference rhs) noexcept
4723  {
4724  const auto lhs_type = lhs.type();
4725  const auto rhs_type = rhs.type();
4726 
4727  if (lhs_type == rhs_type)
4728  {
4729  switch (lhs_type)
4730  {
4731  case value_t::array:
4732  return *lhs.m_value.array < *rhs.m_value.array;
4733  case value_t::object:
4734  return *lhs.m_value.object < *rhs.m_value.object;
4735  case value_t::null:
4736  return false;
4737  case value_t::string:
4738  return *lhs.m_value.string < *rhs.m_value.string;
4739  case value_t::boolean:
4740  return lhs.m_value.boolean < rhs.m_value.boolean;
4742  return lhs.m_value.number_integer < rhs.m_value.number_integer;
4743  case value_t::number_float:
4744  return lhs.m_value.number_float < rhs.m_value.number_float;
4745  default:
4746  return false;
4747  }
4748  }
4749  else if (lhs_type == value_t::number_integer and rhs_type == value_t::number_float)
4750  {
4751  return static_cast<number_float_t>(lhs.m_value.number_integer) <
4752  rhs.m_value.number_float;
4753  }
4754  else if (lhs_type == value_t::number_float and rhs_type == value_t::number_integer)
4755  {
4756  return lhs.m_value.number_float <
4757  static_cast<number_float_t>(rhs.m_value.number_integer);
4758  }
4759 
4760  // We only reach this line if we cannot compare values. In that case,
4761  // we compare types. Note we have to call the operator explicitly,
4762  // because MSVC has problems otherwise.
4763  return operator<(lhs_type, rhs_type);
4764  }
4765 
4783  friend bool operator<=(const_reference lhs, const_reference rhs) noexcept
4784  {
4785  return not (rhs < lhs);
4786  }
4787 
4805  friend bool operator>(const_reference lhs, const_reference rhs) noexcept
4806  {
4807  return not (lhs <= rhs);
4808  }
4809 
4827  friend bool operator>=(const_reference lhs, const_reference rhs) noexcept
4828  {
4829  return not (lhs < rhs);
4830  }
4831 
4833 
4834 
4836  // serialization //
4838 
4841 
4864  friend std::ostream& operator<<(std::ostream& o, const basic_json& j)
4865  {
4866  // read width member and use it as indentation parameter if nonzero
4867  const bool pretty_print = (o.width() > 0);
4868  const auto indentation = (pretty_print ? o.width() : 0);
4869 
4870  // reset width to 0 for subsequent calls to this stream
4871  o.width(0);
4872 
4873  // do the actual serialization
4874  j.dump(o, pretty_print, static_cast<unsigned int>(indentation));
4875  return o;
4876  }
4877 
4882  friend std::ostream& operator>>(const basic_json& j, std::ostream& o)
4883  {
4884  return o << j;
4885  }
4886 
4888 
4889 
4891  // deserialization //
4893 
4896 
4921  static basic_json parse(const string_t& s, parser_callback_t cb = nullptr)
4922  {
4923  return parser(s, cb).parse();
4924  }
4925 
4950  static basic_json parse(std::istream& i, parser_callback_t cb = nullptr)
4951  {
4952  return parser(i, cb).parse();
4953  }
4954 
4958  static basic_json parse(std::istream&& i, parser_callback_t cb = nullptr)
4959  {
4960  return parser(i, cb).parse();
4961  }
4962 
4986  friend std::istream& operator<<(basic_json& j, std::istream& i)
4987  {
4988  j = parser(i).parse();
4989  return i;
4990  }
4991 
4996  friend std::istream& operator>>(std::istream& i, basic_json& j)
4997  {
4998  j = parser(i).parse();
4999  return i;
5000  }
5001 
5003 
5004 
5005  private:
5007  // convenience functions //
5009 
5011  string_t type_name() const
5012  {
5013  switch (m_type)
5014  {
5015  case value_t::null:
5016  return "null";
5017  case value_t::object:
5018  return "object";
5019  case value_t::array:
5020  return "array";
5021  case value_t::string:
5022  return "string";
5023  case value_t::boolean:
5024  return "boolean";
5025  case value_t::discarded:
5026  return "discarded";
5027  default:
5028  return "number";
5029  }
5030  }
5031 
5040  static std::size_t extra_space(const string_t& s) noexcept
5041  {
5042  std::size_t result = 0;
5043 
5044  for (const auto& c : s)
5045  {
5046  switch (c)
5047  {
5048  case '"':
5049  case '\\':
5050  case '\b':
5051  case '\f':
5052  case '\n':
5053  case '\r':
5054  case '\t':
5055  {
5056  // from c (1 byte) to \x (2 bytes)
5057  result += 1;
5058  break;
5059  }
5060 
5061  default:
5062  {
5063  if (c >= 0x00 and c <= 0x1f)
5064  {
5065  // from c (1 byte) to \uxxxx (6 bytes)
5066  result += 5;
5067  }
5068  break;
5069  }
5070  }
5071  }
5072 
5073  return result;
5074  }
5075 
5089  static string_t escape_string(const string_t& s) noexcept
5090  {
5091  const auto space = extra_space(s);
5092  if (space == 0)
5093  {
5094  return s;
5095  }
5096 
5097  // create a result string of necessary size
5098  string_t result(s.size() + space, '\\');
5099  std::size_t pos = 0;
5100 
5101  for (const auto& c : s)
5102  {
5103  switch (c)
5104  {
5105  // quotation mark (0x22)
5106  case '"':
5107  {
5108  result[pos + 1] = '"';
5109  pos += 2;
5110  break;
5111  }
5112 
5113  // reverse solidus (0x5c)
5114  case '\\':
5115  {
5116  // nothing to change
5117  pos += 2;
5118  break;
5119  }
5120 
5121  // backspace (0x08)
5122  case '\b':
5123  {
5124  result[pos + 1] = 'b';
5125  pos += 2;
5126  break;
5127  }
5128 
5129  // formfeed (0x0c)
5130  case '\f':
5131  {
5132  result[pos + 1] = 'f';
5133  pos += 2;
5134  break;
5135  }
5136 
5137  // newline (0x0a)
5138  case '\n':
5139  {
5140  result[pos + 1] = 'n';
5141  pos += 2;
5142  break;
5143  }
5144 
5145  // carriage return (0x0d)
5146  case '\r':
5147  {
5148  result[pos + 1] = 'r';
5149  pos += 2;
5150  break;
5151  }
5152 
5153  // horizontal tab (0x09)
5154  case '\t':
5155  {
5156  result[pos + 1] = 't';
5157  pos += 2;
5158  break;
5159  }
5160 
5161  default:
5162  {
5163  if (c >= 0x00 and c <= 0x1f)
5164  {
5165  // convert a number 0..15 to its hex representation (0..f)
5166  auto hexify = [](const char v) -> char
5167  {
5168  return (v < 10) ? ('0' + v) : ('a' + v - 10);
5169  };
5170 
5171  // print character c as \uxxxx
5172  for (const char m :
5173  { 'u', '0', '0', hexify(c >> 4), hexify(c & 0x0f)
5174  })
5175  {
5176  result[++pos] = m;
5177  }
5178 
5179  ++pos;
5180  }
5181  else
5182  {
5183  // all other characters are added as-is
5184  result[pos++] = c;
5185  }
5186  break;
5187  }
5188  }
5189  }
5190 
5191  return result;
5192  }
5193 
5211  void dump(std::ostream& o,
5212  const bool pretty_print,
5213  const unsigned int indent_step,
5214  const unsigned int current_indent = 0) const
5215  {
5216  // variable to hold indentation for recursive calls
5217  unsigned int new_indent = current_indent;
5218 
5219  switch (m_type)
5220  {
5221  case value_t::object:
5222  {
5223  if (m_value.object->empty())
5224  {
5225  o << "{}";
5226  return;
5227  }
5228 
5229  o << "{";
5230 
5231  // increase indentation
5232  if (pretty_print)
5233  {
5234  new_indent += indent_step;
5235  o << "\n";
5236  }
5237 
5238  for (auto i = m_value.object->cbegin(); i != m_value.object->cend(); ++i)
5239  {
5240  if (i != m_value.object->cbegin())
5241  {
5242  o << (pretty_print ? ",\n" : ",");
5243  }
5244  o << string_t(new_indent, ' ') << "\""
5245  << escape_string(i->first) << "\":"
5246  << (pretty_print ? " " : "");
5247  i->second.dump(o, pretty_print, indent_step, new_indent);
5248  }
5249 
5250  // decrease indentation
5251  if (pretty_print)
5252  {
5253  new_indent -= indent_step;
5254  o << "\n";
5255  }
5256 
5257  o << string_t(new_indent, ' ') + "}";
5258  return;
5259  }
5260 
5261  case value_t::array:
5262  {
5263  if (m_value.array->empty())
5264  {
5265  o << "[]";
5266  return;
5267  }
5268 
5269  o << "[";
5270 
5271  // increase indentation
5272  if (pretty_print)
5273  {
5274  new_indent += indent_step;
5275  o << "\n";
5276  }
5277 
5278  for (auto i = m_value.array->cbegin(); i != m_value.array->cend(); ++i)
5279  {
5280  if (i != m_value.array->cbegin())
5281  {
5282  o << (pretty_print ? ",\n" : ",");
5283  }
5284  o << string_t(new_indent, ' ');
5285  i->dump(o, pretty_print, indent_step, new_indent);
5286  }
5287 
5288  // decrease indentation
5289  if (pretty_print)
5290  {
5291  new_indent -= indent_step;
5292  o << "\n";
5293  }
5294 
5295  o << string_t(new_indent, ' ') << "]";
5296  return;
5297  }
5298 
5299  case value_t::string:
5300  {
5301  o << string_t("\"") << escape_string(*m_value.string) << "\"";
5302  return;
5303  }
5304 
5305  case value_t::boolean:
5306  {
5307  o << (m_value.boolean ? "true" : "false");
5308  return;
5309  }
5310 
5312  {
5313  o << m_value.number_integer;
5314  return;
5315  }
5316 
5317  case value_t::number_float:
5318  {
5319  // 15 digits of precision allows round-trip IEEE 754
5320  // string->double->string; to be safe, we read this value from
5321  // std::numeric_limits<number_float_t>::digits10
5322  o << std::setprecision(std::numeric_limits<number_float_t>::digits10) << m_value.number_float;
5323  return;
5324  }
5325 
5326  case value_t::discarded:
5327  {
5328  o << "<discarded>";
5329  return;
5330  }
5331 
5332  case value_t::null:
5333  {
5334  o << "null";
5335  return;
5336  }
5337  }
5338  }
5339 
5340  private:
5342  // member variables //
5344 
5346  value_t m_type = value_t::null;
5347 
5349  json_value m_value = {};
5350 
5351 
5352  private:
5354  // iterators //
5356 
5366  class primitive_iterator_t
5367  {
5368  public:
5370  void set_begin()
5371  {
5372  m_it = begin_value;
5373  }
5374 
5376  void set_end()
5377  {
5378  m_it = end_value;
5379  }
5380 
5382  bool is_begin() const
5383  {
5384  return (m_it == begin_value);
5385  }
5386 
5388  bool is_end() const
5389  {
5390  return (m_it == end_value);
5391  }
5392 
5394  operator difference_type& ()
5395  {
5396  return m_it;
5397  }
5398 
5400  operator difference_type () const
5401  {
5402  return m_it;
5403  }
5404 
5405  private:
5406  static constexpr difference_type begin_value = 0;
5407  static constexpr difference_type end_value = begin_value + 1;
5408 
5410  difference_type m_it = std::numeric_limits<std::ptrdiff_t>::denorm_min();
5411  };
5412 
5420  struct internal_iterator
5421  {
5423  typename object_t::iterator object_iterator;
5425  typename array_t::iterator array_iterator;
5427  primitive_iterator_t primitive_iterator;
5428 
5430  internal_iterator()
5431  : object_iterator(), array_iterator(), primitive_iterator()
5432  {}
5433  };
5434 
5435  public:
5449  class const_iterator : public std::iterator<std::random_access_iterator_tag, const basic_json>
5450  {
5452  friend class basic_json;
5453 
5454  public:
5464  using iterator_category = std::bidirectional_iterator_tag;
5465 
5467  const_iterator() = default;
5468 
5470  const_iterator(pointer object) : m_object(object)
5471  {
5472  switch (m_object->m_type)
5473  {
5475  {
5476  m_it.object_iterator = typename object_t::iterator();
5477  break;
5478  }
5479 
5481  {
5482  m_it.array_iterator = typename array_t::iterator();
5483  break;
5484  }
5485 
5486  default:
5487  {
5488  m_it.primitive_iterator = primitive_iterator_t();
5489  break;
5490  }
5491  }
5492  }
5493 
5495  const_iterator(const iterator& other) : m_object(other.m_object)
5496  {
5497  switch (m_object->m_type)
5498  {
5500  {
5501  m_it.object_iterator = other.m_it.object_iterator;
5502  break;
5503  }
5504 
5506  {
5507  m_it.array_iterator = other.m_it.array_iterator;
5508  break;
5509  }
5510 
5511  default:
5512  {
5513  m_it.primitive_iterator = other.m_it.primitive_iterator;
5514  break;
5515  }
5516  }
5517  }
5518 
5520  const_iterator(const const_iterator& other) noexcept
5521  : m_object(other.m_object), m_it(other.m_it)
5522  {}
5523 
5526  std::is_nothrow_move_constructible<pointer>::value and
5527  std::is_nothrow_move_assignable<pointer>::value and
5528  std::is_nothrow_move_constructible<internal_iterator>::value and
5529  std::is_nothrow_move_assignable<internal_iterator>::value
5530  )
5531  {
5532  std::swap(m_object, other.m_object);
5533  std::swap(m_it, other.m_it);
5534  return *this;
5535  }
5536 
5537  private:
5539  void set_begin()
5540  {
5541  switch (m_object->m_type)
5542  {
5544  {
5545  m_it.object_iterator = m_object->m_value.object->begin();
5546  break;
5547  }
5548 
5550  {
5551  m_it.array_iterator = m_object->m_value.array->begin();
5552  break;
5553  }
5554 
5556  {
5557  // set to end so begin()==end() is true: null is empty
5558  m_it.primitive_iterator.set_end();
5559  break;
5560  }
5561 
5562  default:
5563  {
5564  m_it.primitive_iterator.set_begin();
5565  break;
5566  }
5567  }
5568  }
5569 
5571  void set_end()
5572  {
5573  switch (m_object->m_type)
5574  {
5576  {
5577  m_it.object_iterator = m_object->m_value.object->end();
5578  break;
5579  }
5580 
5582  {
5583  m_it.array_iterator = m_object->m_value.array->end();
5584  break;
5585  }
5586 
5587  default:
5588  {
5589  m_it.primitive_iterator.set_end();
5590  break;
5591  }
5592  }
5593  }
5594 
5595  public:
5598  {
5599  switch (m_object->m_type)
5600  {
5602  {
5603  return m_it.object_iterator->second;
5604  }
5605 
5607  {
5608  return *m_it.array_iterator;
5609  }
5610 
5612  {
5613  throw std::out_of_range("cannot get value");
5614  }
5615 
5616  default:
5617  {
5618  if (m_it.primitive_iterator.is_begin())
5619  {
5620  return *m_object;
5621  }
5622  else
5623  {
5624  throw std::out_of_range("cannot get value");
5625  }
5626  }
5627  }
5628  }
5629 
5632  {
5633  switch (m_object->m_type)
5634  {
5636  {
5637  return &(m_it.object_iterator->second);
5638  }
5639 
5641  {
5642  return &*m_it.array_iterator;
5643  }
5644 
5645  default:
5646  {
5647  if (m_it.primitive_iterator.is_begin())
5648  {
5649  return m_object;
5650  }
5651  else
5652  {
5653  throw std::out_of_range("cannot get value");
5654  }
5655  }
5656  }
5657  }
5658 
5661  {
5662  auto result = *this;
5663  ++(*this);
5664  return result;
5665  }
5666 
5669  {
5670  switch (m_object->m_type)
5671  {
5673  {
5674  ++m_it.object_iterator;
5675  break;
5676  }
5677 
5679  {
5680  ++m_it.array_iterator;
5681  break;
5682  }
5683 
5684  default:
5685  {
5686  ++m_it.primitive_iterator;
5687  break;
5688  }
5689  }
5690 
5691  return *this;
5692  }
5693 
5696  {
5697  auto result = *this;
5698  --(*this);
5699  return result;
5700  }
5701 
5704  {
5705  switch (m_object->m_type)
5706  {
5708  {
5709  --m_it.object_iterator;
5710  break;
5711  }
5712 
5714  {
5715  --m_it.array_iterator;
5716  break;
5717  }
5718 
5719  default:
5720  {
5721  --m_it.primitive_iterator;
5722  break;
5723  }
5724  }
5725 
5726  return *this;
5727  }
5728 
5730  bool operator==(const const_iterator& other) const
5731  {
5732  // if objects are not the same, the comparison is undefined
5733  if (m_object != other.m_object)
5734  {
5735  throw std::domain_error("cannot compare iterators of different containers");
5736  }
5737 
5738  switch (m_object->m_type)
5739  {
5741  {
5742  return (m_it.object_iterator == other.m_it.object_iterator);
5743  }
5744 
5746  {
5747  return (m_it.array_iterator == other.m_it.array_iterator);
5748  }
5749 
5750  default:
5751  {
5752  return (m_it.primitive_iterator == other.m_it.primitive_iterator);
5753  }
5754  }
5755  }
5756 
5758  bool operator!=(const const_iterator& other) const
5759  {
5760  return not operator==(other);
5761  }
5762 
5764  bool operator<(const const_iterator& other) const
5765  {
5766  // if objects are not the same, the comparison is undefined
5767  if (m_object != other.m_object)
5768  {
5769  throw std::domain_error("cannot compare iterators of different containers");
5770  }
5771 
5772  switch (m_object->m_type)
5773  {
5775  {
5776  throw std::domain_error("cannot use operator< for object iterators");
5777  }
5778 
5780  {
5781  return (m_it.array_iterator < other.m_it.array_iterator);
5782  }
5783 
5784  default:
5785  {
5786  return (m_it.primitive_iterator < other.m_it.primitive_iterator);
5787  }
5788  }
5789  }
5790 
5792  bool operator<=(const const_iterator& other) const
5793  {
5794  return not other.operator < (*this);
5795  }
5796 
5798  bool operator>(const const_iterator& other) const
5799  {
5800  return not operator<=(other);
5801  }
5802 
5804  bool operator>=(const const_iterator& other) const
5805  {
5806  return not operator<(other);
5807  }
5808 
5811  {
5812  switch (m_object->m_type)
5813  {
5815  {
5816  throw std::domain_error("cannot use operator+= for object iterators");
5817  }
5818 
5820  {
5821  m_it.array_iterator += i;
5822  break;
5823  }
5824 
5825  default:
5826  {
5827  m_it.primitive_iterator += i;
5828  break;
5829  }
5830  }
5831 
5832  return *this;
5833  }
5834 
5837  {
5838  return operator+=(-i);
5839  }
5840 
5843  {
5844  auto result = *this;
5845  result += i;
5846  return result;
5847  }
5848 
5851  {
5852  auto result = *this;
5853  result -= i;
5854  return result;
5855  }
5856 
5859  {
5860  switch (m_object->m_type)
5861  {
5863  {
5864  throw std::domain_error("cannot use operator- for object iterators");
5865  }
5866 
5868  {
5869  return m_it.array_iterator - other.m_it.array_iterator;
5870  }
5871 
5872  default:
5873  {
5874  return m_it.primitive_iterator - other.m_it.primitive_iterator;
5875  }
5876  }
5877  }
5878 
5881  {
5882  switch (m_object->m_type)
5883  {
5885  {
5886  throw std::domain_error("cannot use operator[] for object iterators");
5887  }
5888 
5890  {
5891  return *(m_it.array_iterator + n);
5892  }
5893 
5895  {
5896  throw std::out_of_range("cannot get value");
5897  }
5898 
5899  default:
5900  {
5901  if (m_it.primitive_iterator == -n)
5902  {
5903  return *m_object;
5904  }
5905  else
5906  {
5907  throw std::out_of_range("cannot get value");
5908  }
5909  }
5910  }
5911  }
5912 
5914  typename object_t::key_type key() const
5915  {
5916  if (m_object->is_object())
5917  {
5918  return m_it.object_iterator->first;
5919  }
5920  else
5921  {
5922  throw std::domain_error("cannot use key() for non-object iterators");
5923  }
5924  }
5925 
5928  {
5929  return operator*();
5930  }
5931 
5932  private:
5934  pointer m_object = nullptr;
5936  internal_iterator m_it = internal_iterator();
5937  };
5938 
5951  class iterator : public const_iterator
5952  {
5953  public:
5955  using pointer = typename basic_json::pointer;
5957 
5959  iterator() = default;
5960 
5962  iterator(pointer object) noexcept : base_iterator(object)
5963  {}
5964 
5966  iterator(const iterator& other) noexcept
5967  : base_iterator(other)
5968  {}
5969 
5971  iterator& operator=(iterator other) noexcept(
5972  std::is_nothrow_move_constructible<pointer>::value and
5973  std::is_nothrow_move_assignable<pointer>::value and
5974  std::is_nothrow_move_constructible<internal_iterator>::value and
5975  std::is_nothrow_move_assignable<internal_iterator>::value
5976  )
5977  {
5978  base_iterator::operator=(other);
5979  return *this;
5980  }
5981 
5984  {
5985  return const_cast<reference>(base_iterator::operator*());
5986  }
5987 
5990  {
5991  return const_cast<pointer>(base_iterator::operator->());
5992  }
5993 
5996  {
5997  iterator result = *this;
5999  return result;
6000  }
6001 
6004  {
6006  return *this;
6007  }
6008 
6011  {
6012  iterator result = *this;
6014  return result;
6015  }
6016 
6019  {
6021  return *this;
6022  }
6023 
6026  {
6028  return *this;
6029  }
6030 
6033  {
6035  return *this;
6036  }
6037 
6040  {
6041  auto result = *this;
6042  result += i;
6043  return result;
6044  }
6045 
6048  {
6049  auto result = *this;
6050  result -= i;
6051  return result;
6052  }
6053 
6054  difference_type operator-(const iterator& other) const
6055  {
6056  return base_iterator::operator-(other);
6057  }
6058 
6061  {
6062  return const_cast<reference>(base_iterator::operator[](n));
6063  }
6064 
6067  {
6068  return const_cast<reference>(base_iterator::value());
6069  }
6070  };
6071 
6089  template<typename Base>
6090  class json_reverse_iterator : public std::reverse_iterator<Base>
6091  {
6092  public:
6094  using base_iterator = std::reverse_iterator<Base>;
6096  using reference = typename Base::reference;
6097 
6099  json_reverse_iterator(const typename base_iterator::iterator_type& it)
6100  : base_iterator(it) {}
6101 
6104 
6107  {
6108  return base_iterator::operator++(1);
6109  }
6110 
6113  {
6114  base_iterator::operator++();
6115  return *this;
6116  }
6117 
6120  {
6121  return base_iterator::operator--(1);
6122  }
6123 
6126  {
6127  base_iterator::operator--();
6128  return *this;
6129  }
6130 
6133  {
6134  base_iterator::operator+=(i);
6135  return *this;
6136  }
6137 
6140  {
6141  auto result = *this;
6142  result += i;
6143  return result;
6144  }
6145 
6148  {
6149  auto result = *this;
6150  result -= i;
6151  return result;
6152  }
6153 
6156  {
6157  return this->base() - other.base();
6158  }
6159 
6162  {
6163  return *(this->operator+(n));
6164  }
6165 
6167  typename object_t::key_type key() const
6168  {
6169  auto it = --this->base();
6170  return it.key();
6171  }
6172 
6175  {
6176  auto it = --this->base();
6177  return it.operator * ();
6178  }
6179  };
6180 
6181 
6182  private:
6184  template<typename IteratorType>
6185  class iteration_proxy
6186  {
6187  private:
6189  class iteration_proxy_internal
6190  {
6191  private:
6193  IteratorType anchor;
6195  size_t array_index = 0;
6196 
6197  public:
6198  iteration_proxy_internal(IteratorType it)
6199  : anchor(it)
6200  {}
6201 
6203  iteration_proxy_internal& operator*()
6204  {
6205  return *this;
6206  }
6207 
6209  iteration_proxy_internal& operator++()
6210  {
6211  ++anchor;
6212  ++array_index;
6213 
6214  return *this;
6215  }
6216 
6218  bool operator!= (const iteration_proxy_internal& o)
6219  {
6220  return anchor != o.anchor;
6221  }
6222 
6224  typename basic_json::string_t key() const
6225  {
6226  switch (anchor.m_object->type())
6227  {
6228  // use integer array index as key
6229  case value_t::array:
6230  {
6231  return std::to_string(array_index);
6232  }
6233 
6234  // use key from the object
6235  case value_t::object:
6236  {
6237  return anchor.key();
6238  }
6239 
6240  // use an empty key for all primitive types
6241  default:
6242  {
6243  return "";
6244  }
6245  }
6246  }
6247 
6249  typename IteratorType::reference value() const
6250  {
6251  return anchor.value();
6252  }
6253  };
6254 
6256  typename IteratorType::reference container;
6257 
6258  public:
6260  iteration_proxy(typename IteratorType::reference cont)
6261  : container(cont)
6262  {}
6263 
6265  iteration_proxy_internal begin()
6266  {
6267  return iteration_proxy_internal(container.begin());
6268  }
6269 
6271  iteration_proxy_internal end()
6272  {
6273  return iteration_proxy_internal(container.end());
6274  }
6275  };
6276 
6277 
6278  private:
6280  // lexer and parser //
6282 
6290  class lexer
6291  {
6292  public:
6294  enum class token_type
6295  {
6296  uninitialized,
6297  literal_true,
6298  literal_false,
6299  literal_null,
6300  value_string,
6301  value_number,
6302  begin_array,
6303  begin_object,
6304  end_array,
6305  end_object,
6306  name_separator,
6307  value_separator,
6308  parse_error,
6309  end_of_input
6310  };
6311 
6313  using lexer_char_t = unsigned char;
6314 
6316  explicit lexer(const string_t& s) noexcept
6317  : m_stream(nullptr), m_buffer(s)
6318  {
6319  m_content = reinterpret_cast<const lexer_char_t*>(s.c_str());
6320  m_start = m_cursor = m_content;
6321  m_limit = m_content + s.size();
6322  }
6323  explicit lexer(std::istream* s) noexcept
6324  : m_stream(s), m_buffer()
6325  {
6326  getline(*m_stream, m_buffer);
6327  m_content = reinterpret_cast<const lexer_char_t*>(m_buffer.c_str());
6328  m_start = m_cursor = m_content;
6329  m_limit = m_content + m_buffer.size();
6330  }
6331 
6333  lexer() = default;
6334 
6335  // switch of unwanted functions
6336  lexer(const lexer&) = delete;
6337  lexer operator=(const lexer&) = delete;
6338 
6350  static string_t to_unicode(const std::size_t codepoint1,
6351  const std::size_t codepoint2 = 0)
6352  {
6353  string_t result;
6354 
6355  // calculate the codepoint from the given code points
6356  std::size_t codepoint = codepoint1;
6357 
6358  // check if codepoint1 is a high surrogate
6359  if (codepoint1 >= 0xD800 and codepoint1 <= 0xDBFF)
6360  {
6361  // check if codepoint2 is a low surrogate
6362  if (codepoint2 >= 0xDC00 and codepoint2 <= 0xDFFF)
6363  {
6364  codepoint =
6365  // high surrogate occupies the most significant 22 bits
6366  (codepoint1 << 10)
6367  // low surrogate occupies the least significant 15 bits
6368  + codepoint2
6369  // there is still the 0xD800, 0xDC00 and 0x10000 noise
6370  // in the result so we have to substract with:
6371  // (0xD800 << 10) + DC00 - 0x10000 = 0x35FDC00
6372  - 0x35FDC00;
6373  }
6374  else
6375  {
6376  throw std::invalid_argument("missing or wrong low surrogate");
6377  }
6378  }
6379 
6380  if (codepoint < 0x80)
6381  {
6382  // 1-byte characters: 0xxxxxxx (ASCII)
6383  result.append(1, static_cast<typename string_t::value_type>(codepoint));
6384  }
6385  else if (codepoint <= 0x7ff)
6386  {
6387  // 2-byte characters: 110xxxxx 10xxxxxx
6388  result.append(1, static_cast<typename string_t::value_type>(0xC0 | ((codepoint >> 6) & 0x1F)));
6389  result.append(1, static_cast<typename string_t::value_type>(0x80 | (codepoint & 0x3F)));
6390  }
6391  else if (codepoint <= 0xffff)
6392  {
6393  // 3-byte characters: 1110xxxx 10xxxxxx 10xxxxxx
6394  result.append(1, static_cast<typename string_t::value_type>(0xE0 | ((codepoint >> 12) & 0x0F)));
6395  result.append(1, static_cast<typename string_t::value_type>(0x80 | ((codepoint >> 6) & 0x3F)));
6396  result.append(1, static_cast<typename string_t::value_type>(0x80 | (codepoint & 0x3F)));
6397  }
6398  else if (codepoint <= 0x10ffff)
6399  {
6400  // 4-byte characters: 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
6401  result.append(1, static_cast<typename string_t::value_type>(0xF0 | ((codepoint >> 18) & 0x07)));
6402  result.append(1, static_cast<typename string_t::value_type>(0x80 | ((codepoint >> 12) & 0x3F)));
6403  result.append(1, static_cast<typename string_t::value_type>(0x80 | ((codepoint >> 6) & 0x3F)));
6404  result.append(1, static_cast<typename string_t::value_type>(0x80 | (codepoint & 0x3F)));
6405  }
6406  else
6407  {
6408  throw std::out_of_range("code points above 0x10FFFF are invalid");
6409  }
6410 
6411  return result;
6412  }
6413 
6415  static std::string token_type_name(token_type t)
6416  {
6417  switch (t)
6418  {
6419  case token_type::uninitialized:
6420  return "<uninitialized>";
6421  case token_type::literal_true:
6422  return "true literal";
6423  case token_type::literal_false:
6424  return "false literal";
6425  case token_type::literal_null:
6426  return "null literal";
6427  case token_type::value_string:
6428  return "string literal";
6429  case token_type::value_number:
6430  return "number literal";
6431  case token_type::begin_array:
6432  return "[";
6433  case token_type::begin_object:
6434  return "{";
6435  case token_type::end_array:
6436  return "]";
6437  case token_type::end_object:
6438  return "}";
6439  case token_type::name_separator:
6440  return ":";
6441  case token_type::value_separator:
6442  return ",";
6443  case token_type::parse_error:
6444  return "<parse error>";
6445  case token_type::end_of_input:
6446  return "<end of input>";
6447  default:
6448  {
6449  // catch non-enum values
6450  return "unknown token"; // LCOV_EXCL_LINE
6451  }
6452  }
6453  }
6454 
6465  token_type scan() noexcept
6466  {
6467  // pointer for backtracking information
6468  m_marker = nullptr;
6469 
6470  // remember the begin of the token
6471  m_start = m_cursor;
6472 
6473 
6474  {
6475  lexer_char_t yych;
6476  unsigned int yyaccept = 0;
6477  static const unsigned char yybm[] =
6478  {
6479  0, 0, 0, 0, 0, 0, 0, 0,
6480  0, 32, 32, 0, 0, 32, 0, 0,
6481  64, 64, 64, 64, 64, 64, 64, 64,
6482  64, 64, 64, 64, 64, 64, 64, 64,
6483  96, 64, 0, 64, 64, 64, 64, 64,
6484  64, 64, 64, 64, 64, 64, 64, 64,
6485  192, 192, 192, 192, 192, 192, 192, 192,
6486  192, 192, 64, 64, 64, 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, 0, 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  64, 64, 64, 64, 64, 64, 64, 64,
6508  64, 64, 64, 64, 64, 64, 64, 64,
6509  64, 64, 64, 64, 64, 64, 64, 64,
6510  64, 64, 64, 64, 64, 64, 64, 64,
6511  };
6512  if ((m_limit - m_cursor) < 5)
6513  {
6514  yyfill(); // LCOV_EXCL_LINE;
6515  }
6516  yych = *m_cursor;
6517  if (yych <= ':')
6518  {
6519  if (yych <= ' ')
6520  {
6521  if (yych <= '\n')
6522  {
6523  if (yych <= 0x00)
6524  {
6525  goto basic_json_parser_28;
6526  }
6527  if (yych <= 0x08)
6528  {
6529  goto basic_json_parser_30;
6530  }
6531  if (yych >= '\n')
6532  {
6533  goto basic_json_parser_4;
6534  }
6535  }
6536  else
6537  {
6538  if (yych == '\r')
6539  {
6540  goto basic_json_parser_2;
6541  }
6542  if (yych <= 0x1F)
6543  {
6544  goto basic_json_parser_30;
6545  }
6546  }
6547  }
6548  else
6549  {
6550  if (yych <= ',')
6551  {
6552  if (yych == '"')
6553  {
6554  goto basic_json_parser_27;
6555  }
6556  if (yych <= '+')
6557  {
6558  goto basic_json_parser_30;
6559  }
6560  goto basic_json_parser_16;
6561  }
6562  else
6563  {
6564  if (yych <= '/')
6565  {
6566  if (yych <= '-')
6567  {
6568  goto basic_json_parser_23;
6569  }
6570  goto basic_json_parser_30;
6571  }
6572  else
6573  {
6574  if (yych <= '0')
6575  {
6576  goto basic_json_parser_24;
6577  }
6578  if (yych <= '9')
6579  {
6580  goto basic_json_parser_26;
6581  }
6582  goto basic_json_parser_18;
6583  }
6584  }
6585  }
6586  }
6587  else
6588  {
6589  if (yych <= 'n')
6590  {
6591  if (yych <= ']')
6592  {
6593  if (yych == '[')
6594  {
6595  goto basic_json_parser_8;
6596  }
6597  if (yych <= '\\')
6598  {
6599  goto basic_json_parser_30;
6600  }
6601  goto basic_json_parser_10;
6602  }
6603  else
6604  {
6605  if (yych == 'f')
6606  {
6607  goto basic_json_parser_22;
6608  }
6609  if (yych <= 'm')
6610  {
6611  goto basic_json_parser_30;
6612  }
6613  goto basic_json_parser_20;
6614  }
6615  }
6616  else
6617  {
6618  if (yych <= '{')
6619  {
6620  if (yych == 't')
6621  {
6622  goto basic_json_parser_21;
6623  }
6624  if (yych <= 'z')
6625  {
6626  goto basic_json_parser_30;
6627  }
6628  goto basic_json_parser_12;
6629  }
6630  else
6631  {
6632  if (yych <= '}')
6633  {
6634  if (yych <= '|')
6635  {
6636  goto basic_json_parser_30;
6637  }
6638  goto basic_json_parser_14;
6639  }
6640  else
6641  {
6642  if (yych == 0xEF)
6643  {
6644  goto basic_json_parser_6;
6645  }
6646  goto basic_json_parser_30;
6647  }
6648  }
6649  }
6650  }
6651 basic_json_parser_2:
6652  ++m_cursor;
6653  yych = *m_cursor;
6654  goto basic_json_parser_5;
6655 basic_json_parser_3:
6656  {
6657  return scan();
6658  }
6659 basic_json_parser_4:
6660  ++m_cursor;
6661  if (m_limit <= m_cursor)
6662  {
6663  yyfill(); // LCOV_EXCL_LINE;
6664  }
6665  yych = *m_cursor;
6666 basic_json_parser_5:
6667  if (yybm[0 + yych] & 32)
6668  {
6669  goto basic_json_parser_4;
6670  }
6671  goto basic_json_parser_3;
6672 basic_json_parser_6:
6673  yyaccept = 0;
6674  yych = *(m_marker = ++m_cursor);
6675  if (yych == 0xBB)
6676  {
6677  goto basic_json_parser_64;
6678  }
6679 basic_json_parser_7:
6680  {
6681  return token_type::parse_error;
6682  }
6683 basic_json_parser_8:
6684  ++m_cursor;
6685  {
6686  return token_type::begin_array;
6687  }
6688 basic_json_parser_10:
6689  ++m_cursor;
6690  {
6691  return token_type::end_array;
6692  }
6693 basic_json_parser_12:
6694  ++m_cursor;
6695  {
6696  return token_type::begin_object;
6697  }
6698 basic_json_parser_14:
6699  ++m_cursor;
6700  {
6701  return token_type::end_object;
6702  }
6703 basic_json_parser_16:
6704  ++m_cursor;
6705  {
6706  return token_type::value_separator;
6707  }
6708 basic_json_parser_18:
6709  ++m_cursor;
6710  {
6711  return token_type::name_separator;
6712  }
6713 basic_json_parser_20:
6714  yyaccept = 0;
6715  yych = *(m_marker = ++m_cursor);
6716  if (yych == 'u')
6717  {
6718  goto basic_json_parser_60;
6719  }
6720  goto basic_json_parser_7;
6721 basic_json_parser_21:
6722  yyaccept = 0;
6723  yych = *(m_marker = ++m_cursor);
6724  if (yych == 'r')
6725  {
6726  goto basic_json_parser_56;
6727  }
6728  goto basic_json_parser_7;
6729 basic_json_parser_22:
6730  yyaccept = 0;
6731  yych = *(m_marker = ++m_cursor);
6732  if (yych == 'a')
6733  {
6734  goto basic_json_parser_51;
6735  }
6736  goto basic_json_parser_7;
6737 basic_json_parser_23:
6738  yych = *++m_cursor;
6739  if (yych <= '/')
6740  {
6741  goto basic_json_parser_7;
6742  }
6743  if (yych <= '0')
6744  {
6745  goto basic_json_parser_50;
6746  }
6747  if (yych <= '9')
6748  {
6749  goto basic_json_parser_41;
6750  }
6751  goto basic_json_parser_7;
6752 basic_json_parser_24:
6753  yyaccept = 1;
6754  yych = *(m_marker = ++m_cursor);
6755  if (yych <= 'D')
6756  {
6757  if (yych == '.')
6758  {
6759  goto basic_json_parser_43;
6760  }
6761  }
6762  else
6763  {
6764  if (yych <= 'E')
6765  {
6766  goto basic_json_parser_44;
6767  }
6768  if (yych == 'e')
6769  {
6770  goto basic_json_parser_44;
6771  }
6772  }
6773 basic_json_parser_25:
6774  {
6775  return token_type::value_number;
6776  }
6777 basic_json_parser_26:
6778  yyaccept = 1;
6779  yych = *(m_marker = ++m_cursor);
6780  goto basic_json_parser_42;
6781 basic_json_parser_27:
6782  yyaccept = 0;
6783  yych = *(m_marker = ++m_cursor);
6784  if (yych <= 0x0F)
6785  {
6786  goto basic_json_parser_7;
6787  }
6788  goto basic_json_parser_32;
6789 basic_json_parser_28:
6790  ++m_cursor;
6791  {
6792  return token_type::end_of_input;
6793  }
6794 basic_json_parser_30:
6795  yych = *++m_cursor;
6796  goto basic_json_parser_7;
6797 basic_json_parser_31:
6798  ++m_cursor;
6799  if (m_limit <= m_cursor)
6800  {
6801  yyfill(); // LCOV_EXCL_LINE;
6802  }
6803  yych = *m_cursor;
6804 basic_json_parser_32:
6805  if (yybm[0 + yych] & 64)
6806  {
6807  goto basic_json_parser_31;
6808  }
6809  if (yych <= 0x0F)
6810  {
6811  goto basic_json_parser_33;
6812  }
6813  if (yych <= '"')
6814  {
6815  goto basic_json_parser_35;
6816  }
6817  goto basic_json_parser_34;
6818 basic_json_parser_33:
6819  m_cursor = m_marker;
6820  if (yyaccept == 0)
6821  {
6822  goto basic_json_parser_7;
6823  }
6824  else
6825  {
6826  goto basic_json_parser_25;
6827  }
6828 basic_json_parser_34:
6829  ++m_cursor;
6830  if (m_limit <= m_cursor)
6831  {
6832  yyfill(); // LCOV_EXCL_LINE;
6833  }
6834  yych = *m_cursor;
6835  if (yych <= 'e')
6836  {
6837  if (yych <= '/')
6838  {
6839  if (yych == '"')
6840  {
6841  goto basic_json_parser_31;
6842  }
6843  if (yych <= '.')
6844  {
6845  goto basic_json_parser_33;
6846  }
6847  goto basic_json_parser_31;
6848  }
6849  else
6850  {
6851  if (yych <= '\\')
6852  {
6853  if (yych <= '[')
6854  {
6855  goto basic_json_parser_33;
6856  }
6857  goto basic_json_parser_31;
6858  }
6859  else
6860  {
6861  if (yych == 'b')
6862  {
6863  goto basic_json_parser_31;
6864  }
6865  goto basic_json_parser_33;
6866  }
6867  }
6868  }
6869  else
6870  {
6871  if (yych <= 'q')
6872  {
6873  if (yych <= 'f')
6874  {
6875  goto basic_json_parser_31;
6876  }
6877  if (yych == 'n')
6878  {
6879  goto basic_json_parser_31;
6880  }
6881  goto basic_json_parser_33;
6882  }
6883  else
6884  {
6885  if (yych <= 's')
6886  {
6887  if (yych <= 'r')
6888  {
6889  goto basic_json_parser_31;
6890  }
6891  goto basic_json_parser_33;
6892  }
6893  else
6894  {
6895  if (yych <= 't')
6896  {
6897  goto basic_json_parser_31;
6898  }
6899  if (yych <= 'u')
6900  {
6901  goto basic_json_parser_37;
6902  }
6903  goto basic_json_parser_33;
6904  }
6905  }
6906  }
6907 basic_json_parser_35:
6908  ++m_cursor;
6909  {
6910  return token_type::value_string;
6911  }
6912 basic_json_parser_37:
6913  ++m_cursor;
6914  if (m_limit <= m_cursor)
6915  {
6916  yyfill(); // LCOV_EXCL_LINE;
6917  }
6918  yych = *m_cursor;
6919  if (yych <= '@')
6920  {
6921  if (yych <= '/')
6922  {
6923  goto basic_json_parser_33;
6924  }
6925  if (yych >= ':')
6926  {
6927  goto basic_json_parser_33;
6928  }
6929  }
6930  else
6931  {
6932  if (yych <= 'F')
6933  {
6934  goto basic_json_parser_38;
6935  }
6936  if (yych <= '`')
6937  {
6938  goto basic_json_parser_33;
6939  }
6940  if (yych >= 'g')
6941  {
6942  goto basic_json_parser_33;
6943  }
6944  }
6945 basic_json_parser_38:
6946  ++m_cursor;
6947  if (m_limit <= m_cursor)
6948  {
6949  yyfill(); // LCOV_EXCL_LINE;
6950  }
6951  yych = *m_cursor;
6952  if (yych <= '@')
6953  {
6954  if (yych <= '/')
6955  {
6956  goto basic_json_parser_33;
6957  }
6958  if (yych >= ':')
6959  {
6960  goto basic_json_parser_33;
6961  }
6962  }
6963  else
6964  {
6965  if (yych <= 'F')
6966  {
6967  goto basic_json_parser_39;
6968  }
6969  if (yych <= '`')
6970  {
6971  goto basic_json_parser_33;
6972  }
6973  if (yych >= 'g')
6974  {
6975  goto basic_json_parser_33;
6976  }
6977  }
6978 basic_json_parser_39:
6979  ++m_cursor;
6980  if (m_limit <= m_cursor)
6981  {
6982  yyfill(); // LCOV_EXCL_LINE;
6983  }
6984  yych = *m_cursor;
6985  if (yych <= '@')
6986  {
6987  if (yych <= '/')
6988  {
6989  goto basic_json_parser_33;
6990  }
6991  if (yych >= ':')
6992  {
6993  goto basic_json_parser_33;
6994  }
6995  }
6996  else
6997  {
6998  if (yych <= 'F')
6999  {
7000  goto basic_json_parser_40;
7001  }
7002  if (yych <= '`')
7003  {
7004  goto basic_json_parser_33;
7005  }
7006  if (yych >= 'g')
7007  {
7008  goto basic_json_parser_33;
7009  }
7010  }
7011 basic_json_parser_40:
7012  ++m_cursor;
7013  if (m_limit <= m_cursor)
7014  {
7015  yyfill(); // LCOV_EXCL_LINE;
7016  }
7017  yych = *m_cursor;
7018  if (yych <= '@')
7019  {
7020  if (yych <= '/')
7021  {
7022  goto basic_json_parser_33;
7023  }
7024  if (yych <= '9')
7025  {
7026  goto basic_json_parser_31;
7027  }
7028  goto basic_json_parser_33;
7029  }
7030  else
7031  {
7032  if (yych <= 'F')
7033  {
7034  goto basic_json_parser_31;
7035  }
7036  if (yych <= '`')
7037  {
7038  goto basic_json_parser_33;
7039  }
7040  if (yych <= 'f')
7041  {
7042  goto basic_json_parser_31;
7043  }
7044  goto basic_json_parser_33;
7045  }
7046 basic_json_parser_41:
7047  yyaccept = 1;
7048  m_marker = ++m_cursor;
7049  if ((m_limit - m_cursor) < 3)
7050  {
7051  yyfill(); // LCOV_EXCL_LINE;
7052  }
7053  yych = *m_cursor;
7054 basic_json_parser_42:
7055  if (yybm[0 + yych] & 128)
7056  {
7057  goto basic_json_parser_41;
7058  }
7059  if (yych <= 'D')
7060  {
7061  if (yych != '.')
7062  {
7063  goto basic_json_parser_25;
7064  }
7065  }
7066  else
7067  {
7068  if (yych <= 'E')
7069  {
7070  goto basic_json_parser_44;
7071  }
7072  if (yych == 'e')
7073  {
7074  goto basic_json_parser_44;
7075  }
7076  goto basic_json_parser_25;
7077  }
7078 basic_json_parser_43:
7079  yych = *++m_cursor;
7080  if (yych <= '/')
7081  {
7082  goto basic_json_parser_33;
7083  }
7084  if (yych <= '9')
7085  {
7086  goto basic_json_parser_48;
7087  }
7088  goto basic_json_parser_33;
7089 basic_json_parser_44:
7090  yych = *++m_cursor;
7091  if (yych <= ',')
7092  {
7093  if (yych != '+')
7094  {
7095  goto basic_json_parser_33;
7096  }
7097  }
7098  else
7099  {
7100  if (yych <= '-')
7101  {
7102  goto basic_json_parser_45;
7103  }
7104  if (yych <= '/')
7105  {
7106  goto basic_json_parser_33;
7107  }
7108  if (yych <= '9')
7109  {
7110  goto basic_json_parser_46;
7111  }
7112  goto basic_json_parser_33;
7113  }
7114 basic_json_parser_45:
7115  yych = *++m_cursor;
7116  if (yych <= '/')
7117  {
7118  goto basic_json_parser_33;
7119  }
7120  if (yych >= ':')
7121  {
7122  goto basic_json_parser_33;
7123  }
7124 basic_json_parser_46:
7125  ++m_cursor;
7126  if (m_limit <= m_cursor)
7127  {
7128  yyfill(); // LCOV_EXCL_LINE;
7129  }
7130  yych = *m_cursor;
7131  if (yych <= '/')
7132  {
7133  goto basic_json_parser_25;
7134  }
7135  if (yych <= '9')
7136  {
7137  goto basic_json_parser_46;
7138  }
7139  goto basic_json_parser_25;
7140 basic_json_parser_48:
7141  yyaccept = 1;
7142  m_marker = ++m_cursor;
7143  if ((m_limit - m_cursor) < 3)
7144  {
7145  yyfill(); // LCOV_EXCL_LINE;
7146  }
7147  yych = *m_cursor;
7148  if (yych <= 'D')
7149  {
7150  if (yych <= '/')
7151  {
7152  goto basic_json_parser_25;
7153  }
7154  if (yych <= '9')
7155  {
7156  goto basic_json_parser_48;
7157  }
7158  goto basic_json_parser_25;
7159  }
7160  else
7161  {
7162  if (yych <= 'E')
7163  {
7164  goto basic_json_parser_44;
7165  }
7166  if (yych == 'e')
7167  {
7168  goto basic_json_parser_44;
7169  }
7170  goto basic_json_parser_25;
7171  }
7172 basic_json_parser_50:
7173  yyaccept = 1;
7174  yych = *(m_marker = ++m_cursor);
7175  if (yych <= 'D')
7176  {
7177  if (yych == '.')
7178  {
7179  goto basic_json_parser_43;
7180  }
7181  goto basic_json_parser_25;
7182  }
7183  else
7184  {
7185  if (yych <= 'E')
7186  {
7187  goto basic_json_parser_44;
7188  }
7189  if (yych == 'e')
7190  {
7191  goto basic_json_parser_44;
7192  }
7193  goto basic_json_parser_25;
7194  }
7195 basic_json_parser_51:
7196  yych = *++m_cursor;
7197  if (yych != 'l')
7198  {
7199  goto basic_json_parser_33;
7200  }
7201  yych = *++m_cursor;
7202  if (yych != 's')
7203  {
7204  goto basic_json_parser_33;
7205  }
7206  yych = *++m_cursor;
7207  if (yych != 'e')
7208  {
7209  goto basic_json_parser_33;
7210  }
7211  ++m_cursor;
7212  {
7213  return token_type::literal_false;
7214  }
7215 basic_json_parser_56:
7216  yych = *++m_cursor;
7217  if (yych != 'u')
7218  {
7219  goto basic_json_parser_33;
7220  }
7221  yych = *++m_cursor;
7222  if (yych != 'e')
7223  {
7224  goto basic_json_parser_33;
7225  }
7226  ++m_cursor;
7227  {
7228  return token_type::literal_true;
7229  }
7230 basic_json_parser_60:
7231  yych = *++m_cursor;
7232  if (yych != 'l')
7233  {
7234  goto basic_json_parser_33;
7235  }
7236  yych = *++m_cursor;
7237  if (yych != 'l')
7238  {
7239  goto basic_json_parser_33;
7240  }
7241  ++m_cursor;
7242  {
7243  return token_type::literal_null;
7244  }
7245 basic_json_parser_64:
7246  yych = *++m_cursor;
7247  if (yych != 0xBF)
7248  {
7249  goto basic_json_parser_33;
7250  }
7251  ++m_cursor;
7252  {
7253  return scan();
7254  }
7255  }
7256 
7257 
7258  }
7259 
7261  void yyfill() noexcept
7262  {
7263  if (not m_stream or not * m_stream)
7264  {
7265  return;
7266  }
7267 
7268  const ssize_t offset_start = m_start - m_content;
7269  const ssize_t offset_marker = m_marker - m_start;
7270  const ssize_t offset_cursor = m_cursor - m_start;
7271 
7272  m_buffer.erase(0, static_cast<size_t>(offset_start));
7273  std::string line;
7274  std::getline(*m_stream, line);
7275  m_buffer += "\n" + line; // add line with newline symbol
7276 
7277  m_content = reinterpret_cast<const lexer_char_t*>(m_buffer.c_str());
7278  m_start = m_content;
7279  m_marker = m_start + offset_marker;
7280  m_cursor = m_start + offset_cursor;
7281  m_limit = m_start + m_buffer.size() - 1;
7282  }
7283 
7285  string_t get_token() const noexcept
7286  {
7287  return string_t(reinterpret_cast<typename string_t::const_pointer>(m_start),
7288  static_cast<size_t>(m_cursor - m_start));
7289  }
7290 
7312  string_t get_string() const
7313  {
7314  string_t result;
7315  result.reserve(static_cast<size_t>(m_cursor - m_start - 2));
7316 
7317  // iterate the result between the quotes
7318  for (const lexer_char_t* i = m_start + 1; i < m_cursor - 1; ++i)
7319  {
7320  // process escaped characters
7321  if (*i == '\\')
7322  {
7323  // read next character
7324  ++i;
7325 
7326  switch (*i)
7327  {
7328  // the default escapes
7329  case 't':
7330  {
7331  result += "\t";
7332  break;
7333  }
7334  case 'b':
7335  {
7336  result += "\b";
7337  break;
7338  }
7339  case 'f':
7340  {
7341  result += "\f";
7342  break;
7343  }
7344  case 'n':
7345  {
7346  result += "\n";
7347  break;
7348  }
7349  case 'r':
7350  {
7351  result += "\r";
7352  break;
7353  }
7354  case '\\':
7355  {
7356  result += "\\";
7357  break;
7358  }
7359  case '/':
7360  {
7361  result += "/";
7362  break;
7363  }
7364  case '"':
7365  {
7366  result += "\"";
7367  break;
7368  }
7369 
7370  // unicode
7371  case 'u':
7372  {
7373  // get code xxxx from uxxxx
7374  auto codepoint = std::strtoul(std::string(reinterpret_cast<typename string_t::const_pointer>(i + 1),
7375  4).c_str(), nullptr, 16);
7376 
7377  // check if codepoint is a high surrogate
7378  if (codepoint >= 0xD800 and codepoint <= 0xDBFF)
7379  {
7380  // make sure there is a subsequent unicode
7381  if ((i + 6 >= m_limit) or * (i + 5) != '\\' or * (i + 6) != 'u')
7382  {
7383  throw std::invalid_argument("missing low surrogate");
7384  }
7385 
7386  // get code yyyy from uxxxx\uyyyy
7387  auto codepoint2 = std::strtoul(std::string(reinterpret_cast<typename string_t::const_pointer>
7388  (i + 7), 4).c_str(), nullptr, 16);
7389  result += to_unicode(codepoint, codepoint2);
7390  // skip the next 10 characters (xxxx\uyyyy)
7391  i += 10;
7392  }
7393  else
7394  {
7395  // add unicode character(s)
7396  result += to_unicode(codepoint);
7397  // skip the next four characters (xxxx)
7398  i += 4;
7399  }
7400  break;
7401  }
7402  }
7403  }
7404  else
7405  {
7406  // all other characters are just copied to the end of the
7407  // string
7408  result.append(1, static_cast<typename string_t::value_type>(*i));
7409  }
7410  }
7411 
7412  return result;
7413  }
7414 
7432  long double get_number() const
7433  {
7434  // conversion
7435  typename string_t::value_type* endptr;
7436  const auto float_val = std::strtold(reinterpret_cast<typename string_t::const_pointer>(m_start),
7437  &endptr);
7438 
7439  // return float_val if the whole number was translated and NAN
7440  // otherwise
7441  return (reinterpret_cast<lexer_char_t*>(endptr) == m_cursor) ? float_val : NAN;
7442  }
7443 
7444  private:
7446  std::istream* m_stream;
7448  string_t m_buffer;
7450  const lexer_char_t* m_content = nullptr;
7452  const lexer_char_t* m_start = nullptr;
7454  const lexer_char_t* m_marker = nullptr;
7456  const lexer_char_t* m_cursor = nullptr;
7458  const lexer_char_t* m_limit = nullptr;
7459  };
7460 
7466  class parser
7467  {
7468  public:
7470  parser(const string_t& s, parser_callback_t cb = nullptr)
7471  : callback(cb), m_lexer(s)
7472  {
7473  // read first token
7474  get_token();
7475  }
7476 
7478  parser(std::istream& _is, parser_callback_t cb = nullptr)
7479  : callback(cb), m_lexer(&_is)
7480  {
7481  // read first token
7482  get_token();
7483  }
7484 
7486  basic_json parse()
7487  {
7488  basic_json result = parse_internal(true);
7489 
7490  expect(lexer::token_type::end_of_input);
7491 
7492  // return parser result and replace it with null in case the
7493  // top-level value was discarded by the callback function
7494  return result.is_discarded() ? basic_json() : result;
7495  }
7496 
7497  private:
7499  basic_json parse_internal(bool keep)
7500  {
7501  auto result = basic_json(value_t::discarded);
7502 
7503  switch (last_token)
7504  {
7505  case lexer::token_type::begin_object:
7506  {
7507  if (keep and (not callback or (keep = callback(depth++, parse_event_t::object_start, result))))
7508  {
7509  // explicitly set result to object to cope with {}
7510  result.m_type = value_t::object;
7511  result.m_value = json_value(value_t::object);
7512  }
7513 
7514  // read next token
7515  get_token();
7516 
7517  // closing } -> we are done
7518  if (last_token == lexer::token_type::end_object)
7519  {
7520  get_token();
7521  if (keep and callback and not callback(--depth, parse_event_t::object_end, result))
7522  {
7523  result = basic_json(value_t::discarded);
7524  }
7525  return result;
7526  }
7527 
7528  // no comma is expected here
7529  unexpect(lexer::token_type::value_separator);
7530 
7531  // otherwise: parse key-value pairs
7532  do
7533  {
7534  // ugly, but could be fixed with loop reorganization
7535  if (last_token == lexer::token_type::value_separator)
7536  {
7537  get_token();
7538  }
7539 
7540  // store key
7541  expect(lexer::token_type::value_string);
7542  const auto key = m_lexer.get_string();
7543 
7544  bool keep_tag = false;
7545  if (keep)
7546  {
7547  if (callback)
7548  {
7549  basic_json k(key);
7550  keep_tag = callback(depth, parse_event_t::key, k);
7551  }
7552  else
7553  {
7554  keep_tag = true;
7555  }
7556  }
7557 
7558  // parse separator (:)
7559  get_token();
7560  expect(lexer::token_type::name_separator);
7561 
7562  // parse and add value
7563  get_token();
7564  auto value = parse_internal(keep);
7565  if (keep and keep_tag and not value.is_discarded())
7566  {
7567  result[key] = std::move(value);
7568  }
7569  }
7570  while (last_token == lexer::token_type::value_separator);
7571 
7572  // closing }
7573  expect(lexer::token_type::end_object);
7574  get_token();
7575  if (keep and callback and not callback(--depth, parse_event_t::object_end, result))
7576  {
7577  result = basic_json(value_t::discarded);
7578  }
7579 
7580  return result;
7581  }
7582 
7583  case lexer::token_type::begin_array:
7584  {
7585  if (keep and (not callback or (keep = callback(depth++, parse_event_t::array_start, result))))
7586  {
7587  // explicitly set result to object to cope with []
7588  result.m_type = value_t::array;
7589  result.m_value = json_value(value_t::array);
7590  }
7591 
7592  // read next token
7593  get_token();
7594 
7595  // closing ] -> we are done
7596  if (last_token == lexer::token_type::end_array)
7597  {
7598  get_token();
7599  if (callback and not callback(--depth, parse_event_t::array_end, result))
7600  {
7601  result = basic_json(value_t::discarded);
7602  }
7603  return result;
7604  }
7605 
7606  // no comma is expected here
7607  unexpect(lexer::token_type::value_separator);
7608 
7609  // otherwise: parse values
7610  do
7611  {
7612  // ugly, but could be fixed with loop reorganization
7613  if (last_token == lexer::token_type::value_separator)
7614  {
7615  get_token();
7616  }
7617 
7618  // parse value
7619  auto value = parse_internal(keep);
7620  if (keep and not value.is_discarded())
7621  {
7622  result.push_back(std::move(value));
7623  }
7624  }
7625  while (last_token == lexer::token_type::value_separator);
7626 
7627  // closing ]
7628  expect(lexer::token_type::end_array);
7629  get_token();
7630  if (keep and callback and not callback(--depth, parse_event_t::array_end, result))
7631  {
7632  result = basic_json(value_t::discarded);
7633  }
7634 
7635  return result;
7636  }
7637 
7638  case lexer::token_type::literal_null:
7639  {
7640  get_token();
7641  result.m_type = value_t::null;
7642  break;
7643  }
7644 
7645  case lexer::token_type::value_string:
7646  {
7647  const auto s = m_lexer.get_string();
7648  get_token();
7649  result = basic_json(s);
7650  break;
7651  }
7652 
7653  case lexer::token_type::literal_true:
7654  {
7655  get_token();
7656  result.m_type = value_t::boolean;
7657  result.m_value = true;
7658  break;
7659  }
7660 
7661  case lexer::token_type::literal_false:
7662  {
7663  get_token();
7664  result.m_type = value_t::boolean;
7665  result.m_value = false;
7666  break;
7667  }
7668 
7669  case lexer::token_type::value_number:
7670  {
7671  auto float_val = m_lexer.get_number();
7672 
7673  // NAN is returned if token could not be translated
7674  // completely
7675  if (std::isnan(float_val))
7676  {
7677  throw std::invalid_argument(std::string("parse error - ") +
7678  m_lexer.get_token() + " is not a number");
7679  }
7680 
7681  get_token();
7682 
7683  // check if conversion loses precision
7684  const auto int_val = static_cast<number_integer_t>(float_val);
7685  if (approx(float_val, static_cast<long double>(int_val)))
7686  {
7687  // we would not lose precision -> return int
7688  result.m_type = value_t::number_integer;
7689  result.m_value = int_val;
7690  }
7691  else
7692  {
7693  // we would lose precision -> return float
7694  result.m_type = value_t::number_float;
7695  result.m_value = static_cast<number_float_t>(float_val);
7696  }
7697  break;
7698  }
7699 
7700  default:
7701  {
7702  // the last token was unexpected
7703  unexpect(last_token);
7704  }
7705  }
7706 
7707  if (keep and callback and not callback(depth, parse_event_t::value, result))
7708  {
7709  result = basic_json(value_t::discarded);
7710  }
7711  return result;
7712  }
7713 
7715  typename lexer::token_type get_token()
7716  {
7717  last_token = m_lexer.scan();
7718  return last_token;
7719  }
7720 
7721  void expect(typename lexer::token_type t) const
7722  {
7723  if (t != last_token)
7724  {
7725  std::string error_msg = "parse error - unexpected \'";
7726  error_msg += m_lexer.get_token();
7727  error_msg += "\' (" + lexer::token_type_name(last_token);
7728  error_msg += "); expected " + lexer::token_type_name(t);
7729  throw std::invalid_argument(error_msg);
7730  }
7731  }
7732 
7733  void unexpect(typename lexer::token_type t) const
7734  {
7735  if (t == last_token)
7736  {
7737  std::string error_msg = "parse error - unexpected \'";
7738  error_msg += m_lexer.get_token();
7739  error_msg += "\' (";
7740  error_msg += lexer::token_type_name(last_token) + ")";
7741  throw std::invalid_argument(error_msg);
7742  }
7743  }
7744 
7745  private:
7747  int depth = 0;
7749  parser_callback_t callback;
7751  typename lexer::token_type last_token = lexer::token_type::uninitialized;
7753  lexer m_lexer;
7754  };
7755 };
7756 
7757 
7759 // presets //
7761 
7771 }
7772 
7773 
7775 // nonmember functions //
7777 
7778 // specialization of std::swap, and std::hash
7779 namespace std
7780 {
7786 template <>
7787 inline void swap(nlohmann::json& j1,
7788  nlohmann::json& j2) noexcept(
7789  is_nothrow_move_constructible<nlohmann::json>::value and
7790  is_nothrow_move_assignable<nlohmann::json>::value
7791  )
7792 {
7793  j1.swap(j2);
7794 }
7795 
7797 template <>
7798 struct hash<nlohmann::json>
7799 {
7805  std::size_t operator()(const nlohmann::json& j) const
7806  {
7807  // a naive hashing via the string representation
7808  const auto& h = hash<nlohmann::json::string_t>();
7809  return h(j.dump());
7810  }
7811 };
7812 }
7813 
7826 inline nlohmann::json operator "" _json(const char* s, std::size_t)
7827 {
7828  return nlohmann::json::parse(reinterpret_cast<nlohmann::json::string_t::value_type*>
7829  (const_cast<char*>(s)));
7830 }
7831 
7832 #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:5758
iterator insert(const_iterator pos, basic_json &&val)
inserts element
Definition: json.hpp:4234
iterator operator++(int)
post-increment (it++)
Definition: json.hpp:5995
friend bool operator<=(const_reference lhs, const_reference rhs) noexcept
comparison: less than or equal
Definition: json.hpp:4783
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:6147
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:5460
static iteration_proxy< iterator > iterator_wrapper(reference cont)
wrapper to access iterator member functions in range-based for
Definition: json.hpp:3783
const_iterator & operator--()
pre-decrement (–it)
Definition: json.hpp:5703
friend std::istream & operator>>(std::istream &i, basic_json &j)
deserialize from stream
Definition: json.hpp:4996
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:5525
typename basic_json::value_type value_type
the type of the values when the iterator is dereferenced
Definition: json.hpp:5456
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:4309
iterator insert(const_iterator pos, size_type cnt, const basic_json &val)
inserts elements
Definition: json.hpp:4261
json_reverse_iterator operator--(int)
post-decrement (it–)
Definition: json.hpp:6119
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:4159
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:6003
friend bool operator!=(const_reference lhs, const_reference rhs) noexcept
comparison: not equal
Definition: json.hpp:4661
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:5668
difference_type operator-(const json_reverse_iterator &other) const
return difference
Definition: json.hpp:6155
basic_json<> json
default JSON class
Definition: json.hpp:7770
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:6094
json_reverse_iterator(const typename base_iterator::iterator_type &it)
create reverse iterator from iterator
Definition: json.hpp:6099
a class to store JSON values
Definition: json.hpp:187
json_reverse_iterator & operator--()
pre-decrement (–it)
Definition: json.hpp:6125
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:4640
void push_back(basic_json &&val)
add an object to an array
Definition: json.hpp:4075
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:6025
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:5954
reference operator+=(basic_json &&val)
add an object to an array
Definition: json.hpp:4100
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:5951
iterator & operator-=(difference_type i)
subtract from iterator
Definition: json.hpp:6032
static basic_json parse(std::istream &&i, parser_callback_t cb=nullptr)
deserialize from stream
Definition: json.hpp:4958
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:6054
reference value() const
return the value of an iterator
Definition: json.hpp:5927
static iteration_proxy< const_iterator > iterator_wrapper(const_reference cont)
wrapper to access iterator member functions in range-based for
Definition: json.hpp:3791
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:5520
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:5914
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:5983
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:5850
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:5462
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:4133
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:6039
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:4827
iterator & operator--()
pre-decrement (–it)
Definition: json.hpp:6018
friend bool operator<(const_reference lhs, const_reference rhs) noexcept
comparison: less than
Definition: json.hpp:4722
pointer operator->() const
dereference the iterator
Definition: json.hpp:5631
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:6096
size_type size() const noexcept
returns the number of elements
Definition: json.hpp:3892
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:6103
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:4882
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:6167
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:5458
void swap(array_t &other)
exchanges the values
Definition: json.hpp:4430
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:4182
reference operator[](difference_type n) const
access to successor
Definition: json.hpp:6060
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:5842
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:4494
reference value() const
return the value of an iterator
Definition: json.hpp:6066
const_iterator operator--(int)
post-decrement (it–)
Definition: json.hpp:5695
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:4009
pointer operator->()
dereference the iterator
Definition: json.hpp:5989
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:5804
iterator insert(const_iterator pos, std::initializer_list< basic_json > ilist)
inserts elements
Definition: json.hpp:4363
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:5810
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:5858
friend bool operator==(const_reference lhs, const_reference rhs) noexcept
comparison: equal
Definition: json.hpp:4573
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:3835
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:4400
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:6174
const_iterator(pointer object)
constructor for a given JSON instance
Definition: json.hpp:5470
friend bool operator<(const value_t lhs, const value_t rhs)
comparison operator for JSON types
Definition: json.hpp:4527
iterator(pointer object) noexcept
constructor for a given JSON instance
Definition: json.hpp:5962
bool operator<(const const_iterator &other) const
comparison: smaller
Definition: json.hpp:5764
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:4684
const_iterator & operator-=(difference_type i)
subtract from iterator
Definition: json.hpp:5836
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:4921
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:6106
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:5495
friend bool operator!=(std::nullptr_t, const_reference v) noexcept
comparison: not equal
Definition: json.hpp:4693
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:5792
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:5660
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:5966
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:4950
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:3952
void push_back(const basic_json &val)
add an object to an array
Definition: json.hpp:4110
bool operator==(const const_iterator &other) const
comparison: equal
Definition: json.hpp:5730
json_reverse_iterator & operator++()
pre-increment (++it)
Definition: json.hpp:6112
bool operator>(const const_iterator &other) const
comparison: greater than
Definition: json.hpp:5798
friend bool operator>(const_reference lhs, const_reference rhs) noexcept
comparison: greater than
Definition: json.hpp:4805
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:6132
a const random access iterator for the basic_json class
Definition: json.hpp:5449
a template for a reverse iterator class
Definition: json.hpp:232
void swap(object_t &other)
exchanges the values
Definition: json.hpp:4462
std::bidirectional_iterator_tag iterator_category
the category of the iterator
Definition: json.hpp:5464
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:4208
friend bool operator==(const_reference v, std::nullptr_t) noexcept
comparison: equal
Definition: json.hpp:4631
reference operator[](difference_type n) const
access to successor
Definition: json.hpp:6161
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:5880
reference operator*() const
return a reference to the value pointed to by the iterator
Definition: json.hpp:5597
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:4986
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:7805
friend std::ostream & operator<<(std::ostream &o, const basic_json &j)
serialize to stream
Definition: json.hpp:4864
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:5971
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:6010
json_reverse_iterator operator+(difference_type i) const
add to iterator
Definition: json.hpp:6139
parse_event_t
JSON callback events.
Definition: json.hpp:754
iterator operator-(difference_type i)
subtract from iterator
Definition: json.hpp:6047