JSON for Modern C++  2.0.3
json.hpp
1 /*
2  __ _____ _____ _____
3  __| | __| | | | JSON for Modern C++
4 | | |__ | | | | | | version 2.0.3
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 <ciso646>
36 #include <cmath>
37 #include <cstddef>
38 #include <cstdint>
39 #include <cstdlib>
40 #include <cstring>
41 #include <functional>
42 #include <initializer_list>
43 #include <iomanip>
44 #include <iostream>
45 #include <iterator>
46 #include <limits>
47 #include <locale>
48 #include <map>
49 #include <memory>
50 #include <numeric>
51 #include <sstream>
52 #include <stdexcept>
53 #include <string>
54 #include <type_traits>
55 #include <utility>
56 #include <vector>
57 
58 // exclude unsupported compilers
59 #if defined(__clang__)
60  #define CLANG_VERSION (__clang_major__ * 10000 + __clang_minor__ * 100 + __clang_patchlevel__)
61  #if CLANG_VERSION < 30400
62  #error "unsupported Clang version - see https://github.com/nlohmann/json#supported-compilers"
63  #endif
64 #elif defined(__GNUC__)
65  #define GCC_VERSION (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__)
66  #if GCC_VERSION < 40900
67  #error "unsupported GCC version - see https://github.com/nlohmann/json#supported-compilers"
68  #endif
69 #endif
70 
71 // disable float-equal warnings on GCC/clang
72 #if defined(__clang__) || defined(__GNUC__) || defined(__GNUG__)
73  #pragma GCC diagnostic push
74  #pragma GCC diagnostic ignored "-Wfloat-equal"
75 #endif
76 
77 // allow for portable deprecation warnings
78 #if defined(__clang__) || defined(__GNUC__) || defined(__GNUG__)
79  #define JSON_DEPRECATED __attribute__((deprecated))
80 #elif defined(_MSC_VER)
81  #define JSON_DEPRECATED __declspec(deprecated)
82 #else
83  #define JSON_DEPRECATED
84 #endif
85 
91 namespace nlohmann
92 {
93 
94 
99 namespace
100 {
111 template<typename T>
112 struct has_mapped_type
113 {
114  private:
115  template<typename C> static char test(typename C::mapped_type*);
116  template<typename C> static char (&test(...))[2];
117  public:
118  static constexpr bool value = sizeof(test<T>(0)) == 1;
119 };
120 
133 struct DecimalSeparator : std::numpunct<char>
134 {
135  char do_decimal_point() const
136  {
137  return '.';
138  }
139 };
140 
141 }
142 
221 template <
222  template<typename U, typename V, typename... Args> class ObjectType = std::map,
223  template<typename U, typename... Args> class ArrayType = std::vector,
224  class StringType = std::string,
225  class BooleanType = bool,
226  class NumberIntegerType = std::int64_t,
227  class NumberUnsignedType = std::uint64_t,
228  class NumberFloatType = double,
229  template<typename U> class AllocatorType = std::allocator
230  >
232 {
233  private:
235  using basic_json_t = basic_json<ObjectType, ArrayType, StringType,
236  BooleanType, NumberIntegerType, NumberUnsignedType, NumberFloatType,
237  AllocatorType>;
238 
239  public:
240  // forward declarations
241  template<typename Base> class json_reverse_iterator;
242  class json_pointer;
243 
245  // container types //
247 
252 
255 
259  using const_reference = const value_type&;
260 
262  using difference_type = std::ptrdiff_t;
264  using size_type = std::size_t;
265 
267  using allocator_type = AllocatorType<basic_json>;
268 
270  using pointer = typename std::allocator_traits<allocator_type>::pointer;
272  using const_pointer = typename std::allocator_traits<allocator_type>::const_pointer;
273 
275  class iterator;
277  class const_iterator;
282 
284 
285 
290  {
291  return allocator_type();
292  }
293 
294 
296  // JSON value data types //
298 
303 
387  using object_t = ObjectType<StringType,
388  basic_json,
389  std::less<StringType>,
390  AllocatorType<std::pair<const StringType,
391  basic_json>>>;
392 
437  using array_t = ArrayType<basic_json, AllocatorType<basic_json>>;
438 
484  using string_t = StringType;
485 
510  using boolean_t = BooleanType;
511 
582  using number_integer_t = NumberIntegerType;
583 
653  using number_unsigned_t = NumberUnsignedType;
654 
721  using number_float_t = NumberFloatType;
722 
724 
725 
727  // JSON type enumeration //
729 
752  enum class value_t : uint8_t
753  {
754  null,
755  object,
756  array,
757  string,
758  boolean,
759  number_integer,
760  number_unsigned,
761  number_float,
762  discarded
763  };
764 
765 
766  private:
767 
769  template<typename T, typename... Args>
770  static T* create(Args&& ... args)
771  {
772  AllocatorType<T> alloc;
773  auto deleter = [&](T * object)
774  {
775  alloc.deallocate(object, 1);
776  };
777  std::unique_ptr<T, decltype(deleter)> object(alloc.allocate(1), deleter);
778  alloc.construct(object.get(), std::forward<Args>(args)...);
779  assert(object.get() != nullptr);
780  return object.release();
781  }
782 
784  // JSON value storage //
786 
811  union json_value
812  {
814  object_t* object;
816  array_t* array;
818  string_t* string;
820  boolean_t boolean;
822  number_integer_t number_integer;
824  number_unsigned_t number_unsigned;
826  number_float_t number_float;
827 
829  json_value() = default;
831  json_value(boolean_t v) noexcept : boolean(v) {}
833  json_value(number_integer_t v) noexcept : number_integer(v) {}
835  json_value(number_unsigned_t v) noexcept : number_unsigned(v) {}
837  json_value(number_float_t v) noexcept : number_float(v) {}
839  json_value(value_t t)
840  {
841  switch (t)
842  {
843  case value_t::object:
844  {
845  object = create<object_t>();
846  break;
847  }
848 
849  case value_t::array:
850  {
851  array = create<array_t>();
852  break;
853  }
854 
855  case value_t::string:
856  {
857  string = create<string_t>("");
858  break;
859  }
860 
861  case value_t::boolean:
862  {
863  boolean = boolean_t(false);
864  break;
865  }
866 
867  case value_t::number_integer:
868  {
869  number_integer = number_integer_t(0);
870  break;
871  }
872 
873  case value_t::number_unsigned:
874  {
875  number_unsigned = number_unsigned_t(0);
876  break;
877  }
878 
879  case value_t::number_float:
880  {
881  number_float = number_float_t(0.0);
882  break;
883  }
884 
885  default:
886  {
887  break;
888  }
889  }
890  }
891 
893  json_value(const string_t& value)
894  {
895  string = create<string_t>(value);
896  }
897 
899  json_value(const object_t& value)
900  {
901  object = create<object_t>(value);
902  }
903 
905  json_value(const array_t& value)
906  {
907  array = create<array_t>(value);
908  }
909  };
910 
920  void assert_invariant() const
921  {
922  assert(m_type != value_t::object or m_value.object != nullptr);
923  assert(m_type != value_t::array or m_value.array != nullptr);
924  assert(m_type != value_t::string or m_value.string != nullptr);
925  }
926 
927  public:
929  // JSON parser callback //
931 
942  enum class parse_event_t : uint8_t
943  {
945  object_start,
947  object_end,
949  array_start,
951  array_end,
953  key,
955  value
956  };
957 
1010  using parser_callback_t = std::function<bool(int depth,
1011  parse_event_t event,
1012  basic_json& parsed)>;
1013 
1014 
1016  // constructors //
1018 
1023 
1064  : m_type(value_type), m_value(value_type)
1065  {
1066  assert_invariant();
1067  }
1068 
1087  basic_json(std::nullptr_t = nullptr) noexcept
1088  : basic_json(value_t::null)
1089  {
1090  assert_invariant();
1091  }
1092 
1112  basic_json(const object_t& val)
1113  : m_type(value_t::object), m_value(val)
1114  {
1115  assert_invariant();
1116  }
1117 
1144  template<class CompatibleObjectType, typename std::enable_if<
1145  std::is_constructible<typename object_t::key_type, typename CompatibleObjectType::key_type>::value and
1146  std::is_constructible<basic_json, typename CompatibleObjectType::mapped_type>::value, int>::type = 0>
1147  basic_json(const CompatibleObjectType& val)
1148  : m_type(value_t::object)
1149  {
1150  using std::begin;
1151  using std::end;
1152  m_value.object = create<object_t>(begin(val), end(val));
1153  assert_invariant();
1154  }
1155 
1175  basic_json(const array_t& val)
1176  : m_type(value_t::array), m_value(val)
1177  {
1178  assert_invariant();
1179  }
1180 
1207  template<class CompatibleArrayType, typename std::enable_if<
1208  not std::is_same<CompatibleArrayType, typename basic_json_t::iterator>::value and
1209  not std::is_same<CompatibleArrayType, typename basic_json_t::const_iterator>::value and
1210  not std::is_same<CompatibleArrayType, typename basic_json_t::reverse_iterator>::value and
1211  not std::is_same<CompatibleArrayType, typename basic_json_t::const_reverse_iterator>::value and
1212  not std::is_same<CompatibleArrayType, typename array_t::iterator>::value and
1213  not std::is_same<CompatibleArrayType, typename array_t::const_iterator>::value and
1214  std::is_constructible<basic_json, typename CompatibleArrayType::value_type>::value, int>::type = 0>
1215  basic_json(const CompatibleArrayType& val)
1216  : m_type(value_t::array)
1217  {
1218  using std::begin;
1219  using std::end;
1220  m_value.array = create<array_t>(begin(val), end(val));
1221  assert_invariant();
1222  }
1223 
1245  basic_json(const string_t& val)
1246  : m_type(value_t::string), m_value(val)
1247  {
1248  assert_invariant();
1249  }
1250 
1271  basic_json(const typename string_t::value_type* val)
1272  : basic_json(string_t(val))
1273  {
1274  assert_invariant();
1275  }
1276 
1300  template<class CompatibleStringType, typename std::enable_if<
1301  std::is_constructible<string_t, CompatibleStringType>::value, int>::type = 0>
1302  basic_json(const CompatibleStringType& val)
1303  : basic_json(string_t(val))
1304  {
1305  assert_invariant();
1306  }
1307 
1322  basic_json(boolean_t val) noexcept
1323  : m_type(value_t::boolean), m_value(val)
1324  {
1325  assert_invariant();
1326  }
1327 
1351  template<typename T, typename std::enable_if<
1352  not (std::is_same<T, int>::value) and
1353  std::is_same<T, number_integer_t>::value, int>::type = 0>
1354  basic_json(const number_integer_t val) noexcept
1355  : m_type(value_t::number_integer), m_value(val)
1356  {
1357  assert_invariant();
1358  }
1359 
1385  basic_json(const int val) noexcept
1386  : m_type(value_t::number_integer),
1387  m_value(static_cast<number_integer_t>(val))
1388  {
1389  assert_invariant();
1390  }
1391 
1417  template<typename CompatibleNumberIntegerType, typename std::enable_if<
1418  std::is_constructible<number_integer_t, CompatibleNumberIntegerType>::value and
1419  std::numeric_limits<CompatibleNumberIntegerType>::is_integer and
1420  std::numeric_limits<CompatibleNumberIntegerType>::is_signed,
1421  CompatibleNumberIntegerType>::type = 0>
1422  basic_json(const CompatibleNumberIntegerType val) noexcept
1423  : m_type(value_t::number_integer),
1424  m_value(static_cast<number_integer_t>(val))
1425  {
1426  assert_invariant();
1427  }
1428 
1446  template<typename T, typename std::enable_if<
1447  not (std::is_same<T, int>::value) and
1448  std::is_same<T, number_unsigned_t>::value, int>::type = 0>
1449  basic_json(const number_unsigned_t val) noexcept
1450  : m_type(value_t::number_unsigned), m_value(val)
1451  {
1452  assert_invariant();
1453  }
1454 
1475  template<typename CompatibleNumberUnsignedType, typename std::enable_if <
1476  std::is_constructible<number_unsigned_t, CompatibleNumberUnsignedType>::value and
1477  std::numeric_limits<CompatibleNumberUnsignedType>::is_integer and
1478  not std::numeric_limits<CompatibleNumberUnsignedType>::is_signed,
1479  CompatibleNumberUnsignedType>::type = 0>
1480  basic_json(const CompatibleNumberUnsignedType val) noexcept
1481  : m_type(value_t::number_unsigned),
1482  m_value(static_cast<number_unsigned_t>(val))
1483  {
1484  assert_invariant();
1485  }
1486 
1511  basic_json(const number_float_t val) noexcept
1512  : m_type(value_t::number_float), m_value(val)
1513  {
1514  // replace infinity and NAN by null
1515  if (not std::isfinite(val))
1516  {
1517  m_type = value_t::null;
1518  m_value = json_value();
1519  }
1520 
1521  assert_invariant();
1522  }
1523 
1555  template<typename CompatibleNumberFloatType, typename = typename std::enable_if<
1556  std::is_constructible<number_float_t, CompatibleNumberFloatType>::value and
1557  std::is_floating_point<CompatibleNumberFloatType>::value>::type>
1558  basic_json(const CompatibleNumberFloatType val) noexcept
1559  : basic_json(number_float_t(val))
1560  {
1561  assert_invariant();
1562  }
1563 
1633  basic_json(std::initializer_list<basic_json> init,
1634  bool type_deduction = true,
1635  value_t manual_type = value_t::array)
1636  {
1637  // check if each element is an array with two elements whose first
1638  // element is a string
1639  bool is_an_object = std::all_of(init.begin(), init.end(),
1640  [](const basic_json & element)
1641  {
1642  return element.is_array() and element.size() == 2 and element[0].is_string();
1643  });
1644 
1645  // adjust type if type deduction is not wanted
1646  if (not type_deduction)
1647  {
1648  // if array is wanted, do not create an object though possible
1649  if (manual_type == value_t::array)
1650  {
1651  is_an_object = false;
1652  }
1653 
1654  // if object is wanted but impossible, throw an exception
1655  if (manual_type == value_t::object and not is_an_object)
1656  {
1657  throw std::domain_error("cannot create object from initializer list");
1658  }
1659  }
1660 
1661  if (is_an_object)
1662  {
1663  // the initializer list is a list of pairs -> create object
1664  m_type = value_t::object;
1665  m_value = value_t::object;
1666 
1667  std::for_each(init.begin(), init.end(), [this](const basic_json & element)
1668  {
1669  m_value.object->emplace(*(element[0].m_value.string), element[1]);
1670  });
1671  }
1672  else
1673  {
1674  // the initializer list describes an array -> create array
1675  m_type = value_t::array;
1676  m_value.array = create<array_t>(init);
1677  }
1678 
1679  assert_invariant();
1680  }
1681 
1716  static basic_json array(std::initializer_list<basic_json> init =
1717  std::initializer_list<basic_json>())
1718  {
1719  return basic_json(init, false, value_t::array);
1720  }
1721 
1756  static basic_json object(std::initializer_list<basic_json> init =
1757  std::initializer_list<basic_json>())
1758  {
1759  return basic_json(init, false, value_t::object);
1760  }
1761 
1781  : m_type(value_t::array)
1782  {
1783  m_value.array = create<array_t>(cnt, val);
1784  assert_invariant();
1785  }
1786 
1824  template<class InputIT, typename std::enable_if<
1825  std::is_same<InputIT, typename basic_json_t::iterator>::value or
1826  std::is_same<InputIT, typename basic_json_t::const_iterator>::value, int>::type = 0>
1827  basic_json(InputIT first, InputIT last)
1828  {
1829  assert(first.m_object != nullptr);
1830  assert(last.m_object != nullptr);
1831 
1832  // make sure iterator fits the current value
1833  if (first.m_object != last.m_object)
1834  {
1835  throw std::domain_error("iterators are not compatible");
1836  }
1837 
1838  // copy type from first iterator
1839  m_type = first.m_object->m_type;
1840 
1841  // check if iterator range is complete for primitive values
1842  switch (m_type)
1843  {
1844  case value_t::boolean:
1845  case value_t::number_float:
1846  case value_t::number_integer:
1847  case value_t::number_unsigned:
1848  case value_t::string:
1849  {
1850  if (not first.m_it.primitive_iterator.is_begin() or not last.m_it.primitive_iterator.is_end())
1851  {
1852  throw std::out_of_range("iterators out of range");
1853  }
1854  break;
1855  }
1856 
1857  default:
1858  {
1859  break;
1860  }
1861  }
1862 
1863  switch (m_type)
1864  {
1865  case value_t::number_integer:
1866  {
1867  m_value.number_integer = first.m_object->m_value.number_integer;
1868  break;
1869  }
1870 
1871  case value_t::number_unsigned:
1872  {
1873  m_value.number_unsigned = first.m_object->m_value.number_unsigned;
1874  break;
1875  }
1876 
1877  case value_t::number_float:
1878  {
1879  m_value.number_float = first.m_object->m_value.number_float;
1880  break;
1881  }
1882 
1883  case value_t::boolean:
1884  {
1885  m_value.boolean = first.m_object->m_value.boolean;
1886  break;
1887  }
1888 
1889  case value_t::string:
1890  {
1891  m_value = *first.m_object->m_value.string;
1892  break;
1893  }
1894 
1895  case value_t::object:
1896  {
1897  m_value.object = create<object_t>(first.m_it.object_iterator, last.m_it.object_iterator);
1898  break;
1899  }
1900 
1901  case value_t::array:
1902  {
1903  m_value.array = create<array_t>(first.m_it.array_iterator, last.m_it.array_iterator);
1904  break;
1905  }
1906 
1907  default:
1908  {
1909  throw std::domain_error("cannot use construct with iterators from " + first.m_object->type_name());
1910  }
1911  }
1912 
1913  assert_invariant();
1914  }
1915 
1944  JSON_DEPRECATED
1945  explicit basic_json(std::istream& i, const parser_callback_t cb = nullptr)
1946  {
1947  *this = parser(i, cb).parse();
1948  assert_invariant();
1949  }
1950 
1952  // other constructors and destructor //
1954 
1977  basic_json(const basic_json& other)
1978  : m_type(other.m_type)
1979  {
1980  // check of passed value is valid
1981  other.assert_invariant();
1982 
1983  switch (m_type)
1984  {
1985  case value_t::object:
1986  {
1987  m_value = *other.m_value.object;
1988  break;
1989  }
1990 
1991  case value_t::array:
1992  {
1993  m_value = *other.m_value.array;
1994  break;
1995  }
1996 
1997  case value_t::string:
1998  {
1999  m_value = *other.m_value.string;
2000  break;
2001  }
2002 
2003  case value_t::boolean:
2004  {
2005  m_value = other.m_value.boolean;
2006  break;
2007  }
2008 
2009  case value_t::number_integer:
2010  {
2011  m_value = other.m_value.number_integer;
2012  break;
2013  }
2014 
2015  case value_t::number_unsigned:
2016  {
2017  m_value = other.m_value.number_unsigned;
2018  break;
2019  }
2020 
2021  case value_t::number_float:
2022  {
2023  m_value = other.m_value.number_float;
2024  break;
2025  }
2026 
2027  default:
2028  {
2029  break;
2030  }
2031  }
2032 
2033  assert_invariant();
2034  }
2035 
2054  basic_json(basic_json&& other) noexcept
2055  : m_type(std::move(other.m_type)),
2056  m_value(std::move(other.m_value))
2057  {
2058  // check that passed value is valid
2059  other.assert_invariant();
2060 
2061  // invalidate payload
2062  other.m_type = value_t::null;
2063  other.m_value = {};
2064 
2065  assert_invariant();
2066  }
2067 
2091  reference& operator=(basic_json other) noexcept (
2092  std::is_nothrow_move_constructible<value_t>::value and
2093  std::is_nothrow_move_assignable<value_t>::value and
2094  std::is_nothrow_move_constructible<json_value>::value and
2095  std::is_nothrow_move_assignable<json_value>::value
2096  )
2097  {
2098  // check that passed value is valid
2099  other.assert_invariant();
2100 
2101  using std::swap;
2102  swap(m_type, other.m_type);
2103  swap(m_value, other.m_value);
2104 
2105  assert_invariant();
2106  return *this;
2107  }
2108 
2125  {
2126  assert_invariant();
2127 
2128  switch (m_type)
2129  {
2130  case value_t::object:
2131  {
2132  AllocatorType<object_t> alloc;
2133  alloc.destroy(m_value.object);
2134  alloc.deallocate(m_value.object, 1);
2135  break;
2136  }
2137 
2138  case value_t::array:
2139  {
2140  AllocatorType<array_t> alloc;
2141  alloc.destroy(m_value.array);
2142  alloc.deallocate(m_value.array, 1);
2143  break;
2144  }
2145 
2146  case value_t::string:
2147  {
2148  AllocatorType<string_t> alloc;
2149  alloc.destroy(m_value.string);
2150  alloc.deallocate(m_value.string, 1);
2151  break;
2152  }
2153 
2154  default:
2155  {
2156  // all other types need no specific destructor
2157  break;
2158  }
2159  }
2160  }
2161 
2163 
2164  public:
2166  // object inspection //
2168 
2172 
2196  string_t dump(const int indent = -1) const
2197  {
2198  std::stringstream ss;
2199  // fix locale problems
2200  const static std::locale loc(std::locale(), new DecimalSeparator);
2201  ss.imbue(loc);
2202 
2203  // 6, 15 or 16 digits of precision allows round-trip IEEE 754
2204  // string->float->string, string->double->string or string->long
2205  // double->string; to be safe, we read this value from
2206  // std::numeric_limits<number_float_t>::digits10
2207  ss.precision(std::numeric_limits<double>::digits10);
2208 
2209  if (indent >= 0)
2210  {
2211  dump(ss, true, static_cast<unsigned int>(indent));
2212  }
2213  else
2214  {
2215  dump(ss, false, 0);
2216  }
2217 
2218  return ss.str();
2219  }
2220 
2239  constexpr value_t type() const noexcept
2240  {
2241  return m_type;
2242  }
2243 
2269  constexpr bool is_primitive() const noexcept
2270  {
2271  return is_null() or is_string() or is_boolean() or is_number();
2272  }
2273 
2296  constexpr bool is_structured() const noexcept
2297  {
2298  return is_array() or is_object();
2299  }
2300 
2318  constexpr bool is_null() const noexcept
2319  {
2320  return m_type == value_t::null;
2321  }
2322 
2340  constexpr bool is_boolean() const noexcept
2341  {
2342  return m_type == value_t::boolean;
2343  }
2344 
2370  constexpr bool is_number() const noexcept
2371  {
2372  return is_number_integer() or is_number_float();
2373  }
2374 
2399  constexpr bool is_number_integer() const noexcept
2400  {
2401  return m_type == value_t::number_integer or m_type == value_t::number_unsigned;
2402  }
2403 
2427  constexpr bool is_number_unsigned() const noexcept
2428  {
2429  return m_type == value_t::number_unsigned;
2430  }
2431 
2455  constexpr bool is_number_float() const noexcept
2456  {
2457  return m_type == value_t::number_float;
2458  }
2459 
2477  constexpr bool is_object() const noexcept
2478  {
2479  return m_type == value_t::object;
2480  }
2481 
2499  constexpr bool is_array() const noexcept
2500  {
2501  return m_type == value_t::array;
2502  }
2503 
2521  constexpr bool is_string() const noexcept
2522  {
2523  return m_type == value_t::string;
2524  }
2525 
2548  constexpr bool is_discarded() const noexcept
2549  {
2550  return m_type == value_t::discarded;
2551  }
2552 
2571  constexpr operator value_t() const noexcept
2572  {
2573  return m_type;
2574  }
2575 
2577 
2578  private:
2580  // value access //
2582 
2584  template<class T, typename std::enable_if<
2585  std::is_convertible<typename object_t::key_type, typename T::key_type>::value and
2586  std::is_convertible<basic_json_t, typename T::mapped_type>::value, int>::type = 0>
2587  T get_impl(T*) const
2588  {
2589  if (is_object())
2590  {
2591  return T(m_value.object->begin(), m_value.object->end());
2592  }
2593  else
2594  {
2595  throw std::domain_error("type must be object, but is " + type_name());
2596  }
2597  }
2598 
2600  object_t get_impl(object_t*) const
2601  {
2602  if (is_object())
2603  {
2604  return *(m_value.object);
2605  }
2606  else
2607  {
2608  throw std::domain_error("type must be object, but is " + type_name());
2609  }
2610  }
2611 
2613  template<class T, typename std::enable_if<
2614  std::is_convertible<basic_json_t, typename T::value_type>::value and
2615  not std::is_same<basic_json_t, typename T::value_type>::value and
2616  not std::is_arithmetic<T>::value and
2617  not std::is_convertible<std::string, T>::value and
2618  not has_mapped_type<T>::value, int>::type = 0>
2619  T get_impl(T*) const
2620  {
2621  if (is_array())
2622  {
2623  T to_vector;
2624  std::transform(m_value.array->begin(), m_value.array->end(),
2625  std::inserter(to_vector, to_vector.end()), [](basic_json i)
2626  {
2627  return i.get<typename T::value_type>();
2628  });
2629  return to_vector;
2630  }
2631  else
2632  {
2633  throw std::domain_error("type must be array, but is " + type_name());
2634  }
2635  }
2636 
2638  template<class T, typename std::enable_if<
2639  std::is_convertible<basic_json_t, T>::value and
2640  not std::is_same<basic_json_t, T>::value, int>::type = 0>
2641  std::vector<T> get_impl(std::vector<T>*) const
2642  {
2643  if (is_array())
2644  {
2645  std::vector<T> to_vector;
2646  to_vector.reserve(m_value.array->size());
2647  std::transform(m_value.array->begin(), m_value.array->end(),
2648  std::inserter(to_vector, to_vector.end()), [](basic_json i)
2649  {
2650  return i.get<T>();
2651  });
2652  return to_vector;
2653  }
2654  else
2655  {
2656  throw std::domain_error("type must be array, but is " + type_name());
2657  }
2658  }
2659 
2661  template<class T, typename std::enable_if<
2662  std::is_same<basic_json, typename T::value_type>::value and
2663  not has_mapped_type<T>::value, int>::type = 0>
2664  T get_impl(T*) const
2665  {
2666  if (is_array())
2667  {
2668  return T(m_value.array->begin(), m_value.array->end());
2669  }
2670  else
2671  {
2672  throw std::domain_error("type must be array, but is " + type_name());
2673  }
2674  }
2675 
2677  array_t get_impl(array_t*) const
2678  {
2679  if (is_array())
2680  {
2681  return *(m_value.array);
2682  }
2683  else
2684  {
2685  throw std::domain_error("type must be array, but is " + type_name());
2686  }
2687  }
2688 
2690  template<typename T, typename std::enable_if<
2691  std::is_convertible<string_t, T>::value, int>::type = 0>
2692  T get_impl(T*) const
2693  {
2694  if (is_string())
2695  {
2696  return *m_value.string;
2697  }
2698  else
2699  {
2700  throw std::domain_error("type must be string, but is " + type_name());
2701  }
2702  }
2703 
2705  template<typename T, typename std::enable_if<
2706  std::is_arithmetic<T>::value, int>::type = 0>
2707  T get_impl(T*) const
2708  {
2709  switch (m_type)
2710  {
2711  case value_t::number_integer:
2712  {
2713  return static_cast<T>(m_value.number_integer);
2714  }
2715 
2716  case value_t::number_unsigned:
2717  {
2718  return static_cast<T>(m_value.number_unsigned);
2719  }
2720 
2721  case value_t::number_float:
2722  {
2723  return static_cast<T>(m_value.number_float);
2724  }
2725 
2726  default:
2727  {
2728  throw std::domain_error("type must be number, but is " + type_name());
2729  }
2730  }
2731  }
2732 
2734  constexpr boolean_t get_impl(boolean_t*) const
2735  {
2736  return is_boolean()
2737  ? m_value.boolean
2738  : throw std::domain_error("type must be boolean, but is " + type_name());
2739  }
2740 
2742  object_t* get_impl_ptr(object_t*) noexcept
2743  {
2744  return is_object() ? m_value.object : nullptr;
2745  }
2746 
2748  constexpr const object_t* get_impl_ptr(const object_t*) const noexcept
2749  {
2750  return is_object() ? m_value.object : nullptr;
2751  }
2752 
2754  array_t* get_impl_ptr(array_t*) noexcept
2755  {
2756  return is_array() ? m_value.array : nullptr;
2757  }
2758 
2760  constexpr const array_t* get_impl_ptr(const array_t*) const noexcept
2761  {
2762  return is_array() ? m_value.array : nullptr;
2763  }
2764 
2766  string_t* get_impl_ptr(string_t*) noexcept
2767  {
2768  return is_string() ? m_value.string : nullptr;
2769  }
2770 
2772  constexpr const string_t* get_impl_ptr(const string_t*) const noexcept
2773  {
2774  return is_string() ? m_value.string : nullptr;
2775  }
2776 
2778  boolean_t* get_impl_ptr(boolean_t*) noexcept
2779  {
2780  return is_boolean() ? &m_value.boolean : nullptr;
2781  }
2782 
2784  constexpr const boolean_t* get_impl_ptr(const boolean_t*) const noexcept
2785  {
2786  return is_boolean() ? &m_value.boolean : nullptr;
2787  }
2788 
2790  number_integer_t* get_impl_ptr(number_integer_t*) noexcept
2791  {
2792  return is_number_integer() ? &m_value.number_integer : nullptr;
2793  }
2794 
2796  constexpr const number_integer_t* get_impl_ptr(const number_integer_t*) const noexcept
2797  {
2798  return is_number_integer() ? &m_value.number_integer : nullptr;
2799  }
2800 
2802  number_unsigned_t* get_impl_ptr(number_unsigned_t*) noexcept
2803  {
2804  return is_number_unsigned() ? &m_value.number_unsigned : nullptr;
2805  }
2806 
2808  constexpr const number_unsigned_t* get_impl_ptr(const number_unsigned_t*) const noexcept
2809  {
2810  return is_number_unsigned() ? &m_value.number_unsigned : nullptr;
2811  }
2812 
2814  number_float_t* get_impl_ptr(number_float_t*) noexcept
2815  {
2816  return is_number_float() ? &m_value.number_float : nullptr;
2817  }
2818 
2820  constexpr const number_float_t* get_impl_ptr(const number_float_t*) const noexcept
2821  {
2822  return is_number_float() ? &m_value.number_float : nullptr;
2823  }
2824 
2836  template<typename ReferenceType, typename ThisType>
2837  static ReferenceType get_ref_impl(ThisType& obj)
2838  {
2839  // helper type
2840  using PointerType = typename std::add_pointer<ReferenceType>::type;
2841 
2842  // delegate the call to get_ptr<>()
2843  auto ptr = obj.template get_ptr<PointerType>();
2844 
2845  if (ptr != nullptr)
2846  {
2847  return *ptr;
2848  }
2849  else
2850  {
2851  throw std::domain_error("incompatible ReferenceType for get_ref, actual type is " +
2852  obj.type_name());
2853  }
2854  }
2855 
2856  public:
2857 
2861 
2895  template<typename ValueType, typename std::enable_if<
2896  not std::is_pointer<ValueType>::value, int>::type = 0>
2897  ValueType get() const
2898  {
2899  return get_impl(static_cast<ValueType*>(nullptr));
2900  }
2901 
2929  template<typename PointerType, typename std::enable_if<
2930  std::is_pointer<PointerType>::value, int>::type = 0>
2931  PointerType get() noexcept
2932  {
2933  // delegate the call to get_ptr
2934  return get_ptr<PointerType>();
2935  }
2936 
2941  template<typename PointerType, typename std::enable_if<
2942  std::is_pointer<PointerType>::value, int>::type = 0>
2943  constexpr const PointerType get() const noexcept
2944  {
2945  // delegate the call to get_ptr
2946  return get_ptr<PointerType>();
2947  }
2948 
2975  template<typename PointerType, typename std::enable_if<
2976  std::is_pointer<PointerType>::value, int>::type = 0>
2977  PointerType get_ptr() noexcept
2978  {
2979  // get the type of the PointerType (remove pointer and const)
2980  using pointee_t = typename std::remove_const<typename
2981  std::remove_pointer<typename
2982  std::remove_const<PointerType>::type>::type>::type;
2983  // make sure the type matches the allowed types
2984  static_assert(
2985  std::is_same<object_t, pointee_t>::value
2986  or std::is_same<array_t, pointee_t>::value
2987  or std::is_same<string_t, pointee_t>::value
2988  or std::is_same<boolean_t, pointee_t>::value
2989  or std::is_same<number_integer_t, pointee_t>::value
2990  or std::is_same<number_unsigned_t, pointee_t>::value
2991  or std::is_same<number_float_t, pointee_t>::value
2992  , "incompatible pointer type");
2993 
2994  // delegate the call to get_impl_ptr<>()
2995  return get_impl_ptr(static_cast<PointerType>(nullptr));
2996  }
2997 
3002  template<typename PointerType, typename std::enable_if<
3003  std::is_pointer<PointerType>::value and
3004  std::is_const<typename std::remove_pointer<PointerType>::type>::value, int>::type = 0>
3005  constexpr const PointerType get_ptr() const noexcept
3006  {
3007  // get the type of the PointerType (remove pointer and const)
3008  using pointee_t = typename std::remove_const<typename
3009  std::remove_pointer<typename
3010  std::remove_const<PointerType>::type>::type>::type;
3011  // make sure the type matches the allowed types
3012  static_assert(
3013  std::is_same<object_t, pointee_t>::value
3014  or std::is_same<array_t, pointee_t>::value
3015  or std::is_same<string_t, pointee_t>::value
3016  or std::is_same<boolean_t, pointee_t>::value
3017  or std::is_same<number_integer_t, pointee_t>::value
3018  or std::is_same<number_unsigned_t, pointee_t>::value
3019  or std::is_same<number_float_t, pointee_t>::value
3020  , "incompatible pointer type");
3021 
3022  // delegate the call to get_impl_ptr<>() const
3023  return get_impl_ptr(static_cast<const PointerType>(nullptr));
3024  }
3025 
3052  template<typename ReferenceType, typename std::enable_if<
3053  std::is_reference<ReferenceType>::value, int>::type = 0>
3054  ReferenceType get_ref()
3055  {
3056  // delegate call to get_ref_impl
3057  return get_ref_impl<ReferenceType>(*this);
3058  }
3059 
3064  template<typename ReferenceType, typename std::enable_if<
3065  std::is_reference<ReferenceType>::value and
3066  std::is_const<typename std::remove_reference<ReferenceType>::type>::value, int>::type = 0>
3067  ReferenceType get_ref() const
3068  {
3069  // delegate call to get_ref_impl
3070  return get_ref_impl<ReferenceType>(*this);
3071  }
3072 
3101  template < typename ValueType, typename std::enable_if <
3102  not std::is_pointer<ValueType>::value and
3103  not std::is_same<ValueType, typename string_t::value_type>::value
3104 #ifndef _MSC_VER // Fix for issue #167 operator<< abiguity under VS2015
3105  and not std::is_same<ValueType, std::initializer_list<typename string_t::value_type>>::value
3106 #endif
3107  , int >::type = 0 >
3108  operator ValueType() const
3109  {
3110  // delegate the call to get<>() const
3111  return get<ValueType>();
3112  }
3113 
3115 
3116 
3118  // element access //
3120 
3124 
3148  {
3149  // at only works for arrays
3150  if (is_array())
3151  {
3152  try
3153  {
3154  return m_value.array->at(idx);
3155  }
3156  catch (std::out_of_range&)
3157  {
3158  // create better exception explanation
3159  throw std::out_of_range("array index " + std::to_string(idx) + " is out of range");
3160  }
3161  }
3162  else
3163  {
3164  throw std::domain_error("cannot use at() with " + type_name());
3165  }
3166  }
3167 
3191  {
3192  // at only works for arrays
3193  if (is_array())
3194  {
3195  try
3196  {
3197  return m_value.array->at(idx);
3198  }
3199  catch (std::out_of_range&)
3200  {
3201  // create better exception explanation
3202  throw std::out_of_range("array index " + std::to_string(idx) + " is out of range");
3203  }
3204  }
3205  else
3206  {
3207  throw std::domain_error("cannot use at() with " + type_name());
3208  }
3209  }
3210 
3237  reference at(const typename object_t::key_type& key)
3238  {
3239  // at only works for objects
3240  if (is_object())
3241  {
3242  try
3243  {
3244  return m_value.object->at(key);
3245  }
3246  catch (std::out_of_range&)
3247  {
3248  // create better exception explanation
3249  throw std::out_of_range("key '" + key + "' not found");
3250  }
3251  }
3252  else
3253  {
3254  throw std::domain_error("cannot use at() with " + type_name());
3255  }
3256  }
3257 
3284  const_reference at(const typename object_t::key_type& key) const
3285  {
3286  // at only works for objects
3287  if (is_object())
3288  {
3289  try
3290  {
3291  return m_value.object->at(key);
3292  }
3293  catch (std::out_of_range&)
3294  {
3295  // create better exception explanation
3296  throw std::out_of_range("key '" + key + "' not found");
3297  }
3298  }
3299  else
3300  {
3301  throw std::domain_error("cannot use at() with " + type_name());
3302  }
3303  }
3304 
3331  {
3332  // implicitly convert null value to an empty array
3333  if (is_null())
3334  {
3335  m_type = value_t::array;
3336  m_value.array = create<array_t>();
3337  assert_invariant();
3338  }
3339 
3340  // operator[] only works for arrays
3341  if (is_array())
3342  {
3343  // fill up array with null values if given idx is outside range
3344  if (idx >= m_value.array->size())
3345  {
3346  m_value.array->insert(m_value.array->end(),
3347  idx - m_value.array->size() + 1,
3348  basic_json());
3349  }
3350 
3351  return m_value.array->operator[](idx);
3352  }
3353  else
3354  {
3355  throw std::domain_error("cannot use operator[] with " + type_name());
3356  }
3357  }
3358 
3379  {
3380  // const operator[] only works for arrays
3381  if (is_array())
3382  {
3383  return m_value.array->operator[](idx);
3384  }
3385  else
3386  {
3387  throw std::domain_error("cannot use operator[] with " + type_name());
3388  }
3389  }
3390 
3418  reference operator[](const typename object_t::key_type& key)
3419  {
3420  // implicitly convert null value to an empty object
3421  if (is_null())
3422  {
3423  m_type = value_t::object;
3424  m_value.object = create<object_t>();
3425  assert_invariant();
3426  }
3427 
3428  // operator[] only works for objects
3429  if (is_object())
3430  {
3431  return m_value.object->operator[](key);
3432  }
3433  else
3434  {
3435  throw std::domain_error("cannot use operator[] with " + type_name());
3436  }
3437  }
3438 
3469  const_reference operator[](const typename object_t::key_type& key) const
3470  {
3471  // const operator[] only works for objects
3472  if (is_object())
3473  {
3474  assert(m_value.object->find(key) != m_value.object->end());
3475  return m_value.object->find(key)->second;
3476  }
3477  else
3478  {
3479  throw std::domain_error("cannot use operator[] with " + type_name());
3480  }
3481  }
3482 
3510  template<typename T, std::size_t n>
3511  reference operator[](T * (&key)[n])
3512  {
3513  return operator[](static_cast<const T>(key));
3514  }
3515 
3545  template<typename T, std::size_t n>
3546  const_reference operator[](T * (&key)[n]) const
3547  {
3548  return operator[](static_cast<const T>(key));
3549  }
3550 
3578  template<typename T>
3580  {
3581  // implicitly convert null to object
3582  if (is_null())
3583  {
3584  m_type = value_t::object;
3585  m_value = value_t::object;
3586  assert_invariant();
3587  }
3588 
3589  // at only works for objects
3590  if (is_object())
3591  {
3592  return m_value.object->operator[](key);
3593  }
3594  else
3595  {
3596  throw std::domain_error("cannot use operator[] with " + type_name());
3597  }
3598  }
3599 
3630  template<typename T>
3632  {
3633  // at only works for objects
3634  if (is_object())
3635  {
3636  assert(m_value.object->find(key) != m_value.object->end());
3637  return m_value.object->find(key)->second;
3638  }
3639  else
3640  {
3641  throw std::domain_error("cannot use operator[] with " + type_name());
3642  }
3643  }
3644 
3693  template<class ValueType, typename std::enable_if<
3694  std::is_convertible<basic_json_t, ValueType>::value, int>::type = 0>
3695  ValueType value(const typename object_t::key_type& key, ValueType default_value) const
3696  {
3697  // at only works for objects
3698  if (is_object())
3699  {
3700  // if key is found, return value and given default value otherwise
3701  const auto it = find(key);
3702  if (it != end())
3703  {
3704  return *it;
3705  }
3706  else
3707  {
3708  return default_value;
3709  }
3710  }
3711  else
3712  {
3713  throw std::domain_error("cannot use value() with " + type_name());
3714  }
3715  }
3716 
3721  string_t value(const typename object_t::key_type& key, const char* default_value) const
3722  {
3723  return value(key, string_t(default_value));
3724  }
3725 
3767  template<class ValueType, typename std::enable_if<
3768  std::is_convertible<basic_json_t, ValueType>::value, int>::type = 0>
3769  ValueType value(const json_pointer& ptr, ValueType default_value) const
3770  {
3771  // at only works for objects
3772  if (is_object())
3773  {
3774  // if pointer resolves a value, return it or use default value
3775  try
3776  {
3777  return ptr.get_checked(this);
3778  }
3779  catch (std::out_of_range&)
3780  {
3781  return default_value;
3782  }
3783  }
3784  else
3785  {
3786  throw std::domain_error("cannot use value() with " + type_name());
3787  }
3788  }
3789 
3794  string_t value(const json_pointer& ptr, const char* default_value) const
3795  {
3796  return value(ptr, string_t(default_value));
3797  }
3798 
3825  {
3826  return *begin();
3827  }
3828 
3833  {
3834  return *cbegin();
3835  }
3836 
3868  {
3869  auto tmp = end();
3870  --tmp;
3871  return *tmp;
3872  }
3873 
3878  {
3879  auto tmp = cend();
3880  --tmp;
3881  return *tmp;
3882  }
3883 
3929  template<class IteratorType, typename std::enable_if<
3930  std::is_same<IteratorType, typename basic_json_t::iterator>::value or
3931  std::is_same<IteratorType, typename basic_json_t::const_iterator>::value, int>::type
3932  = 0>
3933  IteratorType erase(IteratorType pos)
3934  {
3935  // make sure iterator fits the current value
3936  if (this != pos.m_object)
3937  {
3938  throw std::domain_error("iterator does not fit current value");
3939  }
3940 
3941  IteratorType result = end();
3942 
3943  switch (m_type)
3944  {
3945  case value_t::boolean:
3946  case value_t::number_float:
3947  case value_t::number_integer:
3948  case value_t::number_unsigned:
3949  case value_t::string:
3950  {
3951  if (not pos.m_it.primitive_iterator.is_begin())
3952  {
3953  throw std::out_of_range("iterator out of range");
3954  }
3955 
3956  if (is_string())
3957  {
3958  AllocatorType<string_t> alloc;
3959  alloc.destroy(m_value.string);
3960  alloc.deallocate(m_value.string, 1);
3961  m_value.string = nullptr;
3962  }
3963 
3964  m_type = value_t::null;
3965  assert_invariant();
3966  break;
3967  }
3968 
3969  case value_t::object:
3970  {
3971  result.m_it.object_iterator = m_value.object->erase(pos.m_it.object_iterator);
3972  break;
3973  }
3974 
3975  case value_t::array:
3976  {
3977  result.m_it.array_iterator = m_value.array->erase(pos.m_it.array_iterator);
3978  break;
3979  }
3980 
3981  default:
3982  {
3983  throw std::domain_error("cannot use erase() with " + type_name());
3984  }
3985  }
3986 
3987  return result;
3988  }
3989 
4036  template<class IteratorType, typename std::enable_if<
4037  std::is_same<IteratorType, typename basic_json_t::iterator>::value or
4038  std::is_same<IteratorType, typename basic_json_t::const_iterator>::value, int>::type
4039  = 0>
4040  IteratorType erase(IteratorType first, IteratorType last)
4041  {
4042  // make sure iterator fits the current value
4043  if (this != first.m_object or this != last.m_object)
4044  {
4045  throw std::domain_error("iterators do not fit current value");
4046  }
4047 
4048  IteratorType result = end();
4049 
4050  switch (m_type)
4051  {
4052  case value_t::boolean:
4053  case value_t::number_float:
4054  case value_t::number_integer:
4055  case value_t::number_unsigned:
4056  case value_t::string:
4057  {
4058  if (not first.m_it.primitive_iterator.is_begin() or not last.m_it.primitive_iterator.is_end())
4059  {
4060  throw std::out_of_range("iterators out of range");
4061  }
4062 
4063  if (is_string())
4064  {
4065  AllocatorType<string_t> alloc;
4066  alloc.destroy(m_value.string);
4067  alloc.deallocate(m_value.string, 1);
4068  m_value.string = nullptr;
4069  }
4070 
4071  m_type = value_t::null;
4072  assert_invariant();
4073  break;
4074  }
4075 
4076  case value_t::object:
4077  {
4078  result.m_it.object_iterator = m_value.object->erase(first.m_it.object_iterator,
4079  last.m_it.object_iterator);
4080  break;
4081  }
4082 
4083  case value_t::array:
4084  {
4085  result.m_it.array_iterator = m_value.array->erase(first.m_it.array_iterator,
4086  last.m_it.array_iterator);
4087  break;
4088  }
4089 
4090  default:
4091  {
4092  throw std::domain_error("cannot use erase() with " + type_name());
4093  }
4094  }
4095 
4096  return result;
4097  }
4098 
4128  size_type erase(const typename object_t::key_type& key)
4129  {
4130  // this erase only works for objects
4131  if (is_object())
4132  {
4133  return m_value.object->erase(key);
4134  }
4135  else
4136  {
4137  throw std::domain_error("cannot use erase() with " + type_name());
4138  }
4139  }
4140 
4165  void erase(const size_type idx)
4166  {
4167  // this erase only works for arrays
4168  if (is_array())
4169  {
4170  if (idx >= size())
4171  {
4172  throw std::out_of_range("array index " + std::to_string(idx) + " is out of range");
4173  }
4174 
4175  m_value.array->erase(m_value.array->begin() + static_cast<difference_type>(idx));
4176  }
4177  else
4178  {
4179  throw std::domain_error("cannot use erase() with " + type_name());
4180  }
4181  }
4182 
4184 
4185 
4187  // lookup //
4189 
4192 
4211  iterator find(typename object_t::key_type key)
4212  {
4213  auto result = end();
4214 
4215  if (is_object())
4216  {
4217  result.m_it.object_iterator = m_value.object->find(key);
4218  }
4219 
4220  return result;
4221  }
4222 
4227  const_iterator find(typename object_t::key_type key) const
4228  {
4229  auto result = cend();
4230 
4231  if (is_object())
4232  {
4233  result.m_it.object_iterator = m_value.object->find(key);
4234  }
4235 
4236  return result;
4237  }
4238 
4257  size_type count(typename object_t::key_type key) const
4258  {
4259  // return 0 for all nonobject types
4260  return is_object() ? m_value.object->count(key) : 0;
4261  }
4262 
4264 
4265 
4267  // iterators //
4269 
4272 
4297  iterator begin() noexcept
4298  {
4299  iterator result(this);
4300  result.set_begin();
4301  return result;
4302  }
4303 
4307  const_iterator begin() const noexcept
4308  {
4309  return cbegin();
4310  }
4311 
4337  const_iterator cbegin() const noexcept
4338  {
4339  const_iterator result(this);
4340  result.set_begin();
4341  return result;
4342  }
4343 
4368  iterator end() noexcept
4369  {
4370  iterator result(this);
4371  result.set_end();
4372  return result;
4373  }
4374 
4378  const_iterator end() const noexcept
4379  {
4380  return cend();
4381  }
4382 
4408  const_iterator cend() const noexcept
4409  {
4410  const_iterator result(this);
4411  result.set_end();
4412  return result;
4413  }
4414 
4439  {
4440  return reverse_iterator(end());
4441  }
4442 
4447  {
4448  return crbegin();
4449  }
4450 
4476  {
4477  return reverse_iterator(begin());
4478  }
4479 
4483  const_reverse_iterator rend() const noexcept
4484  {
4485  return crend();
4486  }
4487 
4513  {
4514  return const_reverse_iterator(cend());
4515  }
4516 
4542  {
4543  return const_reverse_iterator(cbegin());
4544  }
4545 
4546  private:
4547  // forward declaration
4548  template<typename IteratorType> class iteration_proxy;
4549 
4550  public:
4562  static iteration_proxy<iterator> iterator_wrapper(reference cont)
4563  {
4564  return iteration_proxy<iterator>(cont);
4565  }
4566 
4570  static iteration_proxy<const_iterator> iterator_wrapper(const_reference cont)
4571  {
4572  return iteration_proxy<const_iterator>(cont);
4573  }
4574 
4576 
4577 
4579  // capacity //
4581 
4584 
4622  bool empty() const noexcept
4623  {
4624  switch (m_type)
4625  {
4626  case value_t::null:
4627  {
4628  // null values are empty
4629  return true;
4630  }
4631 
4632  case value_t::array:
4633  {
4634  // delegate call to array_t::empty()
4635  return m_value.array->empty();
4636  }
4637 
4638  case value_t::object:
4639  {
4640  // delegate call to object_t::empty()
4641  return m_value.object->empty();
4642  }
4643 
4644  default:
4645  {
4646  // all other types are nonempty
4647  return false;
4648  }
4649  }
4650  }
4651 
4690  size_type size() const noexcept
4691  {
4692  switch (m_type)
4693  {
4694  case value_t::null:
4695  {
4696  // null values are empty
4697  return 0;
4698  }
4699 
4700  case value_t::array:
4701  {
4702  // delegate call to array_t::size()
4703  return m_value.array->size();
4704  }
4705 
4706  case value_t::object:
4707  {
4708  // delegate call to object_t::size()
4709  return m_value.object->size();
4710  }
4711 
4712  default:
4713  {
4714  // all other types have size 1
4715  return 1;
4716  }
4717  }
4718  }
4719 
4756  size_type max_size() const noexcept
4757  {
4758  switch (m_type)
4759  {
4760  case value_t::array:
4761  {
4762  // delegate call to array_t::max_size()
4763  return m_value.array->max_size();
4764  }
4765 
4766  case value_t::object:
4767  {
4768  // delegate call to object_t::max_size()
4769  return m_value.object->max_size();
4770  }
4771 
4772  default:
4773  {
4774  // all other types have max_size() == size()
4775  return size();
4776  }
4777  }
4778  }
4779 
4781 
4782 
4784  // modifiers //
4786 
4789 
4815  void clear() noexcept
4816  {
4817  switch (m_type)
4818  {
4819  case value_t::number_integer:
4820  {
4821  m_value.number_integer = 0;
4822  break;
4823  }
4824 
4825  case value_t::number_unsigned:
4826  {
4827  m_value.number_unsigned = 0;
4828  break;
4829  }
4830 
4831  case value_t::number_float:
4832  {
4833  m_value.number_float = 0.0;
4834  break;
4835  }
4836 
4837  case value_t::boolean:
4838  {
4839  m_value.boolean = false;
4840  break;
4841  }
4842 
4843  case value_t::string:
4844  {
4845  m_value.string->clear();
4846  break;
4847  }
4848 
4849  case value_t::array:
4850  {
4851  m_value.array->clear();
4852  break;
4853  }
4854 
4855  case value_t::object:
4856  {
4857  m_value.object->clear();
4858  break;
4859  }
4860 
4861  default:
4862  {
4863  break;
4864  }
4865  }
4866  }
4867 
4888  void push_back(basic_json&& val)
4889  {
4890  // push_back only works for null objects or arrays
4891  if (not(is_null() or is_array()))
4892  {
4893  throw std::domain_error("cannot use push_back() with " + type_name());
4894  }
4895 
4896  // transform null object into an array
4897  if (is_null())
4898  {
4899  m_type = value_t::array;
4900  m_value = value_t::array;
4901  assert_invariant();
4902  }
4903 
4904  // add element to array (move semantics)
4905  m_value.array->push_back(std::move(val));
4906  // invalidate object
4907  val.m_type = value_t::null;
4908  }
4909 
4915  {
4916  push_back(std::move(val));
4917  return *this;
4918  }
4919 
4924  void push_back(const basic_json& val)
4925  {
4926  // push_back only works for null objects or arrays
4927  if (not(is_null() or is_array()))
4928  {
4929  throw std::domain_error("cannot use push_back() with " + type_name());
4930  }
4931 
4932  // transform null object into an array
4933  if (is_null())
4934  {
4935  m_type = value_t::array;
4936  m_value = value_t::array;
4937  assert_invariant();
4938  }
4939 
4940  // add element to array
4941  m_value.array->push_back(val);
4942  }
4943 
4949  {
4950  push_back(val);
4951  return *this;
4952  }
4953 
4974  void push_back(const typename object_t::value_type& val)
4975  {
4976  // push_back only works for null objects or objects
4977  if (not(is_null() or is_object()))
4978  {
4979  throw std::domain_error("cannot use push_back() with " + type_name());
4980  }
4981 
4982  // transform null object into an object
4983  if (is_null())
4984  {
4985  m_type = value_t::object;
4986  m_value = value_t::object;
4987  assert_invariant();
4988  }
4989 
4990  // add element to array
4991  m_value.object->insert(val);
4992  }
4993 
4998  reference operator+=(const typename object_t::value_type& val)
4999  {
5000  push_back(val);
5001  return *this;
5002  }
5003 
5029  void push_back(std::initializer_list<basic_json> init)
5030  {
5031  if (is_object() and init.size() == 2 and init.begin()->is_string())
5032  {
5033  const string_t key = *init.begin();
5034  push_back(typename object_t::value_type(key, *(init.begin() + 1)));
5035  }
5036  else
5037  {
5038  push_back(basic_json(init));
5039  }
5040  }
5041 
5046  reference operator+=(std::initializer_list<basic_json> init)
5047  {
5048  push_back(init);
5049  return *this;
5050  }
5051 
5075  {
5076  // insert only works for arrays
5077  if (is_array())
5078  {
5079  // check if iterator pos fits to this JSON value
5080  if (pos.m_object != this)
5081  {
5082  throw std::domain_error("iterator does not fit current value");
5083  }
5084 
5085  // insert to array and return iterator
5086  iterator result(this);
5087  result.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator, val);
5088  return result;
5089  }
5090  else
5091  {
5092  throw std::domain_error("cannot use insert() with " + type_name());
5093  }
5094  }
5095 
5101  {
5102  return insert(pos, val);
5103  }
5104 
5130  {
5131  // insert only works for arrays
5132  if (is_array())
5133  {
5134  // check if iterator pos fits to this JSON value
5135  if (pos.m_object != this)
5136  {
5137  throw std::domain_error("iterator does not fit current value");
5138  }
5139 
5140  // insert to array and return iterator
5141  iterator result(this);
5142  result.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator, cnt, val);
5143  return result;
5144  }
5145  else
5146  {
5147  throw std::domain_error("cannot use insert() with " + type_name());
5148  }
5149  }
5150 
5182  {
5183  // insert only works for arrays
5184  if (not is_array())
5185  {
5186  throw std::domain_error("cannot use insert() with " + type_name());
5187  }
5188 
5189  // check if iterator pos fits to this JSON value
5190  if (pos.m_object != this)
5191  {
5192  throw std::domain_error("iterator does not fit current value");
5193  }
5194 
5195  // check if range iterators belong to the same JSON object
5196  if (first.m_object != last.m_object)
5197  {
5198  throw std::domain_error("iterators do not fit");
5199  }
5200 
5201  if (first.m_object == this or last.m_object == this)
5202  {
5203  throw std::domain_error("passed iterators may not belong to container");
5204  }
5205 
5206  // insert to array and return iterator
5207  iterator result(this);
5208  result.m_it.array_iterator = m_value.array->insert(
5209  pos.m_it.array_iterator,
5210  first.m_it.array_iterator,
5211  last.m_it.array_iterator);
5212  return result;
5213  }
5214 
5239  iterator insert(const_iterator pos, std::initializer_list<basic_json> ilist)
5240  {
5241  // insert only works for arrays
5242  if (not is_array())
5243  {
5244  throw std::domain_error("cannot use insert() with " + type_name());
5245  }
5246 
5247  // check if iterator pos fits to this JSON value
5248  if (pos.m_object != this)
5249  {
5250  throw std::domain_error("iterator does not fit current value");
5251  }
5252 
5253  // insert to array and return iterator
5254  iterator result(this);
5255  result.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator, ilist);
5256  return result;
5257  }
5258 
5276  void swap(reference other) noexcept (
5277  std::is_nothrow_move_constructible<value_t>::value and
5278  std::is_nothrow_move_assignable<value_t>::value and
5279  std::is_nothrow_move_constructible<json_value>::value and
5280  std::is_nothrow_move_assignable<json_value>::value
5281  )
5282  {
5283  std::swap(m_type, other.m_type);
5284  std::swap(m_value, other.m_value);
5285  assert_invariant();
5286  }
5287 
5308  void swap(array_t& other)
5309  {
5310  // swap only works for arrays
5311  if (is_array())
5312  {
5313  std::swap(*(m_value.array), other);
5314  }
5315  else
5316  {
5317  throw std::domain_error("cannot use swap() with " + type_name());
5318  }
5319  }
5320 
5341  void swap(object_t& other)
5342  {
5343  // swap only works for objects
5344  if (is_object())
5345  {
5346  std::swap(*(m_value.object), other);
5347  }
5348  else
5349  {
5350  throw std::domain_error("cannot use swap() with " + type_name());
5351  }
5352  }
5353 
5374  void swap(string_t& other)
5375  {
5376  // swap only works for strings
5377  if (is_string())
5378  {
5379  std::swap(*(m_value.string), other);
5380  }
5381  else
5382  {
5383  throw std::domain_error("cannot use swap() with " + type_name());
5384  }
5385  }
5386 
5388 
5389 
5391  // lexicographical comparison operators //
5393 
5396 
5397  private:
5407  friend bool operator<(const value_t lhs, const value_t rhs) noexcept
5408  {
5409  static constexpr std::array<uint8_t, 8> order = {{
5410  0, // null
5411  3, // object
5412  4, // array
5413  5, // string
5414  1, // boolean
5415  2, // integer
5416  2, // unsigned
5417  2, // float
5418  }
5419  };
5420 
5421  // discarded values are not comparable
5422  if (lhs == value_t::discarded or rhs == value_t::discarded)
5423  {
5424  return false;
5425  }
5426 
5427  return order[static_cast<std::size_t>(lhs)] < order[static_cast<std::size_t>(rhs)];
5428  }
5429 
5430  public:
5454  friend bool operator==(const_reference lhs, const_reference rhs) noexcept
5455  {
5456  const auto lhs_type = lhs.type();
5457  const auto rhs_type = rhs.type();
5458 
5459  if (lhs_type == rhs_type)
5460  {
5461  switch (lhs_type)
5462  {
5463  case value_t::array:
5464  {
5465  return *lhs.m_value.array == *rhs.m_value.array;
5466  }
5467  case value_t::object:
5468  {
5469  return *lhs.m_value.object == *rhs.m_value.object;
5470  }
5471  case value_t::null:
5472  {
5473  return true;
5474  }
5475  case value_t::string:
5476  {
5477  return *lhs.m_value.string == *rhs.m_value.string;
5478  }
5479  case value_t::boolean:
5480  {
5481  return lhs.m_value.boolean == rhs.m_value.boolean;
5482  }
5483  case value_t::number_integer:
5484  {
5485  return lhs.m_value.number_integer == rhs.m_value.number_integer;
5486  }
5487  case value_t::number_unsigned:
5488  {
5489  return lhs.m_value.number_unsigned == rhs.m_value.number_unsigned;
5490  }
5491  case value_t::number_float:
5492  {
5493  return lhs.m_value.number_float == rhs.m_value.number_float;
5494  }
5495  default:
5496  {
5497  return false;
5498  }
5499  }
5500  }
5501  else if (lhs_type == value_t::number_integer and rhs_type == value_t::number_float)
5502  {
5503  return static_cast<number_float_t>(lhs.m_value.number_integer) == rhs.m_value.number_float;
5504  }
5505  else if (lhs_type == value_t::number_float and rhs_type == value_t::number_integer)
5506  {
5507  return lhs.m_value.number_float == static_cast<number_float_t>(rhs.m_value.number_integer);
5508  }
5509  else if (lhs_type == value_t::number_unsigned and rhs_type == value_t::number_float)
5510  {
5511  return static_cast<number_float_t>(lhs.m_value.number_unsigned) == rhs.m_value.number_float;
5512  }
5513  else if (lhs_type == value_t::number_float and rhs_type == value_t::number_unsigned)
5514  {
5515  return lhs.m_value.number_float == static_cast<number_float_t>(rhs.m_value.number_unsigned);
5516  }
5517  else if (lhs_type == value_t::number_unsigned and rhs_type == value_t::number_integer)
5518  {
5519  return static_cast<number_integer_t>(lhs.m_value.number_unsigned) == rhs.m_value.number_integer;
5520  }
5521  else if (lhs_type == value_t::number_integer and rhs_type == value_t::number_unsigned)
5522  {
5523  return lhs.m_value.number_integer == static_cast<number_integer_t>(rhs.m_value.number_unsigned);
5524  }
5525 
5526  return false;
5527  }
5528 
5547  friend bool operator==(const_reference v, std::nullptr_t) noexcept
5548  {
5549  return v.is_null();
5550  }
5551 
5556  friend bool operator==(std::nullptr_t, const_reference v) noexcept
5557  {
5558  return v.is_null();
5559  }
5560 
5577  friend bool operator!=(const_reference lhs, const_reference rhs) noexcept
5578  {
5579  return not (lhs == rhs);
5580  }
5581 
5600  friend bool operator!=(const_reference v, std::nullptr_t) noexcept
5601  {
5602  return not v.is_null();
5603  }
5604 
5609  friend bool operator!=(std::nullptr_t, const_reference v) noexcept
5610  {
5611  return not v.is_null();
5612  }
5613 
5638  friend bool operator<(const_reference lhs, const_reference rhs) noexcept
5639  {
5640  const auto lhs_type = lhs.type();
5641  const auto rhs_type = rhs.type();
5642 
5643  if (lhs_type == rhs_type)
5644  {
5645  switch (lhs_type)
5646  {
5647  case value_t::array:
5648  {
5649  return *lhs.m_value.array < *rhs.m_value.array;
5650  }
5651  case value_t::object:
5652  {
5653  return *lhs.m_value.object < *rhs.m_value.object;
5654  }
5655  case value_t::null:
5656  {
5657  return false;
5658  }
5659  case value_t::string:
5660  {
5661  return *lhs.m_value.string < *rhs.m_value.string;
5662  }
5663  case value_t::boolean:
5664  {
5665  return lhs.m_value.boolean < rhs.m_value.boolean;
5666  }
5667  case value_t::number_integer:
5668  {
5669  return lhs.m_value.number_integer < rhs.m_value.number_integer;
5670  }
5671  case value_t::number_unsigned:
5672  {
5673  return lhs.m_value.number_unsigned < rhs.m_value.number_unsigned;
5674  }
5675  case value_t::number_float:
5676  {
5677  return lhs.m_value.number_float < rhs.m_value.number_float;
5678  }
5679  default:
5680  {
5681  return false;
5682  }
5683  }
5684  }
5685  else if (lhs_type == value_t::number_integer and rhs_type == value_t::number_float)
5686  {
5687  return static_cast<number_float_t>(lhs.m_value.number_integer) < rhs.m_value.number_float;
5688  }
5689  else if (lhs_type == value_t::number_float and rhs_type == value_t::number_integer)
5690  {
5691  return lhs.m_value.number_float < static_cast<number_float_t>(rhs.m_value.number_integer);
5692  }
5693  else if (lhs_type == value_t::number_unsigned and rhs_type == value_t::number_float)
5694  {
5695  return static_cast<number_float_t>(lhs.m_value.number_unsigned) < rhs.m_value.number_float;
5696  }
5697  else if (lhs_type == value_t::number_float and rhs_type == value_t::number_unsigned)
5698  {
5699  return lhs.m_value.number_float < static_cast<number_float_t>(rhs.m_value.number_unsigned);
5700  }
5701  else if (lhs_type == value_t::number_integer and rhs_type == value_t::number_unsigned)
5702  {
5703  return lhs.m_value.number_integer < static_cast<number_integer_t>(rhs.m_value.number_unsigned);
5704  }
5705  else if (lhs_type == value_t::number_unsigned and rhs_type == value_t::number_integer)
5706  {
5707  return static_cast<number_integer_t>(lhs.m_value.number_unsigned) < rhs.m_value.number_integer;
5708  }
5709 
5710  // We only reach this line if we cannot compare values. In that case,
5711  // we compare types. Note we have to call the operator explicitly,
5712  // because MSVC has problems otherwise.
5713  return operator<(lhs_type, rhs_type);
5714  }
5715 
5733  friend bool operator<=(const_reference lhs, const_reference rhs) noexcept
5734  {
5735  return not (rhs < lhs);
5736  }
5737 
5755  friend bool operator>(const_reference lhs, const_reference rhs) noexcept
5756  {
5757  return not (lhs <= rhs);
5758  }
5759 
5777  friend bool operator>=(const_reference lhs, const_reference rhs) noexcept
5778  {
5779  return not (lhs < rhs);
5780  }
5781 
5783 
5784 
5786  // serialization //
5788 
5791 
5818  friend std::ostream& operator<<(std::ostream& o, const basic_json& j)
5819  {
5820  // read width member and use it as indentation parameter if nonzero
5821  const bool pretty_print = (o.width() > 0);
5822  const auto indentation = (pretty_print ? o.width() : 0);
5823 
5824  // reset width to 0 for subsequent calls to this stream
5825  o.width(0);
5826 
5827  // fix locale problems
5828  const auto old_locale = o.imbue(std::locale(std::locale(), new DecimalSeparator));
5829  // set precision
5830 
5831  // 6, 15 or 16 digits of precision allows round-trip IEEE 754
5832  // string->float->string, string->double->string or string->long
5833  // double->string; to be safe, we read this value from
5834  // std::numeric_limits<number_float_t>::digits10
5835  const auto old_precision = o.precision(std::numeric_limits<double>::digits10);
5836 
5837  // do the actual serialization
5838  j.dump(o, pretty_print, static_cast<unsigned int>(indentation));
5839 
5840  // reset locale and precision
5841  o.imbue(old_locale);
5842  o.precision(old_precision);
5843  return o;
5844  }
5845 
5850  friend std::ostream& operator>>(const basic_json& j, std::ostream& o)
5851  {
5852  return o << j;
5853  }
5854 
5856 
5857 
5859  // deserialization //
5861 
5864 
5892  template<class T, std::size_t N>
5893  static basic_json parse(T (&array)[N],
5894  const parser_callback_t cb = nullptr)
5895  {
5896  // delegate the call to the iterator-range parse overload
5897  return parse(std::begin(array), std::end(array), cb);
5898  }
5899 
5927  template<typename CharPT, typename std::enable_if<
5928  std::is_pointer<CharPT>::value and
5929  std::is_integral<typename std::remove_pointer<CharPT>::type>::value and
5930  sizeof(typename std::remove_pointer<CharPT>::type) == 1, int>::type = 0>
5931  static basic_json parse(const CharPT s,
5932  const parser_callback_t cb = nullptr)
5933  {
5934  return parser(reinterpret_cast<const char*>(s), cb).parse();
5935  }
5936 
5961  static basic_json parse(std::istream& i,
5962  const parser_callback_t cb = nullptr)
5963  {
5964  return parser(i, cb).parse();
5965  }
5966 
5970  static basic_json parse(std::istream&& i,
5971  const parser_callback_t cb = nullptr)
5972  {
5973  return parser(i, cb).parse();
5974  }
5975 
6017  template<class IteratorType, typename std::enable_if<
6018  std::is_base_of<
6019  std::random_access_iterator_tag,
6020  typename std::iterator_traits<IteratorType>::iterator_category>::value, int>::type = 0>
6021  static basic_json parse(IteratorType first, IteratorType last,
6022  const parser_callback_t cb = nullptr)
6023  {
6024  // assertion to check that the iterator range is indeed contiguous,
6025  // see http://stackoverflow.com/a/35008842/266378 for more discussion
6026  assert(std::accumulate(first, last, std::make_pair<bool, int>(true, 0),
6027  [&first](std::pair<bool, int> res, decltype(*first) val)
6028  {
6029  res.first &= (val == *(std::next(std::addressof(*first), res.second++)));
6030  return res;
6031  }).first);
6032 
6033  // assertion to check that each element is 1 byte long
6034  static_assert(sizeof(typename std::iterator_traits<IteratorType>::value_type) == 1,
6035  "each element in the iterator range must have the size of 1 byte");
6036 
6037  // if iterator range is empty, create a parser with an empty string
6038  // to generate "unexpected EOF" error message
6039  if (std::distance(first, last) <= 0)
6040  {
6041  return parser("").parse();
6042  }
6043 
6044  return parser(first, last, cb).parse();
6045  }
6046 
6087  template<class ContiguousContainer, typename std::enable_if<
6088  not std::is_pointer<ContiguousContainer>::value and
6089  std::is_base_of<
6090  std::random_access_iterator_tag,
6091  typename std::iterator_traits<decltype(std::begin(std::declval<ContiguousContainer const>()))>::iterator_category>::value
6092  , int>::type = 0>
6093  static basic_json parse(const ContiguousContainer& c,
6094  const parser_callback_t cb = nullptr)
6095  {
6096  // delegate the call to the iterator-range parse overload
6097  return parse(std::begin(c), std::end(c), cb);
6098  }
6099 
6123  friend std::istream& operator<<(basic_json& j, std::istream& i)
6124  {
6125  j = parser(i).parse();
6126  return i;
6127  }
6128 
6133  friend std::istream& operator>>(std::istream& i, basic_json& j)
6134  {
6135  j = parser(i).parse();
6136  return i;
6137  }
6138 
6140 
6141 
6142  private:
6144  // convenience functions //
6146 
6159  std::string type_name() const
6160  {
6161  switch (m_type)
6162  {
6163  case value_t::null:
6164  return "null";
6165  case value_t::object:
6166  return "object";
6167  case value_t::array:
6168  return "array";
6169  case value_t::string:
6170  return "string";
6171  case value_t::boolean:
6172  return "boolean";
6173  case value_t::discarded:
6174  return "discarded";
6175  default:
6176  return "number";
6177  }
6178  }
6179 
6188  static std::size_t extra_space(const string_t& s) noexcept
6189  {
6190  return std::accumulate(s.begin(), s.end(), size_t{},
6191  [](size_t res, typename string_t::value_type c)
6192  {
6193  switch (c)
6194  {
6195  case '"':
6196  case '\\':
6197  case '\b':
6198  case '\f':
6199  case '\n':
6200  case '\r':
6201  case '\t':
6202  {
6203  // from c (1 byte) to \x (2 bytes)
6204  return res + 1;
6205  }
6206 
6207  default:
6208  {
6209  if (c >= 0x00 and c <= 0x1f)
6210  {
6211  // from c (1 byte) to \uxxxx (6 bytes)
6212  return res + 5;
6213  }
6214  else
6215  {
6216  return res;
6217  }
6218  }
6219  }
6220  });
6221  }
6222 
6236  static string_t escape_string(const string_t& s)
6237  {
6238  const auto space = extra_space(s);
6239  if (space == 0)
6240  {
6241  return s;
6242  }
6243 
6244  // create a result string of necessary size
6245  string_t result(s.size() + space, '\\');
6246  std::size_t pos = 0;
6247 
6248  for (const auto& c : s)
6249  {
6250  switch (c)
6251  {
6252  // quotation mark (0x22)
6253  case '"':
6254  {
6255  result[pos + 1] = '"';
6256  pos += 2;
6257  break;
6258  }
6259 
6260  // reverse solidus (0x5c)
6261  case '\\':
6262  {
6263  // nothing to change
6264  pos += 2;
6265  break;
6266  }
6267 
6268  // backspace (0x08)
6269  case '\b':
6270  {
6271  result[pos + 1] = 'b';
6272  pos += 2;
6273  break;
6274  }
6275 
6276  // formfeed (0x0c)
6277  case '\f':
6278  {
6279  result[pos + 1] = 'f';
6280  pos += 2;
6281  break;
6282  }
6283 
6284  // newline (0x0a)
6285  case '\n':
6286  {
6287  result[pos + 1] = 'n';
6288  pos += 2;
6289  break;
6290  }
6291 
6292  // carriage return (0x0d)
6293  case '\r':
6294  {
6295  result[pos + 1] = 'r';
6296  pos += 2;
6297  break;
6298  }
6299 
6300  // horizontal tab (0x09)
6301  case '\t':
6302  {
6303  result[pos + 1] = 't';
6304  pos += 2;
6305  break;
6306  }
6307 
6308  default:
6309  {
6310  if (c >= 0x00 and c <= 0x1f)
6311  {
6312  // convert a number 0..15 to its hex representation
6313  // (0..f)
6314  static const char hexify[16] =
6315  {
6316  '0', '1', '2', '3', '4', '5', '6', '7',
6317  '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'
6318  };
6319 
6320  // print character c as \uxxxx
6321  for (const char m :
6322  { 'u', '0', '0', hexify[c >> 4], hexify[c & 0x0f]
6323  })
6324  {
6325  result[++pos] = m;
6326  }
6327 
6328  ++pos;
6329  }
6330  else
6331  {
6332  // all other characters are added as-is
6333  result[pos++] = c;
6334  }
6335  break;
6336  }
6337  }
6338  }
6339 
6340  return result;
6341  }
6342 
6360  void dump(std::ostream& o,
6361  const bool pretty_print,
6362  const unsigned int indent_step,
6363  const unsigned int current_indent = 0) const
6364  {
6365  // variable to hold indentation for recursive calls
6366  unsigned int new_indent = current_indent;
6367 
6368  switch (m_type)
6369  {
6370  case value_t::object:
6371  {
6372  if (m_value.object->empty())
6373  {
6374  o << "{}";
6375  return;
6376  }
6377 
6378  o << "{";
6379 
6380  // increase indentation
6381  if (pretty_print)
6382  {
6383  new_indent += indent_step;
6384  o << "\n";
6385  }
6386 
6387  for (auto i = m_value.object->cbegin(); i != m_value.object->cend(); ++i)
6388  {
6389  if (i != m_value.object->cbegin())
6390  {
6391  o << (pretty_print ? ",\n" : ",");
6392  }
6393  o << string_t(new_indent, ' ') << "\""
6394  << escape_string(i->first) << "\":"
6395  << (pretty_print ? " " : "");
6396  i->second.dump(o, pretty_print, indent_step, new_indent);
6397  }
6398 
6399  // decrease indentation
6400  if (pretty_print)
6401  {
6402  new_indent -= indent_step;
6403  o << "\n";
6404  }
6405 
6406  o << string_t(new_indent, ' ') + "}";
6407  return;
6408  }
6409 
6410  case value_t::array:
6411  {
6412  if (m_value.array->empty())
6413  {
6414  o << "[]";
6415  return;
6416  }
6417 
6418  o << "[";
6419 
6420  // increase indentation
6421  if (pretty_print)
6422  {
6423  new_indent += indent_step;
6424  o << "\n";
6425  }
6426 
6427  for (auto i = m_value.array->cbegin(); i != m_value.array->cend(); ++i)
6428  {
6429  if (i != m_value.array->cbegin())
6430  {
6431  o << (pretty_print ? ",\n" : ",");
6432  }
6433  o << string_t(new_indent, ' ');
6434  i->dump(o, pretty_print, indent_step, new_indent);
6435  }
6436 
6437  // decrease indentation
6438  if (pretty_print)
6439  {
6440  new_indent -= indent_step;
6441  o << "\n";
6442  }
6443 
6444  o << string_t(new_indent, ' ') << "]";
6445  return;
6446  }
6447 
6448  case value_t::string:
6449  {
6450  o << string_t("\"") << escape_string(*m_value.string) << "\"";
6451  return;
6452  }
6453 
6454  case value_t::boolean:
6455  {
6456  o << (m_value.boolean ? "true" : "false");
6457  return;
6458  }
6459 
6460  case value_t::number_integer:
6461  {
6462  o << m_value.number_integer;
6463  return;
6464  }
6465 
6466  case value_t::number_unsigned:
6467  {
6468  o << m_value.number_unsigned;
6469  return;
6470  }
6471 
6472  case value_t::number_float:
6473  {
6474  if (m_value.number_float == 0)
6475  {
6476  // special case for zero to get "0.0"/"-0.0"
6477  o << (std::signbit(m_value.number_float) ? "-0.0" : "0.0");
6478  }
6479  else
6480  {
6481  o << m_value.number_float;
6482  }
6483  return;
6484  }
6485 
6486  case value_t::discarded:
6487  {
6488  o << "<discarded>";
6489  return;
6490  }
6491 
6492  case value_t::null:
6493  {
6494  o << "null";
6495  return;
6496  }
6497  }
6498  }
6499 
6500  private:
6502  // member variables //
6504 
6506  value_t m_type = value_t::null;
6507 
6509  json_value m_value = {};
6510 
6511 
6512  private:
6514  // iterators //
6516 
6526  class primitive_iterator_t
6527  {
6528  public:
6530  void set_begin() noexcept
6531  {
6532  m_it = begin_value;
6533  }
6534 
6536  void set_end() noexcept
6537  {
6538  m_it = end_value;
6539  }
6540 
6542  constexpr bool is_begin() const noexcept
6543  {
6544  return (m_it == begin_value);
6545  }
6546 
6548  constexpr bool is_end() const noexcept
6549  {
6550  return (m_it == end_value);
6551  }
6552 
6554  operator difference_type& () noexcept
6555  {
6556  return m_it;
6557  }
6558 
6560  constexpr operator difference_type () const noexcept
6561  {
6562  return m_it;
6563  }
6564 
6565  private:
6566  static constexpr difference_type begin_value = 0;
6567  static constexpr difference_type end_value = begin_value + 1;
6568 
6570  difference_type m_it = std::numeric_limits<std::ptrdiff_t>::denorm_min();
6571  };
6572 
6580  struct internal_iterator
6581  {
6583  typename object_t::iterator object_iterator;
6585  typename array_t::iterator array_iterator;
6587  primitive_iterator_t primitive_iterator;
6588 
6590  internal_iterator() noexcept
6591  : object_iterator(), array_iterator(), primitive_iterator()
6592  {}
6593  };
6594 
6596  template<typename IteratorType>
6597  class iteration_proxy
6598  {
6599  private:
6601  class iteration_proxy_internal
6602  {
6603  private:
6605  IteratorType anchor;
6607  size_t array_index = 0;
6608 
6609  public:
6610  explicit iteration_proxy_internal(IteratorType it) noexcept
6611  : anchor(it)
6612  {}
6613 
6615  iteration_proxy_internal& operator*()
6616  {
6617  return *this;
6618  }
6619 
6621  iteration_proxy_internal& operator++()
6622  {
6623  ++anchor;
6624  ++array_index;
6625 
6626  return *this;
6627  }
6628 
6630  bool operator!= (const iteration_proxy_internal& o) const
6631  {
6632  return anchor != o.anchor;
6633  }
6634 
6636  typename basic_json::string_t key() const
6637  {
6638  assert(anchor.m_object != nullptr);
6639 
6640  switch (anchor.m_object->type())
6641  {
6642  // use integer array index as key
6643  case value_t::array:
6644  {
6645  return std::to_string(array_index);
6646  }
6647 
6648  // use key from the object
6649  case value_t::object:
6650  {
6651  return anchor.key();
6652  }
6653 
6654  // use an empty key for all primitive types
6655  default:
6656  {
6657  return "";
6658  }
6659  }
6660  }
6661 
6663  typename IteratorType::reference value() const
6664  {
6665  return anchor.value();
6666  }
6667  };
6668 
6670  typename IteratorType::reference container;
6671 
6672  public:
6674  explicit iteration_proxy(typename IteratorType::reference cont)
6675  : container(cont)
6676  {}
6677 
6679  iteration_proxy_internal begin() noexcept
6680  {
6681  return iteration_proxy_internal(container.begin());
6682  }
6683 
6685  iteration_proxy_internal end() noexcept
6686  {
6687  return iteration_proxy_internal(container.end());
6688  }
6689  };
6690 
6691  public:
6711  class const_iterator : public std::iterator<std::random_access_iterator_tag, const basic_json>
6712  {
6714  friend class basic_json;
6715 
6716  public:
6726  using iterator_category = std::bidirectional_iterator_tag;
6727 
6729  const_iterator() = default;
6730 
6737  explicit const_iterator(pointer object) noexcept
6738  : m_object(object)
6739  {
6740  assert(m_object != nullptr);
6741 
6742  switch (m_object->m_type)
6743  {
6745  {
6746  m_it.object_iterator = typename object_t::iterator();
6747  break;
6748  }
6749 
6751  {
6752  m_it.array_iterator = typename array_t::iterator();
6753  break;
6754  }
6755 
6756  default:
6757  {
6758  m_it.primitive_iterator = primitive_iterator_t();
6759  break;
6760  }
6761  }
6762  }
6763 
6769  explicit const_iterator(const iterator& other) noexcept
6770  : m_object(other.m_object)
6771  {
6772  if (m_object != nullptr)
6773  {
6774  switch (m_object->m_type)
6775  {
6777  {
6778  m_it.object_iterator = other.m_it.object_iterator;
6779  break;
6780  }
6781 
6783  {
6784  m_it.array_iterator = other.m_it.array_iterator;
6785  break;
6786  }
6787 
6788  default:
6789  {
6790  m_it.primitive_iterator = other.m_it.primitive_iterator;
6791  break;
6792  }
6793  }
6794  }
6795  }
6796 
6802  const_iterator(const const_iterator& other) noexcept
6803  : m_object(other.m_object), m_it(other.m_it)
6804  {}
6805 
6812  std::is_nothrow_move_constructible<pointer>::value and
6813  std::is_nothrow_move_assignable<pointer>::value and
6814  std::is_nothrow_move_constructible<internal_iterator>::value and
6815  std::is_nothrow_move_assignable<internal_iterator>::value
6816  )
6817  {
6818  std::swap(m_object, other.m_object);
6819  std::swap(m_it, other.m_it);
6820  return *this;
6821  }
6822 
6823  private:
6828  void set_begin() noexcept
6829  {
6830  assert(m_object != nullptr);
6831 
6832  switch (m_object->m_type)
6833  {
6835  {
6836  m_it.object_iterator = m_object->m_value.object->begin();
6837  break;
6838  }
6839 
6841  {
6842  m_it.array_iterator = m_object->m_value.array->begin();
6843  break;
6844  }
6845 
6847  {
6848  // set to end so begin()==end() is true: null is empty
6849  m_it.primitive_iterator.set_end();
6850  break;
6851  }
6852 
6853  default:
6854  {
6855  m_it.primitive_iterator.set_begin();
6856  break;
6857  }
6858  }
6859  }
6860 
6865  void set_end() noexcept
6866  {
6867  assert(m_object != nullptr);
6868 
6869  switch (m_object->m_type)
6870  {
6872  {
6873  m_it.object_iterator = m_object->m_value.object->end();
6874  break;
6875  }
6876 
6878  {
6879  m_it.array_iterator = m_object->m_value.array->end();
6880  break;
6881  }
6882 
6883  default:
6884  {
6885  m_it.primitive_iterator.set_end();
6886  break;
6887  }
6888  }
6889  }
6890 
6891  public:
6897  {
6898  assert(m_object != nullptr);
6899 
6900  switch (m_object->m_type)
6901  {
6903  {
6904  assert(m_it.object_iterator != m_object->m_value.object->end());
6905  return m_it.object_iterator->second;
6906  }
6907 
6909  {
6910  assert(m_it.array_iterator != m_object->m_value.array->end());
6911  return *m_it.array_iterator;
6912  }
6913 
6915  {
6916  throw std::out_of_range("cannot get value");
6917  }
6918 
6919  default:
6920  {
6921  if (m_it.primitive_iterator.is_begin())
6922  {
6923  return *m_object;
6924  }
6925  else
6926  {
6927  throw std::out_of_range("cannot get value");
6928  }
6929  }
6930  }
6931  }
6932 
6938  {
6939  assert(m_object != nullptr);
6940 
6941  switch (m_object->m_type)
6942  {
6944  {
6945  assert(m_it.object_iterator != m_object->m_value.object->end());
6946  return &(m_it.object_iterator->second);
6947  }
6948 
6950  {
6951  assert(m_it.array_iterator != m_object->m_value.array->end());
6952  return &*m_it.array_iterator;
6953  }
6954 
6955  default:
6956  {
6957  if (m_it.primitive_iterator.is_begin())
6958  {
6959  return m_object;
6960  }
6961  else
6962  {
6963  throw std::out_of_range("cannot get value");
6964  }
6965  }
6966  }
6967  }
6968 
6974  {
6975  auto result = *this;
6976  ++(*this);
6977  return result;
6978  }
6979 
6985  {
6986  assert(m_object != nullptr);
6987 
6988  switch (m_object->m_type)
6989  {
6991  {
6992  std::advance(m_it.object_iterator, 1);
6993  break;
6994  }
6995 
6997  {
6998  std::advance(m_it.array_iterator, 1);
6999  break;
7000  }
7001 
7002  default:
7003  {
7004  ++m_it.primitive_iterator;
7005  break;
7006  }
7007  }
7008 
7009  return *this;
7010  }
7011 
7017  {
7018  auto result = *this;
7019  --(*this);
7020  return result;
7021  }
7022 
7028  {
7029  assert(m_object != nullptr);
7030 
7031  switch (m_object->m_type)
7032  {
7034  {
7035  std::advance(m_it.object_iterator, -1);
7036  break;
7037  }
7038 
7040  {
7041  std::advance(m_it.array_iterator, -1);
7042  break;
7043  }
7044 
7045  default:
7046  {
7047  --m_it.primitive_iterator;
7048  break;
7049  }
7050  }
7051 
7052  return *this;
7053  }
7054 
7059  bool operator==(const const_iterator& other) const
7060  {
7061  // if objects are not the same, the comparison is undefined
7062  if (m_object != other.m_object)
7063  {
7064  throw std::domain_error("cannot compare iterators of different containers");
7065  }
7066 
7067  assert(m_object != nullptr);
7068 
7069  switch (m_object->m_type)
7070  {
7072  {
7073  return (m_it.object_iterator == other.m_it.object_iterator);
7074  }
7075 
7077  {
7078  return (m_it.array_iterator == other.m_it.array_iterator);
7079  }
7080 
7081  default:
7082  {
7083  return (m_it.primitive_iterator == other.m_it.primitive_iterator);
7084  }
7085  }
7086  }
7087 
7092  bool operator!=(const const_iterator& other) const
7093  {
7094  return not operator==(other);
7095  }
7096 
7101  bool operator<(const const_iterator& other) const
7102  {
7103  // if objects are not the same, the comparison is undefined
7104  if (m_object != other.m_object)
7105  {
7106  throw std::domain_error("cannot compare iterators of different containers");
7107  }
7108 
7109  assert(m_object != nullptr);
7110 
7111  switch (m_object->m_type)
7112  {
7114  {
7115  throw std::domain_error("cannot compare order of object iterators");
7116  }
7117 
7119  {
7120  return (m_it.array_iterator < other.m_it.array_iterator);
7121  }
7122 
7123  default:
7124  {
7125  return (m_it.primitive_iterator < other.m_it.primitive_iterator);
7126  }
7127  }
7128  }
7129 
7134  bool operator<=(const const_iterator& other) const
7135  {
7136  return not other.operator < (*this);
7137  }
7138 
7143  bool operator>(const const_iterator& other) const
7144  {
7145  return not operator<=(other);
7146  }
7147 
7152  bool operator>=(const const_iterator& other) const
7153  {
7154  return not operator<(other);
7155  }
7156 
7162  {
7163  assert(m_object != nullptr);
7164 
7165  switch (m_object->m_type)
7166  {
7168  {
7169  throw std::domain_error("cannot use offsets with object iterators");
7170  }
7171 
7173  {
7174  std::advance(m_it.array_iterator, i);
7175  break;
7176  }
7177 
7178  default:
7179  {
7180  m_it.primitive_iterator += i;
7181  break;
7182  }
7183  }
7184 
7185  return *this;
7186  }
7187 
7193  {
7194  return operator+=(-i);
7195  }
7196 
7202  {
7203  auto result = *this;
7204  result += i;
7205  return result;
7206  }
7207 
7213  {
7214  auto result = *this;
7215  result -= i;
7216  return result;
7217  }
7218 
7224  {
7225  assert(m_object != nullptr);
7226 
7227  switch (m_object->m_type)
7228  {
7230  {
7231  throw std::domain_error("cannot use offsets with object iterators");
7232  }
7233 
7235  {
7236  return m_it.array_iterator - other.m_it.array_iterator;
7237  }
7238 
7239  default:
7240  {
7241  return m_it.primitive_iterator - other.m_it.primitive_iterator;
7242  }
7243  }
7244  }
7245 
7251  {
7252  assert(m_object != nullptr);
7253 
7254  switch (m_object->m_type)
7255  {
7257  {
7258  throw std::domain_error("cannot use operator[] for object iterators");
7259  }
7260 
7262  {
7263  return *std::next(m_it.array_iterator, n);
7264  }
7265 
7267  {
7268  throw std::out_of_range("cannot get value");
7269  }
7270 
7271  default:
7272  {
7273  if (m_it.primitive_iterator == -n)
7274  {
7275  return *m_object;
7276  }
7277  else
7278  {
7279  throw std::out_of_range("cannot get value");
7280  }
7281  }
7282  }
7283  }
7284 
7289  typename object_t::key_type key() const
7290  {
7291  assert(m_object != nullptr);
7292 
7293  if (m_object->is_object())
7294  {
7295  return m_it.object_iterator->first;
7296  }
7297  else
7298  {
7299  throw std::domain_error("cannot use key() for non-object iterators");
7300  }
7301  }
7302 
7308  {
7309  return operator*();
7310  }
7311 
7312  private:
7314  pointer m_object = nullptr;
7316  internal_iterator m_it = internal_iterator();
7317  };
7318 
7331  class iterator : public const_iterator
7332  {
7333  public:
7335  using pointer = typename basic_json::pointer;
7337 
7339  iterator() = default;
7340 
7342  explicit iterator(pointer object) noexcept
7343  : base_iterator(object)
7344  {}
7345 
7347  iterator(const iterator& other) noexcept
7348  : base_iterator(other)
7349  {}
7350 
7352  iterator& operator=(iterator other) noexcept(
7353  std::is_nothrow_move_constructible<pointer>::value and
7354  std::is_nothrow_move_assignable<pointer>::value and
7355  std::is_nothrow_move_constructible<internal_iterator>::value and
7356  std::is_nothrow_move_assignable<internal_iterator>::value
7357  )
7358  {
7359  base_iterator::operator=(other);
7360  return *this;
7361  }
7362 
7365  {
7366  return const_cast<reference>(base_iterator::operator*());
7367  }
7368 
7371  {
7372  return const_cast<pointer>(base_iterator::operator->());
7373  }
7374 
7377  {
7378  iterator result = *this;
7379  base_iterator::operator++();
7380  return result;
7381  }
7382 
7385  {
7386  base_iterator::operator++();
7387  return *this;
7388  }
7389 
7392  {
7393  iterator result = *this;
7394  base_iterator::operator--();
7395  return result;
7396  }
7397 
7400  {
7401  base_iterator::operator--();
7402  return *this;
7403  }
7404 
7407  {
7408  base_iterator::operator+=(i);
7409  return *this;
7410  }
7411 
7414  {
7415  base_iterator::operator-=(i);
7416  return *this;
7417  }
7418 
7421  {
7422  auto result = *this;
7423  result += i;
7424  return result;
7425  }
7426 
7429  {
7430  auto result = *this;
7431  result -= i;
7432  return result;
7433  }
7434 
7436  difference_type operator-(const iterator& other) const
7437  {
7438  return base_iterator::operator-(other);
7439  }
7440 
7443  {
7444  return const_cast<reference>(base_iterator::operator[](n));
7445  }
7446 
7449  {
7450  return const_cast<reference>(base_iterator::value());
7451  }
7452  };
7453 
7471  template<typename Base>
7472  class json_reverse_iterator : public std::reverse_iterator<Base>
7473  {
7474  public:
7476  using base_iterator = std::reverse_iterator<Base>;
7478  using reference = typename Base::reference;
7479 
7481  json_reverse_iterator(const typename base_iterator::iterator_type& it) noexcept
7482  : base_iterator(it)
7483  {}
7484 
7487  : base_iterator(it)
7488  {}
7489 
7492  {
7493  return base_iterator::operator++(1);
7494  }
7495 
7498  {
7499  base_iterator::operator++();
7500  return *this;
7501  }
7502 
7505  {
7506  return base_iterator::operator--(1);
7507  }
7508 
7511  {
7512  base_iterator::operator--();
7513  return *this;
7514  }
7515 
7518  {
7519  base_iterator::operator+=(i);
7520  return *this;
7521  }
7522 
7525  {
7526  auto result = *this;
7527  result += i;
7528  return result;
7529  }
7530 
7533  {
7534  auto result = *this;
7535  result -= i;
7536  return result;
7537  }
7538 
7541  {
7542  return this->base() - other.base();
7543  }
7544 
7547  {
7548  return *(this->operator+(n));
7549  }
7550 
7552  typename object_t::key_type key() const
7553  {
7554  auto it = --this->base();
7555  return it.key();
7556  }
7557 
7560  {
7561  auto it = --this->base();
7562  return it.operator * ();
7563  }
7564  };
7565 
7566 
7567  private:
7569  // lexer and parser //
7571 
7579  class lexer
7580  {
7581  public:
7583  enum class token_type
7584  {
7585  uninitialized,
7586  literal_true,
7587  literal_false,
7588  literal_null,
7589  value_string,
7590  value_number,
7591  begin_array,
7592  begin_object,
7593  end_array,
7594  end_object,
7595  name_separator,
7596  value_separator,
7597  parse_error,
7598  end_of_input
7599  };
7600 
7602  using lexer_char_t = unsigned char;
7603 
7605  lexer(const lexer_char_t* buff, const size_t len) noexcept
7606  : m_content(buff)
7607  {
7608  assert(m_content != nullptr);
7609  m_start = m_cursor = m_content;
7610  m_limit = m_content + len;
7611  }
7612 
7614  explicit lexer(std::istream& s)
7615  : m_stream(&s), m_line_buffer()
7616  {
7617  // fill buffer
7618  fill_line_buffer();
7619  }
7620 
7621  // switch off unwanted functions (due to pointer members)
7622  lexer() = delete;
7623  lexer(const lexer&) = delete;
7624  lexer operator=(const lexer&) = delete;
7625 
7649  static string_t to_unicode(const std::size_t codepoint1,
7650  const std::size_t codepoint2 = 0)
7651  {
7652  // calculate the code point from the given code points
7653  std::size_t codepoint = codepoint1;
7654 
7655  // check if codepoint1 is a high surrogate
7656  if (codepoint1 >= 0xD800 and codepoint1 <= 0xDBFF)
7657  {
7658  // check if codepoint2 is a low surrogate
7659  if (codepoint2 >= 0xDC00 and codepoint2 <= 0xDFFF)
7660  {
7661  codepoint =
7662  // high surrogate occupies the most significant 22 bits
7663  (codepoint1 << 10)
7664  // low surrogate occupies the least significant 15 bits
7665  + codepoint2
7666  // there is still the 0xD800, 0xDC00 and 0x10000 noise
7667  // in the result so we have to subtract with:
7668  // (0xD800 << 10) + DC00 - 0x10000 = 0x35FDC00
7669  - 0x35FDC00;
7670  }
7671  else
7672  {
7673  throw std::invalid_argument("missing or wrong low surrogate");
7674  }
7675  }
7676 
7677  string_t result;
7678 
7679  if (codepoint < 0x80)
7680  {
7681  // 1-byte characters: 0xxxxxxx (ASCII)
7682  result.append(1, static_cast<typename string_t::value_type>(codepoint));
7683  }
7684  else if (codepoint <= 0x7ff)
7685  {
7686  // 2-byte characters: 110xxxxx 10xxxxxx
7687  result.append(1, static_cast<typename string_t::value_type>(0xC0 | ((codepoint >> 6) & 0x1F)));
7688  result.append(1, static_cast<typename string_t::value_type>(0x80 | (codepoint & 0x3F)));
7689  }
7690  else if (codepoint <= 0xffff)
7691  {
7692  // 3-byte characters: 1110xxxx 10xxxxxx 10xxxxxx
7693  result.append(1, static_cast<typename string_t::value_type>(0xE0 | ((codepoint >> 12) & 0x0F)));
7694  result.append(1, static_cast<typename string_t::value_type>(0x80 | ((codepoint >> 6) & 0x3F)));
7695  result.append(1, static_cast<typename string_t::value_type>(0x80 | (codepoint & 0x3F)));
7696  }
7697  else if (codepoint <= 0x10ffff)
7698  {
7699  // 4-byte characters: 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
7700  result.append(1, static_cast<typename string_t::value_type>(0xF0 | ((codepoint >> 18) & 0x07)));
7701  result.append(1, static_cast<typename string_t::value_type>(0x80 | ((codepoint >> 12) & 0x3F)));
7702  result.append(1, static_cast<typename string_t::value_type>(0x80 | ((codepoint >> 6) & 0x3F)));
7703  result.append(1, static_cast<typename string_t::value_type>(0x80 | (codepoint & 0x3F)));
7704  }
7705  else
7706  {
7707  throw std::out_of_range("code points above 0x10FFFF are invalid");
7708  }
7709 
7710  return result;
7711  }
7712 
7714  static std::string token_type_name(const token_type t)
7715  {
7716  switch (t)
7717  {
7718  case token_type::uninitialized:
7719  return "<uninitialized>";
7720  case token_type::literal_true:
7721  return "true literal";
7722  case token_type::literal_false:
7723  return "false literal";
7724  case token_type::literal_null:
7725  return "null literal";
7726  case token_type::value_string:
7727  return "string literal";
7728  case token_type::value_number:
7729  return "number literal";
7730  case token_type::begin_array:
7731  return "'['";
7732  case token_type::begin_object:
7733  return "'{'";
7734  case token_type::end_array:
7735  return "']'";
7736  case token_type::end_object:
7737  return "'}'";
7738  case token_type::name_separator:
7739  return "':'";
7740  case token_type::value_separator:
7741  return "','";
7742  case token_type::parse_error:
7743  return "<parse error>";
7744  case token_type::end_of_input:
7745  return "end of input";
7746  default:
7747  {
7748  // catch non-enum values
7749  return "unknown token"; // LCOV_EXCL_LINE
7750  }
7751  }
7752  }
7753 
7775  token_type scan()
7776  {
7777  while (true)
7778  {
7779  // pointer for backtracking information
7780  m_marker = nullptr;
7781 
7782  // remember the begin of the token
7783  m_start = m_cursor;
7784  assert(m_start != nullptr);
7785 
7786 
7787  {
7788  lexer_char_t yych;
7789  unsigned int yyaccept = 0;
7790  static const unsigned char yybm[] = {
7791  0, 0, 0, 0, 0, 0, 0, 0,
7792  0, 32, 32, 0, 0, 32, 0, 0,
7793  0, 0, 0, 0, 0, 0, 0, 0,
7794  0, 0, 0, 0, 0, 0, 0, 0,
7795  160, 128, 0, 128, 128, 128, 128, 128,
7796  128, 128, 128, 128, 128, 128, 128, 128,
7797  192, 192, 192, 192, 192, 192, 192, 192,
7798  192, 192, 128, 128, 128, 128, 128, 128,
7799  128, 128, 128, 128, 128, 128, 128, 128,
7800  128, 128, 128, 128, 128, 128, 128, 128,
7801  128, 128, 128, 128, 128, 128, 128, 128,
7802  128, 128, 128, 128, 0, 128, 128, 128,
7803  128, 128, 128, 128, 128, 128, 128, 128,
7804  128, 128, 128, 128, 128, 128, 128, 128,
7805  128, 128, 128, 128, 128, 128, 128, 128,
7806  128, 128, 128, 128, 128, 128, 128, 128,
7807  128, 128, 128, 128, 128, 128, 128, 128,
7808  128, 128, 128, 128, 128, 128, 128, 128,
7809  128, 128, 128, 128, 128, 128, 128, 128,
7810  128, 128, 128, 128, 128, 128, 128, 128,
7811  128, 128, 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, 128, 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  128, 128, 128, 128, 128, 128, 128, 128,
7821  128, 128, 128, 128, 128, 128, 128, 128,
7822  128, 128, 128, 128, 128, 128, 128, 128,
7823  };
7824  if ((m_limit - m_cursor) < 5) fill_line_buffer();
7825  yych = *m_cursor;
7826  if (yybm[0+yych] & 32) {
7827  goto basic_json_parser_6;
7828  }
7829  if (yych <= '\\') {
7830  if (yych <= '-') {
7831  if (yych <= '"') {
7832  if (yych <= 0x00) goto basic_json_parser_2;
7833  if (yych <= '!') goto basic_json_parser_4;
7834  goto basic_json_parser_9;
7835  } else {
7836  if (yych <= '+') goto basic_json_parser_4;
7837  if (yych <= ',') goto basic_json_parser_10;
7838  goto basic_json_parser_12;
7839  }
7840  } else {
7841  if (yych <= '9') {
7842  if (yych <= '/') goto basic_json_parser_4;
7843  if (yych <= '0') goto basic_json_parser_13;
7844  goto basic_json_parser_15;
7845  } else {
7846  if (yych <= ':') goto basic_json_parser_17;
7847  if (yych == '[') goto basic_json_parser_19;
7848  goto basic_json_parser_4;
7849  }
7850  }
7851  } else {
7852  if (yych <= 't') {
7853  if (yych <= 'f') {
7854  if (yych <= ']') goto basic_json_parser_21;
7855  if (yych <= 'e') goto basic_json_parser_4;
7856  goto basic_json_parser_23;
7857  } else {
7858  if (yych == 'n') goto basic_json_parser_24;
7859  if (yych <= 's') goto basic_json_parser_4;
7860  goto basic_json_parser_25;
7861  }
7862  } else {
7863  if (yych <= '|') {
7864  if (yych == '{') goto basic_json_parser_26;
7865  goto basic_json_parser_4;
7866  } else {
7867  if (yych <= '}') goto basic_json_parser_28;
7868  if (yych == 0xEF) goto basic_json_parser_30;
7869  goto basic_json_parser_4;
7870  }
7871  }
7872  }
7873 basic_json_parser_2:
7874  ++m_cursor;
7875  { last_token_type = token_type::end_of_input; break; }
7876 basic_json_parser_4:
7877  ++m_cursor;
7878 basic_json_parser_5:
7879  { last_token_type = token_type::parse_error; break; }
7880 basic_json_parser_6:
7881  ++m_cursor;
7882  if (m_limit <= m_cursor) fill_line_buffer();
7883  yych = *m_cursor;
7884  if (yybm[0+yych] & 32) {
7885  goto basic_json_parser_6;
7886  }
7887  { continue; }
7888 basic_json_parser_9:
7889  yyaccept = 0;
7890  yych = *(m_marker = ++m_cursor);
7891  if (yych <= 0x1F) goto basic_json_parser_5;
7892  goto basic_json_parser_32;
7893 basic_json_parser_10:
7894  ++m_cursor;
7895  { last_token_type = token_type::value_separator; break; }
7896 basic_json_parser_12:
7897  yych = *++m_cursor;
7898  if (yych <= '/') goto basic_json_parser_5;
7899  if (yych <= '0') goto basic_json_parser_13;
7900  if (yych <= '9') goto basic_json_parser_15;
7901  goto basic_json_parser_5;
7902 basic_json_parser_13:
7903  yyaccept = 1;
7904  yych = *(m_marker = ++m_cursor);
7905  if (yych <= 'D') {
7906  if (yych == '.') goto basic_json_parser_37;
7907  } else {
7908  if (yych <= 'E') goto basic_json_parser_38;
7909  if (yych == 'e') goto basic_json_parser_38;
7910  }
7911 basic_json_parser_14:
7912  { last_token_type = token_type::value_number; break; }
7913 basic_json_parser_15:
7914  yyaccept = 1;
7915  m_marker = ++m_cursor;
7916  if ((m_limit - m_cursor) < 3) fill_line_buffer();
7917  yych = *m_cursor;
7918  if (yybm[0+yych] & 64) {
7919  goto basic_json_parser_15;
7920  }
7921  if (yych <= 'D') {
7922  if (yych == '.') goto basic_json_parser_37;
7923  goto basic_json_parser_14;
7924  } else {
7925  if (yych <= 'E') goto basic_json_parser_38;
7926  if (yych == 'e') goto basic_json_parser_38;
7927  goto basic_json_parser_14;
7928  }
7929 basic_json_parser_17:
7930  ++m_cursor;
7931  { last_token_type = token_type::name_separator; break; }
7932 basic_json_parser_19:
7933  ++m_cursor;
7934  { last_token_type = token_type::begin_array; break; }
7935 basic_json_parser_21:
7936  ++m_cursor;
7937  { last_token_type = token_type::end_array; break; }
7938 basic_json_parser_23:
7939  yyaccept = 0;
7940  yych = *(m_marker = ++m_cursor);
7941  if (yych == 'a') goto basic_json_parser_39;
7942  goto basic_json_parser_5;
7943 basic_json_parser_24:
7944  yyaccept = 0;
7945  yych = *(m_marker = ++m_cursor);
7946  if (yych == 'u') goto basic_json_parser_40;
7947  goto basic_json_parser_5;
7948 basic_json_parser_25:
7949  yyaccept = 0;
7950  yych = *(m_marker = ++m_cursor);
7951  if (yych == 'r') goto basic_json_parser_41;
7952  goto basic_json_parser_5;
7953 basic_json_parser_26:
7954  ++m_cursor;
7955  { last_token_type = token_type::begin_object; break; }
7956 basic_json_parser_28:
7957  ++m_cursor;
7958  { last_token_type = token_type::end_object; break; }
7959 basic_json_parser_30:
7960  yyaccept = 0;
7961  yych = *(m_marker = ++m_cursor);
7962  if (yych == 0xBB) goto basic_json_parser_42;
7963  goto basic_json_parser_5;
7964 basic_json_parser_31:
7965  ++m_cursor;
7966  if (m_limit <= m_cursor) fill_line_buffer();
7967  yych = *m_cursor;
7968 basic_json_parser_32:
7969  if (yybm[0+yych] & 128) {
7970  goto basic_json_parser_31;
7971  }
7972  if (yych <= 0x1F) goto basic_json_parser_33;
7973  if (yych <= '"') goto basic_json_parser_34;
7974  goto basic_json_parser_36;
7975 basic_json_parser_33:
7976  m_cursor = m_marker;
7977  if (yyaccept == 0) {
7978  goto basic_json_parser_5;
7979  } else {
7980  goto basic_json_parser_14;
7981  }
7982 basic_json_parser_34:
7983  ++m_cursor;
7984  { last_token_type = token_type::value_string; break; }
7985 basic_json_parser_36:
7986  ++m_cursor;
7987  if (m_limit <= m_cursor) fill_line_buffer();
7988  yych = *m_cursor;
7989  if (yych <= 'e') {
7990  if (yych <= '/') {
7991  if (yych == '"') goto basic_json_parser_31;
7992  if (yych <= '.') goto basic_json_parser_33;
7993  goto basic_json_parser_31;
7994  } else {
7995  if (yych <= '\\') {
7996  if (yych <= '[') goto basic_json_parser_33;
7997  goto basic_json_parser_31;
7998  } else {
7999  if (yych == 'b') goto basic_json_parser_31;
8000  goto basic_json_parser_33;
8001  }
8002  }
8003  } else {
8004  if (yych <= 'q') {
8005  if (yych <= 'f') goto basic_json_parser_31;
8006  if (yych == 'n') goto basic_json_parser_31;
8007  goto basic_json_parser_33;
8008  } else {
8009  if (yych <= 's') {
8010  if (yych <= 'r') goto basic_json_parser_31;
8011  goto basic_json_parser_33;
8012  } else {
8013  if (yych <= 't') goto basic_json_parser_31;
8014  if (yych <= 'u') goto basic_json_parser_43;
8015  goto basic_json_parser_33;
8016  }
8017  }
8018  }
8019 basic_json_parser_37:
8020  yych = *++m_cursor;
8021  if (yych <= '/') goto basic_json_parser_33;
8022  if (yych <= '9') goto basic_json_parser_44;
8023  goto basic_json_parser_33;
8024 basic_json_parser_38:
8025  yych = *++m_cursor;
8026  if (yych <= ',') {
8027  if (yych == '+') goto basic_json_parser_46;
8028  goto basic_json_parser_33;
8029  } else {
8030  if (yych <= '-') goto basic_json_parser_46;
8031  if (yych <= '/') goto basic_json_parser_33;
8032  if (yych <= '9') goto basic_json_parser_47;
8033  goto basic_json_parser_33;
8034  }
8035 basic_json_parser_39:
8036  yych = *++m_cursor;
8037  if (yych == 'l') goto basic_json_parser_49;
8038  goto basic_json_parser_33;
8039 basic_json_parser_40:
8040  yych = *++m_cursor;
8041  if (yych == 'l') goto basic_json_parser_50;
8042  goto basic_json_parser_33;
8043 basic_json_parser_41:
8044  yych = *++m_cursor;
8045  if (yych == 'u') goto basic_json_parser_51;
8046  goto basic_json_parser_33;
8047 basic_json_parser_42:
8048  yych = *++m_cursor;
8049  if (yych == 0xBF) goto basic_json_parser_52;
8050  goto basic_json_parser_33;
8051 basic_json_parser_43:
8052  ++m_cursor;
8053  if (m_limit <= m_cursor) fill_line_buffer();
8054  yych = *m_cursor;
8055  if (yych <= '@') {
8056  if (yych <= '/') goto basic_json_parser_33;
8057  if (yych <= '9') goto basic_json_parser_54;
8058  goto basic_json_parser_33;
8059  } else {
8060  if (yych <= 'F') goto basic_json_parser_54;
8061  if (yych <= '`') goto basic_json_parser_33;
8062  if (yych <= 'f') goto basic_json_parser_54;
8063  goto basic_json_parser_33;
8064  }
8065 basic_json_parser_44:
8066  yyaccept = 1;
8067  m_marker = ++m_cursor;
8068  if ((m_limit - m_cursor) < 3) fill_line_buffer();
8069  yych = *m_cursor;
8070  if (yych <= 'D') {
8071  if (yych <= '/') goto basic_json_parser_14;
8072  if (yych <= '9') goto basic_json_parser_44;
8073  goto basic_json_parser_14;
8074  } else {
8075  if (yych <= 'E') goto basic_json_parser_38;
8076  if (yych == 'e') goto basic_json_parser_38;
8077  goto basic_json_parser_14;
8078  }
8079 basic_json_parser_46:
8080  yych = *++m_cursor;
8081  if (yych <= '/') goto basic_json_parser_33;
8082  if (yych >= ':') goto basic_json_parser_33;
8083 basic_json_parser_47:
8084  ++m_cursor;
8085  if (m_limit <= m_cursor) fill_line_buffer();
8086  yych = *m_cursor;
8087  if (yych <= '/') goto basic_json_parser_14;
8088  if (yych <= '9') goto basic_json_parser_47;
8089  goto basic_json_parser_14;
8090 basic_json_parser_49:
8091  yych = *++m_cursor;
8092  if (yych == 's') goto basic_json_parser_55;
8093  goto basic_json_parser_33;
8094 basic_json_parser_50:
8095  yych = *++m_cursor;
8096  if (yych == 'l') goto basic_json_parser_56;
8097  goto basic_json_parser_33;
8098 basic_json_parser_51:
8099  yych = *++m_cursor;
8100  if (yych == 'e') goto basic_json_parser_58;
8101  goto basic_json_parser_33;
8102 basic_json_parser_52:
8103  ++m_cursor;
8104  { continue; }
8105 basic_json_parser_54:
8106  ++m_cursor;
8107  if (m_limit <= m_cursor) fill_line_buffer();
8108  yych = *m_cursor;
8109  if (yych <= '@') {
8110  if (yych <= '/') goto basic_json_parser_33;
8111  if (yych <= '9') goto basic_json_parser_60;
8112  goto basic_json_parser_33;
8113  } else {
8114  if (yych <= 'F') goto basic_json_parser_60;
8115  if (yych <= '`') goto basic_json_parser_33;
8116  if (yych <= 'f') goto basic_json_parser_60;
8117  goto basic_json_parser_33;
8118  }
8119 basic_json_parser_55:
8120  yych = *++m_cursor;
8121  if (yych == 'e') goto basic_json_parser_61;
8122  goto basic_json_parser_33;
8123 basic_json_parser_56:
8124  ++m_cursor;
8125  { last_token_type = token_type::literal_null; break; }
8126 basic_json_parser_58:
8127  ++m_cursor;
8128  { last_token_type = token_type::literal_true; break; }
8129 basic_json_parser_60:
8130  ++m_cursor;
8131  if (m_limit <= m_cursor) fill_line_buffer();
8132  yych = *m_cursor;
8133  if (yych <= '@') {
8134  if (yych <= '/') goto basic_json_parser_33;
8135  if (yych <= '9') goto basic_json_parser_63;
8136  goto basic_json_parser_33;
8137  } else {
8138  if (yych <= 'F') goto basic_json_parser_63;
8139  if (yych <= '`') goto basic_json_parser_33;
8140  if (yych <= 'f') goto basic_json_parser_63;
8141  goto basic_json_parser_33;
8142  }
8143 basic_json_parser_61:
8144  ++m_cursor;
8145  { last_token_type = token_type::literal_false; break; }
8146 basic_json_parser_63:
8147  ++m_cursor;
8148  if (m_limit <= m_cursor) fill_line_buffer();
8149  yych = *m_cursor;
8150  if (yych <= '@') {
8151  if (yych <= '/') goto basic_json_parser_33;
8152  if (yych <= '9') goto basic_json_parser_31;
8153  goto basic_json_parser_33;
8154  } else {
8155  if (yych <= 'F') goto basic_json_parser_31;
8156  if (yych <= '`') goto basic_json_parser_33;
8157  if (yych <= 'f') goto basic_json_parser_31;
8158  goto basic_json_parser_33;
8159  }
8160  }
8161 
8162  }
8163 
8164  return last_token_type;
8165  }
8166 
8195  void fill_line_buffer()
8196  {
8197  // number of processed characters (p)
8198  const auto offset_start = m_start - m_content;
8199  // offset for m_marker wrt. to m_start
8200  const auto offset_marker = (m_marker == nullptr) ? 0 : m_marker - m_start;
8201  // number of unprocessed characters (u)
8202  const auto offset_cursor = m_cursor - m_start;
8203 
8204  // no stream is used or end of file is reached
8205  if (m_stream == nullptr or not * m_stream)
8206  {
8207  // copy unprocessed characters to line buffer
8208  m_line_buffer.clear();
8209  for (m_cursor = m_start; m_cursor != m_limit; ++m_cursor)
8210  {
8211  m_line_buffer.append(1, static_cast<const char>(*m_cursor));
8212  }
8213 
8214  // append 5 characters (size of longest keyword "false") to
8215  // make sure that there is sufficient space between m_cursor
8216  // and m_limit
8217  m_line_buffer.append(5, '\0');
8218  }
8219  else
8220  {
8221  // delete processed characters from line buffer
8222  m_line_buffer.erase(0, static_cast<size_t>(offset_start));
8223  // read next line from input stream
8224  std::string line;
8225  std::getline(*m_stream, line);
8226  // add line with newline symbol to the line buffer
8227  m_line_buffer += "\n" + line;
8228  }
8229 
8230  // set pointers
8231  m_content = reinterpret_cast<const lexer_char_t*>(m_line_buffer.c_str());
8232  assert(m_content != nullptr);
8233  m_start = m_content;
8234  m_marker = m_start + offset_marker;
8235  m_cursor = m_start + offset_cursor;
8236  m_limit = m_start + m_line_buffer.size();
8237  }
8238 
8240  string_t get_token_string() const
8241  {
8242  assert(m_start != nullptr);
8243  return string_t(reinterpret_cast<typename string_t::const_pointer>(m_start),
8244  static_cast<size_t>(m_cursor - m_start));
8245  }
8246 
8304  string_t get_string() const
8305  {
8306  assert(m_cursor - m_start >= 2);
8307 
8308  string_t result;
8309  result.reserve(static_cast<size_t>(m_cursor - m_start - 2));
8310 
8311  // iterate the result between the quotes
8312  for (const lexer_char_t* i = m_start + 1; i < m_cursor - 1; ++i)
8313  {
8314  // process escaped characters
8315  if (*i == '\\')
8316  {
8317  // read next character
8318  ++i;
8319 
8320  switch (*i)
8321  {
8322  // the default escapes
8323  case 't':
8324  {
8325  result += "\t";
8326  break;
8327  }
8328  case 'b':
8329  {
8330  result += "\b";
8331  break;
8332  }
8333  case 'f':
8334  {
8335  result += "\f";
8336  break;
8337  }
8338  case 'n':
8339  {
8340  result += "\n";
8341  break;
8342  }
8343  case 'r':
8344  {
8345  result += "\r";
8346  break;
8347  }
8348  case '\\':
8349  {
8350  result += "\\";
8351  break;
8352  }
8353  case '/':
8354  {
8355  result += "/";
8356  break;
8357  }
8358  case '"':
8359  {
8360  result += "\"";
8361  break;
8362  }
8363 
8364  // unicode
8365  case 'u':
8366  {
8367  // get code xxxx from uxxxx
8368  auto codepoint = std::strtoul(std::string(reinterpret_cast<typename string_t::const_pointer>(i + 1),
8369  4).c_str(), nullptr, 16);
8370 
8371  // check if codepoint is a high surrogate
8372  if (codepoint >= 0xD800 and codepoint <= 0xDBFF)
8373  {
8374  // make sure there is a subsequent unicode
8375  if ((i + 6 >= m_limit) or * (i + 5) != '\\' or * (i + 6) != 'u')
8376  {
8377  throw std::invalid_argument("missing low surrogate");
8378  }
8379 
8380  // get code yyyy from uxxxx\uyyyy
8381  auto codepoint2 = std::strtoul(std::string(reinterpret_cast<typename string_t::const_pointer>
8382  (i + 7), 4).c_str(), nullptr, 16);
8383  result += to_unicode(codepoint, codepoint2);
8384  // skip the next 10 characters (xxxx\uyyyy)
8385  i += 10;
8386  }
8387  else
8388  {
8389  // add unicode character(s)
8390  result += to_unicode(codepoint);
8391  // skip the next four characters (xxxx)
8392  i += 4;
8393  }
8394  break;
8395  }
8396  }
8397  }
8398  else
8399  {
8400  // all other characters are just copied to the end of the
8401  // string
8402  result.append(1, static_cast<typename string_t::value_type>(*i));
8403  }
8404  }
8405 
8406  return result;
8407  }
8408 
8424  long double str_to_float_t(long double* /* type */, char** endptr) const
8425  {
8426  return std::strtold(reinterpret_cast<typename string_t::const_pointer>(m_start), endptr);
8427  }
8428 
8444  double str_to_float_t(double* /* type */, char** endptr) const
8445  {
8446  return std::strtod(reinterpret_cast<typename string_t::const_pointer>(m_start), endptr);
8447  }
8448 
8464  float str_to_float_t(float* /* type */, char** endptr) const
8465  {
8466  return std::strtof(reinterpret_cast<typename string_t::const_pointer>(m_start), endptr);
8467  }
8468 
8490  void get_number(basic_json& result) const
8491  {
8492  assert(m_start != nullptr);
8493 
8494  const lexer::lexer_char_t* curptr = m_start;
8495 
8496  // accumulate the integer conversion result (unsigned for now)
8497  number_unsigned_t value = 0;
8498 
8499  // maximum absolute value of the relevant integer type
8500  number_unsigned_t max;
8501 
8502  // temporarily store the type to avoid unecessary bitfield access
8503  value_t type;
8504 
8505  // look for sign
8506  if (*curptr == '-')
8507  {
8508  type = value_t::number_integer;
8509  max = static_cast<uint64_t>((std::numeric_limits<number_integer_t>::max)()) + 1;
8510  curptr++;
8511  }
8512  else
8513  {
8514  type = value_t::number_unsigned;
8515  max = static_cast<uint64_t>((std::numeric_limits<number_unsigned_t>::max)());
8516  }
8517 
8518  // count the significant figures
8519  for (; curptr < m_cursor; curptr++)
8520  {
8521  // quickly skip tests if a digit
8522  if (*curptr < '0' || *curptr > '9')
8523  {
8524  if (*curptr == '.')
8525  {
8526  // don't count '.' but change to float
8527  type = value_t::number_float;
8528  continue;
8529  }
8530  // assume exponent (if not then will fail parse): change to
8531  // float, stop counting and record exponent details
8532  type = value_t::number_float;
8533  break;
8534  }
8535 
8536  // skip if definitely not an integer
8537  if (type != value_t::number_float)
8538  {
8539  // multiply last value by ten and add the new digit
8540  auto temp = value * 10 + *curptr - '0';
8541 
8542  // test for overflow
8543  if (temp < value || temp > max)
8544  {
8545  // overflow
8546  type = value_t::number_float;
8547  }
8548  else
8549  {
8550  // no overflow - save it
8551  value = temp;
8552  }
8553  }
8554  }
8555 
8556  // save the value (if not a float)
8557  if (type == value_t::number_unsigned)
8558  {
8559  result.m_value.number_unsigned = value;
8560  }
8561  else if (type == value_t::number_integer)
8562  {
8563  result.m_value.number_integer = -static_cast<number_integer_t>(value);
8564  }
8565  else
8566  {
8567  // parse with strtod
8568  result.m_value.number_float = str_to_float_t(static_cast<number_float_t*>(nullptr), NULL);
8569  }
8570 
8571  // save the type
8572  result.m_type = type;
8573  }
8574 
8575  private:
8577  std::istream* m_stream = nullptr;
8579  string_t m_line_buffer {};
8581  const lexer_char_t* m_content = nullptr;
8583  const lexer_char_t* m_start = nullptr;
8585  const lexer_char_t* m_marker = nullptr;
8587  const lexer_char_t* m_cursor = nullptr;
8589  const lexer_char_t* m_limit = nullptr;
8591  token_type last_token_type = token_type::end_of_input;
8592  };
8593 
8599  class parser
8600  {
8601  public:
8603  parser(const char* buff, const parser_callback_t cb = nullptr)
8604  : callback(cb),
8605  m_lexer(reinterpret_cast<const typename lexer::lexer_char_t*>(buff), strlen(buff))
8606  {}
8607 
8609  parser(std::istream& is, const parser_callback_t cb = nullptr)
8610  : callback(cb), m_lexer(is)
8611  {}
8612 
8614  template<class IteratorType, typename std::enable_if<
8615  std::is_same<typename std::iterator_traits<IteratorType>::iterator_category, std::random_access_iterator_tag>::value
8616  , int>::type
8617  = 0>
8618  parser(IteratorType first, IteratorType last, const parser_callback_t cb = nullptr)
8619  : callback(cb),
8620  m_lexer(reinterpret_cast<const typename lexer::lexer_char_t*>(&(*first)),
8621  static_cast<size_t>(std::distance(first, last)))
8622  {}
8623 
8625  basic_json parse()
8626  {
8627  // read first token
8628  get_token();
8629 
8630  basic_json result = parse_internal(true);
8631  result.assert_invariant();
8632 
8633  expect(lexer::token_type::end_of_input);
8634 
8635  // return parser result and replace it with null in case the
8636  // top-level value was discarded by the callback function
8637  return result.is_discarded() ? basic_json() : std::move(result);
8638  }
8639 
8640  private:
8642  basic_json parse_internal(bool keep)
8643  {
8644  auto result = basic_json(value_t::discarded);
8645 
8646  switch (last_token)
8647  {
8648  case lexer::token_type::begin_object:
8649  {
8650  if (keep and (not callback
8651  or ((keep = callback(depth++, parse_event_t::object_start, result)) != 0)))
8652  {
8653  // explicitly set result to object to cope with {}
8654  result.m_type = value_t::object;
8655  result.m_value = value_t::object;
8656  }
8657 
8658  // read next token
8659  get_token();
8660 
8661  // closing } -> we are done
8662  if (last_token == lexer::token_type::end_object)
8663  {
8664  get_token();
8665  if (keep and callback and not callback(--depth, parse_event_t::object_end, result))
8666  {
8667  result = basic_json(value_t::discarded);
8668  }
8669  return result;
8670  }
8671 
8672  // no comma is expected here
8673  unexpect(lexer::token_type::value_separator);
8674 
8675  // otherwise: parse key-value pairs
8676  do
8677  {
8678  // ugly, but could be fixed with loop reorganization
8679  if (last_token == lexer::token_type::value_separator)
8680  {
8681  get_token();
8682  }
8683 
8684  // store key
8685  expect(lexer::token_type::value_string);
8686  const auto key = m_lexer.get_string();
8687 
8688  bool keep_tag = false;
8689  if (keep)
8690  {
8691  if (callback)
8692  {
8693  basic_json k(key);
8694  keep_tag = callback(depth, parse_event_t::key, k);
8695  }
8696  else
8697  {
8698  keep_tag = true;
8699  }
8700  }
8701 
8702  // parse separator (:)
8703  get_token();
8704  expect(lexer::token_type::name_separator);
8705 
8706  // parse and add value
8707  get_token();
8708  auto value = parse_internal(keep);
8709  if (keep and keep_tag and not value.is_discarded())
8710  {
8711  result[key] = std::move(value);
8712  }
8713  }
8714  while (last_token == lexer::token_type::value_separator);
8715 
8716  // closing }
8717  expect(lexer::token_type::end_object);
8718  get_token();
8719  if (keep and callback and not callback(--depth, parse_event_t::object_end, result))
8720  {
8721  result = basic_json(value_t::discarded);
8722  }
8723 
8724  return result;
8725  }
8726 
8727  case lexer::token_type::begin_array:
8728  {
8729  if (keep and (not callback
8730  or ((keep = callback(depth++, parse_event_t::array_start, result)) != 0)))
8731  {
8732  // explicitly set result to object to cope with []
8733  result.m_type = value_t::array;
8734  result.m_value = value_t::array;
8735  }
8736 
8737  // read next token
8738  get_token();
8739 
8740  // closing ] -> we are done
8741  if (last_token == lexer::token_type::end_array)
8742  {
8743  get_token();
8744  if (callback and not callback(--depth, parse_event_t::array_end, result))
8745  {
8746  result = basic_json(value_t::discarded);
8747  }
8748  return result;
8749  }
8750 
8751  // no comma is expected here
8752  unexpect(lexer::token_type::value_separator);
8753 
8754  // otherwise: parse values
8755  do
8756  {
8757  // ugly, but could be fixed with loop reorganization
8758  if (last_token == lexer::token_type::value_separator)
8759  {
8760  get_token();
8761  }
8762 
8763  // parse value
8764  auto value = parse_internal(keep);
8765  if (keep and not value.is_discarded())
8766  {
8767  result.push_back(std::move(value));
8768  }
8769  }
8770  while (last_token == lexer::token_type::value_separator);
8771 
8772  // closing ]
8773  expect(lexer::token_type::end_array);
8774  get_token();
8775  if (keep and callback and not callback(--depth, parse_event_t::array_end, result))
8776  {
8777  result = basic_json(value_t::discarded);
8778  }
8779 
8780  return result;
8781  }
8782 
8783  case lexer::token_type::literal_null:
8784  {
8785  get_token();
8786  result.m_type = value_t::null;
8787  break;
8788  }
8789 
8790  case lexer::token_type::value_string:
8791  {
8792  const auto s = m_lexer.get_string();
8793  get_token();
8794  result = basic_json(s);
8795  break;
8796  }
8797 
8798  case lexer::token_type::literal_true:
8799  {
8800  get_token();
8801  result.m_type = value_t::boolean;
8802  result.m_value = true;
8803  break;
8804  }
8805 
8806  case lexer::token_type::literal_false:
8807  {
8808  get_token();
8809  result.m_type = value_t::boolean;
8810  result.m_value = false;
8811  break;
8812  }
8813 
8814  case lexer::token_type::value_number:
8815  {
8816  m_lexer.get_number(result);
8817  get_token();
8818  break;
8819  }
8820 
8821  default:
8822  {
8823  // the last token was unexpected
8824  unexpect(last_token);
8825  }
8826  }
8827 
8828  if (keep and callback and not callback(depth, parse_event_t::value, result))
8829  {
8830  result = basic_json(value_t::discarded);
8831  }
8832  return result;
8833  }
8834 
8836  typename lexer::token_type get_token()
8837  {
8838  last_token = m_lexer.scan();
8839  return last_token;
8840  }
8841 
8842  void expect(typename lexer::token_type t) const
8843  {
8844  if (t != last_token)
8845  {
8846  std::string error_msg = "parse error - unexpected ";
8847  error_msg += (last_token == lexer::token_type::parse_error ? ("'" + m_lexer.get_token_string() +
8848  "'") :
8849  lexer::token_type_name(last_token));
8850  error_msg += "; expected " + lexer::token_type_name(t);
8851  throw std::invalid_argument(error_msg);
8852  }
8853  }
8854 
8855  void unexpect(typename lexer::token_type t) const
8856  {
8857  if (t == last_token)
8858  {
8859  std::string error_msg = "parse error - unexpected ";
8860  error_msg += (last_token == lexer::token_type::parse_error ? ("'" + m_lexer.get_token_string() +
8861  "'") :
8862  lexer::token_type_name(last_token));
8863  throw std::invalid_argument(error_msg);
8864  }
8865  }
8866 
8867  private:
8869  int depth = 0;
8871  const parser_callback_t callback = nullptr;
8873  typename lexer::token_type last_token = lexer::token_type::uninitialized;
8875  lexer m_lexer;
8876  };
8877 
8878  public:
8891  {
8893  friend class basic_json;
8894 
8895  public:
8918  explicit json_pointer(const std::string& s = "")
8919  : reference_tokens(split(s))
8920  {}
8921 
8937  std::string to_string() const noexcept
8938  {
8939  return std::accumulate(reference_tokens.begin(),
8940  reference_tokens.end(), std::string{},
8941  [](const std::string & a, const std::string & b)
8942  {
8943  return a + "/" + escape(b);
8944  });
8945  }
8946 
8948  operator std::string() const
8949  {
8950  return to_string();
8951  }
8953  private:
8955  std::string pop_back()
8956  {
8957  if (is_root())
8958  {
8959  throw std::domain_error("JSON pointer has no parent");
8960  }
8961 
8962  auto last = reference_tokens.back();
8963  reference_tokens.pop_back();
8964  return last;
8965  }
8966 
8968  bool is_root() const
8969  {
8970  return reference_tokens.empty();
8971  }
8972 
8973  json_pointer top() const
8974  {
8975  if (is_root())
8976  {
8977  throw std::domain_error("JSON pointer has no parent");
8978  }
8979 
8980  json_pointer result = *this;
8981  result.reference_tokens = {reference_tokens[0]};
8982  return result;
8983  }
8984 
8990  reference get_and_create(reference j) const
8991  {
8992  pointer result = &j;
8993 
8994  // in case no reference tokens exist, return a reference to the
8995  // JSON value j which will be overwritten by a primitive value
8996  for (const auto& reference_token : reference_tokens)
8997  {
8998  switch (result->m_type)
8999  {
9000  case value_t::null:
9001  {
9002  if (reference_token == "0")
9003  {
9004  // start a new array if reference token is 0
9005  result = &result->operator[](0);
9006  }
9007  else
9008  {
9009  // start a new object otherwise
9010  result = &result->operator[](reference_token);
9011  }
9012  break;
9013  }
9014 
9015  case value_t::object:
9016  {
9017  // create an entry in the object
9018  result = &result->operator[](reference_token);
9019  break;
9020  }
9021 
9022  case value_t::array:
9023  {
9024  // create an entry in the array
9025  result = &result->operator[](static_cast<size_type>(std::stoi(reference_token)));
9026  break;
9027  }
9028 
9029  /*
9030  The following code is only reached if there exists a
9031  reference token _and_ the current value is primitive. In
9032  this case, we have an error situation, because primitive
9033  values may only occur as single value; that is, with an
9034  empty list of reference tokens.
9035  */
9036  default:
9037  {
9038  throw std::domain_error("invalid value to unflatten");
9039  }
9040  }
9041  }
9042 
9043  return *result;
9044  }
9045 
9059  reference get_unchecked(pointer ptr) const
9060  {
9061  for (const auto& reference_token : reference_tokens)
9062  {
9063  switch (ptr->m_type)
9064  {
9065  case value_t::object:
9066  {
9067  // use unchecked object access
9068  ptr = &ptr->operator[](reference_token);
9069  break;
9070  }
9071 
9072  case value_t::array:
9073  {
9074  // error condition (cf. RFC 6901, Sect. 4)
9075  if (reference_token.size() > 1 and reference_token[0] == '0')
9076  {
9077  throw std::domain_error("array index must not begin with '0'");
9078  }
9079 
9080  if (reference_token == "-")
9081  {
9082  // explicityly treat "-" as index beyond the end
9083  ptr = &ptr->operator[](ptr->m_value.array->size());
9084  }
9085  else
9086  {
9087  // convert array index to number; unchecked access
9088  ptr = &ptr->operator[](static_cast<size_type>(std::stoi(reference_token)));
9089  }
9090  break;
9091  }
9092 
9093  default:
9094  {
9095  throw std::out_of_range("unresolved reference token '" + reference_token + "'");
9096  }
9097  }
9098  }
9099 
9100  return *ptr;
9101  }
9102 
9103  reference get_checked(pointer ptr) const
9104  {
9105  for (const auto& reference_token : reference_tokens)
9106  {
9107  switch (ptr->m_type)
9108  {
9109  case value_t::object:
9110  {
9111  // note: at performs range check
9112  ptr = &ptr->at(reference_token);
9113  break;
9114  }
9115 
9116  case value_t::array:
9117  {
9118  if (reference_token == "-")
9119  {
9120  // "-" always fails the range check
9121  throw std::out_of_range("array index '-' (" +
9122  std::to_string(ptr->m_value.array->size()) +
9123  ") is out of range");
9124  }
9125 
9126  // error condition (cf. RFC 6901, Sect. 4)
9127  if (reference_token.size() > 1 and reference_token[0] == '0')
9128  {
9129  throw std::domain_error("array index must not begin with '0'");
9130  }
9131 
9132  // note: at performs range check
9133  ptr = &ptr->at(static_cast<size_type>(std::stoi(reference_token)));
9134  break;
9135  }
9136 
9137  default:
9138  {
9139  throw std::out_of_range("unresolved reference token '" + reference_token + "'");
9140  }
9141  }
9142  }
9143 
9144  return *ptr;
9145  }
9146 
9155  const_reference get_unchecked(const_pointer ptr) const
9156  {
9157  for (const auto& reference_token : reference_tokens)
9158  {
9159  switch (ptr->m_type)
9160  {
9161  case value_t::object:
9162  {
9163  // use unchecked object access
9164  ptr = &ptr->operator[](reference_token);
9165  break;
9166  }
9167 
9168  case value_t::array:
9169  {
9170  if (reference_token == "-")
9171  {
9172  // "-" cannot be used for const access
9173  throw std::out_of_range("array index '-' (" +
9174  std::to_string(ptr->m_value.array->size()) +
9175  ") is out of range");
9176  }
9177 
9178  // error condition (cf. RFC 6901, Sect. 4)
9179  if (reference_token.size() > 1 and reference_token[0] == '0')
9180  {
9181  throw std::domain_error("array index must not begin with '0'");
9182  }
9183 
9184  // use unchecked array access
9185  ptr = &ptr->operator[](static_cast<size_type>(std::stoi(reference_token)));
9186  break;
9187  }
9188 
9189  default:
9190  {
9191  throw std::out_of_range("unresolved reference token '" + reference_token + "'");
9192  }
9193  }
9194  }
9195 
9196  return *ptr;
9197  }
9198 
9199  const_reference get_checked(const_pointer ptr) const
9200  {
9201  for (const auto& reference_token : reference_tokens)
9202  {
9203  switch (ptr->m_type)
9204  {
9205  case value_t::object:
9206  {
9207  // note: at performs range check
9208  ptr = &ptr->at(reference_token);
9209  break;
9210  }
9211 
9212  case value_t::array:
9213  {
9214  if (reference_token == "-")
9215  {
9216  // "-" always fails the range check
9217  throw std::out_of_range("array index '-' (" +
9218  std::to_string(ptr->m_value.array->size()) +
9219  ") is out of range");
9220  }
9221 
9222  // error condition (cf. RFC 6901, Sect. 4)
9223  if (reference_token.size() > 1 and reference_token[0] == '0')
9224  {
9225  throw std::domain_error("array index must not begin with '0'");
9226  }
9227 
9228  // note: at performs range check
9229  ptr = &ptr->at(static_cast<size_type>(std::stoi(reference_token)));
9230  break;
9231  }
9232 
9233  default:
9234  {
9235  throw std::out_of_range("unresolved reference token '" + reference_token + "'");
9236  }
9237  }
9238  }
9239 
9240  return *ptr;
9241  }
9242 
9244  static std::vector<std::string> split(const std::string& reference_string)
9245  {
9246  std::vector<std::string> result;
9247 
9248  // special case: empty reference string -> no reference tokens
9249  if (reference_string.empty())
9250  {
9251  return result;
9252  }
9253 
9254  // check if nonempty reference string begins with slash
9255  if (reference_string[0] != '/')
9256  {
9257  throw std::domain_error("JSON pointer must be empty or begin with '/'");
9258  }
9259 
9260  // extract the reference tokens:
9261  // - slash: position of the last read slash (or end of string)
9262  // - start: position after the previous slash
9263  for (
9264  // search for the first slash after the first character
9265  size_t slash = reference_string.find_first_of("/", 1),
9266  // set the beginning of the first reference token
9267  start = 1;
9268  // we can stop if start == string::npos+1 = 0
9269  start != 0;
9270  // set the beginning of the next reference token
9271  // (will eventually be 0 if slash == std::string::npos)
9272  start = slash + 1,
9273  // find next slash
9274  slash = reference_string.find_first_of("/", start))
9275  {
9276  // use the text between the beginning of the reference token
9277  // (start) and the last slash (slash).
9278  auto reference_token = reference_string.substr(start, slash - start);
9279 
9280  // check reference tokens are properly escaped
9281  for (size_t pos = reference_token.find_first_of("~");
9282  pos != std::string::npos;
9283  pos = reference_token.find_first_of("~", pos + 1))
9284  {
9285  assert(reference_token[pos] == '~');
9286 
9287  // ~ must be followed by 0 or 1
9288  if (pos == reference_token.size() - 1 or
9289  (reference_token[pos + 1] != '0' and
9290  reference_token[pos + 1] != '1'))
9291  {
9292  throw std::domain_error("escape error: '~' must be followed with '0' or '1'");
9293  }
9294  }
9295 
9296  // finally, store the reference token
9297  unescape(reference_token);
9298  result.push_back(reference_token);
9299  }
9300 
9301  return result;
9302  }
9303 
9304  private:
9319  static void replace_substring(std::string& s,
9320  const std::string& f,
9321  const std::string& t)
9322  {
9323  assert(not f.empty());
9324 
9325  for (
9326  size_t pos = s.find(f); // find first occurrence of f
9327  pos != std::string::npos; // make sure f was found
9328  s.replace(pos, f.size(), t), // replace with t
9329  pos = s.find(f, pos + t.size()) // find next occurrence of f
9330  );
9331  }
9332 
9334  static std::string escape(std::string s)
9335  {
9336  // escape "~"" to "~0" and "/" to "~1"
9337  replace_substring(s, "~", "~0");
9338  replace_substring(s, "/", "~1");
9339  return s;
9340  }
9341 
9343  static void unescape(std::string& s)
9344  {
9345  // first transform any occurrence of the sequence '~1' to '/'
9346  replace_substring(s, "~1", "/");
9347  // then transform any occurrence of the sequence '~0' to '~'
9348  replace_substring(s, "~0", "~");
9349  }
9350 
9358  static void flatten(const std::string& reference_string,
9359  const basic_json& value,
9360  basic_json& result)
9361  {
9362  switch (value.m_type)
9363  {
9364  case value_t::array:
9365  {
9366  if (value.m_value.array->empty())
9367  {
9368  // flatten empty array as null
9369  result[reference_string] = nullptr;
9370  }
9371  else
9372  {
9373  // iterate array and use index as reference string
9374  for (size_t i = 0; i < value.m_value.array->size(); ++i)
9375  {
9376  flatten(reference_string + "/" + std::to_string(i),
9377  value.m_value.array->operator[](i), result);
9378  }
9379  }
9380  break;
9381  }
9382 
9383  case value_t::object:
9384  {
9385  if (value.m_value.object->empty())
9386  {
9387  // flatten empty object as null
9388  result[reference_string] = nullptr;
9389  }
9390  else
9391  {
9392  // iterate object and use keys as reference string
9393  for (const auto& element : *value.m_value.object)
9394  {
9395  flatten(reference_string + "/" + escape(element.first),
9396  element.second, result);
9397  }
9398  }
9399  break;
9400  }
9401 
9402  default:
9403  {
9404  // add primitive value with its reference string
9405  result[reference_string] = value;
9406  break;
9407  }
9408  }
9409  }
9410 
9416  static basic_json unflatten(const basic_json& value)
9417  {
9418  if (not value.is_object())
9419  {
9420  throw std::domain_error("only objects can be unflattened");
9421  }
9422 
9423  basic_json result;
9424 
9425  // iterate the JSON object values
9426  for (const auto& element : *value.m_value.object)
9427  {
9428  if (not element.second.is_primitive())
9429  {
9430  throw std::domain_error("values in object must be primitive");
9431  }
9432 
9433  // assign value to reference pointed to by JSON pointer; Note
9434  // that if the JSON pointer is "" (i.e., points to the whole
9435  // value), function get_and_create returns a reference to
9436  // result itself. An assignment will then create a primitive
9437  // value.
9438  json_pointer(element.first).get_and_create(result) = element.second;
9439  }
9440 
9441  return result;
9442  }
9443 
9444  private:
9446  std::vector<std::string> reference_tokens {};
9447  };
9448 
9450  // JSON Pointer support //
9452 
9455 
9489  reference operator[](const json_pointer& ptr)
9490  {
9491  return ptr.get_unchecked(this);
9492  }
9516  const_reference operator[](const json_pointer& ptr) const
9517  {
9518  return ptr.get_unchecked(this);
9519  }
9541  reference at(const json_pointer& ptr)
9542  {
9543  return ptr.get_checked(this);
9544  }
9566  const_reference at(const json_pointer& ptr) const
9567  {
9568  return ptr.get_checked(this);
9569  }
9593  basic_json flatten() const
9594  {
9595  basic_json result(value_t::object);
9596  json_pointer::flatten("", *this, result);
9597  return result;
9598  }
9599 
9627  basic_json unflatten() const
9628  {
9629  return json_pointer::unflatten(*this);
9630  }
9633 
9635  // JSON Patch functions //
9637 
9640 
9677  basic_json patch(const basic_json& json_patch) const
9678  {
9679  // make a working copy to apply the patch to
9680  basic_json result = *this;
9682  // the valid JSON Patch operations
9683  enum class patch_operations {add, remove, replace, move, copy, test, invalid};
9684 
9685  const auto get_op = [](const std::string op)
9686  {
9687  if (op == "add")
9688  {
9689  return patch_operations::add;
9690  }
9691  if (op == "remove")
9692  {
9693  return patch_operations::remove;
9694  }
9695  if (op == "replace")
9696  {
9697  return patch_operations::replace;
9698  }
9699  if (op == "move")
9700  {
9701  return patch_operations::move;
9702  }
9703  if (op == "copy")
9704  {
9705  return patch_operations::copy;
9706  }
9707  if (op == "test")
9708  {
9709  return patch_operations::test;
9710  }
9711 
9712  return patch_operations::invalid;
9713  };
9714 
9715  // wrapper for "add" operation; add value at ptr
9716  const auto operation_add = [&result](json_pointer & ptr, basic_json val)
9717  {
9718  // adding to the root of the target document means replacing it
9719  if (ptr.is_root())
9720  {
9721  result = val;
9722  }
9723  else
9724  {
9725  // make sure the top element of the pointer exists
9726  json_pointer top_pointer = ptr.top();
9727  if (top_pointer != ptr)
9728  {
9729  basic_json& x = result.at(top_pointer);
9730  }
9731 
9732  // get reference to parent of JSON pointer ptr
9733  const auto last_path = ptr.pop_back();
9734  basic_json& parent = result[ptr];
9735 
9736  switch (parent.m_type)
9737  {
9738  case value_t::null:
9739  case value_t::object:
9740  {
9741  // use operator[] to add value
9742  parent[last_path] = val;
9743  break;
9744  }
9745 
9746  case value_t::array:
9747  {
9748  if (last_path == "-")
9749  {
9750  // special case: append to back
9751  parent.push_back(val);
9752  }
9753  else
9754  {
9755  const auto idx = std::stoi(last_path);
9756  if (static_cast<size_type>(idx) > parent.size())
9757  {
9758  // avoid undefined behavior
9759  throw std::out_of_range("array index " + std::to_string(idx) + " is out of range");
9760  }
9761  else
9762  {
9763  // default case: insert add offset
9764  parent.insert(parent.begin() + static_cast<difference_type>(idx), val);
9765  }
9766  }
9767  break;
9768  }
9769 
9770  default:
9771  {
9772  // if there exists a parent it cannot be primitive
9773  assert(false); // LCOV_EXCL_LINE
9774  }
9775  }
9776  }
9777  };
9778 
9779  // wrapper for "remove" operation; remove value at ptr
9780  const auto operation_remove = [&result](json_pointer & ptr)
9781  {
9782  // get reference to parent of JSON pointer ptr
9783  const auto last_path = ptr.pop_back();
9784  basic_json& parent = result.at(ptr);
9785 
9786  // remove child
9787  if (parent.is_object())
9788  {
9789  // perform range check
9790  auto it = parent.find(last_path);
9791  if (it != parent.end())
9792  {
9793  parent.erase(it);
9794  }
9795  else
9796  {
9797  throw std::out_of_range("key '" + last_path + "' not found");
9798  }
9799  }
9800  else if (parent.is_array())
9801  {
9802  // note erase performs range check
9803  parent.erase(static_cast<size_type>(std::stoi(last_path)));
9804  }
9805  };
9806 
9807  // type check
9808  if (not json_patch.is_array())
9809  {
9810  // a JSON patch must be an array of objects
9811  throw std::invalid_argument("JSON patch must be an array of objects");
9812  }
9813 
9814  // iterate and apply th eoperations
9815  for (const auto& val : json_patch)
9816  {
9817  // wrapper to get a value for an operation
9818  const auto get_value = [&val](const std::string & op,
9819  const std::string & member,
9820  bool string_type) -> basic_json&
9821  {
9822  // find value
9823  auto it = val.m_value.object->find(member);
9824 
9825  // context-sensitive error message
9826  const auto error_msg = (op == "op") ? "operation" : "operation '" + op + "'";
9827 
9828  // check if desired value is present
9829  if (it == val.m_value.object->end())
9830  {
9831  throw std::invalid_argument(error_msg + " must have member '" + member + "'");
9832  }
9833 
9834  // check if result is of type string
9835  if (string_type and not it->second.is_string())
9836  {
9837  throw std::invalid_argument(error_msg + " must have string member '" + member + "'");
9838  }
9839 
9840  // no error: return value
9841  return it->second;
9842  };
9843 
9844  // type check
9845  if (not val.is_object())
9846  {
9847  throw std::invalid_argument("JSON patch must be an array of objects");
9848  }
9849 
9850  // collect mandatory members
9851  const std::string op = get_value("op", "op", true);
9852  const std::string path = get_value(op, "path", true);
9853  json_pointer ptr(path);
9854 
9855  switch (get_op(op))
9856  {
9857  case patch_operations::add:
9858  {
9859  operation_add(ptr, get_value("add", "value", false));
9860  break;
9861  }
9862 
9863  case patch_operations::remove:
9864  {
9865  operation_remove(ptr);
9866  break;
9867  }
9868 
9869  case patch_operations::replace:
9870  {
9871  // the "path" location must exist - use at()
9872  result.at(ptr) = get_value("replace", "value", false);
9873  break;
9874  }
9875 
9876  case patch_operations::move:
9877  {
9878  const std::string from_path = get_value("move", "from", true);
9879  json_pointer from_ptr(from_path);
9880 
9881  // the "from" location must exist - use at()
9882  basic_json v = result.at(from_ptr);
9883 
9884  // The move operation is functionally identical to a
9885  // "remove" operation on the "from" location, followed
9886  // immediately by an "add" operation at the target
9887  // location with the value that was just removed.
9888  operation_remove(from_ptr);
9889  operation_add(ptr, v);
9890  break;
9891  }
9892 
9893  case patch_operations::copy:
9894  {
9895  const std::string from_path = get_value("copy", "from", true);;
9896  const json_pointer from_ptr(from_path);
9897 
9898  // the "from" location must exist - use at()
9899  result[ptr] = result.at(from_ptr);
9900  break;
9901  }
9902 
9903  case patch_operations::test:
9904  {
9905  bool success = false;
9906  try
9907  {
9908  // check if "value" matches the one at "path"
9909  // the "path" location must exist - use at()
9910  success = (result.at(ptr) == get_value("test", "value", false));
9911  }
9912  catch (std::out_of_range&)
9913  {
9914  // ignore out of range errors: success remains false
9915  }
9916 
9917  // throw an exception if test fails
9918  if (not success)
9919  {
9920  throw std::domain_error("unsuccessful: " + val.dump());
9921  }
9922 
9923  break;
9924  }
9925 
9926  case patch_operations::invalid:
9927  {
9928  // op must be "add", "remove", "replace", "move", "copy", or
9929  // "test"
9930  throw std::invalid_argument("operation value '" + op + "' is invalid");
9931  }
9932  }
9933  }
9934 
9935  return result;
9936  }
9937 
9970  static basic_json diff(const basic_json& source,
9971  const basic_json& target,
9972  const std::string& path = "")
9973  {
9974  // the patch
9975  basic_json result(value_t::array);
9976 
9977  // if the values are the same, return empty patch
9978  if (source == target)
9979  {
9980  return result;
9981  }
9982 
9983  if (source.type() != target.type())
9984  {
9985  // different types: replace value
9986  result.push_back(
9987  {
9988  {"op", "replace"},
9989  {"path", path},
9990  {"value", target}
9991  });
9992  }
9993  else
9994  {
9995  switch (source.type())
9996  {
9997  case value_t::array:
9998  {
9999  // first pass: traverse common elements
10000  size_t i = 0;
10001  while (i < source.size() and i < target.size())
10002  {
10003  // recursive call to compare array values at index i
10004  auto temp_diff = diff(source[i], target[i], path + "/" + std::to_string(i));
10005  result.insert(result.end(), temp_diff.begin(), temp_diff.end());
10006  ++i;
10007  }
10008 
10009  // i now reached the end of at least one array
10010  // in a second pass, traverse the remaining elements
10011 
10012  // remove my remaining elements
10013  const auto end_index = static_cast<difference_type>(result.size());
10014  while (i < source.size())
10015  {
10016  // add operations in reverse order to avoid invalid
10017  // indices
10018  result.insert(result.begin() + end_index, object(
10019  {
10020  {"op", "remove"},
10021  {"path", path + "/" + std::to_string(i)}
10022  }));
10023  ++i;
10024  }
10025 
10026  // add other remaining elements
10027  while (i < target.size())
10028  {
10029  result.push_back(
10030  {
10031  {"op", "add"},
10032  {"path", path + "/" + std::to_string(i)},
10033  {"value", target[i]}
10034  });
10035  ++i;
10036  }
10037 
10038  break;
10039  }
10040 
10041  case value_t::object:
10042  {
10043  // first pass: traverse this object's elements
10044  for (auto it = source.begin(); it != source.end(); ++it)
10045  {
10046  // escape the key name to be used in a JSON patch
10047  const auto key = json_pointer::escape(it.key());
10048 
10049  if (target.find(it.key()) != target.end())
10050  {
10051  // recursive call to compare object values at key it
10052  auto temp_diff = diff(it.value(), target[it.key()], path + "/" + key);
10053  result.insert(result.end(), temp_diff.begin(), temp_diff.end());
10054  }
10055  else
10056  {
10057  // found a key that is not in o -> remove it
10058  result.push_back(object(
10059  {
10060  {"op", "remove"},
10061  {"path", path + "/" + key}
10062  }));
10063  }
10064  }
10065 
10066  // second pass: traverse other object's elements
10067  for (auto it = target.begin(); it != target.end(); ++it)
10068  {
10069  if (source.find(it.key()) == source.end())
10070  {
10071  // found a key that is not in this -> add it
10072  const auto key = json_pointer::escape(it.key());
10073  result.push_back(
10074  {
10075  {"op", "add"},
10076  {"path", path + "/" + key},
10077  {"value", it.value()}
10078  });
10079  }
10080  }
10081 
10082  break;
10083  }
10084 
10085  default:
10086  {
10087  // both primitive type: replace value
10088  result.push_back(
10089  {
10090  {"op", "replace"},
10091  {"path", path},
10092  {"value", target}
10093  });
10094  break;
10095  }
10096  }
10097  }
10098 
10099  return result;
10100  }
10101 
10103 };
10104 
10105 
10107 // presets //
10109 
10118 using json = basic_json<>;
10119 }
10120 
10121 
10123 // nonmember support //
10125 
10126 // specialization of std::swap, and std::hash
10127 namespace std
10128 {
10134 template<>
10135 inline void swap(nlohmann::json& j1,
10136  nlohmann::json& j2) noexcept(
10137  is_nothrow_move_constructible<nlohmann::json>::value and
10138  is_nothrow_move_assignable<nlohmann::json>::value
10139  )
10140 {
10141  j1.swap(j2);
10142 }
10143 
10145 template<>
10146 struct hash<nlohmann::json>
10147 {
10153  std::size_t operator()(const nlohmann::json& j) const
10154  {
10155  // a naive hashing via the string representation
10156  const auto& h = hash<nlohmann::json::string_t>();
10157  return h(j.dump());
10158  }
10159 };
10160 }
10161 
10174 inline nlohmann::json operator "" _json(const char* s, std::size_t)
10175 {
10176  return nlohmann::json::parse(s);
10177 }
10178 
10191 inline nlohmann::json::json_pointer operator "" _json_pointer(const char* s, std::size_t)
10192 {
10193  return nlohmann::json::json_pointer(s);
10194 }
10195 
10196 // restore GCC/clang diagnostic settings
10197 #if defined(__clang__) || defined(__GNUC__) || defined(__GNUG__)
10198  #pragma GCC diagnostic pop
10199 #endif
10200 
10201 #endif
const_iterator(pointer object) noexcept
constructor for a given JSON instance
Definition: json.hpp:6737
size_type max_size() const noexcept
returns the maximum possible number of elements
Definition: json.hpp:4756
friend bool operator<=(const_reference lhs, const_reference rhs) noexcept
comparison: less than or equal
Definition: json.hpp:5733
constexpr value_t type() const noexcept
return the type of the JSON value (explicit)
Definition: json.hpp:2239
constexpr bool is_array() const noexcept
return whether value is an array
Definition: json.hpp:2499
basic_json(const value_t value_type)
create an empty value with a given type
Definition: json.hpp:1063
basic_json(const array_t &val)
create an array (explicit)
Definition: json.hpp:1175
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:4257
const_iterator end() const noexcept
returns a const iterator to one past the last element
Definition: json.hpp:4378
constexpr bool is_primitive() const noexcept
return whether type is primitive
Definition: json.hpp:2269
constexpr bool is_null() const noexcept
return whether value is null
Definition: json.hpp:2318
const_reference operator[](size_type idx) const
access specified array element
Definition: json.hpp:3378
const_reverse_iterator rend() const noexcept
returns a const reverse iterator to one before the first
Definition: json.hpp:4483
constexpr bool is_structured() const noexcept
return whether type is structured
Definition: json.hpp:2296
reference value() const
return the value of an iterator
Definition: json.hpp:7448
json_reverse_iterator & operator--()
pre-decrement (–it)
Definition: json.hpp:7510
void clear() noexcept
clears the contents
Definition: json.hpp:4815
bool operator==(const const_iterator &other) const
comparison: equal
Definition: json.hpp:7059
static basic_json parse(const CharPT s, const parser_callback_t cb=nullptr)
deserialize from string literal
Definition: json.hpp:5931
json_reverse_iterator operator--(int)
post-decrement (it–)
Definition: json.hpp:7504
reference operator[](T *(&key)[n])
access specified object element
Definition: json.hpp:3511
friend std::istream & operator>>(std::istream &i, basic_json &j)
deserialize from stream
Definition: json.hpp:6133
iterator & operator+=(difference_type i)
add to iterator
Definition: json.hpp:7406
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:1756
reference & operator=(basic_json other) noexcept(std::is_nothrow_move_constructible< value_t >::value andstd::is_nothrow_move_assignable< value_t >::value andstd::is_nothrow_move_constructible< json_value >::value andstd::is_nothrow_move_assignable< json_value >::value)
copy assignment
Definition: json.hpp:2091
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:6021
constexpr bool is_number_unsigned() const noexcept
return whether value is an unsigned integer number
Definition: json.hpp:2427
const_iterator operator-(difference_type i)
subtract from iterator
Definition: json.hpp:7212
void swap(reference other) noexcept(std::is_nothrow_move_constructible< value_t >::value andstd::is_nothrow_move_assignable< value_t >::value andstd::is_nothrow_move_constructible< json_value >::value andstd::is_nothrow_move_assignable< json_value >::value)
exchanges the values
Definition: json.hpp:5276
BooleanType boolean_t
a type for a boolean
Definition: json.hpp:510
iterator & operator=(iterator other) noexcept(std::is_nothrow_move_constructible< pointer >::value andstd::is_nothrow_move_assignable< pointer >::value andstd::is_nothrow_move_constructible< internal_iterator >::value andstd::is_nothrow_move_assignable< internal_iterator >::value)
copy assignment
Definition: json.hpp:7352
reference operator+=(const typename object_t::value_type &val)
add an object to an object
Definition: json.hpp:4998
reference operator*() const
return a reference to the value pointed to by the iterator
Definition: json.hpp:7364
basic_json(const typename string_t::value_type *val)
create a string (explicit)
Definition: json.hpp:1271
reference operator[](difference_type n) const
access to successor
Definition: json.hpp:7546
iterator find(typename object_t::key_type key)
find an element in a JSON object
Definition: json.hpp:4211
friend bool operator!=(const_reference lhs, const_reference rhs) noexcept
comparison: not equal
Definition: json.hpp:5577
basic_json(const string_t &val)
create a string (explicit)
Definition: json.hpp:1245
void push_back(const basic_json &val)
add an object to an array
Definition: json.hpp:4924
void erase(const size_type idx)
remove element from a JSON array given an index
Definition: json.hpp:4165
ArrayType< basic_json, AllocatorType< basic_json >> array_t
a type for an array
Definition: json.hpp:437
reference front()
access the first element
Definition: json.hpp:3824
void swap(object_t &other)
exchanges the values
Definition: json.hpp:5341
json_reverse_iterator operator-(difference_type i) const
subtract from iterator
Definition: json.hpp:7532
const_iterator & operator+=(difference_type i)
add to iterator
Definition: json.hpp:7161
a class to store JSON values
Definition: json.hpp:231
basic_json(const int val) noexcept
create an integer number from an enum type (explicit)
Definition: json.hpp:1385
static basic_json parse(T(&array)[N], const parser_callback_t cb=nullptr)
deserialize from an array
Definition: json.hpp:5893
reference value() const
return the value of an iterator
Definition: json.hpp:7559
constexpr bool is_object() const noexcept
return whether value is an object
Definition: json.hpp:2477
friend bool operator==(std::nullptr_t, const_reference v) noexcept
comparison: equal
Definition: json.hpp:5556
NumberIntegerType number_integer_t
a type for a number (integer)
Definition: json.hpp:582
iterator insert(const_iterator pos, size_type cnt, const basic_json &val)
inserts elements
Definition: json.hpp:5129
const_reference at(const typename object_t::key_type &key) const
access specified object element with bounds checking
Definition: json.hpp:3284
const_iterator operator+(difference_type i)
add to iterator
Definition: json.hpp:7201
a mutable random access iterator for the basic_json class
Definition: json.hpp:7331
const_iterator operator++(int)
post-increment (it++)
Definition: json.hpp:6973
constexpr bool is_number_integer() const noexcept
return whether value is an integer number
Definition: json.hpp:2399
ObjectType< StringType, basic_json, std::less< StringType >, AllocatorType< std::pair< const StringType, basic_json >>> object_t
a type for an object
Definition: json.hpp:391
STL namespace.
NumberUnsignedType number_unsigned_t
a type for a number (unsigned)
Definition: json.hpp:653
typename std::allocator_traits< allocator_type >::const_pointer const_pointer
the type of an element const pointer
Definition: json.hpp:272
static basic_json parse(std::istream &&i, const parser_callback_t cb=nullptr)
deserialize from stream
Definition: json.hpp:5970
basic_json(const number_integer_t val) noexcept
create an integer number (explicit)
Definition: json.hpp:1354
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:1716
static iteration_proxy< const_iterator > iterator_wrapper(const_reference cont)
wrapper to access iterator member functions in range-based for
Definition: json.hpp:4570
typename basic_json::value_type value_type
the type of the values when the iterator is dereferenced
Definition: json.hpp:6718
json_reverse_iterator(const typename base_iterator::iterator_type &it) noexcept
create reverse iterator from iterator
Definition: json.hpp:7481
PointerType get_ptr() noexcept
get a pointer value (implicit)
Definition: json.hpp:2977
const_iterator cbegin() const noexcept
returns a const iterator to the first element
Definition: json.hpp:4337
reference back()
access the last element
Definition: json.hpp:3867
const value_type & const_reference
the type of an element const reference
Definition: json.hpp:259
typename basic_json::const_pointer pointer
defines a pointer to the type iterated over (value_type)
Definition: json.hpp:6722
IteratorType erase(IteratorType first, IteratorType last)
remove elements given an iterator range
Definition: json.hpp:4040
void push_back(const typename object_t::value_type &val)
add an object to an object
Definition: json.hpp:4974
bool empty() const noexcept
checks whether the container is empty
Definition: json.hpp:4622
void push_back(std::initializer_list< basic_json > init)
add an object to an object
Definition: json.hpp:5029
json_pointer(const std::string &s="")
create JSON pointer
Definition: json.hpp:8918
const_reference operator[](T *(&key)[n]) const
read-only access specified object element
Definition: json.hpp:3546
iterator insert(const_iterator pos, const_iterator first, const_iterator last)
inserts elements
Definition: json.hpp:5181
constexpr const PointerType get_ptr() const noexcept
get a pointer value (implicit)
Definition: json.hpp:3005
constexpr bool is_number_float() const noexcept
return whether value is a floating-point number
Definition: json.hpp:2455
basic_json(InputIT first, InputIT last)
construct a JSON container given an iterator range
Definition: json.hpp:1827
reference operator[](difference_type n) const
access to successor
Definition: json.hpp:7442
basic_json(std::nullptr_t=nullptr) noexcept
create a null object
Definition: json.hpp:1087
IteratorType erase(IteratorType pos)
remove element given an iterator
Definition: json.hpp:3933
static allocator_type get_allocator()
returns the allocator associated with the container
Definition: json.hpp:289
const_reference operator[](const typename object_t::key_type &key) const
read-only access specified object element
Definition: json.hpp:3469
const_reference operator[](T *key) const
read-only access specified object element
Definition: json.hpp:3631
json_reverse_iterator operator+(difference_type i) const
add to iterator
Definition: json.hpp:7524
std::size_t size_type
a type to represent container sizes
Definition: json.hpp:264
JSON_DEPRECATED basic_json(std::istream &i, const parser_callback_t cb=nullptr)
construct a JSON value given an input stream
Definition: json.hpp:1945
object_t::key_type key() const
return the key of an object iterator
Definition: json.hpp:7552
const_iterator(const iterator &other) noexcept
copy constructor given a non-const iterator
Definition: json.hpp:6769
basic_json(const CompatibleArrayType &val)
create an array (implicit)
Definition: json.hpp:1215
const_reference at(size_type idx) const
access specified array element with bounds checking
Definition: json.hpp:3190
basic_json(size_type cnt, const basic_json &val)
construct an array with count copies of given value
Definition: json.hpp:1780
std::reverse_iterator< Base > base_iterator
shortcut to the reverse iterator adaptor
Definition: json.hpp:7476
iterator insert(const_iterator pos, std::initializer_list< basic_json > ilist)
inserts elements
Definition: json.hpp:5239
typename std::allocator_traits< allocator_type >::pointer pointer
the type of an element pointer
Definition: json.hpp:270
iterator insert(const_iterator pos, const basic_json &val)
inserts element
Definition: json.hpp:5074
friend bool operator>=(const_reference lhs, const_reference rhs) noexcept
comparison: greater than or equal
Definition: json.hpp:5777
friend bool operator<(const_reference lhs, const_reference rhs) noexcept
comparison: less than
Definition: json.hpp:5638
iterator & operator++()
pre-increment (++it)
Definition: json.hpp:7384
bool operator<(const const_iterator &other) const
comparison: smaller
Definition: json.hpp:7101
iterator operator++(int)
post-increment (it++)
Definition: json.hpp:7376
const_reverse_iterator rbegin() const noexcept
returns a const reverse iterator to the last element
Definition: json.hpp:4446
basic_json(basic_json &&other) noexcept
move constructor
Definition: json.hpp:2054
const_iterator operator--(int)
post-decrement (it–)
Definition: json.hpp:7016
reference at(const typename object_t::key_type &key)
access specified object element with bounds checking
Definition: json.hpp:3237
object (unordered set of name/value pairs)
~basic_json()
destructor
Definition: json.hpp:2124
iterator operator--(int)
post-decrement (it–)
Definition: json.hpp:7391
iterator operator-(difference_type i)
subtract from iterator
Definition: json.hpp:7428
string_t value(const json_pointer &ptr, const char *default_value) const
overload for a default value of type const char*
Definition: json.hpp:3794
const_iterator & operator--()
pre-decrement (–it)
Definition: json.hpp:7027
string_t dump(const int indent=-1) const
serialization
Definition: json.hpp:2196
basic_json value_type
the type of elements in a basic_json container
Definition: json.hpp:254
std::function< bool(int depth, parse_event_t event, basic_json &parsed)> parser_callback_t
per-element parser callback type
Definition: json.hpp:1012
AllocatorType< basic_json > allocator_type
the allocator type
Definition: json.hpp:267
StringType string_t
a type for a string
Definition: json.hpp:484
reference operator+=(const basic_json &val)
add an object to an array
Definition: json.hpp:4948
static basic_json parse(const ContiguousContainer &c, const parser_callback_t cb=nullptr)
deserialize from a container with contiguous storage
Definition: json.hpp:6093
reference operator+=(std::initializer_list< basic_json > init)
add an object to an object
Definition: json.hpp:5046
difference_type operator-(const const_iterator &other) const
return difference
Definition: json.hpp:7223
value_type & reference
the type of an element reference
Definition: json.hpp:257
friend std::ostream & operator>>(const basic_json &j, std::ostream &o)
serialize to stream
Definition: json.hpp:5850
size_type size() const noexcept
returns the number of elements
Definition: json.hpp:4690
difference_type operator-(const iterator &other) const
return difference
Definition: json.hpp:7436
iterator(const iterator &other) noexcept
copy constructor
Definition: json.hpp:7347
namespace for Niels Lohmann
Definition: json.hpp:91
typename basic_json::difference_type difference_type
a type to represent differences between iterators
Definition: json.hpp:6720
constexpr bool is_string() const noexcept
return whether value is a string
Definition: json.hpp:2521
void swap(string_t &other)
exchanges the values
Definition: json.hpp:5374
basic_json(const CompatibleNumberIntegerType val) noexcept
create an integer number (implicit)
Definition: json.hpp:1422
const_reference front() const
access the first element
Definition: json.hpp:3832
bool operator>(const const_iterator &other) const
comparison: greater than
Definition: json.hpp:7143
pointer operator->() const
dereference the iterator
Definition: json.hpp:6937
NumberFloatType number_float_t
a type for a number (floating-point)
Definition: json.hpp:721
value_t
the JSON type enumeration
Definition: json.hpp:752
reverse_iterator rbegin() noexcept
returns an iterator to the reverse-beginning
Definition: json.hpp:4438
std::ptrdiff_t difference_type
a type to represent differences between iterators
Definition: json.hpp:262
ValueType get() const
get a value (explicit)
Definition: json.hpp:2897
void swap(array_t &other)
exchanges the values
Definition: json.hpp:5308
ValueType value(const typename object_t::key_type &key, ValueType default_value) const
access specified object element with default value
Definition: json.hpp:3695
typename Base::reference reference
the reference type for the pointed-to element
Definition: json.hpp:7478
const_reference back() const
access the last element
Definition: json.hpp:3877
void push_back(basic_json &&val)
add an object to an array
Definition: json.hpp:4888
array (ordered collection of values)
json_reverse_iterator & operator++()
pre-increment (++it)
Definition: json.hpp:7497
friend bool operator==(const_reference lhs, const_reference rhs) noexcept
comparison: equal
Definition: json.hpp:5454
static basic_json parse(std::istream &i, const parser_callback_t cb=nullptr)
deserialize from stream
Definition: json.hpp:5961
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:3721
ReferenceType get_ref() const
get a reference value (implicit)
Definition: json.hpp:3067
basic_json(const CompatibleNumberUnsignedType val) noexcept
create an unsigned number (implicit)
Definition: json.hpp:1480
constexpr bool is_boolean() const noexcept
return whether value is a boolean
Definition: json.hpp:2340
reference operator*() const
return a reference to the value pointed to by the iterator
Definition: json.hpp:6896
const_reverse_iterator crbegin() const noexcept
returns a const reverse iterator to the last element
Definition: json.hpp:4512
ValueType value(const json_pointer &ptr, ValueType default_value) const
access specified object element via JSON Pointer with default value
Definition: json.hpp:3769
friend class basic_json
allow basic_json to access private members
Definition: json.hpp:6714
friend bool operator<(const value_t lhs, const value_t rhs) noexcept
comparison operator for JSON types
Definition: json.hpp:5407
basic_json(const number_float_t val) noexcept
create a floating-point number (explicit)
Definition: json.hpp:1511
friend bool operator!=(const_reference v, std::nullptr_t) noexcept
comparison: not equal
Definition: json.hpp:5600
iterator operator+(difference_type i)
add to iterator
Definition: json.hpp:7420
basic_json(const CompatibleNumberFloatType val) noexcept
create an floating-point number (implicit)
Definition: json.hpp:1558
bool operator<=(const const_iterator &other) const
comparison: less than or equal
Definition: json.hpp:7134
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:1633
iterator(pointer object) noexcept
constructor for a given JSON instance
Definition: json.hpp:7342
friend bool operator!=(std::nullptr_t, const_reference v) noexcept
comparison: not equal
Definition: json.hpp:5609
const_iterator & operator++()
pre-increment (++it)
Definition: json.hpp:6984
pointer operator->() const
dereference the iterator
Definition: json.hpp:7370
constexpr bool is_number() const noexcept
return whether value is a number
Definition: json.hpp:2370
reference value() const
return the value of an iterator
Definition: json.hpp:7307
const_iterator begin() const noexcept
returns a const iterator to the first element
Definition: json.hpp:4307
std::bidirectional_iterator_tag iterator_category
the category of the iterator
Definition: json.hpp:6726
basic_json(boolean_t val) noexcept
create a boolean (explicit)
Definition: json.hpp:1322
iterator end() noexcept
returns an iterator to one past the last element
Definition: json.hpp:4368
reverse_iterator rend() noexcept
returns an iterator to the reverse-end
Definition: json.hpp:4475
difference_type operator-(const json_reverse_iterator &other) const
return difference
Definition: json.hpp:7540
const_iterator find(typename object_t::key_type key) const
find an element in a JSON object
Definition: json.hpp:4227
iterator begin() noexcept
returns an iterator to the first element
Definition: json.hpp:4297
const_iterator cend() const noexcept
returns a const iterator to one past the last element
Definition: json.hpp:4408
basic_json(const CompatibleObjectType &val)
create an object (implicit)
Definition: json.hpp:1147
friend bool operator>(const_reference lhs, const_reference rhs) noexcept
comparison: greater than
Definition: json.hpp:5755
bool operator>=(const const_iterator &other) const
comparison: greater than or equal
Definition: json.hpp:7152
size_type erase(const typename object_t::key_type &key)
remove element from a JSON object given a key
Definition: json.hpp:4128
reference operator[](const typename object_t::key_type &key)
access specified object element
Definition: json.hpp:3418
object_t::key_type key() const
return the key of an object iterator
Definition: json.hpp:7289
reference operator+=(basic_json &&val)
add an object to an array
Definition: json.hpp:4914
const_iterator & operator=(const_iterator other) noexcept(std::is_nothrow_move_constructible< pointer >::value andstd::is_nothrow_move_assignable< pointer >::value andstd::is_nothrow_move_constructible< internal_iterator >::value andstd::is_nothrow_move_assignable< internal_iterator >::value)
copy assignment
Definition: json.hpp:6811
reference operator[](difference_type n) const
access to successor
Definition: json.hpp:7250
a const random access iterator for the basic_json class
Definition: json.hpp:6711
a template for a reverse iterator class
Definition: json.hpp:241
typename basic_json::const_reference reference
defines a reference to the type iterated over (value_type)
Definition: json.hpp:6724
json_reverse_iterator operator++(int)
post-increment (it++)
Definition: json.hpp:7491
friend bool operator==(const_reference v, std::nullptr_t) noexcept
comparison: equal
Definition: json.hpp:5547
reference operator[](size_type idx)
access specified array element
Definition: json.hpp:3330
bool operator!=(const const_iterator &other) const
comparison: not equal
Definition: json.hpp:7092
json_reverse_iterator & operator+=(difference_type i)
add to iterator
Definition: json.hpp:7517
reference at(size_type idx)
access specified array element with bounds checking
Definition: json.hpp:3147
static iteration_proxy< iterator > iterator_wrapper(reference cont)
wrapper to access iterator member functions in range-based for
Definition: json.hpp:4562
constexpr bool is_discarded() const noexcept
return whether value is discarded
Definition: json.hpp:2548
const_reverse_iterator crend() const noexcept
returns a const reverse iterator to one before the first
Definition: json.hpp:4541
iterator & operator-=(difference_type i)
subtract from iterator
Definition: json.hpp:7413
basic_json(const object_t &val)
create an object (explicit)
Definition: json.hpp:1112
basic_json(const number_unsigned_t val) noexcept
create an unsigned integer number (explicit)
Definition: json.hpp:1449
friend std::istream & operator<<(basic_json &j, std::istream &i)
deserialize from stream
Definition: json.hpp:6123
json_reverse_iterator(const base_iterator &it) noexcept
create reverse iterator from base class
Definition: json.hpp:7486
friend std::ostream & operator<<(std::ostream &o, const basic_json &j)
serialize to stream
Definition: json.hpp:5818
const_iterator(const const_iterator &other) noexcept
copy constructor
Definition: json.hpp:6802
iterator & operator--()
pre-decrement (–it)
Definition: json.hpp:7399
iterator insert(const_iterator pos, basic_json &&val)
inserts element
Definition: json.hpp:5100
ReferenceType get_ref()
get a reference value (implicit)
Definition: json.hpp:3054
const_iterator & operator-=(difference_type i)
subtract from iterator
Definition: json.hpp:7192
basic_json(const CompatibleStringType &val)
create a string (implicit)
Definition: json.hpp:1302
basic_json(const basic_json &other)
copy constructor
Definition: json.hpp:1977
reference operator[](T *key)
access specified object element
Definition: json.hpp:3579
parse_event_t
JSON callback events.
Definition: json.hpp:942