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 
3632  {
3633  return ptr.get_unchecked(this);
3634  }
3635 
3659  {
3660  return ptr.get_unchecked(this);
3661  }
3662 
3684  {
3685  return ptr.get_checked(this);
3686  }
3687 
3708  const_reference at(const json_pointer& ptr) const
3709  {
3710  return ptr.get_checked(this);
3711  }
3712 
3761  template <class ValueType, typename
3762  std::enable_if<
3763  std::is_convertible<basic_json_t, ValueType>::value
3764  , int>::type = 0>
3765  ValueType value(const typename object_t::key_type& key, ValueType default_value) const
3766  {
3767  // at only works for objects
3768  if (is_object())
3769  {
3770  // if key is found, return value and given default value otherwise
3771  const auto it = find(key);
3772  if (it != end())
3773  {
3774  return *it;
3775  }
3776  else
3777  {
3778  return default_value;
3779  }
3780  }
3781  else
3782  {
3783  throw std::domain_error("cannot use value() with " + type_name());
3784  }
3785  }
3786 
3791  string_t value(const typename object_t::key_type& key, const char* default_value) const
3792  {
3793  return value(key, string_t(default_value));
3794  }
3795 
3821  {
3822  return *begin();
3823  }
3824 
3829  {
3830  return *cbegin();
3831  }
3832 
3863  {
3864  auto tmp = end();
3865  --tmp;
3866  return *tmp;
3867  }
3868 
3873  {
3874  auto tmp = cend();
3875  --tmp;
3876  return *tmp;
3877  }
3878 
3924  template <class InteratorType, typename
3925  std::enable_if<
3926  std::is_same<InteratorType, typename basic_json_t::iterator>::value or
3927  std::is_same<InteratorType, typename basic_json_t::const_iterator>::value
3928  , int>::type
3929  = 0>
3930  InteratorType erase(InteratorType pos)
3931  {
3932  // make sure iterator fits the current value
3933  if (this != pos.m_object)
3934  {
3935  throw std::domain_error("iterator does not fit current value");
3936  }
3937 
3938  InteratorType result = end();
3939 
3940  switch (m_type)
3941  {
3942  case value_t::boolean:
3943  case value_t::number_float:
3944  case value_t::number_integer:
3945  case value_t::number_unsigned:
3946  case value_t::string:
3947  {
3948  if (not pos.m_it.primitive_iterator.is_begin())
3949  {
3950  throw std::out_of_range("iterator out of range");
3951  }
3952 
3953  if (is_string())
3954  {
3955  delete m_value.string;
3956  m_value.string = nullptr;
3957  }
3958 
3959  m_type = value_t::null;
3960  break;
3961  }
3962 
3963  case value_t::object:
3964  {
3965  assert(m_value.object != nullptr);
3966  result.m_it.object_iterator = m_value.object->erase(pos.m_it.object_iterator);
3967  break;
3968  }
3969 
3970  case value_t::array:
3971  {
3972  assert(m_value.array != nullptr);
3973  result.m_it.array_iterator = m_value.array->erase(pos.m_it.array_iterator);
3974  break;
3975  }
3976 
3977  default:
3978  {
3979  throw std::domain_error("cannot use erase() with " + type_name());
3980  }
3981  }
3982 
3983  return result;
3984  }
3985 
4032  template <class InteratorType, typename
4033  std::enable_if<
4034  std::is_same<InteratorType, typename basic_json_t::iterator>::value or
4035  std::is_same<InteratorType, typename basic_json_t::const_iterator>::value
4036  , int>::type
4037  = 0>
4038  InteratorType erase(InteratorType first, InteratorType last)
4039  {
4040  // make sure iterator fits the current value
4041  if (this != first.m_object or this != last.m_object)
4042  {
4043  throw std::domain_error("iterators do not fit current value");
4044  }
4045 
4046  InteratorType result = end();
4047 
4048  switch (m_type)
4049  {
4050  case value_t::boolean:
4051  case value_t::number_float:
4052  case value_t::number_integer:
4053  case value_t::number_unsigned:
4054  case value_t::string:
4055  {
4056  if (not first.m_it.primitive_iterator.is_begin() or not last.m_it.primitive_iterator.is_end())
4057  {
4058  throw std::out_of_range("iterators out of range");
4059  }
4060 
4061  if (is_string())
4062  {
4063  delete m_value.string;
4064  m_value.string = nullptr;
4065  }
4066 
4067  m_type = value_t::null;
4068  break;
4069  }
4070 
4071  case value_t::object:
4072  {
4073  assert(m_value.object != nullptr);
4074  result.m_it.object_iterator = m_value.object->erase(first.m_it.object_iterator,
4075  last.m_it.object_iterator);
4076  break;
4077  }
4078 
4079  case value_t::array:
4080  {
4081  assert(m_value.array != nullptr);
4082  result.m_it.array_iterator = m_value.array->erase(first.m_it.array_iterator,
4083  last.m_it.array_iterator);
4084  break;
4085  }
4086 
4087  default:
4088  {
4089  throw std::domain_error("cannot use erase() with " + type_name());
4090  }
4091  }
4092 
4093  return result;
4094  }
4095 
4125  size_type erase(const typename object_t::key_type& key)
4126  {
4127  // this erase only works for objects
4128  if (is_object())
4129  {
4130  assert(m_value.object != nullptr);
4131  return m_value.object->erase(key);
4132  }
4133  else
4134  {
4135  throw std::domain_error("cannot use erase() with " + type_name());
4136  }
4137  }
4138 
4163  void erase(const size_type idx)
4164  {
4165  // this erase only works for arrays
4166  if (is_array())
4167  {
4168  if (idx >= size())
4169  {
4170  throw std::out_of_range("index out of range");
4171  }
4172 
4173  assert(m_value.array != nullptr);
4174  m_value.array->erase(m_value.array->begin() + static_cast<difference_type>(idx));
4175  }
4176  else
4177  {
4178  throw std::domain_error("cannot use erase() with " + type_name());
4179  }
4180  }
4181 
4183 
4184 
4186  // lookup //
4188 
4191 
4209  iterator find(typename object_t::key_type key)
4210  {
4211  auto result = end();
4212 
4213  if (is_object())
4214  {
4215  assert(m_value.object != nullptr);
4216  result.m_it.object_iterator = m_value.object->find(key);
4217  }
4218 
4219  return result;
4220  }
4221 
4226  const_iterator find(typename object_t::key_type key) const
4227  {
4228  auto result = cend();
4229 
4230  if (is_object())
4231  {
4232  assert(m_value.object != nullptr);
4233  result.m_it.object_iterator = m_value.object->find(key);
4234  }
4235 
4236  return result;
4237  }
4238 
4257  size_type count(typename object_t::key_type key) const
4258  {
4259  // return 0 for all nonobject types
4260  assert(not is_object() or m_value.object != nullptr);
4261  return is_object() ? m_value.object->count(key) : 0;
4262  }
4263 
4265 
4266 
4268  // iterators //
4270 
4273 
4298  iterator begin() noexcept
4299  {
4300  iterator result(this);
4301  result.set_begin();
4302  return result;
4303  }
4304 
4308  const_iterator begin() const noexcept
4309  {
4310  return cbegin();
4311  }
4312 
4338  const_iterator cbegin() const noexcept
4339  {
4340  const_iterator result(this);
4341  result.set_begin();
4342  return result;
4343  }
4344 
4369  iterator end() noexcept
4370  {
4371  iterator result(this);
4372  result.set_end();
4373  return result;
4374  }
4375 
4379  const_iterator end() const noexcept
4380  {
4381  return cend();
4382  }
4383 
4409  const_iterator cend() const noexcept
4410  {
4411  const_iterator result(this);
4412  result.set_end();
4413  return result;
4414  }
4415 
4440  {
4441  return reverse_iterator(end());
4442  }
4443 
4448  {
4449  return crbegin();
4450  }
4451 
4477  {
4478  return reverse_iterator(begin());
4479  }
4480 
4484  const_reverse_iterator rend() const noexcept
4485  {
4486  return crend();
4487  }
4488 
4514  {
4515  return const_reverse_iterator(cend());
4516  }
4517 
4543  {
4544  return const_reverse_iterator(cbegin());
4545  }
4546 
4547  private:
4548  // forward declaration
4549  template<typename IteratorType> class iteration_proxy;
4550 
4551  public:
4563  static iteration_proxy<iterator> iterator_wrapper(reference cont)
4564  {
4565  return iteration_proxy<iterator>(cont);
4566  }
4567 
4571  static iteration_proxy<const_iterator> iterator_wrapper(const_reference cont)
4572  {
4573  return iteration_proxy<const_iterator>(cont);
4574  }
4575 
4577 
4578 
4580  // capacity //
4582 
4585 
4619  bool empty() const noexcept
4620  {
4621  switch (m_type)
4622  {
4623  case value_t::null:
4624  {
4625  // null values are empty
4626  return true;
4627  }
4628 
4629  case value_t::array:
4630  {
4631  assert(m_value.array != nullptr);
4632  return m_value.array->empty();
4633  }
4634 
4635  case value_t::object:
4636  {
4637  assert(m_value.object != nullptr);
4638  return m_value.object->empty();
4639  }
4640 
4641  default:
4642  {
4643  // all other types are nonempty
4644  return false;
4645  }
4646  }
4647  }
4648 
4682  size_type size() const noexcept
4683  {
4684  switch (m_type)
4685  {
4686  case value_t::null:
4687  {
4688  // null values are empty
4689  return 0;
4690  }
4691 
4692  case value_t::array:
4693  {
4694  assert(m_value.array != nullptr);
4695  return m_value.array->size();
4696  }
4697 
4698  case value_t::object:
4699  {
4700  assert(m_value.object != nullptr);
4701  return m_value.object->size();
4702  }
4703 
4704  default:
4705  {
4706  // all other types have size 1
4707  return 1;
4708  }
4709  }
4710  }
4711 
4748  size_type max_size() const noexcept
4749  {
4750  switch (m_type)
4751  {
4752  case value_t::array:
4753  {
4754  assert(m_value.array != nullptr);
4755  return m_value.array->max_size();
4756  }
4757 
4758  case value_t::object:
4759  {
4760  assert(m_value.object != nullptr);
4761  return m_value.object->max_size();
4762  }
4763 
4764  default:
4765  {
4766  // all other types have max_size() == size()
4767  return size();
4768  }
4769  }
4770  }
4771 
4773 
4774 
4776  // modifiers //
4778 
4781 
4807  void clear() noexcept
4808  {
4809  switch (m_type)
4810  {
4811  case value_t::number_integer:
4812  {
4813  m_value.number_integer = 0;
4814  break;
4815  }
4816 
4817  case value_t::number_unsigned:
4818  {
4819  m_value.number_unsigned = 0;
4820  break;
4821  }
4822 
4823  case value_t::number_float:
4824  {
4825  m_value.number_float = 0.0;
4826  break;
4827  }
4828 
4829  case value_t::boolean:
4830  {
4831  m_value.boolean = false;
4832  break;
4833  }
4834 
4835  case value_t::string:
4836  {
4837  assert(m_value.string != nullptr);
4838  m_value.string->clear();
4839  break;
4840  }
4841 
4842  case value_t::array:
4843  {
4844  assert(m_value.array != nullptr);
4845  m_value.array->clear();
4846  break;
4847  }
4848 
4849  case value_t::object:
4850  {
4851  assert(m_value.object != nullptr);
4852  m_value.object->clear();
4853  break;
4854  }
4855 
4856  default:
4857  {
4858  break;
4859  }
4860  }
4861  }
4862 
4883  void push_back(basic_json&& val)
4884  {
4885  // push_back only works for null objects or arrays
4886  if (not(is_null() or is_array()))
4887  {
4888  throw std::domain_error("cannot use push_back() with " + type_name());
4889  }
4890 
4891  // transform null object into an array
4892  if (is_null())
4893  {
4894  m_type = value_t::array;
4895  m_value = value_t::array;
4896  }
4897 
4898  // add element to array (move semantics)
4899  assert(m_value.array != nullptr);
4900  m_value.array->push_back(std::move(val));
4901  // invalidate object
4902  val.m_type = value_t::null;
4903  }
4904 
4909  reference operator+=(basic_json&& val)
4910  {
4911  push_back(std::move(val));
4912  return *this;
4913  }
4914 
4919  void push_back(const basic_json& val)
4920  {
4921  // push_back only works for null objects or arrays
4922  if (not(is_null() or is_array()))
4923  {
4924  throw std::domain_error("cannot use push_back() with " + type_name());
4925  }
4926 
4927  // transform null object into an array
4928  if (is_null())
4929  {
4930  m_type = value_t::array;
4931  m_value = value_t::array;
4932  }
4933 
4934  // add element to array
4935  assert(m_value.array != nullptr);
4936  m_value.array->push_back(val);
4937  }
4938 
4943  reference operator+=(const basic_json& val)
4944  {
4945  push_back(val);
4946  return *this;
4947  }
4948 
4969  void push_back(const typename object_t::value_type& val)
4970  {
4971  // push_back only works for null objects or objects
4972  if (not(is_null() or is_object()))
4973  {
4974  throw std::domain_error("cannot use push_back() with " + type_name());
4975  }
4976 
4977  // transform null object into an object
4978  if (is_null())
4979  {
4980  m_type = value_t::object;
4981  m_value = value_t::object;
4982  }
4983 
4984  // add element to array
4985  assert(m_value.object != nullptr);
4986  m_value.object->insert(val);
4987  }
4988 
4993  reference operator+=(const typename object_t::value_type& val)
4994  {
4995  push_back(val);
4996  return operator[](val.first);
4997  }
4998 
5021  iterator insert(const_iterator pos, const basic_json& val)
5022  {
5023  // insert only works for arrays
5024  if (is_array())
5025  {
5026  // check if iterator pos fits to this JSON value
5027  if (pos.m_object != this)
5028  {
5029  throw std::domain_error("iterator does not fit current value");
5030  }
5031 
5032  // insert to array and return iterator
5033  iterator result(this);
5034  assert(m_value.array != nullptr);
5035  result.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator, val);
5036  return result;
5037  }
5038  else
5039  {
5040  throw std::domain_error("cannot use insert() with " + type_name());
5041  }
5042  }
5043 
5048  iterator insert(const_iterator pos, basic_json&& val)
5049  {
5050  return insert(pos, val);
5051  }
5052 
5077  iterator insert(const_iterator pos, size_type cnt, const basic_json& val)
5078  {
5079  // insert only works for arrays
5080  if (is_array())
5081  {
5082  // check if iterator pos fits to this JSON value
5083  if (pos.m_object != this)
5084  {
5085  throw std::domain_error("iterator does not fit current value");
5086  }
5087 
5088  // insert to array and return iterator
5089  iterator result(this);
5090  assert(m_value.array != nullptr);
5091  result.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator, cnt, val);
5092  return result;
5093  }
5094  else
5095  {
5096  throw std::domain_error("cannot use insert() with " + type_name());
5097  }
5098  }
5099 
5131  {
5132  // insert only works for arrays
5133  if (not is_array())
5134  {
5135  throw std::domain_error("cannot use insert() with " + type_name());
5136  }
5137 
5138  // check if iterator pos fits to this JSON value
5139  if (pos.m_object != this)
5140  {
5141  throw std::domain_error("iterator does not fit current value");
5142  }
5143 
5144  if (first.m_object != last.m_object)
5145  {
5146  throw std::domain_error("iterators do not fit");
5147  }
5148 
5149  if (first.m_object == this or last.m_object == this)
5150  {
5151  throw std::domain_error("passed iterators may not belong to container");
5152  }
5153 
5154  // insert to array and return iterator
5155  iterator result(this);
5156  assert(m_value.array != nullptr);
5157  result.m_it.array_iterator = m_value.array->insert(
5158  pos.m_it.array_iterator,
5159  first.m_it.array_iterator,
5160  last.m_it.array_iterator);
5161  return result;
5162  }
5163 
5188  iterator insert(const_iterator pos, std::initializer_list<basic_json> ilist)
5189  {
5190  // insert only works for arrays
5191  if (not is_array())
5192  {
5193  throw std::domain_error("cannot use insert() with " + type_name());
5194  }
5195 
5196  // check if iterator pos fits to this JSON value
5197  if (pos.m_object != this)
5198  {
5199  throw std::domain_error("iterator does not fit current value");
5200  }
5201 
5202  // insert to array and return iterator
5203  iterator result(this);
5204  assert(m_value.array != nullptr);
5205  result.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator, ilist);
5206  return result;
5207  }
5208 
5226  void swap(reference other) noexcept (
5227  std::is_nothrow_move_constructible<value_t>::value and
5228  std::is_nothrow_move_assignable<value_t>::value and
5229  std::is_nothrow_move_constructible<json_value>::value and
5230  std::is_nothrow_move_assignable<json_value>::value
5231  )
5232  {
5233  std::swap(m_type, other.m_type);
5234  std::swap(m_value, other.m_value);
5235  }
5236 
5257  void swap(array_t& other)
5258  {
5259  // swap only works for arrays
5260  if (is_array())
5261  {
5262  assert(m_value.array != nullptr);
5263  std::swap(*(m_value.array), other);
5264  }
5265  else
5266  {
5267  throw std::domain_error("cannot use swap() with " + type_name());
5268  }
5269  }
5270 
5291  void swap(object_t& other)
5292  {
5293  // swap only works for objects
5294  if (is_object())
5295  {
5296  assert(m_value.object != nullptr);
5297  std::swap(*(m_value.object), other);
5298  }
5299  else
5300  {
5301  throw std::domain_error("cannot use swap() with " + type_name());
5302  }
5303  }
5304 
5325  void swap(string_t& other)
5326  {
5327  // swap only works for strings
5328  if (is_string())
5329  {
5330  assert(m_value.string != nullptr);
5331  std::swap(*(m_value.string), other);
5332  }
5333  else
5334  {
5335  throw std::domain_error("cannot use swap() with " + type_name());
5336  }
5337  }
5338 
5340 
5341 
5343  // lexicographical comparison operators //
5345 
5348 
5349  private:
5359  friend bool operator<(const value_t lhs, const value_t rhs) noexcept
5360  {
5361  static constexpr std::array<uint8_t, 8> order = {{
5362  0, // null
5363  3, // object
5364  4, // array
5365  5, // string
5366  1, // boolean
5367  2, // integer
5368  2, // unsigned
5369  2, // float
5370  }
5371  };
5372 
5373  // discarded values are not comparable
5374  if (lhs == value_t::discarded or rhs == value_t::discarded)
5375  {
5376  return false;
5377  }
5378 
5379  return order[static_cast<std::size_t>(lhs)] < order[static_cast<std::size_t>(rhs)];
5380  }
5381 
5382  public:
5406  friend bool operator==(const_reference lhs, const_reference rhs) noexcept
5407  {
5408  const auto lhs_type = lhs.type();
5409  const auto rhs_type = rhs.type();
5410 
5411  if (lhs_type == rhs_type)
5412  {
5413  switch (lhs_type)
5414  {
5415  case value_t::array:
5416  {
5417  assert(lhs.m_value.array != nullptr);
5418  assert(rhs.m_value.array != nullptr);
5419  return *lhs.m_value.array == *rhs.m_value.array;
5420  }
5421  case value_t::object:
5422  {
5423  assert(lhs.m_value.object != nullptr);
5424  assert(rhs.m_value.object != nullptr);
5425  return *lhs.m_value.object == *rhs.m_value.object;
5426  }
5427  case value_t::null:
5428  {
5429  return true;
5430  }
5431  case value_t::string:
5432  {
5433  assert(lhs.m_value.string != nullptr);
5434  assert(rhs.m_value.string != nullptr);
5435  return *lhs.m_value.string == *rhs.m_value.string;
5436  }
5437  case value_t::boolean:
5438  {
5439  return lhs.m_value.boolean == rhs.m_value.boolean;
5440  }
5441  case value_t::number_integer:
5442  {
5443  return lhs.m_value.number_integer == rhs.m_value.number_integer;
5444  }
5445  case value_t::number_unsigned:
5446  {
5447  return lhs.m_value.number_unsigned == rhs.m_value.number_unsigned;
5448  }
5449  case value_t::number_float:
5450  {
5451  return lhs.m_value.number_float == rhs.m_value.number_float;
5452  }
5453  default:
5454  {
5455  return false;
5456  }
5457  }
5458  }
5459  else if (lhs_type == value_t::number_integer and rhs_type == value_t::number_float)
5460  {
5461  return static_cast<number_float_t>(lhs.m_value.number_integer) == rhs.m_value.number_float;
5462  }
5463  else if (lhs_type == value_t::number_float and rhs_type == value_t::number_integer)
5464  {
5465  return lhs.m_value.number_float == static_cast<number_float_t>(rhs.m_value.number_integer);
5466  }
5467  else if (lhs_type == value_t::number_unsigned and rhs_type == value_t::number_float)
5468  {
5469  return static_cast<number_float_t>(lhs.m_value.number_unsigned) == rhs.m_value.number_float;
5470  }
5471  else if (lhs_type == value_t::number_float and rhs_type == value_t::number_unsigned)
5472  {
5473  return lhs.m_value.number_float == static_cast<number_float_t>(rhs.m_value.number_unsigned);
5474  }
5475  else if (lhs_type == value_t::number_unsigned and rhs_type == value_t::number_integer)
5476  {
5477  return static_cast<number_integer_t>(lhs.m_value.number_unsigned) == rhs.m_value.number_integer;
5478  }
5479  else if (lhs_type == value_t::number_integer and rhs_type == value_t::number_unsigned)
5480  {
5481  return lhs.m_value.number_integer == static_cast<number_integer_t>(rhs.m_value.number_unsigned);
5482  }
5483 
5484  return false;
5485  }
5486 
5505  friend bool operator==(const_reference v, std::nullptr_t) noexcept
5506  {
5507  return v.is_null();
5508  }
5509 
5514  friend bool operator==(std::nullptr_t, const_reference v) noexcept
5515  {
5516  return v.is_null();
5517  }
5518 
5535  friend bool operator!=(const_reference lhs, const_reference rhs) noexcept
5536  {
5537  return not (lhs == rhs);
5538  }
5539 
5558  friend bool operator!=(const_reference v, std::nullptr_t) noexcept
5559  {
5560  return not v.is_null();
5561  }
5562 
5567  friend bool operator!=(std::nullptr_t, const_reference v) noexcept
5568  {
5569  return not v.is_null();
5570  }
5571 
5596  friend bool operator<(const_reference lhs, const_reference rhs) noexcept
5597  {
5598  const auto lhs_type = lhs.type();
5599  const auto rhs_type = rhs.type();
5600 
5601  if (lhs_type == rhs_type)
5602  {
5603  switch (lhs_type)
5604  {
5605  case value_t::array:
5606  {
5607  assert(lhs.m_value.array != nullptr);
5608  assert(rhs.m_value.array != nullptr);
5609  return *lhs.m_value.array < *rhs.m_value.array;
5610  }
5611  case value_t::object:
5612  {
5613  assert(lhs.m_value.object != nullptr);
5614  assert(rhs.m_value.object != nullptr);
5615  return *lhs.m_value.object < *rhs.m_value.object;
5616  }
5617  case value_t::null:
5618  {
5619  return false;
5620  }
5621  case value_t::string:
5622  {
5623  assert(lhs.m_value.string != nullptr);
5624  assert(rhs.m_value.string != nullptr);
5625  return *lhs.m_value.string < *rhs.m_value.string;
5626  }
5627  case value_t::boolean:
5628  {
5629  return lhs.m_value.boolean < rhs.m_value.boolean;
5630  }
5631  case value_t::number_integer:
5632  {
5633  return lhs.m_value.number_integer < rhs.m_value.number_integer;
5634  }
5635  case value_t::number_unsigned:
5636  {
5637  return lhs.m_value.number_unsigned < rhs.m_value.number_unsigned;
5638  }
5639  case value_t::number_float:
5640  {
5641  return lhs.m_value.number_float < rhs.m_value.number_float;
5642  }
5643  default:
5644  {
5645  return false;
5646  }
5647  }
5648  }
5649  else if (lhs_type == value_t::number_integer and rhs_type == value_t::number_float)
5650  {
5651  return static_cast<number_float_t>(lhs.m_value.number_integer) < rhs.m_value.number_float;
5652  }
5653  else if (lhs_type == value_t::number_float and rhs_type == value_t::number_integer)
5654  {
5655  return lhs.m_value.number_float < static_cast<number_float_t>(rhs.m_value.number_integer);
5656  }
5657  else if (lhs_type == value_t::number_unsigned and rhs_type == value_t::number_float)
5658  {
5659  return static_cast<number_float_t>(lhs.m_value.number_unsigned) < rhs.m_value.number_float;
5660  }
5661  else if (lhs_type == value_t::number_float and rhs_type == value_t::number_unsigned)
5662  {
5663  return lhs.m_value.number_float < static_cast<number_float_t>(rhs.m_value.number_unsigned);
5664  }
5665  else if (lhs_type == value_t::number_integer and rhs_type == value_t::number_unsigned)
5666  {
5667  return lhs.m_value.number_integer < static_cast<number_integer_t>(rhs.m_value.number_unsigned);
5668  }
5669  else if (lhs_type == value_t::number_unsigned and rhs_type == value_t::number_integer)
5670  {
5671  return static_cast<number_integer_t>(lhs.m_value.number_unsigned) < rhs.m_value.number_integer;
5672  }
5673 
5674  // We only reach this line if we cannot compare values. In that case,
5675  // we compare types. Note we have to call the operator explicitly,
5676  // because MSVC has problems otherwise.
5677  return operator<(lhs_type, rhs_type);
5678  }
5679 
5697  friend bool operator<=(const_reference lhs, const_reference rhs) noexcept
5698  {
5699  return not (rhs < lhs);
5700  }
5701 
5719  friend bool operator>(const_reference lhs, const_reference rhs) noexcept
5720  {
5721  return not (lhs <= rhs);
5722  }
5723 
5741  friend bool operator>=(const_reference lhs, const_reference rhs) noexcept
5742  {
5743  return not (lhs < rhs);
5744  }
5745 
5747 
5748 
5750  // serialization //
5752 
5755 
5778  friend std::ostream& operator<<(std::ostream& o, const basic_json& j)
5779  {
5780  // read width member and use it as indentation parameter if nonzero
5781  const bool pretty_print = (o.width() > 0);
5782  const auto indentation = (pretty_print ? o.width() : 0);
5783 
5784  // reset width to 0 for subsequent calls to this stream
5785  o.width(0);
5786 
5787  // do the actual serialization
5788  j.dump(o, pretty_print, static_cast<unsigned int>(indentation));
5789  return o;
5790  }
5791 
5796  friend std::ostream& operator>>(const basic_json& j, std::ostream& o)
5797  {
5798  return o << j;
5799  }
5800 
5802 
5803 
5805  // deserialization //
5807 
5810 
5835  static basic_json parse(const string_t& s, parser_callback_t cb = nullptr)
5836  {
5837  return parser(s, cb).parse();
5838  }
5839 
5864  static basic_json parse(std::istream& i, parser_callback_t cb = nullptr)
5865  {
5866  return parser(i, cb).parse();
5867  }
5868 
5872  static basic_json parse(std::istream&& i, parser_callback_t cb = nullptr)
5873  {
5874  return parser(i, cb).parse();
5875  }
5876 
5900  friend std::istream& operator<<(basic_json& j, std::istream& i)
5901  {
5902  j = parser(i).parse();
5903  return i;
5904  }
5905 
5910  friend std::istream& operator>>(std::istream& i, basic_json& j)
5911  {
5912  j = parser(i).parse();
5913  return i;
5914  }
5915 
5917 
5918 
5919  private:
5921  // convenience functions //
5923 
5925  string_t type_name() const noexcept
5926  {
5927  switch (m_type)
5928  {
5929  case value_t::null:
5930  return "null";
5931  case value_t::object:
5932  return "object";
5933  case value_t::array:
5934  return "array";
5935  case value_t::string:
5936  return "string";
5937  case value_t::boolean:
5938  return "boolean";
5939  case value_t::discarded:
5940  return "discarded";
5941  default:
5942  return "number";
5943  }
5944  }
5945 
5954  static std::size_t extra_space(const string_t& s) noexcept
5955  {
5956  std::size_t result = 0;
5957 
5958  for (const auto& c : s)
5959  {
5960  switch (c)
5961  {
5962  case '"':
5963  case '\\':
5964  case '\b':
5965  case '\f':
5966  case '\n':
5967  case '\r':
5968  case '\t':
5969  {
5970  // from c (1 byte) to \x (2 bytes)
5971  result += 1;
5972  break;
5973  }
5974 
5975  default:
5976  {
5977  if (c >= 0x00 and c <= 0x1f)
5978  {
5979  // from c (1 byte) to \uxxxx (6 bytes)
5980  result += 5;
5981  }
5982  break;
5983  }
5984  }
5985  }
5986 
5987  return result;
5988  }
5989 
6003  static string_t escape_string(const string_t& s)
6004  {
6005  const auto space = extra_space(s);
6006  if (space == 0)
6007  {
6008  return s;
6009  }
6010 
6011  // create a result string of necessary size
6012  string_t result(s.size() + space, '\\');
6013  std::size_t pos = 0;
6014 
6015  for (const auto& c : s)
6016  {
6017  switch (c)
6018  {
6019  // quotation mark (0x22)
6020  case '"':
6021  {
6022  result[pos + 1] = '"';
6023  pos += 2;
6024  break;
6025  }
6026 
6027  // reverse solidus (0x5c)
6028  case '\\':
6029  {
6030  // nothing to change
6031  pos += 2;
6032  break;
6033  }
6034 
6035  // backspace (0x08)
6036  case '\b':
6037  {
6038  result[pos + 1] = 'b';
6039  pos += 2;
6040  break;
6041  }
6042 
6043  // formfeed (0x0c)
6044  case '\f':
6045  {
6046  result[pos + 1] = 'f';
6047  pos += 2;
6048  break;
6049  }
6050 
6051  // newline (0x0a)
6052  case '\n':
6053  {
6054  result[pos + 1] = 'n';
6055  pos += 2;
6056  break;
6057  }
6058 
6059  // carriage return (0x0d)
6060  case '\r':
6061  {
6062  result[pos + 1] = 'r';
6063  pos += 2;
6064  break;
6065  }
6066 
6067  // horizontal tab (0x09)
6068  case '\t':
6069  {
6070  result[pos + 1] = 't';
6071  pos += 2;
6072  break;
6073  }
6074 
6075  default:
6076  {
6077  if (c >= 0x00 and c <= 0x1f)
6078  {
6079  // convert a number 0..15 to its hex representation
6080  // (0..f)
6081  auto hexify = [](const char v) -> char
6082  {
6083  return (v < 10) ? ('0' + v) : ('a' + v - 10);
6084  };
6085 
6086  // print character c as \uxxxx
6087  for (const char m :
6088  { 'u', '0', '0', hexify(c >> 4), hexify(c & 0x0f)
6089  })
6090  {
6091  result[++pos] = m;
6092  }
6093 
6094  ++pos;
6095  }
6096  else
6097  {
6098  // all other characters are added as-is
6099  result[pos++] = c;
6100  }
6101  break;
6102  }
6103  }
6104  }
6105 
6106  return result;
6107  }
6108 
6126  void dump(std::ostream& o,
6127  const bool pretty_print,
6128  const unsigned int indent_step,
6129  const unsigned int current_indent = 0) const
6130  {
6131  // variable to hold indentation for recursive calls
6132  unsigned int new_indent = current_indent;
6133 
6134  switch (m_type)
6135  {
6136  case value_t::object:
6137  {
6138  assert(m_value.object != nullptr);
6139 
6140  if (m_value.object->empty())
6141  {
6142  o << "{}";
6143  return;
6144  }
6145 
6146  o << "{";
6147 
6148  // increase indentation
6149  if (pretty_print)
6150  {
6151  new_indent += indent_step;
6152  o << "\n";
6153  }
6154 
6155  for (auto i = m_value.object->cbegin(); i != m_value.object->cend(); ++i)
6156  {
6157  if (i != m_value.object->cbegin())
6158  {
6159  o << (pretty_print ? ",\n" : ",");
6160  }
6161  o << string_t(new_indent, ' ') << "\""
6162  << escape_string(i->first) << "\":"
6163  << (pretty_print ? " " : "");
6164  i->second.dump(o, pretty_print, indent_step, new_indent);
6165  }
6166 
6167  // decrease indentation
6168  if (pretty_print)
6169  {
6170  new_indent -= indent_step;
6171  o << "\n";
6172  }
6173 
6174  o << string_t(new_indent, ' ') + "}";
6175  return;
6176  }
6177 
6178  case value_t::array:
6179  {
6180  assert(m_value.array != nullptr);
6181 
6182  if (m_value.array->empty())
6183  {
6184  o << "[]";
6185  return;
6186  }
6187 
6188  o << "[";
6189 
6190  // increase indentation
6191  if (pretty_print)
6192  {
6193  new_indent += indent_step;
6194  o << "\n";
6195  }
6196 
6197  for (auto i = m_value.array->cbegin(); i != m_value.array->cend(); ++i)
6198  {
6199  if (i != m_value.array->cbegin())
6200  {
6201  o << (pretty_print ? ",\n" : ",");
6202  }
6203  o << string_t(new_indent, ' ');
6204  i->dump(o, pretty_print, indent_step, new_indent);
6205  }
6206 
6207  // decrease indentation
6208  if (pretty_print)
6209  {
6210  new_indent -= indent_step;
6211  o << "\n";
6212  }
6213 
6214  o << string_t(new_indent, ' ') << "]";
6215  return;
6216  }
6217 
6218  case value_t::string:
6219  {
6220  assert(m_value.string != nullptr);
6221  o << string_t("\"") << escape_string(*m_value.string) << "\"";
6222  return;
6223  }
6224 
6225  case value_t::boolean:
6226  {
6227  o << (m_value.boolean ? "true" : "false");
6228  return;
6229  }
6230 
6231  case value_t::number_integer:
6232  {
6233  o << m_value.number_integer;
6234  return;
6235  }
6236 
6237  case value_t::number_unsigned:
6238  {
6239  o << m_value.number_unsigned;
6240  return;
6241  }
6242 
6243  case value_t::number_float:
6244  {
6245  // check if number was parsed from a string
6246  if (m_type.bits.parsed)
6247  {
6248  // check if parsed number had an exponent given
6249  if (m_type.bits.has_exp)
6250  {
6251  // buffer size: precision (2^8-1 = 255) + other ('-.e-xxx' = 7) + null (1)
6252  char buf[263];
6253  int len;
6254 
6255  // handle capitalization of the exponent
6256  if (m_type.bits.exp_cap)
6257  {
6258  len = snprintf(buf, sizeof(buf), "%.*E",
6259  m_type.bits.precision, m_value.number_float) + 1;
6260  }
6261  else
6262  {
6263  len = snprintf(buf, sizeof(buf), "%.*e",
6264  m_type.bits.precision, m_value.number_float) + 1;
6265  }
6266 
6267  // remove '+' sign from the exponent if necessary
6268  if (not m_type.bits.exp_plus)
6269  {
6270  if (len > static_cast<int>(sizeof(buf)))
6271  {
6272  len = sizeof(buf);
6273  }
6274  for (int i = 0; i < len; i++)
6275  {
6276  if (buf[i] == '+')
6277  {
6278  for (; i + 1 < len; i++)
6279  {
6280  buf[i] = buf[i + 1];
6281  }
6282  }
6283  }
6284  }
6285 
6286  o << buf;
6287  }
6288  else
6289  {
6290  // no exponent - output as a decimal
6291  std::stringstream ss;
6292  ss.imbue(std::locale(std::locale(), new DecimalSeparator)); // fix locale problems
6293  ss << std::setprecision(m_type.bits.precision)
6294  << std::fixed << m_value.number_float;
6295  o << ss.str();
6296  }
6297  }
6298  else
6299  {
6300  if (m_value.number_float == 0)
6301  {
6302  // special case for zero to get "0.0"/"-0.0"
6303  o << (std::signbit(m_value.number_float) ? "-0.0" : "0.0");
6304  }
6305  else
6306  {
6307  // Otherwise 6, 15 or 16 digits of precision allows
6308  // round-trip IEEE 754 string->float->string,
6309  // string->double->string or string->long double->string;
6310  // to be safe, we read this value from
6311  // std::numeric_limits<number_float_t>::digits10
6312  std::stringstream ss;
6313  ss.imbue(std::locale(std::locale(), new DecimalSeparator)); // fix locale problems
6314  ss << std::setprecision(std::numeric_limits<double>::digits10)
6315  << m_value.number_float;
6316  o << ss.str();
6317  }
6318  }
6319  return;
6320  }
6321 
6322  case value_t::discarded:
6323  {
6324  o << "<discarded>";
6325  return;
6326  }
6327 
6328  case value_t::null:
6329  {
6330  o << "null";
6331  return;
6332  }
6333  }
6334  }
6335 
6336  private:
6338  // member variables //
6340 
6342  type_data_t m_type = value_t::null;
6343 
6345  json_value m_value = {};
6346 
6347 
6348  private:
6350  // iterators //
6352 
6362  class primitive_iterator_t
6363  {
6364  public:
6366  void set_begin() noexcept
6367  {
6368  m_it = begin_value;
6369  }
6370 
6372  void set_end() noexcept
6373  {
6374  m_it = end_value;
6375  }
6376 
6378  constexpr bool is_begin() const noexcept
6379  {
6380  return (m_it == begin_value);
6381  }
6382 
6384  constexpr bool is_end() const noexcept
6385  {
6386  return (m_it == end_value);
6387  }
6388 
6390  operator difference_type& () noexcept
6391  {
6392  return m_it;
6393  }
6394 
6396  constexpr operator difference_type () const noexcept
6397  {
6398  return m_it;
6399  }
6400 
6401  private:
6402  static constexpr difference_type begin_value = 0;
6403  static constexpr difference_type end_value = begin_value + 1;
6404 
6406  difference_type m_it = std::numeric_limits<std::ptrdiff_t>::denorm_min();
6407  };
6408 
6416  struct internal_iterator
6417  {
6419  typename object_t::iterator object_iterator;
6421  typename array_t::iterator array_iterator;
6423  primitive_iterator_t primitive_iterator;
6424 
6426  internal_iterator() noexcept
6427  : object_iterator(), array_iterator(), primitive_iterator()
6428  {}
6429  };
6430 
6432  template<typename IteratorType>
6433  class iteration_proxy
6434  {
6435  private:
6437  class iteration_proxy_internal
6438  {
6439  private:
6441  IteratorType anchor;
6443  size_t array_index = 0;
6444 
6445  public:
6446  explicit iteration_proxy_internal(IteratorType it) noexcept
6447  : anchor(it)
6448  {}
6449 
6451  iteration_proxy_internal& operator*()
6452  {
6453  return *this;
6454  }
6455 
6457  iteration_proxy_internal& operator++()
6458  {
6459  ++anchor;
6460  ++array_index;
6461 
6462  return *this;
6463  }
6464 
6466  bool operator!= (const iteration_proxy_internal& o) const
6467  {
6468  return anchor != o.anchor;
6469  }
6470 
6472  typename basic_json::string_t key() const
6473  {
6474  assert(anchor.m_object != nullptr);
6475 
6476  switch (anchor.m_object->type())
6477  {
6478  // use integer array index as key
6479  case value_t::array:
6480  {
6481  return std::to_string(array_index);
6482  }
6483 
6484  // use key from the object
6485  case value_t::object:
6486  {
6487  return anchor.key();
6488  }
6489 
6490  // use an empty key for all primitive types
6491  default:
6492  {
6493  return "";
6494  }
6495  }
6496  }
6497 
6499  typename IteratorType::reference value() const
6500  {
6501  return anchor.value();
6502  }
6503  };
6504 
6506  typename IteratorType::reference container;
6507 
6508  public:
6510  explicit iteration_proxy(typename IteratorType::reference cont)
6511  : container(cont)
6512  {}
6513 
6515  iteration_proxy_internal begin() noexcept
6516  {
6517  return iteration_proxy_internal(container.begin());
6518  }
6519 
6521  iteration_proxy_internal end() noexcept
6522  {
6523  return iteration_proxy_internal(container.end());
6524  }
6525  };
6526 
6527  public:
6541  class const_iterator : public std::iterator<std::random_access_iterator_tag, const basic_json>
6542  {
6544  friend class basic_json;
6545 
6546  public:
6556  using iterator_category = std::bidirectional_iterator_tag;
6557 
6559  const_iterator() = default;
6560 
6562  explicit const_iterator(pointer object) noexcept
6563  : m_object(object)
6564  {
6565  assert(m_object != nullptr);
6566 
6567  switch (m_object->m_type)
6568  {
6570  {
6571  m_it.object_iterator = typename object_t::iterator();
6572  break;
6573  }
6574 
6576  {
6577  m_it.array_iterator = typename array_t::iterator();
6578  break;
6579  }
6580 
6581  default:
6582  {
6583  m_it.primitive_iterator = primitive_iterator_t();
6584  break;
6585  }
6586  }
6587  }
6588 
6590  explicit const_iterator(const iterator& other) noexcept
6591  : m_object(other.m_object)
6592  {
6593  assert(m_object != nullptr);
6594 
6595  switch (m_object->m_type)
6596  {
6598  {
6599  m_it.object_iterator = other.m_it.object_iterator;
6600  break;
6601  }
6602 
6604  {
6605  m_it.array_iterator = other.m_it.array_iterator;
6606  break;
6607  }
6608 
6609  default:
6610  {
6611  m_it.primitive_iterator = other.m_it.primitive_iterator;
6612  break;
6613  }
6614  }
6615  }
6616 
6618  const_iterator(const const_iterator& other) noexcept
6619  : m_object(other.m_object), m_it(other.m_it)
6620  {}
6621 
6624  std::is_nothrow_move_constructible<pointer>::value and
6625  std::is_nothrow_move_assignable<pointer>::value and
6626  std::is_nothrow_move_constructible<internal_iterator>::value and
6627  std::is_nothrow_move_assignable<internal_iterator>::value
6628  )
6629  {
6630  std::swap(m_object, other.m_object);
6631  std::swap(m_it, other.m_it);
6632  return *this;
6633  }
6634 
6635  private:
6637  void set_begin() noexcept
6638  {
6639  assert(m_object != nullptr);
6640 
6641  switch (m_object->m_type)
6642  {
6644  {
6645  assert(m_object->m_value.object != nullptr);
6646  m_it.object_iterator = m_object->m_value.object->begin();
6647  break;
6648  }
6649 
6651  {
6652  assert(m_object->m_value.array != nullptr);
6653  m_it.array_iterator = m_object->m_value.array->begin();
6654  break;
6655  }
6656 
6658  {
6659  // set to end so begin()==end() is true: null is empty
6660  m_it.primitive_iterator.set_end();
6661  break;
6662  }
6663 
6664  default:
6665  {
6666  m_it.primitive_iterator.set_begin();
6667  break;
6668  }
6669  }
6670  }
6671 
6673  void set_end() noexcept
6674  {
6675  assert(m_object != nullptr);
6676 
6677  switch (m_object->m_type)
6678  {
6680  {
6681  assert(m_object->m_value.object != nullptr);
6682  m_it.object_iterator = m_object->m_value.object->end();
6683  break;
6684  }
6685 
6687  {
6688  assert(m_object->m_value.array != nullptr);
6689  m_it.array_iterator = m_object->m_value.array->end();
6690  break;
6691  }
6692 
6693  default:
6694  {
6695  m_it.primitive_iterator.set_end();
6696  break;
6697  }
6698  }
6699  }
6700 
6701  public:
6704  {
6705  assert(m_object != nullptr);
6706 
6707  switch (m_object->m_type)
6708  {
6710  {
6711  assert(m_object->m_value.object);
6712  assert(m_it.object_iterator != m_object->m_value.object->end());
6713  return m_it.object_iterator->second;
6714  }
6715 
6717  {
6718  assert(m_object->m_value.array);
6719  assert(m_it.array_iterator != m_object->m_value.array->end());
6720  return *m_it.array_iterator;
6721  }
6722 
6724  {
6725  throw std::out_of_range("cannot get value");
6726  }
6727 
6728  default:
6729  {
6730  if (m_it.primitive_iterator.is_begin())
6731  {
6732  return *m_object;
6733  }
6734  else
6735  {
6736  throw std::out_of_range("cannot get value");
6737  }
6738  }
6739  }
6740  }
6741 
6744  {
6745  assert(m_object != nullptr);
6746 
6747  switch (m_object->m_type)
6748  {
6750  {
6751  assert(m_object->m_value.object);
6752  assert(m_it.object_iterator != m_object->m_value.object->end());
6753  return &(m_it.object_iterator->second);
6754  }
6755 
6757  {
6758  assert(m_object->m_value.array);
6759  assert(m_it.array_iterator != m_object->m_value.array->end());
6760  return &*m_it.array_iterator;
6761  }
6762 
6763  default:
6764  {
6765  if (m_it.primitive_iterator.is_begin())
6766  {
6767  return m_object;
6768  }
6769  else
6770  {
6771  throw std::out_of_range("cannot get value");
6772  }
6773  }
6774  }
6775  }
6776 
6779  {
6780  auto result = *this;
6781  ++(*this);
6782  return result;
6783  }
6784 
6787  {
6788  assert(m_object != nullptr);
6789 
6790  switch (m_object->m_type)
6791  {
6793  {
6794  ++m_it.object_iterator;
6795  break;
6796  }
6797 
6799  {
6800  ++m_it.array_iterator;
6801  break;
6802  }
6803 
6804  default:
6805  {
6806  ++m_it.primitive_iterator;
6807  break;
6808  }
6809  }
6810 
6811  return *this;
6812  }
6813 
6816  {
6817  auto result = *this;
6818  --(*this);
6819  return result;
6820  }
6821 
6824  {
6825  assert(m_object != nullptr);
6826 
6827  switch (m_object->m_type)
6828  {
6830  {
6831  --m_it.object_iterator;
6832  break;
6833  }
6834 
6836  {
6837  --m_it.array_iterator;
6838  break;
6839  }
6840 
6841  default:
6842  {
6843  --m_it.primitive_iterator;
6844  break;
6845  }
6846  }
6847 
6848  return *this;
6849  }
6850 
6852  bool operator==(const const_iterator& other) const
6853  {
6854  // if objects are not the same, the comparison is undefined
6855  if (m_object != other.m_object)
6856  {
6857  throw std::domain_error("cannot compare iterators of different containers");
6858  }
6859 
6860  assert(m_object != nullptr);
6861 
6862  switch (m_object->m_type)
6863  {
6865  {
6866  return (m_it.object_iterator == other.m_it.object_iterator);
6867  }
6868 
6870  {
6871  return (m_it.array_iterator == other.m_it.array_iterator);
6872  }
6873 
6874  default:
6875  {
6876  return (m_it.primitive_iterator == other.m_it.primitive_iterator);
6877  }
6878  }
6879  }
6880 
6882  bool operator!=(const const_iterator& other) const
6883  {
6884  return not operator==(other);
6885  }
6886 
6888  bool operator<(const const_iterator& other) const
6889  {
6890  // if objects are not the same, the comparison is undefined
6891  if (m_object != other.m_object)
6892  {
6893  throw std::domain_error("cannot compare iterators of different containers");
6894  }
6895 
6896  assert(m_object != nullptr);
6897 
6898  switch (m_object->m_type)
6899  {
6901  {
6902  throw std::domain_error("cannot compare order of object iterators");
6903  }
6904 
6906  {
6907  return (m_it.array_iterator < other.m_it.array_iterator);
6908  }
6909 
6910  default:
6911  {
6912  return (m_it.primitive_iterator < other.m_it.primitive_iterator);
6913  }
6914  }
6915  }
6916 
6918  bool operator<=(const const_iterator& other) const
6919  {
6920  return not other.operator < (*this);
6921  }
6922 
6924  bool operator>(const const_iterator& other) const
6925  {
6926  return not operator<=(other);
6927  }
6928 
6930  bool operator>=(const const_iterator& other) const
6931  {
6932  return not operator<(other);
6933  }
6934 
6937  {
6938  assert(m_object != nullptr);
6939 
6940  switch (m_object->m_type)
6941  {
6943  {
6944  throw std::domain_error("cannot use offsets with object iterators");
6945  }
6946 
6948  {
6949  m_it.array_iterator += i;
6950  break;
6951  }
6952 
6953  default:
6954  {
6955  m_it.primitive_iterator += i;
6956  break;
6957  }
6958  }
6959 
6960  return *this;
6961  }
6962 
6965  {
6966  return operator+=(-i);
6967  }
6968 
6971  {
6972  auto result = *this;
6973  result += i;
6974  return result;
6975  }
6976 
6979  {
6980  auto result = *this;
6981  result -= i;
6982  return result;
6983  }
6984 
6987  {
6988  assert(m_object != nullptr);
6989 
6990  switch (m_object->m_type)
6991  {
6993  {
6994  throw std::domain_error("cannot use offsets with object iterators");
6995  }
6996 
6998  {
6999  return m_it.array_iterator - other.m_it.array_iterator;
7000  }
7001 
7002  default:
7003  {
7004  return m_it.primitive_iterator - other.m_it.primitive_iterator;
7005  }
7006  }
7007  }
7008 
7011  {
7012  assert(m_object != nullptr);
7013 
7014  switch (m_object->m_type)
7015  {
7017  {
7018  throw std::domain_error("cannot use operator[] for object iterators");
7019  }
7020 
7022  {
7023  return *(m_it.array_iterator + n);
7024  }
7025 
7027  {
7028  throw std::out_of_range("cannot get value");
7029  }
7030 
7031  default:
7032  {
7033  if (m_it.primitive_iterator == -n)
7034  {
7035  return *m_object;
7036  }
7037  else
7038  {
7039  throw std::out_of_range("cannot get value");
7040  }
7041  }
7042  }
7043  }
7044 
7046  typename object_t::key_type key() const
7047  {
7048  assert(m_object != nullptr);
7049 
7050  if (m_object->is_object())
7051  {
7052  return m_it.object_iterator->first;
7053  }
7054  else
7055  {
7056  throw std::domain_error("cannot use key() for non-object iterators");
7057  }
7058  }
7059 
7062  {
7063  return operator*();
7064  }
7065 
7066  private:
7068  pointer m_object = nullptr;
7070  internal_iterator m_it = internal_iterator();
7071  };
7072 
7085  class iterator : public const_iterator
7086  {
7087  public:
7089  using pointer = typename basic_json::pointer;
7091 
7093  iterator() = default;
7094 
7096  explicit iterator(pointer object) noexcept
7097  : base_iterator(object)
7098  {}
7099 
7101  iterator(const iterator& other) noexcept
7102  : base_iterator(other)
7103  {}
7104 
7106  iterator& operator=(iterator other) noexcept(
7107  std::is_nothrow_move_constructible<pointer>::value and
7108  std::is_nothrow_move_assignable<pointer>::value and
7109  std::is_nothrow_move_constructible<internal_iterator>::value and
7110  std::is_nothrow_move_assignable<internal_iterator>::value
7111  )
7112  {
7113  base_iterator::operator=(other);
7114  return *this;
7115  }
7116 
7119  {
7120  return const_cast<reference>(base_iterator::operator*());
7121  }
7122 
7125  {
7126  return const_cast<pointer>(base_iterator::operator->());
7127  }
7128 
7131  {
7132  iterator result = *this;
7133  base_iterator::operator++();
7134  return result;
7135  }
7136 
7139  {
7140  base_iterator::operator++();
7141  return *this;
7142  }
7143 
7146  {
7147  iterator result = *this;
7148  base_iterator::operator--();
7149  return result;
7150  }
7151 
7154  {
7155  base_iterator::operator--();
7156  return *this;
7157  }
7158 
7161  {
7162  base_iterator::operator+=(i);
7163  return *this;
7164  }
7165 
7168  {
7169  base_iterator::operator-=(i);
7170  return *this;
7171  }
7172 
7175  {
7176  auto result = *this;
7177  result += i;
7178  return result;
7179  }
7180 
7183  {
7184  auto result = *this;
7185  result -= i;
7186  return result;
7187  }
7188 
7190  difference_type operator-(const iterator& other) const
7191  {
7192  return base_iterator::operator-(other);
7193  }
7194 
7197  {
7198  return const_cast<reference>(base_iterator::operator[](n));
7199  }
7200 
7203  {
7204  return const_cast<reference>(base_iterator::value());
7205  }
7206  };
7207 
7225  template<typename Base>
7226  class json_reverse_iterator : public std::reverse_iterator<Base>
7227  {
7228  public:
7230  using base_iterator = std::reverse_iterator<Base>;
7232  using reference = typename Base::reference;
7233 
7235  json_reverse_iterator(const typename base_iterator::iterator_type& it) noexcept
7236  : base_iterator(it)
7237  {}
7238 
7241  : base_iterator(it)
7242  {}
7243 
7246  {
7247  return base_iterator::operator++(1);
7248  }
7249 
7252  {
7253  base_iterator::operator++();
7254  return *this;
7255  }
7256 
7259  {
7260  return base_iterator::operator--(1);
7261  }
7262 
7265  {
7266  base_iterator::operator--();
7267  return *this;
7268  }
7269 
7272  {
7273  base_iterator::operator+=(i);
7274  return *this;
7275  }
7276 
7279  {
7280  auto result = *this;
7281  result += i;
7282  return result;
7283  }
7284 
7287  {
7288  auto result = *this;
7289  result -= i;
7290  return result;
7291  }
7292 
7295  {
7296  return this->base() - other.base();
7297  }
7298 
7301  {
7302  return *(this->operator+(n));
7303  }
7304 
7306  typename object_t::key_type key() const
7307  {
7308  auto it = --this->base();
7309  return it.key();
7310  }
7311 
7314  {
7315  auto it = --this->base();
7316  return it.operator * ();
7317  }
7318  };
7319 
7320 
7321  private:
7323  // lexer and parser //
7325 
7333  class lexer
7334  {
7335  public:
7337  enum class token_type
7338  {
7339  uninitialized,
7340  literal_true,
7341  literal_false,
7342  literal_null,
7343  value_string,
7344  value_number,
7345  begin_array,
7346  begin_object,
7347  end_array,
7348  end_object,
7349  name_separator,
7350  value_separator,
7351  parse_error,
7352  end_of_input
7353  };
7354 
7356  using lexer_char_t = unsigned char;
7357 
7359  explicit lexer(const string_t& s) noexcept
7360  : m_stream(nullptr), m_buffer(s)
7361  {
7362  m_content = reinterpret_cast<const lexer_char_t*>(s.c_str());
7363  assert(m_content != nullptr);
7364  m_start = m_cursor = m_content;
7365  m_limit = m_content + s.size();
7366  }
7367 
7369  explicit lexer(std::istream* s) noexcept
7370  : m_stream(s), m_buffer()
7371  {
7372  assert(m_stream != nullptr);
7373  getline(*m_stream, m_buffer);
7374  m_content = reinterpret_cast<const lexer_char_t*>(m_buffer.c_str());
7375  assert(m_content != nullptr);
7376  m_start = m_cursor = m_content;
7377  m_limit = m_content + m_buffer.size();
7378  }
7379 
7381  lexer() = default;
7382 
7383  // switch off unwanted functions
7384  lexer(const lexer&) = delete;
7385  lexer operator=(const lexer&) = delete;
7386 
7402  static string_t to_unicode(const std::size_t codepoint1,
7403  const std::size_t codepoint2 = 0)
7404  {
7405  // calculate the codepoint from the given code points
7406  std::size_t codepoint = codepoint1;
7407 
7408  // check if codepoint1 is a high surrogate
7409  if (codepoint1 >= 0xD800 and codepoint1 <= 0xDBFF)
7410  {
7411  // check if codepoint2 is a low surrogate
7412  if (codepoint2 >= 0xDC00 and codepoint2 <= 0xDFFF)
7413  {
7414  codepoint =
7415  // high surrogate occupies the most significant 22 bits
7416  (codepoint1 << 10)
7417  // low surrogate occupies the least significant 15 bits
7418  + codepoint2
7419  // there is still the 0xD800, 0xDC00 and 0x10000 noise
7420  // in the result so we have to subtract with:
7421  // (0xD800 << 10) + DC00 - 0x10000 = 0x35FDC00
7422  - 0x35FDC00;
7423  }
7424  else
7425  {
7426  throw std::invalid_argument("missing or wrong low surrogate");
7427  }
7428  }
7429 
7430  string_t result;
7431 
7432  if (codepoint < 0x80)
7433  {
7434  // 1-byte characters: 0xxxxxxx (ASCII)
7435  result.append(1, static_cast<typename string_t::value_type>(codepoint));
7436  }
7437  else if (codepoint <= 0x7ff)
7438  {
7439  // 2-byte characters: 110xxxxx 10xxxxxx
7440  result.append(1, static_cast<typename string_t::value_type>(0xC0 | ((codepoint >> 6) & 0x1F)));
7441  result.append(1, static_cast<typename string_t::value_type>(0x80 | (codepoint & 0x3F)));
7442  }
7443  else if (codepoint <= 0xffff)
7444  {
7445  // 3-byte characters: 1110xxxx 10xxxxxx 10xxxxxx
7446  result.append(1, static_cast<typename string_t::value_type>(0xE0 | ((codepoint >> 12) & 0x0F)));
7447  result.append(1, static_cast<typename string_t::value_type>(0x80 | ((codepoint >> 6) & 0x3F)));
7448  result.append(1, static_cast<typename string_t::value_type>(0x80 | (codepoint & 0x3F)));
7449  }
7450  else if (codepoint <= 0x10ffff)
7451  {
7452  // 4-byte characters: 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
7453  result.append(1, static_cast<typename string_t::value_type>(0xF0 | ((codepoint >> 18) & 0x07)));
7454  result.append(1, static_cast<typename string_t::value_type>(0x80 | ((codepoint >> 12) & 0x3F)));
7455  result.append(1, static_cast<typename string_t::value_type>(0x80 | ((codepoint >> 6) & 0x3F)));
7456  result.append(1, static_cast<typename string_t::value_type>(0x80 | (codepoint & 0x3F)));
7457  }
7458  else
7459  {
7460  throw std::out_of_range("code points above 0x10FFFF are invalid");
7461  }
7462 
7463  return result;
7464  }
7465 
7467  static std::string token_type_name(token_type t)
7468  {
7469  switch (t)
7470  {
7471  case token_type::uninitialized:
7472  return "<uninitialized>";
7473  case token_type::literal_true:
7474  return "true literal";
7475  case token_type::literal_false:
7476  return "false literal";
7477  case token_type::literal_null:
7478  return "null literal";
7479  case token_type::value_string:
7480  return "string literal";
7481  case token_type::value_number:
7482  return "number literal";
7483  case token_type::begin_array:
7484  return "'['";
7485  case token_type::begin_object:
7486  return "'{'";
7487  case token_type::end_array:
7488  return "']'";
7489  case token_type::end_object:
7490  return "'}'";
7491  case token_type::name_separator:
7492  return "':'";
7493  case token_type::value_separator:
7494  return "','";
7495  case token_type::parse_error:
7496  return "<parse error>";
7497  case token_type::end_of_input:
7498  return "end of input";
7499  default:
7500  {
7501  // catch non-enum values
7502  return "unknown token"; // LCOV_EXCL_LINE
7503  }
7504  }
7505  }
7506 
7517  token_type scan() noexcept
7518  {
7519  // pointer for backtracking information
7520  m_marker = nullptr;
7521 
7522  // remember the begin of the token
7523  m_start = m_cursor;
7524  assert(m_start != nullptr);
7525 
7526 
7527  {
7528  lexer_char_t yych;
7529  unsigned int yyaccept = 0;
7530  static const unsigned char yybm[] =
7531  {
7532  0, 0, 0, 0, 0, 0, 0, 0,
7533  0, 32, 32, 0, 0, 32, 0, 0,
7534  128, 128, 128, 128, 128, 128, 128, 128,
7535  128, 128, 128, 128, 128, 128, 128, 128,
7536  160, 128, 0, 128, 128, 128, 128, 128,
7537  128, 128, 128, 128, 128, 128, 128, 128,
7538  192, 192, 192, 192, 192, 192, 192, 192,
7539  192, 192, 128, 128, 128, 128, 128, 128,
7540  128, 128, 128, 128, 128, 128, 128, 128,
7541  128, 128, 128, 128, 128, 128, 128, 128,
7542  128, 128, 128, 128, 128, 128, 128, 128,
7543  128, 128, 128, 128, 0, 128, 128, 128,
7544  128, 128, 128, 128, 128, 128, 128, 128,
7545  128, 128, 128, 128, 128, 128, 128, 128,
7546  128, 128, 128, 128, 128, 128, 128, 128,
7547  128, 128, 128, 128, 128, 128, 128, 128,
7548  128, 128, 128, 128, 128, 128, 128, 128,
7549  128, 128, 128, 128, 128, 128, 128, 128,
7550  128, 128, 128, 128, 128, 128, 128, 128,
7551  128, 128, 128, 128, 128, 128, 128, 128,
7552  128, 128, 128, 128, 128, 128, 128, 128,
7553  128, 128, 128, 128, 128, 128, 128, 128,
7554  128, 128, 128, 128, 128, 128, 128, 128,
7555  128, 128, 128, 128, 128, 128, 128, 128,
7556  128, 128, 128, 128, 128, 128, 128, 128,
7557  128, 128, 128, 128, 128, 128, 128, 128,
7558  128, 128, 128, 128, 128, 128, 128, 128,
7559  128, 128, 128, 128, 128, 128, 128, 128,
7560  128, 128, 128, 128, 128, 128, 128, 128,
7561  128, 128, 128, 128, 128, 128, 128, 128,
7562  128, 128, 128, 128, 128, 128, 128, 128,
7563  128, 128, 128, 128, 128, 128, 128, 128,
7564  };
7565  if ((m_limit - m_cursor) < 5)
7566  {
7567  yyfill(); // LCOV_EXCL_LINE;
7568  }
7569  yych = *m_cursor;
7570  if (yybm[0 + yych] & 32)
7571  {
7572  goto basic_json_parser_6;
7573  }
7574  if (yych <= '\\')
7575  {
7576  if (yych <= '-')
7577  {
7578  if (yych <= '"')
7579  {
7580  if (yych <= 0x00)
7581  {
7582  goto basic_json_parser_2;
7583  }
7584  if (yych <= '!')
7585  {
7586  goto basic_json_parser_4;
7587  }
7588  goto basic_json_parser_9;
7589  }
7590  else
7591  {
7592  if (yych <= '+')
7593  {
7594  goto basic_json_parser_4;
7595  }
7596  if (yych <= ',')
7597  {
7598  goto basic_json_parser_10;
7599  }
7600  goto basic_json_parser_12;
7601  }
7602  }
7603  else
7604  {
7605  if (yych <= '9')
7606  {
7607  if (yych <= '/')
7608  {
7609  goto basic_json_parser_4;
7610  }
7611  if (yych <= '0')
7612  {
7613  goto basic_json_parser_13;
7614  }
7615  goto basic_json_parser_15;
7616  }
7617  else
7618  {
7619  if (yych <= ':')
7620  {
7621  goto basic_json_parser_17;
7622  }
7623  if (yych == '[')
7624  {
7625  goto basic_json_parser_19;
7626  }
7627  goto basic_json_parser_4;
7628  }
7629  }
7630  }
7631  else
7632  {
7633  if (yych <= 't')
7634  {
7635  if (yych <= 'f')
7636  {
7637  if (yych <= ']')
7638  {
7639  goto basic_json_parser_21;
7640  }
7641  if (yych <= 'e')
7642  {
7643  goto basic_json_parser_4;
7644  }
7645  goto basic_json_parser_23;
7646  }
7647  else
7648  {
7649  if (yych == 'n')
7650  {
7651  goto basic_json_parser_24;
7652  }
7653  if (yych <= 's')
7654  {
7655  goto basic_json_parser_4;
7656  }
7657  goto basic_json_parser_25;
7658  }
7659  }
7660  else
7661  {
7662  if (yych <= '|')
7663  {
7664  if (yych == '{')
7665  {
7666  goto basic_json_parser_26;
7667  }
7668  goto basic_json_parser_4;
7669  }
7670  else
7671  {
7672  if (yych <= '}')
7673  {
7674  goto basic_json_parser_28;
7675  }
7676  if (yych == 0xEF)
7677  {
7678  goto basic_json_parser_30;
7679  }
7680  goto basic_json_parser_4;
7681  }
7682  }
7683  }
7684 basic_json_parser_2:
7685  ++m_cursor;
7686  {
7687  return token_type::end_of_input;
7688  }
7689 basic_json_parser_4:
7690  ++m_cursor;
7691 basic_json_parser_5:
7692  {
7693  return token_type::parse_error;
7694  }
7695 basic_json_parser_6:
7696  ++m_cursor;
7697  if (m_limit <= m_cursor)
7698  {
7699  yyfill(); // LCOV_EXCL_LINE;
7700  }
7701  yych = *m_cursor;
7702  if (yybm[0 + yych] & 32)
7703  {
7704  goto basic_json_parser_6;
7705  }
7706  {
7707  return scan();
7708  }
7709 basic_json_parser_9:
7710  yyaccept = 0;
7711  yych = *(m_marker = ++m_cursor);
7712  if (yych <= 0x0F)
7713  {
7714  goto basic_json_parser_5;
7715  }
7716  goto basic_json_parser_32;
7717 basic_json_parser_10:
7718  ++m_cursor;
7719  {
7720  return token_type::value_separator;
7721  }
7722 basic_json_parser_12:
7723  yych = *++m_cursor;
7724  if (yych <= '/')
7725  {
7726  goto basic_json_parser_5;
7727  }
7728  if (yych <= '0')
7729  {
7730  goto basic_json_parser_13;
7731  }
7732  if (yych <= '9')
7733  {
7734  goto basic_json_parser_15;
7735  }
7736  goto basic_json_parser_5;
7737 basic_json_parser_13:
7738  yyaccept = 1;
7739  yych = *(m_marker = ++m_cursor);
7740  if (yych <= 'D')
7741  {
7742  if (yych == '.')
7743  {
7744  goto basic_json_parser_37;
7745  }
7746  }
7747  else
7748  {
7749  if (yych <= 'E')
7750  {
7751  goto basic_json_parser_38;
7752  }
7753  if (yych == 'e')
7754  {
7755  goto basic_json_parser_38;
7756  }
7757  }
7758 basic_json_parser_14:
7759  {
7760  return token_type::value_number;
7761  }
7762 basic_json_parser_15:
7763  yyaccept = 1;
7764  m_marker = ++m_cursor;
7765  if ((m_limit - m_cursor) < 3)
7766  {
7767  yyfill(); // LCOV_EXCL_LINE;
7768  }
7769  yych = *m_cursor;
7770  if (yybm[0 + yych] & 64)
7771  {
7772  goto basic_json_parser_15;
7773  }
7774  if (yych <= 'D')
7775  {
7776  if (yych == '.')
7777  {
7778  goto basic_json_parser_37;
7779  }
7780  goto basic_json_parser_14;
7781  }
7782  else
7783  {
7784  if (yych <= 'E')
7785  {
7786  goto basic_json_parser_38;
7787  }
7788  if (yych == 'e')
7789  {
7790  goto basic_json_parser_38;
7791  }
7792  goto basic_json_parser_14;
7793  }
7794 basic_json_parser_17:
7795  ++m_cursor;
7796  {
7797  return token_type::name_separator;
7798  }
7799 basic_json_parser_19:
7800  ++m_cursor;
7801  {
7802  return token_type::begin_array;
7803  }
7804 basic_json_parser_21:
7805  ++m_cursor;
7806  {
7807  return token_type::end_array;
7808  }
7809 basic_json_parser_23:
7810  yyaccept = 0;
7811  yych = *(m_marker = ++m_cursor);
7812  if (yych == 'a')
7813  {
7814  goto basic_json_parser_39;
7815  }
7816  goto basic_json_parser_5;
7817 basic_json_parser_24:
7818  yyaccept = 0;
7819  yych = *(m_marker = ++m_cursor);
7820  if (yych == 'u')
7821  {
7822  goto basic_json_parser_40;
7823  }
7824  goto basic_json_parser_5;
7825 basic_json_parser_25:
7826  yyaccept = 0;
7827  yych = *(m_marker = ++m_cursor);
7828  if (yych == 'r')
7829  {
7830  goto basic_json_parser_41;
7831  }
7832  goto basic_json_parser_5;
7833 basic_json_parser_26:
7834  ++m_cursor;
7835  {
7836  return token_type::begin_object;
7837  }
7838 basic_json_parser_28:
7839  ++m_cursor;
7840  {
7841  return token_type::end_object;
7842  }
7843 basic_json_parser_30:
7844  yyaccept = 0;
7845  yych = *(m_marker = ++m_cursor);
7846  if (yych == 0xBB)
7847  {
7848  goto basic_json_parser_42;
7849  }
7850  goto basic_json_parser_5;
7851 basic_json_parser_31:
7852  ++m_cursor;
7853  if (m_limit <= m_cursor)
7854  {
7855  yyfill(); // LCOV_EXCL_LINE;
7856  }
7857  yych = *m_cursor;
7858 basic_json_parser_32:
7859  if (yybm[0 + yych] & 128)
7860  {
7861  goto basic_json_parser_31;
7862  }
7863  if (yych <= 0x0F)
7864  {
7865  goto basic_json_parser_33;
7866  }
7867  if (yych <= '"')
7868  {
7869  goto basic_json_parser_34;
7870  }
7871  goto basic_json_parser_36;
7872 basic_json_parser_33:
7873  m_cursor = m_marker;
7874  if (yyaccept == 0)
7875  {
7876  goto basic_json_parser_5;
7877  }
7878  else
7879  {
7880  goto basic_json_parser_14;
7881  }
7882 basic_json_parser_34:
7883  ++m_cursor;
7884  {
7885  return token_type::value_string;
7886  }
7887 basic_json_parser_36:
7888  ++m_cursor;
7889  if (m_limit <= m_cursor)
7890  {
7891  yyfill(); // LCOV_EXCL_LINE;
7892  }
7893  yych = *m_cursor;
7894  if (yych <= 'e')
7895  {
7896  if (yych <= '/')
7897  {
7898  if (yych == '"')
7899  {
7900  goto basic_json_parser_31;
7901  }
7902  if (yych <= '.')
7903  {
7904  goto basic_json_parser_33;
7905  }
7906  goto basic_json_parser_31;
7907  }
7908  else
7909  {
7910  if (yych <= '\\')
7911  {
7912  if (yych <= '[')
7913  {
7914  goto basic_json_parser_33;
7915  }
7916  goto basic_json_parser_31;
7917  }
7918  else
7919  {
7920  if (yych == 'b')
7921  {
7922  goto basic_json_parser_31;
7923  }
7924  goto basic_json_parser_33;
7925  }
7926  }
7927  }
7928  else
7929  {
7930  if (yych <= 'q')
7931  {
7932  if (yych <= 'f')
7933  {
7934  goto basic_json_parser_31;
7935  }
7936  if (yych == 'n')
7937  {
7938  goto basic_json_parser_31;
7939  }
7940  goto basic_json_parser_33;
7941  }
7942  else
7943  {
7944  if (yych <= 's')
7945  {
7946  if (yych <= 'r')
7947  {
7948  goto basic_json_parser_31;
7949  }
7950  goto basic_json_parser_33;
7951  }
7952  else
7953  {
7954  if (yych <= 't')
7955  {
7956  goto basic_json_parser_31;
7957  }
7958  if (yych <= 'u')
7959  {
7960  goto basic_json_parser_43;
7961  }
7962  goto basic_json_parser_33;
7963  }
7964  }
7965  }
7966 basic_json_parser_37:
7967  yych = *++m_cursor;
7968  if (yych <= '/')
7969  {
7970  goto basic_json_parser_33;
7971  }
7972  if (yych <= '9')
7973  {
7974  goto basic_json_parser_44;
7975  }
7976  goto basic_json_parser_33;
7977 basic_json_parser_38:
7978  yych = *++m_cursor;
7979  if (yych <= ',')
7980  {
7981  if (yych == '+')
7982  {
7983  goto basic_json_parser_46;
7984  }
7985  goto basic_json_parser_33;
7986  }
7987  else
7988  {
7989  if (yych <= '-')
7990  {
7991  goto basic_json_parser_46;
7992  }
7993  if (yych <= '/')
7994  {
7995  goto basic_json_parser_33;
7996  }
7997  if (yych <= '9')
7998  {
7999  goto basic_json_parser_47;
8000  }
8001  goto basic_json_parser_33;
8002  }
8003 basic_json_parser_39:
8004  yych = *++m_cursor;
8005  if (yych == 'l')
8006  {
8007  goto basic_json_parser_49;
8008  }
8009  goto basic_json_parser_33;
8010 basic_json_parser_40:
8011  yych = *++m_cursor;
8012  if (yych == 'l')
8013  {
8014  goto basic_json_parser_50;
8015  }
8016  goto basic_json_parser_33;
8017 basic_json_parser_41:
8018  yych = *++m_cursor;
8019  if (yych == 'u')
8020  {
8021  goto basic_json_parser_51;
8022  }
8023  goto basic_json_parser_33;
8024 basic_json_parser_42:
8025  yych = *++m_cursor;
8026  if (yych == 0xBF)
8027  {
8028  goto basic_json_parser_52;
8029  }
8030  goto basic_json_parser_33;
8031 basic_json_parser_43:
8032  ++m_cursor;
8033  if (m_limit <= m_cursor)
8034  {
8035  yyfill(); // LCOV_EXCL_LINE;
8036  }
8037  yych = *m_cursor;
8038  if (yych <= '@')
8039  {
8040  if (yych <= '/')
8041  {
8042  goto basic_json_parser_33;
8043  }
8044  if (yych <= '9')
8045  {
8046  goto basic_json_parser_54;
8047  }
8048  goto basic_json_parser_33;
8049  }
8050  else
8051  {
8052  if (yych <= 'F')
8053  {
8054  goto basic_json_parser_54;
8055  }
8056  if (yych <= '`')
8057  {
8058  goto basic_json_parser_33;
8059  }
8060  if (yych <= 'f')
8061  {
8062  goto basic_json_parser_54;
8063  }
8064  goto basic_json_parser_33;
8065  }
8066 basic_json_parser_44:
8067  yyaccept = 1;
8068  m_marker = ++m_cursor;
8069  if ((m_limit - m_cursor) < 3)
8070  {
8071  yyfill(); // LCOV_EXCL_LINE;
8072  }
8073  yych = *m_cursor;
8074  if (yych <= 'D')
8075  {
8076  if (yych <= '/')
8077  {
8078  goto basic_json_parser_14;
8079  }
8080  if (yych <= '9')
8081  {
8082  goto basic_json_parser_44;
8083  }
8084  goto basic_json_parser_14;
8085  }
8086  else
8087  {
8088  if (yych <= 'E')
8089  {
8090  goto basic_json_parser_38;
8091  }
8092  if (yych == 'e')
8093  {
8094  goto basic_json_parser_38;
8095  }
8096  goto basic_json_parser_14;
8097  }
8098 basic_json_parser_46:
8099  yych = *++m_cursor;
8100  if (yych <= '/')
8101  {
8102  goto basic_json_parser_33;
8103  }
8104  if (yych >= ':')
8105  {
8106  goto basic_json_parser_33;
8107  }
8108 basic_json_parser_47:
8109  ++m_cursor;
8110  if (m_limit <= m_cursor)
8111  {
8112  yyfill(); // LCOV_EXCL_LINE;
8113  }
8114  yych = *m_cursor;
8115  if (yych <= '/')
8116  {
8117  goto basic_json_parser_14;
8118  }
8119  if (yych <= '9')
8120  {
8121  goto basic_json_parser_47;
8122  }
8123  goto basic_json_parser_14;
8124 basic_json_parser_49:
8125  yych = *++m_cursor;
8126  if (yych == 's')
8127  {
8128  goto basic_json_parser_55;
8129  }
8130  goto basic_json_parser_33;
8131 basic_json_parser_50:
8132  yych = *++m_cursor;
8133  if (yych == 'l')
8134  {
8135  goto basic_json_parser_56;
8136  }
8137  goto basic_json_parser_33;
8138 basic_json_parser_51:
8139  yych = *++m_cursor;
8140  if (yych == 'e')
8141  {
8142  goto basic_json_parser_58;
8143  }
8144  goto basic_json_parser_33;
8145 basic_json_parser_52:
8146  ++m_cursor;
8147  {
8148  return scan();
8149  }
8150 basic_json_parser_54:
8151  ++m_cursor;
8152  if (m_limit <= m_cursor)
8153  {
8154  yyfill(); // LCOV_EXCL_LINE;
8155  }
8156  yych = *m_cursor;
8157  if (yych <= '@')
8158  {
8159  if (yych <= '/')
8160  {
8161  goto basic_json_parser_33;
8162  }
8163  if (yych <= '9')
8164  {
8165  goto basic_json_parser_60;
8166  }
8167  goto basic_json_parser_33;
8168  }
8169  else
8170  {
8171  if (yych <= 'F')
8172  {
8173  goto basic_json_parser_60;
8174  }
8175  if (yych <= '`')
8176  {
8177  goto basic_json_parser_33;
8178  }
8179  if (yych <= 'f')
8180  {
8181  goto basic_json_parser_60;
8182  }
8183  goto basic_json_parser_33;
8184  }
8185 basic_json_parser_55:
8186  yych = *++m_cursor;
8187  if (yych == 'e')
8188  {
8189  goto basic_json_parser_61;
8190  }
8191  goto basic_json_parser_33;
8192 basic_json_parser_56:
8193  ++m_cursor;
8194  {
8195  return token_type::literal_null;
8196  }
8197 basic_json_parser_58:
8198  ++m_cursor;
8199  {
8200  return token_type::literal_true;
8201  }
8202 basic_json_parser_60:
8203  ++m_cursor;
8204  if (m_limit <= m_cursor)
8205  {
8206  yyfill(); // LCOV_EXCL_LINE;
8207  }
8208  yych = *m_cursor;
8209  if (yych <= '@')
8210  {
8211  if (yych <= '/')
8212  {
8213  goto basic_json_parser_33;
8214  }
8215  if (yych <= '9')
8216  {
8217  goto basic_json_parser_63;
8218  }
8219  goto basic_json_parser_33;
8220  }
8221  else
8222  {
8223  if (yych <= 'F')
8224  {
8225  goto basic_json_parser_63;
8226  }
8227  if (yych <= '`')
8228  {
8229  goto basic_json_parser_33;
8230  }
8231  if (yych <= 'f')
8232  {
8233  goto basic_json_parser_63;
8234  }
8235  goto basic_json_parser_33;
8236  }
8237 basic_json_parser_61:
8238  ++m_cursor;
8239  {
8240  return token_type::literal_false;
8241  }
8242 basic_json_parser_63:
8243  ++m_cursor;
8244  if (m_limit <= m_cursor)
8245  {
8246  yyfill(); // LCOV_EXCL_LINE;
8247  }
8248  yych = *m_cursor;
8249  if (yych <= '@')
8250  {
8251  if (yych <= '/')
8252  {
8253  goto basic_json_parser_33;
8254  }
8255  if (yych <= '9')
8256  {
8257  goto basic_json_parser_31;
8258  }
8259  goto basic_json_parser_33;
8260  }
8261  else
8262  {
8263  if (yych <= 'F')
8264  {
8265  goto basic_json_parser_31;
8266  }
8267  if (yych <= '`')
8268  {
8269  goto basic_json_parser_33;
8270  }
8271  if (yych <= 'f')
8272  {
8273  goto basic_json_parser_31;
8274  }
8275  goto basic_json_parser_33;
8276  }
8277  }
8278 
8279  }
8280 
8282  void yyfill() noexcept
8283  {
8284  if (m_stream == nullptr or not * m_stream)
8285  {
8286  return;
8287  }
8288 
8289  const auto offset_start = m_start - m_content;
8290  const auto offset_marker = m_marker - m_start;
8291  const auto offset_cursor = m_cursor - m_start;
8292 
8293  m_buffer.erase(0, static_cast<size_t>(offset_start));
8294  std::string line;
8295  assert(m_stream != nullptr);
8296  std::getline(*m_stream, line);
8297  m_buffer += "\n" + line; // add line with newline symbol
8298 
8299  m_content = reinterpret_cast<const lexer_char_t*>(m_buffer.c_str());
8300  assert(m_content != nullptr);
8301  m_start = m_content;
8302  m_marker = m_start + offset_marker;
8303  m_cursor = m_start + offset_cursor;
8304  m_limit = m_start + m_buffer.size() - 1;
8305  }
8306 
8308  string_t get_token() const
8309  {
8310  assert(m_start != nullptr);
8311  return string_t(reinterpret_cast<typename string_t::const_pointer>(m_start),
8312  static_cast<size_t>(m_cursor - m_start));
8313  }
8314 
8336  string_t get_string() const
8337  {
8338  string_t result;
8339  result.reserve(static_cast<size_t>(m_cursor - m_start - 2));
8340 
8341  // iterate the result between the quotes
8342  for (const lexer_char_t* i = m_start + 1; i < m_cursor - 1; ++i)
8343  {
8344  // process escaped characters
8345  if (*i == '\\')
8346  {
8347  // read next character
8348  ++i;
8349 
8350  switch (*i)
8351  {
8352  // the default escapes
8353  case 't':
8354  {
8355  result += "\t";
8356  break;
8357  }
8358  case 'b':
8359  {
8360  result += "\b";
8361  break;
8362  }
8363  case 'f':
8364  {
8365  result += "\f";
8366  break;
8367  }
8368  case 'n':
8369  {
8370  result += "\n";
8371  break;
8372  }
8373  case 'r':
8374  {
8375  result += "\r";
8376  break;
8377  }
8378  case '\\':
8379  {
8380  result += "\\";
8381  break;
8382  }
8383  case '/':
8384  {
8385  result += "/";
8386  break;
8387  }
8388  case '"':
8389  {
8390  result += "\"";
8391  break;
8392  }
8393 
8394  // unicode
8395  case 'u':
8396  {
8397  // get code xxxx from uxxxx
8398  auto codepoint = std::strtoul(std::string(reinterpret_cast<typename string_t::const_pointer>(i + 1),
8399  4).c_str(), nullptr, 16);
8400 
8401  // check if codepoint is a high surrogate
8402  if (codepoint >= 0xD800 and codepoint <= 0xDBFF)
8403  {
8404  // make sure there is a subsequent unicode
8405  if ((i + 6 >= m_limit) or * (i + 5) != '\\' or * (i + 6) != 'u')
8406  {
8407  throw std::invalid_argument("missing low surrogate");
8408  }
8409 
8410  // get code yyyy from uxxxx\uyyyy
8411  auto codepoint2 = std::strtoul(std::string(reinterpret_cast<typename string_t::const_pointer>
8412  (i + 7), 4).c_str(), nullptr, 16);
8413  result += to_unicode(codepoint, codepoint2);
8414  // skip the next 10 characters (xxxx\uyyyy)
8415  i += 10;
8416  }
8417  else
8418  {
8419  // add unicode character(s)
8420  result += to_unicode(codepoint);
8421  // skip the next four characters (xxxx)
8422  i += 4;
8423  }
8424  break;
8425  }
8426  }
8427  }
8428  else
8429  {
8430  // all other characters are just copied to the end of the
8431  // string
8432  result.append(1, static_cast<typename string_t::value_type>(*i));
8433  }
8434  }
8435 
8436  return result;
8437  }
8438 
8459  long double str_to_float_t(long double* /* type */, char** endptr) const
8460  {
8461  return std::strtold(reinterpret_cast<typename string_t::const_pointer>(m_start), endptr);
8462  }
8463 
8479  double str_to_float_t(double* /* type */, char** endptr) const
8480  {
8481  return std::strtod(reinterpret_cast<typename string_t::const_pointer>(m_start), endptr);
8482  }
8483 
8499  float str_to_float_t(float* /* type */, char** endptr) const
8500  {
8501  return std::strtof(reinterpret_cast<typename string_t::const_pointer>(m_start), endptr);
8502  }
8503 
8531  void get_number(basic_json& result) const
8532  {
8533  assert(m_start != nullptr);
8534 
8535  const lexer::lexer_char_t* curptr = m_start;
8536 
8537  // remember this number was parsed (for later serialization)
8538  result.m_type.bits.parsed = true;
8539 
8540  // 'found_radix_point' will be set to 0xFF upon finding a radix
8541  // point and later used to mask in/out the precision depending
8542  // whether a radix is found i.e. 'precision &= found_radix_point'
8543  uint8_t found_radix_point = 0;
8544  uint8_t precision = 0;
8545 
8546  // accumulate the integer conversion result (unsigned for now)
8547  number_unsigned_t value = 0;
8548 
8549  // maximum absolute value of the relevant integer type
8550  number_unsigned_t max;
8551 
8552  // temporarily store the type to avoid unecessary bitfield access
8553  value_t type;
8554 
8555  // look for sign
8556  if (*curptr == '-')
8557  {
8558  type = value_t::number_integer;
8559  max = static_cast<uint64_t>(std::numeric_limits<number_integer_t>::max()) + 1;
8560  curptr++;
8561  }
8562  else
8563  {
8564  type = value_t::number_unsigned;
8565  max = static_cast<uint64_t>(std::numeric_limits<number_unsigned_t>::max());
8566  if (*curptr == '+')
8567  {
8568  curptr++;
8569  }
8570  }
8571 
8572  // count the significant figures
8573  for (; curptr < m_cursor; curptr++)
8574  {
8575  // quickly skip tests if a digit
8576  if (*curptr < '0' || *curptr > '9')
8577  {
8578  if (*curptr == '.')
8579  {
8580  // don't count '.' but change to float
8581  type = value_t::number_float;
8582 
8583  // reset precision count
8584  precision = 0;
8585  found_radix_point = 0xFF;
8586  continue;
8587  }
8588  // assume exponent (if not then will fail parse): change to
8589  // float, stop counting and record exponent details
8590  type = value_t::number_float;
8591  result.m_type.bits.has_exp = true;
8592 
8593  // exponent capitalization
8594  result.m_type.bits.exp_cap = (*curptr == 'E');
8595 
8596  // exponent '+' sign
8597  result.m_type.bits.exp_plus = (*(++curptr) == '+');
8598  break;
8599  }
8600 
8601  // skip if definitely not an integer
8602  if (type != value_t::number_float)
8603  {
8604  // multiply last value by ten and add the new digit
8605  auto temp = value * 10 + *curptr - 0x30;
8606 
8607  // test for overflow
8608  if (temp < value || temp > max)
8609  {
8610  // overflow
8611  type = value_t::number_float;
8612  }
8613  else
8614  {
8615  // no overflow - save it
8616  value = temp;
8617  }
8618  }
8619  ++precision;
8620  }
8621 
8622  // If no radix point was found then precision would now be set to
8623  // the number of digits, which is wrong - clear it.
8624  result.m_type.bits.precision = precision & found_radix_point;
8625 
8626  // save the value (if not a float)
8627  if (type == value_t::number_unsigned)
8628  {
8629  result.m_value.number_unsigned = value;
8630  }
8631  else if (type == value_t::number_integer)
8632  {
8633  result.m_value.number_integer = -static_cast<number_integer_t>(value);
8634  }
8635  else
8636  {
8637  // parse with strtod
8638  result.m_value.number_float = str_to_float_t(static_cast<number_float_t*>(nullptr), NULL);
8639  }
8640 
8641  // save the type
8642  result.m_type = type;
8643  }
8644 
8645  private:
8647  std::istream* m_stream = nullptr;
8649  string_t m_buffer;
8651  const lexer_char_t* m_content = nullptr;
8653  const lexer_char_t* m_start = nullptr;
8655  const lexer_char_t* m_marker = nullptr;
8657  const lexer_char_t* m_cursor = nullptr;
8659  const lexer_char_t* m_limit = nullptr;
8660  };
8661 
8667  class parser
8668  {
8669  public:
8671  parser(const string_t& s, parser_callback_t cb = nullptr) noexcept
8672  : callback(cb), m_lexer(s)
8673  {
8674  // read first token
8675  get_token();
8676  }
8677 
8679  parser(std::istream& _is, parser_callback_t cb = nullptr) noexcept
8680  : callback(cb), m_lexer(&_is)
8681  {
8682  // read first token
8683  get_token();
8684  }
8685 
8687  basic_json parse()
8688  {
8689  basic_json result = parse_internal(true);
8690 
8691  expect(lexer::token_type::end_of_input);
8692 
8693  // return parser result and replace it with null in case the
8694  // top-level value was discarded by the callback function
8695  return result.is_discarded() ? basic_json() : result;
8696  }
8697 
8698  private:
8700  basic_json parse_internal(bool keep)
8701  {
8702  auto result = basic_json(value_t::discarded);
8703 
8704  switch (last_token)
8705  {
8706  case lexer::token_type::begin_object:
8707  {
8708  if (keep and (not callback or (keep = callback(depth++, parse_event_t::object_start, result))))
8709  {
8710  // explicitly set result to object to cope with {}
8711  result.m_type = value_t::object;
8712  result.m_value = json_value(value_t::object);
8713  }
8714 
8715  // read next token
8716  get_token();
8717 
8718  // closing } -> we are done
8719  if (last_token == lexer::token_type::end_object)
8720  {
8721  get_token();
8722  if (keep and callback and not callback(--depth, parse_event_t::object_end, result))
8723  {
8724  result = basic_json(value_t::discarded);
8725  }
8726  return result;
8727  }
8728 
8729  // no comma is expected here
8730  unexpect(lexer::token_type::value_separator);
8731 
8732  // otherwise: parse key-value pairs
8733  do
8734  {
8735  // ugly, but could be fixed with loop reorganization
8736  if (last_token == lexer::token_type::value_separator)
8737  {
8738  get_token();
8739  }
8740 
8741  // store key
8742  expect(lexer::token_type::value_string);
8743  const auto key = m_lexer.get_string();
8744 
8745  bool keep_tag = false;
8746  if (keep)
8747  {
8748  if (callback)
8749  {
8750  basic_json k(key);
8751  keep_tag = callback(depth, parse_event_t::key, k);
8752  }
8753  else
8754  {
8755  keep_tag = true;
8756  }
8757  }
8758 
8759  // parse separator (:)
8760  get_token();
8761  expect(lexer::token_type::name_separator);
8762 
8763  // parse and add value
8764  get_token();
8765  auto value = parse_internal(keep);
8766  if (keep and keep_tag and not value.is_discarded())
8767  {
8768  result[key] = std::move(value);
8769  }
8770  }
8771  while (last_token == lexer::token_type::value_separator);
8772 
8773  // closing }
8774  expect(lexer::token_type::end_object);
8775  get_token();
8776  if (keep and callback and not callback(--depth, parse_event_t::object_end, result))
8777  {
8778  result = basic_json(value_t::discarded);
8779  }
8780 
8781  return result;
8782  }
8783 
8784  case lexer::token_type::begin_array:
8785  {
8786  if (keep and (not callback or (keep = callback(depth++, parse_event_t::array_start, result))))
8787  {
8788  // explicitly set result to object to cope with []
8789  result.m_type = value_t::array;
8790  result.m_value = json_value(value_t::array);
8791  }
8792 
8793  // read next token
8794  get_token();
8795 
8796  // closing ] -> we are done
8797  if (last_token == lexer::token_type::end_array)
8798  {
8799  get_token();
8800  if (callback and not callback(--depth, parse_event_t::array_end, result))
8801  {
8802  result = basic_json(value_t::discarded);
8803  }
8804  return result;
8805  }
8806 
8807  // no comma is expected here
8808  unexpect(lexer::token_type::value_separator);
8809 
8810  // otherwise: parse values
8811  do
8812  {
8813  // ugly, but could be fixed with loop reorganization
8814  if (last_token == lexer::token_type::value_separator)
8815  {
8816  get_token();
8817  }
8818 
8819  // parse value
8820  auto value = parse_internal(keep);
8821  if (keep and not value.is_discarded())
8822  {
8823  result.push_back(std::move(value));
8824  }
8825  }
8826  while (last_token == lexer::token_type::value_separator);
8827 
8828  // closing ]
8829  expect(lexer::token_type::end_array);
8830  get_token();
8831  if (keep and callback and not callback(--depth, parse_event_t::array_end, result))
8832  {
8833  result = basic_json(value_t::discarded);
8834  }
8835 
8836  return result;
8837  }
8838 
8839  case lexer::token_type::literal_null:
8840  {
8841  get_token();
8842  result.m_type = value_t::null;
8843  break;
8844  }
8845 
8846  case lexer::token_type::value_string:
8847  {
8848  const auto s = m_lexer.get_string();
8849  get_token();
8850  result = basic_json(s);
8851  break;
8852  }
8853 
8854  case lexer::token_type::literal_true:
8855  {
8856  get_token();
8857  result.m_type = value_t::boolean;
8858  result.m_value = true;
8859  break;
8860  }
8861 
8862  case lexer::token_type::literal_false:
8863  {
8864  get_token();
8865  result.m_type = value_t::boolean;
8866  result.m_value = false;
8867  break;
8868  }
8869 
8870  case lexer::token_type::value_number:
8871  {
8872  m_lexer.get_number(result);
8873  get_token();
8874  break;
8875  }
8876 
8877  default:
8878  {
8879  // the last token was unexpected
8880  unexpect(last_token);
8881  }
8882  }
8883 
8884  if (keep and callback and not callback(depth, parse_event_t::value, result))
8885  {
8886  result = basic_json(value_t::discarded);
8887  }
8888  return result;
8889  }
8890 
8892  typename lexer::token_type get_token() noexcept
8893  {
8894  last_token = m_lexer.scan();
8895  return last_token;
8896  }
8897 
8898  void expect(typename lexer::token_type t) const
8899  {
8900  if (t != last_token)
8901  {
8902  std::string error_msg = "parse error - unexpected ";
8903  error_msg += (last_token == lexer::token_type::parse_error ? ("'" + m_lexer.get_token() + "'") :
8904  lexer::token_type_name(last_token));
8905  error_msg += "; expected " + lexer::token_type_name(t);
8906  throw std::invalid_argument(error_msg);
8907  }
8908  }
8909 
8910  void unexpect(typename lexer::token_type t) const
8911  {
8912  if (t == last_token)
8913  {
8914  std::string error_msg = "parse error - unexpected ";
8915  error_msg += (last_token == lexer::token_type::parse_error ? ("'" + m_lexer.get_token() + "'") :
8916  lexer::token_type_name(last_token));
8917  throw std::invalid_argument(error_msg);
8918  }
8919  }
8920 
8921  private:
8923  int depth = 0;
8925  parser_callback_t callback;
8927  typename lexer::token_type last_token = lexer::token_type::uninitialized;
8929  lexer m_lexer;
8930  };
8931 
8932  public:
8941  {
8943  friend class basic_json;
8944 
8945  public:
8968  explicit json_pointer(const std::string& s = "")
8969  : reference_tokens(split(s))
8970  {}
8971 
8972  private:
8976  reference get_and_create(reference j) const
8977  {
8978  pointer result = &j;
8979 
8980  // in case no reference tokens exist, return a reference to the
8981  // JSON value j which will be overwritten by a primitive value
8982  for (const auto& reference_token : reference_tokens)
8983  {
8984  switch (result->m_type)
8985  {
8986  case value_t::null:
8987  {
8988  if (reference_token == "0")
8989  {
8990  // start a new array if reference token is 0
8991  result = &result->operator[](0);
8992  }
8993  else
8994  {
8995  // start a new object otherwise
8996  result = &result->operator[](reference_token);
8997  }
8998  break;
8999  }
9000 
9001  case value_t::object:
9002  {
9003  // create an entry in the object
9004  result = &result->operator[](reference_token);
9005  break;
9006  }
9007 
9008  case value_t::array:
9009  {
9010  // create an entry in the array
9011  result = &result->operator[](static_cast<size_t>(std::stoi(reference_token)));
9012  break;
9013  }
9014 
9015  /*
9016  The following code is only reached if there exists a
9017  reference token _and_ the current value is primitive. In
9018  this case, we have an error situation, because primitive
9019  values may only occur as single value; that is, with an
9020  empty list of reference tokens.
9021  */
9022  default:
9023  {
9024  throw std::domain_error("invalid value to unflatten");
9025  }
9026  }
9027  }
9028 
9029  return *result;
9030  }
9031 
9045  reference get_unchecked(pointer ptr) const
9046  {
9047  for (const auto& reference_token : reference_tokens)
9048  {
9049  switch (ptr->m_type)
9050  {
9051  case value_t::object:
9052  {
9053  // use unchecked object access
9054  ptr = &ptr->operator[](reference_token);
9055  break;
9056  }
9057 
9058  case value_t::array:
9059  {
9060  // error condition (cf. RFC 6901, Sect. 4)
9061  if (reference_token.size() > 1 and reference_token[0] == '0')
9062  {
9063  throw std::domain_error("array index must not begin with '0'");
9064  }
9065 
9066  if (reference_token == "-")
9067  {
9068  // explicityly treat "-" as index beyond the end
9069  ptr = &ptr->operator[](ptr->m_value.array->size());
9070  }
9071  else
9072  {
9073  // convert array index to number; unchecked access
9074  ptr = &ptr->operator[](static_cast<size_t>(std::stoi(reference_token)));
9075  }
9076  break;
9077  }
9078 
9079  default:
9080  {
9081  throw std::out_of_range("unresolved reference token '" + reference_token + "'");
9082  }
9083  }
9084  }
9085 
9086  return *ptr;
9087  }
9088 
9089  reference get_checked(pointer ptr) const
9090  {
9091  for (const auto& reference_token : reference_tokens)
9092  {
9093  switch (ptr->m_type)
9094  {
9095  case value_t::object:
9096  {
9097  // note: at performs range check
9098  ptr = &ptr->at(reference_token);
9099  break;
9100  }
9101 
9102  case value_t::array:
9103  {
9104  if (reference_token == "-")
9105  {
9106  // "-" always fails the range check
9107  throw std::out_of_range("array index '-' (" +
9108  std::to_string(ptr->m_value.array->size()) +
9109  ") is out of range");
9110  }
9111 
9112  // error condition (cf. RFC 6901, Sect. 4)
9113  if (reference_token.size() > 1 and reference_token[0] == '0')
9114  {
9115  throw std::domain_error("array index must not begin with '0'");
9116  }
9117 
9118  // note: at performs range check
9119  ptr = &ptr->at(static_cast<size_t>(std::stoi(reference_token)));
9120  break;
9121  }
9122 
9123  default:
9124  {
9125  throw std::out_of_range("unresolved reference token '" + reference_token + "'");
9126  }
9127  }
9128  }
9129 
9130  return *ptr;
9131  }
9132 
9141  const_reference get_unchecked(const_pointer ptr) const
9142  {
9143  for (const auto& reference_token : reference_tokens)
9144  {
9145  switch (ptr->m_type)
9146  {
9147  case value_t::object:
9148  {
9149  // use unchecked object access
9150  ptr = &ptr->operator[](reference_token);
9151  break;
9152  }
9153 
9154  case value_t::array:
9155  {
9156  if (reference_token == "-")
9157  {
9158  // "-" cannot be used for const access
9159  throw std::out_of_range("array index '-' (" +
9160  std::to_string(ptr->m_value.array->size()) +
9161  ") is out of range");
9162  }
9163 
9164  // error condition (cf. RFC 6901, Sect. 4)
9165  if (reference_token.size() > 1 and reference_token[0] == '0')
9166  {
9167  throw std::domain_error("array index must not begin with '0'");
9168  }
9169 
9170  // use unchecked array access
9171  ptr = &ptr->operator[](static_cast<size_t>(std::stoi(reference_token)));
9172  break;
9173  }
9174 
9175  default:
9176  {
9177  throw std::out_of_range("unresolved reference token '" + reference_token + "'");
9178  }
9179  }
9180  }
9181 
9182  return *ptr;
9183  }
9184 
9185  const_reference get_checked(const_pointer ptr) const
9186  {
9187  for (const auto& reference_token : reference_tokens)
9188  {
9189  switch (ptr->m_type)
9190  {
9191  case value_t::object:
9192  {
9193  // note: at performs range check
9194  ptr = &ptr->at(reference_token);
9195  break;
9196  }
9197 
9198  case value_t::array:
9199  {
9200  if (reference_token == "-")
9201  {
9202  // "-" always fails the range check
9203  throw std::out_of_range("array index '-' (" +
9204  std::to_string(ptr->m_value.array->size()) +
9205  ") is out of range");
9206  }
9207 
9208  // error condition (cf. RFC 6901, Sect. 4)
9209  if (reference_token.size() > 1 and reference_token[0] == '0')
9210  {
9211  throw std::domain_error("array index must not begin with '0'");
9212  }
9213 
9214  // note: at performs range check
9215  ptr = &ptr->at(static_cast<size_t>(std::stoi(reference_token)));
9216  break;
9217  }
9218 
9219  default:
9220  {
9221  throw std::out_of_range("unresolved reference token '" + reference_token + "'");
9222  }
9223  }
9224  }
9225 
9226  return *ptr;
9227  }
9228 
9230  std::vector<std::string> split(std::string reference_string)
9231  {
9232  std::vector<std::string> result;
9233 
9234  // special case: empty reference string -> no reference tokens
9235  if (reference_string.empty())
9236  {
9237  return result;
9238  }
9239 
9240  // check if nonempty reference string begins with slash
9241  if (reference_string[0] != '/')
9242  {
9243  throw std::domain_error("JSON pointer must be empty or begin with '/'");
9244  }
9245 
9246  // extract the reference tokens:
9247  // - slash: position of the last read slash (or end of string)
9248  // - start: position after the previous slash
9249  for (
9250  // search for the first slash after the first character
9251  size_t slash = reference_string.find_first_of("/", 1),
9252  // set the beginning of the first reference token
9253  start = 1;
9254  // we can stop if start == string::npos+1 = 0
9255  start != 0;
9256  // set the beginning of the next reference token
9257  // (will eventually be 0 if slash == std::string::npos)
9258  start = slash + 1,
9259  // find next slash
9260  slash = reference_string.find_first_of("/", start))
9261  {
9262  // use the text between the beginning of the reference token
9263  // (start) and the last slash (slash).
9264  auto reference_token = reference_string.substr(start, slash - start);
9265 
9266  // check reference tokens are properly escaped
9267  for (size_t pos = reference_token.find_first_of("~");
9268  pos != std::string::npos;
9269  pos = reference_token.find_first_of("~", pos + 1))
9270  {
9271  assert(reference_token[pos] == '~');
9272 
9273  // ~ must be followed by 0 or 1
9274  if (pos == reference_token.size() - 1 or
9275  (reference_token[pos + 1] != '0' and
9276  reference_token[pos + 1] != '1'))
9277  {
9278  throw std::domain_error("escape error: '~' must be followed with '0' or '1'");
9279  }
9280  }
9281 
9282  // first transform any occurrence of the sequence '~1' to '/'
9283  replace_substring(reference_token, "~1", "/");
9284  // then transform any occurrence of the sequence '~0' to '~'
9285  replace_substring(reference_token, "~0", "~");
9286 
9287  // finally, store the reference token
9288  result.push_back(reference_token);
9289  }
9290 
9291  return result;
9292  }
9293 
9294  private:
9309  static void replace_substring(std::string& s,
9310  const std::string& f,
9311  const std::string& t)
9312  {
9313  assert(not f.empty());
9314 
9315  for (
9316  size_t pos = s.find(f); // find first occurrence of f
9317  pos != std::string::npos; // make sure f was found
9318  s.replace(pos, f.size(), t), // replace with t
9319  pos = s.find(f, pos + t.size()) // find next occurrence of f
9320  );
9321  }
9322 
9330  static void flatten(const std::string reference_string,
9331  const basic_json& value,
9332  basic_json& result)
9333  {
9334  switch (value.m_type)
9335  {
9336  case value_t::array:
9337  {
9338  if (value.m_value.array->empty())
9339  {
9340  // flatten empty array as null
9341  result[reference_string] = nullptr;
9342  }
9343  else
9344  {
9345  // iterate array and use index as reference string
9346  for (size_t i = 0; i < value.m_value.array->size(); ++i)
9347  {
9348  flatten(reference_string + "/" + std::to_string(i),
9349  value.m_value.array->operator[](i), result);
9350  }
9351  }
9352  break;
9353  }
9354 
9355  case value_t::object:
9356  {
9357  if (value.m_value.object->empty())
9358  {
9359  // flatten empty object as null
9360  result[reference_string] = nullptr;
9361  }
9362  else
9363  {
9364  // iterate object and use keys as reference string
9365  for (const auto& element : *value.m_value.object)
9366  {
9367  // escape "~"" to "~0" and "/" to "~1"
9368  std::string key(element.first);
9369  replace_substring(key, "~", "~0");
9370  replace_substring(key, "/", "~1");
9371 
9372  flatten(reference_string + "/" + key,
9373  element.second, result);
9374  }
9375  }
9376  break;
9377  }
9378 
9379  default:
9380  {
9381  // add primitive value with its reference string
9382  result[reference_string] = value;
9383  break;
9384  }
9385  }
9386  }
9387 
9393  static basic_json unflatten(const basic_json& value)
9394  {
9395  if (not value.is_object())
9396  {
9397  throw std::domain_error("only objects can be unflattened");
9398  }
9399 
9400  basic_json result;
9401 
9402  // iterate the JSON object values
9403  for (const auto& element : *value.m_value.object)
9404  {
9405  if (not element.second.is_primitive())
9406  {
9407  throw std::domain_error("values in object must be primitive");
9408  }
9409 
9410  // assign value to reference pointed to by JSON pointer;
9411  // Note that if the JSON pointer is "" (i.e., points to the
9412  // whole value), function get_and_create returns a reference
9413  // to result itself. An assignment will then create a
9414  // primitive value.
9415  json_pointer(element.first).get_and_create(result) = element.second;
9416  }
9417 
9418  return result;
9419  }
9420 
9421  private:
9423  const std::vector<std::string> reference_tokens {};
9424  };
9425 
9427  // JSON Pointer functions //
9429 
9432 
9455  basic_json flatten() const
9456  {
9457  basic_json result(value_t::object);
9458  json_pointer::flatten("", *this, result);
9459  return result;
9460  }
9461 
9489  basic_json unflatten() const
9490  {
9491  return json_pointer::unflatten(*this);
9492  }
9493 
9495 };
9496 
9497 
9499 // presets //
9501 
9511 }
9512 
9513 
9515 // nonmember functions //
9517 
9518 // specialization of std::swap, and std::hash
9519 namespace std
9520 {
9526 template <>
9527 inline void swap(nlohmann::json& j1,
9528  nlohmann::json& j2) noexcept(
9529  is_nothrow_move_constructible<nlohmann::json>::value and
9530  is_nothrow_move_assignable<nlohmann::json>::value
9531  )
9532 {
9533  j1.swap(j2);
9534 }
9535 
9537 template <>
9538 struct hash<nlohmann::json>
9539 {
9545  std::size_t operator()(const nlohmann::json& j) const
9546  {
9547  // a naive hashing via the string representation
9548  const auto& h = hash<nlohmann::json::string_t>();
9549  return h(j.dump());
9550  }
9551 };
9552 }
9553 
9566 inline nlohmann::json operator "" _json(const char* s, std::size_t)
9567 {
9568  return nlohmann::json::parse(reinterpret_cast<const nlohmann::json::string_t::value_type*>(s));
9569 }
9570 
9576 inline nlohmann::json::json_pointer operator "" _json_pointer(const char* s, std::size_t)
9577 {
9578  return nlohmann::json::json_pointer(s);
9579 }
9580 
9581 // restore GCC/clang diagnostic settings
9582 #if defined(__clang__) || defined(__GNUC__) || defined(__GNUG__)
9583  #pragma GCC diagnostic pop
9584 #endif
9585 
9586 #endif
const_iterator(pointer object) noexcept
constructor for a given JSON instance
Definition: json.hpp:6562
friend bool operator<=(const_reference lhs, const_reference rhs) noexcept
comparison: less than or equal
Definition: json.hpp:5697
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:4257
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:7202
json_reverse_iterator & operator--()
pre-decrement (–it)
Definition: json.hpp:7264
void clear() noexcept
clears the contents
Definition: json.hpp:4807
bool operator==(const const_iterator &other) const
comparison: equal
Definition: json.hpp:6852
json_reverse_iterator operator--(int)
post-decrement (it–)
Definition: json.hpp:7258
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:5910
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:4484
iterator & operator+=(difference_type i)
add to iterator
Definition: json.hpp:7160
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:6978
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:4338
reference operator+=(const typename object_t::value_type &val)
add an object to an object
Definition: json.hpp:4993
reference operator*() const
return a reference to the value pointed to by the iterator
Definition: json.hpp:7118
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:7300
iterator find(typename object_t::key_type key)
find an element in a JSON object
Definition: json.hpp:4209
friend bool operator!=(const_reference lhs, const_reference rhs) noexcept
comparison: not equal
Definition: json.hpp:5535
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:4919
void erase(const size_type idx)
remove element from a JSON array given an index
Definition: json.hpp:4163
basic_json<> json
default JSON class
Definition: json.hpp:9510
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:3820
reference at(const json_pointer &ptr)
access specified element via JSON Pointer
Definition: json.hpp:3683
void swap(object_t &other)
exchanges the values
Definition: json.hpp:5291
json_reverse_iterator operator-(difference_type i) const
subtract from iterator
Definition: json.hpp:7286
const_iterator & operator+=(difference_type i)
add to iterator
Definition: json.hpp:6936
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:7313
friend bool operator==(std::nullptr_t, const_reference v) noexcept
comparison: equal
Definition: json.hpp:5514
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:5077
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:6970
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:7085
static basic_json parse(std::istream &&i, parser_callback_t cb=nullptr)
deserialize from stream
Definition: json.hpp:5872
const_iterator operator++(int)
post-increment (it++)
Definition: json.hpp:6778
basic_json flatten() const
return flattened JSON value
Definition: json.hpp:9455
const_iterator cend() const noexcept
returns a const iterator to one past the last element
Definition: json.hpp:4409
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:4571
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:6548
json_reverse_iterator(const typename base_iterator::iterator_type &it) noexcept
create reverse iterator from iterator
Definition: json.hpp:7235
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:3862
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:6552
void push_back(const typename object_t::value_type &val)
add an object to an object
Definition: json.hpp:4969
json_pointer(const std::string &s="")
create JSON pointer
Definition: json.hpp:8968
static basic_json parse(const string_t &s, parser_callback_t cb=nullptr)
deserialize from string
Definition: json.hpp:5835
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:5130
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:7196
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:7278
bool empty() const noexcept
checks whether the container is empty
Definition: json.hpp:4619
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:7306
const_iterator(const iterator &other) noexcept
copy constructor given a nonconst iterator
Definition: json.hpp:6590
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:7230
const_reverse_iterator crbegin() const noexcept
returns a const reverse iterator to the last element
Definition: json.hpp:4513
const_reference at(const json_pointer &ptr) const
access specified element via JSON Pointer
Definition: json.hpp:3708
iterator insert(const_iterator pos, std::initializer_list< basic_json > ilist)
inserts elements
Definition: json.hpp:5188
const_reference operator[](const json_pointer &ptr) const
access specified element via JSON Pointer
Definition: json.hpp:3658
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:5021
friend bool operator>=(const_reference lhs, const_reference rhs) noexcept
comparison: greater than or equal
Definition: json.hpp:5741
friend bool operator<(const_reference lhs, const_reference rhs) noexcept
comparison: less than
Definition: json.hpp:5596
iterator & operator++()
pre-increment (++it)
Definition: json.hpp:7138
bool operator<(const const_iterator &other) const
comparison: smaller
Definition: json.hpp:6888
iterator operator++(int)
post-increment (it++)
Definition: json.hpp:7130
basic_json(basic_json &&other) noexcept
move constructor
Definition: json.hpp:2032
const_iterator operator--(int)
post-decrement (it–)
Definition: json.hpp:6815
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:7106
object (unordered set of name/value pairs)
size_type max_size() const noexcept
returns the maximum possible number of elements
Definition: json.hpp:4748
~basic_json()
destructor
Definition: json.hpp:2092
iterator operator--(int)
post-decrement (it–)
Definition: json.hpp:7145
iterator operator-(difference_type i)
subtract from iterator
Definition: json.hpp:7182
const_iterator & operator--()
pre-decrement (–it)
Definition: json.hpp:6823
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:4943
difference_type operator-(const const_iterator &other) const
return difference
Definition: json.hpp:6986
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:4447
friend std::ostream & operator>>(const basic_json &j, std::ostream &o)
serialize to stream
Definition: json.hpp:5796
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:4308
difference_type operator-(const iterator &other) const
return difference
Definition: json.hpp:7190
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:7101
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:6550
void swap(string_t &other)
exchanges the values
Definition: json.hpp:5325
basic_json(const CompatibleNumberIntegerType val) noexcept
create an integer number (implicit)
Definition: json.hpp:1410
reference operator[](const json_pointer &ptr)
access specified element via JSON Pointer
Definition: json.hpp:3631
const_reference front() const
access the first element
Definition: json.hpp:3828
bool operator>(const const_iterator &other) const
comparison: greater than
Definition: json.hpp:6924
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:6743
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:4542
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:5226
value_t
the JSON type enumeration
Definition: json.hpp:696
reverse_iterator rbegin() noexcept
returns an iterator to the reverse-beginning
Definition: json.hpp:4439
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:5257
InteratorType erase(InteratorType first, InteratorType last)
remove elements given an iterator range
Definition: json.hpp:4038
ValueType value(const typename object_t::key_type &key, ValueType default_value) const
access specified object element with default value
Definition: json.hpp:3765
typename Base::reference reference
the reference type for the pointed-to element
Definition: json.hpp:7232
const_reference back() const
access the last element
Definition: json.hpp:3872
void push_back(basic_json &&val)
add an object to an array
Definition: json.hpp:4883
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:7251
static basic_json parse(std::istream &i, parser_callback_t cb=nullptr)
deserialize from stream
Definition: json.hpp:5864
friend bool operator==(const_reference lhs, const_reference rhs) noexcept
comparison: equal
Definition: json.hpp:5406
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:3791
ReferenceType get_ref() const
get a reference value (implicit)
Definition: json.hpp:3021
basic_json unflatten() const
unflatten a previously flattened JSON value
Definition: json.hpp:9489
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:6703
friend bool operator<(const value_t lhs, const value_t rhs) noexcept
comparison operator for JSON types
Definition: json.hpp:5359
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:5558
iterator operator+(difference_type i)
add to iterator
Definition: json.hpp:7174
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:6918
InteratorType erase(InteratorType pos)
remove element given an iterator
Definition: json.hpp:3930
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:7096
friend bool operator!=(std::nullptr_t, const_reference v) noexcept
comparison: not equal
Definition: json.hpp:5567
constexpr bool is_primitive() const noexcept
return whether type is primitive
Definition: json.hpp:2225
const_iterator & operator++()
pre-increment (++it)
Definition: json.hpp:6786
pointer operator->() const
dereference the iterator
Definition: json.hpp:7124
reference value() const
return the value of an iterator
Definition: json.hpp:7061
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:6556
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:4369
reverse_iterator rend() noexcept
returns an iterator to the reverse-end
Definition: json.hpp:4476
difference_type operator-(const json_reverse_iterator &other) const
return difference
Definition: json.hpp:7294
const_iterator find(typename object_t::key_type key) const
find an element in a JSON object
Definition: json.hpp:4226
iterator begin() noexcept
returns an iterator to the first element
Definition: json.hpp:4298
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:4379
friend bool operator>(const_reference lhs, const_reference rhs) noexcept
comparison: greater than
Definition: json.hpp:5719
bool operator>=(const const_iterator &other) const
comparison: greater than or equal
Definition: json.hpp:6930
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:6623
size_type erase(const typename object_t::key_type &key)
remove element from a JSON object given a key
Definition: json.hpp:4125
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:7046
reference operator+=(basic_json &&val)
add an object to an array
Definition: json.hpp:4909
reference operator[](difference_type n) const
access to successor
Definition: json.hpp:7010
a const random access iterator for the basic_json class
Definition: json.hpp:6541
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:6554
json_reverse_iterator operator++(int)
post-increment (it++)
Definition: json.hpp:7245
friend bool operator==(const_reference v, std::nullptr_t) noexcept
comparison: equal
Definition: json.hpp:5505
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:6882
json_reverse_iterator & operator+=(difference_type i)
add to iterator
Definition: json.hpp:7271
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:4682
static iteration_proxy< iterator > iterator_wrapper(reference cont)
wrapper to access iterator member functions in range-based for
Definition: json.hpp:4563
iterator & operator-=(difference_type i)
subtract from iterator
Definition: json.hpp:7167
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:5900
std::size_t operator()(const nlohmann::json &j) const
return a hash value for a JSON object
Definition: json.hpp:9545
json_reverse_iterator(const base_iterator &it) noexcept
create reverse iterator from base class
Definition: json.hpp:7240
friend std::ostream & operator<<(std::ostream &o, const basic_json &j)
serialize to stream
Definition: json.hpp:5778
const_iterator(const const_iterator &other) noexcept
copy constructor
Definition: json.hpp:6618
iterator & operator--()
pre-decrement (–it)
Definition: json.hpp:7153
iterator insert(const_iterator pos, basic_json &&val)
inserts element
Definition: json.hpp:5048
ReferenceType get_ref()
get a reference value (implicit)
Definition: json.hpp:3006
const_iterator & operator-=(difference_type i)
subtract from iterator
Definition: json.hpp:6964
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