JSON for Modern C++ 1.0.0-rc1

- Main Page
- Classes

json.hpp
1
38 #ifndef NLOHMANN_JSON_HPP
39 #define NLOHMANN_JSON_HPP
40
41 #include <algorithm>
42 #include <array>
43 #include <ciso646>
44 #include <cmath>
45 #include <cstdio>
46 #include <functional>
47 #include <initializer_list>
48 #include <iomanip>
49 #include <iostream>
50 #include <iterator>
51 #include <limits>
52 #include <map>
53 #include <memory>
54 #include <sstream>
55 #include <string>
56 #include <type_traits>
57 #include <utility>
58 #include <vector>
59
60 // enable ssize_t on MinGW
61 #ifdef __GNUC__
62 #ifdef __MINGW32__
63 #include <sys/types.h>
64 #endif
65 #endif
66
67 // enable ssize_t for MSVC
68 #ifdef _MSC_VER
69 #include <basetsd.h>
70 using ssize_t = SSIZE_T;
71 #endif
72
78 namespace nlohmann
79 {
80
81
86 namespace
87 {
92 template<typename T>
93 struct has_mapped_type
94 {
95 private:
96 template<typename C> static char test(typename C::mapped_type*);
97 template<typename C> static int test(...);
98 public:
99 enum { value = sizeof(test<T>(0)) == sizeof(char) };
100 };
101
103 template<typename T>
104 static bool approx(const T a, const T b)
105 {
106 return not (a > b or a < b);
107 }
108 }
109
178 template <
179 template<typename U, typename V, typename... Args> class ObjectType = std::map,
180 template<typename U, typename... Args> class ArrayType = std::vector,
181 class StringType = std::string,
182 class BooleanType = bool,
183 class NumberIntegerType = int64_t,
184 class NumberFloatType = double,
185 template<typename U> class AllocatorType = std::allocator
186 >
187 class basic_json
188 {
189 private:
191 using basic_json_t = basic_json<ObjectType,
192 ArrayType,
193 StringType,
194 BooleanType,
195 NumberIntegerType,
196 NumberFloatType,
197 AllocatorType>;
198
199 public:
200
202 // container types //
204
207
209 using value_type = basic_json;
210
212 using reference = value_type&;
213
215 using const_reference = const value_type&;
216
218 using difference_type = std::ptrdiff_t;
219
221 using size_type = std::size_t;
222
224 using allocator_type = AllocatorType<basic_json>;
225
227 using pointer = typename std::allocator_traits<allocator_type>::pointer;
229 using const_pointer = typename std::allocator_traits<allocator_type>::const_pointer;
230
231 // forward declaration
232 template<typename Base> class json_reverse_iterator;
233
235 class iterator;
237 class const_iterator;
239 using reverse_iterator = json_reverse_iterator<typename basic_json::iterator>;
241 using const_reverse_iterator = json_reverse_iterator<typename basic_json::const_iterator>;
242
244
245
249 static allocator_type get_allocator()
250 {
251 return allocator_type();
252 }
253
254
256 // JSON value data types //
258
261
336 using object_t = ObjectType<StringType,
337 basic_json,
338 std::less<StringType>,
339 AllocatorType<std::pair<const StringType,
340 basic_json>>>;
341
386 using array_t = ArrayType<basic_json, AllocatorType<basic_json>>;
387
433 using string_t = StringType;
434
459 using boolean_t = BooleanType;
460
527 using number_integer_t = NumberIntegerType;
528
592 using number_float_t = NumberFloatType;
593
595
596
598 // JSON type enumeration //
600
611 enum class value_t : uint8_t
612 {
613 null,
614 object,
615 array,
616 string,
617 boolean,
618 number_integer,
619 number_float,
620 discarded
621 };
622
623
624 private:
626 template<typename T, typename... Args>
627 static T* create(Args&& ... args)
628 {
629 AllocatorType<T> alloc;
630 auto deleter = [&](T * object)
631 {
632 alloc.deallocate(object, 1);
633 };
634 std::unique_ptr<T, decltype(deleter)> object(alloc.allocate(1), deleter);
635 alloc.construct(object.get(), std::forward<Args>(args)...);
636 return object.release();
637 }
638
640 // JSON value storage //
642
650 union json_value
651 {
653 object_t* object;
655 array_t* array;
657 string_t* string;
659 boolean_t boolean;
661 number_integer_t number_integer;
663 number_float_t number_float;
664
666 json_value() noexcept = default;
668 json_value(boolean_t v) noexcept : boolean(v) {}
670 json_value(number_integer_t v) noexcept : number_integer(v) {}
672 json_value(number_float_t v) noexcept : number_float(v) {}
674 json_value(value_t t)
675 {
676 switch (t)
677 {
678 case value_t::object:
679 {
680 object = create<object_t>();
681 break;
682 }
683
684 case value_t::array:
685 {
686 array = create<array_t>();
687 break;
688 }
689
690 case value_t::string:
691 {
692 string = create<string_t>("");
693 break;
694 }
695
696 case value_t::boolean:
697 {
698 boolean = boolean_t(false);
699 break;
700 }
701
702 case value_t::number_integer:
703 {
704 number_integer = number_integer_t(0);
705 break;
706 }
707
708 case value_t::number_float:
709 {
710 number_float = number_float_t(0.0);
711 break;
712 }
713
714 default:
715 {
716 break;
717 }
718 }
719 }
720
722 json_value(const string_t& value)
723 {
724 string = create<string_t>(value);
725 }
726
728 json_value(const object_t& value)
729 {
730 object = create<object_t>(value);
731 }
732
734 json_value(const array_t& value)
735 {
736 array = create<array_t>(value);
737 }
738 };
739
740
741 public:
743 // JSON parser callback //
745
754 enum class parse_event_t : uint8_t
755 {
757 object_start,
759 object_end,
761 array_start,
763 array_end,
765 key,
767 value
768 };
769
819 using parser_callback_t = std::function<bool(int depth, parse_event_t event, basic_json& parsed)>;
820
821
823 // constructors //
825
828
866 basic_json(const value_t value)
867 : m_type(value), m_value(value)
868 {}
869
889 basic_json() noexcept = default;
890
910 basic_json(std::nullptr_t) noexcept
911 : basic_json(value_t::null)
912 {}
913
933 basic_json(const object_t& value)
934 : m_type(value_t::object), m_value(value)
935 {}
936
960 template <class CompatibleObjectType, typename
961 std::enable_if<
962 std::is_constructible<typename object_t::key_type, typename CompatibleObjectType::key_type>::value and
963 std::is_constructible<basic_json, typename CompatibleObjectType::mapped_type>::value, int>::type
964 = 0>
965 basic_json(const CompatibleObjectType& value)
966 : m_type(value_t::object)
967 {
968 using std::begin;
969 using std::end;
970 m_value.object = create<object_t>(begin(value), end(value));
971 }
972
992 basic_json(const array_t& value)
993 : m_type(value_t::array), m_value(value)
994 {}
995
1019 template <class CompatibleArrayType, typename
1020 std::enable_if<
1021 not std::is_same<CompatibleArrayType, typename basic_json_t::iterator>::value and
1022 not std::is_same<CompatibleArrayType, typename basic_json_t::const_iterator>::value and
1023 not std::is_same<CompatibleArrayType, typename basic_json_t::reverse_iterator>::value and
1024 not std::is_same<CompatibleArrayType, typename basic_json_t::const_reverse_iterator>::value and
1025 not std::is_same<CompatibleArrayType, typename array_t::iterator>::value and
1026 not std::is_same<CompatibleArrayType, typename array_t::const_iterator>::value and
1027 std::is_constructible<basic_json, typename CompatibleArrayType::value_type>::value, int>::type
1028 = 0>
1029 basic_json(const CompatibleArrayType& value)
1030 : m_type(value_t::array)
1031 {
1032 using std::begin;
1033 using std::end;
1034 m_value.array = create<array_t>(begin(value), end(value));
1035 }
1036
1058 basic_json(const string_t& value)
1059 : m_type(value_t::string), m_value(value)
1060 {}
1061
1082 basic_json(const typename string_t::value_type* value)
1083 : basic_json(string_t(value))
1084 {}
1085
1109 template <class CompatibleStringType, typename
1110 std::enable_if<
1111 std::is_constructible<string_t, CompatibleStringType>::value, int>::type
1112 = 0>
1113 basic_json(const CompatibleStringType& value)
1114 : basic_json(string_t(value))
1115 {}
1116
1131 basic_json(boolean_t value)
1132 : m_type(value_t::boolean), m_value(value)
1133 {}
1134
1160 template<typename T,
1161 typename std::enable_if<
1162 not (std::is_same<T, int>::value)
1163 and std::is_same<T, number_integer_t>::value
1164 , int>::type = 0>
1165 basic_json(const number_integer_t value)
1166 : m_type(value_t::number_integer), m_value(value)
1167 {}
1168
1194 basic_json(const int value)
1195 : m_type(value_t::number_integer),
1196 m_value(static_cast<number_integer_t>(value))
1197 {}
1198
1224 template<typename CompatibleNumberIntegerType, typename
1225 std::enable_if<
1226 std::is_constructible<number_integer_t, CompatibleNumberIntegerType>::value and
1227 std::numeric_limits<CompatibleNumberIntegerType>::is_integer, CompatibleNumberIntegerType>::type
1228 = 0>
1229 basic_json(const CompatibleNumberIntegerType value) noexcept
1230 : m_type(value_t::number_integer),
1231 m_value(static_cast<number_integer_t>(value))
1232 {}
1233
1258 basic_json(const number_float_t value)
1259 : m_type(value_t::number_float), m_value(value)
1260 {
1261 // replace infinity and NAN by null
1262 if (not std::isfinite(value))
1263 {
1264 m_type = value_t::null;
1265 m_value = json_value();
1266 }
1267 }
1268
1299 template<typename CompatibleNumberFloatType, typename = typename
1300 std::enable_if<
1301 std::is_constructible<number_float_t, CompatibleNumberFloatType>::value and
1302 std::is_floating_point<CompatibleNumberFloatType>::value>::type
1303 >
1304 basic_json(const CompatibleNumberFloatType value) noexcept
1305 : basic_json(number_float_t(value))
1306 {}
1307
1376 basic_json(std::initializer_list<basic_json> init,
1377 bool type_deduction = true,
1378 value_t manual_type = value_t::array)
1379 {
1380 // the initializer list could describe an object
1381 bool is_object = true;
1382
1383 // check if each element is an array with two elements whose first
1384 // element is a string
1385 for (const auto& element : init)
1386 {
1387 if (not element.is_array() or element.size() != 2
1388 or not element[0].is_string())
1389 {
1390 // we found an element that makes it impossible to use the
1391 // initializer list as object
1392 is_object = false;
1393 break;
1394 }
1395 }
1396
1397 // adjust type if type deduction is not wanted
1398 if (not type_deduction)
1399 {
1400 // if array is wanted, do not create an object though possible
1401 if (manual_type == value_t::array)
1402 {
1403 is_object = false;
1404 }
1405
1406 // if object is wanted but impossible, throw an exception
1407 if (manual_type == value_t::object and not is_object)
1408 {
1409 throw std::domain_error("cannot create object from initializer list");
1410 }
1411 }
1412
1413 if (is_object)
1414 {
1415 // the initializer list is a list of pairs -> create object
1416 m_type = value_t::object;
1417 m_value = value_t::object;
1418
1419 for (auto& element : init)
1420 {
1421 m_value.object->emplace(std::move(*(element[0].m_value.string)), std::move(element[1]));
1422 }
1423 }
1424 else
1425 {
1426 // the initializer list describes an array -> create array
1427 m_type = value_t::array;
1428 m_value.array = create<array_t>(std::move(init));
1429 }
1430 }
1431
1466 static basic_json array(std::initializer_list<basic_json> init =
1467 std::initializer_list<basic_json>())
1468 {
1469 return basic_json(init, false, value_t::array);
1470 }
1471
1506 static basic_json object(std::initializer_list<basic_json> init =
1507 std::initializer_list<basic_json>())
1508 {
1509 return basic_json(init, false, value_t::object);
1510 }
1511
1530 basic_json(size_type count, const basic_json& value)
1531 : m_type(value_t::array)
1532 {
1533 m_value.array = create<array_t>(count, value);
1534 }
1535
1568 template <class InputIT, typename
1569 std::enable_if<
1570 std::is_same<InputIT, typename basic_json_t::iterator>::value or
1571 std::is_same<InputIT, typename basic_json_t::const_iterator>::value
1572 , int>::type
1573 = 0>
1574 basic_json(InputIT first, InputIT last) : m_type(first.m_object->m_type)
1575 {
1576 // make sure iterator fits the current value
1577 if (first.m_object != last.m_object)
1578 {
1579 throw std::domain_error("iterators are not compatible");
1580 }
1581
1582 // check if iterator range is complete for primitive values
1583 switch (m_type)
1584 {
1585 case value_t::boolean:
1586 case value_t::number_float:
1587 case value_t::number_integer:
1588 case value_t::string:
1589 {
1590 if (not first.m_it.primitive_iterator.is_begin() or not last.m_it.primitive_iterator.is_end())
1591 {
1592 throw std::out_of_range("iterators out of range");
1593 }
1594 break;
1595 }
1596
1597 default:
1598 {
1599 break;
1600 }
1601 }
1602
1603 switch (m_type)
1604 {
1605 case value_t::number_integer:
1606 {
1607 m_value.number_integer = first.m_object->m_value.number_integer;
1608 break;
1609 }
1610
1611 case value_t::number_float:
1612 {
1613 m_value.number_float = first.m_object->m_value.number_float;
1614 break;
1615 }
1616
1617 case value_t::boolean:
1618 {
1619 m_value.boolean = first.m_object->m_value.boolean;
1620 break;
1621 }
1622
1623 case value_t::string:
1624 {
1625 m_value = *first.m_object->m_value.string;
1626 break;
1627 }
1628
1629 case value_t::object:
1630 {
1631 m_value.object = create<object_t>(first.m_it.object_iterator, last.m_it.object_iterator);
1632 break;
1633 }
1634
1635 case value_t::array:
1636 {
1637 m_value.array = create<array_t>(first.m_it.array_iterator, last.m_it.array_iterator);
1638 break;
1639 }
1640
1641 default:
1642 {
1643 throw std::domain_error("cannot use construct with iterators from " + first.m_object->type_name());
1644 }
1645 }
1646 }
1647
1649 // other constructors and destructor //
1651
1672 basic_json(const basic_json& other)
1673 : m_type(other.m_type)
1674 {
1675 switch (m_type)
1676 {
1677 case value_t::object:
1678 {
1679 m_value = *other.m_value.object;
1680 break;
1681 }
1682
1683 case value_t::array:
1684 {
1685 m_value = *other.m_value.array;
1686 break;
1687 }
1688
1689 case value_t::string:
1690 {
1691 m_value = *other.m_value.string;
1692 break;
1693 }
1694
1695 case value_t::boolean:
1696 {
1697 m_value = other.m_value.boolean;
1698 break;
1699 }
1700
1701 case value_t::number_integer:
1702 {
1703 m_value = other.m_value.number_integer;
1704 break;
1705 }
1706
1707 case value_t::number_float:
1708 {
1709 m_value = other.m_value.number_float;
1710 break;
1711 }
1712
1713 default:
1714 {
1715 break;
1716 }
1717 }
1718 }
1719
1738 basic_json(basic_json&& other) noexcept
1739 : m_type(std::move(other.m_type)),
1740 m_value(std::move(other.m_value))
1741 {
1742 // invalidate payload
1743 other.m_type = value_t::null;
1744 other.m_value = {};
1745 }
1746
1768 reference& operator=(basic_json other) noexcept (
1769 std::is_nothrow_move_constructible<value_t>::value and
1770 std::is_nothrow_move_assignable<value_t>::value and
1771 std::is_nothrow_move_constructible<json_value>::value and
1772 std::is_nothrow_move_assignable<json_value>::value
1773 )
1774 {
1775 using std::swap;
1776 swap(m_type, other.m_type);
1777 swap(m_value, other.m_value);
1778 return *this;
1779 }
1780
1794 ~basic_json()
1795 {
1796 switch (m_type)
1797 {
1798 case value_t::object:
1799 {
1800 AllocatorType<object_t> alloc;
1801 alloc.destroy(m_value.object);
1802 alloc.deallocate(m_value.object, 1);
1803 break;
1804 }
1805
1806 case value_t::array:
1807 {
1808 AllocatorType<array_t> alloc;
1809 alloc.destroy(m_value.array);
1810 alloc.deallocate(m_value.array, 1);
1811 break;
1812 }
1813
1814 case value_t::string:
1815 {
1816 AllocatorType<string_t> alloc;
1817 alloc.destroy(m_value.string);
1818 alloc.deallocate(m_value.string, 1);
1819 break;
1820 }
1821
1822 default:
1823 {
1824 // all other types need no specific destructor
1825 break;
1826 }
1827 }
1828 }
1829
1831
1832 public:
1834 // object inspection //
1836
1839
1863 string_t dump(const int indent = -1) const
1864 {
1865 std::stringstream ss;
1866
1867 if (indent >= 0)
1868 {
1869 dump(ss, true, static_cast<unsigned int>(indent));
1870 }
1871 else
1872 {
1873 dump(ss, false, 0);
1874 }
1875
1876 return ss.str();
1877 }
1878
1894 value_t type() const noexcept
1895 {
1896 return m_type;
1897 }
1898
1915 bool is_primitive() const noexcept
1916 {
1917 return is_null() or is_string() or is_boolean() or is_number();
1918 }
1919
1935 bool is_structured() const noexcept
1936 {
1937 return is_array() or is_object();
1938 }
1939
1954 bool is_null() const noexcept
1955 {
1956 return m_type == value_t::null;
1957 }
1958
1973 bool is_boolean() const noexcept
1974 {
1975 return m_type == value_t::boolean;
1976 }
1977
1997 bool is_number() const noexcept
1998 {
1999 return is_number_integer() or is_number_float();
2000 }
2001
2020 bool is_number_integer() const noexcept
2021 {
2022 return m_type == value_t::number_integer;
2023 }
2024
2043 bool is_number_float() const noexcept
2044 {
2045 return m_type == value_t::number_float;
2046 }
2047
2062 bool is_object() const noexcept
2063 {
2064 return m_type == value_t::object;
2065 }
2066
2081 bool is_array() const noexcept
2082 {
2083 return m_type == value_t::array;
2084 }
2085
2100 bool is_string() const noexcept
2101 {
2102 return m_type == value_t::string;
2103 }
2104
2124 bool is_discarded() const noexcept
2125 {
2126 return m_type == value_t::discarded;
2127 }
2128
2144 operator value_t() const noexcept
2145 {
2146 return m_type;
2147 }
2148
2150
2151 private:
2153 // value access //
2155
2157 template <class T, typename
2158 std::enable_if<
2159 std::is_convertible<typename object_t::key_type, typename T::key_type>::value and
2160 std::is_convertible<basic_json_t, typename T::mapped_type>::value
2161 , int>::type = 0>
2162 T get_impl(T*) const
2163 {
2164 return is_object()
2165 ? T(m_value.object->begin(), m_value.object->end())
2166 : throw std::domain_error("type must be object, but is " + type_name());
2167 }
2168
2170 object_t get_impl(object_t*) const
2171 {
2172 return is_object()
2173 ? *(m_value.object)
2174 : throw std::domain_error("type must be object, but is " + type_name());
2175 }
2176
2178 template <class T, typename
2179 std::enable_if<
2180 std::is_convertible<basic_json_t, typename T::value_type>::value and
2181 not std::is_same<basic_json_t, typename T::value_type>::value and
2182 not std::is_arithmetic<T>::value and
2183 not std::is_convertible<std::string, T>::value and
2184 not has_mapped_type<T>::value
2185 , int>::type = 0>
2186 T get_impl(T*) const
2187 {
2188 if (is_array())
2189 {
2190 T to_vector;
2191 std::transform(m_value.array->begin(), m_value.array->end(),
2192 std::inserter(to_vector, to_vector.end()), [](basic_json i)
2193 {
2194 return i.get<typename T::value_type>();
2195 });
2196 return to_vector;
2197 }
2198 else
2199 {
2200 throw std::domain_error("type must be array, but is " + type_name());
2201 }
2202 }
2203
2205 template <class T, typename
2206 std::enable_if<
2207 std::is_convertible<basic_json_t, T>::value and
2208 not std::is_same<basic_json_t, T>::value
2209 , int>::type = 0>
2210 std::vector<T> get_impl(std::vector<T>*) const
2211 {
2212 if (is_array())
2213 {
2214 std::vector<T> to_vector;
2215 to_vector.reserve(m_value.array->size());
2216 std::transform(m_value.array->begin(), m_value.array->end(),
2217 std::inserter(to_vector, to_vector.end()), [](basic_json i)
2218 {
2219 return i.get<T>();
2220 });
2221 return to_vector;
2222 }
2223 else
2224 {
2225 throw std::domain_error("type must be array, but is " + type_name());
2226 }
2227 }
2228
2230 template <class T, typename
2231 std::enable_if<
2232 std::is_same<basic_json, typename T::value_type>::value and
2233 not has_mapped_type<T>::value
2234 , int>::type = 0>
2235 T get_impl(T*) const
2236 {
2237 return is_array()
2238 ? T(m_value.array->begin(), m_value.array->end())
2239 : throw std::domain_error("type must be array, but is " + type_name());
2240 }
2241
2243 array_t get_impl(array_t*) const
2244 {
2245 return is_array()
2246 ? *(m_value.array)
2247 : throw std::domain_error("type must be array, but is " + type_name());
2248 }
2249
2251 template <typename T, typename
2252 std::enable_if<
2253 std::is_convertible<string_t, T>::value
2254 , int>::type = 0>
2255 T get_impl(T*) const
2256 {
2257 return is_string()
2258 ? *m_value.string
2259 : throw std::domain_error("type must be string, but is " + type_name());
2260 }
2261
2263 template<typename T, typename
2264 std::enable_if<
2265 std::is_arithmetic<T>::value
2266 , int>::type = 0>
2267 T get_impl(T*) const
2268 {
2269 switch (m_type)
2270 {
2271 case value_t::number_integer:
2272 {
2273 return static_cast<T>(m_value.number_integer);
2274 }
2275
2276 case value_t::number_float:
2277 {
2278 return static_cast<T>(m_value.number_float);
2279 }
2280
2281 default:
2282 {
2283 throw std::domain_error("type must be number, but is " + type_name());
2284 }
2285 }
2286 }
2287
2289 boolean_t get_impl(boolean_t*) const
2290 {
2291 return is_boolean()
2292 ? m_value.boolean
2293 : throw std::domain_error("type must be boolean, but is " + type_name());
2294 }
2295
2297 object_t* get_impl_ptr(object_t*) noexcept
2298 {
2299 return is_object() ? m_value.object : nullptr;
2300 }
2301
2303 const object_t* get_impl_ptr(const object_t*) const noexcept
2304 {
2305 return is_object() ? m_value.object : nullptr;
2306 }
2307
2309 array_t* get_impl_ptr(array_t*) noexcept
2310 {
2311 return is_array() ? m_value.array : nullptr;
2312 }
2313
2315 const array_t* get_impl_ptr(const array_t*) const noexcept
2316 {
2317 return is_array() ? m_value.array : nullptr;
2318 }
2319
2321 string_t* get_impl_ptr(string_t*) noexcept
2322 {
2323 return is_string() ? m_value.string : nullptr;
2324 }
2325
2327 const string_t* get_impl_ptr(const string_t*) const noexcept
2328 {
2329 return is_string() ? m_value.string : nullptr;
2330 }
2331
2333 boolean_t* get_impl_ptr(boolean_t*) noexcept
2334 {
2335 return is_boolean() ? &m_value.boolean : nullptr;
2336 }
2337
2339 const boolean_t* get_impl_ptr(const boolean_t*) const noexcept
2340 {
2341 return is_boolean() ? &m_value.boolean : nullptr;
2342 }
2343
2345 number_integer_t* get_impl_ptr(number_integer_t*) noexcept
2346 {
2347 return is_number_integer() ? &m_value.number_integer : nullptr;
2348 }
2349
2351 const number_integer_t* get_impl_ptr(const number_integer_t*) const noexcept
2352 {
2353 return is_number_integer() ? &m_value.number_integer : nullptr;
2354 }
2355
2357 number_float_t* get_impl_ptr(number_float_t*) noexcept
2358 {
2359 return is_number_float() ? &m_value.number_float : nullptr;
2360 }
2361
2363 const number_float_t* get_impl_ptr(const number_float_t*) const noexcept
2364 {
2365 return is_number_float() ? &m_value.number_float : nullptr;
2366 }
2367
2368 public:
2369
2372
2406 template<typename ValueType, typename
2407 std::enable_if<
2408 not std::is_pointer<ValueType>::value
2409 , int>::type = 0>
2410 ValueType get() const
2411 {
2412 return get_impl(static_cast<ValueType*>(nullptr));
2413 }
2414
2441 template<typename PointerType, typename
2442 std::enable_if<
2443 std::is_pointer<PointerType>::value
2444 , int>::type = 0>
2445 PointerType get() noexcept
2446 {
2447 // delegate the call to get_ptr
2448 return get_ptr<PointerType>();
2449 }
2450
2455 template<typename PointerType, typename
2456 std::enable_if<
2457 std::is_pointer<PointerType>::value
2458 , int>::type = 0>
2459 const PointerType get() const noexcept
2460 {
2461 // delegate the call to get_ptr
2462 return get_ptr<PointerType>();
2463 }
2464
2490 template<typename PointerType, typename
2491 std::enable_if<
2492 std::is_pointer<PointerType>::value
2493 , int>::type = 0>
2494 PointerType get_ptr() noexcept
2495 {
2496 // delegate the call to get_impl_ptr<>()
2497 return get_impl_ptr(static_cast<PointerType>(nullptr));
2498 }
2499
2504 template<typename PointerType, typename
2505 std::enable_if<
2506 std::is_pointer<PointerType>::value
2507 and std::is_const<typename std::remove_pointer<PointerType>::type>::value
2508 , int>::type = 0>
2509 const PointerType get_ptr() const noexcept
2510 {
2511 // delegate the call to get_impl_ptr<>() const
2512 return get_impl_ptr(static_cast<const PointerType>(nullptr));
2513 }
2514
2541 template<typename ValueType, typename
2542 std::enable_if<
2543 not std::is_pointer<ValueType>::value
2544 , int>::type = 0>
2545 operator ValueType() const
2546 {
2547 // delegate the call to get<>() const
2548 return get<ValueType>();
2549 }
2550
2552
2553
2555 // element access //
2557
2560
2582 reference at(size_type idx)
2583 {
2584 // at only works for arrays
2585 return is_array()
2586 ? m_value.array->at(idx)
2587 : throw std::domain_error("cannot use at() with " + type_name());
2588 }
2589
2611 const_reference at(size_type idx) const
2612 {
2613 // at only works for arrays
2614 return is_array()
2615 ? m_value.array->at(idx)
2616 : throw std::domain_error("cannot use at() with " + type_name());
2617 }
2618
2644 reference at(const typename object_t::key_type& key)
2645 {
2646 // at only works for objects
2647 return is_object()
2648 ? m_value.object->at(key)
2649 : throw std::domain_error("cannot use at() with " + type_name());
2650 }
2651
2677 const_reference at(const typename object_t::key_type& key) const
2678 {
2679 // at only works for objects
2680 return is_object()
2681 ? m_value.object->at(key)
2682 : throw std::domain_error("cannot use at() with " + type_name());
2683 }
2684
2709 reference operator[](size_type idx)
2710 {
2711 // implicitly convert null to object
2712 if (is_null())
2713 {
2714 m_type = value_t::array;
2715 m_value.array = create<array_t>();
2716 }
2717
2718 // [] only works for arrays
2719 if (is_array())
2720 {
2721 for (size_t i = m_value.array->size(); i <= idx; ++i)
2722 {
2723 m_value.array->push_back(basic_json());
2724 }
2725
2726 return m_value.array->operator[](idx);
2727 }
2728 else
2729 {
2730 throw std::domain_error("cannot use operator[] with " + type_name());
2731 }
2732 }
2733
2752 const_reference operator[](size_type idx) const
2753 {
2754 // at only works for arrays
2755 return is_array()
2756 ? m_value.array->operator[](idx)
2757 : throw std::domain_error("cannot use operator[] with " + type_name());
2758 }
2759
2786 reference operator[](const typename object_t::key_type& key)
2787 {
2788 // implicitly convert null to object
2789 if (is_null())
2790 {
2791 m_type = value_t::object;
2792 m_value.object = create<object_t>();
2793 }
2794
2795 // [] only works for objects
2796 return is_object()
2797 ? m_value.object->operator[](key)
2798 : throw std::domain_error("cannot use operator[] with " + type_name());
2799 }
2800
2829 template<typename T, std::size_t n>
2830 reference operator[](const T (&key)[n])
2831 {
2832 // implicitly convert null to object
2833 if (is_null())
2834 {
2835 m_type = value_t::object;
2836 m_value = value_t::object;
2837 }
2838
2839 // at only works for objects
2840 return is_object()
2841 ? m_value.object->operator[](key)
2842 : throw std::domain_error("cannot use operator[] with " + type_name());
2843 }
2844
2892 template <class ValueType, typename
2893 std::enable_if<
2894 std::is_convertible<basic_json_t, ValueType>::value
2895 , int>::type = 0>
2896 ValueType value(const typename object_t::key_type& key, ValueType default_value) const
2897 {
2898 // at only works for objects
2899 if (is_object())
2900 {
2901 // if key is found, return value and given default value otherwise
2902 const auto it = find(key);
2903 if (it != end())
2904 {
2905 return *it;
2906 }
2907 else
2908 {
2909 return default_value;
2910 }
2911 }
2912 else
2913 {
2914 throw std::domain_error("cannot use value() with " + type_name());
2915 }
2916 }
2917
2922 string_t value(const typename object_t::key_type& key, const char* default_value) const
2923 {
2924 return value(key, string_t(default_value));
2925 }
2926
2947 reference front()
2948 {
2949 return *begin();
2950 }
2951
2955 const_reference front() const
2956 {
2957 return *cbegin();
2958 }
2959
2981 reference back()
2982 {
2983 auto tmp = end();
2984 --tmp;
2985 return *tmp;
2986 }
2987
2991 const_reference back() const
2992 {
2993 auto tmp = cend();
2994 --tmp;
2995 return *tmp;
2996 }
2997
3040 template <class InteratorType, typename
3041 std::enable_if<
3042 std::is_same<InteratorType, typename basic_json_t::iterator>::value or
3043 std::is_same<InteratorType, typename basic_json_t::const_iterator>::value
3044 , int>::type
3045 = 0>
3046 InteratorType erase(InteratorType pos)
3047 {
3048 // make sure iterator fits the current value
3049 if (this != pos.m_object)
3050 {
3051 throw std::domain_error("iterator does not fit current value");
3052 }
3053
3054 InteratorType result = end();
3055
3056 switch (m_type)
3057 {
3058 case value_t::boolean:
3059 case value_t::number_float:
3060 case value_t::number_integer:
3061 case value_t::string:
3062 {
3063 if (not pos.m_it.primitive_iterator.is_begin())
3064 {
3065 throw std::out_of_range("iterator out of range");
3066 }
3067
3068 if (is_string())
3069 {
3070 delete m_value.string;
3071 m_value.string = nullptr;
3072 }
3073
3074 m_type = value_t::null;
3075 break;
3076 }
3077
3078 case value_t::object:
3079 {
3080 result.m_it.object_iterator = m_value.object->erase(pos.m_it.object_iterator);
3081 break;
3082 }
3083
3084 case value_t::array:
3085 {
3086 result.m_it.array_iterator = m_value.array->erase(pos.m_it.array_iterator);
3087 break;
3088 }
3089
3090 default:
3091 {
3092 throw std::domain_error("cannot use erase() with " + type_name());
3093 }
3094 }
3095
3096 return result;
3097 }
3098
3141 template <class InteratorType, typename
3142 std::enable_if<
3143 std::is_same<InteratorType, typename basic_json_t::iterator>::value or
3144 std::is_same<InteratorType, typename basic_json_t::const_iterator>::value
3145 , int>::type
3146 = 0>
3147 InteratorType erase(InteratorType first, InteratorType last)
3148 {
3149 // make sure iterator fits the current value
3150 if (this != first.m_object or this != last.m_object)
3151 {
3152 throw std::domain_error("iterators do not fit current value");
3153 }
3154
3155 InteratorType result = end();
3156
3157 switch (m_type)
3158 {
3159 case value_t::boolean:
3160 case value_t::number_float:
3161 case value_t::number_integer:
3162 case value_t::string:
3163 {
3164 if (not first.m_it.primitive_iterator.is_begin() or not last.m_it.primitive_iterator.is_end())
3165 {
3166 throw std::out_of_range("iterators out of range");
3167 }
3168
3169 if (is_string())
3170 {
3171 delete m_value.string;
3172 m_value.string = nullptr;
3173 }
3174
3175 m_type = value_t::null;
3176 break;
3177 }
3178
3179 case value_t::object:
3180 {
3181 result.m_it.object_iterator = m_value.object->erase(first.m_it.object_iterator,
3182 last.m_it.object_iterator);
3183 break;
3184 }
3185
3186 case value_t::array:
3187 {
3188 result.m_it.array_iterator = m_value.array->erase(first.m_it.array_iterator,
3189 last.m_it.array_iterator);
3190 break;
3191 }
3192
3193 default:
3194 {
3195 throw std::domain_error("cannot use erase with " + type_name());
3196 }
3197 }
3198
3199 return result;
3200 }
3201
3227 size_type erase(const typename object_t::key_type& key)
3228 {
3229 // this erase only works for objects
3230 return is_object()
3231 ? m_value.object->erase(key)
3232 : throw std::domain_error("cannot use erase() with " + type_name());
3233 }
3234
3257 void erase(const size_type idx)
3258 {
3259 // this erase only works for arrays
3260 if (is_array())
3261 {
3262 if (idx >= size())
3263 {
3264 throw std::out_of_range("index out of range");
3265 }
3266
3267 m_value.array->erase(m_value.array->begin() + static_cast<difference_type>(idx));
3268 }
3269 else
3270 {
3271 throw std::domain_error("cannot use erase() with " + type_name());
3272 }
3273 }
3274
3292 iterator find(typename object_t::key_type key)
3293 {
3294 auto result = end();
3295
3296 if (is_object())
3297 {
3298 result.m_it.object_iterator = m_value.object->find(key);
3299 }
3300
3301 return result;
3302 }
3303
3308 const_iterator find(typename object_t::key_type key) const
3309 {
3310 auto result = cend();
3311
3312 if (is_object())
3313 {
3314 result.m_it.object_iterator = m_value.object->find(key);
3315 }
3316
3317 return result;
3318 }
3319
3338 size_type count(typename object_t::key_type key) const
3339 {
3340 // return 0 for all nonobject types
3341 return is_object() ? m_value.object->count(key) : 0;
3342 }
3343
3345
3346
3348 // iterators //
3350
3353
3372 iterator begin()
3373 {
3374 iterator result(this);
3375 result.set_begin();
3376 return result;
3377 }
3378
3382 const_iterator begin() const
3383 {
3384 return cbegin();
3385 }
3386
3406 const_iterator cbegin() const
3407 {
3408 const_iterator result(this);
3409 result.set_begin();
3410 return result;
3411 }
3412
3431 iterator end()
3432 {
3433 iterator result(this);
3434 result.set_end();
3435 return result;
3436 }
3437
3441 const_iterator end() const
3442 {
3443 return cend();
3444 }
3445
3465 const_iterator cend() const
3466 {
3467 const_iterator result(this);
3468 result.set_end();
3469 return result;
3470 }
3471
3489 reverse_iterator rbegin()
3490 {
3491 return reverse_iterator(end());
3492 }
3493
3497 const_reverse_iterator rbegin() const
3498 {
3499 return crbegin();
3500 }
3501
3520 reverse_iterator rend()
3521 {
3522 return reverse_iterator(begin());
3523 }
3524
3528 const_reverse_iterator rend() const
3529 {
3530 return crend();
3531 }
3532
3551 const_reverse_iterator crbegin() const
3552 {
3553 return const_reverse_iterator(cend());
3554 }
3555
3574 const_reverse_iterator crend() const
3575 {
3576 return const_reverse_iterator(cbegin());
3577 }
3578
3580
3581
3583 // capacity //
3585
3588
3618 bool empty() const noexcept
3619 {
3620 switch (m_type)
3621 {
3622 case value_t::null:
3623 {
3624 // null values are empty
3625 return true;
3626 }
3627
3628 case value_t::array:
3629 {
3630 return m_value.array->empty();
3631 }
3632
3633 case value_t::object:
3634 {
3635 return m_value.object->empty();
3636 }
3637
3638 default:
3639 {
3640 // all other types are nonempty
3641 return false;
3642 }
3643 }
3644 }
3645
3675 size_type size() const noexcept
3676 {
3677 switch (m_type)
3678 {
3679 case value_t::null:
3680 {
3681 // null values are empty
3682 return 0;
3683 }
3684
3685 case value_t::array:
3686 {
3687 return m_value.array->size();
3688 }
3689
3690 case value_t::object:
3691 {
3692 return m_value.object->size();
3693 }
3694
3695 default:
3696 {
3697 // all other types have size 1
3698 return 1;
3699 }
3700 }
3701 }
3702
3735 size_type max_size() const noexcept
3736 {
3737 switch (m_type)
3738 {
3739 case value_t::array:
3740 {
3741 return m_value.array->max_size();
3742 }
3743
3744 case value_t::object:
3745 {
3746 return m_value.object->max_size();
3747 }
3748
3749 default:
3750 {
3751 // all other types have max_size() == size()
3752 return size();
3753 }
3754 }
3755 }
3756
3758
3759
3761 // modifiers //
3763
3766
3792 void clear() noexcept
3793 {
3794 switch (m_type)
3795 {
3796 case value_t::number_integer:
3797 {
3798 m_value.number_integer = 0;
3799 break;
3800 }
3801
3802 case value_t::number_float:
3803 {
3804 m_value.number_float = 0.0;
3805 break;
3806 }
3807
3808 case value_t::boolean:
3809 {
3810 m_value.boolean = false;
3811 break;
3812 }
3813
3814 case value_t::string:
3815 {
3816 m_value.string->clear();
3817 break;
3818 }
3819
3820 case value_t::array:
3821 {
3822 m_value.array->clear();
3823 break;
3824 }
3825
3826 case value_t::object:
3827 {
3828 m_value.object->clear();
3829 break;
3830 }
3831
3832 default:
3833 {
3834 break;
3835 }
3836 }
3837 }
3838
3858 void push_back(basic_json&& value)
3859 {
3860 // push_back only works for null objects or arrays
3861 if (not(is_null() or is_array()))
3862 {
3863 throw std::domain_error("cannot use push_back() with " + type_name());
3864 }
3865
3866 // transform null object into an array
3867 if (is_null())
3868 {
3869 m_type = value_t::array;
3870 m_value = value_t::array;
3871 }
3872
3873 // add element to array (move semantics)
3874 m_value.array->push_back(std::move(value));
3875 // invalidate object
3876 value.m_type = value_t::null;
3877 }
3878
3883 reference operator+=(basic_json&& value)
3884 {
3885 push_back(std::move(value));
3886 return *this;
3887 }
3888
3893 void push_back(const basic_json& value)
3894 {
3895 // push_back only works for null objects or arrays
3896 if (not(is_null() or is_array()))
3897 {
3898 throw std::domain_error("cannot use push_back() with " + type_name());
3899 }
3900
3901 // transform null object into an array
3902 if (is_null())
3903 {
3904 m_type = value_t::array;
3905 m_value = value_t::array;
3906 }
3907
3908 // add element to array
3909 m_value.array->push_back(value);
3910 }
3911
3916 reference operator+=(const basic_json& value)
3917 {
3918 push_back(value);
3919 return *this;
3920 }
3921
3942 void push_back(const typename object_t::value_type& value)
3943 {
3944 // push_back only works for null objects or objects
3945 if (not(is_null() or is_object()))
3946 {
3947 throw std::domain_error("cannot use push_back() with " + type_name());
3948 }
3949
3950 // transform null object into an object
3951 if (is_null())
3952 {
3953 m_type = value_t::object;
3954 m_value = value_t::object;
3955 }
3956
3957 // add element to array
3958 m_value.object->insert(value);
3959 }
3960
3965 reference operator+=(const typename object_t::value_type& value)
3966 {
3967 push_back(value);
3968 return operator[](value.first);
3969 }
3970
3991 iterator insert(const_iterator pos, const basic_json& value)
3992 {
3993 // insert only works for arrays
3994 if (is_array())
3995 {
3996 // check if iterator pos fits to this JSON value
3997 if (pos.m_object != this)
3998 {
3999 throw std::domain_error("iterator does not fit current value");
4000 }
4001
4002 // insert to array and return iterator
4003 iterator result(this);
4004 result.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator, value);
4005 return result;
4006 }
4007 else
4008 {
4009 throw std::domain_error("cannot use insert() with " + type_name());
4010 }
4011 }
4012
4017 iterator insert(const_iterator pos, basic_json&& value)
4018 {
4019 return insert(pos, value);
4020 }
4021
4044 iterator insert(const_iterator pos, size_type count, const basic_json& value)
4045 {
4046 // insert only works for arrays
4047 if (is_array())
4048 {
4049 // check if iterator pos fits to this JSON value
4050 if (pos.m_object != this)
4051 {
4052 throw std::domain_error("iterator does not fit current value");
4053 }
4054
4055 // insert to array and return iterator
4056 iterator result(this);
4057 result.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator, count, value);
4058 return result;
4059 }
4060 else
4061 {
4062 throw std::domain_error("cannot use insert() with " + type_name());
4063 }
4064 }
4065
4092 iterator insert(const_iterator pos, const_iterator first, const_iterator last)
4093 {
4094 // insert only works for arrays
4095 if (not is_array())
4096 {
4097 throw std::domain_error("cannot use insert() with " + type_name());
4098 }
4099
4100 // check if iterator pos fits to this JSON value
4101 if (pos.m_object != this)
4102 {
4103 throw std::domain_error("iterator does not fit current value");
4104 }
4105
4106 if (first.m_object != last.m_object)
4107 {
4108 throw std::domain_error("iterators do not fit");
4109 }
4110
4111 if (first.m_object == this or last.m_object == this)
4112 {
4113 throw std::domain_error("passed iterators may not belong to container");
4114 }
4115
4116 // insert to array and return iterator
4117 iterator result(this);
4118 result.m_it.array_iterator = m_value.array->insert(
4119 pos.m_it.array_iterator,
4120 first.m_it.array_iterator,
4121 last.m_it.array_iterator);
4122 return result;
4123 }
4124
4146 iterator insert(const_iterator pos, std::initializer_list<basic_json> ilist)
4147 {
4148 // insert only works for arrays
4149 if (not is_array())
4150 {
4151 throw std::domain_error("cannot use insert() with " + type_name());
4152 }
4153
4154 // check if iterator pos fits to this JSON value
4155 if (pos.m_object != this)
4156 {
4157 throw std::domain_error("iterator does not fit current value");
4158 }
4159
4160 // insert to array and return iterator
4161 iterator result(this);
4162 result.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator, ilist);
4163 return result;
4164 }
4165
4183 void swap(reference other) noexcept (
4184 std::is_nothrow_move_constructible<value_t>::value and
4185 std::is_nothrow_move_assignable<value_t>::value and
4186 std::is_nothrow_move_constructible<json_value>::value and
4187 std::is_nothrow_move_assignable<json_value>::value
4188 )
4189 {
4190 std::swap(m_type, other.m_type);
4191 std::swap(m_value, other.m_value);
4192 }
4193
4213 void swap(array_t& other)
4214 {
4215 // swap only works for arrays
4216 if (is_array())
4217 {
4218 std::swap(*(m_value.array), other);
4219 }
4220 else
4221 {
4222 throw std::domain_error("cannot use swap() with " + type_name());
4223 }
4224 }
4225
4245 void swap(object_t& other)
4246 {
4247 // swap only works for objects
4248 if (is_object())
4249 {
4250 std::swap(*(m_value.object), other);
4251 }
4252 else
4253 {
4254 throw std::domain_error("cannot use swap() with " + type_name());
4255 }
4256 }
4257
4277 void swap(string_t& other)
4278 {
4279 // swap only works for strings
4280 if (is_string())
4281 {
4282 std::swap(*(m_value.string), other);
4283 }
4284 else
4285 {
4286 throw std::domain_error("cannot use swap() with " + type_name());
4287 }
4288 }
4289
4291
4292
4294 // lexicographical comparison operators //
4296
4299
4300 private:
4310 friend bool operator<(const value_t lhs, const value_t rhs)
4311 {
4312 static constexpr std::array<uint8_t, 7> order = {{
4313 0, // null
4314 3, // object
4315 4, // array
4316 5, // string
4317 1, // boolean
4318 2, // integer
4319 2 // float
4320 }
4321 };
4322
4323 // discarded values are not comparable
4324 if (lhs == value_t::discarded or rhs == value_t::discarded)
4325 {
4326 return false;
4327 }
4328
4329 return order[static_cast<std::size_t>(lhs)] < order[static_cast<std::size_t>(rhs)];
4330 }
4331
4332 public:
4356 friend bool operator==(const_reference lhs, const_reference rhs) noexcept
4357 {
4358 const auto lhs_type = lhs.type();
4359 const auto rhs_type = rhs.type();
4360
4361 if (lhs_type == rhs_type)
4362 {
4363 switch (lhs_type)
4364 {
4365 case value_t::array:
4366 return *lhs.m_value.array == *rhs.m_value.array;
4367 case value_t::object:
4368 return *lhs.m_value.object == *rhs.m_value.object;
4369 case value_t::null:
4370 return true;
4371 case value_t::string:
4372 return *lhs.m_value.string == *rhs.m_value.string;
4373 case value_t::boolean:
4374 return lhs.m_value.boolean == rhs.m_value.boolean;
4375 case value_t::number_integer:
4376 return lhs.m_value.number_integer == rhs.m_value.number_integer;
4377 case value_t::number_float:
4378 return approx(lhs.m_value.number_float, rhs.m_value.number_float);
4379 default:
4380 return false;
4381 }
4382 }
4383 else if (lhs_type == value_t::number_integer and rhs_type == value_t::number_float)
4384 {
4385 return approx(static_cast<number_float_t>(lhs.m_value.number_integer),
4386 rhs.m_value.number_float);
4387 }
4388 else if (lhs_type == value_t::number_float and rhs_type == value_t::number_integer)
4389 {
4390 return approx(lhs.m_value.number_float,
4391 static_cast<number_float_t>(rhs.m_value.number_integer));
4392 }
4393 return false;
4394 }
4395
4414 friend bool operator==(const_reference v, std::nullptr_t) noexcept
4415 {
4416 return v.is_null();
4417 }
4418
4423 friend bool operator==(std::nullptr_t, const_reference v) noexcept
4424 {
4425 return v.is_null();
4426 }
4427
4444 friend bool operator!=(const_reference lhs, const_reference rhs) noexcept
4445 {
4446 return not (lhs == rhs);
4447 }
4448
4467 friend bool operator!=(const_reference v, std::nullptr_t) noexcept
4468 {
4469 return not v.is_null();
4470 }
4471
4476 friend bool operator!=(std::nullptr_t, const_reference v) noexcept
4477 {
4478 return not v.is_null();
4479 }
4480
4505 friend bool operator<(const_reference lhs, const_reference rhs) noexcept
4506 {
4507 const auto lhs_type = lhs.type();
4508 const auto rhs_type = rhs.type();
4509
4510 if (lhs_type == rhs_type)
4511 {
4512 switch (lhs_type)
4513 {
4514 case value_t::array:
4515 return *lhs.m_value.array < *rhs.m_value.array;
4516 case value_t::object:
4517 return *lhs.m_value.object < *rhs.m_value.object;
4518 case value_t::null:
4519 return false;
4520 case value_t::string:
4521 return *lhs.m_value.string < *rhs.m_value.string;
4522 case value_t::boolean:
4523 return lhs.m_value.boolean < rhs.m_value.boolean;
4524 case value_t::number_integer:
4525 return lhs.m_value.number_integer < rhs.m_value.number_integer;
4526 case value_t::number_float:
4527 return lhs.m_value.number_float < rhs.m_value.number_float;
4528 default:
4529 return false;
4530 }
4531 }
4532 else if (lhs_type == value_t::number_integer and rhs_type == value_t::number_float)
4533 {
4534 return static_cast<number_float_t>(lhs.m_value.number_integer) <
4535 rhs.m_value.number_float;
4536 }
4537 else if (lhs_type == value_t::number_float and rhs_type == value_t::number_integer)
4538 {
4539 return lhs.m_value.number_float <
4540 static_cast<number_float_t>(rhs.m_value.number_integer);
4541 }
4542
4543 // We only reach this line if we cannot compare values. In that case,
4544 // we compare types. Note we have to call the operator explicitly,
4545 // because MSVC has problems otherwise.
4546 return operator<(lhs_type, rhs_type);
4547 }
4548
4566 friend bool operator<=(const_reference lhs, const_reference rhs) noexcept
4567 {
4568 return not (rhs < lhs);
4569 }
4570
4588 friend bool operator>(const_reference lhs, const_reference rhs) noexcept
4589 {
4590 return not (lhs <= rhs);
4591 }
4592
4610 friend bool operator>=(const_reference lhs, const_reference rhs) noexcept
4611 {
4612 return not (lhs < rhs);
4613 }
4614
4616
4617
4619 // serialization //
4621
4624
4647 friend std::ostream& operator<<(std::ostream& o, const basic_json& j)
4648 {
4649 // read width member and use it as indentation parameter if nonzero
4650 const bool pretty_print = (o.width() > 0);
4651 const auto indentation = (pretty_print ? o.width() : 0);
4652
4653 // reset width to 0 for subsequent calls to this stream
4654 o.width(0);
4655
4656 // do the actual serialization
4657 j.dump(o, pretty_print, static_cast<unsigned int>(indentation));
4658 return o;
4659 }
4660
4665 friend std::ostream& operator>>(const basic_json& j, std::ostream& o)
4666 {
4667 return o << j;
4668 }
4669
4671
4672
4674 // deserialization //
4676
4679
4704 static basic_json parse(const string_t& s, parser_callback_t cb = nullptr)
4705 {
4706 return parser(s, cb).parse();
4707 }
4708
4733 static basic_json parse(std::istream& i, parser_callback_t cb = nullptr)
4734 {
4735 return parser(i, cb).parse();
4736 }
4737
4741 static basic_json parse(std::istream&& i, parser_callback_t cb = nullptr)
4742 {
4743 return parser(i, cb).parse();
4744 }
4745
4769 friend std::istream& operator<<(basic_json& j, std::istream& i)
4770 {
4771 j = parser(i).parse();
4772 return i;
4773 }
4774
4779 friend std::istream& operator>>(std::istream& i, basic_json& j)
4780 {
4781 j = parser(i).parse();
4782 return i;
4783 }
4784
4786
4787
4788 private:
4790 // convenience functions //
4792
4794 string_t type_name() const
4795 {
4796 switch (m_type)
4797 {
4798 case value_t::null:
4799 return "null";
4800 case value_t::object:
4801 return "object";
4802 case value_t::array:
4803 return "array";
4804 case value_t::string:
4805 return "string";
4806 case value_t::boolean:
4807 return "boolean";
4808 case value_t::discarded:
4809 return "discarded";
4810 default:
4811 return "number";
4812 }
4813 }
4814
4823 static std::size_t extra_space(const string_t& s) noexcept
4824 {
4825 std::size_t result = 0;
4826
4827 for (const auto& c : s)
4828 {
4829 switch (c)
4830 {
4831 case '"':
4832 case '\\':
4833 case '\b':
4834 case '\f':
4835 case '\n':
4836 case '\r':
4837 case '\t':
4838 {
4839 // from c (1 byte) to \x (2 bytes)
4840 result += 1;
4841 break;
4842 }
4843
4844 default:
4845 {
4846 if (c >= 0x00 and c <= 0x1f)
4847 {
4848 // from c (1 byte) to \uxxxx (6 bytes)
4849 result += 5;
4850 }
4851 break;
4852 }
4853 }
4854 }
4855
4856 return result;
4857 }
4858
4872 static string_t escape_string(const string_t& s) noexcept
4873 {
4874 const auto space = extra_space(s);
4875 if (space == 0)
4876 {
4877 return s;
4878 }
4879
4880 // create a result string of necessary size
4881 string_t result(s.size() + space, '\\');
4882 std::size_t pos = 0;
4883
4884 for (const auto& c : s)
4885 {
4886 switch (c)
4887 {
4888 // quotation mark (0x22)
4889 case '"':
4890 {
4891 result[pos + 1] = '"';
4892 pos += 2;
4893 break;
4894 }
4895
4896 // reverse solidus (0x5c)
4897 case '\\':
4898 {
4899 // nothing to change
4900 pos += 2;
4901 break;
4902 }
4903
4904 // backspace (0x08)
4905 case '\b':
4906 {
4907 result[pos + 1] = 'b';
4908 pos += 2;
4909 break;
4910 }
4911
4912 // formfeed (0x0c)
4913 case '\f':
4914 {
4915 result[pos + 1] = 'f';
4916 pos += 2;
4917 break;
4918 }
4919
4920 // newline (0x0a)
4921 case '\n':
4922 {
4923 result[pos + 1] = 'n';
4924 pos += 2;
4925 break;
4926 }
4927
4928 // carriage return (0x0d)
4929 case '\r':
4930 {
4931 result[pos + 1] = 'r';
4932 pos += 2;
4933 break;
4934 }
4935
4936 // horizontal tab (0x09)
4937 case '\t':
4938 {
4939 result[pos + 1] = 't';
4940 pos += 2;
4941 break;
4942 }
4943
4944 default:
4945 {
4946 if (c >= 0x00 and c <= 0x1f)
4947 {
4948 // convert a number 0..15 to its hex representation (0..f)
4949 auto hexify = [](const char v) -> char
4950 {
4951 return (v < 10) ? ('0' + v) : ('a' + v - 10);
4952 };
4953
4954 // print character c as \uxxxx
4955 for (const char m :
4956 { 'u', '0', '0', hexify(c >> 4), hexify(c & 0x0f)
4957 })
4958 {
4959 result[++pos] = m;
4960 }
4961
4962 ++pos;
4963 }
4964 else
4965 {
4966 // all other characters are added as-is
4967 result[pos++] = c;
4968 }
4969 break;
4970 }
4971 }
4972 }
4973
4974 return result;
4975 }
4976
4994 void dump(std::ostream& o,
4995 const bool pretty_print,
4996 const unsigned int indent_step,
4997 const unsigned int current_indent = 0) const
4998 {
4999 // variable to hold indentation for recursive calls
5000 unsigned int new_indent = current_indent;
5001
5002 switch (m_type)
5003 {
5004 case value_t::object:
5005 {
5006 if (m_value.object->empty())
5007 {
5008 o << "{}";
5009 return;
5010 }
5011
5012 o << "{";
5013
5014 // increase indentation
5015 if (pretty_print)
5016 {
5017 new_indent += indent_step;
5018 o << "\n";
5019 }
5020
5021 for (auto i = m_value.object->cbegin(); i != m_value.object->cend(); ++i)
5022 {
5023 if (i != m_value.object->cbegin())
5024 {
5025 o << (pretty_print ? ",\n" : ",");
5026 }
5027 o << string_t(new_indent, ' ') << "\""
5028 << escape_string(i->first) << "\":"
5029 << (pretty_print ? " " : "");
5030 i->second.dump(o, pretty_print, indent_step, new_indent);
5031 }
5032
5033 // decrease indentation
5034 if (pretty_print)
5035 {
5036 new_indent -= indent_step;
5037 o << "\n";
5038 }
5039
5040 o << string_t(new_indent, ' ') + "}";
5041 return;
5042 }
5043
5044 case value_t::array:
5045 {
5046 if (m_value.array->empty())
5047 {
5048 o << "[]";
5049 return;
5050 }
5051
5052 o << "[";
5053
5054 // increase indentation
5055 if (pretty_print)
5056 {
5057 new_indent += indent_step;
5058 o << "\n";
5059 }
5060
5061 for (auto i = m_value.array->cbegin(); i != m_value.array->cend(); ++i)
5062 {
5063 if (i != m_value.array->cbegin())
5064 {
5065 o << (pretty_print ? ",\n" : ",");
5066 }
5067 o << string_t(new_indent, ' ');
5068 i->dump(o, pretty_print, indent_step, new_indent);
5069 }
5070
5071 // decrease indentation
5072 if (pretty_print)
5073 {
5074 new_indent -= indent_step;
5075 o << "\n";
5076 }
5077
5078 o << string_t(new_indent, ' ') << "]";
5079 return;
5080 }
5081
5082 case value_t::string:
5083 {
5084 o << string_t("\"") << escape_string(*m_value.string) << "\"";
5085 return;
5086 }
5087
5088 case value_t::boolean:
5089 {
5090 o << (m_value.boolean ? "true" : "false");
5091 return;
5092 }
5093
5094 case value_t::number_integer:
5095 {
5096 o << m_value.number_integer;
5097 return;
5098 }
5099
5100 case value_t::number_float:
5101 {
5102 // 15 digits of precision allows round-trip IEEE 754
5103 // string->double->string; to be safe, we read this value from
5104 // std::numeric_limits<number_float_t>::digits10
5105 o << std::setprecision(std::numeric_limits<number_float_t>::digits10) << m_value.number_float;
5106 return;
5107 }
5108
5109 case value_t::discarded:
5110 {
5111 o << "<discarded>";
5112 return;
5113 }
5114
5115 case value_t::null:
5116 {
5117 o << "null";
5118 return;
5119 }
5120 }
5121 }
5122
5123 private:
5125 // member variables //
5127
5129 value_t m_type = value_t::null;
5130
5132 json_value m_value = {};
5133
5134
5135 private:
5137 // iterators //
5139
5149 class primitive_iterator_t
5150 {
5151 public:
5153 void set_begin()
5154 {
5155 m_it = begin_value;
5156 }
5157
5159 void set_end()
5160 {
5161 m_it = end_value;
5162 }
5163
5165 bool is_begin() const
5166 {
5167 return (m_it == begin_value);
5168 }
5169
5171 bool is_end() const
5172 {
5173 return (m_it == end_value);
5174 }
5175
5177 operator difference_type& ()
5178 {
5179 return m_it;
5180 }
5181
5183 operator difference_type () const
5184 {
5185 return m_it;
5186 }
5187
5188 private:
5189 static constexpr difference_type begin_value = 0;
5190 static constexpr difference_type end_value = begin_value + 1;
5191
5193 difference_type m_it = std::numeric_limits<std::ptrdiff_t>::denorm_min();
5194 };
5195
5203 struct internal_iterator
5204 {
5206 typename object_t::iterator object_iterator;
5208 typename array_t::iterator array_iterator;
5210 primitive_iterator_t primitive_iterator;
5211
5213 internal_iterator()
5214 : object_iterator(), array_iterator(), primitive_iterator()
5215 {}
5216 };
5217
5218 public:
5232 class const_iterator : public std::iterator<std::random_access_iterator_tag, const basic_json>
5233 {
5235 friend class basic_json;
5236
5237 public:
5239 using value_type = typename basic_json::value_type;
5241 using difference_type = typename basic_json::difference_type;
5243 using pointer = typename basic_json::const_pointer;
5245 using reference = typename basic_json::const_reference;
5247 using iterator_category = std::bidirectional_iterator_tag;
5248
5250 const_iterator() = default;
5251
5253 const_iterator(pointer object) : m_object(object)
5254 {
5255 switch (m_object->m_type)
5256 {
5257 case basic_json::value_t::object:
5258 {
5259 m_it.object_iterator = typename object_t::iterator();
5260 break;
5261 }
5262
5263 case basic_json::value_t::array:
5264 {
5265 m_it.array_iterator = typename array_t::iterator();
5266 break;
5267 }
5268
5269 default:
5270 {
5271 m_it.primitive_iterator = primitive_iterator_t();
5272 break;
5273 }
5274 }
5275 }
5276
5278 const_iterator(const iterator& other) : m_object(other.m_object)
5279 {
5280 switch (m_object->m_type)
5281 {
5282 case basic_json::value_t::object:
5283 {
5284 m_it.object_iterator = other.m_it.object_iterator;
5285 break;
5286 }
5287
5288 case basic_json::value_t::array:
5289 {
5290 m_it.array_iterator = other.m_it.array_iterator;
5291 break;
5292 }
5293
5294 default:
5295 {
5296 m_it.primitive_iterator = other.m_it.primitive_iterator;
5297 break;
5298 }
5299 }
5300 }
5301
5303 const_iterator(const const_iterator& other) noexcept
5304 : m_object(other.m_object), m_it(other.m_it)
5305 {}
5306
5308 const_iterator& operator=(const_iterator other) noexcept(
5309 std::is_nothrow_move_constructible<pointer>::value and
5310 std::is_nothrow_move_assignable<pointer>::value and
5311 std::is_nothrow_move_constructible<internal_iterator>::value and
5312 std::is_nothrow_move_assignable<internal_iterator>::value
5313 )
5314 {
5315 std::swap(m_object, other.m_object);
5316 std::swap(m_it, other.m_it);
5317 return *this;
5318 }
5319
5320 private:
5322 void set_begin()
5323 {
5324 switch (m_object->m_type)
5325 {
5326 case basic_json::value_t::object:
5327 {
5328 m_it.object_iterator = m_object->m_value.object->begin();
5329 break;
5330 }
5331
5332 case basic_json::value_t::array:
5333 {
5334 m_it.array_iterator = m_object->m_value.array->begin();
5335 break;
5336 }
5337
5338 case basic_json::value_t::null:
5339 {
5340 // set to end so begin()==end() is true: null is empty
5341 m_it.primitive_iterator.set_end();
5342 break;
5343 }
5344
5345 default:
5346 {
5347 m_it.primitive_iterator.set_begin();
5348 break;
5349 }
5350 }
5351 }
5352
5354 void set_end()
5355 {
5356 switch (m_object->m_type)
5357 {
5358 case basic_json::value_t::object:
5359 {
5360 m_it.object_iterator = m_object->m_value.object->end();
5361 break;
5362 }
5363
5364 case basic_json::value_t::array:
5365 {
5366 m_it.array_iterator = m_object->m_value.array->end();
5367 break;
5368 }
5369
5370 default:
5371 {
5372 m_it.primitive_iterator.set_end();
5373 break;
5374 }
5375 }
5376 }
5377
5378 public:
5380 reference operator*() const
5381 {
5382 switch (m_object->m_type)
5383 {
5384 case basic_json::value_t::object:
5385 {
5386 return m_it.object_iterator->second;
5387 }
5388
5389 case basic_json::value_t::array:
5390 {
5391 return *m_it.array_iterator;
5392 }
5393
5394 case basic_json::value_t::null:
5395 {
5396 throw std::out_of_range("cannot get value");
5397 }
5398
5399 default:
5400 {
5401 return m_it.primitive_iterator.is_begin()
5402 ? *m_object
5403 : throw std::out_of_range("cannot get value");
5404 }
5405 }
5406 }
5407
5409 pointer operator->() const
5410 {
5411 switch (m_object->m_type)
5412 {
5413 case basic_json::value_t::object:
5414 {
5415 return &(m_it.object_iterator->second);
5416 }
5417
5418 case basic_json::value_t::array:
5419 {
5420 return &*m_it.array_iterator;
5421 }
5422
5423 default:
5424 {
5425 return m_it.primitive_iterator.is_begin()
5426 ? m_object
5427 : throw std::out_of_range("cannot get value");
5428 }
5429 }
5430 }
5431
5433 const_iterator operator++(int)
5434 {
5435 auto result = *this;
5436 ++(*this);
5437 return result;
5438 }
5439
5441 const_iterator& operator++()
5442 {
5443 switch (m_object->m_type)
5444 {
5445 case basic_json::value_t::object:
5446 {
5447 ++m_it.object_iterator;
5448 break;
5449 }
5450
5451 case basic_json::value_t::array:
5452 {
5453 ++m_it.array_iterator;
5454 break;
5455 }
5456
5457 default:
5458 {
5459 ++m_it.primitive_iterator;
5460 break;
5461 }
5462 }
5463
5464 return *this;
5465 }
5466
5468 const_iterator operator--(int)
5469 {
5470 auto result = *this;
5471 --(*this);
5472 return result;
5473 }
5474
5476 const_iterator& operator--()
5477 {
5478 switch (m_object->m_type)
5479 {
5480 case basic_json::value_t::object:
5481 {
5482 --m_it.object_iterator;
5483 break;
5484 }
5485
5486 case basic_json::value_t::array:
5487 {
5488 --m_it.array_iterator;
5489 break;
5490 }
5491
5492 default:
5493 {
5494 --m_it.primitive_iterator;
5495 break;
5496 }
5497 }
5498
5499 return *this;
5500 }
5501
5503 bool operator==(const const_iterator& other) const
5504 {
5505 // if objects are not the same, the comparison is undefined
5506 if (m_object != other.m_object)
5507 {
5508 throw std::domain_error("cannot compare iterators of different containers");
5509 }
5510
5511 switch (m_object->m_type)
5512 {
5513 case basic_json::value_t::object:
5514 {
5515 return (m_it.object_iterator == other.m_it.object_iterator);
5516 }
5517
5518 case basic_json::value_t::array:
5519 {
5520 return (m_it.array_iterator == other.m_it.array_iterator);
5521 }
5522
5523 default:
5524 {
5525 return (m_it.primitive_iterator == other.m_it.primitive_iterator);
5526 }
5527 }
5528 }
5529
5531 bool operator!=(const const_iterator& other) const
5532 {
5533 return not operator==(other);
5534 }
5535
5537 bool operator<(const const_iterator& other) const
5538 {
5539 // if objects are not the same, the comparison is undefined
5540 if (m_object != other.m_object)
5541 {
5542 throw std::domain_error("cannot compare iterators of different containers");
5543 }
5544
5545 switch (m_object->m_type)
5546 {
5547 case basic_json::value_t::object:
5548 {
5549 throw std::domain_error("cannot use operator< for object iterators");
5550 }
5551
5552 case basic_json::value_t::array:
5553 {
5554 return (m_it.array_iterator < other.m_it.array_iterator);
5555 }
5556
5557 default:
5558 {
5559 return (m_it.primitive_iterator < other.m_it.primitive_iterator);
5560 }
5561 }
5562 }
5563
5565 bool operator<=(const const_iterator& other) const
5566 {
5567 return not other.operator < (*this);
5568 }
5569
5571 bool operator>(const const_iterator& other) const
5572 {
5573 return not operator<=(other);
5574 }
5575
5577 bool operator>=(const const_iterator& other) const
5578 {
5579 return not operator<(other);
5580 }
5581
5583 const_iterator& operator+=(difference_type i)
5584 {
5585 switch (m_object->m_type)
5586 {
5587 case basic_json::value_t::object:
5588 {
5589 throw std::domain_error("cannot use operator+= for object iterators");
5590 }
5591
5592 case basic_json::value_t::array:
5593 {
5594 m_it.array_iterator += i;
5595 break;
5596 }
5597
5598 default:
5599 {
5600 m_it.primitive_iterator += i;
5601 break;
5602 }
5603 }
5604
5605 return *this;
5606 }
5607
5609 const_iterator& operator-=(difference_type i)
5610 {
5611 return operator+=(-i);
5612 }
5613
5615 const_iterator operator+(difference_type i)
5616 {
5617 auto result = *this;
5618 result += i;
5619 return result;
5620 }
5621
5623 const_iterator operator-(difference_type i)
5624 {
5625 auto result = *this;
5626 result -= i;
5627 return result;
5628 }
5629
5631 difference_type operator-(const const_iterator& other) const
5632 {
5633 switch (m_object->m_type)
5634 {
5635 case basic_json::value_t::object:
5636 {
5637 throw std::domain_error("cannot use operator- for object iterators");
5638 }
5639
5640 case basic_json::value_t::array:
5641 {
5642 return m_it.array_iterator - other.m_it.array_iterator;
5643 }
5644
5645 default:
5646 {
5647 return m_it.primitive_iterator - other.m_it.primitive_iterator;
5648 }
5649 }
5650 }
5651
5653 reference operator[](difference_type n) const
5654 {
5655 switch (m_object->m_type)
5656 {
5657 case basic_json::value_t::object:
5658 {
5659 throw std::domain_error("cannot use operator[] for object iterators");
5660 }
5661
5662 case basic_json::value_t::array:
5663 {
5664 return *(m_it.array_iterator + n);
5665 }
5666
5667 case basic_json::value_t::null:
5668 {
5669 throw std::out_of_range("cannot get value");
5670 }
5671
5672 default:
5673 {
5674 return (m_it.primitive_iterator == -n)
5675 ? *m_object
5676 : throw std::out_of_range("cannot get value");
5677 }
5678 }
5679 }
5680
5682 typename object_t::key_type key() const
5683 {
5684 return m_object->is_object()
5685 ? m_it.object_iterator->first
5686 : throw std::domain_error("cannot use key() for non-object iterators");
5687 }
5688
5690 reference value() const
5691 {
5692 return operator*();
5693 }
5694
5695 private:
5697 pointer m_object = nullptr;
5699 internal_iterator m_it = internal_iterator();
5700 };
5701
5714 class iterator : public const_iterator
5715 {
5716 public:
5717 using base_iterator = const_iterator;
5718 using pointer = typename basic_json::pointer;
5719 using reference = typename basic_json::reference;
5720
5722 iterator() = default;
5723
5725 iterator(pointer object) noexcept : base_iterator(object)
5726 {}
5727
5729 iterator(const iterator& other) noexcept
5730 : base_iterator(other)
5731 {}
5732
5734 iterator& operator=(iterator other) noexcept(
5735 std::is_nothrow_move_constructible<pointer>::value and
5736 std::is_nothrow_move_assignable<pointer>::value and
5737 std::is_nothrow_move_constructible<internal_iterator>::value and
5738 std::is_nothrow_move_assignable<internal_iterator>::value
5739 )
5740 {
5741 base_iterator::operator=(other);
5742 return *this;
5743 }
5744
5746 reference operator*()
5747 {
5748 return const_cast<reference>(base_iterator::operator*());
5749 }
5750
5752 pointer operator->()
5753 {
5754 return const_cast<pointer>(base_iterator::operator->());
5755 }
5756
5758 iterator operator++(int)
5759 {
5760 iterator result = *this;
5761 base_iterator::operator++();
5762 return result;
5763 }
5764
5766 iterator& operator++()
5767 {
5768 base_iterator::operator++();
5769 return *this;
5770 }
5771
5773 iterator operator--(int)
5774 {
5775 iterator result = *this;
5776 base_iterator::operator--();
5777 return result;
5778 }
5779
5781 iterator& operator--()
5782 {
5783 base_iterator::operator--();
5784 return *this;
5785 }
5786
5788 iterator& operator+=(difference_type i)
5789 {
5790 base_iterator::operator+=(i);
5791 return *this;
5792 }
5793
5795 iterator& operator-=(difference_type i)
5796 {
5797 base_iterator::operator-=(i);
5798 return *this;
5799 }
5800
5802 iterator operator+(difference_type i)
5803 {
5804 auto result = *this;
5805 result += i;
5806 return result;
5807 }
5808
5810 iterator operator-(difference_type i)
5811 {
5812 auto result = *this;
5813 result -= i;
5814 return result;
5815 }
5816
5817 difference_type operator-(const iterator& other) const
5818 {
5819 return base_iterator::operator-(other);
5820 }
5821
5823 reference operator[](difference_type n) const
5824 {
5825 return const_cast<reference>(base_iterator::operator[](n));
5826 }
5827
5829 reference value() const
5830 {
5831 return const_cast<reference>(base_iterator::value());
5832 }
5833 };
5834
5852 template<typename Base>
5853 class json_reverse_iterator : public std::reverse_iterator<Base>
5854 {
5855 public:
5857 using base_iterator = std::reverse_iterator<Base>;
5859 using reference = typename Base::reference;
5860
5862 json_reverse_iterator(const typename base_iterator::iterator_type& it)
5863 : base_iterator(it) {}
5864
5866 json_reverse_iterator(const base_iterator& it) : base_iterator(it) {}
5867
5869 json_reverse_iterator operator++(int)
5870 {
5871 return base_iterator::operator++(1);
5872 }
5873
5875 json_reverse_iterator& operator++()
5876 {
5877 base_iterator::operator++();
5878 return *this;
5879 }
5880
5882 json_reverse_iterator operator--(int)
5883 {
5884 return base_iterator::operator--(1);
5885 }
5886
5888 json_reverse_iterator& operator--()
5889 {
5890 base_iterator::operator--();
5891 return *this;
5892 }
5893
5895 json_reverse_iterator& operator+=(difference_type i)
5896 {
5897 base_iterator::operator+=(i);
5898 return *this;
5899 }
5900
5902 json_reverse_iterator operator+(difference_type i) const
5903 {
5904 auto result = *this;
5905 result += i;
5906 return result;
5907 }
5908
5910 json_reverse_iterator operator-(difference_type i) const
5911 {
5912 auto result = *this;
5913 result -= i;
5914 return result;
5915 }
5916
5918 difference_type operator-(const json_reverse_iterator& other) const
5919 {
5920 return this->base() - other.base();
5921 }
5922
5924 reference operator[](difference_type n) const
5925 {
5926 return *(this->operator+(n));
5927 }
5928
5930 typename object_t::key_type key() const
5931 {
5932 auto it = --this->base();
5933 return it.key();
5934 }
5935
5937 reference value() const
5938 {
5939 auto it = --this->base();
5940 return it.operator * ();
5941 }
5942 };
5943
5951 class iterator_wrapper
5952 {
5953 private:
5955 basic_json& container;
5957 using json_iterator = decltype(std::begin(container));
5958
5960 class iterator_wrapper_internal
5961 {
5962 private:
5964 json_iterator anchor;
5966 size_t array_index = 0;
5967
5968 public:
5970 iterator_wrapper_internal(json_iterator i) : anchor(i)
5971 {}
5972
5974 iterator_wrapper_internal& operator*()
5975 {
5976 return *this;
5977 }
5978
5980 iterator_wrapper_internal& operator++()
5981 {
5982 ++anchor;
5983 ++array_index;
5984
5985 return *this;
5986 }
5987
5989 bool operator!= (const iterator_wrapper_internal& o)
5990 {
5991 return anchor != o.anchor;
5992 }
5993
5995 typename basic_json::string_t key() const
5996 {
5997 switch (anchor.m_object->type())
5998 {
5999 // use integer array index as key
6000 case value_t::array:
6001 {
6002 return std::to_string(array_index);
6003 }
6004
6005 // use key from the object
6006 case value_t::object:
6007 {
6008 return anchor.key();
6009 }
6010
6011 // use an empty key for all primitive types
6012 default:
6013 {
6014 return "";
6015 }
6016 }
6017 }
6018
6020 typename json_iterator::reference value() const
6021 {
6022 return anchor.value();
6023 }
6024 };
6025
6026 public:
6028 iterator_wrapper(basic_json& cont)
6029 : container(cont)
6030 {}
6031
6033 iterator_wrapper_internal begin()
6034 {
6035 return iterator_wrapper_internal(container.begin());
6036 }
6037
6039 iterator_wrapper_internal end()
6040 {
6041 return iterator_wrapper_internal(container.end());
6042 }
6043 };
6044
6045 private:
6047 // lexer and parser //
6049
6057 class lexer
6058 {
6059 public:
6061 enum class token_type
6062 {
6063 uninitialized,
6064 literal_true,
6065 literal_false,
6066 literal_null,
6067 value_string,
6068 value_number,
6069 begin_array,
6070 begin_object,
6071 end_array,
6072 end_object,
6073 name_separator,
6074 value_separator,
6075 parse_error,
6076 end_of_input
6077 };
6078
6080 using lexer_char_t = unsigned char;
6081
6083 explicit lexer(const string_t& s) noexcept
6084 : m_stream(nullptr), m_buffer(s)
6085 {
6086 m_content = reinterpret_cast<const lexer_char_t*>(s.c_str());
6087 m_start = m_cursor = m_content;
6088 m_limit = m_content + s.size();
6089 }
6090 explicit lexer(std::istream* s) noexcept
6091 : m_stream(s), m_buffer()
6092 {
6093 getline(*m_stream, m_buffer);
6094 m_content = reinterpret_cast<const lexer_char_t*>(m_buffer.c_str());
6095 m_start = m_cursor = m_content;
6096 m_limit = m_content + m_buffer.size();
6097 }
6098
6100 lexer() = default;
6101
6102 // switch of unwanted functions
6103 lexer(const lexer&) = delete;
6104 lexer operator=(const lexer&) = delete;
6105
6117 static string_t to_unicode(const std::size_t codepoint1,
6118 const std::size_t codepoint2 = 0)
6119 {
6120 string_t result;
6121
6122 // calculate the codepoint from the given code points
6123 std::size_t codepoint = codepoint1;
6124
6125 // check if codepoint1 is a high surrogate
6126 if (codepoint1 >= 0xD800 and codepoint1 <= 0xDBFF)
6127 {
6128 // check if codepoint2 is a low surrogate
6129 if (codepoint2 >= 0xDC00 and codepoint2 <= 0xDFFF)
6130 {
6131 codepoint =
6132 // high surrogate occupies the most significant 22 bits
6133 (codepoint1 << 10)
6134 // low surrogate occupies the least significant 15 bits
6135 + codepoint2
6136 // there is still the 0xD800, 0xDC00 and 0x10000 noise
6137 // in the result so we have to substract with:
6138 // (0xD800 << 10) + DC00 - 0x10000 = 0x35FDC00
6139 - 0x35FDC00;
6140 }
6141 else
6142 {
6143 throw std::invalid_argument("missing or wrong low surrogate");
6144 }
6145 }
6146
6147 if (codepoint < 0x80)
6148 {
6149 // 1-byte characters: 0xxxxxxx (ASCII)
6150 result.append(1, static_cast<typename string_t::value_type>(codepoint));
6151 }
6152 else if (codepoint <= 0x7ff)
6153 {
6154 // 2-byte characters: 110xxxxx 10xxxxxx
6155 result.append(1, static_cast<typename string_t::value_type>(0xC0 | ((codepoint >> 6) & 0x1F)));
6156 result.append(1, static_cast<typename string_t::value_type>(0x80 | (codepoint & 0x3F)));
6157 }
6158 else if (codepoint <= 0xffff)
6159 {
6160 // 3-byte characters: 1110xxxx 10xxxxxx 10xxxxxx
6161 result.append(1, static_cast<typename string_t::value_type>(0xE0 | ((codepoint >> 12) & 0x0F)));
6162 result.append(1, static_cast<typename string_t::value_type>(0x80 | ((codepoint >> 6) & 0x3F)));
6163 result.append(1, static_cast<typename string_t::value_type>(0x80 | (codepoint & 0x3F)));
6164 }
6165 else if (codepoint <= 0x10ffff)
6166 {
6167 // 4-byte characters: 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
6168 result.append(1, static_cast<typename string_t::value_type>(0xF0 | ((codepoint >> 18) & 0x07)));
6169 result.append(1, static_cast<typename string_t::value_type>(0x80 | ((codepoint >> 12) & 0x3F)));
6170 result.append(1, static_cast<typename string_t::value_type>(0x80 | ((codepoint >> 6) & 0x3F)));
6171 result.append(1, static_cast<typename string_t::value_type>(0x80 | (codepoint & 0x3F)));
6172 }
6173 else
6174 {
6175 throw std::out_of_range("code points above 0x10FFFF are invalid");
6176 }
6177
6178 return result;
6179 }
6180
6182 static std::string token_type_name(token_type t)
6183 {
6184 switch (t)
6185 {
6186 case token_type::uninitialized:
6187 return "<uninitialized>";
6188 case token_type::literal_true:
6189 return "true literal";
6190 case token_type::literal_false:
6191 return "false literal";
6192 case token_type::literal_null:
6193 return "null literal";
6194 case token_type::value_string:
6195 return "string literal";
6196 case token_type::value_number:
6197 return "number literal";
6198 case token_type::begin_array:
6199 return "[";
6200 case token_type::begin_object:
6201 return "{";
6202 case token_type::end_array:
6203 return "]";
6204 case token_type::end_object:
6205 return "}";
6206 case token_type::name_separator:
6207 return ":";
6208 case token_type::value_separator:
6209 return ",";
6210 case token_type::end_of_input:
6211 return "<end of input>";
6212 case token_type::parse_error:
6213 return "<parse error>";
6214 }
6215 }
6216
6227 token_type scan() noexcept
6228 {
6229 // pointer for backtracking information
6230 m_marker = nullptr;
6231
6232 // remember the begin of the token
6233 m_start = m_cursor;
6234
6235
6236 {
6237 lexer_char_t yych;
6238 unsigned int yyaccept = 0;
6239 static const unsigned char yybm[] =
6240 {
6241 0, 0, 0, 0, 0, 0, 0, 0,
6242 0, 32, 32, 0, 0, 32, 0, 0,
6243 64, 64, 64, 64, 64, 64, 64, 64,
6244 64, 64, 64, 64, 64, 64, 64, 64,
6245 96, 64, 0, 64, 64, 64, 64, 64,
6246 64, 64, 64, 64, 64, 64, 64, 64,
6247 192, 192, 192, 192, 192, 192, 192, 192,
6248 192, 192, 64, 64, 64, 64, 64, 64,
6249 64, 64, 64, 64, 64, 64, 64, 64,
6250 64, 64, 64, 64, 64, 64, 64, 64,
6251 64, 64, 64, 64, 64, 64, 64, 64,
6252 64, 64, 64, 64, 0, 64, 64, 64,
6253 64, 64, 64, 64, 64, 64, 64, 64,
6254 64, 64, 64, 64, 64, 64, 64, 64,
6255 64, 64, 64, 64, 64, 64, 64, 64,
6256 64, 64, 64, 64, 64, 64, 64, 64,
6257 64, 64, 64, 64, 64, 64, 64, 64,
6258 64, 64, 64, 64, 64, 64, 64, 64,
6259 64, 64, 64, 64, 64, 64, 64, 64,
6260 64, 64, 64, 64, 64, 64, 64, 64,
6261 64, 64, 64, 64, 64, 64, 64, 64,
6262 64, 64, 64, 64, 64, 64, 64, 64,
6263 64, 64, 64, 64, 64, 64, 64, 64,
6264 64, 64, 64, 64, 64, 64, 64, 64,
6265 64, 64, 64, 64, 64, 64, 64, 64,
6266 64, 64, 64, 64, 64, 64, 64, 64,
6267 64, 64, 64, 64, 64, 64, 64, 64,
6268 64, 64, 64, 64, 64, 64, 64, 64,
6269 64, 64, 64, 64, 64, 64, 64, 64,
6270 64, 64, 64, 64, 64, 64, 64, 64,
6271 64, 64, 64, 64, 64, 64, 64, 64,
6272 64, 64, 64, 64, 64, 64, 64, 64,
6273 };
6274 if ((m_limit - m_cursor) < 5)
6275 {
6276 yyfill(); // LCOV_EXCL_LINE;
6277 }
6278 yych = *m_cursor;
6279 if (yych <= ':')
6280 {
6281 if (yych <= ' ')
6282 {
6283 if (yych <= '\n')
6284 {
6285 if (yych <= 0x00)
6286 {
6287 goto basic_json_parser_28;
6288 }
6289 if (yych <= 0x08)
6290 {
6291 goto basic_json_parser_30;
6292 }
6293 if (yych >= '\n')
6294 {
6295 goto basic_json_parser_4;
6296 }
6297 }
6298 else
6299 {
6300 if (yych == '\r')
6301 {
6302 goto basic_json_parser_2;
6303 }
6304 if (yych <= 0x1F)
6305 {
6306 goto basic_json_parser_30;
6307 }
6308 }
6309 }
6310 else
6311 {
6312 if (yych <= ',')
6313 {
6314 if (yych == '"')
6315 {
6316 goto basic_json_parser_27;
6317 }
6318 if (yych <= '+')
6319 {
6320 goto basic_json_parser_30;
6321 }
6322 goto basic_json_parser_16;
6323 }
6324 else
6325 {
6326 if (yych <= '/')
6327 {
6328 if (yych <= '-')
6329 {
6330 goto basic_json_parser_23;
6331 }
6332 goto basic_json_parser_30;
6333 }
6334 else
6335 {
6336 if (yych <= '0')
6337 {
6338 goto basic_json_parser_24;
6339 }
6340 if (yych <= '9')
6341 {
6342 goto basic_json_parser_26;
6343 }
6344 goto basic_json_parser_18;
6345 }
6346 }
6347 }
6348 }
6349 else
6350 {
6351 if (yych <= 'n')
6352 {
6353 if (yych <= ']')
6354 {
6355 if (yych == '[')
6356 {
6357 goto basic_json_parser_8;
6358 }
6359 if (yych <= '\\')
6360 {
6361 goto basic_json_parser_30;
6362 }
6363 goto basic_json_parser_10;
6364 }
6365 else
6366 {
6367 if (yych == 'f')
6368 {
6369 goto basic_json_parser_22;
6370 }
6371 if (yych <= 'm')
6372 {
6373 goto basic_json_parser_30;
6374 }
6375 goto basic_json_parser_20;
6376 }
6377 }
6378 else
6379 {
6380 if (yych <= '{')
6381 {
6382 if (yych == 't')
6383 {
6384 goto basic_json_parser_21;
6385 }
6386 if (yych <= 'z')
6387 {
6388 goto basic_json_parser_30;
6389 }
6390 goto basic_json_parser_12;
6391 }
6392 else
6393 {
6394 if (yych <= '}')
6395 {
6396 if (yych <= '|')
6397 {
6398 goto basic_json_parser_30;
6399 }
6400 goto basic_json_parser_14;
6401 }
6402 else
6403 {
6404 if (yych == 0xEF)
6405 {
6406 goto basic_json_parser_6;
6407 }
6408 goto basic_json_parser_30;
6409 }
6410 }
6411 }
6412 }
6413 basic_json_parser_2:
6414 ++m_cursor;
6415 yych = *m_cursor;
6416 goto basic_json_parser_5;
6417 basic_json_parser_3:
6418 {
6419 return scan();
6420 }
6421 basic_json_parser_4:
6422 ++m_cursor;
6423 if (m_limit <= m_cursor)
6424 {
6425 yyfill(); // LCOV_EXCL_LINE;
6426 }
6427 yych = *m_cursor;
6428 basic_json_parser_5:
6429 if (yybm[0 + yych] & 32)
6430 {
6431 goto basic_json_parser_4;
6432 }
6433 goto basic_json_parser_3;
6434 basic_json_parser_6:
6435 yyaccept = 0;
6436 yych = *(m_marker = ++m_cursor);
6437 if (yych == 0xBB)
6438 {
6439 goto basic_json_parser_64;
6440 }
6441 basic_json_parser_7:
6442 {
6443 return token_type::parse_error;
6444 }
6445 basic_json_parser_8:
6446 ++m_cursor;
6447 {
6448 return token_type::begin_array;
6449 }
6450 basic_json_parser_10:
6451 ++m_cursor;
6452 {
6453 return token_type::end_array;
6454 }
6455 basic_json_parser_12:
6456 ++m_cursor;
6457 {
6458 return token_type::begin_object;
6459 }
6460 basic_json_parser_14:
6461 ++m_cursor;
6462 {
6463 return token_type::end_object;
6464 }
6465 basic_json_parser_16:
6466 ++m_cursor;
6467 {
6468 return token_type::value_separator;
6469 }
6470 basic_json_parser_18:
6471 ++m_cursor;
6472 {
6473 return token_type::name_separator;
6474 }
6475 basic_json_parser_20:
6476 yyaccept = 0;
6477 yych = *(m_marker = ++m_cursor);
6478 if (yych == 'u')
6479 {
6480 goto basic_json_parser_60;
6481 }
6482 goto basic_json_parser_7;
6483 basic_json_parser_21:
6484 yyaccept = 0;
6485 yych = *(m_marker = ++m_cursor);
6486 if (yych == 'r')
6487 {
6488 goto basic_json_parser_56;
6489 }
6490 goto basic_json_parser_7;
6491 basic_json_parser_22:
6492 yyaccept = 0;
6493 yych = *(m_marker = ++m_cursor);
6494 if (yych == 'a')
6495 {
6496 goto basic_json_parser_51;
6497 }
6498 goto basic_json_parser_7;
6499 basic_json_parser_23:
6500 yych = *++m_cursor;
6501 if (yych <= '/')
6502 {
6503 goto basic_json_parser_7;
6504 }
6505 if (yych <= '0')
6506 {
6507 goto basic_json_parser_50;
6508 }
6509 if (yych <= '9')
6510 {
6511 goto basic_json_parser_41;
6512 }
6513 goto basic_json_parser_7;
6514 basic_json_parser_24:
6515 yyaccept = 1;
6516 yych = *(m_marker = ++m_cursor);
6517 if (yych <= 'D')
6518 {
6519 if (yych == '.')
6520 {
6521 goto basic_json_parser_43;
6522 }
6523 }
6524 else
6525 {
6526 if (yych <= 'E')
6527 {
6528 goto basic_json_parser_44;
6529 }
6530 if (yych == 'e')
6531 {
6532 goto basic_json_parser_44;
6533 }
6534 }
6535 basic_json_parser_25:
6536 {
6537 return token_type::value_number;
6538 }
6539 basic_json_parser_26:
6540 yyaccept = 1;
6541 yych = *(m_marker = ++m_cursor);
6542 goto basic_json_parser_42;
6543 basic_json_parser_27:
6544 yyaccept = 0;
6545 yych = *(m_marker = ++m_cursor);
6546 if (yych <= 0x0F)
6547 {
6548 goto basic_json_parser_7;
6549 }
6550 goto basic_json_parser_32;
6551 basic_json_parser_28:
6552 ++m_cursor;
6553 {
6554 return token_type::end_of_input;
6555 }
6556 basic_json_parser_30:
6557 yych = *++m_cursor;
6558 goto basic_json_parser_7;
6559 basic_json_parser_31:
6560 ++m_cursor;
6561 if (m_limit <= m_cursor)
6562 {
6563 yyfill(); // LCOV_EXCL_LINE;
6564 }
6565 yych = *m_cursor;
6566 basic_json_parser_32:
6567 if (yybm[0 + yych] & 64)
6568 {
6569 goto basic_json_parser_31;
6570 }
6571 if (yych <= 0x0F)
6572 {
6573 goto basic_json_parser_33;
6574 }
6575 if (yych <= '"')
6576 {
6577 goto basic_json_parser_35;
6578 }
6579 goto basic_json_parser_34;
6580 basic_json_parser_33:
6581 m_cursor = m_marker;
6582 if (yyaccept == 0)
6583 {
6584 goto basic_json_parser_7;
6585 }
6586 else
6587 {
6588 goto basic_json_parser_25;
6589 }
6590 basic_json_parser_34:
6591 ++m_cursor;
6592 if (m_limit <= m_cursor)
6593 {
6594 yyfill(); // LCOV_EXCL_LINE;
6595 }
6596 yych = *m_cursor;
6597 if (yych <= 'e')
6598 {
6599 if (yych <= '/')
6600 {
6601 if (yych == '"')
6602 {
6603 goto basic_json_parser_31;
6604 }
6605 if (yych <= '.')
6606 {
6607 goto basic_json_parser_33;
6608 }
6609 goto basic_json_parser_31;
6610 }
6611 else
6612 {
6613 if (yych <= '\\')
6614 {
6615 if (yych <= '[')
6616 {
6617 goto basic_json_parser_33;
6618 }
6619 goto basic_json_parser_31;
6620 }
6621 else
6622 {
6623 if (yych == 'b')
6624 {
6625 goto basic_json_parser_31;
6626 }
6627 goto basic_json_parser_33;
6628 }
6629 }
6630 }
6631 else
6632 {
6633 if (yych <= 'q')
6634 {
6635 if (yych <= 'f')
6636 {
6637 goto basic_json_parser_31;
6638 }
6639 if (yych == 'n')
6640 {
6641 goto basic_json_parser_31;
6642 }
6643 goto basic_json_parser_33;
6644 }
6645 else
6646 {
6647 if (yych <= 's')
6648 {
6649 if (yych <= 'r')
6650 {
6651 goto basic_json_parser_31;
6652 }
6653 goto basic_json_parser_33;
6654 }
6655 else
6656 {
6657 if (yych <= 't')
6658 {
6659 goto basic_json_parser_31;
6660 }
6661 if (yych <= 'u')
6662 {
6663 goto basic_json_parser_37;
6664 }
6665 goto basic_json_parser_33;
6666 }
6667 }
6668 }
6669 basic_json_parser_35:
6670 ++m_cursor;
6671 {
6672 return token_type::value_string;
6673 }
6674 basic_json_parser_37:
6675 ++m_cursor;
6676 if (m_limit <= m_cursor)
6677 {
6678 yyfill(); // LCOV_EXCL_LINE;
6679 }
6680 yych = *m_cursor;
6681 if (yych <= '@')
6682 {
6683 if (yych <= '/')
6684 {
6685 goto basic_json_parser_33;
6686 }
6687 if (yych >= ':')
6688 {
6689 goto basic_json_parser_33;
6690 }
6691 }
6692 else
6693 {
6694 if (yych <= 'F')
6695 {
6696 goto basic_json_parser_38;
6697 }
6698 if (yych <= '`')
6699 {
6700 goto basic_json_parser_33;
6701 }
6702 if (yych >= 'g')
6703 {
6704 goto basic_json_parser_33;
6705 }
6706 }
6707 basic_json_parser_38:
6708 ++m_cursor;
6709 if (m_limit <= m_cursor)
6710 {
6711 yyfill(); // LCOV_EXCL_LINE;
6712 }
6713 yych = *m_cursor;
6714 if (yych <= '@')
6715 {
6716 if (yych <= '/')
6717 {
6718 goto basic_json_parser_33;
6719 }
6720 if (yych >= ':')
6721 {
6722 goto basic_json_parser_33;
6723 }
6724 }
6725 else
6726 {
6727 if (yych <= 'F')
6728 {
6729 goto basic_json_parser_39;
6730 }
6731 if (yych <= '`')
6732 {
6733 goto basic_json_parser_33;
6734 }
6735 if (yych >= 'g')
6736 {
6737 goto basic_json_parser_33;
6738 }
6739 }
6740 basic_json_parser_39:
6741 ++m_cursor;
6742 if (m_limit <= m_cursor)
6743 {
6744 yyfill(); // LCOV_EXCL_LINE;
6745 }
6746 yych = *m_cursor;
6747 if (yych <= '@')
6748 {
6749 if (yych <= '/')
6750 {
6751 goto basic_json_parser_33;
6752 }
6753 if (yych >= ':')
6754 {
6755 goto basic_json_parser_33;
6756 }
6757 }
6758 else
6759 {
6760 if (yych <= 'F')
6761 {
6762 goto basic_json_parser_40;
6763 }
6764 if (yych <= '`')
6765 {
6766 goto basic_json_parser_33;
6767 }
6768 if (yych >= 'g')
6769 {
6770 goto basic_json_parser_33;
6771 }
6772 }
6773 basic_json_parser_40:
6774 ++m_cursor;
6775 if (m_limit <= m_cursor)
6776 {
6777 yyfill(); // LCOV_EXCL_LINE;
6778 }
6779 yych = *m_cursor;
6780 if (yych <= '@')
6781 {
6782 if (yych <= '/')
6783 {
6784 goto basic_json_parser_33;
6785 }
6786 if (yych <= '9')
6787 {
6788 goto basic_json_parser_31;
6789 }
6790 goto basic_json_parser_33;
6791 }
6792 else
6793 {
6794 if (yych <= 'F')
6795 {
6796 goto basic_json_parser_31;
6797 }
6798 if (yych <= '`')
6799 {
6800 goto basic_json_parser_33;
6801 }
6802 if (yych <= 'f')
6803 {
6804 goto basic_json_parser_31;
6805 }
6806 goto basic_json_parser_33;
6807 }
6808 basic_json_parser_41:
6809 yyaccept = 1;
6810 m_marker = ++m_cursor;
6811 if ((m_limit - m_cursor) < 3)
6812 {
6813 yyfill(); // LCOV_EXCL_LINE;
6814 }
6815 yych = *m_cursor;
6816 basic_json_parser_42:
6817 if (yybm[0 + yych] & 128)
6818 {
6819 goto basic_json_parser_41;
6820 }
6821 if (yych <= 'D')
6822 {
6823 if (yych != '.')
6824 {
6825 goto basic_json_parser_25;
6826 }
6827 }
6828 else
6829 {
6830 if (yych <= 'E')
6831 {
6832 goto basic_json_parser_44;
6833 }
6834 if (yych == 'e')
6835 {
6836 goto basic_json_parser_44;
6837 }
6838 goto basic_json_parser_25;
6839 }
6840 basic_json_parser_43:
6841 yych = *++m_cursor;
6842 if (yych <= '/')
6843 {
6844 goto basic_json_parser_33;
6845 }
6846 if (yych <= '9')
6847 {
6848 goto basic_json_parser_48;
6849 }
6850 goto basic_json_parser_33;
6851 basic_json_parser_44:
6852 yych = *++m_cursor;
6853 if (yych <= ',')
6854 {
6855 if (yych != '+')
6856 {
6857 goto basic_json_parser_33;
6858 }
6859 }
6860 else
6861 {
6862 if (yych <= '-')
6863 {
6864 goto basic_json_parser_45;
6865 }
6866 if (yych <= '/')
6867 {
6868 goto basic_json_parser_33;
6869 }
6870 if (yych <= '9')
6871 {
6872 goto basic_json_parser_46;
6873 }
6874 goto basic_json_parser_33;
6875 }
6876 basic_json_parser_45:
6877 yych = *++m_cursor;
6878 if (yych <= '/')
6879 {
6880 goto basic_json_parser_33;
6881 }
6882 if (yych >= ':')
6883 {
6884 goto basic_json_parser_33;
6885 }
6886 basic_json_parser_46:
6887 ++m_cursor;
6888 if (m_limit <= m_cursor)
6889 {
6890 yyfill(); // LCOV_EXCL_LINE;
6891 }
6892 yych = *m_cursor;
6893 if (yych <= '/')
6894 {
6895 goto basic_json_parser_25;
6896 }
6897 if (yych <= '9')
6898 {
6899 goto basic_json_parser_46;
6900 }
6901 goto basic_json_parser_25;
6902 basic_json_parser_48:
6903 yyaccept = 1;
6904 m_marker = ++m_cursor;
6905 if ((m_limit - m_cursor) < 3)
6906 {
6907 yyfill(); // LCOV_EXCL_LINE;
6908 }
6909 yych = *m_cursor;
6910 if (yych <= 'D')
6911 {
6912 if (yych <= '/')
6913 {
6914 goto basic_json_parser_25;
6915 }
6916 if (yych <= '9')
6917 {
6918 goto basic_json_parser_48;
6919 }
6920 goto basic_json_parser_25;
6921 }
6922 else
6923 {
6924 if (yych <= 'E')
6925 {
6926 goto basic_json_parser_44;
6927 }
6928 if (yych == 'e')
6929 {
6930 goto basic_json_parser_44;
6931 }
6932 goto basic_json_parser_25;
6933 }
6934 basic_json_parser_50:
6935 yyaccept = 1;
6936 yych = *(m_marker = ++m_cursor);
6937 if (yych <= 'D')
6938 {
6939 if (yych == '.')
6940 {
6941 goto basic_json_parser_43;
6942 }
6943 goto basic_json_parser_25;
6944 }
6945 else
6946 {
6947 if (yych <= 'E')
6948 {
6949 goto basic_json_parser_44;
6950 }
6951 if (yych == 'e')
6952 {
6953 goto basic_json_parser_44;
6954 }
6955 goto basic_json_parser_25;
6956 }
6957 basic_json_parser_51:
6958 yych = *++m_cursor;
6959 if (yych != 'l')
6960 {
6961 goto basic_json_parser_33;
6962 }
6963 yych = *++m_cursor;
6964 if (yych != 's')
6965 {
6966 goto basic_json_parser_33;
6967 }
6968 yych = *++m_cursor;
6969 if (yych != 'e')
6970 {
6971 goto basic_json_parser_33;
6972 }
6973 ++m_cursor;
6974 {
6975 return token_type::literal_false;
6976 }
6977 basic_json_parser_56:
6978 yych = *++m_cursor;
6979 if (yych != 'u')
6980 {
6981 goto basic_json_parser_33;
6982 }
6983 yych = *++m_cursor;
6984 if (yych != 'e')
6985 {
6986 goto basic_json_parser_33;
6987 }
6988 ++m_cursor;
6989 {
6990 return token_type::literal_true;
6991 }
6992 basic_json_parser_60:
6993 yych = *++m_cursor;
6994 if (yych != 'l')
6995 {
6996 goto basic_json_parser_33;
6997 }
6998 yych = *++m_cursor;
6999 if (yych != 'l')
7000 {
7001 goto basic_json_parser_33;
7002 }
7003 ++m_cursor;
7004 {
7005 return token_type::literal_null;
7006 }
7007 basic_json_parser_64:
7008 yych = *++m_cursor;
7009 if (yych != 0xBF)
7010 {
7011 goto basic_json_parser_33;
7012 }
7013 ++m_cursor;
7014 {
7015 return scan();
7016 }
7017 }
7018
7019
7020 }
7021
7023 void yyfill() noexcept
7024 {
7025 if (not m_stream or not * m_stream)
7026 {
7027 return;
7028 }
7029
7030 const ssize_t offset_start = m_start - m_content;
7031 const ssize_t offset_marker = m_marker - m_start;
7032 const ssize_t offset_cursor = m_cursor - m_start;
7033
7034 m_buffer.erase(0, static_cast<size_t>(offset_start));
7035 std::string line;
7036 std::getline(*m_stream, line);
7037 m_buffer += "\n" + line; // add line with newline symbol
7038
7039 m_content = reinterpret_cast<const lexer_char_t*>(m_buffer.c_str());
7040 m_start = m_content;
7041 m_marker = m_start + offset_marker;
7042 m_cursor = m_start + offset_cursor;
7043 m_limit = m_start + m_buffer.size() - 1;
7044 }
7045
7047 string_t get_token() const noexcept
7048 {
7049 return string_t(reinterpret_cast<typename string_t::const_pointer>(m_start),
7050 static_cast<size_t>(m_cursor - m_start));
7051 }
7052
7074 string_t get_string() const
7075 {
7076 string_t result;
7077 result.reserve(static_cast<size_t>(m_cursor - m_start - 2));
7078
7079 // iterate the result between the quotes
7080 for (const lexer_char_t* i = m_start + 1; i < m_cursor - 1; ++i)
7081 {
7082 // process escaped characters
7083 if (*i == '\\')
7084 {
7085 // read next character
7086 ++i;
7087
7088 switch (*i)
7089 {
7090 // the default escapes
7091 case 't':
7092 {
7093 result += "\t";
7094 break;
7095 }
7096 case 'b':
7097 {
7098 result += "\b";
7099 break;
7100 }
7101 case 'f':
7102 {
7103 result += "\f";
7104 break;
7105 }
7106 case 'n':
7107 {
7108 result += "\n";
7109 break;
7110 }
7111 case 'r':
7112 {
7113 result += "\r";
7114 break;
7115 }
7116 case '\\':
7117 {
7118 result += "\\";
7119 break;
7120 }
7121 case '/':
7122 {
7123 result += "/";
7124 break;
7125 }
7126 case '"':
7127 {
7128 result += "\"";
7129 break;
7130 }
7131
7132 // unicode
7133 case 'u':
7134 {
7135 // get code xxxx from uxxxx
7136 auto codepoint = std::strtoul(std::string(reinterpret_cast<typename string_t::const_pointer>(i + 1),
7137 4).c_str(), nullptr, 16);
7138
7139 // check if codepoint is a high surrogate
7140 if (codepoint >= 0xD800 and codepoint <= 0xDBFF)
7141 {
7142 // make sure there is a subsequent unicode
7143 if ((i + 6 >= m_limit) or * (i + 5) != '\\' or * (i + 6) != 'u')
7144 {
7145 throw std::invalid_argument("missing low surrogate");
7146 }
7147
7148 // get code yyyy from uxxxx\uyyyy
7149 auto codepoint2 = std::strtoul(std::string(reinterpret_cast<typename string_t::const_pointer>
7150 (i + 7), 4).c_str(), nullptr, 16);
7151 result += to_unicode(codepoint, codepoint2);
7152 // skip the next 10 characters (xxxx\uyyyy)
7153 i += 10;
7154 }
7155 else
7156 {
7157 // add unicode character(s)
7158 result += to_unicode(codepoint);
7159 // skip the next four characters (xxxx)
7160 i += 4;
7161 }
7162 break;
7163 }
7164 }
7165 }
7166 else
7167 {
7168 // all other characters are just copied to the end of the
7169 // string
7170 result.append(1, static_cast<typename string_t::value_type>(*i));
7171 }
7172 }
7173
7174 return result;
7175 }
7176
7194 long double get_number() const
7195 {
7196 // conversion
7197 typename string_t::value_type* endptr;
7198 const auto float_val = std::strtold(reinterpret_cast<typename string_t::const_pointer>(m_start),
7199 &endptr);
7200
7201 // return float_val if the whole number was translated and NAN
7202 // otherwise
7203 return (reinterpret_cast<lexer_char_t*>(endptr) == m_cursor) ? float_val : NAN;
7204 }
7205
7206 private:
7208 std::istream* m_stream;
7210 string_t m_buffer;
7212 const lexer_char_t* m_content = nullptr;
7214 const lexer_char_t* m_start = nullptr;
7216 const lexer_char_t* m_marker = nullptr;
7218 const lexer_char_t* m_cursor = nullptr;
7220 const lexer_char_t* m_limit = nullptr;
7221 };
7222
7228 class parser
7229 {
7230 public:
7232 parser(const string_t& s, parser_callback_t cb = nullptr)
7233 : callback(cb), m_lexer(s)
7234 {
7235 // read first token
7236 get_token();
7237 }
7238
7240 parser(std::istream& _is, parser_callback_t cb = nullptr)
7241 : callback(cb), m_lexer(&_is)
7242 {
7243 // read first token
7244 get_token();
7245 }
7246
7248 basic_json parse()
7249 {
7250 basic_json result = parse_internal(true);
7251
7252 expect(lexer::token_type::end_of_input);
7253
7254 // return parser result and replace it with null in case the
7255 // top-level value was discarded by the callback function
7256 return result.is_discarded() ? basic_json() : result;
7257 }
7258
7259 private:
7261 basic_json parse_internal(bool keep)
7262 {
7263 auto result = basic_json(value_t::discarded);
7264
7265 switch (last_token)
7266 {
7267 case lexer::token_type::begin_object:
7268 {
7269 if (keep and (not callback or (keep = callback(depth++, parse_event_t::object_start, result))))
7270 {
7271 // explicitly set result to object to cope with {}
7272 result.m_type = value_t::object;
7273 result.m_value = json_value(value_t::object);
7274 }
7275
7276 // read next token
7277 get_token();
7278
7279 // closing } -> we are done
7280 if (last_token == lexer::token_type::end_object)
7281 {
7282 get_token();
7283 if (keep and callback and not callback(--depth, parse_event_t::object_end, result))
7284 {
7285 result = basic_json(value_t::discarded);
7286 }
7287 return result;
7288 }
7289
7290 // no comma is expected here
7291 unexpect(lexer::token_type::value_separator);
7292
7293 // otherwise: parse key-value pairs
7294 do
7295 {
7296 // ugly, but could be fixed with loop reorganization
7297 if (last_token == lexer::token_type::value_separator)
7298 {
7299 get_token();
7300 }
7301
7302 // store key
7303 expect(lexer::token_type::value_string);
7304 const auto key = m_lexer.get_string();
7305
7306 bool keep_tag = false;
7307 if (keep)
7308 {
7309 if (callback)
7310 {
7311 basic_json k(key);
7312 keep_tag = callback(depth, parse_event_t::key, k);
7313 }
7314 else
7315 {
7316 keep_tag = true;
7317 }
7318 }
7319
7320 // parse separator (:)
7321 get_token();
7322 expect(lexer::token_type::name_separator);
7323
7324 // parse and add value
7325 get_token();
7326 auto value = parse_internal(keep);
7327 if (keep and keep_tag and not value.is_discarded())
7328 {
7329 result[key] = std::move(value);
7330 }
7331 }
7332 while (last_token == lexer::token_type::value_separator);
7333
7334 // closing }
7335 expect(lexer::token_type::end_object);
7336 get_token();
7337 if (keep and callback and not callback(--depth, parse_event_t::object_end, result))
7338 {
7339 result = basic_json(value_t::discarded);
7340 }
7341
7342 return result;
7343 }
7344
7345 case lexer::token_type::begin_array:
7346 {
7347 if (keep and (not callback or (keep = callback(depth++, parse_event_t::array_start, result))))
7348 {
7349 // explicitly set result to object to cope with []
7350 result.m_type = value_t::array;
7351 result.m_value = json_value(value_t::array);
7352 }
7353
7354 // read next token
7355 get_token();
7356
7357 // closing ] -> we are done
7358 if (last_token == lexer::token_type::end_array)
7359 {
7360 get_token();
7361 if (callback and not callback(--depth, parse_event_t::array_end, result))
7362 {
7363 result = basic_json(value_t::discarded);
7364 }
7365 return result;
7366 }
7367
7368 // no comma is expected here
7369 unexpect(lexer::token_type::value_separator);
7370
7371 // otherwise: parse values
7372 do
7373 {
7374 // ugly, but could be fixed with loop reorganization
7375 if (last_token == lexer::token_type::value_separator)
7376 {
7377 get_token();
7378 }
7379
7380 // parse value
7381 auto value = parse_internal(keep);
7382 if (keep and not value.is_discarded())
7383 {
7384 result.push_back(std::move(value));
7385 }
7386 }
7387 while (last_token == lexer::token_type::value_separator);
7388
7389 // closing ]
7390 expect(lexer::token_type::end_array);
7391 get_token();
7392 if (keep and callback and not callback(--depth, parse_event_t::array_end, result))
7393 {
7394 result = basic_json(value_t::discarded);
7395 }
7396
7397 return result;
7398 }
7399
7400 case lexer::token_type::literal_null:
7401 {
7402 get_token();
7403 result.m_type = value_t::null;
7404 break;
7405 }
7406
7407 case lexer::token_type::value_string:
7408 {
7409 const auto s = m_lexer.get_string();
7410 get_token();
7411 result = basic_json(s);
7412 break;
7413 }
7414
7415 case lexer::token_type::literal_true:
7416 {
7417 get_token();
7418 result.m_type = value_t::boolean;
7419 result.m_value = true;
7420 break;
7421 }
7422
7423 case lexer::token_type::literal_false:
7424 {
7425 get_token();
7426 result.m_type = value_t::boolean;
7427 result.m_value = false;
7428 break;
7429 }
7430
7431 case lexer::token_type::value_number:
7432 {
7433 auto float_val = m_lexer.get_number();
7434
7435 // NAN is returned if token could not be translated
7436 // completely
7437 if (std::isnan(float_val))
7438 {
7439 throw std::invalid_argument(std::string("parse error - ") +
7440 m_lexer.get_token() + " is not a number");
7441 }
7442
7443 get_token();
7444
7445 // check if conversion loses precision
7446 const auto int_val = static_cast<number_integer_t>(float_val);
7447 if (approx(float_val, static_cast<long double>(int_val)))
7448 {
7449 // we would not lose precision -> return int
7450 result.m_type = value_t::number_integer;
7451 result.m_value = int_val;
7452 }
7453 else
7454 {
7455 // we would lose precision -> return float
7456 result.m_type = value_t::number_float;
7457 result.m_value = static_cast<number_float_t>(float_val);
7458 }
7459 break;
7460 }
7461
7462 default:
7463 {
7464 // the last token was unexpected
7465 unexpect(last_token);
7466 }
7467 }
7468
7469 if (keep and callback and not callback(depth, parse_event_t::value, result))
7470 {
7471 result = basic_json(value_t::discarded);
7472 }
7473 return result;
7474 }
7475
7477 typename lexer::token_type get_token()
7478 {
7479 last_token = m_lexer.scan();
7480 return last_token;
7481 }
7482
7483 void expect(typename lexer::token_type t) const
7484 {
7485 if (t != last_token)
7486 {
7487 std::string error_msg = "parse error - unexpected \'";
7488 error_msg += m_lexer.get_token();
7489 error_msg += "\' (" + lexer::token_type_name(last_token);
7490 error_msg += "); expected " + lexer::token_type_name(t);
7491 throw std::invalid_argument(error_msg);
7492 }
7493 }
7494
7495 void unexpect(typename lexer::token_type t) const
7496 {
7497 if (t == last_token)
7498 {
7499 std::string error_msg = "parse error - unexpected \'";
7500 error_msg += m_lexer.get_token();
7501 error_msg += "\' (";
7502 error_msg += lexer::token_type_name(last_token) + ")";
7503 throw std::invalid_argument(error_msg);
7504 }
7505 }
7506
7507 private:
7509 int depth = 0;
7511 parser_callback_t callback;
7513 typename lexer::token_type last_token = lexer::token_type::uninitialized;
7515 lexer m_lexer;
7516 };
7517 };
7518
7519
7521 // presets //
7523
7532 using json = basic_json<>;
7533 }
7534
7535
7537 // nonmember functions //
7539
7540 // specialization of std::swap, and std::hash
7541 namespace std
7542 {
7548 template <>
7549 inline void swap(nlohmann::json& j1,
7550 nlohmann::json& j2) noexcept(
7551 is_nothrow_move_constructible<nlohmann::json>::value and
7552 is_nothrow_move_assignable<nlohmann::json>::value
7553 )
7554 {
7555 j1.swap(j2);
7556 }
7557
7559 template <>
7560 struct hash<nlohmann::json>
7561 {
7567 std::size_t operator()(const nlohmann::json& j) const
7568 {
7569 // a naive hashing via the string representation
7570 const auto& h = hash<nlohmann::json::string_t>();
7571 return h(j.dump());
7572 }
7573 };
7574 }
7575
7588 inline nlohmann::json operator "" _json(const char* s, std::size_t)
7589 {
7590 return nlohmann::json::parse(reinterpret_cast<nlohmann::json::string_t::value_type*>
7591 (const_cast<char*>(s)));
7592 }
7593
7594 #endif
nlohmann::basic_json::basic_json
basic_json(const number_float_t value)
create a floating-point number (explicit)
Definition: json.hpp:1258
nlohmann::basic_json::reverse_iterator
json_reverse_iterator< typename basic_json::iterator > reverse_iterator
a reverse iterator for a basic_json container
Definition: json.hpp:239
nlohmann::basic_json::iterator_wrapper::iterator_wrapper
iterator_wrapper(basic_json &cont)
construct iterator wrapper from a container
Definition: json.hpp:6028
nlohmann::basic_json::const_iterator::operator!=
bool operator!=(const const_iterator &other) const
comparison: not equal
Definition: json.hpp:5531
nlohmann::basic_json::iterator::operator++
iterator operator++(int)
post-increment (it++)
Definition: json.hpp:5758
nlohmann::basic_json::operator<=
friend bool operator<=(const_reference lhs, const_reference rhs) noexcept
comparison: less than or equal
Definition: json.hpp:4566
nlohmann::basic_json::insert
iterator insert(const_iterator pos, basic_json &&value)
inserts element
Definition: json.hpp:4017
nlohmann::basic_json::pointer
typename std::allocator_traits< allocator_type >::pointer pointer
the type of an element pointer
Definition: json.hpp:227
nlohmann::basic_json::json_reverse_iterator::operator-
json_reverse_iterator operator-(difference_type i) const
subtract from iterator
Definition: json.hpp:5910
nlohmann::basic_json::object
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:1506
nlohmann::basic_json::operator[]
const_reference operator[](size_type idx) const
access specified array element
Definition: json.hpp:2752
nlohmann::basic_json::operator[]
reference operator[](const T(&key)[n])
access specified object element
Definition: json.hpp:2830
nlohmann::basic_json::const_iterator::pointer
typename basic_json::const_pointer pointer
defines a pointer to the type iterated over (value_type)
Definition: json.hpp:5243
nlohmann::basic_json::const_iterator::operator--
const_iterator & operator--()
pre-decrement (–it)
Definition: json.hpp:5476
nlohmann::basic_json::operator>>
friend std::istream & operator>>(std::istream &i, basic_json &j)
deserialize from stream
Definition: json.hpp:4779
nlohmann::basic_json::const_iterator::operator=
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:5308
nlohmann::basic_json::const_iterator::value_type
typename basic_json::value_type value_type
the type of the values when the iterator is dereferenced
Definition: json.hpp:5239
nlohmann::basic_json::operator=
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:1768
nlohmann::basic_json::insert
iterator insert(const_iterator pos, const_iterator first, const_iterator last)
inserts elements
Definition: json.hpp:4092
nlohmann::basic_json::basic_json
basic_json(const int value)
create an integer number from an enum type (explicit)
Definition: json.hpp:1194
nlohmann::basic_json::json_reverse_iterator::operator--
json_reverse_iterator operator--(int)
post-decrement (it–)
Definition: json.hpp:5882
nlohmann::basic_json::string_t
StringType string_t
a type for a string
Definition: json.hpp:433
nlohmann::basic_json::array
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:1466
nlohmann::basic_json::iterator::operator++
iterator & operator++()
pre-increment (++it)
Definition: json.hpp:5766
nlohmann::basic_json::operator!=
friend bool operator!=(const_reference lhs, const_reference rhs) noexcept
comparison: not equal
Definition: json.hpp:4444
nlohmann::basic_json::operator+=
reference operator+=(const typename object_t::value_type &value)
add an object to an object
Definition: json.hpp:3965
nlohmann::basic_json::array_t
ArrayType< basic_json, AllocatorType< basic_json >> array_t
a type for an array
Definition: json.hpp:386
nlohmann::basic_json::const_iterator::operator++
const_iterator & operator++()
pre-increment (++it)
Definition: json.hpp:5441
nlohmann::basic_json::json_reverse_iterator::operator-
difference_type operator-(const json_reverse_iterator &other) const
return difference
Definition: json.hpp:5918
nlohmann::json
basic_json<> json
default JSON class
Definition: json.hpp:7532
nlohmann::basic_json::front
reference front()
access the first element
Definition: json.hpp:2947
nlohmann::basic_json::is_array
bool is_array() const noexcept
return whether value is an array
Definition: json.hpp:2081
nlohmann::basic_json::find
const_iterator find(typename object_t::key_type key) const
find an element in a JSON object
Definition: json.hpp:3308
nlohmann::basic_json::json_reverse_iterator::base_iterator
std::reverse_iterator< Base > base_iterator
shortcut to the reverse iterator adaptor
Definition: json.hpp:5857
nlohmann::basic_json::json_reverse_iterator::json_reverse_iterator
json_reverse_iterator(const typename base_iterator::iterator_type &it)
create reverse iterator from iterator
Definition: json.hpp:5862
nlohmann::basic_json
a class to store JSON values
Definition: json.hpp:187
nlohmann::basic_json::json_reverse_iterator::operator--
json_reverse_iterator & operator--()
pre-decrement (–it)
Definition: json.hpp:5888
nlohmann::basic_json::push_back
void push_back(const typename object_t::value_type &value)
add an object to an object
Definition: json.hpp:3942
nlohmann::basic_json::operator==
friend bool operator==(std::nullptr_t, const_reference v) noexcept
comparison: equal
Definition: json.hpp:4423
nlohmann::basic_json::cbegin
const_iterator cbegin() const
returns a const iterator to the first element
Definition: json.hpp:3406
nlohmann::basic_json::basic_json
basic_json(const CompatibleObjectType &value)
create an object (implicit)
Definition: json.hpp:965
nlohmann::basic_json::is_string
bool is_string() const noexcept
return whether value is a string
Definition: json.hpp:2100
nlohmann::basic_json::iterator::operator+=
iterator & operator+=(difference_type i)
add to iterator
Definition: json.hpp:5788
nlohmann::basic_json::get_ptr
const PointerType get_ptr() const noexcept
get a pointer value (implicit)
Definition: json.hpp:2509
nlohmann::basic_json::parse_event_t::array_end
the parser read ] and finished processing a JSON array
nlohmann::basic_json::iterator::base_iterator
const_iterator base_iterator
Definition: json.hpp:5717
nlohmann::basic_json::iterator
a mutable random access iterator for the basic_json class
Definition: json.hpp:5714
nlohmann::basic_json::iterator::operator-=
iterator & operator-=(difference_type i)
subtract from iterator
Definition: json.hpp:5795
nlohmann::basic_json::parse
static basic_json parse(std::istream &&i, parser_callback_t cb=nullptr)
deserialize from stream
Definition: json.hpp:4741
nlohmann::basic_json::operator[]
reference operator[](const typename object_t::key_type &key)
access specified object element
Definition: json.hpp:2786
std
STL namespace.
nlohmann::basic_json::iterator::operator-
difference_type operator-(const iterator &other) const
Definition: json.hpp:5817
nlohmann::basic_json::const_iterator::value
reference value() const
return the value of an iterator
Definition: json.hpp:5690
nlohmann::basic_json::insert
iterator insert(const_iterator pos, size_type count, const basic_json &value)
inserts elements
Definition: json.hpp:4044
nlohmann::basic_json::end
const_iterator end() const
returns a const iterator to one past the last element
Definition: json.hpp:3441
nlohmann::basic_json::const_iterator::const_iterator
const_iterator(const const_iterator &other) noexcept
copy constructor
Definition: json.hpp:5303
nlohmann::basic_json::at
reference at(const typename object_t::key_type &key)
access specified object element with bounds checking
Definition: json.hpp:2644
nlohmann::basic_json::operator+=
reference operator+=(const basic_json &value)
add an object to an array
Definition: json.hpp:3916
nlohmann::basic_json::const_iterator::key
object_t::key_type key() const
return the key of an object iterator
Definition: json.hpp:5682
nlohmann::basic_json::end
iterator end()
returns an iterator to one past the last element
Definition: json.hpp:3431
nlohmann::basic_json::object_t
ObjectType< StringType, basic_json, std::less< StringType >, AllocatorType< std::pair< const StringType, basic_json >>> object_t
a type for an object
Definition: json.hpp:340
nlohmann::basic_json::iterator::operator*
reference operator*()
return a reference to the value pointed to by the iterator
Definition: json.hpp:5746
nlohmann::basic_json::rend
reverse_iterator rend()
returns an iterator to the reverse-end
Definition: json.hpp:3520
nlohmann::basic_json::is_object
bool is_object() const noexcept
return whether value is an object
Definition: json.hpp:2062
nlohmann::basic_json::const_iterator::operator-
const_iterator operator-(difference_type i)
subtract from iterator
Definition: json.hpp:5623
nlohmann::basic_json::is_discarded
bool is_discarded() const noexcept
return whether value is discarded
Definition: json.hpp:2124
nlohmann::basic_json::const_iterator::reference
typename basic_json::const_reference reference
defines a reference to the type iterated over (value_type)
Definition: json.hpp:5245
nlohmann::basic_json::rend
const_reverse_iterator rend() const
returns a const reverse iterator to one before the first
Definition: json.hpp:3528
nlohmann::basic_json::basic_json
basic_json(const CompatibleArrayType &value)
create an array (implicit)
Definition: json.hpp:1029
nlohmann::basic_json::erase
size_type erase(const typename object_t::key_type &key)
remove element from a JSON object given a key
Definition: json.hpp:3227
nlohmann::basic_json::is_boolean
bool is_boolean() const noexcept
return whether value is a boolean
Definition: json.hpp:1973
nlohmann::basic_json::begin
iterator begin()
returns an iterator to the first element
Definition: json.hpp:3372
nlohmann::basic_json::at
const_reference at(const typename object_t::key_type &key) const
access specified object element with bounds checking
Definition: json.hpp:2677
nlohmann::basic_json::allocator_type
AllocatorType< basic_json > allocator_type
the allocator type
Definition: json.hpp:224
nlohmann::basic_json::is_number_integer
bool is_number_integer() const noexcept
return whether value is an integer number
Definition: json.hpp:2020
nlohmann::basic_json::basic_json
basic_json(const string_t &value)
create a string (explicit)
Definition: json.hpp:1058
nlohmann::basic_json::iterator::operator+
iterator operator+(difference_type i)
add to iterator
Definition: json.hpp:5802
nlohmann::basic_json::parser_callback_t
std::function< bool(int depth, parse_event_t event, basic_json &parsed)> parser_callback_t
per-element parser callback type
Definition: json.hpp:819
nlohmann::basic_json::const_iterator::const_iterator
const_iterator()=default
default constructor
nlohmann::basic_json::parse_event_t::array_start
the parser read [ and started to process a JSON array
nlohmann::basic_json::find
iterator find(typename object_t::key_type key)
find an element in a JSON object
Definition: json.hpp:3292
nlohmann::basic_json::operator>=
friend bool operator>=(const_reference lhs, const_reference rhs) noexcept
comparison: greater than or equal
Definition: json.hpp:4610
nlohmann::basic_json::iterator::operator--
iterator & operator--()
pre-decrement (–it)
Definition: json.hpp:5781
nlohmann::basic_json::operator<
friend bool operator<(const_reference lhs, const_reference rhs) noexcept
comparison: less than
Definition: json.hpp:4505
nlohmann::basic_json::const_iterator::operator->
pointer operator->() const
dereference the iterator
Definition: json.hpp:5409
nlohmann::basic_json::value_t::discarded
discarded by the the parser callback function
nlohmann::basic_json::cend
const_iterator cend() const
returns a const iterator to one past the last element
Definition: json.hpp:3465
nlohmann::basic_json::json_reverse_iterator::reference
typename Base::reference reference
the reference type for the pointed-to element
Definition: json.hpp:5859
nlohmann::basic_json::size
size_type size() const noexcept
returns the number of elements
Definition: json.hpp:3675
nlohmann::basic_json::get_allocator
static allocator_type get_allocator()
returns the allocator associated with the container
Definition: json.hpp:249
nlohmann::basic_json::value_t::object
object (unordered set of name/value pairs)
nlohmann::basic_json::at
reference at(size_type idx)
access specified array element with bounds checking
Definition: json.hpp:2582
nlohmann::basic_json::parse_event_t::object_end
the parser read } and finished processing a JSON object
nlohmann::basic_json::iterator::iterator
iterator()=default
default constructor
nlohmann::basic_json::json_reverse_iterator::json_reverse_iterator
json_reverse_iterator(const base_iterator &it)
create reverse iterator from base class
Definition: json.hpp:5866
nlohmann::basic_json::iterator_wrapper::end
iterator_wrapper_internal end()
return iterator end (needed for range-based for)
Definition: json.hpp:6039
nlohmann::basic_json::type
value_t type() const noexcept
return the type of the JSON value (explicit)
Definition: json.hpp:1894
nlohmann::basic_json::operator>>
friend std::ostream & operator>>(const basic_json &j, std::ostream &o)
serialize to stream
Definition: json.hpp:4665
nlohmann::basic_json::value
ValueType value(const typename object_t::key_type &key, ValueType default_value) const
access specified object element with default value
Definition: json.hpp:2896
nlohmann::basic_json::basic_json
basic_json(size_type count, const basic_json &value)
construct an array with count copies of given value
Definition: json.hpp:1530
nlohmann::basic_json::json_reverse_iterator::key
object_t::key_type key() const
return the key of an object iterator
Definition: json.hpp:5930
nlohmann::basic_json::is_structured
bool is_structured() const noexcept
return whether type is structured
Definition: json.hpp:1935
nlohmann
namespace for Niels Lohmann
Definition: json.hpp:78
nlohmann::basic_json::const_iterator::difference_type
typename basic_json::difference_type difference_type
a type to represent differences between iterators
Definition: json.hpp:5241
nlohmann::basic_json::swap
void swap(array_t &other)
exchanges the values
Definition: json.hpp:4213
nlohmann::basic_json::rbegin
reverse_iterator rbegin()
returns an iterator to the reverse-beginning
Definition: json.hpp:3489
nlohmann::basic_json::value_t::string
string value
nlohmann::basic_json::iterator_wrapper::begin
iterator_wrapper_internal begin()
return iterator begin (needed for range-based for)
Definition: json.hpp:6033
nlohmann::basic_json::iterator::operator[]
reference operator[](difference_type n) const
access to successor
Definition: json.hpp:5823
nlohmann::basic_json::size_type
std::size_t size_type
a type to represent container sizes
Definition: json.hpp:221
nlohmann::basic_json::operator+=
reference operator+=(basic_json &&value)
add an object to an array
Definition: json.hpp:3883
nlohmann::basic_json::rbegin
const_reverse_iterator rbegin() const
returns a const reverse iterator to the last element
Definition: json.hpp:3497
nlohmann::basic_json::~basic_json
~basic_json()
destructor
Definition: json.hpp:1794
nlohmann::basic_json::basic_json
basic_json(const array_t &value)
create an array (explicit)
Definition: json.hpp:992
nlohmann::basic_json::basic_json
basic_json(const basic_json &other)
copy constructor
Definition: json.hpp:1672
nlohmann::basic_json::const_iterator::operator+
const_iterator operator+(difference_type i)
add to iterator
Definition: json.hpp:5615
nlohmann::basic_json::basic_json
basic_json(boolean_t value)
create a boolean (explicit)
Definition: json.hpp:1131
nlohmann::basic_json::value_t
value_t
the JSON type enumeration
Definition: json.hpp:611
nlohmann::basic_json::const_reference
const value_type & const_reference
the type of an element const reference
Definition: json.hpp:215
nlohmann::basic_json::basic_json
basic_json(const CompatibleNumberFloatType value) noexcept
create an floating-point number (implicit)
Definition: json.hpp:1304
nlohmann::basic_json::is_null
bool is_null() const noexcept
return whether value is null
Definition: json.hpp:1954
nlohmann::basic_json::swap
void swap(string_t &other)
exchanges the values
Definition: json.hpp:4277
nlohmann::basic_json::iterator::value
reference value() const
return the value of an iterator
Definition: json.hpp:5829
nlohmann::basic_json::push_back
void push_back(basic_json &&value)
add an object to an array
Definition: json.hpp:3858
nlohmann::basic_json::const_iterator::operator--
const_iterator operator--(int)
post-decrement (it–)
Definition: json.hpp:5468
nlohmann::basic_json::erase
void erase(const size_type idx)
remove element from a JSON array given an index
Definition: json.hpp:3257
nlohmann::basic_json::clear
void clear() noexcept
clears the contents
Definition: json.hpp:3792
nlohmann::basic_json::basic_json
basic_json(const CompatibleStringType &value)
create a string (implicit)
Definition: json.hpp:1113
nlohmann::basic_json::iterator::operator->
pointer operator->()
dereference the iterator
Definition: json.hpp:5752
nlohmann::basic_json::value_type
basic_json value_type
the type of elements in a basic_json container
Definition: json.hpp:209
nlohmann::basic_json::value_t::array
array (ordered collection of values)
nlohmann::basic_json::front
const_reference front() const
access the first element
Definition: json.hpp:2955
nlohmann::basic_json::const_iterator::operator>=
bool operator>=(const const_iterator &other) const
comparison: greater than or equal
Definition: json.hpp:5577
nlohmann::basic_json::insert
iterator insert(const_iterator pos, std::initializer_list< basic_json > ilist)
inserts elements
Definition: json.hpp:4146
nlohmann::basic_json::difference_type
std::ptrdiff_t difference_type
a type to represent differences between iterators
Definition: json.hpp:218
nlohmann::basic_json::const_iterator::operator+=
const_iterator & operator+=(difference_type i)
add to iterator
Definition: json.hpp:5583
nlohmann::basic_json::basic_json
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:1376
nlohmann::basic_json::const_iterator::operator-
difference_type operator-(const const_iterator &other) const
return difference
Definition: json.hpp:5631
nlohmann::basic_json::operator==
friend bool operator==(const_reference lhs, const_reference rhs) noexcept
comparison: equal
Definition: json.hpp:4356
nlohmann::basic_json::is_number
bool is_number() const noexcept
return whether value is a number
Definition: json.hpp:1997
nlohmann::basic_json::boolean_t
BooleanType boolean_t
a type for a boolean
Definition: json.hpp:459
nlohmann::basic_json::crend
const_reverse_iterator crend() const
returns a const reverse iterator to one before the first
Definition: json.hpp:3574
nlohmann::basic_json::basic_json
basic_json() noexcept=default
create a null object (implicitly)
nlohmann::basic_json::parse_event_t::key
the parser read a key of a value in an object
nlohmann::basic_json::empty
bool empty() const noexcept
checks whether the container is empty
Definition: json.hpp:3618
nlohmann::basic_json::value
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:2922
nlohmann::basic_json::swap
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:4183
nlohmann::basic_json::basic_json
basic_json(const object_t &value)
create an object (explicit)
Definition: json.hpp:933
nlohmann::basic_json::const_reverse_iterator
json_reverse_iterator< typename basic_json::const_iterator > const_reverse_iterator
a const reverse iterator for a basic_json container
Definition: json.hpp:241
nlohmann::basic_json::crbegin
const_reverse_iterator crbegin() const
returns a const reverse iterator to the last element
Definition: json.hpp:3551
nlohmann::basic_json::json_reverse_iterator::value
reference value() const
return the value of an iterator
Definition: json.hpp:5937
nlohmann::basic_json::value_t::null
null value
nlohmann::basic_json::const_iterator::const_iterator
const_iterator(pointer object)
constructor for a given JSON instance
Definition: json.hpp:5253
nlohmann::basic_json::operator<
friend bool operator<(const value_t lhs, const value_t rhs)
comparison operator for JSON types
Definition: json.hpp:4310
nlohmann::basic_json::iterator::iterator
iterator(pointer object) noexcept
constructor for a given JSON instance
Definition: json.hpp:5725
nlohmann::basic_json::const_iterator::operator<
bool operator<(const const_iterator &other) const
comparison: smaller
Definition: json.hpp:5537
nlohmann::basic_json::dump
string_t dump(const int indent=-1) const
serialization
Definition: json.hpp:1863
nlohmann::basic_json::operator!=
friend bool operator!=(const_reference v, std::nullptr_t) noexcept
comparison: not equal
Definition: json.hpp:4467
nlohmann::basic_json::const_iterator::operator-=
const_iterator & operator-=(difference_type i)
subtract from iterator
Definition: json.hpp:5609
nlohmann::basic_json::value_t::number_float
number value (floating-point)
nlohmann::basic_json::basic_json
basic_json(const CompatibleNumberIntegerType value) noexcept
create an integer number (implicit)
Definition: json.hpp:1229
nlohmann::basic_json::parse
static basic_json parse(const string_t &s, parser_callback_t cb=nullptr)
deserialize from string
Definition: json.hpp:4704
nlohmann::basic_json::erase
InteratorType erase(InteratorType first, InteratorType last)
remove elements given an iterator range
Definition: json.hpp:3147
nlohmann::basic_json::json_reverse_iterator::operator++
json_reverse_iterator operator++(int)
post-increment (it++)
Definition: json.hpp:5869
nlohmann::basic_json::get_ptr
PointerType get_ptr() noexcept
get a pointer value (implicit)
Definition: json.hpp:2494
nlohmann::basic_json::push_back
void push_back(const basic_json &value)
add an object to an array
Definition: json.hpp:3893
nlohmann::basic_json::value_t::boolean
boolean value
nlohmann::basic_json::const_iterator::const_iterator
const_iterator(const iterator &other)
copy constructor given a nonconst iterator
Definition: json.hpp:5278
nlohmann::basic_json::operator!=
friend bool operator!=(std::nullptr_t, const_reference v) noexcept
comparison: not equal
Definition: json.hpp:4476
nlohmann::basic_json::erase
InteratorType erase(InteratorType pos)
remove element given an iterator
Definition: json.hpp:3046
nlohmann::basic_json::basic_json
basic_json(const typename string_t::value_type *value)
create a string (explicit)
Definition: json.hpp:1082
nlohmann::basic_json::const_iterator::operator<=
bool operator<=(const const_iterator &other) const
comparison: less than or equal
Definition: json.hpp:5565
nlohmann::basic_json::back
reference back()
access the last element
Definition: json.hpp:2981
nlohmann::basic_json::is_number_float
bool is_number_float() const noexcept
return whether value is a floating-point number
Definition: json.hpp:2043
nlohmann::basic_json::parse_event_t::object_start
the parser read { and started to process a JSON object
nlohmann::basic_json::const_iterator::operator++
const_iterator operator++(int)
post-increment (it++)
Definition: json.hpp:5433
nlohmann::basic_json::const_pointer
typename std::allocator_traits< allocator_type >::const_pointer const_pointer
the type of an element const pointer
Definition: json.hpp:229
nlohmann::basic_json::iterator::iterator
iterator(const iterator &other) noexcept
copy constructor
Definition: json.hpp:5729
nlohmann::basic_json::back
const_reference back() const
access the last element
Definition: json.hpp:2991
nlohmann::basic_json::basic_json
basic_json(InputIT first, InputIT last)
construct a JSON container given an iterator range
Definition: json.hpp:1574
nlohmann::basic_json::parse
static basic_json parse(std::istream &i, parser_callback_t cb=nullptr)
deserialize from stream
Definition: json.hpp:4733
nlohmann::basic_json::count
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:3338
nlohmann::basic_json::max_size
size_type max_size() const noexcept
returns the maximum possible number of elements
Definition: json.hpp:3735
nlohmann::basic_json::const_iterator::operator==
bool operator==(const const_iterator &other) const
comparison: equal
Definition: json.hpp:5503
nlohmann::basic_json::json_reverse_iterator::operator++
json_reverse_iterator & operator++()
pre-increment (++it)
Definition: json.hpp:5875
nlohmann::basic_json::const_iterator::operator>
bool operator>(const const_iterator &other) const
comparison: greater than
Definition: json.hpp:5571
nlohmann::basic_json::operator>
friend bool operator>(const_reference lhs, const_reference rhs) noexcept
comparison: greater than
Definition: json.hpp:4588
nlohmann::basic_json::basic_json
basic_json(basic_json &&other) noexcept
move constructor
Definition: json.hpp:1738
nlohmann::basic_json::begin
const_iterator begin() const
returns a const iterator to the first element
Definition: json.hpp:3382
nlohmann::basic_json::at
const_reference at(size_type idx) const
access specified array element with bounds checking
Definition: json.hpp:2611
nlohmann::basic_json::json_reverse_iterator::operator+=
json_reverse_iterator & operator+=(difference_type i)
add to iterator
Definition: json.hpp:5895
nlohmann::basic_json::const_iterator
a const random access iterator for the basic_json class
Definition: json.hpp:5232
nlohmann::basic_json::json_reverse_iterator
a template for a reverse iterator class
Definition: json.hpp:232
nlohmann::basic_json::swap
void swap(object_t &other)
exchanges the values
Definition: json.hpp:4245
nlohmann::basic_json::const_iterator::iterator_category
std::bidirectional_iterator_tag iterator_category
the category of the iterator
Definition: json.hpp:5247
nlohmann::basic_json::is_primitive
bool is_primitive() const noexcept
return whether type is primitive
Definition: json.hpp:1915
nlohmann::basic_json::basic_json
basic_json(const value_t value)
create an empty value with a given type
Definition: json.hpp:866
nlohmann::basic_json::operator==
friend bool operator==(const_reference v, std::nullptr_t) noexcept
comparison: equal
Definition: json.hpp:4414
nlohmann::basic_json::value_t::number_integer
number value (integer)
nlohmann::basic_json::json_reverse_iterator::operator[]
reference operator[](difference_type n) const
access to successor
Definition: json.hpp:5924
nlohmann::basic_json::number_integer_t
NumberIntegerType number_integer_t
a type for a number (integer)
Definition: json.hpp:527
nlohmann::basic_json::const_iterator::operator[]
reference operator[](difference_type n) const
access to successor
Definition: json.hpp:5653
nlohmann::basic_json::const_iterator::operator*
reference operator*() const
return a reference to the value pointed to by the iterator
Definition: json.hpp:5380
nlohmann::basic_json::insert
iterator insert(const_iterator pos, const basic_json &value)
inserts element
Definition: json.hpp:3991
nlohmann::basic_json::reference
value_type & reference
the type of an element reference
Definition: json.hpp:212
nlohmann::basic_json::operator<<
friend std::istream & operator<<(basic_json &j, std::istream &i)
deserialize from stream
Definition: json.hpp:4769
nlohmann::basic_json::parse_event_t::value
the parser finished reading a JSON value
nlohmann::basic_json::number_float_t
NumberFloatType number_float_t
a type for a number (floating-point)
Definition: json.hpp:592
std::hash< nlohmann::json >::operator()
std::size_t operator()(const nlohmann::json &j) const
return a hash value for a JSON object
Definition: json.hpp:7567
nlohmann::basic_json::operator<<
friend std::ostream & operator<<(std::ostream &o, const basic_json &j)
serialize to stream
Definition: json.hpp:4647
nlohmann::basic_json::iterator::operator=
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:5734
nlohmann::basic_json::operator[]
reference operator[](size_type idx)
access specified array element
Definition: json.hpp:2709
nlohmann::basic_json::iterator::operator--
iterator operator--(int)
post-decrement (it–)
Definition: json.hpp:5773
nlohmann::basic_json::json_reverse_iterator::operator+
json_reverse_iterator operator+(difference_type i) const
add to iterator
Definition: json.hpp:5902
nlohmann::basic_json::parse_event_t
parse_event_t
JSON callback events.
Definition: json.hpp:754
nlohmann::basic_json::iterator::operator-
iterator operator-(difference_type i)
subtract from iterator
Definition: json.hpp:5810
nlohmann::basic_json::iterator_wrapper
wrapper to access iterator member functions in range-based for
Definition: json.hpp:5951