JSON for Modern C++  2.0.0
json.hpp
1 /*
2  __ _____ _____ _____
3  __| | __| | | | JSON for Modern C++
4 | | |__ | | | | | | version 2.0.0
5 |_____|_____|_____|_|___| https://github.com/nlohmann/json
6 
7 Licensed under the MIT License <http://opensource.org/licenses/MIT>.
8 Copyright (c) 2013-2016 Niels Lohmann <http://nlohmann.me>.
9 
10 Permission is hereby granted, free of charge, to any person obtaining a copy
11 of this software and associated documentation files (the "Software"), to deal
12 in the Software without restriction, including without limitation the rights
13 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
14 copies of the Software, and to permit persons to whom the Software is
15 furnished to do so, subject to the following conditions:
16 
17 The above copyright notice and this permission notice shall be included in all
18 copies or substantial portions of the Software.
19 
20 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
23 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
25 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
26 SOFTWARE.
27 */
28 
29 #ifndef NLOHMANN_JSON_HPP
30 #define NLOHMANN_JSON_HPP
31 
32 #include <algorithm>
33 #include <array>
34 #include <cassert>
35 #include <cerrno>
36 #include <ciso646>
37 #include <cmath>
38 #include <cstddef>
39 #include <cstdio>
40 #include <cstdlib>
41 #include <functional>
42 #include <initializer_list>
43 #include <iomanip>
44 #include <iostream>
45 #include <iterator>
46 #include <limits>
47 #include <map>
48 #include <memory>
49 #include <sstream>
50 #include <stdexcept>
51 #include <string>
52 #include <type_traits>
53 #include <utility>
54 #include <vector>
55 
56 // disable float-equal warnings on GCC/clang
57 #if defined(__clang__) || defined(__GNUC__) || defined(__GNUG__)
58  #pragma GCC diagnostic push
59  #pragma GCC diagnostic ignored "-Wfloat-equal"
60 #endif
61 
67 namespace nlohmann
68 {
69 
70 
75 namespace
76 {
81 template<typename T>
82 struct has_mapped_type
83 {
84  private:
85  template<typename C> static char test(typename C::mapped_type*);
86  template<typename C> static char (&test(...))[2];
87  public:
88  static constexpr bool value = sizeof(test<T>(0)) == 1;
89 };
90 
95 class DecimalSeparator : public std::numpunct<char>
96 {
97  protected:
98  char do_decimal_point() const
99  {
100  return '.';
101  }
102 };
103 
104 }
105 
177 template <
178  template<typename U, typename V, typename... Args> class ObjectType = std::map,
179  template<typename U, typename... Args> class ArrayType = std::vector,
180  class StringType = std::string,
181  class BooleanType = bool,
182  class NumberIntegerType = std::int64_t,
183  class NumberUnsignedType = std::uint64_t,
184  class NumberFloatType = double,
185  template<typename U> class AllocatorType = std::allocator
186  >
188 {
189  private:
191  using basic_json_t = basic_json<ObjectType,
192  ArrayType,
193  StringType,
194  BooleanType,
195  NumberIntegerType,
196  NumberUnsignedType,
197  NumberFloatType,
198  AllocatorType>;
199 
200  public:
201  // forward declarations
202  template<typename Base> class json_reverse_iterator;
203  class json_pointer;
204 
206  // container types //
208 
211 
214 
218  using const_reference = const value_type&;
219 
221  using difference_type = std::ptrdiff_t;
223  using size_type = std::size_t;
224 
226  using allocator_type = AllocatorType<basic_json>;
227 
229  using pointer = typename std::allocator_traits<allocator_type>::pointer;
231  using const_pointer = typename std::allocator_traits<allocator_type>::const_pointer;
232 
234  class iterator;
236  class const_iterator;
241 
243 
244 
249  {
250  return allocator_type();
251  }
252 
253 
255  // JSON value data types //
257 
260 
344  using object_t = ObjectType<StringType,
345  basic_json,
346  std::less<StringType>,
347  AllocatorType<std::pair<const StringType,
348  basic_json>>>;
349 
394  using array_t = ArrayType<basic_json, AllocatorType<basic_json>>;
395 
441  using string_t = StringType;
442 
467  using boolean_t = BooleanType;
468 
539  using number_integer_t = NumberIntegerType;
540 
611  using number_unsigned_t = NumberUnsignedType;
612 
679  using number_float_t = NumberFloatType;
680 
682 
683 
685  // JSON type enumeration //
687 
698  enum class value_t : uint8_t
699  {
700  null,
701  object,
702  array,
703  string,
704  boolean,
705  number_integer,
706  number_unsigned,
707  number_float,
708  discarded
709  };
710 
711 
712  private:
713 
728  union type_data_t
729  {
730  struct
731  {
733  uint16_t type : 4;
735  uint16_t parsed : 1;
737  uint16_t has_exp : 1;
739  uint16_t exp_plus : 1;
741  uint16_t exp_cap : 1;
743  uint16_t precision : 8;
744  } bits;
745  uint16_t data;
746 
748  operator value_t() const
749  {
750  return static_cast<value_t>(bits.type);
751  }
752 
754  bool operator==(const value_t& rhs) const
755  {
756  return static_cast<value_t>(bits.type) == rhs;
757  }
758 
760  type_data_t& operator=(value_t rhs)
761  {
762  bits.type = static_cast<uint16_t>(rhs) & 15; // avoid overflow
763  return *this;
764  }
765 
767  type_data_t(value_t t) noexcept
768  {
769  *reinterpret_cast<uint16_t*>(this) = 0;
770  bits.type = static_cast<uint16_t>(t) & 15; // avoid overflow
771  }
772 
774  type_data_t() noexcept
775  {
776  data = 0;
777  bits.type = reinterpret_cast<uint16_t>(value_t::null);
778  }
779  };
780 
782  template<typename T, typename... Args>
783  static T* create(Args&& ... args)
784  {
785  AllocatorType<T> alloc;
786  auto deleter = [&](T * object)
787  {
788  alloc.deallocate(object, 1);
789  };
790  std::unique_ptr<T, decltype(deleter)> object(alloc.allocate(1), deleter);
791  alloc.construct(object.get(), std::forward<Args>(args)...);
792  return object.release();
793  }
794 
796  // JSON value storage //
798 
806  union json_value
807  {
809  object_t* object;
811  array_t* array;
813  string_t* string;
815  boolean_t boolean;
817  number_integer_t number_integer;
819  number_unsigned_t number_unsigned;
821  number_float_t number_float;
822 
824  json_value() = default;
826  json_value(boolean_t v) noexcept : boolean(v) {}
828  json_value(number_integer_t v) noexcept : number_integer(v) {}
830  json_value(number_unsigned_t v) noexcept : number_unsigned(v) {}
832  json_value(number_float_t v) noexcept : number_float(v) {}
834  json_value(value_t t)
835  {
836  switch (t)
837  {
838  case value_t::object:
839  {
840  object = create<object_t>();
841  break;
842  }
843 
844  case value_t::array:
845  {
846  array = create<array_t>();
847  break;
848  }
849 
850  case value_t::string:
851  {
852  string = create<string_t>("");
853  break;
854  }
855 
856  case value_t::boolean:
857  {
858  boolean = boolean_t(false);
859  break;
860  }
861 
862  case value_t::number_integer:
863  {
864  number_integer = number_integer_t(0);
865  break;
866  }
867 
868  case value_t::number_unsigned:
869  {
870  number_unsigned = number_unsigned_t(0);
871  break;
872  }
873 
874  case value_t::number_float:
875  {
876  number_float = number_float_t(0.0);
877  break;
878  }
879 
880  default:
881  {
882  break;
883  }
884  }
885  }
886 
888  json_value(const string_t& value)
889  {
890  string = create<string_t>(value);
891  }
892 
894  json_value(const object_t& value)
895  {
896  object = create<object_t>(value);
897  }
898 
900  json_value(const array_t& value)
901  {
902  array = create<array_t>(value);
903  }
904  };
905 
906 
907  public:
909  // JSON parser callback //
911 
920  enum class parse_event_t : uint8_t
921  {
923  object_start,
925  object_end,
927  array_start,
929  array_end,
931  key,
933  value
934  };
935 
985  using parser_callback_t = std::function<bool(int depth, parse_event_t event, basic_json& parsed)>;
986 
987 
989  // constructors //
991 
994 
1035  : m_type(value_type), m_value(value_type)
1036  {}
1037 
1062  basic_json() = default;
1063 
1086  basic_json(std::nullptr_t) noexcept
1087  : basic_json(value_t::null)
1088  {}
1089 
1109  basic_json(const object_t& val)
1110  : m_type(value_t::object), m_value(val)
1111  {}
1112 
1139  template <class CompatibleObjectType, typename
1140  std::enable_if<
1141  std::is_constructible<typename object_t::key_type, typename CompatibleObjectType::key_type>::value and
1142  std::is_constructible<basic_json, typename CompatibleObjectType::mapped_type>::value, int>::type
1143  = 0>
1144  basic_json(const CompatibleObjectType& val)
1145  : m_type(value_t::object)
1146  {
1147  using std::begin;
1148  using std::end;
1149  m_value.object = create<object_t>(begin(val), end(val));
1150  }
1151 
1171  basic_json(const array_t& val)
1172  : m_type(value_t::array), m_value(val)
1173  {}
1174 
1201  template <class CompatibleArrayType, typename
1202  std::enable_if<
1203  not std::is_same<CompatibleArrayType, typename basic_json_t::iterator>::value and
1204  not std::is_same<CompatibleArrayType, typename basic_json_t::const_iterator>::value and
1205  not std::is_same<CompatibleArrayType, typename basic_json_t::reverse_iterator>::value and
1206  not std::is_same<CompatibleArrayType, typename basic_json_t::const_reverse_iterator>::value and
1207  not std::is_same<CompatibleArrayType, typename array_t::iterator>::value and
1208  not std::is_same<CompatibleArrayType, typename array_t::const_iterator>::value and
1209  std::is_constructible<basic_json, typename CompatibleArrayType::value_type>::value, int>::type
1210  = 0>
1211  basic_json(const CompatibleArrayType& val)
1212  : m_type(value_t::array)
1213  {
1214  using std::begin;
1215  using std::end;
1216  m_value.array = create<array_t>(begin(val), end(val));
1217  }
1218 
1240  basic_json(const string_t& val)
1241  : m_type(value_t::string), m_value(val)
1242  {}
1243 
1264  basic_json(const typename string_t::value_type* val)
1265  : basic_json(string_t(val))
1266  {}
1267 
1291  template <class CompatibleStringType, typename
1292  std::enable_if<
1293  std::is_constructible<string_t, CompatibleStringType>::value, int>::type
1294  = 0>
1295  basic_json(const CompatibleStringType& val)
1296  : basic_json(string_t(val))
1297  {}
1298 
1313  basic_json(boolean_t val) noexcept
1314  : m_type(value_t::boolean), m_value(val)
1315  {}
1316 
1340  template<typename T,
1341  typename std::enable_if<
1342  not (std::is_same<T, int>::value)
1343  and std::is_same<T, number_integer_t>::value
1344  , int>::type
1345  = 0>
1346  basic_json(const number_integer_t val) noexcept
1347  : m_type(value_t::number_integer), m_value(val)
1348  {}
1349 
1375  basic_json(const int val) noexcept
1376  : m_type(value_t::number_integer),
1377  m_value(static_cast<number_integer_t>(val))
1378  {}
1379 
1405  template<typename CompatibleNumberIntegerType, typename
1406  std::enable_if<
1407  std::is_constructible<number_integer_t, CompatibleNumberIntegerType>::value and
1408  std::numeric_limits<CompatibleNumberIntegerType>::is_integer and
1409  std::numeric_limits<CompatibleNumberIntegerType>::is_signed,
1410  CompatibleNumberIntegerType>::type
1411  = 0>
1412  basic_json(const CompatibleNumberIntegerType val) noexcept
1413  : m_type(value_t::number_integer),
1414  m_value(static_cast<number_integer_t>(val))
1415  {}
1416 
1434  template<typename T,
1435  typename std::enable_if<
1436  not (std::is_same<T, int>::value)
1437  and std::is_same<T, number_unsigned_t>::value
1438  , int>::type
1439  = 0>
1440  basic_json(const number_unsigned_t val) noexcept
1441  : m_type(value_t::number_unsigned), m_value(val)
1442  {}
1443 
1464  template < typename CompatibleNumberUnsignedType, typename
1465  std::enable_if <
1466  std::is_constructible<number_unsigned_t, CompatibleNumberUnsignedType>::value and
1467  std::numeric_limits<CompatibleNumberUnsignedType>::is_integer and
1468  !std::numeric_limits<CompatibleNumberUnsignedType>::is_signed,
1469  CompatibleNumberUnsignedType >::type
1470  = 0 >
1471  basic_json(const CompatibleNumberUnsignedType val) noexcept
1472  : m_type(value_t::number_unsigned),
1473  m_value(static_cast<number_unsigned_t>(val))
1474  {}
1475 
1500  basic_json(const number_float_t val) noexcept
1501  : m_type(value_t::number_float), m_value(val)
1502  {
1503  // replace infinity and NAN by null
1504  if (not std::isfinite(val))
1505  {
1506  m_type = value_t::null;
1507  m_value = json_value();
1508  }
1509  }
1510 
1542  template<typename CompatibleNumberFloatType, typename = typename
1543  std::enable_if<
1544  std::is_constructible<number_float_t, CompatibleNumberFloatType>::value and
1545  std::is_floating_point<CompatibleNumberFloatType>::value>::type
1546  >
1547  basic_json(const CompatibleNumberFloatType val) noexcept
1548  : basic_json(number_float_t(val))
1549  {}
1550 
1620  basic_json(std::initializer_list<basic_json> init,
1621  bool type_deduction = true,
1622  value_t manual_type = value_t::array)
1623  {
1624  // the initializer list could describe an object
1625  bool is_an_object = true;
1626 
1627  // check if each element is an array with two elements whose first
1628  // element is a string
1629  for (const auto& element : init)
1630  {
1631  if (not element.is_array() or element.size() != 2
1632  or not element[0].is_string())
1633  {
1634  // we found an element that makes it impossible to use the
1635  // initializer list as object
1636  is_an_object = false;
1637  break;
1638  }
1639  }
1640 
1641  // adjust type if type deduction is not wanted
1642  if (not type_deduction)
1643  {
1644  // if array is wanted, do not create an object though possible
1645  if (manual_type == value_t::array)
1646  {
1647  is_an_object = false;
1648  }
1649 
1650  // if object is wanted but impossible, throw an exception
1651  if (manual_type == value_t::object and not is_an_object)
1652  {
1653  throw std::domain_error("cannot create object from initializer list");
1654  }
1655  }
1656 
1657  if (is_an_object)
1658  {
1659  // the initializer list is a list of pairs -> create object
1660  m_type = value_t::object;
1661  m_value = value_t::object;
1662 
1663  assert(m_value.object != nullptr);
1664 
1665  for (auto& element : init)
1666  {
1667  m_value.object->emplace(*(element[0].m_value.string), element[1]);
1668  }
1669  }
1670  else
1671  {
1672  // the initializer list describes an array -> create array
1673  m_type = value_t::array;
1674  m_value.array = create<array_t>(init);
1675  }
1676  }
1677 
1712  static basic_json array(std::initializer_list<basic_json> init =
1713  std::initializer_list<basic_json>())
1714  {
1715  return basic_json(init, false, value_t::array);
1716  }
1717 
1752  static basic_json object(std::initializer_list<basic_json> init =
1753  std::initializer_list<basic_json>())
1754  {
1755  return basic_json(init, false, value_t::object);
1756  }
1757 
1776  basic_json(size_type cnt, const basic_json& val)
1777  : m_type(value_t::array)
1778  {
1779  m_value.array = create<array_t>(cnt, val);
1780  }
1781 
1816  template <class InputIT, typename
1817  std::enable_if<
1818  std::is_same<InputIT, typename basic_json_t::iterator>::value or
1819  std::is_same<InputIT, typename basic_json_t::const_iterator>::value
1820  , int>::type
1821  = 0>
1822  basic_json(InputIT first, InputIT last) : m_type(first.m_object->m_type)
1823  {
1824  // make sure iterator fits the current value
1825  if (first.m_object != last.m_object)
1826  {
1827  throw std::domain_error("iterators are not compatible");
1828  }
1829 
1830  // check if iterator range is complete for primitive values
1831  switch (m_type)
1832  {
1833  case value_t::boolean:
1834  case value_t::number_float:
1835  case value_t::number_integer:
1836  case value_t::number_unsigned:
1837  case value_t::string:
1838  {
1839  if (not first.m_it.primitive_iterator.is_begin() or not last.m_it.primitive_iterator.is_end())
1840  {
1841  throw std::out_of_range("iterators out of range");
1842  }
1843  break;
1844  }
1845 
1846  default:
1847  {
1848  break;
1849  }
1850  }
1851 
1852  switch (m_type)
1853  {
1854  case value_t::number_integer:
1855  {
1856  assert(first.m_object != nullptr);
1857  m_value.number_integer = first.m_object->m_value.number_integer;
1858  break;
1859  }
1860 
1861  case value_t::number_unsigned:
1862  {
1863  assert(first.m_object != nullptr);
1864  m_value.number_unsigned = first.m_object->m_value.number_unsigned;
1865  break;
1866  }
1867 
1868  case value_t::number_float:
1869  {
1870  assert(first.m_object != nullptr);
1871  m_value.number_float = first.m_object->m_value.number_float;
1872  break;
1873  }
1874 
1875  case value_t::boolean:
1876  {
1877  assert(first.m_object != nullptr);
1878  m_value.boolean = first.m_object->m_value.boolean;
1879  break;
1880  }
1881 
1882  case value_t::string:
1883  {
1884  assert(first.m_object != nullptr);
1885  m_value = *first.m_object->m_value.string;
1886  break;
1887  }
1888 
1889  case value_t::object:
1890  {
1891  m_value.object = create<object_t>(first.m_it.object_iterator, last.m_it.object_iterator);
1892  break;
1893  }
1894 
1895  case value_t::array:
1896  {
1897  m_value.array = create<array_t>(first.m_it.array_iterator, last.m_it.array_iterator);
1898  break;
1899  }
1900 
1901  default:
1902  {
1903  assert(first.m_object != nullptr);
1904  throw std::domain_error("cannot use construct with iterators from " + first.m_object->type_name());
1905  }
1906  }
1907  }
1908 
1929  explicit basic_json(std::istream& i, parser_callback_t cb = nullptr)
1930  {
1931  *this = parser(i, cb).parse();
1932  }
1933 
1935  // other constructors and destructor //
1937 
1960  basic_json(const basic_json& other)
1961  : m_type(other.m_type)
1962  {
1963  switch (m_type)
1964  {
1965  case value_t::object:
1966  {
1967  assert(other.m_value.object != nullptr);
1968  m_value = *other.m_value.object;
1969  break;
1970  }
1971 
1972  case value_t::array:
1973  {
1974  assert(other.m_value.array != nullptr);
1975  m_value = *other.m_value.array;
1976  break;
1977  }
1978 
1979  case value_t::string:
1980  {
1981  assert(other.m_value.string != nullptr);
1982  m_value = *other.m_value.string;
1983  break;
1984  }
1985 
1986  case value_t::boolean:
1987  {
1988  m_value = other.m_value.boolean;
1989  break;
1990  }
1991 
1992  case value_t::number_integer:
1993  {
1994  m_value = other.m_value.number_integer;
1995  break;
1996  }
1997 
1998  case value_t::number_unsigned:
1999  {
2000  m_value = other.m_value.number_unsigned;
2001  break;
2002  }
2003 
2004  case value_t::number_float:
2005  {
2006  m_value = other.m_value.number_float;
2007  break;
2008  }
2009 
2010  default:
2011  {
2012  break;
2013  }
2014  }
2015  }
2016 
2035  basic_json(basic_json&& other) noexcept
2036  : m_type(std::move(other.m_type)),
2037  m_value(std::move(other.m_value))
2038  {
2039  // invalidate payload
2040  other.m_type = value_t::null;
2041  other.m_value = {};
2042  }
2043 
2067  reference& operator=(basic_json other) noexcept (
2068  std::is_nothrow_move_constructible<value_t>::value and
2069  std::is_nothrow_move_assignable<value_t>::value and
2070  std::is_nothrow_move_constructible<json_value>::value and
2071  std::is_nothrow_move_assignable<json_value>::value
2072  )
2073  {
2074  using std::swap;
2075  swap(m_type, other.m_type);
2076  swap(m_value, other.m_value);
2077  return *this;
2078  }
2079 
2096  {
2097  switch (m_type)
2098  {
2099  case value_t::object:
2100  {
2101  AllocatorType<object_t> alloc;
2102  alloc.destroy(m_value.object);
2103  alloc.deallocate(m_value.object, 1);
2104  break;
2105  }
2106 
2107  case value_t::array:
2108  {
2109  AllocatorType<array_t> alloc;
2110  alloc.destroy(m_value.array);
2111  alloc.deallocate(m_value.array, 1);
2112  break;
2113  }
2114 
2115  case value_t::string:
2116  {
2117  AllocatorType<string_t> alloc;
2118  alloc.destroy(m_value.string);
2119  alloc.deallocate(m_value.string, 1);
2120  break;
2121  }
2122 
2123  default:
2124  {
2125  // all other types need no specific destructor
2126  break;
2127  }
2128  }
2129  }
2130 
2132 
2133  public:
2135  // object inspection //
2137 
2140 
2164  string_t dump(const int indent = -1) const
2165  {
2166  std::stringstream ss;
2167 
2168  if (indent >= 0)
2169  {
2170  dump(ss, true, static_cast<unsigned int>(indent));
2171  }
2172  else
2173  {
2174  dump(ss, false, 0);
2175  }
2176 
2177  return ss.str();
2178  }
2179 
2198  constexpr value_t type() const noexcept
2199  {
2200  return m_type;
2201  }
2202 
2228  constexpr bool is_primitive() const noexcept
2229  {
2230  return is_null() or is_string() or is_boolean() or is_number();
2231  }
2232 
2255  constexpr bool is_structured() const noexcept
2256  {
2257  return is_array() or is_object();
2258  }
2259 
2277  constexpr bool is_null() const noexcept
2278  {
2279  return m_type == value_t::null;
2280  }
2281 
2299  constexpr bool is_boolean() const noexcept
2300  {
2301  return m_type == value_t::boolean;
2302  }
2303 
2329  constexpr bool is_number() const noexcept
2330  {
2331  return is_number_integer() or is_number_float();
2332  }
2333 
2358  constexpr bool is_number_integer() const noexcept
2359  {
2360  return m_type == value_t::number_integer or m_type == value_t::number_unsigned;
2361  }
2362 
2386  constexpr bool is_number_unsigned() const noexcept
2387  {
2388  return m_type == value_t::number_unsigned;
2389  }
2390 
2414  constexpr bool is_number_float() const noexcept
2415  {
2416  return m_type == value_t::number_float;
2417  }
2418 
2436  constexpr bool is_object() const noexcept
2437  {
2438  return m_type == value_t::object;
2439  }
2440 
2458  constexpr bool is_array() const noexcept
2459  {
2460  return m_type == value_t::array;
2461  }
2462 
2480  constexpr bool is_string() const noexcept
2481  {
2482  return m_type == value_t::string;
2483  }
2484 
2507  constexpr bool is_discarded() const noexcept
2508  {
2509  return m_type == value_t::discarded;
2510  }
2511 
2530  constexpr operator value_t() const noexcept
2531  {
2532  return m_type;
2533  }
2534 
2536 
2537  private:
2539  // value access //
2541 
2543  template <class T, typename
2544  std::enable_if<
2545  std::is_convertible<typename object_t::key_type, typename T::key_type>::value and
2546  std::is_convertible<basic_json_t, typename T::mapped_type>::value
2547  , int>::type = 0>
2548  T get_impl(T*) const
2549  {
2550  if (is_object())
2551  {
2552  assert(m_value.object != nullptr);
2553  return T(m_value.object->begin(), m_value.object->end());
2554  }
2555  else
2556  {
2557  throw std::domain_error("type must be object, but is " + type_name());
2558  }
2559  }
2560 
2562  object_t get_impl(object_t*) const
2563  {
2564  if (is_object())
2565  {
2566  assert(m_value.object != nullptr);
2567  return *(m_value.object);
2568  }
2569  else
2570  {
2571  throw std::domain_error("type must be object, but is " + type_name());
2572  }
2573  }
2574 
2576  template <class T, typename
2577  std::enable_if<
2578  std::is_convertible<basic_json_t, typename T::value_type>::value and
2579  not std::is_same<basic_json_t, typename T::value_type>::value and
2580  not std::is_arithmetic<T>::value and
2581  not std::is_convertible<std::string, T>::value and
2582  not has_mapped_type<T>::value
2583  , int>::type = 0>
2584  T get_impl(T*) const
2585  {
2586  if (is_array())
2587  {
2588  T to_vector;
2589  assert(m_value.array != nullptr);
2590  std::transform(m_value.array->begin(), m_value.array->end(),
2591  std::inserter(to_vector, to_vector.end()), [](basic_json i)
2592  {
2593  return i.get<typename T::value_type>();
2594  });
2595  return to_vector;
2596  }
2597  else
2598  {
2599  throw std::domain_error("type must be array, but is " + type_name());
2600  }
2601  }
2602 
2604  template <class T, typename
2605  std::enable_if<
2606  std::is_convertible<basic_json_t, T>::value and
2607  not std::is_same<basic_json_t, T>::value
2608  , int>::type = 0>
2609  std::vector<T> get_impl(std::vector<T>*) const
2610  {
2611  if (is_array())
2612  {
2613  std::vector<T> to_vector;
2614  assert(m_value.array != nullptr);
2615  to_vector.reserve(m_value.array->size());
2616  std::transform(m_value.array->begin(), m_value.array->end(),
2617  std::inserter(to_vector, to_vector.end()), [](basic_json i)
2618  {
2619  return i.get<T>();
2620  });
2621  return to_vector;
2622  }
2623  else
2624  {
2625  throw std::domain_error("type must be array, but is " + type_name());
2626  }
2627  }
2628 
2630  template <class T, typename
2631  std::enable_if<
2632  std::is_same<basic_json, typename T::value_type>::value and
2633  not has_mapped_type<T>::value
2634  , int>::type = 0>
2635  T get_impl(T*) const
2636  {
2637  if (is_array())
2638  {
2639  assert(m_value.array != nullptr);
2640  return T(m_value.array->begin(), m_value.array->end());
2641  }
2642  else
2643  {
2644  throw std::domain_error("type must be array, but is " + type_name());
2645  }
2646  }
2647 
2649  array_t get_impl(array_t*) const
2650  {
2651  if (is_array())
2652  {
2653  assert(m_value.array != nullptr);
2654  return *(m_value.array);
2655  }
2656  else
2657  {
2658  throw std::domain_error("type must be array, but is " + type_name());
2659  }
2660  }
2661 
2663  template <typename T, typename
2664  std::enable_if<
2665  std::is_convertible<string_t, T>::value
2666  , int>::type = 0>
2667  T get_impl(T*) const
2668  {
2669  if (is_string())
2670  {
2671  assert(m_value.string != nullptr);
2672  return *m_value.string;
2673  }
2674  else
2675  {
2676  throw std::domain_error("type must be string, but is " + type_name());
2677  }
2678  }
2679 
2681  template<typename T, typename
2682  std::enable_if<
2683  std::is_arithmetic<T>::value
2684  , int>::type = 0>
2685  T get_impl(T*) const
2686  {
2687  switch (m_type)
2688  {
2689  case value_t::number_integer:
2690  {
2691  return static_cast<T>(m_value.number_integer);
2692  }
2693 
2694  case value_t::number_unsigned:
2695  {
2696  return static_cast<T>(m_value.number_unsigned);
2697  }
2698 
2699  case value_t::number_float:
2700  {
2701  return static_cast<T>(m_value.number_float);
2702  }
2703 
2704  default:
2705  {
2706  throw std::domain_error("type must be number, but is " + type_name());
2707  }
2708  }
2709  }
2710 
2712  constexpr boolean_t get_impl(boolean_t*) const
2713  {
2714  return is_boolean()
2715  ? m_value.boolean
2716  : throw std::domain_error("type must be boolean, but is " + type_name());
2717  }
2718 
2720  object_t* get_impl_ptr(object_t*) noexcept
2721  {
2722  return is_object() ? m_value.object : nullptr;
2723  }
2724 
2726  constexpr const object_t* get_impl_ptr(const object_t*) const noexcept
2727  {
2728  return is_object() ? m_value.object : nullptr;
2729  }
2730 
2732  array_t* get_impl_ptr(array_t*) noexcept
2733  {
2734  return is_array() ? m_value.array : nullptr;
2735  }
2736 
2738  constexpr const array_t* get_impl_ptr(const array_t*) const noexcept
2739  {
2740  return is_array() ? m_value.array : nullptr;
2741  }
2742 
2744  string_t* get_impl_ptr(string_t*) noexcept
2745  {
2746  return is_string() ? m_value.string : nullptr;
2747  }
2748 
2750  constexpr const string_t* get_impl_ptr(const string_t*) const noexcept
2751  {
2752  return is_string() ? m_value.string : nullptr;
2753  }
2754 
2756  boolean_t* get_impl_ptr(boolean_t*) noexcept
2757  {
2758  return is_boolean() ? &m_value.boolean : nullptr;
2759  }
2760 
2762  constexpr const boolean_t* get_impl_ptr(const boolean_t*) const noexcept
2763  {
2764  return is_boolean() ? &m_value.boolean : nullptr;
2765  }
2766 
2768  number_integer_t* get_impl_ptr(number_integer_t*) noexcept
2769  {
2770  return is_number_integer() ? &m_value.number_integer : nullptr;
2771  }
2772 
2774  constexpr const number_integer_t* get_impl_ptr(const number_integer_t*) const noexcept
2775  {
2776  return is_number_integer() ? &m_value.number_integer : nullptr;
2777  }
2778 
2780  number_unsigned_t* get_impl_ptr(number_unsigned_t*) noexcept
2781  {
2782  return is_number_unsigned() ? &m_value.number_unsigned : nullptr;
2783  }
2784 
2786  constexpr const number_unsigned_t* get_impl_ptr(const number_unsigned_t*) const noexcept
2787  {
2788  return is_number_unsigned() ? &m_value.number_unsigned : nullptr;
2789  }
2790 
2792  number_float_t* get_impl_ptr(number_float_t*) noexcept
2793  {
2794  return is_number_float() ? &m_value.number_float : nullptr;
2795  }
2796 
2798  constexpr const number_float_t* get_impl_ptr(const number_float_t*) const noexcept
2799  {
2800  return is_number_float() ? &m_value.number_float : nullptr;
2801  }
2802 
2814  template<typename ReferenceType, typename ThisType>
2815  static ReferenceType get_ref_impl(ThisType& obj)
2816  {
2817  // delegate the call to get_ptr<>()
2818  using PointerType = typename std::add_pointer<ReferenceType>::type;
2819  auto ptr = obj.template get_ptr<PointerType>();
2820 
2821  if (ptr != nullptr)
2822  {
2823  return *ptr;
2824  }
2825  else
2826  {
2827  throw std::domain_error("incompatible ReferenceType for get_ref, actual type is " +
2828  obj.type_name());
2829  }
2830  }
2831 
2832  public:
2833 
2836 
2870  template<typename ValueType, typename
2871  std::enable_if<
2872  not std::is_pointer<ValueType>::value
2873  , int>::type = 0>
2874  ValueType get() const
2875  {
2876  return get_impl(static_cast<ValueType*>(nullptr));
2877  }
2878 
2905  template<typename PointerType, typename
2906  std::enable_if<
2907  std::is_pointer<PointerType>::value
2908  , int>::type = 0>
2909  PointerType get() noexcept
2910  {
2911  // delegate the call to get_ptr
2912  return get_ptr<PointerType>();
2913  }
2914 
2919  template<typename PointerType, typename
2920  std::enable_if<
2921  std::is_pointer<PointerType>::value
2922  , int>::type = 0>
2923  constexpr const PointerType get() const noexcept
2924  {
2925  // delegate the call to get_ptr
2926  return get_ptr<PointerType>();
2927  }
2928 
2954  template<typename PointerType, typename
2955  std::enable_if<
2956  std::is_pointer<PointerType>::value
2957  , int>::type = 0>
2958  PointerType get_ptr() noexcept
2959  {
2960  // delegate the call to get_impl_ptr<>()
2961  return get_impl_ptr(static_cast<PointerType>(nullptr));
2962  }
2963 
2968  template<typename PointerType, typename
2969  std::enable_if<
2970  std::is_pointer<PointerType>::value
2971  and std::is_const<typename std::remove_pointer<PointerType>::type>::value
2972  , int>::type = 0>
2973  constexpr const PointerType get_ptr() const noexcept
2974  {
2975  // delegate the call to get_impl_ptr<>() const
2976  return get_impl_ptr(static_cast<const PointerType>(nullptr));
2977  }
2978 
3005  template<typename ReferenceType, typename
3006  std::enable_if<
3007  std::is_reference<ReferenceType>::value
3008  , int>::type = 0>
3009  ReferenceType get_ref()
3010  {
3011  // delegate call to get_ref_impl
3012  return get_ref_impl<ReferenceType>(*this);
3013  }
3014 
3019  template<typename ReferenceType, typename
3020  std::enable_if<
3021  std::is_reference<ReferenceType>::value
3022  and std::is_const<typename std::remove_reference<ReferenceType>::type>::value
3023  , int>::type = 0>
3024  ReferenceType get_ref() const
3025  {
3026  // delegate call to get_ref_impl
3027  return get_ref_impl<ReferenceType>(*this);
3028  }
3029 
3058  template < typename ValueType, typename
3059  std::enable_if <
3060  not std::is_pointer<ValueType>::value
3061  and not std::is_same<ValueType, typename string_t::value_type>::value
3062 #ifndef _MSC_VER // Fix for issue #167 operator<< abiguity under VS2015
3063  and not std::is_same<ValueType, std::initializer_list<typename string_t::value_type>>::value
3064 #endif
3065  , int >::type = 0 >
3066  operator ValueType() const
3067  {
3068  // delegate the call to get<>() const
3069  return get<ValueType>();
3070  }
3071 
3073 
3074 
3076  // element access //
3078 
3081 
3105  {
3106  // at only works for arrays
3107  if (is_array())
3108  {
3109  try
3110  {
3111  assert(m_value.array != nullptr);
3112  return m_value.array->at(idx);
3113  }
3114  catch (std::out_of_range&)
3115  {
3116  // create better exception explanation
3117  throw std::out_of_range("array index " + std::to_string(idx) + " is out of range");
3118  }
3119  }
3120  else
3121  {
3122  throw std::domain_error("cannot use at() with " + type_name());
3123  }
3124  }
3125 
3149  {
3150  // at only works for arrays
3151  if (is_array())
3152  {
3153  try
3154  {
3155  assert(m_value.array != nullptr);
3156  return m_value.array->at(idx);
3157  }
3158  catch (std::out_of_range&)
3159  {
3160  // create better exception explanation
3161  throw std::out_of_range("array index " + std::to_string(idx) + " is out of range");
3162  }
3163  }
3164  else
3165  {
3166  throw std::domain_error("cannot use at() with " + type_name());
3167  }
3168  }
3169 
3196  reference at(const typename object_t::key_type& key)
3197  {
3198  // at only works for objects
3199  if (is_object())
3200  {
3201  try
3202  {
3203  assert(m_value.object != nullptr);
3204  return m_value.object->at(key);
3205  }
3206  catch (std::out_of_range&)
3207  {
3208  // create better exception explanation
3209  throw std::out_of_range("key '" + key + "' not found");
3210  }
3211  }
3212  else
3213  {
3214  throw std::domain_error("cannot use at() with " + type_name());
3215  }
3216  }
3217 
3244  const_reference at(const typename object_t::key_type& key) const
3245  {
3246  // at only works for objects
3247  if (is_object())
3248  {
3249  try
3250  {
3251  assert(m_value.object != nullptr);
3252  return m_value.object->at(key);
3253  }
3254  catch (std::out_of_range&)
3255  {
3256  // create better exception explanation
3257  throw std::out_of_range("key '" + key + "' not found");
3258  }
3259  }
3260  else
3261  {
3262  throw std::domain_error("cannot use at() with " + type_name());
3263  }
3264  }
3265 
3292  {
3293  // implicitly convert null value to an empty array
3294  if (is_null())
3295  {
3296  m_type = value_t::array;
3297  m_value.array = create<array_t>();
3298  }
3299 
3300  // operator[] only works for arrays
3301  if (is_array())
3302  {
3303  // fill up array with null values until given idx is reached
3304  assert(m_value.array != nullptr);
3305  for (size_t i = m_value.array->size(); i <= idx; ++i)
3306  {
3307  m_value.array->push_back(basic_json());
3308  }
3309 
3310  return m_value.array->operator[](idx);
3311  }
3312  else
3313  {
3314  throw std::domain_error("cannot use operator[] with " + type_name());
3315  }
3316  }
3317 
3338  {
3339  // const operator[] only works for arrays
3340  if (is_array())
3341  {
3342  assert(m_value.array != nullptr);
3343  return m_value.array->operator[](idx);
3344  }
3345  else
3346  {
3347  throw std::domain_error("cannot use operator[] with " + type_name());
3348  }
3349  }
3350 
3378  reference operator[](const typename object_t::key_type& key)
3379  {
3380  // implicitly convert null value to an empty object
3381  if (is_null())
3382  {
3383  m_type = value_t::object;
3384  m_value.object = create<object_t>();
3385  }
3386 
3387  // operator[] only works for objects
3388  if (is_object())
3389  {
3390  assert(m_value.object != nullptr);
3391  return m_value.object->operator[](key);
3392  }
3393  else
3394  {
3395  throw std::domain_error("cannot use operator[] with " + type_name());
3396  }
3397  }
3398 
3426  const_reference operator[](const typename object_t::key_type& key) const
3427  {
3428  // const operator[] only works for objects
3429  if (is_object())
3430  {
3431  assert(m_value.object != nullptr);
3432  assert(m_value.object->find(key) != m_value.object->end());
3433  return m_value.object->find(key)->second;
3434  }
3435  else
3436  {
3437  throw std::domain_error("cannot use operator[] with " + type_name());
3438  }
3439  }
3440 
3468  template<typename T, std::size_t n>
3469  reference operator[](T * (&key)[n])
3470  {
3471  return operator[](static_cast<const T>(key));
3472  }
3473 
3503  template<typename T, std::size_t n>
3504  const_reference operator[](T * (&key)[n]) const
3505  {
3506  return operator[](static_cast<const T>(key));
3507  }
3508 
3536  template<typename T>
3538  {
3539  // implicitly convert null to object
3540  if (is_null())
3541  {
3542  m_type = value_t::object;
3543  m_value = value_t::object;
3544  }
3545 
3546  // at only works for objects
3547  if (is_object())
3548  {
3549  assert(m_value.object != nullptr);
3550  return m_value.object->operator[](key);
3551  }
3552  else
3553  {
3554  throw std::domain_error("cannot use operator[] with " + type_name());
3555  }
3556  }
3557 
3585  template<typename T>
3587  {
3588  // at only works for objects
3589  if (is_object())
3590  {
3591  assert(m_value.object != nullptr);
3592  assert(m_value.object->find(key) != m_value.object->end());
3593  return m_value.object->find(key)->second;
3594  }
3595  else
3596  {
3597  throw std::domain_error("cannot use operator[] with " + type_name());
3598  }
3599  }
3600 
3649  template <class ValueType, typename
3650  std::enable_if<
3651  std::is_convertible<basic_json_t, ValueType>::value
3652  , int>::type = 0>
3653  ValueType value(const typename object_t::key_type& key, ValueType default_value) const
3654  {
3655  // at only works for objects
3656  if (is_object())
3657  {
3658  // if key is found, return value and given default value otherwise
3659  const auto it = find(key);
3660  if (it != end())
3661  {
3662  return *it;
3663  }
3664  else
3665  {
3666  return default_value;
3667  }
3668  }
3669  else
3670  {
3671  throw std::domain_error("cannot use value() with " + type_name());
3672  }
3673  }
3674 
3679  string_t value(const typename object_t::key_type& key, const char* default_value) const
3680  {
3681  return value(key, string_t(default_value));
3682  }
3683 
3709  {
3710  return *begin();
3711  }
3712 
3717  {
3718  return *cbegin();
3719  }
3720 
3751  {
3752  auto tmp = end();
3753  --tmp;
3754  return *tmp;
3755  }
3756 
3761  {
3762  auto tmp = cend();
3763  --tmp;
3764  return *tmp;
3765  }
3766 
3812  template <class InteratorType, typename
3813  std::enable_if<
3814  std::is_same<InteratorType, typename basic_json_t::iterator>::value or
3815  std::is_same<InteratorType, typename basic_json_t::const_iterator>::value
3816  , int>::type
3817  = 0>
3818  InteratorType erase(InteratorType pos)
3819  {
3820  // make sure iterator fits the current value
3821  if (this != pos.m_object)
3822  {
3823  throw std::domain_error("iterator does not fit current value");
3824  }
3825 
3826  InteratorType result = end();
3827 
3828  switch (m_type)
3829  {
3830  case value_t::boolean:
3831  case value_t::number_float:
3832  case value_t::number_integer:
3833  case value_t::number_unsigned:
3834  case value_t::string:
3835  {
3836  if (not pos.m_it.primitive_iterator.is_begin())
3837  {
3838  throw std::out_of_range("iterator out of range");
3839  }
3840 
3841  if (is_string())
3842  {
3843  delete m_value.string;
3844  m_value.string = nullptr;
3845  }
3846 
3847  m_type = value_t::null;
3848  break;
3849  }
3850 
3851  case value_t::object:
3852  {
3853  assert(m_value.object != nullptr);
3854  result.m_it.object_iterator = m_value.object->erase(pos.m_it.object_iterator);
3855  break;
3856  }
3857 
3858  case value_t::array:
3859  {
3860  assert(m_value.array != nullptr);
3861  result.m_it.array_iterator = m_value.array->erase(pos.m_it.array_iterator);
3862  break;
3863  }
3864 
3865  default:
3866  {
3867  throw std::domain_error("cannot use erase() with " + type_name());
3868  }
3869  }
3870 
3871  return result;
3872  }
3873 
3920  template <class InteratorType, typename
3921  std::enable_if<
3922  std::is_same<InteratorType, typename basic_json_t::iterator>::value or
3923  std::is_same<InteratorType, typename basic_json_t::const_iterator>::value
3924  , int>::type
3925  = 0>
3926  InteratorType erase(InteratorType first, InteratorType last)
3927  {
3928  // make sure iterator fits the current value
3929  if (this != first.m_object or this != last.m_object)
3930  {
3931  throw std::domain_error("iterators do not fit current value");
3932  }
3933 
3934  InteratorType result = end();
3935 
3936  switch (m_type)
3937  {
3938  case value_t::boolean:
3939  case value_t::number_float:
3940  case value_t::number_integer:
3941  case value_t::number_unsigned:
3942  case value_t::string:
3943  {
3944  if (not first.m_it.primitive_iterator.is_begin() or not last.m_it.primitive_iterator.is_end())
3945  {
3946  throw std::out_of_range("iterators out of range");
3947  }
3948 
3949  if (is_string())
3950  {
3951  delete m_value.string;
3952  m_value.string = nullptr;
3953  }
3954 
3955  m_type = value_t::null;
3956  break;
3957  }
3958 
3959  case value_t::object:
3960  {
3961  assert(m_value.object != nullptr);
3962  result.m_it.object_iterator = m_value.object->erase(first.m_it.object_iterator,
3963  last.m_it.object_iterator);
3964  break;
3965  }
3966 
3967  case value_t::array:
3968  {
3969  assert(m_value.array != nullptr);
3970  result.m_it.array_iterator = m_value.array->erase(first.m_it.array_iterator,
3971  last.m_it.array_iterator);
3972  break;
3973  }
3974 
3975  default:
3976  {
3977  throw std::domain_error("cannot use erase() with " + type_name());
3978  }
3979  }
3980 
3981  return result;
3982  }
3983 
4013  size_type erase(const typename object_t::key_type& key)
4014  {
4015  // this erase only works for objects
4016  if (is_object())
4017  {
4018  assert(m_value.object != nullptr);
4019  return m_value.object->erase(key);
4020  }
4021  else
4022  {
4023  throw std::domain_error("cannot use erase() with " + type_name());
4024  }
4025  }
4026 
4051  void erase(const size_type idx)
4052  {
4053  // this erase only works for arrays
4054  if (is_array())
4055  {
4056  if (idx >= size())
4057  {
4058  throw std::out_of_range("array index " + std::to_string(idx) + " is out of range");
4059  }
4060 
4061  assert(m_value.array != nullptr);
4062  m_value.array->erase(m_value.array->begin() + static_cast<difference_type>(idx));
4063  }
4064  else
4065  {
4066  throw std::domain_error("cannot use erase() with " + type_name());
4067  }
4068  }
4069 
4071 
4072 
4074  // lookup //
4076 
4079 
4098  iterator find(typename object_t::key_type key)
4099  {
4100  auto result = end();
4101 
4102  if (is_object())
4103  {
4104  assert(m_value.object != nullptr);
4105  result.m_it.object_iterator = m_value.object->find(key);
4106  }
4107 
4108  return result;
4109  }
4110 
4115  const_iterator find(typename object_t::key_type key) const
4116  {
4117  auto result = cend();
4118 
4119  if (is_object())
4120  {
4121  assert(m_value.object != nullptr);
4122  result.m_it.object_iterator = m_value.object->find(key);
4123  }
4124 
4125  return result;
4126  }
4127 
4146  size_type count(typename object_t::key_type key) const
4147  {
4148  // return 0 for all nonobject types
4149  assert(not is_object() or m_value.object != nullptr);
4150  return is_object() ? m_value.object->count(key) : 0;
4151  }
4152 
4154 
4155 
4157  // iterators //
4159 
4162 
4187  iterator begin() noexcept
4188  {
4189  iterator result(this);
4190  result.set_begin();
4191  return result;
4192  }
4193 
4197  const_iterator begin() const noexcept
4198  {
4199  return cbegin();
4200  }
4201 
4227  const_iterator cbegin() const noexcept
4228  {
4229  const_iterator result(this);
4230  result.set_begin();
4231  return result;
4232  }
4233 
4258  iterator end() noexcept
4259  {
4260  iterator result(this);
4261  result.set_end();
4262  return result;
4263  }
4264 
4268  const_iterator end() const noexcept
4269  {
4270  return cend();
4271  }
4272 
4298  const_iterator cend() const noexcept
4299  {
4300  const_iterator result(this);
4301  result.set_end();
4302  return result;
4303  }
4304 
4329  {
4330  return reverse_iterator(end());
4331  }
4332 
4337  {
4338  return crbegin();
4339  }
4340 
4366  {
4367  return reverse_iterator(begin());
4368  }
4369 
4373  const_reverse_iterator rend() const noexcept
4374  {
4375  return crend();
4376  }
4377 
4403  {
4404  return const_reverse_iterator(cend());
4405  }
4406 
4432  {
4433  return const_reverse_iterator(cbegin());
4434  }
4435 
4436  private:
4437  // forward declaration
4438  template<typename IteratorType> class iteration_proxy;
4439 
4440  public:
4452  static iteration_proxy<iterator> iterator_wrapper(reference cont)
4453  {
4454  return iteration_proxy<iterator>(cont);
4455  }
4456 
4460  static iteration_proxy<const_iterator> iterator_wrapper(const_reference cont)
4461  {
4462  return iteration_proxy<const_iterator>(cont);
4463  }
4464 
4466 
4467 
4469  // capacity //
4471 
4474 
4508  bool empty() const noexcept
4509  {
4510  switch (m_type)
4511  {
4512  case value_t::null:
4513  {
4514  // null values are empty
4515  return true;
4516  }
4517 
4518  case value_t::array:
4519  {
4520  assert(m_value.array != nullptr);
4521  return m_value.array->empty();
4522  }
4523 
4524  case value_t::object:
4525  {
4526  assert(m_value.object != nullptr);
4527  return m_value.object->empty();
4528  }
4529 
4530  default:
4531  {
4532  // all other types are nonempty
4533  return false;
4534  }
4535  }
4536  }
4537 
4572  size_type size() const noexcept
4573  {
4574  switch (m_type)
4575  {
4576  case value_t::null:
4577  {
4578  // null values are empty
4579  return 0;
4580  }
4581 
4582  case value_t::array:
4583  {
4584  assert(m_value.array != nullptr);
4585  return m_value.array->size();
4586  }
4587 
4588  case value_t::object:
4589  {
4590  assert(m_value.object != nullptr);
4591  return m_value.object->size();
4592  }
4593 
4594  default:
4595  {
4596  // all other types have size 1
4597  return 1;
4598  }
4599  }
4600  }
4601 
4638  size_type max_size() const noexcept
4639  {
4640  switch (m_type)
4641  {
4642  case value_t::array:
4643  {
4644  assert(m_value.array != nullptr);
4645  return m_value.array->max_size();
4646  }
4647 
4648  case value_t::object:
4649  {
4650  assert(m_value.object != nullptr);
4651  return m_value.object->max_size();
4652  }
4653 
4654  default:
4655  {
4656  // all other types have max_size() == size()
4657  return size();
4658  }
4659  }
4660  }
4661 
4663 
4664 
4666  // modifiers //
4668 
4671 
4697  void clear() noexcept
4698  {
4699  switch (m_type)
4700  {
4701  case value_t::number_integer:
4702  {
4703  m_value.number_integer = 0;
4704  break;
4705  }
4706 
4707  case value_t::number_unsigned:
4708  {
4709  m_value.number_unsigned = 0;
4710  break;
4711  }
4712 
4713  case value_t::number_float:
4714  {
4715  m_value.number_float = 0.0;
4716  break;
4717  }
4718 
4719  case value_t::boolean:
4720  {
4721  m_value.boolean = false;
4722  break;
4723  }
4724 
4725  case value_t::string:
4726  {
4727  assert(m_value.string != nullptr);
4728  m_value.string->clear();
4729  break;
4730  }
4731 
4732  case value_t::array:
4733  {
4734  assert(m_value.array != nullptr);
4735  m_value.array->clear();
4736  break;
4737  }
4738 
4739  case value_t::object:
4740  {
4741  assert(m_value.object != nullptr);
4742  m_value.object->clear();
4743  break;
4744  }
4745 
4746  default:
4747  {
4748  break;
4749  }
4750  }
4751  }
4752 
4773  void push_back(basic_json&& val)
4774  {
4775  // push_back only works for null objects or arrays
4776  if (not(is_null() or is_array()))
4777  {
4778  throw std::domain_error("cannot use push_back() with " + type_name());
4779  }
4780 
4781  // transform null object into an array
4782  if (is_null())
4783  {
4784  m_type = value_t::array;
4785  m_value = value_t::array;
4786  }
4787 
4788  // add element to array (move semantics)
4789  assert(m_value.array != nullptr);
4790  m_value.array->push_back(std::move(val));
4791  // invalidate object
4792  val.m_type = value_t::null;
4793  }
4794 
4799  reference operator+=(basic_json&& val)
4800  {
4801  push_back(std::move(val));
4802  return *this;
4803  }
4804 
4809  void push_back(const basic_json& val)
4810  {
4811  // push_back only works for null objects or arrays
4812  if (not(is_null() or is_array()))
4813  {
4814  throw std::domain_error("cannot use push_back() with " + type_name());
4815  }
4816 
4817  // transform null object into an array
4818  if (is_null())
4819  {
4820  m_type = value_t::array;
4821  m_value = value_t::array;
4822  }
4823 
4824  // add element to array
4825  assert(m_value.array != nullptr);
4826  m_value.array->push_back(val);
4827  }
4828 
4833  reference operator+=(const basic_json& val)
4834  {
4835  push_back(val);
4836  return *this;
4837  }
4838 
4859  void push_back(const typename object_t::value_type& val)
4860  {
4861  // push_back only works for null objects or objects
4862  if (not(is_null() or is_object()))
4863  {
4864  throw std::domain_error("cannot use push_back() with " + type_name());
4865  }
4866 
4867  // transform null object into an object
4868  if (is_null())
4869  {
4870  m_type = value_t::object;
4871  m_value = value_t::object;
4872  }
4873 
4874  // add element to array
4875  assert(m_value.object != nullptr);
4876  m_value.object->insert(val);
4877  }
4878 
4883  reference operator+=(const typename object_t::value_type& val)
4884  {
4885  push_back(val);
4886  return *this;
4887  }
4888 
4914  void push_back(std::initializer_list<basic_json> init)
4915  {
4916  if (is_object() and init.size() == 2 and init.begin()->is_string())
4917  {
4918  const string_t key = *init.begin();
4919  push_back(typename object_t::value_type(key, *(init.begin() + 1)));
4920  }
4921  else
4922  {
4923  push_back(basic_json(init));
4924  }
4925  }
4926 
4931  reference operator+=(std::initializer_list<basic_json> init)
4932  {
4933  push_back(init);
4934  return *this;
4935  }
4936 
4959  iterator insert(const_iterator pos, const basic_json& val)
4960  {
4961  // insert only works for arrays
4962  if (is_array())
4963  {
4964  // check if iterator pos fits to this JSON value
4965  if (pos.m_object != this)
4966  {
4967  throw std::domain_error("iterator does not fit current value");
4968  }
4969 
4970  // insert to array and return iterator
4971  iterator result(this);
4972  assert(m_value.array != nullptr);
4973  result.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator, val);
4974  return result;
4975  }
4976  else
4977  {
4978  throw std::domain_error("cannot use insert() with " + type_name());
4979  }
4980  }
4981 
4986  iterator insert(const_iterator pos, basic_json&& val)
4987  {
4988  return insert(pos, val);
4989  }
4990 
5015  iterator insert(const_iterator pos, size_type cnt, const basic_json& val)
5016  {
5017  // insert only works for arrays
5018  if (is_array())
5019  {
5020  // check if iterator pos fits to this JSON value
5021  if (pos.m_object != this)
5022  {
5023  throw std::domain_error("iterator does not fit current value");
5024  }
5025 
5026  // insert to array and return iterator
5027  iterator result(this);
5028  assert(m_value.array != nullptr);
5029  result.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator, cnt, val);
5030  return result;
5031  }
5032  else
5033  {
5034  throw std::domain_error("cannot use insert() with " + type_name());
5035  }
5036  }
5037 
5069  {
5070  // insert only works for arrays
5071  if (not is_array())
5072  {
5073  throw std::domain_error("cannot use insert() with " + type_name());
5074  }
5075 
5076  // check if iterator pos fits to this JSON value
5077  if (pos.m_object != this)
5078  {
5079  throw std::domain_error("iterator does not fit current value");
5080  }
5081 
5082  if (first.m_object != last.m_object)
5083  {
5084  throw std::domain_error("iterators do not fit");
5085  }
5086 
5087  if (first.m_object == this or last.m_object == this)
5088  {
5089  throw std::domain_error("passed iterators may not belong to container");
5090  }
5091 
5092  // insert to array and return iterator
5093  iterator result(this);
5094  assert(m_value.array != nullptr);
5095  result.m_it.array_iterator = m_value.array->insert(
5096  pos.m_it.array_iterator,
5097  first.m_it.array_iterator,
5098  last.m_it.array_iterator);
5099  return result;
5100  }
5101 
5126  iterator insert(const_iterator pos, std::initializer_list<basic_json> ilist)
5127  {
5128  // insert only works for arrays
5129  if (not is_array())
5130  {
5131  throw std::domain_error("cannot use insert() with " + type_name());
5132  }
5133 
5134  // check if iterator pos fits to this JSON value
5135  if (pos.m_object != this)
5136  {
5137  throw std::domain_error("iterator does not fit current value");
5138  }
5139 
5140  // insert to array and return iterator
5141  iterator result(this);
5142  assert(m_value.array != nullptr);
5143  result.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator, ilist);
5144  return result;
5145  }
5146 
5164  void swap(reference other) noexcept (
5165  std::is_nothrow_move_constructible<value_t>::value and
5166  std::is_nothrow_move_assignable<value_t>::value and
5167  std::is_nothrow_move_constructible<json_value>::value and
5168  std::is_nothrow_move_assignable<json_value>::value
5169  )
5170  {
5171  std::swap(m_type, other.m_type);
5172  std::swap(m_value, other.m_value);
5173  }
5174 
5195  void swap(array_t& other)
5196  {
5197  // swap only works for arrays
5198  if (is_array())
5199  {
5200  assert(m_value.array != nullptr);
5201  std::swap(*(m_value.array), other);
5202  }
5203  else
5204  {
5205  throw std::domain_error("cannot use swap() with " + type_name());
5206  }
5207  }
5208 
5229  void swap(object_t& other)
5230  {
5231  // swap only works for objects
5232  if (is_object())
5233  {
5234  assert(m_value.object != nullptr);
5235  std::swap(*(m_value.object), other);
5236  }
5237  else
5238  {
5239  throw std::domain_error("cannot use swap() with " + type_name());
5240  }
5241  }
5242 
5263  void swap(string_t& other)
5264  {
5265  // swap only works for strings
5266  if (is_string())
5267  {
5268  assert(m_value.string != nullptr);
5269  std::swap(*(m_value.string), other);
5270  }
5271  else
5272  {
5273  throw std::domain_error("cannot use swap() with " + type_name());
5274  }
5275  }
5276 
5278 
5279 
5281  // lexicographical comparison operators //
5283 
5286 
5287  private:
5297  friend bool operator<(const value_t lhs, const value_t rhs) noexcept
5298  {
5299  static constexpr std::array<uint8_t, 8> order = {{
5300  0, // null
5301  3, // object
5302  4, // array
5303  5, // string
5304  1, // boolean
5305  2, // integer
5306  2, // unsigned
5307  2, // float
5308  }
5309  };
5310 
5311  // discarded values are not comparable
5312  if (lhs == value_t::discarded or rhs == value_t::discarded)
5313  {
5314  return false;
5315  }
5316 
5317  return order[static_cast<std::size_t>(lhs)] < order[static_cast<std::size_t>(rhs)];
5318  }
5319 
5320  public:
5344  friend bool operator==(const_reference lhs, const_reference rhs) noexcept
5345  {
5346  const auto lhs_type = lhs.type();
5347  const auto rhs_type = rhs.type();
5348 
5349  if (lhs_type == rhs_type)
5350  {
5351  switch (lhs_type)
5352  {
5353  case value_t::array:
5354  {
5355  assert(lhs.m_value.array != nullptr);
5356  assert(rhs.m_value.array != nullptr);
5357  return *lhs.m_value.array == *rhs.m_value.array;
5358  }
5359  case value_t::object:
5360  {
5361  assert(lhs.m_value.object != nullptr);
5362  assert(rhs.m_value.object != nullptr);
5363  return *lhs.m_value.object == *rhs.m_value.object;
5364  }
5365  case value_t::null:
5366  {
5367  return true;
5368  }
5369  case value_t::string:
5370  {
5371  assert(lhs.m_value.string != nullptr);
5372  assert(rhs.m_value.string != nullptr);
5373  return *lhs.m_value.string == *rhs.m_value.string;
5374  }
5375  case value_t::boolean:
5376  {
5377  return lhs.m_value.boolean == rhs.m_value.boolean;
5378  }
5379  case value_t::number_integer:
5380  {
5381  return lhs.m_value.number_integer == rhs.m_value.number_integer;
5382  }
5383  case value_t::number_unsigned:
5384  {
5385  return lhs.m_value.number_unsigned == rhs.m_value.number_unsigned;
5386  }
5387  case value_t::number_float:
5388  {
5389  return lhs.m_value.number_float == rhs.m_value.number_float;
5390  }
5391  default:
5392  {
5393  return false;
5394  }
5395  }
5396  }
5397  else if (lhs_type == value_t::number_integer and rhs_type == value_t::number_float)
5398  {
5399  return static_cast<number_float_t>(lhs.m_value.number_integer) == rhs.m_value.number_float;
5400  }
5401  else if (lhs_type == value_t::number_float and rhs_type == value_t::number_integer)
5402  {
5403  return lhs.m_value.number_float == static_cast<number_float_t>(rhs.m_value.number_integer);
5404  }
5405  else if (lhs_type == value_t::number_unsigned and rhs_type == value_t::number_float)
5406  {
5407  return static_cast<number_float_t>(lhs.m_value.number_unsigned) == rhs.m_value.number_float;
5408  }
5409  else if (lhs_type == value_t::number_float and rhs_type == value_t::number_unsigned)
5410  {
5411  return lhs.m_value.number_float == static_cast<number_float_t>(rhs.m_value.number_unsigned);
5412  }
5413  else if (lhs_type == value_t::number_unsigned and rhs_type == value_t::number_integer)
5414  {
5415  return static_cast<number_integer_t>(lhs.m_value.number_unsigned) == rhs.m_value.number_integer;
5416  }
5417  else if (lhs_type == value_t::number_integer and rhs_type == value_t::number_unsigned)
5418  {
5419  return lhs.m_value.number_integer == static_cast<number_integer_t>(rhs.m_value.number_unsigned);
5420  }
5421 
5422  return false;
5423  }
5424 
5443  friend bool operator==(const_reference v, std::nullptr_t) noexcept
5444  {
5445  return v.is_null();
5446  }
5447 
5452  friend bool operator==(std::nullptr_t, const_reference v) noexcept
5453  {
5454  return v.is_null();
5455  }
5456 
5473  friend bool operator!=(const_reference lhs, const_reference rhs) noexcept
5474  {
5475  return not (lhs == rhs);
5476  }
5477 
5496  friend bool operator!=(const_reference v, std::nullptr_t) noexcept
5497  {
5498  return not v.is_null();
5499  }
5500 
5505  friend bool operator!=(std::nullptr_t, const_reference v) noexcept
5506  {
5507  return not v.is_null();
5508  }
5509 
5534  friend bool operator<(const_reference lhs, const_reference rhs) noexcept
5535  {
5536  const auto lhs_type = lhs.type();
5537  const auto rhs_type = rhs.type();
5538 
5539  if (lhs_type == rhs_type)
5540  {
5541  switch (lhs_type)
5542  {
5543  case value_t::array:
5544  {
5545  assert(lhs.m_value.array != nullptr);
5546  assert(rhs.m_value.array != nullptr);
5547  return *lhs.m_value.array < *rhs.m_value.array;
5548  }
5549  case value_t::object:
5550  {
5551  assert(lhs.m_value.object != nullptr);
5552  assert(rhs.m_value.object != nullptr);
5553  return *lhs.m_value.object < *rhs.m_value.object;
5554  }
5555  case value_t::null:
5556  {
5557  return false;
5558  }
5559  case value_t::string:
5560  {
5561  assert(lhs.m_value.string != nullptr);
5562  assert(rhs.m_value.string != nullptr);
5563  return *lhs.m_value.string < *rhs.m_value.string;
5564  }
5565  case value_t::boolean:
5566  {
5567  return lhs.m_value.boolean < rhs.m_value.boolean;
5568  }
5569  case value_t::number_integer:
5570  {
5571  return lhs.m_value.number_integer < rhs.m_value.number_integer;
5572  }
5573  case value_t::number_unsigned:
5574  {
5575  return lhs.m_value.number_unsigned < rhs.m_value.number_unsigned;
5576  }
5577  case value_t::number_float:
5578  {
5579  return lhs.m_value.number_float < rhs.m_value.number_float;
5580  }
5581  default:
5582  {
5583  return false;
5584  }
5585  }
5586  }
5587  else if (lhs_type == value_t::number_integer and rhs_type == value_t::number_float)
5588  {
5589  return static_cast<number_float_t>(lhs.m_value.number_integer) < rhs.m_value.number_float;
5590  }
5591  else if (lhs_type == value_t::number_float and rhs_type == value_t::number_integer)
5592  {
5593  return lhs.m_value.number_float < static_cast<number_float_t>(rhs.m_value.number_integer);
5594  }
5595  else if (lhs_type == value_t::number_unsigned and rhs_type == value_t::number_float)
5596  {
5597  return static_cast<number_float_t>(lhs.m_value.number_unsigned) < rhs.m_value.number_float;
5598  }
5599  else if (lhs_type == value_t::number_float and rhs_type == value_t::number_unsigned)
5600  {
5601  return lhs.m_value.number_float < static_cast<number_float_t>(rhs.m_value.number_unsigned);
5602  }
5603  else if (lhs_type == value_t::number_integer and rhs_type == value_t::number_unsigned)
5604  {
5605  return lhs.m_value.number_integer < static_cast<number_integer_t>(rhs.m_value.number_unsigned);
5606  }
5607  else if (lhs_type == value_t::number_unsigned and rhs_type == value_t::number_integer)
5608  {
5609  return static_cast<number_integer_t>(lhs.m_value.number_unsigned) < rhs.m_value.number_integer;
5610  }
5611 
5612  // We only reach this line if we cannot compare values. In that case,
5613  // we compare types. Note we have to call the operator explicitly,
5614  // because MSVC has problems otherwise.
5615  return operator<(lhs_type, rhs_type);
5616  }
5617 
5635  friend bool operator<=(const_reference lhs, const_reference rhs) noexcept
5636  {
5637  return not (rhs < lhs);
5638  }
5639 
5657  friend bool operator>(const_reference lhs, const_reference rhs) noexcept
5658  {
5659  return not (lhs <= rhs);
5660  }
5661 
5679  friend bool operator>=(const_reference lhs, const_reference rhs) noexcept
5680  {
5681  return not (lhs < rhs);
5682  }
5683 
5685 
5686 
5688  // serialization //
5690 
5693 
5716  friend std::ostream& operator<<(std::ostream& o, const basic_json& j)
5717  {
5718  // read width member and use it as indentation parameter if nonzero
5719  const bool pretty_print = (o.width() > 0);
5720  const auto indentation = (pretty_print ? o.width() : 0);
5721 
5722  // reset width to 0 for subsequent calls to this stream
5723  o.width(0);
5724 
5725  // do the actual serialization
5726  j.dump(o, pretty_print, static_cast<unsigned int>(indentation));
5727  return o;
5728  }
5729 
5734  friend std::ostream& operator>>(const basic_json& j, std::ostream& o)
5735  {
5736  return o << j;
5737  }
5738 
5740 
5741 
5743  // deserialization //
5745 
5748 
5773  static basic_json parse(const string_t& s, parser_callback_t cb = nullptr)
5774  {
5775  return parser(s, cb).parse();
5776  }
5777 
5802  static basic_json parse(std::istream& i, parser_callback_t cb = nullptr)
5803  {
5804  return parser(i, cb).parse();
5805  }
5806 
5810  static basic_json parse(std::istream&& i, parser_callback_t cb = nullptr)
5811  {
5812  return parser(i, cb).parse();
5813  }
5814 
5838  friend std::istream& operator<<(basic_json& j, std::istream& i)
5839  {
5840  j = parser(i).parse();
5841  return i;
5842  }
5843 
5848  friend std::istream& operator>>(std::istream& i, basic_json& j)
5849  {
5850  j = parser(i).parse();
5851  return i;
5852  }
5853 
5855 
5856 
5857  private:
5859  // convenience functions //
5861 
5863  string_t type_name() const noexcept
5864  {
5865  switch (m_type)
5866  {
5867  case value_t::null:
5868  return "null";
5869  case value_t::object:
5870  return "object";
5871  case value_t::array:
5872  return "array";
5873  case value_t::string:
5874  return "string";
5875  case value_t::boolean:
5876  return "boolean";
5877  case value_t::discarded:
5878  return "discarded";
5879  default:
5880  return "number";
5881  }
5882  }
5883 
5892  static std::size_t extra_space(const string_t& s) noexcept
5893  {
5894  std::size_t result = 0;
5895 
5896  for (const auto& c : s)
5897  {
5898  switch (c)
5899  {
5900  case '"':
5901  case '\\':
5902  case '\b':
5903  case '\f':
5904  case '\n':
5905  case '\r':
5906  case '\t':
5907  {
5908  // from c (1 byte) to \x (2 bytes)
5909  result += 1;
5910  break;
5911  }
5912 
5913  default:
5914  {
5915  if (c >= 0x00 and c <= 0x1f)
5916  {
5917  // from c (1 byte) to \uxxxx (6 bytes)
5918  result += 5;
5919  }
5920  break;
5921  }
5922  }
5923  }
5924 
5925  return result;
5926  }
5927 
5941  static string_t escape_string(const string_t& s)
5942  {
5943  const auto space = extra_space(s);
5944  if (space == 0)
5945  {
5946  return s;
5947  }
5948 
5949  // create a result string of necessary size
5950  string_t result(s.size() + space, '\\');
5951  std::size_t pos = 0;
5952 
5953  for (const auto& c : s)
5954  {
5955  switch (c)
5956  {
5957  // quotation mark (0x22)
5958  case '"':
5959  {
5960  result[pos + 1] = '"';
5961  pos += 2;
5962  break;
5963  }
5964 
5965  // reverse solidus (0x5c)
5966  case '\\':
5967  {
5968  // nothing to change
5969  pos += 2;
5970  break;
5971  }
5972 
5973  // backspace (0x08)
5974  case '\b':
5975  {
5976  result[pos + 1] = 'b';
5977  pos += 2;
5978  break;
5979  }
5980 
5981  // formfeed (0x0c)
5982  case '\f':
5983  {
5984  result[pos + 1] = 'f';
5985  pos += 2;
5986  break;
5987  }
5988 
5989  // newline (0x0a)
5990  case '\n':
5991  {
5992  result[pos + 1] = 'n';
5993  pos += 2;
5994  break;
5995  }
5996 
5997  // carriage return (0x0d)
5998  case '\r':
5999  {
6000  result[pos + 1] = 'r';
6001  pos += 2;
6002  break;
6003  }
6004 
6005  // horizontal tab (0x09)
6006  case '\t':
6007  {
6008  result[pos + 1] = 't';
6009  pos += 2;
6010  break;
6011  }
6012 
6013  default:
6014  {
6015  if (c >= 0x00 and c <= 0x1f)
6016  {
6017  // convert a number 0..15 to its hex representation
6018  // (0..f)
6019  const auto hexify = [](const int v) -> char
6020  {
6021  return (v < 10)
6022  ? ('0' + static_cast<char>(v))
6023  : ('a' + static_cast<char>((v - 10) & 0x1f));
6024  };
6025 
6026  // print character c as \uxxxx
6027  for (const char m :
6028  { 'u', '0', '0', hexify(c >> 4), hexify(c & 0x0f)
6029  })
6030  {
6031  result[++pos] = m;
6032  }
6033 
6034  ++pos;
6035  }
6036  else
6037  {
6038  // all other characters are added as-is
6039  result[pos++] = c;
6040  }
6041  break;
6042  }
6043  }
6044  }
6045 
6046  return result;
6047  }
6048 
6066  void dump(std::ostream& o,
6067  const bool pretty_print,
6068  const unsigned int indent_step,
6069  const unsigned int current_indent = 0) const
6070  {
6071  // variable to hold indentation for recursive calls
6072  unsigned int new_indent = current_indent;
6073 
6074  switch (m_type)
6075  {
6076  case value_t::object:
6077  {
6078  assert(m_value.object != nullptr);
6079 
6080  if (m_value.object->empty())
6081  {
6082  o << "{}";
6083  return;
6084  }
6085 
6086  o << "{";
6087 
6088  // increase indentation
6089  if (pretty_print)
6090  {
6091  new_indent += indent_step;
6092  o << "\n";
6093  }
6094 
6095  for (auto i = m_value.object->cbegin(); i != m_value.object->cend(); ++i)
6096  {
6097  if (i != m_value.object->cbegin())
6098  {
6099  o << (pretty_print ? ",\n" : ",");
6100  }
6101  o << string_t(new_indent, ' ') << "\""
6102  << escape_string(i->first) << "\":"
6103  << (pretty_print ? " " : "");
6104  i->second.dump(o, pretty_print, indent_step, new_indent);
6105  }
6106 
6107  // decrease indentation
6108  if (pretty_print)
6109  {
6110  new_indent -= indent_step;
6111  o << "\n";
6112  }
6113 
6114  o << string_t(new_indent, ' ') + "}";
6115  return;
6116  }
6117 
6118  case value_t::array:
6119  {
6120  assert(m_value.array != nullptr);
6121 
6122  if (m_value.array->empty())
6123  {
6124  o << "[]";
6125  return;
6126  }
6127 
6128  o << "[";
6129 
6130  // increase indentation
6131  if (pretty_print)
6132  {
6133  new_indent += indent_step;
6134  o << "\n";
6135  }
6136 
6137  for (auto i = m_value.array->cbegin(); i != m_value.array->cend(); ++i)
6138  {
6139  if (i != m_value.array->cbegin())
6140  {
6141  o << (pretty_print ? ",\n" : ",");
6142  }
6143  o << string_t(new_indent, ' ');
6144  i->dump(o, pretty_print, indent_step, new_indent);
6145  }
6146 
6147  // decrease indentation
6148  if (pretty_print)
6149  {
6150  new_indent -= indent_step;
6151  o << "\n";
6152  }
6153 
6154  o << string_t(new_indent, ' ') << "]";
6155  return;
6156  }
6157 
6158  case value_t::string:
6159  {
6160  assert(m_value.string != nullptr);
6161  o << string_t("\"") << escape_string(*m_value.string) << "\"";
6162  return;
6163  }
6164 
6165  case value_t::boolean:
6166  {
6167  o << (m_value.boolean ? "true" : "false");
6168  return;
6169  }
6170 
6171  case value_t::number_integer:
6172  {
6173  o << m_value.number_integer;
6174  return;
6175  }
6176 
6177  case value_t::number_unsigned:
6178  {
6179  o << m_value.number_unsigned;
6180  return;
6181  }
6182 
6183  case value_t::number_float:
6184  {
6185  // check if number was parsed from a string
6186  if (m_type.bits.parsed)
6187  {
6188  // check if parsed number had an exponent given
6189  if (m_type.bits.has_exp)
6190  {
6191  // buffer size: precision (2^8-1 = 255) + other ('-.e-xxx' = 7) + null (1)
6192  char buf[263];
6193  int len;
6194 
6195  // handle capitalization of the exponent
6196  if (m_type.bits.exp_cap)
6197  {
6198  len = snprintf(buf, sizeof(buf), "%.*E",
6199  m_type.bits.precision, m_value.number_float) + 1;
6200  }
6201  else
6202  {
6203  len = snprintf(buf, sizeof(buf), "%.*e",
6204  m_type.bits.precision, m_value.number_float) + 1;
6205  }
6206 
6207  // remove '+' sign from the exponent if necessary
6208  if (not m_type.bits.exp_plus)
6209  {
6210  if (len > static_cast<int>(sizeof(buf)))
6211  {
6212  len = sizeof(buf);
6213  }
6214  for (int i = 0; i < len; i++)
6215  {
6216  if (buf[i] == '+')
6217  {
6218  for (; i + 1 < len; i++)
6219  {
6220  buf[i] = buf[i + 1];
6221  }
6222  }
6223  }
6224  }
6225 
6226  o << buf;
6227  }
6228  else
6229  {
6230  // no exponent - output as a decimal
6231  std::stringstream ss;
6232  ss.imbue(std::locale(std::locale(), new DecimalSeparator)); // fix locale problems
6233  ss << std::setprecision(m_type.bits.precision)
6234  << std::fixed << m_value.number_float;
6235  o << ss.str();
6236  }
6237  }
6238  else
6239  {
6240  if (m_value.number_float == 0)
6241  {
6242  // special case for zero to get "0.0"/"-0.0"
6243  o << (std::signbit(m_value.number_float) ? "-0.0" : "0.0");
6244  }
6245  else
6246  {
6247  // Otherwise 6, 15 or 16 digits of precision allows
6248  // round-trip IEEE 754 string->float->string,
6249  // string->double->string or string->long
6250  // double->string; to be safe, we read this value from
6251  // std::numeric_limits<number_float_t>::digits10
6252  std::stringstream ss;
6253  ss.imbue(std::locale(std::locale(), new DecimalSeparator)); // fix locale problems
6254  ss << std::setprecision(std::numeric_limits<double>::digits10)
6255  << m_value.number_float;
6256  o << ss.str();
6257  }
6258  }
6259  return;
6260  }
6261 
6262  case value_t::discarded:
6263  {
6264  o << "<discarded>";
6265  return;
6266  }
6267 
6268  case value_t::null:
6269  {
6270  o << "null";
6271  return;
6272  }
6273  }
6274  }
6275 
6276  private:
6278  // member variables //
6280 
6282  type_data_t m_type = value_t::null;
6283 
6285  json_value m_value = {};
6286 
6287 
6288  private:
6290  // iterators //
6292 
6302  class primitive_iterator_t
6303  {
6304  public:
6306  void set_begin() noexcept
6307  {
6308  m_it = begin_value;
6309  }
6310 
6312  void set_end() noexcept
6313  {
6314  m_it = end_value;
6315  }
6316 
6318  constexpr bool is_begin() const noexcept
6319  {
6320  return (m_it == begin_value);
6321  }
6322 
6324  constexpr bool is_end() const noexcept
6325  {
6326  return (m_it == end_value);
6327  }
6328 
6330  operator difference_type& () noexcept
6331  {
6332  return m_it;
6333  }
6334 
6336  constexpr operator difference_type () const noexcept
6337  {
6338  return m_it;
6339  }
6340 
6341  private:
6342  static constexpr difference_type begin_value = 0;
6343  static constexpr difference_type end_value = begin_value + 1;
6344 
6346  difference_type m_it = std::numeric_limits<std::ptrdiff_t>::denorm_min();
6347  };
6348 
6356  struct internal_iterator
6357  {
6359  typename object_t::iterator object_iterator;
6361  typename array_t::iterator array_iterator;
6363  primitive_iterator_t primitive_iterator;
6364 
6366  internal_iterator() noexcept
6367  : object_iterator(), array_iterator(), primitive_iterator()
6368  {}
6369  };
6370 
6372  template<typename IteratorType>
6373  class iteration_proxy
6374  {
6375  private:
6377  class iteration_proxy_internal
6378  {
6379  private:
6381  IteratorType anchor;
6383  size_t array_index = 0;
6384 
6385  public:
6386  explicit iteration_proxy_internal(IteratorType it) noexcept
6387  : anchor(it)
6388  {}
6389 
6391  iteration_proxy_internal& operator*()
6392  {
6393  return *this;
6394  }
6395 
6397  iteration_proxy_internal& operator++()
6398  {
6399  ++anchor;
6400  ++array_index;
6401 
6402  return *this;
6403  }
6404 
6406  bool operator!= (const iteration_proxy_internal& o) const
6407  {
6408  return anchor != o.anchor;
6409  }
6410 
6412  typename basic_json::string_t key() const
6413  {
6414  assert(anchor.m_object != nullptr);
6415 
6416  switch (anchor.m_object->type())
6417  {
6418  // use integer array index as key
6419  case value_t::array:
6420  {
6421  return std::to_string(array_index);
6422  }
6423 
6424  // use key from the object
6425  case value_t::object:
6426  {
6427  return anchor.key();
6428  }
6429 
6430  // use an empty key for all primitive types
6431  default:
6432  {
6433  return "";
6434  }
6435  }
6436  }
6437 
6439  typename IteratorType::reference value() const
6440  {
6441  return anchor.value();
6442  }
6443  };
6444 
6446  typename IteratorType::reference container;
6447 
6448  public:
6450  explicit iteration_proxy(typename IteratorType::reference cont)
6451  : container(cont)
6452  {}
6453 
6455  iteration_proxy_internal begin() noexcept
6456  {
6457  return iteration_proxy_internal(container.begin());
6458  }
6459 
6461  iteration_proxy_internal end() noexcept
6462  {
6463  return iteration_proxy_internal(container.end());
6464  }
6465  };
6466 
6467  public:
6481  class const_iterator : public std::iterator<std::random_access_iterator_tag, const basic_json>
6482  {
6484  friend class basic_json;
6485 
6486  public:
6496  using iterator_category = std::bidirectional_iterator_tag;
6497 
6499  const_iterator() = default;
6500 
6502  explicit const_iterator(pointer object) noexcept
6503  : m_object(object)
6504  {
6505  assert(m_object != nullptr);
6506 
6507  switch (m_object->m_type)
6508  {
6510  {
6511  m_it.object_iterator = typename object_t::iterator();
6512  break;
6513  }
6514 
6516  {
6517  m_it.array_iterator = typename array_t::iterator();
6518  break;
6519  }
6520 
6521  default:
6522  {
6523  m_it.primitive_iterator = primitive_iterator_t();
6524  break;
6525  }
6526  }
6527  }
6528 
6530  explicit const_iterator(const iterator& other) noexcept
6531  : m_object(other.m_object)
6532  {
6533  assert(m_object != nullptr);
6534 
6535  switch (m_object->m_type)
6536  {
6538  {
6539  m_it.object_iterator = other.m_it.object_iterator;
6540  break;
6541  }
6542 
6544  {
6545  m_it.array_iterator = other.m_it.array_iterator;
6546  break;
6547  }
6548 
6549  default:
6550  {
6551  m_it.primitive_iterator = other.m_it.primitive_iterator;
6552  break;
6553  }
6554  }
6555  }
6556 
6558  const_iterator(const const_iterator& other) noexcept
6559  : m_object(other.m_object), m_it(other.m_it)
6560  {}
6561 
6564  std::is_nothrow_move_constructible<pointer>::value and
6565  std::is_nothrow_move_assignable<pointer>::value and
6566  std::is_nothrow_move_constructible<internal_iterator>::value and
6567  std::is_nothrow_move_assignable<internal_iterator>::value
6568  )
6569  {
6570  std::swap(m_object, other.m_object);
6571  std::swap(m_it, other.m_it);
6572  return *this;
6573  }
6574 
6575  private:
6577  void set_begin() noexcept
6578  {
6579  assert(m_object != nullptr);
6580 
6581  switch (m_object->m_type)
6582  {
6584  {
6585  assert(m_object->m_value.object != nullptr);
6586  m_it.object_iterator = m_object->m_value.object->begin();
6587  break;
6588  }
6589 
6591  {
6592  assert(m_object->m_value.array != nullptr);
6593  m_it.array_iterator = m_object->m_value.array->begin();
6594  break;
6595  }
6596 
6598  {
6599  // set to end so begin()==end() is true: null is empty
6600  m_it.primitive_iterator.set_end();
6601  break;
6602  }
6603 
6604  default:
6605  {
6606  m_it.primitive_iterator.set_begin();
6607  break;
6608  }
6609  }
6610  }
6611 
6613  void set_end() noexcept
6614  {
6615  assert(m_object != nullptr);
6616 
6617  switch (m_object->m_type)
6618  {
6620  {
6621  assert(m_object->m_value.object != nullptr);
6622  m_it.object_iterator = m_object->m_value.object->end();
6623  break;
6624  }
6625 
6627  {
6628  assert(m_object->m_value.array != nullptr);
6629  m_it.array_iterator = m_object->m_value.array->end();
6630  break;
6631  }
6632 
6633  default:
6634  {
6635  m_it.primitive_iterator.set_end();
6636  break;
6637  }
6638  }
6639  }
6640 
6641  public:
6644  {
6645  assert(m_object != nullptr);
6646 
6647  switch (m_object->m_type)
6648  {
6650  {
6651  assert(m_object->m_value.object);
6652  assert(m_it.object_iterator != m_object->m_value.object->end());
6653  return m_it.object_iterator->second;
6654  }
6655 
6657  {
6658  assert(m_object->m_value.array);
6659  assert(m_it.array_iterator != m_object->m_value.array->end());
6660  return *m_it.array_iterator;
6661  }
6662 
6664  {
6665  throw std::out_of_range("cannot get value");
6666  }
6667 
6668  default:
6669  {
6670  if (m_it.primitive_iterator.is_begin())
6671  {
6672  return *m_object;
6673  }
6674  else
6675  {
6676  throw std::out_of_range("cannot get value");
6677  }
6678  }
6679  }
6680  }
6681 
6684  {
6685  assert(m_object != nullptr);
6686 
6687  switch (m_object->m_type)
6688  {
6690  {
6691  assert(m_object->m_value.object);
6692  assert(m_it.object_iterator != m_object->m_value.object->end());
6693  return &(m_it.object_iterator->second);
6694  }
6695 
6697  {
6698  assert(m_object->m_value.array);
6699  assert(m_it.array_iterator != m_object->m_value.array->end());
6700  return &*m_it.array_iterator;
6701  }
6702 
6703  default:
6704  {
6705  if (m_it.primitive_iterator.is_begin())
6706  {
6707  return m_object;
6708  }
6709  else
6710  {
6711  throw std::out_of_range("cannot get value");
6712  }
6713  }
6714  }
6715  }
6716 
6719  {
6720  auto result = *this;
6721  ++(*this);
6722  return result;
6723  }
6724 
6727  {
6728  assert(m_object != nullptr);
6729 
6730  switch (m_object->m_type)
6731  {
6733  {
6734  ++m_it.object_iterator;
6735  break;
6736  }
6737 
6739  {
6740  ++m_it.array_iterator;
6741  break;
6742  }
6743 
6744  default:
6745  {
6746  ++m_it.primitive_iterator;
6747  break;
6748  }
6749  }
6750 
6751  return *this;
6752  }
6753 
6756  {
6757  auto result = *this;
6758  --(*this);
6759  return result;
6760  }
6761 
6764  {
6765  assert(m_object != nullptr);
6766 
6767  switch (m_object->m_type)
6768  {
6770  {
6771  --m_it.object_iterator;
6772  break;
6773  }
6774 
6776  {
6777  --m_it.array_iterator;
6778  break;
6779  }
6780 
6781  default:
6782  {
6783  --m_it.primitive_iterator;
6784  break;
6785  }
6786  }
6787 
6788  return *this;
6789  }
6790 
6792  bool operator==(const const_iterator& other) const
6793  {
6794  // if objects are not the same, the comparison is undefined
6795  if (m_object != other.m_object)
6796  {
6797  throw std::domain_error("cannot compare iterators of different containers");
6798  }
6799 
6800  assert(m_object != nullptr);
6801 
6802  switch (m_object->m_type)
6803  {
6805  {
6806  return (m_it.object_iterator == other.m_it.object_iterator);
6807  }
6808 
6810  {
6811  return (m_it.array_iterator == other.m_it.array_iterator);
6812  }
6813 
6814  default:
6815  {
6816  return (m_it.primitive_iterator == other.m_it.primitive_iterator);
6817  }
6818  }
6819  }
6820 
6822  bool operator!=(const const_iterator& other) const
6823  {
6824  return not operator==(other);
6825  }
6826 
6828  bool operator<(const const_iterator& other) const
6829  {
6830  // if objects are not the same, the comparison is undefined
6831  if (m_object != other.m_object)
6832  {
6833  throw std::domain_error("cannot compare iterators of different containers");
6834  }
6835 
6836  assert(m_object != nullptr);
6837 
6838  switch (m_object->m_type)
6839  {
6841  {
6842  throw std::domain_error("cannot compare order of object iterators");
6843  }
6844 
6846  {
6847  return (m_it.array_iterator < other.m_it.array_iterator);
6848  }
6849 
6850  default:
6851  {
6852  return (m_it.primitive_iterator < other.m_it.primitive_iterator);
6853  }
6854  }
6855  }
6856 
6858  bool operator<=(const const_iterator& other) const
6859  {
6860  return not other.operator < (*this);
6861  }
6862 
6864  bool operator>(const const_iterator& other) const
6865  {
6866  return not operator<=(other);
6867  }
6868 
6870  bool operator>=(const const_iterator& other) const
6871  {
6872  return not operator<(other);
6873  }
6874 
6877  {
6878  assert(m_object != nullptr);
6879 
6880  switch (m_object->m_type)
6881  {
6883  {
6884  throw std::domain_error("cannot use offsets with object iterators");
6885  }
6886 
6888  {
6889  m_it.array_iterator += i;
6890  break;
6891  }
6892 
6893  default:
6894  {
6895  m_it.primitive_iterator += i;
6896  break;
6897  }
6898  }
6899 
6900  return *this;
6901  }
6902 
6905  {
6906  return operator+=(-i);
6907  }
6908 
6911  {
6912  auto result = *this;
6913  result += i;
6914  return result;
6915  }
6916 
6919  {
6920  auto result = *this;
6921  result -= i;
6922  return result;
6923  }
6924 
6927  {
6928  assert(m_object != nullptr);
6929 
6930  switch (m_object->m_type)
6931  {
6933  {
6934  throw std::domain_error("cannot use offsets with object iterators");
6935  }
6936 
6938  {
6939  return m_it.array_iterator - other.m_it.array_iterator;
6940  }
6941 
6942  default:
6943  {
6944  return m_it.primitive_iterator - other.m_it.primitive_iterator;
6945  }
6946  }
6947  }
6948 
6951  {
6952  assert(m_object != nullptr);
6953 
6954  switch (m_object->m_type)
6955  {
6957  {
6958  throw std::domain_error("cannot use operator[] for object iterators");
6959  }
6960 
6962  {
6963  return *(m_it.array_iterator + n);
6964  }
6965 
6967  {
6968  throw std::out_of_range("cannot get value");
6969  }
6970 
6971  default:
6972  {
6973  if (m_it.primitive_iterator == -n)
6974  {
6975  return *m_object;
6976  }
6977  else
6978  {
6979  throw std::out_of_range("cannot get value");
6980  }
6981  }
6982  }
6983  }
6984 
6986  typename object_t::key_type key() const
6987  {
6988  assert(m_object != nullptr);
6989 
6990  if (m_object->is_object())
6991  {
6992  return m_it.object_iterator->first;
6993  }
6994  else
6995  {
6996  throw std::domain_error("cannot use key() for non-object iterators");
6997  }
6998  }
6999 
7002  {
7003  return operator*();
7004  }
7005 
7006  private:
7008  pointer m_object = nullptr;
7010  internal_iterator m_it = internal_iterator();
7011  };
7012 
7025  class iterator : public const_iterator
7026  {
7027  public:
7029  using pointer = typename basic_json::pointer;
7031 
7033  iterator() = default;
7034 
7036  explicit iterator(pointer object) noexcept
7037  : base_iterator(object)
7038  {}
7039 
7041  iterator(const iterator& other) noexcept
7042  : base_iterator(other)
7043  {}
7044 
7046  iterator& operator=(iterator other) noexcept(
7047  std::is_nothrow_move_constructible<pointer>::value and
7048  std::is_nothrow_move_assignable<pointer>::value and
7049  std::is_nothrow_move_constructible<internal_iterator>::value and
7050  std::is_nothrow_move_assignable<internal_iterator>::value
7051  )
7052  {
7053  base_iterator::operator=(other);
7054  return *this;
7055  }
7056 
7059  {
7060  return const_cast<reference>(base_iterator::operator*());
7061  }
7062 
7065  {
7066  return const_cast<pointer>(base_iterator::operator->());
7067  }
7068 
7071  {
7072  iterator result = *this;
7073  base_iterator::operator++();
7074  return result;
7075  }
7076 
7079  {
7080  base_iterator::operator++();
7081  return *this;
7082  }
7083 
7086  {
7087  iterator result = *this;
7088  base_iterator::operator--();
7089  return result;
7090  }
7091 
7094  {
7095  base_iterator::operator--();
7096  return *this;
7097  }
7098 
7101  {
7102  base_iterator::operator+=(i);
7103  return *this;
7104  }
7105 
7108  {
7109  base_iterator::operator-=(i);
7110  return *this;
7111  }
7112 
7115  {
7116  auto result = *this;
7117  result += i;
7118  return result;
7119  }
7120 
7123  {
7124  auto result = *this;
7125  result -= i;
7126  return result;
7127  }
7128 
7130  difference_type operator-(const iterator& other) const
7131  {
7132  return base_iterator::operator-(other);
7133  }
7134 
7137  {
7138  return const_cast<reference>(base_iterator::operator[](n));
7139  }
7140 
7143  {
7144  return const_cast<reference>(base_iterator::value());
7145  }
7146  };
7147 
7165  template<typename Base>
7166  class json_reverse_iterator : public std::reverse_iterator<Base>
7167  {
7168  public:
7170  using base_iterator = std::reverse_iterator<Base>;
7172  using reference = typename Base::reference;
7173 
7175  json_reverse_iterator(const typename base_iterator::iterator_type& it) noexcept
7176  : base_iterator(it)
7177  {}
7178 
7181  : base_iterator(it)
7182  {}
7183 
7186  {
7187  return base_iterator::operator++(1);
7188  }
7189 
7192  {
7193  base_iterator::operator++();
7194  return *this;
7195  }
7196 
7199  {
7200  return base_iterator::operator--(1);
7201  }
7202 
7205  {
7206  base_iterator::operator--();
7207  return *this;
7208  }
7209 
7212  {
7213  base_iterator::operator+=(i);
7214  return *this;
7215  }
7216 
7219  {
7220  auto result = *this;
7221  result += i;
7222  return result;
7223  }
7224 
7227  {
7228  auto result = *this;
7229  result -= i;
7230  return result;
7231  }
7232 
7235  {
7236  return this->base() - other.base();
7237  }
7238 
7241  {
7242  return *(this->operator+(n));
7243  }
7244 
7246  typename object_t::key_type key() const
7247  {
7248  auto it = --this->base();
7249  return it.key();
7250  }
7251 
7254  {
7255  auto it = --this->base();
7256  return it.operator * ();
7257  }
7258  };
7259 
7260 
7261  private:
7263  // lexer and parser //
7265 
7273  class lexer
7274  {
7275  public:
7277  enum class token_type
7278  {
7279  uninitialized,
7280  literal_true,
7281  literal_false,
7282  literal_null,
7283  value_string,
7284  value_number,
7285  begin_array,
7286  begin_object,
7287  end_array,
7288  end_object,
7289  name_separator,
7290  value_separator,
7291  parse_error,
7292  end_of_input
7293  };
7294 
7296  using lexer_char_t = unsigned char;
7297 
7299  explicit lexer(const string_t& s) noexcept
7300  : m_stream(nullptr), m_buffer(s)
7301  {
7302  m_content = reinterpret_cast<const lexer_char_t*>(s.c_str());
7303  assert(m_content != nullptr);
7304  m_start = m_cursor = m_content;
7305  m_limit = m_content + s.size();
7306  }
7307 
7309  explicit lexer(std::istream* s) noexcept
7310  : m_stream(s), m_buffer()
7311  {
7312  assert(m_stream != nullptr);
7313  getline(*m_stream, m_buffer);
7314  m_content = reinterpret_cast<const lexer_char_t*>(m_buffer.c_str());
7315  assert(m_content != nullptr);
7316  m_start = m_cursor = m_content;
7317  m_limit = m_content + m_buffer.size();
7318  }
7319 
7321  lexer() = default;
7322 
7323  // switch off unwanted functions
7324  lexer(const lexer&) = delete;
7325  lexer operator=(const lexer&) = delete;
7326 
7342  static string_t to_unicode(const std::size_t codepoint1,
7343  const std::size_t codepoint2 = 0)
7344  {
7345  // calculate the codepoint from the given code points
7346  std::size_t codepoint = codepoint1;
7347 
7348  // check if codepoint1 is a high surrogate
7349  if (codepoint1 >= 0xD800 and codepoint1 <= 0xDBFF)
7350  {
7351  // check if codepoint2 is a low surrogate
7352  if (codepoint2 >= 0xDC00 and codepoint2 <= 0xDFFF)
7353  {
7354  codepoint =
7355  // high surrogate occupies the most significant 22 bits
7356  (codepoint1 << 10)
7357  // low surrogate occupies the least significant 15 bits
7358  + codepoint2
7359  // there is still the 0xD800, 0xDC00 and 0x10000 noise
7360  // in the result so we have to subtract with:
7361  // (0xD800 << 10) + DC00 - 0x10000 = 0x35FDC00
7362  - 0x35FDC00;
7363  }
7364  else
7365  {
7366  throw std::invalid_argument("missing or wrong low surrogate");
7367  }
7368  }
7369 
7370  string_t result;
7371 
7372  if (codepoint < 0x80)
7373  {
7374  // 1-byte characters: 0xxxxxxx (ASCII)
7375  result.append(1, static_cast<typename string_t::value_type>(codepoint));
7376  }
7377  else if (codepoint <= 0x7ff)
7378  {
7379  // 2-byte characters: 110xxxxx 10xxxxxx
7380  result.append(1, static_cast<typename string_t::value_type>(0xC0 | ((codepoint >> 6) & 0x1F)));
7381  result.append(1, static_cast<typename string_t::value_type>(0x80 | (codepoint & 0x3F)));
7382  }
7383  else if (codepoint <= 0xffff)
7384  {
7385  // 3-byte characters: 1110xxxx 10xxxxxx 10xxxxxx
7386  result.append(1, static_cast<typename string_t::value_type>(0xE0 | ((codepoint >> 12) & 0x0F)));
7387  result.append(1, static_cast<typename string_t::value_type>(0x80 | ((codepoint >> 6) & 0x3F)));
7388  result.append(1, static_cast<typename string_t::value_type>(0x80 | (codepoint & 0x3F)));
7389  }
7390  else if (codepoint <= 0x10ffff)
7391  {
7392  // 4-byte characters: 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
7393  result.append(1, static_cast<typename string_t::value_type>(0xF0 | ((codepoint >> 18) & 0x07)));
7394  result.append(1, static_cast<typename string_t::value_type>(0x80 | ((codepoint >> 12) & 0x3F)));
7395  result.append(1, static_cast<typename string_t::value_type>(0x80 | ((codepoint >> 6) & 0x3F)));
7396  result.append(1, static_cast<typename string_t::value_type>(0x80 | (codepoint & 0x3F)));
7397  }
7398  else
7399  {
7400  throw std::out_of_range("code points above 0x10FFFF are invalid");
7401  }
7402 
7403  return result;
7404  }
7405 
7407  static std::string token_type_name(token_type t)
7408  {
7409  switch (t)
7410  {
7411  case token_type::uninitialized:
7412  return "<uninitialized>";
7413  case token_type::literal_true:
7414  return "true literal";
7415  case token_type::literal_false:
7416  return "false literal";
7417  case token_type::literal_null:
7418  return "null literal";
7419  case token_type::value_string:
7420  return "string literal";
7421  case token_type::value_number:
7422  return "number literal";
7423  case token_type::begin_array:
7424  return "'['";
7425  case token_type::begin_object:
7426  return "'{'";
7427  case token_type::end_array:
7428  return "']'";
7429  case token_type::end_object:
7430  return "'}'";
7431  case token_type::name_separator:
7432  return "':'";
7433  case token_type::value_separator:
7434  return "','";
7435  case token_type::parse_error:
7436  return "<parse error>";
7437  case token_type::end_of_input:
7438  return "end of input";
7439  default:
7440  {
7441  // catch non-enum values
7442  return "unknown token"; // LCOV_EXCL_LINE
7443  }
7444  }
7445  }
7446 
7457  token_type scan() noexcept
7458  {
7459  // pointer for backtracking information
7460  m_marker = nullptr;
7461 
7462  // remember the begin of the token
7463  m_start = m_cursor;
7464  assert(m_start != nullptr);
7465 
7466 
7467  {
7468  lexer_char_t yych;
7469  unsigned int yyaccept = 0;
7470  static const unsigned char yybm[] =
7471  {
7472  0, 0, 0, 0, 0, 0, 0, 0,
7473  0, 32, 32, 0, 0, 32, 0, 0,
7474  128, 128, 128, 128, 128, 128, 128, 128,
7475  128, 128, 128, 128, 128, 128, 128, 128,
7476  160, 128, 0, 128, 128, 128, 128, 128,
7477  128, 128, 128, 128, 128, 128, 128, 128,
7478  192, 192, 192, 192, 192, 192, 192, 192,
7479  192, 192, 128, 128, 128, 128, 128, 128,
7480  128, 128, 128, 128, 128, 128, 128, 128,
7481  128, 128, 128, 128, 128, 128, 128, 128,
7482  128, 128, 128, 128, 128, 128, 128, 128,
7483  128, 128, 128, 128, 0, 128, 128, 128,
7484  128, 128, 128, 128, 128, 128, 128, 128,
7485  128, 128, 128, 128, 128, 128, 128, 128,
7486  128, 128, 128, 128, 128, 128, 128, 128,
7487  128, 128, 128, 128, 128, 128, 128, 128,
7488  128, 128, 128, 128, 128, 128, 128, 128,
7489  128, 128, 128, 128, 128, 128, 128, 128,
7490  128, 128, 128, 128, 128, 128, 128, 128,
7491  128, 128, 128, 128, 128, 128, 128, 128,
7492  128, 128, 128, 128, 128, 128, 128, 128,
7493  128, 128, 128, 128, 128, 128, 128, 128,
7494  128, 128, 128, 128, 128, 128, 128, 128,
7495  128, 128, 128, 128, 128, 128, 128, 128,
7496  128, 128, 128, 128, 128, 128, 128, 128,
7497  128, 128, 128, 128, 128, 128, 128, 128,
7498  128, 128, 128, 128, 128, 128, 128, 128,
7499  128, 128, 128, 128, 128, 128, 128, 128,
7500  128, 128, 128, 128, 128, 128, 128, 128,
7501  128, 128, 128, 128, 128, 128, 128, 128,
7502  128, 128, 128, 128, 128, 128, 128, 128,
7503  128, 128, 128, 128, 128, 128, 128, 128,
7504  };
7505  if ((m_limit - m_cursor) < 5)
7506  {
7507  yyfill(); // LCOV_EXCL_LINE;
7508  }
7509  yych = *m_cursor;
7510  if (yybm[0 + yych] & 32)
7511  {
7512  goto basic_json_parser_6;
7513  }
7514  if (yych <= '\\')
7515  {
7516  if (yych <= '-')
7517  {
7518  if (yych <= '"')
7519  {
7520  if (yych <= 0x00)
7521  {
7522  goto basic_json_parser_2;
7523  }
7524  if (yych <= '!')
7525  {
7526  goto basic_json_parser_4;
7527  }
7528  goto basic_json_parser_9;
7529  }
7530  else
7531  {
7532  if (yych <= '+')
7533  {
7534  goto basic_json_parser_4;
7535  }
7536  if (yych <= ',')
7537  {
7538  goto basic_json_parser_10;
7539  }
7540  goto basic_json_parser_12;
7541  }
7542  }
7543  else
7544  {
7545  if (yych <= '9')
7546  {
7547  if (yych <= '/')
7548  {
7549  goto basic_json_parser_4;
7550  }
7551  if (yych <= '0')
7552  {
7553  goto basic_json_parser_13;
7554  }
7555  goto basic_json_parser_15;
7556  }
7557  else
7558  {
7559  if (yych <= ':')
7560  {
7561  goto basic_json_parser_17;
7562  }
7563  if (yych == '[')
7564  {
7565  goto basic_json_parser_19;
7566  }
7567  goto basic_json_parser_4;
7568  }
7569  }
7570  }
7571  else
7572  {
7573  if (yych <= 't')
7574  {
7575  if (yych <= 'f')
7576  {
7577  if (yych <= ']')
7578  {
7579  goto basic_json_parser_21;
7580  }
7581  if (yych <= 'e')
7582  {
7583  goto basic_json_parser_4;
7584  }
7585  goto basic_json_parser_23;
7586  }
7587  else
7588  {
7589  if (yych == 'n')
7590  {
7591  goto basic_json_parser_24;
7592  }
7593  if (yych <= 's')
7594  {
7595  goto basic_json_parser_4;
7596  }
7597  goto basic_json_parser_25;
7598  }
7599  }
7600  else
7601  {
7602  if (yych <= '|')
7603  {
7604  if (yych == '{')
7605  {
7606  goto basic_json_parser_26;
7607  }
7608  goto basic_json_parser_4;
7609  }
7610  else
7611  {
7612  if (yych <= '}')
7613  {
7614  goto basic_json_parser_28;
7615  }
7616  if (yych == 0xEF)
7617  {
7618  goto basic_json_parser_30;
7619  }
7620  goto basic_json_parser_4;
7621  }
7622  }
7623  }
7624 basic_json_parser_2:
7625  ++m_cursor;
7626  {
7627  return token_type::end_of_input;
7628  }
7629 basic_json_parser_4:
7630  ++m_cursor;
7631 basic_json_parser_5:
7632  {
7633  return token_type::parse_error;
7634  }
7635 basic_json_parser_6:
7636  ++m_cursor;
7637  if (m_limit <= m_cursor)
7638  {
7639  yyfill(); // LCOV_EXCL_LINE;
7640  }
7641  yych = *m_cursor;
7642  if (yybm[0 + yych] & 32)
7643  {
7644  goto basic_json_parser_6;
7645  }
7646  {
7647  return scan();
7648  }
7649 basic_json_parser_9:
7650  yyaccept = 0;
7651  yych = *(m_marker = ++m_cursor);
7652  if (yych <= 0x0F)
7653  {
7654  goto basic_json_parser_5;
7655  }
7656  goto basic_json_parser_32;
7657 basic_json_parser_10:
7658  ++m_cursor;
7659  {
7660  return token_type::value_separator;
7661  }
7662 basic_json_parser_12:
7663  yych = *++m_cursor;
7664  if (yych <= '/')
7665  {
7666  goto basic_json_parser_5;
7667  }
7668  if (yych <= '0')
7669  {
7670  goto basic_json_parser_13;
7671  }
7672  if (yych <= '9')
7673  {
7674  goto basic_json_parser_15;
7675  }
7676  goto basic_json_parser_5;
7677 basic_json_parser_13:
7678  yyaccept = 1;
7679  yych = *(m_marker = ++m_cursor);
7680  if (yych <= 'D')
7681  {
7682  if (yych == '.')
7683  {
7684  goto basic_json_parser_37;
7685  }
7686  }
7687  else
7688  {
7689  if (yych <= 'E')
7690  {
7691  goto basic_json_parser_38;
7692  }
7693  if (yych == 'e')
7694  {
7695  goto basic_json_parser_38;
7696  }
7697  }
7698 basic_json_parser_14:
7699  {
7700  return token_type::value_number;
7701  }
7702 basic_json_parser_15:
7703  yyaccept = 1;
7704  m_marker = ++m_cursor;
7705  if ((m_limit - m_cursor) < 3)
7706  {
7707  yyfill(); // LCOV_EXCL_LINE;
7708  }
7709  yych = *m_cursor;
7710  if (yybm[0 + yych] & 64)
7711  {
7712  goto basic_json_parser_15;
7713  }
7714  if (yych <= 'D')
7715  {
7716  if (yych == '.')
7717  {
7718  goto basic_json_parser_37;
7719  }
7720  goto basic_json_parser_14;
7721  }
7722  else
7723  {
7724  if (yych <= 'E')
7725  {
7726  goto basic_json_parser_38;
7727  }
7728  if (yych == 'e')
7729  {
7730  goto basic_json_parser_38;
7731  }
7732  goto basic_json_parser_14;
7733  }
7734 basic_json_parser_17:
7735  ++m_cursor;
7736  {
7737  return token_type::name_separator;
7738  }
7739 basic_json_parser_19:
7740  ++m_cursor;
7741  {
7742  return token_type::begin_array;
7743  }
7744 basic_json_parser_21:
7745  ++m_cursor;
7746  {
7747  return token_type::end_array;
7748  }
7749 basic_json_parser_23:
7750  yyaccept = 0;
7751  yych = *(m_marker = ++m_cursor);
7752  if (yych == 'a')
7753  {
7754  goto basic_json_parser_39;
7755  }
7756  goto basic_json_parser_5;
7757 basic_json_parser_24:
7758  yyaccept = 0;
7759  yych = *(m_marker = ++m_cursor);
7760  if (yych == 'u')
7761  {
7762  goto basic_json_parser_40;
7763  }
7764  goto basic_json_parser_5;
7765 basic_json_parser_25:
7766  yyaccept = 0;
7767  yych = *(m_marker = ++m_cursor);
7768  if (yych == 'r')
7769  {
7770  goto basic_json_parser_41;
7771  }
7772  goto basic_json_parser_5;
7773 basic_json_parser_26:
7774  ++m_cursor;
7775  {
7776  return token_type::begin_object;
7777  }
7778 basic_json_parser_28:
7779  ++m_cursor;
7780  {
7781  return token_type::end_object;
7782  }
7783 basic_json_parser_30:
7784  yyaccept = 0;
7785  yych = *(m_marker = ++m_cursor);
7786  if (yych == 0xBB)
7787  {
7788  goto basic_json_parser_42;
7789  }
7790  goto basic_json_parser_5;
7791 basic_json_parser_31:
7792  ++m_cursor;
7793  if (m_limit <= m_cursor)
7794  {
7795  yyfill(); // LCOV_EXCL_LINE;
7796  }
7797  yych = *m_cursor;
7798 basic_json_parser_32:
7799  if (yybm[0 + yych] & 128)
7800  {
7801  goto basic_json_parser_31;
7802  }
7803  if (yych <= 0x0F)
7804  {
7805  goto basic_json_parser_33;
7806  }
7807  if (yych <= '"')
7808  {
7809  goto basic_json_parser_34;
7810  }
7811  goto basic_json_parser_36;
7812 basic_json_parser_33:
7813  m_cursor = m_marker;
7814  if (yyaccept == 0)
7815  {
7816  goto basic_json_parser_5;
7817  }
7818  else
7819  {
7820  goto basic_json_parser_14;
7821  }
7822 basic_json_parser_34:
7823  ++m_cursor;
7824  {
7825  return token_type::value_string;
7826  }
7827 basic_json_parser_36:
7828  ++m_cursor;
7829  if (m_limit <= m_cursor)
7830  {
7831  yyfill(); // LCOV_EXCL_LINE;
7832  }
7833  yych = *m_cursor;
7834  if (yych <= 'e')
7835  {
7836  if (yych <= '/')
7837  {
7838  if (yych == '"')
7839  {
7840  goto basic_json_parser_31;
7841  }
7842  if (yych <= '.')
7843  {
7844  goto basic_json_parser_33;
7845  }
7846  goto basic_json_parser_31;
7847  }
7848  else
7849  {
7850  if (yych <= '\\')
7851  {
7852  if (yych <= '[')
7853  {
7854  goto basic_json_parser_33;
7855  }
7856  goto basic_json_parser_31;
7857  }
7858  else
7859  {
7860  if (yych == 'b')
7861  {
7862  goto basic_json_parser_31;
7863  }
7864  goto basic_json_parser_33;
7865  }
7866  }
7867  }
7868  else
7869  {
7870  if (yych <= 'q')
7871  {
7872  if (yych <= 'f')
7873  {
7874  goto basic_json_parser_31;
7875  }
7876  if (yych == 'n')
7877  {
7878  goto basic_json_parser_31;
7879  }
7880  goto basic_json_parser_33;
7881  }
7882  else
7883  {
7884  if (yych <= 's')
7885  {
7886  if (yych <= 'r')
7887  {
7888  goto basic_json_parser_31;
7889  }
7890  goto basic_json_parser_33;
7891  }
7892  else
7893  {
7894  if (yych <= 't')
7895  {
7896  goto basic_json_parser_31;
7897  }
7898  if (yych <= 'u')
7899  {
7900  goto basic_json_parser_43;
7901  }
7902  goto basic_json_parser_33;
7903  }
7904  }
7905  }
7906 basic_json_parser_37:
7907  yych = *++m_cursor;
7908  if (yych <= '/')
7909  {
7910  goto basic_json_parser_33;
7911  }
7912  if (yych <= '9')
7913  {
7914  goto basic_json_parser_44;
7915  }
7916  goto basic_json_parser_33;
7917 basic_json_parser_38:
7918  yych = *++m_cursor;
7919  if (yych <= ',')
7920  {
7921  if (yych == '+')
7922  {
7923  goto basic_json_parser_46;
7924  }
7925  goto basic_json_parser_33;
7926  }
7927  else
7928  {
7929  if (yych <= '-')
7930  {
7931  goto basic_json_parser_46;
7932  }
7933  if (yych <= '/')
7934  {
7935  goto basic_json_parser_33;
7936  }
7937  if (yych <= '9')
7938  {
7939  goto basic_json_parser_47;
7940  }
7941  goto basic_json_parser_33;
7942  }
7943 basic_json_parser_39:
7944  yych = *++m_cursor;
7945  if (yych == 'l')
7946  {
7947  goto basic_json_parser_49;
7948  }
7949  goto basic_json_parser_33;
7950 basic_json_parser_40:
7951  yych = *++m_cursor;
7952  if (yych == 'l')
7953  {
7954  goto basic_json_parser_50;
7955  }
7956  goto basic_json_parser_33;
7957 basic_json_parser_41:
7958  yych = *++m_cursor;
7959  if (yych == 'u')
7960  {
7961  goto basic_json_parser_51;
7962  }
7963  goto basic_json_parser_33;
7964 basic_json_parser_42:
7965  yych = *++m_cursor;
7966  if (yych == 0xBF)
7967  {
7968  goto basic_json_parser_52;
7969  }
7970  goto basic_json_parser_33;
7971 basic_json_parser_43:
7972  ++m_cursor;
7973  if (m_limit <= m_cursor)
7974  {
7975  yyfill(); // LCOV_EXCL_LINE;
7976  }
7977  yych = *m_cursor;
7978  if (yych <= '@')
7979  {
7980  if (yych <= '/')
7981  {
7982  goto basic_json_parser_33;
7983  }
7984  if (yych <= '9')
7985  {
7986  goto basic_json_parser_54;
7987  }
7988  goto basic_json_parser_33;
7989  }
7990  else
7991  {
7992  if (yych <= 'F')
7993  {
7994  goto basic_json_parser_54;
7995  }
7996  if (yych <= '`')
7997  {
7998  goto basic_json_parser_33;
7999  }
8000  if (yych <= 'f')
8001  {
8002  goto basic_json_parser_54;
8003  }
8004  goto basic_json_parser_33;
8005  }
8006 basic_json_parser_44:
8007  yyaccept = 1;
8008  m_marker = ++m_cursor;
8009  if ((m_limit - m_cursor) < 3)
8010  {
8011  yyfill(); // LCOV_EXCL_LINE;
8012  }
8013  yych = *m_cursor;
8014  if (yych <= 'D')
8015  {
8016  if (yych <= '/')
8017  {
8018  goto basic_json_parser_14;
8019  }
8020  if (yych <= '9')
8021  {
8022  goto basic_json_parser_44;
8023  }
8024  goto basic_json_parser_14;
8025  }
8026  else
8027  {
8028  if (yych <= 'E')
8029  {
8030  goto basic_json_parser_38;
8031  }
8032  if (yych == 'e')
8033  {
8034  goto basic_json_parser_38;
8035  }
8036  goto basic_json_parser_14;
8037  }
8038 basic_json_parser_46:
8039  yych = *++m_cursor;
8040  if (yych <= '/')
8041  {
8042  goto basic_json_parser_33;
8043  }
8044  if (yych >= ':')
8045  {
8046  goto basic_json_parser_33;
8047  }
8048 basic_json_parser_47:
8049  ++m_cursor;
8050  if (m_limit <= m_cursor)
8051  {
8052  yyfill(); // LCOV_EXCL_LINE;
8053  }
8054  yych = *m_cursor;
8055  if (yych <= '/')
8056  {
8057  goto basic_json_parser_14;
8058  }
8059  if (yych <= '9')
8060  {
8061  goto basic_json_parser_47;
8062  }
8063  goto basic_json_parser_14;
8064 basic_json_parser_49:
8065  yych = *++m_cursor;
8066  if (yych == 's')
8067  {
8068  goto basic_json_parser_55;
8069  }
8070  goto basic_json_parser_33;
8071 basic_json_parser_50:
8072  yych = *++m_cursor;
8073  if (yych == 'l')
8074  {
8075  goto basic_json_parser_56;
8076  }
8077  goto basic_json_parser_33;
8078 basic_json_parser_51:
8079  yych = *++m_cursor;
8080  if (yych == 'e')
8081  {
8082  goto basic_json_parser_58;
8083  }
8084  goto basic_json_parser_33;
8085 basic_json_parser_52:
8086  ++m_cursor;
8087  {
8088  return scan();
8089  }
8090 basic_json_parser_54:
8091  ++m_cursor;
8092  if (m_limit <= m_cursor)
8093  {
8094  yyfill(); // LCOV_EXCL_LINE;
8095  }
8096  yych = *m_cursor;
8097  if (yych <= '@')
8098  {
8099  if (yych <= '/')
8100  {
8101  goto basic_json_parser_33;
8102  }
8103  if (yych <= '9')
8104  {
8105  goto basic_json_parser_60;
8106  }
8107  goto basic_json_parser_33;
8108  }
8109  else
8110  {
8111  if (yych <= 'F')
8112  {
8113  goto basic_json_parser_60;
8114  }
8115  if (yych <= '`')
8116  {
8117  goto basic_json_parser_33;
8118  }
8119  if (yych <= 'f')
8120  {
8121  goto basic_json_parser_60;
8122  }
8123  goto basic_json_parser_33;
8124  }
8125 basic_json_parser_55:
8126  yych = *++m_cursor;
8127  if (yych == 'e')
8128  {
8129  goto basic_json_parser_61;
8130  }
8131  goto basic_json_parser_33;
8132 basic_json_parser_56:
8133  ++m_cursor;
8134  {
8135  return token_type::literal_null;
8136  }
8137 basic_json_parser_58:
8138  ++m_cursor;
8139  {
8140  return token_type::literal_true;
8141  }
8142 basic_json_parser_60:
8143  ++m_cursor;
8144  if (m_limit <= m_cursor)
8145  {
8146  yyfill(); // LCOV_EXCL_LINE;
8147  }
8148  yych = *m_cursor;
8149  if (yych <= '@')
8150  {
8151  if (yych <= '/')
8152  {
8153  goto basic_json_parser_33;
8154  }
8155  if (yych <= '9')
8156  {
8157  goto basic_json_parser_63;
8158  }
8159  goto basic_json_parser_33;
8160  }
8161  else
8162  {
8163  if (yych <= 'F')
8164  {
8165  goto basic_json_parser_63;
8166  }
8167  if (yych <= '`')
8168  {
8169  goto basic_json_parser_33;
8170  }
8171  if (yych <= 'f')
8172  {
8173  goto basic_json_parser_63;
8174  }
8175  goto basic_json_parser_33;
8176  }
8177 basic_json_parser_61:
8178  ++m_cursor;
8179  {
8180  return token_type::literal_false;
8181  }
8182 basic_json_parser_63:
8183  ++m_cursor;
8184  if (m_limit <= m_cursor)
8185  {
8186  yyfill(); // LCOV_EXCL_LINE;
8187  }
8188  yych = *m_cursor;
8189  if (yych <= '@')
8190  {
8191  if (yych <= '/')
8192  {
8193  goto basic_json_parser_33;
8194  }
8195  if (yych <= '9')
8196  {
8197  goto basic_json_parser_31;
8198  }
8199  goto basic_json_parser_33;
8200  }
8201  else
8202  {
8203  if (yych <= 'F')
8204  {
8205  goto basic_json_parser_31;
8206  }
8207  if (yych <= '`')
8208  {
8209  goto basic_json_parser_33;
8210  }
8211  if (yych <= 'f')
8212  {
8213  goto basic_json_parser_31;
8214  }
8215  goto basic_json_parser_33;
8216  }
8217  }
8218 
8219  }
8220 
8222  void yyfill() noexcept
8223  {
8224  if (m_stream == nullptr or not * m_stream)
8225  {
8226  return;
8227  }
8228 
8229  const auto offset_start = m_start - m_content;
8230  const auto offset_marker = m_marker - m_start;
8231  const auto offset_cursor = m_cursor - m_start;
8232 
8233  m_buffer.erase(0, static_cast<size_t>(offset_start));
8234  std::string line;
8235  assert(m_stream != nullptr);
8236  std::getline(*m_stream, line);
8237  m_buffer += "\n" + line; // add line with newline symbol
8238 
8239  m_content = reinterpret_cast<const lexer_char_t*>(m_buffer.c_str());
8240  assert(m_content != nullptr);
8241  m_start = m_content;
8242  m_marker = m_start + offset_marker;
8243  m_cursor = m_start + offset_cursor;
8244  m_limit = m_start + m_buffer.size() - 1;
8245  }
8246 
8248  string_t get_token() const
8249  {
8250  assert(m_start != nullptr);
8251  return string_t(reinterpret_cast<typename string_t::const_pointer>(m_start),
8252  static_cast<size_t>(m_cursor - m_start));
8253  }
8254 
8277  string_t get_string() const
8278  {
8279  string_t result;
8280  result.reserve(static_cast<size_t>(m_cursor - m_start - 2));
8281 
8282  // iterate the result between the quotes
8283  for (const lexer_char_t* i = m_start + 1; i < m_cursor - 1; ++i)
8284  {
8285  // process escaped characters
8286  if (*i == '\\')
8287  {
8288  // read next character
8289  ++i;
8290 
8291  switch (*i)
8292  {
8293  // the default escapes
8294  case 't':
8295  {
8296  result += "\t";
8297  break;
8298  }
8299  case 'b':
8300  {
8301  result += "\b";
8302  break;
8303  }
8304  case 'f':
8305  {
8306  result += "\f";
8307  break;
8308  }
8309  case 'n':
8310  {
8311  result += "\n";
8312  break;
8313  }
8314  case 'r':
8315  {
8316  result += "\r";
8317  break;
8318  }
8319  case '\\':
8320  {
8321  result += "\\";
8322  break;
8323  }
8324  case '/':
8325  {
8326  result += "/";
8327  break;
8328  }
8329  case '"':
8330  {
8331  result += "\"";
8332  break;
8333  }
8334 
8335  // unicode
8336  case 'u':
8337  {
8338  // get code xxxx from uxxxx
8339  auto codepoint = std::strtoul(std::string(reinterpret_cast<typename string_t::const_pointer>(i + 1),
8340  4).c_str(), nullptr, 16);
8341 
8342  // check if codepoint is a high surrogate
8343  if (codepoint >= 0xD800 and codepoint <= 0xDBFF)
8344  {
8345  // make sure there is a subsequent unicode
8346  if ((i + 6 >= m_limit) or * (i + 5) != '\\' or * (i + 6) != 'u')
8347  {
8348  throw std::invalid_argument("missing low surrogate");
8349  }
8350 
8351  // get code yyyy from uxxxx\uyyyy
8352  auto codepoint2 = std::strtoul(std::string(reinterpret_cast<typename string_t::const_pointer>
8353  (i + 7), 4).c_str(), nullptr, 16);
8354  result += to_unicode(codepoint, codepoint2);
8355  // skip the next 10 characters (xxxx\uyyyy)
8356  i += 10;
8357  }
8358  else
8359  {
8360  // add unicode character(s)
8361  result += to_unicode(codepoint);
8362  // skip the next four characters (xxxx)
8363  i += 4;
8364  }
8365  break;
8366  }
8367  }
8368  }
8369  else
8370  {
8371  // all other characters are just copied to the end of the
8372  // string
8373  result.append(1, static_cast<typename string_t::value_type>(*i));
8374  }
8375  }
8376 
8377  return result;
8378  }
8379 
8400  long double str_to_float_t(long double* /* type */, char** endptr) const
8401  {
8402  return std::strtold(reinterpret_cast<typename string_t::const_pointer>(m_start), endptr);
8403  }
8404 
8420  double str_to_float_t(double* /* type */, char** endptr) const
8421  {
8422  return std::strtod(reinterpret_cast<typename string_t::const_pointer>(m_start), endptr);
8423  }
8424 
8440  float str_to_float_t(float* /* type */, char** endptr) const
8441  {
8442  return std::strtof(reinterpret_cast<typename string_t::const_pointer>(m_start), endptr);
8443  }
8444 
8472  void get_number(basic_json& result) const
8473  {
8474  assert(m_start != nullptr);
8475 
8476  const lexer::lexer_char_t* curptr = m_start;
8477 
8478  // remember this number was parsed (for later serialization)
8479  result.m_type.bits.parsed = true;
8480 
8481  // 'found_radix_point' will be set to 0xFF upon finding a radix
8482  // point and later used to mask in/out the precision depending
8483  // whether a radix is found i.e. 'precision &= found_radix_point'
8484  uint8_t found_radix_point = 0;
8485  uint8_t precision = 0;
8486 
8487  // accumulate the integer conversion result (unsigned for now)
8488  number_unsigned_t value = 0;
8489 
8490  // maximum absolute value of the relevant integer type
8491  number_unsigned_t max;
8492 
8493  // temporarily store the type to avoid unecessary bitfield access
8494  value_t type;
8495 
8496  // look for sign
8497  if (*curptr == '-')
8498  {
8499  type = value_t::number_integer;
8500  max = static_cast<uint64_t>(std::numeric_limits<number_integer_t>::max()) + 1;
8501  curptr++;
8502  }
8503  else
8504  {
8505  type = value_t::number_unsigned;
8506  max = static_cast<uint64_t>(std::numeric_limits<number_unsigned_t>::max());
8507  }
8508 
8509  // count the significant figures
8510  for (; curptr < m_cursor; curptr++)
8511  {
8512  // quickly skip tests if a digit
8513  if (*curptr < '0' || *curptr > '9')
8514  {
8515  if (*curptr == '.')
8516  {
8517  // don't count '.' but change to float
8518  type = value_t::number_float;
8519 
8520  // reset precision count
8521  precision = 0;
8522  found_radix_point = 0xFF;
8523  continue;
8524  }
8525  // assume exponent (if not then will fail parse): change to
8526  // float, stop counting and record exponent details
8527  type = value_t::number_float;
8528  result.m_type.bits.has_exp = true;
8529 
8530  // exponent capitalization
8531  result.m_type.bits.exp_cap = (*curptr == 'E');
8532 
8533  // exponent '+' sign
8534  result.m_type.bits.exp_plus = (*(++curptr) == '+');
8535  break;
8536  }
8537 
8538  // skip if definitely not an integer
8539  if (type != value_t::number_float)
8540  {
8541  // multiply last value by ten and add the new digit
8542  auto temp = value * 10 + *curptr - 0x30;
8543 
8544  // test for overflow
8545  if (temp < value || temp > max)
8546  {
8547  // overflow
8548  type = value_t::number_float;
8549  }
8550  else
8551  {
8552  // no overflow - save it
8553  value = temp;
8554  }
8555  }
8556  ++precision;
8557  }
8558 
8559  // If no radix point was found then precision would now be set to
8560  // the number of digits, which is wrong - clear it.
8561  result.m_type.bits.precision = precision & found_radix_point;
8562 
8563  // save the value (if not a float)
8564  if (type == value_t::number_unsigned)
8565  {
8566  result.m_value.number_unsigned = value;
8567  }
8568  else if (type == value_t::number_integer)
8569  {
8570  result.m_value.number_integer = -static_cast<number_integer_t>(value);
8571  }
8572  else
8573  {
8574  // parse with strtod
8575  result.m_value.number_float = str_to_float_t(static_cast<number_float_t*>(nullptr), NULL);
8576  }
8577 
8578  // save the type
8579  result.m_type = type;
8580  }
8581 
8582  private:
8584  std::istream* m_stream = nullptr;
8586  string_t m_buffer;
8588  const lexer_char_t* m_content = nullptr;
8590  const lexer_char_t* m_start = nullptr;
8592  const lexer_char_t* m_marker = nullptr;
8594  const lexer_char_t* m_cursor = nullptr;
8596  const lexer_char_t* m_limit = nullptr;
8597  };
8598 
8604  class parser
8605  {
8606  public:
8608  parser(const string_t& s, parser_callback_t cb = nullptr) noexcept
8609  : callback(cb), m_lexer(s)
8610  {
8611  // read first token
8612  get_token();
8613  }
8614 
8616  parser(std::istream& _is, parser_callback_t cb = nullptr) noexcept
8617  : callback(cb), m_lexer(&_is)
8618  {
8619  // read first token
8620  get_token();
8621  }
8622 
8624  basic_json parse()
8625  {
8626  basic_json result = parse_internal(true);
8627 
8628  expect(lexer::token_type::end_of_input);
8629 
8630  // return parser result and replace it with null in case the
8631  // top-level value was discarded by the callback function
8632  return result.is_discarded() ? basic_json() : result;
8633  }
8634 
8635  private:
8637  basic_json parse_internal(bool keep)
8638  {
8639  auto result = basic_json(value_t::discarded);
8640 
8641  switch (last_token)
8642  {
8643  case lexer::token_type::begin_object:
8644  {
8645  if (keep and (not callback or (keep = callback(depth++, parse_event_t::object_start, result))))
8646  {
8647  // explicitly set result to object to cope with {}
8648  result.m_type = value_t::object;
8649  result.m_value = json_value(value_t::object);
8650  }
8651 
8652  // read next token
8653  get_token();
8654 
8655  // closing } -> we are done
8656  if (last_token == lexer::token_type::end_object)
8657  {
8658  get_token();
8659  if (keep and callback and not callback(--depth, parse_event_t::object_end, result))
8660  {
8661  result = basic_json(value_t::discarded);
8662  }
8663  return result;
8664  }
8665 
8666  // no comma is expected here
8667  unexpect(lexer::token_type::value_separator);
8668 
8669  // otherwise: parse key-value pairs
8670  do
8671  {
8672  // ugly, but could be fixed with loop reorganization
8673  if (last_token == lexer::token_type::value_separator)
8674  {
8675  get_token();
8676  }
8677 
8678  // store key
8679  expect(lexer::token_type::value_string);
8680  const auto key = m_lexer.get_string();
8681 
8682  bool keep_tag = false;
8683  if (keep)
8684  {
8685  if (callback)
8686  {
8687  basic_json k(key);
8688  keep_tag = callback(depth, parse_event_t::key, k);
8689  }
8690  else
8691  {
8692  keep_tag = true;
8693  }
8694  }
8695 
8696  // parse separator (:)
8697  get_token();
8698  expect(lexer::token_type::name_separator);
8699 
8700  // parse and add value
8701  get_token();
8702  auto value = parse_internal(keep);
8703  if (keep and keep_tag and not value.is_discarded())
8704  {
8705  result[key] = std::move(value);
8706  }
8707  }
8708  while (last_token == lexer::token_type::value_separator);
8709 
8710  // closing }
8711  expect(lexer::token_type::end_object);
8712  get_token();
8713  if (keep and callback and not callback(--depth, parse_event_t::object_end, result))
8714  {
8715  result = basic_json(value_t::discarded);
8716  }
8717 
8718  return result;
8719  }
8720 
8721  case lexer::token_type::begin_array:
8722  {
8723  if (keep and (not callback or (keep = callback(depth++, parse_event_t::array_start, result))))
8724  {
8725  // explicitly set result to object to cope with []
8726  result.m_type = value_t::array;
8727  result.m_value = json_value(value_t::array);
8728  }
8729 
8730  // read next token
8731  get_token();
8732 
8733  // closing ] -> we are done
8734  if (last_token == lexer::token_type::end_array)
8735  {
8736  get_token();
8737  if (callback and not callback(--depth, parse_event_t::array_end, result))
8738  {
8739  result = basic_json(value_t::discarded);
8740  }
8741  return result;
8742  }
8743 
8744  // no comma is expected here
8745  unexpect(lexer::token_type::value_separator);
8746 
8747  // otherwise: parse values
8748  do
8749  {
8750  // ugly, but could be fixed with loop reorganization
8751  if (last_token == lexer::token_type::value_separator)
8752  {
8753  get_token();
8754  }
8755 
8756  // parse value
8757  auto value = parse_internal(keep);
8758  if (keep and not value.is_discarded())
8759  {
8760  result.push_back(std::move(value));
8761  }
8762  }
8763  while (last_token == lexer::token_type::value_separator);
8764 
8765  // closing ]
8766  expect(lexer::token_type::end_array);
8767  get_token();
8768  if (keep and callback and not callback(--depth, parse_event_t::array_end, result))
8769  {
8770  result = basic_json(value_t::discarded);
8771  }
8772 
8773  return result;
8774  }
8775 
8776  case lexer::token_type::literal_null:
8777  {
8778  get_token();
8779  result.m_type = value_t::null;
8780  break;
8781  }
8782 
8783  case lexer::token_type::value_string:
8784  {
8785  const auto s = m_lexer.get_string();
8786  get_token();
8787  result = basic_json(s);
8788  break;
8789  }
8790 
8791  case lexer::token_type::literal_true:
8792  {
8793  get_token();
8794  result.m_type = value_t::boolean;
8795  result.m_value = true;
8796  break;
8797  }
8798 
8799  case lexer::token_type::literal_false:
8800  {
8801  get_token();
8802  result.m_type = value_t::boolean;
8803  result.m_value = false;
8804  break;
8805  }
8806 
8807  case lexer::token_type::value_number:
8808  {
8809  m_lexer.get_number(result);
8810  get_token();
8811  break;
8812  }
8813 
8814  default:
8815  {
8816  // the last token was unexpected
8817  unexpect(last_token);
8818  }
8819  }
8820 
8821  if (keep and callback and not callback(depth, parse_event_t::value, result))
8822  {
8823  result = basic_json(value_t::discarded);
8824  }
8825  return result;
8826  }
8827 
8829  typename lexer::token_type get_token() noexcept
8830  {
8831  last_token = m_lexer.scan();
8832  return last_token;
8833  }
8834 
8835  void expect(typename lexer::token_type t) const
8836  {
8837  if (t != last_token)
8838  {
8839  std::string error_msg = "parse error - unexpected ";
8840  error_msg += (last_token == lexer::token_type::parse_error ? ("'" + m_lexer.get_token() + "'") :
8841  lexer::token_type_name(last_token));
8842  error_msg += "; expected " + lexer::token_type_name(t);
8843  throw std::invalid_argument(error_msg);
8844  }
8845  }
8846 
8847  void unexpect(typename lexer::token_type t) const
8848  {
8849  if (t == last_token)
8850  {
8851  std::string error_msg = "parse error - unexpected ";
8852  error_msg += (last_token == lexer::token_type::parse_error ? ("'" + m_lexer.get_token() + "'") :
8853  lexer::token_type_name(last_token));
8854  throw std::invalid_argument(error_msg);
8855  }
8856  }
8857 
8858  private:
8860  int depth = 0;
8862  parser_callback_t callback;
8864  typename lexer::token_type last_token = lexer::token_type::uninitialized;
8866  lexer m_lexer;
8867  };
8868 
8869  public:
8882  {
8884  friend class basic_json;
8885 
8886  public:
8909  explicit json_pointer(const std::string& s = "")
8910  : reference_tokens(split(s))
8911  {}
8912 
8928  std::string to_string() const noexcept
8929  {
8930  std::string result;
8931 
8932  for (const auto& reference_token : reference_tokens)
8933  {
8934  result += "/" + escape(reference_token);
8935  }
8936 
8937  return result;
8938  }
8939 
8941  operator std::string() const
8942  {
8943  return to_string();
8944  }
8946  private:
8948  std::string pop_back()
8949  {
8950  if (is_root())
8951  {
8952  throw std::domain_error("JSON pointer has no parent");
8953  }
8954 
8955  auto last = reference_tokens.back();
8956  reference_tokens.pop_back();
8957  return last;
8958  }
8959 
8961  bool is_root() const
8962  {
8963  return reference_tokens.empty();
8964  }
8965 
8966  json_pointer top() const
8967  {
8968  if (is_root())
8969  {
8970  throw std::domain_error("JSON pointer has no parent");
8971  }
8972 
8973  json_pointer result = *this;
8974  result.reference_tokens = {reference_tokens[0]};
8975  return result;
8976  }
8977 
8981  reference get_and_create(reference j) const
8982  {
8983  pointer result = &j;
8984 
8985  // in case no reference tokens exist, return a reference to the
8986  // JSON value j which will be overwritten by a primitive value
8987  for (const auto& reference_token : reference_tokens)
8988  {
8989  switch (result->m_type)
8990  {
8991  case value_t::null:
8992  {
8993  if (reference_token == "0")
8994  {
8995  // start a new array if reference token is 0
8996  result = &result->operator[](0);
8997  }
8998  else
8999  {
9000  // start a new object otherwise
9001  result = &result->operator[](reference_token);
9002  }
9003  break;
9004  }
9005 
9006  case value_t::object:
9007  {
9008  // create an entry in the object
9009  result = &result->operator[](reference_token);
9010  break;
9011  }
9012 
9013  case value_t::array:
9014  {
9015  // create an entry in the array
9016  result = &result->operator[](static_cast<size_type>(std::stoi(reference_token)));
9017  break;
9018  }
9019 
9020  /*
9021  The following code is only reached if there exists a
9022  reference token _and_ the current value is primitive. In
9023  this case, we have an error situation, because primitive
9024  values may only occur as single value; that is, with an
9025  empty list of reference tokens.
9026  */
9027  default:
9028  {
9029  throw std::domain_error("invalid value to unflatten");
9030  }
9031  }
9032  }
9033 
9034  return *result;
9035  }
9036 
9050  reference get_unchecked(pointer ptr) const
9051  {
9052  for (const auto& reference_token : reference_tokens)
9053  {
9054  switch (ptr->m_type)
9055  {
9056  case value_t::object:
9057  {
9058  // use unchecked object access
9059  ptr = &ptr->operator[](reference_token);
9060  break;
9061  }
9062 
9063  case value_t::array:
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  if (reference_token == "-")
9072  {
9073  // explicityly treat "-" as index beyond the end
9074  ptr = &ptr->operator[](ptr->m_value.array->size());
9075  }
9076  else
9077  {
9078  // convert array index to number; unchecked access
9079  ptr = &ptr->operator[](static_cast<size_type>(std::stoi(reference_token)));
9080  }
9081  break;
9082  }
9083 
9084  default:
9085  {
9086  throw std::out_of_range("unresolved reference token '" + reference_token + "'");
9087  }
9088  }
9089  }
9090 
9091  return *ptr;
9092  }
9093 
9094  reference get_checked(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  // note: at performs range check
9103  ptr = &ptr->at(reference_token);
9104  break;
9105  }
9106 
9107  case value_t::array:
9108  {
9109  if (reference_token == "-")
9110  {
9111  // "-" always fails the range check
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  // note: at performs range check
9124  ptr = &ptr->at(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 
9146  const_reference get_unchecked(const_pointer ptr) const
9147  {
9148  for (const auto& reference_token : reference_tokens)
9149  {
9150  switch (ptr->m_type)
9151  {
9152  case value_t::object:
9153  {
9154  // use unchecked object access
9155  ptr = &ptr->operator[](reference_token);
9156  break;
9157  }
9158 
9159  case value_t::array:
9160  {
9161  if (reference_token == "-")
9162  {
9163  // "-" cannot be used for const access
9164  throw std::out_of_range("array index '-' (" +
9165  std::to_string(ptr->m_value.array->size()) +
9166  ") is out of range");
9167  }
9168 
9169  // error condition (cf. RFC 6901, Sect. 4)
9170  if (reference_token.size() > 1 and reference_token[0] == '0')
9171  {
9172  throw std::domain_error("array index must not begin with '0'");
9173  }
9174 
9175  // use unchecked array access
9176  ptr = &ptr->operator[](static_cast<size_type>(std::stoi(reference_token)));
9177  break;
9178  }
9179 
9180  default:
9181  {
9182  throw std::out_of_range("unresolved reference token '" + reference_token + "'");
9183  }
9184  }
9185  }
9186 
9187  return *ptr;
9188  }
9189 
9190  const_reference get_checked(const_pointer ptr) const
9191  {
9192  for (const auto& reference_token : reference_tokens)
9193  {
9194  switch (ptr->m_type)
9195  {
9196  case value_t::object:
9197  {
9198  // note: at performs range check
9199  ptr = &ptr->at(reference_token);
9200  break;
9201  }
9202 
9203  case value_t::array:
9204  {
9205  if (reference_token == "-")
9206  {
9207  // "-" always fails the range check
9208  throw std::out_of_range("array index '-' (" +
9209  std::to_string(ptr->m_value.array->size()) +
9210  ") is out of range");
9211  }
9212 
9213  // error condition (cf. RFC 6901, Sect. 4)
9214  if (reference_token.size() > 1 and reference_token[0] == '0')
9215  {
9216  throw std::domain_error("array index must not begin with '0'");
9217  }
9218 
9219  // note: at performs range check
9220  ptr = &ptr->at(static_cast<size_type>(std::stoi(reference_token)));
9221  break;
9222  }
9223 
9224  default:
9225  {
9226  throw std::out_of_range("unresolved reference token '" + reference_token + "'");
9227  }
9228  }
9229  }
9230 
9231  return *ptr;
9232  }
9233 
9235  static std::vector<std::string> split(std::string reference_string)
9236  {
9237  std::vector<std::string> result;
9238 
9239  // special case: empty reference string -> no reference tokens
9240  if (reference_string.empty())
9241  {
9242  return result;
9243  }
9244 
9245  // check if nonempty reference string begins with slash
9246  if (reference_string[0] != '/')
9247  {
9248  throw std::domain_error("JSON pointer must be empty or begin with '/'");
9249  }
9250 
9251  // extract the reference tokens:
9252  // - slash: position of the last read slash (or end of string)
9253  // - start: position after the previous slash
9254  for (
9255  // search for the first slash after the first character
9256  size_t slash = reference_string.find_first_of("/", 1),
9257  // set the beginning of the first reference token
9258  start = 1;
9259  // we can stop if start == string::npos+1 = 0
9260  start != 0;
9261  // set the beginning of the next reference token
9262  // (will eventually be 0 if slash == std::string::npos)
9263  start = slash + 1,
9264  // find next slash
9265  slash = reference_string.find_first_of("/", start))
9266  {
9267  // use the text between the beginning of the reference token
9268  // (start) and the last slash (slash).
9269  auto reference_token = reference_string.substr(start, slash - start);
9270 
9271  // check reference tokens are properly escaped
9272  for (size_t pos = reference_token.find_first_of("~");
9273  pos != std::string::npos;
9274  pos = reference_token.find_first_of("~", pos + 1))
9275  {
9276  assert(reference_token[pos] == '~');
9277 
9278  // ~ must be followed by 0 or 1
9279  if (pos == reference_token.size() - 1 or
9280  (reference_token[pos + 1] != '0' and
9281  reference_token[pos + 1] != '1'))
9282  {
9283  throw std::domain_error("escape error: '~' must be followed with '0' or '1'");
9284  }
9285  }
9286 
9287  // finally, store the reference token
9288  unescape(reference_token);
9289  result.push_back(reference_token);
9290  }
9291 
9292  return result;
9293  }
9294 
9295  private:
9310  static void replace_substring(std::string& s,
9311  const std::string& f,
9312  const std::string& t)
9313  {
9314  assert(not f.empty());
9315 
9316  for (
9317  size_t pos = s.find(f); // find first occurrence of f
9318  pos != std::string::npos; // make sure f was found
9319  s.replace(pos, f.size(), t), // replace with t
9320  pos = s.find(f, pos + t.size()) // find next occurrence of f
9321  );
9322  }
9323 
9325  static std::string escape(std::string s)
9326  {
9327  // escape "~"" to "~0" and "/" to "~1"
9328  replace_substring(s, "~", "~0");
9329  replace_substring(s, "/", "~1");
9330  return s;
9331  }
9332 
9334  static void unescape(std::string& s)
9335  {
9336  // first transform any occurrence of the sequence '~1' to '/'
9337  replace_substring(s, "~1", "/");
9338  // then transform any occurrence of the sequence '~0' to '~'
9339  replace_substring(s, "~0", "~");
9340  }
9341 
9349  static void flatten(const std::string& reference_string,
9350  const basic_json& value,
9351  basic_json& result)
9352  {
9353  switch (value.m_type)
9354  {
9355  case value_t::array:
9356  {
9357  if (value.m_value.array->empty())
9358  {
9359  // flatten empty array as null
9360  result[reference_string] = nullptr;
9361  }
9362  else
9363  {
9364  // iterate array and use index as reference string
9365  for (size_t i = 0; i < value.m_value.array->size(); ++i)
9366  {
9367  flatten(reference_string + "/" + std::to_string(i),
9368  value.m_value.array->operator[](i), result);
9369  }
9370  }
9371  break;
9372  }
9373 
9374  case value_t::object:
9375  {
9376  if (value.m_value.object->empty())
9377  {
9378  // flatten empty object as null
9379  result[reference_string] = nullptr;
9380  }
9381  else
9382  {
9383  // iterate object and use keys as reference string
9384  for (const auto& element : *value.m_value.object)
9385  {
9386  flatten(reference_string + "/" + escape(element.first),
9387  element.second, result);
9388  }
9389  }
9390  break;
9391  }
9392 
9393  default:
9394  {
9395  // add primitive value with its reference string
9396  result[reference_string] = value;
9397  break;
9398  }
9399  }
9400  }
9401 
9407  static basic_json unflatten(const basic_json& value)
9408  {
9409  if (not value.is_object())
9410  {
9411  throw std::domain_error("only objects can be unflattened");
9412  }
9413 
9414  basic_json result;
9415 
9416  // iterate the JSON object values
9417  for (const auto& element : *value.m_value.object)
9418  {
9419  if (not element.second.is_primitive())
9420  {
9421  throw std::domain_error("values in object must be primitive");
9422  }
9423 
9424  // assign value to reference pointed to by JSON pointer; Note
9425  // that if the JSON pointer is "" (i.e., points to the whole
9426  // value), function get_and_create returns a reference to
9427  // result itself. An assignment will then create a primitive
9428  // value.
9429  json_pointer(element.first).get_and_create(result) = element.second;
9430  }
9431 
9432  return result;
9433  }
9434 
9435  private:
9437  std::vector<std::string> reference_tokens {};
9438  };
9439 
9441  // JSON Pointer support //
9443 
9446 
9480  reference operator[](const json_pointer& ptr)
9481  {
9482  return ptr.get_unchecked(this);
9483  }
9507  const_reference operator[](const json_pointer& ptr) const
9508  {
9509  return ptr.get_unchecked(this);
9510  }
9532  reference at(const json_pointer& ptr)
9533  {
9534  return ptr.get_checked(this);
9535  }
9557  const_reference at(const json_pointer& ptr) const
9558  {
9559  return ptr.get_checked(this);
9560  }
9584  basic_json flatten() const
9585  {
9586  basic_json result(value_t::object);
9587  json_pointer::flatten("", *this, result);
9588  return result;
9589  }
9590 
9618  basic_json unflatten() const
9619  {
9620  return json_pointer::unflatten(*this);
9621  }
9624 
9626  // JSON Patch functions //
9628 
9631 
9668  basic_json patch(const basic_json& json_patch) const
9669  {
9670  // make a working copy to apply the patch to
9671  basic_json result = *this;
9673  // the valid JSON Patch operations
9674  enum class patch_operations {add, remove, replace, move, copy, test, invalid};
9675 
9676  const auto get_op = [](const std::string op)
9677  {
9678  if (op == "add")
9679  {
9680  return patch_operations::add;
9681  }
9682  if (op == "remove")
9683  {
9684  return patch_operations::remove;
9685  }
9686  if (op == "replace")
9687  {
9688  return patch_operations::replace;
9689  }
9690  if (op == "move")
9691  {
9692  return patch_operations::move;
9693  }
9694  if (op == "copy")
9695  {
9696  return patch_operations::copy;
9697  }
9698  if (op == "test")
9699  {
9700  return patch_operations::test;
9701  }
9702 
9703  return patch_operations::invalid;
9704  };
9705 
9706  // wrapper for "add" operation; add value at ptr
9707  const auto operation_add = [&result](json_pointer & ptr, basic_json val)
9708  {
9709  // adding to the root of the target document means replacing it
9710  if (ptr.is_root())
9711  {
9712  result = val;
9713  }
9714  else
9715  {
9716  // make sure the top element of the pointer exists
9717  json_pointer top_pointer = ptr.top();
9718  if (top_pointer != ptr)
9719  {
9720  basic_json& x = result.at(top_pointer);
9721  }
9722 
9723  // get reference to parent of JSON pointer ptr
9724  const auto last_path = ptr.pop_back();
9725  basic_json& parent = result[ptr];
9726 
9727  switch (parent.m_type)
9728  {
9729  case value_t::null:
9730  case value_t::object:
9731  {
9732  // use operator[] to add value
9733  parent[last_path] = val;
9734  break;
9735  }
9736 
9737  case value_t::array:
9738  {
9739  if (last_path == "-")
9740  {
9741  // special case: append to back
9742  parent.push_back(val);
9743  }
9744  else
9745  {
9746  const auto idx = std::stoi(last_path);
9747  if (static_cast<size_type>(idx) > parent.size())
9748  {
9749  // avoid undefined behavior
9750  throw std::out_of_range("array index " + std::to_string(idx) + " is out of range");
9751  }
9752  else
9753  {
9754  // default case: insert add offset
9755  parent.insert(parent.begin() + static_cast<difference_type>(idx), val);
9756  }
9757  }
9758  break;
9759  }
9760 
9761  default:
9762  {
9763  // if there exists a parent it cannot be primitive
9764  assert(false); // LCOV_EXCL_LINE
9765  }
9766  }
9767  }
9768  };
9769 
9770  // wrapper for "remove" operation; remove value at ptr
9771  const auto operation_remove = [&result](json_pointer & ptr)
9772  {
9773  // get reference to parent of JSON pointer ptr
9774  const auto last_path = ptr.pop_back();
9775  basic_json& parent = result.at(ptr);
9776 
9777  // remove child
9778  if (parent.is_object())
9779  {
9780  // perform range check
9781  auto it = parent.find(last_path);
9782  if (it != parent.end())
9783  {
9784  parent.erase(it);
9785  }
9786  else
9787  {
9788  throw std::out_of_range("key '" + last_path + "' not found");
9789  }
9790  }
9791  else if (parent.is_array())
9792  {
9793  // note erase performs range check
9794  parent.erase(static_cast<size_type>(std::stoi(last_path)));
9795  }
9796  };
9797 
9798  // type check
9799  if (not json_patch.is_array())
9800  {
9801  // a JSON patch must be an array of objects
9802  throw std::invalid_argument("JSON patch must be an array of objects");
9803  }
9804 
9805  // iterate and apply th eoperations
9806  for (const auto& val : json_patch)
9807  {
9808  // wrapper to get a value for an operation
9809  const auto get_value = [&val](const std::string & op,
9810  const std::string & member,
9811  bool string_type) -> basic_json&
9812  {
9813  // find value
9814  auto it = val.m_value.object->find(member);
9815 
9816  // context-sensitive error message
9817  const auto error_msg = (op == "op") ? "operation" : "operation '" + op + "'";
9818 
9819  // check if desired value is present
9820  if (it == val.m_value.object->end())
9821  {
9822  throw std::invalid_argument(error_msg + " must have member '" + member + "'");
9823  }
9824 
9825  // check if result is of type string
9826  if (string_type and not it->second.is_string())
9827  {
9828  throw std::invalid_argument(error_msg + " must have string member '" + member + "'");
9829  }
9830 
9831  // no error: return value
9832  return it->second;
9833  };
9834 
9835  // type check
9836  if (not val.is_object())
9837  {
9838  throw std::invalid_argument("JSON patch must be an array of objects");
9839  }
9840 
9841  // collect mandatory members
9842  const std::string op = get_value("op", "op", true);
9843  const std::string path = get_value(op, "path", true);
9844  json_pointer ptr(path);
9845 
9846  switch (get_op(op))
9847  {
9848  case patch_operations::add:
9849  {
9850  operation_add(ptr, get_value("add", "value", false));
9851  break;
9852  }
9853 
9854  case patch_operations::remove:
9855  {
9856  operation_remove(ptr);
9857  break;
9858  }
9859 
9860  case patch_operations::replace:
9861  {
9862  // the "path" location must exist - use at()
9863  result.at(ptr) = get_value("replace", "value", false);
9864  break;
9865  }
9866 
9867  case patch_operations::move:
9868  {
9869  const std::string from_path = get_value("move", "from", true);
9870  json_pointer from_ptr(from_path);
9871 
9872  // the "from" location must exist - use at()
9873  basic_json v = result.at(from_ptr);
9874 
9875  // The move operation is functionally identical to a
9876  // "remove" operation on the "from" location, followed
9877  // immediately by an "add" operation at the target
9878  // location with the value that was just removed.
9879  operation_remove(from_ptr);
9880  operation_add(ptr, v);
9881  break;
9882  }
9883 
9884  case patch_operations::copy:
9885  {
9886  const std::string from_path = get_value("copy", "from", true);;
9887  const json_pointer from_ptr(from_path);
9888 
9889  // the "from" location must exist - use at()
9890  result[ptr] = result.at(from_ptr);
9891  break;
9892  }
9893 
9894  case patch_operations::test:
9895  {
9896  bool success = false;
9897  try
9898  {
9899  // check if "value" matches the one at "path"
9900  // the "path" location must exist - use at()
9901  success = (result.at(ptr) == get_value("test", "value", false));
9902  }
9903  catch (std::out_of_range&)
9904  {
9905  // ignore out of range errors: success remains false
9906  }
9907 
9908  // throw an exception if test fails
9909  if (not success)
9910  {
9911  throw std::domain_error("unsuccessful: " + val.dump());
9912  }
9913 
9914  break;
9915  }
9916 
9917  case patch_operations::invalid:
9918  {
9919  // op must be "add", "remove", "replace", "move", "copy", or
9920  // "test"
9921  throw std::invalid_argument("operation value '" + op + "' is invalid");
9922  }
9923  }
9924  }
9925 
9926  return result;
9927  }
9928 
9961  static basic_json diff(const basic_json& source,
9962  const basic_json& target,
9963  std::string path = "")
9964  {
9965  // the patch
9966  basic_json result(value_t::array);
9967 
9968  // if the values are the same, return empty patch
9969  if (source == target)
9970  {
9971  return result;
9972  }
9973 
9974  if (source.type() != target.type())
9975  {
9976  // different types: replace value
9977  result.push_back(
9978  {
9979  {"op", "replace"},
9980  {"path", path},
9981  {"value", target}
9982  });
9983  }
9984  else
9985  {
9986  switch (source.type())
9987  {
9988  case value_t::array:
9989  {
9990  // first pass: traverse common elements
9991  size_t i = 0;
9992  while (i < source.size() and i < target.size())
9993  {
9994  // recursive call to compare array values at index i
9995  auto temp_diff = diff(source[i], target[i], path + "/" + std::to_string(i));
9996  result.insert(result.end(), temp_diff.begin(), temp_diff.end());
9997  ++i;
9998  }
9999 
10000  // i now reached the end of at least one array
10001  // in a second pass, traverse the remaining elements
10002 
10003  // remove my remaining elements
10004  while (i < source.size())
10005  {
10006  result.push_back(object(
10007  {
10008  {"op", "remove"},
10009  {"path", path + "/" + std::to_string(i)}
10010  }));
10011  ++i;
10012  }
10013 
10014  // add other remaining elements
10015  while (i < target.size())
10016  {
10017  result.push_back(
10018  {
10019  {"op", "add"},
10020  {"path", path + "/" + std::to_string(i)},
10021  {"value", target[i]}
10022  });
10023  ++i;
10024  }
10025 
10026  break;
10027  }
10028 
10029  case value_t::object:
10030  {
10031  // first pass: traverse this object's elements
10032  for (auto it = source.begin(); it != source.end(); ++it)
10033  {
10034  // escape the key name to be used in a JSON patch
10035  const auto key = json_pointer::escape(it.key());
10036 
10037  if (target.find(it.key()) != target.end())
10038  {
10039  // recursive call to compare object values at key it
10040  auto temp_diff = diff(it.value(), target[it.key()], path + "/" + key);
10041  result.insert(result.end(), temp_diff.begin(), temp_diff.end());
10042  }
10043  else
10044  {
10045  // found a key that is not in o -> remove it
10046  result.push_back(object(
10047  {
10048  {"op", "remove"},
10049  {"path", path + "/" + key}
10050  }));
10051  }
10052  }
10053 
10054  // second pass: traverse other object's elements
10055  for (auto it = target.begin(); it != target.end(); ++it)
10056  {
10057  if (source.find(it.key()) == source.end())
10058  {
10059  // found a key that is not in this -> add it
10060  const auto key = json_pointer::escape(it.key());
10061  result.push_back(
10062  {
10063  {"op", "add"},
10064  {"path", path + "/" + key},
10065  {"value", it.value()}
10066  });
10067  }
10068  }
10069 
10070  break;
10071  }
10072 
10073  default:
10074  {
10075  // both primitive type: replace value
10076  result.push_back(
10077  {
10078  {"op", "replace"},
10079  {"path", path},
10080  {"value", target}
10081  });
10082  break;
10083  }
10084  }
10085  }
10086 
10087  return result;
10088  }
10089 
10091 };
10092 
10093 
10095 // presets //
10097 
10106 using json = basic_json<>;
10107 }
10108 
10109 
10111 // nonmember support //
10113 
10114 // specialization of std::swap, and std::hash
10115 namespace std
10116 {
10122 template <>
10123 inline void swap(nlohmann::json& j1,
10124  nlohmann::json& j2) noexcept(
10125  is_nothrow_move_constructible<nlohmann::json>::value and
10126  is_nothrow_move_assignable<nlohmann::json>::value
10127  )
10128 {
10129  j1.swap(j2);
10130 }
10131 
10133 template <>
10134 struct hash<nlohmann::json>
10135 {
10141  std::size_t operator()(const nlohmann::json& j) const
10142  {
10143  // a naive hashing via the string representation
10144  const auto& h = hash<nlohmann::json::string_t>();
10145  return h(j.dump());
10146  }
10147 };
10148 }
10149 
10162 inline nlohmann::json operator "" _json(const char* s, std::size_t)
10163 {
10164  return nlohmann::json::parse(reinterpret_cast<const nlohmann::json::string_t::value_type*>(s));
10165 }
10166 
10172 inline nlohmann::json::json_pointer operator "" _json_pointer(const char* s, std::size_t)
10173 {
10174  return nlohmann::json::json_pointer(s);
10175 }
10176 
10177 // restore GCC/clang diagnostic settings
10178 #if defined(__clang__) || defined(__GNUC__) || defined(__GNUG__)
10179  #pragma GCC diagnostic pop
10180 #endif
10181 
10182 #endif
const_iterator(pointer object) noexcept
constructor for a given JSON instance
Definition: json.hpp:6502
friend bool operator<=(const_reference lhs, const_reference rhs) noexcept
comparison: less than or equal
Definition: json.hpp:5635
basic_json(const value_t value_type)
create an empty value with a given type
Definition: json.hpp:1034
basic_json(const array_t &val)
create an array (explicit)
Definition: json.hpp:1171
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:4146
const_reference operator[](size_type idx) const
access specified array element
Definition: json.hpp:3337
reference value() const
return the value of an iterator
Definition: json.hpp:7142
json_reverse_iterator & operator--()
pre-decrement (–it)
Definition: json.hpp:7204
void clear() noexcept
clears the contents
Definition: json.hpp:4697
bool operator==(const const_iterator &other) const
comparison: equal
Definition: json.hpp:6792
json_reverse_iterator operator--(int)
post-decrement (it–)
Definition: json.hpp:7198
reference operator[](T *(&key)[n])
access specified object element
Definition: json.hpp:3469
friend std::istream & operator>>(std::istream &i, basic_json &j)
deserialize from stream
Definition: json.hpp:5848
constexpr bool is_number_float() const noexcept
return whether value is a floating-point number
Definition: json.hpp:2414
const_reverse_iterator rend() const noexcept
returns a const reverse iterator to one before the first
Definition: json.hpp:4373
iterator & operator+=(difference_type i)
add to iterator
Definition: json.hpp:7100
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:1752
const_iterator operator-(difference_type i)
subtract from iterator
Definition: json.hpp:6918
BooleanType boolean_t
a type for a boolean
Definition: json.hpp:467
const_iterator cbegin() const noexcept
returns a const iterator to the first element
Definition: json.hpp:4227
reference operator+=(const typename object_t::value_type &val)
add an object to an object
Definition: json.hpp:4883
reference operator*() const
return a reference to the value pointed to by the iterator
Definition: json.hpp:7058
basic_json(const typename string_t::value_type *val)
create a string (explicit)
Definition: json.hpp:1264
reference operator[](difference_type n) const
access to successor
Definition: json.hpp:7240
iterator find(typename object_t::key_type key)
find an element in a JSON object
Definition: json.hpp:4098
friend bool operator!=(const_reference lhs, const_reference rhs) noexcept
comparison: not equal
Definition: json.hpp:5473
basic_json(const string_t &val)
create a string (explicit)
Definition: json.hpp:1240
void push_back(const basic_json &val)
add an object to an array
Definition: json.hpp:4809
void erase(const size_type idx)
remove element from a JSON array given an index
Definition: json.hpp:4051
ArrayType< basic_json, AllocatorType< basic_json >> array_t
a type for an array
Definition: json.hpp:394
reference front()
access the first element
Definition: json.hpp:3708
void swap(object_t &other)
exchanges the values
Definition: json.hpp:5229
json_reverse_iterator operator-(difference_type i) const
subtract from iterator
Definition: json.hpp:7226
const_iterator & operator+=(difference_type i)
add to iterator
Definition: json.hpp:6876
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:1375
reference value() const
return the value of an iterator
Definition: json.hpp:7253
friend bool operator==(std::nullptr_t, const_reference v) noexcept
comparison: equal
Definition: json.hpp:5452
NumberIntegerType number_integer_t
a type for a number (integer)
Definition: json.hpp:539
iterator insert(const_iterator pos, size_type cnt, const basic_json &val)
inserts elements
Definition: json.hpp:5015
const_reference at(const typename object_t::key_type &key) const
access specified object element with bounds checking
Definition: json.hpp:3244
const_iterator operator+(difference_type i)
add to iterator
Definition: json.hpp:6910
constexpr bool is_object() const noexcept
return whether value is an object
Definition: json.hpp:2436
constexpr bool is_number_integer() const noexcept
return whether value is an integer number
Definition: json.hpp:2358
a mutable random access iterator for the basic_json class
Definition: json.hpp:7025
static basic_json parse(std::istream &&i, parser_callback_t cb=nullptr)
deserialize from stream
Definition: json.hpp:5810
const_iterator operator++(int)
post-increment (it++)
Definition: json.hpp:6718
const_iterator cend() const noexcept
returns a const iterator to one past the last element
Definition: json.hpp:4298
ObjectType< StringType, basic_json, std::less< StringType >, AllocatorType< std::pair< const StringType, basic_json >>> object_t
a type for an object
Definition: json.hpp:348
STL namespace.
NumberUnsignedType number_unsigned_t
a type for a number (unsigned)
Definition: json.hpp:611
typename std::allocator_traits< allocator_type >::const_pointer const_pointer
the type of an element const pointer
Definition: json.hpp:231
basic_json(const number_integer_t val) noexcept
create an integer number (explicit)
Definition: json.hpp:1346
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:1712
static iteration_proxy< const_iterator > iterator_wrapper(const_reference cont)
wrapper to access iterator member functions in range-based for
Definition: json.hpp:4460
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:2067
constexpr value_t type() const noexcept
return the type of the JSON value (explicit)
Definition: json.hpp:2198
typename basic_json::value_type value_type
the type of the values when the iterator is dereferenced
Definition: json.hpp:6488
json_reverse_iterator(const typename base_iterator::iterator_type &it) noexcept
create reverse iterator from iterator
Definition: json.hpp:7175
PointerType get_ptr() noexcept
get a pointer value (implicit)
Definition: json.hpp:2958
constexpr bool is_string() const noexcept
return whether value is a string
Definition: json.hpp:2480
reference back()
access the last element
Definition: json.hpp:3750
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:6492
void push_back(const typename object_t::value_type &val)
add an object to an object
Definition: json.hpp:4859
void push_back(std::initializer_list< basic_json > init)
add an object to an object
Definition: json.hpp:4914
json_pointer(const std::string &s="")
create JSON pointer
Definition: json.hpp:8909
static basic_json parse(const string_t &s, parser_callback_t cb=nullptr)
deserialize from string
Definition: json.hpp:5773
const_reference operator[](T *(&key)[n]) const
read-only access specified object element
Definition: json.hpp:3504
iterator insert(const_iterator pos, const_iterator first, const_iterator last)
inserts elements
Definition: json.hpp:5068
basic_json(std::nullptr_t) noexcept
create a null object (explicitly)
Definition: json.hpp:1086
basic_json(InputIT first, InputIT last)
construct a JSON container given an iterator range
Definition: json.hpp:1822
reference operator[](difference_type n) const
access to successor
Definition: json.hpp:7136
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:3426
const_reference operator[](T *key) const
read-only access specified object element
Definition: json.hpp:3586
json_reverse_iterator operator+(difference_type i) const
add to iterator
Definition: json.hpp:7218
bool empty() const noexcept
checks whether the container is empty
Definition: json.hpp:4508
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:7246
const_iterator(const iterator &other) noexcept
copy constructor given a nonconst iterator
Definition: json.hpp:6530
basic_json(const CompatibleArrayType &val)
create an array (implicit)
Definition: json.hpp:1211
constexpr bool is_boolean() const noexcept
return whether value is a boolean
Definition: json.hpp:2299
const_reference at(size_type idx) const
access specified array element with bounds checking
Definition: json.hpp:3148
basic_json(size_type cnt, const basic_json &val)
construct an array with count copies of given value
Definition: json.hpp:1776
std::reverse_iterator< Base > base_iterator
shortcut to the reverse iterator adaptor
Definition: json.hpp:7170
const_reverse_iterator crbegin() const noexcept
returns a const reverse iterator to the last element
Definition: json.hpp:4402
iterator insert(const_iterator pos, std::initializer_list< basic_json > ilist)
inserts elements
Definition: json.hpp:5126
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:4959
friend bool operator>=(const_reference lhs, const_reference rhs) noexcept
comparison: greater than or equal
Definition: json.hpp:5679
friend bool operator<(const_reference lhs, const_reference rhs) noexcept
comparison: less than
Definition: json.hpp:5534
iterator & operator++()
pre-increment (++it)
Definition: json.hpp:7078
bool operator<(const const_iterator &other) const
comparison: smaller
Definition: json.hpp:6828
iterator operator++(int)
post-increment (it++)
Definition: json.hpp:7070
basic_json(basic_json &&other) noexcept
move constructor
Definition: json.hpp:2035
const_iterator operator--(int)
post-decrement (it–)
Definition: json.hpp:6755
reference at(const typename object_t::key_type &key)
access specified object element with bounds checking
Definition: json.hpp:3196
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:7046
object (unordered set of name/value pairs)
size_type max_size() const noexcept
returns the maximum possible number of elements
Definition: json.hpp:4638
~basic_json()
destructor
Definition: json.hpp:2095
iterator operator--(int)
post-decrement (it–)
Definition: json.hpp:7085
iterator operator-(difference_type i)
subtract from iterator
Definition: json.hpp:7122
const_iterator & operator--()
pre-decrement (–it)
Definition: json.hpp:6763
string_t dump(const int indent=-1) const
serialization
Definition: json.hpp:2164
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:985
AllocatorType< basic_json > allocator_type
the allocator type
Definition: json.hpp:226
StringType string_t
a type for a string
Definition: json.hpp:441
reference operator+=(const basic_json &val)
add an object to an array
Definition: json.hpp:4833
reference operator+=(std::initializer_list< basic_json > init)
add an object to an object
Definition: json.hpp:4931
difference_type operator-(const const_iterator &other) const
return difference
Definition: json.hpp:6926
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:4336
friend std::ostream & operator>>(const basic_json &j, std::ostream &o)
serialize to stream
Definition: json.hpp:5734
constexpr bool is_discarded() const noexcept
return whether value is discarded
Definition: json.hpp:2507
const_iterator begin() const noexcept
returns a const iterator to the first element
Definition: json.hpp:4197
difference_type operator-(const iterator &other) const
return difference
Definition: json.hpp:7130
constexpr bool is_array() const noexcept
return whether value is an array
Definition: json.hpp:2458
iterator(const iterator &other) noexcept
copy constructor
Definition: json.hpp:7041
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:6490
void swap(string_t &other)
exchanges the values
Definition: json.hpp:5263
basic_json(const CompatibleNumberIntegerType val) noexcept
create an integer number (implicit)
Definition: json.hpp:1412
const_reference front() const
access the first element
Definition: json.hpp:3716
bool operator>(const const_iterator &other) const
comparison: greater than
Definition: json.hpp:6864
constexpr const PointerType get_ptr() const noexcept
get a pointer value (implicit)
Definition: json.hpp:2973
pointer operator->() const
dereference the iterator
Definition: json.hpp:6683
NumberFloatType number_float_t
a type for a number (floating-point)
Definition: json.hpp:679
const_reverse_iterator crend() const noexcept
returns a const reverse iterator to one before the first
Definition: json.hpp:4431
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:5164
value_t
the JSON type enumeration
Definition: json.hpp:698
reverse_iterator rbegin() noexcept
returns an iterator to the reverse-beginning
Definition: json.hpp:4328
constexpr bool is_null() const noexcept
return whether value is null
Definition: json.hpp:2277
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:2874
void swap(array_t &other)
exchanges the values
Definition: json.hpp:5195
InteratorType erase(InteratorType first, InteratorType last)
remove elements given an iterator range
Definition: json.hpp:3926
ValueType value(const typename object_t::key_type &key, ValueType default_value) const
access specified object element with default value
Definition: json.hpp:3653
typename Base::reference reference
the reference type for the pointed-to element
Definition: json.hpp:7172
const_reference back() const
access the last element
Definition: json.hpp:3760
void push_back(basic_json &&val)
add an object to an array
Definition: json.hpp:4773
array (ordered collection of values)
constexpr bool is_number_unsigned() const noexcept
return whether value is an unsigned integer number
Definition: json.hpp:2386
json_reverse_iterator & operator++()
pre-increment (++it)
Definition: json.hpp:7191
static basic_json parse(std::istream &i, parser_callback_t cb=nullptr)
deserialize from stream
Definition: json.hpp:5802
friend bool operator==(const_reference lhs, const_reference rhs) noexcept
comparison: equal
Definition: json.hpp:5344
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:3679
ReferenceType get_ref() const
get a reference value (implicit)
Definition: json.hpp:3024
basic_json(const CompatibleNumberUnsignedType val) noexcept
create an unsigned number (implicit)
Definition: json.hpp:1471
reference operator*() const
return a reference to the value pointed to by the iterator
Definition: json.hpp:6643
friend bool operator<(const value_t lhs, const value_t rhs) noexcept
comparison operator for JSON types
Definition: json.hpp:5297
basic_json(const number_float_t val) noexcept
create a floating-point number (explicit)
Definition: json.hpp:1500
friend bool operator!=(const_reference v, std::nullptr_t) noexcept
comparison: not equal
Definition: json.hpp:5496
iterator operator+(difference_type i)
add to iterator
Definition: json.hpp:7114
basic_json(const CompatibleNumberFloatType val) noexcept
create an floating-point number (implicit)
Definition: json.hpp:1547
bool operator<=(const const_iterator &other) const
comparison: less than or equal
Definition: json.hpp:6858
InteratorType erase(InteratorType pos)
remove element given an iterator
Definition: json.hpp:3818
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:1620
iterator(pointer object) noexcept
constructor for a given JSON instance
Definition: json.hpp:7036
friend bool operator!=(std::nullptr_t, const_reference v) noexcept
comparison: not equal
Definition: json.hpp:5505
constexpr bool is_primitive() const noexcept
return whether type is primitive
Definition: json.hpp:2228
const_iterator & operator++()
pre-increment (++it)
Definition: json.hpp:6726
pointer operator->() const
dereference the iterator
Definition: json.hpp:7064
reference value() const
return the value of an iterator
Definition: json.hpp:7001
constexpr bool is_structured() const noexcept
return whether type is structured
Definition: json.hpp:2255
std::bidirectional_iterator_tag iterator_category
the category of the iterator
Definition: json.hpp:6496
basic_json(boolean_t val) noexcept
create a boolean (explicit)
Definition: json.hpp:1313
iterator end() noexcept
returns an iterator to one past the last element
Definition: json.hpp:4258
reverse_iterator rend() noexcept
returns an iterator to the reverse-end
Definition: json.hpp:4365
difference_type operator-(const json_reverse_iterator &other) const
return difference
Definition: json.hpp:7234
const_iterator find(typename object_t::key_type key) const
find an element in a JSON object
Definition: json.hpp:4115
iterator begin() noexcept
returns an iterator to the first element
Definition: json.hpp:4187
basic_json(const CompatibleObjectType &val)
create an object (implicit)
Definition: json.hpp:1144
const_iterator end() const noexcept
returns a const iterator to one past the last element
Definition: json.hpp:4268
friend bool operator>(const_reference lhs, const_reference rhs) noexcept
comparison: greater than
Definition: json.hpp:5657
bool operator>=(const const_iterator &other) const
comparison: greater than or equal
Definition: json.hpp:6870
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:6563
size_type erase(const typename object_t::key_type &key)
remove element from a JSON object given a key
Definition: json.hpp:4013
reference operator[](const typename object_t::key_type &key)
access specified object element
Definition: json.hpp:3378
object_t::key_type key() const
return the key of an object iterator
Definition: json.hpp:6986
reference operator+=(basic_json &&val)
add an object to an array
Definition: json.hpp:4799
reference operator[](difference_type n) const
access to successor
Definition: json.hpp:6950
a const random access iterator for the basic_json class
Definition: json.hpp:6481
constexpr bool is_number() const noexcept
return whether value is a number
Definition: json.hpp:2329
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:1929
typename basic_json::const_reference reference
defines a reference to the type iterated over (value_type)
Definition: json.hpp:6494
json_reverse_iterator operator++(int)
post-increment (it++)
Definition: json.hpp:7185
friend bool operator==(const_reference v, std::nullptr_t) noexcept
comparison: equal
Definition: json.hpp:5443
reference operator[](size_type idx)
access specified array element
Definition: json.hpp:3291
bool operator!=(const const_iterator &other) const
comparison: not equal
Definition: json.hpp:6822
json_reverse_iterator & operator+=(difference_type i)
add to iterator
Definition: json.hpp:7211
reference at(size_type idx)
access specified array element with bounds checking
Definition: json.hpp:3104
size_type size() const noexcept
returns the number of elements
Definition: json.hpp:4572
static iteration_proxy< iterator > iterator_wrapper(reference cont)
wrapper to access iterator member functions in range-based for
Definition: json.hpp:4452
iterator & operator-=(difference_type i)
subtract from iterator
Definition: json.hpp:7107
basic_json(const object_t &val)
create an object (explicit)
Definition: json.hpp:1109
basic_json(const number_unsigned_t val) noexcept
create an unsigned integer number (explicit)
Definition: json.hpp:1440
friend std::istream & operator<<(basic_json &j, std::istream &i)
deserialize from stream
Definition: json.hpp:5838
json_reverse_iterator(const base_iterator &it) noexcept
create reverse iterator from base class
Definition: json.hpp:7180
friend std::ostream & operator<<(std::ostream &o, const basic_json &j)
serialize to stream
Definition: json.hpp:5716
const_iterator(const const_iterator &other) noexcept
copy constructor
Definition: json.hpp:6558
iterator & operator--()
pre-decrement (–it)
Definition: json.hpp:7093
iterator insert(const_iterator pos, basic_json &&val)
inserts element
Definition: json.hpp:4986
ReferenceType get_ref()
get a reference value (implicit)
Definition: json.hpp:3009
const_iterator & operator-=(difference_type i)
subtract from iterator
Definition: json.hpp:6904
basic_json(const CompatibleStringType &val)
create a string (implicit)
Definition: json.hpp:1295
basic_json(const basic_json &other)
copy constructor
Definition: json.hpp:1960
reference operator[](T *key)
access specified object element
Definition: json.hpp:3537
parse_event_t
JSON callback events.
Definition: json.hpp:920