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 to object
3161  if (is_null())
3162  {
3163  m_type = value_t::array;
3164  m_value.array = create<array_t>();
3165  }
3166 
3167  // [] only works for arrays
3168  if (is_array())
3169  {
3170  assert(m_value.array != nullptr);
3171  for (size_t i = m_value.array->size(); i <= idx; ++i)
3172  {
3173  m_value.array->push_back(basic_json());
3174  }
3175 
3176  return m_value.array->operator[](idx);
3177  }
3178  else
3179  {
3180  throw std::domain_error("cannot use operator[] with " + type_name());
3181  }
3182  }
3183 
3204  {
3205  // at only works for arrays
3206  if (is_array())
3207  {
3208  assert(m_value.array != nullptr);
3209  return m_value.array->operator[](idx);
3210  }
3211  else
3212  {
3213  throw std::domain_error("cannot use operator[] with " + type_name());
3214  }
3215  }
3216 
3244  reference operator[](const typename object_t::key_type& key)
3245  {
3246  // implicitly convert null to object
3247  if (is_null())
3248  {
3249  m_type = value_t::object;
3250  m_value.object = create<object_t>();
3251  }
3252 
3253  // [] only works for objects
3254  if (is_object())
3255  {
3256  assert(m_value.object != nullptr);
3257  return m_value.object->operator[](key);
3258  }
3259  else
3260  {
3261  throw std::domain_error("cannot use operator[] with " + type_name());
3262  }
3263  }
3264 
3292  const_reference operator[](const typename object_t::key_type& key) const
3293  {
3294  // [] only works for objects
3295  if (is_object())
3296  {
3297  assert(m_value.object != nullptr);
3298  assert(m_value.object->find(key) != m_value.object->end());
3299  return m_value.object->find(key)->second;
3300  }
3301  else
3302  {
3303  throw std::domain_error("cannot use operator[] with " + type_name());
3304  }
3305  }
3306 
3334  template<typename T, std::size_t n>
3335  reference operator[](T * (&key)[n])
3336  {
3337  return operator[](static_cast<const T>(key));
3338  }
3339 
3369  template<typename T, std::size_t n>
3370  const_reference operator[](T * (&key)[n]) const
3371  {
3372  return operator[](static_cast<const T>(key));
3373  }
3374 
3402  template<typename T>
3404  {
3405  // implicitly convert null to object
3406  if (is_null())
3407  {
3408  m_type = value_t::object;
3409  m_value = value_t::object;
3410  }
3411 
3412  // at only works for objects
3413  if (is_object())
3414  {
3415  assert(m_value.object != nullptr);
3416  return m_value.object->operator[](key);
3417  }
3418  else
3419  {
3420  throw std::domain_error("cannot use operator[] with " + type_name());
3421  }
3422  }
3423 
3451  template<typename T>
3453  {
3454  // at only works for objects
3455  if (is_object())
3456  {
3457  assert(m_value.object != nullptr);
3458  assert(m_value.object->find(key) != m_value.object->end());
3459  return m_value.object->find(key)->second;
3460  }
3461  else
3462  {
3463  throw std::domain_error("cannot use operator[] with " + type_name());
3464  }
3465  }
3466 
3515  template <class ValueType, typename
3516  std::enable_if<
3517  std::is_convertible<basic_json_t, ValueType>::value
3518  , int>::type = 0>
3519  ValueType value(const typename object_t::key_type& key, ValueType default_value) const
3520  {
3521  // at only works for objects
3522  if (is_object())
3523  {
3524  // if key is found, return value and given default value otherwise
3525  const auto it = find(key);
3526  if (it != end())
3527  {
3528  return *it;
3529  }
3530  else
3531  {
3532  return default_value;
3533  }
3534  }
3535  else
3536  {
3537  throw std::domain_error("cannot use value() with " + type_name());
3538  }
3539  }
3540 
3545  string_t value(const typename object_t::key_type& key, const char* default_value) const
3546  {
3547  return value(key, string_t(default_value));
3548  }
3549 
3575  {
3576  return *begin();
3577  }
3578 
3583  {
3584  return *cbegin();
3585  }
3586 
3613  {
3614  auto tmp = end();
3615  --tmp;
3616  return *tmp;
3617  }
3618 
3623  {
3624  auto tmp = cend();
3625  --tmp;
3626  return *tmp;
3627  }
3628 
3673  template <class InteratorType, typename
3674  std::enable_if<
3675  std::is_same<InteratorType, typename basic_json_t::iterator>::value or
3676  std::is_same<InteratorType, typename basic_json_t::const_iterator>::value
3677  , int>::type
3678  = 0>
3679  InteratorType erase(InteratorType pos)
3680  {
3681  // make sure iterator fits the current value
3682  if (this != pos.m_object)
3683  {
3684  throw std::domain_error("iterator does not fit current value");
3685  }
3686 
3687  InteratorType result = end();
3688 
3689  switch (m_type)
3690  {
3691  case value_t::boolean:
3692  case value_t::number_float:
3693  case value_t::number_integer:
3694  case value_t::number_unsigned:
3695  case value_t::string:
3696  {
3697  if (not pos.m_it.primitive_iterator.is_begin())
3698  {
3699  throw std::out_of_range("iterator out of range");
3700  }
3701 
3702  if (is_string())
3703  {
3704  delete m_value.string;
3705  m_value.string = nullptr;
3706  }
3707 
3708  m_type = value_t::null;
3709  break;
3710  }
3711 
3712  case value_t::object:
3713  {
3714  assert(m_value.object != nullptr);
3715  result.m_it.object_iterator = m_value.object->erase(pos.m_it.object_iterator);
3716  break;
3717  }
3718 
3719  case value_t::array:
3720  {
3721  assert(m_value.array != nullptr);
3722  result.m_it.array_iterator = m_value.array->erase(pos.m_it.array_iterator);
3723  break;
3724  }
3725 
3726  default:
3727  {
3728  throw std::domain_error("cannot use erase() with " + type_name());
3729  }
3730  }
3731 
3732  return result;
3733  }
3734 
3779  template <class InteratorType, typename
3780  std::enable_if<
3781  std::is_same<InteratorType, typename basic_json_t::iterator>::value or
3782  std::is_same<InteratorType, typename basic_json_t::const_iterator>::value
3783  , int>::type
3784  = 0>
3785  InteratorType erase(InteratorType first, InteratorType last)
3786  {
3787  // make sure iterator fits the current value
3788  if (this != first.m_object or this != last.m_object)
3789  {
3790  throw std::domain_error("iterators do not fit current value");
3791  }
3792 
3793  InteratorType result = end();
3794 
3795  switch (m_type)
3796  {
3797  case value_t::boolean:
3798  case value_t::number_float:
3799  case value_t::number_integer:
3800  case value_t::number_unsigned:
3801  case value_t::string:
3802  {
3803  if (not first.m_it.primitive_iterator.is_begin() or not last.m_it.primitive_iterator.is_end())
3804  {
3805  throw std::out_of_range("iterators out of range");
3806  }
3807 
3808  if (is_string())
3809  {
3810  delete m_value.string;
3811  m_value.string = nullptr;
3812  }
3813 
3814  m_type = value_t::null;
3815  break;
3816  }
3817 
3818  case value_t::object:
3819  {
3820  assert(m_value.object != nullptr);
3821  result.m_it.object_iterator = m_value.object->erase(first.m_it.object_iterator,
3822  last.m_it.object_iterator);
3823  break;
3824  }
3825 
3826  case value_t::array:
3827  {
3828  assert(m_value.array != nullptr);
3829  result.m_it.array_iterator = m_value.array->erase(first.m_it.array_iterator,
3830  last.m_it.array_iterator);
3831  break;
3832  }
3833 
3834  default:
3835  {
3836  throw std::domain_error("cannot use erase() with " + type_name());
3837  }
3838  }
3839 
3840  return result;
3841  }
3842 
3869  size_type erase(const typename object_t::key_type& key)
3870  {
3871  // this erase only works for objects
3872  if (is_object())
3873  {
3874  assert(m_value.object != nullptr);
3875  return m_value.object->erase(key);
3876  }
3877  else
3878  {
3879  throw std::domain_error("cannot use erase() with " + type_name());
3880  }
3881  }
3882 
3907  void erase(const size_type idx)
3908  {
3909  // this erase only works for arrays
3910  if (is_array())
3911  {
3912  if (idx >= size())
3913  {
3914  throw std::out_of_range("index out of range");
3915  }
3916 
3917  assert(m_value.array != nullptr);
3918  m_value.array->erase(m_value.array->begin() + static_cast<difference_type>(idx));
3919  }
3920  else
3921  {
3922  throw std::domain_error("cannot use erase() with " + type_name());
3923  }
3924  }
3925 
3943  iterator find(typename object_t::key_type key)
3944  {
3945  auto result = end();
3946 
3947  if (is_object())
3948  {
3949  assert(m_value.object != nullptr);
3950  result.m_it.object_iterator = m_value.object->find(key);
3951  }
3952 
3953  return result;
3954  }
3955 
3960  const_iterator find(typename object_t::key_type key) const
3961  {
3962  auto result = cend();
3963 
3964  if (is_object())
3965  {
3966  assert(m_value.object != nullptr);
3967  result.m_it.object_iterator = m_value.object->find(key);
3968  }
3969 
3970  return result;
3971  }
3972 
3991  size_type count(typename object_t::key_type key) const
3992  {
3993  // return 0 for all nonobject types
3994  assert(not is_object() or m_value.object != nullptr);
3995  return is_object() ? m_value.object->count(key) : 0;
3996  }
3997 
3999 
4000 
4002  // iterators //
4004 
4007 
4033  {
4034  iterator result(this);
4035  result.set_begin();
4036  return result;
4037  }
4038 
4043  {
4044  return cbegin();
4045  }
4046 
4073  {
4074  const_iterator result(this);
4075  result.set_begin();
4076  return result;
4077  }
4078 
4104  {
4105  iterator result(this);
4106  result.set_end();
4107  return result;
4108  }
4109 
4114  {
4115  return cend();
4116  }
4117 
4144  {
4145  const_iterator result(this);
4146  result.set_end();
4147  return result;
4148  }
4149 
4174  {
4175  return reverse_iterator(end());
4176  }
4177 
4182  {
4183  return crbegin();
4184  }
4185 
4211  {
4212  return reverse_iterator(begin());
4213  }
4214 
4219  {
4220  return crend();
4221  }
4222 
4248  {
4249  return const_reverse_iterator(cend());
4250  }
4251 
4277  {
4278  return const_reverse_iterator(cbegin());
4279  }
4280 
4281  private:
4282  // forward declaration
4283  template<typename IteratorType> class iteration_proxy;
4284 
4285  public:
4297  static iteration_proxy<iterator> iterator_wrapper(reference cont)
4298  {
4299  return iteration_proxy<iterator>(cont);
4300  }
4301 
4305  static iteration_proxy<const_iterator> iterator_wrapper(const_reference cont)
4306  {
4307  return iteration_proxy<const_iterator>(cont);
4308  }
4309 
4311 
4312 
4314  // capacity //
4316 
4319 
4353  bool empty() const noexcept
4354  {
4355  switch (m_type)
4356  {
4357  case value_t::null:
4358  {
4359  // null values are empty
4360  return true;
4361  }
4362 
4363  case value_t::array:
4364  {
4365  assert(m_value.array != nullptr);
4366  return m_value.array->empty();
4367  }
4368 
4369  case value_t::object:
4370  {
4371  assert(m_value.object != nullptr);
4372  return m_value.object->empty();
4373  }
4374 
4375  default:
4376  {
4377  // all other types are nonempty
4378  return false;
4379  }
4380  }
4381  }
4382 
4416  size_type size() const noexcept
4417  {
4418  switch (m_type)
4419  {
4420  case value_t::null:
4421  {
4422  // null values are empty
4423  return 0;
4424  }
4425 
4426  case value_t::array:
4427  {
4428  assert(m_value.array != nullptr);
4429  return m_value.array->size();
4430  }
4431 
4432  case value_t::object:
4433  {
4434  assert(m_value.object != nullptr);
4435  return m_value.object->size();
4436  }
4437 
4438  default:
4439  {
4440  // all other types have size 1
4441  return 1;
4442  }
4443  }
4444  }
4445 
4482  size_type max_size() const noexcept
4483  {
4484  switch (m_type)
4485  {
4486  case value_t::array:
4487  {
4488  assert(m_value.array != nullptr);
4489  return m_value.array->max_size();
4490  }
4491 
4492  case value_t::object:
4493  {
4494  assert(m_value.object != nullptr);
4495  return m_value.object->max_size();
4496  }
4497 
4498  default:
4499  {
4500  // all other types have max_size() == size()
4501  return size();
4502  }
4503  }
4504  }
4505 
4507 
4508 
4510  // modifiers //
4512 
4515 
4541  void clear() noexcept
4542  {
4543  switch (m_type)
4544  {
4545  case value_t::number_integer:
4546  {
4547  m_value.number_integer = 0;
4548  break;
4549  }
4550 
4551  case value_t::number_unsigned:
4552  {
4553  m_value.number_unsigned = 0;
4554  break;
4555  }
4556 
4557  case value_t::number_float:
4558  {
4559  m_value.number_float = 0.0;
4560  break;
4561  }
4562 
4563  case value_t::boolean:
4564  {
4565  m_value.boolean = false;
4566  break;
4567  }
4568 
4569  case value_t::string:
4570  {
4571  assert(m_value.string != nullptr);
4572  m_value.string->clear();
4573  break;
4574  }
4575 
4576  case value_t::array:
4577  {
4578  assert(m_value.array != nullptr);
4579  m_value.array->clear();
4580  break;
4581  }
4582 
4583  case value_t::object:
4584  {
4585  assert(m_value.object != nullptr);
4586  m_value.object->clear();
4587  break;
4588  }
4589 
4590  default:
4591  {
4592  break;
4593  }
4594  }
4595  }
4596 
4617  void push_back(basic_json&& val)
4618  {
4619  // push_back only works for null objects or arrays
4620  if (not(is_null() or is_array()))
4621  {
4622  throw std::domain_error("cannot use push_back() with " + type_name());
4623  }
4624 
4625  // transform null object into an array
4626  if (is_null())
4627  {
4628  m_type = value_t::array;
4629  m_value = value_t::array;
4630  }
4631 
4632  // add element to array (move semantics)
4633  assert(m_value.array != nullptr);
4634  m_value.array->push_back(std::move(val));
4635  // invalidate object
4636  val.m_type = value_t::null;
4637  }
4638 
4643  reference operator+=(basic_json&& val)
4644  {
4645  push_back(std::move(val));
4646  return *this;
4647  }
4648 
4653  void push_back(const basic_json& val)
4654  {
4655  // push_back only works for null objects or arrays
4656  if (not(is_null() or is_array()))
4657  {
4658  throw std::domain_error("cannot use push_back() with " + type_name());
4659  }
4660 
4661  // transform null object into an array
4662  if (is_null())
4663  {
4664  m_type = value_t::array;
4665  m_value = value_t::array;
4666  }
4667 
4668  // add element to array
4669  assert(m_value.array != nullptr);
4670  m_value.array->push_back(val);
4671  }
4672 
4677  reference operator+=(const basic_json& val)
4678  {
4679  push_back(val);
4680  return *this;
4681  }
4682 
4703  void push_back(const typename object_t::value_type& val)
4704  {
4705  // push_back only works for null objects or objects
4706  if (not(is_null() or is_object()))
4707  {
4708  throw std::domain_error("cannot use push_back() with " + type_name());
4709  }
4710 
4711  // transform null object into an object
4712  if (is_null())
4713  {
4714  m_type = value_t::object;
4715  m_value = value_t::object;
4716  }
4717 
4718  // add element to array
4719  assert(m_value.object != nullptr);
4720  m_value.object->insert(val);
4721  }
4722 
4727  reference operator+=(const typename object_t::value_type& val)
4728  {
4729  push_back(val);
4730  return operator[](val.first);
4731  }
4732 
4755  iterator insert(const_iterator pos, const basic_json& val)
4756  {
4757  // insert only works for arrays
4758  if (is_array())
4759  {
4760  // check if iterator pos fits to this JSON value
4761  if (pos.m_object != this)
4762  {
4763  throw std::domain_error("iterator does not fit current value");
4764  }
4765 
4766  // insert to array and return iterator
4767  iterator result(this);
4768  assert(m_value.array != nullptr);
4769  result.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator, val);
4770  return result;
4771  }
4772  else
4773  {
4774  throw std::domain_error("cannot use insert() with " + type_name());
4775  }
4776  }
4777 
4782  iterator insert(const_iterator pos, basic_json&& val)
4783  {
4784  return insert(pos, val);
4785  }
4786 
4811  iterator insert(const_iterator pos, size_type cnt, const basic_json& val)
4812  {
4813  // insert only works for arrays
4814  if (is_array())
4815  {
4816  // check if iterator pos fits to this JSON value
4817  if (pos.m_object != this)
4818  {
4819  throw std::domain_error("iterator does not fit current value");
4820  }
4821 
4822  // insert to array and return iterator
4823  iterator result(this);
4824  assert(m_value.array != nullptr);
4825  result.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator, cnt, val);
4826  return result;
4827  }
4828  else
4829  {
4830  throw std::domain_error("cannot use insert() with " + type_name());
4831  }
4832  }
4833 
4865  {
4866  // insert only works for arrays
4867  if (not is_array())
4868  {
4869  throw std::domain_error("cannot use insert() with " + type_name());
4870  }
4871 
4872  // check if iterator pos fits to this JSON value
4873  if (pos.m_object != this)
4874  {
4875  throw std::domain_error("iterator does not fit current value");
4876  }
4877 
4878  if (first.m_object != last.m_object)
4879  {
4880  throw std::domain_error("iterators do not fit");
4881  }
4882 
4883  if (first.m_object == this or last.m_object == this)
4884  {
4885  throw std::domain_error("passed iterators may not belong to container");
4886  }
4887 
4888  // insert to array and return iterator
4889  iterator result(this);
4890  assert(m_value.array != nullptr);
4891  result.m_it.array_iterator = m_value.array->insert(
4892  pos.m_it.array_iterator,
4893  first.m_it.array_iterator,
4894  last.m_it.array_iterator);
4895  return result;
4896  }
4897 
4922  iterator insert(const_iterator pos, std::initializer_list<basic_json> ilist)
4923  {
4924  // insert only works for arrays
4925  if (not is_array())
4926  {
4927  throw std::domain_error("cannot use insert() with " + type_name());
4928  }
4929 
4930  // check if iterator pos fits to this JSON value
4931  if (pos.m_object != this)
4932  {
4933  throw std::domain_error("iterator does not fit current value");
4934  }
4935 
4936  // insert to array and return iterator
4937  iterator result(this);
4938  assert(m_value.array != nullptr);
4939  result.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator, ilist);
4940  return result;
4941  }
4942 
4960  void swap(reference other) noexcept (
4961  std::is_nothrow_move_constructible<value_t>::value and
4962  std::is_nothrow_move_assignable<value_t>::value and
4963  std::is_nothrow_move_constructible<json_value>::value and
4964  std::is_nothrow_move_assignable<json_value>::value
4965  )
4966  {
4967  std::swap(m_type, other.m_type);
4968  std::swap(m_value, other.m_value);
4969  }
4970 
4991  void swap(array_t& other)
4992  {
4993  // swap only works for arrays
4994  if (is_array())
4995  {
4996  assert(m_value.array != nullptr);
4997  std::swap(*(m_value.array), other);
4998  }
4999  else
5000  {
5001  throw std::domain_error("cannot use swap() with " + type_name());
5002  }
5003  }
5004 
5025  void swap(object_t& other)
5026  {
5027  // swap only works for objects
5028  if (is_object())
5029  {
5030  assert(m_value.object != nullptr);
5031  std::swap(*(m_value.object), other);
5032  }
5033  else
5034  {
5035  throw std::domain_error("cannot use swap() with " + type_name());
5036  }
5037  }
5038 
5059  void swap(string_t& other)
5060  {
5061  // swap only works for strings
5062  if (is_string())
5063  {
5064  assert(m_value.string != nullptr);
5065  std::swap(*(m_value.string), other);
5066  }
5067  else
5068  {
5069  throw std::domain_error("cannot use swap() with " + type_name());
5070  }
5071  }
5072 
5074 
5075 
5077  // lexicographical comparison operators //
5079 
5082 
5083  private:
5093  friend bool operator<(const value_t lhs, const value_t rhs)
5094  {
5095  static constexpr std::array<uint8_t, 8> order = {{
5096  0, // null
5097  3, // object
5098  4, // array
5099  5, // string
5100  1, // boolean
5101  2, // integer
5102  2, // unsigned
5103  2, // float
5104  }
5105  };
5106 
5107  // discarded values are not comparable
5108  if (lhs == value_t::discarded or rhs == value_t::discarded)
5109  {
5110  return false;
5111  }
5112 
5113  return order[static_cast<std::size_t>(lhs)] < order[static_cast<std::size_t>(rhs)];
5114  }
5115 
5116  public:
5140  friend bool operator==(const_reference lhs, const_reference rhs) noexcept
5141  {
5142  const auto lhs_type = lhs.type();
5143  const auto rhs_type = rhs.type();
5144 
5145  if (lhs_type == rhs_type)
5146  {
5147  switch (lhs_type)
5148  {
5149  case value_t::array:
5150  {
5151  assert(lhs.m_value.array != nullptr);
5152  assert(rhs.m_value.array != nullptr);
5153  return *lhs.m_value.array == *rhs.m_value.array;
5154  }
5155  case value_t::object:
5156  {
5157  assert(lhs.m_value.object != nullptr);
5158  assert(rhs.m_value.object != nullptr);
5159  return *lhs.m_value.object == *rhs.m_value.object;
5160  }
5161  case value_t::null:
5162  {
5163  return true;
5164  }
5165  case value_t::string:
5166  {
5167  assert(lhs.m_value.string != nullptr);
5168  assert(rhs.m_value.string != nullptr);
5169  return *lhs.m_value.string == *rhs.m_value.string;
5170  }
5171  case value_t::boolean:
5172  {
5173  return lhs.m_value.boolean == rhs.m_value.boolean;
5174  }
5175  case value_t::number_integer:
5176  {
5177  return lhs.m_value.number_integer == rhs.m_value.number_integer;
5178  }
5179  case value_t::number_unsigned:
5180  {
5181  return lhs.m_value.number_unsigned == rhs.m_value.number_unsigned;
5182  }
5183  case value_t::number_float:
5184  {
5185  return lhs.m_value.number_float == rhs.m_value.number_float;
5186  }
5187  default:
5188  {
5189  return false;
5190  }
5191  }
5192  }
5193  else if (lhs_type == value_t::number_integer and rhs_type == value_t::number_float)
5194  {
5195  return static_cast<number_float_t>(lhs.m_value.number_integer) == rhs.m_value.number_float;
5196  }
5197  else if (lhs_type == value_t::number_float and rhs_type == value_t::number_integer)
5198  {
5199  return lhs.m_value.number_float == static_cast<number_float_t>(rhs.m_value.number_integer);
5200  }
5201  else if (lhs_type == value_t::number_unsigned and rhs_type == value_t::number_float)
5202  {
5203  return static_cast<number_float_t>(lhs.m_value.number_unsigned) == rhs.m_value.number_float;
5204  }
5205  else if (lhs_type == value_t::number_float and rhs_type == value_t::number_unsigned)
5206  {
5207  return lhs.m_value.number_float == static_cast<number_float_t>(rhs.m_value.number_unsigned);
5208  }
5209  else if (lhs_type == value_t::number_unsigned and rhs_type == value_t::number_integer)
5210  {
5211  return static_cast<number_integer_t>(lhs.m_value.number_unsigned) == rhs.m_value.number_integer;
5212  }
5213  else if (lhs_type == value_t::number_integer and rhs_type == value_t::number_unsigned)
5214  {
5215  return lhs.m_value.number_integer == static_cast<number_integer_t>(rhs.m_value.number_unsigned);
5216  }
5217 
5218  return false;
5219  }
5220 
5239  friend bool operator==(const_reference v, std::nullptr_t) noexcept
5240  {
5241  return v.is_null();
5242  }
5243 
5248  friend bool operator==(std::nullptr_t, const_reference v) noexcept
5249  {
5250  return v.is_null();
5251  }
5252 
5269  friend bool operator!=(const_reference lhs, const_reference rhs) noexcept
5270  {
5271  return not (lhs == rhs);
5272  }
5273 
5292  friend bool operator!=(const_reference v, std::nullptr_t) noexcept
5293  {
5294  return not v.is_null();
5295  }
5296 
5301  friend bool operator!=(std::nullptr_t, const_reference v) noexcept
5302  {
5303  return not v.is_null();
5304  }
5305 
5330  friend bool operator<(const_reference lhs, const_reference rhs) noexcept
5331  {
5332  const auto lhs_type = lhs.type();
5333  const auto rhs_type = rhs.type();
5334 
5335  if (lhs_type == rhs_type)
5336  {
5337  switch (lhs_type)
5338  {
5339  case value_t::array:
5340  {
5341  assert(lhs.m_value.array != nullptr);
5342  assert(rhs.m_value.array != nullptr);
5343  return *lhs.m_value.array < *rhs.m_value.array;
5344  }
5345  case value_t::object:
5346  {
5347  assert(lhs.m_value.object != nullptr);
5348  assert(rhs.m_value.object != nullptr);
5349  return *lhs.m_value.object < *rhs.m_value.object;
5350  }
5351  case value_t::null:
5352  {
5353  return false;
5354  }
5355  case value_t::string:
5356  {
5357  assert(lhs.m_value.string != nullptr);
5358  assert(rhs.m_value.string != nullptr);
5359  return *lhs.m_value.string < *rhs.m_value.string;
5360  }
5361  case value_t::boolean:
5362  {
5363  return lhs.m_value.boolean < rhs.m_value.boolean;
5364  }
5365  case value_t::number_integer:
5366  {
5367  return lhs.m_value.number_integer < rhs.m_value.number_integer;
5368  }
5369  case value_t::number_unsigned:
5370  {
5371  return lhs.m_value.number_unsigned < rhs.m_value.number_unsigned;
5372  }
5373  case value_t::number_float:
5374  {
5375  return lhs.m_value.number_float < rhs.m_value.number_float;
5376  }
5377  default:
5378  {
5379  return false;
5380  }
5381  }
5382  }
5383  else if (lhs_type == value_t::number_integer and rhs_type == value_t::number_float)
5384  {
5385  return static_cast<number_float_t>(lhs.m_value.number_integer) < rhs.m_value.number_float;
5386  }
5387  else if (lhs_type == value_t::number_float and rhs_type == value_t::number_integer)
5388  {
5389  return lhs.m_value.number_float < static_cast<number_float_t>(rhs.m_value.number_integer);
5390  }
5391  else if (lhs_type == value_t::number_unsigned and rhs_type == value_t::number_float)
5392  {
5393  return static_cast<number_float_t>(lhs.m_value.number_unsigned) < rhs.m_value.number_float;
5394  }
5395  else if (lhs_type == value_t::number_float and rhs_type == value_t::number_unsigned)
5396  {
5397  return lhs.m_value.number_float < static_cast<number_float_t>(rhs.m_value.number_unsigned);
5398  }
5399  else if (lhs_type == value_t::number_integer and rhs_type == value_t::number_unsigned)
5400  {
5401  return lhs.m_value.number_integer < static_cast<number_integer_t>(rhs.m_value.number_unsigned);
5402  }
5403  else if (lhs_type == value_t::number_unsigned and rhs_type == value_t::number_integer)
5404  {
5405  return static_cast<number_integer_t>(lhs.m_value.number_unsigned) < rhs.m_value.number_integer;
5406  }
5407 
5408  // We only reach this line if we cannot compare values. In that case,
5409  // we compare types. Note we have to call the operator explicitly,
5410  // because MSVC has problems otherwise.
5411  return operator<(lhs_type, rhs_type);
5412  }
5413 
5431  friend bool operator<=(const_reference lhs, const_reference rhs) noexcept
5432  {
5433  return not (rhs < lhs);
5434  }
5435 
5453  friend bool operator>(const_reference lhs, const_reference rhs) noexcept
5454  {
5455  return not (lhs <= rhs);
5456  }
5457 
5475  friend bool operator>=(const_reference lhs, const_reference rhs) noexcept
5476  {
5477  return not (lhs < rhs);
5478  }
5479 
5481 
5482 
5484  // serialization //
5486 
5489 
5512  friend std::ostream& operator<<(std::ostream& o, const basic_json& j)
5513  {
5514  // read width member and use it as indentation parameter if nonzero
5515  const bool pretty_print = (o.width() > 0);
5516  const auto indentation = (pretty_print ? o.width() : 0);
5517 
5518  // reset width to 0 for subsequent calls to this stream
5519  o.width(0);
5520 
5521  // do the actual serialization
5522  j.dump(o, pretty_print, static_cast<unsigned int>(indentation));
5523  return o;
5524  }
5525 
5530  friend std::ostream& operator>>(const basic_json& j, std::ostream& o)
5531  {
5532  return o << j;
5533  }
5534 
5536 
5537 
5539  // deserialization //
5541 
5544 
5569  static basic_json parse(const string_t& s, parser_callback_t cb = nullptr)
5570  {
5571  return parser(s, cb).parse();
5572  }
5573 
5598  static basic_json parse(std::istream& i, parser_callback_t cb = nullptr)
5599  {
5600  return parser(i, cb).parse();
5601  }
5602 
5606  static basic_json parse(std::istream&& i, parser_callback_t cb = nullptr)
5607  {
5608  return parser(i, cb).parse();
5609  }
5610 
5634  friend std::istream& operator<<(basic_json& j, std::istream& i)
5635  {
5636  j = parser(i).parse();
5637  return i;
5638  }
5639 
5644  friend std::istream& operator>>(std::istream& i, basic_json& j)
5645  {
5646  j = parser(i).parse();
5647  return i;
5648  }
5649 
5651 
5652 
5653  private:
5655  // convenience functions //
5657 
5659  string_t type_name() const
5660  {
5661  switch (m_type)
5662  {
5663  case value_t::null:
5664  return "null";
5665  case value_t::object:
5666  return "object";
5667  case value_t::array:
5668  return "array";
5669  case value_t::string:
5670  return "string";
5671  case value_t::boolean:
5672  return "boolean";
5673  case value_t::discarded:
5674  return "discarded";
5675  default:
5676  return "number";
5677  }
5678  }
5679 
5688  static std::size_t extra_space(const string_t& s) noexcept
5689  {
5690  std::size_t result = 0;
5691 
5692  for (const auto& c : s)
5693  {
5694  switch (c)
5695  {
5696  case '"':
5697  case '\\':
5698  case '\b':
5699  case '\f':
5700  case '\n':
5701  case '\r':
5702  case '\t':
5703  {
5704  // from c (1 byte) to \x (2 bytes)
5705  result += 1;
5706  break;
5707  }
5708 
5709  default:
5710  {
5711  if (c >= 0x00 and c <= 0x1f)
5712  {
5713  // from c (1 byte) to \uxxxx (6 bytes)
5714  result += 5;
5715  }
5716  break;
5717  }
5718  }
5719  }
5720 
5721  return result;
5722  }
5723 
5737  static string_t escape_string(const string_t& s) noexcept
5738  {
5739  const auto space = extra_space(s);
5740  if (space == 0)
5741  {
5742  return s;
5743  }
5744 
5745  // create a result string of necessary size
5746  string_t result(s.size() + space, '\\');
5747  std::size_t pos = 0;
5748 
5749  for (const auto& c : s)
5750  {
5751  switch (c)
5752  {
5753  // quotation mark (0x22)
5754  case '"':
5755  {
5756  result[pos + 1] = '"';
5757  pos += 2;
5758  break;
5759  }
5760 
5761  // reverse solidus (0x5c)
5762  case '\\':
5763  {
5764  // nothing to change
5765  pos += 2;
5766  break;
5767  }
5768 
5769  // backspace (0x08)
5770  case '\b':
5771  {
5772  result[pos + 1] = 'b';
5773  pos += 2;
5774  break;
5775  }
5776 
5777  // formfeed (0x0c)
5778  case '\f':
5779  {
5780  result[pos + 1] = 'f';
5781  pos += 2;
5782  break;
5783  }
5784 
5785  // newline (0x0a)
5786  case '\n':
5787  {
5788  result[pos + 1] = 'n';
5789  pos += 2;
5790  break;
5791  }
5792 
5793  // carriage return (0x0d)
5794  case '\r':
5795  {
5796  result[pos + 1] = 'r';
5797  pos += 2;
5798  break;
5799  }
5800 
5801  // horizontal tab (0x09)
5802  case '\t':
5803  {
5804  result[pos + 1] = 't';
5805  pos += 2;
5806  break;
5807  }
5808 
5809  default:
5810  {
5811  if (c >= 0x00 and c <= 0x1f)
5812  {
5813  // convert a number 0..15 to its hex representation
5814  // (0..f)
5815  auto hexify = [](const char v) -> char
5816  {
5817  return (v < 10) ? ('0' + v) : ('a' + v - 10);
5818  };
5819 
5820  // print character c as \uxxxx
5821  for (const char m :
5822  { 'u', '0', '0', hexify(c >> 4), hexify(c & 0x0f)
5823  })
5824  {
5825  result[++pos] = m;
5826  }
5827 
5828  ++pos;
5829  }
5830  else
5831  {
5832  // all other characters are added as-is
5833  result[pos++] = c;
5834  }
5835  break;
5836  }
5837  }
5838  }
5839 
5840  return result;
5841  }
5842 
5860  void dump(std::ostream& o,
5861  const bool pretty_print,
5862  const unsigned int indent_step,
5863  const unsigned int current_indent = 0) const
5864  {
5865  // variable to hold indentation for recursive calls
5866  unsigned int new_indent = current_indent;
5867 
5868  switch (m_type)
5869  {
5870  case value_t::object:
5871  {
5872  assert(m_value.object != nullptr);
5873 
5874  if (m_value.object->empty())
5875  {
5876  o << "{}";
5877  return;
5878  }
5879 
5880  o << "{";
5881 
5882  // increase indentation
5883  if (pretty_print)
5884  {
5885  new_indent += indent_step;
5886  o << "\n";
5887  }
5888 
5889  for (auto i = m_value.object->cbegin(); i != m_value.object->cend(); ++i)
5890  {
5891  if (i != m_value.object->cbegin())
5892  {
5893  o << (pretty_print ? ",\n" : ",");
5894  }
5895  o << string_t(new_indent, ' ') << "\""
5896  << escape_string(i->first) << "\":"
5897  << (pretty_print ? " " : "");
5898  i->second.dump(o, pretty_print, indent_step, new_indent);
5899  }
5900 
5901  // decrease indentation
5902  if (pretty_print)
5903  {
5904  new_indent -= indent_step;
5905  o << "\n";
5906  }
5907 
5908  o << string_t(new_indent, ' ') + "}";
5909  return;
5910  }
5911 
5912  case value_t::array:
5913  {
5914  assert(m_value.array != nullptr);
5915 
5916  if (m_value.array->empty())
5917  {
5918  o << "[]";
5919  return;
5920  }
5921 
5922  o << "[";
5923 
5924  // increase indentation
5925  if (pretty_print)
5926  {
5927  new_indent += indent_step;
5928  o << "\n";
5929  }
5930 
5931  for (auto i = m_value.array->cbegin(); i != m_value.array->cend(); ++i)
5932  {
5933  if (i != m_value.array->cbegin())
5934  {
5935  o << (pretty_print ? ",\n" : ",");
5936  }
5937  o << string_t(new_indent, ' ');
5938  i->dump(o, pretty_print, indent_step, new_indent);
5939  }
5940 
5941  // decrease indentation
5942  if (pretty_print)
5943  {
5944  new_indent -= indent_step;
5945  o << "\n";
5946  }
5947 
5948  o << string_t(new_indent, ' ') << "]";
5949  return;
5950  }
5951 
5952  case value_t::string:
5953  {
5954  assert(m_value.string != nullptr);
5955  o << string_t("\"") << escape_string(*m_value.string) << "\"";
5956  return;
5957  }
5958 
5959  case value_t::boolean:
5960  {
5961  o << (m_value.boolean ? "true" : "false");
5962  return;
5963  }
5964 
5965  case value_t::number_integer:
5966  {
5967  o << m_value.number_integer;
5968  return;
5969  }
5970 
5971  case value_t::number_unsigned:
5972  {
5973  o << m_value.number_unsigned;
5974  return;
5975  }
5976 
5977  case value_t::number_float:
5978  {
5979  // If the number is an integer then output as a fixed with with
5980  // precision 1 to output "0.0", "1.0" etc as expected for some
5981  // round trip tests otherwise 15 digits of precision allows
5982  // round-trip IEEE 754 string->double->string; to be safe, we
5983  // read this value from
5984  // std::numeric_limits<number_float_t>::digits10
5985  if (std::fmod(m_value.number_float, 1) == 0)
5986  {
5987  o << std::fixed << std::setprecision(1);
5988  }
5989  else
5990  {
5991  // std::defaultfloat not supported in gcc version < 5
5992  o.unsetf(std::ios_base::floatfield);
5993  o << std::setprecision(std::numeric_limits<double>::digits10);
5994  }
5995  o << m_value.number_float;
5996  return;
5997  }
5998 
5999  case value_t::discarded:
6000  {
6001  o << "<discarded>";
6002  return;
6003  }
6004 
6005  case value_t::null:
6006  {
6007  o << "null";
6008  return;
6009  }
6010  }
6011  }
6012 
6013  private:
6015  // member variables //
6017 
6019  value_t m_type = value_t::null;
6020 
6022  json_value m_value = {};
6023 
6024 
6025  private:
6027  // iterators //
6029 
6039  class primitive_iterator_t
6040  {
6041  public:
6043  void set_begin()
6044  {
6045  m_it = begin_value;
6046  }
6047 
6049  void set_end()
6050  {
6051  m_it = end_value;
6052  }
6053 
6055  bool is_begin() const
6056  {
6057  return (m_it == begin_value);
6058  }
6059 
6061  bool is_end() const
6062  {
6063  return (m_it == end_value);
6064  }
6065 
6067  operator difference_type& ()
6068  {
6069  return m_it;
6070  }
6071 
6073  operator difference_type () const
6074  {
6075  return m_it;
6076  }
6077 
6078  private:
6079  static constexpr difference_type begin_value = 0;
6080  static constexpr difference_type end_value = begin_value + 1;
6081 
6083  difference_type m_it = std::numeric_limits<std::ptrdiff_t>::denorm_min();
6084  };
6085 
6093  struct internal_iterator
6094  {
6096  typename object_t::iterator object_iterator;
6098  typename array_t::iterator array_iterator;
6100  primitive_iterator_t primitive_iterator;
6101 
6103  internal_iterator()
6104  : object_iterator(), array_iterator(), primitive_iterator()
6105  {}
6106  };
6107 
6109  template<typename IteratorType>
6110  class iteration_proxy
6111  {
6112  private:
6114  class iteration_proxy_internal
6115  {
6116  private:
6118  IteratorType anchor;
6120  size_t array_index = 0;
6121 
6122  public:
6123  iteration_proxy_internal(IteratorType it)
6124  : anchor(it)
6125  {}
6126 
6128  iteration_proxy_internal& operator*()
6129  {
6130  return *this;
6131  }
6132 
6134  iteration_proxy_internal& operator++()
6135  {
6136  ++anchor;
6137  ++array_index;
6138 
6139  return *this;
6140  }
6141 
6143  bool operator!= (const iteration_proxy_internal& o) const
6144  {
6145  return anchor != o.anchor;
6146  }
6147 
6149  typename basic_json::string_t key() const
6150  {
6151  assert(anchor.m_object != nullptr);
6152 
6153  switch (anchor.m_object->type())
6154  {
6155  // use integer array index as key
6156  case value_t::array:
6157  {
6158  return std::to_string(array_index);
6159  }
6160 
6161  // use key from the object
6162  case value_t::object:
6163  {
6164  return anchor.key();
6165  }
6166 
6167  // use an empty key for all primitive types
6168  default:
6169  {
6170  return "";
6171  }
6172  }
6173  }
6174 
6176  typename IteratorType::reference value() const
6177  {
6178  return anchor.value();
6179  }
6180  };
6181 
6183  typename IteratorType::reference container;
6184 
6185  public:
6187  iteration_proxy(typename IteratorType::reference cont)
6188  : container(cont)
6189  {}
6190 
6192  iteration_proxy_internal begin()
6193  {
6194  return iteration_proxy_internal(container.begin());
6195  }
6196 
6198  iteration_proxy_internal end()
6199  {
6200  return iteration_proxy_internal(container.end());
6201  }
6202  };
6203 
6204  public:
6218  class const_iterator : public std::iterator<std::random_access_iterator_tag, const basic_json>
6219  {
6221  friend class basic_json;
6222 
6223  public:
6233  using iterator_category = std::bidirectional_iterator_tag;
6234 
6236  const_iterator() = default;
6237 
6239  const_iterator(pointer object) : m_object(object)
6240  {
6241  assert(m_object != nullptr);
6242 
6243  switch (m_object->m_type)
6244  {
6246  {
6247  m_it.object_iterator = typename object_t::iterator();
6248  break;
6249  }
6250 
6252  {
6253  m_it.array_iterator = typename array_t::iterator();
6254  break;
6255  }
6256 
6257  default:
6258  {
6259  m_it.primitive_iterator = primitive_iterator_t();
6260  break;
6261  }
6262  }
6263  }
6264 
6266  const_iterator(const iterator& other) : m_object(other.m_object)
6267  {
6268  assert(m_object != nullptr);
6269 
6270  switch (m_object->m_type)
6271  {
6273  {
6274  m_it.object_iterator = other.m_it.object_iterator;
6275  break;
6276  }
6277 
6279  {
6280  m_it.array_iterator = other.m_it.array_iterator;
6281  break;
6282  }
6283 
6284  default:
6285  {
6286  m_it.primitive_iterator = other.m_it.primitive_iterator;
6287  break;
6288  }
6289  }
6290  }
6291 
6293  const_iterator(const const_iterator& other) noexcept
6294  : m_object(other.m_object), m_it(other.m_it)
6295  {}
6296 
6299  std::is_nothrow_move_constructible<pointer>::value and
6300  std::is_nothrow_move_assignable<pointer>::value and
6301  std::is_nothrow_move_constructible<internal_iterator>::value and
6302  std::is_nothrow_move_assignable<internal_iterator>::value
6303  )
6304  {
6305  std::swap(m_object, other.m_object);
6306  std::swap(m_it, other.m_it);
6307  return *this;
6308  }
6309 
6310  private:
6312  void set_begin()
6313  {
6314  assert(m_object != nullptr);
6315 
6316  switch (m_object->m_type)
6317  {
6319  {
6320  assert(m_object->m_value.object != nullptr);
6321  m_it.object_iterator = m_object->m_value.object->begin();
6322  break;
6323  }
6324 
6326  {
6327  assert(m_object->m_value.array != nullptr);
6328  m_it.array_iterator = m_object->m_value.array->begin();
6329  break;
6330  }
6331 
6333  {
6334  // set to end so begin()==end() is true: null is empty
6335  m_it.primitive_iterator.set_end();
6336  break;
6337  }
6338 
6339  default:
6340  {
6341  m_it.primitive_iterator.set_begin();
6342  break;
6343  }
6344  }
6345  }
6346 
6348  void set_end()
6349  {
6350  assert(m_object != nullptr);
6351 
6352  switch (m_object->m_type)
6353  {
6355  {
6356  assert(m_object->m_value.object != nullptr);
6357  m_it.object_iterator = m_object->m_value.object->end();
6358  break;
6359  }
6360 
6362  {
6363  assert(m_object->m_value.array != nullptr);
6364  m_it.array_iterator = m_object->m_value.array->end();
6365  break;
6366  }
6367 
6368  default:
6369  {
6370  m_it.primitive_iterator.set_end();
6371  break;
6372  }
6373  }
6374  }
6375 
6376  public:
6379  {
6380  assert(m_object != nullptr);
6381 
6382  switch (m_object->m_type)
6383  {
6385  {
6386  assert(m_object->m_value.object);
6387  assert(m_it.object_iterator != m_object->m_value.object->end());
6388  return m_it.object_iterator->second;
6389  }
6390 
6392  {
6393  assert(m_object->m_value.array);
6394  assert(m_it.array_iterator != m_object->m_value.array->end());
6395  return *m_it.array_iterator;
6396  }
6397 
6399  {
6400  throw std::out_of_range("cannot get value");
6401  }
6402 
6403  default:
6404  {
6405  if (m_it.primitive_iterator.is_begin())
6406  {
6407  return *m_object;
6408  }
6409  else
6410  {
6411  throw std::out_of_range("cannot get value");
6412  }
6413  }
6414  }
6415  }
6416 
6419  {
6420  assert(m_object != nullptr);
6421 
6422  switch (m_object->m_type)
6423  {
6425  {
6426  assert(m_object->m_value.object);
6427  assert(m_it.object_iterator != m_object->m_value.object->end());
6428  return &(m_it.object_iterator->second);
6429  }
6430 
6432  {
6433  assert(m_object->m_value.array);
6434  assert(m_it.array_iterator != m_object->m_value.array->end());
6435  return &*m_it.array_iterator;
6436  }
6437 
6438  default:
6439  {
6440  if (m_it.primitive_iterator.is_begin())
6441  {
6442  return m_object;
6443  }
6444  else
6445  {
6446  throw std::out_of_range("cannot get value");
6447  }
6448  }
6449  }
6450  }
6451 
6454  {
6455  auto result = *this;
6456  ++(*this);
6457  return result;
6458  }
6459 
6462  {
6463  assert(m_object != nullptr);
6464 
6465  switch (m_object->m_type)
6466  {
6468  {
6469  ++m_it.object_iterator;
6470  break;
6471  }
6472 
6474  {
6475  ++m_it.array_iterator;
6476  break;
6477  }
6478 
6479  default:
6480  {
6481  ++m_it.primitive_iterator;
6482  break;
6483  }
6484  }
6485 
6486  return *this;
6487  }
6488 
6491  {
6492  auto result = *this;
6493  --(*this);
6494  return result;
6495  }
6496 
6499  {
6500  assert(m_object != nullptr);
6501 
6502  switch (m_object->m_type)
6503  {
6505  {
6506  --m_it.object_iterator;
6507  break;
6508  }
6509 
6511  {
6512  --m_it.array_iterator;
6513  break;
6514  }
6515 
6516  default:
6517  {
6518  --m_it.primitive_iterator;
6519  break;
6520  }
6521  }
6522 
6523  return *this;
6524  }
6525 
6527  bool operator==(const const_iterator& other) const
6528  {
6529  // if objects are not the same, the comparison is undefined
6530  if (m_object != other.m_object)
6531  {
6532  throw std::domain_error("cannot compare iterators of different containers");
6533  }
6534 
6535  assert(m_object != nullptr);
6536 
6537  switch (m_object->m_type)
6538  {
6540  {
6541  return (m_it.object_iterator == other.m_it.object_iterator);
6542  }
6543 
6545  {
6546  return (m_it.array_iterator == other.m_it.array_iterator);
6547  }
6548 
6549  default:
6550  {
6551  return (m_it.primitive_iterator == other.m_it.primitive_iterator);
6552  }
6553  }
6554  }
6555 
6557  bool operator!=(const const_iterator& other) const
6558  {
6559  return not operator==(other);
6560  }
6561 
6563  bool operator<(const const_iterator& other) const
6564  {
6565  // if objects are not the same, the comparison is undefined
6566  if (m_object != other.m_object)
6567  {
6568  throw std::domain_error("cannot compare iterators of different containers");
6569  }
6570 
6571  assert(m_object != nullptr);
6572 
6573  switch (m_object->m_type)
6574  {
6576  {
6577  throw std::domain_error("cannot compare order of object iterators");
6578  }
6579 
6581  {
6582  return (m_it.array_iterator < other.m_it.array_iterator);
6583  }
6584 
6585  default:
6586  {
6587  return (m_it.primitive_iterator < other.m_it.primitive_iterator);
6588  }
6589  }
6590  }
6591 
6593  bool operator<=(const const_iterator& other) const
6594  {
6595  return not other.operator < (*this);
6596  }
6597 
6599  bool operator>(const const_iterator& other) const
6600  {
6601  return not operator<=(other);
6602  }
6603 
6605  bool operator>=(const const_iterator& other) const
6606  {
6607  return not operator<(other);
6608  }
6609 
6612  {
6613  assert(m_object != nullptr);
6614 
6615  switch (m_object->m_type)
6616  {
6618  {
6619  throw std::domain_error("cannot use offsets with object iterators");
6620  }
6621 
6623  {
6624  m_it.array_iterator += i;
6625  break;
6626  }
6627 
6628  default:
6629  {
6630  m_it.primitive_iterator += i;
6631  break;
6632  }
6633  }
6634 
6635  return *this;
6636  }
6637 
6640  {
6641  return operator+=(-i);
6642  }
6643 
6646  {
6647  auto result = *this;
6648  result += i;
6649  return result;
6650  }
6651 
6654  {
6655  auto result = *this;
6656  result -= i;
6657  return result;
6658  }
6659 
6662  {
6663  assert(m_object != nullptr);
6664 
6665  switch (m_object->m_type)
6666  {
6668  {
6669  throw std::domain_error("cannot use offsets with object iterators");
6670  }
6671 
6673  {
6674  return m_it.array_iterator - other.m_it.array_iterator;
6675  }
6676 
6677  default:
6678  {
6679  return m_it.primitive_iterator - other.m_it.primitive_iterator;
6680  }
6681  }
6682  }
6683 
6686  {
6687  assert(m_object != nullptr);
6688 
6689  switch (m_object->m_type)
6690  {
6692  {
6693  throw std::domain_error("cannot use operator[] for object iterators");
6694  }
6695 
6697  {
6698  return *(m_it.array_iterator + n);
6699  }
6700 
6702  {
6703  throw std::out_of_range("cannot get value");
6704  }
6705 
6706  default:
6707  {
6708  if (m_it.primitive_iterator == -n)
6709  {
6710  return *m_object;
6711  }
6712  else
6713  {
6714  throw std::out_of_range("cannot get value");
6715  }
6716  }
6717  }
6718  }
6719 
6721  typename object_t::key_type key() const
6722  {
6723  assert(m_object != nullptr);
6724 
6725  if (m_object->is_object())
6726  {
6727  return m_it.object_iterator->first;
6728  }
6729  else
6730  {
6731  throw std::domain_error("cannot use key() for non-object iterators");
6732  }
6733  }
6734 
6737  {
6738  return operator*();
6739  }
6740 
6741  private:
6743  pointer m_object = nullptr;
6745  internal_iterator m_it = internal_iterator();
6746  };
6747 
6760  class iterator : public const_iterator
6761  {
6762  public:
6764  using pointer = typename basic_json::pointer;
6766 
6768  iterator() = default;
6769 
6771  iterator(pointer object) noexcept
6772  : base_iterator(object)
6773  {}
6774 
6776  iterator(const iterator& other) noexcept
6777  : base_iterator(other)
6778  {}
6779 
6781  iterator& operator=(iterator other) noexcept(
6782  std::is_nothrow_move_constructible<pointer>::value and
6783  std::is_nothrow_move_assignable<pointer>::value and
6784  std::is_nothrow_move_constructible<internal_iterator>::value and
6785  std::is_nothrow_move_assignable<internal_iterator>::value
6786  )
6787  {
6788  base_iterator::operator=(other);
6789  return *this;
6790  }
6791 
6794  {
6795  return const_cast<reference>(base_iterator::operator*());
6796  }
6797 
6800  {
6801  return const_cast<pointer>(base_iterator::operator->());
6802  }
6803 
6806  {
6807  iterator result = *this;
6808  base_iterator::operator++();
6809  return result;
6810  }
6811 
6814  {
6815  base_iterator::operator++();
6816  return *this;
6817  }
6818 
6821  {
6822  iterator result = *this;
6823  base_iterator::operator--();
6824  return result;
6825  }
6826 
6829  {
6830  base_iterator::operator--();
6831  return *this;
6832  }
6833 
6836  {
6837  base_iterator::operator+=(i);
6838  return *this;
6839  }
6840 
6843  {
6844  base_iterator::operator-=(i);
6845  return *this;
6846  }
6847 
6850  {
6851  auto result = *this;
6852  result += i;
6853  return result;
6854  }
6855 
6858  {
6859  auto result = *this;
6860  result -= i;
6861  return result;
6862  }
6863 
6865  difference_type operator-(const iterator& other) const
6866  {
6867  return base_iterator::operator-(other);
6868  }
6869 
6872  {
6873  return const_cast<reference>(base_iterator::operator[](n));
6874  }
6875 
6878  {
6879  return const_cast<reference>(base_iterator::value());
6880  }
6881  };
6882 
6900  template<typename Base>
6901  class json_reverse_iterator : public std::reverse_iterator<Base>
6902  {
6903  public:
6905  using base_iterator = std::reverse_iterator<Base>;
6907  using reference = typename Base::reference;
6908 
6910  json_reverse_iterator(const typename base_iterator::iterator_type& it)
6911  : base_iterator(it)
6912  {}
6913 
6916  : base_iterator(it)
6917  {}
6918 
6921  {
6922  return base_iterator::operator++(1);
6923  }
6924 
6927  {
6928  base_iterator::operator++();
6929  return *this;
6930  }
6931 
6934  {
6935  return base_iterator::operator--(1);
6936  }
6937 
6940  {
6941  base_iterator::operator--();
6942  return *this;
6943  }
6944 
6947  {
6948  base_iterator::operator+=(i);
6949  return *this;
6950  }
6951 
6954  {
6955  auto result = *this;
6956  result += i;
6957  return result;
6958  }
6959 
6962  {
6963  auto result = *this;
6964  result -= i;
6965  return result;
6966  }
6967 
6970  {
6971  return this->base() - other.base();
6972  }
6973 
6976  {
6977  return *(this->operator+(n));
6978  }
6979 
6981  typename object_t::key_type key() const
6982  {
6983  auto it = --this->base();
6984  return it.key();
6985  }
6986 
6989  {
6990  auto it = --this->base();
6991  return it.operator * ();
6992  }
6993  };
6994 
6995 
6996  private:
6998  // lexer and parser //
7000 
7008  class lexer
7009  {
7010  public:
7012  enum class token_type
7013  {
7014  uninitialized,
7015  literal_true,
7016  literal_false,
7017  literal_null,
7018  value_string,
7019  value_number,
7020  begin_array,
7021  begin_object,
7022  end_array,
7023  end_object,
7024  name_separator,
7025  value_separator,
7026  parse_error,
7027  end_of_input
7028  };
7029 
7031  using lexer_char_t = unsigned char;
7032 
7034  explicit lexer(const string_t& s) noexcept
7035  : m_stream(nullptr), m_buffer(s)
7036  {
7037  m_content = reinterpret_cast<const lexer_char_t*>(s.c_str());
7038  assert(m_content != nullptr);
7039  m_start = m_cursor = m_content;
7040  m_limit = m_content + s.size();
7041  }
7042 
7044  explicit lexer(std::istream* s) noexcept
7045  : m_stream(s), m_buffer()
7046  {
7047  assert(m_stream != nullptr);
7048  getline(*m_stream, m_buffer);
7049  m_content = reinterpret_cast<const lexer_char_t*>(m_buffer.c_str());
7050  assert(m_content != nullptr);
7051  m_start = m_cursor = m_content;
7052  m_limit = m_content + m_buffer.size();
7053  }
7054 
7056  lexer() = default;
7057 
7058  // switch off unwanted functions
7059  lexer(const lexer&) = delete;
7060  lexer operator=(const lexer&) = delete;
7061 
7077  static string_t to_unicode(const std::size_t codepoint1,
7078  const std::size_t codepoint2 = 0)
7079  {
7080  // calculate the codepoint from the given code points
7081  std::size_t codepoint = codepoint1;
7082 
7083  // check if codepoint1 is a high surrogate
7084  if (codepoint1 >= 0xD800 and codepoint1 <= 0xDBFF)
7085  {
7086  // check if codepoint2 is a low surrogate
7087  if (codepoint2 >= 0xDC00 and codepoint2 <= 0xDFFF)
7088  {
7089  codepoint =
7090  // high surrogate occupies the most significant 22 bits
7091  (codepoint1 << 10)
7092  // low surrogate occupies the least significant 15 bits
7093  + codepoint2
7094  // there is still the 0xD800, 0xDC00 and 0x10000 noise
7095  // in the result so we have to subtract with:
7096  // (0xD800 << 10) + DC00 - 0x10000 = 0x35FDC00
7097  - 0x35FDC00;
7098  }
7099  else
7100  {
7101  throw std::invalid_argument("missing or wrong low surrogate");
7102  }
7103  }
7104 
7105  string_t result;
7106 
7107  if (codepoint < 0x80)
7108  {
7109  // 1-byte characters: 0xxxxxxx (ASCII)
7110  result.append(1, static_cast<typename string_t::value_type>(codepoint));
7111  }
7112  else if (codepoint <= 0x7ff)
7113  {
7114  // 2-byte characters: 110xxxxx 10xxxxxx
7115  result.append(1, static_cast<typename string_t::value_type>(0xC0 | ((codepoint >> 6) & 0x1F)));
7116  result.append(1, static_cast<typename string_t::value_type>(0x80 | (codepoint & 0x3F)));
7117  }
7118  else if (codepoint <= 0xffff)
7119  {
7120  // 3-byte characters: 1110xxxx 10xxxxxx 10xxxxxx
7121  result.append(1, static_cast<typename string_t::value_type>(0xE0 | ((codepoint >> 12) & 0x0F)));
7122  result.append(1, static_cast<typename string_t::value_type>(0x80 | ((codepoint >> 6) & 0x3F)));
7123  result.append(1, static_cast<typename string_t::value_type>(0x80 | (codepoint & 0x3F)));
7124  }
7125  else if (codepoint <= 0x10ffff)
7126  {
7127  // 4-byte characters: 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
7128  result.append(1, static_cast<typename string_t::value_type>(0xF0 | ((codepoint >> 18) & 0x07)));
7129  result.append(1, static_cast<typename string_t::value_type>(0x80 | ((codepoint >> 12) & 0x3F)));
7130  result.append(1, static_cast<typename string_t::value_type>(0x80 | ((codepoint >> 6) & 0x3F)));
7131  result.append(1, static_cast<typename string_t::value_type>(0x80 | (codepoint & 0x3F)));
7132  }
7133  else
7134  {
7135  throw std::out_of_range("code points above 0x10FFFF are invalid");
7136  }
7137 
7138  return result;
7139  }
7140 
7142  static std::string token_type_name(token_type t)
7143  {
7144  switch (t)
7145  {
7146  case token_type::uninitialized:
7147  return "<uninitialized>";
7148  case token_type::literal_true:
7149  return "true literal";
7150  case token_type::literal_false:
7151  return "false literal";
7152  case token_type::literal_null:
7153  return "null literal";
7154  case token_type::value_string:
7155  return "string literal";
7156  case token_type::value_number:
7157  return "number literal";
7158  case token_type::begin_array:
7159  return "'['";
7160  case token_type::begin_object:
7161  return "'{'";
7162  case token_type::end_array:
7163  return "']'";
7164  case token_type::end_object:
7165  return "'}'";
7166  case token_type::name_separator:
7167  return "':'";
7168  case token_type::value_separator:
7169  return "','";
7170  case token_type::parse_error:
7171  return "<parse error>";
7172  case token_type::end_of_input:
7173  return "end of input";
7174  default:
7175  {
7176  // catch non-enum values
7177  return "unknown token"; // LCOV_EXCL_LINE
7178  }
7179  }
7180  }
7181 
7192  token_type scan() noexcept
7193  {
7194  // pointer for backtracking information
7195  m_marker = nullptr;
7196 
7197  // remember the begin of the token
7198  m_start = m_cursor;
7199  assert(m_start != nullptr);
7200 
7201 
7202  {
7203  lexer_char_t yych;
7204  unsigned int yyaccept = 0;
7205  static const unsigned char yybm[] =
7206  {
7207  0, 0, 0, 0, 0, 0, 0, 0,
7208  0, 32, 32, 0, 0, 32, 0, 0,
7209  128, 128, 128, 128, 128, 128, 128, 128,
7210  128, 128, 128, 128, 128, 128, 128, 128,
7211  160, 128, 0, 128, 128, 128, 128, 128,
7212  128, 128, 128, 128, 128, 128, 128, 128,
7213  192, 192, 192, 192, 192, 192, 192, 192,
7214  192, 192, 128, 128, 128, 128, 128, 128,
7215  128, 128, 128, 128, 128, 128, 128, 128,
7216  128, 128, 128, 128, 128, 128, 128, 128,
7217  128, 128, 128, 128, 128, 128, 128, 128,
7218  128, 128, 128, 128, 0, 128, 128, 128,
7219  128, 128, 128, 128, 128, 128, 128, 128,
7220  128, 128, 128, 128, 128, 128, 128, 128,
7221  128, 128, 128, 128, 128, 128, 128, 128,
7222  128, 128, 128, 128, 128, 128, 128, 128,
7223  128, 128, 128, 128, 128, 128, 128, 128,
7224  128, 128, 128, 128, 128, 128, 128, 128,
7225  128, 128, 128, 128, 128, 128, 128, 128,
7226  128, 128, 128, 128, 128, 128, 128, 128,
7227  128, 128, 128, 128, 128, 128, 128, 128,
7228  128, 128, 128, 128, 128, 128, 128, 128,
7229  128, 128, 128, 128, 128, 128, 128, 128,
7230  128, 128, 128, 128, 128, 128, 128, 128,
7231  128, 128, 128, 128, 128, 128, 128, 128,
7232  128, 128, 128, 128, 128, 128, 128, 128,
7233  128, 128, 128, 128, 128, 128, 128, 128,
7234  128, 128, 128, 128, 128, 128, 128, 128,
7235  128, 128, 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  };
7240  if ((m_limit - m_cursor) < 5)
7241  {
7242  yyfill(); // LCOV_EXCL_LINE;
7243  }
7244  yych = *m_cursor;
7245  if (yybm[0 + yych] & 32)
7246  {
7247  goto basic_json_parser_6;
7248  }
7249  if (yych <= '\\')
7250  {
7251  if (yych <= '-')
7252  {
7253  if (yych <= '"')
7254  {
7255  if (yych <= 0x00)
7256  {
7257  goto basic_json_parser_2;
7258  }
7259  if (yych <= '!')
7260  {
7261  goto basic_json_parser_4;
7262  }
7263  goto basic_json_parser_9;
7264  }
7265  else
7266  {
7267  if (yych <= '+')
7268  {
7269  goto basic_json_parser_4;
7270  }
7271  if (yych <= ',')
7272  {
7273  goto basic_json_parser_10;
7274  }
7275  goto basic_json_parser_12;
7276  }
7277  }
7278  else
7279  {
7280  if (yych <= '9')
7281  {
7282  if (yych <= '/')
7283  {
7284  goto basic_json_parser_4;
7285  }
7286  if (yych <= '0')
7287  {
7288  goto basic_json_parser_13;
7289  }
7290  goto basic_json_parser_15;
7291  }
7292  else
7293  {
7294  if (yych <= ':')
7295  {
7296  goto basic_json_parser_17;
7297  }
7298  if (yych == '[')
7299  {
7300  goto basic_json_parser_19;
7301  }
7302  goto basic_json_parser_4;
7303  }
7304  }
7305  }
7306  else
7307  {
7308  if (yych <= 't')
7309  {
7310  if (yych <= 'f')
7311  {
7312  if (yych <= ']')
7313  {
7314  goto basic_json_parser_21;
7315  }
7316  if (yych <= 'e')
7317  {
7318  goto basic_json_parser_4;
7319  }
7320  goto basic_json_parser_23;
7321  }
7322  else
7323  {
7324  if (yych == 'n')
7325  {
7326  goto basic_json_parser_24;
7327  }
7328  if (yych <= 's')
7329  {
7330  goto basic_json_parser_4;
7331  }
7332  goto basic_json_parser_25;
7333  }
7334  }
7335  else
7336  {
7337  if (yych <= '|')
7338  {
7339  if (yych == '{')
7340  {
7341  goto basic_json_parser_26;
7342  }
7343  goto basic_json_parser_4;
7344  }
7345  else
7346  {
7347  if (yych <= '}')
7348  {
7349  goto basic_json_parser_28;
7350  }
7351  if (yych == 0xEF)
7352  {
7353  goto basic_json_parser_30;
7354  }
7355  goto basic_json_parser_4;
7356  }
7357  }
7358  }
7359 basic_json_parser_2:
7360  ++m_cursor;
7361  {
7362  return token_type::end_of_input;
7363  }
7364 basic_json_parser_4:
7365  ++m_cursor;
7366 basic_json_parser_5:
7367  {
7368  return token_type::parse_error;
7369  }
7370 basic_json_parser_6:
7371  ++m_cursor;
7372  if (m_limit <= m_cursor)
7373  {
7374  yyfill(); // LCOV_EXCL_LINE;
7375  }
7376  yych = *m_cursor;
7377  if (yybm[0 + yych] & 32)
7378  {
7379  goto basic_json_parser_6;
7380  }
7381  {
7382  return scan();
7383  }
7384 basic_json_parser_9:
7385  yyaccept = 0;
7386  yych = *(m_marker = ++m_cursor);
7387  if (yych <= 0x0F)
7388  {
7389  goto basic_json_parser_5;
7390  }
7391  goto basic_json_parser_32;
7392 basic_json_parser_10:
7393  ++m_cursor;
7394  {
7395  return token_type::value_separator;
7396  }
7397 basic_json_parser_12:
7398  yych = *++m_cursor;
7399  if (yych <= '/')
7400  {
7401  goto basic_json_parser_5;
7402  }
7403  if (yych <= '0')
7404  {
7405  goto basic_json_parser_13;
7406  }
7407  if (yych <= '9')
7408  {
7409  goto basic_json_parser_15;
7410  }
7411  goto basic_json_parser_5;
7412 basic_json_parser_13:
7413  yyaccept = 1;
7414  yych = *(m_marker = ++m_cursor);
7415  if (yych <= 'D')
7416  {
7417  if (yych == '.')
7418  {
7419  goto basic_json_parser_37;
7420  }
7421  }
7422  else
7423  {
7424  if (yych <= 'E')
7425  {
7426  goto basic_json_parser_38;
7427  }
7428  if (yych == 'e')
7429  {
7430  goto basic_json_parser_38;
7431  }
7432  }
7433 basic_json_parser_14:
7434  {
7435  return token_type::value_number;
7436  }
7437 basic_json_parser_15:
7438  yyaccept = 1;
7439  m_marker = ++m_cursor;
7440  if ((m_limit - m_cursor) < 3)
7441  {
7442  yyfill(); // LCOV_EXCL_LINE;
7443  }
7444  yych = *m_cursor;
7445  if (yybm[0 + yych] & 64)
7446  {
7447  goto basic_json_parser_15;
7448  }
7449  if (yych <= 'D')
7450  {
7451  if (yych == '.')
7452  {
7453  goto basic_json_parser_37;
7454  }
7455  goto basic_json_parser_14;
7456  }
7457  else
7458  {
7459  if (yych <= 'E')
7460  {
7461  goto basic_json_parser_38;
7462  }
7463  if (yych == 'e')
7464  {
7465  goto basic_json_parser_38;
7466  }
7467  goto basic_json_parser_14;
7468  }
7469 basic_json_parser_17:
7470  ++m_cursor;
7471  {
7472  return token_type::name_separator;
7473  }
7474 basic_json_parser_19:
7475  ++m_cursor;
7476  {
7477  return token_type::begin_array;
7478  }
7479 basic_json_parser_21:
7480  ++m_cursor;
7481  {
7482  return token_type::end_array;
7483  }
7484 basic_json_parser_23:
7485  yyaccept = 0;
7486  yych = *(m_marker = ++m_cursor);
7487  if (yych == 'a')
7488  {
7489  goto basic_json_parser_39;
7490  }
7491  goto basic_json_parser_5;
7492 basic_json_parser_24:
7493  yyaccept = 0;
7494  yych = *(m_marker = ++m_cursor);
7495  if (yych == 'u')
7496  {
7497  goto basic_json_parser_40;
7498  }
7499  goto basic_json_parser_5;
7500 basic_json_parser_25:
7501  yyaccept = 0;
7502  yych = *(m_marker = ++m_cursor);
7503  if (yych == 'r')
7504  {
7505  goto basic_json_parser_41;
7506  }
7507  goto basic_json_parser_5;
7508 basic_json_parser_26:
7509  ++m_cursor;
7510  {
7511  return token_type::begin_object;
7512  }
7513 basic_json_parser_28:
7514  ++m_cursor;
7515  {
7516  return token_type::end_object;
7517  }
7518 basic_json_parser_30:
7519  yyaccept = 0;
7520  yych = *(m_marker = ++m_cursor);
7521  if (yych == 0xBB)
7522  {
7523  goto basic_json_parser_42;
7524  }
7525  goto basic_json_parser_5;
7526 basic_json_parser_31:
7527  ++m_cursor;
7528  if (m_limit <= m_cursor)
7529  {
7530  yyfill(); // LCOV_EXCL_LINE;
7531  }
7532  yych = *m_cursor;
7533 basic_json_parser_32:
7534  if (yybm[0 + yych] & 128)
7535  {
7536  goto basic_json_parser_31;
7537  }
7538  if (yych <= 0x0F)
7539  {
7540  goto basic_json_parser_33;
7541  }
7542  if (yych <= '"')
7543  {
7544  goto basic_json_parser_34;
7545  }
7546  goto basic_json_parser_36;
7547 basic_json_parser_33:
7548  m_cursor = m_marker;
7549  if (yyaccept == 0)
7550  {
7551  goto basic_json_parser_5;
7552  }
7553  else
7554  {
7555  goto basic_json_parser_14;
7556  }
7557 basic_json_parser_34:
7558  ++m_cursor;
7559  {
7560  return token_type::value_string;
7561  }
7562 basic_json_parser_36:
7563  ++m_cursor;
7564  if (m_limit <= m_cursor)
7565  {
7566  yyfill(); // LCOV_EXCL_LINE;
7567  }
7568  yych = *m_cursor;
7569  if (yych <= 'e')
7570  {
7571  if (yych <= '/')
7572  {
7573  if (yych == '"')
7574  {
7575  goto basic_json_parser_31;
7576  }
7577  if (yych <= '.')
7578  {
7579  goto basic_json_parser_33;
7580  }
7581  goto basic_json_parser_31;
7582  }
7583  else
7584  {
7585  if (yych <= '\\')
7586  {
7587  if (yych <= '[')
7588  {
7589  goto basic_json_parser_33;
7590  }
7591  goto basic_json_parser_31;
7592  }
7593  else
7594  {
7595  if (yych == 'b')
7596  {
7597  goto basic_json_parser_31;
7598  }
7599  goto basic_json_parser_33;
7600  }
7601  }
7602  }
7603  else
7604  {
7605  if (yych <= 'q')
7606  {
7607  if (yych <= 'f')
7608  {
7609  goto basic_json_parser_31;
7610  }
7611  if (yych == 'n')
7612  {
7613  goto basic_json_parser_31;
7614  }
7615  goto basic_json_parser_33;
7616  }
7617  else
7618  {
7619  if (yych <= 's')
7620  {
7621  if (yych <= 'r')
7622  {
7623  goto basic_json_parser_31;
7624  }
7625  goto basic_json_parser_33;
7626  }
7627  else
7628  {
7629  if (yych <= 't')
7630  {
7631  goto basic_json_parser_31;
7632  }
7633  if (yych <= 'u')
7634  {
7635  goto basic_json_parser_43;
7636  }
7637  goto basic_json_parser_33;
7638  }
7639  }
7640  }
7641 basic_json_parser_37:
7642  yych = *++m_cursor;
7643  if (yych <= '/')
7644  {
7645  goto basic_json_parser_33;
7646  }
7647  if (yych <= '9')
7648  {
7649  goto basic_json_parser_44;
7650  }
7651  goto basic_json_parser_33;
7652 basic_json_parser_38:
7653  yych = *++m_cursor;
7654  if (yych <= ',')
7655  {
7656  if (yych == '+')
7657  {
7658  goto basic_json_parser_46;
7659  }
7660  goto basic_json_parser_33;
7661  }
7662  else
7663  {
7664  if (yych <= '-')
7665  {
7666  goto basic_json_parser_46;
7667  }
7668  if (yych <= '/')
7669  {
7670  goto basic_json_parser_33;
7671  }
7672  if (yych <= '9')
7673  {
7674  goto basic_json_parser_47;
7675  }
7676  goto basic_json_parser_33;
7677  }
7678 basic_json_parser_39:
7679  yych = *++m_cursor;
7680  if (yych == 'l')
7681  {
7682  goto basic_json_parser_49;
7683  }
7684  goto basic_json_parser_33;
7685 basic_json_parser_40:
7686  yych = *++m_cursor;
7687  if (yych == 'l')
7688  {
7689  goto basic_json_parser_50;
7690  }
7691  goto basic_json_parser_33;
7692 basic_json_parser_41:
7693  yych = *++m_cursor;
7694  if (yych == 'u')
7695  {
7696  goto basic_json_parser_51;
7697  }
7698  goto basic_json_parser_33;
7699 basic_json_parser_42:
7700  yych = *++m_cursor;
7701  if (yych == 0xBF)
7702  {
7703  goto basic_json_parser_52;
7704  }
7705  goto basic_json_parser_33;
7706 basic_json_parser_43:
7707  ++m_cursor;
7708  if (m_limit <= m_cursor)
7709  {
7710  yyfill(); // LCOV_EXCL_LINE;
7711  }
7712  yych = *m_cursor;
7713  if (yych <= '@')
7714  {
7715  if (yych <= '/')
7716  {
7717  goto basic_json_parser_33;
7718  }
7719  if (yych <= '9')
7720  {
7721  goto basic_json_parser_54;
7722  }
7723  goto basic_json_parser_33;
7724  }
7725  else
7726  {
7727  if (yych <= 'F')
7728  {
7729  goto basic_json_parser_54;
7730  }
7731  if (yych <= '`')
7732  {
7733  goto basic_json_parser_33;
7734  }
7735  if (yych <= 'f')
7736  {
7737  goto basic_json_parser_54;
7738  }
7739  goto basic_json_parser_33;
7740  }
7741 basic_json_parser_44:
7742  yyaccept = 1;
7743  m_marker = ++m_cursor;
7744  if ((m_limit - m_cursor) < 3)
7745  {
7746  yyfill(); // LCOV_EXCL_LINE;
7747  }
7748  yych = *m_cursor;
7749  if (yych <= 'D')
7750  {
7751  if (yych <= '/')
7752  {
7753  goto basic_json_parser_14;
7754  }
7755  if (yych <= '9')
7756  {
7757  goto basic_json_parser_44;
7758  }
7759  goto basic_json_parser_14;
7760  }
7761  else
7762  {
7763  if (yych <= 'E')
7764  {
7765  goto basic_json_parser_38;
7766  }
7767  if (yych == 'e')
7768  {
7769  goto basic_json_parser_38;
7770  }
7771  goto basic_json_parser_14;
7772  }
7773 basic_json_parser_46:
7774  yych = *++m_cursor;
7775  if (yych <= '/')
7776  {
7777  goto basic_json_parser_33;
7778  }
7779  if (yych >= ':')
7780  {
7781  goto basic_json_parser_33;
7782  }
7783 basic_json_parser_47:
7784  ++m_cursor;
7785  if (m_limit <= m_cursor)
7786  {
7787  yyfill(); // LCOV_EXCL_LINE;
7788  }
7789  yych = *m_cursor;
7790  if (yych <= '/')
7791  {
7792  goto basic_json_parser_14;
7793  }
7794  if (yych <= '9')
7795  {
7796  goto basic_json_parser_47;
7797  }
7798  goto basic_json_parser_14;
7799 basic_json_parser_49:
7800  yych = *++m_cursor;
7801  if (yych == 's')
7802  {
7803  goto basic_json_parser_55;
7804  }
7805  goto basic_json_parser_33;
7806 basic_json_parser_50:
7807  yych = *++m_cursor;
7808  if (yych == 'l')
7809  {
7810  goto basic_json_parser_56;
7811  }
7812  goto basic_json_parser_33;
7813 basic_json_parser_51:
7814  yych = *++m_cursor;
7815  if (yych == 'e')
7816  {
7817  goto basic_json_parser_58;
7818  }
7819  goto basic_json_parser_33;
7820 basic_json_parser_52:
7821  ++m_cursor;
7822  {
7823  return scan();
7824  }
7825 basic_json_parser_54:
7826  ++m_cursor;
7827  if (m_limit <= m_cursor)
7828  {
7829  yyfill(); // LCOV_EXCL_LINE;
7830  }
7831  yych = *m_cursor;
7832  if (yych <= '@')
7833  {
7834  if (yych <= '/')
7835  {
7836  goto basic_json_parser_33;
7837  }
7838  if (yych <= '9')
7839  {
7840  goto basic_json_parser_60;
7841  }
7842  goto basic_json_parser_33;
7843  }
7844  else
7845  {
7846  if (yych <= 'F')
7847  {
7848  goto basic_json_parser_60;
7849  }
7850  if (yych <= '`')
7851  {
7852  goto basic_json_parser_33;
7853  }
7854  if (yych <= 'f')
7855  {
7856  goto basic_json_parser_60;
7857  }
7858  goto basic_json_parser_33;
7859  }
7860 basic_json_parser_55:
7861  yych = *++m_cursor;
7862  if (yych == 'e')
7863  {
7864  goto basic_json_parser_61;
7865  }
7866  goto basic_json_parser_33;
7867 basic_json_parser_56:
7868  ++m_cursor;
7869  {
7870  return token_type::literal_null;
7871  }
7872 basic_json_parser_58:
7873  ++m_cursor;
7874  {
7875  return token_type::literal_true;
7876  }
7877 basic_json_parser_60:
7878  ++m_cursor;
7879  if (m_limit <= m_cursor)
7880  {
7881  yyfill(); // LCOV_EXCL_LINE;
7882  }
7883  yych = *m_cursor;
7884  if (yych <= '@')
7885  {
7886  if (yych <= '/')
7887  {
7888  goto basic_json_parser_33;
7889  }
7890  if (yych <= '9')
7891  {
7892  goto basic_json_parser_63;
7893  }
7894  goto basic_json_parser_33;
7895  }
7896  else
7897  {
7898  if (yych <= 'F')
7899  {
7900  goto basic_json_parser_63;
7901  }
7902  if (yych <= '`')
7903  {
7904  goto basic_json_parser_33;
7905  }
7906  if (yych <= 'f')
7907  {
7908  goto basic_json_parser_63;
7909  }
7910  goto basic_json_parser_33;
7911  }
7912 basic_json_parser_61:
7913  ++m_cursor;
7914  {
7915  return token_type::literal_false;
7916  }
7917 basic_json_parser_63:
7918  ++m_cursor;
7919  if (m_limit <= m_cursor)
7920  {
7921  yyfill(); // LCOV_EXCL_LINE;
7922  }
7923  yych = *m_cursor;
7924  if (yych <= '@')
7925  {
7926  if (yych <= '/')
7927  {
7928  goto basic_json_parser_33;
7929  }
7930  if (yych <= '9')
7931  {
7932  goto basic_json_parser_31;
7933  }
7934  goto basic_json_parser_33;
7935  }
7936  else
7937  {
7938  if (yych <= 'F')
7939  {
7940  goto basic_json_parser_31;
7941  }
7942  if (yych <= '`')
7943  {
7944  goto basic_json_parser_33;
7945  }
7946  if (yych <= 'f')
7947  {
7948  goto basic_json_parser_31;
7949  }
7950  goto basic_json_parser_33;
7951  }
7952  }
7953 
7954 
7955  }
7956 
7958  void yyfill() noexcept
7959  {
7960  if (m_stream == nullptr or not * m_stream)
7961  {
7962  return;
7963  }
7964 
7965  const ssize_t offset_start = m_start - m_content;
7966  const ssize_t offset_marker = m_marker - m_start;
7967  const ssize_t offset_cursor = m_cursor - m_start;
7968 
7969  m_buffer.erase(0, static_cast<size_t>(offset_start));
7970  std::string line;
7971  assert(m_stream != nullptr);
7972  std::getline(*m_stream, line);
7973  m_buffer += "\n" + line; // add line with newline symbol
7974 
7975  m_content = reinterpret_cast<const lexer_char_t*>(m_buffer.c_str());
7976  assert(m_content != nullptr);
7977  m_start = m_content;
7978  m_marker = m_start + offset_marker;
7979  m_cursor = m_start + offset_cursor;
7980  m_limit = m_start + m_buffer.size() - 1;
7981  }
7982 
7984  string_t get_token() const noexcept
7985  {
7986  assert(m_start != nullptr);
7987  return string_t(reinterpret_cast<typename string_t::const_pointer>(m_start),
7988  static_cast<size_t>(m_cursor - m_start));
7989  }
7990 
8012  string_t get_string() const
8013  {
8014  string_t result;
8015  result.reserve(static_cast<size_t>(m_cursor - m_start - 2));
8016 
8017  // iterate the result between the quotes
8018  for (const lexer_char_t* i = m_start + 1; i < m_cursor - 1; ++i)
8019  {
8020  // process escaped characters
8021  if (*i == '\\')
8022  {
8023  // read next character
8024  ++i;
8025 
8026  switch (*i)
8027  {
8028  // the default escapes
8029  case 't':
8030  {
8031  result += "\t";
8032  break;
8033  }
8034  case 'b':
8035  {
8036  result += "\b";
8037  break;
8038  }
8039  case 'f':
8040  {
8041  result += "\f";
8042  break;
8043  }
8044  case 'n':
8045  {
8046  result += "\n";
8047  break;
8048  }
8049  case 'r':
8050  {
8051  result += "\r";
8052  break;
8053  }
8054  case '\\':
8055  {
8056  result += "\\";
8057  break;
8058  }
8059  case '/':
8060  {
8061  result += "/";
8062  break;
8063  }
8064  case '"':
8065  {
8066  result += "\"";
8067  break;
8068  }
8069 
8070  // unicode
8071  case 'u':
8072  {
8073  // get code xxxx from uxxxx
8074  auto codepoint = std::strtoul(std::string(reinterpret_cast<typename string_t::const_pointer>(i + 1),
8075  4).c_str(), nullptr, 16);
8076 
8077  // check if codepoint is a high surrogate
8078  if (codepoint >= 0xD800 and codepoint <= 0xDBFF)
8079  {
8080  // make sure there is a subsequent unicode
8081  if ((i + 6 >= m_limit) or * (i + 5) != '\\' or * (i + 6) != 'u')
8082  {
8083  throw std::invalid_argument("missing low surrogate");
8084  }
8085 
8086  // get code yyyy from uxxxx\uyyyy
8087  auto codepoint2 = std::strtoul(std::string(reinterpret_cast<typename string_t::const_pointer>
8088  (i + 7), 4).c_str(), nullptr, 16);
8089  result += to_unicode(codepoint, codepoint2);
8090  // skip the next 10 characters (xxxx\uyyyy)
8091  i += 10;
8092  }
8093  else
8094  {
8095  // add unicode character(s)
8096  result += to_unicode(codepoint);
8097  // skip the next four characters (xxxx)
8098  i += 4;
8099  }
8100  break;
8101  }
8102  }
8103  }
8104  else
8105  {
8106  // all other characters are just copied to the end of the
8107  // string
8108  result.append(1, static_cast<typename string_t::value_type>(*i));
8109  }
8110  }
8111 
8112  return result;
8113  }
8114 
8135  long double str_to_float_t(long double* /* type */, char** endptr) const
8136  {
8137  return std::strtold(reinterpret_cast<typename string_t::const_pointer>(m_start), endptr);
8138  }
8139 
8155  double str_to_float_t(double* /* type */, char** endptr) const
8156  {
8157  return std::strtod(reinterpret_cast<typename string_t::const_pointer>(m_start), endptr);
8158  }
8159 
8175  float str_to_float_t(float* /* type */, char** endptr) const
8176  {
8177  return std::strtof(reinterpret_cast<typename string_t::const_pointer>(m_start), endptr);
8178  }
8179 
8192  template <typename T_A, typename T_B>
8193  bool attempt_cast(T_A source, T_B& dest) const
8194  {
8195  dest = static_cast<T_B>(source);
8196  return (source == static_cast<T_A>(dest));
8197  }
8198 
8237  void get_number(basic_json& result) const
8238  {
8239  typename string_t::value_type* endptr;
8240  assert(m_start != nullptr);
8241  errno = 0;
8242 
8243  // attempt to parse it as an integer - first checking for a
8244  // negative number
8245  if (*reinterpret_cast<typename string_t::const_pointer>(m_start) != '-')
8246  {
8247  // positive, parse with strtoull and attempt cast to
8248  // number_unsigned_t
8249  if (attempt_cast(std::strtoull(reinterpret_cast<typename string_t::const_pointer>(m_start), &endptr,
8250  10), result.m_value.number_unsigned))
8251  {
8252  result.m_type = value_t::number_unsigned;
8253  }
8254  else
8255  {
8256  // cast failed due to overflow - store as float
8257  result.m_type = value_t::number_float;
8258  }
8259  }
8260  else
8261  {
8262  // Negative, parse with strtoll and attempt cast to
8263  // number_integer_t
8264  if (attempt_cast(std::strtoll(reinterpret_cast<typename string_t::const_pointer>(m_start), &endptr,
8265  10), result.m_value.number_integer))
8266  {
8267  result.m_type = value_t::number_integer;
8268  }
8269  else
8270  {
8271  // cast failed due to overflow - store as float
8272  result.m_type = value_t::number_float;
8273  }
8274  }
8275 
8276  // check the end of the number was reached and no range error
8277  // occurred
8278  if (reinterpret_cast<lexer_char_t*>(endptr) != m_cursor || errno == ERANGE)
8279  {
8280  result.m_type = value_t::number_float;
8281  }
8282 
8283  if (result.m_type == value_t::number_float)
8284  {
8285  // either the number won't fit in an integer (range error from
8286  // strtoull/strtoll or overflow on cast) or there was something
8287  // else after the number, which could be an exponent
8288 
8289  // parse with strtod
8290  result.m_value.number_float = str_to_float_t(static_cast<number_float_t*>(nullptr), &endptr);
8291 
8292  // anything after the number is an error
8293  if (reinterpret_cast<lexer_char_t*>(endptr) != m_cursor)
8294  {
8295  throw std::invalid_argument(std::string("parse error - ") + get_token() + " is not a number");
8296  }
8297  }
8298  }
8299 
8300  private:
8302  std::istream* m_stream = nullptr;
8304  string_t m_buffer;
8306  const lexer_char_t* m_content = nullptr;
8308  const lexer_char_t* m_start = nullptr;
8310  const lexer_char_t* m_marker = nullptr;
8312  const lexer_char_t* m_cursor = nullptr;
8314  const lexer_char_t* m_limit = nullptr;
8315  };
8316 
8322  class parser
8323  {
8324  public:
8326  parser(const string_t& s, parser_callback_t cb = nullptr)
8327  : callback(cb), m_lexer(s)
8328  {
8329  // read first token
8330  get_token();
8331  }
8332 
8334  parser(std::istream& _is, parser_callback_t cb = nullptr)
8335  : callback(cb), m_lexer(&_is)
8336  {
8337  // read first token
8338  get_token();
8339  }
8340 
8342  basic_json parse()
8343  {
8344  basic_json result = parse_internal(true);
8345 
8346  expect(lexer::token_type::end_of_input);
8347 
8348  // return parser result and replace it with null in case the
8349  // top-level value was discarded by the callback function
8350  return result.is_discarded() ? basic_json() : result;
8351  }
8352 
8353  private:
8355  basic_json parse_internal(bool keep)
8356  {
8357  auto result = basic_json(value_t::discarded);
8358 
8359  switch (last_token)
8360  {
8361  case lexer::token_type::begin_object:
8362  {
8363  if (keep and (not callback or (keep = callback(depth++, parse_event_t::object_start, result))))
8364  {
8365  // explicitly set result to object to cope with {}
8366  result.m_type = value_t::object;
8367  result.m_value = json_value(value_t::object);
8368  }
8369 
8370  // read next token
8371  get_token();
8372 
8373  // closing } -> we are done
8374  if (last_token == lexer::token_type::end_object)
8375  {
8376  get_token();
8377  if (keep and callback and not callback(--depth, parse_event_t::object_end, result))
8378  {
8379  result = basic_json(value_t::discarded);
8380  }
8381  return result;
8382  }
8383 
8384  // no comma is expected here
8385  unexpect(lexer::token_type::value_separator);
8386 
8387  // otherwise: parse key-value pairs
8388  do
8389  {
8390  // ugly, but could be fixed with loop reorganization
8391  if (last_token == lexer::token_type::value_separator)
8392  {
8393  get_token();
8394  }
8395 
8396  // store key
8397  expect(lexer::token_type::value_string);
8398  const auto key = m_lexer.get_string();
8399 
8400  bool keep_tag = false;
8401  if (keep)
8402  {
8403  if (callback)
8404  {
8405  basic_json k(key);
8406  keep_tag = callback(depth, parse_event_t::key, k);
8407  }
8408  else
8409  {
8410  keep_tag = true;
8411  }
8412  }
8413 
8414  // parse separator (:)
8415  get_token();
8416  expect(lexer::token_type::name_separator);
8417 
8418  // parse and add value
8419  get_token();
8420  auto value = parse_internal(keep);
8421  if (keep and keep_tag and not value.is_discarded())
8422  {
8423  result[key] = std::move(value);
8424  }
8425  }
8426  while (last_token == lexer::token_type::value_separator);
8427 
8428  // closing }
8429  expect(lexer::token_type::end_object);
8430  get_token();
8431  if (keep and callback and not callback(--depth, parse_event_t::object_end, result))
8432  {
8433  result = basic_json(value_t::discarded);
8434  }
8435 
8436  return result;
8437  }
8438 
8439  case lexer::token_type::begin_array:
8440  {
8441  if (keep and (not callback or (keep = callback(depth++, parse_event_t::array_start, result))))
8442  {
8443  // explicitly set result to object to cope with []
8444  result.m_type = value_t::array;
8445  result.m_value = json_value(value_t::array);
8446  }
8447 
8448  // read next token
8449  get_token();
8450 
8451  // closing ] -> we are done
8452  if (last_token == lexer::token_type::end_array)
8453  {
8454  get_token();
8455  if (callback and not callback(--depth, parse_event_t::array_end, result))
8456  {
8457  result = basic_json(value_t::discarded);
8458  }
8459  return result;
8460  }
8461 
8462  // no comma is expected here
8463  unexpect(lexer::token_type::value_separator);
8464 
8465  // otherwise: parse values
8466  do
8467  {
8468  // ugly, but could be fixed with loop reorganization
8469  if (last_token == lexer::token_type::value_separator)
8470  {
8471  get_token();
8472  }
8473 
8474  // parse value
8475  auto value = parse_internal(keep);
8476  if (keep and not value.is_discarded())
8477  {
8478  result.push_back(std::move(value));
8479  }
8480  }
8481  while (last_token == lexer::token_type::value_separator);
8482 
8483  // closing ]
8484  expect(lexer::token_type::end_array);
8485  get_token();
8486  if (keep and callback and not callback(--depth, parse_event_t::array_end, result))
8487  {
8488  result = basic_json(value_t::discarded);
8489  }
8490 
8491  return result;
8492  }
8493 
8494  case lexer::token_type::literal_null:
8495  {
8496  get_token();
8497  result.m_type = value_t::null;
8498  break;
8499  }
8500 
8501  case lexer::token_type::value_string:
8502  {
8503  const auto s = m_lexer.get_string();
8504  get_token();
8505  result = basic_json(s);
8506  break;
8507  }
8508 
8509  case lexer::token_type::literal_true:
8510  {
8511  get_token();
8512  result.m_type = value_t::boolean;
8513  result.m_value = true;
8514  break;
8515  }
8516 
8517  case lexer::token_type::literal_false:
8518  {
8519  get_token();
8520  result.m_type = value_t::boolean;
8521  result.m_value = false;
8522  break;
8523  }
8524 
8525  case lexer::token_type::value_number:
8526  {
8527  m_lexer.get_number(result);
8528  get_token();
8529  break;
8530  }
8531 
8532  default:
8533  {
8534  // the last token was unexpected
8535  unexpect(last_token);
8536  }
8537  }
8538 
8539  if (keep and callback and not callback(depth, parse_event_t::value, result))
8540  {
8541  result = basic_json(value_t::discarded);
8542  }
8543  return result;
8544  }
8545 
8547  typename lexer::token_type get_token()
8548  {
8549  last_token = m_lexer.scan();
8550  return last_token;
8551  }
8552 
8553  void expect(typename lexer::token_type t) const
8554  {
8555  if (t != last_token)
8556  {
8557  std::string error_msg = "parse error - unexpected ";
8558  error_msg += (last_token == lexer::token_type::parse_error ? ("'" + m_lexer.get_token() + "'") :
8559  lexer::token_type_name(last_token));
8560  error_msg += "; expected " + lexer::token_type_name(t);
8561  throw std::invalid_argument(error_msg);
8562  }
8563  }
8564 
8565  void unexpect(typename lexer::token_type t) const
8566  {
8567  if (t == last_token)
8568  {
8569  std::string error_msg = "parse error - unexpected ";
8570  error_msg += (last_token == lexer::token_type::parse_error ? ("'" + m_lexer.get_token() + "'") :
8571  lexer::token_type_name(last_token));
8572  throw std::invalid_argument(error_msg);
8573  }
8574  }
8575 
8576  private:
8578  int depth = 0;
8580  parser_callback_t callback;
8582  typename lexer::token_type last_token = lexer::token_type::uninitialized;
8584  lexer m_lexer;
8585  };
8586 };
8587 
8588 
8590 // presets //
8592 
8602 }
8603 
8604 
8606 // nonmember functions //
8608 
8609 // specialization of std::swap, and std::hash
8610 namespace std
8611 {
8617 template <>
8618 inline void swap(nlohmann::json& j1,
8619  nlohmann::json& j2) noexcept(
8620  is_nothrow_move_constructible<nlohmann::json>::value and
8621  is_nothrow_move_assignable<nlohmann::json>::value
8622  )
8623 {
8624  j1.swap(j2);
8625 }
8626 
8628 template <>
8629 struct hash<nlohmann::json>
8630 {
8636  std::size_t operator()(const nlohmann::json& j) const
8637  {
8638  // a naive hashing via the string representation
8639  const auto& h = hash<nlohmann::json::string_t>();
8640  return h(j.dump());
8641  }
8642 };
8643 }
8644 
8657 inline nlohmann::json operator "" _json(const char* s, std::size_t)
8658 {
8659  return nlohmann::json::parse(reinterpret_cast<const nlohmann::json::string_t::value_type*>(s));
8660 }
8661 
8662 // restore GCC/clang diagnostic settings
8663 #if defined(__clang__) || defined(__GNUC__) || defined(__GNUG__)
8664  #pragma GCC diagnostic pop
8665 #endif
8666 
8667 #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:6793
reverse_iterator rbegin()
returns an iterator to the reverse-beginning
Definition: json.hpp:4173
friend bool operator<=(const_reference lhs, const_reference rhs) noexcept
comparison: less than or equal
Definition: json.hpp:5431
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:3991
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:3203
reference value() const
return the value of an iterator
Definition: json.hpp:6877
json_reverse_iterator & operator--()
pre-decrement (–it)
Definition: json.hpp:6939
bool is_boolean() const noexcept
return whether value is a boolean
Definition: json.hpp:2188
void clear() noexcept
clears the contents
Definition: json.hpp:4541
bool operator==(const const_iterator &other) const
comparison: equal
Definition: json.hpp:6527
json_reverse_iterator operator--(int)
post-decrement (it–)
Definition: json.hpp:6933
reference operator[](T *(&key)[n])
access specified object element
Definition: json.hpp:3335
friend std::istream & operator>>(std::istream &i, basic_json &j)
deserialize from stream
Definition: json.hpp:5644
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:6835
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:6653
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:4727
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:6975
iterator find(typename object_t::key_type key)
find an element in a JSON object
Definition: json.hpp:3943
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:5269
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:4653
void erase(const size_type idx)
remove element from a JSON array given an index
Definition: json.hpp:3907
basic_json<> json
default JSON class
Definition: json.hpp:8601
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:3574
void swap(object_t &other)
exchanges the values
Definition: json.hpp:5025
json_reverse_iterator operator-(difference_type i) const
subtract from iterator
Definition: json.hpp:6961
const_iterator & operator+=(difference_type i)
add to iterator
Definition: json.hpp:6611
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:6799
reference value() const
return the value of an iterator
Definition: json.hpp:6988
friend bool operator==(std::nullptr_t, const_reference v) noexcept
comparison: equal
Definition: json.hpp:5248
const_reverse_iterator crbegin() const
returns a const reverse iterator to the last element
Definition: json.hpp:4247
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:4811
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:6645
const_reverse_iterator rbegin() const
returns a const reverse iterator to the last element
Definition: json.hpp:4181
a mutable random access iterator for the basic_json class
Definition: json.hpp:6760
static basic_json parse(std::istream &&i, parser_callback_t cb=nullptr)
deserialize from stream
Definition: json.hpp:5606
const_iterator operator++(int)
post-increment (it++)
Definition: json.hpp:6453
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:4305
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:6225
PointerType get_ptr() noexcept
get a pointer value (implicit)
Definition: json.hpp:2825
reference back()
access the last element
Definition: json.hpp:3612
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:6229
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:4703
iterator end()
returns an iterator to one past the last element
Definition: json.hpp:4103
static basic_json parse(const string_t &s, parser_callback_t cb=nullptr)
deserialize from string
Definition: json.hpp:5569
const_reference operator[](T *(&key)[n]) const
read-only access specified object element
Definition: json.hpp:3370
iterator insert(const_iterator pos, const_iterator first, const_iterator last)
inserts elements
Definition: json.hpp:4864
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:6871
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:3292
const_reference operator[](T *key) const
read-only access specified object element
Definition: json.hpp:3452
json_reverse_iterator operator+(difference_type i) const
add to iterator
Definition: json.hpp:6953
bool empty() const noexcept
checks whether the container is empty
Definition: json.hpp:4353
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:6981
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:6905
iterator insert(const_iterator pos, std::initializer_list< basic_json > ilist)
inserts elements
Definition: json.hpp:4922
const_iterator(const iterator &other)
copy constructor given a nonconst iterator
Definition: json.hpp:6266
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:4755
friend bool operator>=(const_reference lhs, const_reference rhs) noexcept
comparison: greater than or equal
Definition: json.hpp:5475
friend bool operator<(const_reference lhs, const_reference rhs) noexcept
comparison: less than
Definition: json.hpp:5330
iterator & operator++()
pre-increment (++it)
Definition: json.hpp:6813
bool operator<(const const_iterator &other) const
comparison: smaller
Definition: json.hpp:6563
iterator operator++(int)
post-increment (it++)
Definition: json.hpp:6805
basic_json(basic_json &&other) noexcept
move constructor
Definition: json.hpp:1939
const_iterator operator--(int)
post-decrement (it–)
Definition: json.hpp:6490
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:6781
object (unordered set of name/value pairs)
size_type max_size() const noexcept
returns the maximum possible number of elements
Definition: json.hpp:4482
~basic_json()
destructor
Definition: json.hpp:1999
iterator operator--(int)
post-decrement (it–)
Definition: json.hpp:6820
iterator operator-(difference_type i)
subtract from iterator
Definition: json.hpp:6857
const_iterator & operator--()
pre-decrement (–it)
Definition: json.hpp:6498
const_iterator cend() const
returns a const iterator to one past the last element
Definition: json.hpp:4143
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:4677
iterator begin()
returns an iterator to the first element
Definition: json.hpp:4032
difference_type operator-(const const_iterator &other) const
return difference
Definition: json.hpp:6661
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:4042
friend std::ostream & operator>>(const basic_json &j, std::ostream &o)
serialize to stream
Definition: json.hpp:5530
difference_type operator-(const iterator &other) const
return difference
Definition: json.hpp:6865
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:6776
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:6227
void swap(string_t &other)
exchanges the values
Definition: json.hpp:5059
json_reverse_iterator(const base_iterator &it)
create reverse iterator from base class
Definition: json.hpp:6915
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:4210
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:3582
bool operator>(const const_iterator &other) const
comparison: greater than
Definition: json.hpp:6599
bool is_object() const noexcept
return whether value is an object
Definition: json.hpp:2310
pointer operator->() const
dereference the iterator
Definition: json.hpp:6418
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:4960
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:4218
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:4991
InteratorType erase(InteratorType first, InteratorType last)
remove elements given an iterator range
Definition: json.hpp:3785
ValueType value(const typename object_t::key_type &key, ValueType default_value) const
access specified object element with default value
Definition: json.hpp:3519
typename Base::reference reference
the reference type for the pointed-to element
Definition: json.hpp:6907
const_reference back() const
access the last element
Definition: json.hpp:3622
void push_back(basic_json &&val)
add an object to an array
Definition: json.hpp:4617
array (ordered collection of values)
json_reverse_iterator & operator++()
pre-increment (++it)
Definition: json.hpp:6926
static basic_json parse(std::istream &i, parser_callback_t cb=nullptr)
deserialize from stream
Definition: json.hpp:5598
friend bool operator==(const_reference lhs, const_reference rhs) noexcept
comparison: equal
Definition: json.hpp:5140
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:3545
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:6239
reference operator*() const
return a reference to the value pointed to by the iterator
Definition: json.hpp:6378
friend bool operator<(const value_t lhs, const value_t rhs)
comparison operator for JSON types
Definition: json.hpp:5093
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:5292
iterator operator+(difference_type i)
add to iterator
Definition: json.hpp:6849
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:6593
InteratorType erase(InteratorType pos)
remove element given an iterator
Definition: json.hpp:3679
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:6771
friend bool operator!=(std::nullptr_t, const_reference v) noexcept
comparison: not equal
Definition: json.hpp:5301
json_reverse_iterator(const typename base_iterator::iterator_type &it)
create reverse iterator from iterator
Definition: json.hpp:6910
const_iterator & operator++()
pre-increment (++it)
Definition: json.hpp:6461
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:6736
std::bidirectional_iterator_tag iterator_category
the category of the iterator
Definition: json.hpp:6233
difference_type operator-(const json_reverse_iterator &other) const
return difference
Definition: json.hpp:6969
const_iterator find(typename object_t::key_type key) const
find an element in a JSON object
Definition: json.hpp:3960
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:5453
bool operator>=(const const_iterator &other) const
comparison: greater than or equal
Definition: json.hpp:6605
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:6298
size_type erase(const typename object_t::key_type &key)
remove element from a JSON object given a key
Definition: json.hpp:3869
reference operator[](const typename object_t::key_type &key)
access specified object element
Definition: json.hpp:3244
object_t::key_type key() const
return the key of an object iterator
Definition: json.hpp:6721
const_iterator end() const
returns a const iterator to one past the last element
Definition: json.hpp:4113
reference operator+=(basic_json &&val)
add an object to an array
Definition: json.hpp:4643
reference operator[](difference_type n) const
access to successor
Definition: json.hpp:6685
a const random access iterator for the basic_json class
Definition: json.hpp:6218
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:6231
json_reverse_iterator operator++(int)
post-increment (it++)
Definition: json.hpp:6920
friend bool operator==(const_reference v, std::nullptr_t) noexcept
comparison: equal
Definition: json.hpp:5239
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:6557
json_reverse_iterator & operator+=(difference_type i)
add to iterator
Definition: json.hpp:6946
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:4416
static iteration_proxy< iterator > iterator_wrapper(reference cont)
wrapper to access iterator member functions in range-based for
Definition: json.hpp:4297
const_iterator cbegin() const
returns a const iterator to the first element
Definition: json.hpp:4072
iterator & operator-=(difference_type i)
subtract from iterator
Definition: json.hpp:6842
const_reverse_iterator crend() const
returns a const reverse iterator to one before the first
Definition: json.hpp:4276
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:5634
std::size_t operator()(const nlohmann::json &j) const
return a hash value for a JSON object
Definition: json.hpp:8636
friend std::ostream & operator<<(std::ostream &o, const basic_json &j)
serialize to stream
Definition: json.hpp:5512
const_iterator(const const_iterator &other) noexcept
copy constructor
Definition: json.hpp:6293
iterator & operator--()
pre-decrement (–it)
Definition: json.hpp:6828
iterator insert(const_iterator pos, basic_json &&val)
inserts element
Definition: json.hpp:4782
ReferenceType get_ref()
get a reference value (implicit)
Definition: json.hpp:2876
const_iterator & operator-=(difference_type i)
subtract from iterator
Definition: json.hpp:6639
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:3403
parse_event_t
JSON callback events.
Definition: json.hpp:831