JSON for Modern C++  2.0.8
json.hpp
1 /*
2  __ _____ _____ _____
3  __| | __| | | | JSON for Modern C++
4 | | |__ | | | | | | version 2.0.8
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> // all_of, for_each, transform
33 #include <array> // array
34 #include <cassert> // assert
35 #include <cctype> // isdigit
36 #include <ciso646> // and, not, or
37 #include <cmath> // isfinite, signbit
38 #include <cstddef> // nullptr_t, ptrdiff_t, size_t
39 #include <cstdint> // int64_t, uint64_t
40 #include <cstdlib> // strtod, strtof, strtold, strtoul
41 #include <cstring> // strlen
42 #include <functional> // function, hash, less
43 #include <initializer_list> // initializer_list
44 #include <iomanip> // setw
45 #include <iostream> // istream, ostream
46 #include <iterator> // advance, begin, bidirectional_iterator_tag, distance, end, inserter, iterator, iterator_traits, next, random_access_iterator_tag, reverse_iterator
47 #include <limits> // numeric_limits
48 #include <locale> // locale
49 #include <map> // map
50 #include <memory> // addressof, allocator, allocator_traits, unique_ptr
51 #include <numeric> // accumulate
52 #include <sstream> // stringstream
53 #include <stdexcept> // domain_error, invalid_argument, out_of_range
54 #include <string> // getline, stoi, string, to_string
55 #include <type_traits> // add_pointer, enable_if, is_arithmetic, is_base_of, is_const, is_constructible, is_convertible, is_floating_point, is_integral, is_nothrow_move_assignable, std::is_nothrow_move_constructible, std::is_pointer, std::is_reference, std::is_same, remove_const, remove_pointer, remove_reference
56 #include <utility> // declval, forward, make_pair, move, pair, swap
57 #include <vector> // 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 
125 }
126 
205 template <
206  template<typename U, typename V, typename... Args> class ObjectType = std::map,
207  template<typename U, typename... Args> class ArrayType = std::vector,
208  class StringType = std::string,
209  class BooleanType = bool,
210  class NumberIntegerType = std::int64_t,
211  class NumberUnsignedType = std::uint64_t,
212  class NumberFloatType = double,
213  template<typename U> class AllocatorType = std::allocator
214  >
216 {
217  private:
219  using basic_json_t = basic_json<ObjectType, ArrayType, StringType,
220  BooleanType, NumberIntegerType, NumberUnsignedType, NumberFloatType,
221  AllocatorType>;
222 
223  public:
224  // forward declarations
225  template<typename Base> class json_reverse_iterator;
226  class json_pointer;
227 
229  // container types //
231 
236 
239 
243  using const_reference = const value_type&;
244 
246  using difference_type = std::ptrdiff_t;
248  using size_type = std::size_t;
249 
251  using allocator_type = AllocatorType<basic_json>;
252 
254  using pointer = typename std::allocator_traits<allocator_type>::pointer;
256  using const_pointer = typename std::allocator_traits<allocator_type>::const_pointer;
257 
259  class iterator;
261  class const_iterator;
266 
268 
269 
274  {
275  return allocator_type();
276  }
277 
278 
280  // JSON value data types //
282 
287 
371  using object_t = ObjectType<StringType,
372  basic_json,
373  std::less<StringType>,
374  AllocatorType<std::pair<const StringType,
375  basic_json>>>;
376 
421  using array_t = ArrayType<basic_json, AllocatorType<basic_json>>;
422 
468  using string_t = StringType;
469 
494  using boolean_t = BooleanType;
495 
566  using number_integer_t = NumberIntegerType;
567 
637  using number_unsigned_t = NumberUnsignedType;
638 
705  using number_float_t = NumberFloatType;
706 
708 
709 
711  // JSON type enumeration //
713 
736  enum class value_t : uint8_t
737  {
738  null,
739  object,
740  array,
741  string,
742  boolean,
743  number_integer,
744  number_unsigned,
745  number_float,
746  discarded
747  };
748 
749 
750  private:
751 
753  template<typename T, typename... Args>
754  static T* create(Args&& ... args)
755  {
756  AllocatorType<T> alloc;
757  auto deleter = [&](T * object)
758  {
759  alloc.deallocate(object, 1);
760  };
761  std::unique_ptr<T, decltype(deleter)> object(alloc.allocate(1), deleter);
762  alloc.construct(object.get(), std::forward<Args>(args)...);
763  assert(object.get() != nullptr);
764  return object.release();
765  }
766 
768  // JSON value storage //
770 
795  union json_value
796  {
798  object_t* object;
800  array_t* array;
802  string_t* string;
804  boolean_t boolean;
806  number_integer_t number_integer;
808  number_unsigned_t number_unsigned;
810  number_float_t number_float;
811 
813  json_value() = default;
815  json_value(boolean_t v) noexcept : boolean(v) {}
817  json_value(number_integer_t v) noexcept : number_integer(v) {}
819  json_value(number_unsigned_t v) noexcept : number_unsigned(v) {}
821  json_value(number_float_t v) noexcept : number_float(v) {}
823  json_value(value_t t)
824  {
825  switch (t)
826  {
827  case value_t::object:
828  {
829  object = create<object_t>();
830  break;
831  }
832 
833  case value_t::array:
834  {
835  array = create<array_t>();
836  break;
837  }
838 
839  case value_t::string:
840  {
841  string = create<string_t>("");
842  break;
843  }
844 
845  case value_t::boolean:
846  {
847  boolean = boolean_t(false);
848  break;
849  }
850 
851  case value_t::number_integer:
852  {
853  number_integer = number_integer_t(0);
854  break;
855  }
856 
857  case value_t::number_unsigned:
858  {
859  number_unsigned = number_unsigned_t(0);
860  break;
861  }
862 
863  case value_t::number_float:
864  {
865  number_float = number_float_t(0.0);
866  break;
867  }
868 
869  default:
870  {
871  break;
872  }
873  }
874  }
875 
877  json_value(const string_t& value)
878  {
879  string = create<string_t>(value);
880  }
881 
883  json_value(const object_t& value)
884  {
885  object = create<object_t>(value);
886  }
887 
889  json_value(const array_t& value)
890  {
891  array = create<array_t>(value);
892  }
893  };
894 
904  void assert_invariant() const
905  {
906  assert(m_type != value_t::object or m_value.object != nullptr);
907  assert(m_type != value_t::array or m_value.array != nullptr);
908  assert(m_type != value_t::string or m_value.string != nullptr);
909  }
910 
911  public:
913  // JSON parser callback //
915 
926  enum class parse_event_t : uint8_t
927  {
929  object_start,
931  object_end,
933  array_start,
935  array_end,
937  key,
939  value
940  };
941 
994  using parser_callback_t = std::function<bool(int depth,
995  parse_event_t event,
996  basic_json& parsed)>;
997 
998 
1000  // constructors //
1002 
1007 
1048  : m_type(value_type), m_value(value_type)
1049  {
1050  assert_invariant();
1051  }
1052 
1071  basic_json(std::nullptr_t = nullptr) noexcept
1072  : basic_json(value_t::null)
1073  {
1074  assert_invariant();
1075  }
1076 
1096  basic_json(const object_t& val)
1097  : m_type(value_t::object), m_value(val)
1098  {
1099  assert_invariant();
1100  }
1101 
1128  template<class CompatibleObjectType, typename std::enable_if<
1129  std::is_constructible<typename object_t::key_type, typename CompatibleObjectType::key_type>::value and
1130  std::is_constructible<basic_json, typename CompatibleObjectType::mapped_type>::value, int>::type = 0>
1131  basic_json(const CompatibleObjectType& val)
1132  : m_type(value_t::object)
1133  {
1134  using std::begin;
1135  using std::end;
1136  m_value.object = create<object_t>(begin(val), end(val));
1137  assert_invariant();
1138  }
1139 
1159  basic_json(const array_t& val)
1160  : m_type(value_t::array), m_value(val)
1161  {
1162  assert_invariant();
1163  }
1164 
1191  template<class CompatibleArrayType, typename std::enable_if<
1192  not std::is_same<CompatibleArrayType, typename basic_json_t::iterator>::value and
1193  not std::is_same<CompatibleArrayType, typename basic_json_t::const_iterator>::value and
1194  not std::is_same<CompatibleArrayType, typename basic_json_t::reverse_iterator>::value and
1195  not std::is_same<CompatibleArrayType, typename basic_json_t::const_reverse_iterator>::value and
1196  not std::is_same<CompatibleArrayType, typename array_t::iterator>::value and
1197  not std::is_same<CompatibleArrayType, typename array_t::const_iterator>::value and
1198  std::is_constructible<basic_json, typename CompatibleArrayType::value_type>::value, int>::type = 0>
1199  basic_json(const CompatibleArrayType& val)
1200  : m_type(value_t::array)
1201  {
1202  using std::begin;
1203  using std::end;
1204  m_value.array = create<array_t>(begin(val), end(val));
1205  assert_invariant();
1206  }
1207 
1229  basic_json(const string_t& val)
1230  : m_type(value_t::string), m_value(val)
1231  {
1232  assert_invariant();
1233  }
1234 
1255  basic_json(const typename string_t::value_type* val)
1256  : basic_json(string_t(val))
1257  {
1258  assert_invariant();
1259  }
1260 
1284  template<class CompatibleStringType, typename std::enable_if<
1285  std::is_constructible<string_t, CompatibleStringType>::value, int>::type = 0>
1286  basic_json(const CompatibleStringType& val)
1287  : basic_json(string_t(val))
1288  {
1289  assert_invariant();
1290  }
1291 
1306  basic_json(boolean_t val) noexcept
1307  : m_type(value_t::boolean), m_value(val)
1308  {
1309  assert_invariant();
1310  }
1311 
1335  template<typename T, typename std::enable_if<
1336  not (std::is_same<T, int>::value) and
1337  std::is_same<T, number_integer_t>::value, int>::type = 0>
1338  basic_json(const number_integer_t val) noexcept
1339  : m_type(value_t::number_integer), m_value(val)
1340  {
1341  assert_invariant();
1342  }
1343 
1369  basic_json(const int val) noexcept
1370  : m_type(value_t::number_integer),
1371  m_value(static_cast<number_integer_t>(val))
1372  {
1373  assert_invariant();
1374  }
1375 
1401  template<typename CompatibleNumberIntegerType, typename std::enable_if<
1402  std::is_constructible<number_integer_t, CompatibleNumberIntegerType>::value and
1403  std::numeric_limits<CompatibleNumberIntegerType>::is_integer and
1404  std::numeric_limits<CompatibleNumberIntegerType>::is_signed,
1405  CompatibleNumberIntegerType>::type = 0>
1406  basic_json(const CompatibleNumberIntegerType val) noexcept
1407  : m_type(value_t::number_integer),
1408  m_value(static_cast<number_integer_t>(val))
1409  {
1410  assert_invariant();
1411  }
1412 
1430  template<typename T, typename std::enable_if<
1431  not (std::is_same<T, int>::value) and
1432  std::is_same<T, number_unsigned_t>::value, int>::type = 0>
1433  basic_json(const number_unsigned_t val) noexcept
1434  : m_type(value_t::number_unsigned), m_value(val)
1435  {
1436  assert_invariant();
1437  }
1438 
1459  template<typename CompatibleNumberUnsignedType, typename std::enable_if <
1460  std::is_constructible<number_unsigned_t, CompatibleNumberUnsignedType>::value and
1461  std::numeric_limits<CompatibleNumberUnsignedType>::is_integer and
1462  not std::numeric_limits<CompatibleNumberUnsignedType>::is_signed,
1463  CompatibleNumberUnsignedType>::type = 0>
1464  basic_json(const CompatibleNumberUnsignedType val) noexcept
1465  : m_type(value_t::number_unsigned),
1466  m_value(static_cast<number_unsigned_t>(val))
1467  {
1468  assert_invariant();
1469  }
1470 
1495  basic_json(const number_float_t val) noexcept
1496  : m_type(value_t::number_float), m_value(val)
1497  {
1498  // replace infinity and NAN by null
1499  if (not std::isfinite(val))
1500  {
1501  m_type = value_t::null;
1502  m_value = json_value();
1503  }
1504 
1505  assert_invariant();
1506  }
1507 
1539  template<typename CompatibleNumberFloatType, typename = typename std::enable_if<
1540  std::is_constructible<number_float_t, CompatibleNumberFloatType>::value and
1541  std::is_floating_point<CompatibleNumberFloatType>::value>::type>
1542  basic_json(const CompatibleNumberFloatType val) noexcept
1543  : basic_json(number_float_t(val))
1544  {
1545  assert_invariant();
1546  }
1547 
1617  basic_json(std::initializer_list<basic_json> init,
1618  bool type_deduction = true,
1619  value_t manual_type = value_t::array)
1620  {
1621  // check if each element is an array with two elements whose first
1622  // element is a string
1623  bool is_an_object = std::all_of(init.begin(), init.end(),
1624  [](const basic_json & element)
1625  {
1626  return element.is_array() and element.size() == 2 and element[0].is_string();
1627  });
1628 
1629  // adjust type if type deduction is not wanted
1630  if (not type_deduction)
1631  {
1632  // if array is wanted, do not create an object though possible
1633  if (manual_type == value_t::array)
1634  {
1635  is_an_object = false;
1636  }
1637 
1638  // if object is wanted but impossible, throw an exception
1639  if (manual_type == value_t::object and not is_an_object)
1640  {
1641  throw std::domain_error("cannot create object from initializer list");
1642  }
1643  }
1644 
1645  if (is_an_object)
1646  {
1647  // the initializer list is a list of pairs -> create object
1648  m_type = value_t::object;
1649  m_value = value_t::object;
1650 
1651  std::for_each(init.begin(), init.end(), [this](const basic_json & element)
1652  {
1653  m_value.object->emplace(*(element[0].m_value.string), element[1]);
1654  });
1655  }
1656  else
1657  {
1658  // the initializer list describes an array -> create array
1659  m_type = value_t::array;
1660  m_value.array = create<array_t>(init);
1661  }
1662 
1663  assert_invariant();
1664  }
1665 
1700  static basic_json array(std::initializer_list<basic_json> init =
1701  std::initializer_list<basic_json>())
1702  {
1703  return basic_json(init, false, value_t::array);
1704  }
1705 
1740  static basic_json object(std::initializer_list<basic_json> init =
1741  std::initializer_list<basic_json>())
1742  {
1743  return basic_json(init, false, value_t::object);
1744  }
1745 
1765  : m_type(value_t::array)
1766  {
1767  m_value.array = create<array_t>(cnt, val);
1768  assert_invariant();
1769  }
1770 
1808  template<class InputIT, typename std::enable_if<
1809  std::is_same<InputIT, typename basic_json_t::iterator>::value or
1810  std::is_same<InputIT, typename basic_json_t::const_iterator>::value, int>::type = 0>
1811  basic_json(InputIT first, InputIT last)
1812  {
1813  assert(first.m_object != nullptr);
1814  assert(last.m_object != nullptr);
1815 
1816  // make sure iterator fits the current value
1817  if (first.m_object != last.m_object)
1818  {
1819  throw std::domain_error("iterators are not compatible");
1820  }
1821 
1822  // copy type from first iterator
1823  m_type = first.m_object->m_type;
1824 
1825  // check if iterator range is complete for primitive values
1826  switch (m_type)
1827  {
1828  case value_t::boolean:
1829  case value_t::number_float:
1830  case value_t::number_integer:
1831  case value_t::number_unsigned:
1832  case value_t::string:
1833  {
1834  if (not first.m_it.primitive_iterator.is_begin() or not last.m_it.primitive_iterator.is_end())
1835  {
1836  throw std::out_of_range("iterators out of range");
1837  }
1838  break;
1839  }
1840 
1841  default:
1842  {
1843  break;
1844  }
1845  }
1846 
1847  switch (m_type)
1848  {
1849  case value_t::number_integer:
1850  {
1851  m_value.number_integer = first.m_object->m_value.number_integer;
1852  break;
1853  }
1854 
1855  case value_t::number_unsigned:
1856  {
1857  m_value.number_unsigned = first.m_object->m_value.number_unsigned;
1858  break;
1859  }
1860 
1861  case value_t::number_float:
1862  {
1863  m_value.number_float = first.m_object->m_value.number_float;
1864  break;
1865  }
1866 
1867  case value_t::boolean:
1868  {
1869  m_value.boolean = first.m_object->m_value.boolean;
1870  break;
1871  }
1872 
1873  case value_t::string:
1874  {
1875  m_value = *first.m_object->m_value.string;
1876  break;
1877  }
1878 
1879  case value_t::object:
1880  {
1881  m_value.object = create<object_t>(first.m_it.object_iterator, last.m_it.object_iterator);
1882  break;
1883  }
1884 
1885  case value_t::array:
1886  {
1887  m_value.array = create<array_t>(first.m_it.array_iterator, last.m_it.array_iterator);
1888  break;
1889  }
1890 
1891  default:
1892  {
1893  throw std::domain_error("cannot use construct with iterators from " + first.m_object->type_name());
1894  }
1895  }
1896 
1897  assert_invariant();
1898  }
1899 
1928  JSON_DEPRECATED
1929  explicit basic_json(std::istream& i, const parser_callback_t cb = nullptr)
1930  {
1931  *this = parser(i, cb).parse();
1932  assert_invariant();
1933  }
1934 
1936  // other constructors and destructor //
1938 
1961  basic_json(const basic_json& other)
1962  : m_type(other.m_type)
1963  {
1964  // check of passed value is valid
1965  other.assert_invariant();
1966 
1967  switch (m_type)
1968  {
1969  case value_t::object:
1970  {
1971  m_value = *other.m_value.object;
1972  break;
1973  }
1974 
1975  case value_t::array:
1976  {
1977  m_value = *other.m_value.array;
1978  break;
1979  }
1980 
1981  case value_t::string:
1982  {
1983  m_value = *other.m_value.string;
1984  break;
1985  }
1986 
1987  case value_t::boolean:
1988  {
1989  m_value = other.m_value.boolean;
1990  break;
1991  }
1992 
1993  case value_t::number_integer:
1994  {
1995  m_value = other.m_value.number_integer;
1996  break;
1997  }
1998 
1999  case value_t::number_unsigned:
2000  {
2001  m_value = other.m_value.number_unsigned;
2002  break;
2003  }
2004 
2005  case value_t::number_float:
2006  {
2007  m_value = other.m_value.number_float;
2008  break;
2009  }
2010 
2011  default:
2012  {
2013  break;
2014  }
2015  }
2016 
2017  assert_invariant();
2018  }
2019 
2038  basic_json(basic_json&& other) noexcept
2039  : m_type(std::move(other.m_type)),
2040  m_value(std::move(other.m_value))
2041  {
2042  // check that passed value is valid
2043  other.assert_invariant();
2044 
2045  // invalidate payload
2046  other.m_type = value_t::null;
2047  other.m_value = {};
2048 
2049  assert_invariant();
2050  }
2051 
2075  reference& operator=(basic_json other) noexcept (
2076  std::is_nothrow_move_constructible<value_t>::value and
2077  std::is_nothrow_move_assignable<value_t>::value and
2078  std::is_nothrow_move_constructible<json_value>::value and
2079  std::is_nothrow_move_assignable<json_value>::value
2080  )
2081  {
2082  // check that passed value is valid
2083  other.assert_invariant();
2084 
2085  using std::swap;
2086  swap(m_type, other.m_type);
2087  swap(m_value, other.m_value);
2088 
2089  assert_invariant();
2090  return *this;
2091  }
2092 
2109  {
2110  assert_invariant();
2111 
2112  switch (m_type)
2113  {
2114  case value_t::object:
2115  {
2116  AllocatorType<object_t> alloc;
2117  alloc.destroy(m_value.object);
2118  alloc.deallocate(m_value.object, 1);
2119  break;
2120  }
2121 
2122  case value_t::array:
2123  {
2124  AllocatorType<array_t> alloc;
2125  alloc.destroy(m_value.array);
2126  alloc.deallocate(m_value.array, 1);
2127  break;
2128  }
2129 
2130  case value_t::string:
2131  {
2132  AllocatorType<string_t> alloc;
2133  alloc.destroy(m_value.string);
2134  alloc.deallocate(m_value.string, 1);
2135  break;
2136  }
2137 
2138  default:
2139  {
2140  // all other types need no specific destructor
2141  break;
2142  }
2143  }
2144  }
2145 
2147 
2148  public:
2150  // object inspection //
2152 
2156 
2180  string_t dump(const int indent = -1) const
2181  {
2182  std::stringstream ss;
2183  // fix locale problems
2184  ss.imbue(std::locale::classic());
2185 
2186  // 6, 15 or 16 digits of precision allows round-trip IEEE 754
2187  // string->float->string, string->double->string or string->long
2188  // double->string; to be safe, we read this value from
2189  // std::numeric_limits<number_float_t>::digits10
2190  ss.precision(std::numeric_limits<double>::digits10);
2191 
2192  if (indent >= 0)
2193  {
2194  dump(ss, true, static_cast<unsigned int>(indent));
2195  }
2196  else
2197  {
2198  dump(ss, false, 0);
2199  }
2200 
2201  return ss.str();
2202  }
2203 
2222  constexpr value_t type() const noexcept
2223  {
2224  return m_type;
2225  }
2226 
2252  constexpr bool is_primitive() const noexcept
2253  {
2254  return is_null() or is_string() or is_boolean() or is_number();
2255  }
2256 
2279  constexpr bool is_structured() const noexcept
2280  {
2281  return is_array() or is_object();
2282  }
2283 
2301  constexpr bool is_null() const noexcept
2302  {
2303  return m_type == value_t::null;
2304  }
2305 
2323  constexpr bool is_boolean() const noexcept
2324  {
2325  return m_type == value_t::boolean;
2326  }
2327 
2353  constexpr bool is_number() const noexcept
2354  {
2355  return is_number_integer() or is_number_float();
2356  }
2357 
2382  constexpr bool is_number_integer() const noexcept
2383  {
2384  return m_type == value_t::number_integer or m_type == value_t::number_unsigned;
2385  }
2386 
2410  constexpr bool is_number_unsigned() const noexcept
2411  {
2412  return m_type == value_t::number_unsigned;
2413  }
2414 
2438  constexpr bool is_number_float() const noexcept
2439  {
2440  return m_type == value_t::number_float;
2441  }
2442 
2460  constexpr bool is_object() const noexcept
2461  {
2462  return m_type == value_t::object;
2463  }
2464 
2482  constexpr bool is_array() const noexcept
2483  {
2484  return m_type == value_t::array;
2485  }
2486 
2504  constexpr bool is_string() const noexcept
2505  {
2506  return m_type == value_t::string;
2507  }
2508 
2531  constexpr bool is_discarded() const noexcept
2532  {
2533  return m_type == value_t::discarded;
2534  }
2535 
2554  constexpr operator value_t() const noexcept
2555  {
2556  return m_type;
2557  }
2558 
2560 
2561  private:
2563  // value access //
2565 
2567  template<class T, typename std::enable_if<
2568  std::is_convertible<typename object_t::key_type, typename T::key_type>::value and
2569  std::is_convertible<basic_json_t, typename T::mapped_type>::value, int>::type = 0>
2570  T get_impl(T*) const
2571  {
2572  if (is_object())
2573  {
2574  return T(m_value.object->begin(), m_value.object->end());
2575  }
2576  else
2577  {
2578  throw std::domain_error("type must be object, but is " + type_name());
2579  }
2580  }
2581 
2583  object_t get_impl(object_t*) const
2584  {
2585  if (is_object())
2586  {
2587  return *(m_value.object);
2588  }
2589  else
2590  {
2591  throw std::domain_error("type must be object, but is " + type_name());
2592  }
2593  }
2594 
2596  template<class T, typename std::enable_if<
2597  std::is_convertible<basic_json_t, typename T::value_type>::value and
2598  not std::is_same<basic_json_t, typename T::value_type>::value and
2599  not std::is_arithmetic<T>::value and
2600  not std::is_convertible<std::string, T>::value and
2601  not has_mapped_type<T>::value, int>::type = 0>
2602  T get_impl(T*) const
2603  {
2604  if (is_array())
2605  {
2606  T to_vector;
2607  std::transform(m_value.array->begin(), m_value.array->end(),
2608  std::inserter(to_vector, to_vector.end()), [](basic_json i)
2609  {
2610  return i.get<typename T::value_type>();
2611  });
2612  return to_vector;
2613  }
2614  else
2615  {
2616  throw std::domain_error("type must be array, but is " + type_name());
2617  }
2618  }
2619 
2621  template<class T, typename std::enable_if<
2622  std::is_convertible<basic_json_t, T>::value and
2623  not std::is_same<basic_json_t, T>::value, int>::type = 0>
2624  std::vector<T> get_impl(std::vector<T>*) const
2625  {
2626  if (is_array())
2627  {
2628  std::vector<T> to_vector;
2629  to_vector.reserve(m_value.array->size());
2630  std::transform(m_value.array->begin(), m_value.array->end(),
2631  std::inserter(to_vector, to_vector.end()), [](basic_json i)
2632  {
2633  return i.get<T>();
2634  });
2635  return to_vector;
2636  }
2637  else
2638  {
2639  throw std::domain_error("type must be array, but is " + type_name());
2640  }
2641  }
2642 
2644  template<class T, typename std::enable_if<
2645  std::is_same<basic_json, typename T::value_type>::value and
2646  not has_mapped_type<T>::value, int>::type = 0>
2647  T get_impl(T*) const
2648  {
2649  if (is_array())
2650  {
2651  return T(m_value.array->begin(), m_value.array->end());
2652  }
2653  else
2654  {
2655  throw std::domain_error("type must be array, but is " + type_name());
2656  }
2657  }
2658 
2660  array_t get_impl(array_t*) const
2661  {
2662  if (is_array())
2663  {
2664  return *(m_value.array);
2665  }
2666  else
2667  {
2668  throw std::domain_error("type must be array, but is " + type_name());
2669  }
2670  }
2671 
2673  template<typename T, typename std::enable_if<
2674  std::is_convertible<string_t, T>::value, int>::type = 0>
2675  T get_impl(T*) const
2676  {
2677  if (is_string())
2678  {
2679  return *m_value.string;
2680  }
2681  else
2682  {
2683  throw std::domain_error("type must be string, but is " + type_name());
2684  }
2685  }
2686 
2688  template<typename T, typename std::enable_if<
2689  std::is_arithmetic<T>::value, int>::type = 0>
2690  T get_impl(T*) const
2691  {
2692  switch (m_type)
2693  {
2694  case value_t::number_integer:
2695  {
2696  return static_cast<T>(m_value.number_integer);
2697  }
2698 
2699  case value_t::number_unsigned:
2700  {
2701  return static_cast<T>(m_value.number_unsigned);
2702  }
2703 
2704  case value_t::number_float:
2705  {
2706  return static_cast<T>(m_value.number_float);
2707  }
2708 
2709  default:
2710  {
2711  throw std::domain_error("type must be number, but is " + type_name());
2712  }
2713  }
2714  }
2715 
2717  constexpr boolean_t get_impl(boolean_t*) const
2718  {
2719  return is_boolean()
2720  ? m_value.boolean
2721  : throw std::domain_error("type must be boolean, but is " + type_name());
2722  }
2723 
2725  object_t* get_impl_ptr(object_t*) noexcept
2726  {
2727  return is_object() ? m_value.object : nullptr;
2728  }
2729 
2731  constexpr const object_t* get_impl_ptr(const object_t*) const noexcept
2732  {
2733  return is_object() ? m_value.object : nullptr;
2734  }
2735 
2737  array_t* get_impl_ptr(array_t*) noexcept
2738  {
2739  return is_array() ? m_value.array : nullptr;
2740  }
2741 
2743  constexpr const array_t* get_impl_ptr(const array_t*) const noexcept
2744  {
2745  return is_array() ? m_value.array : nullptr;
2746  }
2747 
2749  string_t* get_impl_ptr(string_t*) noexcept
2750  {
2751  return is_string() ? m_value.string : nullptr;
2752  }
2753 
2755  constexpr const string_t* get_impl_ptr(const string_t*) const noexcept
2756  {
2757  return is_string() ? m_value.string : nullptr;
2758  }
2759 
2761  boolean_t* get_impl_ptr(boolean_t*) noexcept
2762  {
2763  return is_boolean() ? &m_value.boolean : nullptr;
2764  }
2765 
2767  constexpr const boolean_t* get_impl_ptr(const boolean_t*) const noexcept
2768  {
2769  return is_boolean() ? &m_value.boolean : nullptr;
2770  }
2771 
2773  number_integer_t* get_impl_ptr(number_integer_t*) noexcept
2774  {
2775  return is_number_integer() ? &m_value.number_integer : nullptr;
2776  }
2777 
2779  constexpr const number_integer_t* get_impl_ptr(const number_integer_t*) const noexcept
2780  {
2781  return is_number_integer() ? &m_value.number_integer : nullptr;
2782  }
2783 
2785  number_unsigned_t* get_impl_ptr(number_unsigned_t*) noexcept
2786  {
2787  return is_number_unsigned() ? &m_value.number_unsigned : nullptr;
2788  }
2789 
2791  constexpr const number_unsigned_t* get_impl_ptr(const number_unsigned_t*) const noexcept
2792  {
2793  return is_number_unsigned() ? &m_value.number_unsigned : nullptr;
2794  }
2795 
2797  number_float_t* get_impl_ptr(number_float_t*) noexcept
2798  {
2799  return is_number_float() ? &m_value.number_float : nullptr;
2800  }
2801 
2803  constexpr const number_float_t* get_impl_ptr(const number_float_t*) const noexcept
2804  {
2805  return is_number_float() ? &m_value.number_float : nullptr;
2806  }
2807 
2819  template<typename ReferenceType, typename ThisType>
2820  static ReferenceType get_ref_impl(ThisType& obj)
2821  {
2822  // helper type
2823  using PointerType = typename std::add_pointer<ReferenceType>::type;
2824 
2825  // delegate the call to get_ptr<>()
2826  auto ptr = obj.template get_ptr<PointerType>();
2827 
2828  if (ptr != nullptr)
2829  {
2830  return *ptr;
2831  }
2832  else
2833  {
2834  throw std::domain_error("incompatible ReferenceType for get_ref, actual type is " +
2835  obj.type_name());
2836  }
2837  }
2838 
2839  public:
2840 
2844 
2878  template<typename ValueType, typename std::enable_if<
2879  not std::is_pointer<ValueType>::value, int>::type = 0>
2880  ValueType get() const
2881  {
2882  return get_impl(static_cast<ValueType*>(nullptr));
2883  }
2884 
2912  template<typename PointerType, typename std::enable_if<
2913  std::is_pointer<PointerType>::value, int>::type = 0>
2914  PointerType get() noexcept
2915  {
2916  // delegate the call to get_ptr
2917  return get_ptr<PointerType>();
2918  }
2919 
2924  template<typename PointerType, typename std::enable_if<
2925  std::is_pointer<PointerType>::value, int>::type = 0>
2926  constexpr const PointerType get() const noexcept
2927  {
2928  // delegate the call to get_ptr
2929  return get_ptr<PointerType>();
2930  }
2931 
2958  template<typename PointerType, typename std::enable_if<
2959  std::is_pointer<PointerType>::value, int>::type = 0>
2960  PointerType get_ptr() noexcept
2961  {
2962  // get the type of the PointerType (remove pointer and const)
2963  using pointee_t = typename std::remove_const<typename
2964  std::remove_pointer<typename
2965  std::remove_const<PointerType>::type>::type>::type;
2966  // make sure the type matches the allowed types
2967  static_assert(
2968  std::is_same<object_t, pointee_t>::value
2969  or std::is_same<array_t, pointee_t>::value
2970  or std::is_same<string_t, pointee_t>::value
2971  or std::is_same<boolean_t, pointee_t>::value
2972  or std::is_same<number_integer_t, pointee_t>::value
2973  or std::is_same<number_unsigned_t, pointee_t>::value
2974  or std::is_same<number_float_t, pointee_t>::value
2975  , "incompatible pointer type");
2976 
2977  // delegate the call to get_impl_ptr<>()
2978  return get_impl_ptr(static_cast<PointerType>(nullptr));
2979  }
2980 
2985  template<typename PointerType, typename std::enable_if<
2986  std::is_pointer<PointerType>::value and
2987  std::is_const<typename std::remove_pointer<PointerType>::type>::value, int>::type = 0>
2988  constexpr const PointerType get_ptr() const noexcept
2989  {
2990  // get the type of the PointerType (remove pointer and const)
2991  using pointee_t = typename std::remove_const<typename
2992  std::remove_pointer<typename
2993  std::remove_const<PointerType>::type>::type>::type;
2994  // make sure the type matches the allowed types
2995  static_assert(
2996  std::is_same<object_t, pointee_t>::value
2997  or std::is_same<array_t, pointee_t>::value
2998  or std::is_same<string_t, pointee_t>::value
2999  or std::is_same<boolean_t, pointee_t>::value
3000  or std::is_same<number_integer_t, pointee_t>::value
3001  or std::is_same<number_unsigned_t, pointee_t>::value
3002  or std::is_same<number_float_t, pointee_t>::value
3003  , "incompatible pointer type");
3004 
3005  // delegate the call to get_impl_ptr<>() const
3006  return get_impl_ptr(static_cast<const PointerType>(nullptr));
3007  }
3008 
3035  template<typename ReferenceType, typename std::enable_if<
3036  std::is_reference<ReferenceType>::value, int>::type = 0>
3037  ReferenceType get_ref()
3038  {
3039  // delegate call to get_ref_impl
3040  return get_ref_impl<ReferenceType>(*this);
3041  }
3042 
3047  template<typename ReferenceType, typename std::enable_if<
3048  std::is_reference<ReferenceType>::value and
3049  std::is_const<typename std::remove_reference<ReferenceType>::type>::value, int>::type = 0>
3050  ReferenceType get_ref() const
3051  {
3052  // delegate call to get_ref_impl
3053  return get_ref_impl<ReferenceType>(*this);
3054  }
3055 
3084  template < typename ValueType, typename std::enable_if <
3085  not std::is_pointer<ValueType>::value and
3086  not std::is_same<ValueType, typename string_t::value_type>::value
3087 #ifndef _MSC_VER // Fix for issue #167 operator<< abiguity under VS2015
3088  and not std::is_same<ValueType, std::initializer_list<typename string_t::value_type>>::value
3089 #endif
3090  , int >::type = 0 >
3091  operator ValueType() const
3092  {
3093  // delegate the call to get<>() const
3094  return get<ValueType>();
3095  }
3096 
3098 
3099 
3101  // element access //
3103 
3107 
3131  {
3132  // at only works for arrays
3133  if (is_array())
3134  {
3135  try
3136  {
3137  return m_value.array->at(idx);
3138  }
3139  catch (std::out_of_range&)
3140  {
3141  // create better exception explanation
3142  throw std::out_of_range("array index " + std::to_string(idx) + " is out of range");
3143  }
3144  }
3145  else
3146  {
3147  throw std::domain_error("cannot use at() with " + type_name());
3148  }
3149  }
3150 
3174  {
3175  // at only works for arrays
3176  if (is_array())
3177  {
3178  try
3179  {
3180  return m_value.array->at(idx);
3181  }
3182  catch (std::out_of_range&)
3183  {
3184  // create better exception explanation
3185  throw std::out_of_range("array index " + std::to_string(idx) + " is out of range");
3186  }
3187  }
3188  else
3189  {
3190  throw std::domain_error("cannot use at() with " + type_name());
3191  }
3192  }
3193 
3220  reference at(const typename object_t::key_type& key)
3221  {
3222  // at only works for objects
3223  if (is_object())
3224  {
3225  try
3226  {
3227  return m_value.object->at(key);
3228  }
3229  catch (std::out_of_range&)
3230  {
3231  // create better exception explanation
3232  throw std::out_of_range("key '" + key + "' not found");
3233  }
3234  }
3235  else
3236  {
3237  throw std::domain_error("cannot use at() with " + type_name());
3238  }
3239  }
3240 
3267  const_reference at(const typename object_t::key_type& key) const
3268  {
3269  // at only works for objects
3270  if (is_object())
3271  {
3272  try
3273  {
3274  return m_value.object->at(key);
3275  }
3276  catch (std::out_of_range&)
3277  {
3278  // create better exception explanation
3279  throw std::out_of_range("key '" + key + "' not found");
3280  }
3281  }
3282  else
3283  {
3284  throw std::domain_error("cannot use at() with " + type_name());
3285  }
3286  }
3287 
3314  {
3315  // implicitly convert null value to an empty array
3316  if (is_null())
3317  {
3318  m_type = value_t::array;
3319  m_value.array = create<array_t>();
3320  assert_invariant();
3321  }
3322 
3323  // operator[] only works for arrays
3324  if (is_array())
3325  {
3326  // fill up array with null values if given idx is outside range
3327  if (idx >= m_value.array->size())
3328  {
3329  m_value.array->insert(m_value.array->end(),
3330  idx - m_value.array->size() + 1,
3331  basic_json());
3332  }
3333 
3334  return m_value.array->operator[](idx);
3335  }
3336  else
3337  {
3338  throw std::domain_error("cannot use operator[] with " + type_name());
3339  }
3340  }
3341 
3362  {
3363  // const operator[] only works for arrays
3364  if (is_array())
3365  {
3366  return m_value.array->operator[](idx);
3367  }
3368  else
3369  {
3370  throw std::domain_error("cannot use operator[] with " + type_name());
3371  }
3372  }
3373 
3401  reference operator[](const typename object_t::key_type& key)
3402  {
3403  // implicitly convert null value to an empty object
3404  if (is_null())
3405  {
3406  m_type = value_t::object;
3407  m_value.object = create<object_t>();
3408  assert_invariant();
3409  }
3410 
3411  // operator[] only works for objects
3412  if (is_object())
3413  {
3414  return m_value.object->operator[](key);
3415  }
3416  else
3417  {
3418  throw std::domain_error("cannot use operator[] with " + type_name());
3419  }
3420  }
3421 
3452  const_reference operator[](const typename object_t::key_type& key) const
3453  {
3454  // const operator[] only works for objects
3455  if (is_object())
3456  {
3457  assert(m_value.object->find(key) != m_value.object->end());
3458  return m_value.object->find(key)->second;
3459  }
3460  else
3461  {
3462  throw std::domain_error("cannot use operator[] with " + type_name());
3463  }
3464  }
3465 
3493  template<typename T, std::size_t n>
3494  reference operator[](T * (&key)[n])
3495  {
3496  return operator[](static_cast<const T>(key));
3497  }
3498 
3528  template<typename T, std::size_t n>
3529  const_reference operator[](T * (&key)[n]) const
3530  {
3531  return operator[](static_cast<const T>(key));
3532  }
3533 
3561  template<typename T>
3563  {
3564  // implicitly convert null to object
3565  if (is_null())
3566  {
3567  m_type = value_t::object;
3568  m_value = value_t::object;
3569  assert_invariant();
3570  }
3571 
3572  // at only works for objects
3573  if (is_object())
3574  {
3575  return m_value.object->operator[](key);
3576  }
3577  else
3578  {
3579  throw std::domain_error("cannot use operator[] with " + type_name());
3580  }
3581  }
3582 
3613  template<typename T>
3615  {
3616  // at only works for objects
3617  if (is_object())
3618  {
3619  assert(m_value.object->find(key) != m_value.object->end());
3620  return m_value.object->find(key)->second;
3621  }
3622  else
3623  {
3624  throw std::domain_error("cannot use operator[] with " + type_name());
3625  }
3626  }
3627 
3676  template<class ValueType, typename std::enable_if<
3677  std::is_convertible<basic_json_t, ValueType>::value, int>::type = 0>
3678  ValueType value(const typename object_t::key_type& key, ValueType default_value) const
3679  {
3680  // at only works for objects
3681  if (is_object())
3682  {
3683  // if key is found, return value and given default value otherwise
3684  const auto it = find(key);
3685  if (it != end())
3686  {
3687  return *it;
3688  }
3689  else
3690  {
3691  return default_value;
3692  }
3693  }
3694  else
3695  {
3696  throw std::domain_error("cannot use value() with " + type_name());
3697  }
3698  }
3699 
3704  string_t value(const typename object_t::key_type& key, const char* default_value) const
3705  {
3706  return value(key, string_t(default_value));
3707  }
3708 
3750  template<class ValueType, typename std::enable_if<
3751  std::is_convertible<basic_json_t, ValueType>::value, int>::type = 0>
3752  ValueType value(const json_pointer& ptr, ValueType default_value) const
3753  {
3754  // at only works for objects
3755  if (is_object())
3756  {
3757  // if pointer resolves a value, return it or use default value
3758  try
3759  {
3760  return ptr.get_checked(this);
3761  }
3762  catch (std::out_of_range&)
3763  {
3764  return default_value;
3765  }
3766  }
3767  else
3768  {
3769  throw std::domain_error("cannot use value() with " + type_name());
3770  }
3771  }
3772 
3777  string_t value(const json_pointer& ptr, const char* default_value) const
3778  {
3779  return value(ptr, string_t(default_value));
3780  }
3781 
3808  {
3809  return *begin();
3810  }
3811 
3816  {
3817  return *cbegin();
3818  }
3819 
3851  {
3852  auto tmp = end();
3853  --tmp;
3854  return *tmp;
3855  }
3856 
3861  {
3862  auto tmp = cend();
3863  --tmp;
3864  return *tmp;
3865  }
3866 
3912  template<class IteratorType, typename std::enable_if<
3913  std::is_same<IteratorType, typename basic_json_t::iterator>::value or
3914  std::is_same<IteratorType, typename basic_json_t::const_iterator>::value, int>::type
3915  = 0>
3916  IteratorType erase(IteratorType pos)
3917  {
3918  // make sure iterator fits the current value
3919  if (this != pos.m_object)
3920  {
3921  throw std::domain_error("iterator does not fit current value");
3922  }
3923 
3924  IteratorType result = end();
3925 
3926  switch (m_type)
3927  {
3928  case value_t::boolean:
3929  case value_t::number_float:
3930  case value_t::number_integer:
3931  case value_t::number_unsigned:
3932  case value_t::string:
3933  {
3934  if (not pos.m_it.primitive_iterator.is_begin())
3935  {
3936  throw std::out_of_range("iterator out of range");
3937  }
3938 
3939  if (is_string())
3940  {
3941  AllocatorType<string_t> alloc;
3942  alloc.destroy(m_value.string);
3943  alloc.deallocate(m_value.string, 1);
3944  m_value.string = nullptr;
3945  }
3946 
3947  m_type = value_t::null;
3948  assert_invariant();
3949  break;
3950  }
3951 
3952  case value_t::object:
3953  {
3954  result.m_it.object_iterator = m_value.object->erase(pos.m_it.object_iterator);
3955  break;
3956  }
3957 
3958  case value_t::array:
3959  {
3960  result.m_it.array_iterator = m_value.array->erase(pos.m_it.array_iterator);
3961  break;
3962  }
3963 
3964  default:
3965  {
3966  throw std::domain_error("cannot use erase() with " + type_name());
3967  }
3968  }
3969 
3970  return result;
3971  }
3972 
4019  template<class IteratorType, typename std::enable_if<
4020  std::is_same<IteratorType, typename basic_json_t::iterator>::value or
4021  std::is_same<IteratorType, typename basic_json_t::const_iterator>::value, int>::type
4022  = 0>
4023  IteratorType erase(IteratorType first, IteratorType last)
4024  {
4025  // make sure iterator fits the current value
4026  if (this != first.m_object or this != last.m_object)
4027  {
4028  throw std::domain_error("iterators do not fit current value");
4029  }
4030 
4031  IteratorType result = end();
4032 
4033  switch (m_type)
4034  {
4035  case value_t::boolean:
4036  case value_t::number_float:
4037  case value_t::number_integer:
4038  case value_t::number_unsigned:
4039  case value_t::string:
4040  {
4041  if (not first.m_it.primitive_iterator.is_begin() or not last.m_it.primitive_iterator.is_end())
4042  {
4043  throw std::out_of_range("iterators out of range");
4044  }
4045 
4046  if (is_string())
4047  {
4048  AllocatorType<string_t> alloc;
4049  alloc.destroy(m_value.string);
4050  alloc.deallocate(m_value.string, 1);
4051  m_value.string = nullptr;
4052  }
4053 
4054  m_type = value_t::null;
4055  assert_invariant();
4056  break;
4057  }
4058 
4059  case value_t::object:
4060  {
4061  result.m_it.object_iterator = m_value.object->erase(first.m_it.object_iterator,
4062  last.m_it.object_iterator);
4063  break;
4064  }
4065 
4066  case value_t::array:
4067  {
4068  result.m_it.array_iterator = m_value.array->erase(first.m_it.array_iterator,
4069  last.m_it.array_iterator);
4070  break;
4071  }
4072 
4073  default:
4074  {
4075  throw std::domain_error("cannot use erase() with " + type_name());
4076  }
4077  }
4078 
4079  return result;
4080  }
4081 
4111  size_type erase(const typename object_t::key_type& key)
4112  {
4113  // this erase only works for objects
4114  if (is_object())
4115  {
4116  return m_value.object->erase(key);
4117  }
4118  else
4119  {
4120  throw std::domain_error("cannot use erase() with " + type_name());
4121  }
4122  }
4123 
4148  void erase(const size_type idx)
4149  {
4150  // this erase only works for arrays
4151  if (is_array())
4152  {
4153  if (idx >= size())
4154  {
4155  throw std::out_of_range("array index " + std::to_string(idx) + " is out of range");
4156  }
4157 
4158  m_value.array->erase(m_value.array->begin() + static_cast<difference_type>(idx));
4159  }
4160  else
4161  {
4162  throw std::domain_error("cannot use erase() with " + type_name());
4163  }
4164  }
4165 
4167 
4168 
4170  // lookup //
4172 
4175 
4194  iterator find(typename object_t::key_type key)
4195  {
4196  auto result = end();
4197 
4198  if (is_object())
4199  {
4200  result.m_it.object_iterator = m_value.object->find(key);
4201  }
4202 
4203  return result;
4204  }
4205 
4210  const_iterator find(typename object_t::key_type key) const
4211  {
4212  auto result = cend();
4213 
4214  if (is_object())
4215  {
4216  result.m_it.object_iterator = m_value.object->find(key);
4217  }
4218 
4219  return result;
4220  }
4221 
4240  size_type count(typename object_t::key_type key) const
4241  {
4242  // return 0 for all nonobject types
4243  return is_object() ? m_value.object->count(key) : 0;
4244  }
4245 
4247 
4248 
4250  // iterators //
4252 
4255 
4280  iterator begin() noexcept
4281  {
4282  iterator result(this);
4283  result.set_begin();
4284  return result;
4285  }
4286 
4290  const_iterator begin() const noexcept
4291  {
4292  return cbegin();
4293  }
4294 
4320  const_iterator cbegin() const noexcept
4321  {
4322  const_iterator result(this);
4323  result.set_begin();
4324  return result;
4325  }
4326 
4351  iterator end() noexcept
4352  {
4353  iterator result(this);
4354  result.set_end();
4355  return result;
4356  }
4357 
4361  const_iterator end() const noexcept
4362  {
4363  return cend();
4364  }
4365 
4391  const_iterator cend() const noexcept
4392  {
4393  const_iterator result(this);
4394  result.set_end();
4395  return result;
4396  }
4397 
4422  {
4423  return reverse_iterator(end());
4424  }
4425 
4430  {
4431  return crbegin();
4432  }
4433 
4459  {
4460  return reverse_iterator(begin());
4461  }
4462 
4466  const_reverse_iterator rend() const noexcept
4467  {
4468  return crend();
4469  }
4470 
4496  {
4497  return const_reverse_iterator(cend());
4498  }
4499 
4525  {
4526  return const_reverse_iterator(cbegin());
4527  }
4528 
4529  private:
4530  // forward declaration
4531  template<typename IteratorType> class iteration_proxy;
4532 
4533  public:
4545  static iteration_proxy<iterator> iterator_wrapper(reference cont)
4546  {
4547  return iteration_proxy<iterator>(cont);
4548  }
4549 
4553  static iteration_proxy<const_iterator> iterator_wrapper(const_reference cont)
4554  {
4555  return iteration_proxy<const_iterator>(cont);
4556  }
4557 
4559 
4560 
4562  // capacity //
4564 
4567 
4605  bool empty() const noexcept
4606  {
4607  switch (m_type)
4608  {
4609  case value_t::null:
4610  {
4611  // null values are empty
4612  return true;
4613  }
4614 
4615  case value_t::array:
4616  {
4617  // delegate call to array_t::empty()
4618  return m_value.array->empty();
4619  }
4620 
4621  case value_t::object:
4622  {
4623  // delegate call to object_t::empty()
4624  return m_value.object->empty();
4625  }
4626 
4627  default:
4628  {
4629  // all other types are nonempty
4630  return false;
4631  }
4632  }
4633  }
4634 
4673  size_type size() const noexcept
4674  {
4675  switch (m_type)
4676  {
4677  case value_t::null:
4678  {
4679  // null values are empty
4680  return 0;
4681  }
4682 
4683  case value_t::array:
4684  {
4685  // delegate call to array_t::size()
4686  return m_value.array->size();
4687  }
4688 
4689  case value_t::object:
4690  {
4691  // delegate call to object_t::size()
4692  return m_value.object->size();
4693  }
4694 
4695  default:
4696  {
4697  // all other types have size 1
4698  return 1;
4699  }
4700  }
4701  }
4702 
4739  size_type max_size() const noexcept
4740  {
4741  switch (m_type)
4742  {
4743  case value_t::array:
4744  {
4745  // delegate call to array_t::max_size()
4746  return m_value.array->max_size();
4747  }
4748 
4749  case value_t::object:
4750  {
4751  // delegate call to object_t::max_size()
4752  return m_value.object->max_size();
4753  }
4754 
4755  default:
4756  {
4757  // all other types have max_size() == size()
4758  return size();
4759  }
4760  }
4761  }
4762 
4764 
4765 
4767  // modifiers //
4769 
4772 
4798  void clear() noexcept
4799  {
4800  switch (m_type)
4801  {
4802  case value_t::number_integer:
4803  {
4804  m_value.number_integer = 0;
4805  break;
4806  }
4807 
4808  case value_t::number_unsigned:
4809  {
4810  m_value.number_unsigned = 0;
4811  break;
4812  }
4813 
4814  case value_t::number_float:
4815  {
4816  m_value.number_float = 0.0;
4817  break;
4818  }
4819 
4820  case value_t::boolean:
4821  {
4822  m_value.boolean = false;
4823  break;
4824  }
4825 
4826  case value_t::string:
4827  {
4828  m_value.string->clear();
4829  break;
4830  }
4831 
4832  case value_t::array:
4833  {
4834  m_value.array->clear();
4835  break;
4836  }
4837 
4838  case value_t::object:
4839  {
4840  m_value.object->clear();
4841  break;
4842  }
4843 
4844  default:
4845  {
4846  break;
4847  }
4848  }
4849  }
4850 
4871  void push_back(basic_json&& val)
4872  {
4873  // push_back only works for null objects or arrays
4874  if (not(is_null() or is_array()))
4875  {
4876  throw std::domain_error("cannot use push_back() with " + type_name());
4877  }
4878 
4879  // transform null object into an array
4880  if (is_null())
4881  {
4882  m_type = value_t::array;
4883  m_value = value_t::array;
4884  assert_invariant();
4885  }
4886 
4887  // add element to array (move semantics)
4888  m_value.array->push_back(std::move(val));
4889  // invalidate object
4890  val.m_type = value_t::null;
4891  }
4892 
4898  {
4899  push_back(std::move(val));
4900  return *this;
4901  }
4902 
4907  void push_back(const basic_json& val)
4908  {
4909  // push_back only works for null objects or arrays
4910  if (not(is_null() or is_array()))
4911  {
4912  throw std::domain_error("cannot use push_back() with " + type_name());
4913  }
4914 
4915  // transform null object into an array
4916  if (is_null())
4917  {
4918  m_type = value_t::array;
4919  m_value = value_t::array;
4920  assert_invariant();
4921  }
4922 
4923  // add element to array
4924  m_value.array->push_back(val);
4925  }
4926 
4932  {
4933  push_back(val);
4934  return *this;
4935  }
4936 
4957  void push_back(const typename object_t::value_type& val)
4958  {
4959  // push_back only works for null objects or objects
4960  if (not(is_null() or is_object()))
4961  {
4962  throw std::domain_error("cannot use push_back() with " + type_name());
4963  }
4964 
4965  // transform null object into an object
4966  if (is_null())
4967  {
4968  m_type = value_t::object;
4969  m_value = value_t::object;
4970  assert_invariant();
4971  }
4972 
4973  // add element to array
4974  m_value.object->insert(val);
4975  }
4976 
4981  reference operator+=(const typename object_t::value_type& val)
4982  {
4983  push_back(val);
4984  return *this;
4985  }
4986 
5012  void push_back(std::initializer_list<basic_json> init)
5013  {
5014  if (is_object() and init.size() == 2 and init.begin()->is_string())
5015  {
5016  const string_t key = *init.begin();
5017  push_back(typename object_t::value_type(key, *(init.begin() + 1)));
5018  }
5019  else
5020  {
5021  push_back(basic_json(init));
5022  }
5023  }
5024 
5029  reference operator+=(std::initializer_list<basic_json> init)
5030  {
5031  push_back(init);
5032  return *this;
5033  }
5034 
5056  template<class... Args>
5057  void emplace_back(Args&& ... args)
5058  {
5059  // emplace_back only works for null objects or arrays
5060  if (not(is_null() or is_array()))
5061  {
5062  throw std::domain_error("cannot use emplace_back() with " + type_name());
5063  }
5064 
5065  // transform null object into an array
5066  if (is_null())
5067  {
5068  m_type = value_t::array;
5069  m_value = value_t::array;
5070  assert_invariant();
5071  }
5072 
5073  // add element to array (perfect forwarding)
5074  m_value.array->emplace_back(std::forward<Args>(args)...);
5075  }
5076 
5104  template<class... Args>
5105  std::pair<iterator, bool> emplace(Args&& ... args)
5106  {
5107  // emplace only works for null objects or arrays
5108  if (not(is_null() or is_object()))
5109  {
5110  throw std::domain_error("cannot use emplace() with " + type_name());
5111  }
5112 
5113  // transform null object into an object
5114  if (is_null())
5115  {
5116  m_type = value_t::object;
5117  m_value = value_t::object;
5118  assert_invariant();
5119  }
5120 
5121  // add element to array (perfect forwarding)
5122  auto res = m_value.object->emplace(std::forward<Args>(args)...);
5123  // create result iterator and set iterator to the result of emplace
5124  auto it = begin();
5125  it.m_it.object_iterator = res.first;
5126 
5127  // return pair of iterator and boolean
5128  return {it, res.second};
5129  }
5130 
5154  {
5155  // insert only works for arrays
5156  if (is_array())
5157  {
5158  // check if iterator pos fits to this JSON value
5159  if (pos.m_object != this)
5160  {
5161  throw std::domain_error("iterator does not fit current value");
5162  }
5163 
5164  // insert to array and return iterator
5165  iterator result(this);
5166  result.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator, val);
5167  return result;
5168  }
5169  else
5170  {
5171  throw std::domain_error("cannot use insert() with " + type_name());
5172  }
5173  }
5174 
5180  {
5181  return insert(pos, val);
5182  }
5183 
5209  {
5210  // insert only works for arrays
5211  if (is_array())
5212  {
5213  // check if iterator pos fits to this JSON value
5214  if (pos.m_object != this)
5215  {
5216  throw std::domain_error("iterator does not fit current value");
5217  }
5218 
5219  // insert to array and return iterator
5220  iterator result(this);
5221  result.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator, cnt, val);
5222  return result;
5223  }
5224  else
5225  {
5226  throw std::domain_error("cannot use insert() with " + type_name());
5227  }
5228  }
5229 
5261  {
5262  // insert only works for arrays
5263  if (not is_array())
5264  {
5265  throw std::domain_error("cannot use insert() with " + type_name());
5266  }
5267 
5268  // check if iterator pos fits to this JSON value
5269  if (pos.m_object != this)
5270  {
5271  throw std::domain_error("iterator does not fit current value");
5272  }
5273 
5274  // check if range iterators belong to the same JSON object
5275  if (first.m_object != last.m_object)
5276  {
5277  throw std::domain_error("iterators do not fit");
5278  }
5279 
5280  if (first.m_object == this or last.m_object == this)
5281  {
5282  throw std::domain_error("passed iterators may not belong to container");
5283  }
5284 
5285  // insert to array and return iterator
5286  iterator result(this);
5287  result.m_it.array_iterator = m_value.array->insert(
5288  pos.m_it.array_iterator,
5289  first.m_it.array_iterator,
5290  last.m_it.array_iterator);
5291  return result;
5292  }
5293 
5318  iterator insert(const_iterator pos, std::initializer_list<basic_json> ilist)
5319  {
5320  // insert only works for arrays
5321  if (not is_array())
5322  {
5323  throw std::domain_error("cannot use insert() with " + type_name());
5324  }
5325 
5326  // check if iterator pos fits to this JSON value
5327  if (pos.m_object != this)
5328  {
5329  throw std::domain_error("iterator does not fit current value");
5330  }
5331 
5332  // insert to array and return iterator
5333  iterator result(this);
5334  result.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator, ilist);
5335  return result;
5336  }
5337 
5355  void swap(reference other) noexcept (
5356  std::is_nothrow_move_constructible<value_t>::value and
5357  std::is_nothrow_move_assignable<value_t>::value and
5358  std::is_nothrow_move_constructible<json_value>::value and
5359  std::is_nothrow_move_assignable<json_value>::value
5360  )
5361  {
5362  std::swap(m_type, other.m_type);
5363  std::swap(m_value, other.m_value);
5364  assert_invariant();
5365  }
5366 
5387  void swap(array_t& other)
5388  {
5389  // swap only works for arrays
5390  if (is_array())
5391  {
5392  std::swap(*(m_value.array), other);
5393  }
5394  else
5395  {
5396  throw std::domain_error("cannot use swap() with " + type_name());
5397  }
5398  }
5399 
5420  void swap(object_t& other)
5421  {
5422  // swap only works for objects
5423  if (is_object())
5424  {
5425  std::swap(*(m_value.object), other);
5426  }
5427  else
5428  {
5429  throw std::domain_error("cannot use swap() with " + type_name());
5430  }
5431  }
5432 
5453  void swap(string_t& other)
5454  {
5455  // swap only works for strings
5456  if (is_string())
5457  {
5458  std::swap(*(m_value.string), other);
5459  }
5460  else
5461  {
5462  throw std::domain_error("cannot use swap() with " + type_name());
5463  }
5464  }
5465 
5467 
5468 
5470  // lexicographical comparison operators //
5472 
5475 
5476  private:
5486  friend bool operator<(const value_t lhs, const value_t rhs) noexcept
5487  {
5488  static constexpr std::array<uint8_t, 8> order = {{
5489  0, // null
5490  3, // object
5491  4, // array
5492  5, // string
5493  1, // boolean
5494  2, // integer
5495  2, // unsigned
5496  2, // float
5497  }
5498  };
5499 
5500  // discarded values are not comparable
5501  if (lhs == value_t::discarded or rhs == value_t::discarded)
5502  {
5503  return false;
5504  }
5505 
5506  return order[static_cast<std::size_t>(lhs)] < order[static_cast<std::size_t>(rhs)];
5507  }
5508 
5509  public:
5533  friend bool operator==(const_reference lhs, const_reference rhs) noexcept
5534  {
5535  const auto lhs_type = lhs.type();
5536  const auto rhs_type = rhs.type();
5537 
5538  if (lhs_type == rhs_type)
5539  {
5540  switch (lhs_type)
5541  {
5542  case value_t::array:
5543  {
5544  return *lhs.m_value.array == *rhs.m_value.array;
5545  }
5546  case value_t::object:
5547  {
5548  return *lhs.m_value.object == *rhs.m_value.object;
5549  }
5550  case value_t::null:
5551  {
5552  return true;
5553  }
5554  case value_t::string:
5555  {
5556  return *lhs.m_value.string == *rhs.m_value.string;
5557  }
5558  case value_t::boolean:
5559  {
5560  return lhs.m_value.boolean == rhs.m_value.boolean;
5561  }
5562  case value_t::number_integer:
5563  {
5564  return lhs.m_value.number_integer == rhs.m_value.number_integer;
5565  }
5566  case value_t::number_unsigned:
5567  {
5568  return lhs.m_value.number_unsigned == rhs.m_value.number_unsigned;
5569  }
5570  case value_t::number_float:
5571  {
5572  return lhs.m_value.number_float == rhs.m_value.number_float;
5573  }
5574  default:
5575  {
5576  return false;
5577  }
5578  }
5579  }
5580  else if (lhs_type == value_t::number_integer and rhs_type == value_t::number_float)
5581  {
5582  return static_cast<number_float_t>(lhs.m_value.number_integer) == rhs.m_value.number_float;
5583  }
5584  else if (lhs_type == value_t::number_float and rhs_type == value_t::number_integer)
5585  {
5586  return lhs.m_value.number_float == static_cast<number_float_t>(rhs.m_value.number_integer);
5587  }
5588  else if (lhs_type == value_t::number_unsigned and rhs_type == value_t::number_float)
5589  {
5590  return static_cast<number_float_t>(lhs.m_value.number_unsigned) == rhs.m_value.number_float;
5591  }
5592  else if (lhs_type == value_t::number_float and rhs_type == value_t::number_unsigned)
5593  {
5594  return lhs.m_value.number_float == static_cast<number_float_t>(rhs.m_value.number_unsigned);
5595  }
5596  else if (lhs_type == value_t::number_unsigned and rhs_type == value_t::number_integer)
5597  {
5598  return static_cast<number_integer_t>(lhs.m_value.number_unsigned) == rhs.m_value.number_integer;
5599  }
5600  else if (lhs_type == value_t::number_integer and rhs_type == value_t::number_unsigned)
5601  {
5602  return lhs.m_value.number_integer == static_cast<number_integer_t>(rhs.m_value.number_unsigned);
5603  }
5604 
5605  return false;
5606  }
5607 
5626  friend bool operator==(const_reference v, std::nullptr_t) noexcept
5627  {
5628  return v.is_null();
5629  }
5630 
5635  friend bool operator==(std::nullptr_t, const_reference v) noexcept
5636  {
5637  return v.is_null();
5638  }
5639 
5656  friend bool operator!=(const_reference lhs, const_reference rhs) noexcept
5657  {
5658  return not (lhs == rhs);
5659  }
5660 
5679  friend bool operator!=(const_reference v, std::nullptr_t) noexcept
5680  {
5681  return not v.is_null();
5682  }
5683 
5688  friend bool operator!=(std::nullptr_t, const_reference v) noexcept
5689  {
5690  return not v.is_null();
5691  }
5692 
5717  friend bool operator<(const_reference lhs, const_reference rhs) noexcept
5718  {
5719  const auto lhs_type = lhs.type();
5720  const auto rhs_type = rhs.type();
5721 
5722  if (lhs_type == rhs_type)
5723  {
5724  switch (lhs_type)
5725  {
5726  case value_t::array:
5727  {
5728  return *lhs.m_value.array < *rhs.m_value.array;
5729  }
5730  case value_t::object:
5731  {
5732  return *lhs.m_value.object < *rhs.m_value.object;
5733  }
5734  case value_t::null:
5735  {
5736  return false;
5737  }
5738  case value_t::string:
5739  {
5740  return *lhs.m_value.string < *rhs.m_value.string;
5741  }
5742  case value_t::boolean:
5743  {
5744  return lhs.m_value.boolean < rhs.m_value.boolean;
5745  }
5746  case value_t::number_integer:
5747  {
5748  return lhs.m_value.number_integer < rhs.m_value.number_integer;
5749  }
5750  case value_t::number_unsigned:
5751  {
5752  return lhs.m_value.number_unsigned < rhs.m_value.number_unsigned;
5753  }
5754  case value_t::number_float:
5755  {
5756  return lhs.m_value.number_float < rhs.m_value.number_float;
5757  }
5758  default:
5759  {
5760  return false;
5761  }
5762  }
5763  }
5764  else if (lhs_type == value_t::number_integer and rhs_type == value_t::number_float)
5765  {
5766  return static_cast<number_float_t>(lhs.m_value.number_integer) < rhs.m_value.number_float;
5767  }
5768  else if (lhs_type == value_t::number_float and rhs_type == value_t::number_integer)
5769  {
5770  return lhs.m_value.number_float < static_cast<number_float_t>(rhs.m_value.number_integer);
5771  }
5772  else if (lhs_type == value_t::number_unsigned and rhs_type == value_t::number_float)
5773  {
5774  return static_cast<number_float_t>(lhs.m_value.number_unsigned) < rhs.m_value.number_float;
5775  }
5776  else if (lhs_type == value_t::number_float and rhs_type == value_t::number_unsigned)
5777  {
5778  return lhs.m_value.number_float < static_cast<number_float_t>(rhs.m_value.number_unsigned);
5779  }
5780  else if (lhs_type == value_t::number_integer and rhs_type == value_t::number_unsigned)
5781  {
5782  return lhs.m_value.number_integer < static_cast<number_integer_t>(rhs.m_value.number_unsigned);
5783  }
5784  else if (lhs_type == value_t::number_unsigned and rhs_type == value_t::number_integer)
5785  {
5786  return static_cast<number_integer_t>(lhs.m_value.number_unsigned) < rhs.m_value.number_integer;
5787  }
5788 
5789  // We only reach this line if we cannot compare values. In that case,
5790  // we compare types. Note we have to call the operator explicitly,
5791  // because MSVC has problems otherwise.
5792  return operator<(lhs_type, rhs_type);
5793  }
5794 
5812  friend bool operator<=(const_reference lhs, const_reference rhs) noexcept
5813  {
5814  return not (rhs < lhs);
5815  }
5816 
5834  friend bool operator>(const_reference lhs, const_reference rhs) noexcept
5835  {
5836  return not (lhs <= rhs);
5837  }
5838 
5856  friend bool operator>=(const_reference lhs, const_reference rhs) noexcept
5857  {
5858  return not (lhs < rhs);
5859  }
5860 
5862 
5863 
5865  // serialization //
5867 
5870 
5897  friend std::ostream& operator<<(std::ostream& o, const basic_json& j)
5898  {
5899  // read width member and use it as indentation parameter if nonzero
5900  const bool pretty_print = (o.width() > 0);
5901  const auto indentation = (pretty_print ? o.width() : 0);
5902 
5903  // reset width to 0 for subsequent calls to this stream
5904  o.width(0);
5905 
5906  // fix locale problems
5907  const auto old_locale = o.imbue(std::locale::classic());
5908  // set precision
5909 
5910  // 6, 15 or 16 digits of precision allows round-trip IEEE 754
5911  // string->float->string, string->double->string or string->long
5912  // double->string; to be safe, we read this value from
5913  // std::numeric_limits<number_float_t>::digits10
5914  const auto old_precision = o.precision(std::numeric_limits<double>::digits10);
5915 
5916  // do the actual serialization
5917  j.dump(o, pretty_print, static_cast<unsigned int>(indentation));
5918 
5919  // reset locale and precision
5920  o.imbue(old_locale);
5921  o.precision(old_precision);
5922  return o;
5923  }
5924 
5929  friend std::ostream& operator>>(const basic_json& j, std::ostream& o)
5930  {
5931  return o << j;
5932  }
5933 
5935 
5936 
5938  // deserialization //
5940 
5943 
5971  template<class T, std::size_t N>
5972  static basic_json parse(T (&array)[N],
5973  const parser_callback_t cb = nullptr)
5974  {
5975  // delegate the call to the iterator-range parse overload
5976  return parse(std::begin(array), std::end(array), cb);
5977  }
5978 
6006  template<typename CharPT, typename std::enable_if<
6007  std::is_pointer<CharPT>::value and
6008  std::is_integral<typename std::remove_pointer<CharPT>::type>::value and
6009  sizeof(typename std::remove_pointer<CharPT>::type) == 1, int>::type = 0>
6010  static basic_json parse(const CharPT s,
6011  const parser_callback_t cb = nullptr)
6012  {
6013  return parser(reinterpret_cast<const char*>(s), cb).parse();
6014  }
6015 
6040  static basic_json parse(std::istream& i,
6041  const parser_callback_t cb = nullptr)
6042  {
6043  return parser(i, cb).parse();
6044  }
6045 
6049  static basic_json parse(std::istream&& i,
6050  const parser_callback_t cb = nullptr)
6051  {
6052  return parser(i, cb).parse();
6053  }
6054 
6096  template<class IteratorType, typename std::enable_if<
6097  std::is_base_of<
6098  std::random_access_iterator_tag,
6099  typename std::iterator_traits<IteratorType>::iterator_category>::value, int>::type = 0>
6100  static basic_json parse(IteratorType first, IteratorType last,
6101  const parser_callback_t cb = nullptr)
6102  {
6103  // assertion to check that the iterator range is indeed contiguous,
6104  // see http://stackoverflow.com/a/35008842/266378 for more discussion
6105  assert(std::accumulate(first, last, std::make_pair<bool, int>(true, 0),
6106  [&first](std::pair<bool, int> res, decltype(*first) val)
6107  {
6108  res.first &= (val == *(std::next(std::addressof(*first), res.second++)));
6109  return res;
6110  }).first);
6111 
6112  // assertion to check that each element is 1 byte long
6113  static_assert(sizeof(typename std::iterator_traits<IteratorType>::value_type) == 1,
6114  "each element in the iterator range must have the size of 1 byte");
6115 
6116  // if iterator range is empty, create a parser with an empty string
6117  // to generate "unexpected EOF" error message
6118  if (std::distance(first, last) <= 0)
6119  {
6120  return parser("").parse();
6121  }
6122 
6123  return parser(first, last, cb).parse();
6124  }
6125 
6166  template<class ContiguousContainer, typename std::enable_if<
6167  not std::is_pointer<ContiguousContainer>::value and
6168  std::is_base_of<
6169  std::random_access_iterator_tag,
6170  typename std::iterator_traits<decltype(std::begin(std::declval<ContiguousContainer const>()))>::iterator_category>::value
6171  , int>::type = 0>
6172  static basic_json parse(const ContiguousContainer& c,
6173  const parser_callback_t cb = nullptr)
6174  {
6175  // delegate the call to the iterator-range parse overload
6176  return parse(std::begin(c), std::end(c), cb);
6177  }
6178 
6202  friend std::istream& operator<<(basic_json& j, std::istream& i)
6203  {
6204  j = parser(i).parse();
6205  return i;
6206  }
6207 
6212  friend std::istream& operator>>(std::istream& i, basic_json& j)
6213  {
6214  j = parser(i).parse();
6215  return i;
6216  }
6217 
6219 
6220 
6221  private:
6223  // convenience functions //
6225 
6238  std::string type_name() const
6239  {
6240  switch (m_type)
6241  {
6242  case value_t::null:
6243  return "null";
6244  case value_t::object:
6245  return "object";
6246  case value_t::array:
6247  return "array";
6248  case value_t::string:
6249  return "string";
6250  case value_t::boolean:
6251  return "boolean";
6252  case value_t::discarded:
6253  return "discarded";
6254  default:
6255  return "number";
6256  }
6257  }
6258 
6267  static std::size_t extra_space(const string_t& s) noexcept
6268  {
6269  return std::accumulate(s.begin(), s.end(), size_t{},
6270  [](size_t res, typename string_t::value_type c)
6271  {
6272  switch (c)
6273  {
6274  case '"':
6275  case '\\':
6276  case '\b':
6277  case '\f':
6278  case '\n':
6279  case '\r':
6280  case '\t':
6281  {
6282  // from c (1 byte) to \x (2 bytes)
6283  return res + 1;
6284  }
6285 
6286  default:
6287  {
6288  if (c >= 0x00 and c <= 0x1f)
6289  {
6290  // from c (1 byte) to \uxxxx (6 bytes)
6291  return res + 5;
6292  }
6293  else
6294  {
6295  return res;
6296  }
6297  }
6298  }
6299  });
6300  }
6301 
6315  static string_t escape_string(const string_t& s)
6316  {
6317  const auto space = extra_space(s);
6318  if (space == 0)
6319  {
6320  return s;
6321  }
6322 
6323  // create a result string of necessary size
6324  string_t result(s.size() + space, '\\');
6325  std::size_t pos = 0;
6326 
6327  for (const auto& c : s)
6328  {
6329  switch (c)
6330  {
6331  // quotation mark (0x22)
6332  case '"':
6333  {
6334  result[pos + 1] = '"';
6335  pos += 2;
6336  break;
6337  }
6338 
6339  // reverse solidus (0x5c)
6340  case '\\':
6341  {
6342  // nothing to change
6343  pos += 2;
6344  break;
6345  }
6346 
6347  // backspace (0x08)
6348  case '\b':
6349  {
6350  result[pos + 1] = 'b';
6351  pos += 2;
6352  break;
6353  }
6354 
6355  // formfeed (0x0c)
6356  case '\f':
6357  {
6358  result[pos + 1] = 'f';
6359  pos += 2;
6360  break;
6361  }
6362 
6363  // newline (0x0a)
6364  case '\n':
6365  {
6366  result[pos + 1] = 'n';
6367  pos += 2;
6368  break;
6369  }
6370 
6371  // carriage return (0x0d)
6372  case '\r':
6373  {
6374  result[pos + 1] = 'r';
6375  pos += 2;
6376  break;
6377  }
6378 
6379  // horizontal tab (0x09)
6380  case '\t':
6381  {
6382  result[pos + 1] = 't';
6383  pos += 2;
6384  break;
6385  }
6386 
6387  default:
6388  {
6389  if (c >= 0x00 and c <= 0x1f)
6390  {
6391  // convert a number 0..15 to its hex representation
6392  // (0..f)
6393  static const char hexify[16] =
6394  {
6395  '0', '1', '2', '3', '4', '5', '6', '7',
6396  '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'
6397  };
6398 
6399  // print character c as \uxxxx
6400  for (const char m :
6401  { 'u', '0', '0', hexify[c >> 4], hexify[c & 0x0f]
6402  })
6403  {
6404  result[++pos] = m;
6405  }
6406 
6407  ++pos;
6408  }
6409  else
6410  {
6411  // all other characters are added as-is
6412  result[pos++] = c;
6413  }
6414  break;
6415  }
6416  }
6417  }
6418 
6419  return result;
6420  }
6421 
6439  void dump(std::ostream& o,
6440  const bool pretty_print,
6441  const unsigned int indent_step,
6442  const unsigned int current_indent = 0) const
6443  {
6444  // variable to hold indentation for recursive calls
6445  unsigned int new_indent = current_indent;
6446 
6447  switch (m_type)
6448  {
6449  case value_t::object:
6450  {
6451  if (m_value.object->empty())
6452  {
6453  o << "{}";
6454  return;
6455  }
6456 
6457  o << "{";
6458 
6459  // increase indentation
6460  if (pretty_print)
6461  {
6462  new_indent += indent_step;
6463  o << "\n";
6464  }
6465 
6466  for (auto i = m_value.object->cbegin(); i != m_value.object->cend(); ++i)
6467  {
6468  if (i != m_value.object->cbegin())
6469  {
6470  o << (pretty_print ? ",\n" : ",");
6471  }
6472  o << string_t(new_indent, ' ') << "\""
6473  << escape_string(i->first) << "\":"
6474  << (pretty_print ? " " : "");
6475  i->second.dump(o, pretty_print, indent_step, new_indent);
6476  }
6477 
6478  // decrease indentation
6479  if (pretty_print)
6480  {
6481  new_indent -= indent_step;
6482  o << "\n";
6483  }
6484 
6485  o << string_t(new_indent, ' ') + "}";
6486  return;
6487  }
6488 
6489  case value_t::array:
6490  {
6491  if (m_value.array->empty())
6492  {
6493  o << "[]";
6494  return;
6495  }
6496 
6497  o << "[";
6498 
6499  // increase indentation
6500  if (pretty_print)
6501  {
6502  new_indent += indent_step;
6503  o << "\n";
6504  }
6505 
6506  for (auto i = m_value.array->cbegin(); i != m_value.array->cend(); ++i)
6507  {
6508  if (i != m_value.array->cbegin())
6509  {
6510  o << (pretty_print ? ",\n" : ",");
6511  }
6512  o << string_t(new_indent, ' ');
6513  i->dump(o, pretty_print, indent_step, new_indent);
6514  }
6515 
6516  // decrease indentation
6517  if (pretty_print)
6518  {
6519  new_indent -= indent_step;
6520  o << "\n";
6521  }
6522 
6523  o << string_t(new_indent, ' ') << "]";
6524  return;
6525  }
6526 
6527  case value_t::string:
6528  {
6529  o << string_t("\"") << escape_string(*m_value.string) << "\"";
6530  return;
6531  }
6532 
6533  case value_t::boolean:
6534  {
6535  o << (m_value.boolean ? "true" : "false");
6536  return;
6537  }
6538 
6539  case value_t::number_integer:
6540  {
6541  o << m_value.number_integer;
6542  return;
6543  }
6544 
6545  case value_t::number_unsigned:
6546  {
6547  o << m_value.number_unsigned;
6548  return;
6549  }
6550 
6551  case value_t::number_float:
6552  {
6553  if (m_value.number_float == 0)
6554  {
6555  // special case for zero to get "0.0"/"-0.0"
6556  o << (std::signbit(m_value.number_float) ? "-0.0" : "0.0");
6557  }
6558  else
6559  {
6560  o << m_value.number_float;
6561  }
6562  return;
6563  }
6564 
6565  case value_t::discarded:
6566  {
6567  o << "<discarded>";
6568  return;
6569  }
6570 
6571  case value_t::null:
6572  {
6573  o << "null";
6574  return;
6575  }
6576  }
6577  }
6578 
6579  private:
6581  // member variables //
6583 
6585  value_t m_type = value_t::null;
6586 
6588  json_value m_value = {};
6589 
6590 
6591  private:
6593  // iterators //
6595 
6605  class primitive_iterator_t
6606  {
6607  public:
6609  void set_begin() noexcept
6610  {
6611  m_it = begin_value;
6612  }
6613 
6615  void set_end() noexcept
6616  {
6617  m_it = end_value;
6618  }
6619 
6621  constexpr bool is_begin() const noexcept
6622  {
6623  return (m_it == begin_value);
6624  }
6625 
6627  constexpr bool is_end() const noexcept
6628  {
6629  return (m_it == end_value);
6630  }
6631 
6633  operator difference_type& () noexcept
6634  {
6635  return m_it;
6636  }
6637 
6639  constexpr operator difference_type () const noexcept
6640  {
6641  return m_it;
6642  }
6643 
6644  private:
6645  static constexpr difference_type begin_value = 0;
6646  static constexpr difference_type end_value = begin_value + 1;
6647 
6649  difference_type m_it = std::numeric_limits<std::ptrdiff_t>::denorm_min();
6650  };
6651 
6659  struct internal_iterator
6660  {
6662  typename object_t::iterator object_iterator;
6664  typename array_t::iterator array_iterator;
6666  primitive_iterator_t primitive_iterator;
6667 
6669  internal_iterator() noexcept
6670  : object_iterator(), array_iterator(), primitive_iterator()
6671  {}
6672  };
6673 
6675  template<typename IteratorType>
6676  class iteration_proxy
6677  {
6678  private:
6680  class iteration_proxy_internal
6681  {
6682  private:
6684  IteratorType anchor;
6686  size_t array_index = 0;
6687 
6688  public:
6689  explicit iteration_proxy_internal(IteratorType it) noexcept
6690  : anchor(it)
6691  {}
6692 
6694  iteration_proxy_internal& operator*()
6695  {
6696  return *this;
6697  }
6698 
6700  iteration_proxy_internal& operator++()
6701  {
6702  ++anchor;
6703  ++array_index;
6704 
6705  return *this;
6706  }
6707 
6709  bool operator!= (const iteration_proxy_internal& o) const
6710  {
6711  return anchor != o.anchor;
6712  }
6713 
6715  typename basic_json::string_t key() const
6716  {
6717  assert(anchor.m_object != nullptr);
6718 
6719  switch (anchor.m_object->type())
6720  {
6721  // use integer array index as key
6722  case value_t::array:
6723  {
6724  return std::to_string(array_index);
6725  }
6726 
6727  // use key from the object
6728  case value_t::object:
6729  {
6730  return anchor.key();
6731  }
6732 
6733  // use an empty key for all primitive types
6734  default:
6735  {
6736  return "";
6737  }
6738  }
6739  }
6740 
6742  typename IteratorType::reference value() const
6743  {
6744  return anchor.value();
6745  }
6746  };
6747 
6749  typename IteratorType::reference container;
6750 
6751  public:
6753  explicit iteration_proxy(typename IteratorType::reference cont)
6754  : container(cont)
6755  {}
6756 
6758  iteration_proxy_internal begin() noexcept
6759  {
6760  return iteration_proxy_internal(container.begin());
6761  }
6762 
6764  iteration_proxy_internal end() noexcept
6765  {
6766  return iteration_proxy_internal(container.end());
6767  }
6768  };
6769 
6770  public:
6790  class const_iterator : public std::iterator<std::random_access_iterator_tag, const basic_json>
6791  {
6793  friend class basic_json;
6794 
6795  public:
6805  using iterator_category = std::bidirectional_iterator_tag;
6806 
6808  const_iterator() = default;
6809 
6816  explicit const_iterator(pointer object) noexcept
6817  : m_object(object)
6818  {
6819  assert(m_object != nullptr);
6820 
6821  switch (m_object->m_type)
6822  {
6824  {
6825  m_it.object_iterator = typename object_t::iterator();
6826  break;
6827  }
6828 
6830  {
6831  m_it.array_iterator = typename array_t::iterator();
6832  break;
6833  }
6834 
6835  default:
6836  {
6837  m_it.primitive_iterator = primitive_iterator_t();
6838  break;
6839  }
6840  }
6841  }
6842 
6848  explicit const_iterator(const iterator& other) noexcept
6849  : m_object(other.m_object)
6850  {
6851  if (m_object != nullptr)
6852  {
6853  switch (m_object->m_type)
6854  {
6856  {
6857  m_it.object_iterator = other.m_it.object_iterator;
6858  break;
6859  }
6860 
6862  {
6863  m_it.array_iterator = other.m_it.array_iterator;
6864  break;
6865  }
6866 
6867  default:
6868  {
6869  m_it.primitive_iterator = other.m_it.primitive_iterator;
6870  break;
6871  }
6872  }
6873  }
6874  }
6875 
6881  const_iterator(const const_iterator& other) noexcept
6882  : m_object(other.m_object), m_it(other.m_it)
6883  {}
6884 
6891  std::is_nothrow_move_constructible<pointer>::value and
6892  std::is_nothrow_move_assignable<pointer>::value and
6893  std::is_nothrow_move_constructible<internal_iterator>::value and
6894  std::is_nothrow_move_assignable<internal_iterator>::value
6895  )
6896  {
6897  std::swap(m_object, other.m_object);
6898  std::swap(m_it, other.m_it);
6899  return *this;
6900  }
6901 
6902  private:
6907  void set_begin() noexcept
6908  {
6909  assert(m_object != nullptr);
6910 
6911  switch (m_object->m_type)
6912  {
6914  {
6915  m_it.object_iterator = m_object->m_value.object->begin();
6916  break;
6917  }
6918 
6920  {
6921  m_it.array_iterator = m_object->m_value.array->begin();
6922  break;
6923  }
6924 
6926  {
6927  // set to end so begin()==end() is true: null is empty
6928  m_it.primitive_iterator.set_end();
6929  break;
6930  }
6931 
6932  default:
6933  {
6934  m_it.primitive_iterator.set_begin();
6935  break;
6936  }
6937  }
6938  }
6939 
6944  void set_end() noexcept
6945  {
6946  assert(m_object != nullptr);
6947 
6948  switch (m_object->m_type)
6949  {
6951  {
6952  m_it.object_iterator = m_object->m_value.object->end();
6953  break;
6954  }
6955 
6957  {
6958  m_it.array_iterator = m_object->m_value.array->end();
6959  break;
6960  }
6961 
6962  default:
6963  {
6964  m_it.primitive_iterator.set_end();
6965  break;
6966  }
6967  }
6968  }
6969 
6970  public:
6976  {
6977  assert(m_object != nullptr);
6978 
6979  switch (m_object->m_type)
6980  {
6982  {
6983  assert(m_it.object_iterator != m_object->m_value.object->end());
6984  return m_it.object_iterator->second;
6985  }
6986 
6988  {
6989  assert(m_it.array_iterator != m_object->m_value.array->end());
6990  return *m_it.array_iterator;
6991  }
6992 
6994  {
6995  throw std::out_of_range("cannot get value");
6996  }
6997 
6998  default:
6999  {
7000  if (m_it.primitive_iterator.is_begin())
7001  {
7002  return *m_object;
7003  }
7004  else
7005  {
7006  throw std::out_of_range("cannot get value");
7007  }
7008  }
7009  }
7010  }
7011 
7017  {
7018  assert(m_object != nullptr);
7019 
7020  switch (m_object->m_type)
7021  {
7023  {
7024  assert(m_it.object_iterator != m_object->m_value.object->end());
7025  return &(m_it.object_iterator->second);
7026  }
7027 
7029  {
7030  assert(m_it.array_iterator != m_object->m_value.array->end());
7031  return &*m_it.array_iterator;
7032  }
7033 
7034  default:
7035  {
7036  if (m_it.primitive_iterator.is_begin())
7037  {
7038  return m_object;
7039  }
7040  else
7041  {
7042  throw std::out_of_range("cannot get value");
7043  }
7044  }
7045  }
7046  }
7047 
7053  {
7054  auto result = *this;
7055  ++(*this);
7056  return result;
7057  }
7058 
7064  {
7065  assert(m_object != nullptr);
7066 
7067  switch (m_object->m_type)
7068  {
7070  {
7071  std::advance(m_it.object_iterator, 1);
7072  break;
7073  }
7074 
7076  {
7077  std::advance(m_it.array_iterator, 1);
7078  break;
7079  }
7080 
7081  default:
7082  {
7083  ++m_it.primitive_iterator;
7084  break;
7085  }
7086  }
7087 
7088  return *this;
7089  }
7090 
7096  {
7097  auto result = *this;
7098  --(*this);
7099  return result;
7100  }
7101 
7107  {
7108  assert(m_object != nullptr);
7109 
7110  switch (m_object->m_type)
7111  {
7113  {
7114  std::advance(m_it.object_iterator, -1);
7115  break;
7116  }
7117 
7119  {
7120  std::advance(m_it.array_iterator, -1);
7121  break;
7122  }
7123 
7124  default:
7125  {
7126  --m_it.primitive_iterator;
7127  break;
7128  }
7129  }
7130 
7131  return *this;
7132  }
7133 
7138  bool operator==(const const_iterator& other) const
7139  {
7140  // if objects are not the same, the comparison is undefined
7141  if (m_object != other.m_object)
7142  {
7143  throw std::domain_error("cannot compare iterators of different containers");
7144  }
7145 
7146  assert(m_object != nullptr);
7147 
7148  switch (m_object->m_type)
7149  {
7151  {
7152  return (m_it.object_iterator == other.m_it.object_iterator);
7153  }
7154 
7156  {
7157  return (m_it.array_iterator == other.m_it.array_iterator);
7158  }
7159 
7160  default:
7161  {
7162  return (m_it.primitive_iterator == other.m_it.primitive_iterator);
7163  }
7164  }
7165  }
7166 
7171  bool operator!=(const const_iterator& other) const
7172  {
7173  return not operator==(other);
7174  }
7175 
7180  bool operator<(const const_iterator& other) const
7181  {
7182  // if objects are not the same, the comparison is undefined
7183  if (m_object != other.m_object)
7184  {
7185  throw std::domain_error("cannot compare iterators of different containers");
7186  }
7187 
7188  assert(m_object != nullptr);
7189 
7190  switch (m_object->m_type)
7191  {
7193  {
7194  throw std::domain_error("cannot compare order of object iterators");
7195  }
7196 
7198  {
7199  return (m_it.array_iterator < other.m_it.array_iterator);
7200  }
7201 
7202  default:
7203  {
7204  return (m_it.primitive_iterator < other.m_it.primitive_iterator);
7205  }
7206  }
7207  }
7208 
7213  bool operator<=(const const_iterator& other) const
7214  {
7215  return not other.operator < (*this);
7216  }
7217 
7222  bool operator>(const const_iterator& other) const
7223  {
7224  return not operator<=(other);
7225  }
7226 
7231  bool operator>=(const const_iterator& other) const
7232  {
7233  return not operator<(other);
7234  }
7235 
7241  {
7242  assert(m_object != nullptr);
7243 
7244  switch (m_object->m_type)
7245  {
7247  {
7248  throw std::domain_error("cannot use offsets with object iterators");
7249  }
7250 
7252  {
7253  std::advance(m_it.array_iterator, i);
7254  break;
7255  }
7256 
7257  default:
7258  {
7259  m_it.primitive_iterator += i;
7260  break;
7261  }
7262  }
7263 
7264  return *this;
7265  }
7266 
7272  {
7273  return operator+=(-i);
7274  }
7275 
7281  {
7282  auto result = *this;
7283  result += i;
7284  return result;
7285  }
7286 
7292  {
7293  auto result = *this;
7294  result -= i;
7295  return result;
7296  }
7297 
7303  {
7304  assert(m_object != nullptr);
7305 
7306  switch (m_object->m_type)
7307  {
7309  {
7310  throw std::domain_error("cannot use offsets with object iterators");
7311  }
7312 
7314  {
7315  return m_it.array_iterator - other.m_it.array_iterator;
7316  }
7317 
7318  default:
7319  {
7320  return m_it.primitive_iterator - other.m_it.primitive_iterator;
7321  }
7322  }
7323  }
7324 
7330  {
7331  assert(m_object != nullptr);
7332 
7333  switch (m_object->m_type)
7334  {
7336  {
7337  throw std::domain_error("cannot use operator[] for object iterators");
7338  }
7339 
7341  {
7342  return *std::next(m_it.array_iterator, n);
7343  }
7344 
7346  {
7347  throw std::out_of_range("cannot get value");
7348  }
7349 
7350  default:
7351  {
7352  if (m_it.primitive_iterator == -n)
7353  {
7354  return *m_object;
7355  }
7356  else
7357  {
7358  throw std::out_of_range("cannot get value");
7359  }
7360  }
7361  }
7362  }
7363 
7368  typename object_t::key_type key() const
7369  {
7370  assert(m_object != nullptr);
7371 
7372  if (m_object->is_object())
7373  {
7374  return m_it.object_iterator->first;
7375  }
7376  else
7377  {
7378  throw std::domain_error("cannot use key() for non-object iterators");
7379  }
7380  }
7381 
7387  {
7388  return operator*();
7389  }
7390 
7391  private:
7393  pointer m_object = nullptr;
7395  internal_iterator m_it = internal_iterator();
7396  };
7397 
7410  class iterator : public const_iterator
7411  {
7412  public:
7414  using pointer = typename basic_json::pointer;
7416 
7418  iterator() = default;
7419 
7421  explicit iterator(pointer object) noexcept
7422  : base_iterator(object)
7423  {}
7424 
7426  iterator(const iterator& other) noexcept
7427  : base_iterator(other)
7428  {}
7429 
7431  iterator& operator=(iterator other) noexcept(
7432  std::is_nothrow_move_constructible<pointer>::value and
7433  std::is_nothrow_move_assignable<pointer>::value and
7434  std::is_nothrow_move_constructible<internal_iterator>::value and
7435  std::is_nothrow_move_assignable<internal_iterator>::value
7436  )
7437  {
7438  base_iterator::operator=(other);
7439  return *this;
7440  }
7441 
7444  {
7445  return const_cast<reference>(base_iterator::operator*());
7446  }
7447 
7450  {
7451  return const_cast<pointer>(base_iterator::operator->());
7452  }
7453 
7456  {
7457  iterator result = *this;
7458  base_iterator::operator++();
7459  return result;
7460  }
7461 
7464  {
7465  base_iterator::operator++();
7466  return *this;
7467  }
7468 
7471  {
7472  iterator result = *this;
7473  base_iterator::operator--();
7474  return result;
7475  }
7476 
7479  {
7480  base_iterator::operator--();
7481  return *this;
7482  }
7483 
7486  {
7487  base_iterator::operator+=(i);
7488  return *this;
7489  }
7490 
7493  {
7494  base_iterator::operator-=(i);
7495  return *this;
7496  }
7497 
7500  {
7501  auto result = *this;
7502  result += i;
7503  return result;
7504  }
7505 
7508  {
7509  auto result = *this;
7510  result -= i;
7511  return result;
7512  }
7513 
7515  difference_type operator-(const iterator& other) const
7516  {
7517  return base_iterator::operator-(other);
7518  }
7519 
7522  {
7523  return const_cast<reference>(base_iterator::operator[](n));
7524  }
7525 
7528  {
7529  return const_cast<reference>(base_iterator::value());
7530  }
7531  };
7532 
7550  template<typename Base>
7551  class json_reverse_iterator : public std::reverse_iterator<Base>
7552  {
7553  public:
7555  using base_iterator = std::reverse_iterator<Base>;
7557  using reference = typename Base::reference;
7558 
7560  json_reverse_iterator(const typename base_iterator::iterator_type& it) noexcept
7561  : base_iterator(it)
7562  {}
7563 
7566  : base_iterator(it)
7567  {}
7568 
7571  {
7572  return base_iterator::operator++(1);
7573  }
7574 
7577  {
7578  base_iterator::operator++();
7579  return *this;
7580  }
7581 
7584  {
7585  return base_iterator::operator--(1);
7586  }
7587 
7590  {
7591  base_iterator::operator--();
7592  return *this;
7593  }
7594 
7597  {
7598  base_iterator::operator+=(i);
7599  return *this;
7600  }
7601 
7604  {
7605  auto result = *this;
7606  result += i;
7607  return result;
7608  }
7609 
7612  {
7613  auto result = *this;
7614  result -= i;
7615  return result;
7616  }
7617 
7620  {
7621  return this->base() - other.base();
7622  }
7623 
7626  {
7627  return *(this->operator+(n));
7628  }
7629 
7631  typename object_t::key_type key() const
7632  {
7633  auto it = --this->base();
7634  return it.key();
7635  }
7636 
7639  {
7640  auto it = --this->base();
7641  return it.operator * ();
7642  }
7643  };
7644 
7645 
7646  private:
7648  // lexer and parser //
7650 
7658  class lexer
7659  {
7660  public:
7662  enum class token_type
7663  {
7664  uninitialized,
7665  literal_true,
7666  literal_false,
7667  literal_null,
7668  value_string,
7669  value_number,
7670  begin_array,
7671  begin_object,
7672  end_array,
7673  end_object,
7674  name_separator,
7675  value_separator,
7676  parse_error,
7677  end_of_input
7678  };
7679 
7681  using lexer_char_t = unsigned char;
7682 
7684  lexer(const lexer_char_t* buff, const size_t len) noexcept
7685  : m_content(buff)
7686  {
7687  assert(m_content != nullptr);
7688  m_start = m_cursor = m_content;
7689  m_limit = m_content + len;
7690  }
7691 
7693  explicit lexer(std::istream& s)
7694  : m_stream(&s), m_line_buffer()
7695  {
7696  // immediately abort if stream is erroneous
7697  if (s.fail())
7698  {
7699  throw std::invalid_argument("stream error: " + std::string(strerror(errno)));
7700  }
7701 
7702  // fill buffer
7703  fill_line_buffer();
7704 
7705  // skip UTF-8 byte-order mark
7706  if (m_line_buffer.size() >= 3 and m_line_buffer.substr(0, 3) == "\xEF\xBB\xBF")
7707  {
7708  m_line_buffer[0] = ' ';
7709  m_line_buffer[1] = ' ';
7710  m_line_buffer[2] = ' ';
7711  }
7712  }
7713 
7714  // switch off unwanted functions (due to pointer members)
7715  lexer() = delete;
7716  lexer(const lexer&) = delete;
7717  lexer operator=(const lexer&) = delete;
7718 
7742  static string_t to_unicode(const std::size_t codepoint1,
7743  const std::size_t codepoint2 = 0)
7744  {
7745  // calculate the code point from the given code points
7746  std::size_t codepoint = codepoint1;
7747 
7748  // check if codepoint1 is a high surrogate
7749  if (codepoint1 >= 0xD800 and codepoint1 <= 0xDBFF)
7750  {
7751  // check if codepoint2 is a low surrogate
7752  if (codepoint2 >= 0xDC00 and codepoint2 <= 0xDFFF)
7753  {
7754  codepoint =
7755  // high surrogate occupies the most significant 22 bits
7756  (codepoint1 << 10)
7757  // low surrogate occupies the least significant 15 bits
7758  + codepoint2
7759  // there is still the 0xD800, 0xDC00 and 0x10000 noise
7760  // in the result so we have to subtract with:
7761  // (0xD800 << 10) + DC00 - 0x10000 = 0x35FDC00
7762  - 0x35FDC00;
7763  }
7764  else
7765  {
7766  throw std::invalid_argument("missing or wrong low surrogate");
7767  }
7768  }
7769 
7770  string_t result;
7771 
7772  if (codepoint < 0x80)
7773  {
7774  // 1-byte characters: 0xxxxxxx (ASCII)
7775  result.append(1, static_cast<typename string_t::value_type>(codepoint));
7776  }
7777  else if (codepoint <= 0x7ff)
7778  {
7779  // 2-byte characters: 110xxxxx 10xxxxxx
7780  result.append(1, static_cast<typename string_t::value_type>(0xC0 | ((codepoint >> 6) & 0x1F)));
7781  result.append(1, static_cast<typename string_t::value_type>(0x80 | (codepoint & 0x3F)));
7782  }
7783  else if (codepoint <= 0xffff)
7784  {
7785  // 3-byte characters: 1110xxxx 10xxxxxx 10xxxxxx
7786  result.append(1, static_cast<typename string_t::value_type>(0xE0 | ((codepoint >> 12) & 0x0F)));
7787  result.append(1, static_cast<typename string_t::value_type>(0x80 | ((codepoint >> 6) & 0x3F)));
7788  result.append(1, static_cast<typename string_t::value_type>(0x80 | (codepoint & 0x3F)));
7789  }
7790  else if (codepoint <= 0x10ffff)
7791  {
7792  // 4-byte characters: 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
7793  result.append(1, static_cast<typename string_t::value_type>(0xF0 | ((codepoint >> 18) & 0x07)));
7794  result.append(1, static_cast<typename string_t::value_type>(0x80 | ((codepoint >> 12) & 0x3F)));
7795  result.append(1, static_cast<typename string_t::value_type>(0x80 | ((codepoint >> 6) & 0x3F)));
7796  result.append(1, static_cast<typename string_t::value_type>(0x80 | (codepoint & 0x3F)));
7797  }
7798  else
7799  {
7800  throw std::out_of_range("code points above 0x10FFFF are invalid");
7801  }
7802 
7803  return result;
7804  }
7805 
7807  static std::string token_type_name(const token_type t)
7808  {
7809  switch (t)
7810  {
7811  case token_type::uninitialized:
7812  return "<uninitialized>";
7813  case token_type::literal_true:
7814  return "true literal";
7815  case token_type::literal_false:
7816  return "false literal";
7817  case token_type::literal_null:
7818  return "null literal";
7819  case token_type::value_string:
7820  return "string literal";
7821  case token_type::value_number:
7822  return "number literal";
7823  case token_type::begin_array:
7824  return "'['";
7825  case token_type::begin_object:
7826  return "'{'";
7827  case token_type::end_array:
7828  return "']'";
7829  case token_type::end_object:
7830  return "'}'";
7831  case token_type::name_separator:
7832  return "':'";
7833  case token_type::value_separator:
7834  return "','";
7835  case token_type::parse_error:
7836  return "<parse error>";
7837  case token_type::end_of_input:
7838  return "end of input";
7839  default:
7840  {
7841  // catch non-enum values
7842  return "unknown token"; // LCOV_EXCL_LINE
7843  }
7844  }
7845  }
7846 
7868  token_type scan()
7869  {
7870  while (true)
7871  {
7872  // pointer for backtracking information
7873  m_marker = nullptr;
7874 
7875  // remember the begin of the token
7876  m_start = m_cursor;
7877  assert(m_start != nullptr);
7878 
7879 
7880  {
7881  lexer_char_t yych;
7882  unsigned int yyaccept = 0;
7883  static const unsigned char yybm[] =
7884  {
7885  0, 0, 0, 0, 0, 0, 0, 0,
7886  0, 32, 32, 0, 0, 32, 0, 0,
7887  0, 0, 0, 0, 0, 0, 0, 0,
7888  0, 0, 0, 0, 0, 0, 0, 0,
7889  160, 128, 0, 128, 128, 128, 128, 128,
7890  128, 128, 128, 128, 128, 128, 128, 128,
7891  192, 192, 192, 192, 192, 192, 192, 192,
7892  192, 192, 128, 128, 128, 128, 128, 128,
7893  128, 128, 128, 128, 128, 128, 128, 128,
7894  128, 128, 128, 128, 128, 128, 128, 128,
7895  128, 128, 128, 128, 128, 128, 128, 128,
7896  128, 128, 128, 128, 0, 128, 128, 128,
7897  128, 128, 128, 128, 128, 128, 128, 128,
7898  128, 128, 128, 128, 128, 128, 128, 128,
7899  128, 128, 128, 128, 128, 128, 128, 128,
7900  128, 128, 128, 128, 128, 128, 128, 128,
7901  0, 0, 0, 0, 0, 0, 0, 0,
7902  0, 0, 0, 0, 0, 0, 0, 0,
7903  0, 0, 0, 0, 0, 0, 0, 0,
7904  0, 0, 0, 0, 0, 0, 0, 0,
7905  0, 0, 0, 0, 0, 0, 0, 0,
7906  0, 0, 0, 0, 0, 0, 0, 0,
7907  0, 0, 0, 0, 0, 0, 0, 0,
7908  0, 0, 0, 0, 0, 0, 0, 0,
7909  0, 0, 0, 0, 0, 0, 0, 0,
7910  0, 0, 0, 0, 0, 0, 0, 0,
7911  0, 0, 0, 0, 0, 0, 0, 0,
7912  0, 0, 0, 0, 0, 0, 0, 0,
7913  0, 0, 0, 0, 0, 0, 0, 0,
7914  0, 0, 0, 0, 0, 0, 0, 0,
7915  0, 0, 0, 0, 0, 0, 0, 0,
7916  0, 0, 0, 0, 0, 0, 0, 0,
7917  };
7918  if ((m_limit - m_cursor) < 5)
7919  {
7920  fill_line_buffer(5); // LCOV_EXCL_LINE
7921  }
7922  yych = *m_cursor;
7923  if (yybm[0 + yych] & 32)
7924  {
7925  goto basic_json_parser_6;
7926  }
7927  if (yych <= '[')
7928  {
7929  if (yych <= '-')
7930  {
7931  if (yych <= '"')
7932  {
7933  if (yych <= 0x00)
7934  {
7935  goto basic_json_parser_2;
7936  }
7937  if (yych <= '!')
7938  {
7939  goto basic_json_parser_4;
7940  }
7941  goto basic_json_parser_9;
7942  }
7943  else
7944  {
7945  if (yych <= '+')
7946  {
7947  goto basic_json_parser_4;
7948  }
7949  if (yych <= ',')
7950  {
7951  goto basic_json_parser_10;
7952  }
7953  goto basic_json_parser_12;
7954  }
7955  }
7956  else
7957  {
7958  if (yych <= '9')
7959  {
7960  if (yych <= '/')
7961  {
7962  goto basic_json_parser_4;
7963  }
7964  if (yych <= '0')
7965  {
7966  goto basic_json_parser_13;
7967  }
7968  goto basic_json_parser_15;
7969  }
7970  else
7971  {
7972  if (yych <= ':')
7973  {
7974  goto basic_json_parser_17;
7975  }
7976  if (yych <= 'Z')
7977  {
7978  goto basic_json_parser_4;
7979  }
7980  goto basic_json_parser_19;
7981  }
7982  }
7983  }
7984  else
7985  {
7986  if (yych <= 'n')
7987  {
7988  if (yych <= 'e')
7989  {
7990  if (yych == ']')
7991  {
7992  goto basic_json_parser_21;
7993  }
7994  goto basic_json_parser_4;
7995  }
7996  else
7997  {
7998  if (yych <= 'f')
7999  {
8000  goto basic_json_parser_23;
8001  }
8002  if (yych <= 'm')
8003  {
8004  goto basic_json_parser_4;
8005  }
8006  goto basic_json_parser_24;
8007  }
8008  }
8009  else
8010  {
8011  if (yych <= 'z')
8012  {
8013  if (yych == 't')
8014  {
8015  goto basic_json_parser_25;
8016  }
8017  goto basic_json_parser_4;
8018  }
8019  else
8020  {
8021  if (yych <= '{')
8022  {
8023  goto basic_json_parser_26;
8024  }
8025  if (yych == '}')
8026  {
8027  goto basic_json_parser_28;
8028  }
8029  goto basic_json_parser_4;
8030  }
8031  }
8032  }
8033 basic_json_parser_2:
8034  ++m_cursor;
8035  {
8036  last_token_type = token_type::end_of_input;
8037  break;
8038  }
8039 basic_json_parser_4:
8040  ++m_cursor;
8041 basic_json_parser_5:
8042  {
8043  last_token_type = token_type::parse_error;
8044  break;
8045  }
8046 basic_json_parser_6:
8047  ++m_cursor;
8048  if (m_limit <= m_cursor)
8049  {
8050  fill_line_buffer(1); // LCOV_EXCL_LINE
8051  }
8052  yych = *m_cursor;
8053  if (yybm[0 + yych] & 32)
8054  {
8055  goto basic_json_parser_6;
8056  }
8057  {
8058  continue;
8059  }
8060 basic_json_parser_9:
8061  yyaccept = 0;
8062  yych = *(m_marker = ++m_cursor);
8063  if (yych <= 0x1F)
8064  {
8065  goto basic_json_parser_5;
8066  }
8067  if (yych <= 0x7F)
8068  {
8069  goto basic_json_parser_31;
8070  }
8071  if (yych <= 0xC1)
8072  {
8073  goto basic_json_parser_5;
8074  }
8075  if (yych <= 0xF4)
8076  {
8077  goto basic_json_parser_31;
8078  }
8079  goto basic_json_parser_5;
8080 basic_json_parser_10:
8081  ++m_cursor;
8082  {
8083  last_token_type = token_type::value_separator;
8084  break;
8085  }
8086 basic_json_parser_12:
8087  yych = *++m_cursor;
8088  if (yych <= '/')
8089  {
8090  goto basic_json_parser_5;
8091  }
8092  if (yych <= '0')
8093  {
8094  goto basic_json_parser_13;
8095  }
8096  if (yych <= '9')
8097  {
8098  goto basic_json_parser_15;
8099  }
8100  goto basic_json_parser_5;
8101 basic_json_parser_13:
8102  yyaccept = 1;
8103  yych = *(m_marker = ++m_cursor);
8104  if (yych <= 'D')
8105  {
8106  if (yych == '.')
8107  {
8108  goto basic_json_parser_43;
8109  }
8110  }
8111  else
8112  {
8113  if (yych <= 'E')
8114  {
8115  goto basic_json_parser_44;
8116  }
8117  if (yych == 'e')
8118  {
8119  goto basic_json_parser_44;
8120  }
8121  }
8122 basic_json_parser_14:
8123  {
8124  last_token_type = token_type::value_number;
8125  break;
8126  }
8127 basic_json_parser_15:
8128  yyaccept = 1;
8129  m_marker = ++m_cursor;
8130  if ((m_limit - m_cursor) < 3)
8131  {
8132  fill_line_buffer(3); // LCOV_EXCL_LINE
8133  }
8134  yych = *m_cursor;
8135  if (yybm[0 + yych] & 64)
8136  {
8137  goto basic_json_parser_15;
8138  }
8139  if (yych <= 'D')
8140  {
8141  if (yych == '.')
8142  {
8143  goto basic_json_parser_43;
8144  }
8145  goto basic_json_parser_14;
8146  }
8147  else
8148  {
8149  if (yych <= 'E')
8150  {
8151  goto basic_json_parser_44;
8152  }
8153  if (yych == 'e')
8154  {
8155  goto basic_json_parser_44;
8156  }
8157  goto basic_json_parser_14;
8158  }
8159 basic_json_parser_17:
8160  ++m_cursor;
8161  {
8162  last_token_type = token_type::name_separator;
8163  break;
8164  }
8165 basic_json_parser_19:
8166  ++m_cursor;
8167  {
8168  last_token_type = token_type::begin_array;
8169  break;
8170  }
8171 basic_json_parser_21:
8172  ++m_cursor;
8173  {
8174  last_token_type = token_type::end_array;
8175  break;
8176  }
8177 basic_json_parser_23:
8178  yyaccept = 0;
8179  yych = *(m_marker = ++m_cursor);
8180  if (yych == 'a')
8181  {
8182  goto basic_json_parser_45;
8183  }
8184  goto basic_json_parser_5;
8185 basic_json_parser_24:
8186  yyaccept = 0;
8187  yych = *(m_marker = ++m_cursor);
8188  if (yych == 'u')
8189  {
8190  goto basic_json_parser_46;
8191  }
8192  goto basic_json_parser_5;
8193 basic_json_parser_25:
8194  yyaccept = 0;
8195  yych = *(m_marker = ++m_cursor);
8196  if (yych == 'r')
8197  {
8198  goto basic_json_parser_47;
8199  }
8200  goto basic_json_parser_5;
8201 basic_json_parser_26:
8202  ++m_cursor;
8203  {
8204  last_token_type = token_type::begin_object;
8205  break;
8206  }
8207 basic_json_parser_28:
8208  ++m_cursor;
8209  {
8210  last_token_type = token_type::end_object;
8211  break;
8212  }
8213 basic_json_parser_30:
8214  ++m_cursor;
8215  if (m_limit <= m_cursor)
8216  {
8217  fill_line_buffer(1); // LCOV_EXCL_LINE
8218  }
8219  yych = *m_cursor;
8220 basic_json_parser_31:
8221  if (yybm[0 + yych] & 128)
8222  {
8223  goto basic_json_parser_30;
8224  }
8225  if (yych <= 0xE0)
8226  {
8227  if (yych <= '\\')
8228  {
8229  if (yych <= 0x1F)
8230  {
8231  goto basic_json_parser_32;
8232  }
8233  if (yych <= '"')
8234  {
8235  goto basic_json_parser_33;
8236  }
8237  goto basic_json_parser_35;
8238  }
8239  else
8240  {
8241  if (yych <= 0xC1)
8242  {
8243  goto basic_json_parser_32;
8244  }
8245  if (yych <= 0xDF)
8246  {
8247  goto basic_json_parser_36;
8248  }
8249  goto basic_json_parser_37;
8250  }
8251  }
8252  else
8253  {
8254  if (yych <= 0xEF)
8255  {
8256  if (yych == 0xED)
8257  {
8258  goto basic_json_parser_39;
8259  }
8260  goto basic_json_parser_38;
8261  }
8262  else
8263  {
8264  if (yych <= 0xF0)
8265  {
8266  goto basic_json_parser_40;
8267  }
8268  if (yych <= 0xF3)
8269  {
8270  goto basic_json_parser_41;
8271  }
8272  if (yych <= 0xF4)
8273  {
8274  goto basic_json_parser_42;
8275  }
8276  }
8277  }
8278 basic_json_parser_32:
8279  m_cursor = m_marker;
8280  if (yyaccept == 0)
8281  {
8282  goto basic_json_parser_5;
8283  }
8284  else
8285  {
8286  goto basic_json_parser_14;
8287  }
8288 basic_json_parser_33:
8289  ++m_cursor;
8290  {
8291  last_token_type = token_type::value_string;
8292  break;
8293  }
8294 basic_json_parser_35:
8295  ++m_cursor;
8296  if (m_limit <= m_cursor)
8297  {
8298  fill_line_buffer(1); // LCOV_EXCL_LINE
8299  }
8300  yych = *m_cursor;
8301  if (yych <= 'e')
8302  {
8303  if (yych <= '/')
8304  {
8305  if (yych == '"')
8306  {
8307  goto basic_json_parser_30;
8308  }
8309  if (yych <= '.')
8310  {
8311  goto basic_json_parser_32;
8312  }
8313  goto basic_json_parser_30;
8314  }
8315  else
8316  {
8317  if (yych <= '\\')
8318  {
8319  if (yych <= '[')
8320  {
8321  goto basic_json_parser_32;
8322  }
8323  goto basic_json_parser_30;
8324  }
8325  else
8326  {
8327  if (yych == 'b')
8328  {
8329  goto basic_json_parser_30;
8330  }
8331  goto basic_json_parser_32;
8332  }
8333  }
8334  }
8335  else
8336  {
8337  if (yych <= 'q')
8338  {
8339  if (yych <= 'f')
8340  {
8341  goto basic_json_parser_30;
8342  }
8343  if (yych == 'n')
8344  {
8345  goto basic_json_parser_30;
8346  }
8347  goto basic_json_parser_32;
8348  }
8349  else
8350  {
8351  if (yych <= 's')
8352  {
8353  if (yych <= 'r')
8354  {
8355  goto basic_json_parser_30;
8356  }
8357  goto basic_json_parser_32;
8358  }
8359  else
8360  {
8361  if (yych <= 't')
8362  {
8363  goto basic_json_parser_30;
8364  }
8365  if (yych <= 'u')
8366  {
8367  goto basic_json_parser_48;
8368  }
8369  goto basic_json_parser_32;
8370  }
8371  }
8372  }
8373 basic_json_parser_36:
8374  ++m_cursor;
8375  if (m_limit <= m_cursor)
8376  {
8377  fill_line_buffer(1); // LCOV_EXCL_LINE
8378  }
8379  yych = *m_cursor;
8380  if (yych <= 0x7F)
8381  {
8382  goto basic_json_parser_32;
8383  }
8384  if (yych <= 0xBF)
8385  {
8386  goto basic_json_parser_30;
8387  }
8388  goto basic_json_parser_32;
8389 basic_json_parser_37:
8390  ++m_cursor;
8391  if (m_limit <= m_cursor)
8392  {
8393  fill_line_buffer(1); // LCOV_EXCL_LINE
8394  }
8395  yych = *m_cursor;
8396  if (yych <= 0x9F)
8397  {
8398  goto basic_json_parser_32;
8399  }
8400  if (yych <= 0xBF)
8401  {
8402  goto basic_json_parser_36;
8403  }
8404  goto basic_json_parser_32;
8405 basic_json_parser_38:
8406  ++m_cursor;
8407  if (m_limit <= m_cursor)
8408  {
8409  fill_line_buffer(1); // LCOV_EXCL_LINE
8410  }
8411  yych = *m_cursor;
8412  if (yych <= 0x7F)
8413  {
8414  goto basic_json_parser_32;
8415  }
8416  if (yych <= 0xBF)
8417  {
8418  goto basic_json_parser_36;
8419  }
8420  goto basic_json_parser_32;
8421 basic_json_parser_39:
8422  ++m_cursor;
8423  if (m_limit <= m_cursor)
8424  {
8425  fill_line_buffer(1); // LCOV_EXCL_LINE
8426  }
8427  yych = *m_cursor;
8428  if (yych <= 0x7F)
8429  {
8430  goto basic_json_parser_32;
8431  }
8432  if (yych <= 0x9F)
8433  {
8434  goto basic_json_parser_36;
8435  }
8436  goto basic_json_parser_32;
8437 basic_json_parser_40:
8438  ++m_cursor;
8439  if (m_limit <= m_cursor)
8440  {
8441  fill_line_buffer(1); // LCOV_EXCL_LINE
8442  }
8443  yych = *m_cursor;
8444  if (yych <= 0x8F)
8445  {
8446  goto basic_json_parser_32;
8447  }
8448  if (yych <= 0xBF)
8449  {
8450  goto basic_json_parser_38;
8451  }
8452  goto basic_json_parser_32;
8453 basic_json_parser_41:
8454  ++m_cursor;
8455  if (m_limit <= m_cursor)
8456  {
8457  fill_line_buffer(1); // LCOV_EXCL_LINE
8458  }
8459  yych = *m_cursor;
8460  if (yych <= 0x7F)
8461  {
8462  goto basic_json_parser_32;
8463  }
8464  if (yych <= 0xBF)
8465  {
8466  goto basic_json_parser_38;
8467  }
8468  goto basic_json_parser_32;
8469 basic_json_parser_42:
8470  ++m_cursor;
8471  if (m_limit <= m_cursor)
8472  {
8473  fill_line_buffer(1); // LCOV_EXCL_LINE
8474  }
8475  yych = *m_cursor;
8476  if (yych <= 0x7F)
8477  {
8478  goto basic_json_parser_32;
8479  }
8480  if (yych <= 0x8F)
8481  {
8482  goto basic_json_parser_38;
8483  }
8484  goto basic_json_parser_32;
8485 basic_json_parser_43:
8486  yych = *++m_cursor;
8487  if (yych <= '/')
8488  {
8489  goto basic_json_parser_32;
8490  }
8491  if (yych <= '9')
8492  {
8493  goto basic_json_parser_49;
8494  }
8495  goto basic_json_parser_32;
8496 basic_json_parser_44:
8497  yych = *++m_cursor;
8498  if (yych <= ',')
8499  {
8500  if (yych == '+')
8501  {
8502  goto basic_json_parser_51;
8503  }
8504  goto basic_json_parser_32;
8505  }
8506  else
8507  {
8508  if (yych <= '-')
8509  {
8510  goto basic_json_parser_51;
8511  }
8512  if (yych <= '/')
8513  {
8514  goto basic_json_parser_32;
8515  }
8516  if (yych <= '9')
8517  {
8518  goto basic_json_parser_52;
8519  }
8520  goto basic_json_parser_32;
8521  }
8522 basic_json_parser_45:
8523  yych = *++m_cursor;
8524  if (yych == 'l')
8525  {
8526  goto basic_json_parser_54;
8527  }
8528  goto basic_json_parser_32;
8529 basic_json_parser_46:
8530  yych = *++m_cursor;
8531  if (yych == 'l')
8532  {
8533  goto basic_json_parser_55;
8534  }
8535  goto basic_json_parser_32;
8536 basic_json_parser_47:
8537  yych = *++m_cursor;
8538  if (yych == 'u')
8539  {
8540  goto basic_json_parser_56;
8541  }
8542  goto basic_json_parser_32;
8543 basic_json_parser_48:
8544  ++m_cursor;
8545  if (m_limit <= m_cursor)
8546  {
8547  fill_line_buffer(1); // LCOV_EXCL_LINE
8548  }
8549  yych = *m_cursor;
8550  if (yych <= '@')
8551  {
8552  if (yych <= '/')
8553  {
8554  goto basic_json_parser_32;
8555  }
8556  if (yych <= '9')
8557  {
8558  goto basic_json_parser_57;
8559  }
8560  goto basic_json_parser_32;
8561  }
8562  else
8563  {
8564  if (yych <= 'F')
8565  {
8566  goto basic_json_parser_57;
8567  }
8568  if (yych <= '`')
8569  {
8570  goto basic_json_parser_32;
8571  }
8572  if (yych <= 'f')
8573  {
8574  goto basic_json_parser_57;
8575  }
8576  goto basic_json_parser_32;
8577  }
8578 basic_json_parser_49:
8579  yyaccept = 1;
8580  m_marker = ++m_cursor;
8581  if ((m_limit - m_cursor) < 3)
8582  {
8583  fill_line_buffer(3); // LCOV_EXCL_LINE
8584  }
8585  yych = *m_cursor;
8586  if (yych <= 'D')
8587  {
8588  if (yych <= '/')
8589  {
8590  goto basic_json_parser_14;
8591  }
8592  if (yych <= '9')
8593  {
8594  goto basic_json_parser_49;
8595  }
8596  goto basic_json_parser_14;
8597  }
8598  else
8599  {
8600  if (yych <= 'E')
8601  {
8602  goto basic_json_parser_44;
8603  }
8604  if (yych == 'e')
8605  {
8606  goto basic_json_parser_44;
8607  }
8608  goto basic_json_parser_14;
8609  }
8610 basic_json_parser_51:
8611  yych = *++m_cursor;
8612  if (yych <= '/')
8613  {
8614  goto basic_json_parser_32;
8615  }
8616  if (yych >= ':')
8617  {
8618  goto basic_json_parser_32;
8619  }
8620 basic_json_parser_52:
8621  ++m_cursor;
8622  if (m_limit <= m_cursor)
8623  {
8624  fill_line_buffer(1); // LCOV_EXCL_LINE
8625  }
8626  yych = *m_cursor;
8627  if (yych <= '/')
8628  {
8629  goto basic_json_parser_14;
8630  }
8631  if (yych <= '9')
8632  {
8633  goto basic_json_parser_52;
8634  }
8635  goto basic_json_parser_14;
8636 basic_json_parser_54:
8637  yych = *++m_cursor;
8638  if (yych == 's')
8639  {
8640  goto basic_json_parser_58;
8641  }
8642  goto basic_json_parser_32;
8643 basic_json_parser_55:
8644  yych = *++m_cursor;
8645  if (yych == 'l')
8646  {
8647  goto basic_json_parser_59;
8648  }
8649  goto basic_json_parser_32;
8650 basic_json_parser_56:
8651  yych = *++m_cursor;
8652  if (yych == 'e')
8653  {
8654  goto basic_json_parser_61;
8655  }
8656  goto basic_json_parser_32;
8657 basic_json_parser_57:
8658  ++m_cursor;
8659  if (m_limit <= m_cursor)
8660  {
8661  fill_line_buffer(1); // LCOV_EXCL_LINE
8662  }
8663  yych = *m_cursor;
8664  if (yych <= '@')
8665  {
8666  if (yych <= '/')
8667  {
8668  goto basic_json_parser_32;
8669  }
8670  if (yych <= '9')
8671  {
8672  goto basic_json_parser_63;
8673  }
8674  goto basic_json_parser_32;
8675  }
8676  else
8677  {
8678  if (yych <= 'F')
8679  {
8680  goto basic_json_parser_63;
8681  }
8682  if (yych <= '`')
8683  {
8684  goto basic_json_parser_32;
8685  }
8686  if (yych <= 'f')
8687  {
8688  goto basic_json_parser_63;
8689  }
8690  goto basic_json_parser_32;
8691  }
8692 basic_json_parser_58:
8693  yych = *++m_cursor;
8694  if (yych == 'e')
8695  {
8696  goto basic_json_parser_64;
8697  }
8698  goto basic_json_parser_32;
8699 basic_json_parser_59:
8700  ++m_cursor;
8701  {
8702  last_token_type = token_type::literal_null;
8703  break;
8704  }
8705 basic_json_parser_61:
8706  ++m_cursor;
8707  {
8708  last_token_type = token_type::literal_true;
8709  break;
8710  }
8711 basic_json_parser_63:
8712  ++m_cursor;
8713  if (m_limit <= m_cursor)
8714  {
8715  fill_line_buffer(1); // LCOV_EXCL_LINE
8716  }
8717  yych = *m_cursor;
8718  if (yych <= '@')
8719  {
8720  if (yych <= '/')
8721  {
8722  goto basic_json_parser_32;
8723  }
8724  if (yych <= '9')
8725  {
8726  goto basic_json_parser_66;
8727  }
8728  goto basic_json_parser_32;
8729  }
8730  else
8731  {
8732  if (yych <= 'F')
8733  {
8734  goto basic_json_parser_66;
8735  }
8736  if (yych <= '`')
8737  {
8738  goto basic_json_parser_32;
8739  }
8740  if (yych <= 'f')
8741  {
8742  goto basic_json_parser_66;
8743  }
8744  goto basic_json_parser_32;
8745  }
8746 basic_json_parser_64:
8747  ++m_cursor;
8748  {
8749  last_token_type = token_type::literal_false;
8750  break;
8751  }
8752 basic_json_parser_66:
8753  ++m_cursor;
8754  if (m_limit <= m_cursor)
8755  {
8756  fill_line_buffer(1); // LCOV_EXCL_LINE
8757  }
8758  yych = *m_cursor;
8759  if (yych <= '@')
8760  {
8761  if (yych <= '/')
8762  {
8763  goto basic_json_parser_32;
8764  }
8765  if (yych <= '9')
8766  {
8767  goto basic_json_parser_30;
8768  }
8769  goto basic_json_parser_32;
8770  }
8771  else
8772  {
8773  if (yych <= 'F')
8774  {
8775  goto basic_json_parser_30;
8776  }
8777  if (yych <= '`')
8778  {
8779  goto basic_json_parser_32;
8780  }
8781  if (yych <= 'f')
8782  {
8783  goto basic_json_parser_30;
8784  }
8785  goto basic_json_parser_32;
8786  }
8787  }
8788 
8789  }
8790 
8791  return last_token_type;
8792  }
8793 
8822  void fill_line_buffer(size_t n = 0)
8823  {
8824  // if line buffer is used, m_content points to its data
8825  assert(m_line_buffer.empty()
8826  or m_content == reinterpret_cast<const lexer_char_t*>(m_line_buffer.data()));
8827 
8828  // if line buffer is used, m_limit is set past the end of its data
8829  assert(m_line_buffer.empty()
8830  or m_limit == m_content + m_line_buffer.size());
8831 
8832  // pointer relationships
8833  assert(m_content <= m_start);
8834  assert(m_start <= m_cursor);
8835  assert(m_cursor <= m_limit);
8836  assert(m_marker == nullptr or m_marker <= m_limit);
8837 
8838  // number of processed characters (p)
8839  const size_t num_processed_chars = static_cast<size_t>(m_start - m_content);
8840  // offset for m_marker wrt. to m_start
8841  const auto offset_marker = (m_marker == nullptr) ? 0 : m_marker - m_start;
8842  // number of unprocessed characters (u)
8843  const auto offset_cursor = m_cursor - m_start;
8844 
8845  // no stream is used or end of file is reached
8846  if (m_stream == nullptr or m_stream->eof())
8847  {
8848  // m_start may or may not be pointing into m_line_buffer at
8849  // this point. We trust the standand library to do the right
8850  // thing. See http://stackoverflow.com/q/28142011/266378
8851  m_line_buffer.assign(m_start, m_limit);
8852 
8853  // append n characters to make sure that there is sufficient
8854  // space between m_cursor and m_limit
8855  m_line_buffer.append(1, '\x00');
8856  if (n > 0)
8857  {
8858  m_line_buffer.append(n - 1, '\x01');
8859  }
8860  }
8861  else
8862  {
8863  // delete processed characters from line buffer
8864  m_line_buffer.erase(0, num_processed_chars);
8865  // read next line from input stream
8866  m_line_buffer_tmp.clear();
8867  std::getline(*m_stream, m_line_buffer_tmp, '\n');
8868 
8869  // add line with newline symbol to the line buffer
8870  m_line_buffer += m_line_buffer_tmp;
8871  m_line_buffer.push_back('\n');
8872  }
8873 
8874  // set pointers
8875  m_content = reinterpret_cast<const lexer_char_t*>(m_line_buffer.data());
8876  assert(m_content != nullptr);
8877  m_start = m_content;
8878  m_marker = m_start + offset_marker;
8879  m_cursor = m_start + offset_cursor;
8880  m_limit = m_start + m_line_buffer.size();
8881  }
8882 
8884  string_t get_token_string() const
8885  {
8886  assert(m_start != nullptr);
8887  return string_t(reinterpret_cast<typename string_t::const_pointer>(m_start),
8888  static_cast<size_t>(m_cursor - m_start));
8889  }
8890 
8948  string_t get_string() const
8949  {
8950  assert(m_cursor - m_start >= 2);
8951 
8952  string_t result;
8953  result.reserve(static_cast<size_t>(m_cursor - m_start - 2));
8954 
8955  // iterate the result between the quotes
8956  for (const lexer_char_t* i = m_start + 1; i < m_cursor - 1; ++i)
8957  {
8958  // find next escape character
8959  auto e = std::find(i, m_cursor - 1, '\\');
8960  if (e != i)
8961  {
8962  // see https://github.com/nlohmann/json/issues/365#issuecomment-262874705
8963  for (auto k = i; k < e; k++)
8964  {
8965  result.push_back(static_cast<typename string_t::value_type>(*k));
8966  }
8967  i = e - 1; // -1 because of ++i
8968  }
8969  else
8970  {
8971  // processing escaped character
8972  // read next character
8973  ++i;
8974 
8975  switch (*i)
8976  {
8977  // the default escapes
8978  case 't':
8979  {
8980  result += "\t";
8981  break;
8982  }
8983  case 'b':
8984  {
8985  result += "\b";
8986  break;
8987  }
8988  case 'f':
8989  {
8990  result += "\f";
8991  break;
8992  }
8993  case 'n':
8994  {
8995  result += "\n";
8996  break;
8997  }
8998  case 'r':
8999  {
9000  result += "\r";
9001  break;
9002  }
9003  case '\\':
9004  {
9005  result += "\\";
9006  break;
9007  }
9008  case '/':
9009  {
9010  result += "/";
9011  break;
9012  }
9013  case '"':
9014  {
9015  result += "\"";
9016  break;
9017  }
9018 
9019  // unicode
9020  case 'u':
9021  {
9022  // get code xxxx from uxxxx
9023  auto codepoint = std::strtoul(std::string(reinterpret_cast<typename string_t::const_pointer>(i + 1),
9024  4).c_str(), nullptr, 16);
9025 
9026  // check if codepoint is a high surrogate
9027  if (codepoint >= 0xD800 and codepoint <= 0xDBFF)
9028  {
9029  // make sure there is a subsequent unicode
9030  if ((i + 6 >= m_limit) or * (i + 5) != '\\' or * (i + 6) != 'u')
9031  {
9032  throw std::invalid_argument("missing low surrogate");
9033  }
9034 
9035  // get code yyyy from uxxxx\uyyyy
9036  auto codepoint2 = std::strtoul(std::string(reinterpret_cast<typename string_t::const_pointer>
9037  (i + 7), 4).c_str(), nullptr, 16);
9038  result += to_unicode(codepoint, codepoint2);
9039  // skip the next 10 characters (xxxx\uyyyy)
9040  i += 10;
9041  }
9042  else if (codepoint >= 0xDC00 and codepoint <= 0xDFFF)
9043  {
9044  // we found a lone low surrogate
9045  throw std::invalid_argument("missing high surrogate");
9046  }
9047  else
9048  {
9049  // add unicode character(s)
9050  result += to_unicode(codepoint);
9051  // skip the next four characters (xxxx)
9052  i += 4;
9053  }
9054  break;
9055  }
9056  }
9057  }
9058  }
9059 
9060  return result;
9061  }
9062 
9078  long double str_to_float_t(long double* /* type */, char** endptr) const
9079  {
9080  return std::strtold(reinterpret_cast<typename string_t::const_pointer>(m_start), endptr);
9081  }
9082 
9098  double str_to_float_t(double* /* type */, char** endptr) const
9099  {
9100  return std::strtod(reinterpret_cast<typename string_t::const_pointer>(m_start), endptr);
9101  }
9102 
9118  float str_to_float_t(float* /* type */, char** endptr) const
9119  {
9120  return std::strtof(reinterpret_cast<typename string_t::const_pointer>(m_start), endptr);
9121  }
9122 
9144  void get_number(basic_json& result) const
9145  {
9146  assert(m_start != nullptr);
9147 
9148  const lexer::lexer_char_t* curptr = m_start;
9149 
9150  // accumulate the integer conversion result (unsigned for now)
9151  number_unsigned_t value = 0;
9152 
9153  // maximum absolute value of the relevant integer type
9154  number_unsigned_t max;
9155 
9156  // temporarily store the type to avoid unecessary bitfield access
9157  value_t type;
9158 
9159  // look for sign
9160  if (*curptr == '-')
9161  {
9162  type = value_t::number_integer;
9163  max = static_cast<uint64_t>((std::numeric_limits<number_integer_t>::max)()) + 1;
9164  curptr++;
9165  }
9166  else
9167  {
9168  type = value_t::number_unsigned;
9169  max = static_cast<uint64_t>((std::numeric_limits<number_unsigned_t>::max)());
9170  }
9171 
9172  // count the significant figures
9173  for (; curptr < m_cursor; curptr++)
9174  {
9175  // quickly skip tests if a digit
9176  if (*curptr < '0' || *curptr > '9')
9177  {
9178  if (*curptr == '.')
9179  {
9180  // don't count '.' but change to float
9181  type = value_t::number_float;
9182  continue;
9183  }
9184  // assume exponent (if not then will fail parse): change to
9185  // float, stop counting and record exponent details
9186  type = value_t::number_float;
9187  break;
9188  }
9189 
9190  // skip if definitely not an integer
9191  if (type != value_t::number_float)
9192  {
9193  // multiply last value by ten and add the new digit
9194  auto temp = value * 10 + *curptr - '0';
9195 
9196  // test for overflow
9197  if (temp < value || temp > max)
9198  {
9199  // overflow
9200  type = value_t::number_float;
9201  }
9202  else
9203  {
9204  // no overflow - save it
9205  value = temp;
9206  }
9207  }
9208  }
9209 
9210  // save the value (if not a float)
9211  if (type == value_t::number_unsigned)
9212  {
9213  result.m_value.number_unsigned = value;
9214  }
9215  else if (type == value_t::number_integer)
9216  {
9217  result.m_value.number_integer = -static_cast<number_integer_t>(value);
9218  }
9219  else
9220  {
9221  // parse with strtod
9222  result.m_value.number_float = str_to_float_t(static_cast<number_float_t*>(nullptr), NULL);
9223 
9224  // replace infinity and NAN by null
9225  if (not std::isfinite(result.m_value.number_float))
9226  {
9227  type = value_t::null;
9228  result.m_value = basic_json::json_value();
9229  }
9230  }
9231 
9232  // save the type
9233  result.m_type = type;
9234  }
9235 
9236  private:
9238  std::istream* m_stream = nullptr;
9240  string_t m_line_buffer {};
9242  string_t m_line_buffer_tmp {};
9244  const lexer_char_t* m_content = nullptr;
9246  const lexer_char_t* m_start = nullptr;
9248  const lexer_char_t* m_marker = nullptr;
9250  const lexer_char_t* m_cursor = nullptr;
9252  const lexer_char_t* m_limit = nullptr;
9254  token_type last_token_type = token_type::end_of_input;
9255  };
9256 
9262  class parser
9263  {
9264  public:
9266  parser(const char* buff, const parser_callback_t cb = nullptr)
9267  : callback(cb),
9268  m_lexer(reinterpret_cast<const typename lexer::lexer_char_t*>(buff), std::strlen(buff))
9269  {}
9270 
9272  parser(std::istream& is, const parser_callback_t cb = nullptr)
9273  : callback(cb), m_lexer(is)
9274  {}
9275 
9277  template<class IteratorType, typename std::enable_if<
9278  std::is_same<typename std::iterator_traits<IteratorType>::iterator_category, std::random_access_iterator_tag>::value
9279  , int>::type
9280  = 0>
9281  parser(IteratorType first, IteratorType last, const parser_callback_t cb = nullptr)
9282  : callback(cb),
9283  m_lexer(reinterpret_cast<const typename lexer::lexer_char_t*>(&(*first)),
9284  static_cast<size_t>(std::distance(first, last)))
9285  {}
9286 
9288  basic_json parse()
9289  {
9290  // read first token
9291  get_token();
9292 
9293  basic_json result = parse_internal(true);
9294  result.assert_invariant();
9295 
9296  expect(lexer::token_type::end_of_input);
9297 
9298  // return parser result and replace it with null in case the
9299  // top-level value was discarded by the callback function
9300  return result.is_discarded() ? basic_json() : std::move(result);
9301  }
9302 
9303  private:
9305  basic_json parse_internal(bool keep)
9306  {
9307  auto result = basic_json(value_t::discarded);
9308 
9309  switch (last_token)
9310  {
9311  case lexer::token_type::begin_object:
9312  {
9313  if (keep and (not callback
9314  or ((keep = callback(depth++, parse_event_t::object_start, result)) != 0)))
9315  {
9316  // explicitly set result to object to cope with {}
9317  result.m_type = value_t::object;
9318  result.m_value = value_t::object;
9319  }
9320 
9321  // read next token
9322  get_token();
9323 
9324  // closing } -> we are done
9325  if (last_token == lexer::token_type::end_object)
9326  {
9327  get_token();
9328  if (keep and callback and not callback(--depth, parse_event_t::object_end, result))
9329  {
9330  result = basic_json(value_t::discarded);
9331  }
9332  return result;
9333  }
9334 
9335  // no comma is expected here
9336  unexpect(lexer::token_type::value_separator);
9337 
9338  // otherwise: parse key-value pairs
9339  do
9340  {
9341  // ugly, but could be fixed with loop reorganization
9342  if (last_token == lexer::token_type::value_separator)
9343  {
9344  get_token();
9345  }
9346 
9347  // store key
9348  expect(lexer::token_type::value_string);
9349  const auto key = m_lexer.get_string();
9350 
9351  bool keep_tag = false;
9352  if (keep)
9353  {
9354  if (callback)
9355  {
9356  basic_json k(key);
9357  keep_tag = callback(depth, parse_event_t::key, k);
9358  }
9359  else
9360  {
9361  keep_tag = true;
9362  }
9363  }
9364 
9365  // parse separator (:)
9366  get_token();
9367  expect(lexer::token_type::name_separator);
9368 
9369  // parse and add value
9370  get_token();
9371  auto value = parse_internal(keep);
9372  if (keep and keep_tag and not value.is_discarded())
9373  {
9374  result[key] = std::move(value);
9375  }
9376  }
9377  while (last_token == lexer::token_type::value_separator);
9378 
9379  // closing }
9380  expect(lexer::token_type::end_object);
9381  get_token();
9382  if (keep and callback and not callback(--depth, parse_event_t::object_end, result))
9383  {
9384  result = basic_json(value_t::discarded);
9385  }
9386 
9387  return result;
9388  }
9389 
9390  case lexer::token_type::begin_array:
9391  {
9392  if (keep and (not callback
9393  or ((keep = callback(depth++, parse_event_t::array_start, result)) != 0)))
9394  {
9395  // explicitly set result to object to cope with []
9396  result.m_type = value_t::array;
9397  result.m_value = value_t::array;
9398  }
9399 
9400  // read next token
9401  get_token();
9402 
9403  // closing ] -> we are done
9404  if (last_token == lexer::token_type::end_array)
9405  {
9406  get_token();
9407  if (callback and not callback(--depth, parse_event_t::array_end, result))
9408  {
9409  result = basic_json(value_t::discarded);
9410  }
9411  return result;
9412  }
9413 
9414  // no comma is expected here
9415  unexpect(lexer::token_type::value_separator);
9416 
9417  // otherwise: parse values
9418  do
9419  {
9420  // ugly, but could be fixed with loop reorganization
9421  if (last_token == lexer::token_type::value_separator)
9422  {
9423  get_token();
9424  }
9425 
9426  // parse value
9427  auto value = parse_internal(keep);
9428  if (keep and not value.is_discarded())
9429  {
9430  result.push_back(std::move(value));
9431  }
9432  }
9433  while (last_token == lexer::token_type::value_separator);
9434 
9435  // closing ]
9436  expect(lexer::token_type::end_array);
9437  get_token();
9438  if (keep and callback and not callback(--depth, parse_event_t::array_end, result))
9439  {
9440  result = basic_json(value_t::discarded);
9441  }
9442 
9443  return result;
9444  }
9445 
9446  case lexer::token_type::literal_null:
9447  {
9448  get_token();
9449  result.m_type = value_t::null;
9450  break;
9451  }
9452 
9453  case lexer::token_type::value_string:
9454  {
9455  const auto s = m_lexer.get_string();
9456  get_token();
9457  result = basic_json(s);
9458  break;
9459  }
9460 
9461  case lexer::token_type::literal_true:
9462  {
9463  get_token();
9464  result.m_type = value_t::boolean;
9465  result.m_value = true;
9466  break;
9467  }
9468 
9469  case lexer::token_type::literal_false:
9470  {
9471  get_token();
9472  result.m_type = value_t::boolean;
9473  result.m_value = false;
9474  break;
9475  }
9476 
9477  case lexer::token_type::value_number:
9478  {
9479  m_lexer.get_number(result);
9480  get_token();
9481  break;
9482  }
9483 
9484  default:
9485  {
9486  // the last token was unexpected
9487  unexpect(last_token);
9488  }
9489  }
9490 
9491  if (keep and callback and not callback(depth, parse_event_t::value, result))
9492  {
9493  result = basic_json(value_t::discarded);
9494  }
9495  return result;
9496  }
9497 
9499  typename lexer::token_type get_token()
9500  {
9501  last_token = m_lexer.scan();
9502  return last_token;
9503  }
9504 
9505  void expect(typename lexer::token_type t) const
9506  {
9507  if (t != last_token)
9508  {
9509  std::string error_msg = "parse error - unexpected ";
9510  error_msg += (last_token == lexer::token_type::parse_error ? ("'" + m_lexer.get_token_string() +
9511  "'") :
9512  lexer::token_type_name(last_token));
9513  error_msg += "; expected " + lexer::token_type_name(t);
9514  throw std::invalid_argument(error_msg);
9515  }
9516  }
9517 
9518  void unexpect(typename lexer::token_type t) const
9519  {
9520  if (t == last_token)
9521  {
9522  std::string error_msg = "parse error - unexpected ";
9523  error_msg += (last_token == lexer::token_type::parse_error ? ("'" + m_lexer.get_token_string() +
9524  "'") :
9525  lexer::token_type_name(last_token));
9526  throw std::invalid_argument(error_msg);
9527  }
9528  }
9529 
9530  private:
9532  int depth = 0;
9534  const parser_callback_t callback = nullptr;
9536  typename lexer::token_type last_token = lexer::token_type::uninitialized;
9538  lexer m_lexer;
9539  };
9540 
9541  public:
9554  {
9556  friend class basic_json;
9557 
9558  public:
9581  explicit json_pointer(const std::string& s = "")
9582  : reference_tokens(split(s))
9583  {}
9584 
9600  std::string to_string() const noexcept
9601  {
9602  return std::accumulate(reference_tokens.begin(),
9603  reference_tokens.end(), std::string{},
9604  [](const std::string & a, const std::string & b)
9605  {
9606  return a + "/" + escape(b);
9607  });
9608  }
9609 
9611  operator std::string() const
9612  {
9613  return to_string();
9614  }
9616  private:
9618  std::string pop_back()
9619  {
9620  if (is_root())
9621  {
9622  throw std::domain_error("JSON pointer has no parent");
9623  }
9624 
9625  auto last = reference_tokens.back();
9626  reference_tokens.pop_back();
9627  return last;
9628  }
9629 
9631  bool is_root() const
9632  {
9633  return reference_tokens.empty();
9634  }
9635 
9636  json_pointer top() const
9637  {
9638  if (is_root())
9639  {
9640  throw std::domain_error("JSON pointer has no parent");
9641  }
9642 
9643  json_pointer result = *this;
9644  result.reference_tokens = {reference_tokens[0]};
9645  return result;
9646  }
9647 
9653  reference get_and_create(reference j) const
9654  {
9655  pointer result = &j;
9656 
9657  // in case no reference tokens exist, return a reference to the
9658  // JSON value j which will be overwritten by a primitive value
9659  for (const auto& reference_token : reference_tokens)
9660  {
9661  switch (result->m_type)
9662  {
9663  case value_t::null:
9664  {
9665  if (reference_token == "0")
9666  {
9667  // start a new array if reference token is 0
9668  result = &result->operator[](0);
9669  }
9670  else
9671  {
9672  // start a new object otherwise
9673  result = &result->operator[](reference_token);
9674  }
9675  break;
9676  }
9677 
9678  case value_t::object:
9679  {
9680  // create an entry in the object
9681  result = &result->operator[](reference_token);
9682  break;
9683  }
9684 
9685  case value_t::array:
9686  {
9687  // create an entry in the array
9688  result = &result->operator[](static_cast<size_type>(std::stoi(reference_token)));
9689  break;
9690  }
9691 
9692  /*
9693  The following code is only reached if there exists a
9694  reference token _and_ the current value is primitive. In
9695  this case, we have an error situation, because primitive
9696  values may only occur as single value; that is, with an
9697  empty list of reference tokens.
9698  */
9699  default:
9700  {
9701  throw std::domain_error("invalid value to unflatten");
9702  }
9703  }
9704  }
9705 
9706  return *result;
9707  }
9708 
9728  reference get_unchecked(pointer ptr) const
9729  {
9730  for (const auto& reference_token : reference_tokens)
9731  {
9732  // convert null values to arrays or objects before continuing
9733  if (ptr->m_type == value_t::null)
9734  {
9735  // check if reference token is a number
9736  const bool nums = std::all_of(reference_token.begin(),
9737  reference_token.end(),
9738  [](const char x)
9739  {
9740  return std::isdigit(x);
9741  });
9742 
9743  // change value to array for numbers or "-" or to object
9744  // otherwise
9745  if (nums or reference_token == "-")
9746  {
9747  *ptr = value_t::array;
9748  }
9749  else
9750  {
9751  *ptr = value_t::object;
9752  }
9753  }
9754 
9755  switch (ptr->m_type)
9756  {
9757  case value_t::object:
9758  {
9759  // use unchecked object access
9760  ptr = &ptr->operator[](reference_token);
9761  break;
9762  }
9763 
9764  case value_t::array:
9765  {
9766  // error condition (cf. RFC 6901, Sect. 4)
9767  if (reference_token.size() > 1 and reference_token[0] == '0')
9768  {
9769  throw std::domain_error("array index must not begin with '0'");
9770  }
9771 
9772  if (reference_token == "-")
9773  {
9774  // explicityly treat "-" as index beyond the end
9775  ptr = &ptr->operator[](ptr->m_value.array->size());
9776  }
9777  else
9778  {
9779  // convert array index to number; unchecked access
9780  ptr = &ptr->operator[](static_cast<size_type>(std::stoi(reference_token)));
9781  }
9782  break;
9783  }
9784 
9785  default:
9786  {
9787  throw std::out_of_range("unresolved reference token '" + reference_token + "'");
9788  }
9789  }
9790  }
9791 
9792  return *ptr;
9793  }
9794 
9795  reference get_checked(pointer ptr) const
9796  {
9797  for (const auto& reference_token : reference_tokens)
9798  {
9799  switch (ptr->m_type)
9800  {
9801  case value_t::object:
9802  {
9803  // note: at performs range check
9804  ptr = &ptr->at(reference_token);
9805  break;
9806  }
9807 
9808  case value_t::array:
9809  {
9810  if (reference_token == "-")
9811  {
9812  // "-" always fails the range check
9813  throw std::out_of_range("array index '-' (" +
9814  std::to_string(ptr->m_value.array->size()) +
9815  ") is out of range");
9816  }
9817 
9818  // error condition (cf. RFC 6901, Sect. 4)
9819  if (reference_token.size() > 1 and reference_token[0] == '0')
9820  {
9821  throw std::domain_error("array index must not begin with '0'");
9822  }
9823 
9824  // note: at performs range check
9825  ptr = &ptr->at(static_cast<size_type>(std::stoi(reference_token)));
9826  break;
9827  }
9828 
9829  default:
9830  {
9831  throw std::out_of_range("unresolved reference token '" + reference_token + "'");
9832  }
9833  }
9834  }
9835 
9836  return *ptr;
9837  }
9838 
9847  const_reference get_unchecked(const_pointer ptr) const
9848  {
9849  for (const auto& reference_token : reference_tokens)
9850  {
9851  switch (ptr->m_type)
9852  {
9853  case value_t::object:
9854  {
9855  // use unchecked object access
9856  ptr = &ptr->operator[](reference_token);
9857  break;
9858  }
9859 
9860  case value_t::array:
9861  {
9862  if (reference_token == "-")
9863  {
9864  // "-" cannot be used for const access
9865  throw std::out_of_range("array index '-' (" +
9866  std::to_string(ptr->m_value.array->size()) +
9867  ") is out of range");
9868  }
9869 
9870  // error condition (cf. RFC 6901, Sect. 4)
9871  if (reference_token.size() > 1 and reference_token[0] == '0')
9872  {
9873  throw std::domain_error("array index must not begin with '0'");
9874  }
9875 
9876  // use unchecked array access
9877  ptr = &ptr->operator[](static_cast<size_type>(std::stoi(reference_token)));
9878  break;
9879  }
9880 
9881  default:
9882  {
9883  throw std::out_of_range("unresolved reference token '" + reference_token + "'");
9884  }
9885  }
9886  }
9887 
9888  return *ptr;
9889  }
9890 
9891  const_reference get_checked(const_pointer ptr) const
9892  {
9893  for (const auto& reference_token : reference_tokens)
9894  {
9895  switch (ptr->m_type)
9896  {
9897  case value_t::object:
9898  {
9899  // note: at performs range check
9900  ptr = &ptr->at(reference_token);
9901  break;
9902  }
9903 
9904  case value_t::array:
9905  {
9906  if (reference_token == "-")
9907  {
9908  // "-" always fails the range check
9909  throw std::out_of_range("array index '-' (" +
9910  std::to_string(ptr->m_value.array->size()) +
9911  ") is out of range");
9912  }
9913 
9914  // error condition (cf. RFC 6901, Sect. 4)
9915  if (reference_token.size() > 1 and reference_token[0] == '0')
9916  {
9917  throw std::domain_error("array index must not begin with '0'");
9918  }
9919 
9920  // note: at performs range check
9921  ptr = &ptr->at(static_cast<size_type>(std::stoi(reference_token)));
9922  break;
9923  }
9924 
9925  default:
9926  {
9927  throw std::out_of_range("unresolved reference token '" + reference_token + "'");
9928  }
9929  }
9930  }
9931 
9932  return *ptr;
9933  }
9934 
9936  static std::vector<std::string> split(const std::string& reference_string)
9937  {
9938  std::vector<std::string> result;
9939 
9940  // special case: empty reference string -> no reference tokens
9941  if (reference_string.empty())
9942  {
9943  return result;
9944  }
9945 
9946  // check if nonempty reference string begins with slash
9947  if (reference_string[0] != '/')
9948  {
9949  throw std::domain_error("JSON pointer must be empty or begin with '/'");
9950  }
9951 
9952  // extract the reference tokens:
9953  // - slash: position of the last read slash (or end of string)
9954  // - start: position after the previous slash
9955  for (
9956  // search for the first slash after the first character
9957  size_t slash = reference_string.find_first_of("/", 1),
9958  // set the beginning of the first reference token
9959  start = 1;
9960  // we can stop if start == string::npos+1 = 0
9961  start != 0;
9962  // set the beginning of the next reference token
9963  // (will eventually be 0 if slash == std::string::npos)
9964  start = slash + 1,
9965  // find next slash
9966  slash = reference_string.find_first_of("/", start))
9967  {
9968  // use the text between the beginning of the reference token
9969  // (start) and the last slash (slash).
9970  auto reference_token = reference_string.substr(start, slash - start);
9971 
9972  // check reference tokens are properly escaped
9973  for (size_t pos = reference_token.find_first_of("~");
9974  pos != std::string::npos;
9975  pos = reference_token.find_first_of("~", pos + 1))
9976  {
9977  assert(reference_token[pos] == '~');
9978 
9979  // ~ must be followed by 0 or 1
9980  if (pos == reference_token.size() - 1 or
9981  (reference_token[pos + 1] != '0' and
9982  reference_token[pos + 1] != '1'))
9983  {
9984  throw std::domain_error("escape error: '~' must be followed with '0' or '1'");
9985  }
9986  }
9987 
9988  // finally, store the reference token
9989  unescape(reference_token);
9990  result.push_back(reference_token);
9991  }
9992 
9993  return result;
9994  }
9995 
9996  private:
10011  static void replace_substring(std::string& s,
10012  const std::string& f,
10013  const std::string& t)
10014  {
10015  assert(not f.empty());
10016 
10017  for (
10018  size_t pos = s.find(f); // find first occurrence of f
10019  pos != std::string::npos; // make sure f was found
10020  s.replace(pos, f.size(), t), // replace with t
10021  pos = s.find(f, pos + t.size()) // find next occurrence of f
10022  );
10023  }
10024 
10026  static std::string escape(std::string s)
10027  {
10028  // escape "~"" to "~0" and "/" to "~1"
10029  replace_substring(s, "~", "~0");
10030  replace_substring(s, "/", "~1");
10031  return s;
10032  }
10033 
10035  static void unescape(std::string& s)
10036  {
10037  // first transform any occurrence of the sequence '~1' to '/'
10038  replace_substring(s, "~1", "/");
10039  // then transform any occurrence of the sequence '~0' to '~'
10040  replace_substring(s, "~0", "~");
10041  }
10042 
10050  static void flatten(const std::string& reference_string,
10051  const basic_json& value,
10052  basic_json& result)
10053  {
10054  switch (value.m_type)
10055  {
10056  case value_t::array:
10057  {
10058  if (value.m_value.array->empty())
10059  {
10060  // flatten empty array as null
10061  result[reference_string] = nullptr;
10062  }
10063  else
10064  {
10065  // iterate array and use index as reference string
10066  for (size_t i = 0; i < value.m_value.array->size(); ++i)
10067  {
10068  flatten(reference_string + "/" + std::to_string(i),
10069  value.m_value.array->operator[](i), result);
10070  }
10071  }
10072  break;
10073  }
10074 
10075  case value_t::object:
10076  {
10077  if (value.m_value.object->empty())
10078  {
10079  // flatten empty object as null
10080  result[reference_string] = nullptr;
10081  }
10082  else
10083  {
10084  // iterate object and use keys as reference string
10085  for (const auto& element : *value.m_value.object)
10086  {
10087  flatten(reference_string + "/" + escape(element.first),
10088  element.second, result);
10089  }
10090  }
10091  break;
10092  }
10093 
10094  default:
10095  {
10096  // add primitive value with its reference string
10097  result[reference_string] = value;
10098  break;
10099  }
10100  }
10101  }
10102 
10108  static basic_json unflatten(const basic_json& value)
10109  {
10110  if (not value.is_object())
10111  {
10112  throw std::domain_error("only objects can be unflattened");
10113  }
10114 
10115  basic_json result;
10116 
10117  // iterate the JSON object values
10118  for (const auto& element : *value.m_value.object)
10119  {
10120  if (not element.second.is_primitive())
10121  {
10122  throw std::domain_error("values in object must be primitive");
10123  }
10124 
10125  // assign value to reference pointed to by JSON pointer; Note
10126  // that if the JSON pointer is "" (i.e., points to the whole
10127  // value), function get_and_create returns a reference to
10128  // result itself. An assignment will then create a primitive
10129  // value.
10130  json_pointer(element.first).get_and_create(result) = element.second;
10131  }
10132 
10133  return result;
10134  }
10135 
10136  private:
10138  std::vector<std::string> reference_tokens {};
10139  };
10140 
10142  // JSON Pointer support //
10144 
10147 
10181  reference operator[](const json_pointer& ptr)
10182  {
10183  return ptr.get_unchecked(this);
10184  }
10208  const_reference operator[](const json_pointer& ptr) const
10209  {
10210  return ptr.get_unchecked(this);
10211  }
10233  reference at(const json_pointer& ptr)
10234  {
10235  return ptr.get_checked(this);
10236  }
10258  const_reference at(const json_pointer& ptr) const
10259  {
10260  return ptr.get_checked(this);
10261  }
10285  basic_json flatten() const
10286  {
10287  basic_json result(value_t::object);
10288  json_pointer::flatten("", *this, result);
10289  return result;
10290  }
10291 
10319  basic_json unflatten() const
10320  {
10321  return json_pointer::unflatten(*this);
10322  }
10325 
10327  // JSON Patch functions //
10329 
10332 
10369  basic_json patch(const basic_json& json_patch) const
10370  {
10371  // make a working copy to apply the patch to
10372  basic_json result = *this;
10374  // the valid JSON Patch operations
10375  enum class patch_operations {add, remove, replace, move, copy, test, invalid};
10376 
10377  const auto get_op = [](const std::string op)
10378  {
10379  if (op == "add")
10380  {
10381  return patch_operations::add;
10382  }
10383  if (op == "remove")
10384  {
10385  return patch_operations::remove;
10386  }
10387  if (op == "replace")
10388  {
10389  return patch_operations::replace;
10390  }
10391  if (op == "move")
10392  {
10393  return patch_operations::move;
10394  }
10395  if (op == "copy")
10396  {
10397  return patch_operations::copy;
10398  }
10399  if (op == "test")
10400  {
10401  return patch_operations::test;
10402  }
10403 
10404  return patch_operations::invalid;
10405  };
10406 
10407  // wrapper for "add" operation; add value at ptr
10408  const auto operation_add = [&result](json_pointer & ptr, basic_json val)
10409  {
10410  // adding to the root of the target document means replacing it
10411  if (ptr.is_root())
10412  {
10413  result = val;
10414  }
10415  else
10416  {
10417  // make sure the top element of the pointer exists
10418  json_pointer top_pointer = ptr.top();
10419  if (top_pointer != ptr)
10420  {
10421  result.at(top_pointer);
10422  }
10423 
10424  // get reference to parent of JSON pointer ptr
10425  const auto last_path = ptr.pop_back();
10426  basic_json& parent = result[ptr];
10427 
10428  switch (parent.m_type)
10429  {
10430  case value_t::null:
10431  case value_t::object:
10432  {
10433  // use operator[] to add value
10434  parent[last_path] = val;
10435  break;
10436  }
10437 
10438  case value_t::array:
10439  {
10440  if (last_path == "-")
10441  {
10442  // special case: append to back
10443  parent.push_back(val);
10444  }
10445  else
10446  {
10447  const auto idx = std::stoi(last_path);
10448  if (static_cast<size_type>(idx) > parent.size())
10449  {
10450  // avoid undefined behavior
10451  throw std::out_of_range("array index " + std::to_string(idx) + " is out of range");
10452  }
10453  else
10454  {
10455  // default case: insert add offset
10456  parent.insert(parent.begin() + static_cast<difference_type>(idx), val);
10457  }
10458  }
10459  break;
10460  }
10461 
10462  default:
10463  {
10464  // if there exists a parent it cannot be primitive
10465  assert(false); // LCOV_EXCL_LINE
10466  }
10467  }
10468  }
10469  };
10470 
10471  // wrapper for "remove" operation; remove value at ptr
10472  const auto operation_remove = [&result](json_pointer & ptr)
10473  {
10474  // get reference to parent of JSON pointer ptr
10475  const auto last_path = ptr.pop_back();
10476  basic_json& parent = result.at(ptr);
10477 
10478  // remove child
10479  if (parent.is_object())
10480  {
10481  // perform range check
10482  auto it = parent.find(last_path);
10483  if (it != parent.end())
10484  {
10485  parent.erase(it);
10486  }
10487  else
10488  {
10489  throw std::out_of_range("key '" + last_path + "' not found");
10490  }
10491  }
10492  else if (parent.is_array())
10493  {
10494  // note erase performs range check
10495  parent.erase(static_cast<size_type>(std::stoi(last_path)));
10496  }
10497  };
10498 
10499  // type check
10500  if (not json_patch.is_array())
10501  {
10502  // a JSON patch must be an array of objects
10503  throw std::invalid_argument("JSON patch must be an array of objects");
10504  }
10505 
10506  // iterate and apply th eoperations
10507  for (const auto& val : json_patch)
10508  {
10509  // wrapper to get a value for an operation
10510  const auto get_value = [&val](const std::string & op,
10511  const std::string & member,
10512  bool string_type) -> basic_json&
10513  {
10514  // find value
10515  auto it = val.m_value.object->find(member);
10516 
10517  // context-sensitive error message
10518  const auto error_msg = (op == "op") ? "operation" : "operation '" + op + "'";
10519 
10520  // check if desired value is present
10521  if (it == val.m_value.object->end())
10522  {
10523  throw std::invalid_argument(error_msg + " must have member '" + member + "'");
10524  }
10525 
10526  // check if result is of type string
10527  if (string_type and not it->second.is_string())
10528  {
10529  throw std::invalid_argument(error_msg + " must have string member '" + member + "'");
10530  }
10531 
10532  // no error: return value
10533  return it->second;
10534  };
10535 
10536  // type check
10537  if (not val.is_object())
10538  {
10539  throw std::invalid_argument("JSON patch must be an array of objects");
10540  }
10541 
10542  // collect mandatory members
10543  const std::string op = get_value("op", "op", true);
10544  const std::string path = get_value(op, "path", true);
10545  json_pointer ptr(path);
10546 
10547  switch (get_op(op))
10548  {
10549  case patch_operations::add:
10550  {
10551  operation_add(ptr, get_value("add", "value", false));
10552  break;
10553  }
10554 
10555  case patch_operations::remove:
10556  {
10557  operation_remove(ptr);
10558  break;
10559  }
10560 
10561  case patch_operations::replace:
10562  {
10563  // the "path" location must exist - use at()
10564  result.at(ptr) = get_value("replace", "value", false);
10565  break;
10566  }
10567 
10568  case patch_operations::move:
10569  {
10570  const std::string from_path = get_value("move", "from", true);
10571  json_pointer from_ptr(from_path);
10572 
10573  // the "from" location must exist - use at()
10574  basic_json v = result.at(from_ptr);
10575 
10576  // The move operation is functionally identical to a
10577  // "remove" operation on the "from" location, followed
10578  // immediately by an "add" operation at the target
10579  // location with the value that was just removed.
10580  operation_remove(from_ptr);
10581  operation_add(ptr, v);
10582  break;
10583  }
10584 
10585  case patch_operations::copy:
10586  {
10587  const std::string from_path = get_value("copy", "from", true);;
10588  const json_pointer from_ptr(from_path);
10589 
10590  // the "from" location must exist - use at()
10591  result[ptr] = result.at(from_ptr);
10592  break;
10593  }
10594 
10595  case patch_operations::test:
10596  {
10597  bool success = false;
10598  try
10599  {
10600  // check if "value" matches the one at "path"
10601  // the "path" location must exist - use at()
10602  success = (result.at(ptr) == get_value("test", "value", false));
10603  }
10604  catch (std::out_of_range&)
10605  {
10606  // ignore out of range errors: success remains false
10607  }
10608 
10609  // throw an exception if test fails
10610  if (not success)
10611  {
10612  throw std::domain_error("unsuccessful: " + val.dump());
10613  }
10614 
10615  break;
10616  }
10617 
10618  case patch_operations::invalid:
10619  {
10620  // op must be "add", "remove", "replace", "move", "copy", or
10621  // "test"
10622  throw std::invalid_argument("operation value '" + op + "' is invalid");
10623  }
10624  }
10625  }
10626 
10627  return result;
10628  }
10629 
10662  static basic_json diff(const basic_json& source,
10663  const basic_json& target,
10664  const std::string& path = "")
10665  {
10666  // the patch
10667  basic_json result(value_t::array);
10668 
10669  // if the values are the same, return empty patch
10670  if (source == target)
10671  {
10672  return result;
10673  }
10674 
10675  if (source.type() != target.type())
10676  {
10677  // different types: replace value
10678  result.push_back(
10679  {
10680  {"op", "replace"},
10681  {"path", path},
10682  {"value", target}
10683  });
10684  }
10685  else
10686  {
10687  switch (source.type())
10688  {
10689  case value_t::array:
10690  {
10691  // first pass: traverse common elements
10692  size_t i = 0;
10693  while (i < source.size() and i < target.size())
10694  {
10695  // recursive call to compare array values at index i
10696  auto temp_diff = diff(source[i], target[i], path + "/" + std::to_string(i));
10697  result.insert(result.end(), temp_diff.begin(), temp_diff.end());
10698  ++i;
10699  }
10700 
10701  // i now reached the end of at least one array
10702  // in a second pass, traverse the remaining elements
10703 
10704  // remove my remaining elements
10705  const auto end_index = static_cast<difference_type>(result.size());
10706  while (i < source.size())
10707  {
10708  // add operations in reverse order to avoid invalid
10709  // indices
10710  result.insert(result.begin() + end_index, object(
10711  {
10712  {"op", "remove"},
10713  {"path", path + "/" + std::to_string(i)}
10714  }));
10715  ++i;
10716  }
10717 
10718  // add other remaining elements
10719  while (i < target.size())
10720  {
10721  result.push_back(
10722  {
10723  {"op", "add"},
10724  {"path", path + "/" + std::to_string(i)},
10725  {"value", target[i]}
10726  });
10727  ++i;
10728  }
10729 
10730  break;
10731  }
10732 
10733  case value_t::object:
10734  {
10735  // first pass: traverse this object's elements
10736  for (auto it = source.begin(); it != source.end(); ++it)
10737  {
10738  // escape the key name to be used in a JSON patch
10739  const auto key = json_pointer::escape(it.key());
10740 
10741  if (target.find(it.key()) != target.end())
10742  {
10743  // recursive call to compare object values at key it
10744  auto temp_diff = diff(it.value(), target[it.key()], path + "/" + key);
10745  result.insert(result.end(), temp_diff.begin(), temp_diff.end());
10746  }
10747  else
10748  {
10749  // found a key that is not in o -> remove it
10750  result.push_back(object(
10751  {
10752  {"op", "remove"},
10753  {"path", path + "/" + key}
10754  }));
10755  }
10756  }
10757 
10758  // second pass: traverse other object's elements
10759  for (auto it = target.begin(); it != target.end(); ++it)
10760  {
10761  if (source.find(it.key()) == source.end())
10762  {
10763  // found a key that is not in this -> add it
10764  const auto key = json_pointer::escape(it.key());
10765  result.push_back(
10766  {
10767  {"op", "add"},
10768  {"path", path + "/" + key},
10769  {"value", it.value()}
10770  });
10771  }
10772  }
10773 
10774  break;
10775  }
10776 
10777  default:
10778  {
10779  // both primitive type: replace value
10780  result.push_back(
10781  {
10782  {"op", "replace"},
10783  {"path", path},
10784  {"value", target}
10785  });
10786  break;
10787  }
10788  }
10789  }
10790 
10791  return result;
10792  }
10793 
10795 };
10796 
10797 
10799 // presets //
10801 
10810 using json = basic_json<>;
10811 }
10812 
10813 
10815 // nonmember support //
10817 
10818 // specialization of std::swap, and std::hash
10819 namespace std
10820 {
10826 template<>
10827 inline void swap(nlohmann::json& j1,
10828  nlohmann::json& j2) noexcept(
10829  is_nothrow_move_constructible<nlohmann::json>::value and
10830  is_nothrow_move_assignable<nlohmann::json>::value
10831  )
10832 {
10833  j1.swap(j2);
10834 }
10835 
10837 template<>
10838 struct hash<nlohmann::json>
10839 {
10845  std::size_t operator()(const nlohmann::json& j) const
10846  {
10847  // a naive hashing via the string representation
10848  const auto& h = hash<nlohmann::json::string_t>();
10849  return h(j.dump());
10850  }
10851 };
10852 }
10853 
10867 inline nlohmann::json operator "" _json(const char* s, std::size_t n)
10868 {
10869  return nlohmann::json::parse(s, s + n);
10870 }
10871 
10885 inline nlohmann::json::json_pointer operator "" _json_pointer(const char* s, std::size_t n)
10886 {
10887  return nlohmann::json::json_pointer(std::string(s, n));
10888 }
10889 
10890 // restore GCC/clang diagnostic settings
10891 #if defined(__clang__) || defined(__GNUC__) || defined(__GNUG__)
10892  #pragma GCC diagnostic pop
10893 #endif
10894 
10895 #endif
const_iterator(pointer object) noexcept
constructor for a given JSON instance
Definition: json.hpp:6816
size_type max_size() const noexcept
returns the maximum possible number of elements
Definition: json.hpp:4739
friend bool operator<=(const_reference lhs, const_reference rhs) noexcept
comparison: less than or equal
Definition: json.hpp:5812
constexpr value_t type() const noexcept
return the type of the JSON value (explicit)
Definition: json.hpp:2222
constexpr bool is_array() const noexcept
return whether value is an array
Definition: json.hpp:2482
const_reference at(const typename object_t::key_type &key) const
access specified object element with bounds checking
Definition: json.hpp:3267
basic_json(const value_t value_type)
create an empty value with a given type
Definition: json.hpp:1047
basic_json(const array_t &val)
create an array (explicit)
Definition: json.hpp:1159
reference value() const
return the value of an iterator
Definition: json.hpp:7638
const_iterator end() const noexcept
returns a const iterator to one past the last element
Definition: json.hpp:4361
constexpr bool is_primitive() const noexcept
return whether type is primitive
Definition: json.hpp:2252
constexpr bool is_null() const noexcept
return whether value is null
Definition: json.hpp:2301
ValueType get() const
get a value (explicit)
Definition: json.hpp:2880
const_reverse_iterator rend() const noexcept
returns a const reverse iterator to one before the first
Definition: json.hpp:4466
constexpr bool is_structured() const noexcept
return whether type is structured
Definition: json.hpp:2279
json_reverse_iterator & operator--()
pre-decrement (–it)
Definition: json.hpp:7589
void clear() noexcept
clears the contents
Definition: json.hpp:4798
const_reference operator[](size_type idx) const
access specified array element
Definition: json.hpp:3361
static basic_json parse(const CharPT s, const parser_callback_t cb=nullptr)
deserialize from string literal
Definition: json.hpp:6010
json_reverse_iterator operator--(int)
post-decrement (it–)
Definition: json.hpp:7583
reference operator[](T *(&key)[n])
access specified object element
Definition: json.hpp:3494
friend std::istream & operator>>(std::istream &i, basic_json &j)
deserialize from stream
Definition: json.hpp:6212
iterator & operator+=(difference_type i)
add to iterator
Definition: json.hpp:7485
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:1740
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:4240
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:6100
constexpr bool is_number_unsigned() const noexcept
return whether value is an unsigned integer number
Definition: json.hpp:2410
const_iterator operator-(difference_type i)
subtract from iterator
Definition: json.hpp:7291
BooleanType boolean_t
a type for a boolean
Definition: json.hpp:494
reference operator+=(const typename object_t::value_type &val)
add an object to an object
Definition: json.hpp:4981
basic_json(const typename string_t::value_type *val)
create a string (explicit)
Definition: json.hpp:1255
object_t::key_type key() const
return the key of an object iterator
Definition: json.hpp:7368
iterator find(typename object_t::key_type key)
find an element in a JSON object
Definition: json.hpp:4194
friend bool operator!=(const_reference lhs, const_reference rhs) noexcept
comparison: not equal
Definition: json.hpp:5656
basic_json(const string_t &val)
create a string (explicit)
Definition: json.hpp:1229
reference operator*() const
return a reference to the value pointed to by the iterator
Definition: json.hpp:7443
void push_back(const basic_json &val)
add an object to an array
Definition: json.hpp:4907
void erase(const size_type idx)
remove element from a JSON array given an index
Definition: json.hpp:4148
ArrayType< basic_json, AllocatorType< basic_json >> array_t
a type for an array
Definition: json.hpp:421
reference front()
access the first element
Definition: json.hpp:3807
void swap(object_t &other)
exchanges the values
Definition: json.hpp:5420
const_iterator & operator+=(difference_type i)
add to iterator
Definition: json.hpp:7240
a class to store JSON values
Definition: json.hpp:215
basic_json(const int val) noexcept
create an integer number from an enum type (explicit)
Definition: json.hpp:1369
static basic_json parse(T(&array)[N], const parser_callback_t cb=nullptr)
deserialize from an array
Definition: json.hpp:5972
constexpr bool is_object() const noexcept
return whether value is an object
Definition: json.hpp:2460
friend bool operator==(std::nullptr_t, const_reference v) noexcept
comparison: equal
Definition: json.hpp:5635
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:3704
NumberIntegerType number_integer_t
a type for a number (integer)
Definition: json.hpp:566
iterator insert(const_iterator pos, size_type cnt, const basic_json &val)
inserts elements
Definition: json.hpp:5208
const_iterator operator+(difference_type i)
add to iterator
Definition: json.hpp:7280
a mutable random access iterator for the basic_json class
Definition: json.hpp:7410
const_iterator operator++(int)
post-increment (it++)
Definition: json.hpp:7052
constexpr bool is_number_integer() const noexcept
return whether value is an integer number
Definition: json.hpp:2382
ObjectType< StringType, basic_json, std::less< StringType >, AllocatorType< std::pair< const StringType, basic_json >>> object_t
a type for an object
Definition: json.hpp:375
STL namespace.
NumberUnsignedType number_unsigned_t
a type for a number (unsigned)
Definition: json.hpp:637
json_reverse_iterator operator-(difference_type i) const
subtract from iterator
Definition: json.hpp:7611
typename std::allocator_traits< allocator_type >::const_pointer const_pointer
the type of an element const pointer
Definition: json.hpp:256
static basic_json parse(std::istream &&i, const parser_callback_t cb=nullptr)
deserialize from stream
Definition: json.hpp:6049
pointer operator->() const
dereference the iterator
Definition: json.hpp:7449
bool operator>=(const const_iterator &other) const
comparison: greater than or equal
Definition: json.hpp:7231
basic_json(const number_integer_t val) noexcept
create an integer number (explicit)
Definition: json.hpp:1338
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:1700
static iteration_proxy< const_iterator > iterator_wrapper(const_reference cont)
wrapper to access iterator member functions in range-based for
Definition: json.hpp:4553
const_reference front() const
access the first element
Definition: json.hpp:3815
void emplace_back(Args &&... args)
add an object to an array
Definition: json.hpp:5057
typename basic_json::value_type value_type
the type of the values when the iterator is dereferenced
Definition: json.hpp:6797
json_reverse_iterator(const typename base_iterator::iterator_type &it) noexcept
create reverse iterator from iterator
Definition: json.hpp:7560
PointerType get_ptr() noexcept
get a pointer value (implicit)
Definition: json.hpp:2960
const_iterator cbegin() const noexcept
returns a const iterator to the first element
Definition: json.hpp:4320
reference back()
access the last element
Definition: json.hpp:3850
const value_type & const_reference
the type of an element const reference
Definition: json.hpp:243
typename basic_json::const_pointer pointer
defines a pointer to the type iterated over (value_type)
Definition: json.hpp:6801
IteratorType erase(IteratorType first, IteratorType last)
remove elements given an iterator range
Definition: json.hpp:4023
void push_back(const typename object_t::value_type &val)
add an object to an object
Definition: json.hpp:4957
bool empty() const noexcept
checks whether the container is empty
Definition: json.hpp:4605
void push_back(std::initializer_list< basic_json > init)
add an object to an object
Definition: json.hpp:5012
json_pointer(const std::string &s="")
create JSON pointer
Definition: json.hpp:9581
iterator insert(const_iterator pos, const_iterator first, const_iterator last)
inserts elements
Definition: json.hpp:5260
constexpr const PointerType get_ptr() const noexcept
get a pointer value (implicit)
Definition: json.hpp:2988
constexpr bool is_number_float() const noexcept
return whether value is a floating-point number
Definition: json.hpp:2438
basic_json(InputIT first, InputIT last)
construct a JSON container given an iterator range
Definition: json.hpp:1811
basic_json(std::nullptr_t=nullptr) noexcept
create a null object
Definition: json.hpp:1071
IteratorType erase(IteratorType pos)
remove element given an iterator
Definition: json.hpp:3916
static allocator_type get_allocator()
returns the allocator associated with the container
Definition: json.hpp:273
json_reverse_iterator operator+(difference_type i) const
add to iterator
Definition: json.hpp:7603
string_t dump(const int indent=-1) const
serialization
Definition: json.hpp:2180
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:2075
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:5355
std::size_t size_type
a type to represent container sizes
Definition: json.hpp:248
JSON_DEPRECATED basic_json(std::istream &i, const parser_callback_t cb=nullptr)
construct a JSON value given an input stream
Definition: json.hpp:1929
const_iterator(const iterator &other) noexcept
copy constructor given a non-const iterator
Definition: json.hpp:6848
basic_json(const CompatibleArrayType &val)
create an array (implicit)
Definition: json.hpp:1199
basic_json(size_type cnt, const basic_json &val)
construct an array with count copies of given value
Definition: json.hpp:1764
std::reverse_iterator< Base > base_iterator
shortcut to the reverse iterator adaptor
Definition: json.hpp:7555
object_t::key_type key() const
return the key of an object iterator
Definition: json.hpp:7631
iterator insert(const_iterator pos, std::initializer_list< basic_json > ilist)
inserts elements
Definition: json.hpp:5318
typename std::allocator_traits< allocator_type >::pointer pointer
the type of an element pointer
Definition: json.hpp:254
iterator insert(const_iterator pos, const basic_json &val)
inserts element
Definition: json.hpp:5153
friend bool operator>=(const_reference lhs, const_reference rhs) noexcept
comparison: greater than or equal
Definition: json.hpp:5856
friend bool operator<(const_reference lhs, const_reference rhs) noexcept
comparison: less than
Definition: json.hpp:5717
iterator & operator++()
pre-increment (++it)
Definition: json.hpp:7463
iterator operator++(int)
post-increment (it++)
Definition: json.hpp:7455
const_reverse_iterator rbegin() const noexcept
returns a const reverse iterator to the last element
Definition: json.hpp:4429
basic_json(basic_json &&other) noexcept
move constructor
Definition: json.hpp:2038
const_iterator operator--(int)
post-decrement (it–)
Definition: json.hpp:7095
reference at(const typename object_t::key_type &key)
access specified object element with bounds checking
Definition: json.hpp:3220
object (unordered set of name/value pairs)
~basic_json()
destructor
Definition: json.hpp:2108
iterator operator--(int)
post-decrement (it–)
Definition: json.hpp:7470
iterator operator-(difference_type i)
subtract from iterator
Definition: json.hpp:7507
const_iterator & operator--()
pre-decrement (–it)
Definition: json.hpp:7106
basic_json value_type
the type of elements in a basic_json container
Definition: json.hpp:238
std::function< bool(int depth, parse_event_t event, basic_json &parsed)> parser_callback_t
per-element parser callback type
Definition: json.hpp:996
AllocatorType< basic_json > allocator_type
the allocator type
Definition: json.hpp:251
StringType string_t
a type for a string
Definition: json.hpp:468
reference operator+=(const basic_json &val)
add an object to an array
Definition: json.hpp:4931
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:6890
static basic_json parse(const ContiguousContainer &c, const parser_callback_t cb=nullptr)
deserialize from a container with contiguous storage
Definition: json.hpp:6172
reference operator+=(std::initializer_list< basic_json > init)
add an object to an object
Definition: json.hpp:5029
value_type & reference
the type of an element reference
Definition: json.hpp:241
pointer operator->() const
dereference the iterator
Definition: json.hpp:7016
ReferenceType get_ref() const
get a reference value (implicit)
Definition: json.hpp:3050
reference value() const
return the value of an iterator
Definition: json.hpp:7527
friend std::ostream & operator>>(const basic_json &j, std::ostream &o)
serialize to stream
Definition: json.hpp:5929
size_type size() const noexcept
returns the number of elements
Definition: json.hpp:4673
iterator(const iterator &other) noexcept
copy constructor
Definition: json.hpp:7426
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:6799
constexpr bool is_string() const noexcept
return whether value is a string
Definition: json.hpp:2504
void swap(string_t &other)
exchanges the values
Definition: json.hpp:5453
reference operator[](difference_type n) const
access to successor
Definition: json.hpp:7625
basic_json(const CompatibleNumberIntegerType val) noexcept
create an integer number (implicit)
Definition: json.hpp:1406
const_reference at(size_type idx) const
access specified array element with bounds checking
Definition: json.hpp:3173
reference value() const
return the value of an iterator
Definition: json.hpp:7386
ValueType value(const typename object_t::key_type &key, ValueType default_value) const
access specified object element with default value
Definition: json.hpp:3678
const_reference operator[](T *key) const
read-only access specified object element
Definition: json.hpp:3614
NumberFloatType number_float_t
a type for a number (floating-point)
Definition: json.hpp:705
value_t
the JSON type enumeration
Definition: json.hpp:736
reverse_iterator rbegin() noexcept
returns an iterator to the reverse-beginning
Definition: json.hpp:4421
std::ptrdiff_t difference_type
a type to represent differences between iterators
Definition: json.hpp:246
difference_type operator-(const const_iterator &other) const
return difference
Definition: json.hpp:7302
void swap(array_t &other)
exchanges the values
Definition: json.hpp:5387
std::pair< iterator, bool > emplace(Args &&... args)
add an object to an object if key does not exist
Definition: json.hpp:5105
reference operator[](difference_type n) const
access to successor
Definition: json.hpp:7521
typename Base::reference reference
the reference type for the pointed-to element
Definition: json.hpp:7557
void push_back(basic_json &&val)
add an object to an array
Definition: json.hpp:4871
array (ordered collection of values)
json_reverse_iterator & operator++()
pre-increment (++it)
Definition: json.hpp:7576
difference_type operator-(const iterator &other) const
return difference
Definition: json.hpp:7515
friend bool operator==(const_reference lhs, const_reference rhs) noexcept
comparison: equal
Definition: json.hpp:5533
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:7431
static basic_json parse(std::istream &i, const parser_callback_t cb=nullptr)
deserialize from stream
Definition: json.hpp:6040
ValueType value(const json_pointer &ptr, ValueType default_value) const
access specified object element via JSON Pointer with default value
Definition: json.hpp:3752
const_reference operator[](const typename object_t::key_type &key) const
read-only access specified object element
Definition: json.hpp:3452
bool operator!=(const const_iterator &other) const
comparison: not equal
Definition: json.hpp:7171
basic_json(const CompatibleNumberUnsignedType val) noexcept
create an unsigned number (implicit)
Definition: json.hpp:1464
constexpr bool is_boolean() const noexcept
return whether value is a boolean
Definition: json.hpp:2323
bool operator==(const const_iterator &other) const
comparison: equal
Definition: json.hpp:7138
bool operator<=(const const_iterator &other) const
comparison: less than or equal
Definition: json.hpp:7213
const_reverse_iterator crbegin() const noexcept
returns a const reverse iterator to the last element
Definition: json.hpp:4495
string_t value(const json_pointer &ptr, const char *default_value) const
overload for a default value of type const char*
Definition: json.hpp:3777
friend class basic_json
allow basic_json to access private members
Definition: json.hpp:6793
reference operator[](difference_type n) const
access to successor
Definition: json.hpp:7329
friend bool operator<(const value_t lhs, const value_t rhs) noexcept
comparison operator for JSON types
Definition: json.hpp:5486
basic_json(const number_float_t val) noexcept
create a floating-point number (explicit)
Definition: json.hpp:1495
friend bool operator!=(const_reference v, std::nullptr_t) noexcept
comparison: not equal
Definition: json.hpp:5679
iterator operator+(difference_type i)
add to iterator
Definition: json.hpp:7499
basic_json(const CompatibleNumberFloatType val) noexcept
create an floating-point number (implicit)
Definition: json.hpp:1542
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:1617
iterator(pointer object) noexcept
constructor for a given JSON instance
Definition: json.hpp:7421
friend bool operator!=(std::nullptr_t, const_reference v) noexcept
comparison: not equal
Definition: json.hpp:5688
difference_type operator-(const json_reverse_iterator &other) const
return difference
Definition: json.hpp:7619
const_reference back() const
access the last element
Definition: json.hpp:3860
const_iterator & operator++()
pre-increment (++it)
Definition: json.hpp:7063
constexpr bool is_number() const noexcept
return whether value is a number
Definition: json.hpp:2353
const_iterator find(typename object_t::key_type key) const
find an element in a JSON object
Definition: json.hpp:4210
const_iterator begin() const noexcept
returns a const iterator to the first element
Definition: json.hpp:4290
bool operator>(const const_iterator &other) const
comparison: greater than
Definition: json.hpp:7222
std::bidirectional_iterator_tag iterator_category
the category of the iterator
Definition: json.hpp:6805
basic_json(boolean_t val) noexcept
create a boolean (explicit)
Definition: json.hpp:1306
iterator end() noexcept
returns an iterator to one past the last element
Definition: json.hpp:4351
reverse_iterator rend() noexcept
returns an iterator to the reverse-end
Definition: json.hpp:4458
iterator begin() noexcept
returns an iterator to the first element
Definition: json.hpp:4280
const_iterator cend() const noexcept
returns a const iterator to one past the last element
Definition: json.hpp:4391
basic_json(const CompatibleObjectType &val)
create an object (implicit)
Definition: json.hpp:1131
friend bool operator>(const_reference lhs, const_reference rhs) noexcept
comparison: greater than
Definition: json.hpp:5834
size_type erase(const typename object_t::key_type &key)
remove element from a JSON object given a key
Definition: json.hpp:4111
reference operator[](const typename object_t::key_type &key)
access specified object element
Definition: json.hpp:3401
reference operator+=(basic_json &&val)
add an object to an array
Definition: json.hpp:4897
a const random access iterator for the basic_json class
Definition: json.hpp:6790
a template for a reverse iterator class
Definition: json.hpp:225
typename basic_json::const_reference reference
defines a reference to the type iterated over (value_type)
Definition: json.hpp:6803
json_reverse_iterator operator++(int)
post-increment (it++)
Definition: json.hpp:7570
friend bool operator==(const_reference v, std::nullptr_t) noexcept
comparison: equal
Definition: json.hpp:5626
reference operator[](size_type idx)
access specified array element
Definition: json.hpp:3313
json_reverse_iterator & operator+=(difference_type i)
add to iterator
Definition: json.hpp:7596
reference at(size_type idx)
access specified array element with bounds checking
Definition: json.hpp:3130
static iteration_proxy< iterator > iterator_wrapper(reference cont)
wrapper to access iterator member functions in range-based for
Definition: json.hpp:4545
constexpr bool is_discarded() const noexcept
return whether value is discarded
Definition: json.hpp:2531
const_reverse_iterator crend() const noexcept
returns a const reverse iterator to one before the first
Definition: json.hpp:4524
iterator & operator-=(difference_type i)
subtract from iterator
Definition: json.hpp:7492
basic_json(const object_t &val)
create an object (explicit)
Definition: json.hpp:1096
basic_json(const number_unsigned_t val) noexcept
create an unsigned integer number (explicit)
Definition: json.hpp:1433
friend std::istream & operator<<(basic_json &j, std::istream &i)
deserialize from stream
Definition: json.hpp:6202
json_reverse_iterator(const base_iterator &it) noexcept
create reverse iterator from base class
Definition: json.hpp:7565
const_reference operator[](T *(&key)[n]) const
read-only access specified object element
Definition: json.hpp:3529
friend std::ostream & operator<<(std::ostream &o, const basic_json &j)
serialize to stream
Definition: json.hpp:5897
const_iterator(const const_iterator &other) noexcept
copy constructor
Definition: json.hpp:6881
iterator & operator--()
pre-decrement (–it)
Definition: json.hpp:7478
reference operator*() const
return a reference to the value pointed to by the iterator
Definition: json.hpp:6975
iterator insert(const_iterator pos, basic_json &&val)
inserts element
Definition: json.hpp:5179
ReferenceType get_ref()
get a reference value (implicit)
Definition: json.hpp:3037
const_iterator & operator-=(difference_type i)
subtract from iterator
Definition: json.hpp:7271
basic_json(const CompatibleStringType &val)
create a string (implicit)
Definition: json.hpp:1286
basic_json(const basic_json &other)
copy constructor
Definition: json.hpp:1961
bool operator<(const const_iterator &other) const
comparison: smaller
Definition: json.hpp:7180
reference operator[](T *key)
access specified object element
Definition: json.hpp:3562
parse_event_t
JSON callback events.
Definition: json.hpp:926