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 // disable float-equal warnings on GCC/clang
38 #if defined(__clang__) || defined(__GNUC__) || defined(__GNUG__)
39  #pragma GCC diagnostic push
40  #pragma GCC diagnostic ignored "-Wfloat-equal"
41 #endif
42 
48 namespace nlohmann
49 {
50 
51 
56 namespace
57 {
62 template<typename T>
63 struct has_mapped_type
64 {
65  private:
66  template<typename C> static char test(typename C::mapped_type*);
67  template<typename C> static char (&test(...))[2];
68  public:
69  static constexpr bool value = sizeof(test<T>(0)) == 1;
70 };
71 
72 }
73 
145 template <
146  template<typename U, typename V, typename... Args> class ObjectType = std::map,
147  template<typename U, typename... Args> class ArrayType = std::vector,
148  class StringType = std::string,
149  class BooleanType = bool,
150  class NumberIntegerType = int64_t,
151  class NumberUnsignedType = uint64_t,
152  class NumberFloatType = double,
153  template<typename U> class AllocatorType = std::allocator
154  >
156 {
157  private:
159  using basic_json_t = basic_json<ObjectType,
160  ArrayType,
161  StringType,
162  BooleanType,
163  NumberIntegerType,
164  NumberUnsignedType,
165  NumberFloatType,
166  AllocatorType>;
167 
168  public:
169 
171  // container types //
173 
176 
179 
183  using const_reference = const value_type&;
184 
186  using difference_type = std::ptrdiff_t;
188  using size_type = std::size_t;
189 
191  using allocator_type = AllocatorType<basic_json>;
192 
194  using pointer = typename std::allocator_traits<allocator_type>::pointer;
196  using const_pointer = typename std::allocator_traits<allocator_type>::const_pointer;
197 
198  // forward declaration
199  template<typename Base> class json_reverse_iterator;
200 
202  class iterator;
204  class const_iterator;
209 
211 
212 
217  {
218  return allocator_type();
219  }
220 
221 
223  // JSON value data types //
225 
228 
311  using object_t = ObjectType<StringType,
312  basic_json,
313  std::less<StringType>,
314  AllocatorType<std::pair<const StringType,
315  basic_json>>>;
316 
361  using array_t = ArrayType<basic_json, AllocatorType<basic_json>>;
362 
408  using string_t = StringType;
409 
434  using boolean_t = BooleanType;
435 
505  using number_integer_t = NumberIntegerType;
506 
577  using number_unsigned_t = NumberUnsignedType;
578 
645  using number_float_t = NumberFloatType;
646 
648 
649 
651  // JSON type enumeration //
653 
664  enum class value_t : uint8_t
665  {
666  null,
667  object,
668  array,
669  string,
670  boolean,
671  number_integer,
672  number_unsigned,
673  number_float,
674  discarded
675  };
676 
677 
678  private:
680  template<typename T, typename... Args>
681  static T* create(Args&& ... args)
682  {
683  AllocatorType<T> alloc;
684  auto deleter = [&](T * object)
685  {
686  alloc.deallocate(object, 1);
687  };
688  std::unique_ptr<T, decltype(deleter)> object(alloc.allocate(1), deleter);
689  alloc.construct(object.get(), std::forward<Args>(args)...);
690  return object.release();
691  }
692 
694  // JSON value storage //
696 
704  union json_value
705  {
707  object_t* object;
709  array_t* array;
711  string_t* string;
713  boolean_t boolean;
715  number_integer_t number_integer;
717  number_unsigned_t number_unsigned;
719  number_float_t number_float;
720 
722  json_value() = default;
724  json_value(boolean_t v) noexcept : boolean(v) {}
726  json_value(number_integer_t v) noexcept : number_integer(v) {}
728  json_value(number_unsigned_t v) noexcept : number_unsigned(v) {}
730  json_value(number_float_t v) noexcept : number_float(v) {}
732  json_value(value_t t)
733  {
734  switch (t)
735  {
736  case value_t::object:
737  {
738  object = create<object_t>();
739  break;
740  }
741 
742  case value_t::array:
743  {
744  array = create<array_t>();
745  break;
746  }
747 
748  case value_t::string:
749  {
750  string = create<string_t>("");
751  break;
752  }
753 
754  case value_t::boolean:
755  {
756  boolean = boolean_t(false);
757  break;
758  }
759 
760  case value_t::number_integer:
761  {
762  number_integer = number_integer_t(0);
763  break;
764  }
765 
766  case value_t::number_unsigned:
767  {
768  number_unsigned = number_unsigned_t(0);
769  break;
770  }
771 
772  case value_t::number_float:
773  {
774  number_float = number_float_t(0.0);
775  break;
776  }
777 
778  default:
779  {
780  break;
781  }
782  }
783  }
784 
786  json_value(const string_t& value)
787  {
788  string = create<string_t>(value);
789  }
790 
792  json_value(const object_t& value)
793  {
794  object = create<object_t>(value);
795  }
796 
798  json_value(const array_t& value)
799  {
800  array = create<array_t>(value);
801  }
802  };
803 
804 
805  public:
807  // JSON parser callback //
809 
818  enum class parse_event_t : uint8_t
819  {
821  object_start,
823  object_end,
825  array_start,
827  array_end,
829  key,
831  value
832  };
833 
883  using parser_callback_t = std::function<bool(int depth, parse_event_t event, basic_json& parsed)>;
884 
885 
887  // constructors //
889 
892 
933  : m_type(value_type), m_value(value_type)
934  {}
935 
960  basic_json() = default;
961 
984  basic_json(std::nullptr_t) noexcept
985  : basic_json(value_t::null)
986  {}
987 
1007  basic_json(const object_t& val)
1008  : m_type(value_t::object), m_value(val)
1009  {}
1010 
1037  template <class CompatibleObjectType, typename
1038  std::enable_if<
1039  std::is_constructible<typename object_t::key_type, typename CompatibleObjectType::key_type>::value and
1040  std::is_constructible<basic_json, typename CompatibleObjectType::mapped_type>::value, int>::type
1041  = 0>
1042  basic_json(const CompatibleObjectType& val)
1043  : m_type(value_t::object)
1044  {
1045  using std::begin;
1046  using std::end;
1047  m_value.object = create<object_t>(begin(val), end(val));
1048  }
1049 
1069  basic_json(const array_t& val)
1070  : m_type(value_t::array), m_value(val)
1071  {}
1072 
1099  template <class CompatibleArrayType, typename
1100  std::enable_if<
1101  not std::is_same<CompatibleArrayType, typename basic_json_t::iterator>::value and
1102  not std::is_same<CompatibleArrayType, typename basic_json_t::const_iterator>::value and
1103  not std::is_same<CompatibleArrayType, typename basic_json_t::reverse_iterator>::value and
1104  not std::is_same<CompatibleArrayType, typename basic_json_t::const_reverse_iterator>::value and
1105  not std::is_same<CompatibleArrayType, typename array_t::iterator>::value and
1106  not std::is_same<CompatibleArrayType, typename array_t::const_iterator>::value and
1107  std::is_constructible<basic_json, typename CompatibleArrayType::value_type>::value, int>::type
1108  = 0>
1109  basic_json(const CompatibleArrayType& val)
1110  : m_type(value_t::array)
1111  {
1112  using std::begin;
1113  using std::end;
1114  m_value.array = create<array_t>(begin(val), end(val));
1115  }
1116 
1138  basic_json(const string_t& val)
1139  : m_type(value_t::string), m_value(val)
1140  {}
1141 
1162  basic_json(const typename string_t::value_type* val)
1163  : basic_json(string_t(val))
1164  {}
1165 
1189  template <class CompatibleStringType, typename
1190  std::enable_if<
1191  std::is_constructible<string_t, CompatibleStringType>::value, int>::type
1192  = 0>
1193  basic_json(const CompatibleStringType& val)
1194  : basic_json(string_t(val))
1195  {}
1196 
1211  basic_json(boolean_t val) noexcept
1212  : m_type(value_t::boolean), m_value(val)
1213  {}
1214 
1238  template<typename T,
1239  typename std::enable_if<
1240  not (std::is_same<T, int>::value)
1241  and std::is_same<T, number_integer_t>::value
1242  , int>::type
1243  = 0>
1244  basic_json(const number_integer_t val) noexcept
1245  : m_type(value_t::number_integer), m_value(val)
1246  {}
1247 
1273  basic_json(const int val) noexcept
1274  : m_type(value_t::number_integer),
1275  m_value(static_cast<number_integer_t>(val))
1276  {}
1277 
1303  template<typename CompatibleNumberIntegerType, typename
1304  std::enable_if<
1305  std::is_constructible<number_integer_t, CompatibleNumberIntegerType>::value and
1306  std::numeric_limits<CompatibleNumberIntegerType>::is_integer and
1307  std::numeric_limits<CompatibleNumberIntegerType>::is_signed,
1308  CompatibleNumberIntegerType>::type
1309  = 0>
1310  basic_json(const CompatibleNumberIntegerType val) noexcept
1311  : m_type(value_t::number_integer),
1312  m_value(static_cast<number_integer_t>(val))
1313  {}
1314 
1332  template<typename T,
1333  typename std::enable_if<
1334  not (std::is_same<T, int>::value)
1335  and std::is_same<T, number_unsigned_t>::value
1336  , int>::type
1337  = 0>
1338  basic_json(const number_unsigned_t val) noexcept
1339  : m_type(value_t::number_unsigned), m_value(val)
1340  {}
1341 
1362  template < typename CompatibleNumberUnsignedType, typename
1363  std::enable_if <
1364  std::is_constructible<number_unsigned_t, CompatibleNumberUnsignedType>::value and
1365  std::numeric_limits<CompatibleNumberUnsignedType>::is_integer and
1366  !std::numeric_limits<CompatibleNumberUnsignedType>::is_signed,
1367  CompatibleNumberUnsignedType >::type
1368  = 0 >
1369  basic_json(const CompatibleNumberUnsignedType val) noexcept
1370  : m_type(value_t::number_unsigned),
1371  m_value(static_cast<number_unsigned_t>(val))
1372  {}
1373 
1398  basic_json(const number_float_t val) noexcept
1399  : m_type(value_t::number_float), m_value(val)
1400  {
1401  // replace infinity and NAN by null
1402  if (not std::isfinite(val))
1403  {
1404  m_type = value_t::null;
1405  m_value = json_value();
1406  }
1407  }
1408 
1439  template<typename CompatibleNumberFloatType, typename = typename
1440  std::enable_if<
1441  std::is_constructible<number_float_t, CompatibleNumberFloatType>::value and
1442  std::is_floating_point<CompatibleNumberFloatType>::value>::type
1443  >
1444  basic_json(const CompatibleNumberFloatType val) noexcept
1445  : basic_json(number_float_t(val))
1446  {}
1447 
1517  basic_json(std::initializer_list<basic_json> init,
1518  bool type_deduction = true,
1519  value_t manual_type = value_t::array)
1520  {
1521  // the initializer list could describe an object
1522  bool is_an_object = true;
1523 
1524  // check if each element is an array with two elements whose first
1525  // element is a string
1526  for (const auto& element : init)
1527  {
1528  if (not element.is_array() or element.size() != 2
1529  or not element[0].is_string())
1530  {
1531  // we found an element that makes it impossible to use the
1532  // initializer list as object
1533  is_an_object = false;
1534  break;
1535  }
1536  }
1537 
1538  // adjust type if type deduction is not wanted
1539  if (not type_deduction)
1540  {
1541  // if array is wanted, do not create an object though possible
1542  if (manual_type == value_t::array)
1543  {
1544  is_an_object = false;
1545  }
1546 
1547  // if object is wanted but impossible, throw an exception
1548  if (manual_type == value_t::object and not is_an_object)
1549  {
1550  throw std::domain_error("cannot create object from initializer list");
1551  }
1552  }
1553 
1554  if (is_an_object)
1555  {
1556  // the initializer list is a list of pairs -> create object
1557  m_type = value_t::object;
1558  m_value = value_t::object;
1559 
1560  assert(m_value.object != nullptr);
1561 
1562  for (auto& element : init)
1563  {
1564  m_value.object->emplace(std::move(*(element[0].m_value.string)), std::move(element[1]));
1565  }
1566  }
1567  else
1568  {
1569  // the initializer list describes an array -> create array
1570  m_type = value_t::array;
1571  m_value.array = create<array_t>(std::move(init));
1572  }
1573  }
1574 
1609  static basic_json array(std::initializer_list<basic_json> init =
1610  std::initializer_list<basic_json>())
1611  {
1612  return basic_json(init, false, value_t::array);
1613  }
1614 
1649  static basic_json object(std::initializer_list<basic_json> init =
1650  std::initializer_list<basic_json>())
1651  {
1652  return basic_json(init, false, value_t::object);
1653  }
1654 
1673  basic_json(size_type cnt, const basic_json& val)
1674  : m_type(value_t::array)
1675  {
1676  m_value.array = create<array_t>(cnt, val);
1677  }
1678 
1713  template <class InputIT, typename
1714  std::enable_if<
1715  std::is_same<InputIT, typename basic_json_t::iterator>::value or
1716  std::is_same<InputIT, typename basic_json_t::const_iterator>::value
1717  , int>::type
1718  = 0>
1719  basic_json(InputIT first, InputIT last) : m_type(first.m_object->m_type)
1720  {
1721  // make sure iterator fits the current value
1722  if (first.m_object != last.m_object)
1723  {
1724  throw std::domain_error("iterators are not compatible");
1725  }
1726 
1727  // check if iterator range is complete for primitive values
1728  switch (m_type)
1729  {
1730  case value_t::boolean:
1731  case value_t::number_float:
1732  case value_t::number_integer:
1733  case value_t::number_unsigned:
1734  case value_t::string:
1735  {
1736  if (not first.m_it.primitive_iterator.is_begin() or not last.m_it.primitive_iterator.is_end())
1737  {
1738  throw std::out_of_range("iterators out of range");
1739  }
1740  break;
1741  }
1742 
1743  default:
1744  {
1745  break;
1746  }
1747  }
1748 
1749  switch (m_type)
1750  {
1751  case value_t::number_integer:
1752  {
1753  assert(first.m_object != nullptr);
1754  m_value.number_integer = first.m_object->m_value.number_integer;
1755  break;
1756  }
1757 
1758  case value_t::number_unsigned:
1759  {
1760  assert(first.m_object != nullptr);
1761  m_value.number_unsigned = first.m_object->m_value.number_unsigned;
1762  break;
1763  }
1764 
1765  case value_t::number_float:
1766  {
1767  assert(first.m_object != nullptr);
1768  m_value.number_float = first.m_object->m_value.number_float;
1769  break;
1770  }
1771 
1772  case value_t::boolean:
1773  {
1774  assert(first.m_object != nullptr);
1775  m_value.boolean = first.m_object->m_value.boolean;
1776  break;
1777  }
1778 
1779  case value_t::string:
1780  {
1781  assert(first.m_object != nullptr);
1782  m_value = *first.m_object->m_value.string;
1783  break;
1784  }
1785 
1786  case value_t::object:
1787  {
1788  m_value.object = create<object_t>(first.m_it.object_iterator, last.m_it.object_iterator);
1789  break;
1790  }
1791 
1792  case value_t::array:
1793  {
1794  m_value.array = create<array_t>(first.m_it.array_iterator, last.m_it.array_iterator);
1795  break;
1796  }
1797 
1798  default:
1799  {
1800  assert(first.m_object != nullptr);
1801  throw std::domain_error("cannot use construct with iterators from " + first.m_object->type_name());
1802  }
1803  }
1804  }
1805 
1826  explicit basic_json(std::istream& i, parser_callback_t cb = nullptr)
1827  {
1828  *this = parser(i, cb).parse();
1829  }
1830 
1832  // other constructors and destructor //
1834 
1857  basic_json(const basic_json& other)
1858  : m_type(other.m_type)
1859  {
1860  switch (m_type)
1861  {
1862  case value_t::object:
1863  {
1864  assert(other.m_value.object != nullptr);
1865  m_value = *other.m_value.object;
1866  break;
1867  }
1868 
1869  case value_t::array:
1870  {
1871  assert(other.m_value.array != nullptr);
1872  m_value = *other.m_value.array;
1873  break;
1874  }
1875 
1876  case value_t::string:
1877  {
1878  assert(other.m_value.string != nullptr);
1879  m_value = *other.m_value.string;
1880  break;
1881  }
1882 
1883  case value_t::boolean:
1884  {
1885  m_value = other.m_value.boolean;
1886  break;
1887  }
1888 
1889  case value_t::number_integer:
1890  {
1891  m_value = other.m_value.number_integer;
1892  break;
1893  }
1894 
1895  case value_t::number_unsigned:
1896  {
1897  m_value = other.m_value.number_unsigned;
1898  break;
1899  }
1900 
1901  case value_t::number_float:
1902  {
1903  m_value = other.m_value.number_float;
1904  break;
1905  }
1906 
1907  default:
1908  {
1909  break;
1910  }
1911  }
1912  }
1913 
1932  basic_json(basic_json&& other) noexcept
1933  : m_type(std::move(other.m_type)),
1934  m_value(std::move(other.m_value))
1935  {
1936  // invalidate payload
1937  other.m_type = value_t::null;
1938  other.m_value = {};
1939  }
1940 
1964  reference& operator=(basic_json other) noexcept (
1965  std::is_nothrow_move_constructible<value_t>::value and
1966  std::is_nothrow_move_assignable<value_t>::value and
1967  std::is_nothrow_move_constructible<json_value>::value and
1968  std::is_nothrow_move_assignable<json_value>::value
1969  )
1970  {
1971  using std::swap;
1972  swap(m_type, other.m_type);
1973  swap(m_value, other.m_value);
1974  return *this;
1975  }
1976 
1993  {
1994  switch (m_type)
1995  {
1996  case value_t::object:
1997  {
1998  AllocatorType<object_t> alloc;
1999  alloc.destroy(m_value.object);
2000  alloc.deallocate(m_value.object, 1);
2001  break;
2002  }
2003 
2004  case value_t::array:
2005  {
2006  AllocatorType<array_t> alloc;
2007  alloc.destroy(m_value.array);
2008  alloc.deallocate(m_value.array, 1);
2009  break;
2010  }
2011 
2012  case value_t::string:
2013  {
2014  AllocatorType<string_t> alloc;
2015  alloc.destroy(m_value.string);
2016  alloc.deallocate(m_value.string, 1);
2017  break;
2018  }
2019 
2020  default:
2021  {
2022  // all other types need no specific destructor
2023  break;
2024  }
2025  }
2026  }
2027 
2029 
2030  public:
2032  // object inspection //
2034 
2037 
2061  string_t dump(const int indent = -1) const
2062  {
2063  std::stringstream ss;
2064 
2065  if (indent >= 0)
2066  {
2067  dump(ss, true, static_cast<unsigned int>(indent));
2068  }
2069  else
2070  {
2071  dump(ss, false, 0);
2072  }
2073 
2074  return ss.str();
2075  }
2076 
2095  constexpr value_t type() const noexcept
2096  {
2097  return m_type;
2098  }
2099 
2125  constexpr bool is_primitive() const noexcept
2126  {
2127  return is_null() or is_string() or is_boolean() or is_number();
2128  }
2129 
2152  constexpr bool is_structured() const noexcept
2153  {
2154  return is_array() or is_object();
2155  }
2156 
2174  constexpr bool is_null() const noexcept
2175  {
2176  return m_type == value_t::null;
2177  }
2178 
2196  constexpr bool is_boolean() const noexcept
2197  {
2198  return m_type == value_t::boolean;
2199  }
2200 
2226  constexpr bool is_number() const noexcept
2227  {
2228  return is_number_integer() or is_number_float();
2229  }
2230 
2255  constexpr bool is_number_integer() const noexcept
2256  {
2257  return m_type == value_t::number_integer or m_type == value_t::number_unsigned;
2258  }
2259 
2283  constexpr bool is_number_unsigned() const noexcept
2284  {
2285  return m_type == value_t::number_unsigned;
2286  }
2287 
2311  constexpr bool is_number_float() const noexcept
2312  {
2313  return m_type == value_t::number_float;
2314  }
2315 
2333  constexpr bool is_object() const noexcept
2334  {
2335  return m_type == value_t::object;
2336  }
2337 
2355  constexpr bool is_array() const noexcept
2356  {
2357  return m_type == value_t::array;
2358  }
2359 
2377  constexpr bool is_string() const noexcept
2378  {
2379  return m_type == value_t::string;
2380  }
2381 
2404  constexpr bool is_discarded() const noexcept
2405  {
2406  return m_type == value_t::discarded;
2407  }
2408 
2427  constexpr operator value_t() const noexcept
2428  {
2429  return m_type;
2430  }
2431 
2433 
2434  private:
2436  // value access //
2438 
2440  template <class T, typename
2441  std::enable_if<
2442  std::is_convertible<typename object_t::key_type, typename T::key_type>::value and
2443  std::is_convertible<basic_json_t, typename T::mapped_type>::value
2444  , int>::type = 0>
2445  T get_impl(T*) const
2446  {
2447  if (is_object())
2448  {
2449  assert(m_value.object != nullptr);
2450  return T(m_value.object->begin(), m_value.object->end());
2451  }
2452  else
2453  {
2454  throw std::domain_error("type must be object, but is " + type_name());
2455  }
2456  }
2457 
2459  object_t get_impl(object_t*) const
2460  {
2461  if (is_object())
2462  {
2463  assert(m_value.object != nullptr);
2464  return *(m_value.object);
2465  }
2466  else
2467  {
2468  throw std::domain_error("type must be object, but is " + type_name());
2469  }
2470  }
2471 
2473  template <class T, typename
2474  std::enable_if<
2475  std::is_convertible<basic_json_t, typename T::value_type>::value and
2476  not std::is_same<basic_json_t, typename T::value_type>::value and
2477  not std::is_arithmetic<T>::value and
2478  not std::is_convertible<std::string, T>::value and
2479  not has_mapped_type<T>::value
2480  , int>::type = 0>
2481  T get_impl(T*) const
2482  {
2483  if (is_array())
2484  {
2485  T to_vector;
2486  assert(m_value.array != nullptr);
2487  std::transform(m_value.array->begin(), m_value.array->end(),
2488  std::inserter(to_vector, to_vector.end()), [](basic_json i)
2489  {
2490  return i.get<typename T::value_type>();
2491  });
2492  return to_vector;
2493  }
2494  else
2495  {
2496  throw std::domain_error("type must be array, but is " + type_name());
2497  }
2498  }
2499 
2501  template <class T, typename
2502  std::enable_if<
2503  std::is_convertible<basic_json_t, T>::value and
2504  not std::is_same<basic_json_t, T>::value
2505  , int>::type = 0>
2506  std::vector<T> get_impl(std::vector<T>*) const
2507  {
2508  if (is_array())
2509  {
2510  std::vector<T> to_vector;
2511  assert(m_value.array != nullptr);
2512  to_vector.reserve(m_value.array->size());
2513  std::transform(m_value.array->begin(), m_value.array->end(),
2514  std::inserter(to_vector, to_vector.end()), [](basic_json i)
2515  {
2516  return i.get<T>();
2517  });
2518  return to_vector;
2519  }
2520  else
2521  {
2522  throw std::domain_error("type must be array, but is " + type_name());
2523  }
2524  }
2525 
2527  template <class T, typename
2528  std::enable_if<
2529  std::is_same<basic_json, typename T::value_type>::value and
2530  not has_mapped_type<T>::value
2531  , int>::type = 0>
2532  T get_impl(T*) const
2533  {
2534  if (is_array())
2535  {
2536  assert(m_value.array != nullptr);
2537  return T(m_value.array->begin(), m_value.array->end());
2538  }
2539  else
2540  {
2541  throw std::domain_error("type must be array, but is " + type_name());
2542  }
2543  }
2544 
2546  array_t get_impl(array_t*) const
2547  {
2548  if (is_array())
2549  {
2550  assert(m_value.array != nullptr);
2551  return *(m_value.array);
2552  }
2553  else
2554  {
2555  throw std::domain_error("type must be array, but is " + type_name());
2556  }
2557  }
2558 
2560  template <typename T, typename
2561  std::enable_if<
2562  std::is_convertible<string_t, T>::value
2563  , int>::type = 0>
2564  T get_impl(T*) const
2565  {
2566  if (is_string())
2567  {
2568  assert(m_value.string != nullptr);
2569  return *m_value.string;
2570  }
2571  else
2572  {
2573  throw std::domain_error("type must be string, but is " + type_name());
2574  }
2575  }
2576 
2578  template<typename T, typename
2579  std::enable_if<
2580  std::is_arithmetic<T>::value
2581  , int>::type = 0>
2582  T get_impl(T*) const
2583  {
2584  switch (m_type)
2585  {
2586  case value_t::number_integer:
2587  {
2588  return static_cast<T>(m_value.number_integer);
2589  }
2590 
2591  case value_t::number_unsigned:
2592  {
2593  return static_cast<T>(m_value.number_unsigned);
2594  }
2595 
2596  case value_t::number_float:
2597  {
2598  return static_cast<T>(m_value.number_float);
2599  }
2600 
2601  default:
2602  {
2603  throw std::domain_error("type must be number, but is " + type_name());
2604  }
2605  }
2606  }
2607 
2609  constexpr boolean_t get_impl(boolean_t*) const
2610  {
2611  return is_boolean()
2612  ? m_value.boolean
2613  : throw std::domain_error("type must be boolean, but is " + type_name());
2614  }
2615 
2617  object_t* get_impl_ptr(object_t*) noexcept
2618  {
2619  return is_object() ? m_value.object : nullptr;
2620  }
2621 
2623  constexpr const object_t* get_impl_ptr(const object_t*) const noexcept
2624  {
2625  return is_object() ? m_value.object : nullptr;
2626  }
2627 
2629  array_t* get_impl_ptr(array_t*) noexcept
2630  {
2631  return is_array() ? m_value.array : nullptr;
2632  }
2633 
2635  constexpr const array_t* get_impl_ptr(const array_t*) const noexcept
2636  {
2637  return is_array() ? m_value.array : nullptr;
2638  }
2639 
2641  string_t* get_impl_ptr(string_t*) noexcept
2642  {
2643  return is_string() ? m_value.string : nullptr;
2644  }
2645 
2647  constexpr const string_t* get_impl_ptr(const string_t*) const noexcept
2648  {
2649  return is_string() ? m_value.string : nullptr;
2650  }
2651 
2653  boolean_t* get_impl_ptr(boolean_t*) noexcept
2654  {
2655  return is_boolean() ? &m_value.boolean : nullptr;
2656  }
2657 
2659  constexpr const boolean_t* get_impl_ptr(const boolean_t*) const noexcept
2660  {
2661  return is_boolean() ? &m_value.boolean : nullptr;
2662  }
2663 
2665  number_integer_t* get_impl_ptr(number_integer_t*) noexcept
2666  {
2667  return is_number_integer() ? &m_value.number_integer : nullptr;
2668  }
2669 
2671  constexpr const number_integer_t* get_impl_ptr(const number_integer_t*) const noexcept
2672  {
2673  return is_number_integer() ? &m_value.number_integer : nullptr;
2674  }
2675 
2677  number_unsigned_t* get_impl_ptr(number_unsigned_t*) noexcept
2678  {
2679  return is_number_unsigned() ? &m_value.number_unsigned : nullptr;
2680  }
2681 
2683  constexpr const number_unsigned_t* get_impl_ptr(const number_unsigned_t*) const noexcept
2684  {
2685  return is_number_unsigned() ? &m_value.number_unsigned : nullptr;
2686  }
2687 
2689  number_float_t* get_impl_ptr(number_float_t*) noexcept
2690  {
2691  return is_number_float() ? &m_value.number_float : nullptr;
2692  }
2693 
2695  constexpr const number_float_t* get_impl_ptr(const number_float_t*) const noexcept
2696  {
2697  return is_number_float() ? &m_value.number_float : nullptr;
2698  }
2699 
2711  template<typename ReferenceType, typename ThisType>
2712  static ReferenceType get_ref_impl(ThisType& obj)
2713  {
2714  // delegate the call to get_ptr<>()
2715  using PointerType = typename std::add_pointer<ReferenceType>::type;
2716  auto ptr = obj.template get_ptr<PointerType>();
2717 
2718  if (ptr != nullptr)
2719  {
2720  return *ptr;
2721  }
2722  else
2723  {
2724  throw std::domain_error("incompatible ReferenceType for get_ref, actual type is " +
2725  obj.type_name());
2726  }
2727  }
2728 
2729  public:
2730 
2733 
2767  template<typename ValueType, typename
2768  std::enable_if<
2769  not std::is_pointer<ValueType>::value
2770  , int>::type = 0>
2771  ValueType get() const
2772  {
2773  return get_impl(static_cast<ValueType*>(nullptr));
2774  }
2775 
2802  template<typename PointerType, typename
2803  std::enable_if<
2804  std::is_pointer<PointerType>::value
2805  , int>::type = 0>
2806  PointerType get() noexcept
2807  {
2808  // delegate the call to get_ptr
2809  return get_ptr<PointerType>();
2810  }
2811 
2816  template<typename PointerType, typename
2817  std::enable_if<
2818  std::is_pointer<PointerType>::value
2819  , int>::type = 0>
2820  constexpr const PointerType get() const noexcept
2821  {
2822  // delegate the call to get_ptr
2823  return get_ptr<PointerType>();
2824  }
2825 
2851  template<typename PointerType, typename
2852  std::enable_if<
2853  std::is_pointer<PointerType>::value
2854  , int>::type = 0>
2855  PointerType get_ptr() noexcept
2856  {
2857  // delegate the call to get_impl_ptr<>()
2858  return get_impl_ptr(static_cast<PointerType>(nullptr));
2859  }
2860 
2865  template<typename PointerType, typename
2866  std::enable_if<
2867  std::is_pointer<PointerType>::value
2868  and std::is_const<typename std::remove_pointer<PointerType>::type>::value
2869  , int>::type = 0>
2870  constexpr const PointerType get_ptr() const noexcept
2871  {
2872  // delegate the call to get_impl_ptr<>() const
2873  return get_impl_ptr(static_cast<const PointerType>(nullptr));
2874  }
2875 
2902  template<typename ReferenceType, typename
2903  std::enable_if<
2904  std::is_reference<ReferenceType>::value
2905  , int>::type = 0>
2906  ReferenceType get_ref()
2907  {
2908  // delegate call to get_ref_impl
2909  return get_ref_impl<ReferenceType>(*this);
2910  }
2911 
2916  template<typename ReferenceType, typename
2917  std::enable_if<
2918  std::is_reference<ReferenceType>::value
2919  and std::is_const<typename std::remove_reference<ReferenceType>::type>::value
2920  , int>::type = 0>
2921  ReferenceType get_ref() const
2922  {
2923  // delegate call to get_ref_impl
2924  return get_ref_impl<ReferenceType>(*this);
2925  }
2926 
2955  template < typename ValueType, typename
2956  std::enable_if <
2957  not std::is_pointer<ValueType>::value
2958  and not std::is_same<ValueType, typename string_t::value_type>::value
2959 #ifndef _MSC_VER // Fix for issue #167 operator<< abiguity under VS2015
2960  and not std::is_same<ValueType, std::initializer_list<typename string_t::value_type>>::value
2961 #endif
2962  , int >::type = 0 >
2963  operator ValueType() const
2964  {
2965  // delegate the call to get<>() const
2966  return get<ValueType>();
2967  }
2968 
2970 
2971 
2973  // element access //
2975 
2978 
3002  {
3003  // at only works for arrays
3004  if (is_array())
3005  {
3006  try
3007  {
3008  assert(m_value.array != nullptr);
3009  return m_value.array->at(idx);
3010  }
3011  catch (std::out_of_range&)
3012  {
3013  // create better exception explanation
3014  throw std::out_of_range("array index " + std::to_string(idx) + " is out of range");
3015  }
3016  }
3017  else
3018  {
3019  throw std::domain_error("cannot use at() with " + type_name());
3020  }
3021  }
3022 
3046  {
3047  // at only works for arrays
3048  if (is_array())
3049  {
3050  try
3051  {
3052  assert(m_value.array != nullptr);
3053  return m_value.array->at(idx);
3054  }
3055  catch (std::out_of_range&)
3056  {
3057  // create better exception explanation
3058  throw std::out_of_range("array index " + std::to_string(idx) + " is out of range");
3059  }
3060  }
3061  else
3062  {
3063  throw std::domain_error("cannot use at() with " + type_name());
3064  }
3065  }
3066 
3093  reference at(const typename object_t::key_type& key)
3094  {
3095  // at only works for objects
3096  if (is_object())
3097  {
3098  try
3099  {
3100  assert(m_value.object != nullptr);
3101  return m_value.object->at(key);
3102  }
3103  catch (std::out_of_range&)
3104  {
3105  // create better exception explanation
3106  throw std::out_of_range("key '" + key + "' not found");
3107  }
3108  }
3109  else
3110  {
3111  throw std::domain_error("cannot use at() with " + type_name());
3112  }
3113  }
3114 
3141  const_reference at(const typename object_t::key_type& key) const
3142  {
3143  // at only works for objects
3144  if (is_object())
3145  {
3146  try
3147  {
3148  assert(m_value.object != nullptr);
3149  return m_value.object->at(key);
3150  }
3151  catch (std::out_of_range&)
3152  {
3153  // create better exception explanation
3154  throw std::out_of_range("key '" + key + "' not found");
3155  }
3156  }
3157  else
3158  {
3159  throw std::domain_error("cannot use at() with " + type_name());
3160  }
3161  }
3162 
3189  {
3190  // implicitly convert null value to an empty array
3191  if (is_null())
3192  {
3193  m_type = value_t::array;
3194  m_value.array = create<array_t>();
3195  }
3196 
3197  // operator[] only works for arrays
3198  if (is_array())
3199  {
3200  // fill up array with null values until given idx is reached
3201  assert(m_value.array != nullptr);
3202  for (size_t i = m_value.array->size(); i <= idx; ++i)
3203  {
3204  m_value.array->push_back(basic_json());
3205  }
3206 
3207  return m_value.array->operator[](idx);
3208  }
3209  else
3210  {
3211  throw std::domain_error("cannot use operator[] with " + type_name());
3212  }
3213  }
3214 
3235  {
3236  // const operator[] only works for arrays
3237  if (is_array())
3238  {
3239  assert(m_value.array != nullptr);
3240  return m_value.array->operator[](idx);
3241  }
3242  else
3243  {
3244  throw std::domain_error("cannot use operator[] with " + type_name());
3245  }
3246  }
3247 
3275  reference operator[](const typename object_t::key_type& key)
3276  {
3277  // implicitly convert null value to an empty object
3278  if (is_null())
3279  {
3280  m_type = value_t::object;
3281  m_value.object = create<object_t>();
3282  }
3283 
3284  // operator[] only works for objects
3285  if (is_object())
3286  {
3287  assert(m_value.object != nullptr);
3288  return m_value.object->operator[](key);
3289  }
3290  else
3291  {
3292  throw std::domain_error("cannot use operator[] with " + type_name());
3293  }
3294  }
3295 
3323  const_reference operator[](const typename object_t::key_type& key) const
3324  {
3325  // const operator[] only works for objects
3326  if (is_object())
3327  {
3328  assert(m_value.object != nullptr);
3329  assert(m_value.object->find(key) != m_value.object->end());
3330  return m_value.object->find(key)->second;
3331  }
3332  else
3333  {
3334  throw std::domain_error("cannot use operator[] with " + type_name());
3335  }
3336  }
3337 
3365  template<typename T, std::size_t n>
3366  reference operator[](T * (&key)[n])
3367  {
3368  return operator[](static_cast<const T>(key));
3369  }
3370 
3400  template<typename T, std::size_t n>
3401  const_reference operator[](T * (&key)[n]) const
3402  {
3403  return operator[](static_cast<const T>(key));
3404  }
3405 
3433  template<typename T>
3435  {
3436  // implicitly convert null to object
3437  if (is_null())
3438  {
3439  m_type = value_t::object;
3440  m_value = value_t::object;
3441  }
3442 
3443  // at only works for objects
3444  if (is_object())
3445  {
3446  assert(m_value.object != nullptr);
3447  return m_value.object->operator[](key);
3448  }
3449  else
3450  {
3451  throw std::domain_error("cannot use operator[] with " + type_name());
3452  }
3453  }
3454 
3482  template<typename T>
3484  {
3485  // at only works for objects
3486  if (is_object())
3487  {
3488  assert(m_value.object != nullptr);
3489  assert(m_value.object->find(key) != m_value.object->end());
3490  return m_value.object->find(key)->second;
3491  }
3492  else
3493  {
3494  throw std::domain_error("cannot use operator[] with " + type_name());
3495  }
3496  }
3497 
3546  template <class ValueType, typename
3547  std::enable_if<
3548  std::is_convertible<basic_json_t, ValueType>::value
3549  , int>::type = 0>
3550  ValueType value(const typename object_t::key_type& key, ValueType default_value) const
3551  {
3552  // at only works for objects
3553  if (is_object())
3554  {
3555  // if key is found, return value and given default value otherwise
3556  const auto it = find(key);
3557  if (it != end())
3558  {
3559  return *it;
3560  }
3561  else
3562  {
3563  return default_value;
3564  }
3565  }
3566  else
3567  {
3568  throw std::domain_error("cannot use value() with " + type_name());
3569  }
3570  }
3571 
3576  string_t value(const typename object_t::key_type& key, const char* default_value) const
3577  {
3578  return value(key, string_t(default_value));
3579  }
3580 
3606  {
3607  return *begin();
3608  }
3609 
3614  {
3615  return *cbegin();
3616  }
3617 
3648  {
3649  auto tmp = end();
3650  --tmp;
3651  return *tmp;
3652  }
3653 
3658  {
3659  auto tmp = cend();
3660  --tmp;
3661  return *tmp;
3662  }
3663 
3709  template <class InteratorType, typename
3710  std::enable_if<
3711  std::is_same<InteratorType, typename basic_json_t::iterator>::value or
3712  std::is_same<InteratorType, typename basic_json_t::const_iterator>::value
3713  , int>::type
3714  = 0>
3715  InteratorType erase(InteratorType pos)
3716  {
3717  // make sure iterator fits the current value
3718  if (this != pos.m_object)
3719  {
3720  throw std::domain_error("iterator does not fit current value");
3721  }
3722 
3723  InteratorType result = end();
3724 
3725  switch (m_type)
3726  {
3727  case value_t::boolean:
3728  case value_t::number_float:
3729  case value_t::number_integer:
3730  case value_t::number_unsigned:
3731  case value_t::string:
3732  {
3733  if (not pos.m_it.primitive_iterator.is_begin())
3734  {
3735  throw std::out_of_range("iterator out of range");
3736  }
3737 
3738  if (is_string())
3739  {
3740  delete m_value.string;
3741  m_value.string = nullptr;
3742  }
3743 
3744  m_type = value_t::null;
3745  break;
3746  }
3747 
3748  case value_t::object:
3749  {
3750  assert(m_value.object != nullptr);
3751  result.m_it.object_iterator = m_value.object->erase(pos.m_it.object_iterator);
3752  break;
3753  }
3754 
3755  case value_t::array:
3756  {
3757  assert(m_value.array != nullptr);
3758  result.m_it.array_iterator = m_value.array->erase(pos.m_it.array_iterator);
3759  break;
3760  }
3761 
3762  default:
3763  {
3764  throw std::domain_error("cannot use erase() with " + type_name());
3765  }
3766  }
3767 
3768  return result;
3769  }
3770 
3817  template <class InteratorType, typename
3818  std::enable_if<
3819  std::is_same<InteratorType, typename basic_json_t::iterator>::value or
3820  std::is_same<InteratorType, typename basic_json_t::const_iterator>::value
3821  , int>::type
3822  = 0>
3823  InteratorType erase(InteratorType first, InteratorType last)
3824  {
3825  // make sure iterator fits the current value
3826  if (this != first.m_object or this != last.m_object)
3827  {
3828  throw std::domain_error("iterators do not fit current value");
3829  }
3830 
3831  InteratorType result = end();
3832 
3833  switch (m_type)
3834  {
3835  case value_t::boolean:
3836  case value_t::number_float:
3837  case value_t::number_integer:
3838  case value_t::number_unsigned:
3839  case value_t::string:
3840  {
3841  if (not first.m_it.primitive_iterator.is_begin() or not last.m_it.primitive_iterator.is_end())
3842  {
3843  throw std::out_of_range("iterators out of range");
3844  }
3845 
3846  if (is_string())
3847  {
3848  delete m_value.string;
3849  m_value.string = nullptr;
3850  }
3851 
3852  m_type = value_t::null;
3853  break;
3854  }
3855 
3856  case value_t::object:
3857  {
3858  assert(m_value.object != nullptr);
3859  result.m_it.object_iterator = m_value.object->erase(first.m_it.object_iterator,
3860  last.m_it.object_iterator);
3861  break;
3862  }
3863 
3864  case value_t::array:
3865  {
3866  assert(m_value.array != nullptr);
3867  result.m_it.array_iterator = m_value.array->erase(first.m_it.array_iterator,
3868  last.m_it.array_iterator);
3869  break;
3870  }
3871 
3872  default:
3873  {
3874  throw std::domain_error("cannot use erase() with " + type_name());
3875  }
3876  }
3877 
3878  return result;
3879  }
3880 
3910  size_type erase(const typename object_t::key_type& key)
3911  {
3912  // this erase only works for objects
3913  if (is_object())
3914  {
3915  assert(m_value.object != nullptr);
3916  return m_value.object->erase(key);
3917  }
3918  else
3919  {
3920  throw std::domain_error("cannot use erase() with " + type_name());
3921  }
3922  }
3923 
3948  void erase(const size_type idx)
3949  {
3950  // this erase only works for arrays
3951  if (is_array())
3952  {
3953  if (idx >= size())
3954  {
3955  throw std::out_of_range("index out of range");
3956  }
3957 
3958  assert(m_value.array != nullptr);
3959  m_value.array->erase(m_value.array->begin() + static_cast<difference_type>(idx));
3960  }
3961  else
3962  {
3963  throw std::domain_error("cannot use erase() with " + type_name());
3964  }
3965  }
3966 
3968 
3969 
3971  // lookup //
3973 
3976 
3994  iterator find(typename object_t::key_type key)
3995  {
3996  auto result = end();
3997 
3998  if (is_object())
3999  {
4000  assert(m_value.object != nullptr);
4001  result.m_it.object_iterator = m_value.object->find(key);
4002  }
4003 
4004  return result;
4005  }
4006 
4011  const_iterator find(typename object_t::key_type key) const
4012  {
4013  auto result = cend();
4014 
4015  if (is_object())
4016  {
4017  assert(m_value.object != nullptr);
4018  result.m_it.object_iterator = m_value.object->find(key);
4019  }
4020 
4021  return result;
4022  }
4023 
4042  size_type count(typename object_t::key_type key) const
4043  {
4044  // return 0 for all nonobject types
4045  assert(not is_object() or m_value.object != nullptr);
4046  return is_object() ? m_value.object->count(key) : 0;
4047  }
4048 
4050 
4051 
4053  // iterators //
4055 
4058 
4083  iterator begin() noexcept
4084  {
4085  iterator result(this);
4086  result.set_begin();
4087  return result;
4088  }
4089 
4093  const_iterator begin() const noexcept
4094  {
4095  return cbegin();
4096  }
4097 
4123  const_iterator cbegin() const noexcept
4124  {
4125  const_iterator result(this);
4126  result.set_begin();
4127  return result;
4128  }
4129 
4154  iterator end() noexcept
4155  {
4156  iterator result(this);
4157  result.set_end();
4158  return result;
4159  }
4160 
4164  const_iterator end() const noexcept
4165  {
4166  return cend();
4167  }
4168 
4194  const_iterator cend() const noexcept
4195  {
4196  const_iterator result(this);
4197  result.set_end();
4198  return result;
4199  }
4200 
4225  {
4226  return reverse_iterator(end());
4227  }
4228 
4233  {
4234  return crbegin();
4235  }
4236 
4262  {
4263  return reverse_iterator(begin());
4264  }
4265 
4269  const_reverse_iterator rend() const noexcept
4270  {
4271  return crend();
4272  }
4273 
4299  {
4300  return const_reverse_iterator(cend());
4301  }
4302 
4328  {
4329  return const_reverse_iterator(cbegin());
4330  }
4331 
4332  private:
4333  // forward declaration
4334  template<typename IteratorType> class iteration_proxy;
4335 
4336  public:
4348  static iteration_proxy<iterator> iterator_wrapper(reference cont)
4349  {
4350  return iteration_proxy<iterator>(cont);
4351  }
4352 
4356  static iteration_proxy<const_iterator> iterator_wrapper(const_reference cont)
4357  {
4358  return iteration_proxy<const_iterator>(cont);
4359  }
4360 
4362 
4363 
4365  // capacity //
4367 
4370 
4404  bool empty() const noexcept
4405  {
4406  switch (m_type)
4407  {
4408  case value_t::null:
4409  {
4410  // null values are empty
4411  return true;
4412  }
4413 
4414  case value_t::array:
4415  {
4416  assert(m_value.array != nullptr);
4417  return m_value.array->empty();
4418  }
4419 
4420  case value_t::object:
4421  {
4422  assert(m_value.object != nullptr);
4423  return m_value.object->empty();
4424  }
4425 
4426  default:
4427  {
4428  // all other types are nonempty
4429  return false;
4430  }
4431  }
4432  }
4433 
4467  size_type size() const noexcept
4468  {
4469  switch (m_type)
4470  {
4471  case value_t::null:
4472  {
4473  // null values are empty
4474  return 0;
4475  }
4476 
4477  case value_t::array:
4478  {
4479  assert(m_value.array != nullptr);
4480  return m_value.array->size();
4481  }
4482 
4483  case value_t::object:
4484  {
4485  assert(m_value.object != nullptr);
4486  return m_value.object->size();
4487  }
4488 
4489  default:
4490  {
4491  // all other types have size 1
4492  return 1;
4493  }
4494  }
4495  }
4496 
4533  size_type max_size() const noexcept
4534  {
4535  switch (m_type)
4536  {
4537  case value_t::array:
4538  {
4539  assert(m_value.array != nullptr);
4540  return m_value.array->max_size();
4541  }
4542 
4543  case value_t::object:
4544  {
4545  assert(m_value.object != nullptr);
4546  return m_value.object->max_size();
4547  }
4548 
4549  default:
4550  {
4551  // all other types have max_size() == size()
4552  return size();
4553  }
4554  }
4555  }
4556 
4558 
4559 
4561  // modifiers //
4563 
4566 
4592  void clear() noexcept
4593  {
4594  switch (m_type)
4595  {
4596  case value_t::number_integer:
4597  {
4598  m_value.number_integer = 0;
4599  break;
4600  }
4601 
4602  case value_t::number_unsigned:
4603  {
4604  m_value.number_unsigned = 0;
4605  break;
4606  }
4607 
4608  case value_t::number_float:
4609  {
4610  m_value.number_float = 0.0;
4611  break;
4612  }
4613 
4614  case value_t::boolean:
4615  {
4616  m_value.boolean = false;
4617  break;
4618  }
4619 
4620  case value_t::string:
4621  {
4622  assert(m_value.string != nullptr);
4623  m_value.string->clear();
4624  break;
4625  }
4626 
4627  case value_t::array:
4628  {
4629  assert(m_value.array != nullptr);
4630  m_value.array->clear();
4631  break;
4632  }
4633 
4634  case value_t::object:
4635  {
4636  assert(m_value.object != nullptr);
4637  m_value.object->clear();
4638  break;
4639  }
4640 
4641  default:
4642  {
4643  break;
4644  }
4645  }
4646  }
4647 
4668  void push_back(basic_json&& val)
4669  {
4670  // push_back only works for null objects or arrays
4671  if (not(is_null() or is_array()))
4672  {
4673  throw std::domain_error("cannot use push_back() with " + type_name());
4674  }
4675 
4676  // transform null object into an array
4677  if (is_null())
4678  {
4679  m_type = value_t::array;
4680  m_value = value_t::array;
4681  }
4682 
4683  // add element to array (move semantics)
4684  assert(m_value.array != nullptr);
4685  m_value.array->push_back(std::move(val));
4686  // invalidate object
4687  val.m_type = value_t::null;
4688  }
4689 
4694  reference operator+=(basic_json&& val)
4695  {
4696  push_back(std::move(val));
4697  return *this;
4698  }
4699 
4704  void push_back(const basic_json& val)
4705  {
4706  // push_back only works for null objects or arrays
4707  if (not(is_null() or is_array()))
4708  {
4709  throw std::domain_error("cannot use push_back() with " + type_name());
4710  }
4711 
4712  // transform null object into an array
4713  if (is_null())
4714  {
4715  m_type = value_t::array;
4716  m_value = value_t::array;
4717  }
4718 
4719  // add element to array
4720  assert(m_value.array != nullptr);
4721  m_value.array->push_back(val);
4722  }
4723 
4728  reference operator+=(const basic_json& val)
4729  {
4730  push_back(val);
4731  return *this;
4732  }
4733 
4754  void push_back(const typename object_t::value_type& val)
4755  {
4756  // push_back only works for null objects or objects
4757  if (not(is_null() or is_object()))
4758  {
4759  throw std::domain_error("cannot use push_back() with " + type_name());
4760  }
4761 
4762  // transform null object into an object
4763  if (is_null())
4764  {
4765  m_type = value_t::object;
4766  m_value = value_t::object;
4767  }
4768 
4769  // add element to array
4770  assert(m_value.object != nullptr);
4771  m_value.object->insert(val);
4772  }
4773 
4778  reference operator+=(const typename object_t::value_type& val)
4779  {
4780  push_back(val);
4781  return operator[](val.first);
4782  }
4783 
4806  iterator insert(const_iterator pos, const basic_json& val)
4807  {
4808  // insert only works for arrays
4809  if (is_array())
4810  {
4811  // check if iterator pos fits to this JSON value
4812  if (pos.m_object != this)
4813  {
4814  throw std::domain_error("iterator does not fit current value");
4815  }
4816 
4817  // insert to array and return iterator
4818  iterator result(this);
4819  assert(m_value.array != nullptr);
4820  result.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator, val);
4821  return result;
4822  }
4823  else
4824  {
4825  throw std::domain_error("cannot use insert() with " + type_name());
4826  }
4827  }
4828 
4833  iterator insert(const_iterator pos, basic_json&& val)
4834  {
4835  return insert(pos, val);
4836  }
4837 
4862  iterator insert(const_iterator pos, size_type cnt, const basic_json& val)
4863  {
4864  // insert only works for arrays
4865  if (is_array())
4866  {
4867  // check if iterator pos fits to this JSON value
4868  if (pos.m_object != this)
4869  {
4870  throw std::domain_error("iterator does not fit current value");
4871  }
4872 
4873  // insert to array and return iterator
4874  iterator result(this);
4875  assert(m_value.array != nullptr);
4876  result.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator, cnt, val);
4877  return result;
4878  }
4879  else
4880  {
4881  throw std::domain_error("cannot use insert() with " + type_name());
4882  }
4883  }
4884 
4916  {
4917  // insert only works for arrays
4918  if (not is_array())
4919  {
4920  throw std::domain_error("cannot use insert() with " + type_name());
4921  }
4922 
4923  // check if iterator pos fits to this JSON value
4924  if (pos.m_object != this)
4925  {
4926  throw std::domain_error("iterator does not fit current value");
4927  }
4928 
4929  if (first.m_object != last.m_object)
4930  {
4931  throw std::domain_error("iterators do not fit");
4932  }
4933 
4934  if (first.m_object == this or last.m_object == this)
4935  {
4936  throw std::domain_error("passed iterators may not belong to container");
4937  }
4938 
4939  // insert to array and return iterator
4940  iterator result(this);
4941  assert(m_value.array != nullptr);
4942  result.m_it.array_iterator = m_value.array->insert(
4943  pos.m_it.array_iterator,
4944  first.m_it.array_iterator,
4945  last.m_it.array_iterator);
4946  return result;
4947  }
4948 
4973  iterator insert(const_iterator pos, std::initializer_list<basic_json> ilist)
4974  {
4975  // insert only works for arrays
4976  if (not is_array())
4977  {
4978  throw std::domain_error("cannot use insert() with " + type_name());
4979  }
4980 
4981  // check if iterator pos fits to this JSON value
4982  if (pos.m_object != this)
4983  {
4984  throw std::domain_error("iterator does not fit current value");
4985  }
4986 
4987  // insert to array and return iterator
4988  iterator result(this);
4989  assert(m_value.array != nullptr);
4990  result.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator, ilist);
4991  return result;
4992  }
4993 
5011  void swap(reference other) noexcept (
5012  std::is_nothrow_move_constructible<value_t>::value and
5013  std::is_nothrow_move_assignable<value_t>::value and
5014  std::is_nothrow_move_constructible<json_value>::value and
5015  std::is_nothrow_move_assignable<json_value>::value
5016  )
5017  {
5018  std::swap(m_type, other.m_type);
5019  std::swap(m_value, other.m_value);
5020  }
5021 
5042  void swap(array_t& other)
5043  {
5044  // swap only works for arrays
5045  if (is_array())
5046  {
5047  assert(m_value.array != nullptr);
5048  std::swap(*(m_value.array), other);
5049  }
5050  else
5051  {
5052  throw std::domain_error("cannot use swap() with " + type_name());
5053  }
5054  }
5055 
5076  void swap(object_t& other)
5077  {
5078  // swap only works for objects
5079  if (is_object())
5080  {
5081  assert(m_value.object != nullptr);
5082  std::swap(*(m_value.object), other);
5083  }
5084  else
5085  {
5086  throw std::domain_error("cannot use swap() with " + type_name());
5087  }
5088  }
5089 
5110  void swap(string_t& other)
5111  {
5112  // swap only works for strings
5113  if (is_string())
5114  {
5115  assert(m_value.string != nullptr);
5116  std::swap(*(m_value.string), other);
5117  }
5118  else
5119  {
5120  throw std::domain_error("cannot use swap() with " + type_name());
5121  }
5122  }
5123 
5125 
5126 
5128  // lexicographical comparison operators //
5130 
5133 
5134  private:
5144  friend bool operator<(const value_t lhs, const value_t rhs) noexcept
5145  {
5146  static constexpr std::array<uint8_t, 8> order = {{
5147  0, // null
5148  3, // object
5149  4, // array
5150  5, // string
5151  1, // boolean
5152  2, // integer
5153  2, // unsigned
5154  2, // float
5155  }
5156  };
5157 
5158  // discarded values are not comparable
5159  if (lhs == value_t::discarded or rhs == value_t::discarded)
5160  {
5161  return false;
5162  }
5163 
5164  return order[static_cast<std::size_t>(lhs)] < order[static_cast<std::size_t>(rhs)];
5165  }
5166 
5167  public:
5191  friend bool operator==(const_reference lhs, const_reference rhs) noexcept
5192  {
5193  const auto lhs_type = lhs.type();
5194  const auto rhs_type = rhs.type();
5195 
5196  if (lhs_type == rhs_type)
5197  {
5198  switch (lhs_type)
5199  {
5200  case value_t::array:
5201  {
5202  assert(lhs.m_value.array != nullptr);
5203  assert(rhs.m_value.array != nullptr);
5204  return *lhs.m_value.array == *rhs.m_value.array;
5205  }
5206  case value_t::object:
5207  {
5208  assert(lhs.m_value.object != nullptr);
5209  assert(rhs.m_value.object != nullptr);
5210  return *lhs.m_value.object == *rhs.m_value.object;
5211  }
5212  case value_t::null:
5213  {
5214  return true;
5215  }
5216  case value_t::string:
5217  {
5218  assert(lhs.m_value.string != nullptr);
5219  assert(rhs.m_value.string != nullptr);
5220  return *lhs.m_value.string == *rhs.m_value.string;
5221  }
5222  case value_t::boolean:
5223  {
5224  return lhs.m_value.boolean == rhs.m_value.boolean;
5225  }
5226  case value_t::number_integer:
5227  {
5228  return lhs.m_value.number_integer == rhs.m_value.number_integer;
5229  }
5230  case value_t::number_unsigned:
5231  {
5232  return lhs.m_value.number_unsigned == rhs.m_value.number_unsigned;
5233  }
5234  case value_t::number_float:
5235  {
5236  return lhs.m_value.number_float == rhs.m_value.number_float;
5237  }
5238  default:
5239  {
5240  return false;
5241  }
5242  }
5243  }
5244  else if (lhs_type == value_t::number_integer and rhs_type == value_t::number_float)
5245  {
5246  return static_cast<number_float_t>(lhs.m_value.number_integer) == rhs.m_value.number_float;
5247  }
5248  else if (lhs_type == value_t::number_float and rhs_type == value_t::number_integer)
5249  {
5250  return lhs.m_value.number_float == static_cast<number_float_t>(rhs.m_value.number_integer);
5251  }
5252  else if (lhs_type == value_t::number_unsigned and rhs_type == value_t::number_float)
5253  {
5254  return static_cast<number_float_t>(lhs.m_value.number_unsigned) == rhs.m_value.number_float;
5255  }
5256  else if (lhs_type == value_t::number_float and rhs_type == value_t::number_unsigned)
5257  {
5258  return lhs.m_value.number_float == static_cast<number_float_t>(rhs.m_value.number_unsigned);
5259  }
5260  else if (lhs_type == value_t::number_unsigned and rhs_type == value_t::number_integer)
5261  {
5262  return static_cast<number_integer_t>(lhs.m_value.number_unsigned) == rhs.m_value.number_integer;
5263  }
5264  else if (lhs_type == value_t::number_integer and rhs_type == value_t::number_unsigned)
5265  {
5266  return lhs.m_value.number_integer == static_cast<number_integer_t>(rhs.m_value.number_unsigned);
5267  }
5268 
5269  return false;
5270  }
5271 
5290  friend bool operator==(const_reference v, std::nullptr_t) noexcept
5291  {
5292  return v.is_null();
5293  }
5294 
5299  friend bool operator==(std::nullptr_t, const_reference v) noexcept
5300  {
5301  return v.is_null();
5302  }
5303 
5320  friend bool operator!=(const_reference lhs, const_reference rhs) noexcept
5321  {
5322  return not (lhs == rhs);
5323  }
5324 
5343  friend bool operator!=(const_reference v, std::nullptr_t) noexcept
5344  {
5345  return not v.is_null();
5346  }
5347 
5352  friend bool operator!=(std::nullptr_t, const_reference v) noexcept
5353  {
5354  return not v.is_null();
5355  }
5356 
5381  friend bool operator<(const_reference lhs, const_reference rhs) noexcept
5382  {
5383  const auto lhs_type = lhs.type();
5384  const auto rhs_type = rhs.type();
5385 
5386  if (lhs_type == rhs_type)
5387  {
5388  switch (lhs_type)
5389  {
5390  case value_t::array:
5391  {
5392  assert(lhs.m_value.array != nullptr);
5393  assert(rhs.m_value.array != nullptr);
5394  return *lhs.m_value.array < *rhs.m_value.array;
5395  }
5396  case value_t::object:
5397  {
5398  assert(lhs.m_value.object != nullptr);
5399  assert(rhs.m_value.object != nullptr);
5400  return *lhs.m_value.object < *rhs.m_value.object;
5401  }
5402  case value_t::null:
5403  {
5404  return false;
5405  }
5406  case value_t::string:
5407  {
5408  assert(lhs.m_value.string != nullptr);
5409  assert(rhs.m_value.string != nullptr);
5410  return *lhs.m_value.string < *rhs.m_value.string;
5411  }
5412  case value_t::boolean:
5413  {
5414  return lhs.m_value.boolean < rhs.m_value.boolean;
5415  }
5416  case value_t::number_integer:
5417  {
5418  return lhs.m_value.number_integer < rhs.m_value.number_integer;
5419  }
5420  case value_t::number_unsigned:
5421  {
5422  return lhs.m_value.number_unsigned < rhs.m_value.number_unsigned;
5423  }
5424  case value_t::number_float:
5425  {
5426  return lhs.m_value.number_float < rhs.m_value.number_float;
5427  }
5428  default:
5429  {
5430  return false;
5431  }
5432  }
5433  }
5434  else if (lhs_type == value_t::number_integer and rhs_type == value_t::number_float)
5435  {
5436  return static_cast<number_float_t>(lhs.m_value.number_integer) < rhs.m_value.number_float;
5437  }
5438  else if (lhs_type == value_t::number_float and rhs_type == value_t::number_integer)
5439  {
5440  return lhs.m_value.number_float < static_cast<number_float_t>(rhs.m_value.number_integer);
5441  }
5442  else if (lhs_type == value_t::number_unsigned and rhs_type == value_t::number_float)
5443  {
5444  return static_cast<number_float_t>(lhs.m_value.number_unsigned) < rhs.m_value.number_float;
5445  }
5446  else if (lhs_type == value_t::number_float and rhs_type == value_t::number_unsigned)
5447  {
5448  return lhs.m_value.number_float < static_cast<number_float_t>(rhs.m_value.number_unsigned);
5449  }
5450  else if (lhs_type == value_t::number_integer and rhs_type == value_t::number_unsigned)
5451  {
5452  return lhs.m_value.number_integer < static_cast<number_integer_t>(rhs.m_value.number_unsigned);
5453  }
5454  else if (lhs_type == value_t::number_unsigned and rhs_type == value_t::number_integer)
5455  {
5456  return static_cast<number_integer_t>(lhs.m_value.number_unsigned) < rhs.m_value.number_integer;
5457  }
5458 
5459  // We only reach this line if we cannot compare values. In that case,
5460  // we compare types. Note we have to call the operator explicitly,
5461  // because MSVC has problems otherwise.
5462  return operator<(lhs_type, rhs_type);
5463  }
5464 
5482  friend bool operator<=(const_reference lhs, const_reference rhs) noexcept
5483  {
5484  return not (rhs < lhs);
5485  }
5486 
5504  friend bool operator>(const_reference lhs, const_reference rhs) noexcept
5505  {
5506  return not (lhs <= rhs);
5507  }
5508 
5526  friend bool operator>=(const_reference lhs, const_reference rhs) noexcept
5527  {
5528  return not (lhs < rhs);
5529  }
5530 
5532 
5533 
5535  // serialization //
5537 
5540 
5563  friend std::ostream& operator<<(std::ostream& o, const basic_json& j)
5564  {
5565  // read width member and use it as indentation parameter if nonzero
5566  const bool pretty_print = (o.width() > 0);
5567  const auto indentation = (pretty_print ? o.width() : 0);
5568 
5569  // reset width to 0 for subsequent calls to this stream
5570  o.width(0);
5571 
5572  // do the actual serialization
5573  j.dump(o, pretty_print, static_cast<unsigned int>(indentation));
5574  return o;
5575  }
5576 
5581  friend std::ostream& operator>>(const basic_json& j, std::ostream& o)
5582  {
5583  return o << j;
5584  }
5585 
5587 
5588 
5590  // deserialization //
5592 
5595 
5620  static basic_json parse(const string_t& s, parser_callback_t cb = nullptr)
5621  {
5622  return parser(s, cb).parse();
5623  }
5624 
5649  static basic_json parse(std::istream& i, parser_callback_t cb = nullptr)
5650  {
5651  return parser(i, cb).parse();
5652  }
5653 
5657  static basic_json parse(std::istream&& i, parser_callback_t cb = nullptr)
5658  {
5659  return parser(i, cb).parse();
5660  }
5661 
5685  friend std::istream& operator<<(basic_json& j, std::istream& i)
5686  {
5687  j = parser(i).parse();
5688  return i;
5689  }
5690 
5695  friend std::istream& operator>>(std::istream& i, basic_json& j)
5696  {
5697  j = parser(i).parse();
5698  return i;
5699  }
5700 
5702 
5703 
5704  private:
5706  // convenience functions //
5708 
5710  string_t type_name() const noexcept
5711  {
5712  switch (m_type)
5713  {
5714  case value_t::null:
5715  return "null";
5716  case value_t::object:
5717  return "object";
5718  case value_t::array:
5719  return "array";
5720  case value_t::string:
5721  return "string";
5722  case value_t::boolean:
5723  return "boolean";
5724  case value_t::discarded:
5725  return "discarded";
5726  default:
5727  return "number";
5728  }
5729  }
5730 
5739  static std::size_t extra_space(const string_t& s) noexcept
5740  {
5741  std::size_t result = 0;
5742 
5743  for (const auto& c : s)
5744  {
5745  switch (c)
5746  {
5747  case '"':
5748  case '\\':
5749  case '\b':
5750  case '\f':
5751  case '\n':
5752  case '\r':
5753  case '\t':
5754  {
5755  // from c (1 byte) to \x (2 bytes)
5756  result += 1;
5757  break;
5758  }
5759 
5760  default:
5761  {
5762  if (c >= 0x00 and c <= 0x1f)
5763  {
5764  // from c (1 byte) to \uxxxx (6 bytes)
5765  result += 5;
5766  }
5767  break;
5768  }
5769  }
5770  }
5771 
5772  return result;
5773  }
5774 
5788  static string_t escape_string(const string_t& s)
5789  {
5790  const auto space = extra_space(s);
5791  if (space == 0)
5792  {
5793  return s;
5794  }
5795 
5796  // create a result string of necessary size
5797  string_t result(s.size() + space, '\\');
5798  std::size_t pos = 0;
5799 
5800  for (const auto& c : s)
5801  {
5802  switch (c)
5803  {
5804  // quotation mark (0x22)
5805  case '"':
5806  {
5807  result[pos + 1] = '"';
5808  pos += 2;
5809  break;
5810  }
5811 
5812  // reverse solidus (0x5c)
5813  case '\\':
5814  {
5815  // nothing to change
5816  pos += 2;
5817  break;
5818  }
5819 
5820  // backspace (0x08)
5821  case '\b':
5822  {
5823  result[pos + 1] = 'b';
5824  pos += 2;
5825  break;
5826  }
5827 
5828  // formfeed (0x0c)
5829  case '\f':
5830  {
5831  result[pos + 1] = 'f';
5832  pos += 2;
5833  break;
5834  }
5835 
5836  // newline (0x0a)
5837  case '\n':
5838  {
5839  result[pos + 1] = 'n';
5840  pos += 2;
5841  break;
5842  }
5843 
5844  // carriage return (0x0d)
5845  case '\r':
5846  {
5847  result[pos + 1] = 'r';
5848  pos += 2;
5849  break;
5850  }
5851 
5852  // horizontal tab (0x09)
5853  case '\t':
5854  {
5855  result[pos + 1] = 't';
5856  pos += 2;
5857  break;
5858  }
5859 
5860  default:
5861  {
5862  if (c >= 0x00 and c <= 0x1f)
5863  {
5864  // convert a number 0..15 to its hex representation
5865  // (0..f)
5866  auto hexify = [](const char v) -> char
5867  {
5868  return (v < 10) ? ('0' + v) : ('a' + v - 10);
5869  };
5870 
5871  // print character c as \uxxxx
5872  for (const char m :
5873  { 'u', '0', '0', hexify(c >> 4), hexify(c & 0x0f)
5874  })
5875  {
5876  result[++pos] = m;
5877  }
5878 
5879  ++pos;
5880  }
5881  else
5882  {
5883  // all other characters are added as-is
5884  result[pos++] = c;
5885  }
5886  break;
5887  }
5888  }
5889  }
5890 
5891  return result;
5892  }
5893 
5911  void dump(std::ostream& o,
5912  const bool pretty_print,
5913  const unsigned int indent_step,
5914  const unsigned int current_indent = 0) const
5915  {
5916  // variable to hold indentation for recursive calls
5917  unsigned int new_indent = current_indent;
5918 
5919  switch (m_type)
5920  {
5921  case value_t::object:
5922  {
5923  assert(m_value.object != nullptr);
5924 
5925  if (m_value.object->empty())
5926  {
5927  o << "{}";
5928  return;
5929  }
5930 
5931  o << "{";
5932 
5933  // increase indentation
5934  if (pretty_print)
5935  {
5936  new_indent += indent_step;
5937  o << "\n";
5938  }
5939 
5940  for (auto i = m_value.object->cbegin(); i != m_value.object->cend(); ++i)
5941  {
5942  if (i != m_value.object->cbegin())
5943  {
5944  o << (pretty_print ? ",\n" : ",");
5945  }
5946  o << string_t(new_indent, ' ') << "\""
5947  << escape_string(i->first) << "\":"
5948  << (pretty_print ? " " : "");
5949  i->second.dump(o, pretty_print, indent_step, new_indent);
5950  }
5951 
5952  // decrease indentation
5953  if (pretty_print)
5954  {
5955  new_indent -= indent_step;
5956  o << "\n";
5957  }
5958 
5959  o << string_t(new_indent, ' ') + "}";
5960  return;
5961  }
5962 
5963  case value_t::array:
5964  {
5965  assert(m_value.array != nullptr);
5966 
5967  if (m_value.array->empty())
5968  {
5969  o << "[]";
5970  return;
5971  }
5972 
5973  o << "[";
5974 
5975  // increase indentation
5976  if (pretty_print)
5977  {
5978  new_indent += indent_step;
5979  o << "\n";
5980  }
5981 
5982  for (auto i = m_value.array->cbegin(); i != m_value.array->cend(); ++i)
5983  {
5984  if (i != m_value.array->cbegin())
5985  {
5986  o << (pretty_print ? ",\n" : ",");
5987  }
5988  o << string_t(new_indent, ' ');
5989  i->dump(o, pretty_print, indent_step, new_indent);
5990  }
5991 
5992  // decrease indentation
5993  if (pretty_print)
5994  {
5995  new_indent -= indent_step;
5996  o << "\n";
5997  }
5998 
5999  o << string_t(new_indent, ' ') << "]";
6000  return;
6001  }
6002 
6003  case value_t::string:
6004  {
6005  assert(m_value.string != nullptr);
6006  o << string_t("\"") << escape_string(*m_value.string) << "\"";
6007  return;
6008  }
6009 
6010  case value_t::boolean:
6011  {
6012  o << (m_value.boolean ? "true" : "false");
6013  return;
6014  }
6015 
6016  case value_t::number_integer:
6017  {
6018  o << m_value.number_integer;
6019  return;
6020  }
6021 
6022  case value_t::number_unsigned:
6023  {
6024  o << m_value.number_unsigned;
6025  return;
6026  }
6027 
6028  case value_t::number_float:
6029  {
6030  // If the number is an integer then output as a fixed with with
6031  // precision 1 to output "0.0", "1.0" etc as expected for some
6032  // round trip tests otherwise 15 digits of precision allows
6033  // round-trip IEEE 754 string->double->string; to be safe, we
6034  // read this value from
6035  // std::numeric_limits<number_float_t>::digits10
6036  if (std::fmod(m_value.number_float, 1) == 0)
6037  {
6038  o << std::fixed << std::setprecision(1);
6039  }
6040  else
6041  {
6042  // std::defaultfloat not supported in gcc version < 5
6043  o.unsetf(std::ios_base::floatfield);
6044  o << std::setprecision(std::numeric_limits<double>::digits10);
6045  }
6046  o << m_value.number_float;
6047  return;
6048  }
6049 
6050  case value_t::discarded:
6051  {
6052  o << "<discarded>";
6053  return;
6054  }
6055 
6056  case value_t::null:
6057  {
6058  o << "null";
6059  return;
6060  }
6061  }
6062  }
6063 
6064  private:
6066  // member variables //
6068 
6070  value_t m_type = value_t::null;
6071 
6073  json_value m_value = {};
6074 
6075 
6076  private:
6078  // iterators //
6080 
6090  class primitive_iterator_t
6091  {
6092  public:
6094  void set_begin() noexcept
6095  {
6096  m_it = begin_value;
6097  }
6098 
6100  void set_end() noexcept
6101  {
6102  m_it = end_value;
6103  }
6104 
6106  constexpr bool is_begin() const noexcept
6107  {
6108  return (m_it == begin_value);
6109  }
6110 
6112  constexpr bool is_end() const noexcept
6113  {
6114  return (m_it == end_value);
6115  }
6116 
6118  operator difference_type& () noexcept
6119  {
6120  return m_it;
6121  }
6122 
6124  constexpr operator difference_type () const noexcept
6125  {
6126  return m_it;
6127  }
6128 
6129  private:
6130  static constexpr difference_type begin_value = 0;
6131  static constexpr difference_type end_value = begin_value + 1;
6132 
6134  difference_type m_it = std::numeric_limits<std::ptrdiff_t>::denorm_min();
6135  };
6136 
6144  struct internal_iterator
6145  {
6147  typename object_t::iterator object_iterator;
6149  typename array_t::iterator array_iterator;
6151  primitive_iterator_t primitive_iterator;
6152 
6154  internal_iterator() noexcept
6155  : object_iterator(), array_iterator(), primitive_iterator()
6156  {}
6157  };
6158 
6160  template<typename IteratorType>
6161  class iteration_proxy
6162  {
6163  private:
6165  class iteration_proxy_internal
6166  {
6167  private:
6169  IteratorType anchor;
6171  size_t array_index = 0;
6172 
6173  public:
6174  explicit iteration_proxy_internal(IteratorType it) noexcept
6175  : anchor(it)
6176  {}
6177 
6179  iteration_proxy_internal& operator*()
6180  {
6181  return *this;
6182  }
6183 
6185  iteration_proxy_internal& operator++()
6186  {
6187  ++anchor;
6188  ++array_index;
6189 
6190  return *this;
6191  }
6192 
6194  bool operator!= (const iteration_proxy_internal& o) const
6195  {
6196  return anchor != o.anchor;
6197  }
6198 
6200  typename basic_json::string_t key() const
6201  {
6202  assert(anchor.m_object != nullptr);
6203 
6204  switch (anchor.m_object->type())
6205  {
6206  // use integer array index as key
6207  case value_t::array:
6208  {
6209  return std::to_string(array_index);
6210  }
6211 
6212  // use key from the object
6213  case value_t::object:
6214  {
6215  return anchor.key();
6216  }
6217 
6218  // use an empty key for all primitive types
6219  default:
6220  {
6221  return "";
6222  }
6223  }
6224  }
6225 
6227  typename IteratorType::reference value() const
6228  {
6229  return anchor.value();
6230  }
6231  };
6232 
6234  typename IteratorType::reference container;
6235 
6236  public:
6238  explicit iteration_proxy(typename IteratorType::reference cont)
6239  : container(cont)
6240  {}
6241 
6243  iteration_proxy_internal begin() noexcept
6244  {
6245  return iteration_proxy_internal(container.begin());
6246  }
6247 
6249  iteration_proxy_internal end() noexcept
6250  {
6251  return iteration_proxy_internal(container.end());
6252  }
6253  };
6254 
6255  public:
6269  class const_iterator : public std::iterator<std::random_access_iterator_tag, const basic_json>
6270  {
6272  friend class basic_json;
6273 
6274  public:
6284  using iterator_category = std::bidirectional_iterator_tag;
6285 
6287  const_iterator() = default;
6288 
6290  explicit const_iterator(pointer object) noexcept
6291  : m_object(object)
6292  {
6293  assert(m_object != nullptr);
6294 
6295  switch (m_object->m_type)
6296  {
6298  {
6299  m_it.object_iterator = typename object_t::iterator();
6300  break;
6301  }
6302 
6304  {
6305  m_it.array_iterator = typename array_t::iterator();
6306  break;
6307  }
6308 
6309  default:
6310  {
6311  m_it.primitive_iterator = primitive_iterator_t();
6312  break;
6313  }
6314  }
6315  }
6316 
6318  explicit const_iterator(const iterator& other) noexcept
6319  : m_object(other.m_object)
6320  {
6321  assert(m_object != nullptr);
6322 
6323  switch (m_object->m_type)
6324  {
6326  {
6327  m_it.object_iterator = other.m_it.object_iterator;
6328  break;
6329  }
6330 
6332  {
6333  m_it.array_iterator = other.m_it.array_iterator;
6334  break;
6335  }
6336 
6337  default:
6338  {
6339  m_it.primitive_iterator = other.m_it.primitive_iterator;
6340  break;
6341  }
6342  }
6343  }
6344 
6346  const_iterator(const const_iterator& other) noexcept
6347  : m_object(other.m_object), m_it(other.m_it)
6348  {}
6349 
6352  std::is_nothrow_move_constructible<pointer>::value and
6353  std::is_nothrow_move_assignable<pointer>::value and
6354  std::is_nothrow_move_constructible<internal_iterator>::value and
6355  std::is_nothrow_move_assignable<internal_iterator>::value
6356  )
6357  {
6358  std::swap(m_object, other.m_object);
6359  std::swap(m_it, other.m_it);
6360  return *this;
6361  }
6362 
6363  private:
6365  void set_begin() noexcept
6366  {
6367  assert(m_object != nullptr);
6368 
6369  switch (m_object->m_type)
6370  {
6372  {
6373  assert(m_object->m_value.object != nullptr);
6374  m_it.object_iterator = m_object->m_value.object->begin();
6375  break;
6376  }
6377 
6379  {
6380  assert(m_object->m_value.array != nullptr);
6381  m_it.array_iterator = m_object->m_value.array->begin();
6382  break;
6383  }
6384 
6386  {
6387  // set to end so begin()==end() is true: null is empty
6388  m_it.primitive_iterator.set_end();
6389  break;
6390  }
6391 
6392  default:
6393  {
6394  m_it.primitive_iterator.set_begin();
6395  break;
6396  }
6397  }
6398  }
6399 
6401  void set_end() noexcept
6402  {
6403  assert(m_object != nullptr);
6404 
6405  switch (m_object->m_type)
6406  {
6408  {
6409  assert(m_object->m_value.object != nullptr);
6410  m_it.object_iterator = m_object->m_value.object->end();
6411  break;
6412  }
6413 
6415  {
6416  assert(m_object->m_value.array != nullptr);
6417  m_it.array_iterator = m_object->m_value.array->end();
6418  break;
6419  }
6420 
6421  default:
6422  {
6423  m_it.primitive_iterator.set_end();
6424  break;
6425  }
6426  }
6427  }
6428 
6429  public:
6432  {
6433  assert(m_object != nullptr);
6434 
6435  switch (m_object->m_type)
6436  {
6438  {
6439  assert(m_object->m_value.object);
6440  assert(m_it.object_iterator != m_object->m_value.object->end());
6441  return m_it.object_iterator->second;
6442  }
6443 
6445  {
6446  assert(m_object->m_value.array);
6447  assert(m_it.array_iterator != m_object->m_value.array->end());
6448  return *m_it.array_iterator;
6449  }
6450 
6452  {
6453  throw std::out_of_range("cannot get value");
6454  }
6455 
6456  default:
6457  {
6458  if (m_it.primitive_iterator.is_begin())
6459  {
6460  return *m_object;
6461  }
6462  else
6463  {
6464  throw std::out_of_range("cannot get value");
6465  }
6466  }
6467  }
6468  }
6469 
6472  {
6473  assert(m_object != nullptr);
6474 
6475  switch (m_object->m_type)
6476  {
6478  {
6479  assert(m_object->m_value.object);
6480  assert(m_it.object_iterator != m_object->m_value.object->end());
6481  return &(m_it.object_iterator->second);
6482  }
6483 
6485  {
6486  assert(m_object->m_value.array);
6487  assert(m_it.array_iterator != m_object->m_value.array->end());
6488  return &*m_it.array_iterator;
6489  }
6490 
6491  default:
6492  {
6493  if (m_it.primitive_iterator.is_begin())
6494  {
6495  return m_object;
6496  }
6497  else
6498  {
6499  throw std::out_of_range("cannot get value");
6500  }
6501  }
6502  }
6503  }
6504 
6507  {
6508  auto result = *this;
6509  ++(*this);
6510  return result;
6511  }
6512 
6515  {
6516  assert(m_object != nullptr);
6517 
6518  switch (m_object->m_type)
6519  {
6521  {
6522  ++m_it.object_iterator;
6523  break;
6524  }
6525 
6527  {
6528  ++m_it.array_iterator;
6529  break;
6530  }
6531 
6532  default:
6533  {
6534  ++m_it.primitive_iterator;
6535  break;
6536  }
6537  }
6538 
6539  return *this;
6540  }
6541 
6544  {
6545  auto result = *this;
6546  --(*this);
6547  return result;
6548  }
6549 
6552  {
6553  assert(m_object != nullptr);
6554 
6555  switch (m_object->m_type)
6556  {
6558  {
6559  --m_it.object_iterator;
6560  break;
6561  }
6562 
6564  {
6565  --m_it.array_iterator;
6566  break;
6567  }
6568 
6569  default:
6570  {
6571  --m_it.primitive_iterator;
6572  break;
6573  }
6574  }
6575 
6576  return *this;
6577  }
6578 
6580  bool operator==(const const_iterator& other) const
6581  {
6582  // if objects are not the same, the comparison is undefined
6583  if (m_object != other.m_object)
6584  {
6585  throw std::domain_error("cannot compare iterators of different containers");
6586  }
6587 
6588  assert(m_object != nullptr);
6589 
6590  switch (m_object->m_type)
6591  {
6593  {
6594  return (m_it.object_iterator == other.m_it.object_iterator);
6595  }
6596 
6598  {
6599  return (m_it.array_iterator == other.m_it.array_iterator);
6600  }
6601 
6602  default:
6603  {
6604  return (m_it.primitive_iterator == other.m_it.primitive_iterator);
6605  }
6606  }
6607  }
6608 
6610  bool operator!=(const const_iterator& other) const
6611  {
6612  return not operator==(other);
6613  }
6614 
6616  bool operator<(const const_iterator& other) const
6617  {
6618  // if objects are not the same, the comparison is undefined
6619  if (m_object != other.m_object)
6620  {
6621  throw std::domain_error("cannot compare iterators of different containers");
6622  }
6623 
6624  assert(m_object != nullptr);
6625 
6626  switch (m_object->m_type)
6627  {
6629  {
6630  throw std::domain_error("cannot compare order of object iterators");
6631  }
6632 
6634  {
6635  return (m_it.array_iterator < other.m_it.array_iterator);
6636  }
6637 
6638  default:
6639  {
6640  return (m_it.primitive_iterator < other.m_it.primitive_iterator);
6641  }
6642  }
6643  }
6644 
6646  bool operator<=(const const_iterator& other) const
6647  {
6648  return not other.operator < (*this);
6649  }
6650 
6652  bool operator>(const const_iterator& other) const
6653  {
6654  return not operator<=(other);
6655  }
6656 
6658  bool operator>=(const const_iterator& other) const
6659  {
6660  return not operator<(other);
6661  }
6662 
6665  {
6666  assert(m_object != nullptr);
6667 
6668  switch (m_object->m_type)
6669  {
6671  {
6672  throw std::domain_error("cannot use offsets with object iterators");
6673  }
6674 
6676  {
6677  m_it.array_iterator += i;
6678  break;
6679  }
6680 
6681  default:
6682  {
6683  m_it.primitive_iterator += i;
6684  break;
6685  }
6686  }
6687 
6688  return *this;
6689  }
6690 
6693  {
6694  return operator+=(-i);
6695  }
6696 
6699  {
6700  auto result = *this;
6701  result += i;
6702  return result;
6703  }
6704 
6707  {
6708  auto result = *this;
6709  result -= i;
6710  return result;
6711  }
6712 
6715  {
6716  assert(m_object != nullptr);
6717 
6718  switch (m_object->m_type)
6719  {
6721  {
6722  throw std::domain_error("cannot use offsets with object iterators");
6723  }
6724 
6726  {
6727  return m_it.array_iterator - other.m_it.array_iterator;
6728  }
6729 
6730  default:
6731  {
6732  return m_it.primitive_iterator - other.m_it.primitive_iterator;
6733  }
6734  }
6735  }
6736 
6739  {
6740  assert(m_object != nullptr);
6741 
6742  switch (m_object->m_type)
6743  {
6745  {
6746  throw std::domain_error("cannot use operator[] for object iterators");
6747  }
6748 
6750  {
6751  return *(m_it.array_iterator + n);
6752  }
6753 
6755  {
6756  throw std::out_of_range("cannot get value");
6757  }
6758 
6759  default:
6760  {
6761  if (m_it.primitive_iterator == -n)
6762  {
6763  return *m_object;
6764  }
6765  else
6766  {
6767  throw std::out_of_range("cannot get value");
6768  }
6769  }
6770  }
6771  }
6772 
6774  typename object_t::key_type key() const
6775  {
6776  assert(m_object != nullptr);
6777 
6778  if (m_object->is_object())
6779  {
6780  return m_it.object_iterator->first;
6781  }
6782  else
6783  {
6784  throw std::domain_error("cannot use key() for non-object iterators");
6785  }
6786  }
6787 
6790  {
6791  return operator*();
6792  }
6793 
6794  private:
6796  pointer m_object = nullptr;
6798  internal_iterator m_it = internal_iterator();
6799  };
6800 
6813  class iterator : public const_iterator
6814  {
6815  public:
6817  using pointer = typename basic_json::pointer;
6819 
6821  iterator() = default;
6822 
6824  explicit iterator(pointer object) noexcept
6825  : base_iterator(object)
6826  {}
6827 
6829  iterator(const iterator& other) noexcept
6830  : base_iterator(other)
6831  {}
6832 
6834  iterator& operator=(iterator other) noexcept(
6835  std::is_nothrow_move_constructible<pointer>::value and
6836  std::is_nothrow_move_assignable<pointer>::value and
6837  std::is_nothrow_move_constructible<internal_iterator>::value and
6838  std::is_nothrow_move_assignable<internal_iterator>::value
6839  )
6840  {
6841  base_iterator::operator=(other);
6842  return *this;
6843  }
6844 
6847  {
6848  return const_cast<reference>(base_iterator::operator*());
6849  }
6850 
6853  {
6854  return const_cast<pointer>(base_iterator::operator->());
6855  }
6856 
6859  {
6860  iterator result = *this;
6861  base_iterator::operator++();
6862  return result;
6863  }
6864 
6867  {
6868  base_iterator::operator++();
6869  return *this;
6870  }
6871 
6874  {
6875  iterator result = *this;
6876  base_iterator::operator--();
6877  return result;
6878  }
6879 
6882  {
6883  base_iterator::operator--();
6884  return *this;
6885  }
6886 
6889  {
6890  base_iterator::operator+=(i);
6891  return *this;
6892  }
6893 
6896  {
6897  base_iterator::operator-=(i);
6898  return *this;
6899  }
6900 
6903  {
6904  auto result = *this;
6905  result += i;
6906  return result;
6907  }
6908 
6911  {
6912  auto result = *this;
6913  result -= i;
6914  return result;
6915  }
6916 
6918  difference_type operator-(const iterator& other) const
6919  {
6920  return base_iterator::operator-(other);
6921  }
6922 
6925  {
6926  return const_cast<reference>(base_iterator::operator[](n));
6927  }
6928 
6931  {
6932  return const_cast<reference>(base_iterator::value());
6933  }
6934  };
6935 
6953  template<typename Base>
6954  class json_reverse_iterator : public std::reverse_iterator<Base>
6955  {
6956  public:
6958  using base_iterator = std::reverse_iterator<Base>;
6960  using reference = typename Base::reference;
6961 
6963  json_reverse_iterator(const typename base_iterator::iterator_type& it) noexcept
6964  : base_iterator(it)
6965  {}
6966 
6969  : base_iterator(it)
6970  {}
6971 
6974  {
6975  return base_iterator::operator++(1);
6976  }
6977 
6980  {
6981  base_iterator::operator++();
6982  return *this;
6983  }
6984 
6987  {
6988  return base_iterator::operator--(1);
6989  }
6990 
6993  {
6994  base_iterator::operator--();
6995  return *this;
6996  }
6997 
7000  {
7001  base_iterator::operator+=(i);
7002  return *this;
7003  }
7004 
7007  {
7008  auto result = *this;
7009  result += i;
7010  return result;
7011  }
7012 
7015  {
7016  auto result = *this;
7017  result -= i;
7018  return result;
7019  }
7020 
7023  {
7024  return this->base() - other.base();
7025  }
7026 
7029  {
7030  return *(this->operator+(n));
7031  }
7032 
7034  typename object_t::key_type key() const
7035  {
7036  auto it = --this->base();
7037  return it.key();
7038  }
7039 
7042  {
7043  auto it = --this->base();
7044  return it.operator * ();
7045  }
7046  };
7047 
7048 
7049  private:
7051  // lexer and parser //
7053 
7061  class lexer
7062  {
7063  public:
7065  enum class token_type
7066  {
7067  uninitialized,
7068  literal_true,
7069  literal_false,
7070  literal_null,
7071  value_string,
7072  value_number,
7073  begin_array,
7074  begin_object,
7075  end_array,
7076  end_object,
7077  name_separator,
7078  value_separator,
7079  parse_error,
7080  end_of_input
7081  };
7082 
7084  using lexer_char_t = unsigned char;
7085 
7087  explicit lexer(const string_t& s) noexcept
7088  : m_stream(nullptr), m_buffer(s)
7089  {
7090  m_content = reinterpret_cast<const lexer_char_t*>(s.c_str());
7091  assert(m_content != nullptr);
7092  m_start = m_cursor = m_content;
7093  m_limit = m_content + s.size();
7094  }
7095 
7097  explicit lexer(std::istream* s) noexcept
7098  : m_stream(s), m_buffer()
7099  {
7100  assert(m_stream != nullptr);
7101  getline(*m_stream, m_buffer);
7102  m_content = reinterpret_cast<const lexer_char_t*>(m_buffer.c_str());
7103  assert(m_content != nullptr);
7104  m_start = m_cursor = m_content;
7105  m_limit = m_content + m_buffer.size();
7106  }
7107 
7109  lexer() = default;
7110 
7111  // switch off unwanted functions
7112  lexer(const lexer&) = delete;
7113  lexer operator=(const lexer&) = delete;
7114 
7130  static string_t to_unicode(const std::size_t codepoint1,
7131  const std::size_t codepoint2 = 0)
7132  {
7133  // calculate the codepoint from the given code points
7134  std::size_t codepoint = codepoint1;
7135 
7136  // check if codepoint1 is a high surrogate
7137  if (codepoint1 >= 0xD800 and codepoint1 <= 0xDBFF)
7138  {
7139  // check if codepoint2 is a low surrogate
7140  if (codepoint2 >= 0xDC00 and codepoint2 <= 0xDFFF)
7141  {
7142  codepoint =
7143  // high surrogate occupies the most significant 22 bits
7144  (codepoint1 << 10)
7145  // low surrogate occupies the least significant 15 bits
7146  + codepoint2
7147  // there is still the 0xD800, 0xDC00 and 0x10000 noise
7148  // in the result so we have to subtract with:
7149  // (0xD800 << 10) + DC00 - 0x10000 = 0x35FDC00
7150  - 0x35FDC00;
7151  }
7152  else
7153  {
7154  throw std::invalid_argument("missing or wrong low surrogate");
7155  }
7156  }
7157 
7158  string_t result;
7159 
7160  if (codepoint < 0x80)
7161  {
7162  // 1-byte characters: 0xxxxxxx (ASCII)
7163  result.append(1, static_cast<typename string_t::value_type>(codepoint));
7164  }
7165  else if (codepoint <= 0x7ff)
7166  {
7167  // 2-byte characters: 110xxxxx 10xxxxxx
7168  result.append(1, static_cast<typename string_t::value_type>(0xC0 | ((codepoint >> 6) & 0x1F)));
7169  result.append(1, static_cast<typename string_t::value_type>(0x80 | (codepoint & 0x3F)));
7170  }
7171  else if (codepoint <= 0xffff)
7172  {
7173  // 3-byte characters: 1110xxxx 10xxxxxx 10xxxxxx
7174  result.append(1, static_cast<typename string_t::value_type>(0xE0 | ((codepoint >> 12) & 0x0F)));
7175  result.append(1, static_cast<typename string_t::value_type>(0x80 | ((codepoint >> 6) & 0x3F)));
7176  result.append(1, static_cast<typename string_t::value_type>(0x80 | (codepoint & 0x3F)));
7177  }
7178  else if (codepoint <= 0x10ffff)
7179  {
7180  // 4-byte characters: 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
7181  result.append(1, static_cast<typename string_t::value_type>(0xF0 | ((codepoint >> 18) & 0x07)));
7182  result.append(1, static_cast<typename string_t::value_type>(0x80 | ((codepoint >> 12) & 0x3F)));
7183  result.append(1, static_cast<typename string_t::value_type>(0x80 | ((codepoint >> 6) & 0x3F)));
7184  result.append(1, static_cast<typename string_t::value_type>(0x80 | (codepoint & 0x3F)));
7185  }
7186  else
7187  {
7188  throw std::out_of_range("code points above 0x10FFFF are invalid");
7189  }
7190 
7191  return result;
7192  }
7193 
7195  static std::string token_type_name(token_type t)
7196  {
7197  switch (t)
7198  {
7199  case token_type::uninitialized:
7200  return "<uninitialized>";
7201  case token_type::literal_true:
7202  return "true literal";
7203  case token_type::literal_false:
7204  return "false literal";
7205  case token_type::literal_null:
7206  return "null literal";
7207  case token_type::value_string:
7208  return "string literal";
7209  case token_type::value_number:
7210  return "number literal";
7211  case token_type::begin_array:
7212  return "'['";
7213  case token_type::begin_object:
7214  return "'{'";
7215  case token_type::end_array:
7216  return "']'";
7217  case token_type::end_object:
7218  return "'}'";
7219  case token_type::name_separator:
7220  return "':'";
7221  case token_type::value_separator:
7222  return "','";
7223  case token_type::parse_error:
7224  return "<parse error>";
7225  case token_type::end_of_input:
7226  return "end of input";
7227  default:
7228  {
7229  // catch non-enum values
7230  return "unknown token"; // LCOV_EXCL_LINE
7231  }
7232  }
7233  }
7234 
7245  token_type scan() noexcept
7246  {
7247  // pointer for backtracking information
7248  m_marker = nullptr;
7249 
7250  // remember the begin of the token
7251  m_start = m_cursor;
7252  assert(m_start != nullptr);
7253 
7254 
7255  {
7256  lexer_char_t yych;
7257  unsigned int yyaccept = 0;
7258  static const unsigned char yybm[] =
7259  {
7260  0, 0, 0, 0, 0, 0, 0, 0,
7261  0, 32, 32, 0, 0, 32, 0, 0,
7262  128, 128, 128, 128, 128, 128, 128, 128,
7263  128, 128, 128, 128, 128, 128, 128, 128,
7264  160, 128, 0, 128, 128, 128, 128, 128,
7265  128, 128, 128, 128, 128, 128, 128, 128,
7266  192, 192, 192, 192, 192, 192, 192, 192,
7267  192, 192, 128, 128, 128, 128, 128, 128,
7268  128, 128, 128, 128, 128, 128, 128, 128,
7269  128, 128, 128, 128, 128, 128, 128, 128,
7270  128, 128, 128, 128, 128, 128, 128, 128,
7271  128, 128, 128, 128, 0, 128, 128, 128,
7272  128, 128, 128, 128, 128, 128, 128, 128,
7273  128, 128, 128, 128, 128, 128, 128, 128,
7274  128, 128, 128, 128, 128, 128, 128, 128,
7275  128, 128, 128, 128, 128, 128, 128, 128,
7276  128, 128, 128, 128, 128, 128, 128, 128,
7277  128, 128, 128, 128, 128, 128, 128, 128,
7278  128, 128, 128, 128, 128, 128, 128, 128,
7279  128, 128, 128, 128, 128, 128, 128, 128,
7280  128, 128, 128, 128, 128, 128, 128, 128,
7281  128, 128, 128, 128, 128, 128, 128, 128,
7282  128, 128, 128, 128, 128, 128, 128, 128,
7283  128, 128, 128, 128, 128, 128, 128, 128,
7284  128, 128, 128, 128, 128, 128, 128, 128,
7285  128, 128, 128, 128, 128, 128, 128, 128,
7286  128, 128, 128, 128, 128, 128, 128, 128,
7287  128, 128, 128, 128, 128, 128, 128, 128,
7288  128, 128, 128, 128, 128, 128, 128, 128,
7289  128, 128, 128, 128, 128, 128, 128, 128,
7290  128, 128, 128, 128, 128, 128, 128, 128,
7291  128, 128, 128, 128, 128, 128, 128, 128,
7292  };
7293  if ((m_limit - m_cursor) < 5)
7294  {
7295  yyfill(); // LCOV_EXCL_LINE;
7296  }
7297  yych = *m_cursor;
7298  if (yybm[0 + yych] & 32)
7299  {
7300  goto basic_json_parser_6;
7301  }
7302  if (yych <= '\\')
7303  {
7304  if (yych <= '-')
7305  {
7306  if (yych <= '"')
7307  {
7308  if (yych <= 0x00)
7309  {
7310  goto basic_json_parser_2;
7311  }
7312  if (yych <= '!')
7313  {
7314  goto basic_json_parser_4;
7315  }
7316  goto basic_json_parser_9;
7317  }
7318  else
7319  {
7320  if (yych <= '+')
7321  {
7322  goto basic_json_parser_4;
7323  }
7324  if (yych <= ',')
7325  {
7326  goto basic_json_parser_10;
7327  }
7328  goto basic_json_parser_12;
7329  }
7330  }
7331  else
7332  {
7333  if (yych <= '9')
7334  {
7335  if (yych <= '/')
7336  {
7337  goto basic_json_parser_4;
7338  }
7339  if (yych <= '0')
7340  {
7341  goto basic_json_parser_13;
7342  }
7343  goto basic_json_parser_15;
7344  }
7345  else
7346  {
7347  if (yych <= ':')
7348  {
7349  goto basic_json_parser_17;
7350  }
7351  if (yych == '[')
7352  {
7353  goto basic_json_parser_19;
7354  }
7355  goto basic_json_parser_4;
7356  }
7357  }
7358  }
7359  else
7360  {
7361  if (yych <= 't')
7362  {
7363  if (yych <= 'f')
7364  {
7365  if (yych <= ']')
7366  {
7367  goto basic_json_parser_21;
7368  }
7369  if (yych <= 'e')
7370  {
7371  goto basic_json_parser_4;
7372  }
7373  goto basic_json_parser_23;
7374  }
7375  else
7376  {
7377  if (yych == 'n')
7378  {
7379  goto basic_json_parser_24;
7380  }
7381  if (yych <= 's')
7382  {
7383  goto basic_json_parser_4;
7384  }
7385  goto basic_json_parser_25;
7386  }
7387  }
7388  else
7389  {
7390  if (yych <= '|')
7391  {
7392  if (yych == '{')
7393  {
7394  goto basic_json_parser_26;
7395  }
7396  goto basic_json_parser_4;
7397  }
7398  else
7399  {
7400  if (yych <= '}')
7401  {
7402  goto basic_json_parser_28;
7403  }
7404  if (yych == 0xEF)
7405  {
7406  goto basic_json_parser_30;
7407  }
7408  goto basic_json_parser_4;
7409  }
7410  }
7411  }
7412 basic_json_parser_2:
7413  ++m_cursor;
7414  {
7415  return token_type::end_of_input;
7416  }
7417 basic_json_parser_4:
7418  ++m_cursor;
7419 basic_json_parser_5:
7420  {
7421  return token_type::parse_error;
7422  }
7423 basic_json_parser_6:
7424  ++m_cursor;
7425  if (m_limit <= m_cursor)
7426  {
7427  yyfill(); // LCOV_EXCL_LINE;
7428  }
7429  yych = *m_cursor;
7430  if (yybm[0 + yych] & 32)
7431  {
7432  goto basic_json_parser_6;
7433  }
7434  {
7435  return scan();
7436  }
7437 basic_json_parser_9:
7438  yyaccept = 0;
7439  yych = *(m_marker = ++m_cursor);
7440  if (yych <= 0x0F)
7441  {
7442  goto basic_json_parser_5;
7443  }
7444  goto basic_json_parser_32;
7445 basic_json_parser_10:
7446  ++m_cursor;
7447  {
7448  return token_type::value_separator;
7449  }
7450 basic_json_parser_12:
7451  yych = *++m_cursor;
7452  if (yych <= '/')
7453  {
7454  goto basic_json_parser_5;
7455  }
7456  if (yych <= '0')
7457  {
7458  goto basic_json_parser_13;
7459  }
7460  if (yych <= '9')
7461  {
7462  goto basic_json_parser_15;
7463  }
7464  goto basic_json_parser_5;
7465 basic_json_parser_13:
7466  yyaccept = 1;
7467  yych = *(m_marker = ++m_cursor);
7468  if (yych <= 'D')
7469  {
7470  if (yych == '.')
7471  {
7472  goto basic_json_parser_37;
7473  }
7474  }
7475  else
7476  {
7477  if (yych <= 'E')
7478  {
7479  goto basic_json_parser_38;
7480  }
7481  if (yych == 'e')
7482  {
7483  goto basic_json_parser_38;
7484  }
7485  }
7486 basic_json_parser_14:
7487  {
7488  return token_type::value_number;
7489  }
7490 basic_json_parser_15:
7491  yyaccept = 1;
7492  m_marker = ++m_cursor;
7493  if ((m_limit - m_cursor) < 3)
7494  {
7495  yyfill(); // LCOV_EXCL_LINE;
7496  }
7497  yych = *m_cursor;
7498  if (yybm[0 + yych] & 64)
7499  {
7500  goto basic_json_parser_15;
7501  }
7502  if (yych <= 'D')
7503  {
7504  if (yych == '.')
7505  {
7506  goto basic_json_parser_37;
7507  }
7508  goto basic_json_parser_14;
7509  }
7510  else
7511  {
7512  if (yych <= 'E')
7513  {
7514  goto basic_json_parser_38;
7515  }
7516  if (yych == 'e')
7517  {
7518  goto basic_json_parser_38;
7519  }
7520  goto basic_json_parser_14;
7521  }
7522 basic_json_parser_17:
7523  ++m_cursor;
7524  {
7525  return token_type::name_separator;
7526  }
7527 basic_json_parser_19:
7528  ++m_cursor;
7529  {
7530  return token_type::begin_array;
7531  }
7532 basic_json_parser_21:
7533  ++m_cursor;
7534  {
7535  return token_type::end_array;
7536  }
7537 basic_json_parser_23:
7538  yyaccept = 0;
7539  yych = *(m_marker = ++m_cursor);
7540  if (yych == 'a')
7541  {
7542  goto basic_json_parser_39;
7543  }
7544  goto basic_json_parser_5;
7545 basic_json_parser_24:
7546  yyaccept = 0;
7547  yych = *(m_marker = ++m_cursor);
7548  if (yych == 'u')
7549  {
7550  goto basic_json_parser_40;
7551  }
7552  goto basic_json_parser_5;
7553 basic_json_parser_25:
7554  yyaccept = 0;
7555  yych = *(m_marker = ++m_cursor);
7556  if (yych == 'r')
7557  {
7558  goto basic_json_parser_41;
7559  }
7560  goto basic_json_parser_5;
7561 basic_json_parser_26:
7562  ++m_cursor;
7563  {
7564  return token_type::begin_object;
7565  }
7566 basic_json_parser_28:
7567  ++m_cursor;
7568  {
7569  return token_type::end_object;
7570  }
7571 basic_json_parser_30:
7572  yyaccept = 0;
7573  yych = *(m_marker = ++m_cursor);
7574  if (yych == 0xBB)
7575  {
7576  goto basic_json_parser_42;
7577  }
7578  goto basic_json_parser_5;
7579 basic_json_parser_31:
7580  ++m_cursor;
7581  if (m_limit <= m_cursor)
7582  {
7583  yyfill(); // LCOV_EXCL_LINE;
7584  }
7585  yych = *m_cursor;
7586 basic_json_parser_32:
7587  if (yybm[0 + yych] & 128)
7588  {
7589  goto basic_json_parser_31;
7590  }
7591  if (yych <= 0x0F)
7592  {
7593  goto basic_json_parser_33;
7594  }
7595  if (yych <= '"')
7596  {
7597  goto basic_json_parser_34;
7598  }
7599  goto basic_json_parser_36;
7600 basic_json_parser_33:
7601  m_cursor = m_marker;
7602  if (yyaccept == 0)
7603  {
7604  goto basic_json_parser_5;
7605  }
7606  else
7607  {
7608  goto basic_json_parser_14;
7609  }
7610 basic_json_parser_34:
7611  ++m_cursor;
7612  {
7613  return token_type::value_string;
7614  }
7615 basic_json_parser_36:
7616  ++m_cursor;
7617  if (m_limit <= m_cursor)
7618  {
7619  yyfill(); // LCOV_EXCL_LINE;
7620  }
7621  yych = *m_cursor;
7622  if (yych <= 'e')
7623  {
7624  if (yych <= '/')
7625  {
7626  if (yych == '"')
7627  {
7628  goto basic_json_parser_31;
7629  }
7630  if (yych <= '.')
7631  {
7632  goto basic_json_parser_33;
7633  }
7634  goto basic_json_parser_31;
7635  }
7636  else
7637  {
7638  if (yych <= '\\')
7639  {
7640  if (yych <= '[')
7641  {
7642  goto basic_json_parser_33;
7643  }
7644  goto basic_json_parser_31;
7645  }
7646  else
7647  {
7648  if (yych == 'b')
7649  {
7650  goto basic_json_parser_31;
7651  }
7652  goto basic_json_parser_33;
7653  }
7654  }
7655  }
7656  else
7657  {
7658  if (yych <= 'q')
7659  {
7660  if (yych <= 'f')
7661  {
7662  goto basic_json_parser_31;
7663  }
7664  if (yych == 'n')
7665  {
7666  goto basic_json_parser_31;
7667  }
7668  goto basic_json_parser_33;
7669  }
7670  else
7671  {
7672  if (yych <= 's')
7673  {
7674  if (yych <= 'r')
7675  {
7676  goto basic_json_parser_31;
7677  }
7678  goto basic_json_parser_33;
7679  }
7680  else
7681  {
7682  if (yych <= 't')
7683  {
7684  goto basic_json_parser_31;
7685  }
7686  if (yych <= 'u')
7687  {
7688  goto basic_json_parser_43;
7689  }
7690  goto basic_json_parser_33;
7691  }
7692  }
7693  }
7694 basic_json_parser_37:
7695  yych = *++m_cursor;
7696  if (yych <= '/')
7697  {
7698  goto basic_json_parser_33;
7699  }
7700  if (yych <= '9')
7701  {
7702  goto basic_json_parser_44;
7703  }
7704  goto basic_json_parser_33;
7705 basic_json_parser_38:
7706  yych = *++m_cursor;
7707  if (yych <= ',')
7708  {
7709  if (yych == '+')
7710  {
7711  goto basic_json_parser_46;
7712  }
7713  goto basic_json_parser_33;
7714  }
7715  else
7716  {
7717  if (yych <= '-')
7718  {
7719  goto basic_json_parser_46;
7720  }
7721  if (yych <= '/')
7722  {
7723  goto basic_json_parser_33;
7724  }
7725  if (yych <= '9')
7726  {
7727  goto basic_json_parser_47;
7728  }
7729  goto basic_json_parser_33;
7730  }
7731 basic_json_parser_39:
7732  yych = *++m_cursor;
7733  if (yych == 'l')
7734  {
7735  goto basic_json_parser_49;
7736  }
7737  goto basic_json_parser_33;
7738 basic_json_parser_40:
7739  yych = *++m_cursor;
7740  if (yych == 'l')
7741  {
7742  goto basic_json_parser_50;
7743  }
7744  goto basic_json_parser_33;
7745 basic_json_parser_41:
7746  yych = *++m_cursor;
7747  if (yych == 'u')
7748  {
7749  goto basic_json_parser_51;
7750  }
7751  goto basic_json_parser_33;
7752 basic_json_parser_42:
7753  yych = *++m_cursor;
7754  if (yych == 0xBF)
7755  {
7756  goto basic_json_parser_52;
7757  }
7758  goto basic_json_parser_33;
7759 basic_json_parser_43:
7760  ++m_cursor;
7761  if (m_limit <= m_cursor)
7762  {
7763  yyfill(); // LCOV_EXCL_LINE;
7764  }
7765  yych = *m_cursor;
7766  if (yych <= '@')
7767  {
7768  if (yych <= '/')
7769  {
7770  goto basic_json_parser_33;
7771  }
7772  if (yych <= '9')
7773  {
7774  goto basic_json_parser_54;
7775  }
7776  goto basic_json_parser_33;
7777  }
7778  else
7779  {
7780  if (yych <= 'F')
7781  {
7782  goto basic_json_parser_54;
7783  }
7784  if (yych <= '`')
7785  {
7786  goto basic_json_parser_33;
7787  }
7788  if (yych <= 'f')
7789  {
7790  goto basic_json_parser_54;
7791  }
7792  goto basic_json_parser_33;
7793  }
7794 basic_json_parser_44:
7795  yyaccept = 1;
7796  m_marker = ++m_cursor;
7797  if ((m_limit - m_cursor) < 3)
7798  {
7799  yyfill(); // LCOV_EXCL_LINE;
7800  }
7801  yych = *m_cursor;
7802  if (yych <= 'D')
7803  {
7804  if (yych <= '/')
7805  {
7806  goto basic_json_parser_14;
7807  }
7808  if (yych <= '9')
7809  {
7810  goto basic_json_parser_44;
7811  }
7812  goto basic_json_parser_14;
7813  }
7814  else
7815  {
7816  if (yych <= 'E')
7817  {
7818  goto basic_json_parser_38;
7819  }
7820  if (yych == 'e')
7821  {
7822  goto basic_json_parser_38;
7823  }
7824  goto basic_json_parser_14;
7825  }
7826 basic_json_parser_46:
7827  yych = *++m_cursor;
7828  if (yych <= '/')
7829  {
7830  goto basic_json_parser_33;
7831  }
7832  if (yych >= ':')
7833  {
7834  goto basic_json_parser_33;
7835  }
7836 basic_json_parser_47:
7837  ++m_cursor;
7838  if (m_limit <= m_cursor)
7839  {
7840  yyfill(); // LCOV_EXCL_LINE;
7841  }
7842  yych = *m_cursor;
7843  if (yych <= '/')
7844  {
7845  goto basic_json_parser_14;
7846  }
7847  if (yych <= '9')
7848  {
7849  goto basic_json_parser_47;
7850  }
7851  goto basic_json_parser_14;
7852 basic_json_parser_49:
7853  yych = *++m_cursor;
7854  if (yych == 's')
7855  {
7856  goto basic_json_parser_55;
7857  }
7858  goto basic_json_parser_33;
7859 basic_json_parser_50:
7860  yych = *++m_cursor;
7861  if (yych == 'l')
7862  {
7863  goto basic_json_parser_56;
7864  }
7865  goto basic_json_parser_33;
7866 basic_json_parser_51:
7867  yych = *++m_cursor;
7868  if (yych == 'e')
7869  {
7870  goto basic_json_parser_58;
7871  }
7872  goto basic_json_parser_33;
7873 basic_json_parser_52:
7874  ++m_cursor;
7875  {
7876  return scan();
7877  }
7878 basic_json_parser_54:
7879  ++m_cursor;
7880  if (m_limit <= m_cursor)
7881  {
7882  yyfill(); // LCOV_EXCL_LINE;
7883  }
7884  yych = *m_cursor;
7885  if (yych <= '@')
7886  {
7887  if (yych <= '/')
7888  {
7889  goto basic_json_parser_33;
7890  }
7891  if (yych <= '9')
7892  {
7893  goto basic_json_parser_60;
7894  }
7895  goto basic_json_parser_33;
7896  }
7897  else
7898  {
7899  if (yych <= 'F')
7900  {
7901  goto basic_json_parser_60;
7902  }
7903  if (yych <= '`')
7904  {
7905  goto basic_json_parser_33;
7906  }
7907  if (yych <= 'f')
7908  {
7909  goto basic_json_parser_60;
7910  }
7911  goto basic_json_parser_33;
7912  }
7913 basic_json_parser_55:
7914  yych = *++m_cursor;
7915  if (yych == 'e')
7916  {
7917  goto basic_json_parser_61;
7918  }
7919  goto basic_json_parser_33;
7920 basic_json_parser_56:
7921  ++m_cursor;
7922  {
7923  return token_type::literal_null;
7924  }
7925 basic_json_parser_58:
7926  ++m_cursor;
7927  {
7928  return token_type::literal_true;
7929  }
7930 basic_json_parser_60:
7931  ++m_cursor;
7932  if (m_limit <= m_cursor)
7933  {
7934  yyfill(); // LCOV_EXCL_LINE;
7935  }
7936  yych = *m_cursor;
7937  if (yych <= '@')
7938  {
7939  if (yych <= '/')
7940  {
7941  goto basic_json_parser_33;
7942  }
7943  if (yych <= '9')
7944  {
7945  goto basic_json_parser_63;
7946  }
7947  goto basic_json_parser_33;
7948  }
7949  else
7950  {
7951  if (yych <= 'F')
7952  {
7953  goto basic_json_parser_63;
7954  }
7955  if (yych <= '`')
7956  {
7957  goto basic_json_parser_33;
7958  }
7959  if (yych <= 'f')
7960  {
7961  goto basic_json_parser_63;
7962  }
7963  goto basic_json_parser_33;
7964  }
7965 basic_json_parser_61:
7966  ++m_cursor;
7967  {
7968  return token_type::literal_false;
7969  }
7970 basic_json_parser_63:
7971  ++m_cursor;
7972  if (m_limit <= m_cursor)
7973  {
7974  yyfill(); // LCOV_EXCL_LINE;
7975  }
7976  yych = *m_cursor;
7977  if (yych <= '@')
7978  {
7979  if (yych <= '/')
7980  {
7981  goto basic_json_parser_33;
7982  }
7983  if (yych <= '9')
7984  {
7985  goto basic_json_parser_31;
7986  }
7987  goto basic_json_parser_33;
7988  }
7989  else
7990  {
7991  if (yych <= 'F')
7992  {
7993  goto basic_json_parser_31;
7994  }
7995  if (yych <= '`')
7996  {
7997  goto basic_json_parser_33;
7998  }
7999  if (yych <= 'f')
8000  {
8001  goto basic_json_parser_31;
8002  }
8003  goto basic_json_parser_33;
8004  }
8005  }
8006 
8007  }
8008 
8010  void yyfill() noexcept
8011  {
8012  if (m_stream == nullptr or not * m_stream)
8013  {
8014  return;
8015  }
8016 
8017  const auto offset_start = m_start - m_content;
8018  const auto offset_marker = m_marker - m_start;
8019  const auto offset_cursor = m_cursor - m_start;
8020 
8021  m_buffer.erase(0, static_cast<size_t>(offset_start));
8022  std::string line;
8023  assert(m_stream != nullptr);
8024  std::getline(*m_stream, line);
8025  m_buffer += "\n" + line; // add line with newline symbol
8026 
8027  m_content = reinterpret_cast<const lexer_char_t*>(m_buffer.c_str());
8028  assert(m_content != nullptr);
8029  m_start = m_content;
8030  m_marker = m_start + offset_marker;
8031  m_cursor = m_start + offset_cursor;
8032  m_limit = m_start + m_buffer.size() - 1;
8033  }
8034 
8036  string_t get_token() const
8037  {
8038  assert(m_start != nullptr);
8039  return string_t(reinterpret_cast<typename string_t::const_pointer>(m_start),
8040  static_cast<size_t>(m_cursor - m_start));
8041  }
8042 
8064  string_t get_string() const
8065  {
8066  string_t result;
8067  result.reserve(static_cast<size_t>(m_cursor - m_start - 2));
8068 
8069  // iterate the result between the quotes
8070  for (const lexer_char_t* i = m_start + 1; i < m_cursor - 1; ++i)
8071  {
8072  // process escaped characters
8073  if (*i == '\\')
8074  {
8075  // read next character
8076  ++i;
8077 
8078  switch (*i)
8079  {
8080  // the default escapes
8081  case 't':
8082  {
8083  result += "\t";
8084  break;
8085  }
8086  case 'b':
8087  {
8088  result += "\b";
8089  break;
8090  }
8091  case 'f':
8092  {
8093  result += "\f";
8094  break;
8095  }
8096  case 'n':
8097  {
8098  result += "\n";
8099  break;
8100  }
8101  case 'r':
8102  {
8103  result += "\r";
8104  break;
8105  }
8106  case '\\':
8107  {
8108  result += "\\";
8109  break;
8110  }
8111  case '/':
8112  {
8113  result += "/";
8114  break;
8115  }
8116  case '"':
8117  {
8118  result += "\"";
8119  break;
8120  }
8121 
8122  // unicode
8123  case 'u':
8124  {
8125  // get code xxxx from uxxxx
8126  auto codepoint = std::strtoul(std::string(reinterpret_cast<typename string_t::const_pointer>(i + 1),
8127  4).c_str(), nullptr, 16);
8128 
8129  // check if codepoint is a high surrogate
8130  if (codepoint >= 0xD800 and codepoint <= 0xDBFF)
8131  {
8132  // make sure there is a subsequent unicode
8133  if ((i + 6 >= m_limit) or * (i + 5) != '\\' or * (i + 6) != 'u')
8134  {
8135  throw std::invalid_argument("missing low surrogate");
8136  }
8137 
8138  // get code yyyy from uxxxx\uyyyy
8139  auto codepoint2 = std::strtoul(std::string(reinterpret_cast<typename string_t::const_pointer>
8140  (i + 7), 4).c_str(), nullptr, 16);
8141  result += to_unicode(codepoint, codepoint2);
8142  // skip the next 10 characters (xxxx\uyyyy)
8143  i += 10;
8144  }
8145  else
8146  {
8147  // add unicode character(s)
8148  result += to_unicode(codepoint);
8149  // skip the next four characters (xxxx)
8150  i += 4;
8151  }
8152  break;
8153  }
8154  }
8155  }
8156  else
8157  {
8158  // all other characters are just copied to the end of the
8159  // string
8160  result.append(1, static_cast<typename string_t::value_type>(*i));
8161  }
8162  }
8163 
8164  return result;
8165  }
8166 
8187  long double str_to_float_t(long double* /* type */, char** endptr) const
8188  {
8189  return std::strtold(reinterpret_cast<typename string_t::const_pointer>(m_start), endptr);
8190  }
8191 
8207  double str_to_float_t(double* /* type */, char** endptr) const
8208  {
8209  return std::strtod(reinterpret_cast<typename string_t::const_pointer>(m_start), endptr);
8210  }
8211 
8227  float str_to_float_t(float* /* type */, char** endptr) const
8228  {
8229  return std::strtof(reinterpret_cast<typename string_t::const_pointer>(m_start), endptr);
8230  }
8231 
8244  template <typename T_A, typename T_B>
8245  static bool attempt_cast(T_A source, T_B& dest)
8246  {
8247  dest = static_cast<T_B>(source);
8248  return (source == static_cast<T_A>(dest));
8249  }
8250 
8289  void get_number(basic_json& result) const
8290  {
8291  typename string_t::value_type* endptr;
8292  assert(m_start != nullptr);
8293  errno = 0;
8294 
8295  // attempt to parse it as an integer - first checking for a
8296  // negative number
8297  if (*reinterpret_cast<typename string_t::const_pointer>(m_start) != '-')
8298  {
8299  // positive, parse with strtoull and attempt cast to
8300  // number_unsigned_t
8301  if (attempt_cast(std::strtoull(reinterpret_cast<typename string_t::const_pointer>(m_start), &endptr,
8302  10), result.m_value.number_unsigned))
8303  {
8304  result.m_type = value_t::number_unsigned;
8305  }
8306  else
8307  {
8308  // cast failed due to overflow - store as float
8309  result.m_type = value_t::number_float;
8310  }
8311  }
8312  else
8313  {
8314  // Negative, parse with strtoll and attempt cast to
8315  // number_integer_t
8316  if (attempt_cast(std::strtoll(reinterpret_cast<typename string_t::const_pointer>(m_start), &endptr,
8317  10), result.m_value.number_integer))
8318  {
8319  result.m_type = value_t::number_integer;
8320  }
8321  else
8322  {
8323  // cast failed due to overflow - store as float
8324  result.m_type = value_t::number_float;
8325  }
8326  }
8327 
8328  // check the end of the number was reached and no range error
8329  // occurred
8330  if (reinterpret_cast<lexer_char_t*>(endptr) != m_cursor || errno == ERANGE)
8331  {
8332  result.m_type = value_t::number_float;
8333  }
8334 
8335  if (result.m_type == value_t::number_float)
8336  {
8337  // either the number won't fit in an integer (range error from
8338  // strtoull/strtoll or overflow on cast) or there was something
8339  // else after the number, which could be an exponent
8340 
8341  // parse with strtod
8342  result.m_value.number_float = str_to_float_t(static_cast<number_float_t*>(nullptr), &endptr);
8343 
8344  // anything after the number is an error
8345  if (reinterpret_cast<lexer_char_t*>(endptr) != m_cursor)
8346  {
8347  throw std::invalid_argument(std::string("parse error - ") + get_token() + " is not a number");
8348  }
8349  }
8350  }
8351 
8352  private:
8354  std::istream* m_stream = nullptr;
8356  string_t m_buffer;
8358  const lexer_char_t* m_content = nullptr;
8360  const lexer_char_t* m_start = nullptr;
8362  const lexer_char_t* m_marker = nullptr;
8364  const lexer_char_t* m_cursor = nullptr;
8366  const lexer_char_t* m_limit = nullptr;
8367  };
8368 
8374  class parser
8375  {
8376  public:
8378  parser(const string_t& s, parser_callback_t cb = nullptr) noexcept
8379  : callback(cb), m_lexer(s)
8380  {
8381  // read first token
8382  get_token();
8383  }
8384 
8386  parser(std::istream& _is, parser_callback_t cb = nullptr) noexcept
8387  : callback(cb), m_lexer(&_is)
8388  {
8389  // read first token
8390  get_token();
8391  }
8392 
8394  basic_json parse()
8395  {
8396  basic_json result = parse_internal(true);
8397 
8398  expect(lexer::token_type::end_of_input);
8399 
8400  // return parser result and replace it with null in case the
8401  // top-level value was discarded by the callback function
8402  return result.is_discarded() ? basic_json() : result;
8403  }
8404 
8405  private:
8407  basic_json parse_internal(bool keep)
8408  {
8409  auto result = basic_json(value_t::discarded);
8410 
8411  switch (last_token)
8412  {
8413  case lexer::token_type::begin_object:
8414  {
8415  if (keep and (not callback or (keep = callback(depth++, parse_event_t::object_start, result))))
8416  {
8417  // explicitly set result to object to cope with {}
8418  result.m_type = value_t::object;
8419  result.m_value = json_value(value_t::object);
8420  }
8421 
8422  // read next token
8423  get_token();
8424 
8425  // closing } -> we are done
8426  if (last_token == lexer::token_type::end_object)
8427  {
8428  get_token();
8429  if (keep and callback and not callback(--depth, parse_event_t::object_end, result))
8430  {
8431  result = basic_json(value_t::discarded);
8432  }
8433  return result;
8434  }
8435 
8436  // no comma is expected here
8437  unexpect(lexer::token_type::value_separator);
8438 
8439  // otherwise: parse key-value pairs
8440  do
8441  {
8442  // ugly, but could be fixed with loop reorganization
8443  if (last_token == lexer::token_type::value_separator)
8444  {
8445  get_token();
8446  }
8447 
8448  // store key
8449  expect(lexer::token_type::value_string);
8450  const auto key = m_lexer.get_string();
8451 
8452  bool keep_tag = false;
8453  if (keep)
8454  {
8455  if (callback)
8456  {
8457  basic_json k(key);
8458  keep_tag = callback(depth, parse_event_t::key, k);
8459  }
8460  else
8461  {
8462  keep_tag = true;
8463  }
8464  }
8465 
8466  // parse separator (:)
8467  get_token();
8468  expect(lexer::token_type::name_separator);
8469 
8470  // parse and add value
8471  get_token();
8472  auto value = parse_internal(keep);
8473  if (keep and keep_tag and not value.is_discarded())
8474  {
8475  result[key] = std::move(value);
8476  }
8477  }
8478  while (last_token == lexer::token_type::value_separator);
8479 
8480  // closing }
8481  expect(lexer::token_type::end_object);
8482  get_token();
8483  if (keep and callback and not callback(--depth, parse_event_t::object_end, result))
8484  {
8485  result = basic_json(value_t::discarded);
8486  }
8487 
8488  return result;
8489  }
8490 
8491  case lexer::token_type::begin_array:
8492  {
8493  if (keep and (not callback or (keep = callback(depth++, parse_event_t::array_start, result))))
8494  {
8495  // explicitly set result to object to cope with []
8496  result.m_type = value_t::array;
8497  result.m_value = json_value(value_t::array);
8498  }
8499 
8500  // read next token
8501  get_token();
8502 
8503  // closing ] -> we are done
8504  if (last_token == lexer::token_type::end_array)
8505  {
8506  get_token();
8507  if (callback and not callback(--depth, parse_event_t::array_end, result))
8508  {
8509  result = basic_json(value_t::discarded);
8510  }
8511  return result;
8512  }
8513 
8514  // no comma is expected here
8515  unexpect(lexer::token_type::value_separator);
8516 
8517  // otherwise: parse values
8518  do
8519  {
8520  // ugly, but could be fixed with loop reorganization
8521  if (last_token == lexer::token_type::value_separator)
8522  {
8523  get_token();
8524  }
8525 
8526  // parse value
8527  auto value = parse_internal(keep);
8528  if (keep and not value.is_discarded())
8529  {
8530  result.push_back(std::move(value));
8531  }
8532  }
8533  while (last_token == lexer::token_type::value_separator);
8534 
8535  // closing ]
8536  expect(lexer::token_type::end_array);
8537  get_token();
8538  if (keep and callback and not callback(--depth, parse_event_t::array_end, result))
8539  {
8540  result = basic_json(value_t::discarded);
8541  }
8542 
8543  return result;
8544  }
8545 
8546  case lexer::token_type::literal_null:
8547  {
8548  get_token();
8549  result.m_type = value_t::null;
8550  break;
8551  }
8552 
8553  case lexer::token_type::value_string:
8554  {
8555  const auto s = m_lexer.get_string();
8556  get_token();
8557  result = basic_json(s);
8558  break;
8559  }
8560 
8561  case lexer::token_type::literal_true:
8562  {
8563  get_token();
8564  result.m_type = value_t::boolean;
8565  result.m_value = true;
8566  break;
8567  }
8568 
8569  case lexer::token_type::literal_false:
8570  {
8571  get_token();
8572  result.m_type = value_t::boolean;
8573  result.m_value = false;
8574  break;
8575  }
8576 
8577  case lexer::token_type::value_number:
8578  {
8579  m_lexer.get_number(result);
8580  get_token();
8581  break;
8582  }
8583 
8584  default:
8585  {
8586  // the last token was unexpected
8587  unexpect(last_token);
8588  }
8589  }
8590 
8591  if (keep and callback and not callback(depth, parse_event_t::value, result))
8592  {
8593  result = basic_json(value_t::discarded);
8594  }
8595  return result;
8596  }
8597 
8599  typename lexer::token_type get_token() noexcept
8600  {
8601  last_token = m_lexer.scan();
8602  return last_token;
8603  }
8604 
8605  void expect(typename lexer::token_type t) const
8606  {
8607  if (t != last_token)
8608  {
8609  std::string error_msg = "parse error - unexpected ";
8610  error_msg += (last_token == lexer::token_type::parse_error ? ("'" + m_lexer.get_token() + "'") :
8611  lexer::token_type_name(last_token));
8612  error_msg += "; expected " + lexer::token_type_name(t);
8613  throw std::invalid_argument(error_msg);
8614  }
8615  }
8616 
8617  void unexpect(typename lexer::token_type t) const
8618  {
8619  if (t == last_token)
8620  {
8621  std::string error_msg = "parse error - unexpected ";
8622  error_msg += (last_token == lexer::token_type::parse_error ? ("'" + m_lexer.get_token() + "'") :
8623  lexer::token_type_name(last_token));
8624  throw std::invalid_argument(error_msg);
8625  }
8626  }
8627 
8628  private:
8630  int depth = 0;
8632  parser_callback_t callback;
8634  typename lexer::token_type last_token = lexer::token_type::uninitialized;
8636  lexer m_lexer;
8637  };
8638 };
8639 
8640 
8642 // presets //
8644 
8654 }
8655 
8656 
8658 // nonmember functions //
8660 
8661 // specialization of std::swap, and std::hash
8662 namespace std
8663 {
8669 template <>
8670 inline void swap(nlohmann::json& j1,
8671  nlohmann::json& j2) noexcept(
8672  is_nothrow_move_constructible<nlohmann::json>::value and
8673  is_nothrow_move_assignable<nlohmann::json>::value
8674  )
8675 {
8676  j1.swap(j2);
8677 }
8678 
8680 template <>
8681 struct hash<nlohmann::json>
8682 {
8688  std::size_t operator()(const nlohmann::json& j) const
8689  {
8690  // a naive hashing via the string representation
8691  const auto& h = hash<nlohmann::json::string_t>();
8692  return h(j.dump());
8693  }
8694 };
8695 }
8696 
8709 inline nlohmann::json operator "" _json(const char* s, std::size_t)
8710 {
8711  return nlohmann::json::parse(reinterpret_cast<const nlohmann::json::string_t::value_type*>(s));
8712 }
8713 
8714 // restore GCC/clang diagnostic settings
8715 #if defined(__clang__) || defined(__GNUC__) || defined(__GNUG__)
8716  #pragma GCC diagnostic pop
8717 #endif
8718 
8719 #endif
reference operator*()
return a reference to the value pointed to by the iterator
Definition: json.hpp:6846
const_iterator(pointer object) noexcept
constructor for a given JSON instance
Definition: json.hpp:6290
friend bool operator<=(const_reference lhs, const_reference rhs) noexcept
comparison: less than or equal
Definition: json.hpp:5482
basic_json(const value_t value_type)
create an empty value with a given type
Definition: json.hpp:932
basic_json(const array_t &val)
create an array (explicit)
Definition: json.hpp:1069
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:4042
const_reference operator[](size_type idx) const
access specified array element
Definition: json.hpp:3234
reference value() const
return the value of an iterator
Definition: json.hpp:6930
json_reverse_iterator & operator--()
pre-decrement (–it)
Definition: json.hpp:6992
void clear() noexcept
clears the contents
Definition: json.hpp:4592
bool operator==(const const_iterator &other) const
comparison: equal
Definition: json.hpp:6580
json_reverse_iterator operator--(int)
post-decrement (it–)
Definition: json.hpp:6986
reference operator[](T *(&key)[n])
access specified object element
Definition: json.hpp:3366
friend std::istream & operator>>(std::istream &i, basic_json &j)
deserialize from stream
Definition: json.hpp:5695
constexpr bool is_number_float() const noexcept
return whether value is a floating-point number
Definition: json.hpp:2311
const_reverse_iterator rend() const noexcept
returns a const reverse iterator to one before the first
Definition: json.hpp:4269
iterator & operator+=(difference_type i)
add to iterator
Definition: json.hpp:6888
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:1649
const_iterator operator-(difference_type i)
subtract from iterator
Definition: json.hpp:6706
BooleanType boolean_t
a type for a boolean
Definition: json.hpp:434
const_iterator cbegin() const noexcept
returns a const iterator to the first element
Definition: json.hpp:4123
reference operator+=(const typename object_t::value_type &val)
add an object to an object
Definition: json.hpp:4778
basic_json(const typename string_t::value_type *val)
create a string (explicit)
Definition: json.hpp:1162
reference operator[](difference_type n) const
access to successor
Definition: json.hpp:7028
iterator find(typename object_t::key_type key)
find an element in a JSON object
Definition: json.hpp:3994
friend bool operator!=(const_reference lhs, const_reference rhs) noexcept
comparison: not equal
Definition: json.hpp:5320
basic_json(const string_t &val)
create a string (explicit)
Definition: json.hpp:1138
void push_back(const basic_json &val)
add an object to an array
Definition: json.hpp:4704
void erase(const size_type idx)
remove element from a JSON array given an index
Definition: json.hpp:3948
basic_json<> json
default JSON class
Definition: json.hpp:8653
ArrayType< basic_json, AllocatorType< basic_json >> array_t
a type for an array
Definition: json.hpp:361
reference front()
access the first element
Definition: json.hpp:3605
void swap(object_t &other)
exchanges the values
Definition: json.hpp:5076
json_reverse_iterator operator-(difference_type i) const
subtract from iterator
Definition: json.hpp:7014
const_iterator & operator+=(difference_type i)
add to iterator
Definition: json.hpp:6664
a class to store JSON values
Definition: json.hpp:155
basic_json(const int val) noexcept
create an integer number from an enum type (explicit)
Definition: json.hpp:1273
pointer operator->()
dereference the iterator
Definition: json.hpp:6852
reference value() const
return the value of an iterator
Definition: json.hpp:7041
friend bool operator==(std::nullptr_t, const_reference v) noexcept
comparison: equal
Definition: json.hpp:5299
NumberIntegerType number_integer_t
a type for a number (integer)
Definition: json.hpp:505
iterator insert(const_iterator pos, size_type cnt, const basic_json &val)
inserts elements
Definition: json.hpp:4862
const_reference at(const typename object_t::key_type &key) const
access specified object element with bounds checking
Definition: json.hpp:3141
const_iterator operator+(difference_type i)
add to iterator
Definition: json.hpp:6698
constexpr bool is_object() const noexcept
return whether value is an object
Definition: json.hpp:2333
constexpr bool is_number_integer() const noexcept
return whether value is an integer number
Definition: json.hpp:2255
a mutable random access iterator for the basic_json class
Definition: json.hpp:6813
static basic_json parse(std::istream &&i, parser_callback_t cb=nullptr)
deserialize from stream
Definition: json.hpp:5657
const_iterator operator++(int)
post-increment (it++)
Definition: json.hpp:6506
const_iterator cend() const noexcept
returns a const iterator to one past the last element
Definition: json.hpp:4194
ObjectType< StringType, basic_json, std::less< StringType >, AllocatorType< std::pair< const StringType, basic_json >>> object_t
a type for an object
Definition: json.hpp:315
STL namespace.
NumberUnsignedType number_unsigned_t
a type for a number (unsigned)
Definition: json.hpp:577
typename std::allocator_traits< allocator_type >::const_pointer const_pointer
the type of an element const pointer
Definition: json.hpp:196
basic_json(const number_integer_t val) noexcept
create an integer number (explicit)
Definition: json.hpp:1244
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:1609
static iteration_proxy< const_iterator > iterator_wrapper(const_reference cont)
wrapper to access iterator member functions in range-based for
Definition: json.hpp:4356
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:1964
constexpr value_t type() const noexcept
return the type of the JSON value (explicit)
Definition: json.hpp:2095
typename basic_json::value_type value_type
the type of the values when the iterator is dereferenced
Definition: json.hpp:6276
json_reverse_iterator(const typename base_iterator::iterator_type &it) noexcept
create reverse iterator from iterator
Definition: json.hpp:6963
PointerType get_ptr() noexcept
get a pointer value (implicit)
Definition: json.hpp:2855
constexpr bool is_string() const noexcept
return whether value is a string
Definition: json.hpp:2377
reference back()
access the last element
Definition: json.hpp:3647
const value_type & const_reference
the type of an element const reference
Definition: json.hpp:183
typename basic_json::const_pointer pointer
defines a pointer to the type iterated over (value_type)
Definition: json.hpp:6280
void push_back(const typename object_t::value_type &val)
add an object to an object
Definition: json.hpp:4754
static basic_json parse(const string_t &s, parser_callback_t cb=nullptr)
deserialize from string
Definition: json.hpp:5620
const_reference operator[](T *(&key)[n]) const
read-only access specified object element
Definition: json.hpp:3401
iterator insert(const_iterator pos, const_iterator first, const_iterator last)
inserts elements
Definition: json.hpp:4915
basic_json(std::nullptr_t) noexcept
create a null object (explicitly)
Definition: json.hpp:984
basic_json(InputIT first, InputIT last)
construct a JSON container given an iterator range
Definition: json.hpp:1719
reference operator[](difference_type n) const
access to successor
Definition: json.hpp:6924
static allocator_type get_allocator()
returns the allocator associated with the container
Definition: json.hpp:216
const_reference operator[](const typename object_t::key_type &key) const
read-only access specified object element
Definition: json.hpp:3323
const_reference operator[](T *key) const
read-only access specified object element
Definition: json.hpp:3483
json_reverse_iterator operator+(difference_type i) const
add to iterator
Definition: json.hpp:7006
bool empty() const noexcept
checks whether the container is empty
Definition: json.hpp:4404
std::size_t size_type
a type to represent container sizes
Definition: json.hpp:188
object_t::key_type key() const
return the key of an object iterator
Definition: json.hpp:7034
const_iterator(const iterator &other) noexcept
copy constructor given a nonconst iterator
Definition: json.hpp:6318
basic_json(const CompatibleArrayType &val)
create an array (implicit)
Definition: json.hpp:1109
constexpr bool is_boolean() const noexcept
return whether value is a boolean
Definition: json.hpp:2196
const_reference at(size_type idx) const
access specified array element with bounds checking
Definition: json.hpp:3045
basic_json(size_type cnt, const basic_json &val)
construct an array with count copies of given value
Definition: json.hpp:1673
std::reverse_iterator< Base > base_iterator
shortcut to the reverse iterator adaptor
Definition: json.hpp:6958
const_reverse_iterator crbegin() const noexcept
returns a const reverse iterator to the last element
Definition: json.hpp:4298
iterator insert(const_iterator pos, std::initializer_list< basic_json > ilist)
inserts elements
Definition: json.hpp:4973
typename std::allocator_traits< allocator_type >::pointer pointer
the type of an element pointer
Definition: json.hpp:194
iterator insert(const_iterator pos, const basic_json &val)
inserts element
Definition: json.hpp:4806
friend bool operator>=(const_reference lhs, const_reference rhs) noexcept
comparison: greater than or equal
Definition: json.hpp:5526
friend bool operator<(const_reference lhs, const_reference rhs) noexcept
comparison: less than
Definition: json.hpp:5381
iterator & operator++()
pre-increment (++it)
Definition: json.hpp:6866
bool operator<(const const_iterator &other) const
comparison: smaller
Definition: json.hpp:6616
iterator operator++(int)
post-increment (it++)
Definition: json.hpp:6858
basic_json(basic_json &&other) noexcept
move constructor
Definition: json.hpp:1932
const_iterator operator--(int)
post-decrement (it–)
Definition: json.hpp:6543
reference at(const typename object_t::key_type &key)
access specified object element with bounds checking
Definition: json.hpp:3093
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:6834
object (unordered set of name/value pairs)
size_type max_size() const noexcept
returns the maximum possible number of elements
Definition: json.hpp:4533
~basic_json()
destructor
Definition: json.hpp:1992
iterator operator--(int)
post-decrement (it–)
Definition: json.hpp:6873
iterator operator-(difference_type i)
subtract from iterator
Definition: json.hpp:6910
const_iterator & operator--()
pre-decrement (–it)
Definition: json.hpp:6551
string_t dump(const int indent=-1) const
serialization
Definition: json.hpp:2061
basic_json value_type
the type of elements in a basic_json container
Definition: json.hpp:178
std::function< bool(int depth, parse_event_t event, basic_json &parsed)> parser_callback_t
per-element parser callback type
Definition: json.hpp:883
AllocatorType< basic_json > allocator_type
the allocator type
Definition: json.hpp:191
StringType string_t
a type for a string
Definition: json.hpp:408
reference operator+=(const basic_json &val)
add an object to an array
Definition: json.hpp:4728
difference_type operator-(const const_iterator &other) const
return difference
Definition: json.hpp:6714
value_type & reference
the type of an element reference
Definition: json.hpp:181
const_reverse_iterator rbegin() const noexcept
returns a const reverse iterator to the last element
Definition: json.hpp:4232
friend std::ostream & operator>>(const basic_json &j, std::ostream &o)
serialize to stream
Definition: json.hpp:5581
constexpr bool is_discarded() const noexcept
return whether value is discarded
Definition: json.hpp:2404
const_iterator begin() const noexcept
returns a const iterator to the first element
Definition: json.hpp:4093
difference_type operator-(const iterator &other) const
return difference
Definition: json.hpp:6918
constexpr bool is_array() const noexcept
return whether value is an array
Definition: json.hpp:2355
iterator(const iterator &other) noexcept
copy constructor
Definition: json.hpp:6829
namespace for Niels Lohmann
Definition: json.hpp:48
typename basic_json::difference_type difference_type
a type to represent differences between iterators
Definition: json.hpp:6278
void swap(string_t &other)
exchanges the values
Definition: json.hpp:5110
basic_json(const CompatibleNumberIntegerType val) noexcept
create an integer number (implicit)
Definition: json.hpp:1310
const_reference front() const
access the first element
Definition: json.hpp:3613
bool operator>(const const_iterator &other) const
comparison: greater than
Definition: json.hpp:6652
constexpr const PointerType get_ptr() const noexcept
get a pointer value (implicit)
Definition: json.hpp:2870
pointer operator->() const
dereference the iterator
Definition: json.hpp:6471
NumberFloatType number_float_t
a type for a number (floating-point)
Definition: json.hpp:645
const_reverse_iterator crend() const noexcept
returns a const reverse iterator to one before the first
Definition: json.hpp:4327
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:5011
value_t
the JSON type enumeration
Definition: json.hpp:664
reverse_iterator rbegin() noexcept
returns an iterator to the reverse-beginning
Definition: json.hpp:4224
constexpr bool is_null() const noexcept
return whether value is null
Definition: json.hpp:2174
std::ptrdiff_t difference_type
a type to represent differences between iterators
Definition: json.hpp:186
ValueType get() const
get a value (explicit)
Definition: json.hpp:2771
void swap(array_t &other)
exchanges the values
Definition: json.hpp:5042
InteratorType erase(InteratorType first, InteratorType last)
remove elements given an iterator range
Definition: json.hpp:3823
ValueType value(const typename object_t::key_type &key, ValueType default_value) const
access specified object element with default value
Definition: json.hpp:3550
typename Base::reference reference
the reference type for the pointed-to element
Definition: json.hpp:6960
const_reference back() const
access the last element
Definition: json.hpp:3657
void push_back(basic_json &&val)
add an object to an array
Definition: json.hpp:4668
array (ordered collection of values)
constexpr bool is_number_unsigned() const noexcept
return whether value is an unsigned integer number
Definition: json.hpp:2283
json_reverse_iterator & operator++()
pre-increment (++it)
Definition: json.hpp:6979
static basic_json parse(std::istream &i, parser_callback_t cb=nullptr)
deserialize from stream
Definition: json.hpp:5649
friend bool operator==(const_reference lhs, const_reference rhs) noexcept
comparison: equal
Definition: json.hpp:5191
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:3576
ReferenceType get_ref() const
get a reference value (implicit)
Definition: json.hpp:2921
basic_json(const CompatibleNumberUnsignedType val) noexcept
create an unsigned number (implicit)
Definition: json.hpp:1369
reference operator*() const
return a reference to the value pointed to by the iterator
Definition: json.hpp:6431
friend bool operator<(const value_t lhs, const value_t rhs) noexcept
comparison operator for JSON types
Definition: json.hpp:5144
basic_json(const number_float_t val) noexcept
create a floating-point number (explicit)
Definition: json.hpp:1398
friend bool operator!=(const_reference v, std::nullptr_t) noexcept
comparison: not equal
Definition: json.hpp:5343
iterator operator+(difference_type i)
add to iterator
Definition: json.hpp:6902
basic_json(const CompatibleNumberFloatType val) noexcept
create an floating-point number (implicit)
Definition: json.hpp:1444
bool operator<=(const const_iterator &other) const
comparison: less than or equal
Definition: json.hpp:6646
InteratorType erase(InteratorType pos)
remove element given an iterator
Definition: json.hpp:3715
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:1517
iterator(pointer object) noexcept
constructor for a given JSON instance
Definition: json.hpp:6824
friend bool operator!=(std::nullptr_t, const_reference v) noexcept
comparison: not equal
Definition: json.hpp:5352
constexpr bool is_primitive() const noexcept
return whether type is primitive
Definition: json.hpp:2125
const_iterator & operator++()
pre-increment (++it)
Definition: json.hpp:6514
reference value() const
return the value of an iterator
Definition: json.hpp:6789
constexpr bool is_structured() const noexcept
return whether type is structured
Definition: json.hpp:2152
std::bidirectional_iterator_tag iterator_category
the category of the iterator
Definition: json.hpp:6284
basic_json(boolean_t val) noexcept
create a boolean (explicit)
Definition: json.hpp:1211
iterator end() noexcept
returns an iterator to one past the last element
Definition: json.hpp:4154
reverse_iterator rend() noexcept
returns an iterator to the reverse-end
Definition: json.hpp:4261
difference_type operator-(const json_reverse_iterator &other) const
return difference
Definition: json.hpp:7022
const_iterator find(typename object_t::key_type key) const
find an element in a JSON object
Definition: json.hpp:4011
iterator begin() noexcept
returns an iterator to the first element
Definition: json.hpp:4083
basic_json(const CompatibleObjectType &val)
create an object (implicit)
Definition: json.hpp:1042
const_iterator end() const noexcept
returns a const iterator to one past the last element
Definition: json.hpp:4164
friend bool operator>(const_reference lhs, const_reference rhs) noexcept
comparison: greater than
Definition: json.hpp:5504
bool operator>=(const const_iterator &other) const
comparison: greater than or equal
Definition: json.hpp:6658
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:6351
size_type erase(const typename object_t::key_type &key)
remove element from a JSON object given a key
Definition: json.hpp:3910
reference operator[](const typename object_t::key_type &key)
access specified object element
Definition: json.hpp:3275
object_t::key_type key() const
return the key of an object iterator
Definition: json.hpp:6774
reference operator+=(basic_json &&val)
add an object to an array
Definition: json.hpp:4694
reference operator[](difference_type n) const
access to successor
Definition: json.hpp:6738
a const random access iterator for the basic_json class
Definition: json.hpp:6269
constexpr bool is_number() const noexcept
return whether value is a number
Definition: json.hpp:2226
a template for a reverse iterator class
Definition: json.hpp:199
basic_json(std::istream &i, parser_callback_t cb=nullptr)
construct a JSON value given an input stream
Definition: json.hpp:1826
typename basic_json::const_reference reference
defines a reference to the type iterated over (value_type)
Definition: json.hpp:6282
json_reverse_iterator operator++(int)
post-increment (it++)
Definition: json.hpp:6973
friend bool operator==(const_reference v, std::nullptr_t) noexcept
comparison: equal
Definition: json.hpp:5290
reference operator[](size_type idx)
access specified array element
Definition: json.hpp:3188
bool operator!=(const const_iterator &other) const
comparison: not equal
Definition: json.hpp:6610
json_reverse_iterator & operator+=(difference_type i)
add to iterator
Definition: json.hpp:6999
reference at(size_type idx)
access specified array element with bounds checking
Definition: json.hpp:3001
size_type size() const noexcept
returns the number of elements
Definition: json.hpp:4467
static iteration_proxy< iterator > iterator_wrapper(reference cont)
wrapper to access iterator member functions in range-based for
Definition: json.hpp:4348
iterator & operator-=(difference_type i)
subtract from iterator
Definition: json.hpp:6895
basic_json(const object_t &val)
create an object (explicit)
Definition: json.hpp:1007
basic_json(const number_unsigned_t val) noexcept
create an unsigned integer number (explicit)
Definition: json.hpp:1338
friend std::istream & operator<<(basic_json &j, std::istream &i)
deserialize from stream
Definition: json.hpp:5685
std::size_t operator()(const nlohmann::json &j) const
return a hash value for a JSON object
Definition: json.hpp:8688
json_reverse_iterator(const base_iterator &it) noexcept
create reverse iterator from base class
Definition: json.hpp:6968
friend std::ostream & operator<<(std::ostream &o, const basic_json &j)
serialize to stream
Definition: json.hpp:5563
const_iterator(const const_iterator &other) noexcept
copy constructor
Definition: json.hpp:6346
iterator & operator--()
pre-decrement (–it)
Definition: json.hpp:6881
iterator insert(const_iterator pos, basic_json &&val)
inserts element
Definition: json.hpp:4833
ReferenceType get_ref()
get a reference value (implicit)
Definition: json.hpp:2906
const_iterator & operator-=(difference_type i)
subtract from iterator
Definition: json.hpp:6692
basic_json(const CompatibleStringType &val)
create a string (implicit)
Definition: json.hpp:1193
basic_json(const basic_json &other)
copy constructor
Definition: json.hpp:1857
reference operator[](T *key)
access specified object element
Definition: json.hpp:3434
parse_event_t
JSON callback events.
Definition: json.hpp:818