JSON for Modern C++  2.0.0
json.hpp
1 /*
2  __ _____ _____ _____
3  __| | __| | | | JSON for Modern C++
4 | | |__ | | | | | | version 2.0.0
5 |_____|_____|_____|_|___| https://github.com/nlohmann/json
6 
7 Copyright (c) 2013-2016 Niels Lohmann <http://nlohmann.me>.
8 Licensed under the MIT License <http://opensource.org/licenses/MIT>.
9 */
10 
11 #ifndef NLOHMANN_JSON_HPP
12 #define NLOHMANN_JSON_HPP
13 
14 #include <algorithm>
15 #include <array>
16 #include <cassert>
17 #include <ciso646>
18 #include <cmath>
19 #include <cstddef>
20 #include <cstdio>
21 #include <cstdlib>
22 #include <functional>
23 #include <initializer_list>
24 #include <iomanip>
25 #include <iostream>
26 #include <iterator>
27 #include <limits>
28 #include <map>
29 #include <memory>
30 #include <sstream>
31 #include <stdexcept>
32 #include <string>
33 #include <type_traits>
34 #include <utility>
35 #include <vector>
36 
37 // enable ssize_t on MinGW
38 #ifdef __GNUC__
39  #ifdef __MINGW32__
40  #include <sys/types.h>
41  #endif
42 #endif
43 
44 // disable float-equal warnings on GCC/clang
45 #if defined(__clang__) || defined(__GNUC__) || defined(__GNUG__)
46  #pragma GCC diagnostic push
47  #pragma GCC diagnostic ignored "-Wfloat-equal"
48 #endif
49 
50 // enable ssize_t for MSVC
51 #ifdef _MSC_VER
52  #include <basetsd.h>
53  using ssize_t = SSIZE_T;
54 #endif
55 
61 namespace nlohmann
62 {
63 
64 
69 namespace
70 {
75 template<typename T>
76 struct has_mapped_type
77 {
78  private:
79  template<typename C> static char test(typename C::mapped_type*);
80  template<typename C> static char (&test(...))[2];
81  public:
82  static constexpr bool value = sizeof(test<T>(0)) == 1;
83 };
84 
85 }
86 
158 template <
159  template<typename U, typename V, typename... Args> class ObjectType = std::map,
160  template<typename U, typename... Args> class ArrayType = std::vector,
161  class StringType = std::string,
162  class BooleanType = bool,
163  class NumberIntegerType = int64_t,
164  class NumberUnsignedType = uint64_t,
165  class NumberFloatType = double,
166  template<typename U> class AllocatorType = std::allocator
167  >
169 {
170  private:
172  using basic_json_t = basic_json<ObjectType,
173  ArrayType,
174  StringType,
175  BooleanType,
176  NumberIntegerType,
177  NumberUnsignedType,
178  NumberFloatType,
179  AllocatorType>;
180 
181  public:
182 
184  // container types //
186 
189 
192 
196  using const_reference = const value_type&;
197 
199  using difference_type = std::ptrdiff_t;
201  using size_type = std::size_t;
202 
204  using allocator_type = AllocatorType<basic_json>;
205 
207  using pointer = typename std::allocator_traits<allocator_type>::pointer;
209  using const_pointer = typename std::allocator_traits<allocator_type>::const_pointer;
210 
211  // forward declaration
212  template<typename Base> class json_reverse_iterator;
213 
215  class iterator;
217  class const_iterator;
222 
224 
225 
230  {
231  return allocator_type();
232  }
233 
234 
236  // JSON value data types //
238 
241 
324  using object_t = ObjectType<StringType,
325  basic_json,
326  std::less<StringType>,
327  AllocatorType<std::pair<const StringType,
328  basic_json>>>;
329 
374  using array_t = ArrayType<basic_json, AllocatorType<basic_json>>;
375 
421  using string_t = StringType;
422 
447  using boolean_t = BooleanType;
448 
518  using number_integer_t = NumberIntegerType;
519 
590  using number_unsigned_t = NumberUnsignedType;
591 
658  using number_float_t = NumberFloatType;
659 
661 
662 
664  // JSON type enumeration //
666 
677  enum class value_t : uint8_t
678  {
679  null,
680  object,
681  array,
682  string,
683  boolean,
684  number_integer,
685  number_unsigned,
686  number_float,
687  discarded
688  };
689 
690 
691  private:
693  template<typename T, typename... Args>
694  static T* create(Args&& ... args)
695  {
696  AllocatorType<T> alloc;
697  auto deleter = [&](T * object)
698  {
699  alloc.deallocate(object, 1);
700  };
701  std::unique_ptr<T, decltype(deleter)> object(alloc.allocate(1), deleter);
702  alloc.construct(object.get(), std::forward<Args>(args)...);
703  return object.release();
704  }
705 
707  // JSON value storage //
709 
717  union json_value
718  {
720  object_t* object;
722  array_t* array;
724  string_t* string;
726  boolean_t boolean;
728  number_integer_t number_integer;
730  number_unsigned_t number_unsigned;
732  number_float_t number_float;
733 
735  json_value() noexcept = default;
737  json_value(boolean_t v) noexcept : boolean(v) {}
739  json_value(number_integer_t v) noexcept : number_integer(v) {}
741  json_value(number_unsigned_t v) noexcept : number_unsigned(v) {}
743  json_value(number_float_t v) noexcept : number_float(v) {}
745  json_value(value_t t)
746  {
747  switch (t)
748  {
749  case value_t::object:
750  {
751  object = create<object_t>();
752  break;
753  }
754 
755  case value_t::array:
756  {
757  array = create<array_t>();
758  break;
759  }
760 
761  case value_t::string:
762  {
763  string = create<string_t>("");
764  break;
765  }
766 
767  case value_t::boolean:
768  {
769  boolean = boolean_t(false);
770  break;
771  }
772 
773  case value_t::number_integer:
774  {
775  number_integer = number_integer_t(0);
776  break;
777  }
778 
779  case value_t::number_unsigned:
780  {
781  number_unsigned = number_unsigned_t(0);
782  break;
783  }
784 
785  case value_t::number_float:
786  {
787  number_float = number_float_t(0.0);
788  break;
789  }
790 
791  default:
792  {
793  break;
794  }
795  }
796  }
797 
799  json_value(const string_t& value)
800  {
801  string = create<string_t>(value);
802  }
803 
805  json_value(const object_t& value)
806  {
807  object = create<object_t>(value);
808  }
809 
811  json_value(const array_t& value)
812  {
813  array = create<array_t>(value);
814  }
815  };
816 
817 
818  public:
820  // JSON parser callback //
822 
831  enum class parse_event_t : uint8_t
832  {
834  object_start,
836  object_end,
838  array_start,
840  array_end,
842  key,
844  value
845  };
846 
896  using parser_callback_t = std::function<bool(int depth, parse_event_t event, basic_json& parsed)>;
897 
898 
900  // constructors //
902 
905 
946  : m_type(value_type), m_value(value_type)
947  {}
948 
970  basic_json() noexcept = default;
971 
991  basic_json(std::nullptr_t) noexcept
992  : basic_json(value_t::null)
993  {}
994 
1014  basic_json(const object_t& val)
1015  : m_type(value_t::object), m_value(val)
1016  {}
1017 
1041  template <class CompatibleObjectType, typename
1042  std::enable_if<
1043  std::is_constructible<typename object_t::key_type, typename CompatibleObjectType::key_type>::value and
1044  std::is_constructible<basic_json, typename CompatibleObjectType::mapped_type>::value, int>::type
1045  = 0>
1046  basic_json(const CompatibleObjectType& val)
1047  : m_type(value_t::object)
1048  {
1049  using std::begin;
1050  using std::end;
1051  m_value.object = create<object_t>(begin(val), end(val));
1052  }
1053 
1073  basic_json(const array_t& val)
1074  : m_type(value_t::array), m_value(val)
1075  {}
1076 
1100  template <class CompatibleArrayType, typename
1101  std::enable_if<
1102  not std::is_same<CompatibleArrayType, typename basic_json_t::iterator>::value and
1103  not std::is_same<CompatibleArrayType, typename basic_json_t::const_iterator>::value and
1104  not std::is_same<CompatibleArrayType, typename basic_json_t::reverse_iterator>::value and
1105  not std::is_same<CompatibleArrayType, typename basic_json_t::const_reverse_iterator>::value and
1106  not std::is_same<CompatibleArrayType, typename array_t::iterator>::value and
1107  not std::is_same<CompatibleArrayType, typename array_t::const_iterator>::value and
1108  std::is_constructible<basic_json, typename CompatibleArrayType::value_type>::value, int>::type
1109  = 0>
1110  basic_json(const CompatibleArrayType& val)
1111  : m_type(value_t::array)
1112  {
1113  using std::begin;
1114  using std::end;
1115  m_value.array = create<array_t>(begin(val), end(val));
1116  }
1117 
1139  basic_json(const string_t& val)
1140  : m_type(value_t::string), m_value(val)
1141  {}
1142 
1163  basic_json(const typename string_t::value_type* val)
1164  : basic_json(string_t(val))
1165  {}
1166 
1190  template <class CompatibleStringType, typename
1191  std::enable_if<
1192  std::is_constructible<string_t, CompatibleStringType>::value, int>::type
1193  = 0>
1194  basic_json(const CompatibleStringType& val)
1195  : basic_json(string_t(val))
1196  {}
1197 
1213  : m_type(value_t::boolean), m_value(val)
1214  {}
1215 
1241  template<typename T,
1242  typename std::enable_if<
1243  not (std::is_same<T, int>::value)
1244  and std::is_same<T, number_integer_t>::value
1245  , int>::type
1246  = 0>
1248  : m_type(value_t::number_integer), m_value(val)
1249  {}
1250 
1276  basic_json(const int val)
1277  : m_type(value_t::number_integer),
1278  m_value(static_cast<number_integer_t>(val))
1279  {}
1280 
1306  template<typename CompatibleNumberIntegerType, typename
1307  std::enable_if<
1308  std::is_constructible<number_integer_t, CompatibleNumberIntegerType>::value and
1309  std::numeric_limits<CompatibleNumberIntegerType>::is_integer and
1310  std::numeric_limits<CompatibleNumberIntegerType>::is_signed,
1311  CompatibleNumberIntegerType>::type
1312  = 0>
1313  basic_json(const CompatibleNumberIntegerType val) noexcept
1314  : m_type(value_t::number_integer),
1315  m_value(static_cast<number_integer_t>(val))
1316  {}
1317 
1335  template<typename T,
1336  typename std::enable_if<
1337  not (std::is_same<T, int>::value)
1338  and std::is_same<T, number_unsigned_t>::value
1339  , int>::type
1340  = 0>
1342  : m_type(value_t::number_unsigned), m_value(val)
1343  {}
1344 
1365  template < typename CompatibleNumberUnsignedType, typename
1366  std::enable_if <
1367  std::is_constructible<number_unsigned_t, CompatibleNumberUnsignedType>::value and
1368  std::numeric_limits<CompatibleNumberUnsignedType>::is_integer and
1369  !std::numeric_limits<CompatibleNumberUnsignedType>::is_signed,
1370  CompatibleNumberUnsignedType >::type
1371  = 0 >
1372  basic_json(const CompatibleNumberUnsignedType val) noexcept
1373  : m_type(value_t::number_unsigned),
1374  m_value(static_cast<number_unsigned_t>(val))
1375  {}
1376 
1402  : m_type(value_t::number_float), m_value(val)
1403  {
1404  // replace infinity and NAN by null
1405  if (not std::isfinite(val))
1406  {
1407  m_type = value_t::null;
1408  m_value = json_value();
1409  }
1410  }
1411 
1442  template<typename CompatibleNumberFloatType, typename = typename
1443  std::enable_if<
1444  std::is_constructible<number_float_t, CompatibleNumberFloatType>::value and
1445  std::is_floating_point<CompatibleNumberFloatType>::value>::type
1446  >
1447  basic_json(const CompatibleNumberFloatType val) noexcept
1448  : basic_json(number_float_t(val))
1449  {}
1450 
1520  basic_json(std::initializer_list<basic_json> init,
1521  bool type_deduction = true,
1522  value_t manual_type = value_t::array)
1523  {
1524  // the initializer list could describe an object
1525  bool is_an_object = true;
1526 
1527  // check if each element is an array with two elements whose first
1528  // element is a string
1529  for (const auto& element : init)
1530  {
1531  if (not element.is_array() or element.size() != 2
1532  or not element[0].is_string())
1533  {
1534  // we found an element that makes it impossible to use the
1535  // initializer list as object
1536  is_an_object = false;
1537  break;
1538  }
1539  }
1540 
1541  // adjust type if type deduction is not wanted
1542  if (not type_deduction)
1543  {
1544  // if array is wanted, do not create an object though possible
1545  if (manual_type == value_t::array)
1546  {
1547  is_an_object = false;
1548  }
1549 
1550  // if object is wanted but impossible, throw an exception
1551  if (manual_type == value_t::object and not is_an_object)
1552  {
1553  throw std::domain_error("cannot create object from initializer list");
1554  }
1555  }
1556 
1557  if (is_an_object)
1558  {
1559  // the initializer list is a list of pairs -> create object
1560  m_type = value_t::object;
1561  m_value = value_t::object;
1562 
1563  assert(m_value.object != nullptr);
1564 
1565  for (auto& element : init)
1566  {
1567  m_value.object->emplace(std::move(*(element[0].m_value.string)), std::move(element[1]));
1568  }
1569  }
1570  else
1571  {
1572  // the initializer list describes an array -> create array
1573  m_type = value_t::array;
1574  m_value.array = create<array_t>(std::move(init));
1575  }
1576  }
1577 
1612  static basic_json array(std::initializer_list<basic_json> init =
1613  std::initializer_list<basic_json>())
1614  {
1615  return basic_json(init, false, value_t::array);
1616  }
1617 
1652  static basic_json object(std::initializer_list<basic_json> init =
1653  std::initializer_list<basic_json>())
1654  {
1655  return basic_json(init, false, value_t::object);
1656  }
1657 
1676  basic_json(size_type cnt, const basic_json& val)
1677  : m_type(value_t::array)
1678  {
1679  m_value.array = create<array_t>(cnt, val);
1680  }
1681 
1716  template <class InputIT, typename
1717  std::enable_if<
1718  std::is_same<InputIT, typename basic_json_t::iterator>::value or
1719  std::is_same<InputIT, typename basic_json_t::const_iterator>::value
1720  , int>::type
1721  = 0>
1722  basic_json(InputIT first, InputIT last) : m_type(first.m_object->m_type)
1723  {
1724  // make sure iterator fits the current value
1725  if (first.m_object != last.m_object)
1726  {
1727  throw std::domain_error("iterators are not compatible");
1728  }
1729 
1730  // check if iterator range is complete for primitive values
1731  switch (m_type)
1732  {
1733  case value_t::boolean:
1734  case value_t::number_float:
1735  case value_t::number_integer:
1736  case value_t::number_unsigned:
1737  case value_t::string:
1738  {
1739  if (not first.m_it.primitive_iterator.is_begin() or not last.m_it.primitive_iterator.is_end())
1740  {
1741  throw std::out_of_range("iterators out of range");
1742  }
1743  break;
1744  }
1745 
1746  default:
1747  {
1748  break;
1749  }
1750  }
1751 
1752  switch (m_type)
1753  {
1754  case value_t::number_integer:
1755  {
1756  assert(first.m_object != nullptr);
1757  m_value.number_integer = first.m_object->m_value.number_integer;
1758  break;
1759  }
1760 
1761  case value_t::number_unsigned:
1762  {
1763  assert(first.m_object != nullptr);
1764  m_value.number_unsigned = first.m_object->m_value.number_unsigned;
1765  break;
1766  }
1767 
1768  case value_t::number_float:
1769  {
1770  assert(first.m_object != nullptr);
1771  m_value.number_float = first.m_object->m_value.number_float;
1772  break;
1773  }
1774 
1775  case value_t::boolean:
1776  {
1777  assert(first.m_object != nullptr);
1778  m_value.boolean = first.m_object->m_value.boolean;
1779  break;
1780  }
1781 
1782  case value_t::string:
1783  {
1784  assert(first.m_object != nullptr);
1785  m_value = *first.m_object->m_value.string;
1786  break;
1787  }
1788 
1789  case value_t::object:
1790  {
1791  m_value.object = create<object_t>(first.m_it.object_iterator, last.m_it.object_iterator);
1792  break;
1793  }
1794 
1795  case value_t::array:
1796  {
1797  m_value.array = create<array_t>(first.m_it.array_iterator, last.m_it.array_iterator);
1798  break;
1799  }
1800 
1801  default:
1802  {
1803  assert(first.m_object != nullptr);
1804  throw std::domain_error("cannot use construct with iterators from " + first.m_object->type_name());
1805  }
1806  }
1807  }
1808 
1810  // other constructors and destructor //
1812 
1835  basic_json(const basic_json& other)
1836  : m_type(other.m_type)
1837  {
1838  switch (m_type)
1839  {
1840  case value_t::object:
1841  {
1842  assert(other.m_value.object != nullptr);
1843  m_value = *other.m_value.object;
1844  break;
1845  }
1846 
1847  case value_t::array:
1848  {
1849  assert(other.m_value.array != nullptr);
1850  m_value = *other.m_value.array;
1851  break;
1852  }
1853 
1854  case value_t::string:
1855  {
1856  assert(other.m_value.string != nullptr);
1857  m_value = *other.m_value.string;
1858  break;
1859  }
1860 
1861  case value_t::boolean:
1862  {
1863  m_value = other.m_value.boolean;
1864  break;
1865  }
1866 
1867  case value_t::number_integer:
1868  {
1869  m_value = other.m_value.number_integer;
1870  break;
1871  }
1872 
1873  case value_t::number_unsigned:
1874  {
1875  m_value = other.m_value.number_unsigned;
1876  break;
1877  }
1878 
1879  case value_t::number_float:
1880  {
1881  m_value = other.m_value.number_float;
1882  break;
1883  }
1884 
1885  default:
1886  {
1887  break;
1888  }
1889  }
1890  }
1891 
1910  basic_json(basic_json&& other) noexcept
1911  : m_type(std::move(other.m_type)),
1912  m_value(std::move(other.m_value))
1913  {
1914  // invalidate payload
1915  other.m_type = value_t::null;
1916  other.m_value = {};
1917  }
1918 
1942  reference& operator=(basic_json other) noexcept (
1943  std::is_nothrow_move_constructible<value_t>::value and
1944  std::is_nothrow_move_assignable<value_t>::value and
1945  std::is_nothrow_move_constructible<json_value>::value and
1946  std::is_nothrow_move_assignable<json_value>::value
1947  )
1948  {
1949  using std::swap;
1950  swap(m_type, other.m_type);
1951  swap(m_value, other.m_value);
1952  return *this;
1953  }
1954 
1971  {
1972  switch (m_type)
1973  {
1974  case value_t::object:
1975  {
1976  AllocatorType<object_t> alloc;
1977  alloc.destroy(m_value.object);
1978  alloc.deallocate(m_value.object, 1);
1979  break;
1980  }
1981 
1982  case value_t::array:
1983  {
1984  AllocatorType<array_t> alloc;
1985  alloc.destroy(m_value.array);
1986  alloc.deallocate(m_value.array, 1);
1987  break;
1988  }
1989 
1990  case value_t::string:
1991  {
1992  AllocatorType<string_t> alloc;
1993  alloc.destroy(m_value.string);
1994  alloc.deallocate(m_value.string, 1);
1995  break;
1996  }
1997 
1998  default:
1999  {
2000  // all other types need no specific destructor
2001  break;
2002  }
2003  }
2004  }
2005 
2007 
2008  public:
2010  // object inspection //
2012 
2015 
2039  string_t dump(const int indent = -1) const
2040  {
2041  std::stringstream ss;
2042 
2043  if (indent >= 0)
2044  {
2045  dump(ss, true, static_cast<unsigned int>(indent));
2046  }
2047  else
2048  {
2049  dump(ss, false, 0);
2050  }
2051 
2052  return ss.str();
2053  }
2054 
2070  value_t type() const noexcept
2071  {
2072  return m_type;
2073  }
2074 
2097  bool is_primitive() const noexcept
2098  {
2099  return is_null() or is_string() or is_boolean() or is_number();
2100  }
2101 
2121  bool is_structured() const noexcept
2122  {
2123  return is_array() or is_object();
2124  }
2125 
2140  bool is_null() const noexcept
2141  {
2142  return m_type == value_t::null;
2143  }
2144 
2159  bool is_boolean() const noexcept
2160  {
2161  return m_type == value_t::boolean;
2162  }
2163 
2186  bool is_number() const noexcept
2187  {
2188  return is_number_integer() or is_number_float();
2189  }
2190 
2212  bool is_number_integer() const noexcept
2213  {
2214  return m_type == value_t::number_integer or m_type == value_t::number_unsigned;
2215  }
2216 
2237  bool is_number_unsigned() const noexcept
2238  {
2239  return m_type == value_t::number_unsigned;
2240  }
2241 
2262  bool is_number_float() const noexcept
2263  {
2264  return m_type == value_t::number_float;
2265  }
2266 
2281  bool is_object() const noexcept
2282  {
2283  return m_type == value_t::object;
2284  }
2285 
2300  bool is_array() const noexcept
2301  {
2302  return m_type == value_t::array;
2303  }
2304 
2319  bool is_string() const noexcept
2320  {
2321  return m_type == value_t::string;
2322  }
2323 
2343  bool is_discarded() const noexcept
2344  {
2345  return m_type == value_t::discarded;
2346  }
2347 
2363  operator value_t() const noexcept
2364  {
2365  return m_type;
2366  }
2367 
2369 
2370  private:
2372  // value access //
2374 
2376  template <class T, typename
2377  std::enable_if<
2378  std::is_convertible<typename object_t::key_type, typename T::key_type>::value and
2379  std::is_convertible<basic_json_t, typename T::mapped_type>::value
2380  , int>::type = 0>
2381  T get_impl(T*) const
2382  {
2383  if (is_object())
2384  {
2385  assert(m_value.object != nullptr);
2386  return T(m_value.object->begin(), m_value.object->end());
2387  }
2388  else
2389  {
2390  throw std::domain_error("type must be object, but is " + type_name());
2391  }
2392  }
2393 
2395  object_t get_impl(object_t*) const
2396  {
2397  if (is_object())
2398  {
2399  assert(m_value.object != nullptr);
2400  return *(m_value.object);
2401  }
2402  else
2403  {
2404  throw std::domain_error("type must be object, but is " + type_name());
2405  }
2406  }
2407 
2409  template <class T, typename
2410  std::enable_if<
2411  std::is_convertible<basic_json_t, typename T::value_type>::value and
2412  not std::is_same<basic_json_t, typename T::value_type>::value and
2413  not std::is_arithmetic<T>::value and
2414  not std::is_convertible<std::string, T>::value and
2415  not has_mapped_type<T>::value
2416  , int>::type = 0>
2417  T get_impl(T*) const
2418  {
2419  if (is_array())
2420  {
2421  T to_vector;
2422  assert(m_value.array != nullptr);
2423  std::transform(m_value.array->begin(), m_value.array->end(),
2424  std::inserter(to_vector, to_vector.end()), [](basic_json i)
2425  {
2426  return i.get<typename T::value_type>();
2427  });
2428  return to_vector;
2429  }
2430  else
2431  {
2432  throw std::domain_error("type must be array, but is " + type_name());
2433  }
2434  }
2435 
2437  template <class T, typename
2438  std::enable_if<
2439  std::is_convertible<basic_json_t, T>::value and
2440  not std::is_same<basic_json_t, T>::value
2441  , int>::type = 0>
2442  std::vector<T> get_impl(std::vector<T>*) const
2443  {
2444  if (is_array())
2445  {
2446  std::vector<T> to_vector;
2447  assert(m_value.array != nullptr);
2448  to_vector.reserve(m_value.array->size());
2449  std::transform(m_value.array->begin(), m_value.array->end(),
2450  std::inserter(to_vector, to_vector.end()), [](basic_json i)
2451  {
2452  return i.get<T>();
2453  });
2454  return to_vector;
2455  }
2456  else
2457  {
2458  throw std::domain_error("type must be array, but is " + type_name());
2459  }
2460  }
2461 
2463  template <class T, typename
2464  std::enable_if<
2465  std::is_same<basic_json, typename T::value_type>::value and
2466  not has_mapped_type<T>::value
2467  , int>::type = 0>
2468  T get_impl(T*) const
2469  {
2470  if (is_array())
2471  {
2472  assert(m_value.array != nullptr);
2473  return T(m_value.array->begin(), m_value.array->end());
2474  }
2475  else
2476  {
2477  throw std::domain_error("type must be array, but is " + type_name());
2478  }
2479  }
2480 
2482  array_t get_impl(array_t*) const
2483  {
2484  if (is_array())
2485  {
2486  assert(m_value.array != nullptr);
2487  return *(m_value.array);
2488  }
2489  else
2490  {
2491  throw std::domain_error("type must be array, but is " + type_name());
2492  }
2493  }
2494 
2496  template <typename T, typename
2497  std::enable_if<
2498  std::is_convertible<string_t, T>::value
2499  , int>::type = 0>
2500  T get_impl(T*) const
2501  {
2502  if (is_string())
2503  {
2504  assert(m_value.string != nullptr);
2505  return *m_value.string;
2506  }
2507  else
2508  {
2509  throw std::domain_error("type must be string, but is " + type_name());
2510  }
2511  }
2512 
2514  template<typename T, typename
2515  std::enable_if<
2516  std::is_arithmetic<T>::value
2517  , int>::type = 0>
2518  T get_impl(T*) const
2519  {
2520  switch (m_type)
2521  {
2522  case value_t::number_integer:
2523  {
2524  return static_cast<T>(m_value.number_integer);
2525  }
2526 
2527  case value_t::number_unsigned:
2528  {
2529  return static_cast<T>(m_value.number_unsigned);
2530  }
2531 
2532  case value_t::number_float:
2533  {
2534  return static_cast<T>(m_value.number_float);
2535  }
2536 
2537  default:
2538  {
2539  throw std::domain_error("type must be number, but is " + type_name());
2540  }
2541  }
2542  }
2543 
2545  boolean_t get_impl(boolean_t*) const
2546  {
2547  if (is_boolean())
2548  {
2549  return m_value.boolean;
2550  }
2551  else
2552  {
2553  throw std::domain_error("type must be boolean, but is " + type_name());
2554  }
2555  }
2556 
2558  object_t* get_impl_ptr(object_t*) noexcept
2559  {
2560  return is_object() ? m_value.object : nullptr;
2561  }
2562 
2564  const object_t* get_impl_ptr(const object_t*) const noexcept
2565  {
2566  return is_object() ? m_value.object : nullptr;
2567  }
2568 
2570  array_t* get_impl_ptr(array_t*) noexcept
2571  {
2572  return is_array() ? m_value.array : nullptr;
2573  }
2574 
2576  const array_t* get_impl_ptr(const array_t*) const noexcept
2577  {
2578  return is_array() ? m_value.array : nullptr;
2579  }
2580 
2582  string_t* get_impl_ptr(string_t*) noexcept
2583  {
2584  return is_string() ? m_value.string : nullptr;
2585  }
2586 
2588  const string_t* get_impl_ptr(const string_t*) const noexcept
2589  {
2590  return is_string() ? m_value.string : nullptr;
2591  }
2592 
2594  boolean_t* get_impl_ptr(boolean_t*) noexcept
2595  {
2596  return is_boolean() ? &m_value.boolean : nullptr;
2597  }
2598 
2600  const boolean_t* get_impl_ptr(const boolean_t*) const noexcept
2601  {
2602  return is_boolean() ? &m_value.boolean : nullptr;
2603  }
2604 
2606  number_integer_t* get_impl_ptr(number_integer_t*) noexcept
2607  {
2608  return is_number_integer() ? &m_value.number_integer : nullptr;
2609  }
2610 
2612  const number_integer_t* get_impl_ptr(const number_integer_t*) const noexcept
2613  {
2614  return is_number_integer() ? &m_value.number_integer : nullptr;
2615  }
2616 
2618  number_unsigned_t* get_impl_ptr(number_unsigned_t*) noexcept
2619  {
2620  return is_number_unsigned() ? &m_value.number_unsigned : nullptr;
2621  }
2622 
2624  const number_unsigned_t* get_impl_ptr(const number_unsigned_t*) const noexcept
2625  {
2626  return is_number_unsigned() ? &m_value.number_unsigned : nullptr;
2627  }
2628 
2630  number_float_t* get_impl_ptr(number_float_t*) noexcept
2631  {
2632  return is_number_float() ? &m_value.number_float : nullptr;
2633  }
2634 
2636  const number_float_t* get_impl_ptr(const number_float_t*) const noexcept
2637  {
2638  return is_number_float() ? &m_value.number_float : nullptr;
2639  }
2640 
2652  template<typename ReferenceType, typename ThisType>
2653  static ReferenceType get_ref_impl(ThisType& obj)
2654  {
2655  // delegate the call to get_ptr<>()
2656  using PointerType = typename std::add_pointer<ReferenceType>::type;
2657  auto ptr = obj.template get_ptr<PointerType>();
2658 
2659  if (ptr != nullptr)
2660  {
2661  return *ptr;
2662  }
2663  else
2664  {
2665  throw std::domain_error("incompatible ReferenceType for get_ref, actual type is " +
2666  obj.type_name());
2667  }
2668  }
2669 
2670  public:
2671 
2674 
2708  template<typename ValueType, typename
2709  std::enable_if<
2710  not std::is_pointer<ValueType>::value
2711  , int>::type = 0>
2712  ValueType get() const
2713  {
2714  return get_impl(static_cast<ValueType*>(nullptr));
2715  }
2716 
2743  template<typename PointerType, typename
2744  std::enable_if<
2745  std::is_pointer<PointerType>::value
2746  , int>::type = 0>
2747  PointerType get() noexcept
2748  {
2749  // delegate the call to get_ptr
2750  return get_ptr<PointerType>();
2751  }
2752 
2757  template<typename PointerType, typename
2758  std::enable_if<
2759  std::is_pointer<PointerType>::value
2760  , int>::type = 0>
2761  const PointerType get() const noexcept
2762  {
2763  // delegate the call to get_ptr
2764  return get_ptr<PointerType>();
2765  }
2766 
2792  template<typename PointerType, typename
2793  std::enable_if<
2794  std::is_pointer<PointerType>::value
2795  , int>::type = 0>
2796  PointerType get_ptr() noexcept
2797  {
2798  // delegate the call to get_impl_ptr<>()
2799  return get_impl_ptr(static_cast<PointerType>(nullptr));
2800  }
2801 
2806  template<typename PointerType, typename
2807  std::enable_if<
2808  std::is_pointer<PointerType>::value
2809  and std::is_const<typename std::remove_pointer<PointerType>::type>::value
2810  , int>::type = 0>
2811  const PointerType get_ptr() const noexcept
2812  {
2813  // delegate the call to get_impl_ptr<>() const
2814  return get_impl_ptr(static_cast<const PointerType>(nullptr));
2815  }
2816 
2843  template<typename ReferenceType, typename
2844  std::enable_if<
2845  std::is_reference<ReferenceType>::value
2846  , int>::type = 0>
2847  ReferenceType get_ref()
2848  {
2849  // delegate call to get_ref_impl
2850  return get_ref_impl<ReferenceType>(*this);
2851  }
2852 
2857  template<typename ReferenceType, typename
2858  std::enable_if<
2859  std::is_reference<ReferenceType>::value
2860  and std::is_const<typename std::remove_reference<ReferenceType>::type>::value
2861  , int>::type = 0>
2862  ReferenceType get_ref() const
2863  {
2864  // delegate call to get_ref_impl
2865  return get_ref_impl<ReferenceType>(*this);
2866  }
2867 
2896  template < typename ValueType, typename
2897  std::enable_if <
2898  not std::is_pointer<ValueType>::value
2899  and not std::is_same<ValueType, typename string_t::value_type>::value
2900 #ifndef _MSC_VER // Fix for issue #167 operator<< abiguity under VS2015
2901  and not std::is_same<ValueType, std::initializer_list<typename string_t::value_type>>::value
2902 #endif
2903  , int >::type = 0 >
2904  operator ValueType() const
2905  {
2906  // delegate the call to get<>() const
2907  return get<ValueType>();
2908  }
2909 
2911 
2912 
2914  // element access //
2916 
2919 
2943  {
2944  // at only works for arrays
2945  if (is_array())
2946  {
2947  try
2948  {
2949  assert(m_value.array != nullptr);
2950  return m_value.array->at(idx);
2951  }
2952  catch (std::out_of_range&)
2953  {
2954  // create better exception explanation
2955  throw std::out_of_range("array index " + std::to_string(idx) + " is out of range");
2956  }
2957  }
2958  else
2959  {
2960  throw std::domain_error("cannot use at() with " + type_name());
2961  }
2962  }
2963 
2987  {
2988  // at only works for arrays
2989  if (is_array())
2990  {
2991  try
2992  {
2993  assert(m_value.array != nullptr);
2994  return m_value.array->at(idx);
2995  }
2996  catch (std::out_of_range&)
2997  {
2998  // create better exception explanation
2999  throw std::out_of_range("array index " + std::to_string(idx) + " is out of range");
3000  }
3001  }
3002  else
3003  {
3004  throw std::domain_error("cannot use at() with " + type_name());
3005  }
3006  }
3007 
3034  reference at(const typename object_t::key_type& key)
3035  {
3036  // at only works for objects
3037  if (is_object())
3038  {
3039  try
3040  {
3041  assert(m_value.object != nullptr);
3042  return m_value.object->at(key);
3043  }
3044  catch (std::out_of_range&)
3045  {
3046  // create better exception explanation
3047  throw std::out_of_range("key '" + key + "' not found");
3048  }
3049  }
3050  else
3051  {
3052  throw std::domain_error("cannot use at() with " + type_name());
3053  }
3054  }
3055 
3082  const_reference at(const typename object_t::key_type& key) const
3083  {
3084  // at only works for objects
3085  if (is_object())
3086  {
3087  try
3088  {
3089  assert(m_value.object != nullptr);
3090  return m_value.object->at(key);
3091  }
3092  catch (std::out_of_range&)
3093  {
3094  // create better exception explanation
3095  throw std::out_of_range("key '" + key + "' not found");
3096  }
3097  }
3098  else
3099  {
3100  throw std::domain_error("cannot use at() with " + type_name());
3101  }
3102  }
3103 
3130  {
3131  // implicitly convert null to object
3132  if (is_null())
3133  {
3134  m_type = value_t::array;
3135  m_value.array = create<array_t>();
3136  }
3137 
3138  // [] only works for arrays
3139  if (is_array())
3140  {
3141  assert(m_value.array != nullptr);
3142  for (size_t i = m_value.array->size(); i <= idx; ++i)
3143  {
3144  m_value.array->push_back(basic_json());
3145  }
3146 
3147  return m_value.array->operator[](idx);
3148  }
3149  else
3150  {
3151  throw std::domain_error("cannot use operator[] with " + type_name());
3152  }
3153  }
3154 
3175  {
3176  // at only works for arrays
3177  if (is_array())
3178  {
3179  assert(m_value.array != nullptr);
3180  return m_value.array->operator[](idx);
3181  }
3182  else
3183  {
3184  throw std::domain_error("cannot use operator[] with " + type_name());
3185  }
3186  }
3187 
3215  reference operator[](const typename object_t::key_type& key)
3216  {
3217  // implicitly convert null to object
3218  if (is_null())
3219  {
3220  m_type = value_t::object;
3221  m_value.object = create<object_t>();
3222  }
3223 
3224  // [] only works for objects
3225  if (is_object())
3226  {
3227  assert(m_value.object != nullptr);
3228  return m_value.object->operator[](key);
3229  }
3230  else
3231  {
3232  throw std::domain_error("cannot use operator[] with " + type_name());
3233  }
3234  }
3235 
3263  const_reference operator[](const typename object_t::key_type& key) const
3264  {
3265  // [] only works for objects
3266  if (is_object())
3267  {
3268  assert(m_value.object != nullptr);
3269  assert(m_value.object->find(key) != m_value.object->end());
3270  return m_value.object->find(key)->second;
3271  }
3272  else
3273  {
3274  throw std::domain_error("cannot use operator[] with " + type_name());
3275  }
3276  }
3277 
3305  template<typename T, std::size_t n>
3306  reference operator[](T * (&key)[n])
3307  {
3308  return operator[](static_cast<const T>(key));
3309  }
3310 
3340  template<typename T, std::size_t n>
3341  const_reference operator[](T * (&key)[n]) const
3342  {
3343  return operator[](static_cast<const T>(key));
3344  }
3345 
3373  template<typename T>
3375  {
3376  // implicitly convert null to object
3377  if (is_null())
3378  {
3379  m_type = value_t::object;
3380  m_value = value_t::object;
3381  }
3382 
3383  // at only works for objects
3384  if (is_object())
3385  {
3386  assert(m_value.object != nullptr);
3387  return m_value.object->operator[](key);
3388  }
3389  else
3390  {
3391  throw std::domain_error("cannot use operator[] with " + type_name());
3392  }
3393  }
3394 
3422  template<typename T>
3424  {
3425  // at only works for objects
3426  if (is_object())
3427  {
3428  assert(m_value.object != nullptr);
3429  assert(m_value.object->find(key) != m_value.object->end());
3430  return m_value.object->find(key)->second;
3431  }
3432  else
3433  {
3434  throw std::domain_error("cannot use operator[] with " + type_name());
3435  }
3436  }
3437 
3486  template <class ValueType, typename
3487  std::enable_if<
3488  std::is_convertible<basic_json_t, ValueType>::value
3489  , int>::type = 0>
3490  ValueType value(const typename object_t::key_type& key, ValueType default_value) const
3491  {
3492  // at only works for objects
3493  if (is_object())
3494  {
3495  // if key is found, return value and given default value otherwise
3496  const auto it = find(key);
3497  if (it != end())
3498  {
3499  return *it;
3500  }
3501  else
3502  {
3503  return default_value;
3504  }
3505  }
3506  else
3507  {
3508  throw std::domain_error("cannot use value() with " + type_name());
3509  }
3510  }
3511 
3516  string_t value(const typename object_t::key_type& key, const char* default_value) const
3517  {
3518  return value(key, string_t(default_value));
3519  }
3520 
3546  {
3547  return *begin();
3548  }
3549 
3554  {
3555  return *cbegin();
3556  }
3557 
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 
4004  {
4005  iterator result(this);
4006  result.set_begin();
4007  return result;
4008  }
4009 
4014  {
4015  return cbegin();
4016  }
4017 
4044  {
4045  const_iterator result(this);
4046  result.set_begin();
4047  return result;
4048  }
4049 
4075  {
4076  iterator result(this);
4077  result.set_end();
4078  return result;
4079  }
4080 
4085  {
4086  return cend();
4087  }
4088 
4115  {
4116  const_iterator result(this);
4117  result.set_end();
4118  return result;
4119  }
4120 
4145  {
4146  return reverse_iterator(end());
4147  }
4148 
4153  {
4154  return crbegin();
4155  }
4156 
4182  {
4183  return reverse_iterator(begin());
4184  }
4185 
4190  {
4191  return crend();
4192  }
4193 
4219  {
4220  return const_reverse_iterator(cend());
4221  }
4222 
4248  {
4249  return const_reverse_iterator(cbegin());
4250  }
4251 
4252  private:
4253  // forward declaration
4254  template<typename IteratorType> class iteration_proxy;
4255 
4256  public:
4268  static iteration_proxy<iterator> iterator_wrapper(reference cont)
4269  {
4270  return iteration_proxy<iterator>(cont);
4271  }
4272 
4276  static iteration_proxy<const_iterator> iterator_wrapper(const_reference cont)
4277  {
4278  return iteration_proxy<const_iterator>(cont);
4279  }
4280 
4282 
4283 
4285  // capacity //
4287 
4290 
4324  bool empty() const noexcept
4325  {
4326  switch (m_type)
4327  {
4328  case value_t::null:
4329  {
4330  // null values are empty
4331  return true;
4332  }
4333 
4334  case value_t::array:
4335  {
4336  assert(m_value.array != nullptr);
4337  return m_value.array->empty();
4338  }
4339 
4340  case value_t::object:
4341  {
4342  assert(m_value.object != nullptr);
4343  return m_value.object->empty();
4344  }
4345 
4346  default:
4347  {
4348  // all other types are nonempty
4349  return false;
4350  }
4351  }
4352  }
4353 
4387  size_type size() const noexcept
4388  {
4389  switch (m_type)
4390  {
4391  case value_t::null:
4392  {
4393  // null values are empty
4394  return 0;
4395  }
4396 
4397  case value_t::array:
4398  {
4399  assert(m_value.array != nullptr);
4400  return m_value.array->size();
4401  }
4402 
4403  case value_t::object:
4404  {
4405  assert(m_value.object != nullptr);
4406  return m_value.object->size();
4407  }
4408 
4409  default:
4410  {
4411  // all other types have size 1
4412  return 1;
4413  }
4414  }
4415  }
4416 
4453  size_type max_size() const noexcept
4454  {
4455  switch (m_type)
4456  {
4457  case value_t::array:
4458  {
4459  assert(m_value.array != nullptr);
4460  return m_value.array->max_size();
4461  }
4462 
4463  case value_t::object:
4464  {
4465  assert(m_value.object != nullptr);
4466  return m_value.object->max_size();
4467  }
4468 
4469  default:
4470  {
4471  // all other types have max_size() == size()
4472  return size();
4473  }
4474  }
4475  }
4476 
4478 
4479 
4481  // modifiers //
4483 
4486 
4512  void clear() noexcept
4513  {
4514  switch (m_type)
4515  {
4516  case value_t::number_integer:
4517  {
4518  m_value.number_integer = 0;
4519  break;
4520  }
4521 
4522  case value_t::number_unsigned:
4523  {
4524  m_value.number_unsigned = 0;
4525  break;
4526  }
4527 
4528  case value_t::number_float:
4529  {
4530  m_value.number_float = 0.0;
4531  break;
4532  }
4533 
4534  case value_t::boolean:
4535  {
4536  m_value.boolean = false;
4537  break;
4538  }
4539 
4540  case value_t::string:
4541  {
4542  assert(m_value.string != nullptr);
4543  m_value.string->clear();
4544  break;
4545  }
4546 
4547  case value_t::array:
4548  {
4549  assert(m_value.array != nullptr);
4550  m_value.array->clear();
4551  break;
4552  }
4553 
4554  case value_t::object:
4555  {
4556  assert(m_value.object != nullptr);
4557  m_value.object->clear();
4558  break;
4559  }
4560 
4561  default:
4562  {
4563  break;
4564  }
4565  }
4566  }
4567 
4588  void push_back(basic_json&& val)
4589  {
4590  // push_back only works for null objects or arrays
4591  if (not(is_null() or is_array()))
4592  {
4593  throw std::domain_error("cannot use push_back() with " + type_name());
4594  }
4595 
4596  // transform null object into an array
4597  if (is_null())
4598  {
4599  m_type = value_t::array;
4600  m_value = value_t::array;
4601  }
4602 
4603  // add element to array (move semantics)
4604  assert(m_value.array != nullptr);
4605  m_value.array->push_back(std::move(val));
4606  // invalidate object
4607  val.m_type = value_t::null;
4608  }
4609 
4614  reference operator+=(basic_json&& val)
4615  {
4616  push_back(std::move(val));
4617  return *this;
4618  }
4619 
4624  void push_back(const basic_json& val)
4625  {
4626  // push_back only works for null objects or arrays
4627  if (not(is_null() or is_array()))
4628  {
4629  throw std::domain_error("cannot use push_back() with " + type_name());
4630  }
4631 
4632  // transform null object into an array
4633  if (is_null())
4634  {
4635  m_type = value_t::array;
4636  m_value = value_t::array;
4637  }
4638 
4639  // add element to array
4640  assert(m_value.array != nullptr);
4641  m_value.array->push_back(val);
4642  }
4643 
4648  reference operator+=(const basic_json& val)
4649  {
4650  push_back(val);
4651  return *this;
4652  }
4653 
4674  void push_back(const typename object_t::value_type& val)
4675  {
4676  // push_back only works for null objects or objects
4677  if (not(is_null() or is_object()))
4678  {
4679  throw std::domain_error("cannot use push_back() with " + type_name());
4680  }
4681 
4682  // transform null object into an object
4683  if (is_null())
4684  {
4685  m_type = value_t::object;
4686  m_value = value_t::object;
4687  }
4688 
4689  // add element to array
4690  assert(m_value.object != nullptr);
4691  m_value.object->insert(val);
4692  }
4693 
4698  reference operator+=(const typename object_t::value_type& val)
4699  {
4700  push_back(val);
4701  return operator[](val.first);
4702  }
4703 
4726  iterator insert(const_iterator pos, const basic_json& val)
4727  {
4728  // insert only works for arrays
4729  if (is_array())
4730  {
4731  // check if iterator pos fits to this JSON value
4732  if (pos.m_object != this)
4733  {
4734  throw std::domain_error("iterator does not fit current value");
4735  }
4736 
4737  // insert to array and return iterator
4738  iterator result(this);
4739  assert(m_value.array != nullptr);
4740  result.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator, val);
4741  return result;
4742  }
4743  else
4744  {
4745  throw std::domain_error("cannot use insert() with " + type_name());
4746  }
4747  }
4748 
4753  iterator insert(const_iterator pos, basic_json&& val)
4754  {
4755  return insert(pos, val);
4756  }
4757 
4782  iterator insert(const_iterator pos, size_type cnt, const basic_json& val)
4783  {
4784  // insert only works for arrays
4785  if (is_array())
4786  {
4787  // check if iterator pos fits to this JSON value
4788  if (pos.m_object != this)
4789  {
4790  throw std::domain_error("iterator does not fit current value");
4791  }
4792 
4793  // insert to array and return iterator
4794  iterator result(this);
4795  assert(m_value.array != nullptr);
4796  result.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator, cnt, val);
4797  return result;
4798  }
4799  else
4800  {
4801  throw std::domain_error("cannot use insert() with " + type_name());
4802  }
4803  }
4804 
4836  {
4837  // insert only works for arrays
4838  if (not is_array())
4839  {
4840  throw std::domain_error("cannot use insert() with " + type_name());
4841  }
4842 
4843  // check if iterator pos fits to this JSON value
4844  if (pos.m_object != this)
4845  {
4846  throw std::domain_error("iterator does not fit current value");
4847  }
4848 
4849  if (first.m_object != last.m_object)
4850  {
4851  throw std::domain_error("iterators do not fit");
4852  }
4853 
4854  if (first.m_object == this or last.m_object == this)
4855  {
4856  throw std::domain_error("passed iterators may not belong to container");
4857  }
4858 
4859  // insert to array and return iterator
4860  iterator result(this);
4861  assert(m_value.array != nullptr);
4862  result.m_it.array_iterator = m_value.array->insert(
4863  pos.m_it.array_iterator,
4864  first.m_it.array_iterator,
4865  last.m_it.array_iterator);
4866  return result;
4867  }
4868 
4893  iterator insert(const_iterator pos, std::initializer_list<basic_json> ilist)
4894  {
4895  // insert only works for arrays
4896  if (not is_array())
4897  {
4898  throw std::domain_error("cannot use insert() with " + type_name());
4899  }
4900 
4901  // check if iterator pos fits to this JSON value
4902  if (pos.m_object != this)
4903  {
4904  throw std::domain_error("iterator does not fit current value");
4905  }
4906 
4907  // insert to array and return iterator
4908  iterator result(this);
4909  assert(m_value.array != nullptr);
4910  result.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator, ilist);
4911  return result;
4912  }
4913 
4931  void swap(reference other) noexcept (
4932  std::is_nothrow_move_constructible<value_t>::value and
4933  std::is_nothrow_move_assignable<value_t>::value and
4934  std::is_nothrow_move_constructible<json_value>::value and
4935  std::is_nothrow_move_assignable<json_value>::value
4936  )
4937  {
4938  std::swap(m_type, other.m_type);
4939  std::swap(m_value, other.m_value);
4940  }
4941 
4962  void swap(array_t& other)
4963  {
4964  // swap only works for arrays
4965  if (is_array())
4966  {
4967  assert(m_value.array != nullptr);
4968  std::swap(*(m_value.array), other);
4969  }
4970  else
4971  {
4972  throw std::domain_error("cannot use swap() with " + type_name());
4973  }
4974  }
4975 
4996  void swap(object_t& other)
4997  {
4998  // swap only works for objects
4999  if (is_object())
5000  {
5001  assert(m_value.object != nullptr);
5002  std::swap(*(m_value.object), other);
5003  }
5004  else
5005  {
5006  throw std::domain_error("cannot use swap() with " + type_name());
5007  }
5008  }
5009 
5030  void swap(string_t& other)
5031  {
5032  // swap only works for strings
5033  if (is_string())
5034  {
5035  assert(m_value.string != nullptr);
5036  std::swap(*(m_value.string), other);
5037  }
5038  else
5039  {
5040  throw std::domain_error("cannot use swap() with " + type_name());
5041  }
5042  }
5043 
5045 
5046 
5048  // lexicographical comparison operators //
5050 
5053 
5054  private:
5064  friend bool operator<(const value_t lhs, const value_t rhs)
5065  {
5066  static constexpr std::array<uint8_t, 8> order = {{
5067  0, // null
5068  3, // object
5069  4, // array
5070  5, // string
5071  1, // boolean
5072  2, // integer
5073  2, // unsigned
5074  2, // float
5075  }
5076  };
5077 
5078  // discarded values are not comparable
5079  if (lhs == value_t::discarded or rhs == value_t::discarded)
5080  {
5081  return false;
5082  }
5083 
5084  return order[static_cast<std::size_t>(lhs)] < order[static_cast<std::size_t>(rhs)];
5085  }
5086 
5087  public:
5111  friend bool operator==(const_reference lhs, const_reference rhs) noexcept
5112  {
5113  const auto lhs_type = lhs.type();
5114  const auto rhs_type = rhs.type();
5115 
5116  if (lhs_type == rhs_type)
5117  {
5118  switch (lhs_type)
5119  {
5120  case value_t::array:
5121  {
5122  assert(lhs.m_value.array != nullptr);
5123  assert(rhs.m_value.array != nullptr);
5124  return *lhs.m_value.array == *rhs.m_value.array;
5125  }
5126  case value_t::object:
5127  {
5128  assert(lhs.m_value.object != nullptr);
5129  assert(rhs.m_value.object != nullptr);
5130  return *lhs.m_value.object == *rhs.m_value.object;
5131  }
5132  case value_t::null:
5133  {
5134  return true;
5135  }
5136  case value_t::string:
5137  {
5138  assert(lhs.m_value.string != nullptr);
5139  assert(rhs.m_value.string != nullptr);
5140  return *lhs.m_value.string == *rhs.m_value.string;
5141  }
5142  case value_t::boolean:
5143  {
5144  return lhs.m_value.boolean == rhs.m_value.boolean;
5145  }
5146  case value_t::number_integer:
5147  {
5148  return lhs.m_value.number_integer == rhs.m_value.number_integer;
5149  }
5150  case value_t::number_unsigned:
5151  {
5152  return lhs.m_value.number_unsigned == rhs.m_value.number_unsigned;
5153  }
5154  case value_t::number_float:
5155  {
5156  return lhs.m_value.number_float == rhs.m_value.number_float;
5157  }
5158  default:
5159  {
5160  return false;
5161  }
5162  }
5163  }
5164  else if (lhs_type == value_t::number_integer and rhs_type == value_t::number_float)
5165  {
5166  return static_cast<number_float_t>(lhs.m_value.number_integer) == rhs.m_value.number_float;
5167  }
5168  else if (lhs_type == value_t::number_float and rhs_type == value_t::number_integer)
5169  {
5170  return lhs.m_value.number_float == static_cast<number_float_t>(rhs.m_value.number_integer);
5171  }
5172  else if (lhs_type == value_t::number_unsigned and rhs_type == value_t::number_float)
5173  {
5174  return static_cast<number_float_t>(lhs.m_value.number_unsigned) == rhs.m_value.number_float;
5175  }
5176  else if (lhs_type == value_t::number_float and rhs_type == value_t::number_unsigned)
5177  {
5178  return lhs.m_value.number_float == static_cast<number_float_t>(rhs.m_value.number_unsigned);
5179  }
5180  else if (lhs_type == value_t::number_unsigned and rhs_type == value_t::number_integer)
5181  {
5182  return static_cast<number_integer_t>(lhs.m_value.number_unsigned) == rhs.m_value.number_integer;
5183  }
5184  else if (lhs_type == value_t::number_integer and rhs_type == value_t::number_unsigned)
5185  {
5186  return lhs.m_value.number_integer == static_cast<number_integer_t>(rhs.m_value.number_unsigned);
5187  }
5188 
5189  return false;
5190  }
5191 
5210  friend bool operator==(const_reference v, std::nullptr_t) noexcept
5211  {
5212  return v.is_null();
5213  }
5214 
5219  friend bool operator==(std::nullptr_t, const_reference v) noexcept
5220  {
5221  return v.is_null();
5222  }
5223 
5240  friend bool operator!=(const_reference lhs, const_reference rhs) noexcept
5241  {
5242  return not (lhs == rhs);
5243  }
5244 
5263  friend bool operator!=(const_reference v, std::nullptr_t) noexcept
5264  {
5265  return not v.is_null();
5266  }
5267 
5272  friend bool operator!=(std::nullptr_t, const_reference v) noexcept
5273  {
5274  return not v.is_null();
5275  }
5276 
5301  friend bool operator<(const_reference lhs, const_reference rhs) noexcept
5302  {
5303  const auto lhs_type = lhs.type();
5304  const auto rhs_type = rhs.type();
5305 
5306  if (lhs_type == rhs_type)
5307  {
5308  switch (lhs_type)
5309  {
5310  case value_t::array:
5311  {
5312  assert(lhs.m_value.array != nullptr);
5313  assert(rhs.m_value.array != nullptr);
5314  return *lhs.m_value.array < *rhs.m_value.array;
5315  }
5316  case value_t::object:
5317  {
5318  assert(lhs.m_value.object != nullptr);
5319  assert(rhs.m_value.object != nullptr);
5320  return *lhs.m_value.object < *rhs.m_value.object;
5321  }
5322  case value_t::null:
5323  {
5324  return false;
5325  }
5326  case value_t::string:
5327  {
5328  assert(lhs.m_value.string != nullptr);
5329  assert(rhs.m_value.string != nullptr);
5330  return *lhs.m_value.string < *rhs.m_value.string;
5331  }
5332  case value_t::boolean:
5333  {
5334  return lhs.m_value.boolean < rhs.m_value.boolean;
5335  }
5336  case value_t::number_integer:
5337  {
5338  return lhs.m_value.number_integer < rhs.m_value.number_integer;
5339  }
5340  case value_t::number_unsigned:
5341  {
5342  return lhs.m_value.number_unsigned < rhs.m_value.number_unsigned;
5343  }
5344  case value_t::number_float:
5345  {
5346  return lhs.m_value.number_float < rhs.m_value.number_float;
5347  }
5348  default:
5349  {
5350  return false;
5351  }
5352  }
5353  }
5354  else if (lhs_type == value_t::number_integer and rhs_type == value_t::number_float)
5355  {
5356  return static_cast<number_float_t>(lhs.m_value.number_integer) < rhs.m_value.number_float;
5357  }
5358  else if (lhs_type == value_t::number_float and rhs_type == value_t::number_integer)
5359  {
5360  return lhs.m_value.number_float < static_cast<number_float_t>(rhs.m_value.number_integer);
5361  }
5362  else if (lhs_type == value_t::number_unsigned and rhs_type == value_t::number_float)
5363  {
5364  return static_cast<number_float_t>(lhs.m_value.number_unsigned) < rhs.m_value.number_float;
5365  }
5366  else if (lhs_type == value_t::number_float and rhs_type == value_t::number_unsigned)
5367  {
5368  return lhs.m_value.number_float < static_cast<number_float_t>(rhs.m_value.number_unsigned);
5369  }
5370  else if (lhs_type == value_t::number_integer and rhs_type == value_t::number_unsigned)
5371  {
5372  return lhs.m_value.number_integer < static_cast<number_integer_t>(rhs.m_value.number_unsigned);
5373  }
5374  else if (lhs_type == value_t::number_unsigned and rhs_type == value_t::number_integer)
5375  {
5376  return static_cast<number_integer_t>(lhs.m_value.number_unsigned) < rhs.m_value.number_integer;
5377  }
5378 
5379  // We only reach this line if we cannot compare values. In that case,
5380  // we compare types. Note we have to call the operator explicitly,
5381  // because MSVC has problems otherwise.
5382  return operator<(lhs_type, rhs_type);
5383  }
5384 
5402  friend bool operator<=(const_reference lhs, const_reference rhs) noexcept
5403  {
5404  return not (rhs < lhs);
5405  }
5406 
5424  friend bool operator>(const_reference lhs, const_reference rhs) noexcept
5425  {
5426  return not (lhs <= rhs);
5427  }
5428 
5446  friend bool operator>=(const_reference lhs, const_reference rhs) noexcept
5447  {
5448  return not (lhs < rhs);
5449  }
5450 
5452 
5453 
5455  // serialization //
5457 
5460 
5483  friend std::ostream& operator<<(std::ostream& o, const basic_json& j)
5484  {
5485  // read width member and use it as indentation parameter if nonzero
5486  const bool pretty_print = (o.width() > 0);
5487  const auto indentation = (pretty_print ? o.width() : 0);
5488 
5489  // reset width to 0 for subsequent calls to this stream
5490  o.width(0);
5491 
5492  // do the actual serialization
5493  j.dump(o, pretty_print, static_cast<unsigned int>(indentation));
5494  return o;
5495  }
5496 
5501  friend std::ostream& operator>>(const basic_json& j, std::ostream& o)
5502  {
5503  return o << j;
5504  }
5505 
5507 
5508 
5510  // deserialization //
5512 
5515 
5540  static basic_json parse(const string_t& s, parser_callback_t cb = nullptr)
5541  {
5542  return parser(s, cb).parse();
5543  }
5544 
5569  static basic_json parse(std::istream& i, parser_callback_t cb = nullptr)
5570  {
5571  return parser(i, cb).parse();
5572  }
5573 
5577  static basic_json parse(std::istream&& i, parser_callback_t cb = nullptr)
5578  {
5579  return parser(i, cb).parse();
5580  }
5581 
5605  friend std::istream& operator<<(basic_json& j, std::istream& i)
5606  {
5607  j = parser(i).parse();
5608  return i;
5609  }
5610 
5615  friend std::istream& operator>>(std::istream& i, basic_json& j)
5616  {
5617  j = parser(i).parse();
5618  return i;
5619  }
5620 
5622 
5623 
5624  private:
5626  // convenience functions //
5628 
5630  string_t type_name() const
5631  {
5632  switch (m_type)
5633  {
5634  case value_t::null:
5635  return "null";
5636  case value_t::object:
5637  return "object";
5638  case value_t::array:
5639  return "array";
5640  case value_t::string:
5641  return "string";
5642  case value_t::boolean:
5643  return "boolean";
5644  case value_t::discarded:
5645  return "discarded";
5646  default:
5647  return "number";
5648  }
5649  }
5650 
5659  static std::size_t extra_space(const string_t& s) noexcept
5660  {
5661  std::size_t result = 0;
5662 
5663  for (const auto& c : s)
5664  {
5665  switch (c)
5666  {
5667  case '"':
5668  case '\\':
5669  case '\b':
5670  case '\f':
5671  case '\n':
5672  case '\r':
5673  case '\t':
5674  {
5675  // from c (1 byte) to \x (2 bytes)
5676  result += 1;
5677  break;
5678  }
5679 
5680  default:
5681  {
5682  if (c >= 0x00 and c <= 0x1f)
5683  {
5684  // from c (1 byte) to \uxxxx (6 bytes)
5685  result += 5;
5686  }
5687  break;
5688  }
5689  }
5690  }
5691 
5692  return result;
5693  }
5694 
5708  static string_t escape_string(const string_t& s) noexcept
5709  {
5710  const auto space = extra_space(s);
5711  if (space == 0)
5712  {
5713  return s;
5714  }
5715 
5716  // create a result string of necessary size
5717  string_t result(s.size() + space, '\\');
5718  std::size_t pos = 0;
5719 
5720  for (const auto& c : s)
5721  {
5722  switch (c)
5723  {
5724  // quotation mark (0x22)
5725  case '"':
5726  {
5727  result[pos + 1] = '"';
5728  pos += 2;
5729  break;
5730  }
5731 
5732  // reverse solidus (0x5c)
5733  case '\\':
5734  {
5735  // nothing to change
5736  pos += 2;
5737  break;
5738  }
5739 
5740  // backspace (0x08)
5741  case '\b':
5742  {
5743  result[pos + 1] = 'b';
5744  pos += 2;
5745  break;
5746  }
5747 
5748  // formfeed (0x0c)
5749  case '\f':
5750  {
5751  result[pos + 1] = 'f';
5752  pos += 2;
5753  break;
5754  }
5755 
5756  // newline (0x0a)
5757  case '\n':
5758  {
5759  result[pos + 1] = 'n';
5760  pos += 2;
5761  break;
5762  }
5763 
5764  // carriage return (0x0d)
5765  case '\r':
5766  {
5767  result[pos + 1] = 'r';
5768  pos += 2;
5769  break;
5770  }
5771 
5772  // horizontal tab (0x09)
5773  case '\t':
5774  {
5775  result[pos + 1] = 't';
5776  pos += 2;
5777  break;
5778  }
5779 
5780  default:
5781  {
5782  if (c >= 0x00 and c <= 0x1f)
5783  {
5784  // convert a number 0..15 to its hex representation
5785  // (0..f)
5786  auto hexify = [](const char v) -> char
5787  {
5788  return (v < 10) ? ('0' + v) : ('a' + v - 10);
5789  };
5790 
5791  // print character c as \uxxxx
5792  for (const char m :
5793  { 'u', '0', '0', hexify(c >> 4), hexify(c & 0x0f)
5794  })
5795  {
5796  result[++pos] = m;
5797  }
5798 
5799  ++pos;
5800  }
5801  else
5802  {
5803  // all other characters are added as-is
5804  result[pos++] = c;
5805  }
5806  break;
5807  }
5808  }
5809  }
5810 
5811  return result;
5812  }
5813 
5831  void dump(std::ostream& o,
5832  const bool pretty_print,
5833  const unsigned int indent_step,
5834  const unsigned int current_indent = 0) const
5835  {
5836  // variable to hold indentation for recursive calls
5837  unsigned int new_indent = current_indent;
5838 
5839  switch (m_type)
5840  {
5841  case value_t::object:
5842  {
5843  assert(m_value.object != nullptr);
5844 
5845  if (m_value.object->empty())
5846  {
5847  o << "{}";
5848  return;
5849  }
5850 
5851  o << "{";
5852 
5853  // increase indentation
5854  if (pretty_print)
5855  {
5856  new_indent += indent_step;
5857  o << "\n";
5858  }
5859 
5860  for (auto i = m_value.object->cbegin(); i != m_value.object->cend(); ++i)
5861  {
5862  if (i != m_value.object->cbegin())
5863  {
5864  o << (pretty_print ? ",\n" : ",");
5865  }
5866  o << string_t(new_indent, ' ') << "\""
5867  << escape_string(i->first) << "\":"
5868  << (pretty_print ? " " : "");
5869  i->second.dump(o, pretty_print, indent_step, new_indent);
5870  }
5871 
5872  // decrease indentation
5873  if (pretty_print)
5874  {
5875  new_indent -= indent_step;
5876  o << "\n";
5877  }
5878 
5879  o << string_t(new_indent, ' ') + "}";
5880  return;
5881  }
5882 
5883  case value_t::array:
5884  {
5885  assert(m_value.array != nullptr);
5886 
5887  if (m_value.array->empty())
5888  {
5889  o << "[]";
5890  return;
5891  }
5892 
5893  o << "[";
5894 
5895  // increase indentation
5896  if (pretty_print)
5897  {
5898  new_indent += indent_step;
5899  o << "\n";
5900  }
5901 
5902  for (auto i = m_value.array->cbegin(); i != m_value.array->cend(); ++i)
5903  {
5904  if (i != m_value.array->cbegin())
5905  {
5906  o << (pretty_print ? ",\n" : ",");
5907  }
5908  o << string_t(new_indent, ' ');
5909  i->dump(o, pretty_print, indent_step, new_indent);
5910  }
5911 
5912  // decrease indentation
5913  if (pretty_print)
5914  {
5915  new_indent -= indent_step;
5916  o << "\n";
5917  }
5918 
5919  o << string_t(new_indent, ' ') << "]";
5920  return;
5921  }
5922 
5923  case value_t::string:
5924  {
5925  assert(m_value.string != nullptr);
5926  o << string_t("\"") << escape_string(*m_value.string) << "\"";
5927  return;
5928  }
5929 
5930  case value_t::boolean:
5931  {
5932  o << (m_value.boolean ? "true" : "false");
5933  return;
5934  }
5935 
5936  case value_t::number_integer:
5937  {
5938  o << m_value.number_integer;
5939  return;
5940  }
5941 
5942  case value_t::number_unsigned:
5943  {
5944  o << m_value.number_unsigned;
5945  return;
5946  }
5947 
5948  case value_t::number_float:
5949  {
5950  // If the number is an integer then output as a fixed with with
5951  // precision 1 to output "0.0", "1.0" etc as expected for some
5952  // round trip tests otherwise 15 digits of precision allows
5953  // round-trip IEEE 754 string->double->string; to be safe, we
5954  // read this value from
5955  // std::numeric_limits<number_float_t>::digits10
5956  if (std::fmod(m_value.number_float, 1) == 0)
5957  {
5958  o << std::fixed << std::setprecision(1);
5959  }
5960  else
5961  {
5962  // std::defaultfloat not supported in gcc version < 5
5963  o.unsetf(std::ios_base::floatfield);
5964  o << std::setprecision(std::numeric_limits<double>::digits10);
5965  }
5966  o << m_value.number_float;
5967  return;
5968  }
5969 
5970  case value_t::discarded:
5971  {
5972  o << "<discarded>";
5973  return;
5974  }
5975 
5976  case value_t::null:
5977  {
5978  o << "null";
5979  return;
5980  }
5981  }
5982  }
5983 
5984  private:
5986  // member variables //
5988 
5990  value_t m_type = value_t::null;
5991 
5993  json_value m_value = {};
5994 
5995 
5996  private:
5998  // iterators //
6000 
6010  class primitive_iterator_t
6011  {
6012  public:
6014  void set_begin()
6015  {
6016  m_it = begin_value;
6017  }
6018 
6020  void set_end()
6021  {
6022  m_it = end_value;
6023  }
6024 
6026  bool is_begin() const
6027  {
6028  return (m_it == begin_value);
6029  }
6030 
6032  bool is_end() const
6033  {
6034  return (m_it == end_value);
6035  }
6036 
6038  operator difference_type& ()
6039  {
6040  return m_it;
6041  }
6042 
6044  operator difference_type () const
6045  {
6046  return m_it;
6047  }
6048 
6049  private:
6050  static constexpr difference_type begin_value = 0;
6051  static constexpr difference_type end_value = begin_value + 1;
6052 
6054  difference_type m_it = std::numeric_limits<std::ptrdiff_t>::denorm_min();
6055  };
6056 
6064  struct internal_iterator
6065  {
6067  typename object_t::iterator object_iterator;
6069  typename array_t::iterator array_iterator;
6071  primitive_iterator_t primitive_iterator;
6072 
6074  internal_iterator()
6075  : object_iterator(), array_iterator(), primitive_iterator()
6076  {}
6077  };
6078 
6080  template<typename IteratorType>
6081  class iteration_proxy
6082  {
6083  private:
6085  class iteration_proxy_internal
6086  {
6087  private:
6089  IteratorType anchor;
6091  size_t array_index = 0;
6092 
6093  public:
6094  iteration_proxy_internal(IteratorType it)
6095  : anchor(it)
6096  {}
6097 
6099  iteration_proxy_internal& operator*()
6100  {
6101  return *this;
6102  }
6103 
6105  iteration_proxy_internal& operator++()
6106  {
6107  ++anchor;
6108  ++array_index;
6109 
6110  return *this;
6111  }
6112 
6114  bool operator!= (const iteration_proxy_internal& o) const
6115  {
6116  return anchor != o.anchor;
6117  }
6118 
6120  typename basic_json::string_t key() const
6121  {
6122  assert(anchor.m_object != nullptr);
6123 
6124  switch (anchor.m_object->type())
6125  {
6126  // use integer array index as key
6127  case value_t::array:
6128  {
6129  return std::to_string(array_index);
6130  }
6131 
6132  // use key from the object
6133  case value_t::object:
6134  {
6135  return anchor.key();
6136  }
6137 
6138  // use an empty key for all primitive types
6139  default:
6140  {
6141  return "";
6142  }
6143  }
6144  }
6145 
6147  typename IteratorType::reference value() const
6148  {
6149  return anchor.value();
6150  }
6151  };
6152 
6154  typename IteratorType::reference container;
6155 
6156  public:
6158  iteration_proxy(typename IteratorType::reference cont)
6159  : container(cont)
6160  {}
6161 
6163  iteration_proxy_internal begin()
6164  {
6165  return iteration_proxy_internal(container.begin());
6166  }
6167 
6169  iteration_proxy_internal end()
6170  {
6171  return iteration_proxy_internal(container.end());
6172  }
6173  };
6174 
6175  public:
6189  class const_iterator : public std::iterator<std::random_access_iterator_tag, const basic_json>
6190  {
6192  friend class basic_json;
6193 
6194  public:
6204  using iterator_category = std::bidirectional_iterator_tag;
6205 
6207  const_iterator() = default;
6208 
6210  const_iterator(pointer object) : m_object(object)
6211  {
6212  assert(m_object != nullptr);
6213 
6214  switch (m_object->m_type)
6215  {
6217  {
6218  m_it.object_iterator = typename object_t::iterator();
6219  break;
6220  }
6221 
6223  {
6224  m_it.array_iterator = typename array_t::iterator();
6225  break;
6226  }
6227 
6228  default:
6229  {
6230  m_it.primitive_iterator = primitive_iterator_t();
6231  break;
6232  }
6233  }
6234  }
6235 
6237  const_iterator(const iterator& other) : m_object(other.m_object)
6238  {
6239  assert(m_object != nullptr);
6240 
6241  switch (m_object->m_type)
6242  {
6244  {
6245  m_it.object_iterator = other.m_it.object_iterator;
6246  break;
6247  }
6248 
6250  {
6251  m_it.array_iterator = other.m_it.array_iterator;
6252  break;
6253  }
6254 
6255  default:
6256  {
6257  m_it.primitive_iterator = other.m_it.primitive_iterator;
6258  break;
6259  }
6260  }
6261  }
6262 
6264  const_iterator(const const_iterator& other) noexcept
6265  : m_object(other.m_object), m_it(other.m_it)
6266  {}
6267 
6270  std::is_nothrow_move_constructible<pointer>::value and
6271  std::is_nothrow_move_assignable<pointer>::value and
6272  std::is_nothrow_move_constructible<internal_iterator>::value and
6273  std::is_nothrow_move_assignable<internal_iterator>::value
6274  )
6275  {
6276  std::swap(m_object, other.m_object);
6277  std::swap(m_it, other.m_it);
6278  return *this;
6279  }
6280 
6281  private:
6283  void set_begin()
6284  {
6285  assert(m_object != nullptr);
6286 
6287  switch (m_object->m_type)
6288  {
6290  {
6291  assert(m_object->m_value.object != nullptr);
6292  m_it.object_iterator = m_object->m_value.object->begin();
6293  break;
6294  }
6295 
6297  {
6298  assert(m_object->m_value.array != nullptr);
6299  m_it.array_iterator = m_object->m_value.array->begin();
6300  break;
6301  }
6302 
6304  {
6305  // set to end so begin()==end() is true: null is empty
6306  m_it.primitive_iterator.set_end();
6307  break;
6308  }
6309 
6310  default:
6311  {
6312  m_it.primitive_iterator.set_begin();
6313  break;
6314  }
6315  }
6316  }
6317 
6319  void set_end()
6320  {
6321  assert(m_object != nullptr);
6322 
6323  switch (m_object->m_type)
6324  {
6326  {
6327  assert(m_object->m_value.object != nullptr);
6328  m_it.object_iterator = m_object->m_value.object->end();
6329  break;
6330  }
6331 
6333  {
6334  assert(m_object->m_value.array != nullptr);
6335  m_it.array_iterator = m_object->m_value.array->end();
6336  break;
6337  }
6338 
6339  default:
6340  {
6341  m_it.primitive_iterator.set_end();
6342  break;
6343  }
6344  }
6345  }
6346 
6347  public:
6350  {
6351  assert(m_object != nullptr);
6352 
6353  switch (m_object->m_type)
6354  {
6356  {
6357  assert(m_object->m_value.object);
6358  assert(m_it.object_iterator != m_object->m_value.object->end());
6359  return m_it.object_iterator->second;
6360  }
6361 
6363  {
6364  assert(m_object->m_value.array);
6365  assert(m_it.array_iterator != m_object->m_value.array->end());
6366  return *m_it.array_iterator;
6367  }
6368 
6370  {
6371  throw std::out_of_range("cannot get value");
6372  }
6373 
6374  default:
6375  {
6376  if (m_it.primitive_iterator.is_begin())
6377  {
6378  return *m_object;
6379  }
6380  else
6381  {
6382  throw std::out_of_range("cannot get value");
6383  }
6384  }
6385  }
6386  }
6387 
6390  {
6391  assert(m_object != nullptr);
6392 
6393  switch (m_object->m_type)
6394  {
6396  {
6397  assert(m_object->m_value.object);
6398  assert(m_it.object_iterator != m_object->m_value.object->end());
6399  return &(m_it.object_iterator->second);
6400  }
6401 
6403  {
6404  assert(m_object->m_value.array);
6405  assert(m_it.array_iterator != m_object->m_value.array->end());
6406  return &*m_it.array_iterator;
6407  }
6408 
6409  default:
6410  {
6411  if (m_it.primitive_iterator.is_begin())
6412  {
6413  return m_object;
6414  }
6415  else
6416  {
6417  throw std::out_of_range("cannot get value");
6418  }
6419  }
6420  }
6421  }
6422 
6425  {
6426  auto result = *this;
6427  ++(*this);
6428  return result;
6429  }
6430 
6433  {
6434  assert(m_object != nullptr);
6435 
6436  switch (m_object->m_type)
6437  {
6439  {
6440  ++m_it.object_iterator;
6441  break;
6442  }
6443 
6445  {
6446  ++m_it.array_iterator;
6447  break;
6448  }
6449 
6450  default:
6451  {
6452  ++m_it.primitive_iterator;
6453  break;
6454  }
6455  }
6456 
6457  return *this;
6458  }
6459 
6462  {
6463  auto result = *this;
6464  --(*this);
6465  return result;
6466  }
6467 
6470  {
6471  assert(m_object != nullptr);
6472 
6473  switch (m_object->m_type)
6474  {
6476  {
6477  --m_it.object_iterator;
6478  break;
6479  }
6480 
6482  {
6483  --m_it.array_iterator;
6484  break;
6485  }
6486 
6487  default:
6488  {
6489  --m_it.primitive_iterator;
6490  break;
6491  }
6492  }
6493 
6494  return *this;
6495  }
6496 
6498  bool operator==(const const_iterator& other) const
6499  {
6500  // if objects are not the same, the comparison is undefined
6501  if (m_object != other.m_object)
6502  {
6503  throw std::domain_error("cannot compare iterators of different containers");
6504  }
6505 
6506  assert(m_object != nullptr);
6507 
6508  switch (m_object->m_type)
6509  {
6511  {
6512  return (m_it.object_iterator == other.m_it.object_iterator);
6513  }
6514 
6516  {
6517  return (m_it.array_iterator == other.m_it.array_iterator);
6518  }
6519 
6520  default:
6521  {
6522  return (m_it.primitive_iterator == other.m_it.primitive_iterator);
6523  }
6524  }
6525  }
6526 
6528  bool operator!=(const const_iterator& other) const
6529  {
6530  return not operator==(other);
6531  }
6532 
6534  bool operator<(const const_iterator& other) const
6535  {
6536  // if objects are not the same, the comparison is undefined
6537  if (m_object != other.m_object)
6538  {
6539  throw std::domain_error("cannot compare iterators of different containers");
6540  }
6541 
6542  assert(m_object != nullptr);
6543 
6544  switch (m_object->m_type)
6545  {
6547  {
6548  throw std::domain_error("cannot compare order of object iterators");
6549  }
6550 
6552  {
6553  return (m_it.array_iterator < other.m_it.array_iterator);
6554  }
6555 
6556  default:
6557  {
6558  return (m_it.primitive_iterator < other.m_it.primitive_iterator);
6559  }
6560  }
6561  }
6562 
6564  bool operator<=(const const_iterator& other) const
6565  {
6566  return not other.operator < (*this);
6567  }
6568 
6570  bool operator>(const const_iterator& other) const
6571  {
6572  return not operator<=(other);
6573  }
6574 
6576  bool operator>=(const const_iterator& other) const
6577  {
6578  return not operator<(other);
6579  }
6580 
6583  {
6584  assert(m_object != nullptr);
6585 
6586  switch (m_object->m_type)
6587  {
6589  {
6590  throw std::domain_error("cannot use offsets with object iterators");
6591  }
6592 
6594  {
6595  m_it.array_iterator += i;
6596  break;
6597  }
6598 
6599  default:
6600  {
6601  m_it.primitive_iterator += i;
6602  break;
6603  }
6604  }
6605 
6606  return *this;
6607  }
6608 
6611  {
6612  return operator+=(-i);
6613  }
6614 
6617  {
6618  auto result = *this;
6619  result += i;
6620  return result;
6621  }
6622 
6625  {
6626  auto result = *this;
6627  result -= i;
6628  return result;
6629  }
6630 
6633  {
6634  assert(m_object != nullptr);
6635 
6636  switch (m_object->m_type)
6637  {
6639  {
6640  throw std::domain_error("cannot use offsets with object iterators");
6641  }
6642 
6644  {
6645  return m_it.array_iterator - other.m_it.array_iterator;
6646  }
6647 
6648  default:
6649  {
6650  return m_it.primitive_iterator - other.m_it.primitive_iterator;
6651  }
6652  }
6653  }
6654 
6657  {
6658  assert(m_object != nullptr);
6659 
6660  switch (m_object->m_type)
6661  {
6663  {
6664  throw std::domain_error("cannot use operator[] for object iterators");
6665  }
6666 
6668  {
6669  return *(m_it.array_iterator + n);
6670  }
6671 
6673  {
6674  throw std::out_of_range("cannot get value");
6675  }
6676 
6677  default:
6678  {
6679  if (m_it.primitive_iterator == -n)
6680  {
6681  return *m_object;
6682  }
6683  else
6684  {
6685  throw std::out_of_range("cannot get value");
6686  }
6687  }
6688  }
6689  }
6690 
6692  typename object_t::key_type key() const
6693  {
6694  assert(m_object != nullptr);
6695 
6696  if (m_object->is_object())
6697  {
6698  return m_it.object_iterator->first;
6699  }
6700  else
6701  {
6702  throw std::domain_error("cannot use key() for non-object iterators");
6703  }
6704  }
6705 
6708  {
6709  return operator*();
6710  }
6711 
6712  private:
6714  pointer m_object = nullptr;
6716  internal_iterator m_it = internal_iterator();
6717  };
6718 
6731  class iterator : public const_iterator
6732  {
6733  public:
6735  using pointer = typename basic_json::pointer;
6737 
6739  iterator() = default;
6740 
6742  iterator(pointer object) noexcept
6743  : base_iterator(object)
6744  {}
6745 
6747  iterator(const iterator& other) noexcept
6748  : base_iterator(other)
6749  {}
6750 
6752  iterator& operator=(iterator other) noexcept(
6753  std::is_nothrow_move_constructible<pointer>::value and
6754  std::is_nothrow_move_assignable<pointer>::value and
6755  std::is_nothrow_move_constructible<internal_iterator>::value and
6756  std::is_nothrow_move_assignable<internal_iterator>::value
6757  )
6758  {
6759  base_iterator::operator=(other);
6760  return *this;
6761  }
6762 
6765  {
6766  return const_cast<reference>(base_iterator::operator*());
6767  }
6768 
6771  {
6772  return const_cast<pointer>(base_iterator::operator->());
6773  }
6774 
6777  {
6778  iterator result = *this;
6779  base_iterator::operator++();
6780  return result;
6781  }
6782 
6785  {
6786  base_iterator::operator++();
6787  return *this;
6788  }
6789 
6792  {
6793  iterator result = *this;
6794  base_iterator::operator--();
6795  return result;
6796  }
6797 
6800  {
6801  base_iterator::operator--();
6802  return *this;
6803  }
6804 
6807  {
6808  base_iterator::operator+=(i);
6809  return *this;
6810  }
6811 
6814  {
6815  base_iterator::operator-=(i);
6816  return *this;
6817  }
6818 
6821  {
6822  auto result = *this;
6823  result += i;
6824  return result;
6825  }
6826 
6829  {
6830  auto result = *this;
6831  result -= i;
6832  return result;
6833  }
6834 
6836  difference_type operator-(const iterator& other) const
6837  {
6838  return base_iterator::operator-(other);
6839  }
6840 
6843  {
6844  return const_cast<reference>(base_iterator::operator[](n));
6845  }
6846 
6849  {
6850  return const_cast<reference>(base_iterator::value());
6851  }
6852  };
6853 
6871  template<typename Base>
6872  class json_reverse_iterator : public std::reverse_iterator<Base>
6873  {
6874  public:
6876  using base_iterator = std::reverse_iterator<Base>;
6878  using reference = typename Base::reference;
6879 
6881  json_reverse_iterator(const typename base_iterator::iterator_type& it)
6882  : base_iterator(it)
6883  {}
6884 
6887  : base_iterator(it)
6888  {}
6889 
6892  {
6893  return base_iterator::operator++(1);
6894  }
6895 
6898  {
6899  base_iterator::operator++();
6900  return *this;
6901  }
6902 
6905  {
6906  return base_iterator::operator--(1);
6907  }
6908 
6911  {
6912  base_iterator::operator--();
6913  return *this;
6914  }
6915 
6918  {
6919  base_iterator::operator+=(i);
6920  return *this;
6921  }
6922 
6925  {
6926  auto result = *this;
6927  result += i;
6928  return result;
6929  }
6930 
6933  {
6934  auto result = *this;
6935  result -= i;
6936  return result;
6937  }
6938 
6941  {
6942  return this->base() - other.base();
6943  }
6944 
6947  {
6948  return *(this->operator+(n));
6949  }
6950 
6952  typename object_t::key_type key() const
6953  {
6954  auto it = --this->base();
6955  return it.key();
6956  }
6957 
6960  {
6961  auto it = --this->base();
6962  return it.operator * ();
6963  }
6964  };
6965 
6966 
6967  private:
6969  // lexer and parser //
6971 
6979  class lexer
6980  {
6981  public:
6983  enum class token_type
6984  {
6985  uninitialized,
6986  literal_true,
6987  literal_false,
6988  literal_null,
6989  value_string,
6990  value_number,
6991  begin_array,
6992  begin_object,
6993  end_array,
6994  end_object,
6995  name_separator,
6996  value_separator,
6997  parse_error,
6998  end_of_input
6999  };
7000 
7002  using lexer_char_t = unsigned char;
7003 
7005  explicit lexer(const string_t& s) noexcept
7006  : m_stream(nullptr), m_buffer(s)
7007  {
7008  m_content = reinterpret_cast<const lexer_char_t*>(s.c_str());
7009  assert(m_content != nullptr);
7010  m_start = m_cursor = m_content;
7011  m_limit = m_content + s.size();
7012  }
7013 
7015  explicit lexer(std::istream* s) noexcept
7016  : m_stream(s), m_buffer()
7017  {
7018  assert(m_stream != nullptr);
7019  getline(*m_stream, m_buffer);
7020  m_content = reinterpret_cast<const lexer_char_t*>(m_buffer.c_str());
7021  assert(m_content != nullptr);
7022  m_start = m_cursor = m_content;
7023  m_limit = m_content + m_buffer.size();
7024  }
7025 
7027  lexer() = default;
7028 
7029  // switch off unwanted functions
7030  lexer(const lexer&) = delete;
7031  lexer operator=(const lexer&) = delete;
7032 
7048  static string_t to_unicode(const std::size_t codepoint1,
7049  const std::size_t codepoint2 = 0)
7050  {
7051  // calculate the codepoint from the given code points
7052  std::size_t codepoint = codepoint1;
7053 
7054  // check if codepoint1 is a high surrogate
7055  if (codepoint1 >= 0xD800 and codepoint1 <= 0xDBFF)
7056  {
7057  // check if codepoint2 is a low surrogate
7058  if (codepoint2 >= 0xDC00 and codepoint2 <= 0xDFFF)
7059  {
7060  codepoint =
7061  // high surrogate occupies the most significant 22 bits
7062  (codepoint1 << 10)
7063  // low surrogate occupies the least significant 15 bits
7064  + codepoint2
7065  // there is still the 0xD800, 0xDC00 and 0x10000 noise
7066  // in the result so we have to subtract with:
7067  // (0xD800 << 10) + DC00 - 0x10000 = 0x35FDC00
7068  - 0x35FDC00;
7069  }
7070  else
7071  {
7072  throw std::invalid_argument("missing or wrong low surrogate");
7073  }
7074  }
7075 
7076  string_t result;
7077 
7078  if (codepoint < 0x80)
7079  {
7080  // 1-byte characters: 0xxxxxxx (ASCII)
7081  result.append(1, static_cast<typename string_t::value_type>(codepoint));
7082  }
7083  else if (codepoint <= 0x7ff)
7084  {
7085  // 2-byte characters: 110xxxxx 10xxxxxx
7086  result.append(1, static_cast<typename string_t::value_type>(0xC0 | ((codepoint >> 6) & 0x1F)));
7087  result.append(1, static_cast<typename string_t::value_type>(0x80 | (codepoint & 0x3F)));
7088  }
7089  else if (codepoint <= 0xffff)
7090  {
7091  // 3-byte characters: 1110xxxx 10xxxxxx 10xxxxxx
7092  result.append(1, static_cast<typename string_t::value_type>(0xE0 | ((codepoint >> 12) & 0x0F)));
7093  result.append(1, static_cast<typename string_t::value_type>(0x80 | ((codepoint >> 6) & 0x3F)));
7094  result.append(1, static_cast<typename string_t::value_type>(0x80 | (codepoint & 0x3F)));
7095  }
7096  else if (codepoint <= 0x10ffff)
7097  {
7098  // 4-byte characters: 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
7099  result.append(1, static_cast<typename string_t::value_type>(0xF0 | ((codepoint >> 18) & 0x07)));
7100  result.append(1, static_cast<typename string_t::value_type>(0x80 | ((codepoint >> 12) & 0x3F)));
7101  result.append(1, static_cast<typename string_t::value_type>(0x80 | ((codepoint >> 6) & 0x3F)));
7102  result.append(1, static_cast<typename string_t::value_type>(0x80 | (codepoint & 0x3F)));
7103  }
7104  else
7105  {
7106  throw std::out_of_range("code points above 0x10FFFF are invalid");
7107  }
7108 
7109  return result;
7110  }
7111 
7113  static std::string token_type_name(token_type t)
7114  {
7115  switch (t)
7116  {
7117  case token_type::uninitialized:
7118  return "<uninitialized>";
7119  case token_type::literal_true:
7120  return "true literal";
7121  case token_type::literal_false:
7122  return "false literal";
7123  case token_type::literal_null:
7124  return "null literal";
7125  case token_type::value_string:
7126  return "string literal";
7127  case token_type::value_number:
7128  return "number literal";
7129  case token_type::begin_array:
7130  return "'['";
7131  case token_type::begin_object:
7132  return "'{'";
7133  case token_type::end_array:
7134  return "']'";
7135  case token_type::end_object:
7136  return "'}'";
7137  case token_type::name_separator:
7138  return "':'";
7139  case token_type::value_separator:
7140  return "','";
7141  case token_type::parse_error:
7142  return "<parse error>";
7143  case token_type::end_of_input:
7144  return "end of input";
7145  default:
7146  {
7147  // catch non-enum values
7148  return "unknown token"; // LCOV_EXCL_LINE
7149  }
7150  }
7151  }
7152 
7163  token_type scan() noexcept
7164  {
7165  // pointer for backtracking information
7166  m_marker = nullptr;
7167 
7168  // remember the begin of the token
7169  m_start = m_cursor;
7170  assert(m_start != nullptr);
7171 
7172 
7173  {
7174  lexer_char_t yych;
7175  unsigned int yyaccept = 0;
7176  static const unsigned char yybm[] =
7177  {
7178  0, 0, 0, 0, 0, 0, 0, 0,
7179  0, 32, 32, 0, 0, 32, 0, 0,
7180  128, 128, 128, 128, 128, 128, 128, 128,
7181  128, 128, 128, 128, 128, 128, 128, 128,
7182  160, 128, 0, 128, 128, 128, 128, 128,
7183  128, 128, 128, 128, 128, 128, 128, 128,
7184  192, 192, 192, 192, 192, 192, 192, 192,
7185  192, 192, 128, 128, 128, 128, 128, 128,
7186  128, 128, 128, 128, 128, 128, 128, 128,
7187  128, 128, 128, 128, 128, 128, 128, 128,
7188  128, 128, 128, 128, 128, 128, 128, 128,
7189  128, 128, 128, 128, 0, 128, 128, 128,
7190  128, 128, 128, 128, 128, 128, 128, 128,
7191  128, 128, 128, 128, 128, 128, 128, 128,
7192  128, 128, 128, 128, 128, 128, 128, 128,
7193  128, 128, 128, 128, 128, 128, 128, 128,
7194  128, 128, 128, 128, 128, 128, 128, 128,
7195  128, 128, 128, 128, 128, 128, 128, 128,
7196  128, 128, 128, 128, 128, 128, 128, 128,
7197  128, 128, 128, 128, 128, 128, 128, 128,
7198  128, 128, 128, 128, 128, 128, 128, 128,
7199  128, 128, 128, 128, 128, 128, 128, 128,
7200  128, 128, 128, 128, 128, 128, 128, 128,
7201  128, 128, 128, 128, 128, 128, 128, 128,
7202  128, 128, 128, 128, 128, 128, 128, 128,
7203  128, 128, 128, 128, 128, 128, 128, 128,
7204  128, 128, 128, 128, 128, 128, 128, 128,
7205  128, 128, 128, 128, 128, 128, 128, 128,
7206  128, 128, 128, 128, 128, 128, 128, 128,
7207  128, 128, 128, 128, 128, 128, 128, 128,
7208  128, 128, 128, 128, 128, 128, 128, 128,
7209  128, 128, 128, 128, 128, 128, 128, 128,
7210  };
7211  if ((m_limit - m_cursor) < 5)
7212  {
7213  yyfill(); // LCOV_EXCL_LINE;
7214  }
7215  yych = *m_cursor;
7216  if (yybm[0 + yych] & 32)
7217  {
7218  goto basic_json_parser_6;
7219  }
7220  if (yych <= '\\')
7221  {
7222  if (yych <= '-')
7223  {
7224  if (yych <= '"')
7225  {
7226  if (yych <= 0x00)
7227  {
7228  goto basic_json_parser_2;
7229  }
7230  if (yych <= '!')
7231  {
7232  goto basic_json_parser_4;
7233  }
7234  goto basic_json_parser_9;
7235  }
7236  else
7237  {
7238  if (yych <= '+')
7239  {
7240  goto basic_json_parser_4;
7241  }
7242  if (yych <= ',')
7243  {
7244  goto basic_json_parser_10;
7245  }
7246  goto basic_json_parser_12;
7247  }
7248  }
7249  else
7250  {
7251  if (yych <= '9')
7252  {
7253  if (yych <= '/')
7254  {
7255  goto basic_json_parser_4;
7256  }
7257  if (yych <= '0')
7258  {
7259  goto basic_json_parser_13;
7260  }
7261  goto basic_json_parser_15;
7262  }
7263  else
7264  {
7265  if (yych <= ':')
7266  {
7267  goto basic_json_parser_17;
7268  }
7269  if (yych == '[')
7270  {
7271  goto basic_json_parser_19;
7272  }
7273  goto basic_json_parser_4;
7274  }
7275  }
7276  }
7277  else
7278  {
7279  if (yych <= 't')
7280  {
7281  if (yych <= 'f')
7282  {
7283  if (yych <= ']')
7284  {
7285  goto basic_json_parser_21;
7286  }
7287  if (yych <= 'e')
7288  {
7289  goto basic_json_parser_4;
7290  }
7291  goto basic_json_parser_23;
7292  }
7293  else
7294  {
7295  if (yych == 'n')
7296  {
7297  goto basic_json_parser_24;
7298  }
7299  if (yych <= 's')
7300  {
7301  goto basic_json_parser_4;
7302  }
7303  goto basic_json_parser_25;
7304  }
7305  }
7306  else
7307  {
7308  if (yych <= '|')
7309  {
7310  if (yych == '{')
7311  {
7312  goto basic_json_parser_26;
7313  }
7314  goto basic_json_parser_4;
7315  }
7316  else
7317  {
7318  if (yych <= '}')
7319  {
7320  goto basic_json_parser_28;
7321  }
7322  if (yych == 0xEF)
7323  {
7324  goto basic_json_parser_30;
7325  }
7326  goto basic_json_parser_4;
7327  }
7328  }
7329  }
7330 basic_json_parser_2:
7331  ++m_cursor;
7332  {
7333  return token_type::end_of_input;
7334  }
7335 basic_json_parser_4:
7336  ++m_cursor;
7337 basic_json_parser_5:
7338  {
7339  return token_type::parse_error;
7340  }
7341 basic_json_parser_6:
7342  ++m_cursor;
7343  if (m_limit <= m_cursor)
7344  {
7345  yyfill(); // LCOV_EXCL_LINE;
7346  }
7347  yych = *m_cursor;
7348  if (yybm[0 + yych] & 32)
7349  {
7350  goto basic_json_parser_6;
7351  }
7352  {
7353  return scan();
7354  }
7355 basic_json_parser_9:
7356  yyaccept = 0;
7357  yych = *(m_marker = ++m_cursor);
7358  if (yych <= 0x0F)
7359  {
7360  goto basic_json_parser_5;
7361  }
7362  goto basic_json_parser_32;
7363 basic_json_parser_10:
7364  ++m_cursor;
7365  {
7366  return token_type::value_separator;
7367  }
7368 basic_json_parser_12:
7369  yych = *++m_cursor;
7370  if (yych <= '/')
7371  {
7372  goto basic_json_parser_5;
7373  }
7374  if (yych <= '0')
7375  {
7376  goto basic_json_parser_13;
7377  }
7378  if (yych <= '9')
7379  {
7380  goto basic_json_parser_15;
7381  }
7382  goto basic_json_parser_5;
7383 basic_json_parser_13:
7384  yyaccept = 1;
7385  yych = *(m_marker = ++m_cursor);
7386  if (yych <= 'D')
7387  {
7388  if (yych == '.')
7389  {
7390  goto basic_json_parser_37;
7391  }
7392  }
7393  else
7394  {
7395  if (yych <= 'E')
7396  {
7397  goto basic_json_parser_38;
7398  }
7399  if (yych == 'e')
7400  {
7401  goto basic_json_parser_38;
7402  }
7403  }
7404 basic_json_parser_14:
7405  {
7406  return token_type::value_number;
7407  }
7408 basic_json_parser_15:
7409  yyaccept = 1;
7410  m_marker = ++m_cursor;
7411  if ((m_limit - m_cursor) < 3)
7412  {
7413  yyfill(); // LCOV_EXCL_LINE;
7414  }
7415  yych = *m_cursor;
7416  if (yybm[0 + yych] & 64)
7417  {
7418  goto basic_json_parser_15;
7419  }
7420  if (yych <= 'D')
7421  {
7422  if (yych == '.')
7423  {
7424  goto basic_json_parser_37;
7425  }
7426  goto basic_json_parser_14;
7427  }
7428  else
7429  {
7430  if (yych <= 'E')
7431  {
7432  goto basic_json_parser_38;
7433  }
7434  if (yych == 'e')
7435  {
7436  goto basic_json_parser_38;
7437  }
7438  goto basic_json_parser_14;
7439  }
7440 basic_json_parser_17:
7441  ++m_cursor;
7442  {
7443  return token_type::name_separator;
7444  }
7445 basic_json_parser_19:
7446  ++m_cursor;
7447  {
7448  return token_type::begin_array;
7449  }
7450 basic_json_parser_21:
7451  ++m_cursor;
7452  {
7453  return token_type::end_array;
7454  }
7455 basic_json_parser_23:
7456  yyaccept = 0;
7457  yych = *(m_marker = ++m_cursor);
7458  if (yych == 'a')
7459  {
7460  goto basic_json_parser_39;
7461  }
7462  goto basic_json_parser_5;
7463 basic_json_parser_24:
7464  yyaccept = 0;
7465  yych = *(m_marker = ++m_cursor);
7466  if (yych == 'u')
7467  {
7468  goto basic_json_parser_40;
7469  }
7470  goto basic_json_parser_5;
7471 basic_json_parser_25:
7472  yyaccept = 0;
7473  yych = *(m_marker = ++m_cursor);
7474  if (yych == 'r')
7475  {
7476  goto basic_json_parser_41;
7477  }
7478  goto basic_json_parser_5;
7479 basic_json_parser_26:
7480  ++m_cursor;
7481  {
7482  return token_type::begin_object;
7483  }
7484 basic_json_parser_28:
7485  ++m_cursor;
7486  {
7487  return token_type::end_object;
7488  }
7489 basic_json_parser_30:
7490  yyaccept = 0;
7491  yych = *(m_marker = ++m_cursor);
7492  if (yych == 0xBB)
7493  {
7494  goto basic_json_parser_42;
7495  }
7496  goto basic_json_parser_5;
7497 basic_json_parser_31:
7498  ++m_cursor;
7499  if (m_limit <= m_cursor)
7500  {
7501  yyfill(); // LCOV_EXCL_LINE;
7502  }
7503  yych = *m_cursor;
7504 basic_json_parser_32:
7505  if (yybm[0 + yych] & 128)
7506  {
7507  goto basic_json_parser_31;
7508  }
7509  if (yych <= 0x0F)
7510  {
7511  goto basic_json_parser_33;
7512  }
7513  if (yych <= '"')
7514  {
7515  goto basic_json_parser_34;
7516  }
7517  goto basic_json_parser_36;
7518 basic_json_parser_33:
7519  m_cursor = m_marker;
7520  if (yyaccept == 0)
7521  {
7522  goto basic_json_parser_5;
7523  }
7524  else
7525  {
7526  goto basic_json_parser_14;
7527  }
7528 basic_json_parser_34:
7529  ++m_cursor;
7530  {
7531  return token_type::value_string;
7532  }
7533 basic_json_parser_36:
7534  ++m_cursor;
7535  if (m_limit <= m_cursor)
7536  {
7537  yyfill(); // LCOV_EXCL_LINE;
7538  }
7539  yych = *m_cursor;
7540  if (yych <= 'e')
7541  {
7542  if (yych <= '/')
7543  {
7544  if (yych == '"')
7545  {
7546  goto basic_json_parser_31;
7547  }
7548  if (yych <= '.')
7549  {
7550  goto basic_json_parser_33;
7551  }
7552  goto basic_json_parser_31;
7553  }
7554  else
7555  {
7556  if (yych <= '\\')
7557  {
7558  if (yych <= '[')
7559  {
7560  goto basic_json_parser_33;
7561  }
7562  goto basic_json_parser_31;
7563  }
7564  else
7565  {
7566  if (yych == 'b')
7567  {
7568  goto basic_json_parser_31;
7569  }
7570  goto basic_json_parser_33;
7571  }
7572  }
7573  }
7574  else
7575  {
7576  if (yych <= 'q')
7577  {
7578  if (yych <= 'f')
7579  {
7580  goto basic_json_parser_31;
7581  }
7582  if (yych == 'n')
7583  {
7584  goto basic_json_parser_31;
7585  }
7586  goto basic_json_parser_33;
7587  }
7588  else
7589  {
7590  if (yych <= 's')
7591  {
7592  if (yych <= 'r')
7593  {
7594  goto basic_json_parser_31;
7595  }
7596  goto basic_json_parser_33;
7597  }
7598  else
7599  {
7600  if (yych <= 't')
7601  {
7602  goto basic_json_parser_31;
7603  }
7604  if (yych <= 'u')
7605  {
7606  goto basic_json_parser_43;
7607  }
7608  goto basic_json_parser_33;
7609  }
7610  }
7611  }
7612 basic_json_parser_37:
7613  yych = *++m_cursor;
7614  if (yych <= '/')
7615  {
7616  goto basic_json_parser_33;
7617  }
7618  if (yych <= '9')
7619  {
7620  goto basic_json_parser_44;
7621  }
7622  goto basic_json_parser_33;
7623 basic_json_parser_38:
7624  yych = *++m_cursor;
7625  if (yych <= ',')
7626  {
7627  if (yych == '+')
7628  {
7629  goto basic_json_parser_46;
7630  }
7631  goto basic_json_parser_33;
7632  }
7633  else
7634  {
7635  if (yych <= '-')
7636  {
7637  goto basic_json_parser_46;
7638  }
7639  if (yych <= '/')
7640  {
7641  goto basic_json_parser_33;
7642  }
7643  if (yych <= '9')
7644  {
7645  goto basic_json_parser_47;
7646  }
7647  goto basic_json_parser_33;
7648  }
7649 basic_json_parser_39:
7650  yych = *++m_cursor;
7651  if (yych == 'l')
7652  {
7653  goto basic_json_parser_49;
7654  }
7655  goto basic_json_parser_33;
7656 basic_json_parser_40:
7657  yych = *++m_cursor;
7658  if (yych == 'l')
7659  {
7660  goto basic_json_parser_50;
7661  }
7662  goto basic_json_parser_33;
7663 basic_json_parser_41:
7664  yych = *++m_cursor;
7665  if (yych == 'u')
7666  {
7667  goto basic_json_parser_51;
7668  }
7669  goto basic_json_parser_33;
7670 basic_json_parser_42:
7671  yych = *++m_cursor;
7672  if (yych == 0xBF)
7673  {
7674  goto basic_json_parser_52;
7675  }
7676  goto basic_json_parser_33;
7677 basic_json_parser_43:
7678  ++m_cursor;
7679  if (m_limit <= m_cursor)
7680  {
7681  yyfill(); // LCOV_EXCL_LINE;
7682  }
7683  yych = *m_cursor;
7684  if (yych <= '@')
7685  {
7686  if (yych <= '/')
7687  {
7688  goto basic_json_parser_33;
7689  }
7690  if (yych <= '9')
7691  {
7692  goto basic_json_parser_54;
7693  }
7694  goto basic_json_parser_33;
7695  }
7696  else
7697  {
7698  if (yych <= 'F')
7699  {
7700  goto basic_json_parser_54;
7701  }
7702  if (yych <= '`')
7703  {
7704  goto basic_json_parser_33;
7705  }
7706  if (yych <= 'f')
7707  {
7708  goto basic_json_parser_54;
7709  }
7710  goto basic_json_parser_33;
7711  }
7712 basic_json_parser_44:
7713  yyaccept = 1;
7714  m_marker = ++m_cursor;
7715  if ((m_limit - m_cursor) < 3)
7716  {
7717  yyfill(); // LCOV_EXCL_LINE;
7718  }
7719  yych = *m_cursor;
7720  if (yych <= 'D')
7721  {
7722  if (yych <= '/')
7723  {
7724  goto basic_json_parser_14;
7725  }
7726  if (yych <= '9')
7727  {
7728  goto basic_json_parser_44;
7729  }
7730  goto basic_json_parser_14;
7731  }
7732  else
7733  {
7734  if (yych <= 'E')
7735  {
7736  goto basic_json_parser_38;
7737  }
7738  if (yych == 'e')
7739  {
7740  goto basic_json_parser_38;
7741  }
7742  goto basic_json_parser_14;
7743  }
7744 basic_json_parser_46:
7745  yych = *++m_cursor;
7746  if (yych <= '/')
7747  {
7748  goto basic_json_parser_33;
7749  }
7750  if (yych >= ':')
7751  {
7752  goto basic_json_parser_33;
7753  }
7754 basic_json_parser_47:
7755  ++m_cursor;
7756  if (m_limit <= m_cursor)
7757  {
7758  yyfill(); // LCOV_EXCL_LINE;
7759  }
7760  yych = *m_cursor;
7761  if (yych <= '/')
7762  {
7763  goto basic_json_parser_14;
7764  }
7765  if (yych <= '9')
7766  {
7767  goto basic_json_parser_47;
7768  }
7769  goto basic_json_parser_14;
7770 basic_json_parser_49:
7771  yych = *++m_cursor;
7772  if (yych == 's')
7773  {
7774  goto basic_json_parser_55;
7775  }
7776  goto basic_json_parser_33;
7777 basic_json_parser_50:
7778  yych = *++m_cursor;
7779  if (yych == 'l')
7780  {
7781  goto basic_json_parser_56;
7782  }
7783  goto basic_json_parser_33;
7784 basic_json_parser_51:
7785  yych = *++m_cursor;
7786  if (yych == 'e')
7787  {
7788  goto basic_json_parser_58;
7789  }
7790  goto basic_json_parser_33;
7791 basic_json_parser_52:
7792  ++m_cursor;
7793  {
7794  return scan();
7795  }
7796 basic_json_parser_54:
7797  ++m_cursor;
7798  if (m_limit <= m_cursor)
7799  {
7800  yyfill(); // LCOV_EXCL_LINE;
7801  }
7802  yych = *m_cursor;
7803  if (yych <= '@')
7804  {
7805  if (yych <= '/')
7806  {
7807  goto basic_json_parser_33;
7808  }
7809  if (yych <= '9')
7810  {
7811  goto basic_json_parser_60;
7812  }
7813  goto basic_json_parser_33;
7814  }
7815  else
7816  {
7817  if (yych <= 'F')
7818  {
7819  goto basic_json_parser_60;
7820  }
7821  if (yych <= '`')
7822  {
7823  goto basic_json_parser_33;
7824  }
7825  if (yych <= 'f')
7826  {
7827  goto basic_json_parser_60;
7828  }
7829  goto basic_json_parser_33;
7830  }
7831 basic_json_parser_55:
7832  yych = *++m_cursor;
7833  if (yych == 'e')
7834  {
7835  goto basic_json_parser_61;
7836  }
7837  goto basic_json_parser_33;
7838 basic_json_parser_56:
7839  ++m_cursor;
7840  {
7841  return token_type::literal_null;
7842  }
7843 basic_json_parser_58:
7844  ++m_cursor;
7845  {
7846  return token_type::literal_true;
7847  }
7848 basic_json_parser_60:
7849  ++m_cursor;
7850  if (m_limit <= m_cursor)
7851  {
7852  yyfill(); // LCOV_EXCL_LINE;
7853  }
7854  yych = *m_cursor;
7855  if (yych <= '@')
7856  {
7857  if (yych <= '/')
7858  {
7859  goto basic_json_parser_33;
7860  }
7861  if (yych <= '9')
7862  {
7863  goto basic_json_parser_63;
7864  }
7865  goto basic_json_parser_33;
7866  }
7867  else
7868  {
7869  if (yych <= 'F')
7870  {
7871  goto basic_json_parser_63;
7872  }
7873  if (yych <= '`')
7874  {
7875  goto basic_json_parser_33;
7876  }
7877  if (yych <= 'f')
7878  {
7879  goto basic_json_parser_63;
7880  }
7881  goto basic_json_parser_33;
7882  }
7883 basic_json_parser_61:
7884  ++m_cursor;
7885  {
7886  return token_type::literal_false;
7887  }
7888 basic_json_parser_63:
7889  ++m_cursor;
7890  if (m_limit <= m_cursor)
7891  {
7892  yyfill(); // LCOV_EXCL_LINE;
7893  }
7894  yych = *m_cursor;
7895  if (yych <= '@')
7896  {
7897  if (yych <= '/')
7898  {
7899  goto basic_json_parser_33;
7900  }
7901  if (yych <= '9')
7902  {
7903  goto basic_json_parser_31;
7904  }
7905  goto basic_json_parser_33;
7906  }
7907  else
7908  {
7909  if (yych <= 'F')
7910  {
7911  goto basic_json_parser_31;
7912  }
7913  if (yych <= '`')
7914  {
7915  goto basic_json_parser_33;
7916  }
7917  if (yych <= 'f')
7918  {
7919  goto basic_json_parser_31;
7920  }
7921  goto basic_json_parser_33;
7922  }
7923  }
7924 
7925 
7926  }
7927 
7929  void yyfill() noexcept
7930  {
7931  if (m_stream == nullptr or not * m_stream)
7932  {
7933  return;
7934  }
7935 
7936  const ssize_t offset_start = m_start - m_content;
7937  const ssize_t offset_marker = m_marker - m_start;
7938  const ssize_t offset_cursor = m_cursor - m_start;
7939 
7940  m_buffer.erase(0, static_cast<size_t>(offset_start));
7941  std::string line;
7942  assert(m_stream != nullptr);
7943  std::getline(*m_stream, line);
7944  m_buffer += "\n" + line; // add line with newline symbol
7945 
7946  m_content = reinterpret_cast<const lexer_char_t*>(m_buffer.c_str());
7947  assert(m_content != nullptr);
7948  m_start = m_content;
7949  m_marker = m_start + offset_marker;
7950  m_cursor = m_start + offset_cursor;
7951  m_limit = m_start + m_buffer.size() - 1;
7952  }
7953 
7955  string_t get_token() const noexcept
7956  {
7957  assert(m_start != nullptr);
7958  return string_t(reinterpret_cast<typename string_t::const_pointer>(m_start),
7959  static_cast<size_t>(m_cursor - m_start));
7960  }
7961 
7983  string_t get_string() const
7984  {
7985  string_t result;
7986  result.reserve(static_cast<size_t>(m_cursor - m_start - 2));
7987 
7988  // iterate the result between the quotes
7989  for (const lexer_char_t* i = m_start + 1; i < m_cursor - 1; ++i)
7990  {
7991  // process escaped characters
7992  if (*i == '\\')
7993  {
7994  // read next character
7995  ++i;
7996 
7997  switch (*i)
7998  {
7999  // the default escapes
8000  case 't':
8001  {
8002  result += "\t";
8003  break;
8004  }
8005  case 'b':
8006  {
8007  result += "\b";
8008  break;
8009  }
8010  case 'f':
8011  {
8012  result += "\f";
8013  break;
8014  }
8015  case 'n':
8016  {
8017  result += "\n";
8018  break;
8019  }
8020  case 'r':
8021  {
8022  result += "\r";
8023  break;
8024  }
8025  case '\\':
8026  {
8027  result += "\\";
8028  break;
8029  }
8030  case '/':
8031  {
8032  result += "/";
8033  break;
8034  }
8035  case '"':
8036  {
8037  result += "\"";
8038  break;
8039  }
8040 
8041  // unicode
8042  case 'u':
8043  {
8044  // get code xxxx from uxxxx
8045  auto codepoint = std::strtoul(std::string(reinterpret_cast<typename string_t::const_pointer>(i + 1),
8046  4).c_str(), nullptr, 16);
8047 
8048  // check if codepoint is a high surrogate
8049  if (codepoint >= 0xD800 and codepoint <= 0xDBFF)
8050  {
8051  // make sure there is a subsequent unicode
8052  if ((i + 6 >= m_limit) or * (i + 5) != '\\' or * (i + 6) != 'u')
8053  {
8054  throw std::invalid_argument("missing low surrogate");
8055  }
8056 
8057  // get code yyyy from uxxxx\uyyyy
8058  auto codepoint2 = std::strtoul(std::string(reinterpret_cast<typename string_t::const_pointer>
8059  (i + 7), 4).c_str(), nullptr, 16);
8060  result += to_unicode(codepoint, codepoint2);
8061  // skip the next 10 characters (xxxx\uyyyy)
8062  i += 10;
8063  }
8064  else
8065  {
8066  // add unicode character(s)
8067  result += to_unicode(codepoint);
8068  // skip the next four characters (xxxx)
8069  i += 4;
8070  }
8071  break;
8072  }
8073  }
8074  }
8075  else
8076  {
8077  // all other characters are just copied to the end of the
8078  // string
8079  result.append(1, static_cast<typename string_t::value_type>(*i));
8080  }
8081  }
8082 
8083  return result;
8084  }
8085 
8106  long double str_to_float_t(long double* /* type */, char** endptr) const
8107  {
8108  return std::strtold(reinterpret_cast<typename string_t::const_pointer>(m_start), endptr);
8109  }
8110 
8126  double str_to_float_t(double* /* type */, char** endptr) const
8127  {
8128  return std::strtod(reinterpret_cast<typename string_t::const_pointer>(m_start), endptr);
8129  }
8130 
8146  float str_to_float_t(float* /* type */, char** endptr) const
8147  {
8148  return std::strtof(reinterpret_cast<typename string_t::const_pointer>(m_start), endptr);
8149  }
8150 
8163  template <typename T_A, typename T_B>
8164  bool attempt_cast(T_A source, T_B& dest) const
8165  {
8166  dest = static_cast<T_B>(source);
8167  return (source == static_cast<T_A>(dest));
8168  }
8169 
8208  void get_number(basic_json& result) const
8209  {
8210  typename string_t::value_type* endptr;
8211  assert(m_start != nullptr);
8212  errno = 0;
8213 
8214  // attempt to parse it as an integer - first checking for a
8215  // negative number
8216  if (*reinterpret_cast<typename string_t::const_pointer>(m_start) != '-')
8217  {
8218  // positive, parse with strtoull and attempt cast to
8219  // number_unsigned_t
8220  if (attempt_cast(std::strtoull(reinterpret_cast<typename string_t::const_pointer>(m_start), &endptr,
8221  10), result.m_value.number_unsigned))
8222  {
8223  result.m_type = value_t::number_unsigned;
8224  }
8225  else
8226  {
8227  // cast failed due to overflow - store as float
8228  result.m_type = value_t::number_float;
8229  }
8230  }
8231  else
8232  {
8233  // Negative, parse with strtoll and attempt cast to
8234  // number_integer_t
8235  if (attempt_cast(std::strtoll(reinterpret_cast<typename string_t::const_pointer>(m_start), &endptr,
8236  10), result.m_value.number_integer))
8237  {
8238  result.m_type = value_t::number_integer;
8239  }
8240  else
8241  {
8242  // cast failed due to overflow - store as float
8243  result.m_type = value_t::number_float;
8244  }
8245  }
8246 
8247  // check the end of the number was reached and no range error
8248  // occurred
8249  if (reinterpret_cast<lexer_char_t*>(endptr) != m_cursor || errno == ERANGE)
8250  {
8251  result.m_type = value_t::number_float;
8252  }
8253 
8254  if (result.m_type == value_t::number_float)
8255  {
8256  // either the number won't fit in an integer (range error from
8257  // strtoull/strtoll or overflow on cast) or there was something
8258  // else after the number, which could be an exponent
8259 
8260  // parse with strtod
8261  result.m_value.number_float = str_to_float_t(static_cast<number_float_t*>(nullptr), &endptr);
8262 
8263  // anything after the number is an error
8264  if (reinterpret_cast<lexer_char_t*>(endptr) != m_cursor)
8265  {
8266  throw std::invalid_argument(std::string("parse error - ") + get_token() + " is not a number");
8267  }
8268  }
8269  }
8270 
8271  private:
8273  std::istream* m_stream = nullptr;
8275  string_t m_buffer;
8277  const lexer_char_t* m_content = nullptr;
8279  const lexer_char_t* m_start = nullptr;
8281  const lexer_char_t* m_marker = nullptr;
8283  const lexer_char_t* m_cursor = nullptr;
8285  const lexer_char_t* m_limit = nullptr;
8286  };
8287 
8293  class parser
8294  {
8295  public:
8297  parser(const string_t& s, parser_callback_t cb = nullptr)
8298  : callback(cb), m_lexer(s)
8299  {
8300  // read first token
8301  get_token();
8302  }
8303 
8305  parser(std::istream& _is, parser_callback_t cb = nullptr)
8306  : callback(cb), m_lexer(&_is)
8307  {
8308  // read first token
8309  get_token();
8310  }
8311 
8313  basic_json parse()
8314  {
8315  basic_json result = parse_internal(true);
8316 
8317  expect(lexer::token_type::end_of_input);
8318 
8319  // return parser result and replace it with null in case the
8320  // top-level value was discarded by the callback function
8321  return result.is_discarded() ? basic_json() : result;
8322  }
8323 
8324  private:
8326  basic_json parse_internal(bool keep)
8327  {
8328  auto result = basic_json(value_t::discarded);
8329 
8330  switch (last_token)
8331  {
8332  case lexer::token_type::begin_object:
8333  {
8334  if (keep and (not callback or (keep = callback(depth++, parse_event_t::object_start, result))))
8335  {
8336  // explicitly set result to object to cope with {}
8337  result.m_type = value_t::object;
8338  result.m_value = json_value(value_t::object);
8339  }
8340 
8341  // read next token
8342  get_token();
8343 
8344  // closing } -> we are done
8345  if (last_token == lexer::token_type::end_object)
8346  {
8347  get_token();
8348  if (keep and callback and not callback(--depth, parse_event_t::object_end, result))
8349  {
8350  result = basic_json(value_t::discarded);
8351  }
8352  return result;
8353  }
8354 
8355  // no comma is expected here
8356  unexpect(lexer::token_type::value_separator);
8357 
8358  // otherwise: parse key-value pairs
8359  do
8360  {
8361  // ugly, but could be fixed with loop reorganization
8362  if (last_token == lexer::token_type::value_separator)
8363  {
8364  get_token();
8365  }
8366 
8367  // store key
8368  expect(lexer::token_type::value_string);
8369  const auto key = m_lexer.get_string();
8370 
8371  bool keep_tag = false;
8372  if (keep)
8373  {
8374  if (callback)
8375  {
8376  basic_json k(key);
8377  keep_tag = callback(depth, parse_event_t::key, k);
8378  }
8379  else
8380  {
8381  keep_tag = true;
8382  }
8383  }
8384 
8385  // parse separator (:)
8386  get_token();
8387  expect(lexer::token_type::name_separator);
8388 
8389  // parse and add value
8390  get_token();
8391  auto value = parse_internal(keep);
8392  if (keep and keep_tag and not value.is_discarded())
8393  {
8394  result[key] = std::move(value);
8395  }
8396  }
8397  while (last_token == lexer::token_type::value_separator);
8398 
8399  // closing }
8400  expect(lexer::token_type::end_object);
8401  get_token();
8402  if (keep and callback and not callback(--depth, parse_event_t::object_end, result))
8403  {
8404  result = basic_json(value_t::discarded);
8405  }
8406 
8407  return result;
8408  }
8409 
8410  case lexer::token_type::begin_array:
8411  {
8412  if (keep and (not callback or (keep = callback(depth++, parse_event_t::array_start, result))))
8413  {
8414  // explicitly set result to object to cope with []
8415  result.m_type = value_t::array;
8416  result.m_value = json_value(value_t::array);
8417  }
8418 
8419  // read next token
8420  get_token();
8421 
8422  // closing ] -> we are done
8423  if (last_token == lexer::token_type::end_array)
8424  {
8425  get_token();
8426  if (callback and not callback(--depth, parse_event_t::array_end, result))
8427  {
8428  result = basic_json(value_t::discarded);
8429  }
8430  return result;
8431  }
8432 
8433  // no comma is expected here
8434  unexpect(lexer::token_type::value_separator);
8435 
8436  // otherwise: parse values
8437  do
8438  {
8439  // ugly, but could be fixed with loop reorganization
8440  if (last_token == lexer::token_type::value_separator)
8441  {
8442  get_token();
8443  }
8444 
8445  // parse value
8446  auto value = parse_internal(keep);
8447  if (keep and not value.is_discarded())
8448  {
8449  result.push_back(std::move(value));
8450  }
8451  }
8452  while (last_token == lexer::token_type::value_separator);
8453 
8454  // closing ]
8455  expect(lexer::token_type::end_array);
8456  get_token();
8457  if (keep and callback and not callback(--depth, parse_event_t::array_end, result))
8458  {
8459  result = basic_json(value_t::discarded);
8460  }
8461 
8462  return result;
8463  }
8464 
8465  case lexer::token_type::literal_null:
8466  {
8467  get_token();
8468  result.m_type = value_t::null;
8469  break;
8470  }
8471 
8472  case lexer::token_type::value_string:
8473  {
8474  const auto s = m_lexer.get_string();
8475  get_token();
8476  result = basic_json(s);
8477  break;
8478  }
8479 
8480  case lexer::token_type::literal_true:
8481  {
8482  get_token();
8483  result.m_type = value_t::boolean;
8484  result.m_value = true;
8485  break;
8486  }
8487 
8488  case lexer::token_type::literal_false:
8489  {
8490  get_token();
8491  result.m_type = value_t::boolean;
8492  result.m_value = false;
8493  break;
8494  }
8495 
8496  case lexer::token_type::value_number:
8497  {
8498  m_lexer.get_number(result);
8499  get_token();
8500  break;
8501  }
8502 
8503  default:
8504  {
8505  // the last token was unexpected
8506  unexpect(last_token);
8507  }
8508  }
8509 
8510  if (keep and callback and not callback(depth, parse_event_t::value, result))
8511  {
8512  result = basic_json(value_t::discarded);
8513  }
8514  return result;
8515  }
8516 
8518  typename lexer::token_type get_token()
8519  {
8520  last_token = m_lexer.scan();
8521  return last_token;
8522  }
8523 
8524  void expect(typename lexer::token_type t) const
8525  {
8526  if (t != last_token)
8527  {
8528  std::string error_msg = "parse error - unexpected ";
8529  error_msg += (last_token == lexer::token_type::parse_error ? ("'" + m_lexer.get_token() + "'") :
8530  lexer::token_type_name(last_token));
8531  error_msg += "; expected " + lexer::token_type_name(t);
8532  throw std::invalid_argument(error_msg);
8533  }
8534  }
8535 
8536  void unexpect(typename lexer::token_type t) const
8537  {
8538  if (t == last_token)
8539  {
8540  std::string error_msg = "parse error - unexpected ";
8541  error_msg += (last_token == lexer::token_type::parse_error ? ("'" + m_lexer.get_token() + "'") :
8542  lexer::token_type_name(last_token));
8543  throw std::invalid_argument(error_msg);
8544  }
8545  }
8546 
8547  private:
8549  int depth = 0;
8551  parser_callback_t callback;
8553  typename lexer::token_type last_token = lexer::token_type::uninitialized;
8555  lexer m_lexer;
8556  };
8557 };
8558 
8559 
8561 // presets //
8563 
8573 }
8574 
8575 
8577 // nonmember functions //
8579 
8580 // specialization of std::swap, and std::hash
8581 namespace std
8582 {
8588 template <>
8589 inline void swap(nlohmann::json& j1,
8590  nlohmann::json& j2) noexcept(
8591  is_nothrow_move_constructible<nlohmann::json>::value and
8592  is_nothrow_move_assignable<nlohmann::json>::value
8593  )
8594 {
8595  j1.swap(j2);
8596 }
8597 
8599 template <>
8600 struct hash<nlohmann::json>
8601 {
8607  std::size_t operator()(const nlohmann::json& j) const
8608  {
8609  // a naive hashing via the string representation
8610  const auto& h = hash<nlohmann::json::string_t>();
8611  return h(j.dump());
8612  }
8613 };
8614 }
8615 
8628 inline nlohmann::json operator "" _json(const char* s, std::size_t)
8629 {
8630  return nlohmann::json::parse(reinterpret_cast<const nlohmann::json::string_t::value_type*>(s));
8631 }
8632 
8633 // restore GCC/clang diagnostic settings
8634 #if defined(__clang__) || defined(__GNUC__) || defined(__GNUG__)
8635  #pragma GCC diagnostic pop
8636 #endif
8637 
8638 #endif
bool is_null() const noexcept
return whether value is null
Definition: json.hpp:2140
reference operator*()
return a reference to the value pointed to by the iterator
Definition: json.hpp:6764
reverse_iterator rbegin()
returns an iterator to the reverse-beginning
Definition: json.hpp:4144
friend bool operator<=(const_reference lhs, const_reference rhs) noexcept
comparison: less than or equal
Definition: json.hpp:5402
basic_json(const value_t value_type)
create an empty value with a given type
Definition: json.hpp:945
basic_json(const array_t &val)
create an array (explicit)
Definition: json.hpp:1073
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:2070
bool is_number_integer() const noexcept
return whether value is an integer number
Definition: json.hpp:2212
const_reference operator[](size_type idx) const
access specified array element
Definition: json.hpp:3174
reference value() const
return the value of an iterator
Definition: json.hpp:6848
json_reverse_iterator & operator--()
pre-decrement (–it)
Definition: json.hpp:6910
bool is_boolean() const noexcept
return whether value is a boolean
Definition: json.hpp:2159
void clear() noexcept
clears the contents
Definition: json.hpp:4512
bool operator==(const const_iterator &other) const
comparison: equal
Definition: json.hpp:6498
json_reverse_iterator operator--(int)
post-decrement (it–)
Definition: json.hpp:6904
reference operator[](T *(&key)[n])
access specified object element
Definition: json.hpp:3306
friend std::istream & operator>>(std::istream &i, basic_json &j)
deserialize from stream
Definition: json.hpp:5615
bool is_number() const noexcept
return whether value is a number
Definition: json.hpp:2186
iterator & operator+=(difference_type i)
add to iterator
Definition: json.hpp:6806
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:1652
const_iterator operator-(difference_type i)
subtract from iterator
Definition: json.hpp:6624
BooleanType boolean_t
a type for a boolean
Definition: json.hpp:447
reference operator+=(const typename object_t::value_type &val)
add an object to an object
Definition: json.hpp:4698
bool is_array() const noexcept
return whether value is an array
Definition: json.hpp:2300
basic_json(const typename string_t::value_type *val)
create a string (explicit)
Definition: json.hpp:1163
basic_json(boolean_t val)
create a boolean (explicit)
Definition: json.hpp:1212
reference operator[](difference_type n) const
access to successor
Definition: json.hpp:6946
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:1341
friend bool operator!=(const_reference lhs, const_reference rhs) noexcept
comparison: not equal
Definition: json.hpp:5240
basic_json(const string_t &val)
create a string (explicit)
Definition: json.hpp:1139
void push_back(const basic_json &val)
add an object to an array
Definition: json.hpp:4624
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:8572
ArrayType< basic_json, AllocatorType< basic_json >> array_t
a type for an array
Definition: json.hpp:374
bool is_structured() const noexcept
return whether type is structured
Definition: json.hpp:2121
reference front()
access the first element
Definition: json.hpp:3545
void swap(object_t &other)
exchanges the values
Definition: json.hpp:4996
json_reverse_iterator operator-(difference_type i) const
subtract from iterator
Definition: json.hpp:6932
const_iterator & operator+=(difference_type i)
add to iterator
Definition: json.hpp:6582
a class to store JSON values
Definition: json.hpp:168
basic_json(const number_float_t val)
create a floating-point number (explicit)
Definition: json.hpp:1401
pointer operator->()
dereference the iterator
Definition: json.hpp:6770
reference value() const
return the value of an iterator
Definition: json.hpp:6959
friend bool operator==(std::nullptr_t, const_reference v) noexcept
comparison: equal
Definition: json.hpp:5219
const_reverse_iterator crbegin() const
returns a const reverse iterator to the last element
Definition: json.hpp:4218
NumberIntegerType number_integer_t
a type for a number (integer)
Definition: json.hpp:518
iterator insert(const_iterator pos, size_type cnt, const basic_json &val)
inserts elements
Definition: json.hpp:4782
const_reference at(const typename object_t::key_type &key) const
access specified object element with bounds checking
Definition: json.hpp:3082
const_iterator operator+(difference_type i)
add to iterator
Definition: json.hpp:6616
const_reverse_iterator rbegin() const
returns a const reverse iterator to the last element
Definition: json.hpp:4152
a mutable random access iterator for the basic_json class
Definition: json.hpp:6731
static basic_json parse(std::istream &&i, parser_callback_t cb=nullptr)
deserialize from stream
Definition: json.hpp:5577
const_iterator operator++(int)
post-increment (it++)
Definition: json.hpp:6424
bool is_string() const noexcept
return whether value is a string
Definition: json.hpp:2319
ObjectType< StringType, basic_json, std::less< StringType >, AllocatorType< std::pair< const StringType, basic_json >>> object_t
a type for an object
Definition: json.hpp:328
STL namespace.
NumberUnsignedType number_unsigned_t
a type for a number (unsigned)
Definition: json.hpp:590
typename std::allocator_traits< allocator_type >::const_pointer const_pointer
the type of an element const pointer
Definition: json.hpp:209
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:1612
static iteration_proxy< const_iterator > iterator_wrapper(const_reference cont)
wrapper to access iterator member functions in range-based for
Definition: json.hpp:4276
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:1942
typename basic_json::value_type value_type
the type of the values when the iterator is dereferenced
Definition: json.hpp:6196
PointerType get_ptr() noexcept
get a pointer value (implicit)
Definition: json.hpp:2796
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:196
typename basic_json::const_pointer pointer
defines a pointer to the type iterated over (value_type)
Definition: json.hpp:6200
bool is_number_unsigned() const noexcept
return whether value is an unsigned integer number
Definition: json.hpp:2237
void push_back(const typename object_t::value_type &val)
add an object to an object
Definition: json.hpp:4674
iterator end()
returns an iterator to one past the last element
Definition: json.hpp:4074
static basic_json parse(const string_t &s, parser_callback_t cb=nullptr)
deserialize from string
Definition: json.hpp:5540
const_reference operator[](T *(&key)[n]) const
read-only access specified object element
Definition: json.hpp:3341
iterator insert(const_iterator pos, const_iterator first, const_iterator last)
inserts elements
Definition: json.hpp:4835
basic_json(std::nullptr_t) noexcept
create a null object (explicitly)
Definition: json.hpp:991
basic_json(InputIT first, InputIT last)
construct a JSON container given an iterator range
Definition: json.hpp:1722
reference operator[](difference_type n) const
access to successor
Definition: json.hpp:6842
static allocator_type get_allocator()
returns the allocator associated with the container
Definition: json.hpp:229
const_reference operator[](const typename object_t::key_type &key) const
read-only access specified object element
Definition: json.hpp:3263
const_reference operator[](T *key) const
read-only access specified object element
Definition: json.hpp:3423
json_reverse_iterator operator+(difference_type i) const
add to iterator
Definition: json.hpp:6924
bool empty() const noexcept
checks whether the container is empty
Definition: json.hpp:4324
std::size_t size_type
a type to represent container sizes
Definition: json.hpp:201
object_t::key_type key() const
return the key of an object iterator
Definition: json.hpp:6952
basic_json(const CompatibleArrayType &val)
create an array (implicit)
Definition: json.hpp:1110
const_reference at(size_type idx) const
access specified array element with bounds checking
Definition: json.hpp:2986
basic_json(size_type cnt, const basic_json &val)
construct an array with count copies of given value
Definition: json.hpp:1676
std::reverse_iterator< Base > base_iterator
shortcut to the reverse iterator adaptor
Definition: json.hpp:6876
iterator insert(const_iterator pos, std::initializer_list< basic_json > ilist)
inserts elements
Definition: json.hpp:4893
const_iterator(const iterator &other)
copy constructor given a nonconst iterator
Definition: json.hpp:6237
typename std::allocator_traits< allocator_type >::pointer pointer
the type of an element pointer
Definition: json.hpp:207
iterator insert(const_iterator pos, const basic_json &val)
inserts element
Definition: json.hpp:4726
friend bool operator>=(const_reference lhs, const_reference rhs) noexcept
comparison: greater than or equal
Definition: json.hpp:5446
friend bool operator<(const_reference lhs, const_reference rhs) noexcept
comparison: less than
Definition: json.hpp:5301
iterator & operator++()
pre-increment (++it)
Definition: json.hpp:6784
bool operator<(const const_iterator &other) const
comparison: smaller
Definition: json.hpp:6534
iterator operator++(int)
post-increment (it++)
Definition: json.hpp:6776
basic_json(basic_json &&other) noexcept
move constructor
Definition: json.hpp:1910
const_iterator operator--(int)
post-decrement (it–)
Definition: json.hpp:6461
bool is_discarded() const noexcept
return whether value is discarded
Definition: json.hpp:2343
reference at(const typename object_t::key_type &key)
access specified object element with bounds checking
Definition: json.hpp:3034
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:6752
object (unordered set of name/value pairs)
size_type max_size() const noexcept
returns the maximum possible number of elements
Definition: json.hpp:4453
~basic_json()
destructor
Definition: json.hpp:1970
iterator operator--(int)
post-decrement (it–)
Definition: json.hpp:6791
iterator operator-(difference_type i)
subtract from iterator
Definition: json.hpp:6828
const_iterator & operator--()
pre-decrement (–it)
Definition: json.hpp:6469
const_iterator cend() const
returns a const iterator to one past the last element
Definition: json.hpp:4114
string_t dump(const int indent=-1) const
serialization
Definition: json.hpp:2039
basic_json value_type
the type of elements in a basic_json container
Definition: json.hpp:191
std::function< bool(int depth, parse_event_t event, basic_json &parsed)> parser_callback_t
per-element parser callback type
Definition: json.hpp:896
AllocatorType< basic_json > allocator_type
the allocator type
Definition: json.hpp:204
StringType string_t
a type for a string
Definition: json.hpp:421
reference operator+=(const basic_json &val)
add an object to an array
Definition: json.hpp:4648
iterator begin()
returns an iterator to the first element
Definition: json.hpp:4003
difference_type operator-(const const_iterator &other) const
return difference
Definition: json.hpp:6632
value_type & reference
the type of an element reference
Definition: json.hpp:194
const_iterator begin() const
returns a const iterator to the first element
Definition: json.hpp:4013
friend std::ostream & operator>>(const basic_json &j, std::ostream &o)
serialize to stream
Definition: json.hpp:5501
difference_type operator-(const iterator &other) const
return difference
Definition: json.hpp:6836
basic_json(const int val)
create an integer number from an enum type (explicit)
Definition: json.hpp:1276
iterator(const iterator &other) noexcept
copy constructor
Definition: json.hpp:6747
namespace for Niels Lohmann
Definition: json.hpp:61
typename basic_json::difference_type difference_type
a type to represent differences between iterators
Definition: json.hpp:6198
void swap(string_t &other)
exchanges the values
Definition: json.hpp:5030
json_reverse_iterator(const base_iterator &it)
create reverse iterator from base class
Definition: json.hpp:6886
basic_json(const number_integer_t val)
create an integer number (explicit)
Definition: json.hpp:1247
reverse_iterator rend()
returns an iterator to the reverse-end
Definition: json.hpp:4181
basic_json(const CompatibleNumberIntegerType val) noexcept
create an integer number (implicit)
Definition: json.hpp:1313
const_reference front() const
access the first element
Definition: json.hpp:3553
bool operator>(const const_iterator &other) const
comparison: greater than
Definition: json.hpp:6570
bool is_object() const noexcept
return whether value is an object
Definition: json.hpp:2281
pointer operator->() const
dereference the iterator
Definition: json.hpp:6389
NumberFloatType number_float_t
a type for a number (floating-point)
Definition: json.hpp:658
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:4931
value_t
the JSON type enumeration
Definition: json.hpp:677
const_reverse_iterator rend() const
returns a const reverse iterator to one before the first
Definition: json.hpp:4189
std::ptrdiff_t difference_type
a type to represent differences between iterators
Definition: json.hpp:199
bool is_primitive() const noexcept
return whether type is primitive
Definition: json.hpp:2097
ValueType get() const
get a value (explicit)
Definition: json.hpp:2712
void swap(array_t &other)
exchanges the values
Definition: json.hpp:4962
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:3490
typename Base::reference reference
the reference type for the pointed-to element
Definition: json.hpp:6878
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:4588
array (ordered collection of values)
json_reverse_iterator & operator++()
pre-increment (++it)
Definition: json.hpp:6897
static basic_json parse(std::istream &i, parser_callback_t cb=nullptr)
deserialize from stream
Definition: json.hpp:5569
friend bool operator==(const_reference lhs, const_reference rhs) noexcept
comparison: equal
Definition: json.hpp:5111
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:3516
ReferenceType get_ref() const
get a reference value (implicit)
Definition: json.hpp:2862
basic_json(const CompatibleNumberUnsignedType val) noexcept
create an unsigned number (implicit)
Definition: json.hpp:1372
const_iterator(pointer object)
constructor for a given JSON instance
Definition: json.hpp:6210
reference operator*() const
return a reference to the value pointed to by the iterator
Definition: json.hpp:6349
friend bool operator<(const value_t lhs, const value_t rhs)
comparison operator for JSON types
Definition: json.hpp:5064
const PointerType get_ptr() const noexcept
get a pointer value (implicit)
Definition: json.hpp:2811
friend bool operator!=(const_reference v, std::nullptr_t) noexcept
comparison: not equal
Definition: json.hpp:5263
iterator operator+(difference_type i)
add to iterator
Definition: json.hpp:6820
basic_json(const CompatibleNumberFloatType val) noexcept
create an floating-point number (implicit)
Definition: json.hpp:1447
bool operator<=(const const_iterator &other) const
comparison: less than or equal
Definition: json.hpp:6564
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:1520
iterator(pointer object) noexcept
constructor for a given JSON instance
Definition: json.hpp:6742
friend bool operator!=(std::nullptr_t, const_reference v) noexcept
comparison: not equal
Definition: json.hpp:5272
json_reverse_iterator(const typename base_iterator::iterator_type &it)
create reverse iterator from iterator
Definition: json.hpp:6881
const_iterator & operator++()
pre-increment (++it)
Definition: json.hpp:6432
bool is_number_float() const noexcept
return whether value is a floating-point number
Definition: json.hpp:2262
reference value() const
return the value of an iterator
Definition: json.hpp:6707
std::bidirectional_iterator_tag iterator_category
the category of the iterator
Definition: json.hpp:6204
difference_type operator-(const json_reverse_iterator &other) const
return difference
Definition: json.hpp:6940
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:1046
friend bool operator>(const_reference lhs, const_reference rhs) noexcept
comparison: greater than
Definition: json.hpp:5424
bool operator>=(const const_iterator &other) const
comparison: greater than or equal
Definition: json.hpp:6576
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:6269
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:3215
object_t::key_type key() const
return the key of an object iterator
Definition: json.hpp:6692
const_iterator end() const
returns a const iterator to one past the last element
Definition: json.hpp:4084
reference operator+=(basic_json &&val)
add an object to an array
Definition: json.hpp:4614
reference operator[](difference_type n) const
access to successor
Definition: json.hpp:6656
a const random access iterator for the basic_json class
Definition: json.hpp:6189
a template for a reverse iterator class
Definition: json.hpp:212
typename basic_json::const_reference reference
defines a reference to the type iterated over (value_type)
Definition: json.hpp:6202
json_reverse_iterator operator++(int)
post-increment (it++)
Definition: json.hpp:6891
friend bool operator==(const_reference v, std::nullptr_t) noexcept
comparison: equal
Definition: json.hpp:5210
reference operator[](size_type idx)
access specified array element
Definition: json.hpp:3129
bool operator!=(const const_iterator &other) const
comparison: not equal
Definition: json.hpp:6528
json_reverse_iterator & operator+=(difference_type i)
add to iterator
Definition: json.hpp:6917
reference at(size_type idx)
access specified array element with bounds checking
Definition: json.hpp:2942
size_type size() const noexcept
returns the number of elements
Definition: json.hpp:4387
static iteration_proxy< iterator > iterator_wrapper(reference cont)
wrapper to access iterator member functions in range-based for
Definition: json.hpp:4268
const_iterator cbegin() const
returns a const iterator to the first element
Definition: json.hpp:4043
iterator & operator-=(difference_type i)
subtract from iterator
Definition: json.hpp:6813
const_reverse_iterator crend() const
returns a const reverse iterator to one before the first
Definition: json.hpp:4247
basic_json(const object_t &val)
create an object (explicit)
Definition: json.hpp:1014
friend std::istream & operator<<(basic_json &j, std::istream &i)
deserialize from stream
Definition: json.hpp:5605
std::size_t operator()(const nlohmann::json &j) const
return a hash value for a JSON object
Definition: json.hpp:8607
friend std::ostream & operator<<(std::ostream &o, const basic_json &j)
serialize to stream
Definition: json.hpp:5483
const_iterator(const const_iterator &other) noexcept
copy constructor
Definition: json.hpp:6264
iterator & operator--()
pre-decrement (–it)
Definition: json.hpp:6799
iterator insert(const_iterator pos, basic_json &&val)
inserts element
Definition: json.hpp:4753
ReferenceType get_ref()
get a reference value (implicit)
Definition: json.hpp:2847
const_iterator & operator-=(difference_type i)
subtract from iterator
Definition: json.hpp:6610
basic_json(const CompatibleStringType &val)
create a string (implicit)
Definition: json.hpp:1194
basic_json(const basic_json &other)
copy constructor
Definition: json.hpp:1835
reference operator[](T *key)
access specified object element
Definition: json.hpp:3374
parse_event_t
JSON callback events.
Definition: json.hpp:831