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 
343  using object_t = ObjectType<StringType,
344  basic_json,
345  std::less<StringType>,
346  AllocatorType<std::pair<const StringType,
347  basic_json>>>;
348 
393  using array_t = ArrayType<basic_json, AllocatorType<basic_json>>;
394 
440  using string_t = StringType;
441 
466  using boolean_t = BooleanType;
467 
537  using number_integer_t = NumberIntegerType;
538 
609  using number_unsigned_t = NumberUnsignedType;
610 
677  using number_float_t = NumberFloatType;
678 
680 
681 
683  // JSON type enumeration //
685 
696  enum class value_t : uint8_t
697  {
698  null,
699  object,
700  array,
701  string,
702  boolean,
703  number_integer,
704  number_unsigned,
705  number_float,
706  discarded
707  };
708 
709 
710  private:
711 
726  union type_data_t
727  {
728  struct
729  {
731  uint16_t type : 4;
733  uint16_t parsed : 1;
735  uint16_t has_exp : 1;
737  uint16_t exp_plus : 1;
739  uint16_t exp_cap : 1;
741  uint16_t precision : 8;
742  } bits;
743  uint16_t data;
744 
746  operator value_t() const
747  {
748  return static_cast<value_t>(bits.type);
749  }
750 
752  bool operator==(const value_t& rhs) const
753  {
754  return static_cast<value_t>(bits.type) == rhs;
755  }
756 
758  type_data_t& operator=(value_t rhs)
759  {
760  bits.type = static_cast<uint16_t>(rhs);
761  return *this;
762  }
763 
765  type_data_t(value_t t) noexcept
766  {
767  *reinterpret_cast<uint16_t*>(this) = 0;
768  bits.type = static_cast<uint16_t>(t);
769  }
770 
772  type_data_t() noexcept
773  {
774  data = 0;
775  bits.type = reinterpret_cast<uint16_t>(value_t::null);
776  }
777  };
778 
780  template<typename T, typename... Args>
781  static T* create(Args&& ... args)
782  {
783  AllocatorType<T> alloc;
784  auto deleter = [&](T * object)
785  {
786  alloc.deallocate(object, 1);
787  };
788  std::unique_ptr<T, decltype(deleter)> object(alloc.allocate(1), deleter);
789  alloc.construct(object.get(), std::forward<Args>(args)...);
790  return object.release();
791  }
792 
794  // JSON value storage //
796 
804  union json_value
805  {
807  object_t* object;
809  array_t* array;
811  string_t* string;
813  boolean_t boolean;
815  number_integer_t number_integer;
817  number_unsigned_t number_unsigned;
819  number_float_t number_float;
820 
822  json_value() = default;
824  json_value(boolean_t v) noexcept : boolean(v) {}
826  json_value(number_integer_t v) noexcept : number_integer(v) {}
828  json_value(number_unsigned_t v) noexcept : number_unsigned(v) {}
830  json_value(number_float_t v) noexcept : number_float(v) {}
832  json_value(value_t t)
833  {
834  switch (t)
835  {
836  case value_t::object:
837  {
838  object = create<object_t>();
839  break;
840  }
841 
842  case value_t::array:
843  {
844  array = create<array_t>();
845  break;
846  }
847 
848  case value_t::string:
849  {
850  string = create<string_t>("");
851  break;
852  }
853 
854  case value_t::boolean:
855  {
856  boolean = boolean_t(false);
857  break;
858  }
859 
860  case value_t::number_integer:
861  {
862  number_integer = number_integer_t(0);
863  break;
864  }
865 
866  case value_t::number_unsigned:
867  {
868  number_unsigned = number_unsigned_t(0);
869  break;
870  }
871 
872  case value_t::number_float:
873  {
874  number_float = number_float_t(0.0);
875  break;
876  }
877 
878  default:
879  {
880  break;
881  }
882  }
883  }
884 
886  json_value(const string_t& value)
887  {
888  string = create<string_t>(value);
889  }
890 
892  json_value(const object_t& value)
893  {
894  object = create<object_t>(value);
895  }
896 
898  json_value(const array_t& value)
899  {
900  array = create<array_t>(value);
901  }
902  };
903 
904 
905  public:
907  // JSON parser callback //
909 
918  enum class parse_event_t : uint8_t
919  {
921  object_start,
923  object_end,
925  array_start,
927  array_end,
929  key,
931  value
932  };
933 
983  using parser_callback_t = std::function<bool(int depth, parse_event_t event, basic_json& parsed)>;
984 
985 
987  // constructors //
989 
992 
1033  : m_type(value_type), m_value(value_type)
1034  {}
1035 
1060  basic_json() = default;
1061 
1084  basic_json(std::nullptr_t) noexcept
1085  : basic_json(value_t::null)
1086  {}
1087 
1107  basic_json(const object_t& val)
1108  : m_type(value_t::object), m_value(val)
1109  {}
1110 
1137  template <class CompatibleObjectType, typename
1138  std::enable_if<
1139  std::is_constructible<typename object_t::key_type, typename CompatibleObjectType::key_type>::value and
1140  std::is_constructible<basic_json, typename CompatibleObjectType::mapped_type>::value, int>::type
1141  = 0>
1142  basic_json(const CompatibleObjectType& val)
1143  : m_type(value_t::object)
1144  {
1145  using std::begin;
1146  using std::end;
1147  m_value.object = create<object_t>(begin(val), end(val));
1148  }
1149 
1169  basic_json(const array_t& val)
1170  : m_type(value_t::array), m_value(val)
1171  {}
1172 
1199  template <class CompatibleArrayType, typename
1200  std::enable_if<
1201  not std::is_same<CompatibleArrayType, typename basic_json_t::iterator>::value and
1202  not std::is_same<CompatibleArrayType, typename basic_json_t::const_iterator>::value and
1203  not std::is_same<CompatibleArrayType, typename basic_json_t::reverse_iterator>::value and
1204  not std::is_same<CompatibleArrayType, typename basic_json_t::const_reverse_iterator>::value and
1205  not std::is_same<CompatibleArrayType, typename array_t::iterator>::value and
1206  not std::is_same<CompatibleArrayType, typename array_t::const_iterator>::value and
1207  std::is_constructible<basic_json, typename CompatibleArrayType::value_type>::value, int>::type
1208  = 0>
1209  basic_json(const CompatibleArrayType& val)
1210  : m_type(value_t::array)
1211  {
1212  using std::begin;
1213  using std::end;
1214  m_value.array = create<array_t>(begin(val), end(val));
1215  }
1216 
1238  basic_json(const string_t& val)
1239  : m_type(value_t::string), m_value(val)
1240  {}
1241 
1262  basic_json(const typename string_t::value_type* val)
1263  : basic_json(string_t(val))
1264  {}
1265 
1289  template <class CompatibleStringType, typename
1290  std::enable_if<
1291  std::is_constructible<string_t, CompatibleStringType>::value, int>::type
1292  = 0>
1293  basic_json(const CompatibleStringType& val)
1294  : basic_json(string_t(val))
1295  {}
1296 
1311  basic_json(boolean_t val) noexcept
1312  : m_type(value_t::boolean), m_value(val)
1313  {}
1314 
1338  template<typename T,
1339  typename std::enable_if<
1340  not (std::is_same<T, int>::value)
1341  and std::is_same<T, number_integer_t>::value
1342  , int>::type
1343  = 0>
1344  basic_json(const number_integer_t val) noexcept
1345  : m_type(value_t::number_integer), m_value(val)
1346  {}
1347 
1373  basic_json(const int val) noexcept
1374  : m_type(value_t::number_integer),
1375  m_value(static_cast<number_integer_t>(val))
1376  {}
1377 
1403  template<typename CompatibleNumberIntegerType, typename
1404  std::enable_if<
1405  std::is_constructible<number_integer_t, CompatibleNumberIntegerType>::value and
1406  std::numeric_limits<CompatibleNumberIntegerType>::is_integer and
1407  std::numeric_limits<CompatibleNumberIntegerType>::is_signed,
1408  CompatibleNumberIntegerType>::type
1409  = 0>
1410  basic_json(const CompatibleNumberIntegerType val) noexcept
1411  : m_type(value_t::number_integer),
1412  m_value(static_cast<number_integer_t>(val))
1413  {}
1414 
1432  template<typename T,
1433  typename std::enable_if<
1434  not (std::is_same<T, int>::value)
1435  and std::is_same<T, number_unsigned_t>::value
1436  , int>::type
1437  = 0>
1438  basic_json(const number_unsigned_t val) noexcept
1439  : m_type(value_t::number_unsigned), m_value(val)
1440  {}
1441 
1462  template < typename CompatibleNumberUnsignedType, typename
1463  std::enable_if <
1464  std::is_constructible<number_unsigned_t, CompatibleNumberUnsignedType>::value and
1465  std::numeric_limits<CompatibleNumberUnsignedType>::is_integer and
1466  !std::numeric_limits<CompatibleNumberUnsignedType>::is_signed,
1467  CompatibleNumberUnsignedType >::type
1468  = 0 >
1469  basic_json(const CompatibleNumberUnsignedType val) noexcept
1470  : m_type(value_t::number_unsigned),
1471  m_value(static_cast<number_unsigned_t>(val))
1472  {}
1473 
1498  basic_json(const number_float_t val) noexcept
1499  : m_type(value_t::number_float), m_value(val)
1500  {
1501  // replace infinity and NAN by null
1502  if (not std::isfinite(val))
1503  {
1504  m_type = value_t::null;
1505  m_value = json_value();
1506  }
1507  }
1508 
1539  template<typename CompatibleNumberFloatType, typename = typename
1540  std::enable_if<
1541  std::is_constructible<number_float_t, CompatibleNumberFloatType>::value and
1542  std::is_floating_point<CompatibleNumberFloatType>::value>::type
1543  >
1544  basic_json(const CompatibleNumberFloatType val) noexcept
1545  : basic_json(number_float_t(val))
1546  {}
1547 
1617  basic_json(std::initializer_list<basic_json> init,
1618  bool type_deduction = true,
1619  value_t manual_type = value_t::array)
1620  {
1621  // the initializer list could describe an object
1622  bool is_an_object = true;
1623 
1624  // check if each element is an array with two elements whose first
1625  // element is a string
1626  for (const auto& element : init)
1627  {
1628  if (not element.is_array() or element.size() != 2
1629  or not element[0].is_string())
1630  {
1631  // we found an element that makes it impossible to use the
1632  // initializer list as object
1633  is_an_object = false;
1634  break;
1635  }
1636  }
1637 
1638  // adjust type if type deduction is not wanted
1639  if (not type_deduction)
1640  {
1641  // if array is wanted, do not create an object though possible
1642  if (manual_type == value_t::array)
1643  {
1644  is_an_object = false;
1645  }
1646 
1647  // if object is wanted but impossible, throw an exception
1648  if (manual_type == value_t::object and not is_an_object)
1649  {
1650  throw std::domain_error("cannot create object from initializer list");
1651  }
1652  }
1653 
1654  if (is_an_object)
1655  {
1656  // the initializer list is a list of pairs -> create object
1657  m_type = value_t::object;
1658  m_value = value_t::object;
1659 
1660  assert(m_value.object != nullptr);
1661 
1662  for (auto& element : init)
1663  {
1664  m_value.object->emplace(*(element[0].m_value.string), element[1]);
1665  }
1666  }
1667  else
1668  {
1669  // the initializer list describes an array -> create array
1670  m_type = value_t::array;
1671  m_value.array = create<array_t>(init);
1672  }
1673  }
1674 
1709  static basic_json array(std::initializer_list<basic_json> init =
1710  std::initializer_list<basic_json>())
1711  {
1712  return basic_json(init, false, value_t::array);
1713  }
1714 
1749  static basic_json object(std::initializer_list<basic_json> init =
1750  std::initializer_list<basic_json>())
1751  {
1752  return basic_json(init, false, value_t::object);
1753  }
1754 
1773  basic_json(size_type cnt, const basic_json& val)
1774  : m_type(value_t::array)
1775  {
1776  m_value.array = create<array_t>(cnt, val);
1777  }
1778 
1813  template <class InputIT, typename
1814  std::enable_if<
1815  std::is_same<InputIT, typename basic_json_t::iterator>::value or
1816  std::is_same<InputIT, typename basic_json_t::const_iterator>::value
1817  , int>::type
1818  = 0>
1819  basic_json(InputIT first, InputIT last) : m_type(first.m_object->m_type)
1820  {
1821  // make sure iterator fits the current value
1822  if (first.m_object != last.m_object)
1823  {
1824  throw std::domain_error("iterators are not compatible");
1825  }
1826 
1827  // check if iterator range is complete for primitive values
1828  switch (m_type)
1829  {
1830  case value_t::boolean:
1831  case value_t::number_float:
1832  case value_t::number_integer:
1833  case value_t::number_unsigned:
1834  case value_t::string:
1835  {
1836  if (not first.m_it.primitive_iterator.is_begin() or not last.m_it.primitive_iterator.is_end())
1837  {
1838  throw std::out_of_range("iterators out of range");
1839  }
1840  break;
1841  }
1842 
1843  default:
1844  {
1845  break;
1846  }
1847  }
1848 
1849  switch (m_type)
1850  {
1851  case value_t::number_integer:
1852  {
1853  assert(first.m_object != nullptr);
1854  m_value.number_integer = first.m_object->m_value.number_integer;
1855  break;
1856  }
1857 
1858  case value_t::number_unsigned:
1859  {
1860  assert(first.m_object != nullptr);
1861  m_value.number_unsigned = first.m_object->m_value.number_unsigned;
1862  break;
1863  }
1864 
1865  case value_t::number_float:
1866  {
1867  assert(first.m_object != nullptr);
1868  m_value.number_float = first.m_object->m_value.number_float;
1869  break;
1870  }
1871 
1872  case value_t::boolean:
1873  {
1874  assert(first.m_object != nullptr);
1875  m_value.boolean = first.m_object->m_value.boolean;
1876  break;
1877  }
1878 
1879  case value_t::string:
1880  {
1881  assert(first.m_object != nullptr);
1882  m_value = *first.m_object->m_value.string;
1883  break;
1884  }
1885 
1886  case value_t::object:
1887  {
1888  m_value.object = create<object_t>(first.m_it.object_iterator, last.m_it.object_iterator);
1889  break;
1890  }
1891 
1892  case value_t::array:
1893  {
1894  m_value.array = create<array_t>(first.m_it.array_iterator, last.m_it.array_iterator);
1895  break;
1896  }
1897 
1898  default:
1899  {
1900  assert(first.m_object != nullptr);
1901  throw std::domain_error("cannot use construct with iterators from " + first.m_object->type_name());
1902  }
1903  }
1904  }
1905 
1926  explicit basic_json(std::istream& i, parser_callback_t cb = nullptr)
1927  {
1928  *this = parser(i, cb).parse();
1929  }
1930 
1932  // other constructors and destructor //
1934 
1957  basic_json(const basic_json& other)
1958  : m_type(other.m_type)
1959  {
1960  switch (m_type)
1961  {
1962  case value_t::object:
1963  {
1964  assert(other.m_value.object != nullptr);
1965  m_value = *other.m_value.object;
1966  break;
1967  }
1968 
1969  case value_t::array:
1970  {
1971  assert(other.m_value.array != nullptr);
1972  m_value = *other.m_value.array;
1973  break;
1974  }
1975 
1976  case value_t::string:
1977  {
1978  assert(other.m_value.string != nullptr);
1979  m_value = *other.m_value.string;
1980  break;
1981  }
1982 
1983  case value_t::boolean:
1984  {
1985  m_value = other.m_value.boolean;
1986  break;
1987  }
1988 
1989  case value_t::number_integer:
1990  {
1991  m_value = other.m_value.number_integer;
1992  break;
1993  }
1994 
1995  case value_t::number_unsigned:
1996  {
1997  m_value = other.m_value.number_unsigned;
1998  break;
1999  }
2000 
2001  case value_t::number_float:
2002  {
2003  m_value = other.m_value.number_float;
2004  break;
2005  }
2006 
2007  default:
2008  {
2009  break;
2010  }
2011  }
2012  }
2013 
2032  basic_json(basic_json&& other) noexcept
2033  : m_type(std::move(other.m_type)),
2034  m_value(std::move(other.m_value))
2035  {
2036  // invalidate payload
2037  other.m_type = value_t::null;
2038  other.m_value = {};
2039  }
2040 
2064  reference& operator=(basic_json other) noexcept (
2065  std::is_nothrow_move_constructible<value_t>::value and
2066  std::is_nothrow_move_assignable<value_t>::value and
2067  std::is_nothrow_move_constructible<json_value>::value and
2068  std::is_nothrow_move_assignable<json_value>::value
2069  )
2070  {
2071  using std::swap;
2072  swap(m_type, other.m_type);
2073  swap(m_value, other.m_value);
2074  return *this;
2075  }
2076 
2093  {
2094  switch (m_type)
2095  {
2096  case value_t::object:
2097  {
2098  AllocatorType<object_t> alloc;
2099  alloc.destroy(m_value.object);
2100  alloc.deallocate(m_value.object, 1);
2101  break;
2102  }
2103 
2104  case value_t::array:
2105  {
2106  AllocatorType<array_t> alloc;
2107  alloc.destroy(m_value.array);
2108  alloc.deallocate(m_value.array, 1);
2109  break;
2110  }
2111 
2112  case value_t::string:
2113  {
2114  AllocatorType<string_t> alloc;
2115  alloc.destroy(m_value.string);
2116  alloc.deallocate(m_value.string, 1);
2117  break;
2118  }
2119 
2120  default:
2121  {
2122  // all other types need no specific destructor
2123  break;
2124  }
2125  }
2126  }
2127 
2129 
2130  public:
2132  // object inspection //
2134 
2137 
2161  string_t dump(const int indent = -1) const
2162  {
2163  std::stringstream ss;
2164 
2165  if (indent >= 0)
2166  {
2167  dump(ss, true, static_cast<unsigned int>(indent));
2168  }
2169  else
2170  {
2171  dump(ss, false, 0);
2172  }
2173 
2174  return ss.str();
2175  }
2176 
2195  constexpr value_t type() const noexcept
2196  {
2197  return m_type;
2198  }
2199 
2225  constexpr bool is_primitive() const noexcept
2226  {
2227  return is_null() or is_string() or is_boolean() or is_number();
2228  }
2229 
2252  constexpr bool is_structured() const noexcept
2253  {
2254  return is_array() or is_object();
2255  }
2256 
2274  constexpr bool is_null() const noexcept
2275  {
2276  return m_type == value_t::null;
2277  }
2278 
2296  constexpr bool is_boolean() const noexcept
2297  {
2298  return m_type == value_t::boolean;
2299  }
2300 
2326  constexpr bool is_number() const noexcept
2327  {
2328  return is_number_integer() or is_number_float();
2329  }
2330 
2355  constexpr bool is_number_integer() const noexcept
2356  {
2357  return m_type == value_t::number_integer or m_type == value_t::number_unsigned;
2358  }
2359 
2383  constexpr bool is_number_unsigned() const noexcept
2384  {
2385  return m_type == value_t::number_unsigned;
2386  }
2387 
2411  constexpr bool is_number_float() const noexcept
2412  {
2413  return m_type == value_t::number_float;
2414  }
2415 
2433  constexpr bool is_object() const noexcept
2434  {
2435  return m_type == value_t::object;
2436  }
2437 
2455  constexpr bool is_array() const noexcept
2456  {
2457  return m_type == value_t::array;
2458  }
2459 
2477  constexpr bool is_string() const noexcept
2478  {
2479  return m_type == value_t::string;
2480  }
2481 
2504  constexpr bool is_discarded() const noexcept
2505  {
2506  return m_type == value_t::discarded;
2507  }
2508 
2527  constexpr operator value_t() const noexcept
2528  {
2529  return m_type;
2530  }
2531 
2533 
2534  private:
2536  // value access //
2538 
2540  template <class T, typename
2541  std::enable_if<
2542  std::is_convertible<typename object_t::key_type, typename T::key_type>::value and
2543  std::is_convertible<basic_json_t, typename T::mapped_type>::value
2544  , int>::type = 0>
2545  T get_impl(T*) const
2546  {
2547  if (is_object())
2548  {
2549  assert(m_value.object != nullptr);
2550  return T(m_value.object->begin(), m_value.object->end());
2551  }
2552  else
2553  {
2554  throw std::domain_error("type must be object, but is " + type_name());
2555  }
2556  }
2557 
2559  object_t get_impl(object_t*) const
2560  {
2561  if (is_object())
2562  {
2563  assert(m_value.object != nullptr);
2564  return *(m_value.object);
2565  }
2566  else
2567  {
2568  throw std::domain_error("type must be object, but is " + type_name());
2569  }
2570  }
2571 
2573  template <class T, typename
2574  std::enable_if<
2575  std::is_convertible<basic_json_t, typename T::value_type>::value and
2576  not std::is_same<basic_json_t, typename T::value_type>::value and
2577  not std::is_arithmetic<T>::value and
2578  not std::is_convertible<std::string, T>::value and
2579  not has_mapped_type<T>::value
2580  , int>::type = 0>
2581  T get_impl(T*) const
2582  {
2583  if (is_array())
2584  {
2585  T to_vector;
2586  assert(m_value.array != nullptr);
2587  std::transform(m_value.array->begin(), m_value.array->end(),
2588  std::inserter(to_vector, to_vector.end()), [](basic_json i)
2589  {
2590  return i.get<typename T::value_type>();
2591  });
2592  return to_vector;
2593  }
2594  else
2595  {
2596  throw std::domain_error("type must be array, but is " + type_name());
2597  }
2598  }
2599 
2601  template <class T, typename
2602  std::enable_if<
2603  std::is_convertible<basic_json_t, T>::value and
2604  not std::is_same<basic_json_t, T>::value
2605  , int>::type = 0>
2606  std::vector<T> get_impl(std::vector<T>*) const
2607  {
2608  if (is_array())
2609  {
2610  std::vector<T> to_vector;
2611  assert(m_value.array != nullptr);
2612  to_vector.reserve(m_value.array->size());
2613  std::transform(m_value.array->begin(), m_value.array->end(),
2614  std::inserter(to_vector, to_vector.end()), [](basic_json i)
2615  {
2616  return i.get<T>();
2617  });
2618  return to_vector;
2619  }
2620  else
2621  {
2622  throw std::domain_error("type must be array, but is " + type_name());
2623  }
2624  }
2625 
2627  template <class T, typename
2628  std::enable_if<
2629  std::is_same<basic_json, typename T::value_type>::value and
2630  not has_mapped_type<T>::value
2631  , int>::type = 0>
2632  T get_impl(T*) const
2633  {
2634  if (is_array())
2635  {
2636  assert(m_value.array != nullptr);
2637  return T(m_value.array->begin(), m_value.array->end());
2638  }
2639  else
2640  {
2641  throw std::domain_error("type must be array, but is " + type_name());
2642  }
2643  }
2644 
2646  array_t get_impl(array_t*) const
2647  {
2648  if (is_array())
2649  {
2650  assert(m_value.array != nullptr);
2651  return *(m_value.array);
2652  }
2653  else
2654  {
2655  throw std::domain_error("type must be array, but is " + type_name());
2656  }
2657  }
2658 
2660  template <typename T, typename
2661  std::enable_if<
2662  std::is_convertible<string_t, T>::value
2663  , int>::type = 0>
2664  T get_impl(T*) const
2665  {
2666  if (is_string())
2667  {
2668  assert(m_value.string != nullptr);
2669  return *m_value.string;
2670  }
2671  else
2672  {
2673  throw std::domain_error("type must be string, but is " + type_name());
2674  }
2675  }
2676 
2678  template<typename T, typename
2679  std::enable_if<
2680  std::is_arithmetic<T>::value
2681  , int>::type = 0>
2682  T get_impl(T*) const
2683  {
2684  switch (m_type)
2685  {
2686  case value_t::number_integer:
2687  {
2688  return static_cast<T>(m_value.number_integer);
2689  }
2690 
2691  case value_t::number_unsigned:
2692  {
2693  return static_cast<T>(m_value.number_unsigned);
2694  }
2695 
2696  case value_t::number_float:
2697  {
2698  return static_cast<T>(m_value.number_float);
2699  }
2700 
2701  default:
2702  {
2703  throw std::domain_error("type must be number, but is " + type_name());
2704  }
2705  }
2706  }
2707 
2709  constexpr boolean_t get_impl(boolean_t*) const
2710  {
2711  return is_boolean()
2712  ? m_value.boolean
2713  : throw std::domain_error("type must be boolean, but is " + type_name());
2714  }
2715 
2717  object_t* get_impl_ptr(object_t*) noexcept
2718  {
2719  return is_object() ? m_value.object : nullptr;
2720  }
2721 
2723  constexpr const object_t* get_impl_ptr(const object_t*) const noexcept
2724  {
2725  return is_object() ? m_value.object : nullptr;
2726  }
2727 
2729  array_t* get_impl_ptr(array_t*) noexcept
2730  {
2731  return is_array() ? m_value.array : nullptr;
2732  }
2733 
2735  constexpr const array_t* get_impl_ptr(const array_t*) const noexcept
2736  {
2737  return is_array() ? m_value.array : nullptr;
2738  }
2739 
2741  string_t* get_impl_ptr(string_t*) noexcept
2742  {
2743  return is_string() ? m_value.string : nullptr;
2744  }
2745 
2747  constexpr const string_t* get_impl_ptr(const string_t*) const noexcept
2748  {
2749  return is_string() ? m_value.string : nullptr;
2750  }
2751 
2753  boolean_t* get_impl_ptr(boolean_t*) noexcept
2754  {
2755  return is_boolean() ? &m_value.boolean : nullptr;
2756  }
2757 
2759  constexpr const boolean_t* get_impl_ptr(const boolean_t*) const noexcept
2760  {
2761  return is_boolean() ? &m_value.boolean : nullptr;
2762  }
2763 
2765  number_integer_t* get_impl_ptr(number_integer_t*) noexcept
2766  {
2767  return is_number_integer() ? &m_value.number_integer : nullptr;
2768  }
2769 
2771  constexpr const number_integer_t* get_impl_ptr(const number_integer_t*) const noexcept
2772  {
2773  return is_number_integer() ? &m_value.number_integer : nullptr;
2774  }
2775 
2777  number_unsigned_t* get_impl_ptr(number_unsigned_t*) noexcept
2778  {
2779  return is_number_unsigned() ? &m_value.number_unsigned : nullptr;
2780  }
2781 
2783  constexpr const number_unsigned_t* get_impl_ptr(const number_unsigned_t*) const noexcept
2784  {
2785  return is_number_unsigned() ? &m_value.number_unsigned : nullptr;
2786  }
2787 
2789  number_float_t* get_impl_ptr(number_float_t*) noexcept
2790  {
2791  return is_number_float() ? &m_value.number_float : nullptr;
2792  }
2793 
2795  constexpr const number_float_t* get_impl_ptr(const number_float_t*) const noexcept
2796  {
2797  return is_number_float() ? &m_value.number_float : nullptr;
2798  }
2799 
2811  template<typename ReferenceType, typename ThisType>
2812  static ReferenceType get_ref_impl(ThisType& obj)
2813  {
2814  // delegate the call to get_ptr<>()
2815  using PointerType = typename std::add_pointer<ReferenceType>::type;
2816  auto ptr = obj.template get_ptr<PointerType>();
2817 
2818  if (ptr != nullptr)
2819  {
2820  return *ptr;
2821  }
2822  else
2823  {
2824  throw std::domain_error("incompatible ReferenceType for get_ref, actual type is " +
2825  obj.type_name());
2826  }
2827  }
2828 
2829  public:
2830 
2833 
2867  template<typename ValueType, typename
2868  std::enable_if<
2869  not std::is_pointer<ValueType>::value
2870  , int>::type = 0>
2871  ValueType get() const
2872  {
2873  return get_impl(static_cast<ValueType*>(nullptr));
2874  }
2875 
2902  template<typename PointerType, typename
2903  std::enable_if<
2904  std::is_pointer<PointerType>::value
2905  , int>::type = 0>
2906  PointerType get() noexcept
2907  {
2908  // delegate the call to get_ptr
2909  return get_ptr<PointerType>();
2910  }
2911 
2916  template<typename PointerType, typename
2917  std::enable_if<
2918  std::is_pointer<PointerType>::value
2919  , int>::type = 0>
2920  constexpr const PointerType get() const noexcept
2921  {
2922  // delegate the call to get_ptr
2923  return get_ptr<PointerType>();
2924  }
2925 
2951  template<typename PointerType, typename
2952  std::enable_if<
2953  std::is_pointer<PointerType>::value
2954  , int>::type = 0>
2955  PointerType get_ptr() noexcept
2956  {
2957  // delegate the call to get_impl_ptr<>()
2958  return get_impl_ptr(static_cast<PointerType>(nullptr));
2959  }
2960 
2965  template<typename PointerType, typename
2966  std::enable_if<
2967  std::is_pointer<PointerType>::value
2968  and std::is_const<typename std::remove_pointer<PointerType>::type>::value
2969  , int>::type = 0>
2970  constexpr const PointerType get_ptr() const noexcept
2971  {
2972  // delegate the call to get_impl_ptr<>() const
2973  return get_impl_ptr(static_cast<const PointerType>(nullptr));
2974  }
2975 
3002  template<typename ReferenceType, typename
3003  std::enable_if<
3004  std::is_reference<ReferenceType>::value
3005  , int>::type = 0>
3006  ReferenceType get_ref()
3007  {
3008  // delegate call to get_ref_impl
3009  return get_ref_impl<ReferenceType>(*this);
3010  }
3011 
3016  template<typename ReferenceType, typename
3017  std::enable_if<
3018  std::is_reference<ReferenceType>::value
3019  and std::is_const<typename std::remove_reference<ReferenceType>::type>::value
3020  , int>::type = 0>
3021  ReferenceType get_ref() const
3022  {
3023  // delegate call to get_ref_impl
3024  return get_ref_impl<ReferenceType>(*this);
3025  }
3026 
3055  template < typename ValueType, typename
3056  std::enable_if <
3057  not std::is_pointer<ValueType>::value
3058  and not std::is_same<ValueType, typename string_t::value_type>::value
3059 #ifndef _MSC_VER // Fix for issue #167 operator<< abiguity under VS2015
3060  and not std::is_same<ValueType, std::initializer_list<typename string_t::value_type>>::value
3061 #endif
3062  , int >::type = 0 >
3063  operator ValueType() const
3064  {
3065  // delegate the call to get<>() const
3066  return get<ValueType>();
3067  }
3068 
3070 
3071 
3073  // element access //
3075 
3078 
3102  {
3103  // at only works for arrays
3104  if (is_array())
3105  {
3106  try
3107  {
3108  assert(m_value.array != nullptr);
3109  return m_value.array->at(idx);
3110  }
3111  catch (std::out_of_range&)
3112  {
3113  // create better exception explanation
3114  throw std::out_of_range("array index " + std::to_string(idx) + " is out of range");
3115  }
3116  }
3117  else
3118  {
3119  throw std::domain_error("cannot use at() with " + type_name());
3120  }
3121  }
3122 
3146  {
3147  // at only works for arrays
3148  if (is_array())
3149  {
3150  try
3151  {
3152  assert(m_value.array != nullptr);
3153  return m_value.array->at(idx);
3154  }
3155  catch (std::out_of_range&)
3156  {
3157  // create better exception explanation
3158  throw std::out_of_range("array index " + std::to_string(idx) + " is out of range");
3159  }
3160  }
3161  else
3162  {
3163  throw std::domain_error("cannot use at() with " + type_name());
3164  }
3165  }
3166 
3193  reference at(const typename object_t::key_type& key)
3194  {
3195  // at only works for objects
3196  if (is_object())
3197  {
3198  try
3199  {
3200  assert(m_value.object != nullptr);
3201  return m_value.object->at(key);
3202  }
3203  catch (std::out_of_range&)
3204  {
3205  // create better exception explanation
3206  throw std::out_of_range("key '" + key + "' not found");
3207  }
3208  }
3209  else
3210  {
3211  throw std::domain_error("cannot use at() with " + type_name());
3212  }
3213  }
3214 
3241  const_reference at(const typename object_t::key_type& key) const
3242  {
3243  // at only works for objects
3244  if (is_object())
3245  {
3246  try
3247  {
3248  assert(m_value.object != nullptr);
3249  return m_value.object->at(key);
3250  }
3251  catch (std::out_of_range&)
3252  {
3253  // create better exception explanation
3254  throw std::out_of_range("key '" + key + "' not found");
3255  }
3256  }
3257  else
3258  {
3259  throw std::domain_error("cannot use at() with " + type_name());
3260  }
3261  }
3262 
3289  {
3290  // implicitly convert null value to an empty array
3291  if (is_null())
3292  {
3293  m_type = value_t::array;
3294  m_value.array = create<array_t>();
3295  }
3296 
3297  // operator[] only works for arrays
3298  if (is_array())
3299  {
3300  // fill up array with null values until given idx is reached
3301  assert(m_value.array != nullptr);
3302  for (size_t i = m_value.array->size(); i <= idx; ++i)
3303  {
3304  m_value.array->push_back(basic_json());
3305  }
3306 
3307  return m_value.array->operator[](idx);
3308  }
3309  else
3310  {
3311  throw std::domain_error("cannot use operator[] with " + type_name());
3312  }
3313  }
3314 
3335  {
3336  // const operator[] only works for arrays
3337  if (is_array())
3338  {
3339  assert(m_value.array != nullptr);
3340  return m_value.array->operator[](idx);
3341  }
3342  else
3343  {
3344  throw std::domain_error("cannot use operator[] with " + type_name());
3345  }
3346  }
3347 
3375  reference operator[](const typename object_t::key_type& key)
3376  {
3377  // implicitly convert null value to an empty object
3378  if (is_null())
3379  {
3380  m_type = value_t::object;
3381  m_value.object = create<object_t>();
3382  }
3383 
3384  // operator[] only works for objects
3385  if (is_object())
3386  {
3387  assert(m_value.object != nullptr);
3388  return m_value.object->operator[](key);
3389  }
3390  else
3391  {
3392  throw std::domain_error("cannot use operator[] with " + type_name());
3393  }
3394  }
3395 
3423  const_reference operator[](const typename object_t::key_type& key) const
3424  {
3425  // const operator[] only works for objects
3426  if (is_object())
3427  {
3428  assert(m_value.object != nullptr);
3429  assert(m_value.object->find(key) != m_value.object->end());
3430  return m_value.object->find(key)->second;
3431  }
3432  else
3433  {
3434  throw std::domain_error("cannot use operator[] with " + type_name());
3435  }
3436  }
3437 
3465  template<typename T, std::size_t n>
3466  reference operator[](T * (&key)[n])
3467  {
3468  return operator[](static_cast<const T>(key));
3469  }
3470 
3500  template<typename T, std::size_t n>
3501  const_reference operator[](T * (&key)[n]) const
3502  {
3503  return operator[](static_cast<const T>(key));
3504  }
3505 
3533  template<typename T>
3535  {
3536  // implicitly convert null to object
3537  if (is_null())
3538  {
3539  m_type = value_t::object;
3540  m_value = value_t::object;
3541  }
3542 
3543  // at only works for objects
3544  if (is_object())
3545  {
3546  assert(m_value.object != nullptr);
3547  return m_value.object->operator[](key);
3548  }
3549  else
3550  {
3551  throw std::domain_error("cannot use operator[] with " + type_name());
3552  }
3553  }
3554 
3582  template<typename T>
3584  {
3585  // at only works for objects
3586  if (is_object())
3587  {
3588  assert(m_value.object != nullptr);
3589  assert(m_value.object->find(key) != m_value.object->end());
3590  return m_value.object->find(key)->second;
3591  }
3592  else
3593  {
3594  throw std::domain_error("cannot use operator[] with " + type_name());
3595  }
3596  }
3597 
3646  template <class ValueType, typename
3647  std::enable_if<
3648  std::is_convertible<basic_json_t, ValueType>::value
3649  , int>::type = 0>
3650  ValueType value(const typename object_t::key_type& key, ValueType default_value) const
3651  {
3652  // at only works for objects
3653  if (is_object())
3654  {
3655  // if key is found, return value and given default value otherwise
3656  const auto it = find(key);
3657  if (it != end())
3658  {
3659  return *it;
3660  }
3661  else
3662  {
3663  return default_value;
3664  }
3665  }
3666  else
3667  {
3668  throw std::domain_error("cannot use value() with " + type_name());
3669  }
3670  }
3671 
3676  string_t value(const typename object_t::key_type& key, const char* default_value) const
3677  {
3678  return value(key, string_t(default_value));
3679  }
3680 
3706  {
3707  return *begin();
3708  }
3709 
3714  {
3715  return *cbegin();
3716  }
3717 
3748  {
3749  auto tmp = end();
3750  --tmp;
3751  return *tmp;
3752  }
3753 
3758  {
3759  auto tmp = cend();
3760  --tmp;
3761  return *tmp;
3762  }
3763 
3809  template <class InteratorType, typename
3810  std::enable_if<
3811  std::is_same<InteratorType, typename basic_json_t::iterator>::value or
3812  std::is_same<InteratorType, typename basic_json_t::const_iterator>::value
3813  , int>::type
3814  = 0>
3815  InteratorType erase(InteratorType pos)
3816  {
3817  // make sure iterator fits the current value
3818  if (this != pos.m_object)
3819  {
3820  throw std::domain_error("iterator does not fit current value");
3821  }
3822 
3823  InteratorType result = end();
3824 
3825  switch (m_type)
3826  {
3827  case value_t::boolean:
3828  case value_t::number_float:
3829  case value_t::number_integer:
3830  case value_t::number_unsigned:
3831  case value_t::string:
3832  {
3833  if (not pos.m_it.primitive_iterator.is_begin())
3834  {
3835  throw std::out_of_range("iterator out of range");
3836  }
3837 
3838  if (is_string())
3839  {
3840  delete m_value.string;
3841  m_value.string = nullptr;
3842  }
3843 
3844  m_type = value_t::null;
3845  break;
3846  }
3847 
3848  case value_t::object:
3849  {
3850  assert(m_value.object != nullptr);
3851  result.m_it.object_iterator = m_value.object->erase(pos.m_it.object_iterator);
3852  break;
3853  }
3854 
3855  case value_t::array:
3856  {
3857  assert(m_value.array != nullptr);
3858  result.m_it.array_iterator = m_value.array->erase(pos.m_it.array_iterator);
3859  break;
3860  }
3861 
3862  default:
3863  {
3864  throw std::domain_error("cannot use erase() with " + type_name());
3865  }
3866  }
3867 
3868  return result;
3869  }
3870 
3917  template <class InteratorType, typename
3918  std::enable_if<
3919  std::is_same<InteratorType, typename basic_json_t::iterator>::value or
3920  std::is_same<InteratorType, typename basic_json_t::const_iterator>::value
3921  , int>::type
3922  = 0>
3923  InteratorType erase(InteratorType first, InteratorType last)
3924  {
3925  // make sure iterator fits the current value
3926  if (this != first.m_object or this != last.m_object)
3927  {
3928  throw std::domain_error("iterators do not fit current value");
3929  }
3930 
3931  InteratorType result = end();
3932 
3933  switch (m_type)
3934  {
3935  case value_t::boolean:
3936  case value_t::number_float:
3937  case value_t::number_integer:
3938  case value_t::number_unsigned:
3939  case value_t::string:
3940  {
3941  if (not first.m_it.primitive_iterator.is_begin() or not last.m_it.primitive_iterator.is_end())
3942  {
3943  throw std::out_of_range("iterators out of range");
3944  }
3945 
3946  if (is_string())
3947  {
3948  delete m_value.string;
3949  m_value.string = nullptr;
3950  }
3951 
3952  m_type = value_t::null;
3953  break;
3954  }
3955 
3956  case value_t::object:
3957  {
3958  assert(m_value.object != nullptr);
3959  result.m_it.object_iterator = m_value.object->erase(first.m_it.object_iterator,
3960  last.m_it.object_iterator);
3961  break;
3962  }
3963 
3964  case value_t::array:
3965  {
3966  assert(m_value.array != nullptr);
3967  result.m_it.array_iterator = m_value.array->erase(first.m_it.array_iterator,
3968  last.m_it.array_iterator);
3969  break;
3970  }
3971 
3972  default:
3973  {
3974  throw std::domain_error("cannot use erase() with " + type_name());
3975  }
3976  }
3977 
3978  return result;
3979  }
3980 
4010  size_type erase(const typename object_t::key_type& key)
4011  {
4012  // this erase only works for objects
4013  if (is_object())
4014  {
4015  assert(m_value.object != nullptr);
4016  return m_value.object->erase(key);
4017  }
4018  else
4019  {
4020  throw std::domain_error("cannot use erase() with " + type_name());
4021  }
4022  }
4023 
4048  void erase(const size_type idx)
4049  {
4050  // this erase only works for arrays
4051  if (is_array())
4052  {
4053  if (idx >= size())
4054  {
4055  throw std::out_of_range("array index " + std::to_string(idx) + " is out of range");
4056  }
4057 
4058  assert(m_value.array != nullptr);
4059  m_value.array->erase(m_value.array->begin() + static_cast<difference_type>(idx));
4060  }
4061  else
4062  {
4063  throw std::domain_error("cannot use erase() with " + type_name());
4064  }
4065  }
4066 
4068 
4069 
4071  // lookup //
4073 
4076 
4094  iterator find(typename object_t::key_type key)
4095  {
4096  auto result = end();
4097 
4098  if (is_object())
4099  {
4100  assert(m_value.object != nullptr);
4101  result.m_it.object_iterator = m_value.object->find(key);
4102  }
4103 
4104  return result;
4105  }
4106 
4111  const_iterator find(typename object_t::key_type key) const
4112  {
4113  auto result = cend();
4114 
4115  if (is_object())
4116  {
4117  assert(m_value.object != nullptr);
4118  result.m_it.object_iterator = m_value.object->find(key);
4119  }
4120 
4121  return result;
4122  }
4123 
4142  size_type count(typename object_t::key_type key) const
4143  {
4144  // return 0 for all nonobject types
4145  assert(not is_object() or m_value.object != nullptr);
4146  return is_object() ? m_value.object->count(key) : 0;
4147  }
4148 
4150 
4151 
4153  // iterators //
4155 
4158 
4183  iterator begin() noexcept
4184  {
4185  iterator result(this);
4186  result.set_begin();
4187  return result;
4188  }
4189 
4193  const_iterator begin() const noexcept
4194  {
4195  return cbegin();
4196  }
4197 
4223  const_iterator cbegin() const noexcept
4224  {
4225  const_iterator result(this);
4226  result.set_begin();
4227  return result;
4228  }
4229 
4254  iterator end() noexcept
4255  {
4256  iterator result(this);
4257  result.set_end();
4258  return result;
4259  }
4260 
4264  const_iterator end() const noexcept
4265  {
4266  return cend();
4267  }
4268 
4294  const_iterator cend() const noexcept
4295  {
4296  const_iterator result(this);
4297  result.set_end();
4298  return result;
4299  }
4300 
4325  {
4326  return reverse_iterator(end());
4327  }
4328 
4333  {
4334  return crbegin();
4335  }
4336 
4362  {
4363  return reverse_iterator(begin());
4364  }
4365 
4369  const_reverse_iterator rend() const noexcept
4370  {
4371  return crend();
4372  }
4373 
4399  {
4400  return const_reverse_iterator(cend());
4401  }
4402 
4428  {
4429  return const_reverse_iterator(cbegin());
4430  }
4431 
4432  private:
4433  // forward declaration
4434  template<typename IteratorType> class iteration_proxy;
4435 
4436  public:
4448  static iteration_proxy<iterator> iterator_wrapper(reference cont)
4449  {
4450  return iteration_proxy<iterator>(cont);
4451  }
4452 
4456  static iteration_proxy<const_iterator> iterator_wrapper(const_reference cont)
4457  {
4458  return iteration_proxy<const_iterator>(cont);
4459  }
4460 
4462 
4463 
4465  // capacity //
4467 
4470 
4504  bool empty() const noexcept
4505  {
4506  switch (m_type)
4507  {
4508  case value_t::null:
4509  {
4510  // null values are empty
4511  return true;
4512  }
4513 
4514  case value_t::array:
4515  {
4516  assert(m_value.array != nullptr);
4517  return m_value.array->empty();
4518  }
4519 
4520  case value_t::object:
4521  {
4522  assert(m_value.object != nullptr);
4523  return m_value.object->empty();
4524  }
4525 
4526  default:
4527  {
4528  // all other types are nonempty
4529  return false;
4530  }
4531  }
4532  }
4533 
4567  size_type size() const noexcept
4568  {
4569  switch (m_type)
4570  {
4571  case value_t::null:
4572  {
4573  // null values are empty
4574  return 0;
4575  }
4576 
4577  case value_t::array:
4578  {
4579  assert(m_value.array != nullptr);
4580  return m_value.array->size();
4581  }
4582 
4583  case value_t::object:
4584  {
4585  assert(m_value.object != nullptr);
4586  return m_value.object->size();
4587  }
4588 
4589  default:
4590  {
4591  // all other types have size 1
4592  return 1;
4593  }
4594  }
4595  }
4596 
4633  size_type max_size() const noexcept
4634  {
4635  switch (m_type)
4636  {
4637  case value_t::array:
4638  {
4639  assert(m_value.array != nullptr);
4640  return m_value.array->max_size();
4641  }
4642 
4643  case value_t::object:
4644  {
4645  assert(m_value.object != nullptr);
4646  return m_value.object->max_size();
4647  }
4648 
4649  default:
4650  {
4651  // all other types have max_size() == size()
4652  return size();
4653  }
4654  }
4655  }
4656 
4658 
4659 
4661  // modifiers //
4663 
4666 
4692  void clear() noexcept
4693  {
4694  switch (m_type)
4695  {
4696  case value_t::number_integer:
4697  {
4698  m_value.number_integer = 0;
4699  break;
4700  }
4701 
4702  case value_t::number_unsigned:
4703  {
4704  m_value.number_unsigned = 0;
4705  break;
4706  }
4707 
4708  case value_t::number_float:
4709  {
4710  m_value.number_float = 0.0;
4711  break;
4712  }
4713 
4714  case value_t::boolean:
4715  {
4716  m_value.boolean = false;
4717  break;
4718  }
4719 
4720  case value_t::string:
4721  {
4722  assert(m_value.string != nullptr);
4723  m_value.string->clear();
4724  break;
4725  }
4726 
4727  case value_t::array:
4728  {
4729  assert(m_value.array != nullptr);
4730  m_value.array->clear();
4731  break;
4732  }
4733 
4734  case value_t::object:
4735  {
4736  assert(m_value.object != nullptr);
4737  m_value.object->clear();
4738  break;
4739  }
4740 
4741  default:
4742  {
4743  break;
4744  }
4745  }
4746  }
4747 
4768  void push_back(basic_json&& val)
4769  {
4770  // push_back only works for null objects or arrays
4771  if (not(is_null() or is_array()))
4772  {
4773  throw std::domain_error("cannot use push_back() with " + type_name());
4774  }
4775 
4776  // transform null object into an array
4777  if (is_null())
4778  {
4779  m_type = value_t::array;
4780  m_value = value_t::array;
4781  }
4782 
4783  // add element to array (move semantics)
4784  assert(m_value.array != nullptr);
4785  m_value.array->push_back(std::move(val));
4786  // invalidate object
4787  val.m_type = value_t::null;
4788  }
4789 
4794  reference operator+=(basic_json&& val)
4795  {
4796  push_back(std::move(val));
4797  return *this;
4798  }
4799 
4804  void push_back(const basic_json& val)
4805  {
4806  // push_back only works for null objects or arrays
4807  if (not(is_null() or is_array()))
4808  {
4809  throw std::domain_error("cannot use push_back() with " + type_name());
4810  }
4811 
4812  // transform null object into an array
4813  if (is_null())
4814  {
4815  m_type = value_t::array;
4816  m_value = value_t::array;
4817  }
4818 
4819  // add element to array
4820  assert(m_value.array != nullptr);
4821  m_value.array->push_back(val);
4822  }
4823 
4828  reference operator+=(const basic_json& val)
4829  {
4830  push_back(val);
4831  return *this;
4832  }
4833 
4854  void push_back(const typename object_t::value_type& val)
4855  {
4856  // push_back only works for null objects or objects
4857  if (not(is_null() or is_object()))
4858  {
4859  throw std::domain_error("cannot use push_back() with " + type_name());
4860  }
4861 
4862  // transform null object into an object
4863  if (is_null())
4864  {
4865  m_type = value_t::object;
4866  m_value = value_t::object;
4867  }
4868 
4869  // add element to array
4870  assert(m_value.object != nullptr);
4871  m_value.object->insert(val);
4872  }
4873 
4878  reference operator+=(const typename object_t::value_type& val)
4879  {
4880  push_back(val);
4881  return operator[](val.first);
4882  }
4883 
4906  iterator insert(const_iterator pos, const basic_json& val)
4907  {
4908  // insert only works for arrays
4909  if (is_array())
4910  {
4911  // check if iterator pos fits to this JSON value
4912  if (pos.m_object != this)
4913  {
4914  throw std::domain_error("iterator does not fit current value");
4915  }
4916 
4917  // insert to array and return iterator
4918  iterator result(this);
4919  assert(m_value.array != nullptr);
4920  result.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator, val);
4921  return result;
4922  }
4923  else
4924  {
4925  throw std::domain_error("cannot use insert() with " + type_name());
4926  }
4927  }
4928 
4933  iterator insert(const_iterator pos, basic_json&& val)
4934  {
4935  return insert(pos, val);
4936  }
4937 
4962  iterator insert(const_iterator pos, size_type cnt, const basic_json& val)
4963  {
4964  // insert only works for arrays
4965  if (is_array())
4966  {
4967  // check if iterator pos fits to this JSON value
4968  if (pos.m_object != this)
4969  {
4970  throw std::domain_error("iterator does not fit current value");
4971  }
4972 
4973  // insert to array and return iterator
4974  iterator result(this);
4975  assert(m_value.array != nullptr);
4976  result.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator, cnt, val);
4977  return result;
4978  }
4979  else
4980  {
4981  throw std::domain_error("cannot use insert() with " + type_name());
4982  }
4983  }
4984 
5016  {
5017  // insert only works for arrays
5018  if (not is_array())
5019  {
5020  throw std::domain_error("cannot use insert() with " + type_name());
5021  }
5022 
5023  // check if iterator pos fits to this JSON value
5024  if (pos.m_object != this)
5025  {
5026  throw std::domain_error("iterator does not fit current value");
5027  }
5028 
5029  if (first.m_object != last.m_object)
5030  {
5031  throw std::domain_error("iterators do not fit");
5032  }
5033 
5034  if (first.m_object == this or last.m_object == this)
5035  {
5036  throw std::domain_error("passed iterators may not belong to container");
5037  }
5038 
5039  // insert to array and return iterator
5040  iterator result(this);
5041  assert(m_value.array != nullptr);
5042  result.m_it.array_iterator = m_value.array->insert(
5043  pos.m_it.array_iterator,
5044  first.m_it.array_iterator,
5045  last.m_it.array_iterator);
5046  return result;
5047  }
5048 
5073  iterator insert(const_iterator pos, std::initializer_list<basic_json> ilist)
5074  {
5075  // insert only works for arrays
5076  if (not is_array())
5077  {
5078  throw std::domain_error("cannot use insert() with " + type_name());
5079  }
5080 
5081  // check if iterator pos fits to this JSON value
5082  if (pos.m_object != this)
5083  {
5084  throw std::domain_error("iterator does not fit current value");
5085  }
5086 
5087  // insert to array and return iterator
5088  iterator result(this);
5089  assert(m_value.array != nullptr);
5090  result.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator, ilist);
5091  return result;
5092  }
5093 
5111  void swap(reference other) noexcept (
5112  std::is_nothrow_move_constructible<value_t>::value and
5113  std::is_nothrow_move_assignable<value_t>::value and
5114  std::is_nothrow_move_constructible<json_value>::value and
5115  std::is_nothrow_move_assignable<json_value>::value
5116  )
5117  {
5118  std::swap(m_type, other.m_type);
5119  std::swap(m_value, other.m_value);
5120  }
5121 
5142  void swap(array_t& other)
5143  {
5144  // swap only works for arrays
5145  if (is_array())
5146  {
5147  assert(m_value.array != nullptr);
5148  std::swap(*(m_value.array), other);
5149  }
5150  else
5151  {
5152  throw std::domain_error("cannot use swap() with " + type_name());
5153  }
5154  }
5155 
5176  void swap(object_t& other)
5177  {
5178  // swap only works for objects
5179  if (is_object())
5180  {
5181  assert(m_value.object != nullptr);
5182  std::swap(*(m_value.object), other);
5183  }
5184  else
5185  {
5186  throw std::domain_error("cannot use swap() with " + type_name());
5187  }
5188  }
5189 
5210  void swap(string_t& other)
5211  {
5212  // swap only works for strings
5213  if (is_string())
5214  {
5215  assert(m_value.string != nullptr);
5216  std::swap(*(m_value.string), other);
5217  }
5218  else
5219  {
5220  throw std::domain_error("cannot use swap() with " + type_name());
5221  }
5222  }
5223 
5225 
5226 
5228  // lexicographical comparison operators //
5230 
5233 
5234  private:
5244  friend bool operator<(const value_t lhs, const value_t rhs) noexcept
5245  {
5246  static constexpr std::array<uint8_t, 8> order = {{
5247  0, // null
5248  3, // object
5249  4, // array
5250  5, // string
5251  1, // boolean
5252  2, // integer
5253  2, // unsigned
5254  2, // float
5255  }
5256  };
5257 
5258  // discarded values are not comparable
5259  if (lhs == value_t::discarded or rhs == value_t::discarded)
5260  {
5261  return false;
5262  }
5263 
5264  return order[static_cast<std::size_t>(lhs)] < order[static_cast<std::size_t>(rhs)];
5265  }
5266 
5267  public:
5291  friend bool operator==(const_reference lhs, const_reference rhs) noexcept
5292  {
5293  const auto lhs_type = lhs.type();
5294  const auto rhs_type = rhs.type();
5295 
5296  if (lhs_type == rhs_type)
5297  {
5298  switch (lhs_type)
5299  {
5300  case value_t::array:
5301  {
5302  assert(lhs.m_value.array != nullptr);
5303  assert(rhs.m_value.array != nullptr);
5304  return *lhs.m_value.array == *rhs.m_value.array;
5305  }
5306  case value_t::object:
5307  {
5308  assert(lhs.m_value.object != nullptr);
5309  assert(rhs.m_value.object != nullptr);
5310  return *lhs.m_value.object == *rhs.m_value.object;
5311  }
5312  case value_t::null:
5313  {
5314  return true;
5315  }
5316  case value_t::string:
5317  {
5318  assert(lhs.m_value.string != nullptr);
5319  assert(rhs.m_value.string != nullptr);
5320  return *lhs.m_value.string == *rhs.m_value.string;
5321  }
5322  case value_t::boolean:
5323  {
5324  return lhs.m_value.boolean == rhs.m_value.boolean;
5325  }
5326  case value_t::number_integer:
5327  {
5328  return lhs.m_value.number_integer == rhs.m_value.number_integer;
5329  }
5330  case value_t::number_unsigned:
5331  {
5332  return lhs.m_value.number_unsigned == rhs.m_value.number_unsigned;
5333  }
5334  case value_t::number_float:
5335  {
5336  return lhs.m_value.number_float == rhs.m_value.number_float;
5337  }
5338  default:
5339  {
5340  return false;
5341  }
5342  }
5343  }
5344  else if (lhs_type == value_t::number_integer and rhs_type == value_t::number_float)
5345  {
5346  return static_cast<number_float_t>(lhs.m_value.number_integer) == rhs.m_value.number_float;
5347  }
5348  else if (lhs_type == value_t::number_float and rhs_type == value_t::number_integer)
5349  {
5350  return lhs.m_value.number_float == static_cast<number_float_t>(rhs.m_value.number_integer);
5351  }
5352  else if (lhs_type == value_t::number_unsigned and rhs_type == value_t::number_float)
5353  {
5354  return static_cast<number_float_t>(lhs.m_value.number_unsigned) == rhs.m_value.number_float;
5355  }
5356  else if (lhs_type == value_t::number_float and rhs_type == value_t::number_unsigned)
5357  {
5358  return lhs.m_value.number_float == static_cast<number_float_t>(rhs.m_value.number_unsigned);
5359  }
5360  else if (lhs_type == value_t::number_unsigned and rhs_type == value_t::number_integer)
5361  {
5362  return static_cast<number_integer_t>(lhs.m_value.number_unsigned) == rhs.m_value.number_integer;
5363  }
5364  else if (lhs_type == value_t::number_integer and rhs_type == value_t::number_unsigned)
5365  {
5366  return lhs.m_value.number_integer == static_cast<number_integer_t>(rhs.m_value.number_unsigned);
5367  }
5368 
5369  return false;
5370  }
5371 
5390  friend bool operator==(const_reference v, std::nullptr_t) noexcept
5391  {
5392  return v.is_null();
5393  }
5394 
5399  friend bool operator==(std::nullptr_t, const_reference v) noexcept
5400  {
5401  return v.is_null();
5402  }
5403 
5420  friend bool operator!=(const_reference lhs, const_reference rhs) noexcept
5421  {
5422  return not (lhs == rhs);
5423  }
5424 
5443  friend bool operator!=(const_reference v, std::nullptr_t) noexcept
5444  {
5445  return not v.is_null();
5446  }
5447 
5452  friend bool operator!=(std::nullptr_t, const_reference v) noexcept
5453  {
5454  return not v.is_null();
5455  }
5456 
5481  friend bool operator<(const_reference lhs, const_reference rhs) noexcept
5482  {
5483  const auto lhs_type = lhs.type();
5484  const auto rhs_type = rhs.type();
5485 
5486  if (lhs_type == rhs_type)
5487  {
5488  switch (lhs_type)
5489  {
5490  case value_t::array:
5491  {
5492  assert(lhs.m_value.array != nullptr);
5493  assert(rhs.m_value.array != nullptr);
5494  return *lhs.m_value.array < *rhs.m_value.array;
5495  }
5496  case value_t::object:
5497  {
5498  assert(lhs.m_value.object != nullptr);
5499  assert(rhs.m_value.object != nullptr);
5500  return *lhs.m_value.object < *rhs.m_value.object;
5501  }
5502  case value_t::null:
5503  {
5504  return false;
5505  }
5506  case value_t::string:
5507  {
5508  assert(lhs.m_value.string != nullptr);
5509  assert(rhs.m_value.string != nullptr);
5510  return *lhs.m_value.string < *rhs.m_value.string;
5511  }
5512  case value_t::boolean:
5513  {
5514  return lhs.m_value.boolean < rhs.m_value.boolean;
5515  }
5516  case value_t::number_integer:
5517  {
5518  return lhs.m_value.number_integer < rhs.m_value.number_integer;
5519  }
5520  case value_t::number_unsigned:
5521  {
5522  return lhs.m_value.number_unsigned < rhs.m_value.number_unsigned;
5523  }
5524  case value_t::number_float:
5525  {
5526  return lhs.m_value.number_float < rhs.m_value.number_float;
5527  }
5528  default:
5529  {
5530  return false;
5531  }
5532  }
5533  }
5534  else if (lhs_type == value_t::number_integer and rhs_type == value_t::number_float)
5535  {
5536  return static_cast<number_float_t>(lhs.m_value.number_integer) < rhs.m_value.number_float;
5537  }
5538  else if (lhs_type == value_t::number_float and rhs_type == value_t::number_integer)
5539  {
5540  return lhs.m_value.number_float < static_cast<number_float_t>(rhs.m_value.number_integer);
5541  }
5542  else if (lhs_type == value_t::number_unsigned and rhs_type == value_t::number_float)
5543  {
5544  return static_cast<number_float_t>(lhs.m_value.number_unsigned) < rhs.m_value.number_float;
5545  }
5546  else if (lhs_type == value_t::number_float and rhs_type == value_t::number_unsigned)
5547  {
5548  return lhs.m_value.number_float < static_cast<number_float_t>(rhs.m_value.number_unsigned);
5549  }
5550  else if (lhs_type == value_t::number_integer and rhs_type == value_t::number_unsigned)
5551  {
5552  return lhs.m_value.number_integer < static_cast<number_integer_t>(rhs.m_value.number_unsigned);
5553  }
5554  else if (lhs_type == value_t::number_unsigned and rhs_type == value_t::number_integer)
5555  {
5556  return static_cast<number_integer_t>(lhs.m_value.number_unsigned) < rhs.m_value.number_integer;
5557  }
5558 
5559  // We only reach this line if we cannot compare values. In that case,
5560  // we compare types. Note we have to call the operator explicitly,
5561  // because MSVC has problems otherwise.
5562  return operator<(lhs_type, rhs_type);
5563  }
5564 
5582  friend bool operator<=(const_reference lhs, const_reference rhs) noexcept
5583  {
5584  return not (rhs < lhs);
5585  }
5586 
5604  friend bool operator>(const_reference lhs, const_reference rhs) noexcept
5605  {
5606  return not (lhs <= rhs);
5607  }
5608 
5626  friend bool operator>=(const_reference lhs, const_reference rhs) noexcept
5627  {
5628  return not (lhs < rhs);
5629  }
5630 
5632 
5633 
5635  // serialization //
5637 
5640 
5663  friend std::ostream& operator<<(std::ostream& o, const basic_json& j)
5664  {
5665  // read width member and use it as indentation parameter if nonzero
5666  const bool pretty_print = (o.width() > 0);
5667  const auto indentation = (pretty_print ? o.width() : 0);
5668 
5669  // reset width to 0 for subsequent calls to this stream
5670  o.width(0);
5671 
5672  // do the actual serialization
5673  j.dump(o, pretty_print, static_cast<unsigned int>(indentation));
5674  return o;
5675  }
5676 
5681  friend std::ostream& operator>>(const basic_json& j, std::ostream& o)
5682  {
5683  return o << j;
5684  }
5685 
5687 
5688 
5690  // deserialization //
5692 
5695 
5720  static basic_json parse(const string_t& s, parser_callback_t cb = nullptr)
5721  {
5722  return parser(s, cb).parse();
5723  }
5724 
5749  static basic_json parse(std::istream& i, parser_callback_t cb = nullptr)
5750  {
5751  return parser(i, cb).parse();
5752  }
5753 
5757  static basic_json parse(std::istream&& i, parser_callback_t cb = nullptr)
5758  {
5759  return parser(i, cb).parse();
5760  }
5761 
5785  friend std::istream& operator<<(basic_json& j, std::istream& i)
5786  {
5787  j = parser(i).parse();
5788  return i;
5789  }
5790 
5795  friend std::istream& operator>>(std::istream& i, basic_json& j)
5796  {
5797  j = parser(i).parse();
5798  return i;
5799  }
5800 
5802 
5803 
5804  private:
5806  // convenience functions //
5808 
5810  string_t type_name() const noexcept
5811  {
5812  switch (m_type)
5813  {
5814  case value_t::null:
5815  return "null";
5816  case value_t::object:
5817  return "object";
5818  case value_t::array:
5819  return "array";
5820  case value_t::string:
5821  return "string";
5822  case value_t::boolean:
5823  return "boolean";
5824  case value_t::discarded:
5825  return "discarded";
5826  default:
5827  return "number";
5828  }
5829  }
5830 
5839  static std::size_t extra_space(const string_t& s) noexcept
5840  {
5841  std::size_t result = 0;
5842 
5843  for (const auto& c : s)
5844  {
5845  switch (c)
5846  {
5847  case '"':
5848  case '\\':
5849  case '\b':
5850  case '\f':
5851  case '\n':
5852  case '\r':
5853  case '\t':
5854  {
5855  // from c (1 byte) to \x (2 bytes)
5856  result += 1;
5857  break;
5858  }
5859 
5860  default:
5861  {
5862  if (c >= 0x00 and c <= 0x1f)
5863  {
5864  // from c (1 byte) to \uxxxx (6 bytes)
5865  result += 5;
5866  }
5867  break;
5868  }
5869  }
5870  }
5871 
5872  return result;
5873  }
5874 
5888  static string_t escape_string(const string_t& s)
5889  {
5890  const auto space = extra_space(s);
5891  if (space == 0)
5892  {
5893  return s;
5894  }
5895 
5896  // create a result string of necessary size
5897  string_t result(s.size() + space, '\\');
5898  std::size_t pos = 0;
5899 
5900  for (const auto& c : s)
5901  {
5902  switch (c)
5903  {
5904  // quotation mark (0x22)
5905  case '"':
5906  {
5907  result[pos + 1] = '"';
5908  pos += 2;
5909  break;
5910  }
5911 
5912  // reverse solidus (0x5c)
5913  case '\\':
5914  {
5915  // nothing to change
5916  pos += 2;
5917  break;
5918  }
5919 
5920  // backspace (0x08)
5921  case '\b':
5922  {
5923  result[pos + 1] = 'b';
5924  pos += 2;
5925  break;
5926  }
5927 
5928  // formfeed (0x0c)
5929  case '\f':
5930  {
5931  result[pos + 1] = 'f';
5932  pos += 2;
5933  break;
5934  }
5935 
5936  // newline (0x0a)
5937  case '\n':
5938  {
5939  result[pos + 1] = 'n';
5940  pos += 2;
5941  break;
5942  }
5943 
5944  // carriage return (0x0d)
5945  case '\r':
5946  {
5947  result[pos + 1] = 'r';
5948  pos += 2;
5949  break;
5950  }
5951 
5952  // horizontal tab (0x09)
5953  case '\t':
5954  {
5955  result[pos + 1] = 't';
5956  pos += 2;
5957  break;
5958  }
5959 
5960  default:
5961  {
5962  if (c >= 0x00 and c <= 0x1f)
5963  {
5964  // convert a number 0..15 to its hex representation
5965  // (0..f)
5966  auto hexify = [](const char v) -> char
5967  {
5968  return (v < 10) ? ('0' + v) : ('a' + v - 10);
5969  };
5970 
5971  // print character c as \uxxxx
5972  for (const char m :
5973  { 'u', '0', '0', hexify(c >> 4), hexify(c & 0x0f)
5974  })
5975  {
5976  result[++pos] = m;
5977  }
5978 
5979  ++pos;
5980  }
5981  else
5982  {
5983  // all other characters are added as-is
5984  result[pos++] = c;
5985  }
5986  break;
5987  }
5988  }
5989  }
5990 
5991  return result;
5992  }
5993 
6011  void dump(std::ostream& o,
6012  const bool pretty_print,
6013  const unsigned int indent_step,
6014  const unsigned int current_indent = 0) const
6015  {
6016  // variable to hold indentation for recursive calls
6017  unsigned int new_indent = current_indent;
6018 
6019  switch (m_type)
6020  {
6021  case value_t::object:
6022  {
6023  assert(m_value.object != nullptr);
6024 
6025  if (m_value.object->empty())
6026  {
6027  o << "{}";
6028  return;
6029  }
6030 
6031  o << "{";
6032 
6033  // increase indentation
6034  if (pretty_print)
6035  {
6036  new_indent += indent_step;
6037  o << "\n";
6038  }
6039 
6040  for (auto i = m_value.object->cbegin(); i != m_value.object->cend(); ++i)
6041  {
6042  if (i != m_value.object->cbegin())
6043  {
6044  o << (pretty_print ? ",\n" : ",");
6045  }
6046  o << string_t(new_indent, ' ') << "\""
6047  << escape_string(i->first) << "\":"
6048  << (pretty_print ? " " : "");
6049  i->second.dump(o, pretty_print, indent_step, new_indent);
6050  }
6051 
6052  // decrease indentation
6053  if (pretty_print)
6054  {
6055  new_indent -= indent_step;
6056  o << "\n";
6057  }
6058 
6059  o << string_t(new_indent, ' ') + "}";
6060  return;
6061  }
6062 
6063  case value_t::array:
6064  {
6065  assert(m_value.array != nullptr);
6066 
6067  if (m_value.array->empty())
6068  {
6069  o << "[]";
6070  return;
6071  }
6072 
6073  o << "[";
6074 
6075  // increase indentation
6076  if (pretty_print)
6077  {
6078  new_indent += indent_step;
6079  o << "\n";
6080  }
6081 
6082  for (auto i = m_value.array->cbegin(); i != m_value.array->cend(); ++i)
6083  {
6084  if (i != m_value.array->cbegin())
6085  {
6086  o << (pretty_print ? ",\n" : ",");
6087  }
6088  o << string_t(new_indent, ' ');
6089  i->dump(o, pretty_print, indent_step, new_indent);
6090  }
6091 
6092  // decrease indentation
6093  if (pretty_print)
6094  {
6095  new_indent -= indent_step;
6096  o << "\n";
6097  }
6098 
6099  o << string_t(new_indent, ' ') << "]";
6100  return;
6101  }
6102 
6103  case value_t::string:
6104  {
6105  assert(m_value.string != nullptr);
6106  o << string_t("\"") << escape_string(*m_value.string) << "\"";
6107  return;
6108  }
6109 
6110  case value_t::boolean:
6111  {
6112  o << (m_value.boolean ? "true" : "false");
6113  return;
6114  }
6115 
6116  case value_t::number_integer:
6117  {
6118  o << m_value.number_integer;
6119  return;
6120  }
6121 
6122  case value_t::number_unsigned:
6123  {
6124  o << m_value.number_unsigned;
6125  return;
6126  }
6127 
6128  case value_t::number_float:
6129  {
6130  // check if number was parsed from a string
6131  if (m_type.bits.parsed)
6132  {
6133  // check if parsed number had an exponent given
6134  if (m_type.bits.has_exp)
6135  {
6136  // buffer size: precision (2^8-1 = 255) + other ('-.e-xxx' = 7) + null (1)
6137  char buf[263];
6138  int len;
6139 
6140  // handle capitalization of the exponent
6141  if (m_type.bits.exp_cap)
6142  {
6143  len = snprintf(buf, sizeof(buf), "%.*E",
6144  m_type.bits.precision, m_value.number_float) + 1;
6145  }
6146  else
6147  {
6148  len = snprintf(buf, sizeof(buf), "%.*e",
6149  m_type.bits.precision, m_value.number_float) + 1;
6150  }
6151 
6152  // remove '+' sign from the exponent if necessary
6153  if (not m_type.bits.exp_plus)
6154  {
6155  if (len > static_cast<int>(sizeof(buf)))
6156  {
6157  len = sizeof(buf);
6158  }
6159  for (int i = 0; i < len; i++)
6160  {
6161  if (buf[i] == '+')
6162  {
6163  for (; i + 1 < len; i++)
6164  {
6165  buf[i] = buf[i + 1];
6166  }
6167  }
6168  }
6169  }
6170 
6171  o << buf;
6172  }
6173  else
6174  {
6175  // no exponent - output as a decimal
6176  std::stringstream ss;
6177  ss.imbue(std::locale(std::locale(), new DecimalSeparator)); // fix locale problems
6178  ss << std::setprecision(m_type.bits.precision)
6179  << std::fixed << m_value.number_float;
6180  o << ss.str();
6181  }
6182  }
6183  else
6184  {
6185  if (m_value.number_float == 0)
6186  {
6187  // special case for zero to get "0.0"/"-0.0"
6188  o << (std::signbit(m_value.number_float) ? "-0.0" : "0.0");
6189  }
6190  else
6191  {
6192  // Otherwise 6, 15 or 16 digits of precision allows
6193  // round-trip IEEE 754 string->float->string,
6194  // string->double->string or string->long double->string;
6195  // to be safe, we read this value from
6196  // std::numeric_limits<number_float_t>::digits10
6197  std::stringstream ss;
6198  ss.imbue(std::locale(std::locale(), new DecimalSeparator)); // fix locale problems
6199  ss << std::setprecision(std::numeric_limits<double>::digits10)
6200  << m_value.number_float;
6201  o << ss.str();
6202  }
6203  }
6204  return;
6205  }
6206 
6207  case value_t::discarded:
6208  {
6209  o << "<discarded>";
6210  return;
6211  }
6212 
6213  case value_t::null:
6214  {
6215  o << "null";
6216  return;
6217  }
6218  }
6219  }
6220 
6221  private:
6223  // member variables //
6225 
6227  type_data_t m_type = value_t::null;
6228 
6230  json_value m_value = {};
6231 
6232 
6233  private:
6235  // iterators //
6237 
6247  class primitive_iterator_t
6248  {
6249  public:
6251  void set_begin() noexcept
6252  {
6253  m_it = begin_value;
6254  }
6255 
6257  void set_end() noexcept
6258  {
6259  m_it = end_value;
6260  }
6261 
6263  constexpr bool is_begin() const noexcept
6264  {
6265  return (m_it == begin_value);
6266  }
6267 
6269  constexpr bool is_end() const noexcept
6270  {
6271  return (m_it == end_value);
6272  }
6273 
6275  operator difference_type& () noexcept
6276  {
6277  return m_it;
6278  }
6279 
6281  constexpr operator difference_type () const noexcept
6282  {
6283  return m_it;
6284  }
6285 
6286  private:
6287  static constexpr difference_type begin_value = 0;
6288  static constexpr difference_type end_value = begin_value + 1;
6289 
6291  difference_type m_it = std::numeric_limits<std::ptrdiff_t>::denorm_min();
6292  };
6293 
6301  struct internal_iterator
6302  {
6304  typename object_t::iterator object_iterator;
6306  typename array_t::iterator array_iterator;
6308  primitive_iterator_t primitive_iterator;
6309 
6311  internal_iterator() noexcept
6312  : object_iterator(), array_iterator(), primitive_iterator()
6313  {}
6314  };
6315 
6317  template<typename IteratorType>
6318  class iteration_proxy
6319  {
6320  private:
6322  class iteration_proxy_internal
6323  {
6324  private:
6326  IteratorType anchor;
6328  size_t array_index = 0;
6329 
6330  public:
6331  explicit iteration_proxy_internal(IteratorType it) noexcept
6332  : anchor(it)
6333  {}
6334 
6336  iteration_proxy_internal& operator*()
6337  {
6338  return *this;
6339  }
6340 
6342  iteration_proxy_internal& operator++()
6343  {
6344  ++anchor;
6345  ++array_index;
6346 
6347  return *this;
6348  }
6349 
6351  bool operator!= (const iteration_proxy_internal& o) const
6352  {
6353  return anchor != o.anchor;
6354  }
6355 
6357  typename basic_json::string_t key() const
6358  {
6359  assert(anchor.m_object != nullptr);
6360 
6361  switch (anchor.m_object->type())
6362  {
6363  // use integer array index as key
6364  case value_t::array:
6365  {
6366  return std::to_string(array_index);
6367  }
6368 
6369  // use key from the object
6370  case value_t::object:
6371  {
6372  return anchor.key();
6373  }
6374 
6375  // use an empty key for all primitive types
6376  default:
6377  {
6378  return "";
6379  }
6380  }
6381  }
6382 
6384  typename IteratorType::reference value() const
6385  {
6386  return anchor.value();
6387  }
6388  };
6389 
6391  typename IteratorType::reference container;
6392 
6393  public:
6395  explicit iteration_proxy(typename IteratorType::reference cont)
6396  : container(cont)
6397  {}
6398 
6400  iteration_proxy_internal begin() noexcept
6401  {
6402  return iteration_proxy_internal(container.begin());
6403  }
6404 
6406  iteration_proxy_internal end() noexcept
6407  {
6408  return iteration_proxy_internal(container.end());
6409  }
6410  };
6411 
6412  public:
6426  class const_iterator : public std::iterator<std::random_access_iterator_tag, const basic_json>
6427  {
6429  friend class basic_json;
6430 
6431  public:
6441  using iterator_category = std::bidirectional_iterator_tag;
6442 
6444  const_iterator() = default;
6445 
6447  explicit const_iterator(pointer object) noexcept
6448  : m_object(object)
6449  {
6450  assert(m_object != nullptr);
6451 
6452  switch (m_object->m_type)
6453  {
6455  {
6456  m_it.object_iterator = typename object_t::iterator();
6457  break;
6458  }
6459 
6461  {
6462  m_it.array_iterator = typename array_t::iterator();
6463  break;
6464  }
6465 
6466  default:
6467  {
6468  m_it.primitive_iterator = primitive_iterator_t();
6469  break;
6470  }
6471  }
6472  }
6473 
6475  explicit const_iterator(const iterator& other) noexcept
6476  : m_object(other.m_object)
6477  {
6478  assert(m_object != nullptr);
6479 
6480  switch (m_object->m_type)
6481  {
6483  {
6484  m_it.object_iterator = other.m_it.object_iterator;
6485  break;
6486  }
6487 
6489  {
6490  m_it.array_iterator = other.m_it.array_iterator;
6491  break;
6492  }
6493 
6494  default:
6495  {
6496  m_it.primitive_iterator = other.m_it.primitive_iterator;
6497  break;
6498  }
6499  }
6500  }
6501 
6503  const_iterator(const const_iterator& other) noexcept
6504  : m_object(other.m_object), m_it(other.m_it)
6505  {}
6506 
6509  std::is_nothrow_move_constructible<pointer>::value and
6510  std::is_nothrow_move_assignable<pointer>::value and
6511  std::is_nothrow_move_constructible<internal_iterator>::value and
6512  std::is_nothrow_move_assignable<internal_iterator>::value
6513  )
6514  {
6515  std::swap(m_object, other.m_object);
6516  std::swap(m_it, other.m_it);
6517  return *this;
6518  }
6519 
6520  private:
6522  void set_begin() noexcept
6523  {
6524  assert(m_object != nullptr);
6525 
6526  switch (m_object->m_type)
6527  {
6529  {
6530  assert(m_object->m_value.object != nullptr);
6531  m_it.object_iterator = m_object->m_value.object->begin();
6532  break;
6533  }
6534 
6536  {
6537  assert(m_object->m_value.array != nullptr);
6538  m_it.array_iterator = m_object->m_value.array->begin();
6539  break;
6540  }
6541 
6543  {
6544  // set to end so begin()==end() is true: null is empty
6545  m_it.primitive_iterator.set_end();
6546  break;
6547  }
6548 
6549  default:
6550  {
6551  m_it.primitive_iterator.set_begin();
6552  break;
6553  }
6554  }
6555  }
6556 
6558  void set_end() noexcept
6559  {
6560  assert(m_object != nullptr);
6561 
6562  switch (m_object->m_type)
6563  {
6565  {
6566  assert(m_object->m_value.object != nullptr);
6567  m_it.object_iterator = m_object->m_value.object->end();
6568  break;
6569  }
6570 
6572  {
6573  assert(m_object->m_value.array != nullptr);
6574  m_it.array_iterator = m_object->m_value.array->end();
6575  break;
6576  }
6577 
6578  default:
6579  {
6580  m_it.primitive_iterator.set_end();
6581  break;
6582  }
6583  }
6584  }
6585 
6586  public:
6589  {
6590  assert(m_object != nullptr);
6591 
6592  switch (m_object->m_type)
6593  {
6595  {
6596  assert(m_object->m_value.object);
6597  assert(m_it.object_iterator != m_object->m_value.object->end());
6598  return m_it.object_iterator->second;
6599  }
6600 
6602  {
6603  assert(m_object->m_value.array);
6604  assert(m_it.array_iterator != m_object->m_value.array->end());
6605  return *m_it.array_iterator;
6606  }
6607 
6609  {
6610  throw std::out_of_range("cannot get value");
6611  }
6612 
6613  default:
6614  {
6615  if (m_it.primitive_iterator.is_begin())
6616  {
6617  return *m_object;
6618  }
6619  else
6620  {
6621  throw std::out_of_range("cannot get value");
6622  }
6623  }
6624  }
6625  }
6626 
6629  {
6630  assert(m_object != nullptr);
6631 
6632  switch (m_object->m_type)
6633  {
6635  {
6636  assert(m_object->m_value.object);
6637  assert(m_it.object_iterator != m_object->m_value.object->end());
6638  return &(m_it.object_iterator->second);
6639  }
6640 
6642  {
6643  assert(m_object->m_value.array);
6644  assert(m_it.array_iterator != m_object->m_value.array->end());
6645  return &*m_it.array_iterator;
6646  }
6647 
6648  default:
6649  {
6650  if (m_it.primitive_iterator.is_begin())
6651  {
6652  return m_object;
6653  }
6654  else
6655  {
6656  throw std::out_of_range("cannot get value");
6657  }
6658  }
6659  }
6660  }
6661 
6664  {
6665  auto result = *this;
6666  ++(*this);
6667  return result;
6668  }
6669 
6672  {
6673  assert(m_object != nullptr);
6674 
6675  switch (m_object->m_type)
6676  {
6678  {
6679  ++m_it.object_iterator;
6680  break;
6681  }
6682 
6684  {
6685  ++m_it.array_iterator;
6686  break;
6687  }
6688 
6689  default:
6690  {
6691  ++m_it.primitive_iterator;
6692  break;
6693  }
6694  }
6695 
6696  return *this;
6697  }
6698 
6701  {
6702  auto result = *this;
6703  --(*this);
6704  return result;
6705  }
6706 
6709  {
6710  assert(m_object != nullptr);
6711 
6712  switch (m_object->m_type)
6713  {
6715  {
6716  --m_it.object_iterator;
6717  break;
6718  }
6719 
6721  {
6722  --m_it.array_iterator;
6723  break;
6724  }
6725 
6726  default:
6727  {
6728  --m_it.primitive_iterator;
6729  break;
6730  }
6731  }
6732 
6733  return *this;
6734  }
6735 
6737  bool operator==(const const_iterator& other) const
6738  {
6739  // if objects are not the same, the comparison is undefined
6740  if (m_object != other.m_object)
6741  {
6742  throw std::domain_error("cannot compare iterators of different containers");
6743  }
6744 
6745  assert(m_object != nullptr);
6746 
6747  switch (m_object->m_type)
6748  {
6750  {
6751  return (m_it.object_iterator == other.m_it.object_iterator);
6752  }
6753 
6755  {
6756  return (m_it.array_iterator == other.m_it.array_iterator);
6757  }
6758 
6759  default:
6760  {
6761  return (m_it.primitive_iterator == other.m_it.primitive_iterator);
6762  }
6763  }
6764  }
6765 
6767  bool operator!=(const const_iterator& other) const
6768  {
6769  return not operator==(other);
6770  }
6771 
6773  bool operator<(const const_iterator& other) const
6774  {
6775  // if objects are not the same, the comparison is undefined
6776  if (m_object != other.m_object)
6777  {
6778  throw std::domain_error("cannot compare iterators of different containers");
6779  }
6780 
6781  assert(m_object != nullptr);
6782 
6783  switch (m_object->m_type)
6784  {
6786  {
6787  throw std::domain_error("cannot compare order of object iterators");
6788  }
6789 
6791  {
6792  return (m_it.array_iterator < other.m_it.array_iterator);
6793  }
6794 
6795  default:
6796  {
6797  return (m_it.primitive_iterator < other.m_it.primitive_iterator);
6798  }
6799  }
6800  }
6801 
6803  bool operator<=(const const_iterator& other) const
6804  {
6805  return not other.operator < (*this);
6806  }
6807 
6809  bool operator>(const const_iterator& other) const
6810  {
6811  return not operator<=(other);
6812  }
6813 
6815  bool operator>=(const const_iterator& other) const
6816  {
6817  return not operator<(other);
6818  }
6819 
6822  {
6823  assert(m_object != nullptr);
6824 
6825  switch (m_object->m_type)
6826  {
6828  {
6829  throw std::domain_error("cannot use offsets with object iterators");
6830  }
6831 
6833  {
6834  m_it.array_iterator += i;
6835  break;
6836  }
6837 
6838  default:
6839  {
6840  m_it.primitive_iterator += i;
6841  break;
6842  }
6843  }
6844 
6845  return *this;
6846  }
6847 
6850  {
6851  return operator+=(-i);
6852  }
6853 
6856  {
6857  auto result = *this;
6858  result += i;
6859  return result;
6860  }
6861 
6864  {
6865  auto result = *this;
6866  result -= i;
6867  return result;
6868  }
6869 
6872  {
6873  assert(m_object != nullptr);
6874 
6875  switch (m_object->m_type)
6876  {
6878  {
6879  throw std::domain_error("cannot use offsets with object iterators");
6880  }
6881 
6883  {
6884  return m_it.array_iterator - other.m_it.array_iterator;
6885  }
6886 
6887  default:
6888  {
6889  return m_it.primitive_iterator - other.m_it.primitive_iterator;
6890  }
6891  }
6892  }
6893 
6896  {
6897  assert(m_object != nullptr);
6898 
6899  switch (m_object->m_type)
6900  {
6902  {
6903  throw std::domain_error("cannot use operator[] for object iterators");
6904  }
6905 
6907  {
6908  return *(m_it.array_iterator + n);
6909  }
6910 
6912  {
6913  throw std::out_of_range("cannot get value");
6914  }
6915 
6916  default:
6917  {
6918  if (m_it.primitive_iterator == -n)
6919  {
6920  return *m_object;
6921  }
6922  else
6923  {
6924  throw std::out_of_range("cannot get value");
6925  }
6926  }
6927  }
6928  }
6929 
6931  typename object_t::key_type key() const
6932  {
6933  assert(m_object != nullptr);
6934 
6935  if (m_object->is_object())
6936  {
6937  return m_it.object_iterator->first;
6938  }
6939  else
6940  {
6941  throw std::domain_error("cannot use key() for non-object iterators");
6942  }
6943  }
6944 
6947  {
6948  return operator*();
6949  }
6950 
6951  private:
6953  pointer m_object = nullptr;
6955  internal_iterator m_it = internal_iterator();
6956  };
6957 
6970  class iterator : public const_iterator
6971  {
6972  public:
6974  using pointer = typename basic_json::pointer;
6976 
6978  iterator() = default;
6979 
6981  explicit iterator(pointer object) noexcept
6982  : base_iterator(object)
6983  {}
6984 
6986  iterator(const iterator& other) noexcept
6987  : base_iterator(other)
6988  {}
6989 
6991  iterator& operator=(iterator other) noexcept(
6992  std::is_nothrow_move_constructible<pointer>::value and
6993  std::is_nothrow_move_assignable<pointer>::value and
6994  std::is_nothrow_move_constructible<internal_iterator>::value and
6995  std::is_nothrow_move_assignable<internal_iterator>::value
6996  )
6997  {
6998  base_iterator::operator=(other);
6999  return *this;
7000  }
7001 
7004  {
7005  return const_cast<reference>(base_iterator::operator*());
7006  }
7007 
7010  {
7011  return const_cast<pointer>(base_iterator::operator->());
7012  }
7013 
7016  {
7017  iterator result = *this;
7018  base_iterator::operator++();
7019  return result;
7020  }
7021 
7024  {
7025  base_iterator::operator++();
7026  return *this;
7027  }
7028 
7031  {
7032  iterator result = *this;
7033  base_iterator::operator--();
7034  return result;
7035  }
7036 
7039  {
7040  base_iterator::operator--();
7041  return *this;
7042  }
7043 
7046  {
7047  base_iterator::operator+=(i);
7048  return *this;
7049  }
7050 
7053  {
7054  base_iterator::operator-=(i);
7055  return *this;
7056  }
7057 
7060  {
7061  auto result = *this;
7062  result += i;
7063  return result;
7064  }
7065 
7068  {
7069  auto result = *this;
7070  result -= i;
7071  return result;
7072  }
7073 
7075  difference_type operator-(const iterator& other) const
7076  {
7077  return base_iterator::operator-(other);
7078  }
7079 
7082  {
7083  return const_cast<reference>(base_iterator::operator[](n));
7084  }
7085 
7088  {
7089  return const_cast<reference>(base_iterator::value());
7090  }
7091  };
7092 
7110  template<typename Base>
7111  class json_reverse_iterator : public std::reverse_iterator<Base>
7112  {
7113  public:
7115  using base_iterator = std::reverse_iterator<Base>;
7117  using reference = typename Base::reference;
7118 
7120  json_reverse_iterator(const typename base_iterator::iterator_type& it) noexcept
7121  : base_iterator(it)
7122  {}
7123 
7126  : base_iterator(it)
7127  {}
7128 
7131  {
7132  return base_iterator::operator++(1);
7133  }
7134 
7137  {
7138  base_iterator::operator++();
7139  return *this;
7140  }
7141 
7144  {
7145  return base_iterator::operator--(1);
7146  }
7147 
7150  {
7151  base_iterator::operator--();
7152  return *this;
7153  }
7154 
7157  {
7158  base_iterator::operator+=(i);
7159  return *this;
7160  }
7161 
7164  {
7165  auto result = *this;
7166  result += i;
7167  return result;
7168  }
7169 
7172  {
7173  auto result = *this;
7174  result -= i;
7175  return result;
7176  }
7177 
7180  {
7181  return this->base() - other.base();
7182  }
7183 
7186  {
7187  return *(this->operator+(n));
7188  }
7189 
7191  typename object_t::key_type key() const
7192  {
7193  auto it = --this->base();
7194  return it.key();
7195  }
7196 
7199  {
7200  auto it = --this->base();
7201  return it.operator * ();
7202  }
7203  };
7204 
7205 
7206  private:
7208  // lexer and parser //
7210 
7218  class lexer
7219  {
7220  public:
7222  enum class token_type
7223  {
7224  uninitialized,
7225  literal_true,
7226  literal_false,
7227  literal_null,
7228  value_string,
7229  value_number,
7230  begin_array,
7231  begin_object,
7232  end_array,
7233  end_object,
7234  name_separator,
7235  value_separator,
7236  parse_error,
7237  end_of_input
7238  };
7239 
7241  using lexer_char_t = unsigned char;
7242 
7244  explicit lexer(const string_t& s) noexcept
7245  : m_stream(nullptr), m_buffer(s)
7246  {
7247  m_content = reinterpret_cast<const lexer_char_t*>(s.c_str());
7248  assert(m_content != nullptr);
7249  m_start = m_cursor = m_content;
7250  m_limit = m_content + s.size();
7251  }
7252 
7254  explicit lexer(std::istream* s) noexcept
7255  : m_stream(s), m_buffer()
7256  {
7257  assert(m_stream != nullptr);
7258  getline(*m_stream, m_buffer);
7259  m_content = reinterpret_cast<const lexer_char_t*>(m_buffer.c_str());
7260  assert(m_content != nullptr);
7261  m_start = m_cursor = m_content;
7262  m_limit = m_content + m_buffer.size();
7263  }
7264 
7266  lexer() = default;
7267 
7268  // switch off unwanted functions
7269  lexer(const lexer&) = delete;
7270  lexer operator=(const lexer&) = delete;
7271 
7287  static string_t to_unicode(const std::size_t codepoint1,
7288  const std::size_t codepoint2 = 0)
7289  {
7290  // calculate the codepoint from the given code points
7291  std::size_t codepoint = codepoint1;
7292 
7293  // check if codepoint1 is a high surrogate
7294  if (codepoint1 >= 0xD800 and codepoint1 <= 0xDBFF)
7295  {
7296  // check if codepoint2 is a low surrogate
7297  if (codepoint2 >= 0xDC00 and codepoint2 <= 0xDFFF)
7298  {
7299  codepoint =
7300  // high surrogate occupies the most significant 22 bits
7301  (codepoint1 << 10)
7302  // low surrogate occupies the least significant 15 bits
7303  + codepoint2
7304  // there is still the 0xD800, 0xDC00 and 0x10000 noise
7305  // in the result so we have to subtract with:
7306  // (0xD800 << 10) + DC00 - 0x10000 = 0x35FDC00
7307  - 0x35FDC00;
7308  }
7309  else
7310  {
7311  throw std::invalid_argument("missing or wrong low surrogate");
7312  }
7313  }
7314 
7315  string_t result;
7316 
7317  if (codepoint < 0x80)
7318  {
7319  // 1-byte characters: 0xxxxxxx (ASCII)
7320  result.append(1, static_cast<typename string_t::value_type>(codepoint));
7321  }
7322  else if (codepoint <= 0x7ff)
7323  {
7324  // 2-byte characters: 110xxxxx 10xxxxxx
7325  result.append(1, static_cast<typename string_t::value_type>(0xC0 | ((codepoint >> 6) & 0x1F)));
7326  result.append(1, static_cast<typename string_t::value_type>(0x80 | (codepoint & 0x3F)));
7327  }
7328  else if (codepoint <= 0xffff)
7329  {
7330  // 3-byte characters: 1110xxxx 10xxxxxx 10xxxxxx
7331  result.append(1, static_cast<typename string_t::value_type>(0xE0 | ((codepoint >> 12) & 0x0F)));
7332  result.append(1, static_cast<typename string_t::value_type>(0x80 | ((codepoint >> 6) & 0x3F)));
7333  result.append(1, static_cast<typename string_t::value_type>(0x80 | (codepoint & 0x3F)));
7334  }
7335  else if (codepoint <= 0x10ffff)
7336  {
7337  // 4-byte characters: 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
7338  result.append(1, static_cast<typename string_t::value_type>(0xF0 | ((codepoint >> 18) & 0x07)));
7339  result.append(1, static_cast<typename string_t::value_type>(0x80 | ((codepoint >> 12) & 0x3F)));
7340  result.append(1, static_cast<typename string_t::value_type>(0x80 | ((codepoint >> 6) & 0x3F)));
7341  result.append(1, static_cast<typename string_t::value_type>(0x80 | (codepoint & 0x3F)));
7342  }
7343  else
7344  {
7345  throw std::out_of_range("code points above 0x10FFFF are invalid");
7346  }
7347 
7348  return result;
7349  }
7350 
7352  static std::string token_type_name(token_type t)
7353  {
7354  switch (t)
7355  {
7356  case token_type::uninitialized:
7357  return "<uninitialized>";
7358  case token_type::literal_true:
7359  return "true literal";
7360  case token_type::literal_false:
7361  return "false literal";
7362  case token_type::literal_null:
7363  return "null literal";
7364  case token_type::value_string:
7365  return "string literal";
7366  case token_type::value_number:
7367  return "number literal";
7368  case token_type::begin_array:
7369  return "'['";
7370  case token_type::begin_object:
7371  return "'{'";
7372  case token_type::end_array:
7373  return "']'";
7374  case token_type::end_object:
7375  return "'}'";
7376  case token_type::name_separator:
7377  return "':'";
7378  case token_type::value_separator:
7379  return "','";
7380  case token_type::parse_error:
7381  return "<parse error>";
7382  case token_type::end_of_input:
7383  return "end of input";
7384  default:
7385  {
7386  // catch non-enum values
7387  return "unknown token"; // LCOV_EXCL_LINE
7388  }
7389  }
7390  }
7391 
7402  token_type scan() noexcept
7403  {
7404  // pointer for backtracking information
7405  m_marker = nullptr;
7406 
7407  // remember the begin of the token
7408  m_start = m_cursor;
7409  assert(m_start != nullptr);
7410 
7411 
7412  {
7413  lexer_char_t yych;
7414  unsigned int yyaccept = 0;
7415  static const unsigned char yybm[] =
7416  {
7417  0, 0, 0, 0, 0, 0, 0, 0,
7418  0, 32, 32, 0, 0, 32, 0, 0,
7419  128, 128, 128, 128, 128, 128, 128, 128,
7420  128, 128, 128, 128, 128, 128, 128, 128,
7421  160, 128, 0, 128, 128, 128, 128, 128,
7422  128, 128, 128, 128, 128, 128, 128, 128,
7423  192, 192, 192, 192, 192, 192, 192, 192,
7424  192, 192, 128, 128, 128, 128, 128, 128,
7425  128, 128, 128, 128, 128, 128, 128, 128,
7426  128, 128, 128, 128, 128, 128, 128, 128,
7427  128, 128, 128, 128, 128, 128, 128, 128,
7428  128, 128, 128, 128, 0, 128, 128, 128,
7429  128, 128, 128, 128, 128, 128, 128, 128,
7430  128, 128, 128, 128, 128, 128, 128, 128,
7431  128, 128, 128, 128, 128, 128, 128, 128,
7432  128, 128, 128, 128, 128, 128, 128, 128,
7433  128, 128, 128, 128, 128, 128, 128, 128,
7434  128, 128, 128, 128, 128, 128, 128, 128,
7435  128, 128, 128, 128, 128, 128, 128, 128,
7436  128, 128, 128, 128, 128, 128, 128, 128,
7437  128, 128, 128, 128, 128, 128, 128, 128,
7438  128, 128, 128, 128, 128, 128, 128, 128,
7439  128, 128, 128, 128, 128, 128, 128, 128,
7440  128, 128, 128, 128, 128, 128, 128, 128,
7441  128, 128, 128, 128, 128, 128, 128, 128,
7442  128, 128, 128, 128, 128, 128, 128, 128,
7443  128, 128, 128, 128, 128, 128, 128, 128,
7444  128, 128, 128, 128, 128, 128, 128, 128,
7445  128, 128, 128, 128, 128, 128, 128, 128,
7446  128, 128, 128, 128, 128, 128, 128, 128,
7447  128, 128, 128, 128, 128, 128, 128, 128,
7448  128, 128, 128, 128, 128, 128, 128, 128,
7449  };
7450  if ((m_limit - m_cursor) < 5)
7451  {
7452  yyfill(); // LCOV_EXCL_LINE;
7453  }
7454  yych = *m_cursor;
7455  if (yybm[0 + yych] & 32)
7456  {
7457  goto basic_json_parser_6;
7458  }
7459  if (yych <= '\\')
7460  {
7461  if (yych <= '-')
7462  {
7463  if (yych <= '"')
7464  {
7465  if (yych <= 0x00)
7466  {
7467  goto basic_json_parser_2;
7468  }
7469  if (yych <= '!')
7470  {
7471  goto basic_json_parser_4;
7472  }
7473  goto basic_json_parser_9;
7474  }
7475  else
7476  {
7477  if (yych <= '+')
7478  {
7479  goto basic_json_parser_4;
7480  }
7481  if (yych <= ',')
7482  {
7483  goto basic_json_parser_10;
7484  }
7485  goto basic_json_parser_12;
7486  }
7487  }
7488  else
7489  {
7490  if (yych <= '9')
7491  {
7492  if (yych <= '/')
7493  {
7494  goto basic_json_parser_4;
7495  }
7496  if (yych <= '0')
7497  {
7498  goto basic_json_parser_13;
7499  }
7500  goto basic_json_parser_15;
7501  }
7502  else
7503  {
7504  if (yych <= ':')
7505  {
7506  goto basic_json_parser_17;
7507  }
7508  if (yych == '[')
7509  {
7510  goto basic_json_parser_19;
7511  }
7512  goto basic_json_parser_4;
7513  }
7514  }
7515  }
7516  else
7517  {
7518  if (yych <= 't')
7519  {
7520  if (yych <= 'f')
7521  {
7522  if (yych <= ']')
7523  {
7524  goto basic_json_parser_21;
7525  }
7526  if (yych <= 'e')
7527  {
7528  goto basic_json_parser_4;
7529  }
7530  goto basic_json_parser_23;
7531  }
7532  else
7533  {
7534  if (yych == 'n')
7535  {
7536  goto basic_json_parser_24;
7537  }
7538  if (yych <= 's')
7539  {
7540  goto basic_json_parser_4;
7541  }
7542  goto basic_json_parser_25;
7543  }
7544  }
7545  else
7546  {
7547  if (yych <= '|')
7548  {
7549  if (yych == '{')
7550  {
7551  goto basic_json_parser_26;
7552  }
7553  goto basic_json_parser_4;
7554  }
7555  else
7556  {
7557  if (yych <= '}')
7558  {
7559  goto basic_json_parser_28;
7560  }
7561  if (yych == 0xEF)
7562  {
7563  goto basic_json_parser_30;
7564  }
7565  goto basic_json_parser_4;
7566  }
7567  }
7568  }
7569 basic_json_parser_2:
7570  ++m_cursor;
7571  {
7572  return token_type::end_of_input;
7573  }
7574 basic_json_parser_4:
7575  ++m_cursor;
7576 basic_json_parser_5:
7577  {
7578  return token_type::parse_error;
7579  }
7580 basic_json_parser_6:
7581  ++m_cursor;
7582  if (m_limit <= m_cursor)
7583  {
7584  yyfill(); // LCOV_EXCL_LINE;
7585  }
7586  yych = *m_cursor;
7587  if (yybm[0 + yych] & 32)
7588  {
7589  goto basic_json_parser_6;
7590  }
7591  {
7592  return scan();
7593  }
7594 basic_json_parser_9:
7595  yyaccept = 0;
7596  yych = *(m_marker = ++m_cursor);
7597  if (yych <= 0x0F)
7598  {
7599  goto basic_json_parser_5;
7600  }
7601  goto basic_json_parser_32;
7602 basic_json_parser_10:
7603  ++m_cursor;
7604  {
7605  return token_type::value_separator;
7606  }
7607 basic_json_parser_12:
7608  yych = *++m_cursor;
7609  if (yych <= '/')
7610  {
7611  goto basic_json_parser_5;
7612  }
7613  if (yych <= '0')
7614  {
7615  goto basic_json_parser_13;
7616  }
7617  if (yych <= '9')
7618  {
7619  goto basic_json_parser_15;
7620  }
7621  goto basic_json_parser_5;
7622 basic_json_parser_13:
7623  yyaccept = 1;
7624  yych = *(m_marker = ++m_cursor);
7625  if (yych <= 'D')
7626  {
7627  if (yych == '.')
7628  {
7629  goto basic_json_parser_37;
7630  }
7631  }
7632  else
7633  {
7634  if (yych <= 'E')
7635  {
7636  goto basic_json_parser_38;
7637  }
7638  if (yych == 'e')
7639  {
7640  goto basic_json_parser_38;
7641  }
7642  }
7643 basic_json_parser_14:
7644  {
7645  return token_type::value_number;
7646  }
7647 basic_json_parser_15:
7648  yyaccept = 1;
7649  m_marker = ++m_cursor;
7650  if ((m_limit - m_cursor) < 3)
7651  {
7652  yyfill(); // LCOV_EXCL_LINE;
7653  }
7654  yych = *m_cursor;
7655  if (yybm[0 + yych] & 64)
7656  {
7657  goto basic_json_parser_15;
7658  }
7659  if (yych <= 'D')
7660  {
7661  if (yych == '.')
7662  {
7663  goto basic_json_parser_37;
7664  }
7665  goto basic_json_parser_14;
7666  }
7667  else
7668  {
7669  if (yych <= 'E')
7670  {
7671  goto basic_json_parser_38;
7672  }
7673  if (yych == 'e')
7674  {
7675  goto basic_json_parser_38;
7676  }
7677  goto basic_json_parser_14;
7678  }
7679 basic_json_parser_17:
7680  ++m_cursor;
7681  {
7682  return token_type::name_separator;
7683  }
7684 basic_json_parser_19:
7685  ++m_cursor;
7686  {
7687  return token_type::begin_array;
7688  }
7689 basic_json_parser_21:
7690  ++m_cursor;
7691  {
7692  return token_type::end_array;
7693  }
7694 basic_json_parser_23:
7695  yyaccept = 0;
7696  yych = *(m_marker = ++m_cursor);
7697  if (yych == 'a')
7698  {
7699  goto basic_json_parser_39;
7700  }
7701  goto basic_json_parser_5;
7702 basic_json_parser_24:
7703  yyaccept = 0;
7704  yych = *(m_marker = ++m_cursor);
7705  if (yych == 'u')
7706  {
7707  goto basic_json_parser_40;
7708  }
7709  goto basic_json_parser_5;
7710 basic_json_parser_25:
7711  yyaccept = 0;
7712  yych = *(m_marker = ++m_cursor);
7713  if (yych == 'r')
7714  {
7715  goto basic_json_parser_41;
7716  }
7717  goto basic_json_parser_5;
7718 basic_json_parser_26:
7719  ++m_cursor;
7720  {
7721  return token_type::begin_object;
7722  }
7723 basic_json_parser_28:
7724  ++m_cursor;
7725  {
7726  return token_type::end_object;
7727  }
7728 basic_json_parser_30:
7729  yyaccept = 0;
7730  yych = *(m_marker = ++m_cursor);
7731  if (yych == 0xBB)
7732  {
7733  goto basic_json_parser_42;
7734  }
7735  goto basic_json_parser_5;
7736 basic_json_parser_31:
7737  ++m_cursor;
7738  if (m_limit <= m_cursor)
7739  {
7740  yyfill(); // LCOV_EXCL_LINE;
7741  }
7742  yych = *m_cursor;
7743 basic_json_parser_32:
7744  if (yybm[0 + yych] & 128)
7745  {
7746  goto basic_json_parser_31;
7747  }
7748  if (yych <= 0x0F)
7749  {
7750  goto basic_json_parser_33;
7751  }
7752  if (yych <= '"')
7753  {
7754  goto basic_json_parser_34;
7755  }
7756  goto basic_json_parser_36;
7757 basic_json_parser_33:
7758  m_cursor = m_marker;
7759  if (yyaccept == 0)
7760  {
7761  goto basic_json_parser_5;
7762  }
7763  else
7764  {
7765  goto basic_json_parser_14;
7766  }
7767 basic_json_parser_34:
7768  ++m_cursor;
7769  {
7770  return token_type::value_string;
7771  }
7772 basic_json_parser_36:
7773  ++m_cursor;
7774  if (m_limit <= m_cursor)
7775  {
7776  yyfill(); // LCOV_EXCL_LINE;
7777  }
7778  yych = *m_cursor;
7779  if (yych <= 'e')
7780  {
7781  if (yych <= '/')
7782  {
7783  if (yych == '"')
7784  {
7785  goto basic_json_parser_31;
7786  }
7787  if (yych <= '.')
7788  {
7789  goto basic_json_parser_33;
7790  }
7791  goto basic_json_parser_31;
7792  }
7793  else
7794  {
7795  if (yych <= '\\')
7796  {
7797  if (yych <= '[')
7798  {
7799  goto basic_json_parser_33;
7800  }
7801  goto basic_json_parser_31;
7802  }
7803  else
7804  {
7805  if (yych == 'b')
7806  {
7807  goto basic_json_parser_31;
7808  }
7809  goto basic_json_parser_33;
7810  }
7811  }
7812  }
7813  else
7814  {
7815  if (yych <= 'q')
7816  {
7817  if (yych <= 'f')
7818  {
7819  goto basic_json_parser_31;
7820  }
7821  if (yych == 'n')
7822  {
7823  goto basic_json_parser_31;
7824  }
7825  goto basic_json_parser_33;
7826  }
7827  else
7828  {
7829  if (yych <= 's')
7830  {
7831  if (yych <= 'r')
7832  {
7833  goto basic_json_parser_31;
7834  }
7835  goto basic_json_parser_33;
7836  }
7837  else
7838  {
7839  if (yych <= 't')
7840  {
7841  goto basic_json_parser_31;
7842  }
7843  if (yych <= 'u')
7844  {
7845  goto basic_json_parser_43;
7846  }
7847  goto basic_json_parser_33;
7848  }
7849  }
7850  }
7851 basic_json_parser_37:
7852  yych = *++m_cursor;
7853  if (yych <= '/')
7854  {
7855  goto basic_json_parser_33;
7856  }
7857  if (yych <= '9')
7858  {
7859  goto basic_json_parser_44;
7860  }
7861  goto basic_json_parser_33;
7862 basic_json_parser_38:
7863  yych = *++m_cursor;
7864  if (yych <= ',')
7865  {
7866  if (yych == '+')
7867  {
7868  goto basic_json_parser_46;
7869  }
7870  goto basic_json_parser_33;
7871  }
7872  else
7873  {
7874  if (yych <= '-')
7875  {
7876  goto basic_json_parser_46;
7877  }
7878  if (yych <= '/')
7879  {
7880  goto basic_json_parser_33;
7881  }
7882  if (yych <= '9')
7883  {
7884  goto basic_json_parser_47;
7885  }
7886  goto basic_json_parser_33;
7887  }
7888 basic_json_parser_39:
7889  yych = *++m_cursor;
7890  if (yych == 'l')
7891  {
7892  goto basic_json_parser_49;
7893  }
7894  goto basic_json_parser_33;
7895 basic_json_parser_40:
7896  yych = *++m_cursor;
7897  if (yych == 'l')
7898  {
7899  goto basic_json_parser_50;
7900  }
7901  goto basic_json_parser_33;
7902 basic_json_parser_41:
7903  yych = *++m_cursor;
7904  if (yych == 'u')
7905  {
7906  goto basic_json_parser_51;
7907  }
7908  goto basic_json_parser_33;
7909 basic_json_parser_42:
7910  yych = *++m_cursor;
7911  if (yych == 0xBF)
7912  {
7913  goto basic_json_parser_52;
7914  }
7915  goto basic_json_parser_33;
7916 basic_json_parser_43:
7917  ++m_cursor;
7918  if (m_limit <= m_cursor)
7919  {
7920  yyfill(); // LCOV_EXCL_LINE;
7921  }
7922  yych = *m_cursor;
7923  if (yych <= '@')
7924  {
7925  if (yych <= '/')
7926  {
7927  goto basic_json_parser_33;
7928  }
7929  if (yych <= '9')
7930  {
7931  goto basic_json_parser_54;
7932  }
7933  goto basic_json_parser_33;
7934  }
7935  else
7936  {
7937  if (yych <= 'F')
7938  {
7939  goto basic_json_parser_54;
7940  }
7941  if (yych <= '`')
7942  {
7943  goto basic_json_parser_33;
7944  }
7945  if (yych <= 'f')
7946  {
7947  goto basic_json_parser_54;
7948  }
7949  goto basic_json_parser_33;
7950  }
7951 basic_json_parser_44:
7952  yyaccept = 1;
7953  m_marker = ++m_cursor;
7954  if ((m_limit - m_cursor) < 3)
7955  {
7956  yyfill(); // LCOV_EXCL_LINE;
7957  }
7958  yych = *m_cursor;
7959  if (yych <= 'D')
7960  {
7961  if (yych <= '/')
7962  {
7963  goto basic_json_parser_14;
7964  }
7965  if (yych <= '9')
7966  {
7967  goto basic_json_parser_44;
7968  }
7969  goto basic_json_parser_14;
7970  }
7971  else
7972  {
7973  if (yych <= 'E')
7974  {
7975  goto basic_json_parser_38;
7976  }
7977  if (yych == 'e')
7978  {
7979  goto basic_json_parser_38;
7980  }
7981  goto basic_json_parser_14;
7982  }
7983 basic_json_parser_46:
7984  yych = *++m_cursor;
7985  if (yych <= '/')
7986  {
7987  goto basic_json_parser_33;
7988  }
7989  if (yych >= ':')
7990  {
7991  goto basic_json_parser_33;
7992  }
7993 basic_json_parser_47:
7994  ++m_cursor;
7995  if (m_limit <= m_cursor)
7996  {
7997  yyfill(); // LCOV_EXCL_LINE;
7998  }
7999  yych = *m_cursor;
8000  if (yych <= '/')
8001  {
8002  goto basic_json_parser_14;
8003  }
8004  if (yych <= '9')
8005  {
8006  goto basic_json_parser_47;
8007  }
8008  goto basic_json_parser_14;
8009 basic_json_parser_49:
8010  yych = *++m_cursor;
8011  if (yych == 's')
8012  {
8013  goto basic_json_parser_55;
8014  }
8015  goto basic_json_parser_33;
8016 basic_json_parser_50:
8017  yych = *++m_cursor;
8018  if (yych == 'l')
8019  {
8020  goto basic_json_parser_56;
8021  }
8022  goto basic_json_parser_33;
8023 basic_json_parser_51:
8024  yych = *++m_cursor;
8025  if (yych == 'e')
8026  {
8027  goto basic_json_parser_58;
8028  }
8029  goto basic_json_parser_33;
8030 basic_json_parser_52:
8031  ++m_cursor;
8032  {
8033  return scan();
8034  }
8035 basic_json_parser_54:
8036  ++m_cursor;
8037  if (m_limit <= m_cursor)
8038  {
8039  yyfill(); // LCOV_EXCL_LINE;
8040  }
8041  yych = *m_cursor;
8042  if (yych <= '@')
8043  {
8044  if (yych <= '/')
8045  {
8046  goto basic_json_parser_33;
8047  }
8048  if (yych <= '9')
8049  {
8050  goto basic_json_parser_60;
8051  }
8052  goto basic_json_parser_33;
8053  }
8054  else
8055  {
8056  if (yych <= 'F')
8057  {
8058  goto basic_json_parser_60;
8059  }
8060  if (yych <= '`')
8061  {
8062  goto basic_json_parser_33;
8063  }
8064  if (yych <= 'f')
8065  {
8066  goto basic_json_parser_60;
8067  }
8068  goto basic_json_parser_33;
8069  }
8070 basic_json_parser_55:
8071  yych = *++m_cursor;
8072  if (yych == 'e')
8073  {
8074  goto basic_json_parser_61;
8075  }
8076  goto basic_json_parser_33;
8077 basic_json_parser_56:
8078  ++m_cursor;
8079  {
8080  return token_type::literal_null;
8081  }
8082 basic_json_parser_58:
8083  ++m_cursor;
8084  {
8085  return token_type::literal_true;
8086  }
8087 basic_json_parser_60:
8088  ++m_cursor;
8089  if (m_limit <= m_cursor)
8090  {
8091  yyfill(); // LCOV_EXCL_LINE;
8092  }
8093  yych = *m_cursor;
8094  if (yych <= '@')
8095  {
8096  if (yych <= '/')
8097  {
8098  goto basic_json_parser_33;
8099  }
8100  if (yych <= '9')
8101  {
8102  goto basic_json_parser_63;
8103  }
8104  goto basic_json_parser_33;
8105  }
8106  else
8107  {
8108  if (yych <= 'F')
8109  {
8110  goto basic_json_parser_63;
8111  }
8112  if (yych <= '`')
8113  {
8114  goto basic_json_parser_33;
8115  }
8116  if (yych <= 'f')
8117  {
8118  goto basic_json_parser_63;
8119  }
8120  goto basic_json_parser_33;
8121  }
8122 basic_json_parser_61:
8123  ++m_cursor;
8124  {
8125  return token_type::literal_false;
8126  }
8127 basic_json_parser_63:
8128  ++m_cursor;
8129  if (m_limit <= m_cursor)
8130  {
8131  yyfill(); // LCOV_EXCL_LINE;
8132  }
8133  yych = *m_cursor;
8134  if (yych <= '@')
8135  {
8136  if (yych <= '/')
8137  {
8138  goto basic_json_parser_33;
8139  }
8140  if (yych <= '9')
8141  {
8142  goto basic_json_parser_31;
8143  }
8144  goto basic_json_parser_33;
8145  }
8146  else
8147  {
8148  if (yych <= 'F')
8149  {
8150  goto basic_json_parser_31;
8151  }
8152  if (yych <= '`')
8153  {
8154  goto basic_json_parser_33;
8155  }
8156  if (yych <= 'f')
8157  {
8158  goto basic_json_parser_31;
8159  }
8160  goto basic_json_parser_33;
8161  }
8162  }
8163 
8164  }
8165 
8167  void yyfill() noexcept
8168  {
8169  if (m_stream == nullptr or not * m_stream)
8170  {
8171  return;
8172  }
8173 
8174  const auto offset_start = m_start - m_content;
8175  const auto offset_marker = m_marker - m_start;
8176  const auto offset_cursor = m_cursor - m_start;
8177 
8178  m_buffer.erase(0, static_cast<size_t>(offset_start));
8179  std::string line;
8180  assert(m_stream != nullptr);
8181  std::getline(*m_stream, line);
8182  m_buffer += "\n" + line; // add line with newline symbol
8183 
8184  m_content = reinterpret_cast<const lexer_char_t*>(m_buffer.c_str());
8185  assert(m_content != nullptr);
8186  m_start = m_content;
8187  m_marker = m_start + offset_marker;
8188  m_cursor = m_start + offset_cursor;
8189  m_limit = m_start + m_buffer.size() - 1;
8190  }
8191 
8193  string_t get_token() const
8194  {
8195  assert(m_start != nullptr);
8196  return string_t(reinterpret_cast<typename string_t::const_pointer>(m_start),
8197  static_cast<size_t>(m_cursor - m_start));
8198  }
8199 
8221  string_t get_string() const
8222  {
8223  string_t result;
8224  result.reserve(static_cast<size_t>(m_cursor - m_start - 2));
8225 
8226  // iterate the result between the quotes
8227  for (const lexer_char_t* i = m_start + 1; i < m_cursor - 1; ++i)
8228  {
8229  // process escaped characters
8230  if (*i == '\\')
8231  {
8232  // read next character
8233  ++i;
8234 
8235  switch (*i)
8236  {
8237  // the default escapes
8238  case 't':
8239  {
8240  result += "\t";
8241  break;
8242  }
8243  case 'b':
8244  {
8245  result += "\b";
8246  break;
8247  }
8248  case 'f':
8249  {
8250  result += "\f";
8251  break;
8252  }
8253  case 'n':
8254  {
8255  result += "\n";
8256  break;
8257  }
8258  case 'r':
8259  {
8260  result += "\r";
8261  break;
8262  }
8263  case '\\':
8264  {
8265  result += "\\";
8266  break;
8267  }
8268  case '/':
8269  {
8270  result += "/";
8271  break;
8272  }
8273  case '"':
8274  {
8275  result += "\"";
8276  break;
8277  }
8278 
8279  // unicode
8280  case 'u':
8281  {
8282  // get code xxxx from uxxxx
8283  auto codepoint = std::strtoul(std::string(reinterpret_cast<typename string_t::const_pointer>(i + 1),
8284  4).c_str(), nullptr, 16);
8285 
8286  // check if codepoint is a high surrogate
8287  if (codepoint >= 0xD800 and codepoint <= 0xDBFF)
8288  {
8289  // make sure there is a subsequent unicode
8290  if ((i + 6 >= m_limit) or * (i + 5) != '\\' or * (i + 6) != 'u')
8291  {
8292  throw std::invalid_argument("missing low surrogate");
8293  }
8294 
8295  // get code yyyy from uxxxx\uyyyy
8296  auto codepoint2 = std::strtoul(std::string(reinterpret_cast<typename string_t::const_pointer>
8297  (i + 7), 4).c_str(), nullptr, 16);
8298  result += to_unicode(codepoint, codepoint2);
8299  // skip the next 10 characters (xxxx\uyyyy)
8300  i += 10;
8301  }
8302  else
8303  {
8304  // add unicode character(s)
8305  result += to_unicode(codepoint);
8306  // skip the next four characters (xxxx)
8307  i += 4;
8308  }
8309  break;
8310  }
8311  }
8312  }
8313  else
8314  {
8315  // all other characters are just copied to the end of the
8316  // string
8317  result.append(1, static_cast<typename string_t::value_type>(*i));
8318  }
8319  }
8320 
8321  return result;
8322  }
8323 
8344  long double str_to_float_t(long double* /* type */, char** endptr) const
8345  {
8346  return std::strtold(reinterpret_cast<typename string_t::const_pointer>(m_start), endptr);
8347  }
8348 
8364  double str_to_float_t(double* /* type */, char** endptr) const
8365  {
8366  return std::strtod(reinterpret_cast<typename string_t::const_pointer>(m_start), endptr);
8367  }
8368 
8384  float str_to_float_t(float* /* type */, char** endptr) const
8385  {
8386  return std::strtof(reinterpret_cast<typename string_t::const_pointer>(m_start), endptr);
8387  }
8388 
8416  void get_number(basic_json& result) const
8417  {
8418  assert(m_start != nullptr);
8419 
8420  const lexer::lexer_char_t* curptr = m_start;
8421 
8422  // remember this number was parsed (for later serialization)
8423  result.m_type.bits.parsed = true;
8424 
8425  // 'found_radix_point' will be set to 0xFF upon finding a radix
8426  // point and later used to mask in/out the precision depending
8427  // whether a radix is found i.e. 'precision &= found_radix_point'
8428  uint8_t found_radix_point = 0;
8429  uint8_t precision = 0;
8430 
8431  // accumulate the integer conversion result (unsigned for now)
8432  number_unsigned_t value = 0;
8433 
8434  // maximum absolute value of the relevant integer type
8435  number_unsigned_t max;
8436 
8437  // temporarily store the type to avoid unecessary bitfield access
8438  value_t type;
8439 
8440  // look for sign
8441  if (*curptr == '-')
8442  {
8443  type = value_t::number_integer;
8444  max = static_cast<uint64_t>(std::numeric_limits<number_integer_t>::max()) + 1;
8445  curptr++;
8446  }
8447  else
8448  {
8449  type = value_t::number_unsigned;
8450  max = static_cast<uint64_t>(std::numeric_limits<number_unsigned_t>::max());
8451  if (*curptr == '+')
8452  {
8453  curptr++;
8454  }
8455  }
8456 
8457  // count the significant figures
8458  for (; curptr < m_cursor; curptr++)
8459  {
8460  // quickly skip tests if a digit
8461  if (*curptr < '0' || *curptr > '9')
8462  {
8463  if (*curptr == '.')
8464  {
8465  // don't count '.' but change to float
8466  type = value_t::number_float;
8467 
8468  // reset precision count
8469  precision = 0;
8470  found_radix_point = 0xFF;
8471  continue;
8472  }
8473  // assume exponent (if not then will fail parse): change to
8474  // float, stop counting and record exponent details
8475  type = value_t::number_float;
8476  result.m_type.bits.has_exp = true;
8477 
8478  // exponent capitalization
8479  result.m_type.bits.exp_cap = (*curptr == 'E');
8480 
8481  // exponent '+' sign
8482  result.m_type.bits.exp_plus = (*(++curptr) == '+');
8483  break;
8484  }
8485 
8486  // skip if definitely not an integer
8487  if (type != value_t::number_float)
8488  {
8489  // multiply last value by ten and add the new digit
8490  auto temp = value * 10 + *curptr - 0x30;
8491 
8492  // test for overflow
8493  if (temp < value || temp > max)
8494  {
8495  // overflow
8496  type = value_t::number_float;
8497  }
8498  else
8499  {
8500  // no overflow - save it
8501  value = temp;
8502  }
8503  }
8504  ++precision;
8505  }
8506 
8507  // If no radix point was found then precision would now be set to
8508  // the number of digits, which is wrong - clear it.
8509  result.m_type.bits.precision = precision & found_radix_point;
8510 
8511  // save the value (if not a float)
8512  if (type == value_t::number_unsigned)
8513  {
8514  result.m_value.number_unsigned = value;
8515  }
8516  else if (type == value_t::number_integer)
8517  {
8518  result.m_value.number_integer = -static_cast<number_integer_t>(value);
8519  }
8520  else
8521  {
8522  // parse with strtod
8523  result.m_value.number_float = str_to_float_t(static_cast<number_float_t*>(nullptr), NULL);
8524  }
8525 
8526  // save the type
8527  result.m_type = type;
8528  }
8529 
8530  private:
8532  std::istream* m_stream = nullptr;
8534  string_t m_buffer;
8536  const lexer_char_t* m_content = nullptr;
8538  const lexer_char_t* m_start = nullptr;
8540  const lexer_char_t* m_marker = nullptr;
8542  const lexer_char_t* m_cursor = nullptr;
8544  const lexer_char_t* m_limit = nullptr;
8545  };
8546 
8552  class parser
8553  {
8554  public:
8556  parser(const string_t& s, parser_callback_t cb = nullptr) noexcept
8557  : callback(cb), m_lexer(s)
8558  {
8559  // read first token
8560  get_token();
8561  }
8562 
8564  parser(std::istream& _is, parser_callback_t cb = nullptr) noexcept
8565  : callback(cb), m_lexer(&_is)
8566  {
8567  // read first token
8568  get_token();
8569  }
8570 
8572  basic_json parse()
8573  {
8574  basic_json result = parse_internal(true);
8575 
8576  expect(lexer::token_type::end_of_input);
8577 
8578  // return parser result and replace it with null in case the
8579  // top-level value was discarded by the callback function
8580  return result.is_discarded() ? basic_json() : result;
8581  }
8582 
8583  private:
8585  basic_json parse_internal(bool keep)
8586  {
8587  auto result = basic_json(value_t::discarded);
8588 
8589  switch (last_token)
8590  {
8591  case lexer::token_type::begin_object:
8592  {
8593  if (keep and (not callback or (keep = callback(depth++, parse_event_t::object_start, result))))
8594  {
8595  // explicitly set result to object to cope with {}
8596  result.m_type = value_t::object;
8597  result.m_value = json_value(value_t::object);
8598  }
8599 
8600  // read next token
8601  get_token();
8602 
8603  // closing } -> we are done
8604  if (last_token == lexer::token_type::end_object)
8605  {
8606  get_token();
8607  if (keep and callback and not callback(--depth, parse_event_t::object_end, result))
8608  {
8609  result = basic_json(value_t::discarded);
8610  }
8611  return result;
8612  }
8613 
8614  // no comma is expected here
8615  unexpect(lexer::token_type::value_separator);
8616 
8617  // otherwise: parse key-value pairs
8618  do
8619  {
8620  // ugly, but could be fixed with loop reorganization
8621  if (last_token == lexer::token_type::value_separator)
8622  {
8623  get_token();
8624  }
8625 
8626  // store key
8627  expect(lexer::token_type::value_string);
8628  const auto key = m_lexer.get_string();
8629 
8630  bool keep_tag = false;
8631  if (keep)
8632  {
8633  if (callback)
8634  {
8635  basic_json k(key);
8636  keep_tag = callback(depth, parse_event_t::key, k);
8637  }
8638  else
8639  {
8640  keep_tag = true;
8641  }
8642  }
8643 
8644  // parse separator (:)
8645  get_token();
8646  expect(lexer::token_type::name_separator);
8647 
8648  // parse and add value
8649  get_token();
8650  auto value = parse_internal(keep);
8651  if (keep and keep_tag and not value.is_discarded())
8652  {
8653  result[key] = std::move(value);
8654  }
8655  }
8656  while (last_token == lexer::token_type::value_separator);
8657 
8658  // closing }
8659  expect(lexer::token_type::end_object);
8660  get_token();
8661  if (keep and callback and not callback(--depth, parse_event_t::object_end, result))
8662  {
8663  result = basic_json(value_t::discarded);
8664  }
8665 
8666  return result;
8667  }
8668 
8669  case lexer::token_type::begin_array:
8670  {
8671  if (keep and (not callback or (keep = callback(depth++, parse_event_t::array_start, result))))
8672  {
8673  // explicitly set result to object to cope with []
8674  result.m_type = value_t::array;
8675  result.m_value = json_value(value_t::array);
8676  }
8677 
8678  // read next token
8679  get_token();
8680 
8681  // closing ] -> we are done
8682  if (last_token == lexer::token_type::end_array)
8683  {
8684  get_token();
8685  if (callback and not callback(--depth, parse_event_t::array_end, result))
8686  {
8687  result = basic_json(value_t::discarded);
8688  }
8689  return result;
8690  }
8691 
8692  // no comma is expected here
8693  unexpect(lexer::token_type::value_separator);
8694 
8695  // otherwise: parse values
8696  do
8697  {
8698  // ugly, but could be fixed with loop reorganization
8699  if (last_token == lexer::token_type::value_separator)
8700  {
8701  get_token();
8702  }
8703 
8704  // parse value
8705  auto value = parse_internal(keep);
8706  if (keep and not value.is_discarded())
8707  {
8708  result.push_back(std::move(value));
8709  }
8710  }
8711  while (last_token == lexer::token_type::value_separator);
8712 
8713  // closing ]
8714  expect(lexer::token_type::end_array);
8715  get_token();
8716  if (keep and callback and not callback(--depth, parse_event_t::array_end, result))
8717  {
8718  result = basic_json(value_t::discarded);
8719  }
8720 
8721  return result;
8722  }
8723 
8724  case lexer::token_type::literal_null:
8725  {
8726  get_token();
8727  result.m_type = value_t::null;
8728  break;
8729  }
8730 
8731  case lexer::token_type::value_string:
8732  {
8733  const auto s = m_lexer.get_string();
8734  get_token();
8735  result = basic_json(s);
8736  break;
8737  }
8738 
8739  case lexer::token_type::literal_true:
8740  {
8741  get_token();
8742  result.m_type = value_t::boolean;
8743  result.m_value = true;
8744  break;
8745  }
8746 
8747  case lexer::token_type::literal_false:
8748  {
8749  get_token();
8750  result.m_type = value_t::boolean;
8751  result.m_value = false;
8752  break;
8753  }
8754 
8755  case lexer::token_type::value_number:
8756  {
8757  m_lexer.get_number(result);
8758  get_token();
8759  break;
8760  }
8761 
8762  default:
8763  {
8764  // the last token was unexpected
8765  unexpect(last_token);
8766  }
8767  }
8768 
8769  if (keep and callback and not callback(depth, parse_event_t::value, result))
8770  {
8771  result = basic_json(value_t::discarded);
8772  }
8773  return result;
8774  }
8775 
8777  typename lexer::token_type get_token() noexcept
8778  {
8779  last_token = m_lexer.scan();
8780  return last_token;
8781  }
8782 
8783  void expect(typename lexer::token_type t) const
8784  {
8785  if (t != last_token)
8786  {
8787  std::string error_msg = "parse error - unexpected ";
8788  error_msg += (last_token == lexer::token_type::parse_error ? ("'" + m_lexer.get_token() + "'") :
8789  lexer::token_type_name(last_token));
8790  error_msg += "; expected " + lexer::token_type_name(t);
8791  throw std::invalid_argument(error_msg);
8792  }
8793  }
8794 
8795  void unexpect(typename lexer::token_type t) const
8796  {
8797  if (t == last_token)
8798  {
8799  std::string error_msg = "parse error - unexpected ";
8800  error_msg += (last_token == lexer::token_type::parse_error ? ("'" + m_lexer.get_token() + "'") :
8801  lexer::token_type_name(last_token));
8802  throw std::invalid_argument(error_msg);
8803  }
8804  }
8805 
8806  private:
8808  int depth = 0;
8810  parser_callback_t callback;
8812  typename lexer::token_type last_token = lexer::token_type::uninitialized;
8814  lexer m_lexer;
8815  };
8816 
8817  public:
8830  {
8832  friend class basic_json;
8833 
8834  public:
8857  explicit json_pointer(const std::string& s = "")
8858  : reference_tokens(split(s))
8859  {}
8860 
8876  std::string to_string() const noexcept
8877  {
8878  std::string result;
8879 
8880  for (const auto& reference_token : reference_tokens)
8881  {
8882  result += "/" + escape(reference_token);
8883  }
8884 
8885  return result;
8886  }
8887 
8889  operator std::string() const
8890  {
8891  return to_string();
8892  }
8894  private:
8896  std::string pop_back()
8897  {
8898  if (is_root())
8899  {
8900  throw std::domain_error("JSON pointer has no parent");
8901  }
8902 
8903  auto last = reference_tokens.back();
8904  reference_tokens.pop_back();
8905  return last;
8906  }
8907 
8909  bool is_root() const
8910  {
8911  return reference_tokens.empty();
8912  }
8913 
8914  json_pointer top() const
8915  {
8916  if (is_root())
8917  {
8918  throw std::domain_error("JSON pointer has no parent");
8919  }
8920 
8921  json_pointer result = *this;
8922  result.reference_tokens = {reference_tokens[0]};
8923  return result;
8924  }
8925 
8929  reference get_and_create(reference j) const
8930  {
8931  pointer result = &j;
8932 
8933  // in case no reference tokens exist, return a reference to the
8934  // JSON value j which will be overwritten by a primitive value
8935  for (const auto& reference_token : reference_tokens)
8936  {
8937  switch (result->m_type)
8938  {
8939  case value_t::null:
8940  {
8941  if (reference_token == "0")
8942  {
8943  // start a new array if reference token is 0
8944  result = &result->operator[](0);
8945  }
8946  else
8947  {
8948  // start a new object otherwise
8949  result = &result->operator[](reference_token);
8950  }
8951  break;
8952  }
8953 
8954  case value_t::object:
8955  {
8956  // create an entry in the object
8957  result = &result->operator[](reference_token);
8958  break;
8959  }
8960 
8961  case value_t::array:
8962  {
8963  // create an entry in the array
8964  result = &result->operator[](static_cast<size_type>(std::stoi(reference_token)));
8965  break;
8966  }
8967 
8968  /*
8969  The following code is only reached if there exists a
8970  reference token _and_ the current value is primitive. In
8971  this case, we have an error situation, because primitive
8972  values may only occur as single value; that is, with an
8973  empty list of reference tokens.
8974  */
8975  default:
8976  {
8977  throw std::domain_error("invalid value to unflatten");
8978  }
8979  }
8980  }
8981 
8982  return *result;
8983  }
8984 
8998  reference get_unchecked(pointer ptr) const
8999  {
9000  for (const auto& reference_token : reference_tokens)
9001  {
9002  switch (ptr->m_type)
9003  {
9004  case value_t::object:
9005  {
9006  // use unchecked object access
9007  ptr = &ptr->operator[](reference_token);
9008  break;
9009  }
9010 
9011  case value_t::array:
9012  {
9013  // error condition (cf. RFC 6901, Sect. 4)
9014  if (reference_token.size() > 1 and reference_token[0] == '0')
9015  {
9016  throw std::domain_error("array index must not begin with '0'");
9017  }
9018 
9019  if (reference_token == "-")
9020  {
9021  // explicityly treat "-" as index beyond the end
9022  ptr = &ptr->operator[](ptr->m_value.array->size());
9023  }
9024  else
9025  {
9026  // convert array index to number; unchecked access
9027  ptr = &ptr->operator[](static_cast<size_type>(std::stoi(reference_token)));
9028  }
9029  break;
9030  }
9031 
9032  default:
9033  {
9034  throw std::out_of_range("unresolved reference token '" + reference_token + "'");
9035  }
9036  }
9037  }
9038 
9039  return *ptr;
9040  }
9041 
9042  reference get_checked(pointer ptr) const
9043  {
9044  for (const auto& reference_token : reference_tokens)
9045  {
9046  switch (ptr->m_type)
9047  {
9048  case value_t::object:
9049  {
9050  // note: at performs range check
9051  ptr = &ptr->at(reference_token);
9052  break;
9053  }
9054 
9055  case value_t::array:
9056  {
9057  if (reference_token == "-")
9058  {
9059  // "-" always fails the range check
9060  throw std::out_of_range("array index '-' (" +
9061  std::to_string(ptr->m_value.array->size()) +
9062  ") is out of range");
9063  }
9064 
9065  // error condition (cf. RFC 6901, Sect. 4)
9066  if (reference_token.size() > 1 and reference_token[0] == '0')
9067  {
9068  throw std::domain_error("array index must not begin with '0'");
9069  }
9070 
9071  // note: at performs range check
9072  ptr = &ptr->at(static_cast<size_type>(std::stoi(reference_token)));
9073  break;
9074  }
9075 
9076  default:
9077  {
9078  throw std::out_of_range("unresolved reference token '" + reference_token + "'");
9079  }
9080  }
9081  }
9082 
9083  return *ptr;
9084  }
9085 
9094  const_reference get_unchecked(const_pointer ptr) const
9095  {
9096  for (const auto& reference_token : reference_tokens)
9097  {
9098  switch (ptr->m_type)
9099  {
9100  case value_t::object:
9101  {
9102  // use unchecked object access
9103  ptr = &ptr->operator[](reference_token);
9104  break;
9105  }
9106 
9107  case value_t::array:
9108  {
9109  if (reference_token == "-")
9110  {
9111  // "-" cannot be used for const access
9112  throw std::out_of_range("array index '-' (" +
9113  std::to_string(ptr->m_value.array->size()) +
9114  ") is out of range");
9115  }
9116 
9117  // error condition (cf. RFC 6901, Sect. 4)
9118  if (reference_token.size() > 1 and reference_token[0] == '0')
9119  {
9120  throw std::domain_error("array index must not begin with '0'");
9121  }
9122 
9123  // use unchecked array access
9124  ptr = &ptr->operator[](static_cast<size_type>(std::stoi(reference_token)));
9125  break;
9126  }
9127 
9128  default:
9129  {
9130  throw std::out_of_range("unresolved reference token '" + reference_token + "'");
9131  }
9132  }
9133  }
9134 
9135  return *ptr;
9136  }
9137 
9138  const_reference get_checked(const_pointer ptr) const
9139  {
9140  for (const auto& reference_token : reference_tokens)
9141  {
9142  switch (ptr->m_type)
9143  {
9144  case value_t::object:
9145  {
9146  // note: at performs range check
9147  ptr = &ptr->at(reference_token);
9148  break;
9149  }
9150 
9151  case value_t::array:
9152  {
9153  if (reference_token == "-")
9154  {
9155  // "-" always fails the range check
9156  throw std::out_of_range("array index '-' (" +
9157  std::to_string(ptr->m_value.array->size()) +
9158  ") is out of range");
9159  }
9160 
9161  // error condition (cf. RFC 6901, Sect. 4)
9162  if (reference_token.size() > 1 and reference_token[0] == '0')
9163  {
9164  throw std::domain_error("array index must not begin with '0'");
9165  }
9166 
9167  // note: at performs range check
9168  ptr = &ptr->at(static_cast<size_type>(std::stoi(reference_token)));
9169  break;
9170  }
9171 
9172  default:
9173  {
9174  throw std::out_of_range("unresolved reference token '" + reference_token + "'");
9175  }
9176  }
9177  }
9178 
9179  return *ptr;
9180  }
9181 
9183  static std::vector<std::string> split(std::string reference_string)
9184  {
9185  std::vector<std::string> result;
9186 
9187  // special case: empty reference string -> no reference tokens
9188  if (reference_string.empty())
9189  {
9190  return result;
9191  }
9192 
9193  // check if nonempty reference string begins with slash
9194  if (reference_string[0] != '/')
9195  {
9196  throw std::domain_error("JSON pointer must be empty or begin with '/'");
9197  }
9198 
9199  // extract the reference tokens:
9200  // - slash: position of the last read slash (or end of string)
9201  // - start: position after the previous slash
9202  for (
9203  // search for the first slash after the first character
9204  size_t slash = reference_string.find_first_of("/", 1),
9205  // set the beginning of the first reference token
9206  start = 1;
9207  // we can stop if start == string::npos+1 = 0
9208  start != 0;
9209  // set the beginning of the next reference token
9210  // (will eventually be 0 if slash == std::string::npos)
9211  start = slash + 1,
9212  // find next slash
9213  slash = reference_string.find_first_of("/", start))
9214  {
9215  // use the text between the beginning of the reference token
9216  // (start) and the last slash (slash).
9217  auto reference_token = reference_string.substr(start, slash - start);
9218 
9219  // check reference tokens are properly escaped
9220  for (size_t pos = reference_token.find_first_of("~");
9221  pos != std::string::npos;
9222  pos = reference_token.find_first_of("~", pos + 1))
9223  {
9224  assert(reference_token[pos] == '~');
9225 
9226  // ~ must be followed by 0 or 1
9227  if (pos == reference_token.size() - 1 or
9228  (reference_token[pos + 1] != '0' and
9229  reference_token[pos + 1] != '1'))
9230  {
9231  throw std::domain_error("escape error: '~' must be followed with '0' or '1'");
9232  }
9233  }
9234 
9235  // finally, store the reference token
9236  unescape(reference_token);
9237  result.push_back(reference_token);
9238  }
9239 
9240  return result;
9241  }
9242 
9243  private:
9258  static void replace_substring(std::string& s,
9259  const std::string& f,
9260  const std::string& t)
9261  {
9262  assert(not f.empty());
9263 
9264  for (
9265  size_t pos = s.find(f); // find first occurrence of f
9266  pos != std::string::npos; // make sure f was found
9267  s.replace(pos, f.size(), t), // replace with t
9268  pos = s.find(f, pos + t.size()) // find next occurrence of f
9269  );
9270  }
9271 
9273  static std::string escape(std::string s)
9274  {
9275  // escape "~"" to "~0" and "/" to "~1"
9276  replace_substring(s, "~", "~0");
9277  replace_substring(s, "/", "~1");
9278  return s;
9279  }
9280 
9282  static void unescape(std::string& s)
9283  {
9284  // first transform any occurrence of the sequence '~1' to '/'
9285  replace_substring(s, "~1", "/");
9286  // then transform any occurrence of the sequence '~0' to '~'
9287  replace_substring(s, "~0", "~");
9288  }
9289 
9297  static void flatten(const std::string& reference_string,
9298  const basic_json& value,
9299  basic_json& result)
9300  {
9301  switch (value.m_type)
9302  {
9303  case value_t::array:
9304  {
9305  if (value.m_value.array->empty())
9306  {
9307  // flatten empty array as null
9308  result[reference_string] = nullptr;
9309  }
9310  else
9311  {
9312  // iterate array and use index as reference string
9313  for (size_t i = 0; i < value.m_value.array->size(); ++i)
9314  {
9315  flatten(reference_string + "/" + std::to_string(i),
9316  value.m_value.array->operator[](i), result);
9317  }
9318  }
9319  break;
9320  }
9321 
9322  case value_t::object:
9323  {
9324  if (value.m_value.object->empty())
9325  {
9326  // flatten empty object as null
9327  result[reference_string] = nullptr;
9328  }
9329  else
9330  {
9331  // iterate object and use keys as reference string
9332  for (const auto& element : *value.m_value.object)
9333  {
9334  flatten(reference_string + "/" + escape(element.first),
9335  element.second, result);
9336  }
9337  }
9338  break;
9339  }
9340 
9341  default:
9342  {
9343  // add primitive value with its reference string
9344  result[reference_string] = value;
9345  break;
9346  }
9347  }
9348  }
9349 
9355  static basic_json unflatten(const basic_json& value)
9356  {
9357  if (not value.is_object())
9358  {
9359  throw std::domain_error("only objects can be unflattened");
9360  }
9361 
9362  basic_json result;
9363 
9364  // iterate the JSON object values
9365  for (const auto& element : *value.m_value.object)
9366  {
9367  if (not element.second.is_primitive())
9368  {
9369  throw std::domain_error("values in object must be primitive");
9370  }
9371 
9372  // assign value to reference pointed to by JSON pointer;
9373  // Note that if the JSON pointer is "" (i.e., points to the
9374  // whole value), function get_and_create returns a reference
9375  // to result itself. An assignment will then create a
9376  // primitive value.
9377  json_pointer(element.first).get_and_create(result) = element.second;
9378  }
9379 
9380  return result;
9381  }
9382 
9383  private:
9385  std::vector<std::string> reference_tokens {};
9386  };
9387 
9389  // JSON Pointer support //
9391 
9394 
9428  reference operator[](const json_pointer& ptr)
9429  {
9430  return ptr.get_unchecked(this);
9431  }
9455  const_reference operator[](const json_pointer& ptr) const
9456  {
9457  return ptr.get_unchecked(this);
9458  }
9480  reference at(const json_pointer& ptr)
9481  {
9482  return ptr.get_checked(this);
9483  }
9505  const_reference at(const json_pointer& ptr) const
9506  {
9507  return ptr.get_checked(this);
9508  }
9532  basic_json flatten() const
9533  {
9534  basic_json result(value_t::object);
9535  json_pointer::flatten("", *this, result);
9536  return result;
9537  }
9538 
9566  basic_json unflatten() const
9567  {
9568  return json_pointer::unflatten(*this);
9569  }
9572 
9574  // JSON Patch functions //
9576 
9579 
9616  basic_json patch(const basic_json& patch) const
9617  {
9618  // make a working copy to apply the patch to
9619  basic_json result = *this;
9621  // the valid JSON Patch operations
9622  enum class patch_operations {add, remove, replace, move, copy, test, invalid};
9623 
9624  const auto get_op = [](const std::string op)
9625  {
9626  if (op == "add")
9627  {
9628  return patch_operations::add;
9629  }
9630  if (op == "remove")
9631  {
9632  return patch_operations::remove;
9633  }
9634  if (op == "replace")
9635  {
9636  return patch_operations::replace;
9637  }
9638  if (op == "move")
9639  {
9640  return patch_operations::move;
9641  }
9642  if (op == "copy")
9643  {
9644  return patch_operations::copy;
9645  }
9646  if (op == "test")
9647  {
9648  return patch_operations::test;
9649  }
9650 
9651  return patch_operations::invalid;
9652  };
9653 
9654  // wrapper for "add" operation; add value at ptr
9655  const auto operation_add = [&result](json_pointer & ptr, basic_json val)
9656  {
9657  // adding to the root of the target document means replacing it
9658  if (ptr.is_root())
9659  {
9660  result = val;
9661  }
9662  else
9663  {
9664  // make sure the top element of the pointer exists
9665  json_pointer top_pointer = ptr.top();
9666  if (top_pointer != ptr)
9667  {
9668  basic_json& x = result.at(top_pointer);
9669  }
9670 
9671  // get reference to parent of JSON pointer ptr
9672  const auto last_path = ptr.pop_back();
9673  basic_json& parent = result[ptr];
9674 
9675  switch (parent.m_type)
9676  {
9677  case value_t::null:
9678  case value_t::object:
9679  {
9680  // use operator[] to add value
9681  parent[last_path] = val;
9682  break;
9683  }
9684 
9685  case value_t::array:
9686  {
9687  if (last_path == "-")
9688  {
9689  // special case: append to back
9690  parent.push_back(val);
9691  }
9692  else
9693  {
9694  const auto idx = std::stoi(last_path);
9695  if (static_cast<size_type>(idx) > parent.size())
9696  {
9697  // avoid undefined behavior
9698  throw std::out_of_range("array index " + std::to_string(idx) + " is out of range");
9699  }
9700  else
9701  {
9702  // default case: insert add offset
9703  parent.insert(parent.begin() + static_cast<difference_type>(idx), val);
9704  }
9705  }
9706  break;
9707  }
9708 
9709  default:
9710  {
9711  // if there exists a parent it cannot be primitive
9712  assert(false); // LCOV_EXCL_LINE
9713  }
9714  }
9715  }
9716  };
9717 
9718  // wrapper for "remove" operation; remove value at ptr
9719  const auto operation_remove = [&result](json_pointer & ptr)
9720  {
9721  // get reference to parent of JSON pointer ptr
9722  const auto last_path = ptr.pop_back();
9723  basic_json& parent = result.at(ptr);
9724 
9725  // remove child
9726  if (parent.is_object())
9727  {
9728  // perform range check
9729  auto it = parent.find(last_path);
9730  if (it != parent.end())
9731  {
9732  parent.erase(it);
9733  }
9734  else
9735  {
9736  throw std::out_of_range("key '" + last_path + "' not found");
9737  }
9738  }
9739  else if (parent.is_array())
9740  {
9741  // note erase performs range check
9742  parent.erase(static_cast<size_type>(std::stoi(last_path)));
9743  }
9744  };
9745 
9746  // type check
9747  if (not patch.is_array())
9748  {
9749  // a JSON patch must be an array of objects
9750  throw std::invalid_argument("JSON patch must be an array of objects");
9751  }
9752 
9753  // iterate and apply th eoperations
9754  for (const auto& val : patch)
9755  {
9756  // wrapper to get a value for an operation
9757  const auto get_value = [&val](const std::string & op,
9758  const std::string & member,
9759  bool string_type) -> basic_json&
9760  {
9761  // find value
9762  auto it = val.m_value.object->find(member);
9763 
9764  // context-sensitive error message
9765  const auto error_msg = (op == "op") ? "operation" : "operation '" + op + "'";
9766 
9767  // check if desired value is present
9768  if (it == val.m_value.object->end())
9769  {
9770  throw std::invalid_argument(error_msg + " must have member '" + member + "'");
9771  }
9772 
9773  // check if result is of type string
9774  if (string_type and not it->second.is_string())
9775  {
9776  throw std::invalid_argument(error_msg + " must have string member '" + member + "'");
9777  }
9778 
9779  // no error: return value
9780  return it->second;
9781  };
9782 
9783  // type check
9784  if (not val.is_object())
9785  {
9786  throw std::invalid_argument("JSON patch must be an array of objects");
9787  }
9788 
9789  // collect mandatory members
9790  const std::string op = get_value("op", "op", true);
9791  const std::string path = get_value(op, "path", true);
9792  json_pointer ptr(path);
9793 
9794  switch (get_op(op))
9795  {
9796  case patch_operations::add:
9797  {
9798  operation_add(ptr, get_value("add", "value", false));
9799  break;
9800  }
9801 
9802  case patch_operations::remove:
9803  {
9804  operation_remove(ptr);
9805  break;
9806  }
9807 
9808  case patch_operations::replace:
9809  {
9810  // the "path" location must exist - use at()
9811  result.at(ptr) = get_value("replace", "value", false);
9812  break;
9813  }
9814 
9815  case patch_operations::move:
9816  {
9817  const std::string from_path = get_value("move", "from", true);
9818  json_pointer from_ptr(from_path);
9819 
9820  // the "from" location must exist - use at()
9821  basic_json v = result.at(from_ptr);
9822 
9823  // The move operation is functionally identical to a
9824  // "remove" operation on the "from" location, followed
9825  // immediately by an "add" operation at the target
9826  // location with the value that was just removed.
9827  operation_remove(from_ptr);
9828  operation_add(ptr, v);
9829  break;
9830  }
9831 
9832  case patch_operations::copy:
9833  {
9834  const std::string from_path = get_value("copy", "from", true);;
9835  const json_pointer from_ptr(from_path);
9836 
9837  // the "from" location must exist - use at()
9838  result[ptr] = result.at(from_ptr);
9839  break;
9840  }
9841 
9842  case patch_operations::test:
9843  {
9844  bool success = false;
9845  try
9846  {
9847  // check if "value" matches the one at "path"
9848  // the "path" location must exist - use at()
9849  success = (result.at(ptr) == get_value("test", "value", false));
9850  }
9851  catch (std::out_of_range&)
9852  {
9853  // ignore out of range errors: success remains false
9854  }
9855 
9856  // throw an exception if test fails
9857  if (not success)
9858  {
9859  throw std::domain_error("unsuccessful: " + val.dump());
9860  }
9861 
9862  break;
9863  }
9864 
9865  case patch_operations::invalid:
9866  {
9867  // op must be "add", "remove", "replace", "move", "copy", or
9868  // "test"
9869  throw std::invalid_argument("operation value '" + op + "' is invalid");
9870  }
9871  }
9872  }
9873 
9874  return result;
9875  }
9876 
9909  static basic_json diff(const basic_json& source,
9910  const basic_json& target,
9911  std::string path = "") noexcept
9912  {
9913  // the patch
9914  basic_json result(value_t::array);
9915 
9916  // if the values are the same, return empty patch
9917  if (source == target)
9918  {
9919  return result;
9920  }
9921 
9922  if (source.type() != target.type())
9923  {
9924  // different types: replace value
9925  result.push_back(
9926  {
9927  {"op", "replace"},
9928  {"path", path},
9929  {"value", target}
9930  });
9931  }
9932  else
9933  {
9934  switch (source.type())
9935  {
9936  case value_t::array:
9937  {
9938  // first pass: traverse common elements
9939  size_t i = 0;
9940  while (i < source.size() and i < target.size())
9941  {
9942  // recursive call to compare array values at index i
9943  auto temp_diff = diff(source[i], target[i], path + "/" + std::to_string(i));
9944  result.insert(result.end(), temp_diff.begin(), temp_diff.end());
9945  ++i;
9946  }
9947 
9948  // i now reached the end of at least one array
9949  // in a second pass, traverse the remaining elements
9950 
9951  // remove my remaining elements
9952  while (i < source.size())
9953  {
9954  result.push_back(object(
9955  {
9956  {"op", "remove"},
9957  {"path", path + "/" + std::to_string(i)}
9958  }));
9959  ++i;
9960  }
9961 
9962  // add other remaining elements
9963  while (i < target.size())
9964  {
9965  result.push_back(
9966  {
9967  {"op", "add"},
9968  {"path", path + "/" + std::to_string(i)},
9969  {"value", target[i]}
9970  });
9971  ++i;
9972  }
9973 
9974  break;
9975  }
9976 
9977  case value_t::object:
9978  {
9979  // first pass: traverse this object's elements
9980  for (auto it = source.begin(); it != source.end(); ++it)
9981  {
9982  // escape the key name to be used in a JSON patch
9983  const auto key = json_pointer::escape(it.key());
9984 
9985  if (target.find(it.key()) != target.end())
9986  {
9987  // recursive call to compare object values at key it
9988  auto temp_diff = diff(it.value(), target[it.key()], path + "/" + key);
9989  result.insert(result.end(), temp_diff.begin(), temp_diff.end());
9990  }
9991  else
9992  {
9993  // found a key that is not in o -> remove it
9994  result.push_back(object(
9995  {
9996  {"op", "remove"},
9997  {"path", path + "/" + key}
9998  }));
9999  }
10000  }
10001 
10002  // second pass: traverse other object's elements
10003  for (auto it = target.begin(); it != target.end(); ++it)
10004  {
10005  if (source.find(it.key()) == source.end())
10006  {
10007  // found a key that is not in this -> add it
10008  const auto key = json_pointer::escape(it.key());
10009  result.push_back(
10010  {
10011  {"op", "add"},
10012  {"path", path + "/" + key},
10013  {"value", it.value()}
10014  });
10015  }
10016  }
10017 
10018  break;
10019  }
10020 
10021  default:
10022  {
10023  // both primitive type: replace value
10024  result.push_back(
10025  {
10026  {"op", "replace"},
10027  {"path", path},
10028  {"value", target}
10029  });
10030  break;
10031  }
10032  }
10033  }
10034 
10035  return result;
10036  }
10037 
10039 };
10040 
10041 
10043 // presets //
10045 
10054 using json = basic_json<>;
10055 }
10056 
10057 
10059 // nonmember support //
10061 
10062 // specialization of std::swap, and std::hash
10063 namespace std
10064 {
10070 template <>
10071 inline void swap(nlohmann::json& j1,
10072  nlohmann::json& j2) noexcept(
10073  is_nothrow_move_constructible<nlohmann::json>::value and
10074  is_nothrow_move_assignable<nlohmann::json>::value
10075  )
10076 {
10077  j1.swap(j2);
10078 }
10079 
10081 template <>
10082 struct hash<nlohmann::json>
10083 {
10089  std::size_t operator()(const nlohmann::json& j) const
10090  {
10091  // a naive hashing via the string representation
10092  const auto& h = hash<nlohmann::json::string_t>();
10093  return h(j.dump());
10094  }
10095 };
10096 }
10097 
10110 inline nlohmann::json operator "" _json(const char* s, std::size_t)
10111 {
10112  return nlohmann::json::parse(reinterpret_cast<const nlohmann::json::string_t::value_type*>(s));
10113 }
10114 
10120 inline nlohmann::json::json_pointer operator "" _json_pointer(const char* s, std::size_t)
10121 {
10122  return nlohmann::json::json_pointer(s);
10123 }
10124 
10125 // restore GCC/clang diagnostic settings
10126 #if defined(__clang__) || defined(__GNUC__) || defined(__GNUG__)
10127  #pragma GCC diagnostic pop
10128 #endif
10129 
10130 #endif
const_iterator(pointer object) noexcept
constructor for a given JSON instance
Definition: json.hpp:6447
friend bool operator<=(const_reference lhs, const_reference rhs) noexcept
comparison: less than or equal
Definition: json.hpp:5582
basic_json(const value_t value_type)
create an empty value with a given type
Definition: json.hpp:1032
basic_json(const array_t &val)
create an array (explicit)
Definition: json.hpp:1169
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:4142
const_reference operator[](size_type idx) const
access specified array element
Definition: json.hpp:3334
reference value() const
return the value of an iterator
Definition: json.hpp:7087
json_reverse_iterator & operator--()
pre-decrement (–it)
Definition: json.hpp:7149
void clear() noexcept
clears the contents
Definition: json.hpp:4692
bool operator==(const const_iterator &other) const
comparison: equal
Definition: json.hpp:6737
json_reverse_iterator operator--(int)
post-decrement (it–)
Definition: json.hpp:7143
reference operator[](T *(&key)[n])
access specified object element
Definition: json.hpp:3466
friend std::istream & operator>>(std::istream &i, basic_json &j)
deserialize from stream
Definition: json.hpp:5795
constexpr bool is_number_float() const noexcept
return whether value is a floating-point number
Definition: json.hpp:2411
const_reverse_iterator rend() const noexcept
returns a const reverse iterator to one before the first
Definition: json.hpp:4369
iterator & operator+=(difference_type i)
add to iterator
Definition: json.hpp:7045
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:1749
const_iterator operator-(difference_type i)
subtract from iterator
Definition: json.hpp:6863
BooleanType boolean_t
a type for a boolean
Definition: json.hpp:466
const_iterator cbegin() const noexcept
returns a const iterator to the first element
Definition: json.hpp:4223
reference operator+=(const typename object_t::value_type &val)
add an object to an object
Definition: json.hpp:4878
reference operator*() const
return a reference to the value pointed to by the iterator
Definition: json.hpp:7003
basic_json(const typename string_t::value_type *val)
create a string (explicit)
Definition: json.hpp:1262
reference operator[](difference_type n) const
access to successor
Definition: json.hpp:7185
iterator find(typename object_t::key_type key)
find an element in a JSON object
Definition: json.hpp:4094
friend bool operator!=(const_reference lhs, const_reference rhs) noexcept
comparison: not equal
Definition: json.hpp:5420
basic_json(const string_t &val)
create a string (explicit)
Definition: json.hpp:1238
void push_back(const basic_json &val)
add an object to an array
Definition: json.hpp:4804
void erase(const size_type idx)
remove element from a JSON array given an index
Definition: json.hpp:4048
ArrayType< basic_json, AllocatorType< basic_json >> array_t
a type for an array
Definition: json.hpp:393
reference front()
access the first element
Definition: json.hpp:3705
void swap(object_t &other)
exchanges the values
Definition: json.hpp:5176
json_reverse_iterator operator-(difference_type i) const
subtract from iterator
Definition: json.hpp:7171
const_iterator & operator+=(difference_type i)
add to iterator
Definition: json.hpp:6821
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:1373
reference value() const
return the value of an iterator
Definition: json.hpp:7198
friend bool operator==(std::nullptr_t, const_reference v) noexcept
comparison: equal
Definition: json.hpp:5399
NumberIntegerType number_integer_t
a type for a number (integer)
Definition: json.hpp:537
iterator insert(const_iterator pos, size_type cnt, const basic_json &val)
inserts elements
Definition: json.hpp:4962
const_reference at(const typename object_t::key_type &key) const
access specified object element with bounds checking
Definition: json.hpp:3241
const_iterator operator+(difference_type i)
add to iterator
Definition: json.hpp:6855
constexpr bool is_object() const noexcept
return whether value is an object
Definition: json.hpp:2433
constexpr bool is_number_integer() const noexcept
return whether value is an integer number
Definition: json.hpp:2355
a mutable random access iterator for the basic_json class
Definition: json.hpp:6970
static basic_json parse(std::istream &&i, parser_callback_t cb=nullptr)
deserialize from stream
Definition: json.hpp:5757
const_iterator operator++(int)
post-increment (it++)
Definition: json.hpp:6663
const_iterator cend() const noexcept
returns a const iterator to one past the last element
Definition: json.hpp:4294
ObjectType< StringType, basic_json, std::less< StringType >, AllocatorType< std::pair< const StringType, basic_json >>> object_t
a type for an object
Definition: json.hpp:347
STL namespace.
NumberUnsignedType number_unsigned_t
a type for a number (unsigned)
Definition: json.hpp:609
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:1344
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:1709
static iteration_proxy< const_iterator > iterator_wrapper(const_reference cont)
wrapper to access iterator member functions in range-based for
Definition: json.hpp:4456
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:2064
constexpr value_t type() const noexcept
return the type of the JSON value (explicit)
Definition: json.hpp:2195
typename basic_json::value_type value_type
the type of the values when the iterator is dereferenced
Definition: json.hpp:6433
json_reverse_iterator(const typename base_iterator::iterator_type &it) noexcept
create reverse iterator from iterator
Definition: json.hpp:7120
PointerType get_ptr() noexcept
get a pointer value (implicit)
Definition: json.hpp:2955
constexpr bool is_string() const noexcept
return whether value is a string
Definition: json.hpp:2477
reference back()
access the last element
Definition: json.hpp:3747
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:6437
void push_back(const typename object_t::value_type &val)
add an object to an object
Definition: json.hpp:4854
json_pointer(const std::string &s="")
create JSON pointer
Definition: json.hpp:8857
static basic_json parse(const string_t &s, parser_callback_t cb=nullptr)
deserialize from string
Definition: json.hpp:5720
const_reference operator[](T *(&key)[n]) const
read-only access specified object element
Definition: json.hpp:3501
iterator insert(const_iterator pos, const_iterator first, const_iterator last)
inserts elements
Definition: json.hpp:5015
basic_json(std::nullptr_t) noexcept
create a null object (explicitly)
Definition: json.hpp:1084
basic_json(InputIT first, InputIT last)
construct a JSON container given an iterator range
Definition: json.hpp:1819
reference operator[](difference_type n) const
access to successor
Definition: json.hpp:7081
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:3423
const_reference operator[](T *key) const
read-only access specified object element
Definition: json.hpp:3583
json_reverse_iterator operator+(difference_type i) const
add to iterator
Definition: json.hpp:7163
bool empty() const noexcept
checks whether the container is empty
Definition: json.hpp:4504
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:7191
const_iterator(const iterator &other) noexcept
copy constructor given a nonconst iterator
Definition: json.hpp:6475
basic_json(const CompatibleArrayType &val)
create an array (implicit)
Definition: json.hpp:1209
constexpr bool is_boolean() const noexcept
return whether value is a boolean
Definition: json.hpp:2296
const_reference at(size_type idx) const
access specified array element with bounds checking
Definition: json.hpp:3145
basic_json(size_type cnt, const basic_json &val)
construct an array with count copies of given value
Definition: json.hpp:1773
std::reverse_iterator< Base > base_iterator
shortcut to the reverse iterator adaptor
Definition: json.hpp:7115
const_reverse_iterator crbegin() const noexcept
returns a const reverse iterator to the last element
Definition: json.hpp:4398
iterator insert(const_iterator pos, std::initializer_list< basic_json > ilist)
inserts elements
Definition: json.hpp:5073
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:4906
friend bool operator>=(const_reference lhs, const_reference rhs) noexcept
comparison: greater than or equal
Definition: json.hpp:5626
friend bool operator<(const_reference lhs, const_reference rhs) noexcept
comparison: less than
Definition: json.hpp:5481
iterator & operator++()
pre-increment (++it)
Definition: json.hpp:7023
bool operator<(const const_iterator &other) const
comparison: smaller
Definition: json.hpp:6773
iterator operator++(int)
post-increment (it++)
Definition: json.hpp:7015
basic_json(basic_json &&other) noexcept
move constructor
Definition: json.hpp:2032
const_iterator operator--(int)
post-decrement (it–)
Definition: json.hpp:6700
reference at(const typename object_t::key_type &key)
access specified object element with bounds checking
Definition: json.hpp:3193
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:6991
object (unordered set of name/value pairs)
size_type max_size() const noexcept
returns the maximum possible number of elements
Definition: json.hpp:4633
~basic_json()
destructor
Definition: json.hpp:2092
iterator operator--(int)
post-decrement (it–)
Definition: json.hpp:7030
iterator operator-(difference_type i)
subtract from iterator
Definition: json.hpp:7067
const_iterator & operator--()
pre-decrement (–it)
Definition: json.hpp:6708
string_t dump(const int indent=-1) const
serialization
Definition: json.hpp:2161
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:983
AllocatorType< basic_json > allocator_type
the allocator type
Definition: json.hpp:226
StringType string_t
a type for a string
Definition: json.hpp:440
reference operator+=(const basic_json &val)
add an object to an array
Definition: json.hpp:4828
difference_type operator-(const const_iterator &other) const
return difference
Definition: json.hpp:6871
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:4332
friend std::ostream & operator>>(const basic_json &j, std::ostream &o)
serialize to stream
Definition: json.hpp:5681
constexpr bool is_discarded() const noexcept
return whether value is discarded
Definition: json.hpp:2504
const_iterator begin() const noexcept
returns a const iterator to the first element
Definition: json.hpp:4193
difference_type operator-(const iterator &other) const
return difference
Definition: json.hpp:7075
constexpr bool is_array() const noexcept
return whether value is an array
Definition: json.hpp:2455
iterator(const iterator &other) noexcept
copy constructor
Definition: json.hpp:6986
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:6435
void swap(string_t &other)
exchanges the values
Definition: json.hpp:5210
basic_json(const CompatibleNumberIntegerType val) noexcept
create an integer number (implicit)
Definition: json.hpp:1410
const_reference front() const
access the first element
Definition: json.hpp:3713
bool operator>(const const_iterator &other) const
comparison: greater than
Definition: json.hpp:6809
constexpr const PointerType get_ptr() const noexcept
get a pointer value (implicit)
Definition: json.hpp:2970
pointer operator->() const
dereference the iterator
Definition: json.hpp:6628
NumberFloatType number_float_t
a type for a number (floating-point)
Definition: json.hpp:677
const_reverse_iterator crend() const noexcept
returns a const reverse iterator to one before the first
Definition: json.hpp:4427
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:5111
value_t
the JSON type enumeration
Definition: json.hpp:696
reverse_iterator rbegin() noexcept
returns an iterator to the reverse-beginning
Definition: json.hpp:4324
constexpr bool is_null() const noexcept
return whether value is null
Definition: json.hpp:2274
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:2871
void swap(array_t &other)
exchanges the values
Definition: json.hpp:5142
InteratorType erase(InteratorType first, InteratorType last)
remove elements given an iterator range
Definition: json.hpp:3923
ValueType value(const typename object_t::key_type &key, ValueType default_value) const
access specified object element with default value
Definition: json.hpp:3650
typename Base::reference reference
the reference type for the pointed-to element
Definition: json.hpp:7117
const_reference back() const
access the last element
Definition: json.hpp:3757
void push_back(basic_json &&val)
add an object to an array
Definition: json.hpp:4768
array (ordered collection of values)
constexpr bool is_number_unsigned() const noexcept
return whether value is an unsigned integer number
Definition: json.hpp:2383
json_reverse_iterator & operator++()
pre-increment (++it)
Definition: json.hpp:7136
static basic_json parse(std::istream &i, parser_callback_t cb=nullptr)
deserialize from stream
Definition: json.hpp:5749
friend bool operator==(const_reference lhs, const_reference rhs) noexcept
comparison: equal
Definition: json.hpp:5291
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:3676
ReferenceType get_ref() const
get a reference value (implicit)
Definition: json.hpp:3021
basic_json(const CompatibleNumberUnsignedType val) noexcept
create an unsigned number (implicit)
Definition: json.hpp:1469
reference operator*() const
return a reference to the value pointed to by the iterator
Definition: json.hpp:6588
friend bool operator<(const value_t lhs, const value_t rhs) noexcept
comparison operator for JSON types
Definition: json.hpp:5244
basic_json(const number_float_t val) noexcept
create a floating-point number (explicit)
Definition: json.hpp:1498
friend bool operator!=(const_reference v, std::nullptr_t) noexcept
comparison: not equal
Definition: json.hpp:5443
iterator operator+(difference_type i)
add to iterator
Definition: json.hpp:7059
basic_json(const CompatibleNumberFloatType val) noexcept
create an floating-point number (implicit)
Definition: json.hpp:1544
bool operator<=(const const_iterator &other) const
comparison: less than or equal
Definition: json.hpp:6803
InteratorType erase(InteratorType pos)
remove element given an iterator
Definition: json.hpp:3815
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:1617
iterator(pointer object) noexcept
constructor for a given JSON instance
Definition: json.hpp:6981
friend bool operator!=(std::nullptr_t, const_reference v) noexcept
comparison: not equal
Definition: json.hpp:5452
constexpr bool is_primitive() const noexcept
return whether type is primitive
Definition: json.hpp:2225
const_iterator & operator++()
pre-increment (++it)
Definition: json.hpp:6671
pointer operator->() const
dereference the iterator
Definition: json.hpp:7009
reference value() const
return the value of an iterator
Definition: json.hpp:6946
constexpr bool is_structured() const noexcept
return whether type is structured
Definition: json.hpp:2252
std::bidirectional_iterator_tag iterator_category
the category of the iterator
Definition: json.hpp:6441
basic_json(boolean_t val) noexcept
create a boolean (explicit)
Definition: json.hpp:1311
iterator end() noexcept
returns an iterator to one past the last element
Definition: json.hpp:4254
reverse_iterator rend() noexcept
returns an iterator to the reverse-end
Definition: json.hpp:4361
difference_type operator-(const json_reverse_iterator &other) const
return difference
Definition: json.hpp:7179
const_iterator find(typename object_t::key_type key) const
find an element in a JSON object
Definition: json.hpp:4111
iterator begin() noexcept
returns an iterator to the first element
Definition: json.hpp:4183
basic_json(const CompatibleObjectType &val)
create an object (implicit)
Definition: json.hpp:1142
const_iterator end() const noexcept
returns a const iterator to one past the last element
Definition: json.hpp:4264
friend bool operator>(const_reference lhs, const_reference rhs) noexcept
comparison: greater than
Definition: json.hpp:5604
bool operator>=(const const_iterator &other) const
comparison: greater than or equal
Definition: json.hpp:6815
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:6508
size_type erase(const typename object_t::key_type &key)
remove element from a JSON object given a key
Definition: json.hpp:4010
reference operator[](const typename object_t::key_type &key)
access specified object element
Definition: json.hpp:3375
object_t::key_type key() const
return the key of an object iterator
Definition: json.hpp:6931
reference operator+=(basic_json &&val)
add an object to an array
Definition: json.hpp:4794
reference operator[](difference_type n) const
access to successor
Definition: json.hpp:6895
a const random access iterator for the basic_json class
Definition: json.hpp:6426
constexpr bool is_number() const noexcept
return whether value is a number
Definition: json.hpp:2326
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:1926
typename basic_json::const_reference reference
defines a reference to the type iterated over (value_type)
Definition: json.hpp:6439
json_reverse_iterator operator++(int)
post-increment (it++)
Definition: json.hpp:7130
friend bool operator==(const_reference v, std::nullptr_t) noexcept
comparison: equal
Definition: json.hpp:5390
reference operator[](size_type idx)
access specified array element
Definition: json.hpp:3288
bool operator!=(const const_iterator &other) const
comparison: not equal
Definition: json.hpp:6767
json_reverse_iterator & operator+=(difference_type i)
add to iterator
Definition: json.hpp:7156
reference at(size_type idx)
access specified array element with bounds checking
Definition: json.hpp:3101
size_type size() const noexcept
returns the number of elements
Definition: json.hpp:4567
static iteration_proxy< iterator > iterator_wrapper(reference cont)
wrapper to access iterator member functions in range-based for
Definition: json.hpp:4448
iterator & operator-=(difference_type i)
subtract from iterator
Definition: json.hpp:7052
basic_json(const object_t &val)
create an object (explicit)
Definition: json.hpp:1107
basic_json(const number_unsigned_t val) noexcept
create an unsigned integer number (explicit)
Definition: json.hpp:1438
friend std::istream & operator<<(basic_json &j, std::istream &i)
deserialize from stream
Definition: json.hpp:5785
json_reverse_iterator(const base_iterator &it) noexcept
create reverse iterator from base class
Definition: json.hpp:7125
friend std::ostream & operator<<(std::ostream &o, const basic_json &j)
serialize to stream
Definition: json.hpp:5663
const_iterator(const const_iterator &other) noexcept
copy constructor
Definition: json.hpp:6503
iterator & operator--()
pre-decrement (–it)
Definition: json.hpp:7038
iterator insert(const_iterator pos, basic_json &&val)
inserts element
Definition: json.hpp:4933
ReferenceType get_ref()
get a reference value (implicit)
Definition: json.hpp:3006
const_iterator & operator-=(difference_type i)
subtract from iterator
Definition: json.hpp:6849
basic_json(const CompatibleStringType &val)
create a string (implicit)
Definition: json.hpp:1293
basic_json(const basic_json &other)
copy constructor
Definition: json.hpp:1957
reference operator[](T *key)
access specified object element
Definition: json.hpp:3534
parse_event_t
JSON callback events.
Definition: json.hpp:918