JSON for Modern C++  2.0.0
json.hpp
1 /*
2  __ _____ _____ _____
3  __| | __| | | | JSON for Modern C++
4 | | |__ | | | | | | version 2.0.1
5 |_____|_____|_____|_|___| https://github.com/nlohmann/json
6 
7 Licensed under the MIT License <http://opensource.org/licenses/MIT>.
8 Copyright (c) 2013-2016 Niels Lohmann <http://nlohmann.me>.
9 
10 Permission is hereby granted, free of charge, to any person obtaining a copy
11 of this software and associated documentation files (the "Software"), to deal
12 in the Software without restriction, including without limitation the rights
13 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
14 copies of the Software, and to permit persons to whom the Software is
15 furnished to do so, subject to the following conditions:
16 
17 The above copyright notice and this permission notice shall be included in all
18 copies or substantial portions of the Software.
19 
20 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
23 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
25 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
26 SOFTWARE.
27 */
28 
29 #ifndef NLOHMANN_JSON_HPP
30 #define NLOHMANN_JSON_HPP
31 
32 #include <algorithm>
33 #include <array>
34 #include <cassert>
35 #include <cerrno>
36 #include <ciso646>
37 #include <cmath>
38 #include <cstddef>
39 #include <cstdio>
40 #include <cstdlib>
41 #include <functional>
42 #include <initializer_list>
43 #include <iomanip>
44 #include <iostream>
45 #include <iterator>
46 #include <limits>
47 #include <map>
48 #include <memory>
49 #include <sstream>
50 #include <stdexcept>
51 #include <string>
52 #include <type_traits>
53 #include <utility>
54 #include <vector>
55 
56 // disable float-equal warnings on GCC/clang
57 #if defined(__clang__) || defined(__GNUC__) || defined(__GNUG__)
58  #pragma GCC diagnostic push
59  #pragma GCC diagnostic ignored "-Wfloat-equal"
60 #endif
61 
67 namespace nlohmann
68 {
69 
70 
75 namespace
76 {
81 template<typename T>
82 struct has_mapped_type
83 {
84  private:
85  template<typename C> static char test(typename C::mapped_type*);
86  template<typename C> static char (&test(...))[2];
87  public:
88  static constexpr bool value = sizeof(test<T>(0)) == 1;
89 };
90 
95 class DecimalSeparator : public std::numpunct<char>
96 {
97  protected:
98  char do_decimal_point() const
99  {
100  return '.';
101  }
102 };
103 
104 }
105 
177 template <
178  template<typename U, typename V, typename... Args> class ObjectType = std::map,
179  template<typename U, typename... Args> class ArrayType = std::vector,
180  class StringType = std::string,
181  class BooleanType = bool,
182  class NumberIntegerType = std::int64_t,
183  class NumberUnsignedType = std::uint64_t,
184  class NumberFloatType = double,
185  template<typename U> class AllocatorType = std::allocator
186  >
188 {
189  private:
191  using basic_json_t = basic_json<ObjectType,
192  ArrayType,
193  StringType,
194  BooleanType,
195  NumberIntegerType,
196  NumberUnsignedType,
197  NumberFloatType,
198  AllocatorType>;
199 
200  public:
201  // forward declarations
202  template<typename Base> class json_reverse_iterator;
203  class json_pointer;
204 
206  // container types //
208 
211 
214 
218  using const_reference = const value_type&;
219 
221  using difference_type = std::ptrdiff_t;
223  using size_type = std::size_t;
224 
226  using allocator_type = AllocatorType<basic_json>;
227 
229  using pointer = typename std::allocator_traits<allocator_type>::pointer;
231  using const_pointer = typename std::allocator_traits<allocator_type>::const_pointer;
232 
234  class iterator;
236  class const_iterator;
241 
243 
244 
249  {
250  return allocator_type();
251  }
252 
253 
255  // JSON value data types //
257 
260 
344  using object_t = ObjectType<StringType,
345  basic_json,
346  std::less<StringType>,
347  AllocatorType<std::pair<const StringType,
348  basic_json>>>;
349 
394  using array_t = ArrayType<basic_json, AllocatorType<basic_json>>;
395 
441  using string_t = StringType;
442 
467  using boolean_t = BooleanType;
468 
539  using number_integer_t = NumberIntegerType;
540 
611  using number_unsigned_t = NumberUnsignedType;
612 
679  using number_float_t = NumberFloatType;
680 
682 
683 
685  // JSON type enumeration //
687 
698  enum class value_t : uint8_t
699  {
700  null,
701  object,
702  array,
703  string,
704  boolean,
705  number_integer,
706  number_unsigned,
707  number_float,
708  discarded
709  };
710 
711 
712  private:
713 
715  template<typename T, typename... Args>
716  static T* create(Args&& ... args)
717  {
718  AllocatorType<T> alloc;
719  auto deleter = [&](T * object)
720  {
721  alloc.deallocate(object, 1);
722  };
723  std::unique_ptr<T, decltype(deleter)> object(alloc.allocate(1), deleter);
724  alloc.construct(object.get(), std::forward<Args>(args)...);
725  return object.release();
726  }
727 
729  // JSON value storage //
731 
739  union json_value
740  {
742  object_t* object;
744  array_t* array;
746  string_t* string;
748  boolean_t boolean;
750  number_integer_t number_integer;
752  number_unsigned_t number_unsigned;
754  number_float_t number_float;
755 
757  json_value() = default;
759  json_value(boolean_t v) noexcept : boolean(v) {}
761  json_value(number_integer_t v) noexcept : number_integer(v) {}
763  json_value(number_unsigned_t v) noexcept : number_unsigned(v) {}
765  json_value(number_float_t v) noexcept : number_float(v) {}
767  json_value(value_t t)
768  {
769  switch (t)
770  {
771  case value_t::object:
772  {
773  object = create<object_t>();
774  break;
775  }
776 
777  case value_t::array:
778  {
779  array = create<array_t>();
780  break;
781  }
782 
783  case value_t::string:
784  {
785  string = create<string_t>("");
786  break;
787  }
788 
789  case value_t::boolean:
790  {
791  boolean = boolean_t(false);
792  break;
793  }
794 
795  case value_t::number_integer:
796  {
797  number_integer = number_integer_t(0);
798  break;
799  }
800 
801  case value_t::number_unsigned:
802  {
803  number_unsigned = number_unsigned_t(0);
804  break;
805  }
806 
807  case value_t::number_float:
808  {
809  number_float = number_float_t(0.0);
810  break;
811  }
812 
813  default:
814  {
815  break;
816  }
817  }
818  }
819 
821  json_value(const string_t& value)
822  {
823  string = create<string_t>(value);
824  }
825 
827  json_value(const object_t& value)
828  {
829  object = create<object_t>(value);
830  }
831 
833  json_value(const array_t& value)
834  {
835  array = create<array_t>(value);
836  }
837  };
838 
839 
840  public:
842  // JSON parser callback //
844 
853  enum class parse_event_t : uint8_t
854  {
856  object_start,
858  object_end,
860  array_start,
862  array_end,
864  key,
866  value
867  };
868 
918  using parser_callback_t = std::function<bool(int depth, parse_event_t event, basic_json& parsed)>;
919 
920 
922  // constructors //
924 
927 
968  : m_type(value_type), m_value(value_type)
969  {}
970 
995  basic_json() = default;
996 
1019  basic_json(std::nullptr_t) noexcept
1020  : basic_json(value_t::null)
1021  {}
1022 
1042  basic_json(const object_t& val)
1043  : m_type(value_t::object), m_value(val)
1044  {}
1045 
1072  template <class CompatibleObjectType, typename
1073  std::enable_if<
1074  std::is_constructible<typename object_t::key_type, typename CompatibleObjectType::key_type>::value and
1075  std::is_constructible<basic_json, typename CompatibleObjectType::mapped_type>::value, int>::type
1076  = 0>
1077  basic_json(const CompatibleObjectType& val)
1078  : m_type(value_t::object)
1079  {
1080  using std::begin;
1081  using std::end;
1082  m_value.object = create<object_t>(begin(val), end(val));
1083  }
1084 
1104  basic_json(const array_t& val)
1105  : m_type(value_t::array), m_value(val)
1106  {}
1107 
1134  template <class CompatibleArrayType, typename
1135  std::enable_if<
1136  not std::is_same<CompatibleArrayType, typename basic_json_t::iterator>::value and
1137  not std::is_same<CompatibleArrayType, typename basic_json_t::const_iterator>::value and
1138  not std::is_same<CompatibleArrayType, typename basic_json_t::reverse_iterator>::value and
1139  not std::is_same<CompatibleArrayType, typename basic_json_t::const_reverse_iterator>::value and
1140  not std::is_same<CompatibleArrayType, typename array_t::iterator>::value and
1141  not std::is_same<CompatibleArrayType, typename array_t::const_iterator>::value and
1142  std::is_constructible<basic_json, typename CompatibleArrayType::value_type>::value, int>::type
1143  = 0>
1144  basic_json(const CompatibleArrayType& val)
1145  : m_type(value_t::array)
1146  {
1147  using std::begin;
1148  using std::end;
1149  m_value.array = create<array_t>(begin(val), end(val));
1150  }
1151 
1173  basic_json(const string_t& val)
1174  : m_type(value_t::string), m_value(val)
1175  {}
1176 
1197  basic_json(const typename string_t::value_type* val)
1198  : basic_json(string_t(val))
1199  {}
1200 
1224  template <class CompatibleStringType, typename
1225  std::enable_if<
1226  std::is_constructible<string_t, CompatibleStringType>::value, int>::type
1227  = 0>
1228  basic_json(const CompatibleStringType& val)
1229  : basic_json(string_t(val))
1230  {}
1231 
1246  basic_json(boolean_t val) noexcept
1247  : m_type(value_t::boolean), m_value(val)
1248  {}
1249 
1273  template<typename T,
1274  typename std::enable_if<
1275  not (std::is_same<T, int>::value)
1276  and std::is_same<T, number_integer_t>::value
1277  , int>::type
1278  = 0>
1279  basic_json(const number_integer_t val) noexcept
1280  : m_type(value_t::number_integer), m_value(val)
1281  {}
1282 
1308  basic_json(const int val) noexcept
1309  : m_type(value_t::number_integer),
1310  m_value(static_cast<number_integer_t>(val))
1311  {}
1312 
1338  template<typename CompatibleNumberIntegerType, typename
1339  std::enable_if<
1340  std::is_constructible<number_integer_t, CompatibleNumberIntegerType>::value and
1341  std::numeric_limits<CompatibleNumberIntegerType>::is_integer and
1342  std::numeric_limits<CompatibleNumberIntegerType>::is_signed,
1343  CompatibleNumberIntegerType>::type
1344  = 0>
1345  basic_json(const CompatibleNumberIntegerType val) noexcept
1346  : m_type(value_t::number_integer),
1347  m_value(static_cast<number_integer_t>(val))
1348  {}
1349 
1367  template<typename T,
1368  typename std::enable_if<
1369  not (std::is_same<T, int>::value)
1370  and std::is_same<T, number_unsigned_t>::value
1371  , int>::type
1372  = 0>
1373  basic_json(const number_unsigned_t val) noexcept
1374  : m_type(value_t::number_unsigned), m_value(val)
1375  {}
1376 
1397  template <typename CompatibleNumberUnsignedType, typename
1398  std::enable_if <
1399  std::is_constructible<number_unsigned_t, CompatibleNumberUnsignedType>::value and
1400  std::numeric_limits<CompatibleNumberUnsignedType>::is_integer and
1401  not std::numeric_limits<CompatibleNumberUnsignedType>::is_signed,
1402  CompatibleNumberUnsignedType>::type
1403  = 0>
1404  basic_json(const CompatibleNumberUnsignedType val) noexcept
1405  : m_type(value_t::number_unsigned),
1406  m_value(static_cast<number_unsigned_t>(val))
1407  {}
1408 
1433  basic_json(const number_float_t val) noexcept
1434  : m_type(value_t::number_float), m_value(val)
1435  {
1436  // replace infinity and NAN by null
1437  if (not std::isfinite(val))
1438  {
1439  m_type = value_t::null;
1440  m_value = json_value();
1441  }
1442  }
1443 
1475  template<typename CompatibleNumberFloatType, typename = typename
1476  std::enable_if<
1477  std::is_constructible<number_float_t, CompatibleNumberFloatType>::value and
1478  std::is_floating_point<CompatibleNumberFloatType>::value>::type
1479  >
1480  basic_json(const CompatibleNumberFloatType val) noexcept
1481  : basic_json(number_float_t(val))
1482  {}
1483 
1553  basic_json(std::initializer_list<basic_json> init,
1554  bool type_deduction = true,
1555  value_t manual_type = value_t::array)
1556  {
1557  // the initializer list could describe an object
1558  bool is_an_object = true;
1559 
1560  // check if each element is an array with two elements whose first
1561  // element is a string
1562  for (const auto& element : init)
1563  {
1564  if (not element.is_array() or element.size() != 2
1565  or not element[0].is_string())
1566  {
1567  // we found an element that makes it impossible to use the
1568  // initializer list as object
1569  is_an_object = false;
1570  break;
1571  }
1572  }
1573 
1574  // adjust type if type deduction is not wanted
1575  if (not type_deduction)
1576  {
1577  // if array is wanted, do not create an object though possible
1578  if (manual_type == value_t::array)
1579  {
1580  is_an_object = false;
1581  }
1582 
1583  // if object is wanted but impossible, throw an exception
1584  if (manual_type == value_t::object and not is_an_object)
1585  {
1586  throw std::domain_error("cannot create object from initializer list");
1587  }
1588  }
1589 
1590  if (is_an_object)
1591  {
1592  // the initializer list is a list of pairs -> create object
1593  m_type = value_t::object;
1594  m_value = value_t::object;
1595 
1596  assert(m_value.object != nullptr);
1597 
1598  for (auto& element : init)
1599  {
1600  m_value.object->emplace(*(element[0].m_value.string), element[1]);
1601  }
1602  }
1603  else
1604  {
1605  // the initializer list describes an array -> create array
1606  m_type = value_t::array;
1607  m_value.array = create<array_t>(init);
1608  }
1609  }
1610 
1645  static basic_json array(std::initializer_list<basic_json> init =
1646  std::initializer_list<basic_json>())
1647  {
1648  return basic_json(init, false, value_t::array);
1649  }
1650 
1685  static basic_json object(std::initializer_list<basic_json> init =
1686  std::initializer_list<basic_json>())
1687  {
1688  return basic_json(init, false, value_t::object);
1689  }
1690 
1709  basic_json(size_type cnt, const basic_json& val)
1710  : m_type(value_t::array)
1711  {
1712  m_value.array = create<array_t>(cnt, val);
1713  }
1714 
1749  template <class InputIT, typename
1750  std::enable_if<
1751  std::is_same<InputIT, typename basic_json_t::iterator>::value or
1752  std::is_same<InputIT, typename basic_json_t::const_iterator>::value
1753  , int>::type
1754  = 0>
1755  basic_json(InputIT first, InputIT last) : m_type(first.m_object->m_type)
1756  {
1757  // make sure iterator fits the current value
1758  if (first.m_object != last.m_object)
1759  {
1760  throw std::domain_error("iterators are not compatible");
1761  }
1762 
1763  // check if iterator range is complete for primitive values
1764  switch (m_type)
1765  {
1766  case value_t::boolean:
1767  case value_t::number_float:
1768  case value_t::number_integer:
1769  case value_t::number_unsigned:
1770  case value_t::string:
1771  {
1772  if (not first.m_it.primitive_iterator.is_begin() or not last.m_it.primitive_iterator.is_end())
1773  {
1774  throw std::out_of_range("iterators out of range");
1775  }
1776  break;
1777  }
1778 
1779  default:
1780  {
1781  break;
1782  }
1783  }
1784 
1785  switch (m_type)
1786  {
1787  case value_t::number_integer:
1788  {
1789  assert(first.m_object != nullptr);
1790  m_value.number_integer = first.m_object->m_value.number_integer;
1791  break;
1792  }
1793 
1794  case value_t::number_unsigned:
1795  {
1796  assert(first.m_object != nullptr);
1797  m_value.number_unsigned = first.m_object->m_value.number_unsigned;
1798  break;
1799  }
1800 
1801  case value_t::number_float:
1802  {
1803  assert(first.m_object != nullptr);
1804  m_value.number_float = first.m_object->m_value.number_float;
1805  break;
1806  }
1807 
1808  case value_t::boolean:
1809  {
1810  assert(first.m_object != nullptr);
1811  m_value.boolean = first.m_object->m_value.boolean;
1812  break;
1813  }
1814 
1815  case value_t::string:
1816  {
1817  assert(first.m_object != nullptr);
1818  m_value = *first.m_object->m_value.string;
1819  break;
1820  }
1821 
1822  case value_t::object:
1823  {
1824  m_value.object = create<object_t>(first.m_it.object_iterator, last.m_it.object_iterator);
1825  break;
1826  }
1827 
1828  case value_t::array:
1829  {
1830  m_value.array = create<array_t>(first.m_it.array_iterator, last.m_it.array_iterator);
1831  break;
1832  }
1833 
1834  default:
1835  {
1836  assert(first.m_object != nullptr);
1837  throw std::domain_error("cannot use construct with iterators from " + first.m_object->type_name());
1838  }
1839  }
1840  }
1841 
1862  explicit basic_json(std::istream& i, parser_callback_t cb = nullptr)
1863  {
1864  *this = parser(i, cb).parse();
1865  }
1866 
1868  // other constructors and destructor //
1870 
1893  basic_json(const basic_json& other)
1894  : m_type(other.m_type)
1895  {
1896  switch (m_type)
1897  {
1898  case value_t::object:
1899  {
1900  assert(other.m_value.object != nullptr);
1901  m_value = *other.m_value.object;
1902  break;
1903  }
1904 
1905  case value_t::array:
1906  {
1907  assert(other.m_value.array != nullptr);
1908  m_value = *other.m_value.array;
1909  break;
1910  }
1911 
1912  case value_t::string:
1913  {
1914  assert(other.m_value.string != nullptr);
1915  m_value = *other.m_value.string;
1916  break;
1917  }
1918 
1919  case value_t::boolean:
1920  {
1921  m_value = other.m_value.boolean;
1922  break;
1923  }
1924 
1925  case value_t::number_integer:
1926  {
1927  m_value = other.m_value.number_integer;
1928  break;
1929  }
1930 
1931  case value_t::number_unsigned:
1932  {
1933  m_value = other.m_value.number_unsigned;
1934  break;
1935  }
1936 
1937  case value_t::number_float:
1938  {
1939  m_value = other.m_value.number_float;
1940  break;
1941  }
1942 
1943  default:
1944  {
1945  break;
1946  }
1947  }
1948  }
1949 
1968  basic_json(basic_json&& other) noexcept
1969  : m_type(std::move(other.m_type)),
1970  m_value(std::move(other.m_value))
1971  {
1972  // invalidate payload
1973  other.m_type = value_t::null;
1974  other.m_value = {};
1975  }
1976 
2000  reference& operator=(basic_json other) noexcept (
2001  std::is_nothrow_move_constructible<value_t>::value and
2002  std::is_nothrow_move_assignable<value_t>::value and
2003  std::is_nothrow_move_constructible<json_value>::value and
2004  std::is_nothrow_move_assignable<json_value>::value
2005  )
2006  {
2007  using std::swap;
2008  swap(m_type, other.m_type);
2009  swap(m_value, other.m_value);
2010  return *this;
2011  }
2012 
2029  {
2030  switch (m_type)
2031  {
2032  case value_t::object:
2033  {
2034  AllocatorType<object_t> alloc;
2035  alloc.destroy(m_value.object);
2036  alloc.deallocate(m_value.object, 1);
2037  break;
2038  }
2039 
2040  case value_t::array:
2041  {
2042  AllocatorType<array_t> alloc;
2043  alloc.destroy(m_value.array);
2044  alloc.deallocate(m_value.array, 1);
2045  break;
2046  }
2047 
2048  case value_t::string:
2049  {
2050  AllocatorType<string_t> alloc;
2051  alloc.destroy(m_value.string);
2052  alloc.deallocate(m_value.string, 1);
2053  break;
2054  }
2055 
2056  default:
2057  {
2058  // all other types need no specific destructor
2059  break;
2060  }
2061  }
2062  }
2063 
2065 
2066  public:
2068  // object inspection //
2070 
2073 
2097  string_t dump(const int indent = -1) const
2098  {
2099  std::stringstream ss;
2100  // fix locale problems
2101  ss.imbue(std::locale(std::locale(), new DecimalSeparator));
2102 
2103  if (indent >= 0)
2104  {
2105  dump(ss, true, static_cast<unsigned int>(indent));
2106  }
2107  else
2108  {
2109  dump(ss, false, 0);
2110  }
2111 
2112  return ss.str();
2113  }
2114 
2133  constexpr value_t type() const noexcept
2134  {
2135  return m_type;
2136  }
2137 
2163  constexpr bool is_primitive() const noexcept
2164  {
2165  return is_null() or is_string() or is_boolean() or is_number();
2166  }
2167 
2190  constexpr bool is_structured() const noexcept
2191  {
2192  return is_array() or is_object();
2193  }
2194 
2212  constexpr bool is_null() const noexcept
2213  {
2214  return m_type == value_t::null;
2215  }
2216 
2234  constexpr bool is_boolean() const noexcept
2235  {
2236  return m_type == value_t::boolean;
2237  }
2238 
2264  constexpr bool is_number() const noexcept
2265  {
2266  return is_number_integer() or is_number_float();
2267  }
2268 
2293  constexpr bool is_number_integer() const noexcept
2294  {
2295  return m_type == value_t::number_integer or m_type == value_t::number_unsigned;
2296  }
2297 
2321  constexpr bool is_number_unsigned() const noexcept
2322  {
2323  return m_type == value_t::number_unsigned;
2324  }
2325 
2349  constexpr bool is_number_float() const noexcept
2350  {
2351  return m_type == value_t::number_float;
2352  }
2353 
2371  constexpr bool is_object() const noexcept
2372  {
2373  return m_type == value_t::object;
2374  }
2375 
2393  constexpr bool is_array() const noexcept
2394  {
2395  return m_type == value_t::array;
2396  }
2397 
2415  constexpr bool is_string() const noexcept
2416  {
2417  return m_type == value_t::string;
2418  }
2419 
2442  constexpr bool is_discarded() const noexcept
2443  {
2444  return m_type == value_t::discarded;
2445  }
2446 
2465  constexpr operator value_t() const noexcept
2466  {
2467  return m_type;
2468  }
2469 
2471 
2472  private:
2474  // value access //
2476 
2478  template <class T, typename
2479  std::enable_if<
2480  std::is_convertible<typename object_t::key_type, typename T::key_type>::value and
2481  std::is_convertible<basic_json_t, typename T::mapped_type>::value
2482  , int>::type = 0>
2483  T get_impl(T*) const
2484  {
2485  if (is_object())
2486  {
2487  assert(m_value.object != nullptr);
2488  return T(m_value.object->begin(), m_value.object->end());
2489  }
2490  else
2491  {
2492  throw std::domain_error("type must be object, but is " + type_name());
2493  }
2494  }
2495 
2497  object_t get_impl(object_t*) const
2498  {
2499  if (is_object())
2500  {
2501  assert(m_value.object != nullptr);
2502  return *(m_value.object);
2503  }
2504  else
2505  {
2506  throw std::domain_error("type must be object, but is " + type_name());
2507  }
2508  }
2509 
2511  template <class T, typename
2512  std::enable_if<
2513  std::is_convertible<basic_json_t, typename T::value_type>::value and
2514  not std::is_same<basic_json_t, typename T::value_type>::value and
2515  not std::is_arithmetic<T>::value and
2516  not std::is_convertible<std::string, T>::value and
2517  not has_mapped_type<T>::value
2518  , int>::type = 0>
2519  T get_impl(T*) const
2520  {
2521  if (is_array())
2522  {
2523  T to_vector;
2524  assert(m_value.array != nullptr);
2525  std::transform(m_value.array->begin(), m_value.array->end(),
2526  std::inserter(to_vector, to_vector.end()), [](basic_json i)
2527  {
2528  return i.get<typename T::value_type>();
2529  });
2530  return to_vector;
2531  }
2532  else
2533  {
2534  throw std::domain_error("type must be array, but is " + type_name());
2535  }
2536  }
2537 
2539  template <class T, typename
2540  std::enable_if<
2541  std::is_convertible<basic_json_t, T>::value and
2542  not std::is_same<basic_json_t, T>::value
2543  , int>::type = 0>
2544  std::vector<T> get_impl(std::vector<T>*) const
2545  {
2546  if (is_array())
2547  {
2548  std::vector<T> to_vector;
2549  assert(m_value.array != nullptr);
2550  to_vector.reserve(m_value.array->size());
2551  std::transform(m_value.array->begin(), m_value.array->end(),
2552  std::inserter(to_vector, to_vector.end()), [](basic_json i)
2553  {
2554  return i.get<T>();
2555  });
2556  return to_vector;
2557  }
2558  else
2559  {
2560  throw std::domain_error("type must be array, but is " + type_name());
2561  }
2562  }
2563 
2565  template <class T, typename
2566  std::enable_if<
2567  std::is_same<basic_json, typename T::value_type>::value and
2568  not has_mapped_type<T>::value
2569  , int>::type = 0>
2570  T get_impl(T*) const
2571  {
2572  if (is_array())
2573  {
2574  assert(m_value.array != nullptr);
2575  return T(m_value.array->begin(), m_value.array->end());
2576  }
2577  else
2578  {
2579  throw std::domain_error("type must be array, but is " + type_name());
2580  }
2581  }
2582 
2584  array_t get_impl(array_t*) const
2585  {
2586  if (is_array())
2587  {
2588  assert(m_value.array != nullptr);
2589  return *(m_value.array);
2590  }
2591  else
2592  {
2593  throw std::domain_error("type must be array, but is " + type_name());
2594  }
2595  }
2596 
2598  template <typename T, typename
2599  std::enable_if<
2600  std::is_convertible<string_t, T>::value
2601  , int>::type = 0>
2602  T get_impl(T*) const
2603  {
2604  if (is_string())
2605  {
2606  assert(m_value.string != nullptr);
2607  return *m_value.string;
2608  }
2609  else
2610  {
2611  throw std::domain_error("type must be string, but is " + type_name());
2612  }
2613  }
2614 
2616  template<typename T, typename
2617  std::enable_if<
2618  std::is_arithmetic<T>::value
2619  , int>::type = 0>
2620  T get_impl(T*) const
2621  {
2622  switch (m_type)
2623  {
2624  case value_t::number_integer:
2625  {
2626  return static_cast<T>(m_value.number_integer);
2627  }
2628 
2629  case value_t::number_unsigned:
2630  {
2631  return static_cast<T>(m_value.number_unsigned);
2632  }
2633 
2634  case value_t::number_float:
2635  {
2636  return static_cast<T>(m_value.number_float);
2637  }
2638 
2639  default:
2640  {
2641  throw std::domain_error("type must be number, but is " + type_name());
2642  }
2643  }
2644  }
2645 
2647  constexpr boolean_t get_impl(boolean_t*) const
2648  {
2649  return is_boolean()
2650  ? m_value.boolean
2651  : throw std::domain_error("type must be boolean, but is " + type_name());
2652  }
2653 
2655  object_t* get_impl_ptr(object_t*) noexcept
2656  {
2657  return is_object() ? m_value.object : nullptr;
2658  }
2659 
2661  constexpr const object_t* get_impl_ptr(const object_t*) const noexcept
2662  {
2663  return is_object() ? m_value.object : nullptr;
2664  }
2665 
2667  array_t* get_impl_ptr(array_t*) noexcept
2668  {
2669  return is_array() ? m_value.array : nullptr;
2670  }
2671 
2673  constexpr const array_t* get_impl_ptr(const array_t*) const noexcept
2674  {
2675  return is_array() ? m_value.array : nullptr;
2676  }
2677 
2679  string_t* get_impl_ptr(string_t*) noexcept
2680  {
2681  return is_string() ? m_value.string : nullptr;
2682  }
2683 
2685  constexpr const string_t* get_impl_ptr(const string_t*) const noexcept
2686  {
2687  return is_string() ? m_value.string : nullptr;
2688  }
2689 
2691  boolean_t* get_impl_ptr(boolean_t*) noexcept
2692  {
2693  return is_boolean() ? &m_value.boolean : nullptr;
2694  }
2695 
2697  constexpr const boolean_t* get_impl_ptr(const boolean_t*) const noexcept
2698  {
2699  return is_boolean() ? &m_value.boolean : nullptr;
2700  }
2701 
2703  number_integer_t* get_impl_ptr(number_integer_t*) noexcept
2704  {
2705  return is_number_integer() ? &m_value.number_integer : nullptr;
2706  }
2707 
2709  constexpr const number_integer_t* get_impl_ptr(const number_integer_t*) const noexcept
2710  {
2711  return is_number_integer() ? &m_value.number_integer : nullptr;
2712  }
2713 
2715  number_unsigned_t* get_impl_ptr(number_unsigned_t*) noexcept
2716  {
2717  return is_number_unsigned() ? &m_value.number_unsigned : nullptr;
2718  }
2719 
2721  constexpr const number_unsigned_t* get_impl_ptr(const number_unsigned_t*) const noexcept
2722  {
2723  return is_number_unsigned() ? &m_value.number_unsigned : nullptr;
2724  }
2725 
2727  number_float_t* get_impl_ptr(number_float_t*) noexcept
2728  {
2729  return is_number_float() ? &m_value.number_float : nullptr;
2730  }
2731 
2733  constexpr const number_float_t* get_impl_ptr(const number_float_t*) const noexcept
2734  {
2735  return is_number_float() ? &m_value.number_float : nullptr;
2736  }
2737 
2749  template<typename ReferenceType, typename ThisType>
2750  static ReferenceType get_ref_impl(ThisType& obj)
2751  {
2752  // delegate the call to get_ptr<>()
2753  using PointerType = typename std::add_pointer<ReferenceType>::type;
2754  auto ptr = obj.template get_ptr<PointerType>();
2755 
2756  if (ptr != nullptr)
2757  {
2758  return *ptr;
2759  }
2760  else
2761  {
2762  throw std::domain_error("incompatible ReferenceType for get_ref, actual type is " +
2763  obj.type_name());
2764  }
2765  }
2766 
2767  public:
2768 
2771 
2805  template<typename ValueType, typename
2806  std::enable_if<
2807  not std::is_pointer<ValueType>::value
2808  , int>::type = 0>
2809  ValueType get() const
2810  {
2811  return get_impl(static_cast<ValueType*>(nullptr));
2812  }
2813 
2840  template<typename PointerType, typename
2841  std::enable_if<
2842  std::is_pointer<PointerType>::value
2843  , int>::type = 0>
2844  PointerType get() noexcept
2845  {
2846  // delegate the call to get_ptr
2847  return get_ptr<PointerType>();
2848  }
2849 
2854  template<typename PointerType, typename
2855  std::enable_if<
2856  std::is_pointer<PointerType>::value
2857  , int>::type = 0>
2858  constexpr const PointerType get() const noexcept
2859  {
2860  // delegate the call to get_ptr
2861  return get_ptr<PointerType>();
2862  }
2863 
2889  template<typename PointerType, typename
2890  std::enable_if<
2891  std::is_pointer<PointerType>::value
2892  , int>::type = 0>
2893  PointerType get_ptr() noexcept
2894  {
2895  // delegate the call to get_impl_ptr<>()
2896  return get_impl_ptr(static_cast<PointerType>(nullptr));
2897  }
2898 
2903  template<typename PointerType, typename
2904  std::enable_if<
2905  std::is_pointer<PointerType>::value
2906  and std::is_const<typename std::remove_pointer<PointerType>::type>::value
2907  , int>::type = 0>
2908  constexpr const PointerType get_ptr() const noexcept
2909  {
2910  // delegate the call to get_impl_ptr<>() const
2911  return get_impl_ptr(static_cast<const PointerType>(nullptr));
2912  }
2913 
2940  template<typename ReferenceType, typename
2941  std::enable_if<
2942  std::is_reference<ReferenceType>::value
2943  , int>::type = 0>
2944  ReferenceType get_ref()
2945  {
2946  // delegate call to get_ref_impl
2947  return get_ref_impl<ReferenceType>(*this);
2948  }
2949 
2954  template<typename ReferenceType, typename
2955  std::enable_if<
2956  std::is_reference<ReferenceType>::value
2957  and std::is_const<typename std::remove_reference<ReferenceType>::type>::value
2958  , int>::type = 0>
2959  ReferenceType get_ref() const
2960  {
2961  // delegate call to get_ref_impl
2962  return get_ref_impl<ReferenceType>(*this);
2963  }
2964 
2993  template < typename ValueType, typename
2994  std::enable_if <
2995  not std::is_pointer<ValueType>::value
2996  and not std::is_same<ValueType, typename string_t::value_type>::value
2997 #ifndef _MSC_VER // Fix for issue #167 operator<< abiguity under VS2015
2998  and not std::is_same<ValueType, std::initializer_list<typename string_t::value_type>>::value
2999 #endif
3000  , int >::type = 0 >
3001  operator ValueType() const
3002  {
3003  // delegate the call to get<>() const
3004  return get<ValueType>();
3005  }
3006 
3008 
3009 
3011  // element access //
3013 
3016 
3040  {
3041  // at only works for arrays
3042  if (is_array())
3043  {
3044  try
3045  {
3046  assert(m_value.array != nullptr);
3047  return m_value.array->at(idx);
3048  }
3049  catch (std::out_of_range&)
3050  {
3051  // create better exception explanation
3052  throw std::out_of_range("array index " + std::to_string(idx) + " is out of range");
3053  }
3054  }
3055  else
3056  {
3057  throw std::domain_error("cannot use at() with " + type_name());
3058  }
3059  }
3060 
3084  {
3085  // at only works for arrays
3086  if (is_array())
3087  {
3088  try
3089  {
3090  assert(m_value.array != nullptr);
3091  return m_value.array->at(idx);
3092  }
3093  catch (std::out_of_range&)
3094  {
3095  // create better exception explanation
3096  throw std::out_of_range("array index " + std::to_string(idx) + " is out of range");
3097  }
3098  }
3099  else
3100  {
3101  throw std::domain_error("cannot use at() with " + type_name());
3102  }
3103  }
3104 
3131  reference at(const typename object_t::key_type& key)
3132  {
3133  // at only works for objects
3134  if (is_object())
3135  {
3136  try
3137  {
3138  assert(m_value.object != nullptr);
3139  return m_value.object->at(key);
3140  }
3141  catch (std::out_of_range&)
3142  {
3143  // create better exception explanation
3144  throw std::out_of_range("key '" + key + "' not found");
3145  }
3146  }
3147  else
3148  {
3149  throw std::domain_error("cannot use at() with " + type_name());
3150  }
3151  }
3152 
3179  const_reference at(const typename object_t::key_type& key) const
3180  {
3181  // at only works for objects
3182  if (is_object())
3183  {
3184  try
3185  {
3186  assert(m_value.object != nullptr);
3187  return m_value.object->at(key);
3188  }
3189  catch (std::out_of_range&)
3190  {
3191  // create better exception explanation
3192  throw std::out_of_range("key '" + key + "' not found");
3193  }
3194  }
3195  else
3196  {
3197  throw std::domain_error("cannot use at() with " + type_name());
3198  }
3199  }
3200 
3227  {
3228  // implicitly convert null value to an empty array
3229  if (is_null())
3230  {
3231  m_type = value_t::array;
3232  m_value.array = create<array_t>();
3233  }
3234 
3235  // operator[] only works for arrays
3236  if (is_array())
3237  {
3238  // fill up array with null values until given idx is reached
3239  assert(m_value.array != nullptr);
3240  for (size_t i = m_value.array->size(); i <= idx; ++i)
3241  {
3242  m_value.array->push_back(basic_json());
3243  }
3244 
3245  return m_value.array->operator[](idx);
3246  }
3247  else
3248  {
3249  throw std::domain_error("cannot use operator[] with " + type_name());
3250  }
3251  }
3252 
3273  {
3274  // const operator[] only works for arrays
3275  if (is_array())
3276  {
3277  assert(m_value.array != nullptr);
3278  return m_value.array->operator[](idx);
3279  }
3280  else
3281  {
3282  throw std::domain_error("cannot use operator[] with " + type_name());
3283  }
3284  }
3285 
3313  reference operator[](const typename object_t::key_type& key)
3314  {
3315  // implicitly convert null value to an empty object
3316  if (is_null())
3317  {
3318  m_type = value_t::object;
3319  m_value.object = create<object_t>();
3320  }
3321 
3322  // operator[] only works for objects
3323  if (is_object())
3324  {
3325  assert(m_value.object != nullptr);
3326  return m_value.object->operator[](key);
3327  }
3328  else
3329  {
3330  throw std::domain_error("cannot use operator[] with " + type_name());
3331  }
3332  }
3333 
3361  const_reference operator[](const typename object_t::key_type& key) const
3362  {
3363  // const operator[] only works for objects
3364  if (is_object())
3365  {
3366  assert(m_value.object != nullptr);
3367  assert(m_value.object->find(key) != m_value.object->end());
3368  return m_value.object->find(key)->second;
3369  }
3370  else
3371  {
3372  throw std::domain_error("cannot use operator[] with " + type_name());
3373  }
3374  }
3375 
3403  template<typename T, std::size_t n>
3404  reference operator[](T * (&key)[n])
3405  {
3406  return operator[](static_cast<const T>(key));
3407  }
3408 
3438  template<typename T, std::size_t n>
3439  const_reference operator[](T * (&key)[n]) const
3440  {
3441  return operator[](static_cast<const T>(key));
3442  }
3443 
3471  template<typename T>
3473  {
3474  // implicitly convert null to object
3475  if (is_null())
3476  {
3477  m_type = value_t::object;
3478  m_value = value_t::object;
3479  }
3480 
3481  // at only works for objects
3482  if (is_object())
3483  {
3484  assert(m_value.object != nullptr);
3485  return m_value.object->operator[](key);
3486  }
3487  else
3488  {
3489  throw std::domain_error("cannot use operator[] with " + type_name());
3490  }
3491  }
3492 
3520  template<typename T>
3522  {
3523  // at only works for objects
3524  if (is_object())
3525  {
3526  assert(m_value.object != nullptr);
3527  assert(m_value.object->find(key) != m_value.object->end());
3528  return m_value.object->find(key)->second;
3529  }
3530  else
3531  {
3532  throw std::domain_error("cannot use operator[] with " + type_name());
3533  }
3534  }
3535 
3584  template <class ValueType, typename
3585  std::enable_if<
3586  std::is_convertible<basic_json_t, ValueType>::value
3587  , int>::type = 0>
3588  ValueType value(const typename object_t::key_type& key, ValueType default_value) const
3589  {
3590  // at only works for objects
3591  if (is_object())
3592  {
3593  // if key is found, return value and given default value otherwise
3594  const auto it = find(key);
3595  if (it != end())
3596  {
3597  return *it;
3598  }
3599  else
3600  {
3601  return default_value;
3602  }
3603  }
3604  else
3605  {
3606  throw std::domain_error("cannot use value() with " + type_name());
3607  }
3608  }
3609 
3614  string_t value(const typename object_t::key_type& key, const char* default_value) const
3615  {
3616  return value(key, string_t(default_value));
3617  }
3618 
3644  {
3645  return *begin();
3646  }
3647 
3652  {
3653  return *cbegin();
3654  }
3655 
3686  {
3687  auto tmp = end();
3688  --tmp;
3689  return *tmp;
3690  }
3691 
3696  {
3697  auto tmp = cend();
3698  --tmp;
3699  return *tmp;
3700  }
3701 
3747  template <class InteratorType, typename
3748  std::enable_if<
3749  std::is_same<InteratorType, typename basic_json_t::iterator>::value or
3750  std::is_same<InteratorType, typename basic_json_t::const_iterator>::value
3751  , int>::type
3752  = 0>
3753  InteratorType erase(InteratorType pos)
3754  {
3755  // make sure iterator fits the current value
3756  if (this != pos.m_object)
3757  {
3758  throw std::domain_error("iterator does not fit current value");
3759  }
3760 
3761  InteratorType result = end();
3762 
3763  switch (m_type)
3764  {
3765  case value_t::boolean:
3766  case value_t::number_float:
3767  case value_t::number_integer:
3768  case value_t::number_unsigned:
3769  case value_t::string:
3770  {
3771  if (not pos.m_it.primitive_iterator.is_begin())
3772  {
3773  throw std::out_of_range("iterator out of range");
3774  }
3775 
3776  if (is_string())
3777  {
3778  delete m_value.string;
3779  m_value.string = nullptr;
3780  }
3781 
3782  m_type = value_t::null;
3783  break;
3784  }
3785 
3786  case value_t::object:
3787  {
3788  assert(m_value.object != nullptr);
3789  result.m_it.object_iterator = m_value.object->erase(pos.m_it.object_iterator);
3790  break;
3791  }
3792 
3793  case value_t::array:
3794  {
3795  assert(m_value.array != nullptr);
3796  result.m_it.array_iterator = m_value.array->erase(pos.m_it.array_iterator);
3797  break;
3798  }
3799 
3800  default:
3801  {
3802  throw std::domain_error("cannot use erase() with " + type_name());
3803  }
3804  }
3805 
3806  return result;
3807  }
3808 
3855  template <class InteratorType, typename
3856  std::enable_if<
3857  std::is_same<InteratorType, typename basic_json_t::iterator>::value or
3858  std::is_same<InteratorType, typename basic_json_t::const_iterator>::value
3859  , int>::type
3860  = 0>
3861  InteratorType erase(InteratorType first, InteratorType last)
3862  {
3863  // make sure iterator fits the current value
3864  if (this != first.m_object or this != last.m_object)
3865  {
3866  throw std::domain_error("iterators do not fit current value");
3867  }
3868 
3869  InteratorType result = end();
3870 
3871  switch (m_type)
3872  {
3873  case value_t::boolean:
3874  case value_t::number_float:
3875  case value_t::number_integer:
3876  case value_t::number_unsigned:
3877  case value_t::string:
3878  {
3879  if (not first.m_it.primitive_iterator.is_begin() or not last.m_it.primitive_iterator.is_end())
3880  {
3881  throw std::out_of_range("iterators out of range");
3882  }
3883 
3884  if (is_string())
3885  {
3886  delete m_value.string;
3887  m_value.string = nullptr;
3888  }
3889 
3890  m_type = value_t::null;
3891  break;
3892  }
3893 
3894  case value_t::object:
3895  {
3896  assert(m_value.object != nullptr);
3897  result.m_it.object_iterator = m_value.object->erase(first.m_it.object_iterator,
3898  last.m_it.object_iterator);
3899  break;
3900  }
3901 
3902  case value_t::array:
3903  {
3904  assert(m_value.array != nullptr);
3905  result.m_it.array_iterator = m_value.array->erase(first.m_it.array_iterator,
3906  last.m_it.array_iterator);
3907  break;
3908  }
3909 
3910  default:
3911  {
3912  throw std::domain_error("cannot use erase() with " + type_name());
3913  }
3914  }
3915 
3916  return result;
3917  }
3918 
3948  size_type erase(const typename object_t::key_type& key)
3949  {
3950  // this erase only works for objects
3951  if (is_object())
3952  {
3953  assert(m_value.object != nullptr);
3954  return m_value.object->erase(key);
3955  }
3956  else
3957  {
3958  throw std::domain_error("cannot use erase() with " + type_name());
3959  }
3960  }
3961 
3986  void erase(const size_type idx)
3987  {
3988  // this erase only works for arrays
3989  if (is_array())
3990  {
3991  if (idx >= size())
3992  {
3993  throw std::out_of_range("array index " + std::to_string(idx) + " is out of range");
3994  }
3995 
3996  assert(m_value.array != nullptr);
3997  m_value.array->erase(m_value.array->begin() + static_cast<difference_type>(idx));
3998  }
3999  else
4000  {
4001  throw std::domain_error("cannot use erase() with " + type_name());
4002  }
4003  }
4004 
4006 
4007 
4009  // lookup //
4011 
4014 
4033  iterator find(typename object_t::key_type key)
4034  {
4035  auto result = end();
4036 
4037  if (is_object())
4038  {
4039  assert(m_value.object != nullptr);
4040  result.m_it.object_iterator = m_value.object->find(key);
4041  }
4042 
4043  return result;
4044  }
4045 
4050  const_iterator find(typename object_t::key_type key) const
4051  {
4052  auto result = cend();
4053 
4054  if (is_object())
4055  {
4056  assert(m_value.object != nullptr);
4057  result.m_it.object_iterator = m_value.object->find(key);
4058  }
4059 
4060  return result;
4061  }
4062 
4081  size_type count(typename object_t::key_type key) const
4082  {
4083  // return 0 for all nonobject types
4084  assert(not is_object() or m_value.object != nullptr);
4085  return is_object() ? m_value.object->count(key) : 0;
4086  }
4087 
4089 
4090 
4092  // iterators //
4094 
4097 
4122  iterator begin() noexcept
4123  {
4124  iterator result(this);
4125  result.set_begin();
4126  return result;
4127  }
4128 
4132  const_iterator begin() const noexcept
4133  {
4134  return cbegin();
4135  }
4136 
4162  const_iterator cbegin() const noexcept
4163  {
4164  const_iterator result(this);
4165  result.set_begin();
4166  return result;
4167  }
4168 
4193  iterator end() noexcept
4194  {
4195  iterator result(this);
4196  result.set_end();
4197  return result;
4198  }
4199 
4203  const_iterator end() const noexcept
4204  {
4205  return cend();
4206  }
4207 
4233  const_iterator cend() const noexcept
4234  {
4235  const_iterator result(this);
4236  result.set_end();
4237  return result;
4238  }
4239 
4264  {
4265  return reverse_iterator(end());
4266  }
4267 
4272  {
4273  return crbegin();
4274  }
4275 
4301  {
4302  return reverse_iterator(begin());
4303  }
4304 
4308  const_reverse_iterator rend() const noexcept
4309  {
4310  return crend();
4311  }
4312 
4338  {
4339  return const_reverse_iterator(cend());
4340  }
4341 
4367  {
4368  return const_reverse_iterator(cbegin());
4369  }
4370 
4371  private:
4372  // forward declaration
4373  template<typename IteratorType> class iteration_proxy;
4374 
4375  public:
4387  static iteration_proxy<iterator> iterator_wrapper(reference cont)
4388  {
4389  return iteration_proxy<iterator>(cont);
4390  }
4391 
4395  static iteration_proxy<const_iterator> iterator_wrapper(const_reference cont)
4396  {
4397  return iteration_proxy<const_iterator>(cont);
4398  }
4399 
4401 
4402 
4404  // capacity //
4406 
4409 
4443  bool empty() const noexcept
4444  {
4445  switch (m_type)
4446  {
4447  case value_t::null:
4448  {
4449  // null values are empty
4450  return true;
4451  }
4452 
4453  case value_t::array:
4454  {
4455  assert(m_value.array != nullptr);
4456  return m_value.array->empty();
4457  }
4458 
4459  case value_t::object:
4460  {
4461  assert(m_value.object != nullptr);
4462  return m_value.object->empty();
4463  }
4464 
4465  default:
4466  {
4467  // all other types are nonempty
4468  return false;
4469  }
4470  }
4471  }
4472 
4507  size_type size() const noexcept
4508  {
4509  switch (m_type)
4510  {
4511  case value_t::null:
4512  {
4513  // null values are empty
4514  return 0;
4515  }
4516 
4517  case value_t::array:
4518  {
4519  assert(m_value.array != nullptr);
4520  return m_value.array->size();
4521  }
4522 
4523  case value_t::object:
4524  {
4525  assert(m_value.object != nullptr);
4526  return m_value.object->size();
4527  }
4528 
4529  default:
4530  {
4531  // all other types have size 1
4532  return 1;
4533  }
4534  }
4535  }
4536 
4573  size_type max_size() const noexcept
4574  {
4575  switch (m_type)
4576  {
4577  case value_t::array:
4578  {
4579  assert(m_value.array != nullptr);
4580  return m_value.array->max_size();
4581  }
4582 
4583  case value_t::object:
4584  {
4585  assert(m_value.object != nullptr);
4586  return m_value.object->max_size();
4587  }
4588 
4589  default:
4590  {
4591  // all other types have max_size() == size()
4592  return size();
4593  }
4594  }
4595  }
4596 
4598 
4599 
4601  // modifiers //
4603 
4606 
4632  void clear() noexcept
4633  {
4634  switch (m_type)
4635  {
4636  case value_t::number_integer:
4637  {
4638  m_value.number_integer = 0;
4639  break;
4640  }
4641 
4642  case value_t::number_unsigned:
4643  {
4644  m_value.number_unsigned = 0;
4645  break;
4646  }
4647 
4648  case value_t::number_float:
4649  {
4650  m_value.number_float = 0.0;
4651  break;
4652  }
4653 
4654  case value_t::boolean:
4655  {
4656  m_value.boolean = false;
4657  break;
4658  }
4659 
4660  case value_t::string:
4661  {
4662  assert(m_value.string != nullptr);
4663  m_value.string->clear();
4664  break;
4665  }
4666 
4667  case value_t::array:
4668  {
4669  assert(m_value.array != nullptr);
4670  m_value.array->clear();
4671  break;
4672  }
4673 
4674  case value_t::object:
4675  {
4676  assert(m_value.object != nullptr);
4677  m_value.object->clear();
4678  break;
4679  }
4680 
4681  default:
4682  {
4683  break;
4684  }
4685  }
4686  }
4687 
4708  void push_back(basic_json&& val)
4709  {
4710  // push_back only works for null objects or arrays
4711  if (not(is_null() or is_array()))
4712  {
4713  throw std::domain_error("cannot use push_back() with " + type_name());
4714  }
4715 
4716  // transform null object into an array
4717  if (is_null())
4718  {
4719  m_type = value_t::array;
4720  m_value = value_t::array;
4721  }
4722 
4723  // add element to array (move semantics)
4724  assert(m_value.array != nullptr);
4725  m_value.array->push_back(std::move(val));
4726  // invalidate object
4727  val.m_type = value_t::null;
4728  }
4729 
4734  reference operator+=(basic_json&& val)
4735  {
4736  push_back(std::move(val));
4737  return *this;
4738  }
4739 
4744  void push_back(const basic_json& val)
4745  {
4746  // push_back only works for null objects or arrays
4747  if (not(is_null() or is_array()))
4748  {
4749  throw std::domain_error("cannot use push_back() with " + type_name());
4750  }
4751 
4752  // transform null object into an array
4753  if (is_null())
4754  {
4755  m_type = value_t::array;
4756  m_value = value_t::array;
4757  }
4758 
4759  // add element to array
4760  assert(m_value.array != nullptr);
4761  m_value.array->push_back(val);
4762  }
4763 
4768  reference operator+=(const basic_json& val)
4769  {
4770  push_back(val);
4771  return *this;
4772  }
4773 
4794  void push_back(const typename object_t::value_type& val)
4795  {
4796  // push_back only works for null objects or objects
4797  if (not(is_null() or is_object()))
4798  {
4799  throw std::domain_error("cannot use push_back() with " + type_name());
4800  }
4801 
4802  // transform null object into an object
4803  if (is_null())
4804  {
4805  m_type = value_t::object;
4806  m_value = value_t::object;
4807  }
4808 
4809  // add element to array
4810  assert(m_value.object != nullptr);
4811  m_value.object->insert(val);
4812  }
4813 
4818  reference operator+=(const typename object_t::value_type& val)
4819  {
4820  push_back(val);
4821  return *this;
4822  }
4823 
4849  void push_back(std::initializer_list<basic_json> init)
4850  {
4851  if (is_object() and init.size() == 2 and init.begin()->is_string())
4852  {
4853  const string_t key = *init.begin();
4854  push_back(typename object_t::value_type(key, *(init.begin() + 1)));
4855  }
4856  else
4857  {
4858  push_back(basic_json(init));
4859  }
4860  }
4861 
4866  reference operator+=(std::initializer_list<basic_json> init)
4867  {
4868  push_back(init);
4869  return *this;
4870  }
4871 
4894  iterator insert(const_iterator pos, const basic_json& val)
4895  {
4896  // insert only works for arrays
4897  if (is_array())
4898  {
4899  // check if iterator pos fits to this JSON value
4900  if (pos.m_object != this)
4901  {
4902  throw std::domain_error("iterator does not fit current value");
4903  }
4904 
4905  // insert to array and return iterator
4906  iterator result(this);
4907  assert(m_value.array != nullptr);
4908  result.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator, val);
4909  return result;
4910  }
4911  else
4912  {
4913  throw std::domain_error("cannot use insert() with " + type_name());
4914  }
4915  }
4916 
4921  iterator insert(const_iterator pos, basic_json&& val)
4922  {
4923  return insert(pos, val);
4924  }
4925 
4950  iterator insert(const_iterator pos, size_type cnt, const basic_json& val)
4951  {
4952  // insert only works for arrays
4953  if (is_array())
4954  {
4955  // check if iterator pos fits to this JSON value
4956  if (pos.m_object != this)
4957  {
4958  throw std::domain_error("iterator does not fit current value");
4959  }
4960 
4961  // insert to array and return iterator
4962  iterator result(this);
4963  assert(m_value.array != nullptr);
4964  result.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator, cnt, val);
4965  return result;
4966  }
4967  else
4968  {
4969  throw std::domain_error("cannot use insert() with " + type_name());
4970  }
4971  }
4972 
5004  {
5005  // insert only works for arrays
5006  if (not is_array())
5007  {
5008  throw std::domain_error("cannot use insert() with " + type_name());
5009  }
5010 
5011  // check if iterator pos fits to this JSON value
5012  if (pos.m_object != this)
5013  {
5014  throw std::domain_error("iterator does not fit current value");
5015  }
5016 
5017  // check if range iterators belong to the same JSON object
5018  if (first.m_object != last.m_object)
5019  {
5020  throw std::domain_error("iterators do not fit");
5021  }
5022 
5023  if (first.m_object == this or last.m_object == this)
5024  {
5025  throw std::domain_error("passed iterators may not belong to container");
5026  }
5027 
5028  // insert to array and return iterator
5029  iterator result(this);
5030  assert(m_value.array != nullptr);
5031  result.m_it.array_iterator = m_value.array->insert(
5032  pos.m_it.array_iterator,
5033  first.m_it.array_iterator,
5034  last.m_it.array_iterator);
5035  return result;
5036  }
5037 
5062  iterator insert(const_iterator pos, std::initializer_list<basic_json> ilist)
5063  {
5064  // insert only works for arrays
5065  if (not is_array())
5066  {
5067  throw std::domain_error("cannot use insert() with " + type_name());
5068  }
5069 
5070  // check if iterator pos fits to this JSON value
5071  if (pos.m_object != this)
5072  {
5073  throw std::domain_error("iterator does not fit current value");
5074  }
5075 
5076  // insert to array and return iterator
5077  iterator result(this);
5078  assert(m_value.array != nullptr);
5079  result.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator, ilist);
5080  return result;
5081  }
5082 
5100  void swap(reference other) noexcept (
5101  std::is_nothrow_move_constructible<value_t>::value and
5102  std::is_nothrow_move_assignable<value_t>::value and
5103  std::is_nothrow_move_constructible<json_value>::value and
5104  std::is_nothrow_move_assignable<json_value>::value
5105  )
5106  {
5107  std::swap(m_type, other.m_type);
5108  std::swap(m_value, other.m_value);
5109  }
5110 
5131  void swap(array_t& other)
5132  {
5133  // swap only works for arrays
5134  if (is_array())
5135  {
5136  assert(m_value.array != nullptr);
5137  std::swap(*(m_value.array), other);
5138  }
5139  else
5140  {
5141  throw std::domain_error("cannot use swap() with " + type_name());
5142  }
5143  }
5144 
5165  void swap(object_t& other)
5166  {
5167  // swap only works for objects
5168  if (is_object())
5169  {
5170  assert(m_value.object != nullptr);
5171  std::swap(*(m_value.object), other);
5172  }
5173  else
5174  {
5175  throw std::domain_error("cannot use swap() with " + type_name());
5176  }
5177  }
5178 
5199  void swap(string_t& other)
5200  {
5201  // swap only works for strings
5202  if (is_string())
5203  {
5204  assert(m_value.string != nullptr);
5205  std::swap(*(m_value.string), other);
5206  }
5207  else
5208  {
5209  throw std::domain_error("cannot use swap() with " + type_name());
5210  }
5211  }
5212 
5214 
5215 
5217  // lexicographical comparison operators //
5219 
5222 
5223  private:
5233  friend bool operator<(const value_t lhs, const value_t rhs) noexcept
5234  {
5235  static constexpr std::array<uint8_t, 8> order = {{
5236  0, // null
5237  3, // object
5238  4, // array
5239  5, // string
5240  1, // boolean
5241  2, // integer
5242  2, // unsigned
5243  2, // float
5244  }
5245  };
5246 
5247  // discarded values are not comparable
5248  if (lhs == value_t::discarded or rhs == value_t::discarded)
5249  {
5250  return false;
5251  }
5252 
5253  return order[static_cast<std::size_t>(lhs)] < order[static_cast<std::size_t>(rhs)];
5254  }
5255 
5256  public:
5280  friend bool operator==(const_reference lhs, const_reference rhs) noexcept
5281  {
5282  const auto lhs_type = lhs.type();
5283  const auto rhs_type = rhs.type();
5284 
5285  if (lhs_type == rhs_type)
5286  {
5287  switch (lhs_type)
5288  {
5289  case value_t::array:
5290  {
5291  assert(lhs.m_value.array != nullptr);
5292  assert(rhs.m_value.array != nullptr);
5293  return *lhs.m_value.array == *rhs.m_value.array;
5294  }
5295  case value_t::object:
5296  {
5297  assert(lhs.m_value.object != nullptr);
5298  assert(rhs.m_value.object != nullptr);
5299  return *lhs.m_value.object == *rhs.m_value.object;
5300  }
5301  case value_t::null:
5302  {
5303  return true;
5304  }
5305  case value_t::string:
5306  {
5307  assert(lhs.m_value.string != nullptr);
5308  assert(rhs.m_value.string != nullptr);
5309  return *lhs.m_value.string == *rhs.m_value.string;
5310  }
5311  case value_t::boolean:
5312  {
5313  return lhs.m_value.boolean == rhs.m_value.boolean;
5314  }
5315  case value_t::number_integer:
5316  {
5317  return lhs.m_value.number_integer == rhs.m_value.number_integer;
5318  }
5319  case value_t::number_unsigned:
5320  {
5321  return lhs.m_value.number_unsigned == rhs.m_value.number_unsigned;
5322  }
5323  case value_t::number_float:
5324  {
5325  return lhs.m_value.number_float == rhs.m_value.number_float;
5326  }
5327  default:
5328  {
5329  return false;
5330  }
5331  }
5332  }
5333  else if (lhs_type == value_t::number_integer and rhs_type == value_t::number_float)
5334  {
5335  return static_cast<number_float_t>(lhs.m_value.number_integer) == rhs.m_value.number_float;
5336  }
5337  else if (lhs_type == value_t::number_float and rhs_type == value_t::number_integer)
5338  {
5339  return lhs.m_value.number_float == static_cast<number_float_t>(rhs.m_value.number_integer);
5340  }
5341  else if (lhs_type == value_t::number_unsigned and rhs_type == value_t::number_float)
5342  {
5343  return static_cast<number_float_t>(lhs.m_value.number_unsigned) == rhs.m_value.number_float;
5344  }
5345  else if (lhs_type == value_t::number_float and rhs_type == value_t::number_unsigned)
5346  {
5347  return lhs.m_value.number_float == static_cast<number_float_t>(rhs.m_value.number_unsigned);
5348  }
5349  else if (lhs_type == value_t::number_unsigned and rhs_type == value_t::number_integer)
5350  {
5351  return static_cast<number_integer_t>(lhs.m_value.number_unsigned) == rhs.m_value.number_integer;
5352  }
5353  else if (lhs_type == value_t::number_integer and rhs_type == value_t::number_unsigned)
5354  {
5355  return lhs.m_value.number_integer == static_cast<number_integer_t>(rhs.m_value.number_unsigned);
5356  }
5357 
5358  return false;
5359  }
5360 
5379  friend bool operator==(const_reference v, std::nullptr_t) noexcept
5380  {
5381  return v.is_null();
5382  }
5383 
5388  friend bool operator==(std::nullptr_t, const_reference v) noexcept
5389  {
5390  return v.is_null();
5391  }
5392 
5409  friend bool operator!=(const_reference lhs, const_reference rhs) noexcept
5410  {
5411  return not (lhs == rhs);
5412  }
5413 
5432  friend bool operator!=(const_reference v, std::nullptr_t) noexcept
5433  {
5434  return not v.is_null();
5435  }
5436 
5441  friend bool operator!=(std::nullptr_t, const_reference v) noexcept
5442  {
5443  return not v.is_null();
5444  }
5445 
5470  friend bool operator<(const_reference lhs, const_reference rhs) noexcept
5471  {
5472  const auto lhs_type = lhs.type();
5473  const auto rhs_type = rhs.type();
5474 
5475  if (lhs_type == rhs_type)
5476  {
5477  switch (lhs_type)
5478  {
5479  case value_t::array:
5480  {
5481  assert(lhs.m_value.array != nullptr);
5482  assert(rhs.m_value.array != nullptr);
5483  return *lhs.m_value.array < *rhs.m_value.array;
5484  }
5485  case value_t::object:
5486  {
5487  assert(lhs.m_value.object != nullptr);
5488  assert(rhs.m_value.object != nullptr);
5489  return *lhs.m_value.object < *rhs.m_value.object;
5490  }
5491  case value_t::null:
5492  {
5493  return false;
5494  }
5495  case value_t::string:
5496  {
5497  assert(lhs.m_value.string != nullptr);
5498  assert(rhs.m_value.string != nullptr);
5499  return *lhs.m_value.string < *rhs.m_value.string;
5500  }
5501  case value_t::boolean:
5502  {
5503  return lhs.m_value.boolean < rhs.m_value.boolean;
5504  }
5505  case value_t::number_integer:
5506  {
5507  return lhs.m_value.number_integer < rhs.m_value.number_integer;
5508  }
5509  case value_t::number_unsigned:
5510  {
5511  return lhs.m_value.number_unsigned < rhs.m_value.number_unsigned;
5512  }
5513  case value_t::number_float:
5514  {
5515  return lhs.m_value.number_float < rhs.m_value.number_float;
5516  }
5517  default:
5518  {
5519  return false;
5520  }
5521  }
5522  }
5523  else if (lhs_type == value_t::number_integer and rhs_type == value_t::number_float)
5524  {
5525  return static_cast<number_float_t>(lhs.m_value.number_integer) < rhs.m_value.number_float;
5526  }
5527  else if (lhs_type == value_t::number_float and rhs_type == value_t::number_integer)
5528  {
5529  return lhs.m_value.number_float < static_cast<number_float_t>(rhs.m_value.number_integer);
5530  }
5531  else if (lhs_type == value_t::number_unsigned and rhs_type == value_t::number_float)
5532  {
5533  return static_cast<number_float_t>(lhs.m_value.number_unsigned) < rhs.m_value.number_float;
5534  }
5535  else if (lhs_type == value_t::number_float and rhs_type == value_t::number_unsigned)
5536  {
5537  return lhs.m_value.number_float < static_cast<number_float_t>(rhs.m_value.number_unsigned);
5538  }
5539  else if (lhs_type == value_t::number_integer and rhs_type == value_t::number_unsigned)
5540  {
5541  return lhs.m_value.number_integer < static_cast<number_integer_t>(rhs.m_value.number_unsigned);
5542  }
5543  else if (lhs_type == value_t::number_unsigned and rhs_type == value_t::number_integer)
5544  {
5545  return static_cast<number_integer_t>(lhs.m_value.number_unsigned) < rhs.m_value.number_integer;
5546  }
5547 
5548  // We only reach this line if we cannot compare values. In that case,
5549  // we compare types. Note we have to call the operator explicitly,
5550  // because MSVC has problems otherwise.
5551  return operator<(lhs_type, rhs_type);
5552  }
5553 
5571  friend bool operator<=(const_reference lhs, const_reference rhs) noexcept
5572  {
5573  return not (rhs < lhs);
5574  }
5575 
5593  friend bool operator>(const_reference lhs, const_reference rhs) noexcept
5594  {
5595  return not (lhs <= rhs);
5596  }
5597 
5615  friend bool operator>=(const_reference lhs, const_reference rhs) noexcept
5616  {
5617  return not (lhs < rhs);
5618  }
5619 
5621 
5622 
5624  // serialization //
5626 
5629 
5652  friend std::ostream& operator<<(std::ostream& o, const basic_json& j)
5653  {
5654  // read width member and use it as indentation parameter if nonzero
5655  const bool pretty_print = (o.width() > 0);
5656  const auto indentation = (pretty_print ? o.width() : 0);
5657 
5658  // reset width to 0 for subsequent calls to this stream
5659  o.width(0);
5660  // fix locale problems
5661  auto old_locale = o.imbue(std::locale(std::locale(), new DecimalSeparator));
5662 
5663  // do the actual serialization
5664  j.dump(o, pretty_print, static_cast<unsigned int>(indentation));
5665 
5666  // reset locale
5667  o.imbue(old_locale);
5668  return o;
5669  }
5670 
5675  friend std::ostream& operator>>(const basic_json& j, std::ostream& o)
5676  {
5677  return o << j;
5678  }
5679 
5681 
5682 
5684  // deserialization //
5686 
5689 
5714  static basic_json parse(const string_t& s, parser_callback_t cb = nullptr)
5715  {
5716  return parser(s, cb).parse();
5717  }
5718 
5743  static basic_json parse(std::istream& i, parser_callback_t cb = nullptr)
5744  {
5745  return parser(i, cb).parse();
5746  }
5747 
5751  static basic_json parse(std::istream&& i, parser_callback_t cb = nullptr)
5752  {
5753  return parser(i, cb).parse();
5754  }
5755 
5779  friend std::istream& operator<<(basic_json& j, std::istream& i)
5780  {
5781  j = parser(i).parse();
5782  return i;
5783  }
5784 
5789  friend std::istream& operator>>(std::istream& i, basic_json& j)
5790  {
5791  j = parser(i).parse();
5792  return i;
5793  }
5794 
5796 
5797 
5798  private:
5800  // convenience functions //
5802 
5804  string_t type_name() const noexcept
5805  {
5806  switch (m_type)
5807  {
5808  case value_t::null:
5809  return "null";
5810  case value_t::object:
5811  return "object";
5812  case value_t::array:
5813  return "array";
5814  case value_t::string:
5815  return "string";
5816  case value_t::boolean:
5817  return "boolean";
5818  case value_t::discarded:
5819  return "discarded";
5820  default:
5821  return "number";
5822  }
5823  }
5824 
5833  static std::size_t extra_space(const string_t& s) noexcept
5834  {
5835  std::size_t result = 0;
5836 
5837  for (const auto& c : s)
5838  {
5839  switch (c)
5840  {
5841  case '"':
5842  case '\\':
5843  case '\b':
5844  case '\f':
5845  case '\n':
5846  case '\r':
5847  case '\t':
5848  {
5849  // from c (1 byte) to \x (2 bytes)
5850  result += 1;
5851  break;
5852  }
5853 
5854  default:
5855  {
5856  if (c >= 0x00 and c <= 0x1f)
5857  {
5858  // from c (1 byte) to \uxxxx (6 bytes)
5859  result += 5;
5860  }
5861  break;
5862  }
5863  }
5864  }
5865 
5866  return result;
5867  }
5868 
5882  static string_t escape_string(const string_t& s)
5883  {
5884  const auto space = extra_space(s);
5885  if (space == 0)
5886  {
5887  return s;
5888  }
5889 
5890  // create a result string of necessary size
5891  string_t result(s.size() + space, '\\');
5892  std::size_t pos = 0;
5893 
5894  for (const auto& c : s)
5895  {
5896  switch (c)
5897  {
5898  // quotation mark (0x22)
5899  case '"':
5900  {
5901  result[pos + 1] = '"';
5902  pos += 2;
5903  break;
5904  }
5905 
5906  // reverse solidus (0x5c)
5907  case '\\':
5908  {
5909  // nothing to change
5910  pos += 2;
5911  break;
5912  }
5913 
5914  // backspace (0x08)
5915  case '\b':
5916  {
5917  result[pos + 1] = 'b';
5918  pos += 2;
5919  break;
5920  }
5921 
5922  // formfeed (0x0c)
5923  case '\f':
5924  {
5925  result[pos + 1] = 'f';
5926  pos += 2;
5927  break;
5928  }
5929 
5930  // newline (0x0a)
5931  case '\n':
5932  {
5933  result[pos + 1] = 'n';
5934  pos += 2;
5935  break;
5936  }
5937 
5938  // carriage return (0x0d)
5939  case '\r':
5940  {
5941  result[pos + 1] = 'r';
5942  pos += 2;
5943  break;
5944  }
5945 
5946  // horizontal tab (0x09)
5947  case '\t':
5948  {
5949  result[pos + 1] = 't';
5950  pos += 2;
5951  break;
5952  }
5953 
5954  default:
5955  {
5956  if (c >= 0x00 and c <= 0x1f)
5957  {
5958  // convert a number 0..15 to its hex representation
5959  // (0..f)
5960  const auto hexify = [](const int v) -> char
5961  {
5962  return (v < 10)
5963  ? ('0' + static_cast<char>(v))
5964  : ('a' + static_cast<char>((v - 10) & 0x1f));
5965  };
5966 
5967  // print character c as \uxxxx
5968  for (const char m :
5969  { 'u', '0', '0', hexify(c >> 4), hexify(c & 0x0f)
5970  })
5971  {
5972  result[++pos] = m;
5973  }
5974 
5975  ++pos;
5976  }
5977  else
5978  {
5979  // all other characters are added as-is
5980  result[pos++] = c;
5981  }
5982  break;
5983  }
5984  }
5985  }
5986 
5987  return result;
5988  }
5989 
6007  void dump(std::ostream& o,
6008  const bool pretty_print,
6009  const unsigned int indent_step,
6010  const unsigned int current_indent = 0) const
6011  {
6012  // variable to hold indentation for recursive calls
6013  unsigned int new_indent = current_indent;
6014 
6015  switch (m_type)
6016  {
6017  case value_t::object:
6018  {
6019  assert(m_value.object != nullptr);
6020 
6021  if (m_value.object->empty())
6022  {
6023  o << "{}";
6024  return;
6025  }
6026 
6027  o << "{";
6028 
6029  // increase indentation
6030  if (pretty_print)
6031  {
6032  new_indent += indent_step;
6033  o << "\n";
6034  }
6035 
6036  for (auto i = m_value.object->cbegin(); i != m_value.object->cend(); ++i)
6037  {
6038  if (i != m_value.object->cbegin())
6039  {
6040  o << (pretty_print ? ",\n" : ",");
6041  }
6042  o << string_t(new_indent, ' ') << "\""
6043  << escape_string(i->first) << "\":"
6044  << (pretty_print ? " " : "");
6045  i->second.dump(o, pretty_print, indent_step, new_indent);
6046  }
6047 
6048  // decrease indentation
6049  if (pretty_print)
6050  {
6051  new_indent -= indent_step;
6052  o << "\n";
6053  }
6054 
6055  o << string_t(new_indent, ' ') + "}";
6056  return;
6057  }
6058 
6059  case value_t::array:
6060  {
6061  assert(m_value.array != nullptr);
6062 
6063  if (m_value.array->empty())
6064  {
6065  o << "[]";
6066  return;
6067  }
6068 
6069  o << "[";
6070 
6071  // increase indentation
6072  if (pretty_print)
6073  {
6074  new_indent += indent_step;
6075  o << "\n";
6076  }
6077 
6078  for (auto i = m_value.array->cbegin(); i != m_value.array->cend(); ++i)
6079  {
6080  if (i != m_value.array->cbegin())
6081  {
6082  o << (pretty_print ? ",\n" : ",");
6083  }
6084  o << string_t(new_indent, ' ');
6085  i->dump(o, pretty_print, indent_step, new_indent);
6086  }
6087 
6088  // decrease indentation
6089  if (pretty_print)
6090  {
6091  new_indent -= indent_step;
6092  o << "\n";
6093  }
6094 
6095  o << string_t(new_indent, ' ') << "]";
6096  return;
6097  }
6098 
6099  case value_t::string:
6100  {
6101  assert(m_value.string != nullptr);
6102  o << string_t("\"") << escape_string(*m_value.string) << "\"";
6103  return;
6104  }
6105 
6106  case value_t::boolean:
6107  {
6108  o << (m_value.boolean ? "true" : "false");
6109  return;
6110  }
6111 
6112  case value_t::number_integer:
6113  {
6114  o << m_value.number_integer;
6115  return;
6116  }
6117 
6118  case value_t::number_unsigned:
6119  {
6120  o << m_value.number_unsigned;
6121  return;
6122  }
6123 
6124  case value_t::number_float:
6125  {
6126  if (m_value.number_float == 0)
6127  {
6128  // special case for zero to get "0.0"/"-0.0"
6129  o << (std::signbit(m_value.number_float) ? "-0.0" : "0.0");
6130  }
6131  else
6132  {
6133  // Otherwise 6, 15 or 16 digits of precision allows
6134  // round-trip IEEE 754 string->float->string,
6135  // string->double->string or string->long
6136  // double->string; to be safe, we read this value from
6137  // std::numeric_limits<number_float_t>::digits10
6138  o << std::setprecision(std::numeric_limits<double>::digits10)
6139  << m_value.number_float;
6140  }
6141  return;
6142  }
6143 
6144  case value_t::discarded:
6145  {
6146  o << "<discarded>";
6147  return;
6148  }
6149 
6150  case value_t::null:
6151  {
6152  o << "null";
6153  return;
6154  }
6155  }
6156  }
6157 
6158  private:
6160  // member variables //
6162 
6164  value_t m_type = value_t::null;
6165 
6167  json_value m_value = {};
6168 
6169 
6170  private:
6172  // iterators //
6174 
6184  class primitive_iterator_t
6185  {
6186  public:
6188  void set_begin() noexcept
6189  {
6190  m_it = begin_value;
6191  }
6192 
6194  void set_end() noexcept
6195  {
6196  m_it = end_value;
6197  }
6198 
6200  constexpr bool is_begin() const noexcept
6201  {
6202  return (m_it == begin_value);
6203  }
6204 
6206  constexpr bool is_end() const noexcept
6207  {
6208  return (m_it == end_value);
6209  }
6210 
6212  operator difference_type& () noexcept
6213  {
6214  return m_it;
6215  }
6216 
6218  constexpr operator difference_type () const noexcept
6219  {
6220  return m_it;
6221  }
6222 
6223  private:
6224  static constexpr difference_type begin_value = 0;
6225  static constexpr difference_type end_value = begin_value + 1;
6226 
6228  difference_type m_it = std::numeric_limits<std::ptrdiff_t>::denorm_min();
6229  };
6230 
6238  struct internal_iterator
6239  {
6241  typename object_t::iterator object_iterator;
6243  typename array_t::iterator array_iterator;
6245  primitive_iterator_t primitive_iterator;
6246 
6248  internal_iterator() noexcept
6249  : object_iterator(), array_iterator(), primitive_iterator()
6250  {}
6251  };
6252 
6254  template<typename IteratorType>
6255  class iteration_proxy
6256  {
6257  private:
6259  class iteration_proxy_internal
6260  {
6261  private:
6263  IteratorType anchor;
6265  size_t array_index = 0;
6266 
6267  public:
6268  explicit iteration_proxy_internal(IteratorType it) noexcept
6269  : anchor(it)
6270  {}
6271 
6273  iteration_proxy_internal& operator*()
6274  {
6275  return *this;
6276  }
6277 
6279  iteration_proxy_internal& operator++()
6280  {
6281  ++anchor;
6282  ++array_index;
6283 
6284  return *this;
6285  }
6286 
6288  bool operator!= (const iteration_proxy_internal& o) const
6289  {
6290  return anchor != o.anchor;
6291  }
6292 
6294  typename basic_json::string_t key() const
6295  {
6296  assert(anchor.m_object != nullptr);
6297 
6298  switch (anchor.m_object->type())
6299  {
6300  // use integer array index as key
6301  case value_t::array:
6302  {
6303  return std::to_string(array_index);
6304  }
6305 
6306  // use key from the object
6307  case value_t::object:
6308  {
6309  return anchor.key();
6310  }
6311 
6312  // use an empty key for all primitive types
6313  default:
6314  {
6315  return "";
6316  }
6317  }
6318  }
6319 
6321  typename IteratorType::reference value() const
6322  {
6323  return anchor.value();
6324  }
6325  };
6326 
6328  typename IteratorType::reference container;
6329 
6330  public:
6332  explicit iteration_proxy(typename IteratorType::reference cont)
6333  : container(cont)
6334  {}
6335 
6337  iteration_proxy_internal begin() noexcept
6338  {
6339  return iteration_proxy_internal(container.begin());
6340  }
6341 
6343  iteration_proxy_internal end() noexcept
6344  {
6345  return iteration_proxy_internal(container.end());
6346  }
6347  };
6348 
6349  public:
6363  class const_iterator : public std::iterator<std::random_access_iterator_tag, const basic_json>
6364  {
6366  friend class basic_json;
6367 
6368  public:
6378  using iterator_category = std::bidirectional_iterator_tag;
6379 
6381  const_iterator() = default;
6382 
6384  explicit const_iterator(pointer object) noexcept
6385  : m_object(object)
6386  {
6387  assert(m_object != nullptr);
6388 
6389  switch (m_object->m_type)
6390  {
6392  {
6393  m_it.object_iterator = typename object_t::iterator();
6394  break;
6395  }
6396 
6398  {
6399  m_it.array_iterator = typename array_t::iterator();
6400  break;
6401  }
6402 
6403  default:
6404  {
6405  m_it.primitive_iterator = primitive_iterator_t();
6406  break;
6407  }
6408  }
6409  }
6410 
6412  explicit const_iterator(const iterator& other) noexcept
6413  : m_object(other.m_object)
6414  {
6415  assert(m_object != nullptr);
6416 
6417  switch (m_object->m_type)
6418  {
6420  {
6421  m_it.object_iterator = other.m_it.object_iterator;
6422  break;
6423  }
6424 
6426  {
6427  m_it.array_iterator = other.m_it.array_iterator;
6428  break;
6429  }
6430 
6431  default:
6432  {
6433  m_it.primitive_iterator = other.m_it.primitive_iterator;
6434  break;
6435  }
6436  }
6437  }
6438 
6440  const_iterator(const const_iterator& other) noexcept
6441  : m_object(other.m_object), m_it(other.m_it)
6442  {}
6443 
6446  std::is_nothrow_move_constructible<pointer>::value and
6447  std::is_nothrow_move_assignable<pointer>::value and
6448  std::is_nothrow_move_constructible<internal_iterator>::value and
6449  std::is_nothrow_move_assignable<internal_iterator>::value
6450  )
6451  {
6452  std::swap(m_object, other.m_object);
6453  std::swap(m_it, other.m_it);
6454  return *this;
6455  }
6456 
6457  private:
6459  void set_begin() noexcept
6460  {
6461  assert(m_object != nullptr);
6462 
6463  switch (m_object->m_type)
6464  {
6466  {
6467  assert(m_object->m_value.object != nullptr);
6468  m_it.object_iterator = m_object->m_value.object->begin();
6469  break;
6470  }
6471 
6473  {
6474  assert(m_object->m_value.array != nullptr);
6475  m_it.array_iterator = m_object->m_value.array->begin();
6476  break;
6477  }
6478 
6480  {
6481  // set to end so begin()==end() is true: null is empty
6482  m_it.primitive_iterator.set_end();
6483  break;
6484  }
6485 
6486  default:
6487  {
6488  m_it.primitive_iterator.set_begin();
6489  break;
6490  }
6491  }
6492  }
6493 
6495  void set_end() noexcept
6496  {
6497  assert(m_object != nullptr);
6498 
6499  switch (m_object->m_type)
6500  {
6502  {
6503  assert(m_object->m_value.object != nullptr);
6504  m_it.object_iterator = m_object->m_value.object->end();
6505  break;
6506  }
6507 
6509  {
6510  assert(m_object->m_value.array != nullptr);
6511  m_it.array_iterator = m_object->m_value.array->end();
6512  break;
6513  }
6514 
6515  default:
6516  {
6517  m_it.primitive_iterator.set_end();
6518  break;
6519  }
6520  }
6521  }
6522 
6523  public:
6526  {
6527  assert(m_object != nullptr);
6528 
6529  switch (m_object->m_type)
6530  {
6532  {
6533  assert(m_object->m_value.object);
6534  assert(m_it.object_iterator != m_object->m_value.object->end());
6535  return m_it.object_iterator->second;
6536  }
6537 
6539  {
6540  assert(m_object->m_value.array);
6541  assert(m_it.array_iterator != m_object->m_value.array->end());
6542  return *m_it.array_iterator;
6543  }
6544 
6546  {
6547  throw std::out_of_range("cannot get value");
6548  }
6549 
6550  default:
6551  {
6552  if (m_it.primitive_iterator.is_begin())
6553  {
6554  return *m_object;
6555  }
6556  else
6557  {
6558  throw std::out_of_range("cannot get value");
6559  }
6560  }
6561  }
6562  }
6563 
6566  {
6567  assert(m_object != nullptr);
6568 
6569  switch (m_object->m_type)
6570  {
6572  {
6573  assert(m_object->m_value.object);
6574  assert(m_it.object_iterator != m_object->m_value.object->end());
6575  return &(m_it.object_iterator->second);
6576  }
6577 
6579  {
6580  assert(m_object->m_value.array);
6581  assert(m_it.array_iterator != m_object->m_value.array->end());
6582  return &*m_it.array_iterator;
6583  }
6584 
6585  default:
6586  {
6587  if (m_it.primitive_iterator.is_begin())
6588  {
6589  return m_object;
6590  }
6591  else
6592  {
6593  throw std::out_of_range("cannot get value");
6594  }
6595  }
6596  }
6597  }
6598 
6601  {
6602  auto result = *this;
6603  ++(*this);
6604  return result;
6605  }
6606 
6609  {
6610  assert(m_object != nullptr);
6611 
6612  switch (m_object->m_type)
6613  {
6615  {
6616  ++m_it.object_iterator;
6617  break;
6618  }
6619 
6621  {
6622  ++m_it.array_iterator;
6623  break;
6624  }
6625 
6626  default:
6627  {
6628  ++m_it.primitive_iterator;
6629  break;
6630  }
6631  }
6632 
6633  return *this;
6634  }
6635 
6638  {
6639  auto result = *this;
6640  --(*this);
6641  return result;
6642  }
6643 
6646  {
6647  assert(m_object != nullptr);
6648 
6649  switch (m_object->m_type)
6650  {
6652  {
6653  --m_it.object_iterator;
6654  break;
6655  }
6656 
6658  {
6659  --m_it.array_iterator;
6660  break;
6661  }
6662 
6663  default:
6664  {
6665  --m_it.primitive_iterator;
6666  break;
6667  }
6668  }
6669 
6670  return *this;
6671  }
6672 
6674  bool operator==(const const_iterator& other) const
6675  {
6676  // if objects are not the same, the comparison is undefined
6677  if (m_object != other.m_object)
6678  {
6679  throw std::domain_error("cannot compare iterators of different containers");
6680  }
6681 
6682  assert(m_object != nullptr);
6683 
6684  switch (m_object->m_type)
6685  {
6687  {
6688  return (m_it.object_iterator == other.m_it.object_iterator);
6689  }
6690 
6692  {
6693  return (m_it.array_iterator == other.m_it.array_iterator);
6694  }
6695 
6696  default:
6697  {
6698  return (m_it.primitive_iterator == other.m_it.primitive_iterator);
6699  }
6700  }
6701  }
6702 
6704  bool operator!=(const const_iterator& other) const
6705  {
6706  return not operator==(other);
6707  }
6708 
6710  bool operator<(const const_iterator& other) const
6711  {
6712  // if objects are not the same, the comparison is undefined
6713  if (m_object != other.m_object)
6714  {
6715  throw std::domain_error("cannot compare iterators of different containers");
6716  }
6717 
6718  assert(m_object != nullptr);
6719 
6720  switch (m_object->m_type)
6721  {
6723  {
6724  throw std::domain_error("cannot compare order of object iterators");
6725  }
6726 
6728  {
6729  return (m_it.array_iterator < other.m_it.array_iterator);
6730  }
6731 
6732  default:
6733  {
6734  return (m_it.primitive_iterator < other.m_it.primitive_iterator);
6735  }
6736  }
6737  }
6738 
6740  bool operator<=(const const_iterator& other) const
6741  {
6742  return not other.operator < (*this);
6743  }
6744 
6746  bool operator>(const const_iterator& other) const
6747  {
6748  return not operator<=(other);
6749  }
6750 
6752  bool operator>=(const const_iterator& other) const
6753  {
6754  return not operator<(other);
6755  }
6756 
6759  {
6760  assert(m_object != nullptr);
6761 
6762  switch (m_object->m_type)
6763  {
6765  {
6766  throw std::domain_error("cannot use offsets with object iterators");
6767  }
6768 
6770  {
6771  m_it.array_iterator += i;
6772  break;
6773  }
6774 
6775  default:
6776  {
6777  m_it.primitive_iterator += i;
6778  break;
6779  }
6780  }
6781 
6782  return *this;
6783  }
6784 
6787  {
6788  return operator+=(-i);
6789  }
6790 
6793  {
6794  auto result = *this;
6795  result += i;
6796  return result;
6797  }
6798 
6801  {
6802  auto result = *this;
6803  result -= i;
6804  return result;
6805  }
6806 
6809  {
6810  assert(m_object != nullptr);
6811 
6812  switch (m_object->m_type)
6813  {
6815  {
6816  throw std::domain_error("cannot use offsets with object iterators");
6817  }
6818 
6820  {
6821  return m_it.array_iterator - other.m_it.array_iterator;
6822  }
6823 
6824  default:
6825  {
6826  return m_it.primitive_iterator - other.m_it.primitive_iterator;
6827  }
6828  }
6829  }
6830 
6833  {
6834  assert(m_object != nullptr);
6835 
6836  switch (m_object->m_type)
6837  {
6839  {
6840  throw std::domain_error("cannot use operator[] for object iterators");
6841  }
6842 
6844  {
6845  return *(m_it.array_iterator + n);
6846  }
6847 
6849  {
6850  throw std::out_of_range("cannot get value");
6851  }
6852 
6853  default:
6854  {
6855  if (m_it.primitive_iterator == -n)
6856  {
6857  return *m_object;
6858  }
6859  else
6860  {
6861  throw std::out_of_range("cannot get value");
6862  }
6863  }
6864  }
6865  }
6866 
6868  typename object_t::key_type key() const
6869  {
6870  assert(m_object != nullptr);
6871 
6872  if (m_object->is_object())
6873  {
6874  return m_it.object_iterator->first;
6875  }
6876  else
6877  {
6878  throw std::domain_error("cannot use key() for non-object iterators");
6879  }
6880  }
6881 
6884  {
6885  return operator*();
6886  }
6887 
6888  private:
6890  pointer m_object = nullptr;
6892  internal_iterator m_it = internal_iterator();
6893  };
6894 
6907  class iterator : public const_iterator
6908  {
6909  public:
6911  using pointer = typename basic_json::pointer;
6913 
6915  iterator() = default;
6916 
6918  explicit iterator(pointer object) noexcept
6919  : base_iterator(object)
6920  {}
6921 
6923  iterator(const iterator& other) noexcept
6924  : base_iterator(other)
6925  {}
6926 
6928  iterator& operator=(iterator other) noexcept(
6929  std::is_nothrow_move_constructible<pointer>::value and
6930  std::is_nothrow_move_assignable<pointer>::value and
6931  std::is_nothrow_move_constructible<internal_iterator>::value and
6932  std::is_nothrow_move_assignable<internal_iterator>::value
6933  )
6934  {
6935  base_iterator::operator=(other);
6936  return *this;
6937  }
6938 
6941  {
6942  return const_cast<reference>(base_iterator::operator*());
6943  }
6944 
6947  {
6948  return const_cast<pointer>(base_iterator::operator->());
6949  }
6950 
6953  {
6954  iterator result = *this;
6955  base_iterator::operator++();
6956  return result;
6957  }
6958 
6961  {
6962  base_iterator::operator++();
6963  return *this;
6964  }
6965 
6968  {
6969  iterator result = *this;
6970  base_iterator::operator--();
6971  return result;
6972  }
6973 
6976  {
6977  base_iterator::operator--();
6978  return *this;
6979  }
6980 
6983  {
6984  base_iterator::operator+=(i);
6985  return *this;
6986  }
6987 
6990  {
6991  base_iterator::operator-=(i);
6992  return *this;
6993  }
6994 
6997  {
6998  auto result = *this;
6999  result += i;
7000  return result;
7001  }
7002 
7005  {
7006  auto result = *this;
7007  result -= i;
7008  return result;
7009  }
7010 
7012  difference_type operator-(const iterator& other) const
7013  {
7014  return base_iterator::operator-(other);
7015  }
7016 
7019  {
7020  return const_cast<reference>(base_iterator::operator[](n));
7021  }
7022 
7025  {
7026  return const_cast<reference>(base_iterator::value());
7027  }
7028  };
7029 
7047  template<typename Base>
7048  class json_reverse_iterator : public std::reverse_iterator<Base>
7049  {
7050  public:
7052  using base_iterator = std::reverse_iterator<Base>;
7054  using reference = typename Base::reference;
7055 
7057  json_reverse_iterator(const typename base_iterator::iterator_type& it) noexcept
7058  : base_iterator(it)
7059  {}
7060 
7063  : base_iterator(it)
7064  {}
7065 
7068  {
7069  return base_iterator::operator++(1);
7070  }
7071 
7074  {
7075  base_iterator::operator++();
7076  return *this;
7077  }
7078 
7081  {
7082  return base_iterator::operator--(1);
7083  }
7084 
7087  {
7088  base_iterator::operator--();
7089  return *this;
7090  }
7091 
7094  {
7095  base_iterator::operator+=(i);
7096  return *this;
7097  }
7098 
7101  {
7102  auto result = *this;
7103  result += i;
7104  return result;
7105  }
7106 
7109  {
7110  auto result = *this;
7111  result -= i;
7112  return result;
7113  }
7114 
7117  {
7118  return this->base() - other.base();
7119  }
7120 
7123  {
7124  return *(this->operator+(n));
7125  }
7126 
7128  typename object_t::key_type key() const
7129  {
7130  auto it = --this->base();
7131  return it.key();
7132  }
7133 
7136  {
7137  auto it = --this->base();
7138  return it.operator * ();
7139  }
7140  };
7141 
7142 
7143  private:
7145  // lexer and parser //
7147 
7155  class lexer
7156  {
7157  public:
7159  enum class token_type
7160  {
7161  uninitialized,
7162  literal_true,
7163  literal_false,
7164  literal_null,
7165  value_string,
7166  value_number,
7167  begin_array,
7168  begin_object,
7169  end_array,
7170  end_object,
7171  name_separator,
7172  value_separator,
7173  parse_error,
7174  end_of_input
7175  };
7176 
7178  using lexer_char_t = unsigned char;
7179 
7181  explicit lexer(const string_t& s) noexcept
7182  : m_stream(nullptr), m_buffer(s)
7183  {
7184  m_content = reinterpret_cast<const lexer_char_t*>(s.c_str());
7185  assert(m_content != nullptr);
7186  m_start = m_cursor = m_content;
7187  m_limit = m_content + s.size();
7188  }
7189 
7191  explicit lexer(std::istream* s) noexcept
7192  : m_stream(s), m_buffer()
7193  {
7194  assert(m_stream != nullptr);
7195  getline(*m_stream, m_buffer);
7196  m_content = reinterpret_cast<const lexer_char_t*>(m_buffer.c_str());
7197  assert(m_content != nullptr);
7198  m_start = m_cursor = m_content;
7199  m_limit = m_content + m_buffer.size();
7200  }
7201 
7203  lexer() = default;
7204 
7205  // switch off unwanted functions
7206  lexer(const lexer&) = delete;
7207  lexer operator=(const lexer&) = delete;
7208 
7224  static string_t to_unicode(const std::size_t codepoint1,
7225  const std::size_t codepoint2 = 0)
7226  {
7227  // calculate the codepoint from the given code points
7228  std::size_t codepoint = codepoint1;
7229 
7230  // check if codepoint1 is a high surrogate
7231  if (codepoint1 >= 0xD800 and codepoint1 <= 0xDBFF)
7232  {
7233  // check if codepoint2 is a low surrogate
7234  if (codepoint2 >= 0xDC00 and codepoint2 <= 0xDFFF)
7235  {
7236  codepoint =
7237  // high surrogate occupies the most significant 22 bits
7238  (codepoint1 << 10)
7239  // low surrogate occupies the least significant 15 bits
7240  + codepoint2
7241  // there is still the 0xD800, 0xDC00 and 0x10000 noise
7242  // in the result so we have to subtract with:
7243  // (0xD800 << 10) + DC00 - 0x10000 = 0x35FDC00
7244  - 0x35FDC00;
7245  }
7246  else
7247  {
7248  throw std::invalid_argument("missing or wrong low surrogate");
7249  }
7250  }
7251 
7252  string_t result;
7253 
7254  if (codepoint < 0x80)
7255  {
7256  // 1-byte characters: 0xxxxxxx (ASCII)
7257  result.append(1, static_cast<typename string_t::value_type>(codepoint));
7258  }
7259  else if (codepoint <= 0x7ff)
7260  {
7261  // 2-byte characters: 110xxxxx 10xxxxxx
7262  result.append(1, static_cast<typename string_t::value_type>(0xC0 | ((codepoint >> 6) & 0x1F)));
7263  result.append(1, static_cast<typename string_t::value_type>(0x80 | (codepoint & 0x3F)));
7264  }
7265  else if (codepoint <= 0xffff)
7266  {
7267  // 3-byte characters: 1110xxxx 10xxxxxx 10xxxxxx
7268  result.append(1, static_cast<typename string_t::value_type>(0xE0 | ((codepoint >> 12) & 0x0F)));
7269  result.append(1, static_cast<typename string_t::value_type>(0x80 | ((codepoint >> 6) & 0x3F)));
7270  result.append(1, static_cast<typename string_t::value_type>(0x80 | (codepoint & 0x3F)));
7271  }
7272  else if (codepoint <= 0x10ffff)
7273  {
7274  // 4-byte characters: 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
7275  result.append(1, static_cast<typename string_t::value_type>(0xF0 | ((codepoint >> 18) & 0x07)));
7276  result.append(1, static_cast<typename string_t::value_type>(0x80 | ((codepoint >> 12) & 0x3F)));
7277  result.append(1, static_cast<typename string_t::value_type>(0x80 | ((codepoint >> 6) & 0x3F)));
7278  result.append(1, static_cast<typename string_t::value_type>(0x80 | (codepoint & 0x3F)));
7279  }
7280  else
7281  {
7282  throw std::out_of_range("code points above 0x10FFFF are invalid");
7283  }
7284 
7285  return result;
7286  }
7287 
7289  static std::string token_type_name(token_type t)
7290  {
7291  switch (t)
7292  {
7293  case token_type::uninitialized:
7294  return "<uninitialized>";
7295  case token_type::literal_true:
7296  return "true literal";
7297  case token_type::literal_false:
7298  return "false literal";
7299  case token_type::literal_null:
7300  return "null literal";
7301  case token_type::value_string:
7302  return "string literal";
7303  case token_type::value_number:
7304  return "number literal";
7305  case token_type::begin_array:
7306  return "'['";
7307  case token_type::begin_object:
7308  return "'{'";
7309  case token_type::end_array:
7310  return "']'";
7311  case token_type::end_object:
7312  return "'}'";
7313  case token_type::name_separator:
7314  return "':'";
7315  case token_type::value_separator:
7316  return "','";
7317  case token_type::parse_error:
7318  return "<parse error>";
7319  case token_type::end_of_input:
7320  return "end of input";
7321  default:
7322  {
7323  // catch non-enum values
7324  return "unknown token"; // LCOV_EXCL_LINE
7325  }
7326  }
7327  }
7328 
7339  token_type scan() noexcept
7340  {
7341  // pointer for backtracking information
7342  m_marker = nullptr;
7343 
7344  // remember the begin of the token
7345  m_start = m_cursor;
7346  assert(m_start != nullptr);
7347 
7348 
7349  {
7350  lexer_char_t yych;
7351  unsigned int yyaccept = 0;
7352  static const unsigned char yybm[] = {
7353  0, 0, 0, 0, 0, 0, 0, 0,
7354  0, 32, 32, 0, 0, 32, 0, 0,
7355  128, 128, 128, 128, 128, 128, 128, 128,
7356  128, 128, 128, 128, 128, 128, 128, 128,
7357  160, 128, 0, 128, 128, 128, 128, 128,
7358  128, 128, 128, 128, 128, 128, 128, 128,
7359  192, 192, 192, 192, 192, 192, 192, 192,
7360  192, 192, 128, 128, 128, 128, 128, 128,
7361  128, 128, 128, 128, 128, 128, 128, 128,
7362  128, 128, 128, 128, 128, 128, 128, 128,
7363  128, 128, 128, 128, 128, 128, 128, 128,
7364  128, 128, 128, 128, 0, 128, 128, 128,
7365  128, 128, 128, 128, 128, 128, 128, 128,
7366  128, 128, 128, 128, 128, 128, 128, 128,
7367  128, 128, 128, 128, 128, 128, 128, 128,
7368  128, 128, 128, 128, 128, 128, 128, 128,
7369  128, 128, 128, 128, 128, 128, 128, 128,
7370  128, 128, 128, 128, 128, 128, 128, 128,
7371  128, 128, 128, 128, 128, 128, 128, 128,
7372  128, 128, 128, 128, 128, 128, 128, 128,
7373  128, 128, 128, 128, 128, 128, 128, 128,
7374  128, 128, 128, 128, 128, 128, 128, 128,
7375  128, 128, 128, 128, 128, 128, 128, 128,
7376  128, 128, 128, 128, 128, 128, 128, 128,
7377  128, 128, 128, 128, 128, 128, 128, 128,
7378  128, 128, 128, 128, 128, 128, 128, 128,
7379  128, 128, 128, 128, 128, 128, 128, 128,
7380  128, 128, 128, 128, 128, 128, 128, 128,
7381  128, 128, 128, 128, 128, 128, 128, 128,
7382  128, 128, 128, 128, 128, 128, 128, 128,
7383  128, 128, 128, 128, 128, 128, 128, 128,
7384  128, 128, 128, 128, 128, 128, 128, 128,
7385  };
7386  if ((m_limit - m_cursor) < 5) yyfill(); // LCOV_EXCL_LINE;
7387  yych = *m_cursor;
7388  if (yybm[0+yych] & 32) {
7389  goto basic_json_parser_6;
7390  }
7391  if (yych <= '\\') {
7392  if (yych <= '-') {
7393  if (yych <= '"') {
7394  if (yych <= 0x00) goto basic_json_parser_2;
7395  if (yych <= '!') goto basic_json_parser_4;
7396  goto basic_json_parser_9;
7397  } else {
7398  if (yych <= '+') goto basic_json_parser_4;
7399  if (yych <= ',') goto basic_json_parser_10;
7400  goto basic_json_parser_12;
7401  }
7402  } else {
7403  if (yych <= '9') {
7404  if (yych <= '/') goto basic_json_parser_4;
7405  if (yych <= '0') goto basic_json_parser_13;
7406  goto basic_json_parser_15;
7407  } else {
7408  if (yych <= ':') goto basic_json_parser_17;
7409  if (yych == '[') goto basic_json_parser_19;
7410  goto basic_json_parser_4;
7411  }
7412  }
7413  } else {
7414  if (yych <= 't') {
7415  if (yych <= 'f') {
7416  if (yych <= ']') goto basic_json_parser_21;
7417  if (yych <= 'e') goto basic_json_parser_4;
7418  goto basic_json_parser_23;
7419  } else {
7420  if (yych == 'n') goto basic_json_parser_24;
7421  if (yych <= 's') goto basic_json_parser_4;
7422  goto basic_json_parser_25;
7423  }
7424  } else {
7425  if (yych <= '|') {
7426  if (yych == '{') goto basic_json_parser_26;
7427  goto basic_json_parser_4;
7428  } else {
7429  if (yych <= '}') goto basic_json_parser_28;
7430  if (yych == 0xEF) goto basic_json_parser_30;
7431  goto basic_json_parser_4;
7432  }
7433  }
7434  }
7435 basic_json_parser_2:
7436  ++m_cursor;
7437  { return token_type::end_of_input; }
7438 basic_json_parser_4:
7439  ++m_cursor;
7440 basic_json_parser_5:
7441  { return token_type::parse_error; }
7442 basic_json_parser_6:
7443  ++m_cursor;
7444  if (m_limit <= m_cursor) yyfill(); // LCOV_EXCL_LINE;
7445  yych = *m_cursor;
7446  if (yybm[0+yych] & 32) {
7447  goto basic_json_parser_6;
7448  }
7449  { return scan(); }
7450 basic_json_parser_9:
7451  yyaccept = 0;
7452  yych = *(m_marker = ++m_cursor);
7453  if (yych <= 0x0F) goto basic_json_parser_5;
7454  goto basic_json_parser_32;
7455 basic_json_parser_10:
7456  ++m_cursor;
7457  { return token_type::value_separator; }
7458 basic_json_parser_12:
7459  yych = *++m_cursor;
7460  if (yych <= '/') goto basic_json_parser_5;
7461  if (yych <= '0') goto basic_json_parser_13;
7462  if (yych <= '9') goto basic_json_parser_15;
7463  goto basic_json_parser_5;
7464 basic_json_parser_13:
7465  yyaccept = 1;
7466  yych = *(m_marker = ++m_cursor);
7467  if (yych <= 'D') {
7468  if (yych == '.') goto basic_json_parser_37;
7469  } else {
7470  if (yych <= 'E') goto basic_json_parser_38;
7471  if (yych == 'e') goto basic_json_parser_38;
7472  }
7473 basic_json_parser_14:
7474  { return token_type::value_number; }
7475 basic_json_parser_15:
7476  yyaccept = 1;
7477  m_marker = ++m_cursor;
7478  if ((m_limit - m_cursor) < 3) yyfill(); // LCOV_EXCL_LINE;
7479  yych = *m_cursor;
7480  if (yybm[0+yych] & 64) {
7481  goto basic_json_parser_15;
7482  }
7483  if (yych <= 'D') {
7484  if (yych == '.') goto basic_json_parser_37;
7485  goto basic_json_parser_14;
7486  } else {
7487  if (yych <= 'E') goto basic_json_parser_38;
7488  if (yych == 'e') goto basic_json_parser_38;
7489  goto basic_json_parser_14;
7490  }
7491 basic_json_parser_17:
7492  ++m_cursor;
7493  { return token_type::name_separator; }
7494 basic_json_parser_19:
7495  ++m_cursor;
7496  { return token_type::begin_array; }
7497 basic_json_parser_21:
7498  ++m_cursor;
7499  { return token_type::end_array; }
7500 basic_json_parser_23:
7501  yyaccept = 0;
7502  yych = *(m_marker = ++m_cursor);
7503  if (yych == 'a') goto basic_json_parser_39;
7504  goto basic_json_parser_5;
7505 basic_json_parser_24:
7506  yyaccept = 0;
7507  yych = *(m_marker = ++m_cursor);
7508  if (yych == 'u') goto basic_json_parser_40;
7509  goto basic_json_parser_5;
7510 basic_json_parser_25:
7511  yyaccept = 0;
7512  yych = *(m_marker = ++m_cursor);
7513  if (yych == 'r') goto basic_json_parser_41;
7514  goto basic_json_parser_5;
7515 basic_json_parser_26:
7516  ++m_cursor;
7517  { return token_type::begin_object; }
7518 basic_json_parser_28:
7519  ++m_cursor;
7520  { return token_type::end_object; }
7521 basic_json_parser_30:
7522  yyaccept = 0;
7523  yych = *(m_marker = ++m_cursor);
7524  if (yych == 0xBB) goto basic_json_parser_42;
7525  goto basic_json_parser_5;
7526 basic_json_parser_31:
7527  ++m_cursor;
7528  if (m_limit <= m_cursor) yyfill(); // LCOV_EXCL_LINE;
7529  yych = *m_cursor;
7530 basic_json_parser_32:
7531  if (yybm[0+yych] & 128) {
7532  goto basic_json_parser_31;
7533  }
7534  if (yych <= 0x0F) goto basic_json_parser_33;
7535  if (yych <= '"') goto basic_json_parser_34;
7536  goto basic_json_parser_36;
7537 basic_json_parser_33:
7538  m_cursor = m_marker;
7539  if (yyaccept == 0) {
7540  goto basic_json_parser_5;
7541  } else {
7542  goto basic_json_parser_14;
7543  }
7544 basic_json_parser_34:
7545  ++m_cursor;
7546  { return token_type::value_string; }
7547 basic_json_parser_36:
7548  ++m_cursor;
7549  if (m_limit <= m_cursor) yyfill(); // LCOV_EXCL_LINE;
7550  yych = *m_cursor;
7551  if (yych <= 'e') {
7552  if (yych <= '/') {
7553  if (yych == '"') goto basic_json_parser_31;
7554  if (yych <= '.') goto basic_json_parser_33;
7555  goto basic_json_parser_31;
7556  } else {
7557  if (yych <= '\\') {
7558  if (yych <= '[') goto basic_json_parser_33;
7559  goto basic_json_parser_31;
7560  } else {
7561  if (yych == 'b') goto basic_json_parser_31;
7562  goto basic_json_parser_33;
7563  }
7564  }
7565  } else {
7566  if (yych <= 'q') {
7567  if (yych <= 'f') goto basic_json_parser_31;
7568  if (yych == 'n') goto basic_json_parser_31;
7569  goto basic_json_parser_33;
7570  } else {
7571  if (yych <= 's') {
7572  if (yych <= 'r') goto basic_json_parser_31;
7573  goto basic_json_parser_33;
7574  } else {
7575  if (yych <= 't') goto basic_json_parser_31;
7576  if (yych <= 'u') goto basic_json_parser_43;
7577  goto basic_json_parser_33;
7578  }
7579  }
7580  }
7581 basic_json_parser_37:
7582  yych = *++m_cursor;
7583  if (yych <= '/') goto basic_json_parser_33;
7584  if (yych <= '9') goto basic_json_parser_44;
7585  goto basic_json_parser_33;
7586 basic_json_parser_38:
7587  yych = *++m_cursor;
7588  if (yych <= ',') {
7589  if (yych == '+') goto basic_json_parser_46;
7590  goto basic_json_parser_33;
7591  } else {
7592  if (yych <= '-') goto basic_json_parser_46;
7593  if (yych <= '/') goto basic_json_parser_33;
7594  if (yych <= '9') goto basic_json_parser_47;
7595  goto basic_json_parser_33;
7596  }
7597 basic_json_parser_39:
7598  yych = *++m_cursor;
7599  if (yych == 'l') goto basic_json_parser_49;
7600  goto basic_json_parser_33;
7601 basic_json_parser_40:
7602  yych = *++m_cursor;
7603  if (yych == 'l') goto basic_json_parser_50;
7604  goto basic_json_parser_33;
7605 basic_json_parser_41:
7606  yych = *++m_cursor;
7607  if (yych == 'u') goto basic_json_parser_51;
7608  goto basic_json_parser_33;
7609 basic_json_parser_42:
7610  yych = *++m_cursor;
7611  if (yych == 0xBF) goto basic_json_parser_52;
7612  goto basic_json_parser_33;
7613 basic_json_parser_43:
7614  ++m_cursor;
7615  if (m_limit <= m_cursor) yyfill(); // LCOV_EXCL_LINE;
7616  yych = *m_cursor;
7617  if (yych <= '@') {
7618  if (yych <= '/') goto basic_json_parser_33;
7619  if (yych <= '9') goto basic_json_parser_54;
7620  goto basic_json_parser_33;
7621  } else {
7622  if (yych <= 'F') goto basic_json_parser_54;
7623  if (yych <= '`') goto basic_json_parser_33;
7624  if (yych <= 'f') goto basic_json_parser_54;
7625  goto basic_json_parser_33;
7626  }
7627 basic_json_parser_44:
7628  yyaccept = 1;
7629  m_marker = ++m_cursor;
7630  if ((m_limit - m_cursor) < 3) yyfill(); // LCOV_EXCL_LINE;
7631  yych = *m_cursor;
7632  if (yych <= 'D') {
7633  if (yych <= '/') goto basic_json_parser_14;
7634  if (yych <= '9') goto basic_json_parser_44;
7635  goto basic_json_parser_14;
7636  } else {
7637  if (yych <= 'E') goto basic_json_parser_38;
7638  if (yych == 'e') goto basic_json_parser_38;
7639  goto basic_json_parser_14;
7640  }
7641 basic_json_parser_46:
7642  yych = *++m_cursor;
7643  if (yych <= '/') goto basic_json_parser_33;
7644  if (yych >= ':') goto basic_json_parser_33;
7645 basic_json_parser_47:
7646  ++m_cursor;
7647  if (m_limit <= m_cursor) yyfill(); // LCOV_EXCL_LINE;
7648  yych = *m_cursor;
7649  if (yych <= '/') goto basic_json_parser_14;
7650  if (yych <= '9') goto basic_json_parser_47;
7651  goto basic_json_parser_14;
7652 basic_json_parser_49:
7653  yych = *++m_cursor;
7654  if (yych == 's') goto basic_json_parser_55;
7655  goto basic_json_parser_33;
7656 basic_json_parser_50:
7657  yych = *++m_cursor;
7658  if (yych == 'l') goto basic_json_parser_56;
7659  goto basic_json_parser_33;
7660 basic_json_parser_51:
7661  yych = *++m_cursor;
7662  if (yych == 'e') goto basic_json_parser_58;
7663  goto basic_json_parser_33;
7664 basic_json_parser_52:
7665  ++m_cursor;
7666  { return scan(); }
7667 basic_json_parser_54:
7668  ++m_cursor;
7669  if (m_limit <= m_cursor) yyfill(); // LCOV_EXCL_LINE;
7670  yych = *m_cursor;
7671  if (yych <= '@') {
7672  if (yych <= '/') goto basic_json_parser_33;
7673  if (yych <= '9') goto basic_json_parser_60;
7674  goto basic_json_parser_33;
7675  } else {
7676  if (yych <= 'F') goto basic_json_parser_60;
7677  if (yych <= '`') goto basic_json_parser_33;
7678  if (yych <= 'f') goto basic_json_parser_60;
7679  goto basic_json_parser_33;
7680  }
7681 basic_json_parser_55:
7682  yych = *++m_cursor;
7683  if (yych == 'e') goto basic_json_parser_61;
7684  goto basic_json_parser_33;
7685 basic_json_parser_56:
7686  ++m_cursor;
7687  { return token_type::literal_null; }
7688 basic_json_parser_58:
7689  ++m_cursor;
7690  { return token_type::literal_true; }
7691 basic_json_parser_60:
7692  ++m_cursor;
7693  if (m_limit <= m_cursor) yyfill(); // LCOV_EXCL_LINE;
7694  yych = *m_cursor;
7695  if (yych <= '@') {
7696  if (yych <= '/') goto basic_json_parser_33;
7697  if (yych <= '9') goto basic_json_parser_63;
7698  goto basic_json_parser_33;
7699  } else {
7700  if (yych <= 'F') goto basic_json_parser_63;
7701  if (yych <= '`') goto basic_json_parser_33;
7702  if (yych <= 'f') goto basic_json_parser_63;
7703  goto basic_json_parser_33;
7704  }
7705 basic_json_parser_61:
7706  ++m_cursor;
7707  { return token_type::literal_false; }
7708 basic_json_parser_63:
7709  ++m_cursor;
7710  if (m_limit <= m_cursor) yyfill(); // LCOV_EXCL_LINE;
7711  yych = *m_cursor;
7712  if (yych <= '@') {
7713  if (yych <= '/') goto basic_json_parser_33;
7714  if (yych <= '9') goto basic_json_parser_31;
7715  goto basic_json_parser_33;
7716  } else {
7717  if (yych <= 'F') goto basic_json_parser_31;
7718  if (yych <= '`') goto basic_json_parser_33;
7719  if (yych <= 'f') goto basic_json_parser_31;
7720  goto basic_json_parser_33;
7721  }
7722  }
7723 
7724  }
7725 
7727  void yyfill() noexcept
7728  {
7729  if (m_stream == nullptr or not * m_stream)
7730  {
7731  return;
7732  }
7733 
7734  const auto offset_start = m_start - m_content;
7735  const auto offset_marker = m_marker - m_start;
7736  const auto offset_cursor = m_cursor - m_start;
7737 
7738  m_buffer.erase(0, static_cast<size_t>(offset_start));
7739  std::string line;
7740  assert(m_stream != nullptr);
7741  std::getline(*m_stream, line);
7742  m_buffer += "\n" + line; // add line with newline symbol
7743 
7744  m_content = reinterpret_cast<const lexer_char_t*>(m_buffer.c_str());
7745  assert(m_content != nullptr);
7746  m_start = m_content;
7747  m_marker = m_start + offset_marker;
7748  m_cursor = m_start + offset_cursor;
7749  m_limit = m_start + m_buffer.size() - 1;
7750  }
7751 
7753  string_t get_token() const
7754  {
7755  assert(m_start != nullptr);
7756  return string_t(reinterpret_cast<typename string_t::const_pointer>(m_start),
7757  static_cast<size_t>(m_cursor - m_start));
7758  }
7759 
7782  string_t get_string() const
7783  {
7784  string_t result;
7785  result.reserve(static_cast<size_t>(m_cursor - m_start - 2));
7786 
7787  // iterate the result between the quotes
7788  for (const lexer_char_t* i = m_start + 1; i < m_cursor - 1; ++i)
7789  {
7790  // process escaped characters
7791  if (*i == '\\')
7792  {
7793  // read next character
7794  ++i;
7795 
7796  switch (*i)
7797  {
7798  // the default escapes
7799  case 't':
7800  {
7801  result += "\t";
7802  break;
7803  }
7804  case 'b':
7805  {
7806  result += "\b";
7807  break;
7808  }
7809  case 'f':
7810  {
7811  result += "\f";
7812  break;
7813  }
7814  case 'n':
7815  {
7816  result += "\n";
7817  break;
7818  }
7819  case 'r':
7820  {
7821  result += "\r";
7822  break;
7823  }
7824  case '\\':
7825  {
7826  result += "\\";
7827  break;
7828  }
7829  case '/':
7830  {
7831  result += "/";
7832  break;
7833  }
7834  case '"':
7835  {
7836  result += "\"";
7837  break;
7838  }
7839 
7840  // unicode
7841  case 'u':
7842  {
7843  // get code xxxx from uxxxx
7844  auto codepoint = std::strtoul(std::string(reinterpret_cast<typename string_t::const_pointer>(i + 1),
7845  4).c_str(), nullptr, 16);
7846 
7847  // check if codepoint is a high surrogate
7848  if (codepoint >= 0xD800 and codepoint <= 0xDBFF)
7849  {
7850  // make sure there is a subsequent unicode
7851  if ((i + 6 >= m_limit) or * (i + 5) != '\\' or * (i + 6) != 'u')
7852  {
7853  throw std::invalid_argument("missing low surrogate");
7854  }
7855 
7856  // get code yyyy from uxxxx\uyyyy
7857  auto codepoint2 = std::strtoul(std::string(reinterpret_cast<typename string_t::const_pointer>
7858  (i + 7), 4).c_str(), nullptr, 16);
7859  result += to_unicode(codepoint, codepoint2);
7860  // skip the next 10 characters (xxxx\uyyyy)
7861  i += 10;
7862  }
7863  else
7864  {
7865  // add unicode character(s)
7866  result += to_unicode(codepoint);
7867  // skip the next four characters (xxxx)
7868  i += 4;
7869  }
7870  break;
7871  }
7872  }
7873  }
7874  else
7875  {
7876  // all other characters are just copied to the end of the
7877  // string
7878  result.append(1, static_cast<typename string_t::value_type>(*i));
7879  }
7880  }
7881 
7882  return result;
7883  }
7884 
7905  long double str_to_float_t(long double* /* type */, char** endptr) const
7906  {
7907  return std::strtold(reinterpret_cast<typename string_t::const_pointer>(m_start), endptr);
7908  }
7909 
7925  double str_to_float_t(double* /* type */, char** endptr) const
7926  {
7927  return std::strtod(reinterpret_cast<typename string_t::const_pointer>(m_start), endptr);
7928  }
7929 
7945  float str_to_float_t(float* /* type */, char** endptr) const
7946  {
7947  return std::strtof(reinterpret_cast<typename string_t::const_pointer>(m_start), endptr);
7948  }
7949 
7971  void get_number(basic_json& result) const
7972  {
7973  assert(m_start != nullptr);
7974 
7975  const lexer::lexer_char_t* curptr = m_start;
7976 
7977  // accumulate the integer conversion result (unsigned for now)
7978  number_unsigned_t value = 0;
7979 
7980  // maximum absolute value of the relevant integer type
7981  number_unsigned_t max;
7982 
7983  // temporarily store the type to avoid unecessary bitfield access
7984  value_t type;
7985 
7986  // look for sign
7987  if (*curptr == '-')
7988  {
7989  type = value_t::number_integer;
7990  max = static_cast<uint64_t>((std::numeric_limits<number_integer_t>::max)()) + 1;
7991  curptr++;
7992  }
7993  else
7994  {
7995  type = value_t::number_unsigned;
7996  max = static_cast<uint64_t>((std::numeric_limits<number_unsigned_t>::max)());
7997  }
7998 
7999  // count the significant figures
8000  for (; curptr < m_cursor; curptr++)
8001  {
8002  // quickly skip tests if a digit
8003  if (*curptr < '0' || *curptr > '9')
8004  {
8005  if (*curptr == '.')
8006  {
8007  // don't count '.' but change to float
8008  type = value_t::number_float;
8009  continue;
8010  }
8011  // assume exponent (if not then will fail parse): change to
8012  // float, stop counting and record exponent details
8013  type = value_t::number_float;
8014  break;
8015  }
8016 
8017  // skip if definitely not an integer
8018  if (type != value_t::number_float)
8019  {
8020  // multiply last value by ten and add the new digit
8021  auto temp = value * 10 + *curptr - 0x30;
8022 
8023  // test for overflow
8024  if (temp < value || temp > max)
8025  {
8026  // overflow
8027  type = value_t::number_float;
8028  }
8029  else
8030  {
8031  // no overflow - save it
8032  value = temp;
8033  }
8034  }
8035  }
8036 
8037  // save the value (if not a float)
8038  if (type == value_t::number_unsigned)
8039  {
8040  result.m_value.number_unsigned = value;
8041  }
8042  else if (type == value_t::number_integer)
8043  {
8044  result.m_value.number_integer = -static_cast<number_integer_t>(value);
8045  }
8046  else
8047  {
8048  // parse with strtod
8049  result.m_value.number_float = str_to_float_t(static_cast<number_float_t*>(nullptr), NULL);
8050  }
8051 
8052  // save the type
8053  result.m_type = type;
8054  }
8055 
8056  private:
8058  std::istream* m_stream = nullptr;
8060  string_t m_buffer;
8062  const lexer_char_t* m_content = nullptr;
8064  const lexer_char_t* m_start = nullptr;
8066  const lexer_char_t* m_marker = nullptr;
8068  const lexer_char_t* m_cursor = nullptr;
8070  const lexer_char_t* m_limit = nullptr;
8071  };
8072 
8078  class parser
8079  {
8080  public:
8082  parser(const string_t& s, parser_callback_t cb = nullptr) noexcept
8083  : callback(cb), m_lexer(s)
8084  {
8085  // read first token
8086  get_token();
8087  }
8088 
8090  parser(std::istream& _is, parser_callback_t cb = nullptr) noexcept
8091  : callback(cb), m_lexer(&_is)
8092  {
8093  // read first token
8094  get_token();
8095  }
8096 
8098  basic_json parse()
8099  {
8100  basic_json result = parse_internal(true);
8101 
8102  expect(lexer::token_type::end_of_input);
8103 
8104  // return parser result and replace it with null in case the
8105  // top-level value was discarded by the callback function
8106  return result.is_discarded() ? basic_json() : result;
8107  }
8108 
8109  private:
8111  basic_json parse_internal(bool keep)
8112  {
8113  auto result = basic_json(value_t::discarded);
8114 
8115  switch (last_token)
8116  {
8117  case lexer::token_type::begin_object:
8118  {
8119  if (keep and (not callback or (keep = callback(depth++, parse_event_t::object_start, result))))
8120  {
8121  // explicitly set result to object to cope with {}
8122  result.m_type = value_t::object;
8123  result.m_value = json_value(value_t::object);
8124  }
8125 
8126  // read next token
8127  get_token();
8128 
8129  // closing } -> we are done
8130  if (last_token == lexer::token_type::end_object)
8131  {
8132  get_token();
8133  if (keep and callback and not callback(--depth, parse_event_t::object_end, result))
8134  {
8135  result = basic_json(value_t::discarded);
8136  }
8137  return result;
8138  }
8139 
8140  // no comma is expected here
8141  unexpect(lexer::token_type::value_separator);
8142 
8143  // otherwise: parse key-value pairs
8144  do
8145  {
8146  // ugly, but could be fixed with loop reorganization
8147  if (last_token == lexer::token_type::value_separator)
8148  {
8149  get_token();
8150  }
8151 
8152  // store key
8153  expect(lexer::token_type::value_string);
8154  const auto key = m_lexer.get_string();
8155 
8156  bool keep_tag = false;
8157  if (keep)
8158  {
8159  if (callback)
8160  {
8161  basic_json k(key);
8162  keep_tag = callback(depth, parse_event_t::key, k);
8163  }
8164  else
8165  {
8166  keep_tag = true;
8167  }
8168  }
8169 
8170  // parse separator (:)
8171  get_token();
8172  expect(lexer::token_type::name_separator);
8173 
8174  // parse and add value
8175  get_token();
8176  auto value = parse_internal(keep);
8177  if (keep and keep_tag and not value.is_discarded())
8178  {
8179  result[key] = std::move(value);
8180  }
8181  }
8182  while (last_token == lexer::token_type::value_separator);
8183 
8184  // closing }
8185  expect(lexer::token_type::end_object);
8186  get_token();
8187  if (keep and callback and not callback(--depth, parse_event_t::object_end, result))
8188  {
8189  result = basic_json(value_t::discarded);
8190  }
8191 
8192  return result;
8193  }
8194 
8195  case lexer::token_type::begin_array:
8196  {
8197  if (keep and (not callback or (keep = callback(depth++, parse_event_t::array_start, result))))
8198  {
8199  // explicitly set result to object to cope with []
8200  result.m_type = value_t::array;
8201  result.m_value = json_value(value_t::array);
8202  }
8203 
8204  // read next token
8205  get_token();
8206 
8207  // closing ] -> we are done
8208  if (last_token == lexer::token_type::end_array)
8209  {
8210  get_token();
8211  if (callback and not callback(--depth, parse_event_t::array_end, result))
8212  {
8213  result = basic_json(value_t::discarded);
8214  }
8215  return result;
8216  }
8217 
8218  // no comma is expected here
8219  unexpect(lexer::token_type::value_separator);
8220 
8221  // otherwise: parse values
8222  do
8223  {
8224  // ugly, but could be fixed with loop reorganization
8225  if (last_token == lexer::token_type::value_separator)
8226  {
8227  get_token();
8228  }
8229 
8230  // parse value
8231  auto value = parse_internal(keep);
8232  if (keep and not value.is_discarded())
8233  {
8234  result.push_back(std::move(value));
8235  }
8236  }
8237  while (last_token == lexer::token_type::value_separator);
8238 
8239  // closing ]
8240  expect(lexer::token_type::end_array);
8241  get_token();
8242  if (keep and callback and not callback(--depth, parse_event_t::array_end, result))
8243  {
8244  result = basic_json(value_t::discarded);
8245  }
8246 
8247  return result;
8248  }
8249 
8250  case lexer::token_type::literal_null:
8251  {
8252  get_token();
8253  result.m_type = value_t::null;
8254  break;
8255  }
8256 
8257  case lexer::token_type::value_string:
8258  {
8259  const auto s = m_lexer.get_string();
8260  get_token();
8261  result = basic_json(s);
8262  break;
8263  }
8264 
8265  case lexer::token_type::literal_true:
8266  {
8267  get_token();
8268  result.m_type = value_t::boolean;
8269  result.m_value = true;
8270  break;
8271  }
8272 
8273  case lexer::token_type::literal_false:
8274  {
8275  get_token();
8276  result.m_type = value_t::boolean;
8277  result.m_value = false;
8278  break;
8279  }
8280 
8281  case lexer::token_type::value_number:
8282  {
8283  m_lexer.get_number(result);
8284  get_token();
8285  break;
8286  }
8287 
8288  default:
8289  {
8290  // the last token was unexpected
8291  unexpect(last_token);
8292  }
8293  }
8294 
8295  if (keep and callback and not callback(depth, parse_event_t::value, result))
8296  {
8297  result = basic_json(value_t::discarded);
8298  }
8299  return result;
8300  }
8301 
8303  typename lexer::token_type get_token() noexcept
8304  {
8305  last_token = m_lexer.scan();
8306  return last_token;
8307  }
8308 
8309  void expect(typename lexer::token_type t) const
8310  {
8311  if (t != last_token)
8312  {
8313  std::string error_msg = "parse error - unexpected ";
8314  error_msg += (last_token == lexer::token_type::parse_error ? ("'" + m_lexer.get_token() + "'") :
8315  lexer::token_type_name(last_token));
8316  error_msg += "; expected " + lexer::token_type_name(t);
8317  throw std::invalid_argument(error_msg);
8318  }
8319  }
8320 
8321  void unexpect(typename lexer::token_type t) const
8322  {
8323  if (t == last_token)
8324  {
8325  std::string error_msg = "parse error - unexpected ";
8326  error_msg += (last_token == lexer::token_type::parse_error ? ("'" + m_lexer.get_token() + "'") :
8327  lexer::token_type_name(last_token));
8328  throw std::invalid_argument(error_msg);
8329  }
8330  }
8331 
8332  private:
8334  int depth = 0;
8336  parser_callback_t callback;
8338  typename lexer::token_type last_token = lexer::token_type::uninitialized;
8340  lexer m_lexer;
8341  };
8342 
8343  public:
8356  {
8358  friend class basic_json;
8359 
8360  public:
8383  explicit json_pointer(const std::string& s = "")
8384  : reference_tokens(split(s))
8385  {}
8386 
8402  std::string to_string() const noexcept
8403  {
8404  std::string result;
8405 
8406  for (const auto& reference_token : reference_tokens)
8407  {
8408  result += "/" + escape(reference_token);
8409  }
8410 
8411  return result;
8412  }
8413 
8415  operator std::string() const
8416  {
8417  return to_string();
8418  }
8420  private:
8422  std::string pop_back()
8423  {
8424  if (is_root())
8425  {
8426  throw std::domain_error("JSON pointer has no parent");
8427  }
8428 
8429  auto last = reference_tokens.back();
8430  reference_tokens.pop_back();
8431  return last;
8432  }
8433 
8435  bool is_root() const
8436  {
8437  return reference_tokens.empty();
8438  }
8439 
8440  json_pointer top() const
8441  {
8442  if (is_root())
8443  {
8444  throw std::domain_error("JSON pointer has no parent");
8445  }
8446 
8447  json_pointer result = *this;
8448  result.reference_tokens = {reference_tokens[0]};
8449  return result;
8450  }
8451 
8455  reference get_and_create(reference j) const
8456  {
8457  pointer result = &j;
8458 
8459  // in case no reference tokens exist, return a reference to the
8460  // JSON value j which will be overwritten by a primitive value
8461  for (const auto& reference_token : reference_tokens)
8462  {
8463  switch (result->m_type)
8464  {
8465  case value_t::null:
8466  {
8467  if (reference_token == "0")
8468  {
8469  // start a new array if reference token is 0
8470  result = &result->operator[](0);
8471  }
8472  else
8473  {
8474  // start a new object otherwise
8475  result = &result->operator[](reference_token);
8476  }
8477  break;
8478  }
8479 
8480  case value_t::object:
8481  {
8482  // create an entry in the object
8483  result = &result->operator[](reference_token);
8484  break;
8485  }
8486 
8487  case value_t::array:
8488  {
8489  // create an entry in the array
8490  result = &result->operator[](static_cast<size_type>(std::stoi(reference_token)));
8491  break;
8492  }
8493 
8494  /*
8495  The following code is only reached if there exists a
8496  reference token _and_ the current value is primitive. In
8497  this case, we have an error situation, because primitive
8498  values may only occur as single value; that is, with an
8499  empty list of reference tokens.
8500  */
8501  default:
8502  {
8503  throw std::domain_error("invalid value to unflatten");
8504  }
8505  }
8506  }
8507 
8508  return *result;
8509  }
8510 
8524  reference get_unchecked(pointer ptr) const
8525  {
8526  for (const auto& reference_token : reference_tokens)
8527  {
8528  switch (ptr->m_type)
8529  {
8530  case value_t::object:
8531  {
8532  // use unchecked object access
8533  ptr = &ptr->operator[](reference_token);
8534  break;
8535  }
8536 
8537  case value_t::array:
8538  {
8539  // error condition (cf. RFC 6901, Sect. 4)
8540  if (reference_token.size() > 1 and reference_token[0] == '0')
8541  {
8542  throw std::domain_error("array index must not begin with '0'");
8543  }
8544 
8545  if (reference_token == "-")
8546  {
8547  // explicityly treat "-" as index beyond the end
8548  ptr = &ptr->operator[](ptr->m_value.array->size());
8549  }
8550  else
8551  {
8552  // convert array index to number; unchecked access
8553  ptr = &ptr->operator[](static_cast<size_type>(std::stoi(reference_token)));
8554  }
8555  break;
8556  }
8557 
8558  default:
8559  {
8560  throw std::out_of_range("unresolved reference token '" + reference_token + "'");
8561  }
8562  }
8563  }
8564 
8565  return *ptr;
8566  }
8567 
8568  reference get_checked(pointer ptr) const
8569  {
8570  for (const auto& reference_token : reference_tokens)
8571  {
8572  switch (ptr->m_type)
8573  {
8574  case value_t::object:
8575  {
8576  // note: at performs range check
8577  ptr = &ptr->at(reference_token);
8578  break;
8579  }
8580 
8581  case value_t::array:
8582  {
8583  if (reference_token == "-")
8584  {
8585  // "-" always fails the range check
8586  throw std::out_of_range("array index '-' (" +
8587  std::to_string(ptr->m_value.array->size()) +
8588  ") is out of range");
8589  }
8590 
8591  // error condition (cf. RFC 6901, Sect. 4)
8592  if (reference_token.size() > 1 and reference_token[0] == '0')
8593  {
8594  throw std::domain_error("array index must not begin with '0'");
8595  }
8596 
8597  // note: at performs range check
8598  ptr = &ptr->at(static_cast<size_type>(std::stoi(reference_token)));
8599  break;
8600  }
8601 
8602  default:
8603  {
8604  throw std::out_of_range("unresolved reference token '" + reference_token + "'");
8605  }
8606  }
8607  }
8608 
8609  return *ptr;
8610  }
8611 
8620  const_reference get_unchecked(const_pointer ptr) const
8621  {
8622  for (const auto& reference_token : reference_tokens)
8623  {
8624  switch (ptr->m_type)
8625  {
8626  case value_t::object:
8627  {
8628  // use unchecked object access
8629  ptr = &ptr->operator[](reference_token);
8630  break;
8631  }
8632 
8633  case value_t::array:
8634  {
8635  if (reference_token == "-")
8636  {
8637  // "-" cannot be used for const access
8638  throw std::out_of_range("array index '-' (" +
8639  std::to_string(ptr->m_value.array->size()) +
8640  ") is out of range");
8641  }
8642 
8643  // error condition (cf. RFC 6901, Sect. 4)
8644  if (reference_token.size() > 1 and reference_token[0] == '0')
8645  {
8646  throw std::domain_error("array index must not begin with '0'");
8647  }
8648 
8649  // use unchecked array access
8650  ptr = &ptr->operator[](static_cast<size_type>(std::stoi(reference_token)));
8651  break;
8652  }
8653 
8654  default:
8655  {
8656  throw std::out_of_range("unresolved reference token '" + reference_token + "'");
8657  }
8658  }
8659  }
8660 
8661  return *ptr;
8662  }
8663 
8664  const_reference get_checked(const_pointer ptr) const
8665  {
8666  for (const auto& reference_token : reference_tokens)
8667  {
8668  switch (ptr->m_type)
8669  {
8670  case value_t::object:
8671  {
8672  // note: at performs range check
8673  ptr = &ptr->at(reference_token);
8674  break;
8675  }
8676 
8677  case value_t::array:
8678  {
8679  if (reference_token == "-")
8680  {
8681  // "-" always fails the range check
8682  throw std::out_of_range("array index '-' (" +
8683  std::to_string(ptr->m_value.array->size()) +
8684  ") is out of range");
8685  }
8686 
8687  // error condition (cf. RFC 6901, Sect. 4)
8688  if (reference_token.size() > 1 and reference_token[0] == '0')
8689  {
8690  throw std::domain_error("array index must not begin with '0'");
8691  }
8692 
8693  // note: at performs range check
8694  ptr = &ptr->at(static_cast<size_type>(std::stoi(reference_token)));
8695  break;
8696  }
8697 
8698  default:
8699  {
8700  throw std::out_of_range("unresolved reference token '" + reference_token + "'");
8701  }
8702  }
8703  }
8704 
8705  return *ptr;
8706  }
8707 
8709  static std::vector<std::string> split(std::string reference_string)
8710  {
8711  std::vector<std::string> result;
8712 
8713  // special case: empty reference string -> no reference tokens
8714  if (reference_string.empty())
8715  {
8716  return result;
8717  }
8718 
8719  // check if nonempty reference string begins with slash
8720  if (reference_string[0] != '/')
8721  {
8722  throw std::domain_error("JSON pointer must be empty or begin with '/'");
8723  }
8724 
8725  // extract the reference tokens:
8726  // - slash: position of the last read slash (or end of string)
8727  // - start: position after the previous slash
8728  for (
8729  // search for the first slash after the first character
8730  size_t slash = reference_string.find_first_of("/", 1),
8731  // set the beginning of the first reference token
8732  start = 1;
8733  // we can stop if start == string::npos+1 = 0
8734  start != 0;
8735  // set the beginning of the next reference token
8736  // (will eventually be 0 if slash == std::string::npos)
8737  start = slash + 1,
8738  // find next slash
8739  slash = reference_string.find_first_of("/", start))
8740  {
8741  // use the text between the beginning of the reference token
8742  // (start) and the last slash (slash).
8743  auto reference_token = reference_string.substr(start, slash - start);
8744 
8745  // check reference tokens are properly escaped
8746  for (size_t pos = reference_token.find_first_of("~");
8747  pos != std::string::npos;
8748  pos = reference_token.find_first_of("~", pos + 1))
8749  {
8750  assert(reference_token[pos] == '~');
8751 
8752  // ~ must be followed by 0 or 1
8753  if (pos == reference_token.size() - 1 or
8754  (reference_token[pos + 1] != '0' and
8755  reference_token[pos + 1] != '1'))
8756  {
8757  throw std::domain_error("escape error: '~' must be followed with '0' or '1'");
8758  }
8759  }
8760 
8761  // finally, store the reference token
8762  unescape(reference_token);
8763  result.push_back(reference_token);
8764  }
8765 
8766  return result;
8767  }
8768 
8769  private:
8784  static void replace_substring(std::string& s,
8785  const std::string& f,
8786  const std::string& t)
8787  {
8788  assert(not f.empty());
8789 
8790  for (
8791  size_t pos = s.find(f); // find first occurrence of f
8792  pos != std::string::npos; // make sure f was found
8793  s.replace(pos, f.size(), t), // replace with t
8794  pos = s.find(f, pos + t.size()) // find next occurrence of f
8795  );
8796  }
8797 
8799  static std::string escape(std::string s)
8800  {
8801  // escape "~"" to "~0" and "/" to "~1"
8802  replace_substring(s, "~", "~0");
8803  replace_substring(s, "/", "~1");
8804  return s;
8805  }
8806 
8808  static void unescape(std::string& s)
8809  {
8810  // first transform any occurrence of the sequence '~1' to '/'
8811  replace_substring(s, "~1", "/");
8812  // then transform any occurrence of the sequence '~0' to '~'
8813  replace_substring(s, "~0", "~");
8814  }
8815 
8823  static void flatten(const std::string& reference_string,
8824  const basic_json& value,
8825  basic_json& result)
8826  {
8827  switch (value.m_type)
8828  {
8829  case value_t::array:
8830  {
8831  if (value.m_value.array->empty())
8832  {
8833  // flatten empty array as null
8834  result[reference_string] = nullptr;
8835  }
8836  else
8837  {
8838  // iterate array and use index as reference string
8839  for (size_t i = 0; i < value.m_value.array->size(); ++i)
8840  {
8841  flatten(reference_string + "/" + std::to_string(i),
8842  value.m_value.array->operator[](i), result);
8843  }
8844  }
8845  break;
8846  }
8847 
8848  case value_t::object:
8849  {
8850  if (value.m_value.object->empty())
8851  {
8852  // flatten empty object as null
8853  result[reference_string] = nullptr;
8854  }
8855  else
8856  {
8857  // iterate object and use keys as reference string
8858  for (const auto& element : *value.m_value.object)
8859  {
8860  flatten(reference_string + "/" + escape(element.first),
8861  element.second, result);
8862  }
8863  }
8864  break;
8865  }
8866 
8867  default:
8868  {
8869  // add primitive value with its reference string
8870  result[reference_string] = value;
8871  break;
8872  }
8873  }
8874  }
8875 
8881  static basic_json unflatten(const basic_json& value)
8882  {
8883  if (not value.is_object())
8884  {
8885  throw std::domain_error("only objects can be unflattened");
8886  }
8887 
8888  basic_json result;
8889 
8890  // iterate the JSON object values
8891  for (const auto& element : *value.m_value.object)
8892  {
8893  if (not element.second.is_primitive())
8894  {
8895  throw std::domain_error("values in object must be primitive");
8896  }
8897 
8898  // assign value to reference pointed to by JSON pointer; Note
8899  // that if the JSON pointer is "" (i.e., points to the whole
8900  // value), function get_and_create returns a reference to
8901  // result itself. An assignment will then create a primitive
8902  // value.
8903  json_pointer(element.first).get_and_create(result) = element.second;
8904  }
8905 
8906  return result;
8907  }
8908 
8909  private:
8911  std::vector<std::string> reference_tokens {};
8912  };
8913 
8915  // JSON Pointer support //
8917 
8920 
8954  reference operator[](const json_pointer& ptr)
8955  {
8956  return ptr.get_unchecked(this);
8957  }
8981  const_reference operator[](const json_pointer& ptr) const
8982  {
8983  return ptr.get_unchecked(this);
8984  }
9006  reference at(const json_pointer& ptr)
9007  {
9008  return ptr.get_checked(this);
9009  }
9031  const_reference at(const json_pointer& ptr) const
9032  {
9033  return ptr.get_checked(this);
9034  }
9058  basic_json flatten() const
9059  {
9060  basic_json result(value_t::object);
9061  json_pointer::flatten("", *this, result);
9062  return result;
9063  }
9064 
9092  basic_json unflatten() const
9093  {
9094  return json_pointer::unflatten(*this);
9095  }
9098 
9100  // JSON Patch functions //
9102 
9105 
9142  basic_json patch(const basic_json& json_patch) const
9143  {
9144  // make a working copy to apply the patch to
9145  basic_json result = *this;
9147  // the valid JSON Patch operations
9148  enum class patch_operations {add, remove, replace, move, copy, test, invalid};
9149 
9150  const auto get_op = [](const std::string op)
9151  {
9152  if (op == "add")
9153  {
9154  return patch_operations::add;
9155  }
9156  if (op == "remove")
9157  {
9158  return patch_operations::remove;
9159  }
9160  if (op == "replace")
9161  {
9162  return patch_operations::replace;
9163  }
9164  if (op == "move")
9165  {
9166  return patch_operations::move;
9167  }
9168  if (op == "copy")
9169  {
9170  return patch_operations::copy;
9171  }
9172  if (op == "test")
9173  {
9174  return patch_operations::test;
9175  }
9176 
9177  return patch_operations::invalid;
9178  };
9179 
9180  // wrapper for "add" operation; add value at ptr
9181  const auto operation_add = [&result](json_pointer & ptr, basic_json val)
9182  {
9183  // adding to the root of the target document means replacing it
9184  if (ptr.is_root())
9185  {
9186  result = val;
9187  }
9188  else
9189  {
9190  // make sure the top element of the pointer exists
9191  json_pointer top_pointer = ptr.top();
9192  if (top_pointer != ptr)
9193  {
9194  basic_json& x = result.at(top_pointer);
9195  }
9196 
9197  // get reference to parent of JSON pointer ptr
9198  const auto last_path = ptr.pop_back();
9199  basic_json& parent = result[ptr];
9200 
9201  switch (parent.m_type)
9202  {
9203  case value_t::null:
9204  case value_t::object:
9205  {
9206  // use operator[] to add value
9207  parent[last_path] = val;
9208  break;
9209  }
9210 
9211  case value_t::array:
9212  {
9213  if (last_path == "-")
9214  {
9215  // special case: append to back
9216  parent.push_back(val);
9217  }
9218  else
9219  {
9220  const auto idx = std::stoi(last_path);
9221  if (static_cast<size_type>(idx) > parent.size())
9222  {
9223  // avoid undefined behavior
9224  throw std::out_of_range("array index " + std::to_string(idx) + " is out of range");
9225  }
9226  else
9227  {
9228  // default case: insert add offset
9229  parent.insert(parent.begin() + static_cast<difference_type>(idx), val);
9230  }
9231  }
9232  break;
9233  }
9234 
9235  default:
9236  {
9237  // if there exists a parent it cannot be primitive
9238  assert(false); // LCOV_EXCL_LINE
9239  }
9240  }
9241  }
9242  };
9243 
9244  // wrapper for "remove" operation; remove value at ptr
9245  const auto operation_remove = [&result](json_pointer & ptr)
9246  {
9247  // get reference to parent of JSON pointer ptr
9248  const auto last_path = ptr.pop_back();
9249  basic_json& parent = result.at(ptr);
9250 
9251  // remove child
9252  if (parent.is_object())
9253  {
9254  // perform range check
9255  auto it = parent.find(last_path);
9256  if (it != parent.end())
9257  {
9258  parent.erase(it);
9259  }
9260  else
9261  {
9262  throw std::out_of_range("key '" + last_path + "' not found");
9263  }
9264  }
9265  else if (parent.is_array())
9266  {
9267  // note erase performs range check
9268  parent.erase(static_cast<size_type>(std::stoi(last_path)));
9269  }
9270  };
9271 
9272  // type check
9273  if (not json_patch.is_array())
9274  {
9275  // a JSON patch must be an array of objects
9276  throw std::invalid_argument("JSON patch must be an array of objects");
9277  }
9278 
9279  // iterate and apply th eoperations
9280  for (const auto& val : json_patch)
9281  {
9282  // wrapper to get a value for an operation
9283  const auto get_value = [&val](const std::string & op,
9284  const std::string & member,
9285  bool string_type) -> basic_json&
9286  {
9287  // find value
9288  auto it = val.m_value.object->find(member);
9289 
9290  // context-sensitive error message
9291  const auto error_msg = (op == "op") ? "operation" : "operation '" + op + "'";
9292 
9293  // check if desired value is present
9294  if (it == val.m_value.object->end())
9295  {
9296  throw std::invalid_argument(error_msg + " must have member '" + member + "'");
9297  }
9298 
9299  // check if result is of type string
9300  if (string_type and not it->second.is_string())
9301  {
9302  throw std::invalid_argument(error_msg + " must have string member '" + member + "'");
9303  }
9304 
9305  // no error: return value
9306  return it->second;
9307  };
9308 
9309  // type check
9310  if (not val.is_object())
9311  {
9312  throw std::invalid_argument("JSON patch must be an array of objects");
9313  }
9314 
9315  // collect mandatory members
9316  const std::string op = get_value("op", "op", true);
9317  const std::string path = get_value(op, "path", true);
9318  json_pointer ptr(path);
9319 
9320  switch (get_op(op))
9321  {
9322  case patch_operations::add:
9323  {
9324  operation_add(ptr, get_value("add", "value", false));
9325  break;
9326  }
9327 
9328  case patch_operations::remove:
9329  {
9330  operation_remove(ptr);
9331  break;
9332  }
9333 
9334  case patch_operations::replace:
9335  {
9336  // the "path" location must exist - use at()
9337  result.at(ptr) = get_value("replace", "value", false);
9338  break;
9339  }
9340 
9341  case patch_operations::move:
9342  {
9343  const std::string from_path = get_value("move", "from", true);
9344  json_pointer from_ptr(from_path);
9345 
9346  // the "from" location must exist - use at()
9347  basic_json v = result.at(from_ptr);
9348 
9349  // The move operation is functionally identical to a
9350  // "remove" operation on the "from" location, followed
9351  // immediately by an "add" operation at the target
9352  // location with the value that was just removed.
9353  operation_remove(from_ptr);
9354  operation_add(ptr, v);
9355  break;
9356  }
9357 
9358  case patch_operations::copy:
9359  {
9360  const std::string from_path = get_value("copy", "from", true);;
9361  const json_pointer from_ptr(from_path);
9362 
9363  // the "from" location must exist - use at()
9364  result[ptr] = result.at(from_ptr);
9365  break;
9366  }
9367 
9368  case patch_operations::test:
9369  {
9370  bool success = false;
9371  try
9372  {
9373  // check if "value" matches the one at "path"
9374  // the "path" location must exist - use at()
9375  success = (result.at(ptr) == get_value("test", "value", false));
9376  }
9377  catch (std::out_of_range&)
9378  {
9379  // ignore out of range errors: success remains false
9380  }
9381 
9382  // throw an exception if test fails
9383  if (not success)
9384  {
9385  throw std::domain_error("unsuccessful: " + val.dump());
9386  }
9387 
9388  break;
9389  }
9390 
9391  case patch_operations::invalid:
9392  {
9393  // op must be "add", "remove", "replace", "move", "copy", or
9394  // "test"
9395  throw std::invalid_argument("operation value '" + op + "' is invalid");
9396  }
9397  }
9398  }
9399 
9400  return result;
9401  }
9402 
9435  static basic_json diff(const basic_json& source,
9436  const basic_json& target,
9437  std::string path = "")
9438  {
9439  // the patch
9440  basic_json result(value_t::array);
9441 
9442  // if the values are the same, return empty patch
9443  if (source == target)
9444  {
9445  return result;
9446  }
9447 
9448  if (source.type() != target.type())
9449  {
9450  // different types: replace value
9451  result.push_back(
9452  {
9453  {"op", "replace"},
9454  {"path", path},
9455  {"value", target}
9456  });
9457  }
9458  else
9459  {
9460  switch (source.type())
9461  {
9462  case value_t::array:
9463  {
9464  // first pass: traverse common elements
9465  size_t i = 0;
9466  while (i < source.size() and i < target.size())
9467  {
9468  // recursive call to compare array values at index i
9469  auto temp_diff = diff(source[i], target[i], path + "/" + std::to_string(i));
9470  result.insert(result.end(), temp_diff.begin(), temp_diff.end());
9471  ++i;
9472  }
9473 
9474  // i now reached the end of at least one array
9475  // in a second pass, traverse the remaining elements
9476 
9477  // remove my remaining elements
9478  const auto end_index = static_cast<difference_type>(result.size());
9479  while (i < source.size())
9480  {
9481  // add operations in reverse order to avoid invalid
9482  // indices
9483  result.insert(result.begin() + end_index, object(
9484  {
9485  {"op", "remove"},
9486  {"path", path + "/" + std::to_string(i)}
9487  }));
9488  ++i;
9489  }
9490 
9491  // add other remaining elements
9492  while (i < target.size())
9493  {
9494  result.push_back(
9495  {
9496  {"op", "add"},
9497  {"path", path + "/" + std::to_string(i)},
9498  {"value", target[i]}
9499  });
9500  ++i;
9501  }
9502 
9503  break;
9504  }
9505 
9506  case value_t::object:
9507  {
9508  // first pass: traverse this object's elements
9509  for (auto it = source.begin(); it != source.end(); ++it)
9510  {
9511  // escape the key name to be used in a JSON patch
9512  const auto key = json_pointer::escape(it.key());
9513 
9514  if (target.find(it.key()) != target.end())
9515  {
9516  // recursive call to compare object values at key it
9517  auto temp_diff = diff(it.value(), target[it.key()], path + "/" + key);
9518  result.insert(result.end(), temp_diff.begin(), temp_diff.end());
9519  }
9520  else
9521  {
9522  // found a key that is not in o -> remove it
9523  result.push_back(object(
9524  {
9525  {"op", "remove"},
9526  {"path", path + "/" + key}
9527  }));
9528  }
9529  }
9530 
9531  // second pass: traverse other object's elements
9532  for (auto it = target.begin(); it != target.end(); ++it)
9533  {
9534  if (source.find(it.key()) == source.end())
9535  {
9536  // found a key that is not in this -> add it
9537  const auto key = json_pointer::escape(it.key());
9538  result.push_back(
9539  {
9540  {"op", "add"},
9541  {"path", path + "/" + key},
9542  {"value", it.value()}
9543  });
9544  }
9545  }
9546 
9547  break;
9548  }
9549 
9550  default:
9551  {
9552  // both primitive type: replace value
9553  result.push_back(
9554  {
9555  {"op", "replace"},
9556  {"path", path},
9557  {"value", target}
9558  });
9559  break;
9560  }
9561  }
9562  }
9563 
9564  return result;
9565  }
9566 
9568 };
9569 
9570 
9572 // presets //
9574 
9583 using json = basic_json<>;
9584 }
9585 
9586 
9588 // nonmember support //
9590 
9591 // specialization of std::swap, and std::hash
9592 namespace std
9593 {
9599 template <>
9600 inline void swap(nlohmann::json& j1,
9601  nlohmann::json& j2) noexcept(
9602  is_nothrow_move_constructible<nlohmann::json>::value and
9603  is_nothrow_move_assignable<nlohmann::json>::value
9604  )
9605 {
9606  j1.swap(j2);
9607 }
9608 
9610 template <>
9611 struct hash<nlohmann::json>
9612 {
9618  std::size_t operator()(const nlohmann::json& j) const
9619  {
9620  // a naive hashing via the string representation
9621  const auto& h = hash<nlohmann::json::string_t>();
9622  return h(j.dump());
9623  }
9624 };
9625 }
9626 
9639 inline nlohmann::json operator "" _json(const char* s, std::size_t)
9640 {
9641  return nlohmann::json::parse(reinterpret_cast<const nlohmann::json::string_t::value_type*>(s));
9642 }
9643 
9649 inline nlohmann::json::json_pointer operator "" _json_pointer(const char* s, std::size_t)
9650 {
9651  return nlohmann::json::json_pointer(s);
9652 }
9653 
9654 // restore GCC/clang diagnostic settings
9655 #if defined(__clang__) || defined(__GNUC__) || defined(__GNUG__)
9656  #pragma GCC diagnostic pop
9657 #endif
9658 
9659 #endif
const_iterator(pointer object) noexcept
constructor for a given JSON instance
Definition: json.hpp:6384
size_type max_size() const noexcept
returns the maximum possible number of elements
Definition: json.hpp:4573
friend bool operator<=(const_reference lhs, const_reference rhs) noexcept
comparison: less than or equal
Definition: json.hpp:5571
constexpr value_t type() const noexcept
return the type of the JSON value (explicit)
Definition: json.hpp:2133
constexpr bool is_array() const noexcept
return whether value is an array
Definition: json.hpp:2393
basic_json(const value_t value_type)
create an empty value with a given type
Definition: json.hpp:967
basic_json(const array_t &val)
create an array (explicit)
Definition: json.hpp:1104
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:4081
const_iterator end() const noexcept
returns a const iterator to one past the last element
Definition: json.hpp:4203
constexpr bool is_primitive() const noexcept
return whether type is primitive
Definition: json.hpp:2163
constexpr bool is_null() const noexcept
return whether value is null
Definition: json.hpp:2212
const_reference operator[](size_type idx) const
access specified array element
Definition: json.hpp:3272
const_reverse_iterator rend() const noexcept
returns a const reverse iterator to one before the first
Definition: json.hpp:4308
constexpr bool is_structured() const noexcept
return whether type is structured
Definition: json.hpp:2190
reference value() const
return the value of an iterator
Definition: json.hpp:7024
json_reverse_iterator & operator--()
pre-decrement (–it)
Definition: json.hpp:7086
void clear() noexcept
clears the contents
Definition: json.hpp:4632
bool operator==(const const_iterator &other) const
comparison: equal
Definition: json.hpp:6674
json_reverse_iterator operator--(int)
post-decrement (it–)
Definition: json.hpp:7080
reference operator[](T *(&key)[n])
access specified object element
Definition: json.hpp:3404
friend std::istream & operator>>(std::istream &i, basic_json &j)
deserialize from stream
Definition: json.hpp:5789
iterator & operator+=(difference_type i)
add to iterator
Definition: json.hpp:6982
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:1685
reference & operator=(basic_json other) noexcept(std::is_nothrow_move_constructible< value_t >::value andstd::is_nothrow_move_assignable< value_t >::value andstd::is_nothrow_move_constructible< json_value >::value andstd::is_nothrow_move_assignable< json_value >::value)
copy assignment
Definition: json.hpp:2000
constexpr bool is_number_unsigned() const noexcept
return whether value is an unsigned integer number
Definition: json.hpp:2321
const_iterator operator-(difference_type i)
subtract from iterator
Definition: json.hpp:6800
void swap(reference other) noexcept(std::is_nothrow_move_constructible< value_t >::value andstd::is_nothrow_move_assignable< value_t >::value andstd::is_nothrow_move_constructible< json_value >::value andstd::is_nothrow_move_assignable< json_value >::value)
exchanges the values
Definition: json.hpp:5100
BooleanType boolean_t
a type for a boolean
Definition: json.hpp:467
iterator & operator=(iterator other) noexcept(std::is_nothrow_move_constructible< pointer >::value andstd::is_nothrow_move_assignable< pointer >::value andstd::is_nothrow_move_constructible< internal_iterator >::value andstd::is_nothrow_move_assignable< internal_iterator >::value)
copy assignment
Definition: json.hpp:6928
reference operator+=(const typename object_t::value_type &val)
add an object to an object
Definition: json.hpp:4818
reference operator*() const
return a reference to the value pointed to by the iterator
Definition: json.hpp:6940
basic_json(const typename string_t::value_type *val)
create a string (explicit)
Definition: json.hpp:1197
reference operator[](difference_type n) const
access to successor
Definition: json.hpp:7122
iterator find(typename object_t::key_type key)
find an element in a JSON object
Definition: json.hpp:4033
friend bool operator!=(const_reference lhs, const_reference rhs) noexcept
comparison: not equal
Definition: json.hpp:5409
basic_json(const string_t &val)
create a string (explicit)
Definition: json.hpp:1173
void push_back(const basic_json &val)
add an object to an array
Definition: json.hpp:4744
void erase(const size_type idx)
remove element from a JSON array given an index
Definition: json.hpp:3986
ArrayType< basic_json, AllocatorType< basic_json >> array_t
a type for an array
Definition: json.hpp:394
reference front()
access the first element
Definition: json.hpp:3643
void swap(object_t &other)
exchanges the values
Definition: json.hpp:5165
json_reverse_iterator operator-(difference_type i) const
subtract from iterator
Definition: json.hpp:7108
const_iterator & operator+=(difference_type i)
add to iterator
Definition: json.hpp:6758
a class to store JSON values
Definition: json.hpp:187
basic_json(const int val) noexcept
create an integer number from an enum type (explicit)
Definition: json.hpp:1308
reference value() const
return the value of an iterator
Definition: json.hpp:7135
constexpr bool is_object() const noexcept
return whether value is an object
Definition: json.hpp:2371
friend bool operator==(std::nullptr_t, const_reference v) noexcept
comparison: equal
Definition: json.hpp:5388
NumberIntegerType number_integer_t
a type for a number (integer)
Definition: json.hpp:539
iterator insert(const_iterator pos, size_type cnt, const basic_json &val)
inserts elements
Definition: json.hpp:4950
const_reference at(const typename object_t::key_type &key) const
access specified object element with bounds checking
Definition: json.hpp:3179
const_iterator operator+(difference_type i)
add to iterator
Definition: json.hpp:6792
a mutable random access iterator for the basic_json class
Definition: json.hpp:6907
static basic_json parse(std::istream &&i, parser_callback_t cb=nullptr)
deserialize from stream
Definition: json.hpp:5751
const_iterator operator++(int)
post-increment (it++)
Definition: json.hpp:6600
constexpr bool is_number_integer() const noexcept
return whether value is an integer number
Definition: json.hpp:2293
ObjectType< StringType, basic_json, std::less< StringType >, AllocatorType< std::pair< const StringType, basic_json >>> object_t
a type for an object
Definition: json.hpp:348
STL namespace.
NumberUnsignedType number_unsigned_t
a type for a number (unsigned)
Definition: json.hpp:611
typename std::allocator_traits< allocator_type >::const_pointer const_pointer
the type of an element const pointer
Definition: json.hpp:231
basic_json(const number_integer_t val) noexcept
create an integer number (explicit)
Definition: json.hpp:1279
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:1645
static iteration_proxy< const_iterator > iterator_wrapper(const_reference cont)
wrapper to access iterator member functions in range-based for
Definition: json.hpp:4395
typename basic_json::value_type value_type
the type of the values when the iterator is dereferenced
Definition: json.hpp:6370
json_reverse_iterator(const typename base_iterator::iterator_type &it) noexcept
create reverse iterator from iterator
Definition: json.hpp:7057
PointerType get_ptr() noexcept
get a pointer value (implicit)
Definition: json.hpp:2893
const_iterator cbegin() const noexcept
returns a const iterator to the first element
Definition: json.hpp:4162
reference back()
access the last element
Definition: json.hpp:3685
const value_type & const_reference
the type of an element const reference
Definition: json.hpp:218
typename basic_json::const_pointer pointer
defines a pointer to the type iterated over (value_type)
Definition: json.hpp:6374
void push_back(const typename object_t::value_type &val)
add an object to an object
Definition: json.hpp:4794
bool empty() const noexcept
checks whether the container is empty
Definition: json.hpp:4443
void push_back(std::initializer_list< basic_json > init)
add an object to an object
Definition: json.hpp:4849
json_pointer(const std::string &s="")
create JSON pointer
Definition: json.hpp:8383
static basic_json parse(const string_t &s, parser_callback_t cb=nullptr)
deserialize from string
Definition: json.hpp:5714
const_reference operator[](T *(&key)[n]) const
read-only access specified object element
Definition: json.hpp:3439
iterator insert(const_iterator pos, const_iterator first, const_iterator last)
inserts elements
Definition: json.hpp:5003
constexpr const PointerType get_ptr() const noexcept
get a pointer value (implicit)
Definition: json.hpp:2908
basic_json(std::nullptr_t) noexcept
create a null object (explicitly)
Definition: json.hpp:1019
constexpr bool is_number_float() const noexcept
return whether value is a floating-point number
Definition: json.hpp:2349
basic_json(InputIT first, InputIT last)
construct a JSON container given an iterator range
Definition: json.hpp:1755
reference operator[](difference_type n) const
access to successor
Definition: json.hpp:7018
static allocator_type get_allocator()
returns the allocator associated with the container
Definition: json.hpp:248
const_reference operator[](const typename object_t::key_type &key) const
read-only access specified object element
Definition: json.hpp:3361
const_reference operator[](T *key) const
read-only access specified object element
Definition: json.hpp:3521
json_reverse_iterator operator+(difference_type i) const
add to iterator
Definition: json.hpp:7100
std::size_t size_type
a type to represent container sizes
Definition: json.hpp:223
object_t::key_type key() const
return the key of an object iterator
Definition: json.hpp:7128
const_iterator(const iterator &other) noexcept
copy constructor given a nonconst iterator
Definition: json.hpp:6412
basic_json(const CompatibleArrayType &val)
create an array (implicit)
Definition: json.hpp:1144
const_reference at(size_type idx) const
access specified array element with bounds checking
Definition: json.hpp:3083
basic_json(size_type cnt, const basic_json &val)
construct an array with count copies of given value
Definition: json.hpp:1709
std::reverse_iterator< Base > base_iterator
shortcut to the reverse iterator adaptor
Definition: json.hpp:7052
iterator insert(const_iterator pos, std::initializer_list< basic_json > ilist)
inserts elements
Definition: json.hpp:5062
typename std::allocator_traits< allocator_type >::pointer pointer
the type of an element pointer
Definition: json.hpp:229
iterator insert(const_iterator pos, const basic_json &val)
inserts element
Definition: json.hpp:4894
friend bool operator>=(const_reference lhs, const_reference rhs) noexcept
comparison: greater than or equal
Definition: json.hpp:5615
friend bool operator<(const_reference lhs, const_reference rhs) noexcept
comparison: less than
Definition: json.hpp:5470
iterator & operator++()
pre-increment (++it)
Definition: json.hpp:6960
bool operator<(const const_iterator &other) const
comparison: smaller
Definition: json.hpp:6710
iterator operator++(int)
post-increment (it++)
Definition: json.hpp:6952
const_reverse_iterator rbegin() const noexcept
returns a const reverse iterator to the last element
Definition: json.hpp:4271
basic_json(basic_json &&other) noexcept
move constructor
Definition: json.hpp:1968
const_iterator operator--(int)
post-decrement (it–)
Definition: json.hpp:6637
reference at(const typename object_t::key_type &key)
access specified object element with bounds checking
Definition: json.hpp:3131
object (unordered set of name/value pairs)
~basic_json()
destructor
Definition: json.hpp:2028
iterator operator--(int)
post-decrement (it–)
Definition: json.hpp:6967
iterator operator-(difference_type i)
subtract from iterator
Definition: json.hpp:7004
const_iterator & operator--()
pre-decrement (–it)
Definition: json.hpp:6645
string_t dump(const int indent=-1) const
serialization
Definition: json.hpp:2097
basic_json value_type
the type of elements in a basic_json container
Definition: json.hpp:213
std::function< bool(int depth, parse_event_t event, basic_json &parsed)> parser_callback_t
per-element parser callback type
Definition: json.hpp:918
AllocatorType< basic_json > allocator_type
the allocator type
Definition: json.hpp:226
StringType string_t
a type for a string
Definition: json.hpp:441
reference operator+=(const basic_json &val)
add an object to an array
Definition: json.hpp:4768
reference operator+=(std::initializer_list< basic_json > init)
add an object to an object
Definition: json.hpp:4866
difference_type operator-(const const_iterator &other) const
return difference
Definition: json.hpp:6808
value_type & reference
the type of an element reference
Definition: json.hpp:216
friend std::ostream & operator>>(const basic_json &j, std::ostream &o)
serialize to stream
Definition: json.hpp:5675
size_type size() const noexcept
returns the number of elements
Definition: json.hpp:4507
difference_type operator-(const iterator &other) const
return difference
Definition: json.hpp:7012
iterator(const iterator &other) noexcept
copy constructor
Definition: json.hpp:6923
namespace for Niels Lohmann
Definition: json.hpp:67
typename basic_json::difference_type difference_type
a type to represent differences between iterators
Definition: json.hpp:6372
constexpr bool is_string() const noexcept
return whether value is a string
Definition: json.hpp:2415
void swap(string_t &other)
exchanges the values
Definition: json.hpp:5199
basic_json(const CompatibleNumberIntegerType val) noexcept
create an integer number (implicit)
Definition: json.hpp:1345
const_reference front() const
access the first element
Definition: json.hpp:3651
bool operator>(const const_iterator &other) const
comparison: greater than
Definition: json.hpp:6746
pointer operator->() const
dereference the iterator
Definition: json.hpp:6565
NumberFloatType number_float_t
a type for a number (floating-point)
Definition: json.hpp:679
value_t
the JSON type enumeration
Definition: json.hpp:698
reverse_iterator rbegin() noexcept
returns an iterator to the reverse-beginning
Definition: json.hpp:4263
std::ptrdiff_t difference_type
a type to represent differences between iterators
Definition: json.hpp:221
ValueType get() const
get a value (explicit)
Definition: json.hpp:2809
void swap(array_t &other)
exchanges the values
Definition: json.hpp:5131
InteratorType erase(InteratorType first, InteratorType last)
remove elements given an iterator range
Definition: json.hpp:3861
ValueType value(const typename object_t::key_type &key, ValueType default_value) const
access specified object element with default value
Definition: json.hpp:3588
typename Base::reference reference
the reference type for the pointed-to element
Definition: json.hpp:7054
const_reference back() const
access the last element
Definition: json.hpp:3695
void push_back(basic_json &&val)
add an object to an array
Definition: json.hpp:4708
array (ordered collection of values)
json_reverse_iterator & operator++()
pre-increment (++it)
Definition: json.hpp:7073
static basic_json parse(std::istream &i, parser_callback_t cb=nullptr)
deserialize from stream
Definition: json.hpp:5743
friend bool operator==(const_reference lhs, const_reference rhs) noexcept
comparison: equal
Definition: json.hpp:5280
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:3614
ReferenceType get_ref() const
get a reference value (implicit)
Definition: json.hpp:2959
basic_json(const CompatibleNumberUnsignedType val) noexcept
create an unsigned number (implicit)
Definition: json.hpp:1404
constexpr bool is_boolean() const noexcept
return whether value is a boolean
Definition: json.hpp:2234
reference operator*() const
return a reference to the value pointed to by the iterator
Definition: json.hpp:6525
const_reverse_iterator crbegin() const noexcept
returns a const reverse iterator to the last element
Definition: json.hpp:4337
friend bool operator<(const value_t lhs, const value_t rhs) noexcept
comparison operator for JSON types
Definition: json.hpp:5233
basic_json(const number_float_t val) noexcept
create a floating-point number (explicit)
Definition: json.hpp:1433
friend bool operator!=(const_reference v, std::nullptr_t) noexcept
comparison: not equal
Definition: json.hpp:5432
iterator operator+(difference_type i)
add to iterator
Definition: json.hpp:6996
basic_json(const CompatibleNumberFloatType val) noexcept
create an floating-point number (implicit)
Definition: json.hpp:1480
bool operator<=(const const_iterator &other) const
comparison: less than or equal
Definition: json.hpp:6740
InteratorType erase(InteratorType pos)
remove element given an iterator
Definition: json.hpp:3753
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:1553
iterator(pointer object) noexcept
constructor for a given JSON instance
Definition: json.hpp:6918
friend bool operator!=(std::nullptr_t, const_reference v) noexcept
comparison: not equal
Definition: json.hpp:5441
const_iterator & operator++()
pre-increment (++it)
Definition: json.hpp:6608
pointer operator->() const
dereference the iterator
Definition: json.hpp:6946
constexpr bool is_number() const noexcept
return whether value is a number
Definition: json.hpp:2264
reference value() const
return the value of an iterator
Definition: json.hpp:6883
const_iterator begin() const noexcept
returns a const iterator to the first element
Definition: json.hpp:4132
std::bidirectional_iterator_tag iterator_category
the category of the iterator
Definition: json.hpp:6378
basic_json(boolean_t val) noexcept
create a boolean (explicit)
Definition: json.hpp:1246
iterator end() noexcept
returns an iterator to one past the last element
Definition: json.hpp:4193
reverse_iterator rend() noexcept
returns an iterator to the reverse-end
Definition: json.hpp:4300
difference_type operator-(const json_reverse_iterator &other) const
return difference
Definition: json.hpp:7116
const_iterator find(typename object_t::key_type key) const
find an element in a JSON object
Definition: json.hpp:4050
iterator begin() noexcept
returns an iterator to the first element
Definition: json.hpp:4122
const_iterator cend() const noexcept
returns a const iterator to one past the last element
Definition: json.hpp:4233
basic_json(const CompatibleObjectType &val)
create an object (implicit)
Definition: json.hpp:1077
friend bool operator>(const_reference lhs, const_reference rhs) noexcept
comparison: greater than
Definition: json.hpp:5593
bool operator>=(const const_iterator &other) const
comparison: greater than or equal
Definition: json.hpp:6752
size_type erase(const typename object_t::key_type &key)
remove element from a JSON object given a key
Definition: json.hpp:3948
reference operator[](const typename object_t::key_type &key)
access specified object element
Definition: json.hpp:3313
object_t::key_type key() const
return the key of an object iterator
Definition: json.hpp:6868
reference operator+=(basic_json &&val)
add an object to an array
Definition: json.hpp:4734
const_iterator & operator=(const_iterator other) noexcept(std::is_nothrow_move_constructible< pointer >::value andstd::is_nothrow_move_assignable< pointer >::value andstd::is_nothrow_move_constructible< internal_iterator >::value andstd::is_nothrow_move_assignable< internal_iterator >::value)
copy assignment
Definition: json.hpp:6445
reference operator[](difference_type n) const
access to successor
Definition: json.hpp:6832
a const random access iterator for the basic_json class
Definition: json.hpp:6363
a template for a reverse iterator class
Definition: json.hpp:202
basic_json(std::istream &i, parser_callback_t cb=nullptr)
construct a JSON value given an input stream
Definition: json.hpp:1862
typename basic_json::const_reference reference
defines a reference to the type iterated over (value_type)
Definition: json.hpp:6376
json_reverse_iterator operator++(int)
post-increment (it++)
Definition: json.hpp:7067
friend bool operator==(const_reference v, std::nullptr_t) noexcept
comparison: equal
Definition: json.hpp:5379
reference operator[](size_type idx)
access specified array element
Definition: json.hpp:3226
bool operator!=(const const_iterator &other) const
comparison: not equal
Definition: json.hpp:6704
json_reverse_iterator & operator+=(difference_type i)
add to iterator
Definition: json.hpp:7093
reference at(size_type idx)
access specified array element with bounds checking
Definition: json.hpp:3039
static iteration_proxy< iterator > iterator_wrapper(reference cont)
wrapper to access iterator member functions in range-based for
Definition: json.hpp:4387
constexpr bool is_discarded() const noexcept
return whether value is discarded
Definition: json.hpp:2442
const_reverse_iterator crend() const noexcept
returns a const reverse iterator to one before the first
Definition: json.hpp:4366
iterator & operator-=(difference_type i)
subtract from iterator
Definition: json.hpp:6989
basic_json(const object_t &val)
create an object (explicit)
Definition: json.hpp:1042
basic_json(const number_unsigned_t val) noexcept
create an unsigned integer number (explicit)
Definition: json.hpp:1373
friend std::istream & operator<<(basic_json &j, std::istream &i)
deserialize from stream
Definition: json.hpp:5779
json_reverse_iterator(const base_iterator &it) noexcept
create reverse iterator from base class
Definition: json.hpp:7062
friend std::ostream & operator<<(std::ostream &o, const basic_json &j)
serialize to stream
Definition: json.hpp:5652
const_iterator(const const_iterator &other) noexcept
copy constructor
Definition: json.hpp:6440
iterator & operator--()
pre-decrement (–it)
Definition: json.hpp:6975
iterator insert(const_iterator pos, basic_json &&val)
inserts element
Definition: json.hpp:4921
ReferenceType get_ref()
get a reference value (implicit)
Definition: json.hpp:2944
const_iterator & operator-=(difference_type i)
subtract from iterator
Definition: json.hpp:6786
basic_json(const CompatibleStringType &val)
create a string (implicit)
Definition: json.hpp:1228
basic_json(const basic_json &other)
copy constructor
Definition: json.hpp:1893
reference operator[](T *key)
access specified object element
Definition: json.hpp:3472
parse_event_t
JSON callback events.
Definition: json.hpp:853