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