JSON for Modern C++  1.0.0-rc1
json.hpp
1 
38 #ifndef NLOHMANN_JSON_HPP
39 #define NLOHMANN_JSON_HPP
40 
41 #include <algorithm>
42 #include <array>
43 #include <ciso646>
44 #include <cmath>
45 #include <cstdio>
46 #include <functional>
47 #include <initializer_list>
48 #include <iomanip>
49 #include <iostream>
50 #include <iterator>
51 #include <limits>
52 #include <map>
53 #include <memory>
54 #include <sstream>
55 #include <string>
56 #include <type_traits>
57 #include <utility>
58 #include <vector>
59 
60 // enable ssize_t on MinGW
61 #ifdef __GNUC__
62  #ifdef __MINGW32__
63  #include <sys/types.h>
64  #endif
65 #endif
66 
67 // enable ssize_t for MSVC
68 #ifdef _MSC_VER
69  #include <basetsd.h>
70  using ssize_t = SSIZE_T;
71 #endif
72 
77 namespace nlohmann
78 {
79 
80 
84 namespace
85 {
90 template<typename T>
91 struct has_mapped_type
92 {
93  private:
94  template<typename C> static char test(typename C::mapped_type*);
95  template<typename C> static int test(...);
96  public:
97  enum { value = sizeof(test<T>(0)) == sizeof(char) };
98 };
99 
101 template<typename T>
102 static bool approx(const T a, const T b)
103 {
104  return not (a > b or a < b);
105 }
106 }
107 
172 template <
173  template<typename U, typename V, typename... Args> class ObjectType = std::map,
174  template<typename U, typename... Args> class ArrayType = std::vector,
175  class StringType = std::string,
176  class BooleanType = bool,
177  class NumberIntegerType = int64_t,
178  class NumberFloatType = double,
179  template<typename U> class AllocatorType = std::allocator
180  >
182 {
183  private:
185  using basic_json_t = basic_json<ObjectType,
186  ArrayType,
187  StringType,
188  BooleanType,
189  NumberIntegerType,
190  NumberFloatType,
191  AllocatorType>;
192 
193  public:
194 
196  // container types //
198 
201 
204 
207 
209  using const_reference = const value_type&;
210 
212  using difference_type = std::ptrdiff_t;
213 
215  using size_type = std::size_t;
216 
218  using allocator_type = AllocatorType<basic_json>;
219 
221  using pointer = typename std::allocator_traits<allocator_type>::pointer;
223  using const_pointer = typename std::allocator_traits<allocator_type>::const_pointer;
224 
225  // forward declaration
226  template<typename Base> class json_reverse_iterator;
227 
229  class iterator;
231  class const_iterator;
236 
238 
239 
244  {
245  return allocator_type();
246  }
247 
248 
250  // JSON value data types //
252 
255 
324  using object_t = ObjectType<StringType,
325  basic_json,
326  std::less<StringType>,
327  AllocatorType<std::pair<const StringType,
328  basic_json>>>;
329 
371  using array_t = ArrayType<basic_json, AllocatorType<basic_json>>;
372 
417  using string_t = StringType;
418 
443  using boolean_t = BooleanType;
444 
511  using number_integer_t = NumberIntegerType;
512 
576  using number_float_t = NumberFloatType;
577 
579 
580 
582  // JSON type enumeration //
584 
595  enum class value_t : uint8_t
596  {
597  null,
598  object,
599  array,
600  string,
601  boolean,
603  number_float,
604  discarded
605  };
606 
607 
608  private:
610  template<typename T, typename... Args>
611  static T* create(Args&& ... args)
612  {
613  AllocatorType<T> alloc;
614  auto deleter = [&](T * object)
615  {
616  alloc.deallocate(object, 1);
617  };
618  std::unique_ptr<T, decltype(deleter)> object(alloc.allocate(1), deleter);
619  alloc.construct(object.get(), std::forward<Args>(args)...);
620  return object.release();
621  }
622 
624  // JSON value storage //
626 
634  union json_value
635  {
637  object_t* object;
639  array_t* array;
641  string_t* string;
643  boolean_t boolean;
645  number_integer_t number_integer;
647  number_float_t number_float;
648 
650  json_value() noexcept = default;
652  json_value(boolean_t v) noexcept : boolean(v) {}
654  json_value(number_integer_t v) noexcept : number_integer(v) {}
656  json_value(number_float_t v) noexcept : number_float(v) {}
658  json_value(value_t t)
659  {
660  switch (t)
661  {
662  case value_t::object:
663  {
664  object = create<object_t>();
665  break;
666  }
667 
668  case value_t::array:
669  {
670  array = create<array_t>();
671  break;
672  }
673 
674  case value_t::string:
675  {
676  string = create<string_t>("");
677  break;
678  }
679 
680  case value_t::boolean:
681  {
682  boolean = boolean_t(false);
683  break;
684  }
685 
687  {
688  number_integer = number_integer_t(0);
689  break;
690  }
691 
693  {
694  number_float = number_float_t(0.0);
695  break;
696  }
697 
698  default:
699  {
700  break;
701  }
702  }
703  }
704 
706  json_value(const string_t& value)
707  {
708  string = create<string_t>(value);
709  }
710 
712  json_value(const object_t& value)
713  {
714  object = create<object_t>(value);
715  }
716 
718  json_value(const array_t& value)
719  {
720  array = create<array_t>(value);
721  }
722  };
723 
724 
725  public:
727  // JSON parser callback //
729 
738  enum class parse_event_t : uint8_t
739  {
741  object_start,
743  object_end,
745  array_start,
747  array_end,
749  key,
751  value
752  };
753 
803  using parser_callback_t = std::function<bool(int depth, parse_event_t event, basic_json& parsed)>;
804 
805 
807  // constructors //
809 
844  : m_type(value), m_value(value)
845  {}
846 
866  basic_json() noexcept = default;
867 
887  basic_json(std::nullptr_t) noexcept
888  : basic_json(value_t::null)
889  {}
890 
911  : m_type(value_t::object), m_value(value)
912  {}
913 
937  template <class CompatibleObjectType, typename
938  std::enable_if<
939  std::is_constructible<typename object_t::key_type, typename CompatibleObjectType::key_type>::value and
940  std::is_constructible<basic_json, typename CompatibleObjectType::mapped_type>::value, int>::type
941  = 0>
942  basic_json(const CompatibleObjectType& value)
943  : m_type(value_t::object)
944  {
945  using std::begin;
946  using std::end;
947  m_value.object = create<object_t>(begin(value), end(value));
948  }
949 
970  : m_type(value_t::array), m_value(value)
971  {}
972 
996  template <class CompatibleArrayType, typename
997  std::enable_if<
998  not std::is_same<CompatibleArrayType, typename basic_json_t::iterator>::value and
999  not std::is_same<CompatibleArrayType, typename basic_json_t::const_iterator>::value and
1000  not std::is_same<CompatibleArrayType, typename basic_json_t::reverse_iterator>::value and
1001  not std::is_same<CompatibleArrayType, typename basic_json_t::const_reverse_iterator>::value and
1002  not std::is_same<CompatibleArrayType, typename array_t::iterator>::value and
1003  not std::is_same<CompatibleArrayType, typename array_t::const_iterator>::value and
1004  std::is_constructible<basic_json, typename CompatibleArrayType::value_type>::value, int>::type
1005  = 0>
1006  basic_json(const CompatibleArrayType& value)
1007  : m_type(value_t::array)
1008  {
1009  using std::begin;
1010  using std::end;
1011  m_value.array = create<array_t>(begin(value), end(value));
1012  }
1013 
1036  : m_type(value_t::string), m_value(value)
1037  {}
1038 
1059  basic_json(const typename string_t::value_type* value)
1060  : basic_json(string_t(value))
1061  {}
1062 
1086  template <class CompatibleStringType, typename
1087  std::enable_if<
1088  std::is_constructible<string_t, CompatibleStringType>::value, int>::type
1089  = 0>
1090  basic_json(const CompatibleStringType& value)
1091  : basic_json(string_t(value))
1092  {}
1093 
1109  : m_type(value_t::boolean), m_value(value)
1110  {}
1111 
1137  template<typename T,
1138  typename std::enable_if<
1139  not (std::is_same<T, int>::value)
1140  and std::is_same<T, number_integer_t>::value
1141  , int>::type = 0>
1142  basic_json(const number_integer_t value)
1143  : m_type(value_t::number_integer), m_value(value)
1144  {}
1145 
1171  basic_json(const int value)
1172  : m_type(value_t::number_integer),
1173  m_value(static_cast<number_integer_t>(value))
1174  {}
1175 
1201  template<typename CompatibleNumberIntegerType, typename
1202  std::enable_if<
1203  std::is_constructible<number_integer_t, CompatibleNumberIntegerType>::value and
1204  std::numeric_limits<CompatibleNumberIntegerType>::is_integer, CompatibleNumberIntegerType>::type
1205  = 0>
1206  basic_json(const CompatibleNumberIntegerType value) noexcept
1207  : m_type(value_t::number_integer),
1208  m_value(static_cast<number_integer_t>(value))
1209  {}
1210 
1236  : m_type(value_t::number_float), m_value(value)
1237  {
1238  // replace infinity and NAN by null
1239  if (not std::isfinite(value))
1240  {
1241  m_type = value_t::null;
1242  m_value = json_value();
1243  }
1244  }
1245 
1276  template<typename CompatibleNumberFloatType, typename = typename
1277  std::enable_if<
1278  std::is_constructible<number_float_t, CompatibleNumberFloatType>::value and
1279  std::is_floating_point<CompatibleNumberFloatType>::value>::type
1280  >
1281  basic_json(const CompatibleNumberFloatType value) noexcept
1283  {}
1284 
1353  basic_json(std::initializer_list<basic_json> init,
1354  bool type_deduction = true,
1355  value_t manual_type = value_t::array)
1356  {
1357  // the initializer list could describe an object
1358  bool is_object = true;
1359 
1360  // check if each element is an array with two elements whose first element
1361  // is a string
1362  for (const auto& element : init)
1363  {
1364  if (not element.is_array() or element.size() != 2
1365  or not element[0].is_string())
1366  {
1367  // we found an element that makes it impossible to use the
1368  // initializer list as object
1369  is_object = false;
1370  break;
1371  }
1372  }
1373 
1374  // adjust type if type deduction is not wanted
1375  if (not type_deduction)
1376  {
1377  // if array is wanted, do not create an object though possible
1378  if (manual_type == value_t::array)
1379  {
1380  is_object = false;
1381  }
1382 
1383  // if object is wanted but impossible, throw an exception
1384  if (manual_type == value_t::object and not is_object)
1385  {
1386  throw std::domain_error("cannot create object from initializer list");
1387  }
1388  }
1389 
1390  if (is_object)
1391  {
1392  // the initializer list is a list of pairs -> create object
1393  m_type = value_t::object;
1394  m_value = value_t::object;
1395 
1396  for (auto& element : init)
1397  {
1398  m_value.object->emplace(std::move(*(element[0].m_value.string)), std::move(element[1]));
1399  }
1400  }
1401  else
1402  {
1403  // the initializer list describes an array -> create array
1404  m_type = value_t::array;
1405  m_value.array = create<array_t>(std::move(init));
1406  }
1407  }
1408 
1443  static basic_json array(std::initializer_list<basic_json> init =
1444  std::initializer_list<basic_json>())
1445  {
1446  return basic_json(init, false, value_t::array);
1447  }
1448 
1483  static basic_json object(std::initializer_list<basic_json> init =
1484  std::initializer_list<basic_json>())
1485  {
1486  return basic_json(init, false, value_t::object);
1487  }
1488 
1507  basic_json(size_type count, const basic_json& value)
1508  : m_type(value_t::array)
1509  {
1510  m_value.array = create<array_t>(count, value);
1511  }
1512 
1545  template <class InputIT, typename
1546  std::enable_if<
1547  std::is_same<InputIT, typename basic_json_t::iterator>::value or
1548  std::is_same<InputIT, typename basic_json_t::const_iterator>::value
1549  , int>::type
1550  = 0>
1551  basic_json(InputIT first, InputIT last) : m_type(first.m_object->m_type)
1552  {
1553  // make sure iterator fits the current value
1554  if (first.m_object != last.m_object)
1555  {
1556  throw std::domain_error("iterators are not compatible");
1557  }
1558 
1559  // check if iterator range is complete for primitive values
1560  switch (m_type)
1561  {
1562  case value_t::boolean:
1563  case value_t::number_float:
1565  case value_t::string:
1566  {
1567  if (not first.m_it.primitive_iterator.is_begin() or not last.m_it.primitive_iterator.is_end())
1568  {
1569  throw std::out_of_range("iterators out of range");
1570  }
1571  break;
1572  }
1573 
1574  default:
1575  {
1576  break;
1577  }
1578  }
1579 
1580  switch (m_type)
1581  {
1583  {
1584  m_value.number_integer = first.m_object->m_value.number_integer;
1585  break;
1586  }
1587 
1588  case value_t::number_float:
1589  {
1590  m_value.number_float = first.m_object->m_value.number_float;
1591  break;
1592  }
1593 
1594  case value_t::boolean:
1595  {
1596  m_value.boolean = first.m_object->m_value.boolean;
1597  break;
1598  }
1599 
1600  case value_t::string:
1601  {
1602  m_value = *first.m_object->m_value.string;
1603  break;
1604  }
1605 
1606  case value_t::object:
1607  {
1608  m_value.object = create<object_t>(first.m_it.object_iterator, last.m_it.object_iterator);
1609  break;
1610  }
1611 
1612  case value_t::array:
1613  {
1614  m_value.array = create<array_t>(first.m_it.array_iterator, last.m_it.array_iterator);
1615  break;
1616  }
1617 
1618  default:
1619  {
1620  throw std::domain_error("cannot use construct with iterators from " + first.m_object->type_name());
1621  }
1622  }
1623  }
1624 
1626  // other constructors and destructor //
1628 
1649  basic_json(const basic_json& other)
1650  : m_type(other.m_type)
1651  {
1652  switch (m_type)
1653  {
1654  case value_t::object:
1655  {
1656  m_value = *other.m_value.object;
1657  break;
1658  }
1659 
1660  case value_t::array:
1661  {
1662  m_value = *other.m_value.array;
1663  break;
1664  }
1665 
1666  case value_t::string:
1667  {
1668  m_value = *other.m_value.string;
1669  break;
1670  }
1671 
1672  case value_t::boolean:
1673  {
1674  m_value = other.m_value.boolean;
1675  break;
1676  }
1677 
1679  {
1680  m_value = other.m_value.number_integer;
1681  break;
1682  }
1683 
1684  case value_t::number_float:
1685  {
1686  m_value = other.m_value.number_float;
1687  break;
1688  }
1689 
1690  default:
1691  {
1692  break;
1693  }
1694  }
1695  }
1696 
1715  basic_json(basic_json&& other) noexcept
1716  : m_type(std::move(other.m_type)),
1717  m_value(std::move(other.m_value))
1718  {
1719  // invalidate payload
1720  other.m_type = value_t::null;
1721  other.m_value = {};
1722  }
1723 
1743  reference& operator=(basic_json other) noexcept (
1744  std::is_nothrow_move_constructible<value_t>::value and
1745  std::is_nothrow_move_assignable<value_t>::value and
1746  std::is_nothrow_move_constructible<json_value>::value and
1747  std::is_nothrow_move_assignable<json_value>::value
1748  )
1749  {
1750  using std::swap;
1751  swap(m_type, other.m_type);
1752  swap(m_value, other.m_value);
1753  return *this;
1754  }
1755 
1770  {
1771  switch (m_type)
1772  {
1773  case value_t::object:
1774  {
1775  AllocatorType<object_t> alloc;
1776  alloc.destroy(m_value.object);
1777  alloc.deallocate(m_value.object, 1);
1778  break;
1779  }
1780 
1781  case value_t::array:
1782  {
1783  AllocatorType<array_t> alloc;
1784  alloc.destroy(m_value.array);
1785  alloc.deallocate(m_value.array, 1);
1786  break;
1787  }
1788 
1789  case value_t::string:
1790  {
1791  AllocatorType<string_t> alloc;
1792  alloc.destroy(m_value.string);
1793  alloc.deallocate(m_value.string, 1);
1794  break;
1795  }
1796 
1797  default:
1798  {
1799  // all other types need no specific destructor
1800  break;
1801  }
1802  }
1803  }
1804 
1805 
1806  public:
1808  // object inspection //
1810 
1813 
1835  string_t dump(const int indent = -1) const
1836  {
1837  std::stringstream ss;
1838 
1839  if (indent >= 0)
1840  {
1841  dump(ss, true, static_cast<unsigned int>(indent));
1842  }
1843  else
1844  {
1845  dump(ss, false, 0);
1846  }
1847 
1848  return ss.str();
1849  }
1850 
1864  value_t type() const noexcept
1865  {
1866  return m_type;
1867  }
1868 
1883  bool is_primitive() const noexcept
1884  {
1885  return is_null() or is_string() or is_boolean() or is_number();
1886  }
1887 
1901  bool is_structured() const noexcept
1902  {
1903  return is_array() or is_object();
1904  }
1905 
1918  bool is_null() const noexcept
1919  {
1920  return m_type == value_t::null;
1921  }
1922 
1935  bool is_boolean() const noexcept
1936  {
1937  return m_type == value_t::boolean;
1938  }
1939 
1953  bool is_number() const noexcept
1954  {
1955  return is_number_integer() or is_number_float();
1956  }
1957 
1971  bool is_number_integer() const noexcept
1972  {
1973  return m_type == value_t::number_integer;
1974  }
1975 
1989  bool is_number_float() const noexcept
1990  {
1991  return m_type == value_t::number_float;
1992  }
1993 
2006  bool is_object() const noexcept
2007  {
2008  return m_type == value_t::object;
2009  }
2010 
2023  bool is_array() const noexcept
2024  {
2025  return m_type == value_t::array;
2026  }
2027 
2040  bool is_string() const noexcept
2041  {
2042  return m_type == value_t::string;
2043  }
2044 
2062  bool is_discarded() const noexcept
2063  {
2064  return m_type == value_t::discarded;
2065  }
2066 
2080  operator value_t() const noexcept
2081  {
2082  return m_type;
2083  }
2084 
2086 
2087  private:
2089  // value access //
2091 
2093  template <class T, typename
2094  std::enable_if<
2095  std::is_convertible<typename object_t::key_type, typename T::key_type>::value and
2096  std::is_convertible<basic_json_t, typename T::mapped_type>::value
2097  , int>::type = 0>
2098  T get_impl(T*) const
2099  {
2100  if (is_object())
2101  {
2102  return T(m_value.object->begin(), m_value.object->end());
2103  }
2104  else
2105  {
2106  throw std::domain_error("type must be object, but is " + type_name());
2107  }
2108  }
2109 
2111  object_t get_impl(object_t*) const
2112  {
2113  if (is_object())
2114  {
2115  return *(m_value.object);
2116  }
2117  else
2118  {
2119  throw std::domain_error("type must be object, but is " + type_name());
2120  }
2121  }
2122 
2124  template <class T, typename
2125  std::enable_if<
2126  std::is_convertible<basic_json_t, typename T::value_type>::value and
2127  not std::is_same<basic_json_t, typename T::value_type>::value and
2128  not std::is_arithmetic<T>::value and
2129  not std::is_convertible<std::string, T>::value and
2130  not has_mapped_type<T>::value
2131  , int>::type = 0>
2132  T get_impl(T*) const
2133  {
2134  if (is_array())
2135  {
2136  T to_vector;
2137  std::transform(m_value.array->begin(), m_value.array->end(),
2138  std::inserter(to_vector, to_vector.end()), [](basic_json i)
2139  {
2140  return i.get<typename T::value_type>();
2141  });
2142  return to_vector;
2143  }
2144  else
2145  {
2146  throw std::domain_error("type must be array, but is " + type_name());
2147  }
2148  }
2149 
2151  template <class T, typename
2152  std::enable_if<
2153  std::is_convertible<basic_json_t, T>::value and
2154  not std::is_same<basic_json_t, T>::value
2155  , int>::type = 0>
2156  std::vector<T> get_impl(std::vector<T>*) const
2157  {
2158  if (is_array())
2159  {
2160  std::vector<T> to_vector;
2161  to_vector.reserve(m_value.array->size());
2162  std::transform(m_value.array->begin(), m_value.array->end(),
2163  std::inserter(to_vector, to_vector.end()), [](basic_json i)
2164  {
2165  return i.get<T>();
2166  });
2167  return to_vector;
2168  }
2169  else
2170  {
2171  throw std::domain_error("type must be array, but is " + type_name());
2172  }
2173  }
2174 
2176  template <class T, typename
2177  std::enable_if<
2178  std::is_same<basic_json, typename T::value_type>::value and
2179  not has_mapped_type<T>::value
2180  , int>::type = 0>
2181  T get_impl(T*) const
2182  {
2183  if (is_array())
2184  {
2185  return T(m_value.array->begin(), m_value.array->end());
2186  }
2187  else
2188  {
2189  throw std::domain_error("type must be array, but is " + type_name());
2190  }
2191  }
2192 
2194  array_t get_impl(array_t*) const
2195  {
2196  if (is_array())
2197  {
2198  return *(m_value.array);
2199  }
2200  else
2201  {
2202  throw std::domain_error("type must be array, but is " + type_name());
2203  }
2204  }
2205 
2207  template <typename T, typename
2208  std::enable_if<
2209  std::is_convertible<string_t, T>::value
2210  , int>::type = 0>
2211  T get_impl(T*) const
2212  {
2213  if (is_string())
2214  {
2215  return *m_value.string;
2216  }
2217  else
2218  {
2219  throw std::domain_error("type must be string, but is " + type_name());
2220  }
2221  }
2222 
2224  template<typename T, typename
2225  std::enable_if<
2226  std::is_arithmetic<T>::value
2227  , int>::type = 0>
2228  T get_impl(T*) const
2229  {
2230  switch (m_type)
2231  {
2233  {
2234  return static_cast<T>(m_value.number_integer);
2235  }
2236 
2237  case value_t::number_float:
2238  {
2239  return static_cast<T>(m_value.number_float);
2240  }
2241 
2242  default:
2243  {
2244  throw std::domain_error("type must be number, but is " + type_name());
2245  }
2246  }
2247  }
2248 
2250  boolean_t get_impl(boolean_t*) const
2251  {
2252  if (is_boolean())
2253  {
2254  return m_value.boolean;
2255  }
2256  else
2257  {
2258  throw std::domain_error("type must be boolean, but is " + type_name());
2259  }
2260  }
2261 
2263  object_t* get_impl_ptr(object_t*) noexcept
2264  {
2265  return is_object() ? m_value.object : nullptr;
2266  }
2267 
2269  const object_t* get_impl_ptr(const object_t*) const noexcept
2270  {
2271  return is_object() ? m_value.object : nullptr;
2272  }
2273 
2275  array_t* get_impl_ptr(array_t*) noexcept
2276  {
2277  return is_array() ? m_value.array : nullptr;
2278  }
2279 
2281  const array_t* get_impl_ptr(const array_t*) const noexcept
2282  {
2283  return is_array() ? m_value.array : nullptr;
2284  }
2285 
2287  string_t* get_impl_ptr(string_t*) noexcept
2288  {
2289  return is_string() ? m_value.string : nullptr;
2290  }
2291 
2293  const string_t* get_impl_ptr(const string_t*) const noexcept
2294  {
2295  return is_string() ? m_value.string : nullptr;
2296  }
2297 
2299  boolean_t* get_impl_ptr(boolean_t*) noexcept
2300  {
2301  return is_boolean() ? &m_value.boolean : nullptr;
2302  }
2303 
2305  const boolean_t* get_impl_ptr(const boolean_t*) const noexcept
2306  {
2307  return is_boolean() ? &m_value.boolean : nullptr;
2308  }
2309 
2311  number_integer_t* get_impl_ptr(number_integer_t*) noexcept
2312  {
2313  return is_number_integer() ? &m_value.number_integer : nullptr;
2314  }
2315 
2317  const number_integer_t* get_impl_ptr(const number_integer_t*) const noexcept
2318  {
2319  return is_number_integer() ? &m_value.number_integer : nullptr;
2320  }
2321 
2323  number_float_t* get_impl_ptr(number_float_t*) noexcept
2324  {
2325  return is_number_float() ? &m_value.number_float : nullptr;
2326  }
2327 
2329  const number_float_t* get_impl_ptr(const number_float_t*) const noexcept
2330  {
2331  return is_number_float() ? &m_value.number_float : nullptr;
2332  }
2333 
2334  public:
2335 
2338 
2370  template<typename ValueType, typename
2371  std::enable_if<
2372  not std::is_pointer<ValueType>::value
2373  , int>::type = 0>
2374  ValueType get() const
2375  {
2376  return get_impl(static_cast<ValueType*>(nullptr));
2377  }
2378 
2404  template<typename PointerType, typename
2405  std::enable_if<
2406  std::is_pointer<PointerType>::value
2407  , int>::type = 0>
2408  PointerType get() noexcept
2409  {
2410  // delegate the call to get_ptr
2411  return get_ptr<PointerType>();
2412  }
2413 
2418  template<typename PointerType, typename
2419  std::enable_if<
2420  std::is_pointer<PointerType>::value
2421  , int>::type = 0>
2422  const PointerType get() const noexcept
2423  {
2424  // delegate the call to get_ptr
2425  return get_ptr<PointerType>();
2426  }
2427 
2451  template<typename PointerType, typename
2452  std::enable_if<
2453  std::is_pointer<PointerType>::value
2454  , int>::type = 0>
2455  PointerType get_ptr() noexcept
2456  {
2457  // delegate the call to get_impl_ptr<>()
2458  return get_impl_ptr(static_cast<PointerType>(nullptr));
2459  }
2460 
2465  template<typename PointerType, typename
2466  std::enable_if<
2467  std::is_pointer<PointerType>::value
2468  and std::is_const<typename std::remove_pointer<PointerType>::type>::value
2469  , int>::type = 0>
2470  const PointerType get_ptr() const noexcept
2471  {
2472  // delegate the call to get_impl_ptr<>() const
2473  return get_impl_ptr(static_cast<const PointerType>(nullptr));
2474  }
2475 
2500  template<typename ValueType, typename
2501  std::enable_if<
2502  not std::is_pointer<ValueType>::value
2503  , int>::type = 0>
2504  operator ValueType() const
2505  {
2506  // delegate the call to get<>() const
2507  return get<ValueType>();
2508  }
2509 
2511 
2512 
2514  // element access //
2516 
2519 
2540  {
2541  // at only works for arrays
2542  if (is_array())
2543  {
2544  return m_value.array->at(idx);
2545  }
2546  else
2547  {
2548  throw std::domain_error("cannot use at() with " + type_name());
2549  }
2550  }
2551 
2572  {
2573  // at only works for arrays
2574  if (is_array())
2575  {
2576  return m_value.array->at(idx);
2577  }
2578  else
2579  {
2580  throw std::domain_error("cannot use at() with " + type_name());
2581  }
2582  }
2583 
2607  reference at(const typename object_t::key_type& key)
2608  {
2609  // at only works for objects
2610  if (is_object())
2611  {
2612  return m_value.object->at(key);
2613  }
2614  else
2615  {
2616  throw std::domain_error("cannot use at() with " + type_name());
2617  }
2618  }
2619 
2643  const_reference at(const typename object_t::key_type& key) const
2644  {
2645  // at only works for objects
2646  if (is_object())
2647  {
2648  return m_value.object->at(key);
2649  }
2650  else
2651  {
2652  throw std::domain_error("cannot use at() with " + type_name());
2653  }
2654  }
2655 
2679  {
2680  // implicitly convert null to object
2681  if (is_null())
2682  {
2683  m_type = value_t::array;
2684  m_value.array = create<array_t>();
2685  }
2686 
2687  // [] only works for arrays
2688  if (is_array())
2689  {
2690  for (size_t i = m_value.array->size(); i <= idx; ++i)
2691  {
2692  m_value.array->push_back(basic_json());
2693  }
2694 
2695  return m_value.array->operator[](idx);
2696  }
2697  else
2698  {
2699  throw std::domain_error("cannot use operator[] with " + type_name());
2700  }
2701  }
2702 
2720  {
2721  // at only works for arrays
2722  if (is_array())
2723  {
2724  return m_value.array->operator[](idx);
2725  }
2726  else
2727  {
2728  throw std::domain_error("cannot use operator[] with " + type_name());
2729  }
2730  }
2731 
2756  reference operator[](const typename object_t::key_type& key)
2757  {
2758  // implicitly convert null to object
2759  if (is_null())
2760  {
2761  m_type = value_t::object;
2762  m_value.object = create<object_t>();
2763  }
2764 
2765  // [] only works for objects
2766  if (is_object())
2767  {
2768  return m_value.object->operator[](key);
2769  }
2770  else
2771  {
2772  throw std::domain_error("cannot use operator[] with " + type_name());
2773  }
2774  }
2775 
2802  template<typename T, std::size_t n>
2803  reference operator[](const T (&key)[n])
2804  {
2805  // implicitly convert null to object
2806  if (is_null())
2807  {
2808  m_type = value_t::object;
2809  m_value = value_t::object;
2810  }
2811 
2812  // at only works for objects
2813  if (is_object())
2814  {
2815  return m_value.object->operator[](key);
2816  }
2817  else
2818  {
2819  throw std::domain_error("cannot use operator[] with " + type_name());
2820  }
2821  }
2822 
2868  template <class ValueType, typename
2869  std::enable_if<
2870  std::is_convertible<basic_json_t, ValueType>::value
2871  , int>::type = 0>
2872  ValueType value(const typename object_t::key_type& key, ValueType default_value) const
2873  {
2874  // at only works for objects
2875  if (is_object())
2876  {
2877  // if key is found, return value and given default value otherwise
2878  const auto it = find(key);
2879  if (it != end())
2880  {
2881  return *it;
2882  }
2883  else
2884  {
2885  return default_value;
2886  }
2887  }
2888  else
2889  {
2890  throw std::domain_error("cannot use value() with " + type_name());
2891  }
2892  }
2893 
2898  string_t value(const typename object_t::key_type& key, const char* default_value) const
2899  {
2900  return value(key, string_t(default_value));
2901  }
2902 
2922  {
2923  return *begin();
2924  }
2925 
2930  {
2931  return *cbegin();
2932  }
2933 
2954  {
2955  auto tmp = end();
2956  --tmp;
2957  return *tmp;
2958  }
2959 
2964  {
2965  auto tmp = cend();
2966  --tmp;
2967  return *tmp;
2968  }
2969 
3003  template <class InteratorType, typename
3004  std::enable_if<
3005  std::is_same<InteratorType, typename basic_json_t::iterator>::value or
3006  std::is_same<InteratorType, typename basic_json_t::const_iterator>::value
3007  , int>::type
3008  = 0>
3009  InteratorType erase(InteratorType pos)
3010  {
3011  // make sure iterator fits the current value
3012  if (this != pos.m_object)
3013  {
3014  throw std::domain_error("iterator does not fit current value");
3015  }
3016 
3017  InteratorType result = end();
3018 
3019  switch (m_type)
3020  {
3021  case value_t::boolean:
3022  case value_t::number_float:
3024  case value_t::string:
3025  {
3026  if (not pos.m_it.primitive_iterator.is_begin())
3027  {
3028  throw std::out_of_range("iterator out of range");
3029  }
3030 
3031  if (is_string())
3032  {
3033  delete m_value.string;
3034  m_value.string = nullptr;
3035  }
3036 
3037  m_type = value_t::null;
3038  break;
3039  }
3040 
3041  case value_t::object:
3042  {
3043  result.m_it.object_iterator = m_value.object->erase(pos.m_it.object_iterator);
3044  break;
3045  }
3046 
3047  case value_t::array:
3048  {
3049  result.m_it.array_iterator = m_value.array->erase(pos.m_it.array_iterator);
3050  break;
3051  }
3052 
3053  default:
3054  {
3055  throw std::domain_error("cannot use erase() with " + type_name());
3056  }
3057  }
3058 
3059  return result;
3060  }
3061 
3096  template <class InteratorType, typename
3097  std::enable_if<
3098  std::is_same<InteratorType, typename basic_json_t::iterator>::value or
3099  std::is_same<InteratorType, typename basic_json_t::const_iterator>::value
3100  , int>::type
3101  = 0>
3102  InteratorType erase(InteratorType first, InteratorType last)
3103  {
3104  // make sure iterator fits the current value
3105  if (this != first.m_object or this != last.m_object)
3106  {
3107  throw std::domain_error("iterators do not fit current value");
3108  }
3109 
3110  InteratorType result = end();
3111 
3112  switch (m_type)
3113  {
3114  case value_t::boolean:
3115  case value_t::number_float:
3117  case value_t::string:
3118  {
3119  if (not first.m_it.primitive_iterator.is_begin() or not last.m_it.primitive_iterator.is_end())
3120  {
3121  throw std::out_of_range("iterators out of range");
3122  }
3123 
3124  if (is_string())
3125  {
3126  delete m_value.string;
3127  m_value.string = nullptr;
3128  }
3129 
3130  m_type = value_t::null;
3131  break;
3132  }
3133 
3134  case value_t::object:
3135  {
3136  result.m_it.object_iterator = m_value.object->erase(first.m_it.object_iterator,
3137  last.m_it.object_iterator);
3138  break;
3139  }
3140 
3141  case value_t::array:
3142  {
3143  result.m_it.array_iterator = m_value.array->erase(first.m_it.array_iterator,
3144  last.m_it.array_iterator);
3145  break;
3146  }
3147 
3148  default:
3149  {
3150  throw std::domain_error("cannot use erase with " + type_name());
3151  }
3152  }
3153 
3154  return result;
3155  }
3156 
3174  size_type erase(const typename object_t::key_type& key)
3175  {
3176  // this erase only works for objects
3177  if (is_object())
3178  {
3179  return m_value.object->erase(key);
3180  }
3181  else
3182  {
3183  throw std::domain_error("cannot use erase() with " + type_name());
3184  }
3185  }
3186 
3201  void erase(const size_type idx)
3202  {
3203  // this erase only works for arrays
3204  if (is_array())
3205  {
3206  if (idx >= size())
3207  {
3208  throw std::out_of_range("index out of range");
3209  }
3210 
3211  m_value.array->erase(m_value.array->begin() + static_cast<difference_type>(idx));
3212  }
3213  else
3214  {
3215  throw std::domain_error("cannot use erase() with " + type_name());
3216  }
3217  }
3218 
3234  iterator find(typename object_t::key_type key)
3235  {
3236  auto result = end();
3237 
3238  if (is_object())
3239  {
3240  result.m_it.object_iterator = m_value.object->find(key);
3241  }
3242 
3243  return result;
3244  }
3245 
3250  const_iterator find(typename object_t::key_type key) const
3251  {
3252  auto result = cend();
3253 
3254  if (is_object())
3255  {
3256  result.m_it.object_iterator = m_value.object->find(key);
3257  }
3258 
3259  return result;
3260  }
3261 
3278  size_type count(typename object_t::key_type key) const
3279  {
3280  // return 0 for all nonobject types
3281  return (is_object()) ? m_value.object->count(key) : 0;
3282  }
3283 
3285 
3286 
3288  // iterators //
3290 
3293 
3311  {
3312  iterator result(this);
3313  result.set_begin();
3314  return result;
3315  }
3316 
3321  {
3322  return cbegin();
3323  }
3324 
3343  {
3344  const_iterator result(this);
3345  result.set_begin();
3346  return result;
3347  }
3348 
3366  {
3367  iterator result(this);
3368  result.set_end();
3369  return result;
3370  }
3371 
3376  {
3377  return cend();
3378  }
3379 
3398  {
3399  const_iterator result(this);
3400  result.set_end();
3401  return result;
3402  }
3403 
3420  {
3421  return reverse_iterator(end());
3422  }
3423 
3428  {
3429  return crbegin();
3430  }
3431 
3449  {
3450  return reverse_iterator(begin());
3451  }
3452 
3457  {
3458  return crend();
3459  }
3460 
3478  {
3479  return const_reverse_iterator(cend());
3480  }
3481 
3499  {
3500  return const_reverse_iterator(cbegin());
3501  }
3502 
3504 
3505 
3507  // capacity //
3509 
3512 
3540  bool empty() const noexcept
3541  {
3542  switch (m_type)
3543  {
3544  case value_t::null:
3545  {
3546  return true;
3547  }
3548 
3549  case value_t::array:
3550  {
3551  return m_value.array->empty();
3552  }
3553 
3554  case value_t::object:
3555  {
3556  return m_value.object->empty();
3557  }
3558 
3559  default:
3560  {
3561  // all other types are nonempty
3562  return false;
3563  }
3564  }
3565  }
3566 
3594  size_type size() const noexcept
3595  {
3596  switch (m_type)
3597  {
3598  case value_t::null:
3599  {
3600  return 0;
3601  }
3602 
3603  case value_t::array:
3604  {
3605  return m_value.array->size();
3606  }
3607 
3608  case value_t::object:
3609  {
3610  return m_value.object->size();
3611  }
3612 
3613  default:
3614  {
3615  // all other types have size 1
3616  return 1;
3617  }
3618  }
3619  }
3620 
3651  size_type max_size() const noexcept
3652  {
3653  switch (m_type)
3654  {
3655  case value_t::array:
3656  {
3657  return m_value.array->max_size();
3658  }
3659 
3660  case value_t::object:
3661  {
3662  return m_value.object->max_size();
3663  }
3664 
3665  default:
3666  {
3667  // all other types have max_size() == size()
3668  return size();
3669  }
3670  }
3671  }
3672 
3674 
3675 
3677  // modifiers //
3679 
3682 
3706  void clear() noexcept
3707  {
3708  switch (m_type)
3709  {
3711  {
3712  m_value.number_integer = 0;
3713  break;
3714  }
3715 
3716  case value_t::number_float:
3717  {
3718  m_value.number_float = 0.0;
3719  break;
3720  }
3721 
3722  case value_t::boolean:
3723  {
3724  m_value.boolean = false;
3725  break;
3726  }
3727 
3728  case value_t::string:
3729  {
3730  m_value.string->clear();
3731  break;
3732  }
3733 
3734  case value_t::array:
3735  {
3736  m_value.array->clear();
3737  break;
3738  }
3739 
3740  case value_t::object:
3741  {
3742  m_value.object->clear();
3743  break;
3744  }
3745 
3746  default:
3747  {
3748  break;
3749  }
3750  }
3751  }
3752 
3770  void push_back(basic_json&& value)
3771  {
3772  // push_back only works for null objects or arrays
3773  if (not(is_null() or is_array()))
3774  {
3775  throw std::domain_error("cannot use push_back() with " + type_name());
3776  }
3777 
3778  // transform null object into an array
3779  if (is_null())
3780  {
3781  m_type = value_t::array;
3782  m_value = value_t::array;
3783  }
3784 
3785  // add element to array (move semantics)
3786  m_value.array->push_back(std::move(value));
3787  // invalidate object
3788  value.m_type = value_t::null;
3789  }
3790 
3796  {
3797  push_back(std::move(value));
3798  return *this;
3799  }
3800 
3805  void push_back(const basic_json& value)
3806  {
3807  // push_back only works for null objects or arrays
3808  if (not(is_null() or is_array()))
3809  {
3810  throw std::domain_error("cannot use push_back() with " + type_name());
3811  }
3812 
3813  // transform null object into an array
3814  if (is_null())
3815  {
3816  m_type = value_t::array;
3817  m_value = value_t::array;
3818  }
3819 
3820  // add element to array
3821  m_value.array->push_back(value);
3822  }
3823 
3828  reference operator+=(const basic_json& value)
3829  {
3830  push_back(value);
3831  return *this;
3832  }
3833 
3852  void push_back(const typename object_t::value_type& value)
3853  {
3854  // push_back only works for null objects or objects
3855  if (not(is_null() or is_object()))
3856  {
3857  throw std::domain_error("cannot use push_back() with " + type_name());
3858  }
3859 
3860  // transform null object into an object
3861  if (is_null())
3862  {
3863  m_type = value_t::object;
3864  m_value = value_t::object;
3865  }
3866 
3867  // add element to array
3868  m_value.object->insert(value);
3869  }
3870 
3875  reference operator+=(const typename object_t::value_type& value)
3876  {
3877  push_back(value);
3878  return operator[](value.first);
3879  }
3880 
3899  iterator insert(const_iterator pos, const basic_json& value)
3900  {
3901  // insert only works for arrays
3902  if (is_array())
3903  {
3904  // check if iterator pos fits to this JSON value
3905  if (pos.m_object != this)
3906  {
3907  throw std::domain_error("iterator does not fit current value");
3908  }
3909 
3910  // insert to array and return iterator
3911  iterator result(this);
3912  result.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator, value);
3913  return result;
3914  }
3915  else
3916  {
3917  throw std::domain_error("cannot use insert() with " + type_name());
3918  }
3919  }
3920 
3926  {
3927  return insert(pos, value);
3928  }
3929 
3951  {
3952  // insert only works for arrays
3953  if (is_array())
3954  {
3955  // check if iterator pos fits to this JSON value
3956  if (pos.m_object != this)
3957  {
3958  throw std::domain_error("iterator does not fit current value");
3959  }
3960 
3961  // insert to array and return iterator
3962  iterator result(this);
3963  result.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator, count, value);
3964  return result;
3965  }
3966  else
3967  {
3968  throw std::domain_error("cannot use insert() with " + type_name());
3969  }
3970  }
3971 
3997  {
3998  // insert only works for arrays
3999  if (not is_array())
4000  {
4001  throw std::domain_error("cannot use insert() with " + type_name());
4002  }
4003 
4004  // check if iterator pos fits to this JSON value
4005  if (pos.m_object != this)
4006  {
4007  throw std::domain_error("iterator does not fit current value");
4008  }
4009 
4010  if (first.m_object != last.m_object)
4011  {
4012  throw std::domain_error("iterators does not fit");
4013  }
4014 
4015  if (first.m_object == this or last.m_object == this)
4016  {
4017  throw std::domain_error("passed iterators may not belong to container");
4018  }
4019 
4020  // insert to array and return iterator
4021  iterator result(this);
4022  result.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator,
4023  first.m_it.array_iterator, last.m_it.array_iterator);
4024  return result;
4025  }
4026 
4046  iterator insert(const_iterator pos, std::initializer_list<basic_json> ilist)
4047  {
4048  // insert only works for arrays
4049  if (not is_array())
4050  {
4051  throw std::domain_error("cannot use insert() with " + type_name());
4052  }
4053 
4054  // check if iterator pos fits to this JSON value
4055  if (pos.m_object != this)
4056  {
4057  throw std::domain_error("iterator does not fit current value");
4058  }
4059 
4060  // insert to array and return iterator
4061  iterator result(this);
4062  result.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator, ilist);
4063  return result;
4064  }
4065 
4081  void swap(reference other) noexcept (
4082  std::is_nothrow_move_constructible<value_t>::value and
4083  std::is_nothrow_move_assignable<value_t>::value and
4084  std::is_nothrow_move_constructible<json_value>::value and
4085  std::is_nothrow_move_assignable<json_value>::value
4086  )
4087  {
4088  std::swap(m_type, other.m_type);
4089  std::swap(m_value, other.m_value);
4090  }
4091 
4109  void swap(array_t& other)
4110  {
4111  // swap only works for arrays
4112  if (is_array())
4113  {
4114  std::swap(*(m_value.array), other);
4115  }
4116  else
4117  {
4118  throw std::domain_error("cannot use swap() with " + type_name());
4119  }
4120  }
4121 
4139  void swap(object_t& other)
4140  {
4141  // swap only works for objects
4142  if (is_object())
4143  {
4144  std::swap(*(m_value.object), other);
4145  }
4146  else
4147  {
4148  throw std::domain_error("cannot use swap() with " + type_name());
4149  }
4150  }
4151 
4169  void swap(string_t& other)
4170  {
4171  // swap only works for strings
4172  if (is_string())
4173  {
4174  std::swap(*(m_value.string), other);
4175  }
4176  else
4177  {
4178  throw std::domain_error("cannot use swap() with " + type_name());
4179  }
4180  }
4181 
4183 
4184 
4186  // lexicographical comparison operators //
4188 
4191 
4192  private:
4200  friend bool operator<(const value_t lhs, const value_t rhs)
4201  {
4202  static constexpr std::array<uint8_t, 7> order = {{
4203  0, // null
4204  3, // object
4205  4, // array
4206  5, // string
4207  1, // boolean
4208  2, // integer
4209  2 // float
4210  }
4211  };
4212 
4213  // discarded values are not comparable
4214  if (lhs == value_t::discarded or rhs == value_t::discarded)
4215  {
4216  return false;
4217  }
4218 
4219  return order[static_cast<std::size_t>(lhs)] < order[static_cast<std::size_t>(rhs)];
4220  }
4221 
4222  public:
4244  friend bool operator==(const_reference lhs, const_reference rhs) noexcept
4245  {
4246  const auto lhs_type = lhs.type();
4247  const auto rhs_type = rhs.type();
4248 
4249  if (lhs_type == rhs_type)
4250  {
4251  switch (lhs_type)
4252  {
4253  case value_t::array:
4254  return *lhs.m_value.array == *rhs.m_value.array;
4255  case value_t::object:
4256  return *lhs.m_value.object == *rhs.m_value.object;
4257  case value_t::null:
4258  return true;
4259  case value_t::string:
4260  return *lhs.m_value.string == *rhs.m_value.string;
4261  case value_t::boolean:
4262  return lhs.m_value.boolean == rhs.m_value.boolean;
4264  return lhs.m_value.number_integer == rhs.m_value.number_integer;
4265  case value_t::number_float:
4266  return approx(lhs.m_value.number_float, rhs.m_value.number_float);
4267  default:
4268  return false;
4269  }
4270  }
4271  else if (lhs_type == value_t::number_integer and rhs_type == value_t::number_float)
4272  {
4273  return approx(static_cast<number_float_t>(lhs.m_value.number_integer),
4274  rhs.m_value.number_float);
4275  }
4276  else if (lhs_type == value_t::number_float and rhs_type == value_t::number_integer)
4277  {
4278  return approx(lhs.m_value.number_float,
4279  static_cast<number_float_t>(rhs.m_value.number_integer));
4280  }
4281  return false;
4282  }
4283 
4300  friend bool operator==(const_reference v, std::nullptr_t) noexcept
4301  {
4302  return v.is_null();
4303  }
4304 
4309  friend bool operator==(std::nullptr_t, const_reference v) noexcept
4310  {
4311  return v.is_null();
4312  }
4313 
4328  friend bool operator!=(const_reference lhs, const_reference rhs) noexcept
4329  {
4330  return not (lhs == rhs);
4331  }
4332 
4349  friend bool operator!=(const_reference v, std::nullptr_t) noexcept
4350  {
4351  return not v.is_null();
4352  }
4353 
4358  friend bool operator!=(std::nullptr_t, const_reference v) noexcept
4359  {
4360  return not v.is_null();
4361  }
4362 
4385  friend bool operator<(const_reference lhs, const_reference rhs) noexcept
4386  {
4387  const auto lhs_type = lhs.type();
4388  const auto rhs_type = rhs.type();
4389 
4390  if (lhs_type == rhs_type)
4391  {
4392  switch (lhs_type)
4393  {
4394  case value_t::array:
4395  return *lhs.m_value.array < *rhs.m_value.array;
4396  case value_t::object:
4397  return *lhs.m_value.object < *rhs.m_value.object;
4398  case value_t::null:
4399  return false;
4400  case value_t::string:
4401  return *lhs.m_value.string < *rhs.m_value.string;
4402  case value_t::boolean:
4403  return lhs.m_value.boolean < rhs.m_value.boolean;
4405  return lhs.m_value.number_integer < rhs.m_value.number_integer;
4406  case value_t::number_float:
4407  return lhs.m_value.number_float < rhs.m_value.number_float;
4408  default:
4409  return false;
4410  }
4411  }
4412  else if (lhs_type == value_t::number_integer and rhs_type == value_t::number_float)
4413  {
4414  return static_cast<number_float_t>(lhs.m_value.number_integer) <
4415  rhs.m_value.number_float;
4416  }
4417  else if (lhs_type == value_t::number_float and rhs_type == value_t::number_integer)
4418  {
4419  return lhs.m_value.number_float <
4420  static_cast<number_float_t>(rhs.m_value.number_integer);
4421  }
4422 
4423  // We only reach this line if we cannot compare values. In that case,
4424  // we compare types. Note we have to call the operator explicitly,
4425  // because MSVC has problems otherwise.
4426  return operator<(lhs_type, rhs_type);
4427  }
4428 
4444  friend bool operator<=(const_reference lhs, const_reference rhs) noexcept
4445  {
4446  return not (rhs < lhs);
4447  }
4448 
4464  friend bool operator>(const_reference lhs, const_reference rhs) noexcept
4465  {
4466  return not (lhs <= rhs);
4467  }
4468 
4484  friend bool operator>=(const_reference lhs, const_reference rhs) noexcept
4485  {
4486  return not (lhs < rhs);
4487  }
4488 
4490 
4491 
4493  // serialization //
4495 
4498 
4519  friend std::ostream& operator<<(std::ostream& o, const basic_json& j)
4520  {
4521  // read width member and use it as indentation parameter if nonzero
4522  const bool pretty_print = (o.width() > 0);
4523  const auto indentation = (pretty_print ? o.width() : 0);
4524 
4525  // reset width to 0 for subsequent calls to this stream
4526  o.width(0);
4527 
4528  // do the actual serialization
4529  j.dump(o, pretty_print, static_cast<unsigned int>(indentation));
4530  return o;
4531  }
4532 
4537  friend std::ostream& operator>>(const basic_json& j, std::ostream& o)
4538  {
4539  return o << j;
4540  }
4541 
4543 
4544 
4546  // deserialization //
4548 
4551 
4574  static basic_json parse(const string_t& s, parser_callback_t cb = nullptr)
4575  {
4576  return parser(s, cb).parse();
4577  }
4578 
4601  static basic_json parse(std::istream& i, parser_callback_t cb = nullptr)
4602  {
4603  return parser(i, cb).parse();
4604  }
4605 
4606  static basic_json parse(std::istream&& i, parser_callback_t cb = nullptr)
4607  {
4608  return parser(i, cb).parse();
4609  }
4610 
4632  friend std::istream& operator<<(basic_json& j, std::istream& i)
4633  {
4634  j = parser(i).parse();
4635  return i;
4636  }
4637 
4642  friend std::istream& operator>>(std::istream& i, basic_json& j)
4643  {
4644  j = parser(i).parse();
4645  return i;
4646  }
4647 
4649 
4650 
4651  private:
4653  // convenience functions //
4655 
4657  string_t type_name() const
4658  {
4659  switch (m_type)
4660  {
4661  case value_t::null:
4662  {
4663  return "null";
4664  }
4665 
4666  case value_t::object:
4667  {
4668  return "object";
4669  }
4670 
4671  case value_t::array:
4672  {
4673  return "array";
4674  }
4675 
4676  case value_t::string:
4677  {
4678  return "string";
4679  }
4680 
4681  case value_t::boolean:
4682  {
4683  return "boolean";
4684  }
4685 
4686  case value_t::discarded:
4687  {
4688  return "discarded";
4689  }
4690 
4691  default:
4692  {
4693  return "number";
4694  }
4695  }
4696  }
4697 
4706  static std::size_t extra_space(const string_t& s) noexcept
4707  {
4708  std::size_t result = 0;
4709 
4710  for (const auto& c : s)
4711  {
4712  switch (c)
4713  {
4714  case '"':
4715  case '\\':
4716  case '\b':
4717  case '\f':
4718  case '\n':
4719  case '\r':
4720  case '\t':
4721  {
4722  // from c (1 byte) to \x (2 bytes)
4723  result += 1;
4724  break;
4725  }
4726 
4727  default:
4728  {
4729  if (c >= 0x00 and c <= 0x1f)
4730  {
4731  // from c (1 byte) to \uxxxx (6 bytes)
4732  result += 5;
4733  }
4734  break;
4735  }
4736  }
4737  }
4738 
4739  return result;
4740  }
4741 
4755  static string_t escape_string(const string_t& s) noexcept
4756  {
4757  const auto space = extra_space(s);
4758  if (space == 0)
4759  {
4760  return s;
4761  }
4762 
4763  // create a result string of necessary size
4764  string_t result(s.size() + space, '\\');
4765  std::size_t pos = 0;
4766 
4767  for (const auto& c : s)
4768  {
4769  switch (c)
4770  {
4771  // quotation mark (0x22)
4772  case '"':
4773  {
4774  result[pos + 1] = '"';
4775  pos += 2;
4776  break;
4777  }
4778 
4779  // reverse solidus (0x5c)
4780  case '\\':
4781  {
4782  // nothing to change
4783  pos += 2;
4784  break;
4785  }
4786 
4787  // backspace (0x08)
4788  case '\b':
4789  {
4790  result[pos + 1] = 'b';
4791  pos += 2;
4792  break;
4793  }
4794 
4795  // formfeed (0x0c)
4796  case '\f':
4797  {
4798  result[pos + 1] = 'f';
4799  pos += 2;
4800  break;
4801  }
4802 
4803  // newline (0x0a)
4804  case '\n':
4805  {
4806  result[pos + 1] = 'n';
4807  pos += 2;
4808  break;
4809  }
4810 
4811  // carriage return (0x0d)
4812  case '\r':
4813  {
4814  result[pos + 1] = 'r';
4815  pos += 2;
4816  break;
4817  }
4818 
4819  // horizontal tab (0x09)
4820  case '\t':
4821  {
4822  result[pos + 1] = 't';
4823  pos += 2;
4824  break;
4825  }
4826 
4827  default:
4828  {
4829  if (c >= 0x00 and c <= 0x1f)
4830  {
4831  // convert a number 0..15 to its hex representation (0..f)
4832  auto hexify = [](const char v) -> char
4833  {
4834  return (v < 10) ? ('0' + v) : ('a' + v - 10);
4835  };
4836 
4837  // print character c as \uxxxx
4838  for (const char m :
4839  { 'u', '0', '0', hexify(c >> 4), hexify(c & 0x0f)
4840  })
4841  {
4842  result[++pos] = m;
4843  }
4844 
4845  ++pos;
4846  }
4847  else
4848  {
4849  // all other characters are added as-is
4850  result[pos++] = c;
4851  }
4852  break;
4853  }
4854  }
4855  }
4856 
4857  return result;
4858  }
4859 
4877  void dump(std::ostream& o, const bool pretty_print, const unsigned int indent_step,
4878  const unsigned int current_indent = 0) const
4879  {
4880  // variable to hold indentation for recursive calls
4881  unsigned int new_indent = current_indent;
4882 
4883  switch (m_type)
4884  {
4885  case value_t::object:
4886  {
4887  if (m_value.object->empty())
4888  {
4889  o << "{}";
4890  return;
4891  }
4892 
4893  o << "{";
4894 
4895  // increase indentation
4896  if (pretty_print)
4897  {
4898  new_indent += indent_step;
4899  o << "\n";
4900  }
4901 
4902  for (auto i = m_value.object->cbegin(); i != m_value.object->cend(); ++i)
4903  {
4904  if (i != m_value.object->cbegin())
4905  {
4906  o << (pretty_print ? ",\n" : ",");
4907  }
4908  o << string_t(new_indent, ' ') << "\""
4909  << escape_string(i->first) << "\":"
4910  << (pretty_print ? " " : "");
4911  i->second.dump(o, pretty_print, indent_step, new_indent);
4912  }
4913 
4914  // decrease indentation
4915  if (pretty_print)
4916  {
4917  new_indent -= indent_step;
4918  o << "\n";
4919  }
4920 
4921  o << string_t(new_indent, ' ') + "}";
4922  return;
4923  }
4924 
4925  case value_t::array:
4926  {
4927  if (m_value.array->empty())
4928  {
4929  o << "[]";
4930  return;
4931  }
4932 
4933  o << "[";
4934 
4935  // increase indentation
4936  if (pretty_print)
4937  {
4938  new_indent += indent_step;
4939  o << "\n";
4940  }
4941 
4942  for (auto i = m_value.array->cbegin(); i != m_value.array->cend(); ++i)
4943  {
4944  if (i != m_value.array->cbegin())
4945  {
4946  o << (pretty_print ? ",\n" : ",");
4947  }
4948  o << string_t(new_indent, ' ');
4949  i->dump(o, pretty_print, indent_step, new_indent);
4950  }
4951 
4952  // decrease indentation
4953  if (pretty_print)
4954  {
4955  new_indent -= indent_step;
4956  o << "\n";
4957  }
4958 
4959  o << string_t(new_indent, ' ') << "]";
4960  return;
4961  }
4962 
4963  case value_t::string:
4964  {
4965  o << string_t("\"") << escape_string(*m_value.string) << "\"";
4966  return;
4967  }
4968 
4969  case value_t::boolean:
4970  {
4971  o << (m_value.boolean ? "true" : "false");
4972  return;
4973  }
4974 
4976  {
4977  o << m_value.number_integer;
4978  return;
4979  }
4980 
4981  case value_t::number_float:
4982  {
4983  // 15 digits of precision allows round-trip IEEE 754
4984  // string->double->string; to be safe, we read this value from
4985  // std::numeric_limits<number_float_t>::digits10
4986  o << std::setprecision(std::numeric_limits<number_float_t>::digits10) << m_value.number_float;
4987  return;
4988  }
4989 
4990  case value_t::discarded:
4991  {
4992  o << "<discarded>";
4993  return;
4994  }
4995 
4996  case value_t::null:
4997  {
4998  o << "null";
4999  return;
5000  }
5001  }
5002  }
5003 
5004  private:
5006  // member variables //
5008 
5010  value_t m_type = value_t::null;
5011 
5013  json_value m_value = {};
5014 
5015 
5016  private:
5018  // iterators //
5020 
5030  class primitive_iterator_t
5031  {
5032  public:
5034  void set_begin()
5035  {
5036  m_it = begin_value;
5037  }
5038 
5040  void set_end()
5041  {
5042  m_it = end_value;
5043  }
5044 
5046  bool is_begin() const
5047  {
5048  return (m_it == begin_value);
5049  }
5050 
5052  bool is_end() const
5053  {
5054  return (m_it == end_value);
5055  }
5056 
5058  operator difference_type& ()
5059  {
5060  return m_it;
5061  }
5062 
5064  operator difference_type () const
5065  {
5066  return m_it;
5067  }
5068 
5069  private:
5070  static constexpr difference_type begin_value = 0;
5071  static constexpr difference_type end_value = begin_value + 1;
5072 
5074  difference_type m_it = std::numeric_limits<std::ptrdiff_t>::denorm_min();
5075  };
5076 
5084  struct internal_iterator
5085  {
5087  typename object_t::iterator object_iterator;
5089  typename array_t::iterator array_iterator;
5091  primitive_iterator_t primitive_iterator;
5092 
5094  internal_iterator()
5095  : object_iterator(), array_iterator(), primitive_iterator()
5096  {}
5097  };
5098 
5099  public:
5111  class const_iterator : public std::iterator<std::random_access_iterator_tag, const basic_json>
5112  {
5114  friend class basic_json;
5115 
5116  public:
5126  using iterator_category = std::bidirectional_iterator_tag;
5127 
5129  const_iterator() = default;
5130 
5132  const_iterator(pointer object) : m_object(object)
5133  {
5134  switch (m_object->m_type)
5135  {
5137  {
5138  m_it.object_iterator = typename object_t::iterator();
5139  break;
5140  }
5141 
5143  {
5144  m_it.array_iterator = typename array_t::iterator();
5145  break;
5146  }
5147 
5148  default:
5149  {
5150  m_it.primitive_iterator = primitive_iterator_t();
5151  break;
5152  }
5153  }
5154  }
5155 
5157  const_iterator(const iterator& other) : m_object(other.m_object)
5158  {
5159  switch (m_object->m_type)
5160  {
5162  {
5163  m_it.object_iterator = other.m_it.object_iterator;
5164  break;
5165  }
5166 
5168  {
5169  m_it.array_iterator = other.m_it.array_iterator;
5170  break;
5171  }
5172 
5173  default:
5174  {
5175  m_it.primitive_iterator = other.m_it.primitive_iterator;
5176  break;
5177  }
5178  }
5179  }
5180 
5182  const_iterator(const const_iterator& other) noexcept
5183  : m_object(other.m_object), m_it(other.m_it)
5184  {}
5185 
5188  std::is_nothrow_move_constructible<pointer>::value and
5189  std::is_nothrow_move_assignable<pointer>::value and
5190  std::is_nothrow_move_constructible<internal_iterator>::value and
5191  std::is_nothrow_move_assignable<internal_iterator>::value
5192  )
5193  {
5194  std::swap(m_object, other.m_object);
5195  std::swap(m_it, other.m_it);
5196  return *this;
5197  }
5198 
5199  private:
5201  void set_begin()
5202  {
5203  switch (m_object->m_type)
5204  {
5206  {
5207  m_it.object_iterator = m_object->m_value.object->begin();
5208  break;
5209  }
5210 
5212  {
5213  m_it.array_iterator = m_object->m_value.array->begin();
5214  break;
5215  }
5216 
5218  {
5219  // set to end so begin()==end() is true: null is empty
5220  m_it.primitive_iterator.set_end();
5221  break;
5222  }
5223 
5224  default:
5225  {
5226  m_it.primitive_iterator.set_begin();
5227  break;
5228  }
5229  }
5230  }
5231 
5233  void set_end()
5234  {
5235  switch (m_object->m_type)
5236  {
5238  {
5239  m_it.object_iterator = m_object->m_value.object->end();
5240  break;
5241  }
5242 
5244  {
5245  m_it.array_iterator = m_object->m_value.array->end();
5246  break;
5247  }
5248 
5249  default:
5250  {
5251  m_it.primitive_iterator.set_end();
5252  break;
5253  }
5254  }
5255  }
5256 
5257  public:
5260  {
5261  switch (m_object->m_type)
5262  {
5264  {
5265  return m_it.object_iterator->second;
5266  }
5267 
5269  {
5270  return *m_it.array_iterator;
5271  }
5272 
5274  {
5275  throw std::out_of_range("cannot get value");
5276  }
5277 
5278  default:
5279  {
5280  if (m_it.primitive_iterator.is_begin())
5281  {
5282  return *m_object;
5283  }
5284  else
5285  {
5286  throw std::out_of_range("cannot get value");
5287  }
5288  }
5289  }
5290  }
5291 
5294  {
5295  switch (m_object->m_type)
5296  {
5298  {
5299  return &(m_it.object_iterator->second);
5300  }
5301 
5303  {
5304  return &*m_it.array_iterator;
5305  }
5306 
5307  default:
5308  {
5309  if (m_it.primitive_iterator.is_begin())
5310  {
5311  return m_object;
5312  }
5313  else
5314  {
5315  throw std::out_of_range("cannot get value");
5316  }
5317  }
5318  }
5319  }
5320 
5323  {
5324  auto result = *this;
5325  ++(*this);
5326 
5327  return result;
5328  }
5329 
5332  {
5333  switch (m_object->m_type)
5334  {
5336  {
5337  ++m_it.object_iterator;
5338  break;
5339  }
5340 
5342  {
5343  ++m_it.array_iterator;
5344  break;
5345  }
5346 
5347  default:
5348  {
5349  ++m_it.primitive_iterator;
5350  break;
5351  }
5352  }
5353 
5354  return *this;
5355  }
5356 
5359  {
5360  auto result = *this;
5361  --(*this);
5362 
5363  return result;
5364  }
5365 
5368  {
5369  switch (m_object->m_type)
5370  {
5372  {
5373  --m_it.object_iterator;
5374  break;
5375  }
5376 
5378  {
5379  --m_it.array_iterator;
5380  break;
5381  }
5382 
5383  default:
5384  {
5385  --m_it.primitive_iterator;
5386  break;
5387  }
5388  }
5389 
5390  return *this;
5391  }
5392 
5394  bool operator==(const const_iterator& other) const
5395  {
5396  // if objects are not the same, the comparison is undefined
5397  if (m_object != other.m_object)
5398  {
5399  throw std::domain_error("cannot compare iterators of different containers");
5400  }
5401 
5402  switch (m_object->m_type)
5403  {
5405  {
5406  return (m_it.object_iterator == other.m_it.object_iterator);
5407  }
5408 
5410  {
5411  return (m_it.array_iterator == other.m_it.array_iterator);
5412  }
5413 
5414  default:
5415  {
5416  return (m_it.primitive_iterator == other.m_it.primitive_iterator);
5417  }
5418  }
5419  }
5420 
5422  bool operator!=(const const_iterator& other) const
5423  {
5424  return not operator==(other);
5425  }
5426 
5428  bool operator<(const const_iterator& other) const
5429  {
5430  // if objects are not the same, the comparison is undefined
5431  if (m_object != other.m_object)
5432  {
5433  throw std::domain_error("cannot compare iterators of different containers");
5434  }
5435 
5436  switch (m_object->m_type)
5437  {
5439  {
5440  throw std::domain_error("cannot use operator< for object iterators");
5441  }
5442 
5444  {
5445  return (m_it.array_iterator < other.m_it.array_iterator);
5446  }
5447 
5448  default:
5449  {
5450  return (m_it.primitive_iterator < other.m_it.primitive_iterator);
5451  }
5452  }
5453  }
5454 
5456  bool operator<=(const const_iterator& other) const
5457  {
5458  return not other.operator < (*this);
5459  }
5460 
5462  bool operator>(const const_iterator& other) const
5463  {
5464  return not operator<=(other);
5465  }
5466 
5468  bool operator>=(const const_iterator& other) const
5469  {
5470  return not operator<(other);
5471  }
5472 
5475  {
5476  switch (m_object->m_type)
5477  {
5479  {
5480  throw std::domain_error("cannot use operator+= for object iterators");
5481  }
5482 
5484  {
5485  m_it.array_iterator += i;
5486  break;
5487  }
5488 
5489  default:
5490  {
5491  m_it.primitive_iterator += i;
5492  break;
5493  }
5494  }
5495 
5496  return *this;
5497  }
5498 
5501  {
5502  return operator+=(-i);
5503  }
5504 
5507  {
5508  auto result = *this;
5509  result += i;
5510  return result;
5511  }
5512 
5515  {
5516  auto result = *this;
5517  result -= i;
5518  return result;
5519  }
5520 
5523  {
5524  switch (m_object->m_type)
5525  {
5527  {
5528  throw std::domain_error("cannot use operator- for object iterators");
5529  }
5530 
5532  {
5533  return m_it.array_iterator - other.m_it.array_iterator;
5534  }
5535 
5536  default:
5537  {
5538  return m_it.primitive_iterator - other.m_it.primitive_iterator;
5539  }
5540  }
5541  }
5542 
5545  {
5546  switch (m_object->m_type)
5547  {
5549  {
5550  throw std::domain_error("cannot use operator[] for object iterators");
5551  }
5552 
5554  {
5555  return *(m_it.array_iterator + n);
5556  }
5557 
5559  {
5560  throw std::out_of_range("cannot get value");
5561  }
5562 
5563  default:
5564  {
5565  if (m_it.primitive_iterator == -n)
5566  {
5567  return *m_object;
5568  }
5569  else
5570  {
5571  throw std::out_of_range("cannot get value");
5572  }
5573  }
5574  }
5575  }
5576 
5578  typename object_t::key_type key() const
5579  {
5580  if (m_object->is_object())
5581  {
5582  return m_it.object_iterator->first;
5583  }
5584  else
5585  {
5586  throw std::domain_error("cannot use key() for non-object iterators");
5587  }
5588  }
5589 
5592  {
5593  return operator*();
5594  }
5595 
5596  private:
5598  pointer m_object = nullptr;
5600  internal_iterator m_it = internal_iterator();
5601  };
5602 
5613  class iterator : public const_iterator
5614  {
5615  public:
5617  using pointer = typename basic_json::pointer;
5619 
5621  iterator() = default;
5622 
5624  iterator(pointer object) noexcept : base_iterator(object)
5625  {}
5626 
5628  iterator(const iterator& other) noexcept
5629  : base_iterator(other)
5630  {}
5631 
5633  iterator& operator=(iterator other) noexcept(
5634  std::is_nothrow_move_constructible<pointer>::value and
5635  std::is_nothrow_move_assignable<pointer>::value and
5636  std::is_nothrow_move_constructible<internal_iterator>::value and
5637  std::is_nothrow_move_assignable<internal_iterator>::value
5638  )
5639  {
5640  base_iterator::operator=(other);
5641  return *this;
5642  }
5643 
5646  {
5647  return const_cast<reference>(base_iterator::operator*());
5648  }
5649 
5652  {
5653  return const_cast<pointer>(base_iterator::operator->());
5654  }
5655 
5658  {
5659  iterator result = *this;
5661  return result;
5662  }
5663 
5666  {
5668  return *this;
5669  }
5670 
5673  {
5674  iterator result = *this;
5676  return result;
5677  }
5678 
5681  {
5683  return *this;
5684  }
5685 
5688  {
5690  return *this;
5691  }
5692 
5695  {
5697  return *this;
5698  }
5699 
5702  {
5703  auto result = *this;
5704  result += i;
5705  return result;
5706  }
5707 
5710  {
5711  auto result = *this;
5712  result -= i;
5713  return result;
5714  }
5715 
5716  difference_type operator-(const iterator& other) const
5717  {
5718  return base_iterator::operator-(other);
5719  }
5720 
5723  {
5724  return const_cast<reference>(base_iterator::operator[](n));
5725  }
5726 
5729  {
5730  return const_cast<reference>(base_iterator::value());
5731  }
5732  };
5733 
5749  template<typename Base>
5750  class json_reverse_iterator : public std::reverse_iterator<Base>
5751  {
5752  public:
5754  using base_iterator = std::reverse_iterator<Base>;
5756  using reference = typename Base::reference;
5757 
5759  json_reverse_iterator(const typename base_iterator::iterator_type& it)
5760  : base_iterator(it) {}
5761 
5764 
5767  {
5768  return base_iterator::operator++(1);
5769  }
5770 
5773  {
5774  base_iterator::operator++();
5775  return *this;
5776  }
5777 
5780  {
5781  return base_iterator::operator--(1);
5782  }
5783 
5786  {
5787  base_iterator::operator--();
5788  return *this;
5789  }
5790 
5793  {
5794  base_iterator::operator+=(i);
5795  return *this;
5796  }
5797 
5800  {
5801  auto result = *this;
5802  result += i;
5803  return result;
5804  }
5805 
5808  {
5809  auto result = *this;
5810  result -= i;
5811  return result;
5812  }
5813 
5816  {
5817  return this->base() - other.base();
5818  }
5819 
5822  {
5823  return *(this->operator+(n));
5824  }
5825 
5827  typename object_t::key_type key() const
5828  {
5829  auto it = --this->base();
5830  return it.key();
5831  }
5832 
5835  {
5836  auto it = --this->base();
5837  return it.operator * ();
5838  }
5839  };
5840 
5849  {
5850  private:
5852  basic_json& container;
5854  using json_iterator = decltype(std::begin(container));
5855 
5857  class iterator_wrapper_internal
5858  {
5859  private:
5861  json_iterator anchor;
5863  size_t array_index = 0;
5864 
5865  public:
5867  iterator_wrapper_internal(json_iterator i) : anchor(i)
5868  {}
5869 
5871  iterator_wrapper_internal& operator*()
5872  {
5873  return *this;
5874  }
5875 
5877  iterator_wrapper_internal& operator++()
5878  {
5879  ++anchor;
5880  ++array_index;
5881 
5882  return *this;
5883  }
5884 
5886  bool operator!= (const iterator_wrapper_internal& o)
5887  {
5888  return anchor != o.anchor;
5889  }
5890 
5892  typename basic_json::string_t key() const
5893  {
5894  switch (anchor.m_object->type())
5895  {
5897  case value_t::array:
5898  {
5899  return std::to_string(array_index);
5900  }
5901 
5903  case value_t::object:
5904  {
5905  return anchor.key();
5906  }
5907 
5909  default:
5910  {
5911  return "";
5912  }
5913  }
5914  }
5915 
5917  typename json_iterator::reference value() const
5918  {
5919  return anchor.value();
5920  }
5921  };
5922 
5923  public:
5925  iterator_wrapper(basic_json& cont)
5926  : container(cont)
5927  {}
5928 
5930  iterator_wrapper_internal begin()
5931  {
5932  return iterator_wrapper_internal(container.begin());
5933  }
5934 
5936  iterator_wrapper_internal end()
5937  {
5938  return iterator_wrapper_internal(container.end());
5939  }
5940  };
5941 
5942  private:
5944  // lexer and parser //
5946 
5954  class lexer
5955  {
5956  public:
5958  enum class token_type
5959  {
5960  uninitialized,
5961  literal_true,
5962  literal_false,
5963  literal_null,
5964  value_string,
5965  value_number,
5966  begin_array,
5967  begin_object,
5968  end_array,
5969  end_object,
5970  name_separator,
5971  value_separator,
5972  parse_error,
5973  end_of_input
5974  };
5975 
5977  using lexer_char_t = unsigned char;
5978 
5980  explicit lexer(const string_t& s) noexcept
5981  : m_stream(nullptr), m_buffer(s)
5982  {
5983  m_content = reinterpret_cast<const lexer_char_t*>(s.c_str());
5984  m_start = m_cursor = m_content;
5985  m_limit = m_content + s.size();
5986  }
5987  explicit lexer(std::istream* s) noexcept
5988  : m_stream(s), m_buffer()
5989  {
5990  getline(*m_stream, m_buffer);
5991  m_content = reinterpret_cast<const lexer_char_t*>(m_buffer.c_str());
5992  m_start = m_cursor = m_content;
5993  m_limit = m_content + m_buffer.size();
5994  }
5995 
5997  lexer() = default;
5998 
5999  // switch of unwanted functions
6000  lexer(const lexer&) = delete;
6001  lexer operator=(const lexer&) = delete;
6002 
6014  static string_t to_unicode(const std::size_t codepoint1,
6015  const std::size_t codepoint2 = 0)
6016  {
6017  string_t result;
6018 
6019  // calculate the codepoint from the given code points
6020  std::size_t codepoint = codepoint1;
6021 
6022  // check if codepoint1 is a high surrogate
6023  if (codepoint1 >= 0xD800 and codepoint1 <= 0xDBFF)
6024  {
6025  // check if codepoint2 is a low surrogate
6026  if (codepoint2 >= 0xDC00 and codepoint2 <= 0xDFFF)
6027  {
6028  codepoint =
6029  // high surrogate occupies the most significant 22 bits
6030  (codepoint1 << 10)
6031  // low surrogate occupies the least significant 15 bits
6032  + codepoint2
6033  // there is still the 0xD800, 0xDC00 and 0x10000 noise
6034  // in the result so we have to substract with:
6035  // (0xD800 << 10) + DC00 - 0x10000 = 0x35FDC00
6036  - 0x35FDC00;
6037  }
6038  else
6039  {
6040  throw std::invalid_argument("missing or wrong low surrogate");
6041  }
6042  }
6043 
6044  if (codepoint < 0x80)
6045  {
6046  // 1-byte characters: 0xxxxxxx (ASCII)
6047  result.append(1, static_cast<typename string_t::value_type>(codepoint));
6048  }
6049  else if (codepoint <= 0x7ff)
6050  {
6051  // 2-byte characters: 110xxxxx 10xxxxxx
6052  result.append(1, static_cast<typename string_t::value_type>(0xC0 | ((codepoint >> 6) & 0x1F)));
6053  result.append(1, static_cast<typename string_t::value_type>(0x80 | (codepoint & 0x3F)));
6054  }
6055  else if (codepoint <= 0xffff)
6056  {
6057  // 3-byte characters: 1110xxxx 10xxxxxx 10xxxxxx
6058  result.append(1, static_cast<typename string_t::value_type>(0xE0 | ((codepoint >> 12) & 0x0F)));
6059  result.append(1, static_cast<typename string_t::value_type>(0x80 | ((codepoint >> 6) & 0x3F)));
6060  result.append(1, static_cast<typename string_t::value_type>(0x80 | (codepoint & 0x3F)));
6061  }
6062  else if (codepoint <= 0x10ffff)
6063  {
6064  // 4-byte characters: 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
6065  result.append(1, static_cast<typename string_t::value_type>(0xF0 | ((codepoint >> 18) & 0x07)));
6066  result.append(1, static_cast<typename string_t::value_type>(0x80 | ((codepoint >> 12) & 0x3F)));
6067  result.append(1, static_cast<typename string_t::value_type>(0x80 | ((codepoint >> 6) & 0x3F)));
6068  result.append(1, static_cast<typename string_t::value_type>(0x80 | (codepoint & 0x3F)));
6069  }
6070  else
6071  {
6072  throw std::out_of_range("code points above 0x10FFFF are invalid");
6073  }
6074 
6075  return result;
6076  }
6077 
6079  static std::string token_type_name(token_type t)
6080  {
6081  switch (t)
6082  {
6083  case token_type::uninitialized:
6084  return "<uninitialized>";
6085  case token_type::literal_true:
6086  return "true literal";
6087  case token_type::literal_false:
6088  return "false literal";
6089  case token_type::literal_null:
6090  return "null literal";
6091  case token_type::value_string:
6092  return "string literal";
6093  case token_type::value_number:
6094  return "number literal";
6095  case token_type::begin_array:
6096  return "[";
6097  case token_type::begin_object:
6098  return "{";
6099  case token_type::end_array:
6100  return "]";
6101  case token_type::end_object:
6102  return "}";
6103  case token_type::name_separator:
6104  return ":";
6105  case token_type::value_separator:
6106  return ",";
6107  case token_type::end_of_input:
6108  return "<end of input>";
6109  case token_type::parse_error:
6110  return "<parse error>";
6111  }
6112  }
6113 
6124  token_type scan() noexcept
6125  {
6126  // pointer for backtracking information
6127  m_marker = nullptr;
6128 
6129  // remember the begin of the token
6130  m_start = m_cursor;
6131 
6132 
6133  {
6134  lexer_char_t yych;
6135  unsigned int yyaccept = 0;
6136  static const unsigned char yybm[] =
6137  {
6138  0, 0, 0, 0, 0, 0, 0, 0,
6139  0, 32, 32, 0, 0, 32, 0, 0,
6140  64, 64, 64, 64, 64, 64, 64, 64,
6141  64, 64, 64, 64, 64, 64, 64, 64,
6142  96, 64, 0, 64, 64, 64, 64, 64,
6143  64, 64, 64, 64, 64, 64, 64, 64,
6144  192, 192, 192, 192, 192, 192, 192, 192,
6145  192, 192, 64, 64, 64, 64, 64, 64,
6146  64, 64, 64, 64, 64, 64, 64, 64,
6147  64, 64, 64, 64, 64, 64, 64, 64,
6148  64, 64, 64, 64, 64, 64, 64, 64,
6149  64, 64, 64, 64, 0, 64, 64, 64,
6150  64, 64, 64, 64, 64, 64, 64, 64,
6151  64, 64, 64, 64, 64, 64, 64, 64,
6152  64, 64, 64, 64, 64, 64, 64, 64,
6153  64, 64, 64, 64, 64, 64, 64, 64,
6154  64, 64, 64, 64, 64, 64, 64, 64,
6155  64, 64, 64, 64, 64, 64, 64, 64,
6156  64, 64, 64, 64, 64, 64, 64, 64,
6157  64, 64, 64, 64, 64, 64, 64, 64,
6158  64, 64, 64, 64, 64, 64, 64, 64,
6159  64, 64, 64, 64, 64, 64, 64, 64,
6160  64, 64, 64, 64, 64, 64, 64, 64,
6161  64, 64, 64, 64, 64, 64, 64, 64,
6162  64, 64, 64, 64, 64, 64, 64, 64,
6163  64, 64, 64, 64, 64, 64, 64, 64,
6164  64, 64, 64, 64, 64, 64, 64, 64,
6165  64, 64, 64, 64, 64, 64, 64, 64,
6166  64, 64, 64, 64, 64, 64, 64, 64,
6167  64, 64, 64, 64, 64, 64, 64, 64,
6168  64, 64, 64, 64, 64, 64, 64, 64,
6169  64, 64, 64, 64, 64, 64, 64, 64,
6170  };
6171  if ((m_limit - m_cursor) < 5)
6172  {
6173  yyfill(); // LCOV_EXCL_LINE;
6174  }
6175  yych = *m_cursor;
6176  if (yych <= ':')
6177  {
6178  if (yych <= ' ')
6179  {
6180  if (yych <= '\n')
6181  {
6182  if (yych <= 0x00)
6183  {
6184  goto basic_json_parser_28;
6185  }
6186  if (yych <= 0x08)
6187  {
6188  goto basic_json_parser_30;
6189  }
6190  if (yych >= '\n')
6191  {
6192  goto basic_json_parser_4;
6193  }
6194  }
6195  else
6196  {
6197  if (yych == '\r')
6198  {
6199  goto basic_json_parser_2;
6200  }
6201  if (yych <= 0x1F)
6202  {
6203  goto basic_json_parser_30;
6204  }
6205  }
6206  }
6207  else
6208  {
6209  if (yych <= ',')
6210  {
6211  if (yych == '"')
6212  {
6213  goto basic_json_parser_27;
6214  }
6215  if (yych <= '+')
6216  {
6217  goto basic_json_parser_30;
6218  }
6219  goto basic_json_parser_16;
6220  }
6221  else
6222  {
6223  if (yych <= '/')
6224  {
6225  if (yych <= '-')
6226  {
6227  goto basic_json_parser_23;
6228  }
6229  goto basic_json_parser_30;
6230  }
6231  else
6232  {
6233  if (yych <= '0')
6234  {
6235  goto basic_json_parser_24;
6236  }
6237  if (yych <= '9')
6238  {
6239  goto basic_json_parser_26;
6240  }
6241  goto basic_json_parser_18;
6242  }
6243  }
6244  }
6245  }
6246  else
6247  {
6248  if (yych <= 'n')
6249  {
6250  if (yych <= ']')
6251  {
6252  if (yych == '[')
6253  {
6254  goto basic_json_parser_8;
6255  }
6256  if (yych <= '\\')
6257  {
6258  goto basic_json_parser_30;
6259  }
6260  goto basic_json_parser_10;
6261  }
6262  else
6263  {
6264  if (yych == 'f')
6265  {
6266  goto basic_json_parser_22;
6267  }
6268  if (yych <= 'm')
6269  {
6270  goto basic_json_parser_30;
6271  }
6272  goto basic_json_parser_20;
6273  }
6274  }
6275  else
6276  {
6277  if (yych <= '{')
6278  {
6279  if (yych == 't')
6280  {
6281  goto basic_json_parser_21;
6282  }
6283  if (yych <= 'z')
6284  {
6285  goto basic_json_parser_30;
6286  }
6287  goto basic_json_parser_12;
6288  }
6289  else
6290  {
6291  if (yych <= '}')
6292  {
6293  if (yych <= '|')
6294  {
6295  goto basic_json_parser_30;
6296  }
6297  goto basic_json_parser_14;
6298  }
6299  else
6300  {
6301  if (yych == 0xEF)
6302  {
6303  goto basic_json_parser_6;
6304  }
6305  goto basic_json_parser_30;
6306  }
6307  }
6308  }
6309  }
6310 basic_json_parser_2:
6311  ++m_cursor;
6312  yych = *m_cursor;
6313  goto basic_json_parser_5;
6314 basic_json_parser_3:
6315  {
6316  return scan();
6317  }
6318 basic_json_parser_4:
6319  ++m_cursor;
6320  if (m_limit <= m_cursor)
6321  {
6322  yyfill(); // LCOV_EXCL_LINE;
6323  }
6324  yych = *m_cursor;
6325 basic_json_parser_5:
6326  if (yybm[0 + yych] & 32)
6327  {
6328  goto basic_json_parser_4;
6329  }
6330  goto basic_json_parser_3;
6331 basic_json_parser_6:
6332  yyaccept = 0;
6333  yych = *(m_marker = ++m_cursor);
6334  if (yych == 0xBB)
6335  {
6336  goto basic_json_parser_64;
6337  }
6338 basic_json_parser_7:
6339  {
6340  return token_type::parse_error;
6341  }
6342 basic_json_parser_8:
6343  ++m_cursor;
6344  {
6345  return token_type::begin_array;
6346  }
6347 basic_json_parser_10:
6348  ++m_cursor;
6349  {
6350  return token_type::end_array;
6351  }
6352 basic_json_parser_12:
6353  ++m_cursor;
6354  {
6355  return token_type::begin_object;
6356  }
6357 basic_json_parser_14:
6358  ++m_cursor;
6359  {
6360  return token_type::end_object;
6361  }
6362 basic_json_parser_16:
6363  ++m_cursor;
6364  {
6365  return token_type::value_separator;
6366  }
6367 basic_json_parser_18:
6368  ++m_cursor;
6369  {
6370  return token_type::name_separator;
6371  }
6372 basic_json_parser_20:
6373  yyaccept = 0;
6374  yych = *(m_marker = ++m_cursor);
6375  if (yych == 'u')
6376  {
6377  goto basic_json_parser_60;
6378  }
6379  goto basic_json_parser_7;
6380 basic_json_parser_21:
6381  yyaccept = 0;
6382  yych = *(m_marker = ++m_cursor);
6383  if (yych == 'r')
6384  {
6385  goto basic_json_parser_56;
6386  }
6387  goto basic_json_parser_7;
6388 basic_json_parser_22:
6389  yyaccept = 0;
6390  yych = *(m_marker = ++m_cursor);
6391  if (yych == 'a')
6392  {
6393  goto basic_json_parser_51;
6394  }
6395  goto basic_json_parser_7;
6396 basic_json_parser_23:
6397  yych = *++m_cursor;
6398  if (yych <= '/')
6399  {
6400  goto basic_json_parser_7;
6401  }
6402  if (yych <= '0')
6403  {
6404  goto basic_json_parser_50;
6405  }
6406  if (yych <= '9')
6407  {
6408  goto basic_json_parser_41;
6409  }
6410  goto basic_json_parser_7;
6411 basic_json_parser_24:
6412  yyaccept = 1;
6413  yych = *(m_marker = ++m_cursor);
6414  if (yych <= 'D')
6415  {
6416  if (yych == '.')
6417  {
6418  goto basic_json_parser_43;
6419  }
6420  }
6421  else
6422  {
6423  if (yych <= 'E')
6424  {
6425  goto basic_json_parser_44;
6426  }
6427  if (yych == 'e')
6428  {
6429  goto basic_json_parser_44;
6430  }
6431  }
6432 basic_json_parser_25:
6433  {
6434  return token_type::value_number;
6435  }
6436 basic_json_parser_26:
6437  yyaccept = 1;
6438  yych = *(m_marker = ++m_cursor);
6439  goto basic_json_parser_42;
6440 basic_json_parser_27:
6441  yyaccept = 0;
6442  yych = *(m_marker = ++m_cursor);
6443  if (yych <= 0x0F)
6444  {
6445  goto basic_json_parser_7;
6446  }
6447  goto basic_json_parser_32;
6448 basic_json_parser_28:
6449  ++m_cursor;
6450  {
6451  return token_type::end_of_input;
6452  }
6453 basic_json_parser_30:
6454  yych = *++m_cursor;
6455  goto basic_json_parser_7;
6456 basic_json_parser_31:
6457  ++m_cursor;
6458  if (m_limit <= m_cursor)
6459  {
6460  yyfill(); // LCOV_EXCL_LINE;
6461  }
6462  yych = *m_cursor;
6463 basic_json_parser_32:
6464  if (yybm[0 + yych] & 64)
6465  {
6466  goto basic_json_parser_31;
6467  }
6468  if (yych <= 0x0F)
6469  {
6470  goto basic_json_parser_33;
6471  }
6472  if (yych <= '"')
6473  {
6474  goto basic_json_parser_35;
6475  }
6476  goto basic_json_parser_34;
6477 basic_json_parser_33:
6478  m_cursor = m_marker;
6479  if (yyaccept == 0)
6480  {
6481  goto basic_json_parser_7;
6482  }
6483  else
6484  {
6485  goto basic_json_parser_25;
6486  }
6487 basic_json_parser_34:
6488  ++m_cursor;
6489  if (m_limit <= m_cursor)
6490  {
6491  yyfill(); // LCOV_EXCL_LINE;
6492  }
6493  yych = *m_cursor;
6494  if (yych <= 'e')
6495  {
6496  if (yych <= '/')
6497  {
6498  if (yych == '"')
6499  {
6500  goto basic_json_parser_31;
6501  }
6502  if (yych <= '.')
6503  {
6504  goto basic_json_parser_33;
6505  }
6506  goto basic_json_parser_31;
6507  }
6508  else
6509  {
6510  if (yych <= '\\')
6511  {
6512  if (yych <= '[')
6513  {
6514  goto basic_json_parser_33;
6515  }
6516  goto basic_json_parser_31;
6517  }
6518  else
6519  {
6520  if (yych == 'b')
6521  {
6522  goto basic_json_parser_31;
6523  }
6524  goto basic_json_parser_33;
6525  }
6526  }
6527  }
6528  else
6529  {
6530  if (yych <= 'q')
6531  {
6532  if (yych <= 'f')
6533  {
6534  goto basic_json_parser_31;
6535  }
6536  if (yych == 'n')
6537  {
6538  goto basic_json_parser_31;
6539  }
6540  goto basic_json_parser_33;
6541  }
6542  else
6543  {
6544  if (yych <= 's')
6545  {
6546  if (yych <= 'r')
6547  {
6548  goto basic_json_parser_31;
6549  }
6550  goto basic_json_parser_33;
6551  }
6552  else
6553  {
6554  if (yych <= 't')
6555  {
6556  goto basic_json_parser_31;
6557  }
6558  if (yych <= 'u')
6559  {
6560  goto basic_json_parser_37;
6561  }
6562  goto basic_json_parser_33;
6563  }
6564  }
6565  }
6566 basic_json_parser_35:
6567  ++m_cursor;
6568  {
6569  return token_type::value_string;
6570  }
6571 basic_json_parser_37:
6572  ++m_cursor;
6573  if (m_limit <= m_cursor)
6574  {
6575  yyfill(); // LCOV_EXCL_LINE;
6576  }
6577  yych = *m_cursor;
6578  if (yych <= '@')
6579  {
6580  if (yych <= '/')
6581  {
6582  goto basic_json_parser_33;
6583  }
6584  if (yych >= ':')
6585  {
6586  goto basic_json_parser_33;
6587  }
6588  }
6589  else
6590  {
6591  if (yych <= 'F')
6592  {
6593  goto basic_json_parser_38;
6594  }
6595  if (yych <= '`')
6596  {
6597  goto basic_json_parser_33;
6598  }
6599  if (yych >= 'g')
6600  {
6601  goto basic_json_parser_33;
6602  }
6603  }
6604 basic_json_parser_38:
6605  ++m_cursor;
6606  if (m_limit <= m_cursor)
6607  {
6608  yyfill(); // LCOV_EXCL_LINE;
6609  }
6610  yych = *m_cursor;
6611  if (yych <= '@')
6612  {
6613  if (yych <= '/')
6614  {
6615  goto basic_json_parser_33;
6616  }
6617  if (yych >= ':')
6618  {
6619  goto basic_json_parser_33;
6620  }
6621  }
6622  else
6623  {
6624  if (yych <= 'F')
6625  {
6626  goto basic_json_parser_39;
6627  }
6628  if (yych <= '`')
6629  {
6630  goto basic_json_parser_33;
6631  }
6632  if (yych >= 'g')
6633  {
6634  goto basic_json_parser_33;
6635  }
6636  }
6637 basic_json_parser_39:
6638  ++m_cursor;
6639  if (m_limit <= m_cursor)
6640  {
6641  yyfill(); // LCOV_EXCL_LINE;
6642  }
6643  yych = *m_cursor;
6644  if (yych <= '@')
6645  {
6646  if (yych <= '/')
6647  {
6648  goto basic_json_parser_33;
6649  }
6650  if (yych >= ':')
6651  {
6652  goto basic_json_parser_33;
6653  }
6654  }
6655  else
6656  {
6657  if (yych <= 'F')
6658  {
6659  goto basic_json_parser_40;
6660  }
6661  if (yych <= '`')
6662  {
6663  goto basic_json_parser_33;
6664  }
6665  if (yych >= 'g')
6666  {
6667  goto basic_json_parser_33;
6668  }
6669  }
6670 basic_json_parser_40:
6671  ++m_cursor;
6672  if (m_limit <= m_cursor)
6673  {
6674  yyfill(); // LCOV_EXCL_LINE;
6675  }
6676  yych = *m_cursor;
6677  if (yych <= '@')
6678  {
6679  if (yych <= '/')
6680  {
6681  goto basic_json_parser_33;
6682  }
6683  if (yych <= '9')
6684  {
6685  goto basic_json_parser_31;
6686  }
6687  goto basic_json_parser_33;
6688  }
6689  else
6690  {
6691  if (yych <= 'F')
6692  {
6693  goto basic_json_parser_31;
6694  }
6695  if (yych <= '`')
6696  {
6697  goto basic_json_parser_33;
6698  }
6699  if (yych <= 'f')
6700  {
6701  goto basic_json_parser_31;
6702  }
6703  goto basic_json_parser_33;
6704  }
6705 basic_json_parser_41:
6706  yyaccept = 1;
6707  m_marker = ++m_cursor;
6708  if ((m_limit - m_cursor) < 3)
6709  {
6710  yyfill(); // LCOV_EXCL_LINE;
6711  }
6712  yych = *m_cursor;
6713 basic_json_parser_42:
6714  if (yybm[0 + yych] & 128)
6715  {
6716  goto basic_json_parser_41;
6717  }
6718  if (yych <= 'D')
6719  {
6720  if (yych != '.')
6721  {
6722  goto basic_json_parser_25;
6723  }
6724  }
6725  else
6726  {
6727  if (yych <= 'E')
6728  {
6729  goto basic_json_parser_44;
6730  }
6731  if (yych == 'e')
6732  {
6733  goto basic_json_parser_44;
6734  }
6735  goto basic_json_parser_25;
6736  }
6737 basic_json_parser_43:
6738  yych = *++m_cursor;
6739  if (yych <= '/')
6740  {
6741  goto basic_json_parser_33;
6742  }
6743  if (yych <= '9')
6744  {
6745  goto basic_json_parser_48;
6746  }
6747  goto basic_json_parser_33;
6748 basic_json_parser_44:
6749  yych = *++m_cursor;
6750  if (yych <= ',')
6751  {
6752  if (yych != '+')
6753  {
6754  goto basic_json_parser_33;
6755  }
6756  }
6757  else
6758  {
6759  if (yych <= '-')
6760  {
6761  goto basic_json_parser_45;
6762  }
6763  if (yych <= '/')
6764  {
6765  goto basic_json_parser_33;
6766  }
6767  if (yych <= '9')
6768  {
6769  goto basic_json_parser_46;
6770  }
6771  goto basic_json_parser_33;
6772  }
6773 basic_json_parser_45:
6774  yych = *++m_cursor;
6775  if (yych <= '/')
6776  {
6777  goto basic_json_parser_33;
6778  }
6779  if (yych >= ':')
6780  {
6781  goto basic_json_parser_33;
6782  }
6783 basic_json_parser_46:
6784  ++m_cursor;
6785  if (m_limit <= m_cursor)
6786  {
6787  yyfill(); // LCOV_EXCL_LINE;
6788  }
6789  yych = *m_cursor;
6790  if (yych <= '/')
6791  {
6792  goto basic_json_parser_25;
6793  }
6794  if (yych <= '9')
6795  {
6796  goto basic_json_parser_46;
6797  }
6798  goto basic_json_parser_25;
6799 basic_json_parser_48:
6800  yyaccept = 1;
6801  m_marker = ++m_cursor;
6802  if ((m_limit - m_cursor) < 3)
6803  {
6804  yyfill(); // LCOV_EXCL_LINE;
6805  }
6806  yych = *m_cursor;
6807  if (yych <= 'D')
6808  {
6809  if (yych <= '/')
6810  {
6811  goto basic_json_parser_25;
6812  }
6813  if (yych <= '9')
6814  {
6815  goto basic_json_parser_48;
6816  }
6817  goto basic_json_parser_25;
6818  }
6819  else
6820  {
6821  if (yych <= 'E')
6822  {
6823  goto basic_json_parser_44;
6824  }
6825  if (yych == 'e')
6826  {
6827  goto basic_json_parser_44;
6828  }
6829  goto basic_json_parser_25;
6830  }
6831 basic_json_parser_50:
6832  yyaccept = 1;
6833  yych = *(m_marker = ++m_cursor);
6834  if (yych <= 'D')
6835  {
6836  if (yych == '.')
6837  {
6838  goto basic_json_parser_43;
6839  }
6840  goto basic_json_parser_25;
6841  }
6842  else
6843  {
6844  if (yych <= 'E')
6845  {
6846  goto basic_json_parser_44;
6847  }
6848  if (yych == 'e')
6849  {
6850  goto basic_json_parser_44;
6851  }
6852  goto basic_json_parser_25;
6853  }
6854 basic_json_parser_51:
6855  yych = *++m_cursor;
6856  if (yych != 'l')
6857  {
6858  goto basic_json_parser_33;
6859  }
6860  yych = *++m_cursor;
6861  if (yych != 's')
6862  {
6863  goto basic_json_parser_33;
6864  }
6865  yych = *++m_cursor;
6866  if (yych != 'e')
6867  {
6868  goto basic_json_parser_33;
6869  }
6870  ++m_cursor;
6871  {
6872  return token_type::literal_false;
6873  }
6874 basic_json_parser_56:
6875  yych = *++m_cursor;
6876  if (yych != 'u')
6877  {
6878  goto basic_json_parser_33;
6879  }
6880  yych = *++m_cursor;
6881  if (yych != 'e')
6882  {
6883  goto basic_json_parser_33;
6884  }
6885  ++m_cursor;
6886  {
6887  return token_type::literal_true;
6888  }
6889 basic_json_parser_60:
6890  yych = *++m_cursor;
6891  if (yych != 'l')
6892  {
6893  goto basic_json_parser_33;
6894  }
6895  yych = *++m_cursor;
6896  if (yych != 'l')
6897  {
6898  goto basic_json_parser_33;
6899  }
6900  ++m_cursor;
6901  {
6902  return token_type::literal_null;
6903  }
6904 basic_json_parser_64:
6905  yych = *++m_cursor;
6906  if (yych != 0xBF)
6907  {
6908  goto basic_json_parser_33;
6909  }
6910  ++m_cursor;
6911  {
6912  return scan();
6913  }
6914  }
6915 
6916 
6917  }
6918 
6920  void yyfill() noexcept
6921  {
6922  if (not m_stream or not * m_stream)
6923  {
6924  return;
6925  }
6926 
6927  const ssize_t offset_start = m_start - m_content;
6928  const ssize_t offset_marker = m_marker - m_start;
6929  const ssize_t offset_cursor = m_cursor - m_start;
6930 
6931  m_buffer.erase(0, static_cast<size_t>(offset_start));
6932  std::string line;
6933  std::getline(*m_stream, line);
6934  m_buffer += "\n" + line; // add line with newline symbol
6935 
6936  m_content = reinterpret_cast<const lexer_char_t*>(m_buffer.c_str());
6937  m_start = m_content;
6938  m_marker = m_start + offset_marker;
6939  m_cursor = m_start + offset_cursor;
6940  m_limit = m_start + m_buffer.size() - 1;
6941  }
6942 
6944  string_t get_token() const noexcept
6945  {
6946  return string_t(reinterpret_cast<typename string_t::const_pointer>(m_start),
6947  static_cast<size_t>(m_cursor - m_start));
6948  }
6949 
6971  string_t get_string() const
6972  {
6973  string_t result;
6974  result.reserve(static_cast<size_t>(m_cursor - m_start - 2));
6975 
6976  // iterate the result between the quotes
6977  for (const lexer_char_t* i = m_start + 1; i < m_cursor - 1; ++i)
6978  {
6979  // process escaped characters
6980  if (*i == '\\')
6981  {
6982  // read next character
6983  ++i;
6984 
6985  switch (*i)
6986  {
6987  // the default escapes
6988  case 't':
6989  {
6990  result += "\t";
6991  break;
6992  }
6993  case 'b':
6994  {
6995  result += "\b";
6996  break;
6997  }
6998  case 'f':
6999  {
7000  result += "\f";
7001  break;
7002  }
7003  case 'n':
7004  {
7005  result += "\n";
7006  break;
7007  }
7008  case 'r':
7009  {
7010  result += "\r";
7011  break;
7012  }
7013  case '\\':
7014  {
7015  result += "\\";
7016  break;
7017  }
7018  case '/':
7019  {
7020  result += "/";
7021  break;
7022  }
7023  case '"':
7024  {
7025  result += "\"";
7026  break;
7027  }
7028 
7029  // unicode
7030  case 'u':
7031  {
7032  // get code xxxx from uxxxx
7033  auto codepoint = std::strtoul(std::string(reinterpret_cast<typename string_t::const_pointer>(i + 1),
7034  4).c_str(), nullptr, 16);
7035 
7036  // check if codepoint is a high surrogate
7037  if (codepoint >= 0xD800 and codepoint <= 0xDBFF)
7038  {
7039  // make sure there is a subsequent unicode
7040  if ((i + 6 >= m_limit) or * (i + 5) != '\\' or * (i + 6) != 'u')
7041  {
7042  throw std::invalid_argument("missing low surrogate");
7043  }
7044 
7045  // get code yyyy from uxxxx\uyyyy
7046  auto codepoint2 = std::strtoul(std::string(reinterpret_cast<typename string_t::const_pointer>
7047  (i + 7), 4).c_str(), nullptr, 16);
7048  result += to_unicode(codepoint, codepoint2);
7049  // skip the next 10 characters (xxxx\uyyyy)
7050  i += 10;
7051  }
7052  else
7053  {
7054  // add unicode character(s)
7055  result += to_unicode(codepoint);
7056  // skip the next four characters (xxxx)
7057  i += 4;
7058  }
7059  break;
7060  }
7061  }
7062  }
7063  else
7064  {
7065  // all other characters are just copied to the end of the
7066  // string
7067  result.append(1, static_cast<typename string_t::value_type>(*i));
7068  }
7069  }
7070 
7071  return result;
7072  }
7073 
7091  long double get_number() const
7092  {
7093  // conversion
7094  typename string_t::value_type* endptr;
7095  const auto float_val = std::strtold(reinterpret_cast<typename string_t::const_pointer>(m_start),
7096  &endptr);
7097 
7098  // return float_val if the whole number was translated and NAN
7099  // otherwise
7100  return (reinterpret_cast<lexer_char_t*>(endptr) == m_cursor) ? float_val : NAN;
7101  }
7102 
7103  private:
7105  std::istream* m_stream;
7107  string_t m_buffer;
7109  const lexer_char_t* m_content = nullptr;
7111  const lexer_char_t* m_start = nullptr;
7113  const lexer_char_t* m_marker = nullptr;
7115  const lexer_char_t* m_cursor = nullptr;
7117  const lexer_char_t* m_limit = nullptr;
7118  };
7119 
7123  class parser
7124  {
7125  public:
7127  parser(const string_t& s, parser_callback_t cb = nullptr)
7128  : callback(cb), m_lexer(s)
7129  {
7130  // read first token
7131  get_token();
7132  }
7133 
7135  parser(std::istream& _is, parser_callback_t cb = nullptr)
7136  : callback(cb), m_lexer(&_is)
7137  {
7138  // read first token
7139  get_token();
7140  }
7141 
7143  basic_json parse()
7144  {
7145  basic_json result = parse_internal(true);
7146 
7147  expect(lexer::token_type::end_of_input);
7148 
7149  // return parser result and replace it with null in case the
7150  // top-level value was discarded by the callback function
7151  return result.is_discarded() ? basic_json() : result;
7152  }
7153 
7154  private:
7156  basic_json parse_internal(bool keep)
7157  {
7158  auto result = basic_json(value_t::discarded);
7159 
7160  switch (last_token)
7161  {
7162  case lexer::token_type::begin_object:
7163  {
7164  if (keep and (not callback or (keep = callback(depth++, parse_event_t::object_start, result))))
7165  {
7166  // explicitly set result to object to cope with {}
7167  result.m_type = value_t::object;
7168  result.m_value = json_value(value_t::object);
7169  }
7170 
7171  // read next token
7172  get_token();
7173 
7174  // closing } -> we are done
7175  if (last_token == lexer::token_type::end_object)
7176  {
7177  get_token();
7178  if (keep and callback and not callback(--depth, parse_event_t::object_end, result))
7179  {
7180  result = basic_json(value_t::discarded);
7181  }
7182  return result;
7183  }
7184 
7185  // no comma is expected here
7186  unexpect(lexer::token_type::value_separator);
7187 
7188  // otherwise: parse key-value pairs
7189  do
7190  {
7191  // ugly, but could be fixed with loop reorganization
7192  if (last_token == lexer::token_type::value_separator)
7193  {
7194  get_token();
7195  }
7196 
7197  // store key
7198  expect(lexer::token_type::value_string);
7199  const auto key = m_lexer.get_string();
7200 
7201  bool keep_tag = false;
7202  if (keep)
7203  {
7204  if (callback)
7205  {
7206  basic_json k(key);
7207  keep_tag = callback(depth, parse_event_t::key, k);
7208  }
7209  else
7210  {
7211  keep_tag = true;
7212  }
7213  }
7214 
7215  // parse separator (:)
7216  get_token();
7217  expect(lexer::token_type::name_separator);
7218 
7219  // parse and add value
7220  get_token();
7221  auto value = parse_internal(keep);
7222  if (keep and keep_tag and not value.is_discarded())
7223  {
7224  result[key] = std::move(value);
7225  }
7226  }
7227  while (last_token == lexer::token_type::value_separator);
7228 
7229  // closing }
7230  expect(lexer::token_type::end_object);
7231  get_token();
7232  if (keep and callback and not callback(--depth, parse_event_t::object_end, result))
7233  {
7234  result = basic_json(value_t::discarded);
7235  }
7236 
7237  return result;
7238  }
7239 
7240  case lexer::token_type::begin_array:
7241  {
7242  if (keep and (not callback or (keep = callback(depth++, parse_event_t::array_start, result))))
7243  {
7244  // explicitly set result to object to cope with []
7245  result.m_type = value_t::array;
7246  result.m_value = json_value(value_t::array);
7247  }
7248 
7249  // read next token
7250  get_token();
7251 
7252  // closing ] -> we are done
7253  if (last_token == lexer::token_type::end_array)
7254  {
7255  get_token();
7256  if (callback and not callback(--depth, parse_event_t::array_end, result))
7257  {
7258  result = basic_json(value_t::discarded);
7259  }
7260  return result;
7261  }
7262 
7263  // no comma is expected here
7264  unexpect(lexer::token_type::value_separator);
7265 
7266  // otherwise: parse values
7267  do
7268  {
7269  // ugly, but could be fixed with loop reorganization
7270  if (last_token == lexer::token_type::value_separator)
7271  {
7272  get_token();
7273  }
7274 
7275  // parse value
7276  auto value = parse_internal(keep);
7277  if (keep and not value.is_discarded())
7278  {
7279  result.push_back(std::move(value));
7280  }
7281  }
7282  while (last_token == lexer::token_type::value_separator);
7283 
7284  // closing ]
7285  expect(lexer::token_type::end_array);
7286  get_token();
7287  if (keep and callback and not callback(--depth, parse_event_t::array_end, result))
7288  {
7289  result = basic_json(value_t::discarded);
7290  }
7291 
7292  return result;
7293  }
7294 
7295  case lexer::token_type::literal_null:
7296  {
7297  get_token();
7298  result.m_type = value_t::null;
7299  break;
7300  }
7301 
7302  case lexer::token_type::value_string:
7303  {
7304  const auto s = m_lexer.get_string();
7305  get_token();
7306  result = basic_json(s);
7307  break;
7308  }
7309 
7310  case lexer::token_type::literal_true:
7311  {
7312  get_token();
7313  result.m_type = value_t::boolean;
7314  result.m_value = true;
7315  break;
7316  }
7317 
7318  case lexer::token_type::literal_false:
7319  {
7320  get_token();
7321  result.m_type = value_t::boolean;
7322  result.m_value = false;
7323  break;
7324  }
7325 
7326  case lexer::token_type::value_number:
7327  {
7328  auto float_val = m_lexer.get_number();
7329 
7330  // NAN is returned if token could not be translated
7331  // completely
7332  if (std::isnan(float_val))
7333  {
7334  throw std::invalid_argument(std::string("parse error - ") +
7335  m_lexer.get_token() + " is not a number");
7336  }
7337 
7338  get_token();
7339 
7340  // check if conversion loses precision
7341  const auto int_val = static_cast<number_integer_t>(float_val);
7342  if (approx(float_val, static_cast<long double>(int_val)))
7343  {
7344  // we basic_json not lose precision -> return int
7345  result.m_type = value_t::number_integer;
7346  result.m_value = int_val;
7347  }
7348  else
7349  {
7350  // we would lose precision -> returnfloat
7351  result.m_type = value_t::number_float;
7352  result.m_value = static_cast<number_float_t>(float_val);
7353  }
7354  break;
7355  }
7356 
7357  default:
7358  {
7359  // the last token was unexpected
7360  unexpect(last_token);
7361  }
7362  }
7363 
7364  if (keep and callback and not callback(depth, parse_event_t::value, result))
7365  {
7366  result = basic_json(value_t::discarded);
7367  }
7368  return result;
7369  }
7370 
7372  typename lexer::token_type get_token()
7373  {
7374  last_token = m_lexer.scan();
7375  return last_token;
7376  }
7377 
7378  void expect(typename lexer::token_type t) const
7379  {
7380  if (t != last_token)
7381  {
7382  std::string error_msg = "parse error - unexpected \'";
7383  error_msg += m_lexer.get_token();
7384  error_msg += "\' (" + lexer::token_type_name(last_token);
7385  error_msg += "); expected " + lexer::token_type_name(t);
7386  throw std::invalid_argument(error_msg);
7387  }
7388  }
7389 
7390  void unexpect(typename lexer::token_type t) const
7391  {
7392  if (t == last_token)
7393  {
7394  std::string error_msg = "parse error - unexpected \'";
7395  error_msg += m_lexer.get_token();
7396  error_msg += "\' (";
7397  error_msg += lexer::token_type_name(last_token) + ")";
7398  throw std::invalid_argument(error_msg);
7399  }
7400  }
7401 
7402  private:
7404  int depth = 0;
7406  parser_callback_t callback;
7408  typename lexer::token_type last_token = lexer::token_type::uninitialized;
7410  lexer m_lexer;
7411  };
7412 };
7413 
7414 
7416 // presets //
7418 
7426 }
7427 
7428 
7430 // nonmember functions //
7432 
7433 // specialization of std::swap, and std::hash
7434 namespace std
7435 {
7439 template <>
7440 inline void swap(nlohmann::json& j1,
7441  nlohmann::json& j2) noexcept(
7442  is_nothrow_move_constructible<nlohmann::json>::value and
7443  is_nothrow_move_assignable<nlohmann::json>::value
7444  )
7445 {
7446  j1.swap(j2);
7447 }
7448 
7450 template <>
7451 struct hash<nlohmann::json>
7452 {
7454  std::size_t operator()(const nlohmann::json& j) const
7455  {
7456  // a naive hashing via the string representation
7457  const auto& h = hash<nlohmann::json::string_t>();
7458  return h(j.dump());
7459  }
7460 };
7461 }
7462 
7473 inline nlohmann::json operator "" _json(const char* s, std::size_t)
7474 {
7475  return nlohmann::json::parse(reinterpret_cast<nlohmann::json::string_t::value_type*>
7476  (const_cast<char*>(s)));
7477 }
7478 
7479 #endif
basic_json(const number_float_t value)
create a floating-point number (explicit)
Definition: json.hpp:1235
json_reverse_iterator< typename basic_json::iterator > reverse_iterator
a reverse iterator for a basic_json container
Definition: json.hpp:233
iterator_wrapper(basic_json &cont)
construct iterator wrapper from a container
Definition: json.hpp:5925
bool operator!=(const const_iterator &other) const
comparison: not equal
Definition: json.hpp:5422
iterator operator++(int)
post-increment (it++)
Definition: json.hpp:5657
friend bool operator<=(const_reference lhs, const_reference rhs) noexcept
comparison: less than or equal
Definition: json.hpp:4444
iterator insert(const_iterator pos, basic_json &&value)
inserts element
Definition: json.hpp:3925
typename std::allocator_traits< allocator_type >::pointer pointer
the type of an element pointer
Definition: json.hpp:221
json_reverse_iterator operator-(difference_type i) const
subtract from iterator
Definition: json.hpp:5807
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:1483
const_reference operator[](size_type idx) const
access specified array element
Definition: json.hpp:2719
reference operator[](const T(&key)[n])
access specified object element
Definition: json.hpp:2803
typename basic_json::const_pointer pointer
defines a pointer to the type iterated over (value_type)
Definition: json.hpp:5122
const_iterator & operator--()
pre-decrement (–it)
Definition: json.hpp:5367
friend std::istream & operator>>(std::istream &i, basic_json &j)
deserialize from stream
Definition: json.hpp:4642
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:5187
typename basic_json::value_type value_type
the type of the values when the iterator is dereferenced
Definition: json.hpp:5118
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:1743
iterator insert(const_iterator pos, const_iterator first, const_iterator last)
inserts elements
Definition: json.hpp:3996
basic_json(const int value)
create an integer number from an enum type (explicit)
Definition: json.hpp:1171
json_reverse_iterator operator--(int)
post-decrement (it–)
Definition: json.hpp:5779
StringType string_t
a type for a string
Definition: json.hpp:417
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:1443
iterator & operator++()
pre-increment (++it)
Definition: json.hpp:5665
friend bool operator!=(const_reference lhs, const_reference rhs) noexcept
comparison: not equal
Definition: json.hpp:4328
reference operator+=(const typename object_t::value_type &value)
add an object to an object
Definition: json.hpp:3875
ArrayType< basic_json, AllocatorType< basic_json >> array_t
a type for an array
Definition: json.hpp:371
const_iterator & operator++()
pre-increment (++it)
Definition: json.hpp:5331
difference_type operator-(const json_reverse_iterator &other) const
return difference
Definition: json.hpp:5815
basic_json<> json
default JSON class
Definition: json.hpp:7425
reference front()
access the first element
Definition: json.hpp:2921
bool is_array() const noexcept
return whether value is an array
Definition: json.hpp:2023
const_iterator find(typename object_t::key_type key) const
find an element in a JSON object
Definition: json.hpp:3250
std::reverse_iterator< Base > base_iterator
shortcut to the reverse iterator adaptor
Definition: json.hpp:5754
json_reverse_iterator(const typename base_iterator::iterator_type &it)
create reverse iterator from iterator
Definition: json.hpp:5759
a class to store JSON values
Definition: json.hpp:181
json_reverse_iterator & operator--()
pre-decrement (–it)
Definition: json.hpp:5785
void push_back(const typename object_t::value_type &value)
add an object to an object
Definition: json.hpp:3852
friend bool operator==(std::nullptr_t, const_reference v) noexcept
comparison: equal
Definition: json.hpp:4309
const_iterator cbegin() const
returns a const iterator to the first element
Definition: json.hpp:3342
basic_json(const CompatibleObjectType &value)
create an object (implicit)
Definition: json.hpp:942
bool is_string() const noexcept
return whether value is a string
Definition: json.hpp:2040
iterator & operator+=(difference_type i)
add to iterator
Definition: json.hpp:5687
const PointerType get_ptr() const noexcept
get a pointer value (implicit)
Definition: json.hpp:2470
the parser read ] and finished processing a JSON array
const_iterator base_iterator
Definition: json.hpp:5616
a mutable random access iterator for the basic_json class
Definition: json.hpp:5613
iterator & operator-=(difference_type i)
subtract from iterator
Definition: json.hpp:5694
static basic_json parse(std::istream &&i, parser_callback_t cb=nullptr)
Definition: json.hpp:4606
reference operator[](const typename object_t::key_type &key)
access specified object element
Definition: json.hpp:2756
STL namespace.
difference_type operator-(const iterator &other) const
Definition: json.hpp:5716
reference value() const
return the value of an iterator
Definition: json.hpp:5591
iterator insert(const_iterator pos, size_type count, const basic_json &value)
inserts elements
Definition: json.hpp:3950
const_iterator end() const
returns a const iterator to one past the last element
Definition: json.hpp:3375
const_iterator(const const_iterator &other) noexcept
copy constructor
Definition: json.hpp:5182
reference at(const typename object_t::key_type &key)
access specified object element with bounds checking
Definition: json.hpp:2607
reference operator+=(const basic_json &value)
add an object to an array
Definition: json.hpp:3828
object_t::key_type key() const
return the key of an object iterator
Definition: json.hpp:5578
iterator end()
returns an iterator to one past the last element
Definition: json.hpp:3365
ObjectType< StringType, basic_json, std::less< StringType >, AllocatorType< std::pair< const StringType, basic_json >>> object_t
a type for an object
Definition: json.hpp:328
reference operator*()
return a reference to the value pointed to by the iterator
Definition: json.hpp:5645
reverse_iterator rend()
returns an iterator to the reverse-end
Definition: json.hpp:3448
bool is_object() const noexcept
return whether value is an object
Definition: json.hpp:2006
const_iterator operator-(difference_type i)
subtract from iterator
Definition: json.hpp:5514
bool is_discarded() const noexcept
return whether value is discarded
Definition: json.hpp:2062
typename basic_json::const_reference reference
defines a reference to the type iterated over (value_type)
Definition: json.hpp:5124
const_reverse_iterator rend() const
returns a const reverse iterator to one before the first
Definition: json.hpp:3456
basic_json(const CompatibleArrayType &value)
create an array (implicit)
Definition: json.hpp:1006
size_type erase(const typename object_t::key_type &key)
remove element from a JSON object given a key
Definition: json.hpp:3174
bool is_boolean() const noexcept
return whether value is a boolean
Definition: json.hpp:1935
iterator begin()
returns an iterator to the first element
Definition: json.hpp:3310
const_reference at(const typename object_t::key_type &key) const
access specified object element with bounds checking
Definition: json.hpp:2643
AllocatorType< basic_json > allocator_type
the allocator type
Definition: json.hpp:218
bool is_number_integer() const noexcept
return whether value is an integer number
Definition: json.hpp:1971
basic_json(const string_t &value)
create a string (explicit)
Definition: json.hpp:1035
iterator operator+(difference_type i)
add to iterator
Definition: json.hpp:5701
std::function< bool(int depth, parse_event_t event, basic_json &parsed)> parser_callback_t
per-element parser callback type
Definition: json.hpp:803
const_iterator()=default
default constructor
the parser read [ and started to process a JSON array
iterator find(typename object_t::key_type key)
find an element in a JSON object
Definition: json.hpp:3234
friend bool operator>=(const_reference lhs, const_reference rhs) noexcept
comparison: greater than or equal
Definition: json.hpp:4484
iterator & operator--()
pre-decrement (–it)
Definition: json.hpp:5680
friend bool operator<(const_reference lhs, const_reference rhs) noexcept
comparison: less than
Definition: json.hpp:4385
pointer operator->() const
dereference the iterator
Definition: json.hpp:5293
discarded by the the parser callback function
const_iterator cend() const
returns a const iterator to one past the last element
Definition: json.hpp:3397
typename Base::reference reference
the reference type for the pointed-to element
Definition: json.hpp:5756
size_type size() const noexcept
returns the number of elements
Definition: json.hpp:3594
static allocator_type get_allocator()
returns the allocator associated with the container
Definition: json.hpp:243
object (unordered set of name/value pairs)
reference at(size_type idx)
access specified array element with bounds checking
Definition: json.hpp:2539
the parser read } and finished processing a JSON object
iterator()=default
default constructor
json_reverse_iterator(const base_iterator &it)
create reverse iterator from base class
Definition: json.hpp:5763
iterator_wrapper_internal end()
return iterator end (needed for range-based for)
Definition: json.hpp:5936
value_t type() const noexcept
return the type of the JSON value (explicit)
Definition: json.hpp:1864
friend std::ostream & operator>>(const basic_json &j, std::ostream &o)
serialize to stream
Definition: json.hpp:4537
ValueType value(const typename object_t::key_type &key, ValueType default_value) const
access specified object element with default value
Definition: json.hpp:2872
basic_json(size_type count, const basic_json &value)
construct an array with count copies of given value
Definition: json.hpp:1507
object_t::key_type key() const
return the key of an object iterator
Definition: json.hpp:5827
bool is_structured() const noexcept
return whether type is structured
Definition: json.hpp:1901
namespace for Niels Lohmann
Definition: json.hpp:77
typename basic_json::difference_type difference_type
a type to represent differences between iterators
Definition: json.hpp:5120
void swap(array_t &other)
exchanges the values
Definition: json.hpp:4109
reverse_iterator rbegin()
returns an iterator to the reverse-beginning
Definition: json.hpp:3419
iterator_wrapper_internal begin()
return iterator begin (needed for range-based for)
Definition: json.hpp:5930
reference operator[](difference_type n) const
access to successor
Definition: json.hpp:5722
std::size_t size_type
a type to represent container sizes
Definition: json.hpp:215
reference operator+=(basic_json &&value)
add an object to an array
Definition: json.hpp:3795
const_reverse_iterator rbegin() const
returns a const reverse iterator to the last element
Definition: json.hpp:3427
~basic_json()
destructor
Definition: json.hpp:1769
basic_json(const array_t &value)
create an array (explicit)
Definition: json.hpp:969
basic_json(const basic_json &other)
copy constructor
Definition: json.hpp:1649
const_iterator operator+(difference_type i)
add to iterator
Definition: json.hpp:5506
basic_json(boolean_t value)
create a boolean (explicit)
Definition: json.hpp:1108
value_t
the JSON type enumeration
Definition: json.hpp:595
const value_type & const_reference
the type of an element const reference
Definition: json.hpp:209
basic_json(const CompatibleNumberFloatType value) noexcept
create an floating-point number (implicit)
Definition: json.hpp:1281
bool is_null() const noexcept
return whether value is null
Definition: json.hpp:1918
void swap(string_t &other)
exchanges the values
Definition: json.hpp:4169
reference value() const
return the value of an iterator
Definition: json.hpp:5728
void push_back(basic_json &&value)
add an object to an array
Definition: json.hpp:3770
const_iterator operator--(int)
post-decrement (it–)
Definition: json.hpp:5358
void erase(const size_type idx)
remove element from a JSON array given an index
Definition: json.hpp:3201
void clear() noexcept
clears the contents
Definition: json.hpp:3706
basic_json(const CompatibleStringType &value)
create a string (implicit)
Definition: json.hpp:1090
pointer operator->()
dereference the iterator
Definition: json.hpp:5651
basic_json value_type
the type of elements in a basic_json container
Definition: json.hpp:203
array (ordered collection of values)
const_reference front() const
access the first element
Definition: json.hpp:2929
bool operator>=(const const_iterator &other) const
comparison: greater than or equal
Definition: json.hpp:5468
iterator insert(const_iterator pos, std::initializer_list< basic_json > ilist)
inserts elements
Definition: json.hpp:4046
std::ptrdiff_t difference_type
a type to represent differences between iterators
Definition: json.hpp:212
const_iterator & operator+=(difference_type i)
add to iterator
Definition: json.hpp:5474
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:1353
difference_type operator-(const const_iterator &other) const
return difference
Definition: json.hpp:5522
friend bool operator==(const_reference lhs, const_reference rhs) noexcept
comparison: equal
Definition: json.hpp:4244
bool is_number() const noexcept
return whether value is a number
Definition: json.hpp:1953
BooleanType boolean_t
a type for a boolean
Definition: json.hpp:443
const_reverse_iterator crend() const
returns a const reverse iterator to one before the first
Definition: json.hpp:3498
basic_json() noexcept=default
create a null object (implicitly)
the parser read a key of a value in an object
bool empty() const noexcept
checks whether the container is empty
Definition: json.hpp:3540
string_t value(const typename object_t::key_type &key, const char *default_value) const
access specified object element with default value
Definition: json.hpp:2898
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:4081
basic_json(const object_t &value)
create an object (explicit)
Definition: json.hpp:910
json_reverse_iterator< typename basic_json::const_iterator > const_reverse_iterator
a const reverse iterator for a basic_json container
Definition: json.hpp:235
const_reverse_iterator crbegin() const
returns a const reverse iterator to the last element
Definition: json.hpp:3477
reference value() const
return the value of an iterator
Definition: json.hpp:5834
const_iterator(pointer object)
constructor for a given JSON instance
Definition: json.hpp:5132
friend bool operator<(const value_t lhs, const value_t rhs)
comparison operator for JSON types
Definition: json.hpp:4200
iterator(pointer object) noexcept
constructor for a given JSON instance
Definition: json.hpp:5624
bool operator<(const const_iterator &other) const
comparison: smaller
Definition: json.hpp:5428
string_t dump(const int indent=-1) const
serialization
Definition: json.hpp:1835
friend bool operator!=(const_reference v, std::nullptr_t) noexcept
comparison: not equal
Definition: json.hpp:4349
const_iterator & operator-=(difference_type i)
subtract from iterator
Definition: json.hpp:5500
number value (floating-point)
basic_json(const CompatibleNumberIntegerType value) noexcept
create an integer number (implicit)
Definition: json.hpp:1206
static basic_json parse(const string_t &s, parser_callback_t cb=nullptr)
deserialize from string
Definition: json.hpp:4574
InteratorType erase(InteratorType first, InteratorType last)
remove elements given an iterator range
Definition: json.hpp:3102
json_reverse_iterator operator++(int)
post-increment (it++)
Definition: json.hpp:5766
PointerType get_ptr() noexcept
get a pointer value (implicit)
Definition: json.hpp:2455
void push_back(const basic_json &value)
add an object to an array
Definition: json.hpp:3805
const_iterator(const iterator &other)
copy constructor given a nonconst iterator
Definition: json.hpp:5157
friend bool operator!=(std::nullptr_t, const_reference v) noexcept
comparison: not equal
Definition: json.hpp:4358
InteratorType erase(InteratorType pos)
remove element given an iterator
Definition: json.hpp:3009
basic_json(const typename string_t::value_type *value)
create a string (explicit)
Definition: json.hpp:1059
bool operator<=(const const_iterator &other) const
comparison: less than or equal
Definition: json.hpp:5456
reference back()
access the last element
Definition: json.hpp:2953
bool is_number_float() const noexcept
return whether value is a floating-point number
Definition: json.hpp:1989
the parser read { and started to process a JSON object
const_iterator operator++(int)
post-increment (it++)
Definition: json.hpp:5322
typename std::allocator_traits< allocator_type >::const_pointer const_pointer
the type of an element const pointer
Definition: json.hpp:223
iterator(const iterator &other) noexcept
copy constructor
Definition: json.hpp:5628
const_reference back() const
access the last element
Definition: json.hpp:2963
basic_json(InputIT first, InputIT last)
construct a JSON container given an iterator range
Definition: json.hpp:1551
static basic_json parse(std::istream &i, parser_callback_t cb=nullptr)
deserialize from stream
Definition: json.hpp:4601
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:3278
size_type max_size() const noexcept
returns the maximum possible number of elements
Definition: json.hpp:3651
bool operator==(const const_iterator &other) const
comparison: equal
Definition: json.hpp:5394
json_reverse_iterator & operator++()
pre-increment (++it)
Definition: json.hpp:5772
bool operator>(const const_iterator &other) const
comparison: greater than
Definition: json.hpp:5462
friend bool operator>(const_reference lhs, const_reference rhs) noexcept
comparison: greater than
Definition: json.hpp:4464
basic_json(basic_json &&other) noexcept
move constructor
Definition: json.hpp:1715
const_iterator begin() const
returns a const iterator to the first element
Definition: json.hpp:3320
const_reference at(size_type idx) const
access specified array element with bounds checking
Definition: json.hpp:2571
json_reverse_iterator & operator+=(difference_type i)
add to iterator
Definition: json.hpp:5792
a const random access iterator for the basic_json class
Definition: json.hpp:5111
a template for a reverse iterator class
Definition: json.hpp:226
void swap(object_t &other)
exchanges the values
Definition: json.hpp:4139
std::bidirectional_iterator_tag iterator_category
the category of the iterator
Definition: json.hpp:5126
bool is_primitive() const noexcept
return whether type is primitive
Definition: json.hpp:1883
basic_json(const value_t value)
create an empty value with a given type
Definition: json.hpp:843
friend bool operator==(const_reference v, std::nullptr_t) noexcept
comparison: equal
Definition: json.hpp:4300
reference operator[](difference_type n) const
access to successor
Definition: json.hpp:5821
NumberIntegerType number_integer_t
a type for a number (integer)
Definition: json.hpp:511
reference operator[](difference_type n) const
access to successor
Definition: json.hpp:5544
reference operator*() const
return a reference to the value pointed to by the iterator
Definition: json.hpp:5259
iterator insert(const_iterator pos, const basic_json &value)
inserts element
Definition: json.hpp:3899
value_type & reference
the type of an element reference
Definition: json.hpp:206
friend std::istream & operator<<(basic_json &j, std::istream &i)
deserialize from stream
Definition: json.hpp:4632
the parser finished reading a JSON value
NumberFloatType number_float_t
a type for a number (floating-point)
Definition: json.hpp:576
std::size_t operator()(const nlohmann::json &j) const
return a hash value for a JSON object
Definition: json.hpp:7454
friend std::ostream & operator<<(std::ostream &o, const basic_json &j)
serialize to stream
Definition: json.hpp:4519
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:5633
reference operator[](size_type idx)
access specified array element
Definition: json.hpp:2678
iterator operator--(int)
post-decrement (it–)
Definition: json.hpp:5672
json_reverse_iterator operator+(difference_type i) const
add to iterator
Definition: json.hpp:5799
parse_event_t
JSON callback events.
Definition: json.hpp:738
iterator operator-(difference_type i)
subtract from iterator
Definition: json.hpp:5709
wrapper to access iterator member functions in range-based for
Definition: json.hpp:5848