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 }
132 
211 template <
212  template<typename U, typename V, typename... Args> class ObjectType = std::map,
213  template<typename U, typename... Args> class ArrayType = std::vector,
214  class StringType = std::string,
215  class BooleanType = bool,
216  class NumberIntegerType = std::int64_t,
217  class NumberUnsignedType = std::uint64_t,
218  class NumberFloatType = double,
219  template<typename U> class AllocatorType = std::allocator
220  >
222 {
223  private:
225  using basic_json_t = basic_json<ObjectType, ArrayType, StringType,
226  BooleanType, NumberIntegerType, NumberUnsignedType, NumberFloatType,
227  AllocatorType>;
228 
229  public:
230  // forward declarations
231  template<typename U> class iter_impl;
232  template<typename Base> class json_reverse_iterator;
233  class json_pointer;
234 
236  // container types //
238 
243 
246 
250  using const_reference = const value_type&;
251 
253  using difference_type = std::ptrdiff_t;
255  using size_type = std::size_t;
256 
258  using allocator_type = AllocatorType<basic_json>;
259 
261  using pointer = typename std::allocator_traits<allocator_type>::pointer;
263  using const_pointer = typename std::allocator_traits<allocator_type>::const_pointer;
264 
273 
275 
276 
281  {
282  return allocator_type();
283  }
284 
285 
287  // JSON value data types //
289 
294 
378  using object_t = ObjectType<StringType,
379  basic_json,
380  std::less<StringType>,
381  AllocatorType<std::pair<const StringType,
382  basic_json>>>;
383 
428  using array_t = ArrayType<basic_json, AllocatorType<basic_json>>;
429 
475  using string_t = StringType;
476 
501  using boolean_t = BooleanType;
502 
573  using number_integer_t = NumberIntegerType;
574 
644  using number_unsigned_t = NumberUnsignedType;
645 
712  using number_float_t = NumberFloatType;
713 
715 
716 
718  // JSON type enumeration //
720 
743  enum class value_t : uint8_t
744  {
745  null,
746  object,
747  array,
748  string,
749  boolean,
750  number_integer,
751  number_unsigned,
752  number_float,
753  discarded
754  };
755 
756 
757  private:
758 
760  template<typename T, typename... Args>
761  static T* create(Args&& ... args)
762  {
763  AllocatorType<T> alloc;
764  auto deleter = [&](T * object)
765  {
766  alloc.deallocate(object, 1);
767  };
768  std::unique_ptr<T, decltype(deleter)> object(alloc.allocate(1), deleter);
769  alloc.construct(object.get(), std::forward<Args>(args)...);
770  assert(object.get() != nullptr);
771  return object.release();
772  }
773 
775  // JSON value storage //
777 
802  union json_value
803  {
805  object_t* object;
807  array_t* array;
809  string_t* string;
811  boolean_t boolean;
813  number_integer_t number_integer;
815  number_unsigned_t number_unsigned;
817  number_float_t number_float;
818 
820  json_value() = default;
822  json_value(boolean_t v) noexcept : boolean(v) {}
824  json_value(number_integer_t v) noexcept : number_integer(v) {}
826  json_value(number_unsigned_t v) noexcept : number_unsigned(v) {}
828  json_value(number_float_t v) noexcept : number_float(v) {}
830  json_value(value_t t)
831  {
832  switch (t)
833  {
834  case value_t::object:
835  {
836  object = create<object_t>();
837  break;
838  }
839 
840  case value_t::array:
841  {
842  array = create<array_t>();
843  break;
844  }
845 
846  case value_t::string:
847  {
848  string = create<string_t>("");
849  break;
850  }
851 
852  case value_t::boolean:
853  {
854  boolean = boolean_t(false);
855  break;
856  }
857 
858  case value_t::number_integer:
859  {
860  number_integer = number_integer_t(0);
861  break;
862  }
863 
864  case value_t::number_unsigned:
865  {
866  number_unsigned = number_unsigned_t(0);
867  break;
868  }
869 
870  case value_t::number_float:
871  {
872  number_float = number_float_t(0.0);
873  break;
874  }
875 
876  case value_t::null:
877  {
878  break;
879  }
880 
881  default:
882  {
883  if (t == value_t::null)
884  {
885  throw std::domain_error("961c151d2e87f2686a955a9be24d316f1362bf21 2.0.10"); // LCOV_EXCL_LINE
886  }
887  break;
888  }
889  }
890  }
891 
893  json_value(const string_t& value)
894  {
895  string = create<string_t>(value);
896  }
897 
899  json_value(const object_t& value)
900  {
901  object = create<object_t>(value);
902  }
903 
905  json_value(const array_t& value)
906  {
907  array = create<array_t>(value);
908  }
909  };
910 
920  void assert_invariant() const
921  {
922  assert(m_type != value_t::object or m_value.object != nullptr);
923  assert(m_type != value_t::array or m_value.array != nullptr);
924  assert(m_type != value_t::string or m_value.string != nullptr);
925  }
926 
927  public:
929  // JSON parser callback //
931 
942  enum class parse_event_t : uint8_t
943  {
945  object_start,
947  object_end,
949  array_start,
951  array_end,
953  key,
955  value
956  };
957 
1010  using parser_callback_t = std::function<bool(int depth,
1011  parse_event_t event,
1012  basic_json& parsed)>;
1013 
1014 
1016  // constructors //
1018 
1023 
1064  : m_type(value_type), m_value(value_type)
1065  {
1066  assert_invariant();
1067  }
1068 
1087  basic_json(std::nullptr_t = nullptr) noexcept
1088  : basic_json(value_t::null)
1089  {
1090  assert_invariant();
1091  }
1092 
1112  basic_json(const object_t& val)
1113  : m_type(value_t::object), m_value(val)
1114  {
1115  assert_invariant();
1116  }
1117 
1144  template<class CompatibleObjectType, typename std::enable_if<
1145  std::is_constructible<typename object_t::key_type, typename CompatibleObjectType::key_type>::value and
1146  std::is_constructible<basic_json, typename CompatibleObjectType::mapped_type>::value, int>::type = 0>
1147  basic_json(const CompatibleObjectType& val)
1148  : m_type(value_t::object)
1149  {
1150  using std::begin;
1151  using std::end;
1152  m_value.object = create<object_t>(begin(val), end(val));
1153  assert_invariant();
1154  }
1155 
1175  basic_json(const array_t& val)
1176  : m_type(value_t::array), m_value(val)
1177  {
1178  assert_invariant();
1179  }
1180 
1207  template<class CompatibleArrayType, typename std::enable_if<
1208  not std::is_same<CompatibleArrayType, typename basic_json_t::iterator>::value and
1209  not std::is_same<CompatibleArrayType, typename basic_json_t::const_iterator>::value and
1210  not std::is_same<CompatibleArrayType, typename basic_json_t::reverse_iterator>::value and
1211  not std::is_same<CompatibleArrayType, typename basic_json_t::const_reverse_iterator>::value and
1212  not std::is_same<CompatibleArrayType, typename array_t::iterator>::value and
1213  not std::is_same<CompatibleArrayType, typename array_t::const_iterator>::value and
1214  std::is_constructible<basic_json, typename CompatibleArrayType::value_type>::value, int>::type = 0>
1215  basic_json(const CompatibleArrayType& val)
1216  : m_type(value_t::array)
1217  {
1218  using std::begin;
1219  using std::end;
1220  m_value.array = create<array_t>(begin(val), end(val));
1221  assert_invariant();
1222  }
1223 
1245  basic_json(const string_t& val)
1246  : m_type(value_t::string), m_value(val)
1247  {
1248  assert_invariant();
1249  }
1250 
1271  basic_json(const typename string_t::value_type* val)
1272  : basic_json(string_t(val))
1273  {
1274  assert_invariant();
1275  }
1276 
1300  template<class CompatibleStringType, typename std::enable_if<
1301  std::is_constructible<string_t, CompatibleStringType>::value, int>::type = 0>
1302  basic_json(const CompatibleStringType& val)
1303  : basic_json(string_t(val))
1304  {
1305  assert_invariant();
1306  }
1307 
1322  basic_json(boolean_t val) noexcept
1323  : m_type(value_t::boolean), m_value(val)
1324  {
1325  assert_invariant();
1326  }
1327 
1351  template<typename T, typename std::enable_if<
1352  not (std::is_same<T, int>::value) and
1353  std::is_same<T, number_integer_t>::value, int>::type = 0>
1354  basic_json(const number_integer_t val) noexcept
1355  : m_type(value_t::number_integer), m_value(val)
1356  {
1357  assert_invariant();
1358  }
1359 
1385  basic_json(const int val) noexcept
1386  : m_type(value_t::number_integer),
1387  m_value(static_cast<number_integer_t>(val))
1388  {
1389  assert_invariant();
1390  }
1391 
1417  template<typename CompatibleNumberIntegerType, typename std::enable_if<
1418  std::is_constructible<number_integer_t, CompatibleNumberIntegerType>::value and
1419  std::numeric_limits<CompatibleNumberIntegerType>::is_integer and
1420  std::numeric_limits<CompatibleNumberIntegerType>::is_signed,
1421  CompatibleNumberIntegerType>::type = 0>
1422  basic_json(const CompatibleNumberIntegerType val) noexcept
1423  : m_type(value_t::number_integer),
1424  m_value(static_cast<number_integer_t>(val))
1425  {
1426  assert_invariant();
1427  }
1428 
1446  template<typename T, typename std::enable_if<
1447  not (std::is_same<T, int>::value) and
1448  std::is_same<T, number_unsigned_t>::value, int>::type = 0>
1449  basic_json(const number_unsigned_t val) noexcept
1450  : m_type(value_t::number_unsigned), m_value(val)
1451  {
1452  assert_invariant();
1453  }
1454 
1475  template<typename CompatibleNumberUnsignedType, typename std::enable_if <
1476  std::is_constructible<number_unsigned_t, CompatibleNumberUnsignedType>::value and
1477  std::numeric_limits<CompatibleNumberUnsignedType>::is_integer and
1478  not std::numeric_limits<CompatibleNumberUnsignedType>::is_signed,
1479  CompatibleNumberUnsignedType>::type = 0>
1480  basic_json(const CompatibleNumberUnsignedType val) noexcept
1481  : m_type(value_t::number_unsigned),
1482  m_value(static_cast<number_unsigned_t>(val))
1483  {
1484  assert_invariant();
1485  }
1486 
1511  basic_json(const number_float_t val) noexcept
1512  : m_type(value_t::number_float), m_value(val)
1513  {
1514  // replace infinity and NAN by null
1515  if (not std::isfinite(val))
1516  {
1517  m_type = value_t::null;
1518  m_value = json_value();
1519  }
1520 
1521  assert_invariant();
1522  }
1523 
1555  template<typename CompatibleNumberFloatType, typename = typename std::enable_if<
1556  std::is_constructible<number_float_t, CompatibleNumberFloatType>::value and
1557  std::is_floating_point<CompatibleNumberFloatType>::value>::type>
1558  basic_json(const CompatibleNumberFloatType val) noexcept
1559  : basic_json(number_float_t(val))
1560  {
1561  assert_invariant();
1562  }
1563 
1633  basic_json(std::initializer_list<basic_json> init,
1634  bool type_deduction = true,
1635  value_t manual_type = value_t::array)
1636  {
1637  // check if each element is an array with two elements whose first
1638  // element is a string
1639  bool is_an_object = std::all_of(init.begin(), init.end(),
1640  [](const basic_json & element)
1641  {
1642  return element.is_array() and element.size() == 2 and element[0].is_string();
1643  });
1644 
1645  // adjust type if type deduction is not wanted
1646  if (not type_deduction)
1647  {
1648  // if array is wanted, do not create an object though possible
1649  if (manual_type == value_t::array)
1650  {
1651  is_an_object = false;
1652  }
1653 
1654  // if object is wanted but impossible, throw an exception
1655  if (manual_type == value_t::object and not is_an_object)
1656  {
1657  throw std::domain_error("cannot create object from initializer list");
1658  }
1659  }
1660 
1661  if (is_an_object)
1662  {
1663  // the initializer list is a list of pairs -> create object
1664  m_type = value_t::object;
1665  m_value = value_t::object;
1666 
1667  std::for_each(init.begin(), init.end(), [this](const basic_json & element)
1668  {
1669  m_value.object->emplace(*(element[0].m_value.string), element[1]);
1670  });
1671  }
1672  else
1673  {
1674  // the initializer list describes an array -> create array
1675  m_type = value_t::array;
1676  m_value.array = create<array_t>(init);
1677  }
1678 
1679  assert_invariant();
1680  }
1681 
1716  static basic_json array(std::initializer_list<basic_json> init =
1717  std::initializer_list<basic_json>())
1718  {
1719  return basic_json(init, false, value_t::array);
1720  }
1721 
1756  static basic_json object(std::initializer_list<basic_json> init =
1757  std::initializer_list<basic_json>())
1758  {
1759  return basic_json(init, false, value_t::object);
1760  }
1761 
1781  : m_type(value_t::array)
1782  {
1783  m_value.array = create<array_t>(cnt, val);
1784  assert_invariant();
1785  }
1786 
1824  template<class InputIT, typename std::enable_if<
1825  std::is_same<InputIT, typename basic_json_t::iterator>::value or
1826  std::is_same<InputIT, typename basic_json_t::const_iterator>::value, int>::type = 0>
1827  basic_json(InputIT first, InputIT last)
1828  {
1829  assert(first.m_object != nullptr);
1830  assert(last.m_object != nullptr);
1831 
1832  // make sure iterator fits the current value
1833  if (first.m_object != last.m_object)
1834  {
1835  throw std::domain_error("iterators are not compatible");
1836  }
1837 
1838  // copy type from first iterator
1839  m_type = first.m_object->m_type;
1840 
1841  // check if iterator range is complete for primitive values
1842  switch (m_type)
1843  {
1844  case value_t::boolean:
1845  case value_t::number_float:
1846  case value_t::number_integer:
1847  case value_t::number_unsigned:
1848  case value_t::string:
1849  {
1850  if (not first.m_it.primitive_iterator.is_begin() or not last.m_it.primitive_iterator.is_end())
1851  {
1852  throw std::out_of_range("iterators out of range");
1853  }
1854  break;
1855  }
1856 
1857  default:
1858  {
1859  break;
1860  }
1861  }
1862 
1863  switch (m_type)
1864  {
1865  case value_t::number_integer:
1866  {
1867  m_value.number_integer = first.m_object->m_value.number_integer;
1868  break;
1869  }
1870 
1871  case value_t::number_unsigned:
1872  {
1873  m_value.number_unsigned = first.m_object->m_value.number_unsigned;
1874  break;
1875  }
1876 
1877  case value_t::number_float:
1878  {
1879  m_value.number_float = first.m_object->m_value.number_float;
1880  break;
1881  }
1882 
1883  case value_t::boolean:
1884  {
1885  m_value.boolean = first.m_object->m_value.boolean;
1886  break;
1887  }
1888 
1889  case value_t::string:
1890  {
1891  m_value = *first.m_object->m_value.string;
1892  break;
1893  }
1894 
1895  case value_t::object:
1896  {
1897  m_value.object = create<object_t>(first.m_it.object_iterator, last.m_it.object_iterator);
1898  break;
1899  }
1900 
1901  case value_t::array:
1902  {
1903  m_value.array = create<array_t>(first.m_it.array_iterator, last.m_it.array_iterator);
1904  break;
1905  }
1906 
1907  default:
1908  {
1909  throw std::domain_error("cannot use construct with iterators from " + first.m_object->type_name());
1910  }
1911  }
1912 
1913  assert_invariant();
1914  }
1915 
1944  JSON_DEPRECATED
1945  explicit basic_json(std::istream& i, const parser_callback_t cb = nullptr)
1946  {
1947  *this = parser(i, cb).parse();
1948  assert_invariant();
1949  }
1950 
1952  // other constructors and destructor //
1954 
1977  basic_json(const basic_json& other)
1978  : m_type(other.m_type)
1979  {
1980  // check of passed value is valid
1981  other.assert_invariant();
1982 
1983  switch (m_type)
1984  {
1985  case value_t::object:
1986  {
1987  m_value = *other.m_value.object;
1988  break;
1989  }
1990 
1991  case value_t::array:
1992  {
1993  m_value = *other.m_value.array;
1994  break;
1995  }
1996 
1997  case value_t::string:
1998  {
1999  m_value = *other.m_value.string;
2000  break;
2001  }
2002 
2003  case value_t::boolean:
2004  {
2005  m_value = other.m_value.boolean;
2006  break;
2007  }
2008 
2009  case value_t::number_integer:
2010  {
2011  m_value = other.m_value.number_integer;
2012  break;
2013  }
2014 
2015  case value_t::number_unsigned:
2016  {
2017  m_value = other.m_value.number_unsigned;
2018  break;
2019  }
2020 
2021  case value_t::number_float:
2022  {
2023  m_value = other.m_value.number_float;
2024  break;
2025  }
2026 
2027  default:
2028  {
2029  break;
2030  }
2031  }
2032 
2033  assert_invariant();
2034  }
2035 
2054  basic_json(basic_json&& other) noexcept
2055  : m_type(std::move(other.m_type)),
2056  m_value(std::move(other.m_value))
2057  {
2058  // check that passed value is valid
2059  other.assert_invariant();
2060 
2061  // invalidate payload
2062  other.m_type = value_t::null;
2063  other.m_value = {};
2064 
2065  assert_invariant();
2066  }
2067 
2091  reference& operator=(basic_json other) noexcept (
2092  std::is_nothrow_move_constructible<value_t>::value and
2093  std::is_nothrow_move_assignable<value_t>::value and
2094  std::is_nothrow_move_constructible<json_value>::value and
2095  std::is_nothrow_move_assignable<json_value>::value
2096  )
2097  {
2098  // check that passed value is valid
2099  other.assert_invariant();
2100 
2101  using std::swap;
2102  swap(m_type, other.m_type);
2103  swap(m_value, other.m_value);
2104 
2105  assert_invariant();
2106  return *this;
2107  }
2108 
2125  {
2126  assert_invariant();
2127 
2128  switch (m_type)
2129  {
2130  case value_t::object:
2131  {
2132  AllocatorType<object_t> alloc;
2133  alloc.destroy(m_value.object);
2134  alloc.deallocate(m_value.object, 1);
2135  break;
2136  }
2137 
2138  case value_t::array:
2139  {
2140  AllocatorType<array_t> alloc;
2141  alloc.destroy(m_value.array);
2142  alloc.deallocate(m_value.array, 1);
2143  break;
2144  }
2145 
2146  case value_t::string:
2147  {
2148  AllocatorType<string_t> alloc;
2149  alloc.destroy(m_value.string);
2150  alloc.deallocate(m_value.string, 1);
2151  break;
2152  }
2153 
2154  default:
2155  {
2156  // all other types need no specific destructor
2157  break;
2158  }
2159  }
2160  }
2161 
2163 
2164  public:
2166  // object inspection //
2168 
2172 
2196  string_t dump(const int indent = -1) const
2197  {
2198  std::stringstream ss;
2199  // fix locale problems
2200  ss.imbue(std::locale::classic());
2201 
2202  // 6, 15 or 16 digits of precision allows round-trip IEEE 754
2203  // string->float->string, string->double->string or string->long
2204  // double->string; to be safe, we read this value from
2205  // std::numeric_limits<number_float_t>::digits10
2206  ss.precision(std::numeric_limits<double>::digits10);
2207 
2208  if (indent >= 0)
2209  {
2210  dump(ss, true, static_cast<unsigned int>(indent));
2211  }
2212  else
2213  {
2214  dump(ss, false, 0);
2215  }
2216 
2217  return ss.str();
2218  }
2219 
2238  constexpr value_t type() const noexcept
2239  {
2240  return m_type;
2241  }
2242 
2268  constexpr bool is_primitive() const noexcept
2269  {
2270  return is_null() or is_string() or is_boolean() or is_number();
2271  }
2272 
2295  constexpr bool is_structured() const noexcept
2296  {
2297  return is_array() or is_object();
2298  }
2299 
2317  constexpr bool is_null() const noexcept
2318  {
2319  return m_type == value_t::null;
2320  }
2321 
2339  constexpr bool is_boolean() const noexcept
2340  {
2341  return m_type == value_t::boolean;
2342  }
2343 
2369  constexpr bool is_number() const noexcept
2370  {
2371  return is_number_integer() or is_number_float();
2372  }
2373 
2398  constexpr bool is_number_integer() const noexcept
2399  {
2400  return m_type == value_t::number_integer or m_type == value_t::number_unsigned;
2401  }
2402 
2426  constexpr bool is_number_unsigned() const noexcept
2427  {
2428  return m_type == value_t::number_unsigned;
2429  }
2430 
2454  constexpr bool is_number_float() const noexcept
2455  {
2456  return m_type == value_t::number_float;
2457  }
2458 
2476  constexpr bool is_object() const noexcept
2477  {
2478  return m_type == value_t::object;
2479  }
2480 
2498  constexpr bool is_array() const noexcept
2499  {
2500  return m_type == value_t::array;
2501  }
2502 
2520  constexpr bool is_string() const noexcept
2521  {
2522  return m_type == value_t::string;
2523  }
2524 
2547  constexpr bool is_discarded() const noexcept
2548  {
2549  return m_type == value_t::discarded;
2550  }
2551 
2570  constexpr operator value_t() const noexcept
2571  {
2572  return m_type;
2573  }
2574 
2576 
2577  private:
2579  // value access //
2581 
2583  template<class T, typename std::enable_if<
2584  std::is_convertible<typename object_t::key_type, typename T::key_type>::value and
2585  std::is_convertible<basic_json_t, typename T::mapped_type>::value, int>::type = 0>
2586  T get_impl(T*) const
2587  {
2588  if (is_object())
2589  {
2590  return T(m_value.object->begin(), m_value.object->end());
2591  }
2592  else
2593  {
2594  throw std::domain_error("type must be object, but is " + type_name());
2595  }
2596  }
2597 
2599  object_t get_impl(object_t*) const
2600  {
2601  if (is_object())
2602  {
2603  return *(m_value.object);
2604  }
2605  else
2606  {
2607  throw std::domain_error("type must be object, but is " + type_name());
2608  }
2609  }
2610 
2612  template<class T, typename std::enable_if<
2613  std::is_convertible<basic_json_t, typename T::value_type>::value and
2614  not std::is_same<basic_json_t, typename T::value_type>::value and
2615  not std::is_arithmetic<T>::value and
2616  not std::is_convertible<std::string, T>::value and
2617  not has_mapped_type<T>::value, int>::type = 0>
2618  T get_impl(T*) const
2619  {
2620  if (is_array())
2621  {
2622  T to_vector;
2623  std::transform(m_value.array->begin(), m_value.array->end(),
2624  std::inserter(to_vector, to_vector.end()), [](basic_json i)
2625  {
2626  return i.get<typename T::value_type>();
2627  });
2628  return to_vector;
2629  }
2630  else
2631  {
2632  throw std::domain_error("type must be array, but is " + type_name());
2633  }
2634  }
2635 
2637  template<class T, typename std::enable_if<
2638  std::is_convertible<basic_json_t, T>::value and
2639  not std::is_same<basic_json_t, T>::value, int>::type = 0>
2640  std::vector<T> get_impl(std::vector<T>*) const
2641  {
2642  if (is_array())
2643  {
2644  std::vector<T> to_vector;
2645  to_vector.reserve(m_value.array->size());
2646  std::transform(m_value.array->begin(), m_value.array->end(),
2647  std::inserter(to_vector, to_vector.end()), [](basic_json i)
2648  {
2649  return i.get<T>();
2650  });
2651  return to_vector;
2652  }
2653  else
2654  {
2655  throw std::domain_error("type must be array, but is " + type_name());
2656  }
2657  }
2658 
2660  template<class T, typename std::enable_if<
2661  std::is_same<basic_json, typename T::value_type>::value and
2662  not has_mapped_type<T>::value, int>::type = 0>
2663  T get_impl(T*) const
2664  {
2665  if (is_array())
2666  {
2667  return T(m_value.array->begin(), m_value.array->end());
2668  }
2669  else
2670  {
2671  throw std::domain_error("type must be array, but is " + type_name());
2672  }
2673  }
2674 
2676  array_t get_impl(array_t*) const
2677  {
2678  if (is_array())
2679  {
2680  return *(m_value.array);
2681  }
2682  else
2683  {
2684  throw std::domain_error("type must be array, but is " + type_name());
2685  }
2686  }
2687 
2689  template<typename T, typename std::enable_if<
2690  std::is_convertible<string_t, T>::value, int>::type = 0>
2691  T get_impl(T*) const
2692  {
2693  if (is_string())
2694  {
2695  return *m_value.string;
2696  }
2697  else
2698  {
2699  throw std::domain_error("type must be string, but is " + type_name());
2700  }
2701  }
2702 
2704  template<typename T, typename std::enable_if<
2705  std::is_arithmetic<T>::value, int>::type = 0>
2706  T get_impl(T*) const
2707  {
2708  switch (m_type)
2709  {
2710  case value_t::number_integer:
2711  {
2712  return static_cast<T>(m_value.number_integer);
2713  }
2714 
2715  case value_t::number_unsigned:
2716  {
2717  return static_cast<T>(m_value.number_unsigned);
2718  }
2719 
2720  case value_t::number_float:
2721  {
2722  return static_cast<T>(m_value.number_float);
2723  }
2724 
2725  default:
2726  {
2727  throw std::domain_error("type must be number, but is " + type_name());
2728  }
2729  }
2730  }
2731 
2733  constexpr boolean_t get_impl(boolean_t*) const
2734  {
2735  return is_boolean()
2736  ? m_value.boolean
2737  : throw std::domain_error("type must be boolean, but is " + type_name());
2738  }
2739 
2741  object_t* get_impl_ptr(object_t*) noexcept
2742  {
2743  return is_object() ? m_value.object : nullptr;
2744  }
2745 
2747  constexpr const object_t* get_impl_ptr(const object_t*) const noexcept
2748  {
2749  return is_object() ? m_value.object : nullptr;
2750  }
2751 
2753  array_t* get_impl_ptr(array_t*) noexcept
2754  {
2755  return is_array() ? m_value.array : nullptr;
2756  }
2757 
2759  constexpr const array_t* get_impl_ptr(const array_t*) const noexcept
2760  {
2761  return is_array() ? m_value.array : nullptr;
2762  }
2763 
2765  string_t* get_impl_ptr(string_t*) noexcept
2766  {
2767  return is_string() ? m_value.string : nullptr;
2768  }
2769 
2771  constexpr const string_t* get_impl_ptr(const string_t*) const noexcept
2772  {
2773  return is_string() ? m_value.string : nullptr;
2774  }
2775 
2777  boolean_t* get_impl_ptr(boolean_t*) noexcept
2778  {
2779  return is_boolean() ? &m_value.boolean : nullptr;
2780  }
2781 
2783  constexpr const boolean_t* get_impl_ptr(const boolean_t*) const noexcept
2784  {
2785  return is_boolean() ? &m_value.boolean : nullptr;
2786  }
2787 
2789  number_integer_t* get_impl_ptr(number_integer_t*) noexcept
2790  {
2791  return is_number_integer() ? &m_value.number_integer : nullptr;
2792  }
2793 
2795  constexpr const number_integer_t* get_impl_ptr(const number_integer_t*) const noexcept
2796  {
2797  return is_number_integer() ? &m_value.number_integer : nullptr;
2798  }
2799 
2801  number_unsigned_t* get_impl_ptr(number_unsigned_t*) noexcept
2802  {
2803  return is_number_unsigned() ? &m_value.number_unsigned : nullptr;
2804  }
2805 
2807  constexpr const number_unsigned_t* get_impl_ptr(const number_unsigned_t*) const noexcept
2808  {
2809  return is_number_unsigned() ? &m_value.number_unsigned : nullptr;
2810  }
2811 
2813  number_float_t* get_impl_ptr(number_float_t*) noexcept
2814  {
2815  return is_number_float() ? &m_value.number_float : nullptr;
2816  }
2817 
2819  constexpr const number_float_t* get_impl_ptr(const number_float_t*) const noexcept
2820  {
2821  return is_number_float() ? &m_value.number_float : nullptr;
2822  }
2823 
2835  template<typename ReferenceType, typename ThisType>
2836  static ReferenceType get_ref_impl(ThisType& obj)
2837  {
2838  // helper type
2839  using PointerType = typename std::add_pointer<ReferenceType>::type;
2840 
2841  // delegate the call to get_ptr<>()
2842  auto ptr = obj.template get_ptr<PointerType>();
2843 
2844  if (ptr != nullptr)
2845  {
2846  return *ptr;
2847  }
2848  else
2849  {
2850  throw std::domain_error("incompatible ReferenceType for get_ref, actual type is " +
2851  obj.type_name());
2852  }
2853  }
2854 
2855  public:
2856 
2860 
2894  template<typename ValueType, typename std::enable_if<
2895  not std::is_pointer<ValueType>::value, int>::type = 0>
2896  ValueType get() const
2897  {
2898  return get_impl(static_cast<ValueType*>(nullptr));
2899  }
2900 
2928  template<typename PointerType, typename std::enable_if<
2929  std::is_pointer<PointerType>::value, int>::type = 0>
2930  PointerType get() noexcept
2931  {
2932  // delegate the call to get_ptr
2933  return get_ptr<PointerType>();
2934  }
2935 
2940  template<typename PointerType, typename std::enable_if<
2941  std::is_pointer<PointerType>::value, int>::type = 0>
2942  constexpr const PointerType get() const noexcept
2943  {
2944  // delegate the call to get_ptr
2945  return get_ptr<PointerType>();
2946  }
2947 
2974  template<typename PointerType, typename std::enable_if<
2975  std::is_pointer<PointerType>::value, int>::type = 0>
2976  PointerType get_ptr() noexcept
2977  {
2978  // get the type of the PointerType (remove pointer and const)
2979  using pointee_t = typename std::remove_const<typename
2980  std::remove_pointer<typename
2981  std::remove_const<PointerType>::type>::type>::type;
2982  // make sure the type matches the allowed types
2983  static_assert(
2984  std::is_same<object_t, pointee_t>::value
2985  or std::is_same<array_t, pointee_t>::value
2986  or std::is_same<string_t, pointee_t>::value
2987  or std::is_same<boolean_t, pointee_t>::value
2988  or std::is_same<number_integer_t, pointee_t>::value
2989  or std::is_same<number_unsigned_t, pointee_t>::value
2990  or std::is_same<number_float_t, pointee_t>::value
2991  , "incompatible pointer type");
2992 
2993  // delegate the call to get_impl_ptr<>()
2994  return get_impl_ptr(static_cast<PointerType>(nullptr));
2995  }
2996 
3001  template<typename PointerType, typename std::enable_if<
3002  std::is_pointer<PointerType>::value and
3003  std::is_const<typename std::remove_pointer<PointerType>::type>::value, int>::type = 0>
3004  constexpr const PointerType get_ptr() const noexcept
3005  {
3006  // get the type of the PointerType (remove pointer and const)
3007  using pointee_t = typename std::remove_const<typename
3008  std::remove_pointer<typename
3009  std::remove_const<PointerType>::type>::type>::type;
3010  // make sure the type matches the allowed types
3011  static_assert(
3012  std::is_same<object_t, pointee_t>::value
3013  or std::is_same<array_t, pointee_t>::value
3014  or std::is_same<string_t, pointee_t>::value
3015  or std::is_same<boolean_t, pointee_t>::value
3016  or std::is_same<number_integer_t, pointee_t>::value
3017  or std::is_same<number_unsigned_t, pointee_t>::value
3018  or std::is_same<number_float_t, pointee_t>::value
3019  , "incompatible pointer type");
3020 
3021  // delegate the call to get_impl_ptr<>() const
3022  return get_impl_ptr(static_cast<const PointerType>(nullptr));
3023  }
3024 
3051  template<typename ReferenceType, typename std::enable_if<
3052  std::is_reference<ReferenceType>::value, int>::type = 0>
3053  ReferenceType get_ref()
3054  {
3055  // delegate call to get_ref_impl
3056  return get_ref_impl<ReferenceType>(*this);
3057  }
3058 
3063  template<typename ReferenceType, typename std::enable_if<
3064  std::is_reference<ReferenceType>::value and
3065  std::is_const<typename std::remove_reference<ReferenceType>::type>::value, int>::type = 0>
3066  ReferenceType get_ref() const
3067  {
3068  // delegate call to get_ref_impl
3069  return get_ref_impl<ReferenceType>(*this);
3070  }
3071 
3100  template < typename ValueType, typename std::enable_if <
3101  not std::is_pointer<ValueType>::value and
3102  not std::is_same<ValueType, typename string_t::value_type>::value
3103 #ifndef _MSC_VER // Fix for issue #167 operator<< abiguity under VS2015
3104  and not std::is_same<ValueType, std::initializer_list<typename string_t::value_type>>::value
3105 #endif
3106  , int >::type = 0 >
3107  operator ValueType() const
3108  {
3109  // delegate the call to get<>() const
3110  return get<ValueType>();
3111  }
3112 
3114 
3115 
3117  // element access //
3119 
3123 
3147  {
3148  // at only works for arrays
3149  if (is_array())
3150  {
3151  try
3152  {
3153  return m_value.array->at(idx);
3154  }
3155  catch (std::out_of_range&)
3156  {
3157  // create better exception explanation
3158  throw std::out_of_range("array index " + std::to_string(idx) + " is out of range");
3159  }
3160  }
3161  else
3162  {
3163  throw std::domain_error("cannot use at() with " + type_name());
3164  }
3165  }
3166 
3190  {
3191  // at only works for arrays
3192  if (is_array())
3193  {
3194  try
3195  {
3196  return m_value.array->at(idx);
3197  }
3198  catch (std::out_of_range&)
3199  {
3200  // create better exception explanation
3201  throw std::out_of_range("array index " + std::to_string(idx) + " is out of range");
3202  }
3203  }
3204  else
3205  {
3206  throw std::domain_error("cannot use at() with " + type_name());
3207  }
3208  }
3209 
3236  reference at(const typename object_t::key_type& key)
3237  {
3238  // at only works for objects
3239  if (is_object())
3240  {
3241  try
3242  {
3243  return m_value.object->at(key);
3244  }
3245  catch (std::out_of_range&)
3246  {
3247  // create better exception explanation
3248  throw std::out_of_range("key '" + key + "' not found");
3249  }
3250  }
3251  else
3252  {
3253  throw std::domain_error("cannot use at() with " + type_name());
3254  }
3255  }
3256 
3283  const_reference at(const typename object_t::key_type& key) const
3284  {
3285  // at only works for objects
3286  if (is_object())
3287  {
3288  try
3289  {
3290  return m_value.object->at(key);
3291  }
3292  catch (std::out_of_range&)
3293  {
3294  // create better exception explanation
3295  throw std::out_of_range("key '" + key + "' not found");
3296  }
3297  }
3298  else
3299  {
3300  throw std::domain_error("cannot use at() with " + type_name());
3301  }
3302  }
3303 
3330  {
3331  // implicitly convert null value to an empty array
3332  if (is_null())
3333  {
3334  m_type = value_t::array;
3335  m_value.array = create<array_t>();
3336  assert_invariant();
3337  }
3338 
3339  // operator[] only works for arrays
3340  if (is_array())
3341  {
3342  // fill up array with null values if given idx is outside range
3343  if (idx >= m_value.array->size())
3344  {
3345  m_value.array->insert(m_value.array->end(),
3346  idx - m_value.array->size() + 1,
3347  basic_json());
3348  }
3349 
3350  return m_value.array->operator[](idx);
3351  }
3352  else
3353  {
3354  throw std::domain_error("cannot use operator[] with " + type_name());
3355  }
3356  }
3357 
3378  {
3379  // const operator[] only works for arrays
3380  if (is_array())
3381  {
3382  return m_value.array->operator[](idx);
3383  }
3384  else
3385  {
3386  throw std::domain_error("cannot use operator[] with " + type_name());
3387  }
3388  }
3389 
3417  reference operator[](const typename object_t::key_type& key)
3418  {
3419  // implicitly convert null value to an empty object
3420  if (is_null())
3421  {
3422  m_type = value_t::object;
3423  m_value.object = create<object_t>();
3424  assert_invariant();
3425  }
3426 
3427  // operator[] only works for objects
3428  if (is_object())
3429  {
3430  return m_value.object->operator[](key);
3431  }
3432  else
3433  {
3434  throw std::domain_error("cannot use operator[] with " + type_name());
3435  }
3436  }
3437 
3468  const_reference operator[](const typename object_t::key_type& key) const
3469  {
3470  // const operator[] only works for objects
3471  if (is_object())
3472  {
3473  assert(m_value.object->find(key) != m_value.object->end());
3474  return m_value.object->find(key)->second;
3475  }
3476  else
3477  {
3478  throw std::domain_error("cannot use operator[] with " + type_name());
3479  }
3480  }
3481 
3509  template<typename T, std::size_t n>
3510  reference operator[](T * (&key)[n])
3511  {
3512  return operator[](static_cast<const T>(key));
3513  }
3514 
3544  template<typename T, std::size_t n>
3545  const_reference operator[](T * (&key)[n]) const
3546  {
3547  return operator[](static_cast<const T>(key));
3548  }
3549 
3577  template<typename T>
3579  {
3580  // implicitly convert null to object
3581  if (is_null())
3582  {
3583  m_type = value_t::object;
3584  m_value = value_t::object;
3585  assert_invariant();
3586  }
3587 
3588  // at only works for objects
3589  if (is_object())
3590  {
3591  return m_value.object->operator[](key);
3592  }
3593  else
3594  {
3595  throw std::domain_error("cannot use operator[] with " + type_name());
3596  }
3597  }
3598 
3629  template<typename T>
3631  {
3632  // at only works for objects
3633  if (is_object())
3634  {
3635  assert(m_value.object->find(key) != m_value.object->end());
3636  return m_value.object->find(key)->second;
3637  }
3638  else
3639  {
3640  throw std::domain_error("cannot use operator[] with " + type_name());
3641  }
3642  }
3643 
3692  template<class ValueType, typename std::enable_if<
3693  std::is_convertible<basic_json_t, ValueType>::value, int>::type = 0>
3694  ValueType value(const typename object_t::key_type& key, ValueType default_value) const
3695  {
3696  // at only works for objects
3697  if (is_object())
3698  {
3699  // if key is found, return value and given default value otherwise
3700  const auto it = find(key);
3701  if (it != end())
3702  {
3703  return *it;
3704  }
3705  else
3706  {
3707  return default_value;
3708  }
3709  }
3710  else
3711  {
3712  throw std::domain_error("cannot use value() with " + type_name());
3713  }
3714  }
3715 
3720  string_t value(const typename object_t::key_type& key, const char* default_value) const
3721  {
3722  return value(key, string_t(default_value));
3723  }
3724 
3766  template<class ValueType, typename std::enable_if<
3767  std::is_convertible<basic_json_t, ValueType>::value, int>::type = 0>
3768  ValueType value(const json_pointer& ptr, ValueType default_value) const
3769  {
3770  // at only works for objects
3771  if (is_object())
3772  {
3773  // if pointer resolves a value, return it or use default value
3774  try
3775  {
3776  return ptr.get_checked(this);
3777  }
3778  catch (std::out_of_range&)
3779  {
3780  return default_value;
3781  }
3782  }
3783  else
3784  {
3785  throw std::domain_error("cannot use value() with " + type_name());
3786  }
3787  }
3788 
3793  string_t value(const json_pointer& ptr, const char* default_value) const
3794  {
3795  return value(ptr, string_t(default_value));
3796  }
3797 
3824  {
3825  return *begin();
3826  }
3827 
3832  {
3833  return *cbegin();
3834  }
3835 
3867  {
3868  auto tmp = end();
3869  --tmp;
3870  return *tmp;
3871  }
3872 
3877  {
3878  auto tmp = cend();
3879  --tmp;
3880  return *tmp;
3881  }
3882 
3928  template<class IteratorType, typename std::enable_if<
3929  std::is_same<IteratorType, typename basic_json_t::iterator>::value or
3930  std::is_same<IteratorType, typename basic_json_t::const_iterator>::value, int>::type
3931  = 0>
3932  IteratorType erase(IteratorType pos)
3933  {
3934  // make sure iterator fits the current value
3935  if (this != pos.m_object)
3936  {
3937  throw std::domain_error("iterator does not fit current value");
3938  }
3939 
3940  IteratorType result = end();
3941 
3942  switch (m_type)
3943  {
3944  case value_t::boolean:
3945  case value_t::number_float:
3946  case value_t::number_integer:
3947  case value_t::number_unsigned:
3948  case value_t::string:
3949  {
3950  if (not pos.m_it.primitive_iterator.is_begin())
3951  {
3952  throw std::out_of_range("iterator out of range");
3953  }
3954 
3955  if (is_string())
3956  {
3957  AllocatorType<string_t> alloc;
3958  alloc.destroy(m_value.string);
3959  alloc.deallocate(m_value.string, 1);
3960  m_value.string = nullptr;
3961  }
3962 
3963  m_type = value_t::null;
3964  assert_invariant();
3965  break;
3966  }
3967 
3968  case value_t::object:
3969  {
3970  result.m_it.object_iterator = m_value.object->erase(pos.m_it.object_iterator);
3971  break;
3972  }
3973 
3974  case value_t::array:
3975  {
3976  result.m_it.array_iterator = m_value.array->erase(pos.m_it.array_iterator);
3977  break;
3978  }
3979 
3980  default:
3981  {
3982  throw std::domain_error("cannot use erase() with " + type_name());
3983  }
3984  }
3985 
3986  return result;
3987  }
3988 
4035  template<class IteratorType, typename std::enable_if<
4036  std::is_same<IteratorType, typename basic_json_t::iterator>::value or
4037  std::is_same<IteratorType, typename basic_json_t::const_iterator>::value, int>::type
4038  = 0>
4039  IteratorType erase(IteratorType first, IteratorType last)
4040  {
4041  // make sure iterator fits the current value
4042  if (this != first.m_object or this != last.m_object)
4043  {
4044  throw std::domain_error("iterators do not fit current value");
4045  }
4046 
4047  IteratorType result = end();
4048 
4049  switch (m_type)
4050  {
4051  case value_t::boolean:
4052  case value_t::number_float:
4053  case value_t::number_integer:
4054  case value_t::number_unsigned:
4055  case value_t::string:
4056  {
4057  if (not first.m_it.primitive_iterator.is_begin() or not last.m_it.primitive_iterator.is_end())
4058  {
4059  throw std::out_of_range("iterators out of range");
4060  }
4061 
4062  if (is_string())
4063  {
4064  AllocatorType<string_t> alloc;
4065  alloc.destroy(m_value.string);
4066  alloc.deallocate(m_value.string, 1);
4067  m_value.string = nullptr;
4068  }
4069 
4070  m_type = value_t::null;
4071  assert_invariant();
4072  break;
4073  }
4074 
4075  case value_t::object:
4076  {
4077  result.m_it.object_iterator = m_value.object->erase(first.m_it.object_iterator,
4078  last.m_it.object_iterator);
4079  break;
4080  }
4081 
4082  case value_t::array:
4083  {
4084  result.m_it.array_iterator = m_value.array->erase(first.m_it.array_iterator,
4085  last.m_it.array_iterator);
4086  break;
4087  }
4088 
4089  default:
4090  {
4091  throw std::domain_error("cannot use erase() with " + type_name());
4092  }
4093  }
4094 
4095  return result;
4096  }
4097 
4127  size_type erase(const typename object_t::key_type& key)
4128  {
4129  // this erase only works for objects
4130  if (is_object())
4131  {
4132  return m_value.object->erase(key);
4133  }
4134  else
4135  {
4136  throw std::domain_error("cannot use erase() with " + type_name());
4137  }
4138  }
4139 
4164  void erase(const size_type idx)
4165  {
4166  // this erase only works for arrays
4167  if (is_array())
4168  {
4169  if (idx >= size())
4170  {
4171  throw std::out_of_range("array index " + std::to_string(idx) + " is out of range");
4172  }
4173 
4174  m_value.array->erase(m_value.array->begin() + static_cast<difference_type>(idx));
4175  }
4176  else
4177  {
4178  throw std::domain_error("cannot use erase() with " + type_name());
4179  }
4180  }
4181 
4183 
4184 
4186  // lookup //
4188 
4191 
4214  iterator find(typename object_t::key_type key)
4215  {
4216  auto result = end();
4217 
4218  if (is_object())
4219  {
4220  result.m_it.object_iterator = m_value.object->find(key);
4221  }
4222 
4223  return result;
4224  }
4225 
4230  const_iterator find(typename object_t::key_type key) const
4231  {
4232  auto result = cend();
4233 
4234  if (is_object())
4235  {
4236  result.m_it.object_iterator = m_value.object->find(key);
4237  }
4238 
4239  return result;
4240  }
4241 
4263  size_type count(typename object_t::key_type key) const
4264  {
4265  // return 0 for all nonobject types
4266  return is_object() ? m_value.object->count(key) : 0;
4267  }
4268 
4270 
4271 
4273  // iterators //
4275 
4278 
4303  iterator begin() noexcept
4304  {
4305  iterator result(this);
4306  result.set_begin();
4307  return result;
4308  }
4309 
4313  const_iterator begin() const noexcept
4314  {
4315  return cbegin();
4316  }
4317 
4343  const_iterator cbegin() const noexcept
4344  {
4345  const_iterator result(this);
4346  result.set_begin();
4347  return result;
4348  }
4349 
4374  iterator end() noexcept
4375  {
4376  iterator result(this);
4377  result.set_end();
4378  return result;
4379  }
4380 
4384  const_iterator end() const noexcept
4385  {
4386  return cend();
4387  }
4388 
4414  const_iterator cend() const noexcept
4415  {
4416  const_iterator result(this);
4417  result.set_end();
4418  return result;
4419  }
4420 
4445  {
4446  return reverse_iterator(end());
4447  }
4448 
4453  {
4454  return crbegin();
4455  }
4456 
4482  {
4483  return reverse_iterator(begin());
4484  }
4485 
4489  const_reverse_iterator rend() const noexcept
4490  {
4491  return crend();
4492  }
4493 
4519  {
4520  return const_reverse_iterator(cend());
4521  }
4522 
4548  {
4549  return const_reverse_iterator(cbegin());
4550  }
4551 
4552  private:
4553  // forward declaration
4554  template<typename IteratorType> class iteration_proxy;
4555 
4556  public:
4568  static iteration_proxy<iterator> iterator_wrapper(reference cont)
4569  {
4570  return iteration_proxy<iterator>(cont);
4571  }
4572 
4576  static iteration_proxy<const_iterator> iterator_wrapper(const_reference cont)
4577  {
4578  return iteration_proxy<const_iterator>(cont);
4579  }
4580 
4582 
4583 
4585  // capacity //
4587 
4590 
4628  bool empty() const noexcept
4629  {
4630  switch (m_type)
4631  {
4632  case value_t::null:
4633  {
4634  // null values are empty
4635  return true;
4636  }
4637 
4638  case value_t::array:
4639  {
4640  // delegate call to array_t::empty()
4641  return m_value.array->empty();
4642  }
4643 
4644  case value_t::object:
4645  {
4646  // delegate call to object_t::empty()
4647  return m_value.object->empty();
4648  }
4649 
4650  default:
4651  {
4652  // all other types are nonempty
4653  return false;
4654  }
4655  }
4656  }
4657 
4696  size_type size() const noexcept
4697  {
4698  switch (m_type)
4699  {
4700  case value_t::null:
4701  {
4702  // null values are empty
4703  return 0;
4704  }
4705 
4706  case value_t::array:
4707  {
4708  // delegate call to array_t::size()
4709  return m_value.array->size();
4710  }
4711 
4712  case value_t::object:
4713  {
4714  // delegate call to object_t::size()
4715  return m_value.object->size();
4716  }
4717 
4718  default:
4719  {
4720  // all other types have size 1
4721  return 1;
4722  }
4723  }
4724  }
4725 
4762  size_type max_size() const noexcept
4763  {
4764  switch (m_type)
4765  {
4766  case value_t::array:
4767  {
4768  // delegate call to array_t::max_size()
4769  return m_value.array->max_size();
4770  }
4771 
4772  case value_t::object:
4773  {
4774  // delegate call to object_t::max_size()
4775  return m_value.object->max_size();
4776  }
4777 
4778  default:
4779  {
4780  // all other types have max_size() == size()
4781  return size();
4782  }
4783  }
4784  }
4785 
4787 
4788 
4790  // modifiers //
4792 
4795 
4818  void clear() noexcept
4819  {
4820  switch (m_type)
4821  {
4822  case value_t::number_integer:
4823  {
4824  m_value.number_integer = 0;
4825  break;
4826  }
4827 
4828  case value_t::number_unsigned:
4829  {
4830  m_value.number_unsigned = 0;
4831  break;
4832  }
4833 
4834  case value_t::number_float:
4835  {
4836  m_value.number_float = 0.0;
4837  break;
4838  }
4839 
4840  case value_t::boolean:
4841  {
4842  m_value.boolean = false;
4843  break;
4844  }
4845 
4846  case value_t::string:
4847  {
4848  m_value.string->clear();
4849  break;
4850  }
4851 
4852  case value_t::array:
4853  {
4854  m_value.array->clear();
4855  break;
4856  }
4857 
4858  case value_t::object:
4859  {
4860  m_value.object->clear();
4861  break;
4862  }
4863 
4864  default:
4865  {
4866  break;
4867  }
4868  }
4869  }
4870 
4891  void push_back(basic_json&& val)
4892  {
4893  // push_back only works for null objects or arrays
4894  if (not(is_null() or is_array()))
4895  {
4896  throw std::domain_error("cannot use push_back() with " + type_name());
4897  }
4898 
4899  // transform null object into an array
4900  if (is_null())
4901  {
4902  m_type = value_t::array;
4903  m_value = value_t::array;
4904  assert_invariant();
4905  }
4906 
4907  // add element to array (move semantics)
4908  m_value.array->push_back(std::move(val));
4909  // invalidate object
4910  val.m_type = value_t::null;
4911  }
4912 
4918  {
4919  push_back(std::move(val));
4920  return *this;
4921  }
4922 
4927  void push_back(const basic_json& val)
4928  {
4929  // push_back only works for null objects or arrays
4930  if (not(is_null() or is_array()))
4931  {
4932  throw std::domain_error("cannot use push_back() with " + type_name());
4933  }
4934 
4935  // transform null object into an array
4936  if (is_null())
4937  {
4938  m_type = value_t::array;
4939  m_value = value_t::array;
4940  assert_invariant();
4941  }
4942 
4943  // add element to array
4944  m_value.array->push_back(val);
4945  }
4946 
4952  {
4953  push_back(val);
4954  return *this;
4955  }
4956 
4977  void push_back(const typename object_t::value_type& val)
4978  {
4979  // push_back only works for null objects or objects
4980  if (not(is_null() or is_object()))
4981  {
4982  throw std::domain_error("cannot use push_back() with " + type_name());
4983  }
4984 
4985  // transform null object into an object
4986  if (is_null())
4987  {
4988  m_type = value_t::object;
4989  m_value = value_t::object;
4990  assert_invariant();
4991  }
4992 
4993  // add element to array
4994  m_value.object->insert(val);
4995  }
4996 
5001  reference operator+=(const typename object_t::value_type& val)
5002  {
5003  push_back(val);
5004  return *this;
5005  }
5006 
5032  void push_back(std::initializer_list<basic_json> init)
5033  {
5034  if (is_object() and init.size() == 2 and init.begin()->is_string())
5035  {
5036  const string_t key = *init.begin();
5037  push_back(typename object_t::value_type(key, *(init.begin() + 1)));
5038  }
5039  else
5040  {
5041  push_back(basic_json(init));
5042  }
5043  }
5044 
5049  reference operator+=(std::initializer_list<basic_json> init)
5050  {
5051  push_back(init);
5052  return *this;
5053  }
5054 
5076  template<class... Args>
5077  void emplace_back(Args&& ... args)
5078  {
5079  // emplace_back only works for null objects or arrays
5080  if (not(is_null() or is_array()))
5081  {
5082  throw std::domain_error("cannot use emplace_back() with " + type_name());
5083  }
5084 
5085  // transform null object into an array
5086  if (is_null())
5087  {
5088  m_type = value_t::array;
5089  m_value = value_t::array;
5090  assert_invariant();
5091  }
5092 
5093  // add element to array (perfect forwarding)
5094  m_value.array->emplace_back(std::forward<Args>(args)...);
5095  }
5096 
5124  template<class... Args>
5125  std::pair<iterator, bool> emplace(Args&& ... args)
5126  {
5127  // emplace only works for null objects or arrays
5128  if (not(is_null() or is_object()))
5129  {
5130  throw std::domain_error("cannot use emplace() with " + type_name());
5131  }
5132 
5133  // transform null object into an object
5134  if (is_null())
5135  {
5136  m_type = value_t::object;
5137  m_value = value_t::object;
5138  assert_invariant();
5139  }
5140 
5141  // add element to array (perfect forwarding)
5142  auto res = m_value.object->emplace(std::forward<Args>(args)...);
5143  // create result iterator and set iterator to the result of emplace
5144  auto it = begin();
5145  it.m_it.object_iterator = res.first;
5146 
5147  // return pair of iterator and boolean
5148  return {it, res.second};
5149  }
5150 
5174  {
5175  // insert only works for arrays
5176  if (is_array())
5177  {
5178  // check if iterator pos fits to this JSON value
5179  if (pos.m_object != this)
5180  {
5181  throw std::domain_error("iterator does not fit current value");
5182  }
5183 
5184  // insert to array and return iterator
5185  iterator result(this);
5186  result.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator, val);
5187  return result;
5188  }
5189  else
5190  {
5191  throw std::domain_error("cannot use insert() with " + type_name());
5192  }
5193  }
5194 
5200  {
5201  return insert(pos, val);
5202  }
5203 
5229  {
5230  // insert only works for arrays
5231  if (is_array())
5232  {
5233  // check if iterator pos fits to this JSON value
5234  if (pos.m_object != this)
5235  {
5236  throw std::domain_error("iterator does not fit current value");
5237  }
5238 
5239  // insert to array and return iterator
5240  iterator result(this);
5241  result.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator, cnt, val);
5242  return result;
5243  }
5244  else
5245  {
5246  throw std::domain_error("cannot use insert() with " + type_name());
5247  }
5248  }
5249 
5281  {
5282  // insert only works for arrays
5283  if (not is_array())
5284  {
5285  throw std::domain_error("cannot use insert() with " + type_name());
5286  }
5287 
5288  // check if iterator pos fits to this JSON value
5289  if (pos.m_object != this)
5290  {
5291  throw std::domain_error("iterator does not fit current value");
5292  }
5293 
5294  // check if range iterators belong to the same JSON object
5295  if (first.m_object != last.m_object)
5296  {
5297  throw std::domain_error("iterators do not fit");
5298  }
5299 
5300  if (first.m_object == this or last.m_object == this)
5301  {
5302  throw std::domain_error("passed iterators may not belong to container");
5303  }
5304 
5305  // insert to array and return iterator
5306  iterator result(this);
5307  result.m_it.array_iterator = m_value.array->insert(
5308  pos.m_it.array_iterator,
5309  first.m_it.array_iterator,
5310  last.m_it.array_iterator);
5311  return result;
5312  }
5313 
5338  iterator insert(const_iterator pos, std::initializer_list<basic_json> ilist)
5339  {
5340  // insert only works for arrays
5341  if (not is_array())
5342  {
5343  throw std::domain_error("cannot use insert() with " + type_name());
5344  }
5345 
5346  // check if iterator pos fits to this JSON value
5347  if (pos.m_object != this)
5348  {
5349  throw std::domain_error("iterator does not fit current value");
5350  }
5351 
5352  // insert to array and return iterator
5353  iterator result(this);
5354  result.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator, ilist);
5355  return result;
5356  }
5357 
5375  void swap(reference other) noexcept (
5376  std::is_nothrow_move_constructible<value_t>::value and
5377  std::is_nothrow_move_assignable<value_t>::value and
5378  std::is_nothrow_move_constructible<json_value>::value and
5379  std::is_nothrow_move_assignable<json_value>::value
5380  )
5381  {
5382  std::swap(m_type, other.m_type);
5383  std::swap(m_value, other.m_value);
5384  assert_invariant();
5385  }
5386 
5407  void swap(array_t& other)
5408  {
5409  // swap only works for arrays
5410  if (is_array())
5411  {
5412  std::swap(*(m_value.array), other);
5413  }
5414  else
5415  {
5416  throw std::domain_error("cannot use swap() with " + type_name());
5417  }
5418  }
5419 
5440  void swap(object_t& other)
5441  {
5442  // swap only works for objects
5443  if (is_object())
5444  {
5445  std::swap(*(m_value.object), other);
5446  }
5447  else
5448  {
5449  throw std::domain_error("cannot use swap() with " + type_name());
5450  }
5451  }
5452 
5473  void swap(string_t& other)
5474  {
5475  // swap only works for strings
5476  if (is_string())
5477  {
5478  std::swap(*(m_value.string), other);
5479  }
5480  else
5481  {
5482  throw std::domain_error("cannot use swap() with " + type_name());
5483  }
5484  }
5485 
5487 
5488 
5490  // lexicographical comparison operators //
5492 
5495 
5496  private:
5506  friend bool operator<(const value_t lhs, const value_t rhs) noexcept
5507  {
5508  static constexpr std::array<uint8_t, 8> order = {{
5509  0, // null
5510  3, // object
5511  4, // array
5512  5, // string
5513  1, // boolean
5514  2, // integer
5515  2, // unsigned
5516  2, // float
5517  }
5518  };
5519 
5520  // discarded values are not comparable
5521  if (lhs == value_t::discarded or rhs == value_t::discarded)
5522  {
5523  return false;
5524  }
5525 
5526  return order[static_cast<std::size_t>(lhs)] < order[static_cast<std::size_t>(rhs)];
5527  }
5528 
5529  public:
5553  friend bool operator==(const_reference lhs, const_reference rhs) noexcept
5554  {
5555  const auto lhs_type = lhs.type();
5556  const auto rhs_type = rhs.type();
5557 
5558  if (lhs_type == rhs_type)
5559  {
5560  switch (lhs_type)
5561  {
5562  case value_t::array:
5563  {
5564  return *lhs.m_value.array == *rhs.m_value.array;
5565  }
5566  case value_t::object:
5567  {
5568  return *lhs.m_value.object == *rhs.m_value.object;
5569  }
5570  case value_t::null:
5571  {
5572  return true;
5573  }
5574  case value_t::string:
5575  {
5576  return *lhs.m_value.string == *rhs.m_value.string;
5577  }
5578  case value_t::boolean:
5579  {
5580  return lhs.m_value.boolean == rhs.m_value.boolean;
5581  }
5582  case value_t::number_integer:
5583  {
5584  return lhs.m_value.number_integer == rhs.m_value.number_integer;
5585  }
5586  case value_t::number_unsigned:
5587  {
5588  return lhs.m_value.number_unsigned == rhs.m_value.number_unsigned;
5589  }
5590  case value_t::number_float:
5591  {
5592  return lhs.m_value.number_float == rhs.m_value.number_float;
5593  }
5594  default:
5595  {
5596  return false;
5597  }
5598  }
5599  }
5600  else if (lhs_type == value_t::number_integer and rhs_type == value_t::number_float)
5601  {
5602  return static_cast<number_float_t>(lhs.m_value.number_integer) == rhs.m_value.number_float;
5603  }
5604  else if (lhs_type == value_t::number_float and rhs_type == value_t::number_integer)
5605  {
5606  return lhs.m_value.number_float == static_cast<number_float_t>(rhs.m_value.number_integer);
5607  }
5608  else if (lhs_type == value_t::number_unsigned and rhs_type == value_t::number_float)
5609  {
5610  return static_cast<number_float_t>(lhs.m_value.number_unsigned) == rhs.m_value.number_float;
5611  }
5612  else if (lhs_type == value_t::number_float and rhs_type == value_t::number_unsigned)
5613  {
5614  return lhs.m_value.number_float == static_cast<number_float_t>(rhs.m_value.number_unsigned);
5615  }
5616  else if (lhs_type == value_t::number_unsigned and rhs_type == value_t::number_integer)
5617  {
5618  return static_cast<number_integer_t>(lhs.m_value.number_unsigned) == rhs.m_value.number_integer;
5619  }
5620  else if (lhs_type == value_t::number_integer and rhs_type == value_t::number_unsigned)
5621  {
5622  return lhs.m_value.number_integer == static_cast<number_integer_t>(rhs.m_value.number_unsigned);
5623  }
5624 
5625  return false;
5626  }
5627 
5646  friend bool operator==(const_reference v, std::nullptr_t) noexcept
5647  {
5648  return v.is_null();
5649  }
5650 
5655  friend bool operator==(std::nullptr_t, const_reference v) noexcept
5656  {
5657  return v.is_null();
5658  }
5659 
5676  friend bool operator!=(const_reference lhs, const_reference rhs) noexcept
5677  {
5678  return not (lhs == rhs);
5679  }
5680 
5699  friend bool operator!=(const_reference v, std::nullptr_t) noexcept
5700  {
5701  return not v.is_null();
5702  }
5703 
5708  friend bool operator!=(std::nullptr_t, const_reference v) noexcept
5709  {
5710  return not v.is_null();
5711  }
5712 
5737  friend bool operator<(const_reference lhs, const_reference rhs) noexcept
5738  {
5739  const auto lhs_type = lhs.type();
5740  const auto rhs_type = rhs.type();
5741 
5742  if (lhs_type == rhs_type)
5743  {
5744  switch (lhs_type)
5745  {
5746  case value_t::array:
5747  {
5748  return *lhs.m_value.array < *rhs.m_value.array;
5749  }
5750  case value_t::object:
5751  {
5752  return *lhs.m_value.object < *rhs.m_value.object;
5753  }
5754  case value_t::null:
5755  {
5756  return false;
5757  }
5758  case value_t::string:
5759  {
5760  return *lhs.m_value.string < *rhs.m_value.string;
5761  }
5762  case value_t::boolean:
5763  {
5764  return lhs.m_value.boolean < rhs.m_value.boolean;
5765  }
5766  case value_t::number_integer:
5767  {
5768  return lhs.m_value.number_integer < rhs.m_value.number_integer;
5769  }
5770  case value_t::number_unsigned:
5771  {
5772  return lhs.m_value.number_unsigned < rhs.m_value.number_unsigned;
5773  }
5774  case value_t::number_float:
5775  {
5776  return lhs.m_value.number_float < rhs.m_value.number_float;
5777  }
5778  default:
5779  {
5780  return false;
5781  }
5782  }
5783  }
5784  else if (lhs_type == value_t::number_integer and rhs_type == value_t::number_float)
5785  {
5786  return static_cast<number_float_t>(lhs.m_value.number_integer) < rhs.m_value.number_float;
5787  }
5788  else if (lhs_type == value_t::number_float and rhs_type == value_t::number_integer)
5789  {
5790  return lhs.m_value.number_float < static_cast<number_float_t>(rhs.m_value.number_integer);
5791  }
5792  else if (lhs_type == value_t::number_unsigned and rhs_type == value_t::number_float)
5793  {
5794  return static_cast<number_float_t>(lhs.m_value.number_unsigned) < rhs.m_value.number_float;
5795  }
5796  else if (lhs_type == value_t::number_float and rhs_type == value_t::number_unsigned)
5797  {
5798  return lhs.m_value.number_float < static_cast<number_float_t>(rhs.m_value.number_unsigned);
5799  }
5800  else if (lhs_type == value_t::number_integer and rhs_type == value_t::number_unsigned)
5801  {
5802  return lhs.m_value.number_integer < static_cast<number_integer_t>(rhs.m_value.number_unsigned);
5803  }
5804  else if (lhs_type == value_t::number_unsigned and rhs_type == value_t::number_integer)
5805  {
5806  return static_cast<number_integer_t>(lhs.m_value.number_unsigned) < rhs.m_value.number_integer;
5807  }
5808 
5809  // We only reach this line if we cannot compare values. In that case,
5810  // we compare types. Note we have to call the operator explicitly,
5811  // because MSVC has problems otherwise.
5812  return operator<(lhs_type, rhs_type);
5813  }
5814 
5832  friend bool operator<=(const_reference lhs, const_reference rhs) noexcept
5833  {
5834  return not (rhs < lhs);
5835  }
5836 
5854  friend bool operator>(const_reference lhs, const_reference rhs) noexcept
5855  {
5856  return not (lhs <= rhs);
5857  }
5858 
5876  friend bool operator>=(const_reference lhs, const_reference rhs) noexcept
5877  {
5878  return not (lhs < rhs);
5879  }
5880 
5882 
5883 
5885  // serialization //
5887 
5890 
5917  friend std::ostream& operator<<(std::ostream& o, const basic_json& j)
5918  {
5919  // read width member and use it as indentation parameter if nonzero
5920  const bool pretty_print = (o.width() > 0);
5921  const auto indentation = (pretty_print ? o.width() : 0);
5922 
5923  // reset width to 0 for subsequent calls to this stream
5924  o.width(0);
5925 
5926  // fix locale problems
5927  const auto old_locale = o.imbue(std::locale::classic());
5928  // set precision
5929 
5930  // 6, 15 or 16 digits of precision allows round-trip IEEE 754
5931  // string->float->string, string->double->string or string->long
5932  // double->string; to be safe, we read this value from
5933  // std::numeric_limits<number_float_t>::digits10
5934  const auto old_precision = o.precision(std::numeric_limits<double>::digits10);
5935 
5936  // do the actual serialization
5937  j.dump(o, pretty_print, static_cast<unsigned int>(indentation));
5938 
5939  // reset locale and precision
5940  o.imbue(old_locale);
5941  o.precision(old_precision);
5942  return o;
5943  }
5944 
5949  friend std::ostream& operator>>(const basic_json& j, std::ostream& o)
5950  {
5951  return o << j;
5952  }
5953 
5955 
5956 
5958  // deserialization //
5960 
5963 
5991  template<class T, std::size_t N>
5992  static basic_json parse(T (&array)[N],
5993  const parser_callback_t cb = nullptr)
5994  {
5995  // delegate the call to the iterator-range parse overload
5996  return parse(std::begin(array), std::end(array), cb);
5997  }
5998 
6026  template<typename CharT, typename std::enable_if<
6027  std::is_pointer<CharT>::value and
6028  std::is_integral<typename std::remove_pointer<CharT>::type>::value and
6029  sizeof(typename std::remove_pointer<CharT>::type) == 1, int>::type = 0>
6030  static basic_json parse(const CharT s,
6031  const parser_callback_t cb = nullptr)
6032  {
6033  return parser(reinterpret_cast<const char*>(s), cb).parse();
6034  }
6035 
6060  static basic_json parse(std::istream& i,
6061  const parser_callback_t cb = nullptr)
6062  {
6063  return parser(i, cb).parse();
6064  }
6065 
6069  static basic_json parse(std::istream&& i,
6070  const parser_callback_t cb = nullptr)
6071  {
6072  return parser(i, cb).parse();
6073  }
6074 
6116  template<class IteratorType, typename std::enable_if<
6117  std::is_base_of<
6118  std::random_access_iterator_tag,
6119  typename std::iterator_traits<IteratorType>::iterator_category>::value, int>::type = 0>
6120  static basic_json parse(IteratorType first, IteratorType last,
6121  const parser_callback_t cb = nullptr)
6122  {
6123  // assertion to check that the iterator range is indeed contiguous,
6124  // see http://stackoverflow.com/a/35008842/266378 for more discussion
6125  assert(std::accumulate(first, last, std::make_pair<bool, int>(true, 0),
6126  [&first](std::pair<bool, int> res, decltype(*first) val)
6127  {
6128  res.first &= (val == *(std::next(std::addressof(*first), res.second++)));
6129  return res;
6130  }).first);
6131 
6132  // assertion to check that each element is 1 byte long
6133  static_assert(sizeof(typename std::iterator_traits<IteratorType>::value_type) == 1,
6134  "each element in the iterator range must have the size of 1 byte");
6135 
6136  // if iterator range is empty, create a parser with an empty string
6137  // to generate "unexpected EOF" error message
6138  if (std::distance(first, last) <= 0)
6139  {
6140  return parser("").parse();
6141  }
6142 
6143  return parser(first, last, cb).parse();
6144  }
6145 
6186  template<class ContiguousContainer, typename std::enable_if<
6187  not std::is_pointer<ContiguousContainer>::value and
6188  std::is_base_of<
6189  std::random_access_iterator_tag,
6190  typename std::iterator_traits<decltype(std::begin(std::declval<ContiguousContainer const>()))>::iterator_category>::value
6191  , int>::type = 0>
6192  static basic_json parse(const ContiguousContainer& c,
6193  const parser_callback_t cb = nullptr)
6194  {
6195  // delegate the call to the iterator-range parse overload
6196  return parse(std::begin(c), std::end(c), cb);
6197  }
6198 
6222  friend std::istream& operator<<(basic_json& j, std::istream& i)
6223  {
6224  j = parser(i).parse();
6225  return i;
6226  }
6227 
6232  friend std::istream& operator>>(std::istream& i, basic_json& j)
6233  {
6234  j = parser(i).parse();
6235  return i;
6236  }
6237 
6239 
6241  // binary serialization/deserialization //
6243 
6246 
6247  private:
6248  template<typename T>
6249  static void add_to_vector(std::vector<uint8_t>& vec, size_t bytes, const T number)
6250  {
6251  assert(bytes == 1 or bytes == 2 or bytes == 4 or bytes == 8);
6252 
6253  switch (bytes)
6254  {
6255  case 8:
6256  {
6257  vec.push_back(static_cast<uint8_t>((number >> 070) & 0xff));
6258  vec.push_back(static_cast<uint8_t>((number >> 060) & 0xff));
6259  vec.push_back(static_cast<uint8_t>((number >> 050) & 0xff));
6260  vec.push_back(static_cast<uint8_t>((number >> 040) & 0xff));
6261  // intentional fall-through
6262  }
6263 
6264  case 4:
6265  {
6266  vec.push_back(static_cast<uint8_t>((number >> 030) & 0xff));
6267  vec.push_back(static_cast<uint8_t>((number >> 020) & 0xff));
6268  // intentional fall-through
6269  }
6270 
6271  case 2:
6272  {
6273  vec.push_back(static_cast<uint8_t>((number >> 010) & 0xff));
6274  // intentional fall-through
6275  }
6276 
6277  case 1:
6278  {
6279  vec.push_back(static_cast<uint8_t>(number & 0xff));
6280  break;
6281  }
6282  }
6283  }
6284 
6321  template<typename T>
6322  static T get_from_vector(const std::vector<uint8_t>& vec, const size_t current_index)
6323  {
6324  if (current_index + sizeof(T) + 1 > vec.size())
6325  {
6326  throw std::out_of_range("cannot read " + std::to_string(sizeof(T)) + " bytes from vector");
6327  }
6328 
6329  T result;
6330  uint8_t* ptr = reinterpret_cast<uint8_t*>(&result);
6331  for (size_t i = 0; i < sizeof(T); ++i)
6332  {
6333  *ptr++ = vec[current_index + sizeof(T) - i];
6334  }
6335  return result;
6336  }
6337 
6348  static void to_msgpack_internal(const basic_json& j, std::vector<uint8_t>& v)
6349  {
6350  switch (j.type())
6351  {
6352  case value_t::null:
6353  {
6354  // nil
6355  v.push_back(0xc0);
6356  break;
6357  }
6358 
6359  case value_t::boolean:
6360  {
6361  // true and false
6362  v.push_back(j.m_value.boolean ? 0xc3 : 0xc2);
6363  break;
6364  }
6365 
6366  case value_t::number_integer:
6367  {
6368  if (j.m_value.number_integer >= 0)
6369  {
6370  // MessagePack does not differentiate between positive
6371  // signed integers and unsigned integers. Therefore, we used
6372  // the code from the value_t::number_unsigned case here.
6373  if (j.m_value.number_unsigned < 128)
6374  {
6375  // positive fixnum
6376  add_to_vector(v, 1, j.m_value.number_unsigned);
6377  }
6378  else if (j.m_value.number_unsigned <= UINT8_MAX)
6379  {
6380  // uint 8
6381  v.push_back(0xcc);
6382  add_to_vector(v, 1, j.m_value.number_unsigned);
6383  }
6384  else if (j.m_value.number_unsigned <= UINT16_MAX)
6385  {
6386  // uint 16
6387  v.push_back(0xcd);
6388  add_to_vector(v, 2, j.m_value.number_unsigned);
6389  }
6390  else if (j.m_value.number_unsigned <= UINT32_MAX)
6391  {
6392  // uint 32
6393  v.push_back(0xce);
6394  add_to_vector(v, 4, j.m_value.number_unsigned);
6395  }
6396  else if (j.m_value.number_unsigned <= UINT64_MAX)
6397  {
6398  // uint 64
6399  v.push_back(0xcf);
6400  add_to_vector(v, 8, j.m_value.number_unsigned);
6401  }
6402  }
6403  else
6404  {
6405  if (j.m_value.number_integer >= -32)
6406  {
6407  // negative fixnum
6408  add_to_vector(v, 1, j.m_value.number_integer);
6409  }
6410  else if (j.m_value.number_integer >= INT8_MIN and j.m_value.number_integer <= INT8_MAX)
6411  {
6412  // int 8
6413  v.push_back(0xd0);
6414  add_to_vector(v, 1, j.m_value.number_integer);
6415  }
6416  else if (j.m_value.number_integer >= INT16_MIN and j.m_value.number_integer <= INT16_MAX)
6417  {
6418  // int 16
6419  v.push_back(0xd1);
6420  add_to_vector(v, 2, j.m_value.number_integer);
6421  }
6422  else if (j.m_value.number_integer >= INT32_MIN and j.m_value.number_integer <= INT32_MAX)
6423  {
6424  // int 32
6425  v.push_back(0xd2);
6426  add_to_vector(v, 4, j.m_value.number_integer);
6427  }
6428  else if (j.m_value.number_integer >= INT64_MIN and j.m_value.number_integer <= INT64_MAX)
6429  {
6430  // int 64
6431  v.push_back(0xd3);
6432  add_to_vector(v, 8, j.m_value.number_integer);
6433  }
6434  }
6435  break;
6436  }
6437 
6438  case value_t::number_unsigned:
6439  {
6440  if (j.m_value.number_unsigned < 128)
6441  {
6442  // positive fixnum
6443  add_to_vector(v, 1, j.m_value.number_unsigned);
6444  }
6445  else if (j.m_value.number_unsigned <= UINT8_MAX)
6446  {
6447  // uint 8
6448  v.push_back(0xcc);
6449  add_to_vector(v, 1, j.m_value.number_unsigned);
6450  }
6451  else if (j.m_value.number_unsigned <= UINT16_MAX)
6452  {
6453  // uint 16
6454  v.push_back(0xcd);
6455  add_to_vector(v, 2, j.m_value.number_unsigned);
6456  }
6457  else if (j.m_value.number_unsigned <= UINT32_MAX)
6458  {
6459  // uint 32
6460  v.push_back(0xce);
6461  add_to_vector(v, 4, j.m_value.number_unsigned);
6462  }
6463  else if (j.m_value.number_unsigned <= UINT64_MAX)
6464  {
6465  // uint 64
6466  v.push_back(0xcf);
6467  add_to_vector(v, 8, j.m_value.number_unsigned);
6468  }
6469  break;
6470  }
6471 
6472  case value_t::number_float:
6473  {
6474  // float 64
6475  v.push_back(0xcb);
6476  const uint8_t* helper = reinterpret_cast<const uint8_t*>(&(j.m_value.number_float));
6477  for (size_t i = 0; i < 8; ++i)
6478  {
6479  v.push_back(helper[7 - i]);
6480  }
6481  break;
6482  }
6483 
6484  case value_t::string:
6485  {
6486  const auto N = j.m_value.string->size();
6487  if (N <= 31)
6488  {
6489  // fixstr
6490  v.push_back(static_cast<uint8_t>(0xa0 | N));
6491  }
6492  else if (N <= 255)
6493  {
6494  // str 8
6495  v.push_back(0xd9);
6496  add_to_vector(v, 1, N);
6497  }
6498  else if (N <= 65535)
6499  {
6500  // str 16
6501  v.push_back(0xda);
6502  add_to_vector(v, 2, N);
6503  }
6504  else if (N <= 4294967295)
6505  {
6506  // str 32
6507  v.push_back(0xdb);
6508  add_to_vector(v, 4, N);
6509  }
6510 
6511  // append string
6512  std::copy(j.m_value.string->begin(), j.m_value.string->end(),
6513  std::back_inserter(v));
6514  break;
6515  }
6516 
6517  case value_t::array:
6518  {
6519  const auto N = j.m_value.array->size();
6520  if (N <= 15)
6521  {
6522  // fixarray
6523  v.push_back(static_cast<uint8_t>(0x90 | N));
6524  }
6525  else if (N <= 0xffff)
6526  {
6527  // array 16
6528  v.push_back(0xdc);
6529  add_to_vector(v, 2, N);
6530  }
6531  else if (N <= 0xffffffff)
6532  {
6533  // array 32
6534  v.push_back(0xdd);
6535  add_to_vector(v, 4, N);
6536  }
6537 
6538  // append each element
6539  for (const auto& el : *j.m_value.array)
6540  {
6541  to_msgpack_internal(el, v);
6542  }
6543  break;
6544  }
6545 
6546  case value_t::object:
6547  {
6548  const auto N = j.m_value.object->size();
6549  if (N <= 15)
6550  {
6551  // fixmap
6552  v.push_back(static_cast<uint8_t>(0x80 | (N & 0xf)));
6553  }
6554  else if (N <= 65535)
6555  {
6556  // map 16
6557  v.push_back(0xde);
6558  add_to_vector(v, 2, N);
6559  }
6560  else if (N <= 4294967295)
6561  {
6562  // map 32
6563  v.push_back(0xdf);
6564  add_to_vector(v, 4, N);
6565  }
6566 
6567  // append each element
6568  for (const auto& el : *j.m_value.object)
6569  {
6570  to_msgpack_internal(el.first, v);
6571  to_msgpack_internal(el.second, v);
6572  }
6573  break;
6574  }
6575 
6576  default:
6577  {
6578  break;
6579  }
6580  }
6581  }
6582 
6593  static void to_cbor_internal(const basic_json& j, std::vector<uint8_t>& v)
6594  {
6595  switch (j.type())
6596  {
6597  case value_t::null:
6598  {
6599  v.push_back(0xf6);
6600  break;
6601  }
6602 
6603  case value_t::boolean:
6604  {
6605  v.push_back(j.m_value.boolean ? 0xf5 : 0xf4);
6606  break;
6607  }
6608 
6609  case value_t::number_integer:
6610  {
6611  if (j.m_value.number_integer >= 0)
6612  {
6613  // CBOR does not differentiate between positive signed
6614  // integers and unsigned integers. Therefore, we used the
6615  // code from the value_t::number_unsigned case here.
6616  if (j.m_value.number_integer <= 0x17)
6617  {
6618  add_to_vector(v, 1, j.m_value.number_integer);
6619  }
6620  else if (j.m_value.number_integer <= UINT8_MAX)
6621  {
6622  v.push_back(0x18);
6623  // one-byte uint8_t
6624  add_to_vector(v, 1, j.m_value.number_integer);
6625  }
6626  else if (j.m_value.number_integer <= UINT16_MAX)
6627  {
6628  v.push_back(0x19);
6629  // two-byte uint16_t
6630  add_to_vector(v, 2, j.m_value.number_integer);
6631  }
6632  else if (j.m_value.number_integer <= UINT32_MAX)
6633  {
6634  v.push_back(0x1a);
6635  // four-byte uint32_t
6636  add_to_vector(v, 4, j.m_value.number_integer);
6637  }
6638  else
6639  {
6640  v.push_back(0x1b);
6641  // eight-byte uint64_t
6642  add_to_vector(v, 8, j.m_value.number_integer);
6643  }
6644  }
6645  else
6646  {
6647  // The conversions below encode the sign in the first byte,
6648  // and the value is converted to a positive number.
6649  const auto positive_number = -1 - j.m_value.number_integer;
6650  if (j.m_value.number_integer >= -24)
6651  {
6652  v.push_back(static_cast<uint8_t>(0x20 + positive_number));
6653  }
6654  else if (positive_number <= UINT8_MAX)
6655  {
6656  // int 8
6657  v.push_back(0x38);
6658  add_to_vector(v, 1, positive_number);
6659  }
6660  else if (positive_number <= UINT16_MAX)
6661  {
6662  // int 16
6663  v.push_back(0x39);
6664  add_to_vector(v, 2, positive_number);
6665  }
6666  else if (positive_number <= UINT32_MAX)
6667  {
6668  // int 32
6669  v.push_back(0x3a);
6670  add_to_vector(v, 4, positive_number);
6671  }
6672  else
6673  {
6674  // int 64
6675  v.push_back(0x3b);
6676  add_to_vector(v, 8, positive_number);
6677  }
6678  }
6679  break;
6680  }
6681 
6682  case value_t::number_unsigned:
6683  {
6684  if (j.m_value.number_unsigned <= 0x17)
6685  {
6686  v.push_back(static_cast<uint8_t>(j.m_value.number_unsigned));
6687  }
6688  else if (j.m_value.number_unsigned <= 0xff)
6689  {
6690  v.push_back(0x18);
6691  // one-byte uint8_t
6692  add_to_vector(v, 1, j.m_value.number_unsigned);
6693  }
6694  else if (j.m_value.number_unsigned <= 0xffff)
6695  {
6696  v.push_back(0x19);
6697  // two-byte uint16_t
6698  add_to_vector(v, 2, j.m_value.number_unsigned);
6699  }
6700  else if (j.m_value.number_unsigned <= 0xffffffff)
6701  {
6702  v.push_back(0x1a);
6703  // four-byte uint32_t
6704  add_to_vector(v, 4, j.m_value.number_unsigned);
6705  }
6706  else if (j.m_value.number_unsigned <= 0xffffffffffffffff)
6707  {
6708  v.push_back(0x1b);
6709  // eight-byte uint64_t
6710  add_to_vector(v, 8, j.m_value.number_unsigned);
6711  }
6712  break;
6713  }
6714 
6715  case value_t::number_float:
6716  {
6717  // Double-Precision Float
6718  v.push_back(0xfb);
6719  const uint8_t* helper = reinterpret_cast<const uint8_t*>(&(j.m_value.number_float));
6720  for (size_t i = 0; i < 8; ++i)
6721  {
6722  v.push_back(helper[7 - i]);
6723  }
6724  break;
6725  }
6726 
6727  case value_t::string:
6728  {
6729  const auto N = j.m_value.string->size();
6730  if (N <= 0x17)
6731  {
6732  v.push_back(0x60 + N); // 1 byte for string + size
6733  }
6734  else if (N <= 0xff)
6735  {
6736  v.push_back(0x78); // one-byte uint8_t for N
6737  add_to_vector(v, 1, N);
6738  }
6739  else if (N <= 0xffff)
6740  {
6741  v.push_back(0x79); // two-byte uint16_t for N
6742  add_to_vector(v, 2, N);
6743  }
6744  else if (N <= 0xffffffff)
6745  {
6746  v.push_back(0x7a); // four-byte uint32_t for N
6747  add_to_vector(v, 4, N);
6748  }
6749  // LCOV_EXCL_START
6750  else if (N <= 0xffffffffffffffff)
6751  {
6752  v.push_back(0x7b); // eight-byte uint64_t for N
6753  add_to_vector(v, 8, N);
6754  }
6755  // LCOV_EXCL_STOP
6756 
6757  // append string
6758  std::copy(j.m_value.string->begin(), j.m_value.string->end(),
6759  std::back_inserter(v));
6760  break;
6761  }
6762 
6763  case value_t::array:
6764  {
6765  const auto N = j.m_value.array->size();
6766  if (N <= 0x17)
6767  {
6768  v.push_back(0x80 + N); // 1 byte for array + size
6769  }
6770  else if (N <= 0xff)
6771  {
6772  v.push_back(0x98); // one-byte uint8_t for N
6773  add_to_vector(v, 1, N);
6774  }
6775  else if (N <= 0xffff)
6776  {
6777  v.push_back(0x99); // two-byte uint16_t for N
6778  add_to_vector(v, 2, N);
6779  }
6780  else if (N <= 0xffffffff)
6781  {
6782  v.push_back(0x9a); // four-byte uint32_t for N
6783  add_to_vector(v, 4, N);
6784  }
6785  // LCOV_EXCL_START
6786  else if (N <= 0xffffffffffffffff)
6787  {
6788  v.push_back(0x9b); // eight-byte uint64_t for N
6789  add_to_vector(v, 8, N);
6790  }
6791  // LCOV_EXCL_STOP
6792 
6793  // append each element
6794  for (const auto& el : *j.m_value.array)
6795  {
6796  to_cbor_internal(el, v);
6797  }
6798  break;
6799  }
6800 
6801  case value_t::object:
6802  {
6803  const auto N = j.m_value.object->size();
6804  if (N <= 0x17)
6805  {
6806  v.push_back(0xa0 + N); // 1 byte for object + size
6807  }
6808  else if (N <= 0xff)
6809  {
6810  v.push_back(0xb8);
6811  add_to_vector(v, 1, N); // one-byte uint8_t for N
6812  }
6813  else if (N <= 0xffff)
6814  {
6815  v.push_back(0xb9);
6816  add_to_vector(v, 2, N); // two-byte uint16_t for N
6817  }
6818  else if (N <= 0xffffffff)
6819  {
6820  v.push_back(0xba);
6821  add_to_vector(v, 4, N); // four-byte uint32_t for N
6822  }
6823  // LCOV_EXCL_START
6824  else if (N <= 0xffffffffffffffff)
6825  {
6826  v.push_back(0xbb);
6827  add_to_vector(v, 8, N); // eight-byte uint64_t for N
6828  }
6829  // LCOV_EXCL_STOP
6830 
6831  // append each element
6832  for (const auto& el : *j.m_value.object)
6833  {
6834  to_cbor_internal(el.first, v);
6835  to_cbor_internal(el.second, v);
6836  }
6837  break;
6838  }
6839 
6840  default:
6841  {
6842  break;
6843  }
6844  }
6845  }
6846 
6847 
6848  /*
6849  @brief checks if given lengths do not exceed the size of a given vector
6850 
6851  To secure the access to the byte vector during CBOR/MessagePack
6852  deserialization, bytes are copied from the vector into buffers. This
6853  function checks if the number of bytes to copy (@a len) does not exceed the
6854  size @s size of the vector. Additionally, an @a offset is given from where
6855  to start reading the bytes.
6856 
6857  This function checks whether reading the bytes is safe; that is, offset is a
6858  valid index in the vector, offset+len
6859 
6860  @param[in] size size of the byte vector
6861  @param[in] len number of bytes to read
6862  @param[in] offset offset where to start reading
6863 
6864  vec: x x x x x X X X X X
6865  ^ ^ ^
6866  0 offset len
6867 
6868  @throws out_of_range if `len > v.size()`
6869  */
6870  static void check_length(const size_t size, const size_t len, const size_t offset)
6871  {
6872  // simple case: requested length is greater than the vector's length
6873  if (len > size or offset > size)
6874  {
6875  throw std::out_of_range("len out of range");
6876  }
6877 
6878  // second case: adding offset would result in overflow
6879  if ((size > (std::numeric_limits<size_t>::max() - offset)))
6880  {
6881  throw std::out_of_range("len+offset out of range");
6882  }
6883 
6884  // last case: reading past the end of the vector
6885  if (len + offset > size)
6886  {
6887  throw std::out_of_range("len+offset out of range");
6888  }
6889  }
6890 
6905  static basic_json from_msgpack_internal(const std::vector<uint8_t>& v, size_t& idx)
6906  {
6907  // make sure reading 1 byte is safe
6908  check_length(v.size(), 1, idx);
6909 
6910  // store and increment index
6911  const size_t current_idx = idx++;
6912 
6913  if (v[current_idx] <= 0xbf)
6914  {
6915  if (v[current_idx] <= 0x7f) // positive fixint
6916  {
6917  return v[current_idx];
6918  }
6919  else if (v[current_idx] <= 0x8f) // fixmap
6920  {
6921  basic_json result = value_t::object;
6922  const size_t len = v[current_idx] & 0x0f;
6923  for (size_t i = 0; i < len; ++i)
6924  {
6925  std::string key = from_msgpack_internal(v, idx);
6926  result[key] = from_msgpack_internal(v, idx);
6927  }
6928  return result;
6929  }
6930  else if (v[current_idx] <= 0x9f) // fixarray
6931  {
6932  basic_json result = value_t::array;
6933  const size_t len = v[current_idx] & 0x0f;
6934  for (size_t i = 0; i < len; ++i)
6935  {
6936  result.push_back(from_msgpack_internal(v, idx));
6937  }
6938  return result;
6939  }
6940  else // fixstr
6941  {
6942  const size_t len = v[current_idx] & 0x1f;
6943  const size_t offset = current_idx + 1;
6944  idx += len; // skip content bytes
6945  check_length(v.size(), len, offset);
6946  return std::string(reinterpret_cast<const char*>(v.data()) + offset, len);
6947  }
6948  }
6949  else if (v[current_idx] >= 0xe0) // negative fixint
6950  {
6951  return static_cast<int8_t>(v[current_idx]);
6952  }
6953  else
6954  {
6955  switch (v[current_idx])
6956  {
6957  case 0xc0: // nil
6958  {
6959  return value_t::null;
6960  }
6961 
6962  case 0xc2: // false
6963  {
6964  return false;
6965  }
6966 
6967  case 0xc3: // true
6968  {
6969  return true;
6970  }
6971 
6972  case 0xca: // float 32
6973  {
6974  // copy bytes in reverse order into the double variable
6975  check_length(v.size(), sizeof(float), 1);
6976  float res;
6977  for (size_t byte = 0; byte < sizeof(float); ++byte)
6978  {
6979  reinterpret_cast<uint8_t*>(&res)[sizeof(float) - byte - 1] = v[current_idx + 1 + byte];
6980  }
6981  idx += sizeof(float); // skip content bytes
6982  return res;
6983  }
6984 
6985  case 0xcb: // float 64
6986  {
6987  // copy bytes in reverse order into the double variable
6988  check_length(v.size(), sizeof(double), 1);
6989  double res;
6990  for (size_t byte = 0; byte < sizeof(double); ++byte)
6991  {
6992  reinterpret_cast<uint8_t*>(&res)[sizeof(double) - byte - 1] = v[current_idx + 1 + byte];
6993  }
6994  idx += sizeof(double); // skip content bytes
6995  return res;
6996  }
6997 
6998  case 0xcc: // uint 8
6999  {
7000  idx += 1; // skip content byte
7001  return get_from_vector<uint8_t>(v, current_idx);
7002  }
7003 
7004  case 0xcd: // uint 16
7005  {
7006  idx += 2; // skip 2 content bytes
7007  return get_from_vector<uint16_t>(v, current_idx);
7008  }
7009 
7010  case 0xce: // uint 32
7011  {
7012  idx += 4; // skip 4 content bytes
7013  return get_from_vector<uint32_t>(v, current_idx);
7014  }
7015 
7016  case 0xcf: // uint 64
7017  {
7018  idx += 8; // skip 8 content bytes
7019  return get_from_vector<uint64_t>(v, current_idx);
7020  }
7021 
7022  case 0xd0: // int 8
7023  {
7024  idx += 1; // skip content byte
7025  return get_from_vector<int8_t>(v, current_idx);
7026  }
7027 
7028  case 0xd1: // int 16
7029  {
7030  idx += 2; // skip 2 content bytes
7031  return get_from_vector<int16_t>(v, current_idx);
7032  }
7033 
7034  case 0xd2: // int 32
7035  {
7036  idx += 4; // skip 4 content bytes
7037  return get_from_vector<int32_t>(v, current_idx);
7038  }
7039 
7040  case 0xd3: // int 64
7041  {
7042  idx += 8; // skip 8 content bytes
7043  return get_from_vector<int64_t>(v, current_idx);
7044  }
7045 
7046  case 0xd9: // str 8
7047  {
7048  const auto len = static_cast<size_t>(get_from_vector<uint8_t>(v, current_idx));
7049  const size_t offset = current_idx + 2;
7050  idx += len + 1; // skip size byte + content bytes
7051  check_length(v.size(), len, offset);
7052  return std::string(reinterpret_cast<const char*>(v.data()) + offset, len);
7053  }
7054 
7055  case 0xda: // str 16
7056  {
7057  const auto len = static_cast<size_t>(get_from_vector<uint16_t>(v, current_idx));
7058  const size_t offset = current_idx + 3;
7059  idx += len + 2; // skip 2 size bytes + content bytes
7060  check_length(v.size(), len, offset);
7061  return std::string(reinterpret_cast<const char*>(v.data()) + offset, len);
7062  }
7063 
7064  case 0xdb: // str 32
7065  {
7066  const auto len = static_cast<size_t>(get_from_vector<uint32_t>(v, current_idx));
7067  const size_t offset = current_idx + 5;
7068  idx += len + 4; // skip 4 size bytes + content bytes
7069  check_length(v.size(), len, offset);
7070  return std::string(reinterpret_cast<const char*>(v.data()) + offset, len);
7071  }
7072 
7073  case 0xdc: // array 16
7074  {
7075  basic_json result = value_t::array;
7076  const auto len = static_cast<size_t>(get_from_vector<uint16_t>(v, current_idx));
7077  idx += 2; // skip 2 size bytes
7078  for (size_t i = 0; i < len; ++i)
7079  {
7080  result.push_back(from_msgpack_internal(v, idx));
7081  }
7082  return result;
7083  }
7084 
7085  case 0xdd: // array 32
7086  {
7087  basic_json result = value_t::array;
7088  const auto len = static_cast<size_t>(get_from_vector<uint32_t>(v, current_idx));
7089  idx += 4; // skip 4 size bytes
7090  for (size_t i = 0; i < len; ++i)
7091  {
7092  result.push_back(from_msgpack_internal(v, idx));
7093  }
7094  return result;
7095  }
7096 
7097  case 0xde: // map 16
7098  {
7099  basic_json result = value_t::object;
7100  const auto len = static_cast<size_t>(get_from_vector<uint16_t>(v, current_idx));
7101  idx += 2; // skip 2 size bytes
7102  for (size_t i = 0; i < len; ++i)
7103  {
7104  std::string key = from_msgpack_internal(v, idx);
7105  result[key] = from_msgpack_internal(v, idx);
7106  }
7107  return result;
7108  }
7109 
7110  case 0xdf: // map 32
7111  {
7112  basic_json result = value_t::object;
7113  const auto len = static_cast<size_t>(get_from_vector<uint32_t>(v, current_idx));
7114  idx += 4; // skip 4 size bytes
7115  for (size_t i = 0; i < len; ++i)
7116  {
7117  std::string key = from_msgpack_internal(v, idx);
7118  result[key] = from_msgpack_internal(v, idx);
7119  }
7120  return result;
7121  }
7122 
7123  default:
7124  {
7125  throw std::invalid_argument("error parsing a msgpack @ " + std::to_string(current_idx) + ": " + std::to_string(static_cast<int>(v[current_idx])));
7126  }
7127  }
7128  }
7129  }
7130 
7145  static basic_json from_cbor_internal(const std::vector<uint8_t>& v, size_t& idx)
7146  {
7147  // store and increment index
7148  const size_t current_idx = idx++;
7149 
7150  switch (v.at(current_idx))
7151  {
7152  // Integer 0x00..0x17 (0..23)
7153  case 0x00:
7154  case 0x01:
7155  case 0x02:
7156  case 0x03:
7157  case 0x04:
7158  case 0x05:
7159  case 0x06:
7160  case 0x07:
7161  case 0x08:
7162  case 0x09:
7163  case 0x0a:
7164  case 0x0b:
7165  case 0x0c:
7166  case 0x0d:
7167  case 0x0e:
7168  case 0x0f:
7169  case 0x10:
7170  case 0x11:
7171  case 0x12:
7172  case 0x13:
7173  case 0x14:
7174  case 0x15:
7175  case 0x16:
7176  case 0x17:
7177  {
7178  return v[current_idx];
7179  }
7180 
7181  case 0x18: // Unsigned integer (one-byte uint8_t follows)
7182  {
7183  idx += 1; // skip content byte
7184  return get_from_vector<uint8_t>(v, current_idx);
7185  }
7186 
7187  case 0x19: // Unsigned integer (two-byte uint16_t follows)
7188  {
7189  idx += 2; // skip 2 content bytes
7190  return get_from_vector<uint16_t>(v, current_idx);
7191  }
7192 
7193  case 0x1a: // Unsigned integer (four-byte uint32_t follows)
7194  {
7195  idx += 4; // skip 4 content bytes
7196  return get_from_vector<uint32_t>(v, current_idx);
7197  }
7198 
7199  case 0x1b: // Unsigned integer (eight-byte uint64_t follows)
7200  {
7201  idx += 8; // skip 8 content bytes
7202  return get_from_vector<uint64_t>(v, current_idx);
7203  }
7204 
7205  // Negative integer -1-0x00..-1-0x17 (-1..-24)
7206  case 0x20:
7207  case 0x21:
7208  case 0x22:
7209  case 0x23:
7210  case 0x24:
7211  case 0x25:
7212  case 0x26:
7213  case 0x27:
7214  case 0x28:
7215  case 0x29:
7216  case 0x2a:
7217  case 0x2b:
7218  case 0x2c:
7219  case 0x2d:
7220  case 0x2e:
7221  case 0x2f:
7222  case 0x30:
7223  case 0x31:
7224  case 0x32:
7225  case 0x33:
7226  case 0x34:
7227  case 0x35:
7228  case 0x36:
7229  case 0x37:
7230  {
7231  return static_cast<int8_t>(0x20 - 1 - v[current_idx]);
7232  }
7233 
7234  case 0x38: // Negative integer (one-byte uint8_t follows)
7235  {
7236  idx += 1; // skip content byte
7237  // must be uint8_t !
7238  return static_cast<number_integer_t>(-1) - get_from_vector<uint8_t>(v, current_idx);
7239  }
7240 
7241  case 0x39: // Negative integer -1-n (two-byte uint16_t follows)
7242  {
7243  idx += 2; // skip 2 content bytes
7244  return static_cast<number_integer_t>(-1) - get_from_vector<uint16_t>(v, current_idx);
7245  }
7246 
7247  case 0x3a: // Negative integer -1-n (four-byte uint32_t follows)
7248  {
7249  idx += 4; // skip 4 content bytes
7250  return static_cast<number_integer_t>(-1) - get_from_vector<uint32_t>(v, current_idx);
7251  }
7252 
7253  case 0x3b: // Negative integer -1-n (eight-byte uint64_t follows)
7254  {
7255  idx += 8; // skip 8 content bytes
7256  return static_cast<number_integer_t>(-1) - static_cast<number_integer_t>(get_from_vector<uint64_t>(v, current_idx));
7257  }
7258 
7259  // UTF-8 string (0x00..0x17 bytes follow)
7260  case 0x60:
7261  case 0x61:
7262  case 0x62:
7263  case 0x63:
7264  case 0x64:
7265  case 0x65:
7266  case 0x66:
7267  case 0x67:
7268  case 0x68:
7269  case 0x69:
7270  case 0x6a:
7271  case 0x6b:
7272  case 0x6c:
7273  case 0x6d:
7274  case 0x6e:
7275  case 0x6f:
7276  case 0x70:
7277  case 0x71:
7278  case 0x72:
7279  case 0x73:
7280  case 0x74:
7281  case 0x75:
7282  case 0x76:
7283  case 0x77:
7284  {
7285  const auto len = static_cast<size_t>(v[current_idx] - 0x60);
7286  const size_t offset = current_idx + 1;
7287  idx += len; // skip content bytes
7288  check_length(v.size(), len, offset);
7289  return std::string(reinterpret_cast<const char*>(v.data()) + offset, len);
7290  }
7291 
7292  case 0x78: // UTF-8 string (one-byte uint8_t for n follows)
7293  {
7294  const auto len = static_cast<size_t>(get_from_vector<uint8_t>(v, current_idx));
7295  const size_t offset = current_idx + 2;
7296  idx += len + 1; // skip size byte + content bytes
7297  check_length(v.size(), len, offset);
7298  return std::string(reinterpret_cast<const char*>(v.data()) + offset, len);
7299  }
7300 
7301  case 0x79: // UTF-8 string (two-byte uint16_t for n follow)
7302  {
7303  const auto len = static_cast<size_t>(get_from_vector<uint16_t>(v, current_idx));
7304  const size_t offset = current_idx + 3;
7305  idx += len + 2; // skip 2 size bytes + content bytes
7306  check_length(v.size(), len, offset);
7307  return std::string(reinterpret_cast<const char*>(v.data()) + offset, len);
7308  }
7309 
7310  case 0x7a: // UTF-8 string (four-byte uint32_t for n follow)
7311  {
7312  const auto len = static_cast<size_t>(get_from_vector<uint32_t>(v, current_idx));
7313  const size_t offset = current_idx + 5;
7314  idx += len + 4; // skip 4 size bytes + content bytes
7315  check_length(v.size(), len, offset);
7316  return std::string(reinterpret_cast<const char*>(v.data()) + offset, len);
7317  }
7318 
7319  case 0x7b: // UTF-8 string (eight-byte uint64_t for n follow)
7320  {
7321  const auto len = static_cast<size_t>(get_from_vector<uint64_t>(v, current_idx));
7322  const size_t offset = current_idx + 9;
7323  idx += len + 8; // skip 8 size bytes + content bytes
7324  check_length(v.size(), len, offset);
7325  return std::string(reinterpret_cast<const char*>(v.data()) + offset, len);
7326  }
7327 
7328  case 0x7f: // UTF-8 string (indefinite length)
7329  {
7330  std::string result;
7331  while (v.at(idx) != 0xff)
7332  {
7333  string_t s = from_cbor_internal(v, idx);
7334  result += s;
7335  }
7336  // skip break byte (0xFF)
7337  idx += 1;
7338  return result;
7339  }
7340 
7341  // array (0x00..0x17 data items follow)
7342  case 0x80:
7343  case 0x81:
7344  case 0x82:
7345  case 0x83:
7346  case 0x84:
7347  case 0x85:
7348  case 0x86:
7349  case 0x87:
7350  case 0x88:
7351  case 0x89:
7352  case 0x8a:
7353  case 0x8b:
7354  case 0x8c:
7355  case 0x8d:
7356  case 0x8e:
7357  case 0x8f:
7358  case 0x90:
7359  case 0x91:
7360  case 0x92:
7361  case 0x93:
7362  case 0x94:
7363  case 0x95:
7364  case 0x96:
7365  case 0x97:
7366  {
7367  basic_json result = value_t::array;
7368  const auto len = static_cast<size_t>(v[current_idx] - 0x80);
7369  for (size_t i = 0; i < len; ++i)
7370  {
7371  result.push_back(from_cbor_internal(v, idx));
7372  }
7373  return result;
7374  }
7375 
7376  case 0x98: // array (one-byte uint8_t for n follows)
7377  {
7378  basic_json result = value_t::array;
7379  const auto len = static_cast<size_t>(get_from_vector<uint8_t>(v, current_idx));
7380  idx += 1; // skip 1 size byte
7381  for (size_t i = 0; i < len; ++i)
7382  {
7383  result.push_back(from_cbor_internal(v, idx));
7384  }
7385  return result;
7386  }
7387 
7388  case 0x99: // array (two-byte uint16_t for n follow)
7389  {
7390  basic_json result = value_t::array;
7391  const auto len = static_cast<size_t>(get_from_vector<uint16_t>(v, current_idx));
7392  idx += 2; // skip 4 size bytes
7393  for (size_t i = 0; i < len; ++i)
7394  {
7395  result.push_back(from_cbor_internal(v, idx));
7396  }
7397  return result;
7398  }
7399 
7400  case 0x9a: // array (four-byte uint32_t for n follow)
7401  {
7402  basic_json result = value_t::array;
7403  const auto len = static_cast<size_t>(get_from_vector<uint32_t>(v, current_idx));
7404  idx += 4; // skip 4 size bytes
7405  for (size_t i = 0; i < len; ++i)
7406  {
7407  result.push_back(from_cbor_internal(v, idx));
7408  }
7409  return result;
7410  }
7411 
7412  case 0x9b: // array (eight-byte uint64_t for n follow)
7413  {
7414  basic_json result = value_t::array;
7415  const auto len = static_cast<size_t>(get_from_vector<uint64_t>(v, current_idx));
7416  idx += 8; // skip 8 size bytes
7417  for (size_t i = 0; i < len; ++i)
7418  {
7419  result.push_back(from_cbor_internal(v, idx));
7420  }
7421  return result;
7422  }
7423 
7424  case 0x9f: // array (indefinite length)
7425  {
7426  basic_json result = value_t::array;
7427  while (v.at(idx) != 0xff)
7428  {
7429  result.push_back(from_cbor_internal(v, idx));
7430  }
7431  // skip break byte (0xFF)
7432  idx += 1;
7433  return result;
7434  }
7435 
7436  // map (0x00..0x17 pairs of data items follow)
7437  case 0xa0:
7438  case 0xa1:
7439  case 0xa2:
7440  case 0xa3:
7441  case 0xa4:
7442  case 0xa5:
7443  case 0xa6:
7444  case 0xa7:
7445  case 0xa8:
7446  case 0xa9:
7447  case 0xaa:
7448  case 0xab:
7449  case 0xac:
7450  case 0xad:
7451  case 0xae:
7452  case 0xaf:
7453  case 0xb0:
7454  case 0xb1:
7455  case 0xb2:
7456  case 0xb3:
7457  case 0xb4:
7458  case 0xb5:
7459  case 0xb6:
7460  case 0xb7:
7461  {
7462  basic_json result = value_t::object;
7463  const auto len = static_cast<size_t>(v[current_idx] - 0xa0);
7464  for (size_t i = 0; i < len; ++i)
7465  {
7466  std::string key = from_cbor_internal(v, idx);
7467  result[key] = from_cbor_internal(v, idx);
7468  }
7469  return result;
7470  }
7471 
7472  case 0xb8: // map (one-byte uint8_t for n follows)
7473  {
7474  basic_json result = value_t::object;
7475  const auto len = static_cast<size_t>(get_from_vector<uint8_t>(v, current_idx));
7476  idx += 1; // skip 1 size byte
7477  for (size_t i = 0; i < len; ++i)
7478  {
7479  std::string key = from_cbor_internal(v, idx);
7480  result[key] = from_cbor_internal(v, idx);
7481  }
7482  return result;
7483  }
7484 
7485  case 0xb9: // map (two-byte uint16_t for n follow)
7486  {
7487  basic_json result = value_t::object;
7488  const auto len = static_cast<size_t>(get_from_vector<uint16_t>(v, current_idx));
7489  idx += 2; // skip 2 size bytes
7490  for (size_t i = 0; i < len; ++i)
7491  {
7492  std::string key = from_cbor_internal(v, idx);
7493  result[key] = from_cbor_internal(v, idx);
7494  }
7495  return result;
7496  }
7497 
7498  case 0xba: // map (four-byte uint32_t for n follow)
7499  {
7500  basic_json result = value_t::object;
7501  const auto len = static_cast<size_t>(get_from_vector<uint32_t>(v, current_idx));
7502  idx += 4; // skip 4 size bytes
7503  for (size_t i = 0; i < len; ++i)
7504  {
7505  std::string key = from_cbor_internal(v, idx);
7506  result[key] = from_cbor_internal(v, idx);
7507  }
7508  return result;
7509  }
7510 
7511  case 0xbb: // map (eight-byte uint64_t for n follow)
7512  {
7513  basic_json result = value_t::object;
7514  const auto len = static_cast<size_t>(get_from_vector<uint64_t>(v, current_idx));
7515  idx += 8; // skip 8 size bytes
7516  for (size_t i = 0; i < len; ++i)
7517  {
7518  std::string key = from_cbor_internal(v, idx);
7519  result[key] = from_cbor_internal(v, idx);
7520  }
7521  return result;
7522  }
7523 
7524  case 0xbf: // map (indefinite length)
7525  {
7526  basic_json result = value_t::object;
7527  while (v.at(idx) != 0xff)
7528  {
7529  std::string key = from_cbor_internal(v, idx);
7530  result[key] = from_cbor_internal(v, idx);
7531  }
7532  // skip break byte (0xFF)
7533  idx += 1;
7534  return result;
7535  }
7536 
7537  case 0xf4: // false
7538  {
7539  return false;
7540  }
7541 
7542  case 0xf5: // true
7543  {
7544  return true;
7545  }
7546 
7547  case 0xf6: // null
7548  {
7549  return value_t::null;
7550  }
7551 
7552  case 0xf9: // Half-Precision Float (two-byte IEEE 754)
7553  {
7554  check_length(v.size(), 2, 1);
7555  idx += 2; // skip two content bytes
7556 
7557  // code from RFC 7049, Appendix D, Figure 3:
7558  // As half-precision floating-point numbers were only added to
7559  // IEEE 754 in 2008, today's programming platforms often still
7560  // only have limited support for them. It is very easy to
7561  // include at least decoding support for them even without such
7562  // support. An example of a small decoder for half-precision
7563  // floating-point numbers in the C language is shown in Fig. 3.
7564  const int half = (v[current_idx + 1] << 8) + v[current_idx + 2];
7565  const int exp = (half >> 10) & 0x1f;
7566  const int mant = half & 0x3ff;
7567  double val;
7568  if (exp == 0)
7569  {
7570  val = std::ldexp(mant, -24);
7571  }
7572  else if (exp != 31)
7573  {
7574  val = std::ldexp(mant + 1024, exp - 25);
7575  }
7576  else
7577  {
7578  val = mant == 0 ? INFINITY : NAN;
7579  }
7580  return half & 0x8000 ? -val : val;
7581  }
7582 
7583  case 0xfa: // Single-Precision Float (four-byte IEEE 754)
7584  {
7585  // copy bytes in reverse order into the float variable
7586  check_length(v.size(), sizeof(float), 1);
7587  float res;
7588  for (size_t byte = 0; byte < sizeof(float); ++byte)
7589  {
7590  reinterpret_cast<uint8_t*>(&res)[sizeof(float) - byte - 1] = v[current_idx + 1 + byte];
7591  }
7592  idx += sizeof(float); // skip content bytes
7593  return res;
7594  }
7595 
7596  case 0xfb: // Double-Precision Float (eight-byte IEEE 754)
7597  {
7598  check_length(v.size(), sizeof(double), 1);
7599  // copy bytes in reverse order into the double variable
7600  double res;
7601  for (size_t byte = 0; byte < sizeof(double); ++byte)
7602  {
7603  reinterpret_cast<uint8_t*>(&res)[sizeof(double) - byte - 1] = v[current_idx + 1 + byte];
7604  }
7605  idx += sizeof(double); // skip content bytes
7606  return res;
7607  }
7608 
7609  default: // anything else (0xFF is handled inside the other types)
7610  {
7611  throw std::invalid_argument("error parsing a CBOR @ " + std::to_string(current_idx) + ": " + std::to_string(static_cast<int>(v[current_idx])));
7612  }
7613  }
7614  }
7615 
7616  public:
7637  static std::vector<uint8_t> to_msgpack(const basic_json& j)
7638  {
7639  std::vector<uint8_t> result;
7640  to_msgpack_internal(j, result);
7641  return result;
7642  }
7643 
7666  static basic_json from_msgpack(const std::vector<uint8_t>& v)
7667  {
7668  size_t i = 0;
7669  return from_msgpack_internal(v, i);
7670  }
7671 
7693  static std::vector<uint8_t> to_cbor(const basic_json& j)
7694  {
7695  std::vector<uint8_t> result;
7696  to_cbor_internal(j, result);
7697  return result;
7698  }
7699 
7723  static basic_json from_cbor(const std::vector<uint8_t>& v)
7724  {
7725  size_t i = 0;
7726  return from_cbor_internal(v, i);
7727  }
7728 
7730 
7731  private:
7733  // convenience functions //
7735 
7748  std::string type_name() const
7749  {
7750  switch (m_type)
7751  {
7752  case value_t::null:
7753  return "null";
7754  case value_t::object:
7755  return "object";
7756  case value_t::array:
7757  return "array";
7758  case value_t::string:
7759  return "string";
7760  case value_t::boolean:
7761  return "boolean";
7762  case value_t::discarded:
7763  return "discarded";
7764  default:
7765  return "number";
7766  }
7767  }
7768 
7777  static std::size_t extra_space(const string_t& s) noexcept
7778  {
7779  return std::accumulate(s.begin(), s.end(), size_t{},
7780  [](size_t res, typename string_t::value_type c)
7781  {
7782  switch (c)
7783  {
7784  case '"':
7785  case '\\':
7786  case '\b':
7787  case '\f':
7788  case '\n':
7789  case '\r':
7790  case '\t':
7791  {
7792  // from c (1 byte) to \x (2 bytes)
7793  return res + 1;
7794  }
7795 
7796  default:
7797  {
7798  if (c >= 0x00 and c <= 0x1f)
7799  {
7800  // from c (1 byte) to \uxxxx (6 bytes)
7801  return res + 5;
7802  }
7803  else
7804  {
7805  return res;
7806  }
7807  }
7808  }
7809  });
7810  }
7811 
7825  static string_t escape_string(const string_t& s)
7826  {
7827  const auto space = extra_space(s);
7828  if (space == 0)
7829  {
7830  return s;
7831  }
7832 
7833  // create a result string of necessary size
7834  string_t result(s.size() + space, '\\');
7835  std::size_t pos = 0;
7836 
7837  for (const auto& c : s)
7838  {
7839  switch (c)
7840  {
7841  // quotation mark (0x22)
7842  case '"':
7843  {
7844  result[pos + 1] = '"';
7845  pos += 2;
7846  break;
7847  }
7848 
7849  // reverse solidus (0x5c)
7850  case '\\':
7851  {
7852  // nothing to change
7853  pos += 2;
7854  break;
7855  }
7856 
7857  // backspace (0x08)
7858  case '\b':
7859  {
7860  result[pos + 1] = 'b';
7861  pos += 2;
7862  break;
7863  }
7864 
7865  // formfeed (0x0c)
7866  case '\f':
7867  {
7868  result[pos + 1] = 'f';
7869  pos += 2;
7870  break;
7871  }
7872 
7873  // newline (0x0a)
7874  case '\n':
7875  {
7876  result[pos + 1] = 'n';
7877  pos += 2;
7878  break;
7879  }
7880 
7881  // carriage return (0x0d)
7882  case '\r':
7883  {
7884  result[pos + 1] = 'r';
7885  pos += 2;
7886  break;
7887  }
7888 
7889  // horizontal tab (0x09)
7890  case '\t':
7891  {
7892  result[pos + 1] = 't';
7893  pos += 2;
7894  break;
7895  }
7896 
7897  default:
7898  {
7899  if (c >= 0x00 and c <= 0x1f)
7900  {
7901  // convert a number 0..15 to its hex representation
7902  // (0..f)
7903  static const char hexify[16] =
7904  {
7905  '0', '1', '2', '3', '4', '5', '6', '7',
7906  '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'
7907  };
7908 
7909  // print character c as \uxxxx
7910  for (const char m :
7911  { 'u', '0', '0', hexify[c >> 4], hexify[c & 0x0f]
7912  })
7913  {
7914  result[++pos] = m;
7915  }
7916 
7917  ++pos;
7918  }
7919  else
7920  {
7921  // all other characters are added as-is
7922  result[pos++] = c;
7923  }
7924  break;
7925  }
7926  }
7927  }
7928 
7929  return result;
7930  }
7931 
7949  void dump(std::ostream& o,
7950  const bool pretty_print,
7951  const unsigned int indent_step,
7952  const unsigned int current_indent = 0) const
7953  {
7954  // variable to hold indentation for recursive calls
7955  unsigned int new_indent = current_indent;
7956 
7957  switch (m_type)
7958  {
7959  case value_t::object:
7960  {
7961  if (m_value.object->empty())
7962  {
7963  o << "{}";
7964  return;
7965  }
7966 
7967  o << "{";
7968 
7969  // increase indentation
7970  if (pretty_print)
7971  {
7972  new_indent += indent_step;
7973  o << "\n";
7974  }
7975 
7976  for (auto i = m_value.object->cbegin(); i != m_value.object->cend(); ++i)
7977  {
7978  if (i != m_value.object->cbegin())
7979  {
7980  o << (pretty_print ? ",\n" : ",");
7981  }
7982  o << string_t(new_indent, ' ') << "\""
7983  << escape_string(i->first) << "\":"
7984  << (pretty_print ? " " : "");
7985  i->second.dump(o, pretty_print, indent_step, new_indent);
7986  }
7987 
7988  // decrease indentation
7989  if (pretty_print)
7990  {
7991  new_indent -= indent_step;
7992  o << "\n";
7993  }
7994 
7995  o << string_t(new_indent, ' ') + "}";
7996  return;
7997  }
7998 
7999  case value_t::array:
8000  {
8001  if (m_value.array->empty())
8002  {
8003  o << "[]";
8004  return;
8005  }
8006 
8007  o << "[";
8008 
8009  // increase indentation
8010  if (pretty_print)
8011  {
8012  new_indent += indent_step;
8013  o << "\n";
8014  }
8015 
8016  for (auto i = m_value.array->cbegin(); i != m_value.array->cend(); ++i)
8017  {
8018  if (i != m_value.array->cbegin())
8019  {
8020  o << (pretty_print ? ",\n" : ",");
8021  }
8022  o << string_t(new_indent, ' ');
8023  i->dump(o, pretty_print, indent_step, new_indent);
8024  }
8025 
8026  // decrease indentation
8027  if (pretty_print)
8028  {
8029  new_indent -= indent_step;
8030  o << "\n";
8031  }
8032 
8033  o << string_t(new_indent, ' ') << "]";
8034  return;
8035  }
8036 
8037  case value_t::string:
8038  {
8039  o << string_t("\"") << escape_string(*m_value.string) << "\"";
8040  return;
8041  }
8042 
8043  case value_t::boolean:
8044  {
8045  o << (m_value.boolean ? "true" : "false");
8046  return;
8047  }
8048 
8049  case value_t::number_integer:
8050  {
8051  o << m_value.number_integer;
8052  return;
8053  }
8054 
8055  case value_t::number_unsigned:
8056  {
8057  o << m_value.number_unsigned;
8058  return;
8059  }
8060 
8061  case value_t::number_float:
8062  {
8063  if (m_value.number_float == 0)
8064  {
8065  // special case for zero to get "0.0"/"-0.0"
8066  o << (std::signbit(m_value.number_float) ? "-0.0" : "0.0");
8067  }
8068  else
8069  {
8070  o << m_value.number_float;
8071  }
8072  return;
8073  }
8074 
8075  case value_t::discarded:
8076  {
8077  o << "<discarded>";
8078  return;
8079  }
8080 
8081  case value_t::null:
8082  {
8083  o << "null";
8084  return;
8085  }
8086  }
8087  }
8088 
8089  private:
8091  // member variables //
8093 
8095  value_t m_type = value_t::null;
8096 
8098  json_value m_value = {};
8099 
8100 
8101  private:
8103  // iterators //
8105 
8115  class primitive_iterator_t
8116  {
8117  public:
8119  void set_begin() noexcept
8120  {
8121  m_it = begin_value;
8122  }
8123 
8125  void set_end() noexcept
8126  {
8127  m_it = end_value;
8128  }
8129 
8131  constexpr bool is_begin() const noexcept
8132  {
8133  return (m_it == begin_value);
8134  }
8135 
8137  constexpr bool is_end() const noexcept
8138  {
8139  return (m_it == end_value);
8140  }
8141 
8143  operator difference_type& () noexcept
8144  {
8145  return m_it;
8146  }
8147 
8149  constexpr operator difference_type () const noexcept
8150  {
8151  return m_it;
8152  }
8153 
8154  private:
8155  static constexpr difference_type begin_value = 0;
8156  static constexpr difference_type end_value = begin_value + 1;
8157 
8159  difference_type m_it = std::numeric_limits<std::ptrdiff_t>::denorm_min();
8160  };
8161 
8169  struct internal_iterator
8170  {
8172  typename object_t::iterator object_iterator;
8174  typename array_t::iterator array_iterator;
8176  primitive_iterator_t primitive_iterator;
8177 
8179  internal_iterator() noexcept
8180  : object_iterator(), array_iterator(), primitive_iterator()
8181  {}
8182  };
8183 
8185  template<typename IteratorType>
8186  class iteration_proxy
8187  {
8188  private:
8190  class iteration_proxy_internal
8191  {
8192  private:
8194  IteratorType anchor;
8196  size_t array_index = 0;
8197 
8198  public:
8199  explicit iteration_proxy_internal(IteratorType it) noexcept
8200  : anchor(it)
8201  {}
8202 
8204  iteration_proxy_internal& operator*()
8205  {
8206  return *this;
8207  }
8208 
8210  iteration_proxy_internal& operator++()
8211  {
8212  ++anchor;
8213  ++array_index;
8214 
8215  return *this;
8216  }
8217 
8219  bool operator!= (const iteration_proxy_internal& o) const
8220  {
8221  return anchor != o.anchor;
8222  }
8223 
8225  typename basic_json::string_t key() const
8226  {
8227  assert(anchor.m_object != nullptr);
8228 
8229  switch (anchor.m_object->type())
8230  {
8231  // use integer array index as key
8232  case value_t::array:
8233  {
8234  return std::to_string(array_index);
8235  }
8236 
8237  // use key from the object
8238  case value_t::object:
8239  {
8240  return anchor.key();
8241  }
8242 
8243  // use an empty key for all primitive types
8244  default:
8245  {
8246  return "";
8247  }
8248  }
8249  }
8250 
8252  typename IteratorType::reference value() const
8253  {
8254  return anchor.value();
8255  }
8256  };
8257 
8259  typename IteratorType::reference container;
8260 
8261  public:
8263  explicit iteration_proxy(typename IteratorType::reference cont)
8264  : container(cont)
8265  {}
8266 
8268  iteration_proxy_internal begin() noexcept
8269  {
8270  return iteration_proxy_internal(container.begin());
8271  }
8272 
8274  iteration_proxy_internal end() noexcept
8275  {
8276  return iteration_proxy_internal(container.end());
8277  }
8278  };
8279 
8280  public:
8300  template<typename U>
8301  class iter_impl : public std::iterator<std::random_access_iterator_tag, U>
8302  {
8304  friend class basic_json;
8305 
8306  // make sure U is basic_json or const basic_json
8307  static_assert(std::is_same<U, basic_json>::value
8308  or std::is_same<U, const basic_json>::value,
8309  "iter_impl only accepts (const) basic_json");
8310 
8311  public:
8317  using pointer = typename std::conditional<std::is_const<U>::value,
8318  typename basic_json::const_pointer,
8319  typename basic_json::pointer>::type;
8321  using reference = typename std::conditional<std::is_const<U>::value,
8322  typename basic_json::const_reference,
8323  typename basic_json::reference>::type;
8325  using iterator_category = std::bidirectional_iterator_tag;
8326 
8328  iter_impl() = default;
8329 
8336  explicit iter_impl(pointer object) noexcept
8337  : m_object(object)
8338  {
8339  assert(m_object != nullptr);
8340 
8341  switch (m_object->m_type)
8342  {
8344  {
8345  m_it.object_iterator = typename object_t::iterator();
8346  break;
8347  }
8348 
8350  {
8351  m_it.array_iterator = typename array_t::iterator();
8352  break;
8353  }
8354 
8355  default:
8356  {
8357  m_it.primitive_iterator = primitive_iterator_t();
8358  break;
8359  }
8360  }
8361  }
8362 
8363  /*
8364  Use operator `const_iterator` instead of `const_iterator(const iterator&
8365  other) noexcept` to avoid two class definitions for @ref iterator and
8366  @ref const_iterator.
8367 
8368  This function is only called if this class is an @ref iterator. If this
8369  class is a @ref const_iterator this function is not called.
8370  */
8371  operator const_iterator() const
8372  {
8373  const_iterator ret;
8374 
8375  if (m_object)
8376  {
8377  ret.m_object = m_object;
8378  ret.m_it = m_it;
8379  }
8380 
8381  return ret;
8382  }
8383 
8389  iter_impl(const iter_impl& other) noexcept
8390  : m_object(other.m_object), m_it(other.m_it)
8391  {}
8392 
8398  iter_impl& operator=(iter_impl other) noexcept(
8399  std::is_nothrow_move_constructible<pointer>::value and
8400  std::is_nothrow_move_assignable<pointer>::value and
8401  std::is_nothrow_move_constructible<internal_iterator>::value and
8402  std::is_nothrow_move_assignable<internal_iterator>::value
8403  )
8404  {
8405  std::swap(m_object, other.m_object);
8406  std::swap(m_it, other.m_it);
8407  return *this;
8408  }
8409 
8410  private:
8415  void set_begin() noexcept
8416  {
8417  assert(m_object != nullptr);
8418 
8419  switch (m_object->m_type)
8420  {
8422  {
8423  m_it.object_iterator = m_object->m_value.object->begin();
8424  break;
8425  }
8426 
8428  {
8429  m_it.array_iterator = m_object->m_value.array->begin();
8430  break;
8431  }
8432 
8434  {
8435  // set to end so begin()==end() is true: null is empty
8436  m_it.primitive_iterator.set_end();
8437  break;
8438  }
8439 
8440  default:
8441  {
8442  m_it.primitive_iterator.set_begin();
8443  break;
8444  }
8445  }
8446  }
8447 
8452  void set_end() noexcept
8453  {
8454  assert(m_object != nullptr);
8455 
8456  switch (m_object->m_type)
8457  {
8459  {
8460  m_it.object_iterator = m_object->m_value.object->end();
8461  break;
8462  }
8463 
8465  {
8466  m_it.array_iterator = m_object->m_value.array->end();
8467  break;
8468  }
8469 
8470  default:
8471  {
8472  m_it.primitive_iterator.set_end();
8473  break;
8474  }
8475  }
8476  }
8477 
8478  public:
8484  {
8485  assert(m_object != nullptr);
8486 
8487  switch (m_object->m_type)
8488  {
8490  {
8491  assert(m_it.object_iterator != m_object->m_value.object->end());
8492  return m_it.object_iterator->second;
8493  }
8494 
8496  {
8497  assert(m_it.array_iterator != m_object->m_value.array->end());
8498  return *m_it.array_iterator;
8499  }
8500 
8502  {
8503  throw std::out_of_range("cannot get value");
8504  }
8505 
8506  default:
8507  {
8508  if (m_it.primitive_iterator.is_begin())
8509  {
8510  return *m_object;
8511  }
8512  else
8513  {
8514  throw std::out_of_range("cannot get value");
8515  }
8516  }
8517  }
8518  }
8519 
8525  {
8526  assert(m_object != nullptr);
8527 
8528  switch (m_object->m_type)
8529  {
8531  {
8532  assert(m_it.object_iterator != m_object->m_value.object->end());
8533  return &(m_it.object_iterator->second);
8534  }
8535 
8537  {
8538  assert(m_it.array_iterator != m_object->m_value.array->end());
8539  return &*m_it.array_iterator;
8540  }
8541 
8542  default:
8543  {
8544  if (m_it.primitive_iterator.is_begin())
8545  {
8546  return m_object;
8547  }
8548  else
8549  {
8550  throw std::out_of_range("cannot get value");
8551  }
8552  }
8553  }
8554  }
8555 
8561  {
8562  auto result = *this;
8563  ++(*this);
8564  return result;
8565  }
8566 
8572  {
8573  assert(m_object != nullptr);
8574 
8575  switch (m_object->m_type)
8576  {
8578  {
8579  std::advance(m_it.object_iterator, 1);
8580  break;
8581  }
8582 
8584  {
8585  std::advance(m_it.array_iterator, 1);
8586  break;
8587  }
8588 
8589  default:
8590  {
8591  ++m_it.primitive_iterator;
8592  break;
8593  }
8594  }
8595 
8596  return *this;
8597  }
8598 
8604  {
8605  auto result = *this;
8606  --(*this);
8607  return result;
8608  }
8609 
8615  {
8616  assert(m_object != nullptr);
8617 
8618  switch (m_object->m_type)
8619  {
8621  {
8622  std::advance(m_it.object_iterator, -1);
8623  break;
8624  }
8625 
8627  {
8628  std::advance(m_it.array_iterator, -1);
8629  break;
8630  }
8631 
8632  default:
8633  {
8634  --m_it.primitive_iterator;
8635  break;
8636  }
8637  }
8638 
8639  return *this;
8640  }
8641 
8646  bool operator==(const iter_impl& other) const
8647  {
8648  // if objects are not the same, the comparison is undefined
8649  if (m_object != other.m_object)
8650  {
8651  throw std::domain_error("cannot compare iterators of different containers");
8652  }
8653 
8654  assert(m_object != nullptr);
8655 
8656  switch (m_object->m_type)
8657  {
8659  {
8660  return (m_it.object_iterator == other.m_it.object_iterator);
8661  }
8662 
8664  {
8665  return (m_it.array_iterator == other.m_it.array_iterator);
8666  }
8667 
8668  default:
8669  {
8670  return (m_it.primitive_iterator == other.m_it.primitive_iterator);
8671  }
8672  }
8673  }
8674 
8679  bool operator!=(const iter_impl& other) const
8680  {
8681  return not operator==(other);
8682  }
8683 
8688  bool operator<(const iter_impl& other) const
8689  {
8690  // if objects are not the same, the comparison is undefined
8691  if (m_object != other.m_object)
8692  {
8693  throw std::domain_error("cannot compare iterators of different containers");
8694  }
8695 
8696  assert(m_object != nullptr);
8697 
8698  switch (m_object->m_type)
8699  {
8701  {
8702  throw std::domain_error("cannot compare order of object iterators");
8703  }
8704 
8706  {
8707  return (m_it.array_iterator < other.m_it.array_iterator);
8708  }
8709 
8710  default:
8711  {
8712  return (m_it.primitive_iterator < other.m_it.primitive_iterator);
8713  }
8714  }
8715  }
8716 
8721  bool operator<=(const iter_impl& other) const
8722  {
8723  return not other.operator < (*this);
8724  }
8725 
8730  bool operator>(const iter_impl& other) const
8731  {
8732  return not operator<=(other);
8733  }
8734 
8739  bool operator>=(const iter_impl& other) const
8740  {
8741  return not operator<(other);
8742  }
8743 
8749  {
8750  assert(m_object != nullptr);
8751 
8752  switch (m_object->m_type)
8753  {
8755  {
8756  throw std::domain_error("cannot use offsets with object iterators");
8757  }
8758 
8760  {
8761  std::advance(m_it.array_iterator, i);
8762  break;
8763  }
8764 
8765  default:
8766  {
8767  m_it.primitive_iterator += i;
8768  break;
8769  }
8770  }
8771 
8772  return *this;
8773  }
8774 
8780  {
8781  return operator+=(-i);
8782  }
8783 
8789  {
8790  auto result = *this;
8791  result += i;
8792  return result;
8793  }
8794 
8800  {
8801  auto result = *this;
8802  result -= i;
8803  return result;
8804  }
8805 
8811  {
8812  assert(m_object != nullptr);
8813 
8814  switch (m_object->m_type)
8815  {
8817  {
8818  throw std::domain_error("cannot use offsets with object iterators");
8819  }
8820 
8822  {
8823  return m_it.array_iterator - other.m_it.array_iterator;
8824  }
8825 
8826  default:
8827  {
8828  return m_it.primitive_iterator - other.m_it.primitive_iterator;
8829  }
8830  }
8831  }
8832 
8838  {
8839  assert(m_object != nullptr);
8840 
8841  switch (m_object->m_type)
8842  {
8844  {
8845  throw std::domain_error("cannot use operator[] for object iterators");
8846  }
8847 
8849  {
8850  return *std::next(m_it.array_iterator, n);
8851  }
8852 
8854  {
8855  throw std::out_of_range("cannot get value");
8856  }
8857 
8858  default:
8859  {
8860  if (m_it.primitive_iterator == -n)
8861  {
8862  return *m_object;
8863  }
8864  else
8865  {
8866  throw std::out_of_range("cannot get value");
8867  }
8868  }
8869  }
8870  }
8871 
8876  typename object_t::key_type key() const
8877  {
8878  assert(m_object != nullptr);
8879 
8880  if (m_object->is_object())
8881  {
8882  return m_it.object_iterator->first;
8883  }
8884  else
8885  {
8886  throw std::domain_error("cannot use key() for non-object iterators");
8887  }
8888  }
8889 
8895  {
8896  return operator*();
8897  }
8898 
8899  private:
8901  pointer m_object = nullptr;
8903  internal_iterator m_it = internal_iterator();
8904  };
8905 
8923  template<typename Base>
8924  class json_reverse_iterator : public std::reverse_iterator<Base>
8925  {
8926  public:
8928  using base_iterator = std::reverse_iterator<Base>;
8930  using reference = typename Base::reference;
8931 
8933  json_reverse_iterator(const typename base_iterator::iterator_type& it) noexcept
8934  : base_iterator(it)
8935  {}
8936 
8939  : base_iterator(it)
8940  {}
8941 
8944  {
8945  return base_iterator::operator++(1);
8946  }
8947 
8950  {
8951  base_iterator::operator++();
8952  return *this;
8953  }
8954 
8957  {
8958  return base_iterator::operator--(1);
8959  }
8960 
8963  {
8964  base_iterator::operator--();
8965  return *this;
8966  }
8967 
8970  {
8971  base_iterator::operator+=(i);
8972  return *this;
8973  }
8974 
8977  {
8978  auto result = *this;
8979  result += i;
8980  return result;
8981  }
8982 
8985  {
8986  auto result = *this;
8987  result -= i;
8988  return result;
8989  }
8990 
8993  {
8994  return this->base() - other.base();
8995  }
8996 
8999  {
9000  return *(this->operator+(n));
9001  }
9002 
9004  typename object_t::key_type key() const
9005  {
9006  auto it = --this->base();
9007  return it.key();
9008  }
9009 
9012  {
9013  auto it = --this->base();
9014  return it.operator * ();
9015  }
9016  };
9017 
9018 
9019  private:
9021  // lexer and parser //
9023 
9031  class lexer
9032  {
9033  public:
9035  enum class token_type
9036  {
9037  uninitialized,
9038  literal_true,
9039  literal_false,
9040  literal_null,
9041  value_string,
9042  value_number,
9043  begin_array,
9044  begin_object,
9045  end_array,
9046  end_object,
9047  name_separator,
9048  value_separator,
9049  parse_error,
9050  end_of_input
9051  };
9052 
9054  using lexer_char_t = unsigned char;
9055 
9057  lexer(const lexer_char_t* buff, const size_t len) noexcept
9058  : m_content(buff)
9059  {
9060  assert(m_content != nullptr);
9061  m_start = m_cursor = m_content;
9062  m_limit = m_content + len;
9063  }
9064 
9066  explicit lexer(std::istream& s)
9067  : m_stream(&s), m_line_buffer()
9068  {
9069  // immediately abort if stream is erroneous
9070  if (s.fail())
9071  {
9072  throw std::invalid_argument("stream error");
9073  }
9074 
9075  // fill buffer
9076  fill_line_buffer();
9077 
9078  // skip UTF-8 byte-order mark
9079  if (m_line_buffer.size() >= 3 and m_line_buffer.substr(0, 3) == "\xEF\xBB\xBF")
9080  {
9081  m_line_buffer[0] = ' ';
9082  m_line_buffer[1] = ' ';
9083  m_line_buffer[2] = ' ';
9084  }
9085  }
9086 
9087  // switch off unwanted functions (due to pointer members)
9088  lexer() = delete;
9089  lexer(const lexer&) = delete;
9090  lexer operator=(const lexer&) = delete;
9091 
9115  static string_t to_unicode(const std::size_t codepoint1,
9116  const std::size_t codepoint2 = 0)
9117  {
9118  // calculate the code point from the given code points
9119  std::size_t codepoint = codepoint1;
9120 
9121  // check if codepoint1 is a high surrogate
9122  if (codepoint1 >= 0xD800 and codepoint1 <= 0xDBFF)
9123  {
9124  // check if codepoint2 is a low surrogate
9125  if (codepoint2 >= 0xDC00 and codepoint2 <= 0xDFFF)
9126  {
9127  codepoint =
9128  // high surrogate occupies the most significant 22 bits
9129  (codepoint1 << 10)
9130  // low surrogate occupies the least significant 15 bits
9131  + codepoint2
9132  // there is still the 0xD800, 0xDC00 and 0x10000 noise
9133  // in the result so we have to subtract with:
9134  // (0xD800 << 10) + DC00 - 0x10000 = 0x35FDC00
9135  - 0x35FDC00;
9136  }
9137  else
9138  {
9139  throw std::invalid_argument("missing or wrong low surrogate");
9140  }
9141  }
9142 
9143  string_t result;
9144 
9145  if (codepoint < 0x80)
9146  {
9147  // 1-byte characters: 0xxxxxxx (ASCII)
9148  result.append(1, static_cast<typename string_t::value_type>(codepoint));
9149  }
9150  else if (codepoint <= 0x7ff)
9151  {
9152  // 2-byte characters: 110xxxxx 10xxxxxx
9153  result.append(1, static_cast<typename string_t::value_type>(0xC0 | ((codepoint >> 6) & 0x1F)));
9154  result.append(1, static_cast<typename string_t::value_type>(0x80 | (codepoint & 0x3F)));
9155  }
9156  else if (codepoint <= 0xffff)
9157  {
9158  // 3-byte characters: 1110xxxx 10xxxxxx 10xxxxxx
9159  result.append(1, static_cast<typename string_t::value_type>(0xE0 | ((codepoint >> 12) & 0x0F)));
9160  result.append(1, static_cast<typename string_t::value_type>(0x80 | ((codepoint >> 6) & 0x3F)));
9161  result.append(1, static_cast<typename string_t::value_type>(0x80 | (codepoint & 0x3F)));
9162  }
9163  else if (codepoint <= 0x10ffff)
9164  {
9165  // 4-byte characters: 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
9166  result.append(1, static_cast<typename string_t::value_type>(0xF0 | ((codepoint >> 18) & 0x07)));
9167  result.append(1, static_cast<typename string_t::value_type>(0x80 | ((codepoint >> 12) & 0x3F)));
9168  result.append(1, static_cast<typename string_t::value_type>(0x80 | ((codepoint >> 6) & 0x3F)));
9169  result.append(1, static_cast<typename string_t::value_type>(0x80 | (codepoint & 0x3F)));
9170  }
9171  else
9172  {
9173  throw std::out_of_range("code points above 0x10FFFF are invalid");
9174  }
9175 
9176  return result;
9177  }
9178 
9180  static std::string token_type_name(const token_type t)
9181  {
9182  switch (t)
9183  {
9184  case token_type::uninitialized:
9185  return "<uninitialized>";
9186  case token_type::literal_true:
9187  return "true literal";
9188  case token_type::literal_false:
9189  return "false literal";
9190  case token_type::literal_null:
9191  return "null literal";
9192  case token_type::value_string:
9193  return "string literal";
9194  case token_type::value_number:
9195  return "number literal";
9196  case token_type::begin_array:
9197  return "'['";
9198  case token_type::begin_object:
9199  return "'{'";
9200  case token_type::end_array:
9201  return "']'";
9202  case token_type::end_object:
9203  return "'}'";
9204  case token_type::name_separator:
9205  return "':'";
9206  case token_type::value_separator:
9207  return "','";
9208  case token_type::parse_error:
9209  return "<parse error>";
9210  case token_type::end_of_input:
9211  return "end of input";
9212  default:
9213  {
9214  // catch non-enum values
9215  return "unknown token"; // LCOV_EXCL_LINE
9216  }
9217  }
9218  }
9219 
9241  token_type scan()
9242  {
9243  while (true)
9244  {
9245  // pointer for backtracking information
9246  m_marker = nullptr;
9247 
9248  // remember the begin of the token
9249  m_start = m_cursor;
9250  assert(m_start != nullptr);
9251 
9252 
9253  {
9254  lexer_char_t yych;
9255  unsigned int yyaccept = 0;
9256  static const unsigned char yybm[] =
9257  {
9258  0, 0, 0, 0, 0, 0, 0, 0,
9259  0, 32, 32, 0, 0, 32, 0, 0,
9260  0, 0, 0, 0, 0, 0, 0, 0,
9261  0, 0, 0, 0, 0, 0, 0, 0,
9262  160, 128, 0, 128, 128, 128, 128, 128,
9263  128, 128, 128, 128, 128, 128, 128, 128,
9264  192, 192, 192, 192, 192, 192, 192, 192,
9265  192, 192, 128, 128, 128, 128, 128, 128,
9266  128, 128, 128, 128, 128, 128, 128, 128,
9267  128, 128, 128, 128, 128, 128, 128, 128,
9268  128, 128, 128, 128, 128, 128, 128, 128,
9269  128, 128, 128, 128, 0, 128, 128, 128,
9270  128, 128, 128, 128, 128, 128, 128, 128,
9271  128, 128, 128, 128, 128, 128, 128, 128,
9272  128, 128, 128, 128, 128, 128, 128, 128,
9273  128, 128, 128, 128, 128, 128, 128, 128,
9274  0, 0, 0, 0, 0, 0, 0, 0,
9275  0, 0, 0, 0, 0, 0, 0, 0,
9276  0, 0, 0, 0, 0, 0, 0, 0,
9277  0, 0, 0, 0, 0, 0, 0, 0,
9278  0, 0, 0, 0, 0, 0, 0, 0,
9279  0, 0, 0, 0, 0, 0, 0, 0,
9280  0, 0, 0, 0, 0, 0, 0, 0,
9281  0, 0, 0, 0, 0, 0, 0, 0,
9282  0, 0, 0, 0, 0, 0, 0, 0,
9283  0, 0, 0, 0, 0, 0, 0, 0,
9284  0, 0, 0, 0, 0, 0, 0, 0,
9285  0, 0, 0, 0, 0, 0, 0, 0,
9286  0, 0, 0, 0, 0, 0, 0, 0,
9287  0, 0, 0, 0, 0, 0, 0, 0,
9288  0, 0, 0, 0, 0, 0, 0, 0,
9289  0, 0, 0, 0, 0, 0, 0, 0,
9290  };
9291  if ((m_limit - m_cursor) < 5)
9292  {
9293  fill_line_buffer(5); // LCOV_EXCL_LINE
9294  }
9295  yych = *m_cursor;
9296  if (yybm[0 + yych] & 32)
9297  {
9298  goto basic_json_parser_6;
9299  }
9300  if (yych <= '[')
9301  {
9302  if (yych <= '-')
9303  {
9304  if (yych <= '"')
9305  {
9306  if (yych <= 0x00)
9307  {
9308  goto basic_json_parser_2;
9309  }
9310  if (yych <= '!')
9311  {
9312  goto basic_json_parser_4;
9313  }
9314  goto basic_json_parser_9;
9315  }
9316  else
9317  {
9318  if (yych <= '+')
9319  {
9320  goto basic_json_parser_4;
9321  }
9322  if (yych <= ',')
9323  {
9324  goto basic_json_parser_10;
9325  }
9326  goto basic_json_parser_12;
9327  }
9328  }
9329  else
9330  {
9331  if (yych <= '9')
9332  {
9333  if (yych <= '/')
9334  {
9335  goto basic_json_parser_4;
9336  }
9337  if (yych <= '0')
9338  {
9339  goto basic_json_parser_13;
9340  }
9341  goto basic_json_parser_15;
9342  }
9343  else
9344  {
9345  if (yych <= ':')
9346  {
9347  goto basic_json_parser_17;
9348  }
9349  if (yych <= 'Z')
9350  {
9351  goto basic_json_parser_4;
9352  }
9353  goto basic_json_parser_19;
9354  }
9355  }
9356  }
9357  else
9358  {
9359  if (yych <= 'n')
9360  {
9361  if (yych <= 'e')
9362  {
9363  if (yych == ']')
9364  {
9365  goto basic_json_parser_21;
9366  }
9367  goto basic_json_parser_4;
9368  }
9369  else
9370  {
9371  if (yych <= 'f')
9372  {
9373  goto basic_json_parser_23;
9374  }
9375  if (yych <= 'm')
9376  {
9377  goto basic_json_parser_4;
9378  }
9379  goto basic_json_parser_24;
9380  }
9381  }
9382  else
9383  {
9384  if (yych <= 'z')
9385  {
9386  if (yych == 't')
9387  {
9388  goto basic_json_parser_25;
9389  }
9390  goto basic_json_parser_4;
9391  }
9392  else
9393  {
9394  if (yych <= '{')
9395  {
9396  goto basic_json_parser_26;
9397  }
9398  if (yych == '}')
9399  {
9400  goto basic_json_parser_28;
9401  }
9402  goto basic_json_parser_4;
9403  }
9404  }
9405  }
9406 basic_json_parser_2:
9407  ++m_cursor;
9408  {
9409  last_token_type = token_type::end_of_input;
9410  break;
9411  }
9412 basic_json_parser_4:
9413  ++m_cursor;
9414 basic_json_parser_5:
9415  {
9416  last_token_type = token_type::parse_error;
9417  break;
9418  }
9419 basic_json_parser_6:
9420  ++m_cursor;
9421  if (m_limit <= m_cursor)
9422  {
9423  fill_line_buffer(1); // LCOV_EXCL_LINE
9424  }
9425  yych = *m_cursor;
9426  if (yybm[0 + yych] & 32)
9427  {
9428  goto basic_json_parser_6;
9429  }
9430  {
9431  continue;
9432  }
9433 basic_json_parser_9:
9434  yyaccept = 0;
9435  yych = *(m_marker = ++m_cursor);
9436  if (yych <= 0x1F)
9437  {
9438  goto basic_json_parser_5;
9439  }
9440  if (yych <= 0x7F)
9441  {
9442  goto basic_json_parser_31;
9443  }
9444  if (yych <= 0xC1)
9445  {
9446  goto basic_json_parser_5;
9447  }
9448  if (yych <= 0xF4)
9449  {
9450  goto basic_json_parser_31;
9451  }
9452  goto basic_json_parser_5;
9453 basic_json_parser_10:
9454  ++m_cursor;
9455  {
9456  last_token_type = token_type::value_separator;
9457  break;
9458  }
9459 basic_json_parser_12:
9460  yych = *++m_cursor;
9461  if (yych <= '/')
9462  {
9463  goto basic_json_parser_5;
9464  }
9465  if (yych <= '0')
9466  {
9467  goto basic_json_parser_13;
9468  }
9469  if (yych <= '9')
9470  {
9471  goto basic_json_parser_15;
9472  }
9473  goto basic_json_parser_5;
9474 basic_json_parser_13:
9475  yyaccept = 1;
9476  yych = *(m_marker = ++m_cursor);
9477  if (yych <= 'D')
9478  {
9479  if (yych == '.')
9480  {
9481  goto basic_json_parser_43;
9482  }
9483  }
9484  else
9485  {
9486  if (yych <= 'E')
9487  {
9488  goto basic_json_parser_44;
9489  }
9490  if (yych == 'e')
9491  {
9492  goto basic_json_parser_44;
9493  }
9494  }
9495 basic_json_parser_14:
9496  {
9497  last_token_type = token_type::value_number;
9498  break;
9499  }
9500 basic_json_parser_15:
9501  yyaccept = 1;
9502  m_marker = ++m_cursor;
9503  if ((m_limit - m_cursor) < 3)
9504  {
9505  fill_line_buffer(3); // LCOV_EXCL_LINE
9506  }
9507  yych = *m_cursor;
9508  if (yybm[0 + yych] & 64)
9509  {
9510  goto basic_json_parser_15;
9511  }
9512  if (yych <= 'D')
9513  {
9514  if (yych == '.')
9515  {
9516  goto basic_json_parser_43;
9517  }
9518  goto basic_json_parser_14;
9519  }
9520  else
9521  {
9522  if (yych <= 'E')
9523  {
9524  goto basic_json_parser_44;
9525  }
9526  if (yych == 'e')
9527  {
9528  goto basic_json_parser_44;
9529  }
9530  goto basic_json_parser_14;
9531  }
9532 basic_json_parser_17:
9533  ++m_cursor;
9534  {
9535  last_token_type = token_type::name_separator;
9536  break;
9537  }
9538 basic_json_parser_19:
9539  ++m_cursor;
9540  {
9541  last_token_type = token_type::begin_array;
9542  break;
9543  }
9544 basic_json_parser_21:
9545  ++m_cursor;
9546  {
9547  last_token_type = token_type::end_array;
9548  break;
9549  }
9550 basic_json_parser_23:
9551  yyaccept = 0;
9552  yych = *(m_marker = ++m_cursor);
9553  if (yych == 'a')
9554  {
9555  goto basic_json_parser_45;
9556  }
9557  goto basic_json_parser_5;
9558 basic_json_parser_24:
9559  yyaccept = 0;
9560  yych = *(m_marker = ++m_cursor);
9561  if (yych == 'u')
9562  {
9563  goto basic_json_parser_46;
9564  }
9565  goto basic_json_parser_5;
9566 basic_json_parser_25:
9567  yyaccept = 0;
9568  yych = *(m_marker = ++m_cursor);
9569  if (yych == 'r')
9570  {
9571  goto basic_json_parser_47;
9572  }
9573  goto basic_json_parser_5;
9574 basic_json_parser_26:
9575  ++m_cursor;
9576  {
9577  last_token_type = token_type::begin_object;
9578  break;
9579  }
9580 basic_json_parser_28:
9581  ++m_cursor;
9582  {
9583  last_token_type = token_type::end_object;
9584  break;
9585  }
9586 basic_json_parser_30:
9587  ++m_cursor;
9588  if (m_limit <= m_cursor)
9589  {
9590  fill_line_buffer(1); // LCOV_EXCL_LINE
9591  }
9592  yych = *m_cursor;
9593 basic_json_parser_31:
9594  if (yybm[0 + yych] & 128)
9595  {
9596  goto basic_json_parser_30;
9597  }
9598  if (yych <= 0xE0)
9599  {
9600  if (yych <= '\\')
9601  {
9602  if (yych <= 0x1F)
9603  {
9604  goto basic_json_parser_32;
9605  }
9606  if (yych <= '"')
9607  {
9608  goto basic_json_parser_33;
9609  }
9610  goto basic_json_parser_35;
9611  }
9612  else
9613  {
9614  if (yych <= 0xC1)
9615  {
9616  goto basic_json_parser_32;
9617  }
9618  if (yych <= 0xDF)
9619  {
9620  goto basic_json_parser_36;
9621  }
9622  goto basic_json_parser_37;
9623  }
9624  }
9625  else
9626  {
9627  if (yych <= 0xEF)
9628  {
9629  if (yych == 0xED)
9630  {
9631  goto basic_json_parser_39;
9632  }
9633  goto basic_json_parser_38;
9634  }
9635  else
9636  {
9637  if (yych <= 0xF0)
9638  {
9639  goto basic_json_parser_40;
9640  }
9641  if (yych <= 0xF3)
9642  {
9643  goto basic_json_parser_41;
9644  }
9645  if (yych <= 0xF4)
9646  {
9647  goto basic_json_parser_42;
9648  }
9649  }
9650  }
9651 basic_json_parser_32:
9652  m_cursor = m_marker;
9653  if (yyaccept == 0)
9654  {
9655  goto basic_json_parser_5;
9656  }
9657  else
9658  {
9659  goto basic_json_parser_14;
9660  }
9661 basic_json_parser_33:
9662  ++m_cursor;
9663  {
9664  last_token_type = token_type::value_string;
9665  break;
9666  }
9667 basic_json_parser_35:
9668  ++m_cursor;
9669  if (m_limit <= m_cursor)
9670  {
9671  fill_line_buffer(1); // LCOV_EXCL_LINE
9672  }
9673  yych = *m_cursor;
9674  if (yych <= 'e')
9675  {
9676  if (yych <= '/')
9677  {
9678  if (yych == '"')
9679  {
9680  goto basic_json_parser_30;
9681  }
9682  if (yych <= '.')
9683  {
9684  goto basic_json_parser_32;
9685  }
9686  goto basic_json_parser_30;
9687  }
9688  else
9689  {
9690  if (yych <= '\\')
9691  {
9692  if (yych <= '[')
9693  {
9694  goto basic_json_parser_32;
9695  }
9696  goto basic_json_parser_30;
9697  }
9698  else
9699  {
9700  if (yych == 'b')
9701  {
9702  goto basic_json_parser_30;
9703  }
9704  goto basic_json_parser_32;
9705  }
9706  }
9707  }
9708  else
9709  {
9710  if (yych <= 'q')
9711  {
9712  if (yych <= 'f')
9713  {
9714  goto basic_json_parser_30;
9715  }
9716  if (yych == 'n')
9717  {
9718  goto basic_json_parser_30;
9719  }
9720  goto basic_json_parser_32;
9721  }
9722  else
9723  {
9724  if (yych <= 's')
9725  {
9726  if (yych <= 'r')
9727  {
9728  goto basic_json_parser_30;
9729  }
9730  goto basic_json_parser_32;
9731  }
9732  else
9733  {
9734  if (yych <= 't')
9735  {
9736  goto basic_json_parser_30;
9737  }
9738  if (yych <= 'u')
9739  {
9740  goto basic_json_parser_48;
9741  }
9742  goto basic_json_parser_32;
9743  }
9744  }
9745  }
9746 basic_json_parser_36:
9747  ++m_cursor;
9748  if (m_limit <= m_cursor)
9749  {
9750  fill_line_buffer(1); // LCOV_EXCL_LINE
9751  }
9752  yych = *m_cursor;
9753  if (yych <= 0x7F)
9754  {
9755  goto basic_json_parser_32;
9756  }
9757  if (yych <= 0xBF)
9758  {
9759  goto basic_json_parser_30;
9760  }
9761  goto basic_json_parser_32;
9762 basic_json_parser_37:
9763  ++m_cursor;
9764  if (m_limit <= m_cursor)
9765  {
9766  fill_line_buffer(1); // LCOV_EXCL_LINE
9767  }
9768  yych = *m_cursor;
9769  if (yych <= 0x9F)
9770  {
9771  goto basic_json_parser_32;
9772  }
9773  if (yych <= 0xBF)
9774  {
9775  goto basic_json_parser_36;
9776  }
9777  goto basic_json_parser_32;
9778 basic_json_parser_38:
9779  ++m_cursor;
9780  if (m_limit <= m_cursor)
9781  {
9782  fill_line_buffer(1); // LCOV_EXCL_LINE
9783  }
9784  yych = *m_cursor;
9785  if (yych <= 0x7F)
9786  {
9787  goto basic_json_parser_32;
9788  }
9789  if (yych <= 0xBF)
9790  {
9791  goto basic_json_parser_36;
9792  }
9793  goto basic_json_parser_32;
9794 basic_json_parser_39:
9795  ++m_cursor;
9796  if (m_limit <= m_cursor)
9797  {
9798  fill_line_buffer(1); // LCOV_EXCL_LINE
9799  }
9800  yych = *m_cursor;
9801  if (yych <= 0x7F)
9802  {
9803  goto basic_json_parser_32;
9804  }
9805  if (yych <= 0x9F)
9806  {
9807  goto basic_json_parser_36;
9808  }
9809  goto basic_json_parser_32;
9810 basic_json_parser_40:
9811  ++m_cursor;
9812  if (m_limit <= m_cursor)
9813  {
9814  fill_line_buffer(1); // LCOV_EXCL_LINE
9815  }
9816  yych = *m_cursor;
9817  if (yych <= 0x8F)
9818  {
9819  goto basic_json_parser_32;
9820  }
9821  if (yych <= 0xBF)
9822  {
9823  goto basic_json_parser_38;
9824  }
9825  goto basic_json_parser_32;
9826 basic_json_parser_41:
9827  ++m_cursor;
9828  if (m_limit <= m_cursor)
9829  {
9830  fill_line_buffer(1); // LCOV_EXCL_LINE
9831  }
9832  yych = *m_cursor;
9833  if (yych <= 0x7F)
9834  {
9835  goto basic_json_parser_32;
9836  }
9837  if (yych <= 0xBF)
9838  {
9839  goto basic_json_parser_38;
9840  }
9841  goto basic_json_parser_32;
9842 basic_json_parser_42:
9843  ++m_cursor;
9844  if (m_limit <= m_cursor)
9845  {
9846  fill_line_buffer(1); // LCOV_EXCL_LINE
9847  }
9848  yych = *m_cursor;
9849  if (yych <= 0x7F)
9850  {
9851  goto basic_json_parser_32;
9852  }
9853  if (yych <= 0x8F)
9854  {
9855  goto basic_json_parser_38;
9856  }
9857  goto basic_json_parser_32;
9858 basic_json_parser_43:
9859  yych = *++m_cursor;
9860  if (yych <= '/')
9861  {
9862  goto basic_json_parser_32;
9863  }
9864  if (yych <= '9')
9865  {
9866  goto basic_json_parser_49;
9867  }
9868  goto basic_json_parser_32;
9869 basic_json_parser_44:
9870  yych = *++m_cursor;
9871  if (yych <= ',')
9872  {
9873  if (yych == '+')
9874  {
9875  goto basic_json_parser_51;
9876  }
9877  goto basic_json_parser_32;
9878  }
9879  else
9880  {
9881  if (yych <= '-')
9882  {
9883  goto basic_json_parser_51;
9884  }
9885  if (yych <= '/')
9886  {
9887  goto basic_json_parser_32;
9888  }
9889  if (yych <= '9')
9890  {
9891  goto basic_json_parser_52;
9892  }
9893  goto basic_json_parser_32;
9894  }
9895 basic_json_parser_45:
9896  yych = *++m_cursor;
9897  if (yych == 'l')
9898  {
9899  goto basic_json_parser_54;
9900  }
9901  goto basic_json_parser_32;
9902 basic_json_parser_46:
9903  yych = *++m_cursor;
9904  if (yych == 'l')
9905  {
9906  goto basic_json_parser_55;
9907  }
9908  goto basic_json_parser_32;
9909 basic_json_parser_47:
9910  yych = *++m_cursor;
9911  if (yych == 'u')
9912  {
9913  goto basic_json_parser_56;
9914  }
9915  goto basic_json_parser_32;
9916 basic_json_parser_48:
9917  ++m_cursor;
9918  if (m_limit <= m_cursor)
9919  {
9920  fill_line_buffer(1); // LCOV_EXCL_LINE
9921  }
9922  yych = *m_cursor;
9923  if (yych <= '@')
9924  {
9925  if (yych <= '/')
9926  {
9927  goto basic_json_parser_32;
9928  }
9929  if (yych <= '9')
9930  {
9931  goto basic_json_parser_57;
9932  }
9933  goto basic_json_parser_32;
9934  }
9935  else
9936  {
9937  if (yych <= 'F')
9938  {
9939  goto basic_json_parser_57;
9940  }
9941  if (yych <= '`')
9942  {
9943  goto basic_json_parser_32;
9944  }
9945  if (yych <= 'f')
9946  {
9947  goto basic_json_parser_57;
9948  }
9949  goto basic_json_parser_32;
9950  }
9951 basic_json_parser_49:
9952  yyaccept = 1;
9953  m_marker = ++m_cursor;
9954  if ((m_limit - m_cursor) < 3)
9955  {
9956  fill_line_buffer(3); // LCOV_EXCL_LINE
9957  }
9958  yych = *m_cursor;
9959  if (yych <= 'D')
9960  {
9961  if (yych <= '/')
9962  {
9963  goto basic_json_parser_14;
9964  }
9965  if (yych <= '9')
9966  {
9967  goto basic_json_parser_49;
9968  }
9969  goto basic_json_parser_14;
9970  }
9971  else
9972  {
9973  if (yych <= 'E')
9974  {
9975  goto basic_json_parser_44;
9976  }
9977  if (yych == 'e')
9978  {
9979  goto basic_json_parser_44;
9980  }
9981  goto basic_json_parser_14;
9982  }
9983 basic_json_parser_51:
9984  yych = *++m_cursor;
9985  if (yych <= '/')
9986  {
9987  goto basic_json_parser_32;
9988  }
9989  if (yych >= ':')
9990  {
9991  goto basic_json_parser_32;
9992  }
9993 basic_json_parser_52:
9994  ++m_cursor;
9995  if (m_limit <= m_cursor)
9996  {
9997  fill_line_buffer(1); // LCOV_EXCL_LINE
9998  }
9999  yych = *m_cursor;
10000  if (yych <= '/')
10001  {
10002  goto basic_json_parser_14;
10003  }
10004  if (yych <= '9')
10005  {
10006  goto basic_json_parser_52;
10007  }
10008  goto basic_json_parser_14;
10009 basic_json_parser_54:
10010  yych = *++m_cursor;
10011  if (yych == 's')
10012  {
10013  goto basic_json_parser_58;
10014  }
10015  goto basic_json_parser_32;
10016 basic_json_parser_55:
10017  yych = *++m_cursor;
10018  if (yych == 'l')
10019  {
10020  goto basic_json_parser_59;
10021  }
10022  goto basic_json_parser_32;
10023 basic_json_parser_56:
10024  yych = *++m_cursor;
10025  if (yych == 'e')
10026  {
10027  goto basic_json_parser_61;
10028  }
10029  goto basic_json_parser_32;
10030 basic_json_parser_57:
10031  ++m_cursor;
10032  if (m_limit <= m_cursor)
10033  {
10034  fill_line_buffer(1); // LCOV_EXCL_LINE
10035  }
10036  yych = *m_cursor;
10037  if (yych <= '@')
10038  {
10039  if (yych <= '/')
10040  {
10041  goto basic_json_parser_32;
10042  }
10043  if (yych <= '9')
10044  {
10045  goto basic_json_parser_63;
10046  }
10047  goto basic_json_parser_32;
10048  }
10049  else
10050  {
10051  if (yych <= 'F')
10052  {
10053  goto basic_json_parser_63;
10054  }
10055  if (yych <= '`')
10056  {
10057  goto basic_json_parser_32;
10058  }
10059  if (yych <= 'f')
10060  {
10061  goto basic_json_parser_63;
10062  }
10063  goto basic_json_parser_32;
10064  }
10065 basic_json_parser_58:
10066  yych = *++m_cursor;
10067  if (yych == 'e')
10068  {
10069  goto basic_json_parser_64;
10070  }
10071  goto basic_json_parser_32;
10072 basic_json_parser_59:
10073  ++m_cursor;
10074  {
10075  last_token_type = token_type::literal_null;
10076  break;
10077  }
10078 basic_json_parser_61:
10079  ++m_cursor;
10080  {
10081  last_token_type = token_type::literal_true;
10082  break;
10083  }
10084 basic_json_parser_63:
10085  ++m_cursor;
10086  if (m_limit <= m_cursor)
10087  {
10088  fill_line_buffer(1); // LCOV_EXCL_LINE
10089  }
10090  yych = *m_cursor;
10091  if (yych <= '@')
10092  {
10093  if (yych <= '/')
10094  {
10095  goto basic_json_parser_32;
10096  }
10097  if (yych <= '9')
10098  {
10099  goto basic_json_parser_66;
10100  }
10101  goto basic_json_parser_32;
10102  }
10103  else
10104  {
10105  if (yych <= 'F')
10106  {
10107  goto basic_json_parser_66;
10108  }
10109  if (yych <= '`')
10110  {
10111  goto basic_json_parser_32;
10112  }
10113  if (yych <= 'f')
10114  {
10115  goto basic_json_parser_66;
10116  }
10117  goto basic_json_parser_32;
10118  }
10119 basic_json_parser_64:
10120  ++m_cursor;
10121  {
10122  last_token_type = token_type::literal_false;
10123  break;
10124  }
10125 basic_json_parser_66:
10126  ++m_cursor;
10127  if (m_limit <= m_cursor)
10128  {
10129  fill_line_buffer(1); // LCOV_EXCL_LINE
10130  }
10131  yych = *m_cursor;
10132  if (yych <= '@')
10133  {
10134  if (yych <= '/')
10135  {
10136  goto basic_json_parser_32;
10137  }
10138  if (yych <= '9')
10139  {
10140  goto basic_json_parser_30;
10141  }
10142  goto basic_json_parser_32;
10143  }
10144  else
10145  {
10146  if (yych <= 'F')
10147  {
10148  goto basic_json_parser_30;
10149  }
10150  if (yych <= '`')
10151  {
10152  goto basic_json_parser_32;
10153  }
10154  if (yych <= 'f')
10155  {
10156  goto basic_json_parser_30;
10157  }
10158  goto basic_json_parser_32;
10159  }
10160  }
10161 
10162  }
10163 
10164  return last_token_type;
10165  }
10166 
10195  void fill_line_buffer(size_t n = 0)
10196  {
10197  // if line buffer is used, m_content points to its data
10198  assert(m_line_buffer.empty()
10199  or m_content == reinterpret_cast<const lexer_char_t*>(m_line_buffer.data()));
10200 
10201  // if line buffer is used, m_limit is set past the end of its data
10202  assert(m_line_buffer.empty()
10203  or m_limit == m_content + m_line_buffer.size());
10204 
10205  // pointer relationships
10206  assert(m_content <= m_start);
10207  assert(m_start <= m_cursor);
10208  assert(m_cursor <= m_limit);
10209  assert(m_marker == nullptr or m_marker <= m_limit);
10210 
10211  // number of processed characters (p)
10212  const size_t num_processed_chars = static_cast<size_t>(m_start - m_content);
10213  // offset for m_marker wrt. to m_start
10214  const auto offset_marker = (m_marker == nullptr) ? 0 : m_marker - m_start;
10215  // number of unprocessed characters (u)
10216  const auto offset_cursor = m_cursor - m_start;
10217 
10218  // no stream is used or end of file is reached
10219  if (m_stream == nullptr or m_stream->eof())
10220  {
10221  // m_start may or may not be pointing into m_line_buffer at
10222  // this point. We trust the standand library to do the right
10223  // thing. See http://stackoverflow.com/q/28142011/266378
10224  m_line_buffer.assign(m_start, m_limit);
10225 
10226  // append n characters to make sure that there is sufficient
10227  // space between m_cursor and m_limit
10228  m_line_buffer.append(1, '\x00');
10229  if (n > 0)
10230  {
10231  m_line_buffer.append(n - 1, '\x01');
10232  }
10233  }
10234  else
10235  {
10236  // delete processed characters from line buffer
10237  m_line_buffer.erase(0, num_processed_chars);
10238  // read next line from input stream
10239  m_line_buffer_tmp.clear();
10240  std::getline(*m_stream, m_line_buffer_tmp, '\n');
10241 
10242  // add line with newline symbol to the line buffer
10243  m_line_buffer += m_line_buffer_tmp;
10244  m_line_buffer.push_back('\n');
10245  }
10246 
10247  // set pointers
10248  m_content = reinterpret_cast<const lexer_char_t*>(m_line_buffer.data());
10249  assert(m_content != nullptr);
10250  m_start = m_content;
10251  m_marker = m_start + offset_marker;
10252  m_cursor = m_start + offset_cursor;
10253  m_limit = m_start + m_line_buffer.size();
10254  }
10255 
10257  string_t get_token_string() const
10258  {
10259  assert(m_start != nullptr);
10260  return string_t(reinterpret_cast<typename string_t::const_pointer>(m_start),
10261  static_cast<size_t>(m_cursor - m_start));
10262  }
10263 
10321  string_t get_string() const
10322  {
10323  assert(m_cursor - m_start >= 2);
10324 
10325  string_t result;
10326  result.reserve(static_cast<size_t>(m_cursor - m_start - 2));
10327 
10328  // iterate the result between the quotes
10329  for (const lexer_char_t* i = m_start + 1; i < m_cursor - 1; ++i)
10330  {
10331  // find next escape character
10332  auto e = std::find(i, m_cursor - 1, '\\');
10333  if (e != i)
10334  {
10335  // see https://github.com/nlohmann/json/issues/365#issuecomment-262874705
10336  for (auto k = i; k < e; k++)
10337  {
10338  result.push_back(static_cast<typename string_t::value_type>(*k));
10339  }
10340  i = e - 1; // -1 because of ++i
10341  }
10342  else
10343  {
10344  // processing escaped character
10345  // read next character
10346  ++i;
10347 
10348  switch (*i)
10349  {
10350  // the default escapes
10351  case 't':
10352  {
10353  result += "\t";
10354  break;
10355  }
10356  case 'b':
10357  {
10358  result += "\b";
10359  break;
10360  }
10361  case 'f':
10362  {
10363  result += "\f";
10364  break;
10365  }
10366  case 'n':
10367  {
10368  result += "\n";
10369  break;
10370  }
10371  case 'r':
10372  {
10373  result += "\r";
10374  break;
10375  }
10376  case '\\':
10377  {
10378  result += "\\";
10379  break;
10380  }
10381  case '/':
10382  {
10383  result += "/";
10384  break;
10385  }
10386  case '"':
10387  {
10388  result += "\"";
10389  break;
10390  }
10391 
10392  // unicode
10393  case 'u':
10394  {
10395  // get code xxxx from uxxxx
10396  auto codepoint = std::strtoul(std::string(reinterpret_cast<typename string_t::const_pointer>(i + 1),
10397  4).c_str(), nullptr, 16);
10398 
10399  // check if codepoint is a high surrogate
10400  if (codepoint >= 0xD800 and codepoint <= 0xDBFF)
10401  {
10402  // make sure there is a subsequent unicode
10403  if ((i + 6 >= m_limit) or * (i + 5) != '\\' or * (i + 6) != 'u')
10404  {
10405  throw std::invalid_argument("missing low surrogate");
10406  }
10407 
10408  // get code yyyy from uxxxx\uyyyy
10409  auto codepoint2 = std::strtoul(std::string(reinterpret_cast<typename string_t::const_pointer>
10410  (i + 7), 4).c_str(), nullptr, 16);
10411  result += to_unicode(codepoint, codepoint2);
10412  // skip the next 10 characters (xxxx\uyyyy)
10413  i += 10;
10414  }
10415  else if (codepoint >= 0xDC00 and codepoint <= 0xDFFF)
10416  {
10417  // we found a lone low surrogate
10418  throw std::invalid_argument("missing high surrogate");
10419  }
10420  else
10421  {
10422  // add unicode character(s)
10423  result += to_unicode(codepoint);
10424  // skip the next four characters (xxxx)
10425  i += 4;
10426  }
10427  break;
10428  }
10429  }
10430  }
10431  }
10432 
10433  return result;
10434  }
10435 
10449  long double str_to_float_t(long double* /* type */, char** endptr) const
10450  {
10451  return std::strtold(reinterpret_cast<typename string_t::const_pointer>(m_start), endptr);
10452  }
10453 
10467  double str_to_float_t(double* /* type */, char** endptr) const
10468  {
10469  return std::strtod(reinterpret_cast<typename string_t::const_pointer>(m_start), endptr);
10470  }
10471 
10485  float str_to_float_t(float* /* type */, char** endptr) const
10486  {
10487  return std::strtof(reinterpret_cast<typename string_t::const_pointer>(m_start), endptr);
10488  }
10489 
10511  void get_number(basic_json& result) const
10512  {
10513  assert(m_start != nullptr);
10514 
10515  const lexer::lexer_char_t* curptr = m_start;
10516 
10517  // accumulate the integer conversion result (unsigned for now)
10518  number_unsigned_t value = 0;
10519 
10520  // maximum absolute value of the relevant integer type
10521  number_unsigned_t max;
10522 
10523  // temporarily store the type to avoid unecessary bitfield access
10524  value_t type;
10525 
10526  // look for sign
10527  if (*curptr == '-')
10528  {
10529  type = value_t::number_integer;
10530  max = static_cast<uint64_t>((std::numeric_limits<number_integer_t>::max)()) + 1;
10531  curptr++;
10532  }
10533  else
10534  {
10535  type = value_t::number_unsigned;
10536  max = static_cast<uint64_t>((std::numeric_limits<number_unsigned_t>::max)());
10537  }
10538 
10539  // count the significant figures
10540  for (; curptr < m_cursor; curptr++)
10541  {
10542  // quickly skip tests if a digit
10543  if (*curptr < '0' || *curptr > '9')
10544  {
10545  if (*curptr == '.')
10546  {
10547  // don't count '.' but change to float
10548  type = value_t::number_float;
10549  continue;
10550  }
10551  // assume exponent (if not then will fail parse): change to
10552  // float, stop counting and record exponent details
10553  type = value_t::number_float;
10554  break;
10555  }
10556 
10557  // skip if definitely not an integer
10558  if (type != value_t::number_float)
10559  {
10560  auto digit = static_cast<number_unsigned_t>(*curptr - '0');
10561 
10562  // overflow if value * 10 + digit > max, move terms around
10563  // to avoid overflow in intermediate values
10564  if (value > (max - digit) / 10)
10565  {
10566  // overflow
10567  type = value_t::number_float;
10568  }
10569  else
10570  {
10571  // no overflow
10572  value = value * 10 + digit;
10573  }
10574  }
10575  }
10576 
10577  // save the value (if not a float)
10578  if (type == value_t::number_unsigned)
10579  {
10580  result.m_value.number_unsigned = value;
10581  }
10582  else if (type == value_t::number_integer)
10583  {
10584  // invariant: if we parsed a '-', the absolute value is between
10585  // 0 (we allow -0) and max == -INT64_MIN
10586  assert(value >= 0);
10587  assert(value <= max);
10588 
10589  if (value == max)
10590  {
10591  // we cannot simply negate value (== max == -INT64_MIN),
10592  // see https://github.com/nlohmann/json/issues/389
10593  result.m_value.number_integer = static_cast<number_integer_t>(INT64_MIN);
10594  }
10595  else
10596  {
10597  // all other values can be negated safely
10598  result.m_value.number_integer = -static_cast<number_integer_t>(value);
10599  }
10600  }
10601  else
10602  {
10603  // parse with strtod
10604  result.m_value.number_float = str_to_float_t(static_cast<number_float_t*>(nullptr), NULL);
10605 
10606  // replace infinity and NAN by null
10607  if (not std::isfinite(result.m_value.number_float))
10608  {
10609  type = value_t::null;
10610  result.m_value = basic_json::json_value();
10611  }
10612  }
10613 
10614  // save the type
10615  result.m_type = type;
10616  }
10617 
10618  private:
10620  std::istream* m_stream = nullptr;
10622  string_t m_line_buffer {};
10624  string_t m_line_buffer_tmp {};
10626  const lexer_char_t* m_content = nullptr;
10628  const lexer_char_t* m_start = nullptr;
10630  const lexer_char_t* m_marker = nullptr;
10632  const lexer_char_t* m_cursor = nullptr;
10634  const lexer_char_t* m_limit = nullptr;
10636  token_type last_token_type = token_type::end_of_input;
10637  };
10638 
10644  class parser
10645  {
10646  public:
10648  parser(const char* buff, const parser_callback_t cb = nullptr)
10649  : callback(cb),
10650  m_lexer(reinterpret_cast<const typename lexer::lexer_char_t*>(buff), std::strlen(buff))
10651  {}
10652 
10654  parser(std::istream& is, const parser_callback_t cb = nullptr)
10655  : callback(cb), m_lexer(is)
10656  {}
10657 
10659  template<class IteratorType, typename std::enable_if<
10660  std::is_same<typename std::iterator_traits<IteratorType>::iterator_category, std::random_access_iterator_tag>::value
10661  , int>::type
10662  = 0>
10663  parser(IteratorType first, IteratorType last, const parser_callback_t cb = nullptr)
10664  : callback(cb),
10665  m_lexer(reinterpret_cast<const typename lexer::lexer_char_t*>(&(*first)),
10666  static_cast<size_t>(std::distance(first, last)))
10667  {}
10668 
10670  basic_json parse()
10671  {
10672  // read first token
10673  get_token();
10674 
10675  basic_json result = parse_internal(true);
10676  result.assert_invariant();
10677 
10678  expect(lexer::token_type::end_of_input);
10679 
10680  // return parser result and replace it with null in case the
10681  // top-level value was discarded by the callback function
10682  return result.is_discarded() ? basic_json() : std::move(result);
10683  }
10684 
10685  private:
10687  basic_json parse_internal(bool keep)
10688  {
10689  auto result = basic_json(value_t::discarded);
10690 
10691  switch (last_token)
10692  {
10693  case lexer::token_type::begin_object:
10694  {
10695  if (keep and (not callback
10696  or ((keep = callback(depth++, parse_event_t::object_start, result)) != 0)))
10697  {
10698  // explicitly set result to object to cope with {}
10699  result.m_type = value_t::object;
10700  result.m_value = value_t::object;
10701  }
10702 
10703  // read next token
10704  get_token();
10705 
10706  // closing } -> we are done
10707  if (last_token == lexer::token_type::end_object)
10708  {
10709  get_token();
10710  if (keep and callback and not callback(--depth, parse_event_t::object_end, result))
10711  {
10712  result = basic_json(value_t::discarded);
10713  }
10714  return result;
10715  }
10716 
10717  // no comma is expected here
10718  unexpect(lexer::token_type::value_separator);
10719 
10720  // otherwise: parse key-value pairs
10721  do
10722  {
10723  // ugly, but could be fixed with loop reorganization
10724  if (last_token == lexer::token_type::value_separator)
10725  {
10726  get_token();
10727  }
10728 
10729  // store key
10730  expect(lexer::token_type::value_string);
10731  const auto key = m_lexer.get_string();
10732 
10733  bool keep_tag = false;
10734  if (keep)
10735  {
10736  if (callback)
10737  {
10738  basic_json k(key);
10739  keep_tag = callback(depth, parse_event_t::key, k);
10740  }
10741  else
10742  {
10743  keep_tag = true;
10744  }
10745  }
10746 
10747  // parse separator (:)
10748  get_token();
10749  expect(lexer::token_type::name_separator);
10750 
10751  // parse and add value
10752  get_token();
10753  auto value = parse_internal(keep);
10754  if (keep and keep_tag and not value.is_discarded())
10755  {
10756  result[key] = std::move(value);
10757  }
10758  }
10759  while (last_token == lexer::token_type::value_separator);
10760 
10761  // closing }
10762  expect(lexer::token_type::end_object);
10763  get_token();
10764  if (keep and callback and not callback(--depth, parse_event_t::object_end, result))
10765  {
10766  result = basic_json(value_t::discarded);
10767  }
10768 
10769  return result;
10770  }
10771 
10772  case lexer::token_type::begin_array:
10773  {
10774  if (keep and (not callback
10775  or ((keep = callback(depth++, parse_event_t::array_start, result)) != 0)))
10776  {
10777  // explicitly set result to object to cope with []
10778  result.m_type = value_t::array;
10779  result.m_value = value_t::array;
10780  }
10781 
10782  // read next token
10783  get_token();
10784 
10785  // closing ] -> we are done
10786  if (last_token == lexer::token_type::end_array)
10787  {
10788  get_token();
10789  if (callback and not callback(--depth, parse_event_t::array_end, result))
10790  {
10791  result = basic_json(value_t::discarded);
10792  }
10793  return result;
10794  }
10795 
10796  // no comma is expected here
10797  unexpect(lexer::token_type::value_separator);
10798 
10799  // otherwise: parse values
10800  do
10801  {
10802  // ugly, but could be fixed with loop reorganization
10803  if (last_token == lexer::token_type::value_separator)
10804  {
10805  get_token();
10806  }
10807 
10808  // parse value
10809  auto value = parse_internal(keep);
10810  if (keep and not value.is_discarded())
10811  {
10812  result.push_back(std::move(value));
10813  }
10814  }
10815  while (last_token == lexer::token_type::value_separator);
10816 
10817  // closing ]
10818  expect(lexer::token_type::end_array);
10819  get_token();
10820  if (keep and callback and not callback(--depth, parse_event_t::array_end, result))
10821  {
10822  result = basic_json(value_t::discarded);
10823  }
10824 
10825  return result;
10826  }
10827 
10828  case lexer::token_type::literal_null:
10829  {
10830  get_token();
10831  result.m_type = value_t::null;
10832  break;
10833  }
10834 
10835  case lexer::token_type::value_string:
10836  {
10837  const auto s = m_lexer.get_string();
10838  get_token();
10839  result = basic_json(s);
10840  break;
10841  }
10842 
10843  case lexer::token_type::literal_true:
10844  {
10845  get_token();
10846  result.m_type = value_t::boolean;
10847  result.m_value = true;
10848  break;
10849  }
10850 
10851  case lexer::token_type::literal_false:
10852  {
10853  get_token();
10854  result.m_type = value_t::boolean;
10855  result.m_value = false;
10856  break;
10857  }
10858 
10859  case lexer::token_type::value_number:
10860  {
10861  m_lexer.get_number(result);
10862  get_token();
10863  break;
10864  }
10865 
10866  default:
10867  {
10868  // the last token was unexpected
10869  unexpect(last_token);
10870  }
10871  }
10872 
10873  if (keep and callback and not callback(depth, parse_event_t::value, result))
10874  {
10875  result = basic_json(value_t::discarded);
10876  }
10877  return result;
10878  }
10879 
10881  typename lexer::token_type get_token()
10882  {
10883  last_token = m_lexer.scan();
10884  return last_token;
10885  }
10886 
10887  void expect(typename lexer::token_type t) const
10888  {
10889  if (t != last_token)
10890  {
10891  std::string error_msg = "parse error - unexpected ";
10892  error_msg += (last_token == lexer::token_type::parse_error ? ("'" + m_lexer.get_token_string() +
10893  "'") :
10894  lexer::token_type_name(last_token));
10895  error_msg += "; expected " + lexer::token_type_name(t);
10896  throw std::invalid_argument(error_msg);
10897  }
10898  }
10899 
10900  void unexpect(typename lexer::token_type t) const
10901  {
10902  if (t == last_token)
10903  {
10904  std::string error_msg = "parse error - unexpected ";
10905  error_msg += (last_token == lexer::token_type::parse_error ? ("'" + m_lexer.get_token_string() +
10906  "'") :
10907  lexer::token_type_name(last_token));
10908  throw std::invalid_argument(error_msg);
10909  }
10910  }
10911 
10912  private:
10914  int depth = 0;
10916  const parser_callback_t callback = nullptr;
10918  typename lexer::token_type last_token = lexer::token_type::uninitialized;
10920  lexer m_lexer;
10921  };
10922 
10923  public:
10936  {
10938  friend class basic_json;
10939 
10940  public:
10963  explicit json_pointer(const std::string& s = "")
10964  : reference_tokens(split(s))
10965  {}
10966 
10982  std::string to_string() const noexcept
10983  {
10984  return std::accumulate(reference_tokens.begin(),
10985  reference_tokens.end(), std::string{},
10986  [](const std::string & a, const std::string & b)
10987  {
10988  return a + "/" + escape(b);
10989  });
10990  }
10991 
10993  operator std::string() const
10994  {
10995  return to_string();
10996  }
10998  private:
11000  std::string pop_back()
11001  {
11002  if (is_root())
11003  {
11004  throw std::domain_error("JSON pointer has no parent");
11005  }
11006 
11007  auto last = reference_tokens.back();
11008  reference_tokens.pop_back();
11009  return last;
11010  }
11011 
11013  bool is_root() const
11014  {
11015  return reference_tokens.empty();
11016  }
11017 
11018  json_pointer top() const
11019  {
11020  if (is_root())
11021  {
11022  throw std::domain_error("JSON pointer has no parent");
11023  }
11024 
11025  json_pointer result = *this;
11026  result.reference_tokens = {reference_tokens[0]};
11027  return result;
11028  }
11029 
11035  reference get_and_create(reference j) const
11036  {
11037  pointer result = &j;
11038 
11039  // in case no reference tokens exist, return a reference to the
11040  // JSON value j which will be overwritten by a primitive value
11041  for (const auto& reference_token : reference_tokens)
11042  {
11043  switch (result->m_type)
11044  {
11045  case value_t::null:
11046  {
11047  if (reference_token == "0")
11048  {
11049  // start a new array if reference token is 0
11050  result = &result->operator[](0);
11051  }
11052  else
11053  {
11054  // start a new object otherwise
11055  result = &result->operator[](reference_token);
11056  }
11057  break;
11058  }
11059 
11060  case value_t::object:
11061  {
11062  // create an entry in the object
11063  result = &result->operator[](reference_token);
11064  break;
11065  }
11066 
11067  case value_t::array:
11068  {
11069  // create an entry in the array
11070  result = &result->operator[](static_cast<size_type>(std::stoi(reference_token)));
11071  break;
11072  }
11073 
11074  /*
11075  The following code is only reached if there exists a
11076  reference token _and_ the current value is primitive. In
11077  this case, we have an error situation, because primitive
11078  values may only occur as single value; that is, with an
11079  empty list of reference tokens.
11080  */
11081  default:
11082  {
11083  throw std::domain_error("invalid value to unflatten");
11084  }
11085  }
11086  }
11087 
11088  return *result;
11089  }
11090 
11110  reference get_unchecked(pointer ptr) const
11111  {
11112  for (const auto& reference_token : reference_tokens)
11113  {
11114  // convert null values to arrays or objects before continuing
11115  if (ptr->m_type == value_t::null)
11116  {
11117  // check if reference token is a number
11118  const bool nums = std::all_of(reference_token.begin(),
11119  reference_token.end(),
11120  [](const char x)
11121  {
11122  return std::isdigit(x);
11123  });
11124 
11125  // change value to array for numbers or "-" or to object
11126  // otherwise
11127  if (nums or reference_token == "-")
11128  {
11129  *ptr = value_t::array;
11130  }
11131  else
11132  {
11133  *ptr = value_t::object;
11134  }
11135  }
11136 
11137  switch (ptr->m_type)
11138  {
11139  case value_t::object:
11140  {
11141  // use unchecked object access
11142  ptr = &ptr->operator[](reference_token);
11143  break;
11144  }
11145 
11146  case value_t::array:
11147  {
11148  // error condition (cf. RFC 6901, Sect. 4)
11149  if (reference_token.size() > 1 and reference_token[0] == '0')
11150  {
11151  throw std::domain_error("array index must not begin with '0'");
11152  }
11153 
11154  if (reference_token == "-")
11155  {
11156  // explicityly treat "-" as index beyond the end
11157  ptr = &ptr->operator[](ptr->m_value.array->size());
11158  }
11159  else
11160  {
11161  // convert array index to number; unchecked access
11162  ptr = &ptr->operator[](static_cast<size_type>(std::stoi(reference_token)));
11163  }
11164  break;
11165  }
11166 
11167  default:
11168  {
11169  throw std::out_of_range("unresolved reference token '" + reference_token + "'");
11170  }
11171  }
11172  }
11173 
11174  return *ptr;
11175  }
11176 
11177  reference get_checked(pointer ptr) const
11178  {
11179  for (const auto& reference_token : reference_tokens)
11180  {
11181  switch (ptr->m_type)
11182  {
11183  case value_t::object:
11184  {
11185  // note: at performs range check
11186  ptr = &ptr->at(reference_token);
11187  break;
11188  }
11189 
11190  case value_t::array:
11191  {
11192  if (reference_token == "-")
11193  {
11194  // "-" always fails the range check
11195  throw std::out_of_range("array index '-' (" +
11196  std::to_string(ptr->m_value.array->size()) +
11197  ") is out of range");
11198  }
11199 
11200  // error condition (cf. RFC 6901, Sect. 4)
11201  if (reference_token.size() > 1 and reference_token[0] == '0')
11202  {
11203  throw std::domain_error("array index must not begin with '0'");
11204  }
11205 
11206  // note: at performs range check
11207  ptr = &ptr->at(static_cast<size_type>(std::stoi(reference_token)));
11208  break;
11209  }
11210 
11211  default:
11212  {
11213  throw std::out_of_range("unresolved reference token '" + reference_token + "'");
11214  }
11215  }
11216  }
11217 
11218  return *ptr;
11219  }
11220 
11229  const_reference get_unchecked(const_pointer ptr) const
11230  {
11231  for (const auto& reference_token : reference_tokens)
11232  {
11233  switch (ptr->m_type)
11234  {
11235  case value_t::object:
11236  {
11237  // use unchecked object access
11238  ptr = &ptr->operator[](reference_token);
11239  break;
11240  }
11241 
11242  case value_t::array:
11243  {
11244  if (reference_token == "-")
11245  {
11246  // "-" cannot be used for const access
11247  throw std::out_of_range("array index '-' (" +
11248  std::to_string(ptr->m_value.array->size()) +
11249  ") is out of range");
11250  }
11251 
11252  // error condition (cf. RFC 6901, Sect. 4)
11253  if (reference_token.size() > 1 and reference_token[0] == '0')
11254  {
11255  throw std::domain_error("array index must not begin with '0'");
11256  }
11257 
11258  // use unchecked array access
11259  ptr = &ptr->operator[](static_cast<size_type>(std::stoi(reference_token)));
11260  break;
11261  }
11262 
11263  default:
11264  {
11265  throw std::out_of_range("unresolved reference token '" + reference_token + "'");
11266  }
11267  }
11268  }
11269 
11270  return *ptr;
11271  }
11272 
11273  const_reference get_checked(const_pointer ptr) const
11274  {
11275  for (const auto& reference_token : reference_tokens)
11276  {
11277  switch (ptr->m_type)
11278  {
11279  case value_t::object:
11280  {
11281  // note: at performs range check
11282  ptr = &ptr->at(reference_token);
11283  break;
11284  }
11285 
11286  case value_t::array:
11287  {
11288  if (reference_token == "-")
11289  {
11290  // "-" always fails the range check
11291  throw std::out_of_range("array index '-' (" +
11292  std::to_string(ptr->m_value.array->size()) +
11293  ") is out of range");
11294  }
11295 
11296  // error condition (cf. RFC 6901, Sect. 4)
11297  if (reference_token.size() > 1 and reference_token[0] == '0')
11298  {
11299  throw std::domain_error("array index must not begin with '0'");
11300  }
11301 
11302  // note: at performs range check
11303  ptr = &ptr->at(static_cast<size_type>(std::stoi(reference_token)));
11304  break;
11305  }
11306 
11307  default:
11308  {
11309  throw std::out_of_range("unresolved reference token '" + reference_token + "'");
11310  }
11311  }
11312  }
11313 
11314  return *ptr;
11315  }
11316 
11318  static std::vector<std::string> split(const std::string& reference_string)
11319  {
11320  std::vector<std::string> result;
11321 
11322  // special case: empty reference string -> no reference tokens
11323  if (reference_string.empty())
11324  {
11325  return result;
11326  }
11327 
11328  // check if nonempty reference string begins with slash
11329  if (reference_string[0] != '/')
11330  {
11331  throw std::domain_error("JSON pointer must be empty or begin with '/'");
11332  }
11333 
11334  // extract the reference tokens:
11335  // - slash: position of the last read slash (or end of string)
11336  // - start: position after the previous slash
11337  for (
11338  // search for the first slash after the first character
11339  size_t slash = reference_string.find_first_of("/", 1),
11340  // set the beginning of the first reference token
11341  start = 1;
11342  // we can stop if start == string::npos+1 = 0
11343  start != 0;
11344  // set the beginning of the next reference token
11345  // (will eventually be 0 if slash == std::string::npos)
11346  start = slash + 1,
11347  // find next slash
11348  slash = reference_string.find_first_of("/", start))
11349  {
11350  // use the text between the beginning of the reference token
11351  // (start) and the last slash (slash).
11352  auto reference_token = reference_string.substr(start, slash - start);
11353 
11354  // check reference tokens are properly escaped
11355  for (size_t pos = reference_token.find_first_of("~");
11356  pos != std::string::npos;
11357  pos = reference_token.find_first_of("~", pos + 1))
11358  {
11359  assert(reference_token[pos] == '~');
11360 
11361  // ~ must be followed by 0 or 1
11362  if (pos == reference_token.size() - 1 or
11363  (reference_token[pos + 1] != '0' and
11364  reference_token[pos + 1] != '1'))
11365  {
11366  throw std::domain_error("escape error: '~' must be followed with '0' or '1'");
11367  }
11368  }
11369 
11370  // finally, store the reference token
11371  unescape(reference_token);
11372  result.push_back(reference_token);
11373  }
11374 
11375  return result;
11376  }
11377 
11378  private:
11391  static void replace_substring(std::string& s,
11392  const std::string& f,
11393  const std::string& t)
11394  {
11395  assert(not f.empty());
11396 
11397  for (
11398  size_t pos = s.find(f); // find first occurrence of f
11399  pos != std::string::npos; // make sure f was found
11400  s.replace(pos, f.size(), t), // replace with t
11401  pos = s.find(f, pos + t.size()) // find next occurrence of f
11402  );
11403  }
11404 
11406  static std::string escape(std::string s)
11407  {
11408  // escape "~"" to "~0" and "/" to "~1"
11409  replace_substring(s, "~", "~0");
11410  replace_substring(s, "/", "~1");
11411  return s;
11412  }
11413 
11415  static void unescape(std::string& s)
11416  {
11417  // first transform any occurrence of the sequence '~1' to '/'
11418  replace_substring(s, "~1", "/");
11419  // then transform any occurrence of the sequence '~0' to '~'
11420  replace_substring(s, "~0", "~");
11421  }
11422 
11430  static void flatten(const std::string& reference_string,
11431  const basic_json& value,
11432  basic_json& result)
11433  {
11434  switch (value.m_type)
11435  {
11436  case value_t::array:
11437  {
11438  if (value.m_value.array->empty())
11439  {
11440  // flatten empty array as null
11441  result[reference_string] = nullptr;
11442  }
11443  else
11444  {
11445  // iterate array and use index as reference string
11446  for (size_t i = 0; i < value.m_value.array->size(); ++i)
11447  {
11448  flatten(reference_string + "/" + std::to_string(i),
11449  value.m_value.array->operator[](i), result);
11450  }
11451  }
11452  break;
11453  }
11454 
11455  case value_t::object:
11456  {
11457  if (value.m_value.object->empty())
11458  {
11459  // flatten empty object as null
11460  result[reference_string] = nullptr;
11461  }
11462  else
11463  {
11464  // iterate object and use keys as reference string
11465  for (const auto& element : *value.m_value.object)
11466  {
11467  flatten(reference_string + "/" + escape(element.first),
11468  element.second, result);
11469  }
11470  }
11471  break;
11472  }
11473 
11474  default:
11475  {
11476  // add primitive value with its reference string
11477  result[reference_string] = value;
11478  break;
11479  }
11480  }
11481  }
11482 
11488  static basic_json unflatten(const basic_json& value)
11489  {
11490  if (not value.is_object())
11491  {
11492  throw std::domain_error("only objects can be unflattened");
11493  }
11494 
11495  basic_json result;
11496 
11497  // iterate the JSON object values
11498  for (const auto& element : *value.m_value.object)
11499  {
11500  if (not element.second.is_primitive())
11501  {
11502  throw std::domain_error("values in object must be primitive");
11503  }
11504 
11505  // assign value to reference pointed to by JSON pointer; Note
11506  // that if the JSON pointer is "" (i.e., points to the whole
11507  // value), function get_and_create returns a reference to
11508  // result itself. An assignment will then create a primitive
11509  // value.
11510  json_pointer(element.first).get_and_create(result) = element.second;
11511  }
11512 
11513  return result;
11514  }
11515 
11516  private:
11518  std::vector<std::string> reference_tokens {};
11519  };
11520 
11522  // JSON Pointer support //
11524 
11527 
11561  reference operator[](const json_pointer& ptr)
11562  {
11563  return ptr.get_unchecked(this);
11564  }
11588  const_reference operator[](const json_pointer& ptr) const
11589  {
11590  return ptr.get_unchecked(this);
11591  }
11613  reference at(const json_pointer& ptr)
11614  {
11615  return ptr.get_checked(this);
11616  }
11638  const_reference at(const json_pointer& ptr) const
11639  {
11640  return ptr.get_checked(this);
11641  }
11665  basic_json flatten() const
11666  {
11667  basic_json result(value_t::object);
11668  json_pointer::flatten("", *this, result);
11669  return result;
11670  }
11671 
11699  basic_json unflatten() const
11700  {
11701  return json_pointer::unflatten(*this);
11702  }
11705 
11707  // JSON Patch functions //
11709 
11712 
11749  basic_json patch(const basic_json& json_patch) const
11750  {
11751  // make a working copy to apply the patch to
11752  basic_json result = *this;
11754  // the valid JSON Patch operations
11755  enum class patch_operations {add, remove, replace, move, copy, test, invalid};
11756 
11757  const auto get_op = [](const std::string op)
11758  {
11759  if (op == "add")
11760  {
11761  return patch_operations::add;
11762  }
11763  if (op == "remove")
11764  {
11765  return patch_operations::remove;
11766  }
11767  if (op == "replace")
11768  {
11769  return patch_operations::replace;
11770  }
11771  if (op == "move")
11772  {
11773  return patch_operations::move;
11774  }
11775  if (op == "copy")
11776  {
11777  return patch_operations::copy;
11778  }
11779  if (op == "test")
11780  {
11781  return patch_operations::test;
11782  }
11783 
11784  return patch_operations::invalid;
11785  };
11786 
11787  // wrapper for "add" operation; add value at ptr
11788  const auto operation_add = [&result](json_pointer & ptr, basic_json val)
11789  {
11790  // adding to the root of the target document means replacing it
11791  if (ptr.is_root())
11792  {
11793  result = val;
11794  }
11795  else
11796  {
11797  // make sure the top element of the pointer exists
11798  json_pointer top_pointer = ptr.top();
11799  if (top_pointer != ptr)
11800  {
11801  result.at(top_pointer);
11802  }
11803 
11804  // get reference to parent of JSON pointer ptr
11805  const auto last_path = ptr.pop_back();
11806  basic_json& parent = result[ptr];
11807 
11808  switch (parent.m_type)
11809  {
11810  case value_t::null:
11811  case value_t::object:
11812  {
11813  // use operator[] to add value
11814  parent[last_path] = val;
11815  break;
11816  }
11817 
11818  case value_t::array:
11819  {
11820  if (last_path == "-")
11821  {
11822  // special case: append to back
11823  parent.push_back(val);
11824  }
11825  else
11826  {
11827  const auto idx = std::stoi(last_path);
11828  if (static_cast<size_type>(idx) > parent.size())
11829  {
11830  // avoid undefined behavior
11831  throw std::out_of_range("array index " + std::to_string(idx) + " is out of range");
11832  }
11833  else
11834  {
11835  // default case: insert add offset
11836  parent.insert(parent.begin() + static_cast<difference_type>(idx), val);
11837  }
11838  }
11839  break;
11840  }
11841 
11842  default:
11843  {
11844  // if there exists a parent it cannot be primitive
11845  assert(false); // LCOV_EXCL_LINE
11846  }
11847  }
11848  }
11849  };
11850 
11851  // wrapper for "remove" operation; remove value at ptr
11852  const auto operation_remove = [&result](json_pointer & ptr)
11853  {
11854  // get reference to parent of JSON pointer ptr
11855  const auto last_path = ptr.pop_back();
11856  basic_json& parent = result.at(ptr);
11857 
11858  // remove child
11859  if (parent.is_object())
11860  {
11861  // perform range check
11862  auto it = parent.find(last_path);
11863  if (it != parent.end())
11864  {
11865  parent.erase(it);
11866  }
11867  else
11868  {
11869  throw std::out_of_range("key '" + last_path + "' not found");
11870  }
11871  }
11872  else if (parent.is_array())
11873  {
11874  // note erase performs range check
11875  parent.erase(static_cast<size_type>(std::stoi(last_path)));
11876  }
11877  };
11878 
11879  // type check
11880  if (not json_patch.is_array())
11881  {
11882  // a JSON patch must be an array of objects
11883  throw std::invalid_argument("JSON patch must be an array of objects");
11884  }
11885 
11886  // iterate and apply th eoperations
11887  for (const auto& val : json_patch)
11888  {
11889  // wrapper to get a value for an operation
11890  const auto get_value = [&val](const std::string & op,
11891  const std::string & member,
11892  bool string_type) -> basic_json&
11893  {
11894  // find value
11895  auto it = val.m_value.object->find(member);
11896 
11897  // context-sensitive error message
11898  const auto error_msg = (op == "op") ? "operation" : "operation '" + op + "'";
11899 
11900  // check if desired value is present
11901  if (it == val.m_value.object->end())
11902  {
11903  throw std::invalid_argument(error_msg + " must have member '" + member + "'");
11904  }
11905 
11906  // check if result is of type string
11907  if (string_type and not it->second.is_string())
11908  {
11909  throw std::invalid_argument(error_msg + " must have string member '" + member + "'");
11910  }
11911 
11912  // no error: return value
11913  return it->second;
11914  };
11915 
11916  // type check
11917  if (not val.is_object())
11918  {
11919  throw std::invalid_argument("JSON patch must be an array of objects");
11920  }
11921 
11922  // collect mandatory members
11923  const std::string op = get_value("op", "op", true);
11924  const std::string path = get_value(op, "path", true);
11925  json_pointer ptr(path);
11926 
11927  switch (get_op(op))
11928  {
11929  case patch_operations::add:
11930  {
11931  operation_add(ptr, get_value("add", "value", false));
11932  break;
11933  }
11934 
11935  case patch_operations::remove:
11936  {
11937  operation_remove(ptr);
11938  break;
11939  }
11940 
11941  case patch_operations::replace:
11942  {
11943  // the "path" location must exist - use at()
11944  result.at(ptr) = get_value("replace", "value", false);
11945  break;
11946  }
11947 
11948  case patch_operations::move:
11949  {
11950  const std::string from_path = get_value("move", "from", true);
11951  json_pointer from_ptr(from_path);
11952 
11953  // the "from" location must exist - use at()
11954  basic_json v = result.at(from_ptr);
11955 
11956  // The move operation is functionally identical to a
11957  // "remove" operation on the "from" location, followed
11958  // immediately by an "add" operation at the target
11959  // location with the value that was just removed.
11960  operation_remove(from_ptr);
11961  operation_add(ptr, v);
11962  break;
11963  }
11964 
11965  case patch_operations::copy:
11966  {
11967  const std::string from_path = get_value("copy", "from", true);;
11968  const json_pointer from_ptr(from_path);
11969 
11970  // the "from" location must exist - use at()
11971  result[ptr] = result.at(from_ptr);
11972  break;
11973  }
11974 
11975  case patch_operations::test:
11976  {
11977  bool success = false;
11978  try
11979  {
11980  // check if "value" matches the one at "path"
11981  // the "path" location must exist - use at()
11982  success = (result.at(ptr) == get_value("test", "value", false));
11983  }
11984  catch (std::out_of_range&)
11985  {
11986  // ignore out of range errors: success remains false
11987  }
11988 
11989  // throw an exception if test fails
11990  if (not success)
11991  {
11992  throw std::domain_error("unsuccessful: " + val.dump());
11993  }
11994 
11995  break;
11996  }
11997 
11998  case patch_operations::invalid:
11999  {
12000  // op must be "add", "remove", "replace", "move", "copy", or
12001  // "test"
12002  throw std::invalid_argument("operation value '" + op + "' is invalid");
12003  }
12004  }
12005  }
12006 
12007  return result;
12008  }
12009 
12042  static basic_json diff(const basic_json& source,
12043  const basic_json& target,
12044  const std::string& path = "")
12045  {
12046  // the patch
12047  basic_json result(value_t::array);
12048 
12049  // if the values are the same, return empty patch
12050  if (source == target)
12051  {
12052  return result;
12053  }
12054 
12055  if (source.type() != target.type())
12056  {
12057  // different types: replace value
12058  result.push_back(
12059  {
12060  {"op", "replace"},
12061  {"path", path},
12062  {"value", target}
12063  });
12064  }
12065  else
12066  {
12067  switch (source.type())
12068  {
12069  case value_t::array:
12070  {
12071  // first pass: traverse common elements
12072  size_t i = 0;
12073  while (i < source.size() and i < target.size())
12074  {
12075  // recursive call to compare array values at index i
12076  auto temp_diff = diff(source[i], target[i], path + "/" + std::to_string(i));
12077  result.insert(result.end(), temp_diff.begin(), temp_diff.end());
12078  ++i;
12079  }
12080 
12081  // i now reached the end of at least one array
12082  // in a second pass, traverse the remaining elements
12083 
12084  // remove my remaining elements
12085  const auto end_index = static_cast<difference_type>(result.size());
12086  while (i < source.size())
12087  {
12088  // add operations in reverse order to avoid invalid
12089  // indices
12090  result.insert(result.begin() + end_index, object(
12091  {
12092  {"op", "remove"},
12093  {"path", path + "/" + std::to_string(i)}
12094  }));
12095  ++i;
12096  }
12097 
12098  // add other remaining elements
12099  while (i < target.size())
12100  {
12101  result.push_back(
12102  {
12103  {"op", "add"},
12104  {"path", path + "/" + std::to_string(i)},
12105  {"value", target[i]}
12106  });
12107  ++i;
12108  }
12109 
12110  break;
12111  }
12112 
12113  case value_t::object:
12114  {
12115  // first pass: traverse this object's elements
12116  for (auto it = source.begin(); it != source.end(); ++it)
12117  {
12118  // escape the key name to be used in a JSON patch
12119  const auto key = json_pointer::escape(it.key());
12120 
12121  if (target.find(it.key()) != target.end())
12122  {
12123  // recursive call to compare object values at key it
12124  auto temp_diff = diff(it.value(), target[it.key()], path + "/" + key);
12125  result.insert(result.end(), temp_diff.begin(), temp_diff.end());
12126  }
12127  else
12128  {
12129  // found a key that is not in o -> remove it
12130  result.push_back(object(
12131  {
12132  {"op", "remove"},
12133  {"path", path + "/" + key}
12134  }));
12135  }
12136  }
12137 
12138  // second pass: traverse other object's elements
12139  for (auto it = target.begin(); it != target.end(); ++it)
12140  {
12141  if (source.find(it.key()) == source.end())
12142  {
12143  // found a key that is not in this -> add it
12144  const auto key = json_pointer::escape(it.key());
12145  result.push_back(
12146  {
12147  {"op", "add"},
12148  {"path", path + "/" + key},
12149  {"value", it.value()}
12150  });
12151  }
12152  }
12153 
12154  break;
12155  }
12156 
12157  default:
12158  {
12159  // both primitive type: replace value
12160  result.push_back(
12161  {
12162  {"op", "replace"},
12163  {"path", path},
12164  {"value", target}
12165  });
12166  break;
12167  }
12168  }
12169  }
12170 
12171  return result;
12172  }
12173 
12175 };
12176 
12177 
12179 // presets //
12181 
12190 using json = basic_json<>;
12191 }
12192 
12193 
12195 // nonmember support //
12197 
12198 // specialization of std::swap, and std::hash
12199 namespace std
12200 {
12206 template<>
12207 inline void swap(nlohmann::json& j1,
12208  nlohmann::json& j2) noexcept(
12209  is_nothrow_move_constructible<nlohmann::json>::value and
12210  is_nothrow_move_assignable<nlohmann::json>::value
12211  )
12212 {
12213  j1.swap(j2);
12214 }
12215 
12217 template<>
12218 struct hash<nlohmann::json>
12219 {
12225  std::size_t operator()(const nlohmann::json& j) const
12226  {
12227  // a naive hashing via the string representation
12228  const auto& h = hash<nlohmann::json::string_t>();
12229  return h(j.dump());
12230  }
12231 };
12232 }
12233 
12247 inline nlohmann::json operator "" _json(const char* s, std::size_t n)
12248 {
12249  return nlohmann::json::parse(s, s + n);
12250 }
12251 
12265 inline nlohmann::json::json_pointer operator "" _json_pointer(const char* s, std::size_t n)
12266 {
12267  return nlohmann::json::json_pointer(std::string(s, n));
12268 }
12269 
12270 // restore GCC/clang diagnostic settings
12271 #if defined(__clang__) || defined(__GNUC__) || defined(__GNUG__)
12272  #pragma GCC diagnostic pop
12273 #endif
12274 
12275 #endif
size_type max_size() const noexcept
returns the maximum possible number of elements
Definition: json.hpp:4762
friend bool operator<=(const_reference lhs, const_reference rhs) noexcept
comparison: less than or equal
Definition: json.hpp:5832
constexpr value_t type() const noexcept
return the type of the JSON value (explicit)
Definition: json.hpp:2238
constexpr bool is_array() const noexcept
return whether value is an array
Definition: json.hpp:2498
const_reference at(const typename object_t::key_type &key) const
access specified object element with bounds checking
Definition: json.hpp:3283
basic_json(const value_t value_type)
create an empty value with a given type
Definition: json.hpp:1063
bool operator>(const iter_impl &other) const
comparison: greater than
Definition: json.hpp:8730
basic_json(const array_t &val)
create an array (explicit)
Definition: json.hpp:1175
reference value() const
return the value of an iterator
Definition: json.hpp:9011
const_iterator end() const noexcept
returns a const iterator to one past the last element
Definition: json.hpp:4384
constexpr bool is_primitive() const noexcept
return whether type is primitive
Definition: json.hpp:2268
constexpr bool is_null() const noexcept
return whether value is null
Definition: json.hpp:2317
ValueType get() const
get a value (explicit)
Definition: json.hpp:2896
const_reverse_iterator rend() const noexcept
returns a const reverse iterator to one before the first
Definition: json.hpp:4489
constexpr bool is_structured() const noexcept
return whether type is structured
Definition: json.hpp:2295
json_reverse_iterator & operator--()
pre-decrement (–it)
Definition: json.hpp:8962
void clear() noexcept
clears the contents
Definition: json.hpp:4818
const_reference operator[](size_type idx) const
access specified array element
Definition: json.hpp:3377
json_reverse_iterator operator--(int)
post-decrement (it–)
Definition: json.hpp:8956
reference operator[](T *(&key)[n])
access specified object element
Definition: json.hpp:3510
friend std::istream & operator>>(std::istream &i, basic_json &j)
deserialize from stream
Definition: json.hpp:6232
bool operator!=(const iter_impl &other) const
comparison: not equal
Definition: json.hpp:8679
iter_impl operator++(int)
post-increment (it++)
Definition: json.hpp:8560
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:1756
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:4263
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:6120
constexpr bool is_number_unsigned() const noexcept
return whether value is an unsigned integer number
Definition: json.hpp:2426
BooleanType boolean_t
a type for a boolean
Definition: json.hpp:501
reference operator+=(const typename object_t::value_type &val)
add an object to an object
Definition: json.hpp:5001
basic_json(const typename string_t::value_type *val)
create a string (explicit)
Definition: json.hpp:1271
iterator find(typename object_t::key_type key)
find an element in a JSON object
Definition: json.hpp:4214
friend bool operator!=(const_reference lhs, const_reference rhs) noexcept
comparison: not equal
Definition: json.hpp:5676
bool operator<=(const iter_impl &other) const
comparison: less than or equal
Definition: json.hpp:8721
basic_json(const string_t &val)
create a string (explicit)
Definition: json.hpp:1245
void push_back(const basic_json &val)
add an object to an array
Definition: json.hpp:4927
void erase(const size_type idx)
remove element from a JSON array given an index
Definition: json.hpp:4164
ArrayType< basic_json, AllocatorType< basic_json >> array_t
a type for an array
Definition: json.hpp:428
bool operator==(const iter_impl &other) const
comparison: equal
Definition: json.hpp:8646
reference front()
access the first element
Definition: json.hpp:3823
void swap(object_t &other)
exchanges the values
Definition: json.hpp:5440
a class to store JSON values
Definition: json.hpp:221
basic_json(const int val) noexcept
create an integer number from an enum type (explicit)
Definition: json.hpp:1385
static basic_json parse(T(&array)[N], const parser_callback_t cb=nullptr)
deserialize from an array
Definition: json.hpp:5992
constexpr bool is_object() const noexcept
return whether value is an object
Definition: json.hpp:2476
friend bool operator==(std::nullptr_t, const_reference v) noexcept
comparison: equal
Definition: json.hpp:5655
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:3720
NumberIntegerType number_integer_t
a type for a number (integer)
Definition: json.hpp:573
iterator insert(const_iterator pos, size_type cnt, const basic_json &val)
inserts elements
Definition: json.hpp:5228
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:7723
iter_impl(pointer object) noexcept
constructor for a given JSON instance
Definition: json.hpp:8336
constexpr bool is_number_integer() const noexcept
return whether value is an integer number
Definition: json.hpp:2398
ObjectType< StringType, basic_json, std::less< StringType >, AllocatorType< std::pair< const StringType, basic_json >>> object_t
a type for an object
Definition: json.hpp:382
STL namespace.
NumberUnsignedType number_unsigned_t
a type for a number (unsigned)
Definition: json.hpp:644
json_reverse_iterator operator-(difference_type i) const
subtract from iterator
Definition: json.hpp:8984
typename std::allocator_traits< allocator_type >::const_pointer const_pointer
the type of an element const pointer
Definition: json.hpp:263
static basic_json parse(std::istream &&i, const parser_callback_t cb=nullptr)
deserialize from stream
Definition: json.hpp:6069
basic_json(const number_integer_t val) noexcept
create an integer number (explicit)
Definition: json.hpp:1354
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:1716
static iteration_proxy< const_iterator > iterator_wrapper(const_reference cont)
wrapper to access iterator member functions in range-based for
Definition: json.hpp:4576
const_reference front() const
access the first element
Definition: json.hpp:3831
iter_impl(const iter_impl &other) noexcept
copy constructor
Definition: json.hpp:8389
static basic_json parse(const CharT s, const parser_callback_t cb=nullptr)
deserialize from string literal
Definition: json.hpp:6030
reference operator[](difference_type n) const
access to successor
Definition: json.hpp:8837
void emplace_back(Args &&... args)
add an object to an array
Definition: json.hpp:5077
friend class basic_json
allow basic_json to access private members
Definition: json.hpp:8304
json_reverse_iterator(const typename base_iterator::iterator_type &it) noexcept
create reverse iterator from iterator
Definition: json.hpp:8933
PointerType get_ptr() noexcept
get a pointer value (implicit)
Definition: json.hpp:2976
const_iterator cbegin() const noexcept
returns a const iterator to the first element
Definition: json.hpp:4343
reference back()
access the last element
Definition: json.hpp:3866
const value_type & const_reference
the type of an element const reference
Definition: json.hpp:250
IteratorType erase(IteratorType first, IteratorType last)
remove elements given an iterator range
Definition: json.hpp:4039
void push_back(const typename object_t::value_type &val)
add an object to an object
Definition: json.hpp:4977
bool empty() const noexcept
checks whether the container is empty
Definition: json.hpp:4628
void push_back(std::initializer_list< basic_json > init)
add an object to an object
Definition: json.hpp:5032
json_pointer(const std::string &s="")
create JSON pointer
Definition: json.hpp:10963
iterator insert(const_iterator pos, const_iterator first, const_iterator last)
inserts elements
Definition: json.hpp:5280
constexpr const PointerType get_ptr() const noexcept
get a pointer value (implicit)
Definition: json.hpp:3004
constexpr bool is_number_float() const noexcept
return whether value is a floating-point number
Definition: json.hpp:2454
basic_json(InputIT first, InputIT last)
construct a JSON container given an iterator range
Definition: json.hpp:1827
basic_json(std::nullptr_t=nullptr) noexcept
create a null object
Definition: json.hpp:1087
IteratorType erase(IteratorType pos)
remove element given an iterator
Definition: json.hpp:3932
static allocator_type get_allocator()
returns the allocator associated with the container
Definition: json.hpp:280
json_reverse_iterator operator+(difference_type i) const
add to iterator
Definition: json.hpp:8976
string_t dump(const int indent=-1) const
serialization
Definition: json.hpp:2196
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:2091
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:5375
std::size_t size_type
a type to represent container sizes
Definition: json.hpp:255
JSON_DEPRECATED basic_json(std::istream &i, const parser_callback_t cb=nullptr)
construct a JSON value given an input stream
Definition: json.hpp:1945
basic_json(const CompatibleArrayType &val)
create an array (implicit)
Definition: json.hpp:1215
basic_json(size_type cnt, const basic_json &val)
construct an array with count copies of given value
Definition: json.hpp:1780
std::reverse_iterator< Base > base_iterator
shortcut to the reverse iterator adaptor
Definition: json.hpp:8928
object_t::key_type key() const
return the key of an object iterator
Definition: json.hpp:9004
iter_impl operator-(difference_type i)
subtract from iterator
Definition: json.hpp:8799
iterator insert(const_iterator pos, std::initializer_list< basic_json > ilist)
inserts elements
Definition: json.hpp:5338
typename std::allocator_traits< allocator_type >::pointer pointer
the type of an element pointer
Definition: json.hpp:261
iterator insert(const_iterator pos, const basic_json &val)
inserts element
Definition: json.hpp:5173
friend bool operator>=(const_reference lhs, const_reference rhs) noexcept
comparison: greater than or equal
Definition: json.hpp:5876
friend bool operator<(const_reference lhs, const_reference rhs) noexcept
comparison: less than
Definition: json.hpp:5737
const_reverse_iterator rbegin() const noexcept
returns a const reverse iterator to the last element
Definition: json.hpp:4452
basic_json(basic_json &&other) noexcept
move constructor
Definition: json.hpp:2054
iter_impl & operator-=(difference_type i)
subtract from iterator
Definition: json.hpp:8779
reference at(const typename object_t::key_type &key)
access specified object element with bounds checking
Definition: json.hpp:3236
object (unordered set of name/value pairs)
~basic_json()
destructor
Definition: json.hpp:2124
basic_json value_type
the type of elements in a basic_json container
Definition: json.hpp:245
std::function< bool(int depth, parse_event_t event, basic_json &parsed)> parser_callback_t
per-element parser callback type
Definition: json.hpp:1012
AllocatorType< basic_json > allocator_type
the allocator type
Definition: json.hpp:258
StringType string_t
a type for a string
Definition: json.hpp:475
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:8398
typename basic_json::difference_type difference_type
a type to represent differences between iterators
Definition: json.hpp:8315
reference operator+=(const basic_json &val)
add an object to an array
Definition: json.hpp:4951
static basic_json parse(const ContiguousContainer &c, const parser_callback_t cb=nullptr)
deserialize from a container with contiguous storage
Definition: json.hpp:6192
reference operator+=(std::initializer_list< basic_json > init)
add an object to an object
Definition: json.hpp:5049
ReferenceType get_ref() const
get a reference value (implicit)
Definition: json.hpp:3066
friend std::ostream & operator>>(const basic_json &j, std::ostream &o)
serialize to stream
Definition: json.hpp:5949
size_type size() const noexcept
returns the number of elements
Definition: json.hpp:4696
namespace for Niels Lohmann
Definition: json.hpp:98
constexpr bool is_string() const noexcept
return whether value is a string
Definition: json.hpp:2520
void swap(string_t &other)
exchanges the values
Definition: json.hpp:5473
reference operator[](difference_type n) const
access to successor
Definition: json.hpp:8998
basic_json(const CompatibleNumberIntegerType val) noexcept
create an integer number (implicit)
Definition: json.hpp:1422
const_reference at(size_type idx) const
access specified array element with bounds checking
Definition: json.hpp:3189
iter_impl & operator++()
pre-increment (++it)
Definition: json.hpp:8571
ValueType value(const typename object_t::key_type &key, ValueType default_value) const
access specified object element with default value
Definition: json.hpp:3694
const_reference operator[](T *key) const
read-only access specified object element
Definition: json.hpp:3630
NumberFloatType number_float_t
a type for a number (floating-point)
Definition: json.hpp:712
difference_type operator-(const iter_impl &other) const
return difference
Definition: json.hpp:8810
value_t
the JSON type enumeration
Definition: json.hpp:743
reverse_iterator rbegin() noexcept
returns an iterator to the reverse-beginning
Definition: json.hpp:4444
std::ptrdiff_t difference_type
a type to represent differences between iterators
Definition: json.hpp:253
void swap(array_t &other)
exchanges the values
Definition: json.hpp:5407
std::pair< iterator, bool > emplace(Args &&... args)
add an object to an object if key does not exist
Definition: json.hpp:5125
iter_impl & operator--()
pre-decrement (–it)
Definition: json.hpp:8614
typename Base::reference reference
the reference type for the pointed-to element
Definition: json.hpp:8930
void push_back(basic_json &&val)
add an object to an array
Definition: json.hpp:4891
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:7666
array (ordered collection of values)
json_reverse_iterator & operator++()
pre-increment (++it)
Definition: json.hpp:8949
friend bool operator==(const_reference lhs, const_reference rhs) noexcept
comparison: equal
Definition: json.hpp:5553
static basic_json parse(std::istream &i, const parser_callback_t cb=nullptr)
deserialize from stream
Definition: json.hpp:6060
ValueType value(const json_pointer &ptr, ValueType default_value) const
access specified object element via JSON Pointer with default value
Definition: json.hpp:3768
const_reference operator[](const typename object_t::key_type &key) const
read-only access specified object element
Definition: json.hpp:3468
reference value() const
return the value of an iterator
Definition: json.hpp:8894
basic_json(const CompatibleNumberUnsignedType val) noexcept
create an unsigned number (implicit)
Definition: json.hpp:1480
constexpr bool is_boolean() const noexcept
return whether value is a boolean
Definition: json.hpp:2339
typename basic_json::value_type value_type
the type of the values when the iterator is dereferenced
Definition: json.hpp:8313
const_reverse_iterator crbegin() const noexcept
returns a const reverse iterator to the last element
Definition: json.hpp:4518
bool operator<(const iter_impl &other) const
comparison: smaller
Definition: json.hpp:8688
string_t value(const json_pointer &ptr, const char *default_value) const
overload for a default value of type const char*
Definition: json.hpp:3793
pointer operator->() const
dereference the iterator
Definition: json.hpp:8524
friend bool operator<(const value_t lhs, const value_t rhs) noexcept
comparison operator for JSON types
Definition: json.hpp:5506
basic_json(const number_float_t val) noexcept
create a floating-point number (explicit)
Definition: json.hpp:1511
friend bool operator!=(const_reference v, std::nullptr_t) noexcept
comparison: not equal
Definition: json.hpp:5699
basic_json(const CompatibleNumberFloatType val) noexcept
create an floating-point number (implicit)
Definition: json.hpp:1558
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:1633
friend bool operator!=(std::nullptr_t, const_reference v) noexcept
comparison: not equal
Definition: json.hpp:5708
difference_type operator-(const json_reverse_iterator &other) const
return difference
Definition: json.hpp:8992
const_reference back() const
access the last element
Definition: json.hpp:3876
iter_impl operator--(int)
post-decrement (it–)
Definition: json.hpp:8603
constexpr bool is_number() const noexcept
return whether value is a number
Definition: json.hpp:2369
const_iterator find(typename object_t::key_type key) const
find an element in a JSON object
Definition: json.hpp:4230
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:8319
const_iterator begin() const noexcept
returns a const iterator to the first element
Definition: json.hpp:4313
basic_json(boolean_t val) noexcept
create a boolean (explicit)
Definition: json.hpp:1322
iterator end() noexcept
returns an iterator to one past the last element
Definition: json.hpp:4374
reverse_iterator rend() noexcept
returns an iterator to the reverse-end
Definition: json.hpp:4481
bool operator>=(const iter_impl &other) const
comparison: greater than or equal
Definition: json.hpp:8739
iterator begin() noexcept
returns an iterator to the first element
Definition: json.hpp:4303
const_iterator cend() const noexcept
returns a const iterator to one past the last element
Definition: json.hpp:4414
basic_json(const CompatibleObjectType &val)
create an object (implicit)
Definition: json.hpp:1147
friend bool operator>(const_reference lhs, const_reference rhs) noexcept
comparison: greater than
Definition: json.hpp:5854
size_type erase(const typename object_t::key_type &key)
remove element from a JSON object given a key
Definition: json.hpp:4127
reference operator[](const typename object_t::key_type &key)
access specified object element
Definition: json.hpp:3417
reference operator+=(basic_json &&val)
add an object to an array
Definition: json.hpp:4917
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:8323
static std::vector< uint8_t > to_msgpack(const basic_json &j)
create a MessagePack serialization of a given JSON value
Definition: json.hpp:7637
a template for a reverse iterator class
Definition: json.hpp:232
object_t::key_type key() const
return the key of an object iterator
Definition: json.hpp:8876
json_reverse_iterator operator++(int)
post-increment (it++)
Definition: json.hpp:8943
friend bool operator==(const_reference v, std::nullptr_t) noexcept
comparison: equal
Definition: json.hpp:5646
iter_impl operator+(difference_type i)
add to iterator
Definition: json.hpp:8788
reference operator[](size_type idx)
access specified array element
Definition: json.hpp:3329
json_reverse_iterator & operator+=(difference_type i)
add to iterator
Definition: json.hpp:8969
reference at(size_type idx)
access specified array element with bounds checking
Definition: json.hpp:3146
static iteration_proxy< iterator > iterator_wrapper(reference cont)
wrapper to access iterator member functions in range-based for
Definition: json.hpp:4568
constexpr bool is_discarded() const noexcept
return whether value is discarded
Definition: json.hpp:2547
reference operator*() const
return a reference to the value pointed to by the iterator
Definition: json.hpp:8483
iter_impl & operator+=(difference_type i)
add to iterator
Definition: json.hpp:8748
const_reverse_iterator crend() const noexcept
returns a const reverse iterator to one before the first
Definition: json.hpp:4547
std::bidirectional_iterator_tag iterator_category
the category of the iterator
Definition: json.hpp:8325
basic_json(const object_t &val)
create an object (explicit)
Definition: json.hpp:1112
basic_json(const number_unsigned_t val) noexcept
create an unsigned integer number (explicit)
Definition: json.hpp:1449
friend std::istream & operator<<(basic_json &j, std::istream &i)
deserialize from stream
Definition: json.hpp:6222
json_reverse_iterator(const base_iterator &it) noexcept
create reverse iterator from base class
Definition: json.hpp:8938
static std::vector< uint8_t > to_cbor(const basic_json &j)
create a MessagePack serialization of a given JSON value
Definition: json.hpp:7693
const_reference operator[](T *(&key)[n]) const
read-only access specified object element
Definition: json.hpp:3545
friend std::ostream & operator<<(std::ostream &o, const basic_json &j)
serialize to stream
Definition: json.hpp:5917
a template for a random access iterator for the basic_json class
Definition: json.hpp:231
iterator insert(const_iterator pos, basic_json &&val)
inserts element
Definition: json.hpp:5199
ReferenceType get_ref()
get a reference value (implicit)
Definition: json.hpp:3053
basic_json(const CompatibleStringType &val)
create a string (implicit)
Definition: json.hpp:1302
basic_json(const basic_json &other)
copy constructor
Definition: json.hpp:1977
reference operator[](T *key)
access specified object element
Definition: json.hpp:3578
parse_event_t
JSON callback events.
Definition: json.hpp:942