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