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 
2891  const_reference operator[](const typename object_t::key_type& key) const
2892  {
2893  // [] only works for objects
2894  if (is_object())
2895  {
2896  return m_value.object->find(key)->second;
2897  }
2898  else
2899  {
2900  throw std::domain_error("cannot use operator[] with " + type_name());
2901  }
2902  }
2903 
2932  template<typename T, std::size_t n>
2933  reference operator[](const T (&key)[n])
2934  {
2935  // implicitly convert null to object
2936  if (is_null())
2937  {
2938  m_type = value_t::object;
2939  m_value = value_t::object;
2940  }
2941 
2942  // at only works for objects
2943  if (is_object())
2944  {
2945  return m_value.object->operator[](key);
2946  }
2947  else
2948  {
2949  throw std::domain_error("cannot use operator[] with " + type_name());
2950  }
2951  }
2952 
2981  template<typename T, std::size_t n>
2982  const_reference operator[](const T (&key)[n]) const
2983  {
2984  // at only works for objects
2985  if (is_object())
2986  {
2987  return m_value.object->find(key)->second;
2988  }
2989  else
2990  {
2991  throw std::domain_error("cannot use operator[] with " + type_name());
2992  }
2993  }
2994 
3042  template <class ValueType, typename
3043  std::enable_if<
3044  std::is_convertible<basic_json_t, ValueType>::value
3045  , int>::type = 0>
3046  ValueType value(const typename object_t::key_type& key, ValueType default_value) const
3047  {
3048  // at only works for objects
3049  if (is_object())
3050  {
3051  // if key is found, return value and given default value otherwise
3052  const auto it = find(key);
3053  if (it != end())
3054  {
3055  return *it;
3056  }
3057  else
3058  {
3059  return default_value;
3060  }
3061  }
3062  else
3063  {
3064  throw std::domain_error("cannot use value() with " + type_name());
3065  }
3066  }
3067 
3072  string_t value(const typename object_t::key_type& key, const char* default_value) const
3073  {
3074  return value(key, string_t(default_value));
3075  }
3076 
3098  {
3099  return *begin();
3100  }
3101 
3106  {
3107  return *cbegin();
3108  }
3109 
3132  {
3133  auto tmp = end();
3134  --tmp;
3135  return *tmp;
3136  }
3137 
3142  {
3143  auto tmp = cend();
3144  --tmp;
3145  return *tmp;
3146  }
3147 
3190  template <class InteratorType, typename
3191  std::enable_if<
3192  std::is_same<InteratorType, typename basic_json_t::iterator>::value or
3193  std::is_same<InteratorType, typename basic_json_t::const_iterator>::value
3194  , int>::type
3195  = 0>
3196  InteratorType erase(InteratorType pos)
3197  {
3198  // make sure iterator fits the current value
3199  if (this != pos.m_object)
3200  {
3201  throw std::domain_error("iterator does not fit current value");
3202  }
3203 
3204  InteratorType result = end();
3205 
3206  switch (m_type)
3207  {
3208  case value_t::boolean:
3209  case value_t::number_float:
3211  case value_t::string:
3212  {
3213  if (not pos.m_it.primitive_iterator.is_begin())
3214  {
3215  throw std::out_of_range("iterator out of range");
3216  }
3217 
3218  if (is_string())
3219  {
3220  delete m_value.string;
3221  m_value.string = nullptr;
3222  }
3223 
3224  m_type = value_t::null;
3225  break;
3226  }
3227 
3228  case value_t::object:
3229  {
3230  result.m_it.object_iterator = m_value.object->erase(pos.m_it.object_iterator);
3231  break;
3232  }
3233 
3234  case value_t::array:
3235  {
3236  result.m_it.array_iterator = m_value.array->erase(pos.m_it.array_iterator);
3237  break;
3238  }
3239 
3240  default:
3241  {
3242  throw std::domain_error("cannot use erase() with " + type_name());
3243  }
3244  }
3245 
3246  return result;
3247  }
3248 
3291  template <class InteratorType, typename
3292  std::enable_if<
3293  std::is_same<InteratorType, typename basic_json_t::iterator>::value or
3294  std::is_same<InteratorType, typename basic_json_t::const_iterator>::value
3295  , int>::type
3296  = 0>
3297  InteratorType erase(InteratorType first, InteratorType last)
3298  {
3299  // make sure iterator fits the current value
3300  if (this != first.m_object or this != last.m_object)
3301  {
3302  throw std::domain_error("iterators do not fit current value");
3303  }
3304 
3305  InteratorType result = end();
3306 
3307  switch (m_type)
3308  {
3309  case value_t::boolean:
3310  case value_t::number_float:
3312  case value_t::string:
3313  {
3314  if (not first.m_it.primitive_iterator.is_begin() or not last.m_it.primitive_iterator.is_end())
3315  {
3316  throw std::out_of_range("iterators out of range");
3317  }
3318 
3319  if (is_string())
3320  {
3321  delete m_value.string;
3322  m_value.string = nullptr;
3323  }
3324 
3325  m_type = value_t::null;
3326  break;
3327  }
3328 
3329  case value_t::object:
3330  {
3331  result.m_it.object_iterator = m_value.object->erase(first.m_it.object_iterator,
3332  last.m_it.object_iterator);
3333  break;
3334  }
3335 
3336  case value_t::array:
3337  {
3338  result.m_it.array_iterator = m_value.array->erase(first.m_it.array_iterator,
3339  last.m_it.array_iterator);
3340  break;
3341  }
3342 
3343  default:
3344  {
3345  throw std::domain_error("cannot use erase with " + type_name());
3346  }
3347  }
3348 
3349  return result;
3350  }
3351 
3377  size_type erase(const typename object_t::key_type& key)
3378  {
3379  // this erase only works for objects
3380  if (is_object())
3381  {
3382  return m_value.object->erase(key);
3383  }
3384  else
3385  {
3386  throw std::domain_error("cannot use erase() with " + type_name());
3387  }
3388  }
3389 
3412  void erase(const size_type idx)
3413  {
3414  // this erase only works for arrays
3415  if (is_array())
3416  {
3417  if (idx >= size())
3418  {
3419  throw std::out_of_range("index out of range");
3420  }
3421 
3422  m_value.array->erase(m_value.array->begin() + static_cast<difference_type>(idx));
3423  }
3424  else
3425  {
3426  throw std::domain_error("cannot use erase() with " + type_name());
3427  }
3428  }
3429 
3447  iterator find(typename object_t::key_type key)
3448  {
3449  auto result = end();
3450 
3451  if (is_object())
3452  {
3453  result.m_it.object_iterator = m_value.object->find(key);
3454  }
3455 
3456  return result;
3457  }
3458 
3463  const_iterator find(typename object_t::key_type key) const
3464  {
3465  auto result = cend();
3466 
3467  if (is_object())
3468  {
3469  result.m_it.object_iterator = m_value.object->find(key);
3470  }
3471 
3472  return result;
3473  }
3474 
3493  size_type count(typename object_t::key_type key) const
3494  {
3495  // return 0 for all nonobject types
3496  return is_object() ? m_value.object->count(key) : 0;
3497  }
3498 
3500 
3501 
3503  // iterators //
3505 
3508 
3528  {
3529  iterator result(this);
3530  result.set_begin();
3531  return result;
3532  }
3533 
3538  {
3539  return cbegin();
3540  }
3541 
3562  {
3563  const_iterator result(this);
3564  result.set_begin();
3565  return result;
3566  }
3567 
3587  {
3588  iterator result(this);
3589  result.set_end();
3590  return result;
3591  }
3592 
3597  {
3598  return cend();
3599  }
3600 
3621  {
3622  const_iterator result(this);
3623  result.set_end();
3624  return result;
3625  }
3626 
3645  {
3646  return reverse_iterator(end());
3647  }
3648 
3653  {
3654  return crbegin();
3655  }
3656 
3676  {
3677  return reverse_iterator(begin());
3678  }
3679 
3684  {
3685  return crend();
3686  }
3687 
3707  {
3708  return const_reverse_iterator(cend());
3709  }
3710 
3730  {
3731  return const_reverse_iterator(cbegin());
3732  }
3733 
3735 
3736 
3738  // capacity //
3740 
3743 
3773  bool empty() const noexcept
3774  {
3775  switch (m_type)
3776  {
3777  case value_t::null:
3778  {
3779  // null values are empty
3780  return true;
3781  }
3782 
3783  case value_t::array:
3784  {
3785  return m_value.array->empty();
3786  }
3787 
3788  case value_t::object:
3789  {
3790  return m_value.object->empty();
3791  }
3792 
3793  default:
3794  {
3795  // all other types are nonempty
3796  return false;
3797  }
3798  }
3799  }
3800 
3830  size_type size() const noexcept
3831  {
3832  switch (m_type)
3833  {
3834  case value_t::null:
3835  {
3836  // null values are empty
3837  return 0;
3838  }
3839 
3840  case value_t::array:
3841  {
3842  return m_value.array->size();
3843  }
3844 
3845  case value_t::object:
3846  {
3847  return m_value.object->size();
3848  }
3849 
3850  default:
3851  {
3852  // all other types have size 1
3853  return 1;
3854  }
3855  }
3856  }
3857 
3890  size_type max_size() const noexcept
3891  {
3892  switch (m_type)
3893  {
3894  case value_t::array:
3895  {
3896  return m_value.array->max_size();
3897  }
3898 
3899  case value_t::object:
3900  {
3901  return m_value.object->max_size();
3902  }
3903 
3904  default:
3905  {
3906  // all other types have max_size() == size()
3907  return size();
3908  }
3909  }
3910  }
3911 
3913 
3914 
3916  // modifiers //
3918 
3921 
3947  void clear() noexcept
3948  {
3949  switch (m_type)
3950  {
3952  {
3953  m_value.number_integer = 0;
3954  break;
3955  }
3956 
3957  case value_t::number_float:
3958  {
3959  m_value.number_float = 0.0;
3960  break;
3961  }
3962 
3963  case value_t::boolean:
3964  {
3965  m_value.boolean = false;
3966  break;
3967  }
3968 
3969  case value_t::string:
3970  {
3971  m_value.string->clear();
3972  break;
3973  }
3974 
3975  case value_t::array:
3976  {
3977  m_value.array->clear();
3978  break;
3979  }
3980 
3981  case value_t::object:
3982  {
3983  m_value.object->clear();
3984  break;
3985  }
3986 
3987  default:
3988  {
3989  break;
3990  }
3991  }
3992  }
3993 
4013  void push_back(basic_json&& val)
4014  {
4015  // push_back only works for null objects or arrays
4016  if (not(is_null() or is_array()))
4017  {
4018  throw std::domain_error("cannot use push_back() with " + type_name());
4019  }
4020 
4021  // transform null object into an array
4022  if (is_null())
4023  {
4024  m_type = value_t::array;
4025  m_value = value_t::array;
4026  }
4027 
4028  // add element to array (move semantics)
4029  m_value.array->push_back(std::move(val));
4030  // invalidate object
4031  val.m_type = value_t::null;
4032  }
4033 
4038  reference operator+=(basic_json&& val)
4039  {
4040  push_back(std::move(val));
4041  return *this;
4042  }
4043 
4048  void push_back(const basic_json& val)
4049  {
4050  // push_back only works for null objects or arrays
4051  if (not(is_null() or is_array()))
4052  {
4053  throw std::domain_error("cannot use push_back() with " + type_name());
4054  }
4055 
4056  // transform null object into an array
4057  if (is_null())
4058  {
4059  m_type = value_t::array;
4060  m_value = value_t::array;
4061  }
4062 
4063  // add element to array
4064  m_value.array->push_back(val);
4065  }
4066 
4071  reference operator+=(const basic_json& val)
4072  {
4073  push_back(val);
4074  return *this;
4075  }
4076 
4097  void push_back(const typename object_t::value_type& val)
4098  {
4099  // push_back only works for null objects or objects
4100  if (not(is_null() or is_object()))
4101  {
4102  throw std::domain_error("cannot use push_back() with " + type_name());
4103  }
4104 
4105  // transform null object into an object
4106  if (is_null())
4107  {
4108  m_type = value_t::object;
4109  m_value = value_t::object;
4110  }
4111 
4112  // add element to array
4113  m_value.object->insert(val);
4114  }
4115 
4120  reference operator+=(const typename object_t::value_type& val)
4121  {
4122  push_back(val);
4123  return operator[](val.first);
4124  }
4125 
4146  iterator insert(const_iterator pos, const basic_json& val)
4147  {
4148  // insert only works for arrays
4149  if (is_array())
4150  {
4151  // check if iterator pos fits to this JSON value
4152  if (pos.m_object != this)
4153  {
4154  throw std::domain_error("iterator does not fit current value");
4155  }
4156 
4157  // insert to array and return iterator
4158  iterator result(this);
4159  result.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator, val);
4160  return result;
4161  }
4162  else
4163  {
4164  throw std::domain_error("cannot use insert() with " + type_name());
4165  }
4166  }
4167 
4172  iterator insert(const_iterator pos, basic_json&& val)
4173  {
4174  return insert(pos, val);
4175  }
4176 
4199  iterator insert(const_iterator pos, size_type cnt, const basic_json& val)
4200  {
4201  // insert only works for arrays
4202  if (is_array())
4203  {
4204  // check if iterator pos fits to this JSON value
4205  if (pos.m_object != this)
4206  {
4207  throw std::domain_error("iterator does not fit current value");
4208  }
4209 
4210  // insert to array and return iterator
4211  iterator result(this);
4212  result.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator, cnt, val);
4213  return result;
4214  }
4215  else
4216  {
4217  throw std::domain_error("cannot use insert() with " + type_name());
4218  }
4219  }
4220 
4248  {
4249  // insert only works for arrays
4250  if (not is_array())
4251  {
4252  throw std::domain_error("cannot use insert() with " + type_name());
4253  }
4254 
4255  // check if iterator pos fits to this JSON value
4256  if (pos.m_object != this)
4257  {
4258  throw std::domain_error("iterator does not fit current value");
4259  }
4260 
4261  if (first.m_object != last.m_object)
4262  {
4263  throw std::domain_error("iterators do not fit");
4264  }
4265 
4266  if (first.m_object == this or last.m_object == this)
4267  {
4268  throw std::domain_error("passed iterators may not belong to container");
4269  }
4270 
4271  // insert to array and return iterator
4272  iterator result(this);
4273  result.m_it.array_iterator = m_value.array->insert(
4274  pos.m_it.array_iterator,
4275  first.m_it.array_iterator,
4276  last.m_it.array_iterator);
4277  return result;
4278  }
4279 
4301  iterator insert(const_iterator pos, std::initializer_list<basic_json> ilist)
4302  {
4303  // insert only works for arrays
4304  if (not is_array())
4305  {
4306  throw std::domain_error("cannot use insert() with " + type_name());
4307  }
4308 
4309  // check if iterator pos fits to this JSON value
4310  if (pos.m_object != this)
4311  {
4312  throw std::domain_error("iterator does not fit current value");
4313  }
4314 
4315  // insert to array and return iterator
4316  iterator result(this);
4317  result.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator, ilist);
4318  return result;
4319  }
4320 
4338  void swap(reference other) noexcept (
4339  std::is_nothrow_move_constructible<value_t>::value and
4340  std::is_nothrow_move_assignable<value_t>::value and
4341  std::is_nothrow_move_constructible<json_value>::value and
4342  std::is_nothrow_move_assignable<json_value>::value
4343  )
4344  {
4345  std::swap(m_type, other.m_type);
4346  std::swap(m_value, other.m_value);
4347  }
4348 
4368  void swap(array_t& other)
4369  {
4370  // swap only works for arrays
4371  if (is_array())
4372  {
4373  std::swap(*(m_value.array), other);
4374  }
4375  else
4376  {
4377  throw std::domain_error("cannot use swap() with " + type_name());
4378  }
4379  }
4380 
4400  void swap(object_t& other)
4401  {
4402  // swap only works for objects
4403  if (is_object())
4404  {
4405  std::swap(*(m_value.object), other);
4406  }
4407  else
4408  {
4409  throw std::domain_error("cannot use swap() with " + type_name());
4410  }
4411  }
4412 
4432  void swap(string_t& other)
4433  {
4434  // swap only works for strings
4435  if (is_string())
4436  {
4437  std::swap(*(m_value.string), other);
4438  }
4439  else
4440  {
4441  throw std::domain_error("cannot use swap() with " + type_name());
4442  }
4443  }
4444 
4446 
4447 
4449  // lexicographical comparison operators //
4451 
4454 
4455  private:
4465  friend bool operator<(const value_t lhs, const value_t rhs)
4466  {
4467  static constexpr std::array<uint8_t, 7> order = {{
4468  0, // null
4469  3, // object
4470  4, // array
4471  5, // string
4472  1, // boolean
4473  2, // integer
4474  2 // float
4475  }
4476  };
4477 
4478  // discarded values are not comparable
4479  if (lhs == value_t::discarded or rhs == value_t::discarded)
4480  {
4481  return false;
4482  }
4483 
4484  return order[static_cast<std::size_t>(lhs)] < order[static_cast<std::size_t>(rhs)];
4485  }
4486 
4487  public:
4511  friend bool operator==(const_reference lhs, const_reference rhs) noexcept
4512  {
4513  const auto lhs_type = lhs.type();
4514  const auto rhs_type = rhs.type();
4515 
4516  if (lhs_type == rhs_type)
4517  {
4518  switch (lhs_type)
4519  {
4520  case value_t::array:
4521  return *lhs.m_value.array == *rhs.m_value.array;
4522  case value_t::object:
4523  return *lhs.m_value.object == *rhs.m_value.object;
4524  case value_t::null:
4525  return true;
4526  case value_t::string:
4527  return *lhs.m_value.string == *rhs.m_value.string;
4528  case value_t::boolean:
4529  return lhs.m_value.boolean == rhs.m_value.boolean;
4531  return lhs.m_value.number_integer == rhs.m_value.number_integer;
4532  case value_t::number_float:
4533  return approx(lhs.m_value.number_float, rhs.m_value.number_float);
4534  default:
4535  return false;
4536  }
4537  }
4538  else if (lhs_type == value_t::number_integer and rhs_type == value_t::number_float)
4539  {
4540  return approx(static_cast<number_float_t>(lhs.m_value.number_integer),
4541  rhs.m_value.number_float);
4542  }
4543  else if (lhs_type == value_t::number_float and rhs_type == value_t::number_integer)
4544  {
4545  return approx(lhs.m_value.number_float,
4546  static_cast<number_float_t>(rhs.m_value.number_integer));
4547  }
4548  return false;
4549  }
4550 
4569  friend bool operator==(const_reference v, std::nullptr_t) noexcept
4570  {
4571  return v.is_null();
4572  }
4573 
4578  friend bool operator==(std::nullptr_t, const_reference v) noexcept
4579  {
4580  return v.is_null();
4581  }
4582 
4599  friend bool operator!=(const_reference lhs, const_reference rhs) noexcept
4600  {
4601  return not (lhs == rhs);
4602  }
4603 
4622  friend bool operator!=(const_reference v, std::nullptr_t) noexcept
4623  {
4624  return not v.is_null();
4625  }
4626 
4631  friend bool operator!=(std::nullptr_t, const_reference v) noexcept
4632  {
4633  return not v.is_null();
4634  }
4635 
4660  friend bool operator<(const_reference lhs, const_reference rhs) noexcept
4661  {
4662  const auto lhs_type = lhs.type();
4663  const auto rhs_type = rhs.type();
4664 
4665  if (lhs_type == rhs_type)
4666  {
4667  switch (lhs_type)
4668  {
4669  case value_t::array:
4670  return *lhs.m_value.array < *rhs.m_value.array;
4671  case value_t::object:
4672  return *lhs.m_value.object < *rhs.m_value.object;
4673  case value_t::null:
4674  return false;
4675  case value_t::string:
4676  return *lhs.m_value.string < *rhs.m_value.string;
4677  case value_t::boolean:
4678  return lhs.m_value.boolean < rhs.m_value.boolean;
4680  return lhs.m_value.number_integer < rhs.m_value.number_integer;
4681  case value_t::number_float:
4682  return lhs.m_value.number_float < rhs.m_value.number_float;
4683  default:
4684  return false;
4685  }
4686  }
4687  else if (lhs_type == value_t::number_integer and rhs_type == value_t::number_float)
4688  {
4689  return static_cast<number_float_t>(lhs.m_value.number_integer) <
4690  rhs.m_value.number_float;
4691  }
4692  else if (lhs_type == value_t::number_float and rhs_type == value_t::number_integer)
4693  {
4694  return lhs.m_value.number_float <
4695  static_cast<number_float_t>(rhs.m_value.number_integer);
4696  }
4697 
4698  // We only reach this line if we cannot compare values. In that case,
4699  // we compare types. Note we have to call the operator explicitly,
4700  // because MSVC has problems otherwise.
4701  return operator<(lhs_type, rhs_type);
4702  }
4703 
4721  friend bool operator<=(const_reference lhs, const_reference rhs) noexcept
4722  {
4723  return not (rhs < lhs);
4724  }
4725 
4743  friend bool operator>(const_reference lhs, const_reference rhs) noexcept
4744  {
4745  return not (lhs <= rhs);
4746  }
4747 
4765  friend bool operator>=(const_reference lhs, const_reference rhs) noexcept
4766  {
4767  return not (lhs < rhs);
4768  }
4769 
4771 
4772 
4774  // serialization //
4776 
4779 
4802  friend std::ostream& operator<<(std::ostream& o, const basic_json& j)
4803  {
4804  // read width member and use it as indentation parameter if nonzero
4805  const bool pretty_print = (o.width() > 0);
4806  const auto indentation = (pretty_print ? o.width() : 0);
4807 
4808  // reset width to 0 for subsequent calls to this stream
4809  o.width(0);
4810 
4811  // do the actual serialization
4812  j.dump(o, pretty_print, static_cast<unsigned int>(indentation));
4813  return o;
4814  }
4815 
4820  friend std::ostream& operator>>(const basic_json& j, std::ostream& o)
4821  {
4822  return o << j;
4823  }
4824 
4826 
4827 
4829  // deserialization //
4831 
4834 
4859  static basic_json parse(const string_t& s, parser_callback_t cb = nullptr)
4860  {
4861  return parser(s, cb).parse();
4862  }
4863 
4888  static basic_json parse(std::istream& i, parser_callback_t cb = nullptr)
4889  {
4890  return parser(i, cb).parse();
4891  }
4892 
4896  static basic_json parse(std::istream&& i, parser_callback_t cb = nullptr)
4897  {
4898  return parser(i, cb).parse();
4899  }
4900 
4924  friend std::istream& operator<<(basic_json& j, std::istream& i)
4925  {
4926  j = parser(i).parse();
4927  return i;
4928  }
4929 
4934  friend std::istream& operator>>(std::istream& i, basic_json& j)
4935  {
4936  j = parser(i).parse();
4937  return i;
4938  }
4939 
4941 
4942 
4943  private:
4945  // convenience functions //
4947 
4949  string_t type_name() const
4950  {
4951  switch (m_type)
4952  {
4953  case value_t::null:
4954  return "null";
4955  case value_t::object:
4956  return "object";
4957  case value_t::array:
4958  return "array";
4959  case value_t::string:
4960  return "string";
4961  case value_t::boolean:
4962  return "boolean";
4963  case value_t::discarded:
4964  return "discarded";
4965  default:
4966  return "number";
4967  }
4968  }
4969 
4978  static std::size_t extra_space(const string_t& s) noexcept
4979  {
4980  std::size_t result = 0;
4981 
4982  for (const auto& c : s)
4983  {
4984  switch (c)
4985  {
4986  case '"':
4987  case '\\':
4988  case '\b':
4989  case '\f':
4990  case '\n':
4991  case '\r':
4992  case '\t':
4993  {
4994  // from c (1 byte) to \x (2 bytes)
4995  result += 1;
4996  break;
4997  }
4998 
4999  default:
5000  {
5001  if (c >= 0x00 and c <= 0x1f)
5002  {
5003  // from c (1 byte) to \uxxxx (6 bytes)
5004  result += 5;
5005  }
5006  break;
5007  }
5008  }
5009  }
5010 
5011  return result;
5012  }
5013 
5027  static string_t escape_string(const string_t& s) noexcept
5028  {
5029  const auto space = extra_space(s);
5030  if (space == 0)
5031  {
5032  return s;
5033  }
5034 
5035  // create a result string of necessary size
5036  string_t result(s.size() + space, '\\');
5037  std::size_t pos = 0;
5038 
5039  for (const auto& c : s)
5040  {
5041  switch (c)
5042  {
5043  // quotation mark (0x22)
5044  case '"':
5045  {
5046  result[pos + 1] = '"';
5047  pos += 2;
5048  break;
5049  }
5050 
5051  // reverse solidus (0x5c)
5052  case '\\':
5053  {
5054  // nothing to change
5055  pos += 2;
5056  break;
5057  }
5058 
5059  // backspace (0x08)
5060  case '\b':
5061  {
5062  result[pos + 1] = 'b';
5063  pos += 2;
5064  break;
5065  }
5066 
5067  // formfeed (0x0c)
5068  case '\f':
5069  {
5070  result[pos + 1] = 'f';
5071  pos += 2;
5072  break;
5073  }
5074 
5075  // newline (0x0a)
5076  case '\n':
5077  {
5078  result[pos + 1] = 'n';
5079  pos += 2;
5080  break;
5081  }
5082 
5083  // carriage return (0x0d)
5084  case '\r':
5085  {
5086  result[pos + 1] = 'r';
5087  pos += 2;
5088  break;
5089  }
5090 
5091  // horizontal tab (0x09)
5092  case '\t':
5093  {
5094  result[pos + 1] = 't';
5095  pos += 2;
5096  break;
5097  }
5098 
5099  default:
5100  {
5101  if (c >= 0x00 and c <= 0x1f)
5102  {
5103  // convert a number 0..15 to its hex representation (0..f)
5104  auto hexify = [](const char v) -> char
5105  {
5106  return (v < 10) ? ('0' + v) : ('a' + v - 10);
5107  };
5108 
5109  // print character c as \uxxxx
5110  for (const char m :
5111  { 'u', '0', '0', hexify(c >> 4), hexify(c & 0x0f)
5112  })
5113  {
5114  result[++pos] = m;
5115  }
5116 
5117  ++pos;
5118  }
5119  else
5120  {
5121  // all other characters are added as-is
5122  result[pos++] = c;
5123  }
5124  break;
5125  }
5126  }
5127  }
5128 
5129  return result;
5130  }
5131 
5149  void dump(std::ostream& o,
5150  const bool pretty_print,
5151  const unsigned int indent_step,
5152  const unsigned int current_indent = 0) const
5153  {
5154  // variable to hold indentation for recursive calls
5155  unsigned int new_indent = current_indent;
5156 
5157  switch (m_type)
5158  {
5159  case value_t::object:
5160  {
5161  if (m_value.object->empty())
5162  {
5163  o << "{}";
5164  return;
5165  }
5166 
5167  o << "{";
5168 
5169  // increase indentation
5170  if (pretty_print)
5171  {
5172  new_indent += indent_step;
5173  o << "\n";
5174  }
5175 
5176  for (auto i = m_value.object->cbegin(); i != m_value.object->cend(); ++i)
5177  {
5178  if (i != m_value.object->cbegin())
5179  {
5180  o << (pretty_print ? ",\n" : ",");
5181  }
5182  o << string_t(new_indent, ' ') << "\""
5183  << escape_string(i->first) << "\":"
5184  << (pretty_print ? " " : "");
5185  i->second.dump(o, pretty_print, indent_step, new_indent);
5186  }
5187 
5188  // decrease indentation
5189  if (pretty_print)
5190  {
5191  new_indent -= indent_step;
5192  o << "\n";
5193  }
5194 
5195  o << string_t(new_indent, ' ') + "}";
5196  return;
5197  }
5198 
5199  case value_t::array:
5200  {
5201  if (m_value.array->empty())
5202  {
5203  o << "[]";
5204  return;
5205  }
5206 
5207  o << "[";
5208 
5209  // increase indentation
5210  if (pretty_print)
5211  {
5212  new_indent += indent_step;
5213  o << "\n";
5214  }
5215 
5216  for (auto i = m_value.array->cbegin(); i != m_value.array->cend(); ++i)
5217  {
5218  if (i != m_value.array->cbegin())
5219  {
5220  o << (pretty_print ? ",\n" : ",");
5221  }
5222  o << string_t(new_indent, ' ');
5223  i->dump(o, pretty_print, indent_step, new_indent);
5224  }
5225 
5226  // decrease indentation
5227  if (pretty_print)
5228  {
5229  new_indent -= indent_step;
5230  o << "\n";
5231  }
5232 
5233  o << string_t(new_indent, ' ') << "]";
5234  return;
5235  }
5236 
5237  case value_t::string:
5238  {
5239  o << string_t("\"") << escape_string(*m_value.string) << "\"";
5240  return;
5241  }
5242 
5243  case value_t::boolean:
5244  {
5245  o << (m_value.boolean ? "true" : "false");
5246  return;
5247  }
5248 
5250  {
5251  o << m_value.number_integer;
5252  return;
5253  }
5254 
5255  case value_t::number_float:
5256  {
5257  // 15 digits of precision allows round-trip IEEE 754
5258  // string->double->string; to be safe, we read this value from
5259  // std::numeric_limits<number_float_t>::digits10
5260  o << std::setprecision(std::numeric_limits<number_float_t>::digits10) << m_value.number_float;
5261  return;
5262  }
5263 
5264  case value_t::discarded:
5265  {
5266  o << "<discarded>";
5267  return;
5268  }
5269 
5270  case value_t::null:
5271  {
5272  o << "null";
5273  return;
5274  }
5275  }
5276  }
5277 
5278  private:
5280  // member variables //
5282 
5284  value_t m_type = value_t::null;
5285 
5287  json_value m_value = {};
5288 
5289 
5290  private:
5292  // iterators //
5294 
5304  class primitive_iterator_t
5305  {
5306  public:
5308  void set_begin()
5309  {
5310  m_it = begin_value;
5311  }
5312 
5314  void set_end()
5315  {
5316  m_it = end_value;
5317  }
5318 
5320  bool is_begin() const
5321  {
5322  return (m_it == begin_value);
5323  }
5324 
5326  bool is_end() const
5327  {
5328  return (m_it == end_value);
5329  }
5330 
5332  operator difference_type& ()
5333  {
5334  return m_it;
5335  }
5336 
5338  operator difference_type () const
5339  {
5340  return m_it;
5341  }
5342 
5343  private:
5344  static constexpr difference_type begin_value = 0;
5345  static constexpr difference_type end_value = begin_value + 1;
5346 
5348  difference_type m_it = std::numeric_limits<std::ptrdiff_t>::denorm_min();
5349  };
5350 
5358  struct internal_iterator
5359  {
5361  typename object_t::iterator object_iterator;
5363  typename array_t::iterator array_iterator;
5365  primitive_iterator_t primitive_iterator;
5366 
5368  internal_iterator()
5369  : object_iterator(), array_iterator(), primitive_iterator()
5370  {}
5371  };
5372 
5373  public:
5387  class const_iterator : public std::iterator<std::random_access_iterator_tag, const basic_json>
5388  {
5390  friend class basic_json;
5391 
5392  public:
5402  using iterator_category = std::bidirectional_iterator_tag;
5403 
5405  const_iterator() = default;
5406 
5408  const_iterator(pointer object) : m_object(object)
5409  {
5410  switch (m_object->m_type)
5411  {
5413  {
5414  m_it.object_iterator = typename object_t::iterator();
5415  break;
5416  }
5417 
5419  {
5420  m_it.array_iterator = typename array_t::iterator();
5421  break;
5422  }
5423 
5424  default:
5425  {
5426  m_it.primitive_iterator = primitive_iterator_t();
5427  break;
5428  }
5429  }
5430  }
5431 
5433  const_iterator(const iterator& other) : m_object(other.m_object)
5434  {
5435  switch (m_object->m_type)
5436  {
5438  {
5439  m_it.object_iterator = other.m_it.object_iterator;
5440  break;
5441  }
5442 
5444  {
5445  m_it.array_iterator = other.m_it.array_iterator;
5446  break;
5447  }
5448 
5449  default:
5450  {
5451  m_it.primitive_iterator = other.m_it.primitive_iterator;
5452  break;
5453  }
5454  }
5455  }
5456 
5458  const_iterator(const const_iterator& other) noexcept
5459  : m_object(other.m_object), m_it(other.m_it)
5460  {}
5461 
5464  std::is_nothrow_move_constructible<pointer>::value and
5465  std::is_nothrow_move_assignable<pointer>::value and
5466  std::is_nothrow_move_constructible<internal_iterator>::value and
5467  std::is_nothrow_move_assignable<internal_iterator>::value
5468  )
5469  {
5470  std::swap(m_object, other.m_object);
5471  std::swap(m_it, other.m_it);
5472  return *this;
5473  }
5474 
5475  private:
5477  void set_begin()
5478  {
5479  switch (m_object->m_type)
5480  {
5482  {
5483  m_it.object_iterator = m_object->m_value.object->begin();
5484  break;
5485  }
5486 
5488  {
5489  m_it.array_iterator = m_object->m_value.array->begin();
5490  break;
5491  }
5492 
5494  {
5495  // set to end so begin()==end() is true: null is empty
5496  m_it.primitive_iterator.set_end();
5497  break;
5498  }
5499 
5500  default:
5501  {
5502  m_it.primitive_iterator.set_begin();
5503  break;
5504  }
5505  }
5506  }
5507 
5509  void set_end()
5510  {
5511  switch (m_object->m_type)
5512  {
5514  {
5515  m_it.object_iterator = m_object->m_value.object->end();
5516  break;
5517  }
5518 
5520  {
5521  m_it.array_iterator = m_object->m_value.array->end();
5522  break;
5523  }
5524 
5525  default:
5526  {
5527  m_it.primitive_iterator.set_end();
5528  break;
5529  }
5530  }
5531  }
5532 
5533  public:
5536  {
5537  switch (m_object->m_type)
5538  {
5540  {
5541  return m_it.object_iterator->second;
5542  }
5543 
5545  {
5546  return *m_it.array_iterator;
5547  }
5548 
5550  {
5551  throw std::out_of_range("cannot get value");
5552  }
5553 
5554  default:
5555  {
5556  if (m_it.primitive_iterator.is_begin())
5557  {
5558  return *m_object;
5559  }
5560  else
5561  {
5562  throw std::out_of_range("cannot get value");
5563  }
5564  }
5565  }
5566  }
5567 
5570  {
5571  switch (m_object->m_type)
5572  {
5574  {
5575  return &(m_it.object_iterator->second);
5576  }
5577 
5579  {
5580  return &*m_it.array_iterator;
5581  }
5582 
5583  default:
5584  {
5585  if (m_it.primitive_iterator.is_begin())
5586  {
5587  return m_object;
5588  }
5589  else
5590  {
5591  throw std::out_of_range("cannot get value");
5592  }
5593  }
5594  }
5595  }
5596 
5599  {
5600  auto result = *this;
5601  ++(*this);
5602  return result;
5603  }
5604 
5607  {
5608  switch (m_object->m_type)
5609  {
5611  {
5612  ++m_it.object_iterator;
5613  break;
5614  }
5615 
5617  {
5618  ++m_it.array_iterator;
5619  break;
5620  }
5621 
5622  default:
5623  {
5624  ++m_it.primitive_iterator;
5625  break;
5626  }
5627  }
5628 
5629  return *this;
5630  }
5631 
5634  {
5635  auto result = *this;
5636  --(*this);
5637  return result;
5638  }
5639 
5642  {
5643  switch (m_object->m_type)
5644  {
5646  {
5647  --m_it.object_iterator;
5648  break;
5649  }
5650 
5652  {
5653  --m_it.array_iterator;
5654  break;
5655  }
5656 
5657  default:
5658  {
5659  --m_it.primitive_iterator;
5660  break;
5661  }
5662  }
5663 
5664  return *this;
5665  }
5666 
5668  bool operator==(const const_iterator& other) const
5669  {
5670  // if objects are not the same, the comparison is undefined
5671  if (m_object != other.m_object)
5672  {
5673  throw std::domain_error("cannot compare iterators of different containers");
5674  }
5675 
5676  switch (m_object->m_type)
5677  {
5679  {
5680  return (m_it.object_iterator == other.m_it.object_iterator);
5681  }
5682 
5684  {
5685  return (m_it.array_iterator == other.m_it.array_iterator);
5686  }
5687 
5688  default:
5689  {
5690  return (m_it.primitive_iterator == other.m_it.primitive_iterator);
5691  }
5692  }
5693  }
5694 
5696  bool operator!=(const const_iterator& other) const
5697  {
5698  return not operator==(other);
5699  }
5700 
5702  bool operator<(const const_iterator& other) const
5703  {
5704  // if objects are not the same, the comparison is undefined
5705  if (m_object != other.m_object)
5706  {
5707  throw std::domain_error("cannot compare iterators of different containers");
5708  }
5709 
5710  switch (m_object->m_type)
5711  {
5713  {
5714  throw std::domain_error("cannot use operator< for object iterators");
5715  }
5716 
5718  {
5719  return (m_it.array_iterator < other.m_it.array_iterator);
5720  }
5721 
5722  default:
5723  {
5724  return (m_it.primitive_iterator < other.m_it.primitive_iterator);
5725  }
5726  }
5727  }
5728 
5730  bool operator<=(const const_iterator& other) const
5731  {
5732  return not other.operator < (*this);
5733  }
5734 
5736  bool operator>(const const_iterator& other) const
5737  {
5738  return not operator<=(other);
5739  }
5740 
5742  bool operator>=(const const_iterator& other) const
5743  {
5744  return not operator<(other);
5745  }
5746 
5749  {
5750  switch (m_object->m_type)
5751  {
5753  {
5754  throw std::domain_error("cannot use operator+= for object iterators");
5755  }
5756 
5758  {
5759  m_it.array_iterator += i;
5760  break;
5761  }
5762 
5763  default:
5764  {
5765  m_it.primitive_iterator += i;
5766  break;
5767  }
5768  }
5769 
5770  return *this;
5771  }
5772 
5775  {
5776  return operator+=(-i);
5777  }
5778 
5781  {
5782  auto result = *this;
5783  result += i;
5784  return result;
5785  }
5786 
5789  {
5790  auto result = *this;
5791  result -= i;
5792  return result;
5793  }
5794 
5797  {
5798  switch (m_object->m_type)
5799  {
5801  {
5802  throw std::domain_error("cannot use operator- for object iterators");
5803  }
5804 
5806  {
5807  return m_it.array_iterator - other.m_it.array_iterator;
5808  }
5809 
5810  default:
5811  {
5812  return m_it.primitive_iterator - other.m_it.primitive_iterator;
5813  }
5814  }
5815  }
5816 
5819  {
5820  switch (m_object->m_type)
5821  {
5823  {
5824  throw std::domain_error("cannot use operator[] for object iterators");
5825  }
5826 
5828  {
5829  return *(m_it.array_iterator + n);
5830  }
5831 
5833  {
5834  throw std::out_of_range("cannot get value");
5835  }
5836 
5837  default:
5838  {
5839  if (m_it.primitive_iterator == -n)
5840  {
5841  return *m_object;
5842  }
5843  else
5844  {
5845  throw std::out_of_range("cannot get value");
5846  }
5847  }
5848  }
5849  }
5850 
5852  typename object_t::key_type key() const
5853  {
5854  if (m_object->is_object())
5855  {
5856  return m_it.object_iterator->first;
5857  }
5858  else
5859  {
5860  throw std::domain_error("cannot use key() for non-object iterators");
5861  }
5862  }
5863 
5866  {
5867  return operator*();
5868  }
5869 
5870  private:
5872  pointer m_object = nullptr;
5874  internal_iterator m_it = internal_iterator();
5875  };
5876 
5889  class iterator : public const_iterator
5890  {
5891  public:
5893  using pointer = typename basic_json::pointer;
5895 
5897  iterator() = default;
5898 
5900  iterator(pointer object) noexcept : base_iterator(object)
5901  {}
5902 
5904  iterator(const iterator& other) noexcept
5905  : base_iterator(other)
5906  {}
5907 
5909  iterator& operator=(iterator other) noexcept(
5910  std::is_nothrow_move_constructible<pointer>::value and
5911  std::is_nothrow_move_assignable<pointer>::value and
5912  std::is_nothrow_move_constructible<internal_iterator>::value and
5913  std::is_nothrow_move_assignable<internal_iterator>::value
5914  )
5915  {
5916  base_iterator::operator=(other);
5917  return *this;
5918  }
5919 
5922  {
5923  return const_cast<reference>(base_iterator::operator*());
5924  }
5925 
5928  {
5929  return const_cast<pointer>(base_iterator::operator->());
5930  }
5931 
5934  {
5935  iterator result = *this;
5937  return result;
5938  }
5939 
5942  {
5944  return *this;
5945  }
5946 
5949  {
5950  iterator result = *this;
5952  return result;
5953  }
5954 
5957  {
5959  return *this;
5960  }
5961 
5964  {
5966  return *this;
5967  }
5968 
5971  {
5973  return *this;
5974  }
5975 
5978  {
5979  auto result = *this;
5980  result += i;
5981  return result;
5982  }
5983 
5986  {
5987  auto result = *this;
5988  result -= i;
5989  return result;
5990  }
5991 
5992  difference_type operator-(const iterator& other) const
5993  {
5994  return base_iterator::operator-(other);
5995  }
5996 
5999  {
6000  return const_cast<reference>(base_iterator::operator[](n));
6001  }
6002 
6005  {
6006  return const_cast<reference>(base_iterator::value());
6007  }
6008  };
6009 
6027  template<typename Base>
6028  class json_reverse_iterator : public std::reverse_iterator<Base>
6029  {
6030  public:
6032  using base_iterator = std::reverse_iterator<Base>;
6034  using reference = typename Base::reference;
6035 
6037  json_reverse_iterator(const typename base_iterator::iterator_type& it)
6038  : base_iterator(it) {}
6039 
6042 
6045  {
6046  return base_iterator::operator++(1);
6047  }
6048 
6051  {
6052  base_iterator::operator++();
6053  return *this;
6054  }
6055 
6058  {
6059  return base_iterator::operator--(1);
6060  }
6061 
6064  {
6065  base_iterator::operator--();
6066  return *this;
6067  }
6068 
6071  {
6072  base_iterator::operator+=(i);
6073  return *this;
6074  }
6075 
6078  {
6079  auto result = *this;
6080  result += i;
6081  return result;
6082  }
6083 
6086  {
6087  auto result = *this;
6088  result -= i;
6089  return result;
6090  }
6091 
6094  {
6095  return this->base() - other.base();
6096  }
6097 
6100  {
6101  return *(this->operator+(n));
6102  }
6103 
6105  typename object_t::key_type key() const
6106  {
6107  auto it = --this->base();
6108  return it.key();
6109  }
6110 
6113  {
6114  auto it = --this->base();
6115  return it.operator * ();
6116  }
6117  };
6118 
6127  {
6128  private:
6130  basic_json& container;
6132  using json_iterator = decltype(std::begin(container));
6133 
6135  class iterator_wrapper_internal
6136  {
6137  private:
6139  json_iterator anchor;
6141  size_t array_index = 0;
6142 
6143  public:
6145  iterator_wrapper_internal(json_iterator i) : anchor(i)
6146  {}
6147 
6149  iterator_wrapper_internal& operator*()
6150  {
6151  return *this;
6152  }
6153 
6155  iterator_wrapper_internal& operator++()
6156  {
6157  ++anchor;
6158  ++array_index;
6159 
6160  return *this;
6161  }
6162 
6164  bool operator!= (const iterator_wrapper_internal& o)
6165  {
6166  return anchor != o.anchor;
6167  }
6168 
6170  typename basic_json::string_t key() const
6171  {
6172  switch (anchor.m_object->type())
6173  {
6174  // use integer array index as key
6175  case value_t::array:
6176  {
6177  return std::to_string(array_index);
6178  }
6179 
6180  // use key from the object
6181  case value_t::object:
6182  {
6183  return anchor.key();
6184  }
6185 
6186  // use an empty key for all primitive types
6187  default:
6188  {
6189  return "";
6190  }
6191  }
6192  }
6193 
6195  typename json_iterator::reference value() const
6196  {
6197  return anchor.value();
6198  }
6199  };
6200 
6201  public:
6203  iterator_wrapper(basic_json& cont)
6204  : container(cont)
6205  {}
6206 
6208  iterator_wrapper_internal begin()
6209  {
6210  return iterator_wrapper_internal(container.begin());
6211  }
6212 
6214  iterator_wrapper_internal end()
6215  {
6216  return iterator_wrapper_internal(container.end());
6217  }
6218  };
6219 
6220  private:
6222  // lexer and parser //
6224 
6232  class lexer
6233  {
6234  public:
6236  enum class token_type
6237  {
6238  uninitialized,
6239  literal_true,
6240  literal_false,
6241  literal_null,
6242  value_string,
6243  value_number,
6244  begin_array,
6245  begin_object,
6246  end_array,
6247  end_object,
6248  name_separator,
6249  value_separator,
6250  parse_error,
6251  end_of_input
6252  };
6253 
6255  using lexer_char_t = unsigned char;
6256 
6258  explicit lexer(const string_t& s) noexcept
6259  : m_stream(nullptr), m_buffer(s)
6260  {
6261  m_content = reinterpret_cast<const lexer_char_t*>(s.c_str());
6262  m_start = m_cursor = m_content;
6263  m_limit = m_content + s.size();
6264  }
6265  explicit lexer(std::istream* s) noexcept
6266  : m_stream(s), m_buffer()
6267  {
6268  getline(*m_stream, m_buffer);
6269  m_content = reinterpret_cast<const lexer_char_t*>(m_buffer.c_str());
6270  m_start = m_cursor = m_content;
6271  m_limit = m_content + m_buffer.size();
6272  }
6273 
6275  lexer() = default;
6276 
6277  // switch of unwanted functions
6278  lexer(const lexer&) = delete;
6279  lexer operator=(const lexer&) = delete;
6280 
6292  static string_t to_unicode(const std::size_t codepoint1,
6293  const std::size_t codepoint2 = 0)
6294  {
6295  string_t result;
6296 
6297  // calculate the codepoint from the given code points
6298  std::size_t codepoint = codepoint1;
6299 
6300  // check if codepoint1 is a high surrogate
6301  if (codepoint1 >= 0xD800 and codepoint1 <= 0xDBFF)
6302  {
6303  // check if codepoint2 is a low surrogate
6304  if (codepoint2 >= 0xDC00 and codepoint2 <= 0xDFFF)
6305  {
6306  codepoint =
6307  // high surrogate occupies the most significant 22 bits
6308  (codepoint1 << 10)
6309  // low surrogate occupies the least significant 15 bits
6310  + codepoint2
6311  // there is still the 0xD800, 0xDC00 and 0x10000 noise
6312  // in the result so we have to substract with:
6313  // (0xD800 << 10) + DC00 - 0x10000 = 0x35FDC00
6314  - 0x35FDC00;
6315  }
6316  else
6317  {
6318  throw std::invalid_argument("missing or wrong low surrogate");
6319  }
6320  }
6321 
6322  if (codepoint < 0x80)
6323  {
6324  // 1-byte characters: 0xxxxxxx (ASCII)
6325  result.append(1, static_cast<typename string_t::value_type>(codepoint));
6326  }
6327  else if (codepoint <= 0x7ff)
6328  {
6329  // 2-byte characters: 110xxxxx 10xxxxxx
6330  result.append(1, static_cast<typename string_t::value_type>(0xC0 | ((codepoint >> 6) & 0x1F)));
6331  result.append(1, static_cast<typename string_t::value_type>(0x80 | (codepoint & 0x3F)));
6332  }
6333  else if (codepoint <= 0xffff)
6334  {
6335  // 3-byte characters: 1110xxxx 10xxxxxx 10xxxxxx
6336  result.append(1, static_cast<typename string_t::value_type>(0xE0 | ((codepoint >> 12) & 0x0F)));
6337  result.append(1, static_cast<typename string_t::value_type>(0x80 | ((codepoint >> 6) & 0x3F)));
6338  result.append(1, static_cast<typename string_t::value_type>(0x80 | (codepoint & 0x3F)));
6339  }
6340  else if (codepoint <= 0x10ffff)
6341  {
6342  // 4-byte characters: 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
6343  result.append(1, static_cast<typename string_t::value_type>(0xF0 | ((codepoint >> 18) & 0x07)));
6344  result.append(1, static_cast<typename string_t::value_type>(0x80 | ((codepoint >> 12) & 0x3F)));
6345  result.append(1, static_cast<typename string_t::value_type>(0x80 | ((codepoint >> 6) & 0x3F)));
6346  result.append(1, static_cast<typename string_t::value_type>(0x80 | (codepoint & 0x3F)));
6347  }
6348  else
6349  {
6350  throw std::out_of_range("code points above 0x10FFFF are invalid");
6351  }
6352 
6353  return result;
6354  }
6355 
6357  static std::string token_type_name(token_type t)
6358  {
6359  switch (t)
6360  {
6361  case token_type::uninitialized:
6362  return "<uninitialized>";
6363  case token_type::literal_true:
6364  return "true literal";
6365  case token_type::literal_false:
6366  return "false literal";
6367  case token_type::literal_null:
6368  return "null literal";
6369  case token_type::value_string:
6370  return "string literal";
6371  case token_type::value_number:
6372  return "number literal";
6373  case token_type::begin_array:
6374  return "[";
6375  case token_type::begin_object:
6376  return "{";
6377  case token_type::end_array:
6378  return "]";
6379  case token_type::end_object:
6380  return "}";
6381  case token_type::name_separator:
6382  return ":";
6383  case token_type::value_separator:
6384  return ",";
6385  case token_type::parse_error:
6386  return "<parse error>";
6387  case token_type::end_of_input:
6388  return "<end of input>";
6389  default:
6390  {
6391  // catch non-enum values
6392  return "unknown token"; // LCOV_EXCL_LINE
6393  }
6394  }
6395  }
6396 
6407  token_type scan() noexcept
6408  {
6409  // pointer for backtracking information
6410  m_marker = nullptr;
6411 
6412  // remember the begin of the token
6413  m_start = m_cursor;
6414 
6415 
6416  {
6417  lexer_char_t yych;
6418  unsigned int yyaccept = 0;
6419  static const unsigned char yybm[] =
6420  {
6421  0, 0, 0, 0, 0, 0, 0, 0,
6422  0, 32, 32, 0, 0, 32, 0, 0,
6423  64, 64, 64, 64, 64, 64, 64, 64,
6424  64, 64, 64, 64, 64, 64, 64, 64,
6425  96, 64, 0, 64, 64, 64, 64, 64,
6426  64, 64, 64, 64, 64, 64, 64, 64,
6427  192, 192, 192, 192, 192, 192, 192, 192,
6428  192, 192, 64, 64, 64, 64, 64, 64,
6429  64, 64, 64, 64, 64, 64, 64, 64,
6430  64, 64, 64, 64, 64, 64, 64, 64,
6431  64, 64, 64, 64, 64, 64, 64, 64,
6432  64, 64, 64, 64, 0, 64, 64, 64,
6433  64, 64, 64, 64, 64, 64, 64, 64,
6434  64, 64, 64, 64, 64, 64, 64, 64,
6435  64, 64, 64, 64, 64, 64, 64, 64,
6436  64, 64, 64, 64, 64, 64, 64, 64,
6437  64, 64, 64, 64, 64, 64, 64, 64,
6438  64, 64, 64, 64, 64, 64, 64, 64,
6439  64, 64, 64, 64, 64, 64, 64, 64,
6440  64, 64, 64, 64, 64, 64, 64, 64,
6441  64, 64, 64, 64, 64, 64, 64, 64,
6442  64, 64, 64, 64, 64, 64, 64, 64,
6443  64, 64, 64, 64, 64, 64, 64, 64,
6444  64, 64, 64, 64, 64, 64, 64, 64,
6445  64, 64, 64, 64, 64, 64, 64, 64,
6446  64, 64, 64, 64, 64, 64, 64, 64,
6447  64, 64, 64, 64, 64, 64, 64, 64,
6448  64, 64, 64, 64, 64, 64, 64, 64,
6449  64, 64, 64, 64, 64, 64, 64, 64,
6450  64, 64, 64, 64, 64, 64, 64, 64,
6451  64, 64, 64, 64, 64, 64, 64, 64,
6452  64, 64, 64, 64, 64, 64, 64, 64,
6453  };
6454  if ((m_limit - m_cursor) < 5)
6455  {
6456  yyfill(); // LCOV_EXCL_LINE;
6457  }
6458  yych = *m_cursor;
6459  if (yych <= ':')
6460  {
6461  if (yych <= ' ')
6462  {
6463  if (yych <= '\n')
6464  {
6465  if (yych <= 0x00)
6466  {
6467  goto basic_json_parser_28;
6468  }
6469  if (yych <= 0x08)
6470  {
6471  goto basic_json_parser_30;
6472  }
6473  if (yych >= '\n')
6474  {
6475  goto basic_json_parser_4;
6476  }
6477  }
6478  else
6479  {
6480  if (yych == '\r')
6481  {
6482  goto basic_json_parser_2;
6483  }
6484  if (yych <= 0x1F)
6485  {
6486  goto basic_json_parser_30;
6487  }
6488  }
6489  }
6490  else
6491  {
6492  if (yych <= ',')
6493  {
6494  if (yych == '"')
6495  {
6496  goto basic_json_parser_27;
6497  }
6498  if (yych <= '+')
6499  {
6500  goto basic_json_parser_30;
6501  }
6502  goto basic_json_parser_16;
6503  }
6504  else
6505  {
6506  if (yych <= '/')
6507  {
6508  if (yych <= '-')
6509  {
6510  goto basic_json_parser_23;
6511  }
6512  goto basic_json_parser_30;
6513  }
6514  else
6515  {
6516  if (yych <= '0')
6517  {
6518  goto basic_json_parser_24;
6519  }
6520  if (yych <= '9')
6521  {
6522  goto basic_json_parser_26;
6523  }
6524  goto basic_json_parser_18;
6525  }
6526  }
6527  }
6528  }
6529  else
6530  {
6531  if (yych <= 'n')
6532  {
6533  if (yych <= ']')
6534  {
6535  if (yych == '[')
6536  {
6537  goto basic_json_parser_8;
6538  }
6539  if (yych <= '\\')
6540  {
6541  goto basic_json_parser_30;
6542  }
6543  goto basic_json_parser_10;
6544  }
6545  else
6546  {
6547  if (yych == 'f')
6548  {
6549  goto basic_json_parser_22;
6550  }
6551  if (yych <= 'm')
6552  {
6553  goto basic_json_parser_30;
6554  }
6555  goto basic_json_parser_20;
6556  }
6557  }
6558  else
6559  {
6560  if (yych <= '{')
6561  {
6562  if (yych == 't')
6563  {
6564  goto basic_json_parser_21;
6565  }
6566  if (yych <= 'z')
6567  {
6568  goto basic_json_parser_30;
6569  }
6570  goto basic_json_parser_12;
6571  }
6572  else
6573  {
6574  if (yych <= '}')
6575  {
6576  if (yych <= '|')
6577  {
6578  goto basic_json_parser_30;
6579  }
6580  goto basic_json_parser_14;
6581  }
6582  else
6583  {
6584  if (yych == 0xEF)
6585  {
6586  goto basic_json_parser_6;
6587  }
6588  goto basic_json_parser_30;
6589  }
6590  }
6591  }
6592  }
6593 basic_json_parser_2:
6594  ++m_cursor;
6595  yych = *m_cursor;
6596  goto basic_json_parser_5;
6597 basic_json_parser_3:
6598  {
6599  return scan();
6600  }
6601 basic_json_parser_4:
6602  ++m_cursor;
6603  if (m_limit <= m_cursor)
6604  {
6605  yyfill(); // LCOV_EXCL_LINE;
6606  }
6607  yych = *m_cursor;
6608 basic_json_parser_5:
6609  if (yybm[0 + yych] & 32)
6610  {
6611  goto basic_json_parser_4;
6612  }
6613  goto basic_json_parser_3;
6614 basic_json_parser_6:
6615  yyaccept = 0;
6616  yych = *(m_marker = ++m_cursor);
6617  if (yych == 0xBB)
6618  {
6619  goto basic_json_parser_64;
6620  }
6621 basic_json_parser_7:
6622  {
6623  return token_type::parse_error;
6624  }
6625 basic_json_parser_8:
6626  ++m_cursor;
6627  {
6628  return token_type::begin_array;
6629  }
6630 basic_json_parser_10:
6631  ++m_cursor;
6632  {
6633  return token_type::end_array;
6634  }
6635 basic_json_parser_12:
6636  ++m_cursor;
6637  {
6638  return token_type::begin_object;
6639  }
6640 basic_json_parser_14:
6641  ++m_cursor;
6642  {
6643  return token_type::end_object;
6644  }
6645 basic_json_parser_16:
6646  ++m_cursor;
6647  {
6648  return token_type::value_separator;
6649  }
6650 basic_json_parser_18:
6651  ++m_cursor;
6652  {
6653  return token_type::name_separator;
6654  }
6655 basic_json_parser_20:
6656  yyaccept = 0;
6657  yych = *(m_marker = ++m_cursor);
6658  if (yych == 'u')
6659  {
6660  goto basic_json_parser_60;
6661  }
6662  goto basic_json_parser_7;
6663 basic_json_parser_21:
6664  yyaccept = 0;
6665  yych = *(m_marker = ++m_cursor);
6666  if (yych == 'r')
6667  {
6668  goto basic_json_parser_56;
6669  }
6670  goto basic_json_parser_7;
6671 basic_json_parser_22:
6672  yyaccept = 0;
6673  yych = *(m_marker = ++m_cursor);
6674  if (yych == 'a')
6675  {
6676  goto basic_json_parser_51;
6677  }
6678  goto basic_json_parser_7;
6679 basic_json_parser_23:
6680  yych = *++m_cursor;
6681  if (yych <= '/')
6682  {
6683  goto basic_json_parser_7;
6684  }
6685  if (yych <= '0')
6686  {
6687  goto basic_json_parser_50;
6688  }
6689  if (yych <= '9')
6690  {
6691  goto basic_json_parser_41;
6692  }
6693  goto basic_json_parser_7;
6694 basic_json_parser_24:
6695  yyaccept = 1;
6696  yych = *(m_marker = ++m_cursor);
6697  if (yych <= 'D')
6698  {
6699  if (yych == '.')
6700  {
6701  goto basic_json_parser_43;
6702  }
6703  }
6704  else
6705  {
6706  if (yych <= 'E')
6707  {
6708  goto basic_json_parser_44;
6709  }
6710  if (yych == 'e')
6711  {
6712  goto basic_json_parser_44;
6713  }
6714  }
6715 basic_json_parser_25:
6716  {
6717  return token_type::value_number;
6718  }
6719 basic_json_parser_26:
6720  yyaccept = 1;
6721  yych = *(m_marker = ++m_cursor);
6722  goto basic_json_parser_42;
6723 basic_json_parser_27:
6724  yyaccept = 0;
6725  yych = *(m_marker = ++m_cursor);
6726  if (yych <= 0x0F)
6727  {
6728  goto basic_json_parser_7;
6729  }
6730  goto basic_json_parser_32;
6731 basic_json_parser_28:
6732  ++m_cursor;
6733  {
6734  return token_type::end_of_input;
6735  }
6736 basic_json_parser_30:
6737  yych = *++m_cursor;
6738  goto basic_json_parser_7;
6739 basic_json_parser_31:
6740  ++m_cursor;
6741  if (m_limit <= m_cursor)
6742  {
6743  yyfill(); // LCOV_EXCL_LINE;
6744  }
6745  yych = *m_cursor;
6746 basic_json_parser_32:
6747  if (yybm[0 + yych] & 64)
6748  {
6749  goto basic_json_parser_31;
6750  }
6751  if (yych <= 0x0F)
6752  {
6753  goto basic_json_parser_33;
6754  }
6755  if (yych <= '"')
6756  {
6757  goto basic_json_parser_35;
6758  }
6759  goto basic_json_parser_34;
6760 basic_json_parser_33:
6761  m_cursor = m_marker;
6762  if (yyaccept == 0)
6763  {
6764  goto basic_json_parser_7;
6765  }
6766  else
6767  {
6768  goto basic_json_parser_25;
6769  }
6770 basic_json_parser_34:
6771  ++m_cursor;
6772  if (m_limit <= m_cursor)
6773  {
6774  yyfill(); // LCOV_EXCL_LINE;
6775  }
6776  yych = *m_cursor;
6777  if (yych <= 'e')
6778  {
6779  if (yych <= '/')
6780  {
6781  if (yych == '"')
6782  {
6783  goto basic_json_parser_31;
6784  }
6785  if (yych <= '.')
6786  {
6787  goto basic_json_parser_33;
6788  }
6789  goto basic_json_parser_31;
6790  }
6791  else
6792  {
6793  if (yych <= '\\')
6794  {
6795  if (yych <= '[')
6796  {
6797  goto basic_json_parser_33;
6798  }
6799  goto basic_json_parser_31;
6800  }
6801  else
6802  {
6803  if (yych == 'b')
6804  {
6805  goto basic_json_parser_31;
6806  }
6807  goto basic_json_parser_33;
6808  }
6809  }
6810  }
6811  else
6812  {
6813  if (yych <= 'q')
6814  {
6815  if (yych <= 'f')
6816  {
6817  goto basic_json_parser_31;
6818  }
6819  if (yych == 'n')
6820  {
6821  goto basic_json_parser_31;
6822  }
6823  goto basic_json_parser_33;
6824  }
6825  else
6826  {
6827  if (yych <= 's')
6828  {
6829  if (yych <= 'r')
6830  {
6831  goto basic_json_parser_31;
6832  }
6833  goto basic_json_parser_33;
6834  }
6835  else
6836  {
6837  if (yych <= 't')
6838  {
6839  goto basic_json_parser_31;
6840  }
6841  if (yych <= 'u')
6842  {
6843  goto basic_json_parser_37;
6844  }
6845  goto basic_json_parser_33;
6846  }
6847  }
6848  }
6849 basic_json_parser_35:
6850  ++m_cursor;
6851  {
6852  return token_type::value_string;
6853  }
6854 basic_json_parser_37:
6855  ++m_cursor;
6856  if (m_limit <= m_cursor)
6857  {
6858  yyfill(); // LCOV_EXCL_LINE;
6859  }
6860  yych = *m_cursor;
6861  if (yych <= '@')
6862  {
6863  if (yych <= '/')
6864  {
6865  goto basic_json_parser_33;
6866  }
6867  if (yych >= ':')
6868  {
6869  goto basic_json_parser_33;
6870  }
6871  }
6872  else
6873  {
6874  if (yych <= 'F')
6875  {
6876  goto basic_json_parser_38;
6877  }
6878  if (yych <= '`')
6879  {
6880  goto basic_json_parser_33;
6881  }
6882  if (yych >= 'g')
6883  {
6884  goto basic_json_parser_33;
6885  }
6886  }
6887 basic_json_parser_38:
6888  ++m_cursor;
6889  if (m_limit <= m_cursor)
6890  {
6891  yyfill(); // LCOV_EXCL_LINE;
6892  }
6893  yych = *m_cursor;
6894  if (yych <= '@')
6895  {
6896  if (yych <= '/')
6897  {
6898  goto basic_json_parser_33;
6899  }
6900  if (yych >= ':')
6901  {
6902  goto basic_json_parser_33;
6903  }
6904  }
6905  else
6906  {
6907  if (yych <= 'F')
6908  {
6909  goto basic_json_parser_39;
6910  }
6911  if (yych <= '`')
6912  {
6913  goto basic_json_parser_33;
6914  }
6915  if (yych >= 'g')
6916  {
6917  goto basic_json_parser_33;
6918  }
6919  }
6920 basic_json_parser_39:
6921  ++m_cursor;
6922  if (m_limit <= m_cursor)
6923  {
6924  yyfill(); // LCOV_EXCL_LINE;
6925  }
6926  yych = *m_cursor;
6927  if (yych <= '@')
6928  {
6929  if (yych <= '/')
6930  {
6931  goto basic_json_parser_33;
6932  }
6933  if (yych >= ':')
6934  {
6935  goto basic_json_parser_33;
6936  }
6937  }
6938  else
6939  {
6940  if (yych <= 'F')
6941  {
6942  goto basic_json_parser_40;
6943  }
6944  if (yych <= '`')
6945  {
6946  goto basic_json_parser_33;
6947  }
6948  if (yych >= 'g')
6949  {
6950  goto basic_json_parser_33;
6951  }
6952  }
6953 basic_json_parser_40:
6954  ++m_cursor;
6955  if (m_limit <= m_cursor)
6956  {
6957  yyfill(); // LCOV_EXCL_LINE;
6958  }
6959  yych = *m_cursor;
6960  if (yych <= '@')
6961  {
6962  if (yych <= '/')
6963  {
6964  goto basic_json_parser_33;
6965  }
6966  if (yych <= '9')
6967  {
6968  goto basic_json_parser_31;
6969  }
6970  goto basic_json_parser_33;
6971  }
6972  else
6973  {
6974  if (yych <= 'F')
6975  {
6976  goto basic_json_parser_31;
6977  }
6978  if (yych <= '`')
6979  {
6980  goto basic_json_parser_33;
6981  }
6982  if (yych <= 'f')
6983  {
6984  goto basic_json_parser_31;
6985  }
6986  goto basic_json_parser_33;
6987  }
6988 basic_json_parser_41:
6989  yyaccept = 1;
6990  m_marker = ++m_cursor;
6991  if ((m_limit - m_cursor) < 3)
6992  {
6993  yyfill(); // LCOV_EXCL_LINE;
6994  }
6995  yych = *m_cursor;
6996 basic_json_parser_42:
6997  if (yybm[0 + yych] & 128)
6998  {
6999  goto basic_json_parser_41;
7000  }
7001  if (yych <= 'D')
7002  {
7003  if (yych != '.')
7004  {
7005  goto basic_json_parser_25;
7006  }
7007  }
7008  else
7009  {
7010  if (yych <= 'E')
7011  {
7012  goto basic_json_parser_44;
7013  }
7014  if (yych == 'e')
7015  {
7016  goto basic_json_parser_44;
7017  }
7018  goto basic_json_parser_25;
7019  }
7020 basic_json_parser_43:
7021  yych = *++m_cursor;
7022  if (yych <= '/')
7023  {
7024  goto basic_json_parser_33;
7025  }
7026  if (yych <= '9')
7027  {
7028  goto basic_json_parser_48;
7029  }
7030  goto basic_json_parser_33;
7031 basic_json_parser_44:
7032  yych = *++m_cursor;
7033  if (yych <= ',')
7034  {
7035  if (yych != '+')
7036  {
7037  goto basic_json_parser_33;
7038  }
7039  }
7040  else
7041  {
7042  if (yych <= '-')
7043  {
7044  goto basic_json_parser_45;
7045  }
7046  if (yych <= '/')
7047  {
7048  goto basic_json_parser_33;
7049  }
7050  if (yych <= '9')
7051  {
7052  goto basic_json_parser_46;
7053  }
7054  goto basic_json_parser_33;
7055  }
7056 basic_json_parser_45:
7057  yych = *++m_cursor;
7058  if (yych <= '/')
7059  {
7060  goto basic_json_parser_33;
7061  }
7062  if (yych >= ':')
7063  {
7064  goto basic_json_parser_33;
7065  }
7066 basic_json_parser_46:
7067  ++m_cursor;
7068  if (m_limit <= m_cursor)
7069  {
7070  yyfill(); // LCOV_EXCL_LINE;
7071  }
7072  yych = *m_cursor;
7073  if (yych <= '/')
7074  {
7075  goto basic_json_parser_25;
7076  }
7077  if (yych <= '9')
7078  {
7079  goto basic_json_parser_46;
7080  }
7081  goto basic_json_parser_25;
7082 basic_json_parser_48:
7083  yyaccept = 1;
7084  m_marker = ++m_cursor;
7085  if ((m_limit - m_cursor) < 3)
7086  {
7087  yyfill(); // LCOV_EXCL_LINE;
7088  }
7089  yych = *m_cursor;
7090  if (yych <= 'D')
7091  {
7092  if (yych <= '/')
7093  {
7094  goto basic_json_parser_25;
7095  }
7096  if (yych <= '9')
7097  {
7098  goto basic_json_parser_48;
7099  }
7100  goto basic_json_parser_25;
7101  }
7102  else
7103  {
7104  if (yych <= 'E')
7105  {
7106  goto basic_json_parser_44;
7107  }
7108  if (yych == 'e')
7109  {
7110  goto basic_json_parser_44;
7111  }
7112  goto basic_json_parser_25;
7113  }
7114 basic_json_parser_50:
7115  yyaccept = 1;
7116  yych = *(m_marker = ++m_cursor);
7117  if (yych <= 'D')
7118  {
7119  if (yych == '.')
7120  {
7121  goto basic_json_parser_43;
7122  }
7123  goto basic_json_parser_25;
7124  }
7125  else
7126  {
7127  if (yych <= 'E')
7128  {
7129  goto basic_json_parser_44;
7130  }
7131  if (yych == 'e')
7132  {
7133  goto basic_json_parser_44;
7134  }
7135  goto basic_json_parser_25;
7136  }
7137 basic_json_parser_51:
7138  yych = *++m_cursor;
7139  if (yych != 'l')
7140  {
7141  goto basic_json_parser_33;
7142  }
7143  yych = *++m_cursor;
7144  if (yych != 's')
7145  {
7146  goto basic_json_parser_33;
7147  }
7148  yych = *++m_cursor;
7149  if (yych != 'e')
7150  {
7151  goto basic_json_parser_33;
7152  }
7153  ++m_cursor;
7154  {
7155  return token_type::literal_false;
7156  }
7157 basic_json_parser_56:
7158  yych = *++m_cursor;
7159  if (yych != 'u')
7160  {
7161  goto basic_json_parser_33;
7162  }
7163  yych = *++m_cursor;
7164  if (yych != 'e')
7165  {
7166  goto basic_json_parser_33;
7167  }
7168  ++m_cursor;
7169  {
7170  return token_type::literal_true;
7171  }
7172 basic_json_parser_60:
7173  yych = *++m_cursor;
7174  if (yych != 'l')
7175  {
7176  goto basic_json_parser_33;
7177  }
7178  yych = *++m_cursor;
7179  if (yych != 'l')
7180  {
7181  goto basic_json_parser_33;
7182  }
7183  ++m_cursor;
7184  {
7185  return token_type::literal_null;
7186  }
7187 basic_json_parser_64:
7188  yych = *++m_cursor;
7189  if (yych != 0xBF)
7190  {
7191  goto basic_json_parser_33;
7192  }
7193  ++m_cursor;
7194  {
7195  return scan();
7196  }
7197  }
7198 
7199 
7200  }
7201 
7203  void yyfill() noexcept
7204  {
7205  if (not m_stream or not * m_stream)
7206  {
7207  return;
7208  }
7209 
7210  const ssize_t offset_start = m_start - m_content;
7211  const ssize_t offset_marker = m_marker - m_start;
7212  const ssize_t offset_cursor = m_cursor - m_start;
7213 
7214  m_buffer.erase(0, static_cast<size_t>(offset_start));
7215  std::string line;
7216  std::getline(*m_stream, line);
7217  m_buffer += "\n" + line; // add line with newline symbol
7218 
7219  m_content = reinterpret_cast<const lexer_char_t*>(m_buffer.c_str());
7220  m_start = m_content;
7221  m_marker = m_start + offset_marker;
7222  m_cursor = m_start + offset_cursor;
7223  m_limit = m_start + m_buffer.size() - 1;
7224  }
7225 
7227  string_t get_token() const noexcept
7228  {
7229  return string_t(reinterpret_cast<typename string_t::const_pointer>(m_start),
7230  static_cast<size_t>(m_cursor - m_start));
7231  }
7232 
7254  string_t get_string() const
7255  {
7256  string_t result;
7257  result.reserve(static_cast<size_t>(m_cursor - m_start - 2));
7258 
7259  // iterate the result between the quotes
7260  for (const lexer_char_t* i = m_start + 1; i < m_cursor - 1; ++i)
7261  {
7262  // process escaped characters
7263  if (*i == '\\')
7264  {
7265  // read next character
7266  ++i;
7267 
7268  switch (*i)
7269  {
7270  // the default escapes
7271  case 't':
7272  {
7273  result += "\t";
7274  break;
7275  }
7276  case 'b':
7277  {
7278  result += "\b";
7279  break;
7280  }
7281  case 'f':
7282  {
7283  result += "\f";
7284  break;
7285  }
7286  case 'n':
7287  {
7288  result += "\n";
7289  break;
7290  }
7291  case 'r':
7292  {
7293  result += "\r";
7294  break;
7295  }
7296  case '\\':
7297  {
7298  result += "\\";
7299  break;
7300  }
7301  case '/':
7302  {
7303  result += "/";
7304  break;
7305  }
7306  case '"':
7307  {
7308  result += "\"";
7309  break;
7310  }
7311 
7312  // unicode
7313  case 'u':
7314  {
7315  // get code xxxx from uxxxx
7316  auto codepoint = std::strtoul(std::string(reinterpret_cast<typename string_t::const_pointer>(i + 1),
7317  4).c_str(), nullptr, 16);
7318 
7319  // check if codepoint is a high surrogate
7320  if (codepoint >= 0xD800 and codepoint <= 0xDBFF)
7321  {
7322  // make sure there is a subsequent unicode
7323  if ((i + 6 >= m_limit) or * (i + 5) != '\\' or * (i + 6) != 'u')
7324  {
7325  throw std::invalid_argument("missing low surrogate");
7326  }
7327 
7328  // get code yyyy from uxxxx\uyyyy
7329  auto codepoint2 = std::strtoul(std::string(reinterpret_cast<typename string_t::const_pointer>
7330  (i + 7), 4).c_str(), nullptr, 16);
7331  result += to_unicode(codepoint, codepoint2);
7332  // skip the next 10 characters (xxxx\uyyyy)
7333  i += 10;
7334  }
7335  else
7336  {
7337  // add unicode character(s)
7338  result += to_unicode(codepoint);
7339  // skip the next four characters (xxxx)
7340  i += 4;
7341  }
7342  break;
7343  }
7344  }
7345  }
7346  else
7347  {
7348  // all other characters are just copied to the end of the
7349  // string
7350  result.append(1, static_cast<typename string_t::value_type>(*i));
7351  }
7352  }
7353 
7354  return result;
7355  }
7356 
7374  long double get_number() const
7375  {
7376  // conversion
7377  typename string_t::value_type* endptr;
7378  const auto float_val = std::strtold(reinterpret_cast<typename string_t::const_pointer>(m_start),
7379  &endptr);
7380 
7381  // return float_val if the whole number was translated and NAN
7382  // otherwise
7383  return (reinterpret_cast<lexer_char_t*>(endptr) == m_cursor) ? float_val : NAN;
7384  }
7385 
7386  private:
7388  std::istream* m_stream;
7390  string_t m_buffer;
7392  const lexer_char_t* m_content = nullptr;
7394  const lexer_char_t* m_start = nullptr;
7396  const lexer_char_t* m_marker = nullptr;
7398  const lexer_char_t* m_cursor = nullptr;
7400  const lexer_char_t* m_limit = nullptr;
7401  };
7402 
7408  class parser
7409  {
7410  public:
7412  parser(const string_t& s, parser_callback_t cb = nullptr)
7413  : callback(cb), m_lexer(s)
7414  {
7415  // read first token
7416  get_token();
7417  }
7418 
7420  parser(std::istream& _is, parser_callback_t cb = nullptr)
7421  : callback(cb), m_lexer(&_is)
7422  {
7423  // read first token
7424  get_token();
7425  }
7426 
7428  basic_json parse()
7429  {
7430  basic_json result = parse_internal(true);
7431 
7432  expect(lexer::token_type::end_of_input);
7433 
7434  // return parser result and replace it with null in case the
7435  // top-level value was discarded by the callback function
7436  return result.is_discarded() ? basic_json() : result;
7437  }
7438 
7439  private:
7441  basic_json parse_internal(bool keep)
7442  {
7443  auto result = basic_json(value_t::discarded);
7444 
7445  switch (last_token)
7446  {
7447  case lexer::token_type::begin_object:
7448  {
7449  if (keep and (not callback or (keep = callback(depth++, parse_event_t::object_start, result))))
7450  {
7451  // explicitly set result to object to cope with {}
7452  result.m_type = value_t::object;
7453  result.m_value = json_value(value_t::object);
7454  }
7455 
7456  // read next token
7457  get_token();
7458 
7459  // closing } -> we are done
7460  if (last_token == lexer::token_type::end_object)
7461  {
7462  get_token();
7463  if (keep and callback and not callback(--depth, parse_event_t::object_end, result))
7464  {
7465  result = basic_json(value_t::discarded);
7466  }
7467  return result;
7468  }
7469 
7470  // no comma is expected here
7471  unexpect(lexer::token_type::value_separator);
7472 
7473  // otherwise: parse key-value pairs
7474  do
7475  {
7476  // ugly, but could be fixed with loop reorganization
7477  if (last_token == lexer::token_type::value_separator)
7478  {
7479  get_token();
7480  }
7481 
7482  // store key
7483  expect(lexer::token_type::value_string);
7484  const auto key = m_lexer.get_string();
7485 
7486  bool keep_tag = false;
7487  if (keep)
7488  {
7489  if (callback)
7490  {
7491  basic_json k(key);
7492  keep_tag = callback(depth, parse_event_t::key, k);
7493  }
7494  else
7495  {
7496  keep_tag = true;
7497  }
7498  }
7499 
7500  // parse separator (:)
7501  get_token();
7502  expect(lexer::token_type::name_separator);
7503 
7504  // parse and add value
7505  get_token();
7506  auto value = parse_internal(keep);
7507  if (keep and keep_tag and not value.is_discarded())
7508  {
7509  result[key] = std::move(value);
7510  }
7511  }
7512  while (last_token == lexer::token_type::value_separator);
7513 
7514  // closing }
7515  expect(lexer::token_type::end_object);
7516  get_token();
7517  if (keep and callback and not callback(--depth, parse_event_t::object_end, result))
7518  {
7519  result = basic_json(value_t::discarded);
7520  }
7521 
7522  return result;
7523  }
7524 
7525  case lexer::token_type::begin_array:
7526  {
7527  if (keep and (not callback or (keep = callback(depth++, parse_event_t::array_start, result))))
7528  {
7529  // explicitly set result to object to cope with []
7530  result.m_type = value_t::array;
7531  result.m_value = json_value(value_t::array);
7532  }
7533 
7534  // read next token
7535  get_token();
7536 
7537  // closing ] -> we are done
7538  if (last_token == lexer::token_type::end_array)
7539  {
7540  get_token();
7541  if (callback and not callback(--depth, parse_event_t::array_end, result))
7542  {
7543  result = basic_json(value_t::discarded);
7544  }
7545  return result;
7546  }
7547 
7548  // no comma is expected here
7549  unexpect(lexer::token_type::value_separator);
7550 
7551  // otherwise: parse values
7552  do
7553  {
7554  // ugly, but could be fixed with loop reorganization
7555  if (last_token == lexer::token_type::value_separator)
7556  {
7557  get_token();
7558  }
7559 
7560  // parse value
7561  auto value = parse_internal(keep);
7562  if (keep and not value.is_discarded())
7563  {
7564  result.push_back(std::move(value));
7565  }
7566  }
7567  while (last_token == lexer::token_type::value_separator);
7568 
7569  // closing ]
7570  expect(lexer::token_type::end_array);
7571  get_token();
7572  if (keep and callback and not callback(--depth, parse_event_t::array_end, result))
7573  {
7574  result = basic_json(value_t::discarded);
7575  }
7576 
7577  return result;
7578  }
7579 
7580  case lexer::token_type::literal_null:
7581  {
7582  get_token();
7583  result.m_type = value_t::null;
7584  break;
7585  }
7586 
7587  case lexer::token_type::value_string:
7588  {
7589  const auto s = m_lexer.get_string();
7590  get_token();
7591  result = basic_json(s);
7592  break;
7593  }
7594 
7595  case lexer::token_type::literal_true:
7596  {
7597  get_token();
7598  result.m_type = value_t::boolean;
7599  result.m_value = true;
7600  break;
7601  }
7602 
7603  case lexer::token_type::literal_false:
7604  {
7605  get_token();
7606  result.m_type = value_t::boolean;
7607  result.m_value = false;
7608  break;
7609  }
7610 
7611  case lexer::token_type::value_number:
7612  {
7613  auto float_val = m_lexer.get_number();
7614 
7615  // NAN is returned if token could not be translated
7616  // completely
7617  if (std::isnan(float_val))
7618  {
7619  throw std::invalid_argument(std::string("parse error - ") +
7620  m_lexer.get_token() + " is not a number");
7621  }
7622 
7623  get_token();
7624 
7625  // check if conversion loses precision
7626  const auto int_val = static_cast<number_integer_t>(float_val);
7627  if (approx(float_val, static_cast<long double>(int_val)))
7628  {
7629  // we would not lose precision -> return int
7630  result.m_type = value_t::number_integer;
7631  result.m_value = int_val;
7632  }
7633  else
7634  {
7635  // we would lose precision -> return float
7636  result.m_type = value_t::number_float;
7637  result.m_value = static_cast<number_float_t>(float_val);
7638  }
7639  break;
7640  }
7641 
7642  default:
7643  {
7644  // the last token was unexpected
7645  unexpect(last_token);
7646  }
7647  }
7648 
7649  if (keep and callback and not callback(depth, parse_event_t::value, result))
7650  {
7651  result = basic_json(value_t::discarded);
7652  }
7653  return result;
7654  }
7655 
7657  typename lexer::token_type get_token()
7658  {
7659  last_token = m_lexer.scan();
7660  return last_token;
7661  }
7662 
7663  void expect(typename lexer::token_type t) const
7664  {
7665  if (t != last_token)
7666  {
7667  std::string error_msg = "parse error - unexpected \'";
7668  error_msg += m_lexer.get_token();
7669  error_msg += "\' (" + lexer::token_type_name(last_token);
7670  error_msg += "); expected " + lexer::token_type_name(t);
7671  throw std::invalid_argument(error_msg);
7672  }
7673  }
7674 
7675  void unexpect(typename lexer::token_type t) const
7676  {
7677  if (t == last_token)
7678  {
7679  std::string error_msg = "parse error - unexpected \'";
7680  error_msg += m_lexer.get_token();
7681  error_msg += "\' (";
7682  error_msg += lexer::token_type_name(last_token) + ")";
7683  throw std::invalid_argument(error_msg);
7684  }
7685  }
7686 
7687  private:
7689  int depth = 0;
7691  parser_callback_t callback;
7693  typename lexer::token_type last_token = lexer::token_type::uninitialized;
7695  lexer m_lexer;
7696  };
7697 };
7698 
7699 
7701 // presets //
7703 
7713 }
7714 
7715 
7717 // nonmember functions //
7719 
7720 // specialization of std::swap, and std::hash
7721 namespace std
7722 {
7728 template <>
7729 inline void swap(nlohmann::json& j1,
7730  nlohmann::json& j2) noexcept(
7731  is_nothrow_move_constructible<nlohmann::json>::value and
7732  is_nothrow_move_assignable<nlohmann::json>::value
7733  )
7734 {
7735  j1.swap(j2);
7736 }
7737 
7739 template <>
7740 struct hash<nlohmann::json>
7741 {
7747  std::size_t operator()(const nlohmann::json& j) const
7748  {
7749  // a naive hashing via the string representation
7750  const auto& h = hash<nlohmann::json::string_t>();
7751  return h(j.dump());
7752  }
7753 };
7754 }
7755 
7768 inline nlohmann::json operator "" _json(const char* s, std::size_t)
7769 {
7770  return nlohmann::json::parse(reinterpret_cast<nlohmann::json::string_t::value_type*>
7771  (const_cast<char*>(s)));
7772 }
7773 
7774 #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:6203
bool operator!=(const const_iterator &other) const
comparison: not equal
Definition: json.hpp:5696
iterator insert(const_iterator pos, basic_json &&val)
inserts element
Definition: json.hpp:4172
iterator operator++(int)
post-increment (it++)
Definition: json.hpp:5933
friend bool operator<=(const_reference lhs, const_reference rhs) noexcept
comparison: less than or equal
Definition: json.hpp:4721
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:6085
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:2933
typename basic_json::const_pointer pointer
defines a pointer to the type iterated over (value_type)
Definition: json.hpp:5398
const_iterator & operator--()
pre-decrement (–it)
Definition: json.hpp:5641
friend std::istream & operator>>(std::istream &i, basic_json &j)
deserialize from stream
Definition: json.hpp:4934
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:5463
typename basic_json::value_type value_type
the type of the values when the iterator is dereferenced
Definition: json.hpp:5394
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:4247
iterator insert(const_iterator pos, size_type cnt, const basic_json &val)
inserts elements
Definition: json.hpp:4199
json_reverse_iterator operator--(int)
post-decrement (it–)
Definition: json.hpp:6057
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:4097
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:5941
friend bool operator!=(const_reference lhs, const_reference rhs) noexcept
comparison: not equal
Definition: json.hpp:4599
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:5606
difference_type operator-(const json_reverse_iterator &other) const
return difference
Definition: json.hpp:6093
basic_json<> json
default JSON class
Definition: json.hpp:7712
reference front()
access the first element
Definition: json.hpp:3097
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:3463
std::reverse_iterator< Base > base_iterator
shortcut to the reverse iterator adaptor
Definition: json.hpp:6032
json_reverse_iterator(const typename base_iterator::iterator_type &it)
create reverse iterator from iterator
Definition: json.hpp:6037
a class to store JSON values
Definition: json.hpp:187
json_reverse_iterator & operator--()
pre-decrement (–it)
Definition: json.hpp:6063
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:4578
void push_back(basic_json &&val)
add an object to an array
Definition: json.hpp:4013
const_iterator cbegin() const
returns a const iterator to the first element
Definition: json.hpp:3561
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:5963
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:5892
reference operator+=(basic_json &&val)
add an object to an array
Definition: json.hpp:4038
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:5889
iterator & operator-=(difference_type i)
subtract from iterator
Definition: json.hpp:5970
static basic_json parse(std::istream &&i, parser_callback_t cb=nullptr)
deserialize from stream
Definition: json.hpp:4896
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:5992
reference value() const
return the value of an iterator
Definition: json.hpp:5865
const_iterator end() const
returns a const iterator to one past the last element
Definition: json.hpp:3596
const_iterator(const const_iterator &other) noexcept
copy constructor
Definition: json.hpp:5458
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:5852
iterator end()
returns an iterator to one past the last element
Definition: json.hpp:3586
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:5921
reverse_iterator rend()
returns an iterator to the reverse-end
Definition: json.hpp:3675
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:5788
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:5400
const_reverse_iterator rend() const
returns a const reverse iterator to one before the first
Definition: json.hpp:3683
size_type erase(const typename object_t::key_type &key)
remove element from a JSON object given a key
Definition: json.hpp:3377
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:3527
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:4071
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:5977
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:3447
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:4765
iterator & operator--()
pre-decrement (–it)
Definition: json.hpp:5956
friend bool operator<(const_reference lhs, const_reference rhs) noexcept
comparison: less than
Definition: json.hpp:4660
pointer operator->() const
dereference the iterator
Definition: json.hpp:5569
discarded by the the parser callback function
const_reference operator[](const typename object_t::key_type &key) const
read-only access specified object element
Definition: json.hpp:2891
const_iterator cend() const
returns a const iterator to one past the last element
Definition: json.hpp:3620
typename Base::reference reference
the reference type for the pointed-to element
Definition: json.hpp:6034
size_type size() const noexcept
returns the number of elements
Definition: json.hpp:3830
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:6041
iterator_wrapper_internal end()
return iterator end (needed for range-based for)
Definition: json.hpp:6214
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:4820
ValueType value(const typename object_t::key_type &key, ValueType default_value) const
access specified object element with default value
Definition: json.hpp:3046
object_t::key_type key() const
return the key of an object iterator
Definition: json.hpp:6105
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:5396
void swap(array_t &other)
exchanges the values
Definition: json.hpp:4368
reverse_iterator rbegin()
returns an iterator to the reverse-beginning
Definition: json.hpp:3644
reference operator+=(const typename object_t::value_type &val)
add an object to an object
Definition: json.hpp:4120
iterator_wrapper_internal begin()
return iterator begin (needed for range-based for)
Definition: json.hpp:6208
reference operator[](difference_type n) const
access to successor
Definition: json.hpp:5998
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:3652
~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:5780
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:4432
reference value() const
return the value of an iterator
Definition: json.hpp:6004
const_iterator operator--(int)
post-decrement (it–)
Definition: json.hpp:5633
void erase(const size_type idx)
remove element from a JSON array given an index
Definition: json.hpp:3412
void clear() noexcept
clears the contents
Definition: json.hpp:3947
pointer operator->()
dereference the iterator
Definition: json.hpp:5927
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:3105
bool operator>=(const const_iterator &other) const
comparison: greater than or equal
Definition: json.hpp:5742
iterator insert(const_iterator pos, std::initializer_list< basic_json > ilist)
inserts elements
Definition: json.hpp:4301
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:5748
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:5796
friend bool operator==(const_reference lhs, const_reference rhs) noexcept
comparison: equal
Definition: json.hpp:4511
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:3729
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:3773
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:3072
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:4338
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:3706
reference value() const
return the value of an iterator
Definition: json.hpp:6112
const_iterator(pointer object)
constructor for a given JSON instance
Definition: json.hpp:5408
friend bool operator<(const value_t lhs, const value_t rhs)
comparison operator for JSON types
Definition: json.hpp:4465
iterator(pointer object) noexcept
constructor for a given JSON instance
Definition: json.hpp:5900
bool operator<(const const_iterator &other) const
comparison: smaller
Definition: json.hpp:5702
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:4622
const_iterator & operator-=(difference_type i)
subtract from iterator
Definition: json.hpp:5774
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:4859
InteratorType erase(InteratorType first, InteratorType last)
remove elements given an iterator range
Definition: json.hpp:3297
json_reverse_iterator operator++(int)
post-increment (it++)
Definition: json.hpp:6044
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:5433
friend bool operator!=(std::nullptr_t, const_reference v) noexcept
comparison: not equal
Definition: json.hpp:4631
InteratorType erase(InteratorType pos)
remove element given an iterator
Definition: json.hpp:3196
bool operator<=(const const_iterator &other) const
comparison: less than or equal
Definition: json.hpp:5730
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:3131
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:5598
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:5904
const_reference back() const
access the last element
Definition: json.hpp:3141
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:4888
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:3493
size_type max_size() const noexcept
returns the maximum possible number of elements
Definition: json.hpp:3890
void push_back(const basic_json &val)
add an object to an array
Definition: json.hpp:4048
bool operator==(const const_iterator &other) const
comparison: equal
Definition: json.hpp:5668
json_reverse_iterator & operator++()
pre-increment (++it)
Definition: json.hpp:6050
bool operator>(const const_iterator &other) const
comparison: greater than
Definition: json.hpp:5736
friend bool operator>(const_reference lhs, const_reference rhs) noexcept
comparison: greater than
Definition: json.hpp:4743
basic_json(basic_json &&other) noexcept
move constructor
Definition: json.hpp:1738
const_reference operator[](const T(&key)[n]) const
read-only access specified object element
Definition: json.hpp:2982
const_iterator begin() const
returns a const iterator to the first element
Definition: json.hpp:3537
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:6070
a const random access iterator for the basic_json class
Definition: json.hpp:5387
a template for a reverse iterator class
Definition: json.hpp:232
void swap(object_t &other)
exchanges the values
Definition: json.hpp:4400
std::bidirectional_iterator_tag iterator_category
the category of the iterator
Definition: json.hpp:5402
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:4146
friend bool operator==(const_reference v, std::nullptr_t) noexcept
comparison: equal
Definition: json.hpp:4569
reference operator[](difference_type n) const
access to successor
Definition: json.hpp:6099
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:5818
reference operator*() const
return a reference to the value pointed to by the iterator
Definition: json.hpp:5535
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:4924
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:7747
friend std::ostream & operator<<(std::ostream &o, const basic_json &j)
serialize to stream
Definition: json.hpp:4802
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:5909
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:5948
json_reverse_iterator operator+(difference_type i) const
add to iterator
Definition: json.hpp:6077
parse_event_t
JSON callback events.
Definition: json.hpp:754
iterator operator-(difference_type i)
subtract from iterator
Definition: json.hpp:5985
wrapper to access iterator member functions in range-based for
Definition: json.hpp:6126