JSON for Modern C++  2.0.0
json.hpp
1 /*
2  __ _____ _____ _____
3  __| | __| | | | JSON for Modern C++
4 | | |__ | | | | | | version 2.0.0
5 |_____|_____|_____|_|___| https://github.com/nlohmann/json
6 
7 Licensed under the MIT License <http://opensource.org/licenses/MIT>.
8 Copyright (c) 2013-2016 Niels Lohmann <http://nlohmann.me>.
9 
10 Permission is hereby granted, free of charge, to any person obtaining a copy
11 of this software and associated documentation files (the "Software"), to deal
12 in the Software without restriction, including without limitation the rights
13 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
14 copies of the Software, and to permit persons to whom the Software is
15 furnished to do so, subject to the following conditions:
16 
17 The above copyright notice and this permission notice shall be included in all
18 copies or substantial portions of the Software.
19 
20 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
23 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
25 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
26 SOFTWARE.
27 */
28 
29 #ifndef NLOHMANN_JSON_HPP
30 #define NLOHMANN_JSON_HPP
31 
32 #include <algorithm>
33 #include <array>
34 #include <cassert>
35 #include <cerrno>
36 #include <ciso646>
37 #include <cmath>
38 #include <cstddef>
39 #include <cstdio>
40 #include <cstdlib>
41 #include <functional>
42 #include <initializer_list>
43 #include <iomanip>
44 #include <iostream>
45 #include <iterator>
46 #include <limits>
47 #include <map>
48 #include <memory>
49 #include <sstream>
50 #include <stdexcept>
51 #include <string>
52 #include <type_traits>
53 #include <utility>
54 #include <vector>
55 
56 // disable float-equal warnings on GCC/clang
57 #if defined(__clang__) || defined(__GNUC__) || defined(__GNUG__)
58  #pragma GCC diagnostic push
59  #pragma GCC diagnostic ignored "-Wfloat-equal"
60 #endif
61 
67 namespace nlohmann
68 {
69 
70 
75 namespace
76 {
81 template<typename T>
82 struct has_mapped_type
83 {
84  private:
85  template<typename C> static char test(typename C::mapped_type*);
86  template<typename C> static char (&test(...))[2];
87  public:
88  static constexpr bool value = sizeof(test<T>(0)) == 1;
89 };
90 
95 class DecimalSeparator : public std::numpunct<char>
96 {
97  protected:
98  char do_decimal_point() const
99  {
100  return '.';
101  }
102 };
103 
104 }
105 
177 template <
178  template<typename U, typename V, typename... Args> class ObjectType = std::map,
179  template<typename U, typename... Args> class ArrayType = std::vector,
180  class StringType = std::string,
181  class BooleanType = bool,
182  class NumberIntegerType = std::int64_t,
183  class NumberUnsignedType = std::uint64_t,
184  class NumberFloatType = double,
185  template<typename U> class AllocatorType = std::allocator
186  >
188 {
189  private:
191  using basic_json_t = basic_json<ObjectType,
192  ArrayType,
193  StringType,
194  BooleanType,
195  NumberIntegerType,
196  NumberUnsignedType,
197  NumberFloatType,
198  AllocatorType>;
199 
200  public:
201  // forward declarations
202  template<typename Base> class json_reverse_iterator;
203  class json_pointer;
204 
206  // container types //
208 
211 
214 
218  using const_reference = const value_type&;
219 
221  using difference_type = std::ptrdiff_t;
223  using size_type = std::size_t;
224 
226  using allocator_type = AllocatorType<basic_json>;
227 
229  using pointer = typename std::allocator_traits<allocator_type>::pointer;
231  using const_pointer = typename std::allocator_traits<allocator_type>::const_pointer;
232 
234  class iterator;
236  class const_iterator;
241 
243 
244 
249  {
250  return allocator_type();
251  }
252 
253 
255  // JSON value data types //
257 
260 
343  using object_t = ObjectType<StringType,
344  basic_json,
345  std::less<StringType>,
346  AllocatorType<std::pair<const StringType,
347  basic_json>>>;
348 
393  using array_t = ArrayType<basic_json, AllocatorType<basic_json>>;
394 
440  using string_t = StringType;
441 
466  using boolean_t = BooleanType;
467 
537  using number_integer_t = NumberIntegerType;
538 
609  using number_unsigned_t = NumberUnsignedType;
610 
677  using number_float_t = NumberFloatType;
678 
680 
681 
683  // JSON type enumeration //
685 
696  enum class value_t : uint8_t
697  {
698  null,
699  object,
700  array,
701  string,
702  boolean,
703  number_integer,
704  number_unsigned,
705  number_float,
706  discarded
707  };
708 
709 
710  private:
711 
726  union type_data_t
727  {
728  struct
729  {
731  uint16_t type : 4;
733  uint16_t parsed : 1;
735  uint16_t has_exp : 1;
737  uint16_t exp_plus : 1;
739  uint16_t exp_cap : 1;
741  uint16_t precision : 8;
742  } bits;
743  uint16_t data;
744 
746  operator value_t() const
747  {
748  return static_cast<value_t>(bits.type);
749  }
750 
752  bool operator==(const value_t& rhs) const
753  {
754  return static_cast<value_t>(bits.type) == rhs;
755  }
756 
758  type_data_t& operator=(value_t rhs)
759  {
760  bits.type = static_cast<uint16_t>(rhs);
761  return *this;
762  }
763 
765  type_data_t(value_t t) noexcept
766  {
767  *reinterpret_cast<uint16_t*>(this) = 0;
768  bits.type = static_cast<uint16_t>(t);
769  }
770 
772  type_data_t() noexcept
773  {
774  data = 0;
775  bits.type = reinterpret_cast<uint16_t>(value_t::null);
776  }
777  };
778 
780  template<typename T, typename... Args>
781  static T* create(Args&& ... args)
782  {
783  AllocatorType<T> alloc;
784  auto deleter = [&](T * object)
785  {
786  alloc.deallocate(object, 1);
787  };
788  std::unique_ptr<T, decltype(deleter)> object(alloc.allocate(1), deleter);
789  alloc.construct(object.get(), std::forward<Args>(args)...);
790  return object.release();
791  }
792 
794  // JSON value storage //
796 
804  union json_value
805  {
807  object_t* object;
809  array_t* array;
811  string_t* string;
813  boolean_t boolean;
815  number_integer_t number_integer;
817  number_unsigned_t number_unsigned;
819  number_float_t number_float;
820 
822  json_value() = default;
824  json_value(boolean_t v) noexcept : boolean(v) {}
826  json_value(number_integer_t v) noexcept : number_integer(v) {}
828  json_value(number_unsigned_t v) noexcept : number_unsigned(v) {}
830  json_value(number_float_t v) noexcept : number_float(v) {}
832  json_value(value_t t)
833  {
834  switch (t)
835  {
836  case value_t::object:
837  {
838  object = create<object_t>();
839  break;
840  }
841 
842  case value_t::array:
843  {
844  array = create<array_t>();
845  break;
846  }
847 
848  case value_t::string:
849  {
850  string = create<string_t>("");
851  break;
852  }
853 
854  case value_t::boolean:
855  {
856  boolean = boolean_t(false);
857  break;
858  }
859 
860  case value_t::number_integer:
861  {
862  number_integer = number_integer_t(0);
863  break;
864  }
865 
866  case value_t::number_unsigned:
867  {
868  number_unsigned = number_unsigned_t(0);
869  break;
870  }
871 
872  case value_t::number_float:
873  {
874  number_float = number_float_t(0.0);
875  break;
876  }
877 
878  default:
879  {
880  break;
881  }
882  }
883  }
884 
886  json_value(const string_t& value)
887  {
888  string = create<string_t>(value);
889  }
890 
892  json_value(const object_t& value)
893  {
894  object = create<object_t>(value);
895  }
896 
898  json_value(const array_t& value)
899  {
900  array = create<array_t>(value);
901  }
902  };
903 
904 
905  public:
907  // JSON parser callback //
909 
918  enum class parse_event_t : uint8_t
919  {
921  object_start,
923  object_end,
925  array_start,
927  array_end,
929  key,
931  value
932  };
933 
983  using parser_callback_t = std::function<bool(int depth, parse_event_t event, basic_json& parsed)>;
984 
985 
987  // constructors //
989 
992 
1033  : m_type(value_type), m_value(value_type)
1034  {}
1035 
1060  basic_json() = default;
1061 
1084  basic_json(std::nullptr_t) noexcept
1085  : basic_json(value_t::null)
1086  {}
1087 
1107  basic_json(const object_t& val)
1108  : m_type(value_t::object), m_value(val)
1109  {}
1110 
1137  template <class CompatibleObjectType, typename
1138  std::enable_if<
1139  std::is_constructible<typename object_t::key_type, typename CompatibleObjectType::key_type>::value and
1140  std::is_constructible<basic_json, typename CompatibleObjectType::mapped_type>::value, int>::type
1141  = 0>
1142  basic_json(const CompatibleObjectType& val)
1143  : m_type(value_t::object)
1144  {
1145  using std::begin;
1146  using std::end;
1147  m_value.object = create<object_t>(begin(val), end(val));
1148  }
1149 
1169  basic_json(const array_t& val)
1170  : m_type(value_t::array), m_value(val)
1171  {}
1172 
1199  template <class CompatibleArrayType, typename
1200  std::enable_if<
1201  not std::is_same<CompatibleArrayType, typename basic_json_t::iterator>::value and
1202  not std::is_same<CompatibleArrayType, typename basic_json_t::const_iterator>::value and
1203  not std::is_same<CompatibleArrayType, typename basic_json_t::reverse_iterator>::value and
1204  not std::is_same<CompatibleArrayType, typename basic_json_t::const_reverse_iterator>::value and
1205  not std::is_same<CompatibleArrayType, typename array_t::iterator>::value and
1206  not std::is_same<CompatibleArrayType, typename array_t::const_iterator>::value and
1207  std::is_constructible<basic_json, typename CompatibleArrayType::value_type>::value, int>::type
1208  = 0>
1209  basic_json(const CompatibleArrayType& val)
1210  : m_type(value_t::array)
1211  {
1212  using std::begin;
1213  using std::end;
1214  m_value.array = create<array_t>(begin(val), end(val));
1215  }
1216 
1238  basic_json(const string_t& val)
1239  : m_type(value_t::string), m_value(val)
1240  {}
1241 
1262  basic_json(const typename string_t::value_type* val)
1263  : basic_json(string_t(val))
1264  {}
1265 
1289  template <class CompatibleStringType, typename
1290  std::enable_if<
1291  std::is_constructible<string_t, CompatibleStringType>::value, int>::type
1292  = 0>
1293  basic_json(const CompatibleStringType& val)
1294  : basic_json(string_t(val))
1295  {}
1296 
1311  basic_json(boolean_t val) noexcept
1312  : m_type(value_t::boolean), m_value(val)
1313  {}
1314 
1338  template<typename T,
1339  typename std::enable_if<
1340  not (std::is_same<T, int>::value)
1341  and std::is_same<T, number_integer_t>::value
1342  , int>::type
1343  = 0>
1344  basic_json(const number_integer_t val) noexcept
1345  : m_type(value_t::number_integer), m_value(val)
1346  {}
1347 
1373  basic_json(const int val) noexcept
1374  : m_type(value_t::number_integer),
1375  m_value(static_cast<number_integer_t>(val))
1376  {}
1377 
1403  template<typename CompatibleNumberIntegerType, typename
1404  std::enable_if<
1405  std::is_constructible<number_integer_t, CompatibleNumberIntegerType>::value and
1406  std::numeric_limits<CompatibleNumberIntegerType>::is_integer and
1407  std::numeric_limits<CompatibleNumberIntegerType>::is_signed,
1408  CompatibleNumberIntegerType>::type
1409  = 0>
1410  basic_json(const CompatibleNumberIntegerType val) noexcept
1411  : m_type(value_t::number_integer),
1412  m_value(static_cast<number_integer_t>(val))
1413  {}
1414 
1432  template<typename T,
1433  typename std::enable_if<
1434  not (std::is_same<T, int>::value)
1435  and std::is_same<T, number_unsigned_t>::value
1436  , int>::type
1437  = 0>
1438  basic_json(const number_unsigned_t val) noexcept
1439  : m_type(value_t::number_unsigned), m_value(val)
1440  {}
1441 
1462  template < typename CompatibleNumberUnsignedType, typename
1463  std::enable_if <
1464  std::is_constructible<number_unsigned_t, CompatibleNumberUnsignedType>::value and
1465  std::numeric_limits<CompatibleNumberUnsignedType>::is_integer and
1466  !std::numeric_limits<CompatibleNumberUnsignedType>::is_signed,
1467  CompatibleNumberUnsignedType >::type
1468  = 0 >
1469  basic_json(const CompatibleNumberUnsignedType val) noexcept
1470  : m_type(value_t::number_unsigned),
1471  m_value(static_cast<number_unsigned_t>(val))
1472  {}
1473 
1498  basic_json(const number_float_t val) noexcept
1499  : m_type(value_t::number_float), m_value(val)
1500  {
1501  // replace infinity and NAN by null
1502  if (not std::isfinite(val))
1503  {
1504  m_type = value_t::null;
1505  m_value = json_value();
1506  }
1507  }
1508 
1539  template<typename CompatibleNumberFloatType, typename = typename
1540  std::enable_if<
1541  std::is_constructible<number_float_t, CompatibleNumberFloatType>::value and
1542  std::is_floating_point<CompatibleNumberFloatType>::value>::type
1543  >
1544  basic_json(const CompatibleNumberFloatType val) noexcept
1545  : basic_json(number_float_t(val))
1546  {}
1547 
1617  basic_json(std::initializer_list<basic_json> init,
1618  bool type_deduction = true,
1619  value_t manual_type = value_t::array)
1620  {
1621  // the initializer list could describe an object
1622  bool is_an_object = true;
1623 
1624  // check if each element is an array with two elements whose first
1625  // element is a string
1626  for (const auto& element : init)
1627  {
1628  if (not element.is_array() or element.size() != 2
1629  or not element[0].is_string())
1630  {
1631  // we found an element that makes it impossible to use the
1632  // initializer list as object
1633  is_an_object = false;
1634  break;
1635  }
1636  }
1637 
1638  // adjust type if type deduction is not wanted
1639  if (not type_deduction)
1640  {
1641  // if array is wanted, do not create an object though possible
1642  if (manual_type == value_t::array)
1643  {
1644  is_an_object = false;
1645  }
1646 
1647  // if object is wanted but impossible, throw an exception
1648  if (manual_type == value_t::object and not is_an_object)
1649  {
1650  throw std::domain_error("cannot create object from initializer list");
1651  }
1652  }
1653 
1654  if (is_an_object)
1655  {
1656  // the initializer list is a list of pairs -> create object
1657  m_type = value_t::object;
1658  m_value = value_t::object;
1659 
1660  assert(m_value.object != nullptr);
1661 
1662  for (auto& element : init)
1663  {
1664  m_value.object->emplace(*(element[0].m_value.string), element[1]);
1665  }
1666  }
1667  else
1668  {
1669  // the initializer list describes an array -> create array
1670  m_type = value_t::array;
1671  m_value.array = create<array_t>(init);
1672  }
1673  }
1674 
1709  static basic_json array(std::initializer_list<basic_json> init =
1710  std::initializer_list<basic_json>())
1711  {
1712  return basic_json(init, false, value_t::array);
1713  }
1714 
1749  static basic_json object(std::initializer_list<basic_json> init =
1750  std::initializer_list<basic_json>())
1751  {
1752  return basic_json(init, false, value_t::object);
1753  }
1754 
1773  basic_json(size_type cnt, const basic_json& val)
1774  : m_type(value_t::array)
1775  {
1776  m_value.array = create<array_t>(cnt, val);
1777  }
1778 
1813  template <class InputIT, typename
1814  std::enable_if<
1815  std::is_same<InputIT, typename basic_json_t::iterator>::value or
1816  std::is_same<InputIT, typename basic_json_t::const_iterator>::value
1817  , int>::type
1818  = 0>
1819  basic_json(InputIT first, InputIT last) : m_type(first.m_object->m_type)
1820  {
1821  // make sure iterator fits the current value
1822  if (first.m_object != last.m_object)
1823  {
1824  throw std::domain_error("iterators are not compatible");
1825  }
1826 
1827  // check if iterator range is complete for primitive values
1828  switch (m_type)
1829  {
1830  case value_t::boolean:
1831  case value_t::number_float:
1832  case value_t::number_integer:
1833  case value_t::number_unsigned:
1834  case value_t::string:
1835  {
1836  if (not first.m_it.primitive_iterator.is_begin() or not last.m_it.primitive_iterator.is_end())
1837  {
1838  throw std::out_of_range("iterators out of range");
1839  }
1840  break;
1841  }
1842 
1843  default:
1844  {
1845  break;
1846  }
1847  }
1848 
1849  switch (m_type)
1850  {
1851  case value_t::number_integer:
1852  {
1853  assert(first.m_object != nullptr);
1854  m_value.number_integer = first.m_object->m_value.number_integer;
1855  break;
1856  }
1857 
1858  case value_t::number_unsigned:
1859  {
1860  assert(first.m_object != nullptr);
1861  m_value.number_unsigned = first.m_object->m_value.number_unsigned;
1862  break;
1863  }
1864 
1865  case value_t::number_float:
1866  {
1867  assert(first.m_object != nullptr);
1868  m_value.number_float = first.m_object->m_value.number_float;
1869  break;
1870  }
1871 
1872  case value_t::boolean:
1873  {
1874  assert(first.m_object != nullptr);
1875  m_value.boolean = first.m_object->m_value.boolean;
1876  break;
1877  }
1878 
1879  case value_t::string:
1880  {
1881  assert(first.m_object != nullptr);
1882  m_value = *first.m_object->m_value.string;
1883  break;
1884  }
1885 
1886  case value_t::object:
1887  {
1888  m_value.object = create<object_t>(first.m_it.object_iterator, last.m_it.object_iterator);
1889  break;
1890  }
1891 
1892  case value_t::array:
1893  {
1894  m_value.array = create<array_t>(first.m_it.array_iterator, last.m_it.array_iterator);
1895  break;
1896  }
1897 
1898  default:
1899  {
1900  assert(first.m_object != nullptr);
1901  throw std::domain_error("cannot use construct with iterators from " + first.m_object->type_name());
1902  }
1903  }
1904  }
1905 
1926  explicit basic_json(std::istream& i, parser_callback_t cb = nullptr)
1927  {
1928  *this = parser(i, cb).parse();
1929  }
1930 
1932  // other constructors and destructor //
1934 
1957  basic_json(const basic_json& other)
1958  : m_type(other.m_type)
1959  {
1960  switch (m_type)
1961  {
1962  case value_t::object:
1963  {
1964  assert(other.m_value.object != nullptr);
1965  m_value = *other.m_value.object;
1966  break;
1967  }
1968 
1969  case value_t::array:
1970  {
1971  assert(other.m_value.array != nullptr);
1972  m_value = *other.m_value.array;
1973  break;
1974  }
1975 
1976  case value_t::string:
1977  {
1978  assert(other.m_value.string != nullptr);
1979  m_value = *other.m_value.string;
1980  break;
1981  }
1982 
1983  case value_t::boolean:
1984  {
1985  m_value = other.m_value.boolean;
1986  break;
1987  }
1988 
1989  case value_t::number_integer:
1990  {
1991  m_value = other.m_value.number_integer;
1992  break;
1993  }
1994 
1995  case value_t::number_unsigned:
1996  {
1997  m_value = other.m_value.number_unsigned;
1998  break;
1999  }
2000 
2001  case value_t::number_float:
2002  {
2003  m_value = other.m_value.number_float;
2004  break;
2005  }
2006 
2007  default:
2008  {
2009  break;
2010  }
2011  }
2012  }
2013 
2032  basic_json(basic_json&& other) noexcept
2033  : m_type(std::move(other.m_type)),
2034  m_value(std::move(other.m_value))
2035  {
2036  // invalidate payload
2037  other.m_type = value_t::null;
2038  other.m_value = {};
2039  }
2040 
2064  reference& operator=(basic_json other) noexcept (
2065  std::is_nothrow_move_constructible<value_t>::value and
2066  std::is_nothrow_move_assignable<value_t>::value and
2067  std::is_nothrow_move_constructible<json_value>::value and
2068  std::is_nothrow_move_assignable<json_value>::value
2069  )
2070  {
2071  using std::swap;
2072  swap(m_type, other.m_type);
2073  swap(m_value, other.m_value);
2074  return *this;
2075  }
2076 
2093  {
2094  switch (m_type)
2095  {
2096  case value_t::object:
2097  {
2098  AllocatorType<object_t> alloc;
2099  alloc.destroy(m_value.object);
2100  alloc.deallocate(m_value.object, 1);
2101  break;
2102  }
2103 
2104  case value_t::array:
2105  {
2106  AllocatorType<array_t> alloc;
2107  alloc.destroy(m_value.array);
2108  alloc.deallocate(m_value.array, 1);
2109  break;
2110  }
2111 
2112  case value_t::string:
2113  {
2114  AllocatorType<string_t> alloc;
2115  alloc.destroy(m_value.string);
2116  alloc.deallocate(m_value.string, 1);
2117  break;
2118  }
2119 
2120  default:
2121  {
2122  // all other types need no specific destructor
2123  break;
2124  }
2125  }
2126  }
2127 
2129 
2130  public:
2132  // object inspection //
2134 
2137 
2161  string_t dump(const int indent = -1) const
2162  {
2163  std::stringstream ss;
2164 
2165  if (indent >= 0)
2166  {
2167  dump(ss, true, static_cast<unsigned int>(indent));
2168  }
2169  else
2170  {
2171  dump(ss, false, 0);
2172  }
2173 
2174  return ss.str();
2175  }
2176 
2195  constexpr value_t type() const noexcept
2196  {
2197  return m_type;
2198  }
2199 
2225  constexpr bool is_primitive() const noexcept
2226  {
2227  return is_null() or is_string() or is_boolean() or is_number();
2228  }
2229 
2252  constexpr bool is_structured() const noexcept
2253  {
2254  return is_array() or is_object();
2255  }
2256 
2274  constexpr bool is_null() const noexcept
2275  {
2276  return m_type == value_t::null;
2277  }
2278 
2296  constexpr bool is_boolean() const noexcept
2297  {
2298  return m_type == value_t::boolean;
2299  }
2300 
2326  constexpr bool is_number() const noexcept
2327  {
2328  return is_number_integer() or is_number_float();
2329  }
2330 
2355  constexpr bool is_number_integer() const noexcept
2356  {
2357  return m_type == value_t::number_integer or m_type == value_t::number_unsigned;
2358  }
2359 
2383  constexpr bool is_number_unsigned() const noexcept
2384  {
2385  return m_type == value_t::number_unsigned;
2386  }
2387 
2411  constexpr bool is_number_float() const noexcept
2412  {
2413  return m_type == value_t::number_float;
2414  }
2415 
2433  constexpr bool is_object() const noexcept
2434  {
2435  return m_type == value_t::object;
2436  }
2437 
2455  constexpr bool is_array() const noexcept
2456  {
2457  return m_type == value_t::array;
2458  }
2459 
2477  constexpr bool is_string() const noexcept
2478  {
2479  return m_type == value_t::string;
2480  }
2481 
2504  constexpr bool is_discarded() const noexcept
2505  {
2506  return m_type == value_t::discarded;
2507  }
2508 
2527  constexpr operator value_t() const noexcept
2528  {
2529  return m_type;
2530  }
2531 
2533 
2534  private:
2536  // value access //
2538 
2540  template <class T, typename
2541  std::enable_if<
2542  std::is_convertible<typename object_t::key_type, typename T::key_type>::value and
2543  std::is_convertible<basic_json_t, typename T::mapped_type>::value
2544  , int>::type = 0>
2545  T get_impl(T*) const
2546  {
2547  if (is_object())
2548  {
2549  assert(m_value.object != nullptr);
2550  return T(m_value.object->begin(), m_value.object->end());
2551  }
2552  else
2553  {
2554  throw std::domain_error("type must be object, but is " + type_name());
2555  }
2556  }
2557 
2559  object_t get_impl(object_t*) const
2560  {
2561  if (is_object())
2562  {
2563  assert(m_value.object != nullptr);
2564  return *(m_value.object);
2565  }
2566  else
2567  {
2568  throw std::domain_error("type must be object, but is " + type_name());
2569  }
2570  }
2571 
2573  template <class T, typename
2574  std::enable_if<
2575  std::is_convertible<basic_json_t, typename T::value_type>::value and
2576  not std::is_same<basic_json_t, typename T::value_type>::value and
2577  not std::is_arithmetic<T>::value and
2578  not std::is_convertible<std::string, T>::value and
2579  not has_mapped_type<T>::value
2580  , int>::type = 0>
2581  T get_impl(T*) const
2582  {
2583  if (is_array())
2584  {
2585  T to_vector;
2586  assert(m_value.array != nullptr);
2587  std::transform(m_value.array->begin(), m_value.array->end(),
2588  std::inserter(to_vector, to_vector.end()), [](basic_json i)
2589  {
2590  return i.get<typename T::value_type>();
2591  });
2592  return to_vector;
2593  }
2594  else
2595  {
2596  throw std::domain_error("type must be array, but is " + type_name());
2597  }
2598  }
2599 
2601  template <class T, typename
2602  std::enable_if<
2603  std::is_convertible<basic_json_t, T>::value and
2604  not std::is_same<basic_json_t, T>::value
2605  , int>::type = 0>
2606  std::vector<T> get_impl(std::vector<T>*) const
2607  {
2608  if (is_array())
2609  {
2610  std::vector<T> to_vector;
2611  assert(m_value.array != nullptr);
2612  to_vector.reserve(m_value.array->size());
2613  std::transform(m_value.array->begin(), m_value.array->end(),
2614  std::inserter(to_vector, to_vector.end()), [](basic_json i)
2615  {
2616  return i.get<T>();
2617  });
2618  return to_vector;
2619  }
2620  else
2621  {
2622  throw std::domain_error("type must be array, but is " + type_name());
2623  }
2624  }
2625 
2627  template <class T, typename
2628  std::enable_if<
2629  std::is_same<basic_json, typename T::value_type>::value and
2630  not has_mapped_type<T>::value
2631  , int>::type = 0>
2632  T get_impl(T*) const
2633  {
2634  if (is_array())
2635  {
2636  assert(m_value.array != nullptr);
2637  return T(m_value.array->begin(), m_value.array->end());
2638  }
2639  else
2640  {
2641  throw std::domain_error("type must be array, but is " + type_name());
2642  }
2643  }
2644 
2646  array_t get_impl(array_t*) const
2647  {
2648  if (is_array())
2649  {
2650  assert(m_value.array != nullptr);
2651  return *(m_value.array);
2652  }
2653  else
2654  {
2655  throw std::domain_error("type must be array, but is " + type_name());
2656  }
2657  }
2658 
2660  template <typename T, typename
2661  std::enable_if<
2662  std::is_convertible<string_t, T>::value
2663  , int>::type = 0>
2664  T get_impl(T*) const
2665  {
2666  if (is_string())
2667  {
2668  assert(m_value.string != nullptr);
2669  return *m_value.string;
2670  }
2671  else
2672  {
2673  throw std::domain_error("type must be string, but is " + type_name());
2674  }
2675  }
2676 
2678  template<typename T, typename
2679  std::enable_if<
2680  std::is_arithmetic<T>::value
2681  , int>::type = 0>
2682  T get_impl(T*) const
2683  {
2684  switch (m_type)
2685  {
2686  case value_t::number_integer:
2687  {
2688  return static_cast<T>(m_value.number_integer);
2689  }
2690 
2691  case value_t::number_unsigned:
2692  {
2693  return static_cast<T>(m_value.number_unsigned);
2694  }
2695 
2696  case value_t::number_float:
2697  {
2698  return static_cast<T>(m_value.number_float);
2699  }
2700 
2701  default:
2702  {
2703  throw std::domain_error("type must be number, but is " + type_name());
2704  }
2705  }
2706  }
2707 
2709  constexpr boolean_t get_impl(boolean_t*) const
2710  {
2711  return is_boolean()
2712  ? m_value.boolean
2713  : throw std::domain_error("type must be boolean, but is " + type_name());
2714  }
2715 
2717  object_t* get_impl_ptr(object_t*) noexcept
2718  {
2719  return is_object() ? m_value.object : nullptr;
2720  }
2721 
2723  constexpr const object_t* get_impl_ptr(const object_t*) const noexcept
2724  {
2725  return is_object() ? m_value.object : nullptr;
2726  }
2727 
2729  array_t* get_impl_ptr(array_t*) noexcept
2730  {
2731  return is_array() ? m_value.array : nullptr;
2732  }
2733 
2735  constexpr const array_t* get_impl_ptr(const array_t*) const noexcept
2736  {
2737  return is_array() ? m_value.array : nullptr;
2738  }
2739 
2741  string_t* get_impl_ptr(string_t*) noexcept
2742  {
2743  return is_string() ? m_value.string : nullptr;
2744  }
2745 
2747  constexpr const string_t* get_impl_ptr(const string_t*) const noexcept
2748  {
2749  return is_string() ? m_value.string : nullptr;
2750  }
2751 
2753  boolean_t* get_impl_ptr(boolean_t*) noexcept
2754  {
2755  return is_boolean() ? &m_value.boolean : nullptr;
2756  }
2757 
2759  constexpr const boolean_t* get_impl_ptr(const boolean_t*) const noexcept
2760  {
2761  return is_boolean() ? &m_value.boolean : nullptr;
2762  }
2763 
2765  number_integer_t* get_impl_ptr(number_integer_t*) noexcept
2766  {
2767  return is_number_integer() ? &m_value.number_integer : nullptr;
2768  }
2769 
2771  constexpr const number_integer_t* get_impl_ptr(const number_integer_t*) const noexcept
2772  {
2773  return is_number_integer() ? &m_value.number_integer : nullptr;
2774  }
2775 
2777  number_unsigned_t* get_impl_ptr(number_unsigned_t*) noexcept
2778  {
2779  return is_number_unsigned() ? &m_value.number_unsigned : nullptr;
2780  }
2781 
2783  constexpr const number_unsigned_t* get_impl_ptr(const number_unsigned_t*) const noexcept
2784  {
2785  return is_number_unsigned() ? &m_value.number_unsigned : nullptr;
2786  }
2787 
2789  number_float_t* get_impl_ptr(number_float_t*) noexcept
2790  {
2791  return is_number_float() ? &m_value.number_float : nullptr;
2792  }
2793 
2795  constexpr const number_float_t* get_impl_ptr(const number_float_t*) const noexcept
2796  {
2797  return is_number_float() ? &m_value.number_float : nullptr;
2798  }
2799 
2811  template<typename ReferenceType, typename ThisType>
2812  static ReferenceType get_ref_impl(ThisType& obj)
2813  {
2814  // delegate the call to get_ptr<>()
2815  using PointerType = typename std::add_pointer<ReferenceType>::type;
2816  auto ptr = obj.template get_ptr<PointerType>();
2817 
2818  if (ptr != nullptr)
2819  {
2820  return *ptr;
2821  }
2822  else
2823  {
2824  throw std::domain_error("incompatible ReferenceType for get_ref, actual type is " +
2825  obj.type_name());
2826  }
2827  }
2828 
2829  public:
2830 
2833 
2867  template<typename ValueType, typename
2868  std::enable_if<
2869  not std::is_pointer<ValueType>::value
2870  , int>::type = 0>
2871  ValueType get() const
2872  {
2873  return get_impl(static_cast<ValueType*>(nullptr));
2874  }
2875 
2902  template<typename PointerType, typename
2903  std::enable_if<
2904  std::is_pointer<PointerType>::value
2905  , int>::type = 0>
2906  PointerType get() noexcept
2907  {
2908  // delegate the call to get_ptr
2909  return get_ptr<PointerType>();
2910  }
2911 
2916  template<typename PointerType, typename
2917  std::enable_if<
2918  std::is_pointer<PointerType>::value
2919  , int>::type = 0>
2920  constexpr const PointerType get() const noexcept
2921  {
2922  // delegate the call to get_ptr
2923  return get_ptr<PointerType>();
2924  }
2925 
2951  template<typename PointerType, typename
2952  std::enable_if<
2953  std::is_pointer<PointerType>::value
2954  , int>::type = 0>
2955  PointerType get_ptr() noexcept
2956  {
2957  // delegate the call to get_impl_ptr<>()
2958  return get_impl_ptr(static_cast<PointerType>(nullptr));
2959  }
2960 
2965  template<typename PointerType, typename
2966  std::enable_if<
2967  std::is_pointer<PointerType>::value
2968  and std::is_const<typename std::remove_pointer<PointerType>::type>::value
2969  , int>::type = 0>
2970  constexpr const PointerType get_ptr() const noexcept
2971  {
2972  // delegate the call to get_impl_ptr<>() const
2973  return get_impl_ptr(static_cast<const PointerType>(nullptr));
2974  }
2975 
3002  template<typename ReferenceType, typename
3003  std::enable_if<
3004  std::is_reference<ReferenceType>::value
3005  , int>::type = 0>
3006  ReferenceType get_ref()
3007  {
3008  // delegate call to get_ref_impl
3009  return get_ref_impl<ReferenceType>(*this);
3010  }
3011 
3016  template<typename ReferenceType, typename
3017  std::enable_if<
3018  std::is_reference<ReferenceType>::value
3019  and std::is_const<typename std::remove_reference<ReferenceType>::type>::value
3020  , int>::type = 0>
3021  ReferenceType get_ref() const
3022  {
3023  // delegate call to get_ref_impl
3024  return get_ref_impl<ReferenceType>(*this);
3025  }
3026 
3055  template < typename ValueType, typename
3056  std::enable_if <
3057  not std::is_pointer<ValueType>::value
3058  and not std::is_same<ValueType, typename string_t::value_type>::value
3059 #ifndef _MSC_VER // Fix for issue #167 operator<< abiguity under VS2015
3060  and not std::is_same<ValueType, std::initializer_list<typename string_t::value_type>>::value
3061 #endif
3062  , int >::type = 0 >
3063  operator ValueType() const
3064  {
3065  // delegate the call to get<>() const
3066  return get<ValueType>();
3067  }
3068 
3070 
3071 
3073  // element access //
3075 
3078 
3102  {
3103  // at only works for arrays
3104  if (is_array())
3105  {
3106  try
3107  {
3108  assert(m_value.array != nullptr);
3109  return m_value.array->at(idx);
3110  }
3111  catch (std::out_of_range&)
3112  {
3113  // create better exception explanation
3114  throw std::out_of_range("array index " + std::to_string(idx) + " is out of range");
3115  }
3116  }
3117  else
3118  {
3119  throw std::domain_error("cannot use at() with " + type_name());
3120  }
3121  }
3122 
3146  {
3147  // at only works for arrays
3148  if (is_array())
3149  {
3150  try
3151  {
3152  assert(m_value.array != nullptr);
3153  return m_value.array->at(idx);
3154  }
3155  catch (std::out_of_range&)
3156  {
3157  // create better exception explanation
3158  throw std::out_of_range("array index " + std::to_string(idx) + " is out of range");
3159  }
3160  }
3161  else
3162  {
3163  throw std::domain_error("cannot use at() with " + type_name());
3164  }
3165  }
3166 
3193  reference at(const typename object_t::key_type& key)
3194  {
3195  // at only works for objects
3196  if (is_object())
3197  {
3198  try
3199  {
3200  assert(m_value.object != nullptr);
3201  return m_value.object->at(key);
3202  }
3203  catch (std::out_of_range&)
3204  {
3205  // create better exception explanation
3206  throw std::out_of_range("key '" + key + "' not found");
3207  }
3208  }
3209  else
3210  {
3211  throw std::domain_error("cannot use at() with " + type_name());
3212  }
3213  }
3214 
3241  const_reference at(const typename object_t::key_type& key) const
3242  {
3243  // at only works for objects
3244  if (is_object())
3245  {
3246  try
3247  {
3248  assert(m_value.object != nullptr);
3249  return m_value.object->at(key);
3250  }
3251  catch (std::out_of_range&)
3252  {
3253  // create better exception explanation
3254  throw std::out_of_range("key '" + key + "' not found");
3255  }
3256  }
3257  else
3258  {
3259  throw std::domain_error("cannot use at() with " + type_name());
3260  }
3261  }
3262 
3289  {
3290  // implicitly convert null value to an empty array
3291  if (is_null())
3292  {
3293  m_type = value_t::array;
3294  m_value.array = create<array_t>();
3295  }
3296 
3297  // operator[] only works for arrays
3298  if (is_array())
3299  {
3300  // fill up array with null values until given idx is reached
3301  assert(m_value.array != nullptr);
3302  for (size_t i = m_value.array->size(); i <= idx; ++i)
3303  {
3304  m_value.array->push_back(basic_json());
3305  }
3306 
3307  return m_value.array->operator[](idx);
3308  }
3309  else
3310  {
3311  throw std::domain_error("cannot use operator[] with " + type_name());
3312  }
3313  }
3314 
3335  {
3336  // const operator[] only works for arrays
3337  if (is_array())
3338  {
3339  assert(m_value.array != nullptr);
3340  return m_value.array->operator[](idx);
3341  }
3342  else
3343  {
3344  throw std::domain_error("cannot use operator[] with " + type_name());
3345  }
3346  }
3347 
3375  reference operator[](const typename object_t::key_type& key)
3376  {
3377  // implicitly convert null value to an empty object
3378  if (is_null())
3379  {
3380  m_type = value_t::object;
3381  m_value.object = create<object_t>();
3382  }
3383 
3384  // operator[] only works for objects
3385  if (is_object())
3386  {
3387  assert(m_value.object != nullptr);
3388  return m_value.object->operator[](key);
3389  }
3390  else
3391  {
3392  throw std::domain_error("cannot use operator[] with " + type_name());
3393  }
3394  }
3395 
3423  const_reference operator[](const typename object_t::key_type& key) const
3424  {
3425  // const operator[] only works for objects
3426  if (is_object())
3427  {
3428  assert(m_value.object != nullptr);
3429  assert(m_value.object->find(key) != m_value.object->end());
3430  return m_value.object->find(key)->second;
3431  }
3432  else
3433  {
3434  throw std::domain_error("cannot use operator[] with " + type_name());
3435  }
3436  }
3437 
3465  template<typename T, std::size_t n>
3466  reference operator[](T * (&key)[n])
3467  {
3468  return operator[](static_cast<const T>(key));
3469  }
3470 
3500  template<typename T, std::size_t n>
3501  const_reference operator[](T * (&key)[n]) const
3502  {
3503  return operator[](static_cast<const T>(key));
3504  }
3505 
3533  template<typename T>
3535  {
3536  // implicitly convert null to object
3537  if (is_null())
3538  {
3539  m_type = value_t::object;
3540  m_value = value_t::object;
3541  }
3542 
3543  // at only works for objects
3544  if (is_object())
3545  {
3546  assert(m_value.object != nullptr);
3547  return m_value.object->operator[](key);
3548  }
3549  else
3550  {
3551  throw std::domain_error("cannot use operator[] with " + type_name());
3552  }
3553  }
3554 
3582  template<typename T>
3584  {
3585  // at only works for objects
3586  if (is_object())
3587  {
3588  assert(m_value.object != nullptr);
3589  assert(m_value.object->find(key) != m_value.object->end());
3590  return m_value.object->find(key)->second;
3591  }
3592  else
3593  {
3594  throw std::domain_error("cannot use operator[] with " + type_name());
3595  }
3596  }
3597 
3646  template <class ValueType, typename
3647  std::enable_if<
3648  std::is_convertible<basic_json_t, ValueType>::value
3649  , int>::type = 0>
3650  ValueType value(const typename object_t::key_type& key, ValueType default_value) const
3651  {
3652  // at only works for objects
3653  if (is_object())
3654  {
3655  // if key is found, return value and given default value otherwise
3656  const auto it = find(key);
3657  if (it != end())
3658  {
3659  return *it;
3660  }
3661  else
3662  {
3663  return default_value;
3664  }
3665  }
3666  else
3667  {
3668  throw std::domain_error("cannot use value() with " + type_name());
3669  }
3670  }
3671 
3676  string_t value(const typename object_t::key_type& key, const char* default_value) const
3677  {
3678  return value(key, string_t(default_value));
3679  }
3680 
3706  {
3707  return *begin();
3708  }
3709 
3714  {
3715  return *cbegin();
3716  }
3717 
3748  {
3749  auto tmp = end();
3750  --tmp;
3751  return *tmp;
3752  }
3753 
3758  {
3759  auto tmp = cend();
3760  --tmp;
3761  return *tmp;
3762  }
3763 
3809  template <class InteratorType, typename
3810  std::enable_if<
3811  std::is_same<InteratorType, typename basic_json_t::iterator>::value or
3812  std::is_same<InteratorType, typename basic_json_t::const_iterator>::value
3813  , int>::type
3814  = 0>
3815  InteratorType erase(InteratorType pos)
3816  {
3817  // make sure iterator fits the current value
3818  if (this != pos.m_object)
3819  {
3820  throw std::domain_error("iterator does not fit current value");
3821  }
3822 
3823  InteratorType result = end();
3824 
3825  switch (m_type)
3826  {
3827  case value_t::boolean:
3828  case value_t::number_float:
3829  case value_t::number_integer:
3830  case value_t::number_unsigned:
3831  case value_t::string:
3832  {
3833  if (not pos.m_it.primitive_iterator.is_begin())
3834  {
3835  throw std::out_of_range("iterator out of range");
3836  }
3837 
3838  if (is_string())
3839  {
3840  delete m_value.string;
3841  m_value.string = nullptr;
3842  }
3843 
3844  m_type = value_t::null;
3845  break;
3846  }
3847 
3848  case value_t::object:
3849  {
3850  assert(m_value.object != nullptr);
3851  result.m_it.object_iterator = m_value.object->erase(pos.m_it.object_iterator);
3852  break;
3853  }
3854 
3855  case value_t::array:
3856  {
3857  assert(m_value.array != nullptr);
3858  result.m_it.array_iterator = m_value.array->erase(pos.m_it.array_iterator);
3859  break;
3860  }
3861 
3862  default:
3863  {
3864  throw std::domain_error("cannot use erase() with " + type_name());
3865  }
3866  }
3867 
3868  return result;
3869  }
3870 
3917  template <class InteratorType, typename
3918  std::enable_if<
3919  std::is_same<InteratorType, typename basic_json_t::iterator>::value or
3920  std::is_same<InteratorType, typename basic_json_t::const_iterator>::value
3921  , int>::type
3922  = 0>
3923  InteratorType erase(InteratorType first, InteratorType last)
3924  {
3925  // make sure iterator fits the current value
3926  if (this != first.m_object or this != last.m_object)
3927  {
3928  throw std::domain_error("iterators do not fit current value");
3929  }
3930 
3931  InteratorType result = end();
3932 
3933  switch (m_type)
3934  {
3935  case value_t::boolean:
3936  case value_t::number_float:
3937  case value_t::number_integer:
3938  case value_t::number_unsigned:
3939  case value_t::string:
3940  {
3941  if (not first.m_it.primitive_iterator.is_begin() or not last.m_it.primitive_iterator.is_end())
3942  {
3943  throw std::out_of_range("iterators out of range");
3944  }
3945 
3946  if (is_string())
3947  {
3948  delete m_value.string;
3949  m_value.string = nullptr;
3950  }
3951 
3952  m_type = value_t::null;
3953  break;
3954  }
3955 
3956  case value_t::object:
3957  {
3958  assert(m_value.object != nullptr);
3959  result.m_it.object_iterator = m_value.object->erase(first.m_it.object_iterator,
3960  last.m_it.object_iterator);
3961  break;
3962  }
3963 
3964  case value_t::array:
3965  {
3966  assert(m_value.array != nullptr);
3967  result.m_it.array_iterator = m_value.array->erase(first.m_it.array_iterator,
3968  last.m_it.array_iterator);
3969  break;
3970  }
3971 
3972  default:
3973  {
3974  throw std::domain_error("cannot use erase() with " + type_name());
3975  }
3976  }
3977 
3978  return result;
3979  }
3980 
4010  size_type erase(const typename object_t::key_type& key)
4011  {
4012  // this erase only works for objects
4013  if (is_object())
4014  {
4015  assert(m_value.object != nullptr);
4016  return m_value.object->erase(key);
4017  }
4018  else
4019  {
4020  throw std::domain_error("cannot use erase() with " + type_name());
4021  }
4022  }
4023 
4048  void erase(const size_type idx)
4049  {
4050  // this erase only works for arrays
4051  if (is_array())
4052  {
4053  if (idx >= size())
4054  {
4055  throw std::out_of_range("array index " + std::to_string(idx) + " is out of range");
4056  }
4057 
4058  assert(m_value.array != nullptr);
4059  m_value.array->erase(m_value.array->begin() + static_cast<difference_type>(idx));
4060  }
4061  else
4062  {
4063  throw std::domain_error("cannot use erase() with " + type_name());
4064  }
4065  }
4066 
4068 
4069 
4071  // lookup //
4073 
4076 
4094  iterator find(typename object_t::key_type key)
4095  {
4096  auto result = end();
4097 
4098  if (is_object())
4099  {
4100  assert(m_value.object != nullptr);
4101  result.m_it.object_iterator = m_value.object->find(key);
4102  }
4103 
4104  return result;
4105  }
4106 
4111  const_iterator find(typename object_t::key_type key) const
4112  {
4113  auto result = cend();
4114 
4115  if (is_object())
4116  {
4117  assert(m_value.object != nullptr);
4118  result.m_it.object_iterator = m_value.object->find(key);
4119  }
4120 
4121  return result;
4122  }
4123 
4142  size_type count(typename object_t::key_type key) const
4143  {
4144  // return 0 for all nonobject types
4145  assert(not is_object() or m_value.object != nullptr);
4146  return is_object() ? m_value.object->count(key) : 0;
4147  }
4148 
4150 
4151 
4153  // iterators //
4155 
4158 
4183  iterator begin() noexcept
4184  {
4185  iterator result(this);
4186  result.set_begin();
4187  return result;
4188  }
4189 
4193  const_iterator begin() const noexcept
4194  {
4195  return cbegin();
4196  }
4197 
4223  const_iterator cbegin() const noexcept
4224  {
4225  const_iterator result(this);
4226  result.set_begin();
4227  return result;
4228  }
4229 
4254  iterator end() noexcept
4255  {
4256  iterator result(this);
4257  result.set_end();
4258  return result;
4259  }
4260 
4264  const_iterator end() const noexcept
4265  {
4266  return cend();
4267  }
4268 
4294  const_iterator cend() const noexcept
4295  {
4296  const_iterator result(this);
4297  result.set_end();
4298  return result;
4299  }
4300 
4325  {
4326  return reverse_iterator(end());
4327  }
4328 
4333  {
4334  return crbegin();
4335  }
4336 
4362  {
4363  return reverse_iterator(begin());
4364  }
4365 
4369  const_reverse_iterator rend() const noexcept
4370  {
4371  return crend();
4372  }
4373 
4399  {
4400  return const_reverse_iterator(cend());
4401  }
4402 
4428  {
4429  return const_reverse_iterator(cbegin());
4430  }
4431 
4432  private:
4433  // forward declaration
4434  template<typename IteratorType> class iteration_proxy;
4435 
4436  public:
4448  static iteration_proxy<iterator> iterator_wrapper(reference cont)
4449  {
4450  return iteration_proxy<iterator>(cont);
4451  }
4452 
4456  static iteration_proxy<const_iterator> iterator_wrapper(const_reference cont)
4457  {
4458  return iteration_proxy<const_iterator>(cont);
4459  }
4460 
4462 
4463 
4465  // capacity //
4467 
4470 
4504  bool empty() const noexcept
4505  {
4506  switch (m_type)
4507  {
4508  case value_t::null:
4509  {
4510  // null values are empty
4511  return true;
4512  }
4513 
4514  case value_t::array:
4515  {
4516  assert(m_value.array != nullptr);
4517  return m_value.array->empty();
4518  }
4519 
4520  case value_t::object:
4521  {
4522  assert(m_value.object != nullptr);
4523  return m_value.object->empty();
4524  }
4525 
4526  default:
4527  {
4528  // all other types are nonempty
4529  return false;
4530  }
4531  }
4532  }
4533 
4567  size_type size() const noexcept
4568  {
4569  switch (m_type)
4570  {
4571  case value_t::null:
4572  {
4573  // null values are empty
4574  return 0;
4575  }
4576 
4577  case value_t::array:
4578  {
4579  assert(m_value.array != nullptr);
4580  return m_value.array->size();
4581  }
4582 
4583  case value_t::object:
4584  {
4585  assert(m_value.object != nullptr);
4586  return m_value.object->size();
4587  }
4588 
4589  default:
4590  {
4591  // all other types have size 1
4592  return 1;
4593  }
4594  }
4595  }
4596 
4633  size_type max_size() const noexcept
4634  {
4635  switch (m_type)
4636  {
4637  case value_t::array:
4638  {
4639  assert(m_value.array != nullptr);
4640  return m_value.array->max_size();
4641  }
4642 
4643  case value_t::object:
4644  {
4645  assert(m_value.object != nullptr);
4646  return m_value.object->max_size();
4647  }
4648 
4649  default:
4650  {
4651  // all other types have max_size() == size()
4652  return size();
4653  }
4654  }
4655  }
4656 
4658 
4659 
4661  // modifiers //
4663 
4666 
4692  void clear() noexcept
4693  {
4694  switch (m_type)
4695  {
4696  case value_t::number_integer:
4697  {
4698  m_value.number_integer = 0;
4699  break;
4700  }
4701 
4702  case value_t::number_unsigned:
4703  {
4704  m_value.number_unsigned = 0;
4705  break;
4706  }
4707 
4708  case value_t::number_float:
4709  {
4710  m_value.number_float = 0.0;
4711  break;
4712  }
4713 
4714  case value_t::boolean:
4715  {
4716  m_value.boolean = false;
4717  break;
4718  }
4719 
4720  case value_t::string:
4721  {
4722  assert(m_value.string != nullptr);
4723  m_value.string->clear();
4724  break;
4725  }
4726 
4727  case value_t::array:
4728  {
4729  assert(m_value.array != nullptr);
4730  m_value.array->clear();
4731  break;
4732  }
4733 
4734  case value_t::object:
4735  {
4736  assert(m_value.object != nullptr);
4737  m_value.object->clear();
4738  break;
4739  }
4740 
4741  default:
4742  {
4743  break;
4744  }
4745  }
4746  }
4747 
4768  void push_back(basic_json&& val)
4769  {
4770  // push_back only works for null objects or arrays
4771  if (not(is_null() or is_array()))
4772  {
4773  throw std::domain_error("cannot use push_back() with " + type_name());
4774  }
4775 
4776  // transform null object into an array
4777  if (is_null())
4778  {
4779  m_type = value_t::array;
4780  m_value = value_t::array;
4781  }
4782 
4783  // add element to array (move semantics)
4784  assert(m_value.array != nullptr);
4785  m_value.array->push_back(std::move(val));
4786  // invalidate object
4787  val.m_type = value_t::null;
4788  }
4789 
4794  reference operator+=(basic_json&& val)
4795  {
4796  push_back(std::move(val));
4797  return *this;
4798  }
4799 
4804  void push_back(const basic_json& val)
4805  {
4806  // push_back only works for null objects or arrays
4807  if (not(is_null() or is_array()))
4808  {
4809  throw std::domain_error("cannot use push_back() with " + type_name());
4810  }
4811 
4812  // transform null object into an array
4813  if (is_null())
4814  {
4815  m_type = value_t::array;
4816  m_value = value_t::array;
4817  }
4818 
4819  // add element to array
4820  assert(m_value.array != nullptr);
4821  m_value.array->push_back(val);
4822  }
4823 
4828  reference operator+=(const basic_json& val)
4829  {
4830  push_back(val);
4831  return *this;
4832  }
4833 
4854  void push_back(const typename object_t::value_type& val)
4855  {
4856  // push_back only works for null objects or objects
4857  if (not(is_null() or is_object()))
4858  {
4859  throw std::domain_error("cannot use push_back() with " + type_name());
4860  }
4861 
4862  // transform null object into an object
4863  if (is_null())
4864  {
4865  m_type = value_t::object;
4866  m_value = value_t::object;
4867  }
4868 
4869  // add element to array
4870  assert(m_value.object != nullptr);
4871  m_value.object->insert(val);
4872  }
4873 
4878  reference operator+=(const typename object_t::value_type& val)
4879  {
4880  push_back(val);
4881  return *this;
4882  }
4883 
4909  void push_back(std::initializer_list<basic_json> init)
4910  {
4911  if (is_object() and init.size() == 2 and init.begin()->is_string())
4912  {
4913  const string_t key = *init.begin();
4914  push_back(typename object_t::value_type(key, *(init.begin() + 1)));
4915  }
4916  else
4917  {
4918  push_back(basic_json(init));
4919  }
4920  }
4921 
4926  reference operator+=(std::initializer_list<basic_json> init)
4927  {
4928  push_back(init);
4929  return *this;
4930  }
4931 
4954  iterator insert(const_iterator pos, const basic_json& val)
4955  {
4956  // insert only works for arrays
4957  if (is_array())
4958  {
4959  // check if iterator pos fits to this JSON value
4960  if (pos.m_object != this)
4961  {
4962  throw std::domain_error("iterator does not fit current value");
4963  }
4964 
4965  // insert to array and return iterator
4966  iterator result(this);
4967  assert(m_value.array != nullptr);
4968  result.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator, val);
4969  return result;
4970  }
4971  else
4972  {
4973  throw std::domain_error("cannot use insert() with " + type_name());
4974  }
4975  }
4976 
4981  iterator insert(const_iterator pos, basic_json&& val)
4982  {
4983  return insert(pos, val);
4984  }
4985 
5010  iterator insert(const_iterator pos, size_type cnt, const basic_json& val)
5011  {
5012  // insert only works for arrays
5013  if (is_array())
5014  {
5015  // check if iterator pos fits to this JSON value
5016  if (pos.m_object != this)
5017  {
5018  throw std::domain_error("iterator does not fit current value");
5019  }
5020 
5021  // insert to array and return iterator
5022  iterator result(this);
5023  assert(m_value.array != nullptr);
5024  result.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator, cnt, val);
5025  return result;
5026  }
5027  else
5028  {
5029  throw std::domain_error("cannot use insert() with " + type_name());
5030  }
5031  }
5032 
5064  {
5065  // insert only works for arrays
5066  if (not is_array())
5067  {
5068  throw std::domain_error("cannot use insert() with " + type_name());
5069  }
5070 
5071  // check if iterator pos fits to this JSON value
5072  if (pos.m_object != this)
5073  {
5074  throw std::domain_error("iterator does not fit current value");
5075  }
5076 
5077  if (first.m_object != last.m_object)
5078  {
5079  throw std::domain_error("iterators do not fit");
5080  }
5081 
5082  if (first.m_object == this or last.m_object == this)
5083  {
5084  throw std::domain_error("passed iterators may not belong to container");
5085  }
5086 
5087  // insert to array and return iterator
5088  iterator result(this);
5089  assert(m_value.array != nullptr);
5090  result.m_it.array_iterator = m_value.array->insert(
5091  pos.m_it.array_iterator,
5092  first.m_it.array_iterator,
5093  last.m_it.array_iterator);
5094  return result;
5095  }
5096 
5121  iterator insert(const_iterator pos, std::initializer_list<basic_json> ilist)
5122  {
5123  // insert only works for arrays
5124  if (not is_array())
5125  {
5126  throw std::domain_error("cannot use insert() with " + type_name());
5127  }
5128 
5129  // check if iterator pos fits to this JSON value
5130  if (pos.m_object != this)
5131  {
5132  throw std::domain_error("iterator does not fit current value");
5133  }
5134 
5135  // insert to array and return iterator
5136  iterator result(this);
5137  assert(m_value.array != nullptr);
5138  result.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator, ilist);
5139  return result;
5140  }
5141 
5159  void swap(reference other) noexcept (
5160  std::is_nothrow_move_constructible<value_t>::value and
5161  std::is_nothrow_move_assignable<value_t>::value and
5162  std::is_nothrow_move_constructible<json_value>::value and
5163  std::is_nothrow_move_assignable<json_value>::value
5164  )
5165  {
5166  std::swap(m_type, other.m_type);
5167  std::swap(m_value, other.m_value);
5168  }
5169 
5190  void swap(array_t& other)
5191  {
5192  // swap only works for arrays
5193  if (is_array())
5194  {
5195  assert(m_value.array != nullptr);
5196  std::swap(*(m_value.array), other);
5197  }
5198  else
5199  {
5200  throw std::domain_error("cannot use swap() with " + type_name());
5201  }
5202  }
5203 
5224  void swap(object_t& other)
5225  {
5226  // swap only works for objects
5227  if (is_object())
5228  {
5229  assert(m_value.object != nullptr);
5230  std::swap(*(m_value.object), other);
5231  }
5232  else
5233  {
5234  throw std::domain_error("cannot use swap() with " + type_name());
5235  }
5236  }
5237 
5258  void swap(string_t& other)
5259  {
5260  // swap only works for strings
5261  if (is_string())
5262  {
5263  assert(m_value.string != nullptr);
5264  std::swap(*(m_value.string), other);
5265  }
5266  else
5267  {
5268  throw std::domain_error("cannot use swap() with " + type_name());
5269  }
5270  }
5271 
5273 
5274 
5276  // lexicographical comparison operators //
5278 
5281 
5282  private:
5292  friend bool operator<(const value_t lhs, const value_t rhs) noexcept
5293  {
5294  static constexpr std::array<uint8_t, 8> order = {{
5295  0, // null
5296  3, // object
5297  4, // array
5298  5, // string
5299  1, // boolean
5300  2, // integer
5301  2, // unsigned
5302  2, // float
5303  }
5304  };
5305 
5306  // discarded values are not comparable
5307  if (lhs == value_t::discarded or rhs == value_t::discarded)
5308  {
5309  return false;
5310  }
5311 
5312  return order[static_cast<std::size_t>(lhs)] < order[static_cast<std::size_t>(rhs)];
5313  }
5314 
5315  public:
5339  friend bool operator==(const_reference lhs, const_reference rhs) noexcept
5340  {
5341  const auto lhs_type = lhs.type();
5342  const auto rhs_type = rhs.type();
5343 
5344  if (lhs_type == rhs_type)
5345  {
5346  switch (lhs_type)
5347  {
5348  case value_t::array:
5349  {
5350  assert(lhs.m_value.array != nullptr);
5351  assert(rhs.m_value.array != nullptr);
5352  return *lhs.m_value.array == *rhs.m_value.array;
5353  }
5354  case value_t::object:
5355  {
5356  assert(lhs.m_value.object != nullptr);
5357  assert(rhs.m_value.object != nullptr);
5358  return *lhs.m_value.object == *rhs.m_value.object;
5359  }
5360  case value_t::null:
5361  {
5362  return true;
5363  }
5364  case value_t::string:
5365  {
5366  assert(lhs.m_value.string != nullptr);
5367  assert(rhs.m_value.string != nullptr);
5368  return *lhs.m_value.string == *rhs.m_value.string;
5369  }
5370  case value_t::boolean:
5371  {
5372  return lhs.m_value.boolean == rhs.m_value.boolean;
5373  }
5374  case value_t::number_integer:
5375  {
5376  return lhs.m_value.number_integer == rhs.m_value.number_integer;
5377  }
5378  case value_t::number_unsigned:
5379  {
5380  return lhs.m_value.number_unsigned == rhs.m_value.number_unsigned;
5381  }
5382  case value_t::number_float:
5383  {
5384  return lhs.m_value.number_float == rhs.m_value.number_float;
5385  }
5386  default:
5387  {
5388  return false;
5389  }
5390  }
5391  }
5392  else if (lhs_type == value_t::number_integer and rhs_type == value_t::number_float)
5393  {
5394  return static_cast<number_float_t>(lhs.m_value.number_integer) == rhs.m_value.number_float;
5395  }
5396  else if (lhs_type == value_t::number_float and rhs_type == value_t::number_integer)
5397  {
5398  return lhs.m_value.number_float == static_cast<number_float_t>(rhs.m_value.number_integer);
5399  }
5400  else if (lhs_type == value_t::number_unsigned and rhs_type == value_t::number_float)
5401  {
5402  return static_cast<number_float_t>(lhs.m_value.number_unsigned) == rhs.m_value.number_float;
5403  }
5404  else if (lhs_type == value_t::number_float and rhs_type == value_t::number_unsigned)
5405  {
5406  return lhs.m_value.number_float == static_cast<number_float_t>(rhs.m_value.number_unsigned);
5407  }
5408  else if (lhs_type == value_t::number_unsigned and rhs_type == value_t::number_integer)
5409  {
5410  return static_cast<number_integer_t>(lhs.m_value.number_unsigned) == rhs.m_value.number_integer;
5411  }
5412  else if (lhs_type == value_t::number_integer and rhs_type == value_t::number_unsigned)
5413  {
5414  return lhs.m_value.number_integer == static_cast<number_integer_t>(rhs.m_value.number_unsigned);
5415  }
5416 
5417  return false;
5418  }
5419 
5438  friend bool operator==(const_reference v, std::nullptr_t) noexcept
5439  {
5440  return v.is_null();
5441  }
5442 
5447  friend bool operator==(std::nullptr_t, const_reference v) noexcept
5448  {
5449  return v.is_null();
5450  }
5451 
5468  friend bool operator!=(const_reference lhs, const_reference rhs) noexcept
5469  {
5470  return not (lhs == rhs);
5471  }
5472 
5491  friend bool operator!=(const_reference v, std::nullptr_t) noexcept
5492  {
5493  return not v.is_null();
5494  }
5495 
5500  friend bool operator!=(std::nullptr_t, const_reference v) noexcept
5501  {
5502  return not v.is_null();
5503  }
5504 
5529  friend bool operator<(const_reference lhs, const_reference rhs) noexcept
5530  {
5531  const auto lhs_type = lhs.type();
5532  const auto rhs_type = rhs.type();
5533 
5534  if (lhs_type == rhs_type)
5535  {
5536  switch (lhs_type)
5537  {
5538  case value_t::array:
5539  {
5540  assert(lhs.m_value.array != nullptr);
5541  assert(rhs.m_value.array != nullptr);
5542  return *lhs.m_value.array < *rhs.m_value.array;
5543  }
5544  case value_t::object:
5545  {
5546  assert(lhs.m_value.object != nullptr);
5547  assert(rhs.m_value.object != nullptr);
5548  return *lhs.m_value.object < *rhs.m_value.object;
5549  }
5550  case value_t::null:
5551  {
5552  return false;
5553  }
5554  case value_t::string:
5555  {
5556  assert(lhs.m_value.string != nullptr);
5557  assert(rhs.m_value.string != nullptr);
5558  return *lhs.m_value.string < *rhs.m_value.string;
5559  }
5560  case value_t::boolean:
5561  {
5562  return lhs.m_value.boolean < rhs.m_value.boolean;
5563  }
5564  case value_t::number_integer:
5565  {
5566  return lhs.m_value.number_integer < rhs.m_value.number_integer;
5567  }
5568  case value_t::number_unsigned:
5569  {
5570  return lhs.m_value.number_unsigned < rhs.m_value.number_unsigned;
5571  }
5572  case value_t::number_float:
5573  {
5574  return lhs.m_value.number_float < rhs.m_value.number_float;
5575  }
5576  default:
5577  {
5578  return false;
5579  }
5580  }
5581  }
5582  else if (lhs_type == value_t::number_integer and rhs_type == value_t::number_float)
5583  {
5584  return static_cast<number_float_t>(lhs.m_value.number_integer) < rhs.m_value.number_float;
5585  }
5586  else if (lhs_type == value_t::number_float and rhs_type == value_t::number_integer)
5587  {
5588  return lhs.m_value.number_float < static_cast<number_float_t>(rhs.m_value.number_integer);
5589  }
5590  else if (lhs_type == value_t::number_unsigned and rhs_type == value_t::number_float)
5591  {
5592  return static_cast<number_float_t>(lhs.m_value.number_unsigned) < rhs.m_value.number_float;
5593  }
5594  else if (lhs_type == value_t::number_float and rhs_type == value_t::number_unsigned)
5595  {
5596  return lhs.m_value.number_float < static_cast<number_float_t>(rhs.m_value.number_unsigned);
5597  }
5598  else if (lhs_type == value_t::number_integer and rhs_type == value_t::number_unsigned)
5599  {
5600  return lhs.m_value.number_integer < static_cast<number_integer_t>(rhs.m_value.number_unsigned);
5601  }
5602  else if (lhs_type == value_t::number_unsigned and rhs_type == value_t::number_integer)
5603  {
5604  return static_cast<number_integer_t>(lhs.m_value.number_unsigned) < rhs.m_value.number_integer;
5605  }
5606 
5607  // We only reach this line if we cannot compare values. In that case,
5608  // we compare types. Note we have to call the operator explicitly,
5609  // because MSVC has problems otherwise.
5610  return operator<(lhs_type, rhs_type);
5611  }
5612 
5630  friend bool operator<=(const_reference lhs, const_reference rhs) noexcept
5631  {
5632  return not (rhs < lhs);
5633  }
5634 
5652  friend bool operator>(const_reference lhs, const_reference rhs) noexcept
5653  {
5654  return not (lhs <= rhs);
5655  }
5656 
5674  friend bool operator>=(const_reference lhs, const_reference rhs) noexcept
5675  {
5676  return not (lhs < rhs);
5677  }
5678 
5680 
5681 
5683  // serialization //
5685 
5688 
5711  friend std::ostream& operator<<(std::ostream& o, const basic_json& j)
5712  {
5713  // read width member and use it as indentation parameter if nonzero
5714  const bool pretty_print = (o.width() > 0);
5715  const auto indentation = (pretty_print ? o.width() : 0);
5716 
5717  // reset width to 0 for subsequent calls to this stream
5718  o.width(0);
5719 
5720  // do the actual serialization
5721  j.dump(o, pretty_print, static_cast<unsigned int>(indentation));
5722  return o;
5723  }
5724 
5729  friend std::ostream& operator>>(const basic_json& j, std::ostream& o)
5730  {
5731  return o << j;
5732  }
5733 
5735 
5736 
5738  // deserialization //
5740 
5743 
5768  static basic_json parse(const string_t& s, parser_callback_t cb = nullptr)
5769  {
5770  return parser(s, cb).parse();
5771  }
5772 
5797  static basic_json parse(std::istream& i, parser_callback_t cb = nullptr)
5798  {
5799  return parser(i, cb).parse();
5800  }
5801 
5805  static basic_json parse(std::istream&& i, parser_callback_t cb = nullptr)
5806  {
5807  return parser(i, cb).parse();
5808  }
5809 
5833  friend std::istream& operator<<(basic_json& j, std::istream& i)
5834  {
5835  j = parser(i).parse();
5836  return i;
5837  }
5838 
5843  friend std::istream& operator>>(std::istream& i, basic_json& j)
5844  {
5845  j = parser(i).parse();
5846  return i;
5847  }
5848 
5850 
5851 
5852  private:
5854  // convenience functions //
5856 
5858  string_t type_name() const noexcept
5859  {
5860  switch (m_type)
5861  {
5862  case value_t::null:
5863  return "null";
5864  case value_t::object:
5865  return "object";
5866  case value_t::array:
5867  return "array";
5868  case value_t::string:
5869  return "string";
5870  case value_t::boolean:
5871  return "boolean";
5872  case value_t::discarded:
5873  return "discarded";
5874  default:
5875  return "number";
5876  }
5877  }
5878 
5887  static std::size_t extra_space(const string_t& s) noexcept
5888  {
5889  std::size_t result = 0;
5890 
5891  for (const auto& c : s)
5892  {
5893  switch (c)
5894  {
5895  case '"':
5896  case '\\':
5897  case '\b':
5898  case '\f':
5899  case '\n':
5900  case '\r':
5901  case '\t':
5902  {
5903  // from c (1 byte) to \x (2 bytes)
5904  result += 1;
5905  break;
5906  }
5907 
5908  default:
5909  {
5910  if (c >= 0x00 and c <= 0x1f)
5911  {
5912  // from c (1 byte) to \uxxxx (6 bytes)
5913  result += 5;
5914  }
5915  break;
5916  }
5917  }
5918  }
5919 
5920  return result;
5921  }
5922 
5936  static string_t escape_string(const string_t& s)
5937  {
5938  const auto space = extra_space(s);
5939  if (space == 0)
5940  {
5941  return s;
5942  }
5943 
5944  // create a result string of necessary size
5945  string_t result(s.size() + space, '\\');
5946  std::size_t pos = 0;
5947 
5948  for (const auto& c : s)
5949  {
5950  switch (c)
5951  {
5952  // quotation mark (0x22)
5953  case '"':
5954  {
5955  result[pos + 1] = '"';
5956  pos += 2;
5957  break;
5958  }
5959 
5960  // reverse solidus (0x5c)
5961  case '\\':
5962  {
5963  // nothing to change
5964  pos += 2;
5965  break;
5966  }
5967 
5968  // backspace (0x08)
5969  case '\b':
5970  {
5971  result[pos + 1] = 'b';
5972  pos += 2;
5973  break;
5974  }
5975 
5976  // formfeed (0x0c)
5977  case '\f':
5978  {
5979  result[pos + 1] = 'f';
5980  pos += 2;
5981  break;
5982  }
5983 
5984  // newline (0x0a)
5985  case '\n':
5986  {
5987  result[pos + 1] = 'n';
5988  pos += 2;
5989  break;
5990  }
5991 
5992  // carriage return (0x0d)
5993  case '\r':
5994  {
5995  result[pos + 1] = 'r';
5996  pos += 2;
5997  break;
5998  }
5999 
6000  // horizontal tab (0x09)
6001  case '\t':
6002  {
6003  result[pos + 1] = 't';
6004  pos += 2;
6005  break;
6006  }
6007 
6008  default:
6009  {
6010  if (c >= 0x00 and c <= 0x1f)
6011  {
6012  // convert a number 0..15 to its hex representation
6013  // (0..f)
6014  auto hexify = [](const char v) -> char
6015  {
6016  return (v < 10) ? ('0' + v) : ('a' + v - 10);
6017  };
6018 
6019  // print character c as \uxxxx
6020  for (const char m :
6021  { 'u', '0', '0', hexify(c >> 4), hexify(c & 0x0f)
6022  })
6023  {
6024  result[++pos] = m;
6025  }
6026 
6027  ++pos;
6028  }
6029  else
6030  {
6031  // all other characters are added as-is
6032  result[pos++] = c;
6033  }
6034  break;
6035  }
6036  }
6037  }
6038 
6039  return result;
6040  }
6041 
6059  void dump(std::ostream& o,
6060  const bool pretty_print,
6061  const unsigned int indent_step,
6062  const unsigned int current_indent = 0) const
6063  {
6064  // variable to hold indentation for recursive calls
6065  unsigned int new_indent = current_indent;
6066 
6067  switch (m_type)
6068  {
6069  case value_t::object:
6070  {
6071  assert(m_value.object != nullptr);
6072 
6073  if (m_value.object->empty())
6074  {
6075  o << "{}";
6076  return;
6077  }
6078 
6079  o << "{";
6080 
6081  // increase indentation
6082  if (pretty_print)
6083  {
6084  new_indent += indent_step;
6085  o << "\n";
6086  }
6087 
6088  for (auto i = m_value.object->cbegin(); i != m_value.object->cend(); ++i)
6089  {
6090  if (i != m_value.object->cbegin())
6091  {
6092  o << (pretty_print ? ",\n" : ",");
6093  }
6094  o << string_t(new_indent, ' ') << "\""
6095  << escape_string(i->first) << "\":"
6096  << (pretty_print ? " " : "");
6097  i->second.dump(o, pretty_print, indent_step, new_indent);
6098  }
6099 
6100  // decrease indentation
6101  if (pretty_print)
6102  {
6103  new_indent -= indent_step;
6104  o << "\n";
6105  }
6106 
6107  o << string_t(new_indent, ' ') + "}";
6108  return;
6109  }
6110 
6111  case value_t::array:
6112  {
6113  assert(m_value.array != nullptr);
6114 
6115  if (m_value.array->empty())
6116  {
6117  o << "[]";
6118  return;
6119  }
6120 
6121  o << "[";
6122 
6123  // increase indentation
6124  if (pretty_print)
6125  {
6126  new_indent += indent_step;
6127  o << "\n";
6128  }
6129 
6130  for (auto i = m_value.array->cbegin(); i != m_value.array->cend(); ++i)
6131  {
6132  if (i != m_value.array->cbegin())
6133  {
6134  o << (pretty_print ? ",\n" : ",");
6135  }
6136  o << string_t(new_indent, ' ');
6137  i->dump(o, pretty_print, indent_step, new_indent);
6138  }
6139 
6140  // decrease indentation
6141  if (pretty_print)
6142  {
6143  new_indent -= indent_step;
6144  o << "\n";
6145  }
6146 
6147  o << string_t(new_indent, ' ') << "]";
6148  return;
6149  }
6150 
6151  case value_t::string:
6152  {
6153  assert(m_value.string != nullptr);
6154  o << string_t("\"") << escape_string(*m_value.string) << "\"";
6155  return;
6156  }
6157 
6158  case value_t::boolean:
6159  {
6160  o << (m_value.boolean ? "true" : "false");
6161  return;
6162  }
6163 
6164  case value_t::number_integer:
6165  {
6166  o << m_value.number_integer;
6167  return;
6168  }
6169 
6170  case value_t::number_unsigned:
6171  {
6172  o << m_value.number_unsigned;
6173  return;
6174  }
6175 
6176  case value_t::number_float:
6177  {
6178  // check if number was parsed from a string
6179  if (m_type.bits.parsed)
6180  {
6181  // check if parsed number had an exponent given
6182  if (m_type.bits.has_exp)
6183  {
6184  // buffer size: precision (2^8-1 = 255) + other ('-.e-xxx' = 7) + null (1)
6185  char buf[263];
6186  int len;
6187 
6188  // handle capitalization of the exponent
6189  if (m_type.bits.exp_cap)
6190  {
6191  len = snprintf(buf, sizeof(buf), "%.*E",
6192  m_type.bits.precision, m_value.number_float) + 1;
6193  }
6194  else
6195  {
6196  len = snprintf(buf, sizeof(buf), "%.*e",
6197  m_type.bits.precision, m_value.number_float) + 1;
6198  }
6199 
6200  // remove '+' sign from the exponent if necessary
6201  if (not m_type.bits.exp_plus)
6202  {
6203  if (len > static_cast<int>(sizeof(buf)))
6204  {
6205  len = sizeof(buf);
6206  }
6207  for (int i = 0; i < len; i++)
6208  {
6209  if (buf[i] == '+')
6210  {
6211  for (; i + 1 < len; i++)
6212  {
6213  buf[i] = buf[i + 1];
6214  }
6215  }
6216  }
6217  }
6218 
6219  o << buf;
6220  }
6221  else
6222  {
6223  // no exponent - output as a decimal
6224  std::stringstream ss;
6225  ss.imbue(std::locale(std::locale(), new DecimalSeparator)); // fix locale problems
6226  ss << std::setprecision(m_type.bits.precision)
6227  << std::fixed << m_value.number_float;
6228  o << ss.str();
6229  }
6230  }
6231  else
6232  {
6233  if (m_value.number_float == 0)
6234  {
6235  // special case for zero to get "0.0"/"-0.0"
6236  o << (std::signbit(m_value.number_float) ? "-0.0" : "0.0");
6237  }
6238  else
6239  {
6240  // Otherwise 6, 15 or 16 digits of precision allows
6241  // round-trip IEEE 754 string->float->string,
6242  // string->double->string or string->long double->string;
6243  // to be safe, we read this value from
6244  // std::numeric_limits<number_float_t>::digits10
6245  std::stringstream ss;
6246  ss.imbue(std::locale(std::locale(), new DecimalSeparator)); // fix locale problems
6247  ss << std::setprecision(std::numeric_limits<double>::digits10)
6248  << m_value.number_float;
6249  o << ss.str();
6250  }
6251  }
6252  return;
6253  }
6254 
6255  case value_t::discarded:
6256  {
6257  o << "<discarded>";
6258  return;
6259  }
6260 
6261  case value_t::null:
6262  {
6263  o << "null";
6264  return;
6265  }
6266  }
6267  }
6268 
6269  private:
6271  // member variables //
6273 
6275  type_data_t m_type = value_t::null;
6276 
6278  json_value m_value = {};
6279 
6280 
6281  private:
6283  // iterators //
6285 
6295  class primitive_iterator_t
6296  {
6297  public:
6299  void set_begin() noexcept
6300  {
6301  m_it = begin_value;
6302  }
6303 
6305  void set_end() noexcept
6306  {
6307  m_it = end_value;
6308  }
6309 
6311  constexpr bool is_begin() const noexcept
6312  {
6313  return (m_it == begin_value);
6314  }
6315 
6317  constexpr bool is_end() const noexcept
6318  {
6319  return (m_it == end_value);
6320  }
6321 
6323  operator difference_type& () noexcept
6324  {
6325  return m_it;
6326  }
6327 
6329  constexpr operator difference_type () const noexcept
6330  {
6331  return m_it;
6332  }
6333 
6334  private:
6335  static constexpr difference_type begin_value = 0;
6336  static constexpr difference_type end_value = begin_value + 1;
6337 
6339  difference_type m_it = std::numeric_limits<std::ptrdiff_t>::denorm_min();
6340  };
6341 
6349  struct internal_iterator
6350  {
6352  typename object_t::iterator object_iterator;
6354  typename array_t::iterator array_iterator;
6356  primitive_iterator_t primitive_iterator;
6357 
6359  internal_iterator() noexcept
6360  : object_iterator(), array_iterator(), primitive_iterator()
6361  {}
6362  };
6363 
6365  template<typename IteratorType>
6366  class iteration_proxy
6367  {
6368  private:
6370  class iteration_proxy_internal
6371  {
6372  private:
6374  IteratorType anchor;
6376  size_t array_index = 0;
6377 
6378  public:
6379  explicit iteration_proxy_internal(IteratorType it) noexcept
6380  : anchor(it)
6381  {}
6382 
6384  iteration_proxy_internal& operator*()
6385  {
6386  return *this;
6387  }
6388 
6390  iteration_proxy_internal& operator++()
6391  {
6392  ++anchor;
6393  ++array_index;
6394 
6395  return *this;
6396  }
6397 
6399  bool operator!= (const iteration_proxy_internal& o) const
6400  {
6401  return anchor != o.anchor;
6402  }
6403 
6405  typename basic_json::string_t key() const
6406  {
6407  assert(anchor.m_object != nullptr);
6408 
6409  switch (anchor.m_object->type())
6410  {
6411  // use integer array index as key
6412  case value_t::array:
6413  {
6414  return std::to_string(array_index);
6415  }
6416 
6417  // use key from the object
6418  case value_t::object:
6419  {
6420  return anchor.key();
6421  }
6422 
6423  // use an empty key for all primitive types
6424  default:
6425  {
6426  return "";
6427  }
6428  }
6429  }
6430 
6432  typename IteratorType::reference value() const
6433  {
6434  return anchor.value();
6435  }
6436  };
6437 
6439  typename IteratorType::reference container;
6440 
6441  public:
6443  explicit iteration_proxy(typename IteratorType::reference cont)
6444  : container(cont)
6445  {}
6446 
6448  iteration_proxy_internal begin() noexcept
6449  {
6450  return iteration_proxy_internal(container.begin());
6451  }
6452 
6454  iteration_proxy_internal end() noexcept
6455  {
6456  return iteration_proxy_internal(container.end());
6457  }
6458  };
6459 
6460  public:
6474  class const_iterator : public std::iterator<std::random_access_iterator_tag, const basic_json>
6475  {
6477  friend class basic_json;
6478 
6479  public:
6489  using iterator_category = std::bidirectional_iterator_tag;
6490 
6492  const_iterator() = default;
6493 
6495  explicit const_iterator(pointer object) noexcept
6496  : m_object(object)
6497  {
6498  assert(m_object != nullptr);
6499 
6500  switch (m_object->m_type)
6501  {
6503  {
6504  m_it.object_iterator = typename object_t::iterator();
6505  break;
6506  }
6507 
6509  {
6510  m_it.array_iterator = typename array_t::iterator();
6511  break;
6512  }
6513 
6514  default:
6515  {
6516  m_it.primitive_iterator = primitive_iterator_t();
6517  break;
6518  }
6519  }
6520  }
6521 
6523  explicit const_iterator(const iterator& other) noexcept
6524  : m_object(other.m_object)
6525  {
6526  assert(m_object != nullptr);
6527 
6528  switch (m_object->m_type)
6529  {
6531  {
6532  m_it.object_iterator = other.m_it.object_iterator;
6533  break;
6534  }
6535 
6537  {
6538  m_it.array_iterator = other.m_it.array_iterator;
6539  break;
6540  }
6541 
6542  default:
6543  {
6544  m_it.primitive_iterator = other.m_it.primitive_iterator;
6545  break;
6546  }
6547  }
6548  }
6549 
6551  const_iterator(const const_iterator& other) noexcept
6552  : m_object(other.m_object), m_it(other.m_it)
6553  {}
6554 
6557  std::is_nothrow_move_constructible<pointer>::value and
6558  std::is_nothrow_move_assignable<pointer>::value and
6559  std::is_nothrow_move_constructible<internal_iterator>::value and
6560  std::is_nothrow_move_assignable<internal_iterator>::value
6561  )
6562  {
6563  std::swap(m_object, other.m_object);
6564  std::swap(m_it, other.m_it);
6565  return *this;
6566  }
6567 
6568  private:
6570  void set_begin() noexcept
6571  {
6572  assert(m_object != nullptr);
6573 
6574  switch (m_object->m_type)
6575  {
6577  {
6578  assert(m_object->m_value.object != nullptr);
6579  m_it.object_iterator = m_object->m_value.object->begin();
6580  break;
6581  }
6582 
6584  {
6585  assert(m_object->m_value.array != nullptr);
6586  m_it.array_iterator = m_object->m_value.array->begin();
6587  break;
6588  }
6589 
6591  {
6592  // set to end so begin()==end() is true: null is empty
6593  m_it.primitive_iterator.set_end();
6594  break;
6595  }
6596 
6597  default:
6598  {
6599  m_it.primitive_iterator.set_begin();
6600  break;
6601  }
6602  }
6603  }
6604 
6606  void set_end() noexcept
6607  {
6608  assert(m_object != nullptr);
6609 
6610  switch (m_object->m_type)
6611  {
6613  {
6614  assert(m_object->m_value.object != nullptr);
6615  m_it.object_iterator = m_object->m_value.object->end();
6616  break;
6617  }
6618 
6620  {
6621  assert(m_object->m_value.array != nullptr);
6622  m_it.array_iterator = m_object->m_value.array->end();
6623  break;
6624  }
6625 
6626  default:
6627  {
6628  m_it.primitive_iterator.set_end();
6629  break;
6630  }
6631  }
6632  }
6633 
6634  public:
6637  {
6638  assert(m_object != nullptr);
6639 
6640  switch (m_object->m_type)
6641  {
6643  {
6644  assert(m_object->m_value.object);
6645  assert(m_it.object_iterator != m_object->m_value.object->end());
6646  return m_it.object_iterator->second;
6647  }
6648 
6650  {
6651  assert(m_object->m_value.array);
6652  assert(m_it.array_iterator != m_object->m_value.array->end());
6653  return *m_it.array_iterator;
6654  }
6655 
6657  {
6658  throw std::out_of_range("cannot get value");
6659  }
6660 
6661  default:
6662  {
6663  if (m_it.primitive_iterator.is_begin())
6664  {
6665  return *m_object;
6666  }
6667  else
6668  {
6669  throw std::out_of_range("cannot get value");
6670  }
6671  }
6672  }
6673  }
6674 
6677  {
6678  assert(m_object != nullptr);
6679 
6680  switch (m_object->m_type)
6681  {
6683  {
6684  assert(m_object->m_value.object);
6685  assert(m_it.object_iterator != m_object->m_value.object->end());
6686  return &(m_it.object_iterator->second);
6687  }
6688 
6690  {
6691  assert(m_object->m_value.array);
6692  assert(m_it.array_iterator != m_object->m_value.array->end());
6693  return &*m_it.array_iterator;
6694  }
6695 
6696  default:
6697  {
6698  if (m_it.primitive_iterator.is_begin())
6699  {
6700  return m_object;
6701  }
6702  else
6703  {
6704  throw std::out_of_range("cannot get value");
6705  }
6706  }
6707  }
6708  }
6709 
6712  {
6713  auto result = *this;
6714  ++(*this);
6715  return result;
6716  }
6717 
6720  {
6721  assert(m_object != nullptr);
6722 
6723  switch (m_object->m_type)
6724  {
6726  {
6727  ++m_it.object_iterator;
6728  break;
6729  }
6730 
6732  {
6733  ++m_it.array_iterator;
6734  break;
6735  }
6736 
6737  default:
6738  {
6739  ++m_it.primitive_iterator;
6740  break;
6741  }
6742  }
6743 
6744  return *this;
6745  }
6746 
6749  {
6750  auto result = *this;
6751  --(*this);
6752  return result;
6753  }
6754 
6757  {
6758  assert(m_object != nullptr);
6759 
6760  switch (m_object->m_type)
6761  {
6763  {
6764  --m_it.object_iterator;
6765  break;
6766  }
6767 
6769  {
6770  --m_it.array_iterator;
6771  break;
6772  }
6773 
6774  default:
6775  {
6776  --m_it.primitive_iterator;
6777  break;
6778  }
6779  }
6780 
6781  return *this;
6782  }
6783 
6785  bool operator==(const const_iterator& other) const
6786  {
6787  // if objects are not the same, the comparison is undefined
6788  if (m_object != other.m_object)
6789  {
6790  throw std::domain_error("cannot compare iterators of different containers");
6791  }
6792 
6793  assert(m_object != nullptr);
6794 
6795  switch (m_object->m_type)
6796  {
6798  {
6799  return (m_it.object_iterator == other.m_it.object_iterator);
6800  }
6801 
6803  {
6804  return (m_it.array_iterator == other.m_it.array_iterator);
6805  }
6806 
6807  default:
6808  {
6809  return (m_it.primitive_iterator == other.m_it.primitive_iterator);
6810  }
6811  }
6812  }
6813 
6815  bool operator!=(const const_iterator& other) const
6816  {
6817  return not operator==(other);
6818  }
6819 
6821  bool operator<(const const_iterator& other) const
6822  {
6823  // if objects are not the same, the comparison is undefined
6824  if (m_object != other.m_object)
6825  {
6826  throw std::domain_error("cannot compare iterators of different containers");
6827  }
6828 
6829  assert(m_object != nullptr);
6830 
6831  switch (m_object->m_type)
6832  {
6834  {
6835  throw std::domain_error("cannot compare order of object iterators");
6836  }
6837 
6839  {
6840  return (m_it.array_iterator < other.m_it.array_iterator);
6841  }
6842 
6843  default:
6844  {
6845  return (m_it.primitive_iterator < other.m_it.primitive_iterator);
6846  }
6847  }
6848  }
6849 
6851  bool operator<=(const const_iterator& other) const
6852  {
6853  return not other.operator < (*this);
6854  }
6855 
6857  bool operator>(const const_iterator& other) const
6858  {
6859  return not operator<=(other);
6860  }
6861 
6863  bool operator>=(const const_iterator& other) const
6864  {
6865  return not operator<(other);
6866  }
6867 
6870  {
6871  assert(m_object != nullptr);
6872 
6873  switch (m_object->m_type)
6874  {
6876  {
6877  throw std::domain_error("cannot use offsets with object iterators");
6878  }
6879 
6881  {
6882  m_it.array_iterator += i;
6883  break;
6884  }
6885 
6886  default:
6887  {
6888  m_it.primitive_iterator += i;
6889  break;
6890  }
6891  }
6892 
6893  return *this;
6894  }
6895 
6898  {
6899  return operator+=(-i);
6900  }
6901 
6904  {
6905  auto result = *this;
6906  result += i;
6907  return result;
6908  }
6909 
6912  {
6913  auto result = *this;
6914  result -= i;
6915  return result;
6916  }
6917 
6920  {
6921  assert(m_object != nullptr);
6922 
6923  switch (m_object->m_type)
6924  {
6926  {
6927  throw std::domain_error("cannot use offsets with object iterators");
6928  }
6929 
6931  {
6932  return m_it.array_iterator - other.m_it.array_iterator;
6933  }
6934 
6935  default:
6936  {
6937  return m_it.primitive_iterator - other.m_it.primitive_iterator;
6938  }
6939  }
6940  }
6941 
6944  {
6945  assert(m_object != nullptr);
6946 
6947  switch (m_object->m_type)
6948  {
6950  {
6951  throw std::domain_error("cannot use operator[] for object iterators");
6952  }
6953 
6955  {
6956  return *(m_it.array_iterator + n);
6957  }
6958 
6960  {
6961  throw std::out_of_range("cannot get value");
6962  }
6963 
6964  default:
6965  {
6966  if (m_it.primitive_iterator == -n)
6967  {
6968  return *m_object;
6969  }
6970  else
6971  {
6972  throw std::out_of_range("cannot get value");
6973  }
6974  }
6975  }
6976  }
6977 
6979  typename object_t::key_type key() const
6980  {
6981  assert(m_object != nullptr);
6982 
6983  if (m_object->is_object())
6984  {
6985  return m_it.object_iterator->first;
6986  }
6987  else
6988  {
6989  throw std::domain_error("cannot use key() for non-object iterators");
6990  }
6991  }
6992 
6995  {
6996  return operator*();
6997  }
6998 
6999  private:
7001  pointer m_object = nullptr;
7003  internal_iterator m_it = internal_iterator();
7004  };
7005 
7018  class iterator : public const_iterator
7019  {
7020  public:
7022  using pointer = typename basic_json::pointer;
7024 
7026  iterator() = default;
7027 
7029  explicit iterator(pointer object) noexcept
7030  : base_iterator(object)
7031  {}
7032 
7034  iterator(const iterator& other) noexcept
7035  : base_iterator(other)
7036  {}
7037 
7039  iterator& operator=(iterator other) noexcept(
7040  std::is_nothrow_move_constructible<pointer>::value and
7041  std::is_nothrow_move_assignable<pointer>::value and
7042  std::is_nothrow_move_constructible<internal_iterator>::value and
7043  std::is_nothrow_move_assignable<internal_iterator>::value
7044  )
7045  {
7046  base_iterator::operator=(other);
7047  return *this;
7048  }
7049 
7052  {
7053  return const_cast<reference>(base_iterator::operator*());
7054  }
7055 
7058  {
7059  return const_cast<pointer>(base_iterator::operator->());
7060  }
7061 
7064  {
7065  iterator result = *this;
7066  base_iterator::operator++();
7067  return result;
7068  }
7069 
7072  {
7073  base_iterator::operator++();
7074  return *this;
7075  }
7076 
7079  {
7080  iterator result = *this;
7081  base_iterator::operator--();
7082  return result;
7083  }
7084 
7087  {
7088  base_iterator::operator--();
7089  return *this;
7090  }
7091 
7094  {
7095  base_iterator::operator+=(i);
7096  return *this;
7097  }
7098 
7101  {
7102  base_iterator::operator-=(i);
7103  return *this;
7104  }
7105 
7108  {
7109  auto result = *this;
7110  result += i;
7111  return result;
7112  }
7113 
7116  {
7117  auto result = *this;
7118  result -= i;
7119  return result;
7120  }
7121 
7123  difference_type operator-(const iterator& other) const
7124  {
7125  return base_iterator::operator-(other);
7126  }
7127 
7130  {
7131  return const_cast<reference>(base_iterator::operator[](n));
7132  }
7133 
7136  {
7137  return const_cast<reference>(base_iterator::value());
7138  }
7139  };
7140 
7158  template<typename Base>
7159  class json_reverse_iterator : public std::reverse_iterator<Base>
7160  {
7161  public:
7163  using base_iterator = std::reverse_iterator<Base>;
7165  using reference = typename Base::reference;
7166 
7168  json_reverse_iterator(const typename base_iterator::iterator_type& it) noexcept
7169  : base_iterator(it)
7170  {}
7171 
7174  : base_iterator(it)
7175  {}
7176 
7179  {
7180  return base_iterator::operator++(1);
7181  }
7182 
7185  {
7186  base_iterator::operator++();
7187  return *this;
7188  }
7189 
7192  {
7193  return base_iterator::operator--(1);
7194  }
7195 
7198  {
7199  base_iterator::operator--();
7200  return *this;
7201  }
7202 
7205  {
7206  base_iterator::operator+=(i);
7207  return *this;
7208  }
7209 
7212  {
7213  auto result = *this;
7214  result += i;
7215  return result;
7216  }
7217 
7220  {
7221  auto result = *this;
7222  result -= i;
7223  return result;
7224  }
7225 
7228  {
7229  return this->base() - other.base();
7230  }
7231 
7234  {
7235  return *(this->operator+(n));
7236  }
7237 
7239  typename object_t::key_type key() const
7240  {
7241  auto it = --this->base();
7242  return it.key();
7243  }
7244 
7247  {
7248  auto it = --this->base();
7249  return it.operator * ();
7250  }
7251  };
7252 
7253 
7254  private:
7256  // lexer and parser //
7258 
7266  class lexer
7267  {
7268  public:
7270  enum class token_type
7271  {
7272  uninitialized,
7273  literal_true,
7274  literal_false,
7275  literal_null,
7276  value_string,
7277  value_number,
7278  begin_array,
7279  begin_object,
7280  end_array,
7281  end_object,
7282  name_separator,
7283  value_separator,
7284  parse_error,
7285  end_of_input
7286  };
7287 
7289  using lexer_char_t = unsigned char;
7290 
7292  explicit lexer(const string_t& s) noexcept
7293  : m_stream(nullptr), m_buffer(s)
7294  {
7295  m_content = reinterpret_cast<const lexer_char_t*>(s.c_str());
7296  assert(m_content != nullptr);
7297  m_start = m_cursor = m_content;
7298  m_limit = m_content + s.size();
7299  }
7300 
7302  explicit lexer(std::istream* s) noexcept
7303  : m_stream(s), m_buffer()
7304  {
7305  assert(m_stream != nullptr);
7306  getline(*m_stream, m_buffer);
7307  m_content = reinterpret_cast<const lexer_char_t*>(m_buffer.c_str());
7308  assert(m_content != nullptr);
7309  m_start = m_cursor = m_content;
7310  m_limit = m_content + m_buffer.size();
7311  }
7312 
7314  lexer() = default;
7315 
7316  // switch off unwanted functions
7317  lexer(const lexer&) = delete;
7318  lexer operator=(const lexer&) = delete;
7319 
7335  static string_t to_unicode(const std::size_t codepoint1,
7336  const std::size_t codepoint2 = 0)
7337  {
7338  // calculate the codepoint from the given code points
7339  std::size_t codepoint = codepoint1;
7340 
7341  // check if codepoint1 is a high surrogate
7342  if (codepoint1 >= 0xD800 and codepoint1 <= 0xDBFF)
7343  {
7344  // check if codepoint2 is a low surrogate
7345  if (codepoint2 >= 0xDC00 and codepoint2 <= 0xDFFF)
7346  {
7347  codepoint =
7348  // high surrogate occupies the most significant 22 bits
7349  (codepoint1 << 10)
7350  // low surrogate occupies the least significant 15 bits
7351  + codepoint2
7352  // there is still the 0xD800, 0xDC00 and 0x10000 noise
7353  // in the result so we have to subtract with:
7354  // (0xD800 << 10) + DC00 - 0x10000 = 0x35FDC00
7355  - 0x35FDC00;
7356  }
7357  else
7358  {
7359  throw std::invalid_argument("missing or wrong low surrogate");
7360  }
7361  }
7362 
7363  string_t result;
7364 
7365  if (codepoint < 0x80)
7366  {
7367  // 1-byte characters: 0xxxxxxx (ASCII)
7368  result.append(1, static_cast<typename string_t::value_type>(codepoint));
7369  }
7370  else if (codepoint <= 0x7ff)
7371  {
7372  // 2-byte characters: 110xxxxx 10xxxxxx
7373  result.append(1, static_cast<typename string_t::value_type>(0xC0 | ((codepoint >> 6) & 0x1F)));
7374  result.append(1, static_cast<typename string_t::value_type>(0x80 | (codepoint & 0x3F)));
7375  }
7376  else if (codepoint <= 0xffff)
7377  {
7378  // 3-byte characters: 1110xxxx 10xxxxxx 10xxxxxx
7379  result.append(1, static_cast<typename string_t::value_type>(0xE0 | ((codepoint >> 12) & 0x0F)));
7380  result.append(1, static_cast<typename string_t::value_type>(0x80 | ((codepoint >> 6) & 0x3F)));
7381  result.append(1, static_cast<typename string_t::value_type>(0x80 | (codepoint & 0x3F)));
7382  }
7383  else if (codepoint <= 0x10ffff)
7384  {
7385  // 4-byte characters: 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
7386  result.append(1, static_cast<typename string_t::value_type>(0xF0 | ((codepoint >> 18) & 0x07)));
7387  result.append(1, static_cast<typename string_t::value_type>(0x80 | ((codepoint >> 12) & 0x3F)));
7388  result.append(1, static_cast<typename string_t::value_type>(0x80 | ((codepoint >> 6) & 0x3F)));
7389  result.append(1, static_cast<typename string_t::value_type>(0x80 | (codepoint & 0x3F)));
7390  }
7391  else
7392  {
7393  throw std::out_of_range("code points above 0x10FFFF are invalid");
7394  }
7395 
7396  return result;
7397  }
7398 
7400  static std::string token_type_name(token_type t)
7401  {
7402  switch (t)
7403  {
7404  case token_type::uninitialized:
7405  return "<uninitialized>";
7406  case token_type::literal_true:
7407  return "true literal";
7408  case token_type::literal_false:
7409  return "false literal";
7410  case token_type::literal_null:
7411  return "null literal";
7412  case token_type::value_string:
7413  return "string literal";
7414  case token_type::value_number:
7415  return "number literal";
7416  case token_type::begin_array:
7417  return "'['";
7418  case token_type::begin_object:
7419  return "'{'";
7420  case token_type::end_array:
7421  return "']'";
7422  case token_type::end_object:
7423  return "'}'";
7424  case token_type::name_separator:
7425  return "':'";
7426  case token_type::value_separator:
7427  return "','";
7428  case token_type::parse_error:
7429  return "<parse error>";
7430  case token_type::end_of_input:
7431  return "end of input";
7432  default:
7433  {
7434  // catch non-enum values
7435  return "unknown token"; // LCOV_EXCL_LINE
7436  }
7437  }
7438  }
7439 
7450  token_type scan() noexcept
7451  {
7452  // pointer for backtracking information
7453  m_marker = nullptr;
7454 
7455  // remember the begin of the token
7456  m_start = m_cursor;
7457  assert(m_start != nullptr);
7458 
7459 
7460  {
7461  lexer_char_t yych;
7462  unsigned int yyaccept = 0;
7463  static const unsigned char yybm[] =
7464  {
7465  0, 0, 0, 0, 0, 0, 0, 0,
7466  0, 32, 32, 0, 0, 32, 0, 0,
7467  128, 128, 128, 128, 128, 128, 128, 128,
7468  128, 128, 128, 128, 128, 128, 128, 128,
7469  160, 128, 0, 128, 128, 128, 128, 128,
7470  128, 128, 128, 128, 128, 128, 128, 128,
7471  192, 192, 192, 192, 192, 192, 192, 192,
7472  192, 192, 128, 128, 128, 128, 128, 128,
7473  128, 128, 128, 128, 128, 128, 128, 128,
7474  128, 128, 128, 128, 128, 128, 128, 128,
7475  128, 128, 128, 128, 128, 128, 128, 128,
7476  128, 128, 128, 128, 0, 128, 128, 128,
7477  128, 128, 128, 128, 128, 128, 128, 128,
7478  128, 128, 128, 128, 128, 128, 128, 128,
7479  128, 128, 128, 128, 128, 128, 128, 128,
7480  128, 128, 128, 128, 128, 128, 128, 128,
7481  128, 128, 128, 128, 128, 128, 128, 128,
7482  128, 128, 128, 128, 128, 128, 128, 128,
7483  128, 128, 128, 128, 128, 128, 128, 128,
7484  128, 128, 128, 128, 128, 128, 128, 128,
7485  128, 128, 128, 128, 128, 128, 128, 128,
7486  128, 128, 128, 128, 128, 128, 128, 128,
7487  128, 128, 128, 128, 128, 128, 128, 128,
7488  128, 128, 128, 128, 128, 128, 128, 128,
7489  128, 128, 128, 128, 128, 128, 128, 128,
7490  128, 128, 128, 128, 128, 128, 128, 128,
7491  128, 128, 128, 128, 128, 128, 128, 128,
7492  128, 128, 128, 128, 128, 128, 128, 128,
7493  128, 128, 128, 128, 128, 128, 128, 128,
7494  128, 128, 128, 128, 128, 128, 128, 128,
7495  128, 128, 128, 128, 128, 128, 128, 128,
7496  128, 128, 128, 128, 128, 128, 128, 128,
7497  };
7498  if ((m_limit - m_cursor) < 5)
7499  {
7500  yyfill(); // LCOV_EXCL_LINE;
7501  }
7502  yych = *m_cursor;
7503  if (yybm[0 + yych] & 32)
7504  {
7505  goto basic_json_parser_6;
7506  }
7507  if (yych <= '\\')
7508  {
7509  if (yych <= '-')
7510  {
7511  if (yych <= '"')
7512  {
7513  if (yych <= 0x00)
7514  {
7515  goto basic_json_parser_2;
7516  }
7517  if (yych <= '!')
7518  {
7519  goto basic_json_parser_4;
7520  }
7521  goto basic_json_parser_9;
7522  }
7523  else
7524  {
7525  if (yych <= '+')
7526  {
7527  goto basic_json_parser_4;
7528  }
7529  if (yych <= ',')
7530  {
7531  goto basic_json_parser_10;
7532  }
7533  goto basic_json_parser_12;
7534  }
7535  }
7536  else
7537  {
7538  if (yych <= '9')
7539  {
7540  if (yych <= '/')
7541  {
7542  goto basic_json_parser_4;
7543  }
7544  if (yych <= '0')
7545  {
7546  goto basic_json_parser_13;
7547  }
7548  goto basic_json_parser_15;
7549  }
7550  else
7551  {
7552  if (yych <= ':')
7553  {
7554  goto basic_json_parser_17;
7555  }
7556  if (yych == '[')
7557  {
7558  goto basic_json_parser_19;
7559  }
7560  goto basic_json_parser_4;
7561  }
7562  }
7563  }
7564  else
7565  {
7566  if (yych <= 't')
7567  {
7568  if (yych <= 'f')
7569  {
7570  if (yych <= ']')
7571  {
7572  goto basic_json_parser_21;
7573  }
7574  if (yych <= 'e')
7575  {
7576  goto basic_json_parser_4;
7577  }
7578  goto basic_json_parser_23;
7579  }
7580  else
7581  {
7582  if (yych == 'n')
7583  {
7584  goto basic_json_parser_24;
7585  }
7586  if (yych <= 's')
7587  {
7588  goto basic_json_parser_4;
7589  }
7590  goto basic_json_parser_25;
7591  }
7592  }
7593  else
7594  {
7595  if (yych <= '|')
7596  {
7597  if (yych == '{')
7598  {
7599  goto basic_json_parser_26;
7600  }
7601  goto basic_json_parser_4;
7602  }
7603  else
7604  {
7605  if (yych <= '}')
7606  {
7607  goto basic_json_parser_28;
7608  }
7609  if (yych == 0xEF)
7610  {
7611  goto basic_json_parser_30;
7612  }
7613  goto basic_json_parser_4;
7614  }
7615  }
7616  }
7617 basic_json_parser_2:
7618  ++m_cursor;
7619  {
7620  return token_type::end_of_input;
7621  }
7622 basic_json_parser_4:
7623  ++m_cursor;
7624 basic_json_parser_5:
7625  {
7626  return token_type::parse_error;
7627  }
7628 basic_json_parser_6:
7629  ++m_cursor;
7630  if (m_limit <= m_cursor)
7631  {
7632  yyfill(); // LCOV_EXCL_LINE;
7633  }
7634  yych = *m_cursor;
7635  if (yybm[0 + yych] & 32)
7636  {
7637  goto basic_json_parser_6;
7638  }
7639  {
7640  return scan();
7641  }
7642 basic_json_parser_9:
7643  yyaccept = 0;
7644  yych = *(m_marker = ++m_cursor);
7645  if (yych <= 0x0F)
7646  {
7647  goto basic_json_parser_5;
7648  }
7649  goto basic_json_parser_32;
7650 basic_json_parser_10:
7651  ++m_cursor;
7652  {
7653  return token_type::value_separator;
7654  }
7655 basic_json_parser_12:
7656  yych = *++m_cursor;
7657  if (yych <= '/')
7658  {
7659  goto basic_json_parser_5;
7660  }
7661  if (yych <= '0')
7662  {
7663  goto basic_json_parser_13;
7664  }
7665  if (yych <= '9')
7666  {
7667  goto basic_json_parser_15;
7668  }
7669  goto basic_json_parser_5;
7670 basic_json_parser_13:
7671  yyaccept = 1;
7672  yych = *(m_marker = ++m_cursor);
7673  if (yych <= 'D')
7674  {
7675  if (yych == '.')
7676  {
7677  goto basic_json_parser_37;
7678  }
7679  }
7680  else
7681  {
7682  if (yych <= 'E')
7683  {
7684  goto basic_json_parser_38;
7685  }
7686  if (yych == 'e')
7687  {
7688  goto basic_json_parser_38;
7689  }
7690  }
7691 basic_json_parser_14:
7692  {
7693  return token_type::value_number;
7694  }
7695 basic_json_parser_15:
7696  yyaccept = 1;
7697  m_marker = ++m_cursor;
7698  if ((m_limit - m_cursor) < 3)
7699  {
7700  yyfill(); // LCOV_EXCL_LINE;
7701  }
7702  yych = *m_cursor;
7703  if (yybm[0 + yych] & 64)
7704  {
7705  goto basic_json_parser_15;
7706  }
7707  if (yych <= 'D')
7708  {
7709  if (yych == '.')
7710  {
7711  goto basic_json_parser_37;
7712  }
7713  goto basic_json_parser_14;
7714  }
7715  else
7716  {
7717  if (yych <= 'E')
7718  {
7719  goto basic_json_parser_38;
7720  }
7721  if (yych == 'e')
7722  {
7723  goto basic_json_parser_38;
7724  }
7725  goto basic_json_parser_14;
7726  }
7727 basic_json_parser_17:
7728  ++m_cursor;
7729  {
7730  return token_type::name_separator;
7731  }
7732 basic_json_parser_19:
7733  ++m_cursor;
7734  {
7735  return token_type::begin_array;
7736  }
7737 basic_json_parser_21:
7738  ++m_cursor;
7739  {
7740  return token_type::end_array;
7741  }
7742 basic_json_parser_23:
7743  yyaccept = 0;
7744  yych = *(m_marker = ++m_cursor);
7745  if (yych == 'a')
7746  {
7747  goto basic_json_parser_39;
7748  }
7749  goto basic_json_parser_5;
7750 basic_json_parser_24:
7751  yyaccept = 0;
7752  yych = *(m_marker = ++m_cursor);
7753  if (yych == 'u')
7754  {
7755  goto basic_json_parser_40;
7756  }
7757  goto basic_json_parser_5;
7758 basic_json_parser_25:
7759  yyaccept = 0;
7760  yych = *(m_marker = ++m_cursor);
7761  if (yych == 'r')
7762  {
7763  goto basic_json_parser_41;
7764  }
7765  goto basic_json_parser_5;
7766 basic_json_parser_26:
7767  ++m_cursor;
7768  {
7769  return token_type::begin_object;
7770  }
7771 basic_json_parser_28:
7772  ++m_cursor;
7773  {
7774  return token_type::end_object;
7775  }
7776 basic_json_parser_30:
7777  yyaccept = 0;
7778  yych = *(m_marker = ++m_cursor);
7779  if (yych == 0xBB)
7780  {
7781  goto basic_json_parser_42;
7782  }
7783  goto basic_json_parser_5;
7784 basic_json_parser_31:
7785  ++m_cursor;
7786  if (m_limit <= m_cursor)
7787  {
7788  yyfill(); // LCOV_EXCL_LINE;
7789  }
7790  yych = *m_cursor;
7791 basic_json_parser_32:
7792  if (yybm[0 + yych] & 128)
7793  {
7794  goto basic_json_parser_31;
7795  }
7796  if (yych <= 0x0F)
7797  {
7798  goto basic_json_parser_33;
7799  }
7800  if (yych <= '"')
7801  {
7802  goto basic_json_parser_34;
7803  }
7804  goto basic_json_parser_36;
7805 basic_json_parser_33:
7806  m_cursor = m_marker;
7807  if (yyaccept == 0)
7808  {
7809  goto basic_json_parser_5;
7810  }
7811  else
7812  {
7813  goto basic_json_parser_14;
7814  }
7815 basic_json_parser_34:
7816  ++m_cursor;
7817  {
7818  return token_type::value_string;
7819  }
7820 basic_json_parser_36:
7821  ++m_cursor;
7822  if (m_limit <= m_cursor)
7823  {
7824  yyfill(); // LCOV_EXCL_LINE;
7825  }
7826  yych = *m_cursor;
7827  if (yych <= 'e')
7828  {
7829  if (yych <= '/')
7830  {
7831  if (yych == '"')
7832  {
7833  goto basic_json_parser_31;
7834  }
7835  if (yych <= '.')
7836  {
7837  goto basic_json_parser_33;
7838  }
7839  goto basic_json_parser_31;
7840  }
7841  else
7842  {
7843  if (yych <= '\\')
7844  {
7845  if (yych <= '[')
7846  {
7847  goto basic_json_parser_33;
7848  }
7849  goto basic_json_parser_31;
7850  }
7851  else
7852  {
7853  if (yych == 'b')
7854  {
7855  goto basic_json_parser_31;
7856  }
7857  goto basic_json_parser_33;
7858  }
7859  }
7860  }
7861  else
7862  {
7863  if (yych <= 'q')
7864  {
7865  if (yych <= 'f')
7866  {
7867  goto basic_json_parser_31;
7868  }
7869  if (yych == 'n')
7870  {
7871  goto basic_json_parser_31;
7872  }
7873  goto basic_json_parser_33;
7874  }
7875  else
7876  {
7877  if (yych <= 's')
7878  {
7879  if (yych <= 'r')
7880  {
7881  goto basic_json_parser_31;
7882  }
7883  goto basic_json_parser_33;
7884  }
7885  else
7886  {
7887  if (yych <= 't')
7888  {
7889  goto basic_json_parser_31;
7890  }
7891  if (yych <= 'u')
7892  {
7893  goto basic_json_parser_43;
7894  }
7895  goto basic_json_parser_33;
7896  }
7897  }
7898  }
7899 basic_json_parser_37:
7900  yych = *++m_cursor;
7901  if (yych <= '/')
7902  {
7903  goto basic_json_parser_33;
7904  }
7905  if (yych <= '9')
7906  {
7907  goto basic_json_parser_44;
7908  }
7909  goto basic_json_parser_33;
7910 basic_json_parser_38:
7911  yych = *++m_cursor;
7912  if (yych <= ',')
7913  {
7914  if (yych == '+')
7915  {
7916  goto basic_json_parser_46;
7917  }
7918  goto basic_json_parser_33;
7919  }
7920  else
7921  {
7922  if (yych <= '-')
7923  {
7924  goto basic_json_parser_46;
7925  }
7926  if (yych <= '/')
7927  {
7928  goto basic_json_parser_33;
7929  }
7930  if (yych <= '9')
7931  {
7932  goto basic_json_parser_47;
7933  }
7934  goto basic_json_parser_33;
7935  }
7936 basic_json_parser_39:
7937  yych = *++m_cursor;
7938  if (yych == 'l')
7939  {
7940  goto basic_json_parser_49;
7941  }
7942  goto basic_json_parser_33;
7943 basic_json_parser_40:
7944  yych = *++m_cursor;
7945  if (yych == 'l')
7946  {
7947  goto basic_json_parser_50;
7948  }
7949  goto basic_json_parser_33;
7950 basic_json_parser_41:
7951  yych = *++m_cursor;
7952  if (yych == 'u')
7953  {
7954  goto basic_json_parser_51;
7955  }
7956  goto basic_json_parser_33;
7957 basic_json_parser_42:
7958  yych = *++m_cursor;
7959  if (yych == 0xBF)
7960  {
7961  goto basic_json_parser_52;
7962  }
7963  goto basic_json_parser_33;
7964 basic_json_parser_43:
7965  ++m_cursor;
7966  if (m_limit <= m_cursor)
7967  {
7968  yyfill(); // LCOV_EXCL_LINE;
7969  }
7970  yych = *m_cursor;
7971  if (yych <= '@')
7972  {
7973  if (yych <= '/')
7974  {
7975  goto basic_json_parser_33;
7976  }
7977  if (yych <= '9')
7978  {
7979  goto basic_json_parser_54;
7980  }
7981  goto basic_json_parser_33;
7982  }
7983  else
7984  {
7985  if (yych <= 'F')
7986  {
7987  goto basic_json_parser_54;
7988  }
7989  if (yych <= '`')
7990  {
7991  goto basic_json_parser_33;
7992  }
7993  if (yych <= 'f')
7994  {
7995  goto basic_json_parser_54;
7996  }
7997  goto basic_json_parser_33;
7998  }
7999 basic_json_parser_44:
8000  yyaccept = 1;
8001  m_marker = ++m_cursor;
8002  if ((m_limit - m_cursor) < 3)
8003  {
8004  yyfill(); // LCOV_EXCL_LINE;
8005  }
8006  yych = *m_cursor;
8007  if (yych <= 'D')
8008  {
8009  if (yych <= '/')
8010  {
8011  goto basic_json_parser_14;
8012  }
8013  if (yych <= '9')
8014  {
8015  goto basic_json_parser_44;
8016  }
8017  goto basic_json_parser_14;
8018  }
8019  else
8020  {
8021  if (yych <= 'E')
8022  {
8023  goto basic_json_parser_38;
8024  }
8025  if (yych == 'e')
8026  {
8027  goto basic_json_parser_38;
8028  }
8029  goto basic_json_parser_14;
8030  }
8031 basic_json_parser_46:
8032  yych = *++m_cursor;
8033  if (yych <= '/')
8034  {
8035  goto basic_json_parser_33;
8036  }
8037  if (yych >= ':')
8038  {
8039  goto basic_json_parser_33;
8040  }
8041 basic_json_parser_47:
8042  ++m_cursor;
8043  if (m_limit <= m_cursor)
8044  {
8045  yyfill(); // LCOV_EXCL_LINE;
8046  }
8047  yych = *m_cursor;
8048  if (yych <= '/')
8049  {
8050  goto basic_json_parser_14;
8051  }
8052  if (yych <= '9')
8053  {
8054  goto basic_json_parser_47;
8055  }
8056  goto basic_json_parser_14;
8057 basic_json_parser_49:
8058  yych = *++m_cursor;
8059  if (yych == 's')
8060  {
8061  goto basic_json_parser_55;
8062  }
8063  goto basic_json_parser_33;
8064 basic_json_parser_50:
8065  yych = *++m_cursor;
8066  if (yych == 'l')
8067  {
8068  goto basic_json_parser_56;
8069  }
8070  goto basic_json_parser_33;
8071 basic_json_parser_51:
8072  yych = *++m_cursor;
8073  if (yych == 'e')
8074  {
8075  goto basic_json_parser_58;
8076  }
8077  goto basic_json_parser_33;
8078 basic_json_parser_52:
8079  ++m_cursor;
8080  {
8081  return scan();
8082  }
8083 basic_json_parser_54:
8084  ++m_cursor;
8085  if (m_limit <= m_cursor)
8086  {
8087  yyfill(); // LCOV_EXCL_LINE;
8088  }
8089  yych = *m_cursor;
8090  if (yych <= '@')
8091  {
8092  if (yych <= '/')
8093  {
8094  goto basic_json_parser_33;
8095  }
8096  if (yych <= '9')
8097  {
8098  goto basic_json_parser_60;
8099  }
8100  goto basic_json_parser_33;
8101  }
8102  else
8103  {
8104  if (yych <= 'F')
8105  {
8106  goto basic_json_parser_60;
8107  }
8108  if (yych <= '`')
8109  {
8110  goto basic_json_parser_33;
8111  }
8112  if (yych <= 'f')
8113  {
8114  goto basic_json_parser_60;
8115  }
8116  goto basic_json_parser_33;
8117  }
8118 basic_json_parser_55:
8119  yych = *++m_cursor;
8120  if (yych == 'e')
8121  {
8122  goto basic_json_parser_61;
8123  }
8124  goto basic_json_parser_33;
8125 basic_json_parser_56:
8126  ++m_cursor;
8127  {
8128  return token_type::literal_null;
8129  }
8130 basic_json_parser_58:
8131  ++m_cursor;
8132  {
8133  return token_type::literal_true;
8134  }
8135 basic_json_parser_60:
8136  ++m_cursor;
8137  if (m_limit <= m_cursor)
8138  {
8139  yyfill(); // LCOV_EXCL_LINE;
8140  }
8141  yych = *m_cursor;
8142  if (yych <= '@')
8143  {
8144  if (yych <= '/')
8145  {
8146  goto basic_json_parser_33;
8147  }
8148  if (yych <= '9')
8149  {
8150  goto basic_json_parser_63;
8151  }
8152  goto basic_json_parser_33;
8153  }
8154  else
8155  {
8156  if (yych <= 'F')
8157  {
8158  goto basic_json_parser_63;
8159  }
8160  if (yych <= '`')
8161  {
8162  goto basic_json_parser_33;
8163  }
8164  if (yych <= 'f')
8165  {
8166  goto basic_json_parser_63;
8167  }
8168  goto basic_json_parser_33;
8169  }
8170 basic_json_parser_61:
8171  ++m_cursor;
8172  {
8173  return token_type::literal_false;
8174  }
8175 basic_json_parser_63:
8176  ++m_cursor;
8177  if (m_limit <= m_cursor)
8178  {
8179  yyfill(); // LCOV_EXCL_LINE;
8180  }
8181  yych = *m_cursor;
8182  if (yych <= '@')
8183  {
8184  if (yych <= '/')
8185  {
8186  goto basic_json_parser_33;
8187  }
8188  if (yych <= '9')
8189  {
8190  goto basic_json_parser_31;
8191  }
8192  goto basic_json_parser_33;
8193  }
8194  else
8195  {
8196  if (yych <= 'F')
8197  {
8198  goto basic_json_parser_31;
8199  }
8200  if (yych <= '`')
8201  {
8202  goto basic_json_parser_33;
8203  }
8204  if (yych <= 'f')
8205  {
8206  goto basic_json_parser_31;
8207  }
8208  goto basic_json_parser_33;
8209  }
8210  }
8211 
8212  }
8213 
8215  void yyfill() noexcept
8216  {
8217  if (m_stream == nullptr or not * m_stream)
8218  {
8219  return;
8220  }
8221 
8222  const auto offset_start = m_start - m_content;
8223  const auto offset_marker = m_marker - m_start;
8224  const auto offset_cursor = m_cursor - m_start;
8225 
8226  m_buffer.erase(0, static_cast<size_t>(offset_start));
8227  std::string line;
8228  assert(m_stream != nullptr);
8229  std::getline(*m_stream, line);
8230  m_buffer += "\n" + line; // add line with newline symbol
8231 
8232  m_content = reinterpret_cast<const lexer_char_t*>(m_buffer.c_str());
8233  assert(m_content != nullptr);
8234  m_start = m_content;
8235  m_marker = m_start + offset_marker;
8236  m_cursor = m_start + offset_cursor;
8237  m_limit = m_start + m_buffer.size() - 1;
8238  }
8239 
8241  string_t get_token() const
8242  {
8243  assert(m_start != nullptr);
8244  return string_t(reinterpret_cast<typename string_t::const_pointer>(m_start),
8245  static_cast<size_t>(m_cursor - m_start));
8246  }
8247 
8269  string_t get_string() const
8270  {
8271  string_t result;
8272  result.reserve(static_cast<size_t>(m_cursor - m_start - 2));
8273 
8274  // iterate the result between the quotes
8275  for (const lexer_char_t* i = m_start + 1; i < m_cursor - 1; ++i)
8276  {
8277  // process escaped characters
8278  if (*i == '\\')
8279  {
8280  // read next character
8281  ++i;
8282 
8283  switch (*i)
8284  {
8285  // the default escapes
8286  case 't':
8287  {
8288  result += "\t";
8289  break;
8290  }
8291  case 'b':
8292  {
8293  result += "\b";
8294  break;
8295  }
8296  case 'f':
8297  {
8298  result += "\f";
8299  break;
8300  }
8301  case 'n':
8302  {
8303  result += "\n";
8304  break;
8305  }
8306  case 'r':
8307  {
8308  result += "\r";
8309  break;
8310  }
8311  case '\\':
8312  {
8313  result += "\\";
8314  break;
8315  }
8316  case '/':
8317  {
8318  result += "/";
8319  break;
8320  }
8321  case '"':
8322  {
8323  result += "\"";
8324  break;
8325  }
8326 
8327  // unicode
8328  case 'u':
8329  {
8330  // get code xxxx from uxxxx
8331  auto codepoint = std::strtoul(std::string(reinterpret_cast<typename string_t::const_pointer>(i + 1),
8332  4).c_str(), nullptr, 16);
8333 
8334  // check if codepoint is a high surrogate
8335  if (codepoint >= 0xD800 and codepoint <= 0xDBFF)
8336  {
8337  // make sure there is a subsequent unicode
8338  if ((i + 6 >= m_limit) or * (i + 5) != '\\' or * (i + 6) != 'u')
8339  {
8340  throw std::invalid_argument("missing low surrogate");
8341  }
8342 
8343  // get code yyyy from uxxxx\uyyyy
8344  auto codepoint2 = std::strtoul(std::string(reinterpret_cast<typename string_t::const_pointer>
8345  (i + 7), 4).c_str(), nullptr, 16);
8346  result += to_unicode(codepoint, codepoint2);
8347  // skip the next 10 characters (xxxx\uyyyy)
8348  i += 10;
8349  }
8350  else
8351  {
8352  // add unicode character(s)
8353  result += to_unicode(codepoint);
8354  // skip the next four characters (xxxx)
8355  i += 4;
8356  }
8357  break;
8358  }
8359  }
8360  }
8361  else
8362  {
8363  // all other characters are just copied to the end of the
8364  // string
8365  result.append(1, static_cast<typename string_t::value_type>(*i));
8366  }
8367  }
8368 
8369  return result;
8370  }
8371 
8392  long double str_to_float_t(long double* /* type */, char** endptr) const
8393  {
8394  return std::strtold(reinterpret_cast<typename string_t::const_pointer>(m_start), endptr);
8395  }
8396 
8412  double str_to_float_t(double* /* type */, char** endptr) const
8413  {
8414  return std::strtod(reinterpret_cast<typename string_t::const_pointer>(m_start), endptr);
8415  }
8416 
8432  float str_to_float_t(float* /* type */, char** endptr) const
8433  {
8434  return std::strtof(reinterpret_cast<typename string_t::const_pointer>(m_start), endptr);
8435  }
8436 
8464  void get_number(basic_json& result) const
8465  {
8466  assert(m_start != nullptr);
8467 
8468  const lexer::lexer_char_t* curptr = m_start;
8469 
8470  // remember this number was parsed (for later serialization)
8471  result.m_type.bits.parsed = true;
8472 
8473  // 'found_radix_point' will be set to 0xFF upon finding a radix
8474  // point and later used to mask in/out the precision depending
8475  // whether a radix is found i.e. 'precision &= found_radix_point'
8476  uint8_t found_radix_point = 0;
8477  uint8_t precision = 0;
8478 
8479  // accumulate the integer conversion result (unsigned for now)
8480  number_unsigned_t value = 0;
8481 
8482  // maximum absolute value of the relevant integer type
8483  number_unsigned_t max;
8484 
8485  // temporarily store the type to avoid unecessary bitfield access
8486  value_t type;
8487 
8488  // look for sign
8489  if (*curptr == '-')
8490  {
8491  type = value_t::number_integer;
8492  max = static_cast<uint64_t>(std::numeric_limits<number_integer_t>::max()) + 1;
8493  curptr++;
8494  }
8495  else
8496  {
8497  type = value_t::number_unsigned;
8498  max = static_cast<uint64_t>(std::numeric_limits<number_unsigned_t>::max());
8499  }
8500 
8501  // count the significant figures
8502  for (; curptr < m_cursor; curptr++)
8503  {
8504  // quickly skip tests if a digit
8505  if (*curptr < '0' || *curptr > '9')
8506  {
8507  if (*curptr == '.')
8508  {
8509  // don't count '.' but change to float
8510  type = value_t::number_float;
8511 
8512  // reset precision count
8513  precision = 0;
8514  found_radix_point = 0xFF;
8515  continue;
8516  }
8517  // assume exponent (if not then will fail parse): change to
8518  // float, stop counting and record exponent details
8519  type = value_t::number_float;
8520  result.m_type.bits.has_exp = true;
8521 
8522  // exponent capitalization
8523  result.m_type.bits.exp_cap = (*curptr == 'E');
8524 
8525  // exponent '+' sign
8526  result.m_type.bits.exp_plus = (*(++curptr) == '+');
8527  break;
8528  }
8529 
8530  // skip if definitely not an integer
8531  if (type != value_t::number_float)
8532  {
8533  // multiply last value by ten and add the new digit
8534  auto temp = value * 10 + *curptr - 0x30;
8535 
8536  // test for overflow
8537  if (temp < value || temp > max)
8538  {
8539  // overflow
8540  type = value_t::number_float;
8541  }
8542  else
8543  {
8544  // no overflow - save it
8545  value = temp;
8546  }
8547  }
8548  ++precision;
8549  }
8550 
8551  // If no radix point was found then precision would now be set to
8552  // the number of digits, which is wrong - clear it.
8553  result.m_type.bits.precision = precision & found_radix_point;
8554 
8555  // save the value (if not a float)
8556  if (type == value_t::number_unsigned)
8557  {
8558  result.m_value.number_unsigned = value;
8559  }
8560  else if (type == value_t::number_integer)
8561  {
8562  result.m_value.number_integer = -static_cast<number_integer_t>(value);
8563  }
8564  else
8565  {
8566  // parse with strtod
8567  result.m_value.number_float = str_to_float_t(static_cast<number_float_t*>(nullptr), NULL);
8568  }
8569 
8570  // save the type
8571  result.m_type = type;
8572  }
8573 
8574  private:
8576  std::istream* m_stream = nullptr;
8578  string_t m_buffer;
8580  const lexer_char_t* m_content = nullptr;
8582  const lexer_char_t* m_start = nullptr;
8584  const lexer_char_t* m_marker = nullptr;
8586  const lexer_char_t* m_cursor = nullptr;
8588  const lexer_char_t* m_limit = nullptr;
8589  };
8590 
8596  class parser
8597  {
8598  public:
8600  parser(const string_t& s, parser_callback_t cb = nullptr) noexcept
8601  : callback(cb), m_lexer(s)
8602  {
8603  // read first token
8604  get_token();
8605  }
8606 
8608  parser(std::istream& _is, parser_callback_t cb = nullptr) noexcept
8609  : callback(cb), m_lexer(&_is)
8610  {
8611  // read first token
8612  get_token();
8613  }
8614 
8616  basic_json parse()
8617  {
8618  basic_json result = parse_internal(true);
8619 
8620  expect(lexer::token_type::end_of_input);
8621 
8622  // return parser result and replace it with null in case the
8623  // top-level value was discarded by the callback function
8624  return result.is_discarded() ? basic_json() : result;
8625  }
8626 
8627  private:
8629  basic_json parse_internal(bool keep)
8630  {
8631  auto result = basic_json(value_t::discarded);
8632 
8633  switch (last_token)
8634  {
8635  case lexer::token_type::begin_object:
8636  {
8637  if (keep and (not callback or (keep = callback(depth++, parse_event_t::object_start, result))))
8638  {
8639  // explicitly set result to object to cope with {}
8640  result.m_type = value_t::object;
8641  result.m_value = json_value(value_t::object);
8642  }
8643 
8644  // read next token
8645  get_token();
8646 
8647  // closing } -> we are done
8648  if (last_token == lexer::token_type::end_object)
8649  {
8650  get_token();
8651  if (keep and callback and not callback(--depth, parse_event_t::object_end, result))
8652  {
8653  result = basic_json(value_t::discarded);
8654  }
8655  return result;
8656  }
8657 
8658  // no comma is expected here
8659  unexpect(lexer::token_type::value_separator);
8660 
8661  // otherwise: parse key-value pairs
8662  do
8663  {
8664  // ugly, but could be fixed with loop reorganization
8665  if (last_token == lexer::token_type::value_separator)
8666  {
8667  get_token();
8668  }
8669 
8670  // store key
8671  expect(lexer::token_type::value_string);
8672  const auto key = m_lexer.get_string();
8673 
8674  bool keep_tag = false;
8675  if (keep)
8676  {
8677  if (callback)
8678  {
8679  basic_json k(key);
8680  keep_tag = callback(depth, parse_event_t::key, k);
8681  }
8682  else
8683  {
8684  keep_tag = true;
8685  }
8686  }
8687 
8688  // parse separator (:)
8689  get_token();
8690  expect(lexer::token_type::name_separator);
8691 
8692  // parse and add value
8693  get_token();
8694  auto value = parse_internal(keep);
8695  if (keep and keep_tag and not value.is_discarded())
8696  {
8697  result[key] = std::move(value);
8698  }
8699  }
8700  while (last_token == lexer::token_type::value_separator);
8701 
8702  // closing }
8703  expect(lexer::token_type::end_object);
8704  get_token();
8705  if (keep and callback and not callback(--depth, parse_event_t::object_end, result))
8706  {
8707  result = basic_json(value_t::discarded);
8708  }
8709 
8710  return result;
8711  }
8712 
8713  case lexer::token_type::begin_array:
8714  {
8715  if (keep and (not callback or (keep = callback(depth++, parse_event_t::array_start, result))))
8716  {
8717  // explicitly set result to object to cope with []
8718  result.m_type = value_t::array;
8719  result.m_value = json_value(value_t::array);
8720  }
8721 
8722  // read next token
8723  get_token();
8724 
8725  // closing ] -> we are done
8726  if (last_token == lexer::token_type::end_array)
8727  {
8728  get_token();
8729  if (callback and not callback(--depth, parse_event_t::array_end, result))
8730  {
8731  result = basic_json(value_t::discarded);
8732  }
8733  return result;
8734  }
8735 
8736  // no comma is expected here
8737  unexpect(lexer::token_type::value_separator);
8738 
8739  // otherwise: parse values
8740  do
8741  {
8742  // ugly, but could be fixed with loop reorganization
8743  if (last_token == lexer::token_type::value_separator)
8744  {
8745  get_token();
8746  }
8747 
8748  // parse value
8749  auto value = parse_internal(keep);
8750  if (keep and not value.is_discarded())
8751  {
8752  result.push_back(std::move(value));
8753  }
8754  }
8755  while (last_token == lexer::token_type::value_separator);
8756 
8757  // closing ]
8758  expect(lexer::token_type::end_array);
8759  get_token();
8760  if (keep and callback and not callback(--depth, parse_event_t::array_end, result))
8761  {
8762  result = basic_json(value_t::discarded);
8763  }
8764 
8765  return result;
8766  }
8767 
8768  case lexer::token_type::literal_null:
8769  {
8770  get_token();
8771  result.m_type = value_t::null;
8772  break;
8773  }
8774 
8775  case lexer::token_type::value_string:
8776  {
8777  const auto s = m_lexer.get_string();
8778  get_token();
8779  result = basic_json(s);
8780  break;
8781  }
8782 
8783  case lexer::token_type::literal_true:
8784  {
8785  get_token();
8786  result.m_type = value_t::boolean;
8787  result.m_value = true;
8788  break;
8789  }
8790 
8791  case lexer::token_type::literal_false:
8792  {
8793  get_token();
8794  result.m_type = value_t::boolean;
8795  result.m_value = false;
8796  break;
8797  }
8798 
8799  case lexer::token_type::value_number:
8800  {
8801  m_lexer.get_number(result);
8802  get_token();
8803  break;
8804  }
8805 
8806  default:
8807  {
8808  // the last token was unexpected
8809  unexpect(last_token);
8810  }
8811  }
8812 
8813  if (keep and callback and not callback(depth, parse_event_t::value, result))
8814  {
8815  result = basic_json(value_t::discarded);
8816  }
8817  return result;
8818  }
8819 
8821  typename lexer::token_type get_token() noexcept
8822  {
8823  last_token = m_lexer.scan();
8824  return last_token;
8825  }
8826 
8827  void expect(typename lexer::token_type t) const
8828  {
8829  if (t != last_token)
8830  {
8831  std::string error_msg = "parse error - unexpected ";
8832  error_msg += (last_token == lexer::token_type::parse_error ? ("'" + m_lexer.get_token() + "'") :
8833  lexer::token_type_name(last_token));
8834  error_msg += "; expected " + lexer::token_type_name(t);
8835  throw std::invalid_argument(error_msg);
8836  }
8837  }
8838 
8839  void unexpect(typename lexer::token_type t) const
8840  {
8841  if (t == last_token)
8842  {
8843  std::string error_msg = "parse error - unexpected ";
8844  error_msg += (last_token == lexer::token_type::parse_error ? ("'" + m_lexer.get_token() + "'") :
8845  lexer::token_type_name(last_token));
8846  throw std::invalid_argument(error_msg);
8847  }
8848  }
8849 
8850  private:
8852  int depth = 0;
8854  parser_callback_t callback;
8856  typename lexer::token_type last_token = lexer::token_type::uninitialized;
8858  lexer m_lexer;
8859  };
8860 
8861  public:
8874  {
8876  friend class basic_json;
8877 
8878  public:
8901  explicit json_pointer(const std::string& s = "")
8902  : reference_tokens(split(s))
8903  {}
8904 
8920  std::string to_string() const noexcept
8921  {
8922  std::string result;
8923 
8924  for (const auto& reference_token : reference_tokens)
8925  {
8926  result += "/" + escape(reference_token);
8927  }
8928 
8929  return result;
8930  }
8931 
8933  operator std::string() const
8934  {
8935  return to_string();
8936  }
8938  private:
8940  std::string pop_back()
8941  {
8942  if (is_root())
8943  {
8944  throw std::domain_error("JSON pointer has no parent");
8945  }
8946 
8947  auto last = reference_tokens.back();
8948  reference_tokens.pop_back();
8949  return last;
8950  }
8951 
8953  bool is_root() const
8954  {
8955  return reference_tokens.empty();
8956  }
8957 
8958  json_pointer top() const
8959  {
8960  if (is_root())
8961  {
8962  throw std::domain_error("JSON pointer has no parent");
8963  }
8964 
8965  json_pointer result = *this;
8966  result.reference_tokens = {reference_tokens[0]};
8967  return result;
8968  }
8969 
8973  reference get_and_create(reference j) const
8974  {
8975  pointer result = &j;
8976 
8977  // in case no reference tokens exist, return a reference to the
8978  // JSON value j which will be overwritten by a primitive value
8979  for (const auto& reference_token : reference_tokens)
8980  {
8981  switch (result->m_type)
8982  {
8983  case value_t::null:
8984  {
8985  if (reference_token == "0")
8986  {
8987  // start a new array if reference token is 0
8988  result = &result->operator[](0);
8989  }
8990  else
8991  {
8992  // start a new object otherwise
8993  result = &result->operator[](reference_token);
8994  }
8995  break;
8996  }
8997 
8998  case value_t::object:
8999  {
9000  // create an entry in the object
9001  result = &result->operator[](reference_token);
9002  break;
9003  }
9004 
9005  case value_t::array:
9006  {
9007  // create an entry in the array
9008  result = &result->operator[](static_cast<size_type>(std::stoi(reference_token)));
9009  break;
9010  }
9011 
9012  /*
9013  The following code is only reached if there exists a
9014  reference token _and_ the current value is primitive. In
9015  this case, we have an error situation, because primitive
9016  values may only occur as single value; that is, with an
9017  empty list of reference tokens.
9018  */
9019  default:
9020  {
9021  throw std::domain_error("invalid value to unflatten");
9022  }
9023  }
9024  }
9025 
9026  return *result;
9027  }
9028 
9042  reference get_unchecked(pointer ptr) const
9043  {
9044  for (const auto& reference_token : reference_tokens)
9045  {
9046  switch (ptr->m_type)
9047  {
9048  case value_t::object:
9049  {
9050  // use unchecked object access
9051  ptr = &ptr->operator[](reference_token);
9052  break;
9053  }
9054 
9055  case value_t::array:
9056  {
9057  // error condition (cf. RFC 6901, Sect. 4)
9058  if (reference_token.size() > 1 and reference_token[0] == '0')
9059  {
9060  throw std::domain_error("array index must not begin with '0'");
9061  }
9062 
9063  if (reference_token == "-")
9064  {
9065  // explicityly treat "-" as index beyond the end
9066  ptr = &ptr->operator[](ptr->m_value.array->size());
9067  }
9068  else
9069  {
9070  // convert array index to number; unchecked access
9071  ptr = &ptr->operator[](static_cast<size_type>(std::stoi(reference_token)));
9072  }
9073  break;
9074  }
9075 
9076  default:
9077  {
9078  throw std::out_of_range("unresolved reference token '" + reference_token + "'");
9079  }
9080  }
9081  }
9082 
9083  return *ptr;
9084  }
9085 
9086  reference get_checked(pointer ptr) const
9087  {
9088  for (const auto& reference_token : reference_tokens)
9089  {
9090  switch (ptr->m_type)
9091  {
9092  case value_t::object:
9093  {
9094  // note: at performs range check
9095  ptr = &ptr->at(reference_token);
9096  break;
9097  }
9098 
9099  case value_t::array:
9100  {
9101  if (reference_token == "-")
9102  {
9103  // "-" always fails the range check
9104  throw std::out_of_range("array index '-' (" +
9105  std::to_string(ptr->m_value.array->size()) +
9106  ") is out of range");
9107  }
9108 
9109  // error condition (cf. RFC 6901, Sect. 4)
9110  if (reference_token.size() > 1 and reference_token[0] == '0')
9111  {
9112  throw std::domain_error("array index must not begin with '0'");
9113  }
9114 
9115  // note: at performs range check
9116  ptr = &ptr->at(static_cast<size_type>(std::stoi(reference_token)));
9117  break;
9118  }
9119 
9120  default:
9121  {
9122  throw std::out_of_range("unresolved reference token '" + reference_token + "'");
9123  }
9124  }
9125  }
9126 
9127  return *ptr;
9128  }
9129 
9138  const_reference get_unchecked(const_pointer ptr) const
9139  {
9140  for (const auto& reference_token : reference_tokens)
9141  {
9142  switch (ptr->m_type)
9143  {
9144  case value_t::object:
9145  {
9146  // use unchecked object access
9147  ptr = &ptr->operator[](reference_token);
9148  break;
9149  }
9150 
9151  case value_t::array:
9152  {
9153  if (reference_token == "-")
9154  {
9155  // "-" cannot be used for const access
9156  throw std::out_of_range("array index '-' (" +
9157  std::to_string(ptr->m_value.array->size()) +
9158  ") is out of range");
9159  }
9160 
9161  // error condition (cf. RFC 6901, Sect. 4)
9162  if (reference_token.size() > 1 and reference_token[0] == '0')
9163  {
9164  throw std::domain_error("array index must not begin with '0'");
9165  }
9166 
9167  // use unchecked array access
9168  ptr = &ptr->operator[](static_cast<size_type>(std::stoi(reference_token)));
9169  break;
9170  }
9171 
9172  default:
9173  {
9174  throw std::out_of_range("unresolved reference token '" + reference_token + "'");
9175  }
9176  }
9177  }
9178 
9179  return *ptr;
9180  }
9181 
9182  const_reference get_checked(const_pointer ptr) const
9183  {
9184  for (const auto& reference_token : reference_tokens)
9185  {
9186  switch (ptr->m_type)
9187  {
9188  case value_t::object:
9189  {
9190  // note: at performs range check
9191  ptr = &ptr->at(reference_token);
9192  break;
9193  }
9194 
9195  case value_t::array:
9196  {
9197  if (reference_token == "-")
9198  {
9199  // "-" always fails the range check
9200  throw std::out_of_range("array index '-' (" +
9201  std::to_string(ptr->m_value.array->size()) +
9202  ") is out of range");
9203  }
9204 
9205  // error condition (cf. RFC 6901, Sect. 4)
9206  if (reference_token.size() > 1 and reference_token[0] == '0')
9207  {
9208  throw std::domain_error("array index must not begin with '0'");
9209  }
9210 
9211  // note: at performs range check
9212  ptr = &ptr->at(static_cast<size_type>(std::stoi(reference_token)));
9213  break;
9214  }
9215 
9216  default:
9217  {
9218  throw std::out_of_range("unresolved reference token '" + reference_token + "'");
9219  }
9220  }
9221  }
9222 
9223  return *ptr;
9224  }
9225 
9227  static std::vector<std::string> split(std::string reference_string)
9228  {
9229  std::vector<std::string> result;
9230 
9231  // special case: empty reference string -> no reference tokens
9232  if (reference_string.empty())
9233  {
9234  return result;
9235  }
9236 
9237  // check if nonempty reference string begins with slash
9238  if (reference_string[0] != '/')
9239  {
9240  throw std::domain_error("JSON pointer must be empty or begin with '/'");
9241  }
9242 
9243  // extract the reference tokens:
9244  // - slash: position of the last read slash (or end of string)
9245  // - start: position after the previous slash
9246  for (
9247  // search for the first slash after the first character
9248  size_t slash = reference_string.find_first_of("/", 1),
9249  // set the beginning of the first reference token
9250  start = 1;
9251  // we can stop if start == string::npos+1 = 0
9252  start != 0;
9253  // set the beginning of the next reference token
9254  // (will eventually be 0 if slash == std::string::npos)
9255  start = slash + 1,
9256  // find next slash
9257  slash = reference_string.find_first_of("/", start))
9258  {
9259  // use the text between the beginning of the reference token
9260  // (start) and the last slash (slash).
9261  auto reference_token = reference_string.substr(start, slash - start);
9262 
9263  // check reference tokens are properly escaped
9264  for (size_t pos = reference_token.find_first_of("~");
9265  pos != std::string::npos;
9266  pos = reference_token.find_first_of("~", pos + 1))
9267  {
9268  assert(reference_token[pos] == '~');
9269 
9270  // ~ must be followed by 0 or 1
9271  if (pos == reference_token.size() - 1 or
9272  (reference_token[pos + 1] != '0' and
9273  reference_token[pos + 1] != '1'))
9274  {
9275  throw std::domain_error("escape error: '~' must be followed with '0' or '1'");
9276  }
9277  }
9278 
9279  // finally, store the reference token
9280  unescape(reference_token);
9281  result.push_back(reference_token);
9282  }
9283 
9284  return result;
9285  }
9286 
9287  private:
9302  static void replace_substring(std::string& s,
9303  const std::string& f,
9304  const std::string& t)
9305  {
9306  assert(not f.empty());
9307 
9308  for (
9309  size_t pos = s.find(f); // find first occurrence of f
9310  pos != std::string::npos; // make sure f was found
9311  s.replace(pos, f.size(), t), // replace with t
9312  pos = s.find(f, pos + t.size()) // find next occurrence of f
9313  );
9314  }
9315 
9317  static std::string escape(std::string s)
9318  {
9319  // escape "~"" to "~0" and "/" to "~1"
9320  replace_substring(s, "~", "~0");
9321  replace_substring(s, "/", "~1");
9322  return s;
9323  }
9324 
9326  static void unescape(std::string& s)
9327  {
9328  // first transform any occurrence of the sequence '~1' to '/'
9329  replace_substring(s, "~1", "/");
9330  // then transform any occurrence of the sequence '~0' to '~'
9331  replace_substring(s, "~0", "~");
9332  }
9333 
9341  static void flatten(const std::string& reference_string,
9342  const basic_json& value,
9343  basic_json& result)
9344  {
9345  switch (value.m_type)
9346  {
9347  case value_t::array:
9348  {
9349  if (value.m_value.array->empty())
9350  {
9351  // flatten empty array as null
9352  result[reference_string] = nullptr;
9353  }
9354  else
9355  {
9356  // iterate array and use index as reference string
9357  for (size_t i = 0; i < value.m_value.array->size(); ++i)
9358  {
9359  flatten(reference_string + "/" + std::to_string(i),
9360  value.m_value.array->operator[](i), result);
9361  }
9362  }
9363  break;
9364  }
9365 
9366  case value_t::object:
9367  {
9368  if (value.m_value.object->empty())
9369  {
9370  // flatten empty object as null
9371  result[reference_string] = nullptr;
9372  }
9373  else
9374  {
9375  // iterate object and use keys as reference string
9376  for (const auto& element : *value.m_value.object)
9377  {
9378  flatten(reference_string + "/" + escape(element.first),
9379  element.second, result);
9380  }
9381  }
9382  break;
9383  }
9384 
9385  default:
9386  {
9387  // add primitive value with its reference string
9388  result[reference_string] = value;
9389  break;
9390  }
9391  }
9392  }
9393 
9399  static basic_json unflatten(const basic_json& value)
9400  {
9401  if (not value.is_object())
9402  {
9403  throw std::domain_error("only objects can be unflattened");
9404  }
9405 
9406  basic_json result;
9407 
9408  // iterate the JSON object values
9409  for (const auto& element : *value.m_value.object)
9410  {
9411  if (not element.second.is_primitive())
9412  {
9413  throw std::domain_error("values in object must be primitive");
9414  }
9415 
9416  // assign value to reference pointed to by JSON pointer;
9417  // Note that if the JSON pointer is "" (i.e., points to the
9418  // whole value), function get_and_create returns a reference
9419  // to result itself. An assignment will then create a
9420  // primitive value.
9421  json_pointer(element.first).get_and_create(result) = element.second;
9422  }
9423 
9424  return result;
9425  }
9426 
9427  private:
9429  std::vector<std::string> reference_tokens {};
9430  };
9431 
9433  // JSON Pointer support //
9435 
9438 
9472  reference operator[](const json_pointer& ptr)
9473  {
9474  return ptr.get_unchecked(this);
9475  }
9499  const_reference operator[](const json_pointer& ptr) const
9500  {
9501  return ptr.get_unchecked(this);
9502  }
9524  reference at(const json_pointer& ptr)
9525  {
9526  return ptr.get_checked(this);
9527  }
9549  const_reference at(const json_pointer& ptr) const
9550  {
9551  return ptr.get_checked(this);
9552  }
9576  basic_json flatten() const
9577  {
9578  basic_json result(value_t::object);
9579  json_pointer::flatten("", *this, result);
9580  return result;
9581  }
9582 
9610  basic_json unflatten() const
9611  {
9612  return json_pointer::unflatten(*this);
9613  }
9616 
9618  // JSON Patch functions //
9620 
9623 
9660  basic_json patch(const basic_json& patch) const
9661  {
9662  // make a working copy to apply the patch to
9663  basic_json result = *this;
9665  // the valid JSON Patch operations
9666  enum class patch_operations {add, remove, replace, move, copy, test, invalid};
9667 
9668  const auto get_op = [](const std::string op)
9669  {
9670  if (op == "add")
9671  {
9672  return patch_operations::add;
9673  }
9674  if (op == "remove")
9675  {
9676  return patch_operations::remove;
9677  }
9678  if (op == "replace")
9679  {
9680  return patch_operations::replace;
9681  }
9682  if (op == "move")
9683  {
9684  return patch_operations::move;
9685  }
9686  if (op == "copy")
9687  {
9688  return patch_operations::copy;
9689  }
9690  if (op == "test")
9691  {
9692  return patch_operations::test;
9693  }
9694 
9695  return patch_operations::invalid;
9696  };
9697 
9698  // wrapper for "add" operation; add value at ptr
9699  const auto operation_add = [&result](json_pointer & ptr, basic_json val)
9700  {
9701  // adding to the root of the target document means replacing it
9702  if (ptr.is_root())
9703  {
9704  result = val;
9705  }
9706  else
9707  {
9708  // make sure the top element of the pointer exists
9709  json_pointer top_pointer = ptr.top();
9710  if (top_pointer != ptr)
9711  {
9712  basic_json& x = result.at(top_pointer);
9713  }
9714 
9715  // get reference to parent of JSON pointer ptr
9716  const auto last_path = ptr.pop_back();
9717  basic_json& parent = result[ptr];
9718 
9719  switch (parent.m_type)
9720  {
9721  case value_t::null:
9722  case value_t::object:
9723  {
9724  // use operator[] to add value
9725  parent[last_path] = val;
9726  break;
9727  }
9728 
9729  case value_t::array:
9730  {
9731  if (last_path == "-")
9732  {
9733  // special case: append to back
9734  parent.push_back(val);
9735  }
9736  else
9737  {
9738  const auto idx = std::stoi(last_path);
9739  if (static_cast<size_type>(idx) > parent.size())
9740  {
9741  // avoid undefined behavior
9742  throw std::out_of_range("array index " + std::to_string(idx) + " is out of range");
9743  }
9744  else
9745  {
9746  // default case: insert add offset
9747  parent.insert(parent.begin() + static_cast<difference_type>(idx), val);
9748  }
9749  }
9750  break;
9751  }
9752 
9753  default:
9754  {
9755  // if there exists a parent it cannot be primitive
9756  assert(false); // LCOV_EXCL_LINE
9757  }
9758  }
9759  }
9760  };
9761 
9762  // wrapper for "remove" operation; remove value at ptr
9763  const auto operation_remove = [&result](json_pointer & ptr)
9764  {
9765  // get reference to parent of JSON pointer ptr
9766  const auto last_path = ptr.pop_back();
9767  basic_json& parent = result.at(ptr);
9768 
9769  // remove child
9770  if (parent.is_object())
9771  {
9772  // perform range check
9773  auto it = parent.find(last_path);
9774  if (it != parent.end())
9775  {
9776  parent.erase(it);
9777  }
9778  else
9779  {
9780  throw std::out_of_range("key '" + last_path + "' not found");
9781  }
9782  }
9783  else if (parent.is_array())
9784  {
9785  // note erase performs range check
9786  parent.erase(static_cast<size_type>(std::stoi(last_path)));
9787  }
9788  };
9789 
9790  // type check
9791  if (not patch.is_array())
9792  {
9793  // a JSON patch must be an array of objects
9794  throw std::invalid_argument("JSON patch must be an array of objects");
9795  }
9796 
9797  // iterate and apply th eoperations
9798  for (const auto& val : patch)
9799  {
9800  // wrapper to get a value for an operation
9801  const auto get_value = [&val](const std::string & op,
9802  const std::string & member,
9803  bool string_type) -> basic_json&
9804  {
9805  // find value
9806  auto it = val.m_value.object->find(member);
9807 
9808  // context-sensitive error message
9809  const auto error_msg = (op == "op") ? "operation" : "operation '" + op + "'";
9810 
9811  // check if desired value is present
9812  if (it == val.m_value.object->end())
9813  {
9814  throw std::invalid_argument(error_msg + " must have member '" + member + "'");
9815  }
9816 
9817  // check if result is of type string
9818  if (string_type and not it->second.is_string())
9819  {
9820  throw std::invalid_argument(error_msg + " must have string member '" + member + "'");
9821  }
9822 
9823  // no error: return value
9824  return it->second;
9825  };
9826 
9827  // type check
9828  if (not val.is_object())
9829  {
9830  throw std::invalid_argument("JSON patch must be an array of objects");
9831  }
9832 
9833  // collect mandatory members
9834  const std::string op = get_value("op", "op", true);
9835  const std::string path = get_value(op, "path", true);
9836  json_pointer ptr(path);
9837 
9838  switch (get_op(op))
9839  {
9840  case patch_operations::add:
9841  {
9842  operation_add(ptr, get_value("add", "value", false));
9843  break;
9844  }
9845 
9846  case patch_operations::remove:
9847  {
9848  operation_remove(ptr);
9849  break;
9850  }
9851 
9852  case patch_operations::replace:
9853  {
9854  // the "path" location must exist - use at()
9855  result.at(ptr) = get_value("replace", "value", false);
9856  break;
9857  }
9858 
9859  case patch_operations::move:
9860  {
9861  const std::string from_path = get_value("move", "from", true);
9862  json_pointer from_ptr(from_path);
9863 
9864  // the "from" location must exist - use at()
9865  basic_json v = result.at(from_ptr);
9866 
9867  // The move operation is functionally identical to a
9868  // "remove" operation on the "from" location, followed
9869  // immediately by an "add" operation at the target
9870  // location with the value that was just removed.
9871  operation_remove(from_ptr);
9872  operation_add(ptr, v);
9873  break;
9874  }
9875 
9876  case patch_operations::copy:
9877  {
9878  const std::string from_path = get_value("copy", "from", true);;
9879  const json_pointer from_ptr(from_path);
9880 
9881  // the "from" location must exist - use at()
9882  result[ptr] = result.at(from_ptr);
9883  break;
9884  }
9885 
9886  case patch_operations::test:
9887  {
9888  bool success = false;
9889  try
9890  {
9891  // check if "value" matches the one at "path"
9892  // the "path" location must exist - use at()
9893  success = (result.at(ptr) == get_value("test", "value", false));
9894  }
9895  catch (std::out_of_range&)
9896  {
9897  // ignore out of range errors: success remains false
9898  }
9899 
9900  // throw an exception if test fails
9901  if (not success)
9902  {
9903  throw std::domain_error("unsuccessful: " + val.dump());
9904  }
9905 
9906  break;
9907  }
9908 
9909  case patch_operations::invalid:
9910  {
9911  // op must be "add", "remove", "replace", "move", "copy", or
9912  // "test"
9913  throw std::invalid_argument("operation value '" + op + "' is invalid");
9914  }
9915  }
9916  }
9917 
9918  return result;
9919  }
9920 
9953  static basic_json diff(const basic_json& source,
9954  const basic_json& target,
9955  std::string path = "") noexcept
9956  {
9957  // the patch
9958  basic_json result(value_t::array);
9959 
9960  // if the values are the same, return empty patch
9961  if (source == target)
9962  {
9963  return result;
9964  }
9965 
9966  if (source.type() != target.type())
9967  {
9968  // different types: replace value
9969  result.push_back(
9970  {
9971  {"op", "replace"},
9972  {"path", path},
9973  {"value", target}
9974  });
9975  }
9976  else
9977  {
9978  switch (source.type())
9979  {
9980  case value_t::array:
9981  {
9982  // first pass: traverse common elements
9983  size_t i = 0;
9984  while (i < source.size() and i < target.size())
9985  {
9986  // recursive call to compare array values at index i
9987  auto temp_diff = diff(source[i], target[i], path + "/" + std::to_string(i));
9988  result.insert(result.end(), temp_diff.begin(), temp_diff.end());
9989  ++i;
9990  }
9991 
9992  // i now reached the end of at least one array
9993  // in a second pass, traverse the remaining elements
9994 
9995  // remove my remaining elements
9996  while (i < source.size())
9997  {
9998  result.push_back(object(
9999  {
10000  {"op", "remove"},
10001  {"path", path + "/" + std::to_string(i)}
10002  }));
10003  ++i;
10004  }
10005 
10006  // add other remaining elements
10007  while (i < target.size())
10008  {
10009  result.push_back(
10010  {
10011  {"op", "add"},
10012  {"path", path + "/" + std::to_string(i)},
10013  {"value", target[i]}
10014  });
10015  ++i;
10016  }
10017 
10018  break;
10019  }
10020 
10021  case value_t::object:
10022  {
10023  // first pass: traverse this object's elements
10024  for (auto it = source.begin(); it != source.end(); ++it)
10025  {
10026  // escape the key name to be used in a JSON patch
10027  const auto key = json_pointer::escape(it.key());
10028 
10029  if (target.find(it.key()) != target.end())
10030  {
10031  // recursive call to compare object values at key it
10032  auto temp_diff = diff(it.value(), target[it.key()], path + "/" + key);
10033  result.insert(result.end(), temp_diff.begin(), temp_diff.end());
10034  }
10035  else
10036  {
10037  // found a key that is not in o -> remove it
10038  result.push_back(object(
10039  {
10040  {"op", "remove"},
10041  {"path", path + "/" + key}
10042  }));
10043  }
10044  }
10045 
10046  // second pass: traverse other object's elements
10047  for (auto it = target.begin(); it != target.end(); ++it)
10048  {
10049  if (source.find(it.key()) == source.end())
10050  {
10051  // found a key that is not in this -> add it
10052  const auto key = json_pointer::escape(it.key());
10053  result.push_back(
10054  {
10055  {"op", "add"},
10056  {"path", path + "/" + key},
10057  {"value", it.value()}
10058  });
10059  }
10060  }
10061 
10062  break;
10063  }
10064 
10065  default:
10066  {
10067  // both primitive type: replace value
10068  result.push_back(
10069  {
10070  {"op", "replace"},
10071  {"path", path},
10072  {"value", target}
10073  });
10074  break;
10075  }
10076  }
10077  }
10078 
10079  return result;
10080  }
10081 
10083 };
10084 
10085 
10087 // presets //
10089 
10098 using json = basic_json<>;
10099 }
10100 
10101 
10103 // nonmember support //
10105 
10106 // specialization of std::swap, and std::hash
10107 namespace std
10108 {
10114 template <>
10115 inline void swap(nlohmann::json& j1,
10116  nlohmann::json& j2) noexcept(
10117  is_nothrow_move_constructible<nlohmann::json>::value and
10118  is_nothrow_move_assignable<nlohmann::json>::value
10119  )
10120 {
10121  j1.swap(j2);
10122 }
10123 
10125 template <>
10126 struct hash<nlohmann::json>
10127 {
10133  std::size_t operator()(const nlohmann::json& j) const
10134  {
10135  // a naive hashing via the string representation
10136  const auto& h = hash<nlohmann::json::string_t>();
10137  return h(j.dump());
10138  }
10139 };
10140 }
10141 
10154 inline nlohmann::json operator "" _json(const char* s, std::size_t)
10155 {
10156  return nlohmann::json::parse(reinterpret_cast<const nlohmann::json::string_t::value_type*>(s));
10157 }
10158 
10164 inline nlohmann::json::json_pointer operator "" _json_pointer(const char* s, std::size_t)
10165 {
10166  return nlohmann::json::json_pointer(s);
10167 }
10168 
10169 // restore GCC/clang diagnostic settings
10170 #if defined(__clang__) || defined(__GNUC__) || defined(__GNUG__)
10171  #pragma GCC diagnostic pop
10172 #endif
10173 
10174 #endif
const_iterator(pointer object) noexcept
constructor for a given JSON instance
Definition: json.hpp:6495
friend bool operator<=(const_reference lhs, const_reference rhs) noexcept
comparison: less than or equal
Definition: json.hpp:5630
basic_json(const value_t value_type)
create an empty value with a given type
Definition: json.hpp:1032
basic_json(const array_t &val)
create an array (explicit)
Definition: json.hpp:1169
size_type count(typename object_t::key_type key) const
returns the number of occurrences of a key in a JSON object
Definition: json.hpp:4142
const_reference operator[](size_type idx) const
access specified array element
Definition: json.hpp:3334
reference value() const
return the value of an iterator
Definition: json.hpp:7135
json_reverse_iterator & operator--()
pre-decrement (–it)
Definition: json.hpp:7197
void clear() noexcept
clears the contents
Definition: json.hpp:4692
bool operator==(const const_iterator &other) const
comparison: equal
Definition: json.hpp:6785
json_reverse_iterator operator--(int)
post-decrement (it–)
Definition: json.hpp:7191
reference operator[](T *(&key)[n])
access specified object element
Definition: json.hpp:3466
friend std::istream & operator>>(std::istream &i, basic_json &j)
deserialize from stream
Definition: json.hpp:5843
constexpr bool is_number_float() const noexcept
return whether value is a floating-point number
Definition: json.hpp:2411
const_reverse_iterator rend() const noexcept
returns a const reverse iterator to one before the first
Definition: json.hpp:4369
iterator & operator+=(difference_type i)
add to iterator
Definition: json.hpp:7093
static basic_json object(std::initializer_list< basic_json > init=std::initializer_list< basic_json >())
explicitly create an object from an initializer list
Definition: json.hpp:1749
const_iterator operator-(difference_type i)
subtract from iterator
Definition: json.hpp:6911
BooleanType boolean_t
a type for a boolean
Definition: json.hpp:466
const_iterator cbegin() const noexcept
returns a const iterator to the first element
Definition: json.hpp:4223
reference operator+=(const typename object_t::value_type &val)
add an object to an object
Definition: json.hpp:4878
reference operator*() const
return a reference to the value pointed to by the iterator
Definition: json.hpp:7051
basic_json(const typename string_t::value_type *val)
create a string (explicit)
Definition: json.hpp:1262
reference operator[](difference_type n) const
access to successor
Definition: json.hpp:7233
iterator find(typename object_t::key_type key)
find an element in a JSON object
Definition: json.hpp:4094
friend bool operator!=(const_reference lhs, const_reference rhs) noexcept
comparison: not equal
Definition: json.hpp:5468
basic_json(const string_t &val)
create a string (explicit)
Definition: json.hpp:1238
void push_back(const basic_json &val)
add an object to an array
Definition: json.hpp:4804
void erase(const size_type idx)
remove element from a JSON array given an index
Definition: json.hpp:4048
ArrayType< basic_json, AllocatorType< basic_json >> array_t
a type for an array
Definition: json.hpp:393
reference front()
access the first element
Definition: json.hpp:3705
void swap(object_t &other)
exchanges the values
Definition: json.hpp:5224
json_reverse_iterator operator-(difference_type i) const
subtract from iterator
Definition: json.hpp:7219
const_iterator & operator+=(difference_type i)
add to iterator
Definition: json.hpp:6869
a class to store JSON values
Definition: json.hpp:187
basic_json(const int val) noexcept
create an integer number from an enum type (explicit)
Definition: json.hpp:1373
reference value() const
return the value of an iterator
Definition: json.hpp:7246
friend bool operator==(std::nullptr_t, const_reference v) noexcept
comparison: equal
Definition: json.hpp:5447
NumberIntegerType number_integer_t
a type for a number (integer)
Definition: json.hpp:537
iterator insert(const_iterator pos, size_type cnt, const basic_json &val)
inserts elements
Definition: json.hpp:5010
const_reference at(const typename object_t::key_type &key) const
access specified object element with bounds checking
Definition: json.hpp:3241
const_iterator operator+(difference_type i)
add to iterator
Definition: json.hpp:6903
constexpr bool is_object() const noexcept
return whether value is an object
Definition: json.hpp:2433
constexpr bool is_number_integer() const noexcept
return whether value is an integer number
Definition: json.hpp:2355
a mutable random access iterator for the basic_json class
Definition: json.hpp:7018
static basic_json parse(std::istream &&i, parser_callback_t cb=nullptr)
deserialize from stream
Definition: json.hpp:5805
const_iterator operator++(int)
post-increment (it++)
Definition: json.hpp:6711
const_iterator cend() const noexcept
returns a const iterator to one past the last element
Definition: json.hpp:4294
ObjectType< StringType, basic_json, std::less< StringType >, AllocatorType< std::pair< const StringType, basic_json >>> object_t
a type for an object
Definition: json.hpp:347
STL namespace.
NumberUnsignedType number_unsigned_t
a type for a number (unsigned)
Definition: json.hpp:609
typename std::allocator_traits< allocator_type >::const_pointer const_pointer
the type of an element const pointer
Definition: json.hpp:231
basic_json(const number_integer_t val) noexcept
create an integer number (explicit)
Definition: json.hpp:1344
static basic_json array(std::initializer_list< basic_json > init=std::initializer_list< basic_json >())
explicitly create an array from an initializer list
Definition: json.hpp:1709
static iteration_proxy< const_iterator > iterator_wrapper(const_reference cont)
wrapper to access iterator member functions in range-based for
Definition: json.hpp:4456
reference & operator=(basic_json other) noexcept( std::is_nothrow_move_constructible< value_t >::value and std::is_nothrow_move_assignable< value_t >::value and std::is_nothrow_move_constructible< json_value >::value and std::is_nothrow_move_assignable< json_value >::value )
copy assignment
Definition: json.hpp:2064
constexpr value_t type() const noexcept
return the type of the JSON value (explicit)
Definition: json.hpp:2195
typename basic_json::value_type value_type
the type of the values when the iterator is dereferenced
Definition: json.hpp:6481
json_reverse_iterator(const typename base_iterator::iterator_type &it) noexcept
create reverse iterator from iterator
Definition: json.hpp:7168
PointerType get_ptr() noexcept
get a pointer value (implicit)
Definition: json.hpp:2955
constexpr bool is_string() const noexcept
return whether value is a string
Definition: json.hpp:2477
reference back()
access the last element
Definition: json.hpp:3747
const value_type & const_reference
the type of an element const reference
Definition: json.hpp:218
typename basic_json::const_pointer pointer
defines a pointer to the type iterated over (value_type)
Definition: json.hpp:6485
void push_back(const typename object_t::value_type &val)
add an object to an object
Definition: json.hpp:4854
void push_back(std::initializer_list< basic_json > init)
add an object to an object
Definition: json.hpp:4909
json_pointer(const std::string &s="")
create JSON pointer
Definition: json.hpp:8901
static basic_json parse(const string_t &s, parser_callback_t cb=nullptr)
deserialize from string
Definition: json.hpp:5768
const_reference operator[](T *(&key)[n]) const
read-only access specified object element
Definition: json.hpp:3501
iterator insert(const_iterator pos, const_iterator first, const_iterator last)
inserts elements
Definition: json.hpp:5063
basic_json(std::nullptr_t) noexcept
create a null object (explicitly)
Definition: json.hpp:1084
basic_json(InputIT first, InputIT last)
construct a JSON container given an iterator range
Definition: json.hpp:1819
reference operator[](difference_type n) const
access to successor
Definition: json.hpp:7129
static allocator_type get_allocator()
returns the allocator associated with the container
Definition: json.hpp:248
const_reference operator[](const typename object_t::key_type &key) const
read-only access specified object element
Definition: json.hpp:3423
const_reference operator[](T *key) const
read-only access specified object element
Definition: json.hpp:3583
json_reverse_iterator operator+(difference_type i) const
add to iterator
Definition: json.hpp:7211
bool empty() const noexcept
checks whether the container is empty
Definition: json.hpp:4504
std::size_t size_type
a type to represent container sizes
Definition: json.hpp:223
object_t::key_type key() const
return the key of an object iterator
Definition: json.hpp:7239
const_iterator(const iterator &other) noexcept
copy constructor given a nonconst iterator
Definition: json.hpp:6523
basic_json(const CompatibleArrayType &val)
create an array (implicit)
Definition: json.hpp:1209
constexpr bool is_boolean() const noexcept
return whether value is a boolean
Definition: json.hpp:2296
const_reference at(size_type idx) const
access specified array element with bounds checking
Definition: json.hpp:3145
basic_json(size_type cnt, const basic_json &val)
construct an array with count copies of given value
Definition: json.hpp:1773
std::reverse_iterator< Base > base_iterator
shortcut to the reverse iterator adaptor
Definition: json.hpp:7163
const_reverse_iterator crbegin() const noexcept
returns a const reverse iterator to the last element
Definition: json.hpp:4398
iterator insert(const_iterator pos, std::initializer_list< basic_json > ilist)
inserts elements
Definition: json.hpp:5121
typename std::allocator_traits< allocator_type >::pointer pointer
the type of an element pointer
Definition: json.hpp:229
iterator insert(const_iterator pos, const basic_json &val)
inserts element
Definition: json.hpp:4954
friend bool operator>=(const_reference lhs, const_reference rhs) noexcept
comparison: greater than or equal
Definition: json.hpp:5674
friend bool operator<(const_reference lhs, const_reference rhs) noexcept
comparison: less than
Definition: json.hpp:5529
iterator & operator++()
pre-increment (++it)
Definition: json.hpp:7071
bool operator<(const const_iterator &other) const
comparison: smaller
Definition: json.hpp:6821
iterator operator++(int)
post-increment (it++)
Definition: json.hpp:7063
basic_json(basic_json &&other) noexcept
move constructor
Definition: json.hpp:2032
const_iterator operator--(int)
post-decrement (it–)
Definition: json.hpp:6748
reference at(const typename object_t::key_type &key)
access specified object element with bounds checking
Definition: json.hpp:3193
iterator & operator=(iterator other) noexcept( std::is_nothrow_move_constructible< pointer >::value and std::is_nothrow_move_assignable< pointer >::value and std::is_nothrow_move_constructible< internal_iterator >::value and std::is_nothrow_move_assignable< internal_iterator >::value )
copy assignment
Definition: json.hpp:7039
object (unordered set of name/value pairs)
size_type max_size() const noexcept
returns the maximum possible number of elements
Definition: json.hpp:4633
~basic_json()
destructor
Definition: json.hpp:2092
iterator operator--(int)
post-decrement (it–)
Definition: json.hpp:7078
iterator operator-(difference_type i)
subtract from iterator
Definition: json.hpp:7115
const_iterator & operator--()
pre-decrement (–it)
Definition: json.hpp:6756
string_t dump(const int indent=-1) const
serialization
Definition: json.hpp:2161
basic_json value_type
the type of elements in a basic_json container
Definition: json.hpp:213
std::function< bool(int depth, parse_event_t event, basic_json &parsed)> parser_callback_t
per-element parser callback type
Definition: json.hpp:983
AllocatorType< basic_json > allocator_type
the allocator type
Definition: json.hpp:226
StringType string_t
a type for a string
Definition: json.hpp:440
reference operator+=(const basic_json &val)
add an object to an array
Definition: json.hpp:4828
reference operator+=(std::initializer_list< basic_json > init)
add an object to an object
Definition: json.hpp:4926
difference_type operator-(const const_iterator &other) const
return difference
Definition: json.hpp:6919
value_type & reference
the type of an element reference
Definition: json.hpp:216
const_reverse_iterator rbegin() const noexcept
returns a const reverse iterator to the last element
Definition: json.hpp:4332
friend std::ostream & operator>>(const basic_json &j, std::ostream &o)
serialize to stream
Definition: json.hpp:5729
constexpr bool is_discarded() const noexcept
return whether value is discarded
Definition: json.hpp:2504
const_iterator begin() const noexcept
returns a const iterator to the first element
Definition: json.hpp:4193
difference_type operator-(const iterator &other) const
return difference
Definition: json.hpp:7123
constexpr bool is_array() const noexcept
return whether value is an array
Definition: json.hpp:2455
iterator(const iterator &other) noexcept
copy constructor
Definition: json.hpp:7034
namespace for Niels Lohmann
Definition: json.hpp:67
typename basic_json::difference_type difference_type
a type to represent differences between iterators
Definition: json.hpp:6483
void swap(string_t &other)
exchanges the values
Definition: json.hpp:5258
basic_json(const CompatibleNumberIntegerType val) noexcept
create an integer number (implicit)
Definition: json.hpp:1410
const_reference front() const
access the first element
Definition: json.hpp:3713
bool operator>(const const_iterator &other) const
comparison: greater than
Definition: json.hpp:6857
constexpr const PointerType get_ptr() const noexcept
get a pointer value (implicit)
Definition: json.hpp:2970
pointer operator->() const
dereference the iterator
Definition: json.hpp:6676
NumberFloatType number_float_t
a type for a number (floating-point)
Definition: json.hpp:677
const_reverse_iterator crend() const noexcept
returns a const reverse iterator to one before the first
Definition: json.hpp:4427
void swap(reference other) noexcept( std::is_nothrow_move_constructible< value_t >::value and std::is_nothrow_move_assignable< value_t >::value and std::is_nothrow_move_constructible< json_value >::value and std::is_nothrow_move_assignable< json_value >::value )
exchanges the values
Definition: json.hpp:5159
value_t
the JSON type enumeration
Definition: json.hpp:696
reverse_iterator rbegin() noexcept
returns an iterator to the reverse-beginning
Definition: json.hpp:4324
constexpr bool is_null() const noexcept
return whether value is null
Definition: json.hpp:2274
std::ptrdiff_t difference_type
a type to represent differences between iterators
Definition: json.hpp:221
ValueType get() const
get a value (explicit)
Definition: json.hpp:2871
void swap(array_t &other)
exchanges the values
Definition: json.hpp:5190
InteratorType erase(InteratorType first, InteratorType last)
remove elements given an iterator range
Definition: json.hpp:3923
ValueType value(const typename object_t::key_type &key, ValueType default_value) const
access specified object element with default value
Definition: json.hpp:3650
typename Base::reference reference
the reference type for the pointed-to element
Definition: json.hpp:7165
const_reference back() const
access the last element
Definition: json.hpp:3757
void push_back(basic_json &&val)
add an object to an array
Definition: json.hpp:4768
array (ordered collection of values)
constexpr bool is_number_unsigned() const noexcept
return whether value is an unsigned integer number
Definition: json.hpp:2383
json_reverse_iterator & operator++()
pre-increment (++it)
Definition: json.hpp:7184
static basic_json parse(std::istream &i, parser_callback_t cb=nullptr)
deserialize from stream
Definition: json.hpp:5797
friend bool operator==(const_reference lhs, const_reference rhs) noexcept
comparison: equal
Definition: json.hpp:5339
string_t value(const typename object_t::key_type &key, const char *default_value) const
overload for a default value of type const char*
Definition: json.hpp:3676
ReferenceType get_ref() const
get a reference value (implicit)
Definition: json.hpp:3021
basic_json(const CompatibleNumberUnsignedType val) noexcept
create an unsigned number (implicit)
Definition: json.hpp:1469
reference operator*() const
return a reference to the value pointed to by the iterator
Definition: json.hpp:6636
friend bool operator<(const value_t lhs, const value_t rhs) noexcept
comparison operator for JSON types
Definition: json.hpp:5292
basic_json(const number_float_t val) noexcept
create a floating-point number (explicit)
Definition: json.hpp:1498
friend bool operator!=(const_reference v, std::nullptr_t) noexcept
comparison: not equal
Definition: json.hpp:5491
iterator operator+(difference_type i)
add to iterator
Definition: json.hpp:7107
basic_json(const CompatibleNumberFloatType val) noexcept
create an floating-point number (implicit)
Definition: json.hpp:1544
bool operator<=(const const_iterator &other) const
comparison: less than or equal
Definition: json.hpp:6851
InteratorType erase(InteratorType pos)
remove element given an iterator
Definition: json.hpp:3815
basic_json(std::initializer_list< basic_json > init, bool type_deduction=true, value_t manual_type=value_t::array)
create a container (array or object) from an initializer list
Definition: json.hpp:1617
iterator(pointer object) noexcept
constructor for a given JSON instance
Definition: json.hpp:7029
friend bool operator!=(std::nullptr_t, const_reference v) noexcept
comparison: not equal
Definition: json.hpp:5500
constexpr bool is_primitive() const noexcept
return whether type is primitive
Definition: json.hpp:2225
const_iterator & operator++()
pre-increment (++it)
Definition: json.hpp:6719
pointer operator->() const
dereference the iterator
Definition: json.hpp:7057
reference value() const
return the value of an iterator
Definition: json.hpp:6994
constexpr bool is_structured() const noexcept
return whether type is structured
Definition: json.hpp:2252
std::bidirectional_iterator_tag iterator_category
the category of the iterator
Definition: json.hpp:6489
basic_json(boolean_t val) noexcept
create a boolean (explicit)
Definition: json.hpp:1311
iterator end() noexcept
returns an iterator to one past the last element
Definition: json.hpp:4254
reverse_iterator rend() noexcept
returns an iterator to the reverse-end
Definition: json.hpp:4361
difference_type operator-(const json_reverse_iterator &other) const
return difference
Definition: json.hpp:7227
const_iterator find(typename object_t::key_type key) const
find an element in a JSON object
Definition: json.hpp:4111
iterator begin() noexcept
returns an iterator to the first element
Definition: json.hpp:4183
basic_json(const CompatibleObjectType &val)
create an object (implicit)
Definition: json.hpp:1142
const_iterator end() const noexcept
returns a const iterator to one past the last element
Definition: json.hpp:4264
friend bool operator>(const_reference lhs, const_reference rhs) noexcept
comparison: greater than
Definition: json.hpp:5652
bool operator>=(const const_iterator &other) const
comparison: greater than or equal
Definition: json.hpp:6863
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:6556
size_type erase(const typename object_t::key_type &key)
remove element from a JSON object given a key
Definition: json.hpp:4010
reference operator[](const typename object_t::key_type &key)
access specified object element
Definition: json.hpp:3375
object_t::key_type key() const
return the key of an object iterator
Definition: json.hpp:6979
reference operator+=(basic_json &&val)
add an object to an array
Definition: json.hpp:4794
reference operator[](difference_type n) const
access to successor
Definition: json.hpp:6943
a const random access iterator for the basic_json class
Definition: json.hpp:6474
constexpr bool is_number() const noexcept
return whether value is a number
Definition: json.hpp:2326
a template for a reverse iterator class
Definition: json.hpp:202
basic_json(std::istream &i, parser_callback_t cb=nullptr)
construct a JSON value given an input stream
Definition: json.hpp:1926
typename basic_json::const_reference reference
defines a reference to the type iterated over (value_type)
Definition: json.hpp:6487
json_reverse_iterator operator++(int)
post-increment (it++)
Definition: json.hpp:7178
friend bool operator==(const_reference v, std::nullptr_t) noexcept
comparison: equal
Definition: json.hpp:5438
reference operator[](size_type idx)
access specified array element
Definition: json.hpp:3288
bool operator!=(const const_iterator &other) const
comparison: not equal
Definition: json.hpp:6815
json_reverse_iterator & operator+=(difference_type i)
add to iterator
Definition: json.hpp:7204
reference at(size_type idx)
access specified array element with bounds checking
Definition: json.hpp:3101
size_type size() const noexcept
returns the number of elements
Definition: json.hpp:4567
static iteration_proxy< iterator > iterator_wrapper(reference cont)
wrapper to access iterator member functions in range-based for
Definition: json.hpp:4448
iterator & operator-=(difference_type i)
subtract from iterator
Definition: json.hpp:7100
basic_json(const object_t &val)
create an object (explicit)
Definition: json.hpp:1107
basic_json(const number_unsigned_t val) noexcept
create an unsigned integer number (explicit)
Definition: json.hpp:1438
friend std::istream & operator<<(basic_json &j, std::istream &i)
deserialize from stream
Definition: json.hpp:5833
json_reverse_iterator(const base_iterator &it) noexcept
create reverse iterator from base class
Definition: json.hpp:7173
friend std::ostream & operator<<(std::ostream &o, const basic_json &j)
serialize to stream
Definition: json.hpp:5711
const_iterator(const const_iterator &other) noexcept
copy constructor
Definition: json.hpp:6551
iterator & operator--()
pre-decrement (–it)
Definition: json.hpp:7086
iterator insert(const_iterator pos, basic_json &&val)
inserts element
Definition: json.hpp:4981
ReferenceType get_ref()
get a reference value (implicit)
Definition: json.hpp:3006
const_iterator & operator-=(difference_type i)
subtract from iterator
Definition: json.hpp:6897
basic_json(const CompatibleStringType &val)
create a string (implicit)
Definition: json.hpp:1293
basic_json(const basic_json &other)
copy constructor
Definition: json.hpp:1957
reference operator[](T *key)
access specified object element
Definition: json.hpp:3534
parse_event_t
JSON callback events.
Definition: json.hpp:918