JSON for Modern C++  1.1.0
json.hpp
1 
38 #ifndef NLOHMANN_JSON_HPP
39 #define NLOHMANN_JSON_HPP
40 
41 #include <algorithm>
42 #include <array>
43 #include <cassert>
44 #include <ciso646>
45 #include <cmath>
46 #include <cstddef>
47 #include <cstdio>
48 #include <cstdlib>
49 #include <functional>
50 #include <initializer_list>
51 #include <iomanip>
52 #include <iostream>
53 #include <iterator>
54 #include <limits>
55 #include <map>
56 #include <memory>
57 #include <sstream>
58 #include <stdexcept>
59 #include <string>
60 #include <type_traits>
61 #include <utility>
62 #include <vector>
63 
64 // enable ssize_t on MinGW
65 #ifdef __GNUC__
66  #ifdef __MINGW32__
67  #include <sys/types.h>
68  #endif
69 #endif
70 
71 // disable float-equal warnings on GCC/clang
72 #if defined(__clang__) || defined(__GNUC__) || defined(__GNUG__)
73  #pragma GCC diagnostic push
74  #pragma GCC diagnostic ignored "-Wfloat-equal"
75 #endif
76 
77 // enable ssize_t for MSVC
78 #ifdef _MSC_VER
79  #include <basetsd.h>
80  using ssize_t = SSIZE_T;
81 #endif
82 
88 namespace nlohmann
89 {
90 
91 
96 namespace
97 {
102 template<typename T>
103 struct has_mapped_type
104 {
105  private:
106  template<typename C> static char test(typename C::mapped_type*);
107  template<typename C> static char (&test(...))[2];
108  public:
109  static constexpr bool value = sizeof(test<T>(0)) == 1;
110 };
111 
112 }
113 
182 template <
183  template<typename U, typename V, typename... Args> class ObjectType = std::map,
184  template<typename U, typename... Args> class ArrayType = std::vector,
185  class StringType = std::string,
186  class BooleanType = bool,
187  class NumberIntegerType = int64_t,
188  class NumberFloatType = double,
189  template<typename U> class AllocatorType = std::allocator
190  >
192 {
193  private:
195  using basic_json_t = basic_json<ObjectType,
196  ArrayType,
197  StringType,
198  BooleanType,
199  NumberIntegerType,
200  NumberFloatType,
201  AllocatorType>;
202 
203  public:
204 
206  // container types //
208 
211 
214 
218  using const_reference = const value_type&;
219 
221  using difference_type = std::ptrdiff_t;
223  using size_type = std::size_t;
224 
226  using allocator_type = AllocatorType<basic_json>;
227 
229  using pointer = typename std::allocator_traits<allocator_type>::pointer;
231  using const_pointer = typename std::allocator_traits<allocator_type>::const_pointer;
232 
233  // forward declaration
234  template<typename Base> class json_reverse_iterator;
235 
237  class iterator;
239  class const_iterator;
244 
246 
247 
252  {
253  return allocator_type();
254  }
255 
256 
258  // JSON value data types //
260 
263 
346  using object_t = ObjectType<StringType,
347  basic_json,
348  std::less<StringType>,
349  AllocatorType<std::pair<const StringType,
350  basic_json>>>;
351 
396  using array_t = ArrayType<basic_json, AllocatorType<basic_json>>;
397 
443  using string_t = StringType;
444 
469  using boolean_t = BooleanType;
470 
537  using number_integer_t = NumberIntegerType;
538 
602  using number_float_t = NumberFloatType;
603 
605 
606 
608  // JSON type enumeration //
610 
621  enum class value_t : uint8_t
622  {
623  null,
624  object,
625  array,
626  string,
627  boolean,
628  number_integer,
629  number_float,
630  discarded
631  };
632 
633 
634  private:
636  template<typename T, typename... Args>
637  static T* create(Args&& ... args)
638  {
639  AllocatorType<T> alloc;
640  auto deleter = [&](T * object)
641  {
642  alloc.deallocate(object, 1);
643  };
644  std::unique_ptr<T, decltype(deleter)> object(alloc.allocate(1), deleter);
645  alloc.construct(object.get(), std::forward<Args>(args)...);
646  return object.release();
647  }
648 
650  // JSON value storage //
652 
660  union json_value
661  {
663  object_t* object;
665  array_t* array;
667  string_t* string;
669  boolean_t boolean;
671  number_integer_t number_integer;
673  number_float_t number_float;
674 
676  json_value() noexcept = default;
678  json_value(boolean_t v) noexcept : boolean(v) {}
680  json_value(number_integer_t v) noexcept : number_integer(v) {}
682  json_value(number_float_t v) noexcept : number_float(v) {}
684  json_value(value_t t)
685  {
686  switch (t)
687  {
688  case value_t::object:
689  {
690  object = create<object_t>();
691  break;
692  }
693 
694  case value_t::array:
695  {
696  array = create<array_t>();
697  break;
698  }
699 
700  case value_t::string:
701  {
702  string = create<string_t>("");
703  break;
704  }
705 
706  case value_t::boolean:
707  {
708  boolean = boolean_t(false);
709  break;
710  }
711 
712  case value_t::number_integer:
713  {
714  number_integer = number_integer_t(0);
715  break;
716  }
717 
718  case value_t::number_float:
719  {
720  number_float = number_float_t(0.0);
721  break;
722  }
723 
724  default:
725  {
726  break;
727  }
728  }
729  }
730 
732  json_value(const string_t& value)
733  {
734  string = create<string_t>(value);
735  }
736 
738  json_value(const object_t& value)
739  {
740  object = create<object_t>(value);
741  }
742 
744  json_value(const array_t& value)
745  {
746  array = create<array_t>(value);
747  }
748  };
749 
750 
751  public:
753  // JSON parser callback //
755 
764  enum class parse_event_t : uint8_t
765  {
767  object_start,
769  object_end,
771  array_start,
773  array_end,
775  key,
777  value
778  };
779 
829  using parser_callback_t = std::function<bool(int depth, parse_event_t event, basic_json& parsed)>;
830 
831 
833  // constructors //
835 
838 
877  : m_type(value_type), m_value(value_type)
878  {}
879 
899  basic_json() noexcept = default;
900 
920  basic_json(std::nullptr_t) noexcept
921  : basic_json(value_t::null)
922  {}
923 
943  basic_json(const object_t& val)
944  : m_type(value_t::object), m_value(val)
945  {}
946 
970  template <class CompatibleObjectType, typename
971  std::enable_if<
972  std::is_constructible<typename object_t::key_type, typename CompatibleObjectType::key_type>::value and
973  std::is_constructible<basic_json, typename CompatibleObjectType::mapped_type>::value, int>::type
974  = 0>
975  basic_json(const CompatibleObjectType& val)
976  : m_type(value_t::object)
977  {
978  using std::begin;
979  using std::end;
980  m_value.object = create<object_t>(begin(val), end(val));
981  }
982 
1002  basic_json(const array_t& val)
1003  : m_type(value_t::array), m_value(val)
1004  {}
1005 
1029  template <class CompatibleArrayType, typename
1030  std::enable_if<
1031  not std::is_same<CompatibleArrayType, typename basic_json_t::iterator>::value and
1032  not std::is_same<CompatibleArrayType, typename basic_json_t::const_iterator>::value and
1033  not std::is_same<CompatibleArrayType, typename basic_json_t::reverse_iterator>::value and
1034  not std::is_same<CompatibleArrayType, typename basic_json_t::const_reverse_iterator>::value and
1035  not std::is_same<CompatibleArrayType, typename array_t::iterator>::value and
1036  not std::is_same<CompatibleArrayType, typename array_t::const_iterator>::value and
1037  std::is_constructible<basic_json, typename CompatibleArrayType::value_type>::value, int>::type
1038  = 0>
1039  basic_json(const CompatibleArrayType& val)
1040  : m_type(value_t::array)
1041  {
1042  using std::begin;
1043  using std::end;
1044  m_value.array = create<array_t>(begin(val), end(val));
1045  }
1046 
1068  basic_json(const string_t& val)
1069  : m_type(value_t::string), m_value(val)
1070  {}
1071 
1092  basic_json(const typename string_t::value_type* val)
1093  : basic_json(string_t(val))
1094  {}
1095 
1119  template <class CompatibleStringType, typename
1120  std::enable_if<
1121  std::is_constructible<string_t, CompatibleStringType>::value, int>::type
1122  = 0>
1123  basic_json(const CompatibleStringType& val)
1124  : basic_json(string_t(val))
1125  {}
1126 
1142  : m_type(value_t::boolean), m_value(val)
1143  {}
1144 
1170  template<typename T,
1171  typename std::enable_if<
1172  not (std::is_same<T, int>::value)
1173  and std::is_same<T, number_integer_t>::value
1174  , int>::type = 0>
1176  : m_type(value_t::number_integer), m_value(val)
1177  {}
1178 
1204  basic_json(const int val)
1205  : m_type(value_t::number_integer),
1206  m_value(static_cast<number_integer_t>(val))
1207  {}
1208 
1234  template<typename CompatibleNumberIntegerType, typename
1235  std::enable_if<
1236  std::is_constructible<number_integer_t, CompatibleNumberIntegerType>::value and
1237  std::numeric_limits<CompatibleNumberIntegerType>::is_integer, CompatibleNumberIntegerType>::type
1238  = 0>
1239  basic_json(const CompatibleNumberIntegerType val) noexcept
1240  : m_type(value_t::number_integer),
1241  m_value(static_cast<number_integer_t>(val))
1242  {}
1243 
1269  : m_type(value_t::number_float), m_value(val)
1270  {
1271  // replace infinity and NAN by null
1272  if (not std::isfinite(val))
1273  {
1274  m_type = value_t::null;
1275  m_value = json_value();
1276  }
1277  }
1278 
1309  template<typename CompatibleNumberFloatType, typename = typename
1310  std::enable_if<
1311  std::is_constructible<number_float_t, CompatibleNumberFloatType>::value and
1312  std::is_floating_point<CompatibleNumberFloatType>::value>::type
1313  >
1314  basic_json(const CompatibleNumberFloatType val) noexcept
1315  : basic_json(number_float_t(val))
1316  {}
1317 
1387  basic_json(std::initializer_list<basic_json> init,
1388  bool type_deduction = true,
1389  value_t manual_type = value_t::array)
1390  {
1391  // the initializer list could describe an object
1392  bool is_an_object = true;
1393 
1394  // check if each element is an array with two elements whose first
1395  // element is a string
1396  for (const auto& element : init)
1397  {
1398  if (not element.is_array() or element.size() != 2
1399  or not element[0].is_string())
1400  {
1401  // we found an element that makes it impossible to use the
1402  // initializer list as object
1403  is_an_object = false;
1404  break;
1405  }
1406  }
1407 
1408  // adjust type if type deduction is not wanted
1409  if (not type_deduction)
1410  {
1411  // if array is wanted, do not create an object though possible
1412  if (manual_type == value_t::array)
1413  {
1414  is_an_object = false;
1415  }
1416 
1417  // if object is wanted but impossible, throw an exception
1418  if (manual_type == value_t::object and not is_an_object)
1419  {
1420  throw std::domain_error("cannot create object from initializer list");
1421  }
1422  }
1423 
1424  if (is_an_object)
1425  {
1426  // the initializer list is a list of pairs -> create object
1427  m_type = value_t::object;
1428  m_value = value_t::object;
1429 
1430  assert(m_value.object != nullptr);
1431 
1432  for (auto& element : init)
1433  {
1434  m_value.object->emplace(std::move(*(element[0].m_value.string)), std::move(element[1]));
1435  }
1436  }
1437  else
1438  {
1439  // the initializer list describes an array -> create array
1440  m_type = value_t::array;
1441  m_value.array = create<array_t>(std::move(init));
1442  }
1443  }
1444 
1479  static basic_json array(std::initializer_list<basic_json> init =
1480  std::initializer_list<basic_json>())
1481  {
1482  return basic_json(init, false, value_t::array);
1483  }
1484 
1519  static basic_json object(std::initializer_list<basic_json> init =
1520  std::initializer_list<basic_json>())
1521  {
1522  return basic_json(init, false, value_t::object);
1523  }
1524 
1543  basic_json(size_type cnt, const basic_json& val)
1544  : m_type(value_t::array)
1545  {
1546  m_value.array = create<array_t>(cnt, val);
1547  }
1548 
1583  template <class InputIT, typename
1584  std::enable_if<
1585  std::is_same<InputIT, typename basic_json_t::iterator>::value or
1586  std::is_same<InputIT, typename basic_json_t::const_iterator>::value
1587  , int>::type
1588  = 0>
1589  basic_json(InputIT first, InputIT last) : m_type(first.m_object->m_type)
1590  {
1591  // make sure iterator fits the current value
1592  if (first.m_object != last.m_object)
1593  {
1594  throw std::domain_error("iterators are not compatible");
1595  }
1596 
1597  // check if iterator range is complete for primitive values
1598  switch (m_type)
1599  {
1600  case value_t::boolean:
1601  case value_t::number_float:
1602  case value_t::number_integer:
1603  case value_t::string:
1604  {
1605  if (not first.m_it.primitive_iterator.is_begin() or not last.m_it.primitive_iterator.is_end())
1606  {
1607  throw std::out_of_range("iterators out of range");
1608  }
1609  break;
1610  }
1611 
1612  default:
1613  {
1614  break;
1615  }
1616  }
1617 
1618  switch (m_type)
1619  {
1620  case value_t::number_integer:
1621  {
1622  assert(first.m_object != nullptr);
1623  m_value.number_integer = first.m_object->m_value.number_integer;
1624  break;
1625  }
1626 
1627  case value_t::number_float:
1628  {
1629  assert(first.m_object != nullptr);
1630  m_value.number_float = first.m_object->m_value.number_float;
1631  break;
1632  }
1633 
1634  case value_t::boolean:
1635  {
1636  assert(first.m_object != nullptr);
1637  m_value.boolean = first.m_object->m_value.boolean;
1638  break;
1639  }
1640 
1641  case value_t::string:
1642  {
1643  assert(first.m_object != nullptr);
1644  m_value = *first.m_object->m_value.string;
1645  break;
1646  }
1647 
1648  case value_t::object:
1649  {
1650  m_value.object = create<object_t>(first.m_it.object_iterator, last.m_it.object_iterator);
1651  break;
1652  }
1653 
1654  case value_t::array:
1655  {
1656  m_value.array = create<array_t>(first.m_it.array_iterator, last.m_it.array_iterator);
1657  break;
1658  }
1659 
1660  default:
1661  {
1662  assert(first.m_object != nullptr);
1663  throw std::domain_error("cannot use construct with iterators from " + first.m_object->type_name());
1664  }
1665  }
1666  }
1667 
1669  // other constructors and destructor //
1671 
1692  basic_json(const basic_json& other)
1693  : m_type(other.m_type)
1694  {
1695  switch (m_type)
1696  {
1697  case value_t::object:
1698  {
1699  assert(other.m_value.object != nullptr);
1700  m_value = *other.m_value.object;
1701  break;
1702  }
1703 
1704  case value_t::array:
1705  {
1706  assert(other.m_value.array != nullptr);
1707  m_value = *other.m_value.array;
1708  break;
1709  }
1710 
1711  case value_t::string:
1712  {
1713  assert(other.m_value.string != nullptr);
1714  m_value = *other.m_value.string;
1715  break;
1716  }
1717 
1718  case value_t::boolean:
1719  {
1720  m_value = other.m_value.boolean;
1721  break;
1722  }
1723 
1724  case value_t::number_integer:
1725  {
1726  m_value = other.m_value.number_integer;
1727  break;
1728  }
1729 
1730  case value_t::number_float:
1731  {
1732  m_value = other.m_value.number_float;
1733  break;
1734  }
1735 
1736  default:
1737  {
1738  break;
1739  }
1740  }
1741  }
1742 
1761  basic_json(basic_json&& other) noexcept
1762  : m_type(std::move(other.m_type)),
1763  m_value(std::move(other.m_value))
1764  {
1765  // invalidate payload
1766  other.m_type = value_t::null;
1767  other.m_value = {};
1768  }
1769 
1791  reference& operator=(basic_json other) noexcept (
1792  std::is_nothrow_move_constructible<value_t>::value and
1793  std::is_nothrow_move_assignable<value_t>::value and
1794  std::is_nothrow_move_constructible<json_value>::value and
1795  std::is_nothrow_move_assignable<json_value>::value
1796  )
1797  {
1798  using std::swap;
1799  swap(m_type, other.m_type);
1800  swap(m_value, other.m_value);
1801  return *this;
1802  }
1803 
1818  {
1819  switch (m_type)
1820  {
1821  case value_t::object:
1822  {
1823  AllocatorType<object_t> alloc;
1824  alloc.destroy(m_value.object);
1825  alloc.deallocate(m_value.object, 1);
1826  break;
1827  }
1828 
1829  case value_t::array:
1830  {
1831  AllocatorType<array_t> alloc;
1832  alloc.destroy(m_value.array);
1833  alloc.deallocate(m_value.array, 1);
1834  break;
1835  }
1836 
1837  case value_t::string:
1838  {
1839  AllocatorType<string_t> alloc;
1840  alloc.destroy(m_value.string);
1841  alloc.deallocate(m_value.string, 1);
1842  break;
1843  }
1844 
1845  default:
1846  {
1847  // all other types need no specific destructor
1848  break;
1849  }
1850  }
1851  }
1852 
1854 
1855  public:
1857  // object inspection //
1859 
1862 
1886  string_t dump(const int indent = -1) const
1887  {
1888  std::stringstream ss;
1889 
1890  if (indent >= 0)
1891  {
1892  dump(ss, true, static_cast<unsigned int>(indent));
1893  }
1894  else
1895  {
1896  dump(ss, false, 0);
1897  }
1898 
1899  return ss.str();
1900  }
1901 
1917  value_t type() const noexcept
1918  {
1919  return m_type;
1920  }
1921 
1938  bool is_primitive() const noexcept
1939  {
1940  return is_null() or is_string() or is_boolean() or is_number();
1941  }
1942 
1958  bool is_structured() const noexcept
1959  {
1960  return is_array() or is_object();
1961  }
1962 
1977  bool is_null() const noexcept
1978  {
1979  return m_type == value_t::null;
1980  }
1981 
1996  bool is_boolean() const noexcept
1997  {
1998  return m_type == value_t::boolean;
1999  }
2000 
2020  bool is_number() const noexcept
2021  {
2022  return is_number_integer() or is_number_float();
2023  }
2024 
2043  bool is_number_integer() const noexcept
2044  {
2045  return m_type == value_t::number_integer;
2046  }
2047 
2066  bool is_number_float() const noexcept
2067  {
2068  return m_type == value_t::number_float;
2069  }
2070 
2085  bool is_object() const noexcept
2086  {
2087  return m_type == value_t::object;
2088  }
2089 
2104  bool is_array() const noexcept
2105  {
2106  return m_type == value_t::array;
2107  }
2108 
2123  bool is_string() const noexcept
2124  {
2125  return m_type == value_t::string;
2126  }
2127 
2147  bool is_discarded() const noexcept
2148  {
2149  return m_type == value_t::discarded;
2150  }
2151 
2167  operator value_t() const noexcept
2168  {
2169  return m_type;
2170  }
2171 
2173 
2174  private:
2176  // value access //
2178 
2180  template <class T, typename
2181  std::enable_if<
2182  std::is_convertible<typename object_t::key_type, typename T::key_type>::value and
2183  std::is_convertible<basic_json_t, typename T::mapped_type>::value
2184  , int>::type = 0>
2185  T get_impl(T*) const
2186  {
2187  if (is_object())
2188  {
2189  assert(m_value.object != nullptr);
2190  return T(m_value.object->begin(), m_value.object->end());
2191  }
2192  else
2193  {
2194  throw std::domain_error("type must be object, but is " + type_name());
2195  }
2196  }
2197 
2199  object_t get_impl(object_t*) const
2200  {
2201  if (is_object())
2202  {
2203  assert(m_value.object != nullptr);
2204  return *(m_value.object);
2205  }
2206  else
2207  {
2208  throw std::domain_error("type must be object, but is " + type_name());
2209  }
2210  }
2211 
2213  template <class T, typename
2214  std::enable_if<
2215  std::is_convertible<basic_json_t, typename T::value_type>::value and
2216  not std::is_same<basic_json_t, typename T::value_type>::value and
2217  not std::is_arithmetic<T>::value and
2218  not std::is_convertible<std::string, T>::value and
2219  not has_mapped_type<T>::value
2220  , int>::type = 0>
2221  T get_impl(T*) const
2222  {
2223  if (is_array())
2224  {
2225  T to_vector;
2226  assert(m_value.array != nullptr);
2227  std::transform(m_value.array->begin(), m_value.array->end(),
2228  std::inserter(to_vector, to_vector.end()), [](basic_json i)
2229  {
2230  return i.get<typename T::value_type>();
2231  });
2232  return to_vector;
2233  }
2234  else
2235  {
2236  throw std::domain_error("type must be array, but is " + type_name());
2237  }
2238  }
2239 
2241  template <class T, typename
2242  std::enable_if<
2243  std::is_convertible<basic_json_t, T>::value and
2244  not std::is_same<basic_json_t, T>::value
2245  , int>::type = 0>
2246  std::vector<T> get_impl(std::vector<T>*) const
2247  {
2248  if (is_array())
2249  {
2250  std::vector<T> to_vector;
2251  assert(m_value.array != nullptr);
2252  to_vector.reserve(m_value.array->size());
2253  std::transform(m_value.array->begin(), m_value.array->end(),
2254  std::inserter(to_vector, to_vector.end()), [](basic_json i)
2255  {
2256  return i.get<T>();
2257  });
2258  return to_vector;
2259  }
2260  else
2261  {
2262  throw std::domain_error("type must be array, but is " + type_name());
2263  }
2264  }
2265 
2267  template <class T, typename
2268  std::enable_if<
2269  std::is_same<basic_json, typename T::value_type>::value and
2270  not has_mapped_type<T>::value
2271  , int>::type = 0>
2272  T get_impl(T*) const
2273  {
2274  if (is_array())
2275  {
2276  assert(m_value.array != nullptr);
2277  return T(m_value.array->begin(), m_value.array->end());
2278  }
2279  else
2280  {
2281  throw std::domain_error("type must be array, but is " + type_name());
2282  }
2283  }
2284 
2286  array_t get_impl(array_t*) const
2287  {
2288  if (is_array())
2289  {
2290  assert(m_value.array != nullptr);
2291  return *(m_value.array);
2292  }
2293  else
2294  {
2295  throw std::domain_error("type must be array, but is " + type_name());
2296  }
2297  }
2298 
2300  template <typename T, typename
2301  std::enable_if<
2302  std::is_convertible<string_t, T>::value
2303  , int>::type = 0>
2304  T get_impl(T*) const
2305  {
2306  if (is_string())
2307  {
2308  assert(m_value.string != nullptr);
2309  return *m_value.string;
2310  }
2311  else
2312  {
2313  throw std::domain_error("type must be string, but is " + type_name());
2314  }
2315  }
2316 
2318  template<typename T, typename
2319  std::enable_if<
2320  std::is_arithmetic<T>::value
2321  , int>::type = 0>
2322  T get_impl(T*) const
2323  {
2324  switch (m_type)
2325  {
2326  case value_t::number_integer:
2327  {
2328  return static_cast<T>(m_value.number_integer);
2329  }
2330 
2331  case value_t::number_float:
2332  {
2333  return static_cast<T>(m_value.number_float);
2334  }
2335 
2336  default:
2337  {
2338  throw std::domain_error("type must be number, but is " + type_name());
2339  }
2340  }
2341  }
2342 
2344  boolean_t get_impl(boolean_t*) const
2345  {
2346  if (is_boolean())
2347  {
2348  return m_value.boolean;
2349  }
2350  else
2351  {
2352  throw std::domain_error("type must be boolean, but is " + type_name());
2353  }
2354  }
2355 
2357  object_t* get_impl_ptr(object_t*) noexcept
2358  {
2359  return is_object() ? m_value.object : nullptr;
2360  }
2361 
2363  const object_t* get_impl_ptr(const object_t*) const noexcept
2364  {
2365  return is_object() ? m_value.object : nullptr;
2366  }
2367 
2369  array_t* get_impl_ptr(array_t*) noexcept
2370  {
2371  return is_array() ? m_value.array : nullptr;
2372  }
2373 
2375  const array_t* get_impl_ptr(const array_t*) const noexcept
2376  {
2377  return is_array() ? m_value.array : nullptr;
2378  }
2379 
2381  string_t* get_impl_ptr(string_t*) noexcept
2382  {
2383  return is_string() ? m_value.string : nullptr;
2384  }
2385 
2387  const string_t* get_impl_ptr(const string_t*) const noexcept
2388  {
2389  return is_string() ? m_value.string : nullptr;
2390  }
2391 
2393  boolean_t* get_impl_ptr(boolean_t*) noexcept
2394  {
2395  return is_boolean() ? &m_value.boolean : nullptr;
2396  }
2397 
2399  const boolean_t* get_impl_ptr(const boolean_t*) const noexcept
2400  {
2401  return is_boolean() ? &m_value.boolean : nullptr;
2402  }
2403 
2405  number_integer_t* get_impl_ptr(number_integer_t*) noexcept
2406  {
2407  return is_number_integer() ? &m_value.number_integer : nullptr;
2408  }
2409 
2411  const number_integer_t* get_impl_ptr(const number_integer_t*) const noexcept
2412  {
2413  return is_number_integer() ? &m_value.number_integer : nullptr;
2414  }
2415 
2417  number_float_t* get_impl_ptr(number_float_t*) noexcept
2418  {
2419  return is_number_float() ? &m_value.number_float : nullptr;
2420  }
2421 
2423  const number_float_t* get_impl_ptr(const number_float_t*) const noexcept
2424  {
2425  return is_number_float() ? &m_value.number_float : nullptr;
2426  }
2427 
2439  template<typename ReferenceType, typename ThisType>
2440  static ReferenceType get_ref_impl(ThisType& obj)
2441  {
2442  // delegate the call to get_ptr<>()
2443  using PointerType = typename std::add_pointer<ReferenceType>::type;
2444  auto ptr = obj.template get_ptr<PointerType>();
2445 
2446  if (ptr != nullptr)
2447  {
2448  return *ptr;
2449  }
2450  else
2451  {
2452  throw std::domain_error("incompatible ReferenceType for get_ref, actual type is " +
2453  obj.type_name());
2454  }
2455  }
2456 
2457  public:
2458 
2461 
2495  template<typename ValueType, typename
2496  std::enable_if<
2497  not std::is_pointer<ValueType>::value
2498  , int>::type = 0>
2499  ValueType get() const
2500  {
2501  return get_impl(static_cast<ValueType*>(nullptr));
2502  }
2503 
2530  template<typename PointerType, typename
2531  std::enable_if<
2532  std::is_pointer<PointerType>::value
2533  , int>::type = 0>
2534  PointerType get() noexcept
2535  {
2536  // delegate the call to get_ptr
2537  return get_ptr<PointerType>();
2538  }
2539 
2544  template<typename PointerType, typename
2545  std::enable_if<
2546  std::is_pointer<PointerType>::value
2547  , int>::type = 0>
2548  const PointerType get() const noexcept
2549  {
2550  // delegate the call to get_ptr
2551  return get_ptr<PointerType>();
2552  }
2553 
2579  template<typename PointerType, typename
2580  std::enable_if<
2581  std::is_pointer<PointerType>::value
2582  , int>::type = 0>
2583  PointerType get_ptr() noexcept
2584  {
2585  // delegate the call to get_impl_ptr<>()
2586  return get_impl_ptr(static_cast<PointerType>(nullptr));
2587  }
2588 
2593  template<typename PointerType, typename
2594  std::enable_if<
2595  std::is_pointer<PointerType>::value
2596  and std::is_const<typename std::remove_pointer<PointerType>::type>::value
2597  , int>::type = 0>
2598  const PointerType get_ptr() const noexcept
2599  {
2600  // delegate the call to get_impl_ptr<>() const
2601  return get_impl_ptr(static_cast<const PointerType>(nullptr));
2602  }
2603 
2630  template<typename ReferenceType, typename
2631  std::enable_if<
2632  std::is_reference<ReferenceType>::value
2633  , int>::type = 0>
2634  ReferenceType get_ref()
2635  {
2636  // delegate call to get_ref_impl
2637  return get_ref_impl<ReferenceType>(*this);
2638  }
2639 
2644  template<typename ReferenceType, typename
2645  std::enable_if<
2646  std::is_reference<ReferenceType>::value
2647  and std::is_const<typename std::remove_reference<ReferenceType>::type>::value
2648  , int>::type = 0>
2649  ReferenceType get_ref() const
2650  {
2651  // delegate call to get_ref_impl
2652  return get_ref_impl<ReferenceType>(*this);
2653  }
2654 
2683  template < typename ValueType, typename
2684  std::enable_if <
2685  not std::is_pointer<ValueType>::value
2686  and not std::is_same<ValueType, typename string_t::value_type>::value
2687 #ifndef _MSC_VER // Fix for issue #167 operator<< abiguity under VS2015
2688  and not std::is_same<ValueType, std::initializer_list<typename string_t::value_type>>::value
2689 #endif
2690  , int >::type = 0 >
2691  operator ValueType() const
2692  {
2693  // delegate the call to get<>() const
2694  return get<ValueType>();
2695  }
2696 
2698 
2699 
2701  // element access //
2703 
2706 
2730  {
2731  // at only works for arrays
2732  if (is_array())
2733  {
2734  try
2735  {
2736  assert(m_value.array != nullptr);
2737  return m_value.array->at(idx);
2738  }
2739  catch (std::out_of_range&)
2740  {
2741  // create better exception explanation
2742  throw std::out_of_range("array index " + std::to_string(idx) + " is out of range");
2743  }
2744  }
2745  else
2746  {
2747  throw std::domain_error("cannot use at() with " + type_name());
2748  }
2749  }
2750 
2774  {
2775  // at only works for arrays
2776  if (is_array())
2777  {
2778  try
2779  {
2780  assert(m_value.array != nullptr);
2781  return m_value.array->at(idx);
2782  }
2783  catch (std::out_of_range&)
2784  {
2785  // create better exception explanation
2786  throw std::out_of_range("array index " + std::to_string(idx) + " is out of range");
2787  }
2788  }
2789  else
2790  {
2791  throw std::domain_error("cannot use at() with " + type_name());
2792  }
2793  }
2794 
2821  reference at(const typename object_t::key_type& key)
2822  {
2823  // at only works for objects
2824  if (is_object())
2825  {
2826  try
2827  {
2828  assert(m_value.object != nullptr);
2829  return m_value.object->at(key);
2830  }
2831  catch (std::out_of_range&)
2832  {
2833  // create better exception explanation
2834  throw std::out_of_range("key '" + key + "' not found");
2835  }
2836  }
2837  else
2838  {
2839  throw std::domain_error("cannot use at() with " + type_name());
2840  }
2841  }
2842 
2869  const_reference at(const typename object_t::key_type& key) const
2870  {
2871  // at only works for objects
2872  if (is_object())
2873  {
2874  try
2875  {
2876  assert(m_value.object != nullptr);
2877  return m_value.object->at(key);
2878  }
2879  catch (std::out_of_range&)
2880  {
2881  // create better exception explanation
2882  throw std::out_of_range("key '" + key + "' not found");
2883  }
2884  }
2885  else
2886  {
2887  throw std::domain_error("cannot use at() with " + type_name());
2888  }
2889  }
2890 
2917  {
2918  // implicitly convert null to object
2919  if (is_null())
2920  {
2921  m_type = value_t::array;
2922  m_value.array = create<array_t>();
2923  }
2924 
2925  // [] only works for arrays
2926  if (is_array())
2927  {
2928  assert(m_value.array != nullptr);
2929  for (size_t i = m_value.array->size(); i <= idx; ++i)
2930  {
2931  m_value.array->push_back(basic_json());
2932  }
2933 
2934  return m_value.array->operator[](idx);
2935  }
2936  else
2937  {
2938  throw std::domain_error("cannot use operator[] with " + type_name());
2939  }
2940  }
2941 
2962  {
2963  // at only works for arrays
2964  if (is_array())
2965  {
2966  assert(m_value.array != nullptr);
2967  return m_value.array->operator[](idx);
2968  }
2969  else
2970  {
2971  throw std::domain_error("cannot use operator[] with " + type_name());
2972  }
2973  }
2974 
3002  reference operator[](const typename object_t::key_type& key)
3003  {
3004  // implicitly convert null to object
3005  if (is_null())
3006  {
3007  m_type = value_t::object;
3008  m_value.object = create<object_t>();
3009  }
3010 
3011  // [] only works for objects
3012  if (is_object())
3013  {
3014  assert(m_value.object != nullptr);
3015  return m_value.object->operator[](key);
3016  }
3017  else
3018  {
3019  throw std::domain_error("cannot use operator[] with " + type_name());
3020  }
3021  }
3022 
3050  const_reference operator[](const typename object_t::key_type& key) const
3051  {
3052  // [] only works for objects
3053  if (is_object())
3054  {
3055  assert(m_value.object != nullptr);
3056  assert(m_value.object->find(key) != m_value.object->end());
3057  return m_value.object->find(key)->second;
3058  }
3059  else
3060  {
3061  throw std::domain_error("cannot use operator[] with " + type_name());
3062  }
3063  }
3064 
3092  template<typename T, std::size_t n>
3093  reference operator[](T * (&key)[n])
3094  {
3095  return operator[](static_cast<const T>(key));
3096  }
3097 
3127  template<typename T, std::size_t n>
3128  const_reference operator[](T * (&key)[n]) const
3129  {
3130  return operator[](static_cast<const T>(key));
3131  }
3132 
3160  template<typename T>
3162  {
3163  // implicitly convert null to object
3164  if (is_null())
3165  {
3166  m_type = value_t::object;
3167  m_value = value_t::object;
3168  }
3169 
3170  // at only works for objects
3171  if (is_object())
3172  {
3173  assert(m_value.object != nullptr);
3174  return m_value.object->operator[](key);
3175  }
3176  else
3177  {
3178  throw std::domain_error("cannot use operator[] with " + type_name());
3179  }
3180  }
3181 
3209  template<typename T>
3211  {
3212  // at only works for objects
3213  if (is_object())
3214  {
3215  assert(m_value.object != nullptr);
3216  assert(m_value.object->find(key) != m_value.object->end());
3217  return m_value.object->find(key)->second;
3218  }
3219  else
3220  {
3221  throw std::domain_error("cannot use operator[] with " + type_name());
3222  }
3223  }
3224 
3273  template <class ValueType, typename
3274  std::enable_if<
3275  std::is_convertible<basic_json_t, ValueType>::value
3276  , int>::type = 0>
3277  ValueType value(const typename object_t::key_type& key, ValueType default_value) const
3278  {
3279  // at only works for objects
3280  if (is_object())
3281  {
3282  // if key is found, return value and given default value otherwise
3283  const auto it = find(key);
3284  if (it != end())
3285  {
3286  return *it;
3287  }
3288  else
3289  {
3290  return default_value;
3291  }
3292  }
3293  else
3294  {
3295  throw std::domain_error("cannot use value() with " + type_name());
3296  }
3297  }
3298 
3303  string_t value(const typename object_t::key_type& key, const char* default_value) const
3304  {
3305  return value(key, string_t(default_value));
3306  }
3307 
3329  {
3330  return *begin();
3331  }
3332 
3337  {
3338  return *cbegin();
3339  }
3340 
3363  {
3364  auto tmp = end();
3365  --tmp;
3366  return *tmp;
3367  }
3368 
3373  {
3374  auto tmp = cend();
3375  --tmp;
3376  return *tmp;
3377  }
3378 
3423  template <class InteratorType, typename
3424  std::enable_if<
3425  std::is_same<InteratorType, typename basic_json_t::iterator>::value or
3426  std::is_same<InteratorType, typename basic_json_t::const_iterator>::value
3427  , int>::type
3428  = 0>
3429  InteratorType erase(InteratorType pos)
3430  {
3431  // make sure iterator fits the current value
3432  if (this != pos.m_object)
3433  {
3434  throw std::domain_error("iterator does not fit current value");
3435  }
3436 
3437  InteratorType result = end();
3438 
3439  switch (m_type)
3440  {
3441  case value_t::boolean:
3442  case value_t::number_float:
3443  case value_t::number_integer:
3444  case value_t::string:
3445  {
3446  if (not pos.m_it.primitive_iterator.is_begin())
3447  {
3448  throw std::out_of_range("iterator out of range");
3449  }
3450 
3451  if (is_string())
3452  {
3453  delete m_value.string;
3454  m_value.string = nullptr;
3455  }
3456 
3457  m_type = value_t::null;
3458  break;
3459  }
3460 
3461  case value_t::object:
3462  {
3463  assert(m_value.object != nullptr);
3464  result.m_it.object_iterator = m_value.object->erase(pos.m_it.object_iterator);
3465  break;
3466  }
3467 
3468  case value_t::array:
3469  {
3470  assert(m_value.array != nullptr);
3471  result.m_it.array_iterator = m_value.array->erase(pos.m_it.array_iterator);
3472  break;
3473  }
3474 
3475  default:
3476  {
3477  throw std::domain_error("cannot use erase() with " + type_name());
3478  }
3479  }
3480 
3481  return result;
3482  }
3483 
3528  template <class InteratorType, typename
3529  std::enable_if<
3530  std::is_same<InteratorType, typename basic_json_t::iterator>::value or
3531  std::is_same<InteratorType, typename basic_json_t::const_iterator>::value
3532  , int>::type
3533  = 0>
3534  InteratorType erase(InteratorType first, InteratorType last)
3535  {
3536  // make sure iterator fits the current value
3537  if (this != first.m_object or this != last.m_object)
3538  {
3539  throw std::domain_error("iterators do not fit current value");
3540  }
3541 
3542  InteratorType result = end();
3543 
3544  switch (m_type)
3545  {
3546  case value_t::boolean:
3547  case value_t::number_float:
3548  case value_t::number_integer:
3549  case value_t::string:
3550  {
3551  if (not first.m_it.primitive_iterator.is_begin() or not last.m_it.primitive_iterator.is_end())
3552  {
3553  throw std::out_of_range("iterators out of range");
3554  }
3555 
3556  if (is_string())
3557  {
3558  delete m_value.string;
3559  m_value.string = nullptr;
3560  }
3561 
3562  m_type = value_t::null;
3563  break;
3564  }
3565 
3566  case value_t::object:
3567  {
3568  assert(m_value.object != nullptr);
3569  result.m_it.object_iterator = m_value.object->erase(first.m_it.object_iterator,
3570  last.m_it.object_iterator);
3571  break;
3572  }
3573 
3574  case value_t::array:
3575  {
3576  assert(m_value.array != nullptr);
3577  result.m_it.array_iterator = m_value.array->erase(first.m_it.array_iterator,
3578  last.m_it.array_iterator);
3579  break;
3580  }
3581 
3582  default:
3583  {
3584  throw std::domain_error("cannot use erase() with " + type_name());
3585  }
3586  }
3587 
3588  return result;
3589  }
3590 
3617  size_type erase(const typename object_t::key_type& key)
3618  {
3619  // this erase only works for objects
3620  if (is_object())
3621  {
3622  assert(m_value.object != nullptr);
3623  return m_value.object->erase(key);
3624  }
3625  else
3626  {
3627  throw std::domain_error("cannot use erase() with " + type_name());
3628  }
3629  }
3630 
3655  void erase(const size_type idx)
3656  {
3657  // this erase only works for arrays
3658  if (is_array())
3659  {
3660  if (idx >= size())
3661  {
3662  throw std::out_of_range("index out of range");
3663  }
3664 
3665  assert(m_value.array != nullptr);
3666  m_value.array->erase(m_value.array->begin() + static_cast<difference_type>(idx));
3667  }
3668  else
3669  {
3670  throw std::domain_error("cannot use erase() with " + type_name());
3671  }
3672  }
3673 
3691  iterator find(typename object_t::key_type key)
3692  {
3693  auto result = end();
3694 
3695  if (is_object())
3696  {
3697  assert(m_value.object != nullptr);
3698  result.m_it.object_iterator = m_value.object->find(key);
3699  }
3700 
3701  return result;
3702  }
3703 
3708  const_iterator find(typename object_t::key_type key) const
3709  {
3710  auto result = cend();
3711 
3712  if (is_object())
3713  {
3714  assert(m_value.object != nullptr);
3715  result.m_it.object_iterator = m_value.object->find(key);
3716  }
3717 
3718  return result;
3719  }
3720 
3739  size_type count(typename object_t::key_type key) const
3740  {
3741  // return 0 for all nonobject types
3742  assert(not is_object() or m_value.object != nullptr);
3743  return is_object() ? m_value.object->count(key) : 0;
3744  }
3745 
3747 
3748 
3750  // iterators //
3752 
3755 
3775  {
3776  iterator result(this);
3777  result.set_begin();
3778  return result;
3779  }
3780 
3785  {
3786  return cbegin();
3787  }
3788 
3809  {
3810  const_iterator result(this);
3811  result.set_begin();
3812  return result;
3813  }
3814 
3834  {
3835  iterator result(this);
3836  result.set_end();
3837  return result;
3838  }
3839 
3844  {
3845  return cend();
3846  }
3847 
3868  {
3869  const_iterator result(this);
3870  result.set_end();
3871  return result;
3872  }
3873 
3892  {
3893  return reverse_iterator(end());
3894  }
3895 
3900  {
3901  return crbegin();
3902  }
3903 
3923  {
3924  return reverse_iterator(begin());
3925  }
3926 
3931  {
3932  return crend();
3933  }
3934 
3954  {
3955  return const_reverse_iterator(cend());
3956  }
3957 
3977  {
3978  return const_reverse_iterator(cbegin());
3979  }
3980 
3981  private:
3982  // forward declaration
3983  template<typename IteratorType> class iteration_proxy;
3984 
3985  public:
3997  static iteration_proxy<iterator> iterator_wrapper(reference cont)
3998  {
3999  return iteration_proxy<iterator>(cont);
4000  }
4001 
4005  static iteration_proxy<const_iterator> iterator_wrapper(const_reference cont)
4006  {
4007  return iteration_proxy<const_iterator>(cont);
4008  }
4009 
4011 
4012 
4014  // capacity //
4016 
4019 
4049  bool empty() const noexcept
4050  {
4051  switch (m_type)
4052  {
4053  case value_t::null:
4054  {
4055  // null values are empty
4056  return true;
4057  }
4058 
4059  case value_t::array:
4060  {
4061  assert(m_value.array != nullptr);
4062  return m_value.array->empty();
4063  }
4064 
4065  case value_t::object:
4066  {
4067  assert(m_value.object != nullptr);
4068  return m_value.object->empty();
4069  }
4070 
4071  default:
4072  {
4073  // all other types are nonempty
4074  return false;
4075  }
4076  }
4077  }
4078 
4107  size_type size() const noexcept
4108  {
4109  switch (m_type)
4110  {
4111  case value_t::null:
4112  {
4113  // null values are empty
4114  return 0;
4115  }
4116 
4117  case value_t::array:
4118  {
4119  assert(m_value.array != nullptr);
4120  return m_value.array->size();
4121  }
4122 
4123  case value_t::object:
4124  {
4125  assert(m_value.object != nullptr);
4126  return m_value.object->size();
4127  }
4128 
4129  default:
4130  {
4131  // all other types have size 1
4132  return 1;
4133  }
4134  }
4135  }
4136 
4169  size_type max_size() const noexcept
4170  {
4171  switch (m_type)
4172  {
4173  case value_t::array:
4174  {
4175  assert(m_value.array != nullptr);
4176  return m_value.array->max_size();
4177  }
4178 
4179  case value_t::object:
4180  {
4181  assert(m_value.object != nullptr);
4182  return m_value.object->max_size();
4183  }
4184 
4185  default:
4186  {
4187  // all other types have max_size() == size()
4188  return size();
4189  }
4190  }
4191  }
4192 
4194 
4195 
4197  // modifiers //
4199 
4202 
4228  void clear() noexcept
4229  {
4230  switch (m_type)
4231  {
4232  case value_t::number_integer:
4233  {
4234  m_value.number_integer = 0;
4235  break;
4236  }
4237 
4238  case value_t::number_float:
4239  {
4240  m_value.number_float = 0.0;
4241  break;
4242  }
4243 
4244  case value_t::boolean:
4245  {
4246  m_value.boolean = false;
4247  break;
4248  }
4249 
4250  case value_t::string:
4251  {
4252  assert(m_value.string != nullptr);
4253  m_value.string->clear();
4254  break;
4255  }
4256 
4257  case value_t::array:
4258  {
4259  assert(m_value.array != nullptr);
4260  m_value.array->clear();
4261  break;
4262  }
4263 
4264  case value_t::object:
4265  {
4266  assert(m_value.object != nullptr);
4267  m_value.object->clear();
4268  break;
4269  }
4270 
4271  default:
4272  {
4273  break;
4274  }
4275  }
4276  }
4277 
4298  void push_back(basic_json&& val)
4299  {
4300  // push_back only works for null objects or arrays
4301  if (not(is_null() or is_array()))
4302  {
4303  throw std::domain_error("cannot use push_back() with " + type_name());
4304  }
4305 
4306  // transform null object into an array
4307  if (is_null())
4308  {
4309  m_type = value_t::array;
4310  m_value = value_t::array;
4311  }
4312 
4313  // add element to array (move semantics)
4314  assert(m_value.array != nullptr);
4315  m_value.array->push_back(std::move(val));
4316  // invalidate object
4317  val.m_type = value_t::null;
4318  }
4319 
4324  reference operator+=(basic_json&& val)
4325  {
4326  push_back(std::move(val));
4327  return *this;
4328  }
4329 
4334  void push_back(const basic_json& val)
4335  {
4336  // push_back only works for null objects or arrays
4337  if (not(is_null() or is_array()))
4338  {
4339  throw std::domain_error("cannot use push_back() with " + type_name());
4340  }
4341 
4342  // transform null object into an array
4343  if (is_null())
4344  {
4345  m_type = value_t::array;
4346  m_value = value_t::array;
4347  }
4348 
4349  // add element to array
4350  assert(m_value.array != nullptr);
4351  m_value.array->push_back(val);
4352  }
4353 
4358  reference operator+=(const basic_json& val)
4359  {
4360  push_back(val);
4361  return *this;
4362  }
4363 
4384  void push_back(const typename object_t::value_type& val)
4385  {
4386  // push_back only works for null objects or objects
4387  if (not(is_null() or is_object()))
4388  {
4389  throw std::domain_error("cannot use push_back() with " + type_name());
4390  }
4391 
4392  // transform null object into an object
4393  if (is_null())
4394  {
4395  m_type = value_t::object;
4396  m_value = value_t::object;
4397  }
4398 
4399  // add element to array
4400  assert(m_value.object != nullptr);
4401  m_value.object->insert(val);
4402  }
4403 
4408  reference operator+=(const typename object_t::value_type& val)
4409  {
4410  push_back(val);
4411  return operator[](val.first);
4412  }
4413 
4436  iterator insert(const_iterator pos, const basic_json& val)
4437  {
4438  // insert only works for arrays
4439  if (is_array())
4440  {
4441  // check if iterator pos fits to this JSON value
4442  if (pos.m_object != this)
4443  {
4444  throw std::domain_error("iterator does not fit current value");
4445  }
4446 
4447  // insert to array and return iterator
4448  iterator result(this);
4449  assert(m_value.array != nullptr);
4450  result.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator, val);
4451  return result;
4452  }
4453  else
4454  {
4455  throw std::domain_error("cannot use insert() with " + type_name());
4456  }
4457  }
4458 
4463  iterator insert(const_iterator pos, basic_json&& val)
4464  {
4465  return insert(pos, val);
4466  }
4467 
4492  iterator insert(const_iterator pos, size_type cnt, const basic_json& val)
4493  {
4494  // insert only works for arrays
4495  if (is_array())
4496  {
4497  // check if iterator pos fits to this JSON value
4498  if (pos.m_object != this)
4499  {
4500  throw std::domain_error("iterator does not fit current value");
4501  }
4502 
4503  // insert to array and return iterator
4504  iterator result(this);
4505  assert(m_value.array != nullptr);
4506  result.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator, cnt, val);
4507  return result;
4508  }
4509  else
4510  {
4511  throw std::domain_error("cannot use insert() with " + type_name());
4512  }
4513  }
4514 
4546  {
4547  // insert only works for arrays
4548  if (not is_array())
4549  {
4550  throw std::domain_error("cannot use insert() with " + type_name());
4551  }
4552 
4553  // check if iterator pos fits to this JSON value
4554  if (pos.m_object != this)
4555  {
4556  throw std::domain_error("iterator does not fit current value");
4557  }
4558 
4559  if (first.m_object != last.m_object)
4560  {
4561  throw std::domain_error("iterators do not fit");
4562  }
4563 
4564  if (first.m_object == this or last.m_object == this)
4565  {
4566  throw std::domain_error("passed iterators may not belong to container");
4567  }
4568 
4569  // insert to array and return iterator
4570  iterator result(this);
4571  assert(m_value.array != nullptr);
4572  result.m_it.array_iterator = m_value.array->insert(
4573  pos.m_it.array_iterator,
4574  first.m_it.array_iterator,
4575  last.m_it.array_iterator);
4576  return result;
4577  }
4578 
4603  iterator insert(const_iterator pos, std::initializer_list<basic_json> ilist)
4604  {
4605  // insert only works for arrays
4606  if (not is_array())
4607  {
4608  throw std::domain_error("cannot use insert() with " + type_name());
4609  }
4610 
4611  // check if iterator pos fits to this JSON value
4612  if (pos.m_object != this)
4613  {
4614  throw std::domain_error("iterator does not fit current value");
4615  }
4616 
4617  // insert to array and return iterator
4618  iterator result(this);
4619  assert(m_value.array != nullptr);
4620  result.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator, ilist);
4621  return result;
4622  }
4623 
4641  void swap(reference other) noexcept (
4642  std::is_nothrow_move_constructible<value_t>::value and
4643  std::is_nothrow_move_assignable<value_t>::value and
4644  std::is_nothrow_move_constructible<json_value>::value and
4645  std::is_nothrow_move_assignable<json_value>::value
4646  )
4647  {
4648  std::swap(m_type, other.m_type);
4649  std::swap(m_value, other.m_value);
4650  }
4651 
4672  void swap(array_t& other)
4673  {
4674  // swap only works for arrays
4675  if (is_array())
4676  {
4677  assert(m_value.array != nullptr);
4678  std::swap(*(m_value.array), other);
4679  }
4680  else
4681  {
4682  throw std::domain_error("cannot use swap() with " + type_name());
4683  }
4684  }
4685 
4706  void swap(object_t& other)
4707  {
4708  // swap only works for objects
4709  if (is_object())
4710  {
4711  assert(m_value.object != nullptr);
4712  std::swap(*(m_value.object), other);
4713  }
4714  else
4715  {
4716  throw std::domain_error("cannot use swap() with " + type_name());
4717  }
4718  }
4719 
4740  void swap(string_t& other)
4741  {
4742  // swap only works for strings
4743  if (is_string())
4744  {
4745  assert(m_value.string != nullptr);
4746  std::swap(*(m_value.string), other);
4747  }
4748  else
4749  {
4750  throw std::domain_error("cannot use swap() with " + type_name());
4751  }
4752  }
4753 
4755 
4756 
4758  // lexicographical comparison operators //
4760 
4763 
4764  private:
4774  friend bool operator<(const value_t lhs, const value_t rhs)
4775  {
4776  static constexpr std::array<uint8_t, 7> order = {{
4777  0, // null
4778  3, // object
4779  4, // array
4780  5, // string
4781  1, // boolean
4782  2, // integer
4783  2 // float
4784  }
4785  };
4786 
4787  // discarded values are not comparable
4788  if (lhs == value_t::discarded or rhs == value_t::discarded)
4789  {
4790  return false;
4791  }
4792 
4793  return order[static_cast<std::size_t>(lhs)] < order[static_cast<std::size_t>(rhs)];
4794  }
4795 
4796  public:
4820  friend bool operator==(const_reference lhs, const_reference rhs) noexcept
4821  {
4822  const auto lhs_type = lhs.type();
4823  const auto rhs_type = rhs.type();
4824 
4825  if (lhs_type == rhs_type)
4826  {
4827  switch (lhs_type)
4828  {
4829  case value_t::array:
4830  {
4831  assert(lhs.m_value.array != nullptr);
4832  assert(rhs.m_value.array != nullptr);
4833  return *lhs.m_value.array == *rhs.m_value.array;
4834  }
4835  case value_t::object:
4836  {
4837  assert(lhs.m_value.object != nullptr);
4838  assert(rhs.m_value.object != nullptr);
4839  return *lhs.m_value.object == *rhs.m_value.object;
4840  }
4841  case value_t::null:
4842  {
4843  return true;
4844  }
4845  case value_t::string:
4846  {
4847  assert(lhs.m_value.string != nullptr);
4848  assert(rhs.m_value.string != nullptr);
4849  return *lhs.m_value.string == *rhs.m_value.string;
4850  }
4851  case value_t::boolean:
4852  {
4853  return lhs.m_value.boolean == rhs.m_value.boolean;
4854  }
4855  case value_t::number_integer:
4856  {
4857  return lhs.m_value.number_integer == rhs.m_value.number_integer;
4858  }
4859  case value_t::number_float:
4860  {
4861  return lhs.m_value.number_float == rhs.m_value.number_float;
4862  }
4863  default:
4864  {
4865  return false;
4866  }
4867  }
4868  }
4869  else if (lhs_type == value_t::number_integer and rhs_type == value_t::number_float)
4870  {
4871  return static_cast<number_float_t>(lhs.m_value.number_integer) == rhs.m_value.number_float;
4872  }
4873  else if (lhs_type == value_t::number_float and rhs_type == value_t::number_integer)
4874  {
4875  return lhs.m_value.number_float == static_cast<number_float_t>(rhs.m_value.number_integer);
4876  }
4877  return false;
4878  }
4879 
4898  friend bool operator==(const_reference v, std::nullptr_t) noexcept
4899  {
4900  return v.is_null();
4901  }
4902 
4907  friend bool operator==(std::nullptr_t, const_reference v) noexcept
4908  {
4909  return v.is_null();
4910  }
4911 
4928  friend bool operator!=(const_reference lhs, const_reference rhs) noexcept
4929  {
4930  return not (lhs == rhs);
4931  }
4932 
4951  friend bool operator!=(const_reference v, std::nullptr_t) noexcept
4952  {
4953  return not v.is_null();
4954  }
4955 
4960  friend bool operator!=(std::nullptr_t, const_reference v) noexcept
4961  {
4962  return not v.is_null();
4963  }
4964 
4989  friend bool operator<(const_reference lhs, const_reference rhs) noexcept
4990  {
4991  const auto lhs_type = lhs.type();
4992  const auto rhs_type = rhs.type();
4993 
4994  if (lhs_type == rhs_type)
4995  {
4996  switch (lhs_type)
4997  {
4998  case value_t::array:
4999  {
5000  assert(lhs.m_value.array != nullptr);
5001  assert(rhs.m_value.array != nullptr);
5002  return *lhs.m_value.array < *rhs.m_value.array;
5003  }
5004  case value_t::object:
5005  {
5006  assert(lhs.m_value.object != nullptr);
5007  assert(rhs.m_value.object != nullptr);
5008  return *lhs.m_value.object < *rhs.m_value.object;
5009  }
5010  case value_t::null:
5011  {
5012  return false;
5013  }
5014  case value_t::string:
5015  {
5016  assert(lhs.m_value.string != nullptr);
5017  assert(rhs.m_value.string != nullptr);
5018  return *lhs.m_value.string < *rhs.m_value.string;
5019  }
5020  case value_t::boolean:
5021  {
5022  return lhs.m_value.boolean < rhs.m_value.boolean;
5023  }
5024  case value_t::number_integer:
5025  {
5026  return lhs.m_value.number_integer < rhs.m_value.number_integer;
5027  }
5028  case value_t::number_float:
5029  {
5030  return lhs.m_value.number_float < rhs.m_value.number_float;
5031  }
5032  default:
5033  {
5034  return false;
5035  }
5036  }
5037  }
5038  else if (lhs_type == value_t::number_integer and rhs_type == value_t::number_float)
5039  {
5040  return static_cast<number_float_t>(lhs.m_value.number_integer) <
5041  rhs.m_value.number_float;
5042  }
5043  else if (lhs_type == value_t::number_float and rhs_type == value_t::number_integer)
5044  {
5045  return lhs.m_value.number_float <
5046  static_cast<number_float_t>(rhs.m_value.number_integer);
5047  }
5048 
5049  // We only reach this line if we cannot compare values. In that case,
5050  // we compare types. Note we have to call the operator explicitly,
5051  // because MSVC has problems otherwise.
5052  return operator<(lhs_type, rhs_type);
5053  }
5054 
5072  friend bool operator<=(const_reference lhs, const_reference rhs) noexcept
5073  {
5074  return not (rhs < lhs);
5075  }
5076 
5094  friend bool operator>(const_reference lhs, const_reference rhs) noexcept
5095  {
5096  return not (lhs <= rhs);
5097  }
5098 
5116  friend bool operator>=(const_reference lhs, const_reference rhs) noexcept
5117  {
5118  return not (lhs < rhs);
5119  }
5120 
5122 
5123 
5125  // serialization //
5127 
5130 
5153  friend std::ostream& operator<<(std::ostream& o, const basic_json& j)
5154  {
5155  // read width member and use it as indentation parameter if nonzero
5156  const bool pretty_print = (o.width() > 0);
5157  const auto indentation = (pretty_print ? o.width() : 0);
5158 
5159  // reset width to 0 for subsequent calls to this stream
5160  o.width(0);
5161 
5162  // do the actual serialization
5163  j.dump(o, pretty_print, static_cast<unsigned int>(indentation));
5164  return o;
5165  }
5166 
5171  friend std::ostream& operator>>(const basic_json& j, std::ostream& o)
5172  {
5173  return o << j;
5174  }
5175 
5177 
5178 
5180  // deserialization //
5182 
5185 
5210  static basic_json parse(const string_t& s, parser_callback_t cb = nullptr)
5211  {
5212  return parser(s, cb).parse();
5213  }
5214 
5239  static basic_json parse(std::istream& i, parser_callback_t cb = nullptr)
5240  {
5241  return parser(i, cb).parse();
5242  }
5243 
5247  static basic_json parse(std::istream&& i, parser_callback_t cb = nullptr)
5248  {
5249  return parser(i, cb).parse();
5250  }
5251 
5275  friend std::istream& operator<<(basic_json& j, std::istream& i)
5276  {
5277  j = parser(i).parse();
5278  return i;
5279  }
5280 
5285  friend std::istream& operator>>(std::istream& i, basic_json& j)
5286  {
5287  j = parser(i).parse();
5288  return i;
5289  }
5290 
5292 
5293 
5294  private:
5296  // convenience functions //
5298 
5300  string_t type_name() const
5301  {
5302  switch (m_type)
5303  {
5304  case value_t::null:
5305  return "null";
5306  case value_t::object:
5307  return "object";
5308  case value_t::array:
5309  return "array";
5310  case value_t::string:
5311  return "string";
5312  case value_t::boolean:
5313  return "boolean";
5314  case value_t::discarded:
5315  return "discarded";
5316  default:
5317  return "number";
5318  }
5319  }
5320 
5329  static std::size_t extra_space(const string_t& s) noexcept
5330  {
5331  std::size_t result = 0;
5332 
5333  for (const auto& c : s)
5334  {
5335  switch (c)
5336  {
5337  case '"':
5338  case '\\':
5339  case '\b':
5340  case '\f':
5341  case '\n':
5342  case '\r':
5343  case '\t':
5344  {
5345  // from c (1 byte) to \x (2 bytes)
5346  result += 1;
5347  break;
5348  }
5349 
5350  default:
5351  {
5352  if (c >= 0x00 and c <= 0x1f)
5353  {
5354  // from c (1 byte) to \uxxxx (6 bytes)
5355  result += 5;
5356  }
5357  break;
5358  }
5359  }
5360  }
5361 
5362  return result;
5363  }
5364 
5378  static string_t escape_string(const string_t& s) noexcept
5379  {
5380  const auto space = extra_space(s);
5381  if (space == 0)
5382  {
5383  return s;
5384  }
5385 
5386  // create a result string of necessary size
5387  string_t result(s.size() + space, '\\');
5388  std::size_t pos = 0;
5389 
5390  for (const auto& c : s)
5391  {
5392  switch (c)
5393  {
5394  // quotation mark (0x22)
5395  case '"':
5396  {
5397  result[pos + 1] = '"';
5398  pos += 2;
5399  break;
5400  }
5401 
5402  // reverse solidus (0x5c)
5403  case '\\':
5404  {
5405  // nothing to change
5406  pos += 2;
5407  break;
5408  }
5409 
5410  // backspace (0x08)
5411  case '\b':
5412  {
5413  result[pos + 1] = 'b';
5414  pos += 2;
5415  break;
5416  }
5417 
5418  // formfeed (0x0c)
5419  case '\f':
5420  {
5421  result[pos + 1] = 'f';
5422  pos += 2;
5423  break;
5424  }
5425 
5426  // newline (0x0a)
5427  case '\n':
5428  {
5429  result[pos + 1] = 'n';
5430  pos += 2;
5431  break;
5432  }
5433 
5434  // carriage return (0x0d)
5435  case '\r':
5436  {
5437  result[pos + 1] = 'r';
5438  pos += 2;
5439  break;
5440  }
5441 
5442  // horizontal tab (0x09)
5443  case '\t':
5444  {
5445  result[pos + 1] = 't';
5446  pos += 2;
5447  break;
5448  }
5449 
5450  default:
5451  {
5452  if (c >= 0x00 and c <= 0x1f)
5453  {
5454  // convert a number 0..15 to its hex representation (0..f)
5455  auto hexify = [](const char v) -> char
5456  {
5457  return (v < 10) ? ('0' + v) : ('a' + v - 10);
5458  };
5459 
5460  // print character c as \uxxxx
5461  for (const char m :
5462  { 'u', '0', '0', hexify(c >> 4), hexify(c & 0x0f)
5463  })
5464  {
5465  result[++pos] = m;
5466  }
5467 
5468  ++pos;
5469  }
5470  else
5471  {
5472  // all other characters are added as-is
5473  result[pos++] = c;
5474  }
5475  break;
5476  }
5477  }
5478  }
5479 
5480  return result;
5481  }
5482 
5500  void dump(std::ostream& o,
5501  const bool pretty_print,
5502  const unsigned int indent_step,
5503  const unsigned int current_indent = 0) const
5504  {
5505  // variable to hold indentation for recursive calls
5506  unsigned int new_indent = current_indent;
5507 
5508  switch (m_type)
5509  {
5510  case value_t::object:
5511  {
5512  assert(m_value.object != nullptr);
5513 
5514  if (m_value.object->empty())
5515  {
5516  o << "{}";
5517  return;
5518  }
5519 
5520  o << "{";
5521 
5522  // increase indentation
5523  if (pretty_print)
5524  {
5525  new_indent += indent_step;
5526  o << "\n";
5527  }
5528 
5529  for (auto i = m_value.object->cbegin(); i != m_value.object->cend(); ++i)
5530  {
5531  if (i != m_value.object->cbegin())
5532  {
5533  o << (pretty_print ? ",\n" : ",");
5534  }
5535  o << string_t(new_indent, ' ') << "\""
5536  << escape_string(i->first) << "\":"
5537  << (pretty_print ? " " : "");
5538  i->second.dump(o, pretty_print, indent_step, new_indent);
5539  }
5540 
5541  // decrease indentation
5542  if (pretty_print)
5543  {
5544  new_indent -= indent_step;
5545  o << "\n";
5546  }
5547 
5548  o << string_t(new_indent, ' ') + "}";
5549  return;
5550  }
5551 
5552  case value_t::array:
5553  {
5554  assert(m_value.array != nullptr);
5555 
5556  if (m_value.array->empty())
5557  {
5558  o << "[]";
5559  return;
5560  }
5561 
5562  o << "[";
5563 
5564  // increase indentation
5565  if (pretty_print)
5566  {
5567  new_indent += indent_step;
5568  o << "\n";
5569  }
5570 
5571  for (auto i = m_value.array->cbegin(); i != m_value.array->cend(); ++i)
5572  {
5573  if (i != m_value.array->cbegin())
5574  {
5575  o << (pretty_print ? ",\n" : ",");
5576  }
5577  o << string_t(new_indent, ' ');
5578  i->dump(o, pretty_print, indent_step, new_indent);
5579  }
5580 
5581  // decrease indentation
5582  if (pretty_print)
5583  {
5584  new_indent -= indent_step;
5585  o << "\n";
5586  }
5587 
5588  o << string_t(new_indent, ' ') << "]";
5589  return;
5590  }
5591 
5592  case value_t::string:
5593  {
5594  assert(m_value.string != nullptr);
5595  o << string_t("\"") << escape_string(*m_value.string) << "\"";
5596  return;
5597  }
5598 
5599  case value_t::boolean:
5600  {
5601  o << (m_value.boolean ? "true" : "false");
5602  return;
5603  }
5604 
5605  case value_t::number_integer:
5606  {
5607  o << m_value.number_integer;
5608  return;
5609  }
5610 
5611  case value_t::number_float:
5612  {
5613  // If the number is an integer then output as a fixed with with
5614  // precision 1 to output "0.0", "1.0" etc as expected for some
5615  // round trip tests otherwise 15 digits of precision allows
5616  // round-trip IEEE 754 string->double->string; to be safe, we
5617  // read this value from
5618  // std::numeric_limits<number_float_t>::digits10
5619  if (std::fmod(m_value.number_float, 1) == 0)
5620  {
5621  o << std::fixed << std::setprecision(1);
5622  }
5623  else
5624  {
5625  // std::defaultfloat not supported in gcc version < 5
5626  o.unsetf(std::ios_base::floatfield);
5627  o << std::setprecision(std::numeric_limits<double>::digits10);
5628  }
5629  o << m_value.number_float;
5630  return;
5631  }
5632 
5633  case value_t::discarded:
5634  {
5635  o << "<discarded>";
5636  return;
5637  }
5638 
5639  case value_t::null:
5640  {
5641  o << "null";
5642  return;
5643  }
5644  }
5645  }
5646 
5647  private:
5649  // member variables //
5651 
5653  value_t m_type = value_t::null;
5654 
5656  json_value m_value = {};
5657 
5658 
5659  private:
5661  // iterators //
5663 
5673  class primitive_iterator_t
5674  {
5675  public:
5677  void set_begin()
5678  {
5679  m_it = begin_value;
5680  }
5681 
5683  void set_end()
5684  {
5685  m_it = end_value;
5686  }
5687 
5689  bool is_begin() const
5690  {
5691  return (m_it == begin_value);
5692  }
5693 
5695  bool is_end() const
5696  {
5697  return (m_it == end_value);
5698  }
5699 
5701  operator difference_type& ()
5702  {
5703  return m_it;
5704  }
5705 
5707  operator difference_type () const
5708  {
5709  return m_it;
5710  }
5711 
5712  private:
5713  static constexpr difference_type begin_value = 0;
5714  static constexpr difference_type end_value = begin_value + 1;
5715 
5717  difference_type m_it = std::numeric_limits<std::ptrdiff_t>::denorm_min();
5718  };
5719 
5727  struct internal_iterator
5728  {
5730  typename object_t::iterator object_iterator;
5732  typename array_t::iterator array_iterator;
5734  primitive_iterator_t primitive_iterator;
5735 
5737  internal_iterator()
5738  : object_iterator(), array_iterator(), primitive_iterator()
5739  {}
5740  };
5741 
5743  template<typename IteratorType>
5744  class iteration_proxy
5745  {
5746  private:
5748  class iteration_proxy_internal
5749  {
5750  private:
5752  IteratorType anchor;
5754  size_t array_index = 0;
5755 
5756  public:
5757  iteration_proxy_internal(IteratorType it)
5758  : anchor(it)
5759  {}
5760 
5762  iteration_proxy_internal& operator*()
5763  {
5764  return *this;
5765  }
5766 
5768  iteration_proxy_internal& operator++()
5769  {
5770  ++anchor;
5771  ++array_index;
5772 
5773  return *this;
5774  }
5775 
5777  bool operator!= (const iteration_proxy_internal& o) const
5778  {
5779  return anchor != o.anchor;
5780  }
5781 
5783  typename basic_json::string_t key() const
5784  {
5785  assert(anchor.m_object != nullptr);
5786 
5787  switch (anchor.m_object->type())
5788  {
5789  // use integer array index as key
5790  case value_t::array:
5791  {
5792  return std::to_string(array_index);
5793  }
5794 
5795  // use key from the object
5796  case value_t::object:
5797  {
5798  return anchor.key();
5799  }
5800 
5801  // use an empty key for all primitive types
5802  default:
5803  {
5804  return "";
5805  }
5806  }
5807  }
5808 
5810  typename IteratorType::reference value() const
5811  {
5812  return anchor.value();
5813  }
5814  };
5815 
5817  typename IteratorType::reference container;
5818 
5819  public:
5821  iteration_proxy(typename IteratorType::reference cont)
5822  : container(cont)
5823  {}
5824 
5826  iteration_proxy_internal begin()
5827  {
5828  return iteration_proxy_internal(container.begin());
5829  }
5830 
5832  iteration_proxy_internal end()
5833  {
5834  return iteration_proxy_internal(container.end());
5835  }
5836  };
5837 
5838  public:
5852  class const_iterator : public std::iterator<std::random_access_iterator_tag, const basic_json>
5853  {
5855  friend class basic_json;
5856 
5857  public:
5867  using iterator_category = std::bidirectional_iterator_tag;
5868 
5870  const_iterator() = default;
5871 
5873  const_iterator(pointer object) : m_object(object)
5874  {
5875  assert(m_object != nullptr);
5876 
5877  switch (m_object->m_type)
5878  {
5880  {
5881  m_it.object_iterator = typename object_t::iterator();
5882  break;
5883  }
5884 
5886  {
5887  m_it.array_iterator = typename array_t::iterator();
5888  break;
5889  }
5890 
5891  default:
5892  {
5893  m_it.primitive_iterator = primitive_iterator_t();
5894  break;
5895  }
5896  }
5897  }
5898 
5900  const_iterator(const iterator& other) : m_object(other.m_object)
5901  {
5902  assert(m_object != nullptr);
5903 
5904  switch (m_object->m_type)
5905  {
5907  {
5908  m_it.object_iterator = other.m_it.object_iterator;
5909  break;
5910  }
5911 
5913  {
5914  m_it.array_iterator = other.m_it.array_iterator;
5915  break;
5916  }
5917 
5918  default:
5919  {
5920  m_it.primitive_iterator = other.m_it.primitive_iterator;
5921  break;
5922  }
5923  }
5924  }
5925 
5927  const_iterator(const const_iterator& other) noexcept
5928  : m_object(other.m_object), m_it(other.m_it)
5929  {}
5930 
5933  std::is_nothrow_move_constructible<pointer>::value and
5934  std::is_nothrow_move_assignable<pointer>::value and
5935  std::is_nothrow_move_constructible<internal_iterator>::value and
5936  std::is_nothrow_move_assignable<internal_iterator>::value
5937  )
5938  {
5939  std::swap(m_object, other.m_object);
5940  std::swap(m_it, other.m_it);
5941  return *this;
5942  }
5943 
5944  private:
5946  void set_begin()
5947  {
5948  assert(m_object != nullptr);
5949 
5950  switch (m_object->m_type)
5951  {
5953  {
5954  assert(m_object->m_value.object != nullptr);
5955  m_it.object_iterator = m_object->m_value.object->begin();
5956  break;
5957  }
5958 
5960  {
5961  assert(m_object->m_value.array != nullptr);
5962  m_it.array_iterator = m_object->m_value.array->begin();
5963  break;
5964  }
5965 
5967  {
5968  // set to end so begin()==end() is true: null is empty
5969  m_it.primitive_iterator.set_end();
5970  break;
5971  }
5972 
5973  default:
5974  {
5975  m_it.primitive_iterator.set_begin();
5976  break;
5977  }
5978  }
5979  }
5980 
5982  void set_end()
5983  {
5984  assert(m_object != nullptr);
5985 
5986  switch (m_object->m_type)
5987  {
5989  {
5990  assert(m_object->m_value.object != nullptr);
5991  m_it.object_iterator = m_object->m_value.object->end();
5992  break;
5993  }
5994 
5996  {
5997  assert(m_object->m_value.array != nullptr);
5998  m_it.array_iterator = m_object->m_value.array->end();
5999  break;
6000  }
6001 
6002  default:
6003  {
6004  m_it.primitive_iterator.set_end();
6005  break;
6006  }
6007  }
6008  }
6009 
6010  public:
6013  {
6014  assert(m_object != nullptr);
6015 
6016  switch (m_object->m_type)
6017  {
6019  {
6020  assert(m_object->m_value.object);
6021  assert(m_it.object_iterator != m_object->m_value.object->end());
6022  return m_it.object_iterator->second;
6023  }
6024 
6026  {
6027  assert(m_object->m_value.array);
6028  assert(m_it.array_iterator != m_object->m_value.array->end());
6029  return *m_it.array_iterator;
6030  }
6031 
6033  {
6034  throw std::out_of_range("cannot get value");
6035  }
6036 
6037  default:
6038  {
6039  if (m_it.primitive_iterator.is_begin())
6040  {
6041  return *m_object;
6042  }
6043  else
6044  {
6045  throw std::out_of_range("cannot get value");
6046  }
6047  }
6048  }
6049  }
6050 
6053  {
6054  assert(m_object != nullptr);
6055 
6056  switch (m_object->m_type)
6057  {
6059  {
6060  assert(m_object->m_value.object);
6061  assert(m_it.object_iterator != m_object->m_value.object->end());
6062  return &(m_it.object_iterator->second);
6063  }
6064 
6066  {
6067  assert(m_object->m_value.array);
6068  assert(m_it.array_iterator != m_object->m_value.array->end());
6069  return &*m_it.array_iterator;
6070  }
6071 
6072  default:
6073  {
6074  if (m_it.primitive_iterator.is_begin())
6075  {
6076  return m_object;
6077  }
6078  else
6079  {
6080  throw std::out_of_range("cannot get value");
6081  }
6082  }
6083  }
6084  }
6085 
6088  {
6089  auto result = *this;
6090  ++(*this);
6091  return result;
6092  }
6093 
6096  {
6097  assert(m_object != nullptr);
6098 
6099  switch (m_object->m_type)
6100  {
6102  {
6103  ++m_it.object_iterator;
6104  break;
6105  }
6106 
6108  {
6109  ++m_it.array_iterator;
6110  break;
6111  }
6112 
6113  default:
6114  {
6115  ++m_it.primitive_iterator;
6116  break;
6117  }
6118  }
6119 
6120  return *this;
6121  }
6122 
6125  {
6126  auto result = *this;
6127  --(*this);
6128  return result;
6129  }
6130 
6133  {
6134  assert(m_object != nullptr);
6135 
6136  switch (m_object->m_type)
6137  {
6139  {
6140  --m_it.object_iterator;
6141  break;
6142  }
6143 
6145  {
6146  --m_it.array_iterator;
6147  break;
6148  }
6149 
6150  default:
6151  {
6152  --m_it.primitive_iterator;
6153  break;
6154  }
6155  }
6156 
6157  return *this;
6158  }
6159 
6161  bool operator==(const const_iterator& other) const
6162  {
6163  // if objects are not the same, the comparison is undefined
6164  if (m_object != other.m_object)
6165  {
6166  throw std::domain_error("cannot compare iterators of different containers");
6167  }
6168 
6169  assert(m_object != nullptr);
6170 
6171  switch (m_object->m_type)
6172  {
6174  {
6175  return (m_it.object_iterator == other.m_it.object_iterator);
6176  }
6177 
6179  {
6180  return (m_it.array_iterator == other.m_it.array_iterator);
6181  }
6182 
6183  default:
6184  {
6185  return (m_it.primitive_iterator == other.m_it.primitive_iterator);
6186  }
6187  }
6188  }
6189 
6191  bool operator!=(const const_iterator& other) const
6192  {
6193  return not operator==(other);
6194  }
6195 
6197  bool operator<(const const_iterator& other) const
6198  {
6199  // if objects are not the same, the comparison is undefined
6200  if (m_object != other.m_object)
6201  {
6202  throw std::domain_error("cannot compare iterators of different containers");
6203  }
6204 
6205  assert(m_object != nullptr);
6206 
6207  switch (m_object->m_type)
6208  {
6210  {
6211  throw std::domain_error("cannot compare order of object iterators");
6212  }
6213 
6215  {
6216  return (m_it.array_iterator < other.m_it.array_iterator);
6217  }
6218 
6219  default:
6220  {
6221  return (m_it.primitive_iterator < other.m_it.primitive_iterator);
6222  }
6223  }
6224  }
6225 
6227  bool operator<=(const const_iterator& other) const
6228  {
6229  return not other.operator < (*this);
6230  }
6231 
6233  bool operator>(const const_iterator& other) const
6234  {
6235  return not operator<=(other);
6236  }
6237 
6239  bool operator>=(const const_iterator& other) const
6240  {
6241  return not operator<(other);
6242  }
6243 
6246  {
6247  assert(m_object != nullptr);
6248 
6249  switch (m_object->m_type)
6250  {
6252  {
6253  throw std::domain_error("cannot use offsets with object iterators");
6254  }
6255 
6257  {
6258  m_it.array_iterator += i;
6259  break;
6260  }
6261 
6262  default:
6263  {
6264  m_it.primitive_iterator += i;
6265  break;
6266  }
6267  }
6268 
6269  return *this;
6270  }
6271 
6274  {
6275  return operator+=(-i);
6276  }
6277 
6280  {
6281  auto result = *this;
6282  result += i;
6283  return result;
6284  }
6285 
6288  {
6289  auto result = *this;
6290  result -= i;
6291  return result;
6292  }
6293 
6296  {
6297  assert(m_object != nullptr);
6298 
6299  switch (m_object->m_type)
6300  {
6302  {
6303  throw std::domain_error("cannot use offsets with object iterators");
6304  }
6305 
6307  {
6308  return m_it.array_iterator - other.m_it.array_iterator;
6309  }
6310 
6311  default:
6312  {
6313  return m_it.primitive_iterator - other.m_it.primitive_iterator;
6314  }
6315  }
6316  }
6317 
6320  {
6321  assert(m_object != nullptr);
6322 
6323  switch (m_object->m_type)
6324  {
6326  {
6327  throw std::domain_error("cannot use operator[] for object iterators");
6328  }
6329 
6331  {
6332  return *(m_it.array_iterator + n);
6333  }
6334 
6336  {
6337  throw std::out_of_range("cannot get value");
6338  }
6339 
6340  default:
6341  {
6342  if (m_it.primitive_iterator == -n)
6343  {
6344  return *m_object;
6345  }
6346  else
6347  {
6348  throw std::out_of_range("cannot get value");
6349  }
6350  }
6351  }
6352  }
6353 
6355  typename object_t::key_type key() const
6356  {
6357  assert(m_object != nullptr);
6358 
6359  if (m_object->is_object())
6360  {
6361  return m_it.object_iterator->first;
6362  }
6363  else
6364  {
6365  throw std::domain_error("cannot use key() for non-object iterators");
6366  }
6367  }
6368 
6371  {
6372  return operator*();
6373  }
6374 
6375  private:
6377  pointer m_object = nullptr;
6379  internal_iterator m_it = internal_iterator();
6380  };
6381 
6394  class iterator : public const_iterator
6395  {
6396  public:
6398  using pointer = typename basic_json::pointer;
6400 
6402  iterator() = default;
6403 
6405  iterator(pointer object) noexcept
6406  : base_iterator(object)
6407  {}
6408 
6410  iterator(const iterator& other) noexcept
6411  : base_iterator(other)
6412  {}
6413 
6415  iterator& operator=(iterator other) noexcept(
6416  std::is_nothrow_move_constructible<pointer>::value and
6417  std::is_nothrow_move_assignable<pointer>::value and
6418  std::is_nothrow_move_constructible<internal_iterator>::value and
6419  std::is_nothrow_move_assignable<internal_iterator>::value
6420  )
6421  {
6422  base_iterator::operator=(other);
6423  return *this;
6424  }
6425 
6428  {
6429  return const_cast<reference>(base_iterator::operator*());
6430  }
6431 
6434  {
6435  return const_cast<pointer>(base_iterator::operator->());
6436  }
6437 
6440  {
6441  iterator result = *this;
6442  base_iterator::operator++();
6443  return result;
6444  }
6445 
6448  {
6449  base_iterator::operator++();
6450  return *this;
6451  }
6452 
6455  {
6456  iterator result = *this;
6457  base_iterator::operator--();
6458  return result;
6459  }
6460 
6463  {
6464  base_iterator::operator--();
6465  return *this;
6466  }
6467 
6470  {
6471  base_iterator::operator+=(i);
6472  return *this;
6473  }
6474 
6477  {
6478  base_iterator::operator-=(i);
6479  return *this;
6480  }
6481 
6484  {
6485  auto result = *this;
6486  result += i;
6487  return result;
6488  }
6489 
6492  {
6493  auto result = *this;
6494  result -= i;
6495  return result;
6496  }
6497 
6498  difference_type operator-(const iterator& other) const
6499  {
6500  return base_iterator::operator-(other);
6501  }
6502 
6505  {
6506  return const_cast<reference>(base_iterator::operator[](n));
6507  }
6508 
6511  {
6512  return const_cast<reference>(base_iterator::value());
6513  }
6514  };
6515 
6533  template<typename Base>
6534  class json_reverse_iterator : public std::reverse_iterator<Base>
6535  {
6536  public:
6538  using base_iterator = std::reverse_iterator<Base>;
6540  using reference = typename Base::reference;
6541 
6543  json_reverse_iterator(const typename base_iterator::iterator_type& it)
6544  : base_iterator(it)
6545  {}
6546 
6549  : base_iterator(it)
6550  {}
6551 
6554  {
6555  return base_iterator::operator++(1);
6556  }
6557 
6560  {
6561  base_iterator::operator++();
6562  return *this;
6563  }
6564 
6567  {
6568  return base_iterator::operator--(1);
6569  }
6570 
6573  {
6574  base_iterator::operator--();
6575  return *this;
6576  }
6577 
6580  {
6581  base_iterator::operator+=(i);
6582  return *this;
6583  }
6584 
6587  {
6588  auto result = *this;
6589  result += i;
6590  return result;
6591  }
6592 
6595  {
6596  auto result = *this;
6597  result -= i;
6598  return result;
6599  }
6600 
6603  {
6604  return this->base() - other.base();
6605  }
6606 
6609  {
6610  return *(this->operator+(n));
6611  }
6612 
6614  typename object_t::key_type key() const
6615  {
6616  auto it = --this->base();
6617  return it.key();
6618  }
6619 
6622  {
6623  auto it = --this->base();
6624  return it.operator * ();
6625  }
6626  };
6627 
6628 
6629  private:
6631  // lexer and parser //
6633 
6641  class lexer
6642  {
6643  public:
6645  enum class token_type
6646  {
6647  uninitialized,
6648  literal_true,
6649  literal_false,
6650  literal_null,
6651  value_string,
6652  value_number,
6653  begin_array,
6654  begin_object,
6655  end_array,
6656  end_object,
6657  name_separator,
6658  value_separator,
6659  parse_error,
6660  end_of_input
6661  };
6662 
6664  using lexer_char_t = unsigned char;
6665 
6667  explicit lexer(const string_t& s) noexcept
6668  : m_stream(nullptr), m_buffer(s)
6669  {
6670  m_content = reinterpret_cast<const lexer_char_t*>(s.c_str());
6671  assert(m_content != nullptr);
6672  m_start = m_cursor = m_content;
6673  m_limit = m_content + s.size();
6674  }
6675 
6677  explicit lexer(std::istream* s) noexcept
6678  : m_stream(s), m_buffer()
6679  {
6680  assert(m_stream != nullptr);
6681  getline(*m_stream, m_buffer);
6682  m_content = reinterpret_cast<const lexer_char_t*>(m_buffer.c_str());
6683  assert(m_content != nullptr);
6684  m_start = m_cursor = m_content;
6685  m_limit = m_content + m_buffer.size();
6686  }
6687 
6689  lexer() = default;
6690 
6691  // switch off unwanted functions
6692  lexer(const lexer&) = delete;
6693  lexer operator=(const lexer&) = delete;
6694 
6710  static string_t to_unicode(const std::size_t codepoint1,
6711  const std::size_t codepoint2 = 0)
6712  {
6713  string_t result;
6714 
6715  // calculate the codepoint from the given code points
6716  std::size_t codepoint = codepoint1;
6717 
6718  // check if codepoint1 is a high surrogate
6719  if (codepoint1 >= 0xD800 and codepoint1 <= 0xDBFF)
6720  {
6721  // check if codepoint2 is a low surrogate
6722  if (codepoint2 >= 0xDC00 and codepoint2 <= 0xDFFF)
6723  {
6724  codepoint =
6725  // high surrogate occupies the most significant 22 bits
6726  (codepoint1 << 10)
6727  // low surrogate occupies the least significant 15 bits
6728  + codepoint2
6729  // there is still the 0xD800, 0xDC00 and 0x10000 noise
6730  // in the result so we have to subtract with:
6731  // (0xD800 << 10) + DC00 - 0x10000 = 0x35FDC00
6732  - 0x35FDC00;
6733  }
6734  else
6735  {
6736  throw std::invalid_argument("missing or wrong low surrogate");
6737  }
6738  }
6739 
6740  if (codepoint < 0x80)
6741  {
6742  // 1-byte characters: 0xxxxxxx (ASCII)
6743  result.append(1, static_cast<typename string_t::value_type>(codepoint));
6744  }
6745  else if (codepoint <= 0x7ff)
6746  {
6747  // 2-byte characters: 110xxxxx 10xxxxxx
6748  result.append(1, static_cast<typename string_t::value_type>(0xC0 | ((codepoint >> 6) & 0x1F)));
6749  result.append(1, static_cast<typename string_t::value_type>(0x80 | (codepoint & 0x3F)));
6750  }
6751  else if (codepoint <= 0xffff)
6752  {
6753  // 3-byte characters: 1110xxxx 10xxxxxx 10xxxxxx
6754  result.append(1, static_cast<typename string_t::value_type>(0xE0 | ((codepoint >> 12) & 0x0F)));
6755  result.append(1, static_cast<typename string_t::value_type>(0x80 | ((codepoint >> 6) & 0x3F)));
6756  result.append(1, static_cast<typename string_t::value_type>(0x80 | (codepoint & 0x3F)));
6757  }
6758  else if (codepoint <= 0x10ffff)
6759  {
6760  // 4-byte characters: 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
6761  result.append(1, static_cast<typename string_t::value_type>(0xF0 | ((codepoint >> 18) & 0x07)));
6762  result.append(1, static_cast<typename string_t::value_type>(0x80 | ((codepoint >> 12) & 0x3F)));
6763  result.append(1, static_cast<typename string_t::value_type>(0x80 | ((codepoint >> 6) & 0x3F)));
6764  result.append(1, static_cast<typename string_t::value_type>(0x80 | (codepoint & 0x3F)));
6765  }
6766  else
6767  {
6768  throw std::out_of_range("code points above 0x10FFFF are invalid");
6769  }
6770 
6771  return result;
6772  }
6773 
6775  static std::string token_type_name(token_type t)
6776  {
6777  switch (t)
6778  {
6779  case token_type::uninitialized:
6780  return "<uninitialized>";
6781  case token_type::literal_true:
6782  return "true literal";
6783  case token_type::literal_false:
6784  return "false literal";
6785  case token_type::literal_null:
6786  return "null literal";
6787  case token_type::value_string:
6788  return "string literal";
6789  case token_type::value_number:
6790  return "number literal";
6791  case token_type::begin_array:
6792  return "'['";
6793  case token_type::begin_object:
6794  return "'{'";
6795  case token_type::end_array:
6796  return "']'";
6797  case token_type::end_object:
6798  return "'}'";
6799  case token_type::name_separator:
6800  return "':'";
6801  case token_type::value_separator:
6802  return "','";
6803  case token_type::parse_error:
6804  return "<parse error>";
6805  case token_type::end_of_input:
6806  return "end of input";
6807  default:
6808  {
6809  // catch non-enum values
6810  return "unknown token"; // LCOV_EXCL_LINE
6811  }
6812  }
6813  }
6814 
6825  token_type scan() noexcept
6826  {
6827  // pointer for backtracking information
6828  m_marker = nullptr;
6829 
6830  // remember the begin of the token
6831  m_start = m_cursor;
6832  assert(m_start != nullptr);
6833 
6834 
6835  {
6836  lexer_char_t yych;
6837  unsigned int yyaccept = 0;
6838  static const unsigned char yybm[] = {
6839  0, 0, 0, 0, 0, 0, 0, 0,
6840  0, 32, 32, 0, 0, 32, 0, 0,
6841  128, 128, 128, 128, 128, 128, 128, 128,
6842  128, 128, 128, 128, 128, 128, 128, 128,
6843  160, 128, 0, 128, 128, 128, 128, 128,
6844  128, 128, 128, 128, 128, 128, 128, 128,
6845  192, 192, 192, 192, 192, 192, 192, 192,
6846  192, 192, 128, 128, 128, 128, 128, 128,
6847  128, 128, 128, 128, 128, 128, 128, 128,
6848  128, 128, 128, 128, 128, 128, 128, 128,
6849  128, 128, 128, 128, 128, 128, 128, 128,
6850  128, 128, 128, 128, 0, 128, 128, 128,
6851  128, 128, 128, 128, 128, 128, 128, 128,
6852  128, 128, 128, 128, 128, 128, 128, 128,
6853  128, 128, 128, 128, 128, 128, 128, 128,
6854  128, 128, 128, 128, 128, 128, 128, 128,
6855  128, 128, 128, 128, 128, 128, 128, 128,
6856  128, 128, 128, 128, 128, 128, 128, 128,
6857  128, 128, 128, 128, 128, 128, 128, 128,
6858  128, 128, 128, 128, 128, 128, 128, 128,
6859  128, 128, 128, 128, 128, 128, 128, 128,
6860  128, 128, 128, 128, 128, 128, 128, 128,
6861  128, 128, 128, 128, 128, 128, 128, 128,
6862  128, 128, 128, 128, 128, 128, 128, 128,
6863  128, 128, 128, 128, 128, 128, 128, 128,
6864  128, 128, 128, 128, 128, 128, 128, 128,
6865  128, 128, 128, 128, 128, 128, 128, 128,
6866  128, 128, 128, 128, 128, 128, 128, 128,
6867  128, 128, 128, 128, 128, 128, 128, 128,
6868  128, 128, 128, 128, 128, 128, 128, 128,
6869  128, 128, 128, 128, 128, 128, 128, 128,
6870  128, 128, 128, 128, 128, 128, 128, 128,
6871  };
6872  if ((m_limit - m_cursor) < 5) yyfill(); // LCOV_EXCL_LINE;
6873  yych = *m_cursor;
6874  if (yybm[0+yych] & 32) {
6875  goto basic_json_parser_6;
6876  }
6877  if (yych <= '\\') {
6878  if (yych <= '-') {
6879  if (yych <= '"') {
6880  if (yych <= 0x00) goto basic_json_parser_2;
6881  if (yych <= '!') goto basic_json_parser_4;
6882  goto basic_json_parser_9;
6883  } else {
6884  if (yych <= '+') goto basic_json_parser_4;
6885  if (yych <= ',') goto basic_json_parser_10;
6886  goto basic_json_parser_12;
6887  }
6888  } else {
6889  if (yych <= '9') {
6890  if (yych <= '/') goto basic_json_parser_4;
6891  if (yych <= '0') goto basic_json_parser_13;
6892  goto basic_json_parser_15;
6893  } else {
6894  if (yych <= ':') goto basic_json_parser_17;
6895  if (yych == '[') goto basic_json_parser_19;
6896  goto basic_json_parser_4;
6897  }
6898  }
6899  } else {
6900  if (yych <= 't') {
6901  if (yych <= 'f') {
6902  if (yych <= ']') goto basic_json_parser_21;
6903  if (yych <= 'e') goto basic_json_parser_4;
6904  goto basic_json_parser_23;
6905  } else {
6906  if (yych == 'n') goto basic_json_parser_24;
6907  if (yych <= 's') goto basic_json_parser_4;
6908  goto basic_json_parser_25;
6909  }
6910  } else {
6911  if (yych <= '|') {
6912  if (yych == '{') goto basic_json_parser_26;
6913  goto basic_json_parser_4;
6914  } else {
6915  if (yych <= '}') goto basic_json_parser_28;
6916  if (yych == 0xEF) goto basic_json_parser_30;
6917  goto basic_json_parser_4;
6918  }
6919  }
6920  }
6921 basic_json_parser_2:
6922  ++m_cursor;
6923  { return token_type::end_of_input; }
6924 basic_json_parser_4:
6925  ++m_cursor;
6926 basic_json_parser_5:
6927  { return token_type::parse_error; }
6928 basic_json_parser_6:
6929  ++m_cursor;
6930  if (m_limit <= m_cursor) yyfill(); // LCOV_EXCL_LINE;
6931  yych = *m_cursor;
6932  if (yybm[0+yych] & 32) {
6933  goto basic_json_parser_6;
6934  }
6935  { return scan(); }
6936 basic_json_parser_9:
6937  yyaccept = 0;
6938  yych = *(m_marker = ++m_cursor);
6939  if (yych <= 0x0F) goto basic_json_parser_5;
6940  goto basic_json_parser_32;
6941 basic_json_parser_10:
6942  ++m_cursor;
6943  { return token_type::value_separator; }
6944 basic_json_parser_12:
6945  yych = *++m_cursor;
6946  if (yych <= '/') goto basic_json_parser_5;
6947  if (yych <= '0') goto basic_json_parser_13;
6948  if (yych <= '9') goto basic_json_parser_15;
6949  goto basic_json_parser_5;
6950 basic_json_parser_13:
6951  yyaccept = 1;
6952  yych = *(m_marker = ++m_cursor);
6953  if (yych <= 'D') {
6954  if (yych == '.') goto basic_json_parser_37;
6955  } else {
6956  if (yych <= 'E') goto basic_json_parser_38;
6957  if (yych == 'e') goto basic_json_parser_38;
6958  }
6959 basic_json_parser_14:
6960  { return token_type::value_number; }
6961 basic_json_parser_15:
6962  yyaccept = 1;
6963  m_marker = ++m_cursor;
6964  if ((m_limit - m_cursor) < 3) yyfill(); // LCOV_EXCL_LINE;
6965  yych = *m_cursor;
6966  if (yybm[0+yych] & 64) {
6967  goto basic_json_parser_15;
6968  }
6969  if (yych <= 'D') {
6970  if (yych == '.') goto basic_json_parser_37;
6971  goto basic_json_parser_14;
6972  } else {
6973  if (yych <= 'E') goto basic_json_parser_38;
6974  if (yych == 'e') goto basic_json_parser_38;
6975  goto basic_json_parser_14;
6976  }
6977 basic_json_parser_17:
6978  ++m_cursor;
6979  { return token_type::name_separator; }
6980 basic_json_parser_19:
6981  ++m_cursor;
6982  { return token_type::begin_array; }
6983 basic_json_parser_21:
6984  ++m_cursor;
6985  { return token_type::end_array; }
6986 basic_json_parser_23:
6987  yyaccept = 0;
6988  yych = *(m_marker = ++m_cursor);
6989  if (yych == 'a') goto basic_json_parser_39;
6990  goto basic_json_parser_5;
6991 basic_json_parser_24:
6992  yyaccept = 0;
6993  yych = *(m_marker = ++m_cursor);
6994  if (yych == 'u') goto basic_json_parser_40;
6995  goto basic_json_parser_5;
6996 basic_json_parser_25:
6997  yyaccept = 0;
6998  yych = *(m_marker = ++m_cursor);
6999  if (yych == 'r') goto basic_json_parser_41;
7000  goto basic_json_parser_5;
7001 basic_json_parser_26:
7002  ++m_cursor;
7003  { return token_type::begin_object; }
7004 basic_json_parser_28:
7005  ++m_cursor;
7006  { return token_type::end_object; }
7007 basic_json_parser_30:
7008  yyaccept = 0;
7009  yych = *(m_marker = ++m_cursor);
7010  if (yych == 0xBB) goto basic_json_parser_42;
7011  goto basic_json_parser_5;
7012 basic_json_parser_31:
7013  ++m_cursor;
7014  if (m_limit <= m_cursor) yyfill(); // LCOV_EXCL_LINE;
7015  yych = *m_cursor;
7016 basic_json_parser_32:
7017  if (yybm[0+yych] & 128) {
7018  goto basic_json_parser_31;
7019  }
7020  if (yych <= 0x0F) goto basic_json_parser_33;
7021  if (yych <= '"') goto basic_json_parser_34;
7022  goto basic_json_parser_36;
7023 basic_json_parser_33:
7024  m_cursor = m_marker;
7025  if (yyaccept == 0) {
7026  goto basic_json_parser_5;
7027  } else {
7028  goto basic_json_parser_14;
7029  }
7030 basic_json_parser_34:
7031  ++m_cursor;
7032  { return token_type::value_string; }
7033 basic_json_parser_36:
7034  ++m_cursor;
7035  if (m_limit <= m_cursor) yyfill(); // LCOV_EXCL_LINE;
7036  yych = *m_cursor;
7037  if (yych <= 'e') {
7038  if (yych <= '/') {
7039  if (yych == '"') goto basic_json_parser_31;
7040  if (yych <= '.') goto basic_json_parser_33;
7041  goto basic_json_parser_31;
7042  } else {
7043  if (yych <= '\\') {
7044  if (yych <= '[') goto basic_json_parser_33;
7045  goto basic_json_parser_31;
7046  } else {
7047  if (yych == 'b') goto basic_json_parser_31;
7048  goto basic_json_parser_33;
7049  }
7050  }
7051  } else {
7052  if (yych <= 'q') {
7053  if (yych <= 'f') goto basic_json_parser_31;
7054  if (yych == 'n') goto basic_json_parser_31;
7055  goto basic_json_parser_33;
7056  } else {
7057  if (yych <= 's') {
7058  if (yych <= 'r') goto basic_json_parser_31;
7059  goto basic_json_parser_33;
7060  } else {
7061  if (yych <= 't') goto basic_json_parser_31;
7062  if (yych <= 'u') goto basic_json_parser_43;
7063  goto basic_json_parser_33;
7064  }
7065  }
7066  }
7067 basic_json_parser_37:
7068  yych = *++m_cursor;
7069  if (yych <= '/') goto basic_json_parser_33;
7070  if (yych <= '9') goto basic_json_parser_44;
7071  goto basic_json_parser_33;
7072 basic_json_parser_38:
7073  yych = *++m_cursor;
7074  if (yych <= ',') {
7075  if (yych == '+') goto basic_json_parser_46;
7076  goto basic_json_parser_33;
7077  } else {
7078  if (yych <= '-') goto basic_json_parser_46;
7079  if (yych <= '/') goto basic_json_parser_33;
7080  if (yych <= '9') goto basic_json_parser_47;
7081  goto basic_json_parser_33;
7082  }
7083 basic_json_parser_39:
7084  yych = *++m_cursor;
7085  if (yych == 'l') goto basic_json_parser_49;
7086  goto basic_json_parser_33;
7087 basic_json_parser_40:
7088  yych = *++m_cursor;
7089  if (yych == 'l') goto basic_json_parser_50;
7090  goto basic_json_parser_33;
7091 basic_json_parser_41:
7092  yych = *++m_cursor;
7093  if (yych == 'u') goto basic_json_parser_51;
7094  goto basic_json_parser_33;
7095 basic_json_parser_42:
7096  yych = *++m_cursor;
7097  if (yych == 0xBF) goto basic_json_parser_52;
7098  goto basic_json_parser_33;
7099 basic_json_parser_43:
7100  ++m_cursor;
7101  if (m_limit <= m_cursor) yyfill(); // LCOV_EXCL_LINE;
7102  yych = *m_cursor;
7103  if (yych <= '@') {
7104  if (yych <= '/') goto basic_json_parser_33;
7105  if (yych <= '9') goto basic_json_parser_54;
7106  goto basic_json_parser_33;
7107  } else {
7108  if (yych <= 'F') goto basic_json_parser_54;
7109  if (yych <= '`') goto basic_json_parser_33;
7110  if (yych <= 'f') goto basic_json_parser_54;
7111  goto basic_json_parser_33;
7112  }
7113 basic_json_parser_44:
7114  yyaccept = 1;
7115  m_marker = ++m_cursor;
7116  if ((m_limit - m_cursor) < 3) yyfill(); // LCOV_EXCL_LINE;
7117  yych = *m_cursor;
7118  if (yych <= 'D') {
7119  if (yych <= '/') goto basic_json_parser_14;
7120  if (yych <= '9') goto basic_json_parser_44;
7121  goto basic_json_parser_14;
7122  } else {
7123  if (yych <= 'E') goto basic_json_parser_38;
7124  if (yych == 'e') goto basic_json_parser_38;
7125  goto basic_json_parser_14;
7126  }
7127 basic_json_parser_46:
7128  yych = *++m_cursor;
7129  if (yych <= '/') goto basic_json_parser_33;
7130  if (yych >= ':') goto basic_json_parser_33;
7131 basic_json_parser_47:
7132  ++m_cursor;
7133  if (m_limit <= m_cursor) yyfill(); // LCOV_EXCL_LINE;
7134  yych = *m_cursor;
7135  if (yych <= '/') goto basic_json_parser_14;
7136  if (yych <= '9') goto basic_json_parser_47;
7137  goto basic_json_parser_14;
7138 basic_json_parser_49:
7139  yych = *++m_cursor;
7140  if (yych == 's') goto basic_json_parser_55;
7141  goto basic_json_parser_33;
7142 basic_json_parser_50:
7143  yych = *++m_cursor;
7144  if (yych == 'l') goto basic_json_parser_56;
7145  goto basic_json_parser_33;
7146 basic_json_parser_51:
7147  yych = *++m_cursor;
7148  if (yych == 'e') goto basic_json_parser_58;
7149  goto basic_json_parser_33;
7150 basic_json_parser_52:
7151  ++m_cursor;
7152  { return scan(); }
7153 basic_json_parser_54:
7154  ++m_cursor;
7155  if (m_limit <= m_cursor) yyfill(); // LCOV_EXCL_LINE;
7156  yych = *m_cursor;
7157  if (yych <= '@') {
7158  if (yych <= '/') goto basic_json_parser_33;
7159  if (yych <= '9') goto basic_json_parser_60;
7160  goto basic_json_parser_33;
7161  } else {
7162  if (yych <= 'F') goto basic_json_parser_60;
7163  if (yych <= '`') goto basic_json_parser_33;
7164  if (yych <= 'f') goto basic_json_parser_60;
7165  goto basic_json_parser_33;
7166  }
7167 basic_json_parser_55:
7168  yych = *++m_cursor;
7169  if (yych == 'e') goto basic_json_parser_61;
7170  goto basic_json_parser_33;
7171 basic_json_parser_56:
7172  ++m_cursor;
7173  { return token_type::literal_null; }
7174 basic_json_parser_58:
7175  ++m_cursor;
7176  { return token_type::literal_true; }
7177 basic_json_parser_60:
7178  ++m_cursor;
7179  if (m_limit <= m_cursor) yyfill(); // LCOV_EXCL_LINE;
7180  yych = *m_cursor;
7181  if (yych <= '@') {
7182  if (yych <= '/') goto basic_json_parser_33;
7183  if (yych <= '9') goto basic_json_parser_63;
7184  goto basic_json_parser_33;
7185  } else {
7186  if (yych <= 'F') goto basic_json_parser_63;
7187  if (yych <= '`') goto basic_json_parser_33;
7188  if (yych <= 'f') goto basic_json_parser_63;
7189  goto basic_json_parser_33;
7190  }
7191 basic_json_parser_61:
7192  ++m_cursor;
7193  { return token_type::literal_false; }
7194 basic_json_parser_63:
7195  ++m_cursor;
7196  if (m_limit <= m_cursor) yyfill(); // LCOV_EXCL_LINE;
7197  yych = *m_cursor;
7198  if (yych <= '@') {
7199  if (yych <= '/') goto basic_json_parser_33;
7200  if (yych <= '9') goto basic_json_parser_31;
7201  goto basic_json_parser_33;
7202  } else {
7203  if (yych <= 'F') goto basic_json_parser_31;
7204  if (yych <= '`') goto basic_json_parser_33;
7205  if (yych <= 'f') goto basic_json_parser_31;
7206  goto basic_json_parser_33;
7207  }
7208  }
7209 
7210 
7211  }
7212 
7214  void yyfill() noexcept
7215  {
7216  if (m_stream == nullptr or not * m_stream)
7217  {
7218  return;
7219  }
7220 
7221  const ssize_t offset_start = m_start - m_content;
7222  const ssize_t offset_marker = m_marker - m_start;
7223  const ssize_t offset_cursor = m_cursor - m_start;
7224 
7225  m_buffer.erase(0, static_cast<size_t>(offset_start));
7226  std::string line;
7227  assert(m_stream != nullptr);
7228  std::getline(*m_stream, line);
7229  m_buffer += "\n" + line; // add line with newline symbol
7230 
7231  m_content = reinterpret_cast<const lexer_char_t*>(m_buffer.c_str());
7232  assert(m_content != nullptr);
7233  m_start = m_content;
7234  m_marker = m_start + offset_marker;
7235  m_cursor = m_start + offset_cursor;
7236  m_limit = m_start + m_buffer.size() - 1;
7237  }
7238 
7240  string_t get_token() const noexcept
7241  {
7242  assert(m_start != nullptr);
7243  return string_t(reinterpret_cast<typename string_t::const_pointer>(m_start),
7244  static_cast<size_t>(m_cursor - m_start));
7245  }
7246 
7268  string_t get_string() const
7269  {
7270  string_t result;
7271  result.reserve(static_cast<size_t>(m_cursor - m_start - 2));
7272 
7273  // iterate the result between the quotes
7274  for (const lexer_char_t* i = m_start + 1; i < m_cursor - 1; ++i)
7275  {
7276  // process escaped characters
7277  if (*i == '\\')
7278  {
7279  // read next character
7280  ++i;
7281 
7282  switch (*i)
7283  {
7284  // the default escapes
7285  case 't':
7286  {
7287  result += "\t";
7288  break;
7289  }
7290  case 'b':
7291  {
7292  result += "\b";
7293  break;
7294  }
7295  case 'f':
7296  {
7297  result += "\f";
7298  break;
7299  }
7300  case 'n':
7301  {
7302  result += "\n";
7303  break;
7304  }
7305  case 'r':
7306  {
7307  result += "\r";
7308  break;
7309  }
7310  case '\\':
7311  {
7312  result += "\\";
7313  break;
7314  }
7315  case '/':
7316  {
7317  result += "/";
7318  break;
7319  }
7320  case '"':
7321  {
7322  result += "\"";
7323  break;
7324  }
7325 
7326  // unicode
7327  case 'u':
7328  {
7329  // get code xxxx from uxxxx
7330  auto codepoint = std::strtoul(std::string(reinterpret_cast<typename string_t::const_pointer>(i + 1),
7331  4).c_str(), nullptr, 16);
7332 
7333  // check if codepoint is a high surrogate
7334  if (codepoint >= 0xD800 and codepoint <= 0xDBFF)
7335  {
7336  // make sure there is a subsequent unicode
7337  if ((i + 6 >= m_limit) or * (i + 5) != '\\' or * (i + 6) != 'u')
7338  {
7339  throw std::invalid_argument("missing low surrogate");
7340  }
7341 
7342  // get code yyyy from uxxxx\uyyyy
7343  auto codepoint2 = std::strtoul(std::string(reinterpret_cast<typename string_t::const_pointer>
7344  (i + 7), 4).c_str(), nullptr, 16);
7345  result += to_unicode(codepoint, codepoint2);
7346  // skip the next 10 characters (xxxx\uyyyy)
7347  i += 10;
7348  }
7349  else
7350  {
7351  // add unicode character(s)
7352  result += to_unicode(codepoint);
7353  // skip the next four characters (xxxx)
7354  i += 4;
7355  }
7356  break;
7357  }
7358  }
7359  }
7360  else
7361  {
7362  // all other characters are just copied to the end of the
7363  // string
7364  result.append(1, static_cast<typename string_t::value_type>(*i));
7365  }
7366  }
7367 
7368  return result;
7369  }
7370 
7391  long double str_to_float_t(long double* /* type */, char** endptr) const
7392  {
7393  return std::strtold(reinterpret_cast<typename string_t::const_pointer>(m_start), endptr);
7394  }
7395 
7397  double str_to_float_t(double*, char** endptr) const
7398  {
7399  return std::strtod(reinterpret_cast<typename string_t::const_pointer>(m_start), endptr);
7400  }
7401 
7403  float str_to_float_t(float*, char** endptr) const
7404  {
7405  return std::strtof(reinterpret_cast<typename string_t::const_pointer>(m_start), endptr);
7406  }
7407 
7425  number_float_t get_number() const
7426  {
7427  // conversion
7428  typename string_t::value_type* endptr;
7429  assert(m_start != nullptr);
7430  number_float_t float_val = str_to_float_t(static_cast<number_float_t*>(nullptr), &endptr);
7431 
7432  // return float_val if the whole number was translated and NAN
7433  // otherwise
7434  return (reinterpret_cast<lexer_char_t*>(endptr) == m_cursor) ? float_val : NAN;
7435  }
7436 
7437  private:
7439  std::istream* m_stream = nullptr;
7441  string_t m_buffer;
7443  const lexer_char_t* m_content = nullptr;
7445  const lexer_char_t* m_start = nullptr;
7447  const lexer_char_t* m_marker = nullptr;
7449  const lexer_char_t* m_cursor = nullptr;
7451  const lexer_char_t* m_limit = nullptr;
7452  };
7453 
7459  class parser
7460  {
7461  public:
7463  parser(const string_t& s, parser_callback_t cb = nullptr)
7464  : callback(cb), m_lexer(s)
7465  {
7466  // read first token
7467  get_token();
7468  }
7469 
7471  parser(std::istream& _is, parser_callback_t cb = nullptr)
7472  : callback(cb), m_lexer(&_is)
7473  {
7474  // read first token
7475  get_token();
7476  }
7477 
7479  basic_json parse()
7480  {
7481  basic_json result = parse_internal(true);
7482 
7483  expect(lexer::token_type::end_of_input);
7484 
7485  // return parser result and replace it with null in case the
7486  // top-level value was discarded by the callback function
7487  return result.is_discarded() ? basic_json() : result;
7488  }
7489 
7490  private:
7492  basic_json parse_internal(bool keep)
7493  {
7494  auto result = basic_json(value_t::discarded);
7495 
7496  switch (last_token)
7497  {
7498  case lexer::token_type::begin_object:
7499  {
7500  if (keep and (not callback or (keep = callback(depth++, parse_event_t::object_start, result))))
7501  {
7502  // explicitly set result to object to cope with {}
7503  result.m_type = value_t::object;
7504  result.m_value = json_value(value_t::object);
7505  }
7506 
7507  // read next token
7508  get_token();
7509 
7510  // closing } -> we are done
7511  if (last_token == lexer::token_type::end_object)
7512  {
7513  get_token();
7514  if (keep and callback and not callback(--depth, parse_event_t::object_end, result))
7515  {
7516  result = basic_json(value_t::discarded);
7517  }
7518  return result;
7519  }
7520 
7521  // no comma is expected here
7522  unexpect(lexer::token_type::value_separator);
7523 
7524  // otherwise: parse key-value pairs
7525  do
7526  {
7527  // ugly, but could be fixed with loop reorganization
7528  if (last_token == lexer::token_type::value_separator)
7529  {
7530  get_token();
7531  }
7532 
7533  // store key
7534  expect(lexer::token_type::value_string);
7535  const auto key = m_lexer.get_string();
7536 
7537  bool keep_tag = false;
7538  if (keep)
7539  {
7540  if (callback)
7541  {
7542  basic_json k(key);
7543  keep_tag = callback(depth, parse_event_t::key, k);
7544  }
7545  else
7546  {
7547  keep_tag = true;
7548  }
7549  }
7550 
7551  // parse separator (:)
7552  get_token();
7553  expect(lexer::token_type::name_separator);
7554 
7555  // parse and add value
7556  get_token();
7557  auto value = parse_internal(keep);
7558  if (keep and keep_tag and not value.is_discarded())
7559  {
7560  result[key] = std::move(value);
7561  }
7562  }
7563  while (last_token == lexer::token_type::value_separator);
7564 
7565  // closing }
7566  expect(lexer::token_type::end_object);
7567  get_token();
7568  if (keep and callback and not callback(--depth, parse_event_t::object_end, result))
7569  {
7570  result = basic_json(value_t::discarded);
7571  }
7572 
7573  return result;
7574  }
7575 
7576  case lexer::token_type::begin_array:
7577  {
7578  if (keep and (not callback or (keep = callback(depth++, parse_event_t::array_start, result))))
7579  {
7580  // explicitly set result to object to cope with []
7581  result.m_type = value_t::array;
7582  result.m_value = json_value(value_t::array);
7583  }
7584 
7585  // read next token
7586  get_token();
7587 
7588  // closing ] -> we are done
7589  if (last_token == lexer::token_type::end_array)
7590  {
7591  get_token();
7592  if (callback and not callback(--depth, parse_event_t::array_end, result))
7593  {
7594  result = basic_json(value_t::discarded);
7595  }
7596  return result;
7597  }
7598 
7599  // no comma is expected here
7600  unexpect(lexer::token_type::value_separator);
7601 
7602  // otherwise: parse values
7603  do
7604  {
7605  // ugly, but could be fixed with loop reorganization
7606  if (last_token == lexer::token_type::value_separator)
7607  {
7608  get_token();
7609  }
7610 
7611  // parse value
7612  auto value = parse_internal(keep);
7613  if (keep and not value.is_discarded())
7614  {
7615  result.push_back(std::move(value));
7616  }
7617  }
7618  while (last_token == lexer::token_type::value_separator);
7619 
7620  // closing ]
7621  expect(lexer::token_type::end_array);
7622  get_token();
7623  if (keep and callback and not callback(--depth, parse_event_t::array_end, result))
7624  {
7625  result = basic_json(value_t::discarded);
7626  }
7627 
7628  return result;
7629  }
7630 
7631  case lexer::token_type::literal_null:
7632  {
7633  get_token();
7634  result.m_type = value_t::null;
7635  break;
7636  }
7637 
7638  case lexer::token_type::value_string:
7639  {
7640  const auto s = m_lexer.get_string();
7641  get_token();
7642  result = basic_json(s);
7643  break;
7644  }
7645 
7646  case lexer::token_type::literal_true:
7647  {
7648  get_token();
7649  result.m_type = value_t::boolean;
7650  result.m_value = true;
7651  break;
7652  }
7653 
7654  case lexer::token_type::literal_false:
7655  {
7656  get_token();
7657  result.m_type = value_t::boolean;
7658  result.m_value = false;
7659  break;
7660  }
7661 
7662  case lexer::token_type::value_number:
7663  {
7664  result.m_value = m_lexer.get_number();
7665 
7666  // NAN is returned if token could not be translated
7667  // completely
7668  if (std::isnan(result.m_value.number_float))
7669  {
7670  throw std::invalid_argument(std::string("parse error - ") +
7671  m_lexer.get_token() + " is not a number");
7672  }
7673 
7674  get_token();
7675 
7676  // check if conversion loses precision (special case -0.0 always loses precision)
7677  const auto int_val = static_cast<number_integer_t>(result.m_value.number_float);
7678  if (result.m_value.number_float == static_cast<number_float_t>(int_val) and
7679  result.m_value.number_integer != json_value(-0.0f).number_integer)
7680  {
7681  // we would not lose precision -> return int
7682  result.m_type = value_t::number_integer;
7683  result.m_value = int_val;
7684  }
7685  else
7686  {
7687  // we would lose precision -> return float
7688  result.m_type = value_t::number_float;
7689  }
7690  break;
7691  }
7692 
7693  default:
7694  {
7695  // the last token was unexpected
7696  unexpect(last_token);
7697  }
7698  }
7699 
7700  if (keep and callback and not callback(depth, parse_event_t::value, result))
7701  {
7702  result = basic_json(value_t::discarded);
7703  }
7704  return result;
7705  }
7706 
7708  typename lexer::token_type get_token()
7709  {
7710  last_token = m_lexer.scan();
7711  return last_token;
7712  }
7713 
7714  void expect(typename lexer::token_type t) const
7715  {
7716  if (t != last_token)
7717  {
7718  std::string error_msg = "parse error - unexpected ";
7719  error_msg += (last_token == lexer::token_type::parse_error ? ("'" + m_lexer.get_token() + "'") :
7720  lexer::token_type_name(last_token));
7721  error_msg += "; expected " + lexer::token_type_name(t);
7722  throw std::invalid_argument(error_msg);
7723  }
7724  }
7725 
7726  void unexpect(typename lexer::token_type t) const
7727  {
7728  if (t == last_token)
7729  {
7730  std::string error_msg = "parse error - unexpected ";
7731  error_msg += (last_token == lexer::token_type::parse_error ? ("'" + m_lexer.get_token() + "'") :
7732  lexer::token_type_name(last_token));
7733  throw std::invalid_argument(error_msg);
7734  }
7735  }
7736 
7737  private:
7739  int depth = 0;
7741  parser_callback_t callback;
7743  typename lexer::token_type last_token = lexer::token_type::uninitialized;
7745  lexer m_lexer;
7746  };
7747 };
7748 
7749 
7751 // presets //
7753 
7763 }
7764 
7765 
7767 // nonmember functions //
7769 
7770 // specialization of std::swap, and std::hash
7771 namespace std
7772 {
7778 template <>
7779 inline void swap(nlohmann::json& j1,
7780  nlohmann::json& j2) noexcept(
7781  is_nothrow_move_constructible<nlohmann::json>::value and
7782  is_nothrow_move_assignable<nlohmann::json>::value
7783  )
7784 {
7785  j1.swap(j2);
7786 }
7787 
7789 template <>
7790 struct hash<nlohmann::json>
7791 {
7797  std::size_t operator()(const nlohmann::json& j) const
7798  {
7799  // a naive hashing via the string representation
7800  const auto& h = hash<nlohmann::json::string_t>();
7801  return h(j.dump());
7802  }
7803 };
7804 }
7805 
7818 inline nlohmann::json operator "" _json(const char* s, std::size_t)
7819 {
7820  return nlohmann::json::parse(reinterpret_cast<const nlohmann::json::string_t::value_type*>(s));
7821 }
7822 
7823 // restore GCC/clang diagnostic settings
7824 #if defined(__clang__) || defined(__GNUC__) || defined(__GNUG__)
7825  #pragma GCC diagnostic pop
7826 #endif
7827 
7828 #endif
bool operator!=(const const_iterator &other) const
comparison: not equal
Definition: json.hpp:6191
iterator insert(const_iterator pos, basic_json &&val)
inserts element
Definition: json.hpp:4463
iterator operator++(int)
post-increment (it++)
Definition: json.hpp:6439
friend bool operator<=(const_reference lhs, const_reference rhs) noexcept
comparison: less than or equal
Definition: json.hpp:5072
bool is_array() const noexcept
return whether value is an array
Definition: json.hpp:2104
typename std::allocator_traits< allocator_type >::pointer pointer
the type of an element pointer
Definition: json.hpp:229
json_reverse_iterator operator-(difference_type i) const
subtract from iterator
Definition: json.hpp:6594
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:1519
const_reference operator[](size_type idx) const
access specified array element
Definition: json.hpp:2961
typename basic_json::const_pointer pointer
defines a pointer to the type iterated over (value_type)
Definition: json.hpp:5863
static iteration_proxy< iterator > iterator_wrapper(reference cont)
wrapper to access iterator member functions in range-based for
Definition: json.hpp:3997
const_iterator & operator--()
pre-decrement (–it)
Definition: json.hpp:6132
friend std::istream & operator>>(std::istream &i, basic_json &j)
deserialize from stream
Definition: json.hpp:5285
typename basic_json::value_type value_type
the type of the values when the iterator is dereferenced
Definition: json.hpp:5859
const_reference operator[](T *key) const
read-only access specified object element
Definition: json.hpp:3210
iterator insert(const_iterator pos, const_iterator first, const_iterator last)
inserts elements
Definition: json.hpp:4545
iterator insert(const_iterator pos, size_type cnt, const basic_json &val)
inserts elements
Definition: json.hpp:4492
json_reverse_iterator operator--(int)
post-decrement (it–)
Definition: json.hpp:6566
StringType string_t
a type for a string
Definition: json.hpp:443
void push_back(const typename object_t::value_type &val)
add an object to an object
Definition: json.hpp:4384
basic_json(boolean_t val)
create a boolean (explicit)
Definition: json.hpp:1141
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:1479
iterator & operator++()
pre-increment (++it)
Definition: json.hpp:6447
friend bool operator!=(const_reference lhs, const_reference rhs) noexcept
comparison: not equal
Definition: json.hpp:4928
ArrayType< basic_json, AllocatorType< basic_json >> array_t
a type for an array
Definition: json.hpp:396
const_iterator & operator++()
pre-increment (++it)
Definition: json.hpp:6095
difference_type operator-(const json_reverse_iterator &other) const
return difference
Definition: json.hpp:6602
basic_json<> json
default JSON class
Definition: json.hpp:7762
reference front()
access the first element
Definition: json.hpp:3328
const_iterator find(typename object_t::key_type key) const
find an element in a JSON object
Definition: json.hpp:3708
std::reverse_iterator< Base > base_iterator
shortcut to the reverse iterator adaptor
Definition: json.hpp:6538
json_reverse_iterator(const typename base_iterator::iterator_type &it)
create reverse iterator from iterator
Definition: json.hpp:6543
a class to store JSON values
Definition: json.hpp:191
json_reverse_iterator & operator--()
pre-decrement (–it)
Definition: json.hpp:6572
basic_json(const object_t &val)
create an object (explicit)
Definition: json.hpp:943
friend bool operator==(std::nullptr_t, const_reference v) noexcept
comparison: equal
Definition: json.hpp:4907
bool is_number_integer() const noexcept
return whether value is an integer number
Definition: json.hpp:2043
void push_back(basic_json &&val)
add an object to an array
Definition: json.hpp:4298
const_iterator cbegin() const
returns a const iterator to the first element
Definition: json.hpp:3808
reference operator[](T *key)
access specified object element
Definition: json.hpp:3161
iterator & operator+=(difference_type i)
add to iterator
Definition: json.hpp:6469
basic_json(const CompatibleStringType &val)
create a string (implicit)
Definition: json.hpp:1123
reference operator+=(basic_json &&val)
add an object to an array
Definition: json.hpp:4324
basic_json(size_type cnt, const basic_json &val)
construct an array with count copies of given value
Definition: json.hpp:1543
bool is_discarded() const noexcept
return whether value is discarded
Definition: json.hpp:2147
a mutable random access iterator for the basic_json class
Definition: json.hpp:6394
iterator & operator-=(difference_type i)
subtract from iterator
Definition: json.hpp:6476
static basic_json parse(std::istream &&i, parser_callback_t cb=nullptr)
deserialize from stream
Definition: json.hpp:5247
bool is_structured() const noexcept
return whether type is structured
Definition: json.hpp:1958
reference operator[](const typename object_t::key_type &key)
access specified object element
Definition: json.hpp:3002
STL namespace.
difference_type operator-(const iterator &other) const
Definition: json.hpp:6498
reference value() const
return the value of an iterator
Definition: json.hpp:6370
bool is_null() const noexcept
return whether value is null
Definition: json.hpp:1977
static iteration_proxy< const_iterator > iterator_wrapper(const_reference cont)
wrapper to access iterator member functions in range-based for
Definition: json.hpp:4005
const_iterator end() const
returns a const iterator to one past the last element
Definition: json.hpp:3843
const_iterator(const const_iterator &other) noexcept
copy constructor
Definition: json.hpp:5927
reference at(const typename object_t::key_type &key)
access specified object element with bounds checking
Definition: json.hpp:2821
object_t::key_type key() const
return the key of an object iterator
Definition: json.hpp:6355
iterator end()
returns an iterator to one past the last element
Definition: json.hpp:3833
ObjectType< StringType, basic_json, std::less< StringType >, AllocatorType< std::pair< const StringType, basic_json >>> object_t
a type for an object
Definition: json.hpp:350
const PointerType get_ptr() const noexcept
get a pointer value (implicit)
Definition: json.hpp:2598
reference operator*()
return a reference to the value pointed to by the iterator
Definition: json.hpp:6427
reverse_iterator rend()
returns an iterator to the reverse-end
Definition: json.hpp:3922
const_iterator operator-(difference_type i)
subtract from iterator
Definition: json.hpp:6287
basic_json(const CompatibleArrayType &val)
create an array (implicit)
Definition: json.hpp:1039
typename basic_json::const_reference reference
defines a reference to the type iterated over (value_type)
Definition: json.hpp:5865
const_reverse_iterator rend() const
returns a const reverse iterator to one before the first
Definition: json.hpp:3930
size_type erase(const typename object_t::key_type &key)
remove element from a JSON object given a key
Definition: json.hpp:3617
iterator begin()
returns an iterator to the first element
Definition: json.hpp:3774
const_reference at(const typename object_t::key_type &key) const
access specified object element with bounds checking
Definition: json.hpp:2869
bool empty() const noexcept
checks whether the container is empty
Definition: json.hpp:4049
reference operator+=(const basic_json &val)
add an object to an array
Definition: json.hpp:4358
AllocatorType< basic_json > allocator_type
the allocator type
Definition: json.hpp:226
bool is_object() const noexcept
return whether value is an object
Definition: json.hpp:2085
basic_json(const number_float_t val)
create a floating-point number (explicit)
Definition: json.hpp:1268
reference operator[](T *(&key)[n])
access specified object element
Definition: json.hpp:3093
iterator operator+(difference_type i)
add to iterator
Definition: json.hpp:6483
std::function< bool(int depth, parse_event_t event, basic_json &parsed)> parser_callback_t
per-element parser callback type
Definition: json.hpp:829
basic_json(const typename string_t::value_type *val)
create a string (explicit)
Definition: json.hpp:1092
iterator find(typename object_t::key_type key)
find an element in a JSON object
Definition: json.hpp:3691
basic_json(const value_t value_type)
create an empty value with a given type
Definition: json.hpp:876
friend bool operator>=(const_reference lhs, const_reference rhs) noexcept
comparison: greater than or equal
Definition: json.hpp:5116
iterator & operator--()
pre-decrement (–it)
Definition: json.hpp:6462
friend bool operator<(const_reference lhs, const_reference rhs) noexcept
comparison: less than
Definition: json.hpp:4989
pointer operator->() const
dereference the iterator
Definition: json.hpp:6052
const_reference operator[](const typename object_t::key_type &key) const
read-only access specified object element
Definition: json.hpp:3050
const_iterator cend() const
returns a const iterator to one past the last element
Definition: json.hpp:3867
typename Base::reference reference
the reference type for the pointed-to element
Definition: json.hpp:6540
static allocator_type get_allocator()
returns the allocator associated with the container
Definition: json.hpp:251
object (unordered set of name/value pairs)
ReferenceType get_ref()
get a reference value (implicit)
Definition: json.hpp:2634
reference at(size_type idx)
access specified array element with bounds checking
Definition: json.hpp:2729
json_reverse_iterator(const base_iterator &it)
create reverse iterator from base class
Definition: json.hpp:6548
reference & operator=(basic_json other) noexcept(std::is_nothrow_move_constructible< value_t >::value andstd::is_nothrow_move_assignable< value_t >::value andstd::is_nothrow_move_constructible< json_value >::value andstd::is_nothrow_move_assignable< json_value >::value)
copy assignment
Definition: json.hpp:1791
friend std::ostream & operator>>(const basic_json &j, std::ostream &o)
serialize to stream
Definition: json.hpp:5171
ValueType value(const typename object_t::key_type &key, ValueType default_value) const
access specified object element with default value
Definition: json.hpp:3277
bool is_boolean() const noexcept
return whether value is a boolean
Definition: json.hpp:1996
object_t::key_type key() const
return the key of an object iterator
Definition: json.hpp:6614
namespace for Niels Lohmann
Definition: json.hpp:88
typename basic_json::difference_type difference_type
a type to represent differences between iterators
Definition: json.hpp:5861
void swap(array_t &other)
exchanges the values
Definition: json.hpp:4672
reverse_iterator rbegin()
returns an iterator to the reverse-beginning
Definition: json.hpp:3891
reference operator+=(const typename object_t::value_type &val)
add an object to an object
Definition: json.hpp:4408
bool is_number_float() const noexcept
return whether value is a floating-point number
Definition: json.hpp:2066
basic_json(const number_integer_t val)
create an integer number (explicit)
Definition: json.hpp:1175
reference operator[](difference_type n) const
access to successor
Definition: json.hpp:6504
std::size_t size_type
a type to represent container sizes
Definition: json.hpp:223
const_reverse_iterator rbegin() const
returns a const reverse iterator to the last element
Definition: json.hpp:3899
~basic_json()
destructor
Definition: json.hpp:1817
basic_json(const basic_json &other)
copy constructor
Definition: json.hpp:1692
void swap(reference other) noexcept(std::is_nothrow_move_constructible< value_t >::value andstd::is_nothrow_move_assignable< value_t >::value andstd::is_nothrow_move_constructible< json_value >::value andstd::is_nothrow_move_assignable< json_value >::value)
exchanges the values
Definition: json.hpp:4641
const_iterator & operator=(const_iterator other) noexcept(std::is_nothrow_move_constructible< pointer >::value andstd::is_nothrow_move_assignable< pointer >::value andstd::is_nothrow_move_constructible< internal_iterator >::value andstd::is_nothrow_move_assignable< internal_iterator >::value)
copy assignment
Definition: json.hpp:5932
const_iterator operator+(difference_type i)
add to iterator
Definition: json.hpp:6279
value_t
the JSON type enumeration
Definition: json.hpp:621
const value_type & const_reference
the type of an element const reference
Definition: json.hpp:218
basic_json(const CompatibleNumberIntegerType val) noexcept
create an integer number (implicit)
Definition: json.hpp:1239
ReferenceType get_ref() const
get a reference value (implicit)
Definition: json.hpp:2649
void swap(string_t &other)
exchanges the values
Definition: json.hpp:4740
reference value() const
return the value of an iterator
Definition: json.hpp:6510
const_iterator operator--(int)
post-decrement (it–)
Definition: json.hpp:6124
ValueType get() const
get a value (explicit)
Definition: json.hpp:2499
void erase(const size_type idx)
remove element from a JSON array given an index
Definition: json.hpp:3655
void clear() noexcept
clears the contents
Definition: json.hpp:4228
pointer operator->()
dereference the iterator
Definition: json.hpp:6433
basic_json value_type
the type of elements in a basic_json container
Definition: json.hpp:213
array (ordered collection of values)
const_reference front() const
access the first element
Definition: json.hpp:3336
bool is_number() const noexcept
return whether value is a number
Definition: json.hpp:2020
bool operator>=(const const_iterator &other) const
comparison: greater than or equal
Definition: json.hpp:6239
iterator insert(const_iterator pos, std::initializer_list< basic_json > ilist)
inserts elements
Definition: json.hpp:4603
std::ptrdiff_t difference_type
a type to represent differences between iterators
Definition: json.hpp:221
const_iterator & operator+=(difference_type i)
add to iterator
Definition: json.hpp:6245
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:1387
difference_type operator-(const const_iterator &other) const
return difference
Definition: json.hpp:6295
friend bool operator==(const_reference lhs, const_reference rhs) noexcept
comparison: equal
Definition: json.hpp:4820
BooleanType boolean_t
a type for a boolean
Definition: json.hpp:469
const_reverse_iterator crend() const
returns a const reverse iterator to one before the first
Definition: json.hpp:3976
bool is_string() const noexcept
return whether value is a string
Definition: json.hpp:2123
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:3303
const_reference operator[](T *(&key)[n]) const
read-only access specified object element
Definition: json.hpp:3128
const_reverse_iterator crbegin() const
returns a const reverse iterator to the last element
Definition: json.hpp:3953
reference value() const
return the value of an iterator
Definition: json.hpp:6621
const_iterator(pointer object)
constructor for a given JSON instance
Definition: json.hpp:5873
friend bool operator<(const value_t lhs, const value_t rhs)
comparison operator for JSON types
Definition: json.hpp:4774
iterator(pointer object) noexcept
constructor for a given JSON instance
Definition: json.hpp:6405
bool operator<(const const_iterator &other) const
comparison: smaller
Definition: json.hpp:6197
string_t dump(const int indent=-1) const
serialization
Definition: json.hpp:1886
friend bool operator!=(const_reference v, std::nullptr_t) noexcept
comparison: not equal
Definition: json.hpp:4951
const_iterator & operator-=(difference_type i)
subtract from iterator
Definition: json.hpp:6273
basic_json(const int val)
create an integer number from an enum type (explicit)
Definition: json.hpp:1204
basic_json(const array_t &val)
create an array (explicit)
Definition: json.hpp:1002
static basic_json parse(const string_t &s, parser_callback_t cb=nullptr)
deserialize from string
Definition: json.hpp:5210
InteratorType erase(InteratorType first, InteratorType last)
remove elements given an iterator range
Definition: json.hpp:3534
json_reverse_iterator operator++(int)
post-increment (it++)
Definition: json.hpp:6553
PointerType get_ptr() noexcept
get a pointer value (implicit)
Definition: json.hpp:2583
const_iterator(const iterator &other)
copy constructor given a nonconst iterator
Definition: json.hpp:5900
friend bool operator!=(std::nullptr_t, const_reference v) noexcept
comparison: not equal
Definition: json.hpp:4960
InteratorType erase(InteratorType pos)
remove element given an iterator
Definition: json.hpp:3429
bool operator<=(const const_iterator &other) const
comparison: less than or equal
Definition: json.hpp:6227
basic_json(const CompatibleNumberFloatType val) noexcept
create an floating-point number (implicit)
Definition: json.hpp:1314
reference back()
access the last element
Definition: json.hpp:3362
const_iterator operator++(int)
post-increment (it++)
Definition: json.hpp:6087
typename std::allocator_traits< allocator_type >::const_pointer const_pointer
the type of an element const pointer
Definition: json.hpp:231
basic_json(const string_t &val)
create a string (explicit)
Definition: json.hpp:1068
iterator(const iterator &other) noexcept
copy constructor
Definition: json.hpp:6410
const_reference back() const
access the last element
Definition: json.hpp:3372
basic_json(InputIT first, InputIT last)
construct a JSON container given an iterator range
Definition: json.hpp:1589
static basic_json parse(std::istream &i, parser_callback_t cb=nullptr)
deserialize from stream
Definition: json.hpp:5239
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:3739
void push_back(const basic_json &val)
add an object to an array
Definition: json.hpp:4334
bool operator==(const const_iterator &other) const
comparison: equal
Definition: json.hpp:6161
json_reverse_iterator & operator++()
pre-increment (++it)
Definition: json.hpp:6559
basic_json(std::nullptr_t) noexcept
create a null object (explicitly)
Definition: json.hpp:920
bool operator>(const const_iterator &other) const
comparison: greater than
Definition: json.hpp:6233
friend bool operator>(const_reference lhs, const_reference rhs) noexcept
comparison: greater than
Definition: json.hpp:5094
basic_json(basic_json &&other) noexcept
move constructor
Definition: json.hpp:1761
const_iterator begin() const
returns a const iterator to the first element
Definition: json.hpp:3784
bool is_primitive() const noexcept
return whether type is primitive
Definition: json.hpp:1938
const_reference at(size_type idx) const
access specified array element with bounds checking
Definition: json.hpp:2773
json_reverse_iterator & operator+=(difference_type i)
add to iterator
Definition: json.hpp:6579
size_type max_size() const noexcept
returns the maximum possible number of elements
Definition: json.hpp:4169
a const random access iterator for the basic_json class
Definition: json.hpp:5852
a template for a reverse iterator class
Definition: json.hpp:234
void swap(object_t &other)
exchanges the values
Definition: json.hpp:4706
std::bidirectional_iterator_tag iterator_category
the category of the iterator
Definition: json.hpp:5867
iterator insert(const_iterator pos, const basic_json &val)
inserts element
Definition: json.hpp:4436
friend bool operator==(const_reference v, std::nullptr_t) noexcept
comparison: equal
Definition: json.hpp:4898
reference operator[](difference_type n) const
access to successor
Definition: json.hpp:6608
NumberIntegerType number_integer_t
a type for a number (integer)
Definition: json.hpp:537
reference operator[](difference_type n) const
access to successor
Definition: json.hpp:6319
reference operator*() const
return a reference to the value pointed to by the iterator
Definition: json.hpp:6012
value_type & reference
the type of an element reference
Definition: json.hpp:216
friend std::istream & operator<<(basic_json &j, std::istream &i)
deserialize from stream
Definition: json.hpp:5275
NumberFloatType number_float_t
a type for a number (floating-point)
Definition: json.hpp:602
std::size_t operator()(const nlohmann::json &j) const
return a hash value for a JSON object
Definition: json.hpp:7797
iterator & operator=(iterator other) noexcept(std::is_nothrow_move_constructible< pointer >::value andstd::is_nothrow_move_assignable< pointer >::value andstd::is_nothrow_move_constructible< internal_iterator >::value andstd::is_nothrow_move_assignable< internal_iterator >::value)
copy assignment
Definition: json.hpp:6415
friend std::ostream & operator<<(std::ostream &o, const basic_json &j)
serialize to stream
Definition: json.hpp:5153
value_t type() const noexcept
return the type of the JSON value (explicit)
Definition: json.hpp:1917
basic_json(const CompatibleObjectType &val)
create an object (implicit)
Definition: json.hpp:975
reference operator[](size_type idx)
access specified array element
Definition: json.hpp:2916
iterator operator--(int)
post-decrement (it–)
Definition: json.hpp:6454
json_reverse_iterator operator+(difference_type i) const
add to iterator
Definition: json.hpp:6586
parse_event_t
JSON callback events.
Definition: json.hpp:764
iterator operator-(difference_type i)
subtract from iterator
Definition: json.hpp:6491
size_type size() const noexcept
returns the number of elements
Definition: json.hpp:4107