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