JSON for Modern C++  1.0.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 <cstdio>
47 #include <functional>
48 #include <initializer_list>
49 #include <iomanip>
50 #include <iostream>
51 #include <iterator>
52 #include <limits>
53 #include <map>
54 #include <memory>
55 #include <sstream>
56 #include <string>
57 #include <type_traits>
58 #include <utility>
59 #include <vector>
60 
61 // enable ssize_t on MinGW
62 #ifdef __GNUC__
63  #ifdef __MINGW32__
64  #include <sys/types.h>
65  #endif
66 #endif
67 
68 // enable ssize_t for MSVC
69 #ifdef _MSC_VER
70  #include <basetsd.h>
71  using ssize_t = SSIZE_T;
72 #endif
73 
79 namespace nlohmann
80 {
81 
82 
87 namespace
88 {
93 template<typename T>
94 struct has_mapped_type
95 {
96  private:
97  template<typename C> static char test(typename C::mapped_type*);
98  template<typename C> static char (&test(...))[2];
99  public:
100  static constexpr bool value = sizeof(test<T>(0)) == 1;
101 };
102 
104 template<typename T>
105 static bool approx(const T a, const T b)
106 {
107  return not (a > b or a < b);
108 }
109 }
110 
179 template <
180  template<typename U, typename V, typename... Args> class ObjectType = std::map,
181  template<typename U, typename... Args> class ArrayType = std::vector,
182  class StringType = std::string,
183  class BooleanType = bool,
184  class NumberIntegerType = int64_t,
185  class NumberFloatType = double,
186  template<typename U> class AllocatorType = std::allocator
187  >
189 {
190  private:
192  using basic_json_t = basic_json<ObjectType,
193  ArrayType,
194  StringType,
195  BooleanType,
196  NumberIntegerType,
197  NumberFloatType,
198  AllocatorType>;
199 
200  public:
201 
203  // container types //
205 
208 
211 
214 
216  using const_reference = const value_type&;
217 
219  using difference_type = std::ptrdiff_t;
220 
222  using size_type = std::size_t;
223 
225  using allocator_type = AllocatorType<basic_json>;
226 
228  using pointer = typename std::allocator_traits<allocator_type>::pointer;
230  using const_pointer = typename std::allocator_traits<allocator_type>::const_pointer;
231 
232  // forward declaration
233  template<typename Base> class json_reverse_iterator;
234 
236  class iterator;
238  class const_iterator;
243 
245 
246 
251  {
252  return allocator_type();
253  }
254 
255 
257  // JSON value data types //
259 
262 
337  using object_t = ObjectType<StringType,
338  basic_json,
339  std::less<StringType>,
340  AllocatorType<std::pair<const StringType,
341  basic_json>>>;
342 
387  using array_t = ArrayType<basic_json, AllocatorType<basic_json>>;
388 
434  using string_t = StringType;
435 
460  using boolean_t = BooleanType;
461 
528  using number_integer_t = NumberIntegerType;
529 
593  using number_float_t = NumberFloatType;
594 
596 
597 
599  // JSON type enumeration //
601 
612  enum class value_t : uint8_t
613  {
614  null,
615  object,
616  array,
617  string,
618  boolean,
619  number_integer,
620  number_float,
621  discarded
622  };
623 
624 
625  private:
627  template<typename T, typename... Args>
628  static T* create(Args&& ... args)
629  {
630  AllocatorType<T> alloc;
631  auto deleter = [&](T * object)
632  {
633  alloc.deallocate(object, 1);
634  };
635  std::unique_ptr<T, decltype(deleter)> object(alloc.allocate(1), deleter);
636  alloc.construct(object.get(), std::forward<Args>(args)...);
637  return object.release();
638  }
639 
641  // JSON value storage //
643 
651  union json_value
652  {
654  object_t* object;
656  array_t* array;
658  string_t* string;
660  boolean_t boolean;
662  number_integer_t number_integer;
664  number_float_t number_float;
665 
667  json_value() noexcept = default;
669  json_value(boolean_t v) noexcept : boolean(v) {}
671  json_value(number_integer_t v) noexcept : number_integer(v) {}
673  json_value(number_float_t v) noexcept : number_float(v) {}
675  json_value(value_t t)
676  {
677  switch (t)
678  {
679  case value_t::object:
680  {
681  object = create<object_t>();
682  break;
683  }
684 
685  case value_t::array:
686  {
687  array = create<array_t>();
688  break;
689  }
690 
691  case value_t::string:
692  {
693  string = create<string_t>("");
694  break;
695  }
696 
697  case value_t::boolean:
698  {
699  boolean = boolean_t(false);
700  break;
701  }
702 
703  case value_t::number_integer:
704  {
705  number_integer = number_integer_t(0);
706  break;
707  }
708 
709  case value_t::number_float:
710  {
711  number_float = number_float_t(0.0);
712  break;
713  }
714 
715  default:
716  {
717  break;
718  }
719  }
720  }
721 
723  json_value(const string_t& value)
724  {
725  string = create<string_t>(value);
726  }
727 
729  json_value(const object_t& value)
730  {
731  object = create<object_t>(value);
732  }
733 
735  json_value(const array_t& value)
736  {
737  array = create<array_t>(value);
738  }
739  };
740 
741 
742  public:
744  // JSON parser callback //
746 
755  enum class parse_event_t : uint8_t
756  {
758  object_start,
760  object_end,
762  array_start,
764  array_end,
766  key,
768  value
769  };
770 
820  using parser_callback_t = std::function<bool(int depth, parse_event_t event, basic_json& parsed)>;
821 
822 
824  // constructors //
826 
829 
868  : m_type(value_type), m_value(value_type)
869  {}
870 
890  basic_json() noexcept = default;
891 
911  basic_json(std::nullptr_t) noexcept
912  : basic_json(value_t::null)
913  {}
914 
934  basic_json(const object_t& val)
935  : m_type(value_t::object), m_value(val)
936  {}
937 
961  template <class CompatibleObjectType, typename
962  std::enable_if<
963  std::is_constructible<typename object_t::key_type, typename CompatibleObjectType::key_type>::value and
964  std::is_constructible<basic_json, typename CompatibleObjectType::mapped_type>::value, int>::type
965  = 0>
966  basic_json(const CompatibleObjectType& val)
967  : m_type(value_t::object)
968  {
969  using std::begin;
970  using std::end;
971  m_value.object = create<object_t>(begin(val), end(val));
972  }
973 
993  basic_json(const array_t& val)
994  : m_type(value_t::array), m_value(val)
995  {}
996 
1020  template <class CompatibleArrayType, typename
1021  std::enable_if<
1022  not std::is_same<CompatibleArrayType, typename basic_json_t::iterator>::value and
1023  not std::is_same<CompatibleArrayType, typename basic_json_t::const_iterator>::value and
1024  not std::is_same<CompatibleArrayType, typename basic_json_t::reverse_iterator>::value and
1025  not std::is_same<CompatibleArrayType, typename basic_json_t::const_reverse_iterator>::value and
1026  not std::is_same<CompatibleArrayType, typename array_t::iterator>::value and
1027  not std::is_same<CompatibleArrayType, typename array_t::const_iterator>::value and
1028  std::is_constructible<basic_json, typename CompatibleArrayType::value_type>::value, int>::type
1029  = 0>
1030  basic_json(const CompatibleArrayType& val)
1031  : m_type(value_t::array)
1032  {
1033  using std::begin;
1034  using std::end;
1035  m_value.array = create<array_t>(begin(val), end(val));
1036  }
1037 
1059  basic_json(const string_t& val)
1060  : m_type(value_t::string), m_value(val)
1061  {}
1062 
1083  basic_json(const typename string_t::value_type* val)
1084  : basic_json(string_t(val))
1085  {}
1086 
1110  template <class CompatibleStringType, typename
1111  std::enable_if<
1112  std::is_constructible<string_t, CompatibleStringType>::value, int>::type
1113  = 0>
1114  basic_json(const CompatibleStringType& val)
1115  : basic_json(string_t(val))
1116  {}
1117 
1133  : m_type(value_t::boolean), m_value(val)
1134  {}
1135 
1161  template<typename T,
1162  typename std::enable_if<
1163  not (std::is_same<T, int>::value)
1164  and std::is_same<T, number_integer_t>::value
1165  , int>::type = 0>
1167  : m_type(value_t::number_integer), m_value(val)
1168  {}
1169 
1195  basic_json(const int val)
1196  : m_type(value_t::number_integer),
1197  m_value(static_cast<number_integer_t>(val))
1198  {}
1199 
1225  template<typename CompatibleNumberIntegerType, typename
1226  std::enable_if<
1227  std::is_constructible<number_integer_t, CompatibleNumberIntegerType>::value and
1228  std::numeric_limits<CompatibleNumberIntegerType>::is_integer, CompatibleNumberIntegerType>::type
1229  = 0>
1230  basic_json(const CompatibleNumberIntegerType val) noexcept
1231  : m_type(value_t::number_integer),
1232  m_value(static_cast<number_integer_t>(val))
1233  {}
1234 
1260  : m_type(value_t::number_float), m_value(val)
1261  {
1262  // replace infinity and NAN by null
1263  if (not std::isfinite(val))
1264  {
1265  m_type = value_t::null;
1266  m_value = json_value();
1267  }
1268  }
1269 
1300  template<typename CompatibleNumberFloatType, typename = typename
1301  std::enable_if<
1302  std::is_constructible<number_float_t, CompatibleNumberFloatType>::value and
1303  std::is_floating_point<CompatibleNumberFloatType>::value>::type
1304  >
1305  basic_json(const CompatibleNumberFloatType val) noexcept
1306  : basic_json(number_float_t(val))
1307  {}
1308 
1378  basic_json(std::initializer_list<basic_json> init,
1379  bool type_deduction = true,
1380  value_t manual_type = value_t::array)
1381  {
1382  // the initializer list could describe an object
1383  bool is_an_object = true;
1384 
1385  // check if each element is an array with two elements whose first
1386  // element is a string
1387  for (const auto& element : init)
1388  {
1389  if (not element.is_array() or element.size() != 2
1390  or not element[0].is_string())
1391  {
1392  // we found an element that makes it impossible to use the
1393  // initializer list as object
1394  is_an_object = false;
1395  break;
1396  }
1397  }
1398 
1399  // adjust type if type deduction is not wanted
1400  if (not type_deduction)
1401  {
1402  // if array is wanted, do not create an object though possible
1403  if (manual_type == value_t::array)
1404  {
1405  is_an_object = false;
1406  }
1407 
1408  // if object is wanted but impossible, throw an exception
1409  if (manual_type == value_t::object and not is_an_object)
1410  {
1411  throw std::domain_error("cannot create object from initializer list");
1412  }
1413  }
1414 
1415  if (is_an_object)
1416  {
1417  // the initializer list is a list of pairs -> create object
1418  m_type = value_t::object;
1419  m_value = value_t::object;
1420 
1421  assert(m_value.object != nullptr);
1422 
1423  for (auto& element : init)
1424  {
1425  m_value.object->emplace(std::move(*(element[0].m_value.string)), std::move(element[1]));
1426  }
1427  }
1428  else
1429  {
1430  // the initializer list describes an array -> create array
1431  m_type = value_t::array;
1432  m_value.array = create<array_t>(std::move(init));
1433  }
1434  }
1435 
1470  static basic_json array(std::initializer_list<basic_json> init =
1471  std::initializer_list<basic_json>())
1472  {
1473  return basic_json(init, false, value_t::array);
1474  }
1475 
1510  static basic_json object(std::initializer_list<basic_json> init =
1511  std::initializer_list<basic_json>())
1512  {
1513  return basic_json(init, false, value_t::object);
1514  }
1515 
1534  basic_json(size_type cnt, const basic_json& val)
1535  : m_type(value_t::array)
1536  {
1537  m_value.array = create<array_t>(cnt, val);
1538  }
1539 
1574  template <class InputIT, typename
1575  std::enable_if<
1576  std::is_same<InputIT, typename basic_json_t::iterator>::value or
1577  std::is_same<InputIT, typename basic_json_t::const_iterator>::value
1578  , int>::type
1579  = 0>
1580  basic_json(InputIT first, InputIT last) : m_type(first.m_object->m_type)
1581  {
1582  // make sure iterator fits the current value
1583  if (first.m_object != last.m_object)
1584  {
1585  throw std::domain_error("iterators are not compatible");
1586  }
1587 
1588  // check if iterator range is complete for primitive values
1589  switch (m_type)
1590  {
1591  case value_t::boolean:
1592  case value_t::number_float:
1593  case value_t::number_integer:
1594  case value_t::string:
1595  {
1596  if (not first.m_it.primitive_iterator.is_begin() or not last.m_it.primitive_iterator.is_end())
1597  {
1598  throw std::out_of_range("iterators out of range");
1599  }
1600  break;
1601  }
1602 
1603  default:
1604  {
1605  break;
1606  }
1607  }
1608 
1609  switch (m_type)
1610  {
1611  case value_t::number_integer:
1612  {
1613  assert(first.m_object != nullptr);
1614  m_value.number_integer = first.m_object->m_value.number_integer;
1615  break;
1616  }
1617 
1618  case value_t::number_float:
1619  {
1620  assert(first.m_object != nullptr);
1621  m_value.number_float = first.m_object->m_value.number_float;
1622  break;
1623  }
1624 
1625  case value_t::boolean:
1626  {
1627  assert(first.m_object != nullptr);
1628  m_value.boolean = first.m_object->m_value.boolean;
1629  break;
1630  }
1631 
1632  case value_t::string:
1633  {
1634  assert(first.m_object != nullptr);
1635  m_value = *first.m_object->m_value.string;
1636  break;
1637  }
1638 
1639  case value_t::object:
1640  {
1641  m_value.object = create<object_t>(first.m_it.object_iterator, last.m_it.object_iterator);
1642  break;
1643  }
1644 
1645  case value_t::array:
1646  {
1647  m_value.array = create<array_t>(first.m_it.array_iterator, last.m_it.array_iterator);
1648  break;
1649  }
1650 
1651  default:
1652  {
1653  assert(first.m_object != nullptr);
1654  throw std::domain_error("cannot use construct with iterators from " + first.m_object->type_name());
1655  }
1656  }
1657  }
1658 
1660  // other constructors and destructor //
1662 
1683  basic_json(const basic_json& other)
1684  : m_type(other.m_type)
1685  {
1686  switch (m_type)
1687  {
1688  case value_t::object:
1689  {
1690  assert(other.m_value.object != nullptr);
1691  m_value = *other.m_value.object;
1692  break;
1693  }
1694 
1695  case value_t::array:
1696  {
1697  assert(other.m_value.array != nullptr);
1698  m_value = *other.m_value.array;
1699  break;
1700  }
1701 
1702  case value_t::string:
1703  {
1704  assert(other.m_value.string != nullptr);
1705  m_value = *other.m_value.string;
1706  break;
1707  }
1708 
1709  case value_t::boolean:
1710  {
1711  m_value = other.m_value.boolean;
1712  break;
1713  }
1714 
1715  case value_t::number_integer:
1716  {
1717  m_value = other.m_value.number_integer;
1718  break;
1719  }
1720 
1721  case value_t::number_float:
1722  {
1723  m_value = other.m_value.number_float;
1724  break;
1725  }
1726 
1727  default:
1728  {
1729  break;
1730  }
1731  }
1732  }
1733 
1752  basic_json(basic_json&& other) noexcept
1753  : m_type(std::move(other.m_type)),
1754  m_value(std::move(other.m_value))
1755  {
1756  // invalidate payload
1757  other.m_type = value_t::null;
1758  other.m_value = {};
1759  }
1760 
1782  reference& operator=(basic_json other) noexcept (
1783  std::is_nothrow_move_constructible<value_t>::value and
1784  std::is_nothrow_move_assignable<value_t>::value and
1785  std::is_nothrow_move_constructible<json_value>::value and
1786  std::is_nothrow_move_assignable<json_value>::value
1787  )
1788  {
1789  using std::swap;
1790  swap(m_type, other.m_type);
1791  swap(m_value, other.m_value);
1792  return *this;
1793  }
1794 
1809  {
1810  switch (m_type)
1811  {
1812  case value_t::object:
1813  {
1814  AllocatorType<object_t> alloc;
1815  alloc.destroy(m_value.object);
1816  alloc.deallocate(m_value.object, 1);
1817  break;
1818  }
1819 
1820  case value_t::array:
1821  {
1822  AllocatorType<array_t> alloc;
1823  alloc.destroy(m_value.array);
1824  alloc.deallocate(m_value.array, 1);
1825  break;
1826  }
1827 
1828  case value_t::string:
1829  {
1830  AllocatorType<string_t> alloc;
1831  alloc.destroy(m_value.string);
1832  alloc.deallocate(m_value.string, 1);
1833  break;
1834  }
1835 
1836  default:
1837  {
1838  // all other types need no specific destructor
1839  break;
1840  }
1841  }
1842  }
1843 
1845 
1846  public:
1848  // object inspection //
1850 
1853 
1877  string_t dump(const int indent = -1) const
1878  {
1879  std::stringstream ss;
1880 
1881  if (indent >= 0)
1882  {
1883  dump(ss, true, static_cast<unsigned int>(indent));
1884  }
1885  else
1886  {
1887  dump(ss, false, 0);
1888  }
1889 
1890  return ss.str();
1891  }
1892 
1908  value_t type() const noexcept
1909  {
1910  return m_type;
1911  }
1912 
1929  bool is_primitive() const noexcept
1930  {
1931  return is_null() or is_string() or is_boolean() or is_number();
1932  }
1933 
1949  bool is_structured() const noexcept
1950  {
1951  return is_array() or is_object();
1952  }
1953 
1968  bool is_null() const noexcept
1969  {
1970  return m_type == value_t::null;
1971  }
1972 
1987  bool is_boolean() const noexcept
1988  {
1989  return m_type == value_t::boolean;
1990  }
1991 
2011  bool is_number() const noexcept
2012  {
2013  return is_number_integer() or is_number_float();
2014  }
2015 
2034  bool is_number_integer() const noexcept
2035  {
2036  return m_type == value_t::number_integer;
2037  }
2038 
2057  bool is_number_float() const noexcept
2058  {
2059  return m_type == value_t::number_float;
2060  }
2061 
2076  bool is_object() const noexcept
2077  {
2078  return m_type == value_t::object;
2079  }
2080 
2095  bool is_array() const noexcept
2096  {
2097  return m_type == value_t::array;
2098  }
2099 
2114  bool is_string() const noexcept
2115  {
2116  return m_type == value_t::string;
2117  }
2118 
2138  bool is_discarded() const noexcept
2139  {
2140  return m_type == value_t::discarded;
2141  }
2142 
2158  operator value_t() const noexcept
2159  {
2160  return m_type;
2161  }
2162 
2164 
2165  private:
2167  // value access //
2169 
2171  template <class T, typename
2172  std::enable_if<
2173  std::is_convertible<typename object_t::key_type, typename T::key_type>::value and
2174  std::is_convertible<basic_json_t, typename T::mapped_type>::value
2175  , int>::type = 0>
2176  T get_impl(T*) const
2177  {
2178  if (is_object())
2179  {
2180  assert(m_value.object != nullptr);
2181  return T(m_value.object->begin(), m_value.object->end());
2182  }
2183  else
2184  {
2185  throw std::domain_error("type must be object, but is " + type_name());
2186  }
2187  }
2188 
2190  object_t get_impl(object_t*) const
2191  {
2192  if (is_object())
2193  {
2194  assert(m_value.object != nullptr);
2195  return *(m_value.object);
2196  }
2197  else
2198  {
2199  throw std::domain_error("type must be object, but is " + type_name());
2200  }
2201  }
2202 
2204  template <class T, typename
2205  std::enable_if<
2206  std::is_convertible<basic_json_t, typename T::value_type>::value and
2207  not std::is_same<basic_json_t, typename T::value_type>::value and
2208  not std::is_arithmetic<T>::value and
2209  not std::is_convertible<std::string, T>::value and
2210  not has_mapped_type<T>::value
2211  , int>::type = 0>
2212  T get_impl(T*) const
2213  {
2214  if (is_array())
2215  {
2216  T to_vector;
2217  assert(m_value.array != nullptr);
2218  std::transform(m_value.array->begin(), m_value.array->end(),
2219  std::inserter(to_vector, to_vector.end()), [](basic_json i)
2220  {
2221  return i.get<typename T::value_type>();
2222  });
2223  return to_vector;
2224  }
2225  else
2226  {
2227  throw std::domain_error("type must be array, but is " + type_name());
2228  }
2229  }
2230 
2232  template <class T, typename
2233  std::enable_if<
2234  std::is_convertible<basic_json_t, T>::value and
2235  not std::is_same<basic_json_t, T>::value
2236  , int>::type = 0>
2237  std::vector<T> get_impl(std::vector<T>*) const
2238  {
2239  if (is_array())
2240  {
2241  std::vector<T> to_vector;
2242  assert(m_value.array != nullptr);
2243  to_vector.reserve(m_value.array->size());
2244  std::transform(m_value.array->begin(), m_value.array->end(),
2245  std::inserter(to_vector, to_vector.end()), [](basic_json i)
2246  {
2247  return i.get<T>();
2248  });
2249  return to_vector;
2250  }
2251  else
2252  {
2253  throw std::domain_error("type must be array, but is " + type_name());
2254  }
2255  }
2256 
2258  template <class T, typename
2259  std::enable_if<
2260  std::is_same<basic_json, typename T::value_type>::value and
2261  not has_mapped_type<T>::value
2262  , int>::type = 0>
2263  T get_impl(T*) const
2264  {
2265  if (is_array())
2266  {
2267  assert(m_value.array != nullptr);
2268  return T(m_value.array->begin(), m_value.array->end());
2269  }
2270  else
2271  {
2272  throw std::domain_error("type must be array, but is " + type_name());
2273  }
2274  }
2275 
2277  array_t get_impl(array_t*) const
2278  {
2279  if (is_array())
2280  {
2281  assert(m_value.array != nullptr);
2282  return *(m_value.array);
2283  }
2284  else
2285  {
2286  throw std::domain_error("type must be array, but is " + type_name());
2287  }
2288  }
2289 
2291  template <typename T, typename
2292  std::enable_if<
2293  std::is_convertible<string_t, T>::value
2294  , int>::type = 0>
2295  T get_impl(T*) const
2296  {
2297  if (is_string())
2298  {
2299  assert(m_value.string != nullptr);
2300  return *m_value.string;
2301  }
2302  else
2303  {
2304  throw std::domain_error("type must be string, but is " + type_name());
2305  }
2306  }
2307 
2309  template<typename T, typename
2310  std::enable_if<
2311  std::is_arithmetic<T>::value
2312  , int>::type = 0>
2313  T get_impl(T*) const
2314  {
2315  switch (m_type)
2316  {
2317  case value_t::number_integer:
2318  {
2319  return static_cast<T>(m_value.number_integer);
2320  }
2321 
2322  case value_t::number_float:
2323  {
2324  return static_cast<T>(m_value.number_float);
2325  }
2326 
2327  default:
2328  {
2329  throw std::domain_error("type must be number, but is " + type_name());
2330  }
2331  }
2332  }
2333 
2335  boolean_t get_impl(boolean_t*) const
2336  {
2337  if (is_boolean())
2338  {
2339  return m_value.boolean;
2340  }
2341  else
2342  {
2343  throw std::domain_error("type must be boolean, but is " + type_name());
2344  }
2345  }
2346 
2348  object_t* get_impl_ptr(object_t*) noexcept
2349  {
2350  return is_object() ? m_value.object : nullptr;
2351  }
2352 
2354  const object_t* get_impl_ptr(const object_t*) const noexcept
2355  {
2356  return is_object() ? m_value.object : nullptr;
2357  }
2358 
2360  array_t* get_impl_ptr(array_t*) noexcept
2361  {
2362  return is_array() ? m_value.array : nullptr;
2363  }
2364 
2366  const array_t* get_impl_ptr(const array_t*) const noexcept
2367  {
2368  return is_array() ? m_value.array : nullptr;
2369  }
2370 
2372  string_t* get_impl_ptr(string_t*) noexcept
2373  {
2374  return is_string() ? m_value.string : nullptr;
2375  }
2376 
2378  const string_t* get_impl_ptr(const string_t*) const noexcept
2379  {
2380  return is_string() ? m_value.string : nullptr;
2381  }
2382 
2384  boolean_t* get_impl_ptr(boolean_t*) noexcept
2385  {
2386  return is_boolean() ? &m_value.boolean : nullptr;
2387  }
2388 
2390  const boolean_t* get_impl_ptr(const boolean_t*) const noexcept
2391  {
2392  return is_boolean() ? &m_value.boolean : nullptr;
2393  }
2394 
2396  number_integer_t* get_impl_ptr(number_integer_t*) noexcept
2397  {
2398  return is_number_integer() ? &m_value.number_integer : nullptr;
2399  }
2400 
2402  const number_integer_t* get_impl_ptr(const number_integer_t*) const noexcept
2403  {
2404  return is_number_integer() ? &m_value.number_integer : nullptr;
2405  }
2406 
2408  number_float_t* get_impl_ptr(number_float_t*) noexcept
2409  {
2410  return is_number_float() ? &m_value.number_float : nullptr;
2411  }
2412 
2414  const number_float_t* get_impl_ptr(const number_float_t*) const noexcept
2415  {
2416  return is_number_float() ? &m_value.number_float : nullptr;
2417  }
2418 
2419  public:
2420 
2423 
2457  template<typename ValueType, typename
2458  std::enable_if<
2459  not std::is_pointer<ValueType>::value
2460  , int>::type = 0>
2461  ValueType get() const
2462  {
2463  return get_impl(static_cast<ValueType*>(nullptr));
2464  }
2465 
2492  template<typename PointerType, typename
2493  std::enable_if<
2494  std::is_pointer<PointerType>::value
2495  , int>::type = 0>
2496  PointerType get() noexcept
2497  {
2498  // delegate the call to get_ptr
2499  return get_ptr<PointerType>();
2500  }
2501 
2506  template<typename PointerType, typename
2507  std::enable_if<
2508  std::is_pointer<PointerType>::value
2509  , int>::type = 0>
2510  const PointerType get() const noexcept
2511  {
2512  // delegate the call to get_ptr
2513  return get_ptr<PointerType>();
2514  }
2515 
2541  template<typename PointerType, typename
2542  std::enable_if<
2543  std::is_pointer<PointerType>::value
2544  , int>::type = 0>
2545  PointerType get_ptr() noexcept
2546  {
2547  // delegate the call to get_impl_ptr<>()
2548  return get_impl_ptr(static_cast<PointerType>(nullptr));
2549  }
2550 
2555  template<typename PointerType, typename
2556  std::enable_if<
2557  std::is_pointer<PointerType>::value
2558  and std::is_const<typename std::remove_pointer<PointerType>::type>::value
2559  , int>::type = 0>
2560  const PointerType get_ptr() const noexcept
2561  {
2562  // delegate the call to get_impl_ptr<>() const
2563  return get_impl_ptr(static_cast<const PointerType>(nullptr));
2564  }
2565 
2594  template<typename ValueType, typename
2595  std::enable_if<
2596  not std::is_pointer<ValueType>::value
2597  and not std::is_same<ValueType, typename string_t::value_type>::value
2598  and not std::is_same<ValueType, std::initializer_list<typename string_t::value_type>>::value
2599  , int>::type = 0>
2600  operator ValueType() const
2601  {
2602  // delegate the call to get<>() const
2603  return get<ValueType>();
2604  }
2605 
2607 
2608 
2610  // element access //
2612 
2615 
2639  {
2640  // at only works for arrays
2641  if (is_array())
2642  {
2643  try
2644  {
2645  assert(m_value.array != nullptr);
2646  return m_value.array->at(idx);
2647  }
2648  catch (std::out_of_range& e)
2649  {
2650  // create better exception explanation
2651  throw std::out_of_range("array index " + std::to_string(idx) + " is out of range");
2652  }
2653  }
2654  else
2655  {
2656  throw std::domain_error("cannot use at() with " + type_name());
2657  }
2658  }
2659 
2683  {
2684  // at only works for arrays
2685  if (is_array())
2686  {
2687  try
2688  {
2689  assert(m_value.array != nullptr);
2690  return m_value.array->at(idx);
2691  }
2692  catch (std::out_of_range& e)
2693  {
2694  // create better exception explanation
2695  throw std::out_of_range("array index " + std::to_string(idx) + " is out of range");
2696  }
2697  }
2698  else
2699  {
2700  throw std::domain_error("cannot use at() with " + type_name());
2701  }
2702  }
2703 
2730  reference at(const typename object_t::key_type& key)
2731  {
2732  // at only works for objects
2733  if (is_object())
2734  {
2735  try
2736  {
2737  assert(m_value.object != nullptr);
2738  return m_value.object->at(key);
2739  }
2740  catch (std::out_of_range& e)
2741  {
2742  // create better exception explanation
2743  throw std::out_of_range("key '" + key + "' not found");
2744  }
2745  }
2746  else
2747  {
2748  throw std::domain_error("cannot use at() with " + type_name());
2749  }
2750  }
2751 
2778  const_reference at(const typename object_t::key_type& key) const
2779  {
2780  // at only works for objects
2781  if (is_object())
2782  {
2783  try
2784  {
2785  assert(m_value.object != nullptr);
2786  return m_value.object->at(key);
2787  }
2788  catch (std::out_of_range& e)
2789  {
2790  // create better exception explanation
2791  throw std::out_of_range("key '" + key + "' not found");
2792  }
2793  }
2794  else
2795  {
2796  throw std::domain_error("cannot use at() with " + type_name());
2797  }
2798  }
2799 
2826  {
2827  // implicitly convert null to object
2828  if (is_null())
2829  {
2830  m_type = value_t::array;
2831  m_value.array = create<array_t>();
2832  }
2833 
2834  // [] only works for arrays
2835  if (is_array())
2836  {
2837  assert(m_value.array != nullptr);
2838  for (size_t i = m_value.array->size(); i <= idx; ++i)
2839  {
2840  m_value.array->push_back(basic_json());
2841  }
2842 
2843  return m_value.array->operator[](idx);
2844  }
2845  else
2846  {
2847  throw std::domain_error("cannot use operator[] with " + type_name());
2848  }
2849  }
2850 
2871  {
2872  // at only works for arrays
2873  if (is_array())
2874  {
2875  assert(m_value.array != nullptr);
2876  return m_value.array->operator[](idx);
2877  }
2878  else
2879  {
2880  throw std::domain_error("cannot use operator[] with " + type_name());
2881  }
2882  }
2883 
2911  reference operator[](const typename object_t::key_type& key)
2912  {
2913  // implicitly convert null to object
2914  if (is_null())
2915  {
2916  m_type = value_t::object;
2917  m_value.object = create<object_t>();
2918  }
2919 
2920  // [] only works for objects
2921  if (is_object())
2922  {
2923  assert(m_value.object != nullptr);
2924  return m_value.object->operator[](key);
2925  }
2926  else
2927  {
2928  throw std::domain_error("cannot use operator[] with " + type_name());
2929  }
2930  }
2931 
2959  const_reference operator[](const typename object_t::key_type& key) const
2960  {
2961  // [] only works for objects
2962  if (is_object())
2963  {
2964  assert(m_value.object != nullptr);
2965  assert(m_value.object->find(key) != m_value.object->end());
2966  return m_value.object->find(key)->second;
2967  }
2968  else
2969  {
2970  throw std::domain_error("cannot use operator[] with " + type_name());
2971  }
2972  }
2973 
3003  template<typename T, std::size_t n>
3004  reference operator[](const T (&key)[n])
3005  {
3006  // implicitly convert null to object
3007  if (is_null())
3008  {
3009  m_type = value_t::object;
3010  m_value = value_t::object;
3011  }
3012 
3013  // at only works for objects
3014  if (is_object())
3015  {
3016  assert(m_value.object != nullptr);
3017  return m_value.object->operator[](key);
3018  }
3019  else
3020  {
3021  throw std::domain_error("cannot use operator[] with " + type_name());
3022  }
3023  }
3024 
3054  template<typename T, std::size_t n>
3055  const_reference operator[](const T (&key)[n]) const
3056  {
3057  // at only works for objects
3058  if (is_object())
3059  {
3060  assert(m_value.object != nullptr);
3061  assert(m_value.object->find(key) != m_value.object->end());
3062  return m_value.object->find(key)->second;
3063  }
3064  else
3065  {
3066  throw std::domain_error("cannot use operator[] with " + type_name());
3067  }
3068  }
3069 
3118  template <class ValueType, typename
3119  std::enable_if<
3120  std::is_convertible<basic_json_t, ValueType>::value
3121  , int>::type = 0>
3122  ValueType value(const typename object_t::key_type& key, ValueType default_value) const
3123  {
3124  // at only works for objects
3125  if (is_object())
3126  {
3127  // if key is found, return value and given default value otherwise
3128  const auto it = find(key);
3129  if (it != end())
3130  {
3131  return *it;
3132  }
3133  else
3134  {
3135  return default_value;
3136  }
3137  }
3138  else
3139  {
3140  throw std::domain_error("cannot use value() with " + type_name());
3141  }
3142  }
3143 
3148  string_t value(const typename object_t::key_type& key, const char* default_value) const
3149  {
3150  return value(key, string_t(default_value));
3151  }
3152 
3174  {
3175  return *begin();
3176  }
3177 
3182  {
3183  return *cbegin();
3184  }
3185 
3208  {
3209  auto tmp = end();
3210  --tmp;
3211  return *tmp;
3212  }
3213 
3218  {
3219  auto tmp = cend();
3220  --tmp;
3221  return *tmp;
3222  }
3223 
3268  template <class InteratorType, typename
3269  std::enable_if<
3270  std::is_same<InteratorType, typename basic_json_t::iterator>::value or
3271  std::is_same<InteratorType, typename basic_json_t::const_iterator>::value
3272  , int>::type
3273  = 0>
3274  InteratorType erase(InteratorType pos)
3275  {
3276  // make sure iterator fits the current value
3277  if (this != pos.m_object)
3278  {
3279  throw std::domain_error("iterator does not fit current value");
3280  }
3281 
3282  InteratorType result = end();
3283 
3284  switch (m_type)
3285  {
3286  case value_t::boolean:
3287  case value_t::number_float:
3288  case value_t::number_integer:
3289  case value_t::string:
3290  {
3291  if (not pos.m_it.primitive_iterator.is_begin())
3292  {
3293  throw std::out_of_range("iterator out of range");
3294  }
3295 
3296  if (is_string())
3297  {
3298  delete m_value.string;
3299  m_value.string = nullptr;
3300  }
3301 
3302  m_type = value_t::null;
3303  break;
3304  }
3305 
3306  case value_t::object:
3307  {
3308  assert(m_value.object != nullptr);
3309  result.m_it.object_iterator = m_value.object->erase(pos.m_it.object_iterator);
3310  break;
3311  }
3312 
3313  case value_t::array:
3314  {
3315  assert(m_value.array != nullptr);
3316  result.m_it.array_iterator = m_value.array->erase(pos.m_it.array_iterator);
3317  break;
3318  }
3319 
3320  default:
3321  {
3322  throw std::domain_error("cannot use erase() with " + type_name());
3323  }
3324  }
3325 
3326  return result;
3327  }
3328 
3373  template <class InteratorType, typename
3374  std::enable_if<
3375  std::is_same<InteratorType, typename basic_json_t::iterator>::value or
3376  std::is_same<InteratorType, typename basic_json_t::const_iterator>::value
3377  , int>::type
3378  = 0>
3379  InteratorType erase(InteratorType first, InteratorType last)
3380  {
3381  // make sure iterator fits the current value
3382  if (this != first.m_object or this != last.m_object)
3383  {
3384  throw std::domain_error("iterators do not fit current value");
3385  }
3386 
3387  InteratorType result = end();
3388 
3389  switch (m_type)
3390  {
3391  case value_t::boolean:
3392  case value_t::number_float:
3393  case value_t::number_integer:
3394  case value_t::string:
3395  {
3396  if (not first.m_it.primitive_iterator.is_begin() or not last.m_it.primitive_iterator.is_end())
3397  {
3398  throw std::out_of_range("iterators out of range");
3399  }
3400 
3401  if (is_string())
3402  {
3403  delete m_value.string;
3404  m_value.string = nullptr;
3405  }
3406 
3407  m_type = value_t::null;
3408  break;
3409  }
3410 
3411  case value_t::object:
3412  {
3413  assert(m_value.object != nullptr);
3414  result.m_it.object_iterator = m_value.object->erase(first.m_it.object_iterator,
3415  last.m_it.object_iterator);
3416  break;
3417  }
3418 
3419  case value_t::array:
3420  {
3421  assert(m_value.array != nullptr);
3422  result.m_it.array_iterator = m_value.array->erase(first.m_it.array_iterator,
3423  last.m_it.array_iterator);
3424  break;
3425  }
3426 
3427  default:
3428  {
3429  throw std::domain_error("cannot use erase() with " + type_name());
3430  }
3431  }
3432 
3433  return result;
3434  }
3435 
3462  size_type erase(const typename object_t::key_type& key)
3463  {
3464  // this erase only works for objects
3465  if (is_object())
3466  {
3467  assert(m_value.object != nullptr);
3468  return m_value.object->erase(key);
3469  }
3470  else
3471  {
3472  throw std::domain_error("cannot use erase() with " + type_name());
3473  }
3474  }
3475 
3500  void erase(const size_type idx)
3501  {
3502  // this erase only works for arrays
3503  if (is_array())
3504  {
3505  if (idx >= size())
3506  {
3507  throw std::out_of_range("index out of range");
3508  }
3509 
3510  assert(m_value.array != nullptr);
3511  m_value.array->erase(m_value.array->begin() + static_cast<difference_type>(idx));
3512  }
3513  else
3514  {
3515  throw std::domain_error("cannot use erase() with " + type_name());
3516  }
3517  }
3518 
3536  iterator find(typename object_t::key_type key)
3537  {
3538  auto result = end();
3539 
3540  if (is_object())
3541  {
3542  assert(m_value.object != nullptr);
3543  result.m_it.object_iterator = m_value.object->find(key);
3544  }
3545 
3546  return result;
3547  }
3548 
3553  const_iterator find(typename object_t::key_type key) const
3554  {
3555  auto result = cend();
3556 
3557  if (is_object())
3558  {
3559  assert(m_value.object != nullptr);
3560  result.m_it.object_iterator = m_value.object->find(key);
3561  }
3562 
3563  return result;
3564  }
3565 
3584  size_type count(typename object_t::key_type key) const
3585  {
3586  // return 0 for all nonobject types
3587  assert(not is_object() or m_value.object != nullptr);
3588  return is_object() ? m_value.object->count(key) : 0;
3589  }
3590 
3592 
3593 
3595  // iterators //
3597 
3600 
3620  {
3621  iterator result(this);
3622  result.set_begin();
3623  return result;
3624  }
3625 
3630  {
3631  return cbegin();
3632  }
3633 
3654  {
3655  const_iterator result(this);
3656  result.set_begin();
3657  return result;
3658  }
3659 
3679  {
3680  iterator result(this);
3681  result.set_end();
3682  return result;
3683  }
3684 
3689  {
3690  return cend();
3691  }
3692 
3713  {
3714  const_iterator result(this);
3715  result.set_end();
3716  return result;
3717  }
3718 
3737  {
3738  return reverse_iterator(end());
3739  }
3740 
3745  {
3746  return crbegin();
3747  }
3748 
3768  {
3769  return reverse_iterator(begin());
3770  }
3771 
3776  {
3777  return crend();
3778  }
3779 
3799  {
3800  return const_reverse_iterator(cend());
3801  }
3802 
3822  {
3823  return const_reverse_iterator(cbegin());
3824  }
3825 
3826  private:
3827  // forward declaration
3828  template<typename IteratorType> class iteration_proxy;
3829 
3830  public:
3842  static iteration_proxy<iterator> iterator_wrapper(reference cont)
3843  {
3844  return iteration_proxy<iterator>(cont);
3845  }
3846 
3850  static iteration_proxy<const_iterator> iterator_wrapper(const_reference cont)
3851  {
3852  return iteration_proxy<const_iterator>(cont);
3853  }
3854 
3856 
3857 
3859  // capacity //
3861 
3864 
3894  bool empty() const noexcept
3895  {
3896  switch (m_type)
3897  {
3898  case value_t::null:
3899  {
3900  // null values are empty
3901  return true;
3902  }
3903 
3904  case value_t::array:
3905  {
3906  assert(m_value.array != nullptr);
3907  return m_value.array->empty();
3908  }
3909 
3910  case value_t::object:
3911  {
3912  assert(m_value.object != nullptr);
3913  return m_value.object->empty();
3914  }
3915 
3916  default:
3917  {
3918  // all other types are nonempty
3919  return false;
3920  }
3921  }
3922  }
3923 
3952  size_type size() const noexcept
3953  {
3954  switch (m_type)
3955  {
3956  case value_t::null:
3957  {
3958  // null values are empty
3959  return 0;
3960  }
3961 
3962  case value_t::array:
3963  {
3964  assert(m_value.array != nullptr);
3965  return m_value.array->size();
3966  }
3967 
3968  case value_t::object:
3969  {
3970  assert(m_value.object != nullptr);
3971  return m_value.object->size();
3972  }
3973 
3974  default:
3975  {
3976  // all other types have size 1
3977  return 1;
3978  }
3979  }
3980  }
3981 
4014  size_type max_size() const noexcept
4015  {
4016  switch (m_type)
4017  {
4018  case value_t::array:
4019  {
4020  assert(m_value.array != nullptr);
4021  return m_value.array->max_size();
4022  }
4023 
4024  case value_t::object:
4025  {
4026  assert(m_value.object != nullptr);
4027  return m_value.object->max_size();
4028  }
4029 
4030  default:
4031  {
4032  // all other types have max_size() == size()
4033  return size();
4034  }
4035  }
4036  }
4037 
4039 
4040 
4042  // modifiers //
4044 
4047 
4073  void clear() noexcept
4074  {
4075  switch (m_type)
4076  {
4077  case value_t::number_integer:
4078  {
4079  m_value.number_integer = 0;
4080  break;
4081  }
4082 
4083  case value_t::number_float:
4084  {
4085  m_value.number_float = 0.0;
4086  break;
4087  }
4088 
4089  case value_t::boolean:
4090  {
4091  m_value.boolean = false;
4092  break;
4093  }
4094 
4095  case value_t::string:
4096  {
4097  assert(m_value.string != nullptr);
4098  m_value.string->clear();
4099  break;
4100  }
4101 
4102  case value_t::array:
4103  {
4104  assert(m_value.array != nullptr);
4105  m_value.array->clear();
4106  break;
4107  }
4108 
4109  case value_t::object:
4110  {
4111  assert(m_value.object != nullptr);
4112  m_value.object->clear();
4113  break;
4114  }
4115 
4116  default:
4117  {
4118  break;
4119  }
4120  }
4121  }
4122 
4143  void push_back(basic_json&& val)
4144  {
4145  // push_back only works for null objects or arrays
4146  if (not(is_null() or is_array()))
4147  {
4148  throw std::domain_error("cannot use push_back() with " + type_name());
4149  }
4150 
4151  // transform null object into an array
4152  if (is_null())
4153  {
4154  m_type = value_t::array;
4155  m_value = value_t::array;
4156  }
4157 
4158  // add element to array (move semantics)
4159  assert(m_value.array != nullptr);
4160  m_value.array->push_back(std::move(val));
4161  // invalidate object
4162  val.m_type = value_t::null;
4163  }
4164 
4169  reference operator+=(basic_json&& val)
4170  {
4171  push_back(std::move(val));
4172  return *this;
4173  }
4174 
4179  void push_back(const basic_json& val)
4180  {
4181  // push_back only works for null objects or arrays
4182  if (not(is_null() or is_array()))
4183  {
4184  throw std::domain_error("cannot use push_back() with " + type_name());
4185  }
4186 
4187  // transform null object into an array
4188  if (is_null())
4189  {
4190  m_type = value_t::array;
4191  m_value = value_t::array;
4192  }
4193 
4194  // add element to array
4195  assert(m_value.array != nullptr);
4196  m_value.array->push_back(val);
4197  }
4198 
4203  reference operator+=(const basic_json& val)
4204  {
4205  push_back(val);
4206  return *this;
4207  }
4208 
4229  void push_back(const typename object_t::value_type& val)
4230  {
4231  // push_back only works for null objects or objects
4232  if (not(is_null() or is_object()))
4233  {
4234  throw std::domain_error("cannot use push_back() with " + type_name());
4235  }
4236 
4237  // transform null object into an object
4238  if (is_null())
4239  {
4240  m_type = value_t::object;
4241  m_value = value_t::object;
4242  }
4243 
4244  // add element to array
4245  assert(m_value.object != nullptr);
4246  m_value.object->insert(val);
4247  }
4248 
4253  reference operator+=(const typename object_t::value_type& val)
4254  {
4255  push_back(val);
4256  return operator[](val.first);
4257  }
4258 
4281  iterator insert(const_iterator pos, const basic_json& val)
4282  {
4283  // insert only works for arrays
4284  if (is_array())
4285  {
4286  // check if iterator pos fits to this JSON value
4287  if (pos.m_object != this)
4288  {
4289  throw std::domain_error("iterator does not fit current value");
4290  }
4291 
4292  // insert to array and return iterator
4293  iterator result(this);
4294  assert(m_value.array != nullptr);
4295  result.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator, val);
4296  return result;
4297  }
4298  else
4299  {
4300  throw std::domain_error("cannot use insert() with " + type_name());
4301  }
4302  }
4303 
4308  iterator insert(const_iterator pos, basic_json&& val)
4309  {
4310  return insert(pos, val);
4311  }
4312 
4337  iterator insert(const_iterator pos, size_type cnt, const basic_json& val)
4338  {
4339  // insert only works for arrays
4340  if (is_array())
4341  {
4342  // check if iterator pos fits to this JSON value
4343  if (pos.m_object != this)
4344  {
4345  throw std::domain_error("iterator does not fit current value");
4346  }
4347 
4348  // insert to array and return iterator
4349  iterator result(this);
4350  assert(m_value.array != nullptr);
4351  result.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator, cnt, val);
4352  return result;
4353  }
4354  else
4355  {
4356  throw std::domain_error("cannot use insert() with " + type_name());
4357  }
4358  }
4359 
4391  {
4392  // insert only works for arrays
4393  if (not is_array())
4394  {
4395  throw std::domain_error("cannot use insert() with " + type_name());
4396  }
4397 
4398  // check if iterator pos fits to this JSON value
4399  if (pos.m_object != this)
4400  {
4401  throw std::domain_error("iterator does not fit current value");
4402  }
4403 
4404  if (first.m_object != last.m_object)
4405  {
4406  throw std::domain_error("iterators do not fit");
4407  }
4408 
4409  if (first.m_object == this or last.m_object == this)
4410  {
4411  throw std::domain_error("passed iterators may not belong to container");
4412  }
4413 
4414  // insert to array and return iterator
4415  iterator result(this);
4416  assert(m_value.array != nullptr);
4417  result.m_it.array_iterator = m_value.array->insert(
4418  pos.m_it.array_iterator,
4419  first.m_it.array_iterator,
4420  last.m_it.array_iterator);
4421  return result;
4422  }
4423 
4448  iterator insert(const_iterator pos, std::initializer_list<basic_json> ilist)
4449  {
4450  // insert only works for arrays
4451  if (not is_array())
4452  {
4453  throw std::domain_error("cannot use insert() with " + type_name());
4454  }
4455 
4456  // check if iterator pos fits to this JSON value
4457  if (pos.m_object != this)
4458  {
4459  throw std::domain_error("iterator does not fit current value");
4460  }
4461 
4462  // insert to array and return iterator
4463  iterator result(this);
4464  assert(m_value.array != nullptr);
4465  result.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator, ilist);
4466  return result;
4467  }
4468 
4486  void swap(reference other) noexcept (
4487  std::is_nothrow_move_constructible<value_t>::value and
4488  std::is_nothrow_move_assignable<value_t>::value and
4489  std::is_nothrow_move_constructible<json_value>::value and
4490  std::is_nothrow_move_assignable<json_value>::value
4491  )
4492  {
4493  std::swap(m_type, other.m_type);
4494  std::swap(m_value, other.m_value);
4495  }
4496 
4517  void swap(array_t& other)
4518  {
4519  // swap only works for arrays
4520  if (is_array())
4521  {
4522  assert(m_value.array != nullptr);
4523  std::swap(*(m_value.array), other);
4524  }
4525  else
4526  {
4527  throw std::domain_error("cannot use swap() with " + type_name());
4528  }
4529  }
4530 
4551  void swap(object_t& other)
4552  {
4553  // swap only works for objects
4554  if (is_object())
4555  {
4556  assert(m_value.object != nullptr);
4557  std::swap(*(m_value.object), other);
4558  }
4559  else
4560  {
4561  throw std::domain_error("cannot use swap() with " + type_name());
4562  }
4563  }
4564 
4585  void swap(string_t& other)
4586  {
4587  // swap only works for strings
4588  if (is_string())
4589  {
4590  assert(m_value.string != nullptr);
4591  std::swap(*(m_value.string), other);
4592  }
4593  else
4594  {
4595  throw std::domain_error("cannot use swap() with " + type_name());
4596  }
4597  }
4598 
4600 
4601 
4603  // lexicographical comparison operators //
4605 
4608 
4609  private:
4619  friend bool operator<(const value_t lhs, const value_t rhs)
4620  {
4621  static constexpr std::array<uint8_t, 7> order = {{
4622  0, // null
4623  3, // object
4624  4, // array
4625  5, // string
4626  1, // boolean
4627  2, // integer
4628  2 // float
4629  }
4630  };
4631 
4632  // discarded values are not comparable
4633  if (lhs == value_t::discarded or rhs == value_t::discarded)
4634  {
4635  return false;
4636  }
4637 
4638  return order[static_cast<std::size_t>(lhs)] < order[static_cast<std::size_t>(rhs)];
4639  }
4640 
4641  public:
4665  friend bool operator==(const_reference lhs, const_reference rhs) noexcept
4666  {
4667  const auto lhs_type = lhs.type();
4668  const auto rhs_type = rhs.type();
4669 
4670  if (lhs_type == rhs_type)
4671  {
4672  switch (lhs_type)
4673  {
4674  case value_t::array:
4675  {
4676  assert(lhs.m_value.array != nullptr);
4677  assert(rhs.m_value.array != nullptr);
4678  return *lhs.m_value.array == *rhs.m_value.array;
4679  }
4680  case value_t::object:
4681  {
4682  assert(lhs.m_value.object != nullptr);
4683  assert(rhs.m_value.object != nullptr);
4684  return *lhs.m_value.object == *rhs.m_value.object;
4685  }
4686  case value_t::null:
4687  {
4688  return true;
4689  }
4690  case value_t::string:
4691  {
4692  assert(lhs.m_value.string != nullptr);
4693  assert(rhs.m_value.string != nullptr);
4694  return *lhs.m_value.string == *rhs.m_value.string;
4695  }
4696  case value_t::boolean:
4697  {
4698  return lhs.m_value.boolean == rhs.m_value.boolean;
4699  }
4700  case value_t::number_integer:
4701  {
4702  return lhs.m_value.number_integer == rhs.m_value.number_integer;
4703  }
4704  case value_t::number_float:
4705  {
4706  return approx(lhs.m_value.number_float, rhs.m_value.number_float);
4707  }
4708  default:
4709  {
4710  return false;
4711  }
4712  }
4713  }
4714  else if (lhs_type == value_t::number_integer and rhs_type == value_t::number_float)
4715  {
4716  return approx(static_cast<number_float_t>(lhs.m_value.number_integer),
4717  rhs.m_value.number_float);
4718  }
4719  else if (lhs_type == value_t::number_float and rhs_type == value_t::number_integer)
4720  {
4721  return approx(lhs.m_value.number_float,
4722  static_cast<number_float_t>(rhs.m_value.number_integer));
4723  }
4724  return false;
4725  }
4726 
4745  friend bool operator==(const_reference v, std::nullptr_t) noexcept
4746  {
4747  return v.is_null();
4748  }
4749 
4754  friend bool operator==(std::nullptr_t, const_reference v) noexcept
4755  {
4756  return v.is_null();
4757  }
4758 
4775  friend bool operator!=(const_reference lhs, const_reference rhs) noexcept
4776  {
4777  return not (lhs == rhs);
4778  }
4779 
4798  friend bool operator!=(const_reference v, std::nullptr_t) noexcept
4799  {
4800  return not v.is_null();
4801  }
4802 
4807  friend bool operator!=(std::nullptr_t, const_reference v) noexcept
4808  {
4809  return not v.is_null();
4810  }
4811 
4836  friend bool operator<(const_reference lhs, const_reference rhs) noexcept
4837  {
4838  const auto lhs_type = lhs.type();
4839  const auto rhs_type = rhs.type();
4840 
4841  if (lhs_type == rhs_type)
4842  {
4843  switch (lhs_type)
4844  {
4845  case value_t::array:
4846  {
4847  assert(lhs.m_value.array != nullptr);
4848  assert(rhs.m_value.array != nullptr);
4849  return *lhs.m_value.array < *rhs.m_value.array;
4850  }
4851  case value_t::object:
4852  {
4853  assert(lhs.m_value.object != nullptr);
4854  assert(rhs.m_value.object != nullptr);
4855  return *lhs.m_value.object < *rhs.m_value.object;
4856  }
4857  case value_t::null:
4858  {
4859  return false;
4860  }
4861  case value_t::string:
4862  {
4863  assert(lhs.m_value.string != nullptr);
4864  assert(rhs.m_value.string != nullptr);
4865  return *lhs.m_value.string < *rhs.m_value.string;
4866  }
4867  case value_t::boolean:
4868  {
4869  return lhs.m_value.boolean < rhs.m_value.boolean;
4870  }
4871  case value_t::number_integer:
4872  {
4873  return lhs.m_value.number_integer < rhs.m_value.number_integer;
4874  }
4875  case value_t::number_float:
4876  {
4877  return lhs.m_value.number_float < rhs.m_value.number_float;
4878  }
4879  default:
4880  {
4881  return false;
4882  }
4883  }
4884  }
4885  else if (lhs_type == value_t::number_integer and rhs_type == value_t::number_float)
4886  {
4887  return static_cast<number_float_t>(lhs.m_value.number_integer) <
4888  rhs.m_value.number_float;
4889  }
4890  else if (lhs_type == value_t::number_float and rhs_type == value_t::number_integer)
4891  {
4892  return lhs.m_value.number_float <
4893  static_cast<number_float_t>(rhs.m_value.number_integer);
4894  }
4895 
4896  // We only reach this line if we cannot compare values. In that case,
4897  // we compare types. Note we have to call the operator explicitly,
4898  // because MSVC has problems otherwise.
4899  return operator<(lhs_type, rhs_type);
4900  }
4901 
4919  friend bool operator<=(const_reference lhs, const_reference rhs) noexcept
4920  {
4921  return not (rhs < lhs);
4922  }
4923 
4941  friend bool operator>(const_reference lhs, const_reference rhs) noexcept
4942  {
4943  return not (lhs <= rhs);
4944  }
4945 
4963  friend bool operator>=(const_reference lhs, const_reference rhs) noexcept
4964  {
4965  return not (lhs < rhs);
4966  }
4967 
4969 
4970 
4972  // serialization //
4974 
4977 
5000  friend std::ostream& operator<<(std::ostream& o, const basic_json& j)
5001  {
5002  // read width member and use it as indentation parameter if nonzero
5003  const bool pretty_print = (o.width() > 0);
5004  const auto indentation = (pretty_print ? o.width() : 0);
5005 
5006  // reset width to 0 for subsequent calls to this stream
5007  o.width(0);
5008 
5009  // do the actual serialization
5010  j.dump(o, pretty_print, static_cast<unsigned int>(indentation));
5011  return o;
5012  }
5013 
5018  friend std::ostream& operator>>(const basic_json& j, std::ostream& o)
5019  {
5020  return o << j;
5021  }
5022 
5024 
5025 
5027  // deserialization //
5029 
5032 
5057  static basic_json parse(const string_t& s, parser_callback_t cb = nullptr)
5058  {
5059  return parser(s, cb).parse();
5060  }
5061 
5086  static basic_json parse(std::istream& i, parser_callback_t cb = nullptr)
5087  {
5088  return parser(i, cb).parse();
5089  }
5090 
5094  static basic_json parse(std::istream&& i, parser_callback_t cb = nullptr)
5095  {
5096  return parser(i, cb).parse();
5097  }
5098 
5122  friend std::istream& operator<<(basic_json& j, std::istream& i)
5123  {
5124  j = parser(i).parse();
5125  return i;
5126  }
5127 
5132  friend std::istream& operator>>(std::istream& i, basic_json& j)
5133  {
5134  j = parser(i).parse();
5135  return i;
5136  }
5137 
5139 
5140 
5141  private:
5143  // convenience functions //
5145 
5147  string_t type_name() const
5148  {
5149  switch (m_type)
5150  {
5151  case value_t::null:
5152  return "null";
5153  case value_t::object:
5154  return "object";
5155  case value_t::array:
5156  return "array";
5157  case value_t::string:
5158  return "string";
5159  case value_t::boolean:
5160  return "boolean";
5161  case value_t::discarded:
5162  return "discarded";
5163  default:
5164  return "number";
5165  }
5166  }
5167 
5176  static std::size_t extra_space(const string_t& s) noexcept
5177  {
5178  std::size_t result = 0;
5179 
5180  for (const auto& c : s)
5181  {
5182  switch (c)
5183  {
5184  case '"':
5185  case '\\':
5186  case '\b':
5187  case '\f':
5188  case '\n':
5189  case '\r':
5190  case '\t':
5191  {
5192  // from c (1 byte) to \x (2 bytes)
5193  result += 1;
5194  break;
5195  }
5196 
5197  default:
5198  {
5199  if (c >= 0x00 and c <= 0x1f)
5200  {
5201  // from c (1 byte) to \uxxxx (6 bytes)
5202  result += 5;
5203  }
5204  break;
5205  }
5206  }
5207  }
5208 
5209  return result;
5210  }
5211 
5225  static string_t escape_string(const string_t& s) noexcept
5226  {
5227  const auto space = extra_space(s);
5228  if (space == 0)
5229  {
5230  return s;
5231  }
5232 
5233  // create a result string of necessary size
5234  string_t result(s.size() + space, '\\');
5235  std::size_t pos = 0;
5236 
5237  for (const auto& c : s)
5238  {
5239  switch (c)
5240  {
5241  // quotation mark (0x22)
5242  case '"':
5243  {
5244  result[pos + 1] = '"';
5245  pos += 2;
5246  break;
5247  }
5248 
5249  // reverse solidus (0x5c)
5250  case '\\':
5251  {
5252  // nothing to change
5253  pos += 2;
5254  break;
5255  }
5256 
5257  // backspace (0x08)
5258  case '\b':
5259  {
5260  result[pos + 1] = 'b';
5261  pos += 2;
5262  break;
5263  }
5264 
5265  // formfeed (0x0c)
5266  case '\f':
5267  {
5268  result[pos + 1] = 'f';
5269  pos += 2;
5270  break;
5271  }
5272 
5273  // newline (0x0a)
5274  case '\n':
5275  {
5276  result[pos + 1] = 'n';
5277  pos += 2;
5278  break;
5279  }
5280 
5281  // carriage return (0x0d)
5282  case '\r':
5283  {
5284  result[pos + 1] = 'r';
5285  pos += 2;
5286  break;
5287  }
5288 
5289  // horizontal tab (0x09)
5290  case '\t':
5291  {
5292  result[pos + 1] = 't';
5293  pos += 2;
5294  break;
5295  }
5296 
5297  default:
5298  {
5299  if (c >= 0x00 and c <= 0x1f)
5300  {
5301  // convert a number 0..15 to its hex representation (0..f)
5302  auto hexify = [](const char v) -> char
5303  {
5304  return (v < 10) ? ('0' + v) : ('a' + v - 10);
5305  };
5306 
5307  // print character c as \uxxxx
5308  for (const char m :
5309  { 'u', '0', '0', hexify(c >> 4), hexify(c & 0x0f)
5310  })
5311  {
5312  result[++pos] = m;
5313  }
5314 
5315  ++pos;
5316  }
5317  else
5318  {
5319  // all other characters are added as-is
5320  result[pos++] = c;
5321  }
5322  break;
5323  }
5324  }
5325  }
5326 
5327  return result;
5328  }
5329 
5347  void dump(std::ostream& o,
5348  const bool pretty_print,
5349  const unsigned int indent_step,
5350  const unsigned int current_indent = 0) const
5351  {
5352  // variable to hold indentation for recursive calls
5353  unsigned int new_indent = current_indent;
5354 
5355  switch (m_type)
5356  {
5357  case value_t::object:
5358  {
5359  assert(m_value.object != nullptr);
5360 
5361  if (m_value.object->empty())
5362  {
5363  o << "{}";
5364  return;
5365  }
5366 
5367  o << "{";
5368 
5369  // increase indentation
5370  if (pretty_print)
5371  {
5372  new_indent += indent_step;
5373  o << "\n";
5374  }
5375 
5376  for (auto i = m_value.object->cbegin(); i != m_value.object->cend(); ++i)
5377  {
5378  if (i != m_value.object->cbegin())
5379  {
5380  o << (pretty_print ? ",\n" : ",");
5381  }
5382  o << string_t(new_indent, ' ') << "\""
5383  << escape_string(i->first) << "\":"
5384  << (pretty_print ? " " : "");
5385  i->second.dump(o, pretty_print, indent_step, new_indent);
5386  }
5387 
5388  // decrease indentation
5389  if (pretty_print)
5390  {
5391  new_indent -= indent_step;
5392  o << "\n";
5393  }
5394 
5395  o << string_t(new_indent, ' ') + "}";
5396  return;
5397  }
5398 
5399  case value_t::array:
5400  {
5401  assert(m_value.array != nullptr);
5402 
5403  if (m_value.array->empty())
5404  {
5405  o << "[]";
5406  return;
5407  }
5408 
5409  o << "[";
5410 
5411  // increase indentation
5412  if (pretty_print)
5413  {
5414  new_indent += indent_step;
5415  o << "\n";
5416  }
5417 
5418  for (auto i = m_value.array->cbegin(); i != m_value.array->cend(); ++i)
5419  {
5420  if (i != m_value.array->cbegin())
5421  {
5422  o << (pretty_print ? ",\n" : ",");
5423  }
5424  o << string_t(new_indent, ' ');
5425  i->dump(o, pretty_print, indent_step, new_indent);
5426  }
5427 
5428  // decrease indentation
5429  if (pretty_print)
5430  {
5431  new_indent -= indent_step;
5432  o << "\n";
5433  }
5434 
5435  o << string_t(new_indent, ' ') << "]";
5436  return;
5437  }
5438 
5439  case value_t::string:
5440  {
5441  assert(m_value.string != nullptr);
5442  o << string_t("\"") << escape_string(*m_value.string) << "\"";
5443  return;
5444  }
5445 
5446  case value_t::boolean:
5447  {
5448  o << (m_value.boolean ? "true" : "false");
5449  return;
5450  }
5451 
5452  case value_t::number_integer:
5453  {
5454  o << m_value.number_integer;
5455  return;
5456  }
5457 
5458  case value_t::number_float:
5459  {
5460  // 15 digits of precision allows round-trip IEEE 754
5461  // string->double->string; to be safe, we read this value from
5462  // std::numeric_limits<number_float_t>::digits10
5463  o << std::setprecision(std::numeric_limits<number_float_t>::digits10) << m_value.number_float;
5464  return;
5465  }
5466 
5467  case value_t::discarded:
5468  {
5469  o << "<discarded>";
5470  return;
5471  }
5472 
5473  case value_t::null:
5474  {
5475  o << "null";
5476  return;
5477  }
5478  }
5479  }
5480 
5481  private:
5483  // member variables //
5485 
5487  value_t m_type = value_t::null;
5488 
5490  json_value m_value = {};
5491 
5492 
5493  private:
5495  // iterators //
5497 
5507  class primitive_iterator_t
5508  {
5509  public:
5511  void set_begin()
5512  {
5513  m_it = begin_value;
5514  }
5515 
5517  void set_end()
5518  {
5519  m_it = end_value;
5520  }
5521 
5523  bool is_begin() const
5524  {
5525  return (m_it == begin_value);
5526  }
5527 
5529  bool is_end() const
5530  {
5531  return (m_it == end_value);
5532  }
5533 
5535  operator difference_type& ()
5536  {
5537  return m_it;
5538  }
5539 
5541  operator difference_type () const
5542  {
5543  return m_it;
5544  }
5545 
5546  private:
5547  static constexpr difference_type begin_value = 0;
5548  static constexpr difference_type end_value = begin_value + 1;
5549 
5551  difference_type m_it = std::numeric_limits<std::ptrdiff_t>::denorm_min();
5552  };
5553 
5561  struct internal_iterator
5562  {
5564  typename object_t::iterator object_iterator;
5566  typename array_t::iterator array_iterator;
5568  primitive_iterator_t primitive_iterator;
5569 
5571  internal_iterator()
5572  : object_iterator(), array_iterator(), primitive_iterator()
5573  {}
5574  };
5575 
5577  template<typename IteratorType>
5578  class iteration_proxy
5579  {
5580  private:
5582  class iteration_proxy_internal
5583  {
5584  private:
5586  IteratorType anchor;
5588  size_t array_index = 0;
5589 
5590  public:
5591  iteration_proxy_internal(IteratorType it)
5592  : anchor(it)
5593  {}
5594 
5596  iteration_proxy_internal& operator*()
5597  {
5598  return *this;
5599  }
5600 
5602  iteration_proxy_internal& operator++()
5603  {
5604  ++anchor;
5605  ++array_index;
5606 
5607  return *this;
5608  }
5609 
5611  bool operator!= (const iteration_proxy_internal& o) const
5612  {
5613  return anchor != o.anchor;
5614  }
5615 
5617  typename basic_json::string_t key() const
5618  {
5619  assert(anchor.m_object != nullptr);
5620 
5621  switch (anchor.m_object->type())
5622  {
5623  // use integer array index as key
5624  case value_t::array:
5625  {
5626  return std::to_string(array_index);
5627  }
5628 
5629  // use key from the object
5630  case value_t::object:
5631  {
5632  return anchor.key();
5633  }
5634 
5635  // use an empty key for all primitive types
5636  default:
5637  {
5638  return "";
5639  }
5640  }
5641  }
5642 
5644  typename IteratorType::reference value() const
5645  {
5646  return anchor.value();
5647  }
5648  };
5649 
5651  typename IteratorType::reference container;
5652 
5653  public:
5655  iteration_proxy(typename IteratorType::reference cont)
5656  : container(cont)
5657  {}
5658 
5660  iteration_proxy_internal begin()
5661  {
5662  return iteration_proxy_internal(container.begin());
5663  }
5664 
5666  iteration_proxy_internal end()
5667  {
5668  return iteration_proxy_internal(container.end());
5669  }
5670  };
5671 
5672  public:
5686  class const_iterator : public std::iterator<std::random_access_iterator_tag, const basic_json>
5687  {
5689  friend class basic_json;
5690 
5691  public:
5701  using iterator_category = std::bidirectional_iterator_tag;
5702 
5704  const_iterator() = default;
5705 
5707  const_iterator(pointer object) : m_object(object)
5708  {
5709  assert(m_object != nullptr);
5710 
5711  switch (m_object->m_type)
5712  {
5714  {
5715  m_it.object_iterator = typename object_t::iterator();
5716  break;
5717  }
5718 
5720  {
5721  m_it.array_iterator = typename array_t::iterator();
5722  break;
5723  }
5724 
5725  default:
5726  {
5727  m_it.primitive_iterator = primitive_iterator_t();
5728  break;
5729  }
5730  }
5731  }
5732 
5734  const_iterator(const iterator& other) : m_object(other.m_object)
5735  {
5736  assert(m_object != nullptr);
5737 
5738  switch (m_object->m_type)
5739  {
5741  {
5742  m_it.object_iterator = other.m_it.object_iterator;
5743  break;
5744  }
5745 
5747  {
5748  m_it.array_iterator = other.m_it.array_iterator;
5749  break;
5750  }
5751 
5752  default:
5753  {
5754  m_it.primitive_iterator = other.m_it.primitive_iterator;
5755  break;
5756  }
5757  }
5758  }
5759 
5761  const_iterator(const const_iterator& other) noexcept
5762  : m_object(other.m_object), m_it(other.m_it)
5763  {}
5764 
5767  std::is_nothrow_move_constructible<pointer>::value and
5768  std::is_nothrow_move_assignable<pointer>::value and
5769  std::is_nothrow_move_constructible<internal_iterator>::value and
5770  std::is_nothrow_move_assignable<internal_iterator>::value
5771  )
5772  {
5773  std::swap(m_object, other.m_object);
5774  std::swap(m_it, other.m_it);
5775  return *this;
5776  }
5777 
5778  private:
5780  void set_begin()
5781  {
5782  assert(m_object != nullptr);
5783 
5784  switch (m_object->m_type)
5785  {
5787  {
5788  assert(m_object->m_value.object != nullptr);
5789  m_it.object_iterator = m_object->m_value.object->begin();
5790  break;
5791  }
5792 
5794  {
5795  assert(m_object->m_value.array != nullptr);
5796  m_it.array_iterator = m_object->m_value.array->begin();
5797  break;
5798  }
5799 
5801  {
5802  // set to end so begin()==end() is true: null is empty
5803  m_it.primitive_iterator.set_end();
5804  break;
5805  }
5806 
5807  default:
5808  {
5809  m_it.primitive_iterator.set_begin();
5810  break;
5811  }
5812  }
5813  }
5814 
5816  void set_end()
5817  {
5818  assert(m_object != nullptr);
5819 
5820  switch (m_object->m_type)
5821  {
5823  {
5824  assert(m_object->m_value.object != nullptr);
5825  m_it.object_iterator = m_object->m_value.object->end();
5826  break;
5827  }
5828 
5830  {
5831  assert(m_object->m_value.array != nullptr);
5832  m_it.array_iterator = m_object->m_value.array->end();
5833  break;
5834  }
5835 
5836  default:
5837  {
5838  m_it.primitive_iterator.set_end();
5839  break;
5840  }
5841  }
5842  }
5843 
5844  public:
5847  {
5848  assert(m_object != nullptr);
5849 
5850  switch (m_object->m_type)
5851  {
5853  {
5854  assert(m_object->m_value.object);
5855  assert(m_it.object_iterator != m_object->m_value.object->end());
5856  return m_it.object_iterator->second;
5857  }
5858 
5860  {
5861  assert(m_object->m_value.array);
5862  assert(m_it.array_iterator != m_object->m_value.array->end());
5863  return *m_it.array_iterator;
5864  }
5865 
5867  {
5868  throw std::out_of_range("cannot get value");
5869  }
5870 
5871  default:
5872  {
5873  if (m_it.primitive_iterator.is_begin())
5874  {
5875  return *m_object;
5876  }
5877  else
5878  {
5879  throw std::out_of_range("cannot get value");
5880  }
5881  }
5882  }
5883  }
5884 
5887  {
5888  assert(m_object != nullptr);
5889 
5890  switch (m_object->m_type)
5891  {
5893  {
5894  assert(m_object->m_value.object);
5895  assert(m_it.object_iterator != m_object->m_value.object->end());
5896  return &(m_it.object_iterator->second);
5897  }
5898 
5900  {
5901  assert(m_object->m_value.array);
5902  assert(m_it.array_iterator != m_object->m_value.array->end());
5903  return &*m_it.array_iterator;
5904  }
5905 
5906  default:
5907  {
5908  if (m_it.primitive_iterator.is_begin())
5909  {
5910  return m_object;
5911  }
5912  else
5913  {
5914  throw std::out_of_range("cannot get value");
5915  }
5916  }
5917  }
5918  }
5919 
5922  {
5923  auto result = *this;
5924  ++(*this);
5925  return result;
5926  }
5927 
5930  {
5931  assert(m_object != nullptr);
5932 
5933  switch (m_object->m_type)
5934  {
5936  {
5937  ++m_it.object_iterator;
5938  break;
5939  }
5940 
5942  {
5943  ++m_it.array_iterator;
5944  break;
5945  }
5946 
5947  default:
5948  {
5949  ++m_it.primitive_iterator;
5950  break;
5951  }
5952  }
5953 
5954  return *this;
5955  }
5956 
5959  {
5960  auto result = *this;
5961  --(*this);
5962  return result;
5963  }
5964 
5967  {
5968  assert(m_object != nullptr);
5969 
5970  switch (m_object->m_type)
5971  {
5973  {
5974  --m_it.object_iterator;
5975  break;
5976  }
5977 
5979  {
5980  --m_it.array_iterator;
5981  break;
5982  }
5983 
5984  default:
5985  {
5986  --m_it.primitive_iterator;
5987  break;
5988  }
5989  }
5990 
5991  return *this;
5992  }
5993 
5995  bool operator==(const const_iterator& other) const
5996  {
5997  // if objects are not the same, the comparison is undefined
5998  if (m_object != other.m_object)
5999  {
6000  throw std::domain_error("cannot compare iterators of different containers");
6001  }
6002 
6003  assert(m_object != nullptr);
6004 
6005  switch (m_object->m_type)
6006  {
6008  {
6009  return (m_it.object_iterator == other.m_it.object_iterator);
6010  }
6011 
6013  {
6014  return (m_it.array_iterator == other.m_it.array_iterator);
6015  }
6016 
6017  default:
6018  {
6019  return (m_it.primitive_iterator == other.m_it.primitive_iterator);
6020  }
6021  }
6022  }
6023 
6025  bool operator!=(const const_iterator& other) const
6026  {
6027  return not operator==(other);
6028  }
6029 
6031  bool operator<(const const_iterator& other) const
6032  {
6033  // if objects are not the same, the comparison is undefined
6034  if (m_object != other.m_object)
6035  {
6036  throw std::domain_error("cannot compare iterators of different containers");
6037  }
6038 
6039  assert(m_object != nullptr);
6040 
6041  switch (m_object->m_type)
6042  {
6044  {
6045  throw std::domain_error("cannot compare order of object iterators");
6046  }
6047 
6049  {
6050  return (m_it.array_iterator < other.m_it.array_iterator);
6051  }
6052 
6053  default:
6054  {
6055  return (m_it.primitive_iterator < other.m_it.primitive_iterator);
6056  }
6057  }
6058  }
6059 
6061  bool operator<=(const const_iterator& other) const
6062  {
6063  return not other.operator < (*this);
6064  }
6065 
6067  bool operator>(const const_iterator& other) const
6068  {
6069  return not operator<=(other);
6070  }
6071 
6073  bool operator>=(const const_iterator& other) const
6074  {
6075  return not operator<(other);
6076  }
6077 
6080  {
6081  assert(m_object != nullptr);
6082 
6083  switch (m_object->m_type)
6084  {
6086  {
6087  throw std::domain_error("cannot use offsets with object iterators");
6088  }
6089 
6091  {
6092  m_it.array_iterator += i;
6093  break;
6094  }
6095 
6096  default:
6097  {
6098  m_it.primitive_iterator += i;
6099  break;
6100  }
6101  }
6102 
6103  return *this;
6104  }
6105 
6108  {
6109  return operator+=(-i);
6110  }
6111 
6114  {
6115  auto result = *this;
6116  result += i;
6117  return result;
6118  }
6119 
6122  {
6123  auto result = *this;
6124  result -= i;
6125  return result;
6126  }
6127 
6130  {
6131  assert(m_object != nullptr);
6132 
6133  switch (m_object->m_type)
6134  {
6136  {
6137  throw std::domain_error("cannot use offsets with object iterators");
6138  }
6139 
6141  {
6142  return m_it.array_iterator - other.m_it.array_iterator;
6143  }
6144 
6145  default:
6146  {
6147  return m_it.primitive_iterator - other.m_it.primitive_iterator;
6148  }
6149  }
6150  }
6151 
6154  {
6155  assert(m_object != nullptr);
6156 
6157  switch (m_object->m_type)
6158  {
6160  {
6161  throw std::domain_error("cannot use operator[] for object iterators");
6162  }
6163 
6165  {
6166  return *(m_it.array_iterator + n);
6167  }
6168 
6170  {
6171  throw std::out_of_range("cannot get value");
6172  }
6173 
6174  default:
6175  {
6176  if (m_it.primitive_iterator == -n)
6177  {
6178  return *m_object;
6179  }
6180  else
6181  {
6182  throw std::out_of_range("cannot get value");
6183  }
6184  }
6185  }
6186  }
6187 
6189  typename object_t::key_type key() const
6190  {
6191  assert(m_object != nullptr);
6192 
6193  if (m_object->is_object())
6194  {
6195  return m_it.object_iterator->first;
6196  }
6197  else
6198  {
6199  throw std::domain_error("cannot use key() for non-object iterators");
6200  }
6201  }
6202 
6205  {
6206  return operator*();
6207  }
6208 
6209  private:
6211  pointer m_object = nullptr;
6213  internal_iterator m_it = internal_iterator();
6214  };
6215 
6228  class iterator : public const_iterator
6229  {
6230  public:
6232  using pointer = typename basic_json::pointer;
6234 
6236  iterator() = default;
6237 
6239  iterator(pointer object) noexcept
6240  : base_iterator(object)
6241  {}
6242 
6244  iterator(const iterator& other) noexcept
6245  : base_iterator(other)
6246  {}
6247 
6249  iterator& operator=(iterator other) noexcept(
6250  std::is_nothrow_move_constructible<pointer>::value and
6251  std::is_nothrow_move_assignable<pointer>::value and
6252  std::is_nothrow_move_constructible<internal_iterator>::value and
6253  std::is_nothrow_move_assignable<internal_iterator>::value
6254  )
6255  {
6256  base_iterator::operator=(other);
6257  return *this;
6258  }
6259 
6262  {
6263  return const_cast<reference>(base_iterator::operator*());
6264  }
6265 
6268  {
6269  return const_cast<pointer>(base_iterator::operator->());
6270  }
6271 
6274  {
6275  iterator result = *this;
6276  base_iterator::operator++();
6277  return result;
6278  }
6279 
6282  {
6283  base_iterator::operator++();
6284  return *this;
6285  }
6286 
6289  {
6290  iterator result = *this;
6291  base_iterator::operator--();
6292  return result;
6293  }
6294 
6297  {
6298  base_iterator::operator--();
6299  return *this;
6300  }
6301 
6304  {
6305  base_iterator::operator+=(i);
6306  return *this;
6307  }
6308 
6311  {
6312  base_iterator::operator-=(i);
6313  return *this;
6314  }
6315 
6318  {
6319  auto result = *this;
6320  result += i;
6321  return result;
6322  }
6323 
6326  {
6327  auto result = *this;
6328  result -= i;
6329  return result;
6330  }
6331 
6332  difference_type operator-(const iterator& other) const
6333  {
6334  return base_iterator::operator-(other);
6335  }
6336 
6339  {
6340  return const_cast<reference>(base_iterator::operator[](n));
6341  }
6342 
6345  {
6346  return const_cast<reference>(base_iterator::value());
6347  }
6348  };
6349 
6367  template<typename Base>
6368  class json_reverse_iterator : public std::reverse_iterator<Base>
6369  {
6370  public:
6372  using base_iterator = std::reverse_iterator<Base>;
6374  using reference = typename Base::reference;
6375 
6377  json_reverse_iterator(const typename base_iterator::iterator_type& it)
6378  : base_iterator(it)
6379  {}
6380 
6383  : base_iterator(it)
6384  {}
6385 
6388  {
6389  return base_iterator::operator++(1);
6390  }
6391 
6394  {
6395  base_iterator::operator++();
6396  return *this;
6397  }
6398 
6401  {
6402  return base_iterator::operator--(1);
6403  }
6404 
6407  {
6408  base_iterator::operator--();
6409  return *this;
6410  }
6411 
6414  {
6415  base_iterator::operator+=(i);
6416  return *this;
6417  }
6418 
6421  {
6422  auto result = *this;
6423  result += i;
6424  return result;
6425  }
6426 
6429  {
6430  auto result = *this;
6431  result -= i;
6432  return result;
6433  }
6434 
6437  {
6438  return this->base() - other.base();
6439  }
6440 
6443  {
6444  return *(this->operator+(n));
6445  }
6446 
6448  typename object_t::key_type key() const
6449  {
6450  auto it = --this->base();
6451  return it.key();
6452  }
6453 
6456  {
6457  auto it = --this->base();
6458  return it.operator * ();
6459  }
6460  };
6461 
6462 
6463  private:
6465  // lexer and parser //
6467 
6475  class lexer
6476  {
6477  public:
6479  enum class token_type
6480  {
6481  uninitialized,
6482  literal_true,
6483  literal_false,
6484  literal_null,
6485  value_string,
6486  value_number,
6487  begin_array,
6488  begin_object,
6489  end_array,
6490  end_object,
6491  name_separator,
6492  value_separator,
6493  parse_error,
6494  end_of_input
6495  };
6496 
6498  using lexer_char_t = unsigned char;
6499 
6501  explicit lexer(const string_t& s) noexcept
6502  : m_stream(nullptr), m_buffer(s)
6503  {
6504  m_content = reinterpret_cast<const lexer_char_t*>(s.c_str());
6505  assert(m_content != nullptr);
6506  m_start = m_cursor = m_content;
6507  m_limit = m_content + s.size();
6508  }
6509 
6511  explicit lexer(std::istream* s) noexcept
6512  : m_stream(s), m_buffer()
6513  {
6514  assert(m_stream != nullptr);
6515  getline(*m_stream, m_buffer);
6516  m_content = reinterpret_cast<const lexer_char_t*>(m_buffer.c_str());
6517  assert(m_content != nullptr);
6518  m_start = m_cursor = m_content;
6519  m_limit = m_content + m_buffer.size();
6520  }
6521 
6523  lexer() = default;
6524 
6525  // switch off unwanted functions
6526  lexer(const lexer&) = delete;
6527  lexer operator=(const lexer&) = delete;
6528 
6544  static string_t to_unicode(const std::size_t codepoint1,
6545  const std::size_t codepoint2 = 0)
6546  {
6547  string_t result;
6548 
6549  // calculate the codepoint from the given code points
6550  std::size_t codepoint = codepoint1;
6551 
6552  // check if codepoint1 is a high surrogate
6553  if (codepoint1 >= 0xD800 and codepoint1 <= 0xDBFF)
6554  {
6555  // check if codepoint2 is a low surrogate
6556  if (codepoint2 >= 0xDC00 and codepoint2 <= 0xDFFF)
6557  {
6558  codepoint =
6559  // high surrogate occupies the most significant 22 bits
6560  (codepoint1 << 10)
6561  // low surrogate occupies the least significant 15 bits
6562  + codepoint2
6563  // there is still the 0xD800, 0xDC00 and 0x10000 noise
6564  // in the result so we have to subtract with:
6565  // (0xD800 << 10) + DC00 - 0x10000 = 0x35FDC00
6566  - 0x35FDC00;
6567  }
6568  else
6569  {
6570  throw std::invalid_argument("missing or wrong low surrogate");
6571  }
6572  }
6573 
6574  if (codepoint < 0x80)
6575  {
6576  // 1-byte characters: 0xxxxxxx (ASCII)
6577  result.append(1, static_cast<typename string_t::value_type>(codepoint));
6578  }
6579  else if (codepoint <= 0x7ff)
6580  {
6581  // 2-byte characters: 110xxxxx 10xxxxxx
6582  result.append(1, static_cast<typename string_t::value_type>(0xC0 | ((codepoint >> 6) & 0x1F)));
6583  result.append(1, static_cast<typename string_t::value_type>(0x80 | (codepoint & 0x3F)));
6584  }
6585  else if (codepoint <= 0xffff)
6586  {
6587  // 3-byte characters: 1110xxxx 10xxxxxx 10xxxxxx
6588  result.append(1, static_cast<typename string_t::value_type>(0xE0 | ((codepoint >> 12) & 0x0F)));
6589  result.append(1, static_cast<typename string_t::value_type>(0x80 | ((codepoint >> 6) & 0x3F)));
6590  result.append(1, static_cast<typename string_t::value_type>(0x80 | (codepoint & 0x3F)));
6591  }
6592  else if (codepoint <= 0x10ffff)
6593  {
6594  // 4-byte characters: 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
6595  result.append(1, static_cast<typename string_t::value_type>(0xF0 | ((codepoint >> 18) & 0x07)));
6596  result.append(1, static_cast<typename string_t::value_type>(0x80 | ((codepoint >> 12) & 0x3F)));
6597  result.append(1, static_cast<typename string_t::value_type>(0x80 | ((codepoint >> 6) & 0x3F)));
6598  result.append(1, static_cast<typename string_t::value_type>(0x80 | (codepoint & 0x3F)));
6599  }
6600  else
6601  {
6602  throw std::out_of_range("code points above 0x10FFFF are invalid");
6603  }
6604 
6605  return result;
6606  }
6607 
6609  static std::string token_type_name(token_type t)
6610  {
6611  switch (t)
6612  {
6613  case token_type::uninitialized:
6614  return "<uninitialized>";
6615  case token_type::literal_true:
6616  return "true literal";
6617  case token_type::literal_false:
6618  return "false literal";
6619  case token_type::literal_null:
6620  return "null literal";
6621  case token_type::value_string:
6622  return "string literal";
6623  case token_type::value_number:
6624  return "number literal";
6625  case token_type::begin_array:
6626  return "'['";
6627  case token_type::begin_object:
6628  return "'{'";
6629  case token_type::end_array:
6630  return "']'";
6631  case token_type::end_object:
6632  return "'}'";
6633  case token_type::name_separator:
6634  return "':'";
6635  case token_type::value_separator:
6636  return "','";
6637  case token_type::parse_error:
6638  return "<parse error>";
6639  case token_type::end_of_input:
6640  return "end of input";
6641  default:
6642  {
6643  // catch non-enum values
6644  return "unknown token"; // LCOV_EXCL_LINE
6645  }
6646  }
6647  }
6648 
6659  token_type scan() noexcept
6660  {
6661  // pointer for backtracking information
6662  m_marker = nullptr;
6663 
6664  // remember the begin of the token
6665  m_start = m_cursor;
6666  assert(m_start != nullptr);
6667 
6668 
6669  {
6670  lexer_char_t yych;
6671  unsigned int yyaccept = 0;
6672  static const unsigned char yybm[] =
6673  {
6674  0, 0, 0, 0, 0, 0, 0, 0,
6675  0, 32, 32, 0, 0, 32, 0, 0,
6676  64, 64, 64, 64, 64, 64, 64, 64,
6677  64, 64, 64, 64, 64, 64, 64, 64,
6678  96, 64, 0, 64, 64, 64, 64, 64,
6679  64, 64, 64, 64, 64, 64, 64, 64,
6680  192, 192, 192, 192, 192, 192, 192, 192,
6681  192, 192, 64, 64, 64, 64, 64, 64,
6682  64, 64, 64, 64, 64, 64, 64, 64,
6683  64, 64, 64, 64, 64, 64, 64, 64,
6684  64, 64, 64, 64, 64, 64, 64, 64,
6685  64, 64, 64, 64, 0, 64, 64, 64,
6686  64, 64, 64, 64, 64, 64, 64, 64,
6687  64, 64, 64, 64, 64, 64, 64, 64,
6688  64, 64, 64, 64, 64, 64, 64, 64,
6689  64, 64, 64, 64, 64, 64, 64, 64,
6690  64, 64, 64, 64, 64, 64, 64, 64,
6691  64, 64, 64, 64, 64, 64, 64, 64,
6692  64, 64, 64, 64, 64, 64, 64, 64,
6693  64, 64, 64, 64, 64, 64, 64, 64,
6694  64, 64, 64, 64, 64, 64, 64, 64,
6695  64, 64, 64, 64, 64, 64, 64, 64,
6696  64, 64, 64, 64, 64, 64, 64, 64,
6697  64, 64, 64, 64, 64, 64, 64, 64,
6698  64, 64, 64, 64, 64, 64, 64, 64,
6699  64, 64, 64, 64, 64, 64, 64, 64,
6700  64, 64, 64, 64, 64, 64, 64, 64,
6701  64, 64, 64, 64, 64, 64, 64, 64,
6702  64, 64, 64, 64, 64, 64, 64, 64,
6703  64, 64, 64, 64, 64, 64, 64, 64,
6704  64, 64, 64, 64, 64, 64, 64, 64,
6705  64, 64, 64, 64, 64, 64, 64, 64,
6706  };
6707  if ((m_limit - m_cursor) < 5)
6708  {
6709  yyfill(); // LCOV_EXCL_LINE;
6710  }
6711  yych = *m_cursor;
6712  if (yych <= ':')
6713  {
6714  if (yych <= ' ')
6715  {
6716  if (yych <= '\n')
6717  {
6718  if (yych <= 0x00)
6719  {
6720  goto basic_json_parser_28;
6721  }
6722  if (yych <= 0x08)
6723  {
6724  goto basic_json_parser_30;
6725  }
6726  if (yych >= '\n')
6727  {
6728  goto basic_json_parser_4;
6729  }
6730  }
6731  else
6732  {
6733  if (yych == '\r')
6734  {
6735  goto basic_json_parser_2;
6736  }
6737  if (yych <= 0x1F)
6738  {
6739  goto basic_json_parser_30;
6740  }
6741  }
6742  }
6743  else
6744  {
6745  if (yych <= ',')
6746  {
6747  if (yych == '"')
6748  {
6749  goto basic_json_parser_27;
6750  }
6751  if (yych <= '+')
6752  {
6753  goto basic_json_parser_30;
6754  }
6755  goto basic_json_parser_16;
6756  }
6757  else
6758  {
6759  if (yych <= '/')
6760  {
6761  if (yych <= '-')
6762  {
6763  goto basic_json_parser_23;
6764  }
6765  goto basic_json_parser_30;
6766  }
6767  else
6768  {
6769  if (yych <= '0')
6770  {
6771  goto basic_json_parser_24;
6772  }
6773  if (yych <= '9')
6774  {
6775  goto basic_json_parser_26;
6776  }
6777  goto basic_json_parser_18;
6778  }
6779  }
6780  }
6781  }
6782  else
6783  {
6784  if (yych <= 'n')
6785  {
6786  if (yych <= ']')
6787  {
6788  if (yych == '[')
6789  {
6790  goto basic_json_parser_8;
6791  }
6792  if (yych <= '\\')
6793  {
6794  goto basic_json_parser_30;
6795  }
6796  goto basic_json_parser_10;
6797  }
6798  else
6799  {
6800  if (yych == 'f')
6801  {
6802  goto basic_json_parser_22;
6803  }
6804  if (yych <= 'm')
6805  {
6806  goto basic_json_parser_30;
6807  }
6808  goto basic_json_parser_20;
6809  }
6810  }
6811  else
6812  {
6813  if (yych <= '{')
6814  {
6815  if (yych == 't')
6816  {
6817  goto basic_json_parser_21;
6818  }
6819  if (yych <= 'z')
6820  {
6821  goto basic_json_parser_30;
6822  }
6823  goto basic_json_parser_12;
6824  }
6825  else
6826  {
6827  if (yych <= '}')
6828  {
6829  if (yych <= '|')
6830  {
6831  goto basic_json_parser_30;
6832  }
6833  goto basic_json_parser_14;
6834  }
6835  else
6836  {
6837  if (yych == 0xEF)
6838  {
6839  goto basic_json_parser_6;
6840  }
6841  goto basic_json_parser_30;
6842  }
6843  }
6844  }
6845  }
6846 basic_json_parser_2:
6847  ++m_cursor;
6848  yych = *m_cursor;
6849  goto basic_json_parser_5;
6850 basic_json_parser_3:
6851  {
6852  return scan();
6853  }
6854 basic_json_parser_4:
6855  ++m_cursor;
6856  if (m_limit <= m_cursor)
6857  {
6858  yyfill(); // LCOV_EXCL_LINE;
6859  }
6860  yych = *m_cursor;
6861 basic_json_parser_5:
6862  if (yybm[0 + yych] & 32)
6863  {
6864  goto basic_json_parser_4;
6865  }
6866  goto basic_json_parser_3;
6867 basic_json_parser_6:
6868  yyaccept = 0;
6869  yych = *(m_marker = ++m_cursor);
6870  if (yych == 0xBB)
6871  {
6872  goto basic_json_parser_64;
6873  }
6874 basic_json_parser_7:
6875  {
6876  return token_type::parse_error;
6877  }
6878 basic_json_parser_8:
6879  ++m_cursor;
6880  {
6881  return token_type::begin_array;
6882  }
6883 basic_json_parser_10:
6884  ++m_cursor;
6885  {
6886  return token_type::end_array;
6887  }
6888 basic_json_parser_12:
6889  ++m_cursor;
6890  {
6891  return token_type::begin_object;
6892  }
6893 basic_json_parser_14:
6894  ++m_cursor;
6895  {
6896  return token_type::end_object;
6897  }
6898 basic_json_parser_16:
6899  ++m_cursor;
6900  {
6901  return token_type::value_separator;
6902  }
6903 basic_json_parser_18:
6904  ++m_cursor;
6905  {
6906  return token_type::name_separator;
6907  }
6908 basic_json_parser_20:
6909  yyaccept = 0;
6910  yych = *(m_marker = ++m_cursor);
6911  if (yych == 'u')
6912  {
6913  goto basic_json_parser_60;
6914  }
6915  goto basic_json_parser_7;
6916 basic_json_parser_21:
6917  yyaccept = 0;
6918  yych = *(m_marker = ++m_cursor);
6919  if (yych == 'r')
6920  {
6921  goto basic_json_parser_56;
6922  }
6923  goto basic_json_parser_7;
6924 basic_json_parser_22:
6925  yyaccept = 0;
6926  yych = *(m_marker = ++m_cursor);
6927  if (yych == 'a')
6928  {
6929  goto basic_json_parser_51;
6930  }
6931  goto basic_json_parser_7;
6932 basic_json_parser_23:
6933  yych = *++m_cursor;
6934  if (yych <= '/')
6935  {
6936  goto basic_json_parser_7;
6937  }
6938  if (yych <= '0')
6939  {
6940  goto basic_json_parser_50;
6941  }
6942  if (yych <= '9')
6943  {
6944  goto basic_json_parser_41;
6945  }
6946  goto basic_json_parser_7;
6947 basic_json_parser_24:
6948  yyaccept = 1;
6949  yych = *(m_marker = ++m_cursor);
6950  if (yych <= 'D')
6951  {
6952  if (yych == '.')
6953  {
6954  goto basic_json_parser_43;
6955  }
6956  }
6957  else
6958  {
6959  if (yych <= 'E')
6960  {
6961  goto basic_json_parser_44;
6962  }
6963  if (yych == 'e')
6964  {
6965  goto basic_json_parser_44;
6966  }
6967  }
6968 basic_json_parser_25:
6969  {
6970  return token_type::value_number;
6971  }
6972 basic_json_parser_26:
6973  yyaccept = 1;
6974  yych = *(m_marker = ++m_cursor);
6975  goto basic_json_parser_42;
6976 basic_json_parser_27:
6977  yyaccept = 0;
6978  yych = *(m_marker = ++m_cursor);
6979  if (yych <= 0x0F)
6980  {
6981  goto basic_json_parser_7;
6982  }
6983  goto basic_json_parser_32;
6984 basic_json_parser_28:
6985  ++m_cursor;
6986  {
6987  return token_type::end_of_input;
6988  }
6989 basic_json_parser_30:
6990  yych = *++m_cursor;
6991  goto basic_json_parser_7;
6992 basic_json_parser_31:
6993  ++m_cursor;
6994  if (m_limit <= m_cursor)
6995  {
6996  yyfill(); // LCOV_EXCL_LINE;
6997  }
6998  yych = *m_cursor;
6999 basic_json_parser_32:
7000  if (yybm[0 + yych] & 64)
7001  {
7002  goto basic_json_parser_31;
7003  }
7004  if (yych <= 0x0F)
7005  {
7006  goto basic_json_parser_33;
7007  }
7008  if (yych <= '"')
7009  {
7010  goto basic_json_parser_35;
7011  }
7012  goto basic_json_parser_34;
7013 basic_json_parser_33:
7014  m_cursor = m_marker;
7015  if (yyaccept == 0)
7016  {
7017  goto basic_json_parser_7;
7018  }
7019  else
7020  {
7021  goto basic_json_parser_25;
7022  }
7023 basic_json_parser_34:
7024  ++m_cursor;
7025  if (m_limit <= m_cursor)
7026  {
7027  yyfill(); // LCOV_EXCL_LINE;
7028  }
7029  yych = *m_cursor;
7030  if (yych <= 'e')
7031  {
7032  if (yych <= '/')
7033  {
7034  if (yych == '"')
7035  {
7036  goto basic_json_parser_31;
7037  }
7038  if (yych <= '.')
7039  {
7040  goto basic_json_parser_33;
7041  }
7042  goto basic_json_parser_31;
7043  }
7044  else
7045  {
7046  if (yych <= '\\')
7047  {
7048  if (yych <= '[')
7049  {
7050  goto basic_json_parser_33;
7051  }
7052  goto basic_json_parser_31;
7053  }
7054  else
7055  {
7056  if (yych == 'b')
7057  {
7058  goto basic_json_parser_31;
7059  }
7060  goto basic_json_parser_33;
7061  }
7062  }
7063  }
7064  else
7065  {
7066  if (yych <= 'q')
7067  {
7068  if (yych <= 'f')
7069  {
7070  goto basic_json_parser_31;
7071  }
7072  if (yych == 'n')
7073  {
7074  goto basic_json_parser_31;
7075  }
7076  goto basic_json_parser_33;
7077  }
7078  else
7079  {
7080  if (yych <= 's')
7081  {
7082  if (yych <= 'r')
7083  {
7084  goto basic_json_parser_31;
7085  }
7086  goto basic_json_parser_33;
7087  }
7088  else
7089  {
7090  if (yych <= 't')
7091  {
7092  goto basic_json_parser_31;
7093  }
7094  if (yych <= 'u')
7095  {
7096  goto basic_json_parser_37;
7097  }
7098  goto basic_json_parser_33;
7099  }
7100  }
7101  }
7102 basic_json_parser_35:
7103  ++m_cursor;
7104  {
7105  return token_type::value_string;
7106  }
7107 basic_json_parser_37:
7108  ++m_cursor;
7109  if (m_limit <= m_cursor)
7110  {
7111  yyfill(); // LCOV_EXCL_LINE;
7112  }
7113  yych = *m_cursor;
7114  if (yych <= '@')
7115  {
7116  if (yych <= '/')
7117  {
7118  goto basic_json_parser_33;
7119  }
7120  if (yych >= ':')
7121  {
7122  goto basic_json_parser_33;
7123  }
7124  }
7125  else
7126  {
7127  if (yych <= 'F')
7128  {
7129  goto basic_json_parser_38;
7130  }
7131  if (yych <= '`')
7132  {
7133  goto basic_json_parser_33;
7134  }
7135  if (yych >= 'g')
7136  {
7137  goto basic_json_parser_33;
7138  }
7139  }
7140 basic_json_parser_38:
7141  ++m_cursor;
7142  if (m_limit <= m_cursor)
7143  {
7144  yyfill(); // LCOV_EXCL_LINE;
7145  }
7146  yych = *m_cursor;
7147  if (yych <= '@')
7148  {
7149  if (yych <= '/')
7150  {
7151  goto basic_json_parser_33;
7152  }
7153  if (yych >= ':')
7154  {
7155  goto basic_json_parser_33;
7156  }
7157  }
7158  else
7159  {
7160  if (yych <= 'F')
7161  {
7162  goto basic_json_parser_39;
7163  }
7164  if (yych <= '`')
7165  {
7166  goto basic_json_parser_33;
7167  }
7168  if (yych >= 'g')
7169  {
7170  goto basic_json_parser_33;
7171  }
7172  }
7173 basic_json_parser_39:
7174  ++m_cursor;
7175  if (m_limit <= m_cursor)
7176  {
7177  yyfill(); // LCOV_EXCL_LINE;
7178  }
7179  yych = *m_cursor;
7180  if (yych <= '@')
7181  {
7182  if (yych <= '/')
7183  {
7184  goto basic_json_parser_33;
7185  }
7186  if (yych >= ':')
7187  {
7188  goto basic_json_parser_33;
7189  }
7190  }
7191  else
7192  {
7193  if (yych <= 'F')
7194  {
7195  goto basic_json_parser_40;
7196  }
7197  if (yych <= '`')
7198  {
7199  goto basic_json_parser_33;
7200  }
7201  if (yych >= 'g')
7202  {
7203  goto basic_json_parser_33;
7204  }
7205  }
7206 basic_json_parser_40:
7207  ++m_cursor;
7208  if (m_limit <= m_cursor)
7209  {
7210  yyfill(); // LCOV_EXCL_LINE;
7211  }
7212  yych = *m_cursor;
7213  if (yych <= '@')
7214  {
7215  if (yych <= '/')
7216  {
7217  goto basic_json_parser_33;
7218  }
7219  if (yych <= '9')
7220  {
7221  goto basic_json_parser_31;
7222  }
7223  goto basic_json_parser_33;
7224  }
7225  else
7226  {
7227  if (yych <= 'F')
7228  {
7229  goto basic_json_parser_31;
7230  }
7231  if (yych <= '`')
7232  {
7233  goto basic_json_parser_33;
7234  }
7235  if (yych <= 'f')
7236  {
7237  goto basic_json_parser_31;
7238  }
7239  goto basic_json_parser_33;
7240  }
7241 basic_json_parser_41:
7242  yyaccept = 1;
7243  m_marker = ++m_cursor;
7244  if ((m_limit - m_cursor) < 3)
7245  {
7246  yyfill(); // LCOV_EXCL_LINE;
7247  }
7248  yych = *m_cursor;
7249 basic_json_parser_42:
7250  if (yybm[0 + yych] & 128)
7251  {
7252  goto basic_json_parser_41;
7253  }
7254  if (yych <= 'D')
7255  {
7256  if (yych != '.')
7257  {
7258  goto basic_json_parser_25;
7259  }
7260  }
7261  else
7262  {
7263  if (yych <= 'E')
7264  {
7265  goto basic_json_parser_44;
7266  }
7267  if (yych == 'e')
7268  {
7269  goto basic_json_parser_44;
7270  }
7271  goto basic_json_parser_25;
7272  }
7273 basic_json_parser_43:
7274  yych = *++m_cursor;
7275  if (yych <= '/')
7276  {
7277  goto basic_json_parser_33;
7278  }
7279  if (yych <= '9')
7280  {
7281  goto basic_json_parser_48;
7282  }
7283  goto basic_json_parser_33;
7284 basic_json_parser_44:
7285  yych = *++m_cursor;
7286  if (yych <= ',')
7287  {
7288  if (yych != '+')
7289  {
7290  goto basic_json_parser_33;
7291  }
7292  }
7293  else
7294  {
7295  if (yych <= '-')
7296  {
7297  goto basic_json_parser_45;
7298  }
7299  if (yych <= '/')
7300  {
7301  goto basic_json_parser_33;
7302  }
7303  if (yych <= '9')
7304  {
7305  goto basic_json_parser_46;
7306  }
7307  goto basic_json_parser_33;
7308  }
7309 basic_json_parser_45:
7310  yych = *++m_cursor;
7311  if (yych <= '/')
7312  {
7313  goto basic_json_parser_33;
7314  }
7315  if (yych >= ':')
7316  {
7317  goto basic_json_parser_33;
7318  }
7319 basic_json_parser_46:
7320  ++m_cursor;
7321  if (m_limit <= m_cursor)
7322  {
7323  yyfill(); // LCOV_EXCL_LINE;
7324  }
7325  yych = *m_cursor;
7326  if (yych <= '/')
7327  {
7328  goto basic_json_parser_25;
7329  }
7330  if (yych <= '9')
7331  {
7332  goto basic_json_parser_46;
7333  }
7334  goto basic_json_parser_25;
7335 basic_json_parser_48:
7336  yyaccept = 1;
7337  m_marker = ++m_cursor;
7338  if ((m_limit - m_cursor) < 3)
7339  {
7340  yyfill(); // LCOV_EXCL_LINE;
7341  }
7342  yych = *m_cursor;
7343  if (yych <= 'D')
7344  {
7345  if (yych <= '/')
7346  {
7347  goto basic_json_parser_25;
7348  }
7349  if (yych <= '9')
7350  {
7351  goto basic_json_parser_48;
7352  }
7353  goto basic_json_parser_25;
7354  }
7355  else
7356  {
7357  if (yych <= 'E')
7358  {
7359  goto basic_json_parser_44;
7360  }
7361  if (yych == 'e')
7362  {
7363  goto basic_json_parser_44;
7364  }
7365  goto basic_json_parser_25;
7366  }
7367 basic_json_parser_50:
7368  yyaccept = 1;
7369  yych = *(m_marker = ++m_cursor);
7370  if (yych <= 'D')
7371  {
7372  if (yych == '.')
7373  {
7374  goto basic_json_parser_43;
7375  }
7376  goto basic_json_parser_25;
7377  }
7378  else
7379  {
7380  if (yych <= 'E')
7381  {
7382  goto basic_json_parser_44;
7383  }
7384  if (yych == 'e')
7385  {
7386  goto basic_json_parser_44;
7387  }
7388  goto basic_json_parser_25;
7389  }
7390 basic_json_parser_51:
7391  yych = *++m_cursor;
7392  if (yych != 'l')
7393  {
7394  goto basic_json_parser_33;
7395  }
7396  yych = *++m_cursor;
7397  if (yych != 's')
7398  {
7399  goto basic_json_parser_33;
7400  }
7401  yych = *++m_cursor;
7402  if (yych != 'e')
7403  {
7404  goto basic_json_parser_33;
7405  }
7406  ++m_cursor;
7407  {
7408  return token_type::literal_false;
7409  }
7410 basic_json_parser_56:
7411  yych = *++m_cursor;
7412  if (yych != 'u')
7413  {
7414  goto basic_json_parser_33;
7415  }
7416  yych = *++m_cursor;
7417  if (yych != 'e')
7418  {
7419  goto basic_json_parser_33;
7420  }
7421  ++m_cursor;
7422  {
7423  return token_type::literal_true;
7424  }
7425 basic_json_parser_60:
7426  yych = *++m_cursor;
7427  if (yych != 'l')
7428  {
7429  goto basic_json_parser_33;
7430  }
7431  yych = *++m_cursor;
7432  if (yych != 'l')
7433  {
7434  goto basic_json_parser_33;
7435  }
7436  ++m_cursor;
7437  {
7438  return token_type::literal_null;
7439  }
7440 basic_json_parser_64:
7441  yych = *++m_cursor;
7442  if (yych != 0xBF)
7443  {
7444  goto basic_json_parser_33;
7445  }
7446  ++m_cursor;
7447  {
7448  return scan();
7449  }
7450  }
7451 
7452 
7453  }
7454 
7456  void yyfill() noexcept
7457  {
7458  if (m_stream == nullptr or not * m_stream)
7459  {
7460  return;
7461  }
7462 
7463  const ssize_t offset_start = m_start - m_content;
7464  const ssize_t offset_marker = m_marker - m_start;
7465  const ssize_t offset_cursor = m_cursor - m_start;
7466 
7467  m_buffer.erase(0, static_cast<size_t>(offset_start));
7468  std::string line;
7469  assert(m_stream != nullptr);
7470  std::getline(*m_stream, line);
7471  m_buffer += "\n" + line; // add line with newline symbol
7472 
7473  m_content = reinterpret_cast<const lexer_char_t*>(m_buffer.c_str());
7474  assert(m_content != nullptr);
7475  m_start = m_content;
7476  m_marker = m_start + offset_marker;
7477  m_cursor = m_start + offset_cursor;
7478  m_limit = m_start + m_buffer.size() - 1;
7479  }
7480 
7482  string_t get_token() const noexcept
7483  {
7484  assert(m_start != nullptr);
7485  return string_t(reinterpret_cast<typename string_t::const_pointer>(m_start),
7486  static_cast<size_t>(m_cursor - m_start));
7487  }
7488 
7510  string_t get_string() const
7511  {
7512  string_t result;
7513  result.reserve(static_cast<size_t>(m_cursor - m_start - 2));
7514 
7515  // iterate the result between the quotes
7516  for (const lexer_char_t* i = m_start + 1; i < m_cursor - 1; ++i)
7517  {
7518  // process escaped characters
7519  if (*i == '\\')
7520  {
7521  // read next character
7522  ++i;
7523 
7524  switch (*i)
7525  {
7526  // the default escapes
7527  case 't':
7528  {
7529  result += "\t";
7530  break;
7531  }
7532  case 'b':
7533  {
7534  result += "\b";
7535  break;
7536  }
7537  case 'f':
7538  {
7539  result += "\f";
7540  break;
7541  }
7542  case 'n':
7543  {
7544  result += "\n";
7545  break;
7546  }
7547  case 'r':
7548  {
7549  result += "\r";
7550  break;
7551  }
7552  case '\\':
7553  {
7554  result += "\\";
7555  break;
7556  }
7557  case '/':
7558  {
7559  result += "/";
7560  break;
7561  }
7562  case '"':
7563  {
7564  result += "\"";
7565  break;
7566  }
7567 
7568  // unicode
7569  case 'u':
7570  {
7571  // get code xxxx from uxxxx
7572  auto codepoint = std::strtoul(std::string(reinterpret_cast<typename string_t::const_pointer>(i + 1),
7573  4).c_str(), nullptr, 16);
7574 
7575  // check if codepoint is a high surrogate
7576  if (codepoint >= 0xD800 and codepoint <= 0xDBFF)
7577  {
7578  // make sure there is a subsequent unicode
7579  if ((i + 6 >= m_limit) or * (i + 5) != '\\' or * (i + 6) != 'u')
7580  {
7581  throw std::invalid_argument("missing low surrogate");
7582  }
7583 
7584  // get code yyyy from uxxxx\uyyyy
7585  auto codepoint2 = std::strtoul(std::string(reinterpret_cast<typename string_t::const_pointer>
7586  (i + 7), 4).c_str(), nullptr, 16);
7587  result += to_unicode(codepoint, codepoint2);
7588  // skip the next 10 characters (xxxx\uyyyy)
7589  i += 10;
7590  }
7591  else
7592  {
7593  // add unicode character(s)
7594  result += to_unicode(codepoint);
7595  // skip the next four characters (xxxx)
7596  i += 4;
7597  }
7598  break;
7599  }
7600  }
7601  }
7602  else
7603  {
7604  // all other characters are just copied to the end of the
7605  // string
7606  result.append(1, static_cast<typename string_t::value_type>(*i));
7607  }
7608  }
7609 
7610  return result;
7611  }
7612 
7630  long double get_number() const
7631  {
7632  // conversion
7633  typename string_t::value_type* endptr;
7634  assert(m_start != nullptr);
7635  const auto float_val = std::strtold(reinterpret_cast<typename string_t::const_pointer>(m_start),
7636  &endptr);
7637 
7638  // return float_val if the whole number was translated and NAN
7639  // otherwise
7640  return (reinterpret_cast<lexer_char_t*>(endptr) == m_cursor) ? float_val : NAN;
7641  }
7642 
7643  private:
7645  std::istream* m_stream = nullptr;
7647  string_t m_buffer;
7649  const lexer_char_t* m_content = nullptr;
7651  const lexer_char_t* m_start = nullptr;
7653  const lexer_char_t* m_marker = nullptr;
7655  const lexer_char_t* m_cursor = nullptr;
7657  const lexer_char_t* m_limit = nullptr;
7658  };
7659 
7665  class parser
7666  {
7667  public:
7669  parser(const string_t& s, parser_callback_t cb = nullptr)
7670  : callback(cb), m_lexer(s)
7671  {
7672  // read first token
7673  get_token();
7674  }
7675 
7677  parser(std::istream& _is, parser_callback_t cb = nullptr)
7678  : callback(cb), m_lexer(&_is)
7679  {
7680  // read first token
7681  get_token();
7682  }
7683 
7685  basic_json parse()
7686  {
7687  basic_json result = parse_internal(true);
7688 
7689  expect(lexer::token_type::end_of_input);
7690 
7691  // return parser result and replace it with null in case the
7692  // top-level value was discarded by the callback function
7693  return result.is_discarded() ? basic_json() : result;
7694  }
7695 
7696  private:
7698  basic_json parse_internal(bool keep)
7699  {
7700  auto result = basic_json(value_t::discarded);
7701 
7702  switch (last_token)
7703  {
7704  case lexer::token_type::begin_object:
7705  {
7706  if (keep and (not callback or (keep = callback(depth++, parse_event_t::object_start, result))))
7707  {
7708  // explicitly set result to object to cope with {}
7709  result.m_type = value_t::object;
7710  result.m_value = json_value(value_t::object);
7711  }
7712 
7713  // read next token
7714  get_token();
7715 
7716  // closing } -> we are done
7717  if (last_token == lexer::token_type::end_object)
7718  {
7719  get_token();
7720  if (keep and callback and not callback(--depth, parse_event_t::object_end, result))
7721  {
7722  result = basic_json(value_t::discarded);
7723  }
7724  return result;
7725  }
7726 
7727  // no comma is expected here
7728  unexpect(lexer::token_type::value_separator);
7729 
7730  // otherwise: parse key-value pairs
7731  do
7732  {
7733  // ugly, but could be fixed with loop reorganization
7734  if (last_token == lexer::token_type::value_separator)
7735  {
7736  get_token();
7737  }
7738 
7739  // store key
7740  expect(lexer::token_type::value_string);
7741  const auto key = m_lexer.get_string();
7742 
7743  bool keep_tag = false;
7744  if (keep)
7745  {
7746  if (callback)
7747  {
7748  basic_json k(key);
7749  keep_tag = callback(depth, parse_event_t::key, k);
7750  }
7751  else
7752  {
7753  keep_tag = true;
7754  }
7755  }
7756 
7757  // parse separator (:)
7758  get_token();
7759  expect(lexer::token_type::name_separator);
7760 
7761  // parse and add value
7762  get_token();
7763  auto value = parse_internal(keep);
7764  if (keep and keep_tag and not value.is_discarded())
7765  {
7766  result[key] = std::move(value);
7767  }
7768  }
7769  while (last_token == lexer::token_type::value_separator);
7770 
7771  // closing }
7772  expect(lexer::token_type::end_object);
7773  get_token();
7774  if (keep and callback and not callback(--depth, parse_event_t::object_end, result))
7775  {
7776  result = basic_json(value_t::discarded);
7777  }
7778 
7779  return result;
7780  }
7781 
7782  case lexer::token_type::begin_array:
7783  {
7784  if (keep and (not callback or (keep = callback(depth++, parse_event_t::array_start, result))))
7785  {
7786  // explicitly set result to object to cope with []
7787  result.m_type = value_t::array;
7788  result.m_value = json_value(value_t::array);
7789  }
7790 
7791  // read next token
7792  get_token();
7793 
7794  // closing ] -> we are done
7795  if (last_token == lexer::token_type::end_array)
7796  {
7797  get_token();
7798  if (callback and not callback(--depth, parse_event_t::array_end, result))
7799  {
7800  result = basic_json(value_t::discarded);
7801  }
7802  return result;
7803  }
7804 
7805  // no comma is expected here
7806  unexpect(lexer::token_type::value_separator);
7807 
7808  // otherwise: parse values
7809  do
7810  {
7811  // ugly, but could be fixed with loop reorganization
7812  if (last_token == lexer::token_type::value_separator)
7813  {
7814  get_token();
7815  }
7816 
7817  // parse value
7818  auto value = parse_internal(keep);
7819  if (keep and not value.is_discarded())
7820  {
7821  result.push_back(std::move(value));
7822  }
7823  }
7824  while (last_token == lexer::token_type::value_separator);
7825 
7826  // closing ]
7827  expect(lexer::token_type::end_array);
7828  get_token();
7829  if (keep and callback and not callback(--depth, parse_event_t::array_end, result))
7830  {
7831  result = basic_json(value_t::discarded);
7832  }
7833 
7834  return result;
7835  }
7836 
7837  case lexer::token_type::literal_null:
7838  {
7839  get_token();
7840  result.m_type = value_t::null;
7841  break;
7842  }
7843 
7844  case lexer::token_type::value_string:
7845  {
7846  const auto s = m_lexer.get_string();
7847  get_token();
7848  result = basic_json(s);
7849  break;
7850  }
7851 
7852  case lexer::token_type::literal_true:
7853  {
7854  get_token();
7855  result.m_type = value_t::boolean;
7856  result.m_value = true;
7857  break;
7858  }
7859 
7860  case lexer::token_type::literal_false:
7861  {
7862  get_token();
7863  result.m_type = value_t::boolean;
7864  result.m_value = false;
7865  break;
7866  }
7867 
7868  case lexer::token_type::value_number:
7869  {
7870  auto float_val = m_lexer.get_number();
7871 
7872  // NAN is returned if token could not be translated
7873  // completely
7874  if (std::isnan(float_val))
7875  {
7876  throw std::invalid_argument(std::string("parse error - ") +
7877  m_lexer.get_token() + " is not a number");
7878  }
7879 
7880  get_token();
7881 
7882  // check if conversion loses precision
7883  const auto int_val = static_cast<number_integer_t>(float_val);
7884  if (approx(float_val, static_cast<long double>(int_val)))
7885  {
7886  // we would not lose precision -> return int
7887  result.m_type = value_t::number_integer;
7888  result.m_value = int_val;
7889  }
7890  else
7891  {
7892  // we would lose precision -> return float
7893  result.m_type = value_t::number_float;
7894  result.m_value = static_cast<number_float_t>(float_val);
7895  }
7896  break;
7897  }
7898 
7899  default:
7900  {
7901  // the last token was unexpected
7902  unexpect(last_token);
7903  }
7904  }
7905 
7906  if (keep and callback and not callback(depth, parse_event_t::value, result))
7907  {
7908  result = basic_json(value_t::discarded);
7909  }
7910  return result;
7911  }
7912 
7914  typename lexer::token_type get_token()
7915  {
7916  last_token = m_lexer.scan();
7917  return last_token;
7918  }
7919 
7920  void expect(typename lexer::token_type t) const
7921  {
7922  if (t != last_token)
7923  {
7924  std::string error_msg = "parse error - unexpected ";
7925  error_msg += (last_token == lexer::token_type::parse_error ? ("'" + m_lexer.get_token() + "'") :
7926  lexer::token_type_name(last_token));
7927  error_msg += "; expected " + lexer::token_type_name(t);
7928  throw std::invalid_argument(error_msg);
7929  }
7930  }
7931 
7932  void unexpect(typename lexer::token_type t) const
7933  {
7934  if (t == last_token)
7935  {
7936  std::string error_msg = "parse error - unexpected ";
7937  error_msg += (last_token == lexer::token_type::parse_error ? ("'" + m_lexer.get_token() + "'") :
7938  lexer::token_type_name(last_token));
7939  throw std::invalid_argument(error_msg);
7940  }
7941  }
7942 
7943  private:
7945  int depth = 0;
7947  parser_callback_t callback;
7949  typename lexer::token_type last_token = lexer::token_type::uninitialized;
7951  lexer m_lexer;
7952  };
7953 };
7954 
7955 
7957 // presets //
7959 
7969 }
7970 
7971 
7973 // nonmember functions //
7975 
7976 // specialization of std::swap, and std::hash
7977 namespace std
7978 {
7984 template <>
7985 inline void swap(nlohmann::json& j1,
7986  nlohmann::json& j2) noexcept(
7987  is_nothrow_move_constructible<nlohmann::json>::value and
7988  is_nothrow_move_assignable<nlohmann::json>::value
7989  )
7990 {
7991  j1.swap(j2);
7992 }
7993 
7995 template <>
7996 struct hash<nlohmann::json>
7997 {
8003  std::size_t operator()(const nlohmann::json& j) const
8004  {
8005  // a naive hashing via the string representation
8006  const auto& h = hash<nlohmann::json::string_t>();
8007  return h(j.dump());
8008  }
8009 };
8010 }
8011 
8024 inline nlohmann::json operator "" _json(const char* s, std::size_t)
8025 {
8026  return nlohmann::json::parse(reinterpret_cast<const nlohmann::json::string_t::value_type*>(s));
8027 }
8028 
8029 #endif
bool operator!=(const const_iterator &other) const
comparison: not equal
Definition: json.hpp:6025
iterator insert(const_iterator pos, basic_json &&val)
inserts element
Definition: json.hpp:4308
iterator operator++(int)
post-increment (it++)
Definition: json.hpp:6273
friend bool operator<=(const_reference lhs, const_reference rhs) noexcept
comparison: less than or equal
Definition: json.hpp:4919
typename std::allocator_traits< allocator_type >::pointer pointer
the type of an element pointer
Definition: json.hpp:228
json_reverse_iterator operator-(difference_type i) const
subtract from iterator
Definition: json.hpp:6428
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:1510
const_reference operator[](size_type idx) const
access specified array element
Definition: json.hpp:2870
reference operator[](const T(&key)[n])
access specified object element
Definition: json.hpp:3004
typename basic_json::const_pointer pointer
defines a pointer to the type iterated over (value_type)
Definition: json.hpp:5697
static iteration_proxy< iterator > iterator_wrapper(reference cont)
wrapper to access iterator member functions in range-based for
Definition: json.hpp:3842
const_iterator & operator--()
pre-decrement (–it)
Definition: json.hpp:5966
friend std::istream & operator>>(std::istream &i, basic_json &j)
deserialize from stream
Definition: json.hpp:5132
const_iterator & operator=(const_iterator other) noexcept( std::is_nothrow_move_constructible< pointer >::value and std::is_nothrow_move_assignable< pointer >::value and std::is_nothrow_move_constructible< internal_iterator >::value and std::is_nothrow_move_assignable< internal_iterator >::value )
copy assignment
Definition: json.hpp:5766
typename basic_json::value_type value_type
the type of the values when the iterator is dereferenced
Definition: json.hpp:5693
reference & operator=(basic_json other) noexcept( std::is_nothrow_move_constructible< value_t >::value and std::is_nothrow_move_assignable< value_t >::value and std::is_nothrow_move_constructible< json_value >::value and std::is_nothrow_move_assignable< json_value >::value )
copy assignment
Definition: json.hpp:1782
iterator insert(const_iterator pos, const_iterator first, const_iterator last)
inserts elements
Definition: json.hpp:4390
iterator insert(const_iterator pos, size_type cnt, const basic_json &val)
inserts elements
Definition: json.hpp:4337
json_reverse_iterator operator--(int)
post-decrement (it–)
Definition: json.hpp:6400
StringType string_t
a type for a string
Definition: json.hpp:434
void push_back(const typename object_t::value_type &val)
add an object to an object
Definition: json.hpp:4229
basic_json(boolean_t val)
create a boolean (explicit)
Definition: json.hpp:1132
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:1470
iterator & operator++()
pre-increment (++it)
Definition: json.hpp:6281
friend bool operator!=(const_reference lhs, const_reference rhs) noexcept
comparison: not equal
Definition: json.hpp:4775
ArrayType< basic_json, AllocatorType< basic_json >> array_t
a type for an array
Definition: json.hpp:387
const_iterator & operator++()
pre-increment (++it)
Definition: json.hpp:5929
difference_type operator-(const json_reverse_iterator &other) const
return difference
Definition: json.hpp:6436
basic_json<> json
default JSON class
Definition: json.hpp:7968
reference front()
access the first element
Definition: json.hpp:3173
bool is_array() const noexcept
return whether value is an array
Definition: json.hpp:2095
const_iterator find(typename object_t::key_type key) const
find an element in a JSON object
Definition: json.hpp:3553
std::reverse_iterator< Base > base_iterator
shortcut to the reverse iterator adaptor
Definition: json.hpp:6372
json_reverse_iterator(const typename base_iterator::iterator_type &it)
create reverse iterator from iterator
Definition: json.hpp:6377
a class to store JSON values
Definition: json.hpp:188
json_reverse_iterator & operator--()
pre-decrement (–it)
Definition: json.hpp:6406
basic_json(const object_t &val)
create an object (explicit)
Definition: json.hpp:934
friend bool operator==(std::nullptr_t, const_reference v) noexcept
comparison: equal
Definition: json.hpp:4754
void push_back(basic_json &&val)
add an object to an array
Definition: json.hpp:4143
const_iterator cbegin() const
returns a const iterator to the first element
Definition: json.hpp:3653
bool is_string() const noexcept
return whether value is a string
Definition: json.hpp:2114
iterator & operator+=(difference_type i)
add to iterator
Definition: json.hpp:6303
const PointerType get_ptr() const noexcept
get a pointer value (implicit)
Definition: json.hpp:2560
basic_json(const CompatibleStringType &val)
create a string (implicit)
Definition: json.hpp:1114
reference operator+=(basic_json &&val)
add an object to an array
Definition: json.hpp:4169
basic_json(size_type cnt, const basic_json &val)
construct an array with count copies of given value
Definition: json.hpp:1534
a mutable random access iterator for the basic_json class
Definition: json.hpp:6228
iterator & operator-=(difference_type i)
subtract from iterator
Definition: json.hpp:6310
static basic_json parse(std::istream &&i, parser_callback_t cb=nullptr)
deserialize from stream
Definition: json.hpp:5094
reference operator[](const typename object_t::key_type &key)
access specified object element
Definition: json.hpp:2911
STL namespace.
difference_type operator-(const iterator &other) const
Definition: json.hpp:6332
reference value() const
return the value of an iterator
Definition: json.hpp:6204
static iteration_proxy< const_iterator > iterator_wrapper(const_reference cont)
wrapper to access iterator member functions in range-based for
Definition: json.hpp:3850
const_iterator end() const
returns a const iterator to one past the last element
Definition: json.hpp:3688
const_iterator(const const_iterator &other) noexcept
copy constructor
Definition: json.hpp:5761
reference at(const typename object_t::key_type &key)
access specified object element with bounds checking
Definition: json.hpp:2730
object_t::key_type key() const
return the key of an object iterator
Definition: json.hpp:6189
iterator end()
returns an iterator to one past the last element
Definition: json.hpp:3678
ObjectType< StringType, basic_json, std::less< StringType >, AllocatorType< std::pair< const StringType, basic_json >>> object_t
a type for an object
Definition: json.hpp:341
reference operator*()
return a reference to the value pointed to by the iterator
Definition: json.hpp:6261
reverse_iterator rend()
returns an iterator to the reverse-end
Definition: json.hpp:3767
bool is_object() const noexcept
return whether value is an object
Definition: json.hpp:2076
const_iterator operator-(difference_type i)
subtract from iterator
Definition: json.hpp:6121
bool is_discarded() const noexcept
return whether value is discarded
Definition: json.hpp:2138
basic_json(const CompatibleArrayType &val)
create an array (implicit)
Definition: json.hpp:1030
typename basic_json::const_reference reference
defines a reference to the type iterated over (value_type)
Definition: json.hpp:5699
const_reverse_iterator rend() const
returns a const reverse iterator to one before the first
Definition: json.hpp:3775
size_type erase(const typename object_t::key_type &key)
remove element from a JSON object given a key
Definition: json.hpp:3462
bool is_boolean() const noexcept
return whether value is a boolean
Definition: json.hpp:1987
iterator begin()
returns an iterator to the first element
Definition: json.hpp:3619
const_reference at(const typename object_t::key_type &key) const
access specified object element with bounds checking
Definition: json.hpp:2778
reference operator+=(const basic_json &val)
add an object to an array
Definition: json.hpp:4203
AllocatorType< basic_json > allocator_type
the allocator type
Definition: json.hpp:225
basic_json(const number_float_t val)
create a floating-point number (explicit)
Definition: json.hpp:1259
bool is_number_integer() const noexcept
return whether value is an integer number
Definition: json.hpp:2034
iterator operator+(difference_type i)
add to iterator
Definition: json.hpp:6317
std::function< bool(int depth, parse_event_t event, basic_json &parsed)> parser_callback_t
per-element parser callback type
Definition: json.hpp:820
basic_json(const typename string_t::value_type *val)
create a string (explicit)
Definition: json.hpp:1083
iterator find(typename object_t::key_type key)
find an element in a JSON object
Definition: json.hpp:3536
basic_json(const value_t value_type)
create an empty value with a given type
Definition: json.hpp:867
friend bool operator>=(const_reference lhs, const_reference rhs) noexcept
comparison: greater than or equal
Definition: json.hpp:4963
iterator & operator--()
pre-decrement (–it)
Definition: json.hpp:6296
friend bool operator<(const_reference lhs, const_reference rhs) noexcept
comparison: less than
Definition: json.hpp:4836
pointer operator->() const
dereference the iterator
Definition: json.hpp:5886
const_reference operator[](const typename object_t::key_type &key) const
read-only access specified object element
Definition: json.hpp:2959
const_iterator cend() const
returns a const iterator to one past the last element
Definition: json.hpp:3712
typename Base::reference reference
the reference type for the pointed-to element
Definition: json.hpp:6374
size_type size() const noexcept
returns the number of elements
Definition: json.hpp:3952
static allocator_type get_allocator()
returns the allocator associated with the container
Definition: json.hpp:250
object (unordered set of name/value pairs)
reference at(size_type idx)
access specified array element with bounds checking
Definition: json.hpp:2638
json_reverse_iterator(const base_iterator &it)
create reverse iterator from base class
Definition: json.hpp:6382
value_t type() const noexcept
return the type of the JSON value (explicit)
Definition: json.hpp:1908
friend std::ostream & operator>>(const basic_json &j, std::ostream &o)
serialize to stream
Definition: json.hpp:5018
ValueType value(const typename object_t::key_type &key, ValueType default_value) const
access specified object element with default value
Definition: json.hpp:3122
object_t::key_type key() const
return the key of an object iterator
Definition: json.hpp:6448
bool is_structured() const noexcept
return whether type is structured
Definition: json.hpp:1949
namespace for Niels Lohmann
Definition: json.hpp:79
typename basic_json::difference_type difference_type
a type to represent differences between iterators
Definition: json.hpp:5695
void swap(array_t &other)
exchanges the values
Definition: json.hpp:4517
reverse_iterator rbegin()
returns an iterator to the reverse-beginning
Definition: json.hpp:3736
reference operator+=(const typename object_t::value_type &val)
add an object to an object
Definition: json.hpp:4253
basic_json(const number_integer_t val)
create an integer number (explicit)
Definition: json.hpp:1166
reference operator[](difference_type n) const
access to successor
Definition: json.hpp:6338
std::size_t size_type
a type to represent container sizes
Definition: json.hpp:222
const_reverse_iterator rbegin() const
returns a const reverse iterator to the last element
Definition: json.hpp:3744
~basic_json()
destructor
Definition: json.hpp:1808
basic_json(const basic_json &other)
copy constructor
Definition: json.hpp:1683
const_iterator operator+(difference_type i)
add to iterator
Definition: json.hpp:6113
value_t
the JSON type enumeration
Definition: json.hpp:612
const value_type & const_reference
the type of an element const reference
Definition: json.hpp:216
basic_json(const CompatibleNumberIntegerType val) noexcept
create an integer number (implicit)
Definition: json.hpp:1230
bool is_null() const noexcept
return whether value is null
Definition: json.hpp:1968
void swap(string_t &other)
exchanges the values
Definition: json.hpp:4585
reference value() const
return the value of an iterator
Definition: json.hpp:6344
const_iterator operator--(int)
post-decrement (it–)
Definition: json.hpp:5958
ValueType get() const
get a value (explicit)
Definition: json.hpp:2461
void erase(const size_type idx)
remove element from a JSON array given an index
Definition: json.hpp:3500
void clear() noexcept
clears the contents
Definition: json.hpp:4073
pointer operator->()
dereference the iterator
Definition: json.hpp:6267
basic_json value_type
the type of elements in a basic_json container
Definition: json.hpp:210
array (ordered collection of values)
const_reference front() const
access the first element
Definition: json.hpp:3181
bool operator>=(const const_iterator &other) const
comparison: greater than or equal
Definition: json.hpp:6073
iterator insert(const_iterator pos, std::initializer_list< basic_json > ilist)
inserts elements
Definition: json.hpp:4448
std::ptrdiff_t difference_type
a type to represent differences between iterators
Definition: json.hpp:219
const_iterator & operator+=(difference_type i)
add to iterator
Definition: json.hpp:6079
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:1378
difference_type operator-(const const_iterator &other) const
return difference
Definition: json.hpp:6129
friend bool operator==(const_reference lhs, const_reference rhs) noexcept
comparison: equal
Definition: json.hpp:4665
bool is_number() const noexcept
return whether value is a number
Definition: json.hpp:2011
BooleanType boolean_t
a type for a boolean
Definition: json.hpp:460
const_reverse_iterator crend() const
returns a const reverse iterator to one before the first
Definition: json.hpp:3821
bool empty() const noexcept
checks whether the container is empty
Definition: json.hpp:3894
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:3148
void swap(reference other) noexcept( std::is_nothrow_move_constructible< value_t >::value and std::is_nothrow_move_assignable< value_t >::value and std::is_nothrow_move_constructible< json_value >::value and std::is_nothrow_move_assignable< json_value >::value )
exchanges the values
Definition: json.hpp:4486
const_reverse_iterator crbegin() const
returns a const reverse iterator to the last element
Definition: json.hpp:3798
reference value() const
return the value of an iterator
Definition: json.hpp:6455
const_iterator(pointer object)
constructor for a given JSON instance
Definition: json.hpp:5707
friend bool operator<(const value_t lhs, const value_t rhs)
comparison operator for JSON types
Definition: json.hpp:4619
iterator(pointer object) noexcept
constructor for a given JSON instance
Definition: json.hpp:6239
bool operator<(const const_iterator &other) const
comparison: smaller
Definition: json.hpp:6031
string_t dump(const int indent=-1) const
serialization
Definition: json.hpp:1877
friend bool operator!=(const_reference v, std::nullptr_t) noexcept
comparison: not equal
Definition: json.hpp:4798
const_iterator & operator-=(difference_type i)
subtract from iterator
Definition: json.hpp:6107
basic_json(const int val)
create an integer number from an enum type (explicit)
Definition: json.hpp:1195
basic_json(const array_t &val)
create an array (explicit)
Definition: json.hpp:993
static basic_json parse(const string_t &s, parser_callback_t cb=nullptr)
deserialize from string
Definition: json.hpp:5057
InteratorType erase(InteratorType first, InteratorType last)
remove elements given an iterator range
Definition: json.hpp:3379
json_reverse_iterator operator++(int)
post-increment (it++)
Definition: json.hpp:6387
PointerType get_ptr() noexcept
get a pointer value (implicit)
Definition: json.hpp:2545
const_iterator(const iterator &other)
copy constructor given a nonconst iterator
Definition: json.hpp:5734
friend bool operator!=(std::nullptr_t, const_reference v) noexcept
comparison: not equal
Definition: json.hpp:4807
InteratorType erase(InteratorType pos)
remove element given an iterator
Definition: json.hpp:3274
bool operator<=(const const_iterator &other) const
comparison: less than or equal
Definition: json.hpp:6061
basic_json(const CompatibleNumberFloatType val) noexcept
create an floating-point number (implicit)
Definition: json.hpp:1305
reference back()
access the last element
Definition: json.hpp:3207
bool is_number_float() const noexcept
return whether value is a floating-point number
Definition: json.hpp:2057
const_iterator operator++(int)
post-increment (it++)
Definition: json.hpp:5921
typename std::allocator_traits< allocator_type >::const_pointer const_pointer
the type of an element const pointer
Definition: json.hpp:230
basic_json(const string_t &val)
create a string (explicit)
Definition: json.hpp:1059
iterator(const iterator &other) noexcept
copy constructor
Definition: json.hpp:6244
const_reference back() const
access the last element
Definition: json.hpp:3217
basic_json(InputIT first, InputIT last)
construct a JSON container given an iterator range
Definition: json.hpp:1580
static basic_json parse(std::istream &i, parser_callback_t cb=nullptr)
deserialize from stream
Definition: json.hpp:5086
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:3584
size_type max_size() const noexcept
returns the maximum possible number of elements
Definition: json.hpp:4014
void push_back(const basic_json &val)
add an object to an array
Definition: json.hpp:4179
bool operator==(const const_iterator &other) const
comparison: equal
Definition: json.hpp:5995
json_reverse_iterator & operator++()
pre-increment (++it)
Definition: json.hpp:6393
basic_json(std::nullptr_t) noexcept
create a null object (explicitly)
Definition: json.hpp:911
bool operator>(const const_iterator &other) const
comparison: greater than
Definition: json.hpp:6067
friend bool operator>(const_reference lhs, const_reference rhs) noexcept
comparison: greater than
Definition: json.hpp:4941
basic_json(basic_json &&other) noexcept
move constructor
Definition: json.hpp:1752
const_reference operator[](const T(&key)[n]) const
read-only access specified object element
Definition: json.hpp:3055
const_iterator begin() const
returns a const iterator to the first element
Definition: json.hpp:3629
const_reference at(size_type idx) const
access specified array element with bounds checking
Definition: json.hpp:2682
json_reverse_iterator & operator+=(difference_type i)
add to iterator
Definition: json.hpp:6413
a const random access iterator for the basic_json class
Definition: json.hpp:5686
a template for a reverse iterator class
Definition: json.hpp:233
void swap(object_t &other)
exchanges the values
Definition: json.hpp:4551
std::bidirectional_iterator_tag iterator_category
the category of the iterator
Definition: json.hpp:5701
bool is_primitive() const noexcept
return whether type is primitive
Definition: json.hpp:1929
iterator insert(const_iterator pos, const basic_json &val)
inserts element
Definition: json.hpp:4281
friend bool operator==(const_reference v, std::nullptr_t) noexcept
comparison: equal
Definition: json.hpp:4745
reference operator[](difference_type n) const
access to successor
Definition: json.hpp:6442
NumberIntegerType number_integer_t
a type for a number (integer)
Definition: json.hpp:528
reference operator[](difference_type n) const
access to successor
Definition: json.hpp:6153
reference operator*() const
return a reference to the value pointed to by the iterator
Definition: json.hpp:5846
value_type & reference
the type of an element reference
Definition: json.hpp:213
friend std::istream & operator<<(basic_json &j, std::istream &i)
deserialize from stream
Definition: json.hpp:5122
NumberFloatType number_float_t
a type for a number (floating-point)
Definition: json.hpp:593
std::size_t operator()(const nlohmann::json &j) const
return a hash value for a JSON object
Definition: json.hpp:8003
friend std::ostream & operator<<(std::ostream &o, const basic_json &j)
serialize to stream
Definition: json.hpp:5000
iterator & operator=(iterator other) noexcept( std::is_nothrow_move_constructible< pointer >::value and std::is_nothrow_move_assignable< pointer >::value and std::is_nothrow_move_constructible< internal_iterator >::value and std::is_nothrow_move_assignable< internal_iterator >::value )
copy assignment
Definition: json.hpp:6249
basic_json(const CompatibleObjectType &val)
create an object (implicit)
Definition: json.hpp:966
reference operator[](size_type idx)
access specified array element
Definition: json.hpp:2825
iterator operator--(int)
post-decrement (it–)
Definition: json.hpp:6288
json_reverse_iterator operator+(difference_type i) const
add to iterator
Definition: json.hpp:6420
parse_event_t
JSON callback events.
Definition: json.hpp:755
iterator operator-(difference_type i)
subtract from iterator
Definition: json.hpp:6325