JSON for Modern C++  2.0.0
json.hpp
1 /*
2  __ _____ _____ _____
3  __| | __| | | | JSON for Modern C++
4 | | |__ | | | | | | version 2.0.0
5 |_____|_____|_____|_|___| https://github.com/nlohmann/json
6 
7 Copyright (c) 2013-2016 Niels Lohmann <http://nlohmann.me>.
8 Licensed under the MIT License <http://opensource.org/licenses/MIT>.
9 */
10 
11 #ifndef NLOHMANN_JSON_HPP
12 #define NLOHMANN_JSON_HPP
13 
14 #include <algorithm>
15 #include <array>
16 #include <cassert>
17 #include <ciso646>
18 #include <cmath>
19 #include <cstddef>
20 #include <cstdio>
21 #include <cstdlib>
22 #include <functional>
23 #include <initializer_list>
24 #include <iomanip>
25 #include <iostream>
26 #include <iterator>
27 #include <limits>
28 #include <map>
29 #include <memory>
30 #include <sstream>
31 #include <stdexcept>
32 #include <string>
33 #include <type_traits>
34 #include <utility>
35 #include <vector>
36 
37 // enable ssize_t on MinGW
38 #ifdef __GNUC__
39  #ifdef __MINGW32__
40  #include <sys/types.h>
41  #endif
42 #endif
43 
44 // disable float-equal warnings on GCC/clang
45 #if defined(__clang__) || defined(__GNUC__) || defined(__GNUG__)
46  #pragma GCC diagnostic push
47  #pragma GCC diagnostic ignored "-Wfloat-equal"
48 #endif
49 
50 // enable ssize_t for MSVC
51 #ifdef _MSC_VER
52  #include <basetsd.h>
53  using ssize_t = SSIZE_T;
54 #endif
55 
61 namespace nlohmann
62 {
63 
64 
69 namespace
70 {
75 template<typename T>
76 struct has_mapped_type
77 {
78  private:
79  template<typename C> static char test(typename C::mapped_type*);
80  template<typename C> static char (&test(...))[2];
81  public:
82  static constexpr bool value = sizeof(test<T>(0)) == 1;
83 };
84 
85 }
86 
158 template <
159  template<typename U, typename V, typename... Args> class ObjectType = std::map,
160  template<typename U, typename... Args> class ArrayType = std::vector,
161  class StringType = std::string,
162  class BooleanType = bool,
163  class NumberIntegerType = int64_t,
164  class NumberUnsignedType = uint64_t,
165  class NumberFloatType = double,
166  template<typename U> class AllocatorType = std::allocator
167  >
169 {
170  private:
172  using basic_json_t = basic_json<ObjectType,
173  ArrayType,
174  StringType,
175  BooleanType,
176  NumberIntegerType,
177  NumberUnsignedType,
178  NumberFloatType,
179  AllocatorType>;
180 
181  public:
182 
184  // container types //
186 
189 
192 
196  using const_reference = const value_type&;
197 
199  using difference_type = std::ptrdiff_t;
201  using size_type = std::size_t;
202 
204  using allocator_type = AllocatorType<basic_json>;
205 
207  using pointer = typename std::allocator_traits<allocator_type>::pointer;
209  using const_pointer = typename std::allocator_traits<allocator_type>::const_pointer;
210 
211  // forward declaration
212  template<typename Base> class json_reverse_iterator;
213 
215  class iterator;
217  class const_iterator;
222 
224 
225 
230  {
231  return allocator_type();
232  }
233 
234 
236  // JSON value data types //
238 
241 
324  using object_t = ObjectType<StringType,
325  basic_json,
326  std::less<StringType>,
327  AllocatorType<std::pair<const StringType,
328  basic_json>>>;
329 
374  using array_t = ArrayType<basic_json, AllocatorType<basic_json>>;
375 
421  using string_t = StringType;
422 
447  using boolean_t = BooleanType;
448 
518  using number_integer_t = NumberIntegerType;
519 
590  using number_unsigned_t = NumberUnsignedType;
591 
658  using number_float_t = NumberFloatType;
659 
661 
662 
664  // JSON type enumeration //
666 
677  enum class value_t : uint8_t
678  {
679  null,
680  object,
681  array,
682  string,
683  boolean,
684  number_integer,
685  number_unsigned,
686  number_float,
687  discarded
688  };
689 
690 
691  private:
693  template<typename T, typename... Args>
694  static T* create(Args&& ... args)
695  {
696  AllocatorType<T> alloc;
697  auto deleter = [&](T * object)
698  {
699  alloc.deallocate(object, 1);
700  };
701  std::unique_ptr<T, decltype(deleter)> object(alloc.allocate(1), deleter);
702  alloc.construct(object.get(), std::forward<Args>(args)...);
703  return object.release();
704  }
705 
707  // JSON value storage //
709 
717  union json_value
718  {
720  object_t* object;
722  array_t* array;
724  string_t* string;
726  boolean_t boolean;
728  number_integer_t number_integer;
730  number_unsigned_t number_unsigned;
732  number_float_t number_float;
733 
735  json_value() noexcept = default;
737  json_value(boolean_t v) noexcept : boolean(v) {}
739  json_value(number_integer_t v) noexcept : number_integer(v) {}
741  json_value(number_unsigned_t v) noexcept : number_unsigned(v) {}
743  json_value(number_float_t v) noexcept : number_float(v) {}
745  json_value(value_t t)
746  {
747  switch (t)
748  {
749  case value_t::object:
750  {
751  object = create<object_t>();
752  break;
753  }
754 
755  case value_t::array:
756  {
757  array = create<array_t>();
758  break;
759  }
760 
761  case value_t::string:
762  {
763  string = create<string_t>("");
764  break;
765  }
766 
767  case value_t::boolean:
768  {
769  boolean = boolean_t(false);
770  break;
771  }
772 
773  case value_t::number_integer:
774  {
775  number_integer = number_integer_t(0);
776  break;
777  }
778 
779  case value_t::number_unsigned:
780  {
781  number_unsigned = number_unsigned_t(0);
782  break;
783  }
784 
785  case value_t::number_float:
786  {
787  number_float = number_float_t(0.0);
788  break;
789  }
790 
791  default:
792  {
793  break;
794  }
795  }
796  }
797 
799  json_value(const string_t& value)
800  {
801  string = create<string_t>(value);
802  }
803 
805  json_value(const object_t& value)
806  {
807  object = create<object_t>(value);
808  }
809 
811  json_value(const array_t& value)
812  {
813  array = create<array_t>(value);
814  }
815  };
816 
817 
818  public:
820  // JSON parser callback //
822 
831  enum class parse_event_t : uint8_t
832  {
834  object_start,
836  object_end,
838  array_start,
840  array_end,
842  key,
844  value
845  };
846 
896  using parser_callback_t = std::function<bool(int depth, parse_event_t event, basic_json& parsed)>;
897 
898 
900  // constructors //
902 
905 
946  : m_type(value_type), m_value(value_type)
947  {}
948 
970  basic_json() noexcept = default;
971 
991  basic_json(std::nullptr_t) noexcept
992  : basic_json(value_t::null)
993  {}
994 
1014  basic_json(const object_t& val)
1015  : m_type(value_t::object), m_value(val)
1016  {}
1017 
1041  template <class CompatibleObjectType, typename
1042  std::enable_if<
1043  std::is_constructible<typename object_t::key_type, typename CompatibleObjectType::key_type>::value and
1044  std::is_constructible<basic_json, typename CompatibleObjectType::mapped_type>::value, int>::type
1045  = 0>
1046  basic_json(const CompatibleObjectType& val)
1047  : m_type(value_t::object)
1048  {
1049  using std::begin;
1050  using std::end;
1051  m_value.object = create<object_t>(begin(val), end(val));
1052  }
1053 
1073  basic_json(const array_t& val)
1074  : m_type(value_t::array), m_value(val)
1075  {}
1076 
1100  template <class CompatibleArrayType, typename
1101  std::enable_if<
1102  not std::is_same<CompatibleArrayType, typename basic_json_t::iterator>::value and
1103  not std::is_same<CompatibleArrayType, typename basic_json_t::const_iterator>::value and
1104  not std::is_same<CompatibleArrayType, typename basic_json_t::reverse_iterator>::value and
1105  not std::is_same<CompatibleArrayType, typename basic_json_t::const_reverse_iterator>::value and
1106  not std::is_same<CompatibleArrayType, typename array_t::iterator>::value and
1107  not std::is_same<CompatibleArrayType, typename array_t::const_iterator>::value and
1108  std::is_constructible<basic_json, typename CompatibleArrayType::value_type>::value, int>::type
1109  = 0>
1110  basic_json(const CompatibleArrayType& val)
1111  : m_type(value_t::array)
1112  {
1113  using std::begin;
1114  using std::end;
1115  m_value.array = create<array_t>(begin(val), end(val));
1116  }
1117 
1139  basic_json(const string_t& val)
1140  : m_type(value_t::string), m_value(val)
1141  {}
1142 
1163  basic_json(const typename string_t::value_type* val)
1164  : basic_json(string_t(val))
1165  {}
1166 
1190  template <class CompatibleStringType, typename
1191  std::enable_if<
1192  std::is_constructible<string_t, CompatibleStringType>::value, int>::type
1193  = 0>
1194  basic_json(const CompatibleStringType& val)
1195  : basic_json(string_t(val))
1196  {}
1197 
1213  : m_type(value_t::boolean), m_value(val)
1214  {}
1215 
1241  template<typename T,
1242  typename std::enable_if<
1243  not (std::is_same<T, int>::value)
1244  and std::is_same<T, number_integer_t>::value
1245  , int>::type
1246  = 0>
1248  : m_type(value_t::number_integer), m_value(val)
1249  {}
1250 
1276  basic_json(const int val)
1277  : m_type(value_t::number_integer),
1278  m_value(static_cast<number_integer_t>(val))
1279  {}
1280 
1306  template<typename CompatibleNumberIntegerType, typename
1307  std::enable_if<
1308  std::is_constructible<number_integer_t, CompatibleNumberIntegerType>::value and
1309  std::numeric_limits<CompatibleNumberIntegerType>::is_integer and
1310  std::numeric_limits<CompatibleNumberIntegerType>::is_signed,
1311  CompatibleNumberIntegerType>::type
1312  = 0>
1313  basic_json(const CompatibleNumberIntegerType val) noexcept
1314  : m_type(value_t::number_integer),
1315  m_value(static_cast<number_integer_t>(val))
1316  {}
1317 
1335  template<typename T,
1336  typename std::enable_if<
1337  not (std::is_same<T, int>::value)
1338  and std::is_same<T, number_unsigned_t>::value
1339  , int>::type
1340  = 0>
1342  : m_type(value_t::number_unsigned), m_value(val)
1343  {}
1344 
1365  template < typename CompatibleNumberUnsignedType, typename
1366  std::enable_if <
1367  std::is_constructible<number_unsigned_t, CompatibleNumberUnsignedType>::value and
1368  std::numeric_limits<CompatibleNumberUnsignedType>::is_integer and
1369  !std::numeric_limits<CompatibleNumberUnsignedType>::is_signed,
1370  CompatibleNumberUnsignedType >::type
1371  = 0 >
1372  basic_json(const CompatibleNumberUnsignedType val) noexcept
1373  : m_type(value_t::number_unsigned),
1374  m_value(static_cast<number_unsigned_t>(val))
1375  {}
1376 
1402  : m_type(value_t::number_float), m_value(val)
1403  {
1404  // replace infinity and NAN by null
1405  if (not std::isfinite(val))
1406  {
1407  m_type = value_t::null;
1408  m_value = json_value();
1409  }
1410  }
1411 
1442  template<typename CompatibleNumberFloatType, typename = typename
1443  std::enable_if<
1444  std::is_constructible<number_float_t, CompatibleNumberFloatType>::value and
1445  std::is_floating_point<CompatibleNumberFloatType>::value>::type
1446  >
1447  basic_json(const CompatibleNumberFloatType val) noexcept
1448  : basic_json(number_float_t(val))
1449  {}
1450 
1520  basic_json(std::initializer_list<basic_json> init,
1521  bool type_deduction = true,
1522  value_t manual_type = value_t::array)
1523  {
1524  // the initializer list could describe an object
1525  bool is_an_object = true;
1526 
1527  // check if each element is an array with two elements whose first
1528  // element is a string
1529  for (const auto& element : init)
1530  {
1531  if (not element.is_array() or element.size() != 2
1532  or not element[0].is_string())
1533  {
1534  // we found an element that makes it impossible to use the
1535  // initializer list as object
1536  is_an_object = false;
1537  break;
1538  }
1539  }
1540 
1541  // adjust type if type deduction is not wanted
1542  if (not type_deduction)
1543  {
1544  // if array is wanted, do not create an object though possible
1545  if (manual_type == value_t::array)
1546  {
1547  is_an_object = false;
1548  }
1549 
1550  // if object is wanted but impossible, throw an exception
1551  if (manual_type == value_t::object and not is_an_object)
1552  {
1553  throw std::domain_error("cannot create object from initializer list");
1554  }
1555  }
1556 
1557  if (is_an_object)
1558  {
1559  // the initializer list is a list of pairs -> create object
1560  m_type = value_t::object;
1561  m_value = value_t::object;
1562 
1563  assert(m_value.object != nullptr);
1564 
1565  for (auto& element : init)
1566  {
1567  m_value.object->emplace(std::move(*(element[0].m_value.string)), std::move(element[1]));
1568  }
1569  }
1570  else
1571  {
1572  // the initializer list describes an array -> create array
1573  m_type = value_t::array;
1574  m_value.array = create<array_t>(std::move(init));
1575  }
1576  }
1577 
1612  static basic_json array(std::initializer_list<basic_json> init =
1613  std::initializer_list<basic_json>())
1614  {
1615  return basic_json(init, false, value_t::array);
1616  }
1617 
1652  static basic_json object(std::initializer_list<basic_json> init =
1653  std::initializer_list<basic_json>())
1654  {
1655  return basic_json(init, false, value_t::object);
1656  }
1657 
1676  basic_json(size_type cnt, const basic_json& val)
1677  : m_type(value_t::array)
1678  {
1679  m_value.array = create<array_t>(cnt, val);
1680  }
1681 
1716  template <class InputIT, typename
1717  std::enable_if<
1718  std::is_same<InputIT, typename basic_json_t::iterator>::value or
1719  std::is_same<InputIT, typename basic_json_t::const_iterator>::value
1720  , int>::type
1721  = 0>
1722  basic_json(InputIT first, InputIT last) : m_type(first.m_object->m_type)
1723  {
1724  // make sure iterator fits the current value
1725  if (first.m_object != last.m_object)
1726  {
1727  throw std::domain_error("iterators are not compatible");
1728  }
1729 
1730  // check if iterator range is complete for primitive values
1731  switch (m_type)
1732  {
1733  case value_t::boolean:
1734  case value_t::number_float:
1735  case value_t::number_integer:
1736  case value_t::number_unsigned:
1737  case value_t::string:
1738  {
1739  if (not first.m_it.primitive_iterator.is_begin() or not last.m_it.primitive_iterator.is_end())
1740  {
1741  throw std::out_of_range("iterators out of range");
1742  }
1743  break;
1744  }
1745 
1746  default:
1747  {
1748  break;
1749  }
1750  }
1751 
1752  switch (m_type)
1753  {
1754  case value_t::number_integer:
1755  {
1756  assert(first.m_object != nullptr);
1757  m_value.number_integer = first.m_object->m_value.number_integer;
1758  break;
1759  }
1760 
1761  case value_t::number_unsigned:
1762  {
1763  assert(first.m_object != nullptr);
1764  m_value.number_unsigned = first.m_object->m_value.number_unsigned;
1765  break;
1766  }
1767 
1768  case value_t::number_float:
1769  {
1770  assert(first.m_object != nullptr);
1771  m_value.number_float = first.m_object->m_value.number_float;
1772  break;
1773  }
1774 
1775  case value_t::boolean:
1776  {
1777  assert(first.m_object != nullptr);
1778  m_value.boolean = first.m_object->m_value.boolean;
1779  break;
1780  }
1781 
1782  case value_t::string:
1783  {
1784  assert(first.m_object != nullptr);
1785  m_value = *first.m_object->m_value.string;
1786  break;
1787  }
1788 
1789  case value_t::object:
1790  {
1791  m_value.object = create<object_t>(first.m_it.object_iterator, last.m_it.object_iterator);
1792  break;
1793  }
1794 
1795  case value_t::array:
1796  {
1797  m_value.array = create<array_t>(first.m_it.array_iterator, last.m_it.array_iterator);
1798  break;
1799  }
1800 
1801  default:
1802  {
1803  assert(first.m_object != nullptr);
1804  throw std::domain_error("cannot use construct with iterators from " + first.m_object->type_name());
1805  }
1806  }
1807  }
1808 
1829  basic_json(std::istream& i, parser_callback_t cb = nullptr)
1830  {
1831  *this = parser(i, cb).parse();
1832  }
1833 
1835  // other constructors and destructor //
1837 
1860  basic_json(const basic_json& other)
1861  : m_type(other.m_type)
1862  {
1863  switch (m_type)
1864  {
1865  case value_t::object:
1866  {
1867  assert(other.m_value.object != nullptr);
1868  m_value = *other.m_value.object;
1869  break;
1870  }
1871 
1872  case value_t::array:
1873  {
1874  assert(other.m_value.array != nullptr);
1875  m_value = *other.m_value.array;
1876  break;
1877  }
1878 
1879  case value_t::string:
1880  {
1881  assert(other.m_value.string != nullptr);
1882  m_value = *other.m_value.string;
1883  break;
1884  }
1885 
1886  case value_t::boolean:
1887  {
1888  m_value = other.m_value.boolean;
1889  break;
1890  }
1891 
1892  case value_t::number_integer:
1893  {
1894  m_value = other.m_value.number_integer;
1895  break;
1896  }
1897 
1898  case value_t::number_unsigned:
1899  {
1900  m_value = other.m_value.number_unsigned;
1901  break;
1902  }
1903 
1904  case value_t::number_float:
1905  {
1906  m_value = other.m_value.number_float;
1907  break;
1908  }
1909 
1910  default:
1911  {
1912  break;
1913  }
1914  }
1915  }
1916 
1935  basic_json(basic_json&& other) noexcept
1936  : m_type(std::move(other.m_type)),
1937  m_value(std::move(other.m_value))
1938  {
1939  // invalidate payload
1940  other.m_type = value_t::null;
1941  other.m_value = {};
1942  }
1943 
1967  reference& operator=(basic_json other) noexcept (
1968  std::is_nothrow_move_constructible<value_t>::value and
1969  std::is_nothrow_move_assignable<value_t>::value and
1970  std::is_nothrow_move_constructible<json_value>::value and
1971  std::is_nothrow_move_assignable<json_value>::value
1972  )
1973  {
1974  using std::swap;
1975  swap(m_type, other.m_type);
1976  swap(m_value, other.m_value);
1977  return *this;
1978  }
1979 
1996  {
1997  switch (m_type)
1998  {
1999  case value_t::object:
2000  {
2001  AllocatorType<object_t> alloc;
2002  alloc.destroy(m_value.object);
2003  alloc.deallocate(m_value.object, 1);
2004  break;
2005  }
2006 
2007  case value_t::array:
2008  {
2009  AllocatorType<array_t> alloc;
2010  alloc.destroy(m_value.array);
2011  alloc.deallocate(m_value.array, 1);
2012  break;
2013  }
2014 
2015  case value_t::string:
2016  {
2017  AllocatorType<string_t> alloc;
2018  alloc.destroy(m_value.string);
2019  alloc.deallocate(m_value.string, 1);
2020  break;
2021  }
2022 
2023  default:
2024  {
2025  // all other types need no specific destructor
2026  break;
2027  }
2028  }
2029  }
2030 
2032 
2033  public:
2035  // object inspection //
2037 
2040 
2064  string_t dump(const int indent = -1) const
2065  {
2066  std::stringstream ss;
2067 
2068  if (indent >= 0)
2069  {
2070  dump(ss, true, static_cast<unsigned int>(indent));
2071  }
2072  else
2073  {
2074  dump(ss, false, 0);
2075  }
2076 
2077  return ss.str();
2078  }
2079 
2095  value_t type() const noexcept
2096  {
2097  return m_type;
2098  }
2099 
2122  bool is_primitive() const noexcept
2123  {
2124  return is_null() or is_string() or is_boolean() or is_number();
2125  }
2126 
2146  bool is_structured() const noexcept
2147  {
2148  return is_array() or is_object();
2149  }
2150 
2165  bool is_null() const noexcept
2166  {
2167  return m_type == value_t::null;
2168  }
2169 
2184  bool is_boolean() const noexcept
2185  {
2186  return m_type == value_t::boolean;
2187  }
2188 
2211  bool is_number() const noexcept
2212  {
2213  return is_number_integer() or is_number_float();
2214  }
2215 
2237  bool is_number_integer() const noexcept
2238  {
2239  return m_type == value_t::number_integer or m_type == value_t::number_unsigned;
2240  }
2241 
2262  bool is_number_unsigned() const noexcept
2263  {
2264  return m_type == value_t::number_unsigned;
2265  }
2266 
2287  bool is_number_float() const noexcept
2288  {
2289  return m_type == value_t::number_float;
2290  }
2291 
2306  bool is_object() const noexcept
2307  {
2308  return m_type == value_t::object;
2309  }
2310 
2325  bool is_array() const noexcept
2326  {
2327  return m_type == value_t::array;
2328  }
2329 
2344  bool is_string() const noexcept
2345  {
2346  return m_type == value_t::string;
2347  }
2348 
2368  bool is_discarded() const noexcept
2369  {
2370  return m_type == value_t::discarded;
2371  }
2372 
2388  operator value_t() const noexcept
2389  {
2390  return m_type;
2391  }
2392 
2394 
2395  private:
2397  // value access //
2399 
2401  template <class T, typename
2402  std::enable_if<
2403  std::is_convertible<typename object_t::key_type, typename T::key_type>::value and
2404  std::is_convertible<basic_json_t, typename T::mapped_type>::value
2405  , int>::type = 0>
2406  T get_impl(T*) const
2407  {
2408  if (is_object())
2409  {
2410  assert(m_value.object != nullptr);
2411  return T(m_value.object->begin(), m_value.object->end());
2412  }
2413  else
2414  {
2415  throw std::domain_error("type must be object, but is " + type_name());
2416  }
2417  }
2418 
2420  object_t get_impl(object_t*) const
2421  {
2422  if (is_object())
2423  {
2424  assert(m_value.object != nullptr);
2425  return *(m_value.object);
2426  }
2427  else
2428  {
2429  throw std::domain_error("type must be object, but is " + type_name());
2430  }
2431  }
2432 
2434  template <class T, typename
2435  std::enable_if<
2436  std::is_convertible<basic_json_t, typename T::value_type>::value and
2437  not std::is_same<basic_json_t, typename T::value_type>::value and
2438  not std::is_arithmetic<T>::value and
2439  not std::is_convertible<std::string, T>::value and
2440  not has_mapped_type<T>::value
2441  , int>::type = 0>
2442  T get_impl(T*) const
2443  {
2444  if (is_array())
2445  {
2446  T to_vector;
2447  assert(m_value.array != nullptr);
2448  std::transform(m_value.array->begin(), m_value.array->end(),
2449  std::inserter(to_vector, to_vector.end()), [](basic_json i)
2450  {
2451  return i.get<typename T::value_type>();
2452  });
2453  return to_vector;
2454  }
2455  else
2456  {
2457  throw std::domain_error("type must be array, but is " + type_name());
2458  }
2459  }
2460 
2462  template <class T, typename
2463  std::enable_if<
2464  std::is_convertible<basic_json_t, T>::value and
2465  not std::is_same<basic_json_t, T>::value
2466  , int>::type = 0>
2467  std::vector<T> get_impl(std::vector<T>*) const
2468  {
2469  if (is_array())
2470  {
2471  std::vector<T> to_vector;
2472  assert(m_value.array != nullptr);
2473  to_vector.reserve(m_value.array->size());
2474  std::transform(m_value.array->begin(), m_value.array->end(),
2475  std::inserter(to_vector, to_vector.end()), [](basic_json i)
2476  {
2477  return i.get<T>();
2478  });
2479  return to_vector;
2480  }
2481  else
2482  {
2483  throw std::domain_error("type must be array, but is " + type_name());
2484  }
2485  }
2486 
2488  template <class T, typename
2489  std::enable_if<
2490  std::is_same<basic_json, typename T::value_type>::value and
2491  not has_mapped_type<T>::value
2492  , int>::type = 0>
2493  T get_impl(T*) const
2494  {
2495  if (is_array())
2496  {
2497  assert(m_value.array != nullptr);
2498  return T(m_value.array->begin(), m_value.array->end());
2499  }
2500  else
2501  {
2502  throw std::domain_error("type must be array, but is " + type_name());
2503  }
2504  }
2505 
2507  array_t get_impl(array_t*) const
2508  {
2509  if (is_array())
2510  {
2511  assert(m_value.array != nullptr);
2512  return *(m_value.array);
2513  }
2514  else
2515  {
2516  throw std::domain_error("type must be array, but is " + type_name());
2517  }
2518  }
2519 
2521  template <typename T, typename
2522  std::enable_if<
2523  std::is_convertible<string_t, T>::value
2524  , int>::type = 0>
2525  T get_impl(T*) const
2526  {
2527  if (is_string())
2528  {
2529  assert(m_value.string != nullptr);
2530  return *m_value.string;
2531  }
2532  else
2533  {
2534  throw std::domain_error("type must be string, but is " + type_name());
2535  }
2536  }
2537 
2539  template<typename T, typename
2540  std::enable_if<
2541  std::is_arithmetic<T>::value
2542  , int>::type = 0>
2543  T get_impl(T*) const
2544  {
2545  switch (m_type)
2546  {
2547  case value_t::number_integer:
2548  {
2549  return static_cast<T>(m_value.number_integer);
2550  }
2551 
2552  case value_t::number_unsigned:
2553  {
2554  return static_cast<T>(m_value.number_unsigned);
2555  }
2556 
2557  case value_t::number_float:
2558  {
2559  return static_cast<T>(m_value.number_float);
2560  }
2561 
2562  default:
2563  {
2564  throw std::domain_error("type must be number, but is " + type_name());
2565  }
2566  }
2567  }
2568 
2570  boolean_t get_impl(boolean_t*) const
2571  {
2572  if (is_boolean())
2573  {
2574  return m_value.boolean;
2575  }
2576  else
2577  {
2578  throw std::domain_error("type must be boolean, but is " + type_name());
2579  }
2580  }
2581 
2583  object_t* get_impl_ptr(object_t*) noexcept
2584  {
2585  return is_object() ? m_value.object : nullptr;
2586  }
2587 
2589  const object_t* get_impl_ptr(const object_t*) const noexcept
2590  {
2591  return is_object() ? m_value.object : nullptr;
2592  }
2593 
2595  array_t* get_impl_ptr(array_t*) noexcept
2596  {
2597  return is_array() ? m_value.array : nullptr;
2598  }
2599 
2601  const array_t* get_impl_ptr(const array_t*) const noexcept
2602  {
2603  return is_array() ? m_value.array : nullptr;
2604  }
2605 
2607  string_t* get_impl_ptr(string_t*) noexcept
2608  {
2609  return is_string() ? m_value.string : nullptr;
2610  }
2611 
2613  const string_t* get_impl_ptr(const string_t*) const noexcept
2614  {
2615  return is_string() ? m_value.string : nullptr;
2616  }
2617 
2619  boolean_t* get_impl_ptr(boolean_t*) noexcept
2620  {
2621  return is_boolean() ? &m_value.boolean : nullptr;
2622  }
2623 
2625  const boolean_t* get_impl_ptr(const boolean_t*) const noexcept
2626  {
2627  return is_boolean() ? &m_value.boolean : nullptr;
2628  }
2629 
2631  number_integer_t* get_impl_ptr(number_integer_t*) noexcept
2632  {
2633  return is_number_integer() ? &m_value.number_integer : nullptr;
2634  }
2635 
2637  const number_integer_t* get_impl_ptr(const number_integer_t*) const noexcept
2638  {
2639  return is_number_integer() ? &m_value.number_integer : nullptr;
2640  }
2641 
2643  number_unsigned_t* get_impl_ptr(number_unsigned_t*) noexcept
2644  {
2645  return is_number_unsigned() ? &m_value.number_unsigned : nullptr;
2646  }
2647 
2649  const number_unsigned_t* get_impl_ptr(const number_unsigned_t*) const noexcept
2650  {
2651  return is_number_unsigned() ? &m_value.number_unsigned : nullptr;
2652  }
2653 
2655  number_float_t* get_impl_ptr(number_float_t*) noexcept
2656  {
2657  return is_number_float() ? &m_value.number_float : nullptr;
2658  }
2659 
2661  const number_float_t* get_impl_ptr(const number_float_t*) const noexcept
2662  {
2663  return is_number_float() ? &m_value.number_float : nullptr;
2664  }
2665 
2677  template<typename ReferenceType, typename ThisType>
2678  static ReferenceType get_ref_impl(ThisType& obj)
2679  {
2680  // delegate the call to get_ptr<>()
2681  using PointerType = typename std::add_pointer<ReferenceType>::type;
2682  auto ptr = obj.template get_ptr<PointerType>();
2683 
2684  if (ptr != nullptr)
2685  {
2686  return *ptr;
2687  }
2688  else
2689  {
2690  throw std::domain_error("incompatible ReferenceType for get_ref, actual type is " +
2691  obj.type_name());
2692  }
2693  }
2694 
2695  public:
2696 
2699 
2733  template<typename ValueType, typename
2734  std::enable_if<
2735  not std::is_pointer<ValueType>::value
2736  , int>::type = 0>
2737  ValueType get() const
2738  {
2739  return get_impl(static_cast<ValueType*>(nullptr));
2740  }
2741 
2768  template<typename PointerType, typename
2769  std::enable_if<
2770  std::is_pointer<PointerType>::value
2771  , int>::type = 0>
2772  PointerType get() noexcept
2773  {
2774  // delegate the call to get_ptr
2775  return get_ptr<PointerType>();
2776  }
2777 
2782  template<typename PointerType, typename
2783  std::enable_if<
2784  std::is_pointer<PointerType>::value
2785  , int>::type = 0>
2786  const PointerType get() const noexcept
2787  {
2788  // delegate the call to get_ptr
2789  return get_ptr<PointerType>();
2790  }
2791 
2817  template<typename PointerType, typename
2818  std::enable_if<
2819  std::is_pointer<PointerType>::value
2820  , int>::type = 0>
2821  PointerType get_ptr() noexcept
2822  {
2823  // delegate the call to get_impl_ptr<>()
2824  return get_impl_ptr(static_cast<PointerType>(nullptr));
2825  }
2826 
2831  template<typename PointerType, typename
2832  std::enable_if<
2833  std::is_pointer<PointerType>::value
2834  and std::is_const<typename std::remove_pointer<PointerType>::type>::value
2835  , int>::type = 0>
2836  const PointerType get_ptr() const noexcept
2837  {
2838  // delegate the call to get_impl_ptr<>() const
2839  return get_impl_ptr(static_cast<const PointerType>(nullptr));
2840  }
2841 
2868  template<typename ReferenceType, typename
2869  std::enable_if<
2870  std::is_reference<ReferenceType>::value
2871  , int>::type = 0>
2872  ReferenceType get_ref()
2873  {
2874  // delegate call to get_ref_impl
2875  return get_ref_impl<ReferenceType>(*this);
2876  }
2877 
2882  template<typename ReferenceType, typename
2883  std::enable_if<
2884  std::is_reference<ReferenceType>::value
2885  and std::is_const<typename std::remove_reference<ReferenceType>::type>::value
2886  , int>::type = 0>
2887  ReferenceType get_ref() const
2888  {
2889  // delegate call to get_ref_impl
2890  return get_ref_impl<ReferenceType>(*this);
2891  }
2892 
2921  template < typename ValueType, typename
2922  std::enable_if <
2923  not std::is_pointer<ValueType>::value
2924  and not std::is_same<ValueType, typename string_t::value_type>::value
2925 #ifndef _MSC_VER // Fix for issue #167 operator<< abiguity under VS2015
2926  and not std::is_same<ValueType, std::initializer_list<typename string_t::value_type>>::value
2927 #endif
2928  , int >::type = 0 >
2929  operator ValueType() const
2930  {
2931  // delegate the call to get<>() const
2932  return get<ValueType>();
2933  }
2934 
2936 
2937 
2939  // element access //
2941 
2944 
2968  {
2969  // at only works for arrays
2970  if (is_array())
2971  {
2972  try
2973  {
2974  assert(m_value.array != nullptr);
2975  return m_value.array->at(idx);
2976  }
2977  catch (std::out_of_range&)
2978  {
2979  // create better exception explanation
2980  throw std::out_of_range("array index " + std::to_string(idx) + " is out of range");
2981  }
2982  }
2983  else
2984  {
2985  throw std::domain_error("cannot use at() with " + type_name());
2986  }
2987  }
2988 
3012  {
3013  // at only works for arrays
3014  if (is_array())
3015  {
3016  try
3017  {
3018  assert(m_value.array != nullptr);
3019  return m_value.array->at(idx);
3020  }
3021  catch (std::out_of_range&)
3022  {
3023  // create better exception explanation
3024  throw std::out_of_range("array index " + std::to_string(idx) + " is out of range");
3025  }
3026  }
3027  else
3028  {
3029  throw std::domain_error("cannot use at() with " + type_name());
3030  }
3031  }
3032 
3059  reference at(const typename object_t::key_type& key)
3060  {
3061  // at only works for objects
3062  if (is_object())
3063  {
3064  try
3065  {
3066  assert(m_value.object != nullptr);
3067  return m_value.object->at(key);
3068  }
3069  catch (std::out_of_range&)
3070  {
3071  // create better exception explanation
3072  throw std::out_of_range("key '" + key + "' not found");
3073  }
3074  }
3075  else
3076  {
3077  throw std::domain_error("cannot use at() with " + type_name());
3078  }
3079  }
3080 
3107  const_reference at(const typename object_t::key_type& key) const
3108  {
3109  // at only works for objects
3110  if (is_object())
3111  {
3112  try
3113  {
3114  assert(m_value.object != nullptr);
3115  return m_value.object->at(key);
3116  }
3117  catch (std::out_of_range&)
3118  {
3119  // create better exception explanation
3120  throw std::out_of_range("key '" + key + "' not found");
3121  }
3122  }
3123  else
3124  {
3125  throw std::domain_error("cannot use at() with " + type_name());
3126  }
3127  }
3128 
3155  {
3156  // implicitly convert null to object
3157  if (is_null())
3158  {
3159  m_type = value_t::array;
3160  m_value.array = create<array_t>();
3161  }
3162 
3163  // [] only works for arrays
3164  if (is_array())
3165  {
3166  assert(m_value.array != nullptr);
3167  for (size_t i = m_value.array->size(); i <= idx; ++i)
3168  {
3169  m_value.array->push_back(basic_json());
3170  }
3171 
3172  return m_value.array->operator[](idx);
3173  }
3174  else
3175  {
3176  throw std::domain_error("cannot use operator[] with " + type_name());
3177  }
3178  }
3179 
3200  {
3201  // at only works for arrays
3202  if (is_array())
3203  {
3204  assert(m_value.array != nullptr);
3205  return m_value.array->operator[](idx);
3206  }
3207  else
3208  {
3209  throw std::domain_error("cannot use operator[] with " + type_name());
3210  }
3211  }
3212 
3240  reference operator[](const typename object_t::key_type& key)
3241  {
3242  // implicitly convert null to object
3243  if (is_null())
3244  {
3245  m_type = value_t::object;
3246  m_value.object = create<object_t>();
3247  }
3248 
3249  // [] only works for objects
3250  if (is_object())
3251  {
3252  assert(m_value.object != nullptr);
3253  return m_value.object->operator[](key);
3254  }
3255  else
3256  {
3257  throw std::domain_error("cannot use operator[] with " + type_name());
3258  }
3259  }
3260 
3288  const_reference operator[](const typename object_t::key_type& key) const
3289  {
3290  // [] only works for objects
3291  if (is_object())
3292  {
3293  assert(m_value.object != nullptr);
3294  assert(m_value.object->find(key) != m_value.object->end());
3295  return m_value.object->find(key)->second;
3296  }
3297  else
3298  {
3299  throw std::domain_error("cannot use operator[] with " + type_name());
3300  }
3301  }
3302 
3330  template<typename T, std::size_t n>
3331  reference operator[](T * (&key)[n])
3332  {
3333  return operator[](static_cast<const T>(key));
3334  }
3335 
3365  template<typename T, std::size_t n>
3366  const_reference operator[](T * (&key)[n]) const
3367  {
3368  return operator[](static_cast<const T>(key));
3369  }
3370 
3398  template<typename T>
3400  {
3401  // implicitly convert null to object
3402  if (is_null())
3403  {
3404  m_type = value_t::object;
3405  m_value = value_t::object;
3406  }
3407 
3408  // at only works for objects
3409  if (is_object())
3410  {
3411  assert(m_value.object != nullptr);
3412  return m_value.object->operator[](key);
3413  }
3414  else
3415  {
3416  throw std::domain_error("cannot use operator[] with " + type_name());
3417  }
3418  }
3419 
3447  template<typename T>
3449  {
3450  // at only works for objects
3451  if (is_object())
3452  {
3453  assert(m_value.object != nullptr);
3454  assert(m_value.object->find(key) != m_value.object->end());
3455  return m_value.object->find(key)->second;
3456  }
3457  else
3458  {
3459  throw std::domain_error("cannot use operator[] with " + type_name());
3460  }
3461  }
3462 
3511  template <class ValueType, typename
3512  std::enable_if<
3513  std::is_convertible<basic_json_t, ValueType>::value
3514  , int>::type = 0>
3515  ValueType value(const typename object_t::key_type& key, ValueType default_value) const
3516  {
3517  // at only works for objects
3518  if (is_object())
3519  {
3520  // if key is found, return value and given default value otherwise
3521  const auto it = find(key);
3522  if (it != end())
3523  {
3524  return *it;
3525  }
3526  else
3527  {
3528  return default_value;
3529  }
3530  }
3531  else
3532  {
3533  throw std::domain_error("cannot use value() with " + type_name());
3534  }
3535  }
3536 
3541  string_t value(const typename object_t::key_type& key, const char* default_value) const
3542  {
3543  return value(key, string_t(default_value));
3544  }
3545 
3571  {
3572  return *begin();
3573  }
3574 
3579  {
3580  return *cbegin();
3581  }
3582 
3609  {
3610  auto tmp = end();
3611  --tmp;
3612  return *tmp;
3613  }
3614 
3619  {
3620  auto tmp = cend();
3621  --tmp;
3622  return *tmp;
3623  }
3624 
3669  template <class InteratorType, typename
3670  std::enable_if<
3671  std::is_same<InteratorType, typename basic_json_t::iterator>::value or
3672  std::is_same<InteratorType, typename basic_json_t::const_iterator>::value
3673  , int>::type
3674  = 0>
3675  InteratorType erase(InteratorType pos)
3676  {
3677  // make sure iterator fits the current value
3678  if (this != pos.m_object)
3679  {
3680  throw std::domain_error("iterator does not fit current value");
3681  }
3682 
3683  InteratorType result = end();
3684 
3685  switch (m_type)
3686  {
3687  case value_t::boolean:
3688  case value_t::number_float:
3689  case value_t::number_integer:
3690  case value_t::number_unsigned:
3691  case value_t::string:
3692  {
3693  if (not pos.m_it.primitive_iterator.is_begin())
3694  {
3695  throw std::out_of_range("iterator out of range");
3696  }
3697 
3698  if (is_string())
3699  {
3700  delete m_value.string;
3701  m_value.string = nullptr;
3702  }
3703 
3704  m_type = value_t::null;
3705  break;
3706  }
3707 
3708  case value_t::object:
3709  {
3710  assert(m_value.object != nullptr);
3711  result.m_it.object_iterator = m_value.object->erase(pos.m_it.object_iterator);
3712  break;
3713  }
3714 
3715  case value_t::array:
3716  {
3717  assert(m_value.array != nullptr);
3718  result.m_it.array_iterator = m_value.array->erase(pos.m_it.array_iterator);
3719  break;
3720  }
3721 
3722  default:
3723  {
3724  throw std::domain_error("cannot use erase() with " + type_name());
3725  }
3726  }
3727 
3728  return result;
3729  }
3730 
3775  template <class InteratorType, typename
3776  std::enable_if<
3777  std::is_same<InteratorType, typename basic_json_t::iterator>::value or
3778  std::is_same<InteratorType, typename basic_json_t::const_iterator>::value
3779  , int>::type
3780  = 0>
3781  InteratorType erase(InteratorType first, InteratorType last)
3782  {
3783  // make sure iterator fits the current value
3784  if (this != first.m_object or this != last.m_object)
3785  {
3786  throw std::domain_error("iterators do not fit current value");
3787  }
3788 
3789  InteratorType result = end();
3790 
3791  switch (m_type)
3792  {
3793  case value_t::boolean:
3794  case value_t::number_float:
3795  case value_t::number_integer:
3796  case value_t::number_unsigned:
3797  case value_t::string:
3798  {
3799  if (not first.m_it.primitive_iterator.is_begin() or not last.m_it.primitive_iterator.is_end())
3800  {
3801  throw std::out_of_range("iterators out of range");
3802  }
3803 
3804  if (is_string())
3805  {
3806  delete m_value.string;
3807  m_value.string = nullptr;
3808  }
3809 
3810  m_type = value_t::null;
3811  break;
3812  }
3813 
3814  case value_t::object:
3815  {
3816  assert(m_value.object != nullptr);
3817  result.m_it.object_iterator = m_value.object->erase(first.m_it.object_iterator,
3818  last.m_it.object_iterator);
3819  break;
3820  }
3821 
3822  case value_t::array:
3823  {
3824  assert(m_value.array != nullptr);
3825  result.m_it.array_iterator = m_value.array->erase(first.m_it.array_iterator,
3826  last.m_it.array_iterator);
3827  break;
3828  }
3829 
3830  default:
3831  {
3832  throw std::domain_error("cannot use erase() with " + type_name());
3833  }
3834  }
3835 
3836  return result;
3837  }
3838 
3865  size_type erase(const typename object_t::key_type& key)
3866  {
3867  // this erase only works for objects
3868  if (is_object())
3869  {
3870  assert(m_value.object != nullptr);
3871  return m_value.object->erase(key);
3872  }
3873  else
3874  {
3875  throw std::domain_error("cannot use erase() with " + type_name());
3876  }
3877  }
3878 
3903  void erase(const size_type idx)
3904  {
3905  // this erase only works for arrays
3906  if (is_array())
3907  {
3908  if (idx >= size())
3909  {
3910  throw std::out_of_range("index out of range");
3911  }
3912 
3913  assert(m_value.array != nullptr);
3914  m_value.array->erase(m_value.array->begin() + static_cast<difference_type>(idx));
3915  }
3916  else
3917  {
3918  throw std::domain_error("cannot use erase() with " + type_name());
3919  }
3920  }
3921 
3939  iterator find(typename object_t::key_type key)
3940  {
3941  auto result = end();
3942 
3943  if (is_object())
3944  {
3945  assert(m_value.object != nullptr);
3946  result.m_it.object_iterator = m_value.object->find(key);
3947  }
3948 
3949  return result;
3950  }
3951 
3956  const_iterator find(typename object_t::key_type key) const
3957  {
3958  auto result = cend();
3959 
3960  if (is_object())
3961  {
3962  assert(m_value.object != nullptr);
3963  result.m_it.object_iterator = m_value.object->find(key);
3964  }
3965 
3966  return result;
3967  }
3968 
3987  size_type count(typename object_t::key_type key) const
3988  {
3989  // return 0 for all nonobject types
3990  assert(not is_object() or m_value.object != nullptr);
3991  return is_object() ? m_value.object->count(key) : 0;
3992  }
3993 
3995 
3996 
3998  // iterators //
4000 
4003 
4029  {
4030  iterator result(this);
4031  result.set_begin();
4032  return result;
4033  }
4034 
4039  {
4040  return cbegin();
4041  }
4042 
4069  {
4070  const_iterator result(this);
4071  result.set_begin();
4072  return result;
4073  }
4074 
4100  {
4101  iterator result(this);
4102  result.set_end();
4103  return result;
4104  }
4105 
4110  {
4111  return cend();
4112  }
4113 
4140  {
4141  const_iterator result(this);
4142  result.set_end();
4143  return result;
4144  }
4145 
4170  {
4171  return reverse_iterator(end());
4172  }
4173 
4178  {
4179  return crbegin();
4180  }
4181 
4207  {
4208  return reverse_iterator(begin());
4209  }
4210 
4215  {
4216  return crend();
4217  }
4218 
4244  {
4245  return const_reverse_iterator(cend());
4246  }
4247 
4273  {
4274  return const_reverse_iterator(cbegin());
4275  }
4276 
4277  private:
4278  // forward declaration
4279  template<typename IteratorType> class iteration_proxy;
4280 
4281  public:
4293  static iteration_proxy<iterator> iterator_wrapper(reference cont)
4294  {
4295  return iteration_proxy<iterator>(cont);
4296  }
4297 
4301  static iteration_proxy<const_iterator> iterator_wrapper(const_reference cont)
4302  {
4303  return iteration_proxy<const_iterator>(cont);
4304  }
4305 
4307 
4308 
4310  // capacity //
4312 
4315 
4349  bool empty() const noexcept
4350  {
4351  switch (m_type)
4352  {
4353  case value_t::null:
4354  {
4355  // null values are empty
4356  return true;
4357  }
4358 
4359  case value_t::array:
4360  {
4361  assert(m_value.array != nullptr);
4362  return m_value.array->empty();
4363  }
4364 
4365  case value_t::object:
4366  {
4367  assert(m_value.object != nullptr);
4368  return m_value.object->empty();
4369  }
4370 
4371  default:
4372  {
4373  // all other types are nonempty
4374  return false;
4375  }
4376  }
4377  }
4378 
4412  size_type size() const noexcept
4413  {
4414  switch (m_type)
4415  {
4416  case value_t::null:
4417  {
4418  // null values are empty
4419  return 0;
4420  }
4421 
4422  case value_t::array:
4423  {
4424  assert(m_value.array != nullptr);
4425  return m_value.array->size();
4426  }
4427 
4428  case value_t::object:
4429  {
4430  assert(m_value.object != nullptr);
4431  return m_value.object->size();
4432  }
4433 
4434  default:
4435  {
4436  // all other types have size 1
4437  return 1;
4438  }
4439  }
4440  }
4441 
4478  size_type max_size() const noexcept
4479  {
4480  switch (m_type)
4481  {
4482  case value_t::array:
4483  {
4484  assert(m_value.array != nullptr);
4485  return m_value.array->max_size();
4486  }
4487 
4488  case value_t::object:
4489  {
4490  assert(m_value.object != nullptr);
4491  return m_value.object->max_size();
4492  }
4493 
4494  default:
4495  {
4496  // all other types have max_size() == size()
4497  return size();
4498  }
4499  }
4500  }
4501 
4503 
4504 
4506  // modifiers //
4508 
4511 
4537  void clear() noexcept
4538  {
4539  switch (m_type)
4540  {
4541  case value_t::number_integer:
4542  {
4543  m_value.number_integer = 0;
4544  break;
4545  }
4546 
4547  case value_t::number_unsigned:
4548  {
4549  m_value.number_unsigned = 0;
4550  break;
4551  }
4552 
4553  case value_t::number_float:
4554  {
4555  m_value.number_float = 0.0;
4556  break;
4557  }
4558 
4559  case value_t::boolean:
4560  {
4561  m_value.boolean = false;
4562  break;
4563  }
4564 
4565  case value_t::string:
4566  {
4567  assert(m_value.string != nullptr);
4568  m_value.string->clear();
4569  break;
4570  }
4571 
4572  case value_t::array:
4573  {
4574  assert(m_value.array != nullptr);
4575  m_value.array->clear();
4576  break;
4577  }
4578 
4579  case value_t::object:
4580  {
4581  assert(m_value.object != nullptr);
4582  m_value.object->clear();
4583  break;
4584  }
4585 
4586  default:
4587  {
4588  break;
4589  }
4590  }
4591  }
4592 
4613  void push_back(basic_json&& val)
4614  {
4615  // push_back only works for null objects or arrays
4616  if (not(is_null() or is_array()))
4617  {
4618  throw std::domain_error("cannot use push_back() with " + type_name());
4619  }
4620 
4621  // transform null object into an array
4622  if (is_null())
4623  {
4624  m_type = value_t::array;
4625  m_value = value_t::array;
4626  }
4627 
4628  // add element to array (move semantics)
4629  assert(m_value.array != nullptr);
4630  m_value.array->push_back(std::move(val));
4631  // invalidate object
4632  val.m_type = value_t::null;
4633  }
4634 
4639  reference operator+=(basic_json&& val)
4640  {
4641  push_back(std::move(val));
4642  return *this;
4643  }
4644 
4649  void push_back(const basic_json& val)
4650  {
4651  // push_back only works for null objects or arrays
4652  if (not(is_null() or is_array()))
4653  {
4654  throw std::domain_error("cannot use push_back() with " + type_name());
4655  }
4656 
4657  // transform null object into an array
4658  if (is_null())
4659  {
4660  m_type = value_t::array;
4661  m_value = value_t::array;
4662  }
4663 
4664  // add element to array
4665  assert(m_value.array != nullptr);
4666  m_value.array->push_back(val);
4667  }
4668 
4673  reference operator+=(const basic_json& val)
4674  {
4675  push_back(val);
4676  return *this;
4677  }
4678 
4699  void push_back(const typename object_t::value_type& val)
4700  {
4701  // push_back only works for null objects or objects
4702  if (not(is_null() or is_object()))
4703  {
4704  throw std::domain_error("cannot use push_back() with " + type_name());
4705  }
4706 
4707  // transform null object into an object
4708  if (is_null())
4709  {
4710  m_type = value_t::object;
4711  m_value = value_t::object;
4712  }
4713 
4714  // add element to array
4715  assert(m_value.object != nullptr);
4716  m_value.object->insert(val);
4717  }
4718 
4723  reference operator+=(const typename object_t::value_type& val)
4724  {
4725  push_back(val);
4726  return operator[](val.first);
4727  }
4728 
4751  iterator insert(const_iterator pos, const basic_json& val)
4752  {
4753  // insert only works for arrays
4754  if (is_array())
4755  {
4756  // check if iterator pos fits to this JSON value
4757  if (pos.m_object != this)
4758  {
4759  throw std::domain_error("iterator does not fit current value");
4760  }
4761 
4762  // insert to array and return iterator
4763  iterator result(this);
4764  assert(m_value.array != nullptr);
4765  result.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator, val);
4766  return result;
4767  }
4768  else
4769  {
4770  throw std::domain_error("cannot use insert() with " + type_name());
4771  }
4772  }
4773 
4778  iterator insert(const_iterator pos, basic_json&& val)
4779  {
4780  return insert(pos, val);
4781  }
4782 
4807  iterator insert(const_iterator pos, size_type cnt, const basic_json& val)
4808  {
4809  // insert only works for arrays
4810  if (is_array())
4811  {
4812  // check if iterator pos fits to this JSON value
4813  if (pos.m_object != this)
4814  {
4815  throw std::domain_error("iterator does not fit current value");
4816  }
4817 
4818  // insert to array and return iterator
4819  iterator result(this);
4820  assert(m_value.array != nullptr);
4821  result.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator, cnt, val);
4822  return result;
4823  }
4824  else
4825  {
4826  throw std::domain_error("cannot use insert() with " + type_name());
4827  }
4828  }
4829 
4861  {
4862  // insert only works for arrays
4863  if (not is_array())
4864  {
4865  throw std::domain_error("cannot use insert() with " + type_name());
4866  }
4867 
4868  // check if iterator pos fits to this JSON value
4869  if (pos.m_object != this)
4870  {
4871  throw std::domain_error("iterator does not fit current value");
4872  }
4873 
4874  if (first.m_object != last.m_object)
4875  {
4876  throw std::domain_error("iterators do not fit");
4877  }
4878 
4879  if (first.m_object == this or last.m_object == this)
4880  {
4881  throw std::domain_error("passed iterators may not belong to container");
4882  }
4883 
4884  // insert to array and return iterator
4885  iterator result(this);
4886  assert(m_value.array != nullptr);
4887  result.m_it.array_iterator = m_value.array->insert(
4888  pos.m_it.array_iterator,
4889  first.m_it.array_iterator,
4890  last.m_it.array_iterator);
4891  return result;
4892  }
4893 
4918  iterator insert(const_iterator pos, std::initializer_list<basic_json> ilist)
4919  {
4920  // insert only works for arrays
4921  if (not is_array())
4922  {
4923  throw std::domain_error("cannot use insert() with " + type_name());
4924  }
4925 
4926  // check if iterator pos fits to this JSON value
4927  if (pos.m_object != this)
4928  {
4929  throw std::domain_error("iterator does not fit current value");
4930  }
4931 
4932  // insert to array and return iterator
4933  iterator result(this);
4934  assert(m_value.array != nullptr);
4935  result.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator, ilist);
4936  return result;
4937  }
4938 
4956  void swap(reference other) noexcept (
4957  std::is_nothrow_move_constructible<value_t>::value and
4958  std::is_nothrow_move_assignable<value_t>::value and
4959  std::is_nothrow_move_constructible<json_value>::value and
4960  std::is_nothrow_move_assignable<json_value>::value
4961  )
4962  {
4963  std::swap(m_type, other.m_type);
4964  std::swap(m_value, other.m_value);
4965  }
4966 
4987  void swap(array_t& other)
4988  {
4989  // swap only works for arrays
4990  if (is_array())
4991  {
4992  assert(m_value.array != nullptr);
4993  std::swap(*(m_value.array), other);
4994  }
4995  else
4996  {
4997  throw std::domain_error("cannot use swap() with " + type_name());
4998  }
4999  }
5000 
5021  void swap(object_t& other)
5022  {
5023  // swap only works for objects
5024  if (is_object())
5025  {
5026  assert(m_value.object != nullptr);
5027  std::swap(*(m_value.object), other);
5028  }
5029  else
5030  {
5031  throw std::domain_error("cannot use swap() with " + type_name());
5032  }
5033  }
5034 
5055  void swap(string_t& other)
5056  {
5057  // swap only works for strings
5058  if (is_string())
5059  {
5060  assert(m_value.string != nullptr);
5061  std::swap(*(m_value.string), other);
5062  }
5063  else
5064  {
5065  throw std::domain_error("cannot use swap() with " + type_name());
5066  }
5067  }
5068 
5070 
5071 
5073  // lexicographical comparison operators //
5075 
5078 
5079  private:
5089  friend bool operator<(const value_t lhs, const value_t rhs)
5090  {
5091  static constexpr std::array<uint8_t, 8> order = {{
5092  0, // null
5093  3, // object
5094  4, // array
5095  5, // string
5096  1, // boolean
5097  2, // integer
5098  2, // unsigned
5099  2, // float
5100  }
5101  };
5102 
5103  // discarded values are not comparable
5104  if (lhs == value_t::discarded or rhs == value_t::discarded)
5105  {
5106  return false;
5107  }
5108 
5109  return order[static_cast<std::size_t>(lhs)] < order[static_cast<std::size_t>(rhs)];
5110  }
5111 
5112  public:
5136  friend bool operator==(const_reference lhs, const_reference rhs) noexcept
5137  {
5138  const auto lhs_type = lhs.type();
5139  const auto rhs_type = rhs.type();
5140 
5141  if (lhs_type == rhs_type)
5142  {
5143  switch (lhs_type)
5144  {
5145  case value_t::array:
5146  {
5147  assert(lhs.m_value.array != nullptr);
5148  assert(rhs.m_value.array != nullptr);
5149  return *lhs.m_value.array == *rhs.m_value.array;
5150  }
5151  case value_t::object:
5152  {
5153  assert(lhs.m_value.object != nullptr);
5154  assert(rhs.m_value.object != nullptr);
5155  return *lhs.m_value.object == *rhs.m_value.object;
5156  }
5157  case value_t::null:
5158  {
5159  return true;
5160  }
5161  case value_t::string:
5162  {
5163  assert(lhs.m_value.string != nullptr);
5164  assert(rhs.m_value.string != nullptr);
5165  return *lhs.m_value.string == *rhs.m_value.string;
5166  }
5167  case value_t::boolean:
5168  {
5169  return lhs.m_value.boolean == rhs.m_value.boolean;
5170  }
5171  case value_t::number_integer:
5172  {
5173  return lhs.m_value.number_integer == rhs.m_value.number_integer;
5174  }
5175  case value_t::number_unsigned:
5176  {
5177  return lhs.m_value.number_unsigned == rhs.m_value.number_unsigned;
5178  }
5179  case value_t::number_float:
5180  {
5181  return lhs.m_value.number_float == rhs.m_value.number_float;
5182  }
5183  default:
5184  {
5185  return false;
5186  }
5187  }
5188  }
5189  else if (lhs_type == value_t::number_integer and rhs_type == value_t::number_float)
5190  {
5191  return static_cast<number_float_t>(lhs.m_value.number_integer) == rhs.m_value.number_float;
5192  }
5193  else if (lhs_type == value_t::number_float and rhs_type == value_t::number_integer)
5194  {
5195  return lhs.m_value.number_float == static_cast<number_float_t>(rhs.m_value.number_integer);
5196  }
5197  else if (lhs_type == value_t::number_unsigned and rhs_type == value_t::number_float)
5198  {
5199  return static_cast<number_float_t>(lhs.m_value.number_unsigned) == rhs.m_value.number_float;
5200  }
5201  else if (lhs_type == value_t::number_float and rhs_type == value_t::number_unsigned)
5202  {
5203  return lhs.m_value.number_float == static_cast<number_float_t>(rhs.m_value.number_unsigned);
5204  }
5205  else if (lhs_type == value_t::number_unsigned and rhs_type == value_t::number_integer)
5206  {
5207  return static_cast<number_integer_t>(lhs.m_value.number_unsigned) == rhs.m_value.number_integer;
5208  }
5209  else if (lhs_type == value_t::number_integer and rhs_type == value_t::number_unsigned)
5210  {
5211  return lhs.m_value.number_integer == static_cast<number_integer_t>(rhs.m_value.number_unsigned);
5212  }
5213 
5214  return false;
5215  }
5216 
5235  friend bool operator==(const_reference v, std::nullptr_t) noexcept
5236  {
5237  return v.is_null();
5238  }
5239 
5244  friend bool operator==(std::nullptr_t, const_reference v) noexcept
5245  {
5246  return v.is_null();
5247  }
5248 
5265  friend bool operator!=(const_reference lhs, const_reference rhs) noexcept
5266  {
5267  return not (lhs == rhs);
5268  }
5269 
5288  friend bool operator!=(const_reference v, std::nullptr_t) noexcept
5289  {
5290  return not v.is_null();
5291  }
5292 
5297  friend bool operator!=(std::nullptr_t, const_reference v) noexcept
5298  {
5299  return not v.is_null();
5300  }
5301 
5326  friend bool operator<(const_reference lhs, const_reference rhs) noexcept
5327  {
5328  const auto lhs_type = lhs.type();
5329  const auto rhs_type = rhs.type();
5330 
5331  if (lhs_type == rhs_type)
5332  {
5333  switch (lhs_type)
5334  {
5335  case value_t::array:
5336  {
5337  assert(lhs.m_value.array != nullptr);
5338  assert(rhs.m_value.array != nullptr);
5339  return *lhs.m_value.array < *rhs.m_value.array;
5340  }
5341  case value_t::object:
5342  {
5343  assert(lhs.m_value.object != nullptr);
5344  assert(rhs.m_value.object != nullptr);
5345  return *lhs.m_value.object < *rhs.m_value.object;
5346  }
5347  case value_t::null:
5348  {
5349  return false;
5350  }
5351  case value_t::string:
5352  {
5353  assert(lhs.m_value.string != nullptr);
5354  assert(rhs.m_value.string != nullptr);
5355  return *lhs.m_value.string < *rhs.m_value.string;
5356  }
5357  case value_t::boolean:
5358  {
5359  return lhs.m_value.boolean < rhs.m_value.boolean;
5360  }
5361  case value_t::number_integer:
5362  {
5363  return lhs.m_value.number_integer < rhs.m_value.number_integer;
5364  }
5365  case value_t::number_unsigned:
5366  {
5367  return lhs.m_value.number_unsigned < rhs.m_value.number_unsigned;
5368  }
5369  case value_t::number_float:
5370  {
5371  return lhs.m_value.number_float < rhs.m_value.number_float;
5372  }
5373  default:
5374  {
5375  return false;
5376  }
5377  }
5378  }
5379  else if (lhs_type == value_t::number_integer and rhs_type == value_t::number_float)
5380  {
5381  return static_cast<number_float_t>(lhs.m_value.number_integer) < rhs.m_value.number_float;
5382  }
5383  else if (lhs_type == value_t::number_float and rhs_type == value_t::number_integer)
5384  {
5385  return lhs.m_value.number_float < static_cast<number_float_t>(rhs.m_value.number_integer);
5386  }
5387  else if (lhs_type == value_t::number_unsigned and rhs_type == value_t::number_float)
5388  {
5389  return static_cast<number_float_t>(lhs.m_value.number_unsigned) < rhs.m_value.number_float;
5390  }
5391  else if (lhs_type == value_t::number_float and rhs_type == value_t::number_unsigned)
5392  {
5393  return lhs.m_value.number_float < static_cast<number_float_t>(rhs.m_value.number_unsigned);
5394  }
5395  else if (lhs_type == value_t::number_integer and rhs_type == value_t::number_unsigned)
5396  {
5397  return lhs.m_value.number_integer < static_cast<number_integer_t>(rhs.m_value.number_unsigned);
5398  }
5399  else if (lhs_type == value_t::number_unsigned and rhs_type == value_t::number_integer)
5400  {
5401  return static_cast<number_integer_t>(lhs.m_value.number_unsigned) < rhs.m_value.number_integer;
5402  }
5403 
5404  // We only reach this line if we cannot compare values. In that case,
5405  // we compare types. Note we have to call the operator explicitly,
5406  // because MSVC has problems otherwise.
5407  return operator<(lhs_type, rhs_type);
5408  }
5409 
5427  friend bool operator<=(const_reference lhs, const_reference rhs) noexcept
5428  {
5429  return not (rhs < lhs);
5430  }
5431 
5449  friend bool operator>(const_reference lhs, const_reference rhs) noexcept
5450  {
5451  return not (lhs <= rhs);
5452  }
5453 
5471  friend bool operator>=(const_reference lhs, const_reference rhs) noexcept
5472  {
5473  return not (lhs < rhs);
5474  }
5475 
5477 
5478 
5480  // serialization //
5482 
5485 
5508  friend std::ostream& operator<<(std::ostream& o, const basic_json& j)
5509  {
5510  // read width member and use it as indentation parameter if nonzero
5511  const bool pretty_print = (o.width() > 0);
5512  const auto indentation = (pretty_print ? o.width() : 0);
5513 
5514  // reset width to 0 for subsequent calls to this stream
5515  o.width(0);
5516 
5517  // do the actual serialization
5518  j.dump(o, pretty_print, static_cast<unsigned int>(indentation));
5519  return o;
5520  }
5521 
5526  friend std::ostream& operator>>(const basic_json& j, std::ostream& o)
5527  {
5528  return o << j;
5529  }
5530 
5532 
5533 
5535  // deserialization //
5537 
5540 
5565  static basic_json parse(const string_t& s, parser_callback_t cb = nullptr)
5566  {
5567  return parser(s, cb).parse();
5568  }
5569 
5594  static basic_json parse(std::istream& i, parser_callback_t cb = nullptr)
5595  {
5596  return parser(i, cb).parse();
5597  }
5598 
5602  static basic_json parse(std::istream&& i, parser_callback_t cb = nullptr)
5603  {
5604  return parser(i, cb).parse();
5605  }
5606 
5630  friend std::istream& operator<<(basic_json& j, std::istream& i)
5631  {
5632  j = parser(i).parse();
5633  return i;
5634  }
5635 
5640  friend std::istream& operator>>(std::istream& i, basic_json& j)
5641  {
5642  j = parser(i).parse();
5643  return i;
5644  }
5645 
5647 
5648 
5649  private:
5651  // convenience functions //
5653 
5655  string_t type_name() const
5656  {
5657  switch (m_type)
5658  {
5659  case value_t::null:
5660  return "null";
5661  case value_t::object:
5662  return "object";
5663  case value_t::array:
5664  return "array";
5665  case value_t::string:
5666  return "string";
5667  case value_t::boolean:
5668  return "boolean";
5669  case value_t::discarded:
5670  return "discarded";
5671  default:
5672  return "number";
5673  }
5674  }
5675 
5684  static std::size_t extra_space(const string_t& s) noexcept
5685  {
5686  std::size_t result = 0;
5687 
5688  for (const auto& c : s)
5689  {
5690  switch (c)
5691  {
5692  case '"':
5693  case '\\':
5694  case '\b':
5695  case '\f':
5696  case '\n':
5697  case '\r':
5698  case '\t':
5699  {
5700  // from c (1 byte) to \x (2 bytes)
5701  result += 1;
5702  break;
5703  }
5704 
5705  default:
5706  {
5707  if (c >= 0x00 and c <= 0x1f)
5708  {
5709  // from c (1 byte) to \uxxxx (6 bytes)
5710  result += 5;
5711  }
5712  break;
5713  }
5714  }
5715  }
5716 
5717  return result;
5718  }
5719 
5733  static string_t escape_string(const string_t& s) noexcept
5734  {
5735  const auto space = extra_space(s);
5736  if (space == 0)
5737  {
5738  return s;
5739  }
5740 
5741  // create a result string of necessary size
5742  string_t result(s.size() + space, '\\');
5743  std::size_t pos = 0;
5744 
5745  for (const auto& c : s)
5746  {
5747  switch (c)
5748  {
5749  // quotation mark (0x22)
5750  case '"':
5751  {
5752  result[pos + 1] = '"';
5753  pos += 2;
5754  break;
5755  }
5756 
5757  // reverse solidus (0x5c)
5758  case '\\':
5759  {
5760  // nothing to change
5761  pos += 2;
5762  break;
5763  }
5764 
5765  // backspace (0x08)
5766  case '\b':
5767  {
5768  result[pos + 1] = 'b';
5769  pos += 2;
5770  break;
5771  }
5772 
5773  // formfeed (0x0c)
5774  case '\f':
5775  {
5776  result[pos + 1] = 'f';
5777  pos += 2;
5778  break;
5779  }
5780 
5781  // newline (0x0a)
5782  case '\n':
5783  {
5784  result[pos + 1] = 'n';
5785  pos += 2;
5786  break;
5787  }
5788 
5789  // carriage return (0x0d)
5790  case '\r':
5791  {
5792  result[pos + 1] = 'r';
5793  pos += 2;
5794  break;
5795  }
5796 
5797  // horizontal tab (0x09)
5798  case '\t':
5799  {
5800  result[pos + 1] = 't';
5801  pos += 2;
5802  break;
5803  }
5804 
5805  default:
5806  {
5807  if (c >= 0x00 and c <= 0x1f)
5808  {
5809  // convert a number 0..15 to its hex representation
5810  // (0..f)
5811  auto hexify = [](const char v) -> char
5812  {
5813  return (v < 10) ? ('0' + v) : ('a' + v - 10);
5814  };
5815 
5816  // print character c as \uxxxx
5817  for (const char m :
5818  { 'u', '0', '0', hexify(c >> 4), hexify(c & 0x0f)
5819  })
5820  {
5821  result[++pos] = m;
5822  }
5823 
5824  ++pos;
5825  }
5826  else
5827  {
5828  // all other characters are added as-is
5829  result[pos++] = c;
5830  }
5831  break;
5832  }
5833  }
5834  }
5835 
5836  return result;
5837  }
5838 
5856  void dump(std::ostream& o,
5857  const bool pretty_print,
5858  const unsigned int indent_step,
5859  const unsigned int current_indent = 0) const
5860  {
5861  // variable to hold indentation for recursive calls
5862  unsigned int new_indent = current_indent;
5863 
5864  switch (m_type)
5865  {
5866  case value_t::object:
5867  {
5868  assert(m_value.object != nullptr);
5869 
5870  if (m_value.object->empty())
5871  {
5872  o << "{}";
5873  return;
5874  }
5875 
5876  o << "{";
5877 
5878  // increase indentation
5879  if (pretty_print)
5880  {
5881  new_indent += indent_step;
5882  o << "\n";
5883  }
5884 
5885  for (auto i = m_value.object->cbegin(); i != m_value.object->cend(); ++i)
5886  {
5887  if (i != m_value.object->cbegin())
5888  {
5889  o << (pretty_print ? ",\n" : ",");
5890  }
5891  o << string_t(new_indent, ' ') << "\""
5892  << escape_string(i->first) << "\":"
5893  << (pretty_print ? " " : "");
5894  i->second.dump(o, pretty_print, indent_step, new_indent);
5895  }
5896 
5897  // decrease indentation
5898  if (pretty_print)
5899  {
5900  new_indent -= indent_step;
5901  o << "\n";
5902  }
5903 
5904  o << string_t(new_indent, ' ') + "}";
5905  return;
5906  }
5907 
5908  case value_t::array:
5909  {
5910  assert(m_value.array != nullptr);
5911 
5912  if (m_value.array->empty())
5913  {
5914  o << "[]";
5915  return;
5916  }
5917 
5918  o << "[";
5919 
5920  // increase indentation
5921  if (pretty_print)
5922  {
5923  new_indent += indent_step;
5924  o << "\n";
5925  }
5926 
5927  for (auto i = m_value.array->cbegin(); i != m_value.array->cend(); ++i)
5928  {
5929  if (i != m_value.array->cbegin())
5930  {
5931  o << (pretty_print ? ",\n" : ",");
5932  }
5933  o << string_t(new_indent, ' ');
5934  i->dump(o, pretty_print, indent_step, new_indent);
5935  }
5936 
5937  // decrease indentation
5938  if (pretty_print)
5939  {
5940  new_indent -= indent_step;
5941  o << "\n";
5942  }
5943 
5944  o << string_t(new_indent, ' ') << "]";
5945  return;
5946  }
5947 
5948  case value_t::string:
5949  {
5950  assert(m_value.string != nullptr);
5951  o << string_t("\"") << escape_string(*m_value.string) << "\"";
5952  return;
5953  }
5954 
5955  case value_t::boolean:
5956  {
5957  o << (m_value.boolean ? "true" : "false");
5958  return;
5959  }
5960 
5961  case value_t::number_integer:
5962  {
5963  o << m_value.number_integer;
5964  return;
5965  }
5966 
5967  case value_t::number_unsigned:
5968  {
5969  o << m_value.number_unsigned;
5970  return;
5971  }
5972 
5973  case value_t::number_float:
5974  {
5975  // If the number is an integer then output as a fixed with with
5976  // precision 1 to output "0.0", "1.0" etc as expected for some
5977  // round trip tests otherwise 15 digits of precision allows
5978  // round-trip IEEE 754 string->double->string; to be safe, we
5979  // read this value from
5980  // std::numeric_limits<number_float_t>::digits10
5981  if (std::fmod(m_value.number_float, 1) == 0)
5982  {
5983  o << std::fixed << std::setprecision(1);
5984  }
5985  else
5986  {
5987  // std::defaultfloat not supported in gcc version < 5
5988  o.unsetf(std::ios_base::floatfield);
5989  o << std::setprecision(std::numeric_limits<double>::digits10);
5990  }
5991  o << m_value.number_float;
5992  return;
5993  }
5994 
5995  case value_t::discarded:
5996  {
5997  o << "<discarded>";
5998  return;
5999  }
6000 
6001  case value_t::null:
6002  {
6003  o << "null";
6004  return;
6005  }
6006  }
6007  }
6008 
6009  private:
6011  // member variables //
6013 
6015  value_t m_type = value_t::null;
6016 
6018  json_value m_value = {};
6019 
6020 
6021  private:
6023  // iterators //
6025 
6035  class primitive_iterator_t
6036  {
6037  public:
6039  void set_begin()
6040  {
6041  m_it = begin_value;
6042  }
6043 
6045  void set_end()
6046  {
6047  m_it = end_value;
6048  }
6049 
6051  bool is_begin() const
6052  {
6053  return (m_it == begin_value);
6054  }
6055 
6057  bool is_end() const
6058  {
6059  return (m_it == end_value);
6060  }
6061 
6063  operator difference_type& ()
6064  {
6065  return m_it;
6066  }
6067 
6069  operator difference_type () const
6070  {
6071  return m_it;
6072  }
6073 
6074  private:
6075  static constexpr difference_type begin_value = 0;
6076  static constexpr difference_type end_value = begin_value + 1;
6077 
6079  difference_type m_it = std::numeric_limits<std::ptrdiff_t>::denorm_min();
6080  };
6081 
6089  struct internal_iterator
6090  {
6092  typename object_t::iterator object_iterator;
6094  typename array_t::iterator array_iterator;
6096  primitive_iterator_t primitive_iterator;
6097 
6099  internal_iterator()
6100  : object_iterator(), array_iterator(), primitive_iterator()
6101  {}
6102  };
6103 
6105  template<typename IteratorType>
6106  class iteration_proxy
6107  {
6108  private:
6110  class iteration_proxy_internal
6111  {
6112  private:
6114  IteratorType anchor;
6116  size_t array_index = 0;
6117 
6118  public:
6119  iteration_proxy_internal(IteratorType it)
6120  : anchor(it)
6121  {}
6122 
6124  iteration_proxy_internal& operator*()
6125  {
6126  return *this;
6127  }
6128 
6130  iteration_proxy_internal& operator++()
6131  {
6132  ++anchor;
6133  ++array_index;
6134 
6135  return *this;
6136  }
6137 
6139  bool operator!= (const iteration_proxy_internal& o) const
6140  {
6141  return anchor != o.anchor;
6142  }
6143 
6145  typename basic_json::string_t key() const
6146  {
6147  assert(anchor.m_object != nullptr);
6148 
6149  switch (anchor.m_object->type())
6150  {
6151  // use integer array index as key
6152  case value_t::array:
6153  {
6154  return std::to_string(array_index);
6155  }
6156 
6157  // use key from the object
6158  case value_t::object:
6159  {
6160  return anchor.key();
6161  }
6162 
6163  // use an empty key for all primitive types
6164  default:
6165  {
6166  return "";
6167  }
6168  }
6169  }
6170 
6172  typename IteratorType::reference value() const
6173  {
6174  return anchor.value();
6175  }
6176  };
6177 
6179  typename IteratorType::reference container;
6180 
6181  public:
6183  iteration_proxy(typename IteratorType::reference cont)
6184  : container(cont)
6185  {}
6186 
6188  iteration_proxy_internal begin()
6189  {
6190  return iteration_proxy_internal(container.begin());
6191  }
6192 
6194  iteration_proxy_internal end()
6195  {
6196  return iteration_proxy_internal(container.end());
6197  }
6198  };
6199 
6200  public:
6214  class const_iterator : public std::iterator<std::random_access_iterator_tag, const basic_json>
6215  {
6217  friend class basic_json;
6218 
6219  public:
6229  using iterator_category = std::bidirectional_iterator_tag;
6230 
6232  const_iterator() = default;
6233 
6235  const_iterator(pointer object) : m_object(object)
6236  {
6237  assert(m_object != nullptr);
6238 
6239  switch (m_object->m_type)
6240  {
6242  {
6243  m_it.object_iterator = typename object_t::iterator();
6244  break;
6245  }
6246 
6248  {
6249  m_it.array_iterator = typename array_t::iterator();
6250  break;
6251  }
6252 
6253  default:
6254  {
6255  m_it.primitive_iterator = primitive_iterator_t();
6256  break;
6257  }
6258  }
6259  }
6260 
6262  const_iterator(const iterator& other) : m_object(other.m_object)
6263  {
6264  assert(m_object != nullptr);
6265 
6266  switch (m_object->m_type)
6267  {
6269  {
6270  m_it.object_iterator = other.m_it.object_iterator;
6271  break;
6272  }
6273 
6275  {
6276  m_it.array_iterator = other.m_it.array_iterator;
6277  break;
6278  }
6279 
6280  default:
6281  {
6282  m_it.primitive_iterator = other.m_it.primitive_iterator;
6283  break;
6284  }
6285  }
6286  }
6287 
6289  const_iterator(const const_iterator& other) noexcept
6290  : m_object(other.m_object), m_it(other.m_it)
6291  {}
6292 
6295  std::is_nothrow_move_constructible<pointer>::value and
6296  std::is_nothrow_move_assignable<pointer>::value and
6297  std::is_nothrow_move_constructible<internal_iterator>::value and
6298  std::is_nothrow_move_assignable<internal_iterator>::value
6299  )
6300  {
6301  std::swap(m_object, other.m_object);
6302  std::swap(m_it, other.m_it);
6303  return *this;
6304  }
6305 
6306  private:
6308  void set_begin()
6309  {
6310  assert(m_object != nullptr);
6311 
6312  switch (m_object->m_type)
6313  {
6315  {
6316  assert(m_object->m_value.object != nullptr);
6317  m_it.object_iterator = m_object->m_value.object->begin();
6318  break;
6319  }
6320 
6322  {
6323  assert(m_object->m_value.array != nullptr);
6324  m_it.array_iterator = m_object->m_value.array->begin();
6325  break;
6326  }
6327 
6329  {
6330  // set to end so begin()==end() is true: null is empty
6331  m_it.primitive_iterator.set_end();
6332  break;
6333  }
6334 
6335  default:
6336  {
6337  m_it.primitive_iterator.set_begin();
6338  break;
6339  }
6340  }
6341  }
6342 
6344  void set_end()
6345  {
6346  assert(m_object != nullptr);
6347 
6348  switch (m_object->m_type)
6349  {
6351  {
6352  assert(m_object->m_value.object != nullptr);
6353  m_it.object_iterator = m_object->m_value.object->end();
6354  break;
6355  }
6356 
6358  {
6359  assert(m_object->m_value.array != nullptr);
6360  m_it.array_iterator = m_object->m_value.array->end();
6361  break;
6362  }
6363 
6364  default:
6365  {
6366  m_it.primitive_iterator.set_end();
6367  break;
6368  }
6369  }
6370  }
6371 
6372  public:
6375  {
6376  assert(m_object != nullptr);
6377 
6378  switch (m_object->m_type)
6379  {
6381  {
6382  assert(m_object->m_value.object);
6383  assert(m_it.object_iterator != m_object->m_value.object->end());
6384  return m_it.object_iterator->second;
6385  }
6386 
6388  {
6389  assert(m_object->m_value.array);
6390  assert(m_it.array_iterator != m_object->m_value.array->end());
6391  return *m_it.array_iterator;
6392  }
6393 
6395  {
6396  throw std::out_of_range("cannot get value");
6397  }
6398 
6399  default:
6400  {
6401  if (m_it.primitive_iterator.is_begin())
6402  {
6403  return *m_object;
6404  }
6405  else
6406  {
6407  throw std::out_of_range("cannot get value");
6408  }
6409  }
6410  }
6411  }
6412 
6415  {
6416  assert(m_object != nullptr);
6417 
6418  switch (m_object->m_type)
6419  {
6421  {
6422  assert(m_object->m_value.object);
6423  assert(m_it.object_iterator != m_object->m_value.object->end());
6424  return &(m_it.object_iterator->second);
6425  }
6426 
6428  {
6429  assert(m_object->m_value.array);
6430  assert(m_it.array_iterator != m_object->m_value.array->end());
6431  return &*m_it.array_iterator;
6432  }
6433 
6434  default:
6435  {
6436  if (m_it.primitive_iterator.is_begin())
6437  {
6438  return m_object;
6439  }
6440  else
6441  {
6442  throw std::out_of_range("cannot get value");
6443  }
6444  }
6445  }
6446  }
6447 
6450  {
6451  auto result = *this;
6452  ++(*this);
6453  return result;
6454  }
6455 
6458  {
6459  assert(m_object != nullptr);
6460 
6461  switch (m_object->m_type)
6462  {
6464  {
6465  ++m_it.object_iterator;
6466  break;
6467  }
6468 
6470  {
6471  ++m_it.array_iterator;
6472  break;
6473  }
6474 
6475  default:
6476  {
6477  ++m_it.primitive_iterator;
6478  break;
6479  }
6480  }
6481 
6482  return *this;
6483  }
6484 
6487  {
6488  auto result = *this;
6489  --(*this);
6490  return result;
6491  }
6492 
6495  {
6496  assert(m_object != nullptr);
6497 
6498  switch (m_object->m_type)
6499  {
6501  {
6502  --m_it.object_iterator;
6503  break;
6504  }
6505 
6507  {
6508  --m_it.array_iterator;
6509  break;
6510  }
6511 
6512  default:
6513  {
6514  --m_it.primitive_iterator;
6515  break;
6516  }
6517  }
6518 
6519  return *this;
6520  }
6521 
6523  bool operator==(const const_iterator& other) const
6524  {
6525  // if objects are not the same, the comparison is undefined
6526  if (m_object != other.m_object)
6527  {
6528  throw std::domain_error("cannot compare iterators of different containers");
6529  }
6530 
6531  assert(m_object != nullptr);
6532 
6533  switch (m_object->m_type)
6534  {
6536  {
6537  return (m_it.object_iterator == other.m_it.object_iterator);
6538  }
6539 
6541  {
6542  return (m_it.array_iterator == other.m_it.array_iterator);
6543  }
6544 
6545  default:
6546  {
6547  return (m_it.primitive_iterator == other.m_it.primitive_iterator);
6548  }
6549  }
6550  }
6551 
6553  bool operator!=(const const_iterator& other) const
6554  {
6555  return not operator==(other);
6556  }
6557 
6559  bool operator<(const const_iterator& other) const
6560  {
6561  // if objects are not the same, the comparison is undefined
6562  if (m_object != other.m_object)
6563  {
6564  throw std::domain_error("cannot compare iterators of different containers");
6565  }
6566 
6567  assert(m_object != nullptr);
6568 
6569  switch (m_object->m_type)
6570  {
6572  {
6573  throw std::domain_error("cannot compare order of object iterators");
6574  }
6575 
6577  {
6578  return (m_it.array_iterator < other.m_it.array_iterator);
6579  }
6580 
6581  default:
6582  {
6583  return (m_it.primitive_iterator < other.m_it.primitive_iterator);
6584  }
6585  }
6586  }
6587 
6589  bool operator<=(const const_iterator& other) const
6590  {
6591  return not other.operator < (*this);
6592  }
6593 
6595  bool operator>(const const_iterator& other) const
6596  {
6597  return not operator<=(other);
6598  }
6599 
6601  bool operator>=(const const_iterator& other) const
6602  {
6603  return not operator<(other);
6604  }
6605 
6608  {
6609  assert(m_object != nullptr);
6610 
6611  switch (m_object->m_type)
6612  {
6614  {
6615  throw std::domain_error("cannot use offsets with object iterators");
6616  }
6617 
6619  {
6620  m_it.array_iterator += i;
6621  break;
6622  }
6623 
6624  default:
6625  {
6626  m_it.primitive_iterator += i;
6627  break;
6628  }
6629  }
6630 
6631  return *this;
6632  }
6633 
6636  {
6637  return operator+=(-i);
6638  }
6639 
6642  {
6643  auto result = *this;
6644  result += i;
6645  return result;
6646  }
6647 
6650  {
6651  auto result = *this;
6652  result -= i;
6653  return result;
6654  }
6655 
6658  {
6659  assert(m_object != nullptr);
6660 
6661  switch (m_object->m_type)
6662  {
6664  {
6665  throw std::domain_error("cannot use offsets with object iterators");
6666  }
6667 
6669  {
6670  return m_it.array_iterator - other.m_it.array_iterator;
6671  }
6672 
6673  default:
6674  {
6675  return m_it.primitive_iterator - other.m_it.primitive_iterator;
6676  }
6677  }
6678  }
6679 
6682  {
6683  assert(m_object != nullptr);
6684 
6685  switch (m_object->m_type)
6686  {
6688  {
6689  throw std::domain_error("cannot use operator[] for object iterators");
6690  }
6691 
6693  {
6694  return *(m_it.array_iterator + n);
6695  }
6696 
6698  {
6699  throw std::out_of_range("cannot get value");
6700  }
6701 
6702  default:
6703  {
6704  if (m_it.primitive_iterator == -n)
6705  {
6706  return *m_object;
6707  }
6708  else
6709  {
6710  throw std::out_of_range("cannot get value");
6711  }
6712  }
6713  }
6714  }
6715 
6717  typename object_t::key_type key() const
6718  {
6719  assert(m_object != nullptr);
6720 
6721  if (m_object->is_object())
6722  {
6723  return m_it.object_iterator->first;
6724  }
6725  else
6726  {
6727  throw std::domain_error("cannot use key() for non-object iterators");
6728  }
6729  }
6730 
6733  {
6734  return operator*();
6735  }
6736 
6737  private:
6739  pointer m_object = nullptr;
6741  internal_iterator m_it = internal_iterator();
6742  };
6743 
6756  class iterator : public const_iterator
6757  {
6758  public:
6760  using pointer = typename basic_json::pointer;
6762 
6764  iterator() = default;
6765 
6767  iterator(pointer object) noexcept
6768  : base_iterator(object)
6769  {}
6770 
6772  iterator(const iterator& other) noexcept
6773  : base_iterator(other)
6774  {}
6775 
6777  iterator& operator=(iterator other) noexcept(
6778  std::is_nothrow_move_constructible<pointer>::value and
6779  std::is_nothrow_move_assignable<pointer>::value and
6780  std::is_nothrow_move_constructible<internal_iterator>::value and
6781  std::is_nothrow_move_assignable<internal_iterator>::value
6782  )
6783  {
6784  base_iterator::operator=(other);
6785  return *this;
6786  }
6787 
6790  {
6791  return const_cast<reference>(base_iterator::operator*());
6792  }
6793 
6796  {
6797  return const_cast<pointer>(base_iterator::operator->());
6798  }
6799 
6802  {
6803  iterator result = *this;
6804  base_iterator::operator++();
6805  return result;
6806  }
6807 
6810  {
6811  base_iterator::operator++();
6812  return *this;
6813  }
6814 
6817  {
6818  iterator result = *this;
6819  base_iterator::operator--();
6820  return result;
6821  }
6822 
6825  {
6826  base_iterator::operator--();
6827  return *this;
6828  }
6829 
6832  {
6833  base_iterator::operator+=(i);
6834  return *this;
6835  }
6836 
6839  {
6840  base_iterator::operator-=(i);
6841  return *this;
6842  }
6843 
6846  {
6847  auto result = *this;
6848  result += i;
6849  return result;
6850  }
6851 
6854  {
6855  auto result = *this;
6856  result -= i;
6857  return result;
6858  }
6859 
6861  difference_type operator-(const iterator& other) const
6862  {
6863  return base_iterator::operator-(other);
6864  }
6865 
6868  {
6869  return const_cast<reference>(base_iterator::operator[](n));
6870  }
6871 
6874  {
6875  return const_cast<reference>(base_iterator::value());
6876  }
6877  };
6878 
6896  template<typename Base>
6897  class json_reverse_iterator : public std::reverse_iterator<Base>
6898  {
6899  public:
6901  using base_iterator = std::reverse_iterator<Base>;
6903  using reference = typename Base::reference;
6904 
6906  json_reverse_iterator(const typename base_iterator::iterator_type& it)
6907  : base_iterator(it)
6908  {}
6909 
6912  : base_iterator(it)
6913  {}
6914 
6917  {
6918  return base_iterator::operator++(1);
6919  }
6920 
6923  {
6924  base_iterator::operator++();
6925  return *this;
6926  }
6927 
6930  {
6931  return base_iterator::operator--(1);
6932  }
6933 
6936  {
6937  base_iterator::operator--();
6938  return *this;
6939  }
6940 
6943  {
6944  base_iterator::operator+=(i);
6945  return *this;
6946  }
6947 
6950  {
6951  auto result = *this;
6952  result += i;
6953  return result;
6954  }
6955 
6958  {
6959  auto result = *this;
6960  result -= i;
6961  return result;
6962  }
6963 
6966  {
6967  return this->base() - other.base();
6968  }
6969 
6972  {
6973  return *(this->operator+(n));
6974  }
6975 
6977  typename object_t::key_type key() const
6978  {
6979  auto it = --this->base();
6980  return it.key();
6981  }
6982 
6985  {
6986  auto it = --this->base();
6987  return it.operator * ();
6988  }
6989  };
6990 
6991 
6992  private:
6994  // lexer and parser //
6996 
7004  class lexer
7005  {
7006  public:
7008  enum class token_type
7009  {
7010  uninitialized,
7011  literal_true,
7012  literal_false,
7013  literal_null,
7014  value_string,
7015  value_number,
7016  begin_array,
7017  begin_object,
7018  end_array,
7019  end_object,
7020  name_separator,
7021  value_separator,
7022  parse_error,
7023  end_of_input
7024  };
7025 
7027  using lexer_char_t = unsigned char;
7028 
7030  explicit lexer(const string_t& s) noexcept
7031  : m_stream(nullptr), m_buffer(s)
7032  {
7033  m_content = reinterpret_cast<const lexer_char_t*>(s.c_str());
7034  assert(m_content != nullptr);
7035  m_start = m_cursor = m_content;
7036  m_limit = m_content + s.size();
7037  }
7038 
7040  explicit lexer(std::istream* s) noexcept
7041  : m_stream(s), m_buffer()
7042  {
7043  assert(m_stream != nullptr);
7044  getline(*m_stream, m_buffer);
7045  m_content = reinterpret_cast<const lexer_char_t*>(m_buffer.c_str());
7046  assert(m_content != nullptr);
7047  m_start = m_cursor = m_content;
7048  m_limit = m_content + m_buffer.size();
7049  }
7050 
7052  lexer() = default;
7053 
7054  // switch off unwanted functions
7055  lexer(const lexer&) = delete;
7056  lexer operator=(const lexer&) = delete;
7057 
7073  static string_t to_unicode(const std::size_t codepoint1,
7074  const std::size_t codepoint2 = 0)
7075  {
7076  // calculate the codepoint from the given code points
7077  std::size_t codepoint = codepoint1;
7078 
7079  // check if codepoint1 is a high surrogate
7080  if (codepoint1 >= 0xD800 and codepoint1 <= 0xDBFF)
7081  {
7082  // check if codepoint2 is a low surrogate
7083  if (codepoint2 >= 0xDC00 and codepoint2 <= 0xDFFF)
7084  {
7085  codepoint =
7086  // high surrogate occupies the most significant 22 bits
7087  (codepoint1 << 10)
7088  // low surrogate occupies the least significant 15 bits
7089  + codepoint2
7090  // there is still the 0xD800, 0xDC00 and 0x10000 noise
7091  // in the result so we have to subtract with:
7092  // (0xD800 << 10) + DC00 - 0x10000 = 0x35FDC00
7093  - 0x35FDC00;
7094  }
7095  else
7096  {
7097  throw std::invalid_argument("missing or wrong low surrogate");
7098  }
7099  }
7100 
7101  string_t result;
7102 
7103  if (codepoint < 0x80)
7104  {
7105  // 1-byte characters: 0xxxxxxx (ASCII)
7106  result.append(1, static_cast<typename string_t::value_type>(codepoint));
7107  }
7108  else if (codepoint <= 0x7ff)
7109  {
7110  // 2-byte characters: 110xxxxx 10xxxxxx
7111  result.append(1, static_cast<typename string_t::value_type>(0xC0 | ((codepoint >> 6) & 0x1F)));
7112  result.append(1, static_cast<typename string_t::value_type>(0x80 | (codepoint & 0x3F)));
7113  }
7114  else if (codepoint <= 0xffff)
7115  {
7116  // 3-byte characters: 1110xxxx 10xxxxxx 10xxxxxx
7117  result.append(1, static_cast<typename string_t::value_type>(0xE0 | ((codepoint >> 12) & 0x0F)));
7118  result.append(1, static_cast<typename string_t::value_type>(0x80 | ((codepoint >> 6) & 0x3F)));
7119  result.append(1, static_cast<typename string_t::value_type>(0x80 | (codepoint & 0x3F)));
7120  }
7121  else if (codepoint <= 0x10ffff)
7122  {
7123  // 4-byte characters: 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
7124  result.append(1, static_cast<typename string_t::value_type>(0xF0 | ((codepoint >> 18) & 0x07)));
7125  result.append(1, static_cast<typename string_t::value_type>(0x80 | ((codepoint >> 12) & 0x3F)));
7126  result.append(1, static_cast<typename string_t::value_type>(0x80 | ((codepoint >> 6) & 0x3F)));
7127  result.append(1, static_cast<typename string_t::value_type>(0x80 | (codepoint & 0x3F)));
7128  }
7129  else
7130  {
7131  throw std::out_of_range("code points above 0x10FFFF are invalid");
7132  }
7133 
7134  return result;
7135  }
7136 
7138  static std::string token_type_name(token_type t)
7139  {
7140  switch (t)
7141  {
7142  case token_type::uninitialized:
7143  return "<uninitialized>";
7144  case token_type::literal_true:
7145  return "true literal";
7146  case token_type::literal_false:
7147  return "false literal";
7148  case token_type::literal_null:
7149  return "null literal";
7150  case token_type::value_string:
7151  return "string literal";
7152  case token_type::value_number:
7153  return "number literal";
7154  case token_type::begin_array:
7155  return "'['";
7156  case token_type::begin_object:
7157  return "'{'";
7158  case token_type::end_array:
7159  return "']'";
7160  case token_type::end_object:
7161  return "'}'";
7162  case token_type::name_separator:
7163  return "':'";
7164  case token_type::value_separator:
7165  return "','";
7166  case token_type::parse_error:
7167  return "<parse error>";
7168  case token_type::end_of_input:
7169  return "end of input";
7170  default:
7171  {
7172  // catch non-enum values
7173  return "unknown token"; // LCOV_EXCL_LINE
7174  }
7175  }
7176  }
7177 
7188  token_type scan() noexcept
7189  {
7190  // pointer for backtracking information
7191  m_marker = nullptr;
7192 
7193  // remember the begin of the token
7194  m_start = m_cursor;
7195  assert(m_start != nullptr);
7196 
7197 
7198  {
7199  lexer_char_t yych;
7200  unsigned int yyaccept = 0;
7201  static const unsigned char yybm[] =
7202  {
7203  0, 0, 0, 0, 0, 0, 0, 0,
7204  0, 32, 32, 0, 0, 32, 0, 0,
7205  128, 128, 128, 128, 128, 128, 128, 128,
7206  128, 128, 128, 128, 128, 128, 128, 128,
7207  160, 128, 0, 128, 128, 128, 128, 128,
7208  128, 128, 128, 128, 128, 128, 128, 128,
7209  192, 192, 192, 192, 192, 192, 192, 192,
7210  192, 192, 128, 128, 128, 128, 128, 128,
7211  128, 128, 128, 128, 128, 128, 128, 128,
7212  128, 128, 128, 128, 128, 128, 128, 128,
7213  128, 128, 128, 128, 128, 128, 128, 128,
7214  128, 128, 128, 128, 0, 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, 128, 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  };
7236  if ((m_limit - m_cursor) < 5)
7237  {
7238  yyfill(); // LCOV_EXCL_LINE;
7239  }
7240  yych = *m_cursor;
7241  if (yybm[0 + yych] & 32)
7242  {
7243  goto basic_json_parser_6;
7244  }
7245  if (yych <= '\\')
7246  {
7247  if (yych <= '-')
7248  {
7249  if (yych <= '"')
7250  {
7251  if (yych <= 0x00)
7252  {
7253  goto basic_json_parser_2;
7254  }
7255  if (yych <= '!')
7256  {
7257  goto basic_json_parser_4;
7258  }
7259  goto basic_json_parser_9;
7260  }
7261  else
7262  {
7263  if (yych <= '+')
7264  {
7265  goto basic_json_parser_4;
7266  }
7267  if (yych <= ',')
7268  {
7269  goto basic_json_parser_10;
7270  }
7271  goto basic_json_parser_12;
7272  }
7273  }
7274  else
7275  {
7276  if (yych <= '9')
7277  {
7278  if (yych <= '/')
7279  {
7280  goto basic_json_parser_4;
7281  }
7282  if (yych <= '0')
7283  {
7284  goto basic_json_parser_13;
7285  }
7286  goto basic_json_parser_15;
7287  }
7288  else
7289  {
7290  if (yych <= ':')
7291  {
7292  goto basic_json_parser_17;
7293  }
7294  if (yych == '[')
7295  {
7296  goto basic_json_parser_19;
7297  }
7298  goto basic_json_parser_4;
7299  }
7300  }
7301  }
7302  else
7303  {
7304  if (yych <= 't')
7305  {
7306  if (yych <= 'f')
7307  {
7308  if (yych <= ']')
7309  {
7310  goto basic_json_parser_21;
7311  }
7312  if (yych <= 'e')
7313  {
7314  goto basic_json_parser_4;
7315  }
7316  goto basic_json_parser_23;
7317  }
7318  else
7319  {
7320  if (yych == 'n')
7321  {
7322  goto basic_json_parser_24;
7323  }
7324  if (yych <= 's')
7325  {
7326  goto basic_json_parser_4;
7327  }
7328  goto basic_json_parser_25;
7329  }
7330  }
7331  else
7332  {
7333  if (yych <= '|')
7334  {
7335  if (yych == '{')
7336  {
7337  goto basic_json_parser_26;
7338  }
7339  goto basic_json_parser_4;
7340  }
7341  else
7342  {
7343  if (yych <= '}')
7344  {
7345  goto basic_json_parser_28;
7346  }
7347  if (yych == 0xEF)
7348  {
7349  goto basic_json_parser_30;
7350  }
7351  goto basic_json_parser_4;
7352  }
7353  }
7354  }
7355 basic_json_parser_2:
7356  ++m_cursor;
7357  {
7358  return token_type::end_of_input;
7359  }
7360 basic_json_parser_4:
7361  ++m_cursor;
7362 basic_json_parser_5:
7363  {
7364  return token_type::parse_error;
7365  }
7366 basic_json_parser_6:
7367  ++m_cursor;
7368  if (m_limit <= m_cursor)
7369  {
7370  yyfill(); // LCOV_EXCL_LINE;
7371  }
7372  yych = *m_cursor;
7373  if (yybm[0 + yych] & 32)
7374  {
7375  goto basic_json_parser_6;
7376  }
7377  {
7378  return scan();
7379  }
7380 basic_json_parser_9:
7381  yyaccept = 0;
7382  yych = *(m_marker = ++m_cursor);
7383  if (yych <= 0x0F)
7384  {
7385  goto basic_json_parser_5;
7386  }
7387  goto basic_json_parser_32;
7388 basic_json_parser_10:
7389  ++m_cursor;
7390  {
7391  return token_type::value_separator;
7392  }
7393 basic_json_parser_12:
7394  yych = *++m_cursor;
7395  if (yych <= '/')
7396  {
7397  goto basic_json_parser_5;
7398  }
7399  if (yych <= '0')
7400  {
7401  goto basic_json_parser_13;
7402  }
7403  if (yych <= '9')
7404  {
7405  goto basic_json_parser_15;
7406  }
7407  goto basic_json_parser_5;
7408 basic_json_parser_13:
7409  yyaccept = 1;
7410  yych = *(m_marker = ++m_cursor);
7411  if (yych <= 'D')
7412  {
7413  if (yych == '.')
7414  {
7415  goto basic_json_parser_37;
7416  }
7417  }
7418  else
7419  {
7420  if (yych <= 'E')
7421  {
7422  goto basic_json_parser_38;
7423  }
7424  if (yych == 'e')
7425  {
7426  goto basic_json_parser_38;
7427  }
7428  }
7429 basic_json_parser_14:
7430  {
7431  return token_type::value_number;
7432  }
7433 basic_json_parser_15:
7434  yyaccept = 1;
7435  m_marker = ++m_cursor;
7436  if ((m_limit - m_cursor) < 3)
7437  {
7438  yyfill(); // LCOV_EXCL_LINE;
7439  }
7440  yych = *m_cursor;
7441  if (yybm[0 + yych] & 64)
7442  {
7443  goto basic_json_parser_15;
7444  }
7445  if (yych <= 'D')
7446  {
7447  if (yych == '.')
7448  {
7449  goto basic_json_parser_37;
7450  }
7451  goto basic_json_parser_14;
7452  }
7453  else
7454  {
7455  if (yych <= 'E')
7456  {
7457  goto basic_json_parser_38;
7458  }
7459  if (yych == 'e')
7460  {
7461  goto basic_json_parser_38;
7462  }
7463  goto basic_json_parser_14;
7464  }
7465 basic_json_parser_17:
7466  ++m_cursor;
7467  {
7468  return token_type::name_separator;
7469  }
7470 basic_json_parser_19:
7471  ++m_cursor;
7472  {
7473  return token_type::begin_array;
7474  }
7475 basic_json_parser_21:
7476  ++m_cursor;
7477  {
7478  return token_type::end_array;
7479  }
7480 basic_json_parser_23:
7481  yyaccept = 0;
7482  yych = *(m_marker = ++m_cursor);
7483  if (yych == 'a')
7484  {
7485  goto basic_json_parser_39;
7486  }
7487  goto basic_json_parser_5;
7488 basic_json_parser_24:
7489  yyaccept = 0;
7490  yych = *(m_marker = ++m_cursor);
7491  if (yych == 'u')
7492  {
7493  goto basic_json_parser_40;
7494  }
7495  goto basic_json_parser_5;
7496 basic_json_parser_25:
7497  yyaccept = 0;
7498  yych = *(m_marker = ++m_cursor);
7499  if (yych == 'r')
7500  {
7501  goto basic_json_parser_41;
7502  }
7503  goto basic_json_parser_5;
7504 basic_json_parser_26:
7505  ++m_cursor;
7506  {
7507  return token_type::begin_object;
7508  }
7509 basic_json_parser_28:
7510  ++m_cursor;
7511  {
7512  return token_type::end_object;
7513  }
7514 basic_json_parser_30:
7515  yyaccept = 0;
7516  yych = *(m_marker = ++m_cursor);
7517  if (yych == 0xBB)
7518  {
7519  goto basic_json_parser_42;
7520  }
7521  goto basic_json_parser_5;
7522 basic_json_parser_31:
7523  ++m_cursor;
7524  if (m_limit <= m_cursor)
7525  {
7526  yyfill(); // LCOV_EXCL_LINE;
7527  }
7528  yych = *m_cursor;
7529 basic_json_parser_32:
7530  if (yybm[0 + yych] & 128)
7531  {
7532  goto basic_json_parser_31;
7533  }
7534  if (yych <= 0x0F)
7535  {
7536  goto basic_json_parser_33;
7537  }
7538  if (yych <= '"')
7539  {
7540  goto basic_json_parser_34;
7541  }
7542  goto basic_json_parser_36;
7543 basic_json_parser_33:
7544  m_cursor = m_marker;
7545  if (yyaccept == 0)
7546  {
7547  goto basic_json_parser_5;
7548  }
7549  else
7550  {
7551  goto basic_json_parser_14;
7552  }
7553 basic_json_parser_34:
7554  ++m_cursor;
7555  {
7556  return token_type::value_string;
7557  }
7558 basic_json_parser_36:
7559  ++m_cursor;
7560  if (m_limit <= m_cursor)
7561  {
7562  yyfill(); // LCOV_EXCL_LINE;
7563  }
7564  yych = *m_cursor;
7565  if (yych <= 'e')
7566  {
7567  if (yych <= '/')
7568  {
7569  if (yych == '"')
7570  {
7571  goto basic_json_parser_31;
7572  }
7573  if (yych <= '.')
7574  {
7575  goto basic_json_parser_33;
7576  }
7577  goto basic_json_parser_31;
7578  }
7579  else
7580  {
7581  if (yych <= '\\')
7582  {
7583  if (yych <= '[')
7584  {
7585  goto basic_json_parser_33;
7586  }
7587  goto basic_json_parser_31;
7588  }
7589  else
7590  {
7591  if (yych == 'b')
7592  {
7593  goto basic_json_parser_31;
7594  }
7595  goto basic_json_parser_33;
7596  }
7597  }
7598  }
7599  else
7600  {
7601  if (yych <= 'q')
7602  {
7603  if (yych <= 'f')
7604  {
7605  goto basic_json_parser_31;
7606  }
7607  if (yych == 'n')
7608  {
7609  goto basic_json_parser_31;
7610  }
7611  goto basic_json_parser_33;
7612  }
7613  else
7614  {
7615  if (yych <= 's')
7616  {
7617  if (yych <= 'r')
7618  {
7619  goto basic_json_parser_31;
7620  }
7621  goto basic_json_parser_33;
7622  }
7623  else
7624  {
7625  if (yych <= 't')
7626  {
7627  goto basic_json_parser_31;
7628  }
7629  if (yych <= 'u')
7630  {
7631  goto basic_json_parser_43;
7632  }
7633  goto basic_json_parser_33;
7634  }
7635  }
7636  }
7637 basic_json_parser_37:
7638  yych = *++m_cursor;
7639  if (yych <= '/')
7640  {
7641  goto basic_json_parser_33;
7642  }
7643  if (yych <= '9')
7644  {
7645  goto basic_json_parser_44;
7646  }
7647  goto basic_json_parser_33;
7648 basic_json_parser_38:
7649  yych = *++m_cursor;
7650  if (yych <= ',')
7651  {
7652  if (yych == '+')
7653  {
7654  goto basic_json_parser_46;
7655  }
7656  goto basic_json_parser_33;
7657  }
7658  else
7659  {
7660  if (yych <= '-')
7661  {
7662  goto basic_json_parser_46;
7663  }
7664  if (yych <= '/')
7665  {
7666  goto basic_json_parser_33;
7667  }
7668  if (yych <= '9')
7669  {
7670  goto basic_json_parser_47;
7671  }
7672  goto basic_json_parser_33;
7673  }
7674 basic_json_parser_39:
7675  yych = *++m_cursor;
7676  if (yych == 'l')
7677  {
7678  goto basic_json_parser_49;
7679  }
7680  goto basic_json_parser_33;
7681 basic_json_parser_40:
7682  yych = *++m_cursor;
7683  if (yych == 'l')
7684  {
7685  goto basic_json_parser_50;
7686  }
7687  goto basic_json_parser_33;
7688 basic_json_parser_41:
7689  yych = *++m_cursor;
7690  if (yych == 'u')
7691  {
7692  goto basic_json_parser_51;
7693  }
7694  goto basic_json_parser_33;
7695 basic_json_parser_42:
7696  yych = *++m_cursor;
7697  if (yych == 0xBF)
7698  {
7699  goto basic_json_parser_52;
7700  }
7701  goto basic_json_parser_33;
7702 basic_json_parser_43:
7703  ++m_cursor;
7704  if (m_limit <= m_cursor)
7705  {
7706  yyfill(); // LCOV_EXCL_LINE;
7707  }
7708  yych = *m_cursor;
7709  if (yych <= '@')
7710  {
7711  if (yych <= '/')
7712  {
7713  goto basic_json_parser_33;
7714  }
7715  if (yych <= '9')
7716  {
7717  goto basic_json_parser_54;
7718  }
7719  goto basic_json_parser_33;
7720  }
7721  else
7722  {
7723  if (yych <= 'F')
7724  {
7725  goto basic_json_parser_54;
7726  }
7727  if (yych <= '`')
7728  {
7729  goto basic_json_parser_33;
7730  }
7731  if (yych <= 'f')
7732  {
7733  goto basic_json_parser_54;
7734  }
7735  goto basic_json_parser_33;
7736  }
7737 basic_json_parser_44:
7738  yyaccept = 1;
7739  m_marker = ++m_cursor;
7740  if ((m_limit - m_cursor) < 3)
7741  {
7742  yyfill(); // LCOV_EXCL_LINE;
7743  }
7744  yych = *m_cursor;
7745  if (yych <= 'D')
7746  {
7747  if (yych <= '/')
7748  {
7749  goto basic_json_parser_14;
7750  }
7751  if (yych <= '9')
7752  {
7753  goto basic_json_parser_44;
7754  }
7755  goto basic_json_parser_14;
7756  }
7757  else
7758  {
7759  if (yych <= 'E')
7760  {
7761  goto basic_json_parser_38;
7762  }
7763  if (yych == 'e')
7764  {
7765  goto basic_json_parser_38;
7766  }
7767  goto basic_json_parser_14;
7768  }
7769 basic_json_parser_46:
7770  yych = *++m_cursor;
7771  if (yych <= '/')
7772  {
7773  goto basic_json_parser_33;
7774  }
7775  if (yych >= ':')
7776  {
7777  goto basic_json_parser_33;
7778  }
7779 basic_json_parser_47:
7780  ++m_cursor;
7781  if (m_limit <= m_cursor)
7782  {
7783  yyfill(); // LCOV_EXCL_LINE;
7784  }
7785  yych = *m_cursor;
7786  if (yych <= '/')
7787  {
7788  goto basic_json_parser_14;
7789  }
7790  if (yych <= '9')
7791  {
7792  goto basic_json_parser_47;
7793  }
7794  goto basic_json_parser_14;
7795 basic_json_parser_49:
7796  yych = *++m_cursor;
7797  if (yych == 's')
7798  {
7799  goto basic_json_parser_55;
7800  }
7801  goto basic_json_parser_33;
7802 basic_json_parser_50:
7803  yych = *++m_cursor;
7804  if (yych == 'l')
7805  {
7806  goto basic_json_parser_56;
7807  }
7808  goto basic_json_parser_33;
7809 basic_json_parser_51:
7810  yych = *++m_cursor;
7811  if (yych == 'e')
7812  {
7813  goto basic_json_parser_58;
7814  }
7815  goto basic_json_parser_33;
7816 basic_json_parser_52:
7817  ++m_cursor;
7818  {
7819  return scan();
7820  }
7821 basic_json_parser_54:
7822  ++m_cursor;
7823  if (m_limit <= m_cursor)
7824  {
7825  yyfill(); // LCOV_EXCL_LINE;
7826  }
7827  yych = *m_cursor;
7828  if (yych <= '@')
7829  {
7830  if (yych <= '/')
7831  {
7832  goto basic_json_parser_33;
7833  }
7834  if (yych <= '9')
7835  {
7836  goto basic_json_parser_60;
7837  }
7838  goto basic_json_parser_33;
7839  }
7840  else
7841  {
7842  if (yych <= 'F')
7843  {
7844  goto basic_json_parser_60;
7845  }
7846  if (yych <= '`')
7847  {
7848  goto basic_json_parser_33;
7849  }
7850  if (yych <= 'f')
7851  {
7852  goto basic_json_parser_60;
7853  }
7854  goto basic_json_parser_33;
7855  }
7856 basic_json_parser_55:
7857  yych = *++m_cursor;
7858  if (yych == 'e')
7859  {
7860  goto basic_json_parser_61;
7861  }
7862  goto basic_json_parser_33;
7863 basic_json_parser_56:
7864  ++m_cursor;
7865  {
7866  return token_type::literal_null;
7867  }
7868 basic_json_parser_58:
7869  ++m_cursor;
7870  {
7871  return token_type::literal_true;
7872  }
7873 basic_json_parser_60:
7874  ++m_cursor;
7875  if (m_limit <= m_cursor)
7876  {
7877  yyfill(); // LCOV_EXCL_LINE;
7878  }
7879  yych = *m_cursor;
7880  if (yych <= '@')
7881  {
7882  if (yych <= '/')
7883  {
7884  goto basic_json_parser_33;
7885  }
7886  if (yych <= '9')
7887  {
7888  goto basic_json_parser_63;
7889  }
7890  goto basic_json_parser_33;
7891  }
7892  else
7893  {
7894  if (yych <= 'F')
7895  {
7896  goto basic_json_parser_63;
7897  }
7898  if (yych <= '`')
7899  {
7900  goto basic_json_parser_33;
7901  }
7902  if (yych <= 'f')
7903  {
7904  goto basic_json_parser_63;
7905  }
7906  goto basic_json_parser_33;
7907  }
7908 basic_json_parser_61:
7909  ++m_cursor;
7910  {
7911  return token_type::literal_false;
7912  }
7913 basic_json_parser_63:
7914  ++m_cursor;
7915  if (m_limit <= m_cursor)
7916  {
7917  yyfill(); // LCOV_EXCL_LINE;
7918  }
7919  yych = *m_cursor;
7920  if (yych <= '@')
7921  {
7922  if (yych <= '/')
7923  {
7924  goto basic_json_parser_33;
7925  }
7926  if (yych <= '9')
7927  {
7928  goto basic_json_parser_31;
7929  }
7930  goto basic_json_parser_33;
7931  }
7932  else
7933  {
7934  if (yych <= 'F')
7935  {
7936  goto basic_json_parser_31;
7937  }
7938  if (yych <= '`')
7939  {
7940  goto basic_json_parser_33;
7941  }
7942  if (yych <= 'f')
7943  {
7944  goto basic_json_parser_31;
7945  }
7946  goto basic_json_parser_33;
7947  }
7948  }
7949 
7950 
7951  }
7952 
7954  void yyfill() noexcept
7955  {
7956  if (m_stream == nullptr or not * m_stream)
7957  {
7958  return;
7959  }
7960 
7961  const ssize_t offset_start = m_start - m_content;
7962  const ssize_t offset_marker = m_marker - m_start;
7963  const ssize_t offset_cursor = m_cursor - m_start;
7964 
7965  m_buffer.erase(0, static_cast<size_t>(offset_start));
7966  std::string line;
7967  assert(m_stream != nullptr);
7968  std::getline(*m_stream, line);
7969  m_buffer += "\n" + line; // add line with newline symbol
7970 
7971  m_content = reinterpret_cast<const lexer_char_t*>(m_buffer.c_str());
7972  assert(m_content != nullptr);
7973  m_start = m_content;
7974  m_marker = m_start + offset_marker;
7975  m_cursor = m_start + offset_cursor;
7976  m_limit = m_start + m_buffer.size() - 1;
7977  }
7978 
7980  string_t get_token() const noexcept
7981  {
7982  assert(m_start != nullptr);
7983  return string_t(reinterpret_cast<typename string_t::const_pointer>(m_start),
7984  static_cast<size_t>(m_cursor - m_start));
7985  }
7986 
8008  string_t get_string() const
8009  {
8010  string_t result;
8011  result.reserve(static_cast<size_t>(m_cursor - m_start - 2));
8012 
8013  // iterate the result between the quotes
8014  for (const lexer_char_t* i = m_start + 1; i < m_cursor - 1; ++i)
8015  {
8016  // process escaped characters
8017  if (*i == '\\')
8018  {
8019  // read next character
8020  ++i;
8021 
8022  switch (*i)
8023  {
8024  // the default escapes
8025  case 't':
8026  {
8027  result += "\t";
8028  break;
8029  }
8030  case 'b':
8031  {
8032  result += "\b";
8033  break;
8034  }
8035  case 'f':
8036  {
8037  result += "\f";
8038  break;
8039  }
8040  case 'n':
8041  {
8042  result += "\n";
8043  break;
8044  }
8045  case 'r':
8046  {
8047  result += "\r";
8048  break;
8049  }
8050  case '\\':
8051  {
8052  result += "\\";
8053  break;
8054  }
8055  case '/':
8056  {
8057  result += "/";
8058  break;
8059  }
8060  case '"':
8061  {
8062  result += "\"";
8063  break;
8064  }
8065 
8066  // unicode
8067  case 'u':
8068  {
8069  // get code xxxx from uxxxx
8070  auto codepoint = std::strtoul(std::string(reinterpret_cast<typename string_t::const_pointer>(i + 1),
8071  4).c_str(), nullptr, 16);
8072 
8073  // check if codepoint is a high surrogate
8074  if (codepoint >= 0xD800 and codepoint <= 0xDBFF)
8075  {
8076  // make sure there is a subsequent unicode
8077  if ((i + 6 >= m_limit) or * (i + 5) != '\\' or * (i + 6) != 'u')
8078  {
8079  throw std::invalid_argument("missing low surrogate");
8080  }
8081 
8082  // get code yyyy from uxxxx\uyyyy
8083  auto codepoint2 = std::strtoul(std::string(reinterpret_cast<typename string_t::const_pointer>
8084  (i + 7), 4).c_str(), nullptr, 16);
8085  result += to_unicode(codepoint, codepoint2);
8086  // skip the next 10 characters (xxxx\uyyyy)
8087  i += 10;
8088  }
8089  else
8090  {
8091  // add unicode character(s)
8092  result += to_unicode(codepoint);
8093  // skip the next four characters (xxxx)
8094  i += 4;
8095  }
8096  break;
8097  }
8098  }
8099  }
8100  else
8101  {
8102  // all other characters are just copied to the end of the
8103  // string
8104  result.append(1, static_cast<typename string_t::value_type>(*i));
8105  }
8106  }
8107 
8108  return result;
8109  }
8110 
8131  long double str_to_float_t(long double* /* type */, char** endptr) const
8132  {
8133  return std::strtold(reinterpret_cast<typename string_t::const_pointer>(m_start), endptr);
8134  }
8135 
8151  double str_to_float_t(double* /* type */, char** endptr) const
8152  {
8153  return std::strtod(reinterpret_cast<typename string_t::const_pointer>(m_start), endptr);
8154  }
8155 
8171  float str_to_float_t(float* /* type */, char** endptr) const
8172  {
8173  return std::strtof(reinterpret_cast<typename string_t::const_pointer>(m_start), endptr);
8174  }
8175 
8188  template <typename T_A, typename T_B>
8189  bool attempt_cast(T_A source, T_B& dest) const
8190  {
8191  dest = static_cast<T_B>(source);
8192  return (source == static_cast<T_A>(dest));
8193  }
8194 
8233  void get_number(basic_json& result) const
8234  {
8235  typename string_t::value_type* endptr;
8236  assert(m_start != nullptr);
8237  errno = 0;
8238 
8239  // attempt to parse it as an integer - first checking for a
8240  // negative number
8241  if (*reinterpret_cast<typename string_t::const_pointer>(m_start) != '-')
8242  {
8243  // positive, parse with strtoull and attempt cast to
8244  // number_unsigned_t
8245  if (attempt_cast(std::strtoull(reinterpret_cast<typename string_t::const_pointer>(m_start), &endptr,
8246  10), result.m_value.number_unsigned))
8247  {
8248  result.m_type = value_t::number_unsigned;
8249  }
8250  else
8251  {
8252  // cast failed due to overflow - store as float
8253  result.m_type = value_t::number_float;
8254  }
8255  }
8256  else
8257  {
8258  // Negative, parse with strtoll and attempt cast to
8259  // number_integer_t
8260  if (attempt_cast(std::strtoll(reinterpret_cast<typename string_t::const_pointer>(m_start), &endptr,
8261  10), result.m_value.number_integer))
8262  {
8263  result.m_type = value_t::number_integer;
8264  }
8265  else
8266  {
8267  // cast failed due to overflow - store as float
8268  result.m_type = value_t::number_float;
8269  }
8270  }
8271 
8272  // check the end of the number was reached and no range error
8273  // occurred
8274  if (reinterpret_cast<lexer_char_t*>(endptr) != m_cursor || errno == ERANGE)
8275  {
8276  result.m_type = value_t::number_float;
8277  }
8278 
8279  if (result.m_type == value_t::number_float)
8280  {
8281  // either the number won't fit in an integer (range error from
8282  // strtoull/strtoll or overflow on cast) or there was something
8283  // else after the number, which could be an exponent
8284 
8285  // parse with strtod
8286  result.m_value.number_float = str_to_float_t(static_cast<number_float_t*>(nullptr), &endptr);
8287 
8288  // anything after the number is an error
8289  if (reinterpret_cast<lexer_char_t*>(endptr) != m_cursor)
8290  {
8291  throw std::invalid_argument(std::string("parse error - ") + get_token() + " is not a number");
8292  }
8293  }
8294  }
8295 
8296  private:
8298  std::istream* m_stream = nullptr;
8300  string_t m_buffer;
8302  const lexer_char_t* m_content = nullptr;
8304  const lexer_char_t* m_start = nullptr;
8306  const lexer_char_t* m_marker = nullptr;
8308  const lexer_char_t* m_cursor = nullptr;
8310  const lexer_char_t* m_limit = nullptr;
8311  };
8312 
8318  class parser
8319  {
8320  public:
8322  parser(const string_t& s, parser_callback_t cb = nullptr)
8323  : callback(cb), m_lexer(s)
8324  {
8325  // read first token
8326  get_token();
8327  }
8328 
8330  parser(std::istream& _is, parser_callback_t cb = nullptr)
8331  : callback(cb), m_lexer(&_is)
8332  {
8333  // read first token
8334  get_token();
8335  }
8336 
8338  basic_json parse()
8339  {
8340  basic_json result = parse_internal(true);
8341 
8342  expect(lexer::token_type::end_of_input);
8343 
8344  // return parser result and replace it with null in case the
8345  // top-level value was discarded by the callback function
8346  return result.is_discarded() ? basic_json() : result;
8347  }
8348 
8349  private:
8351  basic_json parse_internal(bool keep)
8352  {
8353  auto result = basic_json(value_t::discarded);
8354 
8355  switch (last_token)
8356  {
8357  case lexer::token_type::begin_object:
8358  {
8359  if (keep and (not callback or (keep = callback(depth++, parse_event_t::object_start, result))))
8360  {
8361  // explicitly set result to object to cope with {}
8362  result.m_type = value_t::object;
8363  result.m_value = json_value(value_t::object);
8364  }
8365 
8366  // read next token
8367  get_token();
8368 
8369  // closing } -> we are done
8370  if (last_token == lexer::token_type::end_object)
8371  {
8372  get_token();
8373  if (keep and callback and not callback(--depth, parse_event_t::object_end, result))
8374  {
8375  result = basic_json(value_t::discarded);
8376  }
8377  return result;
8378  }
8379 
8380  // no comma is expected here
8381  unexpect(lexer::token_type::value_separator);
8382 
8383  // otherwise: parse key-value pairs
8384  do
8385  {
8386  // ugly, but could be fixed with loop reorganization
8387  if (last_token == lexer::token_type::value_separator)
8388  {
8389  get_token();
8390  }
8391 
8392  // store key
8393  expect(lexer::token_type::value_string);
8394  const auto key = m_lexer.get_string();
8395 
8396  bool keep_tag = false;
8397  if (keep)
8398  {
8399  if (callback)
8400  {
8401  basic_json k(key);
8402  keep_tag = callback(depth, parse_event_t::key, k);
8403  }
8404  else
8405  {
8406  keep_tag = true;
8407  }
8408  }
8409 
8410  // parse separator (:)
8411  get_token();
8412  expect(lexer::token_type::name_separator);
8413 
8414  // parse and add value
8415  get_token();
8416  auto value = parse_internal(keep);
8417  if (keep and keep_tag and not value.is_discarded())
8418  {
8419  result[key] = std::move(value);
8420  }
8421  }
8422  while (last_token == lexer::token_type::value_separator);
8423 
8424  // closing }
8425  expect(lexer::token_type::end_object);
8426  get_token();
8427  if (keep and callback and not callback(--depth, parse_event_t::object_end, result))
8428  {
8429  result = basic_json(value_t::discarded);
8430  }
8431 
8432  return result;
8433  }
8434 
8435  case lexer::token_type::begin_array:
8436  {
8437  if (keep and (not callback or (keep = callback(depth++, parse_event_t::array_start, result))))
8438  {
8439  // explicitly set result to object to cope with []
8440  result.m_type = value_t::array;
8441  result.m_value = json_value(value_t::array);
8442  }
8443 
8444  // read next token
8445  get_token();
8446 
8447  // closing ] -> we are done
8448  if (last_token == lexer::token_type::end_array)
8449  {
8450  get_token();
8451  if (callback and not callback(--depth, parse_event_t::array_end, result))
8452  {
8453  result = basic_json(value_t::discarded);
8454  }
8455  return result;
8456  }
8457 
8458  // no comma is expected here
8459  unexpect(lexer::token_type::value_separator);
8460 
8461  // otherwise: parse values
8462  do
8463  {
8464  // ugly, but could be fixed with loop reorganization
8465  if (last_token == lexer::token_type::value_separator)
8466  {
8467  get_token();
8468  }
8469 
8470  // parse value
8471  auto value = parse_internal(keep);
8472  if (keep and not value.is_discarded())
8473  {
8474  result.push_back(std::move(value));
8475  }
8476  }
8477  while (last_token == lexer::token_type::value_separator);
8478 
8479  // closing ]
8480  expect(lexer::token_type::end_array);
8481  get_token();
8482  if (keep and callback and not callback(--depth, parse_event_t::array_end, result))
8483  {
8484  result = basic_json(value_t::discarded);
8485  }
8486 
8487  return result;
8488  }
8489 
8490  case lexer::token_type::literal_null:
8491  {
8492  get_token();
8493  result.m_type = value_t::null;
8494  break;
8495  }
8496 
8497  case lexer::token_type::value_string:
8498  {
8499  const auto s = m_lexer.get_string();
8500  get_token();
8501  result = basic_json(s);
8502  break;
8503  }
8504 
8505  case lexer::token_type::literal_true:
8506  {
8507  get_token();
8508  result.m_type = value_t::boolean;
8509  result.m_value = true;
8510  break;
8511  }
8512 
8513  case lexer::token_type::literal_false:
8514  {
8515  get_token();
8516  result.m_type = value_t::boolean;
8517  result.m_value = false;
8518  break;
8519  }
8520 
8521  case lexer::token_type::value_number:
8522  {
8523  m_lexer.get_number(result);
8524  get_token();
8525  break;
8526  }
8527 
8528  default:
8529  {
8530  // the last token was unexpected
8531  unexpect(last_token);
8532  }
8533  }
8534 
8535  if (keep and callback and not callback(depth, parse_event_t::value, result))
8536  {
8537  result = basic_json(value_t::discarded);
8538  }
8539  return result;
8540  }
8541 
8543  typename lexer::token_type get_token()
8544  {
8545  last_token = m_lexer.scan();
8546  return last_token;
8547  }
8548 
8549  void expect(typename lexer::token_type t) const
8550  {
8551  if (t != last_token)
8552  {
8553  std::string error_msg = "parse error - unexpected ";
8554  error_msg += (last_token == lexer::token_type::parse_error ? ("'" + m_lexer.get_token() + "'") :
8555  lexer::token_type_name(last_token));
8556  error_msg += "; expected " + lexer::token_type_name(t);
8557  throw std::invalid_argument(error_msg);
8558  }
8559  }
8560 
8561  void unexpect(typename lexer::token_type t) const
8562  {
8563  if (t == last_token)
8564  {
8565  std::string error_msg = "parse error - unexpected ";
8566  error_msg += (last_token == lexer::token_type::parse_error ? ("'" + m_lexer.get_token() + "'") :
8567  lexer::token_type_name(last_token));
8568  throw std::invalid_argument(error_msg);
8569  }
8570  }
8571 
8572  private:
8574  int depth = 0;
8576  parser_callback_t callback;
8578  typename lexer::token_type last_token = lexer::token_type::uninitialized;
8580  lexer m_lexer;
8581  };
8582 };
8583 
8584 
8586 // presets //
8588 
8598 }
8599 
8600 
8602 // nonmember functions //
8604 
8605 // specialization of std::swap, and std::hash
8606 namespace std
8607 {
8613 template <>
8614 inline void swap(nlohmann::json& j1,
8615  nlohmann::json& j2) noexcept(
8616  is_nothrow_move_constructible<nlohmann::json>::value and
8617  is_nothrow_move_assignable<nlohmann::json>::value
8618  )
8619 {
8620  j1.swap(j2);
8621 }
8622 
8624 template <>
8625 struct hash<nlohmann::json>
8626 {
8632  std::size_t operator()(const nlohmann::json& j) const
8633  {
8634  // a naive hashing via the string representation
8635  const auto& h = hash<nlohmann::json::string_t>();
8636  return h(j.dump());
8637  }
8638 };
8639 }
8640 
8653 inline nlohmann::json operator "" _json(const char* s, std::size_t)
8654 {
8655  return nlohmann::json::parse(reinterpret_cast<const nlohmann::json::string_t::value_type*>(s));
8656 }
8657 
8658 // restore GCC/clang diagnostic settings
8659 #if defined(__clang__) || defined(__GNUC__) || defined(__GNUG__)
8660  #pragma GCC diagnostic pop
8661 #endif
8662 
8663 #endif
bool is_null() const noexcept
return whether value is null
Definition: json.hpp:2165
reference operator*()
return a reference to the value pointed to by the iterator
Definition: json.hpp:6789
reverse_iterator rbegin()
returns an iterator to the reverse-beginning
Definition: json.hpp:4169
friend bool operator<=(const_reference lhs, const_reference rhs) noexcept
comparison: less than or equal
Definition: json.hpp:5427
basic_json(const value_t value_type)
create an empty value with a given type
Definition: json.hpp:945
basic_json(const array_t &val)
create an array (explicit)
Definition: json.hpp:1073
size_type count(typename object_t::key_type key) const
returns the number of occurrences of a key in a JSON object
Definition: json.hpp:3987
value_t type() const noexcept
return the type of the JSON value (explicit)
Definition: json.hpp:2095
bool is_number_integer() const noexcept
return whether value is an integer number
Definition: json.hpp:2237
const_reference operator[](size_type idx) const
access specified array element
Definition: json.hpp:3199
reference value() const
return the value of an iterator
Definition: json.hpp:6873
json_reverse_iterator & operator--()
pre-decrement (–it)
Definition: json.hpp:6935
bool is_boolean() const noexcept
return whether value is a boolean
Definition: json.hpp:2184
void clear() noexcept
clears the contents
Definition: json.hpp:4537
bool operator==(const const_iterator &other) const
comparison: equal
Definition: json.hpp:6523
json_reverse_iterator operator--(int)
post-decrement (it–)
Definition: json.hpp:6929
reference operator[](T *(&key)[n])
access specified object element
Definition: json.hpp:3331
friend std::istream & operator>>(std::istream &i, basic_json &j)
deserialize from stream
Definition: json.hpp:5640
bool is_number() const noexcept
return whether value is a number
Definition: json.hpp:2211
iterator & operator+=(difference_type i)
add to iterator
Definition: json.hpp:6831
static basic_json object(std::initializer_list< basic_json > init=std::initializer_list< basic_json >())
explicitly create an object from an initializer list
Definition: json.hpp:1652
const_iterator operator-(difference_type i)
subtract from iterator
Definition: json.hpp:6649
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:4723
bool is_array() const noexcept
return whether value is an array
Definition: json.hpp:2325
basic_json(const typename string_t::value_type *val)
create a string (explicit)
Definition: json.hpp:1163
basic_json(boolean_t val)
create a boolean (explicit)
Definition: json.hpp:1212
reference operator[](difference_type n) const
access to successor
Definition: json.hpp:6971
iterator find(typename object_t::key_type key)
find an element in a JSON object
Definition: json.hpp:3939
basic_json(const number_unsigned_t val)
create an unsigned integer number (explicit)
Definition: json.hpp:1341
friend bool operator!=(const_reference lhs, const_reference rhs) noexcept
comparison: not equal
Definition: json.hpp:5265
basic_json(const string_t &val)
create a string (explicit)
Definition: json.hpp:1139
void push_back(const basic_json &val)
add an object to an array
Definition: json.hpp:4649
void erase(const size_type idx)
remove element from a JSON array given an index
Definition: json.hpp:3903
basic_json<> json
default JSON class
Definition: json.hpp:8597
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:2146
reference front()
access the first element
Definition: json.hpp:3570
void swap(object_t &other)
exchanges the values
Definition: json.hpp:5021
json_reverse_iterator operator-(difference_type i) const
subtract from iterator
Definition: json.hpp:6957
const_iterator & operator+=(difference_type i)
add to iterator
Definition: json.hpp:6607
a class to store JSON values
Definition: json.hpp:168
basic_json(const number_float_t val)
create a floating-point number (explicit)
Definition: json.hpp:1401
pointer operator->()
dereference the iterator
Definition: json.hpp:6795
reference value() const
return the value of an iterator
Definition: json.hpp:6984
friend bool operator==(std::nullptr_t, const_reference v) noexcept
comparison: equal
Definition: json.hpp:5244
const_reverse_iterator crbegin() const
returns a const reverse iterator to the last element
Definition: json.hpp:4243
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:4807
const_reference at(const typename object_t::key_type &key) const
access specified object element with bounds checking
Definition: json.hpp:3107
const_iterator operator+(difference_type i)
add to iterator
Definition: json.hpp:6641
const_reverse_iterator rbegin() const
returns a const reverse iterator to the last element
Definition: json.hpp:4177
a mutable random access iterator for the basic_json class
Definition: json.hpp:6756
static basic_json parse(std::istream &&i, parser_callback_t cb=nullptr)
deserialize from stream
Definition: json.hpp:5602
const_iterator operator++(int)
post-increment (it++)
Definition: json.hpp:6449
bool is_string() const noexcept
return whether value is a string
Definition: json.hpp:2344
ObjectType< StringType, basic_json, std::less< StringType >, AllocatorType< std::pair< const StringType, basic_json >>> object_t
a type for an object
Definition: json.hpp:328
STL namespace.
NumberUnsignedType number_unsigned_t
a type for a number (unsigned)
Definition: json.hpp:590
typename std::allocator_traits< allocator_type >::const_pointer const_pointer
the type of an element const pointer
Definition: json.hpp:209
static basic_json array(std::initializer_list< basic_json > init=std::initializer_list< basic_json >())
explicitly create an array from an initializer list
Definition: json.hpp:1612
static iteration_proxy< const_iterator > iterator_wrapper(const_reference cont)
wrapper to access iterator member functions in range-based for
Definition: json.hpp:4301
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:1967
typename basic_json::value_type value_type
the type of the values when the iterator is dereferenced
Definition: json.hpp:6221
PointerType get_ptr() noexcept
get a pointer value (implicit)
Definition: json.hpp:2821
reference back()
access the last element
Definition: json.hpp:3608
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:6225
bool is_number_unsigned() const noexcept
return whether value is an unsigned integer number
Definition: json.hpp:2262
void push_back(const typename object_t::value_type &val)
add an object to an object
Definition: json.hpp:4699
iterator end()
returns an iterator to one past the last element
Definition: json.hpp:4099
static basic_json parse(const string_t &s, parser_callback_t cb=nullptr)
deserialize from string
Definition: json.hpp:5565
const_reference operator[](T *(&key)[n]) const
read-only access specified object element
Definition: json.hpp:3366
iterator insert(const_iterator pos, const_iterator first, const_iterator last)
inserts elements
Definition: json.hpp:4860
basic_json(std::nullptr_t) noexcept
create a null object (explicitly)
Definition: json.hpp:991
basic_json(InputIT first, InputIT last)
construct a JSON container given an iterator range
Definition: json.hpp:1722
reference operator[](difference_type n) const
access to successor
Definition: json.hpp:6867
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:3288
const_reference operator[](T *key) const
read-only access specified object element
Definition: json.hpp:3448
json_reverse_iterator operator+(difference_type i) const
add to iterator
Definition: json.hpp:6949
bool empty() const noexcept
checks whether the container is empty
Definition: json.hpp:4349
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:6977
basic_json(const CompatibleArrayType &val)
create an array (implicit)
Definition: json.hpp:1110
const_reference at(size_type idx) const
access specified array element with bounds checking
Definition: json.hpp:3011
basic_json(size_type cnt, const basic_json &val)
construct an array with count copies of given value
Definition: json.hpp:1676
std::reverse_iterator< Base > base_iterator
shortcut to the reverse iterator adaptor
Definition: json.hpp:6901
iterator insert(const_iterator pos, std::initializer_list< basic_json > ilist)
inserts elements
Definition: json.hpp:4918
const_iterator(const iterator &other)
copy constructor given a nonconst iterator
Definition: json.hpp:6262
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:4751
friend bool operator>=(const_reference lhs, const_reference rhs) noexcept
comparison: greater than or equal
Definition: json.hpp:5471
friend bool operator<(const_reference lhs, const_reference rhs) noexcept
comparison: less than
Definition: json.hpp:5326
iterator & operator++()
pre-increment (++it)
Definition: json.hpp:6809
bool operator<(const const_iterator &other) const
comparison: smaller
Definition: json.hpp:6559
iterator operator++(int)
post-increment (it++)
Definition: json.hpp:6801
basic_json(basic_json &&other) noexcept
move constructor
Definition: json.hpp:1935
const_iterator operator--(int)
post-decrement (it–)
Definition: json.hpp:6486
bool is_discarded() const noexcept
return whether value is discarded
Definition: json.hpp:2368
reference at(const typename object_t::key_type &key)
access specified object element with bounds checking
Definition: json.hpp:3059
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:6777
object (unordered set of name/value pairs)
size_type max_size() const noexcept
returns the maximum possible number of elements
Definition: json.hpp:4478
~basic_json()
destructor
Definition: json.hpp:1995
iterator operator--(int)
post-decrement (it–)
Definition: json.hpp:6816
iterator operator-(difference_type i)
subtract from iterator
Definition: json.hpp:6853
const_iterator & operator--()
pre-decrement (–it)
Definition: json.hpp:6494
const_iterator cend() const
returns a const iterator to one past the last element
Definition: json.hpp:4139
string_t dump(const int indent=-1) const
serialization
Definition: json.hpp:2064
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:4673
iterator begin()
returns an iterator to the first element
Definition: json.hpp:4028
difference_type operator-(const const_iterator &other) const
return difference
Definition: json.hpp:6657
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:4038
friend std::ostream & operator>>(const basic_json &j, std::ostream &o)
serialize to stream
Definition: json.hpp:5526
difference_type operator-(const iterator &other) const
return difference
Definition: json.hpp:6861
basic_json(const int val)
create an integer number from an enum type (explicit)
Definition: json.hpp:1276
iterator(const iterator &other) noexcept
copy constructor
Definition: json.hpp:6772
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:6223
void swap(string_t &other)
exchanges the values
Definition: json.hpp:5055
json_reverse_iterator(const base_iterator &it)
create reverse iterator from base class
Definition: json.hpp:6911
basic_json(const number_integer_t val)
create an integer number (explicit)
Definition: json.hpp:1247
reverse_iterator rend()
returns an iterator to the reverse-end
Definition: json.hpp:4206
basic_json(const CompatibleNumberIntegerType val) noexcept
create an integer number (implicit)
Definition: json.hpp:1313
const_reference front() const
access the first element
Definition: json.hpp:3578
bool operator>(const const_iterator &other) const
comparison: greater than
Definition: json.hpp:6595
bool is_object() const noexcept
return whether value is an object
Definition: json.hpp:2306
pointer operator->() const
dereference the iterator
Definition: json.hpp:6414
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:4956
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:4214
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:2122
ValueType get() const
get a value (explicit)
Definition: json.hpp:2737
void swap(array_t &other)
exchanges the values
Definition: json.hpp:4987
InteratorType erase(InteratorType first, InteratorType last)
remove elements given an iterator range
Definition: json.hpp:3781
ValueType value(const typename object_t::key_type &key, ValueType default_value) const
access specified object element with default value
Definition: json.hpp:3515
typename Base::reference reference
the reference type for the pointed-to element
Definition: json.hpp:6903
const_reference back() const
access the last element
Definition: json.hpp:3618
void push_back(basic_json &&val)
add an object to an array
Definition: json.hpp:4613
array (ordered collection of values)
json_reverse_iterator & operator++()
pre-increment (++it)
Definition: json.hpp:6922
static basic_json parse(std::istream &i, parser_callback_t cb=nullptr)
deserialize from stream
Definition: json.hpp:5594
friend bool operator==(const_reference lhs, const_reference rhs) noexcept
comparison: equal
Definition: json.hpp:5136
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:3541
ReferenceType get_ref() const
get a reference value (implicit)
Definition: json.hpp:2887
basic_json(const CompatibleNumberUnsignedType val) noexcept
create an unsigned number (implicit)
Definition: json.hpp:1372
const_iterator(pointer object)
constructor for a given JSON instance
Definition: json.hpp:6235
reference operator*() const
return a reference to the value pointed to by the iterator
Definition: json.hpp:6374
friend bool operator<(const value_t lhs, const value_t rhs)
comparison operator for JSON types
Definition: json.hpp:5089
const PointerType get_ptr() const noexcept
get a pointer value (implicit)
Definition: json.hpp:2836
friend bool operator!=(const_reference v, std::nullptr_t) noexcept
comparison: not equal
Definition: json.hpp:5288
iterator operator+(difference_type i)
add to iterator
Definition: json.hpp:6845
basic_json(const CompatibleNumberFloatType val) noexcept
create an floating-point number (implicit)
Definition: json.hpp:1447
bool operator<=(const const_iterator &other) const
comparison: less than or equal
Definition: json.hpp:6589
InteratorType erase(InteratorType pos)
remove element given an iterator
Definition: json.hpp:3675
basic_json(std::initializer_list< basic_json > init, bool type_deduction=true, value_t manual_type=value_t::array)
create a container (array or object) from an initializer list
Definition: json.hpp:1520
iterator(pointer object) noexcept
constructor for a given JSON instance
Definition: json.hpp:6767
friend bool operator!=(std::nullptr_t, const_reference v) noexcept
comparison: not equal
Definition: json.hpp:5297
json_reverse_iterator(const typename base_iterator::iterator_type &it)
create reverse iterator from iterator
Definition: json.hpp:6906
const_iterator & operator++()
pre-increment (++it)
Definition: json.hpp:6457
bool is_number_float() const noexcept
return whether value is a floating-point number
Definition: json.hpp:2287
reference value() const
return the value of an iterator
Definition: json.hpp:6732
std::bidirectional_iterator_tag iterator_category
the category of the iterator
Definition: json.hpp:6229
difference_type operator-(const json_reverse_iterator &other) const
return difference
Definition: json.hpp:6965
const_iterator find(typename object_t::key_type key) const
find an element in a JSON object
Definition: json.hpp:3956
basic_json(const CompatibleObjectType &val)
create an object (implicit)
Definition: json.hpp:1046
friend bool operator>(const_reference lhs, const_reference rhs) noexcept
comparison: greater than
Definition: json.hpp:5449
bool operator>=(const const_iterator &other) const
comparison: greater than or equal
Definition: json.hpp:6601
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:6294
size_type erase(const typename object_t::key_type &key)
remove element from a JSON object given a key
Definition: json.hpp:3865
reference operator[](const typename object_t::key_type &key)
access specified object element
Definition: json.hpp:3240
object_t::key_type key() const
return the key of an object iterator
Definition: json.hpp:6717
const_iterator end() const
returns a const iterator to one past the last element
Definition: json.hpp:4109
reference operator+=(basic_json &&val)
add an object to an array
Definition: json.hpp:4639
reference operator[](difference_type n) const
access to successor
Definition: json.hpp:6681
a const random access iterator for the basic_json class
Definition: json.hpp:6214
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:1829
typename basic_json::const_reference reference
defines a reference to the type iterated over (value_type)
Definition: json.hpp:6227
json_reverse_iterator operator++(int)
post-increment (it++)
Definition: json.hpp:6916
friend bool operator==(const_reference v, std::nullptr_t) noexcept
comparison: equal
Definition: json.hpp:5235
reference operator[](size_type idx)
access specified array element
Definition: json.hpp:3154
bool operator!=(const const_iterator &other) const
comparison: not equal
Definition: json.hpp:6553
json_reverse_iterator & operator+=(difference_type i)
add to iterator
Definition: json.hpp:6942
reference at(size_type idx)
access specified array element with bounds checking
Definition: json.hpp:2967
size_type size() const noexcept
returns the number of elements
Definition: json.hpp:4412
static iteration_proxy< iterator > iterator_wrapper(reference cont)
wrapper to access iterator member functions in range-based for
Definition: json.hpp:4293
const_iterator cbegin() const
returns a const iterator to the first element
Definition: json.hpp:4068
iterator & operator-=(difference_type i)
subtract from iterator
Definition: json.hpp:6838
const_reverse_iterator crend() const
returns a const reverse iterator to one before the first
Definition: json.hpp:4272
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:5630
std::size_t operator()(const nlohmann::json &j) const
return a hash value for a JSON object
Definition: json.hpp:8632
friend std::ostream & operator<<(std::ostream &o, const basic_json &j)
serialize to stream
Definition: json.hpp:5508
const_iterator(const const_iterator &other) noexcept
copy constructor
Definition: json.hpp:6289
iterator & operator--()
pre-decrement (–it)
Definition: json.hpp:6824
iterator insert(const_iterator pos, basic_json &&val)
inserts element
Definition: json.hpp:4778
ReferenceType get_ref()
get a reference value (implicit)
Definition: json.hpp:2872
const_iterator & operator-=(difference_type i)
subtract from iterator
Definition: json.hpp:6635
basic_json(const CompatibleStringType &val)
create a string (implicit)
Definition: json.hpp:1194
basic_json(const basic_json &other)
copy constructor
Definition: json.hpp:1860
reference operator[](T *key)
access specified object element
Definition: json.hpp:3399
parse_event_t
JSON callback events.
Definition: json.hpp:831