json.hpp
Go to the documentation of this file.
1 /*
2  __ _____ _____ _____
3  __| | __| | | | JSON for Modern C++
4 | | |__ | | | | | | version 2.0.8
5 |_____|_____|_____|_|___| https://github.com/nlohmann/json
6 
7 Licensed under the MIT License <http://opensource.org/licenses/MIT>.
8 Copyright (c) 2013-2016 Niels Lohmann <http://nlohmann.me>.
9 
10 Permission is hereby granted, free of charge, to any person obtaining a copy
11 of this software and associated documentation files (the "Software"), to deal
12 in the Software without restriction, including without limitation the rights
13 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
14 copies of the Software, and to permit persons to whom the Software is
15 furnished to do so, subject to the following conditions:
16 
17 The above copyright notice and this permission notice shall be included in all
18 copies or substantial portions of the Software.
19 
20 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
23 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
25 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
26 SOFTWARE.
27 */
28 
29 #ifndef NLOHMANN_JSON_HPP
30 #define NLOHMANN_JSON_HPP
31 
32 #include <algorithm> // all_of, for_each, transform
33 #include <array> // array
34 #include <cassert> // assert
35 #include <cctype> // isdigit
36 #include <ciso646> // and, not, or
37 #include <cmath> // isfinite, ldexp, signbit
38 #include <cstddef> // nullptr_t, ptrdiff_t, size_t
39 #include <cstdint> // int64_t, uint64_t
40 #include <cstdlib> // strtod, strtof, strtold, strtoul
41 #include <cstring> // strlen
42 #include <functional> // function, hash, less
43 #include <initializer_list> // initializer_list
44 #include <iomanip> // setw
45 #include <iostream> // istream, ostream
46 #include <iterator> // advance, begin, bidirectional_iterator_tag, distance, end, inserter, iterator, iterator_traits, next, random_access_iterator_tag, reverse_iterator
47 #include <limits> // numeric_limits
48 #include <locale> // locale
49 #include <map> // map
50 #include <memory> // addressof, allocator, allocator_traits, unique_ptr
51 #include <numeric> // accumulate
52 #include <sstream> // stringstream
53 #include <stdexcept> // domain_error, invalid_argument, out_of_range
54 #include <string> // getline, stoi, string, to_string
55 #include <type_traits> // add_pointer, enable_if, is_arithmetic, is_base_of, is_const, is_constructible, is_convertible, is_floating_point, is_integral, is_nothrow_move_assignable, std::is_nothrow_move_constructible, std::is_pointer, std::is_reference, std::is_same, remove_const, remove_pointer, remove_reference
56 #include <utility> // declval, forward, make_pair, move, pair, swap
57 #include <vector> // vector
58 
59 // exclude unsupported compilers
60 #if defined(__clang__)
61  #define CLANG_VERSION (__clang_major__ * 10000 + __clang_minor__ * 100 + __clang_patchlevel__)
62  #if CLANG_VERSION < 30400
63  #error "unsupported Clang version - see https://github.com/nlohmann/json#supported-compilers"
64  #endif
65 #elif defined(__GNUC__)
66  #define GCC_VERSION (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__)
67  #if GCC_VERSION < 40900
68  #error "unsupported GCC version - see https://github.com/nlohmann/json#supported-compilers"
69  #endif
70 #endif
71 
72 // disable float-equal warnings on GCC/clang
73 #if defined(__clang__) || defined(__GNUC__) || defined(__GNUG__)
74  #pragma GCC diagnostic push
75  #pragma GCC diagnostic ignored "-Wfloat-equal"
76 #endif
77 
78 // disable documentation warnings on clang
79 #if defined(__clang__)
80  #pragma GCC diagnostic push
81  #pragma GCC diagnostic ignored "-Wdocumentation"
82 #endif
83 
84 // allow for portable deprecation warnings
85 #if defined(__clang__) || defined(__GNUC__) || defined(__GNUG__)
86  #define JSON_DEPRECATED __attribute__((deprecated))
87 #elif defined(_MSC_VER)
88  #define JSON_DEPRECATED __declspec(deprecated)
89 #else
90  #define JSON_DEPRECATED
91 #endif
92 
98 namespace nlohmann
99 {
100 
101 
106 namespace
107 {
118 template<typename T>
119 struct has_mapped_type
120 {
121  private:
122  template <typename U, typename = typename U::mapped_type>
123  static int detect(U&&);
124 
125  static void detect(...);
126  public:
127  static constexpr bool value =
128  std::is_integral<decltype(detect(std::declval<T>()))>::value;
129 };
130 
131 }
132 
211 template <
212  template<typename U, typename V, typename... Args> class ObjectType = std::map,
213  template<typename U, typename... Args> class ArrayType = std::vector,
214  class StringType = std::string,
215  class BooleanType = bool,
216  class NumberIntegerType = std::int64_t,
217  class NumberUnsignedType = std::uint64_t,
218  class NumberFloatType = double,
219  template<typename U> class AllocatorType = std::allocator
220  >
222 {
223  private:
225  using basic_json_t = basic_json<ObjectType, ArrayType, StringType,
226  BooleanType, NumberIntegerType, NumberUnsignedType, NumberFloatType,
227  AllocatorType>;
228 
229  public:
230  // forward declarations
231  template<typename U> class iter_impl;
232  template<typename Base> class json_reverse_iterator;
233  class json_pointer;
234 
236  // container types //
238 
243 
246 
250  using const_reference = const value_type&;
251 
253  using difference_type = std::ptrdiff_t;
255  using size_type = std::size_t;
256 
258  using allocator_type = AllocatorType<basic_json>;
259 
263  using const_pointer = typename std::allocator_traits<allocator_type>::const_pointer;
264 
273 
275 
276 
281  {
282  return allocator_type();
283  }
284 
285 
287  // JSON value data types //
289 
294 
378  using object_t = ObjectType<StringType,
379  basic_json,
380  std::less<StringType>,
381  AllocatorType<std::pair<const StringType,
382  basic_json>>>;
383 
428  using array_t = ArrayType<basic_json, AllocatorType<basic_json>>;
429 
475  using string_t = StringType;
476 
501  using boolean_t = BooleanType;
502 
573  using number_integer_t = NumberIntegerType;
574 
644  using number_unsigned_t = NumberUnsignedType;
645 
712  using number_float_t = NumberFloatType;
713 
715 
716 
718  // JSON type enumeration //
720 
743  enum class value_t : uint8_t
744  {
745  null,
746  object,
747  array,
748  string,
749  boolean,
750  number_integer,
751  number_unsigned,
752  number_float,
753  discarded
754  };
755 
756 
757  private:
758 
760  template<typename T, typename... Args>
761  static T* create(Args&& ... args)
762  {
763  AllocatorType<T> alloc;
764  auto deleter = [&](T * object)
765  {
766  alloc.deallocate(object, 1);
767  };
768  std::unique_ptr<T, decltype(deleter)> object(alloc.allocate(1), deleter);
769  alloc.construct(object.get(), std::forward<Args>(args)...);
770  assert(object.get() != nullptr);
771  return object.release();
772  }
773 
775  // JSON value storage //
777 
803  {
818 
820  json_value() = default;
822  json_value(boolean_t v) noexcept : boolean(v) {}
824  json_value(number_integer_t v) noexcept : number_integer(v) {}
826  json_value(number_unsigned_t v) noexcept : number_unsigned(v) {}
828  json_value(number_float_t v) noexcept : number_float(v) {}
831  {
832  switch (t)
833  {
834  case value_t::object:
835  {
836  object = create<object_t>();
837  break;
838  }
839 
840  case value_t::array:
841  {
842  array = create<array_t>();
843  break;
844  }
845 
846  case value_t::string:
847  {
848  string = create<string_t>("");
849  break;
850  }
851 
852  case value_t::boolean:
853  {
854  boolean = boolean_t(false);
855  break;
856  }
857 
858  case value_t::number_integer:
859  {
860  number_integer = number_integer_t(0);
861  break;
862  }
863 
864  case value_t::number_unsigned:
865  {
866  number_unsigned = number_unsigned_t(0);
867  break;
868  }
869 
870  case value_t::number_float:
871  {
872  number_float = number_float_t(0.0);
873  break;
874  }
875 
876  default:
877  {
878  break;
879  }
880  }
881  }
882 
885  {
886  string = create<string_t>(value);
887  }
888 
891  {
892  object = create<object_t>(value);
893  }
894 
897  {
898  array = create<array_t>(value);
899  }
900  };
901 
911  void assert_invariant() const
912  {
913  assert(m_type != value_t::object or m_value.object != nullptr);
914  assert(m_type != value_t::array or m_value.array != nullptr);
915  assert(m_type != value_t::string or m_value.string != nullptr);
916  }
917 
918  public:
920  // JSON parser callback //
922 
933  enum class parse_event_t : uint8_t
934  {
936  object_start,
938  object_end,
940  array_start,
942  array_end,
944  key,
946  value
947  };
948 
1001  using parser_callback_t = std::function<bool(int depth,
1003  basic_json& parsed)>;
1004 
1005 
1007  // constructors //
1009 
1014 
1055  : m_type(value_type), m_value(value_type)
1056  {
1057  assert_invariant();
1058  }
1059 
1078  basic_json(std::nullptr_t = nullptr) noexcept
1079  : basic_json(value_t::null)
1080  {
1081  assert_invariant();
1082  }
1083 
1104  : m_type(value_t::object), m_value(val)
1105  {
1106  assert_invariant();
1107  }
1108 
1135  template<class CompatibleObjectType, typename std::enable_if<
1138  basic_json(const CompatibleObjectType& val)
1139  : m_type(value_t::object)
1140  {
1141  using std::begin;
1142  using std::end;
1143  m_value.object = create<object_t>(begin(val), end(val));
1144  assert_invariant();
1145  }
1146 
1167  : m_type(value_t::array), m_value(val)
1168  {
1169  assert_invariant();
1170  }
1171 
1198  template<class CompatibleArrayType, typename std::enable_if<
1206  basic_json(const CompatibleArrayType& val)
1207  : m_type(value_t::array)
1208  {
1209  using std::begin;
1210  using std::end;
1211  m_value.array = create<array_t>(begin(val), end(val));
1212  assert_invariant();
1213  }
1214 
1237  : m_type(value_t::string), m_value(val)
1238  {
1239  assert_invariant();
1240  }
1241 
1262  basic_json(const typename string_t::value_type* val)
1263  : basic_json(string_t(val))
1264  {
1265  assert_invariant();
1266  }
1267 
1291  template<class CompatibleStringType, typename std::enable_if<
1293  basic_json(const CompatibleStringType& val)
1294  : basic_json(string_t(val))
1295  {
1296  assert_invariant();
1297  }
1298 
1314  : m_type(value_t::boolean), m_value(val)
1315  {
1316  assert_invariant();
1317  }
1318 
1342  template<typename T, typename std::enable_if<
1343  not (std::is_same<T, int>::value) and
1346  : m_type(value_t::number_integer), m_value(val)
1347  {
1348  assert_invariant();
1349  }
1350 
1376  basic_json(const int val) noexcept
1377  : m_type(value_t::number_integer),
1378  m_value(static_cast<number_integer_t>(val))
1379  {
1380  assert_invariant();
1381  }
1382 
1408  template<typename CompatibleNumberIntegerType, typename std::enable_if<
1411  std::numeric_limits<CompatibleNumberIntegerType>::is_signed,
1412  CompatibleNumberIntegerType>::type = 0>
1413  basic_json(const CompatibleNumberIntegerType val) noexcept
1414  : m_type(value_t::number_integer),
1415  m_value(static_cast<number_integer_t>(val))
1416  {
1417  assert_invariant();
1418  }
1419 
1437  template<typename T, typename std::enable_if<
1438  not (std::is_same<T, int>::value) and
1441  : m_type(value_t::number_unsigned), m_value(val)
1442  {
1443  assert_invariant();
1444  }
1445 
1466  template<typename CompatibleNumberUnsignedType, typename std::enable_if <
1469  not std::numeric_limits<CompatibleNumberUnsignedType>::is_signed,
1470  CompatibleNumberUnsignedType>::type = 0>
1471  basic_json(const CompatibleNumberUnsignedType val) noexcept
1472  : m_type(value_t::number_unsigned),
1473  m_value(static_cast<number_unsigned_t>(val))
1474  {
1475  assert_invariant();
1476  }
1477 
1503  : m_type(value_t::number_float), m_value(val)
1504  {
1505  // replace infinity and NAN by null
1506  if (not std::isfinite(val))
1507  {
1508  m_type = value_t::null;
1509  m_value = json_value();
1510  }
1511 
1512  assert_invariant();
1513  }
1514 
1546  template<typename CompatibleNumberFloatType, typename = typename std::enable_if<
1549  basic_json(const CompatibleNumberFloatType val) noexcept
1551  {
1552  assert_invariant();
1553  }
1554 
1624  basic_json(std::initializer_list<basic_json> init,
1625  bool type_deduction = true,
1626  value_t manual_type = value_t::array)
1627  {
1628  // check if each element is an array with two elements whose first
1629  // element is a string
1630  bool is_an_object = std::all_of(init.begin(), init.end(),
1631  [](const basic_json & element)
1632  {
1633  return element.is_array() and element.size() == 2 and element[0].is_string();
1634  });
1635 
1636  // adjust type if type deduction is not wanted
1637  if (not type_deduction)
1638  {
1639  // if array is wanted, do not create an object though possible
1640  if (manual_type == value_t::array)
1641  {
1642  is_an_object = false;
1643  }
1644 
1645  // if object is wanted but impossible, throw an exception
1646  if (manual_type == value_t::object and not is_an_object)
1647  {
1648  throw std::domain_error("cannot create object from initializer list");
1649  }
1650  }
1651 
1652  if (is_an_object)
1653  {
1654  // the initializer list is a list of pairs -> create object
1655  m_type = value_t::object;
1656  m_value = value_t::object;
1657 
1658  std::for_each(init.begin(), init.end(), [this](const basic_json & element)
1659  {
1660  m_value.object->emplace(*(element[0].m_value.string), element[1]);
1661  });
1662  }
1663  else
1664  {
1665  // the initializer list describes an array -> create array
1666  m_type = value_t::array;
1667  m_value.array = create<array_t>(init);
1668  }
1669 
1670  assert_invariant();
1671  }
1672 
1707  static basic_json array(std::initializer_list<basic_json> init =
1708  std::initializer_list<basic_json>())
1709  {
1710  return basic_json(init, false, value_t::array);
1711  }
1712 
1747  static basic_json object(std::initializer_list<basic_json> init =
1748  std::initializer_list<basic_json>())
1749  {
1750  return basic_json(init, false, value_t::object);
1751  }
1752 
1772  : m_type(value_t::array)
1773  {
1774  m_value.array = create<array_t>(cnt, val);
1775  assert_invariant();
1776  }
1777 
1815  template<class InputIT, typename std::enable_if<
1818  basic_json(InputIT first, InputIT last)
1819  {
1820  assert(first.m_object != nullptr);
1821  assert(last.m_object != nullptr);
1822 
1823  // make sure iterator fits the current value
1824  if (first.m_object != last.m_object)
1825  {
1826  throw std::domain_error("iterators are not compatible");
1827  }
1828 
1829  // copy type from first iterator
1830  m_type = first.m_object->m_type;
1831 
1832  // check if iterator range is complete for primitive values
1833  switch (m_type)
1834  {
1835  case value_t::boolean:
1836  case value_t::number_float:
1837  case value_t::number_integer:
1838  case value_t::number_unsigned:
1839  case value_t::string:
1840  {
1841  if (not first.m_it.primitive_iterator.is_begin() or not last.m_it.primitive_iterator.is_end())
1842  {
1843  throw std::out_of_range("iterators out of range");
1844  }
1845  break;
1846  }
1847 
1848  default:
1849  {
1850  break;
1851  }
1852  }
1853 
1854  switch (m_type)
1855  {
1856  case value_t::number_integer:
1857  {
1858  m_value.number_integer = first.m_object->m_value.number_integer;
1859  break;
1860  }
1861 
1862  case value_t::number_unsigned:
1863  {
1864  m_value.number_unsigned = first.m_object->m_value.number_unsigned;
1865  break;
1866  }
1867 
1868  case value_t::number_float:
1869  {
1870  m_value.number_float = first.m_object->m_value.number_float;
1871  break;
1872  }
1873 
1874  case value_t::boolean:
1875  {
1876  m_value.boolean = first.m_object->m_value.boolean;
1877  break;
1878  }
1879 
1880  case value_t::string:
1881  {
1882  m_value = *first.m_object->m_value.string;
1883  break;
1884  }
1885 
1886  case value_t::object:
1887  {
1888  m_value.object = create<object_t>(first.m_it.object_iterator, last.m_it.object_iterator);
1889  break;
1890  }
1891 
1892  case value_t::array:
1893  {
1894  m_value.array = create<array_t>(first.m_it.array_iterator, last.m_it.array_iterator);
1895  break;
1896  }
1897 
1898  default:
1899  {
1900  throw std::domain_error("cannot use construct with iterators from " + first.m_object->type_name());
1901  }
1902  }
1903 
1904  assert_invariant();
1905  }
1906 
1936  explicit basic_json(std::istream& i, const parser_callback_t cb = nullptr)
1937  {
1938  *this = parser(i, cb).parse();
1939  assert_invariant();
1940  }
1941 
1943  // other constructors and destructor //
1945 
1968  basic_json(const basic_json& other)
1969  : m_type(other.m_type)
1970  {
1971  // check of passed value is valid
1972  other.assert_invariant();
1973 
1974  switch (m_type)
1975  {
1976  case value_t::object:
1977  {
1978  m_value = *other.m_value.object;
1979  break;
1980  }
1981 
1982  case value_t::array:
1983  {
1984  m_value = *other.m_value.array;
1985  break;
1986  }
1987 
1988  case value_t::string:
1989  {
1990  m_value = *other.m_value.string;
1991  break;
1992  }
1993 
1994  case value_t::boolean:
1995  {
1996  m_value = other.m_value.boolean;
1997  break;
1998  }
1999 
2000  case value_t::number_integer:
2001  {
2002  m_value = other.m_value.number_integer;
2003  break;
2004  }
2005 
2006  case value_t::number_unsigned:
2007  {
2008  m_value = other.m_value.number_unsigned;
2009  break;
2010  }
2011 
2012  case value_t::number_float:
2013  {
2014  m_value = other.m_value.number_float;
2015  break;
2016  }
2017 
2018  default:
2019  {
2020  break;
2021  }
2022  }
2023 
2024  assert_invariant();
2025  }
2026 
2045  basic_json(basic_json&& other) noexcept
2046  : m_type(std::move(other.m_type)),
2047  m_value(std::move(other.m_value))
2048  {
2049  // check that passed value is valid
2050  other.assert_invariant();
2051 
2052  // invalidate payload
2053  other.m_type = value_t::null;
2054  other.m_value = {};
2055 
2056  assert_invariant();
2057  }
2058 
2082  reference& operator=(basic_json other) noexcept (
2087  )
2088  {
2089  // check that passed value is valid
2090  other.assert_invariant();
2091 
2092  using std::swap;
2093  swap(m_type, other.m_type);
2094  swap(m_value, other.m_value);
2095 
2096  assert_invariant();
2097  return *this;
2098  }
2099 
2116  {
2117  assert_invariant();
2118 
2119  switch (m_type)
2120  {
2121  case value_t::object:
2122  {
2123  AllocatorType<object_t> alloc;
2124  alloc.destroy(m_value.object);
2125  alloc.deallocate(m_value.object, 1);
2126  break;
2127  }
2128 
2129  case value_t::array:
2130  {
2131  AllocatorType<array_t> alloc;
2132  alloc.destroy(m_value.array);
2133  alloc.deallocate(m_value.array, 1);
2134  break;
2135  }
2136 
2137  case value_t::string:
2138  {
2139  AllocatorType<string_t> alloc;
2140  alloc.destroy(m_value.string);
2141  alloc.deallocate(m_value.string, 1);
2142  break;
2143  }
2144 
2145  default:
2146  {
2147  // all other types need no specific destructor
2148  break;
2149  }
2150  }
2151  }
2152 
2154 
2155  public:
2157  // object inspection //
2159 
2163 
2187  string_t dump(const int indent = -1) const
2188  {
2189  std::stringstream ss;
2190  // fix locale problems
2191  ss.imbue(std::locale::classic());
2192 
2193  // 6, 15 or 16 digits of precision allows round-trip IEEE 754
2194  // string->float->string, string->double->string or string->long
2195  // double->string; to be safe, we read this value from
2196  // std::numeric_limits<number_float_t>::digits10
2197  ss.precision(std::numeric_limits<double>::digits10);
2198 
2199  if (indent >= 0)
2200  {
2201  dump(ss, true, static_cast<unsigned int>(indent));
2202  }
2203  else
2204  {
2205  dump(ss, false, 0);
2206  }
2207 
2208  return ss.str();
2209  }
2210 
2229  constexpr value_t type() const noexcept
2230  {
2231  return m_type;
2232  }
2233 
2259  constexpr bool is_primitive() const noexcept
2260  {
2261  return is_null() or is_string() or is_boolean() or is_number();
2262  }
2263 
2286  constexpr bool is_structured() const noexcept
2287  {
2288  return is_array() or is_object();
2289  }
2290 
2308  constexpr bool is_null() const noexcept
2309  {
2310  return m_type == value_t::null;
2311  }
2312 
2330  constexpr bool is_boolean() const noexcept
2331  {
2332  return m_type == value_t::boolean;
2333  }
2334 
2360  constexpr bool is_number() const noexcept
2361  {
2362  return is_number_integer() or is_number_float();
2363  }
2364 
2389  constexpr bool is_number_integer() const noexcept
2390  {
2391  return m_type == value_t::number_integer or m_type == value_t::number_unsigned;
2392  }
2393 
2417  constexpr bool is_number_unsigned() const noexcept
2418  {
2419  return m_type == value_t::number_unsigned;
2420  }
2421 
2445  constexpr bool is_number_float() const noexcept
2446  {
2447  return m_type == value_t::number_float;
2448  }
2449 
2467  constexpr bool is_object() const noexcept
2468  {
2469  return m_type == value_t::object;
2470  }
2471 
2489  constexpr bool is_array() const noexcept
2490  {
2491  return m_type == value_t::array;
2492  }
2493 
2511  constexpr bool is_string() const noexcept
2512  {
2513  return m_type == value_t::string;
2514  }
2515 
2538  constexpr bool is_discarded() const noexcept
2539  {
2540  return m_type == value_t::discarded;
2541  }
2542 
2561  constexpr operator value_t() const noexcept
2562  {
2563  return m_type;
2564  }
2565 
2567 
2568  private:
2570  // value access //
2572 
2574  template<class T, typename std::enable_if<
2577  T get_impl(T*) const
2578  {
2579  if (is_object())
2580  {
2581  return T(m_value.object->begin(), m_value.object->end());
2582  }
2583  else
2584  {
2585  throw std::domain_error("type must be object, but is " + type_name());
2586  }
2587  }
2588 
2591  {
2592  if (is_object())
2593  {
2594  return *(m_value.object);
2595  }
2596  else
2597  {
2598  throw std::domain_error("type must be object, but is " + type_name());
2599  }
2600  }
2601 
2603  template<class T, typename std::enable_if<
2608  not has_mapped_type<T>::value, int>::type = 0>
2609  T get_impl(T*) const
2610  {
2611  if (is_array())
2612  {
2613  T to_vector;
2614  std::transform(m_value.array->begin(), m_value.array->end(),
2615  std::inserter(to_vector, to_vector.end()), [](basic_json i)
2616  {
2617  return i.get<typename T::value_type>();
2618  });
2619  return to_vector;
2620  }
2621  else
2622  {
2623  throw std::domain_error("type must be array, but is " + type_name());
2624  }
2625  }
2626 
2628  template<class T, typename std::enable_if<
2630  not std::is_same<basic_json_t, T>::value, int>::type = 0>
2631  std::vector<T> get_impl(std::vector<T>*) const
2632  {
2633  if (is_array())
2634  {
2635  std::vector<T> to_vector;
2636  to_vector.reserve(m_value.array->size());
2637  std::transform(m_value.array->begin(), m_value.array->end(),
2638  std::inserter(to_vector, to_vector.end()), [](basic_json i)
2639  {
2640  return i.get<T>();
2641  });
2642  return to_vector;
2643  }
2644  else
2645  {
2646  throw std::domain_error("type must be array, but is " + type_name());
2647  }
2648  }
2649 
2651  template<class T, typename std::enable_if<
2653  not has_mapped_type<T>::value, int>::type = 0>
2654  T get_impl(T*) const
2655  {
2656  if (is_array())
2657  {
2658  return T(m_value.array->begin(), m_value.array->end());
2659  }
2660  else
2661  {
2662  throw std::domain_error("type must be array, but is " + type_name());
2663  }
2664  }
2665 
2668  {
2669  if (is_array())
2670  {
2671  return *(m_value.array);
2672  }
2673  else
2674  {
2675  throw std::domain_error("type must be array, but is " + type_name());
2676  }
2677  }
2678 
2680  template<typename T, typename std::enable_if<
2682  T get_impl(T*) const
2683  {
2684  if (is_string())
2685  {
2686  return *m_value.string;
2687  }
2688  else
2689  {
2690  throw std::domain_error("type must be string, but is " + type_name());
2691  }
2692  }
2693 
2695  template<typename T, typename std::enable_if<
2696  std::is_arithmetic<T>::value, int>::type = 0>
2697  T get_impl(T*) const
2698  {
2699  switch (m_type)
2700  {
2701  case value_t::number_integer:
2702  {
2703  return static_cast<T>(m_value.number_integer);
2704  }
2705 
2706  case value_t::number_unsigned:
2707  {
2708  return static_cast<T>(m_value.number_unsigned);
2709  }
2710 
2711  case value_t::number_float:
2712  {
2713  return static_cast<T>(m_value.number_float);
2714  }
2715 
2716  default:
2717  {
2718  throw std::domain_error("type must be number, but is " + type_name());
2719  }
2720  }
2721  }
2722 
2724  constexpr boolean_t get_impl(boolean_t*) const
2725  {
2726  return is_boolean()
2727  ? m_value.boolean
2728  : throw std::domain_error("type must be boolean, but is " + type_name());
2729  }
2730 
2733  {
2734  return is_object() ? m_value.object : nullptr;
2735  }
2736 
2738  constexpr const object_t* get_impl_ptr(const object_t*) const noexcept
2739  {
2740  return is_object() ? m_value.object : nullptr;
2741  }
2742 
2745  {
2746  return is_array() ? m_value.array : nullptr;
2747  }
2748 
2750  constexpr const array_t* get_impl_ptr(const array_t*) const noexcept
2751  {
2752  return is_array() ? m_value.array : nullptr;
2753  }
2754 
2757  {
2758  return is_string() ? m_value.string : nullptr;
2759  }
2760 
2762  constexpr const string_t* get_impl_ptr(const string_t*) const noexcept
2763  {
2764  return is_string() ? m_value.string : nullptr;
2765  }
2766 
2769  {
2770  return is_boolean() ? &m_value.boolean : nullptr;
2771  }
2772 
2774  constexpr const boolean_t* get_impl_ptr(const boolean_t*) const noexcept
2775  {
2776  return is_boolean() ? &m_value.boolean : nullptr;
2777  }
2778 
2781  {
2782  return is_number_integer() ? &m_value.number_integer : nullptr;
2783  }
2784 
2786  constexpr const number_integer_t* get_impl_ptr(const number_integer_t*) const noexcept
2787  {
2788  return is_number_integer() ? &m_value.number_integer : nullptr;
2789  }
2790 
2793  {
2794  return is_number_unsigned() ? &m_value.number_unsigned : nullptr;
2795  }
2796 
2798  constexpr const number_unsigned_t* get_impl_ptr(const number_unsigned_t*) const noexcept
2799  {
2800  return is_number_unsigned() ? &m_value.number_unsigned : nullptr;
2801  }
2802 
2805  {
2806  return is_number_float() ? &m_value.number_float : nullptr;
2807  }
2808 
2810  constexpr const number_float_t* get_impl_ptr(const number_float_t*) const noexcept
2811  {
2812  return is_number_float() ? &m_value.number_float : nullptr;
2813  }
2814 
2826  template<typename ReferenceType, typename ThisType>
2827  static ReferenceType get_ref_impl(ThisType& obj)
2828  {
2829  // helper type
2830  using PointerType = typename std::add_pointer<ReferenceType>::type;
2831 
2832  // delegate the call to get_ptr<>()
2833  auto ptr = obj.template get_ptr<PointerType>();
2834 
2835  if (ptr != nullptr)
2836  {
2837  return *ptr;
2838  }
2839  else
2840  {
2841  throw std::domain_error("incompatible ReferenceType for get_ref, actual type is " +
2842  obj.type_name());
2843  }
2844  }
2845 
2846  public:
2847 
2851 
2885  template<typename ValueType, typename std::enable_if<
2886  not std::is_pointer<ValueType>::value, int>::type = 0>
2887  ValueType get() const
2888  {
2889  return get_impl(static_cast<ValueType*>(nullptr));
2890  }
2891 
2919  template<typename PointerType, typename std::enable_if<
2920  std::is_pointer<PointerType>::value, int>::type = 0>
2921  PointerType get() noexcept
2922  {
2923  // delegate the call to get_ptr
2924  return get_ptr<PointerType>();
2925  }
2926 
2931  template<typename PointerType, typename std::enable_if<
2932  std::is_pointer<PointerType>::value, int>::type = 0>
2933  constexpr const PointerType get() const noexcept
2934  {
2935  // delegate the call to get_ptr
2936  return get_ptr<PointerType>();
2937  }
2938 
2965  template<typename PointerType, typename std::enable_if<
2966  std::is_pointer<PointerType>::value, int>::type = 0>
2967  PointerType get_ptr() noexcept
2968  {
2969  // get the type of the PointerType (remove pointer and const)
2970  using pointee_t = typename std::remove_const<typename
2971  std::remove_pointer<typename
2973  // make sure the type matches the allowed types
2974  static_assert(
2982  , "incompatible pointer type");
2983 
2984  // delegate the call to get_impl_ptr<>()
2985  return get_impl_ptr(static_cast<PointerType>(nullptr));
2986  }
2987 
2992  template<typename PointerType, typename std::enable_if<
2993  std::is_pointer<PointerType>::value and
2995  constexpr const PointerType get_ptr() const noexcept
2996  {
2997  // get the type of the PointerType (remove pointer and const)
2998  using pointee_t = typename std::remove_const<typename
2999  std::remove_pointer<typename
3001  // make sure the type matches the allowed types
3002  static_assert(
3010  , "incompatible pointer type");
3011 
3012  // delegate the call to get_impl_ptr<>() const
3013  return get_impl_ptr(static_cast<const PointerType>(nullptr));
3014  }
3015 
3042  template<typename ReferenceType, typename std::enable_if<
3044  ReferenceType get_ref()
3045  {
3046  // delegate call to get_ref_impl
3047  return get_ref_impl<ReferenceType>(*this);
3048  }
3049 
3054  template<typename ReferenceType, typename std::enable_if<
3055  std::is_reference<ReferenceType>::value and
3057  ReferenceType get_ref() const
3058  {
3059  // delegate call to get_ref_impl
3060  return get_ref_impl<ReferenceType>(*this);
3061  }
3062 
3091  template < typename ValueType, typename std::enable_if <
3092  not std::is_pointer<ValueType>::value and
3094 #ifndef _MSC_VER // Fix for issue #167 operator<< abiguity under VS2015
3095  and not std::is_same<ValueType, std::initializer_list<typename string_t::value_type>>::value
3096 #endif
3097  , int >::type = 0 >
3098  operator ValueType() const
3099  {
3100  // delegate the call to get<>() const
3101  return get<ValueType>();
3102  }
3103 
3105 
3106 
3108  // element access //
3110 
3114 
3138  {
3139  // at only works for arrays
3140  if (is_array())
3141  {
3142  try
3143  {
3144  return m_value.array->at(idx);
3145  }
3146  catch (std::out_of_range&)
3147  {
3148  // create better exception explanation
3149  throw std::out_of_range("array index " + std::to_string(idx) + " is out of range");
3150  }
3151  }
3152  else
3153  {
3154  throw std::domain_error("cannot use at() with " + type_name());
3155  }
3156  }
3157 
3181  {
3182  // at only works for arrays
3183  if (is_array())
3184  {
3185  try
3186  {
3187  return m_value.array->at(idx);
3188  }
3189  catch (std::out_of_range&)
3190  {
3191  // create better exception explanation
3192  throw std::out_of_range("array index " + std::to_string(idx) + " is out of range");
3193  }
3194  }
3195  else
3196  {
3197  throw std::domain_error("cannot use at() with " + type_name());
3198  }
3199  }
3200 
3227  reference at(const typename object_t::key_type& key)
3228  {
3229  // at only works for objects
3230  if (is_object())
3231  {
3232  try
3233  {
3234  return m_value.object->at(key);
3235  }
3236  catch (std::out_of_range&)
3237  {
3238  // create better exception explanation
3239  throw std::out_of_range("key '" + key + "' not found");
3240  }
3241  }
3242  else
3243  {
3244  throw std::domain_error("cannot use at() with " + type_name());
3245  }
3246  }
3247 
3274  const_reference at(const typename object_t::key_type& key) const
3275  {
3276  // at only works for objects
3277  if (is_object())
3278  {
3279  try
3280  {
3281  return m_value.object->at(key);
3282  }
3283  catch (std::out_of_range&)
3284  {
3285  // create better exception explanation
3286  throw std::out_of_range("key '" + key + "' not found");
3287  }
3288  }
3289  else
3290  {
3291  throw std::domain_error("cannot use at() with " + type_name());
3292  }
3293  }
3294 
3321  {
3322  // implicitly convert null value to an empty array
3323  if (is_null())
3324  {
3325  m_type = value_t::array;
3326  m_value.array = create<array_t>();
3327  assert_invariant();
3328  }
3329 
3330  // operator[] only works for arrays
3331  if (is_array())
3332  {
3333  // fill up array with null values if given idx is outside range
3334  if (idx >= m_value.array->size())
3335  {
3336  m_value.array->insert(m_value.array->end(),
3337  idx - m_value.array->size() + 1,
3338  basic_json());
3339  }
3340 
3341  return m_value.array->operator[](idx);
3342  }
3343  else
3344  {
3345  throw std::domain_error("cannot use operator[] with " + type_name());
3346  }
3347  }
3348 
3369  {
3370  // const operator[] only works for arrays
3371  if (is_array())
3372  {
3373  return m_value.array->operator[](idx);
3374  }
3375  else
3376  {
3377  throw std::domain_error("cannot use operator[] with " + type_name());
3378  }
3379  }
3380 
3408  reference operator[](const typename object_t::key_type& key)
3409  {
3410  // implicitly convert null value to an empty object
3411  if (is_null())
3412  {
3413  m_type = value_t::object;
3414  m_value.object = create<object_t>();
3415  assert_invariant();
3416  }
3417 
3418  // operator[] only works for objects
3419  if (is_object())
3420  {
3421  return m_value.object->operator[](key);
3422  }
3423  else
3424  {
3425  throw std::domain_error("cannot use operator[] with " + type_name());
3426  }
3427  }
3428 
3459  const_reference operator[](const typename object_t::key_type& key) const
3460  {
3461  // const operator[] only works for objects
3462  if (is_object())
3463  {
3464  assert(m_value.object->find(key) != m_value.object->end());
3465  return m_value.object->find(key)->second;
3466  }
3467  else
3468  {
3469  throw std::domain_error("cannot use operator[] with " + type_name());
3470  }
3471  }
3472 
3500  template<typename T, std::size_t n>
3502  {
3503  return operator[](static_cast<const T>(key));
3504  }
3505 
3535  template<typename T, std::size_t n>
3537  {
3538  return operator[](static_cast<const T>(key));
3539  }
3540 
3568  template<typename T>
3570  {
3571  // implicitly convert null to object
3572  if (is_null())
3573  {
3574  m_type = value_t::object;
3575  m_value = value_t::object;
3576  assert_invariant();
3577  }
3578 
3579  // at only works for objects
3580  if (is_object())
3581  {
3582  return m_value.object->operator[](key);
3583  }
3584  else
3585  {
3586  throw std::domain_error("cannot use operator[] with " + type_name());
3587  }
3588  }
3589 
3620  template<typename T>
3622  {
3623  // at only works for objects
3624  if (is_object())
3625  {
3626  assert(m_value.object->find(key) != m_value.object->end());
3627  return m_value.object->find(key)->second;
3628  }
3629  else
3630  {
3631  throw std::domain_error("cannot use operator[] with " + type_name());
3632  }
3633  }
3634 
3683  template<class ValueType, typename std::enable_if<
3685  ValueType value(const typename object_t::key_type& key, ValueType default_value) const
3686  {
3687  // at only works for objects
3688  if (is_object())
3689  {
3690  // if key is found, return value and given default value otherwise
3691  const auto it = find(key);
3692  if (it != end())
3693  {
3694  return *it;
3695  }
3696  else
3697  {
3698  return default_value;
3699  }
3700  }
3701  else
3702  {
3703  throw std::domain_error("cannot use value() with " + type_name());
3704  }
3705  }
3706 
3711  string_t value(const typename object_t::key_type& key, const char* default_value) const
3712  {
3713  return value(key, string_t(default_value));
3714  }
3715 
3757  template<class ValueType, typename std::enable_if<
3758  std::is_convertible<basic_json_t, ValueType>::value, int>::type = 0>
3759  ValueType value(const json_pointer& ptr, ValueType default_value) const
3760  {
3761  // at only works for objects
3762  if (is_object())
3763  {
3764  // if pointer resolves a value, return it or use default value
3765  try
3766  {
3767  return ptr.get_checked(this);
3768  }
3769  catch (std::out_of_range&)
3770  {
3771  return default_value;
3772  }
3773  }
3774  else
3775  {
3776  throw std::domain_error("cannot use value() with " + type_name());
3777  }
3778  }
3779 
3784  string_t value(const json_pointer& ptr, const char* default_value) const
3785  {
3786  return value(ptr, string_t(default_value));
3787  }
3788 
3815  {
3816  return *begin();
3817  }
3818 
3823  {
3824  return *cbegin();
3825  }
3826 
3858  {
3859  auto tmp = end();
3860  --tmp;
3861  return *tmp;
3862  }
3863 
3868  {
3869  auto tmp = cend();
3870  --tmp;
3871  return *tmp;
3872  }
3873 
3919  template<class IteratorType, typename std::enable_if<
3922  = 0>
3923  IteratorType erase(IteratorType pos)
3924  {
3925  // make sure iterator fits the current value
3926  if (this != pos.m_object)
3927  {
3928  throw std::domain_error("iterator does not fit current value");
3929  }
3930 
3931  IteratorType result = end();
3932 
3933  switch (m_type)
3934  {
3935  case value_t::boolean:
3936  case value_t::number_float:
3937  case value_t::number_integer:
3938  case value_t::number_unsigned:
3939  case value_t::string:
3940  {
3941  if (not pos.m_it.primitive_iterator.is_begin())
3942  {
3943  throw std::out_of_range("iterator out of range");
3944  }
3945 
3946  if (is_string())
3947  {
3948  AllocatorType<string_t> alloc;
3949  alloc.destroy(m_value.string);
3950  alloc.deallocate(m_value.string, 1);
3951  m_value.string = nullptr;
3952  }
3953 
3954  m_type = value_t::null;
3955  assert_invariant();
3956  break;
3957  }
3958 
3959  case value_t::object:
3960  {
3961  result.m_it.object_iterator = m_value.object->erase(pos.m_it.object_iterator);
3962  break;
3963  }
3964 
3965  case value_t::array:
3966  {
3967  result.m_it.array_iterator = m_value.array->erase(pos.m_it.array_iterator);
3968  break;
3969  }
3970 
3971  default:
3972  {
3973  throw std::domain_error("cannot use erase() with " + type_name());
3974  }
3975  }
3976 
3977  return result;
3978  }
3979 
4026  template<class IteratorType, typename std::enable_if<
4028  std::is_same<IteratorType, typename basic_json_t::const_iterator>::value, int>::type
4029  = 0>
4030  IteratorType erase(IteratorType first, IteratorType last)
4031  {
4032  // make sure iterator fits the current value
4033  if (this != first.m_object or this != last.m_object)
4034  {
4035  throw std::domain_error("iterators do not fit current value");
4036  }
4037 
4038  IteratorType result = end();
4039 
4040  switch (m_type)
4041  {
4042  case value_t::boolean:
4043  case value_t::number_float:
4044  case value_t::number_integer:
4045  case value_t::number_unsigned:
4046  case value_t::string:
4047  {
4048  if (not first.m_it.primitive_iterator.is_begin() or not last.m_it.primitive_iterator.is_end())
4049  {
4050  throw std::out_of_range("iterators out of range");
4051  }
4052 
4053  if (is_string())
4054  {
4055  AllocatorType<string_t> alloc;
4056  alloc.destroy(m_value.string);
4057  alloc.deallocate(m_value.string, 1);
4058  m_value.string = nullptr;
4059  }
4060 
4061  m_type = value_t::null;
4062  assert_invariant();
4063  break;
4064  }
4065 
4066  case value_t::object:
4067  {
4068  result.m_it.object_iterator = m_value.object->erase(first.m_it.object_iterator,
4069  last.m_it.object_iterator);
4070  break;
4071  }
4072 
4073  case value_t::array:
4074  {
4075  result.m_it.array_iterator = m_value.array->erase(first.m_it.array_iterator,
4076  last.m_it.array_iterator);
4077  break;
4078  }
4079 
4080  default:
4081  {
4082  throw std::domain_error("cannot use erase() with " + type_name());
4083  }
4084  }
4085 
4086  return result;
4087  }
4088 
4118  size_type erase(const typename object_t::key_type& key)
4119  {
4120  // this erase only works for objects
4121  if (is_object())
4122  {
4123  return m_value.object->erase(key);
4124  }
4125  else
4126  {
4127  throw std::domain_error("cannot use erase() with " + type_name());
4128  }
4129  }
4130 
4155  void erase(const size_type idx)
4156  {
4157  // this erase only works for arrays
4158  if (is_array())
4159  {
4160  if (idx >= size())
4161  {
4162  throw std::out_of_range("array index " + std::to_string(idx) + " is out of range");
4163  }
4164 
4165  m_value.array->erase(m_value.array->begin() + static_cast<difference_type>(idx));
4166  }
4167  else
4168  {
4169  throw std::domain_error("cannot use erase() with " + type_name());
4170  }
4171  }
4172 
4174 
4175 
4177  // lookup //
4179 
4182 
4201  iterator find(typename object_t::key_type key)
4202  {
4203  auto result = end();
4204 
4205  if (is_object())
4206  {
4207  result.m_it.object_iterator = m_value.object->find(key);
4208  }
4209 
4210  return result;
4211  }
4212 
4217  const_iterator find(typename object_t::key_type key) const
4218  {
4219  auto result = cend();
4220 
4221  if (is_object())
4222  {
4223  result.m_it.object_iterator = m_value.object->find(key);
4224  }
4225 
4226  return result;
4227  }
4228 
4247  size_type count(typename object_t::key_type key) const
4248  {
4249  // return 0 for all nonobject types
4250  return is_object() ? m_value.object->count(key) : 0;
4251  }
4252 
4254 
4255 
4257  // iterators //
4259 
4262 
4287  iterator begin() noexcept
4288  {
4289  iterator result(this);
4290  result.set_begin();
4291  return result;
4292  }
4293 
4297  const_iterator begin() const noexcept
4298  {
4299  return cbegin();
4300  }
4301 
4327  const_iterator cbegin() const noexcept
4328  {
4329  const_iterator result(this);
4330  result.set_begin();
4331  return result;
4332  }
4333 
4358  iterator end() noexcept
4359  {
4360  iterator result(this);
4361  result.set_end();
4362  return result;
4363  }
4364 
4368  const_iterator end() const noexcept
4369  {
4370  return cend();
4371  }
4372 
4398  const_iterator cend() const noexcept
4399  {
4400  const_iterator result(this);
4401  result.set_end();
4402  return result;
4403  }
4404 
4429  {
4430  return reverse_iterator(end());
4431  }
4432 
4437  {
4438  return crbegin();
4439  }
4440 
4466  {
4467  return reverse_iterator(begin());
4468  }
4469 
4473  const_reverse_iterator rend() const noexcept
4474  {
4475  return crend();
4476  }
4477 
4503  {
4504  return const_reverse_iterator(cend());
4505  }
4506 
4532  {
4533  return const_reverse_iterator(cbegin());
4534  }
4535 
4536  private:
4537  // forward declaration
4538  template<typename IteratorType> class iteration_proxy;
4539 
4540  public:
4553  {
4554  return iteration_proxy<iterator>(cont);
4555  }
4556 
4561  {
4562  return iteration_proxy<const_iterator>(cont);
4563  }
4564 
4566 
4567 
4569  // capacity //
4571 
4574 
4612  bool empty() const noexcept
4613  {
4614  switch (m_type)
4615  {
4616  case value_t::null:
4617  {
4618  // null values are empty
4619  return true;
4620  }
4621 
4622  case value_t::array:
4623  {
4624  // delegate call to array_t::empty()
4625  return m_value.array->empty();
4626  }
4627 
4628  case value_t::object:
4629  {
4630  // delegate call to object_t::empty()
4631  return m_value.object->empty();
4632  }
4633 
4634  default:
4635  {
4636  // all other types are nonempty
4637  return false;
4638  }
4639  }
4640  }
4641 
4680  size_type size() const noexcept
4681  {
4682  switch (m_type)
4683  {
4684  case value_t::null:
4685  {
4686  // null values are empty
4687  return 0;
4688  }
4689 
4690  case value_t::array:
4691  {
4692  // delegate call to array_t::size()
4693  return m_value.array->size();
4694  }
4695 
4696  case value_t::object:
4697  {
4698  // delegate call to object_t::size()
4699  return m_value.object->size();
4700  }
4701 
4702  default:
4703  {
4704  // all other types have size 1
4705  return 1;
4706  }
4707  }
4708  }
4709 
4746  size_type max_size() const noexcept
4747  {
4748  switch (m_type)
4749  {
4750  case value_t::array:
4751  {
4752  // delegate call to array_t::max_size()
4753  return m_value.array->max_size();
4754  }
4755 
4756  case value_t::object:
4757  {
4758  // delegate call to object_t::max_size()
4759  return m_value.object->max_size();
4760  }
4761 
4762  default:
4763  {
4764  // all other types have max_size() == size()
4765  return size();
4766  }
4767  }
4768  }
4769 
4771 
4772 
4774  // modifiers //
4776 
4779 
4805  void clear() noexcept
4806  {
4807  switch (m_type)
4808  {
4809  case value_t::number_integer:
4810  {
4811  m_value.number_integer = 0;
4812  break;
4813  }
4814 
4815  case value_t::number_unsigned:
4816  {
4817  m_value.number_unsigned = 0;
4818  break;
4819  }
4820 
4821  case value_t::number_float:
4822  {
4823  m_value.number_float = 0.0;
4824  break;
4825  }
4826 
4827  case value_t::boolean:
4828  {
4829  m_value.boolean = false;
4830  break;
4831  }
4832 
4833  case value_t::string:
4834  {
4835  m_value.string->clear();
4836  break;
4837  }
4838 
4839  case value_t::array:
4840  {
4841  m_value.array->clear();
4842  break;
4843  }
4844 
4845  case value_t::object:
4846  {
4847  m_value.object->clear();
4848  break;
4849  }
4850 
4851  default:
4852  {
4853  break;
4854  }
4855  }
4856  }
4857 
4879  {
4880  // push_back only works for null objects or arrays
4881  if (not(is_null() or is_array()))
4882  {
4883  throw std::domain_error("cannot use push_back() with " + type_name());
4884  }
4885 
4886  // transform null object into an array
4887  if (is_null())
4888  {
4889  m_type = value_t::array;
4890  m_value = value_t::array;
4891  assert_invariant();
4892  }
4893 
4894  // add element to array (move semantics)
4895  m_value.array->push_back(std::move(val));
4896  // invalidate object
4897  val.m_type = value_t::null;
4898  }
4899 
4905  {
4906  push_back(std::move(val));
4907  return *this;
4908  }
4909 
4914  void push_back(const basic_json& val)
4915  {
4916  // push_back only works for null objects or arrays
4917  if (not(is_null() or is_array()))
4918  {
4919  throw std::domain_error("cannot use push_back() with " + type_name());
4920  }
4921 
4922  // transform null object into an array
4923  if (is_null())
4924  {
4925  m_type = value_t::array;
4926  m_value = value_t::array;
4927  assert_invariant();
4928  }
4929 
4930  // add element to array
4931  m_value.array->push_back(val);
4932  }
4933 
4939  {
4940  push_back(val);
4941  return *this;
4942  }
4943 
4964  void push_back(const typename object_t::value_type& val)
4965  {
4966  // push_back only works for null objects or objects
4967  if (not(is_null() or is_object()))
4968  {
4969  throw std::domain_error("cannot use push_back() with " + type_name());
4970  }
4971 
4972  // transform null object into an object
4973  if (is_null())
4974  {
4975  m_type = value_t::object;
4976  m_value = value_t::object;
4977  assert_invariant();
4978  }
4979 
4980  // add element to array
4981  m_value.object->insert(val);
4982  }
4983 
4988  reference operator+=(const typename object_t::value_type& val)
4989  {
4990  push_back(val);
4991  return *this;
4992  }
4993 
5019  void push_back(std::initializer_list<basic_json> init)
5020  {
5021  if (is_object() and init.size() == 2 and init.begin()->is_string())
5022  {
5023  const string_t key = *init.begin();
5024  push_back(typename object_t::value_type(key, *(init.begin() + 1)));
5025  }
5026  else
5027  {
5028  push_back(basic_json(init));
5029  }
5030  }
5031 
5036  reference operator+=(std::initializer_list<basic_json> init)
5037  {
5038  push_back(init);
5039  return *this;
5040  }
5041 
5063  template<class... Args>
5064  void emplace_back(Args&& ... args)
5065  {
5066  // emplace_back only works for null objects or arrays
5067  if (not(is_null() or is_array()))
5068  {
5069  throw std::domain_error("cannot use emplace_back() with " + type_name());
5070  }
5071 
5072  // transform null object into an array
5073  if (is_null())
5074  {
5075  m_type = value_t::array;
5076  m_value = value_t::array;
5077  assert_invariant();
5078  }
5079 
5080  // add element to array (perfect forwarding)
5081  m_value.array->emplace_back(std::forward<Args>(args)...);
5082  }
5083 
5111  template<class... Args>
5112  std::pair<iterator, bool> emplace(Args&& ... args)
5113  {
5114  // emplace only works for null objects or arrays
5115  if (not(is_null() or is_object()))
5116  {
5117  throw std::domain_error("cannot use emplace() with " + type_name());
5118  }
5119 
5120  // transform null object into an object
5121  if (is_null())
5122  {
5123  m_type = value_t::object;
5124  m_value = value_t::object;
5125  assert_invariant();
5126  }
5127 
5128  // add element to array (perfect forwarding)
5129  auto res = m_value.object->emplace(std::forward<Args>(args)...);
5130  // create result iterator and set iterator to the result of emplace
5131  auto it = begin();
5132  it.m_it.object_iterator = res.first;
5133 
5134  // return pair of iterator and boolean
5135  return {it, res.second};
5136  }
5137 
5161  {
5162  // insert only works for arrays
5163  if (is_array())
5164  {
5165  // check if iterator pos fits to this JSON value
5166  if (pos.m_object != this)
5167  {
5168  throw std::domain_error("iterator does not fit current value");
5169  }
5170 
5171  // insert to array and return iterator
5172  iterator result(this);
5173  result.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator, val);
5174  return result;
5175  }
5176  else
5177  {
5178  throw std::domain_error("cannot use insert() with " + type_name());
5179  }
5180  }
5181 
5187  {
5188  return insert(pos, val);
5189  }
5190 
5216  {
5217  // insert only works for arrays
5218  if (is_array())
5219  {
5220  // check if iterator pos fits to this JSON value
5221  if (pos.m_object != this)
5222  {
5223  throw std::domain_error("iterator does not fit current value");
5224  }
5225 
5226  // insert to array and return iterator
5227  iterator result(this);
5228  result.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator, cnt, val);
5229  return result;
5230  }
5231  else
5232  {
5233  throw std::domain_error("cannot use insert() with " + type_name());
5234  }
5235  }
5236 
5268  {
5269  // insert only works for arrays
5270  if (not is_array())
5271  {
5272  throw std::domain_error("cannot use insert() with " + type_name());
5273  }
5274 
5275  // check if iterator pos fits to this JSON value
5276  if (pos.m_object != this)
5277  {
5278  throw std::domain_error("iterator does not fit current value");
5279  }
5280 
5281  // check if range iterators belong to the same JSON object
5282  if (first.m_object != last.m_object)
5283  {
5284  throw std::domain_error("iterators do not fit");
5285  }
5286 
5287  if (first.m_object == this or last.m_object == this)
5288  {
5289  throw std::domain_error("passed iterators may not belong to container");
5290  }
5291 
5292  // insert to array and return iterator
5293  iterator result(this);
5294  result.m_it.array_iterator = m_value.array->insert(
5295  pos.m_it.array_iterator,
5296  first.m_it.array_iterator,
5297  last.m_it.array_iterator);
5298  return result;
5299  }
5300 
5325  iterator insert(const_iterator pos, std::initializer_list<basic_json> ilist)
5326  {
5327  // insert only works for arrays
5328  if (not is_array())
5329  {
5330  throw std::domain_error("cannot use insert() with " + type_name());
5331  }
5332 
5333  // check if iterator pos fits to this JSON value
5334  if (pos.m_object != this)
5335  {
5336  throw std::domain_error("iterator does not fit current value");
5337  }
5338 
5339  // insert to array and return iterator
5340  iterator result(this);
5341  result.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator, ilist);
5342  return result;
5343  }
5344 
5362  void swap(reference other) noexcept (
5367  )
5368  {
5369  std::swap(m_type, other.m_type);
5370  std::swap(m_value, other.m_value);
5371  assert_invariant();
5372  }
5373 
5394  void swap(array_t& other)
5395  {
5396  // swap only works for arrays
5397  if (is_array())
5398  {
5399  std::swap(*(m_value.array), other);
5400  }
5401  else
5402  {
5403  throw std::domain_error("cannot use swap() with " + type_name());
5404  }
5405  }
5406 
5427  void swap(object_t& other)
5428  {
5429  // swap only works for objects
5430  if (is_object())
5431  {
5432  std::swap(*(m_value.object), other);
5433  }
5434  else
5435  {
5436  throw std::domain_error("cannot use swap() with " + type_name());
5437  }
5438  }
5439 
5460  void swap(string_t& other)
5461  {
5462  // swap only works for strings
5463  if (is_string())
5464  {
5465  std::swap(*(m_value.string), other);
5466  }
5467  else
5468  {
5469  throw std::domain_error("cannot use swap() with " + type_name());
5470  }
5471  }
5472 
5474 
5475 
5477  // lexicographical comparison operators //
5479 
5482 
5483  private:
5493  friend bool operator<(const value_t lhs, const value_t rhs) noexcept
5494  {
5495  static constexpr std::array<uint8_t, 8> order = {{
5496  0, // null
5497  3, // object
5498  4, // array
5499  5, // string
5500  1, // boolean
5501  2, // integer
5502  2, // unsigned
5503  2, // float
5504  }
5505  };
5506 
5507  // discarded values are not comparable
5508  if (lhs == value_t::discarded or rhs == value_t::discarded)
5509  {
5510  return false;
5511  }
5512 
5513  return order[static_cast<std::size_t>(lhs)] < order[static_cast<std::size_t>(rhs)];
5514  }
5515 
5516  public:
5540  friend bool operator==(const_reference lhs, const_reference rhs) noexcept
5541  {
5542  const auto lhs_type = lhs.type();
5543  const auto rhs_type = rhs.type();
5544 
5545  if (lhs_type == rhs_type)
5546  {
5547  switch (lhs_type)
5548  {
5549  case value_t::array:
5550  {
5551  return *lhs.m_value.array == *rhs.m_value.array;
5552  }
5553  case value_t::object:
5554  {
5555  return *lhs.m_value.object == *rhs.m_value.object;
5556  }
5557  case value_t::null:
5558  {
5559  return true;
5560  }
5561  case value_t::string:
5562  {
5563  return *lhs.m_value.string == *rhs.m_value.string;
5564  }
5565  case value_t::boolean:
5566  {
5567  return lhs.m_value.boolean == rhs.m_value.boolean;
5568  }
5569  case value_t::number_integer:
5570  {
5571  return lhs.m_value.number_integer == rhs.m_value.number_integer;
5572  }
5573  case value_t::number_unsigned:
5574  {
5575  return lhs.m_value.number_unsigned == rhs.m_value.number_unsigned;
5576  }
5577  case value_t::number_float:
5578  {
5579  return lhs.m_value.number_float == rhs.m_value.number_float;
5580  }
5581  default:
5582  {
5583  return false;
5584  }
5585  }
5586  }
5587  else if (lhs_type == value_t::number_integer and rhs_type == value_t::number_float)
5588  {
5589  return static_cast<number_float_t>(lhs.m_value.number_integer) == rhs.m_value.number_float;
5590  }
5591  else if (lhs_type == value_t::number_float and rhs_type == value_t::number_integer)
5592  {
5593  return lhs.m_value.number_float == static_cast<number_float_t>(rhs.m_value.number_integer);
5594  }
5595  else if (lhs_type == value_t::number_unsigned and rhs_type == value_t::number_float)
5596  {
5597  return static_cast<number_float_t>(lhs.m_value.number_unsigned) == rhs.m_value.number_float;
5598  }
5599  else if (lhs_type == value_t::number_float and rhs_type == value_t::number_unsigned)
5600  {
5601  return lhs.m_value.number_float == static_cast<number_float_t>(rhs.m_value.number_unsigned);
5602  }
5603  else if (lhs_type == value_t::number_unsigned and rhs_type == value_t::number_integer)
5604  {
5605  return static_cast<number_integer_t>(lhs.m_value.number_unsigned) == rhs.m_value.number_integer;
5606  }
5607  else if (lhs_type == value_t::number_integer and rhs_type == value_t::number_unsigned)
5608  {
5609  return lhs.m_value.number_integer == static_cast<number_integer_t>(rhs.m_value.number_unsigned);
5610  }
5611 
5612  return false;
5613  }
5614 
5633  friend bool operator==(const_reference v, std::nullptr_t) noexcept
5634  {
5635  return v.is_null();
5636  }
5637 
5642  friend bool operator==(std::nullptr_t, const_reference v) noexcept
5643  {
5644  return v.is_null();
5645  }
5646 
5663  friend bool operator!=(const_reference lhs, const_reference rhs) noexcept
5664  {
5665  return not (lhs == rhs);
5666  }
5667 
5686  friend bool operator!=(const_reference v, std::nullptr_t) noexcept
5687  {
5688  return not v.is_null();
5689  }
5690 
5695  friend bool operator!=(std::nullptr_t, const_reference v) noexcept
5696  {
5697  return not v.is_null();
5698  }
5699 
5724  friend bool operator<(const_reference lhs, const_reference rhs) noexcept
5725  {
5726  const auto lhs_type = lhs.type();
5727  const auto rhs_type = rhs.type();
5728 
5729  if (lhs_type == rhs_type)
5730  {
5731  switch (lhs_type)
5732  {
5733  case value_t::array:
5734  {
5735  return *lhs.m_value.array < *rhs.m_value.array;
5736  }
5737  case value_t::object:
5738  {
5739  return *lhs.m_value.object < *rhs.m_value.object;
5740  }
5741  case value_t::null:
5742  {
5743  return false;
5744  }
5745  case value_t::string:
5746  {
5747  return *lhs.m_value.string < *rhs.m_value.string;
5748  }
5749  case value_t::boolean:
5750  {
5751  return lhs.m_value.boolean < rhs.m_value.boolean;
5752  }
5753  case value_t::number_integer:
5754  {
5755  return lhs.m_value.number_integer < rhs.m_value.number_integer;
5756  }
5757  case value_t::number_unsigned:
5758  {
5759  return lhs.m_value.number_unsigned < rhs.m_value.number_unsigned;
5760  }
5761  case value_t::number_float:
5762  {
5763  return lhs.m_value.number_float < rhs.m_value.number_float;
5764  }
5765  default:
5766  {
5767  return false;
5768  }
5769  }
5770  }
5771  else if (lhs_type == value_t::number_integer and rhs_type == value_t::number_float)
5772  {
5773  return static_cast<number_float_t>(lhs.m_value.number_integer) < rhs.m_value.number_float;
5774  }
5775  else if (lhs_type == value_t::number_float and rhs_type == value_t::number_integer)
5776  {
5777  return lhs.m_value.number_float < static_cast<number_float_t>(rhs.m_value.number_integer);
5778  }
5779  else if (lhs_type == value_t::number_unsigned and rhs_type == value_t::number_float)
5780  {
5781  return static_cast<number_float_t>(lhs.m_value.number_unsigned) < rhs.m_value.number_float;
5782  }
5783  else if (lhs_type == value_t::number_float and rhs_type == value_t::number_unsigned)
5784  {
5785  return lhs.m_value.number_float < static_cast<number_float_t>(rhs.m_value.number_unsigned);
5786  }
5787  else if (lhs_type == value_t::number_integer and rhs_type == value_t::number_unsigned)
5788  {
5789  return lhs.m_value.number_integer < static_cast<number_integer_t>(rhs.m_value.number_unsigned);
5790  }
5791  else if (lhs_type == value_t::number_unsigned and rhs_type == value_t::number_integer)
5792  {
5793  return static_cast<number_integer_t>(lhs.m_value.number_unsigned) < rhs.m_value.number_integer;
5794  }
5795 
5796  // We only reach this line if we cannot compare values. In that case,
5797  // we compare types. Note we have to call the operator explicitly,
5798  // because MSVC has problems otherwise.
5799  return operator<(lhs_type, rhs_type);
5800  }
5801 
5819  friend bool operator<=(const_reference lhs, const_reference rhs) noexcept
5820  {
5821  return not (rhs < lhs);
5822  }
5823 
5841  friend bool operator>(const_reference lhs, const_reference rhs) noexcept
5842  {
5843  return not (lhs <= rhs);
5844  }
5845 
5863  friend bool operator>=(const_reference lhs, const_reference rhs) noexcept
5864  {
5865  return not (lhs < rhs);
5866  }
5867 
5869 
5870 
5872  // serialization //
5874 
5877 
5904  friend std::ostream& operator<<(std::ostream& o, const basic_json& j)
5905  {
5906  // read width member and use it as indentation parameter if nonzero
5907  const bool pretty_print = (o.width() > 0);
5908  const auto indentation = (pretty_print ? o.width() : 0);
5909 
5910  // reset width to 0 for subsequent calls to this stream
5911  o.width(0);
5912 
5913  // fix locale problems
5914  const auto old_locale = o.imbue(std::locale::classic());
5915  // set precision
5916 
5917  // 6, 15 or 16 digits of precision allows round-trip IEEE 754
5918  // string->float->string, string->double->string or string->long
5919  // double->string; to be safe, we read this value from
5920  // std::numeric_limits<number_float_t>::digits10
5921  const auto old_precision = o.precision(std::numeric_limits<double>::digits10);
5922 
5923  // do the actual serialization
5924  j.dump(o, pretty_print, static_cast<unsigned int>(indentation));
5925 
5926  // reset locale and precision
5927  o.imbue(old_locale);
5928  o.precision(old_precision);
5929  return o;
5930  }
5931 
5936  friend std::ostream& operator>>(const basic_json& j, std::ostream& o)
5937  {
5938  return o << j;
5939  }
5940 
5942 
5943 
5945  // deserialization //
5947 
5950 
5978  template<class T, std::size_t N>
5979  static basic_json parse(T (&array)[N],
5980  const parser_callback_t cb = nullptr)
5981  {
5982  // delegate the call to the iterator-range parse overload
5983  return parse(std::begin(array), std::end(array), cb);
5984  }
5985 
6013  template<typename CharT, typename std::enable_if<
6016  sizeof(typename std::remove_pointer<CharT>::type) == 1, int>::type = 0>
6017  static basic_json parse(const CharT s,
6018  const parser_callback_t cb = nullptr)
6019  {
6020  return parser(reinterpret_cast<const char*>(s), cb).parse();
6021  }
6022 
6047  static basic_json parse(std::istream& i,
6048  const parser_callback_t cb = nullptr)
6049  {
6050  return parser(i, cb).parse();
6051  }
6052 
6056  static basic_json parse(std::istream&& i,
6057  const parser_callback_t cb = nullptr)
6058  {
6059  return parser(i, cb).parse();
6060  }
6061 
6103  template<class IteratorType, typename std::enable_if<
6104  std::is_base_of<
6105  std::random_access_iterator_tag,
6106  typename std::iterator_traits<IteratorType>::iterator_category>::value, int>::type = 0>
6107  static basic_json parse(IteratorType first, IteratorType last,
6108  const parser_callback_t cb = nullptr)
6109  {
6110  // assertion to check that the iterator range is indeed contiguous,
6111  // see http://stackoverflow.com/a/35008842/266378 for more discussion
6112  assert(std::accumulate(first, last, std::make_pair<bool, int>(true, 0),
6113  [&first](std::pair<bool, int> res, decltype(*first) val)
6114  {
6115  res.first &= (val == *(std::next(std::addressof(*first), res.second++)));
6116  return res;
6117  }).first);
6118 
6119  // assertion to check that each element is 1 byte long
6120  static_assert(sizeof(typename std::iterator_traits<IteratorType>::value_type) == 1,
6121  "each element in the iterator range must have the size of 1 byte");
6122 
6123  // if iterator range is empty, create a parser with an empty string
6124  // to generate "unexpected EOF" error message
6125  if (std::distance(first, last) <= 0)
6126  {
6127  return parser("").parse();
6128  }
6129 
6130  return parser(first, last, cb).parse();
6131  }
6132 
6173  template<class ContiguousContainer, typename std::enable_if<
6175  std::is_base_of<
6176  std::random_access_iterator_tag,
6177  typename std::iterator_traits<decltype(std::begin(std::declval<ContiguousContainer const>()))>::iterator_category>::value
6178  , int>::type = 0>
6179  static basic_json parse(const ContiguousContainer& c,
6180  const parser_callback_t cb = nullptr)
6181  {
6182  // delegate the call to the iterator-range parse overload
6183  return parse(std::begin(c), std::end(c), cb);
6184  }
6185 
6209  friend std::istream& operator<<(basic_json& j, std::istream& i)
6210  {
6211  j = parser(i).parse();
6212  return i;
6213  }
6214 
6219  friend std::istream& operator>>(std::istream& i, basic_json& j)
6220  {
6221  j = parser(i).parse();
6222  return i;
6223  }
6224 
6226 
6228  // binary serialization/deserialization //
6230 
6233 
6234  private:
6235  template<typename T>
6236  static void add_to_vector(std::vector<uint8_t>& vec, size_t bytes, const T number)
6237  {
6238  assert(bytes == 1 or bytes == 2 or bytes == 4 or bytes == 8);
6239 
6240  switch (bytes)
6241  {
6242  case 8:
6243  {
6244  vec.push_back(static_cast<uint8_t>((number >> 070) & 0xff));
6245  vec.push_back(static_cast<uint8_t>((number >> 060) & 0xff));
6246  vec.push_back(static_cast<uint8_t>((number >> 050) & 0xff));
6247  vec.push_back(static_cast<uint8_t>((number >> 040) & 0xff));
6248  // intentional fall-through
6249  }
6250 
6251  case 4:
6252  {
6253  vec.push_back(static_cast<uint8_t>((number >> 030) & 0xff));
6254  vec.push_back(static_cast<uint8_t>((number >> 020) & 0xff));
6255  // intentional fall-through
6256  }
6257 
6258  case 2:
6259  {
6260  vec.push_back(static_cast<uint8_t>((number >> 010) & 0xff));
6261  // intentional fall-through
6262  }
6263 
6264  case 1:
6265  {
6266  vec.push_back(static_cast<uint8_t>(number & 0xff));
6267  break;
6268  }
6269  }
6270  }
6271 
6308  template<typename T>
6309  static T get_from_vector(const std::vector<uint8_t>& vec, const size_t current_index)
6310  {
6311  if (current_index + sizeof(T) + 1 > vec.size())
6312  {
6313  throw std::out_of_range("cannot read " + std::to_string(sizeof(T)) + " bytes from vector");
6314  }
6315 
6316  T result;
6317  uint8_t* ptr = reinterpret_cast<uint8_t*>(&result);
6318  for (size_t i = 0; i < sizeof(T); ++i)
6319  {
6320  *ptr++ = vec[current_index + sizeof(T) - i];
6321  }
6322  return result;
6323  }
6324 
6335  static void to_msgpack_internal(const basic_json& j, std::vector<uint8_t>& v)
6336  {
6337  switch (j.type())
6338  {
6339  case value_t::null:
6340  {
6341  // nil
6342  v.push_back(0xc0);
6343  break;
6344  }
6345 
6346  case value_t::boolean:
6347  {
6348  // true and false
6349  v.push_back(j.m_value.boolean ? 0xc3 : 0xc2);
6350  break;
6351  }
6352 
6353  case value_t::number_integer:
6354  {
6355  if (j.m_value.number_integer >= 0)
6356  {
6357  // MessagePack does not differentiate between positive
6358  // signed integers and unsigned integers. Therefore, we used
6359  // the code from the value_t::number_unsigned case here.
6360  if (j.m_value.number_unsigned < 128)
6361  {
6362  // positive fixnum
6363  add_to_vector(v, 1, j.m_value.number_unsigned);
6364  }
6365  else if (j.m_value.number_unsigned <= UINT8_MAX)
6366  {
6367  // uint 8
6368  v.push_back(0xcc);
6369  add_to_vector(v, 1, j.m_value.number_unsigned);
6370  }
6371  else if (j.m_value.number_unsigned <= UINT16_MAX)
6372  {
6373  // uint 16
6374  v.push_back(0xcd);
6375  add_to_vector(v, 2, j.m_value.number_unsigned);
6376  }
6377  else if (j.m_value.number_unsigned <= UINT32_MAX)
6378  {
6379  // uint 32
6380  v.push_back(0xce);
6381  add_to_vector(v, 4, j.m_value.number_unsigned);
6382  }
6383  else if (j.m_value.number_unsigned <= UINT64_MAX)
6384  {
6385  // uint 64
6386  v.push_back(0xcf);
6387  add_to_vector(v, 8, j.m_value.number_unsigned);
6388  }
6389  }
6390  else
6391  {
6392  if (j.m_value.number_integer >= -32)
6393  {
6394  // negative fixnum
6395  add_to_vector(v, 1, j.m_value.number_integer);
6396  }
6398  {
6399  // int 8
6400  v.push_back(0xd0);
6401  add_to_vector(v, 1, j.m_value.number_integer);
6402  }
6404  {
6405  // int 16
6406  v.push_back(0xd1);
6407  add_to_vector(v, 2, j.m_value.number_integer);
6408  }
6410  {
6411  // int 32
6412  v.push_back(0xd2);
6413  add_to_vector(v, 4, j.m_value.number_integer);
6414  }
6416  {
6417  // int 64
6418  v.push_back(0xd3);
6419  add_to_vector(v, 8, j.m_value.number_integer);
6420  }
6421  }
6422  break;
6423  }
6424 
6425  case value_t::number_unsigned:
6426  {
6427  if (j.m_value.number_unsigned < 128)
6428  {
6429  // positive fixnum
6430  add_to_vector(v, 1, j.m_value.number_unsigned);
6431  }
6432  else if (j.m_value.number_unsigned <= UINT8_MAX)
6433  {
6434  // uint 8
6435  v.push_back(0xcc);
6436  add_to_vector(v, 1, j.m_value.number_unsigned);
6437  }
6438  else if (j.m_value.number_unsigned <= UINT16_MAX)
6439  {
6440  // uint 16
6441  v.push_back(0xcd);
6442  add_to_vector(v, 2, j.m_value.number_unsigned);
6443  }
6444  else if (j.m_value.number_unsigned <= UINT32_MAX)
6445  {
6446  // uint 32
6447  v.push_back(0xce);
6448  add_to_vector(v, 4, j.m_value.number_unsigned);
6449  }
6450  else if (j.m_value.number_unsigned <= UINT64_MAX)
6451  {
6452  // uint 64
6453  v.push_back(0xcf);
6454  add_to_vector(v, 8, j.m_value.number_unsigned);
6455  }
6456  break;
6457  }
6458 
6459  case value_t::number_float:
6460  {
6461  // float 64
6462  v.push_back(0xcb);
6463  const uint8_t* helper = reinterpret_cast<const uint8_t*>(&(j.m_value.number_float));
6464  for (size_t i = 0; i < 8; ++i)
6465  {
6466  v.push_back(helper[7 - i]);
6467  }
6468  break;
6469  }
6470 
6471  case value_t::string:
6472  {
6473  const auto N = j.m_value.string->size();
6474  if (N <= 31)
6475  {
6476  // fixstr
6477  v.push_back(static_cast<uint8_t>(0xa0 | N));
6478  }
6479  else if (N <= 255)
6480  {
6481  // str 8
6482  v.push_back(0xd9);
6483  add_to_vector(v, 1, N);
6484  }
6485  else if (N <= 65535)
6486  {
6487  // str 16
6488  v.push_back(0xda);
6489  add_to_vector(v, 2, N);
6490  }
6491  else if (N <= 4294967295)
6492  {
6493  // str 32
6494  v.push_back(0xdb);
6495  add_to_vector(v, 4, N);
6496  }
6497 
6498  // append string
6499  std::copy(j.m_value.string->begin(), j.m_value.string->end(),
6500  std::back_inserter(v));
6501  break;
6502  }
6503 
6504  case value_t::array:
6505  {
6506  const auto N = j.m_value.array->size();
6507  if (N <= 15)
6508  {
6509  // fixarray
6510  v.push_back(static_cast<uint8_t>(0x90 | N));
6511  }
6512  else if (N <= 0xffff)
6513  {
6514  // array 16
6515  v.push_back(0xdc);
6516  add_to_vector(v, 2, N);
6517  }
6518  else if (N <= 0xffffffff)
6519  {
6520  // array 32
6521  v.push_back(0xdd);
6522  add_to_vector(v, 4, N);
6523  }
6524 
6525  // append each element
6526  for (const auto& el : *j.m_value.array)
6527  {
6528  to_msgpack_internal(el, v);
6529  }
6530  break;
6531  }
6532 
6533  case value_t::object:
6534  {
6535  const auto N = j.m_value.object->size();
6536  if (N <= 15)
6537  {
6538  // fixmap
6539  v.push_back(static_cast<uint8_t>(0x80 | (N & 0xf)));
6540  }
6541  else if (N <= 65535)
6542  {
6543  // map 16
6544  v.push_back(0xde);
6545  add_to_vector(v, 2, N);
6546  }
6547  else if (N <= 4294967295)
6548  {
6549  // map 32
6550  v.push_back(0xdf);
6551  add_to_vector(v, 4, N);
6552  }
6553 
6554  // append each element
6555  for (const auto& el : *j.m_value.object)
6556  {
6557  to_msgpack_internal(el.first, v);
6558  to_msgpack_internal(el.second, v);
6559  }
6560  break;
6561  }
6562 
6563  default:
6564  {
6565  break;
6566  }
6567  }
6568  }
6569 
6580  static void to_cbor_internal(const basic_json& j, std::vector<uint8_t>& v)
6581  {
6582  switch (j.type())
6583  {
6584  case value_t::null:
6585  {
6586  v.push_back(0xf6);
6587  break;
6588  }
6589 
6590  case value_t::boolean:
6591  {
6592  v.push_back(j.m_value.boolean ? 0xf5 : 0xf4);
6593  break;
6594  }
6595 
6596  case value_t::number_integer:
6597  {
6598  if (j.m_value.number_integer >= 0)
6599  {
6600  // CBOR does not differentiate between positive signed
6601  // integers and unsigned integers. Therefore, we used the
6602  // code from the value_t::number_unsigned case here.
6603  if (j.m_value.number_integer <= 0x17)
6604  {
6605  add_to_vector(v, 1, j.m_value.number_integer);
6606  }
6607  else if (j.m_value.number_integer <= UINT8_MAX)
6608  {
6609  v.push_back(0x18);
6610  // one-byte uint8_t
6611  add_to_vector(v, 1, j.m_value.number_integer);
6612  }
6613  else if (j.m_value.number_integer <= UINT16_MAX)
6614  {
6615  v.push_back(0x19);
6616  // two-byte uint16_t
6617  add_to_vector(v, 2, j.m_value.number_integer);
6618  }
6619  else if (j.m_value.number_integer <= UINT32_MAX)
6620  {
6621  v.push_back(0x1a);
6622  // four-byte uint32_t
6623  add_to_vector(v, 4, j.m_value.number_integer);
6624  }
6625  else
6626  {
6627  v.push_back(0x1b);
6628  // eight-byte uint64_t
6629  add_to_vector(v, 8, j.m_value.number_integer);
6630  }
6631  }
6632  else
6633  {
6634  // The conversions below encode the sign in the first byte,
6635  // and the value is converted to a positive number.
6636  const auto positive_number = -1 - j.m_value.number_integer;
6637  if (j.m_value.number_integer >= -24)
6638  {
6639  v.push_back(static_cast<uint8_t>(0x20 + positive_number));
6640  }
6641  else if (positive_number <= UINT8_MAX)
6642  {
6643  // int 8
6644  v.push_back(0x38);
6645  add_to_vector(v, 1, positive_number);
6646  }
6647  else if (positive_number <= UINT16_MAX)
6648  {
6649  // int 16
6650  v.push_back(0x39);
6651  add_to_vector(v, 2, positive_number);
6652  }
6653  else if (positive_number <= UINT32_MAX)
6654  {
6655  // int 32
6656  v.push_back(0x3a);
6657  add_to_vector(v, 4, positive_number);
6658  }
6659  else
6660  {
6661  // int 64
6662  v.push_back(0x3b);
6663  add_to_vector(v, 8, positive_number);
6664  }
6665  }
6666  break;
6667  }
6668 
6669  case value_t::number_unsigned:
6670  {
6671  if (j.m_value.number_unsigned <= 0x17)
6672  {
6673  v.push_back(static_cast<uint8_t>(j.m_value.number_unsigned));
6674  }
6675  else if (j.m_value.number_unsigned <= 0xff)
6676  {
6677  v.push_back(0x18);
6678  // one-byte uint8_t
6679  add_to_vector(v, 1, j.m_value.number_unsigned);
6680  }
6681  else if (j.m_value.number_unsigned <= 0xffff)
6682  {
6683  v.push_back(0x19);
6684  // two-byte uint16_t
6685  add_to_vector(v, 2, j.m_value.number_unsigned);
6686  }
6687  else if (j.m_value.number_unsigned <= 0xffffffff)
6688  {
6689  v.push_back(0x1a);
6690  // four-byte uint32_t
6691  add_to_vector(v, 4, j.m_value.number_unsigned);
6692  }
6693  else if (j.m_value.number_unsigned <= 0xffffffffffffffff)
6694  {
6695  v.push_back(0x1b);
6696  // eight-byte uint64_t
6697  add_to_vector(v, 8, j.m_value.number_unsigned);
6698  }
6699  break;
6700  }
6701 
6702  case value_t::number_float:
6703  {
6704  // Double-Precision Float
6705  v.push_back(0xfb);
6706  const uint8_t* helper = reinterpret_cast<const uint8_t*>(&(j.m_value.number_float));
6707  for (size_t i = 0; i < 8; ++i)
6708  {
6709  v.push_back(helper[7 - i]);
6710  }
6711  break;
6712  }
6713 
6714  case value_t::string:
6715  {
6716  const auto N = j.m_value.string->size();
6717  if (N <= 0x17)
6718  {
6719  v.push_back(0x60 + N); // 1 byte for string + size
6720  }
6721  else if (N <= 0xff)
6722  {
6723  v.push_back(0x78); // one-byte uint8_t for N
6724  add_to_vector(v, 1, N);
6725  }
6726  else if (N <= 0xffff)
6727  {
6728  v.push_back(0x79); // two-byte uint16_t for N
6729  add_to_vector(v, 2, N);
6730  }
6731  else if (N <= 0xffffffff)
6732  {
6733  v.push_back(0x7a); // four-byte uint32_t for N
6734  add_to_vector(v, 4, N);
6735  }
6736  // LCOV_EXCL_START
6737  else if (N <= 0xffffffffffffffff)
6738  {
6739  v.push_back(0x7b); // eight-byte uint64_t for N
6740  add_to_vector(v, 8, N);
6741  }
6742  // LCOV_EXCL_STOP
6743 
6744  // append string
6745  std::copy(j.m_value.string->begin(), j.m_value.string->end(),
6746  std::back_inserter(v));
6747  break;
6748  }
6749 
6750  case value_t::array:
6751  {
6752  const auto N = j.m_value.array->size();
6753  if (N <= 0x17)
6754  {
6755  v.push_back(0x80 + N); // 1 byte for array + size
6756  }
6757  else if (N <= 0xff)
6758  {
6759  v.push_back(0x98); // one-byte uint8_t for N
6760  add_to_vector(v, 1, N);
6761  }
6762  else if (N <= 0xffff)
6763  {
6764  v.push_back(0x99); // two-byte uint16_t for N
6765  add_to_vector(v, 2, N);
6766  }
6767  else if (N <= 0xffffffff)
6768  {
6769  v.push_back(0x9a); // four-byte uint32_t for N
6770  add_to_vector(v, 4, N);
6771  }
6772  // LCOV_EXCL_START
6773  else if (N <= 0xffffffffffffffff)
6774  {
6775  v.push_back(0x9b); // eight-byte uint64_t for N
6776  add_to_vector(v, 8, N);
6777  }
6778  // LCOV_EXCL_STOP
6779 
6780  // append each element
6781  for (const auto& el : *j.m_value.array)
6782  {
6783  to_cbor_internal(el, v);
6784  }
6785  break;
6786  }
6787 
6788  case value_t::object:
6789  {
6790  const auto N = j.m_value.object->size();
6791  if (N <= 0x17)
6792  {
6793  v.push_back(0xa0 + N); // 1 byte for object + size
6794  }
6795  else if (N <= 0xff)
6796  {
6797  v.push_back(0xb8);
6798  add_to_vector(v, 1, N); // one-byte uint8_t for N
6799  }
6800  else if (N <= 0xffff)
6801  {
6802  v.push_back(0xb9);
6803  add_to_vector(v, 2, N); // two-byte uint16_t for N
6804  }
6805  else if (N <= 0xffffffff)
6806  {
6807  v.push_back(0xba);
6808  add_to_vector(v, 4, N); // four-byte uint32_t for N
6809  }
6810  // LCOV_EXCL_START
6811  else if (N <= 0xffffffffffffffff)
6812  {
6813  v.push_back(0xbb);
6814  add_to_vector(v, 8, N); // eight-byte uint64_t for N
6815  }
6816  // LCOV_EXCL_STOP
6817 
6818  // append each element
6819  for (const auto& el : *j.m_value.object)
6820  {
6821  to_cbor_internal(el.first, v);
6822  to_cbor_internal(el.second, v);
6823  }
6824  break;
6825  }
6826 
6827  default:
6828  {
6829  break;
6830  }
6831  }
6832  }
6833 
6848  static basic_json from_msgpack_internal(const std::vector<uint8_t>& v, size_t& idx)
6849  {
6850  // store and increment index
6851  const size_t current_idx = idx++;
6852 
6853  if (v[current_idx] <= 0xbf)
6854  {
6855  if (v[current_idx] <= 0x7f) // positive fixint
6856  {
6857  return v[current_idx];
6858  }
6859  else if (v[current_idx] <= 0x8f) // fixmap
6860  {
6862  const size_t len = v[current_idx] & 0x0f;
6863  for (size_t i = 0; i < len; ++i)
6864  {
6865  std::string key = from_msgpack_internal(v, idx);
6866  result[key] = from_msgpack_internal(v, idx);
6867  }
6868  return result;
6869  }
6870  else if (v[current_idx] <= 0x9f) // fixarray
6871  {
6873  const size_t len = v[current_idx] & 0x0f;
6874  for (size_t i = 0; i < len; ++i)
6875  {
6876  result.push_back(from_msgpack_internal(v, idx));
6877  }
6878  return result;
6879  }
6880  else // fixstr
6881  {
6882  const size_t len = v[current_idx] & 0x1f;
6883  const size_t offset = current_idx + 1;
6884  idx += len; // skip content bytes
6885  return std::string(reinterpret_cast<const char*>(v.data()) + offset, len);
6886  }
6887  }
6888  else if (v[current_idx] >= 0xe0) // negative fixint
6889  {
6890  return static_cast<int8_t>(v[current_idx]);
6891  }
6892  else
6893  {
6894  switch (v[current_idx])
6895  {
6896  case 0xc0: // nil
6897  {
6898  return value_t::null;
6899  }
6900 
6901  case 0xc2: // false
6902  {
6903  return false;
6904  }
6905 
6906  case 0xc3: // true
6907  {
6908  return true;
6909  }
6910 
6911  case 0xca: // float 32
6912  {
6913  // copy bytes in reverse order into the double variable
6914  float res;
6915  for (size_t byte = 0; byte < sizeof(float); ++byte)
6916  {
6917  reinterpret_cast<uint8_t*>(&res)[sizeof(float) - byte - 1] = v[current_idx + 1 + byte];
6918  }
6919  idx += sizeof(float); // skip content bytes
6920  return res;
6921  }
6922 
6923  case 0xcb: // float 64
6924  {
6925  // copy bytes in reverse order into the double variable
6926  double res;
6927  for (size_t byte = 0; byte < sizeof(double); ++byte)
6928  {
6929  reinterpret_cast<uint8_t*>(&res)[sizeof(double) - byte - 1] = v[current_idx + 1 + byte];
6930  }
6931  idx += sizeof(double); // skip content bytes
6932  return res;
6933  }
6934 
6935  case 0xcc: // uint 8
6936  {
6937  idx += 1; // skip content byte
6938  return get_from_vector<uint8_t>(v, current_idx);
6939  }
6940 
6941  case 0xcd: // uint 16
6942  {
6943  idx += 2; // skip 2 content bytes
6944  return get_from_vector<uint16_t>(v, current_idx);
6945  }
6946 
6947  case 0xce: // uint 32
6948  {
6949  idx += 4; // skip 4 content bytes
6950  return get_from_vector<uint32_t>(v, current_idx);
6951  }
6952 
6953  case 0xcf: // uint 64
6954  {
6955  idx += 8; // skip 8 content bytes
6956  return get_from_vector<uint64_t>(v, current_idx);
6957  }
6958 
6959  case 0xd0: // int 8
6960  {
6961  idx += 1; // skip content byte
6962  return get_from_vector<int8_t>(v, current_idx);
6963  }
6964 
6965  case 0xd1: // int 16
6966  {
6967  idx += 2; // skip 2 content bytes
6968  return get_from_vector<int16_t>(v, current_idx);
6969  }
6970 
6971  case 0xd2: // int 32
6972  {
6973  idx += 4; // skip 4 content bytes
6974  return get_from_vector<int32_t>(v, current_idx);
6975  }
6976 
6977  case 0xd3: // int 64
6978  {
6979  idx += 8; // skip 8 content bytes
6980  return get_from_vector<int64_t>(v, current_idx);
6981  }
6982 
6983  case 0xd9: // str 8
6984  {
6985  const auto len = get_from_vector<uint8_t>(v, current_idx);
6986  const size_t offset = current_idx + 2;
6987  idx += len + 1; // skip size byte + content bytes
6988  return std::string(reinterpret_cast<const char*>(v.data()) + offset, len);
6989  }
6990 
6991  case 0xda: // str 16
6992  {
6993  const auto len = get_from_vector<uint16_t>(v, current_idx);
6994  const size_t offset = current_idx + 3;
6995  idx += len + 2; // skip 2 size bytes + content bytes
6996  return std::string(reinterpret_cast<const char*>(v.data()) + offset, len);
6997  }
6998 
6999  case 0xdb: // str 32
7000  {
7001  const auto len = get_from_vector<uint32_t>(v, current_idx);
7002  const size_t offset = current_idx + 5;
7003  idx += len + 4; // skip 4 size bytes + content bytes
7004  return std::string(reinterpret_cast<const char*>(v.data()) + offset, len);
7005  }
7006 
7007  case 0xdc: // array 16
7008  {
7010  const auto len = get_from_vector<uint16_t>(v, current_idx);
7011  idx += 2; // skip 2 size bytes
7012  for (size_t i = 0; i < len; ++i)
7013  {
7014  result.push_back(from_msgpack_internal(v, idx));
7015  }
7016  return result;
7017  }
7018 
7019  case 0xdd: // array 32
7020  {
7022  const auto len = get_from_vector<uint32_t>(v, current_idx);
7023  idx += 4; // skip 4 size bytes
7024  for (size_t i = 0; i < len; ++i)
7025  {
7026  result.push_back(from_msgpack_internal(v, idx));
7027  }
7028  return result;
7029  }
7030 
7031  case 0xde: // map 16
7032  {
7034  const auto len = get_from_vector<uint16_t>(v, current_idx);
7035  idx += 2; // skip 2 size bytes
7036  for (size_t i = 0; i < len; ++i)
7037  {
7038  std::string key = from_msgpack_internal(v, idx);
7039  result[key] = from_msgpack_internal(v, idx);
7040  }
7041  return result;
7042  }
7043 
7044  case 0xdf: // map 32
7045  {
7047  const auto len = get_from_vector<uint32_t>(v, current_idx);
7048  idx += 4; // skip 4 size bytes
7049  for (size_t i = 0; i < len; ++i)
7050  {
7051  std::string key = from_msgpack_internal(v, idx);
7052  result[key] = from_msgpack_internal(v, idx);
7053  }
7054  return result;
7055  }
7056 
7057  default:
7058  {
7059  throw std::invalid_argument("error parsing a msgpack @ " + std::to_string(current_idx));
7060  }
7061  }
7062  }
7063  }
7064 
7079  static basic_json from_cbor_internal(const std::vector<uint8_t>& v, size_t& idx)
7080  {
7081  // store and increment index
7082  const size_t current_idx = idx++;
7083 
7084  switch (v[current_idx])
7085  {
7086  // Integer 0x00..0x17 (0..23)
7087  case 0x00:
7088  case 0x01:
7089  case 0x02:
7090  case 0x03:
7091  case 0x04:
7092  case 0x05:
7093  case 0x06:
7094  case 0x07:
7095  case 0x08:
7096  case 0x09:
7097  case 0x0a:
7098  case 0x0b:
7099  case 0x0c:
7100  case 0x0d:
7101  case 0x0e:
7102  case 0x0f:
7103  case 0x10:
7104  case 0x11:
7105  case 0x12:
7106  case 0x13:
7107  case 0x14:
7108  case 0x15:
7109  case 0x16:
7110  case 0x17:
7111  {
7112  return v[current_idx];
7113  }
7114 
7115  case 0x18: // Unsigned integer (one-byte uint8_t follows)
7116  {
7117  idx += 1; // skip content byte
7118  return get_from_vector<uint8_t>(v, current_idx);
7119  }
7120 
7121  case 0x19: // Unsigned integer (two-byte uint16_t follows)
7122  {
7123  idx += 2; // skip 2 content bytes
7124  return get_from_vector<uint16_t>(v, current_idx);
7125  }
7126 
7127  case 0x1a: // Unsigned integer (four-byte uint32_t follows)
7128  {
7129  idx += 4; // skip 4 content bytes
7130  return get_from_vector<uint32_t>(v, current_idx);
7131  }
7132 
7133  case 0x1b: // Unsigned integer (eight-byte uint64_t follows)
7134  {
7135  idx += 8; // skip 8 content bytes
7136  return get_from_vector<uint64_t>(v, current_idx);
7137  }
7138 
7139  // Negative integer -1-0x00..-1-0x17 (-1..-24)
7140  case 0x20:
7141  case 0x21:
7142  case 0x22:
7143  case 0x23:
7144  case 0x24:
7145  case 0x25:
7146  case 0x26:
7147  case 0x27:
7148  case 0x28:
7149  case 0x29:
7150  case 0x2a:
7151  case 0x2b:
7152  case 0x2c:
7153  case 0x2d:
7154  case 0x2e:
7155  case 0x2f:
7156  case 0x30:
7157  case 0x31:
7158  case 0x32:
7159  case 0x33:
7160  case 0x34:
7161  case 0x35:
7162  case 0x36:
7163  case 0x37:
7164  {
7165  return static_cast<int8_t>(0x20 - 1 - v[current_idx]);
7166  }
7167 
7168  case 0x38: // Negative integer (one-byte uint8_t follows)
7169  {
7170  idx += 1; // skip content byte
7171  // must be uint8_t !
7172  return static_cast<number_integer_t>(-1) - get_from_vector<uint8_t>(v, current_idx);
7173  }
7174 
7175  case 0x39: // Negative integer -1-n (two-byte uint16_t follows)
7176  {
7177  idx += 2; // skip 2 content bytes
7178  return static_cast<number_integer_t>(-1) - get_from_vector<uint16_t>(v, current_idx);
7179  }
7180 
7181  case 0x3a: // Negative integer -1-n (four-byte uint32_t follows)
7182  {
7183  idx += 4; // skip 4 content bytes
7184  return static_cast<number_integer_t>(-1) - get_from_vector<uint32_t>(v, current_idx);
7185  }
7186 
7187  case 0x3b: // Negative integer -1-n (eight-byte uint64_t follows)
7188  {
7189  idx += 8; // skip 8 content bytes
7190  return static_cast<number_integer_t>(-1) - static_cast<number_integer_t>(get_from_vector<uint64_t>(v, current_idx));
7191  }
7192 
7193  // UTF-8 string (0x00..0x17 bytes follow)
7194  case 0x60:
7195  case 0x61:
7196  case 0x62:
7197  case 0x63:
7198  case 0x64:
7199  case 0x65:
7200  case 0x66:
7201  case 0x67:
7202  case 0x68:
7203  case 0x69:
7204  case 0x6a:
7205  case 0x6b:
7206  case 0x6c:
7207  case 0x6d:
7208  case 0x6e:
7209  case 0x6f:
7210  case 0x70:
7211  case 0x71:
7212  case 0x72:
7213  case 0x73:
7214  case 0x74:
7215  case 0x75:
7216  case 0x76:
7217  case 0x77:
7218  {
7219  const size_t len = v[current_idx] - 0x60;
7220  const size_t offset = current_idx + 1;
7221  idx += len; // skip content bytes
7222  return std::string(reinterpret_cast<const char*>(v.data()) + offset, len);
7223  }
7224 
7225  case 0x78: // UTF-8 string (one-byte uint8_t for n follows)
7226  {
7227  const auto len = get_from_vector<uint8_t>(v, current_idx);
7228  const size_t offset = current_idx + 2;
7229  idx += len + 1; // skip size byte + content bytes
7230  return std::string(reinterpret_cast<const char*>(v.data()) + offset, len);
7231  }
7232 
7233  case 0x79: // UTF-8 string (two-byte uint16_t for n follow)
7234  {
7235  const auto len = get_from_vector<uint16_t>(v, current_idx);
7236  const size_t offset = current_idx + 3;
7237  idx += len + 2; // skip 2 size bytes + content bytes
7238  return std::string(reinterpret_cast<const char*>(v.data()) + offset, len);
7239  }
7240 
7241  case 0x7a: // UTF-8 string (four-byte uint32_t for n follow)
7242  {
7243  const auto len = get_from_vector<uint32_t>(v, current_idx);
7244  const size_t offset = current_idx + 5;
7245  idx += len + 4; // skip 4 size bytes + content bytes
7246  return std::string(reinterpret_cast<const char*>(v.data()) + offset, len);
7247  }
7248 
7249  case 0x7b: // UTF-8 string (eight-byte uint64_t for n follow)
7250  {
7251  const auto len = get_from_vector<uint64_t>(v, current_idx);
7252  const size_t offset = current_idx + 9;
7253  idx += len + 8; // skip 8 size bytes + content bytes
7254  return std::string(reinterpret_cast<const char*>(v.data()) + offset, len);
7255  }
7256 
7257  case 0x7f: // UTF-8 string (indefinite length)
7258  {
7260  while (v[idx] != 0xff)
7261  {
7262  string_t s = from_cbor_internal(v, idx);
7263  result += s;
7264  }
7265  // skip break byte (0xFF)
7266  idx += 1;
7267  return result;
7268  }
7269 
7270  // array (0x00..0x17 data items follow)
7271  case 0x80:
7272  case 0x81:
7273  case 0x82:
7274  case 0x83:
7275  case 0x84:
7276  case 0x85:
7277  case 0x86:
7278  case 0x87:
7279  case 0x88:
7280  case 0x89:
7281  case 0x8a:
7282  case 0x8b:
7283  case 0x8c:
7284  case 0x8d:
7285  case 0x8e:
7286  case 0x8f:
7287  case 0x90:
7288  case 0x91:
7289  case 0x92:
7290  case 0x93:
7291  case 0x94:
7292  case 0x95:
7293  case 0x96:
7294  case 0x97:
7295  {
7297  const size_t len = v[current_idx] - 0x80;
7298  for (size_t i = 0; i < len; ++i)
7299  {
7300  result.push_back(from_cbor_internal(v, idx));
7301  }
7302  return result;
7303  }
7304 
7305  case 0x98: // array (one-byte uint8_t for n follows)
7306  {
7308  const auto len = get_from_vector<uint8_t>(v, current_idx);
7309  idx += 1; // skip 1 size byte
7310  for (size_t i = 0; i < len; ++i)
7311  {
7312  result.push_back(from_cbor_internal(v, idx));
7313  }
7314  return result;
7315  }
7316 
7317  case 0x99: // array (two-byte uint16_t for n follow)
7318  {
7320  const auto len = get_from_vector<uint16_t>(v, current_idx);
7321  idx += 2; // skip 4 size bytes
7322  for (size_t i = 0; i < len; ++i)
7323  {
7324  result.push_back(from_cbor_internal(v, idx));
7325  }
7326  return result;
7327  }
7328 
7329  case 0x9a: // array (four-byte uint32_t for n follow)
7330  {
7332  const auto len = get_from_vector<uint32_t>(v, current_idx);
7333  idx += 4; // skip 4 size bytes
7334  for (size_t i = 0; i < len; ++i)
7335  {
7336  result.push_back(from_cbor_internal(v, idx));
7337  }
7338  return result;
7339  }
7340 
7341  case 0x9b: // array (eight-byte uint64_t for n follow)
7342  {
7344  const auto len = get_from_vector<uint64_t>(v, current_idx);
7345  idx += 8; // skip 8 size bytes
7346  for (size_t i = 0; i < len; ++i)
7347  {
7348  result.push_back(from_cbor_internal(v, idx));
7349  }
7350  return result;
7351  }
7352 
7353  case 0x9f: // array (indefinite length)
7354  {
7356  while (v[idx] != 0xff)
7357  {
7358  result.push_back(from_cbor_internal(v, idx));
7359  }
7360  // skip break byte (0xFF)
7361  idx += 1;
7362  return result;
7363  }
7364 
7365  // map (0x00..0x17 pairs of data items follow)
7366  case 0xa0:
7367  case 0xa1:
7368  case 0xa2:
7369  case 0xa3:
7370  case 0xa4:
7371  case 0xa5:
7372  case 0xa6:
7373  case 0xa7:
7374  case 0xa8:
7375  case 0xa9:
7376  case 0xaa:
7377  case 0xab:
7378  case 0xac:
7379  case 0xad:
7380  case 0xae:
7381  case 0xaf:
7382  case 0xb0:
7383  case 0xb1:
7384  case 0xb2:
7385  case 0xb3:
7386  case 0xb4:
7387  case 0xb5:
7388  case 0xb6:
7389  case 0xb7:
7390  {
7392  const size_t len = v[current_idx] - 0xa0;
7393  for (size_t i = 0; i < len; ++i)
7394  {
7395  std::string key = from_cbor_internal(v, idx);
7396  result[key] = from_cbor_internal(v, idx);
7397  }
7398  return result;
7399  }
7400 
7401  case 0xb8: // map (one-byte uint8_t for n follows)
7402  {
7404  const auto len = get_from_vector<uint8_t>(v, current_idx);
7405  idx += 1; // skip 1 size byte
7406  for (size_t i = 0; i < len; ++i)
7407  {
7408  std::string key = from_cbor_internal(v, idx);
7409  result[key] = from_cbor_internal(v, idx);
7410  }
7411  return result;
7412  }
7413 
7414  case 0xb9: // map (two-byte uint16_t for n follow)
7415  {
7417  const auto len = get_from_vector<uint16_t>(v, current_idx);
7418  idx += 2; // skip 2 size bytes
7419  for (size_t i = 0; i < len; ++i)
7420  {
7421  std::string key = from_cbor_internal(v, idx);
7422  result[key] = from_cbor_internal(v, idx);
7423  }
7424  return result;
7425  }
7426 
7427  case 0xba: // map (four-byte uint32_t for n follow)
7428  {
7430  const auto len = get_from_vector<uint32_t>(v, current_idx);
7431  idx += 4; // skip 4 size bytes
7432  for (size_t i = 0; i < len; ++i)
7433  {
7434  std::string key = from_cbor_internal(v, idx);
7435  result[key] = from_cbor_internal(v, idx);
7436  }
7437  return result;
7438  }
7439 
7440  case 0xbb: // map (eight-byte uint64_t for n follow)
7441  {
7443  const auto len = get_from_vector<uint64_t>(v, current_idx);
7444  idx += 8; // skip 8 size bytes
7445  for (size_t i = 0; i < len; ++i)
7446  {
7447  std::string key = from_cbor_internal(v, idx);
7448  result[key] = from_cbor_internal(v, idx);
7449  }
7450  return result;
7451  }
7452 
7453  case 0xbf: // map (indefinite length)
7454  {
7456  while (v[idx] != 0xff)
7457  {
7458  std::string key = from_cbor_internal(v, idx);
7459  result[key] = from_cbor_internal(v, idx);
7460  }
7461  // skip break byte (0xFF)
7462  idx += 1;
7463  return result;
7464  }
7465 
7466  case 0xf4: // false
7467  {
7468  return false;
7469  }
7470 
7471  case 0xf5: // true
7472  {
7473  return true;
7474  }
7475 
7476  case 0xf6: // null
7477  {
7478  return value_t::null;
7479  }
7480 
7481  case 0xf9: // Half-Precision Float (two-byte IEEE 754)
7482  {
7483  idx += 2; // skip two content bytes
7484 
7485  // code from RFC 7049, Appendix D, Figure 3:
7486  // As half-precision floating-point numbers were only added to
7487  // IEEE 754 in 2008, today's programming platforms often still
7488  // only have limited support for them. It is very easy to
7489  // include at least decoding support for them even without such
7490  // support. An example of a small decoder for half-precision
7491  // floating-point numbers in the C language is shown in Fig. 3.
7492  const int half = (v[current_idx + 1] << 8) + v[current_idx + 2];
7493  const int exp = (half >> 10) & 0x1f;
7494  const int mant = half & 0x3ff;
7495  double val;
7496  if (exp == 0)
7497  {
7498  val = std::ldexp(mant, -24);
7499  }
7500  else if (exp != 31)
7501  {
7502  val = std::ldexp(mant + 1024, exp - 25);
7503  }
7504  else
7505  {
7506  val = mant == 0 ? INFINITY : NAN;
7507  }
7508  return half & 0x8000 ? -val : val;
7509  }
7510 
7511  case 0xfa: // Single-Precision Float (four-byte IEEE 754)
7512  {
7513  // copy bytes in reverse order into the float variable
7514  float res;
7515  for (size_t byte = 0; byte < sizeof(float); ++byte)
7516  {
7517  reinterpret_cast<uint8_t*>(&res)[sizeof(float) - byte - 1] = v[current_idx + 1 + byte];
7518  }
7519  idx += sizeof(float); // skip content bytes
7520  return res;
7521  }
7522 
7523  case 0xfb: // Double-Precision Float (eight-byte IEEE 754)
7524  {
7525  // copy bytes in reverse order into the double variable
7526  double res;
7527  for (size_t byte = 0; byte < sizeof(double); ++byte)
7528  {
7529  reinterpret_cast<uint8_t*>(&res)[sizeof(double) - byte - 1] = v[current_idx + 1 + byte];
7530  }
7531  idx += sizeof(double); // skip content bytes
7532  return res;
7533  }
7534 
7535  default: // anything else (0xFF is handled inside the other types)
7536  {
7537  throw std::invalid_argument("error parsing a CBOR @ " + std::to_string(current_idx) + ": " + std::to_string(v[current_idx]));
7538  }
7539  }
7540  }
7541 
7542  public:
7563  static std::vector<uint8_t> to_msgpack(const basic_json& j)
7564  {
7565  std::vector<uint8_t> result;
7566  to_msgpack_internal(j, result);
7567  return result;
7568  }
7569 
7592  static basic_json from_msgpack(const std::vector<uint8_t>& v)
7593  {
7594  size_t i = 0;
7595  return from_msgpack_internal(v, i);
7596  }
7597 
7619  static std::vector<uint8_t> to_cbor(const basic_json& j)
7620  {
7621  std::vector<uint8_t> result;
7622  to_cbor_internal(j, result);
7623  return result;
7624  }
7625 
7649  static basic_json from_cbor(const std::vector<uint8_t>& v)
7650  {
7651  size_t i = 0;
7652  return from_cbor_internal(v, i);
7653  }
7654 
7656 
7657  private:
7659  // convenience functions //
7661 
7675  {
7676  switch (m_type)
7677  {
7678  case value_t::null:
7679  return "null";
7680  case value_t::object:
7681  return "object";
7682  case value_t::array:
7683  return "array";
7684  case value_t::string:
7685  return "string";
7686  case value_t::boolean:
7687  return "boolean";
7688  case value_t::discarded:
7689  return "discarded";
7690  default:
7691  return "number";
7692  }
7693  }
7694 
7703  static std::size_t extra_space(const string_t& s) noexcept
7704  {
7705  return std::accumulate(s.begin(), s.end(), size_t{},
7706  [](size_t res, typename string_t::value_type c)
7707  {
7708  switch (c)
7709  {
7710  case '"':
7711  case '\\':
7712  case '\b':
7713  case '\f':
7714  case '\n':
7715  case '\r':
7716  case '\t':
7717  {
7718  // from c (1 byte) to \x (2 bytes)
7719  return res + 1;
7720  }
7721 
7722  default:
7723  {
7724  if (c >= 0x00 and c <= 0x1f)
7725  {
7726  // from c (1 byte) to \uxxxx (6 bytes)
7727  return res + 5;
7728  }
7729  else
7730  {
7731  return res;
7732  }
7733  }
7734  }
7735  });
7736  }
7737 
7752  {
7753  const auto space = extra_space(s);
7754  if (space == 0)
7755  {
7756  return s;
7757  }
7758 
7759  // create a result string of necessary size
7760  string_t result(s.size() + space, '\\');
7761  std::size_t pos = 0;
7762 
7763  for (const auto& c : s)
7764  {
7765  switch (c)
7766  {
7767  // quotation mark (0x22)
7768  case '"':
7769  {
7770  result[pos + 1] = '"';
7771  pos += 2;
7772  break;
7773  }
7774 
7775  // reverse solidus (0x5c)
7776  case '\\':
7777  {
7778  // nothing to change
7779  pos += 2;
7780  break;
7781  }
7782 
7783  // backspace (0x08)
7784  case '\b':
7785  {
7786  result[pos + 1] = 'b';
7787  pos += 2;
7788  break;
7789  }
7790 
7791  // formfeed (0x0c)
7792  case '\f':
7793  {
7794  result[pos + 1] = 'f';
7795  pos += 2;
7796  break;
7797  }
7798 
7799  // newline (0x0a)
7800  case '\n':
7801  {
7802  result[pos + 1] = 'n';
7803  pos += 2;
7804  break;
7805  }
7806 
7807  // carriage return (0x0d)
7808  case '\r':
7809  {
7810  result[pos + 1] = 'r';
7811  pos += 2;
7812  break;
7813  }
7814 
7815  // horizontal tab (0x09)
7816  case '\t':
7817  {
7818  result[pos + 1] = 't';
7819  pos += 2;
7820  break;
7821  }
7822 
7823  default:
7824  {
7825  if (c >= 0x00 and c <= 0x1f)
7826  {
7827  // convert a number 0..15 to its hex representation
7828  // (0..f)
7829  static const char hexify[16] =
7830  {
7831  '0', '1', '2', '3', '4', '5', '6', '7',
7832  '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'
7833  };
7834 
7835  // print character c as \uxxxx
7836  for (const char m :
7837  { 'u', '0', '0', hexify[c >> 4], hexify[c & 0x0f]
7838  })
7839  {
7840  result[++pos] = m;
7841  }
7842 
7843  ++pos;
7844  }
7845  else
7846  {
7847  // all other characters are added as-is
7848  result[pos++] = c;
7849  }
7850  break;
7851  }
7852  }
7853  }
7854 
7855  return result;
7856  }
7857 
7875  void dump(std::ostream& o,
7876  const bool pretty_print,
7877  const unsigned int indent_step,
7878  const unsigned int current_indent = 0) const
7879  {
7880  // variable to hold indentation for recursive calls
7881  unsigned int new_indent = current_indent;
7882 
7883  switch (m_type)
7884  {
7885  case value_t::object:
7886  {
7887  if (m_value.object->empty())
7888  {
7889  o << "{}";
7890  return;
7891  }
7892 
7893  o << "{";
7894 
7895  // increase indentation
7896  if (pretty_print)
7897  {
7898  new_indent += indent_step;
7899  o << "\n";
7900  }
7901 
7902  for (auto i = m_value.object->cbegin(); i != m_value.object->cend(); ++i)
7903  {
7904  if (i != m_value.object->cbegin())
7905  {
7906  o << (pretty_print ? ",\n" : ",");
7907  }
7908  o << string_t(new_indent, ' ') << "\""
7909  << escape_string(i->first) << "\":"
7910  << (pretty_print ? " " : "");
7911  i->second.dump(o, pretty_print, indent_step, new_indent);
7912  }
7913 
7914  // decrease indentation
7915  if (pretty_print)
7916  {
7917  new_indent -= indent_step;
7918  o << "\n";
7919  }
7920 
7921  o << string_t(new_indent, ' ') + "}";
7922  return;
7923  }
7924 
7925  case value_t::array:
7926  {
7927  if (m_value.array->empty())
7928  {
7929  o << "[]";
7930  return;
7931  }
7932 
7933  o << "[";
7934 
7935  // increase indentation
7936  if (pretty_print)
7937  {
7938  new_indent += indent_step;
7939  o << "\n";
7940  }
7941 
7942  for (auto i = m_value.array->cbegin(); i != m_value.array->cend(); ++i)
7943  {
7944  if (i != m_value.array->cbegin())
7945  {
7946  o << (pretty_print ? ",\n" : ",");
7947  }
7948  o << string_t(new_indent, ' ');
7949  i->dump(o, pretty_print, indent_step, new_indent);
7950  }
7951 
7952  // decrease indentation
7953  if (pretty_print)
7954  {
7955  new_indent -= indent_step;
7956  o << "\n";
7957  }
7958 
7959  o << string_t(new_indent, ' ') << "]";
7960  return;
7961  }
7962 
7963  case value_t::string:
7964  {
7965  o << string_t("\"") << escape_string(*m_value.string) << "\"";
7966  return;
7967  }
7968 
7969  case value_t::boolean:
7970  {
7971  o << (m_value.boolean ? "true" : "false");
7972  return;
7973  }
7974 
7975  case value_t::number_integer:
7976  {
7977  o << m_value.number_integer;
7978  return;
7979  }
7980 
7981  case value_t::number_unsigned:
7982  {
7983  o << m_value.number_unsigned;
7984  return;
7985  }
7986 
7987  case value_t::number_float:
7988  {
7989  if (m_value.number_float == 0)
7990  {
7991  // special case for zero to get "0.0"/"-0.0"
7992  o << (std::signbit(m_value.number_float) ? "-0.0" : "0.0");
7993  }
7994  else
7995  {
7996  o << m_value.number_float;
7997  }
7998  return;
7999  }
8000 
8001  case value_t::discarded:
8002  {
8003  o << "<discarded>";
8004  return;
8005  }
8006 
8007  case value_t::null:
8008  {
8009  o << "null";
8010  return;
8011  }
8012  }
8013  }
8014 
8015  private:
8017  // member variables //
8019 
8021  value_t m_type = value_t::null;
8022 
8024  json_value m_value = {};
8025 
8026 
8027  private:
8029  // iterators //
8031 
8042  {
8043  public:
8045  void set_begin() noexcept
8046  {
8047  m_it = begin_value;
8048  }
8049 
8051  void set_end() noexcept
8052  {
8053  m_it = end_value;
8054  }
8055 
8057  constexpr bool is_begin() const noexcept
8058  {
8059  return (m_it == begin_value);
8060  }
8061 
8063  constexpr bool is_end() const noexcept
8064  {
8065  return (m_it == end_value);
8066  }
8067 
8069  operator difference_type& () noexcept
8070  {
8071  return m_it;
8072  }
8073 
8075  constexpr operator difference_type () const noexcept
8076  {
8077  return m_it;
8078  }
8079 
8080  private:
8081  static constexpr difference_type begin_value = 0;
8082  static constexpr difference_type end_value = begin_value + 1;
8083 
8085  difference_type m_it = std::numeric_limits<std::ptrdiff_t>::denorm_min();
8086  };
8087 
8096  {
8098  typename object_t::iterator object_iterator;
8100  typename array_t::iterator array_iterator;
8103 
8106  : object_iterator(), array_iterator(), primitive_iterator()
8107  {}
8108  };
8109 
8111  template<typename IteratorType>
8112  class iteration_proxy
8113  {
8114  private:
8117  {
8118  private:
8120  IteratorType anchor;
8122  size_t array_index = 0;
8123 
8124  public:
8125  explicit iteration_proxy_internal(IteratorType it) noexcept
8126  : anchor(it)
8127  {}
8128 
8131  {
8132  return *this;
8133  }
8134 
8137  {
8138  ++anchor;
8139  ++array_index;
8140 
8141  return *this;
8142  }
8143 
8146  {
8147  return anchor != o.anchor;
8148  }
8149 
8151  typename basic_json::string_t key() const
8152  {
8153  assert(anchor.m_object != nullptr);
8154 
8155  switch (anchor.m_object->type())
8156  {
8157  // use integer array index as key
8158  case value_t::array:
8159  {
8160  return std::to_string(array_index);
8161  }
8162 
8163  // use key from the object
8164  case value_t::object:
8165  {
8166  return anchor.key();
8167  }
8168 
8169  // use an empty key for all primitive types
8170  default:
8171  {
8172  return "";
8173  }
8174  }
8175  }
8176 
8179  {
8180  return anchor.value();
8181  }
8182  };
8183 
8186 
8187  public:
8190  : container(cont)
8191  {}
8192 
8195  {
8196  return iteration_proxy_internal(container.begin());
8197  }
8198 
8201  {
8202  return iteration_proxy_internal(container.end());
8203  }
8204  };
8205 
8206  public:
8226  template<typename U>
8227  class iter_impl : public std::iterator<std::random_access_iterator_tag, U>
8228  {
8230  friend class basic_json;
8231 
8232  // make sure U is basic_json or const basic_json
8235  "iter_impl only accepts (const) basic_json");
8236 
8237  public:
8244  typename basic_json::const_pointer,
8248  typename basic_json::const_reference,
8251  using iterator_category = std::bidirectional_iterator_tag;
8252 
8254  iter_impl() = default;
8255 
8262  explicit iter_impl(pointer object) noexcept
8263  : m_object(object)
8264  {
8265  assert(m_object != nullptr);
8266 
8267  switch (m_object->m_type)
8268  {
8270  {
8271  m_it.object_iterator = typename object_t::iterator();
8272  break;
8273  }
8274 
8276  {
8277  m_it.array_iterator = typename array_t::iterator();
8278  break;
8279  }
8280 
8281  default:
8282  {
8283  m_it.primitive_iterator = primitive_iterator_t();
8284  break;
8285  }
8286  }
8287  }
8288 
8289  /*
8290  Use operator `const_iterator` instead of `const_iterator(const iterator&
8291  other) noexcept` to avoid two class definitions for @ref iterator and
8292  @ref const_iterator.
8293 
8294  This function is only called if this class is an @ref iterator. If this
8295  class is a @ref const_iterator this function is not called.
8296  */
8297  operator const_iterator() const
8298  {
8299  const_iterator ret;
8300 
8301  if (m_object)
8302  {
8303  ret.m_object = m_object;
8304  ret.m_it = m_it;
8305  }
8306 
8307  return ret;
8308  }
8309 
8315  iter_impl(const iter_impl& other) noexcept
8316  : m_object(other.m_object), m_it(other.m_it)
8317  {}
8318 
8324  iter_impl& operator=(iter_impl other) noexcept(
8329  )
8330  {
8331  std::swap(m_object, other.m_object);
8332  std::swap(m_it, other.m_it);
8333  return *this;
8334  }
8335 
8336  private:
8341  void set_begin() noexcept
8342  {
8343  assert(m_object != nullptr);
8344 
8345  switch (m_object->m_type)
8346  {
8348  {
8349  m_it.object_iterator = m_object->m_value.object->begin();
8350  break;
8351  }
8352 
8354  {
8355  m_it.array_iterator = m_object->m_value.array->begin();
8356  break;
8357  }
8358 
8360  {
8361  // set to end so begin()==end() is true: null is empty
8362  m_it.primitive_iterator.set_end();
8363  break;
8364  }
8365 
8366  default:
8367  {
8368  m_it.primitive_iterator.set_begin();
8369  break;
8370  }
8371  }
8372  }
8373 
8378  void set_end() noexcept
8379  {
8380  assert(m_object != nullptr);
8381 
8382  switch (m_object->m_type)
8383  {
8385  {
8386  m_it.object_iterator = m_object->m_value.object->end();
8387  break;
8388  }
8389 
8391  {
8392  m_it.array_iterator = m_object->m_value.array->end();
8393  break;
8394  }
8395 
8396  default:
8397  {
8398  m_it.primitive_iterator.set_end();
8399  break;
8400  }
8401  }
8402  }
8403 
8404  public:
8410  {
8411  assert(m_object != nullptr);
8412 
8413  switch (m_object->m_type)
8414  {
8416  {
8417  assert(m_it.object_iterator != m_object->m_value.object->end());
8418  return m_it.object_iterator->second;
8419  }
8420 
8422  {
8423  assert(m_it.array_iterator != m_object->m_value.array->end());
8424  return *m_it.array_iterator;
8425  }
8426 
8428  {
8429  throw std::out_of_range("cannot get value");
8430  }
8431 
8432  default:
8433  {
8434  if (m_it.primitive_iterator.is_begin())
8435  {
8436  return *m_object;
8437  }
8438  else
8439  {
8440  throw std::out_of_range("cannot get value");
8441  }
8442  }
8443  }
8444  }
8445 
8451  {
8452  assert(m_object != nullptr);
8453 
8454  switch (m_object->m_type)
8455  {
8457  {
8458  assert(m_it.object_iterator != m_object->m_value.object->end());
8459  return &(m_it.object_iterator->second);
8460  }
8461 
8463  {
8464  assert(m_it.array_iterator != m_object->m_value.array->end());
8465  return &*m_it.array_iterator;
8466  }
8467 
8468  default:
8469  {
8470  if (m_it.primitive_iterator.is_begin())
8471  {
8472  return m_object;
8473  }
8474  else
8475  {
8476  throw std::out_of_range("cannot get value");
8477  }
8478  }
8479  }
8480  }
8481 
8487  {
8488  auto result = *this;
8489  ++(*this);
8490  return result;
8491  }
8492 
8498  {
8499  assert(m_object != nullptr);
8500 
8501  switch (m_object->m_type)
8502  {
8504  {
8505  std::advance(m_it.object_iterator, 1);
8506  break;
8507  }
8508 
8510  {
8511  std::advance(m_it.array_iterator, 1);
8512  break;
8513  }
8514 
8515  default:
8516  {
8517  ++m_it.primitive_iterator;
8518  break;
8519  }
8520  }
8521 
8522  return *this;
8523  }
8524 
8530  {
8531  auto result = *this;
8532  --(*this);
8533  return result;
8534  }
8535 
8541  {
8542  assert(m_object != nullptr);
8543 
8544  switch (m_object->m_type)
8545  {
8547  {
8548  std::advance(m_it.object_iterator, -1);
8549  break;
8550  }
8551 
8553  {
8554  std::advance(m_it.array_iterator, -1);
8555  break;
8556  }
8557 
8558  default:
8559  {
8560  --m_it.primitive_iterator;
8561  break;
8562  }
8563  }
8564 
8565  return *this;
8566  }
8567 
8572  bool operator==(const iter_impl& other) const
8573  {
8574  // if objects are not the same, the comparison is undefined
8575  if (m_object != other.m_object)
8576  {
8577  throw std::domain_error("cannot compare iterators of different containers");
8578  }
8579 
8580  assert(m_object != nullptr);
8581 
8582  switch (m_object->m_type)
8583  {
8585  {
8586  return (m_it.object_iterator == other.m_it.object_iterator);
8587  }
8588 
8590  {
8591  return (m_it.array_iterator == other.m_it.array_iterator);
8592  }
8593 
8594  default:
8595  {
8596  return (m_it.primitive_iterator == other.m_it.primitive_iterator);
8597  }
8598  }
8599  }
8600 
8605  bool operator!=(const iter_impl& other) const
8606  {
8607  return not operator==(other);
8608  }
8609 
8614  bool operator<(const iter_impl& other) const
8615  {
8616  // if objects are not the same, the comparison is undefined
8617  if (m_object != other.m_object)
8618  {
8619  throw std::domain_error("cannot compare iterators of different containers");
8620  }
8621 
8622  assert(m_object != nullptr);
8623 
8624  switch (m_object->m_type)
8625  {
8627  {
8628  throw std::domain_error("cannot compare order of object iterators");
8629  }
8630 
8632  {
8633  return (m_it.array_iterator < other.m_it.array_iterator);
8634  }
8635 
8636  default:
8637  {
8638  return (m_it.primitive_iterator < other.m_it.primitive_iterator);
8639  }
8640  }
8641  }
8642 
8647  bool operator<=(const iter_impl& other) const
8648  {
8649  return not other.operator < (*this);
8650  }
8651 
8656  bool operator>(const iter_impl& other) const
8657  {
8658  return not operator<=(other);
8659  }
8660 
8665  bool operator>=(const iter_impl& other) const
8666  {
8667  return not operator<(other);
8668  }
8669 
8675  {
8676  assert(m_object != nullptr);
8677 
8678  switch (m_object->m_type)
8679  {
8681  {
8682  throw std::domain_error("cannot use offsets with object iterators");
8683  }
8684 
8686  {
8687  std::advance(m_it.array_iterator, i);
8688  break;
8689  }
8690 
8691  default:
8692  {
8693  m_it.primitive_iterator += i;
8694  break;
8695  }
8696  }
8697 
8698  return *this;
8699  }
8700 
8706  {
8707  return operator+=(-i);
8708  }
8709 
8715  {
8716  auto result = *this;
8717  result += i;
8718  return result;
8719  }
8720 
8726  {
8727  auto result = *this;
8728  result -= i;
8729  return result;
8730  }
8731 
8737  {
8738  assert(m_object != nullptr);
8739 
8740  switch (m_object->m_type)
8741  {
8743  {
8744  throw std::domain_error("cannot use offsets with object iterators");
8745  }
8746 
8748  {
8749  return m_it.array_iterator - other.m_it.array_iterator;
8750  }
8751 
8752  default:
8753  {
8754  return m_it.primitive_iterator - other.m_it.primitive_iterator;
8755  }
8756  }
8757  }
8758 
8764  {
8765  assert(m_object != nullptr);
8766 
8767  switch (m_object->m_type)
8768  {
8770  {
8771  throw std::domain_error("cannot use operator[] for object iterators");
8772  }
8773 
8775  {
8776  return *std::next(m_it.array_iterator, n);
8777  }
8778 
8780  {
8781  throw std::out_of_range("cannot get value");
8782  }
8783 
8784  default:
8785  {
8786  if (m_it.primitive_iterator == -n)
8787  {
8788  return *m_object;
8789  }
8790  else
8791  {
8792  throw std::out_of_range("cannot get value");
8793  }
8794  }
8795  }
8796  }
8797 
8802  typename object_t::key_type key() const
8803  {
8804  assert(m_object != nullptr);
8805 
8806  if (m_object->is_object())
8807  {
8808  return m_it.object_iterator->first;
8809  }
8810  else
8811  {
8812  throw std::domain_error("cannot use key() for non-object iterators");
8813  }
8814  }
8815 
8821  {
8822  return operator*();
8823  }
8824 
8825  private:
8827  pointer m_object = nullptr;
8830  };
8831 
8849  template<typename Base>
8850  class json_reverse_iterator : public std::reverse_iterator<Base>
8851  {
8852  public:
8854  using base_iterator = std::reverse_iterator<Base>;
8856  using reference = typename Base::reference;
8857 
8859  json_reverse_iterator(const typename base_iterator::iterator_type& it) noexcept
8860  : base_iterator(it)
8861  {}
8862 
8865  : base_iterator(it)
8866  {}
8867 
8870  {
8871  return base_iterator::operator++(1);
8872  }
8873 
8876  {
8878  return *this;
8879  }
8880 
8883  {
8884  return base_iterator::operator--(1);
8885  }
8886 
8889  {
8890  base_iterator::operator--();
8891  return *this;
8892  }
8893 
8896  {
8898  return *this;
8899  }
8900 
8903  {
8904  auto result = *this;
8905  result += i;
8906  return result;
8907  }
8908 
8911  {
8912  auto result = *this;
8913  result -= i;
8914  return result;
8915  }
8916 
8919  {
8920  return this->base() - other.base();
8921  }
8922 
8925  {
8926  return *(this->operator+(n));
8927  }
8928 
8930  typename object_t::key_type key() const
8931  {
8932  auto it = --this->base();
8933  return it.key();
8934  }
8935 
8938  {
8939  auto it = --this->base();
8940  return it.operator * ();
8941  }
8942  };
8943 
8944 
8945  private:
8947  // lexer and parser //
8949 
8957  class lexer
8958  {
8959  public:
8961  enum class token_type
8962  {
8963  uninitialized,
8964  literal_true,
8965  literal_false,
8966  literal_null,
8967  value_string,
8968  value_number,
8969  begin_array,
8970  begin_object,
8971  end_array,
8972  end_object,
8973  name_separator,
8974  value_separator,
8975  parse_error,
8976  end_of_input
8977  };
8978 
8980  using lexer_char_t = unsigned char;
8981 
8983  lexer(const lexer_char_t* buff, const size_t len) noexcept
8984  : m_content(buff)
8985  {
8986  assert(m_content != nullptr);
8987  m_start = m_cursor = m_content;
8988  m_limit = m_content + len;
8989  }
8990 
8992  explicit lexer(std::istream& s)
8993  : m_stream(&s), m_line_buffer()
8994  {
8995  // immediately abort if stream is erroneous
8996  if (s.fail())
8997  {
8998  throw std::invalid_argument("stream error: " + std::string(strerror(errno)));
8999  }
9000 
9001  // fill buffer
9002  fill_line_buffer();
9003 
9004  // skip UTF-8 byte-order mark
9005  if (m_line_buffer.size() >= 3 and m_line_buffer.substr(0, 3) == "\xEF\xBB\xBF")
9006  {
9007  m_line_buffer[0] = ' ';
9008  m_line_buffer[1] = ' ';
9009  m_line_buffer[2] = ' ';
9010  }
9011  }
9012 
9013  // switch off unwanted functions (due to pointer members)
9014  lexer() = delete;
9015  lexer(const lexer&) = delete;
9016  lexer operator=(const lexer&) = delete;
9017 
9041  static string_t to_unicode(const std::size_t codepoint1,
9042  const std::size_t codepoint2 = 0)
9043  {
9044  // calculate the code point from the given code points
9045  std::size_t codepoint = codepoint1;
9046 
9047  // check if codepoint1 is a high surrogate
9048  if (codepoint1 >= 0xD800 and codepoint1 <= 0xDBFF)
9049  {
9050  // check if codepoint2 is a low surrogate
9051  if (codepoint2 >= 0xDC00 and codepoint2 <= 0xDFFF)
9052  {
9053  codepoint =
9054  // high surrogate occupies the most significant 22 bits
9055  (codepoint1 << 10)
9056  // low surrogate occupies the least significant 15 bits
9057  + codepoint2
9058  // there is still the 0xD800, 0xDC00 and 0x10000 noise
9059  // in the result so we have to subtract with:
9060  // (0xD800 << 10) + DC00 - 0x10000 = 0x35FDC00
9061  - 0x35FDC00;
9062  }
9063  else
9064  {
9065  throw std::invalid_argument("missing or wrong low surrogate");
9066  }
9067  }
9068 
9069  string_t result;
9070 
9071  if (codepoint < 0x80)
9072  {
9073  // 1-byte characters: 0xxxxxxx (ASCII)
9074  result.append(1, static_cast<typename string_t::value_type>(codepoint));
9075  }
9076  else if (codepoint <= 0x7ff)
9077  {
9078  // 2-byte characters: 110xxxxx 10xxxxxx
9079  result.append(1, static_cast<typename string_t::value_type>(0xC0 | ((codepoint >> 6) & 0x1F)));
9080  result.append(1, static_cast<typename string_t::value_type>(0x80 | (codepoint & 0x3F)));
9081  }
9082  else if (codepoint <= 0xffff)
9083  {
9084  // 3-byte characters: 1110xxxx 10xxxxxx 10xxxxxx
9085  result.append(1, static_cast<typename string_t::value_type>(0xE0 | ((codepoint >> 12) & 0x0F)));
9086  result.append(1, static_cast<typename string_t::value_type>(0x80 | ((codepoint >> 6) & 0x3F)));
9087  result.append(1, static_cast<typename string_t::value_type>(0x80 | (codepoint & 0x3F)));
9088  }
9089  else if (codepoint <= 0x10ffff)
9090  {
9091  // 4-byte characters: 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
9092  result.append(1, static_cast<typename string_t::value_type>(0xF0 | ((codepoint >> 18) & 0x07)));
9093  result.append(1, static_cast<typename string_t::value_type>(0x80 | ((codepoint >> 12) & 0x3F)));
9094  result.append(1, static_cast<typename string_t::value_type>(0x80 | ((codepoint >> 6) & 0x3F)));
9095  result.append(1, static_cast<typename string_t::value_type>(0x80 | (codepoint & 0x3F)));
9096  }
9097  else
9098  {
9099  throw std::out_of_range("code points above 0x10FFFF are invalid");
9100  }
9101 
9102  return result;
9103  }
9104 
9107  {
9108  switch (t)
9109  {
9110  case token_type::uninitialized:
9111  return "<uninitialized>";
9112  case token_type::literal_true:
9113  return "true literal";
9114  case token_type::literal_false:
9115  return "false literal";
9116  case token_type::literal_null:
9117  return "null literal";
9118  case token_type::value_string:
9119  return "string literal";
9120  case token_type::value_number:
9121  return "number literal";
9122  case token_type::begin_array:
9123  return "'['";
9124  case token_type::begin_object:
9125  return "'{'";
9126  case token_type::end_array:
9127  return "']'";
9128  case token_type::end_object:
9129  return "'}'";
9130  case token_type::name_separator:
9131  return "':'";
9132  case token_type::value_separator:
9133  return "','";
9134  case token_type::parse_error:
9135  return "<parse error>";
9136  case token_type::end_of_input:
9137  return "end of input";
9138  default:
9139  {
9140  // catch non-enum values
9141  return "unknown token"; // LCOV_EXCL_LINE
9142  }
9143  }
9144  }
9145 
9168  {
9169  while (true)
9170  {
9171  // pointer for backtracking information
9172  m_marker = nullptr;
9173 
9174  // remember the begin of the token
9175  m_start = m_cursor;
9176  assert(m_start != nullptr);
9177 
9178 
9179  {
9180  lexer_char_t yych;
9181  unsigned int yyaccept = 0;
9182  static const unsigned char yybm[] =
9183  {
9184  0, 0, 0, 0, 0, 0, 0, 0,
9185  0, 32, 32, 0, 0, 32, 0, 0,
9186  0, 0, 0, 0, 0, 0, 0, 0,
9187  0, 0, 0, 0, 0, 0, 0, 0,
9188  160, 128, 0, 128, 128, 128, 128, 128,
9189  128, 128, 128, 128, 128, 128, 128, 128,
9190  192, 192, 192, 192, 192, 192, 192, 192,
9191  192, 192, 128, 128, 128, 128, 128, 128,
9192  128, 128, 128, 128, 128, 128, 128, 128,
9193  128, 128, 128, 128, 128, 128, 128, 128,
9194  128, 128, 128, 128, 128, 128, 128, 128,
9195  128, 128, 128, 128, 0, 128, 128, 128,
9196  128, 128, 128, 128, 128, 128, 128, 128,
9197  128, 128, 128, 128, 128, 128, 128, 128,
9198  128, 128, 128, 128, 128, 128, 128, 128,
9199  128, 128, 128, 128, 128, 128, 128, 128,
9200  0, 0, 0, 0, 0, 0, 0, 0,
9201  0, 0, 0, 0, 0, 0, 0, 0,
9202  0, 0, 0, 0, 0, 0, 0, 0,
9203  0, 0, 0, 0, 0, 0, 0, 0,
9204  0, 0, 0, 0, 0, 0, 0, 0,
9205  0, 0, 0, 0, 0, 0, 0, 0,
9206  0, 0, 0, 0, 0, 0, 0, 0,
9207  0, 0, 0, 0, 0, 0, 0, 0,
9208  0, 0, 0, 0, 0, 0, 0, 0,
9209  0, 0, 0, 0, 0, 0, 0, 0,
9210  0, 0, 0, 0, 0, 0, 0, 0,
9211  0, 0, 0, 0, 0, 0, 0, 0,
9212  0, 0, 0, 0, 0, 0, 0, 0,
9213  0, 0, 0, 0, 0, 0, 0, 0,
9214  0, 0, 0, 0, 0, 0, 0, 0,
9215  0, 0, 0, 0, 0, 0, 0, 0,
9216  };
9217  if ((m_limit - m_cursor) < 5)
9218  {
9219  fill_line_buffer(5); // LCOV_EXCL_LINE
9220  }
9221  yych = *m_cursor;
9222  if (yybm[0 + yych] & 32)
9223  {
9224  goto basic_json_parser_6;
9225  }
9226  if (yych <= '[')
9227  {
9228  if (yych <= '-')
9229  {
9230  if (yych <= '"')
9231  {
9232  if (yych <= 0x00)
9233  {
9234  goto basic_json_parser_2;
9235  }
9236  if (yych <= '!')
9237  {
9238  goto basic_json_parser_4;
9239  }
9240  goto basic_json_parser_9;
9241  }
9242  else
9243  {
9244  if (yych <= '+')
9245  {
9246  goto basic_json_parser_4;
9247  }
9248  if (yych <= ',')
9249  {
9250  goto basic_json_parser_10;
9251  }
9252  goto basic_json_parser_12;
9253  }
9254  }
9255  else
9256  {
9257  if (yych <= '9')
9258  {
9259  if (yych <= '/')
9260  {
9261  goto basic_json_parser_4;
9262  }
9263  if (yych <= '0')
9264  {
9265  goto basic_json_parser_13;
9266  }
9267  goto basic_json_parser_15;
9268  }
9269  else
9270  {
9271  if (yych <= ':')
9272  {
9273  goto basic_json_parser_17;
9274  }
9275  if (yych <= 'Z')
9276  {
9277  goto basic_json_parser_4;
9278  }
9279  goto basic_json_parser_19;
9280  }
9281  }
9282  }
9283  else
9284  {
9285  if (yych <= 'n')
9286  {
9287  if (yych <= 'e')
9288  {
9289  if (yych == ']')
9290  {
9291  goto basic_json_parser_21;
9292  }
9293  goto basic_json_parser_4;
9294  }
9295  else
9296  {
9297  if (yych <= 'f')
9298  {
9299  goto basic_json_parser_23;
9300  }
9301  if (yych <= 'm')
9302  {
9303  goto basic_json_parser_4;
9304  }
9305  goto basic_json_parser_24;
9306  }
9307  }
9308  else
9309  {
9310  if (yych <= 'z')
9311  {
9312  if (yych == 't')
9313  {
9314  goto basic_json_parser_25;
9315  }
9316  goto basic_json_parser_4;
9317  }
9318  else
9319  {
9320  if (yych <= '{')
9321  {
9322  goto basic_json_parser_26;
9323  }
9324  if (yych == '}')
9325  {
9326  goto basic_json_parser_28;
9327  }
9328  goto basic_json_parser_4;
9329  }
9330  }
9331  }
9332 basic_json_parser_2:
9333  ++m_cursor;
9334  {
9335  last_token_type = token_type::end_of_input;
9336  break;
9337  }
9338 basic_json_parser_4:
9339  ++m_cursor;
9340 basic_json_parser_5:
9341  {
9342  last_token_type = token_type::parse_error;
9343  break;
9344  }
9345 basic_json_parser_6:
9346  ++m_cursor;
9347  if (m_limit <= m_cursor)
9348  {
9349  fill_line_buffer(1); // LCOV_EXCL_LINE
9350  }
9351  yych = *m_cursor;
9352  if (yybm[0 + yych] & 32)
9353  {
9354  goto basic_json_parser_6;
9355  }
9356  {
9357  continue;
9358  }
9359 basic_json_parser_9:
9360  yyaccept = 0;
9361  yych = *(m_marker = ++m_cursor);
9362  if (yych <= 0x1F)
9363  {
9364  goto basic_json_parser_5;
9365  }
9366  if (yych <= 0x7F)
9367  {
9368  goto basic_json_parser_31;
9369  }
9370  if (yych <= 0xC1)
9371  {
9372  goto basic_json_parser_5;
9373  }
9374  if (yych <= 0xF4)
9375  {
9376  goto basic_json_parser_31;
9377  }
9378  goto basic_json_parser_5;
9379 basic_json_parser_10:
9380  ++m_cursor;
9381  {
9382  last_token_type = token_type::value_separator;
9383  break;
9384  }
9385 basic_json_parser_12:
9386  yych = *++m_cursor;
9387  if (yych <= '/')
9388  {
9389  goto basic_json_parser_5;
9390  }
9391  if (yych <= '0')
9392  {
9393  goto basic_json_parser_13;
9394  }
9395  if (yych <= '9')
9396  {
9397  goto basic_json_parser_15;
9398  }
9399  goto basic_json_parser_5;
9400 basic_json_parser_13:
9401  yyaccept = 1;
9402  yych = *(m_marker = ++m_cursor);
9403  if (yych <= 'D')
9404  {
9405  if (yych == '.')
9406  {
9407  goto basic_json_parser_43;
9408  }
9409  }
9410  else
9411  {
9412  if (yych <= 'E')
9413  {
9414  goto basic_json_parser_44;
9415  }
9416  if (yych == 'e')
9417  {
9418  goto basic_json_parser_44;
9419  }
9420  }
9421 basic_json_parser_14:
9422  {
9423  last_token_type = token_type::value_number;
9424  break;
9425  }
9426 basic_json_parser_15:
9427  yyaccept = 1;
9428  m_marker = ++m_cursor;
9429  if ((m_limit - m_cursor) < 3)
9430  {
9431  fill_line_buffer(3); // LCOV_EXCL_LINE
9432  }
9433  yych = *m_cursor;
9434  if (yybm[0 + yych] & 64)
9435  {
9436  goto basic_json_parser_15;
9437  }
9438  if (yych <= 'D')
9439  {
9440  if (yych == '.')
9441  {
9442  goto basic_json_parser_43;
9443  }
9444  goto basic_json_parser_14;
9445  }
9446  else
9447  {
9448  if (yych <= 'E')
9449  {
9450  goto basic_json_parser_44;
9451  }
9452  if (yych == 'e')
9453  {
9454  goto basic_json_parser_44;
9455  }
9456  goto basic_json_parser_14;
9457  }
9458 basic_json_parser_17:
9459  ++m_cursor;
9460  {
9461  last_token_type = token_type::name_separator;
9462  break;
9463  }
9464 basic_json_parser_19:
9465  ++m_cursor;
9466  {
9467  last_token_type = token_type::begin_array;
9468  break;
9469  }
9470 basic_json_parser_21:
9471  ++m_cursor;
9472  {
9473  last_token_type = token_type::end_array;
9474  break;
9475  }
9476 basic_json_parser_23:
9477  yyaccept = 0;
9478  yych = *(m_marker = ++m_cursor);
9479  if (yych == 'a')
9480  {
9481  goto basic_json_parser_45;
9482  }
9483  goto basic_json_parser_5;
9484 basic_json_parser_24:
9485  yyaccept = 0;
9486  yych = *(m_marker = ++m_cursor);
9487  if (yych == 'u')
9488  {
9489  goto basic_json_parser_46;
9490  }
9491  goto basic_json_parser_5;
9492 basic_json_parser_25:
9493  yyaccept = 0;
9494  yych = *(m_marker = ++m_cursor);
9495  if (yych == 'r')
9496  {
9497  goto basic_json_parser_47;
9498  }
9499  goto basic_json_parser_5;
9500 basic_json_parser_26:
9501  ++m_cursor;
9502  {
9503  last_token_type = token_type::begin_object;
9504  break;
9505  }
9506 basic_json_parser_28:
9507  ++m_cursor;
9508  {
9509  last_token_type = token_type::end_object;
9510  break;
9511  }
9512 basic_json_parser_30:
9513  ++m_cursor;
9514  if (m_limit <= m_cursor)
9515  {
9516  fill_line_buffer(1); // LCOV_EXCL_LINE
9517  }
9518  yych = *m_cursor;
9519 basic_json_parser_31:
9520  if (yybm[0 + yych] & 128)
9521  {
9522  goto basic_json_parser_30;
9523  }
9524  if (yych <= 0xE0)
9525  {
9526  if (yych <= '\\')
9527  {
9528  if (yych <= 0x1F)
9529  {
9530  goto basic_json_parser_32;
9531  }
9532  if (yych <= '"')
9533  {
9534  goto basic_json_parser_33;
9535  }
9536  goto basic_json_parser_35;
9537  }
9538  else
9539  {
9540  if (yych <= 0xC1)
9541  {
9542  goto basic_json_parser_32;
9543  }
9544  if (yych <= 0xDF)
9545  {
9546  goto basic_json_parser_36;
9547  }
9548  goto basic_json_parser_37;
9549  }
9550  }
9551  else
9552  {
9553  if (yych <= 0xEF)
9554  {
9555  if (yych == 0xED)
9556  {
9557  goto basic_json_parser_39;
9558  }
9559  goto basic_json_parser_38;
9560  }
9561  else
9562  {
9563  if (yych <= 0xF0)
9564  {
9565  goto basic_json_parser_40;
9566  }
9567  if (yych <= 0xF3)
9568  {
9569  goto basic_json_parser_41;
9570  }
9571  if (yych <= 0xF4)
9572  {
9573  goto basic_json_parser_42;
9574  }
9575  }
9576  }
9577 basic_json_parser_32:
9578  m_cursor = m_marker;
9579  if (yyaccept == 0)
9580  {
9581  goto basic_json_parser_5;
9582  }
9583  else
9584  {
9585  goto basic_json_parser_14;
9586  }
9587 basic_json_parser_33:
9588  ++m_cursor;
9589  {
9590  last_token_type = token_type::value_string;
9591  break;
9592  }
9593 basic_json_parser_35:
9594  ++m_cursor;
9595  if (m_limit <= m_cursor)
9596  {
9597  fill_line_buffer(1); // LCOV_EXCL_LINE
9598  }
9599  yych = *m_cursor;
9600  if (yych <= 'e')
9601  {
9602  if (yych <= '/')
9603  {
9604  if (yych == '"')
9605  {
9606  goto basic_json_parser_30;
9607  }
9608  if (yych <= '.')
9609  {
9610  goto basic_json_parser_32;
9611  }
9612  goto basic_json_parser_30;
9613  }
9614  else
9615  {
9616  if (yych <= '\\')
9617  {
9618  if (yych <= '[')
9619  {
9620  goto basic_json_parser_32;
9621  }
9622  goto basic_json_parser_30;
9623  }
9624  else
9625  {
9626  if (yych == 'b')
9627  {
9628  goto basic_json_parser_30;
9629  }
9630  goto basic_json_parser_32;
9631  }
9632  }
9633  }
9634  else
9635  {
9636  if (yych <= 'q')
9637  {
9638  if (yych <= 'f')
9639  {
9640  goto basic_json_parser_30;
9641  }
9642  if (yych == 'n')
9643  {
9644  goto basic_json_parser_30;
9645  }
9646  goto basic_json_parser_32;
9647  }
9648  else
9649  {
9650  if (yych <= 's')
9651  {
9652  if (yych <= 'r')
9653  {
9654  goto basic_json_parser_30;
9655  }
9656  goto basic_json_parser_32;
9657  }
9658  else
9659  {
9660  if (yych <= 't')
9661  {
9662  goto basic_json_parser_30;
9663  }
9664  if (yych <= 'u')
9665  {
9666  goto basic_json_parser_48;
9667  }
9668  goto basic_json_parser_32;
9669  }
9670  }
9671  }
9672 basic_json_parser_36:
9673  ++m_cursor;
9674  if (m_limit <= m_cursor)
9675  {
9676  fill_line_buffer(1); // LCOV_EXCL_LINE
9677  }
9678  yych = *m_cursor;
9679  if (yych <= 0x7F)
9680  {
9681  goto basic_json_parser_32;
9682  }
9683  if (yych <= 0xBF)
9684  {
9685  goto basic_json_parser_30;
9686  }
9687  goto basic_json_parser_32;
9688 basic_json_parser_37:
9689  ++m_cursor;
9690  if (m_limit <= m_cursor)
9691  {
9692  fill_line_buffer(1); // LCOV_EXCL_LINE
9693  }
9694  yych = *m_cursor;
9695  if (yych <= 0x9F)
9696  {
9697  goto basic_json_parser_32;
9698  }
9699  if (yych <= 0xBF)
9700  {
9701  goto basic_json_parser_36;
9702  }
9703  goto basic_json_parser_32;
9704 basic_json_parser_38:
9705  ++m_cursor;
9706  if (m_limit <= m_cursor)
9707  {
9708  fill_line_buffer(1); // LCOV_EXCL_LINE
9709  }
9710  yych = *m_cursor;
9711  if (yych <= 0x7F)
9712  {
9713  goto basic_json_parser_32;
9714  }
9715  if (yych <= 0xBF)
9716  {
9717  goto basic_json_parser_36;
9718  }
9719  goto basic_json_parser_32;
9720 basic_json_parser_39:
9721  ++m_cursor;
9722  if (m_limit <= m_cursor)
9723  {
9724  fill_line_buffer(1); // LCOV_EXCL_LINE
9725  }
9726  yych = *m_cursor;
9727  if (yych <= 0x7F)
9728  {
9729  goto basic_json_parser_32;
9730  }
9731  if (yych <= 0x9F)
9732  {
9733  goto basic_json_parser_36;
9734  }
9735  goto basic_json_parser_32;
9736 basic_json_parser_40:
9737  ++m_cursor;
9738  if (m_limit <= m_cursor)
9739  {
9740  fill_line_buffer(1); // LCOV_EXCL_LINE
9741  }
9742  yych = *m_cursor;
9743  if (yych <= 0x8F)
9744  {
9745  goto basic_json_parser_32;
9746  }
9747  if (yych <= 0xBF)
9748  {
9749  goto basic_json_parser_38;
9750  }
9751  goto basic_json_parser_32;
9752 basic_json_parser_41:
9753  ++m_cursor;
9754  if (m_limit <= m_cursor)
9755  {
9756  fill_line_buffer(1); // LCOV_EXCL_LINE
9757  }
9758  yych = *m_cursor;
9759  if (yych <= 0x7F)
9760  {
9761  goto basic_json_parser_32;
9762  }
9763  if (yych <= 0xBF)
9764  {
9765  goto basic_json_parser_38;
9766  }
9767  goto basic_json_parser_32;
9768 basic_json_parser_42:
9769  ++m_cursor;
9770  if (m_limit <= m_cursor)
9771  {
9772  fill_line_buffer(1); // LCOV_EXCL_LINE
9773  }
9774  yych = *m_cursor;
9775  if (yych <= 0x7F)
9776  {
9777  goto basic_json_parser_32;
9778  }
9779  if (yych <= 0x8F)
9780  {
9781  goto basic_json_parser_38;
9782  }
9783  goto basic_json_parser_32;
9784 basic_json_parser_43:
9785  yych = *++m_cursor;
9786  if (yych <= '/')
9787  {
9788  goto basic_json_parser_32;
9789  }
9790  if (yych <= '9')
9791  {
9792  goto basic_json_parser_49;
9793  }
9794  goto basic_json_parser_32;
9795 basic_json_parser_44:
9796  yych = *++m_cursor;
9797  if (yych <= ',')
9798  {
9799  if (yych == '+')
9800  {
9801  goto basic_json_parser_51;
9802  }
9803  goto basic_json_parser_32;
9804  }
9805  else
9806  {
9807  if (yych <= '-')
9808  {
9809  goto basic_json_parser_51;
9810  }
9811  if (yych <= '/')
9812  {
9813  goto basic_json_parser_32;
9814  }
9815  if (yych <= '9')
9816  {
9817  goto basic_json_parser_52;
9818  }
9819  goto basic_json_parser_32;
9820  }
9821 basic_json_parser_45:
9822  yych = *++m_cursor;
9823  if (yych == 'l')
9824  {
9825  goto basic_json_parser_54;
9826  }
9827  goto basic_json_parser_32;
9828 basic_json_parser_46:
9829  yych = *++m_cursor;
9830  if (yych == 'l')
9831  {
9832  goto basic_json_parser_55;
9833  }
9834  goto basic_json_parser_32;
9835 basic_json_parser_47:
9836  yych = *++m_cursor;
9837  if (yych == 'u')
9838  {
9839  goto basic_json_parser_56;
9840  }
9841  goto basic_json_parser_32;
9842 basic_json_parser_48:
9843  ++m_cursor;
9844  if (m_limit <= m_cursor)
9845  {
9846  fill_line_buffer(1); // LCOV_EXCL_LINE
9847  }
9848  yych = *m_cursor;
9849  if (yych <= '@')
9850  {
9851  if (yych <= '/')
9852  {
9853  goto basic_json_parser_32;
9854  }
9855  if (yych <= '9')
9856  {
9857  goto basic_json_parser_57;
9858  }
9859  goto basic_json_parser_32;
9860  }
9861  else
9862  {
9863  if (yych <= 'F')
9864  {
9865  goto basic_json_parser_57;
9866  }
9867  if (yych <= '`')
9868  {
9869  goto basic_json_parser_32;
9870  }
9871  if (yych <= 'f')
9872  {
9873  goto basic_json_parser_57;
9874  }
9875  goto basic_json_parser_32;
9876  }
9877 basic_json_parser_49:
9878  yyaccept = 1;
9879  m_marker = ++m_cursor;
9880  if ((m_limit - m_cursor) < 3)
9881  {
9882  fill_line_buffer(3); // LCOV_EXCL_LINE
9883  }
9884  yych = *m_cursor;
9885  if (yych <= 'D')
9886  {
9887  if (yych <= '/')
9888  {
9889  goto basic_json_parser_14;
9890  }
9891  if (yych <= '9')
9892  {
9893  goto basic_json_parser_49;
9894  }
9895  goto basic_json_parser_14;
9896  }
9897  else
9898  {
9899  if (yych <= 'E')
9900  {
9901  goto basic_json_parser_44;
9902  }
9903  if (yych == 'e')
9904  {
9905  goto basic_json_parser_44;
9906  }
9907  goto basic_json_parser_14;
9908  }
9909 basic_json_parser_51:
9910  yych = *++m_cursor;
9911  if (yych <= '/')
9912  {
9913  goto basic_json_parser_32;
9914  }
9915  if (yych >= ':')
9916  {
9917  goto basic_json_parser_32;
9918  }
9919 basic_json_parser_52:
9920  ++m_cursor;
9921  if (m_limit <= m_cursor)
9922  {
9923  fill_line_buffer(1); // LCOV_EXCL_LINE
9924  }
9925  yych = *m_cursor;
9926  if (yych <= '/')
9927  {
9928  goto basic_json_parser_14;
9929  }
9930  if (yych <= '9')
9931  {
9932  goto basic_json_parser_52;
9933  }
9934  goto basic_json_parser_14;
9935 basic_json_parser_54:
9936  yych = *++m_cursor;
9937  if (yych == 's')
9938  {
9939  goto basic_json_parser_58;
9940  }
9941  goto basic_json_parser_32;
9942 basic_json_parser_55:
9943  yych = *++m_cursor;
9944  if (yych == 'l')
9945  {
9946  goto basic_json_parser_59;
9947  }
9948  goto basic_json_parser_32;
9949 basic_json_parser_56:
9950  yych = *++m_cursor;
9951  if (yych == 'e')
9952  {
9953  goto basic_json_parser_61;
9954  }
9955  goto basic_json_parser_32;
9956 basic_json_parser_57:
9957  ++m_cursor;
9958  if (m_limit <= m_cursor)
9959  {
9960  fill_line_buffer(1); // LCOV_EXCL_LINE
9961  }
9962  yych = *m_cursor;
9963  if (yych <= '@')
9964  {
9965  if (yych <= '/')
9966  {
9967  goto basic_json_parser_32;
9968  }
9969  if (yych <= '9')
9970  {
9971  goto basic_json_parser_63;
9972  }
9973  goto basic_json_parser_32;
9974  }
9975  else
9976  {
9977  if (yych <= 'F')
9978  {
9979  goto basic_json_parser_63;
9980  }
9981  if (yych <= '`')
9982  {
9983  goto basic_json_parser_32;
9984  }
9985  if (yych <= 'f')
9986  {
9987  goto basic_json_parser_63;
9988  }
9989  goto basic_json_parser_32;
9990  }
9991 basic_json_parser_58:
9992  yych = *++m_cursor;
9993  if (yych == 'e')
9994  {
9995  goto basic_json_parser_64;
9996  }
9997  goto basic_json_parser_32;
9998 basic_json_parser_59:
9999  ++m_cursor;
10000  {
10001  last_token_type = token_type::literal_null;
10002  break;
10003  }
10004 basic_json_parser_61:
10005  ++m_cursor;
10006  {
10007  last_token_type = token_type::literal_true;
10008  break;
10009  }
10010 basic_json_parser_63:
10011  ++m_cursor;
10012  if (m_limit <= m_cursor)
10013  {
10014  fill_line_buffer(1); // LCOV_EXCL_LINE
10015  }
10016  yych = *m_cursor;
10017  if (yych <= '@')
10018  {
10019  if (yych <= '/')
10020  {
10021  goto basic_json_parser_32;
10022  }
10023  if (yych <= '9')
10024  {
10025  goto basic_json_parser_66;
10026  }
10027  goto basic_json_parser_32;
10028  }
10029  else
10030  {
10031  if (yych <= 'F')
10032  {
10033  goto basic_json_parser_66;
10034  }
10035  if (yych <= '`')
10036  {
10037  goto basic_json_parser_32;
10038  }
10039  if (yych <= 'f')
10040  {
10041  goto basic_json_parser_66;
10042  }
10043  goto basic_json_parser_32;
10044  }
10045 basic_json_parser_64:
10046  ++m_cursor;
10047  {
10048  last_token_type = token_type::literal_false;
10049  break;
10050  }
10051 basic_json_parser_66:
10052  ++m_cursor;
10053  if (m_limit <= m_cursor)
10054  {
10055  fill_line_buffer(1); // LCOV_EXCL_LINE
10056  }
10057  yych = *m_cursor;
10058  if (yych <= '@')
10059  {
10060  if (yych <= '/')
10061  {
10062  goto basic_json_parser_32;
10063  }
10064  if (yych <= '9')
10065  {
10066  goto basic_json_parser_30;
10067  }
10068  goto basic_json_parser_32;
10069  }
10070  else
10071  {
10072  if (yych <= 'F')
10073  {
10074  goto basic_json_parser_30;
10075  }
10076  if (yych <= '`')
10077  {
10078  goto basic_json_parser_32;
10079  }
10080  if (yych <= 'f')
10081  {
10082  goto basic_json_parser_30;
10083  }
10084  goto basic_json_parser_32;
10085  }
10086  }
10087 
10088  }
10089 
10090  return last_token_type;
10091  }
10092 
10121  void fill_line_buffer(size_t n = 0)
10122  {
10123  // if line buffer is used, m_content points to its data
10124  assert(m_line_buffer.empty()
10125  or m_content == reinterpret_cast<const lexer_char_t*>(m_line_buffer.data()));
10126 
10127  // if line buffer is used, m_limit is set past the end of its data
10128  assert(m_line_buffer.empty()
10129  or m_limit == m_content + m_line_buffer.size());
10130 
10131  // pointer relationships
10132  assert(m_content <= m_start);
10133  assert(m_start <= m_cursor);
10134  assert(m_cursor <= m_limit);
10135  assert(m_marker == nullptr or m_marker <= m_limit);
10136 
10137  // number of processed characters (p)
10138  const size_t num_processed_chars = static_cast<size_t>(m_start - m_content);
10139  // offset for m_marker wrt. to m_start
10140  const auto offset_marker = (m_marker == nullptr) ? 0 : m_marker - m_start;
10141  // number of unprocessed characters (u)
10142  const auto offset_cursor = m_cursor - m_start;
10143 
10144  // no stream is used or end of file is reached
10145  if (m_stream == nullptr or m_stream->eof())
10146  {
10147  // m_start may or may not be pointing into m_line_buffer at
10148  // this point. We trust the standand library to do the right
10149  // thing. See http://stackoverflow.com/q/28142011/266378
10150  m_line_buffer.assign(m_start, m_limit);
10151 
10152  // append n characters to make sure that there is sufficient
10153  // space between m_cursor and m_limit
10154  m_line_buffer.append(1, '\x00');
10155  if (n > 0)
10156  {
10157  m_line_buffer.append(n - 1, '\x01');
10158  }
10159  }
10160  else
10161  {
10162  // delete processed characters from line buffer
10163  m_line_buffer.erase(0, num_processed_chars);
10164  // read next line from input stream
10165  m_line_buffer_tmp.clear();
10166  std::getline(*m_stream, m_line_buffer_tmp, '\n');
10167 
10168  // add line with newline symbol to the line buffer
10169  m_line_buffer += m_line_buffer_tmp;
10170  m_line_buffer.push_back('\n');
10171  }
10172 
10173  // set pointers
10174  m_content = reinterpret_cast<const lexer_char_t*>(m_line_buffer.data());
10175  assert(m_content != nullptr);
10176  m_start = m_content;
10177  m_marker = m_start + offset_marker;
10178  m_cursor = m_start + offset_cursor;
10179  m_limit = m_start + m_line_buffer.size();
10180  }
10181 
10184  {
10185  assert(m_start != nullptr);
10186  return string_t(reinterpret_cast<typename string_t::const_pointer>(m_start),
10187  static_cast<size_t>(m_cursor - m_start));
10188  }
10189 
10248  {
10249  assert(m_cursor - m_start >= 2);
10250 
10251  string_t result;
10252  result.reserve(static_cast<size_t>(m_cursor - m_start - 2));
10253 
10254  // iterate the result between the quotes
10255  for (const lexer_char_t* i = m_start + 1; i < m_cursor - 1; ++i)
10256  {
10257  // find next escape character
10258  auto e = std::find(i, m_cursor - 1, '\\');
10259  if (e != i)
10260  {
10261  // see https://github.com/nlohmann/json/issues/365#issuecomment-262874705
10262  for (auto k = i; k < e; k++)
10263  {
10264  result.push_back(static_cast<typename string_t::value_type>(*k));
10265  }
10266  i = e - 1; // -1 because of ++i
10267  }
10268  else
10269  {
10270  // processing escaped character
10271  // read next character
10272  ++i;
10273 
10274  switch (*i)
10275  {
10276  // the default escapes
10277  case 't':
10278  {
10279  result += "\t";
10280  break;
10281  }
10282  case 'b':
10283  {
10284  result += "\b";
10285  break;
10286  }
10287  case 'f':
10288  {
10289  result += "\f";
10290  break;
10291  }
10292  case 'n':
10293  {
10294  result += "\n";
10295  break;
10296  }
10297  case 'r':
10298  {
10299  result += "\r";
10300  break;
10301  }
10302  case '\\':
10303  {
10304  result += "\\";
10305  break;
10306  }
10307  case '/':
10308  {
10309  result += "/";
10310  break;
10311  }
10312  case '"':
10313  {
10314  result += "\"";
10315  break;
10316  }
10317 
10318  // unicode
10319  case 'u':
10320  {
10321  // get code xxxx from uxxxx
10322  auto codepoint = std::strtoul(std::string(reinterpret_cast<typename string_t::const_pointer>(i + 1),
10323  4).c_str(), nullptr, 16);
10324 
10325  // check if codepoint is a high surrogate
10326  if (codepoint >= 0xD800 and codepoint <= 0xDBFF)
10327  {
10328  // make sure there is a subsequent unicode
10329  if ((i + 6 >= m_limit) or * (i + 5) != '\\' or * (i + 6) != 'u')
10330  {
10331  throw std::invalid_argument("missing low surrogate");
10332  }
10333 
10334  // get code yyyy from uxxxx\uyyyy
10335  auto codepoint2 = std::strtoul(std::string(reinterpret_cast<typename string_t::const_pointer>
10336  (i + 7), 4).c_str(), nullptr, 16);
10337  result += to_unicode(codepoint, codepoint2);
10338  // skip the next 10 characters (xxxx\uyyyy)
10339  i += 10;
10340  }
10341  else if (codepoint >= 0xDC00 and codepoint <= 0xDFFF)
10342  {
10343  // we found a lone low surrogate
10344  throw std::invalid_argument("missing high surrogate");
10345  }
10346  else
10347  {
10348  // add unicode character(s)
10349  result += to_unicode(codepoint);
10350  // skip the next four characters (xxxx)
10351  i += 4;
10352  }
10353  break;
10354  }
10355  }
10356  }
10357  }
10358 
10359  return result;
10360  }
10361 
10375  long double str_to_float_t(long double* /* type */, char** endptr) const
10376  {
10377 #ifdef ANDROID
10378  return strtold(reinterpret_cast<typename string_t::const_pointer>(m_start), endptr); // call to strtold defined in stdlib.h
10379 #else
10380  return std::strtold(reinterpret_cast<typename string_t::const_pointer>(m_start), endptr);
10381 #endif
10382  }
10383 
10397  double str_to_float_t(double* /* type */, char** endptr) const
10398  {
10399  return std::strtod(reinterpret_cast<typename string_t::const_pointer>(m_start), endptr);
10400  }
10401 
10415  float str_to_float_t(float* /* type */, char** endptr) const
10416  {
10417 #ifdef ANDROID
10418  return strtof(reinterpret_cast<typename string_t::const_pointer>(m_start), endptr); // call to strtof defined in stdlib.h
10419 #else
10420  return std::strtof(reinterpret_cast<typename string_t::const_pointer>(m_start), endptr);
10421 #endif
10422  }
10423 
10446  {
10447  assert(m_start != nullptr);
10448 
10449  const lexer::lexer_char_t* curptr = m_start;
10450 
10451  // accumulate the integer conversion result (unsigned for now)
10453 
10454  // maximum absolute value of the relevant integer type
10455  number_unsigned_t max;
10456 
10457  // temporarily store the type to avoid unecessary bitfield access
10458  value_t type;
10459 
10460  // look for sign
10461  if (*curptr == '-')
10462  {
10463  type = value_t::number_integer;
10464  max = static_cast<uint64_t>((std::numeric_limits<number_integer_t>::max)()) + 1;
10465  curptr++;
10466  }
10467  else
10468  {
10469  type = value_t::number_unsigned;
10470  max = static_cast<uint64_t>((std::numeric_limits<number_unsigned_t>::max)());
10471  }
10472 
10473  // count the significant figures
10474  for (; curptr < m_cursor; curptr++)
10475  {
10476  // quickly skip tests if a digit
10477  if (*curptr < '0' || *curptr > '9')
10478  {
10479  if (*curptr == '.')
10480  {
10481  // don't count '.' but change to float
10482  type = value_t::number_float;
10483  continue;
10484  }
10485  // assume exponent (if not then will fail parse): change to
10486  // float, stop counting and record exponent details
10487  type = value_t::number_float;
10488  break;
10489  }
10490 
10491  // skip if definitely not an integer
10492  if (type != value_t::number_float)
10493  {
10494  auto digit = static_cast<number_unsigned_t>(*curptr - '0');
10495 
10496  // overflow if value * 10 + digit > max, move terms around
10497  // to avoid overflow in intermediate values
10498  if (value > (max - digit) / 10)
10499  {
10500  // overflow
10501  type = value_t::number_float;
10502  }
10503  else
10504  {
10505  // no overflow
10506  value = value * 10 + digit;
10507  }
10508  }
10509  }
10510 
10511  // save the value (if not a float)
10512  if (type == value_t::number_unsigned)
10513  {
10514  result.m_value.number_unsigned = value;
10515  }
10516  else if (type == value_t::number_integer)
10517  {
10518  // invariant: if we parsed a '-', the absolute value is between
10519  // 0 (we allow -0) and max == -INT64_MIN
10520  assert(value >= 0);
10521  assert(value <= max);
10522 
10523  if (value == max)
10524  {
10525  // we cannot simply negate value (== max == -INT64_MIN),
10526  // see https://github.com/nlohmann/json/issues/389
10527  result.m_value.number_integer = INT64_MIN;
10528  }
10529  else
10530  {
10531  // all other values can be negated safely
10532  result.m_value.number_integer = -static_cast<number_integer_t>(value);
10533  }
10534  }
10535  else
10536  {
10537  // parse with strtod
10538  result.m_value.number_float = str_to_float_t(static_cast<number_float_t*>(nullptr), NULL);
10539 
10540  // replace infinity and NAN by null
10541  if (not std::isfinite(result.m_value.number_float))
10542  {
10543  type = value_t::null;
10544  result.m_value = basic_json::json_value();
10545  }
10546  }
10547 
10548  // save the type
10549  result.m_type = type;
10550  }
10551 
10552  private:
10554  std::istream* m_stream = nullptr;
10556  string_t m_line_buffer {};
10558  string_t m_line_buffer_tmp {};
10560  const lexer_char_t* m_content = nullptr;
10562  const lexer_char_t* m_start = nullptr;
10564  const lexer_char_t* m_marker = nullptr;
10566  const lexer_char_t* m_cursor = nullptr;
10568  const lexer_char_t* m_limit = nullptr;
10570  token_type last_token_type = token_type::end_of_input;
10571  };
10572 
10578  class parser
10579  {
10580  public:
10582  parser(const char* buff, const parser_callback_t cb = nullptr)
10583  : callback(cb),
10584  m_lexer(reinterpret_cast<const typename lexer::lexer_char_t*>(buff), std::strlen(buff))
10585  {}
10586 
10588  parser(std::istream& is, const parser_callback_t cb = nullptr)
10589  : callback(cb), m_lexer(is)
10590  {}
10591 
10593  template<class IteratorType, typename std::enable_if<
10594  std::is_same<typename std::iterator_traits<IteratorType>::iterator_category, std::random_access_iterator_tag>::value
10595  , int>::type
10596  = 0>
10597  parser(IteratorType first, IteratorType last, const parser_callback_t cb = nullptr)
10598  : callback(cb),
10599  m_lexer(reinterpret_cast<const typename lexer::lexer_char_t*>(&(*first)),
10600  static_cast<size_t>(std::distance(first, last)))
10601  {}
10602 
10605  {
10606  // read first token
10607  get_token();
10608 
10609  basic_json result = parse_internal(true);
10610  result.assert_invariant();
10611 
10612  expect(lexer::token_type::end_of_input);
10613 
10614  // return parser result and replace it with null in case the
10615  // top-level value was discarded by the callback function
10616  return result.is_discarded() ? basic_json() : std::move(result);
10617  }
10618 
10619  private:
10622  {
10623  auto result = basic_json(value_t::discarded);
10624 
10625  switch (last_token)
10626  {
10627  case lexer::token_type::begin_object:
10628  {
10629  if (keep and (not callback
10630  or ((keep = callback(depth++, parse_event_t::object_start, result)) != 0)))
10631  {
10632  // explicitly set result to object to cope with {}
10633  result.m_type = value_t::object;
10634  result.m_value = value_t::object;
10635  }
10636 
10637  // read next token
10638  get_token();
10639 
10640  // closing } -> we are done
10641  if (last_token == lexer::token_type::end_object)
10642  {
10643  get_token();
10644  if (keep and callback and not callback(--depth, parse_event_t::object_end, result))
10645  {
10646  result = basic_json(value_t::discarded);
10647  }
10648  return result;
10649  }
10650 
10651  // no comma is expected here
10652  unexpect(lexer::token_type::value_separator);
10653 
10654  // otherwise: parse key-value pairs
10655  do
10656  {
10657  // ugly, but could be fixed with loop reorganization
10658  if (last_token == lexer::token_type::value_separator)
10659  {
10660  get_token();
10661  }
10662 
10663  // store key
10664  expect(lexer::token_type::value_string);
10665  const auto key = m_lexer.get_string();
10666 
10667  bool keep_tag = false;
10668  if (keep)
10669  {
10670  if (callback)
10671  {
10672  basic_json k(key);
10673  keep_tag = callback(depth, parse_event_t::key, k);
10674  }
10675  else
10676  {
10677  keep_tag = true;
10678  }
10679  }
10680 
10681  // parse separator (:)
10682  get_token();
10683  expect(lexer::token_type::name_separator);
10684 
10685  // parse and add value
10686  get_token();
10687  auto value = parse_internal(keep);
10688  if (keep and keep_tag and not value.is_discarded())
10689  {
10690  result[key] = std::move(value);
10691  }
10692  }
10693  while (last_token == lexer::token_type::value_separator);
10694 
10695  // closing }
10696  expect(lexer::token_type::end_object);
10697  get_token();
10698  if (keep and callback and not callback(--depth, parse_event_t::object_end, result))
10699  {
10700  result = basic_json(value_t::discarded);
10701  }
10702 
10703  return result;
10704  }
10705 
10706  case lexer::token_type::begin_array:
10707  {
10708  if (keep and (not callback
10709  or ((keep = callback(depth++, parse_event_t::array_start, result)) != 0)))
10710  {
10711  // explicitly set result to object to cope with []
10712  result.m_type = value_t::array;
10713  result.m_value = value_t::array;
10714  }
10715 
10716  // read next token
10717  get_token();
10718 
10719  // closing ] -> we are done
10720  if (last_token == lexer::token_type::end_array)
10721  {
10722  get_token();
10724  {
10725  result = basic_json(value_t::discarded);
10726  }
10727  return result;
10728  }
10729 
10730  // no comma is expected here
10731  unexpect(lexer::token_type::value_separator);
10732 
10733  // otherwise: parse values
10734  do
10735  {
10736  // ugly, but could be fixed with loop reorganization
10737  if (last_token == lexer::token_type::value_separator)
10738  {
10739  get_token();
10740  }
10741 
10742  // parse value
10743  auto value = parse_internal(keep);
10744  if (keep and not value.is_discarded())
10745  {
10746  result.push_back(std::move(value));
10747  }
10748  }
10749  while (last_token == lexer::token_type::value_separator);
10750 
10751  // closing ]
10752  expect(lexer::token_type::end_array);
10753  get_token();
10754  if (keep and callback and not callback(--depth, parse_event_t::array_end, result))
10755  {
10756  result = basic_json(value_t::discarded);
10757  }
10758 
10759  return result;
10760  }
10761 
10762  case lexer::token_type::literal_null:
10763  {
10764  get_token();
10765  result.m_type = value_t::null;
10766  break;
10767  }
10768 
10769  case lexer::token_type::value_string:
10770  {
10771  const auto s = m_lexer.get_string();
10772  get_token();
10773  result = basic_json(s);
10774  break;
10775  }
10776 
10777  case lexer::token_type::literal_true:
10778  {
10779  get_token();
10780  result.m_type = value_t::boolean;
10781  result.m_value = true;
10782  break;
10783  }
10784 
10785  case lexer::token_type::literal_false:
10786  {
10787  get_token();
10788  result.m_type = value_t::boolean;
10789  result.m_value = false;
10790  break;
10791  }
10792 
10793  case lexer::token_type::value_number:
10794  {
10795  m_lexer.get_number(result);
10796  get_token();
10797  break;
10798  }
10799 
10800  default:
10801  {
10802  // the last token was unexpected
10803  unexpect(last_token);
10804  }
10805  }
10806 
10807  if (keep and callback and not callback(depth, parse_event_t::value, result))
10808  {
10809  result = basic_json(value_t::discarded);
10810  }
10811  return result;
10812  }
10813 
10816  {
10817  last_token = m_lexer.scan();
10818  return last_token;
10819  }
10820 
10821  void expect(typename lexer::token_type t) const
10822  {
10823  if (t != last_token)
10824  {
10825  std::string error_msg = "parse error - unexpected ";
10826  error_msg += (last_token == lexer::token_type::parse_error ? ("'" + m_lexer.get_token_string() +
10827  "'") :
10828  lexer::token_type_name(last_token));
10829  error_msg += "; expected " + lexer::token_type_name(t);
10830  throw std::invalid_argument(error_msg);
10831  }
10832  }
10833 
10834  void unexpect(typename lexer::token_type t) const
10835  {
10836  if (t == last_token)
10837  {
10838  std::string error_msg = "parse error - unexpected ";
10839  error_msg += (last_token == lexer::token_type::parse_error ? ("'" + m_lexer.get_token_string() +
10840  "'") :
10841  lexer::token_type_name(last_token));
10842  throw std::invalid_argument(error_msg);
10843  }
10844  }
10845 
10846  private:
10848  int depth = 0;
10850  const parser_callback_t callback = nullptr;
10852  typename lexer::token_type last_token = lexer::token_type::uninitialized;
10855  };
10856 
10857  public:
10870  {
10872  friend class basic_json;
10873 
10874  public:
10897  explicit json_pointer(const std::string& s = "")
10898  : reference_tokens(split(s))
10899  {}
10900 
10916  std::string to_string() const noexcept
10917  {
10918  return std::accumulate(reference_tokens.begin(),
10919  reference_tokens.end(), std::string{},
10920  [](const std::string & a, const std::string & b)
10921  {
10922  return a + "/" + escape(b);
10923  });
10924  }
10925 
10927  operator std::string() const
10928  {
10929  return to_string();
10930  }
10931 
10932  private:
10935  {
10936  if (is_root())
10937  {
10938  throw std::domain_error("JSON pointer has no parent");
10939  }
10940 
10941  auto last = reference_tokens.back();
10942  reference_tokens.pop_back();
10943  return last;
10944  }
10945 
10947  bool is_root() const
10948  {
10949  return reference_tokens.empty();
10950  }
10951 
10953  {
10954  if (is_root())
10955  {
10956  throw std::domain_error("JSON pointer has no parent");
10957  }
10958 
10959  json_pointer result = *this;
10960  result.reference_tokens = {reference_tokens[0]};
10961  return result;
10962  }
10963 
10970  {
10971  pointer result = &j;
10972 
10973  // in case no reference tokens exist, return a reference to the
10974  // JSON value j which will be overwritten by a primitive value
10975  for (const auto& reference_token : reference_tokens)
10976  {
10977  switch (result->m_type)
10978  {
10979  case value_t::null:
10980  {
10981  if (reference_token == "0")
10982  {
10983  // start a new array if reference token is 0
10984  result = &result->operator[](0);
10985  }
10986  else
10987  {
10988  // start a new object otherwise
10989  result = &result->operator[](reference_token);
10990  }
10991  break;
10992  }
10993 
10994  case value_t::object:
10995  {
10996  // create an entry in the object
10997  result = &result->operator[](reference_token);
10998  break;
10999  }
11000 
11001  case value_t::array:
11002  {
11003  // create an entry in the array
11004  result = &result->operator[](static_cast<size_type>(std::stoi(reference_token)));
11005  break;
11006  }
11007 
11008  /*
11009  The following code is only reached if there exists a
11010  reference token _and_ the current value is primitive. In
11011  this case, we have an error situation, because primitive
11012  values may only occur as single value; that is, with an
11013  empty list of reference tokens.
11014  */
11015  default:
11016  {
11017  throw std::domain_error("invalid value to unflatten");
11018  }
11019  }
11020  }
11021 
11022  return *result;
11023  }
11024 
11045  {
11046  for (const auto& reference_token : reference_tokens)
11047  {
11048  // convert null values to arrays or objects before continuing
11049  if (ptr->m_type == value_t::null)
11050  {
11051  // check if reference token is a number
11052  const bool nums = std::all_of(reference_token.begin(),
11053  reference_token.end(),
11054  [](const char x)
11055  {
11056  return std::isdigit(x);
11057  });
11058 
11059  // change value to array for numbers or "-" or to object
11060  // otherwise
11061  if (nums or reference_token == "-")
11062  {
11063  *ptr = value_t::array;
11064  }
11065  else
11066  {
11067  *ptr = value_t::object;
11068  }
11069  }
11070 
11071  switch (ptr->m_type)
11072  {
11073  case value_t::object:
11074  {
11075  // use unchecked object access
11076  ptr = &ptr->operator[](reference_token);
11077  break;
11078  }
11079 
11080  case value_t::array:
11081  {
11082  // error condition (cf. RFC 6901, Sect. 4)
11083  if (reference_token.size() > 1 and reference_token[0] == '0')
11084  {
11085  throw std::domain_error("array index must not begin with '0'");
11086  }
11087 
11088  if (reference_token == "-")
11089  {
11090  // explicityly treat "-" as index beyond the end
11091  ptr = &ptr->operator[](ptr->m_value.array->size());
11092  }
11093  else
11094  {
11095  // convert array index to number; unchecked access
11096  ptr = &ptr->operator[](static_cast<size_type>(std::stoi(reference_token)));
11097  }
11098  break;
11099  }
11100 
11101  default:
11102  {
11103  throw std::out_of_range("unresolved reference token '" + reference_token + "'");
11104  }
11105  }
11106  }
11107 
11108  return *ptr;
11109  }
11110 
11112  {
11113  for (const auto& reference_token : reference_tokens)
11114  {
11115  switch (ptr->m_type)
11116  {
11117  case value_t::object:
11118  {
11119  // note: at performs range check
11120  ptr = &ptr->at(reference_token);
11121  break;
11122  }
11123 
11124  case value_t::array:
11125  {
11126  if (reference_token == "-")
11127  {
11128  // "-" always fails the range check
11129  throw std::out_of_range("array index '-' (" +
11130  std::to_string(ptr->m_value.array->size()) +
11131  ") is out of range");
11132  }
11133 
11134  // error condition (cf. RFC 6901, Sect. 4)
11135  if (reference_token.size() > 1 and reference_token[0] == '0')
11136  {
11137  throw std::domain_error("array index must not begin with '0'");
11138  }
11139 
11140  // note: at performs range check
11141  ptr = &ptr->at(static_cast<size_type>(std::stoi(reference_token)));
11142  break;
11143  }
11144 
11145  default:
11146  {
11147  throw std::out_of_range("unresolved reference token '" + reference_token + "'");
11148  }
11149  }
11150  }
11151 
11152  return *ptr;
11153  }
11154 
11164  {
11165  for (const auto& reference_token : reference_tokens)
11166  {
11167  switch (ptr->m_type)
11168  {
11169  case value_t::object:
11170  {
11171  // use unchecked object access
11172  ptr = &ptr->operator[](reference_token);
11173  break;
11174  }
11175 
11176  case value_t::array:
11177  {
11178  if (reference_token == "-")
11179  {
11180  // "-" cannot be used for const access
11181  throw std::out_of_range("array index '-' (" +
11182  std::to_string(ptr->m_value.array->size()) +
11183  ") is out of range");
11184  }
11185 
11186  // error condition (cf. RFC 6901, Sect. 4)
11187  if (reference_token.size() > 1 and reference_token[0] == '0')
11188  {
11189  throw std::domain_error("array index must not begin with '0'");
11190  }
11191 
11192  // use unchecked array access
11193  ptr = &ptr->operator[](static_cast<size_type>(std::stoi(reference_token)));
11194  break;
11195  }
11196 
11197  default:
11198  {
11199  throw std::out_of_range("unresolved reference token '" + reference_token + "'");
11200  }
11201  }
11202  }
11203 
11204  return *ptr;
11205  }
11206 
11208  {
11209  for (const auto& reference_token : reference_tokens)
11210  {
11211  switch (ptr->m_type)
11212  {
11213  case value_t::object:
11214  {
11215  // note: at performs range check
11216  ptr = &ptr->at(reference_token);
11217  break;
11218  }
11219 
11220  case value_t::array:
11221  {
11222  if (reference_token == "-")
11223  {
11224  // "-" always fails the range check
11225  throw std::out_of_range("array index '-' (" +
11226  std::to_string(ptr->m_value.array->size()) +
11227  ") is out of range");
11228  }
11229 
11230  // error condition (cf. RFC 6901, Sect. 4)
11231  if (reference_token.size() > 1 and reference_token[0] == '0')
11232  {
11233  throw std::domain_error("array index must not begin with '0'");
11234  }
11235 
11236  // note: at performs range check
11237  ptr = &ptr->at(static_cast<size_type>(std::stoi(reference_token)));
11238  break;
11239  }
11240 
11241  default:
11242  {
11243  throw std::out_of_range("unresolved reference token '" + reference_token + "'");
11244  }
11245  }
11246  }
11247 
11248  return *ptr;
11249  }
11250 
11252  static std::vector<std::string> split(const std::string& reference_string)
11253  {
11254  std::vector<std::string> result;
11255 
11256  // special case: empty reference string -> no reference tokens
11257  if (reference_string.empty())
11258  {
11259  return result;
11260  }
11261 
11262  // check if nonempty reference string begins with slash
11263  if (reference_string[0] != '/')
11264  {
11265  throw std::domain_error("JSON pointer must be empty or begin with '/'");
11266  }
11267 
11268  // extract the reference tokens:
11269  // - slash: position of the last read slash (or end of string)
11270  // - start: position after the previous slash
11271  for (
11272  // search for the first slash after the first character
11273  size_t slash = reference_string.find_first_of("/", 1),
11274  // set the beginning of the first reference token
11275  start = 1;
11276  // we can stop if start == string::npos+1 = 0
11277  start != 0;
11278  // set the beginning of the next reference token
11279  // (will eventually be 0 if slash == std::string::npos)
11280  start = slash + 1,
11281  // find next slash
11282  slash = reference_string.find_first_of("/", start))
11283  {
11284  // use the text between the beginning of the reference token
11285  // (start) and the last slash (slash).
11286  auto reference_token = reference_string.substr(start, slash - start);
11287 
11288  // check reference tokens are properly escaped
11289  for (size_t pos = reference_token.find_first_of("~");
11290  pos != std::string::npos;
11291  pos = reference_token.find_first_of("~", pos + 1))
11292  {
11293  assert(reference_token[pos] == '~');
11294 
11295  // ~ must be followed by 0 or 1
11296  if (pos == reference_token.size() - 1 or
11297  (reference_token[pos + 1] != '0' and
11298  reference_token[pos + 1] != '1'))
11299  {
11300  throw std::domain_error("escape error: '~' must be followed with '0' or '1'");
11301  }
11302  }
11303 
11304  // finally, store the reference token
11305  unescape(reference_token);
11306  result.push_back(reference_token);
11307  }
11308 
11309  return result;
11310  }
11311 
11312  private:
11326  const std::string& f,
11327  const std::string& t)
11328  {
11329  assert(not f.empty());
11330 
11331  for (
11332  size_t pos = s.find(f); // find first occurrence of f
11333  pos != std::string::npos; // make sure f was found
11334  s.replace(pos, f.size(), t), // replace with t
11335  pos = s.find(f, pos + t.size()) // find next occurrence of f
11336  );
11337  }
11338 
11341  {
11342  // escape "~"" to "~0" and "/" to "~1"
11343  replace_substring(s, "~", "~0");
11344  replace_substring(s, "/", "~1");
11345  return s;
11346  }
11347 
11349  static void unescape(std::string& s)
11350  {
11351  // first transform any occurrence of the sequence '~1' to '/'
11352  replace_substring(s, "~1", "/");
11353  // then transform any occurrence of the sequence '~0' to '~'
11354  replace_substring(s, "~0", "~");
11355  }
11356 
11364  static void flatten(const std::string& reference_string,
11365  const basic_json& value,
11366  basic_json& result)
11367  {
11368  switch (value.m_type)
11369  {
11370  case value_t::array:
11371  {
11372  if (value.m_value.array->empty())
11373  {
11374  // flatten empty array as null
11375  result[reference_string] = nullptr;
11376  }
11377  else
11378  {
11379  // iterate array and use index as reference string
11380  for (size_t i = 0; i < value.m_value.array->size(); ++i)
11381  {
11382  flatten(reference_string + "/" + std::to_string(i),
11383  value.m_value.array->operator[](i), result);
11384  }
11385  }
11386  break;
11387  }
11388 
11389  case value_t::object:
11390  {
11391  if (value.m_value.object->empty())
11392  {
11393  // flatten empty object as null
11394  result[reference_string] = nullptr;
11395  }
11396  else
11397  {
11398  // iterate object and use keys as reference string
11399  for (const auto& element : *value.m_value.object)
11400  {
11401  flatten(reference_string + "/" + escape(element.first),
11402  element.second, result);
11403  }
11404  }
11405  break;
11406  }
11407 
11408  default:
11409  {
11410  // add primitive value with its reference string
11411  result[reference_string] = value;
11412  break;
11413  }
11414  }
11415  }
11416 
11423  {
11424  if (not value.is_object())
11425  {
11426  throw std::domain_error("only objects can be unflattened");
11427  }
11428 
11430 
11431  // iterate the JSON object values
11432  for (const auto& element : *value.m_value.object)
11433  {
11434  if (not element.second.is_primitive())
11435  {
11436  throw std::domain_error("values in object must be primitive");
11437  }
11438 
11439  // assign value to reference pointed to by JSON pointer; Note
11440  // that if the JSON pointer is "" (i.e., points to the whole
11441  // value), function get_and_create returns a reference to
11442  // result itself. An assignment will then create a primitive
11443  // value.
11444  json_pointer(element.first).get_and_create(result) = element.second;
11445  }
11446 
11447  return result;
11448  }
11449 
11450  private:
11452  std::vector<std::string> reference_tokens {};
11453  };
11454 
11456  // JSON Pointer support //
11458 
11461 
11496  {
11497  return ptr.get_unchecked(this);
11498  }
11499 
11523  {
11524  return ptr.get_unchecked(this);
11525  }
11526 
11548  {
11549  return ptr.get_checked(this);
11550  }
11551 
11572  const_reference at(const json_pointer& ptr) const
11573  {
11574  return ptr.get_checked(this);
11575  }
11576 
11600  {
11602  json_pointer::flatten("", *this, result);
11603  return result;
11604  }
11605 
11634  {
11635  return json_pointer::unflatten(*this);
11636  }
11637 
11639 
11641  // JSON Patch functions //
11643 
11646 
11683  basic_json patch(const basic_json& json_patch) const
11684  {
11685  // make a working copy to apply the patch to
11686  basic_json result = *this;
11687 
11688  // the valid JSON Patch operations
11689  enum class patch_operations {add, remove, replace, move, copy, test, invalid};
11690 
11691  const auto get_op = [](const std::string op)
11692  {
11693  if (op == "add")
11694  {
11695  return patch_operations::add;
11696  }
11697  if (op == "remove")
11698  {
11699  return patch_operations::remove;
11700  }
11701  if (op == "replace")
11702  {
11703  return patch_operations::replace;
11704  }
11705  if (op == "move")
11706  {
11707  return patch_operations::move;
11708  }
11709  if (op == "copy")
11710  {
11711  return patch_operations::copy;
11712  }
11713  if (op == "test")
11714  {
11715  return patch_operations::test;
11716  }
11717 
11718  return patch_operations::invalid;
11719  };
11720 
11721  // wrapper for "add" operation; add value at ptr
11722  const auto operation_add = [&result](json_pointer & ptr, basic_json val)
11723  {
11724  // adding to the root of the target document means replacing it
11725  if (ptr.is_root())
11726  {
11727  result = val;
11728  }
11729  else
11730  {
11731  // make sure the top element of the pointer exists
11732  json_pointer top_pointer = ptr.top();
11733  if (top_pointer != ptr)
11734  {
11735  result.at(top_pointer);
11736  }
11737 
11738  // get reference to parent of JSON pointer ptr
11739  const auto last_path = ptr.pop_back();
11740  basic_json& parent = result[ptr];
11741 
11742  switch (parent.m_type)
11743  {
11744  case value_t::null:
11745  case value_t::object:
11746  {
11747  // use operator[] to add value
11748  parent[last_path] = val;
11749  break;
11750  }
11751 
11752  case value_t::array:
11753  {
11754  if (last_path == "-")
11755  {
11756  // special case: append to back
11757  parent.push_back(val);
11758  }
11759  else
11760  {
11761  const auto idx = std::stoi(last_path);
11762  if (static_cast<size_type>(idx) > parent.size())
11763  {
11764  // avoid undefined behavior
11765  throw std::out_of_range("array index " + std::to_string(idx) + " is out of range");
11766  }
11767  else
11768  {
11769  // default case: insert add offset
11770  parent.insert(parent.begin() + static_cast<difference_type>(idx), val);
11771  }
11772  }
11773  break;
11774  }
11775 
11776  default:
11777  {
11778  // if there exists a parent it cannot be primitive
11779  assert(false); // LCOV_EXCL_LINE
11780  }
11781  }
11782  }
11783  };
11784 
11785  // wrapper for "remove" operation; remove value at ptr
11786  const auto operation_remove = [&result](json_pointer & ptr)
11787  {
11788  // get reference to parent of JSON pointer ptr
11789  const auto last_path = ptr.pop_back();
11790  basic_json& parent = result.at(ptr);
11791 
11792  // remove child
11793  if (parent.is_object())
11794  {
11795  // perform range check
11796  auto it = parent.find(last_path);
11797  if (it != parent.end())
11798  {
11799  parent.erase(it);
11800  }
11801  else
11802  {
11803  throw std::out_of_range("key '" + last_path + "' not found");
11804  }
11805  }
11806  else if (parent.is_array())
11807  {
11808  // note erase performs range check
11809  parent.erase(static_cast<size_type>(std::stoi(last_path)));
11810  }
11811  };
11812 
11813  // type check
11814  if (not json_patch.is_array())
11815  {
11816  // a JSON patch must be an array of objects
11817  throw std::invalid_argument("JSON patch must be an array of objects");
11818  }
11819 
11820  // iterate and apply th eoperations
11821  for (const auto& val : json_patch)
11822  {
11823  // wrapper to get a value for an operation
11824  const auto get_value = [&val](const std::string & op,
11825  const std::string & member,
11826  bool string_type) -> basic_json&
11827  {
11828  // find value
11829  auto it = val.m_value.object->find(member);
11830 
11831  // context-sensitive error message
11832  const auto error_msg = (op == "op") ? "operation" : "operation '" + op + "'";
11833 
11834  // check if desired value is present
11835  if (it == val.m_value.object->end())
11836  {
11837  throw std::invalid_argument(error_msg + " must have member '" + member + "'");
11838  }
11839 
11840  // check if result is of type string
11841  if (string_type and not it->second.is_string())
11842  {
11843  throw std::invalid_argument(error_msg + " must have string member '" + member + "'");
11844  }
11845 
11846  // no error: return value
11847  return it->second;
11848  };
11849 
11850  // type check
11851  if (not val.is_object())
11852  {
11853  throw std::invalid_argument("JSON patch must be an array of objects");
11854  }
11855 
11856  // collect mandatory members
11857  const std::string op = get_value("op", "op", true);
11858  const std::string path = get_value(op, "path", true);
11859  json_pointer ptr(path);
11860 
11861  switch (get_op(op))
11862  {
11863  case patch_operations::add:
11864  {
11865  operation_add(ptr, get_value("add", "value", false));
11866  break;
11867  }
11868 
11869  case patch_operations::remove:
11870  {
11871  operation_remove(ptr);
11872  break;
11873  }
11874 
11875  case patch_operations::replace:
11876  {
11877  // the "path" location must exist - use at()
11878  result.at(ptr) = get_value("replace", "value", false);
11879  break;
11880  }
11881 
11883  {
11884  const std::string from_path = get_value("move", "from", true);
11885  json_pointer from_ptr(from_path);
11886 
11887  // the "from" location must exist - use at()
11888  basic_json v = result.at(from_ptr);
11889 
11890  // The move operation is functionally identical to a
11891  // "remove" operation on the "from" location, followed
11892  // immediately by an "add" operation at the target
11893  // location with the value that was just removed.
11894  operation_remove(from_ptr);
11895  operation_add(ptr, v);
11896  break;
11897  }
11898 
11900  {
11901  const std::string from_path = get_value("copy", "from", true);;
11902  const json_pointer from_ptr(from_path);
11903 
11904  // the "from" location must exist - use at()
11905  result[ptr] = result.at(from_ptr);
11906  break;
11907  }
11908 
11909  case patch_operations::test:
11910  {
11911  bool success = false;
11912  try
11913  {
11914  // check if "value" matches the one at "path"
11915  // the "path" location must exist - use at()
11916  success = (result.at(ptr) == get_value("test", "value", false));
11917  }
11918  catch (std::out_of_range&)
11919  {
11920  // ignore out of range errors: success remains false
11921  }
11922 
11923  // throw an exception if test fails
11924  if (not success)
11925  {
11926  throw std::domain_error("unsuccessful: " + val.dump());
11927  }
11928 
11929  break;
11930  }
11931 
11932  case patch_operations::invalid:
11933  {
11934  // op must be "add", "remove", "replace", "move", "copy", or
11935  // "test"
11936  throw std::invalid_argument("operation value '" + op + "' is invalid");
11937  }
11938  }
11939  }
11940 
11941  return result;
11942  }
11943 
11977  const basic_json& target,
11978  const std::string& path = "")
11979  {
11980  // the patch
11982 
11983  // if the values are the same, return empty patch
11984  if (source == target)
11985  {
11986  return result;
11987  }
11988 
11989  if (source.type() != target.type())
11990  {
11991  // different types: replace value
11992  result.push_back(
11993  {
11994  {"op", "replace"},
11995  {"path", path},
11996  {"value", target}
11997  });
11998  }
11999  else
12000  {
12001  switch (source.type())
12002  {
12003  case value_t::array:
12004  {
12005  // first pass: traverse common elements
12006  size_t i = 0;
12007  while (i < source.size() and i < target.size())
12008  {
12009  // recursive call to compare array values at index i
12010  auto temp_diff = diff(source[i], target[i], path + "/" + std::to_string(i));
12011  result.insert(result.end(), temp_diff.begin(), temp_diff.end());
12012  ++i;
12013  }
12014 
12015  // i now reached the end of at least one array
12016  // in a second pass, traverse the remaining elements
12017 
12018  // remove my remaining elements
12019  const auto end_index = static_cast<difference_type>(result.size());
12020  while (i < source.size())
12021  {
12022  // add operations in reverse order to avoid invalid
12023  // indices
12024  result.insert(result.begin() + end_index, object(
12025  {
12026  {"op", "remove"},
12027  {"path", path + "/" + std::to_string(i)}
12028  }));
12029  ++i;
12030  }
12031 
12032  // add other remaining elements
12033  while (i < target.size())
12034  {
12035  result.push_back(
12036  {
12037  {"op", "add"},
12038  {"path", path + "/" + std::to_string(i)},
12039  {"value", target[i]}
12040  });
12041  ++i;
12042  }
12043 
12044  break;
12045  }
12046 
12047  case value_t::object:
12048  {
12049  // first pass: traverse this object's elements
12050  for (auto it = source.begin(); it != source.end(); ++it)
12051  {
12052  // escape the key name to be used in a JSON patch
12053  const auto key = json_pointer::escape(it.key());
12054 
12055  if (target.find(it.key()) != target.end())
12056  {
12057  // recursive call to compare object values at key it
12058  auto temp_diff = diff(it.value(), target[it.key()], path + "/" + key);
12059  result.insert(result.end(), temp_diff.begin(), temp_diff.end());
12060  }
12061  else
12062  {
12063  // found a key that is not in o -> remove it
12064  result.push_back(object(
12065  {
12066  {"op", "remove"},
12067  {"path", path + "/" + key}
12068  }));
12069  }
12070  }
12071 
12072  // second pass: traverse other object's elements
12073  for (auto it = target.begin(); it != target.end(); ++it)
12074  {
12075  if (source.find(it.key()) == source.end())
12076  {
12077  // found a key that is not in this -> add it
12078  const auto key = json_pointer::escape(it.key());
12079  result.push_back(
12080  {
12081  {"op", "add"},
12082  {"path", path + "/" + key},
12083  {"value", it.value()}
12084  });
12085  }
12086  }
12087 
12088  break;
12089  }
12090 
12091  default:
12092  {
12093  // both primitive type: replace value
12094  result.push_back(
12095  {
12096  {"op", "replace"},
12097  {"path", path},
12098  {"value", target}
12099  });
12100  break;
12101  }
12102  }
12103  }
12104 
12105  return result;
12106  }
12107 
12109 };
12110 
12111 
12113 // presets //
12115 
12125 }
12126 
12127 
12129 // nonmember support //
12131 
12132 // specialization of std::swap, and std::hash
12133 namespace std
12134 {
12140 template<>
12141 inline void swap(nlohmann::json& j1,
12142  nlohmann::json& j2) noexcept(
12145  )
12146 {
12147  j1.swap(j2);
12148 }
12149 
12151 template<>
12152 struct hash<nlohmann::json>
12153 {
12159  std::size_t operator()(const nlohmann::json& j) const
12160  {
12161  // a naive hashing via the string representation
12162  const auto& h = hash<nlohmann::json::string_t>();
12163  return h(j.dump());
12164  }
12165 };
12166 }
12167 
12181 inline nlohmann::json operator "" _json(const char* s, std::size_t n)
12182 {
12183  return nlohmann::json::parse(s, s + n);
12184 }
12185 
12199 inline nlohmann::json::json_pointer operator "" _json_pointer(const char* s, std::size_t n)
12200 {
12202 }
12203 
12204 // restore GCC/clang diagnostic settings
12205 #if defined(__clang__) || defined(__GNUC__) || defined(__GNUG__)
12206  #pragma GCC diagnostic pop
12207 #endif
12208 
12209 #endif
12210 
json_value(const object_t &value)
constructor for objects
Definition: json.hpp:890
iteration_proxy_internal end() noexcept
return iterator end (needed for range-based for)
Definition: json.hpp:8200
#define INT32_MAX
Definition: stdint.h:137
reference at(const typename object_t::key_type &key)
access specified object element with bounds checking
Definition: json.hpp:3227
std::string type_name() const
return the type as string
Definition: json.hpp:7674
json_reverse_iterator & operator--()
pre-decrement (–it)
Definition: json.hpp:8888
void swap(string_t &other)
exchanges the values
Definition: json.hpp:5460
json_value(const array_t &value)
constructor for arrays
Definition: json.hpp:896
const_iterator end() const noexcept
returns a const iterator to one past the last element
Definition: json.hpp:4368
GLint GLint GLint j1
size_type max_size() const noexcept
returns the maximum possible number of elements
Definition: json.hpp:4746
object_t::iterator object_iterator
iterator for JSON objects
Definition: json.hpp:8098
BOOST_FORCEINLINE T * addressof(T &v)
GLuint GLuint end
iter_impl & operator+=(difference_type i)
add to iterator
Definition: json.hpp:8674
iter_impl & operator--()
pre-decrement (–it)
Definition: json.hpp:8540
std::bidirectional_iterator_tag iterator_category
the category of the iterator
Definition: json.hpp:8251
const value_type & const_reference
the type of an element const reference
Definition: json.hpp:250
GLboolean GLboolean GLboolean b
iterator insert(const_iterator pos, const_iterator first, const_iterator last)
inserts elements
Definition: json.hpp:5267
object_t::key_type key() const
return the key of an object iterator
Definition: json.hpp:8802
difference_type operator-(const json_reverse_iterator &other) const
return difference
Definition: json.hpp:8918
GLenum GLsizei const void * pointer
bool is_integer(float f)
Definition: rendering.h:1571
constexpr bool is_structured() const noexcept
return whether type is structured
Definition: json.hpp:2286
bool is_root() const
return whether pointer points to the root document
Definition: json.hpp:10947
json_reverse_iterator operator--(int)
post-decrement (it–)
Definition: json.hpp:8882
#define expect(expr, value)
Definition: lz4.c:116
iterator insert(const_iterator pos, const basic_json &val)
inserts element
Definition: json.hpp:5160
number_integer_t number_integer
number (integer)
Definition: json.hpp:813
reference operator[](difference_type n) const
access to successor
Definition: json.hpp:8924
friend bool operator<(const_reference lhs, const_reference rhs) noexcept
comparison: less than
Definition: json.hpp:5724
parser(const char *buff, const parser_callback_t cb=nullptr)
a parser reading from a string literal
Definition: json.hpp:10582
void assert_invariant() const
checks the class invariants
Definition: json.hpp:911
Definition: helper.h:12
string_t value(const typename object_t::key_type &key, const char *default_value) const
overload for a default value of type const char*
Definition: json.hpp:3711
std::ptrdiff_t difference_type
a type to represent differences between iterators
Definition: json.hpp:253
basic_json unflatten() const
unflatten a previously flattened JSON value
Definition: json.hpp:11633
an iterator for primitive JSON types
Definition: json.hpp:8041
json_reverse_iterator(const base_iterator &it) noexcept
create reverse iterator from base class
Definition: json.hpp:8864
GLdouble GLdouble GLint GLint order
std::pair< iterator, bool > emplace(Args &&...args)
add an object to an object if key does not exist
Definition: json.hpp:5112
double str_to_float_t(double *, char **endptr) const
parse floating point number
Definition: json.hpp:10397
reference get_and_create(reference j) const
create and return a reference to the pointed to value
Definition: json.hpp:10969
GLint reference
Definition: glext.h:10544
bool operator==(const plane &lhs, const plane &rhs)
Definition: rendering.h:134
json_value(const string_t &value)
constructor for strings
Definition: json.hpp:884
bool operator!=(failed, failed)
GLdouble s
const_reference front() const
access the first element
Definition: json.hpp:3822
constexpr bool is_primitive() const noexcept
return whether type is primitive
Definition: json.hpp:2259
number_float_t number_float
number (floating-point)
Definition: json.hpp:817
ValueType get() const
get a value (explicit)
Definition: json.hpp:2887
lexer(const lexer_char_t *buff, const size_t len) noexcept
a lexer from a buffer with given length
Definition: json.hpp:8983
static basic_json unflatten(const basic_json &value)
Definition: json.hpp:11422
static basic_json parse(T(&array)[N], const parser_callback_t cb=nullptr)
deserialize from an array
Definition: json.hpp:5979
AllocatorType< basic_json > allocator_type
the allocator type
Definition: json.hpp:258
#define UINT8_MAX
Definition: stdint.h:140
void push_back(const basic_json &val)
add an object to an array
Definition: json.hpp:4914
basic_json(const number_float_t val) noexcept
create a floating-point number (explicit)
Definition: json.hpp:1502
static basic_json parse(const CharT s, const parser_callback_t cb=nullptr)
deserialize from string literal
Definition: json.hpp:6017
iteration_proxy_internal & operator++()
increment operator (needed for range-based for)
Definition: json.hpp:8136
const GLfloat * m
Definition: glext.h:6814
const_reference back() const
access the last element
Definition: json.hpp:3867
std::vector< uint32_t > split(const std::string &s, char delim)
const_reference operator[](const json_pointer &ptr) const
access specified element via JSON Pointer
Definition: json.hpp:11522
static basic_json from_msgpack_internal(const std::vector< uint8_t > &v, size_t &idx)
create a JSON value from a given MessagePack vector
Definition: json.hpp:6848
IteratorType erase(IteratorType first, IteratorType last)
remove elements given an iterator range
Definition: json.hpp:4030
constexpr const object_t * get_impl_ptr(const object_t *) const noexcept
get a pointer to the value (object)
Definition: json.hpp:2738
bool operator>=(const iter_impl &other) const
comparison: greater than or equal
Definition: json.hpp:8665
#define INT64_MAX
Definition: stdint.h:139
const_iterator cend() const noexcept
returns a const iterator to one past the last element
Definition: json.hpp:4398
string_t * string
string (stored with pointer to save storage)
Definition: json.hpp:809
std::string hexify(unsigned char n)
Definition: parser.hpp:197
#define INT64_MIN
Definition: stdint.h:138
a class to store JSON values
Definition: json.hpp:221
GLsizei const GLchar *const * path
Definition: glext.h:4276
GLfloat value
basic_json(const CompatibleStringType &val)
create a string (implicit)
Definition: json.hpp:1293
iter_impl operator-(difference_type i)
subtract from iterator
Definition: json.hpp:8725
basic_json(InputIT first, InputIT last)
construct a JSON container given an iterator range
Definition: json.hpp:1818
ImVec4 operator*(const ImVec4 &color, float t)
Definition: model-views.h:68
constexpr bool is_discarded() const noexcept
return whether value is discarded
Definition: json.hpp:2538
iteration_proxy_internal begin() noexcept
return iterator begin (needed for range-based for)
Definition: json.hpp:8194
constexpr const PointerType get_ptr() const noexcept
get a pointer value (implicit)
Definition: json.hpp:2995
object_t * get_impl_ptr(object_t *) noexcept
get a pointer to the value (object)
Definition: json.hpp:2732
friend std::ostream & operator<<(std::ostream &o, const basic_json &j)
serialize to stream
Definition: json.hpp:5904
constexpr bool is_number_unsigned() const noexcept
return whether value is an unsigned integer number
Definition: json.hpp:2417
constexpr bool is_object() const noexcept
return whether value is an object
Definition: json.hpp:2467
typename basic_json::difference_type difference_type
a type to represent differences between iterators
Definition: json.hpp:8241
typename std::conditional< std::is_const< U >::value, typename basic_json::const_reference, typename basic_json::reference >::type reference
defines a reference to the type iterated over (value_type)
Definition: json.hpp:8249
static void flatten(const std::string &reference_string, const basic_json &value, basic_json &result)
Definition: json.hpp:11364
parser
Definition: enums.py:61
Easylogging++ entry namespace.
PointerType get_ptr() noexcept
get a pointer value (implicit)
Definition: json.hpp:2967
#define INT8_MAX
Definition: stdint.h:133
GLint GLint GLsizei GLsizei GLsizei depth
object_t get_impl(object_t *) const
get an object (explicit)
Definition: json.hpp:2590
ObjectType< StringType, basic_json, std::less< StringType >, AllocatorType< std::pair< const StringType, basic_json >>> object_t
a type for an object
Definition: json.hpp:382
static color_map classic
Definition: colorizer.cpp:34
static void add_to_vector(std::vector< uint8_t > &vec, size_t bytes, const T number)
Definition: json.hpp:6236
basic_json(std::nullptr_t=nullptr) noexcept
create a null object
Definition: json.hpp:1078
reference get_unchecked(pointer ptr) const
return a reference to the pointed to value
Definition: json.hpp:11044
GLsizei const GLchar *const * string
reference at(const json_pointer &ptr)
access specified element via JSON Pointer
Definition: json.hpp:11547
size_type size() const noexcept
returns the number of elements
Definition: json.hpp:4680
const_reference operator[](const typename object_t::key_type &key) const
read-only access specified object element
Definition: json.hpp:3459
lexical analysis
Definition: json.hpp:8957
reference & operator=(basic_json other) noexcept(std::is_nothrow_move_constructible< value_t >::value andstd::is_nothrow_move_assignable< value_t >::value andstd::is_nothrow_move_constructible< json_value >::value andstd::is_nothrow_move_assignable< json_value >::value)
copy assignment
Definition: json.hpp:2082
static allocator_type get_allocator()
returns the allocator associated with the container
Definition: json.hpp:280
constexpr bool is_array() const noexcept
return whether value is an array
Definition: json.hpp:2489
std::array< point3d, 4 > object
basic_json(const CompatibleObjectType &val)
create an object (implicit)
Definition: json.hpp:1138
json_value(boolean_t v) noexcept
constructor for booleans
Definition: json.hpp:822
number_integer_t * get_impl_ptr(number_integer_t *) noexcept
get a pointer to the value (integer number)
Definition: json.hpp:2780
basic_json(const CompatibleNumberFloatType val) noexcept
create an floating-point number (implicit)
Definition: json.hpp:1549
iter_impl & operator=(iter_impl other) noexcept(std::is_nothrow_move_constructible< pointer >::value andstd::is_nothrow_move_assignable< pointer >::value andstd::is_nothrow_move_constructible< internal_iterator >::value andstd::is_nothrow_move_assignable< internal_iterator >::value)
copy assignment
Definition: json.hpp:8324
GLfloat GLfloat GLfloat GLfloat h
Definition: glext.h:1960
friend bool operator==(const_reference v, std::nullptr_t) noexcept
comparison: equal
Definition: json.hpp:5633
GLdouble n
Definition: glext.h:1966
unsigned char uint8_t
Definition: stdint.h:78
GLhandleARB obj
Definition: glext.h:4157
boolean_t * get_impl_ptr(boolean_t *) noexcept
get a pointer to the value (boolean)
Definition: json.hpp:2768
IteratorType::reference value() const
return value of the iterator
Definition: json.hpp:8178
void swap(reference other) noexcept(std::is_nothrow_move_constructible< value_t >::value andstd::is_nothrow_move_assignable< value_t >::value andstd::is_nothrow_move_constructible< json_value >::value andstd::is_nothrow_move_assignable< json_value >::value)
exchanges the values
Definition: json.hpp:5362
e
Definition: rmse.py:177
void emplace_back(Args &&...args)
add an object to an array
Definition: json.hpp:5064
GLsizei GLsizei GLfloat distance
Definition: glext.h:10563
boolean_t boolean
boolean
Definition: json.hpp:811
iter_impl(pointer object) noexcept
constructor for a given JSON instance
Definition: json.hpp:8262
void set_end() noexcept
set the iterator past the last value
Definition: json.hpp:8378
#define INT32_MIN
Definition: stdint.h:136
reference operator+=(std::initializer_list< basic_json > init)
add an object to an object
Definition: json.hpp:5036
static void replace_substring(std::string &s, const std::string &f, const std::string &t)
replace all occurrences of a substring by another string
Definition: json.hpp:11325
iterator end() noexcept
returns an iterator to one past the last element
Definition: json.hpp:4358
basic_json(const int val) noexcept
create an integer number from an enum type (explicit)
Definition: json.hpp:1376
basic_json(const CompatibleArrayType &val)
create an array (implicit)
Definition: json.hpp:1206
reference back()
access the last element
Definition: json.hpp:3857
reverse_iterator rend() noexcept
returns an iterator to the reverse-end
Definition: json.hpp:4465
ValueType value(const typename object_t::key_type &key, ValueType default_value) const
access specified object element with default value
Definition: json.hpp:3685
json_value(number_unsigned_t v) noexcept
constructor for numbers (unsigned)
Definition: json.hpp:826
GLdouble t
bool operator>(const iter_impl &other) const
comparison: greater than
Definition: json.hpp:8656
json_reverse_iterator(const typename base_iterator::iterator_type &it) noexcept
create reverse iterator from iterator
Definition: json.hpp:8859
GLboolean GLboolean GLboolean GLboolean a
static basic_json object(std::initializer_list< basic_json > init=std::initializer_list< basic_json >())
explicitly create an object from an initializer list
Definition: json.hpp:1747
basic_json flatten() const
return flattened JSON value
Definition: json.hpp:11599
GLenum GLsizei len
Definition: glext.h:3285
GLuint GLfloat * val
GLuint64 key
Definition: glext.h:8966
constexpr const number_float_t * get_impl_ptr(const number_float_t *) const noexcept
get a pointer to the value (floating-point number)
Definition: json.hpp:2810
reference operator+=(const basic_json &val)
add an object to an array
Definition: json.hpp:4938
static iteration_proxy< const_iterator > iterator_wrapper(const_reference cont)
wrapper to access iterator member functions in range-based for
Definition: json.hpp:4560
iter_impl operator++(int)
post-increment (it++)
Definition: json.hpp:8486
NumberFloatType number_float_t
a type for a number (floating-point)
Definition: json.hpp:712
static basic_json parse(std::istream &&i, const parser_callback_t cb=nullptr)
deserialize from stream
Definition: json.hpp:6056
void set_end() noexcept
set iterator to a defined past the end
Definition: json.hpp:8051
json_reverse_iterator operator+(difference_type i) const
add to iterator
Definition: json.hpp:8902
not_this_one begin(...)
constexpr const array_t * get_impl_ptr(const array_t *) const noexcept
get a pointer to the value (array)
Definition: json.hpp:2750
static constexpr bool value
Definition: json.hpp:127
GLdouble f
static T parse(const mxArray *cell)
basic_json(const value_t value_type)
create an empty value with a given type
Definition: json.hpp:1054
const_reference at(const typename object_t::key_type &key) const
access specified object element with bounds checking
Definition: json.hpp:3274
reference operator*() const
return a reference to the value pointed to by the iterator
Definition: json.hpp:8409
number_float_t * get_impl_ptr(number_float_t *) noexcept
get a pointer to the value (floating-point number)
Definition: json.hpp:2804
bool operator==(const iter_impl &other) const
comparison: equal
Definition: json.hpp:8572
string_t get_string() const
return string value for string tokens
Definition: json.hpp:10247
static basic_json from_cbor_internal(const std::vector< uint8_t > &v, size_t &idx)
create a JSON value from a given CBOR vector
Definition: json.hpp:7079
static basic_json parse(const ContiguousContainer &c, const parser_callback_t cb=nullptr)
deserialize from a container with contiguous storage
Definition: json.hpp:6179
iter_impl & operator-=(difference_type i)
subtract from iterator
Definition: json.hpp:8705
constexpr const number_unsigned_t * get_impl_ptr(const number_unsigned_t *) const noexcept
get a pointer to the value (unsigned number)
Definition: json.hpp:2798
friend class basic_json
allow basic_json to access private members
Definition: json.hpp:8230
iter_impl operator--(int)
post-decrement (it–)
Definition: json.hpp:8529
json_reverse_iterator & operator+=(difference_type i)
add to iterator
Definition: json.hpp:8895
GLsizeiptr size
const_reverse_iterator rend() const noexcept
returns a const reverse iterator to one before the first
Definition: json.hpp:4473
static T * create(Args &&...args)
helper for exception-safe object creation
Definition: json.hpp:761
static void unescape(std::string &s)
unescape tilde and slash
Definition: json.hpp:11349
difference_type operator-(const iter_impl &other) const
return difference
Definition: json.hpp:8736
number_unsigned_t number_unsigned
number (unsigned integer)
Definition: json.hpp:815
const_iterator find(typename object_t::key_type key) const
find an element in a JSON object
Definition: json.hpp:4217
basic_json(const object_t &val)
create an object (explicit)
Definition: json.hpp:1103
#define JSON_DEPRECATED
Definition: json.hpp:90
ImVec4 operator+(const ImVec4 &c, float v)
std::size_t operator()(const nlohmann::json &j) const
return a hash value for a JSON object
Definition: json.hpp:12159
const GLubyte * c
Definition: glext.h:12690
parser(IteratorType first, IteratorType last, const parser_callback_t cb=nullptr)
a parser reading from an iterator range with contiguous storage
Definition: json.hpp:10597
reverse_iterator rbegin() noexcept
returns an iterator to the reverse-beginning
Definition: json.hpp:4428
basic_json(const string_t &val)
create a string (explicit)
Definition: json.hpp:1236
basic_json::string_t key() const
return key of the iterator
Definition: json.hpp:8151
unsigned char lexer_char_t
the char type to use in the lexer
Definition: json.hpp:8980
bool operator!=(const iter_impl &other) const
comparison: not equal
Definition: json.hpp:8605
static std::size_t extra_space(const string_t &s) noexcept
calculates the extra space to escape a JSON string
Definition: json.hpp:7703
iterator find(typename object_t::key_type key)
find an element in a JSON object
Definition: json.hpp:4201
GLdouble x
constexpr bool is_number() const noexcept
return whether value is a number
Definition: json.hpp:2360
iteration_proxy_internal & operator*()
dereference operator (needed for range-based for)
Definition: json.hpp:8130
reference get_checked(pointer ptr) const
Definition: json.hpp:11111
array_t get_impl(array_t *) const
get an array (explicit)
Definition: json.hpp:2667
void set_begin() noexcept
set iterator to a defined beginning
Definition: json.hpp:8045
lexer(std::istream &s)
a lexer from an input stream
Definition: json.hpp:8992
syntax analysis
Definition: json.hpp:10578
array_t * get_impl_ptr(array_t *) noexcept
get a pointer to the value (array)
Definition: json.hpp:2744
static std::string token_type_name(const token_type t)
return name of values of type token_type (only used for errors)
Definition: json.hpp:9106
void swap(object_t &other)
exchanges the values
Definition: json.hpp:5427
BooleanType boolean_t
a type for a boolean
Definition: json.hpp:501
#define INT16_MIN
Definition: stdint.h:134
reference operator[](T *(&key)[n])
access specified object element
Definition: json.hpp:3501
void unexpect(typename lexer::token_type t) const
Definition: json.hpp:10834
string_t * get_impl_ptr(string_t *) noexcept
get a pointer to the value (string)
Definition: json.hpp:2756
array_t::iterator array_iterator
iterator for JSON arrays
Definition: json.hpp:8100
json_reverse_iterator & operator++()
pre-increment (++it)
Definition: json.hpp:8875
namespace for Niels Lohmann
Definition: json.hpp:98
parse_event_t
JSON callback events.
Definition: json.hpp:933
constexpr bool is_end() const noexcept
return whether the iterator is at end
Definition: json.hpp:8063
bool operator<(failed, failed)
constexpr value_t type() const noexcept
return the type of the JSON value (explicit)
Definition: json.hpp:2229
basic_json(size_type cnt, const basic_json &val)
construct an array with count copies of given value
Definition: json.hpp:1771
const_reverse_iterator crend() const noexcept
returns a const reverse iterator to one before the first
Definition: json.hpp:4531
constexpr const number_integer_t * get_impl_ptr(const number_integer_t *) const noexcept
get a pointer to the value (integer number)
Definition: json.hpp:2786
std::function< bool(int depth, parse_event_t event, basic_json &parsed)> parser_callback_t
per-element parser callback type
Definition: json.hpp:1003
internal_iterator() noexcept
create an uninitialized internal_iterator
Definition: json.hpp:8105
constexpr bool is_string() const noexcept
return whether value is a string
Definition: json.hpp:2511
json_reverse_iterator operator-(difference_type i) const
subtract from iterator
Definition: json.hpp:8910
GLenum target
Definition: glext.h:1565
pointer operator->() const
dereference the iterator
Definition: json.hpp:8450
lexer m_lexer
the lexer
Definition: json.hpp:10854
def find(dir, mask)
Definition: file.py:25
def callback(frame)
Definition: t265_stereo.py:91
basic_json value_type
the type of elements in a basic_json container
Definition: json.hpp:245
basic_json(boolean_t val) noexcept
create a boolean (explicit)
Definition: json.hpp:1313
unsigned __int64 uint64_t
Definition: stdint.h:90
std::vector< std::string > reference_tokens
the reference tokens
Definition: json.hpp:11452
json_value(value_t t)
constructor for empty values of a given type
Definition: json.hpp:830
std::string to_string() const noexcept
return a string representation of the JSON pointer
Definition: json.hpp:10916
basic_json(basic_json &&other) noexcept
move constructor
Definition: json.hpp:2045
static basic_json array(std::initializer_list< basic_json > init=std::initializer_list< basic_json >())
explicitly create an array from an initializer list
Definition: json.hpp:1707
void init(void)
Definition: boing.c:180
GLuint start
GLint j
friend std::istream & operator>>(std::istream &i, basic_json &j)
deserialize from stream
Definition: json.hpp:6219
basic_json(const typename string_t::value_type *val)
create a string (explicit)
Definition: json.hpp:1262
object_t::key_type key() const
return the key of an object iterator
Definition: json.hpp:8930
ValueType value(const json_pointer &ptr, ValueType default_value) const
access specified object element via JSON Pointer with default value
Definition: json.hpp:3759
GLint first
friend bool operator==(const_reference lhs, const_reference rhs) noexcept
comparison: equal
Definition: json.hpp:5540
internal_iterator m_it
the actual iterator of the associated instance
Definition: json.hpp:8829
std::vector< T > get_impl(std::vector< T > *) const
get an array (explicit)
Definition: json.hpp:2631
const_reference at(size_type idx) const
access specified array element with bounds checking
Definition: json.hpp:3180
friend std::ostream & operator>>(const basic_json &j, std::ostream &o)
serialize to stream
Definition: json.hpp:5936
#define INT8_MIN
Definition: stdint.h:132
friend std::istream & operator<<(basic_json &j, std::istream &i)
deserialize from stream
Definition: json.hpp:6209
signed char int8_t
Definition: stdint.h:75
reference operator+=(const typename object_t::value_type &val)
add an object to an object
Definition: json.hpp:4988
std::size_t size_type
a type to represent container sizes
Definition: json.hpp:255
reference value() const
return the value of an iterator
Definition: json.hpp:8937
static iteration_proxy< iterator > iterator_wrapper(reference cont)
wrapper to access iterator member functions in range-based for
Definition: json.hpp:4552
reference operator+=(basic_json &&val)
add an object to an array
Definition: json.hpp:4904
const_reference get_unchecked(const_pointer ptr) const
return a const reference to the pointed to value
Definition: json.hpp:11163
json_value m_value
the value of the current element
Definition: json.hpp:8024
void dump(std::ostream &o, const bool pretty_print, const unsigned int indent_step, const unsigned int current_indent=0) const
internal implementation of the serialization function
Definition: json.hpp:7875
reference operator[](size_type idx)
access specified array element
Definition: json.hpp:3320
const_iterator begin() const noexcept
returns a const iterator to the first element
Definition: json.hpp:4297
friend bool operator!=(const_reference v, std::nullptr_t) noexcept
comparison: not equal
Definition: json.hpp:5686
primitive_iterator_t primitive_iterator
generic iterator for all other types
Definition: json.hpp:8102
#define UINT64_MAX
Definition: stdint.h:143
const_reverse_iterator crbegin() const noexcept
returns a const reverse iterator to the last element
Definition: json.hpp:4502
constexpr bool is_number_float() const noexcept
return whether value is a floating-point number
Definition: json.hpp:2445
void swap(nlohmann::json &j1, nlohmann::json &j2) noexcept(is_nothrow_move_constructible< nlohmann::json >::value andis_nothrow_move_assignable< nlohmann::json >::value)
exchanges the values of two JSON objects
Definition: json.hpp:12141
const_iterator cbegin() const noexcept
returns a const iterator to the first element
Definition: json.hpp:4327
token_type
token types for the parser
Definition: json.hpp:8961
array (ordered collection of values)
constexpr bool is_number_integer() const noexcept
return whether value is an integer number
Definition: json.hpp:2389
value_t m_type
the type of the current element
Definition: json.hpp:8021
basic_json patch(const basic_json &json_patch) const
applies a JSON patch
Definition: json.hpp:11683
std::string string_t
basic_json(const CompatibleNumberUnsignedType val) noexcept
create an unsigned number (implicit)
Definition: json.hpp:1471
static basic_json diff(const basic_json &source, const basic_json &target, const std::string &path="")
creates a diff as a JSON patch
Definition: json.hpp:11976
json_reverse_iterator operator++(int)
post-increment (it++)
Definition: json.hpp:8869
auto operator+=(std::string &lhs, StringRef const &sr) -> std::string &
static void to_cbor_internal(const basic_json &j, std::vector< uint8_t > &v)
create a CBOR serialization of a given JSON value
Definition: json.hpp:6580
constexpr bool is_boolean() const noexcept
return whether value is a boolean
Definition: json.hpp:2330
std::string pop_back()
remove and return last reference pointer
Definition: json.hpp:10934
void push_back(basic_json &&val)
add an object to an array
Definition: json.hpp:4878
typename std::allocator_traits< allocator_type >::const_pointer const_pointer
the type of an element const pointer
Definition: json.hpp:263
ReferenceType get_ref()
get a reference value (implicit)
Definition: json.hpp:3044
friend bool operator>(const_reference lhs, const_reference rhs) noexcept
comparison: greater than
Definition: json.hpp:5841
const_reverse_iterator rbegin() const noexcept
returns a const reverse iterator to the last element
Definition: json.hpp:4436
NumberIntegerType number_integer_t
a type for a number (integer)
Definition: json.hpp:573
lexer::token_type get_token()
get next token from lexer
Definition: json.hpp:10815
struct _cl_event * event
Definition: glext.h:2991
basic_json(const number_unsigned_t val) noexcept
create an unsigned integer number (explicit)
Definition: json.hpp:1440
iterator insert(const_iterator pos, basic_json &&val)
inserts element
Definition: json.hpp:5186
#define UINT32_MAX
Definition: stdint.h:142
bool empty() const noexcept
checks whether the container is empty
Definition: json.hpp:4612
bool operator<=(const iter_impl &other) const
comparison: less than or equal
Definition: json.hpp:8647
JSON_DEPRECATED basic_json(std::istream &i, const parser_callback_t cb=nullptr)
construct a JSON value given an input stream
Definition: json.hpp:1936
basic_json(const number_integer_t val) noexcept
create an integer number (explicit)
Definition: json.hpp:1345
void next(auto_any_t cur, type2type< T, C > *)
Definition: foreach.hpp:757
constexpr bool is_null() const noexcept
return whether value is null
Definition: json.hpp:2308
static ReferenceType get_ref_impl(ThisType &obj)
helper function to implement get_ref()
Definition: json.hpp:2827
size_type count(typename object_t::key_type key) const
returns the number of occurrences of a key in a JSON object
Definition: json.hpp:4247
typename std::conditional< std::is_const< U >::value, typename basic_json::const_pointer, typename basic_json::pointer >::type pointer
defines a pointer to the type iterated over (value_type)
Definition: json.hpp:8245
GLenum array
Definition: glext.h:7022
unsigned char byte
Definition: src/types.h:52
basic_json(std::initializer_list< basic_json > init, bool type_deduction=true, value_t manual_type=value_t::array)
create a container (array or object) from an initializer list
Definition: json.hpp:1624
void get_number(basic_json &result) const
return number value for number tokens
Definition: json.hpp:10445
const_reference operator[](T *key) const
read-only access specified object element
Definition: json.hpp:3621
typename std::allocator_traits< allocator_type >::pointer pointer
the type of an element pointer
Definition: json.hpp:261
reference operator[](const json_pointer &ptr)
access specified element via JSON Pointer
Definition: json.hpp:11495
pointer m_object
associated JSON instance
Definition: json.hpp:8827
static void to_msgpack_internal(const basic_json &j, std::vector< uint8_t > &v)
create a MessagePack serialization of a given JSON value
Definition: json.hpp:6335
static auto it
static std::vector< uint8_t > to_msgpack(const basic_json &j)
create a MessagePack serialization of a given JSON value
Definition: json.hpp:7563
proxy class for the iterator_wrapper functions
Definition: json.hpp:4538
value_t
the JSON type enumeration
Definition: json.hpp:743
GLenum type
basic_json parse_internal(bool keep)
the actual parser
Definition: json.hpp:10621
IteratorType erase(IteratorType pos)
remove element given an iterator
Definition: json.hpp:3923
const_reference get_checked(const_pointer ptr) const
Definition: json.hpp:11207
signed __int64 int64_t
Definition: stdint.h:89
const_reference at(const json_pointer &ptr) const
access specified element via JSON Pointer
Definition: json.hpp:11572
json_pointer(const std::string &s="")
create JSON pointer
Definition: json.hpp:10897
reference at(size_type idx)
access specified array element with bounds checking
Definition: json.hpp:3137
static string_t escape_string(const string_t &s)
escape a string
Definition: json.hpp:7751
constexpr boolean_t get_impl(boolean_t *) const
get a boolean (explicit)
Definition: json.hpp:2724
static basic_json from_msgpack(const std::vector< uint8_t > &v)
create a JSON value from a byte vector in MessagePack format
Definition: json.hpp:7592
basic_json(const CompatibleNumberIntegerType val) noexcept
create an integer number (implicit)
Definition: json.hpp:1413
void push_back(const typename object_t::value_type &val)
add an object to an object
Definition: json.hpp:4964
string_t dump(const int indent=-1) const
serialization
Definition: json.hpp:2187
void expect(typename lexer::token_type t) const
Definition: json.hpp:10821
reference value() const
return the value of an iterator
Definition: json.hpp:8820
static basic_json parse(std::istream &i, const parser_callback_t cb=nullptr)
deserialize from stream
Definition: json.hpp:6047
object (unordered set of name/value pairs)
IteratorType::reference container
the container to iterate
Definition: json.hpp:8185
ReferenceType get_ref() const
get a reference value (implicit)
Definition: json.hpp:3057
friend bool operator<(const value_t lhs, const value_t rhs) noexcept
comparison operator for JSON types
Definition: json.hpp:5493
basic_json(const array_t &val)
create an array (explicit)
Definition: json.hpp:1166
typename::boost::move_detail::remove_reference< T >::type && move(T &&t) BOOST_NOEXCEPT
static std::vector< uint8_t > to_cbor(const basic_json &j)
create a MessagePack serialization of a given JSON value
Definition: json.hpp:7619
GLsizei GLsizei GLchar * source
#define INT16_MAX
Definition: stdint.h:135
float rs2_vector::* pos
json_pointer top() const
Definition: json.hpp:10952
iteration_proxy(typename IteratorType::reference cont)
construct iteration proxy from a container
Definition: json.hpp:8189
iter_impl operator+(difference_type i)
add to iterator
Definition: json.hpp:8714
int stoi(const std::string &value)
T * array_end(T BOOST_RANGE_ARRAY_REF()[sz])
object_t * object
object (stored with pointer to save storage)
Definition: json.hpp:805
#define NULL
Definition: tinycthread.c:47
const_reference operator[](T *(&key)[n]) const
read-only access specified object element
Definition: json.hpp:3536
int i
iter_impl(const iter_impl &other) noexcept
copy constructor
Definition: json.hpp:8315
string_t value(const json_pointer &ptr, const char *default_value) const
overload for a default value of type const char*
Definition: json.hpp:3784
GLuint res
Definition: glext.h:8856
reference operator[](difference_type n) const
access to successor
Definition: json.hpp:8763
static std::string escape(std::string s)
escape tilde and slash
Definition: json.hpp:11340
iterator insert(const_iterator pos, std::initializer_list< basic_json > ilist)
inserts elements
Definition: json.hpp:5325
typename basic_json::value_type value_type
the type of the values when the iterator is dereferenced
Definition: json.hpp:8239
json_value(number_integer_t v) noexcept
constructor for numbers (integer)
Definition: json.hpp:824
number_unsigned_t * get_impl_ptr(number_unsigned_t *) noexcept
get a pointer to the value (unsigned number)
Definition: json.hpp:2792
GLuint GLenum GLenum transform
Definition: glext.h:11553
size_type erase(const typename object_t::key_type &key)
remove element from a JSON object given a key
Definition: json.hpp:4118
void erase(const size_type idx)
remove element from a JSON array given an index
Definition: json.hpp:4155
static string_t to_unicode(const std::size_t codepoint1, const std::size_t codepoint2=0)
create a string from one or two Unicode code points
Definition: json.hpp:9041
void clear() noexcept
clears the contents
Definition: json.hpp:4805
a template for a reverse iterator class
Definition: json.hpp:232
NumberUnsignedType number_unsigned_t
a type for a number (unsigned)
Definition: json.hpp:644
unsigned char advance
T get_impl(T *) const
get an object (explicit)
Definition: json.hpp:2577
static T get_from_vector(const std::vector< uint8_t > &vec, const size_t current_index)
take sufficient bytes from a vector to fill an integer variable
Definition: json.hpp:6309
static basic_json from_cbor(const std::vector< uint8_t > &v)
create a JSON value from a byte vector in CBOR format
Definition: json.hpp:7649
long double str_to_float_t(long double *, char **endptr) const
parse floating point number
Definition: json.hpp:10375
std::reverse_iterator< Base > base_iterator
shortcut to the reverse iterator adaptor
Definition: json.hpp:8854
#define UINT16_MAX
Definition: stdint.h:141
reference operator[](T *key)
access specified object element
Definition: json.hpp:3569
iter_impl & operator++()
pre-increment (++it)
Definition: json.hpp:8497
friend bool operator!=(std::nullptr_t, const_reference v) noexcept
comparison: not equal
Definition: json.hpp:5695
typename Base::reference reference
the reference type for the pointed-to element
Definition: json.hpp:8856
boost::iterators::detail::postfix_increment_result< I, V, R, TC >::type operator++(iterator_facade< I, V, TC, R, D > &i, int)
friend bool operator<=(const_reference lhs, const_reference rhs) noexcept
comparison: less than or equal
Definition: json.hpp:5819
void fill_line_buffer(size_t n=0)
append data from the stream to the line buffer
Definition: json.hpp:10121
GLuint64EXT * result
Definition: glext.h:10921
friend bool operator>=(const_reference lhs, const_reference rhs) noexcept
comparison: greater than or equal
Definition: json.hpp:5863
friend bool operator!=(const_reference lhs, const_reference rhs) noexcept
comparison: not equal
Definition: json.hpp:5663
GLdouble v
basic_json parse()
public parser interface
Definition: json.hpp:10604
bool operator<(const iter_impl &other) const
comparison: smaller
Definition: json.hpp:8614
iterator begin() noexcept
returns an iterator to the first element
Definition: json.hpp:4287
GLint GLint GLint GLint j2
YYCODETYPE lhs
Definition: sqlite3.c:132469
GeneratorWrapper< T > map(Func &&function, GeneratorWrapper< U > &&generator)
Definition: catch.hpp:4271
float str_to_float_t(float *, char **endptr) const
parse floating point number
Definition: json.hpp:10415
constexpr const string_t * get_impl_ptr(const string_t *) const noexcept
get a pointer to the value (string)
Definition: json.hpp:2762
StringType string_t
a type for a string
Definition: json.hpp:475
constexpr const boolean_t * get_impl_ptr(const boolean_t *) const noexcept
get a pointer to the value (boolean)
Definition: json.hpp:2774
static basic_json parse(IteratorType first, IteratorType last, const parser_callback_t cb=nullptr)
deserialize from an iterator range with contiguous storage
Definition: json.hpp:6107
reference front()
access the first element
Definition: json.hpp:3814
iterator insert(const_iterator pos, size_type cnt, const basic_json &val)
inserts elements
Definition: json.hpp:5215
void set_begin() noexcept
set the iterator to the first value
Definition: json.hpp:8341
friend bool operator==(std::nullptr_t, const_reference v) noexcept
comparison: equal
Definition: json.hpp:5642
basic_json(const basic_json &other)
copy constructor
Definition: json.hpp:1968
a template for a random access iterator for the basic_json class
Definition: json.hpp:231
string_t get_token_string() const
return string representation of last read token
Definition: json.hpp:10183
parser(std::istream &is, const parser_callback_t cb=nullptr)
a parser reading from an input stream
Definition: json.hpp:10588
ArrayType< basic_json, AllocatorType< basic_json >> array_t
a type for an array
Definition: json.hpp:428
void copy(void *dst, void const *src, size_t size)
Definition: types.cpp:836
const_reference operator[](size_type idx) const
access specified array element
Definition: json.hpp:3368
json_value(number_float_t v) noexcept
constructor for numbers (floating-point)
Definition: json.hpp:828
bool operator<=(failed, failed)
~basic_json()
destructor
Definition: json.hpp:2115
GLintptr offset
constexpr bool is_begin() const noexcept
return whether the iterator can be dereferenced
Definition: json.hpp:8057
array_t * array
array (stored with pointer to save storage)
Definition: json.hpp:807
void push_back(std::initializer_list< basic_json > init)
add an object to an object
Definition: json.hpp:5019
static std::vector< std::string > split(const std::string &reference_string)
split the string input to reference tokens
Definition: json.hpp:11252
void swap(array_t &other)
exchanges the values
Definition: json.hpp:5394
std::string to_string(T value)
reference operator[](const typename object_t::key_type &key)
access specified object element
Definition: json.hpp:3408


librealsense2
Author(s): Sergey Dorodnicov , Doron Hirshberg , Mark Horn , Reagan Lopez , Itay Carpis
autogenerated on Mon May 3 2021 02:47:21