JSON for Modern C++  2.0.7
json.hpp
1 /*
2  __ _____ _____ _____
3  __| | __| | | | JSON for Modern C++
4 | | |__ | | | | | | version 2.0.7
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 <cctype>
36 #include <ciso646>
37 #include <cmath>
38 #include <cstddef>
39 #include <cstdint>
40 #include <cstdlib>
41 #include <cstring>
42 #include <functional>
43 #include <initializer_list>
44 #include <iomanip>
45 #include <iostream>
46 #include <iterator>
47 #include <limits>
48 #include <locale>
49 #include <map>
50 #include <memory>
51 #include <numeric>
52 #include <sstream>
53 #include <stdexcept>
54 #include <string>
55 #include <type_traits>
56 #include <utility>
57 #include <vector>
58 
59 // exclude unsupported compilers
60 #if defined(__clang__)
61  #define CLANG_VERSION (__clang_major__ * 10000 + __clang_minor__ * 100 + __clang_patchlevel__)
62  #if CLANG_VERSION < 30400
63  #error "unsupported Clang version - see https://github.com/nlohmann/json#supported-compilers"
64  #endif
65 #elif defined(__GNUC__)
66  #define GCC_VERSION (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__)
67  #if GCC_VERSION < 40900
68  #error "unsupported GCC version - see https://github.com/nlohmann/json#supported-compilers"
69  #endif
70 #endif
71 
72 // disable float-equal warnings on GCC/clang
73 #if defined(__clang__) || defined(__GNUC__) || defined(__GNUG__)
74  #pragma GCC diagnostic push
75  #pragma GCC diagnostic ignored "-Wfloat-equal"
76 #endif
77 
78 // allow for portable deprecation warnings
79 #if defined(__clang__) || defined(__GNUC__) || defined(__GNUG__)
80  #define JSON_DEPRECATED __attribute__((deprecated))
81 #elif defined(_MSC_VER)
82  #define JSON_DEPRECATED __declspec(deprecated)
83 #else
84  #define JSON_DEPRECATED
85 #endif
86 
92 namespace nlohmann
93 {
94 
95 
100 namespace
101 {
112 template<typename T>
113 struct has_mapped_type
114 {
115  private:
116  template <typename U, typename = typename U::mapped_type>
117  static int detect(U&&);
118 
119  static void detect(...);
120  public:
121  static constexpr bool value =
122  std::is_integral<decltype(detect(std::declval<T>()))>::value;
123 };
124 
137 struct DecimalSeparator : std::numpunct<char>
138 {
139  char do_decimal_point() const
140  {
141  return '.';
142  }
143 };
144 
145 }
146 
225 template <
226  template<typename U, typename V, typename... Args> class ObjectType = std::map,
227  template<typename U, typename... Args> class ArrayType = std::vector,
228  class StringType = std::string,
229  class BooleanType = bool,
230  class NumberIntegerType = std::int64_t,
231  class NumberUnsignedType = std::uint64_t,
232  class NumberFloatType = double,
233  template<typename U> class AllocatorType = std::allocator
234  >
236 {
237  private:
239  using basic_json_t = basic_json<ObjectType, ArrayType, StringType,
240  BooleanType, NumberIntegerType, NumberUnsignedType, NumberFloatType,
241  AllocatorType>;
242 
243  public:
244  // forward declarations
245  template<typename Base> class json_reverse_iterator;
246  class json_pointer;
247 
249  // container types //
251 
256 
259 
263  using const_reference = const value_type&;
264 
266  using difference_type = std::ptrdiff_t;
268  using size_type = std::size_t;
269 
271  using allocator_type = AllocatorType<basic_json>;
272 
274  using pointer = typename std::allocator_traits<allocator_type>::pointer;
276  using const_pointer = typename std::allocator_traits<allocator_type>::const_pointer;
277 
279  class iterator;
281  class const_iterator;
286 
288 
289 
294  {
295  return allocator_type();
296  }
297 
298 
300  // JSON value data types //
302 
307 
391  using object_t = ObjectType<StringType,
392  basic_json,
393  std::less<StringType>,
394  AllocatorType<std::pair<const StringType,
395  basic_json>>>;
396 
441  using array_t = ArrayType<basic_json, AllocatorType<basic_json>>;
442 
488  using string_t = StringType;
489 
514  using boolean_t = BooleanType;
515 
586  using number_integer_t = NumberIntegerType;
587 
657  using number_unsigned_t = NumberUnsignedType;
658 
725  using number_float_t = NumberFloatType;
726 
728 
729 
731  // JSON type enumeration //
733 
756  enum class value_t : uint8_t
757  {
758  null,
759  object,
760  array,
761  string,
762  boolean,
763  number_integer,
764  number_unsigned,
765  number_float,
766  discarded
767  };
768 
769 
770  private:
771 
773  template<typename T, typename... Args>
774  static T* create(Args&& ... args)
775  {
776  AllocatorType<T> alloc;
777  auto deleter = [&](T * object)
778  {
779  alloc.deallocate(object, 1);
780  };
781  std::unique_ptr<T, decltype(deleter)> object(alloc.allocate(1), deleter);
782  alloc.construct(object.get(), std::forward<Args>(args)...);
783  assert(object.get() != nullptr);
784  return object.release();
785  }
786 
788  // JSON value storage //
790 
815  union json_value
816  {
818  object_t* object;
820  array_t* array;
822  string_t* string;
824  boolean_t boolean;
826  number_integer_t number_integer;
828  number_unsigned_t number_unsigned;
830  number_float_t number_float;
831 
833  json_value() = default;
835  json_value(boolean_t v) noexcept : boolean(v) {}
837  json_value(number_integer_t v) noexcept : number_integer(v) {}
839  json_value(number_unsigned_t v) noexcept : number_unsigned(v) {}
841  json_value(number_float_t v) noexcept : number_float(v) {}
843  json_value(value_t t)
844  {
845  switch (t)
846  {
847  case value_t::object:
848  {
849  object = create<object_t>();
850  break;
851  }
852 
853  case value_t::array:
854  {
855  array = create<array_t>();
856  break;
857  }
858 
859  case value_t::string:
860  {
861  string = create<string_t>("");
862  break;
863  }
864 
865  case value_t::boolean:
866  {
867  boolean = boolean_t(false);
868  break;
869  }
870 
871  case value_t::number_integer:
872  {
873  number_integer = number_integer_t(0);
874  break;
875  }
876 
877  case value_t::number_unsigned:
878  {
879  number_unsigned = number_unsigned_t(0);
880  break;
881  }
882 
883  case value_t::number_float:
884  {
885  number_float = number_float_t(0.0);
886  break;
887  }
888 
889  default:
890  {
891  break;
892  }
893  }
894  }
895 
897  json_value(const string_t& value)
898  {
899  string = create<string_t>(value);
900  }
901 
903  json_value(const object_t& value)
904  {
905  object = create<object_t>(value);
906  }
907 
909  json_value(const array_t& value)
910  {
911  array = create<array_t>(value);
912  }
913  };
914 
924  void assert_invariant() const
925  {
926  assert(m_type != value_t::object or m_value.object != nullptr);
927  assert(m_type != value_t::array or m_value.array != nullptr);
928  assert(m_type != value_t::string or m_value.string != nullptr);
929  }
930 
931  public:
933  // JSON parser callback //
935 
946  enum class parse_event_t : uint8_t
947  {
949  object_start,
951  object_end,
953  array_start,
955  array_end,
957  key,
959  value
960  };
961 
1014  using parser_callback_t = std::function<bool(int depth,
1015  parse_event_t event,
1016  basic_json& parsed)>;
1017 
1018 
1020  // constructors //
1022 
1027 
1068  : m_type(value_type), m_value(value_type)
1069  {
1070  assert_invariant();
1071  }
1072 
1091  basic_json(std::nullptr_t = nullptr) noexcept
1092  : basic_json(value_t::null)
1093  {
1094  assert_invariant();
1095  }
1096 
1116  basic_json(const object_t& val)
1117  : m_type(value_t::object), m_value(val)
1118  {
1119  assert_invariant();
1120  }
1121 
1148  template<class CompatibleObjectType, typename std::enable_if<
1149  std::is_constructible<typename object_t::key_type, typename CompatibleObjectType::key_type>::value and
1150  std::is_constructible<basic_json, typename CompatibleObjectType::mapped_type>::value, int>::type = 0>
1151  basic_json(const CompatibleObjectType& val)
1152  : m_type(value_t::object)
1153  {
1154  using std::begin;
1155  using std::end;
1156  m_value.object = create<object_t>(begin(val), end(val));
1157  assert_invariant();
1158  }
1159 
1179  basic_json(const array_t& val)
1180  : m_type(value_t::array), m_value(val)
1181  {
1182  assert_invariant();
1183  }
1184 
1211  template<class CompatibleArrayType, typename std::enable_if<
1212  not std::is_same<CompatibleArrayType, typename basic_json_t::iterator>::value and
1213  not std::is_same<CompatibleArrayType, typename basic_json_t::const_iterator>::value and
1214  not std::is_same<CompatibleArrayType, typename basic_json_t::reverse_iterator>::value and
1215  not std::is_same<CompatibleArrayType, typename basic_json_t::const_reverse_iterator>::value and
1216  not std::is_same<CompatibleArrayType, typename array_t::iterator>::value and
1217  not std::is_same<CompatibleArrayType, typename array_t::const_iterator>::value and
1218  std::is_constructible<basic_json, typename CompatibleArrayType::value_type>::value, int>::type = 0>
1219  basic_json(const CompatibleArrayType& val)
1220  : m_type(value_t::array)
1221  {
1222  using std::begin;
1223  using std::end;
1224  m_value.array = create<array_t>(begin(val), end(val));
1225  assert_invariant();
1226  }
1227 
1249  basic_json(const string_t& val)
1250  : m_type(value_t::string), m_value(val)
1251  {
1252  assert_invariant();
1253  }
1254 
1275  basic_json(const typename string_t::value_type* val)
1276  : basic_json(string_t(val))
1277  {
1278  assert_invariant();
1279  }
1280 
1304  template<class CompatibleStringType, typename std::enable_if<
1305  std::is_constructible<string_t, CompatibleStringType>::value, int>::type = 0>
1306  basic_json(const CompatibleStringType& val)
1307  : basic_json(string_t(val))
1308  {
1309  assert_invariant();
1310  }
1311 
1326  basic_json(boolean_t val) noexcept
1327  : m_type(value_t::boolean), m_value(val)
1328  {
1329  assert_invariant();
1330  }
1331 
1355  template<typename T, typename std::enable_if<
1356  not (std::is_same<T, int>::value) and
1357  std::is_same<T, number_integer_t>::value, int>::type = 0>
1358  basic_json(const number_integer_t val) noexcept
1359  : m_type(value_t::number_integer), m_value(val)
1360  {
1361  assert_invariant();
1362  }
1363 
1389  basic_json(const int val) noexcept
1390  : m_type(value_t::number_integer),
1391  m_value(static_cast<number_integer_t>(val))
1392  {
1393  assert_invariant();
1394  }
1395 
1421  template<typename CompatibleNumberIntegerType, typename std::enable_if<
1422  std::is_constructible<number_integer_t, CompatibleNumberIntegerType>::value and
1423  std::numeric_limits<CompatibleNumberIntegerType>::is_integer and
1424  std::numeric_limits<CompatibleNumberIntegerType>::is_signed,
1425  CompatibleNumberIntegerType>::type = 0>
1426  basic_json(const CompatibleNumberIntegerType val) noexcept
1427  : m_type(value_t::number_integer),
1428  m_value(static_cast<number_integer_t>(val))
1429  {
1430  assert_invariant();
1431  }
1432 
1450  template<typename T, typename std::enable_if<
1451  not (std::is_same<T, int>::value) and
1452  std::is_same<T, number_unsigned_t>::value, int>::type = 0>
1453  basic_json(const number_unsigned_t val) noexcept
1454  : m_type(value_t::number_unsigned), m_value(val)
1455  {
1456  assert_invariant();
1457  }
1458 
1479  template<typename CompatibleNumberUnsignedType, typename std::enable_if <
1480  std::is_constructible<number_unsigned_t, CompatibleNumberUnsignedType>::value and
1481  std::numeric_limits<CompatibleNumberUnsignedType>::is_integer and
1482  not std::numeric_limits<CompatibleNumberUnsignedType>::is_signed,
1483  CompatibleNumberUnsignedType>::type = 0>
1484  basic_json(const CompatibleNumberUnsignedType val) noexcept
1485  : m_type(value_t::number_unsigned),
1486  m_value(static_cast<number_unsigned_t>(val))
1487  {
1488  assert_invariant();
1489  }
1490 
1515  basic_json(const number_float_t val) noexcept
1516  : m_type(value_t::number_float), m_value(val)
1517  {
1518  // replace infinity and NAN by null
1519  if (not std::isfinite(val))
1520  {
1521  m_type = value_t::null;
1522  m_value = json_value();
1523  }
1524 
1525  assert_invariant();
1526  }
1527 
1559  template<typename CompatibleNumberFloatType, typename = typename std::enable_if<
1560  std::is_constructible<number_float_t, CompatibleNumberFloatType>::value and
1561  std::is_floating_point<CompatibleNumberFloatType>::value>::type>
1562  basic_json(const CompatibleNumberFloatType val) noexcept
1563  : basic_json(number_float_t(val))
1564  {
1565  assert_invariant();
1566  }
1567 
1637  basic_json(std::initializer_list<basic_json> init,
1638  bool type_deduction = true,
1639  value_t manual_type = value_t::array)
1640  {
1641  // check if each element is an array with two elements whose first
1642  // element is a string
1643  bool is_an_object = std::all_of(init.begin(), init.end(),
1644  [](const basic_json & element)
1645  {
1646  return element.is_array() and element.size() == 2 and element[0].is_string();
1647  });
1648 
1649  // adjust type if type deduction is not wanted
1650  if (not type_deduction)
1651  {
1652  // if array is wanted, do not create an object though possible
1653  if (manual_type == value_t::array)
1654  {
1655  is_an_object = false;
1656  }
1657 
1658  // if object is wanted but impossible, throw an exception
1659  if (manual_type == value_t::object and not is_an_object)
1660  {
1661  throw std::domain_error("cannot create object from initializer list");
1662  }
1663  }
1664 
1665  if (is_an_object)
1666  {
1667  // the initializer list is a list of pairs -> create object
1668  m_type = value_t::object;
1669  m_value = value_t::object;
1670 
1671  std::for_each(init.begin(), init.end(), [this](const basic_json & element)
1672  {
1673  m_value.object->emplace(*(element[0].m_value.string), element[1]);
1674  });
1675  }
1676  else
1677  {
1678  // the initializer list describes an array -> create array
1679  m_type = value_t::array;
1680  m_value.array = create<array_t>(init);
1681  }
1682 
1683  assert_invariant();
1684  }
1685 
1720  static basic_json array(std::initializer_list<basic_json> init =
1721  std::initializer_list<basic_json>())
1722  {
1723  return basic_json(init, false, value_t::array);
1724  }
1725 
1760  static basic_json object(std::initializer_list<basic_json> init =
1761  std::initializer_list<basic_json>())
1762  {
1763  return basic_json(init, false, value_t::object);
1764  }
1765 
1785  : m_type(value_t::array)
1786  {
1787  m_value.array = create<array_t>(cnt, val);
1788  assert_invariant();
1789  }
1790 
1828  template<class InputIT, typename std::enable_if<
1829  std::is_same<InputIT, typename basic_json_t::iterator>::value or
1830  std::is_same<InputIT, typename basic_json_t::const_iterator>::value, int>::type = 0>
1831  basic_json(InputIT first, InputIT last)
1832  {
1833  assert(first.m_object != nullptr);
1834  assert(last.m_object != nullptr);
1835 
1836  // make sure iterator fits the current value
1837  if (first.m_object != last.m_object)
1838  {
1839  throw std::domain_error("iterators are not compatible");
1840  }
1841 
1842  // copy type from first iterator
1843  m_type = first.m_object->m_type;
1844 
1845  // check if iterator range is complete for primitive values
1846  switch (m_type)
1847  {
1848  case value_t::boolean:
1849  case value_t::number_float:
1850  case value_t::number_integer:
1851  case value_t::number_unsigned:
1852  case value_t::string:
1853  {
1854  if (not first.m_it.primitive_iterator.is_begin() or not last.m_it.primitive_iterator.is_end())
1855  {
1856  throw std::out_of_range("iterators out of range");
1857  }
1858  break;
1859  }
1860 
1861  default:
1862  {
1863  break;
1864  }
1865  }
1866 
1867  switch (m_type)
1868  {
1869  case value_t::number_integer:
1870  {
1871  m_value.number_integer = first.m_object->m_value.number_integer;
1872  break;
1873  }
1874 
1875  case value_t::number_unsigned:
1876  {
1877  m_value.number_unsigned = first.m_object->m_value.number_unsigned;
1878  break;
1879  }
1880 
1881  case value_t::number_float:
1882  {
1883  m_value.number_float = first.m_object->m_value.number_float;
1884  break;
1885  }
1886 
1887  case value_t::boolean:
1888  {
1889  m_value.boolean = first.m_object->m_value.boolean;
1890  break;
1891  }
1892 
1893  case value_t::string:
1894  {
1895  m_value = *first.m_object->m_value.string;
1896  break;
1897  }
1898 
1899  case value_t::object:
1900  {
1901  m_value.object = create<object_t>(first.m_it.object_iterator, last.m_it.object_iterator);
1902  break;
1903  }
1904 
1905  case value_t::array:
1906  {
1907  m_value.array = create<array_t>(first.m_it.array_iterator, last.m_it.array_iterator);
1908  break;
1909  }
1910 
1911  default:
1912  {
1913  throw std::domain_error("cannot use construct with iterators from " + first.m_object->type_name());
1914  }
1915  }
1916 
1917  assert_invariant();
1918  }
1919 
1948  JSON_DEPRECATED
1949  explicit basic_json(std::istream& i, const parser_callback_t cb = nullptr)
1950  {
1951  *this = parser(i, cb).parse();
1952  assert_invariant();
1953  }
1954 
1956  // other constructors and destructor //
1958 
1981  basic_json(const basic_json& other)
1982  : m_type(other.m_type)
1983  {
1984  // check of passed value is valid
1985  other.assert_invariant();
1986 
1987  switch (m_type)
1988  {
1989  case value_t::object:
1990  {
1991  m_value = *other.m_value.object;
1992  break;
1993  }
1994 
1995  case value_t::array:
1996  {
1997  m_value = *other.m_value.array;
1998  break;
1999  }
2000 
2001  case value_t::string:
2002  {
2003  m_value = *other.m_value.string;
2004  break;
2005  }
2006 
2007  case value_t::boolean:
2008  {
2009  m_value = other.m_value.boolean;
2010  break;
2011  }
2012 
2013  case value_t::number_integer:
2014  {
2015  m_value = other.m_value.number_integer;
2016  break;
2017  }
2018 
2019  case value_t::number_unsigned:
2020  {
2021  m_value = other.m_value.number_unsigned;
2022  break;
2023  }
2024 
2025  case value_t::number_float:
2026  {
2027  m_value = other.m_value.number_float;
2028  break;
2029  }
2030 
2031  default:
2032  {
2033  break;
2034  }
2035  }
2036 
2037  assert_invariant();
2038  }
2039 
2058  basic_json(basic_json&& other) noexcept
2059  : m_type(std::move(other.m_type)),
2060  m_value(std::move(other.m_value))
2061  {
2062  // check that passed value is valid
2063  other.assert_invariant();
2064 
2065  // invalidate payload
2066  other.m_type = value_t::null;
2067  other.m_value = {};
2068 
2069  assert_invariant();
2070  }
2071 
2095  reference& operator=(basic_json other) noexcept (
2096  std::is_nothrow_move_constructible<value_t>::value and
2097  std::is_nothrow_move_assignable<value_t>::value and
2098  std::is_nothrow_move_constructible<json_value>::value and
2099  std::is_nothrow_move_assignable<json_value>::value
2100  )
2101  {
2102  // check that passed value is valid
2103  other.assert_invariant();
2104 
2105  using std::swap;
2106  swap(m_type, other.m_type);
2107  swap(m_value, other.m_value);
2108 
2109  assert_invariant();
2110  return *this;
2111  }
2112 
2129  {
2130  assert_invariant();
2131 
2132  switch (m_type)
2133  {
2134  case value_t::object:
2135  {
2136  AllocatorType<object_t> alloc;
2137  alloc.destroy(m_value.object);
2138  alloc.deallocate(m_value.object, 1);
2139  break;
2140  }
2141 
2142  case value_t::array:
2143  {
2144  AllocatorType<array_t> alloc;
2145  alloc.destroy(m_value.array);
2146  alloc.deallocate(m_value.array, 1);
2147  break;
2148  }
2149 
2150  case value_t::string:
2151  {
2152  AllocatorType<string_t> alloc;
2153  alloc.destroy(m_value.string);
2154  alloc.deallocate(m_value.string, 1);
2155  break;
2156  }
2157 
2158  default:
2159  {
2160  // all other types need no specific destructor
2161  break;
2162  }
2163  }
2164  }
2165 
2167 
2168  public:
2170  // object inspection //
2172 
2176 
2200  string_t dump(const int indent = -1) const
2201  {
2202  std::stringstream ss;
2203  // fix locale problems
2204  const static std::locale loc(std::locale(), new DecimalSeparator);
2205  ss.imbue(loc);
2206 
2207  // 6, 15 or 16 digits of precision allows round-trip IEEE 754
2208  // string->float->string, string->double->string or string->long
2209  // double->string; to be safe, we read this value from
2210  // std::numeric_limits<number_float_t>::digits10
2211  ss.precision(std::numeric_limits<double>::digits10);
2212 
2213  if (indent >= 0)
2214  {
2215  dump(ss, true, static_cast<unsigned int>(indent));
2216  }
2217  else
2218  {
2219  dump(ss, false, 0);
2220  }
2221 
2222  return ss.str();
2223  }
2224 
2243  constexpr value_t type() const noexcept
2244  {
2245  return m_type;
2246  }
2247 
2273  constexpr bool is_primitive() const noexcept
2274  {
2275  return is_null() or is_string() or is_boolean() or is_number();
2276  }
2277 
2300  constexpr bool is_structured() const noexcept
2301  {
2302  return is_array() or is_object();
2303  }
2304 
2322  constexpr bool is_null() const noexcept
2323  {
2324  return m_type == value_t::null;
2325  }
2326 
2344  constexpr bool is_boolean() const noexcept
2345  {
2346  return m_type == value_t::boolean;
2347  }
2348 
2374  constexpr bool is_number() const noexcept
2375  {
2376  return is_number_integer() or is_number_float();
2377  }
2378 
2403  constexpr bool is_number_integer() const noexcept
2404  {
2405  return m_type == value_t::number_integer or m_type == value_t::number_unsigned;
2406  }
2407 
2431  constexpr bool is_number_unsigned() const noexcept
2432  {
2433  return m_type == value_t::number_unsigned;
2434  }
2435 
2459  constexpr bool is_number_float() const noexcept
2460  {
2461  return m_type == value_t::number_float;
2462  }
2463 
2481  constexpr bool is_object() const noexcept
2482  {
2483  return m_type == value_t::object;
2484  }
2485 
2503  constexpr bool is_array() const noexcept
2504  {
2505  return m_type == value_t::array;
2506  }
2507 
2525  constexpr bool is_string() const noexcept
2526  {
2527  return m_type == value_t::string;
2528  }
2529 
2552  constexpr bool is_discarded() const noexcept
2553  {
2554  return m_type == value_t::discarded;
2555  }
2556 
2575  constexpr operator value_t() const noexcept
2576  {
2577  return m_type;
2578  }
2579 
2581 
2582  private:
2584  // value access //
2586 
2588  template<class T, typename std::enable_if<
2589  std::is_convertible<typename object_t::key_type, typename T::key_type>::value and
2590  std::is_convertible<basic_json_t, typename T::mapped_type>::value, int>::type = 0>
2591  T get_impl(T*) const
2592  {
2593  if (is_object())
2594  {
2595  return T(m_value.object->begin(), m_value.object->end());
2596  }
2597  else
2598  {
2599  throw std::domain_error("type must be object, but is " + type_name());
2600  }
2601  }
2602 
2604  object_t get_impl(object_t*) const
2605  {
2606  if (is_object())
2607  {
2608  return *(m_value.object);
2609  }
2610  else
2611  {
2612  throw std::domain_error("type must be object, but is " + type_name());
2613  }
2614  }
2615 
2617  template<class T, typename std::enable_if<
2618  std::is_convertible<basic_json_t, typename T::value_type>::value and
2619  not std::is_same<basic_json_t, typename T::value_type>::value and
2620  not std::is_arithmetic<T>::value and
2621  not std::is_convertible<std::string, T>::value and
2622  not has_mapped_type<T>::value, int>::type = 0>
2623  T get_impl(T*) const
2624  {
2625  if (is_array())
2626  {
2627  T to_vector;
2628  std::transform(m_value.array->begin(), m_value.array->end(),
2629  std::inserter(to_vector, to_vector.end()), [](basic_json i)
2630  {
2631  return i.get<typename T::value_type>();
2632  });
2633  return to_vector;
2634  }
2635  else
2636  {
2637  throw std::domain_error("type must be array, but is " + type_name());
2638  }
2639  }
2640 
2642  template<class T, typename std::enable_if<
2643  std::is_convertible<basic_json_t, T>::value and
2644  not std::is_same<basic_json_t, T>::value, int>::type = 0>
2645  std::vector<T> get_impl(std::vector<T>*) const
2646  {
2647  if (is_array())
2648  {
2649  std::vector<T> to_vector;
2650  to_vector.reserve(m_value.array->size());
2651  std::transform(m_value.array->begin(), m_value.array->end(),
2652  std::inserter(to_vector, to_vector.end()), [](basic_json i)
2653  {
2654  return i.get<T>();
2655  });
2656  return to_vector;
2657  }
2658  else
2659  {
2660  throw std::domain_error("type must be array, but is " + type_name());
2661  }
2662  }
2663 
2665  template<class T, typename std::enable_if<
2666  std::is_same<basic_json, typename T::value_type>::value and
2667  not has_mapped_type<T>::value, int>::type = 0>
2668  T get_impl(T*) const
2669  {
2670  if (is_array())
2671  {
2672  return T(m_value.array->begin(), m_value.array->end());
2673  }
2674  else
2675  {
2676  throw std::domain_error("type must be array, but is " + type_name());
2677  }
2678  }
2679 
2681  array_t get_impl(array_t*) const
2682  {
2683  if (is_array())
2684  {
2685  return *(m_value.array);
2686  }
2687  else
2688  {
2689  throw std::domain_error("type must be array, but is " + type_name());
2690  }
2691  }
2692 
2694  template<typename T, typename std::enable_if<
2695  std::is_convertible<string_t, T>::value, int>::type = 0>
2696  T get_impl(T*) const
2697  {
2698  if (is_string())
2699  {
2700  return *m_value.string;
2701  }
2702  else
2703  {
2704  throw std::domain_error("type must be string, but is " + type_name());
2705  }
2706  }
2707 
2709  template<typename T, typename std::enable_if<
2710  std::is_arithmetic<T>::value, int>::type = 0>
2711  T get_impl(T*) const
2712  {
2713  switch (m_type)
2714  {
2715  case value_t::number_integer:
2716  {
2717  return static_cast<T>(m_value.number_integer);
2718  }
2719 
2720  case value_t::number_unsigned:
2721  {
2722  return static_cast<T>(m_value.number_unsigned);
2723  }
2724 
2725  case value_t::number_float:
2726  {
2727  return static_cast<T>(m_value.number_float);
2728  }
2729 
2730  default:
2731  {
2732  throw std::domain_error("type must be number, but is " + type_name());
2733  }
2734  }
2735  }
2736 
2738  constexpr boolean_t get_impl(boolean_t*) const
2739  {
2740  return is_boolean()
2741  ? m_value.boolean
2742  : throw std::domain_error("type must be boolean, but is " + type_name());
2743  }
2744 
2746  object_t* get_impl_ptr(object_t*) noexcept
2747  {
2748  return is_object() ? m_value.object : nullptr;
2749  }
2750 
2752  constexpr const object_t* get_impl_ptr(const object_t*) const noexcept
2753  {
2754  return is_object() ? m_value.object : nullptr;
2755  }
2756 
2758  array_t* get_impl_ptr(array_t*) noexcept
2759  {
2760  return is_array() ? m_value.array : nullptr;
2761  }
2762 
2764  constexpr const array_t* get_impl_ptr(const array_t*) const noexcept
2765  {
2766  return is_array() ? m_value.array : nullptr;
2767  }
2768 
2770  string_t* get_impl_ptr(string_t*) noexcept
2771  {
2772  return is_string() ? m_value.string : nullptr;
2773  }
2774 
2776  constexpr const string_t* get_impl_ptr(const string_t*) const noexcept
2777  {
2778  return is_string() ? m_value.string : nullptr;
2779  }
2780 
2782  boolean_t* get_impl_ptr(boolean_t*) noexcept
2783  {
2784  return is_boolean() ? &m_value.boolean : nullptr;
2785  }
2786 
2788  constexpr const boolean_t* get_impl_ptr(const boolean_t*) const noexcept
2789  {
2790  return is_boolean() ? &m_value.boolean : nullptr;
2791  }
2792 
2794  number_integer_t* get_impl_ptr(number_integer_t*) noexcept
2795  {
2796  return is_number_integer() ? &m_value.number_integer : nullptr;
2797  }
2798 
2800  constexpr const number_integer_t* get_impl_ptr(const number_integer_t*) const noexcept
2801  {
2802  return is_number_integer() ? &m_value.number_integer : nullptr;
2803  }
2804 
2806  number_unsigned_t* get_impl_ptr(number_unsigned_t*) noexcept
2807  {
2808  return is_number_unsigned() ? &m_value.number_unsigned : nullptr;
2809  }
2810 
2812  constexpr const number_unsigned_t* get_impl_ptr(const number_unsigned_t*) const noexcept
2813  {
2814  return is_number_unsigned() ? &m_value.number_unsigned : nullptr;
2815  }
2816 
2818  number_float_t* get_impl_ptr(number_float_t*) noexcept
2819  {
2820  return is_number_float() ? &m_value.number_float : nullptr;
2821  }
2822 
2824  constexpr const number_float_t* get_impl_ptr(const number_float_t*) const noexcept
2825  {
2826  return is_number_float() ? &m_value.number_float : nullptr;
2827  }
2828 
2840  template<typename ReferenceType, typename ThisType>
2841  static ReferenceType get_ref_impl(ThisType& obj)
2842  {
2843  // helper type
2844  using PointerType = typename std::add_pointer<ReferenceType>::type;
2845 
2846  // delegate the call to get_ptr<>()
2847  auto ptr = obj.template get_ptr<PointerType>();
2848 
2849  if (ptr != nullptr)
2850  {
2851  return *ptr;
2852  }
2853  else
2854  {
2855  throw std::domain_error("incompatible ReferenceType for get_ref, actual type is " +
2856  obj.type_name());
2857  }
2858  }
2859 
2860  public:
2861 
2865 
2899  template<typename ValueType, typename std::enable_if<
2900  not std::is_pointer<ValueType>::value, int>::type = 0>
2901  ValueType get() const
2902  {
2903  return get_impl(static_cast<ValueType*>(nullptr));
2904  }
2905 
2933  template<typename PointerType, typename std::enable_if<
2934  std::is_pointer<PointerType>::value, int>::type = 0>
2935  PointerType get() noexcept
2936  {
2937  // delegate the call to get_ptr
2938  return get_ptr<PointerType>();
2939  }
2940 
2945  template<typename PointerType, typename std::enable_if<
2946  std::is_pointer<PointerType>::value, int>::type = 0>
2947  constexpr const PointerType get() const noexcept
2948  {
2949  // delegate the call to get_ptr
2950  return get_ptr<PointerType>();
2951  }
2952 
2979  template<typename PointerType, typename std::enable_if<
2980  std::is_pointer<PointerType>::value, int>::type = 0>
2981  PointerType get_ptr() noexcept
2982  {
2983  // get the type of the PointerType (remove pointer and const)
2984  using pointee_t = typename std::remove_const<typename
2985  std::remove_pointer<typename
2986  std::remove_const<PointerType>::type>::type>::type;
2987  // make sure the type matches the allowed types
2988  static_assert(
2989  std::is_same<object_t, pointee_t>::value
2990  or std::is_same<array_t, pointee_t>::value
2991  or std::is_same<string_t, pointee_t>::value
2992  or std::is_same<boolean_t, pointee_t>::value
2993  or std::is_same<number_integer_t, pointee_t>::value
2994  or std::is_same<number_unsigned_t, pointee_t>::value
2995  or std::is_same<number_float_t, pointee_t>::value
2996  , "incompatible pointer type");
2997 
2998  // delegate the call to get_impl_ptr<>()
2999  return get_impl_ptr(static_cast<PointerType>(nullptr));
3000  }
3001 
3006  template<typename PointerType, typename std::enable_if<
3007  std::is_pointer<PointerType>::value and
3008  std::is_const<typename std::remove_pointer<PointerType>::type>::value, int>::type = 0>
3009  constexpr const PointerType get_ptr() const noexcept
3010  {
3011  // get the type of the PointerType (remove pointer and const)
3012  using pointee_t = typename std::remove_const<typename
3013  std::remove_pointer<typename
3014  std::remove_const<PointerType>::type>::type>::type;
3015  // make sure the type matches the allowed types
3016  static_assert(
3017  std::is_same<object_t, pointee_t>::value
3018  or std::is_same<array_t, pointee_t>::value
3019  or std::is_same<string_t, pointee_t>::value
3020  or std::is_same<boolean_t, pointee_t>::value
3021  or std::is_same<number_integer_t, pointee_t>::value
3022  or std::is_same<number_unsigned_t, pointee_t>::value
3023  or std::is_same<number_float_t, pointee_t>::value
3024  , "incompatible pointer type");
3025 
3026  // delegate the call to get_impl_ptr<>() const
3027  return get_impl_ptr(static_cast<const PointerType>(nullptr));
3028  }
3029 
3056  template<typename ReferenceType, typename std::enable_if<
3057  std::is_reference<ReferenceType>::value, int>::type = 0>
3058  ReferenceType get_ref()
3059  {
3060  // delegate call to get_ref_impl
3061  return get_ref_impl<ReferenceType>(*this);
3062  }
3063 
3068  template<typename ReferenceType, typename std::enable_if<
3069  std::is_reference<ReferenceType>::value and
3070  std::is_const<typename std::remove_reference<ReferenceType>::type>::value, int>::type = 0>
3071  ReferenceType get_ref() const
3072  {
3073  // delegate call to get_ref_impl
3074  return get_ref_impl<ReferenceType>(*this);
3075  }
3076 
3105  template < typename ValueType, typename std::enable_if <
3106  not std::is_pointer<ValueType>::value and
3107  not std::is_same<ValueType, typename string_t::value_type>::value
3108 #ifndef _MSC_VER // Fix for issue #167 operator<< abiguity under VS2015
3109  and not std::is_same<ValueType, std::initializer_list<typename string_t::value_type>>::value
3110 #endif
3111  , int >::type = 0 >
3112  operator ValueType() const
3113  {
3114  // delegate the call to get<>() const
3115  return get<ValueType>();
3116  }
3117 
3119 
3120 
3122  // element access //
3124 
3128 
3152  {
3153  // at only works for arrays
3154  if (is_array())
3155  {
3156  try
3157  {
3158  return m_value.array->at(idx);
3159  }
3160  catch (std::out_of_range&)
3161  {
3162  // create better exception explanation
3163  throw std::out_of_range("array index " + std::to_string(idx) + " is out of range");
3164  }
3165  }
3166  else
3167  {
3168  throw std::domain_error("cannot use at() with " + type_name());
3169  }
3170  }
3171 
3195  {
3196  // at only works for arrays
3197  if (is_array())
3198  {
3199  try
3200  {
3201  return m_value.array->at(idx);
3202  }
3203  catch (std::out_of_range&)
3204  {
3205  // create better exception explanation
3206  throw std::out_of_range("array index " + std::to_string(idx) + " is out of range");
3207  }
3208  }
3209  else
3210  {
3211  throw std::domain_error("cannot use at() with " + type_name());
3212  }
3213  }
3214 
3241  reference at(const typename object_t::key_type& key)
3242  {
3243  // at only works for objects
3244  if (is_object())
3245  {
3246  try
3247  {
3248  return m_value.object->at(key);
3249  }
3250  catch (std::out_of_range&)
3251  {
3252  // create better exception explanation
3253  throw std::out_of_range("key '" + key + "' not found");
3254  }
3255  }
3256  else
3257  {
3258  throw std::domain_error("cannot use at() with " + type_name());
3259  }
3260  }
3261 
3288  const_reference at(const typename object_t::key_type& key) const
3289  {
3290  // at only works for objects
3291  if (is_object())
3292  {
3293  try
3294  {
3295  return m_value.object->at(key);
3296  }
3297  catch (std::out_of_range&)
3298  {
3299  // create better exception explanation
3300  throw std::out_of_range("key '" + key + "' not found");
3301  }
3302  }
3303  else
3304  {
3305  throw std::domain_error("cannot use at() with " + type_name());
3306  }
3307  }
3308 
3335  {
3336  // implicitly convert null value to an empty array
3337  if (is_null())
3338  {
3339  m_type = value_t::array;
3340  m_value.array = create<array_t>();
3341  assert_invariant();
3342  }
3343 
3344  // operator[] only works for arrays
3345  if (is_array())
3346  {
3347  // fill up array with null values if given idx is outside range
3348  if (idx >= m_value.array->size())
3349  {
3350  m_value.array->insert(m_value.array->end(),
3351  idx - m_value.array->size() + 1,
3352  basic_json());
3353  }
3354 
3355  return m_value.array->operator[](idx);
3356  }
3357  else
3358  {
3359  throw std::domain_error("cannot use operator[] with " + type_name());
3360  }
3361  }
3362 
3383  {
3384  // const operator[] only works for arrays
3385  if (is_array())
3386  {
3387  return m_value.array->operator[](idx);
3388  }
3389  else
3390  {
3391  throw std::domain_error("cannot use operator[] with " + type_name());
3392  }
3393  }
3394 
3422  reference operator[](const typename object_t::key_type& key)
3423  {
3424  // implicitly convert null value to an empty object
3425  if (is_null())
3426  {
3427  m_type = value_t::object;
3428  m_value.object = create<object_t>();
3429  assert_invariant();
3430  }
3431 
3432  // operator[] only works for objects
3433  if (is_object())
3434  {
3435  return m_value.object->operator[](key);
3436  }
3437  else
3438  {
3439  throw std::domain_error("cannot use operator[] with " + type_name());
3440  }
3441  }
3442 
3473  const_reference operator[](const typename object_t::key_type& key) const
3474  {
3475  // const operator[] only works for objects
3476  if (is_object())
3477  {
3478  assert(m_value.object->find(key) != m_value.object->end());
3479  return m_value.object->find(key)->second;
3480  }
3481  else
3482  {
3483  throw std::domain_error("cannot use operator[] with " + type_name());
3484  }
3485  }
3486 
3514  template<typename T, std::size_t n>
3515  reference operator[](T * (&key)[n])
3516  {
3517  return operator[](static_cast<const T>(key));
3518  }
3519 
3549  template<typename T, std::size_t n>
3550  const_reference operator[](T * (&key)[n]) const
3551  {
3552  return operator[](static_cast<const T>(key));
3553  }
3554 
3582  template<typename T>
3584  {
3585  // implicitly convert null to object
3586  if (is_null())
3587  {
3588  m_type = value_t::object;
3589  m_value = value_t::object;
3590  assert_invariant();
3591  }
3592 
3593  // at only works for objects
3594  if (is_object())
3595  {
3596  return m_value.object->operator[](key);
3597  }
3598  else
3599  {
3600  throw std::domain_error("cannot use operator[] with " + type_name());
3601  }
3602  }
3603 
3634  template<typename T>
3636  {
3637  // at only works for objects
3638  if (is_object())
3639  {
3640  assert(m_value.object->find(key) != m_value.object->end());
3641  return m_value.object->find(key)->second;
3642  }
3643  else
3644  {
3645  throw std::domain_error("cannot use operator[] with " + type_name());
3646  }
3647  }
3648 
3697  template<class ValueType, typename std::enable_if<
3698  std::is_convertible<basic_json_t, ValueType>::value, int>::type = 0>
3699  ValueType value(const typename object_t::key_type& key, ValueType default_value) const
3700  {
3701  // at only works for objects
3702  if (is_object())
3703  {
3704  // if key is found, return value and given default value otherwise
3705  const auto it = find(key);
3706  if (it != end())
3707  {
3708  return *it;
3709  }
3710  else
3711  {
3712  return default_value;
3713  }
3714  }
3715  else
3716  {
3717  throw std::domain_error("cannot use value() with " + type_name());
3718  }
3719  }
3720 
3725  string_t value(const typename object_t::key_type& key, const char* default_value) const
3726  {
3727  return value(key, string_t(default_value));
3728  }
3729 
3771  template<class ValueType, typename std::enable_if<
3772  std::is_convertible<basic_json_t, ValueType>::value, int>::type = 0>
3773  ValueType value(const json_pointer& ptr, ValueType default_value) const
3774  {
3775  // at only works for objects
3776  if (is_object())
3777  {
3778  // if pointer resolves a value, return it or use default value
3779  try
3780  {
3781  return ptr.get_checked(this);
3782  }
3783  catch (std::out_of_range&)
3784  {
3785  return default_value;
3786  }
3787  }
3788  else
3789  {
3790  throw std::domain_error("cannot use value() with " + type_name());
3791  }
3792  }
3793 
3798  string_t value(const json_pointer& ptr, const char* default_value) const
3799  {
3800  return value(ptr, string_t(default_value));
3801  }
3802 
3829  {
3830  return *begin();
3831  }
3832 
3837  {
3838  return *cbegin();
3839  }
3840 
3872  {
3873  auto tmp = end();
3874  --tmp;
3875  return *tmp;
3876  }
3877 
3882  {
3883  auto tmp = cend();
3884  --tmp;
3885  return *tmp;
3886  }
3887 
3933  template<class IteratorType, typename std::enable_if<
3934  std::is_same<IteratorType, typename basic_json_t::iterator>::value or
3935  std::is_same<IteratorType, typename basic_json_t::const_iterator>::value, int>::type
3936  = 0>
3937  IteratorType erase(IteratorType pos)
3938  {
3939  // make sure iterator fits the current value
3940  if (this != pos.m_object)
3941  {
3942  throw std::domain_error("iterator does not fit current value");
3943  }
3944 
3945  IteratorType result = end();
3946 
3947  switch (m_type)
3948  {
3949  case value_t::boolean:
3950  case value_t::number_float:
3951  case value_t::number_integer:
3952  case value_t::number_unsigned:
3953  case value_t::string:
3954  {
3955  if (not pos.m_it.primitive_iterator.is_begin())
3956  {
3957  throw std::out_of_range("iterator out of range");
3958  }
3959 
3960  if (is_string())
3961  {
3962  AllocatorType<string_t> alloc;
3963  alloc.destroy(m_value.string);
3964  alloc.deallocate(m_value.string, 1);
3965  m_value.string = nullptr;
3966  }
3967 
3968  m_type = value_t::null;
3969  assert_invariant();
3970  break;
3971  }
3972 
3973  case value_t::object:
3974  {
3975  result.m_it.object_iterator = m_value.object->erase(pos.m_it.object_iterator);
3976  break;
3977  }
3978 
3979  case value_t::array:
3980  {
3981  result.m_it.array_iterator = m_value.array->erase(pos.m_it.array_iterator);
3982  break;
3983  }
3984 
3985  default:
3986  {
3987  throw std::domain_error("cannot use erase() with " + type_name());
3988  }
3989  }
3990 
3991  return result;
3992  }
3993 
4040  template<class IteratorType, typename std::enable_if<
4041  std::is_same<IteratorType, typename basic_json_t::iterator>::value or
4042  std::is_same<IteratorType, typename basic_json_t::const_iterator>::value, int>::type
4043  = 0>
4044  IteratorType erase(IteratorType first, IteratorType last)
4045  {
4046  // make sure iterator fits the current value
4047  if (this != first.m_object or this != last.m_object)
4048  {
4049  throw std::domain_error("iterators do not fit current value");
4050  }
4051 
4052  IteratorType result = end();
4053 
4054  switch (m_type)
4055  {
4056  case value_t::boolean:
4057  case value_t::number_float:
4058  case value_t::number_integer:
4059  case value_t::number_unsigned:
4060  case value_t::string:
4061  {
4062  if (not first.m_it.primitive_iterator.is_begin() or not last.m_it.primitive_iterator.is_end())
4063  {
4064  throw std::out_of_range("iterators out of range");
4065  }
4066 
4067  if (is_string())
4068  {
4069  AllocatorType<string_t> alloc;
4070  alloc.destroy(m_value.string);
4071  alloc.deallocate(m_value.string, 1);
4072  m_value.string = nullptr;
4073  }
4074 
4075  m_type = value_t::null;
4076  assert_invariant();
4077  break;
4078  }
4079 
4080  case value_t::object:
4081  {
4082  result.m_it.object_iterator = m_value.object->erase(first.m_it.object_iterator,
4083  last.m_it.object_iterator);
4084  break;
4085  }
4086 
4087  case value_t::array:
4088  {
4089  result.m_it.array_iterator = m_value.array->erase(first.m_it.array_iterator,
4090  last.m_it.array_iterator);
4091  break;
4092  }
4093 
4094  default:
4095  {
4096  throw std::domain_error("cannot use erase() with " + type_name());
4097  }
4098  }
4099 
4100  return result;
4101  }
4102 
4132  size_type erase(const typename object_t::key_type& key)
4133  {
4134  // this erase only works for objects
4135  if (is_object())
4136  {
4137  return m_value.object->erase(key);
4138  }
4139  else
4140  {
4141  throw std::domain_error("cannot use erase() with " + type_name());
4142  }
4143  }
4144 
4169  void erase(const size_type idx)
4170  {
4171  // this erase only works for arrays
4172  if (is_array())
4173  {
4174  if (idx >= size())
4175  {
4176  throw std::out_of_range("array index " + std::to_string(idx) + " is out of range");
4177  }
4178 
4179  m_value.array->erase(m_value.array->begin() + static_cast<difference_type>(idx));
4180  }
4181  else
4182  {
4183  throw std::domain_error("cannot use erase() with " + type_name());
4184  }
4185  }
4186 
4188 
4189 
4191  // lookup //
4193 
4196 
4215  iterator find(typename object_t::key_type key)
4216  {
4217  auto result = end();
4218 
4219  if (is_object())
4220  {
4221  result.m_it.object_iterator = m_value.object->find(key);
4222  }
4223 
4224  return result;
4225  }
4226 
4231  const_iterator find(typename object_t::key_type key) const
4232  {
4233  auto result = cend();
4234 
4235  if (is_object())
4236  {
4237  result.m_it.object_iterator = m_value.object->find(key);
4238  }
4239 
4240  return result;
4241  }
4242 
4261  size_type count(typename object_t::key_type key) const
4262  {
4263  // return 0 for all nonobject types
4264  return is_object() ? m_value.object->count(key) : 0;
4265  }
4266 
4268 
4269 
4271  // iterators //
4273 
4276 
4301  iterator begin() noexcept
4302  {
4303  iterator result(this);
4304  result.set_begin();
4305  return result;
4306  }
4307 
4311  const_iterator begin() const noexcept
4312  {
4313  return cbegin();
4314  }
4315 
4341  const_iterator cbegin() const noexcept
4342  {
4343  const_iterator result(this);
4344  result.set_begin();
4345  return result;
4346  }
4347 
4372  iterator end() noexcept
4373  {
4374  iterator result(this);
4375  result.set_end();
4376  return result;
4377  }
4378 
4382  const_iterator end() const noexcept
4383  {
4384  return cend();
4385  }
4386 
4412  const_iterator cend() const noexcept
4413  {
4414  const_iterator result(this);
4415  result.set_end();
4416  return result;
4417  }
4418 
4443  {
4444  return reverse_iterator(end());
4445  }
4446 
4451  {
4452  return crbegin();
4453  }
4454 
4480  {
4481  return reverse_iterator(begin());
4482  }
4483 
4487  const_reverse_iterator rend() const noexcept
4488  {
4489  return crend();
4490  }
4491 
4517  {
4518  return const_reverse_iterator(cend());
4519  }
4520 
4546  {
4547  return const_reverse_iterator(cbegin());
4548  }
4549 
4550  private:
4551  // forward declaration
4552  template<typename IteratorType> class iteration_proxy;
4553 
4554  public:
4566  static iteration_proxy<iterator> iterator_wrapper(reference cont)
4567  {
4568  return iteration_proxy<iterator>(cont);
4569  }
4570 
4574  static iteration_proxy<const_iterator> iterator_wrapper(const_reference cont)
4575  {
4576  return iteration_proxy<const_iterator>(cont);
4577  }
4578 
4580 
4581 
4583  // capacity //
4585 
4588 
4626  bool empty() const noexcept
4627  {
4628  switch (m_type)
4629  {
4630  case value_t::null:
4631  {
4632  // null values are empty
4633  return true;
4634  }
4635 
4636  case value_t::array:
4637  {
4638  // delegate call to array_t::empty()
4639  return m_value.array->empty();
4640  }
4641 
4642  case value_t::object:
4643  {
4644  // delegate call to object_t::empty()
4645  return m_value.object->empty();
4646  }
4647 
4648  default:
4649  {
4650  // all other types are nonempty
4651  return false;
4652  }
4653  }
4654  }
4655 
4694  size_type size() const noexcept
4695  {
4696  switch (m_type)
4697  {
4698  case value_t::null:
4699  {
4700  // null values are empty
4701  return 0;
4702  }
4703 
4704  case value_t::array:
4705  {
4706  // delegate call to array_t::size()
4707  return m_value.array->size();
4708  }
4709 
4710  case value_t::object:
4711  {
4712  // delegate call to object_t::size()
4713  return m_value.object->size();
4714  }
4715 
4716  default:
4717  {
4718  // all other types have size 1
4719  return 1;
4720  }
4721  }
4722  }
4723 
4760  size_type max_size() const noexcept
4761  {
4762  switch (m_type)
4763  {
4764  case value_t::array:
4765  {
4766  // delegate call to array_t::max_size()
4767  return m_value.array->max_size();
4768  }
4769 
4770  case value_t::object:
4771  {
4772  // delegate call to object_t::max_size()
4773  return m_value.object->max_size();
4774  }
4775 
4776  default:
4777  {
4778  // all other types have max_size() == size()
4779  return size();
4780  }
4781  }
4782  }
4783 
4785 
4786 
4788  // modifiers //
4790 
4793 
4819  void clear() noexcept
4820  {
4821  switch (m_type)
4822  {
4823  case value_t::number_integer:
4824  {
4825  m_value.number_integer = 0;
4826  break;
4827  }
4828 
4829  case value_t::number_unsigned:
4830  {
4831  m_value.number_unsigned = 0;
4832  break;
4833  }
4834 
4835  case value_t::number_float:
4836  {
4837  m_value.number_float = 0.0;
4838  break;
4839  }
4840 
4841  case value_t::boolean:
4842  {
4843  m_value.boolean = false;
4844  break;
4845  }
4846 
4847  case value_t::string:
4848  {
4849  m_value.string->clear();
4850  break;
4851  }
4852 
4853  case value_t::array:
4854  {
4855  m_value.array->clear();
4856  break;
4857  }
4858 
4859  case value_t::object:
4860  {
4861  m_value.object->clear();
4862  break;
4863  }
4864 
4865  default:
4866  {
4867  break;
4868  }
4869  }
4870  }
4871 
4892  void push_back(basic_json&& val)
4893  {
4894  // push_back only works for null objects or arrays
4895  if (not(is_null() or is_array()))
4896  {
4897  throw std::domain_error("cannot use push_back() with " + type_name());
4898  }
4899 
4900  // transform null object into an array
4901  if (is_null())
4902  {
4903  m_type = value_t::array;
4904  m_value = value_t::array;
4905  assert_invariant();
4906  }
4907 
4908  // add element to array (move semantics)
4909  m_value.array->push_back(std::move(val));
4910  // invalidate object
4911  val.m_type = value_t::null;
4912  }
4913 
4919  {
4920  push_back(std::move(val));
4921  return *this;
4922  }
4923 
4928  void push_back(const basic_json& val)
4929  {
4930  // push_back only works for null objects or arrays
4931  if (not(is_null() or is_array()))
4932  {
4933  throw std::domain_error("cannot use push_back() with " + type_name());
4934  }
4935 
4936  // transform null object into an array
4937  if (is_null())
4938  {
4939  m_type = value_t::array;
4940  m_value = value_t::array;
4941  assert_invariant();
4942  }
4943 
4944  // add element to array
4945  m_value.array->push_back(val);
4946  }
4947 
4953  {
4954  push_back(val);
4955  return *this;
4956  }
4957 
4978  void push_back(const typename object_t::value_type& val)
4979  {
4980  // push_back only works for null objects or objects
4981  if (not(is_null() or is_object()))
4982  {
4983  throw std::domain_error("cannot use push_back() with " + type_name());
4984  }
4985 
4986  // transform null object into an object
4987  if (is_null())
4988  {
4989  m_type = value_t::object;
4990  m_value = value_t::object;
4991  assert_invariant();
4992  }
4993 
4994  // add element to array
4995  m_value.object->insert(val);
4996  }
4997 
5002  reference operator+=(const typename object_t::value_type& val)
5003  {
5004  push_back(val);
5005  return *this;
5006  }
5007 
5033  void push_back(std::initializer_list<basic_json> init)
5034  {
5035  if (is_object() and init.size() == 2 and init.begin()->is_string())
5036  {
5037  const string_t key = *init.begin();
5038  push_back(typename object_t::value_type(key, *(init.begin() + 1)));
5039  }
5040  else
5041  {
5042  push_back(basic_json(init));
5043  }
5044  }
5045 
5050  reference operator+=(std::initializer_list<basic_json> init)
5051  {
5052  push_back(init);
5053  return *this;
5054  }
5055 
5079  {
5080  // insert only works for arrays
5081  if (is_array())
5082  {
5083  // check if iterator pos fits to this JSON value
5084  if (pos.m_object != this)
5085  {
5086  throw std::domain_error("iterator does not fit current value");
5087  }
5088 
5089  // insert to array and return iterator
5090  iterator result(this);
5091  result.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator, val);
5092  return result;
5093  }
5094  else
5095  {
5096  throw std::domain_error("cannot use insert() with " + type_name());
5097  }
5098  }
5099 
5105  {
5106  return insert(pos, val);
5107  }
5108 
5134  {
5135  // insert only works for arrays
5136  if (is_array())
5137  {
5138  // check if iterator pos fits to this JSON value
5139  if (pos.m_object != this)
5140  {
5141  throw std::domain_error("iterator does not fit current value");
5142  }
5143 
5144  // insert to array and return iterator
5145  iterator result(this);
5146  result.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator, cnt, val);
5147  return result;
5148  }
5149  else
5150  {
5151  throw std::domain_error("cannot use insert() with " + type_name());
5152  }
5153  }
5154 
5186  {
5187  // insert only works for arrays
5188  if (not is_array())
5189  {
5190  throw std::domain_error("cannot use insert() with " + type_name());
5191  }
5192 
5193  // check if iterator pos fits to this JSON value
5194  if (pos.m_object != this)
5195  {
5196  throw std::domain_error("iterator does not fit current value");
5197  }
5198 
5199  // check if range iterators belong to the same JSON object
5200  if (first.m_object != last.m_object)
5201  {
5202  throw std::domain_error("iterators do not fit");
5203  }
5204 
5205  if (first.m_object == this or last.m_object == this)
5206  {
5207  throw std::domain_error("passed iterators may not belong to container");
5208  }
5209 
5210  // insert to array and return iterator
5211  iterator result(this);
5212  result.m_it.array_iterator = m_value.array->insert(
5213  pos.m_it.array_iterator,
5214  first.m_it.array_iterator,
5215  last.m_it.array_iterator);
5216  return result;
5217  }
5218 
5243  iterator insert(const_iterator pos, std::initializer_list<basic_json> ilist)
5244  {
5245  // insert only works for arrays
5246  if (not is_array())
5247  {
5248  throw std::domain_error("cannot use insert() with " + type_name());
5249  }
5250 
5251  // check if iterator pos fits to this JSON value
5252  if (pos.m_object != this)
5253  {
5254  throw std::domain_error("iterator does not fit current value");
5255  }
5256 
5257  // insert to array and return iterator
5258  iterator result(this);
5259  result.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator, ilist);
5260  return result;
5261  }
5262 
5280  void swap(reference other) noexcept (
5281  std::is_nothrow_move_constructible<value_t>::value and
5282  std::is_nothrow_move_assignable<value_t>::value and
5283  std::is_nothrow_move_constructible<json_value>::value and
5284  std::is_nothrow_move_assignable<json_value>::value
5285  )
5286  {
5287  std::swap(m_type, other.m_type);
5288  std::swap(m_value, other.m_value);
5289  assert_invariant();
5290  }
5291 
5312  void swap(array_t& other)
5313  {
5314  // swap only works for arrays
5315  if (is_array())
5316  {
5317  std::swap(*(m_value.array), other);
5318  }
5319  else
5320  {
5321  throw std::domain_error("cannot use swap() with " + type_name());
5322  }
5323  }
5324 
5345  void swap(object_t& other)
5346  {
5347  // swap only works for objects
5348  if (is_object())
5349  {
5350  std::swap(*(m_value.object), other);
5351  }
5352  else
5353  {
5354  throw std::domain_error("cannot use swap() with " + type_name());
5355  }
5356  }
5357 
5378  void swap(string_t& other)
5379  {
5380  // swap only works for strings
5381  if (is_string())
5382  {
5383  std::swap(*(m_value.string), other);
5384  }
5385  else
5386  {
5387  throw std::domain_error("cannot use swap() with " + type_name());
5388  }
5389  }
5390 
5392 
5393 
5395  // lexicographical comparison operators //
5397 
5400 
5401  private:
5411  friend bool operator<(const value_t lhs, const value_t rhs) noexcept
5412  {
5413  static constexpr std::array<uint8_t, 8> order = {{
5414  0, // null
5415  3, // object
5416  4, // array
5417  5, // string
5418  1, // boolean
5419  2, // integer
5420  2, // unsigned
5421  2, // float
5422  }
5423  };
5424 
5425  // discarded values are not comparable
5426  if (lhs == value_t::discarded or rhs == value_t::discarded)
5427  {
5428  return false;
5429  }
5430 
5431  return order[static_cast<std::size_t>(lhs)] < order[static_cast<std::size_t>(rhs)];
5432  }
5433 
5434  public:
5458  friend bool operator==(const_reference lhs, const_reference rhs) noexcept
5459  {
5460  const auto lhs_type = lhs.type();
5461  const auto rhs_type = rhs.type();
5462 
5463  if (lhs_type == rhs_type)
5464  {
5465  switch (lhs_type)
5466  {
5467  case value_t::array:
5468  {
5469  return *lhs.m_value.array == *rhs.m_value.array;
5470  }
5471  case value_t::object:
5472  {
5473  return *lhs.m_value.object == *rhs.m_value.object;
5474  }
5475  case value_t::null:
5476  {
5477  return true;
5478  }
5479  case value_t::string:
5480  {
5481  return *lhs.m_value.string == *rhs.m_value.string;
5482  }
5483  case value_t::boolean:
5484  {
5485  return lhs.m_value.boolean == rhs.m_value.boolean;
5486  }
5487  case value_t::number_integer:
5488  {
5489  return lhs.m_value.number_integer == rhs.m_value.number_integer;
5490  }
5491  case value_t::number_unsigned:
5492  {
5493  return lhs.m_value.number_unsigned == rhs.m_value.number_unsigned;
5494  }
5495  case value_t::number_float:
5496  {
5497  return lhs.m_value.number_float == rhs.m_value.number_float;
5498  }
5499  default:
5500  {
5501  return false;
5502  }
5503  }
5504  }
5505  else if (lhs_type == value_t::number_integer and rhs_type == value_t::number_float)
5506  {
5507  return static_cast<number_float_t>(lhs.m_value.number_integer) == rhs.m_value.number_float;
5508  }
5509  else if (lhs_type == value_t::number_float and rhs_type == value_t::number_integer)
5510  {
5511  return lhs.m_value.number_float == static_cast<number_float_t>(rhs.m_value.number_integer);
5512  }
5513  else if (lhs_type == value_t::number_unsigned and rhs_type == value_t::number_float)
5514  {
5515  return static_cast<number_float_t>(lhs.m_value.number_unsigned) == rhs.m_value.number_float;
5516  }
5517  else if (lhs_type == value_t::number_float and rhs_type == value_t::number_unsigned)
5518  {
5519  return lhs.m_value.number_float == static_cast<number_float_t>(rhs.m_value.number_unsigned);
5520  }
5521  else if (lhs_type == value_t::number_unsigned and rhs_type == value_t::number_integer)
5522  {
5523  return static_cast<number_integer_t>(lhs.m_value.number_unsigned) == rhs.m_value.number_integer;
5524  }
5525  else if (lhs_type == value_t::number_integer and rhs_type == value_t::number_unsigned)
5526  {
5527  return lhs.m_value.number_integer == static_cast<number_integer_t>(rhs.m_value.number_unsigned);
5528  }
5529 
5530  return false;
5531  }
5532 
5551  friend bool operator==(const_reference v, std::nullptr_t) noexcept
5552  {
5553  return v.is_null();
5554  }
5555 
5560  friend bool operator==(std::nullptr_t, const_reference v) noexcept
5561  {
5562  return v.is_null();
5563  }
5564 
5581  friend bool operator!=(const_reference lhs, const_reference rhs) noexcept
5582  {
5583  return not (lhs == rhs);
5584  }
5585 
5604  friend bool operator!=(const_reference v, std::nullptr_t) noexcept
5605  {
5606  return not v.is_null();
5607  }
5608 
5613  friend bool operator!=(std::nullptr_t, const_reference v) noexcept
5614  {
5615  return not v.is_null();
5616  }
5617 
5642  friend bool operator<(const_reference lhs, const_reference rhs) noexcept
5643  {
5644  const auto lhs_type = lhs.type();
5645  const auto rhs_type = rhs.type();
5646 
5647  if (lhs_type == rhs_type)
5648  {
5649  switch (lhs_type)
5650  {
5651  case value_t::array:
5652  {
5653  return *lhs.m_value.array < *rhs.m_value.array;
5654  }
5655  case value_t::object:
5656  {
5657  return *lhs.m_value.object < *rhs.m_value.object;
5658  }
5659  case value_t::null:
5660  {
5661  return false;
5662  }
5663  case value_t::string:
5664  {
5665  return *lhs.m_value.string < *rhs.m_value.string;
5666  }
5667  case value_t::boolean:
5668  {
5669  return lhs.m_value.boolean < rhs.m_value.boolean;
5670  }
5671  case value_t::number_integer:
5672  {
5673  return lhs.m_value.number_integer < rhs.m_value.number_integer;
5674  }
5675  case value_t::number_unsigned:
5676  {
5677  return lhs.m_value.number_unsigned < rhs.m_value.number_unsigned;
5678  }
5679  case value_t::number_float:
5680  {
5681  return lhs.m_value.number_float < rhs.m_value.number_float;
5682  }
5683  default:
5684  {
5685  return false;
5686  }
5687  }
5688  }
5689  else if (lhs_type == value_t::number_integer and rhs_type == value_t::number_float)
5690  {
5691  return static_cast<number_float_t>(lhs.m_value.number_integer) < rhs.m_value.number_float;
5692  }
5693  else if (lhs_type == value_t::number_float and rhs_type == value_t::number_integer)
5694  {
5695  return lhs.m_value.number_float < static_cast<number_float_t>(rhs.m_value.number_integer);
5696  }
5697  else if (lhs_type == value_t::number_unsigned and rhs_type == value_t::number_float)
5698  {
5699  return static_cast<number_float_t>(lhs.m_value.number_unsigned) < rhs.m_value.number_float;
5700  }
5701  else if (lhs_type == value_t::number_float and rhs_type == value_t::number_unsigned)
5702  {
5703  return lhs.m_value.number_float < static_cast<number_float_t>(rhs.m_value.number_unsigned);
5704  }
5705  else if (lhs_type == value_t::number_integer and rhs_type == value_t::number_unsigned)
5706  {
5707  return lhs.m_value.number_integer < static_cast<number_integer_t>(rhs.m_value.number_unsigned);
5708  }
5709  else if (lhs_type == value_t::number_unsigned and rhs_type == value_t::number_integer)
5710  {
5711  return static_cast<number_integer_t>(lhs.m_value.number_unsigned) < rhs.m_value.number_integer;
5712  }
5713 
5714  // We only reach this line if we cannot compare values. In that case,
5715  // we compare types. Note we have to call the operator explicitly,
5716  // because MSVC has problems otherwise.
5717  return operator<(lhs_type, rhs_type);
5718  }
5719 
5737  friend bool operator<=(const_reference lhs, const_reference rhs) noexcept
5738  {
5739  return not (rhs < lhs);
5740  }
5741 
5759  friend bool operator>(const_reference lhs, const_reference rhs) noexcept
5760  {
5761  return not (lhs <= rhs);
5762  }
5763 
5781  friend bool operator>=(const_reference lhs, const_reference rhs) noexcept
5782  {
5783  return not (lhs < rhs);
5784  }
5785 
5787 
5788 
5790  // serialization //
5792 
5795 
5822  friend std::ostream& operator<<(std::ostream& o, const basic_json& j)
5823  {
5824  // read width member and use it as indentation parameter if nonzero
5825  const bool pretty_print = (o.width() > 0);
5826  const auto indentation = (pretty_print ? o.width() : 0);
5827 
5828  // reset width to 0 for subsequent calls to this stream
5829  o.width(0);
5830 
5831  // fix locale problems
5832  const auto old_locale = o.imbue(std::locale(std::locale(), new DecimalSeparator));
5833  // set precision
5834 
5835  // 6, 15 or 16 digits of precision allows round-trip IEEE 754
5836  // string->float->string, string->double->string or string->long
5837  // double->string; to be safe, we read this value from
5838  // std::numeric_limits<number_float_t>::digits10
5839  const auto old_precision = o.precision(std::numeric_limits<double>::digits10);
5840 
5841  // do the actual serialization
5842  j.dump(o, pretty_print, static_cast<unsigned int>(indentation));
5843 
5844  // reset locale and precision
5845  o.imbue(old_locale);
5846  o.precision(old_precision);
5847  return o;
5848  }
5849 
5854  friend std::ostream& operator>>(const basic_json& j, std::ostream& o)
5855  {
5856  return o << j;
5857  }
5858 
5860 
5861 
5863  // deserialization //
5865 
5868 
5896  template<class T, std::size_t N>
5897  static basic_json parse(T (&array)[N],
5898  const parser_callback_t cb = nullptr)
5899  {
5900  // delegate the call to the iterator-range parse overload
5901  return parse(std::begin(array), std::end(array), cb);
5902  }
5903 
5931  template<typename CharPT, typename std::enable_if<
5932  std::is_pointer<CharPT>::value and
5933  std::is_integral<typename std::remove_pointer<CharPT>::type>::value and
5934  sizeof(typename std::remove_pointer<CharPT>::type) == 1, int>::type = 0>
5935  static basic_json parse(const CharPT s,
5936  const parser_callback_t cb = nullptr)
5937  {
5938  return parser(reinterpret_cast<const char*>(s), cb).parse();
5939  }
5940 
5965  static basic_json parse(std::istream& i,
5966  const parser_callback_t cb = nullptr)
5967  {
5968  return parser(i, cb).parse();
5969  }
5970 
5974  static basic_json parse(std::istream&& i,
5975  const parser_callback_t cb = nullptr)
5976  {
5977  return parser(i, cb).parse();
5978  }
5979 
6021  template<class IteratorType, typename std::enable_if<
6022  std::is_base_of<
6023  std::random_access_iterator_tag,
6024  typename std::iterator_traits<IteratorType>::iterator_category>::value, int>::type = 0>
6025  static basic_json parse(IteratorType first, IteratorType last,
6026  const parser_callback_t cb = nullptr)
6027  {
6028  // assertion to check that the iterator range is indeed contiguous,
6029  // see http://stackoverflow.com/a/35008842/266378 for more discussion
6030  assert(std::accumulate(first, last, std::make_pair<bool, int>(true, 0),
6031  [&first](std::pair<bool, int> res, decltype(*first) val)
6032  {
6033  res.first &= (val == *(std::next(std::addressof(*first), res.second++)));
6034  return res;
6035  }).first);
6036 
6037  // assertion to check that each element is 1 byte long
6038  static_assert(sizeof(typename std::iterator_traits<IteratorType>::value_type) == 1,
6039  "each element in the iterator range must have the size of 1 byte");
6040 
6041  // if iterator range is empty, create a parser with an empty string
6042  // to generate "unexpected EOF" error message
6043  if (std::distance(first, last) <= 0)
6044  {
6045  return parser("").parse();
6046  }
6047 
6048  return parser(first, last, cb).parse();
6049  }
6050 
6091  template<class ContiguousContainer, typename std::enable_if<
6092  not std::is_pointer<ContiguousContainer>::value and
6093  std::is_base_of<
6094  std::random_access_iterator_tag,
6095  typename std::iterator_traits<decltype(std::begin(std::declval<ContiguousContainer const>()))>::iterator_category>::value
6096  , int>::type = 0>
6097  static basic_json parse(const ContiguousContainer& c,
6098  const parser_callback_t cb = nullptr)
6099  {
6100  // delegate the call to the iterator-range parse overload
6101  return parse(std::begin(c), std::end(c), cb);
6102  }
6103 
6127  friend std::istream& operator<<(basic_json& j, std::istream& i)
6128  {
6129  j = parser(i).parse();
6130  return i;
6131  }
6132 
6137  friend std::istream& operator>>(std::istream& i, basic_json& j)
6138  {
6139  j = parser(i).parse();
6140  return i;
6141  }
6142 
6144 
6145 
6146  private:
6148  // convenience functions //
6150 
6163  std::string type_name() const
6164  {
6165  switch (m_type)
6166  {
6167  case value_t::null:
6168  return "null";
6169  case value_t::object:
6170  return "object";
6171  case value_t::array:
6172  return "array";
6173  case value_t::string:
6174  return "string";
6175  case value_t::boolean:
6176  return "boolean";
6177  case value_t::discarded:
6178  return "discarded";
6179  default:
6180  return "number";
6181  }
6182  }
6183 
6192  static std::size_t extra_space(const string_t& s) noexcept
6193  {
6194  return std::accumulate(s.begin(), s.end(), size_t{},
6195  [](size_t res, typename string_t::value_type c)
6196  {
6197  switch (c)
6198  {
6199  case '"':
6200  case '\\':
6201  case '\b':
6202  case '\f':
6203  case '\n':
6204  case '\r':
6205  case '\t':
6206  {
6207  // from c (1 byte) to \x (2 bytes)
6208  return res + 1;
6209  }
6210 
6211  default:
6212  {
6213  if (c >= 0x00 and c <= 0x1f)
6214  {
6215  // from c (1 byte) to \uxxxx (6 bytes)
6216  return res + 5;
6217  }
6218  else
6219  {
6220  return res;
6221  }
6222  }
6223  }
6224  });
6225  }
6226 
6240  static string_t escape_string(const string_t& s)
6241  {
6242  const auto space = extra_space(s);
6243  if (space == 0)
6244  {
6245  return s;
6246  }
6247 
6248  // create a result string of necessary size
6249  string_t result(s.size() + space, '\\');
6250  std::size_t pos = 0;
6251 
6252  for (const auto& c : s)
6253  {
6254  switch (c)
6255  {
6256  // quotation mark (0x22)
6257  case '"':
6258  {
6259  result[pos + 1] = '"';
6260  pos += 2;
6261  break;
6262  }
6263 
6264  // reverse solidus (0x5c)
6265  case '\\':
6266  {
6267  // nothing to change
6268  pos += 2;
6269  break;
6270  }
6271 
6272  // backspace (0x08)
6273  case '\b':
6274  {
6275  result[pos + 1] = 'b';
6276  pos += 2;
6277  break;
6278  }
6279 
6280  // formfeed (0x0c)
6281  case '\f':
6282  {
6283  result[pos + 1] = 'f';
6284  pos += 2;
6285  break;
6286  }
6287 
6288  // newline (0x0a)
6289  case '\n':
6290  {
6291  result[pos + 1] = 'n';
6292  pos += 2;
6293  break;
6294  }
6295 
6296  // carriage return (0x0d)
6297  case '\r':
6298  {
6299  result[pos + 1] = 'r';
6300  pos += 2;
6301  break;
6302  }
6303 
6304  // horizontal tab (0x09)
6305  case '\t':
6306  {
6307  result[pos + 1] = 't';
6308  pos += 2;
6309  break;
6310  }
6311 
6312  default:
6313  {
6314  if (c >= 0x00 and c <= 0x1f)
6315  {
6316  // convert a number 0..15 to its hex representation
6317  // (0..f)
6318  static const char hexify[16] =
6319  {
6320  '0', '1', '2', '3', '4', '5', '6', '7',
6321  '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'
6322  };
6323 
6324  // print character c as \uxxxx
6325  for (const char m :
6326  { 'u', '0', '0', hexify[c >> 4], hexify[c & 0x0f]
6327  })
6328  {
6329  result[++pos] = m;
6330  }
6331 
6332  ++pos;
6333  }
6334  else
6335  {
6336  // all other characters are added as-is
6337  result[pos++] = c;
6338  }
6339  break;
6340  }
6341  }
6342  }
6343 
6344  return result;
6345  }
6346 
6364  void dump(std::ostream& o,
6365  const bool pretty_print,
6366  const unsigned int indent_step,
6367  const unsigned int current_indent = 0) const
6368  {
6369  // variable to hold indentation for recursive calls
6370  unsigned int new_indent = current_indent;
6371 
6372  switch (m_type)
6373  {
6374  case value_t::object:
6375  {
6376  if (m_value.object->empty())
6377  {
6378  o << "{}";
6379  return;
6380  }
6381 
6382  o << "{";
6383 
6384  // increase indentation
6385  if (pretty_print)
6386  {
6387  new_indent += indent_step;
6388  o << "\n";
6389  }
6390 
6391  for (auto i = m_value.object->cbegin(); i != m_value.object->cend(); ++i)
6392  {
6393  if (i != m_value.object->cbegin())
6394  {
6395  o << (pretty_print ? ",\n" : ",");
6396  }
6397  o << string_t(new_indent, ' ') << "\""
6398  << escape_string(i->first) << "\":"
6399  << (pretty_print ? " " : "");
6400  i->second.dump(o, pretty_print, indent_step, new_indent);
6401  }
6402 
6403  // decrease indentation
6404  if (pretty_print)
6405  {
6406  new_indent -= indent_step;
6407  o << "\n";
6408  }
6409 
6410  o << string_t(new_indent, ' ') + "}";
6411  return;
6412  }
6413 
6414  case value_t::array:
6415  {
6416  if (m_value.array->empty())
6417  {
6418  o << "[]";
6419  return;
6420  }
6421 
6422  o << "[";
6423 
6424  // increase indentation
6425  if (pretty_print)
6426  {
6427  new_indent += indent_step;
6428  o << "\n";
6429  }
6430 
6431  for (auto i = m_value.array->cbegin(); i != m_value.array->cend(); ++i)
6432  {
6433  if (i != m_value.array->cbegin())
6434  {
6435  o << (pretty_print ? ",\n" : ",");
6436  }
6437  o << string_t(new_indent, ' ');
6438  i->dump(o, pretty_print, indent_step, new_indent);
6439  }
6440 
6441  // decrease indentation
6442  if (pretty_print)
6443  {
6444  new_indent -= indent_step;
6445  o << "\n";
6446  }
6447 
6448  o << string_t(new_indent, ' ') << "]";
6449  return;
6450  }
6451 
6452  case value_t::string:
6453  {
6454  o << string_t("\"") << escape_string(*m_value.string) << "\"";
6455  return;
6456  }
6457 
6458  case value_t::boolean:
6459  {
6460  o << (m_value.boolean ? "true" : "false");
6461  return;
6462  }
6463 
6464  case value_t::number_integer:
6465  {
6466  o << m_value.number_integer;
6467  return;
6468  }
6469 
6470  case value_t::number_unsigned:
6471  {
6472  o << m_value.number_unsigned;
6473  return;
6474  }
6475 
6476  case value_t::number_float:
6477  {
6478  if (m_value.number_float == 0)
6479  {
6480  // special case for zero to get "0.0"/"-0.0"
6481  o << (std::signbit(m_value.number_float) ? "-0.0" : "0.0");
6482  }
6483  else
6484  {
6485  o << m_value.number_float;
6486  }
6487  return;
6488  }
6489 
6490  case value_t::discarded:
6491  {
6492  o << "<discarded>";
6493  return;
6494  }
6495 
6496  case value_t::null:
6497  {
6498  o << "null";
6499  return;
6500  }
6501  }
6502  }
6503 
6504  private:
6506  // member variables //
6508 
6510  value_t m_type = value_t::null;
6511 
6513  json_value m_value = {};
6514 
6515 
6516  private:
6518  // iterators //
6520 
6530  class primitive_iterator_t
6531  {
6532  public:
6534  void set_begin() noexcept
6535  {
6536  m_it = begin_value;
6537  }
6538 
6540  void set_end() noexcept
6541  {
6542  m_it = end_value;
6543  }
6544 
6546  constexpr bool is_begin() const noexcept
6547  {
6548  return (m_it == begin_value);
6549  }
6550 
6552  constexpr bool is_end() const noexcept
6553  {
6554  return (m_it == end_value);
6555  }
6556 
6558  operator difference_type& () noexcept
6559  {
6560  return m_it;
6561  }
6562 
6564  constexpr operator difference_type () const noexcept
6565  {
6566  return m_it;
6567  }
6568 
6569  private:
6570  static constexpr difference_type begin_value = 0;
6571  static constexpr difference_type end_value = begin_value + 1;
6572 
6574  difference_type m_it = std::numeric_limits<std::ptrdiff_t>::denorm_min();
6575  };
6576 
6584  struct internal_iterator
6585  {
6587  typename object_t::iterator object_iterator;
6589  typename array_t::iterator array_iterator;
6591  primitive_iterator_t primitive_iterator;
6592 
6594  internal_iterator() noexcept
6595  : object_iterator(), array_iterator(), primitive_iterator()
6596  {}
6597  };
6598 
6600  template<typename IteratorType>
6601  class iteration_proxy
6602  {
6603  private:
6605  class iteration_proxy_internal
6606  {
6607  private:
6609  IteratorType anchor;
6611  size_t array_index = 0;
6612 
6613  public:
6614  explicit iteration_proxy_internal(IteratorType it) noexcept
6615  : anchor(it)
6616  {}
6617 
6619  iteration_proxy_internal& operator*()
6620  {
6621  return *this;
6622  }
6623 
6625  iteration_proxy_internal& operator++()
6626  {
6627  ++anchor;
6628  ++array_index;
6629 
6630  return *this;
6631  }
6632 
6634  bool operator!= (const iteration_proxy_internal& o) const
6635  {
6636  return anchor != o.anchor;
6637  }
6638 
6640  typename basic_json::string_t key() const
6641  {
6642  assert(anchor.m_object != nullptr);
6643 
6644  switch (anchor.m_object->type())
6645  {
6646  // use integer array index as key
6647  case value_t::array:
6648  {
6649  return std::to_string(array_index);
6650  }
6651 
6652  // use key from the object
6653  case value_t::object:
6654  {
6655  return anchor.key();
6656  }
6657 
6658  // use an empty key for all primitive types
6659  default:
6660  {
6661  return "";
6662  }
6663  }
6664  }
6665 
6667  typename IteratorType::reference value() const
6668  {
6669  return anchor.value();
6670  }
6671  };
6672 
6674  typename IteratorType::reference container;
6675 
6676  public:
6678  explicit iteration_proxy(typename IteratorType::reference cont)
6679  : container(cont)
6680  {}
6681 
6683  iteration_proxy_internal begin() noexcept
6684  {
6685  return iteration_proxy_internal(container.begin());
6686  }
6687 
6689  iteration_proxy_internal end() noexcept
6690  {
6691  return iteration_proxy_internal(container.end());
6692  }
6693  };
6694 
6695  public:
6715  class const_iterator : public std::iterator<std::random_access_iterator_tag, const basic_json>
6716  {
6718  friend class basic_json;
6719 
6720  public:
6730  using iterator_category = std::bidirectional_iterator_tag;
6731 
6733  const_iterator() = default;
6734 
6741  explicit const_iterator(pointer object) noexcept
6742  : m_object(object)
6743  {
6744  assert(m_object != nullptr);
6745 
6746  switch (m_object->m_type)
6747  {
6749  {
6750  m_it.object_iterator = typename object_t::iterator();
6751  break;
6752  }
6753 
6755  {
6756  m_it.array_iterator = typename array_t::iterator();
6757  break;
6758  }
6759 
6760  default:
6761  {
6762  m_it.primitive_iterator = primitive_iterator_t();
6763  break;
6764  }
6765  }
6766  }
6767 
6773  explicit const_iterator(const iterator& other) noexcept
6774  : m_object(other.m_object)
6775  {
6776  if (m_object != nullptr)
6777  {
6778  switch (m_object->m_type)
6779  {
6781  {
6782  m_it.object_iterator = other.m_it.object_iterator;
6783  break;
6784  }
6785 
6787  {
6788  m_it.array_iterator = other.m_it.array_iterator;
6789  break;
6790  }
6791 
6792  default:
6793  {
6794  m_it.primitive_iterator = other.m_it.primitive_iterator;
6795  break;
6796  }
6797  }
6798  }
6799  }
6800 
6806  const_iterator(const const_iterator& other) noexcept
6807  : m_object(other.m_object), m_it(other.m_it)
6808  {}
6809 
6816  std::is_nothrow_move_constructible<pointer>::value and
6817  std::is_nothrow_move_assignable<pointer>::value and
6818  std::is_nothrow_move_constructible<internal_iterator>::value and
6819  std::is_nothrow_move_assignable<internal_iterator>::value
6820  )
6821  {
6822  std::swap(m_object, other.m_object);
6823  std::swap(m_it, other.m_it);
6824  return *this;
6825  }
6826 
6827  private:
6832  void set_begin() noexcept
6833  {
6834  assert(m_object != nullptr);
6835 
6836  switch (m_object->m_type)
6837  {
6839  {
6840  m_it.object_iterator = m_object->m_value.object->begin();
6841  break;
6842  }
6843 
6845  {
6846  m_it.array_iterator = m_object->m_value.array->begin();
6847  break;
6848  }
6849 
6851  {
6852  // set to end so begin()==end() is true: null is empty
6853  m_it.primitive_iterator.set_end();
6854  break;
6855  }
6856 
6857  default:
6858  {
6859  m_it.primitive_iterator.set_begin();
6860  break;
6861  }
6862  }
6863  }
6864 
6869  void set_end() noexcept
6870  {
6871  assert(m_object != nullptr);
6872 
6873  switch (m_object->m_type)
6874  {
6876  {
6877  m_it.object_iterator = m_object->m_value.object->end();
6878  break;
6879  }
6880 
6882  {
6883  m_it.array_iterator = m_object->m_value.array->end();
6884  break;
6885  }
6886 
6887  default:
6888  {
6889  m_it.primitive_iterator.set_end();
6890  break;
6891  }
6892  }
6893  }
6894 
6895  public:
6901  {
6902  assert(m_object != nullptr);
6903 
6904  switch (m_object->m_type)
6905  {
6907  {
6908  assert(m_it.object_iterator != m_object->m_value.object->end());
6909  return m_it.object_iterator->second;
6910  }
6911 
6913  {
6914  assert(m_it.array_iterator != m_object->m_value.array->end());
6915  return *m_it.array_iterator;
6916  }
6917 
6919  {
6920  throw std::out_of_range("cannot get value");
6921  }
6922 
6923  default:
6924  {
6925  if (m_it.primitive_iterator.is_begin())
6926  {
6927  return *m_object;
6928  }
6929  else
6930  {
6931  throw std::out_of_range("cannot get value");
6932  }
6933  }
6934  }
6935  }
6936 
6942  {
6943  assert(m_object != nullptr);
6944 
6945  switch (m_object->m_type)
6946  {
6948  {
6949  assert(m_it.object_iterator != m_object->m_value.object->end());
6950  return &(m_it.object_iterator->second);
6951  }
6952 
6954  {
6955  assert(m_it.array_iterator != m_object->m_value.array->end());
6956  return &*m_it.array_iterator;
6957  }
6958 
6959  default:
6960  {
6961  if (m_it.primitive_iterator.is_begin())
6962  {
6963  return m_object;
6964  }
6965  else
6966  {
6967  throw std::out_of_range("cannot get value");
6968  }
6969  }
6970  }
6971  }
6972 
6978  {
6979  auto result = *this;
6980  ++(*this);
6981  return result;
6982  }
6983 
6989  {
6990  assert(m_object != nullptr);
6991 
6992  switch (m_object->m_type)
6993  {
6995  {
6996  std::advance(m_it.object_iterator, 1);
6997  break;
6998  }
6999 
7001  {
7002  std::advance(m_it.array_iterator, 1);
7003  break;
7004  }
7005 
7006  default:
7007  {
7008  ++m_it.primitive_iterator;
7009  break;
7010  }
7011  }
7012 
7013  return *this;
7014  }
7015 
7021  {
7022  auto result = *this;
7023  --(*this);
7024  return result;
7025  }
7026 
7032  {
7033  assert(m_object != nullptr);
7034 
7035  switch (m_object->m_type)
7036  {
7038  {
7039  std::advance(m_it.object_iterator, -1);
7040  break;
7041  }
7042 
7044  {
7045  std::advance(m_it.array_iterator, -1);
7046  break;
7047  }
7048 
7049  default:
7050  {
7051  --m_it.primitive_iterator;
7052  break;
7053  }
7054  }
7055 
7056  return *this;
7057  }
7058 
7063  bool operator==(const const_iterator& other) const
7064  {
7065  // if objects are not the same, the comparison is undefined
7066  if (m_object != other.m_object)
7067  {
7068  throw std::domain_error("cannot compare iterators of different containers");
7069  }
7070 
7071  assert(m_object != nullptr);
7072 
7073  switch (m_object->m_type)
7074  {
7076  {
7077  return (m_it.object_iterator == other.m_it.object_iterator);
7078  }
7079 
7081  {
7082  return (m_it.array_iterator == other.m_it.array_iterator);
7083  }
7084 
7085  default:
7086  {
7087  return (m_it.primitive_iterator == other.m_it.primitive_iterator);
7088  }
7089  }
7090  }
7091 
7096  bool operator!=(const const_iterator& other) const
7097  {
7098  return not operator==(other);
7099  }
7100 
7105  bool operator<(const const_iterator& other) const
7106  {
7107  // if objects are not the same, the comparison is undefined
7108  if (m_object != other.m_object)
7109  {
7110  throw std::domain_error("cannot compare iterators of different containers");
7111  }
7112 
7113  assert(m_object != nullptr);
7114 
7115  switch (m_object->m_type)
7116  {
7118  {
7119  throw std::domain_error("cannot compare order of object iterators");
7120  }
7121 
7123  {
7124  return (m_it.array_iterator < other.m_it.array_iterator);
7125  }
7126 
7127  default:
7128  {
7129  return (m_it.primitive_iterator < other.m_it.primitive_iterator);
7130  }
7131  }
7132  }
7133 
7138  bool operator<=(const const_iterator& other) const
7139  {
7140  return not other.operator < (*this);
7141  }
7142 
7147  bool operator>(const const_iterator& other) const
7148  {
7149  return not operator<=(other);
7150  }
7151 
7156  bool operator>=(const const_iterator& other) const
7157  {
7158  return not operator<(other);
7159  }
7160 
7166  {
7167  assert(m_object != nullptr);
7168 
7169  switch (m_object->m_type)
7170  {
7172  {
7173  throw std::domain_error("cannot use offsets with object iterators");
7174  }
7175 
7177  {
7178  std::advance(m_it.array_iterator, i);
7179  break;
7180  }
7181 
7182  default:
7183  {
7184  m_it.primitive_iterator += i;
7185  break;
7186  }
7187  }
7188 
7189  return *this;
7190  }
7191 
7197  {
7198  return operator+=(-i);
7199  }
7200 
7206  {
7207  auto result = *this;
7208  result += i;
7209  return result;
7210  }
7211 
7217  {
7218  auto result = *this;
7219  result -= i;
7220  return result;
7221  }
7222 
7228  {
7229  assert(m_object != nullptr);
7230 
7231  switch (m_object->m_type)
7232  {
7234  {
7235  throw std::domain_error("cannot use offsets with object iterators");
7236  }
7237 
7239  {
7240  return m_it.array_iterator - other.m_it.array_iterator;
7241  }
7242 
7243  default:
7244  {
7245  return m_it.primitive_iterator - other.m_it.primitive_iterator;
7246  }
7247  }
7248  }
7249 
7255  {
7256  assert(m_object != nullptr);
7257 
7258  switch (m_object->m_type)
7259  {
7261  {
7262  throw std::domain_error("cannot use operator[] for object iterators");
7263  }
7264 
7266  {
7267  return *std::next(m_it.array_iterator, n);
7268  }
7269 
7271  {
7272  throw std::out_of_range("cannot get value");
7273  }
7274 
7275  default:
7276  {
7277  if (m_it.primitive_iterator == -n)
7278  {
7279  return *m_object;
7280  }
7281  else
7282  {
7283  throw std::out_of_range("cannot get value");
7284  }
7285  }
7286  }
7287  }
7288 
7293  typename object_t::key_type key() const
7294  {
7295  assert(m_object != nullptr);
7296 
7297  if (m_object->is_object())
7298  {
7299  return m_it.object_iterator->first;
7300  }
7301  else
7302  {
7303  throw std::domain_error("cannot use key() for non-object iterators");
7304  }
7305  }
7306 
7312  {
7313  return operator*();
7314  }
7315 
7316  private:
7318  pointer m_object = nullptr;
7320  internal_iterator m_it = internal_iterator();
7321  };
7322 
7335  class iterator : public const_iterator
7336  {
7337  public:
7339  using pointer = typename basic_json::pointer;
7341 
7343  iterator() = default;
7344 
7346  explicit iterator(pointer object) noexcept
7347  : base_iterator(object)
7348  {}
7349 
7351  iterator(const iterator& other) noexcept
7352  : base_iterator(other)
7353  {}
7354 
7356  iterator& operator=(iterator other) noexcept(
7357  std::is_nothrow_move_constructible<pointer>::value and
7358  std::is_nothrow_move_assignable<pointer>::value and
7359  std::is_nothrow_move_constructible<internal_iterator>::value and
7360  std::is_nothrow_move_assignable<internal_iterator>::value
7361  )
7362  {
7363  base_iterator::operator=(other);
7364  return *this;
7365  }
7366 
7369  {
7370  return const_cast<reference>(base_iterator::operator*());
7371  }
7372 
7375  {
7376  return const_cast<pointer>(base_iterator::operator->());
7377  }
7378 
7381  {
7382  iterator result = *this;
7383  base_iterator::operator++();
7384  return result;
7385  }
7386 
7389  {
7390  base_iterator::operator++();
7391  return *this;
7392  }
7393 
7396  {
7397  iterator result = *this;
7398  base_iterator::operator--();
7399  return result;
7400  }
7401 
7404  {
7405  base_iterator::operator--();
7406  return *this;
7407  }
7408 
7411  {
7412  base_iterator::operator+=(i);
7413  return *this;
7414  }
7415 
7418  {
7419  base_iterator::operator-=(i);
7420  return *this;
7421  }
7422 
7425  {
7426  auto result = *this;
7427  result += i;
7428  return result;
7429  }
7430 
7433  {
7434  auto result = *this;
7435  result -= i;
7436  return result;
7437  }
7438 
7440  difference_type operator-(const iterator& other) const
7441  {
7442  return base_iterator::operator-(other);
7443  }
7444 
7447  {
7448  return const_cast<reference>(base_iterator::operator[](n));
7449  }
7450 
7453  {
7454  return const_cast<reference>(base_iterator::value());
7455  }
7456  };
7457 
7475  template<typename Base>
7476  class json_reverse_iterator : public std::reverse_iterator<Base>
7477  {
7478  public:
7480  using base_iterator = std::reverse_iterator<Base>;
7482  using reference = typename Base::reference;
7483 
7485  json_reverse_iterator(const typename base_iterator::iterator_type& it) noexcept
7486  : base_iterator(it)
7487  {}
7488 
7491  : base_iterator(it)
7492  {}
7493 
7496  {
7497  return base_iterator::operator++(1);
7498  }
7499 
7502  {
7503  base_iterator::operator++();
7504  return *this;
7505  }
7506 
7509  {
7510  return base_iterator::operator--(1);
7511  }
7512 
7515  {
7516  base_iterator::operator--();
7517  return *this;
7518  }
7519 
7522  {
7523  base_iterator::operator+=(i);
7524  return *this;
7525  }
7526 
7529  {
7530  auto result = *this;
7531  result += i;
7532  return result;
7533  }
7534 
7537  {
7538  auto result = *this;
7539  result -= i;
7540  return result;
7541  }
7542 
7545  {
7546  return this->base() - other.base();
7547  }
7548 
7551  {
7552  return *(this->operator+(n));
7553  }
7554 
7556  typename object_t::key_type key() const
7557  {
7558  auto it = --this->base();
7559  return it.key();
7560  }
7561 
7564  {
7565  auto it = --this->base();
7566  return it.operator * ();
7567  }
7568  };
7569 
7570 
7571  private:
7573  // lexer and parser //
7575 
7583  class lexer
7584  {
7585  public:
7587  enum class token_type
7588  {
7589  uninitialized,
7590  literal_true,
7591  literal_false,
7592  literal_null,
7593  value_string,
7594  value_number,
7595  begin_array,
7596  begin_object,
7597  end_array,
7598  end_object,
7599  name_separator,
7600  value_separator,
7601  parse_error,
7602  end_of_input
7603  };
7604 
7606  using lexer_char_t = unsigned char;
7607 
7609  lexer(const lexer_char_t* buff, const size_t len) noexcept
7610  : m_content(buff)
7611  {
7612  assert(m_content != nullptr);
7613  m_start = m_cursor = m_content;
7614  m_limit = m_content + len;
7615  }
7616 
7618  explicit lexer(std::istream& s)
7619  : m_stream(&s), m_line_buffer()
7620  {
7621  // fill buffer
7622  fill_line_buffer();
7623 
7624  // skip UTF-8 byte-order mark
7625  if (m_line_buffer.size() >= 3 and m_line_buffer.substr(0, 3) == "\xEF\xBB\xBF")
7626  {
7627  m_line_buffer[0] = ' ';
7628  m_line_buffer[1] = ' ';
7629  m_line_buffer[2] = ' ';
7630  }
7631  }
7632 
7633  // switch off unwanted functions (due to pointer members)
7634  lexer() = delete;
7635  lexer(const lexer&) = delete;
7636  lexer operator=(const lexer&) = delete;
7637 
7661  static string_t to_unicode(const std::size_t codepoint1,
7662  const std::size_t codepoint2 = 0)
7663  {
7664  // calculate the code point from the given code points
7665  std::size_t codepoint = codepoint1;
7666 
7667  // check if codepoint1 is a high surrogate
7668  if (codepoint1 >= 0xD800 and codepoint1 <= 0xDBFF)
7669  {
7670  // check if codepoint2 is a low surrogate
7671  if (codepoint2 >= 0xDC00 and codepoint2 <= 0xDFFF)
7672  {
7673  codepoint =
7674  // high surrogate occupies the most significant 22 bits
7675  (codepoint1 << 10)
7676  // low surrogate occupies the least significant 15 bits
7677  + codepoint2
7678  // there is still the 0xD800, 0xDC00 and 0x10000 noise
7679  // in the result so we have to subtract with:
7680  // (0xD800 << 10) + DC00 - 0x10000 = 0x35FDC00
7681  - 0x35FDC00;
7682  }
7683  else
7684  {
7685  throw std::invalid_argument("missing or wrong low surrogate");
7686  }
7687  }
7688 
7689  string_t result;
7690 
7691  if (codepoint < 0x80)
7692  {
7693  // 1-byte characters: 0xxxxxxx (ASCII)
7694  result.append(1, static_cast<typename string_t::value_type>(codepoint));
7695  }
7696  else if (codepoint <= 0x7ff)
7697  {
7698  // 2-byte characters: 110xxxxx 10xxxxxx
7699  result.append(1, static_cast<typename string_t::value_type>(0xC0 | ((codepoint >> 6) & 0x1F)));
7700  result.append(1, static_cast<typename string_t::value_type>(0x80 | (codepoint & 0x3F)));
7701  }
7702  else if (codepoint <= 0xffff)
7703  {
7704  // 3-byte characters: 1110xxxx 10xxxxxx 10xxxxxx
7705  result.append(1, static_cast<typename string_t::value_type>(0xE0 | ((codepoint >> 12) & 0x0F)));
7706  result.append(1, static_cast<typename string_t::value_type>(0x80 | ((codepoint >> 6) & 0x3F)));
7707  result.append(1, static_cast<typename string_t::value_type>(0x80 | (codepoint & 0x3F)));
7708  }
7709  else if (codepoint <= 0x10ffff)
7710  {
7711  // 4-byte characters: 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
7712  result.append(1, static_cast<typename string_t::value_type>(0xF0 | ((codepoint >> 18) & 0x07)));
7713  result.append(1, static_cast<typename string_t::value_type>(0x80 | ((codepoint >> 12) & 0x3F)));
7714  result.append(1, static_cast<typename string_t::value_type>(0x80 | ((codepoint >> 6) & 0x3F)));
7715  result.append(1, static_cast<typename string_t::value_type>(0x80 | (codepoint & 0x3F)));
7716  }
7717  else
7718  {
7719  throw std::out_of_range("code points above 0x10FFFF are invalid");
7720  }
7721 
7722  return result;
7723  }
7724 
7726  static std::string token_type_name(const token_type t)
7727  {
7728  switch (t)
7729  {
7730  case token_type::uninitialized:
7731  return "<uninitialized>";
7732  case token_type::literal_true:
7733  return "true literal";
7734  case token_type::literal_false:
7735  return "false literal";
7736  case token_type::literal_null:
7737  return "null literal";
7738  case token_type::value_string:
7739  return "string literal";
7740  case token_type::value_number:
7741  return "number literal";
7742  case token_type::begin_array:
7743  return "'['";
7744  case token_type::begin_object:
7745  return "'{'";
7746  case token_type::end_array:
7747  return "']'";
7748  case token_type::end_object:
7749  return "'}'";
7750  case token_type::name_separator:
7751  return "':'";
7752  case token_type::value_separator:
7753  return "','";
7754  case token_type::parse_error:
7755  return "<parse error>";
7756  case token_type::end_of_input:
7757  return "end of input";
7758  default:
7759  {
7760  // catch non-enum values
7761  return "unknown token"; // LCOV_EXCL_LINE
7762  }
7763  }
7764  }
7765 
7787  token_type scan()
7788  {
7789  while (true)
7790  {
7791  // pointer for backtracking information
7792  m_marker = nullptr;
7793 
7794  // remember the begin of the token
7795  m_start = m_cursor;
7796  assert(m_start != nullptr);
7797 
7798 
7799  {
7800  lexer_char_t yych;
7801  unsigned int yyaccept = 0;
7802  static const unsigned char yybm[] =
7803  {
7804  0, 0, 0, 0, 0, 0, 0, 0,
7805  0, 32, 32, 0, 0, 32, 0, 0,
7806  0, 0, 0, 0, 0, 0, 0, 0,
7807  0, 0, 0, 0, 0, 0, 0, 0,
7808  160, 128, 0, 128, 128, 128, 128, 128,
7809  128, 128, 128, 128, 128, 128, 128, 128,
7810  192, 192, 192, 192, 192, 192, 192, 192,
7811  192, 192, 128, 128, 128, 128, 128, 128,
7812  128, 128, 128, 128, 128, 128, 128, 128,
7813  128, 128, 128, 128, 128, 128, 128, 128,
7814  128, 128, 128, 128, 128, 128, 128, 128,
7815  128, 128, 128, 128, 0, 128, 128, 128,
7816  128, 128, 128, 128, 128, 128, 128, 128,
7817  128, 128, 128, 128, 128, 128, 128, 128,
7818  128, 128, 128, 128, 128, 128, 128, 128,
7819  128, 128, 128, 128, 128, 128, 128, 128,
7820  0, 0, 0, 0, 0, 0, 0, 0,
7821  0, 0, 0, 0, 0, 0, 0, 0,
7822  0, 0, 0, 0, 0, 0, 0, 0,
7823  0, 0, 0, 0, 0, 0, 0, 0,
7824  0, 0, 0, 0, 0, 0, 0, 0,
7825  0, 0, 0, 0, 0, 0, 0, 0,
7826  0, 0, 0, 0, 0, 0, 0, 0,
7827  0, 0, 0, 0, 0, 0, 0, 0,
7828  0, 0, 0, 0, 0, 0, 0, 0,
7829  0, 0, 0, 0, 0, 0, 0, 0,
7830  0, 0, 0, 0, 0, 0, 0, 0,
7831  0, 0, 0, 0, 0, 0, 0, 0,
7832  0, 0, 0, 0, 0, 0, 0, 0,
7833  0, 0, 0, 0, 0, 0, 0, 0,
7834  0, 0, 0, 0, 0, 0, 0, 0,
7835  0, 0, 0, 0, 0, 0, 0, 0,
7836  };
7837  if ((m_limit - m_cursor) < 5)
7838  {
7839  fill_line_buffer(5); // LCOV_EXCL_LINE
7840  }
7841  yych = *m_cursor;
7842  if (yybm[0 + yych] & 32)
7843  {
7844  goto basic_json_parser_6;
7845  }
7846  if (yych <= '[')
7847  {
7848  if (yych <= '-')
7849  {
7850  if (yych <= '"')
7851  {
7852  if (yych <= 0x00)
7853  {
7854  goto basic_json_parser_2;
7855  }
7856  if (yych <= '!')
7857  {
7858  goto basic_json_parser_4;
7859  }
7860  goto basic_json_parser_9;
7861  }
7862  else
7863  {
7864  if (yych <= '+')
7865  {
7866  goto basic_json_parser_4;
7867  }
7868  if (yych <= ',')
7869  {
7870  goto basic_json_parser_10;
7871  }
7872  goto basic_json_parser_12;
7873  }
7874  }
7875  else
7876  {
7877  if (yych <= '9')
7878  {
7879  if (yych <= '/')
7880  {
7881  goto basic_json_parser_4;
7882  }
7883  if (yych <= '0')
7884  {
7885  goto basic_json_parser_13;
7886  }
7887  goto basic_json_parser_15;
7888  }
7889  else
7890  {
7891  if (yych <= ':')
7892  {
7893  goto basic_json_parser_17;
7894  }
7895  if (yych <= 'Z')
7896  {
7897  goto basic_json_parser_4;
7898  }
7899  goto basic_json_parser_19;
7900  }
7901  }
7902  }
7903  else
7904  {
7905  if (yych <= 'n')
7906  {
7907  if (yych <= 'e')
7908  {
7909  if (yych == ']')
7910  {
7911  goto basic_json_parser_21;
7912  }
7913  goto basic_json_parser_4;
7914  }
7915  else
7916  {
7917  if (yych <= 'f')
7918  {
7919  goto basic_json_parser_23;
7920  }
7921  if (yych <= 'm')
7922  {
7923  goto basic_json_parser_4;
7924  }
7925  goto basic_json_parser_24;
7926  }
7927  }
7928  else
7929  {
7930  if (yych <= 'z')
7931  {
7932  if (yych == 't')
7933  {
7934  goto basic_json_parser_25;
7935  }
7936  goto basic_json_parser_4;
7937  }
7938  else
7939  {
7940  if (yych <= '{')
7941  {
7942  goto basic_json_parser_26;
7943  }
7944  if (yych == '}')
7945  {
7946  goto basic_json_parser_28;
7947  }
7948  goto basic_json_parser_4;
7949  }
7950  }
7951  }
7952 basic_json_parser_2:
7953  ++m_cursor;
7954  {
7955  last_token_type = token_type::end_of_input;
7956  break;
7957  }
7958 basic_json_parser_4:
7959  ++m_cursor;
7960 basic_json_parser_5:
7961  {
7962  last_token_type = token_type::parse_error;
7963  break;
7964  }
7965 basic_json_parser_6:
7966  ++m_cursor;
7967  if (m_limit <= m_cursor)
7968  {
7969  fill_line_buffer(1); // LCOV_EXCL_LINE
7970  }
7971  yych = *m_cursor;
7972  if (yybm[0 + yych] & 32)
7973  {
7974  goto basic_json_parser_6;
7975  }
7976  {
7977  continue;
7978  }
7979 basic_json_parser_9:
7980  yyaccept = 0;
7981  yych = *(m_marker = ++m_cursor);
7982  if (yych <= 0x1F)
7983  {
7984  goto basic_json_parser_5;
7985  }
7986  if (yych <= 0x7F)
7987  {
7988  goto basic_json_parser_31;
7989  }
7990  if (yych <= 0xC1)
7991  {
7992  goto basic_json_parser_5;
7993  }
7994  if (yych <= 0xF4)
7995  {
7996  goto basic_json_parser_31;
7997  }
7998  goto basic_json_parser_5;
7999 basic_json_parser_10:
8000  ++m_cursor;
8001  {
8002  last_token_type = token_type::value_separator;
8003  break;
8004  }
8005 basic_json_parser_12:
8006  yych = *++m_cursor;
8007  if (yych <= '/')
8008  {
8009  goto basic_json_parser_5;
8010  }
8011  if (yych <= '0')
8012  {
8013  goto basic_json_parser_13;
8014  }
8015  if (yych <= '9')
8016  {
8017  goto basic_json_parser_15;
8018  }
8019  goto basic_json_parser_5;
8020 basic_json_parser_13:
8021  yyaccept = 1;
8022  yych = *(m_marker = ++m_cursor);
8023  if (yych <= 'D')
8024  {
8025  if (yych == '.')
8026  {
8027  goto basic_json_parser_43;
8028  }
8029  }
8030  else
8031  {
8032  if (yych <= 'E')
8033  {
8034  goto basic_json_parser_44;
8035  }
8036  if (yych == 'e')
8037  {
8038  goto basic_json_parser_44;
8039  }
8040  }
8041 basic_json_parser_14:
8042  {
8043  last_token_type = token_type::value_number;
8044  break;
8045  }
8046 basic_json_parser_15:
8047  yyaccept = 1;
8048  m_marker = ++m_cursor;
8049  if ((m_limit - m_cursor) < 3)
8050  {
8051  fill_line_buffer(3); // LCOV_EXCL_LINE
8052  }
8053  yych = *m_cursor;
8054  if (yybm[0 + yych] & 64)
8055  {
8056  goto basic_json_parser_15;
8057  }
8058  if (yych <= 'D')
8059  {
8060  if (yych == '.')
8061  {
8062  goto basic_json_parser_43;
8063  }
8064  goto basic_json_parser_14;
8065  }
8066  else
8067  {
8068  if (yych <= 'E')
8069  {
8070  goto basic_json_parser_44;
8071  }
8072  if (yych == 'e')
8073  {
8074  goto basic_json_parser_44;
8075  }
8076  goto basic_json_parser_14;
8077  }
8078 basic_json_parser_17:
8079  ++m_cursor;
8080  {
8081  last_token_type = token_type::name_separator;
8082  break;
8083  }
8084 basic_json_parser_19:
8085  ++m_cursor;
8086  {
8087  last_token_type = token_type::begin_array;
8088  break;
8089  }
8090 basic_json_parser_21:
8091  ++m_cursor;
8092  {
8093  last_token_type = token_type::end_array;
8094  break;
8095  }
8096 basic_json_parser_23:
8097  yyaccept = 0;
8098  yych = *(m_marker = ++m_cursor);
8099  if (yych == 'a')
8100  {
8101  goto basic_json_parser_45;
8102  }
8103  goto basic_json_parser_5;
8104 basic_json_parser_24:
8105  yyaccept = 0;
8106  yych = *(m_marker = ++m_cursor);
8107  if (yych == 'u')
8108  {
8109  goto basic_json_parser_46;
8110  }
8111  goto basic_json_parser_5;
8112 basic_json_parser_25:
8113  yyaccept = 0;
8114  yych = *(m_marker = ++m_cursor);
8115  if (yych == 'r')
8116  {
8117  goto basic_json_parser_47;
8118  }
8119  goto basic_json_parser_5;
8120 basic_json_parser_26:
8121  ++m_cursor;
8122  {
8123  last_token_type = token_type::begin_object;
8124  break;
8125  }
8126 basic_json_parser_28:
8127  ++m_cursor;
8128  {
8129  last_token_type = token_type::end_object;
8130  break;
8131  }
8132 basic_json_parser_30:
8133  ++m_cursor;
8134  if (m_limit <= m_cursor)
8135  {
8136  fill_line_buffer(1); // LCOV_EXCL_LINE
8137  }
8138  yych = *m_cursor;
8139 basic_json_parser_31:
8140  if (yybm[0 + yych] & 128)
8141  {
8142  goto basic_json_parser_30;
8143  }
8144  if (yych <= 0xE0)
8145  {
8146  if (yych <= '\\')
8147  {
8148  if (yych <= 0x1F)
8149  {
8150  goto basic_json_parser_32;
8151  }
8152  if (yych <= '"')
8153  {
8154  goto basic_json_parser_33;
8155  }
8156  goto basic_json_parser_35;
8157  }
8158  else
8159  {
8160  if (yych <= 0xC1)
8161  {
8162  goto basic_json_parser_32;
8163  }
8164  if (yych <= 0xDF)
8165  {
8166  goto basic_json_parser_36;
8167  }
8168  goto basic_json_parser_37;
8169  }
8170  }
8171  else
8172  {
8173  if (yych <= 0xEF)
8174  {
8175  if (yych == 0xED)
8176  {
8177  goto basic_json_parser_39;
8178  }
8179  goto basic_json_parser_38;
8180  }
8181  else
8182  {
8183  if (yych <= 0xF0)
8184  {
8185  goto basic_json_parser_40;
8186  }
8187  if (yych <= 0xF3)
8188  {
8189  goto basic_json_parser_41;
8190  }
8191  if (yych <= 0xF4)
8192  {
8193  goto basic_json_parser_42;
8194  }
8195  }
8196  }
8197 basic_json_parser_32:
8198  m_cursor = m_marker;
8199  if (yyaccept == 0)
8200  {
8201  goto basic_json_parser_5;
8202  }
8203  else
8204  {
8205  goto basic_json_parser_14;
8206  }
8207 basic_json_parser_33:
8208  ++m_cursor;
8209  {
8210  last_token_type = token_type::value_string;
8211  break;
8212  }
8213 basic_json_parser_35:
8214  ++m_cursor;
8215  if (m_limit <= m_cursor)
8216  {
8217  fill_line_buffer(1); // LCOV_EXCL_LINE
8218  }
8219  yych = *m_cursor;
8220  if (yych <= 'e')
8221  {
8222  if (yych <= '/')
8223  {
8224  if (yych == '"')
8225  {
8226  goto basic_json_parser_30;
8227  }
8228  if (yych <= '.')
8229  {
8230  goto basic_json_parser_32;
8231  }
8232  goto basic_json_parser_30;
8233  }
8234  else
8235  {
8236  if (yych <= '\\')
8237  {
8238  if (yych <= '[')
8239  {
8240  goto basic_json_parser_32;
8241  }
8242  goto basic_json_parser_30;
8243  }
8244  else
8245  {
8246  if (yych == 'b')
8247  {
8248  goto basic_json_parser_30;
8249  }
8250  goto basic_json_parser_32;
8251  }
8252  }
8253  }
8254  else
8255  {
8256  if (yych <= 'q')
8257  {
8258  if (yych <= 'f')
8259  {
8260  goto basic_json_parser_30;
8261  }
8262  if (yych == 'n')
8263  {
8264  goto basic_json_parser_30;
8265  }
8266  goto basic_json_parser_32;
8267  }
8268  else
8269  {
8270  if (yych <= 's')
8271  {
8272  if (yych <= 'r')
8273  {
8274  goto basic_json_parser_30;
8275  }
8276  goto basic_json_parser_32;
8277  }
8278  else
8279  {
8280  if (yych <= 't')
8281  {
8282  goto basic_json_parser_30;
8283  }
8284  if (yych <= 'u')
8285  {
8286  goto basic_json_parser_48;
8287  }
8288  goto basic_json_parser_32;
8289  }
8290  }
8291  }
8292 basic_json_parser_36:
8293  ++m_cursor;
8294  if (m_limit <= m_cursor)
8295  {
8296  fill_line_buffer(1); // LCOV_EXCL_LINE
8297  }
8298  yych = *m_cursor;
8299  if (yych <= 0x7F)
8300  {
8301  goto basic_json_parser_32;
8302  }
8303  if (yych <= 0xBF)
8304  {
8305  goto basic_json_parser_30;
8306  }
8307  goto basic_json_parser_32;
8308 basic_json_parser_37:
8309  ++m_cursor;
8310  if (m_limit <= m_cursor)
8311  {
8312  fill_line_buffer(1); // LCOV_EXCL_LINE
8313  }
8314  yych = *m_cursor;
8315  if (yych <= 0x9F)
8316  {
8317  goto basic_json_parser_32;
8318  }
8319  if (yych <= 0xBF)
8320  {
8321  goto basic_json_parser_36;
8322  }
8323  goto basic_json_parser_32;
8324 basic_json_parser_38:
8325  ++m_cursor;
8326  if (m_limit <= m_cursor)
8327  {
8328  fill_line_buffer(1); // LCOV_EXCL_LINE
8329  }
8330  yych = *m_cursor;
8331  if (yych <= 0x7F)
8332  {
8333  goto basic_json_parser_32;
8334  }
8335  if (yych <= 0xBF)
8336  {
8337  goto basic_json_parser_36;
8338  }
8339  goto basic_json_parser_32;
8340 basic_json_parser_39:
8341  ++m_cursor;
8342  if (m_limit <= m_cursor)
8343  {
8344  fill_line_buffer(1); // LCOV_EXCL_LINE
8345  }
8346  yych = *m_cursor;
8347  if (yych <= 0x7F)
8348  {
8349  goto basic_json_parser_32;
8350  }
8351  if (yych <= 0x9F)
8352  {
8353  goto basic_json_parser_36;
8354  }
8355  goto basic_json_parser_32;
8356 basic_json_parser_40:
8357  ++m_cursor;
8358  if (m_limit <= m_cursor)
8359  {
8360  fill_line_buffer(1); // LCOV_EXCL_LINE
8361  }
8362  yych = *m_cursor;
8363  if (yych <= 0x8F)
8364  {
8365  goto basic_json_parser_32;
8366  }
8367  if (yych <= 0xBF)
8368  {
8369  goto basic_json_parser_38;
8370  }
8371  goto basic_json_parser_32;
8372 basic_json_parser_41:
8373  ++m_cursor;
8374  if (m_limit <= m_cursor)
8375  {
8376  fill_line_buffer(1); // LCOV_EXCL_LINE
8377  }
8378  yych = *m_cursor;
8379  if (yych <= 0x7F)
8380  {
8381  goto basic_json_parser_32;
8382  }
8383  if (yych <= 0xBF)
8384  {
8385  goto basic_json_parser_38;
8386  }
8387  goto basic_json_parser_32;
8388 basic_json_parser_42:
8389  ++m_cursor;
8390  if (m_limit <= m_cursor)
8391  {
8392  fill_line_buffer(1); // LCOV_EXCL_LINE
8393  }
8394  yych = *m_cursor;
8395  if (yych <= 0x7F)
8396  {
8397  goto basic_json_parser_32;
8398  }
8399  if (yych <= 0x8F)
8400  {
8401  goto basic_json_parser_38;
8402  }
8403  goto basic_json_parser_32;
8404 basic_json_parser_43:
8405  yych = *++m_cursor;
8406  if (yych <= '/')
8407  {
8408  goto basic_json_parser_32;
8409  }
8410  if (yych <= '9')
8411  {
8412  goto basic_json_parser_49;
8413  }
8414  goto basic_json_parser_32;
8415 basic_json_parser_44:
8416  yych = *++m_cursor;
8417  if (yych <= ',')
8418  {
8419  if (yych == '+')
8420  {
8421  goto basic_json_parser_51;
8422  }
8423  goto basic_json_parser_32;
8424  }
8425  else
8426  {
8427  if (yych <= '-')
8428  {
8429  goto basic_json_parser_51;
8430  }
8431  if (yych <= '/')
8432  {
8433  goto basic_json_parser_32;
8434  }
8435  if (yych <= '9')
8436  {
8437  goto basic_json_parser_52;
8438  }
8439  goto basic_json_parser_32;
8440  }
8441 basic_json_parser_45:
8442  yych = *++m_cursor;
8443  if (yych == 'l')
8444  {
8445  goto basic_json_parser_54;
8446  }
8447  goto basic_json_parser_32;
8448 basic_json_parser_46:
8449  yych = *++m_cursor;
8450  if (yych == 'l')
8451  {
8452  goto basic_json_parser_55;
8453  }
8454  goto basic_json_parser_32;
8455 basic_json_parser_47:
8456  yych = *++m_cursor;
8457  if (yych == 'u')
8458  {
8459  goto basic_json_parser_56;
8460  }
8461  goto basic_json_parser_32;
8462 basic_json_parser_48:
8463  ++m_cursor;
8464  if (m_limit <= m_cursor)
8465  {
8466  fill_line_buffer(1); // LCOV_EXCL_LINE
8467  }
8468  yych = *m_cursor;
8469  if (yych <= '@')
8470  {
8471  if (yych <= '/')
8472  {
8473  goto basic_json_parser_32;
8474  }
8475  if (yych <= '9')
8476  {
8477  goto basic_json_parser_57;
8478  }
8479  goto basic_json_parser_32;
8480  }
8481  else
8482  {
8483  if (yych <= 'F')
8484  {
8485  goto basic_json_parser_57;
8486  }
8487  if (yych <= '`')
8488  {
8489  goto basic_json_parser_32;
8490  }
8491  if (yych <= 'f')
8492  {
8493  goto basic_json_parser_57;
8494  }
8495  goto basic_json_parser_32;
8496  }
8497 basic_json_parser_49:
8498  yyaccept = 1;
8499  m_marker = ++m_cursor;
8500  if ((m_limit - m_cursor) < 3)
8501  {
8502  fill_line_buffer(3); // LCOV_EXCL_LINE
8503  }
8504  yych = *m_cursor;
8505  if (yych <= 'D')
8506  {
8507  if (yych <= '/')
8508  {
8509  goto basic_json_parser_14;
8510  }
8511  if (yych <= '9')
8512  {
8513  goto basic_json_parser_49;
8514  }
8515  goto basic_json_parser_14;
8516  }
8517  else
8518  {
8519  if (yych <= 'E')
8520  {
8521  goto basic_json_parser_44;
8522  }
8523  if (yych == 'e')
8524  {
8525  goto basic_json_parser_44;
8526  }
8527  goto basic_json_parser_14;
8528  }
8529 basic_json_parser_51:
8530  yych = *++m_cursor;
8531  if (yych <= '/')
8532  {
8533  goto basic_json_parser_32;
8534  }
8535  if (yych >= ':')
8536  {
8537  goto basic_json_parser_32;
8538  }
8539 basic_json_parser_52:
8540  ++m_cursor;
8541  if (m_limit <= m_cursor)
8542  {
8543  fill_line_buffer(1); // LCOV_EXCL_LINE
8544  }
8545  yych = *m_cursor;
8546  if (yych <= '/')
8547  {
8548  goto basic_json_parser_14;
8549  }
8550  if (yych <= '9')
8551  {
8552  goto basic_json_parser_52;
8553  }
8554  goto basic_json_parser_14;
8555 basic_json_parser_54:
8556  yych = *++m_cursor;
8557  if (yych == 's')
8558  {
8559  goto basic_json_parser_58;
8560  }
8561  goto basic_json_parser_32;
8562 basic_json_parser_55:
8563  yych = *++m_cursor;
8564  if (yych == 'l')
8565  {
8566  goto basic_json_parser_59;
8567  }
8568  goto basic_json_parser_32;
8569 basic_json_parser_56:
8570  yych = *++m_cursor;
8571  if (yych == 'e')
8572  {
8573  goto basic_json_parser_61;
8574  }
8575  goto basic_json_parser_32;
8576 basic_json_parser_57:
8577  ++m_cursor;
8578  if (m_limit <= m_cursor)
8579  {
8580  fill_line_buffer(1); // LCOV_EXCL_LINE
8581  }
8582  yych = *m_cursor;
8583  if (yych <= '@')
8584  {
8585  if (yych <= '/')
8586  {
8587  goto basic_json_parser_32;
8588  }
8589  if (yych <= '9')
8590  {
8591  goto basic_json_parser_63;
8592  }
8593  goto basic_json_parser_32;
8594  }
8595  else
8596  {
8597  if (yych <= 'F')
8598  {
8599  goto basic_json_parser_63;
8600  }
8601  if (yych <= '`')
8602  {
8603  goto basic_json_parser_32;
8604  }
8605  if (yych <= 'f')
8606  {
8607  goto basic_json_parser_63;
8608  }
8609  goto basic_json_parser_32;
8610  }
8611 basic_json_parser_58:
8612  yych = *++m_cursor;
8613  if (yych == 'e')
8614  {
8615  goto basic_json_parser_64;
8616  }
8617  goto basic_json_parser_32;
8618 basic_json_parser_59:
8619  ++m_cursor;
8620  {
8621  last_token_type = token_type::literal_null;
8622  break;
8623  }
8624 basic_json_parser_61:
8625  ++m_cursor;
8626  {
8627  last_token_type = token_type::literal_true;
8628  break;
8629  }
8630 basic_json_parser_63:
8631  ++m_cursor;
8632  if (m_limit <= m_cursor)
8633  {
8634  fill_line_buffer(1); // LCOV_EXCL_LINE
8635  }
8636  yych = *m_cursor;
8637  if (yych <= '@')
8638  {
8639  if (yych <= '/')
8640  {
8641  goto basic_json_parser_32;
8642  }
8643  if (yych <= '9')
8644  {
8645  goto basic_json_parser_66;
8646  }
8647  goto basic_json_parser_32;
8648  }
8649  else
8650  {
8651  if (yych <= 'F')
8652  {
8653  goto basic_json_parser_66;
8654  }
8655  if (yych <= '`')
8656  {
8657  goto basic_json_parser_32;
8658  }
8659  if (yych <= 'f')
8660  {
8661  goto basic_json_parser_66;
8662  }
8663  goto basic_json_parser_32;
8664  }
8665 basic_json_parser_64:
8666  ++m_cursor;
8667  {
8668  last_token_type = token_type::literal_false;
8669  break;
8670  }
8671 basic_json_parser_66:
8672  ++m_cursor;
8673  if (m_limit <= m_cursor)
8674  {
8675  fill_line_buffer(1); // LCOV_EXCL_LINE
8676  }
8677  yych = *m_cursor;
8678  if (yych <= '@')
8679  {
8680  if (yych <= '/')
8681  {
8682  goto basic_json_parser_32;
8683  }
8684  if (yych <= '9')
8685  {
8686  goto basic_json_parser_30;
8687  }
8688  goto basic_json_parser_32;
8689  }
8690  else
8691  {
8692  if (yych <= 'F')
8693  {
8694  goto basic_json_parser_30;
8695  }
8696  if (yych <= '`')
8697  {
8698  goto basic_json_parser_32;
8699  }
8700  if (yych <= 'f')
8701  {
8702  goto basic_json_parser_30;
8703  }
8704  goto basic_json_parser_32;
8705  }
8706  }
8707 
8708  }
8709 
8710  return last_token_type;
8711  }
8712 
8741  void fill_line_buffer(size_t n = 0)
8742  {
8743  // number of processed characters (p)
8744  const auto offset_start = m_start - m_content;
8745  // offset for m_marker wrt. to m_start
8746  const auto offset_marker = (m_marker == nullptr) ? 0 : m_marker - m_start;
8747  // number of unprocessed characters (u)
8748  const auto offset_cursor = m_cursor - m_start;
8749 
8750  // no stream is used or end of file is reached
8751  if (m_stream == nullptr or m_stream->eof())
8752  {
8753  // skip this part if we are already using the line buffer
8754  if (m_start != reinterpret_cast<const lexer_char_t*>(m_line_buffer.data()))
8755  {
8756  // copy unprocessed characters to line buffer
8757  m_line_buffer.clear();
8758  for (m_cursor = m_start; m_cursor != m_limit; ++m_cursor)
8759  {
8760  m_line_buffer.append(1, static_cast<const char>(*m_cursor));
8761  }
8762  }
8763 
8764  // append n characters to make sure that there is sufficient
8765  // space between m_cursor and m_limit
8766  m_line_buffer.append(1, '\x00');
8767  m_line_buffer.append(n - 1, '\x01');
8768  }
8769  else
8770  {
8771  // delete processed characters from line buffer
8772  m_line_buffer.erase(0, static_cast<size_t>(offset_start));
8773  // read next line from input stream
8774  std::string line;
8775  std::getline(*m_stream, line, '\n');
8776  // add line with newline symbol to the line buffer
8777  m_line_buffer += line + "\n";
8778  }
8779 
8780  // set pointers
8781  m_content = reinterpret_cast<const lexer_char_t*>(m_line_buffer.c_str());
8782  assert(m_content != nullptr);
8783  m_start = m_content;
8784  m_marker = m_start + offset_marker;
8785  m_cursor = m_start + offset_cursor;
8786  m_limit = m_start + m_line_buffer.size();
8787  }
8788 
8790  string_t get_token_string() const
8791  {
8792  assert(m_start != nullptr);
8793  return string_t(reinterpret_cast<typename string_t::const_pointer>(m_start),
8794  static_cast<size_t>(m_cursor - m_start));
8795  }
8796 
8854  string_t get_string() const
8855  {
8856  assert(m_cursor - m_start >= 2);
8857 
8858  string_t result;
8859  result.reserve(static_cast<size_t>(m_cursor - m_start - 2));
8860 
8861  // iterate the result between the quotes
8862  for (const lexer_char_t* i = m_start + 1; i < m_cursor - 1; ++i)
8863  {
8864  // process escaped characters
8865  if (*i == '\\')
8866  {
8867  // read next character
8868  ++i;
8869 
8870  switch (*i)
8871  {
8872  // the default escapes
8873  case 't':
8874  {
8875  result += "\t";
8876  break;
8877  }
8878  case 'b':
8879  {
8880  result += "\b";
8881  break;
8882  }
8883  case 'f':
8884  {
8885  result += "\f";
8886  break;
8887  }
8888  case 'n':
8889  {
8890  result += "\n";
8891  break;
8892  }
8893  case 'r':
8894  {
8895  result += "\r";
8896  break;
8897  }
8898  case '\\':
8899  {
8900  result += "\\";
8901  break;
8902  }
8903  case '/':
8904  {
8905  result += "/";
8906  break;
8907  }
8908  case '"':
8909  {
8910  result += "\"";
8911  break;
8912  }
8913 
8914  // unicode
8915  case 'u':
8916  {
8917  // get code xxxx from uxxxx
8918  auto codepoint = std::strtoul(std::string(reinterpret_cast<typename string_t::const_pointer>(i + 1),
8919  4).c_str(), nullptr, 16);
8920 
8921  // check if codepoint is a high surrogate
8922  if (codepoint >= 0xD800 and codepoint <= 0xDBFF)
8923  {
8924  // make sure there is a subsequent unicode
8925  if ((i + 6 >= m_limit) or * (i + 5) != '\\' or * (i + 6) != 'u')
8926  {
8927  throw std::invalid_argument("missing low surrogate");
8928  }
8929 
8930  // get code yyyy from uxxxx\uyyyy
8931  auto codepoint2 = std::strtoul(std::string(reinterpret_cast<typename string_t::const_pointer>
8932  (i + 7), 4).c_str(), nullptr, 16);
8933  result += to_unicode(codepoint, codepoint2);
8934  // skip the next 10 characters (xxxx\uyyyy)
8935  i += 10;
8936  }
8937  else if (codepoint >= 0xDC00 and codepoint <= 0xDFFF)
8938  {
8939  // we found a lone low surrogate
8940  throw std::invalid_argument("missing high surrogate");
8941  }
8942  else
8943  {
8944  // add unicode character(s)
8945  result += to_unicode(codepoint);
8946  // skip the next four characters (xxxx)
8947  i += 4;
8948  }
8949  break;
8950  }
8951  }
8952  }
8953  else
8954  {
8955  // all other characters are just copied to the end of the
8956  // string
8957  result.append(1, static_cast<typename string_t::value_type>(*i));
8958  }
8959  }
8960 
8961  return result;
8962  }
8963 
8979  long double str_to_float_t(long double* /* type */, char** endptr) const
8980  {
8981  return std::strtold(reinterpret_cast<typename string_t::const_pointer>(m_start), endptr);
8982  }
8983 
8999  double str_to_float_t(double* /* type */, char** endptr) const
9000  {
9001  return std::strtod(reinterpret_cast<typename string_t::const_pointer>(m_start), endptr);
9002  }
9003 
9019  float str_to_float_t(float* /* type */, char** endptr) const
9020  {
9021  return std::strtof(reinterpret_cast<typename string_t::const_pointer>(m_start), endptr);
9022  }
9023 
9045  void get_number(basic_json& result) const
9046  {
9047  assert(m_start != nullptr);
9048 
9049  const lexer::lexer_char_t* curptr = m_start;
9050 
9051  // accumulate the integer conversion result (unsigned for now)
9052  number_unsigned_t value = 0;
9053 
9054  // maximum absolute value of the relevant integer type
9055  number_unsigned_t max;
9056 
9057  // temporarily store the type to avoid unecessary bitfield access
9058  value_t type;
9059 
9060  // look for sign
9061  if (*curptr == '-')
9062  {
9063  type = value_t::number_integer;
9064  max = static_cast<uint64_t>((std::numeric_limits<number_integer_t>::max)()) + 1;
9065  curptr++;
9066  }
9067  else
9068  {
9069  type = value_t::number_unsigned;
9070  max = static_cast<uint64_t>((std::numeric_limits<number_unsigned_t>::max)());
9071  }
9072 
9073  // count the significant figures
9074  for (; curptr < m_cursor; curptr++)
9075  {
9076  // quickly skip tests if a digit
9077  if (*curptr < '0' || *curptr > '9')
9078  {
9079  if (*curptr == '.')
9080  {
9081  // don't count '.' but change to float
9082  type = value_t::number_float;
9083  continue;
9084  }
9085  // assume exponent (if not then will fail parse): change to
9086  // float, stop counting and record exponent details
9087  type = value_t::number_float;
9088  break;
9089  }
9090 
9091  // skip if definitely not an integer
9092  if (type != value_t::number_float)
9093  {
9094  // multiply last value by ten and add the new digit
9095  auto temp = value * 10 + *curptr - '0';
9096 
9097  // test for overflow
9098  if (temp < value || temp > max)
9099  {
9100  // overflow
9101  type = value_t::number_float;
9102  }
9103  else
9104  {
9105  // no overflow - save it
9106  value = temp;
9107  }
9108  }
9109  }
9110 
9111  // save the value (if not a float)
9112  if (type == value_t::number_unsigned)
9113  {
9114  result.m_value.number_unsigned = value;
9115  }
9116  else if (type == value_t::number_integer)
9117  {
9118  result.m_value.number_integer = -static_cast<number_integer_t>(value);
9119  }
9120  else
9121  {
9122  // parse with strtod
9123  result.m_value.number_float = str_to_float_t(static_cast<number_float_t*>(nullptr), NULL);
9124 
9125  // replace infinity and NAN by null
9126  if (not std::isfinite(result.m_value.number_float))
9127  {
9128  type = value_t::null;
9129  result.m_value = basic_json::json_value();
9130  }
9131  }
9132 
9133  // save the type
9134  result.m_type = type;
9135  }
9136 
9137  private:
9139  std::istream* m_stream = nullptr;
9141  string_t m_line_buffer {};
9143  const lexer_char_t* m_content = nullptr;
9145  const lexer_char_t* m_start = nullptr;
9147  const lexer_char_t* m_marker = nullptr;
9149  const lexer_char_t* m_cursor = nullptr;
9151  const lexer_char_t* m_limit = nullptr;
9153  token_type last_token_type = token_type::end_of_input;
9154  };
9155 
9161  class parser
9162  {
9163  public:
9165  parser(const char* buff, const parser_callback_t cb = nullptr)
9166  : callback(cb),
9167  m_lexer(reinterpret_cast<const typename lexer::lexer_char_t*>(buff), strlen(buff))
9168  {}
9169 
9171  parser(std::istream& is, const parser_callback_t cb = nullptr)
9172  : callback(cb), m_lexer(is)
9173  {}
9174 
9176  template<class IteratorType, typename std::enable_if<
9177  std::is_same<typename std::iterator_traits<IteratorType>::iterator_category, std::random_access_iterator_tag>::value
9178  , int>::type
9179  = 0>
9180  parser(IteratorType first, IteratorType last, const parser_callback_t cb = nullptr)
9181  : callback(cb),
9182  m_lexer(reinterpret_cast<const typename lexer::lexer_char_t*>(&(*first)),
9183  static_cast<size_t>(std::distance(first, last)))
9184  {}
9185 
9187  basic_json parse()
9188  {
9189  // read first token
9190  get_token();
9191 
9192  basic_json result = parse_internal(true);
9193  result.assert_invariant();
9194 
9195  expect(lexer::token_type::end_of_input);
9196 
9197  // return parser result and replace it with null in case the
9198  // top-level value was discarded by the callback function
9199  return result.is_discarded() ? basic_json() : std::move(result);
9200  }
9201 
9202  private:
9204  basic_json parse_internal(bool keep)
9205  {
9206  auto result = basic_json(value_t::discarded);
9207 
9208  switch (last_token)
9209  {
9210  case lexer::token_type::begin_object:
9211  {
9212  if (keep and (not callback
9213  or ((keep = callback(depth++, parse_event_t::object_start, result)) != 0)))
9214  {
9215  // explicitly set result to object to cope with {}
9216  result.m_type = value_t::object;
9217  result.m_value = value_t::object;
9218  }
9219 
9220  // read next token
9221  get_token();
9222 
9223  // closing } -> we are done
9224  if (last_token == lexer::token_type::end_object)
9225  {
9226  get_token();
9227  if (keep and callback and not callback(--depth, parse_event_t::object_end, result))
9228  {
9229  result = basic_json(value_t::discarded);
9230  }
9231  return result;
9232  }
9233 
9234  // no comma is expected here
9235  unexpect(lexer::token_type::value_separator);
9236 
9237  // otherwise: parse key-value pairs
9238  do
9239  {
9240  // ugly, but could be fixed with loop reorganization
9241  if (last_token == lexer::token_type::value_separator)
9242  {
9243  get_token();
9244  }
9245 
9246  // store key
9247  expect(lexer::token_type::value_string);
9248  const auto key = m_lexer.get_string();
9249 
9250  bool keep_tag = false;
9251  if (keep)
9252  {
9253  if (callback)
9254  {
9255  basic_json k(key);
9256  keep_tag = callback(depth, parse_event_t::key, k);
9257  }
9258  else
9259  {
9260  keep_tag = true;
9261  }
9262  }
9263 
9264  // parse separator (:)
9265  get_token();
9266  expect(lexer::token_type::name_separator);
9267 
9268  // parse and add value
9269  get_token();
9270  auto value = parse_internal(keep);
9271  if (keep and keep_tag and not value.is_discarded())
9272  {
9273  result[key] = std::move(value);
9274  }
9275  }
9276  while (last_token == lexer::token_type::value_separator);
9277 
9278  // closing }
9279  expect(lexer::token_type::end_object);
9280  get_token();
9281  if (keep and callback and not callback(--depth, parse_event_t::object_end, result))
9282  {
9283  result = basic_json(value_t::discarded);
9284  }
9285 
9286  return result;
9287  }
9288 
9289  case lexer::token_type::begin_array:
9290  {
9291  if (keep and (not callback
9292  or ((keep = callback(depth++, parse_event_t::array_start, result)) != 0)))
9293  {
9294  // explicitly set result to object to cope with []
9295  result.m_type = value_t::array;
9296  result.m_value = value_t::array;
9297  }
9298 
9299  // read next token
9300  get_token();
9301 
9302  // closing ] -> we are done
9303  if (last_token == lexer::token_type::end_array)
9304  {
9305  get_token();
9306  if (callback and not callback(--depth, parse_event_t::array_end, result))
9307  {
9308  result = basic_json(value_t::discarded);
9309  }
9310  return result;
9311  }
9312 
9313  // no comma is expected here
9314  unexpect(lexer::token_type::value_separator);
9315 
9316  // otherwise: parse values
9317  do
9318  {
9319  // ugly, but could be fixed with loop reorganization
9320  if (last_token == lexer::token_type::value_separator)
9321  {
9322  get_token();
9323  }
9324 
9325  // parse value
9326  auto value = parse_internal(keep);
9327  if (keep and not value.is_discarded())
9328  {
9329  result.push_back(std::move(value));
9330  }
9331  }
9332  while (last_token == lexer::token_type::value_separator);
9333 
9334  // closing ]
9335  expect(lexer::token_type::end_array);
9336  get_token();
9337  if (keep and callback and not callback(--depth, parse_event_t::array_end, result))
9338  {
9339  result = basic_json(value_t::discarded);
9340  }
9341 
9342  return result;
9343  }
9344 
9345  case lexer::token_type::literal_null:
9346  {
9347  get_token();
9348  result.m_type = value_t::null;
9349  break;
9350  }
9351 
9352  case lexer::token_type::value_string:
9353  {
9354  const auto s = m_lexer.get_string();
9355  get_token();
9356  result = basic_json(s);
9357  break;
9358  }
9359 
9360  case lexer::token_type::literal_true:
9361  {
9362  get_token();
9363  result.m_type = value_t::boolean;
9364  result.m_value = true;
9365  break;
9366  }
9367 
9368  case lexer::token_type::literal_false:
9369  {
9370  get_token();
9371  result.m_type = value_t::boolean;
9372  result.m_value = false;
9373  break;
9374  }
9375 
9376  case lexer::token_type::value_number:
9377  {
9378  m_lexer.get_number(result);
9379  get_token();
9380  break;
9381  }
9382 
9383  default:
9384  {
9385  // the last token was unexpected
9386  unexpect(last_token);
9387  }
9388  }
9389 
9390  if (keep and callback and not callback(depth, parse_event_t::value, result))
9391  {
9392  result = basic_json(value_t::discarded);
9393  }
9394  return result;
9395  }
9396 
9398  typename lexer::token_type get_token()
9399  {
9400  last_token = m_lexer.scan();
9401  return last_token;
9402  }
9403 
9404  void expect(typename lexer::token_type t) const
9405  {
9406  if (t != last_token)
9407  {
9408  std::string error_msg = "parse error - unexpected ";
9409  error_msg += (last_token == lexer::token_type::parse_error ? ("'" + m_lexer.get_token_string() +
9410  "'") :
9411  lexer::token_type_name(last_token));
9412  error_msg += "; expected " + lexer::token_type_name(t);
9413  throw std::invalid_argument(error_msg);
9414  }
9415  }
9416 
9417  void unexpect(typename lexer::token_type t) const
9418  {
9419  if (t == last_token)
9420  {
9421  std::string error_msg = "parse error - unexpected ";
9422  error_msg += (last_token == lexer::token_type::parse_error ? ("'" + m_lexer.get_token_string() +
9423  "'") :
9424  lexer::token_type_name(last_token));
9425  throw std::invalid_argument(error_msg);
9426  }
9427  }
9428 
9429  private:
9431  int depth = 0;
9433  const parser_callback_t callback = nullptr;
9435  typename lexer::token_type last_token = lexer::token_type::uninitialized;
9437  lexer m_lexer;
9438  };
9439 
9440  public:
9453  {
9455  friend class basic_json;
9456 
9457  public:
9480  explicit json_pointer(const std::string& s = "")
9481  : reference_tokens(split(s))
9482  {}
9483 
9499  std::string to_string() const noexcept
9500  {
9501  return std::accumulate(reference_tokens.begin(),
9502  reference_tokens.end(), std::string{},
9503  [](const std::string & a, const std::string & b)
9504  {
9505  return a + "/" + escape(b);
9506  });
9507  }
9508 
9510  operator std::string() const
9511  {
9512  return to_string();
9513  }
9515  private:
9517  std::string pop_back()
9518  {
9519  if (is_root())
9520  {
9521  throw std::domain_error("JSON pointer has no parent");
9522  }
9523 
9524  auto last = reference_tokens.back();
9525  reference_tokens.pop_back();
9526  return last;
9527  }
9528 
9530  bool is_root() const
9531  {
9532  return reference_tokens.empty();
9533  }
9534 
9535  json_pointer top() const
9536  {
9537  if (is_root())
9538  {
9539  throw std::domain_error("JSON pointer has no parent");
9540  }
9541 
9542  json_pointer result = *this;
9543  result.reference_tokens = {reference_tokens[0]};
9544  return result;
9545  }
9546 
9552  reference get_and_create(reference j) const
9553  {
9554  pointer result = &j;
9555 
9556  // in case no reference tokens exist, return a reference to the
9557  // JSON value j which will be overwritten by a primitive value
9558  for (const auto& reference_token : reference_tokens)
9559  {
9560  switch (result->m_type)
9561  {
9562  case value_t::null:
9563  {
9564  if (reference_token == "0")
9565  {
9566  // start a new array if reference token is 0
9567  result = &result->operator[](0);
9568  }
9569  else
9570  {
9571  // start a new object otherwise
9572  result = &result->operator[](reference_token);
9573  }
9574  break;
9575  }
9576 
9577  case value_t::object:
9578  {
9579  // create an entry in the object
9580  result = &result->operator[](reference_token);
9581  break;
9582  }
9583 
9584  case value_t::array:
9585  {
9586  // create an entry in the array
9587  result = &result->operator[](static_cast<size_type>(std::stoi(reference_token)));
9588  break;
9589  }
9590 
9591  /*
9592  The following code is only reached if there exists a
9593  reference token _and_ the current value is primitive. In
9594  this case, we have an error situation, because primitive
9595  values may only occur as single value; that is, with an
9596  empty list of reference tokens.
9597  */
9598  default:
9599  {
9600  throw std::domain_error("invalid value to unflatten");
9601  }
9602  }
9603  }
9604 
9605  return *result;
9606  }
9607 
9627  reference get_unchecked(pointer ptr) const
9628  {
9629  for (const auto& reference_token : reference_tokens)
9630  {
9631  // convert null values to arrays or objects before continuing
9632  if (ptr->m_type == value_t::null)
9633  {
9634  // check if reference token is a number
9635  const bool nums = std::all_of(reference_token.begin(),
9636  reference_token.end(),
9637  [](const char x)
9638  {
9639  return std::isdigit(x);
9640  });
9641 
9642  // change value to array for numbers or "-" or to object
9643  // otherwise
9644  if (nums or reference_token == "-")
9645  {
9646  *ptr = value_t::array;
9647  }
9648  else
9649  {
9650  *ptr = value_t::object;
9651  }
9652  }
9653 
9654  switch (ptr->m_type)
9655  {
9656  case value_t::object:
9657  {
9658  // use unchecked object access
9659  ptr = &ptr->operator[](reference_token);
9660  break;
9661  }
9662 
9663  case value_t::array:
9664  {
9665  // error condition (cf. RFC 6901, Sect. 4)
9666  if (reference_token.size() > 1 and reference_token[0] == '0')
9667  {
9668  throw std::domain_error("array index must not begin with '0'");
9669  }
9670 
9671  if (reference_token == "-")
9672  {
9673  // explicityly treat "-" as index beyond the end
9674  ptr = &ptr->operator[](ptr->m_value.array->size());
9675  }
9676  else
9677  {
9678  // convert array index to number; unchecked access
9679  ptr = &ptr->operator[](static_cast<size_type>(std::stoi(reference_token)));
9680  }
9681  break;
9682  }
9683 
9684  default:
9685  {
9686  throw std::out_of_range("unresolved reference token '" + reference_token + "'");
9687  }
9688  }
9689  }
9690 
9691  return *ptr;
9692  }
9693 
9694  reference get_checked(pointer ptr) const
9695  {
9696  for (const auto& reference_token : reference_tokens)
9697  {
9698  switch (ptr->m_type)
9699  {
9700  case value_t::object:
9701  {
9702  // note: at performs range check
9703  ptr = &ptr->at(reference_token);
9704  break;
9705  }
9706 
9707  case value_t::array:
9708  {
9709  if (reference_token == "-")
9710  {
9711  // "-" always fails the range check
9712  throw std::out_of_range("array index '-' (" +
9713  std::to_string(ptr->m_value.array->size()) +
9714  ") is out of range");
9715  }
9716 
9717  // error condition (cf. RFC 6901, Sect. 4)
9718  if (reference_token.size() > 1 and reference_token[0] == '0')
9719  {
9720  throw std::domain_error("array index must not begin with '0'");
9721  }
9722 
9723  // note: at performs range check
9724  ptr = &ptr->at(static_cast<size_type>(std::stoi(reference_token)));
9725  break;
9726  }
9727 
9728  default:
9729  {
9730  throw std::out_of_range("unresolved reference token '" + reference_token + "'");
9731  }
9732  }
9733  }
9734 
9735  return *ptr;
9736  }
9737 
9746  const_reference get_unchecked(const_pointer ptr) const
9747  {
9748  for (const auto& reference_token : reference_tokens)
9749  {
9750  switch (ptr->m_type)
9751  {
9752  case value_t::object:
9753  {
9754  // use unchecked object access
9755  ptr = &ptr->operator[](reference_token);
9756  break;
9757  }
9758 
9759  case value_t::array:
9760  {
9761  if (reference_token == "-")
9762  {
9763  // "-" cannot be used for const access
9764  throw std::out_of_range("array index '-' (" +
9765  std::to_string(ptr->m_value.array->size()) +
9766  ") is out of range");
9767  }
9768 
9769  // error condition (cf. RFC 6901, Sect. 4)
9770  if (reference_token.size() > 1 and reference_token[0] == '0')
9771  {
9772  throw std::domain_error("array index must not begin with '0'");
9773  }
9774 
9775  // use unchecked array access
9776  ptr = &ptr->operator[](static_cast<size_type>(std::stoi(reference_token)));
9777  break;
9778  }
9779 
9780  default:
9781  {
9782  throw std::out_of_range("unresolved reference token '" + reference_token + "'");
9783  }
9784  }
9785  }
9786 
9787  return *ptr;
9788  }
9789 
9790  const_reference get_checked(const_pointer ptr) const
9791  {
9792  for (const auto& reference_token : reference_tokens)
9793  {
9794  switch (ptr->m_type)
9795  {
9796  case value_t::object:
9797  {
9798  // note: at performs range check
9799  ptr = &ptr->at(reference_token);
9800  break;
9801  }
9802 
9803  case value_t::array:
9804  {
9805  if (reference_token == "-")
9806  {
9807  // "-" always fails the range check
9808  throw std::out_of_range("array index '-' (" +
9809  std::to_string(ptr->m_value.array->size()) +
9810  ") is out of range");
9811  }
9812 
9813  // error condition (cf. RFC 6901, Sect. 4)
9814  if (reference_token.size() > 1 and reference_token[0] == '0')
9815  {
9816  throw std::domain_error("array index must not begin with '0'");
9817  }
9818 
9819  // note: at performs range check
9820  ptr = &ptr->at(static_cast<size_type>(std::stoi(reference_token)));
9821  break;
9822  }
9823 
9824  default:
9825  {
9826  throw std::out_of_range("unresolved reference token '" + reference_token + "'");
9827  }
9828  }
9829  }
9830 
9831  return *ptr;
9832  }
9833 
9835  static std::vector<std::string> split(const std::string& reference_string)
9836  {
9837  std::vector<std::string> result;
9838 
9839  // special case: empty reference string -> no reference tokens
9840  if (reference_string.empty())
9841  {
9842  return result;
9843  }
9844 
9845  // check if nonempty reference string begins with slash
9846  if (reference_string[0] != '/')
9847  {
9848  throw std::domain_error("JSON pointer must be empty or begin with '/'");
9849  }
9850 
9851  // extract the reference tokens:
9852  // - slash: position of the last read slash (or end of string)
9853  // - start: position after the previous slash
9854  for (
9855  // search for the first slash after the first character
9856  size_t slash = reference_string.find_first_of("/", 1),
9857  // set the beginning of the first reference token
9858  start = 1;
9859  // we can stop if start == string::npos+1 = 0
9860  start != 0;
9861  // set the beginning of the next reference token
9862  // (will eventually be 0 if slash == std::string::npos)
9863  start = slash + 1,
9864  // find next slash
9865  slash = reference_string.find_first_of("/", start))
9866  {
9867  // use the text between the beginning of the reference token
9868  // (start) and the last slash (slash).
9869  auto reference_token = reference_string.substr(start, slash - start);
9870 
9871  // check reference tokens are properly escaped
9872  for (size_t pos = reference_token.find_first_of("~");
9873  pos != std::string::npos;
9874  pos = reference_token.find_first_of("~", pos + 1))
9875  {
9876  assert(reference_token[pos] == '~');
9877 
9878  // ~ must be followed by 0 or 1
9879  if (pos == reference_token.size() - 1 or
9880  (reference_token[pos + 1] != '0' and
9881  reference_token[pos + 1] != '1'))
9882  {
9883  throw std::domain_error("escape error: '~' must be followed with '0' or '1'");
9884  }
9885  }
9886 
9887  // finally, store the reference token
9888  unescape(reference_token);
9889  result.push_back(reference_token);
9890  }
9891 
9892  return result;
9893  }
9894 
9895  private:
9910  static void replace_substring(std::string& s,
9911  const std::string& f,
9912  const std::string& t)
9913  {
9914  assert(not f.empty());
9915 
9916  for (
9917  size_t pos = s.find(f); // find first occurrence of f
9918  pos != std::string::npos; // make sure f was found
9919  s.replace(pos, f.size(), t), // replace with t
9920  pos = s.find(f, pos + t.size()) // find next occurrence of f
9921  );
9922  }
9923 
9925  static std::string escape(std::string s)
9926  {
9927  // escape "~"" to "~0" and "/" to "~1"
9928  replace_substring(s, "~", "~0");
9929  replace_substring(s, "/", "~1");
9930  return s;
9931  }
9932 
9934  static void unescape(std::string& s)
9935  {
9936  // first transform any occurrence of the sequence '~1' to '/'
9937  replace_substring(s, "~1", "/");
9938  // then transform any occurrence of the sequence '~0' to '~'
9939  replace_substring(s, "~0", "~");
9940  }
9941 
9949  static void flatten(const std::string& reference_string,
9950  const basic_json& value,
9951  basic_json& result)
9952  {
9953  switch (value.m_type)
9954  {
9955  case value_t::array:
9956  {
9957  if (value.m_value.array->empty())
9958  {
9959  // flatten empty array as null
9960  result[reference_string] = nullptr;
9961  }
9962  else
9963  {
9964  // iterate array and use index as reference string
9965  for (size_t i = 0; i < value.m_value.array->size(); ++i)
9966  {
9967  flatten(reference_string + "/" + std::to_string(i),
9968  value.m_value.array->operator[](i), result);
9969  }
9970  }
9971  break;
9972  }
9973 
9974  case value_t::object:
9975  {
9976  if (value.m_value.object->empty())
9977  {
9978  // flatten empty object as null
9979  result[reference_string] = nullptr;
9980  }
9981  else
9982  {
9983  // iterate object and use keys as reference string
9984  for (const auto& element : *value.m_value.object)
9985  {
9986  flatten(reference_string + "/" + escape(element.first),
9987  element.second, result);
9988  }
9989  }
9990  break;
9991  }
9992 
9993  default:
9994  {
9995  // add primitive value with its reference string
9996  result[reference_string] = value;
9997  break;
9998  }
9999  }
10000  }
10001 
10007  static basic_json unflatten(const basic_json& value)
10008  {
10009  if (not value.is_object())
10010  {
10011  throw std::domain_error("only objects can be unflattened");
10012  }
10013 
10014  basic_json result;
10015 
10016  // iterate the JSON object values
10017  for (const auto& element : *value.m_value.object)
10018  {
10019  if (not element.second.is_primitive())
10020  {
10021  throw std::domain_error("values in object must be primitive");
10022  }
10023 
10024  // assign value to reference pointed to by JSON pointer; Note
10025  // that if the JSON pointer is "" (i.e., points to the whole
10026  // value), function get_and_create returns a reference to
10027  // result itself. An assignment will then create a primitive
10028  // value.
10029  json_pointer(element.first).get_and_create(result) = element.second;
10030  }
10031 
10032  return result;
10033  }
10034 
10035  private:
10037  std::vector<std::string> reference_tokens {};
10038  };
10039 
10041  // JSON Pointer support //
10043 
10046 
10080  reference operator[](const json_pointer& ptr)
10081  {
10082  return ptr.get_unchecked(this);
10083  }
10107  const_reference operator[](const json_pointer& ptr) const
10108  {
10109  return ptr.get_unchecked(this);
10110  }
10132  reference at(const json_pointer& ptr)
10133  {
10134  return ptr.get_checked(this);
10135  }
10157  const_reference at(const json_pointer& ptr) const
10158  {
10159  return ptr.get_checked(this);
10160  }
10184  basic_json flatten() const
10185  {
10186  basic_json result(value_t::object);
10187  json_pointer::flatten("", *this, result);
10188  return result;
10189  }
10190 
10218  basic_json unflatten() const
10219  {
10220  return json_pointer::unflatten(*this);
10221  }
10224 
10226  // JSON Patch functions //
10228 
10231 
10268  basic_json patch(const basic_json& json_patch) const
10269  {
10270  // make a working copy to apply the patch to
10271  basic_json result = *this;
10273  // the valid JSON Patch operations
10274  enum class patch_operations {add, remove, replace, move, copy, test, invalid};
10275 
10276  const auto get_op = [](const std::string op)
10277  {
10278  if (op == "add")
10279  {
10280  return patch_operations::add;
10281  }
10282  if (op == "remove")
10283  {
10284  return patch_operations::remove;
10285  }
10286  if (op == "replace")
10287  {
10288  return patch_operations::replace;
10289  }
10290  if (op == "move")
10291  {
10292  return patch_operations::move;
10293  }
10294  if (op == "copy")
10295  {
10296  return patch_operations::copy;
10297  }
10298  if (op == "test")
10299  {
10300  return patch_operations::test;
10301  }
10302 
10303  return patch_operations::invalid;
10304  };
10305 
10306  // wrapper for "add" operation; add value at ptr
10307  const auto operation_add = [&result](json_pointer & ptr, basic_json val)
10308  {
10309  // adding to the root of the target document means replacing it
10310  if (ptr.is_root())
10311  {
10312  result = val;
10313  }
10314  else
10315  {
10316  // make sure the top element of the pointer exists
10317  json_pointer top_pointer = ptr.top();
10318  if (top_pointer != ptr)
10319  {
10320  result.at(top_pointer);
10321  }
10322 
10323  // get reference to parent of JSON pointer ptr
10324  const auto last_path = ptr.pop_back();
10325  basic_json& parent = result[ptr];
10326 
10327  switch (parent.m_type)
10328  {
10329  case value_t::null:
10330  case value_t::object:
10331  {
10332  // use operator[] to add value
10333  parent[last_path] = val;
10334  break;
10335  }
10336 
10337  case value_t::array:
10338  {
10339  if (last_path == "-")
10340  {
10341  // special case: append to back
10342  parent.push_back(val);
10343  }
10344  else
10345  {
10346  const auto idx = std::stoi(last_path);
10347  if (static_cast<size_type>(idx) > parent.size())
10348  {
10349  // avoid undefined behavior
10350  throw std::out_of_range("array index " + std::to_string(idx) + " is out of range");
10351  }
10352  else
10353  {
10354  // default case: insert add offset
10355  parent.insert(parent.begin() + static_cast<difference_type>(idx), val);
10356  }
10357  }
10358  break;
10359  }
10360 
10361  default:
10362  {
10363  // if there exists a parent it cannot be primitive
10364  assert(false); // LCOV_EXCL_LINE
10365  }
10366  }
10367  }
10368  };
10369 
10370  // wrapper for "remove" operation; remove value at ptr
10371  const auto operation_remove = [&result](json_pointer & ptr)
10372  {
10373  // get reference to parent of JSON pointer ptr
10374  const auto last_path = ptr.pop_back();
10375  basic_json& parent = result.at(ptr);
10376 
10377  // remove child
10378  if (parent.is_object())
10379  {
10380  // perform range check
10381  auto it = parent.find(last_path);
10382  if (it != parent.end())
10383  {
10384  parent.erase(it);
10385  }
10386  else
10387  {
10388  throw std::out_of_range("key '" + last_path + "' not found");
10389  }
10390  }
10391  else if (parent.is_array())
10392  {
10393  // note erase performs range check
10394  parent.erase(static_cast<size_type>(std::stoi(last_path)));
10395  }
10396  };
10397 
10398  // type check
10399  if (not json_patch.is_array())
10400  {
10401  // a JSON patch must be an array of objects
10402  throw std::invalid_argument("JSON patch must be an array of objects");
10403  }
10404 
10405  // iterate and apply th eoperations
10406  for (const auto& val : json_patch)
10407  {
10408  // wrapper to get a value for an operation
10409  const auto get_value = [&val](const std::string & op,
10410  const std::string & member,
10411  bool string_type) -> basic_json&
10412  {
10413  // find value
10414  auto it = val.m_value.object->find(member);
10415 
10416  // context-sensitive error message
10417  const auto error_msg = (op == "op") ? "operation" : "operation '" + op + "'";
10418 
10419  // check if desired value is present
10420  if (it == val.m_value.object->end())
10421  {
10422  throw std::invalid_argument(error_msg + " must have member '" + member + "'");
10423  }
10424 
10425  // check if result is of type string
10426  if (string_type and not it->second.is_string())
10427  {
10428  throw std::invalid_argument(error_msg + " must have string member '" + member + "'");
10429  }
10430 
10431  // no error: return value
10432  return it->second;
10433  };
10434 
10435  // type check
10436  if (not val.is_object())
10437  {
10438  throw std::invalid_argument("JSON patch must be an array of objects");
10439  }
10440 
10441  // collect mandatory members
10442  const std::string op = get_value("op", "op", true);
10443  const std::string path = get_value(op, "path", true);
10444  json_pointer ptr(path);
10445 
10446  switch (get_op(op))
10447  {
10448  case patch_operations::add:
10449  {
10450  operation_add(ptr, get_value("add", "value", false));
10451  break;
10452  }
10453 
10454  case patch_operations::remove:
10455  {
10456  operation_remove(ptr);
10457  break;
10458  }
10459 
10460  case patch_operations::replace:
10461  {
10462  // the "path" location must exist - use at()
10463  result.at(ptr) = get_value("replace", "value", false);
10464  break;
10465  }
10466 
10467  case patch_operations::move:
10468  {
10469  const std::string from_path = get_value("move", "from", true);
10470  json_pointer from_ptr(from_path);
10471 
10472  // the "from" location must exist - use at()
10473  basic_json v = result.at(from_ptr);
10474 
10475  // The move operation is functionally identical to a
10476  // "remove" operation on the "from" location, followed
10477  // immediately by an "add" operation at the target
10478  // location with the value that was just removed.
10479  operation_remove(from_ptr);
10480  operation_add(ptr, v);
10481  break;
10482  }
10483 
10484  case patch_operations::copy:
10485  {
10486  const std::string from_path = get_value("copy", "from", true);;
10487  const json_pointer from_ptr(from_path);
10488 
10489  // the "from" location must exist - use at()
10490  result[ptr] = result.at(from_ptr);
10491  break;
10492  }
10493 
10494  case patch_operations::test:
10495  {
10496  bool success = false;
10497  try
10498  {
10499  // check if "value" matches the one at "path"
10500  // the "path" location must exist - use at()
10501  success = (result.at(ptr) == get_value("test", "value", false));
10502  }
10503  catch (std::out_of_range&)
10504  {
10505  // ignore out of range errors: success remains false
10506  }
10507 
10508  // throw an exception if test fails
10509  if (not success)
10510  {
10511  throw std::domain_error("unsuccessful: " + val.dump());
10512  }
10513 
10514  break;
10515  }
10516 
10517  case patch_operations::invalid:
10518  {
10519  // op must be "add", "remove", "replace", "move", "copy", or
10520  // "test"
10521  throw std::invalid_argument("operation value '" + op + "' is invalid");
10522  }
10523  }
10524  }
10525 
10526  return result;
10527  }
10528 
10561  static basic_json diff(const basic_json& source,
10562  const basic_json& target,
10563  const std::string& path = "")
10564  {
10565  // the patch
10566  basic_json result(value_t::array);
10567 
10568  // if the values are the same, return empty patch
10569  if (source == target)
10570  {
10571  return result;
10572  }
10573 
10574  if (source.type() != target.type())
10575  {
10576  // different types: replace value
10577  result.push_back(
10578  {
10579  {"op", "replace"},
10580  {"path", path},
10581  {"value", target}
10582  });
10583  }
10584  else
10585  {
10586  switch (source.type())
10587  {
10588  case value_t::array:
10589  {
10590  // first pass: traverse common elements
10591  size_t i = 0;
10592  while (i < source.size() and i < target.size())
10593  {
10594  // recursive call to compare array values at index i
10595  auto temp_diff = diff(source[i], target[i], path + "/" + std::to_string(i));
10596  result.insert(result.end(), temp_diff.begin(), temp_diff.end());
10597  ++i;
10598  }
10599 
10600  // i now reached the end of at least one array
10601  // in a second pass, traverse the remaining elements
10602 
10603  // remove my remaining elements
10604  const auto end_index = static_cast<difference_type>(result.size());
10605  while (i < source.size())
10606  {
10607  // add operations in reverse order to avoid invalid
10608  // indices
10609  result.insert(result.begin() + end_index, object(
10610  {
10611  {"op", "remove"},
10612  {"path", path + "/" + std::to_string(i)}
10613  }));
10614  ++i;
10615  }
10616 
10617  // add other remaining elements
10618  while (i < target.size())
10619  {
10620  result.push_back(
10621  {
10622  {"op", "add"},
10623  {"path", path + "/" + std::to_string(i)},
10624  {"value", target[i]}
10625  });
10626  ++i;
10627  }
10628 
10629  break;
10630  }
10631 
10632  case value_t::object:
10633  {
10634  // first pass: traverse this object's elements
10635  for (auto it = source.begin(); it != source.end(); ++it)
10636  {
10637  // escape the key name to be used in a JSON patch
10638  const auto key = json_pointer::escape(it.key());
10639 
10640  if (target.find(it.key()) != target.end())
10641  {
10642  // recursive call to compare object values at key it
10643  auto temp_diff = diff(it.value(), target[it.key()], path + "/" + key);
10644  result.insert(result.end(), temp_diff.begin(), temp_diff.end());
10645  }
10646  else
10647  {
10648  // found a key that is not in o -> remove it
10649  result.push_back(object(
10650  {
10651  {"op", "remove"},
10652  {"path", path + "/" + key}
10653  }));
10654  }
10655  }
10656 
10657  // second pass: traverse other object's elements
10658  for (auto it = target.begin(); it != target.end(); ++it)
10659  {
10660  if (source.find(it.key()) == source.end())
10661  {
10662  // found a key that is not in this -> add it
10663  const auto key = json_pointer::escape(it.key());
10664  result.push_back(
10665  {
10666  {"op", "add"},
10667  {"path", path + "/" + key},
10668  {"value", it.value()}
10669  });
10670  }
10671  }
10672 
10673  break;
10674  }
10675 
10676  default:
10677  {
10678  // both primitive type: replace value
10679  result.push_back(
10680  {
10681  {"op", "replace"},
10682  {"path", path},
10683  {"value", target}
10684  });
10685  break;
10686  }
10687  }
10688  }
10689 
10690  return result;
10691  }
10692 
10694 };
10695 
10696 
10698 // presets //
10700 
10709 using json = basic_json<>;
10710 }
10711 
10712 
10714 // nonmember support //
10716 
10717 // specialization of std::swap, and std::hash
10718 namespace std
10719 {
10725 template<>
10726 inline void swap(nlohmann::json& j1,
10727  nlohmann::json& j2) noexcept(
10728  is_nothrow_move_constructible<nlohmann::json>::value and
10729  is_nothrow_move_assignable<nlohmann::json>::value
10730  )
10731 {
10732  j1.swap(j2);
10733 }
10734 
10736 template<>
10737 struct hash<nlohmann::json>
10738 {
10744  std::size_t operator()(const nlohmann::json& j) const
10745  {
10746  // a naive hashing via the string representation
10747  const auto& h = hash<nlohmann::json::string_t>();
10748  return h(j.dump());
10749  }
10750 };
10751 }
10752 
10766 inline nlohmann::json operator "" _json(const char* s, std::size_t n)
10767 {
10768  return nlohmann::json::parse(s, s + n);
10769 }
10770 
10784 inline nlohmann::json::json_pointer operator "" _json_pointer(const char* s, std::size_t n)
10785 {
10786  return nlohmann::json::json_pointer(std::string(s, n));
10787 }
10788 
10789 // restore GCC/clang diagnostic settings
10790 #if defined(__clang__) || defined(__GNUC__) || defined(__GNUG__)
10791  #pragma GCC diagnostic pop
10792 #endif
10793 
10794 #endif
const_iterator(pointer object) noexcept
constructor for a given JSON instance
Definition: json.hpp:6741
size_type max_size() const noexcept
returns the maximum possible number of elements
Definition: json.hpp:4760
friend bool operator<=(const_reference lhs, const_reference rhs) noexcept
comparison: less than or equal
Definition: json.hpp:5737
constexpr value_t type() const noexcept
return the type of the JSON value (explicit)
Definition: json.hpp:2243
constexpr bool is_array() const noexcept
return whether value is an array
Definition: json.hpp:2503
const_reference at(const typename object_t::key_type &key) const
access specified object element with bounds checking
Definition: json.hpp:3288
basic_json(const value_t value_type)
create an empty value with a given type
Definition: json.hpp:1067
basic_json(const array_t &val)
create an array (explicit)
Definition: json.hpp:1179
reference value() const
return the value of an iterator
Definition: json.hpp:7563
const_iterator end() const noexcept
returns a const iterator to one past the last element
Definition: json.hpp:4382
constexpr bool is_primitive() const noexcept
return whether type is primitive
Definition: json.hpp:2273
constexpr bool is_null() const noexcept
return whether value is null
Definition: json.hpp:2322
ValueType get() const
get a value (explicit)
Definition: json.hpp:2901
const_reverse_iterator rend() const noexcept
returns a const reverse iterator to one before the first
Definition: json.hpp:4487
constexpr bool is_structured() const noexcept
return whether type is structured
Definition: json.hpp:2300
json_reverse_iterator & operator--()
pre-decrement (–it)
Definition: json.hpp:7514
void clear() noexcept
clears the contents
Definition: json.hpp:4819
const_reference operator[](size_type idx) const
access specified array element
Definition: json.hpp:3382
static basic_json parse(const CharPT s, const parser_callback_t cb=nullptr)
deserialize from string literal
Definition: json.hpp:5935
json_reverse_iterator operator--(int)
post-decrement (it–)
Definition: json.hpp:7508
reference operator[](T *(&key)[n])
access specified object element
Definition: json.hpp:3515
friend std::istream & operator>>(std::istream &i, basic_json &j)
deserialize from stream
Definition: json.hpp:6137
iterator & operator+=(difference_type i)
add to iterator
Definition: json.hpp:7410
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:1760
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:4261
static basic_json parse(IteratorType first, IteratorType last, const parser_callback_t cb=nullptr)
deserialize from an iterator range with contiguous storage
Definition: json.hpp:6025
constexpr bool is_number_unsigned() const noexcept
return whether value is an unsigned integer number
Definition: json.hpp:2431
const_iterator operator-(difference_type i)
subtract from iterator
Definition: json.hpp:7216
BooleanType boolean_t
a type for a boolean
Definition: json.hpp:514
reference operator+=(const typename object_t::value_type &val)
add an object to an object
Definition: json.hpp:5002
basic_json(const typename string_t::value_type *val)
create a string (explicit)
Definition: json.hpp:1275
object_t::key_type key() const
return the key of an object iterator
Definition: json.hpp:7293
iterator find(typename object_t::key_type key)
find an element in a JSON object
Definition: json.hpp:4215
friend bool operator!=(const_reference lhs, const_reference rhs) noexcept
comparison: not equal
Definition: json.hpp:5581
basic_json(const string_t &val)
create a string (explicit)
Definition: json.hpp:1249
reference operator*() const
return a reference to the value pointed to by the iterator
Definition: json.hpp:7368
void push_back(const basic_json &val)
add an object to an array
Definition: json.hpp:4928
void erase(const size_type idx)
remove element from a JSON array given an index
Definition: json.hpp:4169
ArrayType< basic_json, AllocatorType< basic_json >> array_t
a type for an array
Definition: json.hpp:441
reference front()
access the first element
Definition: json.hpp:3828
void swap(object_t &other)
exchanges the values
Definition: json.hpp:5345
const_iterator & operator+=(difference_type i)
add to iterator
Definition: json.hpp:7165
a class to store JSON values
Definition: json.hpp:235
basic_json(const int val) noexcept
create an integer number from an enum type (explicit)
Definition: json.hpp:1389
static basic_json parse(T(&array)[N], const parser_callback_t cb=nullptr)
deserialize from an array
Definition: json.hpp:5897
constexpr bool is_object() const noexcept
return whether value is an object
Definition: json.hpp:2481
friend bool operator==(std::nullptr_t, const_reference v) noexcept
comparison: equal
Definition: json.hpp:5560
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:3725
NumberIntegerType number_integer_t
a type for a number (integer)
Definition: json.hpp:586
iterator insert(const_iterator pos, size_type cnt, const basic_json &val)
inserts elements
Definition: json.hpp:5133
const_iterator operator+(difference_type i)
add to iterator
Definition: json.hpp:7205
a mutable random access iterator for the basic_json class
Definition: json.hpp:7335
const_iterator operator++(int)
post-increment (it++)
Definition: json.hpp:6977
constexpr bool is_number_integer() const noexcept
return whether value is an integer number
Definition: json.hpp:2403
ObjectType< StringType, basic_json, std::less< StringType >, AllocatorType< std::pair< const StringType, basic_json >>> object_t
a type for an object
Definition: json.hpp:395
STL namespace.
NumberUnsignedType number_unsigned_t
a type for a number (unsigned)
Definition: json.hpp:657
json_reverse_iterator operator-(difference_type i) const
subtract from iterator
Definition: json.hpp:7536
typename std::allocator_traits< allocator_type >::const_pointer const_pointer
the type of an element const pointer
Definition: json.hpp:276
static basic_json parse(std::istream &&i, const parser_callback_t cb=nullptr)
deserialize from stream
Definition: json.hpp:5974
pointer operator->() const
dereference the iterator
Definition: json.hpp:7374
bool operator>=(const const_iterator &other) const
comparison: greater than or equal
Definition: json.hpp:7156
basic_json(const number_integer_t val) noexcept
create an integer number (explicit)
Definition: json.hpp:1358
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:1720
static iteration_proxy< const_iterator > iterator_wrapper(const_reference cont)
wrapper to access iterator member functions in range-based for
Definition: json.hpp:4574
const_reference front() const
access the first element
Definition: json.hpp:3836
typename basic_json::value_type value_type
the type of the values when the iterator is dereferenced
Definition: json.hpp:6722
json_reverse_iterator(const typename base_iterator::iterator_type &it) noexcept
create reverse iterator from iterator
Definition: json.hpp:7485
PointerType get_ptr() noexcept
get a pointer value (implicit)
Definition: json.hpp:2981
const_iterator cbegin() const noexcept
returns a const iterator to the first element
Definition: json.hpp:4341
reference back()
access the last element
Definition: json.hpp:3871
const value_type & const_reference
the type of an element const reference
Definition: json.hpp:263
typename basic_json::const_pointer pointer
defines a pointer to the type iterated over (value_type)
Definition: json.hpp:6726
IteratorType erase(IteratorType first, IteratorType last)
remove elements given an iterator range
Definition: json.hpp:4044
void push_back(const typename object_t::value_type &val)
add an object to an object
Definition: json.hpp:4978
bool empty() const noexcept
checks whether the container is empty
Definition: json.hpp:4626
void push_back(std::initializer_list< basic_json > init)
add an object to an object
Definition: json.hpp:5033
json_pointer(const std::string &s="")
create JSON pointer
Definition: json.hpp:9480
iterator insert(const_iterator pos, const_iterator first, const_iterator last)
inserts elements
Definition: json.hpp:5185
constexpr const PointerType get_ptr() const noexcept
get a pointer value (implicit)
Definition: json.hpp:3009
constexpr bool is_number_float() const noexcept
return whether value is a floating-point number
Definition: json.hpp:2459
basic_json(InputIT first, InputIT last)
construct a JSON container given an iterator range
Definition: json.hpp:1831
basic_json(std::nullptr_t=nullptr) noexcept
create a null object
Definition: json.hpp:1091
IteratorType erase(IteratorType pos)
remove element given an iterator
Definition: json.hpp:3937
static allocator_type get_allocator()
returns the allocator associated with the container
Definition: json.hpp:293
json_reverse_iterator operator+(difference_type i) const
add to iterator
Definition: json.hpp:7528
string_t dump(const int indent=-1) const
serialization
Definition: json.hpp:2200
reference & operator=(basic_json other) noexcept(std::is_nothrow_move_constructible< value_t >::value and std::is_nothrow_move_assignable< value_t >::value and std::is_nothrow_move_constructible< json_value >::value and std::is_nothrow_move_assignable< json_value >::value)
copy assignment
Definition: json.hpp:2095
void swap(reference other) noexcept(std::is_nothrow_move_constructible< value_t >::value and std::is_nothrow_move_assignable< value_t >::value and std::is_nothrow_move_constructible< json_value >::value and std::is_nothrow_move_assignable< json_value >::value)
exchanges the values
Definition: json.hpp:5280
std::size_t size_type
a type to represent container sizes
Definition: json.hpp:268
JSON_DEPRECATED basic_json(std::istream &i, const parser_callback_t cb=nullptr)
construct a JSON value given an input stream
Definition: json.hpp:1949
const_iterator(const iterator &other) noexcept
copy constructor given a non-const iterator
Definition: json.hpp:6773
basic_json(const CompatibleArrayType &val)
create an array (implicit)
Definition: json.hpp:1219
basic_json(size_type cnt, const basic_json &val)
construct an array with count copies of given value
Definition: json.hpp:1784
std::reverse_iterator< Base > base_iterator
shortcut to the reverse iterator adaptor
Definition: json.hpp:7480
object_t::key_type key() const
return the key of an object iterator
Definition: json.hpp:7556
iterator insert(const_iterator pos, std::initializer_list< basic_json > ilist)
inserts elements
Definition: json.hpp:5243
typename std::allocator_traits< allocator_type >::pointer pointer
the type of an element pointer
Definition: json.hpp:274
iterator insert(const_iterator pos, const basic_json &val)
inserts element
Definition: json.hpp:5078
friend bool operator>=(const_reference lhs, const_reference rhs) noexcept
comparison: greater than or equal
Definition: json.hpp:5781
friend bool operator<(const_reference lhs, const_reference rhs) noexcept
comparison: less than
Definition: json.hpp:5642
iterator & operator++()
pre-increment (++it)
Definition: json.hpp:7388
iterator operator++(int)
post-increment (it++)
Definition: json.hpp:7380
const_reverse_iterator rbegin() const noexcept
returns a const reverse iterator to the last element
Definition: json.hpp:4450
basic_json(basic_json &&other) noexcept
move constructor
Definition: json.hpp:2058
const_iterator operator--(int)
post-decrement (it–)
Definition: json.hpp:7020
reference at(const typename object_t::key_type &key)
access specified object element with bounds checking
Definition: json.hpp:3241
object (unordered set of name/value pairs)
~basic_json()
destructor
Definition: json.hpp:2128
iterator operator--(int)
post-decrement (it–)
Definition: json.hpp:7395
iterator operator-(difference_type i)
subtract from iterator
Definition: json.hpp:7432
const_iterator & operator--()
pre-decrement (–it)
Definition: json.hpp:7031
basic_json value_type
the type of elements in a basic_json container
Definition: json.hpp:258
std::function< bool(int depth, parse_event_t event, basic_json &parsed)> parser_callback_t
per-element parser callback type
Definition: json.hpp:1016
AllocatorType< basic_json > allocator_type
the allocator type
Definition: json.hpp:271
StringType string_t
a type for a string
Definition: json.hpp:488
reference operator+=(const basic_json &val)
add an object to an array
Definition: json.hpp:4952
const_iterator & operator=(const_iterator other) noexcept(std::is_nothrow_move_constructible< pointer >::value and std::is_nothrow_move_assignable< pointer >::value and std::is_nothrow_move_constructible< internal_iterator >::value and std::is_nothrow_move_assignable< internal_iterator >::value)
copy assignment
Definition: json.hpp:6815
static basic_json parse(const ContiguousContainer &c, const parser_callback_t cb=nullptr)
deserialize from a container with contiguous storage
Definition: json.hpp:6097
reference operator+=(std::initializer_list< basic_json > init)
add an object to an object
Definition: json.hpp:5050
value_type & reference
the type of an element reference
Definition: json.hpp:261
pointer operator->() const
dereference the iterator
Definition: json.hpp:6941
ReferenceType get_ref() const
get a reference value (implicit)
Definition: json.hpp:3071
reference value() const
return the value of an iterator
Definition: json.hpp:7452
friend std::ostream & operator>>(const basic_json &j, std::ostream &o)
serialize to stream
Definition: json.hpp:5854
size_type size() const noexcept
returns the number of elements
Definition: json.hpp:4694
iterator(const iterator &other) noexcept
copy constructor
Definition: json.hpp:7351
namespace for Niels Lohmann
Definition: json.hpp:92
typename basic_json::difference_type difference_type
a type to represent differences between iterators
Definition: json.hpp:6724
constexpr bool is_string() const noexcept
return whether value is a string
Definition: json.hpp:2525
void swap(string_t &other)
exchanges the values
Definition: json.hpp:5378
reference operator[](difference_type n) const
access to successor
Definition: json.hpp:7550
basic_json(const CompatibleNumberIntegerType val) noexcept
create an integer number (implicit)
Definition: json.hpp:1426
const_reference at(size_type idx) const
access specified array element with bounds checking
Definition: json.hpp:3194
reference value() const
return the value of an iterator
Definition: json.hpp:7311
ValueType value(const typename object_t::key_type &key, ValueType default_value) const
access specified object element with default value
Definition: json.hpp:3699
const_reference operator[](T *key) const
read-only access specified object element
Definition: json.hpp:3635
NumberFloatType number_float_t
a type for a number (floating-point)
Definition: json.hpp:725
value_t
the JSON type enumeration
Definition: json.hpp:756
reverse_iterator rbegin() noexcept
returns an iterator to the reverse-beginning
Definition: json.hpp:4442
std::ptrdiff_t difference_type
a type to represent differences between iterators
Definition: json.hpp:266
difference_type operator-(const const_iterator &other) const
return difference
Definition: json.hpp:7227
void swap(array_t &other)
exchanges the values
Definition: json.hpp:5312
reference operator[](difference_type n) const
access to successor
Definition: json.hpp:7446
typename Base::reference reference
the reference type for the pointed-to element
Definition: json.hpp:7482
void push_back(basic_json &&val)
add an object to an array
Definition: json.hpp:4892
array (ordered collection of values)
json_reverse_iterator & operator++()
pre-increment (++it)
Definition: json.hpp:7501
difference_type operator-(const iterator &other) const
return difference
Definition: json.hpp:7440
friend bool operator==(const_reference lhs, const_reference rhs) noexcept
comparison: equal
Definition: json.hpp:5458
iterator & operator=(iterator other) noexcept(std::is_nothrow_move_constructible< pointer >::value and std::is_nothrow_move_assignable< pointer >::value and std::is_nothrow_move_constructible< internal_iterator >::value and std::is_nothrow_move_assignable< internal_iterator >::value)
copy assignment
Definition: json.hpp:7356
static basic_json parse(std::istream &i, const parser_callback_t cb=nullptr)
deserialize from stream
Definition: json.hpp:5965
ValueType value(const json_pointer &ptr, ValueType default_value) const
access specified object element via JSON Pointer with default value
Definition: json.hpp:3773
const_reference operator[](const typename object_t::key_type &key) const
read-only access specified object element
Definition: json.hpp:3473
bool operator!=(const const_iterator &other) const
comparison: not equal
Definition: json.hpp:7096
basic_json(const CompatibleNumberUnsignedType val) noexcept
create an unsigned number (implicit)
Definition: json.hpp:1484
constexpr bool is_boolean() const noexcept
return whether value is a boolean
Definition: json.hpp:2344
bool operator==(const const_iterator &other) const
comparison: equal
Definition: json.hpp:7063
bool operator<=(const const_iterator &other) const
comparison: less than or equal
Definition: json.hpp:7138
const_reverse_iterator crbegin() const noexcept
returns a const reverse iterator to the last element
Definition: json.hpp:4516
string_t value(const json_pointer &ptr, const char *default_value) const
overload for a default value of type const char*
Definition: json.hpp:3798
friend class basic_json
allow basic_json to access private members
Definition: json.hpp:6718
reference operator[](difference_type n) const
access to successor
Definition: json.hpp:7254
friend bool operator<(const value_t lhs, const value_t rhs) noexcept
comparison operator for JSON types
Definition: json.hpp:5411
basic_json(const number_float_t val) noexcept
create a floating-point number (explicit)
Definition: json.hpp:1515
friend bool operator!=(const_reference v, std::nullptr_t) noexcept
comparison: not equal
Definition: json.hpp:5604
iterator operator+(difference_type i)
add to iterator
Definition: json.hpp:7424
basic_json(const CompatibleNumberFloatType val) noexcept
create an floating-point number (implicit)
Definition: json.hpp:1562
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:1637
iterator(pointer object) noexcept
constructor for a given JSON instance
Definition: json.hpp:7346
friend bool operator!=(std::nullptr_t, const_reference v) noexcept
comparison: not equal
Definition: json.hpp:5613
difference_type operator-(const json_reverse_iterator &other) const
return difference
Definition: json.hpp:7544
const_reference back() const
access the last element
Definition: json.hpp:3881
const_iterator & operator++()
pre-increment (++it)
Definition: json.hpp:6988
constexpr bool is_number() const noexcept
return whether value is a number
Definition: json.hpp:2374
const_iterator find(typename object_t::key_type key) const
find an element in a JSON object
Definition: json.hpp:4231
const_iterator begin() const noexcept
returns a const iterator to the first element
Definition: json.hpp:4311
bool operator>(const const_iterator &other) const
comparison: greater than
Definition: json.hpp:7147
std::bidirectional_iterator_tag iterator_category
the category of the iterator
Definition: json.hpp:6730
basic_json(boolean_t val) noexcept
create a boolean (explicit)
Definition: json.hpp:1326
iterator end() noexcept
returns an iterator to one past the last element
Definition: json.hpp:4372
reverse_iterator rend() noexcept
returns an iterator to the reverse-end
Definition: json.hpp:4479
iterator begin() noexcept
returns an iterator to the first element
Definition: json.hpp:4301
const_iterator cend() const noexcept
returns a const iterator to one past the last element
Definition: json.hpp:4412
basic_json(const CompatibleObjectType &val)
create an object (implicit)
Definition: json.hpp:1151
friend bool operator>(const_reference lhs, const_reference rhs) noexcept
comparison: greater than
Definition: json.hpp:5759
size_type erase(const typename object_t::key_type &key)
remove element from a JSON object given a key
Definition: json.hpp:4132
reference operator[](const typename object_t::key_type &key)
access specified object element
Definition: json.hpp:3422
reference operator+=(basic_json &&val)
add an object to an array
Definition: json.hpp:4918
a const random access iterator for the basic_json class
Definition: json.hpp:6715
a template for a reverse iterator class
Definition: json.hpp:245
typename basic_json::const_reference reference
defines a reference to the type iterated over (value_type)
Definition: json.hpp:6728
json_reverse_iterator operator++(int)
post-increment (it++)
Definition: json.hpp:7495
friend bool operator==(const_reference v, std::nullptr_t) noexcept
comparison: equal
Definition: json.hpp:5551
reference operator[](size_type idx)
access specified array element
Definition: json.hpp:3334
json_reverse_iterator & operator+=(difference_type i)
add to iterator
Definition: json.hpp:7521
reference at(size_type idx)
access specified array element with bounds checking
Definition: json.hpp:3151
static iteration_proxy< iterator > iterator_wrapper(reference cont)
wrapper to access iterator member functions in range-based for
Definition: json.hpp:4566
constexpr bool is_discarded() const noexcept
return whether value is discarded
Definition: json.hpp:2552
const_reverse_iterator crend() const noexcept
returns a const reverse iterator to one before the first
Definition: json.hpp:4545
iterator & operator-=(difference_type i)
subtract from iterator
Definition: json.hpp:7417
basic_json(const object_t &val)
create an object (explicit)
Definition: json.hpp:1116
basic_json(const number_unsigned_t val) noexcept
create an unsigned integer number (explicit)
Definition: json.hpp:1453
friend std::istream & operator<<(basic_json &j, std::istream &i)
deserialize from stream
Definition: json.hpp:6127
json_reverse_iterator(const base_iterator &it) noexcept
create reverse iterator from base class
Definition: json.hpp:7490
const_reference operator[](T *(&key)[n]) const
read-only access specified object element
Definition: json.hpp:3550
friend std::ostream & operator<<(std::ostream &o, const basic_json &j)
serialize to stream
Definition: json.hpp:5822
const_iterator(const const_iterator &other) noexcept
copy constructor
Definition: json.hpp:6806
iterator & operator--()
pre-decrement (–it)
Definition: json.hpp:7403
reference operator*() const
return a reference to the value pointed to by the iterator
Definition: json.hpp:6900
iterator insert(const_iterator pos, basic_json &&val)
inserts element
Definition: json.hpp:5104
ReferenceType get_ref()
get a reference value (implicit)
Definition: json.hpp:3058
const_iterator & operator-=(difference_type i)
subtract from iterator
Definition: json.hpp:7196
basic_json(const CompatibleStringType &val)
create a string (implicit)
Definition: json.hpp:1306
basic_json(const basic_json &other)
copy constructor
Definition: json.hpp:1981
bool operator<(const const_iterator &other) const
comparison: smaller
Definition: json.hpp:7105
reference operator[](T *key)
access specified object element
Definition: json.hpp:3583
parse_event_t
JSON callback events.
Definition: json.hpp:946