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 
968  basic_json() noexcept = default;
969 
989  basic_json(std::nullptr_t) noexcept
990  : basic_json(value_t::null)
991  {}
992 
1012  basic_json(const object_t& val)
1013  : m_type(value_t::object), m_value(val)
1014  {}
1015 
1039  template <class CompatibleObjectType, typename
1040  std::enable_if<
1041  std::is_constructible<typename object_t::key_type, typename CompatibleObjectType::key_type>::value and
1042  std::is_constructible<basic_json, typename CompatibleObjectType::mapped_type>::value, int>::type
1043  = 0>
1044  basic_json(const CompatibleObjectType& val)
1045  : m_type(value_t::object)
1046  {
1047  using std::begin;
1048  using std::end;
1049  m_value.object = create<object_t>(begin(val), end(val));
1050  }
1051 
1071  basic_json(const array_t& val)
1072  : m_type(value_t::array), m_value(val)
1073  {}
1074 
1098  template <class CompatibleArrayType, typename
1099  std::enable_if<
1100  not std::is_same<CompatibleArrayType, typename basic_json_t::iterator>::value and
1101  not std::is_same<CompatibleArrayType, typename basic_json_t::const_iterator>::value and
1102  not std::is_same<CompatibleArrayType, typename basic_json_t::reverse_iterator>::value and
1103  not std::is_same<CompatibleArrayType, typename basic_json_t::const_reverse_iterator>::value and
1104  not std::is_same<CompatibleArrayType, typename array_t::iterator>::value and
1105  not std::is_same<CompatibleArrayType, typename array_t::const_iterator>::value and
1106  std::is_constructible<basic_json, typename CompatibleArrayType::value_type>::value, int>::type
1107  = 0>
1108  basic_json(const CompatibleArrayType& val)
1109  : m_type(value_t::array)
1110  {
1111  using std::begin;
1112  using std::end;
1113  m_value.array = create<array_t>(begin(val), end(val));
1114  }
1115 
1137  basic_json(const string_t& val)
1138  : m_type(value_t::string), m_value(val)
1139  {}
1140 
1161  basic_json(const typename string_t::value_type* val)
1162  : basic_json(string_t(val))
1163  {}
1164 
1188  template <class CompatibleStringType, typename
1189  std::enable_if<
1190  std::is_constructible<string_t, CompatibleStringType>::value, int>::type
1191  = 0>
1192  basic_json(const CompatibleStringType& val)
1193  : basic_json(string_t(val))
1194  {}
1195 
1211  : m_type(value_t::boolean), m_value(val)
1212  {}
1213 
1239  template<typename T,
1240  typename std::enable_if<
1241  not (std::is_same<T, int>::value)
1242  and std::is_same<T, number_integer_t>::value
1243  , int>::type
1244  = 0>
1246  : m_type(value_t::number_integer), m_value(val)
1247  {}
1248 
1274  basic_json(const int val)
1275  : m_type(value_t::number_integer),
1276  m_value(static_cast<number_integer_t>(val))
1277  {}
1278 
1304  template<typename CompatibleNumberIntegerType, typename
1305  std::enable_if<
1306  std::is_constructible<number_integer_t, CompatibleNumberIntegerType>::value and
1307  std::numeric_limits<CompatibleNumberIntegerType>::is_integer and
1308  std::numeric_limits<CompatibleNumberIntegerType>::is_signed,
1309  CompatibleNumberIntegerType>::type
1310  = 0>
1311  basic_json(const CompatibleNumberIntegerType val) noexcept
1312  : m_type(value_t::number_integer),
1313  m_value(static_cast<number_integer_t>(val))
1314  {}
1315 
1333  template<typename T,
1334  typename std::enable_if<
1335  not (std::is_same<T, int>::value)
1336  and std::is_same<T, number_unsigned_t>::value
1337  , int>::type
1338  = 0>
1340  : m_type(value_t::number_unsigned), m_value(val)
1341  {}
1342 
1363  template < typename CompatibleNumberUnsignedType, typename
1364  std::enable_if <
1365  std::is_constructible<number_unsigned_t, CompatibleNumberUnsignedType>::value and
1366  std::numeric_limits<CompatibleNumberUnsignedType>::is_integer and
1367  !std::numeric_limits<CompatibleNumberUnsignedType>::is_signed,
1368  CompatibleNumberUnsignedType >::type
1369  = 0 >
1370  basic_json(const CompatibleNumberUnsignedType val) noexcept
1371  : m_type(value_t::number_unsigned),
1372  m_value(static_cast<number_unsigned_t>(val))
1373  {}
1374 
1400  : m_type(value_t::number_float), m_value(val)
1401  {
1402  // replace infinity and NAN by null
1403  if (not std::isfinite(val))
1404  {
1405  m_type = value_t::null;
1406  m_value = json_value();
1407  }
1408  }
1409 
1440  template<typename CompatibleNumberFloatType, typename = typename
1441  std::enable_if<
1442  std::is_constructible<number_float_t, CompatibleNumberFloatType>::value and
1443  std::is_floating_point<CompatibleNumberFloatType>::value>::type
1444  >
1445  basic_json(const CompatibleNumberFloatType val) noexcept
1446  : basic_json(number_float_t(val))
1447  {}
1448 
1518  basic_json(std::initializer_list<basic_json> init,
1519  bool type_deduction = true,
1520  value_t manual_type = value_t::array)
1521  {
1522  // the initializer list could describe an object
1523  bool is_an_object = true;
1524 
1525  // check if each element is an array with two elements whose first
1526  // element is a string
1527  for (const auto& element : init)
1528  {
1529  if (not element.is_array() or element.size() != 2
1530  or not element[0].is_string())
1531  {
1532  // we found an element that makes it impossible to use the
1533  // initializer list as object
1534  is_an_object = false;
1535  break;
1536  }
1537  }
1538 
1539  // adjust type if type deduction is not wanted
1540  if (not type_deduction)
1541  {
1542  // if array is wanted, do not create an object though possible
1543  if (manual_type == value_t::array)
1544  {
1545  is_an_object = false;
1546  }
1547 
1548  // if object is wanted but impossible, throw an exception
1549  if (manual_type == value_t::object and not is_an_object)
1550  {
1551  throw std::domain_error("cannot create object from initializer list");
1552  }
1553  }
1554 
1555  if (is_an_object)
1556  {
1557  // the initializer list is a list of pairs -> create object
1558  m_type = value_t::object;
1559  m_value = value_t::object;
1560 
1561  assert(m_value.object != nullptr);
1562 
1563  for (auto& element : init)
1564  {
1565  m_value.object->emplace(std::move(*(element[0].m_value.string)), std::move(element[1]));
1566  }
1567  }
1568  else
1569  {
1570  // the initializer list describes an array -> create array
1571  m_type = value_t::array;
1572  m_value.array = create<array_t>(std::move(init));
1573  }
1574  }
1575 
1610  static basic_json array(std::initializer_list<basic_json> init =
1611  std::initializer_list<basic_json>())
1612  {
1613  return basic_json(init, false, value_t::array);
1614  }
1615 
1650  static basic_json object(std::initializer_list<basic_json> init =
1651  std::initializer_list<basic_json>())
1652  {
1653  return basic_json(init, false, value_t::object);
1654  }
1655 
1674  basic_json(size_type cnt, const basic_json& val)
1675  : m_type(value_t::array)
1676  {
1677  m_value.array = create<array_t>(cnt, val);
1678  }
1679 
1714  template <class InputIT, typename
1715  std::enable_if<
1716  std::is_same<InputIT, typename basic_json_t::iterator>::value or
1717  std::is_same<InputIT, typename basic_json_t::const_iterator>::value
1718  , int>::type
1719  = 0>
1720  basic_json(InputIT first, InputIT last) : m_type(first.m_object->m_type)
1721  {
1722  // make sure iterator fits the current value
1723  if (first.m_object != last.m_object)
1724  {
1725  throw std::domain_error("iterators are not compatible");
1726  }
1727 
1728  // check if iterator range is complete for primitive values
1729  switch (m_type)
1730  {
1731  case value_t::boolean:
1732  case value_t::number_float:
1733  case value_t::number_integer:
1734  case value_t::number_unsigned:
1735  case value_t::string:
1736  {
1737  if (not first.m_it.primitive_iterator.is_begin() or not last.m_it.primitive_iterator.is_end())
1738  {
1739  throw std::out_of_range("iterators out of range");
1740  }
1741  break;
1742  }
1743 
1744  default:
1745  {
1746  break;
1747  }
1748  }
1749 
1750  switch (m_type)
1751  {
1752  case value_t::number_integer:
1753  {
1754  assert(first.m_object != nullptr);
1755  m_value.number_integer = first.m_object->m_value.number_integer;
1756  break;
1757  }
1758 
1759  case value_t::number_unsigned:
1760  {
1761  assert(first.m_object != nullptr);
1762  m_value.number_unsigned = first.m_object->m_value.number_unsigned;
1763  break;
1764  }
1765 
1766  case value_t::number_float:
1767  {
1768  assert(first.m_object != nullptr);
1769  m_value.number_float = first.m_object->m_value.number_float;
1770  break;
1771  }
1772 
1773  case value_t::boolean:
1774  {
1775  assert(first.m_object != nullptr);
1776  m_value.boolean = first.m_object->m_value.boolean;
1777  break;
1778  }
1779 
1780  case value_t::string:
1781  {
1782  assert(first.m_object != nullptr);
1783  m_value = *first.m_object->m_value.string;
1784  break;
1785  }
1786 
1787  case value_t::object:
1788  {
1789  m_value.object = create<object_t>(first.m_it.object_iterator, last.m_it.object_iterator);
1790  break;
1791  }
1792 
1793  case value_t::array:
1794  {
1795  m_value.array = create<array_t>(first.m_it.array_iterator, last.m_it.array_iterator);
1796  break;
1797  }
1798 
1799  default:
1800  {
1801  assert(first.m_object != nullptr);
1802  throw std::domain_error("cannot use construct with iterators from " + first.m_object->type_name());
1803  }
1804  }
1805  }
1806 
1808  // other constructors and destructor //
1810 
1831  basic_json(const basic_json& other)
1832  : m_type(other.m_type)
1833  {
1834  switch (m_type)
1835  {
1836  case value_t::object:
1837  {
1838  assert(other.m_value.object != nullptr);
1839  m_value = *other.m_value.object;
1840  break;
1841  }
1842 
1843  case value_t::array:
1844  {
1845  assert(other.m_value.array != nullptr);
1846  m_value = *other.m_value.array;
1847  break;
1848  }
1849 
1850  case value_t::string:
1851  {
1852  assert(other.m_value.string != nullptr);
1853  m_value = *other.m_value.string;
1854  break;
1855  }
1856 
1857  case value_t::boolean:
1858  {
1859  m_value = other.m_value.boolean;
1860  break;
1861  }
1862 
1863  case value_t::number_integer:
1864  {
1865  m_value = other.m_value.number_integer;
1866  break;
1867  }
1868 
1869  case value_t::number_unsigned:
1870  {
1871  m_value = other.m_value.number_unsigned;
1872  break;
1873  }
1874 
1875  case value_t::number_float:
1876  {
1877  m_value = other.m_value.number_float;
1878  break;
1879  }
1880 
1881  default:
1882  {
1883  break;
1884  }
1885  }
1886  }
1887 
1906  basic_json(basic_json&& other) noexcept
1907  : m_type(std::move(other.m_type)),
1908  m_value(std::move(other.m_value))
1909  {
1910  // invalidate payload
1911  other.m_type = value_t::null;
1912  other.m_value = {};
1913  }
1914 
1936  reference& operator=(basic_json other) noexcept (
1937  std::is_nothrow_move_constructible<value_t>::value and
1938  std::is_nothrow_move_assignable<value_t>::value and
1939  std::is_nothrow_move_constructible<json_value>::value and
1940  std::is_nothrow_move_assignable<json_value>::value
1941  )
1942  {
1943  using std::swap;
1944  swap(m_type, other.m_type);
1945  swap(m_value, other.m_value);
1946  return *this;
1947  }
1948 
1963  {
1964  switch (m_type)
1965  {
1966  case value_t::object:
1967  {
1968  AllocatorType<object_t> alloc;
1969  alloc.destroy(m_value.object);
1970  alloc.deallocate(m_value.object, 1);
1971  break;
1972  }
1973 
1974  case value_t::array:
1975  {
1976  AllocatorType<array_t> alloc;
1977  alloc.destroy(m_value.array);
1978  alloc.deallocate(m_value.array, 1);
1979  break;
1980  }
1981 
1982  case value_t::string:
1983  {
1984  AllocatorType<string_t> alloc;
1985  alloc.destroy(m_value.string);
1986  alloc.deallocate(m_value.string, 1);
1987  break;
1988  }
1989 
1990  default:
1991  {
1992  // all other types need no specific destructor
1993  break;
1994  }
1995  }
1996  }
1997 
1999 
2000  public:
2002  // object inspection //
2004 
2007 
2031  string_t dump(const int indent = -1) const
2032  {
2033  std::stringstream ss;
2034 
2035  if (indent >= 0)
2036  {
2037  dump(ss, true, static_cast<unsigned int>(indent));
2038  }
2039  else
2040  {
2041  dump(ss, false, 0);
2042  }
2043 
2044  return ss.str();
2045  }
2046 
2062  value_t type() const noexcept
2063  {
2064  return m_type;
2065  }
2066 
2083  bool is_primitive() const noexcept
2084  {
2085  return is_null() or is_string() or is_boolean() or is_number();
2086  }
2087 
2103  bool is_structured() const noexcept
2104  {
2105  return is_array() or is_object();
2106  }
2107 
2122  bool is_null() const noexcept
2123  {
2124  return m_type == value_t::null;
2125  }
2126 
2141  bool is_boolean() const noexcept
2142  {
2143  return m_type == value_t::boolean;
2144  }
2145 
2168  bool is_number() const noexcept
2169  {
2170  return is_number_integer() or is_number_float();
2171  }
2172 
2194  bool is_number_integer() const noexcept
2195  {
2196  return m_type == value_t::number_integer or m_type == value_t::number_unsigned;
2197  }
2198 
2219  bool is_number_unsigned() const noexcept
2220  {
2221  return m_type == value_t::number_unsigned;
2222  }
2223 
2244  bool is_number_float() const noexcept
2245  {
2246  return m_type == value_t::number_float;
2247  }
2248 
2263  bool is_object() const noexcept
2264  {
2265  return m_type == value_t::object;
2266  }
2267 
2282  bool is_array() const noexcept
2283  {
2284  return m_type == value_t::array;
2285  }
2286 
2301  bool is_string() const noexcept
2302  {
2303  return m_type == value_t::string;
2304  }
2305 
2325  bool is_discarded() const noexcept
2326  {
2327  return m_type == value_t::discarded;
2328  }
2329 
2345  operator value_t() const noexcept
2346  {
2347  return m_type;
2348  }
2349 
2351 
2352  private:
2354  // value access //
2356 
2358  template <class T, typename
2359  std::enable_if<
2360  std::is_convertible<typename object_t::key_type, typename T::key_type>::value and
2361  std::is_convertible<basic_json_t, typename T::mapped_type>::value
2362  , int>::type = 0>
2363  T get_impl(T*) const
2364  {
2365  if (is_object())
2366  {
2367  assert(m_value.object != nullptr);
2368  return T(m_value.object->begin(), m_value.object->end());
2369  }
2370  else
2371  {
2372  throw std::domain_error("type must be object, but is " + type_name());
2373  }
2374  }
2375 
2377  object_t get_impl(object_t*) const
2378  {
2379  if (is_object())
2380  {
2381  assert(m_value.object != nullptr);
2382  return *(m_value.object);
2383  }
2384  else
2385  {
2386  throw std::domain_error("type must be object, but is " + type_name());
2387  }
2388  }
2389 
2391  template <class T, typename
2392  std::enable_if<
2393  std::is_convertible<basic_json_t, typename T::value_type>::value and
2394  not std::is_same<basic_json_t, typename T::value_type>::value and
2395  not std::is_arithmetic<T>::value and
2396  not std::is_convertible<std::string, T>::value and
2397  not has_mapped_type<T>::value
2398  , int>::type = 0>
2399  T get_impl(T*) const
2400  {
2401  if (is_array())
2402  {
2403  T to_vector;
2404  assert(m_value.array != nullptr);
2405  std::transform(m_value.array->begin(), m_value.array->end(),
2406  std::inserter(to_vector, to_vector.end()), [](basic_json i)
2407  {
2408  return i.get<typename T::value_type>();
2409  });
2410  return to_vector;
2411  }
2412  else
2413  {
2414  throw std::domain_error("type must be array, but is " + type_name());
2415  }
2416  }
2417 
2419  template <class T, typename
2420  std::enable_if<
2421  std::is_convertible<basic_json_t, T>::value and
2422  not std::is_same<basic_json_t, T>::value
2423  , int>::type = 0>
2424  std::vector<T> get_impl(std::vector<T>*) const
2425  {
2426  if (is_array())
2427  {
2428  std::vector<T> to_vector;
2429  assert(m_value.array != nullptr);
2430  to_vector.reserve(m_value.array->size());
2431  std::transform(m_value.array->begin(), m_value.array->end(),
2432  std::inserter(to_vector, to_vector.end()), [](basic_json i)
2433  {
2434  return i.get<T>();
2435  });
2436  return to_vector;
2437  }
2438  else
2439  {
2440  throw std::domain_error("type must be array, but is " + type_name());
2441  }
2442  }
2443 
2445  template <class T, typename
2446  std::enable_if<
2447  std::is_same<basic_json, typename T::value_type>::value and
2448  not has_mapped_type<T>::value
2449  , int>::type = 0>
2450  T get_impl(T*) const
2451  {
2452  if (is_array())
2453  {
2454  assert(m_value.array != nullptr);
2455  return T(m_value.array->begin(), m_value.array->end());
2456  }
2457  else
2458  {
2459  throw std::domain_error("type must be array, but is " + type_name());
2460  }
2461  }
2462 
2464  array_t get_impl(array_t*) const
2465  {
2466  if (is_array())
2467  {
2468  assert(m_value.array != nullptr);
2469  return *(m_value.array);
2470  }
2471  else
2472  {
2473  throw std::domain_error("type must be array, but is " + type_name());
2474  }
2475  }
2476 
2478  template <typename T, typename
2479  std::enable_if<
2480  std::is_convertible<string_t, T>::value
2481  , int>::type = 0>
2482  T get_impl(T*) const
2483  {
2484  if (is_string())
2485  {
2486  assert(m_value.string != nullptr);
2487  return *m_value.string;
2488  }
2489  else
2490  {
2491  throw std::domain_error("type must be string, but is " + type_name());
2492  }
2493  }
2494 
2496  template<typename T, typename
2497  std::enable_if<
2498  std::is_arithmetic<T>::value
2499  , int>::type = 0>
2500  T get_impl(T*) const
2501  {
2502  switch (m_type)
2503  {
2504  case value_t::number_integer:
2505  {
2506  return static_cast<T>(m_value.number_integer);
2507  }
2508 
2509  case value_t::number_unsigned:
2510  {
2511  return static_cast<T>(m_value.number_unsigned);
2512  }
2513 
2514  case value_t::number_float:
2515  {
2516  return static_cast<T>(m_value.number_float);
2517  }
2518 
2519  default:
2520  {
2521  throw std::domain_error("type must be number, but is " + type_name());
2522  }
2523  }
2524  }
2525 
2527  boolean_t get_impl(boolean_t*) const
2528  {
2529  if (is_boolean())
2530  {
2531  return m_value.boolean;
2532  }
2533  else
2534  {
2535  throw std::domain_error("type must be boolean, but is " + type_name());
2536  }
2537  }
2538 
2540  object_t* get_impl_ptr(object_t*) noexcept
2541  {
2542  return is_object() ? m_value.object : nullptr;
2543  }
2544 
2546  const object_t* get_impl_ptr(const object_t*) const noexcept
2547  {
2548  return is_object() ? m_value.object : nullptr;
2549  }
2550 
2552  array_t* get_impl_ptr(array_t*) noexcept
2553  {
2554  return is_array() ? m_value.array : nullptr;
2555  }
2556 
2558  const array_t* get_impl_ptr(const array_t*) const noexcept
2559  {
2560  return is_array() ? m_value.array : nullptr;
2561  }
2562 
2564  string_t* get_impl_ptr(string_t*) noexcept
2565  {
2566  return is_string() ? m_value.string : nullptr;
2567  }
2568 
2570  const string_t* get_impl_ptr(const string_t*) const noexcept
2571  {
2572  return is_string() ? m_value.string : nullptr;
2573  }
2574 
2576  boolean_t* get_impl_ptr(boolean_t*) noexcept
2577  {
2578  return is_boolean() ? &m_value.boolean : nullptr;
2579  }
2580 
2582  const boolean_t* get_impl_ptr(const boolean_t*) const noexcept
2583  {
2584  return is_boolean() ? &m_value.boolean : nullptr;
2585  }
2586 
2588  number_integer_t* get_impl_ptr(number_integer_t*) noexcept
2589  {
2590  return is_number_integer() ? &m_value.number_integer : nullptr;
2591  }
2592 
2594  const number_integer_t* get_impl_ptr(const number_integer_t*) const noexcept
2595  {
2596  return is_number_integer() ? &m_value.number_integer : nullptr;
2597  }
2598 
2600  number_unsigned_t* get_impl_ptr(number_unsigned_t*) noexcept
2601  {
2602  return is_number_unsigned() ? &m_value.number_unsigned : nullptr;
2603  }
2604 
2606  const number_unsigned_t* get_impl_ptr(const number_unsigned_t*) const noexcept
2607  {
2608  return is_number_unsigned() ? &m_value.number_unsigned : nullptr;
2609  }
2610 
2612  number_float_t* get_impl_ptr(number_float_t*) noexcept
2613  {
2614  return is_number_float() ? &m_value.number_float : nullptr;
2615  }
2616 
2618  const number_float_t* get_impl_ptr(const number_float_t*) const noexcept
2619  {
2620  return is_number_float() ? &m_value.number_float : nullptr;
2621  }
2622 
2634  template<typename ReferenceType, typename ThisType>
2635  static ReferenceType get_ref_impl(ThisType& obj)
2636  {
2637  // delegate the call to get_ptr<>()
2638  using PointerType = typename std::add_pointer<ReferenceType>::type;
2639  auto ptr = obj.template get_ptr<PointerType>();
2640 
2641  if (ptr != nullptr)
2642  {
2643  return *ptr;
2644  }
2645  else
2646  {
2647  throw std::domain_error("incompatible ReferenceType for get_ref, actual type is " +
2648  obj.type_name());
2649  }
2650  }
2651 
2652  public:
2653 
2656 
2690  template<typename ValueType, typename
2691  std::enable_if<
2692  not std::is_pointer<ValueType>::value
2693  , int>::type = 0>
2694  ValueType get() const
2695  {
2696  return get_impl(static_cast<ValueType*>(nullptr));
2697  }
2698 
2725  template<typename PointerType, typename
2726  std::enable_if<
2727  std::is_pointer<PointerType>::value
2728  , int>::type = 0>
2729  PointerType get() noexcept
2730  {
2731  // delegate the call to get_ptr
2732  return get_ptr<PointerType>();
2733  }
2734 
2739  template<typename PointerType, typename
2740  std::enable_if<
2741  std::is_pointer<PointerType>::value
2742  , int>::type = 0>
2743  const PointerType get() const noexcept
2744  {
2745  // delegate the call to get_ptr
2746  return get_ptr<PointerType>();
2747  }
2748 
2774  template<typename PointerType, typename
2775  std::enable_if<
2776  std::is_pointer<PointerType>::value
2777  , int>::type = 0>
2778  PointerType get_ptr() noexcept
2779  {
2780  // delegate the call to get_impl_ptr<>()
2781  return get_impl_ptr(static_cast<PointerType>(nullptr));
2782  }
2783 
2788  template<typename PointerType, typename
2789  std::enable_if<
2790  std::is_pointer<PointerType>::value
2791  and std::is_const<typename std::remove_pointer<PointerType>::type>::value
2792  , int>::type = 0>
2793  const PointerType get_ptr() const noexcept
2794  {
2795  // delegate the call to get_impl_ptr<>() const
2796  return get_impl_ptr(static_cast<const PointerType>(nullptr));
2797  }
2798 
2825  template<typename ReferenceType, typename
2826  std::enable_if<
2827  std::is_reference<ReferenceType>::value
2828  , int>::type = 0>
2829  ReferenceType get_ref()
2830  {
2831  // delegate call to get_ref_impl
2832  return get_ref_impl<ReferenceType>(*this);
2833  }
2834 
2839  template<typename ReferenceType, typename
2840  std::enable_if<
2841  std::is_reference<ReferenceType>::value
2842  and std::is_const<typename std::remove_reference<ReferenceType>::type>::value
2843  , int>::type = 0>
2844  ReferenceType get_ref() const
2845  {
2846  // delegate call to get_ref_impl
2847  return get_ref_impl<ReferenceType>(*this);
2848  }
2849 
2878  template < typename ValueType, typename
2879  std::enable_if <
2880  not std::is_pointer<ValueType>::value
2881  and not std::is_same<ValueType, typename string_t::value_type>::value
2882 #ifndef _MSC_VER // Fix for issue #167 operator<< abiguity under VS2015
2883  and not std::is_same<ValueType, std::initializer_list<typename string_t::value_type>>::value
2884 #endif
2885  , int >::type = 0 >
2886  operator ValueType() const
2887  {
2888  // delegate the call to get<>() const
2889  return get<ValueType>();
2890  }
2891 
2893 
2894 
2896  // element access //
2898 
2901 
2925  {
2926  // at only works for arrays
2927  if (is_array())
2928  {
2929  try
2930  {
2931  assert(m_value.array != nullptr);
2932  return m_value.array->at(idx);
2933  }
2934  catch (std::out_of_range&)
2935  {
2936  // create better exception explanation
2937  throw std::out_of_range("array index " + std::to_string(idx) + " is out of range");
2938  }
2939  }
2940  else
2941  {
2942  throw std::domain_error("cannot use at() with " + type_name());
2943  }
2944  }
2945 
2969  {
2970  // at only works for arrays
2971  if (is_array())
2972  {
2973  try
2974  {
2975  assert(m_value.array != nullptr);
2976  return m_value.array->at(idx);
2977  }
2978  catch (std::out_of_range&)
2979  {
2980  // create better exception explanation
2981  throw std::out_of_range("array index " + std::to_string(idx) + " is out of range");
2982  }
2983  }
2984  else
2985  {
2986  throw std::domain_error("cannot use at() with " + type_name());
2987  }
2988  }
2989 
3016  reference at(const typename object_t::key_type& key)
3017  {
3018  // at only works for objects
3019  if (is_object())
3020  {
3021  try
3022  {
3023  assert(m_value.object != nullptr);
3024  return m_value.object->at(key);
3025  }
3026  catch (std::out_of_range&)
3027  {
3028  // create better exception explanation
3029  throw std::out_of_range("key '" + key + "' not found");
3030  }
3031  }
3032  else
3033  {
3034  throw std::domain_error("cannot use at() with " + type_name());
3035  }
3036  }
3037 
3064  const_reference at(const typename object_t::key_type& key) const
3065  {
3066  // at only works for objects
3067  if (is_object())
3068  {
3069  try
3070  {
3071  assert(m_value.object != nullptr);
3072  return m_value.object->at(key);
3073  }
3074  catch (std::out_of_range&)
3075  {
3076  // create better exception explanation
3077  throw std::out_of_range("key '" + key + "' not found");
3078  }
3079  }
3080  else
3081  {
3082  throw std::domain_error("cannot use at() with " + type_name());
3083  }
3084  }
3085 
3112  {
3113  // implicitly convert null to object
3114  if (is_null())
3115  {
3116  m_type = value_t::array;
3117  m_value.array = create<array_t>();
3118  }
3119 
3120  // [] only works for arrays
3121  if (is_array())
3122  {
3123  assert(m_value.array != nullptr);
3124  for (size_t i = m_value.array->size(); i <= idx; ++i)
3125  {
3126  m_value.array->push_back(basic_json());
3127  }
3128 
3129  return m_value.array->operator[](idx);
3130  }
3131  else
3132  {
3133  throw std::domain_error("cannot use operator[] with " + type_name());
3134  }
3135  }
3136 
3157  {
3158  // at only works for arrays
3159  if (is_array())
3160  {
3161  assert(m_value.array != nullptr);
3162  return m_value.array->operator[](idx);
3163  }
3164  else
3165  {
3166  throw std::domain_error("cannot use operator[] with " + type_name());
3167  }
3168  }
3169 
3197  reference operator[](const typename object_t::key_type& key)
3198  {
3199  // implicitly convert null to object
3200  if (is_null())
3201  {
3202  m_type = value_t::object;
3203  m_value.object = create<object_t>();
3204  }
3205 
3206  // [] only works for objects
3207  if (is_object())
3208  {
3209  assert(m_value.object != nullptr);
3210  return m_value.object->operator[](key);
3211  }
3212  else
3213  {
3214  throw std::domain_error("cannot use operator[] with " + type_name());
3215  }
3216  }
3217 
3245  const_reference operator[](const typename object_t::key_type& key) const
3246  {
3247  // [] only works for objects
3248  if (is_object())
3249  {
3250  assert(m_value.object != nullptr);
3251  assert(m_value.object->find(key) != m_value.object->end());
3252  return m_value.object->find(key)->second;
3253  }
3254  else
3255  {
3256  throw std::domain_error("cannot use operator[] with " + type_name());
3257  }
3258  }
3259 
3287  template<typename T, std::size_t n>
3288  reference operator[](T * (&key)[n])
3289  {
3290  return operator[](static_cast<const T>(key));
3291  }
3292 
3322  template<typename T, std::size_t n>
3323  const_reference operator[](T * (&key)[n]) const
3324  {
3325  return operator[](static_cast<const T>(key));
3326  }
3327 
3355  template<typename T>
3357  {
3358  // implicitly convert null to object
3359  if (is_null())
3360  {
3361  m_type = value_t::object;
3362  m_value = value_t::object;
3363  }
3364 
3365  // at only works for objects
3366  if (is_object())
3367  {
3368  assert(m_value.object != nullptr);
3369  return m_value.object->operator[](key);
3370  }
3371  else
3372  {
3373  throw std::domain_error("cannot use operator[] with " + type_name());
3374  }
3375  }
3376 
3404  template<typename T>
3406  {
3407  // at only works for objects
3408  if (is_object())
3409  {
3410  assert(m_value.object != nullptr);
3411  assert(m_value.object->find(key) != m_value.object->end());
3412  return m_value.object->find(key)->second;
3413  }
3414  else
3415  {
3416  throw std::domain_error("cannot use operator[] with " + type_name());
3417  }
3418  }
3419 
3468  template <class ValueType, typename
3469  std::enable_if<
3470  std::is_convertible<basic_json_t, ValueType>::value
3471  , int>::type = 0>
3472  ValueType value(const typename object_t::key_type& key, ValueType default_value) const
3473  {
3474  // at only works for objects
3475  if (is_object())
3476  {
3477  // if key is found, return value and given default value otherwise
3478  const auto it = find(key);
3479  if (it != end())
3480  {
3481  return *it;
3482  }
3483  else
3484  {
3485  return default_value;
3486  }
3487  }
3488  else
3489  {
3490  throw std::domain_error("cannot use value() with " + type_name());
3491  }
3492  }
3493 
3498  string_t value(const typename object_t::key_type& key, const char* default_value) const
3499  {
3500  return value(key, string_t(default_value));
3501  }
3502 
3524  {
3525  return *begin();
3526  }
3527 
3532  {
3533  return *cbegin();
3534  }
3535 
3558  {
3559  auto tmp = end();
3560  --tmp;
3561  return *tmp;
3562  }
3563 
3568  {
3569  auto tmp = cend();
3570  --tmp;
3571  return *tmp;
3572  }
3573 
3618  template <class InteratorType, typename
3619  std::enable_if<
3620  std::is_same<InteratorType, typename basic_json_t::iterator>::value or
3621  std::is_same<InteratorType, typename basic_json_t::const_iterator>::value
3622  , int>::type
3623  = 0>
3624  InteratorType erase(InteratorType pos)
3625  {
3626  // make sure iterator fits the current value
3627  if (this != pos.m_object)
3628  {
3629  throw std::domain_error("iterator does not fit current value");
3630  }
3631 
3632  InteratorType result = end();
3633 
3634  switch (m_type)
3635  {
3636  case value_t::boolean:
3637  case value_t::number_float:
3638  case value_t::number_integer:
3639  case value_t::number_unsigned:
3640  case value_t::string:
3641  {
3642  if (not pos.m_it.primitive_iterator.is_begin())
3643  {
3644  throw std::out_of_range("iterator out of range");
3645  }
3646 
3647  if (is_string())
3648  {
3649  delete m_value.string;
3650  m_value.string = nullptr;
3651  }
3652 
3653  m_type = value_t::null;
3654  break;
3655  }
3656 
3657  case value_t::object:
3658  {
3659  assert(m_value.object != nullptr);
3660  result.m_it.object_iterator = m_value.object->erase(pos.m_it.object_iterator);
3661  break;
3662  }
3663 
3664  case value_t::array:
3665  {
3666  assert(m_value.array != nullptr);
3667  result.m_it.array_iterator = m_value.array->erase(pos.m_it.array_iterator);
3668  break;
3669  }
3670 
3671  default:
3672  {
3673  throw std::domain_error("cannot use erase() with " + type_name());
3674  }
3675  }
3676 
3677  return result;
3678  }
3679 
3724  template <class InteratorType, typename
3725  std::enable_if<
3726  std::is_same<InteratorType, typename basic_json_t::iterator>::value or
3727  std::is_same<InteratorType, typename basic_json_t::const_iterator>::value
3728  , int>::type
3729  = 0>
3730  InteratorType erase(InteratorType first, InteratorType last)
3731  {
3732  // make sure iterator fits the current value
3733  if (this != first.m_object or this != last.m_object)
3734  {
3735  throw std::domain_error("iterators do not fit current value");
3736  }
3737 
3738  InteratorType result = end();
3739 
3740  switch (m_type)
3741  {
3742  case value_t::boolean:
3743  case value_t::number_float:
3744  case value_t::number_integer:
3745  case value_t::number_unsigned:
3746  case value_t::string:
3747  {
3748  if (not first.m_it.primitive_iterator.is_begin() or not last.m_it.primitive_iterator.is_end())
3749  {
3750  throw std::out_of_range("iterators out of range");
3751  }
3752 
3753  if (is_string())
3754  {
3755  delete m_value.string;
3756  m_value.string = nullptr;
3757  }
3758 
3759  m_type = value_t::null;
3760  break;
3761  }
3762 
3763  case value_t::object:
3764  {
3765  assert(m_value.object != nullptr);
3766  result.m_it.object_iterator = m_value.object->erase(first.m_it.object_iterator,
3767  last.m_it.object_iterator);
3768  break;
3769  }
3770 
3771  case value_t::array:
3772  {
3773  assert(m_value.array != nullptr);
3774  result.m_it.array_iterator = m_value.array->erase(first.m_it.array_iterator,
3775  last.m_it.array_iterator);
3776  break;
3777  }
3778 
3779  default:
3780  {
3781  throw std::domain_error("cannot use erase() with " + type_name());
3782  }
3783  }
3784 
3785  return result;
3786  }
3787 
3814  size_type erase(const typename object_t::key_type& key)
3815  {
3816  // this erase only works for objects
3817  if (is_object())
3818  {
3819  assert(m_value.object != nullptr);
3820  return m_value.object->erase(key);
3821  }
3822  else
3823  {
3824  throw std::domain_error("cannot use erase() with " + type_name());
3825  }
3826  }
3827 
3852  void erase(const size_type idx)
3853  {
3854  // this erase only works for arrays
3855  if (is_array())
3856  {
3857  if (idx >= size())
3858  {
3859  throw std::out_of_range("index out of range");
3860  }
3861 
3862  assert(m_value.array != nullptr);
3863  m_value.array->erase(m_value.array->begin() + static_cast<difference_type>(idx));
3864  }
3865  else
3866  {
3867  throw std::domain_error("cannot use erase() with " + type_name());
3868  }
3869  }
3870 
3888  iterator find(typename object_t::key_type key)
3889  {
3890  auto result = end();
3891 
3892  if (is_object())
3893  {
3894  assert(m_value.object != nullptr);
3895  result.m_it.object_iterator = m_value.object->find(key);
3896  }
3897 
3898  return result;
3899  }
3900 
3905  const_iterator find(typename object_t::key_type key) const
3906  {
3907  auto result = cend();
3908 
3909  if (is_object())
3910  {
3911  assert(m_value.object != nullptr);
3912  result.m_it.object_iterator = m_value.object->find(key);
3913  }
3914 
3915  return result;
3916  }
3917 
3936  size_type count(typename object_t::key_type key) const
3937  {
3938  // return 0 for all nonobject types
3939  assert(not is_object() or m_value.object != nullptr);
3940  return is_object() ? m_value.object->count(key) : 0;
3941  }
3942 
3944 
3945 
3947  // iterators //
3949 
3952 
3972  {
3973  iterator result(this);
3974  result.set_begin();
3975  return result;
3976  }
3977 
3982  {
3983  return cbegin();
3984  }
3985 
4006  {
4007  const_iterator result(this);
4008  result.set_begin();
4009  return result;
4010  }
4011 
4031  {
4032  iterator result(this);
4033  result.set_end();
4034  return result;
4035  }
4036 
4041  {
4042  return cend();
4043  }
4044 
4065  {
4066  const_iterator result(this);
4067  result.set_end();
4068  return result;
4069  }
4070 
4089  {
4090  return reverse_iterator(end());
4091  }
4092 
4097  {
4098  return crbegin();
4099  }
4100 
4120  {
4121  return reverse_iterator(begin());
4122  }
4123 
4128  {
4129  return crend();
4130  }
4131 
4151  {
4152  return const_reverse_iterator(cend());
4153  }
4154 
4174  {
4175  return const_reverse_iterator(cbegin());
4176  }
4177 
4178  private:
4179  // forward declaration
4180  template<typename IteratorType> class iteration_proxy;
4181 
4182  public:
4194  static iteration_proxy<iterator> iterator_wrapper(reference cont)
4195  {
4196  return iteration_proxy<iterator>(cont);
4197  }
4198 
4202  static iteration_proxy<const_iterator> iterator_wrapper(const_reference cont)
4203  {
4204  return iteration_proxy<const_iterator>(cont);
4205  }
4206 
4208 
4209 
4211  // capacity //
4213 
4216 
4246  bool empty() const noexcept
4247  {
4248  switch (m_type)
4249  {
4250  case value_t::null:
4251  {
4252  // null values are empty
4253  return true;
4254  }
4255 
4256  case value_t::array:
4257  {
4258  assert(m_value.array != nullptr);
4259  return m_value.array->empty();
4260  }
4261 
4262  case value_t::object:
4263  {
4264  assert(m_value.object != nullptr);
4265  return m_value.object->empty();
4266  }
4267 
4268  default:
4269  {
4270  // all other types are nonempty
4271  return false;
4272  }
4273  }
4274  }
4275 
4304  size_type size() const noexcept
4305  {
4306  switch (m_type)
4307  {
4308  case value_t::null:
4309  {
4310  // null values are empty
4311  return 0;
4312  }
4313 
4314  case value_t::array:
4315  {
4316  assert(m_value.array != nullptr);
4317  return m_value.array->size();
4318  }
4319 
4320  case value_t::object:
4321  {
4322  assert(m_value.object != nullptr);
4323  return m_value.object->size();
4324  }
4325 
4326  default:
4327  {
4328  // all other types have size 1
4329  return 1;
4330  }
4331  }
4332  }
4333 
4366  size_type max_size() const noexcept
4367  {
4368  switch (m_type)
4369  {
4370  case value_t::array:
4371  {
4372  assert(m_value.array != nullptr);
4373  return m_value.array->max_size();
4374  }
4375 
4376  case value_t::object:
4377  {
4378  assert(m_value.object != nullptr);
4379  return m_value.object->max_size();
4380  }
4381 
4382  default:
4383  {
4384  // all other types have max_size() == size()
4385  return size();
4386  }
4387  }
4388  }
4389 
4391 
4392 
4394  // modifiers //
4396 
4399 
4425  void clear() noexcept
4426  {
4427  switch (m_type)
4428  {
4429  case value_t::number_integer:
4430  {
4431  m_value.number_integer = 0;
4432  break;
4433  }
4434 
4435  case value_t::number_unsigned:
4436  {
4437  m_value.number_unsigned = 0;
4438  break;
4439  }
4440 
4441  case value_t::number_float:
4442  {
4443  m_value.number_float = 0.0;
4444  break;
4445  }
4446 
4447  case value_t::boolean:
4448  {
4449  m_value.boolean = false;
4450  break;
4451  }
4452 
4453  case value_t::string:
4454  {
4455  assert(m_value.string != nullptr);
4456  m_value.string->clear();
4457  break;
4458  }
4459 
4460  case value_t::array:
4461  {
4462  assert(m_value.array != nullptr);
4463  m_value.array->clear();
4464  break;
4465  }
4466 
4467  case value_t::object:
4468  {
4469  assert(m_value.object != nullptr);
4470  m_value.object->clear();
4471  break;
4472  }
4473 
4474  default:
4475  {
4476  break;
4477  }
4478  }
4479  }
4480 
4501  void push_back(basic_json&& val)
4502  {
4503  // push_back only works for null objects or arrays
4504  if (not(is_null() or is_array()))
4505  {
4506  throw std::domain_error("cannot use push_back() with " + type_name());
4507  }
4508 
4509  // transform null object into an array
4510  if (is_null())
4511  {
4512  m_type = value_t::array;
4513  m_value = value_t::array;
4514  }
4515 
4516  // add element to array (move semantics)
4517  assert(m_value.array != nullptr);
4518  m_value.array->push_back(std::move(val));
4519  // invalidate object
4520  val.m_type = value_t::null;
4521  }
4522 
4527  reference operator+=(basic_json&& val)
4528  {
4529  push_back(std::move(val));
4530  return *this;
4531  }
4532 
4537  void push_back(const basic_json& val)
4538  {
4539  // push_back only works for null objects or arrays
4540  if (not(is_null() or is_array()))
4541  {
4542  throw std::domain_error("cannot use push_back() with " + type_name());
4543  }
4544 
4545  // transform null object into an array
4546  if (is_null())
4547  {
4548  m_type = value_t::array;
4549  m_value = value_t::array;
4550  }
4551 
4552  // add element to array
4553  assert(m_value.array != nullptr);
4554  m_value.array->push_back(val);
4555  }
4556 
4561  reference operator+=(const basic_json& val)
4562  {
4563  push_back(val);
4564  return *this;
4565  }
4566 
4587  void push_back(const typename object_t::value_type& val)
4588  {
4589  // push_back only works for null objects or objects
4590  if (not(is_null() or is_object()))
4591  {
4592  throw std::domain_error("cannot use push_back() with " + type_name());
4593  }
4594 
4595  // transform null object into an object
4596  if (is_null())
4597  {
4598  m_type = value_t::object;
4599  m_value = value_t::object;
4600  }
4601 
4602  // add element to array
4603  assert(m_value.object != nullptr);
4604  m_value.object->insert(val);
4605  }
4606 
4611  reference operator+=(const typename object_t::value_type& val)
4612  {
4613  push_back(val);
4614  return operator[](val.first);
4615  }
4616 
4639  iterator insert(const_iterator pos, const basic_json& val)
4640  {
4641  // insert only works for arrays
4642  if (is_array())
4643  {
4644  // check if iterator pos fits to this JSON value
4645  if (pos.m_object != this)
4646  {
4647  throw std::domain_error("iterator does not fit current value");
4648  }
4649 
4650  // insert to array and return iterator
4651  iterator result(this);
4652  assert(m_value.array != nullptr);
4653  result.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator, val);
4654  return result;
4655  }
4656  else
4657  {
4658  throw std::domain_error("cannot use insert() with " + type_name());
4659  }
4660  }
4661 
4666  iterator insert(const_iterator pos, basic_json&& val)
4667  {
4668  return insert(pos, val);
4669  }
4670 
4695  iterator insert(const_iterator pos, size_type cnt, const basic_json& val)
4696  {
4697  // insert only works for arrays
4698  if (is_array())
4699  {
4700  // check if iterator pos fits to this JSON value
4701  if (pos.m_object != this)
4702  {
4703  throw std::domain_error("iterator does not fit current value");
4704  }
4705 
4706  // insert to array and return iterator
4707  iterator result(this);
4708  assert(m_value.array != nullptr);
4709  result.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator, cnt, val);
4710  return result;
4711  }
4712  else
4713  {
4714  throw std::domain_error("cannot use insert() with " + type_name());
4715  }
4716  }
4717 
4749  {
4750  // insert only works for arrays
4751  if (not is_array())
4752  {
4753  throw std::domain_error("cannot use insert() with " + type_name());
4754  }
4755 
4756  // check if iterator pos fits to this JSON value
4757  if (pos.m_object != this)
4758  {
4759  throw std::domain_error("iterator does not fit current value");
4760  }
4761 
4762  if (first.m_object != last.m_object)
4763  {
4764  throw std::domain_error("iterators do not fit");
4765  }
4766 
4767  if (first.m_object == this or last.m_object == this)
4768  {
4769  throw std::domain_error("passed iterators may not belong to container");
4770  }
4771 
4772  // insert to array and return iterator
4773  iterator result(this);
4774  assert(m_value.array != nullptr);
4775  result.m_it.array_iterator = m_value.array->insert(
4776  pos.m_it.array_iterator,
4777  first.m_it.array_iterator,
4778  last.m_it.array_iterator);
4779  return result;
4780  }
4781 
4806  iterator insert(const_iterator pos, std::initializer_list<basic_json> ilist)
4807  {
4808  // insert only works for arrays
4809  if (not is_array())
4810  {
4811  throw std::domain_error("cannot use insert() with " + type_name());
4812  }
4813 
4814  // check if iterator pos fits to this JSON value
4815  if (pos.m_object != this)
4816  {
4817  throw std::domain_error("iterator does not fit current value");
4818  }
4819 
4820  // insert to array and return iterator
4821  iterator result(this);
4822  assert(m_value.array != nullptr);
4823  result.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator, ilist);
4824  return result;
4825  }
4826 
4844  void swap(reference other) noexcept (
4845  std::is_nothrow_move_constructible<value_t>::value and
4846  std::is_nothrow_move_assignable<value_t>::value and
4847  std::is_nothrow_move_constructible<json_value>::value and
4848  std::is_nothrow_move_assignable<json_value>::value
4849  )
4850  {
4851  std::swap(m_type, other.m_type);
4852  std::swap(m_value, other.m_value);
4853  }
4854 
4875  void swap(array_t& other)
4876  {
4877  // swap only works for arrays
4878  if (is_array())
4879  {
4880  assert(m_value.array != nullptr);
4881  std::swap(*(m_value.array), other);
4882  }
4883  else
4884  {
4885  throw std::domain_error("cannot use swap() with " + type_name());
4886  }
4887  }
4888 
4909  void swap(object_t& other)
4910  {
4911  // swap only works for objects
4912  if (is_object())
4913  {
4914  assert(m_value.object != nullptr);
4915  std::swap(*(m_value.object), other);
4916  }
4917  else
4918  {
4919  throw std::domain_error("cannot use swap() with " + type_name());
4920  }
4921  }
4922 
4943  void swap(string_t& other)
4944  {
4945  // swap only works for strings
4946  if (is_string())
4947  {
4948  assert(m_value.string != nullptr);
4949  std::swap(*(m_value.string), other);
4950  }
4951  else
4952  {
4953  throw std::domain_error("cannot use swap() with " + type_name());
4954  }
4955  }
4956 
4958 
4959 
4961  // lexicographical comparison operators //
4963 
4966 
4967  private:
4977  friend bool operator<(const value_t lhs, const value_t rhs)
4978  {
4979  static constexpr std::array<uint8_t, 8> order = {{
4980  0, // null
4981  3, // object
4982  4, // array
4983  5, // string
4984  1, // boolean
4985  2, // integer
4986  2, // unsigned
4987  2, // float
4988  }
4989  };
4990 
4991  // discarded values are not comparable
4992  if (lhs == value_t::discarded or rhs == value_t::discarded)
4993  {
4994  return false;
4995  }
4996 
4997  return order[static_cast<std::size_t>(lhs)] < order[static_cast<std::size_t>(rhs)];
4998  }
4999 
5000  public:
5024  friend bool operator==(const_reference lhs, const_reference rhs) noexcept
5025  {
5026  const auto lhs_type = lhs.type();
5027  const auto rhs_type = rhs.type();
5028 
5029  if (lhs_type == rhs_type)
5030  {
5031  switch (lhs_type)
5032  {
5033  case value_t::array:
5034  {
5035  assert(lhs.m_value.array != nullptr);
5036  assert(rhs.m_value.array != nullptr);
5037  return *lhs.m_value.array == *rhs.m_value.array;
5038  }
5039  case value_t::object:
5040  {
5041  assert(lhs.m_value.object != nullptr);
5042  assert(rhs.m_value.object != nullptr);
5043  return *lhs.m_value.object == *rhs.m_value.object;
5044  }
5045  case value_t::null:
5046  {
5047  return true;
5048  }
5049  case value_t::string:
5050  {
5051  assert(lhs.m_value.string != nullptr);
5052  assert(rhs.m_value.string != nullptr);
5053  return *lhs.m_value.string == *rhs.m_value.string;
5054  }
5055  case value_t::boolean:
5056  {
5057  return lhs.m_value.boolean == rhs.m_value.boolean;
5058  }
5059  case value_t::number_integer:
5060  {
5061  return lhs.m_value.number_integer == rhs.m_value.number_integer;
5062  }
5063  case value_t::number_unsigned:
5064  {
5065  return lhs.m_value.number_unsigned == rhs.m_value.number_unsigned;
5066  }
5067  case value_t::number_float:
5068  {
5069  return lhs.m_value.number_float == rhs.m_value.number_float;
5070  }
5071  default:
5072  {
5073  return false;
5074  }
5075  }
5076  }
5077  else if (lhs_type == value_t::number_integer and rhs_type == value_t::number_float)
5078  {
5079  return static_cast<number_float_t>(lhs.m_value.number_integer) == rhs.m_value.number_float;
5080  }
5081  else if (lhs_type == value_t::number_float and rhs_type == value_t::number_integer)
5082  {
5083  return lhs.m_value.number_float == static_cast<number_float_t>(rhs.m_value.number_integer);
5084  }
5085  else if (lhs_type == value_t::number_unsigned and rhs_type == value_t::number_float)
5086  {
5087  return static_cast<number_float_t>(lhs.m_value.number_unsigned) == rhs.m_value.number_float;
5088  }
5089  else if (lhs_type == value_t::number_float and rhs_type == value_t::number_unsigned)
5090  {
5091  return lhs.m_value.number_float == static_cast<number_float_t>(rhs.m_value.number_unsigned);
5092  }
5093  else if (lhs_type == value_t::number_unsigned and rhs_type == value_t::number_integer)
5094  {
5095  return static_cast<number_integer_t>(lhs.m_value.number_unsigned) == rhs.m_value.number_integer;
5096  }
5097  else if (lhs_type == value_t::number_integer and rhs_type == value_t::number_unsigned)
5098  {
5099  return lhs.m_value.number_integer == static_cast<number_integer_t>(rhs.m_value.number_unsigned);
5100  }
5101 
5102  return false;
5103  }
5104 
5123  friend bool operator==(const_reference v, std::nullptr_t) noexcept
5124  {
5125  return v.is_null();
5126  }
5127 
5132  friend bool operator==(std::nullptr_t, const_reference v) noexcept
5133  {
5134  return v.is_null();
5135  }
5136 
5153  friend bool operator!=(const_reference lhs, const_reference rhs) noexcept
5154  {
5155  return not (lhs == rhs);
5156  }
5157 
5176  friend bool operator!=(const_reference v, std::nullptr_t) noexcept
5177  {
5178  return not v.is_null();
5179  }
5180 
5185  friend bool operator!=(std::nullptr_t, const_reference v) noexcept
5186  {
5187  return not v.is_null();
5188  }
5189 
5214  friend bool operator<(const_reference lhs, const_reference rhs) noexcept
5215  {
5216  const auto lhs_type = lhs.type();
5217  const auto rhs_type = rhs.type();
5218 
5219  if (lhs_type == rhs_type)
5220  {
5221  switch (lhs_type)
5222  {
5223  case value_t::array:
5224  {
5225  assert(lhs.m_value.array != nullptr);
5226  assert(rhs.m_value.array != nullptr);
5227  return *lhs.m_value.array < *rhs.m_value.array;
5228  }
5229  case value_t::object:
5230  {
5231  assert(lhs.m_value.object != nullptr);
5232  assert(rhs.m_value.object != nullptr);
5233  return *lhs.m_value.object < *rhs.m_value.object;
5234  }
5235  case value_t::null:
5236  {
5237  return false;
5238  }
5239  case value_t::string:
5240  {
5241  assert(lhs.m_value.string != nullptr);
5242  assert(rhs.m_value.string != nullptr);
5243  return *lhs.m_value.string < *rhs.m_value.string;
5244  }
5245  case value_t::boolean:
5246  {
5247  return lhs.m_value.boolean < rhs.m_value.boolean;
5248  }
5249  case value_t::number_integer:
5250  {
5251  return lhs.m_value.number_integer < rhs.m_value.number_integer;
5252  }
5253  case value_t::number_unsigned:
5254  {
5255  return lhs.m_value.number_unsigned < rhs.m_value.number_unsigned;
5256  }
5257  case value_t::number_float:
5258  {
5259  return lhs.m_value.number_float < rhs.m_value.number_float;
5260  }
5261  default:
5262  {
5263  return false;
5264  }
5265  }
5266  }
5267  else if (lhs_type == value_t::number_integer and rhs_type == value_t::number_float)
5268  {
5269  return static_cast<number_float_t>(lhs.m_value.number_integer) < rhs.m_value.number_float;
5270  }
5271  else if (lhs_type == value_t::number_float and rhs_type == value_t::number_integer)
5272  {
5273  return lhs.m_value.number_float < static_cast<number_float_t>(rhs.m_value.number_integer);
5274  }
5275  else if (lhs_type == value_t::number_unsigned and rhs_type == value_t::number_float)
5276  {
5277  return static_cast<number_float_t>(lhs.m_value.number_unsigned) < rhs.m_value.number_float;
5278  }
5279  else if (lhs_type == value_t::number_float and rhs_type == value_t::number_unsigned)
5280  {
5281  return lhs.m_value.number_float < static_cast<number_float_t>(rhs.m_value.number_unsigned);
5282  }
5283  else if (lhs_type == value_t::number_integer and rhs_type == value_t::number_unsigned)
5284  {
5285  return lhs.m_value.number_integer < static_cast<number_integer_t>(rhs.m_value.number_unsigned);
5286  }
5287  else if (lhs_type == value_t::number_unsigned and rhs_type == value_t::number_integer)
5288  {
5289  return static_cast<number_integer_t>(lhs.m_value.number_unsigned) < rhs.m_value.number_integer;
5290  }
5291 
5292  // We only reach this line if we cannot compare values. In that case,
5293  // we compare types. Note we have to call the operator explicitly,
5294  // because MSVC has problems otherwise.
5295  return operator<(lhs_type, rhs_type);
5296  }
5297 
5315  friend bool operator<=(const_reference lhs, const_reference rhs) noexcept
5316  {
5317  return not (rhs < lhs);
5318  }
5319 
5337  friend bool operator>(const_reference lhs, const_reference rhs) noexcept
5338  {
5339  return not (lhs <= rhs);
5340  }
5341 
5359  friend bool operator>=(const_reference lhs, const_reference rhs) noexcept
5360  {
5361  return not (lhs < rhs);
5362  }
5363 
5365 
5366 
5368  // serialization //
5370 
5373 
5396  friend std::ostream& operator<<(std::ostream& o, const basic_json& j)
5397  {
5398  // read width member and use it as indentation parameter if nonzero
5399  const bool pretty_print = (o.width() > 0);
5400  const auto indentation = (pretty_print ? o.width() : 0);
5401 
5402  // reset width to 0 for subsequent calls to this stream
5403  o.width(0);
5404 
5405  // do the actual serialization
5406  j.dump(o, pretty_print, static_cast<unsigned int>(indentation));
5407  return o;
5408  }
5409 
5414  friend std::ostream& operator>>(const basic_json& j, std::ostream& o)
5415  {
5416  return o << j;
5417  }
5418 
5420 
5421 
5423  // deserialization //
5425 
5428 
5453  static basic_json parse(const string_t& s, parser_callback_t cb = nullptr)
5454  {
5455  return parser(s, cb).parse();
5456  }
5457 
5482  static basic_json parse(std::istream& i, parser_callback_t cb = nullptr)
5483  {
5484  return parser(i, cb).parse();
5485  }
5486 
5490  static basic_json parse(std::istream&& i, parser_callback_t cb = nullptr)
5491  {
5492  return parser(i, cb).parse();
5493  }
5494 
5518  friend std::istream& operator<<(basic_json& j, std::istream& i)
5519  {
5520  j = parser(i).parse();
5521  return i;
5522  }
5523 
5528  friend std::istream& operator>>(std::istream& i, basic_json& j)
5529  {
5530  j = parser(i).parse();
5531  return i;
5532  }
5533 
5535 
5536 
5537  private:
5539  // convenience functions //
5541 
5543  string_t type_name() const
5544  {
5545  switch (m_type)
5546  {
5547  case value_t::null:
5548  return "null";
5549  case value_t::object:
5550  return "object";
5551  case value_t::array:
5552  return "array";
5553  case value_t::string:
5554  return "string";
5555  case value_t::boolean:
5556  return "boolean";
5557  case value_t::discarded:
5558  return "discarded";
5559  default:
5560  return "number";
5561  }
5562  }
5563 
5572  static std::size_t extra_space(const string_t& s) noexcept
5573  {
5574  std::size_t result = 0;
5575 
5576  for (const auto& c : s)
5577  {
5578  switch (c)
5579  {
5580  case '"':
5581  case '\\':
5582  case '\b':
5583  case '\f':
5584  case '\n':
5585  case '\r':
5586  case '\t':
5587  {
5588  // from c (1 byte) to \x (2 bytes)
5589  result += 1;
5590  break;
5591  }
5592 
5593  default:
5594  {
5595  if (c >= 0x00 and c <= 0x1f)
5596  {
5597  // from c (1 byte) to \uxxxx (6 bytes)
5598  result += 5;
5599  }
5600  break;
5601  }
5602  }
5603  }
5604 
5605  return result;
5606  }
5607 
5621  static string_t escape_string(const string_t& s) noexcept
5622  {
5623  const auto space = extra_space(s);
5624  if (space == 0)
5625  {
5626  return s;
5627  }
5628 
5629  // create a result string of necessary size
5630  string_t result(s.size() + space, '\\');
5631  std::size_t pos = 0;
5632 
5633  for (const auto& c : s)
5634  {
5635  switch (c)
5636  {
5637  // quotation mark (0x22)
5638  case '"':
5639  {
5640  result[pos + 1] = '"';
5641  pos += 2;
5642  break;
5643  }
5644 
5645  // reverse solidus (0x5c)
5646  case '\\':
5647  {
5648  // nothing to change
5649  pos += 2;
5650  break;
5651  }
5652 
5653  // backspace (0x08)
5654  case '\b':
5655  {
5656  result[pos + 1] = 'b';
5657  pos += 2;
5658  break;
5659  }
5660 
5661  // formfeed (0x0c)
5662  case '\f':
5663  {
5664  result[pos + 1] = 'f';
5665  pos += 2;
5666  break;
5667  }
5668 
5669  // newline (0x0a)
5670  case '\n':
5671  {
5672  result[pos + 1] = 'n';
5673  pos += 2;
5674  break;
5675  }
5676 
5677  // carriage return (0x0d)
5678  case '\r':
5679  {
5680  result[pos + 1] = 'r';
5681  pos += 2;
5682  break;
5683  }
5684 
5685  // horizontal tab (0x09)
5686  case '\t':
5687  {
5688  result[pos + 1] = 't';
5689  pos += 2;
5690  break;
5691  }
5692 
5693  default:
5694  {
5695  if (c >= 0x00 and c <= 0x1f)
5696  {
5697  // convert a number 0..15 to its hex representation (0..f)
5698  auto hexify = [](const char v) -> char
5699  {
5700  return (v < 10) ? ('0' + v) : ('a' + v - 10);
5701  };
5702 
5703  // print character c as \uxxxx
5704  for (const char m :
5705  { 'u', '0', '0', hexify(c >> 4), hexify(c & 0x0f)
5706  })
5707  {
5708  result[++pos] = m;
5709  }
5710 
5711  ++pos;
5712  }
5713  else
5714  {
5715  // all other characters are added as-is
5716  result[pos++] = c;
5717  }
5718  break;
5719  }
5720  }
5721  }
5722 
5723  return result;
5724  }
5725 
5743  void dump(std::ostream& o,
5744  const bool pretty_print,
5745  const unsigned int indent_step,
5746  const unsigned int current_indent = 0) const
5747  {
5748  // variable to hold indentation for recursive calls
5749  unsigned int new_indent = current_indent;
5750 
5751  switch (m_type)
5752  {
5753  case value_t::object:
5754  {
5755  assert(m_value.object != nullptr);
5756 
5757  if (m_value.object->empty())
5758  {
5759  o << "{}";
5760  return;
5761  }
5762 
5763  o << "{";
5764 
5765  // increase indentation
5766  if (pretty_print)
5767  {
5768  new_indent += indent_step;
5769  o << "\n";
5770  }
5771 
5772  for (auto i = m_value.object->cbegin(); i != m_value.object->cend(); ++i)
5773  {
5774  if (i != m_value.object->cbegin())
5775  {
5776  o << (pretty_print ? ",\n" : ",");
5777  }
5778  o << string_t(new_indent, ' ') << "\""
5779  << escape_string(i->first) << "\":"
5780  << (pretty_print ? " " : "");
5781  i->second.dump(o, pretty_print, indent_step, new_indent);
5782  }
5783 
5784  // decrease indentation
5785  if (pretty_print)
5786  {
5787  new_indent -= indent_step;
5788  o << "\n";
5789  }
5790 
5791  o << string_t(new_indent, ' ') + "}";
5792  return;
5793  }
5794 
5795  case value_t::array:
5796  {
5797  assert(m_value.array != nullptr);
5798 
5799  if (m_value.array->empty())
5800  {
5801  o << "[]";
5802  return;
5803  }
5804 
5805  o << "[";
5806 
5807  // increase indentation
5808  if (pretty_print)
5809  {
5810  new_indent += indent_step;
5811  o << "\n";
5812  }
5813 
5814  for (auto i = m_value.array->cbegin(); i != m_value.array->cend(); ++i)
5815  {
5816  if (i != m_value.array->cbegin())
5817  {
5818  o << (pretty_print ? ",\n" : ",");
5819  }
5820  o << string_t(new_indent, ' ');
5821  i->dump(o, pretty_print, indent_step, new_indent);
5822  }
5823 
5824  // decrease indentation
5825  if (pretty_print)
5826  {
5827  new_indent -= indent_step;
5828  o << "\n";
5829  }
5830 
5831  o << string_t(new_indent, ' ') << "]";
5832  return;
5833  }
5834 
5835  case value_t::string:
5836  {
5837  assert(m_value.string != nullptr);
5838  o << string_t("\"") << escape_string(*m_value.string) << "\"";
5839  return;
5840  }
5841 
5842  case value_t::boolean:
5843  {
5844  o << (m_value.boolean ? "true" : "false");
5845  return;
5846  }
5847 
5848  case value_t::number_integer:
5849  {
5850  o << m_value.number_integer;
5851  return;
5852  }
5853 
5854  case value_t::number_unsigned:
5855  {
5856  o << m_value.number_unsigned;
5857  return;
5858  }
5859 
5860  case value_t::number_float:
5861  {
5862  // If the number is an integer then output as a fixed with with
5863  // precision 1 to output "0.0", "1.0" etc as expected for some
5864  // round trip tests otherwise 15 digits of precision allows
5865  // round-trip IEEE 754 string->double->string; to be safe, we
5866  // read this value from
5867  // std::numeric_limits<number_float_t>::digits10
5868  if (std::fmod(m_value.number_float, 1) == 0)
5869  {
5870  o << std::fixed << std::setprecision(1);
5871  }
5872  else
5873  {
5874  // std::defaultfloat not supported in gcc version < 5
5875  o.unsetf(std::ios_base::floatfield);
5876  o << std::setprecision(std::numeric_limits<double>::digits10);
5877  }
5878  o << m_value.number_float;
5879  return;
5880  }
5881 
5882  case value_t::discarded:
5883  {
5884  o << "<discarded>";
5885  return;
5886  }
5887 
5888  case value_t::null:
5889  {
5890  o << "null";
5891  return;
5892  }
5893  }
5894  }
5895 
5896  private:
5898  // member variables //
5900 
5902  value_t m_type = value_t::null;
5903 
5905  json_value m_value = {};
5906 
5907 
5908  private:
5910  // iterators //
5912 
5922  class primitive_iterator_t
5923  {
5924  public:
5926  void set_begin()
5927  {
5928  m_it = begin_value;
5929  }
5930 
5932  void set_end()
5933  {
5934  m_it = end_value;
5935  }
5936 
5938  bool is_begin() const
5939  {
5940  return (m_it == begin_value);
5941  }
5942 
5944  bool is_end() const
5945  {
5946  return (m_it == end_value);
5947  }
5948 
5950  operator difference_type& ()
5951  {
5952  return m_it;
5953  }
5954 
5956  operator difference_type () const
5957  {
5958  return m_it;
5959  }
5960 
5961  private:
5962  static constexpr difference_type begin_value = 0;
5963  static constexpr difference_type end_value = begin_value + 1;
5964 
5966  difference_type m_it = std::numeric_limits<std::ptrdiff_t>::denorm_min();
5967  };
5968 
5976  struct internal_iterator
5977  {
5979  typename object_t::iterator object_iterator;
5981  typename array_t::iterator array_iterator;
5983  primitive_iterator_t primitive_iterator;
5984 
5986  internal_iterator()
5987  : object_iterator(), array_iterator(), primitive_iterator()
5988  {}
5989  };
5990 
5992  template<typename IteratorType>
5993  class iteration_proxy
5994  {
5995  private:
5997  class iteration_proxy_internal
5998  {
5999  private:
6001  IteratorType anchor;
6003  size_t array_index = 0;
6004 
6005  public:
6006  iteration_proxy_internal(IteratorType it)
6007  : anchor(it)
6008  {}
6009 
6011  iteration_proxy_internal& operator*()
6012  {
6013  return *this;
6014  }
6015 
6017  iteration_proxy_internal& operator++()
6018  {
6019  ++anchor;
6020  ++array_index;
6021 
6022  return *this;
6023  }
6024 
6026  bool operator!= (const iteration_proxy_internal& o) const
6027  {
6028  return anchor != o.anchor;
6029  }
6030 
6032  typename basic_json::string_t key() const
6033  {
6034  assert(anchor.m_object != nullptr);
6035 
6036  switch (anchor.m_object->type())
6037  {
6038  // use integer array index as key
6039  case value_t::array:
6040  {
6041  return std::to_string(array_index);
6042  }
6043 
6044  // use key from the object
6045  case value_t::object:
6046  {
6047  return anchor.key();
6048  }
6049 
6050  // use an empty key for all primitive types
6051  default:
6052  {
6053  return "";
6054  }
6055  }
6056  }
6057 
6059  typename IteratorType::reference value() const
6060  {
6061  return anchor.value();
6062  }
6063  };
6064 
6066  typename IteratorType::reference container;
6067 
6068  public:
6070  iteration_proxy(typename IteratorType::reference cont)
6071  : container(cont)
6072  {}
6073 
6075  iteration_proxy_internal begin()
6076  {
6077  return iteration_proxy_internal(container.begin());
6078  }
6079 
6081  iteration_proxy_internal end()
6082  {
6083  return iteration_proxy_internal(container.end());
6084  }
6085  };
6086 
6087  public:
6101  class const_iterator : public std::iterator<std::random_access_iterator_tag, const basic_json>
6102  {
6104  friend class basic_json;
6105 
6106  public:
6116  using iterator_category = std::bidirectional_iterator_tag;
6117 
6119  const_iterator() = default;
6120 
6122  const_iterator(pointer object) : m_object(object)
6123  {
6124  assert(m_object != nullptr);
6125 
6126  switch (m_object->m_type)
6127  {
6129  {
6130  m_it.object_iterator = typename object_t::iterator();
6131  break;
6132  }
6133 
6135  {
6136  m_it.array_iterator = typename array_t::iterator();
6137  break;
6138  }
6139 
6140  default:
6141  {
6142  m_it.primitive_iterator = primitive_iterator_t();
6143  break;
6144  }
6145  }
6146  }
6147 
6149  const_iterator(const iterator& other) : m_object(other.m_object)
6150  {
6151  assert(m_object != nullptr);
6152 
6153  switch (m_object->m_type)
6154  {
6156  {
6157  m_it.object_iterator = other.m_it.object_iterator;
6158  break;
6159  }
6160 
6162  {
6163  m_it.array_iterator = other.m_it.array_iterator;
6164  break;
6165  }
6166 
6167  default:
6168  {
6169  m_it.primitive_iterator = other.m_it.primitive_iterator;
6170  break;
6171  }
6172  }
6173  }
6174 
6176  const_iterator(const const_iterator& other) noexcept
6177  : m_object(other.m_object), m_it(other.m_it)
6178  {}
6179 
6182  std::is_nothrow_move_constructible<pointer>::value and
6183  std::is_nothrow_move_assignable<pointer>::value and
6184  std::is_nothrow_move_constructible<internal_iterator>::value and
6185  std::is_nothrow_move_assignable<internal_iterator>::value
6186  )
6187  {
6188  std::swap(m_object, other.m_object);
6189  std::swap(m_it, other.m_it);
6190  return *this;
6191  }
6192 
6193  private:
6195  void set_begin()
6196  {
6197  assert(m_object != nullptr);
6198 
6199  switch (m_object->m_type)
6200  {
6202  {
6203  assert(m_object->m_value.object != nullptr);
6204  m_it.object_iterator = m_object->m_value.object->begin();
6205  break;
6206  }
6207 
6209  {
6210  assert(m_object->m_value.array != nullptr);
6211  m_it.array_iterator = m_object->m_value.array->begin();
6212  break;
6213  }
6214 
6216  {
6217  // set to end so begin()==end() is true: null is empty
6218  m_it.primitive_iterator.set_end();
6219  break;
6220  }
6221 
6222  default:
6223  {
6224  m_it.primitive_iterator.set_begin();
6225  break;
6226  }
6227  }
6228  }
6229 
6231  void set_end()
6232  {
6233  assert(m_object != nullptr);
6234 
6235  switch (m_object->m_type)
6236  {
6238  {
6239  assert(m_object->m_value.object != nullptr);
6240  m_it.object_iterator = m_object->m_value.object->end();
6241  break;
6242  }
6243 
6245  {
6246  assert(m_object->m_value.array != nullptr);
6247  m_it.array_iterator = m_object->m_value.array->end();
6248  break;
6249  }
6250 
6251  default:
6252  {
6253  m_it.primitive_iterator.set_end();
6254  break;
6255  }
6256  }
6257  }
6258 
6259  public:
6262  {
6263  assert(m_object != nullptr);
6264 
6265  switch (m_object->m_type)
6266  {
6268  {
6269  assert(m_object->m_value.object);
6270  assert(m_it.object_iterator != m_object->m_value.object->end());
6271  return m_it.object_iterator->second;
6272  }
6273 
6275  {
6276  assert(m_object->m_value.array);
6277  assert(m_it.array_iterator != m_object->m_value.array->end());
6278  return *m_it.array_iterator;
6279  }
6280 
6282  {
6283  throw std::out_of_range("cannot get value");
6284  }
6285 
6286  default:
6287  {
6288  if (m_it.primitive_iterator.is_begin())
6289  {
6290  return *m_object;
6291  }
6292  else
6293  {
6294  throw std::out_of_range("cannot get value");
6295  }
6296  }
6297  }
6298  }
6299 
6302  {
6303  assert(m_object != nullptr);
6304 
6305  switch (m_object->m_type)
6306  {
6308  {
6309  assert(m_object->m_value.object);
6310  assert(m_it.object_iterator != m_object->m_value.object->end());
6311  return &(m_it.object_iterator->second);
6312  }
6313 
6315  {
6316  assert(m_object->m_value.array);
6317  assert(m_it.array_iterator != m_object->m_value.array->end());
6318  return &*m_it.array_iterator;
6319  }
6320 
6321  default:
6322  {
6323  if (m_it.primitive_iterator.is_begin())
6324  {
6325  return m_object;
6326  }
6327  else
6328  {
6329  throw std::out_of_range("cannot get value");
6330  }
6331  }
6332  }
6333  }
6334 
6337  {
6338  auto result = *this;
6339  ++(*this);
6340  return result;
6341  }
6342 
6345  {
6346  assert(m_object != nullptr);
6347 
6348  switch (m_object->m_type)
6349  {
6351  {
6352  ++m_it.object_iterator;
6353  break;
6354  }
6355 
6357  {
6358  ++m_it.array_iterator;
6359  break;
6360  }
6361 
6362  default:
6363  {
6364  ++m_it.primitive_iterator;
6365  break;
6366  }
6367  }
6368 
6369  return *this;
6370  }
6371 
6374  {
6375  auto result = *this;
6376  --(*this);
6377  return result;
6378  }
6379 
6382  {
6383  assert(m_object != nullptr);
6384 
6385  switch (m_object->m_type)
6386  {
6388  {
6389  --m_it.object_iterator;
6390  break;
6391  }
6392 
6394  {
6395  --m_it.array_iterator;
6396  break;
6397  }
6398 
6399  default:
6400  {
6401  --m_it.primitive_iterator;
6402  break;
6403  }
6404  }
6405 
6406  return *this;
6407  }
6408 
6410  bool operator==(const const_iterator& other) const
6411  {
6412  // if objects are not the same, the comparison is undefined
6413  if (m_object != other.m_object)
6414  {
6415  throw std::domain_error("cannot compare iterators of different containers");
6416  }
6417 
6418  assert(m_object != nullptr);
6419 
6420  switch (m_object->m_type)
6421  {
6423  {
6424  return (m_it.object_iterator == other.m_it.object_iterator);
6425  }
6426 
6428  {
6429  return (m_it.array_iterator == other.m_it.array_iterator);
6430  }
6431 
6432  default:
6433  {
6434  return (m_it.primitive_iterator == other.m_it.primitive_iterator);
6435  }
6436  }
6437  }
6438 
6440  bool operator!=(const const_iterator& other) const
6441  {
6442  return not operator==(other);
6443  }
6444 
6446  bool operator<(const const_iterator& other) const
6447  {
6448  // if objects are not the same, the comparison is undefined
6449  if (m_object != other.m_object)
6450  {
6451  throw std::domain_error("cannot compare iterators of different containers");
6452  }
6453 
6454  assert(m_object != nullptr);
6455 
6456  switch (m_object->m_type)
6457  {
6459  {
6460  throw std::domain_error("cannot compare order of object iterators");
6461  }
6462 
6464  {
6465  return (m_it.array_iterator < other.m_it.array_iterator);
6466  }
6467 
6468  default:
6469  {
6470  return (m_it.primitive_iterator < other.m_it.primitive_iterator);
6471  }
6472  }
6473  }
6474 
6476  bool operator<=(const const_iterator& other) const
6477  {
6478  return not other.operator < (*this);
6479  }
6480 
6482  bool operator>(const const_iterator& other) const
6483  {
6484  return not operator<=(other);
6485  }
6486 
6488  bool operator>=(const const_iterator& other) const
6489  {
6490  return not operator<(other);
6491  }
6492 
6495  {
6496  assert(m_object != nullptr);
6497 
6498  switch (m_object->m_type)
6499  {
6501  {
6502  throw std::domain_error("cannot use offsets with object iterators");
6503  }
6504 
6506  {
6507  m_it.array_iterator += i;
6508  break;
6509  }
6510 
6511  default:
6512  {
6513  m_it.primitive_iterator += i;
6514  break;
6515  }
6516  }
6517 
6518  return *this;
6519  }
6520 
6523  {
6524  return operator+=(-i);
6525  }
6526 
6529  {
6530  auto result = *this;
6531  result += i;
6532  return result;
6533  }
6534 
6537  {
6538  auto result = *this;
6539  result -= i;
6540  return result;
6541  }
6542 
6545  {
6546  assert(m_object != nullptr);
6547 
6548  switch (m_object->m_type)
6549  {
6551  {
6552  throw std::domain_error("cannot use offsets with object iterators");
6553  }
6554 
6556  {
6557  return m_it.array_iterator - other.m_it.array_iterator;
6558  }
6559 
6560  default:
6561  {
6562  return m_it.primitive_iterator - other.m_it.primitive_iterator;
6563  }
6564  }
6565  }
6566 
6569  {
6570  assert(m_object != nullptr);
6571 
6572  switch (m_object->m_type)
6573  {
6575  {
6576  throw std::domain_error("cannot use operator[] for object iterators");
6577  }
6578 
6580  {
6581  return *(m_it.array_iterator + n);
6582  }
6583 
6585  {
6586  throw std::out_of_range("cannot get value");
6587  }
6588 
6589  default:
6590  {
6591  if (m_it.primitive_iterator == -n)
6592  {
6593  return *m_object;
6594  }
6595  else
6596  {
6597  throw std::out_of_range("cannot get value");
6598  }
6599  }
6600  }
6601  }
6602 
6604  typename object_t::key_type key() const
6605  {
6606  assert(m_object != nullptr);
6607 
6608  if (m_object->is_object())
6609  {
6610  return m_it.object_iterator->first;
6611  }
6612  else
6613  {
6614  throw std::domain_error("cannot use key() for non-object iterators");
6615  }
6616  }
6617 
6620  {
6621  return operator*();
6622  }
6623 
6624  private:
6626  pointer m_object = nullptr;
6628  internal_iterator m_it = internal_iterator();
6629  };
6630 
6643  class iterator : public const_iterator
6644  {
6645  public:
6647  using pointer = typename basic_json::pointer;
6649 
6651  iterator() = default;
6652 
6654  iterator(pointer object) noexcept
6655  : base_iterator(object)
6656  {}
6657 
6659  iterator(const iterator& other) noexcept
6660  : base_iterator(other)
6661  {}
6662 
6664  iterator& operator=(iterator other) noexcept(
6665  std::is_nothrow_move_constructible<pointer>::value and
6666  std::is_nothrow_move_assignable<pointer>::value and
6667  std::is_nothrow_move_constructible<internal_iterator>::value and
6668  std::is_nothrow_move_assignable<internal_iterator>::value
6669  )
6670  {
6671  base_iterator::operator=(other);
6672  return *this;
6673  }
6674 
6677  {
6678  return const_cast<reference>(base_iterator::operator*());
6679  }
6680 
6683  {
6684  return const_cast<pointer>(base_iterator::operator->());
6685  }
6686 
6689  {
6690  iterator result = *this;
6691  base_iterator::operator++();
6692  return result;
6693  }
6694 
6697  {
6698  base_iterator::operator++();
6699  return *this;
6700  }
6701 
6704  {
6705  iterator result = *this;
6706  base_iterator::operator--();
6707  return result;
6708  }
6709 
6712  {
6713  base_iterator::operator--();
6714  return *this;
6715  }
6716 
6719  {
6720  base_iterator::operator+=(i);
6721  return *this;
6722  }
6723 
6726  {
6727  base_iterator::operator-=(i);
6728  return *this;
6729  }
6730 
6733  {
6734  auto result = *this;
6735  result += i;
6736  return result;
6737  }
6738 
6741  {
6742  auto result = *this;
6743  result -= i;
6744  return result;
6745  }
6746 
6747  difference_type operator-(const iterator& other) const
6748  {
6749  return base_iterator::operator-(other);
6750  }
6751 
6754  {
6755  return const_cast<reference>(base_iterator::operator[](n));
6756  }
6757 
6760  {
6761  return const_cast<reference>(base_iterator::value());
6762  }
6763  };
6764 
6782  template<typename Base>
6783  class json_reverse_iterator : public std::reverse_iterator<Base>
6784  {
6785  public:
6787  using base_iterator = std::reverse_iterator<Base>;
6789  using reference = typename Base::reference;
6790 
6792  json_reverse_iterator(const typename base_iterator::iterator_type& it)
6793  : base_iterator(it)
6794  {}
6795 
6798  : base_iterator(it)
6799  {}
6800 
6803  {
6804  return base_iterator::operator++(1);
6805  }
6806 
6809  {
6810  base_iterator::operator++();
6811  return *this;
6812  }
6813 
6816  {
6817  return base_iterator::operator--(1);
6818  }
6819 
6822  {
6823  base_iterator::operator--();
6824  return *this;
6825  }
6826 
6829  {
6830  base_iterator::operator+=(i);
6831  return *this;
6832  }
6833 
6836  {
6837  auto result = *this;
6838  result += i;
6839  return result;
6840  }
6841 
6844  {
6845  auto result = *this;
6846  result -= i;
6847  return result;
6848  }
6849 
6852  {
6853  return this->base() - other.base();
6854  }
6855 
6858  {
6859  return *(this->operator+(n));
6860  }
6861 
6863  typename object_t::key_type key() const
6864  {
6865  auto it = --this->base();
6866  return it.key();
6867  }
6868 
6871  {
6872  auto it = --this->base();
6873  return it.operator * ();
6874  }
6875  };
6876 
6877 
6878  private:
6880  // lexer and parser //
6882 
6890  class lexer
6891  {
6892  public:
6894  enum class token_type
6895  {
6896  uninitialized,
6897  literal_true,
6898  literal_false,
6899  literal_null,
6900  value_string,
6901  value_number,
6902  begin_array,
6903  begin_object,
6904  end_array,
6905  end_object,
6906  name_separator,
6907  value_separator,
6908  parse_error,
6909  end_of_input
6910  };
6911 
6913  using lexer_char_t = unsigned char;
6914 
6916  explicit lexer(const string_t& s) noexcept
6917  : m_stream(nullptr), m_buffer(s)
6918  {
6919  m_content = reinterpret_cast<const lexer_char_t*>(s.c_str());
6920  assert(m_content != nullptr);
6921  m_start = m_cursor = m_content;
6922  m_limit = m_content + s.size();
6923  }
6924 
6926  explicit lexer(std::istream* s) noexcept
6927  : m_stream(s), m_buffer()
6928  {
6929  assert(m_stream != nullptr);
6930  getline(*m_stream, m_buffer);
6931  m_content = reinterpret_cast<const lexer_char_t*>(m_buffer.c_str());
6932  assert(m_content != nullptr);
6933  m_start = m_cursor = m_content;
6934  m_limit = m_content + m_buffer.size();
6935  }
6936 
6938  lexer() = default;
6939 
6940  // switch off unwanted functions
6941  lexer(const lexer&) = delete;
6942  lexer operator=(const lexer&) = delete;
6943 
6959  static string_t to_unicode(const std::size_t codepoint1,
6960  const std::size_t codepoint2 = 0)
6961  {
6962  string_t result;
6963 
6964  // calculate the codepoint from the given code points
6965  std::size_t codepoint = codepoint1;
6966 
6967  // check if codepoint1 is a high surrogate
6968  if (codepoint1 >= 0xD800 and codepoint1 <= 0xDBFF)
6969  {
6970  // check if codepoint2 is a low surrogate
6971  if (codepoint2 >= 0xDC00 and codepoint2 <= 0xDFFF)
6972  {
6973  codepoint =
6974  // high surrogate occupies the most significant 22 bits
6975  (codepoint1 << 10)
6976  // low surrogate occupies the least significant 15 bits
6977  + codepoint2
6978  // there is still the 0xD800, 0xDC00 and 0x10000 noise
6979  // in the result so we have to subtract with:
6980  // (0xD800 << 10) + DC00 - 0x10000 = 0x35FDC00
6981  - 0x35FDC00;
6982  }
6983  else
6984  {
6985  throw std::invalid_argument("missing or wrong low surrogate");
6986  }
6987  }
6988 
6989  if (codepoint < 0x80)
6990  {
6991  // 1-byte characters: 0xxxxxxx (ASCII)
6992  result.append(1, static_cast<typename string_t::value_type>(codepoint));
6993  }
6994  else if (codepoint <= 0x7ff)
6995  {
6996  // 2-byte characters: 110xxxxx 10xxxxxx
6997  result.append(1, static_cast<typename string_t::value_type>(0xC0 | ((codepoint >> 6) & 0x1F)));
6998  result.append(1, static_cast<typename string_t::value_type>(0x80 | (codepoint & 0x3F)));
6999  }
7000  else if (codepoint <= 0xffff)
7001  {
7002  // 3-byte characters: 1110xxxx 10xxxxxx 10xxxxxx
7003  result.append(1, static_cast<typename string_t::value_type>(0xE0 | ((codepoint >> 12) & 0x0F)));
7004  result.append(1, static_cast<typename string_t::value_type>(0x80 | ((codepoint >> 6) & 0x3F)));
7005  result.append(1, static_cast<typename string_t::value_type>(0x80 | (codepoint & 0x3F)));
7006  }
7007  else if (codepoint <= 0x10ffff)
7008  {
7009  // 4-byte characters: 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
7010  result.append(1, static_cast<typename string_t::value_type>(0xF0 | ((codepoint >> 18) & 0x07)));
7011  result.append(1, static_cast<typename string_t::value_type>(0x80 | ((codepoint >> 12) & 0x3F)));
7012  result.append(1, static_cast<typename string_t::value_type>(0x80 | ((codepoint >> 6) & 0x3F)));
7013  result.append(1, static_cast<typename string_t::value_type>(0x80 | (codepoint & 0x3F)));
7014  }
7015  else
7016  {
7017  throw std::out_of_range("code points above 0x10FFFF are invalid");
7018  }
7019 
7020  return result;
7021  }
7022 
7024  static std::string token_type_name(token_type t)
7025  {
7026  switch (t)
7027  {
7028  case token_type::uninitialized:
7029  return "<uninitialized>";
7030  case token_type::literal_true:
7031  return "true literal";
7032  case token_type::literal_false:
7033  return "false literal";
7034  case token_type::literal_null:
7035  return "null literal";
7036  case token_type::value_string:
7037  return "string literal";
7038  case token_type::value_number:
7039  return "number literal";
7040  case token_type::begin_array:
7041  return "'['";
7042  case token_type::begin_object:
7043  return "'{'";
7044  case token_type::end_array:
7045  return "']'";
7046  case token_type::end_object:
7047  return "'}'";
7048  case token_type::name_separator:
7049  return "':'";
7050  case token_type::value_separator:
7051  return "','";
7052  case token_type::parse_error:
7053  return "<parse error>";
7054  case token_type::end_of_input:
7055  return "end of input";
7056  default:
7057  {
7058  // catch non-enum values
7059  return "unknown token"; // LCOV_EXCL_LINE
7060  }
7061  }
7062  }
7063 
7074  token_type scan() noexcept
7075  {
7076  // pointer for backtracking information
7077  m_marker = nullptr;
7078 
7079  // remember the begin of the token
7080  m_start = m_cursor;
7081  assert(m_start != nullptr);
7082 
7083 
7084  {
7085  lexer_char_t yych;
7086  unsigned int yyaccept = 0;
7087  static const unsigned char yybm[] =
7088  {
7089  0, 0, 0, 0, 0, 0, 0, 0,
7090  0, 32, 32, 0, 0, 32, 0, 0,
7091  128, 128, 128, 128, 128, 128, 128, 128,
7092  128, 128, 128, 128, 128, 128, 128, 128,
7093  160, 128, 0, 128, 128, 128, 128, 128,
7094  128, 128, 128, 128, 128, 128, 128, 128,
7095  192, 192, 192, 192, 192, 192, 192, 192,
7096  192, 192, 128, 128, 128, 128, 128, 128,
7097  128, 128, 128, 128, 128, 128, 128, 128,
7098  128, 128, 128, 128, 128, 128, 128, 128,
7099  128, 128, 128, 128, 128, 128, 128, 128,
7100  128, 128, 128, 128, 0, 128, 128, 128,
7101  128, 128, 128, 128, 128, 128, 128, 128,
7102  128, 128, 128, 128, 128, 128, 128, 128,
7103  128, 128, 128, 128, 128, 128, 128, 128,
7104  128, 128, 128, 128, 128, 128, 128, 128,
7105  128, 128, 128, 128, 128, 128, 128, 128,
7106  128, 128, 128, 128, 128, 128, 128, 128,
7107  128, 128, 128, 128, 128, 128, 128, 128,
7108  128, 128, 128, 128, 128, 128, 128, 128,
7109  128, 128, 128, 128, 128, 128, 128, 128,
7110  128, 128, 128, 128, 128, 128, 128, 128,
7111  128, 128, 128, 128, 128, 128, 128, 128,
7112  128, 128, 128, 128, 128, 128, 128, 128,
7113  128, 128, 128, 128, 128, 128, 128, 128,
7114  128, 128, 128, 128, 128, 128, 128, 128,
7115  128, 128, 128, 128, 128, 128, 128, 128,
7116  128, 128, 128, 128, 128, 128, 128, 128,
7117  128, 128, 128, 128, 128, 128, 128, 128,
7118  128, 128, 128, 128, 128, 128, 128, 128,
7119  128, 128, 128, 128, 128, 128, 128, 128,
7120  128, 128, 128, 128, 128, 128, 128, 128,
7121  };
7122  if ((m_limit - m_cursor) < 5)
7123  {
7124  yyfill(); // LCOV_EXCL_LINE;
7125  }
7126  yych = *m_cursor;
7127  if (yybm[0 + yych] & 32)
7128  {
7129  goto basic_json_parser_6;
7130  }
7131  if (yych <= '\\')
7132  {
7133  if (yych <= '-')
7134  {
7135  if (yych <= '"')
7136  {
7137  if (yych <= 0x00)
7138  {
7139  goto basic_json_parser_2;
7140  }
7141  if (yych <= '!')
7142  {
7143  goto basic_json_parser_4;
7144  }
7145  goto basic_json_parser_9;
7146  }
7147  else
7148  {
7149  if (yych <= '+')
7150  {
7151  goto basic_json_parser_4;
7152  }
7153  if (yych <= ',')
7154  {
7155  goto basic_json_parser_10;
7156  }
7157  goto basic_json_parser_12;
7158  }
7159  }
7160  else
7161  {
7162  if (yych <= '9')
7163  {
7164  if (yych <= '/')
7165  {
7166  goto basic_json_parser_4;
7167  }
7168  if (yych <= '0')
7169  {
7170  goto basic_json_parser_13;
7171  }
7172  goto basic_json_parser_15;
7173  }
7174  else
7175  {
7176  if (yych <= ':')
7177  {
7178  goto basic_json_parser_17;
7179  }
7180  if (yych == '[')
7181  {
7182  goto basic_json_parser_19;
7183  }
7184  goto basic_json_parser_4;
7185  }
7186  }
7187  }
7188  else
7189  {
7190  if (yych <= 't')
7191  {
7192  if (yych <= 'f')
7193  {
7194  if (yych <= ']')
7195  {
7196  goto basic_json_parser_21;
7197  }
7198  if (yych <= 'e')
7199  {
7200  goto basic_json_parser_4;
7201  }
7202  goto basic_json_parser_23;
7203  }
7204  else
7205  {
7206  if (yych == 'n')
7207  {
7208  goto basic_json_parser_24;
7209  }
7210  if (yych <= 's')
7211  {
7212  goto basic_json_parser_4;
7213  }
7214  goto basic_json_parser_25;
7215  }
7216  }
7217  else
7218  {
7219  if (yych <= '|')
7220  {
7221  if (yych == '{')
7222  {
7223  goto basic_json_parser_26;
7224  }
7225  goto basic_json_parser_4;
7226  }
7227  else
7228  {
7229  if (yych <= '}')
7230  {
7231  goto basic_json_parser_28;
7232  }
7233  if (yych == 0xEF)
7234  {
7235  goto basic_json_parser_30;
7236  }
7237  goto basic_json_parser_4;
7238  }
7239  }
7240  }
7241 basic_json_parser_2:
7242  ++m_cursor;
7243  {
7244  return token_type::end_of_input;
7245  }
7246 basic_json_parser_4:
7247  ++m_cursor;
7248 basic_json_parser_5:
7249  {
7250  return token_type::parse_error;
7251  }
7252 basic_json_parser_6:
7253  ++m_cursor;
7254  if (m_limit <= m_cursor)
7255  {
7256  yyfill(); // LCOV_EXCL_LINE;
7257  }
7258  yych = *m_cursor;
7259  if (yybm[0 + yych] & 32)
7260  {
7261  goto basic_json_parser_6;
7262  }
7263  {
7264  return scan();
7265  }
7266 basic_json_parser_9:
7267  yyaccept = 0;
7268  yych = *(m_marker = ++m_cursor);
7269  if (yych <= 0x0F)
7270  {
7271  goto basic_json_parser_5;
7272  }
7273  goto basic_json_parser_32;
7274 basic_json_parser_10:
7275  ++m_cursor;
7276  {
7277  return token_type::value_separator;
7278  }
7279 basic_json_parser_12:
7280  yych = *++m_cursor;
7281  if (yych <= '/')
7282  {
7283  goto basic_json_parser_5;
7284  }
7285  if (yych <= '0')
7286  {
7287  goto basic_json_parser_13;
7288  }
7289  if (yych <= '9')
7290  {
7291  goto basic_json_parser_15;
7292  }
7293  goto basic_json_parser_5;
7294 basic_json_parser_13:
7295  yyaccept = 1;
7296  yych = *(m_marker = ++m_cursor);
7297  if (yych <= 'D')
7298  {
7299  if (yych == '.')
7300  {
7301  goto basic_json_parser_37;
7302  }
7303  }
7304  else
7305  {
7306  if (yych <= 'E')
7307  {
7308  goto basic_json_parser_38;
7309  }
7310  if (yych == 'e')
7311  {
7312  goto basic_json_parser_38;
7313  }
7314  }
7315 basic_json_parser_14:
7316  {
7317  return token_type::value_number;
7318  }
7319 basic_json_parser_15:
7320  yyaccept = 1;
7321  m_marker = ++m_cursor;
7322  if ((m_limit - m_cursor) < 3)
7323  {
7324  yyfill(); // LCOV_EXCL_LINE;
7325  }
7326  yych = *m_cursor;
7327  if (yybm[0 + yych] & 64)
7328  {
7329  goto basic_json_parser_15;
7330  }
7331  if (yych <= 'D')
7332  {
7333  if (yych == '.')
7334  {
7335  goto basic_json_parser_37;
7336  }
7337  goto basic_json_parser_14;
7338  }
7339  else
7340  {
7341  if (yych <= 'E')
7342  {
7343  goto basic_json_parser_38;
7344  }
7345  if (yych == 'e')
7346  {
7347  goto basic_json_parser_38;
7348  }
7349  goto basic_json_parser_14;
7350  }
7351 basic_json_parser_17:
7352  ++m_cursor;
7353  {
7354  return token_type::name_separator;
7355  }
7356 basic_json_parser_19:
7357  ++m_cursor;
7358  {
7359  return token_type::begin_array;
7360  }
7361 basic_json_parser_21:
7362  ++m_cursor;
7363  {
7364  return token_type::end_array;
7365  }
7366 basic_json_parser_23:
7367  yyaccept = 0;
7368  yych = *(m_marker = ++m_cursor);
7369  if (yych == 'a')
7370  {
7371  goto basic_json_parser_39;
7372  }
7373  goto basic_json_parser_5;
7374 basic_json_parser_24:
7375  yyaccept = 0;
7376  yych = *(m_marker = ++m_cursor);
7377  if (yych == 'u')
7378  {
7379  goto basic_json_parser_40;
7380  }
7381  goto basic_json_parser_5;
7382 basic_json_parser_25:
7383  yyaccept = 0;
7384  yych = *(m_marker = ++m_cursor);
7385  if (yych == 'r')
7386  {
7387  goto basic_json_parser_41;
7388  }
7389  goto basic_json_parser_5;
7390 basic_json_parser_26:
7391  ++m_cursor;
7392  {
7393  return token_type::begin_object;
7394  }
7395 basic_json_parser_28:
7396  ++m_cursor;
7397  {
7398  return token_type::end_object;
7399  }
7400 basic_json_parser_30:
7401  yyaccept = 0;
7402  yych = *(m_marker = ++m_cursor);
7403  if (yych == 0xBB)
7404  {
7405  goto basic_json_parser_42;
7406  }
7407  goto basic_json_parser_5;
7408 basic_json_parser_31:
7409  ++m_cursor;
7410  if (m_limit <= m_cursor)
7411  {
7412  yyfill(); // LCOV_EXCL_LINE;
7413  }
7414  yych = *m_cursor;
7415 basic_json_parser_32:
7416  if (yybm[0 + yych] & 128)
7417  {
7418  goto basic_json_parser_31;
7419  }
7420  if (yych <= 0x0F)
7421  {
7422  goto basic_json_parser_33;
7423  }
7424  if (yych <= '"')
7425  {
7426  goto basic_json_parser_34;
7427  }
7428  goto basic_json_parser_36;
7429 basic_json_parser_33:
7430  m_cursor = m_marker;
7431  if (yyaccept == 0)
7432  {
7433  goto basic_json_parser_5;
7434  }
7435  else
7436  {
7437  goto basic_json_parser_14;
7438  }
7439 basic_json_parser_34:
7440  ++m_cursor;
7441  {
7442  return token_type::value_string;
7443  }
7444 basic_json_parser_36:
7445  ++m_cursor;
7446  if (m_limit <= m_cursor)
7447  {
7448  yyfill(); // LCOV_EXCL_LINE;
7449  }
7450  yych = *m_cursor;
7451  if (yych <= 'e')
7452  {
7453  if (yych <= '/')
7454  {
7455  if (yych == '"')
7456  {
7457  goto basic_json_parser_31;
7458  }
7459  if (yych <= '.')
7460  {
7461  goto basic_json_parser_33;
7462  }
7463  goto basic_json_parser_31;
7464  }
7465  else
7466  {
7467  if (yych <= '\\')
7468  {
7469  if (yych <= '[')
7470  {
7471  goto basic_json_parser_33;
7472  }
7473  goto basic_json_parser_31;
7474  }
7475  else
7476  {
7477  if (yych == 'b')
7478  {
7479  goto basic_json_parser_31;
7480  }
7481  goto basic_json_parser_33;
7482  }
7483  }
7484  }
7485  else
7486  {
7487  if (yych <= 'q')
7488  {
7489  if (yych <= 'f')
7490  {
7491  goto basic_json_parser_31;
7492  }
7493  if (yych == 'n')
7494  {
7495  goto basic_json_parser_31;
7496  }
7497  goto basic_json_parser_33;
7498  }
7499  else
7500  {
7501  if (yych <= 's')
7502  {
7503  if (yych <= 'r')
7504  {
7505  goto basic_json_parser_31;
7506  }
7507  goto basic_json_parser_33;
7508  }
7509  else
7510  {
7511  if (yych <= 't')
7512  {
7513  goto basic_json_parser_31;
7514  }
7515  if (yych <= 'u')
7516  {
7517  goto basic_json_parser_43;
7518  }
7519  goto basic_json_parser_33;
7520  }
7521  }
7522  }
7523 basic_json_parser_37:
7524  yych = *++m_cursor;
7525  if (yych <= '/')
7526  {
7527  goto basic_json_parser_33;
7528  }
7529  if (yych <= '9')
7530  {
7531  goto basic_json_parser_44;
7532  }
7533  goto basic_json_parser_33;
7534 basic_json_parser_38:
7535  yych = *++m_cursor;
7536  if (yych <= ',')
7537  {
7538  if (yych == '+')
7539  {
7540  goto basic_json_parser_46;
7541  }
7542  goto basic_json_parser_33;
7543  }
7544  else
7545  {
7546  if (yych <= '-')
7547  {
7548  goto basic_json_parser_46;
7549  }
7550  if (yych <= '/')
7551  {
7552  goto basic_json_parser_33;
7553  }
7554  if (yych <= '9')
7555  {
7556  goto basic_json_parser_47;
7557  }
7558  goto basic_json_parser_33;
7559  }
7560 basic_json_parser_39:
7561  yych = *++m_cursor;
7562  if (yych == 'l')
7563  {
7564  goto basic_json_parser_49;
7565  }
7566  goto basic_json_parser_33;
7567 basic_json_parser_40:
7568  yych = *++m_cursor;
7569  if (yych == 'l')
7570  {
7571  goto basic_json_parser_50;
7572  }
7573  goto basic_json_parser_33;
7574 basic_json_parser_41:
7575  yych = *++m_cursor;
7576  if (yych == 'u')
7577  {
7578  goto basic_json_parser_51;
7579  }
7580  goto basic_json_parser_33;
7581 basic_json_parser_42:
7582  yych = *++m_cursor;
7583  if (yych == 0xBF)
7584  {
7585  goto basic_json_parser_52;
7586  }
7587  goto basic_json_parser_33;
7588 basic_json_parser_43:
7589  ++m_cursor;
7590  if (m_limit <= m_cursor)
7591  {
7592  yyfill(); // LCOV_EXCL_LINE;
7593  }
7594  yych = *m_cursor;
7595  if (yych <= '@')
7596  {
7597  if (yych <= '/')
7598  {
7599  goto basic_json_parser_33;
7600  }
7601  if (yych <= '9')
7602  {
7603  goto basic_json_parser_54;
7604  }
7605  goto basic_json_parser_33;
7606  }
7607  else
7608  {
7609  if (yych <= 'F')
7610  {
7611  goto basic_json_parser_54;
7612  }
7613  if (yych <= '`')
7614  {
7615  goto basic_json_parser_33;
7616  }
7617  if (yych <= 'f')
7618  {
7619  goto basic_json_parser_54;
7620  }
7621  goto basic_json_parser_33;
7622  }
7623 basic_json_parser_44:
7624  yyaccept = 1;
7625  m_marker = ++m_cursor;
7626  if ((m_limit - m_cursor) < 3)
7627  {
7628  yyfill(); // LCOV_EXCL_LINE;
7629  }
7630  yych = *m_cursor;
7631  if (yych <= 'D')
7632  {
7633  if (yych <= '/')
7634  {
7635  goto basic_json_parser_14;
7636  }
7637  if (yych <= '9')
7638  {
7639  goto basic_json_parser_44;
7640  }
7641  goto basic_json_parser_14;
7642  }
7643  else
7644  {
7645  if (yych <= 'E')
7646  {
7647  goto basic_json_parser_38;
7648  }
7649  if (yych == 'e')
7650  {
7651  goto basic_json_parser_38;
7652  }
7653  goto basic_json_parser_14;
7654  }
7655 basic_json_parser_46:
7656  yych = *++m_cursor;
7657  if (yych <= '/')
7658  {
7659  goto basic_json_parser_33;
7660  }
7661  if (yych >= ':')
7662  {
7663  goto basic_json_parser_33;
7664  }
7665 basic_json_parser_47:
7666  ++m_cursor;
7667  if (m_limit <= m_cursor)
7668  {
7669  yyfill(); // LCOV_EXCL_LINE;
7670  }
7671  yych = *m_cursor;
7672  if (yych <= '/')
7673  {
7674  goto basic_json_parser_14;
7675  }
7676  if (yych <= '9')
7677  {
7678  goto basic_json_parser_47;
7679  }
7680  goto basic_json_parser_14;
7681 basic_json_parser_49:
7682  yych = *++m_cursor;
7683  if (yych == 's')
7684  {
7685  goto basic_json_parser_55;
7686  }
7687  goto basic_json_parser_33;
7688 basic_json_parser_50:
7689  yych = *++m_cursor;
7690  if (yych == 'l')
7691  {
7692  goto basic_json_parser_56;
7693  }
7694  goto basic_json_parser_33;
7695 basic_json_parser_51:
7696  yych = *++m_cursor;
7697  if (yych == 'e')
7698  {
7699  goto basic_json_parser_58;
7700  }
7701  goto basic_json_parser_33;
7702 basic_json_parser_52:
7703  ++m_cursor;
7704  {
7705  return scan();
7706  }
7707 basic_json_parser_54:
7708  ++m_cursor;
7709  if (m_limit <= m_cursor)
7710  {
7711  yyfill(); // LCOV_EXCL_LINE;
7712  }
7713  yych = *m_cursor;
7714  if (yych <= '@')
7715  {
7716  if (yych <= '/')
7717  {
7718  goto basic_json_parser_33;
7719  }
7720  if (yych <= '9')
7721  {
7722  goto basic_json_parser_60;
7723  }
7724  goto basic_json_parser_33;
7725  }
7726  else
7727  {
7728  if (yych <= 'F')
7729  {
7730  goto basic_json_parser_60;
7731  }
7732  if (yych <= '`')
7733  {
7734  goto basic_json_parser_33;
7735  }
7736  if (yych <= 'f')
7737  {
7738  goto basic_json_parser_60;
7739  }
7740  goto basic_json_parser_33;
7741  }
7742 basic_json_parser_55:
7743  yych = *++m_cursor;
7744  if (yych == 'e')
7745  {
7746  goto basic_json_parser_61;
7747  }
7748  goto basic_json_parser_33;
7749 basic_json_parser_56:
7750  ++m_cursor;
7751  {
7752  return token_type::literal_null;
7753  }
7754 basic_json_parser_58:
7755  ++m_cursor;
7756  {
7757  return token_type::literal_true;
7758  }
7759 basic_json_parser_60:
7760  ++m_cursor;
7761  if (m_limit <= m_cursor)
7762  {
7763  yyfill(); // LCOV_EXCL_LINE;
7764  }
7765  yych = *m_cursor;
7766  if (yych <= '@')
7767  {
7768  if (yych <= '/')
7769  {
7770  goto basic_json_parser_33;
7771  }
7772  if (yych <= '9')
7773  {
7774  goto basic_json_parser_63;
7775  }
7776  goto basic_json_parser_33;
7777  }
7778  else
7779  {
7780  if (yych <= 'F')
7781  {
7782  goto basic_json_parser_63;
7783  }
7784  if (yych <= '`')
7785  {
7786  goto basic_json_parser_33;
7787  }
7788  if (yych <= 'f')
7789  {
7790  goto basic_json_parser_63;
7791  }
7792  goto basic_json_parser_33;
7793  }
7794 basic_json_parser_61:
7795  ++m_cursor;
7796  {
7797  return token_type::literal_false;
7798  }
7799 basic_json_parser_63:
7800  ++m_cursor;
7801  if (m_limit <= m_cursor)
7802  {
7803  yyfill(); // LCOV_EXCL_LINE;
7804  }
7805  yych = *m_cursor;
7806  if (yych <= '@')
7807  {
7808  if (yych <= '/')
7809  {
7810  goto basic_json_parser_33;
7811  }
7812  if (yych <= '9')
7813  {
7814  goto basic_json_parser_31;
7815  }
7816  goto basic_json_parser_33;
7817  }
7818  else
7819  {
7820  if (yych <= 'F')
7821  {
7822  goto basic_json_parser_31;
7823  }
7824  if (yych <= '`')
7825  {
7826  goto basic_json_parser_33;
7827  }
7828  if (yych <= 'f')
7829  {
7830  goto basic_json_parser_31;
7831  }
7832  goto basic_json_parser_33;
7833  }
7834  }
7835 
7836 
7837  }
7838 
7840  void yyfill() noexcept
7841  {
7842  if (m_stream == nullptr or not * m_stream)
7843  {
7844  return;
7845  }
7846 
7847  const ssize_t offset_start = m_start - m_content;
7848  const ssize_t offset_marker = m_marker - m_start;
7849  const ssize_t offset_cursor = m_cursor - m_start;
7850 
7851  m_buffer.erase(0, static_cast<size_t>(offset_start));
7852  std::string line;
7853  assert(m_stream != nullptr);
7854  std::getline(*m_stream, line);
7855  m_buffer += "\n" + line; // add line with newline symbol
7856 
7857  m_content = reinterpret_cast<const lexer_char_t*>(m_buffer.c_str());
7858  assert(m_content != nullptr);
7859  m_start = m_content;
7860  m_marker = m_start + offset_marker;
7861  m_cursor = m_start + offset_cursor;
7862  m_limit = m_start + m_buffer.size() - 1;
7863  }
7864 
7866  string_t get_token() const noexcept
7867  {
7868  assert(m_start != nullptr);
7869  return string_t(reinterpret_cast<typename string_t::const_pointer>(m_start),
7870  static_cast<size_t>(m_cursor - m_start));
7871  }
7872 
7894  string_t get_string() const
7895  {
7896  string_t result;
7897  result.reserve(static_cast<size_t>(m_cursor - m_start - 2));
7898 
7899  // iterate the result between the quotes
7900  for (const lexer_char_t* i = m_start + 1; i < m_cursor - 1; ++i)
7901  {
7902  // process escaped characters
7903  if (*i == '\\')
7904  {
7905  // read next character
7906  ++i;
7907 
7908  switch (*i)
7909  {
7910  // the default escapes
7911  case 't':
7912  {
7913  result += "\t";
7914  break;
7915  }
7916  case 'b':
7917  {
7918  result += "\b";
7919  break;
7920  }
7921  case 'f':
7922  {
7923  result += "\f";
7924  break;
7925  }
7926  case 'n':
7927  {
7928  result += "\n";
7929  break;
7930  }
7931  case 'r':
7932  {
7933  result += "\r";
7934  break;
7935  }
7936  case '\\':
7937  {
7938  result += "\\";
7939  break;
7940  }
7941  case '/':
7942  {
7943  result += "/";
7944  break;
7945  }
7946  case '"':
7947  {
7948  result += "\"";
7949  break;
7950  }
7951 
7952  // unicode
7953  case 'u':
7954  {
7955  // get code xxxx from uxxxx
7956  auto codepoint = std::strtoul(std::string(reinterpret_cast<typename string_t::const_pointer>(i + 1),
7957  4).c_str(), nullptr, 16);
7958 
7959  // check if codepoint is a high surrogate
7960  if (codepoint >= 0xD800 and codepoint <= 0xDBFF)
7961  {
7962  // make sure there is a subsequent unicode
7963  if ((i + 6 >= m_limit) or * (i + 5) != '\\' or * (i + 6) != 'u')
7964  {
7965  throw std::invalid_argument("missing low surrogate");
7966  }
7967 
7968  // get code yyyy from uxxxx\uyyyy
7969  auto codepoint2 = std::strtoul(std::string(reinterpret_cast<typename string_t::const_pointer>
7970  (i + 7), 4).c_str(), nullptr, 16);
7971  result += to_unicode(codepoint, codepoint2);
7972  // skip the next 10 characters (xxxx\uyyyy)
7973  i += 10;
7974  }
7975  else
7976  {
7977  // add unicode character(s)
7978  result += to_unicode(codepoint);
7979  // skip the next four characters (xxxx)
7980  i += 4;
7981  }
7982  break;
7983  }
7984  }
7985  }
7986  else
7987  {
7988  // all other characters are just copied to the end of the
7989  // string
7990  result.append(1, static_cast<typename string_t::value_type>(*i));
7991  }
7992  }
7993 
7994  return result;
7995  }
7996 
8017  long double str_to_float_t(long double* /* type */, char** endptr) const
8018  {
8019  return std::strtold(reinterpret_cast<typename string_t::const_pointer>(m_start), endptr);
8020  }
8021 
8036  double str_to_float_t(double* /* type */, char** endptr) const
8037  {
8038  return std::strtod(reinterpret_cast<typename string_t::const_pointer>(m_start), endptr);
8039  }
8040 
8055  float str_to_float_t(float* /* type */, char** endptr) const
8056  {
8057  return std::strtof(reinterpret_cast<typename string_t::const_pointer>(m_start), endptr);
8058  }
8059 
8072  template <typename T_A, typename T_B>
8073  bool attempt_cast(T_A source, T_B& dest) const
8074  {
8075  dest = static_cast<T_B>(source);
8076  return (source == static_cast<T_A>(dest));
8077  }
8078 
8117  void get_number(basic_json& result) const
8118  {
8119  typename string_t::value_type* endptr;
8120  assert(m_start != nullptr);
8121  errno = 0;
8122 
8123  // attempt to parse it as an integer - first checking for a
8124  // negative number
8125  if (*reinterpret_cast<typename string_t::const_pointer>(m_start) != '-')
8126  {
8127  // positive, parse with strtoull and attempt cast to
8128  // number_unsigned_t
8129  if (attempt_cast(std::strtoull(reinterpret_cast<typename string_t::const_pointer>(m_start), &endptr,
8130  10), result.m_value.number_unsigned))
8131  {
8132  result.m_type = value_t::number_unsigned;
8133  }
8134  else
8135  {
8136  // cast failed due to overflow - store as float
8137  result.m_type = value_t::number_float;
8138  }
8139  }
8140  else
8141  {
8142  // Negative, parse with strtoll and attempt cast to
8143  // number_integer_t
8144  if (attempt_cast(std::strtoll(reinterpret_cast<typename string_t::const_pointer>(m_start), &endptr,
8145  10), result.m_value.number_integer))
8146  {
8147  result.m_type = value_t::number_integer;
8148  }
8149  else
8150  {
8151  // cast failed due to overflow - store as float
8152  result.m_type = value_t::number_float;
8153  }
8154  }
8155 
8156  // check the end of the number was reached and no range error
8157  // occurred
8158  if (reinterpret_cast<lexer_char_t*>(endptr) != m_cursor || errno == ERANGE)
8159  {
8160  result.m_type = value_t::number_float;
8161  }
8162 
8163  if (result.m_type == value_t::number_float)
8164  {
8165  // either the number won't fit in an integer (range error from
8166  // strtoull/strtoll or overflow on cast) or there was something
8167  // else after the number, which could be an exponent
8168 
8169  // parse with strtod
8170  result.m_value.number_float = str_to_float_t(static_cast<number_float_t*>(nullptr), &endptr);
8171 
8172  // anything after the number is an error
8173  if (reinterpret_cast<lexer_char_t*>(endptr) != m_cursor)
8174  {
8175  throw std::invalid_argument(std::string("parse error - ") + get_token() + " is not a number");
8176  }
8177  }
8178  }
8179 
8180  private:
8182  std::istream* m_stream = nullptr;
8184  string_t m_buffer;
8186  const lexer_char_t* m_content = nullptr;
8188  const lexer_char_t* m_start = nullptr;
8190  const lexer_char_t* m_marker = nullptr;
8192  const lexer_char_t* m_cursor = nullptr;
8194  const lexer_char_t* m_limit = nullptr;
8195  };
8196 
8202  class parser
8203  {
8204  public:
8206  parser(const string_t& s, parser_callback_t cb = nullptr)
8207  : callback(cb), m_lexer(s)
8208  {
8209  // read first token
8210  get_token();
8211  }
8212 
8214  parser(std::istream& _is, parser_callback_t cb = nullptr)
8215  : callback(cb), m_lexer(&_is)
8216  {
8217  // read first token
8218  get_token();
8219  }
8220 
8222  basic_json parse()
8223  {
8224  basic_json result = parse_internal(true);
8225 
8226  expect(lexer::token_type::end_of_input);
8227 
8228  // return parser result and replace it with null in case the
8229  // top-level value was discarded by the callback function
8230  return result.is_discarded() ? basic_json() : result;
8231  }
8232 
8233  private:
8235  basic_json parse_internal(bool keep)
8236  {
8237  auto result = basic_json(value_t::discarded);
8238 
8239  switch (last_token)
8240  {
8241  case lexer::token_type::begin_object:
8242  {
8243  if (keep and (not callback or (keep = callback(depth++, parse_event_t::object_start, result))))
8244  {
8245  // explicitly set result to object to cope with {}
8246  result.m_type = value_t::object;
8247  result.m_value = json_value(value_t::object);
8248  }
8249 
8250  // read next token
8251  get_token();
8252 
8253  // closing } -> we are done
8254  if (last_token == lexer::token_type::end_object)
8255  {
8256  get_token();
8257  if (keep and callback and not callback(--depth, parse_event_t::object_end, result))
8258  {
8259  result = basic_json(value_t::discarded);
8260  }
8261  return result;
8262  }
8263 
8264  // no comma is expected here
8265  unexpect(lexer::token_type::value_separator);
8266 
8267  // otherwise: parse key-value pairs
8268  do
8269  {
8270  // ugly, but could be fixed with loop reorganization
8271  if (last_token == lexer::token_type::value_separator)
8272  {
8273  get_token();
8274  }
8275 
8276  // store key
8277  expect(lexer::token_type::value_string);
8278  const auto key = m_lexer.get_string();
8279 
8280  bool keep_tag = false;
8281  if (keep)
8282  {
8283  if (callback)
8284  {
8285  basic_json k(key);
8286  keep_tag = callback(depth, parse_event_t::key, k);
8287  }
8288  else
8289  {
8290  keep_tag = true;
8291  }
8292  }
8293 
8294  // parse separator (:)
8295  get_token();
8296  expect(lexer::token_type::name_separator);
8297 
8298  // parse and add value
8299  get_token();
8300  auto value = parse_internal(keep);
8301  if (keep and keep_tag and not value.is_discarded())
8302  {
8303  result[key] = std::move(value);
8304  }
8305  }
8306  while (last_token == lexer::token_type::value_separator);
8307 
8308  // closing }
8309  expect(lexer::token_type::end_object);
8310  get_token();
8311  if (keep and callback and not callback(--depth, parse_event_t::object_end, result))
8312  {
8313  result = basic_json(value_t::discarded);
8314  }
8315 
8316  return result;
8317  }
8318 
8319  case lexer::token_type::begin_array:
8320  {
8321  if (keep and (not callback or (keep = callback(depth++, parse_event_t::array_start, result))))
8322  {
8323  // explicitly set result to object to cope with []
8324  result.m_type = value_t::array;
8325  result.m_value = json_value(value_t::array);
8326  }
8327 
8328  // read next token
8329  get_token();
8330 
8331  // closing ] -> we are done
8332  if (last_token == lexer::token_type::end_array)
8333  {
8334  get_token();
8335  if (callback and not callback(--depth, parse_event_t::array_end, result))
8336  {
8337  result = basic_json(value_t::discarded);
8338  }
8339  return result;
8340  }
8341 
8342  // no comma is expected here
8343  unexpect(lexer::token_type::value_separator);
8344 
8345  // otherwise: parse values
8346  do
8347  {
8348  // ugly, but could be fixed with loop reorganization
8349  if (last_token == lexer::token_type::value_separator)
8350  {
8351  get_token();
8352  }
8353 
8354  // parse value
8355  auto value = parse_internal(keep);
8356  if (keep and not value.is_discarded())
8357  {
8358  result.push_back(std::move(value));
8359  }
8360  }
8361  while (last_token == lexer::token_type::value_separator);
8362 
8363  // closing ]
8364  expect(lexer::token_type::end_array);
8365  get_token();
8366  if (keep and callback and not callback(--depth, parse_event_t::array_end, result))
8367  {
8368  result = basic_json(value_t::discarded);
8369  }
8370 
8371  return result;
8372  }
8373 
8374  case lexer::token_type::literal_null:
8375  {
8376  get_token();
8377  result.m_type = value_t::null;
8378  break;
8379  }
8380 
8381  case lexer::token_type::value_string:
8382  {
8383  const auto s = m_lexer.get_string();
8384  get_token();
8385  result = basic_json(s);
8386  break;
8387  }
8388 
8389  case lexer::token_type::literal_true:
8390  {
8391  get_token();
8392  result.m_type = value_t::boolean;
8393  result.m_value = true;
8394  break;
8395  }
8396 
8397  case lexer::token_type::literal_false:
8398  {
8399  get_token();
8400  result.m_type = value_t::boolean;
8401  result.m_value = false;
8402  break;
8403  }
8404 
8405  case lexer::token_type::value_number:
8406  {
8407  m_lexer.get_number(result);
8408  get_token();
8409  break;
8410  }
8411 
8412  default:
8413  {
8414  // the last token was unexpected
8415  unexpect(last_token);
8416  }
8417  }
8418 
8419  if (keep and callback and not callback(depth, parse_event_t::value, result))
8420  {
8421  result = basic_json(value_t::discarded);
8422  }
8423  return result;
8424  }
8425 
8427  typename lexer::token_type get_token()
8428  {
8429  last_token = m_lexer.scan();
8430  return last_token;
8431  }
8432 
8433  void expect(typename lexer::token_type t) const
8434  {
8435  if (t != last_token)
8436  {
8437  std::string error_msg = "parse error - unexpected ";
8438  error_msg += (last_token == lexer::token_type::parse_error ? ("'" + m_lexer.get_token() + "'") :
8439  lexer::token_type_name(last_token));
8440  error_msg += "; expected " + lexer::token_type_name(t);
8441  throw std::invalid_argument(error_msg);
8442  }
8443  }
8444 
8445  void unexpect(typename lexer::token_type t) const
8446  {
8447  if (t == last_token)
8448  {
8449  std::string error_msg = "parse error - unexpected ";
8450  error_msg += (last_token == lexer::token_type::parse_error ? ("'" + m_lexer.get_token() + "'") :
8451  lexer::token_type_name(last_token));
8452  throw std::invalid_argument(error_msg);
8453  }
8454  }
8455 
8456  private:
8458  int depth = 0;
8460  parser_callback_t callback;
8462  typename lexer::token_type last_token = lexer::token_type::uninitialized;
8464  lexer m_lexer;
8465  };
8466 };
8467 
8468 
8470 // presets //
8472 
8482 }
8483 
8484 
8486 // nonmember functions //
8488 
8489 // specialization of std::swap, and std::hash
8490 namespace std
8491 {
8497 template <>
8498 inline void swap(nlohmann::json& j1,
8499  nlohmann::json& j2) noexcept(
8500  is_nothrow_move_constructible<nlohmann::json>::value and
8501  is_nothrow_move_assignable<nlohmann::json>::value
8502  )
8503 {
8504  j1.swap(j2);
8505 }
8506 
8508 template <>
8509 struct hash<nlohmann::json>
8510 {
8516  std::size_t operator()(const nlohmann::json& j) const
8517  {
8518  // a naive hashing via the string representation
8519  const auto& h = hash<nlohmann::json::string_t>();
8520  return h(j.dump());
8521  }
8522 };
8523 }
8524 
8537 inline nlohmann::json operator "" _json(const char* s, std::size_t)
8538 {
8539  return nlohmann::json::parse(reinterpret_cast<const nlohmann::json::string_t::value_type*>(s));
8540 }
8541 
8542 // restore GCC/clang diagnostic settings
8543 #if defined(__clang__) || defined(__GNUC__) || defined(__GNUG__)
8544  #pragma GCC diagnostic pop
8545 #endif
8546 
8547 #endif
bool is_null() const noexcept
return whether value is null
Definition: json.hpp:2122
reference operator*()
return a reference to the value pointed to by the iterator
Definition: json.hpp:6676
reverse_iterator rbegin()
returns an iterator to the reverse-beginning
Definition: json.hpp:4088
friend bool operator<=(const_reference lhs, const_reference rhs) noexcept
comparison: less than or equal
Definition: json.hpp:5315
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:1071
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:3936
value_t type() const noexcept
return the type of the JSON value (explicit)
Definition: json.hpp:2062
bool is_number_integer() const noexcept
return whether value is an integer number
Definition: json.hpp:2194
const_reference operator[](size_type idx) const
access specified array element
Definition: json.hpp:3156
reference value() const
return the value of an iterator
Definition: json.hpp:6759
json_reverse_iterator & operator--()
pre-decrement (–it)
Definition: json.hpp:6821
bool is_boolean() const noexcept
return whether value is a boolean
Definition: json.hpp:2141
void clear() noexcept
clears the contents
Definition: json.hpp:4425
bool operator==(const const_iterator &other) const
comparison: equal
Definition: json.hpp:6410
json_reverse_iterator operator--(int)
post-decrement (it–)
Definition: json.hpp:6815
reference operator[](T *(&key)[n])
access specified object element
Definition: json.hpp:3288
friend std::istream & operator>>(std::istream &i, basic_json &j)
deserialize from stream
Definition: json.hpp:5528
bool is_number() const noexcept
return whether value is a number
Definition: json.hpp:2168
iterator & operator+=(difference_type i)
add to iterator
Definition: json.hpp:6718
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:1650
const_iterator operator-(difference_type i)
subtract from iterator
Definition: json.hpp:6536
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:4611
bool is_array() const noexcept
return whether value is an array
Definition: json.hpp:2282
basic_json(const typename string_t::value_type *val)
create a string (explicit)
Definition: json.hpp:1161
basic_json(boolean_t val)
create a boolean (explicit)
Definition: json.hpp:1210
reference operator[](difference_type n) const
access to successor
Definition: json.hpp:6857
iterator find(typename object_t::key_type key)
find an element in a JSON object
Definition: json.hpp:3888
basic_json(const number_unsigned_t val)
create an unsigned integer number (explicit)
Definition: json.hpp:1339
friend bool operator!=(const_reference lhs, const_reference rhs) noexcept
comparison: not equal
Definition: json.hpp:5153
basic_json(const string_t &val)
create a string (explicit)
Definition: json.hpp:1137
void push_back(const basic_json &val)
add an object to an array
Definition: json.hpp:4537
void erase(const size_type idx)
remove element from a JSON array given an index
Definition: json.hpp:3852
basic_json<> json
default JSON class
Definition: json.hpp:8481
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:2103
reference front()
access the first element
Definition: json.hpp:3523
void swap(object_t &other)
exchanges the values
Definition: json.hpp:4909
json_reverse_iterator operator-(difference_type i) const
subtract from iterator
Definition: json.hpp:6843
const_iterator & operator+=(difference_type i)
add to iterator
Definition: json.hpp:6494
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:1399
pointer operator->()
dereference the iterator
Definition: json.hpp:6682
reference value() const
return the value of an iterator
Definition: json.hpp:6870
friend bool operator==(std::nullptr_t, const_reference v) noexcept
comparison: equal
Definition: json.hpp:5132
const_reverse_iterator crbegin() const
returns a const reverse iterator to the last element
Definition: json.hpp:4150
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:4695
const_reference at(const typename object_t::key_type &key) const
access specified object element with bounds checking
Definition: json.hpp:3064
const_iterator operator+(difference_type i)
add to iterator
Definition: json.hpp:6528
const_reverse_iterator rbegin() const
returns a const reverse iterator to the last element
Definition: json.hpp:4096
a mutable random access iterator for the basic_json class
Definition: json.hpp:6643
static basic_json parse(std::istream &&i, parser_callback_t cb=nullptr)
deserialize from stream
Definition: json.hpp:5490
const_iterator operator++(int)
post-increment (it++)
Definition: json.hpp:6336
bool is_string() const noexcept
return whether value is a string
Definition: json.hpp:2301
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:1610
static iteration_proxy< const_iterator > iterator_wrapper(const_reference cont)
wrapper to access iterator member functions in range-based for
Definition: json.hpp:4202
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:1936
typename basic_json::value_type value_type
the type of the values when the iterator is dereferenced
Definition: json.hpp:6108
PointerType get_ptr() noexcept
get a pointer value (implicit)
Definition: json.hpp:2778
reference back()
access the last element
Definition: json.hpp:3557
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:6112
bool is_number_unsigned() const noexcept
return whether value is an unsigned integer number
Definition: json.hpp:2219
void push_back(const typename object_t::value_type &val)
add an object to an object
Definition: json.hpp:4587
iterator end()
returns an iterator to one past the last element
Definition: json.hpp:4030
static basic_json parse(const string_t &s, parser_callback_t cb=nullptr)
deserialize from string
Definition: json.hpp:5453
const_reference operator[](T *(&key)[n]) const
read-only access specified object element
Definition: json.hpp:3323
iterator insert(const_iterator pos, const_iterator first, const_iterator last)
inserts elements
Definition: json.hpp:4748
basic_json(std::nullptr_t) noexcept
create a null object (explicitly)
Definition: json.hpp:989
basic_json(InputIT first, InputIT last)
construct a JSON container given an iterator range
Definition: json.hpp:1720
reference operator[](difference_type n) const
access to successor
Definition: json.hpp:6753
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:3245
const_reference operator[](T *key) const
read-only access specified object element
Definition: json.hpp:3405
json_reverse_iterator operator+(difference_type i) const
add to iterator
Definition: json.hpp:6835
bool empty() const noexcept
checks whether the container is empty
Definition: json.hpp:4246
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:6863
basic_json(const CompatibleArrayType &val)
create an array (implicit)
Definition: json.hpp:1108
const_reference at(size_type idx) const
access specified array element with bounds checking
Definition: json.hpp:2968
basic_json(size_type cnt, const basic_json &val)
construct an array with count copies of given value
Definition: json.hpp:1674
std::reverse_iterator< Base > base_iterator
shortcut to the reverse iterator adaptor
Definition: json.hpp:6787
iterator insert(const_iterator pos, std::initializer_list< basic_json > ilist)
inserts elements
Definition: json.hpp:4806
const_iterator(const iterator &other)
copy constructor given a nonconst iterator
Definition: json.hpp:6149
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:4639
friend bool operator>=(const_reference lhs, const_reference rhs) noexcept
comparison: greater than or equal
Definition: json.hpp:5359
friend bool operator<(const_reference lhs, const_reference rhs) noexcept
comparison: less than
Definition: json.hpp:5214
iterator & operator++()
pre-increment (++it)
Definition: json.hpp:6696
bool operator<(const const_iterator &other) const
comparison: smaller
Definition: json.hpp:6446
iterator operator++(int)
post-increment (it++)
Definition: json.hpp:6688
basic_json(basic_json &&other) noexcept
move constructor
Definition: json.hpp:1906
const_iterator operator--(int)
post-decrement (it–)
Definition: json.hpp:6373
bool is_discarded() const noexcept
return whether value is discarded
Definition: json.hpp:2325
reference at(const typename object_t::key_type &key)
access specified object element with bounds checking
Definition: json.hpp:3016
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:6664
object (unordered set of name/value pairs)
size_type max_size() const noexcept
returns the maximum possible number of elements
Definition: json.hpp:4366
~basic_json()
destructor
Definition: json.hpp:1962
iterator operator--(int)
post-decrement (it–)
Definition: json.hpp:6703
iterator operator-(difference_type i)
subtract from iterator
Definition: json.hpp:6740
const_iterator & operator--()
pre-decrement (–it)
Definition: json.hpp:6381
const_iterator cend() const
returns a const iterator to one past the last element
Definition: json.hpp:4064
string_t dump(const int indent=-1) const
serialization
Definition: json.hpp:2031
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:4561
iterator begin()
returns an iterator to the first element
Definition: json.hpp:3971
difference_type operator-(const const_iterator &other) const
return difference
Definition: json.hpp:6544
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:3981
friend std::ostream & operator>>(const basic_json &j, std::ostream &o)
serialize to stream
Definition: json.hpp:5414
difference_type operator-(const iterator &other) const
Definition: json.hpp:6747
basic_json(const int val)
create an integer number from an enum type (explicit)
Definition: json.hpp:1274
iterator(const iterator &other) noexcept
copy constructor
Definition: json.hpp:6659
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:6110
void swap(string_t &other)
exchanges the values
Definition: json.hpp:4943
json_reverse_iterator(const base_iterator &it)
create reverse iterator from base class
Definition: json.hpp:6797
basic_json(const number_integer_t val)
create an integer number (explicit)
Definition: json.hpp:1245
reverse_iterator rend()
returns an iterator to the reverse-end
Definition: json.hpp:4119
basic_json(const CompatibleNumberIntegerType val) noexcept
create an integer number (implicit)
Definition: json.hpp:1311
const_reference front() const
access the first element
Definition: json.hpp:3531
bool operator>(const const_iterator &other) const
comparison: greater than
Definition: json.hpp:6482
bool is_object() const noexcept
return whether value is an object
Definition: json.hpp:2263
pointer operator->() const
dereference the iterator
Definition: json.hpp:6301
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:4844
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:4127
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:2083
ValueType get() const
get a value (explicit)
Definition: json.hpp:2694
void swap(array_t &other)
exchanges the values
Definition: json.hpp:4875
InteratorType erase(InteratorType first, InteratorType last)
remove elements given an iterator range
Definition: json.hpp:3730
ValueType value(const typename object_t::key_type &key, ValueType default_value) const
access specified object element with default value
Definition: json.hpp:3472
typename Base::reference reference
the reference type for the pointed-to element
Definition: json.hpp:6789
const_reference back() const
access the last element
Definition: json.hpp:3567
void push_back(basic_json &&val)
add an object to an array
Definition: json.hpp:4501
array (ordered collection of values)
json_reverse_iterator & operator++()
pre-increment (++it)
Definition: json.hpp:6808
static basic_json parse(std::istream &i, parser_callback_t cb=nullptr)
deserialize from stream
Definition: json.hpp:5482
friend bool operator==(const_reference lhs, const_reference rhs) noexcept
comparison: equal
Definition: json.hpp:5024
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:3498
ReferenceType get_ref() const
get a reference value (implicit)
Definition: json.hpp:2844
basic_json(const CompatibleNumberUnsignedType val) noexcept
create an unsigned number (implicit)
Definition: json.hpp:1370
const_iterator(pointer object)
constructor for a given JSON instance
Definition: json.hpp:6122
reference operator*() const
return a reference to the value pointed to by the iterator
Definition: json.hpp:6261
friend bool operator<(const value_t lhs, const value_t rhs)
comparison operator for JSON types
Definition: json.hpp:4977
const PointerType get_ptr() const noexcept
get a pointer value (implicit)
Definition: json.hpp:2793
friend bool operator!=(const_reference v, std::nullptr_t) noexcept
comparison: not equal
Definition: json.hpp:5176
iterator operator+(difference_type i)
add to iterator
Definition: json.hpp:6732
basic_json(const CompatibleNumberFloatType val) noexcept
create an floating-point number (implicit)
Definition: json.hpp:1445
bool operator<=(const const_iterator &other) const
comparison: less than or equal
Definition: json.hpp:6476
InteratorType erase(InteratorType pos)
remove element given an iterator
Definition: json.hpp:3624
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:1518
iterator(pointer object) noexcept
constructor for a given JSON instance
Definition: json.hpp:6654
friend bool operator!=(std::nullptr_t, const_reference v) noexcept
comparison: not equal
Definition: json.hpp:5185
json_reverse_iterator(const typename base_iterator::iterator_type &it)
create reverse iterator from iterator
Definition: json.hpp:6792
const_iterator & operator++()
pre-increment (++it)
Definition: json.hpp:6344
bool is_number_float() const noexcept
return whether value is a floating-point number
Definition: json.hpp:2244
reference value() const
return the value of an iterator
Definition: json.hpp:6619
std::bidirectional_iterator_tag iterator_category
the category of the iterator
Definition: json.hpp:6116
difference_type operator-(const json_reverse_iterator &other) const
return difference
Definition: json.hpp:6851
const_iterator find(typename object_t::key_type key) const
find an element in a JSON object
Definition: json.hpp:3905
basic_json(const CompatibleObjectType &val)
create an object (implicit)
Definition: json.hpp:1044
friend bool operator>(const_reference lhs, const_reference rhs) noexcept
comparison: greater than
Definition: json.hpp:5337
bool operator>=(const const_iterator &other) const
comparison: greater than or equal
Definition: json.hpp:6488
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:6181
size_type erase(const typename object_t::key_type &key)
remove element from a JSON object given a key
Definition: json.hpp:3814
reference operator[](const typename object_t::key_type &key)
access specified object element
Definition: json.hpp:3197
object_t::key_type key() const
return the key of an object iterator
Definition: json.hpp:6604
const_iterator end() const
returns a const iterator to one past the last element
Definition: json.hpp:4040
reference operator+=(basic_json &&val)
add an object to an array
Definition: json.hpp:4527
reference operator[](difference_type n) const
access to successor
Definition: json.hpp:6568
a const random access iterator for the basic_json class
Definition: json.hpp:6101
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:6114
json_reverse_iterator operator++(int)
post-increment (it++)
Definition: json.hpp:6802
friend bool operator==(const_reference v, std::nullptr_t) noexcept
comparison: equal
Definition: json.hpp:5123
reference operator[](size_type idx)
access specified array element
Definition: json.hpp:3111
bool operator!=(const const_iterator &other) const
comparison: not equal
Definition: json.hpp:6440
json_reverse_iterator & operator+=(difference_type i)
add to iterator
Definition: json.hpp:6828
reference at(size_type idx)
access specified array element with bounds checking
Definition: json.hpp:2924
size_type size() const noexcept
returns the number of elements
Definition: json.hpp:4304
static iteration_proxy< iterator > iterator_wrapper(reference cont)
wrapper to access iterator member functions in range-based for
Definition: json.hpp:4194
const_iterator cbegin() const
returns a const iterator to the first element
Definition: json.hpp:4005
iterator & operator-=(difference_type i)
subtract from iterator
Definition: json.hpp:6725
const_reverse_iterator crend() const
returns a const reverse iterator to one before the first
Definition: json.hpp:4173
basic_json(const object_t &val)
create an object (explicit)
Definition: json.hpp:1012
friend std::istream & operator<<(basic_json &j, std::istream &i)
deserialize from stream
Definition: json.hpp:5518
std::size_t operator()(const nlohmann::json &j) const
return a hash value for a JSON object
Definition: json.hpp:8516
friend std::ostream & operator<<(std::ostream &o, const basic_json &j)
serialize to stream
Definition: json.hpp:5396
const_iterator(const const_iterator &other) noexcept
copy constructor
Definition: json.hpp:6176
iterator & operator--()
pre-decrement (–it)
Definition: json.hpp:6711
iterator insert(const_iterator pos, basic_json &&val)
inserts element
Definition: json.hpp:4666
ReferenceType get_ref()
get a reference value (implicit)
Definition: json.hpp:2829
const_iterator & operator-=(difference_type i)
subtract from iterator
Definition: json.hpp:6522
basic_json(const CompatibleStringType &val)
create a string (implicit)
Definition: json.hpp:1192
basic_json(const basic_json &other)
copy constructor
Definition: json.hpp:1831
reference operator[](T *key)
access specified object element
Definition: json.hpp:3356
parse_event_t
JSON callback events.
Definition: json.hpp:831