JSON for Modern C++  2.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 <cstddef>
47 #include <cstdio>
48 #include <cstdlib>
49 #include <functional>
50 #include <initializer_list>
51 #include <iomanip>
52 #include <iostream>
53 #include <iterator>
54 #include <limits>
55 #include <map>
56 #include <memory>
57 #include <sstream>
58 #include <stdexcept>
59 #include <string>
60 #include <type_traits>
61 #include <utility>
62 #include <vector>
63 
64 // enable ssize_t on MinGW
65 #ifdef __GNUC__
66  #ifdef __MINGW32__
67  #include <sys/types.h>
68  #endif
69 #endif
70 
71 // disable float-equal warnings on GCC/clang
72 #if defined(__clang__) || defined(__GNUC__) || defined(__GNUG__)
73  #pragma GCC diagnostic push
74  #pragma GCC diagnostic ignored "-Wfloat-equal"
75 #endif
76 
77 // enable ssize_t for MSVC
78 #ifdef _MSC_VER
79  #include <basetsd.h>
80  using ssize_t = SSIZE_T;
81 #endif
82 
88 namespace nlohmann
89 {
90 
91 
96 namespace
97 {
102 template<typename T>
103 struct has_mapped_type
104 {
105  private:
106  template<typename C> static char test(typename C::mapped_type*);
107  template<typename C> static char (&test(...))[2];
108  public:
109  static constexpr bool value = sizeof(test<T>(0)) == 1;
110 };
111 
112 }
113 
184 template <
185  template<typename U, typename V, typename... Args> class ObjectType = std::map,
186  template<typename U, typename... Args> class ArrayType = std::vector,
187  class StringType = std::string,
188  class BooleanType = bool,
189  class NumberIntegerType = int64_t,
190  class NumberUnsignedType = uint64_t,
191  class NumberFloatType = double,
192  template<typename U> class AllocatorType = std::allocator
193  >
195 {
196  private:
198  using basic_json_t = basic_json<ObjectType,
199  ArrayType,
200  StringType,
201  BooleanType,
202  NumberIntegerType,
203  NumberUnsignedType,
204  NumberFloatType,
205  AllocatorType>;
206 
207  public:
208 
210  // container types //
212 
215 
218 
222  using const_reference = const value_type&;
223 
225  using difference_type = std::ptrdiff_t;
227  using size_type = std::size_t;
228 
230  using allocator_type = AllocatorType<basic_json>;
231 
233  using pointer = typename std::allocator_traits<allocator_type>::pointer;
235  using const_pointer = typename std::allocator_traits<allocator_type>::const_pointer;
236 
237  // forward declaration
238  template<typename Base> class json_reverse_iterator;
239 
241  class iterator;
243  class const_iterator;
248 
250 
251 
256  {
257  return allocator_type();
258  }
259 
260 
262  // JSON value data types //
264 
267 
350  using object_t = ObjectType<StringType,
351  basic_json,
352  std::less<StringType>,
353  AllocatorType<std::pair<const StringType,
354  basic_json>>>;
355 
400  using array_t = ArrayType<basic_json, AllocatorType<basic_json>>;
401 
447  using string_t = StringType;
448 
473  using boolean_t = BooleanType;
474 
544  using number_integer_t = NumberIntegerType;
545 
616  using number_unsigned_t = NumberUnsignedType;
617 
684  using number_float_t = NumberFloatType;
685 
687 
688 
690  // JSON type enumeration //
692 
703  enum class value_t : uint8_t
704  {
705  null,
706  object,
707  array,
708  string,
709  boolean,
710  number_integer,
711  number_unsigned,
712  number_float,
713  discarded
714  };
715 
716 
717  private:
719  template<typename T, typename... Args>
720  static T* create(Args&& ... args)
721  {
722  AllocatorType<T> alloc;
723  auto deleter = [&](T * object)
724  {
725  alloc.deallocate(object, 1);
726  };
727  std::unique_ptr<T, decltype(deleter)> object(alloc.allocate(1), deleter);
728  alloc.construct(object.get(), std::forward<Args>(args)...);
729  return object.release();
730  }
731 
733  // JSON value storage //
735 
743  union json_value
744  {
746  object_t* object;
748  array_t* array;
750  string_t* string;
752  boolean_t boolean;
754  number_integer_t number_integer;
756  number_unsigned_t number_unsigned;
758  number_float_t number_float;
759 
761  json_value() noexcept = default;
763  json_value(boolean_t v) noexcept : boolean(v) {}
765  json_value(number_integer_t v) noexcept : number_integer(v) {}
767  json_value(number_unsigned_t v) noexcept : number_unsigned(v) {}
769  json_value(number_float_t v) noexcept : number_float(v) {}
771  json_value(value_t t)
772  {
773  switch (t)
774  {
775  case value_t::object:
776  {
777  object = create<object_t>();
778  break;
779  }
780 
781  case value_t::array:
782  {
783  array = create<array_t>();
784  break;
785  }
786 
787  case value_t::string:
788  {
789  string = create<string_t>("");
790  break;
791  }
792 
793  case value_t::boolean:
794  {
795  boolean = boolean_t(false);
796  break;
797  }
798 
799  case value_t::number_integer:
800  {
801  number_integer = number_integer_t(0);
802  break;
803  }
804 
805  case value_t::number_unsigned:
806  {
807  number_unsigned = number_unsigned_t(0);
808  break;
809  }
810 
811  case value_t::number_float:
812  {
813  number_float = number_float_t(0.0);
814  break;
815  }
816 
817  default:
818  {
819  break;
820  }
821  }
822  }
823 
825  json_value(const string_t& value)
826  {
827  string = create<string_t>(value);
828  }
829 
831  json_value(const object_t& value)
832  {
833  object = create<object_t>(value);
834  }
835 
837  json_value(const array_t& value)
838  {
839  array = create<array_t>(value);
840  }
841  };
842 
843 
844  public:
846  // JSON parser callback //
848 
857  enum class parse_event_t : uint8_t
858  {
860  object_start,
862  object_end,
864  array_start,
866  array_end,
868  key,
870  value
871  };
872 
922  using parser_callback_t = std::function<bool(int depth, parse_event_t event, basic_json& parsed)>;
923 
924 
926  // constructors //
928 
931 
972  : m_type(value_type), m_value(value_type)
973  {}
974 
994  basic_json() noexcept = default;
995 
1015  basic_json(std::nullptr_t) noexcept
1016  : basic_json(value_t::null)
1017  {}
1018 
1038  basic_json(const object_t& val)
1039  : m_type(value_t::object), m_value(val)
1040  {}
1041 
1065  template <class CompatibleObjectType, typename
1066  std::enable_if<
1067  std::is_constructible<typename object_t::key_type, typename CompatibleObjectType::key_type>::value and
1068  std::is_constructible<basic_json, typename CompatibleObjectType::mapped_type>::value, int>::type
1069  = 0>
1070  basic_json(const CompatibleObjectType& val)
1071  : m_type(value_t::object)
1072  {
1073  using std::begin;
1074  using std::end;
1075  m_value.object = create<object_t>(begin(val), end(val));
1076  }
1077 
1097  basic_json(const array_t& val)
1098  : m_type(value_t::array), m_value(val)
1099  {}
1100 
1124  template <class CompatibleArrayType, typename
1125  std::enable_if<
1126  not std::is_same<CompatibleArrayType, typename basic_json_t::iterator>::value and
1127  not std::is_same<CompatibleArrayType, typename basic_json_t::const_iterator>::value and
1128  not std::is_same<CompatibleArrayType, typename basic_json_t::reverse_iterator>::value and
1129  not std::is_same<CompatibleArrayType, typename basic_json_t::const_reverse_iterator>::value and
1130  not std::is_same<CompatibleArrayType, typename array_t::iterator>::value and
1131  not std::is_same<CompatibleArrayType, typename array_t::const_iterator>::value and
1132  std::is_constructible<basic_json, typename CompatibleArrayType::value_type>::value, int>::type
1133  = 0>
1134  basic_json(const CompatibleArrayType& val)
1135  : m_type(value_t::array)
1136  {
1137  using std::begin;
1138  using std::end;
1139  m_value.array = create<array_t>(begin(val), end(val));
1140  }
1141 
1163  basic_json(const string_t& val)
1164  : m_type(value_t::string), m_value(val)
1165  {}
1166 
1187  basic_json(const typename string_t::value_type* val)
1188  : basic_json(string_t(val))
1189  {}
1190 
1214  template <class CompatibleStringType, typename
1215  std::enable_if<
1216  std::is_constructible<string_t, CompatibleStringType>::value, int>::type
1217  = 0>
1218  basic_json(const CompatibleStringType& val)
1219  : basic_json(string_t(val))
1220  {}
1221 
1237  : m_type(value_t::boolean), m_value(val)
1238  {}
1239 
1265  template<typename T,
1266  typename std::enable_if<
1267  not (std::is_same<T, int>::value)
1268  and std::is_same<T, number_integer_t>::value
1269  , int>::type
1270  = 0>
1272  : m_type(value_t::number_integer), m_value(val)
1273  {}
1274 
1300  basic_json(const int val)
1301  : m_type(value_t::number_integer),
1302  m_value(static_cast<number_integer_t>(val))
1303  {}
1304 
1330  template<typename CompatibleNumberIntegerType, typename
1331  std::enable_if<
1332  std::is_constructible<number_integer_t, CompatibleNumberIntegerType>::value and
1333  std::numeric_limits<CompatibleNumberIntegerType>::is_integer and
1334  std::numeric_limits<CompatibleNumberIntegerType>::is_signed,
1335  CompatibleNumberIntegerType>::type
1336  = 0>
1337  basic_json(const CompatibleNumberIntegerType val) noexcept
1338  : m_type(value_t::number_integer),
1339  m_value(static_cast<number_integer_t>(val))
1340  {}
1341 
1359  template<typename T,
1360  typename std::enable_if<
1361  not (std::is_same<T, int>::value)
1362  and std::is_same<T, number_unsigned_t>::value
1363  , int>::type
1364  = 0>
1366  : m_type(value_t::number_unsigned), m_value(val)
1367  {}
1368 
1389  template < typename CompatibleNumberUnsignedType, typename
1390  std::enable_if <
1391  std::is_constructible<number_unsigned_t, CompatibleNumberUnsignedType>::value and
1392  std::numeric_limits<CompatibleNumberUnsignedType>::is_integer and
1393  !std::numeric_limits<CompatibleNumberUnsignedType>::is_signed,
1394  CompatibleNumberUnsignedType >::type
1395  = 0 >
1396  basic_json(const CompatibleNumberUnsignedType val) noexcept
1397  : m_type(value_t::number_unsigned),
1398  m_value(static_cast<number_unsigned_t>(val))
1399  {}
1400 
1426  : m_type(value_t::number_float), m_value(val)
1427  {
1428  // replace infinity and NAN by null
1429  if (not std::isfinite(val))
1430  {
1431  m_type = value_t::null;
1432  m_value = json_value();
1433  }
1434  }
1435 
1466  template<typename CompatibleNumberFloatType, typename = typename
1467  std::enable_if<
1468  std::is_constructible<number_float_t, CompatibleNumberFloatType>::value and
1469  std::is_floating_point<CompatibleNumberFloatType>::value>::type
1470  >
1471  basic_json(const CompatibleNumberFloatType val) noexcept
1472  : basic_json(number_float_t(val))
1473  {}
1474 
1544  basic_json(std::initializer_list<basic_json> init,
1545  bool type_deduction = true,
1546  value_t manual_type = value_t::array)
1547  {
1548  // the initializer list could describe an object
1549  bool is_an_object = true;
1550 
1551  // check if each element is an array with two elements whose first
1552  // element is a string
1553  for (const auto& element : init)
1554  {
1555  if (not element.is_array() or element.size() != 2
1556  or not element[0].is_string())
1557  {
1558  // we found an element that makes it impossible to use the
1559  // initializer list as object
1560  is_an_object = false;
1561  break;
1562  }
1563  }
1564 
1565  // adjust type if type deduction is not wanted
1566  if (not type_deduction)
1567  {
1568  // if array is wanted, do not create an object though possible
1569  if (manual_type == value_t::array)
1570  {
1571  is_an_object = false;
1572  }
1573 
1574  // if object is wanted but impossible, throw an exception
1575  if (manual_type == value_t::object and not is_an_object)
1576  {
1577  throw std::domain_error("cannot create object from initializer list");
1578  }
1579  }
1580 
1581  if (is_an_object)
1582  {
1583  // the initializer list is a list of pairs -> create object
1584  m_type = value_t::object;
1585  m_value = value_t::object;
1586 
1587  assert(m_value.object != nullptr);
1588 
1589  for (auto& element : init)
1590  {
1591  m_value.object->emplace(std::move(*(element[0].m_value.string)), std::move(element[1]));
1592  }
1593  }
1594  else
1595  {
1596  // the initializer list describes an array -> create array
1597  m_type = value_t::array;
1598  m_value.array = create<array_t>(std::move(init));
1599  }
1600  }
1601 
1636  static basic_json array(std::initializer_list<basic_json> init =
1637  std::initializer_list<basic_json>())
1638  {
1639  return basic_json(init, false, value_t::array);
1640  }
1641 
1676  static basic_json object(std::initializer_list<basic_json> init =
1677  std::initializer_list<basic_json>())
1678  {
1679  return basic_json(init, false, value_t::object);
1680  }
1681 
1700  basic_json(size_type cnt, const basic_json& val)
1701  : m_type(value_t::array)
1702  {
1703  m_value.array = create<array_t>(cnt, val);
1704  }
1705 
1740  template <class InputIT, typename
1741  std::enable_if<
1742  std::is_same<InputIT, typename basic_json_t::iterator>::value or
1743  std::is_same<InputIT, typename basic_json_t::const_iterator>::value
1744  , int>::type
1745  = 0>
1746  basic_json(InputIT first, InputIT last) : m_type(first.m_object->m_type)
1747  {
1748  // make sure iterator fits the current value
1749  if (first.m_object != last.m_object)
1750  {
1751  throw std::domain_error("iterators are not compatible");
1752  }
1753 
1754  // check if iterator range is complete for primitive values
1755  switch (m_type)
1756  {
1757  case value_t::boolean:
1758  case value_t::number_float:
1759  case value_t::number_integer:
1760  case value_t::number_unsigned:
1761  case value_t::string:
1762  {
1763  if (not first.m_it.primitive_iterator.is_begin() or not last.m_it.primitive_iterator.is_end())
1764  {
1765  throw std::out_of_range("iterators out of range");
1766  }
1767  break;
1768  }
1769 
1770  default:
1771  {
1772  break;
1773  }
1774  }
1775 
1776  switch (m_type)
1777  {
1778  case value_t::number_integer:
1779  {
1780  assert(first.m_object != nullptr);
1781  m_value.number_integer = first.m_object->m_value.number_integer;
1782  break;
1783  }
1784 
1785  case value_t::number_unsigned:
1786  {
1787  assert(first.m_object != nullptr);
1788  m_value.number_unsigned = first.m_object->m_value.number_unsigned;
1789  break;
1790  }
1791 
1792  case value_t::number_float:
1793  {
1794  assert(first.m_object != nullptr);
1795  m_value.number_float = first.m_object->m_value.number_float;
1796  break;
1797  }
1798 
1799  case value_t::boolean:
1800  {
1801  assert(first.m_object != nullptr);
1802  m_value.boolean = first.m_object->m_value.boolean;
1803  break;
1804  }
1805 
1806  case value_t::string:
1807  {
1808  assert(first.m_object != nullptr);
1809  m_value = *first.m_object->m_value.string;
1810  break;
1811  }
1812 
1813  case value_t::object:
1814  {
1815  m_value.object = create<object_t>(first.m_it.object_iterator, last.m_it.object_iterator);
1816  break;
1817  }
1818 
1819  case value_t::array:
1820  {
1821  m_value.array = create<array_t>(first.m_it.array_iterator, last.m_it.array_iterator);
1822  break;
1823  }
1824 
1825  default:
1826  {
1827  assert(first.m_object != nullptr);
1828  throw std::domain_error("cannot use construct with iterators from " + first.m_object->type_name());
1829  }
1830  }
1831  }
1832 
1834  // other constructors and destructor //
1836 
1857  basic_json(const basic_json& other)
1858  : m_type(other.m_type)
1859  {
1860  switch (m_type)
1861  {
1862  case value_t::object:
1863  {
1864  assert(other.m_value.object != nullptr);
1865  m_value = *other.m_value.object;
1866  break;
1867  }
1868 
1869  case value_t::array:
1870  {
1871  assert(other.m_value.array != nullptr);
1872  m_value = *other.m_value.array;
1873  break;
1874  }
1875 
1876  case value_t::string:
1877  {
1878  assert(other.m_value.string != nullptr);
1879  m_value = *other.m_value.string;
1880  break;
1881  }
1882 
1883  case value_t::boolean:
1884  {
1885  m_value = other.m_value.boolean;
1886  break;
1887  }
1888 
1889  case value_t::number_integer:
1890  {
1891  m_value = other.m_value.number_integer;
1892  break;
1893  }
1894 
1895  case value_t::number_unsigned:
1896  {
1897  m_value = other.m_value.number_unsigned;
1898  break;
1899  }
1900 
1901  case value_t::number_float:
1902  {
1903  m_value = other.m_value.number_float;
1904  break;
1905  }
1906 
1907  default:
1908  {
1909  break;
1910  }
1911  }
1912  }
1913 
1932  basic_json(basic_json&& other) noexcept
1933  : m_type(std::move(other.m_type)),
1934  m_value(std::move(other.m_value))
1935  {
1936  // invalidate payload
1937  other.m_type = value_t::null;
1938  other.m_value = {};
1939  }
1940 
1962  reference& operator=(basic_json other) noexcept (
1963  std::is_nothrow_move_constructible<value_t>::value and
1964  std::is_nothrow_move_assignable<value_t>::value and
1965  std::is_nothrow_move_constructible<json_value>::value and
1966  std::is_nothrow_move_assignable<json_value>::value
1967  )
1968  {
1969  using std::swap;
1970  swap(m_type, other.m_type);
1971  swap(m_value, other.m_value);
1972  return *this;
1973  }
1974 
1989  {
1990  switch (m_type)
1991  {
1992  case value_t::object:
1993  {
1994  AllocatorType<object_t> alloc;
1995  alloc.destroy(m_value.object);
1996  alloc.deallocate(m_value.object, 1);
1997  break;
1998  }
1999 
2000  case value_t::array:
2001  {
2002  AllocatorType<array_t> alloc;
2003  alloc.destroy(m_value.array);
2004  alloc.deallocate(m_value.array, 1);
2005  break;
2006  }
2007 
2008  case value_t::string:
2009  {
2010  AllocatorType<string_t> alloc;
2011  alloc.destroy(m_value.string);
2012  alloc.deallocate(m_value.string, 1);
2013  break;
2014  }
2015 
2016  default:
2017  {
2018  // all other types need no specific destructor
2019  break;
2020  }
2021  }
2022  }
2023 
2025 
2026  public:
2028  // object inspection //
2030 
2033 
2057  string_t dump(const int indent = -1) const
2058  {
2059  std::stringstream ss;
2060 
2061  if (indent >= 0)
2062  {
2063  dump(ss, true, static_cast<unsigned int>(indent));
2064  }
2065  else
2066  {
2067  dump(ss, false, 0);
2068  }
2069 
2070  return ss.str();
2071  }
2072 
2088  value_t type() const noexcept
2089  {
2090  return m_type;
2091  }
2092 
2109  bool is_primitive() const noexcept
2110  {
2111  return is_null() or is_string() or is_boolean() or is_number();
2112  }
2113 
2129  bool is_structured() const noexcept
2130  {
2131  return is_array() or is_object();
2132  }
2133 
2148  bool is_null() const noexcept
2149  {
2150  return m_type == value_t::null;
2151  }
2152 
2167  bool is_boolean() const noexcept
2168  {
2169  return m_type == value_t::boolean;
2170  }
2171 
2194  bool is_number() const noexcept
2195  {
2196  return is_number_integer() or is_number_float();
2197  }
2198 
2220  bool is_number_integer() const noexcept
2221  {
2222  return m_type == value_t::number_integer or m_type == value_t::number_unsigned;
2223  }
2224 
2245  bool is_number_unsigned() const noexcept
2246  {
2247  return m_type == value_t::number_unsigned;
2248  }
2249 
2270  bool is_number_float() const noexcept
2271  {
2272  return m_type == value_t::number_float;
2273  }
2274 
2289  bool is_object() const noexcept
2290  {
2291  return m_type == value_t::object;
2292  }
2293 
2308  bool is_array() const noexcept
2309  {
2310  return m_type == value_t::array;
2311  }
2312 
2327  bool is_string() const noexcept
2328  {
2329  return m_type == value_t::string;
2330  }
2331 
2351  bool is_discarded() const noexcept
2352  {
2353  return m_type == value_t::discarded;
2354  }
2355 
2371  operator value_t() const noexcept
2372  {
2373  return m_type;
2374  }
2375 
2377 
2378  private:
2380  // value access //
2382 
2384  template <class T, typename
2385  std::enable_if<
2386  std::is_convertible<typename object_t::key_type, typename T::key_type>::value and
2387  std::is_convertible<basic_json_t, typename T::mapped_type>::value
2388  , int>::type = 0>
2389  T get_impl(T*) const
2390  {
2391  if (is_object())
2392  {
2393  assert(m_value.object != nullptr);
2394  return T(m_value.object->begin(), m_value.object->end());
2395  }
2396  else
2397  {
2398  throw std::domain_error("type must be object, but is " + type_name());
2399  }
2400  }
2401 
2403  object_t get_impl(object_t*) const
2404  {
2405  if (is_object())
2406  {
2407  assert(m_value.object != nullptr);
2408  return *(m_value.object);
2409  }
2410  else
2411  {
2412  throw std::domain_error("type must be object, but is " + type_name());
2413  }
2414  }
2415 
2417  template <class T, typename
2418  std::enable_if<
2419  std::is_convertible<basic_json_t, typename T::value_type>::value and
2420  not std::is_same<basic_json_t, typename T::value_type>::value and
2421  not std::is_arithmetic<T>::value and
2422  not std::is_convertible<std::string, T>::value and
2423  not has_mapped_type<T>::value
2424  , int>::type = 0>
2425  T get_impl(T*) const
2426  {
2427  if (is_array())
2428  {
2429  T to_vector;
2430  assert(m_value.array != nullptr);
2431  std::transform(m_value.array->begin(), m_value.array->end(),
2432  std::inserter(to_vector, to_vector.end()), [](basic_json i)
2433  {
2434  return i.get<typename T::value_type>();
2435  });
2436  return to_vector;
2437  }
2438  else
2439  {
2440  throw std::domain_error("type must be array, but is " + type_name());
2441  }
2442  }
2443 
2445  template <class T, typename
2446  std::enable_if<
2447  std::is_convertible<basic_json_t, T>::value and
2448  not std::is_same<basic_json_t, T>::value
2449  , int>::type = 0>
2450  std::vector<T> get_impl(std::vector<T>*) const
2451  {
2452  if (is_array())
2453  {
2454  std::vector<T> to_vector;
2455  assert(m_value.array != nullptr);
2456  to_vector.reserve(m_value.array->size());
2457  std::transform(m_value.array->begin(), m_value.array->end(),
2458  std::inserter(to_vector, to_vector.end()), [](basic_json i)
2459  {
2460  return i.get<T>();
2461  });
2462  return to_vector;
2463  }
2464  else
2465  {
2466  throw std::domain_error("type must be array, but is " + type_name());
2467  }
2468  }
2469 
2471  template <class T, typename
2472  std::enable_if<
2473  std::is_same<basic_json, typename T::value_type>::value and
2474  not has_mapped_type<T>::value
2475  , int>::type = 0>
2476  T get_impl(T*) const
2477  {
2478  if (is_array())
2479  {
2480  assert(m_value.array != nullptr);
2481  return T(m_value.array->begin(), m_value.array->end());
2482  }
2483  else
2484  {
2485  throw std::domain_error("type must be array, but is " + type_name());
2486  }
2487  }
2488 
2490  array_t get_impl(array_t*) const
2491  {
2492  if (is_array())
2493  {
2494  assert(m_value.array != nullptr);
2495  return *(m_value.array);
2496  }
2497  else
2498  {
2499  throw std::domain_error("type must be array, but is " + type_name());
2500  }
2501  }
2502 
2504  template <typename T, typename
2505  std::enable_if<
2506  std::is_convertible<string_t, T>::value
2507  , int>::type = 0>
2508  T get_impl(T*) const
2509  {
2510  if (is_string())
2511  {
2512  assert(m_value.string != nullptr);
2513  return *m_value.string;
2514  }
2515  else
2516  {
2517  throw std::domain_error("type must be string, but is " + type_name());
2518  }
2519  }
2520 
2522  template<typename T, typename
2523  std::enable_if<
2524  std::is_arithmetic<T>::value
2525  , int>::type = 0>
2526  T get_impl(T*) const
2527  {
2528  switch (m_type)
2529  {
2530  case value_t::number_integer:
2531  {
2532  return static_cast<T>(m_value.number_integer);
2533  }
2534 
2535  case value_t::number_unsigned:
2536  {
2537  return static_cast<T>(m_value.number_unsigned);
2538  }
2539 
2540  case value_t::number_float:
2541  {
2542  return static_cast<T>(m_value.number_float);
2543  }
2544 
2545  default:
2546  {
2547  throw std::domain_error("type must be number, but is " + type_name());
2548  }
2549  }
2550  }
2551 
2553  boolean_t get_impl(boolean_t*) const
2554  {
2555  if (is_boolean())
2556  {
2557  return m_value.boolean;
2558  }
2559  else
2560  {
2561  throw std::domain_error("type must be boolean, but is " + type_name());
2562  }
2563  }
2564 
2566  object_t* get_impl_ptr(object_t*) noexcept
2567  {
2568  return is_object() ? m_value.object : nullptr;
2569  }
2570 
2572  const object_t* get_impl_ptr(const object_t*) const noexcept
2573  {
2574  return is_object() ? m_value.object : nullptr;
2575  }
2576 
2578  array_t* get_impl_ptr(array_t*) noexcept
2579  {
2580  return is_array() ? m_value.array : nullptr;
2581  }
2582 
2584  const array_t* get_impl_ptr(const array_t*) const noexcept
2585  {
2586  return is_array() ? m_value.array : nullptr;
2587  }
2588 
2590  string_t* get_impl_ptr(string_t*) noexcept
2591  {
2592  return is_string() ? m_value.string : nullptr;
2593  }
2594 
2596  const string_t* get_impl_ptr(const string_t*) const noexcept
2597  {
2598  return is_string() ? m_value.string : nullptr;
2599  }
2600 
2602  boolean_t* get_impl_ptr(boolean_t*) noexcept
2603  {
2604  return is_boolean() ? &m_value.boolean : nullptr;
2605  }
2606 
2608  const boolean_t* get_impl_ptr(const boolean_t*) const noexcept
2609  {
2610  return is_boolean() ? &m_value.boolean : nullptr;
2611  }
2612 
2614  number_integer_t* get_impl_ptr(number_integer_t*) noexcept
2615  {
2616  return is_number_integer() ? &m_value.number_integer : nullptr;
2617  }
2618 
2620  const number_integer_t* get_impl_ptr(const number_integer_t*) const noexcept
2621  {
2622  return is_number_integer() ? &m_value.number_integer : nullptr;
2623  }
2624 
2626  number_unsigned_t* get_impl_ptr(number_unsigned_t*) noexcept
2627  {
2628  return is_number_unsigned() ? &m_value.number_unsigned : nullptr;
2629  }
2630 
2632  const number_unsigned_t* get_impl_ptr(const number_unsigned_t*) const noexcept
2633  {
2634  return is_number_unsigned() ? &m_value.number_unsigned : nullptr;
2635  }
2636 
2638  number_float_t* get_impl_ptr(number_float_t*) noexcept
2639  {
2640  return is_number_float() ? &m_value.number_float : nullptr;
2641  }
2642 
2644  const number_float_t* get_impl_ptr(const number_float_t*) const noexcept
2645  {
2646  return is_number_float() ? &m_value.number_float : nullptr;
2647  }
2648 
2660  template<typename ReferenceType, typename ThisType>
2661  static ReferenceType get_ref_impl(ThisType& obj)
2662  {
2663  // delegate the call to get_ptr<>()
2664  using PointerType = typename std::add_pointer<ReferenceType>::type;
2665  auto ptr = obj.template get_ptr<PointerType>();
2666 
2667  if (ptr != nullptr)
2668  {
2669  return *ptr;
2670  }
2671  else
2672  {
2673  throw std::domain_error("incompatible ReferenceType for get_ref, actual type is " +
2674  obj.type_name());
2675  }
2676  }
2677 
2678  public:
2679 
2682 
2716  template<typename ValueType, typename
2717  std::enable_if<
2718  not std::is_pointer<ValueType>::value
2719  , int>::type = 0>
2720  ValueType get() const
2721  {
2722  return get_impl(static_cast<ValueType*>(nullptr));
2723  }
2724 
2751  template<typename PointerType, typename
2752  std::enable_if<
2753  std::is_pointer<PointerType>::value
2754  , int>::type = 0>
2755  PointerType get() noexcept
2756  {
2757  // delegate the call to get_ptr
2758  return get_ptr<PointerType>();
2759  }
2760 
2765  template<typename PointerType, typename
2766  std::enable_if<
2767  std::is_pointer<PointerType>::value
2768  , int>::type = 0>
2769  const PointerType get() const noexcept
2770  {
2771  // delegate the call to get_ptr
2772  return get_ptr<PointerType>();
2773  }
2774 
2800  template<typename PointerType, typename
2801  std::enable_if<
2802  std::is_pointer<PointerType>::value
2803  , int>::type = 0>
2804  PointerType get_ptr() noexcept
2805  {
2806  // delegate the call to get_impl_ptr<>()
2807  return get_impl_ptr(static_cast<PointerType>(nullptr));
2808  }
2809 
2814  template<typename PointerType, typename
2815  std::enable_if<
2816  std::is_pointer<PointerType>::value
2817  and std::is_const<typename std::remove_pointer<PointerType>::type>::value
2818  , int>::type = 0>
2819  const PointerType get_ptr() const noexcept
2820  {
2821  // delegate the call to get_impl_ptr<>() const
2822  return get_impl_ptr(static_cast<const PointerType>(nullptr));
2823  }
2824 
2851  template<typename ReferenceType, typename
2852  std::enable_if<
2853  std::is_reference<ReferenceType>::value
2854  , int>::type = 0>
2855  ReferenceType get_ref()
2856  {
2857  // delegate call to get_ref_impl
2858  return get_ref_impl<ReferenceType>(*this);
2859  }
2860 
2865  template<typename ReferenceType, typename
2866  std::enable_if<
2867  std::is_reference<ReferenceType>::value
2868  and std::is_const<typename std::remove_reference<ReferenceType>::type>::value
2869  , int>::type = 0>
2870  ReferenceType get_ref() const
2871  {
2872  // delegate call to get_ref_impl
2873  return get_ref_impl<ReferenceType>(*this);
2874  }
2875 
2904  template < typename ValueType, typename
2905  std::enable_if <
2906  not std::is_pointer<ValueType>::value
2907  and not std::is_same<ValueType, typename string_t::value_type>::value
2908 #ifndef _MSC_VER // Fix for issue #167 operator<< abiguity under VS2015
2909  and not std::is_same<ValueType, std::initializer_list<typename string_t::value_type>>::value
2910 #endif
2911  , int >::type = 0 >
2912  operator ValueType() const
2913  {
2914  // delegate the call to get<>() const
2915  return get<ValueType>();
2916  }
2917 
2919 
2920 
2922  // element access //
2924 
2927 
2951  {
2952  // at only works for arrays
2953  if (is_array())
2954  {
2955  try
2956  {
2957  assert(m_value.array != nullptr);
2958  return m_value.array->at(idx);
2959  }
2960  catch (std::out_of_range&)
2961  {
2962  // create better exception explanation
2963  throw std::out_of_range("array index " + std::to_string(idx) + " is out of range");
2964  }
2965  }
2966  else
2967  {
2968  throw std::domain_error("cannot use at() with " + type_name());
2969  }
2970  }
2971 
2995  {
2996  // at only works for arrays
2997  if (is_array())
2998  {
2999  try
3000  {
3001  assert(m_value.array != nullptr);
3002  return m_value.array->at(idx);
3003  }
3004  catch (std::out_of_range&)
3005  {
3006  // create better exception explanation
3007  throw std::out_of_range("array index " + std::to_string(idx) + " is out of range");
3008  }
3009  }
3010  else
3011  {
3012  throw std::domain_error("cannot use at() with " + type_name());
3013  }
3014  }
3015 
3042  reference at(const typename object_t::key_type& key)
3043  {
3044  // at only works for objects
3045  if (is_object())
3046  {
3047  try
3048  {
3049  assert(m_value.object != nullptr);
3050  return m_value.object->at(key);
3051  }
3052  catch (std::out_of_range&)
3053  {
3054  // create better exception explanation
3055  throw std::out_of_range("key '" + key + "' not found");
3056  }
3057  }
3058  else
3059  {
3060  throw std::domain_error("cannot use at() with " + type_name());
3061  }
3062  }
3063 
3090  const_reference at(const typename object_t::key_type& key) const
3091  {
3092  // at only works for objects
3093  if (is_object())
3094  {
3095  try
3096  {
3097  assert(m_value.object != nullptr);
3098  return m_value.object->at(key);
3099  }
3100  catch (std::out_of_range&)
3101  {
3102  // create better exception explanation
3103  throw std::out_of_range("key '" + key + "' not found");
3104  }
3105  }
3106  else
3107  {
3108  throw std::domain_error("cannot use at() with " + type_name());
3109  }
3110  }
3111 
3138  {
3139  // implicitly convert null to object
3140  if (is_null())
3141  {
3142  m_type = value_t::array;
3143  m_value.array = create<array_t>();
3144  }
3145 
3146  // [] only works for arrays
3147  if (is_array())
3148  {
3149  assert(m_value.array != nullptr);
3150  for (size_t i = m_value.array->size(); i <= idx; ++i)
3151  {
3152  m_value.array->push_back(basic_json());
3153  }
3154 
3155  return m_value.array->operator[](idx);
3156  }
3157  else
3158  {
3159  throw std::domain_error("cannot use operator[] with " + type_name());
3160  }
3161  }
3162 
3183  {
3184  // at only works for arrays
3185  if (is_array())
3186  {
3187  assert(m_value.array != nullptr);
3188  return m_value.array->operator[](idx);
3189  }
3190  else
3191  {
3192  throw std::domain_error("cannot use operator[] with " + type_name());
3193  }
3194  }
3195 
3223  reference operator[](const typename object_t::key_type& key)
3224  {
3225  // implicitly convert null to object
3226  if (is_null())
3227  {
3228  m_type = value_t::object;
3229  m_value.object = create<object_t>();
3230  }
3231 
3232  // [] only works for objects
3233  if (is_object())
3234  {
3235  assert(m_value.object != nullptr);
3236  return m_value.object->operator[](key);
3237  }
3238  else
3239  {
3240  throw std::domain_error("cannot use operator[] with " + type_name());
3241  }
3242  }
3243 
3271  const_reference operator[](const typename object_t::key_type& key) const
3272  {
3273  // [] only works for objects
3274  if (is_object())
3275  {
3276  assert(m_value.object != nullptr);
3277  assert(m_value.object->find(key) != m_value.object->end());
3278  return m_value.object->find(key)->second;
3279  }
3280  else
3281  {
3282  throw std::domain_error("cannot use operator[] with " + type_name());
3283  }
3284  }
3285 
3313  template<typename T, std::size_t n>
3314  reference operator[](T * (&key)[n])
3315  {
3316  return operator[](static_cast<const T>(key));
3317  }
3318 
3348  template<typename T, std::size_t n>
3349  const_reference operator[](T * (&key)[n]) const
3350  {
3351  return operator[](static_cast<const T>(key));
3352  }
3353 
3381  template<typename T>
3383  {
3384  // implicitly convert null to object
3385  if (is_null())
3386  {
3387  m_type = value_t::object;
3388  m_value = value_t::object;
3389  }
3390 
3391  // at only works for objects
3392  if (is_object())
3393  {
3394  assert(m_value.object != nullptr);
3395  return m_value.object->operator[](key);
3396  }
3397  else
3398  {
3399  throw std::domain_error("cannot use operator[] with " + type_name());
3400  }
3401  }
3402 
3430  template<typename T>
3432  {
3433  // at only works for objects
3434  if (is_object())
3435  {
3436  assert(m_value.object != nullptr);
3437  assert(m_value.object->find(key) != m_value.object->end());
3438  return m_value.object->find(key)->second;
3439  }
3440  else
3441  {
3442  throw std::domain_error("cannot use operator[] with " + type_name());
3443  }
3444  }
3445 
3494  template <class ValueType, typename
3495  std::enable_if<
3496  std::is_convertible<basic_json_t, ValueType>::value
3497  , int>::type = 0>
3498  ValueType value(const typename object_t::key_type& key, ValueType default_value) const
3499  {
3500  // at only works for objects
3501  if (is_object())
3502  {
3503  // if key is found, return value and given default value otherwise
3504  const auto it = find(key);
3505  if (it != end())
3506  {
3507  return *it;
3508  }
3509  else
3510  {
3511  return default_value;
3512  }
3513  }
3514  else
3515  {
3516  throw std::domain_error("cannot use value() with " + type_name());
3517  }
3518  }
3519 
3524  string_t value(const typename object_t::key_type& key, const char* default_value) const
3525  {
3526  return value(key, string_t(default_value));
3527  }
3528 
3550  {
3551  return *begin();
3552  }
3553 
3558  {
3559  return *cbegin();
3560  }
3561 
3584  {
3585  auto tmp = end();
3586  --tmp;
3587  return *tmp;
3588  }
3589 
3594  {
3595  auto tmp = cend();
3596  --tmp;
3597  return *tmp;
3598  }
3599 
3644  template <class InteratorType, typename
3645  std::enable_if<
3646  std::is_same<InteratorType, typename basic_json_t::iterator>::value or
3647  std::is_same<InteratorType, typename basic_json_t::const_iterator>::value
3648  , int>::type
3649  = 0>
3650  InteratorType erase(InteratorType pos)
3651  {
3652  // make sure iterator fits the current value
3653  if (this != pos.m_object)
3654  {
3655  throw std::domain_error("iterator does not fit current value");
3656  }
3657 
3658  InteratorType result = end();
3659 
3660  switch (m_type)
3661  {
3662  case value_t::boolean:
3663  case value_t::number_float:
3664  case value_t::number_integer:
3665  case value_t::number_unsigned:
3666  case value_t::string:
3667  {
3668  if (not pos.m_it.primitive_iterator.is_begin())
3669  {
3670  throw std::out_of_range("iterator out of range");
3671  }
3672 
3673  if (is_string())
3674  {
3675  delete m_value.string;
3676  m_value.string = nullptr;
3677  }
3678 
3679  m_type = value_t::null;
3680  break;
3681  }
3682 
3683  case value_t::object:
3684  {
3685  assert(m_value.object != nullptr);
3686  result.m_it.object_iterator = m_value.object->erase(pos.m_it.object_iterator);
3687  break;
3688  }
3689 
3690  case value_t::array:
3691  {
3692  assert(m_value.array != nullptr);
3693  result.m_it.array_iterator = m_value.array->erase(pos.m_it.array_iterator);
3694  break;
3695  }
3696 
3697  default:
3698  {
3699  throw std::domain_error("cannot use erase() with " + type_name());
3700  }
3701  }
3702 
3703  return result;
3704  }
3705 
3750  template <class InteratorType, typename
3751  std::enable_if<
3752  std::is_same<InteratorType, typename basic_json_t::iterator>::value or
3753  std::is_same<InteratorType, typename basic_json_t::const_iterator>::value
3754  , int>::type
3755  = 0>
3756  InteratorType erase(InteratorType first, InteratorType last)
3757  {
3758  // make sure iterator fits the current value
3759  if (this != first.m_object or this != last.m_object)
3760  {
3761  throw std::domain_error("iterators do not fit current value");
3762  }
3763 
3764  InteratorType result = end();
3765 
3766  switch (m_type)
3767  {
3768  case value_t::boolean:
3769  case value_t::number_float:
3770  case value_t::number_integer:
3771  case value_t::number_unsigned:
3772  case value_t::string:
3773  {
3774  if (not first.m_it.primitive_iterator.is_begin() or not last.m_it.primitive_iterator.is_end())
3775  {
3776  throw std::out_of_range("iterators out of range");
3777  }
3778 
3779  if (is_string())
3780  {
3781  delete m_value.string;
3782  m_value.string = nullptr;
3783  }
3784 
3785  m_type = value_t::null;
3786  break;
3787  }
3788 
3789  case value_t::object:
3790  {
3791  assert(m_value.object != nullptr);
3792  result.m_it.object_iterator = m_value.object->erase(first.m_it.object_iterator,
3793  last.m_it.object_iterator);
3794  break;
3795  }
3796 
3797  case value_t::array:
3798  {
3799  assert(m_value.array != nullptr);
3800  result.m_it.array_iterator = m_value.array->erase(first.m_it.array_iterator,
3801  last.m_it.array_iterator);
3802  break;
3803  }
3804 
3805  default:
3806  {
3807  throw std::domain_error("cannot use erase() with " + type_name());
3808  }
3809  }
3810 
3811  return result;
3812  }
3813 
3840  size_type erase(const typename object_t::key_type& key)
3841  {
3842  // this erase only works for objects
3843  if (is_object())
3844  {
3845  assert(m_value.object != nullptr);
3846  return m_value.object->erase(key);
3847  }
3848  else
3849  {
3850  throw std::domain_error("cannot use erase() with " + type_name());
3851  }
3852  }
3853 
3878  void erase(const size_type idx)
3879  {
3880  // this erase only works for arrays
3881  if (is_array())
3882  {
3883  if (idx >= size())
3884  {
3885  throw std::out_of_range("index out of range");
3886  }
3887 
3888  assert(m_value.array != nullptr);
3889  m_value.array->erase(m_value.array->begin() + static_cast<difference_type>(idx));
3890  }
3891  else
3892  {
3893  throw std::domain_error("cannot use erase() with " + type_name());
3894  }
3895  }
3896 
3914  iterator find(typename object_t::key_type key)
3915  {
3916  auto result = end();
3917 
3918  if (is_object())
3919  {
3920  assert(m_value.object != nullptr);
3921  result.m_it.object_iterator = m_value.object->find(key);
3922  }
3923 
3924  return result;
3925  }
3926 
3931  const_iterator find(typename object_t::key_type key) const
3932  {
3933  auto result = cend();
3934 
3935  if (is_object())
3936  {
3937  assert(m_value.object != nullptr);
3938  result.m_it.object_iterator = m_value.object->find(key);
3939  }
3940 
3941  return result;
3942  }
3943 
3962  size_type count(typename object_t::key_type key) const
3963  {
3964  // return 0 for all nonobject types
3965  assert(not is_object() or m_value.object != nullptr);
3966  return is_object() ? m_value.object->count(key) : 0;
3967  }
3968 
3970 
3971 
3973  // iterators //
3975 
3978 
3998  {
3999  iterator result(this);
4000  result.set_begin();
4001  return result;
4002  }
4003 
4008  {
4009  return cbegin();
4010  }
4011 
4032  {
4033  const_iterator result(this);
4034  result.set_begin();
4035  return result;
4036  }
4037 
4057  {
4058  iterator result(this);
4059  result.set_end();
4060  return result;
4061  }
4062 
4067  {
4068  return cend();
4069  }
4070 
4091  {
4092  const_iterator result(this);
4093  result.set_end();
4094  return result;
4095  }
4096 
4115  {
4116  return reverse_iterator(end());
4117  }
4118 
4123  {
4124  return crbegin();
4125  }
4126 
4146  {
4147  return reverse_iterator(begin());
4148  }
4149 
4154  {
4155  return crend();
4156  }
4157 
4177  {
4178  return const_reverse_iterator(cend());
4179  }
4180 
4200  {
4201  return const_reverse_iterator(cbegin());
4202  }
4203 
4204  private:
4205  // forward declaration
4206  template<typename IteratorType> class iteration_proxy;
4207 
4208  public:
4220  static iteration_proxy<iterator> iterator_wrapper(reference cont)
4221  {
4222  return iteration_proxy<iterator>(cont);
4223  }
4224 
4228  static iteration_proxy<const_iterator> iterator_wrapper(const_reference cont)
4229  {
4230  return iteration_proxy<const_iterator>(cont);
4231  }
4232 
4234 
4235 
4237  // capacity //
4239 
4242 
4272  bool empty() const noexcept
4273  {
4274  switch (m_type)
4275  {
4276  case value_t::null:
4277  {
4278  // null values are empty
4279  return true;
4280  }
4281 
4282  case value_t::array:
4283  {
4284  assert(m_value.array != nullptr);
4285  return m_value.array->empty();
4286  }
4287 
4288  case value_t::object:
4289  {
4290  assert(m_value.object != nullptr);
4291  return m_value.object->empty();
4292  }
4293 
4294  default:
4295  {
4296  // all other types are nonempty
4297  return false;
4298  }
4299  }
4300  }
4301 
4330  size_type size() const noexcept
4331  {
4332  switch (m_type)
4333  {
4334  case value_t::null:
4335  {
4336  // null values are empty
4337  return 0;
4338  }
4339 
4340  case value_t::array:
4341  {
4342  assert(m_value.array != nullptr);
4343  return m_value.array->size();
4344  }
4345 
4346  case value_t::object:
4347  {
4348  assert(m_value.object != nullptr);
4349  return m_value.object->size();
4350  }
4351 
4352  default:
4353  {
4354  // all other types have size 1
4355  return 1;
4356  }
4357  }
4358  }
4359 
4392  size_type max_size() const noexcept
4393  {
4394  switch (m_type)
4395  {
4396  case value_t::array:
4397  {
4398  assert(m_value.array != nullptr);
4399  return m_value.array->max_size();
4400  }
4401 
4402  case value_t::object:
4403  {
4404  assert(m_value.object != nullptr);
4405  return m_value.object->max_size();
4406  }
4407 
4408  default:
4409  {
4410  // all other types have max_size() == size()
4411  return size();
4412  }
4413  }
4414  }
4415 
4417 
4418 
4420  // modifiers //
4422 
4425 
4451  void clear() noexcept
4452  {
4453  switch (m_type)
4454  {
4455  case value_t::number_integer:
4456  {
4457  m_value.number_integer = 0;
4458  break;
4459  }
4460 
4461  case value_t::number_unsigned:
4462  {
4463  m_value.number_unsigned = 0;
4464  break;
4465  }
4466 
4467  case value_t::number_float:
4468  {
4469  m_value.number_float = 0.0;
4470  break;
4471  }
4472 
4473  case value_t::boolean:
4474  {
4475  m_value.boolean = false;
4476  break;
4477  }
4478 
4479  case value_t::string:
4480  {
4481  assert(m_value.string != nullptr);
4482  m_value.string->clear();
4483  break;
4484  }
4485 
4486  case value_t::array:
4487  {
4488  assert(m_value.array != nullptr);
4489  m_value.array->clear();
4490  break;
4491  }
4492 
4493  case value_t::object:
4494  {
4495  assert(m_value.object != nullptr);
4496  m_value.object->clear();
4497  break;
4498  }
4499 
4500  default:
4501  {
4502  break;
4503  }
4504  }
4505  }
4506 
4527  void push_back(basic_json&& val)
4528  {
4529  // push_back only works for null objects or arrays
4530  if (not(is_null() or is_array()))
4531  {
4532  throw std::domain_error("cannot use push_back() with " + type_name());
4533  }
4534 
4535  // transform null object into an array
4536  if (is_null())
4537  {
4538  m_type = value_t::array;
4539  m_value = value_t::array;
4540  }
4541 
4542  // add element to array (move semantics)
4543  assert(m_value.array != nullptr);
4544  m_value.array->push_back(std::move(val));
4545  // invalidate object
4546  val.m_type = value_t::null;
4547  }
4548 
4553  reference operator+=(basic_json&& val)
4554  {
4555  push_back(std::move(val));
4556  return *this;
4557  }
4558 
4563  void push_back(const basic_json& val)
4564  {
4565  // push_back only works for null objects or arrays
4566  if (not(is_null() or is_array()))
4567  {
4568  throw std::domain_error("cannot use push_back() with " + type_name());
4569  }
4570 
4571  // transform null object into an array
4572  if (is_null())
4573  {
4574  m_type = value_t::array;
4575  m_value = value_t::array;
4576  }
4577 
4578  // add element to array
4579  assert(m_value.array != nullptr);
4580  m_value.array->push_back(val);
4581  }
4582 
4587  reference operator+=(const basic_json& val)
4588  {
4589  push_back(val);
4590  return *this;
4591  }
4592 
4613  void push_back(const typename object_t::value_type& val)
4614  {
4615  // push_back only works for null objects or objects
4616  if (not(is_null() or is_object()))
4617  {
4618  throw std::domain_error("cannot use push_back() with " + type_name());
4619  }
4620 
4621  // transform null object into an object
4622  if (is_null())
4623  {
4624  m_type = value_t::object;
4625  m_value = value_t::object;
4626  }
4627 
4628  // add element to array
4629  assert(m_value.object != nullptr);
4630  m_value.object->insert(val);
4631  }
4632 
4637  reference operator+=(const typename object_t::value_type& val)
4638  {
4639  push_back(val);
4640  return operator[](val.first);
4641  }
4642 
4665  iterator insert(const_iterator pos, const basic_json& val)
4666  {
4667  // insert only works for arrays
4668  if (is_array())
4669  {
4670  // check if iterator pos fits to this JSON value
4671  if (pos.m_object != this)
4672  {
4673  throw std::domain_error("iterator does not fit current value");
4674  }
4675 
4676  // insert to array and return iterator
4677  iterator result(this);
4678  assert(m_value.array != nullptr);
4679  result.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator, val);
4680  return result;
4681  }
4682  else
4683  {
4684  throw std::domain_error("cannot use insert() with " + type_name());
4685  }
4686  }
4687 
4692  iterator insert(const_iterator pos, basic_json&& val)
4693  {
4694  return insert(pos, val);
4695  }
4696 
4721  iterator insert(const_iterator pos, size_type cnt, const basic_json& val)
4722  {
4723  // insert only works for arrays
4724  if (is_array())
4725  {
4726  // check if iterator pos fits to this JSON value
4727  if (pos.m_object != this)
4728  {
4729  throw std::domain_error("iterator does not fit current value");
4730  }
4731 
4732  // insert to array and return iterator
4733  iterator result(this);
4734  assert(m_value.array != nullptr);
4735  result.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator, cnt, val);
4736  return result;
4737  }
4738  else
4739  {
4740  throw std::domain_error("cannot use insert() with " + type_name());
4741  }
4742  }
4743 
4775  {
4776  // insert only works for arrays
4777  if (not is_array())
4778  {
4779  throw std::domain_error("cannot use insert() with " + type_name());
4780  }
4781 
4782  // check if iterator pos fits to this JSON value
4783  if (pos.m_object != this)
4784  {
4785  throw std::domain_error("iterator does not fit current value");
4786  }
4787 
4788  if (first.m_object != last.m_object)
4789  {
4790  throw std::domain_error("iterators do not fit");
4791  }
4792 
4793  if (first.m_object == this or last.m_object == this)
4794  {
4795  throw std::domain_error("passed iterators may not belong to container");
4796  }
4797 
4798  // insert to array and return iterator
4799  iterator result(this);
4800  assert(m_value.array != nullptr);
4801  result.m_it.array_iterator = m_value.array->insert(
4802  pos.m_it.array_iterator,
4803  first.m_it.array_iterator,
4804  last.m_it.array_iterator);
4805  return result;
4806  }
4807 
4832  iterator insert(const_iterator pos, std::initializer_list<basic_json> ilist)
4833  {
4834  // insert only works for arrays
4835  if (not is_array())
4836  {
4837  throw std::domain_error("cannot use insert() with " + type_name());
4838  }
4839 
4840  // check if iterator pos fits to this JSON value
4841  if (pos.m_object != this)
4842  {
4843  throw std::domain_error("iterator does not fit current value");
4844  }
4845 
4846  // insert to array and return iterator
4847  iterator result(this);
4848  assert(m_value.array != nullptr);
4849  result.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator, ilist);
4850  return result;
4851  }
4852 
4870  void swap(reference other) noexcept (
4871  std::is_nothrow_move_constructible<value_t>::value and
4872  std::is_nothrow_move_assignable<value_t>::value and
4873  std::is_nothrow_move_constructible<json_value>::value and
4874  std::is_nothrow_move_assignable<json_value>::value
4875  )
4876  {
4877  std::swap(m_type, other.m_type);
4878  std::swap(m_value, other.m_value);
4879  }
4880 
4901  void swap(array_t& other)
4902  {
4903  // swap only works for arrays
4904  if (is_array())
4905  {
4906  assert(m_value.array != nullptr);
4907  std::swap(*(m_value.array), other);
4908  }
4909  else
4910  {
4911  throw std::domain_error("cannot use swap() with " + type_name());
4912  }
4913  }
4914 
4935  void swap(object_t& other)
4936  {
4937  // swap only works for objects
4938  if (is_object())
4939  {
4940  assert(m_value.object != nullptr);
4941  std::swap(*(m_value.object), other);
4942  }
4943  else
4944  {
4945  throw std::domain_error("cannot use swap() with " + type_name());
4946  }
4947  }
4948 
4969  void swap(string_t& other)
4970  {
4971  // swap only works for strings
4972  if (is_string())
4973  {
4974  assert(m_value.string != nullptr);
4975  std::swap(*(m_value.string), other);
4976  }
4977  else
4978  {
4979  throw std::domain_error("cannot use swap() with " + type_name());
4980  }
4981  }
4982 
4984 
4985 
4987  // lexicographical comparison operators //
4989 
4992 
4993  private:
5003  friend bool operator<(const value_t lhs, const value_t rhs)
5004  {
5005  static constexpr std::array<uint8_t, 8> order = {{
5006  0, // null
5007  3, // object
5008  4, // array
5009  5, // string
5010  1, // boolean
5011  2, // integer
5012  2, // unsigned
5013  2, // float
5014  }
5015  };
5016 
5017  // discarded values are not comparable
5018  if (lhs == value_t::discarded or rhs == value_t::discarded)
5019  {
5020  return false;
5021  }
5022 
5023  return order[static_cast<std::size_t>(lhs)] < order[static_cast<std::size_t>(rhs)];
5024  }
5025 
5026  public:
5050  friend bool operator==(const_reference lhs, const_reference rhs) noexcept
5051  {
5052  const auto lhs_type = lhs.type();
5053  const auto rhs_type = rhs.type();
5054 
5055  if (lhs_type == rhs_type)
5056  {
5057  switch (lhs_type)
5058  {
5059  case value_t::array:
5060  {
5061  assert(lhs.m_value.array != nullptr);
5062  assert(rhs.m_value.array != nullptr);
5063  return *lhs.m_value.array == *rhs.m_value.array;
5064  }
5065  case value_t::object:
5066  {
5067  assert(lhs.m_value.object != nullptr);
5068  assert(rhs.m_value.object != nullptr);
5069  return *lhs.m_value.object == *rhs.m_value.object;
5070  }
5071  case value_t::null:
5072  {
5073  return true;
5074  }
5075  case value_t::string:
5076  {
5077  assert(lhs.m_value.string != nullptr);
5078  assert(rhs.m_value.string != nullptr);
5079  return *lhs.m_value.string == *rhs.m_value.string;
5080  }
5081  case value_t::boolean:
5082  {
5083  return lhs.m_value.boolean == rhs.m_value.boolean;
5084  }
5085  case value_t::number_integer:
5086  {
5087  return lhs.m_value.number_integer == rhs.m_value.number_integer;
5088  }
5089  case value_t::number_unsigned:
5090  {
5091  return lhs.m_value.number_unsigned == rhs.m_value.number_unsigned;
5092  }
5093  case value_t::number_float:
5094  {
5095  return lhs.m_value.number_float == rhs.m_value.number_float;
5096  }
5097  default:
5098  {
5099  return false;
5100  }
5101  }
5102  }
5103  else if (lhs_type == value_t::number_integer and rhs_type == value_t::number_float)
5104  {
5105  return static_cast<number_float_t>(lhs.m_value.number_integer) == rhs.m_value.number_float;
5106  }
5107  else if (lhs_type == value_t::number_float and rhs_type == value_t::number_integer)
5108  {
5109  return lhs.m_value.number_float == static_cast<number_float_t>(rhs.m_value.number_integer);
5110  }
5111  else if (lhs_type == value_t::number_unsigned and rhs_type == value_t::number_float)
5112  {
5113  return static_cast<number_float_t>(lhs.m_value.number_unsigned) == rhs.m_value.number_float;
5114  }
5115  else if (lhs_type == value_t::number_float and rhs_type == value_t::number_unsigned)
5116  {
5117  return lhs.m_value.number_float == static_cast<number_float_t>(rhs.m_value.number_unsigned);
5118  }
5119  else if (lhs_type == value_t::number_unsigned and rhs_type == value_t::number_integer)
5120  {
5121  return static_cast<number_integer_t>(lhs.m_value.number_unsigned) == rhs.m_value.number_integer;
5122  }
5123  else if (lhs_type == value_t::number_integer and rhs_type == value_t::number_unsigned)
5124  {
5125  return lhs.m_value.number_integer == static_cast<number_integer_t>(rhs.m_value.number_unsigned);
5126  }
5127 
5128  return false;
5129  }
5130 
5149  friend bool operator==(const_reference v, std::nullptr_t) noexcept
5150  {
5151  return v.is_null();
5152  }
5153 
5158  friend bool operator==(std::nullptr_t, const_reference v) noexcept
5159  {
5160  return v.is_null();
5161  }
5162 
5179  friend bool operator!=(const_reference lhs, const_reference rhs) noexcept
5180  {
5181  return not (lhs == rhs);
5182  }
5183 
5202  friend bool operator!=(const_reference v, std::nullptr_t) noexcept
5203  {
5204  return not v.is_null();
5205  }
5206 
5211  friend bool operator!=(std::nullptr_t, const_reference v) noexcept
5212  {
5213  return not v.is_null();
5214  }
5215 
5240  friend bool operator<(const_reference lhs, const_reference rhs) noexcept
5241  {
5242  const auto lhs_type = lhs.type();
5243  const auto rhs_type = rhs.type();
5244 
5245  if (lhs_type == rhs_type)
5246  {
5247  switch (lhs_type)
5248  {
5249  case value_t::array:
5250  {
5251  assert(lhs.m_value.array != nullptr);
5252  assert(rhs.m_value.array != nullptr);
5253  return *lhs.m_value.array < *rhs.m_value.array;
5254  }
5255  case value_t::object:
5256  {
5257  assert(lhs.m_value.object != nullptr);
5258  assert(rhs.m_value.object != nullptr);
5259  return *lhs.m_value.object < *rhs.m_value.object;
5260  }
5261  case value_t::null:
5262  {
5263  return false;
5264  }
5265  case value_t::string:
5266  {
5267  assert(lhs.m_value.string != nullptr);
5268  assert(rhs.m_value.string != nullptr);
5269  return *lhs.m_value.string < *rhs.m_value.string;
5270  }
5271  case value_t::boolean:
5272  {
5273  return lhs.m_value.boolean < rhs.m_value.boolean;
5274  }
5275  case value_t::number_integer:
5276  {
5277  return lhs.m_value.number_integer < rhs.m_value.number_integer;
5278  }
5279  case value_t::number_unsigned:
5280  {
5281  return lhs.m_value.number_unsigned < rhs.m_value.number_unsigned;
5282  }
5283  case value_t::number_float:
5284  {
5285  return lhs.m_value.number_float < rhs.m_value.number_float;
5286  }
5287  default:
5288  {
5289  return false;
5290  }
5291  }
5292  }
5293  else if (lhs_type == value_t::number_integer and rhs_type == value_t::number_float)
5294  {
5295  return static_cast<number_float_t>(lhs.m_value.number_integer) < rhs.m_value.number_float;
5296  }
5297  else if (lhs_type == value_t::number_float and rhs_type == value_t::number_integer)
5298  {
5299  return lhs.m_value.number_float < static_cast<number_float_t>(rhs.m_value.number_integer);
5300  }
5301  else if (lhs_type == value_t::number_unsigned and rhs_type == value_t::number_float)
5302  {
5303  return static_cast<number_float_t>(lhs.m_value.number_unsigned) < rhs.m_value.number_float;
5304  }
5305  else if (lhs_type == value_t::number_float and rhs_type == value_t::number_unsigned)
5306  {
5307  return lhs.m_value.number_float < static_cast<number_float_t>(rhs.m_value.number_unsigned);
5308  }
5309  else if (lhs_type == value_t::number_integer and rhs_type == value_t::number_unsigned)
5310  {
5311  return lhs.m_value.number_integer < static_cast<number_integer_t>(rhs.m_value.number_unsigned);
5312  }
5313  else if (lhs_type == value_t::number_unsigned and rhs_type == value_t::number_integer)
5314  {
5315  return static_cast<number_integer_t>(lhs.m_value.number_unsigned) < rhs.m_value.number_integer;
5316  }
5317 
5318  // We only reach this line if we cannot compare values. In that case,
5319  // we compare types. Note we have to call the operator explicitly,
5320  // because MSVC has problems otherwise.
5321  return operator<(lhs_type, rhs_type);
5322  }
5323 
5341  friend bool operator<=(const_reference lhs, const_reference rhs) noexcept
5342  {
5343  return not (rhs < lhs);
5344  }
5345 
5363  friend bool operator>(const_reference lhs, const_reference rhs) noexcept
5364  {
5365  return not (lhs <= rhs);
5366  }
5367 
5385  friend bool operator>=(const_reference lhs, const_reference rhs) noexcept
5386  {
5387  return not (lhs < rhs);
5388  }
5389 
5391 
5392 
5394  // serialization //
5396 
5399 
5422  friend std::ostream& operator<<(std::ostream& o, const basic_json& j)
5423  {
5424  // read width member and use it as indentation parameter if nonzero
5425  const bool pretty_print = (o.width() > 0);
5426  const auto indentation = (pretty_print ? o.width() : 0);
5427 
5428  // reset width to 0 for subsequent calls to this stream
5429  o.width(0);
5430 
5431  // do the actual serialization
5432  j.dump(o, pretty_print, static_cast<unsigned int>(indentation));
5433  return o;
5434  }
5435 
5440  friend std::ostream& operator>>(const basic_json& j, std::ostream& o)
5441  {
5442  return o << j;
5443  }
5444 
5446 
5447 
5449  // deserialization //
5451 
5454 
5479  static basic_json parse(const string_t& s, parser_callback_t cb = nullptr)
5480  {
5481  return parser(s, cb).parse();
5482  }
5483 
5508  static basic_json parse(std::istream& i, parser_callback_t cb = nullptr)
5509  {
5510  return parser(i, cb).parse();
5511  }
5512 
5516  static basic_json parse(std::istream&& i, parser_callback_t cb = nullptr)
5517  {
5518  return parser(i, cb).parse();
5519  }
5520 
5544  friend std::istream& operator<<(basic_json& j, std::istream& i)
5545  {
5546  j = parser(i).parse();
5547  return i;
5548  }
5549 
5554  friend std::istream& operator>>(std::istream& i, basic_json& j)
5555  {
5556  j = parser(i).parse();
5557  return i;
5558  }
5559 
5561 
5562 
5563  private:
5565  // convenience functions //
5567 
5569  string_t type_name() const
5570  {
5571  switch (m_type)
5572  {
5573  case value_t::null:
5574  return "null";
5575  case value_t::object:
5576  return "object";
5577  case value_t::array:
5578  return "array";
5579  case value_t::string:
5580  return "string";
5581  case value_t::boolean:
5582  return "boolean";
5583  case value_t::discarded:
5584  return "discarded";
5585  default:
5586  return "number";
5587  }
5588  }
5589 
5598  static std::size_t extra_space(const string_t& s) noexcept
5599  {
5600  std::size_t result = 0;
5601 
5602  for (const auto& c : s)
5603  {
5604  switch (c)
5605  {
5606  case '"':
5607  case '\\':
5608  case '\b':
5609  case '\f':
5610  case '\n':
5611  case '\r':
5612  case '\t':
5613  {
5614  // from c (1 byte) to \x (2 bytes)
5615  result += 1;
5616  break;
5617  }
5618 
5619  default:
5620  {
5621  if (c >= 0x00 and c <= 0x1f)
5622  {
5623  // from c (1 byte) to \uxxxx (6 bytes)
5624  result += 5;
5625  }
5626  break;
5627  }
5628  }
5629  }
5630 
5631  return result;
5632  }
5633 
5647  static string_t escape_string(const string_t& s) noexcept
5648  {
5649  const auto space = extra_space(s);
5650  if (space == 0)
5651  {
5652  return s;
5653  }
5654 
5655  // create a result string of necessary size
5656  string_t result(s.size() + space, '\\');
5657  std::size_t pos = 0;
5658 
5659  for (const auto& c : s)
5660  {
5661  switch (c)
5662  {
5663  // quotation mark (0x22)
5664  case '"':
5665  {
5666  result[pos + 1] = '"';
5667  pos += 2;
5668  break;
5669  }
5670 
5671  // reverse solidus (0x5c)
5672  case '\\':
5673  {
5674  // nothing to change
5675  pos += 2;
5676  break;
5677  }
5678 
5679  // backspace (0x08)
5680  case '\b':
5681  {
5682  result[pos + 1] = 'b';
5683  pos += 2;
5684  break;
5685  }
5686 
5687  // formfeed (0x0c)
5688  case '\f':
5689  {
5690  result[pos + 1] = 'f';
5691  pos += 2;
5692  break;
5693  }
5694 
5695  // newline (0x0a)
5696  case '\n':
5697  {
5698  result[pos + 1] = 'n';
5699  pos += 2;
5700  break;
5701  }
5702 
5703  // carriage return (0x0d)
5704  case '\r':
5705  {
5706  result[pos + 1] = 'r';
5707  pos += 2;
5708  break;
5709  }
5710 
5711  // horizontal tab (0x09)
5712  case '\t':
5713  {
5714  result[pos + 1] = 't';
5715  pos += 2;
5716  break;
5717  }
5718 
5719  default:
5720  {
5721  if (c >= 0x00 and c <= 0x1f)
5722  {
5723  // convert a number 0..15 to its hex representation (0..f)
5724  auto hexify = [](const char v) -> char
5725  {
5726  return (v < 10) ? ('0' + v) : ('a' + v - 10);
5727  };
5728 
5729  // print character c as \uxxxx
5730  for (const char m :
5731  { 'u', '0', '0', hexify(c >> 4), hexify(c & 0x0f)
5732  })
5733  {
5734  result[++pos] = m;
5735  }
5736 
5737  ++pos;
5738  }
5739  else
5740  {
5741  // all other characters are added as-is
5742  result[pos++] = c;
5743  }
5744  break;
5745  }
5746  }
5747  }
5748 
5749  return result;
5750  }
5751 
5769  void dump(std::ostream& o,
5770  const bool pretty_print,
5771  const unsigned int indent_step,
5772  const unsigned int current_indent = 0) const
5773  {
5774  // variable to hold indentation for recursive calls
5775  unsigned int new_indent = current_indent;
5776 
5777  switch (m_type)
5778  {
5779  case value_t::object:
5780  {
5781  assert(m_value.object != nullptr);
5782 
5783  if (m_value.object->empty())
5784  {
5785  o << "{}";
5786  return;
5787  }
5788 
5789  o << "{";
5790 
5791  // increase indentation
5792  if (pretty_print)
5793  {
5794  new_indent += indent_step;
5795  o << "\n";
5796  }
5797 
5798  for (auto i = m_value.object->cbegin(); i != m_value.object->cend(); ++i)
5799  {
5800  if (i != m_value.object->cbegin())
5801  {
5802  o << (pretty_print ? ",\n" : ",");
5803  }
5804  o << string_t(new_indent, ' ') << "\""
5805  << escape_string(i->first) << "\":"
5806  << (pretty_print ? " " : "");
5807  i->second.dump(o, pretty_print, indent_step, new_indent);
5808  }
5809 
5810  // decrease indentation
5811  if (pretty_print)
5812  {
5813  new_indent -= indent_step;
5814  o << "\n";
5815  }
5816 
5817  o << string_t(new_indent, ' ') + "}";
5818  return;
5819  }
5820 
5821  case value_t::array:
5822  {
5823  assert(m_value.array != nullptr);
5824 
5825  if (m_value.array->empty())
5826  {
5827  o << "[]";
5828  return;
5829  }
5830 
5831  o << "[";
5832 
5833  // increase indentation
5834  if (pretty_print)
5835  {
5836  new_indent += indent_step;
5837  o << "\n";
5838  }
5839 
5840  for (auto i = m_value.array->cbegin(); i != m_value.array->cend(); ++i)
5841  {
5842  if (i != m_value.array->cbegin())
5843  {
5844  o << (pretty_print ? ",\n" : ",");
5845  }
5846  o << string_t(new_indent, ' ');
5847  i->dump(o, pretty_print, indent_step, new_indent);
5848  }
5849 
5850  // decrease indentation
5851  if (pretty_print)
5852  {
5853  new_indent -= indent_step;
5854  o << "\n";
5855  }
5856 
5857  o << string_t(new_indent, ' ') << "]";
5858  return;
5859  }
5860 
5861  case value_t::string:
5862  {
5863  assert(m_value.string != nullptr);
5864  o << string_t("\"") << escape_string(*m_value.string) << "\"";
5865  return;
5866  }
5867 
5868  case value_t::boolean:
5869  {
5870  o << (m_value.boolean ? "true" : "false");
5871  return;
5872  }
5873 
5874  case value_t::number_integer:
5875  {
5876  o << m_value.number_integer;
5877  return;
5878  }
5879 
5880  case value_t::number_unsigned:
5881  {
5882  o << m_value.number_unsigned;
5883  return;
5884  }
5885 
5886  case value_t::number_float:
5887  {
5888  // If the number is an integer then output as a fixed with with
5889  // precision 1 to output "0.0", "1.0" etc as expected for some
5890  // round trip tests otherwise 15 digits of precision allows
5891  // round-trip IEEE 754 string->double->string; to be safe, we
5892  // read this value from
5893  // std::numeric_limits<number_float_t>::digits10
5894  if (std::fmod(m_value.number_float, 1) == 0)
5895  {
5896  o << std::fixed << std::setprecision(1);
5897  }
5898  else
5899  {
5900  // std::defaultfloat not supported in gcc version < 5
5901  o.unsetf(std::ios_base::floatfield);
5902  o << std::setprecision(std::numeric_limits<double>::digits10);
5903  }
5904  o << m_value.number_float;
5905  return;
5906  }
5907 
5908  case value_t::discarded:
5909  {
5910  o << "<discarded>";
5911  return;
5912  }
5913 
5914  case value_t::null:
5915  {
5916  o << "null";
5917  return;
5918  }
5919  }
5920  }
5921 
5922  private:
5924  // member variables //
5926 
5928  value_t m_type = value_t::null;
5929 
5931  json_value m_value = {};
5932 
5933 
5934  private:
5936  // iterators //
5938 
5948  class primitive_iterator_t
5949  {
5950  public:
5952  void set_begin()
5953  {
5954  m_it = begin_value;
5955  }
5956 
5958  void set_end()
5959  {
5960  m_it = end_value;
5961  }
5962 
5964  bool is_begin() const
5965  {
5966  return (m_it == begin_value);
5967  }
5968 
5970  bool is_end() const
5971  {
5972  return (m_it == end_value);
5973  }
5974 
5976  operator difference_type& ()
5977  {
5978  return m_it;
5979  }
5980 
5982  operator difference_type () const
5983  {
5984  return m_it;
5985  }
5986 
5987  private:
5988  static constexpr difference_type begin_value = 0;
5989  static constexpr difference_type end_value = begin_value + 1;
5990 
5992  difference_type m_it = std::numeric_limits<std::ptrdiff_t>::denorm_min();
5993  };
5994 
6002  struct internal_iterator
6003  {
6005  typename object_t::iterator object_iterator;
6007  typename array_t::iterator array_iterator;
6009  primitive_iterator_t primitive_iterator;
6010 
6012  internal_iterator()
6013  : object_iterator(), array_iterator(), primitive_iterator()
6014  {}
6015  };
6016 
6018  template<typename IteratorType>
6019  class iteration_proxy
6020  {
6021  private:
6023  class iteration_proxy_internal
6024  {
6025  private:
6027  IteratorType anchor;
6029  size_t array_index = 0;
6030 
6031  public:
6032  iteration_proxy_internal(IteratorType it)
6033  : anchor(it)
6034  {}
6035 
6037  iteration_proxy_internal& operator*()
6038  {
6039  return *this;
6040  }
6041 
6043  iteration_proxy_internal& operator++()
6044  {
6045  ++anchor;
6046  ++array_index;
6047 
6048  return *this;
6049  }
6050 
6052  bool operator!= (const iteration_proxy_internal& o) const
6053  {
6054  return anchor != o.anchor;
6055  }
6056 
6058  typename basic_json::string_t key() const
6059  {
6060  assert(anchor.m_object != nullptr);
6061 
6062  switch (anchor.m_object->type())
6063  {
6064  // use integer array index as key
6065  case value_t::array:
6066  {
6067  return std::to_string(array_index);
6068  }
6069 
6070  // use key from the object
6071  case value_t::object:
6072  {
6073  return anchor.key();
6074  }
6075 
6076  // use an empty key for all primitive types
6077  default:
6078  {
6079  return "";
6080  }
6081  }
6082  }
6083 
6085  typename IteratorType::reference value() const
6086  {
6087  return anchor.value();
6088  }
6089  };
6090 
6092  typename IteratorType::reference container;
6093 
6094  public:
6096  iteration_proxy(typename IteratorType::reference cont)
6097  : container(cont)
6098  {}
6099 
6101  iteration_proxy_internal begin()
6102  {
6103  return iteration_proxy_internal(container.begin());
6104  }
6105 
6107  iteration_proxy_internal end()
6108  {
6109  return iteration_proxy_internal(container.end());
6110  }
6111  };
6112 
6113  public:
6127  class const_iterator : public std::iterator<std::random_access_iterator_tag, const basic_json>
6128  {
6130  friend class basic_json;
6131 
6132  public:
6142  using iterator_category = std::bidirectional_iterator_tag;
6143 
6145  const_iterator() = default;
6146 
6148  const_iterator(pointer object) : m_object(object)
6149  {
6150  assert(m_object != nullptr);
6151 
6152  switch (m_object->m_type)
6153  {
6155  {
6156  m_it.object_iterator = typename object_t::iterator();
6157  break;
6158  }
6159 
6161  {
6162  m_it.array_iterator = typename array_t::iterator();
6163  break;
6164  }
6165 
6166  default:
6167  {
6168  m_it.primitive_iterator = primitive_iterator_t();
6169  break;
6170  }
6171  }
6172  }
6173 
6175  const_iterator(const iterator& other) : m_object(other.m_object)
6176  {
6177  assert(m_object != nullptr);
6178 
6179  switch (m_object->m_type)
6180  {
6182  {
6183  m_it.object_iterator = other.m_it.object_iterator;
6184  break;
6185  }
6186 
6188  {
6189  m_it.array_iterator = other.m_it.array_iterator;
6190  break;
6191  }
6192 
6193  default:
6194  {
6195  m_it.primitive_iterator = other.m_it.primitive_iterator;
6196  break;
6197  }
6198  }
6199  }
6200 
6202  const_iterator(const const_iterator& other) noexcept
6203  : m_object(other.m_object), m_it(other.m_it)
6204  {}
6205 
6208  std::is_nothrow_move_constructible<pointer>::value and
6209  std::is_nothrow_move_assignable<pointer>::value and
6210  std::is_nothrow_move_constructible<internal_iterator>::value and
6211  std::is_nothrow_move_assignable<internal_iterator>::value
6212  )
6213  {
6214  std::swap(m_object, other.m_object);
6215  std::swap(m_it, other.m_it);
6216  return *this;
6217  }
6218 
6219  private:
6221  void set_begin()
6222  {
6223  assert(m_object != nullptr);
6224 
6225  switch (m_object->m_type)
6226  {
6228  {
6229  assert(m_object->m_value.object != nullptr);
6230  m_it.object_iterator = m_object->m_value.object->begin();
6231  break;
6232  }
6233 
6235  {
6236  assert(m_object->m_value.array != nullptr);
6237  m_it.array_iterator = m_object->m_value.array->begin();
6238  break;
6239  }
6240 
6242  {
6243  // set to end so begin()==end() is true: null is empty
6244  m_it.primitive_iterator.set_end();
6245  break;
6246  }
6247 
6248  default:
6249  {
6250  m_it.primitive_iterator.set_begin();
6251  break;
6252  }
6253  }
6254  }
6255 
6257  void set_end()
6258  {
6259  assert(m_object != nullptr);
6260 
6261  switch (m_object->m_type)
6262  {
6264  {
6265  assert(m_object->m_value.object != nullptr);
6266  m_it.object_iterator = m_object->m_value.object->end();
6267  break;
6268  }
6269 
6271  {
6272  assert(m_object->m_value.array != nullptr);
6273  m_it.array_iterator = m_object->m_value.array->end();
6274  break;
6275  }
6276 
6277  default:
6278  {
6279  m_it.primitive_iterator.set_end();
6280  break;
6281  }
6282  }
6283  }
6284 
6285  public:
6288  {
6289  assert(m_object != nullptr);
6290 
6291  switch (m_object->m_type)
6292  {
6294  {
6295  assert(m_object->m_value.object);
6296  assert(m_it.object_iterator != m_object->m_value.object->end());
6297  return m_it.object_iterator->second;
6298  }
6299 
6301  {
6302  assert(m_object->m_value.array);
6303  assert(m_it.array_iterator != m_object->m_value.array->end());
6304  return *m_it.array_iterator;
6305  }
6306 
6308  {
6309  throw std::out_of_range("cannot get value");
6310  }
6311 
6312  default:
6313  {
6314  if (m_it.primitive_iterator.is_begin())
6315  {
6316  return *m_object;
6317  }
6318  else
6319  {
6320  throw std::out_of_range("cannot get value");
6321  }
6322  }
6323  }
6324  }
6325 
6328  {
6329  assert(m_object != nullptr);
6330 
6331  switch (m_object->m_type)
6332  {
6334  {
6335  assert(m_object->m_value.object);
6336  assert(m_it.object_iterator != m_object->m_value.object->end());
6337  return &(m_it.object_iterator->second);
6338  }
6339 
6341  {
6342  assert(m_object->m_value.array);
6343  assert(m_it.array_iterator != m_object->m_value.array->end());
6344  return &*m_it.array_iterator;
6345  }
6346 
6347  default:
6348  {
6349  if (m_it.primitive_iterator.is_begin())
6350  {
6351  return m_object;
6352  }
6353  else
6354  {
6355  throw std::out_of_range("cannot get value");
6356  }
6357  }
6358  }
6359  }
6360 
6363  {
6364  auto result = *this;
6365  ++(*this);
6366  return result;
6367  }
6368 
6371  {
6372  assert(m_object != nullptr);
6373 
6374  switch (m_object->m_type)
6375  {
6377  {
6378  ++m_it.object_iterator;
6379  break;
6380  }
6381 
6383  {
6384  ++m_it.array_iterator;
6385  break;
6386  }
6387 
6388  default:
6389  {
6390  ++m_it.primitive_iterator;
6391  break;
6392  }
6393  }
6394 
6395  return *this;
6396  }
6397 
6400  {
6401  auto result = *this;
6402  --(*this);
6403  return result;
6404  }
6405 
6408  {
6409  assert(m_object != nullptr);
6410 
6411  switch (m_object->m_type)
6412  {
6414  {
6415  --m_it.object_iterator;
6416  break;
6417  }
6418 
6420  {
6421  --m_it.array_iterator;
6422  break;
6423  }
6424 
6425  default:
6426  {
6427  --m_it.primitive_iterator;
6428  break;
6429  }
6430  }
6431 
6432  return *this;
6433  }
6434 
6436  bool operator==(const const_iterator& other) const
6437  {
6438  // if objects are not the same, the comparison is undefined
6439  if (m_object != other.m_object)
6440  {
6441  throw std::domain_error("cannot compare iterators of different containers");
6442  }
6443 
6444  assert(m_object != nullptr);
6445 
6446  switch (m_object->m_type)
6447  {
6449  {
6450  return (m_it.object_iterator == other.m_it.object_iterator);
6451  }
6452 
6454  {
6455  return (m_it.array_iterator == other.m_it.array_iterator);
6456  }
6457 
6458  default:
6459  {
6460  return (m_it.primitive_iterator == other.m_it.primitive_iterator);
6461  }
6462  }
6463  }
6464 
6466  bool operator!=(const const_iterator& other) const
6467  {
6468  return not operator==(other);
6469  }
6470 
6472  bool operator<(const const_iterator& other) const
6473  {
6474  // if objects are not the same, the comparison is undefined
6475  if (m_object != other.m_object)
6476  {
6477  throw std::domain_error("cannot compare iterators of different containers");
6478  }
6479 
6480  assert(m_object != nullptr);
6481 
6482  switch (m_object->m_type)
6483  {
6485  {
6486  throw std::domain_error("cannot compare order of object iterators");
6487  }
6488 
6490  {
6491  return (m_it.array_iterator < other.m_it.array_iterator);
6492  }
6493 
6494  default:
6495  {
6496  return (m_it.primitive_iterator < other.m_it.primitive_iterator);
6497  }
6498  }
6499  }
6500 
6502  bool operator<=(const const_iterator& other) const
6503  {
6504  return not other.operator < (*this);
6505  }
6506 
6508  bool operator>(const const_iterator& other) const
6509  {
6510  return not operator<=(other);
6511  }
6512 
6514  bool operator>=(const const_iterator& other) const
6515  {
6516  return not operator<(other);
6517  }
6518 
6521  {
6522  assert(m_object != nullptr);
6523 
6524  switch (m_object->m_type)
6525  {
6527  {
6528  throw std::domain_error("cannot use offsets with object iterators");
6529  }
6530 
6532  {
6533  m_it.array_iterator += i;
6534  break;
6535  }
6536 
6537  default:
6538  {
6539  m_it.primitive_iterator += i;
6540  break;
6541  }
6542  }
6543 
6544  return *this;
6545  }
6546 
6549  {
6550  return operator+=(-i);
6551  }
6552 
6555  {
6556  auto result = *this;
6557  result += i;
6558  return result;
6559  }
6560 
6563  {
6564  auto result = *this;
6565  result -= i;
6566  return result;
6567  }
6568 
6571  {
6572  assert(m_object != nullptr);
6573 
6574  switch (m_object->m_type)
6575  {
6577  {
6578  throw std::domain_error("cannot use offsets with object iterators");
6579  }
6580 
6582  {
6583  return m_it.array_iterator - other.m_it.array_iterator;
6584  }
6585 
6586  default:
6587  {
6588  return m_it.primitive_iterator - other.m_it.primitive_iterator;
6589  }
6590  }
6591  }
6592 
6595  {
6596  assert(m_object != nullptr);
6597 
6598  switch (m_object->m_type)
6599  {
6601  {
6602  throw std::domain_error("cannot use operator[] for object iterators");
6603  }
6604 
6606  {
6607  return *(m_it.array_iterator + n);
6608  }
6609 
6611  {
6612  throw std::out_of_range("cannot get value");
6613  }
6614 
6615  default:
6616  {
6617  if (m_it.primitive_iterator == -n)
6618  {
6619  return *m_object;
6620  }
6621  else
6622  {
6623  throw std::out_of_range("cannot get value");
6624  }
6625  }
6626  }
6627  }
6628 
6630  typename object_t::key_type key() const
6631  {
6632  assert(m_object != nullptr);
6633 
6634  if (m_object->is_object())
6635  {
6636  return m_it.object_iterator->first;
6637  }
6638  else
6639  {
6640  throw std::domain_error("cannot use key() for non-object iterators");
6641  }
6642  }
6643 
6646  {
6647  return operator*();
6648  }
6649 
6650  private:
6652  pointer m_object = nullptr;
6654  internal_iterator m_it = internal_iterator();
6655  };
6656 
6669  class iterator : public const_iterator
6670  {
6671  public:
6673  using pointer = typename basic_json::pointer;
6675 
6677  iterator() = default;
6678 
6680  iterator(pointer object) noexcept
6681  : base_iterator(object)
6682  {}
6683 
6685  iterator(const iterator& other) noexcept
6686  : base_iterator(other)
6687  {}
6688 
6690  iterator& operator=(iterator other) noexcept(
6691  std::is_nothrow_move_constructible<pointer>::value and
6692  std::is_nothrow_move_assignable<pointer>::value and
6693  std::is_nothrow_move_constructible<internal_iterator>::value and
6694  std::is_nothrow_move_assignable<internal_iterator>::value
6695  )
6696  {
6697  base_iterator::operator=(other);
6698  return *this;
6699  }
6700 
6703  {
6704  return const_cast<reference>(base_iterator::operator*());
6705  }
6706 
6709  {
6710  return const_cast<pointer>(base_iterator::operator->());
6711  }
6712 
6715  {
6716  iterator result = *this;
6717  base_iterator::operator++();
6718  return result;
6719  }
6720 
6723  {
6724  base_iterator::operator++();
6725  return *this;
6726  }
6727 
6730  {
6731  iterator result = *this;
6732  base_iterator::operator--();
6733  return result;
6734  }
6735 
6738  {
6739  base_iterator::operator--();
6740  return *this;
6741  }
6742 
6745  {
6746  base_iterator::operator+=(i);
6747  return *this;
6748  }
6749 
6752  {
6753  base_iterator::operator-=(i);
6754  return *this;
6755  }
6756 
6759  {
6760  auto result = *this;
6761  result += i;
6762  return result;
6763  }
6764 
6767  {
6768  auto result = *this;
6769  result -= i;
6770  return result;
6771  }
6772 
6773  difference_type operator-(const iterator& other) const
6774  {
6775  return base_iterator::operator-(other);
6776  }
6777 
6780  {
6781  return const_cast<reference>(base_iterator::operator[](n));
6782  }
6783 
6786  {
6787  return const_cast<reference>(base_iterator::value());
6788  }
6789  };
6790 
6808  template<typename Base>
6809  class json_reverse_iterator : public std::reverse_iterator<Base>
6810  {
6811  public:
6813  using base_iterator = std::reverse_iterator<Base>;
6815  using reference = typename Base::reference;
6816 
6818  json_reverse_iterator(const typename base_iterator::iterator_type& it)
6819  : base_iterator(it)
6820  {}
6821 
6824  : base_iterator(it)
6825  {}
6826 
6829  {
6830  return base_iterator::operator++(1);
6831  }
6832 
6835  {
6836  base_iterator::operator++();
6837  return *this;
6838  }
6839 
6842  {
6843  return base_iterator::operator--(1);
6844  }
6845 
6848  {
6849  base_iterator::operator--();
6850  return *this;
6851  }
6852 
6855  {
6856  base_iterator::operator+=(i);
6857  return *this;
6858  }
6859 
6862  {
6863  auto result = *this;
6864  result += i;
6865  return result;
6866  }
6867 
6870  {
6871  auto result = *this;
6872  result -= i;
6873  return result;
6874  }
6875 
6878  {
6879  return this->base() - other.base();
6880  }
6881 
6884  {
6885  return *(this->operator+(n));
6886  }
6887 
6889  typename object_t::key_type key() const
6890  {
6891  auto it = --this->base();
6892  return it.key();
6893  }
6894 
6897  {
6898  auto it = --this->base();
6899  return it.operator * ();
6900  }
6901  };
6902 
6903 
6904  private:
6906  // lexer and parser //
6908 
6916  class lexer
6917  {
6918  public:
6920  enum class token_type
6921  {
6922  uninitialized,
6923  literal_true,
6924  literal_false,
6925  literal_null,
6926  value_string,
6927  value_number,
6928  begin_array,
6929  begin_object,
6930  end_array,
6931  end_object,
6932  name_separator,
6933  value_separator,
6934  parse_error,
6935  end_of_input
6936  };
6937 
6939  using lexer_char_t = unsigned char;
6940 
6942  explicit lexer(const string_t& s) noexcept
6943  : m_stream(nullptr), m_buffer(s)
6944  {
6945  m_content = reinterpret_cast<const lexer_char_t*>(s.c_str());
6946  assert(m_content != nullptr);
6947  m_start = m_cursor = m_content;
6948  m_limit = m_content + s.size();
6949  }
6950 
6952  explicit lexer(std::istream* s) noexcept
6953  : m_stream(s), m_buffer()
6954  {
6955  assert(m_stream != nullptr);
6956  getline(*m_stream, m_buffer);
6957  m_content = reinterpret_cast<const lexer_char_t*>(m_buffer.c_str());
6958  assert(m_content != nullptr);
6959  m_start = m_cursor = m_content;
6960  m_limit = m_content + m_buffer.size();
6961  }
6962 
6964  lexer() = default;
6965 
6966  // switch off unwanted functions
6967  lexer(const lexer&) = delete;
6968  lexer operator=(const lexer&) = delete;
6969 
6985  static string_t to_unicode(const std::size_t codepoint1,
6986  const std::size_t codepoint2 = 0)
6987  {
6988  string_t result;
6989 
6990  // calculate the codepoint from the given code points
6991  std::size_t codepoint = codepoint1;
6992 
6993  // check if codepoint1 is a high surrogate
6994  if (codepoint1 >= 0xD800 and codepoint1 <= 0xDBFF)
6995  {
6996  // check if codepoint2 is a low surrogate
6997  if (codepoint2 >= 0xDC00 and codepoint2 <= 0xDFFF)
6998  {
6999  codepoint =
7000  // high surrogate occupies the most significant 22 bits
7001  (codepoint1 << 10)
7002  // low surrogate occupies the least significant 15 bits
7003  + codepoint2
7004  // there is still the 0xD800, 0xDC00 and 0x10000 noise
7005  // in the result so we have to subtract with:
7006  // (0xD800 << 10) + DC00 - 0x10000 = 0x35FDC00
7007  - 0x35FDC00;
7008  }
7009  else
7010  {
7011  throw std::invalid_argument("missing or wrong low surrogate");
7012  }
7013  }
7014 
7015  if (codepoint < 0x80)
7016  {
7017  // 1-byte characters: 0xxxxxxx (ASCII)
7018  result.append(1, static_cast<typename string_t::value_type>(codepoint));
7019  }
7020  else if (codepoint <= 0x7ff)
7021  {
7022  // 2-byte characters: 110xxxxx 10xxxxxx
7023  result.append(1, static_cast<typename string_t::value_type>(0xC0 | ((codepoint >> 6) & 0x1F)));
7024  result.append(1, static_cast<typename string_t::value_type>(0x80 | (codepoint & 0x3F)));
7025  }
7026  else if (codepoint <= 0xffff)
7027  {
7028  // 3-byte characters: 1110xxxx 10xxxxxx 10xxxxxx
7029  result.append(1, static_cast<typename string_t::value_type>(0xE0 | ((codepoint >> 12) & 0x0F)));
7030  result.append(1, static_cast<typename string_t::value_type>(0x80 | ((codepoint >> 6) & 0x3F)));
7031  result.append(1, static_cast<typename string_t::value_type>(0x80 | (codepoint & 0x3F)));
7032  }
7033  else if (codepoint <= 0x10ffff)
7034  {
7035  // 4-byte characters: 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
7036  result.append(1, static_cast<typename string_t::value_type>(0xF0 | ((codepoint >> 18) & 0x07)));
7037  result.append(1, static_cast<typename string_t::value_type>(0x80 | ((codepoint >> 12) & 0x3F)));
7038  result.append(1, static_cast<typename string_t::value_type>(0x80 | ((codepoint >> 6) & 0x3F)));
7039  result.append(1, static_cast<typename string_t::value_type>(0x80 | (codepoint & 0x3F)));
7040  }
7041  else
7042  {
7043  throw std::out_of_range("code points above 0x10FFFF are invalid");
7044  }
7045 
7046  return result;
7047  }
7048 
7050  static std::string token_type_name(token_type t)
7051  {
7052  switch (t)
7053  {
7054  case token_type::uninitialized:
7055  return "<uninitialized>";
7056  case token_type::literal_true:
7057  return "true literal";
7058  case token_type::literal_false:
7059  return "false literal";
7060  case token_type::literal_null:
7061  return "null literal";
7062  case token_type::value_string:
7063  return "string literal";
7064  case token_type::value_number:
7065  return "number literal";
7066  case token_type::begin_array:
7067  return "'['";
7068  case token_type::begin_object:
7069  return "'{'";
7070  case token_type::end_array:
7071  return "']'";
7072  case token_type::end_object:
7073  return "'}'";
7074  case token_type::name_separator:
7075  return "':'";
7076  case token_type::value_separator:
7077  return "','";
7078  case token_type::parse_error:
7079  return "<parse error>";
7080  case token_type::end_of_input:
7081  return "end of input";
7082  default:
7083  {
7084  // catch non-enum values
7085  return "unknown token"; // LCOV_EXCL_LINE
7086  }
7087  }
7088  }
7089 
7100  token_type scan() noexcept
7101  {
7102  // pointer for backtracking information
7103  m_marker = nullptr;
7104 
7105  // remember the begin of the token
7106  m_start = m_cursor;
7107  assert(m_start != nullptr);
7108 
7109 
7110  {
7111  lexer_char_t yych;
7112  unsigned int yyaccept = 0;
7113  static const unsigned char yybm[] =
7114  {
7115  0, 0, 0, 0, 0, 0, 0, 0,
7116  0, 32, 32, 0, 0, 32, 0, 0,
7117  64, 64, 64, 64, 64, 64, 64, 64,
7118  64, 64, 64, 64, 64, 64, 64, 64,
7119  96, 64, 0, 64, 64, 64, 64, 64,
7120  64, 64, 64, 64, 64, 64, 64, 64,
7121  192, 192, 192, 192, 192, 192, 192, 192,
7122  192, 192, 64, 64, 64, 64, 64, 64,
7123  64, 64, 64, 64, 64, 64, 64, 64,
7124  64, 64, 64, 64, 64, 64, 64, 64,
7125  64, 64, 64, 64, 64, 64, 64, 64,
7126  64, 64, 64, 64, 0, 64, 64, 64,
7127  64, 64, 64, 64, 64, 64, 64, 64,
7128  64, 64, 64, 64, 64, 64, 64, 64,
7129  64, 64, 64, 64, 64, 64, 64, 64,
7130  64, 64, 64, 64, 64, 64, 64, 64,
7131  64, 64, 64, 64, 64, 64, 64, 64,
7132  64, 64, 64, 64, 64, 64, 64, 64,
7133  64, 64, 64, 64, 64, 64, 64, 64,
7134  64, 64, 64, 64, 64, 64, 64, 64,
7135  64, 64, 64, 64, 64, 64, 64, 64,
7136  64, 64, 64, 64, 64, 64, 64, 64,
7137  64, 64, 64, 64, 64, 64, 64, 64,
7138  64, 64, 64, 64, 64, 64, 64, 64,
7139  64, 64, 64, 64, 64, 64, 64, 64,
7140  64, 64, 64, 64, 64, 64, 64, 64,
7141  64, 64, 64, 64, 64, 64, 64, 64,
7142  64, 64, 64, 64, 64, 64, 64, 64,
7143  64, 64, 64, 64, 64, 64, 64, 64,
7144  64, 64, 64, 64, 64, 64, 64, 64,
7145  64, 64, 64, 64, 64, 64, 64, 64,
7146  64, 64, 64, 64, 64, 64, 64, 64,
7147  };
7148  if ((m_limit - m_cursor) < 5)
7149  {
7150  yyfill(); // LCOV_EXCL_LINE;
7151  }
7152  yych = *m_cursor;
7153  if (yych <= ':')
7154  {
7155  if (yych <= ' ')
7156  {
7157  if (yych <= '\n')
7158  {
7159  if (yych <= 0x00)
7160  {
7161  goto basic_json_parser_28;
7162  }
7163  if (yych <= 0x08)
7164  {
7165  goto basic_json_parser_30;
7166  }
7167  if (yych >= '\n')
7168  {
7169  goto basic_json_parser_4;
7170  }
7171  }
7172  else
7173  {
7174  if (yych == '\r')
7175  {
7176  goto basic_json_parser_2;
7177  }
7178  if (yych <= 0x1F)
7179  {
7180  goto basic_json_parser_30;
7181  }
7182  }
7183  }
7184  else
7185  {
7186  if (yych <= ',')
7187  {
7188  if (yych == '"')
7189  {
7190  goto basic_json_parser_27;
7191  }
7192  if (yych <= '+')
7193  {
7194  goto basic_json_parser_30;
7195  }
7196  goto basic_json_parser_16;
7197  }
7198  else
7199  {
7200  if (yych <= '/')
7201  {
7202  if (yych <= '-')
7203  {
7204  goto basic_json_parser_23;
7205  }
7206  goto basic_json_parser_30;
7207  }
7208  else
7209  {
7210  if (yych <= '0')
7211  {
7212  goto basic_json_parser_24;
7213  }
7214  if (yych <= '9')
7215  {
7216  goto basic_json_parser_26;
7217  }
7218  goto basic_json_parser_18;
7219  }
7220  }
7221  }
7222  }
7223  else
7224  {
7225  if (yych <= 'n')
7226  {
7227  if (yych <= ']')
7228  {
7229  if (yych == '[')
7230  {
7231  goto basic_json_parser_8;
7232  }
7233  if (yych <= '\\')
7234  {
7235  goto basic_json_parser_30;
7236  }
7237  goto basic_json_parser_10;
7238  }
7239  else
7240  {
7241  if (yych == 'f')
7242  {
7243  goto basic_json_parser_22;
7244  }
7245  if (yych <= 'm')
7246  {
7247  goto basic_json_parser_30;
7248  }
7249  goto basic_json_parser_20;
7250  }
7251  }
7252  else
7253  {
7254  if (yych <= '{')
7255  {
7256  if (yych == 't')
7257  {
7258  goto basic_json_parser_21;
7259  }
7260  if (yych <= 'z')
7261  {
7262  goto basic_json_parser_30;
7263  }
7264  goto basic_json_parser_12;
7265  }
7266  else
7267  {
7268  if (yych <= '}')
7269  {
7270  if (yych <= '|')
7271  {
7272  goto basic_json_parser_30;
7273  }
7274  goto basic_json_parser_14;
7275  }
7276  else
7277  {
7278  if (yych == 0xEF)
7279  {
7280  goto basic_json_parser_6;
7281  }
7282  goto basic_json_parser_30;
7283  }
7284  }
7285  }
7286  }
7287 basic_json_parser_2:
7288  ++m_cursor;
7289  yych = *m_cursor;
7290  goto basic_json_parser_5;
7291 basic_json_parser_3:
7292  {
7293  return scan();
7294  }
7295 basic_json_parser_4:
7296  ++m_cursor;
7297  if (m_limit <= m_cursor)
7298  {
7299  yyfill(); // LCOV_EXCL_LINE;
7300  }
7301  yych = *m_cursor;
7302 basic_json_parser_5:
7303  if (yybm[0 + yych] & 32)
7304  {
7305  goto basic_json_parser_4;
7306  }
7307  goto basic_json_parser_3;
7308 basic_json_parser_6:
7309  yyaccept = 0;
7310  yych = *(m_marker = ++m_cursor);
7311  if (yych == 0xBB)
7312  {
7313  goto basic_json_parser_64;
7314  }
7315 basic_json_parser_7:
7316  {
7317  return token_type::parse_error;
7318  }
7319 basic_json_parser_8:
7320  ++m_cursor;
7321  {
7322  return token_type::begin_array;
7323  }
7324 basic_json_parser_10:
7325  ++m_cursor;
7326  {
7327  return token_type::end_array;
7328  }
7329 basic_json_parser_12:
7330  ++m_cursor;
7331  {
7332  return token_type::begin_object;
7333  }
7334 basic_json_parser_14:
7335  ++m_cursor;
7336  {
7337  return token_type::end_object;
7338  }
7339 basic_json_parser_16:
7340  ++m_cursor;
7341  {
7342  return token_type::value_separator;
7343  }
7344 basic_json_parser_18:
7345  ++m_cursor;
7346  {
7347  return token_type::name_separator;
7348  }
7349 basic_json_parser_20:
7350  yyaccept = 0;
7351  yych = *(m_marker = ++m_cursor);
7352  if (yych == 'u')
7353  {
7354  goto basic_json_parser_60;
7355  }
7356  goto basic_json_parser_7;
7357 basic_json_parser_21:
7358  yyaccept = 0;
7359  yych = *(m_marker = ++m_cursor);
7360  if (yych == 'r')
7361  {
7362  goto basic_json_parser_56;
7363  }
7364  goto basic_json_parser_7;
7365 basic_json_parser_22:
7366  yyaccept = 0;
7367  yych = *(m_marker = ++m_cursor);
7368  if (yych == 'a')
7369  {
7370  goto basic_json_parser_51;
7371  }
7372  goto basic_json_parser_7;
7373 basic_json_parser_23:
7374  yych = *++m_cursor;
7375  if (yych <= '/')
7376  {
7377  goto basic_json_parser_7;
7378  }
7379  if (yych <= '0')
7380  {
7381  goto basic_json_parser_50;
7382  }
7383  if (yych <= '9')
7384  {
7385  goto basic_json_parser_41;
7386  }
7387  goto basic_json_parser_7;
7388 basic_json_parser_24:
7389  yyaccept = 1;
7390  yych = *(m_marker = ++m_cursor);
7391  if (yych <= 'D')
7392  {
7393  if (yych == '.')
7394  {
7395  goto basic_json_parser_43;
7396  }
7397  }
7398  else
7399  {
7400  if (yych <= 'E')
7401  {
7402  goto basic_json_parser_44;
7403  }
7404  if (yych == 'e')
7405  {
7406  goto basic_json_parser_44;
7407  }
7408  }
7409 basic_json_parser_25:
7410  {
7411  return token_type::value_number;
7412  }
7413 basic_json_parser_26:
7414  yyaccept = 1;
7415  yych = *(m_marker = ++m_cursor);
7416  goto basic_json_parser_42;
7417 basic_json_parser_27:
7418  yyaccept = 0;
7419  yych = *(m_marker = ++m_cursor);
7420  if (yych <= 0x0F)
7421  {
7422  goto basic_json_parser_7;
7423  }
7424  goto basic_json_parser_32;
7425 basic_json_parser_28:
7426  ++m_cursor;
7427  {
7428  return token_type::end_of_input;
7429  }
7430 basic_json_parser_30:
7431  yych = *++m_cursor;
7432  goto basic_json_parser_7;
7433 basic_json_parser_31:
7434  ++m_cursor;
7435  if (m_limit <= m_cursor)
7436  {
7437  yyfill(); // LCOV_EXCL_LINE;
7438  }
7439  yych = *m_cursor;
7440 basic_json_parser_32:
7441  if (yybm[0 + yych] & 64)
7442  {
7443  goto basic_json_parser_31;
7444  }
7445  if (yych <= 0x0F)
7446  {
7447  goto basic_json_parser_33;
7448  }
7449  if (yych <= '"')
7450  {
7451  goto basic_json_parser_35;
7452  }
7453  goto basic_json_parser_34;
7454 basic_json_parser_33:
7455  m_cursor = m_marker;
7456  if (yyaccept == 0)
7457  {
7458  goto basic_json_parser_7;
7459  }
7460  else
7461  {
7462  goto basic_json_parser_25;
7463  }
7464 basic_json_parser_34:
7465  ++m_cursor;
7466  if (m_limit <= m_cursor)
7467  {
7468  yyfill(); // LCOV_EXCL_LINE;
7469  }
7470  yych = *m_cursor;
7471  if (yych <= 'e')
7472  {
7473  if (yych <= '/')
7474  {
7475  if (yych == '"')
7476  {
7477  goto basic_json_parser_31;
7478  }
7479  if (yych <= '.')
7480  {
7481  goto basic_json_parser_33;
7482  }
7483  goto basic_json_parser_31;
7484  }
7485  else
7486  {
7487  if (yych <= '\\')
7488  {
7489  if (yych <= '[')
7490  {
7491  goto basic_json_parser_33;
7492  }
7493  goto basic_json_parser_31;
7494  }
7495  else
7496  {
7497  if (yych == 'b')
7498  {
7499  goto basic_json_parser_31;
7500  }
7501  goto basic_json_parser_33;
7502  }
7503  }
7504  }
7505  else
7506  {
7507  if (yych <= 'q')
7508  {
7509  if (yych <= 'f')
7510  {
7511  goto basic_json_parser_31;
7512  }
7513  if (yych == 'n')
7514  {
7515  goto basic_json_parser_31;
7516  }
7517  goto basic_json_parser_33;
7518  }
7519  else
7520  {
7521  if (yych <= 's')
7522  {
7523  if (yych <= 'r')
7524  {
7525  goto basic_json_parser_31;
7526  }
7527  goto basic_json_parser_33;
7528  }
7529  else
7530  {
7531  if (yych <= 't')
7532  {
7533  goto basic_json_parser_31;
7534  }
7535  if (yych <= 'u')
7536  {
7537  goto basic_json_parser_37;
7538  }
7539  goto basic_json_parser_33;
7540  }
7541  }
7542  }
7543 basic_json_parser_35:
7544  ++m_cursor;
7545  {
7546  return token_type::value_string;
7547  }
7548 basic_json_parser_37:
7549  ++m_cursor;
7550  if (m_limit <= m_cursor)
7551  {
7552  yyfill(); // LCOV_EXCL_LINE;
7553  }
7554  yych = *m_cursor;
7555  if (yych <= '@')
7556  {
7557  if (yych <= '/')
7558  {
7559  goto basic_json_parser_33;
7560  }
7561  if (yych >= ':')
7562  {
7563  goto basic_json_parser_33;
7564  }
7565  }
7566  else
7567  {
7568  if (yych <= 'F')
7569  {
7570  goto basic_json_parser_38;
7571  }
7572  if (yych <= '`')
7573  {
7574  goto basic_json_parser_33;
7575  }
7576  if (yych >= 'g')
7577  {
7578  goto basic_json_parser_33;
7579  }
7580  }
7581 basic_json_parser_38:
7582  ++m_cursor;
7583  if (m_limit <= m_cursor)
7584  {
7585  yyfill(); // LCOV_EXCL_LINE;
7586  }
7587  yych = *m_cursor;
7588  if (yych <= '@')
7589  {
7590  if (yych <= '/')
7591  {
7592  goto basic_json_parser_33;
7593  }
7594  if (yych >= ':')
7595  {
7596  goto basic_json_parser_33;
7597  }
7598  }
7599  else
7600  {
7601  if (yych <= 'F')
7602  {
7603  goto basic_json_parser_39;
7604  }
7605  if (yych <= '`')
7606  {
7607  goto basic_json_parser_33;
7608  }
7609  if (yych >= 'g')
7610  {
7611  goto basic_json_parser_33;
7612  }
7613  }
7614 basic_json_parser_39:
7615  ++m_cursor;
7616  if (m_limit <= m_cursor)
7617  {
7618  yyfill(); // LCOV_EXCL_LINE;
7619  }
7620  yych = *m_cursor;
7621  if (yych <= '@')
7622  {
7623  if (yych <= '/')
7624  {
7625  goto basic_json_parser_33;
7626  }
7627  if (yych >= ':')
7628  {
7629  goto basic_json_parser_33;
7630  }
7631  }
7632  else
7633  {
7634  if (yych <= 'F')
7635  {
7636  goto basic_json_parser_40;
7637  }
7638  if (yych <= '`')
7639  {
7640  goto basic_json_parser_33;
7641  }
7642  if (yych >= 'g')
7643  {
7644  goto basic_json_parser_33;
7645  }
7646  }
7647 basic_json_parser_40:
7648  ++m_cursor;
7649  if (m_limit <= m_cursor)
7650  {
7651  yyfill(); // LCOV_EXCL_LINE;
7652  }
7653  yych = *m_cursor;
7654  if (yych <= '@')
7655  {
7656  if (yych <= '/')
7657  {
7658  goto basic_json_parser_33;
7659  }
7660  if (yych <= '9')
7661  {
7662  goto basic_json_parser_31;
7663  }
7664  goto basic_json_parser_33;
7665  }
7666  else
7667  {
7668  if (yych <= 'F')
7669  {
7670  goto basic_json_parser_31;
7671  }
7672  if (yych <= '`')
7673  {
7674  goto basic_json_parser_33;
7675  }
7676  if (yych <= 'f')
7677  {
7678  goto basic_json_parser_31;
7679  }
7680  goto basic_json_parser_33;
7681  }
7682 basic_json_parser_41:
7683  yyaccept = 1;
7684  m_marker = ++m_cursor;
7685  if ((m_limit - m_cursor) < 3)
7686  {
7687  yyfill(); // LCOV_EXCL_LINE;
7688  }
7689  yych = *m_cursor;
7690 basic_json_parser_42:
7691  if (yybm[0 + yych] & 128)
7692  {
7693  goto basic_json_parser_41;
7694  }
7695  if (yych <= 'D')
7696  {
7697  if (yych != '.')
7698  {
7699  goto basic_json_parser_25;
7700  }
7701  }
7702  else
7703  {
7704  if (yych <= 'E')
7705  {
7706  goto basic_json_parser_44;
7707  }
7708  if (yych == 'e')
7709  {
7710  goto basic_json_parser_44;
7711  }
7712  goto basic_json_parser_25;
7713  }
7714 basic_json_parser_43:
7715  yych = *++m_cursor;
7716  if (yych <= '/')
7717  {
7718  goto basic_json_parser_33;
7719  }
7720  if (yych <= '9')
7721  {
7722  goto basic_json_parser_48;
7723  }
7724  goto basic_json_parser_33;
7725 basic_json_parser_44:
7726  yych = *++m_cursor;
7727  if (yych <= ',')
7728  {
7729  if (yych != '+')
7730  {
7731  goto basic_json_parser_33;
7732  }
7733  }
7734  else
7735  {
7736  if (yych <= '-')
7737  {
7738  goto basic_json_parser_45;
7739  }
7740  if (yych <= '/')
7741  {
7742  goto basic_json_parser_33;
7743  }
7744  if (yych <= '9')
7745  {
7746  goto basic_json_parser_46;
7747  }
7748  goto basic_json_parser_33;
7749  }
7750 basic_json_parser_45:
7751  yych = *++m_cursor;
7752  if (yych <= '/')
7753  {
7754  goto basic_json_parser_33;
7755  }
7756  if (yych >= ':')
7757  {
7758  goto basic_json_parser_33;
7759  }
7760 basic_json_parser_46:
7761  ++m_cursor;
7762  if (m_limit <= m_cursor)
7763  {
7764  yyfill(); // LCOV_EXCL_LINE;
7765  }
7766  yych = *m_cursor;
7767  if (yych <= '/')
7768  {
7769  goto basic_json_parser_25;
7770  }
7771  if (yych <= '9')
7772  {
7773  goto basic_json_parser_46;
7774  }
7775  goto basic_json_parser_25;
7776 basic_json_parser_48:
7777  yyaccept = 1;
7778  m_marker = ++m_cursor;
7779  if ((m_limit - m_cursor) < 3)
7780  {
7781  yyfill(); // LCOV_EXCL_LINE;
7782  }
7783  yych = *m_cursor;
7784  if (yych <= 'D')
7785  {
7786  if (yych <= '/')
7787  {
7788  goto basic_json_parser_25;
7789  }
7790  if (yych <= '9')
7791  {
7792  goto basic_json_parser_48;
7793  }
7794  goto basic_json_parser_25;
7795  }
7796  else
7797  {
7798  if (yych <= 'E')
7799  {
7800  goto basic_json_parser_44;
7801  }
7802  if (yych == 'e')
7803  {
7804  goto basic_json_parser_44;
7805  }
7806  goto basic_json_parser_25;
7807  }
7808 basic_json_parser_50:
7809  yyaccept = 1;
7810  yych = *(m_marker = ++m_cursor);
7811  if (yych <= 'D')
7812  {
7813  if (yych == '.')
7814  {
7815  goto basic_json_parser_43;
7816  }
7817  goto basic_json_parser_25;
7818  }
7819  else
7820  {
7821  if (yych <= 'E')
7822  {
7823  goto basic_json_parser_44;
7824  }
7825  if (yych == 'e')
7826  {
7827  goto basic_json_parser_44;
7828  }
7829  goto basic_json_parser_25;
7830  }
7831 basic_json_parser_51:
7832  yych = *++m_cursor;
7833  if (yych != 'l')
7834  {
7835  goto basic_json_parser_33;
7836  }
7837  yych = *++m_cursor;
7838  if (yych != 's')
7839  {
7840  goto basic_json_parser_33;
7841  }
7842  yych = *++m_cursor;
7843  if (yych != 'e')
7844  {
7845  goto basic_json_parser_33;
7846  }
7847  ++m_cursor;
7848  {
7849  return token_type::literal_false;
7850  }
7851 basic_json_parser_56:
7852  yych = *++m_cursor;
7853  if (yych != 'u')
7854  {
7855  goto basic_json_parser_33;
7856  }
7857  yych = *++m_cursor;
7858  if (yych != 'e')
7859  {
7860  goto basic_json_parser_33;
7861  }
7862  ++m_cursor;
7863  {
7864  return token_type::literal_true;
7865  }
7866 basic_json_parser_60:
7867  yych = *++m_cursor;
7868  if (yych != 'l')
7869  {
7870  goto basic_json_parser_33;
7871  }
7872  yych = *++m_cursor;
7873  if (yych != 'l')
7874  {
7875  goto basic_json_parser_33;
7876  }
7877  ++m_cursor;
7878  {
7879  return token_type::literal_null;
7880  }
7881 basic_json_parser_64:
7882  yych = *++m_cursor;
7883  if (yych != 0xBF)
7884  {
7885  goto basic_json_parser_33;
7886  }
7887  ++m_cursor;
7888  {
7889  return scan();
7890  }
7891  }
7892 
7893 
7894  }
7895 
7897  void yyfill() noexcept
7898  {
7899  if (m_stream == nullptr or not * m_stream)
7900  {
7901  return;
7902  }
7903 
7904  const ssize_t offset_start = m_start - m_content;
7905  const ssize_t offset_marker = m_marker - m_start;
7906  const ssize_t offset_cursor = m_cursor - m_start;
7907 
7908  m_buffer.erase(0, static_cast<size_t>(offset_start));
7909  std::string line;
7910  assert(m_stream != nullptr);
7911  std::getline(*m_stream, line);
7912  m_buffer += "\n" + line; // add line with newline symbol
7913 
7914  m_content = reinterpret_cast<const lexer_char_t*>(m_buffer.c_str());
7915  assert(m_content != nullptr);
7916  m_start = m_content;
7917  m_marker = m_start + offset_marker;
7918  m_cursor = m_start + offset_cursor;
7919  m_limit = m_start + m_buffer.size() - 1;
7920  }
7921 
7923  string_t get_token() const noexcept
7924  {
7925  assert(m_start != nullptr);
7926  return string_t(reinterpret_cast<typename string_t::const_pointer>(m_start),
7927  static_cast<size_t>(m_cursor - m_start));
7928  }
7929 
7951  string_t get_string() const
7952  {
7953  string_t result;
7954  result.reserve(static_cast<size_t>(m_cursor - m_start - 2));
7955 
7956  // iterate the result between the quotes
7957  for (const lexer_char_t* i = m_start + 1; i < m_cursor - 1; ++i)
7958  {
7959  // process escaped characters
7960  if (*i == '\\')
7961  {
7962  // read next character
7963  ++i;
7964 
7965  switch (*i)
7966  {
7967  // the default escapes
7968  case 't':
7969  {
7970  result += "\t";
7971  break;
7972  }
7973  case 'b':
7974  {
7975  result += "\b";
7976  break;
7977  }
7978  case 'f':
7979  {
7980  result += "\f";
7981  break;
7982  }
7983  case 'n':
7984  {
7985  result += "\n";
7986  break;
7987  }
7988  case 'r':
7989  {
7990  result += "\r";
7991  break;
7992  }
7993  case '\\':
7994  {
7995  result += "\\";
7996  break;
7997  }
7998  case '/':
7999  {
8000  result += "/";
8001  break;
8002  }
8003  case '"':
8004  {
8005  result += "\"";
8006  break;
8007  }
8008 
8009  // unicode
8010  case 'u':
8011  {
8012  // get code xxxx from uxxxx
8013  auto codepoint = std::strtoul(std::string(reinterpret_cast<typename string_t::const_pointer>(i + 1),
8014  4).c_str(), nullptr, 16);
8015 
8016  // check if codepoint is a high surrogate
8017  if (codepoint >= 0xD800 and codepoint <= 0xDBFF)
8018  {
8019  // make sure there is a subsequent unicode
8020  if ((i + 6 >= m_limit) or * (i + 5) != '\\' or * (i + 6) != 'u')
8021  {
8022  throw std::invalid_argument("missing low surrogate");
8023  }
8024 
8025  // get code yyyy from uxxxx\uyyyy
8026  auto codepoint2 = std::strtoul(std::string(reinterpret_cast<typename string_t::const_pointer>
8027  (i + 7), 4).c_str(), nullptr, 16);
8028  result += to_unicode(codepoint, codepoint2);
8029  // skip the next 10 characters (xxxx\uyyyy)
8030  i += 10;
8031  }
8032  else
8033  {
8034  // add unicode character(s)
8035  result += to_unicode(codepoint);
8036  // skip the next four characters (xxxx)
8037  i += 4;
8038  }
8039  break;
8040  }
8041  }
8042  }
8043  else
8044  {
8045  // all other characters are just copied to the end of the
8046  // string
8047  result.append(1, static_cast<typename string_t::value_type>(*i));
8048  }
8049  }
8050 
8051  return result;
8052  }
8053 
8074  long double str_to_float_t(long double* /* type */, char** endptr) const
8075  {
8076  return std::strtold(reinterpret_cast<typename string_t::const_pointer>(m_start), endptr);
8077  }
8078 
8093  double str_to_float_t(double* /* type */, char** endptr) const
8094  {
8095  return std::strtod(reinterpret_cast<typename string_t::const_pointer>(m_start), endptr);
8096  }
8097 
8112  float str_to_float_t(float* /* type */, char** endptr) const
8113  {
8114  return std::strtof(reinterpret_cast<typename string_t::const_pointer>(m_start), endptr);
8115  }
8116 
8129  template <typename T_A, typename T_B>
8130  bool attempt_cast(T_A source, T_B& dest) const
8131  {
8132  dest = static_cast<T_B>(source);
8133  return (source == static_cast<T_A>(dest));
8134  }
8135 
8174  void get_number(basic_json& result) const
8175  {
8176  typename string_t::value_type* endptr;
8177  assert(m_start != nullptr);
8178  errno = 0;
8179 
8180  // attempt to parse it as an integer - first checking for a
8181  // negative number
8182  if (*reinterpret_cast<typename string_t::const_pointer>(m_start) != '-')
8183  {
8184  // positive, parse with strtoull and attempt cast to
8185  // number_unsigned_t
8186  if (attempt_cast(std::strtoull(reinterpret_cast<typename string_t::const_pointer>(m_start), &endptr,
8187  10), result.m_value.number_unsigned))
8188  {
8189  result.m_type = value_t::number_unsigned;
8190  }
8191  else
8192  {
8193  // cast failed due to overflow - store as float
8194  result.m_type = value_t::number_float;
8195  }
8196  }
8197  else
8198  {
8199  // Negative, parse with strtoll and attempt cast to
8200  // number_integer_t
8201  if (attempt_cast(std::strtoll(reinterpret_cast<typename string_t::const_pointer>(m_start), &endptr,
8202  10), result.m_value.number_unsigned))
8203  {
8204  result.m_type = value_t::number_integer;
8205  }
8206  else
8207  {
8208  // cast failed due to overflow - store as float
8209  result.m_type = value_t::number_float;
8210  }
8211  }
8212 
8213  // check the end of the number was reached and no range error
8214  // occurred
8215  if (reinterpret_cast<lexer_char_t*>(endptr) != m_cursor || errno == ERANGE)
8216  {
8217  result.m_type = value_t::number_float;
8218  }
8219 
8220  if (result.m_type == value_t::number_float)
8221  {
8222  // either the number won't fit in an integer (range error from
8223  // strtoull/strtoll or overflow on cast) or there was something
8224  // else after the number, which could be an exponent
8225 
8226  // parse with strtod
8227  result.m_value.number_float = str_to_float_t(static_cast<number_float_t*>(nullptr), &endptr);
8228 
8229  // anything after the number is an error
8230  if (reinterpret_cast<lexer_char_t*>(endptr) != m_cursor)
8231  {
8232  throw std::invalid_argument(std::string("parse error - ") + get_token() + " is not a number");
8233  }
8234  }
8235  }
8236 
8237  private:
8239  std::istream* m_stream = nullptr;
8241  string_t m_buffer;
8243  const lexer_char_t* m_content = nullptr;
8245  const lexer_char_t* m_start = nullptr;
8247  const lexer_char_t* m_marker = nullptr;
8249  const lexer_char_t* m_cursor = nullptr;
8251  const lexer_char_t* m_limit = nullptr;
8252  };
8253 
8259  class parser
8260  {
8261  public:
8263  parser(const string_t& s, parser_callback_t cb = nullptr)
8264  : callback(cb), m_lexer(s)
8265  {
8266  // read first token
8267  get_token();
8268  }
8269 
8271  parser(std::istream& _is, parser_callback_t cb = nullptr)
8272  : callback(cb), m_lexer(&_is)
8273  {
8274  // read first token
8275  get_token();
8276  }
8277 
8279  basic_json parse()
8280  {
8281  basic_json result = parse_internal(true);
8282 
8283  expect(lexer::token_type::end_of_input);
8284 
8285  // return parser result and replace it with null in case the
8286  // top-level value was discarded by the callback function
8287  return result.is_discarded() ? basic_json() : result;
8288  }
8289 
8290  private:
8292  basic_json parse_internal(bool keep)
8293  {
8294  auto result = basic_json(value_t::discarded);
8295 
8296  switch (last_token)
8297  {
8298  case lexer::token_type::begin_object:
8299  {
8300  if (keep and (not callback or (keep = callback(depth++, parse_event_t::object_start, result))))
8301  {
8302  // explicitly set result to object to cope with {}
8303  result.m_type = value_t::object;
8304  result.m_value = json_value(value_t::object);
8305  }
8306 
8307  // read next token
8308  get_token();
8309 
8310  // closing } -> we are done
8311  if (last_token == lexer::token_type::end_object)
8312  {
8313  get_token();
8314  if (keep and callback and not callback(--depth, parse_event_t::object_end, result))
8315  {
8316  result = basic_json(value_t::discarded);
8317  }
8318  return result;
8319  }
8320 
8321  // no comma is expected here
8322  unexpect(lexer::token_type::value_separator);
8323 
8324  // otherwise: parse key-value pairs
8325  do
8326  {
8327  // ugly, but could be fixed with loop reorganization
8328  if (last_token == lexer::token_type::value_separator)
8329  {
8330  get_token();
8331  }
8332 
8333  // store key
8334  expect(lexer::token_type::value_string);
8335  const auto key = m_lexer.get_string();
8336 
8337  bool keep_tag = false;
8338  if (keep)
8339  {
8340  if (callback)
8341  {
8342  basic_json k(key);
8343  keep_tag = callback(depth, parse_event_t::key, k);
8344  }
8345  else
8346  {
8347  keep_tag = true;
8348  }
8349  }
8350 
8351  // parse separator (:)
8352  get_token();
8353  expect(lexer::token_type::name_separator);
8354 
8355  // parse and add value
8356  get_token();
8357  auto value = parse_internal(keep);
8358  if (keep and keep_tag and not value.is_discarded())
8359  {
8360  result[key] = std::move(value);
8361  }
8362  }
8363  while (last_token == lexer::token_type::value_separator);
8364 
8365  // closing }
8366  expect(lexer::token_type::end_object);
8367  get_token();
8368  if (keep and callback and not callback(--depth, parse_event_t::object_end, result))
8369  {
8370  result = basic_json(value_t::discarded);
8371  }
8372 
8373  return result;
8374  }
8375 
8376  case lexer::token_type::begin_array:
8377  {
8378  if (keep and (not callback or (keep = callback(depth++, parse_event_t::array_start, result))))
8379  {
8380  // explicitly set result to object to cope with []
8381  result.m_type = value_t::array;
8382  result.m_value = json_value(value_t::array);
8383  }
8384 
8385  // read next token
8386  get_token();
8387 
8388  // closing ] -> we are done
8389  if (last_token == lexer::token_type::end_array)
8390  {
8391  get_token();
8392  if (callback and not callback(--depth, parse_event_t::array_end, result))
8393  {
8394  result = basic_json(value_t::discarded);
8395  }
8396  return result;
8397  }
8398 
8399  // no comma is expected here
8400  unexpect(lexer::token_type::value_separator);
8401 
8402  // otherwise: parse values
8403  do
8404  {
8405  // ugly, but could be fixed with loop reorganization
8406  if (last_token == lexer::token_type::value_separator)
8407  {
8408  get_token();
8409  }
8410 
8411  // parse value
8412  auto value = parse_internal(keep);
8413  if (keep and not value.is_discarded())
8414  {
8415  result.push_back(std::move(value));
8416  }
8417  }
8418  while (last_token == lexer::token_type::value_separator);
8419 
8420  // closing ]
8421  expect(lexer::token_type::end_array);
8422  get_token();
8423  if (keep and callback and not callback(--depth, parse_event_t::array_end, result))
8424  {
8425  result = basic_json(value_t::discarded);
8426  }
8427 
8428  return result;
8429  }
8430 
8431  case lexer::token_type::literal_null:
8432  {
8433  get_token();
8434  result.m_type = value_t::null;
8435  break;
8436  }
8437 
8438  case lexer::token_type::value_string:
8439  {
8440  const auto s = m_lexer.get_string();
8441  get_token();
8442  result = basic_json(s);
8443  break;
8444  }
8445 
8446  case lexer::token_type::literal_true:
8447  {
8448  get_token();
8449  result.m_type = value_t::boolean;
8450  result.m_value = true;
8451  break;
8452  }
8453 
8454  case lexer::token_type::literal_false:
8455  {
8456  get_token();
8457  result.m_type = value_t::boolean;
8458  result.m_value = false;
8459  break;
8460  }
8461 
8462  case lexer::token_type::value_number:
8463  {
8464  m_lexer.get_number(result);
8465  get_token();
8466  break;
8467  }
8468 
8469  default:
8470  {
8471  // the last token was unexpected
8472  unexpect(last_token);
8473  }
8474  }
8475 
8476  if (keep and callback and not callback(depth, parse_event_t::value, result))
8477  {
8478  result = basic_json(value_t::discarded);
8479  }
8480  return result;
8481  }
8482 
8484  typename lexer::token_type get_token()
8485  {
8486  last_token = m_lexer.scan();
8487  return last_token;
8488  }
8489 
8490  void expect(typename lexer::token_type t) const
8491  {
8492  if (t != last_token)
8493  {
8494  std::string error_msg = "parse error - unexpected ";
8495  error_msg += (last_token == lexer::token_type::parse_error ? ("'" + m_lexer.get_token() + "'") :
8496  lexer::token_type_name(last_token));
8497  error_msg += "; expected " + lexer::token_type_name(t);
8498  throw std::invalid_argument(error_msg);
8499  }
8500  }
8501 
8502  void unexpect(typename lexer::token_type t) const
8503  {
8504  if (t == last_token)
8505  {
8506  std::string error_msg = "parse error - unexpected ";
8507  error_msg += (last_token == lexer::token_type::parse_error ? ("'" + m_lexer.get_token() + "'") :
8508  lexer::token_type_name(last_token));
8509  throw std::invalid_argument(error_msg);
8510  }
8511  }
8512 
8513  private:
8515  int depth = 0;
8517  parser_callback_t callback;
8519  typename lexer::token_type last_token = lexer::token_type::uninitialized;
8521  lexer m_lexer;
8522  };
8523 };
8524 
8525 
8527 // presets //
8529 
8539 }
8540 
8541 
8543 // nonmember functions //
8545 
8546 // specialization of std::swap, and std::hash
8547 namespace std
8548 {
8554 template <>
8555 inline void swap(nlohmann::json& j1,
8556  nlohmann::json& j2) noexcept(
8557  is_nothrow_move_constructible<nlohmann::json>::value and
8558  is_nothrow_move_assignable<nlohmann::json>::value
8559  )
8560 {
8561  j1.swap(j2);
8562 }
8563 
8565 template <>
8566 struct hash<nlohmann::json>
8567 {
8573  std::size_t operator()(const nlohmann::json& j) const
8574  {
8575  // a naive hashing via the string representation
8576  const auto& h = hash<nlohmann::json::string_t>();
8577  return h(j.dump());
8578  }
8579 };
8580 }
8581 
8594 inline nlohmann::json operator "" _json(const char* s, std::size_t)
8595 {
8596  return nlohmann::json::parse(reinterpret_cast<const nlohmann::json::string_t::value_type*>(s));
8597 }
8598 
8599 // restore GCC/clang diagnostic settings
8600 #if defined(__clang__) || defined(__GNUC__) || defined(__GNUG__)
8601  #pragma GCC diagnostic pop
8602 #endif
8603 
8604 #endif
bool is_null() const noexcept
return whether value is null
Definition: json.hpp:2148
reference operator*()
return a reference to the value pointed to by the iterator
Definition: json.hpp:6702
reverse_iterator rbegin()
returns an iterator to the reverse-beginning
Definition: json.hpp:4114
friend bool operator<=(const_reference lhs, const_reference rhs) noexcept
comparison: less than or equal
Definition: json.hpp:5341
basic_json(const value_t value_type)
create an empty value with a given type
Definition: json.hpp:971
basic_json(const array_t &val)
create an array (explicit)
Definition: json.hpp:1097
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:3962
value_t type() const noexcept
return the type of the JSON value (explicit)
Definition: json.hpp:2088
bool is_number_integer() const noexcept
return whether value is an integer number
Definition: json.hpp:2220
const_reference operator[](size_type idx) const
access specified array element
Definition: json.hpp:3182
reference value() const
return the value of an iterator
Definition: json.hpp:6785
json_reverse_iterator & operator--()
pre-decrement (–it)
Definition: json.hpp:6847
bool is_boolean() const noexcept
return whether value is a boolean
Definition: json.hpp:2167
void clear() noexcept
clears the contents
Definition: json.hpp:4451
bool operator==(const const_iterator &other) const
comparison: equal
Definition: json.hpp:6436
json_reverse_iterator operator--(int)
post-decrement (it–)
Definition: json.hpp:6841
reference operator[](T *(&key)[n])
access specified object element
Definition: json.hpp:3314
friend std::istream & operator>>(std::istream &i, basic_json &j)
deserialize from stream
Definition: json.hpp:5554
bool is_number() const noexcept
return whether value is a number
Definition: json.hpp:2194
iterator & operator+=(difference_type i)
add to iterator
Definition: json.hpp:6744
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:1676
const_iterator operator-(difference_type i)
subtract from iterator
Definition: json.hpp:6562
BooleanType boolean_t
a type for a boolean
Definition: json.hpp:473
reference operator+=(const typename object_t::value_type &val)
add an object to an object
Definition: json.hpp:4637
bool is_array() const noexcept
return whether value is an array
Definition: json.hpp:2308
basic_json(const typename string_t::value_type *val)
create a string (explicit)
Definition: json.hpp:1187
basic_json(boolean_t val)
create a boolean (explicit)
Definition: json.hpp:1236
reference operator[](difference_type n) const
access to successor
Definition: json.hpp:6883
iterator find(typename object_t::key_type key)
find an element in a JSON object
Definition: json.hpp:3914
basic_json(const number_unsigned_t val)
create an unsigned integer number (explicit)
Definition: json.hpp:1365
friend bool operator!=(const_reference lhs, const_reference rhs) noexcept
comparison: not equal
Definition: json.hpp:5179
basic_json(const string_t &val)
create a string (explicit)
Definition: json.hpp:1163
void push_back(const basic_json &val)
add an object to an array
Definition: json.hpp:4563
void erase(const size_type idx)
remove element from a JSON array given an index
Definition: json.hpp:3878
basic_json<> json
default JSON class
Definition: json.hpp:8538
ArrayType< basic_json, AllocatorType< basic_json >> array_t
a type for an array
Definition: json.hpp:400
bool is_structured() const noexcept
return whether type is structured
Definition: json.hpp:2129
reference front()
access the first element
Definition: json.hpp:3549
void swap(object_t &other)
exchanges the values
Definition: json.hpp:4935
json_reverse_iterator operator-(difference_type i) const
subtract from iterator
Definition: json.hpp:6869
const_iterator & operator+=(difference_type i)
add to iterator
Definition: json.hpp:6520
a class to store JSON values
Definition: json.hpp:194
basic_json(const number_float_t val)
create a floating-point number (explicit)
Definition: json.hpp:1425
pointer operator->()
dereference the iterator
Definition: json.hpp:6708
reference value() const
return the value of an iterator
Definition: json.hpp:6896
friend bool operator==(std::nullptr_t, const_reference v) noexcept
comparison: equal
Definition: json.hpp:5158
const_reverse_iterator crbegin() const
returns a const reverse iterator to the last element
Definition: json.hpp:4176
NumberIntegerType number_integer_t
a type for a number (integer)
Definition: json.hpp:544
iterator insert(const_iterator pos, size_type cnt, const basic_json &val)
inserts elements
Definition: json.hpp:4721
const_reference at(const typename object_t::key_type &key) const
access specified object element with bounds checking
Definition: json.hpp:3090
const_iterator operator+(difference_type i)
add to iterator
Definition: json.hpp:6554
const_reverse_iterator rbegin() const
returns a const reverse iterator to the last element
Definition: json.hpp:4122
a mutable random access iterator for the basic_json class
Definition: json.hpp:6669
static basic_json parse(std::istream &&i, parser_callback_t cb=nullptr)
deserialize from stream
Definition: json.hpp:5516
const_iterator operator++(int)
post-increment (it++)
Definition: json.hpp:6362
bool is_string() const noexcept
return whether value is a string
Definition: json.hpp:2327
ObjectType< StringType, basic_json, std::less< StringType >, AllocatorType< std::pair< const StringType, basic_json >>> object_t
a type for an object
Definition: json.hpp:354
STL namespace.
NumberUnsignedType number_unsigned_t
a type for a number (unsigned)
Definition: json.hpp:616
typename std::allocator_traits< allocator_type >::const_pointer const_pointer
the type of an element const pointer
Definition: json.hpp:235
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:1636
static iteration_proxy< const_iterator > iterator_wrapper(const_reference cont)
wrapper to access iterator member functions in range-based for
Definition: json.hpp:4228
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:1962
typename basic_json::value_type value_type
the type of the values when the iterator is dereferenced
Definition: json.hpp:6134
PointerType get_ptr() noexcept
get a pointer value (implicit)
Definition: json.hpp:2804
reference back()
access the last element
Definition: json.hpp:3583
const value_type & const_reference
the type of an element const reference
Definition: json.hpp:222
typename basic_json::const_pointer pointer
defines a pointer to the type iterated over (value_type)
Definition: json.hpp:6138
bool is_number_unsigned() const noexcept
return whether value is an unsigned integer number
Definition: json.hpp:2245
void push_back(const typename object_t::value_type &val)
add an object to an object
Definition: json.hpp:4613
iterator end()
returns an iterator to one past the last element
Definition: json.hpp:4056
static basic_json parse(const string_t &s, parser_callback_t cb=nullptr)
deserialize from string
Definition: json.hpp:5479
const_reference operator[](T *(&key)[n]) const
read-only access specified object element
Definition: json.hpp:3349
iterator insert(const_iterator pos, const_iterator first, const_iterator last)
inserts elements
Definition: json.hpp:4774
basic_json(std::nullptr_t) noexcept
create a null object (explicitly)
Definition: json.hpp:1015
basic_json(InputIT first, InputIT last)
construct a JSON container given an iterator range
Definition: json.hpp:1746
reference operator[](difference_type n) const
access to successor
Definition: json.hpp:6779
static allocator_type get_allocator()
returns the allocator associated with the container
Definition: json.hpp:255
const_reference operator[](const typename object_t::key_type &key) const
read-only access specified object element
Definition: json.hpp:3271
const_reference operator[](T *key) const
read-only access specified object element
Definition: json.hpp:3431
json_reverse_iterator operator+(difference_type i) const
add to iterator
Definition: json.hpp:6861
bool empty() const noexcept
checks whether the container is empty
Definition: json.hpp:4272
std::size_t size_type
a type to represent container sizes
Definition: json.hpp:227
object_t::key_type key() const
return the key of an object iterator
Definition: json.hpp:6889
basic_json(const CompatibleArrayType &val)
create an array (implicit)
Definition: json.hpp:1134
const_reference at(size_type idx) const
access specified array element with bounds checking
Definition: json.hpp:2994
basic_json(size_type cnt, const basic_json &val)
construct an array with count copies of given value
Definition: json.hpp:1700
std::reverse_iterator< Base > base_iterator
shortcut to the reverse iterator adaptor
Definition: json.hpp:6813
iterator insert(const_iterator pos, std::initializer_list< basic_json > ilist)
inserts elements
Definition: json.hpp:4832
const_iterator(const iterator &other)
copy constructor given a nonconst iterator
Definition: json.hpp:6175
typename std::allocator_traits< allocator_type >::pointer pointer
the type of an element pointer
Definition: json.hpp:233
iterator insert(const_iterator pos, const basic_json &val)
inserts element
Definition: json.hpp:4665
friend bool operator>=(const_reference lhs, const_reference rhs) noexcept
comparison: greater than or equal
Definition: json.hpp:5385
friend bool operator<(const_reference lhs, const_reference rhs) noexcept
comparison: less than
Definition: json.hpp:5240
iterator & operator++()
pre-increment (++it)
Definition: json.hpp:6722
bool operator<(const const_iterator &other) const
comparison: smaller
Definition: json.hpp:6472
iterator operator++(int)
post-increment (it++)
Definition: json.hpp:6714
basic_json(basic_json &&other) noexcept
move constructor
Definition: json.hpp:1932
const_iterator operator--(int)
post-decrement (it–)
Definition: json.hpp:6399
bool is_discarded() const noexcept
return whether value is discarded
Definition: json.hpp:2351
reference at(const typename object_t::key_type &key)
access specified object element with bounds checking
Definition: json.hpp:3042
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:6690
object (unordered set of name/value pairs)
size_type max_size() const noexcept
returns the maximum possible number of elements
Definition: json.hpp:4392
~basic_json()
destructor
Definition: json.hpp:1988
iterator operator--(int)
post-decrement (it–)
Definition: json.hpp:6729
iterator operator-(difference_type i)
subtract from iterator
Definition: json.hpp:6766
const_iterator & operator--()
pre-decrement (–it)
Definition: json.hpp:6407
const_iterator cend() const
returns a const iterator to one past the last element
Definition: json.hpp:4090
string_t dump(const int indent=-1) const
serialization
Definition: json.hpp:2057
basic_json value_type
the type of elements in a basic_json container
Definition: json.hpp:217
std::function< bool(int depth, parse_event_t event, basic_json &parsed)> parser_callback_t
per-element parser callback type
Definition: json.hpp:922
AllocatorType< basic_json > allocator_type
the allocator type
Definition: json.hpp:230
StringType string_t
a type for a string
Definition: json.hpp:447
reference operator+=(const basic_json &val)
add an object to an array
Definition: json.hpp:4587
iterator begin()
returns an iterator to the first element
Definition: json.hpp:3997
difference_type operator-(const const_iterator &other) const
return difference
Definition: json.hpp:6570
value_type & reference
the type of an element reference
Definition: json.hpp:220
const_iterator begin() const
returns a const iterator to the first element
Definition: json.hpp:4007
friend std::ostream & operator>>(const basic_json &j, std::ostream &o)
serialize to stream
Definition: json.hpp:5440
difference_type operator-(const iterator &other) const
Definition: json.hpp:6773
basic_json(const int val)
create an integer number from an enum type (explicit)
Definition: json.hpp:1300
iterator(const iterator &other) noexcept
copy constructor
Definition: json.hpp:6685
namespace for Niels Lohmann
Definition: json.hpp:88
typename basic_json::difference_type difference_type
a type to represent differences between iterators
Definition: json.hpp:6136
void swap(string_t &other)
exchanges the values
Definition: json.hpp:4969
json_reverse_iterator(const base_iterator &it)
create reverse iterator from base class
Definition: json.hpp:6823
basic_json(const number_integer_t val)
create an integer number (explicit)
Definition: json.hpp:1271
reverse_iterator rend()
returns an iterator to the reverse-end
Definition: json.hpp:4145
basic_json(const CompatibleNumberIntegerType val) noexcept
create an integer number (implicit)
Definition: json.hpp:1337
const_reference front() const
access the first element
Definition: json.hpp:3557
bool operator>(const const_iterator &other) const
comparison: greater than
Definition: json.hpp:6508
bool is_object() const noexcept
return whether value is an object
Definition: json.hpp:2289
pointer operator->() const
dereference the iterator
Definition: json.hpp:6327
NumberFloatType number_float_t
a type for a number (floating-point)
Definition: json.hpp:684
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:4870
value_t
the JSON type enumeration
Definition: json.hpp:703
const_reverse_iterator rend() const
returns a const reverse iterator to one before the first
Definition: json.hpp:4153
std::ptrdiff_t difference_type
a type to represent differences between iterators
Definition: json.hpp:225
bool is_primitive() const noexcept
return whether type is primitive
Definition: json.hpp:2109
ValueType get() const
get a value (explicit)
Definition: json.hpp:2720
void swap(array_t &other)
exchanges the values
Definition: json.hpp:4901
InteratorType erase(InteratorType first, InteratorType last)
remove elements given an iterator range
Definition: json.hpp:3756
ValueType value(const typename object_t::key_type &key, ValueType default_value) const
access specified object element with default value
Definition: json.hpp:3498
typename Base::reference reference
the reference type for the pointed-to element
Definition: json.hpp:6815
const_reference back() const
access the last element
Definition: json.hpp:3593
void push_back(basic_json &&val)
add an object to an array
Definition: json.hpp:4527
array (ordered collection of values)
json_reverse_iterator & operator++()
pre-increment (++it)
Definition: json.hpp:6834
static basic_json parse(std::istream &i, parser_callback_t cb=nullptr)
deserialize from stream
Definition: json.hpp:5508
friend bool operator==(const_reference lhs, const_reference rhs) noexcept
comparison: equal
Definition: json.hpp:5050
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:3524
ReferenceType get_ref() const
get a reference value (implicit)
Definition: json.hpp:2870
basic_json(const CompatibleNumberUnsignedType val) noexcept
create an unsigned number (implicit)
Definition: json.hpp:1396
const_iterator(pointer object)
constructor for a given JSON instance
Definition: json.hpp:6148
reference operator*() const
return a reference to the value pointed to by the iterator
Definition: json.hpp:6287
friend bool operator<(const value_t lhs, const value_t rhs)
comparison operator for JSON types
Definition: json.hpp:5003
const PointerType get_ptr() const noexcept
get a pointer value (implicit)
Definition: json.hpp:2819
friend bool operator!=(const_reference v, std::nullptr_t) noexcept
comparison: not equal
Definition: json.hpp:5202
iterator operator+(difference_type i)
add to iterator
Definition: json.hpp:6758
basic_json(const CompatibleNumberFloatType val) noexcept
create an floating-point number (implicit)
Definition: json.hpp:1471
bool operator<=(const const_iterator &other) const
comparison: less than or equal
Definition: json.hpp:6502
InteratorType erase(InteratorType pos)
remove element given an iterator
Definition: json.hpp:3650
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:1544
iterator(pointer object) noexcept
constructor for a given JSON instance
Definition: json.hpp:6680
friend bool operator!=(std::nullptr_t, const_reference v) noexcept
comparison: not equal
Definition: json.hpp:5211
json_reverse_iterator(const typename base_iterator::iterator_type &it)
create reverse iterator from iterator
Definition: json.hpp:6818
const_iterator & operator++()
pre-increment (++it)
Definition: json.hpp:6370
bool is_number_float() const noexcept
return whether value is a floating-point number
Definition: json.hpp:2270
reference value() const
return the value of an iterator
Definition: json.hpp:6645
std::bidirectional_iterator_tag iterator_category
the category of the iterator
Definition: json.hpp:6142
difference_type operator-(const json_reverse_iterator &other) const
return difference
Definition: json.hpp:6877
const_iterator find(typename object_t::key_type key) const
find an element in a JSON object
Definition: json.hpp:3931
basic_json(const CompatibleObjectType &val)
create an object (implicit)
Definition: json.hpp:1070
friend bool operator>(const_reference lhs, const_reference rhs) noexcept
comparison: greater than
Definition: json.hpp:5363
bool operator>=(const const_iterator &other) const
comparison: greater than or equal
Definition: json.hpp:6514
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:6207
size_type erase(const typename object_t::key_type &key)
remove element from a JSON object given a key
Definition: json.hpp:3840
reference operator[](const typename object_t::key_type &key)
access specified object element
Definition: json.hpp:3223
object_t::key_type key() const
return the key of an object iterator
Definition: json.hpp:6630
const_iterator end() const
returns a const iterator to one past the last element
Definition: json.hpp:4066
reference operator+=(basic_json &&val)
add an object to an array
Definition: json.hpp:4553
reference operator[](difference_type n) const
access to successor
Definition: json.hpp:6594
a const random access iterator for the basic_json class
Definition: json.hpp:6127
a template for a reverse iterator class
Definition: json.hpp:238
typename basic_json::const_reference reference
defines a reference to the type iterated over (value_type)
Definition: json.hpp:6140
json_reverse_iterator operator++(int)
post-increment (it++)
Definition: json.hpp:6828
friend bool operator==(const_reference v, std::nullptr_t) noexcept
comparison: equal
Definition: json.hpp:5149
reference operator[](size_type idx)
access specified array element
Definition: json.hpp:3137
bool operator!=(const const_iterator &other) const
comparison: not equal
Definition: json.hpp:6466
json_reverse_iterator & operator+=(difference_type i)
add to iterator
Definition: json.hpp:6854
reference at(size_type idx)
access specified array element with bounds checking
Definition: json.hpp:2950
size_type size() const noexcept
returns the number of elements
Definition: json.hpp:4330
static iteration_proxy< iterator > iterator_wrapper(reference cont)
wrapper to access iterator member functions in range-based for
Definition: json.hpp:4220
const_iterator cbegin() const
returns a const iterator to the first element
Definition: json.hpp:4031
iterator & operator-=(difference_type i)
subtract from iterator
Definition: json.hpp:6751
const_reverse_iterator crend() const
returns a const reverse iterator to one before the first
Definition: json.hpp:4199
basic_json(const object_t &val)
create an object (explicit)
Definition: json.hpp:1038
friend std::istream & operator<<(basic_json &j, std::istream &i)
deserialize from stream
Definition: json.hpp:5544
std::size_t operator()(const nlohmann::json &j) const
return a hash value for a JSON object
Definition: json.hpp:8573
friend std::ostream & operator<<(std::ostream &o, const basic_json &j)
serialize to stream
Definition: json.hpp:5422
const_iterator(const const_iterator &other) noexcept
copy constructor
Definition: json.hpp:6202
iterator & operator--()
pre-decrement (–it)
Definition: json.hpp:6737
iterator insert(const_iterator pos, basic_json &&val)
inserts element
Definition: json.hpp:4692
ReferenceType get_ref()
get a reference value (implicit)
Definition: json.hpp:2855
const_iterator & operator-=(difference_type i)
subtract from iterator
Definition: json.hpp:6548
basic_json(const CompatibleStringType &val)
create a string (implicit)
Definition: json.hpp:1218
basic_json(const basic_json &other)
copy constructor
Definition: json.hpp:1857
reference operator[](T *key)
access specified object element
Definition: json.hpp:3382
parse_event_t
JSON callback events.
Definition: json.hpp:857