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 
2571  template<typename ValueType, typename
2572  std::enable_if<
2573  not std::is_pointer<ValueType>::value
2574  , int>::type = 0>
2575  operator ValueType() const
2576  {
2577  // delegate the call to get<>() const
2578  return get<ValueType>();
2579  }
2580 
2582 
2583 
2585  // element access //
2587 
2590 
2613  {
2614  // at only works for arrays
2615  if (is_array())
2616  {
2617  return m_value.array->at(idx);
2618  }
2619  else
2620  {
2621  throw std::domain_error("cannot use at() with " + type_name());
2622  }
2623  }
2624 
2647  {
2648  // at only works for arrays
2649  if (is_array())
2650  {
2651  return m_value.array->at(idx);
2652  }
2653  else
2654  {
2655  throw std::domain_error("cannot use at() with " + type_name());
2656  }
2657  }
2658 
2684  reference at(const typename object_t::key_type& key)
2685  {
2686  // at only works for objects
2687  if (is_object())
2688  {
2689  return m_value.object->at(key);
2690  }
2691  else
2692  {
2693  throw std::domain_error("cannot use at() with " + type_name());
2694  }
2695  }
2696 
2722  const_reference at(const typename object_t::key_type& key) const
2723  {
2724  // at only works for objects
2725  if (is_object())
2726  {
2727  return m_value.object->at(key);
2728  }
2729  else
2730  {
2731  throw std::domain_error("cannot use at() with " + type_name());
2732  }
2733  }
2734 
2760  {
2761  // implicitly convert null to object
2762  if (is_null())
2763  {
2764  m_type = value_t::array;
2765  m_value.array = create<array_t>();
2766  }
2767 
2768  // [] only works for arrays
2769  if (is_array())
2770  {
2771  for (size_t i = m_value.array->size(); i <= idx; ++i)
2772  {
2773  m_value.array->push_back(basic_json());
2774  }
2775 
2776  return m_value.array->operator[](idx);
2777  }
2778  else
2779  {
2780  throw std::domain_error("cannot use operator[] with " + type_name());
2781  }
2782  }
2783 
2803  {
2804  // at only works for arrays
2805  if (is_array())
2806  {
2807  return m_value.array->operator[](idx);
2808  }
2809  else
2810  {
2811  throw std::domain_error("cannot use operator[] with " + type_name());
2812  }
2813  }
2814 
2841  reference operator[](const typename object_t::key_type& key)
2842  {
2843  // implicitly convert null to object
2844  if (is_null())
2845  {
2846  m_type = value_t::object;
2847  m_value.object = create<object_t>();
2848  }
2849 
2850  // [] only works for objects
2851  if (is_object())
2852  {
2853  return m_value.object->operator[](key);
2854  }
2855  else
2856  {
2857  throw std::domain_error("cannot use operator[] with " + type_name());
2858  }
2859  }
2860 
2889  template<typename T, std::size_t n>
2890  reference operator[](const T (&key)[n])
2891  {
2892  // implicitly convert null to object
2893  if (is_null())
2894  {
2895  m_type = value_t::object;
2896  m_value = value_t::object;
2897  }
2898 
2899  // at only works for objects
2900  if (is_object())
2901  {
2902  return m_value.object->operator[](key);
2903  }
2904  else
2905  {
2906  throw std::domain_error("cannot use operator[] with " + type_name());
2907  }
2908  }
2909 
2957  template <class ValueType, typename
2958  std::enable_if<
2959  std::is_convertible<basic_json_t, ValueType>::value
2960  , int>::type = 0>
2961  ValueType value(const typename object_t::key_type& key, ValueType default_value) const
2962  {
2963  // at only works for objects
2964  if (is_object())
2965  {
2966  // if key is found, return value and given default value otherwise
2967  const auto it = find(key);
2968  if (it != end())
2969  {
2970  return *it;
2971  }
2972  else
2973  {
2974  return default_value;
2975  }
2976  }
2977  else
2978  {
2979  throw std::domain_error("cannot use value() with " + type_name());
2980  }
2981  }
2982 
2987  string_t value(const typename object_t::key_type& key, const char* default_value) const
2988  {
2989  return value(key, string_t(default_value));
2990  }
2991 
3013  {
3014  return *begin();
3015  }
3016 
3021  {
3022  return *cbegin();
3023  }
3024 
3047  {
3048  auto tmp = end();
3049  --tmp;
3050  return *tmp;
3051  }
3052 
3057  {
3058  auto tmp = cend();
3059  --tmp;
3060  return *tmp;
3061  }
3062 
3105  template <class InteratorType, typename
3106  std::enable_if<
3107  std::is_same<InteratorType, typename basic_json_t::iterator>::value or
3108  std::is_same<InteratorType, typename basic_json_t::const_iterator>::value
3109  , int>::type
3110  = 0>
3111  InteratorType erase(InteratorType pos)
3112  {
3113  // make sure iterator fits the current value
3114  if (this != pos.m_object)
3115  {
3116  throw std::domain_error("iterator does not fit current value");
3117  }
3118 
3119  InteratorType result = end();
3120 
3121  switch (m_type)
3122  {
3123  case value_t::boolean:
3124  case value_t::number_float:
3126  case value_t::string:
3127  {
3128  if (not pos.m_it.primitive_iterator.is_begin())
3129  {
3130  throw std::out_of_range("iterator out of range");
3131  }
3132 
3133  if (is_string())
3134  {
3135  delete m_value.string;
3136  m_value.string = nullptr;
3137  }
3138 
3139  m_type = value_t::null;
3140  break;
3141  }
3142 
3143  case value_t::object:
3144  {
3145  result.m_it.object_iterator = m_value.object->erase(pos.m_it.object_iterator);
3146  break;
3147  }
3148 
3149  case value_t::array:
3150  {
3151  result.m_it.array_iterator = m_value.array->erase(pos.m_it.array_iterator);
3152  break;
3153  }
3154 
3155  default:
3156  {
3157  throw std::domain_error("cannot use erase() with " + type_name());
3158  }
3159  }
3160 
3161  return result;
3162  }
3163 
3206  template <class InteratorType, typename
3207  std::enable_if<
3208  std::is_same<InteratorType, typename basic_json_t::iterator>::value or
3209  std::is_same<InteratorType, typename basic_json_t::const_iterator>::value
3210  , int>::type
3211  = 0>
3212  InteratorType erase(InteratorType first, InteratorType last)
3213  {
3214  // make sure iterator fits the current value
3215  if (this != first.m_object or this != last.m_object)
3216  {
3217  throw std::domain_error("iterators do not fit current value");
3218  }
3219 
3220  InteratorType result = end();
3221 
3222  switch (m_type)
3223  {
3224  case value_t::boolean:
3225  case value_t::number_float:
3227  case value_t::string:
3228  {
3229  if (not first.m_it.primitive_iterator.is_begin() or not last.m_it.primitive_iterator.is_end())
3230  {
3231  throw std::out_of_range("iterators out of range");
3232  }
3233 
3234  if (is_string())
3235  {
3236  delete m_value.string;
3237  m_value.string = nullptr;
3238  }
3239 
3240  m_type = value_t::null;
3241  break;
3242  }
3243 
3244  case value_t::object:
3245  {
3246  result.m_it.object_iterator = m_value.object->erase(first.m_it.object_iterator,
3247  last.m_it.object_iterator);
3248  break;
3249  }
3250 
3251  case value_t::array:
3252  {
3253  result.m_it.array_iterator = m_value.array->erase(first.m_it.array_iterator,
3254  last.m_it.array_iterator);
3255  break;
3256  }
3257 
3258  default:
3259  {
3260  throw std::domain_error("cannot use erase with " + type_name());
3261  }
3262  }
3263 
3264  return result;
3265  }
3266 
3292  size_type erase(const typename object_t::key_type& key)
3293  {
3294  // this erase only works for objects
3295  if (is_object())
3296  {
3297  return m_value.object->erase(key);
3298  }
3299  else
3300  {
3301  throw std::domain_error("cannot use erase() with " + type_name());
3302  }
3303  }
3304 
3327  void erase(const size_type idx)
3328  {
3329  // this erase only works for arrays
3330  if (is_array())
3331  {
3332  if (idx >= size())
3333  {
3334  throw std::out_of_range("index out of range");
3335  }
3336 
3337  m_value.array->erase(m_value.array->begin() + static_cast<difference_type>(idx));
3338  }
3339  else
3340  {
3341  throw std::domain_error("cannot use erase() with " + type_name());
3342  }
3343  }
3344 
3362  iterator find(typename object_t::key_type key)
3363  {
3364  auto result = end();
3365 
3366  if (is_object())
3367  {
3368  result.m_it.object_iterator = m_value.object->find(key);
3369  }
3370 
3371  return result;
3372  }
3373 
3378  const_iterator find(typename object_t::key_type key) const
3379  {
3380  auto result = cend();
3381 
3382  if (is_object())
3383  {
3384  result.m_it.object_iterator = m_value.object->find(key);
3385  }
3386 
3387  return result;
3388  }
3389 
3408  size_type count(typename object_t::key_type key) const
3409  {
3410  // return 0 for all nonobject types
3411  return is_object() ? m_value.object->count(key) : 0;
3412  }
3413 
3415 
3416 
3418  // iterators //
3420 
3423 
3443  {
3444  iterator result(this);
3445  result.set_begin();
3446  return result;
3447  }
3448 
3453  {
3454  return cbegin();
3455  }
3456 
3477  {
3478  const_iterator result(this);
3479  result.set_begin();
3480  return result;
3481  }
3482 
3502  {
3503  iterator result(this);
3504  result.set_end();
3505  return result;
3506  }
3507 
3512  {
3513  return cend();
3514  }
3515 
3536  {
3537  const_iterator result(this);
3538  result.set_end();
3539  return result;
3540  }
3541 
3560  {
3561  return reverse_iterator(end());
3562  }
3563 
3568  {
3569  return crbegin();
3570  }
3571 
3591  {
3592  return reverse_iterator(begin());
3593  }
3594 
3599  {
3600  return crend();
3601  }
3602 
3622  {
3623  return const_reverse_iterator(cend());
3624  }
3625 
3645  {
3646  return const_reverse_iterator(cbegin());
3647  }
3648 
3650 
3651 
3653  // capacity //
3655 
3658 
3688  bool empty() const noexcept
3689  {
3690  switch (m_type)
3691  {
3692  case value_t::null:
3693  {
3694  // null values are empty
3695  return true;
3696  }
3697 
3698  case value_t::array:
3699  {
3700  return m_value.array->empty();
3701  }
3702 
3703  case value_t::object:
3704  {
3705  return m_value.object->empty();
3706  }
3707 
3708  default:
3709  {
3710  // all other types are nonempty
3711  return false;
3712  }
3713  }
3714  }
3715 
3745  size_type size() const noexcept
3746  {
3747  switch (m_type)
3748  {
3749  case value_t::null:
3750  {
3751  // null values are empty
3752  return 0;
3753  }
3754 
3755  case value_t::array:
3756  {
3757  return m_value.array->size();
3758  }
3759 
3760  case value_t::object:
3761  {
3762  return m_value.object->size();
3763  }
3764 
3765  default:
3766  {
3767  // all other types have size 1
3768  return 1;
3769  }
3770  }
3771  }
3772 
3805  size_type max_size() const noexcept
3806  {
3807  switch (m_type)
3808  {
3809  case value_t::array:
3810  {
3811  return m_value.array->max_size();
3812  }
3813 
3814  case value_t::object:
3815  {
3816  return m_value.object->max_size();
3817  }
3818 
3819  default:
3820  {
3821  // all other types have max_size() == size()
3822  return size();
3823  }
3824  }
3825  }
3826 
3828 
3829 
3831  // modifiers //
3833 
3836 
3862  void clear() noexcept
3863  {
3864  switch (m_type)
3865  {
3867  {
3868  m_value.number_integer = 0;
3869  break;
3870  }
3871 
3872  case value_t::number_float:
3873  {
3874  m_value.number_float = 0.0;
3875  break;
3876  }
3877 
3878  case value_t::boolean:
3879  {
3880  m_value.boolean = false;
3881  break;
3882  }
3883 
3884  case value_t::string:
3885  {
3886  m_value.string->clear();
3887  break;
3888  }
3889 
3890  case value_t::array:
3891  {
3892  m_value.array->clear();
3893  break;
3894  }
3895 
3896  case value_t::object:
3897  {
3898  m_value.object->clear();
3899  break;
3900  }
3901 
3902  default:
3903  {
3904  break;
3905  }
3906  }
3907  }
3908 
3928  void push_back(basic_json&& val)
3929  {
3930  // push_back only works for null objects or arrays
3931  if (not(is_null() or is_array()))
3932  {
3933  throw std::domain_error("cannot use push_back() with " + type_name());
3934  }
3935 
3936  // transform null object into an array
3937  if (is_null())
3938  {
3939  m_type = value_t::array;
3940  m_value = value_t::array;
3941  }
3942 
3943  // add element to array (move semantics)
3944  m_value.array->push_back(std::move(val));
3945  // invalidate object
3946  val.m_type = value_t::null;
3947  }
3948 
3953  reference operator+=(basic_json&& val)
3954  {
3955  push_back(std::move(val));
3956  return *this;
3957  }
3958 
3963  void push_back(const basic_json& val)
3964  {
3965  // push_back only works for null objects or arrays
3966  if (not(is_null() or is_array()))
3967  {
3968  throw std::domain_error("cannot use push_back() with " + type_name());
3969  }
3970 
3971  // transform null object into an array
3972  if (is_null())
3973  {
3974  m_type = value_t::array;
3975  m_value = value_t::array;
3976  }
3977 
3978  // add element to array
3979  m_value.array->push_back(val);
3980  }
3981 
3986  reference operator+=(const basic_json& val)
3987  {
3988  push_back(val);
3989  return *this;
3990  }
3991 
4012  void push_back(const typename object_t::value_type& val)
4013  {
4014  // push_back only works for null objects or objects
4015  if (not(is_null() or is_object()))
4016  {
4017  throw std::domain_error("cannot use push_back() with " + type_name());
4018  }
4019 
4020  // transform null object into an object
4021  if (is_null())
4022  {
4023  m_type = value_t::object;
4024  m_value = value_t::object;
4025  }
4026 
4027  // add element to array
4028  m_value.object->insert(val);
4029  }
4030 
4035  reference operator+=(const typename object_t::value_type& val)
4036  {
4037  push_back(val);
4038  return operator[](val.first);
4039  }
4040 
4061  iterator insert(const_iterator pos, const basic_json& val)
4062  {
4063  // insert only works for arrays
4064  if (is_array())
4065  {
4066  // check if iterator pos fits to this JSON value
4067  if (pos.m_object != this)
4068  {
4069  throw std::domain_error("iterator does not fit current value");
4070  }
4071 
4072  // insert to array and return iterator
4073  iterator result(this);
4074  result.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator, val);
4075  return result;
4076  }
4077  else
4078  {
4079  throw std::domain_error("cannot use insert() with " + type_name());
4080  }
4081  }
4082 
4087  iterator insert(const_iterator pos, basic_json&& val)
4088  {
4089  return insert(pos, val);
4090  }
4091 
4114  iterator insert(const_iterator pos, size_type cnt, const basic_json& val)
4115  {
4116  // insert only works for arrays
4117  if (is_array())
4118  {
4119  // check if iterator pos fits to this JSON value
4120  if (pos.m_object != this)
4121  {
4122  throw std::domain_error("iterator does not fit current value");
4123  }
4124 
4125  // insert to array and return iterator
4126  iterator result(this);
4127  result.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator, cnt, val);
4128  return result;
4129  }
4130  else
4131  {
4132  throw std::domain_error("cannot use insert() with " + type_name());
4133  }
4134  }
4135 
4163  {
4164  // insert only works for arrays
4165  if (not is_array())
4166  {
4167  throw std::domain_error("cannot use insert() with " + type_name());
4168  }
4169 
4170  // check if iterator pos fits to this JSON value
4171  if (pos.m_object != this)
4172  {
4173  throw std::domain_error("iterator does not fit current value");
4174  }
4175 
4176  if (first.m_object != last.m_object)
4177  {
4178  throw std::domain_error("iterators do not fit");
4179  }
4180 
4181  if (first.m_object == this or last.m_object == this)
4182  {
4183  throw std::domain_error("passed iterators may not belong to container");
4184  }
4185 
4186  // insert to array and return iterator
4187  iterator result(this);
4188  result.m_it.array_iterator = m_value.array->insert(
4189  pos.m_it.array_iterator,
4190  first.m_it.array_iterator,
4191  last.m_it.array_iterator);
4192  return result;
4193  }
4194 
4216  iterator insert(const_iterator pos, std::initializer_list<basic_json> ilist)
4217  {
4218  // insert only works for arrays
4219  if (not is_array())
4220  {
4221  throw std::domain_error("cannot use insert() with " + type_name());
4222  }
4223 
4224  // check if iterator pos fits to this JSON value
4225  if (pos.m_object != this)
4226  {
4227  throw std::domain_error("iterator does not fit current value");
4228  }
4229 
4230  // insert to array and return iterator
4231  iterator result(this);
4232  result.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator, ilist);
4233  return result;
4234  }
4235 
4253  void swap(reference other) noexcept (
4254  std::is_nothrow_move_constructible<value_t>::value and
4255  std::is_nothrow_move_assignable<value_t>::value and
4256  std::is_nothrow_move_constructible<json_value>::value and
4257  std::is_nothrow_move_assignable<json_value>::value
4258  )
4259  {
4260  std::swap(m_type, other.m_type);
4261  std::swap(m_value, other.m_value);
4262  }
4263 
4283  void swap(array_t& other)
4284  {
4285  // swap only works for arrays
4286  if (is_array())
4287  {
4288  std::swap(*(m_value.array), other);
4289  }
4290  else
4291  {
4292  throw std::domain_error("cannot use swap() with " + type_name());
4293  }
4294  }
4295 
4315  void swap(object_t& other)
4316  {
4317  // swap only works for objects
4318  if (is_object())
4319  {
4320  std::swap(*(m_value.object), other);
4321  }
4322  else
4323  {
4324  throw std::domain_error("cannot use swap() with " + type_name());
4325  }
4326  }
4327 
4347  void swap(string_t& other)
4348  {
4349  // swap only works for strings
4350  if (is_string())
4351  {
4352  std::swap(*(m_value.string), other);
4353  }
4354  else
4355  {
4356  throw std::domain_error("cannot use swap() with " + type_name());
4357  }
4358  }
4359 
4361 
4362 
4364  // lexicographical comparison operators //
4366 
4369 
4370  private:
4380  friend bool operator<(const value_t lhs, const value_t rhs)
4381  {
4382  static constexpr std::array<uint8_t, 7> order = {{
4383  0, // null
4384  3, // object
4385  4, // array
4386  5, // string
4387  1, // boolean
4388  2, // integer
4389  2 // float
4390  }
4391  };
4392 
4393  // discarded values are not comparable
4394  if (lhs == value_t::discarded or rhs == value_t::discarded)
4395  {
4396  return false;
4397  }
4398 
4399  return order[static_cast<std::size_t>(lhs)] < order[static_cast<std::size_t>(rhs)];
4400  }
4401 
4402  public:
4426  friend bool operator==(const_reference lhs, const_reference rhs) noexcept
4427  {
4428  const auto lhs_type = lhs.type();
4429  const auto rhs_type = rhs.type();
4430 
4431  if (lhs_type == rhs_type)
4432  {
4433  switch (lhs_type)
4434  {
4435  case value_t::array:
4436  return *lhs.m_value.array == *rhs.m_value.array;
4437  case value_t::object:
4438  return *lhs.m_value.object == *rhs.m_value.object;
4439  case value_t::null:
4440  return true;
4441  case value_t::string:
4442  return *lhs.m_value.string == *rhs.m_value.string;
4443  case value_t::boolean:
4444  return lhs.m_value.boolean == rhs.m_value.boolean;
4446  return lhs.m_value.number_integer == rhs.m_value.number_integer;
4447  case value_t::number_float:
4448  return approx(lhs.m_value.number_float, rhs.m_value.number_float);
4449  default:
4450  return false;
4451  }
4452  }
4453  else if (lhs_type == value_t::number_integer and rhs_type == value_t::number_float)
4454  {
4455  return approx(static_cast<number_float_t>(lhs.m_value.number_integer),
4456  rhs.m_value.number_float);
4457  }
4458  else if (lhs_type == value_t::number_float and rhs_type == value_t::number_integer)
4459  {
4460  return approx(lhs.m_value.number_float,
4461  static_cast<number_float_t>(rhs.m_value.number_integer));
4462  }
4463  return false;
4464  }
4465 
4484  friend bool operator==(const_reference v, std::nullptr_t) noexcept
4485  {
4486  return v.is_null();
4487  }
4488 
4493  friend bool operator==(std::nullptr_t, const_reference v) noexcept
4494  {
4495  return v.is_null();
4496  }
4497 
4514  friend bool operator!=(const_reference lhs, const_reference rhs) noexcept
4515  {
4516  return not (lhs == rhs);
4517  }
4518 
4537  friend bool operator!=(const_reference v, std::nullptr_t) noexcept
4538  {
4539  return not v.is_null();
4540  }
4541 
4546  friend bool operator!=(std::nullptr_t, const_reference v) noexcept
4547  {
4548  return not v.is_null();
4549  }
4550 
4575  friend bool operator<(const_reference lhs, const_reference rhs) noexcept
4576  {
4577  const auto lhs_type = lhs.type();
4578  const auto rhs_type = rhs.type();
4579 
4580  if (lhs_type == rhs_type)
4581  {
4582  switch (lhs_type)
4583  {
4584  case value_t::array:
4585  return *lhs.m_value.array < *rhs.m_value.array;
4586  case value_t::object:
4587  return *lhs.m_value.object < *rhs.m_value.object;
4588  case value_t::null:
4589  return false;
4590  case value_t::string:
4591  return *lhs.m_value.string < *rhs.m_value.string;
4592  case value_t::boolean:
4593  return lhs.m_value.boolean < rhs.m_value.boolean;
4595  return lhs.m_value.number_integer < rhs.m_value.number_integer;
4596  case value_t::number_float:
4597  return lhs.m_value.number_float < rhs.m_value.number_float;
4598  default:
4599  return false;
4600  }
4601  }
4602  else if (lhs_type == value_t::number_integer and rhs_type == value_t::number_float)
4603  {
4604  return static_cast<number_float_t>(lhs.m_value.number_integer) <
4605  rhs.m_value.number_float;
4606  }
4607  else if (lhs_type == value_t::number_float and rhs_type == value_t::number_integer)
4608  {
4609  return lhs.m_value.number_float <
4610  static_cast<number_float_t>(rhs.m_value.number_integer);
4611  }
4612 
4613  // We only reach this line if we cannot compare values. In that case,
4614  // we compare types. Note we have to call the operator explicitly,
4615  // because MSVC has problems otherwise.
4616  return operator<(lhs_type, rhs_type);
4617  }
4618 
4636  friend bool operator<=(const_reference lhs, const_reference rhs) noexcept
4637  {
4638  return not (rhs < lhs);
4639  }
4640 
4658  friend bool operator>(const_reference lhs, const_reference rhs) noexcept
4659  {
4660  return not (lhs <= rhs);
4661  }
4662 
4680  friend bool operator>=(const_reference lhs, const_reference rhs) noexcept
4681  {
4682  return not (lhs < rhs);
4683  }
4684 
4686 
4687 
4689  // serialization //
4691 
4694 
4717  friend std::ostream& operator<<(std::ostream& o, const basic_json& j)
4718  {
4719  // read width member and use it as indentation parameter if nonzero
4720  const bool pretty_print = (o.width() > 0);
4721  const auto indentation = (pretty_print ? o.width() : 0);
4722 
4723  // reset width to 0 for subsequent calls to this stream
4724  o.width(0);
4725 
4726  // do the actual serialization
4727  j.dump(o, pretty_print, static_cast<unsigned int>(indentation));
4728  return o;
4729  }
4730 
4735  friend std::ostream& operator>>(const basic_json& j, std::ostream& o)
4736  {
4737  return o << j;
4738  }
4739 
4741 
4742 
4744  // deserialization //
4746 
4749 
4774  static basic_json parse(const string_t& s, parser_callback_t cb = nullptr)
4775  {
4776  return parser(s, cb).parse();
4777  }
4778 
4803  static basic_json parse(std::istream& i, parser_callback_t cb = nullptr)
4804  {
4805  return parser(i, cb).parse();
4806  }
4807 
4811  static basic_json parse(std::istream&& i, parser_callback_t cb = nullptr)
4812  {
4813  return parser(i, cb).parse();
4814  }
4815 
4839  friend std::istream& operator<<(basic_json& j, std::istream& i)
4840  {
4841  j = parser(i).parse();
4842  return i;
4843  }
4844 
4849  friend std::istream& operator>>(std::istream& i, basic_json& j)
4850  {
4851  j = parser(i).parse();
4852  return i;
4853  }
4854 
4856 
4857 
4858  private:
4860  // convenience functions //
4862 
4864  string_t type_name() const
4865  {
4866  switch (m_type)
4867  {
4868  case value_t::null:
4869  return "null";
4870  case value_t::object:
4871  return "object";
4872  case value_t::array:
4873  return "array";
4874  case value_t::string:
4875  return "string";
4876  case value_t::boolean:
4877  return "boolean";
4878  case value_t::discarded:
4879  return "discarded";
4880  default:
4881  return "number";
4882  }
4883  }
4884 
4893  static std::size_t extra_space(const string_t& s) noexcept
4894  {
4895  std::size_t result = 0;
4896 
4897  for (const auto& c : s)
4898  {
4899  switch (c)
4900  {
4901  case '"':
4902  case '\\':
4903  case '\b':
4904  case '\f':
4905  case '\n':
4906  case '\r':
4907  case '\t':
4908  {
4909  // from c (1 byte) to \x (2 bytes)
4910  result += 1;
4911  break;
4912  }
4913 
4914  default:
4915  {
4916  if (c >= 0x00 and c <= 0x1f)
4917  {
4918  // from c (1 byte) to \uxxxx (6 bytes)
4919  result += 5;
4920  }
4921  break;
4922  }
4923  }
4924  }
4925 
4926  return result;
4927  }
4928 
4942  static string_t escape_string(const string_t& s) noexcept
4943  {
4944  const auto space = extra_space(s);
4945  if (space == 0)
4946  {
4947  return s;
4948  }
4949 
4950  // create a result string of necessary size
4951  string_t result(s.size() + space, '\\');
4952  std::size_t pos = 0;
4953 
4954  for (const auto& c : s)
4955  {
4956  switch (c)
4957  {
4958  // quotation mark (0x22)
4959  case '"':
4960  {
4961  result[pos + 1] = '"';
4962  pos += 2;
4963  break;
4964  }
4965 
4966  // reverse solidus (0x5c)
4967  case '\\':
4968  {
4969  // nothing to change
4970  pos += 2;
4971  break;
4972  }
4973 
4974  // backspace (0x08)
4975  case '\b':
4976  {
4977  result[pos + 1] = 'b';
4978  pos += 2;
4979  break;
4980  }
4981 
4982  // formfeed (0x0c)
4983  case '\f':
4984  {
4985  result[pos + 1] = 'f';
4986  pos += 2;
4987  break;
4988  }
4989 
4990  // newline (0x0a)
4991  case '\n':
4992  {
4993  result[pos + 1] = 'n';
4994  pos += 2;
4995  break;
4996  }
4997 
4998  // carriage return (0x0d)
4999  case '\r':
5000  {
5001  result[pos + 1] = 'r';
5002  pos += 2;
5003  break;
5004  }
5005 
5006  // horizontal tab (0x09)
5007  case '\t':
5008  {
5009  result[pos + 1] = 't';
5010  pos += 2;
5011  break;
5012  }
5013 
5014  default:
5015  {
5016  if (c >= 0x00 and c <= 0x1f)
5017  {
5018  // convert a number 0..15 to its hex representation (0..f)
5019  auto hexify = [](const char v) -> char
5020  {
5021  return (v < 10) ? ('0' + v) : ('a' + v - 10);
5022  };
5023 
5024  // print character c as \uxxxx
5025  for (const char m :
5026  { 'u', '0', '0', hexify(c >> 4), hexify(c & 0x0f)
5027  })
5028  {
5029  result[++pos] = m;
5030  }
5031 
5032  ++pos;
5033  }
5034  else
5035  {
5036  // all other characters are added as-is
5037  result[pos++] = c;
5038  }
5039  break;
5040  }
5041  }
5042  }
5043 
5044  return result;
5045  }
5046 
5064  void dump(std::ostream& o,
5065  const bool pretty_print,
5066  const unsigned int indent_step,
5067  const unsigned int current_indent = 0) const
5068  {
5069  // variable to hold indentation for recursive calls
5070  unsigned int new_indent = current_indent;
5071 
5072  switch (m_type)
5073  {
5074  case value_t::object:
5075  {
5076  if (m_value.object->empty())
5077  {
5078  o << "{}";
5079  return;
5080  }
5081 
5082  o << "{";
5083 
5084  // increase indentation
5085  if (pretty_print)
5086  {
5087  new_indent += indent_step;
5088  o << "\n";
5089  }
5090 
5091  for (auto i = m_value.object->cbegin(); i != m_value.object->cend(); ++i)
5092  {
5093  if (i != m_value.object->cbegin())
5094  {
5095  o << (pretty_print ? ",\n" : ",");
5096  }
5097  o << string_t(new_indent, ' ') << "\""
5098  << escape_string(i->first) << "\":"
5099  << (pretty_print ? " " : "");
5100  i->second.dump(o, pretty_print, indent_step, new_indent);
5101  }
5102 
5103  // decrease indentation
5104  if (pretty_print)
5105  {
5106  new_indent -= indent_step;
5107  o << "\n";
5108  }
5109 
5110  o << string_t(new_indent, ' ') + "}";
5111  return;
5112  }
5113 
5114  case value_t::array:
5115  {
5116  if (m_value.array->empty())
5117  {
5118  o << "[]";
5119  return;
5120  }
5121 
5122  o << "[";
5123 
5124  // increase indentation
5125  if (pretty_print)
5126  {
5127  new_indent += indent_step;
5128  o << "\n";
5129  }
5130 
5131  for (auto i = m_value.array->cbegin(); i != m_value.array->cend(); ++i)
5132  {
5133  if (i != m_value.array->cbegin())
5134  {
5135  o << (pretty_print ? ",\n" : ",");
5136  }
5137  o << string_t(new_indent, ' ');
5138  i->dump(o, pretty_print, indent_step, new_indent);
5139  }
5140 
5141  // decrease indentation
5142  if (pretty_print)
5143  {
5144  new_indent -= indent_step;
5145  o << "\n";
5146  }
5147 
5148  o << string_t(new_indent, ' ') << "]";
5149  return;
5150  }
5151 
5152  case value_t::string:
5153  {
5154  o << string_t("\"") << escape_string(*m_value.string) << "\"";
5155  return;
5156  }
5157 
5158  case value_t::boolean:
5159  {
5160  o << (m_value.boolean ? "true" : "false");
5161  return;
5162  }
5163 
5165  {
5166  o << m_value.number_integer;
5167  return;
5168  }
5169 
5170  case value_t::number_float:
5171  {
5172  // 15 digits of precision allows round-trip IEEE 754
5173  // string->double->string; to be safe, we read this value from
5174  // std::numeric_limits<number_float_t>::digits10
5175  o << std::setprecision(std::numeric_limits<number_float_t>::digits10) << m_value.number_float;
5176  return;
5177  }
5178 
5179  case value_t::discarded:
5180  {
5181  o << "<discarded>";
5182  return;
5183  }
5184 
5185  case value_t::null:
5186  {
5187  o << "null";
5188  return;
5189  }
5190  }
5191  }
5192 
5193  private:
5195  // member variables //
5197 
5199  value_t m_type = value_t::null;
5200 
5202  json_value m_value = {};
5203 
5204 
5205  private:
5207  // iterators //
5209 
5219  class primitive_iterator_t
5220  {
5221  public:
5223  void set_begin()
5224  {
5225  m_it = begin_value;
5226  }
5227 
5229  void set_end()
5230  {
5231  m_it = end_value;
5232  }
5233 
5235  bool is_begin() const
5236  {
5237  return (m_it == begin_value);
5238  }
5239 
5241  bool is_end() const
5242  {
5243  return (m_it == end_value);
5244  }
5245 
5247  operator difference_type& ()
5248  {
5249  return m_it;
5250  }
5251 
5253  operator difference_type () const
5254  {
5255  return m_it;
5256  }
5257 
5258  private:
5259  static constexpr difference_type begin_value = 0;
5260  static constexpr difference_type end_value = begin_value + 1;
5261 
5263  difference_type m_it = std::numeric_limits<std::ptrdiff_t>::denorm_min();
5264  };
5265 
5273  struct internal_iterator
5274  {
5276  typename object_t::iterator object_iterator;
5278  typename array_t::iterator array_iterator;
5280  primitive_iterator_t primitive_iterator;
5281 
5283  internal_iterator()
5284  : object_iterator(), array_iterator(), primitive_iterator()
5285  {}
5286  };
5287 
5288  public:
5302  class const_iterator : public std::iterator<std::random_access_iterator_tag, const basic_json>
5303  {
5305  friend class basic_json;
5306 
5307  public:
5317  using iterator_category = std::bidirectional_iterator_tag;
5318 
5320  const_iterator() = default;
5321 
5323  const_iterator(pointer object) : m_object(object)
5324  {
5325  switch (m_object->m_type)
5326  {
5328  {
5329  m_it.object_iterator = typename object_t::iterator();
5330  break;
5331  }
5332 
5334  {
5335  m_it.array_iterator = typename array_t::iterator();
5336  break;
5337  }
5338 
5339  default:
5340  {
5341  m_it.primitive_iterator = primitive_iterator_t();
5342  break;
5343  }
5344  }
5345  }
5346 
5348  const_iterator(const iterator& other) : m_object(other.m_object)
5349  {
5350  switch (m_object->m_type)
5351  {
5353  {
5354  m_it.object_iterator = other.m_it.object_iterator;
5355  break;
5356  }
5357 
5359  {
5360  m_it.array_iterator = other.m_it.array_iterator;
5361  break;
5362  }
5363 
5364  default:
5365  {
5366  m_it.primitive_iterator = other.m_it.primitive_iterator;
5367  break;
5368  }
5369  }
5370  }
5371 
5373  const_iterator(const const_iterator& other) noexcept
5374  : m_object(other.m_object), m_it(other.m_it)
5375  {}
5376 
5379  std::is_nothrow_move_constructible<pointer>::value and
5380  std::is_nothrow_move_assignable<pointer>::value and
5381  std::is_nothrow_move_constructible<internal_iterator>::value and
5382  std::is_nothrow_move_assignable<internal_iterator>::value
5383  )
5384  {
5385  std::swap(m_object, other.m_object);
5386  std::swap(m_it, other.m_it);
5387  return *this;
5388  }
5389 
5390  private:
5392  void set_begin()
5393  {
5394  switch (m_object->m_type)
5395  {
5397  {
5398  m_it.object_iterator = m_object->m_value.object->begin();
5399  break;
5400  }
5401 
5403  {
5404  m_it.array_iterator = m_object->m_value.array->begin();
5405  break;
5406  }
5407 
5409  {
5410  // set to end so begin()==end() is true: null is empty
5411  m_it.primitive_iterator.set_end();
5412  break;
5413  }
5414 
5415  default:
5416  {
5417  m_it.primitive_iterator.set_begin();
5418  break;
5419  }
5420  }
5421  }
5422 
5424  void set_end()
5425  {
5426  switch (m_object->m_type)
5427  {
5429  {
5430  m_it.object_iterator = m_object->m_value.object->end();
5431  break;
5432  }
5433 
5435  {
5436  m_it.array_iterator = m_object->m_value.array->end();
5437  break;
5438  }
5439 
5440  default:
5441  {
5442  m_it.primitive_iterator.set_end();
5443  break;
5444  }
5445  }
5446  }
5447 
5448  public:
5451  {
5452  switch (m_object->m_type)
5453  {
5455  {
5456  return m_it.object_iterator->second;
5457  }
5458 
5460  {
5461  return *m_it.array_iterator;
5462  }
5463 
5465  {
5466  throw std::out_of_range("cannot get value");
5467  }
5468 
5469  default:
5470  {
5471  if (m_it.primitive_iterator.is_begin())
5472  {
5473  return *m_object;
5474  }
5475  else
5476  {
5477  throw std::out_of_range("cannot get value");
5478  }
5479  }
5480  }
5481  }
5482 
5485  {
5486  switch (m_object->m_type)
5487  {
5489  {
5490  return &(m_it.object_iterator->second);
5491  }
5492 
5494  {
5495  return &*m_it.array_iterator;
5496  }
5497 
5498  default:
5499  {
5500  if (m_it.primitive_iterator.is_begin())
5501  {
5502  return m_object;
5503  }
5504  else
5505  {
5506  throw std::out_of_range("cannot get value");
5507  }
5508  }
5509  }
5510  }
5511 
5514  {
5515  auto result = *this;
5516  ++(*this);
5517  return result;
5518  }
5519 
5522  {
5523  switch (m_object->m_type)
5524  {
5526  {
5527  ++m_it.object_iterator;
5528  break;
5529  }
5530 
5532  {
5533  ++m_it.array_iterator;
5534  break;
5535  }
5536 
5537  default:
5538  {
5539  ++m_it.primitive_iterator;
5540  break;
5541  }
5542  }
5543 
5544  return *this;
5545  }
5546 
5549  {
5550  auto result = *this;
5551  --(*this);
5552  return result;
5553  }
5554 
5557  {
5558  switch (m_object->m_type)
5559  {
5561  {
5562  --m_it.object_iterator;
5563  break;
5564  }
5565 
5567  {
5568  --m_it.array_iterator;
5569  break;
5570  }
5571 
5572  default:
5573  {
5574  --m_it.primitive_iterator;
5575  break;
5576  }
5577  }
5578 
5579  return *this;
5580  }
5581 
5583  bool operator==(const const_iterator& other) const
5584  {
5585  // if objects are not the same, the comparison is undefined
5586  if (m_object != other.m_object)
5587  {
5588  throw std::domain_error("cannot compare iterators of different containers");
5589  }
5590 
5591  switch (m_object->m_type)
5592  {
5594  {
5595  return (m_it.object_iterator == other.m_it.object_iterator);
5596  }
5597 
5599  {
5600  return (m_it.array_iterator == other.m_it.array_iterator);
5601  }
5602 
5603  default:
5604  {
5605  return (m_it.primitive_iterator == other.m_it.primitive_iterator);
5606  }
5607  }
5608  }
5609 
5611  bool operator!=(const const_iterator& other) const
5612  {
5613  return not operator==(other);
5614  }
5615 
5617  bool operator<(const const_iterator& other) const
5618  {
5619  // if objects are not the same, the comparison is undefined
5620  if (m_object != other.m_object)
5621  {
5622  throw std::domain_error("cannot compare iterators of different containers");
5623  }
5624 
5625  switch (m_object->m_type)
5626  {
5628  {
5629  throw std::domain_error("cannot use operator< for object iterators");
5630  }
5631 
5633  {
5634  return (m_it.array_iterator < other.m_it.array_iterator);
5635  }
5636 
5637  default:
5638  {
5639  return (m_it.primitive_iterator < other.m_it.primitive_iterator);
5640  }
5641  }
5642  }
5643 
5645  bool operator<=(const const_iterator& other) const
5646  {
5647  return not other.operator < (*this);
5648  }
5649 
5651  bool operator>(const const_iterator& other) const
5652  {
5653  return not operator<=(other);
5654  }
5655 
5657  bool operator>=(const const_iterator& other) const
5658  {
5659  return not operator<(other);
5660  }
5661 
5664  {
5665  switch (m_object->m_type)
5666  {
5668  {
5669  throw std::domain_error("cannot use operator+= for object iterators");
5670  }
5671 
5673  {
5674  m_it.array_iterator += i;
5675  break;
5676  }
5677 
5678  default:
5679  {
5680  m_it.primitive_iterator += i;
5681  break;
5682  }
5683  }
5684 
5685  return *this;
5686  }
5687 
5690  {
5691  return operator+=(-i);
5692  }
5693 
5696  {
5697  auto result = *this;
5698  result += i;
5699  return result;
5700  }
5701 
5704  {
5705  auto result = *this;
5706  result -= i;
5707  return result;
5708  }
5709 
5712  {
5713  switch (m_object->m_type)
5714  {
5716  {
5717  throw std::domain_error("cannot use operator- for object iterators");
5718  }
5719 
5721  {
5722  return m_it.array_iterator - other.m_it.array_iterator;
5723  }
5724 
5725  default:
5726  {
5727  return m_it.primitive_iterator - other.m_it.primitive_iterator;
5728  }
5729  }
5730  }
5731 
5734  {
5735  switch (m_object->m_type)
5736  {
5738  {
5739  throw std::domain_error("cannot use operator[] for object iterators");
5740  }
5741 
5743  {
5744  return *(m_it.array_iterator + n);
5745  }
5746 
5748  {
5749  throw std::out_of_range("cannot get value");
5750  }
5751 
5752  default:
5753  {
5754  if (m_it.primitive_iterator == -n)
5755  {
5756  return *m_object;
5757  }
5758  else
5759  {
5760  throw std::out_of_range("cannot get value");
5761  }
5762  }
5763  }
5764  }
5765 
5767  typename object_t::key_type key() const
5768  {
5769  if (m_object->is_object())
5770  {
5771  return m_it.object_iterator->first;
5772  }
5773  else
5774  {
5775  throw std::domain_error("cannot use key() for non-object iterators");
5776  }
5777  }
5778 
5781  {
5782  return operator*();
5783  }
5784 
5785  private:
5787  pointer m_object = nullptr;
5789  internal_iterator m_it = internal_iterator();
5790  };
5791 
5804  class iterator : public const_iterator
5805  {
5806  public:
5808  using pointer = typename basic_json::pointer;
5810 
5812  iterator() = default;
5813 
5815  iterator(pointer object) noexcept : base_iterator(object)
5816  {}
5817 
5819  iterator(const iterator& other) noexcept
5820  : base_iterator(other)
5821  {}
5822 
5824  iterator& operator=(iterator other) noexcept(
5825  std::is_nothrow_move_constructible<pointer>::value and
5826  std::is_nothrow_move_assignable<pointer>::value and
5827  std::is_nothrow_move_constructible<internal_iterator>::value and
5828  std::is_nothrow_move_assignable<internal_iterator>::value
5829  )
5830  {
5831  base_iterator::operator=(other);
5832  return *this;
5833  }
5834 
5837  {
5838  return const_cast<reference>(base_iterator::operator*());
5839  }
5840 
5843  {
5844  return const_cast<pointer>(base_iterator::operator->());
5845  }
5846 
5849  {
5850  iterator result = *this;
5852  return result;
5853  }
5854 
5857  {
5859  return *this;
5860  }
5861 
5864  {
5865  iterator result = *this;
5867  return result;
5868  }
5869 
5872  {
5874  return *this;
5875  }
5876 
5879  {
5881  return *this;
5882  }
5883 
5886  {
5888  return *this;
5889  }
5890 
5893  {
5894  auto result = *this;
5895  result += i;
5896  return result;
5897  }
5898 
5901  {
5902  auto result = *this;
5903  result -= i;
5904  return result;
5905  }
5906 
5907  difference_type operator-(const iterator& other) const
5908  {
5909  return base_iterator::operator-(other);
5910  }
5911 
5914  {
5915  return const_cast<reference>(base_iterator::operator[](n));
5916  }
5917 
5920  {
5921  return const_cast<reference>(base_iterator::value());
5922  }
5923  };
5924 
5942  template<typename Base>
5943  class json_reverse_iterator : public std::reverse_iterator<Base>
5944  {
5945  public:
5947  using base_iterator = std::reverse_iterator<Base>;
5949  using reference = typename Base::reference;
5950 
5952  json_reverse_iterator(const typename base_iterator::iterator_type& it)
5953  : base_iterator(it) {}
5954 
5957 
5960  {
5961  return base_iterator::operator++(1);
5962  }
5963 
5966  {
5967  base_iterator::operator++();
5968  return *this;
5969  }
5970 
5973  {
5974  return base_iterator::operator--(1);
5975  }
5976 
5979  {
5980  base_iterator::operator--();
5981  return *this;
5982  }
5983 
5986  {
5987  base_iterator::operator+=(i);
5988  return *this;
5989  }
5990 
5993  {
5994  auto result = *this;
5995  result += i;
5996  return result;
5997  }
5998 
6001  {
6002  auto result = *this;
6003  result -= i;
6004  return result;
6005  }
6006 
6009  {
6010  return this->base() - other.base();
6011  }
6012 
6015  {
6016  return *(this->operator+(n));
6017  }
6018 
6020  typename object_t::key_type key() const
6021  {
6022  auto it = --this->base();
6023  return it.key();
6024  }
6025 
6028  {
6029  auto it = --this->base();
6030  return it.operator * ();
6031  }
6032  };
6033 
6042  {
6043  private:
6045  basic_json& container;
6047  using json_iterator = decltype(std::begin(container));
6048 
6050  class iterator_wrapper_internal
6051  {
6052  private:
6054  json_iterator anchor;
6056  size_t array_index = 0;
6057 
6058  public:
6060  iterator_wrapper_internal(json_iterator i) : anchor(i)
6061  {}
6062 
6064  iterator_wrapper_internal& operator*()
6065  {
6066  return *this;
6067  }
6068 
6070  iterator_wrapper_internal& operator++()
6071  {
6072  ++anchor;
6073  ++array_index;
6074 
6075  return *this;
6076  }
6077 
6079  bool operator!= (const iterator_wrapper_internal& o)
6080  {
6081  return anchor != o.anchor;
6082  }
6083 
6085  typename basic_json::string_t key() const
6086  {
6087  switch (anchor.m_object->type())
6088  {
6089  // use integer array index as key
6090  case value_t::array:
6091  {
6092  return std::to_string(array_index);
6093  }
6094 
6095  // use key from the object
6096  case value_t::object:
6097  {
6098  return anchor.key();
6099  }
6100 
6101  // use an empty key for all primitive types
6102  default:
6103  {
6104  return "";
6105  }
6106  }
6107  }
6108 
6110  typename json_iterator::reference value() const
6111  {
6112  return anchor.value();
6113  }
6114  };
6115 
6116  public:
6118  iterator_wrapper(basic_json& cont)
6119  : container(cont)
6120  {}
6121 
6123  iterator_wrapper_internal begin()
6124  {
6125  return iterator_wrapper_internal(container.begin());
6126  }
6127 
6129  iterator_wrapper_internal end()
6130  {
6131  return iterator_wrapper_internal(container.end());
6132  }
6133  };
6134 
6135  private:
6137  // lexer and parser //
6139 
6147  class lexer
6148  {
6149  public:
6151  enum class token_type
6152  {
6153  uninitialized,
6154  literal_true,
6155  literal_false,
6156  literal_null,
6157  value_string,
6158  value_number,
6159  begin_array,
6160  begin_object,
6161  end_array,
6162  end_object,
6163  name_separator,
6164  value_separator,
6165  parse_error,
6166  end_of_input
6167  };
6168 
6170  using lexer_char_t = unsigned char;
6171 
6173  explicit lexer(const string_t& s) noexcept
6174  : m_stream(nullptr), m_buffer(s)
6175  {
6176  m_content = reinterpret_cast<const lexer_char_t*>(s.c_str());
6177  m_start = m_cursor = m_content;
6178  m_limit = m_content + s.size();
6179  }
6180  explicit lexer(std::istream* s) noexcept
6181  : m_stream(s), m_buffer()
6182  {
6183  getline(*m_stream, m_buffer);
6184  m_content = reinterpret_cast<const lexer_char_t*>(m_buffer.c_str());
6185  m_start = m_cursor = m_content;
6186  m_limit = m_content + m_buffer.size();
6187  }
6188 
6190  lexer() = default;
6191 
6192  // switch of unwanted functions
6193  lexer(const lexer&) = delete;
6194  lexer operator=(const lexer&) = delete;
6195 
6207  static string_t to_unicode(const std::size_t codepoint1,
6208  const std::size_t codepoint2 = 0)
6209  {
6210  string_t result;
6211 
6212  // calculate the codepoint from the given code points
6213  std::size_t codepoint = codepoint1;
6214 
6215  // check if codepoint1 is a high surrogate
6216  if (codepoint1 >= 0xD800 and codepoint1 <= 0xDBFF)
6217  {
6218  // check if codepoint2 is a low surrogate
6219  if (codepoint2 >= 0xDC00 and codepoint2 <= 0xDFFF)
6220  {
6221  codepoint =
6222  // high surrogate occupies the most significant 22 bits
6223  (codepoint1 << 10)
6224  // low surrogate occupies the least significant 15 bits
6225  + codepoint2
6226  // there is still the 0xD800, 0xDC00 and 0x10000 noise
6227  // in the result so we have to substract with:
6228  // (0xD800 << 10) + DC00 - 0x10000 = 0x35FDC00
6229  - 0x35FDC00;
6230  }
6231  else
6232  {
6233  throw std::invalid_argument("missing or wrong low surrogate");
6234  }
6235  }
6236 
6237  if (codepoint < 0x80)
6238  {
6239  // 1-byte characters: 0xxxxxxx (ASCII)
6240  result.append(1, static_cast<typename string_t::value_type>(codepoint));
6241  }
6242  else if (codepoint <= 0x7ff)
6243  {
6244  // 2-byte characters: 110xxxxx 10xxxxxx
6245  result.append(1, static_cast<typename string_t::value_type>(0xC0 | ((codepoint >> 6) & 0x1F)));
6246  result.append(1, static_cast<typename string_t::value_type>(0x80 | (codepoint & 0x3F)));
6247  }
6248  else if (codepoint <= 0xffff)
6249  {
6250  // 3-byte characters: 1110xxxx 10xxxxxx 10xxxxxx
6251  result.append(1, static_cast<typename string_t::value_type>(0xE0 | ((codepoint >> 12) & 0x0F)));
6252  result.append(1, static_cast<typename string_t::value_type>(0x80 | ((codepoint >> 6) & 0x3F)));
6253  result.append(1, static_cast<typename string_t::value_type>(0x80 | (codepoint & 0x3F)));
6254  }
6255  else if (codepoint <= 0x10ffff)
6256  {
6257  // 4-byte characters: 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
6258  result.append(1, static_cast<typename string_t::value_type>(0xF0 | ((codepoint >> 18) & 0x07)));
6259  result.append(1, static_cast<typename string_t::value_type>(0x80 | ((codepoint >> 12) & 0x3F)));
6260  result.append(1, static_cast<typename string_t::value_type>(0x80 | ((codepoint >> 6) & 0x3F)));
6261  result.append(1, static_cast<typename string_t::value_type>(0x80 | (codepoint & 0x3F)));
6262  }
6263  else
6264  {
6265  throw std::out_of_range("code points above 0x10FFFF are invalid");
6266  }
6267 
6268  return result;
6269  }
6270 
6272  static std::string token_type_name(token_type t)
6273  {
6274  switch (t)
6275  {
6276  case token_type::uninitialized:
6277  return "<uninitialized>";
6278  case token_type::literal_true:
6279  return "true literal";
6280  case token_type::literal_false:
6281  return "false literal";
6282  case token_type::literal_null:
6283  return "null literal";
6284  case token_type::value_string:
6285  return "string literal";
6286  case token_type::value_number:
6287  return "number literal";
6288  case token_type::begin_array:
6289  return "[";
6290  case token_type::begin_object:
6291  return "{";
6292  case token_type::end_array:
6293  return "]";
6294  case token_type::end_object:
6295  return "}";
6296  case token_type::name_separator:
6297  return ":";
6298  case token_type::value_separator:
6299  return ",";
6300  case token_type::parse_error:
6301  return "<parse error>";
6302  case token_type::end_of_input:
6303  return "<end of input>";
6304  }
6305  }
6306 
6317  token_type scan() noexcept
6318  {
6319  // pointer for backtracking information
6320  m_marker = nullptr;
6321 
6322  // remember the begin of the token
6323  m_start = m_cursor;
6324 
6325 
6326  {
6327  lexer_char_t yych;
6328  unsigned int yyaccept = 0;
6329  static const unsigned char yybm[] =
6330  {
6331  0, 0, 0, 0, 0, 0, 0, 0,
6332  0, 32, 32, 0, 0, 32, 0, 0,
6333  64, 64, 64, 64, 64, 64, 64, 64,
6334  64, 64, 64, 64, 64, 64, 64, 64,
6335  96, 64, 0, 64, 64, 64, 64, 64,
6336  64, 64, 64, 64, 64, 64, 64, 64,
6337  192, 192, 192, 192, 192, 192, 192, 192,
6338  192, 192, 64, 64, 64, 64, 64, 64,
6339  64, 64, 64, 64, 64, 64, 64, 64,
6340  64, 64, 64, 64, 64, 64, 64, 64,
6341  64, 64, 64, 64, 64, 64, 64, 64,
6342  64, 64, 64, 64, 0, 64, 64, 64,
6343  64, 64, 64, 64, 64, 64, 64, 64,
6344  64, 64, 64, 64, 64, 64, 64, 64,
6345  64, 64, 64, 64, 64, 64, 64, 64,
6346  64, 64, 64, 64, 64, 64, 64, 64,
6347  64, 64, 64, 64, 64, 64, 64, 64,
6348  64, 64, 64, 64, 64, 64, 64, 64,
6349  64, 64, 64, 64, 64, 64, 64, 64,
6350  64, 64, 64, 64, 64, 64, 64, 64,
6351  64, 64, 64, 64, 64, 64, 64, 64,
6352  64, 64, 64, 64, 64, 64, 64, 64,
6353  64, 64, 64, 64, 64, 64, 64, 64,
6354  64, 64, 64, 64, 64, 64, 64, 64,
6355  64, 64, 64, 64, 64, 64, 64, 64,
6356  64, 64, 64, 64, 64, 64, 64, 64,
6357  64, 64, 64, 64, 64, 64, 64, 64,
6358  64, 64, 64, 64, 64, 64, 64, 64,
6359  64, 64, 64, 64, 64, 64, 64, 64,
6360  64, 64, 64, 64, 64, 64, 64, 64,
6361  64, 64, 64, 64, 64, 64, 64, 64,
6362  64, 64, 64, 64, 64, 64, 64, 64,
6363  };
6364  if ((m_limit - m_cursor) < 5)
6365  {
6366  yyfill(); // LCOV_EXCL_LINE;
6367  }
6368  yych = *m_cursor;
6369  if (yych <= ':')
6370  {
6371  if (yych <= ' ')
6372  {
6373  if (yych <= '\n')
6374  {
6375  if (yych <= 0x00)
6376  {
6377  goto basic_json_parser_28;
6378  }
6379  if (yych <= 0x08)
6380  {
6381  goto basic_json_parser_30;
6382  }
6383  if (yych >= '\n')
6384  {
6385  goto basic_json_parser_4;
6386  }
6387  }
6388  else
6389  {
6390  if (yych == '\r')
6391  {
6392  goto basic_json_parser_2;
6393  }
6394  if (yych <= 0x1F)
6395  {
6396  goto basic_json_parser_30;
6397  }
6398  }
6399  }
6400  else
6401  {
6402  if (yych <= ',')
6403  {
6404  if (yych == '"')
6405  {
6406  goto basic_json_parser_27;
6407  }
6408  if (yych <= '+')
6409  {
6410  goto basic_json_parser_30;
6411  }
6412  goto basic_json_parser_16;
6413  }
6414  else
6415  {
6416  if (yych <= '/')
6417  {
6418  if (yych <= '-')
6419  {
6420  goto basic_json_parser_23;
6421  }
6422  goto basic_json_parser_30;
6423  }
6424  else
6425  {
6426  if (yych <= '0')
6427  {
6428  goto basic_json_parser_24;
6429  }
6430  if (yych <= '9')
6431  {
6432  goto basic_json_parser_26;
6433  }
6434  goto basic_json_parser_18;
6435  }
6436  }
6437  }
6438  }
6439  else
6440  {
6441  if (yych <= 'n')
6442  {
6443  if (yych <= ']')
6444  {
6445  if (yych == '[')
6446  {
6447  goto basic_json_parser_8;
6448  }
6449  if (yych <= '\\')
6450  {
6451  goto basic_json_parser_30;
6452  }
6453  goto basic_json_parser_10;
6454  }
6455  else
6456  {
6457  if (yych == 'f')
6458  {
6459  goto basic_json_parser_22;
6460  }
6461  if (yych <= 'm')
6462  {
6463  goto basic_json_parser_30;
6464  }
6465  goto basic_json_parser_20;
6466  }
6467  }
6468  else
6469  {
6470  if (yych <= '{')
6471  {
6472  if (yych == 't')
6473  {
6474  goto basic_json_parser_21;
6475  }
6476  if (yych <= 'z')
6477  {
6478  goto basic_json_parser_30;
6479  }
6480  goto basic_json_parser_12;
6481  }
6482  else
6483  {
6484  if (yych <= '}')
6485  {
6486  if (yych <= '|')
6487  {
6488  goto basic_json_parser_30;
6489  }
6490  goto basic_json_parser_14;
6491  }
6492  else
6493  {
6494  if (yych == 0xEF)
6495  {
6496  goto basic_json_parser_6;
6497  }
6498  goto basic_json_parser_30;
6499  }
6500  }
6501  }
6502  }
6503 basic_json_parser_2:
6504  ++m_cursor;
6505  yych = *m_cursor;
6506  goto basic_json_parser_5;
6507 basic_json_parser_3:
6508  {
6509  return scan();
6510  }
6511 basic_json_parser_4:
6512  ++m_cursor;
6513  if (m_limit <= m_cursor)
6514  {
6515  yyfill(); // LCOV_EXCL_LINE;
6516  }
6517  yych = *m_cursor;
6518 basic_json_parser_5:
6519  if (yybm[0 + yych] & 32)
6520  {
6521  goto basic_json_parser_4;
6522  }
6523  goto basic_json_parser_3;
6524 basic_json_parser_6:
6525  yyaccept = 0;
6526  yych = *(m_marker = ++m_cursor);
6527  if (yych == 0xBB)
6528  {
6529  goto basic_json_parser_64;
6530  }
6531 basic_json_parser_7:
6532  {
6533  return token_type::parse_error;
6534  }
6535 basic_json_parser_8:
6536  ++m_cursor;
6537  {
6538  return token_type::begin_array;
6539  }
6540 basic_json_parser_10:
6541  ++m_cursor;
6542  {
6543  return token_type::end_array;
6544  }
6545 basic_json_parser_12:
6546  ++m_cursor;
6547  {
6548  return token_type::begin_object;
6549  }
6550 basic_json_parser_14:
6551  ++m_cursor;
6552  {
6553  return token_type::end_object;
6554  }
6555 basic_json_parser_16:
6556  ++m_cursor;
6557  {
6558  return token_type::value_separator;
6559  }
6560 basic_json_parser_18:
6561  ++m_cursor;
6562  {
6563  return token_type::name_separator;
6564  }
6565 basic_json_parser_20:
6566  yyaccept = 0;
6567  yych = *(m_marker = ++m_cursor);
6568  if (yych == 'u')
6569  {
6570  goto basic_json_parser_60;
6571  }
6572  goto basic_json_parser_7;
6573 basic_json_parser_21:
6574  yyaccept = 0;
6575  yych = *(m_marker = ++m_cursor);
6576  if (yych == 'r')
6577  {
6578  goto basic_json_parser_56;
6579  }
6580  goto basic_json_parser_7;
6581 basic_json_parser_22:
6582  yyaccept = 0;
6583  yych = *(m_marker = ++m_cursor);
6584  if (yych == 'a')
6585  {
6586  goto basic_json_parser_51;
6587  }
6588  goto basic_json_parser_7;
6589 basic_json_parser_23:
6590  yych = *++m_cursor;
6591  if (yych <= '/')
6592  {
6593  goto basic_json_parser_7;
6594  }
6595  if (yych <= '0')
6596  {
6597  goto basic_json_parser_50;
6598  }
6599  if (yych <= '9')
6600  {
6601  goto basic_json_parser_41;
6602  }
6603  goto basic_json_parser_7;
6604 basic_json_parser_24:
6605  yyaccept = 1;
6606  yych = *(m_marker = ++m_cursor);
6607  if (yych <= 'D')
6608  {
6609  if (yych == '.')
6610  {
6611  goto basic_json_parser_43;
6612  }
6613  }
6614  else
6615  {
6616  if (yych <= 'E')
6617  {
6618  goto basic_json_parser_44;
6619  }
6620  if (yych == 'e')
6621  {
6622  goto basic_json_parser_44;
6623  }
6624  }
6625 basic_json_parser_25:
6626  {
6627  return token_type::value_number;
6628  }
6629 basic_json_parser_26:
6630  yyaccept = 1;
6631  yych = *(m_marker = ++m_cursor);
6632  goto basic_json_parser_42;
6633 basic_json_parser_27:
6634  yyaccept = 0;
6635  yych = *(m_marker = ++m_cursor);
6636  if (yych <= 0x0F)
6637  {
6638  goto basic_json_parser_7;
6639  }
6640  goto basic_json_parser_32;
6641 basic_json_parser_28:
6642  ++m_cursor;
6643  {
6644  return token_type::end_of_input;
6645  }
6646 basic_json_parser_30:
6647  yych = *++m_cursor;
6648  goto basic_json_parser_7;
6649 basic_json_parser_31:
6650  ++m_cursor;
6651  if (m_limit <= m_cursor)
6652  {
6653  yyfill(); // LCOV_EXCL_LINE;
6654  }
6655  yych = *m_cursor;
6656 basic_json_parser_32:
6657  if (yybm[0 + yych] & 64)
6658  {
6659  goto basic_json_parser_31;
6660  }
6661  if (yych <= 0x0F)
6662  {
6663  goto basic_json_parser_33;
6664  }
6665  if (yych <= '"')
6666  {
6667  goto basic_json_parser_35;
6668  }
6669  goto basic_json_parser_34;
6670 basic_json_parser_33:
6671  m_cursor = m_marker;
6672  if (yyaccept == 0)
6673  {
6674  goto basic_json_parser_7;
6675  }
6676  else
6677  {
6678  goto basic_json_parser_25;
6679  }
6680 basic_json_parser_34:
6681  ++m_cursor;
6682  if (m_limit <= m_cursor)
6683  {
6684  yyfill(); // LCOV_EXCL_LINE;
6685  }
6686  yych = *m_cursor;
6687  if (yych <= 'e')
6688  {
6689  if (yych <= '/')
6690  {
6691  if (yych == '"')
6692  {
6693  goto basic_json_parser_31;
6694  }
6695  if (yych <= '.')
6696  {
6697  goto basic_json_parser_33;
6698  }
6699  goto basic_json_parser_31;
6700  }
6701  else
6702  {
6703  if (yych <= '\\')
6704  {
6705  if (yych <= '[')
6706  {
6707  goto basic_json_parser_33;
6708  }
6709  goto basic_json_parser_31;
6710  }
6711  else
6712  {
6713  if (yych == 'b')
6714  {
6715  goto basic_json_parser_31;
6716  }
6717  goto basic_json_parser_33;
6718  }
6719  }
6720  }
6721  else
6722  {
6723  if (yych <= 'q')
6724  {
6725  if (yych <= 'f')
6726  {
6727  goto basic_json_parser_31;
6728  }
6729  if (yych == 'n')
6730  {
6731  goto basic_json_parser_31;
6732  }
6733  goto basic_json_parser_33;
6734  }
6735  else
6736  {
6737  if (yych <= 's')
6738  {
6739  if (yych <= 'r')
6740  {
6741  goto basic_json_parser_31;
6742  }
6743  goto basic_json_parser_33;
6744  }
6745  else
6746  {
6747  if (yych <= 't')
6748  {
6749  goto basic_json_parser_31;
6750  }
6751  if (yych <= 'u')
6752  {
6753  goto basic_json_parser_37;
6754  }
6755  goto basic_json_parser_33;
6756  }
6757  }
6758  }
6759 basic_json_parser_35:
6760  ++m_cursor;
6761  {
6762  return token_type::value_string;
6763  }
6764 basic_json_parser_37:
6765  ++m_cursor;
6766  if (m_limit <= m_cursor)
6767  {
6768  yyfill(); // LCOV_EXCL_LINE;
6769  }
6770  yych = *m_cursor;
6771  if (yych <= '@')
6772  {
6773  if (yych <= '/')
6774  {
6775  goto basic_json_parser_33;
6776  }
6777  if (yych >= ':')
6778  {
6779  goto basic_json_parser_33;
6780  }
6781  }
6782  else
6783  {
6784  if (yych <= 'F')
6785  {
6786  goto basic_json_parser_38;
6787  }
6788  if (yych <= '`')
6789  {
6790  goto basic_json_parser_33;
6791  }
6792  if (yych >= 'g')
6793  {
6794  goto basic_json_parser_33;
6795  }
6796  }
6797 basic_json_parser_38:
6798  ++m_cursor;
6799  if (m_limit <= m_cursor)
6800  {
6801  yyfill(); // LCOV_EXCL_LINE;
6802  }
6803  yych = *m_cursor;
6804  if (yych <= '@')
6805  {
6806  if (yych <= '/')
6807  {
6808  goto basic_json_parser_33;
6809  }
6810  if (yych >= ':')
6811  {
6812  goto basic_json_parser_33;
6813  }
6814  }
6815  else
6816  {
6817  if (yych <= 'F')
6818  {
6819  goto basic_json_parser_39;
6820  }
6821  if (yych <= '`')
6822  {
6823  goto basic_json_parser_33;
6824  }
6825  if (yych >= 'g')
6826  {
6827  goto basic_json_parser_33;
6828  }
6829  }
6830 basic_json_parser_39:
6831  ++m_cursor;
6832  if (m_limit <= m_cursor)
6833  {
6834  yyfill(); // LCOV_EXCL_LINE;
6835  }
6836  yych = *m_cursor;
6837  if (yych <= '@')
6838  {
6839  if (yych <= '/')
6840  {
6841  goto basic_json_parser_33;
6842  }
6843  if (yych >= ':')
6844  {
6845  goto basic_json_parser_33;
6846  }
6847  }
6848  else
6849  {
6850  if (yych <= 'F')
6851  {
6852  goto basic_json_parser_40;
6853  }
6854  if (yych <= '`')
6855  {
6856  goto basic_json_parser_33;
6857  }
6858  if (yych >= 'g')
6859  {
6860  goto basic_json_parser_33;
6861  }
6862  }
6863 basic_json_parser_40:
6864  ++m_cursor;
6865  if (m_limit <= m_cursor)
6866  {
6867  yyfill(); // LCOV_EXCL_LINE;
6868  }
6869  yych = *m_cursor;
6870  if (yych <= '@')
6871  {
6872  if (yych <= '/')
6873  {
6874  goto basic_json_parser_33;
6875  }
6876  if (yych <= '9')
6877  {
6878  goto basic_json_parser_31;
6879  }
6880  goto basic_json_parser_33;
6881  }
6882  else
6883  {
6884  if (yych <= 'F')
6885  {
6886  goto basic_json_parser_31;
6887  }
6888  if (yych <= '`')
6889  {
6890  goto basic_json_parser_33;
6891  }
6892  if (yych <= 'f')
6893  {
6894  goto basic_json_parser_31;
6895  }
6896  goto basic_json_parser_33;
6897  }
6898 basic_json_parser_41:
6899  yyaccept = 1;
6900  m_marker = ++m_cursor;
6901  if ((m_limit - m_cursor) < 3)
6902  {
6903  yyfill(); // LCOV_EXCL_LINE;
6904  }
6905  yych = *m_cursor;
6906 basic_json_parser_42:
6907  if (yybm[0 + yych] & 128)
6908  {
6909  goto basic_json_parser_41;
6910  }
6911  if (yych <= 'D')
6912  {
6913  if (yych != '.')
6914  {
6915  goto basic_json_parser_25;
6916  }
6917  }
6918  else
6919  {
6920  if (yych <= 'E')
6921  {
6922  goto basic_json_parser_44;
6923  }
6924  if (yych == 'e')
6925  {
6926  goto basic_json_parser_44;
6927  }
6928  goto basic_json_parser_25;
6929  }
6930 basic_json_parser_43:
6931  yych = *++m_cursor;
6932  if (yych <= '/')
6933  {
6934  goto basic_json_parser_33;
6935  }
6936  if (yych <= '9')
6937  {
6938  goto basic_json_parser_48;
6939  }
6940  goto basic_json_parser_33;
6941 basic_json_parser_44:
6942  yych = *++m_cursor;
6943  if (yych <= ',')
6944  {
6945  if (yych != '+')
6946  {
6947  goto basic_json_parser_33;
6948  }
6949  }
6950  else
6951  {
6952  if (yych <= '-')
6953  {
6954  goto basic_json_parser_45;
6955  }
6956  if (yych <= '/')
6957  {
6958  goto basic_json_parser_33;
6959  }
6960  if (yych <= '9')
6961  {
6962  goto basic_json_parser_46;
6963  }
6964  goto basic_json_parser_33;
6965  }
6966 basic_json_parser_45:
6967  yych = *++m_cursor;
6968  if (yych <= '/')
6969  {
6970  goto basic_json_parser_33;
6971  }
6972  if (yych >= ':')
6973  {
6974  goto basic_json_parser_33;
6975  }
6976 basic_json_parser_46:
6977  ++m_cursor;
6978  if (m_limit <= m_cursor)
6979  {
6980  yyfill(); // LCOV_EXCL_LINE;
6981  }
6982  yych = *m_cursor;
6983  if (yych <= '/')
6984  {
6985  goto basic_json_parser_25;
6986  }
6987  if (yych <= '9')
6988  {
6989  goto basic_json_parser_46;
6990  }
6991  goto basic_json_parser_25;
6992 basic_json_parser_48:
6993  yyaccept = 1;
6994  m_marker = ++m_cursor;
6995  if ((m_limit - m_cursor) < 3)
6996  {
6997  yyfill(); // LCOV_EXCL_LINE;
6998  }
6999  yych = *m_cursor;
7000  if (yych <= 'D')
7001  {
7002  if (yych <= '/')
7003  {
7004  goto basic_json_parser_25;
7005  }
7006  if (yych <= '9')
7007  {
7008  goto basic_json_parser_48;
7009  }
7010  goto basic_json_parser_25;
7011  }
7012  else
7013  {
7014  if (yych <= 'E')
7015  {
7016  goto basic_json_parser_44;
7017  }
7018  if (yych == 'e')
7019  {
7020  goto basic_json_parser_44;
7021  }
7022  goto basic_json_parser_25;
7023  }
7024 basic_json_parser_50:
7025  yyaccept = 1;
7026  yych = *(m_marker = ++m_cursor);
7027  if (yych <= 'D')
7028  {
7029  if (yych == '.')
7030  {
7031  goto basic_json_parser_43;
7032  }
7033  goto basic_json_parser_25;
7034  }
7035  else
7036  {
7037  if (yych <= 'E')
7038  {
7039  goto basic_json_parser_44;
7040  }
7041  if (yych == 'e')
7042  {
7043  goto basic_json_parser_44;
7044  }
7045  goto basic_json_parser_25;
7046  }
7047 basic_json_parser_51:
7048  yych = *++m_cursor;
7049  if (yych != 'l')
7050  {
7051  goto basic_json_parser_33;
7052  }
7053  yych = *++m_cursor;
7054  if (yych != 's')
7055  {
7056  goto basic_json_parser_33;
7057  }
7058  yych = *++m_cursor;
7059  if (yych != 'e')
7060  {
7061  goto basic_json_parser_33;
7062  }
7063  ++m_cursor;
7064  {
7065  return token_type::literal_false;
7066  }
7067 basic_json_parser_56:
7068  yych = *++m_cursor;
7069  if (yych != 'u')
7070  {
7071  goto basic_json_parser_33;
7072  }
7073  yych = *++m_cursor;
7074  if (yych != 'e')
7075  {
7076  goto basic_json_parser_33;
7077  }
7078  ++m_cursor;
7079  {
7080  return token_type::literal_true;
7081  }
7082 basic_json_parser_60:
7083  yych = *++m_cursor;
7084  if (yych != 'l')
7085  {
7086  goto basic_json_parser_33;
7087  }
7088  yych = *++m_cursor;
7089  if (yych != 'l')
7090  {
7091  goto basic_json_parser_33;
7092  }
7093  ++m_cursor;
7094  {
7095  return token_type::literal_null;
7096  }
7097 basic_json_parser_64:
7098  yych = *++m_cursor;
7099  if (yych != 0xBF)
7100  {
7101  goto basic_json_parser_33;
7102  }
7103  ++m_cursor;
7104  {
7105  return scan();
7106  }
7107  }
7108 
7109 
7110  }
7111 
7113  void yyfill() noexcept
7114  {
7115  if (not m_stream or not * m_stream)
7116  {
7117  return;
7118  }
7119 
7120  const ssize_t offset_start = m_start - m_content;
7121  const ssize_t offset_marker = m_marker - m_start;
7122  const ssize_t offset_cursor = m_cursor - m_start;
7123 
7124  m_buffer.erase(0, static_cast<size_t>(offset_start));
7125  std::string line;
7126  std::getline(*m_stream, line);
7127  m_buffer += "\n" + line; // add line with newline symbol
7128 
7129  m_content = reinterpret_cast<const lexer_char_t*>(m_buffer.c_str());
7130  m_start = m_content;
7131  m_marker = m_start + offset_marker;
7132  m_cursor = m_start + offset_cursor;
7133  m_limit = m_start + m_buffer.size() - 1;
7134  }
7135 
7137  string_t get_token() const noexcept
7138  {
7139  return string_t(reinterpret_cast<typename string_t::const_pointer>(m_start),
7140  static_cast<size_t>(m_cursor - m_start));
7141  }
7142 
7164  string_t get_string() const
7165  {
7166  string_t result;
7167  result.reserve(static_cast<size_t>(m_cursor - m_start - 2));
7168 
7169  // iterate the result between the quotes
7170  for (const lexer_char_t* i = m_start + 1; i < m_cursor - 1; ++i)
7171  {
7172  // process escaped characters
7173  if (*i == '\\')
7174  {
7175  // read next character
7176  ++i;
7177 
7178  switch (*i)
7179  {
7180  // the default escapes
7181  case 't':
7182  {
7183  result += "\t";
7184  break;
7185  }
7186  case 'b':
7187  {
7188  result += "\b";
7189  break;
7190  }
7191  case 'f':
7192  {
7193  result += "\f";
7194  break;
7195  }
7196  case 'n':
7197  {
7198  result += "\n";
7199  break;
7200  }
7201  case 'r':
7202  {
7203  result += "\r";
7204  break;
7205  }
7206  case '\\':
7207  {
7208  result += "\\";
7209  break;
7210  }
7211  case '/':
7212  {
7213  result += "/";
7214  break;
7215  }
7216  case '"':
7217  {
7218  result += "\"";
7219  break;
7220  }
7221 
7222  // unicode
7223  case 'u':
7224  {
7225  // get code xxxx from uxxxx
7226  auto codepoint = std::strtoul(std::string(reinterpret_cast<typename string_t::const_pointer>(i + 1),
7227  4).c_str(), nullptr, 16);
7228 
7229  // check if codepoint is a high surrogate
7230  if (codepoint >= 0xD800 and codepoint <= 0xDBFF)
7231  {
7232  // make sure there is a subsequent unicode
7233  if ((i + 6 >= m_limit) or * (i + 5) != '\\' or * (i + 6) != 'u')
7234  {
7235  throw std::invalid_argument("missing low surrogate");
7236  }
7237 
7238  // get code yyyy from uxxxx\uyyyy
7239  auto codepoint2 = std::strtoul(std::string(reinterpret_cast<typename string_t::const_pointer>
7240  (i + 7), 4).c_str(), nullptr, 16);
7241  result += to_unicode(codepoint, codepoint2);
7242  // skip the next 10 characters (xxxx\uyyyy)
7243  i += 10;
7244  }
7245  else
7246  {
7247  // add unicode character(s)
7248  result += to_unicode(codepoint);
7249  // skip the next four characters (xxxx)
7250  i += 4;
7251  }
7252  break;
7253  }
7254  }
7255  }
7256  else
7257  {
7258  // all other characters are just copied to the end of the
7259  // string
7260  result.append(1, static_cast<typename string_t::value_type>(*i));
7261  }
7262  }
7263 
7264  return result;
7265  }
7266 
7284  long double get_number() const
7285  {
7286  // conversion
7287  typename string_t::value_type* endptr;
7288  const auto float_val = std::strtold(reinterpret_cast<typename string_t::const_pointer>(m_start),
7289  &endptr);
7290 
7291  // return float_val if the whole number was translated and NAN
7292  // otherwise
7293  return (reinterpret_cast<lexer_char_t*>(endptr) == m_cursor) ? float_val : NAN;
7294  }
7295 
7296  private:
7298  std::istream* m_stream;
7300  string_t m_buffer;
7302  const lexer_char_t* m_content = nullptr;
7304  const lexer_char_t* m_start = nullptr;
7306  const lexer_char_t* m_marker = nullptr;
7308  const lexer_char_t* m_cursor = nullptr;
7310  const lexer_char_t* m_limit = nullptr;
7311  };
7312 
7318  class parser
7319  {
7320  public:
7322  parser(const string_t& s, parser_callback_t cb = nullptr)
7323  : callback(cb), m_lexer(s)
7324  {
7325  // read first token
7326  get_token();
7327  }
7328 
7330  parser(std::istream& _is, parser_callback_t cb = nullptr)
7331  : callback(cb), m_lexer(&_is)
7332  {
7333  // read first token
7334  get_token();
7335  }
7336 
7338  basic_json parse()
7339  {
7340  basic_json result = parse_internal(true);
7341 
7342  expect(lexer::token_type::end_of_input);
7343 
7344  // return parser result and replace it with null in case the
7345  // top-level value was discarded by the callback function
7346  return result.is_discarded() ? basic_json() : result;
7347  }
7348 
7349  private:
7351  basic_json parse_internal(bool keep)
7352  {
7353  auto result = basic_json(value_t::discarded);
7354 
7355  switch (last_token)
7356  {
7357  case lexer::token_type::begin_object:
7358  {
7359  if (keep and (not callback or (keep = callback(depth++, parse_event_t::object_start, result))))
7360  {
7361  // explicitly set result to object to cope with {}
7362  result.m_type = value_t::object;
7363  result.m_value = json_value(value_t::object);
7364  }
7365 
7366  // read next token
7367  get_token();
7368 
7369  // closing } -> we are done
7370  if (last_token == lexer::token_type::end_object)
7371  {
7372  get_token();
7373  if (keep and callback and not callback(--depth, parse_event_t::object_end, result))
7374  {
7375  result = basic_json(value_t::discarded);
7376  }
7377  return result;
7378  }
7379 
7380  // no comma is expected here
7381  unexpect(lexer::token_type::value_separator);
7382 
7383  // otherwise: parse key-value pairs
7384  do
7385  {
7386  // ugly, but could be fixed with loop reorganization
7387  if (last_token == lexer::token_type::value_separator)
7388  {
7389  get_token();
7390  }
7391 
7392  // store key
7393  expect(lexer::token_type::value_string);
7394  const auto key = m_lexer.get_string();
7395 
7396  bool keep_tag = false;
7397  if (keep)
7398  {
7399  if (callback)
7400  {
7401  basic_json k(key);
7402  keep_tag = callback(depth, parse_event_t::key, k);
7403  }
7404  else
7405  {
7406  keep_tag = true;
7407  }
7408  }
7409 
7410  // parse separator (:)
7411  get_token();
7412  expect(lexer::token_type::name_separator);
7413 
7414  // parse and add value
7415  get_token();
7416  auto value = parse_internal(keep);
7417  if (keep and keep_tag and not value.is_discarded())
7418  {
7419  result[key] = std::move(value);
7420  }
7421  }
7422  while (last_token == lexer::token_type::value_separator);
7423 
7424  // closing }
7425  expect(lexer::token_type::end_object);
7426  get_token();
7427  if (keep and callback and not callback(--depth, parse_event_t::object_end, result))
7428  {
7429  result = basic_json(value_t::discarded);
7430  }
7431 
7432  return result;
7433  }
7434 
7435  case lexer::token_type::begin_array:
7436  {
7437  if (keep and (not callback or (keep = callback(depth++, parse_event_t::array_start, result))))
7438  {
7439  // explicitly set result to object to cope with []
7440  result.m_type = value_t::array;
7441  result.m_value = json_value(value_t::array);
7442  }
7443 
7444  // read next token
7445  get_token();
7446 
7447  // closing ] -> we are done
7448  if (last_token == lexer::token_type::end_array)
7449  {
7450  get_token();
7451  if (callback and not callback(--depth, parse_event_t::array_end, result))
7452  {
7453  result = basic_json(value_t::discarded);
7454  }
7455  return result;
7456  }
7457 
7458  // no comma is expected here
7459  unexpect(lexer::token_type::value_separator);
7460 
7461  // otherwise: parse values
7462  do
7463  {
7464  // ugly, but could be fixed with loop reorganization
7465  if (last_token == lexer::token_type::value_separator)
7466  {
7467  get_token();
7468  }
7469 
7470  // parse value
7471  auto value = parse_internal(keep);
7472  if (keep and not value.is_discarded())
7473  {
7474  result.push_back(std::move(value));
7475  }
7476  }
7477  while (last_token == lexer::token_type::value_separator);
7478 
7479  // closing ]
7480  expect(lexer::token_type::end_array);
7481  get_token();
7482  if (keep and callback and not callback(--depth, parse_event_t::array_end, result))
7483  {
7484  result = basic_json(value_t::discarded);
7485  }
7486 
7487  return result;
7488  }
7489 
7490  case lexer::token_type::literal_null:
7491  {
7492  get_token();
7493  result.m_type = value_t::null;
7494  break;
7495  }
7496 
7497  case lexer::token_type::value_string:
7498  {
7499  const auto s = m_lexer.get_string();
7500  get_token();
7501  result = basic_json(s);
7502  break;
7503  }
7504 
7505  case lexer::token_type::literal_true:
7506  {
7507  get_token();
7508  result.m_type = value_t::boolean;
7509  result.m_value = true;
7510  break;
7511  }
7512 
7513  case lexer::token_type::literal_false:
7514  {
7515  get_token();
7516  result.m_type = value_t::boolean;
7517  result.m_value = false;
7518  break;
7519  }
7520 
7521  case lexer::token_type::value_number:
7522  {
7523  auto float_val = m_lexer.get_number();
7524 
7525  // NAN is returned if token could not be translated
7526  // completely
7527  if (std::isnan(float_val))
7528  {
7529  throw std::invalid_argument(std::string("parse error - ") +
7530  m_lexer.get_token() + " is not a number");
7531  }
7532 
7533  get_token();
7534 
7535  // check if conversion loses precision
7536  const auto int_val = static_cast<number_integer_t>(float_val);
7537  if (approx(float_val, static_cast<long double>(int_val)))
7538  {
7539  // we would not lose precision -> return int
7540  result.m_type = value_t::number_integer;
7541  result.m_value = int_val;
7542  }
7543  else
7544  {
7545  // we would lose precision -> return float
7546  result.m_type = value_t::number_float;
7547  result.m_value = static_cast<number_float_t>(float_val);
7548  }
7549  break;
7550  }
7551 
7552  default:
7553  {
7554  // the last token was unexpected
7555  unexpect(last_token);
7556  }
7557  }
7558 
7559  if (keep and callback and not callback(depth, parse_event_t::value, result))
7560  {
7561  result = basic_json(value_t::discarded);
7562  }
7563  return result;
7564  }
7565 
7567  typename lexer::token_type get_token()
7568  {
7569  last_token = m_lexer.scan();
7570  return last_token;
7571  }
7572 
7573  void expect(typename lexer::token_type t) const
7574  {
7575  if (t != last_token)
7576  {
7577  std::string error_msg = "parse error - unexpected \'";
7578  error_msg += m_lexer.get_token();
7579  error_msg += "\' (" + lexer::token_type_name(last_token);
7580  error_msg += "); expected " + lexer::token_type_name(t);
7581  throw std::invalid_argument(error_msg);
7582  }
7583  }
7584 
7585  void unexpect(typename lexer::token_type t) const
7586  {
7587  if (t == last_token)
7588  {
7589  std::string error_msg = "parse error - unexpected \'";
7590  error_msg += m_lexer.get_token();
7591  error_msg += "\' (";
7592  error_msg += lexer::token_type_name(last_token) + ")";
7593  throw std::invalid_argument(error_msg);
7594  }
7595  }
7596 
7597  private:
7599  int depth = 0;
7601  parser_callback_t callback;
7603  typename lexer::token_type last_token = lexer::token_type::uninitialized;
7605  lexer m_lexer;
7606  };
7607 };
7608 
7609 
7611 // presets //
7613 
7623 }
7624 
7625 
7627 // nonmember functions //
7629 
7630 // specialization of std::swap, and std::hash
7631 namespace std
7632 {
7638 template <>
7639 inline void swap(nlohmann::json& j1,
7640  nlohmann::json& j2) noexcept(
7641  is_nothrow_move_constructible<nlohmann::json>::value and
7642  is_nothrow_move_assignable<nlohmann::json>::value
7643  )
7644 {
7645  j1.swap(j2);
7646 }
7647 
7649 template <>
7650 struct hash<nlohmann::json>
7651 {
7657  std::size_t operator()(const nlohmann::json& j) const
7658  {
7659  // a naive hashing via the string representation
7660  const auto& h = hash<nlohmann::json::string_t>();
7661  return h(j.dump());
7662  }
7663 };
7664 }
7665 
7678 inline nlohmann::json operator "" _json(const char* s, std::size_t)
7679 {
7680  return nlohmann::json::parse(reinterpret_cast<nlohmann::json::string_t::value_type*>
7681  (const_cast<char*>(s)));
7682 }
7683 
7684 #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:6118
bool operator!=(const const_iterator &other) const
comparison: not equal
Definition: json.hpp:5611
iterator insert(const_iterator pos, basic_json &&val)
inserts element
Definition: json.hpp:4087
iterator operator++(int)
post-increment (it++)
Definition: json.hpp:5848
friend bool operator<=(const_reference lhs, const_reference rhs) noexcept
comparison: less than or equal
Definition: json.hpp:4636
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:6000
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:2802
reference operator[](const T(&key)[n])
access specified object element
Definition: json.hpp:2890
typename basic_json::const_pointer pointer
defines a pointer to the type iterated over (value_type)
Definition: json.hpp:5313
const_iterator & operator--()
pre-decrement (–it)
Definition: json.hpp:5556
friend std::istream & operator>>(std::istream &i, basic_json &j)
deserialize from stream
Definition: json.hpp:4849
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:5378
typename basic_json::value_type value_type
the type of the values when the iterator is dereferenced
Definition: json.hpp:5309
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:4162
iterator insert(const_iterator pos, size_type cnt, const basic_json &val)
inserts elements
Definition: json.hpp:4114
json_reverse_iterator operator--(int)
post-decrement (it–)
Definition: json.hpp:5972
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:4012
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:5856
friend bool operator!=(const_reference lhs, const_reference rhs) noexcept
comparison: not equal
Definition: json.hpp:4514
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:5521
difference_type operator-(const json_reverse_iterator &other) const
return difference
Definition: json.hpp:6008
basic_json<> json
default JSON class
Definition: json.hpp:7622
reference front()
access the first element
Definition: json.hpp:3012
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:3378
std::reverse_iterator< Base > base_iterator
shortcut to the reverse iterator adaptor
Definition: json.hpp:5947
json_reverse_iterator(const typename base_iterator::iterator_type &it)
create reverse iterator from iterator
Definition: json.hpp:5952
a class to store JSON values
Definition: json.hpp:187
json_reverse_iterator & operator--()
pre-decrement (–it)
Definition: json.hpp:5978
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:4493
void push_back(basic_json &&val)
add an object to an array
Definition: json.hpp:3928
const_iterator cbegin() const
returns a const iterator to the first element
Definition: json.hpp:3476
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:5878
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:5807
reference operator+=(basic_json &&val)
add an object to an array
Definition: json.hpp:3953
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:5804
iterator & operator-=(difference_type i)
subtract from iterator
Definition: json.hpp:5885
static basic_json parse(std::istream &&i, parser_callback_t cb=nullptr)
deserialize from stream
Definition: json.hpp:4811
reference operator[](const typename object_t::key_type &key)
access specified object element
Definition: json.hpp:2841
STL namespace.
difference_type operator-(const iterator &other) const
Definition: json.hpp:5907
reference value() const
return the value of an iterator
Definition: json.hpp:5780
const_iterator end() const
returns a const iterator to one past the last element
Definition: json.hpp:3511
const_iterator(const const_iterator &other) noexcept
copy constructor
Definition: json.hpp:5373
reference at(const typename object_t::key_type &key)
access specified object element with bounds checking
Definition: json.hpp:2684
object_t::key_type key() const
return the key of an object iterator
Definition: json.hpp:5767
iterator end()
returns an iterator to one past the last element
Definition: json.hpp:3501
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:5836
reverse_iterator rend()
returns an iterator to the reverse-end
Definition: json.hpp:3590
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:5703
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:5315
const_reverse_iterator rend() const
returns a const reverse iterator to one before the first
Definition: json.hpp:3598
size_type erase(const typename object_t::key_type &key)
remove element from a JSON object given a key
Definition: json.hpp:3292
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:3442
const_reference at(const typename object_t::key_type &key) const
access specified object element with bounds checking
Definition: json.hpp:2722
reference operator+=(const basic_json &val)
add an object to an array
Definition: json.hpp:3986
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:5892
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:3362
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:4680
iterator & operator--()
pre-decrement (–it)
Definition: json.hpp:5871
friend bool operator<(const_reference lhs, const_reference rhs) noexcept
comparison: less than
Definition: json.hpp:4575
pointer operator->() const
dereference the iterator
Definition: json.hpp:5484
discarded by the the parser callback function
const_iterator cend() const
returns a const iterator to one past the last element
Definition: json.hpp:3535
typename Base::reference reference
the reference type for the pointed-to element
Definition: json.hpp:5949
size_type size() const noexcept
returns the number of elements
Definition: json.hpp:3745
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:2612
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:5956
iterator_wrapper_internal end()
return iterator end (needed for range-based for)
Definition: json.hpp:6129
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:4735
ValueType value(const typename object_t::key_type &key, ValueType default_value) const
access specified object element with default value
Definition: json.hpp:2961
object_t::key_type key() const
return the key of an object iterator
Definition: json.hpp:6020
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:5311
void swap(array_t &other)
exchanges the values
Definition: json.hpp:4283
reverse_iterator rbegin()
returns an iterator to the reverse-beginning
Definition: json.hpp:3559
reference operator+=(const typename object_t::value_type &val)
add an object to an object
Definition: json.hpp:4035
iterator_wrapper_internal begin()
return iterator begin (needed for range-based for)
Definition: json.hpp:6123
reference operator[](difference_type n) const
access to successor
Definition: json.hpp:5913
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:3567
~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:5695
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:4347
reference value() const
return the value of an iterator
Definition: json.hpp:5919
const_iterator operator--(int)
post-decrement (it–)
Definition: json.hpp:5548
void erase(const size_type idx)
remove element from a JSON array given an index
Definition: json.hpp:3327
void clear() noexcept
clears the contents
Definition: json.hpp:3862
pointer operator->()
dereference the iterator
Definition: json.hpp:5842
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:3020
bool operator>=(const const_iterator &other) const
comparison: greater than or equal
Definition: json.hpp:5657
iterator insert(const_iterator pos, std::initializer_list< basic_json > ilist)
inserts elements
Definition: json.hpp:4216
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:5663
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:5711
friend bool operator==(const_reference lhs, const_reference rhs) noexcept
comparison: equal
Definition: json.hpp:4426
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:3644
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:3688
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:2987
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:4253
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:3621
reference value() const
return the value of an iterator
Definition: json.hpp:6027
const_iterator(pointer object)
constructor for a given JSON instance
Definition: json.hpp:5323
friend bool operator<(const value_t lhs, const value_t rhs)
comparison operator for JSON types
Definition: json.hpp:4380
iterator(pointer object) noexcept
constructor for a given JSON instance
Definition: json.hpp:5815
bool operator<(const const_iterator &other) const
comparison: smaller
Definition: json.hpp:5617
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:4537
const_iterator & operator-=(difference_type i)
subtract from iterator
Definition: json.hpp:5689
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:4774
InteratorType erase(InteratorType first, InteratorType last)
remove elements given an iterator range
Definition: json.hpp:3212
json_reverse_iterator operator++(int)
post-increment (it++)
Definition: json.hpp:5959
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:5348
friend bool operator!=(std::nullptr_t, const_reference v) noexcept
comparison: not equal
Definition: json.hpp:4546
InteratorType erase(InteratorType pos)
remove element given an iterator
Definition: json.hpp:3111
bool operator<=(const const_iterator &other) const
comparison: less than or equal
Definition: json.hpp:5645
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:3046
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:5513
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:5819
const_reference back() const
access the last element
Definition: json.hpp:3056
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:4803
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:3408
size_type max_size() const noexcept
returns the maximum possible number of elements
Definition: json.hpp:3805
void push_back(const basic_json &val)
add an object to an array
Definition: json.hpp:3963
bool operator==(const const_iterator &other) const
comparison: equal
Definition: json.hpp:5583
json_reverse_iterator & operator++()
pre-increment (++it)
Definition: json.hpp:5965
bool operator>(const const_iterator &other) const
comparison: greater than
Definition: json.hpp:5651
friend bool operator>(const_reference lhs, const_reference rhs) noexcept
comparison: greater than
Definition: json.hpp:4658
basic_json(basic_json &&other) noexcept
move constructor
Definition: json.hpp:1738
const_iterator begin() const
returns a const iterator to the first element
Definition: json.hpp:3452
const_reference at(size_type idx) const
access specified array element with bounds checking
Definition: json.hpp:2646
json_reverse_iterator & operator+=(difference_type i)
add to iterator
Definition: json.hpp:5985
a const random access iterator for the basic_json class
Definition: json.hpp:5302
a template for a reverse iterator class
Definition: json.hpp:232
void swap(object_t &other)
exchanges the values
Definition: json.hpp:4315
std::bidirectional_iterator_tag iterator_category
the category of the iterator
Definition: json.hpp:5317
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:4061
friend bool operator==(const_reference v, std::nullptr_t) noexcept
comparison: equal
Definition: json.hpp:4484
reference operator[](difference_type n) const
access to successor
Definition: json.hpp:6014
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:5733
reference operator*() const
return a reference to the value pointed to by the iterator
Definition: json.hpp:5450
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:4839
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:7657
friend std::ostream & operator<<(std::ostream &o, const basic_json &j)
serialize to stream
Definition: json.hpp:4717
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:5824
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:2759
iterator operator--(int)
post-decrement (it–)
Definition: json.hpp:5863
json_reverse_iterator operator+(difference_type i) const
add to iterator
Definition: json.hpp:5992
parse_event_t
JSON callback events.
Definition: json.hpp:754
iterator operator-(difference_type i)
subtract from iterator
Definition: json.hpp:5900
wrapper to access iterator member functions in range-based for
Definition: json.hpp:6041