JSON for Modern C++  2.0.0
json.hpp
1 /*
2  __ _____ _____ _____
3  __| | __| | | | JSON for Modern C++
4 | | |__ | | | | | | version 2.0.0
5 |_____|_____|_____|_|___| https://github.com/nlohmann/json
6 
7 Copyright (c) 2013-2016 Niels Lohmann <http://nlohmann.me>.
8 Licensed under the MIT License <http://opensource.org/licenses/MIT>.
9 */
10 
11 #ifndef NLOHMANN_JSON_HPP
12 #define NLOHMANN_JSON_HPP
13 
14 #include <algorithm>
15 #include <array>
16 #include <cassert>
17 #include <ciso646>
18 #include <cmath>
19 #include <cstddef>
20 #include <cstdio>
21 #include <cstdlib>
22 #include <functional>
23 #include <initializer_list>
24 #include <iomanip>
25 #include <iostream>
26 #include <iterator>
27 #include <limits>
28 #include <map>
29 #include <memory>
30 #include <sstream>
31 #include <stdexcept>
32 #include <string>
33 #include <type_traits>
34 #include <utility>
35 #include <vector>
36 
37 // enable ssize_t on MinGW
38 #ifdef __GNUC__
39  #ifdef __MINGW32__
40  #include <sys/types.h>
41  #endif
42 #endif
43 
44 // disable float-equal warnings on GCC/clang
45 #if defined(__clang__) || defined(__GNUC__) || defined(__GNUG__)
46  #pragma GCC diagnostic push
47  #pragma GCC diagnostic ignored "-Wfloat-equal"
48 #endif
49 
50 // enable ssize_t for MSVC
51 #ifdef _MSC_VER
52  #include <basetsd.h>
53  using ssize_t = SSIZE_T;
54 #endif
55 
61 namespace nlohmann
62 {
63 
64 
69 namespace
70 {
75 template<typename T>
76 struct has_mapped_type
77 {
78  private:
79  template<typename C> static char test(typename C::mapped_type*);
80  template<typename C> static char (&test(...))[2];
81  public:
82  static constexpr bool value = sizeof(test<T>(0)) == 1;
83 };
84 
85 }
86 
158 template <
159  template<typename U, typename V, typename... Args> class ObjectType = std::map,
160  template<typename U, typename... Args> class ArrayType = std::vector,
161  class StringType = std::string,
162  class BooleanType = bool,
163  class NumberIntegerType = int64_t,
164  class NumberUnsignedType = uint64_t,
165  class NumberFloatType = double,
166  template<typename U> class AllocatorType = std::allocator
167  >
169 {
170  private:
172  using basic_json_t = basic_json<ObjectType,
173  ArrayType,
174  StringType,
175  BooleanType,
176  NumberIntegerType,
177  NumberUnsignedType,
178  NumberFloatType,
179  AllocatorType>;
180 
181  public:
182 
184  // container types //
186 
189 
192 
196  using const_reference = const value_type&;
197 
199  using difference_type = std::ptrdiff_t;
201  using size_type = std::size_t;
202 
204  using allocator_type = AllocatorType<basic_json>;
205 
207  using pointer = typename std::allocator_traits<allocator_type>::pointer;
209  using const_pointer = typename std::allocator_traits<allocator_type>::const_pointer;
210 
211  // forward declaration
212  template<typename Base> class json_reverse_iterator;
213 
215  class iterator;
217  class const_iterator;
222 
224 
225 
230  {
231  return allocator_type();
232  }
233 
234 
236  // JSON value data types //
238 
241 
324  using object_t = ObjectType<StringType,
325  basic_json,
326  std::less<StringType>,
327  AllocatorType<std::pair<const StringType,
328  basic_json>>>;
329 
374  using array_t = ArrayType<basic_json, AllocatorType<basic_json>>;
375 
421  using string_t = StringType;
422 
447  using boolean_t = BooleanType;
448 
518  using number_integer_t = NumberIntegerType;
519 
590  using number_unsigned_t = NumberUnsignedType;
591 
658  using number_float_t = NumberFloatType;
659 
661 
662 
664  // JSON type enumeration //
666 
677  enum class value_t : uint8_t
678  {
679  null,
680  object,
681  array,
682  string,
683  boolean,
684  number_integer,
685  number_unsigned,
686  number_float,
687  discarded
688  };
689 
690 
691  private:
693  template<typename T, typename... Args>
694  static T* create(Args&& ... args)
695  {
696  AllocatorType<T> alloc;
697  auto deleter = [&](T * object)
698  {
699  alloc.deallocate(object, 1);
700  };
701  std::unique_ptr<T, decltype(deleter)> object(alloc.allocate(1), deleter);
702  alloc.construct(object.get(), std::forward<Args>(args)...);
703  return object.release();
704  }
705 
707  // JSON value storage //
709 
717  union json_value
718  {
720  object_t* object;
722  array_t* array;
724  string_t* string;
726  boolean_t boolean;
728  number_integer_t number_integer;
730  number_unsigned_t number_unsigned;
732  number_float_t number_float;
733 
735  json_value() noexcept = default;
737  json_value(boolean_t v) noexcept : boolean(v) {}
739  json_value(number_integer_t v) noexcept : number_integer(v) {}
741  json_value(number_unsigned_t v) noexcept : number_unsigned(v) {}
743  json_value(number_float_t v) noexcept : number_float(v) {}
745  json_value(value_t t)
746  {
747  switch (t)
748  {
749  case value_t::object:
750  {
751  object = create<object_t>();
752  break;
753  }
754 
755  case value_t::array:
756  {
757  array = create<array_t>();
758  break;
759  }
760 
761  case value_t::string:
762  {
763  string = create<string_t>("");
764  break;
765  }
766 
767  case value_t::boolean:
768  {
769  boolean = boolean_t(false);
770  break;
771  }
772 
773  case value_t::number_integer:
774  {
775  number_integer = number_integer_t(0);
776  break;
777  }
778 
779  case value_t::number_unsigned:
780  {
781  number_unsigned = number_unsigned_t(0);
782  break;
783  }
784 
785  case value_t::number_float:
786  {
787  number_float = number_float_t(0.0);
788  break;
789  }
790 
791  default:
792  {
793  break;
794  }
795  }
796  }
797 
799  json_value(const string_t& value)
800  {
801  string = create<string_t>(value);
802  }
803 
805  json_value(const object_t& value)
806  {
807  object = create<object_t>(value);
808  }
809 
811  json_value(const array_t& value)
812  {
813  array = create<array_t>(value);
814  }
815  };
816 
817 
818  public:
820  // JSON parser callback //
822 
831  enum class parse_event_t : uint8_t
832  {
834  object_start,
836  object_end,
838  array_start,
840  array_end,
842  key,
844  value
845  };
846 
896  using parser_callback_t = std::function<bool(int depth, parse_event_t event, basic_json& parsed)>;
897 
898 
900  // constructors //
902 
905 
946  : m_type(value_type), m_value(value_type)
947  {}
948 
970  basic_json() noexcept = default;
971 
991  basic_json(std::nullptr_t) noexcept
992  : basic_json(value_t::null)
993  {}
994 
1014  basic_json(const object_t& val)
1015  : m_type(value_t::object), m_value(val)
1016  {}
1017 
1044  template <class CompatibleObjectType, typename
1045  std::enable_if<
1046  std::is_constructible<typename object_t::key_type, typename CompatibleObjectType::key_type>::value and
1047  std::is_constructible<basic_json, typename CompatibleObjectType::mapped_type>::value, int>::type
1048  = 0>
1049  basic_json(const CompatibleObjectType& val)
1050  : m_type(value_t::object)
1051  {
1052  using std::begin;
1053  using std::end;
1054  m_value.object = create<object_t>(begin(val), end(val));
1055  }
1056 
1076  basic_json(const array_t& val)
1077  : m_type(value_t::array), m_value(val)
1078  {}
1079 
1106  template <class CompatibleArrayType, typename
1107  std::enable_if<
1108  not std::is_same<CompatibleArrayType, typename basic_json_t::iterator>::value and
1109  not std::is_same<CompatibleArrayType, typename basic_json_t::const_iterator>::value and
1110  not std::is_same<CompatibleArrayType, typename basic_json_t::reverse_iterator>::value and
1111  not std::is_same<CompatibleArrayType, typename basic_json_t::const_reverse_iterator>::value and
1112  not std::is_same<CompatibleArrayType, typename array_t::iterator>::value and
1113  not std::is_same<CompatibleArrayType, typename array_t::const_iterator>::value and
1114  std::is_constructible<basic_json, typename CompatibleArrayType::value_type>::value, int>::type
1115  = 0>
1116  basic_json(const CompatibleArrayType& val)
1117  : m_type(value_t::array)
1118  {
1119  using std::begin;
1120  using std::end;
1121  m_value.array = create<array_t>(begin(val), end(val));
1122  }
1123 
1145  basic_json(const string_t& val)
1146  : m_type(value_t::string), m_value(val)
1147  {}
1148 
1169  basic_json(const typename string_t::value_type* val)
1170  : basic_json(string_t(val))
1171  {}
1172 
1196  template <class CompatibleStringType, typename
1197  std::enable_if<
1198  std::is_constructible<string_t, CompatibleStringType>::value, int>::type
1199  = 0>
1200  basic_json(const CompatibleStringType& val)
1201  : basic_json(string_t(val))
1202  {}
1203 
1219  : m_type(value_t::boolean), m_value(val)
1220  {}
1221 
1245  template<typename T,
1246  typename std::enable_if<
1247  not (std::is_same<T, int>::value)
1248  and std::is_same<T, number_integer_t>::value
1249  , int>::type
1250  = 0>
1252  : m_type(value_t::number_integer), m_value(val)
1253  {}
1254 
1280  basic_json(const int val)
1281  : m_type(value_t::number_integer),
1282  m_value(static_cast<number_integer_t>(val))
1283  {}
1284 
1310  template<typename CompatibleNumberIntegerType, typename
1311  std::enable_if<
1312  std::is_constructible<number_integer_t, CompatibleNumberIntegerType>::value and
1313  std::numeric_limits<CompatibleNumberIntegerType>::is_integer and
1314  std::numeric_limits<CompatibleNumberIntegerType>::is_signed,
1315  CompatibleNumberIntegerType>::type
1316  = 0>
1317  basic_json(const CompatibleNumberIntegerType val) noexcept
1318  : m_type(value_t::number_integer),
1319  m_value(static_cast<number_integer_t>(val))
1320  {}
1321 
1339  template<typename T,
1340  typename std::enable_if<
1341  not (std::is_same<T, int>::value)
1342  and std::is_same<T, number_unsigned_t>::value
1343  , int>::type
1344  = 0>
1346  : m_type(value_t::number_unsigned), m_value(val)
1347  {}
1348 
1369  template < typename CompatibleNumberUnsignedType, typename
1370  std::enable_if <
1371  std::is_constructible<number_unsigned_t, CompatibleNumberUnsignedType>::value and
1372  std::numeric_limits<CompatibleNumberUnsignedType>::is_integer and
1373  !std::numeric_limits<CompatibleNumberUnsignedType>::is_signed,
1374  CompatibleNumberUnsignedType >::type
1375  = 0 >
1376  basic_json(const CompatibleNumberUnsignedType val) noexcept
1377  : m_type(value_t::number_unsigned),
1378  m_value(static_cast<number_unsigned_t>(val))
1379  {}
1380 
1406  : m_type(value_t::number_float), m_value(val)
1407  {
1408  // replace infinity and NAN by null
1409  if (not std::isfinite(val))
1410  {
1411  m_type = value_t::null;
1412  m_value = json_value();
1413  }
1414  }
1415 
1446  template<typename CompatibleNumberFloatType, typename = typename
1447  std::enable_if<
1448  std::is_constructible<number_float_t, CompatibleNumberFloatType>::value and
1449  std::is_floating_point<CompatibleNumberFloatType>::value>::type
1450  >
1451  basic_json(const CompatibleNumberFloatType val) noexcept
1452  : basic_json(number_float_t(val))
1453  {}
1454 
1524  basic_json(std::initializer_list<basic_json> init,
1525  bool type_deduction = true,
1526  value_t manual_type = value_t::array)
1527  {
1528  // the initializer list could describe an object
1529  bool is_an_object = true;
1530 
1531  // check if each element is an array with two elements whose first
1532  // element is a string
1533  for (const auto& element : init)
1534  {
1535  if (not element.is_array() or element.size() != 2
1536  or not element[0].is_string())
1537  {
1538  // we found an element that makes it impossible to use the
1539  // initializer list as object
1540  is_an_object = false;
1541  break;
1542  }
1543  }
1544 
1545  // adjust type if type deduction is not wanted
1546  if (not type_deduction)
1547  {
1548  // if array is wanted, do not create an object though possible
1549  if (manual_type == value_t::array)
1550  {
1551  is_an_object = false;
1552  }
1553 
1554  // if object is wanted but impossible, throw an exception
1555  if (manual_type == value_t::object and not is_an_object)
1556  {
1557  throw std::domain_error("cannot create object from initializer list");
1558  }
1559  }
1560 
1561  if (is_an_object)
1562  {
1563  // the initializer list is a list of pairs -> create object
1564  m_type = value_t::object;
1565  m_value = value_t::object;
1566 
1567  assert(m_value.object != nullptr);
1568 
1569  for (auto& element : init)
1570  {
1571  m_value.object->emplace(std::move(*(element[0].m_value.string)), std::move(element[1]));
1572  }
1573  }
1574  else
1575  {
1576  // the initializer list describes an array -> create array
1577  m_type = value_t::array;
1578  m_value.array = create<array_t>(std::move(init));
1579  }
1580  }
1581 
1616  static basic_json array(std::initializer_list<basic_json> init =
1617  std::initializer_list<basic_json>())
1618  {
1619  return basic_json(init, false, value_t::array);
1620  }
1621 
1656  static basic_json object(std::initializer_list<basic_json> init =
1657  std::initializer_list<basic_json>())
1658  {
1659  return basic_json(init, false, value_t::object);
1660  }
1661 
1680  basic_json(size_type cnt, const basic_json& val)
1681  : m_type(value_t::array)
1682  {
1683  m_value.array = create<array_t>(cnt, val);
1684  }
1685 
1720  template <class InputIT, typename
1721  std::enable_if<
1722  std::is_same<InputIT, typename basic_json_t::iterator>::value or
1723  std::is_same<InputIT, typename basic_json_t::const_iterator>::value
1724  , int>::type
1725  = 0>
1726  basic_json(InputIT first, InputIT last) : m_type(first.m_object->m_type)
1727  {
1728  // make sure iterator fits the current value
1729  if (first.m_object != last.m_object)
1730  {
1731  throw std::domain_error("iterators are not compatible");
1732  }
1733 
1734  // check if iterator range is complete for primitive values
1735  switch (m_type)
1736  {
1737  case value_t::boolean:
1738  case value_t::number_float:
1739  case value_t::number_integer:
1740  case value_t::number_unsigned:
1741  case value_t::string:
1742  {
1743  if (not first.m_it.primitive_iterator.is_begin() or not last.m_it.primitive_iterator.is_end())
1744  {
1745  throw std::out_of_range("iterators out of range");
1746  }
1747  break;
1748  }
1749 
1750  default:
1751  {
1752  break;
1753  }
1754  }
1755 
1756  switch (m_type)
1757  {
1758  case value_t::number_integer:
1759  {
1760  assert(first.m_object != nullptr);
1761  m_value.number_integer = first.m_object->m_value.number_integer;
1762  break;
1763  }
1764 
1765  case value_t::number_unsigned:
1766  {
1767  assert(first.m_object != nullptr);
1768  m_value.number_unsigned = first.m_object->m_value.number_unsigned;
1769  break;
1770  }
1771 
1772  case value_t::number_float:
1773  {
1774  assert(first.m_object != nullptr);
1775  m_value.number_float = first.m_object->m_value.number_float;
1776  break;
1777  }
1778 
1779  case value_t::boolean:
1780  {
1781  assert(first.m_object != nullptr);
1782  m_value.boolean = first.m_object->m_value.boolean;
1783  break;
1784  }
1785 
1786  case value_t::string:
1787  {
1788  assert(first.m_object != nullptr);
1789  m_value = *first.m_object->m_value.string;
1790  break;
1791  }
1792 
1793  case value_t::object:
1794  {
1795  m_value.object = create<object_t>(first.m_it.object_iterator, last.m_it.object_iterator);
1796  break;
1797  }
1798 
1799  case value_t::array:
1800  {
1801  m_value.array = create<array_t>(first.m_it.array_iterator, last.m_it.array_iterator);
1802  break;
1803  }
1804 
1805  default:
1806  {
1807  assert(first.m_object != nullptr);
1808  throw std::domain_error("cannot use construct with iterators from " + first.m_object->type_name());
1809  }
1810  }
1811  }
1812 
1833  explicit basic_json(std::istream& i, parser_callback_t cb = nullptr)
1834  {
1835  *this = parser(i, cb).parse();
1836  }
1837 
1839  // other constructors and destructor //
1841 
1864  basic_json(const basic_json& other)
1865  : m_type(other.m_type)
1866  {
1867  switch (m_type)
1868  {
1869  case value_t::object:
1870  {
1871  assert(other.m_value.object != nullptr);
1872  m_value = *other.m_value.object;
1873  break;
1874  }
1875 
1876  case value_t::array:
1877  {
1878  assert(other.m_value.array != nullptr);
1879  m_value = *other.m_value.array;
1880  break;
1881  }
1882 
1883  case value_t::string:
1884  {
1885  assert(other.m_value.string != nullptr);
1886  m_value = *other.m_value.string;
1887  break;
1888  }
1889 
1890  case value_t::boolean:
1891  {
1892  m_value = other.m_value.boolean;
1893  break;
1894  }
1895 
1896  case value_t::number_integer:
1897  {
1898  m_value = other.m_value.number_integer;
1899  break;
1900  }
1901 
1902  case value_t::number_unsigned:
1903  {
1904  m_value = other.m_value.number_unsigned;
1905  break;
1906  }
1907 
1908  case value_t::number_float:
1909  {
1910  m_value = other.m_value.number_float;
1911  break;
1912  }
1913 
1914  default:
1915  {
1916  break;
1917  }
1918  }
1919  }
1920 
1939  basic_json(basic_json&& other) noexcept
1940  : m_type(std::move(other.m_type)),
1941  m_value(std::move(other.m_value))
1942  {
1943  // invalidate payload
1944  other.m_type = value_t::null;
1945  other.m_value = {};
1946  }
1947 
1971  reference& operator=(basic_json other) noexcept (
1972  std::is_nothrow_move_constructible<value_t>::value and
1973  std::is_nothrow_move_assignable<value_t>::value and
1974  std::is_nothrow_move_constructible<json_value>::value and
1975  std::is_nothrow_move_assignable<json_value>::value
1976  )
1977  {
1978  using std::swap;
1979  swap(m_type, other.m_type);
1980  swap(m_value, other.m_value);
1981  return *this;
1982  }
1983 
2000  {
2001  switch (m_type)
2002  {
2003  case value_t::object:
2004  {
2005  AllocatorType<object_t> alloc;
2006  alloc.destroy(m_value.object);
2007  alloc.deallocate(m_value.object, 1);
2008  break;
2009  }
2010 
2011  case value_t::array:
2012  {
2013  AllocatorType<array_t> alloc;
2014  alloc.destroy(m_value.array);
2015  alloc.deallocate(m_value.array, 1);
2016  break;
2017  }
2018 
2019  case value_t::string:
2020  {
2021  AllocatorType<string_t> alloc;
2022  alloc.destroy(m_value.string);
2023  alloc.deallocate(m_value.string, 1);
2024  break;
2025  }
2026 
2027  default:
2028  {
2029  // all other types need no specific destructor
2030  break;
2031  }
2032  }
2033  }
2034 
2036 
2037  public:
2039  // object inspection //
2041 
2044 
2068  string_t dump(const int indent = -1) const
2069  {
2070  std::stringstream ss;
2071 
2072  if (indent >= 0)
2073  {
2074  dump(ss, true, static_cast<unsigned int>(indent));
2075  }
2076  else
2077  {
2078  dump(ss, false, 0);
2079  }
2080 
2081  return ss.str();
2082  }
2083 
2099  value_t type() const noexcept
2100  {
2101  return m_type;
2102  }
2103 
2126  bool is_primitive() const noexcept
2127  {
2128  return is_null() or is_string() or is_boolean() or is_number();
2129  }
2130 
2150  bool is_structured() const noexcept
2151  {
2152  return is_array() or is_object();
2153  }
2154 
2169  bool is_null() const noexcept
2170  {
2171  return m_type == value_t::null;
2172  }
2173 
2188  bool is_boolean() const noexcept
2189  {
2190  return m_type == value_t::boolean;
2191  }
2192 
2215  bool is_number() const noexcept
2216  {
2217  return is_number_integer() or is_number_float();
2218  }
2219 
2241  bool is_number_integer() const noexcept
2242  {
2243  return m_type == value_t::number_integer or m_type == value_t::number_unsigned;
2244  }
2245 
2266  bool is_number_unsigned() const noexcept
2267  {
2268  return m_type == value_t::number_unsigned;
2269  }
2270 
2291  bool is_number_float() const noexcept
2292  {
2293  return m_type == value_t::number_float;
2294  }
2295 
2310  bool is_object() const noexcept
2311  {
2312  return m_type == value_t::object;
2313  }
2314 
2329  bool is_array() const noexcept
2330  {
2331  return m_type == value_t::array;
2332  }
2333 
2348  bool is_string() const noexcept
2349  {
2350  return m_type == value_t::string;
2351  }
2352 
2372  bool is_discarded() const noexcept
2373  {
2374  return m_type == value_t::discarded;
2375  }
2376 
2392  operator value_t() const noexcept
2393  {
2394  return m_type;
2395  }
2396 
2398 
2399  private:
2401  // value access //
2403 
2405  template <class T, typename
2406  std::enable_if<
2407  std::is_convertible<typename object_t::key_type, typename T::key_type>::value and
2408  std::is_convertible<basic_json_t, typename T::mapped_type>::value
2409  , int>::type = 0>
2410  T get_impl(T*) const
2411  {
2412  if (is_object())
2413  {
2414  assert(m_value.object != nullptr);
2415  return T(m_value.object->begin(), m_value.object->end());
2416  }
2417  else
2418  {
2419  throw std::domain_error("type must be object, but is " + type_name());
2420  }
2421  }
2422 
2424  object_t get_impl(object_t*) const
2425  {
2426  if (is_object())
2427  {
2428  assert(m_value.object != nullptr);
2429  return *(m_value.object);
2430  }
2431  else
2432  {
2433  throw std::domain_error("type must be object, but is " + type_name());
2434  }
2435  }
2436 
2438  template <class T, typename
2439  std::enable_if<
2440  std::is_convertible<basic_json_t, typename T::value_type>::value and
2441  not std::is_same<basic_json_t, typename T::value_type>::value and
2442  not std::is_arithmetic<T>::value and
2443  not std::is_convertible<std::string, T>::value and
2444  not has_mapped_type<T>::value
2445  , int>::type = 0>
2446  T get_impl(T*) const
2447  {
2448  if (is_array())
2449  {
2450  T to_vector;
2451  assert(m_value.array != nullptr);
2452  std::transform(m_value.array->begin(), m_value.array->end(),
2453  std::inserter(to_vector, to_vector.end()), [](basic_json i)
2454  {
2455  return i.get<typename T::value_type>();
2456  });
2457  return to_vector;
2458  }
2459  else
2460  {
2461  throw std::domain_error("type must be array, but is " + type_name());
2462  }
2463  }
2464 
2466  template <class T, typename
2467  std::enable_if<
2468  std::is_convertible<basic_json_t, T>::value and
2469  not std::is_same<basic_json_t, T>::value
2470  , int>::type = 0>
2471  std::vector<T> get_impl(std::vector<T>*) const
2472  {
2473  if (is_array())
2474  {
2475  std::vector<T> to_vector;
2476  assert(m_value.array != nullptr);
2477  to_vector.reserve(m_value.array->size());
2478  std::transform(m_value.array->begin(), m_value.array->end(),
2479  std::inserter(to_vector, to_vector.end()), [](basic_json i)
2480  {
2481  return i.get<T>();
2482  });
2483  return to_vector;
2484  }
2485  else
2486  {
2487  throw std::domain_error("type must be array, but is " + type_name());
2488  }
2489  }
2490 
2492  template <class T, typename
2493  std::enable_if<
2494  std::is_same<basic_json, typename T::value_type>::value and
2495  not has_mapped_type<T>::value
2496  , int>::type = 0>
2497  T get_impl(T*) const
2498  {
2499  if (is_array())
2500  {
2501  assert(m_value.array != nullptr);
2502  return T(m_value.array->begin(), m_value.array->end());
2503  }
2504  else
2505  {
2506  throw std::domain_error("type must be array, but is " + type_name());
2507  }
2508  }
2509 
2511  array_t get_impl(array_t*) const
2512  {
2513  if (is_array())
2514  {
2515  assert(m_value.array != nullptr);
2516  return *(m_value.array);
2517  }
2518  else
2519  {
2520  throw std::domain_error("type must be array, but is " + type_name());
2521  }
2522  }
2523 
2525  template <typename T, typename
2526  std::enable_if<
2527  std::is_convertible<string_t, T>::value
2528  , int>::type = 0>
2529  T get_impl(T*) const
2530  {
2531  if (is_string())
2532  {
2533  assert(m_value.string != nullptr);
2534  return *m_value.string;
2535  }
2536  else
2537  {
2538  throw std::domain_error("type must be string, but is " + type_name());
2539  }
2540  }
2541 
2543  template<typename T, typename
2544  std::enable_if<
2545  std::is_arithmetic<T>::value
2546  , int>::type = 0>
2547  T get_impl(T*) const
2548  {
2549  switch (m_type)
2550  {
2551  case value_t::number_integer:
2552  {
2553  return static_cast<T>(m_value.number_integer);
2554  }
2555 
2556  case value_t::number_unsigned:
2557  {
2558  return static_cast<T>(m_value.number_unsigned);
2559  }
2560 
2561  case value_t::number_float:
2562  {
2563  return static_cast<T>(m_value.number_float);
2564  }
2565 
2566  default:
2567  {
2568  throw std::domain_error("type must be number, but is " + type_name());
2569  }
2570  }
2571  }
2572 
2574  boolean_t get_impl(boolean_t*) const
2575  {
2576  if (is_boolean())
2577  {
2578  return m_value.boolean;
2579  }
2580  else
2581  {
2582  throw std::domain_error("type must be boolean, but is " + type_name());
2583  }
2584  }
2585 
2587  object_t* get_impl_ptr(object_t*) noexcept
2588  {
2589  return is_object() ? m_value.object : nullptr;
2590  }
2591 
2593  const object_t* get_impl_ptr(const object_t*) const noexcept
2594  {
2595  return is_object() ? m_value.object : nullptr;
2596  }
2597 
2599  array_t* get_impl_ptr(array_t*) noexcept
2600  {
2601  return is_array() ? m_value.array : nullptr;
2602  }
2603 
2605  const array_t* get_impl_ptr(const array_t*) const noexcept
2606  {
2607  return is_array() ? m_value.array : nullptr;
2608  }
2609 
2611  string_t* get_impl_ptr(string_t*) noexcept
2612  {
2613  return is_string() ? m_value.string : nullptr;
2614  }
2615 
2617  const string_t* get_impl_ptr(const string_t*) const noexcept
2618  {
2619  return is_string() ? m_value.string : nullptr;
2620  }
2621 
2623  boolean_t* get_impl_ptr(boolean_t*) noexcept
2624  {
2625  return is_boolean() ? &m_value.boolean : nullptr;
2626  }
2627 
2629  const boolean_t* get_impl_ptr(const boolean_t*) const noexcept
2630  {
2631  return is_boolean() ? &m_value.boolean : nullptr;
2632  }
2633 
2635  number_integer_t* get_impl_ptr(number_integer_t*) noexcept
2636  {
2637  return is_number_integer() ? &m_value.number_integer : nullptr;
2638  }
2639 
2641  const number_integer_t* get_impl_ptr(const number_integer_t*) const noexcept
2642  {
2643  return is_number_integer() ? &m_value.number_integer : nullptr;
2644  }
2645 
2647  number_unsigned_t* get_impl_ptr(number_unsigned_t*) noexcept
2648  {
2649  return is_number_unsigned() ? &m_value.number_unsigned : nullptr;
2650  }
2651 
2653  const number_unsigned_t* get_impl_ptr(const number_unsigned_t*) const noexcept
2654  {
2655  return is_number_unsigned() ? &m_value.number_unsigned : nullptr;
2656  }
2657 
2659  number_float_t* get_impl_ptr(number_float_t*) noexcept
2660  {
2661  return is_number_float() ? &m_value.number_float : nullptr;
2662  }
2663 
2665  const number_float_t* get_impl_ptr(const number_float_t*) const noexcept
2666  {
2667  return is_number_float() ? &m_value.number_float : nullptr;
2668  }
2669 
2681  template<typename ReferenceType, typename ThisType>
2682  static ReferenceType get_ref_impl(ThisType& obj)
2683  {
2684  // delegate the call to get_ptr<>()
2685  using PointerType = typename std::add_pointer<ReferenceType>::type;
2686  auto ptr = obj.template get_ptr<PointerType>();
2687 
2688  if (ptr != nullptr)
2689  {
2690  return *ptr;
2691  }
2692  else
2693  {
2694  throw std::domain_error("incompatible ReferenceType for get_ref, actual type is " +
2695  obj.type_name());
2696  }
2697  }
2698 
2699  public:
2700 
2703 
2737  template<typename ValueType, typename
2738  std::enable_if<
2739  not std::is_pointer<ValueType>::value
2740  , int>::type = 0>
2741  ValueType get() const
2742  {
2743  return get_impl(static_cast<ValueType*>(nullptr));
2744  }
2745 
2772  template<typename PointerType, typename
2773  std::enable_if<
2774  std::is_pointer<PointerType>::value
2775  , int>::type = 0>
2776  PointerType get() noexcept
2777  {
2778  // delegate the call to get_ptr
2779  return get_ptr<PointerType>();
2780  }
2781 
2786  template<typename PointerType, typename
2787  std::enable_if<
2788  std::is_pointer<PointerType>::value
2789  , int>::type = 0>
2790  const PointerType get() const noexcept
2791  {
2792  // delegate the call to get_ptr
2793  return get_ptr<PointerType>();
2794  }
2795 
2821  template<typename PointerType, typename
2822  std::enable_if<
2823  std::is_pointer<PointerType>::value
2824  , int>::type = 0>
2825  PointerType get_ptr() noexcept
2826  {
2827  // delegate the call to get_impl_ptr<>()
2828  return get_impl_ptr(static_cast<PointerType>(nullptr));
2829  }
2830 
2835  template<typename PointerType, typename
2836  std::enable_if<
2837  std::is_pointer<PointerType>::value
2838  and std::is_const<typename std::remove_pointer<PointerType>::type>::value
2839  , int>::type = 0>
2840  const PointerType get_ptr() const noexcept
2841  {
2842  // delegate the call to get_impl_ptr<>() const
2843  return get_impl_ptr(static_cast<const PointerType>(nullptr));
2844  }
2845 
2872  template<typename ReferenceType, typename
2873  std::enable_if<
2874  std::is_reference<ReferenceType>::value
2875  , int>::type = 0>
2876  ReferenceType get_ref()
2877  {
2878  // delegate call to get_ref_impl
2879  return get_ref_impl<ReferenceType>(*this);
2880  }
2881 
2886  template<typename ReferenceType, typename
2887  std::enable_if<
2888  std::is_reference<ReferenceType>::value
2889  and std::is_const<typename std::remove_reference<ReferenceType>::type>::value
2890  , int>::type = 0>
2891  ReferenceType get_ref() const
2892  {
2893  // delegate call to get_ref_impl
2894  return get_ref_impl<ReferenceType>(*this);
2895  }
2896 
2925  template < typename ValueType, typename
2926  std::enable_if <
2927  not std::is_pointer<ValueType>::value
2928  and not std::is_same<ValueType, typename string_t::value_type>::value
2929 #ifndef _MSC_VER // Fix for issue #167 operator<< abiguity under VS2015
2930  and not std::is_same<ValueType, std::initializer_list<typename string_t::value_type>>::value
2931 #endif
2932  , int >::type = 0 >
2933  operator ValueType() const
2934  {
2935  // delegate the call to get<>() const
2936  return get<ValueType>();
2937  }
2938 
2940 
2941 
2943  // element access //
2945 
2948 
2972  {
2973  // at only works for arrays
2974  if (is_array())
2975  {
2976  try
2977  {
2978  assert(m_value.array != nullptr);
2979  return m_value.array->at(idx);
2980  }
2981  catch (std::out_of_range&)
2982  {
2983  // create better exception explanation
2984  throw std::out_of_range("array index " + std::to_string(idx) + " is out of range");
2985  }
2986  }
2987  else
2988  {
2989  throw std::domain_error("cannot use at() with " + type_name());
2990  }
2991  }
2992 
3016  {
3017  // at only works for arrays
3018  if (is_array())
3019  {
3020  try
3021  {
3022  assert(m_value.array != nullptr);
3023  return m_value.array->at(idx);
3024  }
3025  catch (std::out_of_range&)
3026  {
3027  // create better exception explanation
3028  throw std::out_of_range("array index " + std::to_string(idx) + " is out of range");
3029  }
3030  }
3031  else
3032  {
3033  throw std::domain_error("cannot use at() with " + type_name());
3034  }
3035  }
3036 
3063  reference at(const typename object_t::key_type& key)
3064  {
3065  // at only works for objects
3066  if (is_object())
3067  {
3068  try
3069  {
3070  assert(m_value.object != nullptr);
3071  return m_value.object->at(key);
3072  }
3073  catch (std::out_of_range&)
3074  {
3075  // create better exception explanation
3076  throw std::out_of_range("key '" + key + "' not found");
3077  }
3078  }
3079  else
3080  {
3081  throw std::domain_error("cannot use at() with " + type_name());
3082  }
3083  }
3084 
3111  const_reference at(const typename object_t::key_type& key) const
3112  {
3113  // at only works for objects
3114  if (is_object())
3115  {
3116  try
3117  {
3118  assert(m_value.object != nullptr);
3119  return m_value.object->at(key);
3120  }
3121  catch (std::out_of_range&)
3122  {
3123  // create better exception explanation
3124  throw std::out_of_range("key '" + key + "' not found");
3125  }
3126  }
3127  else
3128  {
3129  throw std::domain_error("cannot use at() with " + type_name());
3130  }
3131  }
3132 
3159  {
3160  // implicitly convert null value to an empty array
3161  if (is_null())
3162  {
3163  m_type = value_t::array;
3164  m_value.array = create<array_t>();
3165  }
3166 
3167  // operator[] only works for arrays
3168  if (is_array())
3169  {
3170  // fill up array with null values until given idx is reached
3171  assert(m_value.array != nullptr);
3172  for (size_t i = m_value.array->size(); i <= idx; ++i)
3173  {
3174  m_value.array->push_back(basic_json());
3175  }
3176 
3177  return m_value.array->operator[](idx);
3178  }
3179  else
3180  {
3181  throw std::domain_error("cannot use operator[] with " + type_name());
3182  }
3183  }
3184 
3205  {
3206  // const operator[] only works for arrays
3207  if (is_array())
3208  {
3209  assert(m_value.array != nullptr);
3210  return m_value.array->operator[](idx);
3211  }
3212  else
3213  {
3214  throw std::domain_error("cannot use operator[] with " + type_name());
3215  }
3216  }
3217 
3245  reference operator[](const typename object_t::key_type& key)
3246  {
3247  // implicitly convert null value to an empty object
3248  if (is_null())
3249  {
3250  m_type = value_t::object;
3251  m_value.object = create<object_t>();
3252  }
3253 
3254  // operator[] only works for objects
3255  if (is_object())
3256  {
3257  assert(m_value.object != nullptr);
3258  return m_value.object->operator[](key);
3259  }
3260  else
3261  {
3262  throw std::domain_error("cannot use operator[] with " + type_name());
3263  }
3264  }
3265 
3293  const_reference operator[](const typename object_t::key_type& key) const
3294  {
3295  // const operator[] only works for objects
3296  if (is_object())
3297  {
3298  assert(m_value.object != nullptr);
3299  assert(m_value.object->find(key) != m_value.object->end());
3300  return m_value.object->find(key)->second;
3301  }
3302  else
3303  {
3304  throw std::domain_error("cannot use operator[] with " + type_name());
3305  }
3306  }
3307 
3335  template<typename T, std::size_t n>
3336  reference operator[](T * (&key)[n])
3337  {
3338  return operator[](static_cast<const T>(key));
3339  }
3340 
3370  template<typename T, std::size_t n>
3371  const_reference operator[](T * (&key)[n]) const
3372  {
3373  return operator[](static_cast<const T>(key));
3374  }
3375 
3403  template<typename T>
3405  {
3406  // implicitly convert null to object
3407  if (is_null())
3408  {
3409  m_type = value_t::object;
3410  m_value = value_t::object;
3411  }
3412 
3413  // at only works for objects
3414  if (is_object())
3415  {
3416  assert(m_value.object != nullptr);
3417  return m_value.object->operator[](key);
3418  }
3419  else
3420  {
3421  throw std::domain_error("cannot use operator[] with " + type_name());
3422  }
3423  }
3424 
3452  template<typename T>
3454  {
3455  // at only works for objects
3456  if (is_object())
3457  {
3458  assert(m_value.object != nullptr);
3459  assert(m_value.object->find(key) != m_value.object->end());
3460  return m_value.object->find(key)->second;
3461  }
3462  else
3463  {
3464  throw std::domain_error("cannot use operator[] with " + type_name());
3465  }
3466  }
3467 
3516  template <class ValueType, typename
3517  std::enable_if<
3518  std::is_convertible<basic_json_t, ValueType>::value
3519  , int>::type = 0>
3520  ValueType value(const typename object_t::key_type& key, ValueType default_value) const
3521  {
3522  // at only works for objects
3523  if (is_object())
3524  {
3525  // if key is found, return value and given default value otherwise
3526  const auto it = find(key);
3527  if (it != end())
3528  {
3529  return *it;
3530  }
3531  else
3532  {
3533  return default_value;
3534  }
3535  }
3536  else
3537  {
3538  throw std::domain_error("cannot use value() with " + type_name());
3539  }
3540  }
3541 
3546  string_t value(const typename object_t::key_type& key, const char* default_value) const
3547  {
3548  return value(key, string_t(default_value));
3549  }
3550 
3576  {
3577  return *begin();
3578  }
3579 
3584  {
3585  return *cbegin();
3586  }
3587 
3618  {
3619  auto tmp = end();
3620  --tmp;
3621  return *tmp;
3622  }
3623 
3628  {
3629  auto tmp = cend();
3630  --tmp;
3631  return *tmp;
3632  }
3633 
3679  template <class InteratorType, typename
3680  std::enable_if<
3681  std::is_same<InteratorType, typename basic_json_t::iterator>::value or
3682  std::is_same<InteratorType, typename basic_json_t::const_iterator>::value
3683  , int>::type
3684  = 0>
3685  InteratorType erase(InteratorType pos)
3686  {
3687  // make sure iterator fits the current value
3688  if (this != pos.m_object)
3689  {
3690  throw std::domain_error("iterator does not fit current value");
3691  }
3692 
3693  InteratorType result = end();
3694 
3695  switch (m_type)
3696  {
3697  case value_t::boolean:
3698  case value_t::number_float:
3699  case value_t::number_integer:
3700  case value_t::number_unsigned:
3701  case value_t::string:
3702  {
3703  if (not pos.m_it.primitive_iterator.is_begin())
3704  {
3705  throw std::out_of_range("iterator out of range");
3706  }
3707 
3708  if (is_string())
3709  {
3710  delete m_value.string;
3711  m_value.string = nullptr;
3712  }
3713 
3714  m_type = value_t::null;
3715  break;
3716  }
3717 
3718  case value_t::object:
3719  {
3720  assert(m_value.object != nullptr);
3721  result.m_it.object_iterator = m_value.object->erase(pos.m_it.object_iterator);
3722  break;
3723  }
3724 
3725  case value_t::array:
3726  {
3727  assert(m_value.array != nullptr);
3728  result.m_it.array_iterator = m_value.array->erase(pos.m_it.array_iterator);
3729  break;
3730  }
3731 
3732  default:
3733  {
3734  throw std::domain_error("cannot use erase() with " + type_name());
3735  }
3736  }
3737 
3738  return result;
3739  }
3740 
3787  template <class InteratorType, typename
3788  std::enable_if<
3789  std::is_same<InteratorType, typename basic_json_t::iterator>::value or
3790  std::is_same<InteratorType, typename basic_json_t::const_iterator>::value
3791  , int>::type
3792  = 0>
3793  InteratorType erase(InteratorType first, InteratorType last)
3794  {
3795  // make sure iterator fits the current value
3796  if (this != first.m_object or this != last.m_object)
3797  {
3798  throw std::domain_error("iterators do not fit current value");
3799  }
3800 
3801  InteratorType result = end();
3802 
3803  switch (m_type)
3804  {
3805  case value_t::boolean:
3806  case value_t::number_float:
3807  case value_t::number_integer:
3808  case value_t::number_unsigned:
3809  case value_t::string:
3810  {
3811  if (not first.m_it.primitive_iterator.is_begin() or not last.m_it.primitive_iterator.is_end())
3812  {
3813  throw std::out_of_range("iterators out of range");
3814  }
3815 
3816  if (is_string())
3817  {
3818  delete m_value.string;
3819  m_value.string = nullptr;
3820  }
3821 
3822  m_type = value_t::null;
3823  break;
3824  }
3825 
3826  case value_t::object:
3827  {
3828  assert(m_value.object != nullptr);
3829  result.m_it.object_iterator = m_value.object->erase(first.m_it.object_iterator,
3830  last.m_it.object_iterator);
3831  break;
3832  }
3833 
3834  case value_t::array:
3835  {
3836  assert(m_value.array != nullptr);
3837  result.m_it.array_iterator = m_value.array->erase(first.m_it.array_iterator,
3838  last.m_it.array_iterator);
3839  break;
3840  }
3841 
3842  default:
3843  {
3844  throw std::domain_error("cannot use erase() with " + type_name());
3845  }
3846  }
3847 
3848  return result;
3849  }
3850 
3880  size_type erase(const typename object_t::key_type& key)
3881  {
3882  // this erase only works for objects
3883  if (is_object())
3884  {
3885  assert(m_value.object != nullptr);
3886  return m_value.object->erase(key);
3887  }
3888  else
3889  {
3890  throw std::domain_error("cannot use erase() with " + type_name());
3891  }
3892  }
3893 
3918  void erase(const size_type idx)
3919  {
3920  // this erase only works for arrays
3921  if (is_array())
3922  {
3923  if (idx >= size())
3924  {
3925  throw std::out_of_range("index out of range");
3926  }
3927 
3928  assert(m_value.array != nullptr);
3929  m_value.array->erase(m_value.array->begin() + static_cast<difference_type>(idx));
3930  }
3931  else
3932  {
3933  throw std::domain_error("cannot use erase() with " + type_name());
3934  }
3935  }
3936 
3938 
3939 
3941  // lookup //
3943 
3946 
3964  iterator find(typename object_t::key_type key)
3965  {
3966  auto result = end();
3967 
3968  if (is_object())
3969  {
3970  assert(m_value.object != nullptr);
3971  result.m_it.object_iterator = m_value.object->find(key);
3972  }
3973 
3974  return result;
3975  }
3976 
3981  const_iterator find(typename object_t::key_type key) const
3982  {
3983  auto result = cend();
3984 
3985  if (is_object())
3986  {
3987  assert(m_value.object != nullptr);
3988  result.m_it.object_iterator = m_value.object->find(key);
3989  }
3990 
3991  return result;
3992  }
3993 
4012  size_type count(typename object_t::key_type key) const
4013  {
4014  // return 0 for all nonobject types
4015  assert(not is_object() or m_value.object != nullptr);
4016  return is_object() ? m_value.object->count(key) : 0;
4017  }
4018 
4020 
4021 
4023  // iterators //
4025 
4028 
4054  {
4055  iterator result(this);
4056  result.set_begin();
4057  return result;
4058  }
4059 
4064  {
4065  return cbegin();
4066  }
4067 
4094  {
4095  const_iterator result(this);
4096  result.set_begin();
4097  return result;
4098  }
4099 
4125  {
4126  iterator result(this);
4127  result.set_end();
4128  return result;
4129  }
4130 
4135  {
4136  return cend();
4137  }
4138 
4165  {
4166  const_iterator result(this);
4167  result.set_end();
4168  return result;
4169  }
4170 
4195  {
4196  return reverse_iterator(end());
4197  }
4198 
4203  {
4204  return crbegin();
4205  }
4206 
4232  {
4233  return reverse_iterator(begin());
4234  }
4235 
4240  {
4241  return crend();
4242  }
4243 
4269  {
4270  return const_reverse_iterator(cend());
4271  }
4272 
4298  {
4299  return const_reverse_iterator(cbegin());
4300  }
4301 
4302  private:
4303  // forward declaration
4304  template<typename IteratorType> class iteration_proxy;
4305 
4306  public:
4318  static iteration_proxy<iterator> iterator_wrapper(reference cont)
4319  {
4320  return iteration_proxy<iterator>(cont);
4321  }
4322 
4326  static iteration_proxy<const_iterator> iterator_wrapper(const_reference cont)
4327  {
4328  return iteration_proxy<const_iterator>(cont);
4329  }
4330 
4332 
4333 
4335  // capacity //
4337 
4340 
4374  bool empty() const noexcept
4375  {
4376  switch (m_type)
4377  {
4378  case value_t::null:
4379  {
4380  // null values are empty
4381  return true;
4382  }
4383 
4384  case value_t::array:
4385  {
4386  assert(m_value.array != nullptr);
4387  return m_value.array->empty();
4388  }
4389 
4390  case value_t::object:
4391  {
4392  assert(m_value.object != nullptr);
4393  return m_value.object->empty();
4394  }
4395 
4396  default:
4397  {
4398  // all other types are nonempty
4399  return false;
4400  }
4401  }
4402  }
4403 
4437  size_type size() const noexcept
4438  {
4439  switch (m_type)
4440  {
4441  case value_t::null:
4442  {
4443  // null values are empty
4444  return 0;
4445  }
4446 
4447  case value_t::array:
4448  {
4449  assert(m_value.array != nullptr);
4450  return m_value.array->size();
4451  }
4452 
4453  case value_t::object:
4454  {
4455  assert(m_value.object != nullptr);
4456  return m_value.object->size();
4457  }
4458 
4459  default:
4460  {
4461  // all other types have size 1
4462  return 1;
4463  }
4464  }
4465  }
4466 
4503  size_type max_size() const noexcept
4504  {
4505  switch (m_type)
4506  {
4507  case value_t::array:
4508  {
4509  assert(m_value.array != nullptr);
4510  return m_value.array->max_size();
4511  }
4512 
4513  case value_t::object:
4514  {
4515  assert(m_value.object != nullptr);
4516  return m_value.object->max_size();
4517  }
4518 
4519  default:
4520  {
4521  // all other types have max_size() == size()
4522  return size();
4523  }
4524  }
4525  }
4526 
4528 
4529 
4531  // modifiers //
4533 
4536 
4562  void clear() noexcept
4563  {
4564  switch (m_type)
4565  {
4566  case value_t::number_integer:
4567  {
4568  m_value.number_integer = 0;
4569  break;
4570  }
4571 
4572  case value_t::number_unsigned:
4573  {
4574  m_value.number_unsigned = 0;
4575  break;
4576  }
4577 
4578  case value_t::number_float:
4579  {
4580  m_value.number_float = 0.0;
4581  break;
4582  }
4583 
4584  case value_t::boolean:
4585  {
4586  m_value.boolean = false;
4587  break;
4588  }
4589 
4590  case value_t::string:
4591  {
4592  assert(m_value.string != nullptr);
4593  m_value.string->clear();
4594  break;
4595  }
4596 
4597  case value_t::array:
4598  {
4599  assert(m_value.array != nullptr);
4600  m_value.array->clear();
4601  break;
4602  }
4603 
4604  case value_t::object:
4605  {
4606  assert(m_value.object != nullptr);
4607  m_value.object->clear();
4608  break;
4609  }
4610 
4611  default:
4612  {
4613  break;
4614  }
4615  }
4616  }
4617 
4638  void push_back(basic_json&& val)
4639  {
4640  // push_back only works for null objects or arrays
4641  if (not(is_null() or is_array()))
4642  {
4643  throw std::domain_error("cannot use push_back() with " + type_name());
4644  }
4645 
4646  // transform null object into an array
4647  if (is_null())
4648  {
4649  m_type = value_t::array;
4650  m_value = value_t::array;
4651  }
4652 
4653  // add element to array (move semantics)
4654  assert(m_value.array != nullptr);
4655  m_value.array->push_back(std::move(val));
4656  // invalidate object
4657  val.m_type = value_t::null;
4658  }
4659 
4664  reference operator+=(basic_json&& val)
4665  {
4666  push_back(std::move(val));
4667  return *this;
4668  }
4669 
4674  void push_back(const basic_json& val)
4675  {
4676  // push_back only works for null objects or arrays
4677  if (not(is_null() or is_array()))
4678  {
4679  throw std::domain_error("cannot use push_back() with " + type_name());
4680  }
4681 
4682  // transform null object into an array
4683  if (is_null())
4684  {
4685  m_type = value_t::array;
4686  m_value = value_t::array;
4687  }
4688 
4689  // add element to array
4690  assert(m_value.array != nullptr);
4691  m_value.array->push_back(val);
4692  }
4693 
4698  reference operator+=(const basic_json& val)
4699  {
4700  push_back(val);
4701  return *this;
4702  }
4703 
4724  void push_back(const typename object_t::value_type& val)
4725  {
4726  // push_back only works for null objects or objects
4727  if (not(is_null() or is_object()))
4728  {
4729  throw std::domain_error("cannot use push_back() with " + type_name());
4730  }
4731 
4732  // transform null object into an object
4733  if (is_null())
4734  {
4735  m_type = value_t::object;
4736  m_value = value_t::object;
4737  }
4738 
4739  // add element to array
4740  assert(m_value.object != nullptr);
4741  m_value.object->insert(val);
4742  }
4743 
4748  reference operator+=(const typename object_t::value_type& val)
4749  {
4750  push_back(val);
4751  return operator[](val.first);
4752  }
4753 
4776  iterator insert(const_iterator pos, const basic_json& val)
4777  {
4778  // insert only works for arrays
4779  if (is_array())
4780  {
4781  // check if iterator pos fits to this JSON value
4782  if (pos.m_object != this)
4783  {
4784  throw std::domain_error("iterator does not fit current value");
4785  }
4786 
4787  // insert to array and return iterator
4788  iterator result(this);
4789  assert(m_value.array != nullptr);
4790  result.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator, val);
4791  return result;
4792  }
4793  else
4794  {
4795  throw std::domain_error("cannot use insert() with " + type_name());
4796  }
4797  }
4798 
4803  iterator insert(const_iterator pos, basic_json&& val)
4804  {
4805  return insert(pos, val);
4806  }
4807 
4832  iterator insert(const_iterator pos, size_type cnt, const basic_json& val)
4833  {
4834  // insert only works for arrays
4835  if (is_array())
4836  {
4837  // check if iterator pos fits to this JSON value
4838  if (pos.m_object != this)
4839  {
4840  throw std::domain_error("iterator does not fit current value");
4841  }
4842 
4843  // insert to array and return iterator
4844  iterator result(this);
4845  assert(m_value.array != nullptr);
4846  result.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator, cnt, val);
4847  return result;
4848  }
4849  else
4850  {
4851  throw std::domain_error("cannot use insert() with " + type_name());
4852  }
4853  }
4854 
4886  {
4887  // insert only works for arrays
4888  if (not is_array())
4889  {
4890  throw std::domain_error("cannot use insert() with " + type_name());
4891  }
4892 
4893  // check if iterator pos fits to this JSON value
4894  if (pos.m_object != this)
4895  {
4896  throw std::domain_error("iterator does not fit current value");
4897  }
4898 
4899  if (first.m_object != last.m_object)
4900  {
4901  throw std::domain_error("iterators do not fit");
4902  }
4903 
4904  if (first.m_object == this or last.m_object == this)
4905  {
4906  throw std::domain_error("passed iterators may not belong to container");
4907  }
4908 
4909  // insert to array and return iterator
4910  iterator result(this);
4911  assert(m_value.array != nullptr);
4912  result.m_it.array_iterator = m_value.array->insert(
4913  pos.m_it.array_iterator,
4914  first.m_it.array_iterator,
4915  last.m_it.array_iterator);
4916  return result;
4917  }
4918 
4943  iterator insert(const_iterator pos, std::initializer_list<basic_json> ilist)
4944  {
4945  // insert only works for arrays
4946  if (not is_array())
4947  {
4948  throw std::domain_error("cannot use insert() with " + type_name());
4949  }
4950 
4951  // check if iterator pos fits to this JSON value
4952  if (pos.m_object != this)
4953  {
4954  throw std::domain_error("iterator does not fit current value");
4955  }
4956 
4957  // insert to array and return iterator
4958  iterator result(this);
4959  assert(m_value.array != nullptr);
4960  result.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator, ilist);
4961  return result;
4962  }
4963 
4981  void swap(reference other) noexcept (
4982  std::is_nothrow_move_constructible<value_t>::value and
4983  std::is_nothrow_move_assignable<value_t>::value and
4984  std::is_nothrow_move_constructible<json_value>::value and
4985  std::is_nothrow_move_assignable<json_value>::value
4986  )
4987  {
4988  std::swap(m_type, other.m_type);
4989  std::swap(m_value, other.m_value);
4990  }
4991 
5012  void swap(array_t& other)
5013  {
5014  // swap only works for arrays
5015  if (is_array())
5016  {
5017  assert(m_value.array != nullptr);
5018  std::swap(*(m_value.array), other);
5019  }
5020  else
5021  {
5022  throw std::domain_error("cannot use swap() with " + type_name());
5023  }
5024  }
5025 
5046  void swap(object_t& other)
5047  {
5048  // swap only works for objects
5049  if (is_object())
5050  {
5051  assert(m_value.object != nullptr);
5052  std::swap(*(m_value.object), other);
5053  }
5054  else
5055  {
5056  throw std::domain_error("cannot use swap() with " + type_name());
5057  }
5058  }
5059 
5080  void swap(string_t& other)
5081  {
5082  // swap only works for strings
5083  if (is_string())
5084  {
5085  assert(m_value.string != nullptr);
5086  std::swap(*(m_value.string), other);
5087  }
5088  else
5089  {
5090  throw std::domain_error("cannot use swap() with " + type_name());
5091  }
5092  }
5093 
5095 
5096 
5098  // lexicographical comparison operators //
5100 
5103 
5104  private:
5114  friend bool operator<(const value_t lhs, const value_t rhs)
5115  {
5116  static constexpr std::array<uint8_t, 8> order = {{
5117  0, // null
5118  3, // object
5119  4, // array
5120  5, // string
5121  1, // boolean
5122  2, // integer
5123  2, // unsigned
5124  2, // float
5125  }
5126  };
5127 
5128  // discarded values are not comparable
5129  if (lhs == value_t::discarded or rhs == value_t::discarded)
5130  {
5131  return false;
5132  }
5133 
5134  return order[static_cast<std::size_t>(lhs)] < order[static_cast<std::size_t>(rhs)];
5135  }
5136 
5137  public:
5161  friend bool operator==(const_reference lhs, const_reference rhs) noexcept
5162  {
5163  const auto lhs_type = lhs.type();
5164  const auto rhs_type = rhs.type();
5165 
5166  if (lhs_type == rhs_type)
5167  {
5168  switch (lhs_type)
5169  {
5170  case value_t::array:
5171  {
5172  assert(lhs.m_value.array != nullptr);
5173  assert(rhs.m_value.array != nullptr);
5174  return *lhs.m_value.array == *rhs.m_value.array;
5175  }
5176  case value_t::object:
5177  {
5178  assert(lhs.m_value.object != nullptr);
5179  assert(rhs.m_value.object != nullptr);
5180  return *lhs.m_value.object == *rhs.m_value.object;
5181  }
5182  case value_t::null:
5183  {
5184  return true;
5185  }
5186  case value_t::string:
5187  {
5188  assert(lhs.m_value.string != nullptr);
5189  assert(rhs.m_value.string != nullptr);
5190  return *lhs.m_value.string == *rhs.m_value.string;
5191  }
5192  case value_t::boolean:
5193  {
5194  return lhs.m_value.boolean == rhs.m_value.boolean;
5195  }
5196  case value_t::number_integer:
5197  {
5198  return lhs.m_value.number_integer == rhs.m_value.number_integer;
5199  }
5200  case value_t::number_unsigned:
5201  {
5202  return lhs.m_value.number_unsigned == rhs.m_value.number_unsigned;
5203  }
5204  case value_t::number_float:
5205  {
5206  return lhs.m_value.number_float == rhs.m_value.number_float;
5207  }
5208  default:
5209  {
5210  return false;
5211  }
5212  }
5213  }
5214  else if (lhs_type == value_t::number_integer and rhs_type == value_t::number_float)
5215  {
5216  return static_cast<number_float_t>(lhs.m_value.number_integer) == rhs.m_value.number_float;
5217  }
5218  else if (lhs_type == value_t::number_float and rhs_type == value_t::number_integer)
5219  {
5220  return lhs.m_value.number_float == static_cast<number_float_t>(rhs.m_value.number_integer);
5221  }
5222  else if (lhs_type == value_t::number_unsigned and rhs_type == value_t::number_float)
5223  {
5224  return static_cast<number_float_t>(lhs.m_value.number_unsigned) == rhs.m_value.number_float;
5225  }
5226  else if (lhs_type == value_t::number_float and rhs_type == value_t::number_unsigned)
5227  {
5228  return lhs.m_value.number_float == static_cast<number_float_t>(rhs.m_value.number_unsigned);
5229  }
5230  else if (lhs_type == value_t::number_unsigned and rhs_type == value_t::number_integer)
5231  {
5232  return static_cast<number_integer_t>(lhs.m_value.number_unsigned) == rhs.m_value.number_integer;
5233  }
5234  else if (lhs_type == value_t::number_integer and rhs_type == value_t::number_unsigned)
5235  {
5236  return lhs.m_value.number_integer == static_cast<number_integer_t>(rhs.m_value.number_unsigned);
5237  }
5238 
5239  return false;
5240  }
5241 
5260  friend bool operator==(const_reference v, std::nullptr_t) noexcept
5261  {
5262  return v.is_null();
5263  }
5264 
5269  friend bool operator==(std::nullptr_t, const_reference v) noexcept
5270  {
5271  return v.is_null();
5272  }
5273 
5290  friend bool operator!=(const_reference lhs, const_reference rhs) noexcept
5291  {
5292  return not (lhs == rhs);
5293  }
5294 
5313  friend bool operator!=(const_reference v, std::nullptr_t) noexcept
5314  {
5315  return not v.is_null();
5316  }
5317 
5322  friend bool operator!=(std::nullptr_t, const_reference v) noexcept
5323  {
5324  return not v.is_null();
5325  }
5326 
5351  friend bool operator<(const_reference lhs, const_reference rhs) noexcept
5352  {
5353  const auto lhs_type = lhs.type();
5354  const auto rhs_type = rhs.type();
5355 
5356  if (lhs_type == rhs_type)
5357  {
5358  switch (lhs_type)
5359  {
5360  case value_t::array:
5361  {
5362  assert(lhs.m_value.array != nullptr);
5363  assert(rhs.m_value.array != nullptr);
5364  return *lhs.m_value.array < *rhs.m_value.array;
5365  }
5366  case value_t::object:
5367  {
5368  assert(lhs.m_value.object != nullptr);
5369  assert(rhs.m_value.object != nullptr);
5370  return *lhs.m_value.object < *rhs.m_value.object;
5371  }
5372  case value_t::null:
5373  {
5374  return false;
5375  }
5376  case value_t::string:
5377  {
5378  assert(lhs.m_value.string != nullptr);
5379  assert(rhs.m_value.string != nullptr);
5380  return *lhs.m_value.string < *rhs.m_value.string;
5381  }
5382  case value_t::boolean:
5383  {
5384  return lhs.m_value.boolean < rhs.m_value.boolean;
5385  }
5386  case value_t::number_integer:
5387  {
5388  return lhs.m_value.number_integer < rhs.m_value.number_integer;
5389  }
5390  case value_t::number_unsigned:
5391  {
5392  return lhs.m_value.number_unsigned < rhs.m_value.number_unsigned;
5393  }
5394  case value_t::number_float:
5395  {
5396  return lhs.m_value.number_float < rhs.m_value.number_float;
5397  }
5398  default:
5399  {
5400  return false;
5401  }
5402  }
5403  }
5404  else if (lhs_type == value_t::number_integer and rhs_type == value_t::number_float)
5405  {
5406  return static_cast<number_float_t>(lhs.m_value.number_integer) < rhs.m_value.number_float;
5407  }
5408  else if (lhs_type == value_t::number_float and rhs_type == value_t::number_integer)
5409  {
5410  return lhs.m_value.number_float < static_cast<number_float_t>(rhs.m_value.number_integer);
5411  }
5412  else if (lhs_type == value_t::number_unsigned and rhs_type == value_t::number_float)
5413  {
5414  return static_cast<number_float_t>(lhs.m_value.number_unsigned) < rhs.m_value.number_float;
5415  }
5416  else if (lhs_type == value_t::number_float and rhs_type == value_t::number_unsigned)
5417  {
5418  return lhs.m_value.number_float < static_cast<number_float_t>(rhs.m_value.number_unsigned);
5419  }
5420  else if (lhs_type == value_t::number_integer and rhs_type == value_t::number_unsigned)
5421  {
5422  return lhs.m_value.number_integer < static_cast<number_integer_t>(rhs.m_value.number_unsigned);
5423  }
5424  else if (lhs_type == value_t::number_unsigned and rhs_type == value_t::number_integer)
5425  {
5426  return static_cast<number_integer_t>(lhs.m_value.number_unsigned) < rhs.m_value.number_integer;
5427  }
5428 
5429  // We only reach this line if we cannot compare values. In that case,
5430  // we compare types. Note we have to call the operator explicitly,
5431  // because MSVC has problems otherwise.
5432  return operator<(lhs_type, rhs_type);
5433  }
5434 
5452  friend bool operator<=(const_reference lhs, const_reference rhs) noexcept
5453  {
5454  return not (rhs < lhs);
5455  }
5456 
5474  friend bool operator>(const_reference lhs, const_reference rhs) noexcept
5475  {
5476  return not (lhs <= rhs);
5477  }
5478 
5496  friend bool operator>=(const_reference lhs, const_reference rhs) noexcept
5497  {
5498  return not (lhs < rhs);
5499  }
5500 
5502 
5503 
5505  // serialization //
5507 
5510 
5533  friend std::ostream& operator<<(std::ostream& o, const basic_json& j)
5534  {
5535  // read width member and use it as indentation parameter if nonzero
5536  const bool pretty_print = (o.width() > 0);
5537  const auto indentation = (pretty_print ? o.width() : 0);
5538 
5539  // reset width to 0 for subsequent calls to this stream
5540  o.width(0);
5541 
5542  // do the actual serialization
5543  j.dump(o, pretty_print, static_cast<unsigned int>(indentation));
5544  return o;
5545  }
5546 
5551  friend std::ostream& operator>>(const basic_json& j, std::ostream& o)
5552  {
5553  return o << j;
5554  }
5555 
5557 
5558 
5560  // deserialization //
5562 
5565 
5590  static basic_json parse(const string_t& s, parser_callback_t cb = nullptr)
5591  {
5592  return parser(s, cb).parse();
5593  }
5594 
5619  static basic_json parse(std::istream& i, parser_callback_t cb = nullptr)
5620  {
5621  return parser(i, cb).parse();
5622  }
5623 
5627  static basic_json parse(std::istream&& i, parser_callback_t cb = nullptr)
5628  {
5629  return parser(i, cb).parse();
5630  }
5631 
5655  friend std::istream& operator<<(basic_json& j, std::istream& i)
5656  {
5657  j = parser(i).parse();
5658  return i;
5659  }
5660 
5665  friend std::istream& operator>>(std::istream& i, basic_json& j)
5666  {
5667  j = parser(i).parse();
5668  return i;
5669  }
5670 
5672 
5673 
5674  private:
5676  // convenience functions //
5678 
5680  string_t type_name() const
5681  {
5682  switch (m_type)
5683  {
5684  case value_t::null:
5685  return "null";
5686  case value_t::object:
5687  return "object";
5688  case value_t::array:
5689  return "array";
5690  case value_t::string:
5691  return "string";
5692  case value_t::boolean:
5693  return "boolean";
5694  case value_t::discarded:
5695  return "discarded";
5696  default:
5697  return "number";
5698  }
5699  }
5700 
5709  static std::size_t extra_space(const string_t& s) noexcept
5710  {
5711  std::size_t result = 0;
5712 
5713  for (const auto& c : s)
5714  {
5715  switch (c)
5716  {
5717  case '"':
5718  case '\\':
5719  case '\b':
5720  case '\f':
5721  case '\n':
5722  case '\r':
5723  case '\t':
5724  {
5725  // from c (1 byte) to \x (2 bytes)
5726  result += 1;
5727  break;
5728  }
5729 
5730  default:
5731  {
5732  if (c >= 0x00 and c <= 0x1f)
5733  {
5734  // from c (1 byte) to \uxxxx (6 bytes)
5735  result += 5;
5736  }
5737  break;
5738  }
5739  }
5740  }
5741 
5742  return result;
5743  }
5744 
5758  static string_t escape_string(const string_t& s) noexcept
5759  {
5760  const auto space = extra_space(s);
5761  if (space == 0)
5762  {
5763  return s;
5764  }
5765 
5766  // create a result string of necessary size
5767  string_t result(s.size() + space, '\\');
5768  std::size_t pos = 0;
5769 
5770  for (const auto& c : s)
5771  {
5772  switch (c)
5773  {
5774  // quotation mark (0x22)
5775  case '"':
5776  {
5777  result[pos + 1] = '"';
5778  pos += 2;
5779  break;
5780  }
5781 
5782  // reverse solidus (0x5c)
5783  case '\\':
5784  {
5785  // nothing to change
5786  pos += 2;
5787  break;
5788  }
5789 
5790  // backspace (0x08)
5791  case '\b':
5792  {
5793  result[pos + 1] = 'b';
5794  pos += 2;
5795  break;
5796  }
5797 
5798  // formfeed (0x0c)
5799  case '\f':
5800  {
5801  result[pos + 1] = 'f';
5802  pos += 2;
5803  break;
5804  }
5805 
5806  // newline (0x0a)
5807  case '\n':
5808  {
5809  result[pos + 1] = 'n';
5810  pos += 2;
5811  break;
5812  }
5813 
5814  // carriage return (0x0d)
5815  case '\r':
5816  {
5817  result[pos + 1] = 'r';
5818  pos += 2;
5819  break;
5820  }
5821 
5822  // horizontal tab (0x09)
5823  case '\t':
5824  {
5825  result[pos + 1] = 't';
5826  pos += 2;
5827  break;
5828  }
5829 
5830  default:
5831  {
5832  if (c >= 0x00 and c <= 0x1f)
5833  {
5834  // convert a number 0..15 to its hex representation
5835  // (0..f)
5836  auto hexify = [](const char v) -> char
5837  {
5838  return (v < 10) ? ('0' + v) : ('a' + v - 10);
5839  };
5840 
5841  // print character c as \uxxxx
5842  for (const char m :
5843  { 'u', '0', '0', hexify(c >> 4), hexify(c & 0x0f)
5844  })
5845  {
5846  result[++pos] = m;
5847  }
5848 
5849  ++pos;
5850  }
5851  else
5852  {
5853  // all other characters are added as-is
5854  result[pos++] = c;
5855  }
5856  break;
5857  }
5858  }
5859  }
5860 
5861  return result;
5862  }
5863 
5881  void dump(std::ostream& o,
5882  const bool pretty_print,
5883  const unsigned int indent_step,
5884  const unsigned int current_indent = 0) const
5885  {
5886  // variable to hold indentation for recursive calls
5887  unsigned int new_indent = current_indent;
5888 
5889  switch (m_type)
5890  {
5891  case value_t::object:
5892  {
5893  assert(m_value.object != nullptr);
5894 
5895  if (m_value.object->empty())
5896  {
5897  o << "{}";
5898  return;
5899  }
5900 
5901  o << "{";
5902 
5903  // increase indentation
5904  if (pretty_print)
5905  {
5906  new_indent += indent_step;
5907  o << "\n";
5908  }
5909 
5910  for (auto i = m_value.object->cbegin(); i != m_value.object->cend(); ++i)
5911  {
5912  if (i != m_value.object->cbegin())
5913  {
5914  o << (pretty_print ? ",\n" : ",");
5915  }
5916  o << string_t(new_indent, ' ') << "\""
5917  << escape_string(i->first) << "\":"
5918  << (pretty_print ? " " : "");
5919  i->second.dump(o, pretty_print, indent_step, new_indent);
5920  }
5921 
5922  // decrease indentation
5923  if (pretty_print)
5924  {
5925  new_indent -= indent_step;
5926  o << "\n";
5927  }
5928 
5929  o << string_t(new_indent, ' ') + "}";
5930  return;
5931  }
5932 
5933  case value_t::array:
5934  {
5935  assert(m_value.array != nullptr);
5936 
5937  if (m_value.array->empty())
5938  {
5939  o << "[]";
5940  return;
5941  }
5942 
5943  o << "[";
5944 
5945  // increase indentation
5946  if (pretty_print)
5947  {
5948  new_indent += indent_step;
5949  o << "\n";
5950  }
5951 
5952  for (auto i = m_value.array->cbegin(); i != m_value.array->cend(); ++i)
5953  {
5954  if (i != m_value.array->cbegin())
5955  {
5956  o << (pretty_print ? ",\n" : ",");
5957  }
5958  o << string_t(new_indent, ' ');
5959  i->dump(o, pretty_print, indent_step, new_indent);
5960  }
5961 
5962  // decrease indentation
5963  if (pretty_print)
5964  {
5965  new_indent -= indent_step;
5966  o << "\n";
5967  }
5968 
5969  o << string_t(new_indent, ' ') << "]";
5970  return;
5971  }
5972 
5973  case value_t::string:
5974  {
5975  assert(m_value.string != nullptr);
5976  o << string_t("\"") << escape_string(*m_value.string) << "\"";
5977  return;
5978  }
5979 
5980  case value_t::boolean:
5981  {
5982  o << (m_value.boolean ? "true" : "false");
5983  return;
5984  }
5985 
5986  case value_t::number_integer:
5987  {
5988  o << m_value.number_integer;
5989  return;
5990  }
5991 
5992  case value_t::number_unsigned:
5993  {
5994  o << m_value.number_unsigned;
5995  return;
5996  }
5997 
5998  case value_t::number_float:
5999  {
6000  // If the number is an integer then output as a fixed with with
6001  // precision 1 to output "0.0", "1.0" etc as expected for some
6002  // round trip tests otherwise 15 digits of precision allows
6003  // round-trip IEEE 754 string->double->string; to be safe, we
6004  // read this value from
6005  // std::numeric_limits<number_float_t>::digits10
6006  if (std::fmod(m_value.number_float, 1) == 0)
6007  {
6008  o << std::fixed << std::setprecision(1);
6009  }
6010  else
6011  {
6012  // std::defaultfloat not supported in gcc version < 5
6013  o.unsetf(std::ios_base::floatfield);
6014  o << std::setprecision(std::numeric_limits<double>::digits10);
6015  }
6016  o << m_value.number_float;
6017  return;
6018  }
6019 
6020  case value_t::discarded:
6021  {
6022  o << "<discarded>";
6023  return;
6024  }
6025 
6026  case value_t::null:
6027  {
6028  o << "null";
6029  return;
6030  }
6031  }
6032  }
6033 
6034  private:
6036  // member variables //
6038 
6040  value_t m_type = value_t::null;
6041 
6043  json_value m_value = {};
6044 
6045 
6046  private:
6048  // iterators //
6050 
6060  class primitive_iterator_t
6061  {
6062  public:
6064  void set_begin()
6065  {
6066  m_it = begin_value;
6067  }
6068 
6070  void set_end()
6071  {
6072  m_it = end_value;
6073  }
6074 
6076  bool is_begin() const
6077  {
6078  return (m_it == begin_value);
6079  }
6080 
6082  bool is_end() const
6083  {
6084  return (m_it == end_value);
6085  }
6086 
6088  operator difference_type& ()
6089  {
6090  return m_it;
6091  }
6092 
6094  operator difference_type () const
6095  {
6096  return m_it;
6097  }
6098 
6099  private:
6100  static constexpr difference_type begin_value = 0;
6101  static constexpr difference_type end_value = begin_value + 1;
6102 
6104  difference_type m_it = std::numeric_limits<std::ptrdiff_t>::denorm_min();
6105  };
6106 
6114  struct internal_iterator
6115  {
6117  typename object_t::iterator object_iterator;
6119  typename array_t::iterator array_iterator;
6121  primitive_iterator_t primitive_iterator;
6122 
6124  internal_iterator()
6125  : object_iterator(), array_iterator(), primitive_iterator()
6126  {}
6127  };
6128 
6130  template<typename IteratorType>
6131  class iteration_proxy
6132  {
6133  private:
6135  class iteration_proxy_internal
6136  {
6137  private:
6139  IteratorType anchor;
6141  size_t array_index = 0;
6142 
6143  public:
6144  iteration_proxy_internal(IteratorType it)
6145  : anchor(it)
6146  {}
6147 
6149  iteration_proxy_internal& operator*()
6150  {
6151  return *this;
6152  }
6153 
6155  iteration_proxy_internal& operator++()
6156  {
6157  ++anchor;
6158  ++array_index;
6159 
6160  return *this;
6161  }
6162 
6164  bool operator!= (const iteration_proxy_internal& o) const
6165  {
6166  return anchor != o.anchor;
6167  }
6168 
6170  typename basic_json::string_t key() const
6171  {
6172  assert(anchor.m_object != nullptr);
6173 
6174  switch (anchor.m_object->type())
6175  {
6176  // use integer array index as key
6177  case value_t::array:
6178  {
6179  return std::to_string(array_index);
6180  }
6181 
6182  // use key from the object
6183  case value_t::object:
6184  {
6185  return anchor.key();
6186  }
6187 
6188  // use an empty key for all primitive types
6189  default:
6190  {
6191  return "";
6192  }
6193  }
6194  }
6195 
6197  typename IteratorType::reference value() const
6198  {
6199  return anchor.value();
6200  }
6201  };
6202 
6204  typename IteratorType::reference container;
6205 
6206  public:
6208  iteration_proxy(typename IteratorType::reference cont)
6209  : container(cont)
6210  {}
6211 
6213  iteration_proxy_internal begin()
6214  {
6215  return iteration_proxy_internal(container.begin());
6216  }
6217 
6219  iteration_proxy_internal end()
6220  {
6221  return iteration_proxy_internal(container.end());
6222  }
6223  };
6224 
6225  public:
6239  class const_iterator : public std::iterator<std::random_access_iterator_tag, const basic_json>
6240  {
6242  friend class basic_json;
6243 
6244  public:
6254  using iterator_category = std::bidirectional_iterator_tag;
6255 
6257  const_iterator() = default;
6258 
6260  const_iterator(pointer object) : m_object(object)
6261  {
6262  assert(m_object != nullptr);
6263 
6264  switch (m_object->m_type)
6265  {
6267  {
6268  m_it.object_iterator = typename object_t::iterator();
6269  break;
6270  }
6271 
6273  {
6274  m_it.array_iterator = typename array_t::iterator();
6275  break;
6276  }
6277 
6278  default:
6279  {
6280  m_it.primitive_iterator = primitive_iterator_t();
6281  break;
6282  }
6283  }
6284  }
6285 
6287  const_iterator(const iterator& other) : m_object(other.m_object)
6288  {
6289  assert(m_object != nullptr);
6290 
6291  switch (m_object->m_type)
6292  {
6294  {
6295  m_it.object_iterator = other.m_it.object_iterator;
6296  break;
6297  }
6298 
6300  {
6301  m_it.array_iterator = other.m_it.array_iterator;
6302  break;
6303  }
6304 
6305  default:
6306  {
6307  m_it.primitive_iterator = other.m_it.primitive_iterator;
6308  break;
6309  }
6310  }
6311  }
6312 
6314  const_iterator(const const_iterator& other) noexcept
6315  : m_object(other.m_object), m_it(other.m_it)
6316  {}
6317 
6320  std::is_nothrow_move_constructible<pointer>::value and
6321  std::is_nothrow_move_assignable<pointer>::value and
6322  std::is_nothrow_move_constructible<internal_iterator>::value and
6323  std::is_nothrow_move_assignable<internal_iterator>::value
6324  )
6325  {
6326  std::swap(m_object, other.m_object);
6327  std::swap(m_it, other.m_it);
6328  return *this;
6329  }
6330 
6331  private:
6333  void set_begin()
6334  {
6335  assert(m_object != nullptr);
6336 
6337  switch (m_object->m_type)
6338  {
6340  {
6341  assert(m_object->m_value.object != nullptr);
6342  m_it.object_iterator = m_object->m_value.object->begin();
6343  break;
6344  }
6345 
6347  {
6348  assert(m_object->m_value.array != nullptr);
6349  m_it.array_iterator = m_object->m_value.array->begin();
6350  break;
6351  }
6352 
6354  {
6355  // set to end so begin()==end() is true: null is empty
6356  m_it.primitive_iterator.set_end();
6357  break;
6358  }
6359 
6360  default:
6361  {
6362  m_it.primitive_iterator.set_begin();
6363  break;
6364  }
6365  }
6366  }
6367 
6369  void set_end()
6370  {
6371  assert(m_object != nullptr);
6372 
6373  switch (m_object->m_type)
6374  {
6376  {
6377  assert(m_object->m_value.object != nullptr);
6378  m_it.object_iterator = m_object->m_value.object->end();
6379  break;
6380  }
6381 
6383  {
6384  assert(m_object->m_value.array != nullptr);
6385  m_it.array_iterator = m_object->m_value.array->end();
6386  break;
6387  }
6388 
6389  default:
6390  {
6391  m_it.primitive_iterator.set_end();
6392  break;
6393  }
6394  }
6395  }
6396 
6397  public:
6400  {
6401  assert(m_object != nullptr);
6402 
6403  switch (m_object->m_type)
6404  {
6406  {
6407  assert(m_object->m_value.object);
6408  assert(m_it.object_iterator != m_object->m_value.object->end());
6409  return m_it.object_iterator->second;
6410  }
6411 
6413  {
6414  assert(m_object->m_value.array);
6415  assert(m_it.array_iterator != m_object->m_value.array->end());
6416  return *m_it.array_iterator;
6417  }
6418 
6420  {
6421  throw std::out_of_range("cannot get value");
6422  }
6423 
6424  default:
6425  {
6426  if (m_it.primitive_iterator.is_begin())
6427  {
6428  return *m_object;
6429  }
6430  else
6431  {
6432  throw std::out_of_range("cannot get value");
6433  }
6434  }
6435  }
6436  }
6437 
6440  {
6441  assert(m_object != nullptr);
6442 
6443  switch (m_object->m_type)
6444  {
6446  {
6447  assert(m_object->m_value.object);
6448  assert(m_it.object_iterator != m_object->m_value.object->end());
6449  return &(m_it.object_iterator->second);
6450  }
6451 
6453  {
6454  assert(m_object->m_value.array);
6455  assert(m_it.array_iterator != m_object->m_value.array->end());
6456  return &*m_it.array_iterator;
6457  }
6458 
6459  default:
6460  {
6461  if (m_it.primitive_iterator.is_begin())
6462  {
6463  return m_object;
6464  }
6465  else
6466  {
6467  throw std::out_of_range("cannot get value");
6468  }
6469  }
6470  }
6471  }
6472 
6475  {
6476  auto result = *this;
6477  ++(*this);
6478  return result;
6479  }
6480 
6483  {
6484  assert(m_object != nullptr);
6485 
6486  switch (m_object->m_type)
6487  {
6489  {
6490  ++m_it.object_iterator;
6491  break;
6492  }
6493 
6495  {
6496  ++m_it.array_iterator;
6497  break;
6498  }
6499 
6500  default:
6501  {
6502  ++m_it.primitive_iterator;
6503  break;
6504  }
6505  }
6506 
6507  return *this;
6508  }
6509 
6512  {
6513  auto result = *this;
6514  --(*this);
6515  return result;
6516  }
6517 
6520  {
6521  assert(m_object != nullptr);
6522 
6523  switch (m_object->m_type)
6524  {
6526  {
6527  --m_it.object_iterator;
6528  break;
6529  }
6530 
6532  {
6533  --m_it.array_iterator;
6534  break;
6535  }
6536 
6537  default:
6538  {
6539  --m_it.primitive_iterator;
6540  break;
6541  }
6542  }
6543 
6544  return *this;
6545  }
6546 
6548  bool operator==(const const_iterator& other) const
6549  {
6550  // if objects are not the same, the comparison is undefined
6551  if (m_object != other.m_object)
6552  {
6553  throw std::domain_error("cannot compare iterators of different containers");
6554  }
6555 
6556  assert(m_object != nullptr);
6557 
6558  switch (m_object->m_type)
6559  {
6561  {
6562  return (m_it.object_iterator == other.m_it.object_iterator);
6563  }
6564 
6566  {
6567  return (m_it.array_iterator == other.m_it.array_iterator);
6568  }
6569 
6570  default:
6571  {
6572  return (m_it.primitive_iterator == other.m_it.primitive_iterator);
6573  }
6574  }
6575  }
6576 
6578  bool operator!=(const const_iterator& other) const
6579  {
6580  return not operator==(other);
6581  }
6582 
6584  bool operator<(const const_iterator& other) const
6585  {
6586  // if objects are not the same, the comparison is undefined
6587  if (m_object != other.m_object)
6588  {
6589  throw std::domain_error("cannot compare iterators of different containers");
6590  }
6591 
6592  assert(m_object != nullptr);
6593 
6594  switch (m_object->m_type)
6595  {
6597  {
6598  throw std::domain_error("cannot compare order of object iterators");
6599  }
6600 
6602  {
6603  return (m_it.array_iterator < other.m_it.array_iterator);
6604  }
6605 
6606  default:
6607  {
6608  return (m_it.primitive_iterator < other.m_it.primitive_iterator);
6609  }
6610  }
6611  }
6612 
6614  bool operator<=(const const_iterator& other) const
6615  {
6616  return not other.operator < (*this);
6617  }
6618 
6620  bool operator>(const const_iterator& other) const
6621  {
6622  return not operator<=(other);
6623  }
6624 
6626  bool operator>=(const const_iterator& other) const
6627  {
6628  return not operator<(other);
6629  }
6630 
6633  {
6634  assert(m_object != nullptr);
6635 
6636  switch (m_object->m_type)
6637  {
6639  {
6640  throw std::domain_error("cannot use offsets with object iterators");
6641  }
6642 
6644  {
6645  m_it.array_iterator += i;
6646  break;
6647  }
6648 
6649  default:
6650  {
6651  m_it.primitive_iterator += i;
6652  break;
6653  }
6654  }
6655 
6656  return *this;
6657  }
6658 
6661  {
6662  return operator+=(-i);
6663  }
6664 
6667  {
6668  auto result = *this;
6669  result += i;
6670  return result;
6671  }
6672 
6675  {
6676  auto result = *this;
6677  result -= i;
6678  return result;
6679  }
6680 
6683  {
6684  assert(m_object != nullptr);
6685 
6686  switch (m_object->m_type)
6687  {
6689  {
6690  throw std::domain_error("cannot use offsets with object iterators");
6691  }
6692 
6694  {
6695  return m_it.array_iterator - other.m_it.array_iterator;
6696  }
6697 
6698  default:
6699  {
6700  return m_it.primitive_iterator - other.m_it.primitive_iterator;
6701  }
6702  }
6703  }
6704 
6707  {
6708  assert(m_object != nullptr);
6709 
6710  switch (m_object->m_type)
6711  {
6713  {
6714  throw std::domain_error("cannot use operator[] for object iterators");
6715  }
6716 
6718  {
6719  return *(m_it.array_iterator + n);
6720  }
6721 
6723  {
6724  throw std::out_of_range("cannot get value");
6725  }
6726 
6727  default:
6728  {
6729  if (m_it.primitive_iterator == -n)
6730  {
6731  return *m_object;
6732  }
6733  else
6734  {
6735  throw std::out_of_range("cannot get value");
6736  }
6737  }
6738  }
6739  }
6740 
6742  typename object_t::key_type key() const
6743  {
6744  assert(m_object != nullptr);
6745 
6746  if (m_object->is_object())
6747  {
6748  return m_it.object_iterator->first;
6749  }
6750  else
6751  {
6752  throw std::domain_error("cannot use key() for non-object iterators");
6753  }
6754  }
6755 
6758  {
6759  return operator*();
6760  }
6761 
6762  private:
6764  pointer m_object = nullptr;
6766  internal_iterator m_it = internal_iterator();
6767  };
6768 
6781  class iterator : public const_iterator
6782  {
6783  public:
6785  using pointer = typename basic_json::pointer;
6787 
6789  iterator() = default;
6790 
6792  iterator(pointer object) noexcept
6793  : base_iterator(object)
6794  {}
6795 
6797  iterator(const iterator& other) noexcept
6798  : base_iterator(other)
6799  {}
6800 
6802  iterator& operator=(iterator other) noexcept(
6803  std::is_nothrow_move_constructible<pointer>::value and
6804  std::is_nothrow_move_assignable<pointer>::value and
6805  std::is_nothrow_move_constructible<internal_iterator>::value and
6806  std::is_nothrow_move_assignable<internal_iterator>::value
6807  )
6808  {
6809  base_iterator::operator=(other);
6810  return *this;
6811  }
6812 
6815  {
6816  return const_cast<reference>(base_iterator::operator*());
6817  }
6818 
6821  {
6822  return const_cast<pointer>(base_iterator::operator->());
6823  }
6824 
6827  {
6828  iterator result = *this;
6829  base_iterator::operator++();
6830  return result;
6831  }
6832 
6835  {
6836  base_iterator::operator++();
6837  return *this;
6838  }
6839 
6842  {
6843  iterator result = *this;
6844  base_iterator::operator--();
6845  return result;
6846  }
6847 
6850  {
6851  base_iterator::operator--();
6852  return *this;
6853  }
6854 
6857  {
6858  base_iterator::operator+=(i);
6859  return *this;
6860  }
6861 
6864  {
6865  base_iterator::operator-=(i);
6866  return *this;
6867  }
6868 
6871  {
6872  auto result = *this;
6873  result += i;
6874  return result;
6875  }
6876 
6879  {
6880  auto result = *this;
6881  result -= i;
6882  return result;
6883  }
6884 
6886  difference_type operator-(const iterator& other) const
6887  {
6888  return base_iterator::operator-(other);
6889  }
6890 
6893  {
6894  return const_cast<reference>(base_iterator::operator[](n));
6895  }
6896 
6899  {
6900  return const_cast<reference>(base_iterator::value());
6901  }
6902  };
6903 
6921  template<typename Base>
6922  class json_reverse_iterator : public std::reverse_iterator<Base>
6923  {
6924  public:
6926  using base_iterator = std::reverse_iterator<Base>;
6928  using reference = typename Base::reference;
6929 
6931  json_reverse_iterator(const typename base_iterator::iterator_type& it)
6932  : base_iterator(it)
6933  {}
6934 
6937  : base_iterator(it)
6938  {}
6939 
6942  {
6943  return base_iterator::operator++(1);
6944  }
6945 
6948  {
6949  base_iterator::operator++();
6950  return *this;
6951  }
6952 
6955  {
6956  return base_iterator::operator--(1);
6957  }
6958 
6961  {
6962  base_iterator::operator--();
6963  return *this;
6964  }
6965 
6968  {
6969  base_iterator::operator+=(i);
6970  return *this;
6971  }
6972 
6975  {
6976  auto result = *this;
6977  result += i;
6978  return result;
6979  }
6980 
6983  {
6984  auto result = *this;
6985  result -= i;
6986  return result;
6987  }
6988 
6991  {
6992  return this->base() - other.base();
6993  }
6994 
6997  {
6998  return *(this->operator+(n));
6999  }
7000 
7002  typename object_t::key_type key() const
7003  {
7004  auto it = --this->base();
7005  return it.key();
7006  }
7007 
7010  {
7011  auto it = --this->base();
7012  return it.operator * ();
7013  }
7014  };
7015 
7016 
7017  private:
7019  // lexer and parser //
7021 
7029  class lexer
7030  {
7031  public:
7033  enum class token_type
7034  {
7035  uninitialized,
7036  literal_true,
7037  literal_false,
7038  literal_null,
7039  value_string,
7040  value_number,
7041  begin_array,
7042  begin_object,
7043  end_array,
7044  end_object,
7045  name_separator,
7046  value_separator,
7047  parse_error,
7048  end_of_input
7049  };
7050 
7052  using lexer_char_t = unsigned char;
7053 
7055  explicit lexer(const string_t& s) noexcept
7056  : m_stream(nullptr), m_buffer(s)
7057  {
7058  m_content = reinterpret_cast<const lexer_char_t*>(s.c_str());
7059  assert(m_content != nullptr);
7060  m_start = m_cursor = m_content;
7061  m_limit = m_content + s.size();
7062  }
7063 
7065  explicit lexer(std::istream* s) noexcept
7066  : m_stream(s), m_buffer()
7067  {
7068  assert(m_stream != nullptr);
7069  getline(*m_stream, m_buffer);
7070  m_content = reinterpret_cast<const lexer_char_t*>(m_buffer.c_str());
7071  assert(m_content != nullptr);
7072  m_start = m_cursor = m_content;
7073  m_limit = m_content + m_buffer.size();
7074  }
7075 
7077  lexer() = default;
7078 
7079  // switch off unwanted functions
7080  lexer(const lexer&) = delete;
7081  lexer operator=(const lexer&) = delete;
7082 
7098  static string_t to_unicode(const std::size_t codepoint1,
7099  const std::size_t codepoint2 = 0)
7100  {
7101  // calculate the codepoint from the given code points
7102  std::size_t codepoint = codepoint1;
7103 
7104  // check if codepoint1 is a high surrogate
7105  if (codepoint1 >= 0xD800 and codepoint1 <= 0xDBFF)
7106  {
7107  // check if codepoint2 is a low surrogate
7108  if (codepoint2 >= 0xDC00 and codepoint2 <= 0xDFFF)
7109  {
7110  codepoint =
7111  // high surrogate occupies the most significant 22 bits
7112  (codepoint1 << 10)
7113  // low surrogate occupies the least significant 15 bits
7114  + codepoint2
7115  // there is still the 0xD800, 0xDC00 and 0x10000 noise
7116  // in the result so we have to subtract with:
7117  // (0xD800 << 10) + DC00 - 0x10000 = 0x35FDC00
7118  - 0x35FDC00;
7119  }
7120  else
7121  {
7122  throw std::invalid_argument("missing or wrong low surrogate");
7123  }
7124  }
7125 
7126  string_t result;
7127 
7128  if (codepoint < 0x80)
7129  {
7130  // 1-byte characters: 0xxxxxxx (ASCII)
7131  result.append(1, static_cast<typename string_t::value_type>(codepoint));
7132  }
7133  else if (codepoint <= 0x7ff)
7134  {
7135  // 2-byte characters: 110xxxxx 10xxxxxx
7136  result.append(1, static_cast<typename string_t::value_type>(0xC0 | ((codepoint >> 6) & 0x1F)));
7137  result.append(1, static_cast<typename string_t::value_type>(0x80 | (codepoint & 0x3F)));
7138  }
7139  else if (codepoint <= 0xffff)
7140  {
7141  // 3-byte characters: 1110xxxx 10xxxxxx 10xxxxxx
7142  result.append(1, static_cast<typename string_t::value_type>(0xE0 | ((codepoint >> 12) & 0x0F)));
7143  result.append(1, static_cast<typename string_t::value_type>(0x80 | ((codepoint >> 6) & 0x3F)));
7144  result.append(1, static_cast<typename string_t::value_type>(0x80 | (codepoint & 0x3F)));
7145  }
7146  else if (codepoint <= 0x10ffff)
7147  {
7148  // 4-byte characters: 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
7149  result.append(1, static_cast<typename string_t::value_type>(0xF0 | ((codepoint >> 18) & 0x07)));
7150  result.append(1, static_cast<typename string_t::value_type>(0x80 | ((codepoint >> 12) & 0x3F)));
7151  result.append(1, static_cast<typename string_t::value_type>(0x80 | ((codepoint >> 6) & 0x3F)));
7152  result.append(1, static_cast<typename string_t::value_type>(0x80 | (codepoint & 0x3F)));
7153  }
7154  else
7155  {
7156  throw std::out_of_range("code points above 0x10FFFF are invalid");
7157  }
7158 
7159  return result;
7160  }
7161 
7163  static std::string token_type_name(token_type t)
7164  {
7165  switch (t)
7166  {
7167  case token_type::uninitialized:
7168  return "<uninitialized>";
7169  case token_type::literal_true:
7170  return "true literal";
7171  case token_type::literal_false:
7172  return "false literal";
7173  case token_type::literal_null:
7174  return "null literal";
7175  case token_type::value_string:
7176  return "string literal";
7177  case token_type::value_number:
7178  return "number literal";
7179  case token_type::begin_array:
7180  return "'['";
7181  case token_type::begin_object:
7182  return "'{'";
7183  case token_type::end_array:
7184  return "']'";
7185  case token_type::end_object:
7186  return "'}'";
7187  case token_type::name_separator:
7188  return "':'";
7189  case token_type::value_separator:
7190  return "','";
7191  case token_type::parse_error:
7192  return "<parse error>";
7193  case token_type::end_of_input:
7194  return "end of input";
7195  default:
7196  {
7197  // catch non-enum values
7198  return "unknown token"; // LCOV_EXCL_LINE
7199  }
7200  }
7201  }
7202 
7213  token_type scan() noexcept
7214  {
7215  // pointer for backtracking information
7216  m_marker = nullptr;
7217 
7218  // remember the begin of the token
7219  m_start = m_cursor;
7220  assert(m_start != nullptr);
7221 
7222 
7223  {
7224  lexer_char_t yych;
7225  unsigned int yyaccept = 0;
7226  static const unsigned char yybm[] =
7227  {
7228  0, 0, 0, 0, 0, 0, 0, 0,
7229  0, 32, 32, 0, 0, 32, 0, 0,
7230  128, 128, 128, 128, 128, 128, 128, 128,
7231  128, 128, 128, 128, 128, 128, 128, 128,
7232  160, 128, 0, 128, 128, 128, 128, 128,
7233  128, 128, 128, 128, 128, 128, 128, 128,
7234  192, 192, 192, 192, 192, 192, 192, 192,
7235  192, 192, 128, 128, 128, 128, 128, 128,
7236  128, 128, 128, 128, 128, 128, 128, 128,
7237  128, 128, 128, 128, 128, 128, 128, 128,
7238  128, 128, 128, 128, 128, 128, 128, 128,
7239  128, 128, 128, 128, 0, 128, 128, 128,
7240  128, 128, 128, 128, 128, 128, 128, 128,
7241  128, 128, 128, 128, 128, 128, 128, 128,
7242  128, 128, 128, 128, 128, 128, 128, 128,
7243  128, 128, 128, 128, 128, 128, 128, 128,
7244  128, 128, 128, 128, 128, 128, 128, 128,
7245  128, 128, 128, 128, 128, 128, 128, 128,
7246  128, 128, 128, 128, 128, 128, 128, 128,
7247  128, 128, 128, 128, 128, 128, 128, 128,
7248  128, 128, 128, 128, 128, 128, 128, 128,
7249  128, 128, 128, 128, 128, 128, 128, 128,
7250  128, 128, 128, 128, 128, 128, 128, 128,
7251  128, 128, 128, 128, 128, 128, 128, 128,
7252  128, 128, 128, 128, 128, 128, 128, 128,
7253  128, 128, 128, 128, 128, 128, 128, 128,
7254  128, 128, 128, 128, 128, 128, 128, 128,
7255  128, 128, 128, 128, 128, 128, 128, 128,
7256  128, 128, 128, 128, 128, 128, 128, 128,
7257  128, 128, 128, 128, 128, 128, 128, 128,
7258  128, 128, 128, 128, 128, 128, 128, 128,
7259  128, 128, 128, 128, 128, 128, 128, 128,
7260  };
7261  if ((m_limit - m_cursor) < 5)
7262  {
7263  yyfill(); // LCOV_EXCL_LINE;
7264  }
7265  yych = *m_cursor;
7266  if (yybm[0 + yych] & 32)
7267  {
7268  goto basic_json_parser_6;
7269  }
7270  if (yych <= '\\')
7271  {
7272  if (yych <= '-')
7273  {
7274  if (yych <= '"')
7275  {
7276  if (yych <= 0x00)
7277  {
7278  goto basic_json_parser_2;
7279  }
7280  if (yych <= '!')
7281  {
7282  goto basic_json_parser_4;
7283  }
7284  goto basic_json_parser_9;
7285  }
7286  else
7287  {
7288  if (yych <= '+')
7289  {
7290  goto basic_json_parser_4;
7291  }
7292  if (yych <= ',')
7293  {
7294  goto basic_json_parser_10;
7295  }
7296  goto basic_json_parser_12;
7297  }
7298  }
7299  else
7300  {
7301  if (yych <= '9')
7302  {
7303  if (yych <= '/')
7304  {
7305  goto basic_json_parser_4;
7306  }
7307  if (yych <= '0')
7308  {
7309  goto basic_json_parser_13;
7310  }
7311  goto basic_json_parser_15;
7312  }
7313  else
7314  {
7315  if (yych <= ':')
7316  {
7317  goto basic_json_parser_17;
7318  }
7319  if (yych == '[')
7320  {
7321  goto basic_json_parser_19;
7322  }
7323  goto basic_json_parser_4;
7324  }
7325  }
7326  }
7327  else
7328  {
7329  if (yych <= 't')
7330  {
7331  if (yych <= 'f')
7332  {
7333  if (yych <= ']')
7334  {
7335  goto basic_json_parser_21;
7336  }
7337  if (yych <= 'e')
7338  {
7339  goto basic_json_parser_4;
7340  }
7341  goto basic_json_parser_23;
7342  }
7343  else
7344  {
7345  if (yych == 'n')
7346  {
7347  goto basic_json_parser_24;
7348  }
7349  if (yych <= 's')
7350  {
7351  goto basic_json_parser_4;
7352  }
7353  goto basic_json_parser_25;
7354  }
7355  }
7356  else
7357  {
7358  if (yych <= '|')
7359  {
7360  if (yych == '{')
7361  {
7362  goto basic_json_parser_26;
7363  }
7364  goto basic_json_parser_4;
7365  }
7366  else
7367  {
7368  if (yych <= '}')
7369  {
7370  goto basic_json_parser_28;
7371  }
7372  if (yych == 0xEF)
7373  {
7374  goto basic_json_parser_30;
7375  }
7376  goto basic_json_parser_4;
7377  }
7378  }
7379  }
7380 basic_json_parser_2:
7381  ++m_cursor;
7382  {
7383  return token_type::end_of_input;
7384  }
7385 basic_json_parser_4:
7386  ++m_cursor;
7387 basic_json_parser_5:
7388  {
7389  return token_type::parse_error;
7390  }
7391 basic_json_parser_6:
7392  ++m_cursor;
7393  if (m_limit <= m_cursor)
7394  {
7395  yyfill(); // LCOV_EXCL_LINE;
7396  }
7397  yych = *m_cursor;
7398  if (yybm[0 + yych] & 32)
7399  {
7400  goto basic_json_parser_6;
7401  }
7402  {
7403  return scan();
7404  }
7405 basic_json_parser_9:
7406  yyaccept = 0;
7407  yych = *(m_marker = ++m_cursor);
7408  if (yych <= 0x0F)
7409  {
7410  goto basic_json_parser_5;
7411  }
7412  goto basic_json_parser_32;
7413 basic_json_parser_10:
7414  ++m_cursor;
7415  {
7416  return token_type::value_separator;
7417  }
7418 basic_json_parser_12:
7419  yych = *++m_cursor;
7420  if (yych <= '/')
7421  {
7422  goto basic_json_parser_5;
7423  }
7424  if (yych <= '0')
7425  {
7426  goto basic_json_parser_13;
7427  }
7428  if (yych <= '9')
7429  {
7430  goto basic_json_parser_15;
7431  }
7432  goto basic_json_parser_5;
7433 basic_json_parser_13:
7434  yyaccept = 1;
7435  yych = *(m_marker = ++m_cursor);
7436  if (yych <= 'D')
7437  {
7438  if (yych == '.')
7439  {
7440  goto basic_json_parser_37;
7441  }
7442  }
7443  else
7444  {
7445  if (yych <= 'E')
7446  {
7447  goto basic_json_parser_38;
7448  }
7449  if (yych == 'e')
7450  {
7451  goto basic_json_parser_38;
7452  }
7453  }
7454 basic_json_parser_14:
7455  {
7456  return token_type::value_number;
7457  }
7458 basic_json_parser_15:
7459  yyaccept = 1;
7460  m_marker = ++m_cursor;
7461  if ((m_limit - m_cursor) < 3)
7462  {
7463  yyfill(); // LCOV_EXCL_LINE;
7464  }
7465  yych = *m_cursor;
7466  if (yybm[0 + yych] & 64)
7467  {
7468  goto basic_json_parser_15;
7469  }
7470  if (yych <= 'D')
7471  {
7472  if (yych == '.')
7473  {
7474  goto basic_json_parser_37;
7475  }
7476  goto basic_json_parser_14;
7477  }
7478  else
7479  {
7480  if (yych <= 'E')
7481  {
7482  goto basic_json_parser_38;
7483  }
7484  if (yych == 'e')
7485  {
7486  goto basic_json_parser_38;
7487  }
7488  goto basic_json_parser_14;
7489  }
7490 basic_json_parser_17:
7491  ++m_cursor;
7492  {
7493  return token_type::name_separator;
7494  }
7495 basic_json_parser_19:
7496  ++m_cursor;
7497  {
7498  return token_type::begin_array;
7499  }
7500 basic_json_parser_21:
7501  ++m_cursor;
7502  {
7503  return token_type::end_array;
7504  }
7505 basic_json_parser_23:
7506  yyaccept = 0;
7507  yych = *(m_marker = ++m_cursor);
7508  if (yych == 'a')
7509  {
7510  goto basic_json_parser_39;
7511  }
7512  goto basic_json_parser_5;
7513 basic_json_parser_24:
7514  yyaccept = 0;
7515  yych = *(m_marker = ++m_cursor);
7516  if (yych == 'u')
7517  {
7518  goto basic_json_parser_40;
7519  }
7520  goto basic_json_parser_5;
7521 basic_json_parser_25:
7522  yyaccept = 0;
7523  yych = *(m_marker = ++m_cursor);
7524  if (yych == 'r')
7525  {
7526  goto basic_json_parser_41;
7527  }
7528  goto basic_json_parser_5;
7529 basic_json_parser_26:
7530  ++m_cursor;
7531  {
7532  return token_type::begin_object;
7533  }
7534 basic_json_parser_28:
7535  ++m_cursor;
7536  {
7537  return token_type::end_object;
7538  }
7539 basic_json_parser_30:
7540  yyaccept = 0;
7541  yych = *(m_marker = ++m_cursor);
7542  if (yych == 0xBB)
7543  {
7544  goto basic_json_parser_42;
7545  }
7546  goto basic_json_parser_5;
7547 basic_json_parser_31:
7548  ++m_cursor;
7549  if (m_limit <= m_cursor)
7550  {
7551  yyfill(); // LCOV_EXCL_LINE;
7552  }
7553  yych = *m_cursor;
7554 basic_json_parser_32:
7555  if (yybm[0 + yych] & 128)
7556  {
7557  goto basic_json_parser_31;
7558  }
7559  if (yych <= 0x0F)
7560  {
7561  goto basic_json_parser_33;
7562  }
7563  if (yych <= '"')
7564  {
7565  goto basic_json_parser_34;
7566  }
7567  goto basic_json_parser_36;
7568 basic_json_parser_33:
7569  m_cursor = m_marker;
7570  if (yyaccept == 0)
7571  {
7572  goto basic_json_parser_5;
7573  }
7574  else
7575  {
7576  goto basic_json_parser_14;
7577  }
7578 basic_json_parser_34:
7579  ++m_cursor;
7580  {
7581  return token_type::value_string;
7582  }
7583 basic_json_parser_36:
7584  ++m_cursor;
7585  if (m_limit <= m_cursor)
7586  {
7587  yyfill(); // LCOV_EXCL_LINE;
7588  }
7589  yych = *m_cursor;
7590  if (yych <= 'e')
7591  {
7592  if (yych <= '/')
7593  {
7594  if (yych == '"')
7595  {
7596  goto basic_json_parser_31;
7597  }
7598  if (yych <= '.')
7599  {
7600  goto basic_json_parser_33;
7601  }
7602  goto basic_json_parser_31;
7603  }
7604  else
7605  {
7606  if (yych <= '\\')
7607  {
7608  if (yych <= '[')
7609  {
7610  goto basic_json_parser_33;
7611  }
7612  goto basic_json_parser_31;
7613  }
7614  else
7615  {
7616  if (yych == 'b')
7617  {
7618  goto basic_json_parser_31;
7619  }
7620  goto basic_json_parser_33;
7621  }
7622  }
7623  }
7624  else
7625  {
7626  if (yych <= 'q')
7627  {
7628  if (yych <= 'f')
7629  {
7630  goto basic_json_parser_31;
7631  }
7632  if (yych == 'n')
7633  {
7634  goto basic_json_parser_31;
7635  }
7636  goto basic_json_parser_33;
7637  }
7638  else
7639  {
7640  if (yych <= 's')
7641  {
7642  if (yych <= 'r')
7643  {
7644  goto basic_json_parser_31;
7645  }
7646  goto basic_json_parser_33;
7647  }
7648  else
7649  {
7650  if (yych <= 't')
7651  {
7652  goto basic_json_parser_31;
7653  }
7654  if (yych <= 'u')
7655  {
7656  goto basic_json_parser_43;
7657  }
7658  goto basic_json_parser_33;
7659  }
7660  }
7661  }
7662 basic_json_parser_37:
7663  yych = *++m_cursor;
7664  if (yych <= '/')
7665  {
7666  goto basic_json_parser_33;
7667  }
7668  if (yych <= '9')
7669  {
7670  goto basic_json_parser_44;
7671  }
7672  goto basic_json_parser_33;
7673 basic_json_parser_38:
7674  yych = *++m_cursor;
7675  if (yych <= ',')
7676  {
7677  if (yych == '+')
7678  {
7679  goto basic_json_parser_46;
7680  }
7681  goto basic_json_parser_33;
7682  }
7683  else
7684  {
7685  if (yych <= '-')
7686  {
7687  goto basic_json_parser_46;
7688  }
7689  if (yych <= '/')
7690  {
7691  goto basic_json_parser_33;
7692  }
7693  if (yych <= '9')
7694  {
7695  goto basic_json_parser_47;
7696  }
7697  goto basic_json_parser_33;
7698  }
7699 basic_json_parser_39:
7700  yych = *++m_cursor;
7701  if (yych == 'l')
7702  {
7703  goto basic_json_parser_49;
7704  }
7705  goto basic_json_parser_33;
7706 basic_json_parser_40:
7707  yych = *++m_cursor;
7708  if (yych == 'l')
7709  {
7710  goto basic_json_parser_50;
7711  }
7712  goto basic_json_parser_33;
7713 basic_json_parser_41:
7714  yych = *++m_cursor;
7715  if (yych == 'u')
7716  {
7717  goto basic_json_parser_51;
7718  }
7719  goto basic_json_parser_33;
7720 basic_json_parser_42:
7721  yych = *++m_cursor;
7722  if (yych == 0xBF)
7723  {
7724  goto basic_json_parser_52;
7725  }
7726  goto basic_json_parser_33;
7727 basic_json_parser_43:
7728  ++m_cursor;
7729  if (m_limit <= m_cursor)
7730  {
7731  yyfill(); // LCOV_EXCL_LINE;
7732  }
7733  yych = *m_cursor;
7734  if (yych <= '@')
7735  {
7736  if (yych <= '/')
7737  {
7738  goto basic_json_parser_33;
7739  }
7740  if (yych <= '9')
7741  {
7742  goto basic_json_parser_54;
7743  }
7744  goto basic_json_parser_33;
7745  }
7746  else
7747  {
7748  if (yych <= 'F')
7749  {
7750  goto basic_json_parser_54;
7751  }
7752  if (yych <= '`')
7753  {
7754  goto basic_json_parser_33;
7755  }
7756  if (yych <= 'f')
7757  {
7758  goto basic_json_parser_54;
7759  }
7760  goto basic_json_parser_33;
7761  }
7762 basic_json_parser_44:
7763  yyaccept = 1;
7764  m_marker = ++m_cursor;
7765  if ((m_limit - m_cursor) < 3)
7766  {
7767  yyfill(); // LCOV_EXCL_LINE;
7768  }
7769  yych = *m_cursor;
7770  if (yych <= 'D')
7771  {
7772  if (yych <= '/')
7773  {
7774  goto basic_json_parser_14;
7775  }
7776  if (yych <= '9')
7777  {
7778  goto basic_json_parser_44;
7779  }
7780  goto basic_json_parser_14;
7781  }
7782  else
7783  {
7784  if (yych <= 'E')
7785  {
7786  goto basic_json_parser_38;
7787  }
7788  if (yych == 'e')
7789  {
7790  goto basic_json_parser_38;
7791  }
7792  goto basic_json_parser_14;
7793  }
7794 basic_json_parser_46:
7795  yych = *++m_cursor;
7796  if (yych <= '/')
7797  {
7798  goto basic_json_parser_33;
7799  }
7800  if (yych >= ':')
7801  {
7802  goto basic_json_parser_33;
7803  }
7804 basic_json_parser_47:
7805  ++m_cursor;
7806  if (m_limit <= m_cursor)
7807  {
7808  yyfill(); // LCOV_EXCL_LINE;
7809  }
7810  yych = *m_cursor;
7811  if (yych <= '/')
7812  {
7813  goto basic_json_parser_14;
7814  }
7815  if (yych <= '9')
7816  {
7817  goto basic_json_parser_47;
7818  }
7819  goto basic_json_parser_14;
7820 basic_json_parser_49:
7821  yych = *++m_cursor;
7822  if (yych == 's')
7823  {
7824  goto basic_json_parser_55;
7825  }
7826  goto basic_json_parser_33;
7827 basic_json_parser_50:
7828  yych = *++m_cursor;
7829  if (yych == 'l')
7830  {
7831  goto basic_json_parser_56;
7832  }
7833  goto basic_json_parser_33;
7834 basic_json_parser_51:
7835  yych = *++m_cursor;
7836  if (yych == 'e')
7837  {
7838  goto basic_json_parser_58;
7839  }
7840  goto basic_json_parser_33;
7841 basic_json_parser_52:
7842  ++m_cursor;
7843  {
7844  return scan();
7845  }
7846 basic_json_parser_54:
7847  ++m_cursor;
7848  if (m_limit <= m_cursor)
7849  {
7850  yyfill(); // LCOV_EXCL_LINE;
7851  }
7852  yych = *m_cursor;
7853  if (yych <= '@')
7854  {
7855  if (yych <= '/')
7856  {
7857  goto basic_json_parser_33;
7858  }
7859  if (yych <= '9')
7860  {
7861  goto basic_json_parser_60;
7862  }
7863  goto basic_json_parser_33;
7864  }
7865  else
7866  {
7867  if (yych <= 'F')
7868  {
7869  goto basic_json_parser_60;
7870  }
7871  if (yych <= '`')
7872  {
7873  goto basic_json_parser_33;
7874  }
7875  if (yych <= 'f')
7876  {
7877  goto basic_json_parser_60;
7878  }
7879  goto basic_json_parser_33;
7880  }
7881 basic_json_parser_55:
7882  yych = *++m_cursor;
7883  if (yych == 'e')
7884  {
7885  goto basic_json_parser_61;
7886  }
7887  goto basic_json_parser_33;
7888 basic_json_parser_56:
7889  ++m_cursor;
7890  {
7891  return token_type::literal_null;
7892  }
7893 basic_json_parser_58:
7894  ++m_cursor;
7895  {
7896  return token_type::literal_true;
7897  }
7898 basic_json_parser_60:
7899  ++m_cursor;
7900  if (m_limit <= m_cursor)
7901  {
7902  yyfill(); // LCOV_EXCL_LINE;
7903  }
7904  yych = *m_cursor;
7905  if (yych <= '@')
7906  {
7907  if (yych <= '/')
7908  {
7909  goto basic_json_parser_33;
7910  }
7911  if (yych <= '9')
7912  {
7913  goto basic_json_parser_63;
7914  }
7915  goto basic_json_parser_33;
7916  }
7917  else
7918  {
7919  if (yych <= 'F')
7920  {
7921  goto basic_json_parser_63;
7922  }
7923  if (yych <= '`')
7924  {
7925  goto basic_json_parser_33;
7926  }
7927  if (yych <= 'f')
7928  {
7929  goto basic_json_parser_63;
7930  }
7931  goto basic_json_parser_33;
7932  }
7933 basic_json_parser_61:
7934  ++m_cursor;
7935  {
7936  return token_type::literal_false;
7937  }
7938 basic_json_parser_63:
7939  ++m_cursor;
7940  if (m_limit <= m_cursor)
7941  {
7942  yyfill(); // LCOV_EXCL_LINE;
7943  }
7944  yych = *m_cursor;
7945  if (yych <= '@')
7946  {
7947  if (yych <= '/')
7948  {
7949  goto basic_json_parser_33;
7950  }
7951  if (yych <= '9')
7952  {
7953  goto basic_json_parser_31;
7954  }
7955  goto basic_json_parser_33;
7956  }
7957  else
7958  {
7959  if (yych <= 'F')
7960  {
7961  goto basic_json_parser_31;
7962  }
7963  if (yych <= '`')
7964  {
7965  goto basic_json_parser_33;
7966  }
7967  if (yych <= 'f')
7968  {
7969  goto basic_json_parser_31;
7970  }
7971  goto basic_json_parser_33;
7972  }
7973  }
7974 
7975 
7976  }
7977 
7979  void yyfill() noexcept
7980  {
7981  if (m_stream == nullptr or not * m_stream)
7982  {
7983  return;
7984  }
7985 
7986  const ssize_t offset_start = m_start - m_content;
7987  const ssize_t offset_marker = m_marker - m_start;
7988  const ssize_t offset_cursor = m_cursor - m_start;
7989 
7990  m_buffer.erase(0, static_cast<size_t>(offset_start));
7991  std::string line;
7992  assert(m_stream != nullptr);
7993  std::getline(*m_stream, line);
7994  m_buffer += "\n" + line; // add line with newline symbol
7995 
7996  m_content = reinterpret_cast<const lexer_char_t*>(m_buffer.c_str());
7997  assert(m_content != nullptr);
7998  m_start = m_content;
7999  m_marker = m_start + offset_marker;
8000  m_cursor = m_start + offset_cursor;
8001  m_limit = m_start + m_buffer.size() - 1;
8002  }
8003 
8005  string_t get_token() const noexcept
8006  {
8007  assert(m_start != nullptr);
8008  return string_t(reinterpret_cast<typename string_t::const_pointer>(m_start),
8009  static_cast<size_t>(m_cursor - m_start));
8010  }
8011 
8033  string_t get_string() const
8034  {
8035  string_t result;
8036  result.reserve(static_cast<size_t>(m_cursor - m_start - 2));
8037 
8038  // iterate the result between the quotes
8039  for (const lexer_char_t* i = m_start + 1; i < m_cursor - 1; ++i)
8040  {
8041  // process escaped characters
8042  if (*i == '\\')
8043  {
8044  // read next character
8045  ++i;
8046 
8047  switch (*i)
8048  {
8049  // the default escapes
8050  case 't':
8051  {
8052  result += "\t";
8053  break;
8054  }
8055  case 'b':
8056  {
8057  result += "\b";
8058  break;
8059  }
8060  case 'f':
8061  {
8062  result += "\f";
8063  break;
8064  }
8065  case 'n':
8066  {
8067  result += "\n";
8068  break;
8069  }
8070  case 'r':
8071  {
8072  result += "\r";
8073  break;
8074  }
8075  case '\\':
8076  {
8077  result += "\\";
8078  break;
8079  }
8080  case '/':
8081  {
8082  result += "/";
8083  break;
8084  }
8085  case '"':
8086  {
8087  result += "\"";
8088  break;
8089  }
8090 
8091  // unicode
8092  case 'u':
8093  {
8094  // get code xxxx from uxxxx
8095  auto codepoint = std::strtoul(std::string(reinterpret_cast<typename string_t::const_pointer>(i + 1),
8096  4).c_str(), nullptr, 16);
8097 
8098  // check if codepoint is a high surrogate
8099  if (codepoint >= 0xD800 and codepoint <= 0xDBFF)
8100  {
8101  // make sure there is a subsequent unicode
8102  if ((i + 6 >= m_limit) or * (i + 5) != '\\' or * (i + 6) != 'u')
8103  {
8104  throw std::invalid_argument("missing low surrogate");
8105  }
8106 
8107  // get code yyyy from uxxxx\uyyyy
8108  auto codepoint2 = std::strtoul(std::string(reinterpret_cast<typename string_t::const_pointer>
8109  (i + 7), 4).c_str(), nullptr, 16);
8110  result += to_unicode(codepoint, codepoint2);
8111  // skip the next 10 characters (xxxx\uyyyy)
8112  i += 10;
8113  }
8114  else
8115  {
8116  // add unicode character(s)
8117  result += to_unicode(codepoint);
8118  // skip the next four characters (xxxx)
8119  i += 4;
8120  }
8121  break;
8122  }
8123  }
8124  }
8125  else
8126  {
8127  // all other characters are just copied to the end of the
8128  // string
8129  result.append(1, static_cast<typename string_t::value_type>(*i));
8130  }
8131  }
8132 
8133  return result;
8134  }
8135 
8156  long double str_to_float_t(long double* /* type */, char** endptr) const
8157  {
8158  return std::strtold(reinterpret_cast<typename string_t::const_pointer>(m_start), endptr);
8159  }
8160 
8176  double str_to_float_t(double* /* type */, char** endptr) const
8177  {
8178  return std::strtod(reinterpret_cast<typename string_t::const_pointer>(m_start), endptr);
8179  }
8180 
8196  float str_to_float_t(float* /* type */, char** endptr) const
8197  {
8198  return std::strtof(reinterpret_cast<typename string_t::const_pointer>(m_start), endptr);
8199  }
8200 
8213  template <typename T_A, typename T_B>
8214  bool attempt_cast(T_A source, T_B& dest) const
8215  {
8216  dest = static_cast<T_B>(source);
8217  return (source == static_cast<T_A>(dest));
8218  }
8219 
8258  void get_number(basic_json& result) const
8259  {
8260  typename string_t::value_type* endptr;
8261  assert(m_start != nullptr);
8262  errno = 0;
8263 
8264  // attempt to parse it as an integer - first checking for a
8265  // negative number
8266  if (*reinterpret_cast<typename string_t::const_pointer>(m_start) != '-')
8267  {
8268  // positive, parse with strtoull and attempt cast to
8269  // number_unsigned_t
8270  if (attempt_cast(std::strtoull(reinterpret_cast<typename string_t::const_pointer>(m_start), &endptr,
8271  10), result.m_value.number_unsigned))
8272  {
8273  result.m_type = value_t::number_unsigned;
8274  }
8275  else
8276  {
8277  // cast failed due to overflow - store as float
8278  result.m_type = value_t::number_float;
8279  }
8280  }
8281  else
8282  {
8283  // Negative, parse with strtoll and attempt cast to
8284  // number_integer_t
8285  if (attempt_cast(std::strtoll(reinterpret_cast<typename string_t::const_pointer>(m_start), &endptr,
8286  10), result.m_value.number_integer))
8287  {
8288  result.m_type = value_t::number_integer;
8289  }
8290  else
8291  {
8292  // cast failed due to overflow - store as float
8293  result.m_type = value_t::number_float;
8294  }
8295  }
8296 
8297  // check the end of the number was reached and no range error
8298  // occurred
8299  if (reinterpret_cast<lexer_char_t*>(endptr) != m_cursor || errno == ERANGE)
8300  {
8301  result.m_type = value_t::number_float;
8302  }
8303 
8304  if (result.m_type == value_t::number_float)
8305  {
8306  // either the number won't fit in an integer (range error from
8307  // strtoull/strtoll or overflow on cast) or there was something
8308  // else after the number, which could be an exponent
8309 
8310  // parse with strtod
8311  result.m_value.number_float = str_to_float_t(static_cast<number_float_t*>(nullptr), &endptr);
8312 
8313  // anything after the number is an error
8314  if (reinterpret_cast<lexer_char_t*>(endptr) != m_cursor)
8315  {
8316  throw std::invalid_argument(std::string("parse error - ") + get_token() + " is not a number");
8317  }
8318  }
8319  }
8320 
8321  private:
8323  std::istream* m_stream = nullptr;
8325  string_t m_buffer;
8327  const lexer_char_t* m_content = nullptr;
8329  const lexer_char_t* m_start = nullptr;
8331  const lexer_char_t* m_marker = nullptr;
8333  const lexer_char_t* m_cursor = nullptr;
8335  const lexer_char_t* m_limit = nullptr;
8336  };
8337 
8343  class parser
8344  {
8345  public:
8347  parser(const string_t& s, parser_callback_t cb = nullptr)
8348  : callback(cb), m_lexer(s)
8349  {
8350  // read first token
8351  get_token();
8352  }
8353 
8355  parser(std::istream& _is, parser_callback_t cb = nullptr)
8356  : callback(cb), m_lexer(&_is)
8357  {
8358  // read first token
8359  get_token();
8360  }
8361 
8363  basic_json parse()
8364  {
8365  basic_json result = parse_internal(true);
8366 
8367  expect(lexer::token_type::end_of_input);
8368 
8369  // return parser result and replace it with null in case the
8370  // top-level value was discarded by the callback function
8371  return result.is_discarded() ? basic_json() : result;
8372  }
8373 
8374  private:
8376  basic_json parse_internal(bool keep)
8377  {
8378  auto result = basic_json(value_t::discarded);
8379 
8380  switch (last_token)
8381  {
8382  case lexer::token_type::begin_object:
8383  {
8384  if (keep and (not callback or (keep = callback(depth++, parse_event_t::object_start, result))))
8385  {
8386  // explicitly set result to object to cope with {}
8387  result.m_type = value_t::object;
8388  result.m_value = json_value(value_t::object);
8389  }
8390 
8391  // read next token
8392  get_token();
8393 
8394  // closing } -> we are done
8395  if (last_token == lexer::token_type::end_object)
8396  {
8397  get_token();
8398  if (keep and callback and not callback(--depth, parse_event_t::object_end, result))
8399  {
8400  result = basic_json(value_t::discarded);
8401  }
8402  return result;
8403  }
8404 
8405  // no comma is expected here
8406  unexpect(lexer::token_type::value_separator);
8407 
8408  // otherwise: parse key-value pairs
8409  do
8410  {
8411  // ugly, but could be fixed with loop reorganization
8412  if (last_token == lexer::token_type::value_separator)
8413  {
8414  get_token();
8415  }
8416 
8417  // store key
8418  expect(lexer::token_type::value_string);
8419  const auto key = m_lexer.get_string();
8420 
8421  bool keep_tag = false;
8422  if (keep)
8423  {
8424  if (callback)
8425  {
8426  basic_json k(key);
8427  keep_tag = callback(depth, parse_event_t::key, k);
8428  }
8429  else
8430  {
8431  keep_tag = true;
8432  }
8433  }
8434 
8435  // parse separator (:)
8436  get_token();
8437  expect(lexer::token_type::name_separator);
8438 
8439  // parse and add value
8440  get_token();
8441  auto value = parse_internal(keep);
8442  if (keep and keep_tag and not value.is_discarded())
8443  {
8444  result[key] = std::move(value);
8445  }
8446  }
8447  while (last_token == lexer::token_type::value_separator);
8448 
8449  // closing }
8450  expect(lexer::token_type::end_object);
8451  get_token();
8452  if (keep and callback and not callback(--depth, parse_event_t::object_end, result))
8453  {
8454  result = basic_json(value_t::discarded);
8455  }
8456 
8457  return result;
8458  }
8459 
8460  case lexer::token_type::begin_array:
8461  {
8462  if (keep and (not callback or (keep = callback(depth++, parse_event_t::array_start, result))))
8463  {
8464  // explicitly set result to object to cope with []
8465  result.m_type = value_t::array;
8466  result.m_value = json_value(value_t::array);
8467  }
8468 
8469  // read next token
8470  get_token();
8471 
8472  // closing ] -> we are done
8473  if (last_token == lexer::token_type::end_array)
8474  {
8475  get_token();
8476  if (callback and not callback(--depth, parse_event_t::array_end, result))
8477  {
8478  result = basic_json(value_t::discarded);
8479  }
8480  return result;
8481  }
8482 
8483  // no comma is expected here
8484  unexpect(lexer::token_type::value_separator);
8485 
8486  // otherwise: parse values
8487  do
8488  {
8489  // ugly, but could be fixed with loop reorganization
8490  if (last_token == lexer::token_type::value_separator)
8491  {
8492  get_token();
8493  }
8494 
8495  // parse value
8496  auto value = parse_internal(keep);
8497  if (keep and not value.is_discarded())
8498  {
8499  result.push_back(std::move(value));
8500  }
8501  }
8502  while (last_token == lexer::token_type::value_separator);
8503 
8504  // closing ]
8505  expect(lexer::token_type::end_array);
8506  get_token();
8507  if (keep and callback and not callback(--depth, parse_event_t::array_end, result))
8508  {
8509  result = basic_json(value_t::discarded);
8510  }
8511 
8512  return result;
8513  }
8514 
8515  case lexer::token_type::literal_null:
8516  {
8517  get_token();
8518  result.m_type = value_t::null;
8519  break;
8520  }
8521 
8522  case lexer::token_type::value_string:
8523  {
8524  const auto s = m_lexer.get_string();
8525  get_token();
8526  result = basic_json(s);
8527  break;
8528  }
8529 
8530  case lexer::token_type::literal_true:
8531  {
8532  get_token();
8533  result.m_type = value_t::boolean;
8534  result.m_value = true;
8535  break;
8536  }
8537 
8538  case lexer::token_type::literal_false:
8539  {
8540  get_token();
8541  result.m_type = value_t::boolean;
8542  result.m_value = false;
8543  break;
8544  }
8545 
8546  case lexer::token_type::value_number:
8547  {
8548  m_lexer.get_number(result);
8549  get_token();
8550  break;
8551  }
8552 
8553  default:
8554  {
8555  // the last token was unexpected
8556  unexpect(last_token);
8557  }
8558  }
8559 
8560  if (keep and callback and not callback(depth, parse_event_t::value, result))
8561  {
8562  result = basic_json(value_t::discarded);
8563  }
8564  return result;
8565  }
8566 
8568  typename lexer::token_type get_token()
8569  {
8570  last_token = m_lexer.scan();
8571  return last_token;
8572  }
8573 
8574  void expect(typename lexer::token_type t) const
8575  {
8576  if (t != last_token)
8577  {
8578  std::string error_msg = "parse error - unexpected ";
8579  error_msg += (last_token == lexer::token_type::parse_error ? ("'" + m_lexer.get_token() + "'") :
8580  lexer::token_type_name(last_token));
8581  error_msg += "; expected " + lexer::token_type_name(t);
8582  throw std::invalid_argument(error_msg);
8583  }
8584  }
8585 
8586  void unexpect(typename lexer::token_type t) const
8587  {
8588  if (t == last_token)
8589  {
8590  std::string error_msg = "parse error - unexpected ";
8591  error_msg += (last_token == lexer::token_type::parse_error ? ("'" + m_lexer.get_token() + "'") :
8592  lexer::token_type_name(last_token));
8593  throw std::invalid_argument(error_msg);
8594  }
8595  }
8596 
8597  private:
8599  int depth = 0;
8601  parser_callback_t callback;
8603  typename lexer::token_type last_token = lexer::token_type::uninitialized;
8605  lexer m_lexer;
8606  };
8607 };
8608 
8609 
8611 // presets //
8613 
8623 }
8624 
8625 
8627 // nonmember functions //
8629 
8630 // specialization of std::swap, and std::hash
8631 namespace std
8632 {
8638 template <>
8639 inline void swap(nlohmann::json& j1,
8640  nlohmann::json& j2) noexcept(
8641  is_nothrow_move_constructible<nlohmann::json>::value and
8642  is_nothrow_move_assignable<nlohmann::json>::value
8643  )
8644 {
8645  j1.swap(j2);
8646 }
8647 
8649 template <>
8650 struct hash<nlohmann::json>
8651 {
8657  std::size_t operator()(const nlohmann::json& j) const
8658  {
8659  // a naive hashing via the string representation
8660  const auto& h = hash<nlohmann::json::string_t>();
8661  return h(j.dump());
8662  }
8663 };
8664 }
8665 
8678 inline nlohmann::json operator "" _json(const char* s, std::size_t)
8679 {
8680  return nlohmann::json::parse(reinterpret_cast<const nlohmann::json::string_t::value_type*>(s));
8681 }
8682 
8683 // restore GCC/clang diagnostic settings
8684 #if defined(__clang__) || defined(__GNUC__) || defined(__GNUG__)
8685  #pragma GCC diagnostic pop
8686 #endif
8687 
8688 #endif
bool is_null() const noexcept
return whether value is null
Definition: json.hpp:2169
reference operator*()
return a reference to the value pointed to by the iterator
Definition: json.hpp:6814
reverse_iterator rbegin()
returns an iterator to the reverse-beginning
Definition: json.hpp:4194
friend bool operator<=(const_reference lhs, const_reference rhs) noexcept
comparison: less than or equal
Definition: json.hpp:5452
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:1076
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:4012
value_t type() const noexcept
return the type of the JSON value (explicit)
Definition: json.hpp:2099
bool is_number_integer() const noexcept
return whether value is an integer number
Definition: json.hpp:2241
const_reference operator[](size_type idx) const
access specified array element
Definition: json.hpp:3204
reference value() const
return the value of an iterator
Definition: json.hpp:6898
json_reverse_iterator & operator--()
pre-decrement (–it)
Definition: json.hpp:6960
bool is_boolean() const noexcept
return whether value is a boolean
Definition: json.hpp:2188
void clear() noexcept
clears the contents
Definition: json.hpp:4562
bool operator==(const const_iterator &other) const
comparison: equal
Definition: json.hpp:6548
json_reverse_iterator operator--(int)
post-decrement (it–)
Definition: json.hpp:6954
reference operator[](T *(&key)[n])
access specified object element
Definition: json.hpp:3336
friend std::istream & operator>>(std::istream &i, basic_json &j)
deserialize from stream
Definition: json.hpp:5665
bool is_number() const noexcept
return whether value is a number
Definition: json.hpp:2215
iterator & operator+=(difference_type i)
add to iterator
Definition: json.hpp:6856
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:1656
const_iterator operator-(difference_type i)
subtract from iterator
Definition: json.hpp:6674
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:4748
bool is_array() const noexcept
return whether value is an array
Definition: json.hpp:2329
basic_json(const typename string_t::value_type *val)
create a string (explicit)
Definition: json.hpp:1169
basic_json(boolean_t val)
create a boolean (explicit)
Definition: json.hpp:1218
reference operator[](difference_type n) const
access to successor
Definition: json.hpp:6996
iterator find(typename object_t::key_type key)
find an element in a JSON object
Definition: json.hpp:3964
basic_json(const number_unsigned_t val)
create an unsigned integer number (explicit)
Definition: json.hpp:1345
friend bool operator!=(const_reference lhs, const_reference rhs) noexcept
comparison: not equal
Definition: json.hpp:5290
basic_json(const string_t &val)
create a string (explicit)
Definition: json.hpp:1145
void push_back(const basic_json &val)
add an object to an array
Definition: json.hpp:4674
void erase(const size_type idx)
remove element from a JSON array given an index
Definition: json.hpp:3918
basic_json<> json
default JSON class
Definition: json.hpp:8622
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:2150
reference front()
access the first element
Definition: json.hpp:3575
void swap(object_t &other)
exchanges the values
Definition: json.hpp:5046
json_reverse_iterator operator-(difference_type i) const
subtract from iterator
Definition: json.hpp:6982
const_iterator & operator+=(difference_type i)
add to iterator
Definition: json.hpp:6632
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:1405
pointer operator->()
dereference the iterator
Definition: json.hpp:6820
reference value() const
return the value of an iterator
Definition: json.hpp:7009
friend bool operator==(std::nullptr_t, const_reference v) noexcept
comparison: equal
Definition: json.hpp:5269
const_reverse_iterator crbegin() const
returns a const reverse iterator to the last element
Definition: json.hpp:4268
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:4832
const_reference at(const typename object_t::key_type &key) const
access specified object element with bounds checking
Definition: json.hpp:3111
const_iterator operator+(difference_type i)
add to iterator
Definition: json.hpp:6666
const_reverse_iterator rbegin() const
returns a const reverse iterator to the last element
Definition: json.hpp:4202
a mutable random access iterator for the basic_json class
Definition: json.hpp:6781
static basic_json parse(std::istream &&i, parser_callback_t cb=nullptr)
deserialize from stream
Definition: json.hpp:5627
const_iterator operator++(int)
post-increment (it++)
Definition: json.hpp:6474
bool is_string() const noexcept
return whether value is a string
Definition: json.hpp:2348
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:1616
static iteration_proxy< const_iterator > iterator_wrapper(const_reference cont)
wrapper to access iterator member functions in range-based for
Definition: json.hpp:4326
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:1971
typename basic_json::value_type value_type
the type of the values when the iterator is dereferenced
Definition: json.hpp:6246
PointerType get_ptr() noexcept
get a pointer value (implicit)
Definition: json.hpp:2825
reference back()
access the last element
Definition: json.hpp:3617
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:6250
bool is_number_unsigned() const noexcept
return whether value is an unsigned integer number
Definition: json.hpp:2266
void push_back(const typename object_t::value_type &val)
add an object to an object
Definition: json.hpp:4724
iterator end()
returns an iterator to one past the last element
Definition: json.hpp:4124
static basic_json parse(const string_t &s, parser_callback_t cb=nullptr)
deserialize from string
Definition: json.hpp:5590
const_reference operator[](T *(&key)[n]) const
read-only access specified object element
Definition: json.hpp:3371
iterator insert(const_iterator pos, const_iterator first, const_iterator last)
inserts elements
Definition: json.hpp:4885
basic_json(std::nullptr_t) noexcept
create a null object (explicitly)
Definition: json.hpp:991
basic_json(InputIT first, InputIT last)
construct a JSON container given an iterator range
Definition: json.hpp:1726
reference operator[](difference_type n) const
access to successor
Definition: json.hpp:6892
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:3293
const_reference operator[](T *key) const
read-only access specified object element
Definition: json.hpp:3453
json_reverse_iterator operator+(difference_type i) const
add to iterator
Definition: json.hpp:6974
bool empty() const noexcept
checks whether the container is empty
Definition: json.hpp:4374
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:7002
basic_json(const CompatibleArrayType &val)
create an array (implicit)
Definition: json.hpp:1116
const_reference at(size_type idx) const
access specified array element with bounds checking
Definition: json.hpp:3015
basic_json(size_type cnt, const basic_json &val)
construct an array with count copies of given value
Definition: json.hpp:1680
std::reverse_iterator< Base > base_iterator
shortcut to the reverse iterator adaptor
Definition: json.hpp:6926
iterator insert(const_iterator pos, std::initializer_list< basic_json > ilist)
inserts elements
Definition: json.hpp:4943
const_iterator(const iterator &other)
copy constructor given a nonconst iterator
Definition: json.hpp:6287
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:4776
friend bool operator>=(const_reference lhs, const_reference rhs) noexcept
comparison: greater than or equal
Definition: json.hpp:5496
friend bool operator<(const_reference lhs, const_reference rhs) noexcept
comparison: less than
Definition: json.hpp:5351
iterator & operator++()
pre-increment (++it)
Definition: json.hpp:6834
bool operator<(const const_iterator &other) const
comparison: smaller
Definition: json.hpp:6584
iterator operator++(int)
post-increment (it++)
Definition: json.hpp:6826
basic_json(basic_json &&other) noexcept
move constructor
Definition: json.hpp:1939
const_iterator operator--(int)
post-decrement (it–)
Definition: json.hpp:6511
bool is_discarded() const noexcept
return whether value is discarded
Definition: json.hpp:2372
reference at(const typename object_t::key_type &key)
access specified object element with bounds checking
Definition: json.hpp:3063
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:6802
object (unordered set of name/value pairs)
size_type max_size() const noexcept
returns the maximum possible number of elements
Definition: json.hpp:4503
~basic_json()
destructor
Definition: json.hpp:1999
iterator operator--(int)
post-decrement (it–)
Definition: json.hpp:6841
iterator operator-(difference_type i)
subtract from iterator
Definition: json.hpp:6878
const_iterator & operator--()
pre-decrement (–it)
Definition: json.hpp:6519
const_iterator cend() const
returns a const iterator to one past the last element
Definition: json.hpp:4164
string_t dump(const int indent=-1) const
serialization
Definition: json.hpp:2068
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:4698
iterator begin()
returns an iterator to the first element
Definition: json.hpp:4053
difference_type operator-(const const_iterator &other) const
return difference
Definition: json.hpp:6682
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:4063
friend std::ostream & operator>>(const basic_json &j, std::ostream &o)
serialize to stream
Definition: json.hpp:5551
difference_type operator-(const iterator &other) const
return difference
Definition: json.hpp:6886
basic_json(const int val)
create an integer number from an enum type (explicit)
Definition: json.hpp:1280
iterator(const iterator &other) noexcept
copy constructor
Definition: json.hpp:6797
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:6248
void swap(string_t &other)
exchanges the values
Definition: json.hpp:5080
json_reverse_iterator(const base_iterator &it)
create reverse iterator from base class
Definition: json.hpp:6936
basic_json(const number_integer_t val)
create an integer number (explicit)
Definition: json.hpp:1251
reverse_iterator rend()
returns an iterator to the reverse-end
Definition: json.hpp:4231
basic_json(const CompatibleNumberIntegerType val) noexcept
create an integer number (implicit)
Definition: json.hpp:1317
const_reference front() const
access the first element
Definition: json.hpp:3583
bool operator>(const const_iterator &other) const
comparison: greater than
Definition: json.hpp:6620
bool is_object() const noexcept
return whether value is an object
Definition: json.hpp:2310
pointer operator->() const
dereference the iterator
Definition: json.hpp:6439
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:4981
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:4239
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:2126
ValueType get() const
get a value (explicit)
Definition: json.hpp:2741
void swap(array_t &other)
exchanges the values
Definition: json.hpp:5012
InteratorType erase(InteratorType first, InteratorType last)
remove elements given an iterator range
Definition: json.hpp:3793
ValueType value(const typename object_t::key_type &key, ValueType default_value) const
access specified object element with default value
Definition: json.hpp:3520
typename Base::reference reference
the reference type for the pointed-to element
Definition: json.hpp:6928
const_reference back() const
access the last element
Definition: json.hpp:3627
void push_back(basic_json &&val)
add an object to an array
Definition: json.hpp:4638
array (ordered collection of values)
json_reverse_iterator & operator++()
pre-increment (++it)
Definition: json.hpp:6947
static basic_json parse(std::istream &i, parser_callback_t cb=nullptr)
deserialize from stream
Definition: json.hpp:5619
friend bool operator==(const_reference lhs, const_reference rhs) noexcept
comparison: equal
Definition: json.hpp:5161
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:3546
ReferenceType get_ref() const
get a reference value (implicit)
Definition: json.hpp:2891
basic_json(const CompatibleNumberUnsignedType val) noexcept
create an unsigned number (implicit)
Definition: json.hpp:1376
const_iterator(pointer object)
constructor for a given JSON instance
Definition: json.hpp:6260
reference operator*() const
return a reference to the value pointed to by the iterator
Definition: json.hpp:6399
friend bool operator<(const value_t lhs, const value_t rhs)
comparison operator for JSON types
Definition: json.hpp:5114
const PointerType get_ptr() const noexcept
get a pointer value (implicit)
Definition: json.hpp:2840
friend bool operator!=(const_reference v, std::nullptr_t) noexcept
comparison: not equal
Definition: json.hpp:5313
iterator operator+(difference_type i)
add to iterator
Definition: json.hpp:6870
basic_json(const CompatibleNumberFloatType val) noexcept
create an floating-point number (implicit)
Definition: json.hpp:1451
bool operator<=(const const_iterator &other) const
comparison: less than or equal
Definition: json.hpp:6614
InteratorType erase(InteratorType pos)
remove element given an iterator
Definition: json.hpp:3685
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:1524
iterator(pointer object) noexcept
constructor for a given JSON instance
Definition: json.hpp:6792
friend bool operator!=(std::nullptr_t, const_reference v) noexcept
comparison: not equal
Definition: json.hpp:5322
json_reverse_iterator(const typename base_iterator::iterator_type &it)
create reverse iterator from iterator
Definition: json.hpp:6931
const_iterator & operator++()
pre-increment (++it)
Definition: json.hpp:6482
bool is_number_float() const noexcept
return whether value is a floating-point number
Definition: json.hpp:2291
reference value() const
return the value of an iterator
Definition: json.hpp:6757
std::bidirectional_iterator_tag iterator_category
the category of the iterator
Definition: json.hpp:6254
difference_type operator-(const json_reverse_iterator &other) const
return difference
Definition: json.hpp:6990
const_iterator find(typename object_t::key_type key) const
find an element in a JSON object
Definition: json.hpp:3981
basic_json(const CompatibleObjectType &val)
create an object (implicit)
Definition: json.hpp:1049
friend bool operator>(const_reference lhs, const_reference rhs) noexcept
comparison: greater than
Definition: json.hpp:5474
bool operator>=(const const_iterator &other) const
comparison: greater than or equal
Definition: json.hpp:6626
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:6319
size_type erase(const typename object_t::key_type &key)
remove element from a JSON object given a key
Definition: json.hpp:3880
reference operator[](const typename object_t::key_type &key)
access specified object element
Definition: json.hpp:3245
object_t::key_type key() const
return the key of an object iterator
Definition: json.hpp:6742
const_iterator end() const
returns a const iterator to one past the last element
Definition: json.hpp:4134
reference operator+=(basic_json &&val)
add an object to an array
Definition: json.hpp:4664
reference operator[](difference_type n) const
access to successor
Definition: json.hpp:6706
a const random access iterator for the basic_json class
Definition: json.hpp:6239
a template for a reverse iterator class
Definition: json.hpp:212
basic_json(std::istream &i, parser_callback_t cb=nullptr)
construct a JSON value given an input stream
Definition: json.hpp:1833
typename basic_json::const_reference reference
defines a reference to the type iterated over (value_type)
Definition: json.hpp:6252
json_reverse_iterator operator++(int)
post-increment (it++)
Definition: json.hpp:6941
friend bool operator==(const_reference v, std::nullptr_t) noexcept
comparison: equal
Definition: json.hpp:5260
reference operator[](size_type idx)
access specified array element
Definition: json.hpp:3158
bool operator!=(const const_iterator &other) const
comparison: not equal
Definition: json.hpp:6578
json_reverse_iterator & operator+=(difference_type i)
add to iterator
Definition: json.hpp:6967
reference at(size_type idx)
access specified array element with bounds checking
Definition: json.hpp:2971
size_type size() const noexcept
returns the number of elements
Definition: json.hpp:4437
static iteration_proxy< iterator > iterator_wrapper(reference cont)
wrapper to access iterator member functions in range-based for
Definition: json.hpp:4318
const_iterator cbegin() const
returns a const iterator to the first element
Definition: json.hpp:4093
iterator & operator-=(difference_type i)
subtract from iterator
Definition: json.hpp:6863
const_reverse_iterator crend() const
returns a const reverse iterator to one before the first
Definition: json.hpp:4297
basic_json(const object_t &val)
create an object (explicit)
Definition: json.hpp:1014
friend std::istream & operator<<(basic_json &j, std::istream &i)
deserialize from stream
Definition: json.hpp:5655
std::size_t operator()(const nlohmann::json &j) const
return a hash value for a JSON object
Definition: json.hpp:8657
friend std::ostream & operator<<(std::ostream &o, const basic_json &j)
serialize to stream
Definition: json.hpp:5533
const_iterator(const const_iterator &other) noexcept
copy constructor
Definition: json.hpp:6314
iterator & operator--()
pre-decrement (–it)
Definition: json.hpp:6849
iterator insert(const_iterator pos, basic_json &&val)
inserts element
Definition: json.hpp:4803
ReferenceType get_ref()
get a reference value (implicit)
Definition: json.hpp:2876
const_iterator & operator-=(difference_type i)
subtract from iterator
Definition: json.hpp:6660
basic_json(const CompatibleStringType &val)
create a string (implicit)
Definition: json.hpp:1200
basic_json(const basic_json &other)
copy constructor
Definition: json.hpp:1864
reference operator[](T *key)
access specified object element
Definition: json.hpp:3404
parse_event_t
JSON callback events.
Definition: json.hpp:831