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  and not std::is_same<ValueType, std::initializer_list<typename string_t::value_type>>::value
2679  , int>::type = 0>
2680  operator ValueType() const
2681  {
2682  // delegate the call to get<>() const
2683  return get<ValueType>();
2684  }
2685 
2687 
2688 
2690  // element access //
2692 
2695 
2719  {
2720  // at only works for arrays
2721  if (is_array())
2722  {
2723  try
2724  {
2725  assert(m_value.array != nullptr);
2726  return m_value.array->at(idx);
2727  }
2728  catch (std::out_of_range&)
2729  {
2730  // create better exception explanation
2731  throw std::out_of_range("array index " + std::to_string(idx) + " is out of range");
2732  }
2733  }
2734  else
2735  {
2736  throw std::domain_error("cannot use at() with " + type_name());
2737  }
2738  }
2739 
2763  {
2764  // at only works for arrays
2765  if (is_array())
2766  {
2767  try
2768  {
2769  assert(m_value.array != nullptr);
2770  return m_value.array->at(idx);
2771  }
2772  catch (std::out_of_range&)
2773  {
2774  // create better exception explanation
2775  throw std::out_of_range("array index " + std::to_string(idx) + " is out of range");
2776  }
2777  }
2778  else
2779  {
2780  throw std::domain_error("cannot use at() with " + type_name());
2781  }
2782  }
2783 
2810  reference at(const typename object_t::key_type& key)
2811  {
2812  // at only works for objects
2813  if (is_object())
2814  {
2815  try
2816  {
2817  assert(m_value.object != nullptr);
2818  return m_value.object->at(key);
2819  }
2820  catch (std::out_of_range&)
2821  {
2822  // create better exception explanation
2823  throw std::out_of_range("key '" + key + "' not found");
2824  }
2825  }
2826  else
2827  {
2828  throw std::domain_error("cannot use at() with " + type_name());
2829  }
2830  }
2831 
2858  const_reference at(const typename object_t::key_type& key) const
2859  {
2860  // at only works for objects
2861  if (is_object())
2862  {
2863  try
2864  {
2865  assert(m_value.object != nullptr);
2866  return m_value.object->at(key);
2867  }
2868  catch (std::out_of_range&)
2869  {
2870  // create better exception explanation
2871  throw std::out_of_range("key '" + key + "' not found");
2872  }
2873  }
2874  else
2875  {
2876  throw std::domain_error("cannot use at() with " + type_name());
2877  }
2878  }
2879 
2906  {
2907  // implicitly convert null to object
2908  if (is_null())
2909  {
2910  m_type = value_t::array;
2911  m_value.array = create<array_t>();
2912  }
2913 
2914  // [] only works for arrays
2915  if (is_array())
2916  {
2917  assert(m_value.array != nullptr);
2918  for (size_t i = m_value.array->size(); i <= idx; ++i)
2919  {
2920  m_value.array->push_back(basic_json());
2921  }
2922 
2923  return m_value.array->operator[](idx);
2924  }
2925  else
2926  {
2927  throw std::domain_error("cannot use operator[] with " + type_name());
2928  }
2929  }
2930 
2951  {
2952  // at only works for arrays
2953  if (is_array())
2954  {
2955  assert(m_value.array != nullptr);
2956  return m_value.array->operator[](idx);
2957  }
2958  else
2959  {
2960  throw std::domain_error("cannot use operator[] with " + type_name());
2961  }
2962  }
2963 
2991  reference operator[](const typename object_t::key_type& key)
2992  {
2993  // implicitly convert null to object
2994  if (is_null())
2995  {
2996  m_type = value_t::object;
2997  m_value.object = create<object_t>();
2998  }
2999 
3000  // [] only works for objects
3001  if (is_object())
3002  {
3003  assert(m_value.object != nullptr);
3004  return m_value.object->operator[](key);
3005  }
3006  else
3007  {
3008  throw std::domain_error("cannot use operator[] with " + type_name());
3009  }
3010  }
3011 
3039  const_reference operator[](const typename object_t::key_type& key) const
3040  {
3041  // [] only works for objects
3042  if (is_object())
3043  {
3044  assert(m_value.object != nullptr);
3045  assert(m_value.object->find(key) != m_value.object->end());
3046  return m_value.object->find(key)->second;
3047  }
3048  else
3049  {
3050  throw std::domain_error("cannot use operator[] with " + type_name());
3051  }
3052  }
3053 
3083  template<typename T, std::size_t n>
3084  reference operator[](const T (&key)[n])
3085  {
3086  // implicitly convert null to object
3087  if (is_null())
3088  {
3089  m_type = value_t::object;
3090  m_value = value_t::object;
3091  }
3092 
3093  // at only works for objects
3094  if (is_object())
3095  {
3096  assert(m_value.object != nullptr);
3097  return m_value.object->operator[](key);
3098  }
3099  else
3100  {
3101  throw std::domain_error("cannot use operator[] with " + type_name());
3102  }
3103  }
3104 
3134  template<typename T, std::size_t n>
3135  const_reference operator[](const T (&key)[n]) const
3136  {
3137  // at only works for objects
3138  if (is_object())
3139  {
3140  assert(m_value.object != nullptr);
3141  assert(m_value.object->find(key) != m_value.object->end());
3142  return m_value.object->find(key)->second;
3143  }
3144  else
3145  {
3146  throw std::domain_error("cannot use operator[] with " + type_name());
3147  }
3148  }
3149 
3198  template <class ValueType, typename
3199  std::enable_if<
3200  std::is_convertible<basic_json_t, ValueType>::value
3201  , int>::type = 0>
3202  ValueType value(const typename object_t::key_type& key, ValueType default_value) const
3203  {
3204  // at only works for objects
3205  if (is_object())
3206  {
3207  // if key is found, return value and given default value otherwise
3208  const auto it = find(key);
3209  if (it != end())
3210  {
3211  return *it;
3212  }
3213  else
3214  {
3215  return default_value;
3216  }
3217  }
3218  else
3219  {
3220  throw std::domain_error("cannot use value() with " + type_name());
3221  }
3222  }
3223 
3228  string_t value(const typename object_t::key_type& key, const char* default_value) const
3229  {
3230  return value(key, string_t(default_value));
3231  }
3232 
3254  {
3255  return *begin();
3256  }
3257 
3262  {
3263  return *cbegin();
3264  }
3265 
3288  {
3289  auto tmp = end();
3290  --tmp;
3291  return *tmp;
3292  }
3293 
3298  {
3299  auto tmp = cend();
3300  --tmp;
3301  return *tmp;
3302  }
3303 
3348  template <class InteratorType, typename
3349  std::enable_if<
3350  std::is_same<InteratorType, typename basic_json_t::iterator>::value or
3351  std::is_same<InteratorType, typename basic_json_t::const_iterator>::value
3352  , int>::type
3353  = 0>
3354  InteratorType erase(InteratorType pos)
3355  {
3356  // make sure iterator fits the current value
3357  if (this != pos.m_object)
3358  {
3359  throw std::domain_error("iterator does not fit current value");
3360  }
3361 
3362  InteratorType result = end();
3363 
3364  switch (m_type)
3365  {
3366  case value_t::boolean:
3367  case value_t::number_float:
3368  case value_t::number_integer:
3369  case value_t::string:
3370  {
3371  if (not pos.m_it.primitive_iterator.is_begin())
3372  {
3373  throw std::out_of_range("iterator out of range");
3374  }
3375 
3376  if (is_string())
3377  {
3378  delete m_value.string;
3379  m_value.string = nullptr;
3380  }
3381 
3382  m_type = value_t::null;
3383  break;
3384  }
3385 
3386  case value_t::object:
3387  {
3388  assert(m_value.object != nullptr);
3389  result.m_it.object_iterator = m_value.object->erase(pos.m_it.object_iterator);
3390  break;
3391  }
3392 
3393  case value_t::array:
3394  {
3395  assert(m_value.array != nullptr);
3396  result.m_it.array_iterator = m_value.array->erase(pos.m_it.array_iterator);
3397  break;
3398  }
3399 
3400  default:
3401  {
3402  throw std::domain_error("cannot use erase() with " + type_name());
3403  }
3404  }
3405 
3406  return result;
3407  }
3408 
3453  template <class InteratorType, typename
3454  std::enable_if<
3455  std::is_same<InteratorType, typename basic_json_t::iterator>::value or
3456  std::is_same<InteratorType, typename basic_json_t::const_iterator>::value
3457  , int>::type
3458  = 0>
3459  InteratorType erase(InteratorType first, InteratorType last)
3460  {
3461  // make sure iterator fits the current value
3462  if (this != first.m_object or this != last.m_object)
3463  {
3464  throw std::domain_error("iterators do not fit current value");
3465  }
3466 
3467  InteratorType result = end();
3468 
3469  switch (m_type)
3470  {
3471  case value_t::boolean:
3472  case value_t::number_float:
3473  case value_t::number_integer:
3474  case value_t::string:
3475  {
3476  if (not first.m_it.primitive_iterator.is_begin() or not last.m_it.primitive_iterator.is_end())
3477  {
3478  throw std::out_of_range("iterators out of range");
3479  }
3480 
3481  if (is_string())
3482  {
3483  delete m_value.string;
3484  m_value.string = nullptr;
3485  }
3486 
3487  m_type = value_t::null;
3488  break;
3489  }
3490 
3491  case value_t::object:
3492  {
3493  assert(m_value.object != nullptr);
3494  result.m_it.object_iterator = m_value.object->erase(first.m_it.object_iterator,
3495  last.m_it.object_iterator);
3496  break;
3497  }
3498 
3499  case value_t::array:
3500  {
3501  assert(m_value.array != nullptr);
3502  result.m_it.array_iterator = m_value.array->erase(first.m_it.array_iterator,
3503  last.m_it.array_iterator);
3504  break;
3505  }
3506 
3507  default:
3508  {
3509  throw std::domain_error("cannot use erase() with " + type_name());
3510  }
3511  }
3512 
3513  return result;
3514  }
3515 
3542  size_type erase(const typename object_t::key_type& key)
3543  {
3544  // this erase only works for objects
3545  if (is_object())
3546  {
3547  assert(m_value.object != nullptr);
3548  return m_value.object->erase(key);
3549  }
3550  else
3551  {
3552  throw std::domain_error("cannot use erase() with " + type_name());
3553  }
3554  }
3555 
3580  void erase(const size_type idx)
3581  {
3582  // this erase only works for arrays
3583  if (is_array())
3584  {
3585  if (idx >= size())
3586  {
3587  throw std::out_of_range("index out of range");
3588  }
3589 
3590  assert(m_value.array != nullptr);
3591  m_value.array->erase(m_value.array->begin() + static_cast<difference_type>(idx));
3592  }
3593  else
3594  {
3595  throw std::domain_error("cannot use erase() with " + type_name());
3596  }
3597  }
3598 
3616  iterator find(typename object_t::key_type key)
3617  {
3618  auto result = end();
3619 
3620  if (is_object())
3621  {
3622  assert(m_value.object != nullptr);
3623  result.m_it.object_iterator = m_value.object->find(key);
3624  }
3625 
3626  return result;
3627  }
3628 
3633  const_iterator find(typename object_t::key_type key) const
3634  {
3635  auto result = cend();
3636 
3637  if (is_object())
3638  {
3639  assert(m_value.object != nullptr);
3640  result.m_it.object_iterator = m_value.object->find(key);
3641  }
3642 
3643  return result;
3644  }
3645 
3664  size_type count(typename object_t::key_type key) const
3665  {
3666  // return 0 for all nonobject types
3667  assert(not is_object() or m_value.object != nullptr);
3668  return is_object() ? m_value.object->count(key) : 0;
3669  }
3670 
3672 
3673 
3675  // iterators //
3677 
3680 
3700  {
3701  iterator result(this);
3702  result.set_begin();
3703  return result;
3704  }
3705 
3710  {
3711  return cbegin();
3712  }
3713 
3734  {
3735  const_iterator result(this);
3736  result.set_begin();
3737  return result;
3738  }
3739 
3759  {
3760  iterator result(this);
3761  result.set_end();
3762  return result;
3763  }
3764 
3769  {
3770  return cend();
3771  }
3772 
3793  {
3794  const_iterator result(this);
3795  result.set_end();
3796  return result;
3797  }
3798 
3817  {
3818  return reverse_iterator(end());
3819  }
3820 
3825  {
3826  return crbegin();
3827  }
3828 
3848  {
3849  return reverse_iterator(begin());
3850  }
3851 
3856  {
3857  return crend();
3858  }
3859 
3879  {
3880  return const_reverse_iterator(cend());
3881  }
3882 
3902  {
3903  return const_reverse_iterator(cbegin());
3904  }
3905 
3906  private:
3907  // forward declaration
3908  template<typename IteratorType> class iteration_proxy;
3909 
3910  public:
3922  static iteration_proxy<iterator> iterator_wrapper(reference cont)
3923  {
3924  return iteration_proxy<iterator>(cont);
3925  }
3926 
3930  static iteration_proxy<const_iterator> iterator_wrapper(const_reference cont)
3931  {
3932  return iteration_proxy<const_iterator>(cont);
3933  }
3934 
3936 
3937 
3939  // capacity //
3941 
3944 
3974  bool empty() const noexcept
3975  {
3976  switch (m_type)
3977  {
3978  case value_t::null:
3979  {
3980  // null values are empty
3981  return true;
3982  }
3983 
3984  case value_t::array:
3985  {
3986  assert(m_value.array != nullptr);
3987  return m_value.array->empty();
3988  }
3989 
3990  case value_t::object:
3991  {
3992  assert(m_value.object != nullptr);
3993  return m_value.object->empty();
3994  }
3995 
3996  default:
3997  {
3998  // all other types are nonempty
3999  return false;
4000  }
4001  }
4002  }
4003 
4032  size_type size() const noexcept
4033  {
4034  switch (m_type)
4035  {
4036  case value_t::null:
4037  {
4038  // null values are empty
4039  return 0;
4040  }
4041 
4042  case value_t::array:
4043  {
4044  assert(m_value.array != nullptr);
4045  return m_value.array->size();
4046  }
4047 
4048  case value_t::object:
4049  {
4050  assert(m_value.object != nullptr);
4051  return m_value.object->size();
4052  }
4053 
4054  default:
4055  {
4056  // all other types have size 1
4057  return 1;
4058  }
4059  }
4060  }
4061 
4094  size_type max_size() const noexcept
4095  {
4096  switch (m_type)
4097  {
4098  case value_t::array:
4099  {
4100  assert(m_value.array != nullptr);
4101  return m_value.array->max_size();
4102  }
4103 
4104  case value_t::object:
4105  {
4106  assert(m_value.object != nullptr);
4107  return m_value.object->max_size();
4108  }
4109 
4110  default:
4111  {
4112  // all other types have max_size() == size()
4113  return size();
4114  }
4115  }
4116  }
4117 
4119 
4120 
4122  // modifiers //
4124 
4127 
4153  void clear() noexcept
4154  {
4155  switch (m_type)
4156  {
4157  case value_t::number_integer:
4158  {
4159  m_value.number_integer = 0;
4160  break;
4161  }
4162 
4163  case value_t::number_float:
4164  {
4165  m_value.number_float = 0.0;
4166  break;
4167  }
4168 
4169  case value_t::boolean:
4170  {
4171  m_value.boolean = false;
4172  break;
4173  }
4174 
4175  case value_t::string:
4176  {
4177  assert(m_value.string != nullptr);
4178  m_value.string->clear();
4179  break;
4180  }
4181 
4182  case value_t::array:
4183  {
4184  assert(m_value.array != nullptr);
4185  m_value.array->clear();
4186  break;
4187  }
4188 
4189  case value_t::object:
4190  {
4191  assert(m_value.object != nullptr);
4192  m_value.object->clear();
4193  break;
4194  }
4195 
4196  default:
4197  {
4198  break;
4199  }
4200  }
4201  }
4202 
4223  void push_back(basic_json&& val)
4224  {
4225  // push_back only works for null objects or arrays
4226  if (not(is_null() or is_array()))
4227  {
4228  throw std::domain_error("cannot use push_back() with " + type_name());
4229  }
4230 
4231  // transform null object into an array
4232  if (is_null())
4233  {
4234  m_type = value_t::array;
4235  m_value = value_t::array;
4236  }
4237 
4238  // add element to array (move semantics)
4239  assert(m_value.array != nullptr);
4240  m_value.array->push_back(std::move(val));
4241  // invalidate object
4242  val.m_type = value_t::null;
4243  }
4244 
4249  reference operator+=(basic_json&& val)
4250  {
4251  push_back(std::move(val));
4252  return *this;
4253  }
4254 
4259  void push_back(const basic_json& val)
4260  {
4261  // push_back only works for null objects or arrays
4262  if (not(is_null() or is_array()))
4263  {
4264  throw std::domain_error("cannot use push_back() with " + type_name());
4265  }
4266 
4267  // transform null object into an array
4268  if (is_null())
4269  {
4270  m_type = value_t::array;
4271  m_value = value_t::array;
4272  }
4273 
4274  // add element to array
4275  assert(m_value.array != nullptr);
4276  m_value.array->push_back(val);
4277  }
4278 
4283  reference operator+=(const basic_json& val)
4284  {
4285  push_back(val);
4286  return *this;
4287  }
4288 
4309  void push_back(const typename object_t::value_type& val)
4310  {
4311  // push_back only works for null objects or objects
4312  if (not(is_null() or is_object()))
4313  {
4314  throw std::domain_error("cannot use push_back() with " + type_name());
4315  }
4316 
4317  // transform null object into an object
4318  if (is_null())
4319  {
4320  m_type = value_t::object;
4321  m_value = value_t::object;
4322  }
4323 
4324  // add element to array
4325  assert(m_value.object != nullptr);
4326  m_value.object->insert(val);
4327  }
4328 
4333  reference operator+=(const typename object_t::value_type& val)
4334  {
4335  push_back(val);
4336  return operator[](val.first);
4337  }
4338 
4361  iterator insert(const_iterator pos, const basic_json& val)
4362  {
4363  // insert only works for arrays
4364  if (is_array())
4365  {
4366  // check if iterator pos fits to this JSON value
4367  if (pos.m_object != this)
4368  {
4369  throw std::domain_error("iterator does not fit current value");
4370  }
4371 
4372  // insert to array and return iterator
4373  iterator result(this);
4374  assert(m_value.array != nullptr);
4375  result.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator, val);
4376  return result;
4377  }
4378  else
4379  {
4380  throw std::domain_error("cannot use insert() with " + type_name());
4381  }
4382  }
4383 
4388  iterator insert(const_iterator pos, basic_json&& val)
4389  {
4390  return insert(pos, val);
4391  }
4392 
4417  iterator insert(const_iterator pos, size_type cnt, const basic_json& val)
4418  {
4419  // insert only works for arrays
4420  if (is_array())
4421  {
4422  // check if iterator pos fits to this JSON value
4423  if (pos.m_object != this)
4424  {
4425  throw std::domain_error("iterator does not fit current value");
4426  }
4427 
4428  // insert to array and return iterator
4429  iterator result(this);
4430  assert(m_value.array != nullptr);
4431  result.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator, cnt, val);
4432  return result;
4433  }
4434  else
4435  {
4436  throw std::domain_error("cannot use insert() with " + type_name());
4437  }
4438  }
4439 
4471  {
4472  // insert only works for arrays
4473  if (not is_array())
4474  {
4475  throw std::domain_error("cannot use insert() with " + type_name());
4476  }
4477 
4478  // check if iterator pos fits to this JSON value
4479  if (pos.m_object != this)
4480  {
4481  throw std::domain_error("iterator does not fit current value");
4482  }
4483 
4484  if (first.m_object != last.m_object)
4485  {
4486  throw std::domain_error("iterators do not fit");
4487  }
4488 
4489  if (first.m_object == this or last.m_object == this)
4490  {
4491  throw std::domain_error("passed iterators may not belong to container");
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(
4498  pos.m_it.array_iterator,
4499  first.m_it.array_iterator,
4500  last.m_it.array_iterator);
4501  return result;
4502  }
4503 
4528  iterator insert(const_iterator pos, std::initializer_list<basic_json> ilist)
4529  {
4530  // insert only works for arrays
4531  if (not is_array())
4532  {
4533  throw std::domain_error("cannot use insert() with " + type_name());
4534  }
4535 
4536  // check if iterator pos fits to this JSON value
4537  if (pos.m_object != this)
4538  {
4539  throw std::domain_error("iterator does not fit current value");
4540  }
4541 
4542  // insert to array and return iterator
4543  iterator result(this);
4544  assert(m_value.array != nullptr);
4545  result.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator, ilist);
4546  return result;
4547  }
4548 
4566  void swap(reference other) noexcept (
4567  std::is_nothrow_move_constructible<value_t>::value and
4568  std::is_nothrow_move_assignable<value_t>::value and
4569  std::is_nothrow_move_constructible<json_value>::value and
4570  std::is_nothrow_move_assignable<json_value>::value
4571  )
4572  {
4573  std::swap(m_type, other.m_type);
4574  std::swap(m_value, other.m_value);
4575  }
4576 
4597  void swap(array_t& other)
4598  {
4599  // swap only works for arrays
4600  if (is_array())
4601  {
4602  assert(m_value.array != nullptr);
4603  std::swap(*(m_value.array), other);
4604  }
4605  else
4606  {
4607  throw std::domain_error("cannot use swap() with " + type_name());
4608  }
4609  }
4610 
4631  void swap(object_t& other)
4632  {
4633  // swap only works for objects
4634  if (is_object())
4635  {
4636  assert(m_value.object != nullptr);
4637  std::swap(*(m_value.object), other);
4638  }
4639  else
4640  {
4641  throw std::domain_error("cannot use swap() with " + type_name());
4642  }
4643  }
4644 
4665  void swap(string_t& other)
4666  {
4667  // swap only works for strings
4668  if (is_string())
4669  {
4670  assert(m_value.string != nullptr);
4671  std::swap(*(m_value.string), other);
4672  }
4673  else
4674  {
4675  throw std::domain_error("cannot use swap() with " + type_name());
4676  }
4677  }
4678 
4680 
4681 
4683  // lexicographical comparison operators //
4685 
4688 
4689  private:
4699  friend bool operator<(const value_t lhs, const value_t rhs)
4700  {
4701  static constexpr std::array<uint8_t, 7> order = {{
4702  0, // null
4703  3, // object
4704  4, // array
4705  5, // string
4706  1, // boolean
4707  2, // integer
4708  2 // float
4709  }
4710  };
4711 
4712  // discarded values are not comparable
4713  if (lhs == value_t::discarded or rhs == value_t::discarded)
4714  {
4715  return false;
4716  }
4717 
4718  return order[static_cast<std::size_t>(lhs)] < order[static_cast<std::size_t>(rhs)];
4719  }
4720 
4721  public:
4745  friend bool operator==(const_reference lhs, const_reference rhs) noexcept
4746  {
4747  const auto lhs_type = lhs.type();
4748  const auto rhs_type = rhs.type();
4749 
4750  if (lhs_type == rhs_type)
4751  {
4752  switch (lhs_type)
4753  {
4754  case value_t::array:
4755  {
4756  assert(lhs.m_value.array != nullptr);
4757  assert(rhs.m_value.array != nullptr);
4758  return *lhs.m_value.array == *rhs.m_value.array;
4759  }
4760  case value_t::object:
4761  {
4762  assert(lhs.m_value.object != nullptr);
4763  assert(rhs.m_value.object != nullptr);
4764  return *lhs.m_value.object == *rhs.m_value.object;
4765  }
4766  case value_t::null:
4767  {
4768  return true;
4769  }
4770  case value_t::string:
4771  {
4772  assert(lhs.m_value.string != nullptr);
4773  assert(rhs.m_value.string != nullptr);
4774  return *lhs.m_value.string == *rhs.m_value.string;
4775  }
4776  case value_t::boolean:
4777  {
4778  return lhs.m_value.boolean == rhs.m_value.boolean;
4779  }
4780  case value_t::number_integer:
4781  {
4782  return lhs.m_value.number_integer == rhs.m_value.number_integer;
4783  }
4784  case value_t::number_float:
4785  {
4786  return approx(lhs.m_value.number_float, rhs.m_value.number_float);
4787  }
4788  default:
4789  {
4790  return false;
4791  }
4792  }
4793  }
4794  else if (lhs_type == value_t::number_integer and rhs_type == value_t::number_float)
4795  {
4796  return approx(static_cast<number_float_t>(lhs.m_value.number_integer),
4797  rhs.m_value.number_float);
4798  }
4799  else if (lhs_type == value_t::number_float and rhs_type == value_t::number_integer)
4800  {
4801  return approx(lhs.m_value.number_float,
4802  static_cast<number_float_t>(rhs.m_value.number_integer));
4803  }
4804  return false;
4805  }
4806 
4825  friend bool operator==(const_reference v, std::nullptr_t) noexcept
4826  {
4827  return v.is_null();
4828  }
4829 
4834  friend bool operator==(std::nullptr_t, const_reference v) noexcept
4835  {
4836  return v.is_null();
4837  }
4838 
4855  friend bool operator!=(const_reference lhs, const_reference rhs) noexcept
4856  {
4857  return not (lhs == rhs);
4858  }
4859 
4878  friend bool operator!=(const_reference v, std::nullptr_t) noexcept
4879  {
4880  return not v.is_null();
4881  }
4882 
4887  friend bool operator!=(std::nullptr_t, const_reference v) noexcept
4888  {
4889  return not v.is_null();
4890  }
4891 
4916  friend bool operator<(const_reference lhs, const_reference rhs) noexcept
4917  {
4918  const auto lhs_type = lhs.type();
4919  const auto rhs_type = rhs.type();
4920 
4921  if (lhs_type == rhs_type)
4922  {
4923  switch (lhs_type)
4924  {
4925  case value_t::array:
4926  {
4927  assert(lhs.m_value.array != nullptr);
4928  assert(rhs.m_value.array != nullptr);
4929  return *lhs.m_value.array < *rhs.m_value.array;
4930  }
4931  case value_t::object:
4932  {
4933  assert(lhs.m_value.object != nullptr);
4934  assert(rhs.m_value.object != nullptr);
4935  return *lhs.m_value.object < *rhs.m_value.object;
4936  }
4937  case value_t::null:
4938  {
4939  return false;
4940  }
4941  case value_t::string:
4942  {
4943  assert(lhs.m_value.string != nullptr);
4944  assert(rhs.m_value.string != nullptr);
4945  return *lhs.m_value.string < *rhs.m_value.string;
4946  }
4947  case value_t::boolean:
4948  {
4949  return lhs.m_value.boolean < rhs.m_value.boolean;
4950  }
4951  case value_t::number_integer:
4952  {
4953  return lhs.m_value.number_integer < rhs.m_value.number_integer;
4954  }
4955  case value_t::number_float:
4956  {
4957  return lhs.m_value.number_float < rhs.m_value.number_float;
4958  }
4959  default:
4960  {
4961  return false;
4962  }
4963  }
4964  }
4965  else if (lhs_type == value_t::number_integer and rhs_type == value_t::number_float)
4966  {
4967  return static_cast<number_float_t>(lhs.m_value.number_integer) <
4968  rhs.m_value.number_float;
4969  }
4970  else if (lhs_type == value_t::number_float and rhs_type == value_t::number_integer)
4971  {
4972  return lhs.m_value.number_float <
4973  static_cast<number_float_t>(rhs.m_value.number_integer);
4974  }
4975 
4976  // We only reach this line if we cannot compare values. In that case,
4977  // we compare types. Note we have to call the operator explicitly,
4978  // because MSVC has problems otherwise.
4979  return operator<(lhs_type, rhs_type);
4980  }
4981 
4999  friend bool operator<=(const_reference lhs, const_reference rhs) noexcept
5000  {
5001  return not (rhs < lhs);
5002  }
5003 
5021  friend bool operator>(const_reference lhs, const_reference rhs) noexcept
5022  {
5023  return not (lhs <= rhs);
5024  }
5025 
5043  friend bool operator>=(const_reference lhs, const_reference rhs) noexcept
5044  {
5045  return not (lhs < rhs);
5046  }
5047 
5049 
5050 
5052  // serialization //
5054 
5057 
5080  friend std::ostream& operator<<(std::ostream& o, const basic_json& j)
5081  {
5082  // read width member and use it as indentation parameter if nonzero
5083  const bool pretty_print = (o.width() > 0);
5084  const auto indentation = (pretty_print ? o.width() : 0);
5085 
5086  // reset width to 0 for subsequent calls to this stream
5087  o.width(0);
5088 
5089  // do the actual serialization
5090  j.dump(o, pretty_print, static_cast<unsigned int>(indentation));
5091  return o;
5092  }
5093 
5098  friend std::ostream& operator>>(const basic_json& j, std::ostream& o)
5099  {
5100  return o << j;
5101  }
5102 
5104 
5105 
5107  // deserialization //
5109 
5112 
5137  static basic_json parse(const string_t& s, parser_callback_t cb = nullptr)
5138  {
5139  return parser(s, cb).parse();
5140  }
5141 
5166  static basic_json parse(std::istream& i, parser_callback_t cb = nullptr)
5167  {
5168  return parser(i, cb).parse();
5169  }
5170 
5174  static basic_json parse(std::istream&& i, parser_callback_t cb = nullptr)
5175  {
5176  return parser(i, cb).parse();
5177  }
5178 
5202  friend std::istream& operator<<(basic_json& j, std::istream& i)
5203  {
5204  j = parser(i).parse();
5205  return i;
5206  }
5207 
5212  friend std::istream& operator>>(std::istream& i, basic_json& j)
5213  {
5214  j = parser(i).parse();
5215  return i;
5216  }
5217 
5219 
5220 
5221  private:
5223  // convenience functions //
5225 
5227  string_t type_name() const
5228  {
5229  switch (m_type)
5230  {
5231  case value_t::null:
5232  return "null";
5233  case value_t::object:
5234  return "object";
5235  case value_t::array:
5236  return "array";
5237  case value_t::string:
5238  return "string";
5239  case value_t::boolean:
5240  return "boolean";
5241  case value_t::discarded:
5242  return "discarded";
5243  default:
5244  return "number";
5245  }
5246  }
5247 
5256  static std::size_t extra_space(const string_t& s) noexcept
5257  {
5258  std::size_t result = 0;
5259 
5260  for (const auto& c : s)
5261  {
5262  switch (c)
5263  {
5264  case '"':
5265  case '\\':
5266  case '\b':
5267  case '\f':
5268  case '\n':
5269  case '\r':
5270  case '\t':
5271  {
5272  // from c (1 byte) to \x (2 bytes)
5273  result += 1;
5274  break;
5275  }
5276 
5277  default:
5278  {
5279  if (c >= 0x00 and c <= 0x1f)
5280  {
5281  // from c (1 byte) to \uxxxx (6 bytes)
5282  result += 5;
5283  }
5284  break;
5285  }
5286  }
5287  }
5288 
5289  return result;
5290  }
5291 
5305  static string_t escape_string(const string_t& s) noexcept
5306  {
5307  const auto space = extra_space(s);
5308  if (space == 0)
5309  {
5310  return s;
5311  }
5312 
5313  // create a result string of necessary size
5314  string_t result(s.size() + space, '\\');
5315  std::size_t pos = 0;
5316 
5317  for (const auto& c : s)
5318  {
5319  switch (c)
5320  {
5321  // quotation mark (0x22)
5322  case '"':
5323  {
5324  result[pos + 1] = '"';
5325  pos += 2;
5326  break;
5327  }
5328 
5329  // reverse solidus (0x5c)
5330  case '\\':
5331  {
5332  // nothing to change
5333  pos += 2;
5334  break;
5335  }
5336 
5337  // backspace (0x08)
5338  case '\b':
5339  {
5340  result[pos + 1] = 'b';
5341  pos += 2;
5342  break;
5343  }
5344 
5345  // formfeed (0x0c)
5346  case '\f':
5347  {
5348  result[pos + 1] = 'f';
5349  pos += 2;
5350  break;
5351  }
5352 
5353  // newline (0x0a)
5354  case '\n':
5355  {
5356  result[pos + 1] = 'n';
5357  pos += 2;
5358  break;
5359  }
5360 
5361  // carriage return (0x0d)
5362  case '\r':
5363  {
5364  result[pos + 1] = 'r';
5365  pos += 2;
5366  break;
5367  }
5368 
5369  // horizontal tab (0x09)
5370  case '\t':
5371  {
5372  result[pos + 1] = 't';
5373  pos += 2;
5374  break;
5375  }
5376 
5377  default:
5378  {
5379  if (c >= 0x00 and c <= 0x1f)
5380  {
5381  // convert a number 0..15 to its hex representation (0..f)
5382  auto hexify = [](const char v) -> char
5383  {
5384  return (v < 10) ? ('0' + v) : ('a' + v - 10);
5385  };
5386 
5387  // print character c as \uxxxx
5388  for (const char m :
5389  { 'u', '0', '0', hexify(c >> 4), hexify(c & 0x0f)
5390  })
5391  {
5392  result[++pos] = m;
5393  }
5394 
5395  ++pos;
5396  }
5397  else
5398  {
5399  // all other characters are added as-is
5400  result[pos++] = c;
5401  }
5402  break;
5403  }
5404  }
5405  }
5406 
5407  return result;
5408  }
5409 
5427  void dump(std::ostream& o,
5428  const bool pretty_print,
5429  const unsigned int indent_step,
5430  const unsigned int current_indent = 0) const
5431  {
5432  // variable to hold indentation for recursive calls
5433  unsigned int new_indent = current_indent;
5434 
5435  switch (m_type)
5436  {
5437  case value_t::object:
5438  {
5439  assert(m_value.object != nullptr);
5440 
5441  if (m_value.object->empty())
5442  {
5443  o << "{}";
5444  return;
5445  }
5446 
5447  o << "{";
5448 
5449  // increase indentation
5450  if (pretty_print)
5451  {
5452  new_indent += indent_step;
5453  o << "\n";
5454  }
5455 
5456  for (auto i = m_value.object->cbegin(); i != m_value.object->cend(); ++i)
5457  {
5458  if (i != m_value.object->cbegin())
5459  {
5460  o << (pretty_print ? ",\n" : ",");
5461  }
5462  o << string_t(new_indent, ' ') << "\""
5463  << escape_string(i->first) << "\":"
5464  << (pretty_print ? " " : "");
5465  i->second.dump(o, pretty_print, indent_step, new_indent);
5466  }
5467 
5468  // decrease indentation
5469  if (pretty_print)
5470  {
5471  new_indent -= indent_step;
5472  o << "\n";
5473  }
5474 
5475  o << string_t(new_indent, ' ') + "}";
5476  return;
5477  }
5478 
5479  case value_t::array:
5480  {
5481  assert(m_value.array != nullptr);
5482 
5483  if (m_value.array->empty())
5484  {
5485  o << "[]";
5486  return;
5487  }
5488 
5489  o << "[";
5490 
5491  // increase indentation
5492  if (pretty_print)
5493  {
5494  new_indent += indent_step;
5495  o << "\n";
5496  }
5497 
5498  for (auto i = m_value.array->cbegin(); i != m_value.array->cend(); ++i)
5499  {
5500  if (i != m_value.array->cbegin())
5501  {
5502  o << (pretty_print ? ",\n" : ",");
5503  }
5504  o << string_t(new_indent, ' ');
5505  i->dump(o, pretty_print, indent_step, new_indent);
5506  }
5507 
5508  // decrease indentation
5509  if (pretty_print)
5510  {
5511  new_indent -= indent_step;
5512  o << "\n";
5513  }
5514 
5515  o << string_t(new_indent, ' ') << "]";
5516  return;
5517  }
5518 
5519  case value_t::string:
5520  {
5521  assert(m_value.string != nullptr);
5522  o << string_t("\"") << escape_string(*m_value.string) << "\"";
5523  return;
5524  }
5525 
5526  case value_t::boolean:
5527  {
5528  o << (m_value.boolean ? "true" : "false");
5529  return;
5530  }
5531 
5532  case value_t::number_integer:
5533  {
5534  o << m_value.number_integer;
5535  return;
5536  }
5537 
5538  case value_t::number_float:
5539  {
5540  // 15 digits of precision allows round-trip IEEE 754
5541  // string->double->string; to be safe, we read this value from
5542  // std::numeric_limits<number_float_t>::digits10
5543  o << std::setprecision(std::numeric_limits<number_float_t>::digits10) << m_value.number_float;
5544  return;
5545  }
5546 
5547  case value_t::discarded:
5548  {
5549  o << "<discarded>";
5550  return;
5551  }
5552 
5553  case value_t::null:
5554  {
5555  o << "null";
5556  return;
5557  }
5558  }
5559  }
5560 
5561  private:
5563  // member variables //
5565 
5567  value_t m_type = value_t::null;
5568 
5570  json_value m_value = {};
5571 
5572 
5573  private:
5575  // iterators //
5577 
5587  class primitive_iterator_t
5588  {
5589  public:
5591  void set_begin()
5592  {
5593  m_it = begin_value;
5594  }
5595 
5597  void set_end()
5598  {
5599  m_it = end_value;
5600  }
5601 
5603  bool is_begin() const
5604  {
5605  return (m_it == begin_value);
5606  }
5607 
5609  bool is_end() const
5610  {
5611  return (m_it == end_value);
5612  }
5613 
5615  operator difference_type& ()
5616  {
5617  return m_it;
5618  }
5619 
5621  operator difference_type () const
5622  {
5623  return m_it;
5624  }
5625 
5626  private:
5627  static constexpr difference_type begin_value = 0;
5628  static constexpr difference_type end_value = begin_value + 1;
5629 
5631  difference_type m_it = std::numeric_limits<std::ptrdiff_t>::denorm_min();
5632  };
5633 
5641  struct internal_iterator
5642  {
5644  typename object_t::iterator object_iterator;
5646  typename array_t::iterator array_iterator;
5648  primitive_iterator_t primitive_iterator;
5649 
5651  internal_iterator()
5652  : object_iterator(), array_iterator(), primitive_iterator()
5653  {}
5654  };
5655 
5657  template<typename IteratorType>
5658  class iteration_proxy
5659  {
5660  private:
5662  class iteration_proxy_internal
5663  {
5664  private:
5666  IteratorType anchor;
5668  size_t array_index = 0;
5669 
5670  public:
5671  iteration_proxy_internal(IteratorType it)
5672  : anchor(it)
5673  {}
5674 
5676  iteration_proxy_internal& operator*()
5677  {
5678  return *this;
5679  }
5680 
5682  iteration_proxy_internal& operator++()
5683  {
5684  ++anchor;
5685  ++array_index;
5686 
5687  return *this;
5688  }
5689 
5691  bool operator!= (const iteration_proxy_internal& o) const
5692  {
5693  return anchor != o.anchor;
5694  }
5695 
5697  typename basic_json::string_t key() const
5698  {
5699  assert(anchor.m_object != nullptr);
5700 
5701  switch (anchor.m_object->type())
5702  {
5703  // use integer array index as key
5704  case value_t::array:
5705  {
5706  return std::to_string(array_index);
5707  }
5708 
5709  // use key from the object
5710  case value_t::object:
5711  {
5712  return anchor.key();
5713  }
5714 
5715  // use an empty key for all primitive types
5716  default:
5717  {
5718  return "";
5719  }
5720  }
5721  }
5722 
5724  typename IteratorType::reference value() const
5725  {
5726  return anchor.value();
5727  }
5728  };
5729 
5731  typename IteratorType::reference container;
5732 
5733  public:
5735  iteration_proxy(typename IteratorType::reference cont)
5736  : container(cont)
5737  {}
5738 
5740  iteration_proxy_internal begin()
5741  {
5742  return iteration_proxy_internal(container.begin());
5743  }
5744 
5746  iteration_proxy_internal end()
5747  {
5748  return iteration_proxy_internal(container.end());
5749  }
5750  };
5751 
5752  public:
5766  class const_iterator : public std::iterator<std::random_access_iterator_tag, const basic_json>
5767  {
5769  friend class basic_json;
5770 
5771  public:
5781  using iterator_category = std::bidirectional_iterator_tag;
5782 
5784  const_iterator() = default;
5785 
5787  const_iterator(pointer object) : m_object(object)
5788  {
5789  assert(m_object != nullptr);
5790 
5791  switch (m_object->m_type)
5792  {
5794  {
5795  m_it.object_iterator = typename object_t::iterator();
5796  break;
5797  }
5798 
5800  {
5801  m_it.array_iterator = typename array_t::iterator();
5802  break;
5803  }
5804 
5805  default:
5806  {
5807  m_it.primitive_iterator = primitive_iterator_t();
5808  break;
5809  }
5810  }
5811  }
5812 
5814  const_iterator(const iterator& other) : m_object(other.m_object)
5815  {
5816  assert(m_object != nullptr);
5817 
5818  switch (m_object->m_type)
5819  {
5821  {
5822  m_it.object_iterator = other.m_it.object_iterator;
5823  break;
5824  }
5825 
5827  {
5828  m_it.array_iterator = other.m_it.array_iterator;
5829  break;
5830  }
5831 
5832  default:
5833  {
5834  m_it.primitive_iterator = other.m_it.primitive_iterator;
5835  break;
5836  }
5837  }
5838  }
5839 
5841  const_iterator(const const_iterator& other) noexcept
5842  : m_object(other.m_object), m_it(other.m_it)
5843  {}
5844 
5847  std::is_nothrow_move_constructible<pointer>::value and
5848  std::is_nothrow_move_assignable<pointer>::value and
5849  std::is_nothrow_move_constructible<internal_iterator>::value and
5850  std::is_nothrow_move_assignable<internal_iterator>::value
5851  )
5852  {
5853  std::swap(m_object, other.m_object);
5854  std::swap(m_it, other.m_it);
5855  return *this;
5856  }
5857 
5858  private:
5860  void set_begin()
5861  {
5862  assert(m_object != nullptr);
5863 
5864  switch (m_object->m_type)
5865  {
5867  {
5868  assert(m_object->m_value.object != nullptr);
5869  m_it.object_iterator = m_object->m_value.object->begin();
5870  break;
5871  }
5872 
5874  {
5875  assert(m_object->m_value.array != nullptr);
5876  m_it.array_iterator = m_object->m_value.array->begin();
5877  break;
5878  }
5879 
5881  {
5882  // set to end so begin()==end() is true: null is empty
5883  m_it.primitive_iterator.set_end();
5884  break;
5885  }
5886 
5887  default:
5888  {
5889  m_it.primitive_iterator.set_begin();
5890  break;
5891  }
5892  }
5893  }
5894 
5896  void set_end()
5897  {
5898  assert(m_object != nullptr);
5899 
5900  switch (m_object->m_type)
5901  {
5903  {
5904  assert(m_object->m_value.object != nullptr);
5905  m_it.object_iterator = m_object->m_value.object->end();
5906  break;
5907  }
5908 
5910  {
5911  assert(m_object->m_value.array != nullptr);
5912  m_it.array_iterator = m_object->m_value.array->end();
5913  break;
5914  }
5915 
5916  default:
5917  {
5918  m_it.primitive_iterator.set_end();
5919  break;
5920  }
5921  }
5922  }
5923 
5924  public:
5927  {
5928  assert(m_object != nullptr);
5929 
5930  switch (m_object->m_type)
5931  {
5933  {
5934  assert(m_object->m_value.object);
5935  assert(m_it.object_iterator != m_object->m_value.object->end());
5936  return m_it.object_iterator->second;
5937  }
5938 
5940  {
5941  assert(m_object->m_value.array);
5942  assert(m_it.array_iterator != m_object->m_value.array->end());
5943  return *m_it.array_iterator;
5944  }
5945 
5947  {
5948  throw std::out_of_range("cannot get value");
5949  }
5950 
5951  default:
5952  {
5953  if (m_it.primitive_iterator.is_begin())
5954  {
5955  return *m_object;
5956  }
5957  else
5958  {
5959  throw std::out_of_range("cannot get value");
5960  }
5961  }
5962  }
5963  }
5964 
5967  {
5968  assert(m_object != nullptr);
5969 
5970  switch (m_object->m_type)
5971  {
5973  {
5974  assert(m_object->m_value.object);
5975  assert(m_it.object_iterator != m_object->m_value.object->end());
5976  return &(m_it.object_iterator->second);
5977  }
5978 
5980  {
5981  assert(m_object->m_value.array);
5982  assert(m_it.array_iterator != m_object->m_value.array->end());
5983  return &*m_it.array_iterator;
5984  }
5985 
5986  default:
5987  {
5988  if (m_it.primitive_iterator.is_begin())
5989  {
5990  return m_object;
5991  }
5992  else
5993  {
5994  throw std::out_of_range("cannot get value");
5995  }
5996  }
5997  }
5998  }
5999 
6002  {
6003  auto result = *this;
6004  ++(*this);
6005  return result;
6006  }
6007 
6010  {
6011  assert(m_object != nullptr);
6012 
6013  switch (m_object->m_type)
6014  {
6016  {
6017  ++m_it.object_iterator;
6018  break;
6019  }
6020 
6022  {
6023  ++m_it.array_iterator;
6024  break;
6025  }
6026 
6027  default:
6028  {
6029  ++m_it.primitive_iterator;
6030  break;
6031  }
6032  }
6033 
6034  return *this;
6035  }
6036 
6039  {
6040  auto result = *this;
6041  --(*this);
6042  return result;
6043  }
6044 
6047  {
6048  assert(m_object != nullptr);
6049 
6050  switch (m_object->m_type)
6051  {
6053  {
6054  --m_it.object_iterator;
6055  break;
6056  }
6057 
6059  {
6060  --m_it.array_iterator;
6061  break;
6062  }
6063 
6064  default:
6065  {
6066  --m_it.primitive_iterator;
6067  break;
6068  }
6069  }
6070 
6071  return *this;
6072  }
6073 
6075  bool operator==(const const_iterator& other) const
6076  {
6077  // if objects are not the same, the comparison is undefined
6078  if (m_object != other.m_object)
6079  {
6080  throw std::domain_error("cannot compare iterators of different containers");
6081  }
6082 
6083  assert(m_object != nullptr);
6084 
6085  switch (m_object->m_type)
6086  {
6088  {
6089  return (m_it.object_iterator == other.m_it.object_iterator);
6090  }
6091 
6093  {
6094  return (m_it.array_iterator == other.m_it.array_iterator);
6095  }
6096 
6097  default:
6098  {
6099  return (m_it.primitive_iterator == other.m_it.primitive_iterator);
6100  }
6101  }
6102  }
6103 
6105  bool operator!=(const const_iterator& other) const
6106  {
6107  return not operator==(other);
6108  }
6109 
6111  bool operator<(const const_iterator& other) const
6112  {
6113  // if objects are not the same, the comparison is undefined
6114  if (m_object != other.m_object)
6115  {
6116  throw std::domain_error("cannot compare iterators of different containers");
6117  }
6118 
6119  assert(m_object != nullptr);
6120 
6121  switch (m_object->m_type)
6122  {
6124  {
6125  throw std::domain_error("cannot compare order of object iterators");
6126  }
6127 
6129  {
6130  return (m_it.array_iterator < other.m_it.array_iterator);
6131  }
6132 
6133  default:
6134  {
6135  return (m_it.primitive_iterator < other.m_it.primitive_iterator);
6136  }
6137  }
6138  }
6139 
6141  bool operator<=(const const_iterator& other) const
6142  {
6143  return not other.operator < (*this);
6144  }
6145 
6147  bool operator>(const const_iterator& other) const
6148  {
6149  return not operator<=(other);
6150  }
6151 
6153  bool operator>=(const const_iterator& other) const
6154  {
6155  return not operator<(other);
6156  }
6157 
6160  {
6161  assert(m_object != nullptr);
6162 
6163  switch (m_object->m_type)
6164  {
6166  {
6167  throw std::domain_error("cannot use offsets with object iterators");
6168  }
6169 
6171  {
6172  m_it.array_iterator += i;
6173  break;
6174  }
6175 
6176  default:
6177  {
6178  m_it.primitive_iterator += i;
6179  break;
6180  }
6181  }
6182 
6183  return *this;
6184  }
6185 
6188  {
6189  return operator+=(-i);
6190  }
6191 
6194  {
6195  auto result = *this;
6196  result += i;
6197  return result;
6198  }
6199 
6202  {
6203  auto result = *this;
6204  result -= i;
6205  return result;
6206  }
6207 
6210  {
6211  assert(m_object != nullptr);
6212 
6213  switch (m_object->m_type)
6214  {
6216  {
6217  throw std::domain_error("cannot use offsets with object iterators");
6218  }
6219 
6221  {
6222  return m_it.array_iterator - other.m_it.array_iterator;
6223  }
6224 
6225  default:
6226  {
6227  return m_it.primitive_iterator - other.m_it.primitive_iterator;
6228  }
6229  }
6230  }
6231 
6234  {
6235  assert(m_object != nullptr);
6236 
6237  switch (m_object->m_type)
6238  {
6240  {
6241  throw std::domain_error("cannot use operator[] for object iterators");
6242  }
6243 
6245  {
6246  return *(m_it.array_iterator + n);
6247  }
6248 
6250  {
6251  throw std::out_of_range("cannot get value");
6252  }
6253 
6254  default:
6255  {
6256  if (m_it.primitive_iterator == -n)
6257  {
6258  return *m_object;
6259  }
6260  else
6261  {
6262  throw std::out_of_range("cannot get value");
6263  }
6264  }
6265  }
6266  }
6267 
6269  typename object_t::key_type key() const
6270  {
6271  assert(m_object != nullptr);
6272 
6273  if (m_object->is_object())
6274  {
6275  return m_it.object_iterator->first;
6276  }
6277  else
6278  {
6279  throw std::domain_error("cannot use key() for non-object iterators");
6280  }
6281  }
6282 
6285  {
6286  return operator*();
6287  }
6288 
6289  private:
6291  pointer m_object = nullptr;
6293  internal_iterator m_it = internal_iterator();
6294  };
6295 
6308  class iterator : public const_iterator
6309  {
6310  public:
6312  using pointer = typename basic_json::pointer;
6314 
6316  iterator() = default;
6317 
6319  iterator(pointer object) noexcept
6320  : base_iterator(object)
6321  {}
6322 
6324  iterator(const iterator& other) noexcept
6325  : base_iterator(other)
6326  {}
6327 
6329  iterator& operator=(iterator other) noexcept(
6330  std::is_nothrow_move_constructible<pointer>::value and
6331  std::is_nothrow_move_assignable<pointer>::value and
6332  std::is_nothrow_move_constructible<internal_iterator>::value and
6333  std::is_nothrow_move_assignable<internal_iterator>::value
6334  )
6335  {
6336  base_iterator::operator=(other);
6337  return *this;
6338  }
6339 
6342  {
6343  return const_cast<reference>(base_iterator::operator*());
6344  }
6345 
6348  {
6349  return const_cast<pointer>(base_iterator::operator->());
6350  }
6351 
6354  {
6355  iterator result = *this;
6356  base_iterator::operator++();
6357  return result;
6358  }
6359 
6362  {
6363  base_iterator::operator++();
6364  return *this;
6365  }
6366 
6369  {
6370  iterator result = *this;
6371  base_iterator::operator--();
6372  return result;
6373  }
6374 
6377  {
6378  base_iterator::operator--();
6379  return *this;
6380  }
6381 
6384  {
6385  base_iterator::operator+=(i);
6386  return *this;
6387  }
6388 
6391  {
6392  base_iterator::operator-=(i);
6393  return *this;
6394  }
6395 
6398  {
6399  auto result = *this;
6400  result += i;
6401  return result;
6402  }
6403 
6406  {
6407  auto result = *this;
6408  result -= i;
6409  return result;
6410  }
6411 
6412  difference_type operator-(const iterator& other) const
6413  {
6414  return base_iterator::operator-(other);
6415  }
6416 
6419  {
6420  return const_cast<reference>(base_iterator::operator[](n));
6421  }
6422 
6425  {
6426  return const_cast<reference>(base_iterator::value());
6427  }
6428  };
6429 
6447  template<typename Base>
6448  class json_reverse_iterator : public std::reverse_iterator<Base>
6449  {
6450  public:
6452  using base_iterator = std::reverse_iterator<Base>;
6454  using reference = typename Base::reference;
6455 
6457  json_reverse_iterator(const typename base_iterator::iterator_type& it)
6458  : base_iterator(it)
6459  {}
6460 
6463  : base_iterator(it)
6464  {}
6465 
6468  {
6469  return base_iterator::operator++(1);
6470  }
6471 
6474  {
6475  base_iterator::operator++();
6476  return *this;
6477  }
6478 
6481  {
6482  return base_iterator::operator--(1);
6483  }
6484 
6487  {
6488  base_iterator::operator--();
6489  return *this;
6490  }
6491 
6494  {
6495  base_iterator::operator+=(i);
6496  return *this;
6497  }
6498 
6501  {
6502  auto result = *this;
6503  result += i;
6504  return result;
6505  }
6506 
6509  {
6510  auto result = *this;
6511  result -= i;
6512  return result;
6513  }
6514 
6517  {
6518  return this->base() - other.base();
6519  }
6520 
6523  {
6524  return *(this->operator+(n));
6525  }
6526 
6528  typename object_t::key_type key() const
6529  {
6530  auto it = --this->base();
6531  return it.key();
6532  }
6533 
6536  {
6537  auto it = --this->base();
6538  return it.operator * ();
6539  }
6540  };
6541 
6542 
6543  private:
6545  // lexer and parser //
6547 
6555  class lexer
6556  {
6557  public:
6559  enum class token_type
6560  {
6561  uninitialized,
6562  literal_true,
6563  literal_false,
6564  literal_null,
6565  value_string,
6566  value_number,
6567  begin_array,
6568  begin_object,
6569  end_array,
6570  end_object,
6571  name_separator,
6572  value_separator,
6573  parse_error,
6574  end_of_input
6575  };
6576 
6578  using lexer_char_t = unsigned char;
6579 
6581  explicit lexer(const string_t& s) noexcept
6582  : m_stream(nullptr), m_buffer(s)
6583  {
6584  m_content = reinterpret_cast<const lexer_char_t*>(s.c_str());
6585  assert(m_content != nullptr);
6586  m_start = m_cursor = m_content;
6587  m_limit = m_content + s.size();
6588  }
6589 
6591  explicit lexer(std::istream* s) noexcept
6592  : m_stream(s), m_buffer()
6593  {
6594  assert(m_stream != nullptr);
6595  getline(*m_stream, m_buffer);
6596  m_content = reinterpret_cast<const lexer_char_t*>(m_buffer.c_str());
6597  assert(m_content != nullptr);
6598  m_start = m_cursor = m_content;
6599  m_limit = m_content + m_buffer.size();
6600  }
6601 
6603  lexer() = default;
6604 
6605  // switch off unwanted functions
6606  lexer(const lexer&) = delete;
6607  lexer operator=(const lexer&) = delete;
6608 
6624  static string_t to_unicode(const std::size_t codepoint1,
6625  const std::size_t codepoint2 = 0)
6626  {
6627  string_t result;
6628 
6629  // calculate the codepoint from the given code points
6630  std::size_t codepoint = codepoint1;
6631 
6632  // check if codepoint1 is a high surrogate
6633  if (codepoint1 >= 0xD800 and codepoint1 <= 0xDBFF)
6634  {
6635  // check if codepoint2 is a low surrogate
6636  if (codepoint2 >= 0xDC00 and codepoint2 <= 0xDFFF)
6637  {
6638  codepoint =
6639  // high surrogate occupies the most significant 22 bits
6640  (codepoint1 << 10)
6641  // low surrogate occupies the least significant 15 bits
6642  + codepoint2
6643  // there is still the 0xD800, 0xDC00 and 0x10000 noise
6644  // in the result so we have to subtract with:
6645  // (0xD800 << 10) + DC00 - 0x10000 = 0x35FDC00
6646  - 0x35FDC00;
6647  }
6648  else
6649  {
6650  throw std::invalid_argument("missing or wrong low surrogate");
6651  }
6652  }
6653 
6654  if (codepoint < 0x80)
6655  {
6656  // 1-byte characters: 0xxxxxxx (ASCII)
6657  result.append(1, static_cast<typename string_t::value_type>(codepoint));
6658  }
6659  else if (codepoint <= 0x7ff)
6660  {
6661  // 2-byte characters: 110xxxxx 10xxxxxx
6662  result.append(1, static_cast<typename string_t::value_type>(0xC0 | ((codepoint >> 6) & 0x1F)));
6663  result.append(1, static_cast<typename string_t::value_type>(0x80 | (codepoint & 0x3F)));
6664  }
6665  else if (codepoint <= 0xffff)
6666  {
6667  // 3-byte characters: 1110xxxx 10xxxxxx 10xxxxxx
6668  result.append(1, static_cast<typename string_t::value_type>(0xE0 | ((codepoint >> 12) & 0x0F)));
6669  result.append(1, static_cast<typename string_t::value_type>(0x80 | ((codepoint >> 6) & 0x3F)));
6670  result.append(1, static_cast<typename string_t::value_type>(0x80 | (codepoint & 0x3F)));
6671  }
6672  else if (codepoint <= 0x10ffff)
6673  {
6674  // 4-byte characters: 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
6675  result.append(1, static_cast<typename string_t::value_type>(0xF0 | ((codepoint >> 18) & 0x07)));
6676  result.append(1, static_cast<typename string_t::value_type>(0x80 | ((codepoint >> 12) & 0x3F)));
6677  result.append(1, static_cast<typename string_t::value_type>(0x80 | ((codepoint >> 6) & 0x3F)));
6678  result.append(1, static_cast<typename string_t::value_type>(0x80 | (codepoint & 0x3F)));
6679  }
6680  else
6681  {
6682  throw std::out_of_range("code points above 0x10FFFF are invalid");
6683  }
6684 
6685  return result;
6686  }
6687 
6689  static std::string token_type_name(token_type t)
6690  {
6691  switch (t)
6692  {
6693  case token_type::uninitialized:
6694  return "<uninitialized>";
6695  case token_type::literal_true:
6696  return "true literal";
6697  case token_type::literal_false:
6698  return "false literal";
6699  case token_type::literal_null:
6700  return "null literal";
6701  case token_type::value_string:
6702  return "string literal";
6703  case token_type::value_number:
6704  return "number literal";
6705  case token_type::begin_array:
6706  return "'['";
6707  case token_type::begin_object:
6708  return "'{'";
6709  case token_type::end_array:
6710  return "']'";
6711  case token_type::end_object:
6712  return "'}'";
6713  case token_type::name_separator:
6714  return "':'";
6715  case token_type::value_separator:
6716  return "','";
6717  case token_type::parse_error:
6718  return "<parse error>";
6719  case token_type::end_of_input:
6720  return "end of input";
6721  default:
6722  {
6723  // catch non-enum values
6724  return "unknown token"; // LCOV_EXCL_LINE
6725  }
6726  }
6727  }
6728 
6739  token_type scan() noexcept
6740  {
6741  // pointer for backtracking information
6742  m_marker = nullptr;
6743 
6744  // remember the begin of the token
6745  m_start = m_cursor;
6746  assert(m_start != nullptr);
6747 
6748 
6749  {
6750  lexer_char_t yych;
6751  unsigned int yyaccept = 0;
6752  static const unsigned char yybm[] =
6753  {
6754  0, 0, 0, 0, 0, 0, 0, 0,
6755  0, 32, 32, 0, 0, 32, 0, 0,
6756  64, 64, 64, 64, 64, 64, 64, 64,
6757  64, 64, 64, 64, 64, 64, 64, 64,
6758  96, 64, 0, 64, 64, 64, 64, 64,
6759  64, 64, 64, 64, 64, 64, 64, 64,
6760  192, 192, 192, 192, 192, 192, 192, 192,
6761  192, 192, 64, 64, 64, 64, 64, 64,
6762  64, 64, 64, 64, 64, 64, 64, 64,
6763  64, 64, 64, 64, 64, 64, 64, 64,
6764  64, 64, 64, 64, 64, 64, 64, 64,
6765  64, 64, 64, 64, 0, 64, 64, 64,
6766  64, 64, 64, 64, 64, 64, 64, 64,
6767  64, 64, 64, 64, 64, 64, 64, 64,
6768  64, 64, 64, 64, 64, 64, 64, 64,
6769  64, 64, 64, 64, 64, 64, 64, 64,
6770  64, 64, 64, 64, 64, 64, 64, 64,
6771  64, 64, 64, 64, 64, 64, 64, 64,
6772  64, 64, 64, 64, 64, 64, 64, 64,
6773  64, 64, 64, 64, 64, 64, 64, 64,
6774  64, 64, 64, 64, 64, 64, 64, 64,
6775  64, 64, 64, 64, 64, 64, 64, 64,
6776  64, 64, 64, 64, 64, 64, 64, 64,
6777  64, 64, 64, 64, 64, 64, 64, 64,
6778  64, 64, 64, 64, 64, 64, 64, 64,
6779  64, 64, 64, 64, 64, 64, 64, 64,
6780  64, 64, 64, 64, 64, 64, 64, 64,
6781  64, 64, 64, 64, 64, 64, 64, 64,
6782  64, 64, 64, 64, 64, 64, 64, 64,
6783  64, 64, 64, 64, 64, 64, 64, 64,
6784  64, 64, 64, 64, 64, 64, 64, 64,
6785  64, 64, 64, 64, 64, 64, 64, 64,
6786  };
6787  if ((m_limit - m_cursor) < 5)
6788  {
6789  yyfill(); // LCOV_EXCL_LINE;
6790  }
6791  yych = *m_cursor;
6792  if (yych <= ':')
6793  {
6794  if (yych <= ' ')
6795  {
6796  if (yych <= '\n')
6797  {
6798  if (yych <= 0x00)
6799  {
6800  goto basic_json_parser_28;
6801  }
6802  if (yych <= 0x08)
6803  {
6804  goto basic_json_parser_30;
6805  }
6806  if (yych >= '\n')
6807  {
6808  goto basic_json_parser_4;
6809  }
6810  }
6811  else
6812  {
6813  if (yych == '\r')
6814  {
6815  goto basic_json_parser_2;
6816  }
6817  if (yych <= 0x1F)
6818  {
6819  goto basic_json_parser_30;
6820  }
6821  }
6822  }
6823  else
6824  {
6825  if (yych <= ',')
6826  {
6827  if (yych == '"')
6828  {
6829  goto basic_json_parser_27;
6830  }
6831  if (yych <= '+')
6832  {
6833  goto basic_json_parser_30;
6834  }
6835  goto basic_json_parser_16;
6836  }
6837  else
6838  {
6839  if (yych <= '/')
6840  {
6841  if (yych <= '-')
6842  {
6843  goto basic_json_parser_23;
6844  }
6845  goto basic_json_parser_30;
6846  }
6847  else
6848  {
6849  if (yych <= '0')
6850  {
6851  goto basic_json_parser_24;
6852  }
6853  if (yych <= '9')
6854  {
6855  goto basic_json_parser_26;
6856  }
6857  goto basic_json_parser_18;
6858  }
6859  }
6860  }
6861  }
6862  else
6863  {
6864  if (yych <= 'n')
6865  {
6866  if (yych <= ']')
6867  {
6868  if (yych == '[')
6869  {
6870  goto basic_json_parser_8;
6871  }
6872  if (yych <= '\\')
6873  {
6874  goto basic_json_parser_30;
6875  }
6876  goto basic_json_parser_10;
6877  }
6878  else
6879  {
6880  if (yych == 'f')
6881  {
6882  goto basic_json_parser_22;
6883  }
6884  if (yych <= 'm')
6885  {
6886  goto basic_json_parser_30;
6887  }
6888  goto basic_json_parser_20;
6889  }
6890  }
6891  else
6892  {
6893  if (yych <= '{')
6894  {
6895  if (yych == 't')
6896  {
6897  goto basic_json_parser_21;
6898  }
6899  if (yych <= 'z')
6900  {
6901  goto basic_json_parser_30;
6902  }
6903  goto basic_json_parser_12;
6904  }
6905  else
6906  {
6907  if (yych <= '}')
6908  {
6909  if (yych <= '|')
6910  {
6911  goto basic_json_parser_30;
6912  }
6913  goto basic_json_parser_14;
6914  }
6915  else
6916  {
6917  if (yych == 0xEF)
6918  {
6919  goto basic_json_parser_6;
6920  }
6921  goto basic_json_parser_30;
6922  }
6923  }
6924  }
6925  }
6926 basic_json_parser_2:
6927  ++m_cursor;
6928  yych = *m_cursor;
6929  goto basic_json_parser_5;
6930 basic_json_parser_3:
6931  {
6932  return scan();
6933  }
6934 basic_json_parser_4:
6935  ++m_cursor;
6936  if (m_limit <= m_cursor)
6937  {
6938  yyfill(); // LCOV_EXCL_LINE;
6939  }
6940  yych = *m_cursor;
6941 basic_json_parser_5:
6942  if (yybm[0 + yych] & 32)
6943  {
6944  goto basic_json_parser_4;
6945  }
6946  goto basic_json_parser_3;
6947 basic_json_parser_6:
6948  yyaccept = 0;
6949  yych = *(m_marker = ++m_cursor);
6950  if (yych == 0xBB)
6951  {
6952  goto basic_json_parser_64;
6953  }
6954 basic_json_parser_7:
6955  {
6956  return token_type::parse_error;
6957  }
6958 basic_json_parser_8:
6959  ++m_cursor;
6960  {
6961  return token_type::begin_array;
6962  }
6963 basic_json_parser_10:
6964  ++m_cursor;
6965  {
6966  return token_type::end_array;
6967  }
6968 basic_json_parser_12:
6969  ++m_cursor;
6970  {
6971  return token_type::begin_object;
6972  }
6973 basic_json_parser_14:
6974  ++m_cursor;
6975  {
6976  return token_type::end_object;
6977  }
6978 basic_json_parser_16:
6979  ++m_cursor;
6980  {
6981  return token_type::value_separator;
6982  }
6983 basic_json_parser_18:
6984  ++m_cursor;
6985  {
6986  return token_type::name_separator;
6987  }
6988 basic_json_parser_20:
6989  yyaccept = 0;
6990  yych = *(m_marker = ++m_cursor);
6991  if (yych == 'u')
6992  {
6993  goto basic_json_parser_60;
6994  }
6995  goto basic_json_parser_7;
6996 basic_json_parser_21:
6997  yyaccept = 0;
6998  yych = *(m_marker = ++m_cursor);
6999  if (yych == 'r')
7000  {
7001  goto basic_json_parser_56;
7002  }
7003  goto basic_json_parser_7;
7004 basic_json_parser_22:
7005  yyaccept = 0;
7006  yych = *(m_marker = ++m_cursor);
7007  if (yych == 'a')
7008  {
7009  goto basic_json_parser_51;
7010  }
7011  goto basic_json_parser_7;
7012 basic_json_parser_23:
7013  yych = *++m_cursor;
7014  if (yych <= '/')
7015  {
7016  goto basic_json_parser_7;
7017  }
7018  if (yych <= '0')
7019  {
7020  goto basic_json_parser_50;
7021  }
7022  if (yych <= '9')
7023  {
7024  goto basic_json_parser_41;
7025  }
7026  goto basic_json_parser_7;
7027 basic_json_parser_24:
7028  yyaccept = 1;
7029  yych = *(m_marker = ++m_cursor);
7030  if (yych <= 'D')
7031  {
7032  if (yych == '.')
7033  {
7034  goto basic_json_parser_43;
7035  }
7036  }
7037  else
7038  {
7039  if (yych <= 'E')
7040  {
7041  goto basic_json_parser_44;
7042  }
7043  if (yych == 'e')
7044  {
7045  goto basic_json_parser_44;
7046  }
7047  }
7048 basic_json_parser_25:
7049  {
7050  return token_type::value_number;
7051  }
7052 basic_json_parser_26:
7053  yyaccept = 1;
7054  yych = *(m_marker = ++m_cursor);
7055  goto basic_json_parser_42;
7056 basic_json_parser_27:
7057  yyaccept = 0;
7058  yych = *(m_marker = ++m_cursor);
7059  if (yych <= 0x0F)
7060  {
7061  goto basic_json_parser_7;
7062  }
7063  goto basic_json_parser_32;
7064 basic_json_parser_28:
7065  ++m_cursor;
7066  {
7067  return token_type::end_of_input;
7068  }
7069 basic_json_parser_30:
7070  yych = *++m_cursor;
7071  goto basic_json_parser_7;
7072 basic_json_parser_31:
7073  ++m_cursor;
7074  if (m_limit <= m_cursor)
7075  {
7076  yyfill(); // LCOV_EXCL_LINE;
7077  }
7078  yych = *m_cursor;
7079 basic_json_parser_32:
7080  if (yybm[0 + yych] & 64)
7081  {
7082  goto basic_json_parser_31;
7083  }
7084  if (yych <= 0x0F)
7085  {
7086  goto basic_json_parser_33;
7087  }
7088  if (yych <= '"')
7089  {
7090  goto basic_json_parser_35;
7091  }
7092  goto basic_json_parser_34;
7093 basic_json_parser_33:
7094  m_cursor = m_marker;
7095  if (yyaccept == 0)
7096  {
7097  goto basic_json_parser_7;
7098  }
7099  else
7100  {
7101  goto basic_json_parser_25;
7102  }
7103 basic_json_parser_34:
7104  ++m_cursor;
7105  if (m_limit <= m_cursor)
7106  {
7107  yyfill(); // LCOV_EXCL_LINE;
7108  }
7109  yych = *m_cursor;
7110  if (yych <= 'e')
7111  {
7112  if (yych <= '/')
7113  {
7114  if (yych == '"')
7115  {
7116  goto basic_json_parser_31;
7117  }
7118  if (yych <= '.')
7119  {
7120  goto basic_json_parser_33;
7121  }
7122  goto basic_json_parser_31;
7123  }
7124  else
7125  {
7126  if (yych <= '\\')
7127  {
7128  if (yych <= '[')
7129  {
7130  goto basic_json_parser_33;
7131  }
7132  goto basic_json_parser_31;
7133  }
7134  else
7135  {
7136  if (yych == 'b')
7137  {
7138  goto basic_json_parser_31;
7139  }
7140  goto basic_json_parser_33;
7141  }
7142  }
7143  }
7144  else
7145  {
7146  if (yych <= 'q')
7147  {
7148  if (yych <= 'f')
7149  {
7150  goto basic_json_parser_31;
7151  }
7152  if (yych == 'n')
7153  {
7154  goto basic_json_parser_31;
7155  }
7156  goto basic_json_parser_33;
7157  }
7158  else
7159  {
7160  if (yych <= 's')
7161  {
7162  if (yych <= 'r')
7163  {
7164  goto basic_json_parser_31;
7165  }
7166  goto basic_json_parser_33;
7167  }
7168  else
7169  {
7170  if (yych <= 't')
7171  {
7172  goto basic_json_parser_31;
7173  }
7174  if (yych <= 'u')
7175  {
7176  goto basic_json_parser_37;
7177  }
7178  goto basic_json_parser_33;
7179  }
7180  }
7181  }
7182 basic_json_parser_35:
7183  ++m_cursor;
7184  {
7185  return token_type::value_string;
7186  }
7187 basic_json_parser_37:
7188  ++m_cursor;
7189  if (m_limit <= m_cursor)
7190  {
7191  yyfill(); // LCOV_EXCL_LINE;
7192  }
7193  yych = *m_cursor;
7194  if (yych <= '@')
7195  {
7196  if (yych <= '/')
7197  {
7198  goto basic_json_parser_33;
7199  }
7200  if (yych >= ':')
7201  {
7202  goto basic_json_parser_33;
7203  }
7204  }
7205  else
7206  {
7207  if (yych <= 'F')
7208  {
7209  goto basic_json_parser_38;
7210  }
7211  if (yych <= '`')
7212  {
7213  goto basic_json_parser_33;
7214  }
7215  if (yych >= 'g')
7216  {
7217  goto basic_json_parser_33;
7218  }
7219  }
7220 basic_json_parser_38:
7221  ++m_cursor;
7222  if (m_limit <= m_cursor)
7223  {
7224  yyfill(); // LCOV_EXCL_LINE;
7225  }
7226  yych = *m_cursor;
7227  if (yych <= '@')
7228  {
7229  if (yych <= '/')
7230  {
7231  goto basic_json_parser_33;
7232  }
7233  if (yych >= ':')
7234  {
7235  goto basic_json_parser_33;
7236  }
7237  }
7238  else
7239  {
7240  if (yych <= 'F')
7241  {
7242  goto basic_json_parser_39;
7243  }
7244  if (yych <= '`')
7245  {
7246  goto basic_json_parser_33;
7247  }
7248  if (yych >= 'g')
7249  {
7250  goto basic_json_parser_33;
7251  }
7252  }
7253 basic_json_parser_39:
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_40;
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_40:
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 <= '9')
7300  {
7301  goto basic_json_parser_31;
7302  }
7303  goto basic_json_parser_33;
7304  }
7305  else
7306  {
7307  if (yych <= 'F')
7308  {
7309  goto basic_json_parser_31;
7310  }
7311  if (yych <= '`')
7312  {
7313  goto basic_json_parser_33;
7314  }
7315  if (yych <= 'f')
7316  {
7317  goto basic_json_parser_31;
7318  }
7319  goto basic_json_parser_33;
7320  }
7321 basic_json_parser_41:
7322  yyaccept = 1;
7323  m_marker = ++m_cursor;
7324  if ((m_limit - m_cursor) < 3)
7325  {
7326  yyfill(); // LCOV_EXCL_LINE;
7327  }
7328  yych = *m_cursor;
7329 basic_json_parser_42:
7330  if (yybm[0 + yych] & 128)
7331  {
7332  goto basic_json_parser_41;
7333  }
7334  if (yych <= 'D')
7335  {
7336  if (yych != '.')
7337  {
7338  goto basic_json_parser_25;
7339  }
7340  }
7341  else
7342  {
7343  if (yych <= 'E')
7344  {
7345  goto basic_json_parser_44;
7346  }
7347  if (yych == 'e')
7348  {
7349  goto basic_json_parser_44;
7350  }
7351  goto basic_json_parser_25;
7352  }
7353 basic_json_parser_43:
7354  yych = *++m_cursor;
7355  if (yych <= '/')
7356  {
7357  goto basic_json_parser_33;
7358  }
7359  if (yych <= '9')
7360  {
7361  goto basic_json_parser_48;
7362  }
7363  goto basic_json_parser_33;
7364 basic_json_parser_44:
7365  yych = *++m_cursor;
7366  if (yych <= ',')
7367  {
7368  if (yych != '+')
7369  {
7370  goto basic_json_parser_33;
7371  }
7372  }
7373  else
7374  {
7375  if (yych <= '-')
7376  {
7377  goto basic_json_parser_45;
7378  }
7379  if (yych <= '/')
7380  {
7381  goto basic_json_parser_33;
7382  }
7383  if (yych <= '9')
7384  {
7385  goto basic_json_parser_46;
7386  }
7387  goto basic_json_parser_33;
7388  }
7389 basic_json_parser_45:
7390  yych = *++m_cursor;
7391  if (yych <= '/')
7392  {
7393  goto basic_json_parser_33;
7394  }
7395  if (yych >= ':')
7396  {
7397  goto basic_json_parser_33;
7398  }
7399 basic_json_parser_46:
7400  ++m_cursor;
7401  if (m_limit <= m_cursor)
7402  {
7403  yyfill(); // LCOV_EXCL_LINE;
7404  }
7405  yych = *m_cursor;
7406  if (yych <= '/')
7407  {
7408  goto basic_json_parser_25;
7409  }
7410  if (yych <= '9')
7411  {
7412  goto basic_json_parser_46;
7413  }
7414  goto basic_json_parser_25;
7415 basic_json_parser_48:
7416  yyaccept = 1;
7417  m_marker = ++m_cursor;
7418  if ((m_limit - m_cursor) < 3)
7419  {
7420  yyfill(); // LCOV_EXCL_LINE;
7421  }
7422  yych = *m_cursor;
7423  if (yych <= 'D')
7424  {
7425  if (yych <= '/')
7426  {
7427  goto basic_json_parser_25;
7428  }
7429  if (yych <= '9')
7430  {
7431  goto basic_json_parser_48;
7432  }
7433  goto basic_json_parser_25;
7434  }
7435  else
7436  {
7437  if (yych <= 'E')
7438  {
7439  goto basic_json_parser_44;
7440  }
7441  if (yych == 'e')
7442  {
7443  goto basic_json_parser_44;
7444  }
7445  goto basic_json_parser_25;
7446  }
7447 basic_json_parser_50:
7448  yyaccept = 1;
7449  yych = *(m_marker = ++m_cursor);
7450  if (yych <= 'D')
7451  {
7452  if (yych == '.')
7453  {
7454  goto basic_json_parser_43;
7455  }
7456  goto basic_json_parser_25;
7457  }
7458  else
7459  {
7460  if (yych <= 'E')
7461  {
7462  goto basic_json_parser_44;
7463  }
7464  if (yych == 'e')
7465  {
7466  goto basic_json_parser_44;
7467  }
7468  goto basic_json_parser_25;
7469  }
7470 basic_json_parser_51:
7471  yych = *++m_cursor;
7472  if (yych != 'l')
7473  {
7474  goto basic_json_parser_33;
7475  }
7476  yych = *++m_cursor;
7477  if (yych != 's')
7478  {
7479  goto basic_json_parser_33;
7480  }
7481  yych = *++m_cursor;
7482  if (yych != 'e')
7483  {
7484  goto basic_json_parser_33;
7485  }
7486  ++m_cursor;
7487  {
7488  return token_type::literal_false;
7489  }
7490 basic_json_parser_56:
7491  yych = *++m_cursor;
7492  if (yych != 'u')
7493  {
7494  goto basic_json_parser_33;
7495  }
7496  yych = *++m_cursor;
7497  if (yych != 'e')
7498  {
7499  goto basic_json_parser_33;
7500  }
7501  ++m_cursor;
7502  {
7503  return token_type::literal_true;
7504  }
7505 basic_json_parser_60:
7506  yych = *++m_cursor;
7507  if (yych != 'l')
7508  {
7509  goto basic_json_parser_33;
7510  }
7511  yych = *++m_cursor;
7512  if (yych != 'l')
7513  {
7514  goto basic_json_parser_33;
7515  }
7516  ++m_cursor;
7517  {
7518  return token_type::literal_null;
7519  }
7520 basic_json_parser_64:
7521  yych = *++m_cursor;
7522  if (yych != 0xBF)
7523  {
7524  goto basic_json_parser_33;
7525  }
7526  ++m_cursor;
7527  {
7528  return scan();
7529  }
7530  }
7531 
7532 
7533  }
7534 
7536  void yyfill() noexcept
7537  {
7538  if (m_stream == nullptr or not * m_stream)
7539  {
7540  return;
7541  }
7542 
7543  const ssize_t offset_start = m_start - m_content;
7544  const ssize_t offset_marker = m_marker - m_start;
7545  const ssize_t offset_cursor = m_cursor - m_start;
7546 
7547  m_buffer.erase(0, static_cast<size_t>(offset_start));
7548  std::string line;
7549  assert(m_stream != nullptr);
7550  std::getline(*m_stream, line);
7551  m_buffer += "\n" + line; // add line with newline symbol
7552 
7553  m_content = reinterpret_cast<const lexer_char_t*>(m_buffer.c_str());
7554  assert(m_content != nullptr);
7555  m_start = m_content;
7556  m_marker = m_start + offset_marker;
7557  m_cursor = m_start + offset_cursor;
7558  m_limit = m_start + m_buffer.size() - 1;
7559  }
7560 
7562  string_t get_token() const noexcept
7563  {
7564  assert(m_start != nullptr);
7565  return string_t(reinterpret_cast<typename string_t::const_pointer>(m_start),
7566  static_cast<size_t>(m_cursor - m_start));
7567  }
7568 
7590  string_t get_string() const
7591  {
7592  string_t result;
7593  result.reserve(static_cast<size_t>(m_cursor - m_start - 2));
7594 
7595  // iterate the result between the quotes
7596  for (const lexer_char_t* i = m_start + 1; i < m_cursor - 1; ++i)
7597  {
7598  // process escaped characters
7599  if (*i == '\\')
7600  {
7601  // read next character
7602  ++i;
7603 
7604  switch (*i)
7605  {
7606  // the default escapes
7607  case 't':
7608  {
7609  result += "\t";
7610  break;
7611  }
7612  case 'b':
7613  {
7614  result += "\b";
7615  break;
7616  }
7617  case 'f':
7618  {
7619  result += "\f";
7620  break;
7621  }
7622  case 'n':
7623  {
7624  result += "\n";
7625  break;
7626  }
7627  case 'r':
7628  {
7629  result += "\r";
7630  break;
7631  }
7632  case '\\':
7633  {
7634  result += "\\";
7635  break;
7636  }
7637  case '/':
7638  {
7639  result += "/";
7640  break;
7641  }
7642  case '"':
7643  {
7644  result += "\"";
7645  break;
7646  }
7647 
7648  // unicode
7649  case 'u':
7650  {
7651  // get code xxxx from uxxxx
7652  auto codepoint = std::strtoul(std::string(reinterpret_cast<typename string_t::const_pointer>(i + 1),
7653  4).c_str(), nullptr, 16);
7654 
7655  // check if codepoint is a high surrogate
7656  if (codepoint >= 0xD800 and codepoint <= 0xDBFF)
7657  {
7658  // make sure there is a subsequent unicode
7659  if ((i + 6 >= m_limit) or * (i + 5) != '\\' or * (i + 6) != 'u')
7660  {
7661  throw std::invalid_argument("missing low surrogate");
7662  }
7663 
7664  // get code yyyy from uxxxx\uyyyy
7665  auto codepoint2 = std::strtoul(std::string(reinterpret_cast<typename string_t::const_pointer>
7666  (i + 7), 4).c_str(), nullptr, 16);
7667  result += to_unicode(codepoint, codepoint2);
7668  // skip the next 10 characters (xxxx\uyyyy)
7669  i += 10;
7670  }
7671  else
7672  {
7673  // add unicode character(s)
7674  result += to_unicode(codepoint);
7675  // skip the next four characters (xxxx)
7676  i += 4;
7677  }
7678  break;
7679  }
7680  }
7681  }
7682  else
7683  {
7684  // all other characters are just copied to the end of the
7685  // string
7686  result.append(1, static_cast<typename string_t::value_type>(*i));
7687  }
7688  }
7689 
7690  return result;
7691  }
7692 
7710  long double get_number() const
7711  {
7712  // conversion
7713  typename string_t::value_type* endptr;
7714  assert(m_start != nullptr);
7715  const auto float_val = std::strtold(reinterpret_cast<typename string_t::const_pointer>(m_start),
7716  &endptr);
7717 
7718  // return float_val if the whole number was translated and NAN
7719  // otherwise
7720  return (reinterpret_cast<lexer_char_t*>(endptr) == m_cursor) ? float_val : NAN;
7721  }
7722 
7723  private:
7725  std::istream* m_stream = nullptr;
7727  string_t m_buffer;
7729  const lexer_char_t* m_content = nullptr;
7731  const lexer_char_t* m_start = nullptr;
7733  const lexer_char_t* m_marker = nullptr;
7735  const lexer_char_t* m_cursor = nullptr;
7737  const lexer_char_t* m_limit = nullptr;
7738  };
7739 
7745  class parser
7746  {
7747  public:
7749  parser(const string_t& s, parser_callback_t cb = nullptr)
7750  : callback(cb), m_lexer(s)
7751  {
7752  // read first token
7753  get_token();
7754  }
7755 
7757  parser(std::istream& _is, parser_callback_t cb = nullptr)
7758  : callback(cb), m_lexer(&_is)
7759  {
7760  // read first token
7761  get_token();
7762  }
7763 
7765  basic_json parse()
7766  {
7767  basic_json result = parse_internal(true);
7768 
7769  expect(lexer::token_type::end_of_input);
7770 
7771  // return parser result and replace it with null in case the
7772  // top-level value was discarded by the callback function
7773  return result.is_discarded() ? basic_json() : result;
7774  }
7775 
7776  private:
7778  basic_json parse_internal(bool keep)
7779  {
7780  auto result = basic_json(value_t::discarded);
7781 
7782  switch (last_token)
7783  {
7784  case lexer::token_type::begin_object:
7785  {
7786  if (keep and (not callback or (keep = callback(depth++, parse_event_t::object_start, result))))
7787  {
7788  // explicitly set result to object to cope with {}
7789  result.m_type = value_t::object;
7790  result.m_value = json_value(value_t::object);
7791  }
7792 
7793  // read next token
7794  get_token();
7795 
7796  // closing } -> we are done
7797  if (last_token == lexer::token_type::end_object)
7798  {
7799  get_token();
7800  if (keep and callback and not callback(--depth, parse_event_t::object_end, result))
7801  {
7802  result = basic_json(value_t::discarded);
7803  }
7804  return result;
7805  }
7806 
7807  // no comma is expected here
7808  unexpect(lexer::token_type::value_separator);
7809 
7810  // otherwise: parse key-value pairs
7811  do
7812  {
7813  // ugly, but could be fixed with loop reorganization
7814  if (last_token == lexer::token_type::value_separator)
7815  {
7816  get_token();
7817  }
7818 
7819  // store key
7820  expect(lexer::token_type::value_string);
7821  const auto key = m_lexer.get_string();
7822 
7823  bool keep_tag = false;
7824  if (keep)
7825  {
7826  if (callback)
7827  {
7828  basic_json k(key);
7829  keep_tag = callback(depth, parse_event_t::key, k);
7830  }
7831  else
7832  {
7833  keep_tag = true;
7834  }
7835  }
7836 
7837  // parse separator (:)
7838  get_token();
7839  expect(lexer::token_type::name_separator);
7840 
7841  // parse and add value
7842  get_token();
7843  auto value = parse_internal(keep);
7844  if (keep and keep_tag and not value.is_discarded())
7845  {
7846  result[key] = std::move(value);
7847  }
7848  }
7849  while (last_token == lexer::token_type::value_separator);
7850 
7851  // closing }
7852  expect(lexer::token_type::end_object);
7853  get_token();
7854  if (keep and callback and not callback(--depth, parse_event_t::object_end, result))
7855  {
7856  result = basic_json(value_t::discarded);
7857  }
7858 
7859  return result;
7860  }
7861 
7862  case lexer::token_type::begin_array:
7863  {
7864  if (keep and (not callback or (keep = callback(depth++, parse_event_t::array_start, result))))
7865  {
7866  // explicitly set result to object to cope with []
7867  result.m_type = value_t::array;
7868  result.m_value = json_value(value_t::array);
7869  }
7870 
7871  // read next token
7872  get_token();
7873 
7874  // closing ] -> we are done
7875  if (last_token == lexer::token_type::end_array)
7876  {
7877  get_token();
7878  if (callback and not callback(--depth, parse_event_t::array_end, result))
7879  {
7880  result = basic_json(value_t::discarded);
7881  }
7882  return result;
7883  }
7884 
7885  // no comma is expected here
7886  unexpect(lexer::token_type::value_separator);
7887 
7888  // otherwise: parse values
7889  do
7890  {
7891  // ugly, but could be fixed with loop reorganization
7892  if (last_token == lexer::token_type::value_separator)
7893  {
7894  get_token();
7895  }
7896 
7897  // parse value
7898  auto value = parse_internal(keep);
7899  if (keep and not value.is_discarded())
7900  {
7901  result.push_back(std::move(value));
7902  }
7903  }
7904  while (last_token == lexer::token_type::value_separator);
7905 
7906  // closing ]
7907  expect(lexer::token_type::end_array);
7908  get_token();
7909  if (keep and callback and not callback(--depth, parse_event_t::array_end, result))
7910  {
7911  result = basic_json(value_t::discarded);
7912  }
7913 
7914  return result;
7915  }
7916 
7917  case lexer::token_type::literal_null:
7918  {
7919  get_token();
7920  result.m_type = value_t::null;
7921  break;
7922  }
7923 
7924  case lexer::token_type::value_string:
7925  {
7926  const auto s = m_lexer.get_string();
7927  get_token();
7928  result = basic_json(s);
7929  break;
7930  }
7931 
7932  case lexer::token_type::literal_true:
7933  {
7934  get_token();
7935  result.m_type = value_t::boolean;
7936  result.m_value = true;
7937  break;
7938  }
7939 
7940  case lexer::token_type::literal_false:
7941  {
7942  get_token();
7943  result.m_type = value_t::boolean;
7944  result.m_value = false;
7945  break;
7946  }
7947 
7948  case lexer::token_type::value_number:
7949  {
7950  auto float_val = m_lexer.get_number();
7951 
7952  // NAN is returned if token could not be translated
7953  // completely
7954  if (std::isnan(float_val))
7955  {
7956  throw std::invalid_argument(std::string("parse error - ") +
7957  m_lexer.get_token() + " is not a number");
7958  }
7959 
7960  get_token();
7961 
7962  // check if conversion loses precision
7963  const auto int_val = static_cast<number_integer_t>(float_val);
7964  if (approx(float_val, static_cast<long double>(int_val)))
7965  {
7966  // we would not lose precision -> return int
7967  result.m_type = value_t::number_integer;
7968  result.m_value = int_val;
7969  }
7970  else
7971  {
7972  // we would lose precision -> return float
7973  result.m_type = value_t::number_float;
7974  result.m_value = static_cast<number_float_t>(float_val);
7975  }
7976  break;
7977  }
7978 
7979  default:
7980  {
7981  // the last token was unexpected
7982  unexpect(last_token);
7983  }
7984  }
7985 
7986  if (keep and callback and not callback(depth, parse_event_t::value, result))
7987  {
7988  result = basic_json(value_t::discarded);
7989  }
7990  return result;
7991  }
7992 
7994  typename lexer::token_type get_token()
7995  {
7996  last_token = m_lexer.scan();
7997  return last_token;
7998  }
7999 
8000  void expect(typename lexer::token_type t) const
8001  {
8002  if (t != last_token)
8003  {
8004  std::string error_msg = "parse error - unexpected ";
8005  error_msg += (last_token == lexer::token_type::parse_error ? ("'" + m_lexer.get_token() + "'") :
8006  lexer::token_type_name(last_token));
8007  error_msg += "; expected " + lexer::token_type_name(t);
8008  throw std::invalid_argument(error_msg);
8009  }
8010  }
8011 
8012  void unexpect(typename lexer::token_type t) const
8013  {
8014  if (t == last_token)
8015  {
8016  std::string error_msg = "parse error - unexpected ";
8017  error_msg += (last_token == lexer::token_type::parse_error ? ("'" + m_lexer.get_token() + "'") :
8018  lexer::token_type_name(last_token));
8019  throw std::invalid_argument(error_msg);
8020  }
8021  }
8022 
8023  private:
8025  int depth = 0;
8027  parser_callback_t callback;
8029  typename lexer::token_type last_token = lexer::token_type::uninitialized;
8031  lexer m_lexer;
8032  };
8033 };
8034 
8035 
8037 // presets //
8039 
8049 }
8050 
8051 
8053 // nonmember functions //
8055 
8056 // specialization of std::swap, and std::hash
8057 namespace std
8058 {
8064 template <>
8065 inline void swap(nlohmann::json& j1,
8066  nlohmann::json& j2) noexcept(
8067  is_nothrow_move_constructible<nlohmann::json>::value and
8068  is_nothrow_move_assignable<nlohmann::json>::value
8069  )
8070 {
8071  j1.swap(j2);
8072 }
8073 
8075 template <>
8076 struct hash<nlohmann::json>
8077 {
8083  std::size_t operator()(const nlohmann::json& j) const
8084  {
8085  // a naive hashing via the string representation
8086  const auto& h = hash<nlohmann::json::string_t>();
8087  return h(j.dump());
8088  }
8089 };
8090 }
8091 
8104 inline nlohmann::json operator "" _json(const char* s, std::size_t)
8105 {
8106  return nlohmann::json::parse(reinterpret_cast<const nlohmann::json::string_t::value_type*>(s));
8107 }
8108 
8109 #endif
bool operator!=(const const_iterator &other) const
comparison: not equal
Definition: json.hpp:6105
iterator insert(const_iterator pos, basic_json &&val)
inserts element
Definition: json.hpp:4388
iterator operator++(int)
post-increment (it++)
Definition: json.hpp:6353
friend bool operator<=(const_reference lhs, const_reference rhs) noexcept
comparison: less than or equal
Definition: json.hpp:4999
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:6508
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:2950
reference operator[](const T(&key)[n])
access specified object element
Definition: json.hpp:3084
typename basic_json::const_pointer pointer
defines a pointer to the type iterated over (value_type)
Definition: json.hpp:5777
static iteration_proxy< iterator > iterator_wrapper(reference cont)
wrapper to access iterator member functions in range-based for
Definition: json.hpp:3922
const_iterator & operator--()
pre-decrement (–it)
Definition: json.hpp:6046
friend std::istream & operator>>(std::istream &i, basic_json &j)
deserialize from stream
Definition: json.hpp:5212
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:5846
typename basic_json::value_type value_type
the type of the values when the iterator is dereferenced
Definition: json.hpp:5773
reference & operator=(basic_json other) noexcept( std::is_nothrow_move_constructible< value_t >::value and std::is_nothrow_move_assignable< value_t >::value and std::is_nothrow_move_constructible< json_value >::value and std::is_nothrow_move_assignable< json_value >::value )
copy assignment
Definition: json.hpp:1782
iterator insert(const_iterator pos, const_iterator first, const_iterator last)
inserts elements
Definition: json.hpp:4470
iterator insert(const_iterator pos, size_type cnt, const basic_json &val)
inserts elements
Definition: json.hpp:4417
json_reverse_iterator operator--(int)
post-decrement (it–)
Definition: json.hpp:6480
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:4309
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:6361
friend bool operator!=(const_reference lhs, const_reference rhs) noexcept
comparison: not equal
Definition: json.hpp:4855
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:6009
difference_type operator-(const json_reverse_iterator &other) const
return difference
Definition: json.hpp:6516
basic_json<> json
default JSON class
Definition: json.hpp:8048
reference front()
access the first element
Definition: json.hpp:3253
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:3633
std::reverse_iterator< Base > base_iterator
shortcut to the reverse iterator adaptor
Definition: json.hpp:6452
json_reverse_iterator(const typename base_iterator::iterator_type &it)
create reverse iterator from iterator
Definition: json.hpp:6457
a class to store JSON values
Definition: json.hpp:188
json_reverse_iterator & operator--()
pre-decrement (–it)
Definition: json.hpp:6486
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:4834
void push_back(basic_json &&val)
add an object to an array
Definition: json.hpp:4223
const_iterator cbegin() const
returns a const iterator to the first element
Definition: json.hpp:3733
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:6383
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:4249
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:6308
iterator & operator-=(difference_type i)
subtract from iterator
Definition: json.hpp:6390
static basic_json parse(std::istream &&i, parser_callback_t cb=nullptr)
deserialize from stream
Definition: json.hpp:5174
reference operator[](const typename object_t::key_type &key)
access specified object element
Definition: json.hpp:2991
STL namespace.
difference_type operator-(const iterator &other) const
Definition: json.hpp:6412
reference value() const
return the value of an iterator
Definition: json.hpp:6284
static iteration_proxy< const_iterator > iterator_wrapper(const_reference cont)
wrapper to access iterator member functions in range-based for
Definition: json.hpp:3930
const_iterator end() const
returns a const iterator to one past the last element
Definition: json.hpp:3768
const_iterator(const const_iterator &other) noexcept
copy constructor
Definition: json.hpp:5841
reference at(const typename object_t::key_type &key)
access specified object element with bounds checking
Definition: json.hpp:2810
object_t::key_type key() const
return the key of an object iterator
Definition: json.hpp:6269
iterator end()
returns an iterator to one past the last element
Definition: json.hpp:3758
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:6341
reverse_iterator rend()
returns an iterator to the reverse-end
Definition: json.hpp:3847
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:6201
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:5779
const_reverse_iterator rend() const
returns a const reverse iterator to one before the first
Definition: json.hpp:3855
size_type erase(const typename object_t::key_type &key)
remove element from a JSON object given a key
Definition: json.hpp:3542
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:3699
const_reference at(const typename object_t::key_type &key) const
access specified object element with bounds checking
Definition: json.hpp:2858
reference operator+=(const basic_json &val)
add an object to an array
Definition: json.hpp:4283
AllocatorType< basic_json > allocator_type
the allocator type
Definition: json.hpp:225
basic_json(const number_float_t val)
create a floating-point number (explicit)
Definition: json.hpp:1259
bool is_number_integer() const noexcept
return whether value is an integer number
Definition: json.hpp:2034
iterator operator+(difference_type i)
add to iterator
Definition: json.hpp:6397
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:3616
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:5043
iterator & operator--()
pre-decrement (–it)
Definition: json.hpp:6376
friend bool operator<(const_reference lhs, const_reference rhs) noexcept
comparison: less than
Definition: json.hpp:4916
pointer operator->() const
dereference the iterator
Definition: json.hpp:5966
const_reference operator[](const typename object_t::key_type &key) const
read-only access specified object element
Definition: json.hpp:3039
const_iterator cend() const
returns a const iterator to one past the last element
Definition: json.hpp:3792
typename Base::reference reference
the reference type for the pointed-to element
Definition: json.hpp:6454
size_type size() const noexcept
returns the number of elements
Definition: json.hpp:4032
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:2718
json_reverse_iterator(const base_iterator &it)
create reverse iterator from base class
Definition: json.hpp:6462
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:5098
ValueType value(const typename object_t::key_type &key, ValueType default_value) const
access specified object element with default value
Definition: json.hpp:3202
object_t::key_type key() const
return the key of an object iterator
Definition: json.hpp:6528
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:5775
void swap(array_t &other)
exchanges the values
Definition: json.hpp:4597
reverse_iterator rbegin()
returns an iterator to the reverse-beginning
Definition: json.hpp:3816
reference operator+=(const typename object_t::value_type &val)
add an object to an object
Definition: json.hpp:4333
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:6418
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:3824
~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:6193
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:4665
reference value() const
return the value of an iterator
Definition: json.hpp:6424
const_iterator operator--(int)
post-decrement (it–)
Definition: json.hpp:6038
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:3580
void clear() noexcept
clears the contents
Definition: json.hpp:4153
pointer operator->()
dereference the iterator
Definition: json.hpp:6347
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:3261
bool operator>=(const const_iterator &other) const
comparison: greater than or equal
Definition: json.hpp:6153
iterator insert(const_iterator pos, std::initializer_list< basic_json > ilist)
inserts elements
Definition: json.hpp:4528
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:6159
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:6209
friend bool operator==(const_reference lhs, const_reference rhs) noexcept
comparison: equal
Definition: json.hpp:4745
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:3901
bool empty() const noexcept
checks whether the container is empty
Definition: json.hpp:3974
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:3228
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:4566
const_reverse_iterator crbegin() const
returns a const reverse iterator to the last element
Definition: json.hpp:3878
reference value() const
return the value of an iterator
Definition: json.hpp:6535
const_iterator(pointer object)
constructor for a given JSON instance
Definition: json.hpp:5787
friend bool operator<(const value_t lhs, const value_t rhs)
comparison operator for JSON types
Definition: json.hpp:4699
iterator(pointer object) noexcept
constructor for a given JSON instance
Definition: json.hpp:6319
bool operator<(const const_iterator &other) const
comparison: smaller
Definition: json.hpp:6111
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:4878
const_iterator & operator-=(difference_type i)
subtract from iterator
Definition: json.hpp:6187
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:5137
InteratorType erase(InteratorType first, InteratorType last)
remove elements given an iterator range
Definition: json.hpp:3459
json_reverse_iterator operator++(int)
post-increment (it++)
Definition: json.hpp:6467
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:5814
friend bool operator!=(std::nullptr_t, const_reference v) noexcept
comparison: not equal
Definition: json.hpp:4887
InteratorType erase(InteratorType pos)
remove element given an iterator
Definition: json.hpp:3354
bool operator<=(const const_iterator &other) const
comparison: less than or equal
Definition: json.hpp:6141
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:3287
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:6001
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:6324
const_reference back() const
access the last element
Definition: json.hpp:3297
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:5166
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:3664
size_type max_size() const noexcept
returns the maximum possible number of elements
Definition: json.hpp:4094
void push_back(const basic_json &val)
add an object to an array
Definition: json.hpp:4259
bool operator==(const const_iterator &other) const
comparison: equal
Definition: json.hpp:6075
json_reverse_iterator & operator++()
pre-increment (++it)
Definition: json.hpp:6473
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:6147
friend bool operator>(const_reference lhs, const_reference rhs) noexcept
comparison: greater than
Definition: json.hpp:5021
basic_json(basic_json &&other) noexcept
move constructor
Definition: json.hpp:1752
const_reference operator[](const T(&key)[n]) const
read-only access specified object element
Definition: json.hpp:3135
const_iterator begin() const
returns a const iterator to the first element
Definition: json.hpp:3709
const_reference at(size_type idx) const
access specified array element with bounds checking
Definition: json.hpp:2762
json_reverse_iterator & operator+=(difference_type i)
add to iterator
Definition: json.hpp:6493
a const random access iterator for the basic_json class
Definition: json.hpp:5766
a template for a reverse iterator class
Definition: json.hpp:233
void swap(object_t &other)
exchanges the values
Definition: json.hpp:4631
std::bidirectional_iterator_tag iterator_category
the category of the iterator
Definition: json.hpp:5781
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:4361
friend bool operator==(const_reference v, std::nullptr_t) noexcept
comparison: equal
Definition: json.hpp:4825
reference operator[](difference_type n) const
access to successor
Definition: json.hpp:6522
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:6233
reference operator*() const
return a reference to the value pointed to by the iterator
Definition: json.hpp:5926
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:5202
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:8083
friend std::ostream & operator<<(std::ostream &o, const basic_json &j)
serialize to stream
Definition: json.hpp:5080
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:6329
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:2905
iterator operator--(int)
post-decrement (it–)
Definition: json.hpp:6368
json_reverse_iterator operator+(difference_type i) const
add to iterator
Definition: json.hpp:6500
parse_event_t
JSON callback events.
Definition: json.hpp:755
iterator operator-(difference_type i)
subtract from iterator
Definition: json.hpp:6405