JSON for Modern C++  2.0.0
json.hpp
1 /*
2  __ _____ _____ _____
3  __| | __| | | | JSON for Modern C++
4 | | |__ | | | | | | version 2.0.0
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 
2101  if (indent >= 0)
2102  {
2103  dump(ss, true, static_cast<unsigned int>(indent));
2104  }
2105  else
2106  {
2107  dump(ss, false, 0);
2108  }
2109 
2110  return ss.str();
2111  }
2112 
2131  constexpr value_t type() const noexcept
2132  {
2133  return m_type;
2134  }
2135 
2161  constexpr bool is_primitive() const noexcept
2162  {
2163  return is_null() or is_string() or is_boolean() or is_number();
2164  }
2165 
2188  constexpr bool is_structured() const noexcept
2189  {
2190  return is_array() or is_object();
2191  }
2192 
2210  constexpr bool is_null() const noexcept
2211  {
2212  return m_type == value_t::null;
2213  }
2214 
2232  constexpr bool is_boolean() const noexcept
2233  {
2234  return m_type == value_t::boolean;
2235  }
2236 
2262  constexpr bool is_number() const noexcept
2263  {
2264  return is_number_integer() or is_number_float();
2265  }
2266 
2291  constexpr bool is_number_integer() const noexcept
2292  {
2293  return m_type == value_t::number_integer or m_type == value_t::number_unsigned;
2294  }
2295 
2319  constexpr bool is_number_unsigned() const noexcept
2320  {
2321  return m_type == value_t::number_unsigned;
2322  }
2323 
2347  constexpr bool is_number_float() const noexcept
2348  {
2349  return m_type == value_t::number_float;
2350  }
2351 
2369  constexpr bool is_object() const noexcept
2370  {
2371  return m_type == value_t::object;
2372  }
2373 
2391  constexpr bool is_array() const noexcept
2392  {
2393  return m_type == value_t::array;
2394  }
2395 
2413  constexpr bool is_string() const noexcept
2414  {
2415  return m_type == value_t::string;
2416  }
2417 
2440  constexpr bool is_discarded() const noexcept
2441  {
2442  return m_type == value_t::discarded;
2443  }
2444 
2463  constexpr operator value_t() const noexcept
2464  {
2465  return m_type;
2466  }
2467 
2469 
2470  private:
2472  // value access //
2474 
2476  template <class T, typename
2477  std::enable_if<
2478  std::is_convertible<typename object_t::key_type, typename T::key_type>::value and
2479  std::is_convertible<basic_json_t, typename T::mapped_type>::value
2480  , int>::type = 0>
2481  T get_impl(T*) const
2482  {
2483  if (is_object())
2484  {
2485  assert(m_value.object != nullptr);
2486  return T(m_value.object->begin(), m_value.object->end());
2487  }
2488  else
2489  {
2490  throw std::domain_error("type must be object, but is " + type_name());
2491  }
2492  }
2493 
2495  object_t get_impl(object_t*) const
2496  {
2497  if (is_object())
2498  {
2499  assert(m_value.object != nullptr);
2500  return *(m_value.object);
2501  }
2502  else
2503  {
2504  throw std::domain_error("type must be object, but is " + type_name());
2505  }
2506  }
2507 
2509  template <class T, typename
2510  std::enable_if<
2511  std::is_convertible<basic_json_t, typename T::value_type>::value and
2512  not std::is_same<basic_json_t, typename T::value_type>::value and
2513  not std::is_arithmetic<T>::value and
2514  not std::is_convertible<std::string, T>::value and
2515  not has_mapped_type<T>::value
2516  , int>::type = 0>
2517  T get_impl(T*) const
2518  {
2519  if (is_array())
2520  {
2521  T to_vector;
2522  assert(m_value.array != nullptr);
2523  std::transform(m_value.array->begin(), m_value.array->end(),
2524  std::inserter(to_vector, to_vector.end()), [](basic_json i)
2525  {
2526  return i.get<typename T::value_type>();
2527  });
2528  return to_vector;
2529  }
2530  else
2531  {
2532  throw std::domain_error("type must be array, but is " + type_name());
2533  }
2534  }
2535 
2537  template <class T, typename
2538  std::enable_if<
2539  std::is_convertible<basic_json_t, T>::value and
2540  not std::is_same<basic_json_t, T>::value
2541  , int>::type = 0>
2542  std::vector<T> get_impl(std::vector<T>*) const
2543  {
2544  if (is_array())
2545  {
2546  std::vector<T> to_vector;
2547  assert(m_value.array != nullptr);
2548  to_vector.reserve(m_value.array->size());
2549  std::transform(m_value.array->begin(), m_value.array->end(),
2550  std::inserter(to_vector, to_vector.end()), [](basic_json i)
2551  {
2552  return i.get<T>();
2553  });
2554  return to_vector;
2555  }
2556  else
2557  {
2558  throw std::domain_error("type must be array, but is " + type_name());
2559  }
2560  }
2561 
2563  template <class T, typename
2564  std::enable_if<
2565  std::is_same<basic_json, typename T::value_type>::value and
2566  not has_mapped_type<T>::value
2567  , int>::type = 0>
2568  T get_impl(T*) const
2569  {
2570  if (is_array())
2571  {
2572  assert(m_value.array != nullptr);
2573  return T(m_value.array->begin(), m_value.array->end());
2574  }
2575  else
2576  {
2577  throw std::domain_error("type must be array, but is " + type_name());
2578  }
2579  }
2580 
2582  array_t get_impl(array_t*) const
2583  {
2584  if (is_array())
2585  {
2586  assert(m_value.array != nullptr);
2587  return *(m_value.array);
2588  }
2589  else
2590  {
2591  throw std::domain_error("type must be array, but is " + type_name());
2592  }
2593  }
2594 
2596  template <typename T, typename
2597  std::enable_if<
2598  std::is_convertible<string_t, T>::value
2599  , int>::type = 0>
2600  T get_impl(T*) const
2601  {
2602  if (is_string())
2603  {
2604  assert(m_value.string != nullptr);
2605  return *m_value.string;
2606  }
2607  else
2608  {
2609  throw std::domain_error("type must be string, but is " + type_name());
2610  }
2611  }
2612 
2614  template<typename T, typename
2615  std::enable_if<
2616  std::is_arithmetic<T>::value
2617  , int>::type = 0>
2618  T get_impl(T*) const
2619  {
2620  switch (m_type)
2621  {
2622  case value_t::number_integer:
2623  {
2624  return static_cast<T>(m_value.number_integer);
2625  }
2626 
2627  case value_t::number_unsigned:
2628  {
2629  return static_cast<T>(m_value.number_unsigned);
2630  }
2631 
2632  case value_t::number_float:
2633  {
2634  return static_cast<T>(m_value.number_float);
2635  }
2636 
2637  default:
2638  {
2639  throw std::domain_error("type must be number, but is " + type_name());
2640  }
2641  }
2642  }
2643 
2645  constexpr boolean_t get_impl(boolean_t*) const
2646  {
2647  return is_boolean()
2648  ? m_value.boolean
2649  : throw std::domain_error("type must be boolean, but is " + type_name());
2650  }
2651 
2653  object_t* get_impl_ptr(object_t*) noexcept
2654  {
2655  return is_object() ? m_value.object : nullptr;
2656  }
2657 
2659  constexpr const object_t* get_impl_ptr(const object_t*) const noexcept
2660  {
2661  return is_object() ? m_value.object : nullptr;
2662  }
2663 
2665  array_t* get_impl_ptr(array_t*) noexcept
2666  {
2667  return is_array() ? m_value.array : nullptr;
2668  }
2669 
2671  constexpr const array_t* get_impl_ptr(const array_t*) const noexcept
2672  {
2673  return is_array() ? m_value.array : nullptr;
2674  }
2675 
2677  string_t* get_impl_ptr(string_t*) noexcept
2678  {
2679  return is_string() ? m_value.string : nullptr;
2680  }
2681 
2683  constexpr const string_t* get_impl_ptr(const string_t*) const noexcept
2684  {
2685  return is_string() ? m_value.string : nullptr;
2686  }
2687 
2689  boolean_t* get_impl_ptr(boolean_t*) noexcept
2690  {
2691  return is_boolean() ? &m_value.boolean : nullptr;
2692  }
2693 
2695  constexpr const boolean_t* get_impl_ptr(const boolean_t*) const noexcept
2696  {
2697  return is_boolean() ? &m_value.boolean : nullptr;
2698  }
2699 
2701  number_integer_t* get_impl_ptr(number_integer_t*) noexcept
2702  {
2703  return is_number_integer() ? &m_value.number_integer : nullptr;
2704  }
2705 
2707  constexpr const number_integer_t* get_impl_ptr(const number_integer_t*) const noexcept
2708  {
2709  return is_number_integer() ? &m_value.number_integer : nullptr;
2710  }
2711 
2713  number_unsigned_t* get_impl_ptr(number_unsigned_t*) noexcept
2714  {
2715  return is_number_unsigned() ? &m_value.number_unsigned : nullptr;
2716  }
2717 
2719  constexpr const number_unsigned_t* get_impl_ptr(const number_unsigned_t*) const noexcept
2720  {
2721  return is_number_unsigned() ? &m_value.number_unsigned : nullptr;
2722  }
2723 
2725  number_float_t* get_impl_ptr(number_float_t*) noexcept
2726  {
2727  return is_number_float() ? &m_value.number_float : nullptr;
2728  }
2729 
2731  constexpr const number_float_t* get_impl_ptr(const number_float_t*) const noexcept
2732  {
2733  return is_number_float() ? &m_value.number_float : nullptr;
2734  }
2735 
2747  template<typename ReferenceType, typename ThisType>
2748  static ReferenceType get_ref_impl(ThisType& obj)
2749  {
2750  // delegate the call to get_ptr<>()
2751  using PointerType = typename std::add_pointer<ReferenceType>::type;
2752  auto ptr = obj.template get_ptr<PointerType>();
2753 
2754  if (ptr != nullptr)
2755  {
2756  return *ptr;
2757  }
2758  else
2759  {
2760  throw std::domain_error("incompatible ReferenceType for get_ref, actual type is " +
2761  obj.type_name());
2762  }
2763  }
2764 
2765  public:
2766 
2769 
2803  template<typename ValueType, typename
2804  std::enable_if<
2805  not std::is_pointer<ValueType>::value
2806  , int>::type = 0>
2807  ValueType get() const
2808  {
2809  return get_impl(static_cast<ValueType*>(nullptr));
2810  }
2811 
2838  template<typename PointerType, typename
2839  std::enable_if<
2840  std::is_pointer<PointerType>::value
2841  , int>::type = 0>
2842  PointerType get() noexcept
2843  {
2844  // delegate the call to get_ptr
2845  return get_ptr<PointerType>();
2846  }
2847 
2852  template<typename PointerType, typename
2853  std::enable_if<
2854  std::is_pointer<PointerType>::value
2855  , int>::type = 0>
2856  constexpr const PointerType get() const noexcept
2857  {
2858  // delegate the call to get_ptr
2859  return get_ptr<PointerType>();
2860  }
2861 
2887  template<typename PointerType, typename
2888  std::enable_if<
2889  std::is_pointer<PointerType>::value
2890  , int>::type = 0>
2891  PointerType get_ptr() noexcept
2892  {
2893  // delegate the call to get_impl_ptr<>()
2894  return get_impl_ptr(static_cast<PointerType>(nullptr));
2895  }
2896 
2901  template<typename PointerType, typename
2902  std::enable_if<
2903  std::is_pointer<PointerType>::value
2904  and std::is_const<typename std::remove_pointer<PointerType>::type>::value
2905  , int>::type = 0>
2906  constexpr const PointerType get_ptr() const noexcept
2907  {
2908  // delegate the call to get_impl_ptr<>() const
2909  return get_impl_ptr(static_cast<const PointerType>(nullptr));
2910  }
2911 
2938  template<typename ReferenceType, typename
2939  std::enable_if<
2940  std::is_reference<ReferenceType>::value
2941  , int>::type = 0>
2942  ReferenceType get_ref()
2943  {
2944  // delegate call to get_ref_impl
2945  return get_ref_impl<ReferenceType>(*this);
2946  }
2947 
2952  template<typename ReferenceType, typename
2953  std::enable_if<
2954  std::is_reference<ReferenceType>::value
2955  and std::is_const<typename std::remove_reference<ReferenceType>::type>::value
2956  , int>::type = 0>
2957  ReferenceType get_ref() const
2958  {
2959  // delegate call to get_ref_impl
2960  return get_ref_impl<ReferenceType>(*this);
2961  }
2962 
2991  template < typename ValueType, typename
2992  std::enable_if <
2993  not std::is_pointer<ValueType>::value
2994  and not std::is_same<ValueType, typename string_t::value_type>::value
2995 #ifndef _MSC_VER // Fix for issue #167 operator<< abiguity under VS2015
2996  and not std::is_same<ValueType, std::initializer_list<typename string_t::value_type>>::value
2997 #endif
2998  , int >::type = 0 >
2999  operator ValueType() const
3000  {
3001  // delegate the call to get<>() const
3002  return get<ValueType>();
3003  }
3004 
3006 
3007 
3009  // element access //
3011 
3014 
3038  {
3039  // at only works for arrays
3040  if (is_array())
3041  {
3042  try
3043  {
3044  assert(m_value.array != nullptr);
3045  return m_value.array->at(idx);
3046  }
3047  catch (std::out_of_range&)
3048  {
3049  // create better exception explanation
3050  throw std::out_of_range("array index " + std::to_string(idx) + " is out of range");
3051  }
3052  }
3053  else
3054  {
3055  throw std::domain_error("cannot use at() with " + type_name());
3056  }
3057  }
3058 
3082  {
3083  // at only works for arrays
3084  if (is_array())
3085  {
3086  try
3087  {
3088  assert(m_value.array != nullptr);
3089  return m_value.array->at(idx);
3090  }
3091  catch (std::out_of_range&)
3092  {
3093  // create better exception explanation
3094  throw std::out_of_range("array index " + std::to_string(idx) + " is out of range");
3095  }
3096  }
3097  else
3098  {
3099  throw std::domain_error("cannot use at() with " + type_name());
3100  }
3101  }
3102 
3129  reference at(const typename object_t::key_type& key)
3130  {
3131  // at only works for objects
3132  if (is_object())
3133  {
3134  try
3135  {
3136  assert(m_value.object != nullptr);
3137  return m_value.object->at(key);
3138  }
3139  catch (std::out_of_range&)
3140  {
3141  // create better exception explanation
3142  throw std::out_of_range("key '" + key + "' not found");
3143  }
3144  }
3145  else
3146  {
3147  throw std::domain_error("cannot use at() with " + type_name());
3148  }
3149  }
3150 
3177  const_reference at(const typename object_t::key_type& key) const
3178  {
3179  // at only works for objects
3180  if (is_object())
3181  {
3182  try
3183  {
3184  assert(m_value.object != nullptr);
3185  return m_value.object->at(key);
3186  }
3187  catch (std::out_of_range&)
3188  {
3189  // create better exception explanation
3190  throw std::out_of_range("key '" + key + "' not found");
3191  }
3192  }
3193  else
3194  {
3195  throw std::domain_error("cannot use at() with " + type_name());
3196  }
3197  }
3198 
3225  {
3226  // implicitly convert null value to an empty array
3227  if (is_null())
3228  {
3229  m_type = value_t::array;
3230  m_value.array = create<array_t>();
3231  }
3232 
3233  // operator[] only works for arrays
3234  if (is_array())
3235  {
3236  // fill up array with null values until given idx is reached
3237  assert(m_value.array != nullptr);
3238  for (size_t i = m_value.array->size(); i <= idx; ++i)
3239  {
3240  m_value.array->push_back(basic_json());
3241  }
3242 
3243  return m_value.array->operator[](idx);
3244  }
3245  else
3246  {
3247  throw std::domain_error("cannot use operator[] with " + type_name());
3248  }
3249  }
3250 
3271  {
3272  // const operator[] only works for arrays
3273  if (is_array())
3274  {
3275  assert(m_value.array != nullptr);
3276  return m_value.array->operator[](idx);
3277  }
3278  else
3279  {
3280  throw std::domain_error("cannot use operator[] with " + type_name());
3281  }
3282  }
3283 
3311  reference operator[](const typename object_t::key_type& key)
3312  {
3313  // implicitly convert null value to an empty object
3314  if (is_null())
3315  {
3316  m_type = value_t::object;
3317  m_value.object = create<object_t>();
3318  }
3319 
3320  // operator[] only works for objects
3321  if (is_object())
3322  {
3323  assert(m_value.object != nullptr);
3324  return m_value.object->operator[](key);
3325  }
3326  else
3327  {
3328  throw std::domain_error("cannot use operator[] with " + type_name());
3329  }
3330  }
3331 
3359  const_reference operator[](const typename object_t::key_type& key) const
3360  {
3361  // const operator[] only works for objects
3362  if (is_object())
3363  {
3364  assert(m_value.object != nullptr);
3365  assert(m_value.object->find(key) != m_value.object->end());
3366  return m_value.object->find(key)->second;
3367  }
3368  else
3369  {
3370  throw std::domain_error("cannot use operator[] with " + type_name());
3371  }
3372  }
3373 
3401  template<typename T, std::size_t n>
3402  reference operator[](T * (&key)[n])
3403  {
3404  return operator[](static_cast<const T>(key));
3405  }
3406 
3436  template<typename T, std::size_t n>
3437  const_reference operator[](T * (&key)[n]) const
3438  {
3439  return operator[](static_cast<const T>(key));
3440  }
3441 
3469  template<typename T>
3471  {
3472  // implicitly convert null to object
3473  if (is_null())
3474  {
3475  m_type = value_t::object;
3476  m_value = value_t::object;
3477  }
3478 
3479  // at only works for objects
3480  if (is_object())
3481  {
3482  assert(m_value.object != nullptr);
3483  return m_value.object->operator[](key);
3484  }
3485  else
3486  {
3487  throw std::domain_error("cannot use operator[] with " + type_name());
3488  }
3489  }
3490 
3518  template<typename T>
3520  {
3521  // at only works for objects
3522  if (is_object())
3523  {
3524  assert(m_value.object != nullptr);
3525  assert(m_value.object->find(key) != m_value.object->end());
3526  return m_value.object->find(key)->second;
3527  }
3528  else
3529  {
3530  throw std::domain_error("cannot use operator[] with " + type_name());
3531  }
3532  }
3533 
3582  template <class ValueType, typename
3583  std::enable_if<
3584  std::is_convertible<basic_json_t, ValueType>::value
3585  , int>::type = 0>
3586  ValueType value(const typename object_t::key_type& key, ValueType default_value) const
3587  {
3588  // at only works for objects
3589  if (is_object())
3590  {
3591  // if key is found, return value and given default value otherwise
3592  const auto it = find(key);
3593  if (it != end())
3594  {
3595  return *it;
3596  }
3597  else
3598  {
3599  return default_value;
3600  }
3601  }
3602  else
3603  {
3604  throw std::domain_error("cannot use value() with " + type_name());
3605  }
3606  }
3607 
3612  string_t value(const typename object_t::key_type& key, const char* default_value) const
3613  {
3614  return value(key, string_t(default_value));
3615  }
3616 
3642  {
3643  return *begin();
3644  }
3645 
3650  {
3651  return *cbegin();
3652  }
3653 
3684  {
3685  auto tmp = end();
3686  --tmp;
3687  return *tmp;
3688  }
3689 
3694  {
3695  auto tmp = cend();
3696  --tmp;
3697  return *tmp;
3698  }
3699 
3745  template <class InteratorType, typename
3746  std::enable_if<
3747  std::is_same<InteratorType, typename basic_json_t::iterator>::value or
3748  std::is_same<InteratorType, typename basic_json_t::const_iterator>::value
3749  , int>::type
3750  = 0>
3751  InteratorType erase(InteratorType pos)
3752  {
3753  // make sure iterator fits the current value
3754  if (this != pos.m_object)
3755  {
3756  throw std::domain_error("iterator does not fit current value");
3757  }
3758 
3759  InteratorType result = end();
3760 
3761  switch (m_type)
3762  {
3763  case value_t::boolean:
3764  case value_t::number_float:
3765  case value_t::number_integer:
3766  case value_t::number_unsigned:
3767  case value_t::string:
3768  {
3769  if (not pos.m_it.primitive_iterator.is_begin())
3770  {
3771  throw std::out_of_range("iterator out of range");
3772  }
3773 
3774  if (is_string())
3775  {
3776  delete m_value.string;
3777  m_value.string = nullptr;
3778  }
3779 
3780  m_type = value_t::null;
3781  break;
3782  }
3783 
3784  case value_t::object:
3785  {
3786  assert(m_value.object != nullptr);
3787  result.m_it.object_iterator = m_value.object->erase(pos.m_it.object_iterator);
3788  break;
3789  }
3790 
3791  case value_t::array:
3792  {
3793  assert(m_value.array != nullptr);
3794  result.m_it.array_iterator = m_value.array->erase(pos.m_it.array_iterator);
3795  break;
3796  }
3797 
3798  default:
3799  {
3800  throw std::domain_error("cannot use erase() with " + type_name());
3801  }
3802  }
3803 
3804  return result;
3805  }
3806 
3853  template <class InteratorType, typename
3854  std::enable_if<
3855  std::is_same<InteratorType, typename basic_json_t::iterator>::value or
3856  std::is_same<InteratorType, typename basic_json_t::const_iterator>::value
3857  , int>::type
3858  = 0>
3859  InteratorType erase(InteratorType first, InteratorType last)
3860  {
3861  // make sure iterator fits the current value
3862  if (this != first.m_object or this != last.m_object)
3863  {
3864  throw std::domain_error("iterators do not fit current value");
3865  }
3866 
3867  InteratorType result = end();
3868 
3869  switch (m_type)
3870  {
3871  case value_t::boolean:
3872  case value_t::number_float:
3873  case value_t::number_integer:
3874  case value_t::number_unsigned:
3875  case value_t::string:
3876  {
3877  if (not first.m_it.primitive_iterator.is_begin() or not last.m_it.primitive_iterator.is_end())
3878  {
3879  throw std::out_of_range("iterators out of range");
3880  }
3881 
3882  if (is_string())
3883  {
3884  delete m_value.string;
3885  m_value.string = nullptr;
3886  }
3887 
3888  m_type = value_t::null;
3889  break;
3890  }
3891 
3892  case value_t::object:
3893  {
3894  assert(m_value.object != nullptr);
3895  result.m_it.object_iterator = m_value.object->erase(first.m_it.object_iterator,
3896  last.m_it.object_iterator);
3897  break;
3898  }
3899 
3900  case value_t::array:
3901  {
3902  assert(m_value.array != nullptr);
3903  result.m_it.array_iterator = m_value.array->erase(first.m_it.array_iterator,
3904  last.m_it.array_iterator);
3905  break;
3906  }
3907 
3908  default:
3909  {
3910  throw std::domain_error("cannot use erase() with " + type_name());
3911  }
3912  }
3913 
3914  return result;
3915  }
3916 
3946  size_type erase(const typename object_t::key_type& key)
3947  {
3948  // this erase only works for objects
3949  if (is_object())
3950  {
3951  assert(m_value.object != nullptr);
3952  return m_value.object->erase(key);
3953  }
3954  else
3955  {
3956  throw std::domain_error("cannot use erase() with " + type_name());
3957  }
3958  }
3959 
3984  void erase(const size_type idx)
3985  {
3986  // this erase only works for arrays
3987  if (is_array())
3988  {
3989  if (idx >= size())
3990  {
3991  throw std::out_of_range("array index " + std::to_string(idx) + " is out of range");
3992  }
3993 
3994  assert(m_value.array != nullptr);
3995  m_value.array->erase(m_value.array->begin() + static_cast<difference_type>(idx));
3996  }
3997  else
3998  {
3999  throw std::domain_error("cannot use erase() with " + type_name());
4000  }
4001  }
4002 
4004 
4005 
4007  // lookup //
4009 
4012 
4031  iterator find(typename object_t::key_type key)
4032  {
4033  auto result = end();
4034 
4035  if (is_object())
4036  {
4037  assert(m_value.object != nullptr);
4038  result.m_it.object_iterator = m_value.object->find(key);
4039  }
4040 
4041  return result;
4042  }
4043 
4048  const_iterator find(typename object_t::key_type key) const
4049  {
4050  auto result = cend();
4051 
4052  if (is_object())
4053  {
4054  assert(m_value.object != nullptr);
4055  result.m_it.object_iterator = m_value.object->find(key);
4056  }
4057 
4058  return result;
4059  }
4060 
4079  size_type count(typename object_t::key_type key) const
4080  {
4081  // return 0 for all nonobject types
4082  assert(not is_object() or m_value.object != nullptr);
4083  return is_object() ? m_value.object->count(key) : 0;
4084  }
4085 
4087 
4088 
4090  // iterators //
4092 
4095 
4120  iterator begin() noexcept
4121  {
4122  iterator result(this);
4123  result.set_begin();
4124  return result;
4125  }
4126 
4130  const_iterator begin() const noexcept
4131  {
4132  return cbegin();
4133  }
4134 
4160  const_iterator cbegin() const noexcept
4161  {
4162  const_iterator result(this);
4163  result.set_begin();
4164  return result;
4165  }
4166 
4191  iterator end() noexcept
4192  {
4193  iterator result(this);
4194  result.set_end();
4195  return result;
4196  }
4197 
4201  const_iterator end() const noexcept
4202  {
4203  return cend();
4204  }
4205 
4231  const_iterator cend() const noexcept
4232  {
4233  const_iterator result(this);
4234  result.set_end();
4235  return result;
4236  }
4237 
4262  {
4263  return reverse_iterator(end());
4264  }
4265 
4270  {
4271  return crbegin();
4272  }
4273 
4299  {
4300  return reverse_iterator(begin());
4301  }
4302 
4306  const_reverse_iterator rend() const noexcept
4307  {
4308  return crend();
4309  }
4310 
4336  {
4337  return const_reverse_iterator(cend());
4338  }
4339 
4365  {
4366  return const_reverse_iterator(cbegin());
4367  }
4368 
4369  private:
4370  // forward declaration
4371  template<typename IteratorType> class iteration_proxy;
4372 
4373  public:
4385  static iteration_proxy<iterator> iterator_wrapper(reference cont)
4386  {
4387  return iteration_proxy<iterator>(cont);
4388  }
4389 
4393  static iteration_proxy<const_iterator> iterator_wrapper(const_reference cont)
4394  {
4395  return iteration_proxy<const_iterator>(cont);
4396  }
4397 
4399 
4400 
4402  // capacity //
4404 
4407 
4441  bool empty() const noexcept
4442  {
4443  switch (m_type)
4444  {
4445  case value_t::null:
4446  {
4447  // null values are empty
4448  return true;
4449  }
4450 
4451  case value_t::array:
4452  {
4453  assert(m_value.array != nullptr);
4454  return m_value.array->empty();
4455  }
4456 
4457  case value_t::object:
4458  {
4459  assert(m_value.object != nullptr);
4460  return m_value.object->empty();
4461  }
4462 
4463  default:
4464  {
4465  // all other types are nonempty
4466  return false;
4467  }
4468  }
4469  }
4470 
4505  size_type size() const noexcept
4506  {
4507  switch (m_type)
4508  {
4509  case value_t::null:
4510  {
4511  // null values are empty
4512  return 0;
4513  }
4514 
4515  case value_t::array:
4516  {
4517  assert(m_value.array != nullptr);
4518  return m_value.array->size();
4519  }
4520 
4521  case value_t::object:
4522  {
4523  assert(m_value.object != nullptr);
4524  return m_value.object->size();
4525  }
4526 
4527  default:
4528  {
4529  // all other types have size 1
4530  return 1;
4531  }
4532  }
4533  }
4534 
4571  size_type max_size() const noexcept
4572  {
4573  switch (m_type)
4574  {
4575  case value_t::array:
4576  {
4577  assert(m_value.array != nullptr);
4578  return m_value.array->max_size();
4579  }
4580 
4581  case value_t::object:
4582  {
4583  assert(m_value.object != nullptr);
4584  return m_value.object->max_size();
4585  }
4586 
4587  default:
4588  {
4589  // all other types have max_size() == size()
4590  return size();
4591  }
4592  }
4593  }
4594 
4596 
4597 
4599  // modifiers //
4601 
4604 
4630  void clear() noexcept
4631  {
4632  switch (m_type)
4633  {
4634  case value_t::number_integer:
4635  {
4636  m_value.number_integer = 0;
4637  break;
4638  }
4639 
4640  case value_t::number_unsigned:
4641  {
4642  m_value.number_unsigned = 0;
4643  break;
4644  }
4645 
4646  case value_t::number_float:
4647  {
4648  m_value.number_float = 0.0;
4649  break;
4650  }
4651 
4652  case value_t::boolean:
4653  {
4654  m_value.boolean = false;
4655  break;
4656  }
4657 
4658  case value_t::string:
4659  {
4660  assert(m_value.string != nullptr);
4661  m_value.string->clear();
4662  break;
4663  }
4664 
4665  case value_t::array:
4666  {
4667  assert(m_value.array != nullptr);
4668  m_value.array->clear();
4669  break;
4670  }
4671 
4672  case value_t::object:
4673  {
4674  assert(m_value.object != nullptr);
4675  m_value.object->clear();
4676  break;
4677  }
4678 
4679  default:
4680  {
4681  break;
4682  }
4683  }
4684  }
4685 
4706  void push_back(basic_json&& val)
4707  {
4708  // push_back only works for null objects or arrays
4709  if (not(is_null() or is_array()))
4710  {
4711  throw std::domain_error("cannot use push_back() with " + type_name());
4712  }
4713 
4714  // transform null object into an array
4715  if (is_null())
4716  {
4717  m_type = value_t::array;
4718  m_value = value_t::array;
4719  }
4720 
4721  // add element to array (move semantics)
4722  assert(m_value.array != nullptr);
4723  m_value.array->push_back(std::move(val));
4724  // invalidate object
4725  val.m_type = value_t::null;
4726  }
4727 
4732  reference operator+=(basic_json&& val)
4733  {
4734  push_back(std::move(val));
4735  return *this;
4736  }
4737 
4742  void push_back(const basic_json& val)
4743  {
4744  // push_back only works for null objects or arrays
4745  if (not(is_null() or is_array()))
4746  {
4747  throw std::domain_error("cannot use push_back() with " + type_name());
4748  }
4749 
4750  // transform null object into an array
4751  if (is_null())
4752  {
4753  m_type = value_t::array;
4754  m_value = value_t::array;
4755  }
4756 
4757  // add element to array
4758  assert(m_value.array != nullptr);
4759  m_value.array->push_back(val);
4760  }
4761 
4766  reference operator+=(const basic_json& val)
4767  {
4768  push_back(val);
4769  return *this;
4770  }
4771 
4792  void push_back(const typename object_t::value_type& val)
4793  {
4794  // push_back only works for null objects or objects
4795  if (not(is_null() or is_object()))
4796  {
4797  throw std::domain_error("cannot use push_back() with " + type_name());
4798  }
4799 
4800  // transform null object into an object
4801  if (is_null())
4802  {
4803  m_type = value_t::object;
4804  m_value = value_t::object;
4805  }
4806 
4807  // add element to array
4808  assert(m_value.object != nullptr);
4809  m_value.object->insert(val);
4810  }
4811 
4816  reference operator+=(const typename object_t::value_type& val)
4817  {
4818  push_back(val);
4819  return *this;
4820  }
4821 
4847  void push_back(std::initializer_list<basic_json> init)
4848  {
4849  if (is_object() and init.size() == 2 and init.begin()->is_string())
4850  {
4851  const string_t key = *init.begin();
4852  push_back(typename object_t::value_type(key, *(init.begin() + 1)));
4853  }
4854  else
4855  {
4856  push_back(basic_json(init));
4857  }
4858  }
4859 
4864  reference operator+=(std::initializer_list<basic_json> init)
4865  {
4866  push_back(init);
4867  return *this;
4868  }
4869 
4892  iterator insert(const_iterator pos, const basic_json& val)
4893  {
4894  // insert only works for arrays
4895  if (is_array())
4896  {
4897  // check if iterator pos fits to this JSON value
4898  if (pos.m_object != this)
4899  {
4900  throw std::domain_error("iterator does not fit current value");
4901  }
4902 
4903  // insert to array and return iterator
4904  iterator result(this);
4905  assert(m_value.array != nullptr);
4906  result.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator, val);
4907  return result;
4908  }
4909  else
4910  {
4911  throw std::domain_error("cannot use insert() with " + type_name());
4912  }
4913  }
4914 
4919  iterator insert(const_iterator pos, basic_json&& val)
4920  {
4921  return insert(pos, val);
4922  }
4923 
4948  iterator insert(const_iterator pos, size_type cnt, const basic_json& val)
4949  {
4950  // insert only works for arrays
4951  if (is_array())
4952  {
4953  // check if iterator pos fits to this JSON value
4954  if (pos.m_object != this)
4955  {
4956  throw std::domain_error("iterator does not fit current value");
4957  }
4958 
4959  // insert to array and return iterator
4960  iterator result(this);
4961  assert(m_value.array != nullptr);
4962  result.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator, cnt, val);
4963  return result;
4964  }
4965  else
4966  {
4967  throw std::domain_error("cannot use insert() with " + type_name());
4968  }
4969  }
4970 
5002  {
5003  // insert only works for arrays
5004  if (not is_array())
5005  {
5006  throw std::domain_error("cannot use insert() with " + type_name());
5007  }
5008 
5009  // check if iterator pos fits to this JSON value
5010  if (pos.m_object != this)
5011  {
5012  throw std::domain_error("iterator does not fit current value");
5013  }
5014 
5015  // check if range iterators belong to the same JSON object
5016  if (first.m_object != last.m_object)
5017  {
5018  throw std::domain_error("iterators do not fit");
5019  }
5020 
5021  if (first.m_object == this or last.m_object == this)
5022  {
5023  throw std::domain_error("passed iterators may not belong to container");
5024  }
5025 
5026  // insert to array and return iterator
5027  iterator result(this);
5028  assert(m_value.array != nullptr);
5029  result.m_it.array_iterator = m_value.array->insert(
5030  pos.m_it.array_iterator,
5031  first.m_it.array_iterator,
5032  last.m_it.array_iterator);
5033  return result;
5034  }
5035 
5060  iterator insert(const_iterator pos, std::initializer_list<basic_json> ilist)
5061  {
5062  // insert only works for arrays
5063  if (not is_array())
5064  {
5065  throw std::domain_error("cannot use insert() with " + type_name());
5066  }
5067 
5068  // check if iterator pos fits to this JSON value
5069  if (pos.m_object != this)
5070  {
5071  throw std::domain_error("iterator does not fit current value");
5072  }
5073 
5074  // insert to array and return iterator
5075  iterator result(this);
5076  assert(m_value.array != nullptr);
5077  result.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator, ilist);
5078  return result;
5079  }
5080 
5098  void swap(reference other) noexcept (
5099  std::is_nothrow_move_constructible<value_t>::value and
5100  std::is_nothrow_move_assignable<value_t>::value and
5101  std::is_nothrow_move_constructible<json_value>::value and
5102  std::is_nothrow_move_assignable<json_value>::value
5103  )
5104  {
5105  std::swap(m_type, other.m_type);
5106  std::swap(m_value, other.m_value);
5107  }
5108 
5129  void swap(array_t& other)
5130  {
5131  // swap only works for arrays
5132  if (is_array())
5133  {
5134  assert(m_value.array != nullptr);
5135  std::swap(*(m_value.array), other);
5136  }
5137  else
5138  {
5139  throw std::domain_error("cannot use swap() with " + type_name());
5140  }
5141  }
5142 
5163  void swap(object_t& other)
5164  {
5165  // swap only works for objects
5166  if (is_object())
5167  {
5168  assert(m_value.object != nullptr);
5169  std::swap(*(m_value.object), other);
5170  }
5171  else
5172  {
5173  throw std::domain_error("cannot use swap() with " + type_name());
5174  }
5175  }
5176 
5197  void swap(string_t& other)
5198  {
5199  // swap only works for strings
5200  if (is_string())
5201  {
5202  assert(m_value.string != nullptr);
5203  std::swap(*(m_value.string), other);
5204  }
5205  else
5206  {
5207  throw std::domain_error("cannot use swap() with " + type_name());
5208  }
5209  }
5210 
5212 
5213 
5215  // lexicographical comparison operators //
5217 
5220 
5221  private:
5231  friend bool operator<(const value_t lhs, const value_t rhs) noexcept
5232  {
5233  static constexpr std::array<uint8_t, 8> order = {{
5234  0, // null
5235  3, // object
5236  4, // array
5237  5, // string
5238  1, // boolean
5239  2, // integer
5240  2, // unsigned
5241  2, // float
5242  }
5243  };
5244 
5245  // discarded values are not comparable
5246  if (lhs == value_t::discarded or rhs == value_t::discarded)
5247  {
5248  return false;
5249  }
5250 
5251  return order[static_cast<std::size_t>(lhs)] < order[static_cast<std::size_t>(rhs)];
5252  }
5253 
5254  public:
5278  friend bool operator==(const_reference lhs, const_reference rhs) noexcept
5279  {
5280  const auto lhs_type = lhs.type();
5281  const auto rhs_type = rhs.type();
5282 
5283  if (lhs_type == rhs_type)
5284  {
5285  switch (lhs_type)
5286  {
5287  case value_t::array:
5288  {
5289  assert(lhs.m_value.array != nullptr);
5290  assert(rhs.m_value.array != nullptr);
5291  return *lhs.m_value.array == *rhs.m_value.array;
5292  }
5293  case value_t::object:
5294  {
5295  assert(lhs.m_value.object != nullptr);
5296  assert(rhs.m_value.object != nullptr);
5297  return *lhs.m_value.object == *rhs.m_value.object;
5298  }
5299  case value_t::null:
5300  {
5301  return true;
5302  }
5303  case value_t::string:
5304  {
5305  assert(lhs.m_value.string != nullptr);
5306  assert(rhs.m_value.string != nullptr);
5307  return *lhs.m_value.string == *rhs.m_value.string;
5308  }
5309  case value_t::boolean:
5310  {
5311  return lhs.m_value.boolean == rhs.m_value.boolean;
5312  }
5313  case value_t::number_integer:
5314  {
5315  return lhs.m_value.number_integer == rhs.m_value.number_integer;
5316  }
5317  case value_t::number_unsigned:
5318  {
5319  return lhs.m_value.number_unsigned == rhs.m_value.number_unsigned;
5320  }
5321  case value_t::number_float:
5322  {
5323  return lhs.m_value.number_float == rhs.m_value.number_float;
5324  }
5325  default:
5326  {
5327  return false;
5328  }
5329  }
5330  }
5331  else if (lhs_type == value_t::number_integer and rhs_type == value_t::number_float)
5332  {
5333  return static_cast<number_float_t>(lhs.m_value.number_integer) == rhs.m_value.number_float;
5334  }
5335  else if (lhs_type == value_t::number_float and rhs_type == value_t::number_integer)
5336  {
5337  return lhs.m_value.number_float == static_cast<number_float_t>(rhs.m_value.number_integer);
5338  }
5339  else if (lhs_type == value_t::number_unsigned and rhs_type == value_t::number_float)
5340  {
5341  return static_cast<number_float_t>(lhs.m_value.number_unsigned) == rhs.m_value.number_float;
5342  }
5343  else if (lhs_type == value_t::number_float and rhs_type == value_t::number_unsigned)
5344  {
5345  return lhs.m_value.number_float == static_cast<number_float_t>(rhs.m_value.number_unsigned);
5346  }
5347  else if (lhs_type == value_t::number_unsigned and rhs_type == value_t::number_integer)
5348  {
5349  return static_cast<number_integer_t>(lhs.m_value.number_unsigned) == rhs.m_value.number_integer;
5350  }
5351  else if (lhs_type == value_t::number_integer and rhs_type == value_t::number_unsigned)
5352  {
5353  return lhs.m_value.number_integer == static_cast<number_integer_t>(rhs.m_value.number_unsigned);
5354  }
5355 
5356  return false;
5357  }
5358 
5377  friend bool operator==(const_reference v, std::nullptr_t) noexcept
5378  {
5379  return v.is_null();
5380  }
5381 
5386  friend bool operator==(std::nullptr_t, const_reference v) noexcept
5387  {
5388  return v.is_null();
5389  }
5390 
5407  friend bool operator!=(const_reference lhs, const_reference rhs) noexcept
5408  {
5409  return not (lhs == rhs);
5410  }
5411 
5430  friend bool operator!=(const_reference v, std::nullptr_t) noexcept
5431  {
5432  return not v.is_null();
5433  }
5434 
5439  friend bool operator!=(std::nullptr_t, const_reference v) noexcept
5440  {
5441  return not v.is_null();
5442  }
5443 
5468  friend bool operator<(const_reference lhs, const_reference rhs) noexcept
5469  {
5470  const auto lhs_type = lhs.type();
5471  const auto rhs_type = rhs.type();
5472 
5473  if (lhs_type == rhs_type)
5474  {
5475  switch (lhs_type)
5476  {
5477  case value_t::array:
5478  {
5479  assert(lhs.m_value.array != nullptr);
5480  assert(rhs.m_value.array != nullptr);
5481  return *lhs.m_value.array < *rhs.m_value.array;
5482  }
5483  case value_t::object:
5484  {
5485  assert(lhs.m_value.object != nullptr);
5486  assert(rhs.m_value.object != nullptr);
5487  return *lhs.m_value.object < *rhs.m_value.object;
5488  }
5489  case value_t::null:
5490  {
5491  return false;
5492  }
5493  case value_t::string:
5494  {
5495  assert(lhs.m_value.string != nullptr);
5496  assert(rhs.m_value.string != nullptr);
5497  return *lhs.m_value.string < *rhs.m_value.string;
5498  }
5499  case value_t::boolean:
5500  {
5501  return lhs.m_value.boolean < rhs.m_value.boolean;
5502  }
5503  case value_t::number_integer:
5504  {
5505  return lhs.m_value.number_integer < rhs.m_value.number_integer;
5506  }
5507  case value_t::number_unsigned:
5508  {
5509  return lhs.m_value.number_unsigned < rhs.m_value.number_unsigned;
5510  }
5511  case value_t::number_float:
5512  {
5513  return lhs.m_value.number_float < rhs.m_value.number_float;
5514  }
5515  default:
5516  {
5517  return false;
5518  }
5519  }
5520  }
5521  else if (lhs_type == value_t::number_integer and rhs_type == value_t::number_float)
5522  {
5523  return static_cast<number_float_t>(lhs.m_value.number_integer) < rhs.m_value.number_float;
5524  }
5525  else if (lhs_type == value_t::number_float and rhs_type == value_t::number_integer)
5526  {
5527  return lhs.m_value.number_float < static_cast<number_float_t>(rhs.m_value.number_integer);
5528  }
5529  else if (lhs_type == value_t::number_unsigned and rhs_type == value_t::number_float)
5530  {
5531  return static_cast<number_float_t>(lhs.m_value.number_unsigned) < rhs.m_value.number_float;
5532  }
5533  else if (lhs_type == value_t::number_float and rhs_type == value_t::number_unsigned)
5534  {
5535  return lhs.m_value.number_float < static_cast<number_float_t>(rhs.m_value.number_unsigned);
5536  }
5537  else if (lhs_type == value_t::number_integer and rhs_type == value_t::number_unsigned)
5538  {
5539  return lhs.m_value.number_integer < static_cast<number_integer_t>(rhs.m_value.number_unsigned);
5540  }
5541  else if (lhs_type == value_t::number_unsigned and rhs_type == value_t::number_integer)
5542  {
5543  return static_cast<number_integer_t>(lhs.m_value.number_unsigned) < rhs.m_value.number_integer;
5544  }
5545 
5546  // We only reach this line if we cannot compare values. In that case,
5547  // we compare types. Note we have to call the operator explicitly,
5548  // because MSVC has problems otherwise.
5549  return operator<(lhs_type, rhs_type);
5550  }
5551 
5569  friend bool operator<=(const_reference lhs, const_reference rhs) noexcept
5570  {
5571  return not (rhs < lhs);
5572  }
5573 
5591  friend bool operator>(const_reference lhs, const_reference rhs) noexcept
5592  {
5593  return not (lhs <= rhs);
5594  }
5595 
5613  friend bool operator>=(const_reference lhs, const_reference rhs) noexcept
5614  {
5615  return not (lhs < rhs);
5616  }
5617 
5619 
5620 
5622  // serialization //
5624 
5627 
5650  friend std::ostream& operator<<(std::ostream& o, const basic_json& j)
5651  {
5652  // read width member and use it as indentation parameter if nonzero
5653  const bool pretty_print = (o.width() > 0);
5654  const auto indentation = (pretty_print ? o.width() : 0);
5655 
5656  // reset width to 0 for subsequent calls to this stream
5657  o.width(0);
5658 
5659  // do the actual serialization
5660  j.dump(o, pretty_print, static_cast<unsigned int>(indentation));
5661  return o;
5662  }
5663 
5668  friend std::ostream& operator>>(const basic_json& j, std::ostream& o)
5669  {
5670  return o << j;
5671  }
5672 
5674 
5675 
5677  // deserialization //
5679 
5682 
5707  static basic_json parse(const string_t& s, parser_callback_t cb = nullptr)
5708  {
5709  return parser(s, cb).parse();
5710  }
5711 
5736  static basic_json parse(std::istream& i, parser_callback_t cb = nullptr)
5737  {
5738  return parser(i, cb).parse();
5739  }
5740 
5744  static basic_json parse(std::istream&& i, parser_callback_t cb = nullptr)
5745  {
5746  return parser(i, cb).parse();
5747  }
5748 
5772  friend std::istream& operator<<(basic_json& j, std::istream& i)
5773  {
5774  j = parser(i).parse();
5775  return i;
5776  }
5777 
5782  friend std::istream& operator>>(std::istream& i, basic_json& j)
5783  {
5784  j = parser(i).parse();
5785  return i;
5786  }
5787 
5789 
5790 
5791  private:
5793  // convenience functions //
5795 
5797  string_t type_name() const noexcept
5798  {
5799  switch (m_type)
5800  {
5801  case value_t::null:
5802  return "null";
5803  case value_t::object:
5804  return "object";
5805  case value_t::array:
5806  return "array";
5807  case value_t::string:
5808  return "string";
5809  case value_t::boolean:
5810  return "boolean";
5811  case value_t::discarded:
5812  return "discarded";
5813  default:
5814  return "number";
5815  }
5816  }
5817 
5826  static std::size_t extra_space(const string_t& s) noexcept
5827  {
5828  std::size_t result = 0;
5829 
5830  for (const auto& c : s)
5831  {
5832  switch (c)
5833  {
5834  case '"':
5835  case '\\':
5836  case '\b':
5837  case '\f':
5838  case '\n':
5839  case '\r':
5840  case '\t':
5841  {
5842  // from c (1 byte) to \x (2 bytes)
5843  result += 1;
5844  break;
5845  }
5846 
5847  default:
5848  {
5849  if (c >= 0x00 and c <= 0x1f)
5850  {
5851  // from c (1 byte) to \uxxxx (6 bytes)
5852  result += 5;
5853  }
5854  break;
5855  }
5856  }
5857  }
5858 
5859  return result;
5860  }
5861 
5875  static string_t escape_string(const string_t& s)
5876  {
5877  const auto space = extra_space(s);
5878  if (space == 0)
5879  {
5880  return s;
5881  }
5882 
5883  // create a result string of necessary size
5884  string_t result(s.size() + space, '\\');
5885  std::size_t pos = 0;
5886 
5887  for (const auto& c : s)
5888  {
5889  switch (c)
5890  {
5891  // quotation mark (0x22)
5892  case '"':
5893  {
5894  result[pos + 1] = '"';
5895  pos += 2;
5896  break;
5897  }
5898 
5899  // reverse solidus (0x5c)
5900  case '\\':
5901  {
5902  // nothing to change
5903  pos += 2;
5904  break;
5905  }
5906 
5907  // backspace (0x08)
5908  case '\b':
5909  {
5910  result[pos + 1] = 'b';
5911  pos += 2;
5912  break;
5913  }
5914 
5915  // formfeed (0x0c)
5916  case '\f':
5917  {
5918  result[pos + 1] = 'f';
5919  pos += 2;
5920  break;
5921  }
5922 
5923  // newline (0x0a)
5924  case '\n':
5925  {
5926  result[pos + 1] = 'n';
5927  pos += 2;
5928  break;
5929  }
5930 
5931  // carriage return (0x0d)
5932  case '\r':
5933  {
5934  result[pos + 1] = 'r';
5935  pos += 2;
5936  break;
5937  }
5938 
5939  // horizontal tab (0x09)
5940  case '\t':
5941  {
5942  result[pos + 1] = 't';
5943  pos += 2;
5944  break;
5945  }
5946 
5947  default:
5948  {
5949  if (c >= 0x00 and c <= 0x1f)
5950  {
5951  // convert a number 0..15 to its hex representation
5952  // (0..f)
5953  const auto hexify = [](const int v) -> char
5954  {
5955  return (v < 10)
5956  ? ('0' + static_cast<char>(v))
5957  : ('a' + static_cast<char>((v - 10) & 0x1f));
5958  };
5959 
5960  // print character c as \uxxxx
5961  for (const char m :
5962  { 'u', '0', '0', hexify(c >> 4), hexify(c & 0x0f)
5963  })
5964  {
5965  result[++pos] = m;
5966  }
5967 
5968  ++pos;
5969  }
5970  else
5971  {
5972  // all other characters are added as-is
5973  result[pos++] = c;
5974  }
5975  break;
5976  }
5977  }
5978  }
5979 
5980  return result;
5981  }
5982 
6000  void dump(std::ostream& o,
6001  const bool pretty_print,
6002  const unsigned int indent_step,
6003  const unsigned int current_indent = 0) const
6004  {
6005  // variable to hold indentation for recursive calls
6006  unsigned int new_indent = current_indent;
6007 
6008  switch (m_type)
6009  {
6010  case value_t::object:
6011  {
6012  assert(m_value.object != nullptr);
6013 
6014  if (m_value.object->empty())
6015  {
6016  o << "{}";
6017  return;
6018  }
6019 
6020  o << "{";
6021 
6022  // increase indentation
6023  if (pretty_print)
6024  {
6025  new_indent += indent_step;
6026  o << "\n";
6027  }
6028 
6029  for (auto i = m_value.object->cbegin(); i != m_value.object->cend(); ++i)
6030  {
6031  if (i != m_value.object->cbegin())
6032  {
6033  o << (pretty_print ? ",\n" : ",");
6034  }
6035  o << string_t(new_indent, ' ') << "\""
6036  << escape_string(i->first) << "\":"
6037  << (pretty_print ? " " : "");
6038  i->second.dump(o, pretty_print, indent_step, new_indent);
6039  }
6040 
6041  // decrease indentation
6042  if (pretty_print)
6043  {
6044  new_indent -= indent_step;
6045  o << "\n";
6046  }
6047 
6048  o << string_t(new_indent, ' ') + "}";
6049  return;
6050  }
6051 
6052  case value_t::array:
6053  {
6054  assert(m_value.array != nullptr);
6055 
6056  if (m_value.array->empty())
6057  {
6058  o << "[]";
6059  return;
6060  }
6061 
6062  o << "[";
6063 
6064  // increase indentation
6065  if (pretty_print)
6066  {
6067  new_indent += indent_step;
6068  o << "\n";
6069  }
6070 
6071  for (auto i = m_value.array->cbegin(); i != m_value.array->cend(); ++i)
6072  {
6073  if (i != m_value.array->cbegin())
6074  {
6075  o << (pretty_print ? ",\n" : ",");
6076  }
6077  o << string_t(new_indent, ' ');
6078  i->dump(o, pretty_print, indent_step, new_indent);
6079  }
6080 
6081  // decrease indentation
6082  if (pretty_print)
6083  {
6084  new_indent -= indent_step;
6085  o << "\n";
6086  }
6087 
6088  o << string_t(new_indent, ' ') << "]";
6089  return;
6090  }
6091 
6092  case value_t::string:
6093  {
6094  assert(m_value.string != nullptr);
6095  o << string_t("\"") << escape_string(*m_value.string) << "\"";
6096  return;
6097  }
6098 
6099  case value_t::boolean:
6100  {
6101  o << (m_value.boolean ? "true" : "false");
6102  return;
6103  }
6104 
6105  case value_t::number_integer:
6106  {
6107  o << m_value.number_integer;
6108  return;
6109  }
6110 
6111  case value_t::number_unsigned:
6112  {
6113  o << m_value.number_unsigned;
6114  return;
6115  }
6116 
6117  case value_t::number_float:
6118  {
6119  if (m_value.number_float == 0)
6120  {
6121  // special case for zero to get "0.0"/"-0.0"
6122  o << (std::signbit(m_value.number_float) ? "-0.0" : "0.0");
6123  }
6124  else
6125  {
6126  // Otherwise 6, 15 or 16 digits of precision allows
6127  // round-trip IEEE 754 string->float->string,
6128  // string->double->string or string->long
6129  // double->string; to be safe, we read this value from
6130  // std::numeric_limits<number_float_t>::digits10
6131  std::stringstream ss;
6132  ss.imbue(std::locale(std::locale(), new DecimalSeparator)); // fix locale problems
6133  ss << std::setprecision(std::numeric_limits<double>::digits10)
6134  << m_value.number_float;
6135  o << ss.str();
6136  }
6137  return;
6138  }
6139 
6140  case value_t::discarded:
6141  {
6142  o << "<discarded>";
6143  return;
6144  }
6145 
6146  case value_t::null:
6147  {
6148  o << "null";
6149  return;
6150  }
6151  }
6152  }
6153 
6154  private:
6156  // member variables //
6158 
6160  value_t m_type = value_t::null;
6161 
6163  json_value m_value = {};
6164 
6165 
6166  private:
6168  // iterators //
6170 
6180  class primitive_iterator_t
6181  {
6182  public:
6184  void set_begin() noexcept
6185  {
6186  m_it = begin_value;
6187  }
6188 
6190  void set_end() noexcept
6191  {
6192  m_it = end_value;
6193  }
6194 
6196  constexpr bool is_begin() const noexcept
6197  {
6198  return (m_it == begin_value);
6199  }
6200 
6202  constexpr bool is_end() const noexcept
6203  {
6204  return (m_it == end_value);
6205  }
6206 
6208  operator difference_type& () noexcept
6209  {
6210  return m_it;
6211  }
6212 
6214  constexpr operator difference_type () const noexcept
6215  {
6216  return m_it;
6217  }
6218 
6219  private:
6220  static constexpr difference_type begin_value = 0;
6221  static constexpr difference_type end_value = begin_value + 1;
6222 
6224  difference_type m_it = std::numeric_limits<std::ptrdiff_t>::denorm_min();
6225  };
6226 
6234  struct internal_iterator
6235  {
6237  typename object_t::iterator object_iterator;
6239  typename array_t::iterator array_iterator;
6241  primitive_iterator_t primitive_iterator;
6242 
6244  internal_iterator() noexcept
6245  : object_iterator(), array_iterator(), primitive_iterator()
6246  {}
6247  };
6248 
6250  template<typename IteratorType>
6251  class iteration_proxy
6252  {
6253  private:
6255  class iteration_proxy_internal
6256  {
6257  private:
6259  IteratorType anchor;
6261  size_t array_index = 0;
6262 
6263  public:
6264  explicit iteration_proxy_internal(IteratorType it) noexcept
6265  : anchor(it)
6266  {}
6267 
6269  iteration_proxy_internal& operator*()
6270  {
6271  return *this;
6272  }
6273 
6275  iteration_proxy_internal& operator++()
6276  {
6277  ++anchor;
6278  ++array_index;
6279 
6280  return *this;
6281  }
6282 
6284  bool operator!= (const iteration_proxy_internal& o) const
6285  {
6286  return anchor != o.anchor;
6287  }
6288 
6290  typename basic_json::string_t key() const
6291  {
6292  assert(anchor.m_object != nullptr);
6293 
6294  switch (anchor.m_object->type())
6295  {
6296  // use integer array index as key
6297  case value_t::array:
6298  {
6299  return std::to_string(array_index);
6300  }
6301 
6302  // use key from the object
6303  case value_t::object:
6304  {
6305  return anchor.key();
6306  }
6307 
6308  // use an empty key for all primitive types
6309  default:
6310  {
6311  return "";
6312  }
6313  }
6314  }
6315 
6317  typename IteratorType::reference value() const
6318  {
6319  return anchor.value();
6320  }
6321  };
6322 
6324  typename IteratorType::reference container;
6325 
6326  public:
6328  explicit iteration_proxy(typename IteratorType::reference cont)
6329  : container(cont)
6330  {}
6331 
6333  iteration_proxy_internal begin() noexcept
6334  {
6335  return iteration_proxy_internal(container.begin());
6336  }
6337 
6339  iteration_proxy_internal end() noexcept
6340  {
6341  return iteration_proxy_internal(container.end());
6342  }
6343  };
6344 
6345  public:
6359  class const_iterator : public std::iterator<std::random_access_iterator_tag, const basic_json>
6360  {
6362  friend class basic_json;
6363 
6364  public:
6374  using iterator_category = std::bidirectional_iterator_tag;
6375 
6377  const_iterator() = default;
6378 
6380  explicit const_iterator(pointer object) noexcept
6381  : m_object(object)
6382  {
6383  assert(m_object != nullptr);
6384 
6385  switch (m_object->m_type)
6386  {
6388  {
6389  m_it.object_iterator = typename object_t::iterator();
6390  break;
6391  }
6392 
6394  {
6395  m_it.array_iterator = typename array_t::iterator();
6396  break;
6397  }
6398 
6399  default:
6400  {
6401  m_it.primitive_iterator = primitive_iterator_t();
6402  break;
6403  }
6404  }
6405  }
6406 
6408  explicit const_iterator(const iterator& other) noexcept
6409  : m_object(other.m_object)
6410  {
6411  assert(m_object != nullptr);
6412 
6413  switch (m_object->m_type)
6414  {
6416  {
6417  m_it.object_iterator = other.m_it.object_iterator;
6418  break;
6419  }
6420 
6422  {
6423  m_it.array_iterator = other.m_it.array_iterator;
6424  break;
6425  }
6426 
6427  default:
6428  {
6429  m_it.primitive_iterator = other.m_it.primitive_iterator;
6430  break;
6431  }
6432  }
6433  }
6434 
6436  const_iterator(const const_iterator& other) noexcept
6437  : m_object(other.m_object), m_it(other.m_it)
6438  {}
6439 
6442  std::is_nothrow_move_constructible<pointer>::value and
6443  std::is_nothrow_move_assignable<pointer>::value and
6444  std::is_nothrow_move_constructible<internal_iterator>::value and
6445  std::is_nothrow_move_assignable<internal_iterator>::value
6446  )
6447  {
6448  std::swap(m_object, other.m_object);
6449  std::swap(m_it, other.m_it);
6450  return *this;
6451  }
6452 
6453  private:
6455  void set_begin() noexcept
6456  {
6457  assert(m_object != nullptr);
6458 
6459  switch (m_object->m_type)
6460  {
6462  {
6463  assert(m_object->m_value.object != nullptr);
6464  m_it.object_iterator = m_object->m_value.object->begin();
6465  break;
6466  }
6467 
6469  {
6470  assert(m_object->m_value.array != nullptr);
6471  m_it.array_iterator = m_object->m_value.array->begin();
6472  break;
6473  }
6474 
6476  {
6477  // set to end so begin()==end() is true: null is empty
6478  m_it.primitive_iterator.set_end();
6479  break;
6480  }
6481 
6482  default:
6483  {
6484  m_it.primitive_iterator.set_begin();
6485  break;
6486  }
6487  }
6488  }
6489 
6491  void set_end() noexcept
6492  {
6493  assert(m_object != nullptr);
6494 
6495  switch (m_object->m_type)
6496  {
6498  {
6499  assert(m_object->m_value.object != nullptr);
6500  m_it.object_iterator = m_object->m_value.object->end();
6501  break;
6502  }
6503 
6505  {
6506  assert(m_object->m_value.array != nullptr);
6507  m_it.array_iterator = m_object->m_value.array->end();
6508  break;
6509  }
6510 
6511  default:
6512  {
6513  m_it.primitive_iterator.set_end();
6514  break;
6515  }
6516  }
6517  }
6518 
6519  public:
6522  {
6523  assert(m_object != nullptr);
6524 
6525  switch (m_object->m_type)
6526  {
6528  {
6529  assert(m_object->m_value.object);
6530  assert(m_it.object_iterator != m_object->m_value.object->end());
6531  return m_it.object_iterator->second;
6532  }
6533 
6535  {
6536  assert(m_object->m_value.array);
6537  assert(m_it.array_iterator != m_object->m_value.array->end());
6538  return *m_it.array_iterator;
6539  }
6540 
6542  {
6543  throw std::out_of_range("cannot get value");
6544  }
6545 
6546  default:
6547  {
6548  if (m_it.primitive_iterator.is_begin())
6549  {
6550  return *m_object;
6551  }
6552  else
6553  {
6554  throw std::out_of_range("cannot get value");
6555  }
6556  }
6557  }
6558  }
6559 
6562  {
6563  assert(m_object != nullptr);
6564 
6565  switch (m_object->m_type)
6566  {
6568  {
6569  assert(m_object->m_value.object);
6570  assert(m_it.object_iterator != m_object->m_value.object->end());
6571  return &(m_it.object_iterator->second);
6572  }
6573 
6575  {
6576  assert(m_object->m_value.array);
6577  assert(m_it.array_iterator != m_object->m_value.array->end());
6578  return &*m_it.array_iterator;
6579  }
6580 
6581  default:
6582  {
6583  if (m_it.primitive_iterator.is_begin())
6584  {
6585  return m_object;
6586  }
6587  else
6588  {
6589  throw std::out_of_range("cannot get value");
6590  }
6591  }
6592  }
6593  }
6594 
6597  {
6598  auto result = *this;
6599  ++(*this);
6600  return result;
6601  }
6602 
6605  {
6606  assert(m_object != nullptr);
6607 
6608  switch (m_object->m_type)
6609  {
6611  {
6612  ++m_it.object_iterator;
6613  break;
6614  }
6615 
6617  {
6618  ++m_it.array_iterator;
6619  break;
6620  }
6621 
6622  default:
6623  {
6624  ++m_it.primitive_iterator;
6625  break;
6626  }
6627  }
6628 
6629  return *this;
6630  }
6631 
6634  {
6635  auto result = *this;
6636  --(*this);
6637  return result;
6638  }
6639 
6642  {
6643  assert(m_object != nullptr);
6644 
6645  switch (m_object->m_type)
6646  {
6648  {
6649  --m_it.object_iterator;
6650  break;
6651  }
6652 
6654  {
6655  --m_it.array_iterator;
6656  break;
6657  }
6658 
6659  default:
6660  {
6661  --m_it.primitive_iterator;
6662  break;
6663  }
6664  }
6665 
6666  return *this;
6667  }
6668 
6670  bool operator==(const const_iterator& other) const
6671  {
6672  // if objects are not the same, the comparison is undefined
6673  if (m_object != other.m_object)
6674  {
6675  throw std::domain_error("cannot compare iterators of different containers");
6676  }
6677 
6678  assert(m_object != nullptr);
6679 
6680  switch (m_object->m_type)
6681  {
6683  {
6684  return (m_it.object_iterator == other.m_it.object_iterator);
6685  }
6686 
6688  {
6689  return (m_it.array_iterator == other.m_it.array_iterator);
6690  }
6691 
6692  default:
6693  {
6694  return (m_it.primitive_iterator == other.m_it.primitive_iterator);
6695  }
6696  }
6697  }
6698 
6700  bool operator!=(const const_iterator& other) const
6701  {
6702  return not operator==(other);
6703  }
6704 
6706  bool operator<(const const_iterator& other) const
6707  {
6708  // if objects are not the same, the comparison is undefined
6709  if (m_object != other.m_object)
6710  {
6711  throw std::domain_error("cannot compare iterators of different containers");
6712  }
6713 
6714  assert(m_object != nullptr);
6715 
6716  switch (m_object->m_type)
6717  {
6719  {
6720  throw std::domain_error("cannot compare order of object iterators");
6721  }
6722 
6724  {
6725  return (m_it.array_iterator < other.m_it.array_iterator);
6726  }
6727 
6728  default:
6729  {
6730  return (m_it.primitive_iterator < other.m_it.primitive_iterator);
6731  }
6732  }
6733  }
6734 
6736  bool operator<=(const const_iterator& other) const
6737  {
6738  return not other.operator < (*this);
6739  }
6740 
6742  bool operator>(const const_iterator& other) const
6743  {
6744  return not operator<=(other);
6745  }
6746 
6748  bool operator>=(const const_iterator& other) const
6749  {
6750  return not operator<(other);
6751  }
6752 
6755  {
6756  assert(m_object != nullptr);
6757 
6758  switch (m_object->m_type)
6759  {
6761  {
6762  throw std::domain_error("cannot use offsets with object iterators");
6763  }
6764 
6766  {
6767  m_it.array_iterator += i;
6768  break;
6769  }
6770 
6771  default:
6772  {
6773  m_it.primitive_iterator += i;
6774  break;
6775  }
6776  }
6777 
6778  return *this;
6779  }
6780 
6783  {
6784  return operator+=(-i);
6785  }
6786 
6789  {
6790  auto result = *this;
6791  result += i;
6792  return result;
6793  }
6794 
6797  {
6798  auto result = *this;
6799  result -= i;
6800  return result;
6801  }
6802 
6805  {
6806  assert(m_object != nullptr);
6807 
6808  switch (m_object->m_type)
6809  {
6811  {
6812  throw std::domain_error("cannot use offsets with object iterators");
6813  }
6814 
6816  {
6817  return m_it.array_iterator - other.m_it.array_iterator;
6818  }
6819 
6820  default:
6821  {
6822  return m_it.primitive_iterator - other.m_it.primitive_iterator;
6823  }
6824  }
6825  }
6826 
6829  {
6830  assert(m_object != nullptr);
6831 
6832  switch (m_object->m_type)
6833  {
6835  {
6836  throw std::domain_error("cannot use operator[] for object iterators");
6837  }
6838 
6840  {
6841  return *(m_it.array_iterator + n);
6842  }
6843 
6845  {
6846  throw std::out_of_range("cannot get value");
6847  }
6848 
6849  default:
6850  {
6851  if (m_it.primitive_iterator == -n)
6852  {
6853  return *m_object;
6854  }
6855  else
6856  {
6857  throw std::out_of_range("cannot get value");
6858  }
6859  }
6860  }
6861  }
6862 
6864  typename object_t::key_type key() const
6865  {
6866  assert(m_object != nullptr);
6867 
6868  if (m_object->is_object())
6869  {
6870  return m_it.object_iterator->first;
6871  }
6872  else
6873  {
6874  throw std::domain_error("cannot use key() for non-object iterators");
6875  }
6876  }
6877 
6880  {
6881  return operator*();
6882  }
6883 
6884  private:
6886  pointer m_object = nullptr;
6888  internal_iterator m_it = internal_iterator();
6889  };
6890 
6903  class iterator : public const_iterator
6904  {
6905  public:
6907  using pointer = typename basic_json::pointer;
6909 
6911  iterator() = default;
6912 
6914  explicit iterator(pointer object) noexcept
6915  : base_iterator(object)
6916  {}
6917 
6919  iterator(const iterator& other) noexcept
6920  : base_iterator(other)
6921  {}
6922 
6924  iterator& operator=(iterator other) noexcept(
6925  std::is_nothrow_move_constructible<pointer>::value and
6926  std::is_nothrow_move_assignable<pointer>::value and
6927  std::is_nothrow_move_constructible<internal_iterator>::value and
6928  std::is_nothrow_move_assignable<internal_iterator>::value
6929  )
6930  {
6931  base_iterator::operator=(other);
6932  return *this;
6933  }
6934 
6937  {
6938  return const_cast<reference>(base_iterator::operator*());
6939  }
6940 
6943  {
6944  return const_cast<pointer>(base_iterator::operator->());
6945  }
6946 
6949  {
6950  iterator result = *this;
6951  base_iterator::operator++();
6952  return result;
6953  }
6954 
6957  {
6958  base_iterator::operator++();
6959  return *this;
6960  }
6961 
6964  {
6965  iterator result = *this;
6966  base_iterator::operator--();
6967  return result;
6968  }
6969 
6972  {
6973  base_iterator::operator--();
6974  return *this;
6975  }
6976 
6979  {
6980  base_iterator::operator+=(i);
6981  return *this;
6982  }
6983 
6986  {
6987  base_iterator::operator-=(i);
6988  return *this;
6989  }
6990 
6993  {
6994  auto result = *this;
6995  result += i;
6996  return result;
6997  }
6998 
7001  {
7002  auto result = *this;
7003  result -= i;
7004  return result;
7005  }
7006 
7008  difference_type operator-(const iterator& other) const
7009  {
7010  return base_iterator::operator-(other);
7011  }
7012 
7015  {
7016  return const_cast<reference>(base_iterator::operator[](n));
7017  }
7018 
7021  {
7022  return const_cast<reference>(base_iterator::value());
7023  }
7024  };
7025 
7043  template<typename Base>
7044  class json_reverse_iterator : public std::reverse_iterator<Base>
7045  {
7046  public:
7048  using base_iterator = std::reverse_iterator<Base>;
7050  using reference = typename Base::reference;
7051 
7053  json_reverse_iterator(const typename base_iterator::iterator_type& it) noexcept
7054  : base_iterator(it)
7055  {}
7056 
7059  : base_iterator(it)
7060  {}
7061 
7064  {
7065  return base_iterator::operator++(1);
7066  }
7067 
7070  {
7071  base_iterator::operator++();
7072  return *this;
7073  }
7074 
7077  {
7078  return base_iterator::operator--(1);
7079  }
7080 
7083  {
7084  base_iterator::operator--();
7085  return *this;
7086  }
7087 
7090  {
7091  base_iterator::operator+=(i);
7092  return *this;
7093  }
7094 
7097  {
7098  auto result = *this;
7099  result += i;
7100  return result;
7101  }
7102 
7105  {
7106  auto result = *this;
7107  result -= i;
7108  return result;
7109  }
7110 
7113  {
7114  return this->base() - other.base();
7115  }
7116 
7119  {
7120  return *(this->operator+(n));
7121  }
7122 
7124  typename object_t::key_type key() const
7125  {
7126  auto it = --this->base();
7127  return it.key();
7128  }
7129 
7132  {
7133  auto it = --this->base();
7134  return it.operator * ();
7135  }
7136  };
7137 
7138 
7139  private:
7141  // lexer and parser //
7143 
7151  class lexer
7152  {
7153  public:
7155  enum class token_type
7156  {
7157  uninitialized,
7158  literal_true,
7159  literal_false,
7160  literal_null,
7161  value_string,
7162  value_number,
7163  begin_array,
7164  begin_object,
7165  end_array,
7166  end_object,
7167  name_separator,
7168  value_separator,
7169  parse_error,
7170  end_of_input
7171  };
7172 
7174  using lexer_char_t = unsigned char;
7175 
7177  explicit lexer(const string_t& s) noexcept
7178  : m_stream(nullptr), m_buffer(s)
7179  {
7180  m_content = reinterpret_cast<const lexer_char_t*>(s.c_str());
7181  assert(m_content != nullptr);
7182  m_start = m_cursor = m_content;
7183  m_limit = m_content + s.size();
7184  }
7185 
7187  explicit lexer(std::istream* s) noexcept
7188  : m_stream(s), m_buffer()
7189  {
7190  assert(m_stream != nullptr);
7191  getline(*m_stream, m_buffer);
7192  m_content = reinterpret_cast<const lexer_char_t*>(m_buffer.c_str());
7193  assert(m_content != nullptr);
7194  m_start = m_cursor = m_content;
7195  m_limit = m_content + m_buffer.size();
7196  }
7197 
7199  lexer() = default;
7200 
7201  // switch off unwanted functions
7202  lexer(const lexer&) = delete;
7203  lexer operator=(const lexer&) = delete;
7204 
7220  static string_t to_unicode(const std::size_t codepoint1,
7221  const std::size_t codepoint2 = 0)
7222  {
7223  // calculate the codepoint from the given code points
7224  std::size_t codepoint = codepoint1;
7225 
7226  // check if codepoint1 is a high surrogate
7227  if (codepoint1 >= 0xD800 and codepoint1 <= 0xDBFF)
7228  {
7229  // check if codepoint2 is a low surrogate
7230  if (codepoint2 >= 0xDC00 and codepoint2 <= 0xDFFF)
7231  {
7232  codepoint =
7233  // high surrogate occupies the most significant 22 bits
7234  (codepoint1 << 10)
7235  // low surrogate occupies the least significant 15 bits
7236  + codepoint2
7237  // there is still the 0xD800, 0xDC00 and 0x10000 noise
7238  // in the result so we have to subtract with:
7239  // (0xD800 << 10) + DC00 - 0x10000 = 0x35FDC00
7240  - 0x35FDC00;
7241  }
7242  else
7243  {
7244  throw std::invalid_argument("missing or wrong low surrogate");
7245  }
7246  }
7247 
7248  string_t result;
7249 
7250  if (codepoint < 0x80)
7251  {
7252  // 1-byte characters: 0xxxxxxx (ASCII)
7253  result.append(1, static_cast<typename string_t::value_type>(codepoint));
7254  }
7255  else if (codepoint <= 0x7ff)
7256  {
7257  // 2-byte characters: 110xxxxx 10xxxxxx
7258  result.append(1, static_cast<typename string_t::value_type>(0xC0 | ((codepoint >> 6) & 0x1F)));
7259  result.append(1, static_cast<typename string_t::value_type>(0x80 | (codepoint & 0x3F)));
7260  }
7261  else if (codepoint <= 0xffff)
7262  {
7263  // 3-byte characters: 1110xxxx 10xxxxxx 10xxxxxx
7264  result.append(1, static_cast<typename string_t::value_type>(0xE0 | ((codepoint >> 12) & 0x0F)));
7265  result.append(1, static_cast<typename string_t::value_type>(0x80 | ((codepoint >> 6) & 0x3F)));
7266  result.append(1, static_cast<typename string_t::value_type>(0x80 | (codepoint & 0x3F)));
7267  }
7268  else if (codepoint <= 0x10ffff)
7269  {
7270  // 4-byte characters: 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
7271  result.append(1, static_cast<typename string_t::value_type>(0xF0 | ((codepoint >> 18) & 0x07)));
7272  result.append(1, static_cast<typename string_t::value_type>(0x80 | ((codepoint >> 12) & 0x3F)));
7273  result.append(1, static_cast<typename string_t::value_type>(0x80 | ((codepoint >> 6) & 0x3F)));
7274  result.append(1, static_cast<typename string_t::value_type>(0x80 | (codepoint & 0x3F)));
7275  }
7276  else
7277  {
7278  throw std::out_of_range("code points above 0x10FFFF are invalid");
7279  }
7280 
7281  return result;
7282  }
7283 
7285  static std::string token_type_name(token_type t)
7286  {
7287  switch (t)
7288  {
7289  case token_type::uninitialized:
7290  return "<uninitialized>";
7291  case token_type::literal_true:
7292  return "true literal";
7293  case token_type::literal_false:
7294  return "false literal";
7295  case token_type::literal_null:
7296  return "null literal";
7297  case token_type::value_string:
7298  return "string literal";
7299  case token_type::value_number:
7300  return "number literal";
7301  case token_type::begin_array:
7302  return "'['";
7303  case token_type::begin_object:
7304  return "'{'";
7305  case token_type::end_array:
7306  return "']'";
7307  case token_type::end_object:
7308  return "'}'";
7309  case token_type::name_separator:
7310  return "':'";
7311  case token_type::value_separator:
7312  return "','";
7313  case token_type::parse_error:
7314  return "<parse error>";
7315  case token_type::end_of_input:
7316  return "end of input";
7317  default:
7318  {
7319  // catch non-enum values
7320  return "unknown token"; // LCOV_EXCL_LINE
7321  }
7322  }
7323  }
7324 
7335  token_type scan() noexcept
7336  {
7337  // pointer for backtracking information
7338  m_marker = nullptr;
7339 
7340  // remember the begin of the token
7341  m_start = m_cursor;
7342  assert(m_start != nullptr);
7343 
7344 
7345  {
7346  lexer_char_t yych;
7347  unsigned int yyaccept = 0;
7348  static const unsigned char yybm[] =
7349  {
7350  0, 0, 0, 0, 0, 0, 0, 0,
7351  0, 32, 32, 0, 0, 32, 0, 0,
7352  128, 128, 128, 128, 128, 128, 128, 128,
7353  128, 128, 128, 128, 128, 128, 128, 128,
7354  160, 128, 0, 128, 128, 128, 128, 128,
7355  128, 128, 128, 128, 128, 128, 128, 128,
7356  192, 192, 192, 192, 192, 192, 192, 192,
7357  192, 192, 128, 128, 128, 128, 128, 128,
7358  128, 128, 128, 128, 128, 128, 128, 128,
7359  128, 128, 128, 128, 128, 128, 128, 128,
7360  128, 128, 128, 128, 128, 128, 128, 128,
7361  128, 128, 128, 128, 0, 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, 128, 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  };
7383  if ((m_limit - m_cursor) < 5)
7384  {
7385  yyfill(); // LCOV_EXCL_LINE;
7386  }
7387  yych = *m_cursor;
7388  if (yybm[0 + yych] & 32)
7389  {
7390  goto basic_json_parser_6;
7391  }
7392  if (yych <= '\\')
7393  {
7394  if (yych <= '-')
7395  {
7396  if (yych <= '"')
7397  {
7398  if (yych <= 0x00)
7399  {
7400  goto basic_json_parser_2;
7401  }
7402  if (yych <= '!')
7403  {
7404  goto basic_json_parser_4;
7405  }
7406  goto basic_json_parser_9;
7407  }
7408  else
7409  {
7410  if (yych <= '+')
7411  {
7412  goto basic_json_parser_4;
7413  }
7414  if (yych <= ',')
7415  {
7416  goto basic_json_parser_10;
7417  }
7418  goto basic_json_parser_12;
7419  }
7420  }
7421  else
7422  {
7423  if (yych <= '9')
7424  {
7425  if (yych <= '/')
7426  {
7427  goto basic_json_parser_4;
7428  }
7429  if (yych <= '0')
7430  {
7431  goto basic_json_parser_13;
7432  }
7433  goto basic_json_parser_15;
7434  }
7435  else
7436  {
7437  if (yych <= ':')
7438  {
7439  goto basic_json_parser_17;
7440  }
7441  if (yych == '[')
7442  {
7443  goto basic_json_parser_19;
7444  }
7445  goto basic_json_parser_4;
7446  }
7447  }
7448  }
7449  else
7450  {
7451  if (yych <= 't')
7452  {
7453  if (yych <= 'f')
7454  {
7455  if (yych <= ']')
7456  {
7457  goto basic_json_parser_21;
7458  }
7459  if (yych <= 'e')
7460  {
7461  goto basic_json_parser_4;
7462  }
7463  goto basic_json_parser_23;
7464  }
7465  else
7466  {
7467  if (yych == 'n')
7468  {
7469  goto basic_json_parser_24;
7470  }
7471  if (yych <= 's')
7472  {
7473  goto basic_json_parser_4;
7474  }
7475  goto basic_json_parser_25;
7476  }
7477  }
7478  else
7479  {
7480  if (yych <= '|')
7481  {
7482  if (yych == '{')
7483  {
7484  goto basic_json_parser_26;
7485  }
7486  goto basic_json_parser_4;
7487  }
7488  else
7489  {
7490  if (yych <= '}')
7491  {
7492  goto basic_json_parser_28;
7493  }
7494  if (yych == 0xEF)
7495  {
7496  goto basic_json_parser_30;
7497  }
7498  goto basic_json_parser_4;
7499  }
7500  }
7501  }
7502 basic_json_parser_2:
7503  ++m_cursor;
7504  {
7505  return token_type::end_of_input;
7506  }
7507 basic_json_parser_4:
7508  ++m_cursor;
7509 basic_json_parser_5:
7510  {
7511  return token_type::parse_error;
7512  }
7513 basic_json_parser_6:
7514  ++m_cursor;
7515  if (m_limit <= m_cursor)
7516  {
7517  yyfill(); // LCOV_EXCL_LINE;
7518  }
7519  yych = *m_cursor;
7520  if (yybm[0 + yych] & 32)
7521  {
7522  goto basic_json_parser_6;
7523  }
7524  {
7525  return scan();
7526  }
7527 basic_json_parser_9:
7528  yyaccept = 0;
7529  yych = *(m_marker = ++m_cursor);
7530  if (yych <= 0x0F)
7531  {
7532  goto basic_json_parser_5;
7533  }
7534  goto basic_json_parser_32;
7535 basic_json_parser_10:
7536  ++m_cursor;
7537  {
7538  return token_type::value_separator;
7539  }
7540 basic_json_parser_12:
7541  yych = *++m_cursor;
7542  if (yych <= '/')
7543  {
7544  goto basic_json_parser_5;
7545  }
7546  if (yych <= '0')
7547  {
7548  goto basic_json_parser_13;
7549  }
7550  if (yych <= '9')
7551  {
7552  goto basic_json_parser_15;
7553  }
7554  goto basic_json_parser_5;
7555 basic_json_parser_13:
7556  yyaccept = 1;
7557  yych = *(m_marker = ++m_cursor);
7558  if (yych <= 'D')
7559  {
7560  if (yych == '.')
7561  {
7562  goto basic_json_parser_37;
7563  }
7564  }
7565  else
7566  {
7567  if (yych <= 'E')
7568  {
7569  goto basic_json_parser_38;
7570  }
7571  if (yych == 'e')
7572  {
7573  goto basic_json_parser_38;
7574  }
7575  }
7576 basic_json_parser_14:
7577  {
7578  return token_type::value_number;
7579  }
7580 basic_json_parser_15:
7581  yyaccept = 1;
7582  m_marker = ++m_cursor;
7583  if ((m_limit - m_cursor) < 3)
7584  {
7585  yyfill(); // LCOV_EXCL_LINE;
7586  }
7587  yych = *m_cursor;
7588  if (yybm[0 + yych] & 64)
7589  {
7590  goto basic_json_parser_15;
7591  }
7592  if (yych <= 'D')
7593  {
7594  if (yych == '.')
7595  {
7596  goto basic_json_parser_37;
7597  }
7598  goto basic_json_parser_14;
7599  }
7600  else
7601  {
7602  if (yych <= 'E')
7603  {
7604  goto basic_json_parser_38;
7605  }
7606  if (yych == 'e')
7607  {
7608  goto basic_json_parser_38;
7609  }
7610  goto basic_json_parser_14;
7611  }
7612 basic_json_parser_17:
7613  ++m_cursor;
7614  {
7615  return token_type::name_separator;
7616  }
7617 basic_json_parser_19:
7618  ++m_cursor;
7619  {
7620  return token_type::begin_array;
7621  }
7622 basic_json_parser_21:
7623  ++m_cursor;
7624  {
7625  return token_type::end_array;
7626  }
7627 basic_json_parser_23:
7628  yyaccept = 0;
7629  yych = *(m_marker = ++m_cursor);
7630  if (yych == 'a')
7631  {
7632  goto basic_json_parser_39;
7633  }
7634  goto basic_json_parser_5;
7635 basic_json_parser_24:
7636  yyaccept = 0;
7637  yych = *(m_marker = ++m_cursor);
7638  if (yych == 'u')
7639  {
7640  goto basic_json_parser_40;
7641  }
7642  goto basic_json_parser_5;
7643 basic_json_parser_25:
7644  yyaccept = 0;
7645  yych = *(m_marker = ++m_cursor);
7646  if (yych == 'r')
7647  {
7648  goto basic_json_parser_41;
7649  }
7650  goto basic_json_parser_5;
7651 basic_json_parser_26:
7652  ++m_cursor;
7653  {
7654  return token_type::begin_object;
7655  }
7656 basic_json_parser_28:
7657  ++m_cursor;
7658  {
7659  return token_type::end_object;
7660  }
7661 basic_json_parser_30:
7662  yyaccept = 0;
7663  yych = *(m_marker = ++m_cursor);
7664  if (yych == 0xBB)
7665  {
7666  goto basic_json_parser_42;
7667  }
7668  goto basic_json_parser_5;
7669 basic_json_parser_31:
7670  ++m_cursor;
7671  if (m_limit <= m_cursor)
7672  {
7673  yyfill(); // LCOV_EXCL_LINE;
7674  }
7675  yych = *m_cursor;
7676 basic_json_parser_32:
7677  if (yybm[0 + yych] & 128)
7678  {
7679  goto basic_json_parser_31;
7680  }
7681  if (yych <= 0x0F)
7682  {
7683  goto basic_json_parser_33;
7684  }
7685  if (yych <= '"')
7686  {
7687  goto basic_json_parser_34;
7688  }
7689  goto basic_json_parser_36;
7690 basic_json_parser_33:
7691  m_cursor = m_marker;
7692  if (yyaccept == 0)
7693  {
7694  goto basic_json_parser_5;
7695  }
7696  else
7697  {
7698  goto basic_json_parser_14;
7699  }
7700 basic_json_parser_34:
7701  ++m_cursor;
7702  {
7703  return token_type::value_string;
7704  }
7705 basic_json_parser_36:
7706  ++m_cursor;
7707  if (m_limit <= m_cursor)
7708  {
7709  yyfill(); // LCOV_EXCL_LINE;
7710  }
7711  yych = *m_cursor;
7712  if (yych <= 'e')
7713  {
7714  if (yych <= '/')
7715  {
7716  if (yych == '"')
7717  {
7718  goto basic_json_parser_31;
7719  }
7720  if (yych <= '.')
7721  {
7722  goto basic_json_parser_33;
7723  }
7724  goto basic_json_parser_31;
7725  }
7726  else
7727  {
7728  if (yych <= '\\')
7729  {
7730  if (yych <= '[')
7731  {
7732  goto basic_json_parser_33;
7733  }
7734  goto basic_json_parser_31;
7735  }
7736  else
7737  {
7738  if (yych == 'b')
7739  {
7740  goto basic_json_parser_31;
7741  }
7742  goto basic_json_parser_33;
7743  }
7744  }
7745  }
7746  else
7747  {
7748  if (yych <= 'q')
7749  {
7750  if (yych <= 'f')
7751  {
7752  goto basic_json_parser_31;
7753  }
7754  if (yych == 'n')
7755  {
7756  goto basic_json_parser_31;
7757  }
7758  goto basic_json_parser_33;
7759  }
7760  else
7761  {
7762  if (yych <= 's')
7763  {
7764  if (yych <= 'r')
7765  {
7766  goto basic_json_parser_31;
7767  }
7768  goto basic_json_parser_33;
7769  }
7770  else
7771  {
7772  if (yych <= 't')
7773  {
7774  goto basic_json_parser_31;
7775  }
7776  if (yych <= 'u')
7777  {
7778  goto basic_json_parser_43;
7779  }
7780  goto basic_json_parser_33;
7781  }
7782  }
7783  }
7784 basic_json_parser_37:
7785  yych = *++m_cursor;
7786  if (yych <= '/')
7787  {
7788  goto basic_json_parser_33;
7789  }
7790  if (yych <= '9')
7791  {
7792  goto basic_json_parser_44;
7793  }
7794  goto basic_json_parser_33;
7795 basic_json_parser_38:
7796  yych = *++m_cursor;
7797  if (yych <= ',')
7798  {
7799  if (yych == '+')
7800  {
7801  goto basic_json_parser_46;
7802  }
7803  goto basic_json_parser_33;
7804  }
7805  else
7806  {
7807  if (yych <= '-')
7808  {
7809  goto basic_json_parser_46;
7810  }
7811  if (yych <= '/')
7812  {
7813  goto basic_json_parser_33;
7814  }
7815  if (yych <= '9')
7816  {
7817  goto basic_json_parser_47;
7818  }
7819  goto basic_json_parser_33;
7820  }
7821 basic_json_parser_39:
7822  yych = *++m_cursor;
7823  if (yych == 'l')
7824  {
7825  goto basic_json_parser_49;
7826  }
7827  goto basic_json_parser_33;
7828 basic_json_parser_40:
7829  yych = *++m_cursor;
7830  if (yych == 'l')
7831  {
7832  goto basic_json_parser_50;
7833  }
7834  goto basic_json_parser_33;
7835 basic_json_parser_41:
7836  yych = *++m_cursor;
7837  if (yych == 'u')
7838  {
7839  goto basic_json_parser_51;
7840  }
7841  goto basic_json_parser_33;
7842 basic_json_parser_42:
7843  yych = *++m_cursor;
7844  if (yych == 0xBF)
7845  {
7846  goto basic_json_parser_52;
7847  }
7848  goto basic_json_parser_33;
7849 basic_json_parser_43:
7850  ++m_cursor;
7851  if (m_limit <= m_cursor)
7852  {
7853  yyfill(); // LCOV_EXCL_LINE;
7854  }
7855  yych = *m_cursor;
7856  if (yych <= '@')
7857  {
7858  if (yych <= '/')
7859  {
7860  goto basic_json_parser_33;
7861  }
7862  if (yych <= '9')
7863  {
7864  goto basic_json_parser_54;
7865  }
7866  goto basic_json_parser_33;
7867  }
7868  else
7869  {
7870  if (yych <= 'F')
7871  {
7872  goto basic_json_parser_54;
7873  }
7874  if (yych <= '`')
7875  {
7876  goto basic_json_parser_33;
7877  }
7878  if (yych <= 'f')
7879  {
7880  goto basic_json_parser_54;
7881  }
7882  goto basic_json_parser_33;
7883  }
7884 basic_json_parser_44:
7885  yyaccept = 1;
7886  m_marker = ++m_cursor;
7887  if ((m_limit - m_cursor) < 3)
7888  {
7889  yyfill(); // LCOV_EXCL_LINE;
7890  }
7891  yych = *m_cursor;
7892  if (yych <= 'D')
7893  {
7894  if (yych <= '/')
7895  {
7896  goto basic_json_parser_14;
7897  }
7898  if (yych <= '9')
7899  {
7900  goto basic_json_parser_44;
7901  }
7902  goto basic_json_parser_14;
7903  }
7904  else
7905  {
7906  if (yych <= 'E')
7907  {
7908  goto basic_json_parser_38;
7909  }
7910  if (yych == 'e')
7911  {
7912  goto basic_json_parser_38;
7913  }
7914  goto basic_json_parser_14;
7915  }
7916 basic_json_parser_46:
7917  yych = *++m_cursor;
7918  if (yych <= '/')
7919  {
7920  goto basic_json_parser_33;
7921  }
7922  if (yych >= ':')
7923  {
7924  goto basic_json_parser_33;
7925  }
7926 basic_json_parser_47:
7927  ++m_cursor;
7928  if (m_limit <= m_cursor)
7929  {
7930  yyfill(); // LCOV_EXCL_LINE;
7931  }
7932  yych = *m_cursor;
7933  if (yych <= '/')
7934  {
7935  goto basic_json_parser_14;
7936  }
7937  if (yych <= '9')
7938  {
7939  goto basic_json_parser_47;
7940  }
7941  goto basic_json_parser_14;
7942 basic_json_parser_49:
7943  yych = *++m_cursor;
7944  if (yych == 's')
7945  {
7946  goto basic_json_parser_55;
7947  }
7948  goto basic_json_parser_33;
7949 basic_json_parser_50:
7950  yych = *++m_cursor;
7951  if (yych == 'l')
7952  {
7953  goto basic_json_parser_56;
7954  }
7955  goto basic_json_parser_33;
7956 basic_json_parser_51:
7957  yych = *++m_cursor;
7958  if (yych == 'e')
7959  {
7960  goto basic_json_parser_58;
7961  }
7962  goto basic_json_parser_33;
7963 basic_json_parser_52:
7964  ++m_cursor;
7965  {
7966  return scan();
7967  }
7968 basic_json_parser_54:
7969  ++m_cursor;
7970  if (m_limit <= m_cursor)
7971  {
7972  yyfill(); // LCOV_EXCL_LINE;
7973  }
7974  yych = *m_cursor;
7975  if (yych <= '@')
7976  {
7977  if (yych <= '/')
7978  {
7979  goto basic_json_parser_33;
7980  }
7981  if (yych <= '9')
7982  {
7983  goto basic_json_parser_60;
7984  }
7985  goto basic_json_parser_33;
7986  }
7987  else
7988  {
7989  if (yych <= 'F')
7990  {
7991  goto basic_json_parser_60;
7992  }
7993  if (yych <= '`')
7994  {
7995  goto basic_json_parser_33;
7996  }
7997  if (yych <= 'f')
7998  {
7999  goto basic_json_parser_60;
8000  }
8001  goto basic_json_parser_33;
8002  }
8003 basic_json_parser_55:
8004  yych = *++m_cursor;
8005  if (yych == 'e')
8006  {
8007  goto basic_json_parser_61;
8008  }
8009  goto basic_json_parser_33;
8010 basic_json_parser_56:
8011  ++m_cursor;
8012  {
8013  return token_type::literal_null;
8014  }
8015 basic_json_parser_58:
8016  ++m_cursor;
8017  {
8018  return token_type::literal_true;
8019  }
8020 basic_json_parser_60:
8021  ++m_cursor;
8022  if (m_limit <= m_cursor)
8023  {
8024  yyfill(); // LCOV_EXCL_LINE;
8025  }
8026  yych = *m_cursor;
8027  if (yych <= '@')
8028  {
8029  if (yych <= '/')
8030  {
8031  goto basic_json_parser_33;
8032  }
8033  if (yych <= '9')
8034  {
8035  goto basic_json_parser_63;
8036  }
8037  goto basic_json_parser_33;
8038  }
8039  else
8040  {
8041  if (yych <= 'F')
8042  {
8043  goto basic_json_parser_63;
8044  }
8045  if (yych <= '`')
8046  {
8047  goto basic_json_parser_33;
8048  }
8049  if (yych <= 'f')
8050  {
8051  goto basic_json_parser_63;
8052  }
8053  goto basic_json_parser_33;
8054  }
8055 basic_json_parser_61:
8056  ++m_cursor;
8057  {
8058  return token_type::literal_false;
8059  }
8060 basic_json_parser_63:
8061  ++m_cursor;
8062  if (m_limit <= m_cursor)
8063  {
8064  yyfill(); // LCOV_EXCL_LINE;
8065  }
8066  yych = *m_cursor;
8067  if (yych <= '@')
8068  {
8069  if (yych <= '/')
8070  {
8071  goto basic_json_parser_33;
8072  }
8073  if (yych <= '9')
8074  {
8075  goto basic_json_parser_31;
8076  }
8077  goto basic_json_parser_33;
8078  }
8079  else
8080  {
8081  if (yych <= 'F')
8082  {
8083  goto basic_json_parser_31;
8084  }
8085  if (yych <= '`')
8086  {
8087  goto basic_json_parser_33;
8088  }
8089  if (yych <= 'f')
8090  {
8091  goto basic_json_parser_31;
8092  }
8093  goto basic_json_parser_33;
8094  }
8095  }
8096 
8097  }
8098 
8100  void yyfill() noexcept
8101  {
8102  if (m_stream == nullptr or not * m_stream)
8103  {
8104  return;
8105  }
8106 
8107  const auto offset_start = m_start - m_content;
8108  const auto offset_marker = m_marker - m_start;
8109  const auto offset_cursor = m_cursor - m_start;
8110 
8111  m_buffer.erase(0, static_cast<size_t>(offset_start));
8112  std::string line;
8113  assert(m_stream != nullptr);
8114  std::getline(*m_stream, line);
8115  m_buffer += "\n" + line; // add line with newline symbol
8116 
8117  m_content = reinterpret_cast<const lexer_char_t*>(m_buffer.c_str());
8118  assert(m_content != nullptr);
8119  m_start = m_content;
8120  m_marker = m_start + offset_marker;
8121  m_cursor = m_start + offset_cursor;
8122  m_limit = m_start + m_buffer.size() - 1;
8123  }
8124 
8126  string_t get_token() const
8127  {
8128  assert(m_start != nullptr);
8129  return string_t(reinterpret_cast<typename string_t::const_pointer>(m_start),
8130  static_cast<size_t>(m_cursor - m_start));
8131  }
8132 
8155  string_t get_string() const
8156  {
8157  string_t result;
8158  result.reserve(static_cast<size_t>(m_cursor - m_start - 2));
8159 
8160  // iterate the result between the quotes
8161  for (const lexer_char_t* i = m_start + 1; i < m_cursor - 1; ++i)
8162  {
8163  // process escaped characters
8164  if (*i == '\\')
8165  {
8166  // read next character
8167  ++i;
8168 
8169  switch (*i)
8170  {
8171  // the default escapes
8172  case 't':
8173  {
8174  result += "\t";
8175  break;
8176  }
8177  case 'b':
8178  {
8179  result += "\b";
8180  break;
8181  }
8182  case 'f':
8183  {
8184  result += "\f";
8185  break;
8186  }
8187  case 'n':
8188  {
8189  result += "\n";
8190  break;
8191  }
8192  case 'r':
8193  {
8194  result += "\r";
8195  break;
8196  }
8197  case '\\':
8198  {
8199  result += "\\";
8200  break;
8201  }
8202  case '/':
8203  {
8204  result += "/";
8205  break;
8206  }
8207  case '"':
8208  {
8209  result += "\"";
8210  break;
8211  }
8212 
8213  // unicode
8214  case 'u':
8215  {
8216  // get code xxxx from uxxxx
8217  auto codepoint = std::strtoul(std::string(reinterpret_cast<typename string_t::const_pointer>(i + 1),
8218  4).c_str(), nullptr, 16);
8219 
8220  // check if codepoint is a high surrogate
8221  if (codepoint >= 0xD800 and codepoint <= 0xDBFF)
8222  {
8223  // make sure there is a subsequent unicode
8224  if ((i + 6 >= m_limit) or * (i + 5) != '\\' or * (i + 6) != 'u')
8225  {
8226  throw std::invalid_argument("missing low surrogate");
8227  }
8228 
8229  // get code yyyy from uxxxx\uyyyy
8230  auto codepoint2 = std::strtoul(std::string(reinterpret_cast<typename string_t::const_pointer>
8231  (i + 7), 4).c_str(), nullptr, 16);
8232  result += to_unicode(codepoint, codepoint2);
8233  // skip the next 10 characters (xxxx\uyyyy)
8234  i += 10;
8235  }
8236  else
8237  {
8238  // add unicode character(s)
8239  result += to_unicode(codepoint);
8240  // skip the next four characters (xxxx)
8241  i += 4;
8242  }
8243  break;
8244  }
8245  }
8246  }
8247  else
8248  {
8249  // all other characters are just copied to the end of the
8250  // string
8251  result.append(1, static_cast<typename string_t::value_type>(*i));
8252  }
8253  }
8254 
8255  return result;
8256  }
8257 
8278  long double str_to_float_t(long double* /* type */, char** endptr) const
8279  {
8280  return std::strtold(reinterpret_cast<typename string_t::const_pointer>(m_start), endptr);
8281  }
8282 
8298  double str_to_float_t(double* /* type */, char** endptr) const
8299  {
8300  return std::strtod(reinterpret_cast<typename string_t::const_pointer>(m_start), endptr);
8301  }
8302 
8318  float str_to_float_t(float* /* type */, char** endptr) const
8319  {
8320  return std::strtof(reinterpret_cast<typename string_t::const_pointer>(m_start), endptr);
8321  }
8322 
8344  void get_number(basic_json& result) const
8345  {
8346  assert(m_start != nullptr);
8347 
8348  const lexer::lexer_char_t* curptr = m_start;
8349 
8350  // accumulate the integer conversion result (unsigned for now)
8351  number_unsigned_t value = 0;
8352 
8353  // maximum absolute value of the relevant integer type
8354  number_unsigned_t max;
8355 
8356  // temporarily store the type to avoid unecessary bitfield access
8357  value_t type;
8358 
8359  // look for sign
8360  if (*curptr == '-')
8361  {
8362  type = value_t::number_integer;
8363  max = static_cast<uint64_t>((std::numeric_limits<number_integer_t>::max)()) + 1;
8364  curptr++;
8365  }
8366  else
8367  {
8368  type = value_t::number_unsigned;
8369  max = static_cast<uint64_t>((std::numeric_limits<number_unsigned_t>::max)());
8370  }
8371 
8372  // count the significant figures
8373  for (; curptr < m_cursor; curptr++)
8374  {
8375  // quickly skip tests if a digit
8376  if (*curptr < '0' || *curptr > '9')
8377  {
8378  if (*curptr == '.')
8379  {
8380  // don't count '.' but change to float
8381  type = value_t::number_float;
8382  continue;
8383  }
8384  // assume exponent (if not then will fail parse): change to
8385  // float, stop counting and record exponent details
8386  type = value_t::number_float;
8387  break;
8388  }
8389 
8390  // skip if definitely not an integer
8391  if (type != value_t::number_float)
8392  {
8393  // multiply last value by ten and add the new digit
8394  auto temp = value * 10 + *curptr - 0x30;
8395 
8396  // test for overflow
8397  if (temp < value || temp > max)
8398  {
8399  // overflow
8400  type = value_t::number_float;
8401  }
8402  else
8403  {
8404  // no overflow - save it
8405  value = temp;
8406  }
8407  }
8408  }
8409 
8410  // save the value (if not a float)
8411  if (type == value_t::number_unsigned)
8412  {
8413  result.m_value.number_unsigned = value;
8414  }
8415  else if (type == value_t::number_integer)
8416  {
8417  result.m_value.number_integer = -static_cast<number_integer_t>(value);
8418  }
8419  else
8420  {
8421  // parse with strtod
8422  result.m_value.number_float = str_to_float_t(static_cast<number_float_t*>(nullptr), NULL);
8423  }
8424 
8425  // save the type
8426  result.m_type = type;
8427  }
8428 
8429  private:
8431  std::istream* m_stream = nullptr;
8433  string_t m_buffer;
8435  const lexer_char_t* m_content = nullptr;
8437  const lexer_char_t* m_start = nullptr;
8439  const lexer_char_t* m_marker = nullptr;
8441  const lexer_char_t* m_cursor = nullptr;
8443  const lexer_char_t* m_limit = nullptr;
8444  };
8445 
8451  class parser
8452  {
8453  public:
8455  parser(const string_t& s, parser_callback_t cb = nullptr) noexcept
8456  : callback(cb), m_lexer(s)
8457  {
8458  // read first token
8459  get_token();
8460  }
8461 
8463  parser(std::istream& _is, parser_callback_t cb = nullptr) noexcept
8464  : callback(cb), m_lexer(&_is)
8465  {
8466  // read first token
8467  get_token();
8468  }
8469 
8471  basic_json parse()
8472  {
8473  basic_json result = parse_internal(true);
8474 
8475  expect(lexer::token_type::end_of_input);
8476 
8477  // return parser result and replace it with null in case the
8478  // top-level value was discarded by the callback function
8479  return result.is_discarded() ? basic_json() : result;
8480  }
8481 
8482  private:
8484  basic_json parse_internal(bool keep)
8485  {
8486  auto result = basic_json(value_t::discarded);
8487 
8488  switch (last_token)
8489  {
8490  case lexer::token_type::begin_object:
8491  {
8492  if (keep and (not callback or (keep = callback(depth++, parse_event_t::object_start, result))))
8493  {
8494  // explicitly set result to object to cope with {}
8495  result.m_type = value_t::object;
8496  result.m_value = json_value(value_t::object);
8497  }
8498 
8499  // read next token
8500  get_token();
8501 
8502  // closing } -> we are done
8503  if (last_token == lexer::token_type::end_object)
8504  {
8505  get_token();
8506  if (keep and callback and not callback(--depth, parse_event_t::object_end, result))
8507  {
8508  result = basic_json(value_t::discarded);
8509  }
8510  return result;
8511  }
8512 
8513  // no comma is expected here
8514  unexpect(lexer::token_type::value_separator);
8515 
8516  // otherwise: parse key-value pairs
8517  do
8518  {
8519  // ugly, but could be fixed with loop reorganization
8520  if (last_token == lexer::token_type::value_separator)
8521  {
8522  get_token();
8523  }
8524 
8525  // store key
8526  expect(lexer::token_type::value_string);
8527  const auto key = m_lexer.get_string();
8528 
8529  bool keep_tag = false;
8530  if (keep)
8531  {
8532  if (callback)
8533  {
8534  basic_json k(key);
8535  keep_tag = callback(depth, parse_event_t::key, k);
8536  }
8537  else
8538  {
8539  keep_tag = true;
8540  }
8541  }
8542 
8543  // parse separator (:)
8544  get_token();
8545  expect(lexer::token_type::name_separator);
8546 
8547  // parse and add value
8548  get_token();
8549  auto value = parse_internal(keep);
8550  if (keep and keep_tag and not value.is_discarded())
8551  {
8552  result[key] = std::move(value);
8553  }
8554  }
8555  while (last_token == lexer::token_type::value_separator);
8556 
8557  // closing }
8558  expect(lexer::token_type::end_object);
8559  get_token();
8560  if (keep and callback and not callback(--depth, parse_event_t::object_end, result))
8561  {
8562  result = basic_json(value_t::discarded);
8563  }
8564 
8565  return result;
8566  }
8567 
8568  case lexer::token_type::begin_array:
8569  {
8570  if (keep and (not callback or (keep = callback(depth++, parse_event_t::array_start, result))))
8571  {
8572  // explicitly set result to object to cope with []
8573  result.m_type = value_t::array;
8574  result.m_value = json_value(value_t::array);
8575  }
8576 
8577  // read next token
8578  get_token();
8579 
8580  // closing ] -> we are done
8581  if (last_token == lexer::token_type::end_array)
8582  {
8583  get_token();
8584  if (callback and not callback(--depth, parse_event_t::array_end, result))
8585  {
8586  result = basic_json(value_t::discarded);
8587  }
8588  return result;
8589  }
8590 
8591  // no comma is expected here
8592  unexpect(lexer::token_type::value_separator);
8593 
8594  // otherwise: parse values
8595  do
8596  {
8597  // ugly, but could be fixed with loop reorganization
8598  if (last_token == lexer::token_type::value_separator)
8599  {
8600  get_token();
8601  }
8602 
8603  // parse value
8604  auto value = parse_internal(keep);
8605  if (keep and not value.is_discarded())
8606  {
8607  result.push_back(std::move(value));
8608  }
8609  }
8610  while (last_token == lexer::token_type::value_separator);
8611 
8612  // closing ]
8613  expect(lexer::token_type::end_array);
8614  get_token();
8615  if (keep and callback and not callback(--depth, parse_event_t::array_end, result))
8616  {
8617  result = basic_json(value_t::discarded);
8618  }
8619 
8620  return result;
8621  }
8622 
8623  case lexer::token_type::literal_null:
8624  {
8625  get_token();
8626  result.m_type = value_t::null;
8627  break;
8628  }
8629 
8630  case lexer::token_type::value_string:
8631  {
8632  const auto s = m_lexer.get_string();
8633  get_token();
8634  result = basic_json(s);
8635  break;
8636  }
8637 
8638  case lexer::token_type::literal_true:
8639  {
8640  get_token();
8641  result.m_type = value_t::boolean;
8642  result.m_value = true;
8643  break;
8644  }
8645 
8646  case lexer::token_type::literal_false:
8647  {
8648  get_token();
8649  result.m_type = value_t::boolean;
8650  result.m_value = false;
8651  break;
8652  }
8653 
8654  case lexer::token_type::value_number:
8655  {
8656  m_lexer.get_number(result);
8657  get_token();
8658  break;
8659  }
8660 
8661  default:
8662  {
8663  // the last token was unexpected
8664  unexpect(last_token);
8665  }
8666  }
8667 
8668  if (keep and callback and not callback(depth, parse_event_t::value, result))
8669  {
8670  result = basic_json(value_t::discarded);
8671  }
8672  return result;
8673  }
8674 
8676  typename lexer::token_type get_token() noexcept
8677  {
8678  last_token = m_lexer.scan();
8679  return last_token;
8680  }
8681 
8682  void expect(typename lexer::token_type t) const
8683  {
8684  if (t != last_token)
8685  {
8686  std::string error_msg = "parse error - unexpected ";
8687  error_msg += (last_token == lexer::token_type::parse_error ? ("'" + m_lexer.get_token() + "'") :
8688  lexer::token_type_name(last_token));
8689  error_msg += "; expected " + lexer::token_type_name(t);
8690  throw std::invalid_argument(error_msg);
8691  }
8692  }
8693 
8694  void unexpect(typename lexer::token_type t) const
8695  {
8696  if (t == last_token)
8697  {
8698  std::string error_msg = "parse error - unexpected ";
8699  error_msg += (last_token == lexer::token_type::parse_error ? ("'" + m_lexer.get_token() + "'") :
8700  lexer::token_type_name(last_token));
8701  throw std::invalid_argument(error_msg);
8702  }
8703  }
8704 
8705  private:
8707  int depth = 0;
8709  parser_callback_t callback;
8711  typename lexer::token_type last_token = lexer::token_type::uninitialized;
8713  lexer m_lexer;
8714  };
8715 
8716  public:
8729  {
8731  friend class basic_json;
8732 
8733  public:
8756  explicit json_pointer(const std::string& s = "")
8757  : reference_tokens(split(s))
8758  {}
8759 
8775  std::string to_string() const noexcept
8776  {
8777  std::string result;
8778 
8779  for (const auto& reference_token : reference_tokens)
8780  {
8781  result += "/" + escape(reference_token);
8782  }
8783 
8784  return result;
8785  }
8786 
8788  operator std::string() const
8789  {
8790  return to_string();
8791  }
8793  private:
8795  std::string pop_back()
8796  {
8797  if (is_root())
8798  {
8799  throw std::domain_error("JSON pointer has no parent");
8800  }
8801 
8802  auto last = reference_tokens.back();
8803  reference_tokens.pop_back();
8804  return last;
8805  }
8806 
8808  bool is_root() const
8809  {
8810  return reference_tokens.empty();
8811  }
8812 
8813  json_pointer top() const
8814  {
8815  if (is_root())
8816  {
8817  throw std::domain_error("JSON pointer has no parent");
8818  }
8819 
8820  json_pointer result = *this;
8821  result.reference_tokens = {reference_tokens[0]};
8822  return result;
8823  }
8824 
8828  reference get_and_create(reference j) const
8829  {
8830  pointer result = &j;
8831 
8832  // in case no reference tokens exist, return a reference to the
8833  // JSON value j which will be overwritten by a primitive value
8834  for (const auto& reference_token : reference_tokens)
8835  {
8836  switch (result->m_type)
8837  {
8838  case value_t::null:
8839  {
8840  if (reference_token == "0")
8841  {
8842  // start a new array if reference token is 0
8843  result = &result->operator[](0);
8844  }
8845  else
8846  {
8847  // start a new object otherwise
8848  result = &result->operator[](reference_token);
8849  }
8850  break;
8851  }
8852 
8853  case value_t::object:
8854  {
8855  // create an entry in the object
8856  result = &result->operator[](reference_token);
8857  break;
8858  }
8859 
8860  case value_t::array:
8861  {
8862  // create an entry in the array
8863  result = &result->operator[](static_cast<size_type>(std::stoi(reference_token)));
8864  break;
8865  }
8866 
8867  /*
8868  The following code is only reached if there exists a
8869  reference token _and_ the current value is primitive. In
8870  this case, we have an error situation, because primitive
8871  values may only occur as single value; that is, with an
8872  empty list of reference tokens.
8873  */
8874  default:
8875  {
8876  throw std::domain_error("invalid value to unflatten");
8877  }
8878  }
8879  }
8880 
8881  return *result;
8882  }
8883 
8897  reference get_unchecked(pointer ptr) const
8898  {
8899  for (const auto& reference_token : reference_tokens)
8900  {
8901  switch (ptr->m_type)
8902  {
8903  case value_t::object:
8904  {
8905  // use unchecked object access
8906  ptr = &ptr->operator[](reference_token);
8907  break;
8908  }
8909 
8910  case value_t::array:
8911  {
8912  // error condition (cf. RFC 6901, Sect. 4)
8913  if (reference_token.size() > 1 and reference_token[0] == '0')
8914  {
8915  throw std::domain_error("array index must not begin with '0'");
8916  }
8917 
8918  if (reference_token == "-")
8919  {
8920  // explicityly treat "-" as index beyond the end
8921  ptr = &ptr->operator[](ptr->m_value.array->size());
8922  }
8923  else
8924  {
8925  // convert array index to number; unchecked access
8926  ptr = &ptr->operator[](static_cast<size_type>(std::stoi(reference_token)));
8927  }
8928  break;
8929  }
8930 
8931  default:
8932  {
8933  throw std::out_of_range("unresolved reference token '" + reference_token + "'");
8934  }
8935  }
8936  }
8937 
8938  return *ptr;
8939  }
8940 
8941  reference get_checked(pointer ptr) const
8942  {
8943  for (const auto& reference_token : reference_tokens)
8944  {
8945  switch (ptr->m_type)
8946  {
8947  case value_t::object:
8948  {
8949  // note: at performs range check
8950  ptr = &ptr->at(reference_token);
8951  break;
8952  }
8953 
8954  case value_t::array:
8955  {
8956  if (reference_token == "-")
8957  {
8958  // "-" always fails the range check
8959  throw std::out_of_range("array index '-' (" +
8960  std::to_string(ptr->m_value.array->size()) +
8961  ") is out of range");
8962  }
8963 
8964  // error condition (cf. RFC 6901, Sect. 4)
8965  if (reference_token.size() > 1 and reference_token[0] == '0')
8966  {
8967  throw std::domain_error("array index must not begin with '0'");
8968  }
8969 
8970  // note: at performs range check
8971  ptr = &ptr->at(static_cast<size_type>(std::stoi(reference_token)));
8972  break;
8973  }
8974 
8975  default:
8976  {
8977  throw std::out_of_range("unresolved reference token '" + reference_token + "'");
8978  }
8979  }
8980  }
8981 
8982  return *ptr;
8983  }
8984 
8993  const_reference get_unchecked(const_pointer ptr) const
8994  {
8995  for (const auto& reference_token : reference_tokens)
8996  {
8997  switch (ptr->m_type)
8998  {
8999  case value_t::object:
9000  {
9001  // use unchecked object access
9002  ptr = &ptr->operator[](reference_token);
9003  break;
9004  }
9005 
9006  case value_t::array:
9007  {
9008  if (reference_token == "-")
9009  {
9010  // "-" cannot be used for const access
9011  throw std::out_of_range("array index '-' (" +
9012  std::to_string(ptr->m_value.array->size()) +
9013  ") is out of range");
9014  }
9015 
9016  // error condition (cf. RFC 6901, Sect. 4)
9017  if (reference_token.size() > 1 and reference_token[0] == '0')
9018  {
9019  throw std::domain_error("array index must not begin with '0'");
9020  }
9021 
9022  // use unchecked array access
9023  ptr = &ptr->operator[](static_cast<size_type>(std::stoi(reference_token)));
9024  break;
9025  }
9026 
9027  default:
9028  {
9029  throw std::out_of_range("unresolved reference token '" + reference_token + "'");
9030  }
9031  }
9032  }
9033 
9034  return *ptr;
9035  }
9036 
9037  const_reference get_checked(const_pointer ptr) const
9038  {
9039  for (const auto& reference_token : reference_tokens)
9040  {
9041  switch (ptr->m_type)
9042  {
9043  case value_t::object:
9044  {
9045  // note: at performs range check
9046  ptr = &ptr->at(reference_token);
9047  break;
9048  }
9049 
9050  case value_t::array:
9051  {
9052  if (reference_token == "-")
9053  {
9054  // "-" always fails the range check
9055  throw std::out_of_range("array index '-' (" +
9056  std::to_string(ptr->m_value.array->size()) +
9057  ") is out of range");
9058  }
9059 
9060  // error condition (cf. RFC 6901, Sect. 4)
9061  if (reference_token.size() > 1 and reference_token[0] == '0')
9062  {
9063  throw std::domain_error("array index must not begin with '0'");
9064  }
9065 
9066  // note: at performs range check
9067  ptr = &ptr->at(static_cast<size_type>(std::stoi(reference_token)));
9068  break;
9069  }
9070 
9071  default:
9072  {
9073  throw std::out_of_range("unresolved reference token '" + reference_token + "'");
9074  }
9075  }
9076  }
9077 
9078  return *ptr;
9079  }
9080 
9082  static std::vector<std::string> split(std::string reference_string)
9083  {
9084  std::vector<std::string> result;
9085 
9086  // special case: empty reference string -> no reference tokens
9087  if (reference_string.empty())
9088  {
9089  return result;
9090  }
9091 
9092  // check if nonempty reference string begins with slash
9093  if (reference_string[0] != '/')
9094  {
9095  throw std::domain_error("JSON pointer must be empty or begin with '/'");
9096  }
9097 
9098  // extract the reference tokens:
9099  // - slash: position of the last read slash (or end of string)
9100  // - start: position after the previous slash
9101  for (
9102  // search for the first slash after the first character
9103  size_t slash = reference_string.find_first_of("/", 1),
9104  // set the beginning of the first reference token
9105  start = 1;
9106  // we can stop if start == string::npos+1 = 0
9107  start != 0;
9108  // set the beginning of the next reference token
9109  // (will eventually be 0 if slash == std::string::npos)
9110  start = slash + 1,
9111  // find next slash
9112  slash = reference_string.find_first_of("/", start))
9113  {
9114  // use the text between the beginning of the reference token
9115  // (start) and the last slash (slash).
9116  auto reference_token = reference_string.substr(start, slash - start);
9117 
9118  // check reference tokens are properly escaped
9119  for (size_t pos = reference_token.find_first_of("~");
9120  pos != std::string::npos;
9121  pos = reference_token.find_first_of("~", pos + 1))
9122  {
9123  assert(reference_token[pos] == '~');
9124 
9125  // ~ must be followed by 0 or 1
9126  if (pos == reference_token.size() - 1 or
9127  (reference_token[pos + 1] != '0' and
9128  reference_token[pos + 1] != '1'))
9129  {
9130  throw std::domain_error("escape error: '~' must be followed with '0' or '1'");
9131  }
9132  }
9133 
9134  // finally, store the reference token
9135  unescape(reference_token);
9136  result.push_back(reference_token);
9137  }
9138 
9139  return result;
9140  }
9141 
9142  private:
9157  static void replace_substring(std::string& s,
9158  const std::string& f,
9159  const std::string& t)
9160  {
9161  assert(not f.empty());
9162 
9163  for (
9164  size_t pos = s.find(f); // find first occurrence of f
9165  pos != std::string::npos; // make sure f was found
9166  s.replace(pos, f.size(), t), // replace with t
9167  pos = s.find(f, pos + t.size()) // find next occurrence of f
9168  );
9169  }
9170 
9172  static std::string escape(std::string s)
9173  {
9174  // escape "~"" to "~0" and "/" to "~1"
9175  replace_substring(s, "~", "~0");
9176  replace_substring(s, "/", "~1");
9177  return s;
9178  }
9179 
9181  static void unescape(std::string& s)
9182  {
9183  // first transform any occurrence of the sequence '~1' to '/'
9184  replace_substring(s, "~1", "/");
9185  // then transform any occurrence of the sequence '~0' to '~'
9186  replace_substring(s, "~0", "~");
9187  }
9188 
9196  static void flatten(const std::string& reference_string,
9197  const basic_json& value,
9198  basic_json& result)
9199  {
9200  switch (value.m_type)
9201  {
9202  case value_t::array:
9203  {
9204  if (value.m_value.array->empty())
9205  {
9206  // flatten empty array as null
9207  result[reference_string] = nullptr;
9208  }
9209  else
9210  {
9211  // iterate array and use index as reference string
9212  for (size_t i = 0; i < value.m_value.array->size(); ++i)
9213  {
9214  flatten(reference_string + "/" + std::to_string(i),
9215  value.m_value.array->operator[](i), result);
9216  }
9217  }
9218  break;
9219  }
9220 
9221  case value_t::object:
9222  {
9223  if (value.m_value.object->empty())
9224  {
9225  // flatten empty object as null
9226  result[reference_string] = nullptr;
9227  }
9228  else
9229  {
9230  // iterate object and use keys as reference string
9231  for (const auto& element : *value.m_value.object)
9232  {
9233  flatten(reference_string + "/" + escape(element.first),
9234  element.second, result);
9235  }
9236  }
9237  break;
9238  }
9239 
9240  default:
9241  {
9242  // add primitive value with its reference string
9243  result[reference_string] = value;
9244  break;
9245  }
9246  }
9247  }
9248 
9254  static basic_json unflatten(const basic_json& value)
9255  {
9256  if (not value.is_object())
9257  {
9258  throw std::domain_error("only objects can be unflattened");
9259  }
9260 
9261  basic_json result;
9262 
9263  // iterate the JSON object values
9264  for (const auto& element : *value.m_value.object)
9265  {
9266  if (not element.second.is_primitive())
9267  {
9268  throw std::domain_error("values in object must be primitive");
9269  }
9270 
9271  // assign value to reference pointed to by JSON pointer; Note
9272  // that if the JSON pointer is "" (i.e., points to the whole
9273  // value), function get_and_create returns a reference to
9274  // result itself. An assignment will then create a primitive
9275  // value.
9276  json_pointer(element.first).get_and_create(result) = element.second;
9277  }
9278 
9279  return result;
9280  }
9281 
9282  private:
9284  std::vector<std::string> reference_tokens {};
9285  };
9286 
9288  // JSON Pointer support //
9290 
9293 
9327  reference operator[](const json_pointer& ptr)
9328  {
9329  return ptr.get_unchecked(this);
9330  }
9354  const_reference operator[](const json_pointer& ptr) const
9355  {
9356  return ptr.get_unchecked(this);
9357  }
9379  reference at(const json_pointer& ptr)
9380  {
9381  return ptr.get_checked(this);
9382  }
9404  const_reference at(const json_pointer& ptr) const
9405  {
9406  return ptr.get_checked(this);
9407  }
9431  basic_json flatten() const
9432  {
9433  basic_json result(value_t::object);
9434  json_pointer::flatten("", *this, result);
9435  return result;
9436  }
9437 
9465  basic_json unflatten() const
9466  {
9467  return json_pointer::unflatten(*this);
9468  }
9471 
9473  // JSON Patch functions //
9475 
9478 
9515  basic_json patch(const basic_json& json_patch) const
9516  {
9517  // make a working copy to apply the patch to
9518  basic_json result = *this;
9520  // the valid JSON Patch operations
9521  enum class patch_operations {add, remove, replace, move, copy, test, invalid};
9522 
9523  const auto get_op = [](const std::string op)
9524  {
9525  if (op == "add")
9526  {
9527  return patch_operations::add;
9528  }
9529  if (op == "remove")
9530  {
9531  return patch_operations::remove;
9532  }
9533  if (op == "replace")
9534  {
9535  return patch_operations::replace;
9536  }
9537  if (op == "move")
9538  {
9539  return patch_operations::move;
9540  }
9541  if (op == "copy")
9542  {
9543  return patch_operations::copy;
9544  }
9545  if (op == "test")
9546  {
9547  return patch_operations::test;
9548  }
9549 
9550  return patch_operations::invalid;
9551  };
9552 
9553  // wrapper for "add" operation; add value at ptr
9554  const auto operation_add = [&result](json_pointer & ptr, basic_json val)
9555  {
9556  // adding to the root of the target document means replacing it
9557  if (ptr.is_root())
9558  {
9559  result = val;
9560  }
9561  else
9562  {
9563  // make sure the top element of the pointer exists
9564  json_pointer top_pointer = ptr.top();
9565  if (top_pointer != ptr)
9566  {
9567  basic_json& x = result.at(top_pointer);
9568  }
9569 
9570  // get reference to parent of JSON pointer ptr
9571  const auto last_path = ptr.pop_back();
9572  basic_json& parent = result[ptr];
9573 
9574  switch (parent.m_type)
9575  {
9576  case value_t::null:
9577  case value_t::object:
9578  {
9579  // use operator[] to add value
9580  parent[last_path] = val;
9581  break;
9582  }
9583 
9584  case value_t::array:
9585  {
9586  if (last_path == "-")
9587  {
9588  // special case: append to back
9589  parent.push_back(val);
9590  }
9591  else
9592  {
9593  const auto idx = std::stoi(last_path);
9594  if (static_cast<size_type>(idx) > parent.size())
9595  {
9596  // avoid undefined behavior
9597  throw std::out_of_range("array index " + std::to_string(idx) + " is out of range");
9598  }
9599  else
9600  {
9601  // default case: insert add offset
9602  parent.insert(parent.begin() + static_cast<difference_type>(idx), val);
9603  }
9604  }
9605  break;
9606  }
9607 
9608  default:
9609  {
9610  // if there exists a parent it cannot be primitive
9611  assert(false); // LCOV_EXCL_LINE
9612  }
9613  }
9614  }
9615  };
9616 
9617  // wrapper for "remove" operation; remove value at ptr
9618  const auto operation_remove = [&result](json_pointer & ptr)
9619  {
9620  // get reference to parent of JSON pointer ptr
9621  const auto last_path = ptr.pop_back();
9622  basic_json& parent = result.at(ptr);
9623 
9624  // remove child
9625  if (parent.is_object())
9626  {
9627  // perform range check
9628  auto it = parent.find(last_path);
9629  if (it != parent.end())
9630  {
9631  parent.erase(it);
9632  }
9633  else
9634  {
9635  throw std::out_of_range("key '" + last_path + "' not found");
9636  }
9637  }
9638  else if (parent.is_array())
9639  {
9640  // note erase performs range check
9641  parent.erase(static_cast<size_type>(std::stoi(last_path)));
9642  }
9643  };
9644 
9645  // type check
9646  if (not json_patch.is_array())
9647  {
9648  // a JSON patch must be an array of objects
9649  throw std::invalid_argument("JSON patch must be an array of objects");
9650  }
9651 
9652  // iterate and apply th eoperations
9653  for (const auto& val : json_patch)
9654  {
9655  // wrapper to get a value for an operation
9656  const auto get_value = [&val](const std::string & op,
9657  const std::string & member,
9658  bool string_type) -> basic_json&
9659  {
9660  // find value
9661  auto it = val.m_value.object->find(member);
9662 
9663  // context-sensitive error message
9664  const auto error_msg = (op == "op") ? "operation" : "operation '" + op + "'";
9665 
9666  // check if desired value is present
9667  if (it == val.m_value.object->end())
9668  {
9669  throw std::invalid_argument(error_msg + " must have member '" + member + "'");
9670  }
9671 
9672  // check if result is of type string
9673  if (string_type and not it->second.is_string())
9674  {
9675  throw std::invalid_argument(error_msg + " must have string member '" + member + "'");
9676  }
9677 
9678  // no error: return value
9679  return it->second;
9680  };
9681 
9682  // type check
9683  if (not val.is_object())
9684  {
9685  throw std::invalid_argument("JSON patch must be an array of objects");
9686  }
9687 
9688  // collect mandatory members
9689  const std::string op = get_value("op", "op", true);
9690  const std::string path = get_value(op, "path", true);
9691  json_pointer ptr(path);
9692 
9693  switch (get_op(op))
9694  {
9695  case patch_operations::add:
9696  {
9697  operation_add(ptr, get_value("add", "value", false));
9698  break;
9699  }
9700 
9701  case patch_operations::remove:
9702  {
9703  operation_remove(ptr);
9704  break;
9705  }
9706 
9707  case patch_operations::replace:
9708  {
9709  // the "path" location must exist - use at()
9710  result.at(ptr) = get_value("replace", "value", false);
9711  break;
9712  }
9713 
9714  case patch_operations::move:
9715  {
9716  const std::string from_path = get_value("move", "from", true);
9717  json_pointer from_ptr(from_path);
9718 
9719  // the "from" location must exist - use at()
9720  basic_json v = result.at(from_ptr);
9721 
9722  // The move operation is functionally identical to a
9723  // "remove" operation on the "from" location, followed
9724  // immediately by an "add" operation at the target
9725  // location with the value that was just removed.
9726  operation_remove(from_ptr);
9727  operation_add(ptr, v);
9728  break;
9729  }
9730 
9731  case patch_operations::copy:
9732  {
9733  const std::string from_path = get_value("copy", "from", true);;
9734  const json_pointer from_ptr(from_path);
9735 
9736  // the "from" location must exist - use at()
9737  result[ptr] = result.at(from_ptr);
9738  break;
9739  }
9740 
9741  case patch_operations::test:
9742  {
9743  bool success = false;
9744  try
9745  {
9746  // check if "value" matches the one at "path"
9747  // the "path" location must exist - use at()
9748  success = (result.at(ptr) == get_value("test", "value", false));
9749  }
9750  catch (std::out_of_range&)
9751  {
9752  // ignore out of range errors: success remains false
9753  }
9754 
9755  // throw an exception if test fails
9756  if (not success)
9757  {
9758  throw std::domain_error("unsuccessful: " + val.dump());
9759  }
9760 
9761  break;
9762  }
9763 
9764  case patch_operations::invalid:
9765  {
9766  // op must be "add", "remove", "replace", "move", "copy", or
9767  // "test"
9768  throw std::invalid_argument("operation value '" + op + "' is invalid");
9769  }
9770  }
9771  }
9772 
9773  return result;
9774  }
9775 
9808  static basic_json diff(const basic_json& source,
9809  const basic_json& target,
9810  std::string path = "")
9811  {
9812  // the patch
9813  basic_json result(value_t::array);
9814 
9815  // if the values are the same, return empty patch
9816  if (source == target)
9817  {
9818  return result;
9819  }
9820 
9821  if (source.type() != target.type())
9822  {
9823  // different types: replace value
9824  result.push_back(
9825  {
9826  {"op", "replace"},
9827  {"path", path},
9828  {"value", target}
9829  });
9830  }
9831  else
9832  {
9833  switch (source.type())
9834  {
9835  case value_t::array:
9836  {
9837  // first pass: traverse common elements
9838  size_t i = 0;
9839  while (i < source.size() and i < target.size())
9840  {
9841  // recursive call to compare array values at index i
9842  auto temp_diff = diff(source[i], target[i], path + "/" + std::to_string(i));
9843  result.insert(result.end(), temp_diff.begin(), temp_diff.end());
9844  ++i;
9845  }
9846 
9847  // i now reached the end of at least one array
9848  // in a second pass, traverse the remaining elements
9849 
9850  // remove my remaining elements
9851  const auto end_index = static_cast<difference_type>(result.size());
9852  while (i < source.size())
9853  {
9854  // add operations in reverse order to avoid invalid
9855  // indices
9856  result.insert(result.begin() + end_index, object(
9857  {
9858  {"op", "remove"},
9859  {"path", path + "/" + std::to_string(i)}
9860  }));
9861  ++i;
9862  }
9863 
9864  // add other remaining elements
9865  while (i < target.size())
9866  {
9867  result.push_back(
9868  {
9869  {"op", "add"},
9870  {"path", path + "/" + std::to_string(i)},
9871  {"value", target[i]}
9872  });
9873  ++i;
9874  }
9875 
9876  break;
9877  }
9878 
9879  case value_t::object:
9880  {
9881  // first pass: traverse this object's elements
9882  for (auto it = source.begin(); it != source.end(); ++it)
9883  {
9884  // escape the key name to be used in a JSON patch
9885  const auto key = json_pointer::escape(it.key());
9886 
9887  if (target.find(it.key()) != target.end())
9888  {
9889  // recursive call to compare object values at key it
9890  auto temp_diff = diff(it.value(), target[it.key()], path + "/" + key);
9891  result.insert(result.end(), temp_diff.begin(), temp_diff.end());
9892  }
9893  else
9894  {
9895  // found a key that is not in o -> remove it
9896  result.push_back(object(
9897  {
9898  {"op", "remove"},
9899  {"path", path + "/" + key}
9900  }));
9901  }
9902  }
9903 
9904  // second pass: traverse other object's elements
9905  for (auto it = target.begin(); it != target.end(); ++it)
9906  {
9907  if (source.find(it.key()) == source.end())
9908  {
9909  // found a key that is not in this -> add it
9910  const auto key = json_pointer::escape(it.key());
9911  result.push_back(
9912  {
9913  {"op", "add"},
9914  {"path", path + "/" + key},
9915  {"value", it.value()}
9916  });
9917  }
9918  }
9919 
9920  break;
9921  }
9922 
9923  default:
9924  {
9925  // both primitive type: replace value
9926  result.push_back(
9927  {
9928  {"op", "replace"},
9929  {"path", path},
9930  {"value", target}
9931  });
9932  break;
9933  }
9934  }
9935  }
9936 
9937  return result;
9938  }
9939 
9941 };
9942 
9943 
9945 // presets //
9947 
9956 using json = basic_json<>;
9957 }
9958 
9959 
9961 // nonmember support //
9963 
9964 // specialization of std::swap, and std::hash
9965 namespace std
9966 {
9972 template <>
9973 inline void swap(nlohmann::json& j1,
9974  nlohmann::json& j2) noexcept(
9975  is_nothrow_move_constructible<nlohmann::json>::value and
9976  is_nothrow_move_assignable<nlohmann::json>::value
9977  )
9978 {
9979  j1.swap(j2);
9980 }
9981 
9983 template <>
9984 struct hash<nlohmann::json>
9985 {
9991  std::size_t operator()(const nlohmann::json& j) const
9992  {
9993  // a naive hashing via the string representation
9994  const auto& h = hash<nlohmann::json::string_t>();
9995  return h(j.dump());
9996  }
9997 };
9998 }
9999 
10012 inline nlohmann::json operator "" _json(const char* s, std::size_t)
10013 {
10014  return nlohmann::json::parse(reinterpret_cast<const nlohmann::json::string_t::value_type*>(s));
10015 }
10016 
10022 inline nlohmann::json::json_pointer operator "" _json_pointer(const char* s, std::size_t)
10023 {
10024  return nlohmann::json::json_pointer(s);
10025 }
10026 
10027 // restore GCC/clang diagnostic settings
10028 #if defined(__clang__) || defined(__GNUC__) || defined(__GNUG__)
10029  #pragma GCC diagnostic pop
10030 #endif
10031 
10032 #endif
const_iterator(pointer object) noexcept
constructor for a given JSON instance
Definition: json.hpp:6380
friend bool operator<=(const_reference lhs, const_reference rhs) noexcept
comparison: less than or equal
Definition: json.hpp:5569
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:4079
const_reference operator[](size_type idx) const
access specified array element
Definition: json.hpp:3270
reference value() const
return the value of an iterator
Definition: json.hpp:7020
json_reverse_iterator & operator--()
pre-decrement (–it)
Definition: json.hpp:7082
void clear() noexcept
clears the contents
Definition: json.hpp:4630
bool operator==(const const_iterator &other) const
comparison: equal
Definition: json.hpp:6670
json_reverse_iterator operator--(int)
post-decrement (it–)
Definition: json.hpp:7076
reference operator[](T *(&key)[n])
access specified object element
Definition: json.hpp:3402
friend std::istream & operator>>(std::istream &i, basic_json &j)
deserialize from stream
Definition: json.hpp:5782
constexpr bool is_number_float() const noexcept
return whether value is a floating-point number
Definition: json.hpp:2347
const_reverse_iterator rend() const noexcept
returns a const reverse iterator to one before the first
Definition: json.hpp:4306
iterator & operator+=(difference_type i)
add to iterator
Definition: json.hpp:6978
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
const_iterator operator-(difference_type i)
subtract from iterator
Definition: json.hpp:6796
BooleanType boolean_t
a type for a boolean
Definition: json.hpp:467
const_iterator cbegin() const noexcept
returns a const iterator to the first element
Definition: json.hpp:4160
reference operator+=(const typename object_t::value_type &val)
add an object to an object
Definition: json.hpp:4816
reference operator*() const
return a reference to the value pointed to by the iterator
Definition: json.hpp:6936
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:7118
iterator find(typename object_t::key_type key)
find an element in a JSON object
Definition: json.hpp:4031
friend bool operator!=(const_reference lhs, const_reference rhs) noexcept
comparison: not equal
Definition: json.hpp:5407
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:4742
void erase(const size_type idx)
remove element from a JSON array given an index
Definition: json.hpp:3984
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:3641
void swap(object_t &other)
exchanges the values
Definition: json.hpp:5163
json_reverse_iterator operator-(difference_type i) const
subtract from iterator
Definition: json.hpp:7104
const_iterator & operator+=(difference_type i)
add to iterator
Definition: json.hpp:6754
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:7131
friend bool operator==(std::nullptr_t, const_reference v) noexcept
comparison: equal
Definition: json.hpp:5386
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:4948
const_reference at(const typename object_t::key_type &key) const
access specified object element with bounds checking
Definition: json.hpp:3177
const_iterator operator+(difference_type i)
add to iterator
Definition: json.hpp:6788
constexpr bool is_object() const noexcept
return whether value is an object
Definition: json.hpp:2369
constexpr bool is_number_integer() const noexcept
return whether value is an integer number
Definition: json.hpp:2291
a mutable random access iterator for the basic_json class
Definition: json.hpp:6903
static basic_json parse(std::istream &&i, parser_callback_t cb=nullptr)
deserialize from stream
Definition: json.hpp:5744
const_iterator operator++(int)
post-increment (it++)
Definition: json.hpp:6596
const_iterator cend() const noexcept
returns a const iterator to one past the last element
Definition: json.hpp:4231
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:4393
reference & operator=(basic_json other) noexcept( std::is_nothrow_move_constructible< value_t >::value and std::is_nothrow_move_assignable< value_t >::value and std::is_nothrow_move_constructible< json_value >::value and std::is_nothrow_move_assignable< json_value >::value )
copy assignment
Definition: json.hpp:2000
constexpr value_t type() const noexcept
return the type of the JSON value (explicit)
Definition: json.hpp:2131
typename basic_json::value_type value_type
the type of the values when the iterator is dereferenced
Definition: json.hpp:6366
json_reverse_iterator(const typename base_iterator::iterator_type &it) noexcept
create reverse iterator from iterator
Definition: json.hpp:7053
PointerType get_ptr() noexcept
get a pointer value (implicit)
Definition: json.hpp:2891
constexpr bool is_string() const noexcept
return whether value is a string
Definition: json.hpp:2413
reference back()
access the last element
Definition: json.hpp:3683
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:6370
void push_back(const typename object_t::value_type &val)
add an object to an object
Definition: json.hpp:4792
void push_back(std::initializer_list< basic_json > init)
add an object to an object
Definition: json.hpp:4847
json_pointer(const std::string &s="")
create JSON pointer
Definition: json.hpp:8756
static basic_json parse(const string_t &s, parser_callback_t cb=nullptr)
deserialize from string
Definition: json.hpp:5707
const_reference operator[](T *(&key)[n]) const
read-only access specified object element
Definition: json.hpp:3437
iterator insert(const_iterator pos, const_iterator first, const_iterator last)
inserts elements
Definition: json.hpp:5001
basic_json(std::nullptr_t) noexcept
create a null object (explicitly)
Definition: json.hpp:1019
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:7014
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:3359
const_reference operator[](T *key) const
read-only access specified object element
Definition: json.hpp:3519
json_reverse_iterator operator+(difference_type i) const
add to iterator
Definition: json.hpp:7096
bool empty() const noexcept
checks whether the container is empty
Definition: json.hpp:4441
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:7124
const_iterator(const iterator &other) noexcept
copy constructor given a nonconst iterator
Definition: json.hpp:6408
basic_json(const CompatibleArrayType &val)
create an array (implicit)
Definition: json.hpp:1144
constexpr bool is_boolean() const noexcept
return whether value is a boolean
Definition: json.hpp:2232
const_reference at(size_type idx) const
access specified array element with bounds checking
Definition: json.hpp:3081
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:7048
const_reverse_iterator crbegin() const noexcept
returns a const reverse iterator to the last element
Definition: json.hpp:4335
iterator insert(const_iterator pos, std::initializer_list< basic_json > ilist)
inserts elements
Definition: json.hpp:5060
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:4892
friend bool operator>=(const_reference lhs, const_reference rhs) noexcept
comparison: greater than or equal
Definition: json.hpp:5613
friend bool operator<(const_reference lhs, const_reference rhs) noexcept
comparison: less than
Definition: json.hpp:5468
iterator & operator++()
pre-increment (++it)
Definition: json.hpp:6956
bool operator<(const const_iterator &other) const
comparison: smaller
Definition: json.hpp:6706
iterator operator++(int)
post-increment (it++)
Definition: json.hpp:6948
basic_json(basic_json &&other) noexcept
move constructor
Definition: json.hpp:1968
const_iterator operator--(int)
post-decrement (it–)
Definition: json.hpp:6633
reference at(const typename object_t::key_type &key)
access specified object element with bounds checking
Definition: json.hpp:3129
iterator & operator=(iterator other) noexcept( std::is_nothrow_move_constructible< pointer >::value and std::is_nothrow_move_assignable< pointer >::value and std::is_nothrow_move_constructible< internal_iterator >::value and std::is_nothrow_move_assignable< internal_iterator >::value )
copy assignment
Definition: json.hpp:6924
object (unordered set of name/value pairs)
size_type max_size() const noexcept
returns the maximum possible number of elements
Definition: json.hpp:4571
~basic_json()
destructor
Definition: json.hpp:2028
iterator operator--(int)
post-decrement (it–)
Definition: json.hpp:6963
iterator operator-(difference_type i)
subtract from iterator
Definition: json.hpp:7000
const_iterator & operator--()
pre-decrement (–it)
Definition: json.hpp:6641
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:4766
reference operator+=(std::initializer_list< basic_json > init)
add an object to an object
Definition: json.hpp:4864
difference_type operator-(const const_iterator &other) const
return difference
Definition: json.hpp:6804
value_type & reference
the type of an element reference
Definition: json.hpp:216
const_reverse_iterator rbegin() const noexcept
returns a const reverse iterator to the last element
Definition: json.hpp:4269
friend std::ostream & operator>>(const basic_json &j, std::ostream &o)
serialize to stream
Definition: json.hpp:5668
constexpr bool is_discarded() const noexcept
return whether value is discarded
Definition: json.hpp:2440
const_iterator begin() const noexcept
returns a const iterator to the first element
Definition: json.hpp:4130
difference_type operator-(const iterator &other) const
return difference
Definition: json.hpp:7008
constexpr bool is_array() const noexcept
return whether value is an array
Definition: json.hpp:2391
iterator(const iterator &other) noexcept
copy constructor
Definition: json.hpp:6919
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:6368
void swap(string_t &other)
exchanges the values
Definition: json.hpp:5197
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:3649
bool operator>(const const_iterator &other) const
comparison: greater than
Definition: json.hpp:6742
constexpr const PointerType get_ptr() const noexcept
get a pointer value (implicit)
Definition: json.hpp:2906
pointer operator->() const
dereference the iterator
Definition: json.hpp:6561
NumberFloatType number_float_t
a type for a number (floating-point)
Definition: json.hpp:679
const_reverse_iterator crend() const noexcept
returns a const reverse iterator to one before the first
Definition: json.hpp:4364
void swap(reference other) noexcept( std::is_nothrow_move_constructible< value_t >::value and std::is_nothrow_move_assignable< value_t >::value and std::is_nothrow_move_constructible< json_value >::value and std::is_nothrow_move_assignable< json_value >::value )
exchanges the values
Definition: json.hpp:5098
value_t
the JSON type enumeration
Definition: json.hpp:698
reverse_iterator rbegin() noexcept
returns an iterator to the reverse-beginning
Definition: json.hpp:4261
constexpr bool is_null() const noexcept
return whether value is null
Definition: json.hpp:2210
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:2807
void swap(array_t &other)
exchanges the values
Definition: json.hpp:5129
InteratorType erase(InteratorType first, InteratorType last)
remove elements given an iterator range
Definition: json.hpp:3859
ValueType value(const typename object_t::key_type &key, ValueType default_value) const
access specified object element with default value
Definition: json.hpp:3586
typename Base::reference reference
the reference type for the pointed-to element
Definition: json.hpp:7050
const_reference back() const
access the last element
Definition: json.hpp:3693
void push_back(basic_json &&val)
add an object to an array
Definition: json.hpp:4706
array (ordered collection of values)
constexpr bool is_number_unsigned() const noexcept
return whether value is an unsigned integer number
Definition: json.hpp:2319
json_reverse_iterator & operator++()
pre-increment (++it)
Definition: json.hpp:7069
static basic_json parse(std::istream &i, parser_callback_t cb=nullptr)
deserialize from stream
Definition: json.hpp:5736
friend bool operator==(const_reference lhs, const_reference rhs) noexcept
comparison: equal
Definition: json.hpp:5278
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:3612
ReferenceType get_ref() const
get a reference value (implicit)
Definition: json.hpp:2957
basic_json(const CompatibleNumberUnsignedType val) noexcept
create an unsigned number (implicit)
Definition: json.hpp:1404
reference operator*() const
return a reference to the value pointed to by the iterator
Definition: json.hpp:6521
friend bool operator<(const value_t lhs, const value_t rhs) noexcept
comparison operator for JSON types
Definition: json.hpp:5231
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:5430
iterator operator+(difference_type i)
add to iterator
Definition: json.hpp:6992
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:6736
InteratorType erase(InteratorType pos)
remove element given an iterator
Definition: json.hpp:3751
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:6914
friend bool operator!=(std::nullptr_t, const_reference v) noexcept
comparison: not equal
Definition: json.hpp:5439
constexpr bool is_primitive() const noexcept
return whether type is primitive
Definition: json.hpp:2161
const_iterator & operator++()
pre-increment (++it)
Definition: json.hpp:6604
pointer operator->() const
dereference the iterator
Definition: json.hpp:6942
reference value() const
return the value of an iterator
Definition: json.hpp:6879
constexpr bool is_structured() const noexcept
return whether type is structured
Definition: json.hpp:2188
std::bidirectional_iterator_tag iterator_category
the category of the iterator
Definition: json.hpp:6374
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:4191
reverse_iterator rend() noexcept
returns an iterator to the reverse-end
Definition: json.hpp:4298
difference_type operator-(const json_reverse_iterator &other) const
return difference
Definition: json.hpp:7112
const_iterator find(typename object_t::key_type key) const
find an element in a JSON object
Definition: json.hpp:4048
iterator begin() noexcept
returns an iterator to the first element
Definition: json.hpp:4120
basic_json(const CompatibleObjectType &val)
create an object (implicit)
Definition: json.hpp:1077
const_iterator end() const noexcept
returns a const iterator to one past the last element
Definition: json.hpp:4201
friend bool operator>(const_reference lhs, const_reference rhs) noexcept
comparison: greater than
Definition: json.hpp:5591
bool operator>=(const const_iterator &other) const
comparison: greater than or equal
Definition: json.hpp:6748
const_iterator & operator=(const_iterator other) noexcept( std::is_nothrow_move_constructible< pointer >::value and std::is_nothrow_move_assignable< pointer >::value and std::is_nothrow_move_constructible< internal_iterator >::value and std::is_nothrow_move_assignable< internal_iterator >::value )
copy assignment
Definition: json.hpp:6441
size_type erase(const typename object_t::key_type &key)
remove element from a JSON object given a key
Definition: json.hpp:3946
reference operator[](const typename object_t::key_type &key)
access specified object element
Definition: json.hpp:3311
object_t::key_type key() const
return the key of an object iterator
Definition: json.hpp:6864
reference operator+=(basic_json &&val)
add an object to an array
Definition: json.hpp:4732
reference operator[](difference_type n) const
access to successor
Definition: json.hpp:6828
a const random access iterator for the basic_json class
Definition: json.hpp:6359
constexpr bool is_number() const noexcept
return whether value is a number
Definition: json.hpp:2262
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:6372
json_reverse_iterator operator++(int)
post-increment (it++)
Definition: json.hpp:7063
friend bool operator==(const_reference v, std::nullptr_t) noexcept
comparison: equal
Definition: json.hpp:5377
reference operator[](size_type idx)
access specified array element
Definition: json.hpp:3224
bool operator!=(const const_iterator &other) const
comparison: not equal
Definition: json.hpp:6700
json_reverse_iterator & operator+=(difference_type i)
add to iterator
Definition: json.hpp:7089
reference at(size_type idx)
access specified array element with bounds checking
Definition: json.hpp:3037
size_type size() const noexcept
returns the number of elements
Definition: json.hpp:4505
static iteration_proxy< iterator > iterator_wrapper(reference cont)
wrapper to access iterator member functions in range-based for
Definition: json.hpp:4385
iterator & operator-=(difference_type i)
subtract from iterator
Definition: json.hpp:6985
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:5772
json_reverse_iterator(const base_iterator &it) noexcept
create reverse iterator from base class
Definition: json.hpp:7058
friend std::ostream & operator<<(std::ostream &o, const basic_json &j)
serialize to stream
Definition: json.hpp:5650
const_iterator(const const_iterator &other) noexcept
copy constructor
Definition: json.hpp:6436
iterator & operator--()
pre-decrement (–it)
Definition: json.hpp:6971
iterator insert(const_iterator pos, basic_json &&val)
inserts element
Definition: json.hpp:4919
ReferenceType get_ref()
get a reference value (implicit)
Definition: json.hpp:2942
const_iterator & operator-=(difference_type i)
subtract from iterator
Definition: json.hpp:6782
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:3470
parse_event_t
JSON callback events.
Definition: json.hpp:853