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 
2430  template<typename ReferenceType, typename ThisType>
2431  static ReferenceType get_ref_impl(ThisType& obj)
2432  {
2433  // delegate the call to get_ptr<>()
2434  using PointerType = typename std::add_pointer<ReferenceType>::type;
2435  auto ptr = obj.template get_ptr<PointerType>();
2436 
2437  if (ptr != nullptr)
2438  {
2439  return *ptr;
2440  }
2441  else
2442  {
2443  throw std::domain_error("incompatible ReferenceType for get_ref, actual type is " +
2444  obj.type_name());
2445  }
2446  }
2447 
2448  public:
2449 
2452 
2486  template<typename ValueType, typename
2487  std::enable_if<
2488  not std::is_pointer<ValueType>::value
2489  , int>::type = 0>
2490  ValueType get() const
2491  {
2492  return get_impl(static_cast<ValueType*>(nullptr));
2493  }
2494 
2521  template<typename PointerType, typename
2522  std::enable_if<
2523  std::is_pointer<PointerType>::value
2524  , int>::type = 0>
2525  PointerType get() noexcept
2526  {
2527  // delegate the call to get_ptr
2528  return get_ptr<PointerType>();
2529  }
2530 
2535  template<typename PointerType, typename
2536  std::enable_if<
2537  std::is_pointer<PointerType>::value
2538  , int>::type = 0>
2539  const PointerType get() const noexcept
2540  {
2541  // delegate the call to get_ptr
2542  return get_ptr<PointerType>();
2543  }
2544 
2570  template<typename PointerType, typename
2571  std::enable_if<
2572  std::is_pointer<PointerType>::value
2573  , int>::type = 0>
2574  PointerType get_ptr() noexcept
2575  {
2576  // delegate the call to get_impl_ptr<>()
2577  return get_impl_ptr(static_cast<PointerType>(nullptr));
2578  }
2579 
2584  template<typename PointerType, typename
2585  std::enable_if<
2586  std::is_pointer<PointerType>::value
2587  and std::is_const<typename std::remove_pointer<PointerType>::type>::value
2588  , int>::type = 0>
2589  const PointerType get_ptr() const noexcept
2590  {
2591  // delegate the call to get_impl_ptr<>() const
2592  return get_impl_ptr(static_cast<const PointerType>(nullptr));
2593  }
2594 
2621  template<typename ReferenceType, typename
2622  std::enable_if<
2623  std::is_reference<ReferenceType>::value
2624  , int>::type = 0>
2625  ReferenceType get_ref()
2626  {
2627  // delegate call to get_ref_impl
2628  return get_ref_impl<ReferenceType>(*this);
2629  }
2630 
2635  template<typename ReferenceType, typename
2636  std::enable_if<
2637  std::is_reference<ReferenceType>::value
2638  and std::is_const<typename std::remove_reference<ReferenceType>::type>::value
2639  , int>::type = 0>
2640  ReferenceType get_ref() const
2641  {
2642  // delegate call to get_ref_impl
2643  return get_ref_impl<ReferenceType>(*this);
2644  }
2645 
2674  template < typename ValueType, typename
2675  std::enable_if <
2676  not std::is_pointer<ValueType>::value
2677  and not std::is_same<ValueType, typename string_t::value_type>::value
2678 #ifndef _MSC_VER // Fix for issue #167 operator<< abiguity under VS2015
2679  and not std::is_same<ValueType, std::initializer_list<typename string_t::value_type>>::value
2680 #endif
2681  , int >::type = 0 >
2682  operator ValueType() const
2683  {
2684  // delegate the call to get<>() const
2685  return get<ValueType>();
2686  }
2687 
2689 
2690 
2692  // element access //
2694 
2697 
2721  {
2722  // at only works for arrays
2723  if (is_array())
2724  {
2725  try
2726  {
2727  assert(m_value.array != nullptr);
2728  return m_value.array->at(idx);
2729  }
2730  catch (std::out_of_range&)
2731  {
2732  // create better exception explanation
2733  throw std::out_of_range("array index " + std::to_string(idx) + " is out of range");
2734  }
2735  }
2736  else
2737  {
2738  throw std::domain_error("cannot use at() with " + type_name());
2739  }
2740  }
2741 
2765  {
2766  // at only works for arrays
2767  if (is_array())
2768  {
2769  try
2770  {
2771  assert(m_value.array != nullptr);
2772  return m_value.array->at(idx);
2773  }
2774  catch (std::out_of_range&)
2775  {
2776  // create better exception explanation
2777  throw std::out_of_range("array index " + std::to_string(idx) + " is out of range");
2778  }
2779  }
2780  else
2781  {
2782  throw std::domain_error("cannot use at() with " + type_name());
2783  }
2784  }
2785 
2812  reference at(const typename object_t::key_type& key)
2813  {
2814  // at only works for objects
2815  if (is_object())
2816  {
2817  try
2818  {
2819  assert(m_value.object != nullptr);
2820  return m_value.object->at(key);
2821  }
2822  catch (std::out_of_range&)
2823  {
2824  // create better exception explanation
2825  throw std::out_of_range("key '" + key + "' not found");
2826  }
2827  }
2828  else
2829  {
2830  throw std::domain_error("cannot use at() with " + type_name());
2831  }
2832  }
2833 
2860  const_reference at(const typename object_t::key_type& key) const
2861  {
2862  // at only works for objects
2863  if (is_object())
2864  {
2865  try
2866  {
2867  assert(m_value.object != nullptr);
2868  return m_value.object->at(key);
2869  }
2870  catch (std::out_of_range&)
2871  {
2872  // create better exception explanation
2873  throw std::out_of_range("key '" + key + "' not found");
2874  }
2875  }
2876  else
2877  {
2878  throw std::domain_error("cannot use at() with " + type_name());
2879  }
2880  }
2881 
2908  {
2909  // implicitly convert null to object
2910  if (is_null())
2911  {
2912  m_type = value_t::array;
2913  m_value.array = create<array_t>();
2914  }
2915 
2916  // [] only works for arrays
2917  if (is_array())
2918  {
2919  assert(m_value.array != nullptr);
2920  for (size_t i = m_value.array->size(); i <= idx; ++i)
2921  {
2922  m_value.array->push_back(basic_json());
2923  }
2924 
2925  return m_value.array->operator[](idx);
2926  }
2927  else
2928  {
2929  throw std::domain_error("cannot use operator[] with " + type_name());
2930  }
2931  }
2932 
2953  {
2954  // at only works for arrays
2955  if (is_array())
2956  {
2957  assert(m_value.array != nullptr);
2958  return m_value.array->operator[](idx);
2959  }
2960  else
2961  {
2962  throw std::domain_error("cannot use operator[] with " + type_name());
2963  }
2964  }
2965 
2993  reference operator[](const typename object_t::key_type& key)
2994  {
2995  // implicitly convert null to object
2996  if (is_null())
2997  {
2998  m_type = value_t::object;
2999  m_value.object = create<object_t>();
3000  }
3001 
3002  // [] only works for objects
3003  if (is_object())
3004  {
3005  assert(m_value.object != nullptr);
3006  return m_value.object->operator[](key);
3007  }
3008  else
3009  {
3010  throw std::domain_error("cannot use operator[] with " + type_name());
3011  }
3012  }
3013 
3041  const_reference operator[](const typename object_t::key_type& key) const
3042  {
3043  // [] only works for objects
3044  if (is_object())
3045  {
3046  assert(m_value.object != nullptr);
3047  assert(m_value.object->find(key) != m_value.object->end());
3048  return m_value.object->find(key)->second;
3049  }
3050  else
3051  {
3052  throw std::domain_error("cannot use operator[] with " + type_name());
3053  }
3054  }
3055 
3083  template<typename T, std::size_t n>
3084  reference operator[](T * (&key)[n])
3085  {
3086  return operator[](static_cast<const T>(key));
3087  }
3088 
3118  template<typename T, std::size_t n>
3119  const_reference operator[](T * (&key)[n]) const
3120  {
3121  return operator[](static_cast<const T>(key));
3122  }
3123 
3151  template<typename T>
3153  {
3154  // implicitly convert null to object
3155  if (is_null())
3156  {
3157  m_type = value_t::object;
3158  m_value = value_t::object;
3159  }
3160 
3161  // at only works for objects
3162  if (is_object())
3163  {
3164  assert(m_value.object != nullptr);
3165  return m_value.object->operator[](key);
3166  }
3167  else
3168  {
3169  throw std::domain_error("cannot use operator[] with " + type_name());
3170  }
3171  }
3172 
3200  template<typename T>
3202  {
3203  // at only works for objects
3204  if (is_object())
3205  {
3206  assert(m_value.object != nullptr);
3207  assert(m_value.object->find(key) != m_value.object->end());
3208  return m_value.object->find(key)->second;
3209  }
3210  else
3211  {
3212  throw std::domain_error("cannot use operator[] with " + type_name());
3213  }
3214  }
3215 
3264  template <class ValueType, typename
3265  std::enable_if<
3266  std::is_convertible<basic_json_t, ValueType>::value
3267  , int>::type = 0>
3268  ValueType value(const typename object_t::key_type& key, ValueType default_value) const
3269  {
3270  // at only works for objects
3271  if (is_object())
3272  {
3273  // if key is found, return value and given default value otherwise
3274  const auto it = find(key);
3275  if (it != end())
3276  {
3277  return *it;
3278  }
3279  else
3280  {
3281  return default_value;
3282  }
3283  }
3284  else
3285  {
3286  throw std::domain_error("cannot use value() with " + type_name());
3287  }
3288  }
3289 
3294  string_t value(const typename object_t::key_type& key, const char* default_value) const
3295  {
3296  return value(key, string_t(default_value));
3297  }
3298 
3320  {
3321  return *begin();
3322  }
3323 
3328  {
3329  return *cbegin();
3330  }
3331 
3354  {
3355  auto tmp = end();
3356  --tmp;
3357  return *tmp;
3358  }
3359 
3364  {
3365  auto tmp = cend();
3366  --tmp;
3367  return *tmp;
3368  }
3369 
3414  template <class InteratorType, typename
3415  std::enable_if<
3416  std::is_same<InteratorType, typename basic_json_t::iterator>::value or
3417  std::is_same<InteratorType, typename basic_json_t::const_iterator>::value
3418  , int>::type
3419  = 0>
3420  InteratorType erase(InteratorType pos)
3421  {
3422  // make sure iterator fits the current value
3423  if (this != pos.m_object)
3424  {
3425  throw std::domain_error("iterator does not fit current value");
3426  }
3427 
3428  InteratorType result = end();
3429 
3430  switch (m_type)
3431  {
3432  case value_t::boolean:
3433  case value_t::number_float:
3434  case value_t::number_integer:
3435  case value_t::string:
3436  {
3437  if (not pos.m_it.primitive_iterator.is_begin())
3438  {
3439  throw std::out_of_range("iterator out of range");
3440  }
3441 
3442  if (is_string())
3443  {
3444  delete m_value.string;
3445  m_value.string = nullptr;
3446  }
3447 
3448  m_type = value_t::null;
3449  break;
3450  }
3451 
3452  case value_t::object:
3453  {
3454  assert(m_value.object != nullptr);
3455  result.m_it.object_iterator = m_value.object->erase(pos.m_it.object_iterator);
3456  break;
3457  }
3458 
3459  case value_t::array:
3460  {
3461  assert(m_value.array != nullptr);
3462  result.m_it.array_iterator = m_value.array->erase(pos.m_it.array_iterator);
3463  break;
3464  }
3465 
3466  default:
3467  {
3468  throw std::domain_error("cannot use erase() with " + type_name());
3469  }
3470  }
3471 
3472  return result;
3473  }
3474 
3519  template <class InteratorType, typename
3520  std::enable_if<
3521  std::is_same<InteratorType, typename basic_json_t::iterator>::value or
3522  std::is_same<InteratorType, typename basic_json_t::const_iterator>::value
3523  , int>::type
3524  = 0>
3525  InteratorType erase(InteratorType first, InteratorType last)
3526  {
3527  // make sure iterator fits the current value
3528  if (this != first.m_object or this != last.m_object)
3529  {
3530  throw std::domain_error("iterators do not fit current value");
3531  }
3532 
3533  InteratorType result = end();
3534 
3535  switch (m_type)
3536  {
3537  case value_t::boolean:
3538  case value_t::number_float:
3539  case value_t::number_integer:
3540  case value_t::string:
3541  {
3542  if (not first.m_it.primitive_iterator.is_begin() or not last.m_it.primitive_iterator.is_end())
3543  {
3544  throw std::out_of_range("iterators out of range");
3545  }
3546 
3547  if (is_string())
3548  {
3549  delete m_value.string;
3550  m_value.string = nullptr;
3551  }
3552 
3553  m_type = value_t::null;
3554  break;
3555  }
3556 
3557  case value_t::object:
3558  {
3559  assert(m_value.object != nullptr);
3560  result.m_it.object_iterator = m_value.object->erase(first.m_it.object_iterator,
3561  last.m_it.object_iterator);
3562  break;
3563  }
3564 
3565  case value_t::array:
3566  {
3567  assert(m_value.array != nullptr);
3568  result.m_it.array_iterator = m_value.array->erase(first.m_it.array_iterator,
3569  last.m_it.array_iterator);
3570  break;
3571  }
3572 
3573  default:
3574  {
3575  throw std::domain_error("cannot use erase() with " + type_name());
3576  }
3577  }
3578 
3579  return result;
3580  }
3581 
3608  size_type erase(const typename object_t::key_type& key)
3609  {
3610  // this erase only works for objects
3611  if (is_object())
3612  {
3613  assert(m_value.object != nullptr);
3614  return m_value.object->erase(key);
3615  }
3616  else
3617  {
3618  throw std::domain_error("cannot use erase() with " + type_name());
3619  }
3620  }
3621 
3646  void erase(const size_type idx)
3647  {
3648  // this erase only works for arrays
3649  if (is_array())
3650  {
3651  if (idx >= size())
3652  {
3653  throw std::out_of_range("index out of range");
3654  }
3655 
3656  assert(m_value.array != nullptr);
3657  m_value.array->erase(m_value.array->begin() + static_cast<difference_type>(idx));
3658  }
3659  else
3660  {
3661  throw std::domain_error("cannot use erase() with " + type_name());
3662  }
3663  }
3664 
3682  iterator find(typename object_t::key_type key)
3683  {
3684  auto result = end();
3685 
3686  if (is_object())
3687  {
3688  assert(m_value.object != nullptr);
3689  result.m_it.object_iterator = m_value.object->find(key);
3690  }
3691 
3692  return result;
3693  }
3694 
3699  const_iterator find(typename object_t::key_type key) const
3700  {
3701  auto result = cend();
3702 
3703  if (is_object())
3704  {
3705  assert(m_value.object != nullptr);
3706  result.m_it.object_iterator = m_value.object->find(key);
3707  }
3708 
3709  return result;
3710  }
3711 
3730  size_type count(typename object_t::key_type key) const
3731  {
3732  // return 0 for all nonobject types
3733  assert(not is_object() or m_value.object != nullptr);
3734  return is_object() ? m_value.object->count(key) : 0;
3735  }
3736 
3738 
3739 
3741  // iterators //
3743 
3746 
3766  {
3767  iterator result(this);
3768  result.set_begin();
3769  return result;
3770  }
3771 
3776  {
3777  return cbegin();
3778  }
3779 
3800  {
3801  const_iterator result(this);
3802  result.set_begin();
3803  return result;
3804  }
3805 
3825  {
3826  iterator result(this);
3827  result.set_end();
3828  return result;
3829  }
3830 
3835  {
3836  return cend();
3837  }
3838 
3859  {
3860  const_iterator result(this);
3861  result.set_end();
3862  return result;
3863  }
3864 
3883  {
3884  return reverse_iterator(end());
3885  }
3886 
3891  {
3892  return crbegin();
3893  }
3894 
3914  {
3915  return reverse_iterator(begin());
3916  }
3917 
3922  {
3923  return crend();
3924  }
3925 
3945  {
3946  return const_reverse_iterator(cend());
3947  }
3948 
3968  {
3969  return const_reverse_iterator(cbegin());
3970  }
3971 
3972  private:
3973  // forward declaration
3974  template<typename IteratorType> class iteration_proxy;
3975 
3976  public:
3988  static iteration_proxy<iterator> iterator_wrapper(reference cont)
3989  {
3990  return iteration_proxy<iterator>(cont);
3991  }
3992 
3996  static iteration_proxy<const_iterator> iterator_wrapper(const_reference cont)
3997  {
3998  return iteration_proxy<const_iterator>(cont);
3999  }
4000 
4002 
4003 
4005  // capacity //
4007 
4010 
4040  bool empty() const noexcept
4041  {
4042  switch (m_type)
4043  {
4044  case value_t::null:
4045  {
4046  // null values are empty
4047  return true;
4048  }
4049 
4050  case value_t::array:
4051  {
4052  assert(m_value.array != nullptr);
4053  return m_value.array->empty();
4054  }
4055 
4056  case value_t::object:
4057  {
4058  assert(m_value.object != nullptr);
4059  return m_value.object->empty();
4060  }
4061 
4062  default:
4063  {
4064  // all other types are nonempty
4065  return false;
4066  }
4067  }
4068  }
4069 
4098  size_type size() const noexcept
4099  {
4100  switch (m_type)
4101  {
4102  case value_t::null:
4103  {
4104  // null values are empty
4105  return 0;
4106  }
4107 
4108  case value_t::array:
4109  {
4110  assert(m_value.array != nullptr);
4111  return m_value.array->size();
4112  }
4113 
4114  case value_t::object:
4115  {
4116  assert(m_value.object != nullptr);
4117  return m_value.object->size();
4118  }
4119 
4120  default:
4121  {
4122  // all other types have size 1
4123  return 1;
4124  }
4125  }
4126  }
4127 
4160  size_type max_size() const noexcept
4161  {
4162  switch (m_type)
4163  {
4164  case value_t::array:
4165  {
4166  assert(m_value.array != nullptr);
4167  return m_value.array->max_size();
4168  }
4169 
4170  case value_t::object:
4171  {
4172  assert(m_value.object != nullptr);
4173  return m_value.object->max_size();
4174  }
4175 
4176  default:
4177  {
4178  // all other types have max_size() == size()
4179  return size();
4180  }
4181  }
4182  }
4183 
4185 
4186 
4188  // modifiers //
4190 
4193 
4219  void clear() noexcept
4220  {
4221  switch (m_type)
4222  {
4223  case value_t::number_integer:
4224  {
4225  m_value.number_integer = 0;
4226  break;
4227  }
4228 
4229  case value_t::number_float:
4230  {
4231  m_value.number_float = 0.0;
4232  break;
4233  }
4234 
4235  case value_t::boolean:
4236  {
4237  m_value.boolean = false;
4238  break;
4239  }
4240 
4241  case value_t::string:
4242  {
4243  assert(m_value.string != nullptr);
4244  m_value.string->clear();
4245  break;
4246  }
4247 
4248  case value_t::array:
4249  {
4250  assert(m_value.array != nullptr);
4251  m_value.array->clear();
4252  break;
4253  }
4254 
4255  case value_t::object:
4256  {
4257  assert(m_value.object != nullptr);
4258  m_value.object->clear();
4259  break;
4260  }
4261 
4262  default:
4263  {
4264  break;
4265  }
4266  }
4267  }
4268 
4289  void push_back(basic_json&& val)
4290  {
4291  // push_back only works for null objects or arrays
4292  if (not(is_null() or is_array()))
4293  {
4294  throw std::domain_error("cannot use push_back() with " + type_name());
4295  }
4296 
4297  // transform null object into an array
4298  if (is_null())
4299  {
4300  m_type = value_t::array;
4301  m_value = value_t::array;
4302  }
4303 
4304  // add element to array (move semantics)
4305  assert(m_value.array != nullptr);
4306  m_value.array->push_back(std::move(val));
4307  // invalidate object
4308  val.m_type = value_t::null;
4309  }
4310 
4315  reference operator+=(basic_json&& val)
4316  {
4317  push_back(std::move(val));
4318  return *this;
4319  }
4320 
4325  void push_back(const basic_json& val)
4326  {
4327  // push_back only works for null objects or arrays
4328  if (not(is_null() or is_array()))
4329  {
4330  throw std::domain_error("cannot use push_back() with " + type_name());
4331  }
4332 
4333  // transform null object into an array
4334  if (is_null())
4335  {
4336  m_type = value_t::array;
4337  m_value = value_t::array;
4338  }
4339 
4340  // add element to array
4341  assert(m_value.array != nullptr);
4342  m_value.array->push_back(val);
4343  }
4344 
4349  reference operator+=(const basic_json& val)
4350  {
4351  push_back(val);
4352  return *this;
4353  }
4354 
4375  void push_back(const typename object_t::value_type& val)
4376  {
4377  // push_back only works for null objects or objects
4378  if (not(is_null() or is_object()))
4379  {
4380  throw std::domain_error("cannot use push_back() with " + type_name());
4381  }
4382 
4383  // transform null object into an object
4384  if (is_null())
4385  {
4386  m_type = value_t::object;
4387  m_value = value_t::object;
4388  }
4389 
4390  // add element to array
4391  assert(m_value.object != nullptr);
4392  m_value.object->insert(val);
4393  }
4394 
4399  reference operator+=(const typename object_t::value_type& val)
4400  {
4401  push_back(val);
4402  return operator[](val.first);
4403  }
4404 
4427  iterator insert(const_iterator pos, const basic_json& val)
4428  {
4429  // insert only works for arrays
4430  if (is_array())
4431  {
4432  // check if iterator pos fits to this JSON value
4433  if (pos.m_object != this)
4434  {
4435  throw std::domain_error("iterator does not fit current value");
4436  }
4437 
4438  // insert to array and return iterator
4439  iterator result(this);
4440  assert(m_value.array != nullptr);
4441  result.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator, val);
4442  return result;
4443  }
4444  else
4445  {
4446  throw std::domain_error("cannot use insert() with " + type_name());
4447  }
4448  }
4449 
4454  iterator insert(const_iterator pos, basic_json&& val)
4455  {
4456  return insert(pos, val);
4457  }
4458 
4483  iterator insert(const_iterator pos, size_type cnt, const basic_json& val)
4484  {
4485  // insert only works for arrays
4486  if (is_array())
4487  {
4488  // check if iterator pos fits to this JSON value
4489  if (pos.m_object != this)
4490  {
4491  throw std::domain_error("iterator does not fit current value");
4492  }
4493 
4494  // insert to array and return iterator
4495  iterator result(this);
4496  assert(m_value.array != nullptr);
4497  result.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator, cnt, val);
4498  return result;
4499  }
4500  else
4501  {
4502  throw std::domain_error("cannot use insert() with " + type_name());
4503  }
4504  }
4505 
4537  {
4538  // insert only works for arrays
4539  if (not is_array())
4540  {
4541  throw std::domain_error("cannot use insert() with " + type_name());
4542  }
4543 
4544  // check if iterator pos fits to this JSON value
4545  if (pos.m_object != this)
4546  {
4547  throw std::domain_error("iterator does not fit current value");
4548  }
4549 
4550  if (first.m_object != last.m_object)
4551  {
4552  throw std::domain_error("iterators do not fit");
4553  }
4554 
4555  if (first.m_object == this or last.m_object == this)
4556  {
4557  throw std::domain_error("passed iterators may not belong to container");
4558  }
4559 
4560  // insert to array and return iterator
4561  iterator result(this);
4562  assert(m_value.array != nullptr);
4563  result.m_it.array_iterator = m_value.array->insert(
4564  pos.m_it.array_iterator,
4565  first.m_it.array_iterator,
4566  last.m_it.array_iterator);
4567  return result;
4568  }
4569 
4594  iterator insert(const_iterator pos, std::initializer_list<basic_json> ilist)
4595  {
4596  // insert only works for arrays
4597  if (not is_array())
4598  {
4599  throw std::domain_error("cannot use insert() with " + type_name());
4600  }
4601 
4602  // check if iterator pos fits to this JSON value
4603  if (pos.m_object != this)
4604  {
4605  throw std::domain_error("iterator does not fit current value");
4606  }
4607 
4608  // insert to array and return iterator
4609  iterator result(this);
4610  assert(m_value.array != nullptr);
4611  result.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator, ilist);
4612  return result;
4613  }
4614 
4632  void swap(reference other) noexcept (
4633  std::is_nothrow_move_constructible<value_t>::value and
4634  std::is_nothrow_move_assignable<value_t>::value and
4635  std::is_nothrow_move_constructible<json_value>::value and
4636  std::is_nothrow_move_assignable<json_value>::value
4637  )
4638  {
4639  std::swap(m_type, other.m_type);
4640  std::swap(m_value, other.m_value);
4641  }
4642 
4663  void swap(array_t& other)
4664  {
4665  // swap only works for arrays
4666  if (is_array())
4667  {
4668  assert(m_value.array != nullptr);
4669  std::swap(*(m_value.array), other);
4670  }
4671  else
4672  {
4673  throw std::domain_error("cannot use swap() with " + type_name());
4674  }
4675  }
4676 
4697  void swap(object_t& other)
4698  {
4699  // swap only works for objects
4700  if (is_object())
4701  {
4702  assert(m_value.object != nullptr);
4703  std::swap(*(m_value.object), other);
4704  }
4705  else
4706  {
4707  throw std::domain_error("cannot use swap() with " + type_name());
4708  }
4709  }
4710 
4731  void swap(string_t& other)
4732  {
4733  // swap only works for strings
4734  if (is_string())
4735  {
4736  assert(m_value.string != nullptr);
4737  std::swap(*(m_value.string), other);
4738  }
4739  else
4740  {
4741  throw std::domain_error("cannot use swap() with " + type_name());
4742  }
4743  }
4744 
4746 
4747 
4749  // lexicographical comparison operators //
4751 
4754 
4755  private:
4765  friend bool operator<(const value_t lhs, const value_t rhs)
4766  {
4767  static constexpr std::array<uint8_t, 7> order = {{
4768  0, // null
4769  3, // object
4770  4, // array
4771  5, // string
4772  1, // boolean
4773  2, // integer
4774  2 // float
4775  }
4776  };
4777 
4778  // discarded values are not comparable
4779  if (lhs == value_t::discarded or rhs == value_t::discarded)
4780  {
4781  return false;
4782  }
4783 
4784  return order[static_cast<std::size_t>(lhs)] < order[static_cast<std::size_t>(rhs)];
4785  }
4786 
4787  public:
4811  friend bool operator==(const_reference lhs, const_reference rhs) noexcept
4812  {
4813  const auto lhs_type = lhs.type();
4814  const auto rhs_type = rhs.type();
4815 
4816  if (lhs_type == rhs_type)
4817  {
4818  switch (lhs_type)
4819  {
4820  case value_t::array:
4821  {
4822  assert(lhs.m_value.array != nullptr);
4823  assert(rhs.m_value.array != nullptr);
4824  return *lhs.m_value.array == *rhs.m_value.array;
4825  }
4826  case value_t::object:
4827  {
4828  assert(lhs.m_value.object != nullptr);
4829  assert(rhs.m_value.object != nullptr);
4830  return *lhs.m_value.object == *rhs.m_value.object;
4831  }
4832  case value_t::null:
4833  {
4834  return true;
4835  }
4836  case value_t::string:
4837  {
4838  assert(lhs.m_value.string != nullptr);
4839  assert(rhs.m_value.string != nullptr);
4840  return *lhs.m_value.string == *rhs.m_value.string;
4841  }
4842  case value_t::boolean:
4843  {
4844  return lhs.m_value.boolean == rhs.m_value.boolean;
4845  }
4846  case value_t::number_integer:
4847  {
4848  return lhs.m_value.number_integer == rhs.m_value.number_integer;
4849  }
4850  case value_t::number_float:
4851  {
4852  return approx(lhs.m_value.number_float, rhs.m_value.number_float);
4853  }
4854  default:
4855  {
4856  return false;
4857  }
4858  }
4859  }
4860  else if (lhs_type == value_t::number_integer and rhs_type == value_t::number_float)
4861  {
4862  return approx(static_cast<number_float_t>(lhs.m_value.number_integer),
4863  rhs.m_value.number_float);
4864  }
4865  else if (lhs_type == value_t::number_float and rhs_type == value_t::number_integer)
4866  {
4867  return approx(lhs.m_value.number_float,
4868  static_cast<number_float_t>(rhs.m_value.number_integer));
4869  }
4870  return false;
4871  }
4872 
4891  friend bool operator==(const_reference v, std::nullptr_t) noexcept
4892  {
4893  return v.is_null();
4894  }
4895 
4900  friend bool operator==(std::nullptr_t, const_reference v) noexcept
4901  {
4902  return v.is_null();
4903  }
4904 
4921  friend bool operator!=(const_reference lhs, const_reference rhs) noexcept
4922  {
4923  return not (lhs == rhs);
4924  }
4925 
4944  friend bool operator!=(const_reference v, std::nullptr_t) noexcept
4945  {
4946  return not v.is_null();
4947  }
4948 
4953  friend bool operator!=(std::nullptr_t, const_reference v) noexcept
4954  {
4955  return not v.is_null();
4956  }
4957 
4982  friend bool operator<(const_reference lhs, const_reference rhs) noexcept
4983  {
4984  const auto lhs_type = lhs.type();
4985  const auto rhs_type = rhs.type();
4986 
4987  if (lhs_type == rhs_type)
4988  {
4989  switch (lhs_type)
4990  {
4991  case value_t::array:
4992  {
4993  assert(lhs.m_value.array != nullptr);
4994  assert(rhs.m_value.array != nullptr);
4995  return *lhs.m_value.array < *rhs.m_value.array;
4996  }
4997  case value_t::object:
4998  {
4999  assert(lhs.m_value.object != nullptr);
5000  assert(rhs.m_value.object != nullptr);
5001  return *lhs.m_value.object < *rhs.m_value.object;
5002  }
5003  case value_t::null:
5004  {
5005  return false;
5006  }
5007  case value_t::string:
5008  {
5009  assert(lhs.m_value.string != nullptr);
5010  assert(rhs.m_value.string != nullptr);
5011  return *lhs.m_value.string < *rhs.m_value.string;
5012  }
5013  case value_t::boolean:
5014  {
5015  return lhs.m_value.boolean < rhs.m_value.boolean;
5016  }
5017  case value_t::number_integer:
5018  {
5019  return lhs.m_value.number_integer < rhs.m_value.number_integer;
5020  }
5021  case value_t::number_float:
5022  {
5023  return lhs.m_value.number_float < rhs.m_value.number_float;
5024  }
5025  default:
5026  {
5027  return false;
5028  }
5029  }
5030  }
5031  else if (lhs_type == value_t::number_integer and rhs_type == value_t::number_float)
5032  {
5033  return static_cast<number_float_t>(lhs.m_value.number_integer) <
5034  rhs.m_value.number_float;
5035  }
5036  else if (lhs_type == value_t::number_float and rhs_type == value_t::number_integer)
5037  {
5038  return lhs.m_value.number_float <
5039  static_cast<number_float_t>(rhs.m_value.number_integer);
5040  }
5041 
5042  // We only reach this line if we cannot compare values. In that case,
5043  // we compare types. Note we have to call the operator explicitly,
5044  // because MSVC has problems otherwise.
5045  return operator<(lhs_type, rhs_type);
5046  }
5047 
5065  friend bool operator<=(const_reference lhs, const_reference rhs) noexcept
5066  {
5067  return not (rhs < lhs);
5068  }
5069 
5087  friend bool operator>(const_reference lhs, const_reference rhs) noexcept
5088  {
5089  return not (lhs <= rhs);
5090  }
5091 
5109  friend bool operator>=(const_reference lhs, const_reference rhs) noexcept
5110  {
5111  return not (lhs < rhs);
5112  }
5113 
5115 
5116 
5118  // serialization //
5120 
5123 
5146  friend std::ostream& operator<<(std::ostream& o, const basic_json& j)
5147  {
5148  // read width member and use it as indentation parameter if nonzero
5149  const bool pretty_print = (o.width() > 0);
5150  const auto indentation = (pretty_print ? o.width() : 0);
5151 
5152  // reset width to 0 for subsequent calls to this stream
5153  o.width(0);
5154 
5155  // do the actual serialization
5156  j.dump(o, pretty_print, static_cast<unsigned int>(indentation));
5157  return o;
5158  }
5159 
5164  friend std::ostream& operator>>(const basic_json& j, std::ostream& o)
5165  {
5166  return o << j;
5167  }
5168 
5170 
5171 
5173  // deserialization //
5175 
5178 
5203  static basic_json parse(const string_t& s, parser_callback_t cb = nullptr)
5204  {
5205  return parser(s, cb).parse();
5206  }
5207 
5232  static basic_json parse(std::istream& i, parser_callback_t cb = nullptr)
5233  {
5234  return parser(i, cb).parse();
5235  }
5236 
5240  static basic_json parse(std::istream&& i, parser_callback_t cb = nullptr)
5241  {
5242  return parser(i, cb).parse();
5243  }
5244 
5268  friend std::istream& operator<<(basic_json& j, std::istream& i)
5269  {
5270  j = parser(i).parse();
5271  return i;
5272  }
5273 
5278  friend std::istream& operator>>(std::istream& i, basic_json& j)
5279  {
5280  j = parser(i).parse();
5281  return i;
5282  }
5283 
5285 
5286 
5287  private:
5289  // convenience functions //
5291 
5293  string_t type_name() const
5294  {
5295  switch (m_type)
5296  {
5297  case value_t::null:
5298  return "null";
5299  case value_t::object:
5300  return "object";
5301  case value_t::array:
5302  return "array";
5303  case value_t::string:
5304  return "string";
5305  case value_t::boolean:
5306  return "boolean";
5307  case value_t::discarded:
5308  return "discarded";
5309  default:
5310  return "number";
5311  }
5312  }
5313 
5322  static std::size_t extra_space(const string_t& s) noexcept
5323  {
5324  std::size_t result = 0;
5325 
5326  for (const auto& c : s)
5327  {
5328  switch (c)
5329  {
5330  case '"':
5331  case '\\':
5332  case '\b':
5333  case '\f':
5334  case '\n':
5335  case '\r':
5336  case '\t':
5337  {
5338  // from c (1 byte) to \x (2 bytes)
5339  result += 1;
5340  break;
5341  }
5342 
5343  default:
5344  {
5345  if (c >= 0x00 and c <= 0x1f)
5346  {
5347  // from c (1 byte) to \uxxxx (6 bytes)
5348  result += 5;
5349  }
5350  break;
5351  }
5352  }
5353  }
5354 
5355  return result;
5356  }
5357 
5371  static string_t escape_string(const string_t& s) noexcept
5372  {
5373  const auto space = extra_space(s);
5374  if (space == 0)
5375  {
5376  return s;
5377  }
5378 
5379  // create a result string of necessary size
5380  string_t result(s.size() + space, '\\');
5381  std::size_t pos = 0;
5382 
5383  for (const auto& c : s)
5384  {
5385  switch (c)
5386  {
5387  // quotation mark (0x22)
5388  case '"':
5389  {
5390  result[pos + 1] = '"';
5391  pos += 2;
5392  break;
5393  }
5394 
5395  // reverse solidus (0x5c)
5396  case '\\':
5397  {
5398  // nothing to change
5399  pos += 2;
5400  break;
5401  }
5402 
5403  // backspace (0x08)
5404  case '\b':
5405  {
5406  result[pos + 1] = 'b';
5407  pos += 2;
5408  break;
5409  }
5410 
5411  // formfeed (0x0c)
5412  case '\f':
5413  {
5414  result[pos + 1] = 'f';
5415  pos += 2;
5416  break;
5417  }
5418 
5419  // newline (0x0a)
5420  case '\n':
5421  {
5422  result[pos + 1] = 'n';
5423  pos += 2;
5424  break;
5425  }
5426 
5427  // carriage return (0x0d)
5428  case '\r':
5429  {
5430  result[pos + 1] = 'r';
5431  pos += 2;
5432  break;
5433  }
5434 
5435  // horizontal tab (0x09)
5436  case '\t':
5437  {
5438  result[pos + 1] = 't';
5439  pos += 2;
5440  break;
5441  }
5442 
5443  default:
5444  {
5445  if (c >= 0x00 and c <= 0x1f)
5446  {
5447  // convert a number 0..15 to its hex representation (0..f)
5448  auto hexify = [](const char v) -> char
5449  {
5450  return (v < 10) ? ('0' + v) : ('a' + v - 10);
5451  };
5452 
5453  // print character c as \uxxxx
5454  for (const char m :
5455  { 'u', '0', '0', hexify(c >> 4), hexify(c & 0x0f)
5456  })
5457  {
5458  result[++pos] = m;
5459  }
5460 
5461  ++pos;
5462  }
5463  else
5464  {
5465  // all other characters are added as-is
5466  result[pos++] = c;
5467  }
5468  break;
5469  }
5470  }
5471  }
5472 
5473  return result;
5474  }
5475 
5493  void dump(std::ostream& o,
5494  const bool pretty_print,
5495  const unsigned int indent_step,
5496  const unsigned int current_indent = 0) const
5497  {
5498  // variable to hold indentation for recursive calls
5499  unsigned int new_indent = current_indent;
5500 
5501  switch (m_type)
5502  {
5503  case value_t::object:
5504  {
5505  assert(m_value.object != nullptr);
5506 
5507  if (m_value.object->empty())
5508  {
5509  o << "{}";
5510  return;
5511  }
5512 
5513  o << "{";
5514 
5515  // increase indentation
5516  if (pretty_print)
5517  {
5518  new_indent += indent_step;
5519  o << "\n";
5520  }
5521 
5522  for (auto i = m_value.object->cbegin(); i != m_value.object->cend(); ++i)
5523  {
5524  if (i != m_value.object->cbegin())
5525  {
5526  o << (pretty_print ? ",\n" : ",");
5527  }
5528  o << string_t(new_indent, ' ') << "\""
5529  << escape_string(i->first) << "\":"
5530  << (pretty_print ? " " : "");
5531  i->second.dump(o, pretty_print, indent_step, new_indent);
5532  }
5533 
5534  // decrease indentation
5535  if (pretty_print)
5536  {
5537  new_indent -= indent_step;
5538  o << "\n";
5539  }
5540 
5541  o << string_t(new_indent, ' ') + "}";
5542  return;
5543  }
5544 
5545  case value_t::array:
5546  {
5547  assert(m_value.array != nullptr);
5548 
5549  if (m_value.array->empty())
5550  {
5551  o << "[]";
5552  return;
5553  }
5554 
5555  o << "[";
5556 
5557  // increase indentation
5558  if (pretty_print)
5559  {
5560  new_indent += indent_step;
5561  o << "\n";
5562  }
5563 
5564  for (auto i = m_value.array->cbegin(); i != m_value.array->cend(); ++i)
5565  {
5566  if (i != m_value.array->cbegin())
5567  {
5568  o << (pretty_print ? ",\n" : ",");
5569  }
5570  o << string_t(new_indent, ' ');
5571  i->dump(o, pretty_print, indent_step, new_indent);
5572  }
5573 
5574  // decrease indentation
5575  if (pretty_print)
5576  {
5577  new_indent -= indent_step;
5578  o << "\n";
5579  }
5580 
5581  o << string_t(new_indent, ' ') << "]";
5582  return;
5583  }
5584 
5585  case value_t::string:
5586  {
5587  assert(m_value.string != nullptr);
5588  o << string_t("\"") << escape_string(*m_value.string) << "\"";
5589  return;
5590  }
5591 
5592  case value_t::boolean:
5593  {
5594  o << (m_value.boolean ? "true" : "false");
5595  return;
5596  }
5597 
5598  case value_t::number_integer:
5599  {
5600  o << m_value.number_integer;
5601  return;
5602  }
5603 
5604  case value_t::number_float:
5605  {
5606  // 15 digits of precision allows round-trip IEEE 754
5607  // string->double->string; to be safe, we read this value from
5608  // std::numeric_limits<number_float_t>::digits10
5609  o << std::setprecision(std::numeric_limits<number_float_t>::digits10) << m_value.number_float;
5610  return;
5611  }
5612 
5613  case value_t::discarded:
5614  {
5615  o << "<discarded>";
5616  return;
5617  }
5618 
5619  case value_t::null:
5620  {
5621  o << "null";
5622  return;
5623  }
5624  }
5625  }
5626 
5627  private:
5629  // member variables //
5631 
5633  value_t m_type = value_t::null;
5634 
5636  json_value m_value = {};
5637 
5638 
5639  private:
5641  // iterators //
5643 
5653  class primitive_iterator_t
5654  {
5655  public:
5657  void set_begin()
5658  {
5659  m_it = begin_value;
5660  }
5661 
5663  void set_end()
5664  {
5665  m_it = end_value;
5666  }
5667 
5669  bool is_begin() const
5670  {
5671  return (m_it == begin_value);
5672  }
5673 
5675  bool is_end() const
5676  {
5677  return (m_it == end_value);
5678  }
5679 
5681  operator difference_type& ()
5682  {
5683  return m_it;
5684  }
5685 
5687  operator difference_type () const
5688  {
5689  return m_it;
5690  }
5691 
5692  private:
5693  static constexpr difference_type begin_value = 0;
5694  static constexpr difference_type end_value = begin_value + 1;
5695 
5697  difference_type m_it = std::numeric_limits<std::ptrdiff_t>::denorm_min();
5698  };
5699 
5707  struct internal_iterator
5708  {
5710  typename object_t::iterator object_iterator;
5712  typename array_t::iterator array_iterator;
5714  primitive_iterator_t primitive_iterator;
5715 
5717  internal_iterator()
5718  : object_iterator(), array_iterator(), primitive_iterator()
5719  {}
5720  };
5721 
5723  template<typename IteratorType>
5724  class iteration_proxy
5725  {
5726  private:
5728  class iteration_proxy_internal
5729  {
5730  private:
5732  IteratorType anchor;
5734  size_t array_index = 0;
5735 
5736  public:
5737  iteration_proxy_internal(IteratorType it)
5738  : anchor(it)
5739  {}
5740 
5742  iteration_proxy_internal& operator*()
5743  {
5744  return *this;
5745  }
5746 
5748  iteration_proxy_internal& operator++()
5749  {
5750  ++anchor;
5751  ++array_index;
5752 
5753  return *this;
5754  }
5755 
5757  bool operator!= (const iteration_proxy_internal& o) const
5758  {
5759  return anchor != o.anchor;
5760  }
5761 
5763  typename basic_json::string_t key() const
5764  {
5765  assert(anchor.m_object != nullptr);
5766 
5767  switch (anchor.m_object->type())
5768  {
5769  // use integer array index as key
5770  case value_t::array:
5771  {
5772  return std::to_string(array_index);
5773  }
5774 
5775  // use key from the object
5776  case value_t::object:
5777  {
5778  return anchor.key();
5779  }
5780 
5781  // use an empty key for all primitive types
5782  default:
5783  {
5784  return "";
5785  }
5786  }
5787  }
5788 
5790  typename IteratorType::reference value() const
5791  {
5792  return anchor.value();
5793  }
5794  };
5795 
5797  typename IteratorType::reference container;
5798 
5799  public:
5801  iteration_proxy(typename IteratorType::reference cont)
5802  : container(cont)
5803  {}
5804 
5806  iteration_proxy_internal begin()
5807  {
5808  return iteration_proxy_internal(container.begin());
5809  }
5810 
5812  iteration_proxy_internal end()
5813  {
5814  return iteration_proxy_internal(container.end());
5815  }
5816  };
5817 
5818  public:
5832  class const_iterator : public std::iterator<std::random_access_iterator_tag, const basic_json>
5833  {
5835  friend class basic_json;
5836 
5837  public:
5847  using iterator_category = std::bidirectional_iterator_tag;
5848 
5850  const_iterator() = default;
5851 
5853  const_iterator(pointer object) : m_object(object)
5854  {
5855  assert(m_object != nullptr);
5856 
5857  switch (m_object->m_type)
5858  {
5860  {
5861  m_it.object_iterator = typename object_t::iterator();
5862  break;
5863  }
5864 
5866  {
5867  m_it.array_iterator = typename array_t::iterator();
5868  break;
5869  }
5870 
5871  default:
5872  {
5873  m_it.primitive_iterator = primitive_iterator_t();
5874  break;
5875  }
5876  }
5877  }
5878 
5880  const_iterator(const iterator& other) : m_object(other.m_object)
5881  {
5882  assert(m_object != nullptr);
5883 
5884  switch (m_object->m_type)
5885  {
5887  {
5888  m_it.object_iterator = other.m_it.object_iterator;
5889  break;
5890  }
5891 
5893  {
5894  m_it.array_iterator = other.m_it.array_iterator;
5895  break;
5896  }
5897 
5898  default:
5899  {
5900  m_it.primitive_iterator = other.m_it.primitive_iterator;
5901  break;
5902  }
5903  }
5904  }
5905 
5907  const_iterator(const const_iterator& other) noexcept
5908  : m_object(other.m_object), m_it(other.m_it)
5909  {}
5910 
5913  std::is_nothrow_move_constructible<pointer>::value and
5914  std::is_nothrow_move_assignable<pointer>::value and
5915  std::is_nothrow_move_constructible<internal_iterator>::value and
5916  std::is_nothrow_move_assignable<internal_iterator>::value
5917  )
5918  {
5919  std::swap(m_object, other.m_object);
5920  std::swap(m_it, other.m_it);
5921  return *this;
5922  }
5923 
5924  private:
5926  void set_begin()
5927  {
5928  assert(m_object != nullptr);
5929 
5930  switch (m_object->m_type)
5931  {
5933  {
5934  assert(m_object->m_value.object != nullptr);
5935  m_it.object_iterator = m_object->m_value.object->begin();
5936  break;
5937  }
5938 
5940  {
5941  assert(m_object->m_value.array != nullptr);
5942  m_it.array_iterator = m_object->m_value.array->begin();
5943  break;
5944  }
5945 
5947  {
5948  // set to end so begin()==end() is true: null is empty
5949  m_it.primitive_iterator.set_end();
5950  break;
5951  }
5952 
5953  default:
5954  {
5955  m_it.primitive_iterator.set_begin();
5956  break;
5957  }
5958  }
5959  }
5960 
5962  void set_end()
5963  {
5964  assert(m_object != nullptr);
5965 
5966  switch (m_object->m_type)
5967  {
5969  {
5970  assert(m_object->m_value.object != nullptr);
5971  m_it.object_iterator = m_object->m_value.object->end();
5972  break;
5973  }
5974 
5976  {
5977  assert(m_object->m_value.array != nullptr);
5978  m_it.array_iterator = m_object->m_value.array->end();
5979  break;
5980  }
5981 
5982  default:
5983  {
5984  m_it.primitive_iterator.set_end();
5985  break;
5986  }
5987  }
5988  }
5989 
5990  public:
5993  {
5994  assert(m_object != nullptr);
5995 
5996  switch (m_object->m_type)
5997  {
5999  {
6000  assert(m_object->m_value.object);
6001  assert(m_it.object_iterator != m_object->m_value.object->end());
6002  return m_it.object_iterator->second;
6003  }
6004 
6006  {
6007  assert(m_object->m_value.array);
6008  assert(m_it.array_iterator != m_object->m_value.array->end());
6009  return *m_it.array_iterator;
6010  }
6011 
6013  {
6014  throw std::out_of_range("cannot get value");
6015  }
6016 
6017  default:
6018  {
6019  if (m_it.primitive_iterator.is_begin())
6020  {
6021  return *m_object;
6022  }
6023  else
6024  {
6025  throw std::out_of_range("cannot get value");
6026  }
6027  }
6028  }
6029  }
6030 
6033  {
6034  assert(m_object != nullptr);
6035 
6036  switch (m_object->m_type)
6037  {
6039  {
6040  assert(m_object->m_value.object);
6041  assert(m_it.object_iterator != m_object->m_value.object->end());
6042  return &(m_it.object_iterator->second);
6043  }
6044 
6046  {
6047  assert(m_object->m_value.array);
6048  assert(m_it.array_iterator != m_object->m_value.array->end());
6049  return &*m_it.array_iterator;
6050  }
6051 
6052  default:
6053  {
6054  if (m_it.primitive_iterator.is_begin())
6055  {
6056  return m_object;
6057  }
6058  else
6059  {
6060  throw std::out_of_range("cannot get value");
6061  }
6062  }
6063  }
6064  }
6065 
6068  {
6069  auto result = *this;
6070  ++(*this);
6071  return result;
6072  }
6073 
6076  {
6077  assert(m_object != nullptr);
6078 
6079  switch (m_object->m_type)
6080  {
6082  {
6083  ++m_it.object_iterator;
6084  break;
6085  }
6086 
6088  {
6089  ++m_it.array_iterator;
6090  break;
6091  }
6092 
6093  default:
6094  {
6095  ++m_it.primitive_iterator;
6096  break;
6097  }
6098  }
6099 
6100  return *this;
6101  }
6102 
6105  {
6106  auto result = *this;
6107  --(*this);
6108  return result;
6109  }
6110 
6113  {
6114  assert(m_object != nullptr);
6115 
6116  switch (m_object->m_type)
6117  {
6119  {
6120  --m_it.object_iterator;
6121  break;
6122  }
6123 
6125  {
6126  --m_it.array_iterator;
6127  break;
6128  }
6129 
6130  default:
6131  {
6132  --m_it.primitive_iterator;
6133  break;
6134  }
6135  }
6136 
6137  return *this;
6138  }
6139 
6141  bool operator==(const const_iterator& other) const
6142  {
6143  // if objects are not the same, the comparison is undefined
6144  if (m_object != other.m_object)
6145  {
6146  throw std::domain_error("cannot compare iterators of different containers");
6147  }
6148 
6149  assert(m_object != nullptr);
6150 
6151  switch (m_object->m_type)
6152  {
6154  {
6155  return (m_it.object_iterator == other.m_it.object_iterator);
6156  }
6157 
6159  {
6160  return (m_it.array_iterator == other.m_it.array_iterator);
6161  }
6162 
6163  default:
6164  {
6165  return (m_it.primitive_iterator == other.m_it.primitive_iterator);
6166  }
6167  }
6168  }
6169 
6171  bool operator!=(const const_iterator& other) const
6172  {
6173  return not operator==(other);
6174  }
6175 
6177  bool operator<(const const_iterator& other) const
6178  {
6179  // if objects are not the same, the comparison is undefined
6180  if (m_object != other.m_object)
6181  {
6182  throw std::domain_error("cannot compare iterators of different containers");
6183  }
6184 
6185  assert(m_object != nullptr);
6186 
6187  switch (m_object->m_type)
6188  {
6190  {
6191  throw std::domain_error("cannot compare order of object iterators");
6192  }
6193 
6195  {
6196  return (m_it.array_iterator < other.m_it.array_iterator);
6197  }
6198 
6199  default:
6200  {
6201  return (m_it.primitive_iterator < other.m_it.primitive_iterator);
6202  }
6203  }
6204  }
6205 
6207  bool operator<=(const const_iterator& other) const
6208  {
6209  return not other.operator < (*this);
6210  }
6211 
6213  bool operator>(const const_iterator& other) const
6214  {
6215  return not operator<=(other);
6216  }
6217 
6219  bool operator>=(const const_iterator& other) const
6220  {
6221  return not operator<(other);
6222  }
6223 
6226  {
6227  assert(m_object != nullptr);
6228 
6229  switch (m_object->m_type)
6230  {
6232  {
6233  throw std::domain_error("cannot use offsets with object iterators");
6234  }
6235 
6237  {
6238  m_it.array_iterator += i;
6239  break;
6240  }
6241 
6242  default:
6243  {
6244  m_it.primitive_iterator += i;
6245  break;
6246  }
6247  }
6248 
6249  return *this;
6250  }
6251 
6254  {
6255  return operator+=(-i);
6256  }
6257 
6260  {
6261  auto result = *this;
6262  result += i;
6263  return result;
6264  }
6265 
6268  {
6269  auto result = *this;
6270  result -= i;
6271  return result;
6272  }
6273 
6276  {
6277  assert(m_object != nullptr);
6278 
6279  switch (m_object->m_type)
6280  {
6282  {
6283  throw std::domain_error("cannot use offsets with object iterators");
6284  }
6285 
6287  {
6288  return m_it.array_iterator - other.m_it.array_iterator;
6289  }
6290 
6291  default:
6292  {
6293  return m_it.primitive_iterator - other.m_it.primitive_iterator;
6294  }
6295  }
6296  }
6297 
6300  {
6301  assert(m_object != nullptr);
6302 
6303  switch (m_object->m_type)
6304  {
6306  {
6307  throw std::domain_error("cannot use operator[] for object iterators");
6308  }
6309 
6311  {
6312  return *(m_it.array_iterator + n);
6313  }
6314 
6316  {
6317  throw std::out_of_range("cannot get value");
6318  }
6319 
6320  default:
6321  {
6322  if (m_it.primitive_iterator == -n)
6323  {
6324  return *m_object;
6325  }
6326  else
6327  {
6328  throw std::out_of_range("cannot get value");
6329  }
6330  }
6331  }
6332  }
6333 
6335  typename object_t::key_type key() const
6336  {
6337  assert(m_object != nullptr);
6338 
6339  if (m_object->is_object())
6340  {
6341  return m_it.object_iterator->first;
6342  }
6343  else
6344  {
6345  throw std::domain_error("cannot use key() for non-object iterators");
6346  }
6347  }
6348 
6351  {
6352  return operator*();
6353  }
6354 
6355  private:
6357  pointer m_object = nullptr;
6359  internal_iterator m_it = internal_iterator();
6360  };
6361 
6374  class iterator : public const_iterator
6375  {
6376  public:
6378  using pointer = typename basic_json::pointer;
6380 
6382  iterator() = default;
6383 
6385  iterator(pointer object) noexcept
6386  : base_iterator(object)
6387  {}
6388 
6390  iterator(const iterator& other) noexcept
6391  : base_iterator(other)
6392  {}
6393 
6395  iterator& operator=(iterator other) noexcept(
6396  std::is_nothrow_move_constructible<pointer>::value and
6397  std::is_nothrow_move_assignable<pointer>::value and
6398  std::is_nothrow_move_constructible<internal_iterator>::value and
6399  std::is_nothrow_move_assignable<internal_iterator>::value
6400  )
6401  {
6402  base_iterator::operator=(other);
6403  return *this;
6404  }
6405 
6408  {
6409  return const_cast<reference>(base_iterator::operator*());
6410  }
6411 
6414  {
6415  return const_cast<pointer>(base_iterator::operator->());
6416  }
6417 
6420  {
6421  iterator result = *this;
6422  base_iterator::operator++();
6423  return result;
6424  }
6425 
6428  {
6429  base_iterator::operator++();
6430  return *this;
6431  }
6432 
6435  {
6436  iterator result = *this;
6437  base_iterator::operator--();
6438  return result;
6439  }
6440 
6443  {
6444  base_iterator::operator--();
6445  return *this;
6446  }
6447 
6450  {
6451  base_iterator::operator+=(i);
6452  return *this;
6453  }
6454 
6457  {
6458  base_iterator::operator-=(i);
6459  return *this;
6460  }
6461 
6464  {
6465  auto result = *this;
6466  result += i;
6467  return result;
6468  }
6469 
6472  {
6473  auto result = *this;
6474  result -= i;
6475  return result;
6476  }
6477 
6478  difference_type operator-(const iterator& other) const
6479  {
6480  return base_iterator::operator-(other);
6481  }
6482 
6485  {
6486  return const_cast<reference>(base_iterator::operator[](n));
6487  }
6488 
6491  {
6492  return const_cast<reference>(base_iterator::value());
6493  }
6494  };
6495 
6513  template<typename Base>
6514  class json_reverse_iterator : public std::reverse_iterator<Base>
6515  {
6516  public:
6518  using base_iterator = std::reverse_iterator<Base>;
6520  using reference = typename Base::reference;
6521 
6523  json_reverse_iterator(const typename base_iterator::iterator_type& it)
6524  : base_iterator(it)
6525  {}
6526 
6529  : base_iterator(it)
6530  {}
6531 
6534  {
6535  return base_iterator::operator++(1);
6536  }
6537 
6540  {
6541  base_iterator::operator++();
6542  return *this;
6543  }
6544 
6547  {
6548  return base_iterator::operator--(1);
6549  }
6550 
6553  {
6554  base_iterator::operator--();
6555  return *this;
6556  }
6557 
6560  {
6561  base_iterator::operator+=(i);
6562  return *this;
6563  }
6564 
6567  {
6568  auto result = *this;
6569  result += i;
6570  return result;
6571  }
6572 
6575  {
6576  auto result = *this;
6577  result -= i;
6578  return result;
6579  }
6580 
6583  {
6584  return this->base() - other.base();
6585  }
6586 
6589  {
6590  return *(this->operator+(n));
6591  }
6592 
6594  typename object_t::key_type key() const
6595  {
6596  auto it = --this->base();
6597  return it.key();
6598  }
6599 
6602  {
6603  auto it = --this->base();
6604  return it.operator * ();
6605  }
6606  };
6607 
6608 
6609  private:
6611  // lexer and parser //
6613 
6621  class lexer
6622  {
6623  public:
6625  enum class token_type
6626  {
6627  uninitialized,
6628  literal_true,
6629  literal_false,
6630  literal_null,
6631  value_string,
6632  value_number,
6633  begin_array,
6634  begin_object,
6635  end_array,
6636  end_object,
6637  name_separator,
6638  value_separator,
6639  parse_error,
6640  end_of_input
6641  };
6642 
6644  using lexer_char_t = unsigned char;
6645 
6647  explicit lexer(const string_t& s) noexcept
6648  : m_stream(nullptr), m_buffer(s)
6649  {
6650  m_content = reinterpret_cast<const lexer_char_t*>(s.c_str());
6651  assert(m_content != nullptr);
6652  m_start = m_cursor = m_content;
6653  m_limit = m_content + s.size();
6654  }
6655 
6657  explicit lexer(std::istream* s) noexcept
6658  : m_stream(s), m_buffer()
6659  {
6660  assert(m_stream != nullptr);
6661  getline(*m_stream, m_buffer);
6662  m_content = reinterpret_cast<const lexer_char_t*>(m_buffer.c_str());
6663  assert(m_content != nullptr);
6664  m_start = m_cursor = m_content;
6665  m_limit = m_content + m_buffer.size();
6666  }
6667 
6669  lexer() = default;
6670 
6671  // switch off unwanted functions
6672  lexer(const lexer&) = delete;
6673  lexer operator=(const lexer&) = delete;
6674 
6690  static string_t to_unicode(const std::size_t codepoint1,
6691  const std::size_t codepoint2 = 0)
6692  {
6693  string_t result;
6694 
6695  // calculate the codepoint from the given code points
6696  std::size_t codepoint = codepoint1;
6697 
6698  // check if codepoint1 is a high surrogate
6699  if (codepoint1 >= 0xD800 and codepoint1 <= 0xDBFF)
6700  {
6701  // check if codepoint2 is a low surrogate
6702  if (codepoint2 >= 0xDC00 and codepoint2 <= 0xDFFF)
6703  {
6704  codepoint =
6705  // high surrogate occupies the most significant 22 bits
6706  (codepoint1 << 10)
6707  // low surrogate occupies the least significant 15 bits
6708  + codepoint2
6709  // there is still the 0xD800, 0xDC00 and 0x10000 noise
6710  // in the result so we have to subtract with:
6711  // (0xD800 << 10) + DC00 - 0x10000 = 0x35FDC00
6712  - 0x35FDC00;
6713  }
6714  else
6715  {
6716  throw std::invalid_argument("missing or wrong low surrogate");
6717  }
6718  }
6719 
6720  if (codepoint < 0x80)
6721  {
6722  // 1-byte characters: 0xxxxxxx (ASCII)
6723  result.append(1, static_cast<typename string_t::value_type>(codepoint));
6724  }
6725  else if (codepoint <= 0x7ff)
6726  {
6727  // 2-byte characters: 110xxxxx 10xxxxxx
6728  result.append(1, static_cast<typename string_t::value_type>(0xC0 | ((codepoint >> 6) & 0x1F)));
6729  result.append(1, static_cast<typename string_t::value_type>(0x80 | (codepoint & 0x3F)));
6730  }
6731  else if (codepoint <= 0xffff)
6732  {
6733  // 3-byte characters: 1110xxxx 10xxxxxx 10xxxxxx
6734  result.append(1, static_cast<typename string_t::value_type>(0xE0 | ((codepoint >> 12) & 0x0F)));
6735  result.append(1, static_cast<typename string_t::value_type>(0x80 | ((codepoint >> 6) & 0x3F)));
6736  result.append(1, static_cast<typename string_t::value_type>(0x80 | (codepoint & 0x3F)));
6737  }
6738  else if (codepoint <= 0x10ffff)
6739  {
6740  // 4-byte characters: 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
6741  result.append(1, static_cast<typename string_t::value_type>(0xF0 | ((codepoint >> 18) & 0x07)));
6742  result.append(1, static_cast<typename string_t::value_type>(0x80 | ((codepoint >> 12) & 0x3F)));
6743  result.append(1, static_cast<typename string_t::value_type>(0x80 | ((codepoint >> 6) & 0x3F)));
6744  result.append(1, static_cast<typename string_t::value_type>(0x80 | (codepoint & 0x3F)));
6745  }
6746  else
6747  {
6748  throw std::out_of_range("code points above 0x10FFFF are invalid");
6749  }
6750 
6751  return result;
6752  }
6753 
6755  static std::string token_type_name(token_type t)
6756  {
6757  switch (t)
6758  {
6759  case token_type::uninitialized:
6760  return "<uninitialized>";
6761  case token_type::literal_true:
6762  return "true literal";
6763  case token_type::literal_false:
6764  return "false literal";
6765  case token_type::literal_null:
6766  return "null literal";
6767  case token_type::value_string:
6768  return "string literal";
6769  case token_type::value_number:
6770  return "number literal";
6771  case token_type::begin_array:
6772  return "'['";
6773  case token_type::begin_object:
6774  return "'{'";
6775  case token_type::end_array:
6776  return "']'";
6777  case token_type::end_object:
6778  return "'}'";
6779  case token_type::name_separator:
6780  return "':'";
6781  case token_type::value_separator:
6782  return "','";
6783  case token_type::parse_error:
6784  return "<parse error>";
6785  case token_type::end_of_input:
6786  return "end of input";
6787  default:
6788  {
6789  // catch non-enum values
6790  return "unknown token"; // LCOV_EXCL_LINE
6791  }
6792  }
6793  }
6794 
6805  token_type scan() noexcept
6806  {
6807  // pointer for backtracking information
6808  m_marker = nullptr;
6809 
6810  // remember the begin of the token
6811  m_start = m_cursor;
6812  assert(m_start != nullptr);
6813 
6814 
6815  {
6816  lexer_char_t yych;
6817  unsigned int yyaccept = 0;
6818  static const unsigned char yybm[] =
6819  {
6820  0, 0, 0, 0, 0, 0, 0, 0,
6821  0, 32, 32, 0, 0, 32, 0, 0,
6822  64, 64, 64, 64, 64, 64, 64, 64,
6823  64, 64, 64, 64, 64, 64, 64, 64,
6824  96, 64, 0, 64, 64, 64, 64, 64,
6825  64, 64, 64, 64, 64, 64, 64, 64,
6826  192, 192, 192, 192, 192, 192, 192, 192,
6827  192, 192, 64, 64, 64, 64, 64, 64,
6828  64, 64, 64, 64, 64, 64, 64, 64,
6829  64, 64, 64, 64, 64, 64, 64, 64,
6830  64, 64, 64, 64, 64, 64, 64, 64,
6831  64, 64, 64, 64, 0, 64, 64, 64,
6832  64, 64, 64, 64, 64, 64, 64, 64,
6833  64, 64, 64, 64, 64, 64, 64, 64,
6834  64, 64, 64, 64, 64, 64, 64, 64,
6835  64, 64, 64, 64, 64, 64, 64, 64,
6836  64, 64, 64, 64, 64, 64, 64, 64,
6837  64, 64, 64, 64, 64, 64, 64, 64,
6838  64, 64, 64, 64, 64, 64, 64, 64,
6839  64, 64, 64, 64, 64, 64, 64, 64,
6840  64, 64, 64, 64, 64, 64, 64, 64,
6841  64, 64, 64, 64, 64, 64, 64, 64,
6842  64, 64, 64, 64, 64, 64, 64, 64,
6843  64, 64, 64, 64, 64, 64, 64, 64,
6844  64, 64, 64, 64, 64, 64, 64, 64,
6845  64, 64, 64, 64, 64, 64, 64, 64,
6846  64, 64, 64, 64, 64, 64, 64, 64,
6847  64, 64, 64, 64, 64, 64, 64, 64,
6848  64, 64, 64, 64, 64, 64, 64, 64,
6849  64, 64, 64, 64, 64, 64, 64, 64,
6850  64, 64, 64, 64, 64, 64, 64, 64,
6851  64, 64, 64, 64, 64, 64, 64, 64,
6852  };
6853  if ((m_limit - m_cursor) < 5)
6854  {
6855  yyfill(); // LCOV_EXCL_LINE;
6856  }
6857  yych = *m_cursor;
6858  if (yych <= ':')
6859  {
6860  if (yych <= ' ')
6861  {
6862  if (yych <= '\n')
6863  {
6864  if (yych <= 0x00)
6865  {
6866  goto basic_json_parser_28;
6867  }
6868  if (yych <= 0x08)
6869  {
6870  goto basic_json_parser_30;
6871  }
6872  if (yych >= '\n')
6873  {
6874  goto basic_json_parser_4;
6875  }
6876  }
6877  else
6878  {
6879  if (yych == '\r')
6880  {
6881  goto basic_json_parser_2;
6882  }
6883  if (yych <= 0x1F)
6884  {
6885  goto basic_json_parser_30;
6886  }
6887  }
6888  }
6889  else
6890  {
6891  if (yych <= ',')
6892  {
6893  if (yych == '"')
6894  {
6895  goto basic_json_parser_27;
6896  }
6897  if (yych <= '+')
6898  {
6899  goto basic_json_parser_30;
6900  }
6901  goto basic_json_parser_16;
6902  }
6903  else
6904  {
6905  if (yych <= '/')
6906  {
6907  if (yych <= '-')
6908  {
6909  goto basic_json_parser_23;
6910  }
6911  goto basic_json_parser_30;
6912  }
6913  else
6914  {
6915  if (yych <= '0')
6916  {
6917  goto basic_json_parser_24;
6918  }
6919  if (yych <= '9')
6920  {
6921  goto basic_json_parser_26;
6922  }
6923  goto basic_json_parser_18;
6924  }
6925  }
6926  }
6927  }
6928  else
6929  {
6930  if (yych <= 'n')
6931  {
6932  if (yych <= ']')
6933  {
6934  if (yych == '[')
6935  {
6936  goto basic_json_parser_8;
6937  }
6938  if (yych <= '\\')
6939  {
6940  goto basic_json_parser_30;
6941  }
6942  goto basic_json_parser_10;
6943  }
6944  else
6945  {
6946  if (yych == 'f')
6947  {
6948  goto basic_json_parser_22;
6949  }
6950  if (yych <= 'm')
6951  {
6952  goto basic_json_parser_30;
6953  }
6954  goto basic_json_parser_20;
6955  }
6956  }
6957  else
6958  {
6959  if (yych <= '{')
6960  {
6961  if (yych == 't')
6962  {
6963  goto basic_json_parser_21;
6964  }
6965  if (yych <= 'z')
6966  {
6967  goto basic_json_parser_30;
6968  }
6969  goto basic_json_parser_12;
6970  }
6971  else
6972  {
6973  if (yych <= '}')
6974  {
6975  if (yych <= '|')
6976  {
6977  goto basic_json_parser_30;
6978  }
6979  goto basic_json_parser_14;
6980  }
6981  else
6982  {
6983  if (yych == 0xEF)
6984  {
6985  goto basic_json_parser_6;
6986  }
6987  goto basic_json_parser_30;
6988  }
6989  }
6990  }
6991  }
6992 basic_json_parser_2:
6993  ++m_cursor;
6994  yych = *m_cursor;
6995  goto basic_json_parser_5;
6996 basic_json_parser_3:
6997  {
6998  return scan();
6999  }
7000 basic_json_parser_4:
7001  ++m_cursor;
7002  if (m_limit <= m_cursor)
7003  {
7004  yyfill(); // LCOV_EXCL_LINE;
7005  }
7006  yych = *m_cursor;
7007 basic_json_parser_5:
7008  if (yybm[0 + yych] & 32)
7009  {
7010  goto basic_json_parser_4;
7011  }
7012  goto basic_json_parser_3;
7013 basic_json_parser_6:
7014  yyaccept = 0;
7015  yych = *(m_marker = ++m_cursor);
7016  if (yych == 0xBB)
7017  {
7018  goto basic_json_parser_64;
7019  }
7020 basic_json_parser_7:
7021  {
7022  return token_type::parse_error;
7023  }
7024 basic_json_parser_8:
7025  ++m_cursor;
7026  {
7027  return token_type::begin_array;
7028  }
7029 basic_json_parser_10:
7030  ++m_cursor;
7031  {
7032  return token_type::end_array;
7033  }
7034 basic_json_parser_12:
7035  ++m_cursor;
7036  {
7037  return token_type::begin_object;
7038  }
7039 basic_json_parser_14:
7040  ++m_cursor;
7041  {
7042  return token_type::end_object;
7043  }
7044 basic_json_parser_16:
7045  ++m_cursor;
7046  {
7047  return token_type::value_separator;
7048  }
7049 basic_json_parser_18:
7050  ++m_cursor;
7051  {
7052  return token_type::name_separator;
7053  }
7054 basic_json_parser_20:
7055  yyaccept = 0;
7056  yych = *(m_marker = ++m_cursor);
7057  if (yych == 'u')
7058  {
7059  goto basic_json_parser_60;
7060  }
7061  goto basic_json_parser_7;
7062 basic_json_parser_21:
7063  yyaccept = 0;
7064  yych = *(m_marker = ++m_cursor);
7065  if (yych == 'r')
7066  {
7067  goto basic_json_parser_56;
7068  }
7069  goto basic_json_parser_7;
7070 basic_json_parser_22:
7071  yyaccept = 0;
7072  yych = *(m_marker = ++m_cursor);
7073  if (yych == 'a')
7074  {
7075  goto basic_json_parser_51;
7076  }
7077  goto basic_json_parser_7;
7078 basic_json_parser_23:
7079  yych = *++m_cursor;
7080  if (yych <= '/')
7081  {
7082  goto basic_json_parser_7;
7083  }
7084  if (yych <= '0')
7085  {
7086  goto basic_json_parser_50;
7087  }
7088  if (yych <= '9')
7089  {
7090  goto basic_json_parser_41;
7091  }
7092  goto basic_json_parser_7;
7093 basic_json_parser_24:
7094  yyaccept = 1;
7095  yych = *(m_marker = ++m_cursor);
7096  if (yych <= 'D')
7097  {
7098  if (yych == '.')
7099  {
7100  goto basic_json_parser_43;
7101  }
7102  }
7103  else
7104  {
7105  if (yych <= 'E')
7106  {
7107  goto basic_json_parser_44;
7108  }
7109  if (yych == 'e')
7110  {
7111  goto basic_json_parser_44;
7112  }
7113  }
7114 basic_json_parser_25:
7115  {
7116  return token_type::value_number;
7117  }
7118 basic_json_parser_26:
7119  yyaccept = 1;
7120  yych = *(m_marker = ++m_cursor);
7121  goto basic_json_parser_42;
7122 basic_json_parser_27:
7123  yyaccept = 0;
7124  yych = *(m_marker = ++m_cursor);
7125  if (yych <= 0x0F)
7126  {
7127  goto basic_json_parser_7;
7128  }
7129  goto basic_json_parser_32;
7130 basic_json_parser_28:
7131  ++m_cursor;
7132  {
7133  return token_type::end_of_input;
7134  }
7135 basic_json_parser_30:
7136  yych = *++m_cursor;
7137  goto basic_json_parser_7;
7138 basic_json_parser_31:
7139  ++m_cursor;
7140  if (m_limit <= m_cursor)
7141  {
7142  yyfill(); // LCOV_EXCL_LINE;
7143  }
7144  yych = *m_cursor;
7145 basic_json_parser_32:
7146  if (yybm[0 + yych] & 64)
7147  {
7148  goto basic_json_parser_31;
7149  }
7150  if (yych <= 0x0F)
7151  {
7152  goto basic_json_parser_33;
7153  }
7154  if (yych <= '"')
7155  {
7156  goto basic_json_parser_35;
7157  }
7158  goto basic_json_parser_34;
7159 basic_json_parser_33:
7160  m_cursor = m_marker;
7161  if (yyaccept == 0)
7162  {
7163  goto basic_json_parser_7;
7164  }
7165  else
7166  {
7167  goto basic_json_parser_25;
7168  }
7169 basic_json_parser_34:
7170  ++m_cursor;
7171  if (m_limit <= m_cursor)
7172  {
7173  yyfill(); // LCOV_EXCL_LINE;
7174  }
7175  yych = *m_cursor;
7176  if (yych <= 'e')
7177  {
7178  if (yych <= '/')
7179  {
7180  if (yych == '"')
7181  {
7182  goto basic_json_parser_31;
7183  }
7184  if (yych <= '.')
7185  {
7186  goto basic_json_parser_33;
7187  }
7188  goto basic_json_parser_31;
7189  }
7190  else
7191  {
7192  if (yych <= '\\')
7193  {
7194  if (yych <= '[')
7195  {
7196  goto basic_json_parser_33;
7197  }
7198  goto basic_json_parser_31;
7199  }
7200  else
7201  {
7202  if (yych == 'b')
7203  {
7204  goto basic_json_parser_31;
7205  }
7206  goto basic_json_parser_33;
7207  }
7208  }
7209  }
7210  else
7211  {
7212  if (yych <= 'q')
7213  {
7214  if (yych <= 'f')
7215  {
7216  goto basic_json_parser_31;
7217  }
7218  if (yych == 'n')
7219  {
7220  goto basic_json_parser_31;
7221  }
7222  goto basic_json_parser_33;
7223  }
7224  else
7225  {
7226  if (yych <= 's')
7227  {
7228  if (yych <= 'r')
7229  {
7230  goto basic_json_parser_31;
7231  }
7232  goto basic_json_parser_33;
7233  }
7234  else
7235  {
7236  if (yych <= 't')
7237  {
7238  goto basic_json_parser_31;
7239  }
7240  if (yych <= 'u')
7241  {
7242  goto basic_json_parser_37;
7243  }
7244  goto basic_json_parser_33;
7245  }
7246  }
7247  }
7248 basic_json_parser_35:
7249  ++m_cursor;
7250  {
7251  return token_type::value_string;
7252  }
7253 basic_json_parser_37:
7254  ++m_cursor;
7255  if (m_limit <= m_cursor)
7256  {
7257  yyfill(); // LCOV_EXCL_LINE;
7258  }
7259  yych = *m_cursor;
7260  if (yych <= '@')
7261  {
7262  if (yych <= '/')
7263  {
7264  goto basic_json_parser_33;
7265  }
7266  if (yych >= ':')
7267  {
7268  goto basic_json_parser_33;
7269  }
7270  }
7271  else
7272  {
7273  if (yych <= 'F')
7274  {
7275  goto basic_json_parser_38;
7276  }
7277  if (yych <= '`')
7278  {
7279  goto basic_json_parser_33;
7280  }
7281  if (yych >= 'g')
7282  {
7283  goto basic_json_parser_33;
7284  }
7285  }
7286 basic_json_parser_38:
7287  ++m_cursor;
7288  if (m_limit <= m_cursor)
7289  {
7290  yyfill(); // LCOV_EXCL_LINE;
7291  }
7292  yych = *m_cursor;
7293  if (yych <= '@')
7294  {
7295  if (yych <= '/')
7296  {
7297  goto basic_json_parser_33;
7298  }
7299  if (yych >= ':')
7300  {
7301  goto basic_json_parser_33;
7302  }
7303  }
7304  else
7305  {
7306  if (yych <= 'F')
7307  {
7308  goto basic_json_parser_39;
7309  }
7310  if (yych <= '`')
7311  {
7312  goto basic_json_parser_33;
7313  }
7314  if (yych >= 'g')
7315  {
7316  goto basic_json_parser_33;
7317  }
7318  }
7319 basic_json_parser_39:
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  if (yych <= '/')
7329  {
7330  goto basic_json_parser_33;
7331  }
7332  if (yych >= ':')
7333  {
7334  goto basic_json_parser_33;
7335  }
7336  }
7337  else
7338  {
7339  if (yych <= 'F')
7340  {
7341  goto basic_json_parser_40;
7342  }
7343  if (yych <= '`')
7344  {
7345  goto basic_json_parser_33;
7346  }
7347  if (yych >= 'g')
7348  {
7349  goto basic_json_parser_33;
7350  }
7351  }
7352 basic_json_parser_40:
7353  ++m_cursor;
7354  if (m_limit <= m_cursor)
7355  {
7356  yyfill(); // LCOV_EXCL_LINE;
7357  }
7358  yych = *m_cursor;
7359  if (yych <= '@')
7360  {
7361  if (yych <= '/')
7362  {
7363  goto basic_json_parser_33;
7364  }
7365  if (yych <= '9')
7366  {
7367  goto basic_json_parser_31;
7368  }
7369  goto basic_json_parser_33;
7370  }
7371  else
7372  {
7373  if (yych <= 'F')
7374  {
7375  goto basic_json_parser_31;
7376  }
7377  if (yych <= '`')
7378  {
7379  goto basic_json_parser_33;
7380  }
7381  if (yych <= 'f')
7382  {
7383  goto basic_json_parser_31;
7384  }
7385  goto basic_json_parser_33;
7386  }
7387 basic_json_parser_41:
7388  yyaccept = 1;
7389  m_marker = ++m_cursor;
7390  if ((m_limit - m_cursor) < 3)
7391  {
7392  yyfill(); // LCOV_EXCL_LINE;
7393  }
7394  yych = *m_cursor;
7395 basic_json_parser_42:
7396  if (yybm[0 + yych] & 128)
7397  {
7398  goto basic_json_parser_41;
7399  }
7400  if (yych <= 'D')
7401  {
7402  if (yych != '.')
7403  {
7404  goto basic_json_parser_25;
7405  }
7406  }
7407  else
7408  {
7409  if (yych <= 'E')
7410  {
7411  goto basic_json_parser_44;
7412  }
7413  if (yych == 'e')
7414  {
7415  goto basic_json_parser_44;
7416  }
7417  goto basic_json_parser_25;
7418  }
7419 basic_json_parser_43:
7420  yych = *++m_cursor;
7421  if (yych <= '/')
7422  {
7423  goto basic_json_parser_33;
7424  }
7425  if (yych <= '9')
7426  {
7427  goto basic_json_parser_48;
7428  }
7429  goto basic_json_parser_33;
7430 basic_json_parser_44:
7431  yych = *++m_cursor;
7432  if (yych <= ',')
7433  {
7434  if (yych != '+')
7435  {
7436  goto basic_json_parser_33;
7437  }
7438  }
7439  else
7440  {
7441  if (yych <= '-')
7442  {
7443  goto basic_json_parser_45;
7444  }
7445  if (yych <= '/')
7446  {
7447  goto basic_json_parser_33;
7448  }
7449  if (yych <= '9')
7450  {
7451  goto basic_json_parser_46;
7452  }
7453  goto basic_json_parser_33;
7454  }
7455 basic_json_parser_45:
7456  yych = *++m_cursor;
7457  if (yych <= '/')
7458  {
7459  goto basic_json_parser_33;
7460  }
7461  if (yych >= ':')
7462  {
7463  goto basic_json_parser_33;
7464  }
7465 basic_json_parser_46:
7466  ++m_cursor;
7467  if (m_limit <= m_cursor)
7468  {
7469  yyfill(); // LCOV_EXCL_LINE;
7470  }
7471  yych = *m_cursor;
7472  if (yych <= '/')
7473  {
7474  goto basic_json_parser_25;
7475  }
7476  if (yych <= '9')
7477  {
7478  goto basic_json_parser_46;
7479  }
7480  goto basic_json_parser_25;
7481 basic_json_parser_48:
7482  yyaccept = 1;
7483  m_marker = ++m_cursor;
7484  if ((m_limit - m_cursor) < 3)
7485  {
7486  yyfill(); // LCOV_EXCL_LINE;
7487  }
7488  yych = *m_cursor;
7489  if (yych <= 'D')
7490  {
7491  if (yych <= '/')
7492  {
7493  goto basic_json_parser_25;
7494  }
7495  if (yych <= '9')
7496  {
7497  goto basic_json_parser_48;
7498  }
7499  goto basic_json_parser_25;
7500  }
7501  else
7502  {
7503  if (yych <= 'E')
7504  {
7505  goto basic_json_parser_44;
7506  }
7507  if (yych == 'e')
7508  {
7509  goto basic_json_parser_44;
7510  }
7511  goto basic_json_parser_25;
7512  }
7513 basic_json_parser_50:
7514  yyaccept = 1;
7515  yych = *(m_marker = ++m_cursor);
7516  if (yych <= 'D')
7517  {
7518  if (yych == '.')
7519  {
7520  goto basic_json_parser_43;
7521  }
7522  goto basic_json_parser_25;
7523  }
7524  else
7525  {
7526  if (yych <= 'E')
7527  {
7528  goto basic_json_parser_44;
7529  }
7530  if (yych == 'e')
7531  {
7532  goto basic_json_parser_44;
7533  }
7534  goto basic_json_parser_25;
7535  }
7536 basic_json_parser_51:
7537  yych = *++m_cursor;
7538  if (yych != 'l')
7539  {
7540  goto basic_json_parser_33;
7541  }
7542  yych = *++m_cursor;
7543  if (yych != 's')
7544  {
7545  goto basic_json_parser_33;
7546  }
7547  yych = *++m_cursor;
7548  if (yych != 'e')
7549  {
7550  goto basic_json_parser_33;
7551  }
7552  ++m_cursor;
7553  {
7554  return token_type::literal_false;
7555  }
7556 basic_json_parser_56:
7557  yych = *++m_cursor;
7558  if (yych != 'u')
7559  {
7560  goto basic_json_parser_33;
7561  }
7562  yych = *++m_cursor;
7563  if (yych != 'e')
7564  {
7565  goto basic_json_parser_33;
7566  }
7567  ++m_cursor;
7568  {
7569  return token_type::literal_true;
7570  }
7571 basic_json_parser_60:
7572  yych = *++m_cursor;
7573  if (yych != 'l')
7574  {
7575  goto basic_json_parser_33;
7576  }
7577  yych = *++m_cursor;
7578  if (yych != 'l')
7579  {
7580  goto basic_json_parser_33;
7581  }
7582  ++m_cursor;
7583  {
7584  return token_type::literal_null;
7585  }
7586 basic_json_parser_64:
7587  yych = *++m_cursor;
7588  if (yych != 0xBF)
7589  {
7590  goto basic_json_parser_33;
7591  }
7592  ++m_cursor;
7593  {
7594  return scan();
7595  }
7596  }
7597 
7598 
7599  }
7600 
7602  void yyfill() noexcept
7603  {
7604  if (m_stream == nullptr or not * m_stream)
7605  {
7606  return;
7607  }
7608 
7609  const ssize_t offset_start = m_start - m_content;
7610  const ssize_t offset_marker = m_marker - m_start;
7611  const ssize_t offset_cursor = m_cursor - m_start;
7612 
7613  m_buffer.erase(0, static_cast<size_t>(offset_start));
7614  std::string line;
7615  assert(m_stream != nullptr);
7616  std::getline(*m_stream, line);
7617  m_buffer += "\n" + line; // add line with newline symbol
7618 
7619  m_content = reinterpret_cast<const lexer_char_t*>(m_buffer.c_str());
7620  assert(m_content != nullptr);
7621  m_start = m_content;
7622  m_marker = m_start + offset_marker;
7623  m_cursor = m_start + offset_cursor;
7624  m_limit = m_start + m_buffer.size() - 1;
7625  }
7626 
7628  string_t get_token() const noexcept
7629  {
7630  assert(m_start != nullptr);
7631  return string_t(reinterpret_cast<typename string_t::const_pointer>(m_start),
7632  static_cast<size_t>(m_cursor - m_start));
7633  }
7634 
7656  string_t get_string() const
7657  {
7658  string_t result;
7659  result.reserve(static_cast<size_t>(m_cursor - m_start - 2));
7660 
7661  // iterate the result between the quotes
7662  for (const lexer_char_t* i = m_start + 1; i < m_cursor - 1; ++i)
7663  {
7664  // process escaped characters
7665  if (*i == '\\')
7666  {
7667  // read next character
7668  ++i;
7669 
7670  switch (*i)
7671  {
7672  // the default escapes
7673  case 't':
7674  {
7675  result += "\t";
7676  break;
7677  }
7678  case 'b':
7679  {
7680  result += "\b";
7681  break;
7682  }
7683  case 'f':
7684  {
7685  result += "\f";
7686  break;
7687  }
7688  case 'n':
7689  {
7690  result += "\n";
7691  break;
7692  }
7693  case 'r':
7694  {
7695  result += "\r";
7696  break;
7697  }
7698  case '\\':
7699  {
7700  result += "\\";
7701  break;
7702  }
7703  case '/':
7704  {
7705  result += "/";
7706  break;
7707  }
7708  case '"':
7709  {
7710  result += "\"";
7711  break;
7712  }
7713 
7714  // unicode
7715  case 'u':
7716  {
7717  // get code xxxx from uxxxx
7718  auto codepoint = std::strtoul(std::string(reinterpret_cast<typename string_t::const_pointer>(i + 1),
7719  4).c_str(), nullptr, 16);
7720 
7721  // check if codepoint is a high surrogate
7722  if (codepoint >= 0xD800 and codepoint <= 0xDBFF)
7723  {
7724  // make sure there is a subsequent unicode
7725  if ((i + 6 >= m_limit) or * (i + 5) != '\\' or * (i + 6) != 'u')
7726  {
7727  throw std::invalid_argument("missing low surrogate");
7728  }
7729 
7730  // get code yyyy from uxxxx\uyyyy
7731  auto codepoint2 = std::strtoul(std::string(reinterpret_cast<typename string_t::const_pointer>
7732  (i + 7), 4).c_str(), nullptr, 16);
7733  result += to_unicode(codepoint, codepoint2);
7734  // skip the next 10 characters (xxxx\uyyyy)
7735  i += 10;
7736  }
7737  else
7738  {
7739  // add unicode character(s)
7740  result += to_unicode(codepoint);
7741  // skip the next four characters (xxxx)
7742  i += 4;
7743  }
7744  break;
7745  }
7746  }
7747  }
7748  else
7749  {
7750  // all other characters are just copied to the end of the
7751  // string
7752  result.append(1, static_cast<typename string_t::value_type>(*i));
7753  }
7754  }
7755 
7756  return result;
7757  }
7758 
7776  long double get_number() const
7777  {
7778  // conversion
7779  typename string_t::value_type* endptr;
7780  assert(m_start != nullptr);
7781  const auto float_val = std::strtold(reinterpret_cast<typename string_t::const_pointer>(m_start),
7782  &endptr);
7783 
7784  // return float_val if the whole number was translated and NAN
7785  // otherwise
7786  return (reinterpret_cast<lexer_char_t*>(endptr) == m_cursor) ? float_val : NAN;
7787  }
7788 
7789  private:
7791  std::istream* m_stream = nullptr;
7793  string_t m_buffer;
7795  const lexer_char_t* m_content = nullptr;
7797  const lexer_char_t* m_start = nullptr;
7799  const lexer_char_t* m_marker = nullptr;
7801  const lexer_char_t* m_cursor = nullptr;
7803  const lexer_char_t* m_limit = nullptr;
7804  };
7805 
7811  class parser
7812  {
7813  public:
7815  parser(const string_t& s, parser_callback_t cb = nullptr)
7816  : callback(cb), m_lexer(s)
7817  {
7818  // read first token
7819  get_token();
7820  }
7821 
7823  parser(std::istream& _is, parser_callback_t cb = nullptr)
7824  : callback(cb), m_lexer(&_is)
7825  {
7826  // read first token
7827  get_token();
7828  }
7829 
7831  basic_json parse()
7832  {
7833  basic_json result = parse_internal(true);
7834 
7835  expect(lexer::token_type::end_of_input);
7836 
7837  // return parser result and replace it with null in case the
7838  // top-level value was discarded by the callback function
7839  return result.is_discarded() ? basic_json() : result;
7840  }
7841 
7842  private:
7844  basic_json parse_internal(bool keep)
7845  {
7846  auto result = basic_json(value_t::discarded);
7847 
7848  switch (last_token)
7849  {
7850  case lexer::token_type::begin_object:
7851  {
7852  if (keep and (not callback or (keep = callback(depth++, parse_event_t::object_start, result))))
7853  {
7854  // explicitly set result to object to cope with {}
7855  result.m_type = value_t::object;
7856  result.m_value = json_value(value_t::object);
7857  }
7858 
7859  // read next token
7860  get_token();
7861 
7862  // closing } -> we are done
7863  if (last_token == lexer::token_type::end_object)
7864  {
7865  get_token();
7866  if (keep and callback and not callback(--depth, parse_event_t::object_end, result))
7867  {
7868  result = basic_json(value_t::discarded);
7869  }
7870  return result;
7871  }
7872 
7873  // no comma is expected here
7874  unexpect(lexer::token_type::value_separator);
7875 
7876  // otherwise: parse key-value pairs
7877  do
7878  {
7879  // ugly, but could be fixed with loop reorganization
7880  if (last_token == lexer::token_type::value_separator)
7881  {
7882  get_token();
7883  }
7884 
7885  // store key
7886  expect(lexer::token_type::value_string);
7887  const auto key = m_lexer.get_string();
7888 
7889  bool keep_tag = false;
7890  if (keep)
7891  {
7892  if (callback)
7893  {
7894  basic_json k(key);
7895  keep_tag = callback(depth, parse_event_t::key, k);
7896  }
7897  else
7898  {
7899  keep_tag = true;
7900  }
7901  }
7902 
7903  // parse separator (:)
7904  get_token();
7905  expect(lexer::token_type::name_separator);
7906 
7907  // parse and add value
7908  get_token();
7909  auto value = parse_internal(keep);
7910  if (keep and keep_tag and not value.is_discarded())
7911  {
7912  result[key] = std::move(value);
7913  }
7914  }
7915  while (last_token == lexer::token_type::value_separator);
7916 
7917  // closing }
7918  expect(lexer::token_type::end_object);
7919  get_token();
7920  if (keep and callback and not callback(--depth, parse_event_t::object_end, result))
7921  {
7922  result = basic_json(value_t::discarded);
7923  }
7924 
7925  return result;
7926  }
7927 
7928  case lexer::token_type::begin_array:
7929  {
7930  if (keep and (not callback or (keep = callback(depth++, parse_event_t::array_start, result))))
7931  {
7932  // explicitly set result to object to cope with []
7933  result.m_type = value_t::array;
7934  result.m_value = json_value(value_t::array);
7935  }
7936 
7937  // read next token
7938  get_token();
7939 
7940  // closing ] -> we are done
7941  if (last_token == lexer::token_type::end_array)
7942  {
7943  get_token();
7944  if (callback and not callback(--depth, parse_event_t::array_end, result))
7945  {
7946  result = basic_json(value_t::discarded);
7947  }
7948  return result;
7949  }
7950 
7951  // no comma is expected here
7952  unexpect(lexer::token_type::value_separator);
7953 
7954  // otherwise: parse values
7955  do
7956  {
7957  // ugly, but could be fixed with loop reorganization
7958  if (last_token == lexer::token_type::value_separator)
7959  {
7960  get_token();
7961  }
7962 
7963  // parse value
7964  auto value = parse_internal(keep);
7965  if (keep and not value.is_discarded())
7966  {
7967  result.push_back(std::move(value));
7968  }
7969  }
7970  while (last_token == lexer::token_type::value_separator);
7971 
7972  // closing ]
7973  expect(lexer::token_type::end_array);
7974  get_token();
7975  if (keep and callback and not callback(--depth, parse_event_t::array_end, result))
7976  {
7977  result = basic_json(value_t::discarded);
7978  }
7979 
7980  return result;
7981  }
7982 
7983  case lexer::token_type::literal_null:
7984  {
7985  get_token();
7986  result.m_type = value_t::null;
7987  break;
7988  }
7989 
7990  case lexer::token_type::value_string:
7991  {
7992  const auto s = m_lexer.get_string();
7993  get_token();
7994  result = basic_json(s);
7995  break;
7996  }
7997 
7998  case lexer::token_type::literal_true:
7999  {
8000  get_token();
8001  result.m_type = value_t::boolean;
8002  result.m_value = true;
8003  break;
8004  }
8005 
8006  case lexer::token_type::literal_false:
8007  {
8008  get_token();
8009  result.m_type = value_t::boolean;
8010  result.m_value = false;
8011  break;
8012  }
8013 
8014  case lexer::token_type::value_number:
8015  {
8016  auto float_val = m_lexer.get_number();
8017 
8018  // NAN is returned if token could not be translated
8019  // completely
8020  if (std::isnan(float_val))
8021  {
8022  throw std::invalid_argument(std::string("parse error - ") +
8023  m_lexer.get_token() + " is not a number");
8024  }
8025 
8026  get_token();
8027 
8028  // check if conversion loses precision
8029  const auto int_val = static_cast<number_integer_t>(float_val);
8030  if (approx(float_val, static_cast<long double>(int_val)))
8031  {
8032  // we would not lose precision -> return int
8033  result.m_type = value_t::number_integer;
8034  result.m_value = int_val;
8035  }
8036  else
8037  {
8038  // we would lose precision -> return float
8039  result.m_type = value_t::number_float;
8040  result.m_value = static_cast<number_float_t>(float_val);
8041  }
8042  break;
8043  }
8044 
8045  default:
8046  {
8047  // the last token was unexpected
8048  unexpect(last_token);
8049  }
8050  }
8051 
8052  if (keep and callback and not callback(depth, parse_event_t::value, result))
8053  {
8054  result = basic_json(value_t::discarded);
8055  }
8056  return result;
8057  }
8058 
8060  typename lexer::token_type get_token()
8061  {
8062  last_token = m_lexer.scan();
8063  return last_token;
8064  }
8065 
8066  void expect(typename lexer::token_type t) const
8067  {
8068  if (t != last_token)
8069  {
8070  std::string error_msg = "parse error - unexpected ";
8071  error_msg += (last_token == lexer::token_type::parse_error ? ("'" + m_lexer.get_token() + "'") :
8072  lexer::token_type_name(last_token));
8073  error_msg += "; expected " + lexer::token_type_name(t);
8074  throw std::invalid_argument(error_msg);
8075  }
8076  }
8077 
8078  void unexpect(typename lexer::token_type t) const
8079  {
8080  if (t == last_token)
8081  {
8082  std::string error_msg = "parse error - unexpected ";
8083  error_msg += (last_token == lexer::token_type::parse_error ? ("'" + m_lexer.get_token() + "'") :
8084  lexer::token_type_name(last_token));
8085  throw std::invalid_argument(error_msg);
8086  }
8087  }
8088 
8089  private:
8091  int depth = 0;
8093  parser_callback_t callback;
8095  typename lexer::token_type last_token = lexer::token_type::uninitialized;
8097  lexer m_lexer;
8098  };
8099 };
8100 
8101 
8103 // presets //
8105 
8115 }
8116 
8117 
8119 // nonmember functions //
8121 
8122 // specialization of std::swap, and std::hash
8123 namespace std
8124 {
8130 template <>
8131 inline void swap(nlohmann::json& j1,
8132  nlohmann::json& j2) noexcept(
8133  is_nothrow_move_constructible<nlohmann::json>::value and
8134  is_nothrow_move_assignable<nlohmann::json>::value
8135  )
8136 {
8137  j1.swap(j2);
8138 }
8139 
8141 template <>
8142 struct hash<nlohmann::json>
8143 {
8149  std::size_t operator()(const nlohmann::json& j) const
8150  {
8151  // a naive hashing via the string representation
8152  const auto& h = hash<nlohmann::json::string_t>();
8153  return h(j.dump());
8154  }
8155 };
8156 }
8157 
8170 inline nlohmann::json operator "" _json(const char* s, std::size_t)
8171 {
8172  return nlohmann::json::parse(reinterpret_cast<const nlohmann::json::string_t::value_type*>(s));
8173 }
8174 
8175 #endif
bool operator!=(const const_iterator &other) const
comparison: not equal
Definition: json.hpp:6171
iterator insert(const_iterator pos, basic_json &&val)
inserts element
Definition: json.hpp:4454
iterator operator++(int)
post-increment (it++)
Definition: json.hpp:6419
friend bool operator<=(const_reference lhs, const_reference rhs) noexcept
comparison: less than or equal
Definition: json.hpp:5065
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:6574
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:2952
typename basic_json::const_pointer pointer
defines a pointer to the type iterated over (value_type)
Definition: json.hpp:5843
static iteration_proxy< iterator > iterator_wrapper(reference cont)
wrapper to access iterator member functions in range-based for
Definition: json.hpp:3988
const_iterator & operator--()
pre-decrement (–it)
Definition: json.hpp:6112
friend std::istream & operator>>(std::istream &i, basic_json &j)
deserialize from stream
Definition: json.hpp:5278
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:5912
typename basic_json::value_type value_type
the type of the values when the iterator is dereferenced
Definition: json.hpp:5839
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
const_reference operator[](T *key) const
read-only access specified object element
Definition: json.hpp:3201
iterator insert(const_iterator pos, const_iterator first, const_iterator last)
inserts elements
Definition: json.hpp:4536
iterator insert(const_iterator pos, size_type cnt, const basic_json &val)
inserts elements
Definition: json.hpp:4483
json_reverse_iterator operator--(int)
post-decrement (it–)
Definition: json.hpp:6546
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:4375
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:6427
friend bool operator!=(const_reference lhs, const_reference rhs) noexcept
comparison: not equal
Definition: json.hpp:4921
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:6075
difference_type operator-(const json_reverse_iterator &other) const
return difference
Definition: json.hpp:6582
basic_json<> json
default JSON class
Definition: json.hpp:8114
reference front()
access the first element
Definition: json.hpp:3319
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:3699
std::reverse_iterator< Base > base_iterator
shortcut to the reverse iterator adaptor
Definition: json.hpp:6518
json_reverse_iterator(const typename base_iterator::iterator_type &it)
create reverse iterator from iterator
Definition: json.hpp:6523
a class to store JSON values
Definition: json.hpp:188
json_reverse_iterator & operator--()
pre-decrement (–it)
Definition: json.hpp:6552
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:4900
void push_back(basic_json &&val)
add an object to an array
Definition: json.hpp:4289
const_iterator cbegin() const
returns a const iterator to the first element
Definition: json.hpp:3799
reference operator[](T *key)
access specified object element
Definition: json.hpp:3152
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:6449
const PointerType get_ptr() const noexcept
get a pointer value (implicit)
Definition: json.hpp:2589
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:4315
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:6374
iterator & operator-=(difference_type i)
subtract from iterator
Definition: json.hpp:6456
static basic_json parse(std::istream &&i, parser_callback_t cb=nullptr)
deserialize from stream
Definition: json.hpp:5240
reference operator[](const typename object_t::key_type &key)
access specified object element
Definition: json.hpp:2993
STL namespace.
difference_type operator-(const iterator &other) const
Definition: json.hpp:6478
reference value() const
return the value of an iterator
Definition: json.hpp:6350
static iteration_proxy< const_iterator > iterator_wrapper(const_reference cont)
wrapper to access iterator member functions in range-based for
Definition: json.hpp:3996
const_iterator end() const
returns a const iterator to one past the last element
Definition: json.hpp:3834
const_iterator(const const_iterator &other) noexcept
copy constructor
Definition: json.hpp:5907
reference at(const typename object_t::key_type &key)
access specified object element with bounds checking
Definition: json.hpp:2812
object_t::key_type key() const
return the key of an object iterator
Definition: json.hpp:6335
iterator end()
returns an iterator to one past the last element
Definition: json.hpp:3824
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:6407
reverse_iterator rend()
returns an iterator to the reverse-end
Definition: json.hpp:3913
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:6267
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:5845
const_reverse_iterator rend() const
returns a const reverse iterator to one before the first
Definition: json.hpp:3921
size_type erase(const typename object_t::key_type &key)
remove element from a JSON object given a key
Definition: json.hpp:3608
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:3765
const_reference at(const typename object_t::key_type &key) const
access specified object element with bounds checking
Definition: json.hpp:2860
reference operator+=(const basic_json &val)
add an object to an array
Definition: json.hpp:4349
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
reference operator[](T *(&key)[n])
access specified object element
Definition: json.hpp:3084
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:6463
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:3682
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:5109
iterator & operator--()
pre-decrement (–it)
Definition: json.hpp:6442
friend bool operator<(const_reference lhs, const_reference rhs) noexcept
comparison: less than
Definition: json.hpp:4982
pointer operator->() const
dereference the iterator
Definition: json.hpp:6032
const_reference operator[](const typename object_t::key_type &key) const
read-only access specified object element
Definition: json.hpp:3041
const_iterator cend() const
returns a const iterator to one past the last element
Definition: json.hpp:3858
typename Base::reference reference
the reference type for the pointed-to element
Definition: json.hpp:6520
size_type size() const noexcept
returns the number of elements
Definition: json.hpp:4098
static allocator_type get_allocator()
returns the allocator associated with the container
Definition: json.hpp:250
object (unordered set of name/value pairs)
ReferenceType get_ref()
get a reference value (implicit)
Definition: json.hpp:2625
reference at(size_type idx)
access specified array element with bounds checking
Definition: json.hpp:2720
json_reverse_iterator(const base_iterator &it)
create reverse iterator from base class
Definition: json.hpp:6528
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:5164
ValueType value(const typename object_t::key_type &key, ValueType default_value) const
access specified object element with default value
Definition: json.hpp:3268
object_t::key_type key() const
return the key of an object iterator
Definition: json.hpp:6594
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:5841
void swap(array_t &other)
exchanges the values
Definition: json.hpp:4663
reverse_iterator rbegin()
returns an iterator to the reverse-beginning
Definition: json.hpp:3882
reference operator+=(const typename object_t::value_type &val)
add an object to an object
Definition: json.hpp:4399
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:6484
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:3890
~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:6259
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
ReferenceType get_ref() const
get a reference value (implicit)
Definition: json.hpp:2640
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:4731
reference value() const
return the value of an iterator
Definition: json.hpp:6490
const_iterator operator--(int)
post-decrement (it–)
Definition: json.hpp:6104
ValueType get() const
get a value (explicit)
Definition: json.hpp:2490
void erase(const size_type idx)
remove element from a JSON array given an index
Definition: json.hpp:3646
void clear() noexcept
clears the contents
Definition: json.hpp:4219
pointer operator->()
dereference the iterator
Definition: json.hpp:6413
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:3327
bool operator>=(const const_iterator &other) const
comparison: greater than or equal
Definition: json.hpp:6219
iterator insert(const_iterator pos, std::initializer_list< basic_json > ilist)
inserts elements
Definition: json.hpp:4594
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:6225
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:6275
friend bool operator==(const_reference lhs, const_reference rhs) noexcept
comparison: equal
Definition: json.hpp:4811
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:3967
bool empty() const noexcept
checks whether the container is empty
Definition: json.hpp:4040
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:3294
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:4632
const_reference operator[](T *(&key)[n]) const
read-only access specified object element
Definition: json.hpp:3119
const_reverse_iterator crbegin() const
returns a const reverse iterator to the last element
Definition: json.hpp:3944
reference value() const
return the value of an iterator
Definition: json.hpp:6601
const_iterator(pointer object)
constructor for a given JSON instance
Definition: json.hpp:5853
friend bool operator<(const value_t lhs, const value_t rhs)
comparison operator for JSON types
Definition: json.hpp:4765
iterator(pointer object) noexcept
constructor for a given JSON instance
Definition: json.hpp:6385
bool operator<(const const_iterator &other) const
comparison: smaller
Definition: json.hpp:6177
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:4944
const_iterator & operator-=(difference_type i)
subtract from iterator
Definition: json.hpp:6253
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:5203
InteratorType erase(InteratorType first, InteratorType last)
remove elements given an iterator range
Definition: json.hpp:3525
json_reverse_iterator operator++(int)
post-increment (it++)
Definition: json.hpp:6533
PointerType get_ptr() noexcept
get a pointer value (implicit)
Definition: json.hpp:2574
const_iterator(const iterator &other)
copy constructor given a nonconst iterator
Definition: json.hpp:5880
friend bool operator!=(std::nullptr_t, const_reference v) noexcept
comparison: not equal
Definition: json.hpp:4953
InteratorType erase(InteratorType pos)
remove element given an iterator
Definition: json.hpp:3420
bool operator<=(const const_iterator &other) const
comparison: less than or equal
Definition: json.hpp:6207
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:3353
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:6067
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:6390
const_reference back() const
access the last element
Definition: json.hpp:3363
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:5232
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:3730
size_type max_size() const noexcept
returns the maximum possible number of elements
Definition: json.hpp:4160
void push_back(const basic_json &val)
add an object to an array
Definition: json.hpp:4325
bool operator==(const const_iterator &other) const
comparison: equal
Definition: json.hpp:6141
json_reverse_iterator & operator++()
pre-increment (++it)
Definition: json.hpp:6539
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:6213
friend bool operator>(const_reference lhs, const_reference rhs) noexcept
comparison: greater than
Definition: json.hpp:5087
basic_json(basic_json &&other) noexcept
move constructor
Definition: json.hpp:1752
const_iterator begin() const
returns a const iterator to the first element
Definition: json.hpp:3775
const_reference at(size_type idx) const
access specified array element with bounds checking
Definition: json.hpp:2764
json_reverse_iterator & operator+=(difference_type i)
add to iterator
Definition: json.hpp:6559
a const random access iterator for the basic_json class
Definition: json.hpp:5832
a template for a reverse iterator class
Definition: json.hpp:233
void swap(object_t &other)
exchanges the values
Definition: json.hpp:4697
std::bidirectional_iterator_tag iterator_category
the category of the iterator
Definition: json.hpp:5847
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:4427
friend bool operator==(const_reference v, std::nullptr_t) noexcept
comparison: equal
Definition: json.hpp:4891
reference operator[](difference_type n) const
access to successor
Definition: json.hpp:6588
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:6299
reference operator*() const
return a reference to the value pointed to by the iterator
Definition: json.hpp:5992
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:5268
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:8149
friend std::ostream & operator<<(std::ostream &o, const basic_json &j)
serialize to stream
Definition: json.hpp:5146
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:6395
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:2907
iterator operator--(int)
post-decrement (it–)
Definition: json.hpp:6434
json_reverse_iterator operator+(difference_type i) const
add to iterator
Definition: json.hpp:6566
parse_event_t
JSON callback events.
Definition: json.hpp:755
iterator operator-(difference_type i)
subtract from iterator
Definition: json.hpp:6471