JSON for Modern C++  1.0.0-rc1
json.hpp
1 
38 #ifndef NLOHMANN_JSON_HPP
39 #define NLOHMANN_JSON_HPP
40 
41 #include <algorithm>
42 #include <array>
43 #include <ciso646>
44 #include <cmath>
45 #include <cstdio>
46 #include <functional>
47 #include <initializer_list>
48 #include <iomanip>
49 #include <iostream>
50 #include <iterator>
51 #include <limits>
52 #include <map>
53 #include <memory>
54 #include <sstream>
55 #include <string>
56 #include <type_traits>
57 #include <utility>
58 #include <vector>
59 
60 // enable ssize_t on MinGW
61 #ifdef __GNUC__
62  #ifdef __MINGW32__
63  #include <sys/types.h>
64  #endif
65 #endif
66 
67 // enable ssize_t for MSVC
68 #ifdef _MSC_VER
69  #include <basetsd.h>
70  using ssize_t = SSIZE_T;
71 #endif
72 
78 namespace nlohmann
79 {
80 
81 
86 namespace
87 {
92 template<typename T>
93 struct has_mapped_type
94 {
95  private:
96  template<typename C> static char test(typename C::mapped_type*);
97  template<typename C> static int test(...);
98  public:
99  enum { value = sizeof(test<T>(0)) == sizeof(char) };
100 };
101 
103 template<typename T>
104 static bool approx(const T a, const T b)
105 {
106  return not (a > b or a < b);
107 }
108 }
109 
178 template <
179  template<typename U, typename V, typename... Args> class ObjectType = std::map,
180  template<typename U, typename... Args> class ArrayType = std::vector,
181  class StringType = std::string,
182  class BooleanType = bool,
183  class NumberIntegerType = int64_t,
184  class NumberFloatType = double,
185  template<typename U> class AllocatorType = std::allocator
186  >
188 {
189  private:
191  using basic_json_t = basic_json<ObjectType,
192  ArrayType,
193  StringType,
194  BooleanType,
195  NumberIntegerType,
196  NumberFloatType,
197  AllocatorType>;
198 
199  public:
200 
202  // container types //
204 
207 
210 
213 
215  using const_reference = const value_type&;
216 
218  using difference_type = std::ptrdiff_t;
219 
221  using size_type = std::size_t;
222 
224  using allocator_type = AllocatorType<basic_json>;
225 
227  using pointer = typename std::allocator_traits<allocator_type>::pointer;
229  using const_pointer = typename std::allocator_traits<allocator_type>::const_pointer;
230 
231  // forward declaration
232  template<typename Base> class json_reverse_iterator;
233 
235  class iterator;
237  class const_iterator;
242 
244 
245 
250  {
251  return allocator_type();
252  }
253 
254 
256  // JSON value data types //
258 
261 
336  using object_t = ObjectType<StringType,
337  basic_json,
338  std::less<StringType>,
339  AllocatorType<std::pair<const StringType,
340  basic_json>>>;
341 
386  using array_t = ArrayType<basic_json, AllocatorType<basic_json>>;
387 
433  using string_t = StringType;
434 
459  using boolean_t = BooleanType;
460 
527  using number_integer_t = NumberIntegerType;
528 
592  using number_float_t = NumberFloatType;
593 
595 
596 
598  // JSON type enumeration //
600 
611  enum class value_t : uint8_t
612  {
613  null,
614  object,
615  array,
616  string,
617  boolean,
619  number_float,
620  discarded
621  };
622 
623 
624  private:
626  template<typename T, typename... Args>
627  static T* create(Args&& ... args)
628  {
629  AllocatorType<T> alloc;
630  auto deleter = [&](T * object)
631  {
632  alloc.deallocate(object, 1);
633  };
634  std::unique_ptr<T, decltype(deleter)> object(alloc.allocate(1), deleter);
635  alloc.construct(object.get(), std::forward<Args>(args)...);
636  return object.release();
637  }
638 
640  // JSON value storage //
642 
650  union json_value
651  {
653  object_t* object;
655  array_t* array;
657  string_t* string;
659  boolean_t boolean;
661  number_integer_t number_integer;
663  number_float_t number_float;
664 
666  json_value() noexcept = default;
668  json_value(boolean_t v) noexcept : boolean(v) {}
670  json_value(number_integer_t v) noexcept : number_integer(v) {}
672  json_value(number_float_t v) noexcept : number_float(v) {}
674  json_value(value_t t)
675  {
676  switch (t)
677  {
678  case value_t::object:
679  {
680  object = create<object_t>();
681  break;
682  }
683 
684  case value_t::array:
685  {
686  array = create<array_t>();
687  break;
688  }
689 
690  case value_t::string:
691  {
692  string = create<string_t>("");
693  break;
694  }
695 
696  case value_t::boolean:
697  {
698  boolean = boolean_t(false);
699  break;
700  }
701 
703  {
704  number_integer = number_integer_t(0);
705  break;
706  }
707 
709  {
710  number_float = number_float_t(0.0);
711  break;
712  }
713 
714  default:
715  {
716  break;
717  }
718  }
719  }
720 
722  json_value(const string_t& value)
723  {
724  string = create<string_t>(value);
725  }
726 
728  json_value(const object_t& value)
729  {
730  object = create<object_t>(value);
731  }
732 
734  json_value(const array_t& value)
735  {
736  array = create<array_t>(value);
737  }
738  };
739 
740 
741  public:
743  // JSON parser callback //
745 
754  enum class parse_event_t : uint8_t
755  {
757  object_start,
759  object_end,
761  array_start,
763  array_end,
765  key,
767  value
768  };
769 
819  using parser_callback_t = std::function<bool(int depth, parse_event_t event, basic_json& parsed)>;
820 
821 
823  // constructors //
825 
828 
867  : m_type(value_type), m_value(value_type)
868  {}
869 
889  basic_json() noexcept = default;
890 
910  basic_json(std::nullptr_t) noexcept
911  : basic_json(value_t::null)
912  {}
913 
933  basic_json(const object_t& val)
934  : m_type(value_t::object), m_value(val)
935  {}
936 
960  template <class CompatibleObjectType, typename
961  std::enable_if<
962  std::is_constructible<typename object_t::key_type, typename CompatibleObjectType::key_type>::value and
963  std::is_constructible<basic_json, typename CompatibleObjectType::mapped_type>::value, int>::type
964  = 0>
965  basic_json(const CompatibleObjectType& val)
966  : m_type(value_t::object)
967  {
968  using std::begin;
969  using std::end;
970  m_value.object = create<object_t>(begin(val), end(val));
971  }
972 
992  basic_json(const array_t& val)
993  : m_type(value_t::array), m_value(val)
994  {}
995 
1019  template <class CompatibleArrayType, typename
1020  std::enable_if<
1021  not std::is_same<CompatibleArrayType, typename basic_json_t::iterator>::value and
1022  not std::is_same<CompatibleArrayType, typename basic_json_t::const_iterator>::value and
1023  not std::is_same<CompatibleArrayType, typename basic_json_t::reverse_iterator>::value and
1024  not std::is_same<CompatibleArrayType, typename basic_json_t::const_reverse_iterator>::value and
1025  not std::is_same<CompatibleArrayType, typename array_t::iterator>::value and
1026  not std::is_same<CompatibleArrayType, typename array_t::const_iterator>::value and
1027  std::is_constructible<basic_json, typename CompatibleArrayType::value_type>::value, int>::type
1028  = 0>
1029  basic_json(const CompatibleArrayType& val)
1030  : m_type(value_t::array)
1031  {
1032  using std::begin;
1033  using std::end;
1034  m_value.array = create<array_t>(begin(val), end(val));
1035  }
1036 
1058  basic_json(const string_t& val)
1059  : m_type(value_t::string), m_value(val)
1060  {}
1061 
1082  basic_json(const typename string_t::value_type* val)
1083  : basic_json(string_t(val))
1084  {}
1085 
1109  template <class CompatibleStringType, typename
1110  std::enable_if<
1111  std::is_constructible<string_t, CompatibleStringType>::value, int>::type
1112  = 0>
1113  basic_json(const CompatibleStringType& val)
1114  : basic_json(string_t(val))
1115  {}
1116 
1132  : m_type(value_t::boolean), m_value(val)
1133  {}
1134 
1160  template<typename T,
1161  typename std::enable_if<
1162  not (std::is_same<T, int>::value)
1163  and std::is_same<T, number_integer_t>::value
1164  , int>::type = 0>
1165  basic_json(const number_integer_t val)
1166  : m_type(value_t::number_integer), m_value(val)
1167  {}
1168 
1194  basic_json(const int val)
1195  : m_type(value_t::number_integer),
1196  m_value(static_cast<number_integer_t>(val))
1197  {}
1198 
1224  template<typename CompatibleNumberIntegerType, typename
1225  std::enable_if<
1226  std::is_constructible<number_integer_t, CompatibleNumberIntegerType>::value and
1227  std::numeric_limits<CompatibleNumberIntegerType>::is_integer, CompatibleNumberIntegerType>::type
1228  = 0>
1229  basic_json(const CompatibleNumberIntegerType val) noexcept
1230  : m_type(value_t::number_integer),
1231  m_value(static_cast<number_integer_t>(val))
1232  {}
1233 
1259  : m_type(value_t::number_float), m_value(val)
1260  {
1261  // replace infinity and NAN by null
1262  if (not std::isfinite(val))
1263  {
1264  m_type = value_t::null;
1265  m_value = json_value();
1266  }
1267  }
1268 
1299  template<typename CompatibleNumberFloatType, typename = typename
1300  std::enable_if<
1301  std::is_constructible<number_float_t, CompatibleNumberFloatType>::value and
1302  std::is_floating_point<CompatibleNumberFloatType>::value>::type
1303  >
1304  basic_json(const CompatibleNumberFloatType val) noexcept
1305  : basic_json(number_float_t(val))
1306  {}
1307 
1376  basic_json(std::initializer_list<basic_json> init,
1377  bool type_deduction = true,
1378  value_t manual_type = value_t::array)
1379  {
1380  // the initializer list could describe an object
1381  bool is_an_object = true;
1382 
1383  // check if each element is an array with two elements whose first
1384  // element is a string
1385  for (const auto& element : init)
1386  {
1387  if (not element.is_array() or element.size() != 2
1388  or not element[0].is_string())
1389  {
1390  // we found an element that makes it impossible to use the
1391  // initializer list as object
1392  is_an_object = false;
1393  break;
1394  }
1395  }
1396 
1397  // adjust type if type deduction is not wanted
1398  if (not type_deduction)
1399  {
1400  // if array is wanted, do not create an object though possible
1401  if (manual_type == value_t::array)
1402  {
1403  is_an_object = false;
1404  }
1405 
1406  // if object is wanted but impossible, throw an exception
1407  if (manual_type == value_t::object and not is_an_object)
1408  {
1409  throw std::domain_error("cannot create object from initializer list");
1410  }
1411  }
1412 
1413  if (is_an_object)
1414  {
1415  // the initializer list is a list of pairs -> create object
1416  m_type = value_t::object;
1417  m_value = value_t::object;
1418 
1419  for (auto& element : init)
1420  {
1421  m_value.object->emplace(std::move(*(element[0].m_value.string)), std::move(element[1]));
1422  }
1423  }
1424  else
1425  {
1426  // the initializer list describes an array -> create array
1427  m_type = value_t::array;
1428  m_value.array = create<array_t>(std::move(init));
1429  }
1430  }
1431 
1466  static basic_json array(std::initializer_list<basic_json> init =
1467  std::initializer_list<basic_json>())
1468  {
1469  return basic_json(init, false, value_t::array);
1470  }
1471 
1506  static basic_json object(std::initializer_list<basic_json> init =
1507  std::initializer_list<basic_json>())
1508  {
1509  return basic_json(init, false, value_t::object);
1510  }
1511 
1530  basic_json(size_type cnt, const basic_json& val)
1531  : m_type(value_t::array)
1532  {
1533  m_value.array = create<array_t>(cnt, val);
1534  }
1535 
1568  template <class InputIT, typename
1569  std::enable_if<
1570  std::is_same<InputIT, typename basic_json_t::iterator>::value or
1571  std::is_same<InputIT, typename basic_json_t::const_iterator>::value
1572  , int>::type
1573  = 0>
1574  basic_json(InputIT first, InputIT last) : m_type(first.m_object->m_type)
1575  {
1576  // make sure iterator fits the current value
1577  if (first.m_object != last.m_object)
1578  {
1579  throw std::domain_error("iterators are not compatible");
1580  }
1581 
1582  // check if iterator range is complete for primitive values
1583  switch (m_type)
1584  {
1585  case value_t::boolean:
1586  case value_t::number_float:
1588  case value_t::string:
1589  {
1590  if (not first.m_it.primitive_iterator.is_begin() or not last.m_it.primitive_iterator.is_end())
1591  {
1592  throw std::out_of_range("iterators out of range");
1593  }
1594  break;
1595  }
1596 
1597  default:
1598  {
1599  break;
1600  }
1601  }
1602 
1603  switch (m_type)
1604  {
1606  {
1607  m_value.number_integer = first.m_object->m_value.number_integer;
1608  break;
1609  }
1610 
1611  case value_t::number_float:
1612  {
1613  m_value.number_float = first.m_object->m_value.number_float;
1614  break;
1615  }
1616 
1617  case value_t::boolean:
1618  {
1619  m_value.boolean = first.m_object->m_value.boolean;
1620  break;
1621  }
1622 
1623  case value_t::string:
1624  {
1625  m_value = *first.m_object->m_value.string;
1626  break;
1627  }
1628 
1629  case value_t::object:
1630  {
1631  m_value.object = create<object_t>(first.m_it.object_iterator, last.m_it.object_iterator);
1632  break;
1633  }
1634 
1635  case value_t::array:
1636  {
1637  m_value.array = create<array_t>(first.m_it.array_iterator, last.m_it.array_iterator);
1638  break;
1639  }
1640 
1641  default:
1642  {
1643  throw std::domain_error("cannot use construct with iterators from " + first.m_object->type_name());
1644  }
1645  }
1646  }
1647 
1649  // other constructors and destructor //
1651 
1672  basic_json(const basic_json& other)
1673  : m_type(other.m_type)
1674  {
1675  switch (m_type)
1676  {
1677  case value_t::object:
1678  {
1679  m_value = *other.m_value.object;
1680  break;
1681  }
1682 
1683  case value_t::array:
1684  {
1685  m_value = *other.m_value.array;
1686  break;
1687  }
1688 
1689  case value_t::string:
1690  {
1691  m_value = *other.m_value.string;
1692  break;
1693  }
1694 
1695  case value_t::boolean:
1696  {
1697  m_value = other.m_value.boolean;
1698  break;
1699  }
1700 
1702  {
1703  m_value = other.m_value.number_integer;
1704  break;
1705  }
1706 
1707  case value_t::number_float:
1708  {
1709  m_value = other.m_value.number_float;
1710  break;
1711  }
1712 
1713  default:
1714  {
1715  break;
1716  }
1717  }
1718  }
1719 
1738  basic_json(basic_json&& other) noexcept
1739  : m_type(std::move(other.m_type)),
1740  m_value(std::move(other.m_value))
1741  {
1742  // invalidate payload
1743  other.m_type = value_t::null;
1744  other.m_value = {};
1745  }
1746 
1768  reference& operator=(basic_json other) noexcept (
1769  std::is_nothrow_move_constructible<value_t>::value and
1770  std::is_nothrow_move_assignable<value_t>::value and
1771  std::is_nothrow_move_constructible<json_value>::value and
1772  std::is_nothrow_move_assignable<json_value>::value
1773  )
1774  {
1775  using std::swap;
1776  swap(m_type, other.m_type);
1777  swap(m_value, other.m_value);
1778  return *this;
1779  }
1780 
1795  {
1796  switch (m_type)
1797  {
1798  case value_t::object:
1799  {
1800  AllocatorType<object_t> alloc;
1801  alloc.destroy(m_value.object);
1802  alloc.deallocate(m_value.object, 1);
1803  break;
1804  }
1805 
1806  case value_t::array:
1807  {
1808  AllocatorType<array_t> alloc;
1809  alloc.destroy(m_value.array);
1810  alloc.deallocate(m_value.array, 1);
1811  break;
1812  }
1813 
1814  case value_t::string:
1815  {
1816  AllocatorType<string_t> alloc;
1817  alloc.destroy(m_value.string);
1818  alloc.deallocate(m_value.string, 1);
1819  break;
1820  }
1821 
1822  default:
1823  {
1824  // all other types need no specific destructor
1825  break;
1826  }
1827  }
1828  }
1829 
1831 
1832  public:
1834  // object inspection //
1836 
1839 
1863  string_t dump(const int indent = -1) const
1864  {
1865  std::stringstream ss;
1866 
1867  if (indent >= 0)
1868  {
1869  dump(ss, true, static_cast<unsigned int>(indent));
1870  }
1871  else
1872  {
1873  dump(ss, false, 0);
1874  }
1875 
1876  return ss.str();
1877  }
1878 
1894  value_t type() const noexcept
1895  {
1896  return m_type;
1897  }
1898 
1915  bool is_primitive() const noexcept
1916  {
1917  return is_null() or is_string() or is_boolean() or is_number();
1918  }
1919 
1935  bool is_structured() const noexcept
1936  {
1937  return is_array() or is_object();
1938  }
1939 
1954  bool is_null() const noexcept
1955  {
1956  return m_type == value_t::null;
1957  }
1958 
1973  bool is_boolean() const noexcept
1974  {
1975  return m_type == value_t::boolean;
1976  }
1977 
1997  bool is_number() const noexcept
1998  {
1999  return is_number_integer() or is_number_float();
2000  }
2001 
2020  bool is_number_integer() const noexcept
2021  {
2022  return m_type == value_t::number_integer;
2023  }
2024 
2043  bool is_number_float() const noexcept
2044  {
2045  return m_type == value_t::number_float;
2046  }
2047 
2062  bool is_object() const noexcept
2063  {
2064  return m_type == value_t::object;
2065  }
2066 
2081  bool is_array() const noexcept
2082  {
2083  return m_type == value_t::array;
2084  }
2085 
2100  bool is_string() const noexcept
2101  {
2102  return m_type == value_t::string;
2103  }
2104 
2124  bool is_discarded() const noexcept
2125  {
2126  return m_type == value_t::discarded;
2127  }
2128 
2144  operator value_t() const noexcept
2145  {
2146  return m_type;
2147  }
2148 
2150 
2151  private:
2153  // value access //
2155 
2157  template <class T, typename
2158  std::enable_if<
2159  std::is_convertible<typename object_t::key_type, typename T::key_type>::value and
2160  std::is_convertible<basic_json_t, typename T::mapped_type>::value
2161  , int>::type = 0>
2162  T get_impl(T*) const
2163  {
2164  if (is_object())
2165  {
2166  return T(m_value.object->begin(), m_value.object->end());
2167  }
2168  else
2169  {
2170  throw std::domain_error("type must be object, but is " + type_name());
2171  }
2172  }
2173 
2175  object_t get_impl(object_t*) const
2176  {
2177  if (is_object())
2178  {
2179  return *(m_value.object);
2180  }
2181  else
2182  {
2183  throw std::domain_error("type must be object, but is " + type_name());
2184  }
2185  }
2186 
2188  template <class T, typename
2189  std::enable_if<
2190  std::is_convertible<basic_json_t, typename T::value_type>::value and
2191  not std::is_same<basic_json_t, typename T::value_type>::value and
2192  not std::is_arithmetic<T>::value and
2193  not std::is_convertible<std::string, T>::value and
2194  not has_mapped_type<T>::value
2195  , int>::type = 0>
2196  T get_impl(T*) const
2197  {
2198  if (is_array())
2199  {
2200  T to_vector;
2201  std::transform(m_value.array->begin(), m_value.array->end(),
2202  std::inserter(to_vector, to_vector.end()), [](basic_json i)
2203  {
2204  return i.get<typename T::value_type>();
2205  });
2206  return to_vector;
2207  }
2208  else
2209  {
2210  throw std::domain_error("type must be array, but is " + type_name());
2211  }
2212  }
2213 
2215  template <class T, typename
2216  std::enable_if<
2217  std::is_convertible<basic_json_t, T>::value and
2218  not std::is_same<basic_json_t, T>::value
2219  , int>::type = 0>
2220  std::vector<T> get_impl(std::vector<T>*) const
2221  {
2222  if (is_array())
2223  {
2224  std::vector<T> to_vector;
2225  to_vector.reserve(m_value.array->size());
2226  std::transform(m_value.array->begin(), m_value.array->end(),
2227  std::inserter(to_vector, to_vector.end()), [](basic_json i)
2228  {
2229  return i.get<T>();
2230  });
2231  return to_vector;
2232  }
2233  else
2234  {
2235  throw std::domain_error("type must be array, but is " + type_name());
2236  }
2237  }
2238 
2240  template <class T, typename
2241  std::enable_if<
2242  std::is_same<basic_json, typename T::value_type>::value and
2243  not has_mapped_type<T>::value
2244  , int>::type = 0>
2245  T get_impl(T*) const
2246  {
2247  if (is_array())
2248  {
2249  return T(m_value.array->begin(), m_value.array->end());
2250  }
2251  else
2252  {
2253  throw std::domain_error("type must be array, but is " + type_name());
2254  }
2255  }
2256 
2258  array_t get_impl(array_t*) const
2259  {
2260  if (is_array())
2261  {
2262  return *(m_value.array);
2263  }
2264  else
2265  {
2266  throw std::domain_error("type must be array, but is " + type_name());
2267  }
2268  }
2269 
2271  template <typename T, typename
2272  std::enable_if<
2273  std::is_convertible<string_t, T>::value
2274  , int>::type = 0>
2275  T get_impl(T*) const
2276  {
2277  if (is_string())
2278  {
2279  return *m_value.string;
2280  }
2281  else
2282  {
2283  throw std::domain_error("type must be string, but is " + type_name());
2284  }
2285  }
2286 
2288  template<typename T, typename
2289  std::enable_if<
2290  std::is_arithmetic<T>::value
2291  , int>::type = 0>
2292  T get_impl(T*) const
2293  {
2294  switch (m_type)
2295  {
2297  {
2298  return static_cast<T>(m_value.number_integer);
2299  }
2300 
2301  case value_t::number_float:
2302  {
2303  return static_cast<T>(m_value.number_float);
2304  }
2305 
2306  default:
2307  {
2308  throw std::domain_error("type must be number, but is " + type_name());
2309  }
2310  }
2311  }
2312 
2314  boolean_t get_impl(boolean_t*) const
2315  {
2316  if (is_boolean())
2317  {
2318  return m_value.boolean;
2319  }
2320  else
2321  {
2322  throw std::domain_error("type must be boolean, but is " + type_name());
2323  }
2324  }
2325 
2327  object_t* get_impl_ptr(object_t*) noexcept
2328  {
2329  return is_object() ? m_value.object : nullptr;
2330  }
2331 
2333  const object_t* get_impl_ptr(const object_t*) const noexcept
2334  {
2335  return is_object() ? m_value.object : nullptr;
2336  }
2337 
2339  array_t* get_impl_ptr(array_t*) noexcept
2340  {
2341  return is_array() ? m_value.array : nullptr;
2342  }
2343 
2345  const array_t* get_impl_ptr(const array_t*) const noexcept
2346  {
2347  return is_array() ? m_value.array : nullptr;
2348  }
2349 
2351  string_t* get_impl_ptr(string_t*) noexcept
2352  {
2353  return is_string() ? m_value.string : nullptr;
2354  }
2355 
2357  const string_t* get_impl_ptr(const string_t*) const noexcept
2358  {
2359  return is_string() ? m_value.string : nullptr;
2360  }
2361 
2363  boolean_t* get_impl_ptr(boolean_t*) noexcept
2364  {
2365  return is_boolean() ? &m_value.boolean : nullptr;
2366  }
2367 
2369  const boolean_t* get_impl_ptr(const boolean_t*) const noexcept
2370  {
2371  return is_boolean() ? &m_value.boolean : nullptr;
2372  }
2373 
2375  number_integer_t* get_impl_ptr(number_integer_t*) noexcept
2376  {
2377  return is_number_integer() ? &m_value.number_integer : nullptr;
2378  }
2379 
2381  const number_integer_t* get_impl_ptr(const number_integer_t*) const noexcept
2382  {
2383  return is_number_integer() ? &m_value.number_integer : nullptr;
2384  }
2385 
2387  number_float_t* get_impl_ptr(number_float_t*) noexcept
2388  {
2389  return is_number_float() ? &m_value.number_float : nullptr;
2390  }
2391 
2393  const number_float_t* get_impl_ptr(const number_float_t*) const noexcept
2394  {
2395  return is_number_float() ? &m_value.number_float : nullptr;
2396  }
2397 
2398  public:
2399 
2402 
2436  template<typename ValueType, typename
2437  std::enable_if<
2438  not std::is_pointer<ValueType>::value
2439  , int>::type = 0>
2440  ValueType get() const
2441  {
2442  return get_impl(static_cast<ValueType*>(nullptr));
2443  }
2444 
2471  template<typename PointerType, typename
2472  std::enable_if<
2473  std::is_pointer<PointerType>::value
2474  , int>::type = 0>
2475  PointerType get() noexcept
2476  {
2477  // delegate the call to get_ptr
2478  return get_ptr<PointerType>();
2479  }
2480 
2485  template<typename PointerType, typename
2486  std::enable_if<
2487  std::is_pointer<PointerType>::value
2488  , int>::type = 0>
2489  const PointerType get() const noexcept
2490  {
2491  // delegate the call to get_ptr
2492  return get_ptr<PointerType>();
2493  }
2494 
2520  template<typename PointerType, typename
2521  std::enable_if<
2522  std::is_pointer<PointerType>::value
2523  , int>::type = 0>
2524  PointerType get_ptr() noexcept
2525  {
2526  // delegate the call to get_impl_ptr<>()
2527  return get_impl_ptr(static_cast<PointerType>(nullptr));
2528  }
2529 
2534  template<typename PointerType, typename
2535  std::enable_if<
2536  std::is_pointer<PointerType>::value
2537  and std::is_const<typename std::remove_pointer<PointerType>::type>::value
2538  , int>::type = 0>
2539  const PointerType get_ptr() const noexcept
2540  {
2541  // delegate the call to get_impl_ptr<>() const
2542  return get_impl_ptr(static_cast<const PointerType>(nullptr));
2543  }
2544 
2573  template<typename ValueType, typename
2574  std::enable_if<
2575  not std::is_pointer<ValueType>::value
2576  and not std::is_same<ValueType, typename string_t::value_type>::value
2577  and not std::is_same<ValueType, std::initializer_list<typename string_t::value_type>>::value
2578  , int>::type = 0>
2579  operator ValueType() const
2580  {
2581  // delegate the call to get<>() const
2582  return get<ValueType>();
2583  }
2584 
2586 
2587 
2589  // element access //
2591 
2594 
2617  {
2618  // at only works for arrays
2619  if (is_array())
2620  {
2621  return m_value.array->at(idx);
2622  }
2623  else
2624  {
2625  throw std::domain_error("cannot use at() with " + type_name());
2626  }
2627  }
2628 
2651  {
2652  // at only works for arrays
2653  if (is_array())
2654  {
2655  return m_value.array->at(idx);
2656  }
2657  else
2658  {
2659  throw std::domain_error("cannot use at() with " + type_name());
2660  }
2661  }
2662 
2688  reference at(const typename object_t::key_type& key)
2689  {
2690  // at only works for objects
2691  if (is_object())
2692  {
2693  return m_value.object->at(key);
2694  }
2695  else
2696  {
2697  throw std::domain_error("cannot use at() with " + type_name());
2698  }
2699  }
2700 
2726  const_reference at(const typename object_t::key_type& key) const
2727  {
2728  // at only works for objects
2729  if (is_object())
2730  {
2731  return m_value.object->at(key);
2732  }
2733  else
2734  {
2735  throw std::domain_error("cannot use at() with " + type_name());
2736  }
2737  }
2738 
2764  {
2765  // implicitly convert null to object
2766  if (is_null())
2767  {
2768  m_type = value_t::array;
2769  m_value.array = create<array_t>();
2770  }
2771 
2772  // [] only works for arrays
2773  if (is_array())
2774  {
2775  for (size_t i = m_value.array->size(); i <= idx; ++i)
2776  {
2777  m_value.array->push_back(basic_json());
2778  }
2779 
2780  return m_value.array->operator[](idx);
2781  }
2782  else
2783  {
2784  throw std::domain_error("cannot use operator[] with " + type_name());
2785  }
2786  }
2787 
2807  {
2808  // at only works for arrays
2809  if (is_array())
2810  {
2811  return m_value.array->operator[](idx);
2812  }
2813  else
2814  {
2815  throw std::domain_error("cannot use operator[] with " + type_name());
2816  }
2817  }
2818 
2845  reference operator[](const typename object_t::key_type& key)
2846  {
2847  // implicitly convert null to object
2848  if (is_null())
2849  {
2850  m_type = value_t::object;
2851  m_value.object = create<object_t>();
2852  }
2853 
2854  // [] only works for objects
2855  if (is_object())
2856  {
2857  return m_value.object->operator[](key);
2858  }
2859  else
2860  {
2861  throw std::domain_error("cannot use operator[] with " + type_name());
2862  }
2863  }
2864 
2893  template<typename T, std::size_t n>
2894  reference operator[](const T (&key)[n])
2895  {
2896  // implicitly convert null to object
2897  if (is_null())
2898  {
2899  m_type = value_t::object;
2900  m_value = value_t::object;
2901  }
2902 
2903  // at only works for objects
2904  if (is_object())
2905  {
2906  return m_value.object->operator[](key);
2907  }
2908  else
2909  {
2910  throw std::domain_error("cannot use operator[] with " + type_name());
2911  }
2912  }
2913 
2961  template <class ValueType, typename
2962  std::enable_if<
2963  std::is_convertible<basic_json_t, ValueType>::value
2964  , int>::type = 0>
2965  ValueType value(const typename object_t::key_type& key, ValueType default_value) const
2966  {
2967  // at only works for objects
2968  if (is_object())
2969  {
2970  // if key is found, return value and given default value otherwise
2971  const auto it = find(key);
2972  if (it != end())
2973  {
2974  return *it;
2975  }
2976  else
2977  {
2978  return default_value;
2979  }
2980  }
2981  else
2982  {
2983  throw std::domain_error("cannot use value() with " + type_name());
2984  }
2985  }
2986 
2991  string_t value(const typename object_t::key_type& key, const char* default_value) const
2992  {
2993  return value(key, string_t(default_value));
2994  }
2995 
3017  {
3018  return *begin();
3019  }
3020 
3025  {
3026  return *cbegin();
3027  }
3028 
3051  {
3052  auto tmp = end();
3053  --tmp;
3054  return *tmp;
3055  }
3056 
3061  {
3062  auto tmp = cend();
3063  --tmp;
3064  return *tmp;
3065  }
3066 
3109  template <class InteratorType, typename
3110  std::enable_if<
3111  std::is_same<InteratorType, typename basic_json_t::iterator>::value or
3112  std::is_same<InteratorType, typename basic_json_t::const_iterator>::value
3113  , int>::type
3114  = 0>
3115  InteratorType erase(InteratorType pos)
3116  {
3117  // make sure iterator fits the current value
3118  if (this != pos.m_object)
3119  {
3120  throw std::domain_error("iterator does not fit current value");
3121  }
3122 
3123  InteratorType result = end();
3124 
3125  switch (m_type)
3126  {
3127  case value_t::boolean:
3128  case value_t::number_float:
3130  case value_t::string:
3131  {
3132  if (not pos.m_it.primitive_iterator.is_begin())
3133  {
3134  throw std::out_of_range("iterator out of range");
3135  }
3136 
3137  if (is_string())
3138  {
3139  delete m_value.string;
3140  m_value.string = nullptr;
3141  }
3142 
3143  m_type = value_t::null;
3144  break;
3145  }
3146 
3147  case value_t::object:
3148  {
3149  result.m_it.object_iterator = m_value.object->erase(pos.m_it.object_iterator);
3150  break;
3151  }
3152 
3153  case value_t::array:
3154  {
3155  result.m_it.array_iterator = m_value.array->erase(pos.m_it.array_iterator);
3156  break;
3157  }
3158 
3159  default:
3160  {
3161  throw std::domain_error("cannot use erase() with " + type_name());
3162  }
3163  }
3164 
3165  return result;
3166  }
3167 
3210  template <class InteratorType, typename
3211  std::enable_if<
3212  std::is_same<InteratorType, typename basic_json_t::iterator>::value or
3213  std::is_same<InteratorType, typename basic_json_t::const_iterator>::value
3214  , int>::type
3215  = 0>
3216  InteratorType erase(InteratorType first, InteratorType last)
3217  {
3218  // make sure iterator fits the current value
3219  if (this != first.m_object or this != last.m_object)
3220  {
3221  throw std::domain_error("iterators do not fit current value");
3222  }
3223 
3224  InteratorType result = end();
3225 
3226  switch (m_type)
3227  {
3228  case value_t::boolean:
3229  case value_t::number_float:
3231  case value_t::string:
3232  {
3233  if (not first.m_it.primitive_iterator.is_begin() or not last.m_it.primitive_iterator.is_end())
3234  {
3235  throw std::out_of_range("iterators out of range");
3236  }
3237 
3238  if (is_string())
3239  {
3240  delete m_value.string;
3241  m_value.string = nullptr;
3242  }
3243 
3244  m_type = value_t::null;
3245  break;
3246  }
3247 
3248  case value_t::object:
3249  {
3250  result.m_it.object_iterator = m_value.object->erase(first.m_it.object_iterator,
3251  last.m_it.object_iterator);
3252  break;
3253  }
3254 
3255  case value_t::array:
3256  {
3257  result.m_it.array_iterator = m_value.array->erase(first.m_it.array_iterator,
3258  last.m_it.array_iterator);
3259  break;
3260  }
3261 
3262  default:
3263  {
3264  throw std::domain_error("cannot use erase with " + type_name());
3265  }
3266  }
3267 
3268  return result;
3269  }
3270 
3296  size_type erase(const typename object_t::key_type& key)
3297  {
3298  // this erase only works for objects
3299  if (is_object())
3300  {
3301  return m_value.object->erase(key);
3302  }
3303  else
3304  {
3305  throw std::domain_error("cannot use erase() with " + type_name());
3306  }
3307  }
3308 
3331  void erase(const size_type idx)
3332  {
3333  // this erase only works for arrays
3334  if (is_array())
3335  {
3336  if (idx >= size())
3337  {
3338  throw std::out_of_range("index out of range");
3339  }
3340 
3341  m_value.array->erase(m_value.array->begin() + static_cast<difference_type>(idx));
3342  }
3343  else
3344  {
3345  throw std::domain_error("cannot use erase() with " + type_name());
3346  }
3347  }
3348 
3366  iterator find(typename object_t::key_type key)
3367  {
3368  auto result = end();
3369 
3370  if (is_object())
3371  {
3372  result.m_it.object_iterator = m_value.object->find(key);
3373  }
3374 
3375  return result;
3376  }
3377 
3382  const_iterator find(typename object_t::key_type key) const
3383  {
3384  auto result = cend();
3385 
3386  if (is_object())
3387  {
3388  result.m_it.object_iterator = m_value.object->find(key);
3389  }
3390 
3391  return result;
3392  }
3393 
3412  size_type count(typename object_t::key_type key) const
3413  {
3414  // return 0 for all nonobject types
3415  return is_object() ? m_value.object->count(key) : 0;
3416  }
3417 
3419 
3420 
3422  // iterators //
3424 
3427 
3447  {
3448  iterator result(this);
3449  result.set_begin();
3450  return result;
3451  }
3452 
3457  {
3458  return cbegin();
3459  }
3460 
3481  {
3482  const_iterator result(this);
3483  result.set_begin();
3484  return result;
3485  }
3486 
3506  {
3507  iterator result(this);
3508  result.set_end();
3509  return result;
3510  }
3511 
3516  {
3517  return cend();
3518  }
3519 
3540  {
3541  const_iterator result(this);
3542  result.set_end();
3543  return result;
3544  }
3545 
3564  {
3565  return reverse_iterator(end());
3566  }
3567 
3572  {
3573  return crbegin();
3574  }
3575 
3595  {
3596  return reverse_iterator(begin());
3597  }
3598 
3603  {
3604  return crend();
3605  }
3606 
3626  {
3627  return const_reverse_iterator(cend());
3628  }
3629 
3649  {
3650  return const_reverse_iterator(cbegin());
3651  }
3652 
3654 
3655 
3657  // capacity //
3659 
3662 
3692  bool empty() const noexcept
3693  {
3694  switch (m_type)
3695  {
3696  case value_t::null:
3697  {
3698  // null values are empty
3699  return true;
3700  }
3701 
3702  case value_t::array:
3703  {
3704  return m_value.array->empty();
3705  }
3706 
3707  case value_t::object:
3708  {
3709  return m_value.object->empty();
3710  }
3711 
3712  default:
3713  {
3714  // all other types are nonempty
3715  return false;
3716  }
3717  }
3718  }
3719 
3749  size_type size() const noexcept
3750  {
3751  switch (m_type)
3752  {
3753  case value_t::null:
3754  {
3755  // null values are empty
3756  return 0;
3757  }
3758 
3759  case value_t::array:
3760  {
3761  return m_value.array->size();
3762  }
3763 
3764  case value_t::object:
3765  {
3766  return m_value.object->size();
3767  }
3768 
3769  default:
3770  {
3771  // all other types have size 1
3772  return 1;
3773  }
3774  }
3775  }
3776 
3809  size_type max_size() const noexcept
3810  {
3811  switch (m_type)
3812  {
3813  case value_t::array:
3814  {
3815  return m_value.array->max_size();
3816  }
3817 
3818  case value_t::object:
3819  {
3820  return m_value.object->max_size();
3821  }
3822 
3823  default:
3824  {
3825  // all other types have max_size() == size()
3826  return size();
3827  }
3828  }
3829  }
3830 
3832 
3833 
3835  // modifiers //
3837 
3840 
3866  void clear() noexcept
3867  {
3868  switch (m_type)
3869  {
3871  {
3872  m_value.number_integer = 0;
3873  break;
3874  }
3875 
3876  case value_t::number_float:
3877  {
3878  m_value.number_float = 0.0;
3879  break;
3880  }
3881 
3882  case value_t::boolean:
3883  {
3884  m_value.boolean = false;
3885  break;
3886  }
3887 
3888  case value_t::string:
3889  {
3890  m_value.string->clear();
3891  break;
3892  }
3893 
3894  case value_t::array:
3895  {
3896  m_value.array->clear();
3897  break;
3898  }
3899 
3900  case value_t::object:
3901  {
3902  m_value.object->clear();
3903  break;
3904  }
3905 
3906  default:
3907  {
3908  break;
3909  }
3910  }
3911  }
3912 
3932  void push_back(basic_json&& val)
3933  {
3934  // push_back only works for null objects or arrays
3935  if (not(is_null() or is_array()))
3936  {
3937  throw std::domain_error("cannot use push_back() with " + type_name());
3938  }
3939 
3940  // transform null object into an array
3941  if (is_null())
3942  {
3943  m_type = value_t::array;
3944  m_value = value_t::array;
3945  }
3946 
3947  // add element to array (move semantics)
3948  m_value.array->push_back(std::move(val));
3949  // invalidate object
3950  val.m_type = value_t::null;
3951  }
3952 
3957  reference operator+=(basic_json&& val)
3958  {
3959  push_back(std::move(val));
3960  return *this;
3961  }
3962 
3967  void push_back(const basic_json& val)
3968  {
3969  // push_back only works for null objects or arrays
3970  if (not(is_null() or is_array()))
3971  {
3972  throw std::domain_error("cannot use push_back() with " + type_name());
3973  }
3974 
3975  // transform null object into an array
3976  if (is_null())
3977  {
3978  m_type = value_t::array;
3979  m_value = value_t::array;
3980  }
3981 
3982  // add element to array
3983  m_value.array->push_back(val);
3984  }
3985 
3990  reference operator+=(const basic_json& val)
3991  {
3992  push_back(val);
3993  return *this;
3994  }
3995 
4016  void push_back(const typename object_t::value_type& val)
4017  {
4018  // push_back only works for null objects or objects
4019  if (not(is_null() or is_object()))
4020  {
4021  throw std::domain_error("cannot use push_back() with " + type_name());
4022  }
4023 
4024  // transform null object into an object
4025  if (is_null())
4026  {
4027  m_type = value_t::object;
4028  m_value = value_t::object;
4029  }
4030 
4031  // add element to array
4032  m_value.object->insert(val);
4033  }
4034 
4039  reference operator+=(const typename object_t::value_type& val)
4040  {
4041  push_back(val);
4042  return operator[](val.first);
4043  }
4044 
4065  iterator insert(const_iterator pos, const basic_json& val)
4066  {
4067  // insert only works for arrays
4068  if (is_array())
4069  {
4070  // check if iterator pos fits to this JSON value
4071  if (pos.m_object != this)
4072  {
4073  throw std::domain_error("iterator does not fit current value");
4074  }
4075 
4076  // insert to array and return iterator
4077  iterator result(this);
4078  result.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator, val);
4079  return result;
4080  }
4081  else
4082  {
4083  throw std::domain_error("cannot use insert() with " + type_name());
4084  }
4085  }
4086 
4091  iterator insert(const_iterator pos, basic_json&& val)
4092  {
4093  return insert(pos, val);
4094  }
4095 
4118  iterator insert(const_iterator pos, size_type cnt, const basic_json& val)
4119  {
4120  // insert only works for arrays
4121  if (is_array())
4122  {
4123  // check if iterator pos fits to this JSON value
4124  if (pos.m_object != this)
4125  {
4126  throw std::domain_error("iterator does not fit current value");
4127  }
4128 
4129  // insert to array and return iterator
4130  iterator result(this);
4131  result.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator, cnt, val);
4132  return result;
4133  }
4134  else
4135  {
4136  throw std::domain_error("cannot use insert() with " + type_name());
4137  }
4138  }
4139 
4167  {
4168  // insert only works for arrays
4169  if (not is_array())
4170  {
4171  throw std::domain_error("cannot use insert() with " + type_name());
4172  }
4173 
4174  // check if iterator pos fits to this JSON value
4175  if (pos.m_object != this)
4176  {
4177  throw std::domain_error("iterator does not fit current value");
4178  }
4179 
4180  if (first.m_object != last.m_object)
4181  {
4182  throw std::domain_error("iterators do not fit");
4183  }
4184 
4185  if (first.m_object == this or last.m_object == this)
4186  {
4187  throw std::domain_error("passed iterators may not belong to container");
4188  }
4189 
4190  // insert to array and return iterator
4191  iterator result(this);
4192  result.m_it.array_iterator = m_value.array->insert(
4193  pos.m_it.array_iterator,
4194  first.m_it.array_iterator,
4195  last.m_it.array_iterator);
4196  return result;
4197  }
4198 
4220  iterator insert(const_iterator pos, std::initializer_list<basic_json> ilist)
4221  {
4222  // insert only works for arrays
4223  if (not is_array())
4224  {
4225  throw std::domain_error("cannot use insert() with " + type_name());
4226  }
4227 
4228  // check if iterator pos fits to this JSON value
4229  if (pos.m_object != this)
4230  {
4231  throw std::domain_error("iterator does not fit current value");
4232  }
4233 
4234  // insert to array and return iterator
4235  iterator result(this);
4236  result.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator, ilist);
4237  return result;
4238  }
4239 
4257  void swap(reference other) noexcept (
4258  std::is_nothrow_move_constructible<value_t>::value and
4259  std::is_nothrow_move_assignable<value_t>::value and
4260  std::is_nothrow_move_constructible<json_value>::value and
4261  std::is_nothrow_move_assignable<json_value>::value
4262  )
4263  {
4264  std::swap(m_type, other.m_type);
4265  std::swap(m_value, other.m_value);
4266  }
4267 
4287  void swap(array_t& other)
4288  {
4289  // swap only works for arrays
4290  if (is_array())
4291  {
4292  std::swap(*(m_value.array), other);
4293  }
4294  else
4295  {
4296  throw std::domain_error("cannot use swap() with " + type_name());
4297  }
4298  }
4299 
4319  void swap(object_t& other)
4320  {
4321  // swap only works for objects
4322  if (is_object())
4323  {
4324  std::swap(*(m_value.object), other);
4325  }
4326  else
4327  {
4328  throw std::domain_error("cannot use swap() with " + type_name());
4329  }
4330  }
4331 
4351  void swap(string_t& other)
4352  {
4353  // swap only works for strings
4354  if (is_string())
4355  {
4356  std::swap(*(m_value.string), other);
4357  }
4358  else
4359  {
4360  throw std::domain_error("cannot use swap() with " + type_name());
4361  }
4362  }
4363 
4365 
4366 
4368  // lexicographical comparison operators //
4370 
4373 
4374  private:
4384  friend bool operator<(const value_t lhs, const value_t rhs)
4385  {
4386  static constexpr std::array<uint8_t, 7> order = {{
4387  0, // null
4388  3, // object
4389  4, // array
4390  5, // string
4391  1, // boolean
4392  2, // integer
4393  2 // float
4394  }
4395  };
4396 
4397  // discarded values are not comparable
4398  if (lhs == value_t::discarded or rhs == value_t::discarded)
4399  {
4400  return false;
4401  }
4402 
4403  return order[static_cast<std::size_t>(lhs)] < order[static_cast<std::size_t>(rhs)];
4404  }
4405 
4406  public:
4430  friend bool operator==(const_reference lhs, const_reference rhs) noexcept
4431  {
4432  const auto lhs_type = lhs.type();
4433  const auto rhs_type = rhs.type();
4434 
4435  if (lhs_type == rhs_type)
4436  {
4437  switch (lhs_type)
4438  {
4439  case value_t::array:
4440  return *lhs.m_value.array == *rhs.m_value.array;
4441  case value_t::object:
4442  return *lhs.m_value.object == *rhs.m_value.object;
4443  case value_t::null:
4444  return true;
4445  case value_t::string:
4446  return *lhs.m_value.string == *rhs.m_value.string;
4447  case value_t::boolean:
4448  return lhs.m_value.boolean == rhs.m_value.boolean;
4450  return lhs.m_value.number_integer == rhs.m_value.number_integer;
4451  case value_t::number_float:
4452  return approx(lhs.m_value.number_float, rhs.m_value.number_float);
4453  default:
4454  return false;
4455  }
4456  }
4457  else if (lhs_type == value_t::number_integer and rhs_type == value_t::number_float)
4458  {
4459  return approx(static_cast<number_float_t>(lhs.m_value.number_integer),
4460  rhs.m_value.number_float);
4461  }
4462  else if (lhs_type == value_t::number_float and rhs_type == value_t::number_integer)
4463  {
4464  return approx(lhs.m_value.number_float,
4465  static_cast<number_float_t>(rhs.m_value.number_integer));
4466  }
4467  return false;
4468  }
4469 
4488  friend bool operator==(const_reference v, std::nullptr_t) noexcept
4489  {
4490  return v.is_null();
4491  }
4492 
4497  friend bool operator==(std::nullptr_t, const_reference v) noexcept
4498  {
4499  return v.is_null();
4500  }
4501 
4518  friend bool operator!=(const_reference lhs, const_reference rhs) noexcept
4519  {
4520  return not (lhs == rhs);
4521  }
4522 
4541  friend bool operator!=(const_reference v, std::nullptr_t) noexcept
4542  {
4543  return not v.is_null();
4544  }
4545 
4550  friend bool operator!=(std::nullptr_t, const_reference v) noexcept
4551  {
4552  return not v.is_null();
4553  }
4554 
4579  friend bool operator<(const_reference lhs, const_reference rhs) noexcept
4580  {
4581  const auto lhs_type = lhs.type();
4582  const auto rhs_type = rhs.type();
4583 
4584  if (lhs_type == rhs_type)
4585  {
4586  switch (lhs_type)
4587  {
4588  case value_t::array:
4589  return *lhs.m_value.array < *rhs.m_value.array;
4590  case value_t::object:
4591  return *lhs.m_value.object < *rhs.m_value.object;
4592  case value_t::null:
4593  return false;
4594  case value_t::string:
4595  return *lhs.m_value.string < *rhs.m_value.string;
4596  case value_t::boolean:
4597  return lhs.m_value.boolean < rhs.m_value.boolean;
4599  return lhs.m_value.number_integer < rhs.m_value.number_integer;
4600  case value_t::number_float:
4601  return lhs.m_value.number_float < rhs.m_value.number_float;
4602  default:
4603  return false;
4604  }
4605  }
4606  else if (lhs_type == value_t::number_integer and rhs_type == value_t::number_float)
4607  {
4608  return static_cast<number_float_t>(lhs.m_value.number_integer) <
4609  rhs.m_value.number_float;
4610  }
4611  else if (lhs_type == value_t::number_float and rhs_type == value_t::number_integer)
4612  {
4613  return lhs.m_value.number_float <
4614  static_cast<number_float_t>(rhs.m_value.number_integer);
4615  }
4616 
4617  // We only reach this line if we cannot compare values. In that case,
4618  // we compare types. Note we have to call the operator explicitly,
4619  // because MSVC has problems otherwise.
4620  return operator<(lhs_type, rhs_type);
4621  }
4622 
4640  friend bool operator<=(const_reference lhs, const_reference rhs) noexcept
4641  {
4642  return not (rhs < lhs);
4643  }
4644 
4662  friend bool operator>(const_reference lhs, const_reference rhs) noexcept
4663  {
4664  return not (lhs <= rhs);
4665  }
4666 
4684  friend bool operator>=(const_reference lhs, const_reference rhs) noexcept
4685  {
4686  return not (lhs < rhs);
4687  }
4688 
4690 
4691 
4693  // serialization //
4695 
4698 
4721  friend std::ostream& operator<<(std::ostream& o, const basic_json& j)
4722  {
4723  // read width member and use it as indentation parameter if nonzero
4724  const bool pretty_print = (o.width() > 0);
4725  const auto indentation = (pretty_print ? o.width() : 0);
4726 
4727  // reset width to 0 for subsequent calls to this stream
4728  o.width(0);
4729 
4730  // do the actual serialization
4731  j.dump(o, pretty_print, static_cast<unsigned int>(indentation));
4732  return o;
4733  }
4734 
4739  friend std::ostream& operator>>(const basic_json& j, std::ostream& o)
4740  {
4741  return o << j;
4742  }
4743 
4745 
4746 
4748  // deserialization //
4750 
4753 
4778  static basic_json parse(const string_t& s, parser_callback_t cb = nullptr)
4779  {
4780  return parser(s, cb).parse();
4781  }
4782 
4807  static basic_json parse(std::istream& i, parser_callback_t cb = nullptr)
4808  {
4809  return parser(i, cb).parse();
4810  }
4811 
4815  static basic_json parse(std::istream&& i, parser_callback_t cb = nullptr)
4816  {
4817  return parser(i, cb).parse();
4818  }
4819 
4843  friend std::istream& operator<<(basic_json& j, std::istream& i)
4844  {
4845  j = parser(i).parse();
4846  return i;
4847  }
4848 
4853  friend std::istream& operator>>(std::istream& i, basic_json& j)
4854  {
4855  j = parser(i).parse();
4856  return i;
4857  }
4858 
4860 
4861 
4862  private:
4864  // convenience functions //
4866 
4868  string_t type_name() const
4869  {
4870  switch (m_type)
4871  {
4872  case value_t::null:
4873  return "null";
4874  case value_t::object:
4875  return "object";
4876  case value_t::array:
4877  return "array";
4878  case value_t::string:
4879  return "string";
4880  case value_t::boolean:
4881  return "boolean";
4882  case value_t::discarded:
4883  return "discarded";
4884  default:
4885  return "number";
4886  }
4887  }
4888 
4897  static std::size_t extra_space(const string_t& s) noexcept
4898  {
4899  std::size_t result = 0;
4900 
4901  for (const auto& c : s)
4902  {
4903  switch (c)
4904  {
4905  case '"':
4906  case '\\':
4907  case '\b':
4908  case '\f':
4909  case '\n':
4910  case '\r':
4911  case '\t':
4912  {
4913  // from c (1 byte) to \x (2 bytes)
4914  result += 1;
4915  break;
4916  }
4917 
4918  default:
4919  {
4920  if (c >= 0x00 and c <= 0x1f)
4921  {
4922  // from c (1 byte) to \uxxxx (6 bytes)
4923  result += 5;
4924  }
4925  break;
4926  }
4927  }
4928  }
4929 
4930  return result;
4931  }
4932 
4946  static string_t escape_string(const string_t& s) noexcept
4947  {
4948  const auto space = extra_space(s);
4949  if (space == 0)
4950  {
4951  return s;
4952  }
4953 
4954  // create a result string of necessary size
4955  string_t result(s.size() + space, '\\');
4956  std::size_t pos = 0;
4957 
4958  for (const auto& c : s)
4959  {
4960  switch (c)
4961  {
4962  // quotation mark (0x22)
4963  case '"':
4964  {
4965  result[pos + 1] = '"';
4966  pos += 2;
4967  break;
4968  }
4969 
4970  // reverse solidus (0x5c)
4971  case '\\':
4972  {
4973  // nothing to change
4974  pos += 2;
4975  break;
4976  }
4977 
4978  // backspace (0x08)
4979  case '\b':
4980  {
4981  result[pos + 1] = 'b';
4982  pos += 2;
4983  break;
4984  }
4985 
4986  // formfeed (0x0c)
4987  case '\f':
4988  {
4989  result[pos + 1] = 'f';
4990  pos += 2;
4991  break;
4992  }
4993 
4994  // newline (0x0a)
4995  case '\n':
4996  {
4997  result[pos + 1] = 'n';
4998  pos += 2;
4999  break;
5000  }
5001 
5002  // carriage return (0x0d)
5003  case '\r':
5004  {
5005  result[pos + 1] = 'r';
5006  pos += 2;
5007  break;
5008  }
5009 
5010  // horizontal tab (0x09)
5011  case '\t':
5012  {
5013  result[pos + 1] = 't';
5014  pos += 2;
5015  break;
5016  }
5017 
5018  default:
5019  {
5020  if (c >= 0x00 and c <= 0x1f)
5021  {
5022  // convert a number 0..15 to its hex representation (0..f)
5023  auto hexify = [](const char v) -> char
5024  {
5025  return (v < 10) ? ('0' + v) : ('a' + v - 10);
5026  };
5027 
5028  // print character c as \uxxxx
5029  for (const char m :
5030  { 'u', '0', '0', hexify(c >> 4), hexify(c & 0x0f)
5031  })
5032  {
5033  result[++pos] = m;
5034  }
5035 
5036  ++pos;
5037  }
5038  else
5039  {
5040  // all other characters are added as-is
5041  result[pos++] = c;
5042  }
5043  break;
5044  }
5045  }
5046  }
5047 
5048  return result;
5049  }
5050 
5068  void dump(std::ostream& o,
5069  const bool pretty_print,
5070  const unsigned int indent_step,
5071  const unsigned int current_indent = 0) const
5072  {
5073  // variable to hold indentation for recursive calls
5074  unsigned int new_indent = current_indent;
5075 
5076  switch (m_type)
5077  {
5078  case value_t::object:
5079  {
5080  if (m_value.object->empty())
5081  {
5082  o << "{}";
5083  return;
5084  }
5085 
5086  o << "{";
5087 
5088  // increase indentation
5089  if (pretty_print)
5090  {
5091  new_indent += indent_step;
5092  o << "\n";
5093  }
5094 
5095  for (auto i = m_value.object->cbegin(); i != m_value.object->cend(); ++i)
5096  {
5097  if (i != m_value.object->cbegin())
5098  {
5099  o << (pretty_print ? ",\n" : ",");
5100  }
5101  o << string_t(new_indent, ' ') << "\""
5102  << escape_string(i->first) << "\":"
5103  << (pretty_print ? " " : "");
5104  i->second.dump(o, pretty_print, indent_step, new_indent);
5105  }
5106 
5107  // decrease indentation
5108  if (pretty_print)
5109  {
5110  new_indent -= indent_step;
5111  o << "\n";
5112  }
5113 
5114  o << string_t(new_indent, ' ') + "}";
5115  return;
5116  }
5117 
5118  case value_t::array:
5119  {
5120  if (m_value.array->empty())
5121  {
5122  o << "[]";
5123  return;
5124  }
5125 
5126  o << "[";
5127 
5128  // increase indentation
5129  if (pretty_print)
5130  {
5131  new_indent += indent_step;
5132  o << "\n";
5133  }
5134 
5135  for (auto i = m_value.array->cbegin(); i != m_value.array->cend(); ++i)
5136  {
5137  if (i != m_value.array->cbegin())
5138  {
5139  o << (pretty_print ? ",\n" : ",");
5140  }
5141  o << string_t(new_indent, ' ');
5142  i->dump(o, pretty_print, indent_step, new_indent);
5143  }
5144 
5145  // decrease indentation
5146  if (pretty_print)
5147  {
5148  new_indent -= indent_step;
5149  o << "\n";
5150  }
5151 
5152  o << string_t(new_indent, ' ') << "]";
5153  return;
5154  }
5155 
5156  case value_t::string:
5157  {
5158  o << string_t("\"") << escape_string(*m_value.string) << "\"";
5159  return;
5160  }
5161 
5162  case value_t::boolean:
5163  {
5164  o << (m_value.boolean ? "true" : "false");
5165  return;
5166  }
5167 
5169  {
5170  o << m_value.number_integer;
5171  return;
5172  }
5173 
5174  case value_t::number_float:
5175  {
5176  // 15 digits of precision allows round-trip IEEE 754
5177  // string->double->string; to be safe, we read this value from
5178  // std::numeric_limits<number_float_t>::digits10
5179  o << std::setprecision(std::numeric_limits<number_float_t>::digits10) << m_value.number_float;
5180  return;
5181  }
5182 
5183  case value_t::discarded:
5184  {
5185  o << "<discarded>";
5186  return;
5187  }
5188 
5189  case value_t::null:
5190  {
5191  o << "null";
5192  return;
5193  }
5194  }
5195  }
5196 
5197  private:
5199  // member variables //
5201 
5203  value_t m_type = value_t::null;
5204 
5206  json_value m_value = {};
5207 
5208 
5209  private:
5211  // iterators //
5213 
5223  class primitive_iterator_t
5224  {
5225  public:
5227  void set_begin()
5228  {
5229  m_it = begin_value;
5230  }
5231 
5233  void set_end()
5234  {
5235  m_it = end_value;
5236  }
5237 
5239  bool is_begin() const
5240  {
5241  return (m_it == begin_value);
5242  }
5243 
5245  bool is_end() const
5246  {
5247  return (m_it == end_value);
5248  }
5249 
5251  operator difference_type& ()
5252  {
5253  return m_it;
5254  }
5255 
5257  operator difference_type () const
5258  {
5259  return m_it;
5260  }
5261 
5262  private:
5263  static constexpr difference_type begin_value = 0;
5264  static constexpr difference_type end_value = begin_value + 1;
5265 
5267  difference_type m_it = std::numeric_limits<std::ptrdiff_t>::denorm_min();
5268  };
5269 
5277  struct internal_iterator
5278  {
5280  typename object_t::iterator object_iterator;
5282  typename array_t::iterator array_iterator;
5284  primitive_iterator_t primitive_iterator;
5285 
5287  internal_iterator()
5288  : object_iterator(), array_iterator(), primitive_iterator()
5289  {}
5290  };
5291 
5292  public:
5306  class const_iterator : public std::iterator<std::random_access_iterator_tag, const basic_json>
5307  {
5309  friend class basic_json;
5310 
5311  public:
5321  using iterator_category = std::bidirectional_iterator_tag;
5322 
5324  const_iterator() = default;
5325 
5327  const_iterator(pointer object) : m_object(object)
5328  {
5329  switch (m_object->m_type)
5330  {
5332  {
5333  m_it.object_iterator = typename object_t::iterator();
5334  break;
5335  }
5336 
5338  {
5339  m_it.array_iterator = typename array_t::iterator();
5340  break;
5341  }
5342 
5343  default:
5344  {
5345  m_it.primitive_iterator = primitive_iterator_t();
5346  break;
5347  }
5348  }
5349  }
5350 
5352  const_iterator(const iterator& other) : m_object(other.m_object)
5353  {
5354  switch (m_object->m_type)
5355  {
5357  {
5358  m_it.object_iterator = other.m_it.object_iterator;
5359  break;
5360  }
5361 
5363  {
5364  m_it.array_iterator = other.m_it.array_iterator;
5365  break;
5366  }
5367 
5368  default:
5369  {
5370  m_it.primitive_iterator = other.m_it.primitive_iterator;
5371  break;
5372  }
5373  }
5374  }
5375 
5377  const_iterator(const const_iterator& other) noexcept
5378  : m_object(other.m_object), m_it(other.m_it)
5379  {}
5380 
5383  std::is_nothrow_move_constructible<pointer>::value and
5384  std::is_nothrow_move_assignable<pointer>::value and
5385  std::is_nothrow_move_constructible<internal_iterator>::value and
5386  std::is_nothrow_move_assignable<internal_iterator>::value
5387  )
5388  {
5389  std::swap(m_object, other.m_object);
5390  std::swap(m_it, other.m_it);
5391  return *this;
5392  }
5393 
5394  private:
5396  void set_begin()
5397  {
5398  switch (m_object->m_type)
5399  {
5401  {
5402  m_it.object_iterator = m_object->m_value.object->begin();
5403  break;
5404  }
5405 
5407  {
5408  m_it.array_iterator = m_object->m_value.array->begin();
5409  break;
5410  }
5411 
5413  {
5414  // set to end so begin()==end() is true: null is empty
5415  m_it.primitive_iterator.set_end();
5416  break;
5417  }
5418 
5419  default:
5420  {
5421  m_it.primitive_iterator.set_begin();
5422  break;
5423  }
5424  }
5425  }
5426 
5428  void set_end()
5429  {
5430  switch (m_object->m_type)
5431  {
5433  {
5434  m_it.object_iterator = m_object->m_value.object->end();
5435  break;
5436  }
5437 
5439  {
5440  m_it.array_iterator = m_object->m_value.array->end();
5441  break;
5442  }
5443 
5444  default:
5445  {
5446  m_it.primitive_iterator.set_end();
5447  break;
5448  }
5449  }
5450  }
5451 
5452  public:
5455  {
5456  switch (m_object->m_type)
5457  {
5459  {
5460  return m_it.object_iterator->second;
5461  }
5462 
5464  {
5465  return *m_it.array_iterator;
5466  }
5467 
5469  {
5470  throw std::out_of_range("cannot get value");
5471  }
5472 
5473  default:
5474  {
5475  if (m_it.primitive_iterator.is_begin())
5476  {
5477  return *m_object;
5478  }
5479  else
5480  {
5481  throw std::out_of_range("cannot get value");
5482  }
5483  }
5484  }
5485  }
5486 
5489  {
5490  switch (m_object->m_type)
5491  {
5493  {
5494  return &(m_it.object_iterator->second);
5495  }
5496 
5498  {
5499  return &*m_it.array_iterator;
5500  }
5501 
5502  default:
5503  {
5504  if (m_it.primitive_iterator.is_begin())
5505  {
5506  return m_object;
5507  }
5508  else
5509  {
5510  throw std::out_of_range("cannot get value");
5511  }
5512  }
5513  }
5514  }
5515 
5518  {
5519  auto result = *this;
5520  ++(*this);
5521  return result;
5522  }
5523 
5526  {
5527  switch (m_object->m_type)
5528  {
5530  {
5531  ++m_it.object_iterator;
5532  break;
5533  }
5534 
5536  {
5537  ++m_it.array_iterator;
5538  break;
5539  }
5540 
5541  default:
5542  {
5543  ++m_it.primitive_iterator;
5544  break;
5545  }
5546  }
5547 
5548  return *this;
5549  }
5550 
5553  {
5554  auto result = *this;
5555  --(*this);
5556  return result;
5557  }
5558 
5561  {
5562  switch (m_object->m_type)
5563  {
5565  {
5566  --m_it.object_iterator;
5567  break;
5568  }
5569 
5571  {
5572  --m_it.array_iterator;
5573  break;
5574  }
5575 
5576  default:
5577  {
5578  --m_it.primitive_iterator;
5579  break;
5580  }
5581  }
5582 
5583  return *this;
5584  }
5585 
5587  bool operator==(const const_iterator& other) const
5588  {
5589  // if objects are not the same, the comparison is undefined
5590  if (m_object != other.m_object)
5591  {
5592  throw std::domain_error("cannot compare iterators of different containers");
5593  }
5594 
5595  switch (m_object->m_type)
5596  {
5598  {
5599  return (m_it.object_iterator == other.m_it.object_iterator);
5600  }
5601 
5603  {
5604  return (m_it.array_iterator == other.m_it.array_iterator);
5605  }
5606 
5607  default:
5608  {
5609  return (m_it.primitive_iterator == other.m_it.primitive_iterator);
5610  }
5611  }
5612  }
5613 
5615  bool operator!=(const const_iterator& other) const
5616  {
5617  return not operator==(other);
5618  }
5619 
5621  bool operator<(const const_iterator& other) const
5622  {
5623  // if objects are not the same, the comparison is undefined
5624  if (m_object != other.m_object)
5625  {
5626  throw std::domain_error("cannot compare iterators of different containers");
5627  }
5628 
5629  switch (m_object->m_type)
5630  {
5632  {
5633  throw std::domain_error("cannot use operator< for object iterators");
5634  }
5635 
5637  {
5638  return (m_it.array_iterator < other.m_it.array_iterator);
5639  }
5640 
5641  default:
5642  {
5643  return (m_it.primitive_iterator < other.m_it.primitive_iterator);
5644  }
5645  }
5646  }
5647 
5649  bool operator<=(const const_iterator& other) const
5650  {
5651  return not other.operator < (*this);
5652  }
5653 
5655  bool operator>(const const_iterator& other) const
5656  {
5657  return not operator<=(other);
5658  }
5659 
5661  bool operator>=(const const_iterator& other) const
5662  {
5663  return not operator<(other);
5664  }
5665 
5668  {
5669  switch (m_object->m_type)
5670  {
5672  {
5673  throw std::domain_error("cannot use operator+= for object iterators");
5674  }
5675 
5677  {
5678  m_it.array_iterator += i;
5679  break;
5680  }
5681 
5682  default:
5683  {
5684  m_it.primitive_iterator += i;
5685  break;
5686  }
5687  }
5688 
5689  return *this;
5690  }
5691 
5694  {
5695  return operator+=(-i);
5696  }
5697 
5700  {
5701  auto result = *this;
5702  result += i;
5703  return result;
5704  }
5705 
5708  {
5709  auto result = *this;
5710  result -= i;
5711  return result;
5712  }
5713 
5716  {
5717  switch (m_object->m_type)
5718  {
5720  {
5721  throw std::domain_error("cannot use operator- for object iterators");
5722  }
5723 
5725  {
5726  return m_it.array_iterator - other.m_it.array_iterator;
5727  }
5728 
5729  default:
5730  {
5731  return m_it.primitive_iterator - other.m_it.primitive_iterator;
5732  }
5733  }
5734  }
5735 
5738  {
5739  switch (m_object->m_type)
5740  {
5742  {
5743  throw std::domain_error("cannot use operator[] for object iterators");
5744  }
5745 
5747  {
5748  return *(m_it.array_iterator + n);
5749  }
5750 
5752  {
5753  throw std::out_of_range("cannot get value");
5754  }
5755 
5756  default:
5757  {
5758  if (m_it.primitive_iterator == -n)
5759  {
5760  return *m_object;
5761  }
5762  else
5763  {
5764  throw std::out_of_range("cannot get value");
5765  }
5766  }
5767  }
5768  }
5769 
5771  typename object_t::key_type key() const
5772  {
5773  if (m_object->is_object())
5774  {
5775  return m_it.object_iterator->first;
5776  }
5777  else
5778  {
5779  throw std::domain_error("cannot use key() for non-object iterators");
5780  }
5781  }
5782 
5785  {
5786  return operator*();
5787  }
5788 
5789  private:
5791  pointer m_object = nullptr;
5793  internal_iterator m_it = internal_iterator();
5794  };
5795 
5808  class iterator : public const_iterator
5809  {
5810  public:
5812  using pointer = typename basic_json::pointer;
5814 
5816  iterator() = default;
5817 
5819  iterator(pointer object) noexcept : base_iterator(object)
5820  {}
5821 
5823  iterator(const iterator& other) noexcept
5824  : base_iterator(other)
5825  {}
5826 
5828  iterator& operator=(iterator other) noexcept(
5829  std::is_nothrow_move_constructible<pointer>::value and
5830  std::is_nothrow_move_assignable<pointer>::value and
5831  std::is_nothrow_move_constructible<internal_iterator>::value and
5832  std::is_nothrow_move_assignable<internal_iterator>::value
5833  )
5834  {
5835  base_iterator::operator=(other);
5836  return *this;
5837  }
5838 
5841  {
5842  return const_cast<reference>(base_iterator::operator*());
5843  }
5844 
5847  {
5848  return const_cast<pointer>(base_iterator::operator->());
5849  }
5850 
5853  {
5854  iterator result = *this;
5856  return result;
5857  }
5858 
5861  {
5863  return *this;
5864  }
5865 
5868  {
5869  iterator result = *this;
5871  return result;
5872  }
5873 
5876  {
5878  return *this;
5879  }
5880 
5883  {
5885  return *this;
5886  }
5887 
5890  {
5892  return *this;
5893  }
5894 
5897  {
5898  auto result = *this;
5899  result += i;
5900  return result;
5901  }
5902 
5905  {
5906  auto result = *this;
5907  result -= i;
5908  return result;
5909  }
5910 
5911  difference_type operator-(const iterator& other) const
5912  {
5913  return base_iterator::operator-(other);
5914  }
5915 
5918  {
5919  return const_cast<reference>(base_iterator::operator[](n));
5920  }
5921 
5924  {
5925  return const_cast<reference>(base_iterator::value());
5926  }
5927  };
5928 
5946  template<typename Base>
5947  class json_reverse_iterator : public std::reverse_iterator<Base>
5948  {
5949  public:
5951  using base_iterator = std::reverse_iterator<Base>;
5953  using reference = typename Base::reference;
5954 
5956  json_reverse_iterator(const typename base_iterator::iterator_type& it)
5957  : base_iterator(it) {}
5958 
5961 
5964  {
5965  return base_iterator::operator++(1);
5966  }
5967 
5970  {
5971  base_iterator::operator++();
5972  return *this;
5973  }
5974 
5977  {
5978  return base_iterator::operator--(1);
5979  }
5980 
5983  {
5984  base_iterator::operator--();
5985  return *this;
5986  }
5987 
5990  {
5991  base_iterator::operator+=(i);
5992  return *this;
5993  }
5994 
5997  {
5998  auto result = *this;
5999  result += i;
6000  return result;
6001  }
6002 
6005  {
6006  auto result = *this;
6007  result -= i;
6008  return result;
6009  }
6010 
6013  {
6014  return this->base() - other.base();
6015  }
6016 
6019  {
6020  return *(this->operator+(n));
6021  }
6022 
6024  typename object_t::key_type key() const
6025  {
6026  auto it = --this->base();
6027  return it.key();
6028  }
6029 
6032  {
6033  auto it = --this->base();
6034  return it.operator * ();
6035  }
6036  };
6037 
6046  {
6047  private:
6049  basic_json& container;
6051  using json_iterator = decltype(std::begin(container));
6052 
6054  class iterator_wrapper_internal
6055  {
6056  private:
6058  json_iterator anchor;
6060  size_t array_index = 0;
6061 
6062  public:
6064  iterator_wrapper_internal(json_iterator i) : anchor(i)
6065  {}
6066 
6068  iterator_wrapper_internal& operator*()
6069  {
6070  return *this;
6071  }
6072 
6074  iterator_wrapper_internal& operator++()
6075  {
6076  ++anchor;
6077  ++array_index;
6078 
6079  return *this;
6080  }
6081 
6083  bool operator!= (const iterator_wrapper_internal& o)
6084  {
6085  return anchor != o.anchor;
6086  }
6087 
6089  typename basic_json::string_t key() const
6090  {
6091  switch (anchor.m_object->type())
6092  {
6093  // use integer array index as key
6094  case value_t::array:
6095  {
6096  return std::to_string(array_index);
6097  }
6098 
6099  // use key from the object
6100  case value_t::object:
6101  {
6102  return anchor.key();
6103  }
6104 
6105  // use an empty key for all primitive types
6106  default:
6107  {
6108  return "";
6109  }
6110  }
6111  }
6112 
6114  typename json_iterator::reference value() const
6115  {
6116  return anchor.value();
6117  }
6118  };
6119 
6120  public:
6122  iterator_wrapper(basic_json& cont)
6123  : container(cont)
6124  {}
6125 
6127  iterator_wrapper_internal begin()
6128  {
6129  return iterator_wrapper_internal(container.begin());
6130  }
6131 
6133  iterator_wrapper_internal end()
6134  {
6135  return iterator_wrapper_internal(container.end());
6136  }
6137  };
6138 
6139  private:
6141  // lexer and parser //
6143 
6151  class lexer
6152  {
6153  public:
6155  enum class token_type
6156  {
6157  uninitialized,
6158  literal_true,
6159  literal_false,
6160  literal_null,
6161  value_string,
6162  value_number,
6163  begin_array,
6164  begin_object,
6165  end_array,
6166  end_object,
6167  name_separator,
6168  value_separator,
6169  parse_error,
6170  end_of_input
6171  };
6172 
6174  using lexer_char_t = unsigned char;
6175 
6177  explicit lexer(const string_t& s) noexcept
6178  : m_stream(nullptr), m_buffer(s)
6179  {
6180  m_content = reinterpret_cast<const lexer_char_t*>(s.c_str());
6181  m_start = m_cursor = m_content;
6182  m_limit = m_content + s.size();
6183  }
6184  explicit lexer(std::istream* s) noexcept
6185  : m_stream(s), m_buffer()
6186  {
6187  getline(*m_stream, m_buffer);
6188  m_content = reinterpret_cast<const lexer_char_t*>(m_buffer.c_str());
6189  m_start = m_cursor = m_content;
6190  m_limit = m_content + m_buffer.size();
6191  }
6192 
6194  lexer() = default;
6195 
6196  // switch of unwanted functions
6197  lexer(const lexer&) = delete;
6198  lexer operator=(const lexer&) = delete;
6199 
6211  static string_t to_unicode(const std::size_t codepoint1,
6212  const std::size_t codepoint2 = 0)
6213  {
6214  string_t result;
6215 
6216  // calculate the codepoint from the given code points
6217  std::size_t codepoint = codepoint1;
6218 
6219  // check if codepoint1 is a high surrogate
6220  if (codepoint1 >= 0xD800 and codepoint1 <= 0xDBFF)
6221  {
6222  // check if codepoint2 is a low surrogate
6223  if (codepoint2 >= 0xDC00 and codepoint2 <= 0xDFFF)
6224  {
6225  codepoint =
6226  // high surrogate occupies the most significant 22 bits
6227  (codepoint1 << 10)
6228  // low surrogate occupies the least significant 15 bits
6229  + codepoint2
6230  // there is still the 0xD800, 0xDC00 and 0x10000 noise
6231  // in the result so we have to substract with:
6232  // (0xD800 << 10) + DC00 - 0x10000 = 0x35FDC00
6233  - 0x35FDC00;
6234  }
6235  else
6236  {
6237  throw std::invalid_argument("missing or wrong low surrogate");
6238  }
6239  }
6240 
6241  if (codepoint < 0x80)
6242  {
6243  // 1-byte characters: 0xxxxxxx (ASCII)
6244  result.append(1, static_cast<typename string_t::value_type>(codepoint));
6245  }
6246  else if (codepoint <= 0x7ff)
6247  {
6248  // 2-byte characters: 110xxxxx 10xxxxxx
6249  result.append(1, static_cast<typename string_t::value_type>(0xC0 | ((codepoint >> 6) & 0x1F)));
6250  result.append(1, static_cast<typename string_t::value_type>(0x80 | (codepoint & 0x3F)));
6251  }
6252  else if (codepoint <= 0xffff)
6253  {
6254  // 3-byte characters: 1110xxxx 10xxxxxx 10xxxxxx
6255  result.append(1, static_cast<typename string_t::value_type>(0xE0 | ((codepoint >> 12) & 0x0F)));
6256  result.append(1, static_cast<typename string_t::value_type>(0x80 | ((codepoint >> 6) & 0x3F)));
6257  result.append(1, static_cast<typename string_t::value_type>(0x80 | (codepoint & 0x3F)));
6258  }
6259  else if (codepoint <= 0x10ffff)
6260  {
6261  // 4-byte characters: 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
6262  result.append(1, static_cast<typename string_t::value_type>(0xF0 | ((codepoint >> 18) & 0x07)));
6263  result.append(1, static_cast<typename string_t::value_type>(0x80 | ((codepoint >> 12) & 0x3F)));
6264  result.append(1, static_cast<typename string_t::value_type>(0x80 | ((codepoint >> 6) & 0x3F)));
6265  result.append(1, static_cast<typename string_t::value_type>(0x80 | (codepoint & 0x3F)));
6266  }
6267  else
6268  {
6269  throw std::out_of_range("code points above 0x10FFFF are invalid");
6270  }
6271 
6272  return result;
6273  }
6274 
6276  static std::string token_type_name(token_type t)
6277  {
6278  switch (t)
6279  {
6280  case token_type::uninitialized:
6281  return "<uninitialized>";
6282  case token_type::literal_true:
6283  return "true literal";
6284  case token_type::literal_false:
6285  return "false literal";
6286  case token_type::literal_null:
6287  return "null literal";
6288  case token_type::value_string:
6289  return "string literal";
6290  case token_type::value_number:
6291  return "number literal";
6292  case token_type::begin_array:
6293  return "[";
6294  case token_type::begin_object:
6295  return "{";
6296  case token_type::end_array:
6297  return "]";
6298  case token_type::end_object:
6299  return "}";
6300  case token_type::name_separator:
6301  return ":";
6302  case token_type::value_separator:
6303  return ",";
6304  case token_type::parse_error:
6305  return "<parse error>";
6306  case token_type::end_of_input:
6307  return "<end of input>";
6308  default:
6309  {
6310  // catch non-enum values
6311  return "unknown token"; // LCOV_EXCL_LINE
6312  }
6313  }
6314  }
6315 
6326  token_type scan() noexcept
6327  {
6328  // pointer for backtracking information
6329  m_marker = nullptr;
6330 
6331  // remember the begin of the token
6332  m_start = m_cursor;
6333 
6334 
6335  {
6336  lexer_char_t yych;
6337  unsigned int yyaccept = 0;
6338  static const unsigned char yybm[] =
6339  {
6340  0, 0, 0, 0, 0, 0, 0, 0,
6341  0, 32, 32, 0, 0, 32, 0, 0,
6342  64, 64, 64, 64, 64, 64, 64, 64,
6343  64, 64, 64, 64, 64, 64, 64, 64,
6344  96, 64, 0, 64, 64, 64, 64, 64,
6345  64, 64, 64, 64, 64, 64, 64, 64,
6346  192, 192, 192, 192, 192, 192, 192, 192,
6347  192, 192, 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, 0, 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  64, 64, 64, 64, 64, 64, 64, 64,
6364  64, 64, 64, 64, 64, 64, 64, 64,
6365  64, 64, 64, 64, 64, 64, 64, 64,
6366  64, 64, 64, 64, 64, 64, 64, 64,
6367  64, 64, 64, 64, 64, 64, 64, 64,
6368  64, 64, 64, 64, 64, 64, 64, 64,
6369  64, 64, 64, 64, 64, 64, 64, 64,
6370  64, 64, 64, 64, 64, 64, 64, 64,
6371  64, 64, 64, 64, 64, 64, 64, 64,
6372  };
6373  if ((m_limit - m_cursor) < 5)
6374  {
6375  yyfill(); // LCOV_EXCL_LINE;
6376  }
6377  yych = *m_cursor;
6378  if (yych <= ':')
6379  {
6380  if (yych <= ' ')
6381  {
6382  if (yych <= '\n')
6383  {
6384  if (yych <= 0x00)
6385  {
6386  goto basic_json_parser_28;
6387  }
6388  if (yych <= 0x08)
6389  {
6390  goto basic_json_parser_30;
6391  }
6392  if (yych >= '\n')
6393  {
6394  goto basic_json_parser_4;
6395  }
6396  }
6397  else
6398  {
6399  if (yych == '\r')
6400  {
6401  goto basic_json_parser_2;
6402  }
6403  if (yych <= 0x1F)
6404  {
6405  goto basic_json_parser_30;
6406  }
6407  }
6408  }
6409  else
6410  {
6411  if (yych <= ',')
6412  {
6413  if (yych == '"')
6414  {
6415  goto basic_json_parser_27;
6416  }
6417  if (yych <= '+')
6418  {
6419  goto basic_json_parser_30;
6420  }
6421  goto basic_json_parser_16;
6422  }
6423  else
6424  {
6425  if (yych <= '/')
6426  {
6427  if (yych <= '-')
6428  {
6429  goto basic_json_parser_23;
6430  }
6431  goto basic_json_parser_30;
6432  }
6433  else
6434  {
6435  if (yych <= '0')
6436  {
6437  goto basic_json_parser_24;
6438  }
6439  if (yych <= '9')
6440  {
6441  goto basic_json_parser_26;
6442  }
6443  goto basic_json_parser_18;
6444  }
6445  }
6446  }
6447  }
6448  else
6449  {
6450  if (yych <= 'n')
6451  {
6452  if (yych <= ']')
6453  {
6454  if (yych == '[')
6455  {
6456  goto basic_json_parser_8;
6457  }
6458  if (yych <= '\\')
6459  {
6460  goto basic_json_parser_30;
6461  }
6462  goto basic_json_parser_10;
6463  }
6464  else
6465  {
6466  if (yych == 'f')
6467  {
6468  goto basic_json_parser_22;
6469  }
6470  if (yych <= 'm')
6471  {
6472  goto basic_json_parser_30;
6473  }
6474  goto basic_json_parser_20;
6475  }
6476  }
6477  else
6478  {
6479  if (yych <= '{')
6480  {
6481  if (yych == 't')
6482  {
6483  goto basic_json_parser_21;
6484  }
6485  if (yych <= 'z')
6486  {
6487  goto basic_json_parser_30;
6488  }
6489  goto basic_json_parser_12;
6490  }
6491  else
6492  {
6493  if (yych <= '}')
6494  {
6495  if (yych <= '|')
6496  {
6497  goto basic_json_parser_30;
6498  }
6499  goto basic_json_parser_14;
6500  }
6501  else
6502  {
6503  if (yych == 0xEF)
6504  {
6505  goto basic_json_parser_6;
6506  }
6507  goto basic_json_parser_30;
6508  }
6509  }
6510  }
6511  }
6512 basic_json_parser_2:
6513  ++m_cursor;
6514  yych = *m_cursor;
6515  goto basic_json_parser_5;
6516 basic_json_parser_3:
6517  {
6518  return scan();
6519  }
6520 basic_json_parser_4:
6521  ++m_cursor;
6522  if (m_limit <= m_cursor)
6523  {
6524  yyfill(); // LCOV_EXCL_LINE;
6525  }
6526  yych = *m_cursor;
6527 basic_json_parser_5:
6528  if (yybm[0 + yych] & 32)
6529  {
6530  goto basic_json_parser_4;
6531  }
6532  goto basic_json_parser_3;
6533 basic_json_parser_6:
6534  yyaccept = 0;
6535  yych = *(m_marker = ++m_cursor);
6536  if (yych == 0xBB)
6537  {
6538  goto basic_json_parser_64;
6539  }
6540 basic_json_parser_7:
6541  {
6542  return token_type::parse_error;
6543  }
6544 basic_json_parser_8:
6545  ++m_cursor;
6546  {
6547  return token_type::begin_array;
6548  }
6549 basic_json_parser_10:
6550  ++m_cursor;
6551  {
6552  return token_type::end_array;
6553  }
6554 basic_json_parser_12:
6555  ++m_cursor;
6556  {
6557  return token_type::begin_object;
6558  }
6559 basic_json_parser_14:
6560  ++m_cursor;
6561  {
6562  return token_type::end_object;
6563  }
6564 basic_json_parser_16:
6565  ++m_cursor;
6566  {
6567  return token_type::value_separator;
6568  }
6569 basic_json_parser_18:
6570  ++m_cursor;
6571  {
6572  return token_type::name_separator;
6573  }
6574 basic_json_parser_20:
6575  yyaccept = 0;
6576  yych = *(m_marker = ++m_cursor);
6577  if (yych == 'u')
6578  {
6579  goto basic_json_parser_60;
6580  }
6581  goto basic_json_parser_7;
6582 basic_json_parser_21:
6583  yyaccept = 0;
6584  yych = *(m_marker = ++m_cursor);
6585  if (yych == 'r')
6586  {
6587  goto basic_json_parser_56;
6588  }
6589  goto basic_json_parser_7;
6590 basic_json_parser_22:
6591  yyaccept = 0;
6592  yych = *(m_marker = ++m_cursor);
6593  if (yych == 'a')
6594  {
6595  goto basic_json_parser_51;
6596  }
6597  goto basic_json_parser_7;
6598 basic_json_parser_23:
6599  yych = *++m_cursor;
6600  if (yych <= '/')
6601  {
6602  goto basic_json_parser_7;
6603  }
6604  if (yych <= '0')
6605  {
6606  goto basic_json_parser_50;
6607  }
6608  if (yych <= '9')
6609  {
6610  goto basic_json_parser_41;
6611  }
6612  goto basic_json_parser_7;
6613 basic_json_parser_24:
6614  yyaccept = 1;
6615  yych = *(m_marker = ++m_cursor);
6616  if (yych <= 'D')
6617  {
6618  if (yych == '.')
6619  {
6620  goto basic_json_parser_43;
6621  }
6622  }
6623  else
6624  {
6625  if (yych <= 'E')
6626  {
6627  goto basic_json_parser_44;
6628  }
6629  if (yych == 'e')
6630  {
6631  goto basic_json_parser_44;
6632  }
6633  }
6634 basic_json_parser_25:
6635  {
6636  return token_type::value_number;
6637  }
6638 basic_json_parser_26:
6639  yyaccept = 1;
6640  yych = *(m_marker = ++m_cursor);
6641  goto basic_json_parser_42;
6642 basic_json_parser_27:
6643  yyaccept = 0;
6644  yych = *(m_marker = ++m_cursor);
6645  if (yych <= 0x0F)
6646  {
6647  goto basic_json_parser_7;
6648  }
6649  goto basic_json_parser_32;
6650 basic_json_parser_28:
6651  ++m_cursor;
6652  {
6653  return token_type::end_of_input;
6654  }
6655 basic_json_parser_30:
6656  yych = *++m_cursor;
6657  goto basic_json_parser_7;
6658 basic_json_parser_31:
6659  ++m_cursor;
6660  if (m_limit <= m_cursor)
6661  {
6662  yyfill(); // LCOV_EXCL_LINE;
6663  }
6664  yych = *m_cursor;
6665 basic_json_parser_32:
6666  if (yybm[0 + yych] & 64)
6667  {
6668  goto basic_json_parser_31;
6669  }
6670  if (yych <= 0x0F)
6671  {
6672  goto basic_json_parser_33;
6673  }
6674  if (yych <= '"')
6675  {
6676  goto basic_json_parser_35;
6677  }
6678  goto basic_json_parser_34;
6679 basic_json_parser_33:
6680  m_cursor = m_marker;
6681  if (yyaccept == 0)
6682  {
6683  goto basic_json_parser_7;
6684  }
6685  else
6686  {
6687  goto basic_json_parser_25;
6688  }
6689 basic_json_parser_34:
6690  ++m_cursor;
6691  if (m_limit <= m_cursor)
6692  {
6693  yyfill(); // LCOV_EXCL_LINE;
6694  }
6695  yych = *m_cursor;
6696  if (yych <= 'e')
6697  {
6698  if (yych <= '/')
6699  {
6700  if (yych == '"')
6701  {
6702  goto basic_json_parser_31;
6703  }
6704  if (yych <= '.')
6705  {
6706  goto basic_json_parser_33;
6707  }
6708  goto basic_json_parser_31;
6709  }
6710  else
6711  {
6712  if (yych <= '\\')
6713  {
6714  if (yych <= '[')
6715  {
6716  goto basic_json_parser_33;
6717  }
6718  goto basic_json_parser_31;
6719  }
6720  else
6721  {
6722  if (yych == 'b')
6723  {
6724  goto basic_json_parser_31;
6725  }
6726  goto basic_json_parser_33;
6727  }
6728  }
6729  }
6730  else
6731  {
6732  if (yych <= 'q')
6733  {
6734  if (yych <= 'f')
6735  {
6736  goto basic_json_parser_31;
6737  }
6738  if (yych == 'n')
6739  {
6740  goto basic_json_parser_31;
6741  }
6742  goto basic_json_parser_33;
6743  }
6744  else
6745  {
6746  if (yych <= 's')
6747  {
6748  if (yych <= 'r')
6749  {
6750  goto basic_json_parser_31;
6751  }
6752  goto basic_json_parser_33;
6753  }
6754  else
6755  {
6756  if (yych <= 't')
6757  {
6758  goto basic_json_parser_31;
6759  }
6760  if (yych <= 'u')
6761  {
6762  goto basic_json_parser_37;
6763  }
6764  goto basic_json_parser_33;
6765  }
6766  }
6767  }
6768 basic_json_parser_35:
6769  ++m_cursor;
6770  {
6771  return token_type::value_string;
6772  }
6773 basic_json_parser_37:
6774  ++m_cursor;
6775  if (m_limit <= m_cursor)
6776  {
6777  yyfill(); // LCOV_EXCL_LINE;
6778  }
6779  yych = *m_cursor;
6780  if (yych <= '@')
6781  {
6782  if (yych <= '/')
6783  {
6784  goto basic_json_parser_33;
6785  }
6786  if (yych >= ':')
6787  {
6788  goto basic_json_parser_33;
6789  }
6790  }
6791  else
6792  {
6793  if (yych <= 'F')
6794  {
6795  goto basic_json_parser_38;
6796  }
6797  if (yych <= '`')
6798  {
6799  goto basic_json_parser_33;
6800  }
6801  if (yych >= 'g')
6802  {
6803  goto basic_json_parser_33;
6804  }
6805  }
6806 basic_json_parser_38:
6807  ++m_cursor;
6808  if (m_limit <= m_cursor)
6809  {
6810  yyfill(); // LCOV_EXCL_LINE;
6811  }
6812  yych = *m_cursor;
6813  if (yych <= '@')
6814  {
6815  if (yych <= '/')
6816  {
6817  goto basic_json_parser_33;
6818  }
6819  if (yych >= ':')
6820  {
6821  goto basic_json_parser_33;
6822  }
6823  }
6824  else
6825  {
6826  if (yych <= 'F')
6827  {
6828  goto basic_json_parser_39;
6829  }
6830  if (yych <= '`')
6831  {
6832  goto basic_json_parser_33;
6833  }
6834  if (yych >= 'g')
6835  {
6836  goto basic_json_parser_33;
6837  }
6838  }
6839 basic_json_parser_39:
6840  ++m_cursor;
6841  if (m_limit <= m_cursor)
6842  {
6843  yyfill(); // LCOV_EXCL_LINE;
6844  }
6845  yych = *m_cursor;
6846  if (yych <= '@')
6847  {
6848  if (yych <= '/')
6849  {
6850  goto basic_json_parser_33;
6851  }
6852  if (yych >= ':')
6853  {
6854  goto basic_json_parser_33;
6855  }
6856  }
6857  else
6858  {
6859  if (yych <= 'F')
6860  {
6861  goto basic_json_parser_40;
6862  }
6863  if (yych <= '`')
6864  {
6865  goto basic_json_parser_33;
6866  }
6867  if (yych >= 'g')
6868  {
6869  goto basic_json_parser_33;
6870  }
6871  }
6872 basic_json_parser_40:
6873  ++m_cursor;
6874  if (m_limit <= m_cursor)
6875  {
6876  yyfill(); // LCOV_EXCL_LINE;
6877  }
6878  yych = *m_cursor;
6879  if (yych <= '@')
6880  {
6881  if (yych <= '/')
6882  {
6883  goto basic_json_parser_33;
6884  }
6885  if (yych <= '9')
6886  {
6887  goto basic_json_parser_31;
6888  }
6889  goto basic_json_parser_33;
6890  }
6891  else
6892  {
6893  if (yych <= 'F')
6894  {
6895  goto basic_json_parser_31;
6896  }
6897  if (yych <= '`')
6898  {
6899  goto basic_json_parser_33;
6900  }
6901  if (yych <= 'f')
6902  {
6903  goto basic_json_parser_31;
6904  }
6905  goto basic_json_parser_33;
6906  }
6907 basic_json_parser_41:
6908  yyaccept = 1;
6909  m_marker = ++m_cursor;
6910  if ((m_limit - m_cursor) < 3)
6911  {
6912  yyfill(); // LCOV_EXCL_LINE;
6913  }
6914  yych = *m_cursor;
6915 basic_json_parser_42:
6916  if (yybm[0 + yych] & 128)
6917  {
6918  goto basic_json_parser_41;
6919  }
6920  if (yych <= 'D')
6921  {
6922  if (yych != '.')
6923  {
6924  goto basic_json_parser_25;
6925  }
6926  }
6927  else
6928  {
6929  if (yych <= 'E')
6930  {
6931  goto basic_json_parser_44;
6932  }
6933  if (yych == 'e')
6934  {
6935  goto basic_json_parser_44;
6936  }
6937  goto basic_json_parser_25;
6938  }
6939 basic_json_parser_43:
6940  yych = *++m_cursor;
6941  if (yych <= '/')
6942  {
6943  goto basic_json_parser_33;
6944  }
6945  if (yych <= '9')
6946  {
6947  goto basic_json_parser_48;
6948  }
6949  goto basic_json_parser_33;
6950 basic_json_parser_44:
6951  yych = *++m_cursor;
6952  if (yych <= ',')
6953  {
6954  if (yych != '+')
6955  {
6956  goto basic_json_parser_33;
6957  }
6958  }
6959  else
6960  {
6961  if (yych <= '-')
6962  {
6963  goto basic_json_parser_45;
6964  }
6965  if (yych <= '/')
6966  {
6967  goto basic_json_parser_33;
6968  }
6969  if (yych <= '9')
6970  {
6971  goto basic_json_parser_46;
6972  }
6973  goto basic_json_parser_33;
6974  }
6975 basic_json_parser_45:
6976  yych = *++m_cursor;
6977  if (yych <= '/')
6978  {
6979  goto basic_json_parser_33;
6980  }
6981  if (yych >= ':')
6982  {
6983  goto basic_json_parser_33;
6984  }
6985 basic_json_parser_46:
6986  ++m_cursor;
6987  if (m_limit <= m_cursor)
6988  {
6989  yyfill(); // LCOV_EXCL_LINE;
6990  }
6991  yych = *m_cursor;
6992  if (yych <= '/')
6993  {
6994  goto basic_json_parser_25;
6995  }
6996  if (yych <= '9')
6997  {
6998  goto basic_json_parser_46;
6999  }
7000  goto basic_json_parser_25;
7001 basic_json_parser_48:
7002  yyaccept = 1;
7003  m_marker = ++m_cursor;
7004  if ((m_limit - m_cursor) < 3)
7005  {
7006  yyfill(); // LCOV_EXCL_LINE;
7007  }
7008  yych = *m_cursor;
7009  if (yych <= 'D')
7010  {
7011  if (yych <= '/')
7012  {
7013  goto basic_json_parser_25;
7014  }
7015  if (yych <= '9')
7016  {
7017  goto basic_json_parser_48;
7018  }
7019  goto basic_json_parser_25;
7020  }
7021  else
7022  {
7023  if (yych <= 'E')
7024  {
7025  goto basic_json_parser_44;
7026  }
7027  if (yych == 'e')
7028  {
7029  goto basic_json_parser_44;
7030  }
7031  goto basic_json_parser_25;
7032  }
7033 basic_json_parser_50:
7034  yyaccept = 1;
7035  yych = *(m_marker = ++m_cursor);
7036  if (yych <= 'D')
7037  {
7038  if (yych == '.')
7039  {
7040  goto basic_json_parser_43;
7041  }
7042  goto basic_json_parser_25;
7043  }
7044  else
7045  {
7046  if (yych <= 'E')
7047  {
7048  goto basic_json_parser_44;
7049  }
7050  if (yych == 'e')
7051  {
7052  goto basic_json_parser_44;
7053  }
7054  goto basic_json_parser_25;
7055  }
7056 basic_json_parser_51:
7057  yych = *++m_cursor;
7058  if (yych != 'l')
7059  {
7060  goto basic_json_parser_33;
7061  }
7062  yych = *++m_cursor;
7063  if (yych != 's')
7064  {
7065  goto basic_json_parser_33;
7066  }
7067  yych = *++m_cursor;
7068  if (yych != 'e')
7069  {
7070  goto basic_json_parser_33;
7071  }
7072  ++m_cursor;
7073  {
7074  return token_type::literal_false;
7075  }
7076 basic_json_parser_56:
7077  yych = *++m_cursor;
7078  if (yych != 'u')
7079  {
7080  goto basic_json_parser_33;
7081  }
7082  yych = *++m_cursor;
7083  if (yych != 'e')
7084  {
7085  goto basic_json_parser_33;
7086  }
7087  ++m_cursor;
7088  {
7089  return token_type::literal_true;
7090  }
7091 basic_json_parser_60:
7092  yych = *++m_cursor;
7093  if (yych != 'l')
7094  {
7095  goto basic_json_parser_33;
7096  }
7097  yych = *++m_cursor;
7098  if (yych != 'l')
7099  {
7100  goto basic_json_parser_33;
7101  }
7102  ++m_cursor;
7103  {
7104  return token_type::literal_null;
7105  }
7106 basic_json_parser_64:
7107  yych = *++m_cursor;
7108  if (yych != 0xBF)
7109  {
7110  goto basic_json_parser_33;
7111  }
7112  ++m_cursor;
7113  {
7114  return scan();
7115  }
7116  }
7117 
7118 
7119  }
7120 
7122  void yyfill() noexcept
7123  {
7124  if (not m_stream or not * m_stream)
7125  {
7126  return;
7127  }
7128 
7129  const ssize_t offset_start = m_start - m_content;
7130  const ssize_t offset_marker = m_marker - m_start;
7131  const ssize_t offset_cursor = m_cursor - m_start;
7132 
7133  m_buffer.erase(0, static_cast<size_t>(offset_start));
7134  std::string line;
7135  std::getline(*m_stream, line);
7136  m_buffer += "\n" + line; // add line with newline symbol
7137 
7138  m_content = reinterpret_cast<const lexer_char_t*>(m_buffer.c_str());
7139  m_start = m_content;
7140  m_marker = m_start + offset_marker;
7141  m_cursor = m_start + offset_cursor;
7142  m_limit = m_start + m_buffer.size() - 1;
7143  }
7144 
7146  string_t get_token() const noexcept
7147  {
7148  return string_t(reinterpret_cast<typename string_t::const_pointer>(m_start),
7149  static_cast<size_t>(m_cursor - m_start));
7150  }
7151 
7173  string_t get_string() const
7174  {
7175  string_t result;
7176  result.reserve(static_cast<size_t>(m_cursor - m_start - 2));
7177 
7178  // iterate the result between the quotes
7179  for (const lexer_char_t* i = m_start + 1; i < m_cursor - 1; ++i)
7180  {
7181  // process escaped characters
7182  if (*i == '\\')
7183  {
7184  // read next character
7185  ++i;
7186 
7187  switch (*i)
7188  {
7189  // the default escapes
7190  case 't':
7191  {
7192  result += "\t";
7193  break;
7194  }
7195  case 'b':
7196  {
7197  result += "\b";
7198  break;
7199  }
7200  case 'f':
7201  {
7202  result += "\f";
7203  break;
7204  }
7205  case 'n':
7206  {
7207  result += "\n";
7208  break;
7209  }
7210  case 'r':
7211  {
7212  result += "\r";
7213  break;
7214  }
7215  case '\\':
7216  {
7217  result += "\\";
7218  break;
7219  }
7220  case '/':
7221  {
7222  result += "/";
7223  break;
7224  }
7225  case '"':
7226  {
7227  result += "\"";
7228  break;
7229  }
7230 
7231  // unicode
7232  case 'u':
7233  {
7234  // get code xxxx from uxxxx
7235  auto codepoint = std::strtoul(std::string(reinterpret_cast<typename string_t::const_pointer>(i + 1),
7236  4).c_str(), nullptr, 16);
7237 
7238  // check if codepoint is a high surrogate
7239  if (codepoint >= 0xD800 and codepoint <= 0xDBFF)
7240  {
7241  // make sure there is a subsequent unicode
7242  if ((i + 6 >= m_limit) or * (i + 5) != '\\' or * (i + 6) != 'u')
7243  {
7244  throw std::invalid_argument("missing low surrogate");
7245  }
7246 
7247  // get code yyyy from uxxxx\uyyyy
7248  auto codepoint2 = std::strtoul(std::string(reinterpret_cast<typename string_t::const_pointer>
7249  (i + 7), 4).c_str(), nullptr, 16);
7250  result += to_unicode(codepoint, codepoint2);
7251  // skip the next 10 characters (xxxx\uyyyy)
7252  i += 10;
7253  }
7254  else
7255  {
7256  // add unicode character(s)
7257  result += to_unicode(codepoint);
7258  // skip the next four characters (xxxx)
7259  i += 4;
7260  }
7261  break;
7262  }
7263  }
7264  }
7265  else
7266  {
7267  // all other characters are just copied to the end of the
7268  // string
7269  result.append(1, static_cast<typename string_t::value_type>(*i));
7270  }
7271  }
7272 
7273  return result;
7274  }
7275 
7293  long double get_number() const
7294  {
7295  // conversion
7296  typename string_t::value_type* endptr;
7297  const auto float_val = std::strtold(reinterpret_cast<typename string_t::const_pointer>(m_start),
7298  &endptr);
7299 
7300  // return float_val if the whole number was translated and NAN
7301  // otherwise
7302  return (reinterpret_cast<lexer_char_t*>(endptr) == m_cursor) ? float_val : NAN;
7303  }
7304 
7305  private:
7307  std::istream* m_stream;
7309  string_t m_buffer;
7311  const lexer_char_t* m_content = nullptr;
7313  const lexer_char_t* m_start = nullptr;
7315  const lexer_char_t* m_marker = nullptr;
7317  const lexer_char_t* m_cursor = nullptr;
7319  const lexer_char_t* m_limit = nullptr;
7320  };
7321 
7327  class parser
7328  {
7329  public:
7331  parser(const string_t& s, parser_callback_t cb = nullptr)
7332  : callback(cb), m_lexer(s)
7333  {
7334  // read first token
7335  get_token();
7336  }
7337 
7339  parser(std::istream& _is, parser_callback_t cb = nullptr)
7340  : callback(cb), m_lexer(&_is)
7341  {
7342  // read first token
7343  get_token();
7344  }
7345 
7347  basic_json parse()
7348  {
7349  basic_json result = parse_internal(true);
7350 
7351  expect(lexer::token_type::end_of_input);
7352 
7353  // return parser result and replace it with null in case the
7354  // top-level value was discarded by the callback function
7355  return result.is_discarded() ? basic_json() : result;
7356  }
7357 
7358  private:
7360  basic_json parse_internal(bool keep)
7361  {
7362  auto result = basic_json(value_t::discarded);
7363 
7364  switch (last_token)
7365  {
7366  case lexer::token_type::begin_object:
7367  {
7368  if (keep and (not callback or (keep = callback(depth++, parse_event_t::object_start, result))))
7369  {
7370  // explicitly set result to object to cope with {}
7371  result.m_type = value_t::object;
7372  result.m_value = json_value(value_t::object);
7373  }
7374 
7375  // read next token
7376  get_token();
7377 
7378  // closing } -> we are done
7379  if (last_token == lexer::token_type::end_object)
7380  {
7381  get_token();
7382  if (keep and callback and not callback(--depth, parse_event_t::object_end, result))
7383  {
7384  result = basic_json(value_t::discarded);
7385  }
7386  return result;
7387  }
7388 
7389  // no comma is expected here
7390  unexpect(lexer::token_type::value_separator);
7391 
7392  // otherwise: parse key-value pairs
7393  do
7394  {
7395  // ugly, but could be fixed with loop reorganization
7396  if (last_token == lexer::token_type::value_separator)
7397  {
7398  get_token();
7399  }
7400 
7401  // store key
7402  expect(lexer::token_type::value_string);
7403  const auto key = m_lexer.get_string();
7404 
7405  bool keep_tag = false;
7406  if (keep)
7407  {
7408  if (callback)
7409  {
7410  basic_json k(key);
7411  keep_tag = callback(depth, parse_event_t::key, k);
7412  }
7413  else
7414  {
7415  keep_tag = true;
7416  }
7417  }
7418 
7419  // parse separator (:)
7420  get_token();
7421  expect(lexer::token_type::name_separator);
7422 
7423  // parse and add value
7424  get_token();
7425  auto value = parse_internal(keep);
7426  if (keep and keep_tag and not value.is_discarded())
7427  {
7428  result[key] = std::move(value);
7429  }
7430  }
7431  while (last_token == lexer::token_type::value_separator);
7432 
7433  // closing }
7434  expect(lexer::token_type::end_object);
7435  get_token();
7436  if (keep and callback and not callback(--depth, parse_event_t::object_end, result))
7437  {
7438  result = basic_json(value_t::discarded);
7439  }
7440 
7441  return result;
7442  }
7443 
7444  case lexer::token_type::begin_array:
7445  {
7446  if (keep and (not callback or (keep = callback(depth++, parse_event_t::array_start, result))))
7447  {
7448  // explicitly set result to object to cope with []
7449  result.m_type = value_t::array;
7450  result.m_value = json_value(value_t::array);
7451  }
7452 
7453  // read next token
7454  get_token();
7455 
7456  // closing ] -> we are done
7457  if (last_token == lexer::token_type::end_array)
7458  {
7459  get_token();
7460  if (callback and not callback(--depth, parse_event_t::array_end, result))
7461  {
7462  result = basic_json(value_t::discarded);
7463  }
7464  return result;
7465  }
7466 
7467  // no comma is expected here
7468  unexpect(lexer::token_type::value_separator);
7469 
7470  // otherwise: parse values
7471  do
7472  {
7473  // ugly, but could be fixed with loop reorganization
7474  if (last_token == lexer::token_type::value_separator)
7475  {
7476  get_token();
7477  }
7478 
7479  // parse value
7480  auto value = parse_internal(keep);
7481  if (keep and not value.is_discarded())
7482  {
7483  result.push_back(std::move(value));
7484  }
7485  }
7486  while (last_token == lexer::token_type::value_separator);
7487 
7488  // closing ]
7489  expect(lexer::token_type::end_array);
7490  get_token();
7491  if (keep and callback and not callback(--depth, parse_event_t::array_end, result))
7492  {
7493  result = basic_json(value_t::discarded);
7494  }
7495 
7496  return result;
7497  }
7498 
7499  case lexer::token_type::literal_null:
7500  {
7501  get_token();
7502  result.m_type = value_t::null;
7503  break;
7504  }
7505 
7506  case lexer::token_type::value_string:
7507  {
7508  const auto s = m_lexer.get_string();
7509  get_token();
7510  result = basic_json(s);
7511  break;
7512  }
7513 
7514  case lexer::token_type::literal_true:
7515  {
7516  get_token();
7517  result.m_type = value_t::boolean;
7518  result.m_value = true;
7519  break;
7520  }
7521 
7522  case lexer::token_type::literal_false:
7523  {
7524  get_token();
7525  result.m_type = value_t::boolean;
7526  result.m_value = false;
7527  break;
7528  }
7529 
7530  case lexer::token_type::value_number:
7531  {
7532  auto float_val = m_lexer.get_number();
7533 
7534  // NAN is returned if token could not be translated
7535  // completely
7536  if (std::isnan(float_val))
7537  {
7538  throw std::invalid_argument(std::string("parse error - ") +
7539  m_lexer.get_token() + " is not a number");
7540  }
7541 
7542  get_token();
7543 
7544  // check if conversion loses precision
7545  const auto int_val = static_cast<number_integer_t>(float_val);
7546  if (approx(float_val, static_cast<long double>(int_val)))
7547  {
7548  // we would not lose precision -> return int
7549  result.m_type = value_t::number_integer;
7550  result.m_value = int_val;
7551  }
7552  else
7553  {
7554  // we would lose precision -> return float
7555  result.m_type = value_t::number_float;
7556  result.m_value = static_cast<number_float_t>(float_val);
7557  }
7558  break;
7559  }
7560 
7561  default:
7562  {
7563  // the last token was unexpected
7564  unexpect(last_token);
7565  }
7566  }
7567 
7568  if (keep and callback and not callback(depth, parse_event_t::value, result))
7569  {
7570  result = basic_json(value_t::discarded);
7571  }
7572  return result;
7573  }
7574 
7576  typename lexer::token_type get_token()
7577  {
7578  last_token = m_lexer.scan();
7579  return last_token;
7580  }
7581 
7582  void expect(typename lexer::token_type t) const
7583  {
7584  if (t != last_token)
7585  {
7586  std::string error_msg = "parse error - unexpected \'";
7587  error_msg += m_lexer.get_token();
7588  error_msg += "\' (" + lexer::token_type_name(last_token);
7589  error_msg += "); expected " + lexer::token_type_name(t);
7590  throw std::invalid_argument(error_msg);
7591  }
7592  }
7593 
7594  void unexpect(typename lexer::token_type t) const
7595  {
7596  if (t == last_token)
7597  {
7598  std::string error_msg = "parse error - unexpected \'";
7599  error_msg += m_lexer.get_token();
7600  error_msg += "\' (";
7601  error_msg += lexer::token_type_name(last_token) + ")";
7602  throw std::invalid_argument(error_msg);
7603  }
7604  }
7605 
7606  private:
7608  int depth = 0;
7610  parser_callback_t callback;
7612  typename lexer::token_type last_token = lexer::token_type::uninitialized;
7614  lexer m_lexer;
7615  };
7616 };
7617 
7618 
7620 // presets //
7622 
7632 }
7633 
7634 
7636 // nonmember functions //
7638 
7639 // specialization of std::swap, and std::hash
7640 namespace std
7641 {
7647 template <>
7648 inline void swap(nlohmann::json& j1,
7649  nlohmann::json& j2) noexcept(
7650  is_nothrow_move_constructible<nlohmann::json>::value and
7651  is_nothrow_move_assignable<nlohmann::json>::value
7652  )
7653 {
7654  j1.swap(j2);
7655 }
7656 
7658 template <>
7659 struct hash<nlohmann::json>
7660 {
7666  std::size_t operator()(const nlohmann::json& j) const
7667  {
7668  // a naive hashing via the string representation
7669  const auto& h = hash<nlohmann::json::string_t>();
7670  return h(j.dump());
7671  }
7672 };
7673 }
7674 
7687 inline nlohmann::json operator "" _json(const char* s, std::size_t)
7688 {
7689  return nlohmann::json::parse(reinterpret_cast<nlohmann::json::string_t::value_type*>
7690  (const_cast<char*>(s)));
7691 }
7692 
7693 #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:6122
bool operator!=(const const_iterator &other) const
comparison: not equal
Definition: json.hpp:5615
iterator insert(const_iterator pos, basic_json &&val)
inserts element
Definition: json.hpp:4091
iterator operator++(int)
post-increment (it++)
Definition: json.hpp:5852
friend bool operator<=(const_reference lhs, const_reference rhs) noexcept
comparison: less than or equal
Definition: json.hpp:4640
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:6004
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:2806
reference operator[](const T(&key)[n])
access specified object element
Definition: json.hpp:2894
typename basic_json::const_pointer pointer
defines a pointer to the type iterated over (value_type)
Definition: json.hpp:5317
const_iterator & operator--()
pre-decrement (–it)
Definition: json.hpp:5560
friend std::istream & operator>>(std::istream &i, basic_json &j)
deserialize from stream
Definition: json.hpp:4853
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:5382
typename basic_json::value_type value_type
the type of the values when the iterator is dereferenced
Definition: json.hpp:5313
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:4166
iterator insert(const_iterator pos, size_type cnt, const basic_json &val)
inserts elements
Definition: json.hpp:4118
json_reverse_iterator operator--(int)
post-decrement (it–)
Definition: json.hpp:5976
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:4016
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:5860
friend bool operator!=(const_reference lhs, const_reference rhs) noexcept
comparison: not equal
Definition: json.hpp:4518
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:5525
difference_type operator-(const json_reverse_iterator &other) const
return difference
Definition: json.hpp:6012
basic_json<> json
default JSON class
Definition: json.hpp:7631
reference front()
access the first element
Definition: json.hpp:3016
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:3382
std::reverse_iterator< Base > base_iterator
shortcut to the reverse iterator adaptor
Definition: json.hpp:5951
json_reverse_iterator(const typename base_iterator::iterator_type &it)
create reverse iterator from iterator
Definition: json.hpp:5956
a class to store JSON values
Definition: json.hpp:187
json_reverse_iterator & operator--()
pre-decrement (–it)
Definition: json.hpp:5982
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:4497
void push_back(basic_json &&val)
add an object to an array
Definition: json.hpp:3932
const_iterator cbegin() const
returns a const iterator to the first element
Definition: json.hpp:3480
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:5882
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:5811
reference operator+=(basic_json &&val)
add an object to an array
Definition: json.hpp:3957
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:5808
iterator & operator-=(difference_type i)
subtract from iterator
Definition: json.hpp:5889
static basic_json parse(std::istream &&i, parser_callback_t cb=nullptr)
deserialize from stream
Definition: json.hpp:4815
reference operator[](const typename object_t::key_type &key)
access specified object element
Definition: json.hpp:2845
STL namespace.
difference_type operator-(const iterator &other) const
Definition: json.hpp:5911
reference value() const
return the value of an iterator
Definition: json.hpp:5784
const_iterator end() const
returns a const iterator to one past the last element
Definition: json.hpp:3515
const_iterator(const const_iterator &other) noexcept
copy constructor
Definition: json.hpp:5377
reference at(const typename object_t::key_type &key)
access specified object element with bounds checking
Definition: json.hpp:2688
object_t::key_type key() const
return the key of an object iterator
Definition: json.hpp:5771
iterator end()
returns an iterator to one past the last element
Definition: json.hpp:3505
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:5840
reverse_iterator rend()
returns an iterator to the reverse-end
Definition: json.hpp:3594
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:5707
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:5319
const_reverse_iterator rend() const
returns a const reverse iterator to one before the first
Definition: json.hpp:3602
size_type erase(const typename object_t::key_type &key)
remove element from a JSON object given a key
Definition: json.hpp:3296
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:3446
const_reference at(const typename object_t::key_type &key) const
access specified object element with bounds checking
Definition: json.hpp:2726
reference operator+=(const basic_json &val)
add an object to an array
Definition: json.hpp:3990
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:5896
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:3366
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:4684
iterator & operator--()
pre-decrement (–it)
Definition: json.hpp:5875
friend bool operator<(const_reference lhs, const_reference rhs) noexcept
comparison: less than
Definition: json.hpp:4579
pointer operator->() const
dereference the iterator
Definition: json.hpp:5488
discarded by the the parser callback function
const_iterator cend() const
returns a const iterator to one past the last element
Definition: json.hpp:3539
typename Base::reference reference
the reference type for the pointed-to element
Definition: json.hpp:5953
size_type size() const noexcept
returns the number of elements
Definition: json.hpp:3749
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:2616
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:5960
iterator_wrapper_internal end()
return iterator end (needed for range-based for)
Definition: json.hpp:6133
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:4739
ValueType value(const typename object_t::key_type &key, ValueType default_value) const
access specified object element with default value
Definition: json.hpp:2965
object_t::key_type key() const
return the key of an object iterator
Definition: json.hpp:6024
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:5315
void swap(array_t &other)
exchanges the values
Definition: json.hpp:4287
reverse_iterator rbegin()
returns an iterator to the reverse-beginning
Definition: json.hpp:3563
reference operator+=(const typename object_t::value_type &val)
add an object to an object
Definition: json.hpp:4039
iterator_wrapper_internal begin()
return iterator begin (needed for range-based for)
Definition: json.hpp:6127
reference operator[](difference_type n) const
access to successor
Definition: json.hpp:5917
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:3571
~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:5699
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:4351
reference value() const
return the value of an iterator
Definition: json.hpp:5923
const_iterator operator--(int)
post-decrement (it–)
Definition: json.hpp:5552
void erase(const size_type idx)
remove element from a JSON array given an index
Definition: json.hpp:3331
void clear() noexcept
clears the contents
Definition: json.hpp:3866
pointer operator->()
dereference the iterator
Definition: json.hpp:5846
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:3024
bool operator>=(const const_iterator &other) const
comparison: greater than or equal
Definition: json.hpp:5661
iterator insert(const_iterator pos, std::initializer_list< basic_json > ilist)
inserts elements
Definition: json.hpp:4220
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:5667
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:5715
friend bool operator==(const_reference lhs, const_reference rhs) noexcept
comparison: equal
Definition: json.hpp:4430
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:3648
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:3692
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:2991
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:4257
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:3625
reference value() const
return the value of an iterator
Definition: json.hpp:6031
const_iterator(pointer object)
constructor for a given JSON instance
Definition: json.hpp:5327
friend bool operator<(const value_t lhs, const value_t rhs)
comparison operator for JSON types
Definition: json.hpp:4384
iterator(pointer object) noexcept
constructor for a given JSON instance
Definition: json.hpp:5819
bool operator<(const const_iterator &other) const
comparison: smaller
Definition: json.hpp:5621
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:4541
const_iterator & operator-=(difference_type i)
subtract from iterator
Definition: json.hpp:5693
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:4778
InteratorType erase(InteratorType first, InteratorType last)
remove elements given an iterator range
Definition: json.hpp:3216
json_reverse_iterator operator++(int)
post-increment (it++)
Definition: json.hpp:5963
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:5352
friend bool operator!=(std::nullptr_t, const_reference v) noexcept
comparison: not equal
Definition: json.hpp:4550
InteratorType erase(InteratorType pos)
remove element given an iterator
Definition: json.hpp:3115
bool operator<=(const const_iterator &other) const
comparison: less than or equal
Definition: json.hpp:5649
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:3050
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:5517
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:5823
const_reference back() const
access the last element
Definition: json.hpp:3060
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:4807
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:3412
size_type max_size() const noexcept
returns the maximum possible number of elements
Definition: json.hpp:3809
void push_back(const basic_json &val)
add an object to an array
Definition: json.hpp:3967
bool operator==(const const_iterator &other) const
comparison: equal
Definition: json.hpp:5587
json_reverse_iterator & operator++()
pre-increment (++it)
Definition: json.hpp:5969
bool operator>(const const_iterator &other) const
comparison: greater than
Definition: json.hpp:5655
friend bool operator>(const_reference lhs, const_reference rhs) noexcept
comparison: greater than
Definition: json.hpp:4662
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:3456
const_reference at(size_type idx) const
access specified array element with bounds checking
Definition: json.hpp:2650
json_reverse_iterator & operator+=(difference_type i)
add to iterator
Definition: json.hpp:5989
a const random access iterator for the basic_json class
Definition: json.hpp:5306
a template for a reverse iterator class
Definition: json.hpp:232
void swap(object_t &other)
exchanges the values
Definition: json.hpp:4319
std::bidirectional_iterator_tag iterator_category
the category of the iterator
Definition: json.hpp:5321
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:4065
friend bool operator==(const_reference v, std::nullptr_t) noexcept
comparison: equal
Definition: json.hpp:4488
reference operator[](difference_type n) const
access to successor
Definition: json.hpp:6018
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:5737
reference operator*() const
return a reference to the value pointed to by the iterator
Definition: json.hpp:5454
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:4843
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:7666
friend std::ostream & operator<<(std::ostream &o, const basic_json &j)
serialize to stream
Definition: json.hpp:4721
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:5828
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:2763
iterator operator--(int)
post-decrement (it–)
Definition: json.hpp:5867
json_reverse_iterator operator+(difference_type i) const
add to iterator
Definition: json.hpp:5996
parse_event_t
JSON callback events.
Definition: json.hpp:754
iterator operator-(difference_type i)
subtract from iterator
Definition: json.hpp:5904
wrapper to access iterator member functions in range-based for
Definition: json.hpp:6045