json.hpp
1 /*
2  __ _____ _____ _____
3  __| | __| | | | JSON for Modern C++
4 | | |__ | | | | | | version 2.0.0
5 |_____|_____|_____|_|___| https://github.com/nlohmann/json
6 
7 Licensed under the MIT License <http://opensource.org/licenses/MIT>.
8 Copyright (c) 2013-2016 Niels Lohmann <http://nlohmann.me>.
9 
10 Permission is hereby granted, free of charge, to any person obtaining a copy
11 of this software and associated documentation files (the "Software"), to deal
12 in the Software without restriction, including without limitation the rights
13 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
14 copies of the Software, and to permit persons to whom the Software is
15 furnished to do so, subject to the following conditions:
16 
17 The above copyright notice and this permission notice shall be included in all
18 copies or substantial portions of the Software.
19 
20 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
23 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
25 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
26 SOFTWARE.
27 */
28 
29 #ifndef NLOHMANN_JSON_HPP
30 #define NLOHMANN_JSON_HPP
31 
32 #include <algorithm>
33 #include <array>
34 #include <cassert>
35 #include <cerrno>
36 #include <ciso646>
37 #include <cmath>
38 #include <cstddef>
39 #include <cstdio>
40 #include <cstdlib>
41 #include <functional>
42 #include <initializer_list>
43 #include <iomanip>
44 #include <iostream>
45 #include <iterator>
46 #include <limits>
47 #include <map>
48 #include <memory>
49 #include <sstream>
50 #include <stdexcept>
51 #include <string>
52 #include <type_traits>
53 #include <utility>
54 #include <vector>
55 
56 // disable float-equal warnings on GCC/clang
57 #if defined(__clang__) || defined(__GNUC__) || defined(__GNUG__)
58  #pragma GCC diagnostic push
59  #pragma GCC diagnostic ignored "-Wfloat-equal"
60 #endif
61 
67 namespace nlohmann
68 {
69 
70 
75 namespace
76 {
81 template<typename T>
82 struct has_mapped_type
83 {
84  private:
85  template<typename C> static char test(typename C::mapped_type*);
86  template<typename C> static char (&test(...))[2];
87  public:
88  static constexpr bool value = sizeof(test<T>(0)) == 1;
89 };
90 
91 }
92 
164 template <
165  template<typename U, typename V, typename... Args> class ObjectType = std::map,
166  template<typename U, typename... Args> class ArrayType = std::vector,
167  class StringType = std::string,
168  class BooleanType = bool,
169  class NumberIntegerType = std::int64_t,
170  class NumberUnsignedType = std::uint64_t,
171  class NumberFloatType = double,
172  template<typename U> class AllocatorType = std::allocator
173  >
175 {
176  private:
178  using basic_json_t = basic_json<ObjectType,
179  ArrayType,
180  StringType,
181  BooleanType,
182  NumberIntegerType,
183  NumberUnsignedType,
184  NumberFloatType,
185  AllocatorType>;
186 
187  public:
188 
190  // container types //
192 
195 
198 
202  using const_reference = const value_type&;
203 
205  using difference_type = std::ptrdiff_t;
207  using size_type = std::size_t;
208 
210  using allocator_type = AllocatorType<basic_json>;
211 
213  using pointer = typename std::allocator_traits<allocator_type>::pointer;
215  using const_pointer = typename std::allocator_traits<allocator_type>::const_pointer;
216 
217  // forward declaration
218  template<typename Base> class json_reverse_iterator;
219 
221  class iterator;
223  class const_iterator;
228 
230 
231 
236  {
237  return allocator_type();
238  }
239 
240 
242  // JSON value data types //
244 
247 
330  using object_t = ObjectType<StringType,
331  basic_json,
332  std::less<StringType>,
333  AllocatorType<std::pair<const StringType,
334  basic_json>>>;
335 
380  using array_t = ArrayType<basic_json, AllocatorType<basic_json>>;
381 
427  using string_t = StringType;
428 
453  using boolean_t = BooleanType;
454 
524  using number_integer_t = NumberIntegerType;
525 
596  using number_unsigned_t = NumberUnsignedType;
597 
664  using number_float_t = NumberFloatType;
665 
667 
668 
670  // JSON type enumeration //
672 
683  enum class value_t : uint8_t
684  {
685  null,
686  object,
687  array,
688  string,
689  boolean,
692  number_float,
693  discarded
694  };
695 
696 
697  private:
699  template<typename T, typename... Args>
700  static T* create(Args&& ... args)
701  {
702  AllocatorType<T> alloc;
703  auto deleter = [&](T * object)
704  {
705  alloc.deallocate(object, 1);
706  };
707  std::unique_ptr<T, decltype(deleter)> object(alloc.allocate(1), deleter);
708  alloc.construct(object.get(), std::forward<Args>(args)...);
709  return object.release();
710  }
711 
713  // JSON value storage //
715 
723  union json_value
724  {
726  object_t* object;
728  array_t* array;
730  string_t* string;
732  boolean_t boolean;
734  number_integer_t number_integer;
736  number_unsigned_t number_unsigned;
738  number_float_t number_float;
739 
741  json_value() = default;
743  json_value(boolean_t v) noexcept : boolean(v) {}
745  json_value(number_integer_t v) noexcept : number_integer(v) {}
747  json_value(number_unsigned_t v) noexcept : number_unsigned(v) {}
749  json_value(number_float_t v) noexcept : number_float(v) {}
751  json_value(value_t t)
752  {
753  switch (t)
754  {
755  case value_t::object:
756  {
757  object = create<object_t>();
758  break;
759  }
760 
761  case value_t::array:
762  {
763  array = create<array_t>();
764  break;
765  }
766 
767  case value_t::string:
768  {
769  string = create<string_t>("");
770  break;
771  }
772 
773  case value_t::boolean:
774  {
775  boolean = boolean_t(false);
776  break;
777  }
778 
780  {
781  number_integer = number_integer_t(0);
782  break;
783  }
784 
786  {
787  number_unsigned = number_unsigned_t(0);
788  break;
789  }
790 
792  {
793  number_float = number_float_t(0.0);
794  break;
795  }
796 
797  default:
798  {
799  break;
800  }
801  }
802  }
803 
805  json_value(const string_t& value)
806  {
807  string = create<string_t>(value);
808  }
809 
811  json_value(const object_t& value)
812  {
813  object = create<object_t>(value);
814  }
815 
817  json_value(const array_t& value)
818  {
819  array = create<array_t>(value);
820  }
821  };
822 
823 
824  public:
826  // JSON parser callback //
828 
837  enum class parse_event_t : uint8_t
838  {
840  object_start,
842  object_end,
844  array_start,
846  array_end,
848  key,
850  value
851  };
852 
902  using parser_callback_t = std::function<bool(int depth, parse_event_t event, basic_json& parsed)>;
903 
904 
906  // constructors //
908 
911 
952  : m_type(value_type), m_value(value_type)
953  {}
954 
979  basic_json() = default;
980 
1003  basic_json(std::nullptr_t) noexcept
1004  : basic_json(value_t::null)
1005  {}
1006 
1026  basic_json(const object_t& val)
1027  : m_type(value_t::object), m_value(val)
1028  {}
1029 
1056  template <class CompatibleObjectType, typename
1057  std::enable_if<
1058  std::is_constructible<typename object_t::key_type, typename CompatibleObjectType::key_type>::value and
1059  std::is_constructible<basic_json, typename CompatibleObjectType::mapped_type>::value, int>::type
1060  = 0>
1061  basic_json(const CompatibleObjectType& val)
1062  : m_type(value_t::object)
1063  {
1064  using std::begin;
1065  using std::end;
1066  m_value.object = create<object_t>(begin(val), end(val));
1067  }
1068 
1088  basic_json(const array_t& val)
1089  : m_type(value_t::array), m_value(val)
1090  {}
1091 
1118  template <class CompatibleArrayType, typename
1119  std::enable_if<
1120  not std::is_same<CompatibleArrayType, typename basic_json_t::iterator>::value and
1121  not std::is_same<CompatibleArrayType, typename basic_json_t::const_iterator>::value and
1122  not std::is_same<CompatibleArrayType, typename basic_json_t::reverse_iterator>::value and
1123  not std::is_same<CompatibleArrayType, typename basic_json_t::const_reverse_iterator>::value and
1124  not std::is_same<CompatibleArrayType, typename array_t::iterator>::value and
1125  not std::is_same<CompatibleArrayType, typename array_t::const_iterator>::value and
1126  std::is_constructible<basic_json, typename CompatibleArrayType::value_type>::value, int>::type
1127  = 0>
1128  basic_json(const CompatibleArrayType& val)
1129  : m_type(value_t::array)
1130  {
1131  using std::begin;
1132  using std::end;
1133  m_value.array = create<array_t>(begin(val), end(val));
1134  }
1135 
1157  basic_json(const string_t& val)
1158  : m_type(value_t::string), m_value(val)
1159  {}
1160 
1181  basic_json(const typename string_t::value_type* val)
1182  : basic_json(string_t(val))
1183  {}
1184 
1208  template <class CompatibleStringType, typename
1209  std::enable_if<
1210  std::is_constructible<string_t, CompatibleStringType>::value, int>::type
1211  = 0>
1212  basic_json(const CompatibleStringType& val)
1213  : basic_json(string_t(val))
1214  {}
1215 
1230  basic_json(boolean_t val) noexcept
1231  : m_type(value_t::boolean), m_value(val)
1232  {}
1233 
1257  template<typename T,
1258  typename std::enable_if<
1259  not (std::is_same<T, int>::value)
1260  and std::is_same<T, number_integer_t>::value
1261  , int>::type
1262  = 0>
1263  basic_json(const number_integer_t val) noexcept
1264  : m_type(value_t::number_integer), m_value(val)
1265  {}
1266 
1292  basic_json(const int val) noexcept
1293  : m_type(value_t::number_integer),
1294  m_value(static_cast<number_integer_t>(val))
1295  {}
1296 
1322  template<typename CompatibleNumberIntegerType, typename
1323  std::enable_if<
1324  std::is_constructible<number_integer_t, CompatibleNumberIntegerType>::value and
1325  std::numeric_limits<CompatibleNumberIntegerType>::is_integer and
1326  std::numeric_limits<CompatibleNumberIntegerType>::is_signed,
1327  CompatibleNumberIntegerType>::type
1328  = 0>
1329  basic_json(const CompatibleNumberIntegerType val) noexcept
1330  : m_type(value_t::number_integer),
1331  m_value(static_cast<number_integer_t>(val))
1332  {}
1333 
1351  template<typename T,
1352  typename std::enable_if<
1353  not (std::is_same<T, int>::value)
1354  and std::is_same<T, number_unsigned_t>::value
1355  , int>::type
1356  = 0>
1357  basic_json(const number_unsigned_t val) noexcept
1358  : m_type(value_t::number_unsigned), m_value(val)
1359  {}
1360 
1381  template < typename CompatibleNumberUnsignedType, typename
1382  std::enable_if <
1383  std::is_constructible<number_unsigned_t, CompatibleNumberUnsignedType>::value and
1384  std::numeric_limits<CompatibleNumberUnsignedType>::is_integer and
1385  !std::numeric_limits<CompatibleNumberUnsignedType>::is_signed,
1386  CompatibleNumberUnsignedType >::type
1387  = 0 >
1388  basic_json(const CompatibleNumberUnsignedType val) noexcept
1389  : m_type(value_t::number_unsigned),
1390  m_value(static_cast<number_unsigned_t>(val))
1391  {}
1392 
1417  basic_json(const number_float_t val) noexcept
1418  : m_type(value_t::number_float), m_value(val)
1419  {
1420  // replace infinity and NAN by null
1421  if (not std::isfinite(val))
1422  {
1423  m_type = value_t::null;
1424  m_value = json_value();
1425  }
1426  }
1427 
1458  template<typename CompatibleNumberFloatType, typename = typename
1459  std::enable_if<
1460  std::is_constructible<number_float_t, CompatibleNumberFloatType>::value and
1461  std::is_floating_point<CompatibleNumberFloatType>::value>::type
1462  >
1463  basic_json(const CompatibleNumberFloatType val) noexcept
1464  : basic_json(number_float_t(val))
1465  {}
1466 
1536  basic_json(std::initializer_list<basic_json> init,
1537  bool type_deduction = true,
1538  value_t manual_type = value_t::array)
1539  {
1540  // the initializer list could describe an object
1541  bool is_an_object = true;
1542 
1543  // check if each element is an array with two elements whose first
1544  // element is a string
1545  for (const auto& element : init)
1546  {
1547  if (not element.is_array() or element.size() != 2
1548  or not element[0].is_string())
1549  {
1550  // we found an element that makes it impossible to use the
1551  // initializer list as object
1552  is_an_object = false;
1553  break;
1554  }
1555  }
1556 
1557  // adjust type if type deduction is not wanted
1558  if (not type_deduction)
1559  {
1560  // if array is wanted, do not create an object though possible
1561  if (manual_type == value_t::array)
1562  {
1563  is_an_object = false;
1564  }
1565 
1566  // if object is wanted but impossible, throw an exception
1567  if (manual_type == value_t::object and not is_an_object)
1568  {
1569  throw std::domain_error("cannot create object from initializer list");
1570  }
1571  }
1572 
1573  if (is_an_object)
1574  {
1575  // the initializer list is a list of pairs -> create object
1576  m_type = value_t::object;
1577  m_value = value_t::object;
1578 
1579  assert(m_value.object != nullptr);
1580 
1581  for (auto& element : init)
1582  {
1583  m_value.object->emplace(*(element[0].m_value.string), element[1]);
1584  }
1585  }
1586  else
1587  {
1588  // the initializer list describes an array -> create array
1589  m_type = value_t::array;
1590  m_value.array = create<array_t>(init);
1591  }
1592  }
1593 
1628  static basic_json array(std::initializer_list<basic_json> init =
1629  std::initializer_list<basic_json>())
1630  {
1631  return basic_json(init, false, value_t::array);
1632  }
1633 
1668  static basic_json object(std::initializer_list<basic_json> init =
1669  std::initializer_list<basic_json>())
1670  {
1671  return basic_json(init, false, value_t::object);
1672  }
1673 
1692  basic_json(size_type cnt, const basic_json& val)
1693  : m_type(value_t::array)
1694  {
1695  m_value.array = create<array_t>(cnt, val);
1696  }
1697 
1732  template <class InputIT, typename
1733  std::enable_if<
1734  std::is_same<InputIT, typename basic_json_t::iterator>::value or
1735  std::is_same<InputIT, typename basic_json_t::const_iterator>::value
1736  , int>::type
1737  = 0>
1738  basic_json(InputIT first, InputIT last) : m_type(first.m_object->m_type)
1739  {
1740  // make sure iterator fits the current value
1741  if (first.m_object != last.m_object)
1742  {
1743  throw std::domain_error("iterators are not compatible");
1744  }
1745 
1746  // check if iterator range is complete for primitive values
1747  switch (m_type)
1748  {
1749  case value_t::boolean:
1750  case value_t::number_float:
1753  case value_t::string:
1754  {
1755  if (not first.m_it.primitive_iterator.is_begin() or not last.m_it.primitive_iterator.is_end())
1756  {
1757  throw std::out_of_range("iterators out of range");
1758  }
1759  break;
1760  }
1761 
1762  default:
1763  {
1764  break;
1765  }
1766  }
1767 
1768  switch (m_type)
1769  {
1771  {
1772  assert(first.m_object != nullptr);
1773  m_value.number_integer = first.m_object->m_value.number_integer;
1774  break;
1775  }
1776 
1778  {
1779  assert(first.m_object != nullptr);
1780  m_value.number_unsigned = first.m_object->m_value.number_unsigned;
1781  break;
1782  }
1783 
1784  case value_t::number_float:
1785  {
1786  assert(first.m_object != nullptr);
1787  m_value.number_float = first.m_object->m_value.number_float;
1788  break;
1789  }
1790 
1791  case value_t::boolean:
1792  {
1793  assert(first.m_object != nullptr);
1794  m_value.boolean = first.m_object->m_value.boolean;
1795  break;
1796  }
1797 
1798  case value_t::string:
1799  {
1800  assert(first.m_object != nullptr);
1801  m_value = *first.m_object->m_value.string;
1802  break;
1803  }
1804 
1805  case value_t::object:
1806  {
1807  m_value.object = create<object_t>(first.m_it.object_iterator, last.m_it.object_iterator);
1808  break;
1809  }
1810 
1811  case value_t::array:
1812  {
1813  m_value.array = create<array_t>(first.m_it.array_iterator, last.m_it.array_iterator);
1814  break;
1815  }
1816 
1817  default:
1818  {
1819  assert(first.m_object != nullptr);
1820  throw std::domain_error("cannot use construct with iterators from " + first.m_object->type_name());
1821  }
1822  }
1823  }
1824 
1845  explicit basic_json(std::istream& i, parser_callback_t cb = nullptr)
1846  {
1847  *this = parser(i, cb).parse();
1848  }
1849 
1851  // other constructors and destructor //
1853 
1876  basic_json(const basic_json& other)
1877  : m_type(other.m_type)
1878  {
1879  switch (m_type)
1880  {
1881  case value_t::object:
1882  {
1883  assert(other.m_value.object != nullptr);
1884  m_value = *other.m_value.object;
1885  break;
1886  }
1887 
1888  case value_t::array:
1889  {
1890  assert(other.m_value.array != nullptr);
1891  m_value = *other.m_value.array;
1892  break;
1893  }
1894 
1895  case value_t::string:
1896  {
1897  assert(other.m_value.string != nullptr);
1898  m_value = *other.m_value.string;
1899  break;
1900  }
1901 
1902  case value_t::boolean:
1903  {
1904  m_value = other.m_value.boolean;
1905  break;
1906  }
1907 
1909  {
1910  m_value = other.m_value.number_integer;
1911  break;
1912  }
1913 
1915  {
1916  m_value = other.m_value.number_unsigned;
1917  break;
1918  }
1919 
1920  case value_t::number_float:
1921  {
1922  m_value = other.m_value.number_float;
1923  break;
1924  }
1925 
1926  default:
1927  {
1928  break;
1929  }
1930  }
1931  }
1932 
1951  basic_json(basic_json&& other) noexcept
1952  : m_type(std::move(other.m_type)),
1953  m_value(std::move(other.m_value))
1954  {
1955  // invalidate payload
1956  other.m_type = value_t::null;
1957  other.m_value = {};
1958  }
1959 
1983  reference& operator=(basic_json other) noexcept (
1984  std::is_nothrow_move_constructible<value_t>::value and
1985  std::is_nothrow_move_assignable<value_t>::value and
1986  std::is_nothrow_move_constructible<json_value>::value and
1987  std::is_nothrow_move_assignable<json_value>::value
1988  )
1989  {
1990  using std::swap;
1991  swap(m_type, other.m_type);
1992  swap(m_value, other.m_value);
1993  return *this;
1994  }
1995 
2012  {
2013  switch (m_type)
2014  {
2015  case value_t::object:
2016  {
2017  AllocatorType<object_t> alloc;
2018  alloc.destroy(m_value.object);
2019  alloc.deallocate(m_value.object, 1);
2020  break;
2021  }
2022 
2023  case value_t::array:
2024  {
2025  AllocatorType<array_t> alloc;
2026  alloc.destroy(m_value.array);
2027  alloc.deallocate(m_value.array, 1);
2028  break;
2029  }
2030 
2031  case value_t::string:
2032  {
2033  AllocatorType<string_t> alloc;
2034  alloc.destroy(m_value.string);
2035  alloc.deallocate(m_value.string, 1);
2036  break;
2037  }
2038 
2039  default:
2040  {
2041  // all other types need no specific destructor
2042  break;
2043  }
2044  }
2045  }
2046 
2048 
2049  public:
2051  // object inspection //
2053 
2056 
2080  string_t dump(const int indent = -1) const
2081  {
2082  std::stringstream ss;
2083 
2084  if (indent >= 0)
2085  {
2086  dump(ss, true, static_cast<unsigned int>(indent));
2087  }
2088  else
2089  {
2090  dump(ss, false, 0);
2091  }
2092 
2093  return ss.str();
2094  }
2095 
2114  constexpr value_t type() const noexcept
2115  {
2116  return m_type;
2117  }
2118 
2144  constexpr bool is_primitive() const noexcept
2145  {
2146  return is_null() or is_string() or is_boolean() or is_number();
2147  }
2148 
2171  constexpr bool is_structured() const noexcept
2172  {
2173  return is_array() or is_object();
2174  }
2175 
2193  constexpr bool is_null() const noexcept
2194  {
2195  return m_type == value_t::null;
2196  }
2197 
2215  constexpr bool is_boolean() const noexcept
2216  {
2217  return m_type == value_t::boolean;
2218  }
2219 
2245  constexpr bool is_number() const noexcept
2246  {
2247  return is_number_integer() or is_number_float();
2248  }
2249 
2274  constexpr bool is_number_integer() const noexcept
2275  {
2276  return m_type == value_t::number_integer or m_type == value_t::number_unsigned;
2277  }
2278 
2302  constexpr bool is_number_unsigned() const noexcept
2303  {
2304  return m_type == value_t::number_unsigned;
2305  }
2306 
2330  constexpr bool is_number_float() const noexcept
2331  {
2332  return m_type == value_t::number_float;
2333  }
2334 
2352  constexpr bool is_object() const noexcept
2353  {
2354  return m_type == value_t::object;
2355  }
2356 
2374  constexpr bool is_array() const noexcept
2375  {
2376  return m_type == value_t::array;
2377  }
2378 
2396  constexpr bool is_string() const noexcept
2397  {
2398  return m_type == value_t::string;
2399  }
2400 
2423  constexpr bool is_discarded() const noexcept
2424  {
2425  return m_type == value_t::discarded;
2426  }
2427 
2446  constexpr operator value_t() const noexcept
2447  {
2448  return m_type;
2449  }
2450 
2452 
2453  private:
2455  // value access //
2457 
2459  template <class T, typename
2460  std::enable_if<
2461  std::is_convertible<typename object_t::key_type, typename T::key_type>::value and
2462  std::is_convertible<basic_json_t, typename T::mapped_type>::value
2463  , int>::type = 0>
2464  T get_impl(T*) const
2465  {
2466  if (is_object())
2467  {
2468  assert(m_value.object != nullptr);
2469  return T(m_value.object->begin(), m_value.object->end());
2470  }
2471  else
2472  {
2473  throw std::domain_error("type must be object, but is " + type_name());
2474  }
2475  }
2476 
2478  object_t get_impl(object_t*) const
2479  {
2480  if (is_object())
2481  {
2482  assert(m_value.object != nullptr);
2483  return *(m_value.object);
2484  }
2485  else
2486  {
2487  throw std::domain_error("type must be object, but is " + type_name());
2488  }
2489  }
2490 
2492  template <class T, typename
2493  std::enable_if<
2494  std::is_convertible<basic_json_t, typename T::value_type>::value and
2495  not std::is_same<basic_json_t, typename T::value_type>::value and
2496  not std::is_arithmetic<T>::value and
2497  not std::is_convertible<std::string, T>::value and
2498  not has_mapped_type<T>::value
2499  , int>::type = 0>
2500  T get_impl(T*) const
2501  {
2502  if (is_array())
2503  {
2504  T to_vector;
2505  assert(m_value.array != nullptr);
2506  std::transform(m_value.array->begin(), m_value.array->end(),
2507  std::inserter(to_vector, to_vector.end()), [](basic_json i)
2508  {
2509  return i.get<typename T::value_type>();
2510  });
2511  return to_vector;
2512  }
2513  else
2514  {
2515  throw std::domain_error("type must be array, but is " + type_name());
2516  }
2517  }
2518 
2520  template <class T, typename
2521  std::enable_if<
2522  std::is_convertible<basic_json_t, T>::value and
2523  not std::is_same<basic_json_t, T>::value
2524  , int>::type = 0>
2525  std::vector<T> get_impl(std::vector<T>*) const
2526  {
2527  if (is_array())
2528  {
2529  std::vector<T> to_vector;
2530  assert(m_value.array != nullptr);
2531  to_vector.reserve(m_value.array->size());
2532  std::transform(m_value.array->begin(), m_value.array->end(),
2533  std::inserter(to_vector, to_vector.end()), [](basic_json i)
2534  {
2535  return i.get<T>();
2536  });
2537  return to_vector;
2538  }
2539  else
2540  {
2541  throw std::domain_error("type must be array, but is " + type_name());
2542  }
2543  }
2544 
2546  template <class T, typename
2547  std::enable_if<
2548  std::is_same<basic_json, typename T::value_type>::value and
2549  not has_mapped_type<T>::value
2550  , int>::type = 0>
2551  T get_impl(T*) const
2552  {
2553  if (is_array())
2554  {
2555  assert(m_value.array != nullptr);
2556  return T(m_value.array->begin(), m_value.array->end());
2557  }
2558  else
2559  {
2560  throw std::domain_error("type must be array, but is " + type_name());
2561  }
2562  }
2563 
2565  array_t get_impl(array_t*) const
2566  {
2567  if (is_array())
2568  {
2569  assert(m_value.array != nullptr);
2570  return *(m_value.array);
2571  }
2572  else
2573  {
2574  throw std::domain_error("type must be array, but is " + type_name());
2575  }
2576  }
2577 
2579  template <typename T, typename
2580  std::enable_if<
2581  std::is_convertible<string_t, T>::value
2582  , int>::type = 0>
2583  T get_impl(T*) const
2584  {
2585  if (is_string())
2586  {
2587  assert(m_value.string != nullptr);
2588  return *m_value.string;
2589  }
2590  else
2591  {
2592  throw std::domain_error("type must be string, but is " + type_name());
2593  }
2594  }
2595 
2597  template<typename T, typename
2598  std::enable_if<
2599  std::is_arithmetic<T>::value
2600  , int>::type = 0>
2601  T get_impl(T*) const
2602  {
2603  switch (m_type)
2604  {
2606  {
2607  return static_cast<T>(m_value.number_integer);
2608  }
2609 
2611  {
2612  return static_cast<T>(m_value.number_unsigned);
2613  }
2614 
2615  case value_t::number_float:
2616  {
2617  return static_cast<T>(m_value.number_float);
2618  }
2619 
2620  default:
2621  {
2622  throw std::domain_error("type must be number, but is " + type_name());
2623  }
2624  }
2625  }
2626 
2628  constexpr boolean_t get_impl(boolean_t*) const
2629  {
2630  return is_boolean()
2631  ? m_value.boolean
2632  : throw std::domain_error("type must be boolean, but is " + type_name());
2633  }
2634 
2636  object_t* get_impl_ptr(object_t*) noexcept
2637  {
2638  return is_object() ? m_value.object : nullptr;
2639  }
2640 
2642  constexpr const object_t* get_impl_ptr(const object_t*) const noexcept
2643  {
2644  return is_object() ? m_value.object : nullptr;
2645  }
2646 
2648  array_t* get_impl_ptr(array_t*) noexcept
2649  {
2650  return is_array() ? m_value.array : nullptr;
2651  }
2652 
2654  constexpr const array_t* get_impl_ptr(const array_t*) const noexcept
2655  {
2656  return is_array() ? m_value.array : nullptr;
2657  }
2658 
2660  string_t* get_impl_ptr(string_t*) noexcept
2661  {
2662  return is_string() ? m_value.string : nullptr;
2663  }
2664 
2666  constexpr const string_t* get_impl_ptr(const string_t*) const noexcept
2667  {
2668  return is_string() ? m_value.string : nullptr;
2669  }
2670 
2672  boolean_t* get_impl_ptr(boolean_t*) noexcept
2673  {
2674  return is_boolean() ? &m_value.boolean : nullptr;
2675  }
2676 
2678  constexpr const boolean_t* get_impl_ptr(const boolean_t*) const noexcept
2679  {
2680  return is_boolean() ? &m_value.boolean : nullptr;
2681  }
2682 
2684  number_integer_t* get_impl_ptr(number_integer_t*) noexcept
2685  {
2686  return is_number_integer() ? &m_value.number_integer : nullptr;
2687  }
2688 
2690  constexpr const number_integer_t* get_impl_ptr(const number_integer_t*) const noexcept
2691  {
2692  return is_number_integer() ? &m_value.number_integer : nullptr;
2693  }
2694 
2696  number_unsigned_t* get_impl_ptr(number_unsigned_t*) noexcept
2697  {
2698  return is_number_unsigned() ? &m_value.number_unsigned : nullptr;
2699  }
2700 
2702  constexpr const number_unsigned_t* get_impl_ptr(const number_unsigned_t*) const noexcept
2703  {
2704  return is_number_unsigned() ? &m_value.number_unsigned : nullptr;
2705  }
2706 
2708  number_float_t* get_impl_ptr(number_float_t*) noexcept
2709  {
2710  return is_number_float() ? &m_value.number_float : nullptr;
2711  }
2712 
2714  constexpr const number_float_t* get_impl_ptr(const number_float_t*) const noexcept
2715  {
2716  return is_number_float() ? &m_value.number_float : nullptr;
2717  }
2718 
2730  template<typename ReferenceType, typename ThisType>
2731  static ReferenceType get_ref_impl(ThisType& obj)
2732  {
2733  // delegate the call to get_ptr<>()
2734  using PointerType = typename std::add_pointer<ReferenceType>::type;
2735  auto ptr = obj.template get_ptr<PointerType>();
2736 
2737  if (ptr != nullptr)
2738  {
2739  return *ptr;
2740  }
2741  else
2742  {
2743  throw std::domain_error("incompatible ReferenceType for get_ref, actual type is " +
2744  obj.type_name());
2745  }
2746  }
2747 
2748  public:
2749 
2752 
2786  template<typename ValueType, typename
2787  std::enable_if<
2788  not std::is_pointer<ValueType>::value
2789  , int>::type = 0>
2790  ValueType get() const
2791  {
2792  return get_impl(static_cast<ValueType*>(nullptr));
2793  }
2794 
2821  template<typename PointerType, typename
2822  std::enable_if<
2823  std::is_pointer<PointerType>::value
2824  , int>::type = 0>
2825  PointerType get() noexcept
2826  {
2827  // delegate the call to get_ptr
2828  return get_ptr<PointerType>();
2829  }
2830 
2835  template<typename PointerType, typename
2836  std::enable_if<
2837  std::is_pointer<PointerType>::value
2838  , int>::type = 0>
2839  constexpr const PointerType get() const noexcept
2840  {
2841  // delegate the call to get_ptr
2842  return get_ptr<PointerType>();
2843  }
2844 
2870  template<typename PointerType, typename
2871  std::enable_if<
2872  std::is_pointer<PointerType>::value
2873  , int>::type = 0>
2874  PointerType get_ptr() noexcept
2875  {
2876  // delegate the call to get_impl_ptr<>()
2877  return get_impl_ptr(static_cast<PointerType>(nullptr));
2878  }
2879 
2884  template<typename PointerType, typename
2885  std::enable_if<
2886  std::is_pointer<PointerType>::value
2887  and std::is_const<typename std::remove_pointer<PointerType>::type>::value
2888  , int>::type = 0>
2889  constexpr const PointerType get_ptr() const noexcept
2890  {
2891  // delegate the call to get_impl_ptr<>() const
2892  return get_impl_ptr(static_cast<const PointerType>(nullptr));
2893  }
2894 
2921  template<typename ReferenceType, typename
2922  std::enable_if<
2923  std::is_reference<ReferenceType>::value
2924  , int>::type = 0>
2925  ReferenceType get_ref()
2926  {
2927  // delegate call to get_ref_impl
2928  return get_ref_impl<ReferenceType>(*this);
2929  }
2930 
2935  template<typename ReferenceType, typename
2936  std::enable_if<
2937  std::is_reference<ReferenceType>::value
2938  and std::is_const<typename std::remove_reference<ReferenceType>::type>::value
2939  , int>::type = 0>
2940  ReferenceType get_ref() const
2941  {
2942  // delegate call to get_ref_impl
2943  return get_ref_impl<ReferenceType>(*this);
2944  }
2945 
2974  template < typename ValueType, typename
2975  std::enable_if <
2976  not std::is_pointer<ValueType>::value
2977  and not std::is_same<ValueType, typename string_t::value_type>::value
2978 #ifndef _MSC_VER // Fix for issue #167 operator<< abiguity under VS2015
2979  and not std::is_same<ValueType, std::initializer_list<typename string_t::value_type>>::value
2980 #endif
2981  , int >::type = 0 >
2982  operator ValueType() const
2983  {
2984  // delegate the call to get<>() const
2985  return get<ValueType>();
2986  }
2987 
2989 
2990 
2992  // element access //
2994 
2997 
3021  {
3022  // at only works for arrays
3023  if (is_array())
3024  {
3025  try
3026  {
3027  assert(m_value.array != nullptr);
3028  return m_value.array->at(idx);
3029  }
3030  catch (std::out_of_range&)
3031  {
3032  // create better exception explanation
3033  throw std::out_of_range("array index " + std::to_string(idx) + " is out of range");
3034  }
3035  }
3036  else
3037  {
3038  throw std::domain_error("cannot use at() with " + type_name());
3039  }
3040  }
3041 
3065  {
3066  // at only works for arrays
3067  if (is_array())
3068  {
3069  try
3070  {
3071  assert(m_value.array != nullptr);
3072  return m_value.array->at(idx);
3073  }
3074  catch (std::out_of_range&)
3075  {
3076  // create better exception explanation
3077  throw std::out_of_range("array index " + std::to_string(idx) + " is out of range");
3078  }
3079  }
3080  else
3081  {
3082  throw std::domain_error("cannot use at() with " + type_name());
3083  }
3084  }
3085 
3112  reference at(const typename object_t::key_type& key)
3113  {
3114  // at only works for objects
3115  if (is_object())
3116  {
3117  try
3118  {
3119  assert(m_value.object != nullptr);
3120  return m_value.object->at(key);
3121  }
3122  catch (std::out_of_range&)
3123  {
3124  // create better exception explanation
3125  throw std::out_of_range("key '" + key + "' not found");
3126  }
3127  }
3128  else
3129  {
3130  throw std::domain_error("cannot use at() with " + type_name());
3131  }
3132  }
3133 
3160  const_reference at(const typename object_t::key_type& key) const
3161  {
3162  // at only works for objects
3163  if (is_object())
3164  {
3165  try
3166  {
3167  assert(m_value.object != nullptr);
3168  return m_value.object->at(key);
3169  }
3170  catch (std::out_of_range&)
3171  {
3172  // create better exception explanation
3173  throw std::out_of_range("key '" + key + "' not found");
3174  }
3175  }
3176  else
3177  {
3178  throw std::domain_error("cannot use at() with " + type_name());
3179  }
3180  }
3181 
3208  {
3209  // implicitly convert null value to an empty array
3210  if (is_null())
3211  {
3212  m_type = value_t::array;
3213  m_value.array = create<array_t>();
3214  }
3215 
3216  // operator[] only works for arrays
3217  if (is_array())
3218  {
3219  // fill up array with null values until given idx is reached
3220  assert(m_value.array != nullptr);
3221  for (size_t i = m_value.array->size(); i <= idx; ++i)
3222  {
3223  m_value.array->push_back(basic_json());
3224  }
3225 
3226  return m_value.array->operator[](idx);
3227  }
3228  else
3229  {
3230  throw std::domain_error("cannot use operator[] with " + type_name());
3231  }
3232  }
3233 
3254  {
3255  // const operator[] only works for arrays
3256  if (is_array())
3257  {
3258  assert(m_value.array != nullptr);
3259  return m_value.array->operator[](idx);
3260  }
3261  else
3262  {
3263  throw std::domain_error("cannot use operator[] with " + type_name());
3264  }
3265  }
3266 
3294  reference operator[](const typename object_t::key_type& key)
3295  {
3296  // implicitly convert null value to an empty object
3297  if (is_null())
3298  {
3299  m_type = value_t::object;
3300  m_value.object = create<object_t>();
3301  }
3302 
3303  // operator[] only works for objects
3304  if (is_object())
3305  {
3306  assert(m_value.object != nullptr);
3307  return m_value.object->operator[](key);
3308  }
3309  else
3310  {
3311  throw std::domain_error("cannot use operator[] with " + type_name());
3312  }
3313  }
3314 
3342  const_reference operator[](const typename object_t::key_type& key) const
3343  {
3344  // const operator[] only works for objects
3345  if (is_object())
3346  {
3347  assert(m_value.object != nullptr);
3348  assert(m_value.object->find(key) != m_value.object->end());
3349  return m_value.object->find(key)->second;
3350  }
3351  else
3352  {
3353  throw std::domain_error("cannot use operator[] with " + type_name());
3354  }
3355  }
3356 
3384  template<typename T, std::size_t n>
3385  reference operator[](T * (&key)[n])
3386  {
3387  return operator[](static_cast<const T>(key));
3388  }
3389 
3419  template<typename T, std::size_t n>
3420  const_reference operator[](T * (&key)[n]) const
3421  {
3422  return operator[](static_cast<const T>(key));
3423  }
3424 
3452  template<typename T>
3454  {
3455  // implicitly convert null to object
3456  if (is_null())
3457  {
3458  m_type = value_t::object;
3459  m_value = value_t::object;
3460  }
3461 
3462  // at only works for objects
3463  if (is_object())
3464  {
3465  assert(m_value.object != nullptr);
3466  return m_value.object->operator[](key);
3467  }
3468  else
3469  {
3470  throw std::domain_error("cannot use operator[] with " + type_name());
3471  }
3472  }
3473 
3501  template<typename T>
3503  {
3504  // at only works for objects
3505  if (is_object())
3506  {
3507  assert(m_value.object != nullptr);
3508  assert(m_value.object->find(key) != m_value.object->end());
3509  return m_value.object->find(key)->second;
3510  }
3511  else
3512  {
3513  throw std::domain_error("cannot use operator[] with " + type_name());
3514  }
3515  }
3516 
3565  template <class ValueType, typename
3566  std::enable_if<
3567  std::is_convertible<basic_json_t, ValueType>::value
3568  , int>::type = 0>
3569  ValueType value(const typename object_t::key_type& key, ValueType default_value) const
3570  {
3571  // at only works for objects
3572  if (is_object())
3573  {
3574  // if key is found, return value and given default value otherwise
3575  const auto it = find(key);
3576  if (it != end())
3577  {
3578  return *it;
3579  }
3580  else
3581  {
3582  return default_value;
3583  }
3584  }
3585  else
3586  {
3587  throw std::domain_error("cannot use value() with " + type_name());
3588  }
3589  }
3590 
3595  string_t value(const typename object_t::key_type& key, const char* default_value) const
3596  {
3597  return value(key, string_t(default_value));
3598  }
3599 
3625  {
3626  return *begin();
3627  }
3628 
3633  {
3634  return *cbegin();
3635  }
3636 
3667  {
3668  auto tmp = end();
3669  --tmp;
3670  return *tmp;
3671  }
3672 
3677  {
3678  auto tmp = cend();
3679  --tmp;
3680  return *tmp;
3681  }
3682 
3728  template <class InteratorType, typename
3729  std::enable_if<
3730  std::is_same<InteratorType, typename basic_json_t::iterator>::value or
3731  std::is_same<InteratorType, typename basic_json_t::const_iterator>::value
3732  , int>::type
3733  = 0>
3734  InteratorType erase(InteratorType pos)
3735  {
3736  // make sure iterator fits the current value
3737  if (this != pos.m_object)
3738  {
3739  throw std::domain_error("iterator does not fit current value");
3740  }
3741 
3742  InteratorType result = end();
3743 
3744  switch (m_type)
3745  {
3746  case value_t::boolean:
3747  case value_t::number_float:
3750  case value_t::string:
3751  {
3752  if (not pos.m_it.primitive_iterator.is_begin())
3753  {
3754  throw std::out_of_range("iterator out of range");
3755  }
3756 
3757  if (is_string())
3758  {
3759  delete m_value.string;
3760  m_value.string = nullptr;
3761  }
3762 
3763  m_type = value_t::null;
3764  break;
3765  }
3766 
3767  case value_t::object:
3768  {
3769  assert(m_value.object != nullptr);
3770  result.m_it.object_iterator = m_value.object->erase(pos.m_it.object_iterator);
3771  break;
3772  }
3773 
3774  case value_t::array:
3775  {
3776  assert(m_value.array != nullptr);
3777  result.m_it.array_iterator = m_value.array->erase(pos.m_it.array_iterator);
3778  break;
3779  }
3780 
3781  default:
3782  {
3783  throw std::domain_error("cannot use erase() with " + type_name());
3784  }
3785  }
3786 
3787  return result;
3788  }
3789 
3836  template <class InteratorType, typename
3837  std::enable_if<
3838  std::is_same<InteratorType, typename basic_json_t::iterator>::value or
3839  std::is_same<InteratorType, typename basic_json_t::const_iterator>::value
3840  , int>::type
3841  = 0>
3842  InteratorType erase(InteratorType first, InteratorType last)
3843  {
3844  // make sure iterator fits the current value
3845  if (this != first.m_object or this != last.m_object)
3846  {
3847  throw std::domain_error("iterators do not fit current value");
3848  }
3849 
3850  InteratorType result = end();
3851 
3852  switch (m_type)
3853  {
3854  case value_t::boolean:
3855  case value_t::number_float:
3858  case value_t::string:
3859  {
3860  if (not first.m_it.primitive_iterator.is_begin() or not last.m_it.primitive_iterator.is_end())
3861  {
3862  throw std::out_of_range("iterators out of range");
3863  }
3864 
3865  if (is_string())
3866  {
3867  delete m_value.string;
3868  m_value.string = nullptr;
3869  }
3870 
3871  m_type = value_t::null;
3872  break;
3873  }
3874 
3875  case value_t::object:
3876  {
3877  assert(m_value.object != nullptr);
3878  result.m_it.object_iterator = m_value.object->erase(first.m_it.object_iterator,
3879  last.m_it.object_iterator);
3880  break;
3881  }
3882 
3883  case value_t::array:
3884  {
3885  assert(m_value.array != nullptr);
3886  result.m_it.array_iterator = m_value.array->erase(first.m_it.array_iterator,
3887  last.m_it.array_iterator);
3888  break;
3889  }
3890 
3891  default:
3892  {
3893  throw std::domain_error("cannot use erase() with " + type_name());
3894  }
3895  }
3896 
3897  return result;
3898  }
3899 
3929  size_type erase(const typename object_t::key_type& key)
3930  {
3931  // this erase only works for objects
3932  if (is_object())
3933  {
3934  assert(m_value.object != nullptr);
3935  return m_value.object->erase(key);
3936  }
3937  else
3938  {
3939  throw std::domain_error("cannot use erase() with " + type_name());
3940  }
3941  }
3942 
3967  void erase(const size_type idx)
3968  {
3969  // this erase only works for arrays
3970  if (is_array())
3971  {
3972  if (idx >= size())
3973  {
3974  throw std::out_of_range("index out of range");
3975  }
3976 
3977  assert(m_value.array != nullptr);
3978  m_value.array->erase(m_value.array->begin() + static_cast<difference_type>(idx));
3979  }
3980  else
3981  {
3982  throw std::domain_error("cannot use erase() with " + type_name());
3983  }
3984  }
3985 
3987 
3988 
3990  // lookup //
3992 
3995 
4013  iterator find(typename object_t::key_type key)
4014  {
4015  auto result = end();
4016 
4017  if (is_object())
4018  {
4019  assert(m_value.object != nullptr);
4020  result.m_it.object_iterator = m_value.object->find(key);
4021  }
4022 
4023  return result;
4024  }
4025 
4030  const_iterator find(typename object_t::key_type key) const
4031  {
4032  auto result = cend();
4033 
4034  if (is_object())
4035  {
4036  assert(m_value.object != nullptr);
4037  result.m_it.object_iterator = m_value.object->find(key);
4038  }
4039 
4040  return result;
4041  }
4042 
4061  size_type count(typename object_t::key_type key) const
4062  {
4063  // return 0 for all nonobject types
4064  assert(not is_object() or m_value.object != nullptr);
4065  return is_object() ? m_value.object->count(key) : 0;
4066  }
4067 
4069 
4070 
4072  // iterators //
4074 
4077 
4102  iterator begin() noexcept
4103  {
4104  iterator result(this);
4105  result.set_begin();
4106  return result;
4107  }
4108 
4112  const_iterator begin() const noexcept
4113  {
4114  return cbegin();
4115  }
4116 
4142  const_iterator cbegin() const noexcept
4143  {
4144  const_iterator result(this);
4145  result.set_begin();
4146  return result;
4147  }
4148 
4173  iterator end() noexcept
4174  {
4175  iterator result(this);
4176  result.set_end();
4177  return result;
4178  }
4179 
4183  const_iterator end() const noexcept
4184  {
4185  return cend();
4186  }
4187 
4213  const_iterator cend() const noexcept
4214  {
4215  const_iterator result(this);
4216  result.set_end();
4217  return result;
4218  }
4219 
4244  {
4245  return reverse_iterator(end());
4246  }
4247 
4252  {
4253  return crbegin();
4254  }
4255 
4281  {
4282  return reverse_iterator(begin());
4283  }
4284 
4288  const_reverse_iterator rend() const noexcept
4289  {
4290  return crend();
4291  }
4292 
4318  {
4319  return const_reverse_iterator(cend());
4320  }
4321 
4347  {
4348  return const_reverse_iterator(cbegin());
4349  }
4350 
4351  private:
4352  // forward declaration
4353  template<typename IteratorType> class iteration_proxy;
4354 
4355  public:
4367  static iteration_proxy<iterator> iterator_wrapper(reference cont)
4368  {
4369  return iteration_proxy<iterator>(cont);
4370  }
4371 
4375  static iteration_proxy<const_iterator> iterator_wrapper(const_reference cont)
4376  {
4377  return iteration_proxy<const_iterator>(cont);
4378  }
4379 
4381 
4382 
4384  // capacity //
4386 
4389 
4423  bool empty() const noexcept
4424  {
4425  switch (m_type)
4426  {
4427  case value_t::null:
4428  {
4429  // null values are empty
4430  return true;
4431  }
4432 
4433  case value_t::array:
4434  {
4435  assert(m_value.array != nullptr);
4436  return m_value.array->empty();
4437  }
4438 
4439  case value_t::object:
4440  {
4441  assert(m_value.object != nullptr);
4442  return m_value.object->empty();
4443  }
4444 
4445  default:
4446  {
4447  // all other types are nonempty
4448  return false;
4449  }
4450  }
4451  }
4452 
4486  size_type size() const noexcept
4487  {
4488  switch (m_type)
4489  {
4490  case value_t::null:
4491  {
4492  // null values are empty
4493  return 0;
4494  }
4495 
4496  case value_t::array:
4497  {
4498  assert(m_value.array != nullptr);
4499  return m_value.array->size();
4500  }
4501 
4502  case value_t::object:
4503  {
4504  assert(m_value.object != nullptr);
4505  return m_value.object->size();
4506  }
4507 
4508  default:
4509  {
4510  // all other types have size 1
4511  return 1;
4512  }
4513  }
4514  }
4515 
4552  size_type max_size() const noexcept
4553  {
4554  switch (m_type)
4555  {
4556  case value_t::array:
4557  {
4558  assert(m_value.array != nullptr);
4559  return m_value.array->max_size();
4560  }
4561 
4562  case value_t::object:
4563  {
4564  assert(m_value.object != nullptr);
4565  return m_value.object->max_size();
4566  }
4567 
4568  default:
4569  {
4570  // all other types have max_size() == size()
4571  return size();
4572  }
4573  }
4574  }
4575 
4577 
4578 
4580  // modifiers //
4582 
4585 
4611  void clear() noexcept
4612  {
4613  switch (m_type)
4614  {
4616  {
4617  m_value.number_integer = 0;
4618  break;
4619  }
4620 
4622  {
4623  m_value.number_unsigned = 0;
4624  break;
4625  }
4626 
4627  case value_t::number_float:
4628  {
4629  m_value.number_float = 0.0;
4630  break;
4631  }
4632 
4633  case value_t::boolean:
4634  {
4635  m_value.boolean = false;
4636  break;
4637  }
4638 
4639  case value_t::string:
4640  {
4641  assert(m_value.string != nullptr);
4642  m_value.string->clear();
4643  break;
4644  }
4645 
4646  case value_t::array:
4647  {
4648  assert(m_value.array != nullptr);
4649  m_value.array->clear();
4650  break;
4651  }
4652 
4653  case value_t::object:
4654  {
4655  assert(m_value.object != nullptr);
4656  m_value.object->clear();
4657  break;
4658  }
4659 
4660  default:
4661  {
4662  break;
4663  }
4664  }
4665  }
4666 
4687  void push_back(basic_json&& val)
4688  {
4689  // push_back only works for null objects or arrays
4690  if (not(is_null() or is_array()))
4691  {
4692  throw std::domain_error("cannot use push_back() with " + type_name());
4693  }
4694 
4695  // transform null object into an array
4696  if (is_null())
4697  {
4698  m_type = value_t::array;
4699  m_value = value_t::array;
4700  }
4701 
4702  // add element to array (move semantics)
4703  assert(m_value.array != nullptr);
4704  m_value.array->push_back(std::move(val));
4705  // invalidate object
4706  val.m_type = value_t::null;
4707  }
4708 
4713  reference operator+=(basic_json&& val)
4714  {
4715  push_back(std::move(val));
4716  return *this;
4717  }
4718 
4723  void push_back(const basic_json& val)
4724  {
4725  // push_back only works for null objects or arrays
4726  if (not(is_null() or is_array()))
4727  {
4728  throw std::domain_error("cannot use push_back() with " + type_name());
4729  }
4730 
4731  // transform null object into an array
4732  if (is_null())
4733  {
4734  m_type = value_t::array;
4735  m_value = value_t::array;
4736  }
4737 
4738  // add element to array
4739  assert(m_value.array != nullptr);
4740  m_value.array->push_back(val);
4741  }
4742 
4747  reference operator+=(const basic_json& val)
4748  {
4749  push_back(val);
4750  return *this;
4751  }
4752 
4773  void push_back(const typename object_t::value_type& val)
4774  {
4775  // push_back only works for null objects or objects
4776  if (not(is_null() or is_object()))
4777  {
4778  throw std::domain_error("cannot use push_back() with " + type_name());
4779  }
4780 
4781  // transform null object into an object
4782  if (is_null())
4783  {
4784  m_type = value_t::object;
4785  m_value = value_t::object;
4786  }
4787 
4788  // add element to array
4789  assert(m_value.object != nullptr);
4790  m_value.object->insert(val);
4791  }
4792 
4797  reference operator+=(const typename object_t::value_type& val)
4798  {
4799  push_back(val);
4800  return operator[](val.first);
4801  }
4802 
4825  iterator insert(const_iterator pos, const basic_json& val)
4826  {
4827  // insert only works for arrays
4828  if (is_array())
4829  {
4830  // check if iterator pos fits to this JSON value
4831  if (pos.m_object != this)
4832  {
4833  throw std::domain_error("iterator does not fit current value");
4834  }
4835 
4836  // insert to array and return iterator
4837  iterator result(this);
4838  assert(m_value.array != nullptr);
4839  result.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator, val);
4840  return result;
4841  }
4842  else
4843  {
4844  throw std::domain_error("cannot use insert() with " + type_name());
4845  }
4846  }
4847 
4852  iterator insert(const_iterator pos, basic_json&& val)
4853  {
4854  return insert(pos, val);
4855  }
4856 
4881  iterator insert(const_iterator pos, size_type cnt, const basic_json& val)
4882  {
4883  // insert only works for arrays
4884  if (is_array())
4885  {
4886  // check if iterator pos fits to this JSON value
4887  if (pos.m_object != this)
4888  {
4889  throw std::domain_error("iterator does not fit current value");
4890  }
4891 
4892  // insert to array and return iterator
4893  iterator result(this);
4894  assert(m_value.array != nullptr);
4895  result.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator, cnt, val);
4896  return result;
4897  }
4898  else
4899  {
4900  throw std::domain_error("cannot use insert() with " + type_name());
4901  }
4902  }
4903 
4935  {
4936  // insert only works for arrays
4937  if (not is_array())
4938  {
4939  throw std::domain_error("cannot use insert() with " + type_name());
4940  }
4941 
4942  // check if iterator pos fits to this JSON value
4943  if (pos.m_object != this)
4944  {
4945  throw std::domain_error("iterator does not fit current value");
4946  }
4947 
4948  if (first.m_object != last.m_object)
4949  {
4950  throw std::domain_error("iterators do not fit");
4951  }
4952 
4953  if (first.m_object == this or last.m_object == this)
4954  {
4955  throw std::domain_error("passed iterators may not belong to container");
4956  }
4957 
4958  // insert to array and return iterator
4959  iterator result(this);
4960  assert(m_value.array != nullptr);
4961  result.m_it.array_iterator = m_value.array->insert(
4962  pos.m_it.array_iterator,
4963  first.m_it.array_iterator,
4964  last.m_it.array_iterator);
4965  return result;
4966  }
4967 
4992  iterator insert(const_iterator pos, std::initializer_list<basic_json> ilist)
4993  {
4994  // insert only works for arrays
4995  if (not is_array())
4996  {
4997  throw std::domain_error("cannot use insert() with " + type_name());
4998  }
4999 
5000  // check if iterator pos fits to this JSON value
5001  if (pos.m_object != this)
5002  {
5003  throw std::domain_error("iterator does not fit current value");
5004  }
5005 
5006  // insert to array and return iterator
5007  iterator result(this);
5008  assert(m_value.array != nullptr);
5009  result.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator, ilist);
5010  return result;
5011  }
5012 
5030  void swap(reference other) noexcept (
5031  std::is_nothrow_move_constructible<value_t>::value and
5032  std::is_nothrow_move_assignable<value_t>::value and
5033  std::is_nothrow_move_constructible<json_value>::value and
5034  std::is_nothrow_move_assignable<json_value>::value
5035  )
5036  {
5037  std::swap(m_type, other.m_type);
5038  std::swap(m_value, other.m_value);
5039  }
5040 
5061  void swap(array_t& other)
5062  {
5063  // swap only works for arrays
5064  if (is_array())
5065  {
5066  assert(m_value.array != nullptr);
5067  std::swap(*(m_value.array), other);
5068  }
5069  else
5070  {
5071  throw std::domain_error("cannot use swap() with " + type_name());
5072  }
5073  }
5074 
5095  void swap(object_t& other)
5096  {
5097  // swap only works for objects
5098  if (is_object())
5099  {
5100  assert(m_value.object != nullptr);
5101  std::swap(*(m_value.object), other);
5102  }
5103  else
5104  {
5105  throw std::domain_error("cannot use swap() with " + type_name());
5106  }
5107  }
5108 
5129  void swap(string_t& other)
5130  {
5131  // swap only works for strings
5132  if (is_string())
5133  {
5134  assert(m_value.string != nullptr);
5135  std::swap(*(m_value.string), other);
5136  }
5137  else
5138  {
5139  throw std::domain_error("cannot use swap() with " + type_name());
5140  }
5141  }
5142 
5144 
5145 
5147  // lexicographical comparison operators //
5149 
5152 
5153  private:
5163  friend bool operator<(const value_t lhs, const value_t rhs) noexcept
5164  {
5165  static constexpr std::array<uint8_t, 8> order = {{
5166  0, // null
5167  3, // object
5168  4, // array
5169  5, // string
5170  1, // boolean
5171  2, // integer
5172  2, // unsigned
5173  2, // float
5174  }
5175  };
5176 
5177  // discarded values are not comparable
5178  if (lhs == value_t::discarded or rhs == value_t::discarded)
5179  {
5180  return false;
5181  }
5182 
5183  return order[static_cast<std::size_t>(lhs)] < order[static_cast<std::size_t>(rhs)];
5184  }
5185 
5186  public:
5210  friend bool operator==(const_reference lhs, const_reference rhs) noexcept
5211  {
5212  const auto lhs_type = lhs.type();
5213  const auto rhs_type = rhs.type();
5214 
5215  if (lhs_type == rhs_type)
5216  {
5217  switch (lhs_type)
5218  {
5219  case value_t::array:
5220  {
5221  assert(lhs.m_value.array != nullptr);
5222  assert(rhs.m_value.array != nullptr);
5223  return *lhs.m_value.array == *rhs.m_value.array;
5224  }
5225  case value_t::object:
5226  {
5227  assert(lhs.m_value.object != nullptr);
5228  assert(rhs.m_value.object != nullptr);
5229  return *lhs.m_value.object == *rhs.m_value.object;
5230  }
5231  case value_t::null:
5232  {
5233  return true;
5234  }
5235  case value_t::string:
5236  {
5237  assert(lhs.m_value.string != nullptr);
5238  assert(rhs.m_value.string != nullptr);
5239  return *lhs.m_value.string == *rhs.m_value.string;
5240  }
5241  case value_t::boolean:
5242  {
5243  return lhs.m_value.boolean == rhs.m_value.boolean;
5244  }
5246  {
5247  return lhs.m_value.number_integer == rhs.m_value.number_integer;
5248  }
5250  {
5251  return lhs.m_value.number_unsigned == rhs.m_value.number_unsigned;
5252  }
5253  case value_t::number_float:
5254  {
5255  return lhs.m_value.number_float == rhs.m_value.number_float;
5256  }
5257  default:
5258  {
5259  return false;
5260  }
5261  }
5262  }
5263  else if (lhs_type == value_t::number_integer and rhs_type == value_t::number_float)
5264  {
5265  return static_cast<number_float_t>(lhs.m_value.number_integer) == rhs.m_value.number_float;
5266  }
5267  else if (lhs_type == value_t::number_float and rhs_type == value_t::number_integer)
5268  {
5269  return lhs.m_value.number_float == static_cast<number_float_t>(rhs.m_value.number_integer);
5270  }
5271  else if (lhs_type == value_t::number_unsigned and rhs_type == value_t::number_float)
5272  {
5273  return static_cast<number_float_t>(lhs.m_value.number_unsigned) == rhs.m_value.number_float;
5274  }
5275  else if (lhs_type == value_t::number_float and rhs_type == value_t::number_unsigned)
5276  {
5277  return lhs.m_value.number_float == static_cast<number_float_t>(rhs.m_value.number_unsigned);
5278  }
5279  else if (lhs_type == value_t::number_unsigned and rhs_type == value_t::number_integer)
5280  {
5281  return static_cast<number_integer_t>(lhs.m_value.number_unsigned) == rhs.m_value.number_integer;
5282  }
5283  else if (lhs_type == value_t::number_integer and rhs_type == value_t::number_unsigned)
5284  {
5285  return lhs.m_value.number_integer == static_cast<number_integer_t>(rhs.m_value.number_unsigned);
5286  }
5287 
5288  return false;
5289  }
5290 
5309  friend bool operator==(const_reference v, std::nullptr_t) noexcept
5310  {
5311  return v.is_null();
5312  }
5313 
5318  friend bool operator==(std::nullptr_t, const_reference v) noexcept
5319  {
5320  return v.is_null();
5321  }
5322 
5339  friend bool operator!=(const_reference lhs, const_reference rhs) noexcept
5340  {
5341  return not (lhs == rhs);
5342  }
5343 
5362  friend bool operator!=(const_reference v, std::nullptr_t) noexcept
5363  {
5364  return not v.is_null();
5365  }
5366 
5371  friend bool operator!=(std::nullptr_t, const_reference v) noexcept
5372  {
5373  return not v.is_null();
5374  }
5375 
5400  friend bool operator<(const_reference lhs, const_reference rhs) noexcept
5401  {
5402  const auto lhs_type = lhs.type();
5403  const auto rhs_type = rhs.type();
5404 
5405  if (lhs_type == rhs_type)
5406  {
5407  switch (lhs_type)
5408  {
5409  case value_t::array:
5410  {
5411  assert(lhs.m_value.array != nullptr);
5412  assert(rhs.m_value.array != nullptr);
5413  return *lhs.m_value.array < *rhs.m_value.array;
5414  }
5415  case value_t::object:
5416  {
5417  assert(lhs.m_value.object != nullptr);
5418  assert(rhs.m_value.object != nullptr);
5419  return *lhs.m_value.object < *rhs.m_value.object;
5420  }
5421  case value_t::null:
5422  {
5423  return false;
5424  }
5425  case value_t::string:
5426  {
5427  assert(lhs.m_value.string != nullptr);
5428  assert(rhs.m_value.string != nullptr);
5429  return *lhs.m_value.string < *rhs.m_value.string;
5430  }
5431  case value_t::boolean:
5432  {
5433  return lhs.m_value.boolean < rhs.m_value.boolean;
5434  }
5436  {
5437  return lhs.m_value.number_integer < rhs.m_value.number_integer;
5438  }
5440  {
5441  return lhs.m_value.number_unsigned < rhs.m_value.number_unsigned;
5442  }
5443  case value_t::number_float:
5444  {
5445  return lhs.m_value.number_float < rhs.m_value.number_float;
5446  }
5447  default:
5448  {
5449  return false;
5450  }
5451  }
5452  }
5453  else if (lhs_type == value_t::number_integer and rhs_type == value_t::number_float)
5454  {
5455  return static_cast<number_float_t>(lhs.m_value.number_integer) < rhs.m_value.number_float;
5456  }
5457  else if (lhs_type == value_t::number_float and rhs_type == value_t::number_integer)
5458  {
5459  return lhs.m_value.number_float < static_cast<number_float_t>(rhs.m_value.number_integer);
5460  }
5461  else if (lhs_type == value_t::number_unsigned and rhs_type == value_t::number_float)
5462  {
5463  return static_cast<number_float_t>(lhs.m_value.number_unsigned) < rhs.m_value.number_float;
5464  }
5465  else if (lhs_type == value_t::number_float and rhs_type == value_t::number_unsigned)
5466  {
5467  return lhs.m_value.number_float < static_cast<number_float_t>(rhs.m_value.number_unsigned);
5468  }
5469  else if (lhs_type == value_t::number_integer and rhs_type == value_t::number_unsigned)
5470  {
5471  return lhs.m_value.number_integer < static_cast<number_integer_t>(rhs.m_value.number_unsigned);
5472  }
5473  else if (lhs_type == value_t::number_unsigned and rhs_type == value_t::number_integer)
5474  {
5475  return static_cast<number_integer_t>(lhs.m_value.number_unsigned) < rhs.m_value.number_integer;
5476  }
5477 
5478  // We only reach this line if we cannot compare values. In that case,
5479  // we compare types. Note we have to call the operator explicitly,
5480  // because MSVC has problems otherwise.
5481  return operator<(lhs_type, rhs_type);
5482  }
5483 
5501  friend bool operator<=(const_reference lhs, const_reference rhs) noexcept
5502  {
5503  return not (rhs < lhs);
5504  }
5505 
5523  friend bool operator>(const_reference lhs, const_reference rhs) noexcept
5524  {
5525  return not (lhs <= rhs);
5526  }
5527 
5545  friend bool operator>=(const_reference lhs, const_reference rhs) noexcept
5546  {
5547  return not (lhs < rhs);
5548  }
5549 
5551 
5552 
5554  // serialization //
5556 
5559 
5582  friend std::ostream& operator<<(std::ostream& o, const basic_json& j)
5583  {
5584  // read width member and use it as indentation parameter if nonzero
5585  const bool pretty_print = (o.width() > 0);
5586  const auto indentation = (pretty_print ? o.width() : 0);
5587 
5588  // reset width to 0 for subsequent calls to this stream
5589  o.width(0);
5590 
5591  // do the actual serialization
5592  j.dump(o, pretty_print, static_cast<unsigned int>(indentation));
5593  return o;
5594  }
5595 
5600  friend std::ostream& operator>>(const basic_json& j, std::ostream& o)
5601  {
5602  return o << j;
5603  }
5604 
5606 
5607 
5609  // deserialization //
5611 
5614 
5639  static basic_json parse(const string_t& s, parser_callback_t cb = nullptr)
5640  {
5641  return parser(s, cb).parse();
5642  }
5643 
5668  static basic_json parse(std::istream& i, parser_callback_t cb = nullptr)
5669  {
5670  return parser(i, cb).parse();
5671  }
5672 
5676  static basic_json parse(std::istream&& i, parser_callback_t cb = nullptr)
5677  {
5678  return parser(i, cb).parse();
5679  }
5680 
5704  friend std::istream& operator<<(basic_json& j, std::istream& i)
5705  {
5706  j = parser(i).parse();
5707  return i;
5708  }
5709 
5714  friend std::istream& operator>>(std::istream& i, basic_json& j)
5715  {
5716  j = parser(i).parse();
5717  return i;
5718  }
5719 
5721 
5722 
5723  private:
5725  // convenience functions //
5727 
5729  string_t type_name() const noexcept
5730  {
5731  switch (m_type)
5732  {
5733  case value_t::null:
5734  return "null";
5735  case value_t::object:
5736  return "object";
5737  case value_t::array:
5738  return "array";
5739  case value_t::string:
5740  return "string";
5741  case value_t::boolean:
5742  return "boolean";
5743  case value_t::discarded:
5744  return "discarded";
5745  default:
5746  return "number";
5747  }
5748  }
5749 
5758  static std::size_t extra_space(const string_t& s) noexcept
5759  {
5760  std::size_t result = 0;
5761 
5762  for (const auto& c : s)
5763  {
5764  switch (c)
5765  {
5766  case '"':
5767  case '\\':
5768  case '\b':
5769  case '\f':
5770  case '\n':
5771  case '\r':
5772  case '\t':
5773  {
5774  // from c (1 byte) to \x (2 bytes)
5775  result += 1;
5776  break;
5777  }
5778 
5779  default:
5780  {
5781  if (c >= 0x00 and c <= 0x1f)
5782  {
5783  // from c (1 byte) to \uxxxx (6 bytes)
5784  result += 5;
5785  }
5786  break;
5787  }
5788  }
5789  }
5790 
5791  return result;
5792  }
5793 
5807  static string_t escape_string(const string_t& s)
5808  {
5809  const auto space = extra_space(s);
5810  if (space == 0)
5811  {
5812  return s;
5813  }
5814 
5815  // create a result string of necessary size
5816  string_t result(s.size() + space, '\\');
5817  std::size_t pos = 0;
5818 
5819  for (const auto& c : s)
5820  {
5821  switch (c)
5822  {
5823  // quotation mark (0x22)
5824  case '"':
5825  {
5826  result[pos + 1] = '"';
5827  pos += 2;
5828  break;
5829  }
5830 
5831  // reverse solidus (0x5c)
5832  case '\\':
5833  {
5834  // nothing to change
5835  pos += 2;
5836  break;
5837  }
5838 
5839  // backspace (0x08)
5840  case '\b':
5841  {
5842  result[pos + 1] = 'b';
5843  pos += 2;
5844  break;
5845  }
5846 
5847  // formfeed (0x0c)
5848  case '\f':
5849  {
5850  result[pos + 1] = 'f';
5851  pos += 2;
5852  break;
5853  }
5854 
5855  // newline (0x0a)
5856  case '\n':
5857  {
5858  result[pos + 1] = 'n';
5859  pos += 2;
5860  break;
5861  }
5862 
5863  // carriage return (0x0d)
5864  case '\r':
5865  {
5866  result[pos + 1] = 'r';
5867  pos += 2;
5868  break;
5869  }
5870 
5871  // horizontal tab (0x09)
5872  case '\t':
5873  {
5874  result[pos + 1] = 't';
5875  pos += 2;
5876  break;
5877  }
5878 
5879  default:
5880  {
5881  if (c >= 0x00 and c <= 0x1f)
5882  {
5883  // convert a number 0..15 to its hex representation
5884  // (0..f)
5885  auto hexify = [](const char v) -> char
5886  {
5887  return (v < 10) ? ('0' + v) : ('a' + v - 10);
5888  };
5889 
5890  // print character c as \uxxxx
5891  for (const char m :
5892  { 'u', '0', '0', hexify(c >> 4), hexify(c & 0x0f)
5893  })
5894  {
5895  result[++pos] = m;
5896  }
5897 
5898  ++pos;
5899  }
5900  else
5901  {
5902  // all other characters are added as-is
5903  result[pos++] = c;
5904  }
5905  break;
5906  }
5907  }
5908  }
5909 
5910  return result;
5911  }
5912 
5930  void dump(std::ostream& o,
5931  const bool pretty_print,
5932  const unsigned int indent_step,
5933  const unsigned int current_indent = 0) const
5934  {
5935  // variable to hold indentation for recursive calls
5936  unsigned int new_indent = current_indent;
5937 
5938  switch (m_type)
5939  {
5940  case value_t::object:
5941  {
5942  assert(m_value.object != nullptr);
5943 
5944  if (m_value.object->empty())
5945  {
5946  o << "{}";
5947  return;
5948  }
5949 
5950  o << "{";
5951 
5952  // increase indentation
5953  if (pretty_print)
5954  {
5955  new_indent += indent_step;
5956  o << "\n";
5957  }
5958 
5959  for (auto i = m_value.object->cbegin(); i != m_value.object->cend(); ++i)
5960  {
5961  if (i != m_value.object->cbegin())
5962  {
5963  o << (pretty_print ? ",\n" : ",");
5964  }
5965  o << string_t(new_indent, ' ') << "\""
5966  << escape_string(i->first) << "\":"
5967  << (pretty_print ? " " : "");
5968  i->second.dump(o, pretty_print, indent_step, new_indent);
5969  }
5970 
5971  // decrease indentation
5972  if (pretty_print)
5973  {
5974  new_indent -= indent_step;
5975  o << "\n";
5976  }
5977 
5978  o << string_t(new_indent, ' ') + "}";
5979  return;
5980  }
5981 
5982  case value_t::array:
5983  {
5984  assert(m_value.array != nullptr);
5985 
5986  if (m_value.array->empty())
5987  {
5988  o << "[]";
5989  return;
5990  }
5991 
5992  o << "[";
5993 
5994  // increase indentation
5995  if (pretty_print)
5996  {
5997  new_indent += indent_step;
5998  o << "\n";
5999  }
6000 
6001  for (auto i = m_value.array->cbegin(); i != m_value.array->cend(); ++i)
6002  {
6003  if (i != m_value.array->cbegin())
6004  {
6005  o << (pretty_print ? ",\n" : ",");
6006  }
6007  o << string_t(new_indent, ' ');
6008  i->dump(o, pretty_print, indent_step, new_indent);
6009  }
6010 
6011  // decrease indentation
6012  if (pretty_print)
6013  {
6014  new_indent -= indent_step;
6015  o << "\n";
6016  }
6017 
6018  o << string_t(new_indent, ' ') << "]";
6019  return;
6020  }
6021 
6022  case value_t::string:
6023  {
6024  assert(m_value.string != nullptr);
6025  o << string_t("\"") << escape_string(*m_value.string) << "\"";
6026  return;
6027  }
6028 
6029  case value_t::boolean:
6030  {
6031  o << (m_value.boolean ? "true" : "false");
6032  return;
6033  }
6034 
6036  {
6037  o << m_value.number_integer;
6038  return;
6039  }
6040 
6042  {
6043  o << m_value.number_unsigned;
6044  return;
6045  }
6046 
6047  case value_t::number_float:
6048  {
6049  // If the number is an integer then output as a fixed with with
6050  // precision 1 to output "0.0", "1.0" etc as expected for some
6051  // round trip tests otherwise 15 digits of precision allows
6052  // round-trip IEEE 754 string->double->string; to be safe, we
6053  // read this value from
6054  // std::numeric_limits<number_float_t>::digits10
6055  if (std::fmod(m_value.number_float, 1) == 0)
6056  {
6057  o << std::fixed << std::setprecision(1);
6058  }
6059  else
6060  {
6061  // std::defaultfloat not supported in gcc version < 5
6062  o.unsetf(std::ios_base::floatfield);
6063  o << std::setprecision(std::numeric_limits<double>::digits10);
6064  }
6065  o << m_value.number_float;
6066  return;
6067  }
6068 
6069  case value_t::discarded:
6070  {
6071  o << "<discarded>";
6072  return;
6073  }
6074 
6075  case value_t::null:
6076  {
6077  o << "null";
6078  return;
6079  }
6080  }
6081  }
6082 
6083  private:
6085  // member variables //
6087 
6089  value_t m_type = value_t::null;
6090 
6092  json_value m_value = {};
6093 
6094 
6095  private:
6097  // iterators //
6099 
6109  class primitive_iterator_t
6110  {
6111  public:
6113  void set_begin() noexcept
6114  {
6115  m_it = begin_value;
6116  }
6117 
6119  void set_end() noexcept
6120  {
6121  m_it = end_value;
6122  }
6123 
6125  constexpr bool is_begin() const noexcept
6126  {
6127  return (m_it == begin_value);
6128  }
6129 
6131  constexpr bool is_end() const noexcept
6132  {
6133  return (m_it == end_value);
6134  }
6135 
6137  operator difference_type& () noexcept
6138  {
6139  return m_it;
6140  }
6141 
6143  constexpr operator difference_type () const noexcept
6144  {
6145  return m_it;
6146  }
6147 
6148  private:
6149  static constexpr difference_type begin_value = 0;
6150  static constexpr difference_type end_value = begin_value + 1;
6151 
6153  difference_type m_it = std::numeric_limits<std::ptrdiff_t>::denorm_min();
6154  };
6155 
6163  struct internal_iterator
6164  {
6166  typename object_t::iterator object_iterator;
6168  typename array_t::iterator array_iterator;
6170  primitive_iterator_t primitive_iterator;
6171 
6173  internal_iterator() noexcept
6174  : object_iterator(), array_iterator(), primitive_iterator()
6175  {}
6176  };
6177 
6179  template<typename IteratorType>
6180  class iteration_proxy
6181  {
6182  private:
6184  class iteration_proxy_internal
6185  {
6186  private:
6188  IteratorType anchor;
6190  size_t array_index = 0;
6191 
6192  public:
6193  explicit iteration_proxy_internal(IteratorType it) noexcept
6194  : anchor(it)
6195  {}
6196 
6198  iteration_proxy_internal& operator*()
6199  {
6200  return *this;
6201  }
6202 
6204  iteration_proxy_internal& operator++()
6205  {
6206  ++anchor;
6207  ++array_index;
6208 
6209  return *this;
6210  }
6211 
6213  bool operator!= (const iteration_proxy_internal& o) const
6214  {
6215  return anchor != o.anchor;
6216  }
6217 
6219  typename basic_json::string_t key() const
6220  {
6221  assert(anchor.m_object != nullptr);
6222 
6223  switch (anchor.m_object->type())
6224  {
6225  // use integer array index as key
6226  case value_t::array:
6227  {
6228  return std::to_string(array_index);
6229  }
6230 
6231  // use key from the object
6232  case value_t::object:
6233  {
6234  return anchor.key();
6235  }
6236 
6237  // use an empty key for all primitive types
6238  default:
6239  {
6240  return "";
6241  }
6242  }
6243  }
6244 
6246  typename IteratorType::reference value() const
6247  {
6248  return anchor.value();
6249  }
6250  };
6251 
6253  typename IteratorType::reference container;
6254 
6255  public:
6257  explicit iteration_proxy(typename IteratorType::reference cont)
6258  : container(cont)
6259  {}
6260 
6262  iteration_proxy_internal begin() noexcept
6263  {
6264  return iteration_proxy_internal(container.begin());
6265  }
6266 
6268  iteration_proxy_internal end() noexcept
6269  {
6270  return iteration_proxy_internal(container.end());
6271  }
6272  };
6273 
6274  public:
6288  class const_iterator : public std::iterator<std::random_access_iterator_tag, const basic_json>
6289  {
6291  friend class basic_json;
6292 
6293  public:
6303  using iterator_category = std::bidirectional_iterator_tag;
6304 
6306  const_iterator() = default;
6307 
6309  explicit const_iterator(pointer object) noexcept
6310  : m_object(object)
6311  {
6312  assert(m_object != nullptr);
6313 
6314  switch (m_object->m_type)
6315  {
6317  {
6318  m_it.object_iterator = typename object_t::iterator();
6319  break;
6320  }
6321 
6323  {
6324  m_it.array_iterator = typename array_t::iterator();
6325  break;
6326  }
6327 
6328  default:
6329  {
6330  m_it.primitive_iterator = primitive_iterator_t();
6331  break;
6332  }
6333  }
6334  }
6335 
6337  explicit const_iterator(const iterator& other) noexcept
6338  : m_object(other.m_object)
6339  {
6340  assert(m_object != nullptr);
6341 
6342  switch (m_object->m_type)
6343  {
6345  {
6346  m_it.object_iterator = other.m_it.object_iterator;
6347  break;
6348  }
6349 
6351  {
6352  m_it.array_iterator = other.m_it.array_iterator;
6353  break;
6354  }
6355 
6356  default:
6357  {
6358  m_it.primitive_iterator = other.m_it.primitive_iterator;
6359  break;
6360  }
6361  }
6362  }
6363 
6365  const_iterator(const const_iterator& other) noexcept
6366  : m_object(other.m_object), m_it(other.m_it)
6367  {}
6368 
6371  std::is_nothrow_move_constructible<pointer>::value and
6372  std::is_nothrow_move_assignable<pointer>::value and
6373  std::is_nothrow_move_constructible<internal_iterator>::value and
6374  std::is_nothrow_move_assignable<internal_iterator>::value
6375  )
6376  {
6377  std::swap(m_object, other.m_object);
6378  std::swap(m_it, other.m_it);
6379  return *this;
6380  }
6381 
6382  private:
6384  void set_begin() noexcept
6385  {
6386  assert(m_object != nullptr);
6387 
6388  switch (m_object->m_type)
6389  {
6391  {
6392  assert(m_object->m_value.object != nullptr);
6393  m_it.object_iterator = m_object->m_value.object->begin();
6394  break;
6395  }
6396 
6398  {
6399  assert(m_object->m_value.array != nullptr);
6400  m_it.array_iterator = m_object->m_value.array->begin();
6401  break;
6402  }
6403 
6405  {
6406  // set to end so begin()==end() is true: null is empty
6407  m_it.primitive_iterator.set_end();
6408  break;
6409  }
6410 
6411  default:
6412  {
6413  m_it.primitive_iterator.set_begin();
6414  break;
6415  }
6416  }
6417  }
6418 
6420  void set_end() noexcept
6421  {
6422  assert(m_object != nullptr);
6423 
6424  switch (m_object->m_type)
6425  {
6427  {
6428  assert(m_object->m_value.object != nullptr);
6429  m_it.object_iterator = m_object->m_value.object->end();
6430  break;
6431  }
6432 
6434  {
6435  assert(m_object->m_value.array != nullptr);
6436  m_it.array_iterator = m_object->m_value.array->end();
6437  break;
6438  }
6439 
6440  default:
6441  {
6442  m_it.primitive_iterator.set_end();
6443  break;
6444  }
6445  }
6446  }
6447 
6448  public:
6451  {
6452  assert(m_object != nullptr);
6453 
6454  switch (m_object->m_type)
6455  {
6457  {
6458  assert(m_object->m_value.object);
6459  assert(m_it.object_iterator != m_object->m_value.object->end());
6460  return m_it.object_iterator->second;
6461  }
6462 
6464  {
6465  assert(m_object->m_value.array);
6466  assert(m_it.array_iterator != m_object->m_value.array->end());
6467  return *m_it.array_iterator;
6468  }
6469 
6471  {
6472  throw std::out_of_range("cannot get value");
6473  }
6474 
6475  default:
6476  {
6477  if (m_it.primitive_iterator.is_begin())
6478  {
6479  return *m_object;
6480  }
6481  else
6482  {
6483  throw std::out_of_range("cannot get value");
6484  }
6485  }
6486  }
6487  }
6488 
6491  {
6492  assert(m_object != nullptr);
6493 
6494  switch (m_object->m_type)
6495  {
6497  {
6498  assert(m_object->m_value.object);
6499  assert(m_it.object_iterator != m_object->m_value.object->end());
6500  return &(m_it.object_iterator->second);
6501  }
6502 
6504  {
6505  assert(m_object->m_value.array);
6506  assert(m_it.array_iterator != m_object->m_value.array->end());
6507  return &*m_it.array_iterator;
6508  }
6509 
6510  default:
6511  {
6512  if (m_it.primitive_iterator.is_begin())
6513  {
6514  return m_object;
6515  }
6516  else
6517  {
6518  throw std::out_of_range("cannot get value");
6519  }
6520  }
6521  }
6522  }
6523 
6526  {
6527  auto result = *this;
6528  ++(*this);
6529  return result;
6530  }
6531 
6534  {
6535  assert(m_object != nullptr);
6536 
6537  switch (m_object->m_type)
6538  {
6540  {
6541  ++m_it.object_iterator;
6542  break;
6543  }
6544 
6546  {
6547  ++m_it.array_iterator;
6548  break;
6549  }
6550 
6551  default:
6552  {
6553  ++m_it.primitive_iterator;
6554  break;
6555  }
6556  }
6557 
6558  return *this;
6559  }
6560 
6563  {
6564  auto result = *this;
6565  --(*this);
6566  return result;
6567  }
6568 
6571  {
6572  assert(m_object != nullptr);
6573 
6574  switch (m_object->m_type)
6575  {
6577  {
6578  --m_it.object_iterator;
6579  break;
6580  }
6581 
6583  {
6584  --m_it.array_iterator;
6585  break;
6586  }
6587 
6588  default:
6589  {
6590  --m_it.primitive_iterator;
6591  break;
6592  }
6593  }
6594 
6595  return *this;
6596  }
6597 
6599  bool operator==(const const_iterator& other) const
6600  {
6601  // if objects are not the same, the comparison is undefined
6602  if (m_object != other.m_object)
6603  {
6604  throw std::domain_error("cannot compare iterators of different containers");
6605  }
6606 
6607  assert(m_object != nullptr);
6608 
6609  switch (m_object->m_type)
6610  {
6612  {
6613  return (m_it.object_iterator == other.m_it.object_iterator);
6614  }
6615 
6617  {
6618  return (m_it.array_iterator == other.m_it.array_iterator);
6619  }
6620 
6621  default:
6622  {
6623  return (m_it.primitive_iterator == other.m_it.primitive_iterator);
6624  }
6625  }
6626  }
6627 
6629  bool operator!=(const const_iterator& other) const
6630  {
6631  return not operator==(other);
6632  }
6633 
6635  bool operator<(const const_iterator& other) const
6636  {
6637  // if objects are not the same, the comparison is undefined
6638  if (m_object != other.m_object)
6639  {
6640  throw std::domain_error("cannot compare iterators of different containers");
6641  }
6642 
6643  assert(m_object != nullptr);
6644 
6645  switch (m_object->m_type)
6646  {
6648  {
6649  throw std::domain_error("cannot compare order of object iterators");
6650  }
6651 
6653  {
6654  return (m_it.array_iterator < other.m_it.array_iterator);
6655  }
6656 
6657  default:
6658  {
6659  return (m_it.primitive_iterator < other.m_it.primitive_iterator);
6660  }
6661  }
6662  }
6663 
6665  bool operator<=(const const_iterator& other) const
6666  {
6667  return not other.operator < (*this);
6668  }
6669 
6671  bool operator>(const const_iterator& other) const
6672  {
6673  return not operator<=(other);
6674  }
6675 
6677  bool operator>=(const const_iterator& other) const
6678  {
6679  return not operator<(other);
6680  }
6681 
6684  {
6685  assert(m_object != nullptr);
6686 
6687  switch (m_object->m_type)
6688  {
6690  {
6691  throw std::domain_error("cannot use offsets with object iterators");
6692  }
6693 
6695  {
6696  m_it.array_iterator += i;
6697  break;
6698  }
6699 
6700  default:
6701  {
6702  m_it.primitive_iterator += i;
6703  break;
6704  }
6705  }
6706 
6707  return *this;
6708  }
6709 
6712  {
6713  return operator+=(-i);
6714  }
6715 
6718  {
6719  auto result = *this;
6720  result += i;
6721  return result;
6722  }
6723 
6726  {
6727  auto result = *this;
6728  result -= i;
6729  return result;
6730  }
6731 
6734  {
6735  assert(m_object != nullptr);
6736 
6737  switch (m_object->m_type)
6738  {
6740  {
6741  throw std::domain_error("cannot use offsets with object iterators");
6742  }
6743 
6745  {
6746  return m_it.array_iterator - other.m_it.array_iterator;
6747  }
6748 
6749  default:
6750  {
6751  return m_it.primitive_iterator - other.m_it.primitive_iterator;
6752  }
6753  }
6754  }
6755 
6758  {
6759  assert(m_object != nullptr);
6760 
6761  switch (m_object->m_type)
6762  {
6764  {
6765  throw std::domain_error("cannot use operator[] for object iterators");
6766  }
6767 
6769  {
6770  return *(m_it.array_iterator + n);
6771  }
6772 
6774  {
6775  throw std::out_of_range("cannot get value");
6776  }
6777 
6778  default:
6779  {
6780  if (m_it.primitive_iterator == -n)
6781  {
6782  return *m_object;
6783  }
6784  else
6785  {
6786  throw std::out_of_range("cannot get value");
6787  }
6788  }
6789  }
6790  }
6791 
6793  typename object_t::key_type key() const
6794  {
6795  assert(m_object != nullptr);
6796 
6797  if (m_object->is_object())
6798  {
6799  return m_it.object_iterator->first;
6800  }
6801  else
6802  {
6803  throw std::domain_error("cannot use key() for non-object iterators");
6804  }
6805  }
6806 
6809  {
6810  return operator*();
6811  }
6812 
6813  private:
6815  pointer m_object = nullptr;
6817  internal_iterator m_it = internal_iterator();
6818  };
6819 
6832  class iterator : public const_iterator
6833  {
6834  public:
6835  using base_iterator = const_iterator;
6836  using pointer = typename basic_json::pointer;
6837  using reference = typename basic_json::reference;
6838 
6840  iterator() = default;
6841 
6843  explicit iterator(pointer object) noexcept
6844  : base_iterator(object)
6845  {}
6846 
6848  iterator(const iterator& other) noexcept
6849  : base_iterator(other)
6850  {}
6851 
6853  iterator& operator=(iterator other) noexcept(
6854  std::is_nothrow_move_constructible<pointer>::value and
6855  std::is_nothrow_move_assignable<pointer>::value and
6856  std::is_nothrow_move_constructible<internal_iterator>::value and
6857  std::is_nothrow_move_assignable<internal_iterator>::value
6858  )
6859  {
6860  base_iterator::operator=(other);
6861  return *this;
6862  }
6863 
6866  {
6867  return const_cast<reference>(base_iterator::operator*());
6868  }
6869 
6872  {
6873  return const_cast<pointer>(base_iterator::operator->());
6874  }
6875 
6878  {
6879  iterator result = *this;
6881  return result;
6882  }
6883 
6886  {
6888  return *this;
6889  }
6890 
6893  {
6894  iterator result = *this;
6896  return result;
6897  }
6898 
6901  {
6903  return *this;
6904  }
6905 
6908  {
6910  return *this;
6911  }
6912 
6915  {
6917  return *this;
6918  }
6919 
6922  {
6923  auto result = *this;
6924  result += i;
6925  return result;
6926  }
6927 
6930  {
6931  auto result = *this;
6932  result -= i;
6933  return result;
6934  }
6935 
6937  difference_type operator-(const iterator& other) const
6938  {
6939  return base_iterator::operator-(other);
6940  }
6941 
6944  {
6945  return const_cast<reference>(base_iterator::operator[](n));
6946  }
6947 
6950  {
6951  return const_cast<reference>(base_iterator::value());
6952  }
6953  };
6954 
6972  template<typename Base>
6973  class json_reverse_iterator : public std::reverse_iterator<Base>
6974  {
6975  public:
6977  using base_iterator = std::reverse_iterator<Base>;
6979  using reference = typename Base::reference;
6980 
6982  json_reverse_iterator(const typename base_iterator::iterator_type& it) noexcept
6983  : base_iterator(it)
6984  {}
6985 
6988  : base_iterator(it)
6989  {}
6990 
6993  {
6994  return base_iterator::operator++(1);
6995  }
6996 
6999  {
7000  base_iterator::operator++();
7001  return *this;
7002  }
7003 
7006  {
7007  return base_iterator::operator--(1);
7008  }
7009 
7012  {
7013  base_iterator::operator--();
7014  return *this;
7015  }
7016 
7019  {
7020  base_iterator::operator+=(i);
7021  return *this;
7022  }
7023 
7026  {
7027  auto result = *this;
7028  result += i;
7029  return result;
7030  }
7031 
7034  {
7035  auto result = *this;
7036  result -= i;
7037  return result;
7038  }
7039 
7042  {
7043  return this->base() - other.base();
7044  }
7045 
7048  {
7049  return *(this->operator+(n));
7050  }
7051 
7053  typename object_t::key_type key() const
7054  {
7055  auto it = --this->base();
7056  return it.key();
7057  }
7058 
7061  {
7062  auto it = --this->base();
7063  return it.operator * ();
7064  }
7065  };
7066 
7067 
7068  private:
7070  // lexer and parser //
7072 
7080  class lexer
7081  {
7082  public:
7084  enum class token_type
7085  {
7086  uninitialized,
7087  literal_true,
7088  literal_false,
7089  literal_null,
7090  value_string,
7091  value_number,
7092  begin_array,
7093  begin_object,
7094  end_array,
7095  end_object,
7096  name_separator,
7097  value_separator,
7098  parse_error,
7099  end_of_input
7100  };
7101 
7103  using lexer_char_t = unsigned char;
7104 
7106  explicit lexer(const string_t& s) noexcept
7107  : m_stream(nullptr), m_buffer(s)
7108  {
7109  m_content = reinterpret_cast<const lexer_char_t*>(s.c_str());
7110  assert(m_content != nullptr);
7111  m_start = m_cursor = m_content;
7112  m_limit = m_content + s.size();
7113  }
7114 
7116  explicit lexer(std::istream* s) noexcept
7117  : m_stream(s), m_buffer()
7118  {
7119  assert(m_stream != nullptr);
7120  getline(*m_stream, m_buffer);
7121  m_content = reinterpret_cast<const lexer_char_t*>(m_buffer.c_str());
7122  assert(m_content != nullptr);
7123  m_start = m_cursor = m_content;
7124  m_limit = m_content + m_buffer.size();
7125  }
7126 
7128  lexer() = default;
7129 
7130  // switch off unwanted functions
7131  lexer(const lexer&) = delete;
7132  lexer operator=(const lexer&) = delete;
7133 
7149  static string_t to_unicode(const std::size_t codepoint1,
7150  const std::size_t codepoint2 = 0)
7151  {
7152  // calculate the codepoint from the given code points
7153  std::size_t codepoint = codepoint1;
7154 
7155  // check if codepoint1 is a high surrogate
7156  if (codepoint1 >= 0xD800 and codepoint1 <= 0xDBFF)
7157  {
7158  // check if codepoint2 is a low surrogate
7159  if (codepoint2 >= 0xDC00 and codepoint2 <= 0xDFFF)
7160  {
7161  codepoint =
7162  // high surrogate occupies the most significant 22 bits
7163  (codepoint1 << 10)
7164  // low surrogate occupies the least significant 15 bits
7165  + codepoint2
7166  // there is still the 0xD800, 0xDC00 and 0x10000 noise
7167  // in the result so we have to subtract with:
7168  // (0xD800 << 10) + DC00 - 0x10000 = 0x35FDC00
7169  - 0x35FDC00;
7170  }
7171  else
7172  {
7173  throw std::invalid_argument("missing or wrong low surrogate");
7174  }
7175  }
7176 
7177  string_t result;
7178 
7179  if (codepoint < 0x80)
7180  {
7181  // 1-byte characters: 0xxxxxxx (ASCII)
7182  result.append(1, static_cast<typename string_t::value_type>(codepoint));
7183  }
7184  else if (codepoint <= 0x7ff)
7185  {
7186  // 2-byte characters: 110xxxxx 10xxxxxx
7187  result.append(1, static_cast<typename string_t::value_type>(0xC0 | ((codepoint >> 6) & 0x1F)));
7188  result.append(1, static_cast<typename string_t::value_type>(0x80 | (codepoint & 0x3F)));
7189  }
7190  else if (codepoint <= 0xffff)
7191  {
7192  // 3-byte characters: 1110xxxx 10xxxxxx 10xxxxxx
7193  result.append(1, static_cast<typename string_t::value_type>(0xE0 | ((codepoint >> 12) & 0x0F)));
7194  result.append(1, static_cast<typename string_t::value_type>(0x80 | ((codepoint >> 6) & 0x3F)));
7195  result.append(1, static_cast<typename string_t::value_type>(0x80 | (codepoint & 0x3F)));
7196  }
7197  else if (codepoint <= 0x10ffff)
7198  {
7199  // 4-byte characters: 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
7200  result.append(1, static_cast<typename string_t::value_type>(0xF0 | ((codepoint >> 18) & 0x07)));
7201  result.append(1, static_cast<typename string_t::value_type>(0x80 | ((codepoint >> 12) & 0x3F)));
7202  result.append(1, static_cast<typename string_t::value_type>(0x80 | ((codepoint >> 6) & 0x3F)));
7203  result.append(1, static_cast<typename string_t::value_type>(0x80 | (codepoint & 0x3F)));
7204  }
7205  else
7206  {
7207  throw std::out_of_range("code points above 0x10FFFF are invalid");
7208  }
7209 
7210  return result;
7211  }
7212 
7214  static std::string token_type_name(token_type t)
7215  {
7216  switch (t)
7217  {
7218  case token_type::uninitialized:
7219  return "<uninitialized>";
7220  case token_type::literal_true:
7221  return "true literal";
7222  case token_type::literal_false:
7223  return "false literal";
7224  case token_type::literal_null:
7225  return "null literal";
7226  case token_type::value_string:
7227  return "string literal";
7228  case token_type::value_number:
7229  return "number literal";
7230  case token_type::begin_array:
7231  return "'['";
7232  case token_type::begin_object:
7233  return "'{'";
7234  case token_type::end_array:
7235  return "']'";
7236  case token_type::end_object:
7237  return "'}'";
7238  case token_type::name_separator:
7239  return "':'";
7240  case token_type::value_separator:
7241  return "','";
7242  case token_type::parse_error:
7243  return "<parse error>";
7244  case token_type::end_of_input:
7245  return "end of input";
7246  default:
7247  {
7248  // catch non-enum values
7249  return "unknown token"; // LCOV_EXCL_LINE
7250  }
7251  }
7252  }
7253 
7264  token_type scan() noexcept
7265  {
7266  // pointer for backtracking information
7267  m_marker = nullptr;
7268 
7269  // remember the begin of the token
7270  m_start = m_cursor;
7271  assert(m_start != nullptr);
7272 
7273 
7274  {
7275  lexer_char_t yych;
7276  unsigned int yyaccept = 0;
7277  static const unsigned char yybm[] =
7278  {
7279  0, 0, 0, 0, 0, 0, 0, 0,
7280  0, 32, 32, 0, 0, 32, 0, 0,
7281  128, 128, 128, 128, 128, 128, 128, 128,
7282  128, 128, 128, 128, 128, 128, 128, 128,
7283  160, 128, 0, 128, 128, 128, 128, 128,
7284  128, 128, 128, 128, 128, 128, 128, 128,
7285  192, 192, 192, 192, 192, 192, 192, 192,
7286  192, 192, 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, 0, 128, 128, 128,
7291  128, 128, 128, 128, 128, 128, 128, 128,
7292  128, 128, 128, 128, 128, 128, 128, 128,
7293  128, 128, 128, 128, 128, 128, 128, 128,
7294  128, 128, 128, 128, 128, 128, 128, 128,
7295  128, 128, 128, 128, 128, 128, 128, 128,
7296  128, 128, 128, 128, 128, 128, 128, 128,
7297  128, 128, 128, 128, 128, 128, 128, 128,
7298  128, 128, 128, 128, 128, 128, 128, 128,
7299  128, 128, 128, 128, 128, 128, 128, 128,
7300  128, 128, 128, 128, 128, 128, 128, 128,
7301  128, 128, 128, 128, 128, 128, 128, 128,
7302  128, 128, 128, 128, 128, 128, 128, 128,
7303  128, 128, 128, 128, 128, 128, 128, 128,
7304  128, 128, 128, 128, 128, 128, 128, 128,
7305  128, 128, 128, 128, 128, 128, 128, 128,
7306  128, 128, 128, 128, 128, 128, 128, 128,
7307  128, 128, 128, 128, 128, 128, 128, 128,
7308  128, 128, 128, 128, 128, 128, 128, 128,
7309  128, 128, 128, 128, 128, 128, 128, 128,
7310  128, 128, 128, 128, 128, 128, 128, 128,
7311  };
7312  if ((m_limit - m_cursor) < 5)
7313  {
7314  yyfill(); // LCOV_EXCL_LINE;
7315  }
7316  yych = *m_cursor;
7317  if (yybm[0 + yych] & 32)
7318  {
7319  goto basic_json_parser_6;
7320  }
7321  if (yych <= '\\')
7322  {
7323  if (yych <= '-')
7324  {
7325  if (yych <= '"')
7326  {
7327  if (yych <= 0x00)
7328  {
7329  goto basic_json_parser_2;
7330  }
7331  if (yych <= '!')
7332  {
7333  goto basic_json_parser_4;
7334  }
7335  goto basic_json_parser_9;
7336  }
7337  else
7338  {
7339  if (yych <= '+')
7340  {
7341  goto basic_json_parser_4;
7342  }
7343  if (yych <= ',')
7344  {
7345  goto basic_json_parser_10;
7346  }
7347  goto basic_json_parser_12;
7348  }
7349  }
7350  else
7351  {
7352  if (yych <= '9')
7353  {
7354  if (yych <= '/')
7355  {
7356  goto basic_json_parser_4;
7357  }
7358  if (yych <= '0')
7359  {
7360  goto basic_json_parser_13;
7361  }
7362  goto basic_json_parser_15;
7363  }
7364  else
7365  {
7366  if (yych <= ':')
7367  {
7368  goto basic_json_parser_17;
7369  }
7370  if (yych == '[')
7371  {
7372  goto basic_json_parser_19;
7373  }
7374  goto basic_json_parser_4;
7375  }
7376  }
7377  }
7378  else
7379  {
7380  if (yych <= 't')
7381  {
7382  if (yych <= 'f')
7383  {
7384  if (yych <= ']')
7385  {
7386  goto basic_json_parser_21;
7387  }
7388  if (yych <= 'e')
7389  {
7390  goto basic_json_parser_4;
7391  }
7392  goto basic_json_parser_23;
7393  }
7394  else
7395  {
7396  if (yych == 'n')
7397  {
7398  goto basic_json_parser_24;
7399  }
7400  if (yych <= 's')
7401  {
7402  goto basic_json_parser_4;
7403  }
7404  goto basic_json_parser_25;
7405  }
7406  }
7407  else
7408  {
7409  if (yych <= '|')
7410  {
7411  if (yych == '{')
7412  {
7413  goto basic_json_parser_26;
7414  }
7415  goto basic_json_parser_4;
7416  }
7417  else
7418  {
7419  if (yych <= '}')
7420  {
7421  goto basic_json_parser_28;
7422  }
7423  if (yych == 0xEF)
7424  {
7425  goto basic_json_parser_30;
7426  }
7427  goto basic_json_parser_4;
7428  }
7429  }
7430  }
7431 basic_json_parser_2:
7432  ++m_cursor;
7433  {
7434  return token_type::end_of_input;
7435  }
7436 basic_json_parser_4:
7437  ++m_cursor;
7438 basic_json_parser_5:
7439  {
7440  return token_type::parse_error;
7441  }
7442 basic_json_parser_6:
7443  ++m_cursor;
7444  if (m_limit <= m_cursor)
7445  {
7446  yyfill(); // LCOV_EXCL_LINE;
7447  }
7448  yych = *m_cursor;
7449  if (yybm[0 + yych] & 32)
7450  {
7451  goto basic_json_parser_6;
7452  }
7453  {
7454  return scan();
7455  }
7456 basic_json_parser_9:
7457  yyaccept = 0;
7458  yych = *(m_marker = ++m_cursor);
7459  if (yych <= 0x0F)
7460  {
7461  goto basic_json_parser_5;
7462  }
7463  goto basic_json_parser_32;
7464 basic_json_parser_10:
7465  ++m_cursor;
7466  {
7467  return token_type::value_separator;
7468  }
7469 basic_json_parser_12:
7470  yych = *++m_cursor;
7471  if (yych <= '/')
7472  {
7473  goto basic_json_parser_5;
7474  }
7475  if (yych <= '0')
7476  {
7477  goto basic_json_parser_13;
7478  }
7479  if (yych <= '9')
7480  {
7481  goto basic_json_parser_15;
7482  }
7483  goto basic_json_parser_5;
7484 basic_json_parser_13:
7485  yyaccept = 1;
7486  yych = *(m_marker = ++m_cursor);
7487  if (yych <= 'D')
7488  {
7489  if (yych == '.')
7490  {
7491  goto basic_json_parser_37;
7492  }
7493  }
7494  else
7495  {
7496  if (yych <= 'E')
7497  {
7498  goto basic_json_parser_38;
7499  }
7500  if (yych == 'e')
7501  {
7502  goto basic_json_parser_38;
7503  }
7504  }
7505 basic_json_parser_14:
7506  {
7507  return token_type::value_number;
7508  }
7509 basic_json_parser_15:
7510  yyaccept = 1;
7511  m_marker = ++m_cursor;
7512  if ((m_limit - m_cursor) < 3)
7513  {
7514  yyfill(); // LCOV_EXCL_LINE;
7515  }
7516  yych = *m_cursor;
7517  if (yybm[0 + yych] & 64)
7518  {
7519  goto basic_json_parser_15;
7520  }
7521  if (yych <= 'D')
7522  {
7523  if (yych == '.')
7524  {
7525  goto basic_json_parser_37;
7526  }
7527  goto basic_json_parser_14;
7528  }
7529  else
7530  {
7531  if (yych <= 'E')
7532  {
7533  goto basic_json_parser_38;
7534  }
7535  if (yych == 'e')
7536  {
7537  goto basic_json_parser_38;
7538  }
7539  goto basic_json_parser_14;
7540  }
7541 basic_json_parser_17:
7542  ++m_cursor;
7543  {
7544  return token_type::name_separator;
7545  }
7546 basic_json_parser_19:
7547  ++m_cursor;
7548  {
7549  return token_type::begin_array;
7550  }
7551 basic_json_parser_21:
7552  ++m_cursor;
7553  {
7554  return token_type::end_array;
7555  }
7556 basic_json_parser_23:
7557  yyaccept = 0;
7558  yych = *(m_marker = ++m_cursor);
7559  if (yych == 'a')
7560  {
7561  goto basic_json_parser_39;
7562  }
7563  goto basic_json_parser_5;
7564 basic_json_parser_24:
7565  yyaccept = 0;
7566  yych = *(m_marker = ++m_cursor);
7567  if (yych == 'u')
7568  {
7569  goto basic_json_parser_40;
7570  }
7571  goto basic_json_parser_5;
7572 basic_json_parser_25:
7573  yyaccept = 0;
7574  yych = *(m_marker = ++m_cursor);
7575  if (yych == 'r')
7576  {
7577  goto basic_json_parser_41;
7578  }
7579  goto basic_json_parser_5;
7580 basic_json_parser_26:
7581  ++m_cursor;
7582  {
7583  return token_type::begin_object;
7584  }
7585 basic_json_parser_28:
7586  ++m_cursor;
7587  {
7588  return token_type::end_object;
7589  }
7590 basic_json_parser_30:
7591  yyaccept = 0;
7592  yych = *(m_marker = ++m_cursor);
7593  if (yych == 0xBB)
7594  {
7595  goto basic_json_parser_42;
7596  }
7597  goto basic_json_parser_5;
7598 basic_json_parser_31:
7599  ++m_cursor;
7600  if (m_limit <= m_cursor)
7601  {
7602  yyfill(); // LCOV_EXCL_LINE;
7603  }
7604  yych = *m_cursor;
7605 basic_json_parser_32:
7606  if (yybm[0 + yych] & 128)
7607  {
7608  goto basic_json_parser_31;
7609  }
7610  if (yych <= 0x0F)
7611  {
7612  goto basic_json_parser_33;
7613  }
7614  if (yych <= '"')
7615  {
7616  goto basic_json_parser_34;
7617  }
7618  goto basic_json_parser_36;
7619 basic_json_parser_33:
7620  m_cursor = m_marker;
7621  if (yyaccept == 0)
7622  {
7623  goto basic_json_parser_5;
7624  }
7625  else
7626  {
7627  goto basic_json_parser_14;
7628  }
7629 basic_json_parser_34:
7630  ++m_cursor;
7631  {
7632  return token_type::value_string;
7633  }
7634 basic_json_parser_36:
7635  ++m_cursor;
7636  if (m_limit <= m_cursor)
7637  {
7638  yyfill(); // LCOV_EXCL_LINE;
7639  }
7640  yych = *m_cursor;
7641  if (yych <= 'e')
7642  {
7643  if (yych <= '/')
7644  {
7645  if (yych == '"')
7646  {
7647  goto basic_json_parser_31;
7648  }
7649  if (yych <= '.')
7650  {
7651  goto basic_json_parser_33;
7652  }
7653  goto basic_json_parser_31;
7654  }
7655  else
7656  {
7657  if (yych <= '\\')
7658  {
7659  if (yych <= '[')
7660  {
7661  goto basic_json_parser_33;
7662  }
7663  goto basic_json_parser_31;
7664  }
7665  else
7666  {
7667  if (yych == 'b')
7668  {
7669  goto basic_json_parser_31;
7670  }
7671  goto basic_json_parser_33;
7672  }
7673  }
7674  }
7675  else
7676  {
7677  if (yych <= 'q')
7678  {
7679  if (yych <= 'f')
7680  {
7681  goto basic_json_parser_31;
7682  }
7683  if (yych == 'n')
7684  {
7685  goto basic_json_parser_31;
7686  }
7687  goto basic_json_parser_33;
7688  }
7689  else
7690  {
7691  if (yych <= 's')
7692  {
7693  if (yych <= 'r')
7694  {
7695  goto basic_json_parser_31;
7696  }
7697  goto basic_json_parser_33;
7698  }
7699  else
7700  {
7701  if (yych <= 't')
7702  {
7703  goto basic_json_parser_31;
7704  }
7705  if (yych <= 'u')
7706  {
7707  goto basic_json_parser_43;
7708  }
7709  goto basic_json_parser_33;
7710  }
7711  }
7712  }
7713 basic_json_parser_37:
7714  yych = *++m_cursor;
7715  if (yych <= '/')
7716  {
7717  goto basic_json_parser_33;
7718  }
7719  if (yych <= '9')
7720  {
7721  goto basic_json_parser_44;
7722  }
7723  goto basic_json_parser_33;
7724 basic_json_parser_38:
7725  yych = *++m_cursor;
7726  if (yych <= ',')
7727  {
7728  if (yych == '+')
7729  {
7730  goto basic_json_parser_46;
7731  }
7732  goto basic_json_parser_33;
7733  }
7734  else
7735  {
7736  if (yych <= '-')
7737  {
7738  goto basic_json_parser_46;
7739  }
7740  if (yych <= '/')
7741  {
7742  goto basic_json_parser_33;
7743  }
7744  if (yych <= '9')
7745  {
7746  goto basic_json_parser_47;
7747  }
7748  goto basic_json_parser_33;
7749  }
7750 basic_json_parser_39:
7751  yych = *++m_cursor;
7752  if (yych == 'l')
7753  {
7754  goto basic_json_parser_49;
7755  }
7756  goto basic_json_parser_33;
7757 basic_json_parser_40:
7758  yych = *++m_cursor;
7759  if (yych == 'l')
7760  {
7761  goto basic_json_parser_50;
7762  }
7763  goto basic_json_parser_33;
7764 basic_json_parser_41:
7765  yych = *++m_cursor;
7766  if (yych == 'u')
7767  {
7768  goto basic_json_parser_51;
7769  }
7770  goto basic_json_parser_33;
7771 basic_json_parser_42:
7772  yych = *++m_cursor;
7773  if (yych == 0xBF)
7774  {
7775  goto basic_json_parser_52;
7776  }
7777  goto basic_json_parser_33;
7778 basic_json_parser_43:
7779  ++m_cursor;
7780  if (m_limit <= m_cursor)
7781  {
7782  yyfill(); // LCOV_EXCL_LINE;
7783  }
7784  yych = *m_cursor;
7785  if (yych <= '@')
7786  {
7787  if (yych <= '/')
7788  {
7789  goto basic_json_parser_33;
7790  }
7791  if (yych <= '9')
7792  {
7793  goto basic_json_parser_54;
7794  }
7795  goto basic_json_parser_33;
7796  }
7797  else
7798  {
7799  if (yych <= 'F')
7800  {
7801  goto basic_json_parser_54;
7802  }
7803  if (yych <= '`')
7804  {
7805  goto basic_json_parser_33;
7806  }
7807  if (yych <= 'f')
7808  {
7809  goto basic_json_parser_54;
7810  }
7811  goto basic_json_parser_33;
7812  }
7813 basic_json_parser_44:
7814  yyaccept = 1;
7815  m_marker = ++m_cursor;
7816  if ((m_limit - m_cursor) < 3)
7817  {
7818  yyfill(); // LCOV_EXCL_LINE;
7819  }
7820  yych = *m_cursor;
7821  if (yych <= 'D')
7822  {
7823  if (yych <= '/')
7824  {
7825  goto basic_json_parser_14;
7826  }
7827  if (yych <= '9')
7828  {
7829  goto basic_json_parser_44;
7830  }
7831  goto basic_json_parser_14;
7832  }
7833  else
7834  {
7835  if (yych <= 'E')
7836  {
7837  goto basic_json_parser_38;
7838  }
7839  if (yych == 'e')
7840  {
7841  goto basic_json_parser_38;
7842  }
7843  goto basic_json_parser_14;
7844  }
7845 basic_json_parser_46:
7846  yych = *++m_cursor;
7847  if (yych <= '/')
7848  {
7849  goto basic_json_parser_33;
7850  }
7851  if (yych >= ':')
7852  {
7853  goto basic_json_parser_33;
7854  }
7855 basic_json_parser_47:
7856  ++m_cursor;
7857  if (m_limit <= m_cursor)
7858  {
7859  yyfill(); // LCOV_EXCL_LINE;
7860  }
7861  yych = *m_cursor;
7862  if (yych <= '/')
7863  {
7864  goto basic_json_parser_14;
7865  }
7866  if (yych <= '9')
7867  {
7868  goto basic_json_parser_47;
7869  }
7870  goto basic_json_parser_14;
7871 basic_json_parser_49:
7872  yych = *++m_cursor;
7873  if (yych == 's')
7874  {
7875  goto basic_json_parser_55;
7876  }
7877  goto basic_json_parser_33;
7878 basic_json_parser_50:
7879  yych = *++m_cursor;
7880  if (yych == 'l')
7881  {
7882  goto basic_json_parser_56;
7883  }
7884  goto basic_json_parser_33;
7885 basic_json_parser_51:
7886  yych = *++m_cursor;
7887  if (yych == 'e')
7888  {
7889  goto basic_json_parser_58;
7890  }
7891  goto basic_json_parser_33;
7892 basic_json_parser_52:
7893  ++m_cursor;
7894  {
7895  return scan();
7896  }
7897 basic_json_parser_54:
7898  ++m_cursor;
7899  if (m_limit <= m_cursor)
7900  {
7901  yyfill(); // LCOV_EXCL_LINE;
7902  }
7903  yych = *m_cursor;
7904  if (yych <= '@')
7905  {
7906  if (yych <= '/')
7907  {
7908  goto basic_json_parser_33;
7909  }
7910  if (yych <= '9')
7911  {
7912  goto basic_json_parser_60;
7913  }
7914  goto basic_json_parser_33;
7915  }
7916  else
7917  {
7918  if (yych <= 'F')
7919  {
7920  goto basic_json_parser_60;
7921  }
7922  if (yych <= '`')
7923  {
7924  goto basic_json_parser_33;
7925  }
7926  if (yych <= 'f')
7927  {
7928  goto basic_json_parser_60;
7929  }
7930  goto basic_json_parser_33;
7931  }
7932 basic_json_parser_55:
7933  yych = *++m_cursor;
7934  if (yych == 'e')
7935  {
7936  goto basic_json_parser_61;
7937  }
7938  goto basic_json_parser_33;
7939 basic_json_parser_56:
7940  ++m_cursor;
7941  {
7942  return token_type::literal_null;
7943  }
7944 basic_json_parser_58:
7945  ++m_cursor;
7946  {
7947  return token_type::literal_true;
7948  }
7949 basic_json_parser_60:
7950  ++m_cursor;
7951  if (m_limit <= m_cursor)
7952  {
7953  yyfill(); // LCOV_EXCL_LINE;
7954  }
7955  yych = *m_cursor;
7956  if (yych <= '@')
7957  {
7958  if (yych <= '/')
7959  {
7960  goto basic_json_parser_33;
7961  }
7962  if (yych <= '9')
7963  {
7964  goto basic_json_parser_63;
7965  }
7966  goto basic_json_parser_33;
7967  }
7968  else
7969  {
7970  if (yych <= 'F')
7971  {
7972  goto basic_json_parser_63;
7973  }
7974  if (yych <= '`')
7975  {
7976  goto basic_json_parser_33;
7977  }
7978  if (yych <= 'f')
7979  {
7980  goto basic_json_parser_63;
7981  }
7982  goto basic_json_parser_33;
7983  }
7984 basic_json_parser_61:
7985  ++m_cursor;
7986  {
7987  return token_type::literal_false;
7988  }
7989 basic_json_parser_63:
7990  ++m_cursor;
7991  if (m_limit <= m_cursor)
7992  {
7993  yyfill(); // LCOV_EXCL_LINE;
7994  }
7995  yych = *m_cursor;
7996  if (yych <= '@')
7997  {
7998  if (yych <= '/')
7999  {
8000  goto basic_json_parser_33;
8001  }
8002  if (yych <= '9')
8003  {
8004  goto basic_json_parser_31;
8005  }
8006  goto basic_json_parser_33;
8007  }
8008  else
8009  {
8010  if (yych <= 'F')
8011  {
8012  goto basic_json_parser_31;
8013  }
8014  if (yych <= '`')
8015  {
8016  goto basic_json_parser_33;
8017  }
8018  if (yych <= 'f')
8019  {
8020  goto basic_json_parser_31;
8021  }
8022  goto basic_json_parser_33;
8023  }
8024  }
8025 
8026  }
8027 
8029  void yyfill() noexcept
8030  {
8031  if (m_stream == nullptr or not * m_stream)
8032  {
8033  return;
8034  }
8035 
8036  const auto offset_start = m_start - m_content;
8037  const auto offset_marker = m_marker - m_start;
8038  const auto offset_cursor = m_cursor - m_start;
8039 
8040  m_buffer.erase(0, static_cast<size_t>(offset_start));
8041  std::string line;
8042  assert(m_stream != nullptr);
8043  std::getline(*m_stream, line);
8044  m_buffer += "\n" + line; // add line with newline symbol
8045 
8046  m_content = reinterpret_cast<const lexer_char_t*>(m_buffer.c_str());
8047  assert(m_content != nullptr);
8048  m_start = m_content;
8049  m_marker = m_start + offset_marker;
8050  m_cursor = m_start + offset_cursor;
8051  m_limit = m_start + m_buffer.size() - 1;
8052  }
8053 
8055  string_t get_token() const
8056  {
8057  assert(m_start != nullptr);
8058  return string_t(reinterpret_cast<typename string_t::const_pointer>(m_start),
8059  static_cast<size_t>(m_cursor - m_start));
8060  }
8061 
8083  string_t get_string() const
8084  {
8085  string_t result;
8086  result.reserve(static_cast<size_t>(m_cursor - m_start - 2));
8087 
8088  // iterate the result between the quotes
8089  for (const lexer_char_t* i = m_start + 1; i < m_cursor - 1; ++i)
8090  {
8091  // process escaped characters
8092  if (*i == '\\')
8093  {
8094  // read next character
8095  ++i;
8096 
8097  switch (*i)
8098  {
8099  // the default escapes
8100  case 't':
8101  {
8102  result += "\t";
8103  break;
8104  }
8105  case 'b':
8106  {
8107  result += "\b";
8108  break;
8109  }
8110  case 'f':
8111  {
8112  result += "\f";
8113  break;
8114  }
8115  case 'n':
8116  {
8117  result += "\n";
8118  break;
8119  }
8120  case 'r':
8121  {
8122  result += "\r";
8123  break;
8124  }
8125  case '\\':
8126  {
8127  result += "\\";
8128  break;
8129  }
8130  case '/':
8131  {
8132  result += "/";
8133  break;
8134  }
8135  case '"':
8136  {
8137  result += "\"";
8138  break;
8139  }
8140 
8141  // unicode
8142  case 'u':
8143  {
8144  // get code xxxx from uxxxx
8145  auto codepoint = std::strtoul(std::string(reinterpret_cast<typename string_t::const_pointer>(i + 1),
8146  4).c_str(), nullptr, 16);
8147 
8148  // check if codepoint is a high surrogate
8149  if (codepoint >= 0xD800 and codepoint <= 0xDBFF)
8150  {
8151  // make sure there is a subsequent unicode
8152  if ((i + 6 >= m_limit) or * (i + 5) != '\\' or * (i + 6) != 'u')
8153  {
8154  throw std::invalid_argument("missing low surrogate");
8155  }
8156 
8157  // get code yyyy from uxxxx\uyyyy
8158  auto codepoint2 = std::strtoul(std::string(reinterpret_cast<typename string_t::const_pointer>
8159  (i + 7), 4).c_str(), nullptr, 16);
8160  result += to_unicode(codepoint, codepoint2);
8161  // skip the next 10 characters (xxxx\uyyyy)
8162  i += 10;
8163  }
8164  else
8165  {
8166  // add unicode character(s)
8167  result += to_unicode(codepoint);
8168  // skip the next four characters (xxxx)
8169  i += 4;
8170  }
8171  break;
8172  }
8173  }
8174  }
8175  else
8176  {
8177  // all other characters are just copied to the end of the
8178  // string
8179  result.append(1, static_cast<typename string_t::value_type>(*i));
8180  }
8181  }
8182 
8183  return result;
8184  }
8185 
8206  long double str_to_float_t(long double* /* type */, char** endptr) const
8207  {
8208  return std::strtold(reinterpret_cast<typename string_t::const_pointer>(m_start), endptr);
8209  }
8210 
8226  double str_to_float_t(double* /* type */, char** endptr) const
8227  {
8228  return std::strtod(reinterpret_cast<typename string_t::const_pointer>(m_start), endptr);
8229  }
8230 
8246  float str_to_float_t(float* /* type */, char** endptr) const
8247  {
8248  return std::strtof(reinterpret_cast<typename string_t::const_pointer>(m_start), endptr);
8249  }
8250 
8263  template <typename T_A, typename T_B>
8264  static bool attempt_cast(T_A source, T_B& dest)
8265  {
8266  dest = static_cast<T_B>(source);
8267  return (source == static_cast<T_A>(dest));
8268  }
8269 
8308  void get_number(basic_json& result) const
8309  {
8310  typename string_t::value_type* endptr;
8311  assert(m_start != nullptr);
8312  errno = 0;
8313 
8314  // attempt to parse it as an integer - first checking for a
8315  // negative number
8316  if (*reinterpret_cast<typename string_t::const_pointer>(m_start) != '-')
8317  {
8318  // positive, parse with strtoull and attempt cast to
8319  // number_unsigned_t
8320  if (attempt_cast(std::strtoull(reinterpret_cast<typename string_t::const_pointer>(m_start), &endptr,
8321  10), result.m_value.number_unsigned))
8322  {
8323  result.m_type = value_t::number_unsigned;
8324  }
8325  else
8326  {
8327  // cast failed due to overflow - store as float
8328  result.m_type = value_t::number_float;
8329  }
8330  }
8331  else
8332  {
8333  // Negative, parse with strtoll and attempt cast to
8334  // number_integer_t
8335  if (attempt_cast(std::strtoll(reinterpret_cast<typename string_t::const_pointer>(m_start), &endptr,
8336  10), result.m_value.number_integer))
8337  {
8338  result.m_type = value_t::number_integer;
8339  }
8340  else
8341  {
8342  // cast failed due to overflow - store as float
8343  result.m_type = value_t::number_float;
8344  }
8345  }
8346 
8347  // check the end of the number was reached and no range error
8348  // occurred
8349  if (reinterpret_cast<lexer_char_t*>(endptr) != m_cursor || errno == ERANGE)
8350  {
8351  result.m_type = value_t::number_float;
8352  }
8353 
8354  if (result.m_type == value_t::number_float)
8355  {
8356  // either the number won't fit in an integer (range error from
8357  // strtoull/strtoll or overflow on cast) or there was something
8358  // else after the number, which could be an exponent
8359 
8360  // parse with strtod
8361  result.m_value.number_float = str_to_float_t(static_cast<number_float_t*>(nullptr), &endptr);
8362 
8363  // anything after the number is an error
8364  if (reinterpret_cast<lexer_char_t*>(endptr) != m_cursor)
8365  {
8366  throw std::invalid_argument(std::string("parse error - ") + get_token() + " is not a number");
8367  }
8368  }
8369  }
8370 
8371  private:
8373  std::istream* m_stream = nullptr;
8375  string_t m_buffer;
8377  const lexer_char_t* m_content = nullptr;
8379  const lexer_char_t* m_start = nullptr;
8381  const lexer_char_t* m_marker = nullptr;
8383  const lexer_char_t* m_cursor = nullptr;
8385  const lexer_char_t* m_limit = nullptr;
8386  };
8387 
8393  class parser
8394  {
8395  public:
8397  parser(const string_t& s, parser_callback_t cb = nullptr) noexcept
8398  : callback(cb), m_lexer(s)
8399  {
8400  // read first token
8401  get_token();
8402  }
8403 
8405  parser(std::istream& _is, parser_callback_t cb = nullptr) noexcept
8406  : callback(cb), m_lexer(&_is)
8407  {
8408  // read first token
8409  get_token();
8410  }
8411 
8413  basic_json parse()
8414  {
8415  basic_json result = parse_internal(true);
8416 
8417  expect(lexer::token_type::end_of_input);
8418 
8419  // return parser result and replace it with null in case the
8420  // top-level value was discarded by the callback function
8421  return result.is_discarded() ? basic_json() : result;
8422  }
8423 
8424  private:
8426  basic_json parse_internal(bool keep)
8427  {
8428  auto result = basic_json(value_t::discarded);
8429 
8430  switch (last_token)
8431  {
8432  case lexer::token_type::begin_object:
8433  {
8434  if (keep and (not callback or (keep = callback(depth++, parse_event_t::object_start, result))))
8435  {
8436  // explicitly set result to object to cope with {}
8437  result.m_type = value_t::object;
8438  result.m_value = json_value(value_t::object);
8439  }
8440 
8441  // read next token
8442  get_token();
8443 
8444  // closing } -> we are done
8445  if (last_token == lexer::token_type::end_object)
8446  {
8447  get_token();
8448  if (keep and callback and not callback(--depth, parse_event_t::object_end, result))
8449  {
8450  result = basic_json(value_t::discarded);
8451  }
8452  return result;
8453  }
8454 
8455  // no comma is expected here
8456  unexpect(lexer::token_type::value_separator);
8457 
8458  // otherwise: parse key-value pairs
8459  do
8460  {
8461  // ugly, but could be fixed with loop reorganization
8462  if (last_token == lexer::token_type::value_separator)
8463  {
8464  get_token();
8465  }
8466 
8467  // store key
8468  expect(lexer::token_type::value_string);
8469  const auto key = m_lexer.get_string();
8470 
8471  bool keep_tag = false;
8472  if (keep)
8473  {
8474  if (callback)
8475  {
8476  basic_json k(key);
8477  keep_tag = callback(depth, parse_event_t::key, k);
8478  }
8479  else
8480  {
8481  keep_tag = true;
8482  }
8483  }
8484 
8485  // parse separator (:)
8486  get_token();
8487  expect(lexer::token_type::name_separator);
8488 
8489  // parse and add value
8490  get_token();
8491  auto value = parse_internal(keep);
8492  if (keep and keep_tag and not value.is_discarded())
8493  {
8494  result[key] = std::move(value);
8495  }
8496  }
8497  while (last_token == lexer::token_type::value_separator);
8498 
8499  // closing }
8500  expect(lexer::token_type::end_object);
8501  get_token();
8502  if (keep and callback and not callback(--depth, parse_event_t::object_end, result))
8503  {
8504  result = basic_json(value_t::discarded);
8505  }
8506 
8507  return result;
8508  }
8509 
8510  case lexer::token_type::begin_array:
8511  {
8512  if (keep and (not callback or (keep = callback(depth++, parse_event_t::array_start, result))))
8513  {
8514  // explicitly set result to object to cope with []
8515  result.m_type = value_t::array;
8516  result.m_value = json_value(value_t::array);
8517  }
8518 
8519  // read next token
8520  get_token();
8521 
8522  // closing ] -> we are done
8523  if (last_token == lexer::token_type::end_array)
8524  {
8525  get_token();
8526  if (callback and not callback(--depth, parse_event_t::array_end, result))
8527  {
8528  result = basic_json(value_t::discarded);
8529  }
8530  return result;
8531  }
8532 
8533  // no comma is expected here
8534  unexpect(lexer::token_type::value_separator);
8535 
8536  // otherwise: parse values
8537  do
8538  {
8539  // ugly, but could be fixed with loop reorganization
8540  if (last_token == lexer::token_type::value_separator)
8541  {
8542  get_token();
8543  }
8544 
8545  // parse value
8546  auto value = parse_internal(keep);
8547  if (keep and not value.is_discarded())
8548  {
8549  result.push_back(std::move(value));
8550  }
8551  }
8552  while (last_token == lexer::token_type::value_separator);
8553 
8554  // closing ]
8555  expect(lexer::token_type::end_array);
8556  get_token();
8557  if (keep and callback and not callback(--depth, parse_event_t::array_end, result))
8558  {
8559  result = basic_json(value_t::discarded);
8560  }
8561 
8562  return result;
8563  }
8564 
8565  case lexer::token_type::literal_null:
8566  {
8567  get_token();
8568  result.m_type = value_t::null;
8569  break;
8570  }
8571 
8572  case lexer::token_type::value_string:
8573  {
8574  const auto s = m_lexer.get_string();
8575  get_token();
8576  result = basic_json(s);
8577  break;
8578  }
8579 
8580  case lexer::token_type::literal_true:
8581  {
8582  get_token();
8583  result.m_type = value_t::boolean;
8584  result.m_value = true;
8585  break;
8586  }
8587 
8588  case lexer::token_type::literal_false:
8589  {
8590  get_token();
8591  result.m_type = value_t::boolean;
8592  result.m_value = false;
8593  break;
8594  }
8595 
8596  case lexer::token_type::value_number:
8597  {
8598  m_lexer.get_number(result);
8599  get_token();
8600  break;
8601  }
8602 
8603  default:
8604  {
8605  // the last token was unexpected
8606  unexpect(last_token);
8607  }
8608  }
8609 
8610  if (keep and callback and not callback(depth, parse_event_t::value, result))
8611  {
8612  result = basic_json(value_t::discarded);
8613  }
8614  return result;
8615  }
8616 
8618  typename lexer::token_type get_token() noexcept
8619  {
8620  last_token = m_lexer.scan();
8621  return last_token;
8622  }
8623 
8624  void expect(typename lexer::token_type t) const
8625  {
8626  if (t != last_token)
8627  {
8628  std::string error_msg = "parse error - unexpected ";
8629  error_msg += (last_token == lexer::token_type::parse_error ? ("'" + m_lexer.get_token() + "'") :
8630  lexer::token_type_name(last_token));
8631  error_msg += "; expected " + lexer::token_type_name(t);
8632  throw std::invalid_argument(error_msg);
8633  }
8634  }
8635 
8636  void unexpect(typename lexer::token_type t) const
8637  {
8638  if (t == last_token)
8639  {
8640  std::string error_msg = "parse error - unexpected ";
8641  error_msg += (last_token == lexer::token_type::parse_error ? ("'" + m_lexer.get_token() + "'") :
8642  lexer::token_type_name(last_token));
8643  throw std::invalid_argument(error_msg);
8644  }
8645  }
8646 
8647  private:
8649  int depth = 0;
8651  parser_callback_t callback;
8653  typename lexer::token_type last_token = lexer::token_type::uninitialized;
8655  lexer m_lexer;
8656  };
8657 };
8658 
8659 
8661 // presets //
8663 
8673 }
8674 
8675 
8677 // nonmember functions //
8679 
8680 // specialization of std::swap, and std::hash
8681 namespace std
8682 {
8688 template <>
8689 inline void swap(nlohmann::json& j1,
8690  nlohmann::json& j2) noexcept(
8691  is_nothrow_move_constructible<nlohmann::json>::value and
8692  is_nothrow_move_assignable<nlohmann::json>::value
8693  )
8694 {
8695  j1.swap(j2);
8696 }
8697 
8699 template <>
8700 struct hash<nlohmann::json>
8701 {
8707  std::size_t operator()(const nlohmann::json& j) const
8708  {
8709  // a naive hashing via the string representation
8710  const auto& h = hash<nlohmann::json::string_t>();
8711  return h(j.dump());
8712  }
8713 };
8714 }
8715 
8728 inline nlohmann::json operator "" _json(const char* s, std::size_t)
8729 {
8730  return nlohmann::json::parse(reinterpret_cast<const nlohmann::json::string_t::value_type*>(s));
8731 }
8732 
8733 // restore GCC/clang diagnostic settings
8734 #if defined(__clang__) || defined(__GNUC__) || defined(__GNUG__)
8735  #pragma GCC diagnostic pop
8736 #endif
8737 
8738 #endif
the parser read ] and finished processing a JSON array
const_iterator & operator+=(difference_type i)
add to iterator
Definition: json.hpp:6683
iterator operator++(int)
post-increment (it++)
Definition: json.hpp:6877
reference operator[](difference_type n) const
access to successor
Definition: json.hpp:6943
reference at(const typename object_t::key_type &key)
access specified object element with bounds checking
Definition: json.hpp:3112
iterator & operator+=(difference_type i)
add to iterator
Definition: json.hpp:6907
bool operator>=(const const_iterator &other) const
comparison: greater than or equal
Definition: json.hpp:6677
const_iterator()=default
default constructor
void swap(string_t &other)
exchanges the values
Definition: json.hpp:5129
const_iterator end() const noexcept
returns a const iterator to one past the last element
Definition: json.hpp:4183
size_type max_size() const noexcept
returns the maximum possible number of elements
Definition: json.hpp:4552
const value_type & const_reference
the type of an element const reference
Definition: json.hpp:202
iterator insert(const_iterator pos, const_iterator first, const_iterator last)
inserts elements
Definition: json.hpp:4934
typename basic_json::difference_type difference_type
a type to represent differences between iterators
Definition: json.hpp:6297
std::bidirectional_iterator_tag iterator_category
the category of the iterator
Definition: json.hpp:6303
bool operator>(const const_iterator &other) const
comparison: greater than
Definition: json.hpp:6671
constexpr bool is_structured() const noexcept
return whether type is structured
Definition: json.hpp:2171
json_reverse_iterator operator-(difference_type i) const
subtract from iterator
Definition: json.hpp:7033
iterator insert(const_iterator pos, const basic_json &val)
inserts element
Definition: json.hpp:4825
friend bool operator<(const_reference lhs, const_reference rhs) noexcept
comparison: less than
Definition: json.hpp:5400
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:3595
std::ptrdiff_t difference_type
a type to represent differences between iterators
Definition: json.hpp:205
iterator & operator--()
pre-decrement (–it)
Definition: json.hpp:6900
typename Base::reference reference
the reference type for the pointed-to element
Definition: json.hpp:6979
const_iterator(pointer object) noexcept
constructor for a given JSON instance
Definition: json.hpp:6309
number value (unsigned integer)
const_reference front() const
access the first element
Definition: json.hpp:3632
constexpr bool is_primitive() const noexcept
return whether type is primitive
Definition: json.hpp:2144
basic_json(std::nullptr_t) noexcept
create a null object (explicitly)
Definition: json.hpp:1003
pointer operator->()
dereference the iterator
Definition: json.hpp:6871
AllocatorType< basic_json > allocator_type
the allocator type
Definition: json.hpp:210
void push_back(const basic_json &val)
add an object to an array
Definition: json.hpp:4723
basic_json(const number_float_t val) noexcept
create a floating-point number (explicit)
Definition: json.hpp:1417
const_reference back() const
access the last element
Definition: json.hpp:3676
const_iterator cend() const noexcept
returns a const iterator to one past the last element
Definition: json.hpp:4213
a class to store JSON values
Definition: json.hpp:174
iterator & operator=(iterator other) noexcept(std::is_nothrow_move_constructible< pointer >::value andstd::is_nothrow_move_assignable< pointer >::value andstd::is_nothrow_move_constructible< internal_iterator >::value andstd::is_nothrow_move_assignable< internal_iterator >::value)
copy assignment
Definition: json.hpp:6853
basic_json(const CompatibleStringType &val)
create a string (implicit)
Definition: json.hpp:1212
basic_json(InputIT first, InputIT last)
construct a JSON container given an iterator range
Definition: json.hpp:1738
basic_json(std::istream &i, parser_callback_t cb=nullptr)
construct a JSON value given an input stream
Definition: json.hpp:1845
constexpr bool is_discarded() const noexcept
return whether value is discarded
Definition: json.hpp:2423
constexpr const PointerType get_ptr() const noexcept
get a pointer value (implicit)
Definition: json.hpp:2889
friend std::ostream & operator<<(std::ostream &o, const basic_json &j)
serialize to stream
Definition: json.hpp:5582
constexpr bool is_number_unsigned() const noexcept
return whether value is an unsigned integer number
Definition: json.hpp:2302
InteratorType erase(InteratorType pos)
remove element given an iterator
Definition: json.hpp:3734
json_reverse_iterator(const base_iterator &it) noexcept
create reverse iterator from base class
Definition: json.hpp:6987
iterator(pointer object) noexcept
constructor for a given JSON instance
Definition: json.hpp:6843
a mutable random access iterator for the basic_json class
Definition: json.hpp:6832
constexpr bool is_object() const noexcept
return whether value is an object
Definition: json.hpp:2352
PointerType get_ptr() noexcept
get a pointer value (implicit)
Definition: json.hpp:2874
Definition: json.hpp:8681
ObjectType< StringType, basic_json, std::less< StringType >, AllocatorType< std::pair< const StringType, basic_json >>> object_t
a type for an object
Definition: json.hpp:334
iterator & operator-=(difference_type i)
subtract from iterator
Definition: json.hpp:6914
const_iterator & operator-=(difference_type i)
subtract from iterator
Definition: json.hpp:6711
size_type size() const noexcept
returns the number of elements
Definition: json.hpp:4486
const_reference operator[](const typename object_t::key_type &key) const
read-only access specified object element
Definition: json.hpp:3342
reference & operator=(basic_json other) noexcept(std::is_nothrow_move_constructible< value_t >::value andstd::is_nothrow_move_assignable< value_t >::value andstd::is_nothrow_move_constructible< json_value >::value andstd::is_nothrow_move_assignable< json_value >::value)
copy assignment
Definition: json.hpp:1983
static allocator_type get_allocator()
returns the allocator associated with the container
Definition: json.hpp:235
constexpr bool is_array() const noexcept
return whether value is an array
Definition: json.hpp:2374
basic_json()=default
create a null object (implicitly)
const_iterator & operator=(const_iterator other) noexcept(std::is_nothrow_move_constructible< pointer >::value andstd::is_nothrow_move_assignable< pointer >::value andstd::is_nothrow_move_constructible< internal_iterator >::value andstd::is_nothrow_move_assignable< internal_iterator >::value)
copy assignment
Definition: json.hpp:6370
pointer operator->() const
dereference the iterator
Definition: json.hpp:6490
const_iterator operator-(difference_type i)
subtract from iterator
Definition: json.hpp:6725
basic_json(const CompatibleObjectType &val)
create an object (implicit)
Definition: json.hpp:1061
basic_json(const CompatibleNumberFloatType val) noexcept
create an floating-point number (implicit)
Definition: json.hpp:1463
friend bool operator==(const_reference v, std::nullptr_t) noexcept
comparison: equal
Definition: json.hpp:5309
void swap(reference other) noexcept(std::is_nothrow_move_constructible< value_t >::value andstd::is_nothrow_move_assignable< value_t >::value andstd::is_nothrow_move_constructible< json_value >::value andstd::is_nothrow_move_assignable< json_value >::value)
exchanges the values
Definition: json.hpp:5030
reference value() const
return the value of an iterator
Definition: json.hpp:6808
iterator end() noexcept
returns an iterator to one past the last element
Definition: json.hpp:4173
const_iterator operator--(int)
post-decrement (it–)
Definition: json.hpp:6562
basic_json(const int val) noexcept
create an integer number from an enum type (explicit)
Definition: json.hpp:1292
basic_json(const CompatibleArrayType &val)
create an array (implicit)
Definition: json.hpp:1128
reference back()
access the last element
Definition: json.hpp:3666
reverse_iterator rend() noexcept
returns an iterator to the reverse-end
Definition: json.hpp:4280
ValueType value(const typename object_t::key_type &key, ValueType default_value) const
access specified object element with default value
Definition: json.hpp:3569
reference operator[](difference_type n) const
access to successor
Definition: json.hpp:6757
iterator()=default
default constructor
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:1668
json_reverse_iterator< typename basic_json::iterator > reverse_iterator
a reverse iterator for a basic_json container
Definition: json.hpp:225
reference operator+=(const basic_json &val)
add an object to an array
Definition: json.hpp:4747
static iteration_proxy< const_iterator > iterator_wrapper(const_reference cont)
wrapper to access iterator member functions in range-based for
Definition: json.hpp:4375
NumberFloatType number_float_t
a type for a number (floating-point)
Definition: json.hpp:664
typename basic_json::const_pointer pointer
defines a pointer to the type iterated over (value_type)
Definition: json.hpp:6299
basic_json(const value_t value_type)
create an empty value with a given type
Definition: json.hpp:951
const_reference at(const typename object_t::key_type &key) const
access specified object element with bounds checking
Definition: json.hpp:3160
reference operator[](difference_type n) const
access to successor
Definition: json.hpp:7047
const_reverse_iterator rend() const noexcept
returns a const reverse iterator to one before the first
Definition: json.hpp:4288
const_iterator find(typename object_t::key_type key) const
find an element in a JSON object
Definition: json.hpp:4030
a template for a reverse iterator class
Definition: json.hpp:218
basic_json(const object_t &val)
create an object (explicit)
Definition: json.hpp:1026
std::size_t operator()(const nlohmann::json &j) const
return a hash value for a JSON object
Definition: json.hpp:8707
reverse_iterator rbegin() noexcept
returns an iterator to the reverse-beginning
Definition: json.hpp:4243
basic_json(const string_t &val)
create a string (explicit)
Definition: json.hpp:1157
iterator find(typename object_t::key_type key)
find an element in a JSON object
Definition: json.hpp:4013
constexpr bool is_number() const noexcept
return whether value is a number
Definition: json.hpp:2245
json_reverse_iterator & operator+=(difference_type i)
add to iterator
Definition: json.hpp:7018
difference_type operator-(const const_iterator &other) const
return difference
Definition: json.hpp:6733
void swap(object_t &other)
exchanges the values
Definition: json.hpp:5095
BooleanType boolean_t
a type for a boolean
Definition: json.hpp:453
reference operator[](T *(&key)[n])
access specified object element
Definition: json.hpp:3385
const_iterator(const iterator &other) noexcept
copy constructor given a nonconst iterator
Definition: json.hpp:6337
json_reverse_iterator operator+(difference_type i) const
add to iterator
Definition: json.hpp:7025
namespace for Niels Lohmann
Definition: json.hpp:67
parse_event_t
JSON callback events.
Definition: json.hpp:837
constexpr value_t type() const noexcept
return the type of the JSON value (explicit)
Definition: json.hpp:2114
static basic_json parse(std::istream &&i, parser_callback_t cb=nullptr)
deserialize from stream
Definition: json.hpp:5676
basic_json(size_type cnt, const basic_json &val)
construct an array with count copies of given value
Definition: json.hpp:1692
const_reverse_iterator crend() const noexcept
returns a const reverse iterator to one before the first
Definition: json.hpp:4346
std::function< bool(int depth, parse_event_t event, basic_json &parsed)> parser_callback_t
per-element parser callback type
Definition: json.hpp:902
const_iterator & operator--()
pre-decrement (–it)
Definition: json.hpp:6570
constexpr bool is_string() const noexcept
return whether value is a string
Definition: json.hpp:2396
basic_json value_type
the type of elements in a basic_json container
Definition: json.hpp:197
basic_json(boolean_t val) noexcept
create a boolean (explicit)
Definition: json.hpp:1230
the parser read } and finished processing a JSON object
basic_json(basic_json &&other) noexcept
move constructor
Definition: json.hpp:1951
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:1628
friend std::istream & operator>>(std::istream &i, basic_json &j)
deserialize from stream
Definition: json.hpp:5714
basic_json(const typename string_t::value_type *val)
create a string (explicit)
Definition: json.hpp:1181
json_reverse_iterator operator++(int)
post-increment (it++)
Definition: json.hpp:6992
friend bool operator==(const_reference lhs, const_reference rhs) noexcept
comparison: equal
Definition: json.hpp:5210
const_reference at(size_type idx) const
access specified array element with bounds checking
Definition: json.hpp:3064
friend std::ostream & operator>>(const basic_json &j, std::ostream &o)
serialize to stream
Definition: json.hpp:5600
friend std::istream & operator<<(basic_json &j, std::istream &i)
deserialize from stream
Definition: json.hpp:5704
json_reverse_iterator & operator++()
pre-increment (++it)
Definition: json.hpp:6998
reference operator+=(const typename object_t::value_type &val)
add an object to an object
Definition: json.hpp:4797
std::size_t size_type
a type to represent container sizes
Definition: json.hpp:207
static iteration_proxy< iterator > iterator_wrapper(reference cont)
wrapper to access iterator member functions in range-based for
Definition: json.hpp:4367
reference operator+=(basic_json &&val)
add an object to an array
Definition: json.hpp:4713
bool operator!=(const const_iterator &other) const
comparison: not equal
Definition: json.hpp:6629
reference operator[](size_type idx)
access specified array element
Definition: json.hpp:3207
const_iterator begin() const noexcept
returns a const iterator to the first element
Definition: json.hpp:4112
friend bool operator!=(const_reference v, std::nullptr_t) noexcept
comparison: not equal
Definition: json.hpp:5362
typename basic_json::value_type value_type
the type of the values when the iterator is dereferenced
Definition: json.hpp:6295
const_reverse_iterator crbegin() const noexcept
returns a const reverse iterator to the last element
Definition: json.hpp:4317
constexpr bool is_number_float() const noexcept
return whether value is a floating-point number
Definition: json.hpp:2330
const_iterator cbegin() const noexcept
returns a const iterator to the first element
Definition: json.hpp:4142
array (ordered collection of values)
constexpr bool is_number_integer() const noexcept
return whether value is an integer number
Definition: json.hpp:2274
object_t::key_type key() const
return the key of an object iterator
Definition: json.hpp:7053
basic_json(const CompatibleNumberUnsignedType val) noexcept
create an unsigned number (implicit)
Definition: json.hpp:1388
constexpr bool is_boolean() const noexcept
return whether value is a boolean
Definition: json.hpp:2215
void push_back(basic_json &&val)
add an object to an array
Definition: json.hpp:4687
typename std::allocator_traits< allocator_type >::const_pointer const_pointer
the type of an element const pointer
Definition: json.hpp:215
ReferenceType get_ref()
get a reference value (implicit)
Definition: json.hpp:2925
friend bool operator>(const_reference lhs, const_reference rhs) noexcept
comparison: greater than
Definition: json.hpp:5523
const_reverse_iterator rbegin() const noexcept
returns a const reverse iterator to the last element
Definition: json.hpp:4251
NumberIntegerType number_integer_t
a type for a number (integer)
Definition: json.hpp:524
iterator operator--(int)
post-decrement (it–)
Definition: json.hpp:6892
reference operator*() const
return a reference to the value pointed to by the iterator
Definition: json.hpp:6450
iterator insert(const_iterator pos, basic_json &&val)
inserts element
Definition: json.hpp:4852
bool empty() const noexcept
checks whether the container is empty
Definition: json.hpp:4423
json_reverse_iterator(const typename base_iterator::iterator_type &it) noexcept
create reverse iterator from iterator
Definition: json.hpp:6982
bool operator==(const const_iterator &other) const
comparison: equal
Definition: json.hpp:6599
constexpr bool is_null() const noexcept
return whether value is null
Definition: json.hpp:2193
the parser finished reading a JSON value
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:4061
iterator operator+(difference_type i)
add to iterator
Definition: json.hpp:6921
difference_type operator-(const iterator &other) const
return difference
Definition: json.hpp:6937
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:1536
const_reference operator[](T *key) const
read-only access specified object element
Definition: json.hpp:3502
typename std::allocator_traits< allocator_type >::pointer pointer
the type of an element pointer
Definition: json.hpp:213
json_reverse_iterator< typename basic_json::const_iterator > const_reverse_iterator
a const reverse iterator for a basic_json container
Definition: json.hpp:227
value_t
the JSON type enumeration
Definition: json.hpp:683
reference value() const
return the value of an iterator
Definition: json.hpp:6949
iterator & operator++()
pre-increment (++it)
Definition: json.hpp:6885
reference at(size_type idx)
access specified array element with bounds checking
Definition: json.hpp:3020
basic_json(const CompatibleNumberIntegerType val) noexcept
create an integer number (implicit)
Definition: json.hpp:1329
void push_back(const typename object_t::value_type &val)
add an object to an object
Definition: json.hpp:4773
string_t dump(const int indent=-1) const
serialization
Definition: json.hpp:2080
iterator operator-(difference_type i)
subtract from iterator
Definition: json.hpp:6929
std::reverse_iterator< Base > base_iterator
shortcut to the reverse iterator adaptor
Definition: json.hpp:6977
object (unordered set of name/value pairs)
the parser read { and started to process a JSON object
ReferenceType get_ref() const
get a reference value (implicit)
Definition: json.hpp:2940
friend bool operator<(const value_t lhs, const value_t rhs) noexcept
comparison operator for JSON types
Definition: json.hpp:5163
number value (floating-point)
const_iterator & operator++()
pre-increment (++it)
Definition: json.hpp:6533
basic_json(const array_t &val)
create an array (explicit)
Definition: json.hpp:1088
reference operator*()
return a reference to the value pointed to by the iterator
Definition: json.hpp:6865
typename basic_json::const_reference reference
defines a reference to the type iterated over (value_type)
Definition: json.hpp:6301
discarded by the the parser callback function
iterator(const iterator &other) noexcept
copy constructor
Definition: json.hpp:6848
the parser read a key of a value in an object
const_reference operator[](T *(&key)[n]) const
read-only access specified object element
Definition: json.hpp:3420
iterator insert(const_iterator pos, std::initializer_list< basic_json > ilist)
inserts elements
Definition: json.hpp:4992
json_reverse_iterator & operator--()
pre-decrement (–it)
Definition: json.hpp:7011
size_type erase(const typename object_t::key_type &key)
remove element from a JSON object given a key
Definition: json.hpp:3929
void erase(const size_type idx)
remove element from a JSON array given an index
Definition: json.hpp:3967
void clear() noexcept
clears the contents
Definition: json.hpp:4611
a const random access iterator for the basic_json class
Definition: json.hpp:6288
NumberUnsignedType number_unsigned_t
a type for a number (unsigned)
Definition: json.hpp:596
object_t::key_type key() const
return the key of an object iterator
Definition: json.hpp:6793
const_iterator operator++(int)
post-increment (it++)
Definition: json.hpp:6525
reference operator[](T *key)
access specified object element
Definition: json.hpp:3453
friend bool operator!=(std::nullptr_t, const_reference v) noexcept
comparison: not equal
Definition: json.hpp:5371
bool operator<=(const const_iterator &other) const
comparison: less than or equal
Definition: json.hpp:6665
friend bool operator<=(const_reference lhs, const_reference rhs) noexcept
comparison: less than or equal
Definition: json.hpp:5501
bool operator<(const const_iterator &other) const
comparison: smaller
Definition: json.hpp:6635
friend bool operator>=(const_reference lhs, const_reference rhs) noexcept
comparison: greater than or equal
Definition: json.hpp:5545
const_iterator operator+(difference_type i)
add to iterator
Definition: json.hpp:6717
static basic_json parse(std::istream &i, parser_callback_t cb=nullptr)
deserialize from stream
Definition: json.hpp:5668
friend bool operator!=(const_reference lhs, const_reference rhs) noexcept
comparison: not equal
Definition: json.hpp:5339
iterator begin() noexcept
returns an iterator to the first element
Definition: json.hpp:4102
InteratorType erase(InteratorType first, InteratorType last)
remove elements given an iterator range
Definition: json.hpp:3842
StringType string_t
a type for a string
Definition: json.hpp:427
reference front()
access the first element
Definition: json.hpp:3624
iterator insert(const_iterator pos, size_type cnt, const basic_json &val)
inserts elements
Definition: json.hpp:4881
friend bool operator==(std::nullptr_t, const_reference v) noexcept
comparison: equal
Definition: json.hpp:5318
value_type & reference
the type of an element reference
Definition: json.hpp:200
basic_json(const basic_json &other)
copy constructor
Definition: json.hpp:1876
the parser read [ and started to process a JSON array
ArrayType< basic_json, AllocatorType< basic_json >> array_t
a type for an array
Definition: json.hpp:380
difference_type operator-(const json_reverse_iterator &other) const
return difference
Definition: json.hpp:7041
const_reference operator[](size_type idx) const
access specified array element
Definition: json.hpp:3253
static basic_json parse(const string_t &s, parser_callback_t cb=nullptr)
deserialize from string
Definition: json.hpp:5639
json_reverse_iterator operator--(int)
post-decrement (it–)
Definition: json.hpp:7005
~basic_json()
destructor
Definition: json.hpp:2011
const_iterator(const const_iterator &other) noexcept
copy constructor
Definition: json.hpp:6365
void swap(array_t &other)
exchanges the values
Definition: json.hpp:5061
reference value() const
return the value of an iterator
Definition: json.hpp:7060
reference operator[](const typename object_t::key_type &key)
access specified object element
Definition: json.hpp:3294