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