JSON for Modern C++  2.0.10
json.hpp
1 /*
2  __ _____ _____ _____
3  __| | __| | | | JSON for Modern C++
4 | | |__ | | | | | | version 2.0.10
5 |_____|_____|_____|_|___| https://github.com/nlohmann/json
6 
7 Licensed under the MIT License <http://opensource.org/licenses/MIT>.
8 Copyright (c) 2013-2017 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 } // namespace
132 
212 template <
213  template<typename U, typename V, typename... Args> class ObjectType = std::map,
214  template<typename U, typename... Args> class ArrayType = std::vector,
215  class StringType = std::string,
216  class BooleanType = bool,
217  class NumberIntegerType = std::int64_t,
218  class NumberUnsignedType = std::uint64_t,
219  class NumberFloatType = double,
220  template<typename U> class AllocatorType = std::allocator
221  >
223 {
224  private:
226  using basic_json_t = basic_json<ObjectType, ArrayType, StringType,
227  BooleanType, NumberIntegerType, NumberUnsignedType, NumberFloatType,
228  AllocatorType>;
229 
230  public:
231  // forward declarations
232  template<typename U> class iter_impl;
233  template<typename Base> class json_reverse_iterator;
234  class json_pointer;
235 
237  // container types //
239 
244 
247 
251  using const_reference = const value_type&;
252 
254  using difference_type = std::ptrdiff_t;
256  using size_type = std::size_t;
257 
259  using allocator_type = AllocatorType<basic_json>;
260 
262  using pointer = typename std::allocator_traits<allocator_type>::pointer;
264  using const_pointer = typename std::allocator_traits<allocator_type>::const_pointer;
265 
274 
276 
277 
282  {
283  return allocator_type();
284  }
285 
286 
288  // JSON value data types //
290 
295 
379  using object_t = ObjectType<StringType,
380  basic_json,
381  std::less<StringType>,
382  AllocatorType<std::pair<const StringType,
383  basic_json>>>;
384 
429  using array_t = ArrayType<basic_json, AllocatorType<basic_json>>;
430 
482  using string_t = StringType;
483 
508  using boolean_t = BooleanType;
509 
580  using number_integer_t = NumberIntegerType;
581 
651  using number_unsigned_t = NumberUnsignedType;
652 
719  using number_float_t = NumberFloatType;
720 
722 
723 
725  // JSON type enumeration //
727 
750  enum class value_t : uint8_t
751  {
752  null,
753  object,
754  array,
755  string,
756  boolean,
757  number_integer,
758  number_unsigned,
759  number_float,
760  discarded
761  };
762 
763 
764  private:
765 
767  template<typename T, typename... Args>
768  static T* create(Args&& ... args)
769  {
770  AllocatorType<T> alloc;
771  auto deleter = [&](T * object)
772  {
773  alloc.deallocate(object, 1);
774  };
775  std::unique_ptr<T, decltype(deleter)> object(alloc.allocate(1), deleter);
776  alloc.construct(object.get(), std::forward<Args>(args)...);
777  assert(object != nullptr);
778  return object.release();
779  }
780 
782  // JSON value storage //
784 
809  union json_value
810  {
812  object_t* object;
814  array_t* array;
816  string_t* string;
818  boolean_t boolean;
820  number_integer_t number_integer;
822  number_unsigned_t number_unsigned;
824  number_float_t number_float;
825 
827  json_value() = default;
829  json_value(boolean_t v) noexcept : boolean(v) {}
831  json_value(number_integer_t v) noexcept : number_integer(v) {}
833  json_value(number_unsigned_t v) noexcept : number_unsigned(v) {}
835  json_value(number_float_t v) noexcept : number_float(v) {}
837  json_value(value_t t)
838  {
839  switch (t)
840  {
841  case value_t::object:
842  {
843  object = create<object_t>();
844  break;
845  }
846 
847  case value_t::array:
848  {
849  array = create<array_t>();
850  break;
851  }
852 
853  case value_t::string:
854  {
855  string = create<string_t>("");
856  break;
857  }
858 
859  case value_t::boolean:
860  {
861  boolean = boolean_t(false);
862  break;
863  }
864 
865  case value_t::number_integer:
866  {
867  number_integer = number_integer_t(0);
868  break;
869  }
870 
871  case value_t::number_unsigned:
872  {
873  number_unsigned = number_unsigned_t(0);
874  break;
875  }
876 
877  case value_t::number_float:
878  {
879  number_float = number_float_t(0.0);
880  break;
881  }
882 
883  case value_t::null:
884  {
885  break;
886  }
887 
888  default:
889  {
890  if (t == value_t::null)
891  {
892  throw std::domain_error("961c151d2e87f2686a955a9be24d316f1362bf21 2.0.10"); // LCOV_EXCL_LINE
893  }
894  break;
895  }
896  }
897  }
898 
900  json_value(const string_t& value)
901  {
902  string = create<string_t>(value);
903  }
904 
906  json_value(const object_t& value)
907  {
908  object = create<object_t>(value);
909  }
910 
912  json_value(const array_t& value)
913  {
914  array = create<array_t>(value);
915  }
916  };
917 
927  void assert_invariant() const
928  {
929  assert(m_type != value_t::object or m_value.object != nullptr);
930  assert(m_type != value_t::array or m_value.array != nullptr);
931  assert(m_type != value_t::string or m_value.string != nullptr);
932  }
933 
934  public:
936  // JSON parser callback //
938 
949  enum class parse_event_t : uint8_t
950  {
952  object_start,
954  object_end,
956  array_start,
958  array_end,
960  key,
962  value
963  };
964 
1017  using parser_callback_t = std::function<bool(int depth,
1018  parse_event_t event,
1019  basic_json& parsed)>;
1020 
1021 
1023  // constructors //
1025 
1030 
1071  : m_type(value_type), m_value(value_type)
1072  {
1073  assert_invariant();
1074  }
1075 
1094  basic_json(std::nullptr_t = nullptr) noexcept
1095  : basic_json(value_t::null)
1096  {
1097  assert_invariant();
1098  }
1099 
1119  basic_json(const object_t& val)
1120  : m_type(value_t::object), m_value(val)
1121  {
1122  assert_invariant();
1123  }
1124 
1151  template<class CompatibleObjectType, typename std::enable_if<
1152  std::is_constructible<typename object_t::key_type, typename CompatibleObjectType::key_type>::value and
1153  std::is_constructible<basic_json, typename CompatibleObjectType::mapped_type>::value, int>::type = 0>
1154  basic_json(const CompatibleObjectType& val)
1155  : m_type(value_t::object)
1156  {
1157  using std::begin;
1158  using std::end;
1159  m_value.object = create<object_t>(begin(val), end(val));
1160  assert_invariant();
1161  }
1162 
1182  basic_json(const array_t& val)
1183  : m_type(value_t::array), m_value(val)
1184  {
1185  assert_invariant();
1186  }
1187 
1214  template<class CompatibleArrayType, typename std::enable_if<
1215  not std::is_same<CompatibleArrayType, typename basic_json_t::iterator>::value and
1216  not std::is_same<CompatibleArrayType, typename basic_json_t::const_iterator>::value and
1217  not std::is_same<CompatibleArrayType, typename basic_json_t::reverse_iterator>::value and
1218  not std::is_same<CompatibleArrayType, typename basic_json_t::const_reverse_iterator>::value and
1219  not std::is_same<CompatibleArrayType, typename array_t::iterator>::value and
1220  not std::is_same<CompatibleArrayType, typename array_t::const_iterator>::value and
1221  std::is_constructible<basic_json, typename CompatibleArrayType::value_type>::value, int>::type = 0>
1222  basic_json(const CompatibleArrayType& val)
1223  : m_type(value_t::array)
1224  {
1225  using std::begin;
1226  using std::end;
1227  m_value.array = create<array_t>(begin(val), end(val));
1228  assert_invariant();
1229  }
1230 
1252  basic_json(const string_t& val)
1253  : m_type(value_t::string), m_value(val)
1254  {
1255  assert_invariant();
1256  }
1257 
1278  basic_json(const typename string_t::value_type* val)
1279  : basic_json(string_t(val))
1280  {
1281  assert_invariant();
1282  }
1283 
1307  template<class CompatibleStringType, typename std::enable_if<
1308  std::is_constructible<string_t, CompatibleStringType>::value, int>::type = 0>
1309  basic_json(const CompatibleStringType& val)
1310  : basic_json(string_t(val))
1311  {
1312  assert_invariant();
1313  }
1314 
1329  basic_json(boolean_t val) noexcept
1330  : m_type(value_t::boolean), m_value(val)
1331  {
1332  assert_invariant();
1333  }
1334 
1358  template<typename T, typename std::enable_if<
1359  not (std::is_same<T, int>::value) and
1360  std::is_same<T, number_integer_t>::value, int>::type = 0>
1361  basic_json(const number_integer_t val) noexcept
1362  : m_type(value_t::number_integer), m_value(val)
1363  {
1364  assert_invariant();
1365  }
1366 
1392  basic_json(const int val) noexcept
1393  : m_type(value_t::number_integer),
1394  m_value(static_cast<number_integer_t>(val))
1395  {
1396  assert_invariant();
1397  }
1398 
1424  template<typename CompatibleNumberIntegerType, typename std::enable_if<
1425  std::is_constructible<number_integer_t, CompatibleNumberIntegerType>::value and
1426  std::numeric_limits<CompatibleNumberIntegerType>::is_integer and
1427  std::numeric_limits<CompatibleNumberIntegerType>::is_signed,
1428  CompatibleNumberIntegerType>::type = 0>
1429  basic_json(const CompatibleNumberIntegerType val) noexcept
1430  : m_type(value_t::number_integer),
1431  m_value(static_cast<number_integer_t>(val))
1432  {
1433  assert_invariant();
1434  }
1435 
1453  template<typename T, typename std::enable_if<
1454  not (std::is_same<T, int>::value) and
1455  std::is_same<T, number_unsigned_t>::value, int>::type = 0>
1456  basic_json(const number_unsigned_t val) noexcept
1457  : m_type(value_t::number_unsigned), m_value(val)
1458  {
1459  assert_invariant();
1460  }
1461 
1482  template<typename CompatibleNumberUnsignedType, typename std::enable_if <
1483  std::is_constructible<number_unsigned_t, CompatibleNumberUnsignedType>::value and
1484  std::numeric_limits<CompatibleNumberUnsignedType>::is_integer and
1485  not std::numeric_limits<CompatibleNumberUnsignedType>::is_signed,
1486  CompatibleNumberUnsignedType>::type = 0>
1487  basic_json(const CompatibleNumberUnsignedType val) noexcept
1488  : m_type(value_t::number_unsigned),
1489  m_value(static_cast<number_unsigned_t>(val))
1490  {
1491  assert_invariant();
1492  }
1493 
1518  basic_json(const number_float_t val) noexcept
1519  : m_type(value_t::number_float), m_value(val)
1520  {
1521  // replace infinity and NAN by null
1522  if (not std::isfinite(val))
1523  {
1524  m_type = value_t::null;
1525  m_value = json_value();
1526  }
1527 
1528  assert_invariant();
1529  }
1530 
1562  template<typename CompatibleNumberFloatType, typename = typename std::enable_if<
1563  std::is_constructible<number_float_t, CompatibleNumberFloatType>::value and
1564  std::is_floating_point<CompatibleNumberFloatType>::value>::type>
1565  basic_json(const CompatibleNumberFloatType val) noexcept
1566  : basic_json(number_float_t(val))
1567  {
1568  assert_invariant();
1569  }
1570 
1640  basic_json(std::initializer_list<basic_json> init,
1641  bool type_deduction = true,
1642  value_t manual_type = value_t::array)
1643  {
1644  // check if each element is an array with two elements whose first
1645  // element is a string
1646  bool is_an_object = std::all_of(init.begin(), init.end(),
1647  [](const basic_json & element)
1648  {
1649  return element.is_array() and element.size() == 2 and element[0].is_string();
1650  });
1651 
1652  // adjust type if type deduction is not wanted
1653  if (not type_deduction)
1654  {
1655  // if array is wanted, do not create an object though possible
1656  if (manual_type == value_t::array)
1657  {
1658  is_an_object = false;
1659  }
1660 
1661  // if object is wanted but impossible, throw an exception
1662  if (manual_type == value_t::object and not is_an_object)
1663  {
1664  throw std::domain_error("cannot create object from initializer list");
1665  }
1666  }
1667 
1668  if (is_an_object)
1669  {
1670  // the initializer list is a list of pairs -> create object
1671  m_type = value_t::object;
1672  m_value = value_t::object;
1673 
1674  std::for_each(init.begin(), init.end(), [this](const basic_json & element)
1675  {
1676  m_value.object->emplace(*(element[0].m_value.string), element[1]);
1677  });
1678  }
1679  else
1680  {
1681  // the initializer list describes an array -> create array
1682  m_type = value_t::array;
1683  m_value.array = create<array_t>(init);
1684  }
1685 
1686  assert_invariant();
1687  }
1688 
1723  static basic_json array(std::initializer_list<basic_json> init =
1724  std::initializer_list<basic_json>())
1725  {
1726  return basic_json(init, false, value_t::array);
1727  }
1728 
1763  static basic_json object(std::initializer_list<basic_json> init =
1764  std::initializer_list<basic_json>())
1765  {
1766  return basic_json(init, false, value_t::object);
1767  }
1768 
1788  : m_type(value_t::array)
1789  {
1790  m_value.array = create<array_t>(cnt, val);
1791  assert_invariant();
1792  }
1793 
1831  template<class InputIT, typename std::enable_if<
1832  std::is_same<InputIT, typename basic_json_t::iterator>::value or
1833  std::is_same<InputIT, typename basic_json_t::const_iterator>::value, int>::type = 0>
1834  basic_json(InputIT first, InputIT last)
1835  {
1836  assert(first.m_object != nullptr);
1837  assert(last.m_object != nullptr);
1838 
1839  // make sure iterator fits the current value
1840  if (first.m_object != last.m_object)
1841  {
1842  throw std::domain_error("iterators are not compatible");
1843  }
1844 
1845  // copy type from first iterator
1846  m_type = first.m_object->m_type;
1847 
1848  // check if iterator range is complete for primitive values
1849  switch (m_type)
1850  {
1851  case value_t::boolean:
1852  case value_t::number_float:
1853  case value_t::number_integer:
1854  case value_t::number_unsigned:
1855  case value_t::string:
1856  {
1857  if (not first.m_it.primitive_iterator.is_begin() or not last.m_it.primitive_iterator.is_end())
1858  {
1859  throw std::out_of_range("iterators out of range");
1860  }
1861  break;
1862  }
1863 
1864  default:
1865  {
1866  break;
1867  }
1868  }
1869 
1870  switch (m_type)
1871  {
1872  case value_t::number_integer:
1873  {
1874  m_value.number_integer = first.m_object->m_value.number_integer;
1875  break;
1876  }
1877 
1878  case value_t::number_unsigned:
1879  {
1880  m_value.number_unsigned = first.m_object->m_value.number_unsigned;
1881  break;
1882  }
1883 
1884  case value_t::number_float:
1885  {
1886  m_value.number_float = first.m_object->m_value.number_float;
1887  break;
1888  }
1889 
1890  case value_t::boolean:
1891  {
1892  m_value.boolean = first.m_object->m_value.boolean;
1893  break;
1894  }
1895 
1896  case value_t::string:
1897  {
1898  m_value = *first.m_object->m_value.string;
1899  break;
1900  }
1901 
1902  case value_t::object:
1903  {
1904  m_value.object = create<object_t>(first.m_it.object_iterator,
1905  last.m_it.object_iterator);
1906  break;
1907  }
1908 
1909  case value_t::array:
1910  {
1911  m_value.array = create<array_t>(first.m_it.array_iterator,
1912  last.m_it.array_iterator);
1913  break;
1914  }
1915 
1916  default:
1917  {
1918  throw std::domain_error("cannot use construct with iterators from " + first.m_object->type_name());
1919  }
1920  }
1921 
1922  assert_invariant();
1923  }
1924 
1953  JSON_DEPRECATED
1954  explicit basic_json(std::istream& i, const parser_callback_t cb = nullptr)
1955  {
1956  *this = parser(i, cb).parse();
1957  assert_invariant();
1958  }
1959 
1961  // other constructors and destructor //
1963 
1986  basic_json(const basic_json& other)
1987  : m_type(other.m_type)
1988  {
1989  // check of passed value is valid
1990  other.assert_invariant();
1991 
1992  switch (m_type)
1993  {
1994  case value_t::object:
1995  {
1996  m_value = *other.m_value.object;
1997  break;
1998  }
1999 
2000  case value_t::array:
2001  {
2002  m_value = *other.m_value.array;
2003  break;
2004  }
2005 
2006  case value_t::string:
2007  {
2008  m_value = *other.m_value.string;
2009  break;
2010  }
2011 
2012  case value_t::boolean:
2013  {
2014  m_value = other.m_value.boolean;
2015  break;
2016  }
2017 
2018  case value_t::number_integer:
2019  {
2020  m_value = other.m_value.number_integer;
2021  break;
2022  }
2023 
2024  case value_t::number_unsigned:
2025  {
2026  m_value = other.m_value.number_unsigned;
2027  break;
2028  }
2029 
2030  case value_t::number_float:
2031  {
2032  m_value = other.m_value.number_float;
2033  break;
2034  }
2035 
2036  default:
2037  {
2038  break;
2039  }
2040  }
2041 
2042  assert_invariant();
2043  }
2044 
2063  basic_json(basic_json&& other) noexcept
2064  : m_type(std::move(other.m_type)),
2065  m_value(std::move(other.m_value))
2066  {
2067  // check that passed value is valid
2068  other.assert_invariant();
2069 
2070  // invalidate payload
2071  other.m_type = value_t::null;
2072  other.m_value = {};
2073 
2074  assert_invariant();
2075  }
2076 
2100  reference& operator=(basic_json other) noexcept (
2101  std::is_nothrow_move_constructible<value_t>::value and
2102  std::is_nothrow_move_assignable<value_t>::value and
2103  std::is_nothrow_move_constructible<json_value>::value and
2104  std::is_nothrow_move_assignable<json_value>::value
2105  )
2106  {
2107  // check that passed value is valid
2108  other.assert_invariant();
2109 
2110  using std::swap;
2111  swap(m_type, other.m_type);
2112  swap(m_value, other.m_value);
2113 
2114  assert_invariant();
2115  return *this;
2116  }
2117 
2134  {
2135  assert_invariant();
2136 
2137  switch (m_type)
2138  {
2139  case value_t::object:
2140  {
2141  AllocatorType<object_t> alloc;
2142  alloc.destroy(m_value.object);
2143  alloc.deallocate(m_value.object, 1);
2144  break;
2145  }
2146 
2147  case value_t::array:
2148  {
2149  AllocatorType<array_t> alloc;
2150  alloc.destroy(m_value.array);
2151  alloc.deallocate(m_value.array, 1);
2152  break;
2153  }
2154 
2155  case value_t::string:
2156  {
2157  AllocatorType<string_t> alloc;
2158  alloc.destroy(m_value.string);
2159  alloc.deallocate(m_value.string, 1);
2160  break;
2161  }
2162 
2163  default:
2164  {
2165  // all other types need no specific destructor
2166  break;
2167  }
2168  }
2169  }
2170 
2172 
2173  public:
2175  // object inspection //
2177 
2181 
2205  string_t dump(const int indent = -1) const
2206  {
2207  std::stringstream ss;
2208  // fix locale problems
2209  ss.imbue(std::locale::classic());
2210 
2211  // 6, 15 or 16 digits of precision allows round-trip IEEE 754
2212  // string->float->string, string->double->string or string->long
2213  // double->string; to be safe, we read this value from
2214  // std::numeric_limits<number_float_t>::digits10
2215  ss.precision(std::numeric_limits<double>::digits10);
2216 
2217  if (indent >= 0)
2218  {
2219  dump(ss, true, static_cast<unsigned int>(indent));
2220  }
2221  else
2222  {
2223  dump(ss, false, 0);
2224  }
2225 
2226  return ss.str();
2227  }
2228 
2247  constexpr value_t type() const noexcept
2248  {
2249  return m_type;
2250  }
2251 
2277  constexpr bool is_primitive() const noexcept
2278  {
2279  return is_null() or is_string() or is_boolean() or is_number();
2280  }
2281 
2304  constexpr bool is_structured() const noexcept
2305  {
2306  return is_array() or is_object();
2307  }
2308 
2326  constexpr bool is_null() const noexcept
2327  {
2328  return m_type == value_t::null;
2329  }
2330 
2348  constexpr bool is_boolean() const noexcept
2349  {
2350  return m_type == value_t::boolean;
2351  }
2352 
2378  constexpr bool is_number() const noexcept
2379  {
2380  return is_number_integer() or is_number_float();
2381  }
2382 
2407  constexpr bool is_number_integer() const noexcept
2408  {
2409  return m_type == value_t::number_integer or m_type == value_t::number_unsigned;
2410  }
2411 
2435  constexpr bool is_number_unsigned() const noexcept
2436  {
2437  return m_type == value_t::number_unsigned;
2438  }
2439 
2463  constexpr bool is_number_float() const noexcept
2464  {
2465  return m_type == value_t::number_float;
2466  }
2467 
2485  constexpr bool is_object() const noexcept
2486  {
2487  return m_type == value_t::object;
2488  }
2489 
2507  constexpr bool is_array() const noexcept
2508  {
2509  return m_type == value_t::array;
2510  }
2511 
2529  constexpr bool is_string() const noexcept
2530  {
2531  return m_type == value_t::string;
2532  }
2533 
2556  constexpr bool is_discarded() const noexcept
2557  {
2558  return m_type == value_t::discarded;
2559  }
2560 
2579  constexpr operator value_t() const noexcept
2580  {
2581  return m_type;
2582  }
2583 
2585 
2586  private:
2588  // value access //
2590 
2592  template<class T, typename std::enable_if<
2593  std::is_convertible<typename object_t::key_type, typename T::key_type>::value and
2594  std::is_convertible<basic_json_t, typename T::mapped_type>::value, int>::type = 0>
2595  T get_impl(T* /*unused*/) const
2596  {
2597  if (is_object())
2598  {
2599  return T(m_value.object->begin(), m_value.object->end());
2600  }
2601 
2602  throw std::domain_error("type must be object, but is " + type_name());
2603  }
2604 
2606  object_t get_impl(object_t* /*unused*/) const
2607  {
2608  if (is_object())
2609  {
2610  return *(m_value.object);
2611  }
2612 
2613  throw std::domain_error("type must be object, but is " + type_name());
2614  }
2615 
2617  template<class T, typename std::enable_if<
2618  std::is_convertible<basic_json_t, typename T::value_type>::value and
2619  not std::is_same<basic_json_t, typename T::value_type>::value and
2620  not std::is_arithmetic<T>::value and
2621  not std::is_convertible<std::string, T>::value and
2622  not has_mapped_type<T>::value, int>::type = 0>
2623  T get_impl(T* /*unused*/) const
2624  {
2625  if (is_array())
2626  {
2627  T to_vector;
2628  std::transform(m_value.array->begin(), m_value.array->end(),
2629  std::inserter(to_vector, to_vector.end()), [](basic_json i)
2630  {
2631  return i.get<typename T::value_type>();
2632  });
2633  return to_vector;
2634  }
2635 
2636  throw std::domain_error("type must be array, but is " + type_name());
2637  }
2638 
2640  template<class T, typename std::enable_if<
2641  std::is_convertible<basic_json_t, T>::value and
2642  not std::is_same<basic_json_t, T>::value, int>::type = 0>
2643  std::vector<T> get_impl(std::vector<T>* /*unused*/) const
2644  {
2645  if (is_array())
2646  {
2647  std::vector<T> to_vector;
2648  to_vector.reserve(m_value.array->size());
2649  std::transform(m_value.array->begin(), m_value.array->end(),
2650  std::inserter(to_vector, to_vector.end()), [](basic_json i)
2651  {
2652  return i.get<T>();
2653  });
2654  return to_vector;
2655  }
2656 
2657  throw std::domain_error("type must be array, but is " + type_name());
2658  }
2659 
2661  template<class T, typename std::enable_if<
2662  std::is_same<basic_json, typename T::value_type>::value and
2663  not has_mapped_type<T>::value, int>::type = 0>
2664  T get_impl(T* /*unused*/) const
2665  {
2666  if (is_array())
2667  {
2668  return T(m_value.array->begin(), m_value.array->end());
2669  }
2670 
2671  throw std::domain_error("type must be array, but is " + type_name());
2672  }
2673 
2675  array_t get_impl(array_t* /*unused*/) const
2676  {
2677  if (is_array())
2678  {
2679  return *(m_value.array);
2680  }
2681 
2682  throw std::domain_error("type must be array, but is " + type_name());
2683  }
2684 
2686  template<typename T, typename std::enable_if<
2687  std::is_convertible<string_t, T>::value, int>::type = 0>
2688  T get_impl(T* /*unused*/) const
2689  {
2690  if (is_string())
2691  {
2692  return *m_value.string;
2693  }
2694 
2695  throw std::domain_error("type must be string, but is " + type_name());
2696  }
2697 
2699  template<typename T, typename std::enable_if<
2700  std::is_arithmetic<T>::value, int>::type = 0>
2701  T get_impl(T* /*unused*/) const
2702  {
2703  switch (m_type)
2704  {
2705  case value_t::number_integer:
2706  {
2707  return static_cast<T>(m_value.number_integer);
2708  }
2709 
2710  case value_t::number_unsigned:
2711  {
2712  return static_cast<T>(m_value.number_unsigned);
2713  }
2714 
2715  case value_t::number_float:
2716  {
2717  return static_cast<T>(m_value.number_float);
2718  }
2719 
2720  default:
2721  {
2722  throw std::domain_error("type must be number, but is " + type_name());
2723  }
2724  }
2725  }
2726 
2728  constexpr boolean_t get_impl(boolean_t* /*unused*/) const
2729  {
2730  return is_boolean()
2731  ? m_value.boolean
2732  : throw std::domain_error("type must be boolean, but is " + type_name());
2733  }
2734 
2736  object_t* get_impl_ptr(object_t* /*unused*/) noexcept
2737  {
2738  return is_object() ? m_value.object : nullptr;
2739  }
2740 
2742  constexpr const object_t* get_impl_ptr(const object_t* /*unused*/) const noexcept
2743  {
2744  return is_object() ? m_value.object : nullptr;
2745  }
2746 
2748  array_t* get_impl_ptr(array_t* /*unused*/) noexcept
2749  {
2750  return is_array() ? m_value.array : nullptr;
2751  }
2752 
2754  constexpr const array_t* get_impl_ptr(const array_t* /*unused*/) const noexcept
2755  {
2756  return is_array() ? m_value.array : nullptr;
2757  }
2758 
2760  string_t* get_impl_ptr(string_t* /*unused*/) noexcept
2761  {
2762  return is_string() ? m_value.string : nullptr;
2763  }
2764 
2766  constexpr const string_t* get_impl_ptr(const string_t* /*unused*/) const noexcept
2767  {
2768  return is_string() ? m_value.string : nullptr;
2769  }
2770 
2772  boolean_t* get_impl_ptr(boolean_t* /*unused*/) noexcept
2773  {
2774  return is_boolean() ? &m_value.boolean : nullptr;
2775  }
2776 
2778  constexpr const boolean_t* get_impl_ptr(const boolean_t* /*unused*/) const noexcept
2779  {
2780  return is_boolean() ? &m_value.boolean : nullptr;
2781  }
2782 
2784  number_integer_t* get_impl_ptr(number_integer_t* /*unused*/) noexcept
2785  {
2786  return is_number_integer() ? &m_value.number_integer : nullptr;
2787  }
2788 
2790  constexpr const number_integer_t* get_impl_ptr(const number_integer_t* /*unused*/) const noexcept
2791  {
2792  return is_number_integer() ? &m_value.number_integer : nullptr;
2793  }
2794 
2796  number_unsigned_t* get_impl_ptr(number_unsigned_t* /*unused*/) noexcept
2797  {
2798  return is_number_unsigned() ? &m_value.number_unsigned : nullptr;
2799  }
2800 
2802  constexpr const number_unsigned_t* get_impl_ptr(const number_unsigned_t* /*unused*/) const noexcept
2803  {
2804  return is_number_unsigned() ? &m_value.number_unsigned : nullptr;
2805  }
2806 
2808  number_float_t* get_impl_ptr(number_float_t* /*unused*/) noexcept
2809  {
2810  return is_number_float() ? &m_value.number_float : nullptr;
2811  }
2812 
2814  constexpr const number_float_t* get_impl_ptr(const number_float_t* /*unused*/) const noexcept
2815  {
2816  return is_number_float() ? &m_value.number_float : nullptr;
2817  }
2818 
2830  template<typename ReferenceType, typename ThisType>
2831  static ReferenceType get_ref_impl(ThisType& obj)
2832  {
2833  // helper type
2834  using PointerType = typename std::add_pointer<ReferenceType>::type;
2835 
2836  // delegate the call to get_ptr<>()
2837  auto ptr = obj.template get_ptr<PointerType>();
2838 
2839  if (ptr != nullptr)
2840  {
2841  return *ptr;
2842  }
2843 
2844  throw std::domain_error("incompatible ReferenceType for get_ref, actual type is " +
2845  obj.type_name());
2846  }
2847 
2848  public:
2849 
2853 
2887  template<typename ValueType, typename std::enable_if<
2888  not std::is_pointer<ValueType>::value, int>::type = 0>
2889  ValueType get() const
2890  {
2891  return get_impl(static_cast<ValueType*>(nullptr));
2892  }
2893 
2921  template<typename PointerType, typename std::enable_if<
2922  std::is_pointer<PointerType>::value, int>::type = 0>
2923  PointerType get() noexcept
2924  {
2925  // delegate the call to get_ptr
2926  return get_ptr<PointerType>();
2927  }
2928 
2933  template<typename PointerType, typename std::enable_if<
2934  std::is_pointer<PointerType>::value, int>::type = 0>
2935  constexpr const PointerType get() const noexcept
2936  {
2937  // delegate the call to get_ptr
2938  return get_ptr<PointerType>();
2939  }
2940 
2967  template<typename PointerType, typename std::enable_if<
2968  std::is_pointer<PointerType>::value, int>::type = 0>
2969  PointerType get_ptr() noexcept
2970  {
2971  // get the type of the PointerType (remove pointer and const)
2972  using pointee_t = typename std::remove_const<typename
2973  std::remove_pointer<typename
2974  std::remove_const<PointerType>::type>::type>::type;
2975  // make sure the type matches the allowed types
2976  static_assert(
2977  std::is_same<object_t, pointee_t>::value
2978  or std::is_same<array_t, pointee_t>::value
2979  or std::is_same<string_t, pointee_t>::value
2980  or std::is_same<boolean_t, pointee_t>::value
2981  or std::is_same<number_integer_t, pointee_t>::value
2982  or std::is_same<number_unsigned_t, pointee_t>::value
2983  or std::is_same<number_float_t, pointee_t>::value
2984  , "incompatible pointer type");
2985 
2986  // delegate the call to get_impl_ptr<>()
2987  return get_impl_ptr(static_cast<PointerType>(nullptr));
2988  }
2989 
2994  template<typename PointerType, typename std::enable_if<
2995  std::is_pointer<PointerType>::value and
2996  std::is_const<typename std::remove_pointer<PointerType>::type>::value, int>::type = 0>
2997  constexpr const PointerType get_ptr() const noexcept
2998  {
2999  // get the type of the PointerType (remove pointer and const)
3000  using pointee_t = typename std::remove_const<typename
3001  std::remove_pointer<typename
3002  std::remove_const<PointerType>::type>::type>::type;
3003  // make sure the type matches the allowed types
3004  static_assert(
3005  std::is_same<object_t, pointee_t>::value
3006  or std::is_same<array_t, pointee_t>::value
3007  or std::is_same<string_t, pointee_t>::value
3008  or std::is_same<boolean_t, pointee_t>::value
3009  or std::is_same<number_integer_t, pointee_t>::value
3010  or std::is_same<number_unsigned_t, pointee_t>::value
3011  or std::is_same<number_float_t, pointee_t>::value
3012  , "incompatible pointer type");
3013 
3014  // delegate the call to get_impl_ptr<>() const
3015  return get_impl_ptr(static_cast<const PointerType>(nullptr));
3016  }
3017 
3044  template<typename ReferenceType, typename std::enable_if<
3045  std::is_reference<ReferenceType>::value, int>::type = 0>
3046  ReferenceType get_ref()
3047  {
3048  // delegate call to get_ref_impl
3049  return get_ref_impl<ReferenceType>(*this);
3050  }
3051 
3056  template<typename ReferenceType, typename std::enable_if<
3057  std::is_reference<ReferenceType>::value and
3058  std::is_const<typename std::remove_reference<ReferenceType>::type>::value, int>::type = 0>
3059  ReferenceType get_ref() const
3060  {
3061  // delegate call to get_ref_impl
3062  return get_ref_impl<ReferenceType>(*this);
3063  }
3064 
3093  template < typename ValueType, typename std::enable_if <
3094  not std::is_pointer<ValueType>::value and
3095  not std::is_same<ValueType, typename string_t::value_type>::value
3096 #ifndef _MSC_VER // fix for issue #167 operator<< abiguity under VS2015
3097  and not std::is_same<ValueType, std::initializer_list<typename string_t::value_type>>::value
3098 #endif
3099  , int >::type = 0 >
3100  operator ValueType() const
3101  {
3102  // delegate the call to get<>() const
3103  return get<ValueType>();
3104  }
3105 
3107 
3108 
3110  // element access //
3112 
3116 
3140  {
3141  // at only works for arrays
3142  if (is_array())
3143  {
3144  try
3145  {
3146  return m_value.array->at(idx);
3147  }
3148  catch (std::out_of_range&)
3149  {
3150  // create better exception explanation
3151  throw std::out_of_range("array index " + std::to_string(idx) + " is out of range");
3152  }
3153  }
3154  else
3155  {
3156  throw std::domain_error("cannot use at() with " + type_name());
3157  }
3158  }
3159 
3183  {
3184  // at only works for arrays
3185  if (is_array())
3186  {
3187  try
3188  {
3189  return m_value.array->at(idx);
3190  }
3191  catch (std::out_of_range&)
3192  {
3193  // create better exception explanation
3194  throw std::out_of_range("array index " + std::to_string(idx) + " is out of range");
3195  }
3196  }
3197  else
3198  {
3199  throw std::domain_error("cannot use at() with " + type_name());
3200  }
3201  }
3202 
3229  reference at(const typename object_t::key_type& key)
3230  {
3231  // at only works for objects
3232  if (is_object())
3233  {
3234  try
3235  {
3236  return m_value.object->at(key);
3237  }
3238  catch (std::out_of_range&)
3239  {
3240  // create better exception explanation
3241  throw std::out_of_range("key '" + key + "' not found");
3242  }
3243  }
3244  else
3245  {
3246  throw std::domain_error("cannot use at() with " + type_name());
3247  }
3248  }
3249 
3276  const_reference at(const typename object_t::key_type& key) const
3277  {
3278  // at only works for objects
3279  if (is_object())
3280  {
3281  try
3282  {
3283  return m_value.object->at(key);
3284  }
3285  catch (std::out_of_range&)
3286  {
3287  // create better exception explanation
3288  throw std::out_of_range("key '" + key + "' not found");
3289  }
3290  }
3291  else
3292  {
3293  throw std::domain_error("cannot use at() with " + type_name());
3294  }
3295  }
3296 
3323  {
3324  // implicitly convert null value to an empty array
3325  if (is_null())
3326  {
3327  m_type = value_t::array;
3328  m_value.array = create<array_t>();
3329  assert_invariant();
3330  }
3331 
3332  // operator[] only works for arrays
3333  if (is_array())
3334  {
3335  // fill up array with null values if given idx is outside range
3336  if (idx >= m_value.array->size())
3337  {
3338  m_value.array->insert(m_value.array->end(),
3339  idx - m_value.array->size() + 1,
3340  basic_json());
3341  }
3342 
3343  return m_value.array->operator[](idx);
3344  }
3345 
3346  throw std::domain_error("cannot use operator[] with " + type_name());
3347  }
3348 
3369  {
3370  // const operator[] only works for arrays
3371  if (is_array())
3372  {
3373  return m_value.array->operator[](idx);
3374  }
3375 
3376  throw std::domain_error("cannot use operator[] with " + type_name());
3377  }
3378 
3406  reference operator[](const typename object_t::key_type& key)
3407  {
3408  // implicitly convert null value to an empty object
3409  if (is_null())
3410  {
3411  m_type = value_t::object;
3412  m_value.object = create<object_t>();
3413  assert_invariant();
3414  }
3415 
3416  // operator[] only works for objects
3417  if (is_object())
3418  {
3419  return m_value.object->operator[](key);
3420  }
3421 
3422  throw std::domain_error("cannot use operator[] with " + type_name());
3423  }
3424 
3455  const_reference operator[](const typename object_t::key_type& key) const
3456  {
3457  // const operator[] only works for objects
3458  if (is_object())
3459  {
3460  assert(m_value.object->find(key) != m_value.object->end());
3461  return m_value.object->find(key)->second;
3462  }
3463 
3464  throw std::domain_error("cannot use operator[] with " + type_name());
3465  }
3466 
3494  template<typename T, std::size_t n>
3495  reference operator[](T * (&key)[n])
3496  {
3497  return operator[](static_cast<const T>(key));
3498  }
3499 
3529  template<typename T, std::size_t n>
3530  const_reference operator[](T * (&key)[n]) const
3531  {
3532  return operator[](static_cast<const T>(key));
3533  }
3534 
3562  template<typename T>
3564  {
3565  // implicitly convert null to object
3566  if (is_null())
3567  {
3568  m_type = value_t::object;
3569  m_value = value_t::object;
3570  assert_invariant();
3571  }
3572 
3573  // at only works for objects
3574  if (is_object())
3575  {
3576  return m_value.object->operator[](key);
3577  }
3578 
3579  throw std::domain_error("cannot use operator[] with " + type_name());
3580  }
3581 
3612  template<typename T>
3614  {
3615  // at only works for objects
3616  if (is_object())
3617  {
3618  assert(m_value.object->find(key) != m_value.object->end());
3619  return m_value.object->find(key)->second;
3620  }
3621 
3622  throw std::domain_error("cannot use operator[] with " + type_name());
3623  }
3624 
3673  template<class ValueType, typename std::enable_if<
3674  std::is_convertible<basic_json_t, ValueType>::value, int>::type = 0>
3675  ValueType value(const typename object_t::key_type& key, ValueType default_value) const
3676  {
3677  // at only works for objects
3678  if (is_object())
3679  {
3680  // if key is found, return value and given default value otherwise
3681  const auto it = find(key);
3682  if (it != end())
3683  {
3684  return *it;
3685  }
3686 
3687  return default_value;
3688  }
3689  else
3690  {
3691  throw std::domain_error("cannot use value() with " + type_name());
3692  }
3693  }
3694 
3699  string_t value(const typename object_t::key_type& key, const char* default_value) const
3700  {
3701  return value(key, string_t(default_value));
3702  }
3703 
3745  template<class ValueType, typename std::enable_if<
3746  std::is_convertible<basic_json_t, ValueType>::value, int>::type = 0>
3747  ValueType value(const json_pointer& ptr, ValueType default_value) const
3748  {
3749  // at only works for objects
3750  if (is_object())
3751  {
3752  // if pointer resolves a value, return it or use default value
3753  try
3754  {
3755  return ptr.get_checked(this);
3756  }
3757  catch (std::out_of_range&)
3758  {
3759  return default_value;
3760  }
3761  }
3762 
3763  throw std::domain_error("cannot use value() with " + type_name());
3764  }
3765 
3770  string_t value(const json_pointer& ptr, const char* default_value) const
3771  {
3772  return value(ptr, string_t(default_value));
3773  }
3774 
3801  {
3802  return *begin();
3803  }
3804 
3809  {
3810  return *cbegin();
3811  }
3812 
3844  {
3845  auto tmp = end();
3846  --tmp;
3847  return *tmp;
3848  }
3849 
3854  {
3855  auto tmp = cend();
3856  --tmp;
3857  return *tmp;
3858  }
3859 
3905  template<class IteratorType, typename std::enable_if<
3906  std::is_same<IteratorType, typename basic_json_t::iterator>::value or
3907  std::is_same<IteratorType, typename basic_json_t::const_iterator>::value, int>::type
3908  = 0>
3909  IteratorType erase(IteratorType pos)
3910  {
3911  // make sure iterator fits the current value
3912  if (this != pos.m_object)
3913  {
3914  throw std::domain_error("iterator does not fit current value");
3915  }
3916 
3917  IteratorType result = end();
3918 
3919  switch (m_type)
3920  {
3921  case value_t::boolean:
3922  case value_t::number_float:
3923  case value_t::number_integer:
3924  case value_t::number_unsigned:
3925  case value_t::string:
3926  {
3927  if (not pos.m_it.primitive_iterator.is_begin())
3928  {
3929  throw std::out_of_range("iterator out of range");
3930  }
3931 
3932  if (is_string())
3933  {
3934  AllocatorType<string_t> alloc;
3935  alloc.destroy(m_value.string);
3936  alloc.deallocate(m_value.string, 1);
3937  m_value.string = nullptr;
3938  }
3939 
3940  m_type = value_t::null;
3941  assert_invariant();
3942  break;
3943  }
3944 
3945  case value_t::object:
3946  {
3947  result.m_it.object_iterator = m_value.object->erase(pos.m_it.object_iterator);
3948  break;
3949  }
3950 
3951  case value_t::array:
3952  {
3953  result.m_it.array_iterator = m_value.array->erase(pos.m_it.array_iterator);
3954  break;
3955  }
3956 
3957  default:
3958  {
3959  throw std::domain_error("cannot use erase() with " + type_name());
3960  }
3961  }
3962 
3963  return result;
3964  }
3965 
4012  template<class IteratorType, typename std::enable_if<
4013  std::is_same<IteratorType, typename basic_json_t::iterator>::value or
4014  std::is_same<IteratorType, typename basic_json_t::const_iterator>::value, int>::type
4015  = 0>
4016  IteratorType erase(IteratorType first, IteratorType last)
4017  {
4018  // make sure iterator fits the current value
4019  if (this != first.m_object or this != last.m_object)
4020  {
4021  throw std::domain_error("iterators do not fit current value");
4022  }
4023 
4024  IteratorType result = end();
4025 
4026  switch (m_type)
4027  {
4028  case value_t::boolean:
4029  case value_t::number_float:
4030  case value_t::number_integer:
4031  case value_t::number_unsigned:
4032  case value_t::string:
4033  {
4034  if (not first.m_it.primitive_iterator.is_begin() or not last.m_it.primitive_iterator.is_end())
4035  {
4036  throw std::out_of_range("iterators out of range");
4037  }
4038 
4039  if (is_string())
4040  {
4041  AllocatorType<string_t> alloc;
4042  alloc.destroy(m_value.string);
4043  alloc.deallocate(m_value.string, 1);
4044  m_value.string = nullptr;
4045  }
4046 
4047  m_type = value_t::null;
4048  assert_invariant();
4049  break;
4050  }
4051 
4052  case value_t::object:
4053  {
4054  result.m_it.object_iterator = m_value.object->erase(first.m_it.object_iterator,
4055  last.m_it.object_iterator);
4056  break;
4057  }
4058 
4059  case value_t::array:
4060  {
4061  result.m_it.array_iterator = m_value.array->erase(first.m_it.array_iterator,
4062  last.m_it.array_iterator);
4063  break;
4064  }
4065 
4066  default:
4067  {
4068  throw std::domain_error("cannot use erase() with " + type_name());
4069  }
4070  }
4071 
4072  return result;
4073  }
4074 
4104  size_type erase(const typename object_t::key_type& key)
4105  {
4106  // this erase only works for objects
4107  if (is_object())
4108  {
4109  return m_value.object->erase(key);
4110  }
4111 
4112  throw std::domain_error("cannot use erase() with " + type_name());
4113  }
4114 
4139  void erase(const size_type idx)
4140  {
4141  // this erase only works for arrays
4142  if (is_array())
4143  {
4144  if (idx >= size())
4145  {
4146  throw std::out_of_range("array index " + std::to_string(idx) + " is out of range");
4147  }
4148 
4149  m_value.array->erase(m_value.array->begin() + static_cast<difference_type>(idx));
4150  }
4151  else
4152  {
4153  throw std::domain_error("cannot use erase() with " + type_name());
4154  }
4155  }
4156 
4158 
4159 
4161  // lookup //
4163 
4166 
4189  iterator find(typename object_t::key_type key)
4190  {
4191  auto result = end();
4192 
4193  if (is_object())
4194  {
4195  result.m_it.object_iterator = m_value.object->find(key);
4196  }
4197 
4198  return result;
4199  }
4200 
4205  const_iterator find(typename object_t::key_type key) const
4206  {
4207  auto result = cend();
4208 
4209  if (is_object())
4210  {
4211  result.m_it.object_iterator = m_value.object->find(key);
4212  }
4213 
4214  return result;
4215  }
4216 
4238  size_type count(typename object_t::key_type key) const
4239  {
4240  // return 0 for all nonobject types
4241  return is_object() ? m_value.object->count(key) : 0;
4242  }
4243 
4245 
4246 
4248  // iterators //
4250 
4253 
4278  iterator begin() noexcept
4279  {
4280  iterator result(this);
4281  result.set_begin();
4282  return result;
4283  }
4284 
4288  const_iterator begin() const noexcept
4289  {
4290  return cbegin();
4291  }
4292 
4318  const_iterator cbegin() const noexcept
4319  {
4320  const_iterator result(this);
4321  result.set_begin();
4322  return result;
4323  }
4324 
4349  iterator end() noexcept
4350  {
4351  iterator result(this);
4352  result.set_end();
4353  return result;
4354  }
4355 
4359  const_iterator end() const noexcept
4360  {
4361  return cend();
4362  }
4363 
4389  const_iterator cend() const noexcept
4390  {
4391  const_iterator result(this);
4392  result.set_end();
4393  return result;
4394  }
4395 
4420  {
4421  return reverse_iterator(end());
4422  }
4423 
4428  {
4429  return crbegin();
4430  }
4431 
4457  {
4458  return reverse_iterator(begin());
4459  }
4460 
4464  const_reverse_iterator rend() const noexcept
4465  {
4466  return crend();
4467  }
4468 
4494  {
4495  return const_reverse_iterator(cend());
4496  }
4497 
4523  {
4524  return const_reverse_iterator(cbegin());
4525  }
4526 
4527  private:
4528  // forward declaration
4529  template<typename IteratorType> class iteration_proxy;
4530 
4531  public:
4543  static iteration_proxy<iterator> iterator_wrapper(reference cont)
4544  {
4545  return iteration_proxy<iterator>(cont);
4546  }
4547 
4551  static iteration_proxy<const_iterator> iterator_wrapper(const_reference cont)
4552  {
4553  return iteration_proxy<const_iterator>(cont);
4554  }
4555 
4557 
4558 
4560  // capacity //
4562 
4565 
4603  bool empty() const noexcept
4604  {
4605  switch (m_type)
4606  {
4607  case value_t::null:
4608  {
4609  // null values are empty
4610  return true;
4611  }
4612 
4613  case value_t::array:
4614  {
4615  // delegate call to array_t::empty()
4616  return m_value.array->empty();
4617  }
4618 
4619  case value_t::object:
4620  {
4621  // delegate call to object_t::empty()
4622  return m_value.object->empty();
4623  }
4624 
4625  default:
4626  {
4627  // all other types are nonempty
4628  return false;
4629  }
4630  }
4631  }
4632 
4671  size_type size() const noexcept
4672  {
4673  switch (m_type)
4674  {
4675  case value_t::null:
4676  {
4677  // null values are empty
4678  return 0;
4679  }
4680 
4681  case value_t::array:
4682  {
4683  // delegate call to array_t::size()
4684  return m_value.array->size();
4685  }
4686 
4687  case value_t::object:
4688  {
4689  // delegate call to object_t::size()
4690  return m_value.object->size();
4691  }
4692 
4693  default:
4694  {
4695  // all other types have size 1
4696  return 1;
4697  }
4698  }
4699  }
4700 
4737  size_type max_size() const noexcept
4738  {
4739  switch (m_type)
4740  {
4741  case value_t::array:
4742  {
4743  // delegate call to array_t::max_size()
4744  return m_value.array->max_size();
4745  }
4746 
4747  case value_t::object:
4748  {
4749  // delegate call to object_t::max_size()
4750  return m_value.object->max_size();
4751  }
4752 
4753  default:
4754  {
4755  // all other types have max_size() == size()
4756  return size();
4757  }
4758  }
4759  }
4760 
4762 
4763 
4765  // modifiers //
4767 
4770 
4793  void clear() noexcept
4794  {
4795  switch (m_type)
4796  {
4797  case value_t::number_integer:
4798  {
4799  m_value.number_integer = 0;
4800  break;
4801  }
4802 
4803  case value_t::number_unsigned:
4804  {
4805  m_value.number_unsigned = 0;
4806  break;
4807  }
4808 
4809  case value_t::number_float:
4810  {
4811  m_value.number_float = 0.0;
4812  break;
4813  }
4814 
4815  case value_t::boolean:
4816  {
4817  m_value.boolean = false;
4818  break;
4819  }
4820 
4821  case value_t::string:
4822  {
4823  m_value.string->clear();
4824  break;
4825  }
4826 
4827  case value_t::array:
4828  {
4829  m_value.array->clear();
4830  break;
4831  }
4832 
4833  case value_t::object:
4834  {
4835  m_value.object->clear();
4836  break;
4837  }
4838 
4839  default:
4840  {
4841  break;
4842  }
4843  }
4844  }
4845 
4866  void push_back(basic_json&& val)
4867  {
4868  // push_back only works for null objects or arrays
4869  if (not(is_null() or is_array()))
4870  {
4871  throw std::domain_error("cannot use push_back() with " + type_name());
4872  }
4873 
4874  // transform null object into an array
4875  if (is_null())
4876  {
4877  m_type = value_t::array;
4878  m_value = value_t::array;
4879  assert_invariant();
4880  }
4881 
4882  // add element to array (move semantics)
4883  m_value.array->push_back(std::move(val));
4884  // invalidate object
4885  val.m_type = value_t::null;
4886  }
4887 
4893  {
4894  push_back(std::move(val));
4895  return *this;
4896  }
4897 
4902  void push_back(const basic_json& val)
4903  {
4904  // push_back only works for null objects or arrays
4905  if (not(is_null() or is_array()))
4906  {
4907  throw std::domain_error("cannot use push_back() with " + type_name());
4908  }
4909 
4910  // transform null object into an array
4911  if (is_null())
4912  {
4913  m_type = value_t::array;
4914  m_value = value_t::array;
4915  assert_invariant();
4916  }
4917 
4918  // add element to array
4919  m_value.array->push_back(val);
4920  }
4921 
4927  {
4928  push_back(val);
4929  return *this;
4930  }
4931 
4952  void push_back(const typename object_t::value_type& val)
4953  {
4954  // push_back only works for null objects or objects
4955  if (not(is_null() or is_object()))
4956  {
4957  throw std::domain_error("cannot use push_back() with " + type_name());
4958  }
4959 
4960  // transform null object into an object
4961  if (is_null())
4962  {
4963  m_type = value_t::object;
4964  m_value = value_t::object;
4965  assert_invariant();
4966  }
4967 
4968  // add element to array
4969  m_value.object->insert(val);
4970  }
4971 
4976  reference operator+=(const typename object_t::value_type& val)
4977  {
4978  push_back(val);
4979  return *this;
4980  }
4981 
5007  void push_back(std::initializer_list<basic_json> init)
5008  {
5009  if (is_object() and init.size() == 2 and init.begin()->is_string())
5010  {
5011  const string_t key = *init.begin();
5012  push_back(typename object_t::value_type(key, *(init.begin() + 1)));
5013  }
5014  else
5015  {
5016  push_back(basic_json(init));
5017  }
5018  }
5019 
5024  reference operator+=(std::initializer_list<basic_json> init)
5025  {
5026  push_back(init);
5027  return *this;
5028  }
5029 
5051  template<class... Args>
5052  void emplace_back(Args&& ... args)
5053  {
5054  // emplace_back only works for null objects or arrays
5055  if (not(is_null() or is_array()))
5056  {
5057  throw std::domain_error("cannot use emplace_back() with " + type_name());
5058  }
5059 
5060  // transform null object into an array
5061  if (is_null())
5062  {
5063  m_type = value_t::array;
5064  m_value = value_t::array;
5065  assert_invariant();
5066  }
5067 
5068  // add element to array (perfect forwarding)
5069  m_value.array->emplace_back(std::forward<Args>(args)...);
5070  }
5071 
5099  template<class... Args>
5100  std::pair<iterator, bool> emplace(Args&& ... args)
5101  {
5102  // emplace only works for null objects or arrays
5103  if (not(is_null() or is_object()))
5104  {
5105  throw std::domain_error("cannot use emplace() with " + type_name());
5106  }
5107 
5108  // transform null object into an object
5109  if (is_null())
5110  {
5111  m_type = value_t::object;
5112  m_value = value_t::object;
5113  assert_invariant();
5114  }
5115 
5116  // add element to array (perfect forwarding)
5117  auto res = m_value.object->emplace(std::forward<Args>(args)...);
5118  // create result iterator and set iterator to the result of emplace
5119  auto it = begin();
5120  it.m_it.object_iterator = res.first;
5121 
5122  // return pair of iterator and boolean
5123  return {it, res.second};
5124  }
5125 
5149  {
5150  // insert only works for arrays
5151  if (is_array())
5152  {
5153  // check if iterator pos fits to this JSON value
5154  if (pos.m_object != this)
5155  {
5156  throw std::domain_error("iterator does not fit current value");
5157  }
5158 
5159  // insert to array and return iterator
5160  iterator result(this);
5161  result.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator, val);
5162  return result;
5163  }
5164 
5165  throw std::domain_error("cannot use insert() with " + type_name());
5166  }
5167 
5173  {
5174  return insert(pos, val);
5175  }
5176 
5202  {
5203  // insert only works for arrays
5204  if (is_array())
5205  {
5206  // check if iterator pos fits to this JSON value
5207  if (pos.m_object != this)
5208  {
5209  throw std::domain_error("iterator does not fit current value");
5210  }
5211 
5212  // insert to array and return iterator
5213  iterator result(this);
5214  result.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator, cnt, val);
5215  return result;
5216  }
5217 
5218  throw std::domain_error("cannot use insert() with " + type_name());
5219  }
5220 
5252  {
5253  // insert only works for arrays
5254  if (not is_array())
5255  {
5256  throw std::domain_error("cannot use insert() with " + type_name());
5257  }
5258 
5259  // check if iterator pos fits to this JSON value
5260  if (pos.m_object != this)
5261  {
5262  throw std::domain_error("iterator does not fit current value");
5263  }
5264 
5265  // check if range iterators belong to the same JSON object
5266  if (first.m_object != last.m_object)
5267  {
5268  throw std::domain_error("iterators do not fit");
5269  }
5270 
5271  if (first.m_object == this or last.m_object == this)
5272  {
5273  throw std::domain_error("passed iterators may not belong to container");
5274  }
5275 
5276  // insert to array and return iterator
5277  iterator result(this);
5278  result.m_it.array_iterator = m_value.array->insert(
5279  pos.m_it.array_iterator,
5280  first.m_it.array_iterator,
5281  last.m_it.array_iterator);
5282  return result;
5283  }
5284 
5309  iterator insert(const_iterator pos, std::initializer_list<basic_json> ilist)
5310  {
5311  // insert only works for arrays
5312  if (not is_array())
5313  {
5314  throw std::domain_error("cannot use insert() with " + type_name());
5315  }
5316 
5317  // check if iterator pos fits to this JSON value
5318  if (pos.m_object != this)
5319  {
5320  throw std::domain_error("iterator does not fit current value");
5321  }
5322 
5323  // insert to array and return iterator
5324  iterator result(this);
5325  result.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator, ilist);
5326  return result;
5327  }
5328 
5346  void swap(reference other) noexcept (
5347  std::is_nothrow_move_constructible<value_t>::value and
5348  std::is_nothrow_move_assignable<value_t>::value and
5349  std::is_nothrow_move_constructible<json_value>::value and
5350  std::is_nothrow_move_assignable<json_value>::value
5351  )
5352  {
5353  std::swap(m_type, other.m_type);
5354  std::swap(m_value, other.m_value);
5355  assert_invariant();
5356  }
5357 
5378  void swap(array_t& other)
5379  {
5380  // swap only works for arrays
5381  if (is_array())
5382  {
5383  std::swap(*(m_value.array), other);
5384  }
5385  else
5386  {
5387  throw std::domain_error("cannot use swap() with " + type_name());
5388  }
5389  }
5390 
5411  void swap(object_t& other)
5412  {
5413  // swap only works for objects
5414  if (is_object())
5415  {
5416  std::swap(*(m_value.object), other);
5417  }
5418  else
5419  {
5420  throw std::domain_error("cannot use swap() with " + type_name());
5421  }
5422  }
5423 
5444  void swap(string_t& other)
5445  {
5446  // swap only works for strings
5447  if (is_string())
5448  {
5449  std::swap(*(m_value.string), other);
5450  }
5451  else
5452  {
5453  throw std::domain_error("cannot use swap() with " + type_name());
5454  }
5455  }
5456 
5458 
5459 
5461  // lexicographical comparison operators //
5463 
5466 
5467  private:
5477  friend bool operator<(const value_t lhs, const value_t rhs) noexcept
5478  {
5479  static constexpr std::array<uint8_t, 8> order = {{
5480  0, // null
5481  3, // object
5482  4, // array
5483  5, // string
5484  1, // boolean
5485  2, // integer
5486  2, // unsigned
5487  2, // float
5488  }
5489  };
5490 
5491  // discarded values are not comparable
5492  if (lhs == value_t::discarded or rhs == value_t::discarded)
5493  {
5494  return false;
5495  }
5496 
5497  return order[static_cast<std::size_t>(lhs)] < order[static_cast<std::size_t>(rhs)];
5498  }
5499 
5500  public:
5524  friend bool operator==(const_reference lhs, const_reference rhs) noexcept
5525  {
5526  const auto lhs_type = lhs.type();
5527  const auto rhs_type = rhs.type();
5528 
5529  if (lhs_type == rhs_type)
5530  {
5531  switch (lhs_type)
5532  {
5533  case value_t::array:
5534  {
5535  return *lhs.m_value.array == *rhs.m_value.array;
5536  }
5537  case value_t::object:
5538  {
5539  return *lhs.m_value.object == *rhs.m_value.object;
5540  }
5541  case value_t::null:
5542  {
5543  return true;
5544  }
5545  case value_t::string:
5546  {
5547  return *lhs.m_value.string == *rhs.m_value.string;
5548  }
5549  case value_t::boolean:
5550  {
5551  return lhs.m_value.boolean == rhs.m_value.boolean;
5552  }
5553  case value_t::number_integer:
5554  {
5555  return lhs.m_value.number_integer == rhs.m_value.number_integer;
5556  }
5557  case value_t::number_unsigned:
5558  {
5559  return lhs.m_value.number_unsigned == rhs.m_value.number_unsigned;
5560  }
5561  case value_t::number_float:
5562  {
5563  return lhs.m_value.number_float == rhs.m_value.number_float;
5564  }
5565  default:
5566  {
5567  return false;
5568  }
5569  }
5570  }
5571  else if (lhs_type == value_t::number_integer and rhs_type == value_t::number_float)
5572  {
5573  return static_cast<number_float_t>(lhs.m_value.number_integer) == rhs.m_value.number_float;
5574  }
5575  else if (lhs_type == value_t::number_float and rhs_type == value_t::number_integer)
5576  {
5577  return lhs.m_value.number_float == static_cast<number_float_t>(rhs.m_value.number_integer);
5578  }
5579  else if (lhs_type == value_t::number_unsigned and rhs_type == value_t::number_float)
5580  {
5581  return static_cast<number_float_t>(lhs.m_value.number_unsigned) == rhs.m_value.number_float;
5582  }
5583  else if (lhs_type == value_t::number_float and rhs_type == value_t::number_unsigned)
5584  {
5585  return lhs.m_value.number_float == static_cast<number_float_t>(rhs.m_value.number_unsigned);
5586  }
5587  else if (lhs_type == value_t::number_unsigned and rhs_type == value_t::number_integer)
5588  {
5589  return static_cast<number_integer_t>(lhs.m_value.number_unsigned) == rhs.m_value.number_integer;
5590  }
5591  else if (lhs_type == value_t::number_integer and rhs_type == value_t::number_unsigned)
5592  {
5593  return lhs.m_value.number_integer == static_cast<number_integer_t>(rhs.m_value.number_unsigned);
5594  }
5595 
5596  return false;
5597  }
5598 
5617  friend bool operator==(const_reference v, std::nullptr_t) noexcept
5618  {
5619  return v.is_null();
5620  }
5621 
5626  friend bool operator==(std::nullptr_t, const_reference v) noexcept
5627  {
5628  return v.is_null();
5629  }
5630 
5647  friend bool operator!=(const_reference lhs, const_reference rhs) noexcept
5648  {
5649  return not (lhs == rhs);
5650  }
5651 
5670  friend bool operator!=(const_reference v, std::nullptr_t) noexcept
5671  {
5672  return not v.is_null();
5673  }
5674 
5679  friend bool operator!=(std::nullptr_t, const_reference v) noexcept
5680  {
5681  return not v.is_null();
5682  }
5683 
5708  friend bool operator<(const_reference lhs, const_reference rhs) noexcept
5709  {
5710  const auto lhs_type = lhs.type();
5711  const auto rhs_type = rhs.type();
5712 
5713  if (lhs_type == rhs_type)
5714  {
5715  switch (lhs_type)
5716  {
5717  case value_t::array:
5718  {
5719  return *lhs.m_value.array < *rhs.m_value.array;
5720  }
5721  case value_t::object:
5722  {
5723  return *lhs.m_value.object < *rhs.m_value.object;
5724  }
5725  case value_t::null:
5726  {
5727  return false;
5728  }
5729  case value_t::string:
5730  {
5731  return *lhs.m_value.string < *rhs.m_value.string;
5732  }
5733  case value_t::boolean:
5734  {
5735  return lhs.m_value.boolean < rhs.m_value.boolean;
5736  }
5737  case value_t::number_integer:
5738  {
5739  return lhs.m_value.number_integer < rhs.m_value.number_integer;
5740  }
5741  case value_t::number_unsigned:
5742  {
5743  return lhs.m_value.number_unsigned < rhs.m_value.number_unsigned;
5744  }
5745  case value_t::number_float:
5746  {
5747  return lhs.m_value.number_float < rhs.m_value.number_float;
5748  }
5749  default:
5750  {
5751  return false;
5752  }
5753  }
5754  }
5755  else if (lhs_type == value_t::number_integer and rhs_type == value_t::number_float)
5756  {
5757  return static_cast<number_float_t>(lhs.m_value.number_integer) < rhs.m_value.number_float;
5758  }
5759  else if (lhs_type == value_t::number_float and rhs_type == value_t::number_integer)
5760  {
5761  return lhs.m_value.number_float < static_cast<number_float_t>(rhs.m_value.number_integer);
5762  }
5763  else if (lhs_type == value_t::number_unsigned and rhs_type == value_t::number_float)
5764  {
5765  return static_cast<number_float_t>(lhs.m_value.number_unsigned) < rhs.m_value.number_float;
5766  }
5767  else if (lhs_type == value_t::number_float and rhs_type == value_t::number_unsigned)
5768  {
5769  return lhs.m_value.number_float < static_cast<number_float_t>(rhs.m_value.number_unsigned);
5770  }
5771  else if (lhs_type == value_t::number_integer and rhs_type == value_t::number_unsigned)
5772  {
5773  return lhs.m_value.number_integer < static_cast<number_integer_t>(rhs.m_value.number_unsigned);
5774  }
5775  else if (lhs_type == value_t::number_unsigned and rhs_type == value_t::number_integer)
5776  {
5777  return static_cast<number_integer_t>(lhs.m_value.number_unsigned) < rhs.m_value.number_integer;
5778  }
5779 
5780  // We only reach this line if we cannot compare values. In that case,
5781  // we compare types. Note we have to call the operator explicitly,
5782  // because MSVC has problems otherwise.
5783  return operator<(lhs_type, rhs_type);
5784  }
5785 
5803  friend bool operator<=(const_reference lhs, const_reference rhs) noexcept
5804  {
5805  return not (rhs < lhs);
5806  }
5807 
5825  friend bool operator>(const_reference lhs, const_reference rhs) noexcept
5826  {
5827  return not (lhs <= rhs);
5828  }
5829 
5847  friend bool operator>=(const_reference lhs, const_reference rhs) noexcept
5848  {
5849  return not (lhs < rhs);
5850  }
5851 
5853 
5854 
5856  // serialization //
5858 
5861 
5888  friend std::ostream& operator<<(std::ostream& o, const basic_json& j)
5889  {
5890  // read width member and use it as indentation parameter if nonzero
5891  const bool pretty_print = (o.width() > 0);
5892  const auto indentation = (pretty_print ? o.width() : 0);
5893 
5894  // reset width to 0 for subsequent calls to this stream
5895  o.width(0);
5896 
5897  // fix locale problems
5898  const auto old_locale = o.imbue(std::locale::classic());
5899  // set precision
5900 
5901  // 6, 15 or 16 digits of precision allows round-trip IEEE 754
5902  // string->float->string, string->double->string or string->long
5903  // double->string; to be safe, we read this value from
5904  // std::numeric_limits<number_float_t>::digits10
5905  const auto old_precision = o.precision(std::numeric_limits<double>::digits10);
5906 
5907  // do the actual serialization
5908  j.dump(o, pretty_print, static_cast<unsigned int>(indentation));
5909 
5910  // reset locale and precision
5911  o.imbue(old_locale);
5912  o.precision(old_precision);
5913  return o;
5914  }
5915 
5920  friend std::ostream& operator>>(const basic_json& j, std::ostream& o)
5921  {
5922  return o << j;
5923  }
5924 
5926 
5927 
5929  // deserialization //
5931 
5934 
5962  template<class T, std::size_t N>
5963  static basic_json parse(T (&array)[N],
5964  const parser_callback_t cb = nullptr)
5965  {
5966  // delegate the call to the iterator-range parse overload
5967  return parse(std::begin(array), std::end(array), cb);
5968  }
5969 
5997  template<typename CharT, typename std::enable_if<
5998  std::is_pointer<CharT>::value and
5999  std::is_integral<typename std::remove_pointer<CharT>::type>::value and
6000  sizeof(typename std::remove_pointer<CharT>::type) == 1, int>::type = 0>
6001  static basic_json parse(const CharT s,
6002  const parser_callback_t cb = nullptr)
6003  {
6004  return parser(reinterpret_cast<const char*>(s), cb).parse();
6005  }
6006 
6031  static basic_json parse(std::istream& i,
6032  const parser_callback_t cb = nullptr)
6033  {
6034  return parser(i, cb).parse();
6035  }
6036 
6040  static basic_json parse(std::istream&& i,
6041  const parser_callback_t cb = nullptr)
6042  {
6043  return parser(i, cb).parse();
6044  }
6045 
6087  template<class IteratorType, typename std::enable_if<
6088  std::is_base_of<
6089  std::random_access_iterator_tag,
6090  typename std::iterator_traits<IteratorType>::iterator_category>::value, int>::type = 0>
6091  static basic_json parse(IteratorType first, IteratorType last,
6092  const parser_callback_t cb = nullptr)
6093  {
6094  // assertion to check that the iterator range is indeed contiguous,
6095  // see http://stackoverflow.com/a/35008842/266378 for more discussion
6096  assert(std::accumulate(first, last, std::pair<bool, int>(true, 0),
6097  [&first](std::pair<bool, int> res, decltype(*first) val)
6098  {
6099  res.first &= (val == *(std::next(std::addressof(*first), res.second++)));
6100  return res;
6101  }).first);
6102 
6103  // assertion to check that each element is 1 byte long
6104  static_assert(sizeof(typename std::iterator_traits<IteratorType>::value_type) == 1,
6105  "each element in the iterator range must have the size of 1 byte");
6106 
6107  // if iterator range is empty, create a parser with an empty string
6108  // to generate "unexpected EOF" error message
6109  if (std::distance(first, last) <= 0)
6110  {
6111  return parser("").parse();
6112  }
6113 
6114  return parser(first, last, cb).parse();
6115  }
6116 
6157  template<class ContiguousContainer, typename std::enable_if<
6158  not std::is_pointer<ContiguousContainer>::value and
6159  std::is_base_of<
6160  std::random_access_iterator_tag,
6161  typename std::iterator_traits<decltype(std::begin(std::declval<ContiguousContainer const>()))>::iterator_category>::value
6162  , int>::type = 0>
6163  static basic_json parse(const ContiguousContainer& c,
6164  const parser_callback_t cb = nullptr)
6165  {
6166  // delegate the call to the iterator-range parse overload
6167  return parse(std::begin(c), std::end(c), cb);
6168  }
6169 
6193  friend std::istream& operator<<(basic_json& j, std::istream& i)
6194  {
6195  j = parser(i).parse();
6196  return i;
6197  }
6198 
6203  friend std::istream& operator>>(std::istream& i, basic_json& j)
6204  {
6205  j = parser(i).parse();
6206  return i;
6207  }
6208 
6210 
6212  // binary serialization/deserialization //
6214 
6217 
6218  private:
6219  template<typename T>
6220  static void add_to_vector(std::vector<uint8_t>& vec, size_t bytes, const T number)
6221  {
6222  assert(bytes == 1 or bytes == 2 or bytes == 4 or bytes == 8);
6223 
6224  switch (bytes)
6225  {
6226  case 8:
6227  {
6228  vec.push_back(static_cast<uint8_t>((number >> 070) & 0xff));
6229  vec.push_back(static_cast<uint8_t>((number >> 060) & 0xff));
6230  vec.push_back(static_cast<uint8_t>((number >> 050) & 0xff));
6231  vec.push_back(static_cast<uint8_t>((number >> 040) & 0xff));
6232  // intentional fall-through
6233  }
6234 
6235  case 4:
6236  {
6237  vec.push_back(static_cast<uint8_t>((number >> 030) & 0xff));
6238  vec.push_back(static_cast<uint8_t>((number >> 020) & 0xff));
6239  // intentional fall-through
6240  }
6241 
6242  case 2:
6243  {
6244  vec.push_back(static_cast<uint8_t>((number >> 010) & 0xff));
6245  // intentional fall-through
6246  }
6247 
6248  case 1:
6249  {
6250  vec.push_back(static_cast<uint8_t>(number & 0xff));
6251  break;
6252  }
6253  }
6254  }
6255 
6292  template<typename T>
6293  static T get_from_vector(const std::vector<uint8_t>& vec, const size_t current_index)
6294  {
6295  if (current_index + sizeof(T) + 1 > vec.size())
6296  {
6297  throw std::out_of_range("cannot read " + std::to_string(sizeof(T)) + " bytes from vector");
6298  }
6299 
6300  T result;
6301  auto* ptr = reinterpret_cast<uint8_t*>(&result);
6302  for (size_t i = 0; i < sizeof(T); ++i)
6303  {
6304  *ptr++ = vec[current_index + sizeof(T) - i];
6305  }
6306  return result;
6307  }
6308 
6319  static void to_msgpack_internal(const basic_json& j, std::vector<uint8_t>& v)
6320  {
6321  switch (j.type())
6322  {
6323  case value_t::null:
6324  {
6325  // nil
6326  v.push_back(0xc0);
6327  break;
6328  }
6329 
6330  case value_t::boolean:
6331  {
6332  // true and false
6333  v.push_back(j.m_value.boolean ? 0xc3 : 0xc2);
6334  break;
6335  }
6336 
6337  case value_t::number_integer:
6338  {
6339  if (j.m_value.number_integer >= 0)
6340  {
6341  // MessagePack does not differentiate between positive
6342  // signed integers and unsigned integers. Therefore, we
6343  // used the code from the value_t::number_unsigned case
6344  // here.
6345  if (j.m_value.number_unsigned < 128)
6346  {
6347  // positive fixnum
6348  add_to_vector(v, 1, j.m_value.number_unsigned);
6349  }
6350  else if (j.m_value.number_unsigned <= UINT8_MAX)
6351  {
6352  // uint 8
6353  v.push_back(0xcc);
6354  add_to_vector(v, 1, j.m_value.number_unsigned);
6355  }
6356  else if (j.m_value.number_unsigned <= UINT16_MAX)
6357  {
6358  // uint 16
6359  v.push_back(0xcd);
6360  add_to_vector(v, 2, j.m_value.number_unsigned);
6361  }
6362  else if (j.m_value.number_unsigned <= UINT32_MAX)
6363  {
6364  // uint 32
6365  v.push_back(0xce);
6366  add_to_vector(v, 4, j.m_value.number_unsigned);
6367  }
6368  else if (j.m_value.number_unsigned <= UINT64_MAX)
6369  {
6370  // uint 64
6371  v.push_back(0xcf);
6372  add_to_vector(v, 8, j.m_value.number_unsigned);
6373  }
6374  }
6375  else
6376  {
6377  if (j.m_value.number_integer >= -32)
6378  {
6379  // negative fixnum
6380  add_to_vector(v, 1, j.m_value.number_integer);
6381  }
6382  else if (j.m_value.number_integer >= INT8_MIN and j.m_value.number_integer <= INT8_MAX)
6383  {
6384  // int 8
6385  v.push_back(0xd0);
6386  add_to_vector(v, 1, j.m_value.number_integer);
6387  }
6388  else if (j.m_value.number_integer >= INT16_MIN and j.m_value.number_integer <= INT16_MAX)
6389  {
6390  // int 16
6391  v.push_back(0xd1);
6392  add_to_vector(v, 2, j.m_value.number_integer);
6393  }
6394  else if (j.m_value.number_integer >= INT32_MIN and j.m_value.number_integer <= INT32_MAX)
6395  {
6396  // int 32
6397  v.push_back(0xd2);
6398  add_to_vector(v, 4, j.m_value.number_integer);
6399  }
6400  else if (j.m_value.number_integer >= INT64_MIN and j.m_value.number_integer <= INT64_MAX)
6401  {
6402  // int 64
6403  v.push_back(0xd3);
6404  add_to_vector(v, 8, j.m_value.number_integer);
6405  }
6406  }
6407  break;
6408  }
6409 
6410  case value_t::number_unsigned:
6411  {
6412  if (j.m_value.number_unsigned < 128)
6413  {
6414  // positive fixnum
6415  add_to_vector(v, 1, j.m_value.number_unsigned);
6416  }
6417  else if (j.m_value.number_unsigned <= UINT8_MAX)
6418  {
6419  // uint 8
6420  v.push_back(0xcc);
6421  add_to_vector(v, 1, j.m_value.number_unsigned);
6422  }
6423  else if (j.m_value.number_unsigned <= UINT16_MAX)
6424  {
6425  // uint 16
6426  v.push_back(0xcd);
6427  add_to_vector(v, 2, j.m_value.number_unsigned);
6428  }
6429  else if (j.m_value.number_unsigned <= UINT32_MAX)
6430  {
6431  // uint 32
6432  v.push_back(0xce);
6433  add_to_vector(v, 4, j.m_value.number_unsigned);
6434  }
6435  else if (j.m_value.number_unsigned <= UINT64_MAX)
6436  {
6437  // uint 64
6438  v.push_back(0xcf);
6439  add_to_vector(v, 8, j.m_value.number_unsigned);
6440  }
6441  break;
6442  }
6443 
6444  case value_t::number_float:
6445  {
6446  // float 64
6447  v.push_back(0xcb);
6448  const auto* helper = reinterpret_cast<const uint8_t*>(&(j.m_value.number_float));
6449  for (size_t i = 0; i < 8; ++i)
6450  {
6451  v.push_back(helper[7 - i]);
6452  }
6453  break;
6454  }
6455 
6456  case value_t::string:
6457  {
6458  const auto N = j.m_value.string->size();
6459  if (N <= 31)
6460  {
6461  // fixstr
6462  v.push_back(static_cast<uint8_t>(0xa0 | N));
6463  }
6464  else if (N <= 255)
6465  {
6466  // str 8
6467  v.push_back(0xd9);
6468  add_to_vector(v, 1, N);
6469  }
6470  else if (N <= 65535)
6471  {
6472  // str 16
6473  v.push_back(0xda);
6474  add_to_vector(v, 2, N);
6475  }
6476  else if (N <= 4294967295)
6477  {
6478  // str 32
6479  v.push_back(0xdb);
6480  add_to_vector(v, 4, N);
6481  }
6482 
6483  // append string
6484  std::copy(j.m_value.string->begin(), j.m_value.string->end(),
6485  std::back_inserter(v));
6486  break;
6487  }
6488 
6489  case value_t::array:
6490  {
6491  const auto N = j.m_value.array->size();
6492  if (N <= 15)
6493  {
6494  // fixarray
6495  v.push_back(static_cast<uint8_t>(0x90 | N));
6496  }
6497  else if (N <= 0xffff)
6498  {
6499  // array 16
6500  v.push_back(0xdc);
6501  add_to_vector(v, 2, N);
6502  }
6503  else if (N <= 0xffffffff)
6504  {
6505  // array 32
6506  v.push_back(0xdd);
6507  add_to_vector(v, 4, N);
6508  }
6509 
6510  // append each element
6511  for (const auto& el : *j.m_value.array)
6512  {
6513  to_msgpack_internal(el, v);
6514  }
6515  break;
6516  }
6517 
6518  case value_t::object:
6519  {
6520  const auto N = j.m_value.object->size();
6521  if (N <= 15)
6522  {
6523  // fixmap
6524  v.push_back(static_cast<uint8_t>(0x80 | (N & 0xf)));
6525  }
6526  else if (N <= 65535)
6527  {
6528  // map 16
6529  v.push_back(0xde);
6530  add_to_vector(v, 2, N);
6531  }
6532  else if (N <= 4294967295)
6533  {
6534  // map 32
6535  v.push_back(0xdf);
6536  add_to_vector(v, 4, N);
6537  }
6538 
6539  // append each element
6540  for (const auto& el : *j.m_value.object)
6541  {
6542  to_msgpack_internal(el.first, v);
6543  to_msgpack_internal(el.second, v);
6544  }
6545  break;
6546  }
6547 
6548  default:
6549  {
6550  break;
6551  }
6552  }
6553  }
6554 
6565  static void to_cbor_internal(const basic_json& j, std::vector<uint8_t>& v)
6566  {
6567  switch (j.type())
6568  {
6569  case value_t::null:
6570  {
6571  v.push_back(0xf6);
6572  break;
6573  }
6574 
6575  case value_t::boolean:
6576  {
6577  v.push_back(j.m_value.boolean ? 0xf5 : 0xf4);
6578  break;
6579  }
6580 
6581  case value_t::number_integer:
6582  {
6583  if (j.m_value.number_integer >= 0)
6584  {
6585  // CBOR does not differentiate between positive signed
6586  // integers and unsigned integers. Therefore, we used the
6587  // code from the value_t::number_unsigned case here.
6588  if (j.m_value.number_integer <= 0x17)
6589  {
6590  add_to_vector(v, 1, j.m_value.number_integer);
6591  }
6592  else if (j.m_value.number_integer <= UINT8_MAX)
6593  {
6594  v.push_back(0x18);
6595  // one-byte uint8_t
6596  add_to_vector(v, 1, j.m_value.number_integer);
6597  }
6598  else if (j.m_value.number_integer <= UINT16_MAX)
6599  {
6600  v.push_back(0x19);
6601  // two-byte uint16_t
6602  add_to_vector(v, 2, j.m_value.number_integer);
6603  }
6604  else if (j.m_value.number_integer <= UINT32_MAX)
6605  {
6606  v.push_back(0x1a);
6607  // four-byte uint32_t
6608  add_to_vector(v, 4, j.m_value.number_integer);
6609  }
6610  else
6611  {
6612  v.push_back(0x1b);
6613  // eight-byte uint64_t
6614  add_to_vector(v, 8, j.m_value.number_integer);
6615  }
6616  }
6617  else
6618  {
6619  // The conversions below encode the sign in the first
6620  // byte, and the value is converted to a positive number.
6621  const auto positive_number = -1 - j.m_value.number_integer;
6622  if (j.m_value.number_integer >= -24)
6623  {
6624  v.push_back(static_cast<uint8_t>(0x20 + positive_number));
6625  }
6626  else if (positive_number <= UINT8_MAX)
6627  {
6628  // int 8
6629  v.push_back(0x38);
6630  add_to_vector(v, 1, positive_number);
6631  }
6632  else if (positive_number <= UINT16_MAX)
6633  {
6634  // int 16
6635  v.push_back(0x39);
6636  add_to_vector(v, 2, positive_number);
6637  }
6638  else if (positive_number <= UINT32_MAX)
6639  {
6640  // int 32
6641  v.push_back(0x3a);
6642  add_to_vector(v, 4, positive_number);
6643  }
6644  else
6645  {
6646  // int 64
6647  v.push_back(0x3b);
6648  add_to_vector(v, 8, positive_number);
6649  }
6650  }
6651  break;
6652  }
6653 
6654  case value_t::number_unsigned:
6655  {
6656  if (j.m_value.number_unsigned <= 0x17)
6657  {
6658  v.push_back(static_cast<uint8_t>(j.m_value.number_unsigned));
6659  }
6660  else if (j.m_value.number_unsigned <= 0xff)
6661  {
6662  v.push_back(0x18);
6663  // one-byte uint8_t
6664  add_to_vector(v, 1, j.m_value.number_unsigned);
6665  }
6666  else if (j.m_value.number_unsigned <= 0xffff)
6667  {
6668  v.push_back(0x19);
6669  // two-byte uint16_t
6670  add_to_vector(v, 2, j.m_value.number_unsigned);
6671  }
6672  else if (j.m_value.number_unsigned <= 0xffffffff)
6673  {
6674  v.push_back(0x1a);
6675  // four-byte uint32_t
6676  add_to_vector(v, 4, j.m_value.number_unsigned);
6677  }
6678  else if (j.m_value.number_unsigned <= 0xffffffffffffffff)
6679  {
6680  v.push_back(0x1b);
6681  // eight-byte uint64_t
6682  add_to_vector(v, 8, j.m_value.number_unsigned);
6683  }
6684  break;
6685  }
6686 
6687  case value_t::number_float:
6688  {
6689  // Double-Precision Float
6690  v.push_back(0xfb);
6691  const auto* helper = reinterpret_cast<const uint8_t*>(&(j.m_value.number_float));
6692  for (size_t i = 0; i < 8; ++i)
6693  {
6694  v.push_back(helper[7 - i]);
6695  }
6696  break;
6697  }
6698 
6699  case value_t::string:
6700  {
6701  const auto N = j.m_value.string->size();
6702  if (N <= 0x17)
6703  {
6704  v.push_back(0x60 + N); // 1 byte for string + size
6705  }
6706  else if (N <= 0xff)
6707  {
6708  v.push_back(0x78); // one-byte uint8_t for N
6709  add_to_vector(v, 1, N);
6710  }
6711  else if (N <= 0xffff)
6712  {
6713  v.push_back(0x79); // two-byte uint16_t for N
6714  add_to_vector(v, 2, N);
6715  }
6716  else if (N <= 0xffffffff)
6717  {
6718  v.push_back(0x7a); // four-byte uint32_t for N
6719  add_to_vector(v, 4, N);
6720  }
6721  // LCOV_EXCL_START
6722  else if (N <= 0xffffffffffffffff)
6723  {
6724  v.push_back(0x7b); // eight-byte uint64_t for N
6725  add_to_vector(v, 8, N);
6726  }
6727  // LCOV_EXCL_STOP
6728 
6729  // append string
6730  std::copy(j.m_value.string->begin(), j.m_value.string->end(),
6731  std::back_inserter(v));
6732  break;
6733  }
6734 
6735  case value_t::array:
6736  {
6737  const auto N = j.m_value.array->size();
6738  if (N <= 0x17)
6739  {
6740  v.push_back(0x80 + N); // 1 byte for array + size
6741  }
6742  else if (N <= 0xff)
6743  {
6744  v.push_back(0x98); // one-byte uint8_t for N
6745  add_to_vector(v, 1, N);
6746  }
6747  else if (N <= 0xffff)
6748  {
6749  v.push_back(0x99); // two-byte uint16_t for N
6750  add_to_vector(v, 2, N);
6751  }
6752  else if (N <= 0xffffffff)
6753  {
6754  v.push_back(0x9a); // four-byte uint32_t for N
6755  add_to_vector(v, 4, N);
6756  }
6757  // LCOV_EXCL_START
6758  else if (N <= 0xffffffffffffffff)
6759  {
6760  v.push_back(0x9b); // eight-byte uint64_t for N
6761  add_to_vector(v, 8, N);
6762  }
6763  // LCOV_EXCL_STOP
6764 
6765  // append each element
6766  for (const auto& el : *j.m_value.array)
6767  {
6768  to_cbor_internal(el, v);
6769  }
6770  break;
6771  }
6772 
6773  case value_t::object:
6774  {
6775  const auto N = j.m_value.object->size();
6776  if (N <= 0x17)
6777  {
6778  v.push_back(0xa0 + N); // 1 byte for object + size
6779  }
6780  else if (N <= 0xff)
6781  {
6782  v.push_back(0xb8);
6783  add_to_vector(v, 1, N); // one-byte uint8_t for N
6784  }
6785  else if (N <= 0xffff)
6786  {
6787  v.push_back(0xb9);
6788  add_to_vector(v, 2, N); // two-byte uint16_t for N
6789  }
6790  else if (N <= 0xffffffff)
6791  {
6792  v.push_back(0xba);
6793  add_to_vector(v, 4, N); // four-byte uint32_t for N
6794  }
6795  // LCOV_EXCL_START
6796  else if (N <= 0xffffffffffffffff)
6797  {
6798  v.push_back(0xbb);
6799  add_to_vector(v, 8, N); // eight-byte uint64_t for N
6800  }
6801  // LCOV_EXCL_STOP
6802 
6803  // append each element
6804  for (const auto& el : *j.m_value.object)
6805  {
6806  to_cbor_internal(el.first, v);
6807  to_cbor_internal(el.second, v);
6808  }
6809  break;
6810  }
6811 
6812  default:
6813  {
6814  break;
6815  }
6816  }
6817  }
6818 
6819 
6820  /*
6821  @brief checks if given lengths do not exceed the size of a given vector
6822 
6823  To secure the access to the byte vector during CBOR/MessagePack
6824  deserialization, bytes are copied from the vector into buffers. This
6825  function checks if the number of bytes to copy (@a len) does not exceed
6826  the size @s size of the vector. Additionally, an @a offset is given from
6827  where to start reading the bytes.
6828 
6829  This function checks whether reading the bytes is safe; that is, offset is
6830  a valid index in the vector, offset+len
6831 
6832  @param[in] size size of the byte vector
6833  @param[in] len number of bytes to read
6834  @param[in] offset offset where to start reading
6835 
6836  vec: x x x x x X X X X X
6837  ^ ^ ^
6838  0 offset len
6839 
6840  @throws out_of_range if `len > v.size()`
6841  */
6842  static void check_length(const size_t size, const size_t len, const size_t offset)
6843  {
6844  // simple case: requested length is greater than the vector's length
6845  if (len > size or offset > size)
6846  {
6847  throw std::out_of_range("len out of range");
6848  }
6849 
6850  // second case: adding offset would result in overflow
6851  if ((size > (std::numeric_limits<size_t>::max() - offset)))
6852  {
6853  throw std::out_of_range("len+offset out of range");
6854  }
6855 
6856  // last case: reading past the end of the vector
6857  if (len + offset > size)
6858  {
6859  throw std::out_of_range("len+offset out of range");
6860  }
6861  }
6862 
6877  static basic_json from_msgpack_internal(const std::vector<uint8_t>& v, size_t& idx)
6878  {
6879  // make sure reading 1 byte is safe
6880  check_length(v.size(), 1, idx);
6881 
6882  // store and increment index
6883  const size_t current_idx = idx++;
6884 
6885  if (v[current_idx] <= 0xbf)
6886  {
6887  if (v[current_idx] <= 0x7f) // positive fixint
6888  {
6889  return v[current_idx];
6890  }
6891  if (v[current_idx] <= 0x8f) // fixmap
6892  {
6893  basic_json result = value_t::object;
6894  const size_t len = v[current_idx] & 0x0f;
6895  for (size_t i = 0; i < len; ++i)
6896  {
6897  std::string key = from_msgpack_internal(v, idx);
6898  result[key] = from_msgpack_internal(v, idx);
6899  }
6900  return result;
6901  }
6902  else if (v[current_idx] <= 0x9f) // fixarray
6903  {
6904  basic_json result = value_t::array;
6905  const size_t len = v[current_idx] & 0x0f;
6906  for (size_t i = 0; i < len; ++i)
6907  {
6908  result.push_back(from_msgpack_internal(v, idx));
6909  }
6910  return result;
6911  }
6912  else // fixstr
6913  {
6914  const size_t len = v[current_idx] & 0x1f;
6915  const size_t offset = current_idx + 1;
6916  idx += len; // skip content bytes
6917  check_length(v.size(), len, offset);
6918  return std::string(reinterpret_cast<const char*>(v.data()) + offset, len);
6919  }
6920  }
6921  else if (v[current_idx] >= 0xe0) // negative fixint
6922  {
6923  return static_cast<int8_t>(v[current_idx]);
6924  }
6925  else
6926  {
6927  switch (v[current_idx])
6928  {
6929  case 0xc0: // nil
6930  {
6931  return value_t::null;
6932  }
6933 
6934  case 0xc2: // false
6935  {
6936  return false;
6937  }
6938 
6939  case 0xc3: // true
6940  {
6941  return true;
6942  }
6943 
6944  case 0xca: // float 32
6945  {
6946  // copy bytes in reverse order into the double variable
6947  float res;
6948  for (size_t byte = 0; byte < sizeof(float); ++byte)
6949  {
6950  reinterpret_cast<uint8_t*>(&res)[sizeof(float) - byte - 1] = v.at(current_idx + 1 + byte);
6951  }
6952  idx += sizeof(float); // skip content bytes
6953  return res;
6954  }
6955 
6956  case 0xcb: // float 64
6957  {
6958  // copy bytes in reverse order into the double variable
6959  double res;
6960  for (size_t byte = 0; byte < sizeof(double); ++byte)
6961  {
6962  reinterpret_cast<uint8_t*>(&res)[sizeof(double) - byte - 1] = v.at(current_idx + 1 + byte);
6963  }
6964  idx += sizeof(double); // skip content bytes
6965  return res;
6966  }
6967 
6968  case 0xcc: // uint 8
6969  {
6970  idx += 1; // skip content byte
6971  return get_from_vector<uint8_t>(v, current_idx);
6972  }
6973 
6974  case 0xcd: // uint 16
6975  {
6976  idx += 2; // skip 2 content bytes
6977  return get_from_vector<uint16_t>(v, current_idx);
6978  }
6979 
6980  case 0xce: // uint 32
6981  {
6982  idx += 4; // skip 4 content bytes
6983  return get_from_vector<uint32_t>(v, current_idx);
6984  }
6985 
6986  case 0xcf: // uint 64
6987  {
6988  idx += 8; // skip 8 content bytes
6989  return get_from_vector<uint64_t>(v, current_idx);
6990  }
6991 
6992  case 0xd0: // int 8
6993  {
6994  idx += 1; // skip content byte
6995  return get_from_vector<int8_t>(v, current_idx);
6996  }
6997 
6998  case 0xd1: // int 16
6999  {
7000  idx += 2; // skip 2 content bytes
7001  return get_from_vector<int16_t>(v, current_idx);
7002  }
7003 
7004  case 0xd2: // int 32
7005  {
7006  idx += 4; // skip 4 content bytes
7007  return get_from_vector<int32_t>(v, current_idx);
7008  }
7009 
7010  case 0xd3: // int 64
7011  {
7012  idx += 8; // skip 8 content bytes
7013  return get_from_vector<int64_t>(v, current_idx);
7014  }
7015 
7016  case 0xd9: // str 8
7017  {
7018  const auto len = static_cast<size_t>(get_from_vector<uint8_t>(v, current_idx));
7019  const size_t offset = current_idx + 2;
7020  idx += len + 1; // skip size byte + content bytes
7021  check_length(v.size(), len, offset);
7022  return std::string(reinterpret_cast<const char*>(v.data()) + offset, len);
7023  }
7024 
7025  case 0xda: // str 16
7026  {
7027  const auto len = static_cast<size_t>(get_from_vector<uint16_t>(v, current_idx));
7028  const size_t offset = current_idx + 3;
7029  idx += len + 2; // skip 2 size bytes + content bytes
7030  check_length(v.size(), len, offset);
7031  return std::string(reinterpret_cast<const char*>(v.data()) + offset, len);
7032  }
7033 
7034  case 0xdb: // str 32
7035  {
7036  const auto len = static_cast<size_t>(get_from_vector<uint32_t>(v, current_idx));
7037  const size_t offset = current_idx + 5;
7038  idx += len + 4; // skip 4 size bytes + content bytes
7039  check_length(v.size(), len, offset);
7040  return std::string(reinterpret_cast<const char*>(v.data()) + offset, len);
7041  }
7042 
7043  case 0xdc: // array 16
7044  {
7045  basic_json result = value_t::array;
7046  const auto len = static_cast<size_t>(get_from_vector<uint16_t>(v, current_idx));
7047  idx += 2; // skip 2 size bytes
7048  for (size_t i = 0; i < len; ++i)
7049  {
7050  result.push_back(from_msgpack_internal(v, idx));
7051  }
7052  return result;
7053  }
7054 
7055  case 0xdd: // array 32
7056  {
7057  basic_json result = value_t::array;
7058  const auto len = static_cast<size_t>(get_from_vector<uint32_t>(v, current_idx));
7059  idx += 4; // skip 4 size bytes
7060  for (size_t i = 0; i < len; ++i)
7061  {
7062  result.push_back(from_msgpack_internal(v, idx));
7063  }
7064  return result;
7065  }
7066 
7067  case 0xde: // map 16
7068  {
7069  basic_json result = value_t::object;
7070  const auto len = static_cast<size_t>(get_from_vector<uint16_t>(v, current_idx));
7071  idx += 2; // skip 2 size bytes
7072  for (size_t i = 0; i < len; ++i)
7073  {
7074  std::string key = from_msgpack_internal(v, idx);
7075  result[key] = from_msgpack_internal(v, idx);
7076  }
7077  return result;
7078  }
7079 
7080  case 0xdf: // map 32
7081  {
7082  basic_json result = value_t::object;
7083  const auto len = static_cast<size_t>(get_from_vector<uint32_t>(v, current_idx));
7084  idx += 4; // skip 4 size bytes
7085  for (size_t i = 0; i < len; ++i)
7086  {
7087  std::string key = from_msgpack_internal(v, idx);
7088  result[key] = from_msgpack_internal(v, idx);
7089  }
7090  return result;
7091  }
7092 
7093  default:
7094  {
7095  throw std::invalid_argument("error parsing a msgpack @ " + std::to_string(current_idx) + ": " + std::to_string(static_cast<int>(v[current_idx])));
7096  }
7097  }
7098  }
7099  }
7100 
7115  static basic_json from_cbor_internal(const std::vector<uint8_t>& v, size_t& idx)
7116  {
7117  // store and increment index
7118  const size_t current_idx = idx++;
7119 
7120  switch (v.at(current_idx))
7121  {
7122  // Integer 0x00..0x17 (0..23)
7123  case 0x00:
7124  case 0x01:
7125  case 0x02:
7126  case 0x03:
7127  case 0x04:
7128  case 0x05:
7129  case 0x06:
7130  case 0x07:
7131  case 0x08:
7132  case 0x09:
7133  case 0x0a:
7134  case 0x0b:
7135  case 0x0c:
7136  case 0x0d:
7137  case 0x0e:
7138  case 0x0f:
7139  case 0x10:
7140  case 0x11:
7141  case 0x12:
7142  case 0x13:
7143  case 0x14:
7144  case 0x15:
7145  case 0x16:
7146  case 0x17:
7147  {
7148  return v[current_idx];
7149  }
7150 
7151  case 0x18: // Unsigned integer (one-byte uint8_t follows)
7152  {
7153  idx += 1; // skip content byte
7154  return get_from_vector<uint8_t>(v, current_idx);
7155  }
7156 
7157  case 0x19: // Unsigned integer (two-byte uint16_t follows)
7158  {
7159  idx += 2; // skip 2 content bytes
7160  return get_from_vector<uint16_t>(v, current_idx);
7161  }
7162 
7163  case 0x1a: // Unsigned integer (four-byte uint32_t follows)
7164  {
7165  idx += 4; // skip 4 content bytes
7166  return get_from_vector<uint32_t>(v, current_idx);
7167  }
7168 
7169  case 0x1b: // Unsigned integer (eight-byte uint64_t follows)
7170  {
7171  idx += 8; // skip 8 content bytes
7172  return get_from_vector<uint64_t>(v, current_idx);
7173  }
7174 
7175  // Negative integer -1-0x00..-1-0x17 (-1..-24)
7176  case 0x20:
7177  case 0x21:
7178  case 0x22:
7179  case 0x23:
7180  case 0x24:
7181  case 0x25:
7182  case 0x26:
7183  case 0x27:
7184  case 0x28:
7185  case 0x29:
7186  case 0x2a:
7187  case 0x2b:
7188  case 0x2c:
7189  case 0x2d:
7190  case 0x2e:
7191  case 0x2f:
7192  case 0x30:
7193  case 0x31:
7194  case 0x32:
7195  case 0x33:
7196  case 0x34:
7197  case 0x35:
7198  case 0x36:
7199  case 0x37:
7200  {
7201  return static_cast<int8_t>(0x20 - 1 - v[current_idx]);
7202  }
7203 
7204  case 0x38: // Negative integer (one-byte uint8_t follows)
7205  {
7206  idx += 1; // skip content byte
7207  // must be uint8_t !
7208  return static_cast<number_integer_t>(-1) - get_from_vector<uint8_t>(v, current_idx);
7209  }
7210 
7211  case 0x39: // Negative integer -1-n (two-byte uint16_t follows)
7212  {
7213  idx += 2; // skip 2 content bytes
7214  return static_cast<number_integer_t>(-1) - get_from_vector<uint16_t>(v, current_idx);
7215  }
7216 
7217  case 0x3a: // Negative integer -1-n (four-byte uint32_t follows)
7218  {
7219  idx += 4; // skip 4 content bytes
7220  return static_cast<number_integer_t>(-1) - get_from_vector<uint32_t>(v, current_idx);
7221  }
7222 
7223  case 0x3b: // Negative integer -1-n (eight-byte uint64_t follows)
7224  {
7225  idx += 8; // skip 8 content bytes
7226  return static_cast<number_integer_t>(-1) - static_cast<number_integer_t>(get_from_vector<uint64_t>(v, current_idx));
7227  }
7228 
7229  // UTF-8 string (0x00..0x17 bytes follow)
7230  case 0x60:
7231  case 0x61:
7232  case 0x62:
7233  case 0x63:
7234  case 0x64:
7235  case 0x65:
7236  case 0x66:
7237  case 0x67:
7238  case 0x68:
7239  case 0x69:
7240  case 0x6a:
7241  case 0x6b:
7242  case 0x6c:
7243  case 0x6d:
7244  case 0x6e:
7245  case 0x6f:
7246  case 0x70:
7247  case 0x71:
7248  case 0x72:
7249  case 0x73:
7250  case 0x74:
7251  case 0x75:
7252  case 0x76:
7253  case 0x77:
7254  {
7255  const auto len = static_cast<size_t>(v[current_idx] - 0x60);
7256  const size_t offset = current_idx + 1;
7257  idx += len; // skip content bytes
7258  check_length(v.size(), len, offset);
7259  return std::string(reinterpret_cast<const char*>(v.data()) + offset, len);
7260  }
7261 
7262  case 0x78: // UTF-8 string (one-byte uint8_t for n follows)
7263  {
7264  const auto len = static_cast<size_t>(get_from_vector<uint8_t>(v, current_idx));
7265  const size_t offset = current_idx + 2;
7266  idx += len + 1; // skip size byte + content bytes
7267  check_length(v.size(), len, offset);
7268  return std::string(reinterpret_cast<const char*>(v.data()) + offset, len);
7269  }
7270 
7271  case 0x79: // UTF-8 string (two-byte uint16_t for n follow)
7272  {
7273  const auto len = static_cast<size_t>(get_from_vector<uint16_t>(v, current_idx));
7274  const size_t offset = current_idx + 3;
7275  idx += len + 2; // skip 2 size bytes + content bytes
7276  check_length(v.size(), len, offset);
7277  return std::string(reinterpret_cast<const char*>(v.data()) + offset, len);
7278  }
7279 
7280  case 0x7a: // UTF-8 string (four-byte uint32_t for n follow)
7281  {
7282  const auto len = static_cast<size_t>(get_from_vector<uint32_t>(v, current_idx));
7283  const size_t offset = current_idx + 5;
7284  idx += len + 4; // skip 4 size bytes + content bytes
7285  check_length(v.size(), len, offset);
7286  return std::string(reinterpret_cast<const char*>(v.data()) + offset, len);
7287  }
7288 
7289  case 0x7b: // UTF-8 string (eight-byte uint64_t for n follow)
7290  {
7291  const auto len = static_cast<size_t>(get_from_vector<uint64_t>(v, current_idx));
7292  const size_t offset = current_idx + 9;
7293  idx += len + 8; // skip 8 size bytes + content bytes
7294  check_length(v.size(), len, offset);
7295  return std::string(reinterpret_cast<const char*>(v.data()) + offset, len);
7296  }
7297 
7298  case 0x7f: // UTF-8 string (indefinite length)
7299  {
7300  std::string result;
7301  while (v.at(idx) != 0xff)
7302  {
7303  string_t s = from_cbor_internal(v, idx);
7304  result += s;
7305  }
7306  // skip break byte (0xFF)
7307  idx += 1;
7308  return result;
7309  }
7310 
7311  // array (0x00..0x17 data items follow)
7312  case 0x80:
7313  case 0x81:
7314  case 0x82:
7315  case 0x83:
7316  case 0x84:
7317  case 0x85:
7318  case 0x86:
7319  case 0x87:
7320  case 0x88:
7321  case 0x89:
7322  case 0x8a:
7323  case 0x8b:
7324  case 0x8c:
7325  case 0x8d:
7326  case 0x8e:
7327  case 0x8f:
7328  case 0x90:
7329  case 0x91:
7330  case 0x92:
7331  case 0x93:
7332  case 0x94:
7333  case 0x95:
7334  case 0x96:
7335  case 0x97:
7336  {
7337  basic_json result = value_t::array;
7338  const auto len = static_cast<size_t>(v[current_idx] - 0x80);
7339  for (size_t i = 0; i < len; ++i)
7340  {
7341  result.push_back(from_cbor_internal(v, idx));
7342  }
7343  return result;
7344  }
7345 
7346  case 0x98: // array (one-byte uint8_t for n follows)
7347  {
7348  basic_json result = value_t::array;
7349  const auto len = static_cast<size_t>(get_from_vector<uint8_t>(v, current_idx));
7350  idx += 1; // skip 1 size byte
7351  for (size_t i = 0; i < len; ++i)
7352  {
7353  result.push_back(from_cbor_internal(v, idx));
7354  }
7355  return result;
7356  }
7357 
7358  case 0x99: // array (two-byte uint16_t for n follow)
7359  {
7360  basic_json result = value_t::array;
7361  const auto len = static_cast<size_t>(get_from_vector<uint16_t>(v, current_idx));
7362  idx += 2; // skip 4 size bytes
7363  for (size_t i = 0; i < len; ++i)
7364  {
7365  result.push_back(from_cbor_internal(v, idx));
7366  }
7367  return result;
7368  }
7369 
7370  case 0x9a: // array (four-byte uint32_t for n follow)
7371  {
7372  basic_json result = value_t::array;
7373  const auto len = static_cast<size_t>(get_from_vector<uint32_t>(v, current_idx));
7374  idx += 4; // skip 4 size bytes
7375  for (size_t i = 0; i < len; ++i)
7376  {
7377  result.push_back(from_cbor_internal(v, idx));
7378  }
7379  return result;
7380  }
7381 
7382  case 0x9b: // array (eight-byte uint64_t for n follow)
7383  {
7384  basic_json result = value_t::array;
7385  const auto len = static_cast<size_t>(get_from_vector<uint64_t>(v, current_idx));
7386  idx += 8; // skip 8 size bytes
7387  for (size_t i = 0; i < len; ++i)
7388  {
7389  result.push_back(from_cbor_internal(v, idx));
7390  }
7391  return result;
7392  }
7393 
7394  case 0x9f: // array (indefinite length)
7395  {
7396  basic_json result = value_t::array;
7397  while (v.at(idx) != 0xff)
7398  {
7399  result.push_back(from_cbor_internal(v, idx));
7400  }
7401  // skip break byte (0xFF)
7402  idx += 1;
7403  return result;
7404  }
7405 
7406  // map (0x00..0x17 pairs of data items follow)
7407  case 0xa0:
7408  case 0xa1:
7409  case 0xa2:
7410  case 0xa3:
7411  case 0xa4:
7412  case 0xa5:
7413  case 0xa6:
7414  case 0xa7:
7415  case 0xa8:
7416  case 0xa9:
7417  case 0xaa:
7418  case 0xab:
7419  case 0xac:
7420  case 0xad:
7421  case 0xae:
7422  case 0xaf:
7423  case 0xb0:
7424  case 0xb1:
7425  case 0xb2:
7426  case 0xb3:
7427  case 0xb4:
7428  case 0xb5:
7429  case 0xb6:
7430  case 0xb7:
7431  {
7432  basic_json result = value_t::object;
7433  const auto len = static_cast<size_t>(v[current_idx] - 0xa0);
7434  for (size_t i = 0; i < len; ++i)
7435  {
7436  std::string key = from_cbor_internal(v, idx);
7437  result[key] = from_cbor_internal(v, idx);
7438  }
7439  return result;
7440  }
7441 
7442  case 0xb8: // map (one-byte uint8_t for n follows)
7443  {
7444  basic_json result = value_t::object;
7445  const auto len = static_cast<size_t>(get_from_vector<uint8_t>(v, current_idx));
7446  idx += 1; // skip 1 size byte
7447  for (size_t i = 0; i < len; ++i)
7448  {
7449  std::string key = from_cbor_internal(v, idx);
7450  result[key] = from_cbor_internal(v, idx);
7451  }
7452  return result;
7453  }
7454 
7455  case 0xb9: // map (two-byte uint16_t for n follow)
7456  {
7457  basic_json result = value_t::object;
7458  const auto len = static_cast<size_t>(get_from_vector<uint16_t>(v, current_idx));
7459  idx += 2; // skip 2 size bytes
7460  for (size_t i = 0; i < len; ++i)
7461  {
7462  std::string key = from_cbor_internal(v, idx);
7463  result[key] = from_cbor_internal(v, idx);
7464  }
7465  return result;
7466  }
7467 
7468  case 0xba: // map (four-byte uint32_t for n follow)
7469  {
7470  basic_json result = value_t::object;
7471  const auto len = static_cast<size_t>(get_from_vector<uint32_t>(v, current_idx));
7472  idx += 4; // skip 4 size bytes
7473  for (size_t i = 0; i < len; ++i)
7474  {
7475  std::string key = from_cbor_internal(v, idx);
7476  result[key] = from_cbor_internal(v, idx);
7477  }
7478  return result;
7479  }
7480 
7481  case 0xbb: // map (eight-byte uint64_t for n follow)
7482  {
7483  basic_json result = value_t::object;
7484  const auto len = static_cast<size_t>(get_from_vector<uint64_t>(v, current_idx));
7485  idx += 8; // skip 8 size bytes
7486  for (size_t i = 0; i < len; ++i)
7487  {
7488  std::string key = from_cbor_internal(v, idx);
7489  result[key] = from_cbor_internal(v, idx);
7490  }
7491  return result;
7492  }
7493 
7494  case 0xbf: // map (indefinite length)
7495  {
7496  basic_json result = value_t::object;
7497  while (v.at(idx) != 0xff)
7498  {
7499  std::string key = from_cbor_internal(v, idx);
7500  result[key] = from_cbor_internal(v, idx);
7501  }
7502  // skip break byte (0xFF)
7503  idx += 1;
7504  return result;
7505  }
7506 
7507  case 0xf4: // false
7508  {
7509  return false;
7510  }
7511 
7512  case 0xf5: // true
7513  {
7514  return true;
7515  }
7516 
7517  case 0xf6: // null
7518  {
7519  return value_t::null;
7520  }
7521 
7522  case 0xf9: // Half-Precision Float (two-byte IEEE 754)
7523  {
7524  idx += 2; // skip two content bytes
7525 
7526  // code from RFC 7049, Appendix D, Figure 3:
7527  // As half-precision floating-point numbers were only added to
7528  // IEEE 754 in 2008, today's programming platforms often still
7529  // only have limited support for them. It is very easy to
7530  // include at least decoding support for them even without such
7531  // support. An example of a small decoder for half-precision
7532  // floating-point numbers in the C language is shown in Fig. 3.
7533  const int half = (v.at(current_idx + 1) << 8) + v.at(current_idx + 2);
7534  const int exp = (half >> 10) & 0x1f;
7535  const int mant = half & 0x3ff;
7536  double val;
7537  if (exp == 0)
7538  {
7539  val = std::ldexp(mant, -24);
7540  }
7541  else if (exp != 31)
7542  {
7543  val = std::ldexp(mant + 1024, exp - 25);
7544  }
7545  else
7546  {
7547  val = mant == 0 ? INFINITY : NAN;
7548  }
7549  return (half & 0x8000) != 0 ? -val : val;
7550  }
7551 
7552  case 0xfa: // Single-Precision Float (four-byte IEEE 754)
7553  {
7554  // copy bytes in reverse order into the float variable
7555  float res;
7556  for (size_t byte = 0; byte < sizeof(float); ++byte)
7557  {
7558  reinterpret_cast<uint8_t*>(&res)[sizeof(float) - byte - 1] = v.at(current_idx + 1 + byte);
7559  }
7560  idx += sizeof(float); // skip content bytes
7561  return res;
7562  }
7563 
7564  case 0xfb: // Double-Precision Float (eight-byte IEEE 754)
7565  {
7566  // copy bytes in reverse order into the double variable
7567  double res;
7568  for (size_t byte = 0; byte < sizeof(double); ++byte)
7569  {
7570  reinterpret_cast<uint8_t*>(&res)[sizeof(double) - byte - 1] = v.at(current_idx + 1 + byte);
7571  }
7572  idx += sizeof(double); // skip content bytes
7573  return res;
7574  }
7575 
7576  default: // anything else (0xFF is handled inside the other types)
7577  {
7578  throw std::invalid_argument("error parsing a CBOR @ " + std::to_string(current_idx) + ": " + std::to_string(static_cast<int>(v[current_idx])));
7579  }
7580  }
7581  }
7582 
7583  public:
7604  static std::vector<uint8_t> to_msgpack(const basic_json& j)
7605  {
7606  std::vector<uint8_t> result;
7607  to_msgpack_internal(j, result);
7608  return result;
7609  }
7610 
7633  static basic_json from_msgpack(const std::vector<uint8_t>& v)
7634  {
7635  size_t i = 0;
7636  return from_msgpack_internal(v, i);
7637  }
7638 
7660  static std::vector<uint8_t> to_cbor(const basic_json& j)
7661  {
7662  std::vector<uint8_t> result;
7663  to_cbor_internal(j, result);
7664  return result;
7665  }
7666 
7690  static basic_json from_cbor(const std::vector<uint8_t>& v)
7691  {
7692  size_t i = 0;
7693  return from_cbor_internal(v, i);
7694  }
7695 
7697 
7698  private:
7700  // convenience functions //
7702 
7715  std::string type_name() const
7716  {
7717  switch (m_type)
7718  {
7719  case value_t::null:
7720  return "null";
7721  case value_t::object:
7722  return "object";
7723  case value_t::array:
7724  return "array";
7725  case value_t::string:
7726  return "string";
7727  case value_t::boolean:
7728  return "boolean";
7729  case value_t::discarded:
7730  return "discarded";
7731  default:
7732  return "number";
7733  }
7734  }
7735 
7744  static std::size_t extra_space(const string_t& s) noexcept
7745  {
7746  return std::accumulate(s.begin(), s.end(), size_t{},
7747  [](size_t res, typename string_t::value_type c)
7748  {
7749  switch (c)
7750  {
7751  case '"':
7752  case '\\':
7753  case '\b':
7754  case '\f':
7755  case '\n':
7756  case '\r':
7757  case '\t':
7758  {
7759  // from c (1 byte) to \x (2 bytes)
7760  return res + 1;
7761  }
7762 
7763  default:
7764  {
7765  if (c >= 0x00 and c <= 0x1f)
7766  {
7767  // from c (1 byte) to \uxxxx (6 bytes)
7768  return res + 5;
7769  }
7770 
7771  return res;
7772  }
7773  }
7774  });
7775  }
7776 
7790  static string_t escape_string(const string_t& s)
7791  {
7792  const auto space = extra_space(s);
7793  if (space == 0)
7794  {
7795  return s;
7796  }
7797 
7798  // create a result string of necessary size
7799  string_t result(s.size() + space, '\\');
7800  std::size_t pos = 0;
7801 
7802  for (const auto& c : s)
7803  {
7804  switch (c)
7805  {
7806  // quotation mark (0x22)
7807  case '"':
7808  {
7809  result[pos + 1] = '"';
7810  pos += 2;
7811  break;
7812  }
7813 
7814  // reverse solidus (0x5c)
7815  case '\\':
7816  {
7817  // nothing to change
7818  pos += 2;
7819  break;
7820  }
7821 
7822  // backspace (0x08)
7823  case '\b':
7824  {
7825  result[pos + 1] = 'b';
7826  pos += 2;
7827  break;
7828  }
7829 
7830  // formfeed (0x0c)
7831  case '\f':
7832  {
7833  result[pos + 1] = 'f';
7834  pos += 2;
7835  break;
7836  }
7837 
7838  // newline (0x0a)
7839  case '\n':
7840  {
7841  result[pos + 1] = 'n';
7842  pos += 2;
7843  break;
7844  }
7845 
7846  // carriage return (0x0d)
7847  case '\r':
7848  {
7849  result[pos + 1] = 'r';
7850  pos += 2;
7851  break;
7852  }
7853 
7854  // horizontal tab (0x09)
7855  case '\t':
7856  {
7857  result[pos + 1] = 't';
7858  pos += 2;
7859  break;
7860  }
7861 
7862  default:
7863  {
7864  if (c >= 0x00 and c <= 0x1f)
7865  {
7866  // convert a number 0..15 to its hex representation
7867  // (0..f)
7868  static const char hexify[16] =
7869  {
7870  '0', '1', '2', '3', '4', '5', '6', '7',
7871  '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'
7872  };
7873 
7874  // print character c as \uxxxx
7875  for (const char m :
7876  { 'u', '0', '0', hexify[c >> 4], hexify[c & 0x0f]
7877  })
7878  {
7879  result[++pos] = m;
7880  }
7881 
7882  ++pos;
7883  }
7884  else
7885  {
7886  // all other characters are added as-is
7887  result[pos++] = c;
7888  }
7889  break;
7890  }
7891  }
7892  }
7893 
7894  return result;
7895  }
7896 
7914  void dump(std::ostream& o,
7915  const bool pretty_print,
7916  const unsigned int indent_step,
7917  const unsigned int current_indent = 0) const
7918  {
7919  // variable to hold indentation for recursive calls
7920  unsigned int new_indent = current_indent;
7921 
7922  switch (m_type)
7923  {
7924  case value_t::object:
7925  {
7926  if (m_value.object->empty())
7927  {
7928  o << "{}";
7929  return;
7930  }
7931 
7932  o << "{";
7933 
7934  // increase indentation
7935  if (pretty_print)
7936  {
7937  new_indent += indent_step;
7938  o << "\n";
7939  }
7940 
7941  for (auto i = m_value.object->cbegin(); i != m_value.object->cend(); ++i)
7942  {
7943  if (i != m_value.object->cbegin())
7944  {
7945  o << (pretty_print ? ",\n" : ",");
7946  }
7947  o << string_t(new_indent, ' ') << "\""
7948  << escape_string(i->first) << "\":"
7949  << (pretty_print ? " " : "");
7950  i->second.dump(o, pretty_print, indent_step, new_indent);
7951  }
7952 
7953  // decrease indentation
7954  if (pretty_print)
7955  {
7956  new_indent -= indent_step;
7957  o << "\n";
7958  }
7959 
7960  o << string_t(new_indent, ' ') + "}";
7961  return;
7962  }
7963 
7964  case value_t::array:
7965  {
7966  if (m_value.array->empty())
7967  {
7968  o << "[]";
7969  return;
7970  }
7971 
7972  o << "[";
7973 
7974  // increase indentation
7975  if (pretty_print)
7976  {
7977  new_indent += indent_step;
7978  o << "\n";
7979  }
7980 
7981  for (auto i = m_value.array->cbegin(); i != m_value.array->cend(); ++i)
7982  {
7983  if (i != m_value.array->cbegin())
7984  {
7985  o << (pretty_print ? ",\n" : ",");
7986  }
7987  o << string_t(new_indent, ' ');
7988  i->dump(o, pretty_print, indent_step, new_indent);
7989  }
7990 
7991  // decrease indentation
7992  if (pretty_print)
7993  {
7994  new_indent -= indent_step;
7995  o << "\n";
7996  }
7997 
7998  o << string_t(new_indent, ' ') << "]";
7999  return;
8000  }
8001 
8002  case value_t::string:
8003  {
8004  o << string_t("\"") << escape_string(*m_value.string) << "\"";
8005  return;
8006  }
8007 
8008  case value_t::boolean:
8009  {
8010  o << (m_value.boolean ? "true" : "false");
8011  return;
8012  }
8013 
8014  case value_t::number_integer:
8015  {
8016  o << m_value.number_integer;
8017  return;
8018  }
8019 
8020  case value_t::number_unsigned:
8021  {
8022  o << m_value.number_unsigned;
8023  return;
8024  }
8025 
8026  case value_t::number_float:
8027  {
8028  if (m_value.number_float == 0)
8029  {
8030  // special case for zero to get "0.0"/"-0.0"
8031  o << (std::signbit(m_value.number_float) ? "-0.0" : "0.0");
8032  }
8033  else
8034  {
8035  o << m_value.number_float;
8036  }
8037  return;
8038  }
8039 
8040  case value_t::discarded:
8041  {
8042  o << "<discarded>";
8043  return;
8044  }
8045 
8046  case value_t::null:
8047  {
8048  o << "null";
8049  return;
8050  }
8051  }
8052  }
8053 
8054  private:
8056  // member variables //
8058 
8060  value_t m_type = value_t::null;
8061 
8063  json_value m_value = {};
8064 
8065 
8066  private:
8068  // iterators //
8070 
8080  class primitive_iterator_t
8081  {
8082  public:
8084  void set_begin() noexcept
8085  {
8086  m_it = begin_value;
8087  }
8088 
8090  void set_end() noexcept
8091  {
8092  m_it = end_value;
8093  }
8094 
8096  constexpr bool is_begin() const noexcept
8097  {
8098  return (m_it == begin_value);
8099  }
8100 
8102  constexpr bool is_end() const noexcept
8103  {
8104  return (m_it == end_value);
8105  }
8106 
8108  operator difference_type& () noexcept
8109  {
8110  return m_it;
8111  }
8112 
8114  constexpr operator difference_type () const noexcept
8115  {
8116  return m_it;
8117  }
8118 
8119  private:
8120  static constexpr difference_type begin_value = 0;
8121  static constexpr difference_type end_value = begin_value + 1;
8122 
8124  difference_type m_it = std::numeric_limits<std::ptrdiff_t>::denorm_min();
8125  };
8126 
8134  struct internal_iterator
8135  {
8137  typename object_t::iterator object_iterator;
8139  typename array_t::iterator array_iterator;
8141  primitive_iterator_t primitive_iterator;
8142 
8144  internal_iterator() noexcept
8145  : object_iterator(), array_iterator(), primitive_iterator()
8146  {}
8147  };
8148 
8150  template<typename IteratorType>
8151  class iteration_proxy
8152  {
8153  private:
8155  class iteration_proxy_internal
8156  {
8157  private:
8159  IteratorType anchor;
8161  size_t array_index = 0;
8162 
8163  public:
8164  explicit iteration_proxy_internal(IteratorType it) noexcept
8165  : anchor(it)
8166  {}
8167 
8169  iteration_proxy_internal& operator*()
8170  {
8171  return *this;
8172  }
8173 
8175  iteration_proxy_internal& operator++()
8176  {
8177  ++anchor;
8178  ++array_index;
8179 
8180  return *this;
8181  }
8182 
8184  bool operator!= (const iteration_proxy_internal& o) const
8185  {
8186  return anchor != o.anchor;
8187  }
8188 
8190  typename basic_json::string_t key() const
8191  {
8192  assert(anchor.m_object != nullptr);
8193 
8194  switch (anchor.m_object->type())
8195  {
8196  // use integer array index as key
8197  case value_t::array:
8198  {
8199  return std::to_string(array_index);
8200  }
8201 
8202  // use key from the object
8203  case value_t::object:
8204  {
8205  return anchor.key();
8206  }
8207 
8208  // use an empty key for all primitive types
8209  default:
8210  {
8211  return "";
8212  }
8213  }
8214  }
8215 
8217  typename IteratorType::reference value() const
8218  {
8219  return anchor.value();
8220  }
8221  };
8222 
8224  typename IteratorType::reference container;
8225 
8226  public:
8228  explicit iteration_proxy(typename IteratorType::reference cont)
8229  : container(cont)
8230  {}
8231 
8233  iteration_proxy_internal begin() noexcept
8234  {
8235  return iteration_proxy_internal(container.begin());
8236  }
8237 
8239  iteration_proxy_internal end() noexcept
8240  {
8241  return iteration_proxy_internal(container.end());
8242  }
8243  };
8244 
8245  public:
8265  template<typename U>
8266  class iter_impl : public std::iterator<std::random_access_iterator_tag, U>
8267  {
8269  friend class basic_json;
8270 
8271  // make sure U is basic_json or const basic_json
8272  static_assert(std::is_same<U, basic_json>::value
8273  or std::is_same<U, const basic_json>::value,
8274  "iter_impl only accepts (const) basic_json");
8275 
8276  public:
8282  using pointer = typename std::conditional<std::is_const<U>::value,
8283  typename basic_json::const_pointer,
8284  typename basic_json::pointer>::type;
8286  using reference = typename std::conditional<std::is_const<U>::value,
8287  typename basic_json::const_reference,
8288  typename basic_json::reference>::type;
8290  using iterator_category = std::bidirectional_iterator_tag;
8291 
8293  iter_impl() = default;
8294 
8301  explicit iter_impl(pointer object) noexcept
8302  : m_object(object)
8303  {
8304  assert(m_object != nullptr);
8305 
8306  switch (m_object->m_type)
8307  {
8309  {
8310  m_it.object_iterator = typename object_t::iterator();
8311  break;
8312  }
8313 
8315  {
8316  m_it.array_iterator = typename array_t::iterator();
8317  break;
8318  }
8319 
8320  default:
8321  {
8322  m_it.primitive_iterator = primitive_iterator_t();
8323  break;
8324  }
8325  }
8326  }
8327 
8328  /*
8329  Use operator `const_iterator` instead of `const_iterator(const iterator&
8330  other) noexcept` to avoid two class definitions for @ref iterator and
8331  @ref const_iterator.
8332 
8333  This function is only called if this class is an @ref iterator. If this
8334  class is a @ref const_iterator this function is not called.
8335  */
8336  operator const_iterator() const
8337  {
8338  const_iterator ret;
8339 
8340  if (m_object)
8341  {
8342  ret.m_object = m_object;
8343  ret.m_it = m_it;
8344  }
8345 
8346  return ret;
8347  }
8348 
8354  iter_impl(const iter_impl& other) noexcept
8355  : m_object(other.m_object), m_it(other.m_it)
8356  {}
8357 
8363  iter_impl& operator=(iter_impl other) noexcept(
8364  std::is_nothrow_move_constructible<pointer>::value and
8365  std::is_nothrow_move_assignable<pointer>::value and
8366  std::is_nothrow_move_constructible<internal_iterator>::value and
8367  std::is_nothrow_move_assignable<internal_iterator>::value
8368  )
8369  {
8370  std::swap(m_object, other.m_object);
8371  std::swap(m_it, other.m_it);
8372  return *this;
8373  }
8374 
8375  private:
8380  void set_begin() noexcept
8381  {
8382  assert(m_object != nullptr);
8383 
8384  switch (m_object->m_type)
8385  {
8387  {
8388  m_it.object_iterator = m_object->m_value.object->begin();
8389  break;
8390  }
8391 
8393  {
8394  m_it.array_iterator = m_object->m_value.array->begin();
8395  break;
8396  }
8397 
8399  {
8400  // set to end so begin()==end() is true: null is empty
8401  m_it.primitive_iterator.set_end();
8402  break;
8403  }
8404 
8405  default:
8406  {
8407  m_it.primitive_iterator.set_begin();
8408  break;
8409  }
8410  }
8411  }
8412 
8417  void set_end() noexcept
8418  {
8419  assert(m_object != nullptr);
8420 
8421  switch (m_object->m_type)
8422  {
8424  {
8425  m_it.object_iterator = m_object->m_value.object->end();
8426  break;
8427  }
8428 
8430  {
8431  m_it.array_iterator = m_object->m_value.array->end();
8432  break;
8433  }
8434 
8435  default:
8436  {
8437  m_it.primitive_iterator.set_end();
8438  break;
8439  }
8440  }
8441  }
8442 
8443  public:
8449  {
8450  assert(m_object != nullptr);
8451 
8452  switch (m_object->m_type)
8453  {
8455  {
8456  assert(m_it.object_iterator != m_object->m_value.object->end());
8457  return m_it.object_iterator->second;
8458  }
8459 
8461  {
8462  assert(m_it.array_iterator != m_object->m_value.array->end());
8463  return *m_it.array_iterator;
8464  }
8465 
8467  {
8468  throw std::out_of_range("cannot get value");
8469  }
8470 
8471  default:
8472  {
8473  if (m_it.primitive_iterator.is_begin())
8474  {
8475  return *m_object;
8476  }
8477 
8478  throw std::out_of_range("cannot get value");
8479  }
8480  }
8481  }
8482 
8488  {
8489  assert(m_object != nullptr);
8490 
8491  switch (m_object->m_type)
8492  {
8494  {
8495  assert(m_it.object_iterator != m_object->m_value.object->end());
8496  return &(m_it.object_iterator->second);
8497  }
8498 
8500  {
8501  assert(m_it.array_iterator != m_object->m_value.array->end());
8502  return &*m_it.array_iterator;
8503  }
8504 
8505  default:
8506  {
8507  if (m_it.primitive_iterator.is_begin())
8508  {
8509  return m_object;
8510  }
8511 
8512  throw std::out_of_range("cannot get value");
8513  }
8514  }
8515  }
8516 
8522  {
8523  auto result = *this;
8524  ++(*this);
8525  return result;
8526  }
8527 
8533  {
8534  assert(m_object != nullptr);
8535 
8536  switch (m_object->m_type)
8537  {
8539  {
8540  std::advance(m_it.object_iterator, 1);
8541  break;
8542  }
8543 
8545  {
8546  std::advance(m_it.array_iterator, 1);
8547  break;
8548  }
8549 
8550  default:
8551  {
8552  ++m_it.primitive_iterator;
8553  break;
8554  }
8555  }
8556 
8557  return *this;
8558  }
8559 
8565  {
8566  auto result = *this;
8567  --(*this);
8568  return result;
8569  }
8570 
8576  {
8577  assert(m_object != nullptr);
8578 
8579  switch (m_object->m_type)
8580  {
8582  {
8583  std::advance(m_it.object_iterator, -1);
8584  break;
8585  }
8586 
8588  {
8589  std::advance(m_it.array_iterator, -1);
8590  break;
8591  }
8592 
8593  default:
8594  {
8595  --m_it.primitive_iterator;
8596  break;
8597  }
8598  }
8599 
8600  return *this;
8601  }
8602 
8607  bool operator==(const iter_impl& other) const
8608  {
8609  // if objects are not the same, the comparison is undefined
8610  if (m_object != other.m_object)
8611  {
8612  throw std::domain_error("cannot compare iterators of different containers");
8613  }
8614 
8615  assert(m_object != nullptr);
8616 
8617  switch (m_object->m_type)
8618  {
8620  {
8621  return (m_it.object_iterator == other.m_it.object_iterator);
8622  }
8623 
8625  {
8626  return (m_it.array_iterator == other.m_it.array_iterator);
8627  }
8628 
8629  default:
8630  {
8631  return (m_it.primitive_iterator == other.m_it.primitive_iterator);
8632  }
8633  }
8634  }
8635 
8640  bool operator!=(const iter_impl& other) const
8641  {
8642  return not operator==(other);
8643  }
8644 
8649  bool operator<(const iter_impl& other) const
8650  {
8651  // if objects are not the same, the comparison is undefined
8652  if (m_object != other.m_object)
8653  {
8654  throw std::domain_error("cannot compare iterators of different containers");
8655  }
8656 
8657  assert(m_object != nullptr);
8658 
8659  switch (m_object->m_type)
8660  {
8662  {
8663  throw std::domain_error("cannot compare order of object iterators");
8664  }
8665 
8667  {
8668  return (m_it.array_iterator < other.m_it.array_iterator);
8669  }
8670 
8671  default:
8672  {
8673  return (m_it.primitive_iterator < other.m_it.primitive_iterator);
8674  }
8675  }
8676  }
8677 
8682  bool operator<=(const iter_impl& other) const
8683  {
8684  return not other.operator < (*this);
8685  }
8686 
8691  bool operator>(const iter_impl& other) const
8692  {
8693  return not operator<=(other);
8694  }
8695 
8700  bool operator>=(const iter_impl& other) const
8701  {
8702  return not operator<(other);
8703  }
8704 
8710  {
8711  assert(m_object != nullptr);
8712 
8713  switch (m_object->m_type)
8714  {
8716  {
8717  throw std::domain_error("cannot use offsets with object iterators");
8718  }
8719 
8721  {
8722  std::advance(m_it.array_iterator, i);
8723  break;
8724  }
8725 
8726  default:
8727  {
8728  m_it.primitive_iterator += i;
8729  break;
8730  }
8731  }
8732 
8733  return *this;
8734  }
8735 
8741  {
8742  return operator+=(-i);
8743  }
8744 
8750  {
8751  auto result = *this;
8752  result += i;
8753  return result;
8754  }
8755 
8761  {
8762  auto result = *this;
8763  result -= i;
8764  return result;
8765  }
8766 
8772  {
8773  assert(m_object != nullptr);
8774 
8775  switch (m_object->m_type)
8776  {
8778  {
8779  throw std::domain_error("cannot use offsets with object iterators");
8780  }
8781 
8783  {
8784  return m_it.array_iterator - other.m_it.array_iterator;
8785  }
8786 
8787  default:
8788  {
8789  return m_it.primitive_iterator - other.m_it.primitive_iterator;
8790  }
8791  }
8792  }
8793 
8799  {
8800  assert(m_object != nullptr);
8801 
8802  switch (m_object->m_type)
8803  {
8805  {
8806  throw std::domain_error("cannot use operator[] for object iterators");
8807  }
8808 
8810  {
8811  return *std::next(m_it.array_iterator, n);
8812  }
8813 
8815  {
8816  throw std::out_of_range("cannot get value");
8817  }
8818 
8819  default:
8820  {
8821  if (m_it.primitive_iterator == -n)
8822  {
8823  return *m_object;
8824  }
8825 
8826  throw std::out_of_range("cannot get value");
8827  }
8828  }
8829  }
8830 
8835  typename object_t::key_type key() const
8836  {
8837  assert(m_object != nullptr);
8838 
8839  if (m_object->is_object())
8840  {
8841  return m_it.object_iterator->first;
8842  }
8843 
8844  throw std::domain_error("cannot use key() for non-object iterators");
8845  }
8846 
8852  {
8853  return operator*();
8854  }
8855 
8856  private:
8858  pointer m_object = nullptr;
8860  internal_iterator m_it = internal_iterator();
8861  };
8862 
8880  template<typename Base>
8881  class json_reverse_iterator : public std::reverse_iterator<Base>
8882  {
8883  public:
8885  using base_iterator = std::reverse_iterator<Base>;
8887  using reference = typename Base::reference;
8888 
8890  json_reverse_iterator(const typename base_iterator::iterator_type& it) noexcept
8891  : base_iterator(it)
8892  {}
8893 
8896  : base_iterator(it)
8897  {}
8898 
8901  {
8902  return base_iterator::operator++(1);
8903  }
8904 
8907  {
8908  base_iterator::operator++();
8909  return *this;
8910  }
8911 
8914  {
8915  return base_iterator::operator--(1);
8916  }
8917 
8920  {
8921  base_iterator::operator--();
8922  return *this;
8923  }
8924 
8927  {
8928  base_iterator::operator+=(i);
8929  return *this;
8930  }
8931 
8934  {
8935  auto result = *this;
8936  result += i;
8937  return result;
8938  }
8939 
8942  {
8943  auto result = *this;
8944  result -= i;
8945  return result;
8946  }
8947 
8950  {
8951  return this->base() - other.base();
8952  }
8953 
8956  {
8957  return *(this->operator+(n));
8958  }
8959 
8961  typename object_t::key_type key() const
8962  {
8963  auto it = --this->base();
8964  return it.key();
8965  }
8966 
8969  {
8970  auto it = --this->base();
8971  return it.operator * ();
8972  }
8973  };
8974 
8975 
8976  private:
8978  // lexer and parser //
8980 
8988  class lexer
8989  {
8990  public:
8992  enum class token_type
8993  {
8994  uninitialized,
8995  literal_true,
8996  literal_false,
8997  literal_null,
8998  value_string,
8999  value_number,
9000  begin_array,
9001  begin_object,
9002  end_array,
9003  end_object,
9004  name_separator,
9005  value_separator,
9006  parse_error,
9007  end_of_input
9008  };
9009 
9011  using lexer_char_t = unsigned char;
9012 
9014  lexer(const lexer_char_t* buff, const size_t len) noexcept
9015  : m_content(buff)
9016  {
9017  assert(m_content != nullptr);
9018  m_start = m_cursor = m_content;
9019  m_limit = m_content + len;
9020  }
9021 
9023  explicit lexer(std::istream& s)
9024  : m_stream(&s), m_line_buffer()
9025  {
9026  // immediately abort if stream is erroneous
9027  if (s.fail())
9028  {
9029  throw std::invalid_argument("stream error");
9030  }
9031 
9032  // fill buffer
9033  fill_line_buffer();
9034 
9035  // skip UTF-8 byte-order mark
9036  if (m_line_buffer.size() >= 3 and m_line_buffer.substr(0, 3) == "\xEF\xBB\xBF")
9037  {
9038  m_line_buffer[0] = ' ';
9039  m_line_buffer[1] = ' ';
9040  m_line_buffer[2] = ' ';
9041  }
9042  }
9043 
9044  // switch off unwanted functions (due to pointer members)
9045  lexer() = delete;
9046  lexer(const lexer&) = delete;
9047  lexer operator=(const lexer&) = delete;
9048 
9072  static string_t to_unicode(const std::size_t codepoint1,
9073  const std::size_t codepoint2 = 0)
9074  {
9075  // calculate the code point from the given code points
9076  std::size_t codepoint = codepoint1;
9077 
9078  // check if codepoint1 is a high surrogate
9079  if (codepoint1 >= 0xD800 and codepoint1 <= 0xDBFF)
9080  {
9081  // check if codepoint2 is a low surrogate
9082  if (codepoint2 >= 0xDC00 and codepoint2 <= 0xDFFF)
9083  {
9084  codepoint =
9085  // high surrogate occupies the most significant 22 bits
9086  (codepoint1 << 10)
9087  // low surrogate occupies the least significant 15 bits
9088  + codepoint2
9089  // there is still the 0xD800, 0xDC00 and 0x10000 noise
9090  // in the result so we have to subtract with:
9091  // (0xD800 << 10) + DC00 - 0x10000 = 0x35FDC00
9092  - 0x35FDC00;
9093  }
9094  else
9095  {
9096  throw std::invalid_argument("missing or wrong low surrogate");
9097  }
9098  }
9099 
9100  string_t result;
9101 
9102  if (codepoint < 0x80)
9103  {
9104  // 1-byte characters: 0xxxxxxx (ASCII)
9105  result.append(1, static_cast<typename string_t::value_type>(codepoint));
9106  }
9107  else if (codepoint <= 0x7ff)
9108  {
9109  // 2-byte characters: 110xxxxx 10xxxxxx
9110  result.append(1, static_cast<typename string_t::value_type>(0xC0 | ((codepoint >> 6) & 0x1F)));
9111  result.append(1, static_cast<typename string_t::value_type>(0x80 | (codepoint & 0x3F)));
9112  }
9113  else if (codepoint <= 0xffff)
9114  {
9115  // 3-byte characters: 1110xxxx 10xxxxxx 10xxxxxx
9116  result.append(1, static_cast<typename string_t::value_type>(0xE0 | ((codepoint >> 12) & 0x0F)));
9117  result.append(1, static_cast<typename string_t::value_type>(0x80 | ((codepoint >> 6) & 0x3F)));
9118  result.append(1, static_cast<typename string_t::value_type>(0x80 | (codepoint & 0x3F)));
9119  }
9120  else if (codepoint <= 0x10ffff)
9121  {
9122  // 4-byte characters: 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
9123  result.append(1, static_cast<typename string_t::value_type>(0xF0 | ((codepoint >> 18) & 0x07)));
9124  result.append(1, static_cast<typename string_t::value_type>(0x80 | ((codepoint >> 12) & 0x3F)));
9125  result.append(1, static_cast<typename string_t::value_type>(0x80 | ((codepoint >> 6) & 0x3F)));
9126  result.append(1, static_cast<typename string_t::value_type>(0x80 | (codepoint & 0x3F)));
9127  }
9128  else
9129  {
9130  throw std::out_of_range("code points above 0x10FFFF are invalid");
9131  }
9132 
9133  return result;
9134  }
9135 
9137  static std::string token_type_name(const token_type t)
9138  {
9139  switch (t)
9140  {
9141  case token_type::uninitialized:
9142  return "<uninitialized>";
9143  case token_type::literal_true:
9144  return "true literal";
9145  case token_type::literal_false:
9146  return "false literal";
9147  case token_type::literal_null:
9148  return "null literal";
9149  case token_type::value_string:
9150  return "string literal";
9151  case token_type::value_number:
9152  return "number literal";
9153  case token_type::begin_array:
9154  return "'['";
9155  case token_type::begin_object:
9156  return "'{'";
9157  case token_type::end_array:
9158  return "']'";
9159  case token_type::end_object:
9160  return "'}'";
9161  case token_type::name_separator:
9162  return "':'";
9163  case token_type::value_separator:
9164  return "','";
9165  case token_type::parse_error:
9166  return "<parse error>";
9167  case token_type::end_of_input:
9168  return "end of input";
9169  default:
9170  {
9171  // catch non-enum values
9172  return "unknown token"; // LCOV_EXCL_LINE
9173  }
9174  }
9175  }
9176 
9198  token_type scan()
9199  {
9200  while (true)
9201  {
9202  // pointer for backtracking information
9203  m_marker = nullptr;
9204 
9205  // remember the begin of the token
9206  m_start = m_cursor;
9207  assert(m_start != nullptr);
9208 
9209 
9210  {
9211  lexer_char_t yych;
9212  unsigned int yyaccept = 0;
9213  static const unsigned char yybm[] =
9214  {
9215  0, 0, 0, 0, 0, 0, 0, 0,
9216  0, 32, 32, 0, 0, 32, 0, 0,
9217  0, 0, 0, 0, 0, 0, 0, 0,
9218  0, 0, 0, 0, 0, 0, 0, 0,
9219  160, 128, 0, 128, 128, 128, 128, 128,
9220  128, 128, 128, 128, 128, 128, 128, 128,
9221  192, 192, 192, 192, 192, 192, 192, 192,
9222  192, 192, 128, 128, 128, 128, 128, 128,
9223  128, 128, 128, 128, 128, 128, 128, 128,
9224  128, 128, 128, 128, 128, 128, 128, 128,
9225  128, 128, 128, 128, 128, 128, 128, 128,
9226  128, 128, 128, 128, 0, 128, 128, 128,
9227  128, 128, 128, 128, 128, 128, 128, 128,
9228  128, 128, 128, 128, 128, 128, 128, 128,
9229  128, 128, 128, 128, 128, 128, 128, 128,
9230  128, 128, 128, 128, 128, 128, 128, 128,
9231  0, 0, 0, 0, 0, 0, 0, 0,
9232  0, 0, 0, 0, 0, 0, 0, 0,
9233  0, 0, 0, 0, 0, 0, 0, 0,
9234  0, 0, 0, 0, 0, 0, 0, 0,
9235  0, 0, 0, 0, 0, 0, 0, 0,
9236  0, 0, 0, 0, 0, 0, 0, 0,
9237  0, 0, 0, 0, 0, 0, 0, 0,
9238  0, 0, 0, 0, 0, 0, 0, 0,
9239  0, 0, 0, 0, 0, 0, 0, 0,
9240  0, 0, 0, 0, 0, 0, 0, 0,
9241  0, 0, 0, 0, 0, 0, 0, 0,
9242  0, 0, 0, 0, 0, 0, 0, 0,
9243  0, 0, 0, 0, 0, 0, 0, 0,
9244  0, 0, 0, 0, 0, 0, 0, 0,
9245  0, 0, 0, 0, 0, 0, 0, 0,
9246  0, 0, 0, 0, 0, 0, 0, 0,
9247  };
9248  if ((m_limit - m_cursor) < 5)
9249  {
9250  fill_line_buffer(5); // LCOV_EXCL_LINE
9251  }
9252  yych = *m_cursor;
9253  if (yybm[0 + yych] & 32)
9254  {
9255  goto basic_json_parser_6;
9256  }
9257  if (yych <= '[')
9258  {
9259  if (yych <= '-')
9260  {
9261  if (yych <= '"')
9262  {
9263  if (yych <= 0x00)
9264  {
9265  goto basic_json_parser_2;
9266  }
9267  if (yych <= '!')
9268  {
9269  goto basic_json_parser_4;
9270  }
9271  goto basic_json_parser_9;
9272  }
9273  else
9274  {
9275  if (yych <= '+')
9276  {
9277  goto basic_json_parser_4;
9278  }
9279  if (yych <= ',')
9280  {
9281  goto basic_json_parser_10;
9282  }
9283  goto basic_json_parser_12;
9284  }
9285  }
9286  else
9287  {
9288  if (yych <= '9')
9289  {
9290  if (yych <= '/')
9291  {
9292  goto basic_json_parser_4;
9293  }
9294  if (yych <= '0')
9295  {
9296  goto basic_json_parser_13;
9297  }
9298  goto basic_json_parser_15;
9299  }
9300  else
9301  {
9302  if (yych <= ':')
9303  {
9304  goto basic_json_parser_17;
9305  }
9306  if (yych <= 'Z')
9307  {
9308  goto basic_json_parser_4;
9309  }
9310  goto basic_json_parser_19;
9311  }
9312  }
9313  }
9314  else
9315  {
9316  if (yych <= 'n')
9317  {
9318  if (yych <= 'e')
9319  {
9320  if (yych == ']')
9321  {
9322  goto basic_json_parser_21;
9323  }
9324  goto basic_json_parser_4;
9325  }
9326  else
9327  {
9328  if (yych <= 'f')
9329  {
9330  goto basic_json_parser_23;
9331  }
9332  if (yych <= 'm')
9333  {
9334  goto basic_json_parser_4;
9335  }
9336  goto basic_json_parser_24;
9337  }
9338  }
9339  else
9340  {
9341  if (yych <= 'z')
9342  {
9343  if (yych == 't')
9344  {
9345  goto basic_json_parser_25;
9346  }
9347  goto basic_json_parser_4;
9348  }
9349  else
9350  {
9351  if (yych <= '{')
9352  {
9353  goto basic_json_parser_26;
9354  }
9355  if (yych == '}')
9356  {
9357  goto basic_json_parser_28;
9358  }
9359  goto basic_json_parser_4;
9360  }
9361  }
9362  }
9363 basic_json_parser_2:
9364  ++m_cursor;
9365  {
9366  last_token_type = token_type::end_of_input;
9367  break;
9368  }
9369 basic_json_parser_4:
9370  ++m_cursor;
9371 basic_json_parser_5:
9372  {
9373  last_token_type = token_type::parse_error;
9374  break;
9375  }
9376 basic_json_parser_6:
9377  ++m_cursor;
9378  if (m_limit <= m_cursor)
9379  {
9380  fill_line_buffer(1); // LCOV_EXCL_LINE
9381  }
9382  yych = *m_cursor;
9383  if (yybm[0 + yych] & 32)
9384  {
9385  goto basic_json_parser_6;
9386  }
9387  {
9388  continue;
9389  }
9390 basic_json_parser_9:
9391  yyaccept = 0;
9392  yych = *(m_marker = ++m_cursor);
9393  if (yych <= 0x1F)
9394  {
9395  goto basic_json_parser_5;
9396  }
9397  if (yych <= 0x7F)
9398  {
9399  goto basic_json_parser_31;
9400  }
9401  if (yych <= 0xC1)
9402  {
9403  goto basic_json_parser_5;
9404  }
9405  if (yych <= 0xF4)
9406  {
9407  goto basic_json_parser_31;
9408  }
9409  goto basic_json_parser_5;
9410 basic_json_parser_10:
9411  ++m_cursor;
9412  {
9413  last_token_type = token_type::value_separator;
9414  break;
9415  }
9416 basic_json_parser_12:
9417  yych = *++m_cursor;
9418  if (yych <= '/')
9419  {
9420  goto basic_json_parser_5;
9421  }
9422  if (yych <= '0')
9423  {
9424  goto basic_json_parser_13;
9425  }
9426  if (yych <= '9')
9427  {
9428  goto basic_json_parser_15;
9429  }
9430  goto basic_json_parser_5;
9431 basic_json_parser_13:
9432  yyaccept = 1;
9433  yych = *(m_marker = ++m_cursor);
9434  if (yych <= 'D')
9435  {
9436  if (yych == '.')
9437  {
9438  goto basic_json_parser_43;
9439  }
9440  }
9441  else
9442  {
9443  if (yych <= 'E')
9444  {
9445  goto basic_json_parser_44;
9446  }
9447  if (yych == 'e')
9448  {
9449  goto basic_json_parser_44;
9450  }
9451  }
9452 basic_json_parser_14:
9453  {
9454  last_token_type = token_type::value_number;
9455  break;
9456  }
9457 basic_json_parser_15:
9458  yyaccept = 1;
9459  m_marker = ++m_cursor;
9460  if ((m_limit - m_cursor) < 3)
9461  {
9462  fill_line_buffer(3); // LCOV_EXCL_LINE
9463  }
9464  yych = *m_cursor;
9465  if (yybm[0 + yych] & 64)
9466  {
9467  goto basic_json_parser_15;
9468  }
9469  if (yych <= 'D')
9470  {
9471  if (yych == '.')
9472  {
9473  goto basic_json_parser_43;
9474  }
9475  goto basic_json_parser_14;
9476  }
9477  else
9478  {
9479  if (yych <= 'E')
9480  {
9481  goto basic_json_parser_44;
9482  }
9483  if (yych == 'e')
9484  {
9485  goto basic_json_parser_44;
9486  }
9487  goto basic_json_parser_14;
9488  }
9489 basic_json_parser_17:
9490  ++m_cursor;
9491  {
9492  last_token_type = token_type::name_separator;
9493  break;
9494  }
9495 basic_json_parser_19:
9496  ++m_cursor;
9497  {
9498  last_token_type = token_type::begin_array;
9499  break;
9500  }
9501 basic_json_parser_21:
9502  ++m_cursor;
9503  {
9504  last_token_type = token_type::end_array;
9505  break;
9506  }
9507 basic_json_parser_23:
9508  yyaccept = 0;
9509  yych = *(m_marker = ++m_cursor);
9510  if (yych == 'a')
9511  {
9512  goto basic_json_parser_45;
9513  }
9514  goto basic_json_parser_5;
9515 basic_json_parser_24:
9516  yyaccept = 0;
9517  yych = *(m_marker = ++m_cursor);
9518  if (yych == 'u')
9519  {
9520  goto basic_json_parser_46;
9521  }
9522  goto basic_json_parser_5;
9523 basic_json_parser_25:
9524  yyaccept = 0;
9525  yych = *(m_marker = ++m_cursor);
9526  if (yych == 'r')
9527  {
9528  goto basic_json_parser_47;
9529  }
9530  goto basic_json_parser_5;
9531 basic_json_parser_26:
9532  ++m_cursor;
9533  {
9534  last_token_type = token_type::begin_object;
9535  break;
9536  }
9537 basic_json_parser_28:
9538  ++m_cursor;
9539  {
9540  last_token_type = token_type::end_object;
9541  break;
9542  }
9543 basic_json_parser_30:
9544  ++m_cursor;
9545  if (m_limit <= m_cursor)
9546  {
9547  fill_line_buffer(1); // LCOV_EXCL_LINE
9548  }
9549  yych = *m_cursor;
9550 basic_json_parser_31:
9551  if (yybm[0 + yych] & 128)
9552  {
9553  goto basic_json_parser_30;
9554  }
9555  if (yych <= 0xE0)
9556  {
9557  if (yych <= '\\')
9558  {
9559  if (yych <= 0x1F)
9560  {
9561  goto basic_json_parser_32;
9562  }
9563  if (yych <= '"')
9564  {
9565  goto basic_json_parser_33;
9566  }
9567  goto basic_json_parser_35;
9568  }
9569  else
9570  {
9571  if (yych <= 0xC1)
9572  {
9573  goto basic_json_parser_32;
9574  }
9575  if (yych <= 0xDF)
9576  {
9577  goto basic_json_parser_36;
9578  }
9579  goto basic_json_parser_37;
9580  }
9581  }
9582  else
9583  {
9584  if (yych <= 0xEF)
9585  {
9586  if (yych == 0xED)
9587  {
9588  goto basic_json_parser_39;
9589  }
9590  goto basic_json_parser_38;
9591  }
9592  else
9593  {
9594  if (yych <= 0xF0)
9595  {
9596  goto basic_json_parser_40;
9597  }
9598  if (yych <= 0xF3)
9599  {
9600  goto basic_json_parser_41;
9601  }
9602  if (yych <= 0xF4)
9603  {
9604  goto basic_json_parser_42;
9605  }
9606  }
9607  }
9608 basic_json_parser_32:
9609  m_cursor = m_marker;
9610  if (yyaccept == 0)
9611  {
9612  goto basic_json_parser_5;
9613  }
9614  else
9615  {
9616  goto basic_json_parser_14;
9617  }
9618 basic_json_parser_33:
9619  ++m_cursor;
9620  {
9621  last_token_type = token_type::value_string;
9622  break;
9623  }
9624 basic_json_parser_35:
9625  ++m_cursor;
9626  if (m_limit <= m_cursor)
9627  {
9628  fill_line_buffer(1); // LCOV_EXCL_LINE
9629  }
9630  yych = *m_cursor;
9631  if (yych <= 'e')
9632  {
9633  if (yych <= '/')
9634  {
9635  if (yych == '"')
9636  {
9637  goto basic_json_parser_30;
9638  }
9639  if (yych <= '.')
9640  {
9641  goto basic_json_parser_32;
9642  }
9643  goto basic_json_parser_30;
9644  }
9645  else
9646  {
9647  if (yych <= '\\')
9648  {
9649  if (yych <= '[')
9650  {
9651  goto basic_json_parser_32;
9652  }
9653  goto basic_json_parser_30;
9654  }
9655  else
9656  {
9657  if (yych == 'b')
9658  {
9659  goto basic_json_parser_30;
9660  }
9661  goto basic_json_parser_32;
9662  }
9663  }
9664  }
9665  else
9666  {
9667  if (yych <= 'q')
9668  {
9669  if (yych <= 'f')
9670  {
9671  goto basic_json_parser_30;
9672  }
9673  if (yych == 'n')
9674  {
9675  goto basic_json_parser_30;
9676  }
9677  goto basic_json_parser_32;
9678  }
9679  else
9680  {
9681  if (yych <= 's')
9682  {
9683  if (yych <= 'r')
9684  {
9685  goto basic_json_parser_30;
9686  }
9687  goto basic_json_parser_32;
9688  }
9689  else
9690  {
9691  if (yych <= 't')
9692  {
9693  goto basic_json_parser_30;
9694  }
9695  if (yych <= 'u')
9696  {
9697  goto basic_json_parser_48;
9698  }
9699  goto basic_json_parser_32;
9700  }
9701  }
9702  }
9703 basic_json_parser_36:
9704  ++m_cursor;
9705  if (m_limit <= m_cursor)
9706  {
9707  fill_line_buffer(1); // LCOV_EXCL_LINE
9708  }
9709  yych = *m_cursor;
9710  if (yych <= 0x7F)
9711  {
9712  goto basic_json_parser_32;
9713  }
9714  if (yych <= 0xBF)
9715  {
9716  goto basic_json_parser_30;
9717  }
9718  goto basic_json_parser_32;
9719 basic_json_parser_37:
9720  ++m_cursor;
9721  if (m_limit <= m_cursor)
9722  {
9723  fill_line_buffer(1); // LCOV_EXCL_LINE
9724  }
9725  yych = *m_cursor;
9726  if (yych <= 0x9F)
9727  {
9728  goto basic_json_parser_32;
9729  }
9730  if (yych <= 0xBF)
9731  {
9732  goto basic_json_parser_36;
9733  }
9734  goto basic_json_parser_32;
9735 basic_json_parser_38:
9736  ++m_cursor;
9737  if (m_limit <= m_cursor)
9738  {
9739  fill_line_buffer(1); // LCOV_EXCL_LINE
9740  }
9741  yych = *m_cursor;
9742  if (yych <= 0x7F)
9743  {
9744  goto basic_json_parser_32;
9745  }
9746  if (yych <= 0xBF)
9747  {
9748  goto basic_json_parser_36;
9749  }
9750  goto basic_json_parser_32;
9751 basic_json_parser_39:
9752  ++m_cursor;
9753  if (m_limit <= m_cursor)
9754  {
9755  fill_line_buffer(1); // LCOV_EXCL_LINE
9756  }
9757  yych = *m_cursor;
9758  if (yych <= 0x7F)
9759  {
9760  goto basic_json_parser_32;
9761  }
9762  if (yych <= 0x9F)
9763  {
9764  goto basic_json_parser_36;
9765  }
9766  goto basic_json_parser_32;
9767 basic_json_parser_40:
9768  ++m_cursor;
9769  if (m_limit <= m_cursor)
9770  {
9771  fill_line_buffer(1); // LCOV_EXCL_LINE
9772  }
9773  yych = *m_cursor;
9774  if (yych <= 0x8F)
9775  {
9776  goto basic_json_parser_32;
9777  }
9778  if (yych <= 0xBF)
9779  {
9780  goto basic_json_parser_38;
9781  }
9782  goto basic_json_parser_32;
9783 basic_json_parser_41:
9784  ++m_cursor;
9785  if (m_limit <= m_cursor)
9786  {
9787  fill_line_buffer(1); // LCOV_EXCL_LINE
9788  }
9789  yych = *m_cursor;
9790  if (yych <= 0x7F)
9791  {
9792  goto basic_json_parser_32;
9793  }
9794  if (yych <= 0xBF)
9795  {
9796  goto basic_json_parser_38;
9797  }
9798  goto basic_json_parser_32;
9799 basic_json_parser_42:
9800  ++m_cursor;
9801  if (m_limit <= m_cursor)
9802  {
9803  fill_line_buffer(1); // LCOV_EXCL_LINE
9804  }
9805  yych = *m_cursor;
9806  if (yych <= 0x7F)
9807  {
9808  goto basic_json_parser_32;
9809  }
9810  if (yych <= 0x8F)
9811  {
9812  goto basic_json_parser_38;
9813  }
9814  goto basic_json_parser_32;
9815 basic_json_parser_43:
9816  yych = *++m_cursor;
9817  if (yych <= '/')
9818  {
9819  goto basic_json_parser_32;
9820  }
9821  if (yych <= '9')
9822  {
9823  goto basic_json_parser_49;
9824  }
9825  goto basic_json_parser_32;
9826 basic_json_parser_44:
9827  yych = *++m_cursor;
9828  if (yych <= ',')
9829  {
9830  if (yych == '+')
9831  {
9832  goto basic_json_parser_51;
9833  }
9834  goto basic_json_parser_32;
9835  }
9836  else
9837  {
9838  if (yych <= '-')
9839  {
9840  goto basic_json_parser_51;
9841  }
9842  if (yych <= '/')
9843  {
9844  goto basic_json_parser_32;
9845  }
9846  if (yych <= '9')
9847  {
9848  goto basic_json_parser_52;
9849  }
9850  goto basic_json_parser_32;
9851  }
9852 basic_json_parser_45:
9853  yych = *++m_cursor;
9854  if (yych == 'l')
9855  {
9856  goto basic_json_parser_54;
9857  }
9858  goto basic_json_parser_32;
9859 basic_json_parser_46:
9860  yych = *++m_cursor;
9861  if (yych == 'l')
9862  {
9863  goto basic_json_parser_55;
9864  }
9865  goto basic_json_parser_32;
9866 basic_json_parser_47:
9867  yych = *++m_cursor;
9868  if (yych == 'u')
9869  {
9870  goto basic_json_parser_56;
9871  }
9872  goto basic_json_parser_32;
9873 basic_json_parser_48:
9874  ++m_cursor;
9875  if (m_limit <= m_cursor)
9876  {
9877  fill_line_buffer(1); // LCOV_EXCL_LINE
9878  }
9879  yych = *m_cursor;
9880  if (yych <= '@')
9881  {
9882  if (yych <= '/')
9883  {
9884  goto basic_json_parser_32;
9885  }
9886  if (yych <= '9')
9887  {
9888  goto basic_json_parser_57;
9889  }
9890  goto basic_json_parser_32;
9891  }
9892  else
9893  {
9894  if (yych <= 'F')
9895  {
9896  goto basic_json_parser_57;
9897  }
9898  if (yych <= '`')
9899  {
9900  goto basic_json_parser_32;
9901  }
9902  if (yych <= 'f')
9903  {
9904  goto basic_json_parser_57;
9905  }
9906  goto basic_json_parser_32;
9907  }
9908 basic_json_parser_49:
9909  yyaccept = 1;
9910  m_marker = ++m_cursor;
9911  if ((m_limit - m_cursor) < 3)
9912  {
9913  fill_line_buffer(3); // LCOV_EXCL_LINE
9914  }
9915  yych = *m_cursor;
9916  if (yych <= 'D')
9917  {
9918  if (yych <= '/')
9919  {
9920  goto basic_json_parser_14;
9921  }
9922  if (yych <= '9')
9923  {
9924  goto basic_json_parser_49;
9925  }
9926  goto basic_json_parser_14;
9927  }
9928  else
9929  {
9930  if (yych <= 'E')
9931  {
9932  goto basic_json_parser_44;
9933  }
9934  if (yych == 'e')
9935  {
9936  goto basic_json_parser_44;
9937  }
9938  goto basic_json_parser_14;
9939  }
9940 basic_json_parser_51:
9941  yych = *++m_cursor;
9942  if (yych <= '/')
9943  {
9944  goto basic_json_parser_32;
9945  }
9946  if (yych >= ':')
9947  {
9948  goto basic_json_parser_32;
9949  }
9950 basic_json_parser_52:
9951  ++m_cursor;
9952  if (m_limit <= m_cursor)
9953  {
9954  fill_line_buffer(1); // LCOV_EXCL_LINE
9955  }
9956  yych = *m_cursor;
9957  if (yych <= '/')
9958  {
9959  goto basic_json_parser_14;
9960  }
9961  if (yych <= '9')
9962  {
9963  goto basic_json_parser_52;
9964  }
9965  goto basic_json_parser_14;
9966 basic_json_parser_54:
9967  yych = *++m_cursor;
9968  if (yych == 's')
9969  {
9970  goto basic_json_parser_58;
9971  }
9972  goto basic_json_parser_32;
9973 basic_json_parser_55:
9974  yych = *++m_cursor;
9975  if (yych == 'l')
9976  {
9977  goto basic_json_parser_59;
9978  }
9979  goto basic_json_parser_32;
9980 basic_json_parser_56:
9981  yych = *++m_cursor;
9982  if (yych == 'e')
9983  {
9984  goto basic_json_parser_61;
9985  }
9986  goto basic_json_parser_32;
9987 basic_json_parser_57:
9988  ++m_cursor;
9989  if (m_limit <= m_cursor)
9990  {
9991  fill_line_buffer(1); // LCOV_EXCL_LINE
9992  }
9993  yych = *m_cursor;
9994  if (yych <= '@')
9995  {
9996  if (yych <= '/')
9997  {
9998  goto basic_json_parser_32;
9999  }
10000  if (yych <= '9')
10001  {
10002  goto basic_json_parser_63;
10003  }
10004  goto basic_json_parser_32;
10005  }
10006  else
10007  {
10008  if (yych <= 'F')
10009  {
10010  goto basic_json_parser_63;
10011  }
10012  if (yych <= '`')
10013  {
10014  goto basic_json_parser_32;
10015  }
10016  if (yych <= 'f')
10017  {
10018  goto basic_json_parser_63;
10019  }
10020  goto basic_json_parser_32;
10021  }
10022 basic_json_parser_58:
10023  yych = *++m_cursor;
10024  if (yych == 'e')
10025  {
10026  goto basic_json_parser_64;
10027  }
10028  goto basic_json_parser_32;
10029 basic_json_parser_59:
10030  ++m_cursor;
10031  {
10032  last_token_type = token_type::literal_null;
10033  break;
10034  }
10035 basic_json_parser_61:
10036  ++m_cursor;
10037  {
10038  last_token_type = token_type::literal_true;
10039  break;
10040  }
10041 basic_json_parser_63:
10042  ++m_cursor;
10043  if (m_limit <= m_cursor)
10044  {
10045  fill_line_buffer(1); // LCOV_EXCL_LINE
10046  }
10047  yych = *m_cursor;
10048  if (yych <= '@')
10049  {
10050  if (yych <= '/')
10051  {
10052  goto basic_json_parser_32;
10053  }
10054  if (yych <= '9')
10055  {
10056  goto basic_json_parser_66;
10057  }
10058  goto basic_json_parser_32;
10059  }
10060  else
10061  {
10062  if (yych <= 'F')
10063  {
10064  goto basic_json_parser_66;
10065  }
10066  if (yych <= '`')
10067  {
10068  goto basic_json_parser_32;
10069  }
10070  if (yych <= 'f')
10071  {
10072  goto basic_json_parser_66;
10073  }
10074  goto basic_json_parser_32;
10075  }
10076 basic_json_parser_64:
10077  ++m_cursor;
10078  {
10079  last_token_type = token_type::literal_false;
10080  break;
10081  }
10082 basic_json_parser_66:
10083  ++m_cursor;
10084  if (m_limit <= m_cursor)
10085  {
10086  fill_line_buffer(1); // LCOV_EXCL_LINE
10087  }
10088  yych = *m_cursor;
10089  if (yych <= '@')
10090  {
10091  if (yych <= '/')
10092  {
10093  goto basic_json_parser_32;
10094  }
10095  if (yych <= '9')
10096  {
10097  goto basic_json_parser_30;
10098  }
10099  goto basic_json_parser_32;
10100  }
10101  else
10102  {
10103  if (yych <= 'F')
10104  {
10105  goto basic_json_parser_30;
10106  }
10107  if (yych <= '`')
10108  {
10109  goto basic_json_parser_32;
10110  }
10111  if (yych <= 'f')
10112  {
10113  goto basic_json_parser_30;
10114  }
10115  goto basic_json_parser_32;
10116  }
10117  }
10118 
10119  }
10120 
10121  return last_token_type;
10122  }
10123 
10152  void fill_line_buffer(size_t n = 0)
10153  {
10154  // if line buffer is used, m_content points to its data
10155  assert(m_line_buffer.empty()
10156  or m_content == reinterpret_cast<const lexer_char_t*>(m_line_buffer.data()));
10157 
10158  // if line buffer is used, m_limit is set past the end of its data
10159  assert(m_line_buffer.empty()
10160  or m_limit == m_content + m_line_buffer.size());
10161 
10162  // pointer relationships
10163  assert(m_content <= m_start);
10164  assert(m_start <= m_cursor);
10165  assert(m_cursor <= m_limit);
10166  assert(m_marker == nullptr or m_marker <= m_limit);
10167 
10168  // number of processed characters (p)
10169  const auto num_processed_chars = static_cast<size_t>(m_start - m_content);
10170  // offset for m_marker wrt. to m_start
10171  const auto offset_marker = (m_marker == nullptr) ? 0 : m_marker - m_start;
10172  // number of unprocessed characters (u)
10173  const auto offset_cursor = m_cursor - m_start;
10174 
10175  // no stream is used or end of file is reached
10176  if (m_stream == nullptr or m_stream->eof())
10177  {
10178  // m_start may or may not be pointing into m_line_buffer at
10179  // this point. We trust the standand library to do the right
10180  // thing. See http://stackoverflow.com/q/28142011/266378
10181  m_line_buffer.assign(m_start, m_limit);
10182 
10183  // append n characters to make sure that there is sufficient
10184  // space between m_cursor and m_limit
10185  m_line_buffer.append(1, '\x00');
10186  if (n > 0)
10187  {
10188  m_line_buffer.append(n - 1, '\x01');
10189  }
10190  }
10191  else
10192  {
10193  // delete processed characters from line buffer
10194  m_line_buffer.erase(0, num_processed_chars);
10195  // read next line from input stream
10196  m_line_buffer_tmp.clear();
10197  std::getline(*m_stream, m_line_buffer_tmp, '\n');
10198 
10199  // add line with newline symbol to the line buffer
10200  m_line_buffer += m_line_buffer_tmp;
10201  m_line_buffer.push_back('\n');
10202  }
10203 
10204  // set pointers
10205  m_content = reinterpret_cast<const lexer_char_t*>(m_line_buffer.data());
10206  assert(m_content != nullptr);
10207  m_start = m_content;
10208  m_marker = m_start + offset_marker;
10209  m_cursor = m_start + offset_cursor;
10210  m_limit = m_start + m_line_buffer.size();
10211  }
10212 
10214  string_t get_token_string() const
10215  {
10216  assert(m_start != nullptr);
10217  return string_t(reinterpret_cast<typename string_t::const_pointer>(m_start),
10218  static_cast<size_t>(m_cursor - m_start));
10219  }
10220 
10278  string_t get_string() const
10279  {
10280  assert(m_cursor - m_start >= 2);
10281 
10282  string_t result;
10283  result.reserve(static_cast<size_t>(m_cursor - m_start - 2));
10284 
10285  // iterate the result between the quotes
10286  for (const lexer_char_t* i = m_start + 1; i < m_cursor - 1; ++i)
10287  {
10288  // find next escape character
10289  auto e = std::find(i, m_cursor - 1, '\\');
10290  if (e != i)
10291  {
10292  // see https://github.com/nlohmann/json/issues/365#issuecomment-262874705
10293  for (auto k = i; k < e; k++)
10294  {
10295  result.push_back(static_cast<typename string_t::value_type>(*k));
10296  }
10297  i = e - 1; // -1 because of ++i
10298  }
10299  else
10300  {
10301  // processing escaped character
10302  // read next character
10303  ++i;
10304 
10305  switch (*i)
10306  {
10307  // the default escapes
10308  case 't':
10309  {
10310  result += "\t";
10311  break;
10312  }
10313  case 'b':
10314  {
10315  result += "\b";
10316  break;
10317  }
10318  case 'f':
10319  {
10320  result += "\f";
10321  break;
10322  }
10323  case 'n':
10324  {
10325  result += "\n";
10326  break;
10327  }
10328  case 'r':
10329  {
10330  result += "\r";
10331  break;
10332  }
10333  case '\\':
10334  {
10335  result += "\\";
10336  break;
10337  }
10338  case '/':
10339  {
10340  result += "/";
10341  break;
10342  }
10343  case '"':
10344  {
10345  result += "\"";
10346  break;
10347  }
10348 
10349  // unicode
10350  case 'u':
10351  {
10352  // get code xxxx from uxxxx
10353  auto codepoint = std::strtoul(std::string(reinterpret_cast<typename string_t::const_pointer>(i + 1),
10354  4).c_str(), nullptr, 16);
10355 
10356  // check if codepoint is a high surrogate
10357  if (codepoint >= 0xD800 and codepoint <= 0xDBFF)
10358  {
10359  // make sure there is a subsequent unicode
10360  if ((i + 6 >= m_limit) or * (i + 5) != '\\' or * (i + 6) != 'u')
10361  {
10362  throw std::invalid_argument("missing low surrogate");
10363  }
10364 
10365  // get code yyyy from uxxxx\uyyyy
10366  auto codepoint2 = std::strtoul(std::string(reinterpret_cast<typename string_t::const_pointer>
10367  (i + 7), 4).c_str(), nullptr, 16);
10368  result += to_unicode(codepoint, codepoint2);
10369  // skip the next 10 characters (xxxx\uyyyy)
10370  i += 10;
10371  }
10372  else if (codepoint >= 0xDC00 and codepoint <= 0xDFFF)
10373  {
10374  // we found a lone low surrogate
10375  throw std::invalid_argument("missing high surrogate");
10376  }
10377  else
10378  {
10379  // add unicode character(s)
10380  result += to_unicode(codepoint);
10381  // skip the next four characters (xxxx)
10382  i += 4;
10383  }
10384  break;
10385  }
10386  }
10387  }
10388  }
10389 
10390  return result;
10391  }
10392 
10406  long double str_to_float_t(long double* /* type */, char** endptr) const
10407  {
10408  return std::strtold(reinterpret_cast<typename string_t::const_pointer>(m_start), endptr);
10409  }
10410 
10424  double str_to_float_t(double* /* type */, char** endptr) const
10425  {
10426  return std::strtod(reinterpret_cast<typename string_t::const_pointer>(m_start), endptr);
10427  }
10428 
10442  float str_to_float_t(float* /* type */, char** endptr) const
10443  {
10444  return std::strtof(reinterpret_cast<typename string_t::const_pointer>(m_start), endptr);
10445  }
10446 
10468  void get_number(basic_json& result) const
10469  {
10470  assert(m_start != nullptr);
10471 
10472  const lexer::lexer_char_t* curptr = m_start;
10473 
10474  // accumulate the integer conversion result (unsigned for now)
10475  number_unsigned_t value = 0;
10476 
10477  // maximum absolute value of the relevant integer type
10478  number_unsigned_t max;
10479 
10480  // temporarily store the type to avoid unecessary bitfield access
10481  value_t type;
10482 
10483  // look for sign
10484  if (*curptr == '-')
10485  {
10486  type = value_t::number_integer;
10487  max = static_cast<uint64_t>((std::numeric_limits<number_integer_t>::max)()) + 1;
10488  curptr++;
10489  }
10490  else
10491  {
10492  type = value_t::number_unsigned;
10493  max = static_cast<uint64_t>((std::numeric_limits<number_unsigned_t>::max)());
10494  }
10495 
10496  // count the significant figures
10497  for (; curptr < m_cursor; curptr++)
10498  {
10499  // quickly skip tests if a digit
10500  if (*curptr < '0' || *curptr > '9')
10501  {
10502  if (*curptr == '.')
10503  {
10504  // don't count '.' but change to float
10505  type = value_t::number_float;
10506  continue;
10507  }
10508  // assume exponent (if not then will fail parse): change to
10509  // float, stop counting and record exponent details
10510  type = value_t::number_float;
10511  break;
10512  }
10513 
10514  // skip if definitely not an integer
10515  if (type != value_t::number_float)
10516  {
10517  auto digit = static_cast<number_unsigned_t>(*curptr - '0');
10518 
10519  // overflow if value * 10 + digit > max, move terms around
10520  // to avoid overflow in intermediate values
10521  if (value > (max - digit) / 10)
10522  {
10523  // overflow
10524  type = value_t::number_float;
10525  }
10526  else
10527  {
10528  // no overflow
10529  value = value * 10 + digit;
10530  }
10531  }
10532  }
10533 
10534  // save the value (if not a float)
10535  if (type == value_t::number_unsigned)
10536  {
10537  result.m_value.number_unsigned = value;
10538  }
10539  else if (type == value_t::number_integer)
10540  {
10541  // invariant: if we parsed a '-', the absolute value is between
10542  // 0 (we allow -0) and max == -INT64_MIN
10543  assert(value >= 0);
10544  assert(value <= max);
10545 
10546  if (value == max)
10547  {
10548  // we cannot simply negate value (== max == -INT64_MIN),
10549  // see https://github.com/nlohmann/json/issues/389
10550  result.m_value.number_integer = static_cast<number_integer_t>(INT64_MIN);
10551  }
10552  else
10553  {
10554  // all other values can be negated safely
10555  result.m_value.number_integer = -static_cast<number_integer_t>(value);
10556  }
10557  }
10558  else
10559  {
10560  // parse with strtod
10561  result.m_value.number_float = str_to_float_t(static_cast<number_float_t*>(nullptr), nullptr);
10562 
10563  // replace infinity and NAN by null
10564  if (not std::isfinite(result.m_value.number_float))
10565  {
10566  type = value_t::null;
10567  result.m_value = basic_json::json_value();
10568  }
10569  }
10570 
10571  // save the type
10572  result.m_type = type;
10573  }
10574 
10575  private:
10577  std::istream* m_stream = nullptr;
10579  string_t m_line_buffer {};
10581  string_t m_line_buffer_tmp {};
10583  const lexer_char_t* m_content = nullptr;
10585  const lexer_char_t* m_start = nullptr;
10587  const lexer_char_t* m_marker = nullptr;
10589  const lexer_char_t* m_cursor = nullptr;
10591  const lexer_char_t* m_limit = nullptr;
10593  token_type last_token_type = token_type::end_of_input;
10594  };
10595 
10601  class parser
10602  {
10603  public:
10605  parser(const char* buff, const parser_callback_t cb = nullptr)
10606  : callback(cb),
10607  m_lexer(reinterpret_cast<const typename lexer::lexer_char_t*>(buff), std::strlen(buff))
10608  {}
10609 
10611  parser(std::istream& is, const parser_callback_t cb = nullptr)
10612  : callback(cb), m_lexer(is)
10613  {}
10614 
10616  template<class IteratorType, typename std::enable_if<
10617  std::is_same<typename std::iterator_traits<IteratorType>::iterator_category, std::random_access_iterator_tag>::value
10618  , int>::type
10619  = 0>
10620  parser(IteratorType first, IteratorType last, const parser_callback_t cb = nullptr)
10621  : callback(cb),
10622  m_lexer(reinterpret_cast<const typename lexer::lexer_char_t*>(&(*first)),
10623  static_cast<size_t>(std::distance(first, last)))
10624  {}
10625 
10627  basic_json parse()
10628  {
10629  // read first token
10630  get_token();
10631 
10632  basic_json result = parse_internal(true);
10633  result.assert_invariant();
10634 
10635  expect(lexer::token_type::end_of_input);
10636 
10637  // return parser result and replace it with null in case the
10638  // top-level value was discarded by the callback function
10639  return result.is_discarded() ? basic_json() : std::move(result);
10640  }
10641 
10642  private:
10644  basic_json parse_internal(bool keep)
10645  {
10646  auto result = basic_json(value_t::discarded);
10647 
10648  switch (last_token)
10649  {
10650  case lexer::token_type::begin_object:
10651  {
10652  if (keep and (not callback
10653  or ((keep = callback(depth++, parse_event_t::object_start, result)) != 0)))
10654  {
10655  // explicitly set result to object to cope with {}
10656  result.m_type = value_t::object;
10657  result.m_value = value_t::object;
10658  }
10659 
10660  // read next token
10661  get_token();
10662 
10663  // closing } -> we are done
10664  if (last_token == lexer::token_type::end_object)
10665  {
10666  get_token();
10667  if (keep and callback and not callback(--depth, parse_event_t::object_end, result))
10668  {
10669  result = basic_json(value_t::discarded);
10670  }
10671  return result;
10672  }
10673 
10674  // no comma is expected here
10675  unexpect(lexer::token_type::value_separator);
10676 
10677  // otherwise: parse key-value pairs
10678  do
10679  {
10680  // ugly, but could be fixed with loop reorganization
10681  if (last_token == lexer::token_type::value_separator)
10682  {
10683  get_token();
10684  }
10685 
10686  // store key
10687  expect(lexer::token_type::value_string);
10688  const auto key = m_lexer.get_string();
10689 
10690  bool keep_tag = false;
10691  if (keep)
10692  {
10693  if (callback)
10694  {
10695  basic_json k(key);
10696  keep_tag = callback(depth, parse_event_t::key, k);
10697  }
10698  else
10699  {
10700  keep_tag = true;
10701  }
10702  }
10703 
10704  // parse separator (:)
10705  get_token();
10706  expect(lexer::token_type::name_separator);
10707 
10708  // parse and add value
10709  get_token();
10710  auto value = parse_internal(keep);
10711  if (keep and keep_tag and not value.is_discarded())
10712  {
10713  result[key] = std::move(value);
10714  }
10715  }
10716  while (last_token == lexer::token_type::value_separator);
10717 
10718  // closing }
10719  expect(lexer::token_type::end_object);
10720  get_token();
10721  if (keep and callback and not callback(--depth, parse_event_t::object_end, result))
10722  {
10723  result = basic_json(value_t::discarded);
10724  }
10725 
10726  return result;
10727  }
10728 
10729  case lexer::token_type::begin_array:
10730  {
10731  if (keep and (not callback
10732  or ((keep = callback(depth++, parse_event_t::array_start, result)) != 0)))
10733  {
10734  // explicitly set result to object to cope with []
10735  result.m_type = value_t::array;
10736  result.m_value = value_t::array;
10737  }
10738 
10739  // read next token
10740  get_token();
10741 
10742  // closing ] -> we are done
10743  if (last_token == lexer::token_type::end_array)
10744  {
10745  get_token();
10746  if (callback and not callback(--depth, parse_event_t::array_end, result))
10747  {
10748  result = basic_json(value_t::discarded);
10749  }
10750  return result;
10751  }
10752 
10753  // no comma is expected here
10754  unexpect(lexer::token_type::value_separator);
10755 
10756  // otherwise: parse values
10757  do
10758  {
10759  // ugly, but could be fixed with loop reorganization
10760  if (last_token == lexer::token_type::value_separator)
10761  {
10762  get_token();
10763  }
10764 
10765  // parse value
10766  auto value = parse_internal(keep);
10767  if (keep and not value.is_discarded())
10768  {
10769  result.push_back(std::move(value));
10770  }
10771  }
10772  while (last_token == lexer::token_type::value_separator);
10773 
10774  // closing ]
10775  expect(lexer::token_type::end_array);
10776  get_token();
10777  if (keep and callback and not callback(--depth, parse_event_t::array_end, result))
10778  {
10779  result = basic_json(value_t::discarded);
10780  }
10781 
10782  return result;
10783  }
10784 
10785  case lexer::token_type::literal_null:
10786  {
10787  get_token();
10788  result.m_type = value_t::null;
10789  break;
10790  }
10791 
10792  case lexer::token_type::value_string:
10793  {
10794  const auto s = m_lexer.get_string();
10795  get_token();
10796  result = basic_json(s);
10797  break;
10798  }
10799 
10800  case lexer::token_type::literal_true:
10801  {
10802  get_token();
10803  result.m_type = value_t::boolean;
10804  result.m_value = true;
10805  break;
10806  }
10807 
10808  case lexer::token_type::literal_false:
10809  {
10810  get_token();
10811  result.m_type = value_t::boolean;
10812  result.m_value = false;
10813  break;
10814  }
10815 
10816  case lexer::token_type::value_number:
10817  {
10818  m_lexer.get_number(result);
10819  get_token();
10820  break;
10821  }
10822 
10823  default:
10824  {
10825  // the last token was unexpected
10826  unexpect(last_token);
10827  }
10828  }
10829 
10830  if (keep and callback and not callback(depth, parse_event_t::value, result))
10831  {
10832  result = basic_json(value_t::discarded);
10833  }
10834  return result;
10835  }
10836 
10838  typename lexer::token_type get_token()
10839  {
10840  last_token = m_lexer.scan();
10841  return last_token;
10842  }
10843 
10844  void expect(typename lexer::token_type t) const
10845  {
10846  if (t != last_token)
10847  {
10848  std::string error_msg = "parse error - unexpected ";
10849  error_msg += (last_token == lexer::token_type::parse_error ? ("'" + m_lexer.get_token_string() +
10850  "'") :
10851  lexer::token_type_name(last_token));
10852  error_msg += "; expected " + lexer::token_type_name(t);
10853  throw std::invalid_argument(error_msg);
10854  }
10855  }
10856 
10857  void unexpect(typename lexer::token_type t) const
10858  {
10859  if (t == last_token)
10860  {
10861  std::string error_msg = "parse error - unexpected ";
10862  error_msg += (last_token == lexer::token_type::parse_error ? ("'" + m_lexer.get_token_string() +
10863  "'") :
10864  lexer::token_type_name(last_token));
10865  throw std::invalid_argument(error_msg);
10866  }
10867  }
10868 
10869  private:
10871  int depth = 0;
10873  const parser_callback_t callback = nullptr;
10875  typename lexer::token_type last_token = lexer::token_type::uninitialized;
10877  lexer m_lexer;
10878  };
10879 
10880  public:
10893  {
10895  friend class basic_json;
10896 
10897  public:
10920  explicit json_pointer(const std::string& s = "")
10921  : reference_tokens(split(s))
10922  {}
10923 
10939  std::string to_string() const noexcept
10940  {
10941  return std::accumulate(reference_tokens.begin(),
10942  reference_tokens.end(), std::string{},
10943  [](const std::string & a, const std::string & b)
10944  {
10945  return a + "/" + escape(b);
10946  });
10947  }
10948 
10950  operator std::string() const
10951  {
10952  return to_string();
10953  }
10955  private:
10957  std::string pop_back()
10958  {
10959  if (is_root())
10960  {
10961  throw std::domain_error("JSON pointer has no parent");
10962  }
10963 
10964  auto last = reference_tokens.back();
10965  reference_tokens.pop_back();
10966  return last;
10967  }
10968 
10970  bool is_root() const
10971  {
10972  return reference_tokens.empty();
10973  }
10974 
10975  json_pointer top() const
10976  {
10977  if (is_root())
10978  {
10979  throw std::domain_error("JSON pointer has no parent");
10980  }
10981 
10982  json_pointer result = *this;
10983  result.reference_tokens = {reference_tokens[0]};
10984  return result;
10985  }
10986 
10992  reference get_and_create(reference j) const
10993  {
10994  pointer result = &j;
10995 
10996  // in case no reference tokens exist, return a reference to the
10997  // JSON value j which will be overwritten by a primitive value
10998  for (const auto& reference_token : reference_tokens)
10999  {
11000  switch (result->m_type)
11001  {
11002  case value_t::null:
11003  {
11004  if (reference_token == "0")
11005  {
11006  // start a new array if reference token is 0
11007  result = &result->operator[](0);
11008  }
11009  else
11010  {
11011  // start a new object otherwise
11012  result = &result->operator[](reference_token);
11013  }
11014  break;
11015  }
11016 
11017  case value_t::object:
11018  {
11019  // create an entry in the object
11020  result = &result->operator[](reference_token);
11021  break;
11022  }
11023 
11024  case value_t::array:
11025  {
11026  // create an entry in the array
11027  result = &result->operator[](static_cast<size_type>(std::stoi(reference_token)));
11028  break;
11029  }
11030 
11031  /*
11032  The following code is only reached if there exists a
11033  reference token _and_ the current value is primitive. In
11034  this case, we have an error situation, because primitive
11035  values may only occur as single value; that is, with an
11036  empty list of reference tokens.
11037  */
11038  default:
11039  {
11040  throw std::domain_error("invalid value to unflatten");
11041  }
11042  }
11043  }
11044 
11045  return *result;
11046  }
11047 
11067  reference get_unchecked(pointer ptr) const
11068  {
11069  for (const auto& reference_token : reference_tokens)
11070  {
11071  // convert null values to arrays or objects before continuing
11072  if (ptr->m_type == value_t::null)
11073  {
11074  // check if reference token is a number
11075  const bool nums = std::all_of(reference_token.begin(),
11076  reference_token.end(),
11077  [](const char x)
11078  {
11079  return std::isdigit(x);
11080  });
11081 
11082  // change value to array for numbers or "-" or to object
11083  // otherwise
11084  if (nums or reference_token == "-")
11085  {
11086  *ptr = value_t::array;
11087  }
11088  else
11089  {
11090  *ptr = value_t::object;
11091  }
11092  }
11093 
11094  switch (ptr->m_type)
11095  {
11096  case value_t::object:
11097  {
11098  // use unchecked object access
11099  ptr = &ptr->operator[](reference_token);
11100  break;
11101  }
11102 
11103  case value_t::array:
11104  {
11105  // error condition (cf. RFC 6901, Sect. 4)
11106  if (reference_token.size() > 1 and reference_token[0] == '0')
11107  {
11108  throw std::domain_error("array index must not begin with '0'");
11109  }
11110 
11111  if (reference_token == "-")
11112  {
11113  // explicityly treat "-" as index beyond the end
11114  ptr = &ptr->operator[](ptr->m_value.array->size());
11115  }
11116  else
11117  {
11118  // convert array index to number; unchecked access
11119  ptr = &ptr->operator[](static_cast<size_type>(std::stoi(reference_token)));
11120  }
11121  break;
11122  }
11123 
11124  default:
11125  {
11126  throw std::out_of_range("unresolved reference token '" + reference_token + "'");
11127  }
11128  }
11129  }
11130 
11131  return *ptr;
11132  }
11133 
11134  reference get_checked(pointer ptr) const
11135  {
11136  for (const auto& reference_token : reference_tokens)
11137  {
11138  switch (ptr->m_type)
11139  {
11140  case value_t::object:
11141  {
11142  // note: at performs range check
11143  ptr = &ptr->at(reference_token);
11144  break;
11145  }
11146 
11147  case value_t::array:
11148  {
11149  if (reference_token == "-")
11150  {
11151  // "-" always fails the range check
11152  throw std::out_of_range("array index '-' (" +
11153  std::to_string(ptr->m_value.array->size()) +
11154  ") is out of range");
11155  }
11156 
11157  // error condition (cf. RFC 6901, Sect. 4)
11158  if (reference_token.size() > 1 and reference_token[0] == '0')
11159  {
11160  throw std::domain_error("array index must not begin with '0'");
11161  }
11162 
11163  // note: at performs range check
11164  ptr = &ptr->at(static_cast<size_type>(std::stoi(reference_token)));
11165  break;
11166  }
11167 
11168  default:
11169  {
11170  throw std::out_of_range("unresolved reference token '" + reference_token + "'");
11171  }
11172  }
11173  }
11174 
11175  return *ptr;
11176  }
11177 
11186  const_reference get_unchecked(const_pointer ptr) const
11187  {
11188  for (const auto& reference_token : reference_tokens)
11189  {
11190  switch (ptr->m_type)
11191  {
11192  case value_t::object:
11193  {
11194  // use unchecked object access
11195  ptr = &ptr->operator[](reference_token);
11196  break;
11197  }
11198 
11199  case value_t::array:
11200  {
11201  if (reference_token == "-")
11202  {
11203  // "-" cannot be used for const access
11204  throw std::out_of_range("array index '-' (" +
11205  std::to_string(ptr->m_value.array->size()) +
11206  ") is out of range");
11207  }
11208 
11209  // error condition (cf. RFC 6901, Sect. 4)
11210  if (reference_token.size() > 1 and reference_token[0] == '0')
11211  {
11212  throw std::domain_error("array index must not begin with '0'");
11213  }
11214 
11215  // use unchecked array access
11216  ptr = &ptr->operator[](static_cast<size_type>(std::stoi(reference_token)));
11217  break;
11218  }
11219 
11220  default:
11221  {
11222  throw std::out_of_range("unresolved reference token '" + reference_token + "'");
11223  }
11224  }
11225  }
11226 
11227  return *ptr;
11228  }
11229 
11230  const_reference get_checked(const_pointer ptr) const
11231  {
11232  for (const auto& reference_token : reference_tokens)
11233  {
11234  switch (ptr->m_type)
11235  {
11236  case value_t::object:
11237  {
11238  // note: at performs range check
11239  ptr = &ptr->at(reference_token);
11240  break;
11241  }
11242 
11243  case value_t::array:
11244  {
11245  if (reference_token == "-")
11246  {
11247  // "-" always fails the range check
11248  throw std::out_of_range("array index '-' (" +
11249  std::to_string(ptr->m_value.array->size()) +
11250  ") is out of range");
11251  }
11252 
11253  // error condition (cf. RFC 6901, Sect. 4)
11254  if (reference_token.size() > 1 and reference_token[0] == '0')
11255  {
11256  throw std::domain_error("array index must not begin with '0'");
11257  }
11258 
11259  // note: at performs range check
11260  ptr = &ptr->at(static_cast<size_type>(std::stoi(reference_token)));
11261  break;
11262  }
11263 
11264  default:
11265  {
11266  throw std::out_of_range("unresolved reference token '" + reference_token + "'");
11267  }
11268  }
11269  }
11270 
11271  return *ptr;
11272  }
11273 
11275  static std::vector<std::string> split(const std::string& reference_string)
11276  {
11277  std::vector<std::string> result;
11278 
11279  // special case: empty reference string -> no reference tokens
11280  if (reference_string.empty())
11281  {
11282  return result;
11283  }
11284 
11285  // check if nonempty reference string begins with slash
11286  if (reference_string[0] != '/')
11287  {
11288  throw std::domain_error("JSON pointer must be empty or begin with '/'");
11289  }
11290 
11291  // extract the reference tokens:
11292  // - slash: position of the last read slash (or end of string)
11293  // - start: position after the previous slash
11294  for (
11295  // search for the first slash after the first character
11296  size_t slash = reference_string.find_first_of('/', 1),
11297  // set the beginning of the first reference token
11298  start = 1;
11299  // we can stop if start == string::npos+1 = 0
11300  start != 0;
11301  // set the beginning of the next reference token
11302  // (will eventually be 0 if slash == std::string::npos)
11303  start = slash + 1,
11304  // find next slash
11305  slash = reference_string.find_first_of('/', start))
11306  {
11307  // use the text between the beginning of the reference token
11308  // (start) and the last slash (slash).
11309  auto reference_token = reference_string.substr(start, slash - start);
11310 
11311  // check reference tokens are properly escaped
11312  for (size_t pos = reference_token.find_first_of('~');
11313  pos != std::string::npos;
11314  pos = reference_token.find_first_of('~', pos + 1))
11315  {
11316  assert(reference_token[pos] == '~');
11317 
11318  // ~ must be followed by 0 or 1
11319  if (pos == reference_token.size() - 1 or
11320  (reference_token[pos + 1] != '0' and
11321  reference_token[pos + 1] != '1'))
11322  {
11323  throw std::domain_error("escape error: '~' must be followed with '0' or '1'");
11324  }
11325  }
11326 
11327  // finally, store the reference token
11328  unescape(reference_token);
11329  result.push_back(reference_token);
11330  }
11331 
11332  return result;
11333  }
11334 
11335  private:
11348  static void replace_substring(std::string& s,
11349  const std::string& f,
11350  const std::string& t)
11351  {
11352  assert(not f.empty());
11353 
11354  for (
11355  size_t pos = s.find(f); // find first occurrence of f
11356  pos != std::string::npos; // make sure f was found
11357  s.replace(pos, f.size(), t), // replace with t
11358  pos = s.find(f, pos + t.size()) // find next occurrence of f
11359  );
11360  }
11361 
11363  static std::string escape(std::string s)
11364  {
11365  // escape "~"" to "~0" and "/" to "~1"
11366  replace_substring(s, "~", "~0");
11367  replace_substring(s, "/", "~1");
11368  return s;
11369  }
11370 
11372  static void unescape(std::string& s)
11373  {
11374  // first transform any occurrence of the sequence '~1' to '/'
11375  replace_substring(s, "~1", "/");
11376  // then transform any occurrence of the sequence '~0' to '~'
11377  replace_substring(s, "~0", "~");
11378  }
11379 
11387  static void flatten(const std::string& reference_string,
11388  const basic_json& value,
11389  basic_json& result)
11390  {
11391  switch (value.m_type)
11392  {
11393  case value_t::array:
11394  {
11395  if (value.m_value.array->empty())
11396  {
11397  // flatten empty array as null
11398  result[reference_string] = nullptr;
11399  }
11400  else
11401  {
11402  // iterate array and use index as reference string
11403  for (size_t i = 0; i < value.m_value.array->size(); ++i)
11404  {
11405  flatten(reference_string + "/" + std::to_string(i),
11406  value.m_value.array->operator[](i), result);
11407  }
11408  }
11409  break;
11410  }
11411 
11412  case value_t::object:
11413  {
11414  if (value.m_value.object->empty())
11415  {
11416  // flatten empty object as null
11417  result[reference_string] = nullptr;
11418  }
11419  else
11420  {
11421  // iterate object and use keys as reference string
11422  for (const auto& element : *value.m_value.object)
11423  {
11424  flatten(reference_string + "/" + escape(element.first),
11425  element.second, result);
11426  }
11427  }
11428  break;
11429  }
11430 
11431  default:
11432  {
11433  // add primitive value with its reference string
11434  result[reference_string] = value;
11435  break;
11436  }
11437  }
11438  }
11439 
11445  static basic_json unflatten(const basic_json& value)
11446  {
11447  if (not value.is_object())
11448  {
11449  throw std::domain_error("only objects can be unflattened");
11450  }
11451 
11452  basic_json result;
11453 
11454  // iterate the JSON object values
11455  for (const auto& element : *value.m_value.object)
11456  {
11457  if (not element.second.is_primitive())
11458  {
11459  throw std::domain_error("values in object must be primitive");
11460  }
11461 
11462  // assign value to reference pointed to by JSON pointer; Note
11463  // that if the JSON pointer is "" (i.e., points to the whole
11464  // value), function get_and_create returns a reference to
11465  // result itself. An assignment will then create a primitive
11466  // value.
11467  json_pointer(element.first).get_and_create(result) = element.second;
11468  }
11469 
11470  return result;
11471  }
11472 
11473  private:
11475  std::vector<std::string> reference_tokens {};
11476  };
11477 
11479  // JSON Pointer support //
11481 
11484 
11518  reference operator[](const json_pointer& ptr)
11519  {
11520  return ptr.get_unchecked(this);
11521  }
11545  const_reference operator[](const json_pointer& ptr) const
11546  {
11547  return ptr.get_unchecked(this);
11548  }
11570  reference at(const json_pointer& ptr)
11571  {
11572  return ptr.get_checked(this);
11573  }
11595  const_reference at(const json_pointer& ptr) const
11596  {
11597  return ptr.get_checked(this);
11598  }
11622  basic_json flatten() const
11623  {
11624  basic_json result(value_t::object);
11625  json_pointer::flatten("", *this, result);
11626  return result;
11627  }
11628 
11656  basic_json unflatten() const
11657  {
11658  return json_pointer::unflatten(*this);
11659  }
11662 
11664  // JSON Patch functions //
11666 
11669 
11706  basic_json patch(const basic_json& json_patch) const
11707  {
11708  // make a working copy to apply the patch to
11709  basic_json result = *this;
11711  // the valid JSON Patch operations
11712  enum class patch_operations {add, remove, replace, move, copy, test, invalid};
11713 
11714  const auto get_op = [](const std::string op)
11715  {
11716  if (op == "add")
11717  {
11718  return patch_operations::add;
11719  }
11720  if (op == "remove")
11721  {
11722  return patch_operations::remove;
11723  }
11724  if (op == "replace")
11725  {
11726  return patch_operations::replace;
11727  }
11728  if (op == "move")
11729  {
11730  return patch_operations::move;
11731  }
11732  if (op == "copy")
11733  {
11734  return patch_operations::copy;
11735  }
11736  if (op == "test")
11737  {
11738  return patch_operations::test;
11739  }
11740 
11741  return patch_operations::invalid;
11742  };
11743 
11744  // wrapper for "add" operation; add value at ptr
11745  const auto operation_add = [&result](json_pointer & ptr, basic_json val)
11746  {
11747  // adding to the root of the target document means replacing it
11748  if (ptr.is_root())
11749  {
11750  result = val;
11751  }
11752  else
11753  {
11754  // make sure the top element of the pointer exists
11755  json_pointer top_pointer = ptr.top();
11756  if (top_pointer != ptr)
11757  {
11758  result.at(top_pointer);
11759  }
11760 
11761  // get reference to parent of JSON pointer ptr
11762  const auto last_path = ptr.pop_back();
11763  basic_json& parent = result[ptr];
11764 
11765  switch (parent.m_type)
11766  {
11767  case value_t::null:
11768  case value_t::object:
11769  {
11770  // use operator[] to add value
11771  parent[last_path] = val;
11772  break;
11773  }
11774 
11775  case value_t::array:
11776  {
11777  if (last_path == "-")
11778  {
11779  // special case: append to back
11780  parent.push_back(val);
11781  }
11782  else
11783  {
11784  const auto idx = std::stoi(last_path);
11785  if (static_cast<size_type>(idx) > parent.size())
11786  {
11787  // avoid undefined behavior
11788  throw std::out_of_range("array index " + std::to_string(idx) + " is out of range");
11789  }
11790  else
11791  {
11792  // default case: insert add offset
11793  parent.insert(parent.begin() + static_cast<difference_type>(idx), val);
11794  }
11795  }
11796  break;
11797  }
11798 
11799  default:
11800  {
11801  // if there exists a parent it cannot be primitive
11802  assert(false); // LCOV_EXCL_LINE
11803  }
11804  }
11805  }
11806  };
11807 
11808  // wrapper for "remove" operation; remove value at ptr
11809  const auto operation_remove = [&result](json_pointer & ptr)
11810  {
11811  // get reference to parent of JSON pointer ptr
11812  const auto last_path = ptr.pop_back();
11813  basic_json& parent = result.at(ptr);
11814 
11815  // remove child
11816  if (parent.is_object())
11817  {
11818  // perform range check
11819  auto it = parent.find(last_path);
11820  if (it != parent.end())
11821  {
11822  parent.erase(it);
11823  }
11824  else
11825  {
11826  throw std::out_of_range("key '" + last_path + "' not found");
11827  }
11828  }
11829  else if (parent.is_array())
11830  {
11831  // note erase performs range check
11832  parent.erase(static_cast<size_type>(std::stoi(last_path)));
11833  }
11834  };
11835 
11836  // type check
11837  if (not json_patch.is_array())
11838  {
11839  // a JSON patch must be an array of objects
11840  throw std::invalid_argument("JSON patch must be an array of objects");
11841  }
11842 
11843  // iterate and apply th eoperations
11844  for (const auto& val : json_patch)
11845  {
11846  // wrapper to get a value for an operation
11847  const auto get_value = [&val](const std::string & op,
11848  const std::string & member,
11849  bool string_type) -> basic_json&
11850  {
11851  // find value
11852  auto it = val.m_value.object->find(member);
11853 
11854  // context-sensitive error message
11855  const auto error_msg = (op == "op") ? "operation" : "operation '" + op + "'";
11856 
11857  // check if desired value is present
11858  if (it == val.m_value.object->end())
11859  {
11860  throw std::invalid_argument(error_msg + " must have member '" + member + "'");
11861  }
11862 
11863  // check if result is of type string
11864  if (string_type and not it->second.is_string())
11865  {
11866  throw std::invalid_argument(error_msg + " must have string member '" + member + "'");
11867  }
11868 
11869  // no error: return value
11870  return it->second;
11871  };
11872 
11873  // type check
11874  if (not val.is_object())
11875  {
11876  throw std::invalid_argument("JSON patch must be an array of objects");
11877  }
11878 
11879  // collect mandatory members
11880  const std::string op = get_value("op", "op", true);
11881  const std::string path = get_value(op, "path", true);
11882  json_pointer ptr(path);
11883 
11884  switch (get_op(op))
11885  {
11886  case patch_operations::add:
11887  {
11888  operation_add(ptr, get_value("add", "value", false));
11889  break;
11890  }
11891 
11892  case patch_operations::remove:
11893  {
11894  operation_remove(ptr);
11895  break;
11896  }
11897 
11898  case patch_operations::replace:
11899  {
11900  // the "path" location must exist - use at()
11901  result.at(ptr) = get_value("replace", "value", false);
11902  break;
11903  }
11904 
11905  case patch_operations::move:
11906  {
11907  const std::string from_path = get_value("move", "from", true);
11908  json_pointer from_ptr(from_path);
11909 
11910  // the "from" location must exist - use at()
11911  basic_json v = result.at(from_ptr);
11912 
11913  // The move operation is functionally identical to a
11914  // "remove" operation on the "from" location, followed
11915  // immediately by an "add" operation at the target
11916  // location with the value that was just removed.
11917  operation_remove(from_ptr);
11918  operation_add(ptr, v);
11919  break;
11920  }
11921 
11922  case patch_operations::copy:
11923  {
11924  const std::string from_path = get_value("copy", "from", true);;
11925  const json_pointer from_ptr(from_path);
11926 
11927  // the "from" location must exist - use at()
11928  result[ptr] = result.at(from_ptr);
11929  break;
11930  }
11931 
11932  case patch_operations::test:
11933  {
11934  bool success = false;
11935  try
11936  {
11937  // check if "value" matches the one at "path"
11938  // the "path" location must exist - use at()
11939  success = (result.at(ptr) == get_value("test", "value", false));
11940  }
11941  catch (std::out_of_range&)
11942  {
11943  // ignore out of range errors: success remains false
11944  }
11945 
11946  // throw an exception if test fails
11947  if (not success)
11948  {
11949  throw std::domain_error("unsuccessful: " + val.dump());
11950  }
11951 
11952  break;
11953  }
11954 
11955  case patch_operations::invalid:
11956  {
11957  // op must be "add", "remove", "replace", "move", "copy", or
11958  // "test"
11959  throw std::invalid_argument("operation value '" + op + "' is invalid");
11960  }
11961  }
11962  }
11963 
11964  return result;
11965  }
11966 
11999  static basic_json diff(const basic_json& source,
12000  const basic_json& target,
12001  const std::string& path = "")
12002  {
12003  // the patch
12004  basic_json result(value_t::array);
12005 
12006  // if the values are the same, return empty patch
12007  if (source == target)
12008  {
12009  return result;
12010  }
12011 
12012  if (source.type() != target.type())
12013  {
12014  // different types: replace value
12015  result.push_back(
12016  {
12017  {"op", "replace"},
12018  {"path", path},
12019  {"value", target}
12020  });
12021  }
12022  else
12023  {
12024  switch (source.type())
12025  {
12026  case value_t::array:
12027  {
12028  // first pass: traverse common elements
12029  size_t i = 0;
12030  while (i < source.size() and i < target.size())
12031  {
12032  // recursive call to compare array values at index i
12033  auto temp_diff = diff(source[i], target[i], path + "/" + std::to_string(i));
12034  result.insert(result.end(), temp_diff.begin(), temp_diff.end());
12035  ++i;
12036  }
12037 
12038  // i now reached the end of at least one array
12039  // in a second pass, traverse the remaining elements
12040 
12041  // remove my remaining elements
12042  const auto end_index = static_cast<difference_type>(result.size());
12043  while (i < source.size())
12044  {
12045  // add operations in reverse order to avoid invalid
12046  // indices
12047  result.insert(result.begin() + end_index, object(
12048  {
12049  {"op", "remove"},
12050  {"path", path + "/" + std::to_string(i)}
12051  }));
12052  ++i;
12053  }
12054 
12055  // add other remaining elements
12056  while (i < target.size())
12057  {
12058  result.push_back(
12059  {
12060  {"op", "add"},
12061  {"path", path + "/" + std::to_string(i)},
12062  {"value", target[i]}
12063  });
12064  ++i;
12065  }
12066 
12067  break;
12068  }
12069 
12070  case value_t::object:
12071  {
12072  // first pass: traverse this object's elements
12073  for (auto it = source.begin(); it != source.end(); ++it)
12074  {
12075  // escape the key name to be used in a JSON patch
12076  const auto key = json_pointer::escape(it.key());
12077 
12078  if (target.find(it.key()) != target.end())
12079  {
12080  // recursive call to compare object values at key it
12081  auto temp_diff = diff(it.value(), target[it.key()], path + "/" + key);
12082  result.insert(result.end(), temp_diff.begin(), temp_diff.end());
12083  }
12084  else
12085  {
12086  // found a key that is not in o -> remove it
12087  result.push_back(object(
12088  {
12089  {"op", "remove"},
12090  {"path", path + "/" + key}
12091  }));
12092  }
12093  }
12094 
12095  // second pass: traverse other object's elements
12096  for (auto it = target.begin(); it != target.end(); ++it)
12097  {
12098  if (source.find(it.key()) == source.end())
12099  {
12100  // found a key that is not in this -> add it
12101  const auto key = json_pointer::escape(it.key());
12102  result.push_back(
12103  {
12104  {"op", "add"},
12105  {"path", path + "/" + key},
12106  {"value", it.value()}
12107  });
12108  }
12109  }
12110 
12111  break;
12112  }
12113 
12114  default:
12115  {
12116  // both primitive type: replace value
12117  result.push_back(
12118  {
12119  {"op", "replace"},
12120  {"path", path},
12121  {"value", target}
12122  });
12123  break;
12124  }
12125  }
12126  }
12127 
12128  return result;
12129  }
12130 
12132 };
12133 
12134 
12136 // presets //
12138 
12147 using json = basic_json<>;
12148 } // namespace nlohmann
12149 
12150 
12152 // nonmember support //
12154 
12155 // specialization of std::swap, and std::hash
12156 namespace std
12157 {
12163 template<>
12164 inline void swap(nlohmann::json& j1,
12165  nlohmann::json& j2) noexcept(
12166  is_nothrow_move_constructible<nlohmann::json>::value and
12167  is_nothrow_move_assignable<nlohmann::json>::value
12168  )
12169 {
12170  j1.swap(j2);
12171 }
12172 
12174 template<>
12175 struct hash<nlohmann::json>
12176 {
12182  std::size_t operator()(const nlohmann::json& j) const
12183  {
12184  // a naive hashing via the string representation
12185  const auto& h = hash<nlohmann::json::string_t>();
12186  return h(j.dump());
12187  }
12188 };
12189 } // namespace std
12190 
12204 inline nlohmann::json operator "" _json(const char* s, std::size_t n)
12205 {
12206  return nlohmann::json::parse(s, s + n);
12207 }
12208 
12222 inline nlohmann::json::json_pointer operator "" _json_pointer(const char* s, std::size_t n)
12223 {
12224  return nlohmann::json::json_pointer(std::string(s, n));
12225 }
12226 
12227 // restore GCC/clang diagnostic settings
12228 #if defined(__clang__) || defined(__GNUC__) || defined(__GNUG__)
12229  #pragma GCC diagnostic pop
12230 #endif
12231 
12232 #endif
size_type max_size() const noexcept
returns the maximum possible number of elements
Definition: json.hpp:4737
friend bool operator<=(const_reference lhs, const_reference rhs) noexcept
comparison: less than or equal
Definition: json.hpp:5803
constexpr value_t type() const noexcept
return the type of the JSON value (explicit)
Definition: json.hpp:2247
constexpr bool is_array() const noexcept
return whether value is an array
Definition: json.hpp:2507
const_reference at(const typename object_t::key_type &key) const
access specified object element with bounds checking
Definition: json.hpp:3276
basic_json(const value_t value_type)
create an empty value with a given type
Definition: json.hpp:1070
bool operator>(const iter_impl &other) const
comparison: greater than
Definition: json.hpp:8691
basic_json(const array_t &val)
create an array (explicit)
Definition: json.hpp:1182
reference value() const
return the value of an iterator
Definition: json.hpp:8968
const_iterator end() const noexcept
returns a const iterator to one past the last element
Definition: json.hpp:4359
constexpr bool is_primitive() const noexcept
return whether type is primitive
Definition: json.hpp:2277
constexpr bool is_null() const noexcept
return whether value is null
Definition: json.hpp:2326
ValueType get() const
get a value (explicit)
Definition: json.hpp:2889
const_reverse_iterator rend() const noexcept
returns a const reverse iterator to one before the first
Definition: json.hpp:4464
constexpr bool is_structured() const noexcept
return whether type is structured
Definition: json.hpp:2304
json_reverse_iterator & operator--()
pre-decrement (–it)
Definition: json.hpp:8919
void clear() noexcept
clears the contents
Definition: json.hpp:4793
const_reference operator[](size_type idx) const
access specified array element
Definition: json.hpp:3368
json_reverse_iterator operator--(int)
post-decrement (it–)
Definition: json.hpp:8913
reference operator[](T *(&key)[n])
access specified object element
Definition: json.hpp:3495
friend std::istream & operator>>(std::istream &i, basic_json &j)
deserialize from stream
Definition: json.hpp:6203
bool operator!=(const iter_impl &other) const
comparison: not equal
Definition: json.hpp:8640
iter_impl operator++(int)
post-increment (it++)
Definition: json.hpp:8521
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:1763
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:4238
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:6091
constexpr bool is_number_unsigned() const noexcept
return whether value is an unsigned integer number
Definition: json.hpp:2435
BooleanType boolean_t
a type for a boolean
Definition: json.hpp:508
reference operator+=(const typename object_t::value_type &val)
add an object to an object
Definition: json.hpp:4976
basic_json(const typename string_t::value_type *val)
create a string (explicit)
Definition: json.hpp:1278
iterator find(typename object_t::key_type key)
find an element in a JSON object
Definition: json.hpp:4189
friend bool operator!=(const_reference lhs, const_reference rhs) noexcept
comparison: not equal
Definition: json.hpp:5647
bool operator<=(const iter_impl &other) const
comparison: less than or equal
Definition: json.hpp:8682
basic_json(const string_t &val)
create a string (explicit)
Definition: json.hpp:1252
void push_back(const basic_json &val)
add an object to an array
Definition: json.hpp:4902
void erase(const size_type idx)
remove element from a JSON array given an index
Definition: json.hpp:4139
ArrayType< basic_json, AllocatorType< basic_json >> array_t
a type for an array
Definition: json.hpp:429
bool operator==(const iter_impl &other) const
comparison: equal
Definition: json.hpp:8607
reference front()
access the first element
Definition: json.hpp:3800
void swap(object_t &other)
exchanges the values
Definition: json.hpp:5411
a class to store JSON values
Definition: json.hpp:222
basic_json(const int val) noexcept
create an integer number from an enum type (explicit)
Definition: json.hpp:1392
static basic_json parse(T(&array)[N], const parser_callback_t cb=nullptr)
deserialize from an array
Definition: json.hpp:5963
constexpr bool is_object() const noexcept
return whether value is an object
Definition: json.hpp:2485
friend bool operator==(std::nullptr_t, const_reference v) noexcept
comparison: equal
Definition: json.hpp:5626
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:3699
NumberIntegerType number_integer_t
a type for a number (integer)
Definition: json.hpp:580
iterator insert(const_iterator pos, size_type cnt, const basic_json &val)
inserts elements
Definition: json.hpp:5201
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:7690
iter_impl(pointer object) noexcept
constructor for a given JSON instance
Definition: json.hpp:8301
constexpr bool is_number_integer() const noexcept
return whether value is an integer number
Definition: json.hpp:2407
ObjectType< StringType, basic_json, std::less< StringType >, AllocatorType< std::pair< const StringType, basic_json >>> object_t
a type for an object
Definition: json.hpp:383
STL namespace.
NumberUnsignedType number_unsigned_t
a type for a number (unsigned)
Definition: json.hpp:651
json_reverse_iterator operator-(difference_type i) const
subtract from iterator
Definition: json.hpp:8941
typename std::allocator_traits< allocator_type >::const_pointer const_pointer
the type of an element const pointer
Definition: json.hpp:264
static basic_json parse(std::istream &&i, const parser_callback_t cb=nullptr)
deserialize from stream
Definition: json.hpp:6040
basic_json(const number_integer_t val) noexcept
create an integer number (explicit)
Definition: json.hpp:1361
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:1723
static iteration_proxy< const_iterator > iterator_wrapper(const_reference cont)
wrapper to access iterator member functions in range-based for
Definition: json.hpp:4551
const_reference front() const
access the first element
Definition: json.hpp:3808
iter_impl(const iter_impl &other) noexcept
copy constructor
Definition: json.hpp:8354
static basic_json parse(const CharT s, const parser_callback_t cb=nullptr)
deserialize from string literal
Definition: json.hpp:6001
reference operator[](difference_type n) const
access to successor
Definition: json.hpp:8798
void emplace_back(Args &&... args)
add an object to an array
Definition: json.hpp:5052
friend class basic_json
allow basic_json to access private members
Definition: json.hpp:8269
json_reverse_iterator(const typename base_iterator::iterator_type &it) noexcept
create reverse iterator from iterator
Definition: json.hpp:8890
PointerType get_ptr() noexcept
get a pointer value (implicit)
Definition: json.hpp:2969
const_iterator cbegin() const noexcept
returns a const iterator to the first element
Definition: json.hpp:4318
reference back()
access the last element
Definition: json.hpp:3843
const value_type & const_reference
the type of an element const reference
Definition: json.hpp:251
IteratorType erase(IteratorType first, IteratorType last)
remove elements given an iterator range
Definition: json.hpp:4016
void push_back(const typename object_t::value_type &val)
add an object to an object
Definition: json.hpp:4952
bool empty() const noexcept
checks whether the container is empty
Definition: json.hpp:4603
void push_back(std::initializer_list< basic_json > init)
add an object to an object
Definition: json.hpp:5007
json_pointer(const std::string &s="")
create JSON pointer
Definition: json.hpp:10920
iterator insert(const_iterator pos, const_iterator first, const_iterator last)
inserts elements
Definition: json.hpp:5251
constexpr const PointerType get_ptr() const noexcept
get a pointer value (implicit)
Definition: json.hpp:2997
constexpr bool is_number_float() const noexcept
return whether value is a floating-point number
Definition: json.hpp:2463
basic_json(InputIT first, InputIT last)
construct a JSON container given an iterator range
Definition: json.hpp:1834
basic_json(std::nullptr_t=nullptr) noexcept
create a null object
Definition: json.hpp:1094
IteratorType erase(IteratorType pos)
remove element given an iterator
Definition: json.hpp:3909
static allocator_type get_allocator()
returns the allocator associated with the container
Definition: json.hpp:281
json_reverse_iterator operator+(difference_type i) const
add to iterator
Definition: json.hpp:8933
string_t dump(const int indent=-1) const
serialization
Definition: json.hpp:2205
reference & operator=(basic_json other) noexcept(std::is_nothrow_move_constructible< value_t >::value and std::is_nothrow_move_assignable< value_t >::value and std::is_nothrow_move_constructible< json_value >::value and std::is_nothrow_move_assignable< json_value >::value)
copy assignment
Definition: json.hpp:2100
void swap(reference other) noexcept(std::is_nothrow_move_constructible< value_t >::value and std::is_nothrow_move_assignable< value_t >::value and std::is_nothrow_move_constructible< json_value >::value and std::is_nothrow_move_assignable< json_value >::value)
exchanges the values
Definition: json.hpp:5346
std::size_t size_type
a type to represent container sizes
Definition: json.hpp:256
JSON_DEPRECATED basic_json(std::istream &i, const parser_callback_t cb=nullptr)
construct a JSON value given an input stream
Definition: json.hpp:1954
basic_json(const CompatibleArrayType &val)
create an array (implicit)
Definition: json.hpp:1222
basic_json(size_type cnt, const basic_json &val)
construct an array with count copies of given value
Definition: json.hpp:1787
std::reverse_iterator< Base > base_iterator
shortcut to the reverse iterator adaptor
Definition: json.hpp:8885
object_t::key_type key() const
return the key of an object iterator
Definition: json.hpp:8961
iter_impl operator-(difference_type i)
subtract from iterator
Definition: json.hpp:8760
iterator insert(const_iterator pos, std::initializer_list< basic_json > ilist)
inserts elements
Definition: json.hpp:5309
typename std::allocator_traits< allocator_type >::pointer pointer
the type of an element pointer
Definition: json.hpp:262
iterator insert(const_iterator pos, const basic_json &val)
inserts element
Definition: json.hpp:5148
friend bool operator>=(const_reference lhs, const_reference rhs) noexcept
comparison: greater than or equal
Definition: json.hpp:5847
friend bool operator<(const_reference lhs, const_reference rhs) noexcept
comparison: less than
Definition: json.hpp:5708
const_reverse_iterator rbegin() const noexcept
returns a const reverse iterator to the last element
Definition: json.hpp:4427
basic_json(basic_json &&other) noexcept
move constructor
Definition: json.hpp:2063
iter_impl & operator-=(difference_type i)
subtract from iterator
Definition: json.hpp:8740
reference at(const typename object_t::key_type &key)
access specified object element with bounds checking
Definition: json.hpp:3229
object (unordered set of name/value pairs)
~basic_json()
destructor
Definition: json.hpp:2133
basic_json value_type
the type of elements in a basic_json container
Definition: json.hpp:246
std::function< bool(int depth, parse_event_t event, basic_json &parsed)> parser_callback_t
per-element parser callback type
Definition: json.hpp:1019
AllocatorType< basic_json > allocator_type
the allocator type
Definition: json.hpp:259
StringType string_t
a type for a string
Definition: json.hpp:482
iter_impl & operator=(iter_impl other) noexcept(std::is_nothrow_move_constructible< pointer >::value and std::is_nothrow_move_assignable< pointer >::value and std::is_nothrow_move_constructible< internal_iterator >::value and std::is_nothrow_move_assignable< internal_iterator >::value)
copy assignment
Definition: json.hpp:8363
typename basic_json::difference_type difference_type
a type to represent differences between iterators
Definition: json.hpp:8280
reference operator+=(const basic_json &val)
add an object to an array
Definition: json.hpp:4926
static basic_json parse(const ContiguousContainer &c, const parser_callback_t cb=nullptr)
deserialize from a container with contiguous storage
Definition: json.hpp:6163
reference operator+=(std::initializer_list< basic_json > init)
add an object to an object
Definition: json.hpp:5024
ReferenceType get_ref() const
get a reference value (implicit)
Definition: json.hpp:3059
friend std::ostream & operator>>(const basic_json &j, std::ostream &o)
serialize to stream
Definition: json.hpp:5920
size_type size() const noexcept
returns the number of elements
Definition: json.hpp:4671
namespace for Niels Lohmann
Definition: json.hpp:98
constexpr bool is_string() const noexcept
return whether value is a string
Definition: json.hpp:2529
void swap(string_t &other)
exchanges the values
Definition: json.hpp:5444
reference operator[](difference_type n) const
access to successor
Definition: json.hpp:8955
basic_json(const CompatibleNumberIntegerType val) noexcept
create an integer number (implicit)
Definition: json.hpp:1429
const_reference at(size_type idx) const
access specified array element with bounds checking
Definition: json.hpp:3182
iter_impl & operator++()
pre-increment (++it)
Definition: json.hpp:8532
ValueType value(const typename object_t::key_type &key, ValueType default_value) const
access specified object element with default value
Definition: json.hpp:3675
const_reference operator[](T *key) const
read-only access specified object element
Definition: json.hpp:3613
NumberFloatType number_float_t
a type for a number (floating-point)
Definition: json.hpp:719
difference_type operator-(const iter_impl &other) const
return difference
Definition: json.hpp:8771
value_t
the JSON type enumeration
Definition: json.hpp:750
reverse_iterator rbegin() noexcept
returns an iterator to the reverse-beginning
Definition: json.hpp:4419
std::ptrdiff_t difference_type
a type to represent differences between iterators
Definition: json.hpp:254
void swap(array_t &other)
exchanges the values
Definition: json.hpp:5378
std::pair< iterator, bool > emplace(Args &&... args)
add an object to an object if key does not exist
Definition: json.hpp:5100
iter_impl & operator--()
pre-decrement (–it)
Definition: json.hpp:8575
typename Base::reference reference
the reference type for the pointed-to element
Definition: json.hpp:8887
void push_back(basic_json &&val)
add an object to an array
Definition: json.hpp:4866
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:7633
array (ordered collection of values)
json_reverse_iterator & operator++()
pre-increment (++it)
Definition: json.hpp:8906
friend bool operator==(const_reference lhs, const_reference rhs) noexcept
comparison: equal
Definition: json.hpp:5524
static basic_json parse(std::istream &i, const parser_callback_t cb=nullptr)
deserialize from stream
Definition: json.hpp:6031
ValueType value(const json_pointer &ptr, ValueType default_value) const
access specified object element via JSON Pointer with default value
Definition: json.hpp:3747
const_reference operator[](const typename object_t::key_type &key) const
read-only access specified object element
Definition: json.hpp:3455
reference value() const
return the value of an iterator
Definition: json.hpp:8851
basic_json(const CompatibleNumberUnsignedType val) noexcept
create an unsigned number (implicit)
Definition: json.hpp:1487
constexpr bool is_boolean() const noexcept
return whether value is a boolean
Definition: json.hpp:2348
typename basic_json::value_type value_type
the type of the values when the iterator is dereferenced
Definition: json.hpp:8278
const_reverse_iterator crbegin() const noexcept
returns a const reverse iterator to the last element
Definition: json.hpp:4493
bool operator<(const iter_impl &other) const
comparison: smaller
Definition: json.hpp:8649
string_t value(const json_pointer &ptr, const char *default_value) const
overload for a default value of type const char*
Definition: json.hpp:3770
pointer operator->() const
dereference the iterator
Definition: json.hpp:8487
friend bool operator<(const value_t lhs, const value_t rhs) noexcept
comparison operator for JSON types
Definition: json.hpp:5477
basic_json(const number_float_t val) noexcept
create a floating-point number (explicit)
Definition: json.hpp:1518
friend bool operator!=(const_reference v, std::nullptr_t) noexcept
comparison: not equal
Definition: json.hpp:5670
basic_json(const CompatibleNumberFloatType val) noexcept
create an floating-point number (implicit)
Definition: json.hpp:1565
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:1640
friend bool operator!=(std::nullptr_t, const_reference v) noexcept
comparison: not equal
Definition: json.hpp:5679
difference_type operator-(const json_reverse_iterator &other) const
return difference
Definition: json.hpp:8949
const_reference back() const
access the last element
Definition: json.hpp:3853
iter_impl operator--(int)
post-decrement (it–)
Definition: json.hpp:8564
constexpr bool is_number() const noexcept
return whether value is a number
Definition: json.hpp:2378
const_iterator find(typename object_t::key_type key) const
find an element in a JSON object
Definition: json.hpp:4205
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:8284
const_iterator begin() const noexcept
returns a const iterator to the first element
Definition: json.hpp:4288
basic_json(boolean_t val) noexcept
create a boolean (explicit)
Definition: json.hpp:1329
iterator end() noexcept
returns an iterator to one past the last element
Definition: json.hpp:4349
reverse_iterator rend() noexcept
returns an iterator to the reverse-end
Definition: json.hpp:4456
bool operator>=(const iter_impl &other) const
comparison: greater than or equal
Definition: json.hpp:8700
iterator begin() noexcept
returns an iterator to the first element
Definition: json.hpp:4278
const_iterator cend() const noexcept
returns a const iterator to one past the last element
Definition: json.hpp:4389
basic_json(const CompatibleObjectType &val)
create an object (implicit)
Definition: json.hpp:1154
friend bool operator>(const_reference lhs, const_reference rhs) noexcept
comparison: greater than
Definition: json.hpp:5825
size_type erase(const typename object_t::key_type &key)
remove element from a JSON object given a key
Definition: json.hpp:4104
reference operator[](const typename object_t::key_type &key)
access specified object element
Definition: json.hpp:3406
reference operator+=(basic_json &&val)
add an object to an array
Definition: json.hpp:4892
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:8288
static std::vector< uint8_t > to_msgpack(const basic_json &j)
create a MessagePack serialization of a given JSON value
Definition: json.hpp:7604
a template for a reverse iterator class
Definition: json.hpp:233
object_t::key_type key() const
return the key of an object iterator
Definition: json.hpp:8835
json_reverse_iterator operator++(int)
post-increment (it++)
Definition: json.hpp:8900
friend bool operator==(const_reference v, std::nullptr_t) noexcept
comparison: equal
Definition: json.hpp:5617
iter_impl operator+(difference_type i)
add to iterator
Definition: json.hpp:8749
reference operator[](size_type idx)
access specified array element
Definition: json.hpp:3322
json_reverse_iterator & operator+=(difference_type i)
add to iterator
Definition: json.hpp:8926
reference at(size_type idx)
access specified array element with bounds checking
Definition: json.hpp:3139
static iteration_proxy< iterator > iterator_wrapper(reference cont)
wrapper to access iterator member functions in range-based for
Definition: json.hpp:4543
constexpr bool is_discarded() const noexcept
return whether value is discarded
Definition: json.hpp:2556
reference operator*() const
return a reference to the value pointed to by the iterator
Definition: json.hpp:8448
iter_impl & operator+=(difference_type i)
add to iterator
Definition: json.hpp:8709
const_reverse_iterator crend() const noexcept
returns a const reverse iterator to one before the first
Definition: json.hpp:4522
std::bidirectional_iterator_tag iterator_category
the category of the iterator
Definition: json.hpp:8290
basic_json(const object_t &val)
create an object (explicit)
Definition: json.hpp:1119
basic_json(const number_unsigned_t val) noexcept
create an unsigned integer number (explicit)
Definition: json.hpp:1456
friend std::istream & operator<<(basic_json &j, std::istream &i)
deserialize from stream
Definition: json.hpp:6193
json_reverse_iterator(const base_iterator &it) noexcept
create reverse iterator from base class
Definition: json.hpp:8895
static std::vector< uint8_t > to_cbor(const basic_json &j)
create a MessagePack serialization of a given JSON value
Definition: json.hpp:7660
const_reference operator[](T *(&key)[n]) const
read-only access specified object element
Definition: json.hpp:3530
friend std::ostream & operator<<(std::ostream &o, const basic_json &j)
serialize to stream
Definition: json.hpp:5888
a template for a random access iterator for the basic_json class
Definition: json.hpp:232
iterator insert(const_iterator pos, basic_json &&val)
inserts element
Definition: json.hpp:5172
ReferenceType get_ref()
get a reference value (implicit)
Definition: json.hpp:3046
basic_json(const CompatibleStringType &val)
create a string (implicit)
Definition: json.hpp:1309
basic_json(const basic_json &other)
copy constructor
Definition: json.hpp:1986
reference operator[](T *key)
access specified object element
Definition: json.hpp:3563
parse_event_t
JSON callback events.
Definition: json.hpp:949