JSON for Modern C++ 1.0.0

- 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 <cassert>
44 #include <ciso646>
45 #include <cmath>
46 #include <cstddef>
47 #include <cstdio>
48 #include <cstdlib>
49 #include <functional>
50 #include <initializer_list>
51 #include <iomanip>
52 #include <iostream>
53 #include <iterator>
54 #include <limits>
55 #include <map>
56 #include <memory>
57 #include <sstream>
58 #include <stdexcept>
59 #include <string>
60 #include <type_traits>
61 #include <utility>
62 #include <vector>
63
64 // enable ssize_t on MinGW
65 #ifdef __GNUC__
66 #ifdef __MINGW32__
67 #include <sys/types.h>
68 #endif
69 #endif
70
71 // disable float-equal warnings on GCC/clang
72 #if defined(__clang__) || defined(__GNUC__) || defined(__GNUG__)
73 #pragma GCC diagnostic push
74 #pragma GCC diagnostic ignored "-Wfloat-equal"
75 #endif
76
77 // enable ssize_t for MSVC
78 #ifdef _MSC_VER
79 #include <basetsd.h>
80 using ssize_t = SSIZE_T;
81 #endif
82
88 namespace nlohmann
89 {
90
91
96 namespace
97 {
102 template<typename T>
103 struct has_mapped_type
104 {
105 private:
106 template<typename C> static char test(typename C::mapped_type*);
107 template<typename C> static char (&test(...))[2];
108 public:
109 static constexpr bool value = sizeof(test<T>(0)) == 1;
110 };
111
112 }
113
182 template <
183 template<typename U, typename V, typename... Args> class ObjectType = std::map,
184 template<typename U, typename... Args> class ArrayType = std::vector,
185 class StringType = std::string,
186 class BooleanType = bool,
187 class NumberIntegerType = int64_t,
188 class NumberFloatType = double,
189 template<typename U> class AllocatorType = std::allocator
190 >
191 class basic_json
192 {
193 private:
195 using basic_json_t = basic_json<ObjectType,
196 ArrayType,
197 StringType,
198 BooleanType,
199 NumberIntegerType,
200 NumberFloatType,
201 AllocatorType>;
202
203 public:
204
206 // container types //
208
211
213 using value_type = basic_json;
214
216 using reference = value_type&;
218 using const_reference = const value_type&;
219
221 using difference_type = std::ptrdiff_t;
223 using size_type = std::size_t;
224
226 using allocator_type = AllocatorType<basic_json>;
227
229 using pointer = typename std::allocator_traits<allocator_type>::pointer;
231 using const_pointer = typename std::allocator_traits<allocator_type>::const_pointer;
232
233 // forward declaration
234 template<typename Base> class json_reverse_iterator;
235
237 class iterator;
239 class const_iterator;
241 using reverse_iterator = json_reverse_iterator<typename basic_json::iterator>;
243 using const_reverse_iterator = json_reverse_iterator<typename basic_json::const_iterator>;
244
246
247
251 static allocator_type get_allocator()
252 {
253 return allocator_type();
254 }
255
256
258 // JSON value data types //
260
263
346 using object_t = ObjectType<StringType,
347 basic_json,
348 std::less<StringType>,
349 AllocatorType<std::pair<const StringType,
350 basic_json>>>;
351
396 using array_t = ArrayType<basic_json, AllocatorType<basic_json>>;
397
443 using string_t = StringType;
444
469 using boolean_t = BooleanType;
470
537 using number_integer_t = NumberIntegerType;
538
602 using number_float_t = NumberFloatType;
603
605
606
608 // JSON type enumeration //
610
621 enum class value_t : uint8_t
622 {
623 null,
624 object,
625 array,
626 string,
627 boolean,
628 number_integer,
629 number_float,
630 discarded
631 };
632
633
634 private:
636 template<typename T, typename... Args>
637 static T* create(Args&& ... args)
638 {
639 AllocatorType<T> alloc;
640 auto deleter = [&](T * object)
641 {
642 alloc.deallocate(object, 1);
643 };
644 std::unique_ptr<T, decltype(deleter)> object(alloc.allocate(1), deleter);
645 alloc.construct(object.get(), std::forward<Args>(args)...);
646 return object.release();
647 }
648
650 // JSON value storage //
652
660 union json_value
661 {
663 object_t* object;
665 array_t* array;
667 string_t* string;
669 boolean_t boolean;
671 number_integer_t number_integer;
673 number_float_t number_float;
674
676 json_value() noexcept = default;
678 json_value(boolean_t v) noexcept : boolean(v) {}
680 json_value(number_integer_t v) noexcept : number_integer(v) {}
682 json_value(number_float_t v) noexcept : number_float(v) {}
684 json_value(value_t t)
685 {
686 switch (t)
687 {
688 case value_t::object:
689 {
690 object = create<object_t>();
691 break;
692 }
693
694 case value_t::array:
695 {
696 array = create<array_t>();
697 break;
698 }
699
700 case value_t::string:
701 {
702 string = create<string_t>("");
703 break;
704 }
705
706 case value_t::boolean:
707 {
708 boolean = boolean_t(false);
709 break;
710 }
711
712 case value_t::number_integer:
713 {
714 number_integer = number_integer_t(0);
715 break;
716 }
717
718 case value_t::number_float:
719 {
720 number_float = number_float_t(0.0);
721 break;
722 }
723
724 default:
725 {
726 break;
727 }
728 }
729 }
730
732 json_value(const string_t& value)
733 {
734 string = create<string_t>(value);
735 }
736
738 json_value(const object_t& value)
739 {
740 object = create<object_t>(value);
741 }
742
744 json_value(const array_t& value)
745 {
746 array = create<array_t>(value);
747 }
748 };
749
750
751 public:
753 // JSON parser callback //
755
764 enum class parse_event_t : uint8_t
765 {
767 object_start,
769 object_end,
771 array_start,
773 array_end,
775 key,
777 value
778 };
779
829 using parser_callback_t = std::function<bool(int depth, parse_event_t event, basic_json& parsed)>;
830
831
833 // constructors //
835
838
876 basic_json(const value_t value_type)
877 : m_type(value_type), m_value(value_type)
878 {}
879
899 basic_json() noexcept = default;
900
920 basic_json(std::nullptr_t) noexcept
921 : basic_json(value_t::null)
922 {}
923
943 basic_json(const object_t& val)
944 : m_type(value_t::object), m_value(val)
945 {}
946
970 template <class CompatibleObjectType, typename
971 std::enable_if<
972 std::is_constructible<typename object_t::key_type, typename CompatibleObjectType::key_type>::value and
973 std::is_constructible<basic_json, typename CompatibleObjectType::mapped_type>::value, int>::type
974 = 0>
975 basic_json(const CompatibleObjectType& val)
976 : m_type(value_t::object)
977 {
978 using std::begin;
979 using std::end;
980 m_value.object = create<object_t>(begin(val), end(val));
981 }
982
1002 basic_json(const array_t& val)
1003 : m_type(value_t::array), m_value(val)
1004 {}
1005
1029 template <class CompatibleArrayType, typename
1030 std::enable_if<
1031 not std::is_same<CompatibleArrayType, typename basic_json_t::iterator>::value and
1032 not std::is_same<CompatibleArrayType, typename basic_json_t::const_iterator>::value and
1033 not std::is_same<CompatibleArrayType, typename basic_json_t::reverse_iterator>::value and
1034 not std::is_same<CompatibleArrayType, typename basic_json_t::const_reverse_iterator>::value and
1035 not std::is_same<CompatibleArrayType, typename array_t::iterator>::value and
1036 not std::is_same<CompatibleArrayType, typename array_t::const_iterator>::value and
1037 std::is_constructible<basic_json, typename CompatibleArrayType::value_type>::value, int>::type
1038 = 0>
1039 basic_json(const CompatibleArrayType& val)
1040 : m_type(value_t::array)
1041 {
1042 using std::begin;
1043 using std::end;
1044 m_value.array = create<array_t>(begin(val), end(val));
1045 }
1046
1068 basic_json(const string_t& val)
1069 : m_type(value_t::string), m_value(val)
1070 {}
1071
1092 basic_json(const typename string_t::value_type* val)
1093 : basic_json(string_t(val))
1094 {}
1095
1119 template <class CompatibleStringType, typename
1120 std::enable_if<
1121 std::is_constructible<string_t, CompatibleStringType>::value, int>::type
1122 = 0>
1123 basic_json(const CompatibleStringType& val)
1124 : basic_json(string_t(val))
1125 {}
1126
1141 basic_json(boolean_t val)
1142 : m_type(value_t::boolean), m_value(val)
1143 {}
1144
1170 template<typename T,
1171 typename std::enable_if<
1172 not (std::is_same<T, int>::value)
1173 and std::is_same<T, number_integer_t>::value
1174 , int>::type = 0>
1175 basic_json(const number_integer_t val)
1176 : m_type(value_t::number_integer), m_value(val)
1177 {}
1178
1204 basic_json(const int val)
1205 : m_type(value_t::number_integer),
1206 m_value(static_cast<number_integer_t>(val))
1207 {}
1208
1234 template<typename CompatibleNumberIntegerType, typename
1235 std::enable_if<
1236 std::is_constructible<number_integer_t, CompatibleNumberIntegerType>::value and
1237 std::numeric_limits<CompatibleNumberIntegerType>::is_integer, CompatibleNumberIntegerType>::type
1238 = 0>
1239 basic_json(const CompatibleNumberIntegerType val) noexcept
1240 : m_type(value_t::number_integer),
1241 m_value(static_cast<number_integer_t>(val))
1242 {}
1243
1268 basic_json(const number_float_t val)
1269 : m_type(value_t::number_float), m_value(val)
1270 {
1271 // replace infinity and NAN by null
1272 if (not std::isfinite(val))
1273 {
1274 m_type = value_t::null;
1275 m_value = json_value();
1276 }
1277 }
1278
1309 template<typename CompatibleNumberFloatType, typename = typename
1310 std::enable_if<
1311 std::is_constructible<number_float_t, CompatibleNumberFloatType>::value and
1312 std::is_floating_point<CompatibleNumberFloatType>::value>::type
1313 >
1314 basic_json(const CompatibleNumberFloatType val) noexcept
1315 : basic_json(number_float_t(val))
1316 {}
1317
1387 basic_json(std::initializer_list<basic_json> init,
1388 bool type_deduction = true,
1389 value_t manual_type = value_t::array)
1390 {
1391 // the initializer list could describe an object
1392 bool is_an_object = true;
1393
1394 // check if each element is an array with two elements whose first
1395 // element is a string
1396 for (const auto& element : init)
1397 {
1398 if (not element.is_array() or element.size() != 2
1399 or not element[0].is_string())
1400 {
1401 // we found an element that makes it impossible to use the
1402 // initializer list as object
1403 is_an_object = false;
1404 break;
1405 }
1406 }
1407
1408 // adjust type if type deduction is not wanted
1409 if (not type_deduction)
1410 {
1411 // if array is wanted, do not create an object though possible
1412 if (manual_type == value_t::array)
1413 {
1414 is_an_object = false;
1415 }
1416
1417 // if object is wanted but impossible, throw an exception
1418 if (manual_type == value_t::object and not is_an_object)
1419 {
1420 throw std::domain_error("cannot create object from initializer list");
1421 }
1422 }
1423
1424 if (is_an_object)
1425 {
1426 // the initializer list is a list of pairs -> create object
1427 m_type = value_t::object;
1428 m_value = value_t::object;
1429
1430 assert(m_value.object != nullptr);
1431
1432 for (auto& element : init)
1433 {
1434 m_value.object->emplace(std::move(*(element[0].m_value.string)), std::move(element[1]));
1435 }
1436 }
1437 else
1438 {
1439 // the initializer list describes an array -> create array
1440 m_type = value_t::array;
1441 m_value.array = create<array_t>(std::move(init));
1442 }
1443 }
1444
1479 static basic_json array(std::initializer_list<basic_json> init =
1480 std::initializer_list<basic_json>())
1481 {
1482 return basic_json(init, false, value_t::array);
1483 }
1484
1519 static basic_json object(std::initializer_list<basic_json> init =
1520 std::initializer_list<basic_json>())
1521 {
1522 return basic_json(init, false, value_t::object);
1523 }
1524
1543 basic_json(size_type cnt, const basic_json& val)
1544 : m_type(value_t::array)
1545 {
1546 m_value.array = create<array_t>(cnt, val);
1547 }
1548
1583 template <class InputIT, typename
1584 std::enable_if<
1585 std::is_same<InputIT, typename basic_json_t::iterator>::value or
1586 std::is_same<InputIT, typename basic_json_t::const_iterator>::value
1587 , int>::type
1588 = 0>
1589 basic_json(InputIT first, InputIT last) : m_type(first.m_object->m_type)
1590 {
1591 // make sure iterator fits the current value
1592 if (first.m_object != last.m_object)
1593 {
1594 throw std::domain_error("iterators are not compatible");
1595 }
1596
1597 // check if iterator range is complete for primitive values
1598 switch (m_type)
1599 {
1600 case value_t::boolean:
1601 case value_t::number_float:
1602 case value_t::number_integer:
1603 case value_t::string:
1604 {
1605 if (not first.m_it.primitive_iterator.is_begin() or not last.m_it.primitive_iterator.is_end())
1606 {
1607 throw std::out_of_range("iterators out of range");
1608 }
1609 break;
1610 }
1611
1612 default:
1613 {
1614 break;
1615 }
1616 }
1617
1618 switch (m_type)
1619 {
1620 case value_t::number_integer:
1621 {
1622 assert(first.m_object != nullptr);
1623 m_value.number_integer = first.m_object->m_value.number_integer;
1624 break;
1625 }
1626
1627 case value_t::number_float:
1628 {
1629 assert(first.m_object != nullptr);
1630 m_value.number_float = first.m_object->m_value.number_float;
1631 break;
1632 }
1633
1634 case value_t::boolean:
1635 {
1636 assert(first.m_object != nullptr);
1637 m_value.boolean = first.m_object->m_value.boolean;
1638 break;
1639 }
1640
1641 case value_t::string:
1642 {
1643 assert(first.m_object != nullptr);
1644 m_value = *first.m_object->m_value.string;
1645 break;
1646 }
1647
1648 case value_t::object:
1649 {
1650 m_value.object = create<object_t>(first.m_it.object_iterator, last.m_it.object_iterator);
1651 break;
1652 }
1653
1654 case value_t::array:
1655 {
1656 m_value.array = create<array_t>(first.m_it.array_iterator, last.m_it.array_iterator);
1657 break;
1658 }
1659
1660 default:
1661 {
1662 assert(first.m_object != nullptr);
1663 throw std::domain_error("cannot use construct with iterators from " + first.m_object->type_name());
1664 }
1665 }
1666 }
1667
1669 // other constructors and destructor //
1671
1692 basic_json(const basic_json& other)
1693 : m_type(other.m_type)
1694 {
1695 switch (m_type)
1696 {
1697 case value_t::object:
1698 {
1699 assert(other.m_value.object != nullptr);
1700 m_value = *other.m_value.object;
1701 break;
1702 }
1703
1704 case value_t::array:
1705 {
1706 assert(other.m_value.array != nullptr);
1707 m_value = *other.m_value.array;
1708 break;
1709 }
1710
1711 case value_t::string:
1712 {
1713 assert(other.m_value.string != nullptr);
1714 m_value = *other.m_value.string;
1715 break;
1716 }
1717
1718 case value_t::boolean:
1719 {
1720 m_value = other.m_value.boolean;
1721 break;
1722 }
1723
1724 case value_t::number_integer:
1725 {
1726 m_value = other.m_value.number_integer;
1727 break;
1728 }
1729
1730 case value_t::number_float:
1731 {
1732 m_value = other.m_value.number_float;
1733 break;
1734 }
1735
1736 default:
1737 {
1738 break;
1739 }
1740 }
1741 }
1742
1761 basic_json(basic_json&& other) noexcept
1762 : m_type(std::move(other.m_type)),
1763 m_value(std::move(other.m_value))
1764 {
1765 // invalidate payload
1766 other.m_type = value_t::null;
1767 other.m_value = {};
1768 }
1769
1791 reference& operator=(basic_json other) noexcept (
1792 std::is_nothrow_move_constructible<value_t>::value and
1793 std::is_nothrow_move_assignable<value_t>::value and
1794 std::is_nothrow_move_constructible<json_value>::value and
1795 std::is_nothrow_move_assignable<json_value>::value
1796 )
1797 {
1798 using std::swap;
1799 swap(m_type, other.m_type);
1800 swap(m_value, other.m_value);
1801 return *this;
1802 }
1803
1817 ~basic_json()
1818 {
1819 switch (m_type)
1820 {
1821 case value_t::object:
1822 {
1823 AllocatorType<object_t> alloc;
1824 alloc.destroy(m_value.object);
1825 alloc.deallocate(m_value.object, 1);
1826 break;
1827 }
1828
1829 case value_t::array:
1830 {
1831 AllocatorType<array_t> alloc;
1832 alloc.destroy(m_value.array);
1833 alloc.deallocate(m_value.array, 1);
1834 break;
1835 }
1836
1837 case value_t::string:
1838 {
1839 AllocatorType<string_t> alloc;
1840 alloc.destroy(m_value.string);
1841 alloc.deallocate(m_value.string, 1);
1842 break;
1843 }
1844
1845 default:
1846 {
1847 // all other types need no specific destructor
1848 break;
1849 }
1850 }
1851 }
1852
1854
1855 public:
1857 // object inspection //
1859
1862
1886 string_t dump(const int indent = -1) const
1887 {
1888 std::stringstream ss;
1889
1890 if (indent >= 0)
1891 {
1892 dump(ss, true, static_cast<unsigned int>(indent));
1893 }
1894 else
1895 {
1896 dump(ss, false, 0);
1897 }
1898
1899 return ss.str();
1900 }
1901
1917 value_t type() const noexcept
1918 {
1919 return m_type;
1920 }
1921
1938 bool is_primitive() const noexcept
1939 {
1940 return is_null() or is_string() or is_boolean() or is_number();
1941 }
1942
1958 bool is_structured() const noexcept
1959 {
1960 return is_array() or is_object();
1961 }
1962
1977 bool is_null() const noexcept
1978 {
1979 return m_type == value_t::null;
1980 }
1981
1996 bool is_boolean() const noexcept
1997 {
1998 return m_type == value_t::boolean;
1999 }
2000
2020 bool is_number() const noexcept
2021 {
2022 return is_number_integer() or is_number_float();
2023 }
2024
2043 bool is_number_integer() const noexcept
2044 {
2045 return m_type == value_t::number_integer;
2046 }
2047
2066 bool is_number_float() const noexcept
2067 {
2068 return m_type == value_t::number_float;
2069 }
2070
2085 bool is_object() const noexcept
2086 {
2087 return m_type == value_t::object;
2088 }
2089
2104 bool is_array() const noexcept
2105 {
2106 return m_type == value_t::array;
2107 }
2108
2123 bool is_string() const noexcept
2124 {
2125 return m_type == value_t::string;
2126 }
2127
2147 bool is_discarded() const noexcept
2148 {
2149 return m_type == value_t::discarded;
2150 }
2151
2167 operator value_t() const noexcept
2168 {
2169 return m_type;
2170 }
2171
2173
2174 private:
2176 // value access //
2178
2180 template <class T, typename
2181 std::enable_if<
2182 std::is_convertible<typename object_t::key_type, typename T::key_type>::value and
2183 std::is_convertible<basic_json_t, typename T::mapped_type>::value
2184 , int>::type = 0>
2185 T get_impl(T*) const
2186 {
2187 if (is_object())
2188 {
2189 assert(m_value.object != nullptr);
2190 return T(m_value.object->begin(), m_value.object->end());
2191 }
2192 else
2193 {
2194 throw std::domain_error("type must be object, but is " + type_name());
2195 }
2196 }
2197
2199 object_t get_impl(object_t*) const
2200 {
2201 if (is_object())
2202 {
2203 assert(m_value.object != nullptr);
2204 return *(m_value.object);
2205 }
2206 else
2207 {
2208 throw std::domain_error("type must be object, but is " + type_name());
2209 }
2210 }
2211
2213 template <class T, typename
2214 std::enable_if<
2215 std::is_convertible<basic_json_t, typename T::value_type>::value and
2216 not std::is_same<basic_json_t, typename T::value_type>::value and
2217 not std::is_arithmetic<T>::value and
2218 not std::is_convertible<std::string, T>::value and
2219 not has_mapped_type<T>::value
2220 , int>::type = 0>
2221 T get_impl(T*) const
2222 {
2223 if (is_array())
2224 {
2225 T to_vector;
2226 assert(m_value.array != nullptr);
2227 std::transform(m_value.array->begin(), m_value.array->end(),
2228 std::inserter(to_vector, to_vector.end()), [](basic_json i)
2229 {
2230 return i.get<typename T::value_type>();
2231 });
2232 return to_vector;
2233 }
2234 else
2235 {
2236 throw std::domain_error("type must be array, but is " + type_name());
2237 }
2238 }
2239
2241 template <class T, typename
2242 std::enable_if<
2243 std::is_convertible<basic_json_t, T>::value and
2244 not std::is_same<basic_json_t, T>::value
2245 , int>::type = 0>
2246 std::vector<T> get_impl(std::vector<T>*) const
2247 {
2248 if (is_array())
2249 {
2250 std::vector<T> to_vector;
2251 assert(m_value.array != nullptr);
2252 to_vector.reserve(m_value.array->size());
2253 std::transform(m_value.array->begin(), m_value.array->end(),
2254 std::inserter(to_vector, to_vector.end()), [](basic_json i)
2255 {
2256 return i.get<T>();
2257 });
2258 return to_vector;
2259 }
2260 else
2261 {
2262 throw std::domain_error("type must be array, but is " + type_name());
2263 }
2264 }
2265
2267 template <class T, typename
2268 std::enable_if<
2269 std::is_same<basic_json, typename T::value_type>::value and
2270 not has_mapped_type<T>::value
2271 , int>::type = 0>
2272 T get_impl(T*) const
2273 {
2274 if (is_array())
2275 {
2276 assert(m_value.array != nullptr);
2277 return T(m_value.array->begin(), m_value.array->end());
2278 }
2279 else
2280 {
2281 throw std::domain_error("type must be array, but is " + type_name());
2282 }
2283 }
2284
2286 array_t get_impl(array_t*) const
2287 {
2288 if (is_array())
2289 {
2290 assert(m_value.array != nullptr);
2291 return *(m_value.array);
2292 }
2293 else
2294 {
2295 throw std::domain_error("type must be array, but is " + type_name());
2296 }
2297 }
2298
2300 template <typename T, typename
2301 std::enable_if<
2302 std::is_convertible<string_t, T>::value
2303 , int>::type = 0>
2304 T get_impl(T*) const
2305 {
2306 if (is_string())
2307 {
2308 assert(m_value.string != nullptr);
2309 return *m_value.string;
2310 }
2311 else
2312 {
2313 throw std::domain_error("type must be string, but is " + type_name());
2314 }
2315 }
2316
2318 template<typename T, typename
2319 std::enable_if<
2320 std::is_arithmetic<T>::value
2321 , int>::type = 0>
2322 T get_impl(T*) const
2323 {
2324 switch (m_type)
2325 {
2326 case value_t::number_integer:
2327 {
2328 return static_cast<T>(m_value.number_integer);
2329 }
2330
2331 case value_t::number_float:
2332 {
2333 return static_cast<T>(m_value.number_float);
2334 }
2335
2336 default:
2337 {
2338 throw std::domain_error("type must be number, but is " + type_name());
2339 }
2340 }
2341 }
2342
2344 boolean_t get_impl(boolean_t*) const
2345 {
2346 if (is_boolean())
2347 {
2348 return m_value.boolean;
2349 }
2350 else
2351 {
2352 throw std::domain_error("type must be boolean, but is " + type_name());
2353 }
2354 }
2355
2357 object_t* get_impl_ptr(object_t*) noexcept
2358 {
2359 return is_object() ? m_value.object : nullptr;
2360 }
2361
2363 const object_t* get_impl_ptr(const object_t*) const noexcept
2364 {
2365 return is_object() ? m_value.object : nullptr;
2366 }
2367
2369 array_t* get_impl_ptr(array_t*) noexcept
2370 {
2371 return is_array() ? m_value.array : nullptr;
2372 }
2373
2375 const array_t* get_impl_ptr(const array_t*) const noexcept
2376 {
2377 return is_array() ? m_value.array : nullptr;
2378 }
2379
2381 string_t* get_impl_ptr(string_t*) noexcept
2382 {
2383 return is_string() ? m_value.string : nullptr;
2384 }
2385
2387 const string_t* get_impl_ptr(const string_t*) const noexcept
2388 {
2389 return is_string() ? m_value.string : nullptr;
2390 }
2391
2393 boolean_t* get_impl_ptr(boolean_t*) noexcept
2394 {
2395 return is_boolean() ? &m_value.boolean : nullptr;
2396 }
2397
2399 const boolean_t* get_impl_ptr(const boolean_t*) const noexcept
2400 {
2401 return is_boolean() ? &m_value.boolean : nullptr;
2402 }
2403
2405 number_integer_t* get_impl_ptr(number_integer_t*) noexcept
2406 {
2407 return is_number_integer() ? &m_value.number_integer : nullptr;
2408 }
2409
2411 const number_integer_t* get_impl_ptr(const number_integer_t*) const noexcept
2412 {
2413 return is_number_integer() ? &m_value.number_integer : nullptr;
2414 }
2415
2417 number_float_t* get_impl_ptr(number_float_t*) noexcept
2418 {
2419 return is_number_float() ? &m_value.number_float : nullptr;
2420 }
2421
2423 const number_float_t* get_impl_ptr(const number_float_t*) const noexcept
2424 {
2425 return is_number_float() ? &m_value.number_float : nullptr;
2426 }
2427
2439 template<typename ReferenceType, typename ThisType>
2440 static ReferenceType get_ref_impl(ThisType& obj)
2441 {
2442 // delegate the call to get_ptr<>()
2443 using PointerType = typename std::add_pointer<ReferenceType>::type;
2444 auto ptr = obj.template get_ptr<PointerType>();
2445
2446 if (ptr != nullptr)
2447 {
2448 return *ptr;
2449 }
2450 else
2451 {
2452 throw std::domain_error("incompatible ReferenceType for get_ref, actual type is " +
2453 obj.type_name());
2454 }
2455 }
2456
2457 public:
2458
2461
2495 template<typename ValueType, typename
2496 std::enable_if<
2497 not std::is_pointer<ValueType>::value
2498 , int>::type = 0>
2499 ValueType get() const
2500 {
2501 return get_impl(static_cast<ValueType*>(nullptr));
2502 }
2503
2530 template<typename PointerType, typename
2531 std::enable_if<
2532 std::is_pointer<PointerType>::value
2533 , int>::type = 0>
2534 PointerType get() noexcept
2535 {
2536 // delegate the call to get_ptr
2537 return get_ptr<PointerType>();
2538 }
2539
2544 template<typename PointerType, typename
2545 std::enable_if<
2546 std::is_pointer<PointerType>::value
2547 , int>::type = 0>
2548 const PointerType get() const noexcept
2549 {
2550 // delegate the call to get_ptr
2551 return get_ptr<PointerType>();
2552 }
2553
2579 template<typename PointerType, typename
2580 std::enable_if<
2581 std::is_pointer<PointerType>::value
2582 , int>::type = 0>
2583 PointerType get_ptr() noexcept
2584 {
2585 // delegate the call to get_impl_ptr<>()
2586 return get_impl_ptr(static_cast<PointerType>(nullptr));
2587 }
2588
2593 template<typename PointerType, typename
2594 std::enable_if<
2595 std::is_pointer<PointerType>::value
2596 and std::is_const<typename std::remove_pointer<PointerType>::type>::value
2597 , int>::type = 0>
2598 const PointerType get_ptr() const noexcept
2599 {
2600 // delegate the call to get_impl_ptr<>() const
2601 return get_impl_ptr(static_cast<const PointerType>(nullptr));
2602 }
2603
2630 template<typename ReferenceType, typename
2631 std::enable_if<
2632 std::is_reference<ReferenceType>::value
2633 , int>::type = 0>
2634 ReferenceType get_ref()
2635 {
2636 // delegate call to get_ref_impl
2637 return get_ref_impl<ReferenceType>(*this);
2638 }
2639
2644 template<typename ReferenceType, typename
2645 std::enable_if<
2646 std::is_reference<ReferenceType>::value
2647 and std::is_const<typename std::remove_reference<ReferenceType>::type>::value
2648 , int>::type = 0>
2649 ReferenceType get_ref() const
2650 {
2651 // delegate call to get_ref_impl
2652 return get_ref_impl<ReferenceType>(*this);
2653 }
2654
2683 template < typename ValueType, typename
2684 std::enable_if <
2685 not std::is_pointer<ValueType>::value
2686 and not std::is_same<ValueType, typename string_t::value_type>::value
2687 #ifndef _MSC_VER // Fix for issue #167 operator<< abiguity under VS2015
2688 and not std::is_same<ValueType, std::initializer_list<typename string_t::value_type>>::value
2689 #endif
2690 , int >::type = 0 >
2691 operator ValueType() const
2692 {
2693 // delegate the call to get<>() const
2694 return get<ValueType>();
2695 }
2696
2698
2699
2701 // element access //
2703
2706
2729 reference at(size_type idx)
2730 {
2731 // at only works for arrays
2732 if (is_array())
2733 {
2734 try
2735 {
2736 assert(m_value.array != nullptr);
2737 return m_value.array->at(idx);
2738 }
2739 catch (std::out_of_range&)
2740 {
2741 // create better exception explanation
2742 throw std::out_of_range("array index " + std::to_string(idx) + " is out of range");
2743 }
2744 }
2745 else
2746 {
2747 throw std::domain_error("cannot use at() with " + type_name());
2748 }
2749 }
2750
2773 const_reference at(size_type idx) const
2774 {
2775 // at only works for arrays
2776 if (is_array())
2777 {
2778 try
2779 {
2780 assert(m_value.array != nullptr);
2781 return m_value.array->at(idx);
2782 }
2783 catch (std::out_of_range&)
2784 {
2785 // create better exception explanation
2786 throw std::out_of_range("array index " + std::to_string(idx) + " is out of range");
2787 }
2788 }
2789 else
2790 {
2791 throw std::domain_error("cannot use at() with " + type_name());
2792 }
2793 }
2794
2821 reference at(const typename object_t::key_type& key)
2822 {
2823 // at only works for objects
2824 if (is_object())
2825 {
2826 try
2827 {
2828 assert(m_value.object != nullptr);
2829 return m_value.object->at(key);
2830 }
2831 catch (std::out_of_range&)
2832 {
2833 // create better exception explanation
2834 throw std::out_of_range("key '" + key + "' not found");
2835 }
2836 }
2837 else
2838 {
2839 throw std::domain_error("cannot use at() with " + type_name());
2840 }
2841 }
2842
2869 const_reference at(const typename object_t::key_type& key) const
2870 {
2871 // at only works for objects
2872 if (is_object())
2873 {
2874 try
2875 {
2876 assert(m_value.object != nullptr);
2877 return m_value.object->at(key);
2878 }
2879 catch (std::out_of_range&)
2880 {
2881 // create better exception explanation
2882 throw std::out_of_range("key '" + key + "' not found");
2883 }
2884 }
2885 else
2886 {
2887 throw std::domain_error("cannot use at() with " + type_name());
2888 }
2889 }
2890
2916 reference operator[](size_type idx)
2917 {
2918 // implicitly convert null to object
2919 if (is_null())
2920 {
2921 m_type = value_t::array;
2922 m_value.array = create<array_t>();
2923 }
2924
2925 // [] only works for arrays
2926 if (is_array())
2927 {
2928 assert(m_value.array != nullptr);
2929 for (size_t i = m_value.array->size(); i <= idx; ++i)
2930 {
2931 m_value.array->push_back(basic_json());
2932 }
2933
2934 return m_value.array->operator[](idx);
2935 }
2936 else
2937 {
2938 throw std::domain_error("cannot use operator[] with " + type_name());
2939 }
2940 }
2941
2961 const_reference operator[](size_type idx) const
2962 {
2963 // at only works for arrays
2964 if (is_array())
2965 {
2966 assert(m_value.array != nullptr);
2967 return m_value.array->operator[](idx);
2968 }
2969 else
2970 {
2971 throw std::domain_error("cannot use operator[] with " + type_name());
2972 }
2973 }
2974
3002 reference operator[](const typename object_t::key_type& key)
3003 {
3004 // implicitly convert null to object
3005 if (is_null())
3006 {
3007 m_type = value_t::object;
3008 m_value.object = create<object_t>();
3009 }
3010
3011 // [] only works for objects
3012 if (is_object())
3013 {
3014 assert(m_value.object != nullptr);
3015 return m_value.object->operator[](key);
3016 }
3017 else
3018 {
3019 throw std::domain_error("cannot use operator[] with " + type_name());
3020 }
3021 }
3022
3050 const_reference operator[](const typename object_t::key_type& key) const
3051 {
3052 // [] only works for objects
3053 if (is_object())
3054 {
3055 assert(m_value.object != nullptr);
3056 assert(m_value.object->find(key) != m_value.object->end());
3057 return m_value.object->find(key)->second;
3058 }
3059 else
3060 {
3061 throw std::domain_error("cannot use operator[] with " + type_name());
3062 }
3063 }
3064
3092 template<typename T, std::size_t n>
3093 reference operator[](T * (&key)[n])
3094 {
3095 return operator[](static_cast<const T>(key));
3096 }
3097
3127 template<typename T, std::size_t n>
3128 const_reference operator[](T * (&key)[n]) const
3129 {
3130 return operator[](static_cast<const T>(key));
3131 }
3132
3160 template<typename T>
3161 reference operator[](T* key)
3162 {
3163 // implicitly convert null to object
3164 if (is_null())
3165 {
3166 m_type = value_t::object;
3167 m_value = value_t::object;
3168 }
3169
3170 // at only works for objects
3171 if (is_object())
3172 {
3173 assert(m_value.object != nullptr);
3174 return m_value.object->operator[](key);
3175 }
3176 else
3177 {
3178 throw std::domain_error("cannot use operator[] with " + type_name());
3179 }
3180 }
3181
3209 template<typename T>
3210 const_reference operator[](T* key) const
3211 {
3212 // at only works for objects
3213 if (is_object())
3214 {
3215 assert(m_value.object != nullptr);
3216 assert(m_value.object->find(key) != m_value.object->end());
3217 return m_value.object->find(key)->second;
3218 }
3219 else
3220 {
3221 throw std::domain_error("cannot use operator[] with " + type_name());
3222 }
3223 }
3224
3273 template <class ValueType, typename
3274 std::enable_if<
3275 std::is_convertible<basic_json_t, ValueType>::value
3276 , int>::type = 0>
3277 ValueType value(const typename object_t::key_type& key, ValueType default_value) const
3278 {
3279 // at only works for objects
3280 if (is_object())
3281 {
3282 // if key is found, return value and given default value otherwise
3283 const auto it = find(key);
3284 if (it != end())
3285 {
3286 return *it;
3287 }
3288 else
3289 {
3290 return default_value;
3291 }
3292 }
3293 else
3294 {
3295 throw std::domain_error("cannot use value() with " + type_name());
3296 }
3297 }
3298
3303 string_t value(const typename object_t::key_type& key, const char* default_value) const
3304 {
3305 return value(key, string_t(default_value));
3306 }
3307
3328 reference front()
3329 {
3330 return *begin();
3331 }
3332
3336 const_reference front() const
3337 {
3338 return *cbegin();
3339 }
3340
3362 reference back()
3363 {
3364 auto tmp = end();
3365 --tmp;
3366 return *tmp;
3367 }
3368
3372 const_reference back() const
3373 {
3374 auto tmp = cend();
3375 --tmp;
3376 return *tmp;
3377 }
3378
3423 template <class InteratorType, typename
3424 std::enable_if<
3425 std::is_same<InteratorType, typename basic_json_t::iterator>::value or
3426 std::is_same<InteratorType, typename basic_json_t::const_iterator>::value
3427 , int>::type
3428 = 0>
3429 InteratorType erase(InteratorType pos)
3430 {
3431 // make sure iterator fits the current value
3432 if (this != pos.m_object)
3433 {
3434 throw std::domain_error("iterator does not fit current value");
3435 }
3436
3437 InteratorType result = end();
3438
3439 switch (m_type)
3440 {
3441 case value_t::boolean:
3442 case value_t::number_float:
3443 case value_t::number_integer:
3444 case value_t::string:
3445 {
3446 if (not pos.m_it.primitive_iterator.is_begin())
3447 {
3448 throw std::out_of_range("iterator out of range");
3449 }
3450
3451 if (is_string())
3452 {
3453 delete m_value.string;
3454 m_value.string = nullptr;
3455 }
3456
3457 m_type = value_t::null;
3458 break;
3459 }
3460
3461 case value_t::object:
3462 {
3463 assert(m_value.object != nullptr);
3464 result.m_it.object_iterator = m_value.object->erase(pos.m_it.object_iterator);
3465 break;
3466 }
3467
3468 case value_t::array:
3469 {
3470 assert(m_value.array != nullptr);
3471 result.m_it.array_iterator = m_value.array->erase(pos.m_it.array_iterator);
3472 break;
3473 }
3474
3475 default:
3476 {
3477 throw std::domain_error("cannot use erase() with " + type_name());
3478 }
3479 }
3480
3481 return result;
3482 }
3483
3528 template <class InteratorType, typename
3529 std::enable_if<
3530 std::is_same<InteratorType, typename basic_json_t::iterator>::value or
3531 std::is_same<InteratorType, typename basic_json_t::const_iterator>::value
3532 , int>::type
3533 = 0>
3534 InteratorType erase(InteratorType first, InteratorType last)
3535 {
3536 // make sure iterator fits the current value
3537 if (this != first.m_object or this != last.m_object)
3538 {
3539 throw std::domain_error("iterators do not fit current value");
3540 }
3541
3542 InteratorType result = end();
3543
3544 switch (m_type)
3545 {
3546 case value_t::boolean:
3547 case value_t::number_float:
3548 case value_t::number_integer:
3549 case value_t::string:
3550 {
3551 if (not first.m_it.primitive_iterator.is_begin() or not last.m_it.primitive_iterator.is_end())
3552 {
3553 throw std::out_of_range("iterators out of range");
3554 }
3555
3556 if (is_string())
3557 {
3558 delete m_value.string;
3559 m_value.string = nullptr;
3560 }
3561
3562 m_type = value_t::null;
3563 break;
3564 }
3565
3566 case value_t::object:
3567 {
3568 assert(m_value.object != nullptr);
3569 result.m_it.object_iterator = m_value.object->erase(first.m_it.object_iterator,
3570 last.m_it.object_iterator);
3571 break;
3572 }
3573
3574 case value_t::array:
3575 {
3576 assert(m_value.array != nullptr);
3577 result.m_it.array_iterator = m_value.array->erase(first.m_it.array_iterator,
3578 last.m_it.array_iterator);
3579 break;
3580 }
3581
3582 default:
3583 {
3584 throw std::domain_error("cannot use erase() with " + type_name());
3585 }
3586 }
3587
3588 return result;
3589 }
3590
3617 size_type erase(const typename object_t::key_type& key)
3618 {
3619 // this erase only works for objects
3620 if (is_object())
3621 {
3622 assert(m_value.object != nullptr);
3623 return m_value.object->erase(key);
3624 }
3625 else
3626 {
3627 throw std::domain_error("cannot use erase() with " + type_name());
3628 }
3629 }
3630
3655 void erase(const size_type idx)
3656 {
3657 // this erase only works for arrays
3658 if (is_array())
3659 {
3660 if (idx >= size())
3661 {
3662 throw std::out_of_range("index out of range");
3663 }
3664
3665 assert(m_value.array != nullptr);
3666 m_value.array->erase(m_value.array->begin() + static_cast<difference_type>(idx));
3667 }
3668 else
3669 {
3670 throw std::domain_error("cannot use erase() with " + type_name());
3671 }
3672 }
3673
3691 iterator find(typename object_t::key_type key)
3692 {
3693 auto result = end();
3694
3695 if (is_object())
3696 {
3697 assert(m_value.object != nullptr);
3698 result.m_it.object_iterator = m_value.object->find(key);
3699 }
3700
3701 return result;
3702 }
3703
3708 const_iterator find(typename object_t::key_type key) const
3709 {
3710 auto result = cend();
3711
3712 if (is_object())
3713 {
3714 assert(m_value.object != nullptr);
3715 result.m_it.object_iterator = m_value.object->find(key);
3716 }
3717
3718 return result;
3719 }
3720
3739 size_type count(typename object_t::key_type key) const
3740 {
3741 // return 0 for all nonobject types
3742 assert(not is_object() or m_value.object != nullptr);
3743 return is_object() ? m_value.object->count(key) : 0;
3744 }
3745
3747
3748
3750 // iterators //
3752
3755
3774 iterator begin()
3775 {
3776 iterator result(this);
3777 result.set_begin();
3778 return result;
3779 }
3780
3784 const_iterator begin() const
3785 {
3786 return cbegin();
3787 }
3788
3808 const_iterator cbegin() const
3809 {
3810 const_iterator result(this);
3811 result.set_begin();
3812 return result;
3813 }
3814
3833 iterator end()
3834 {
3835 iterator result(this);
3836 result.set_end();
3837 return result;
3838 }
3839
3843 const_iterator end() const
3844 {
3845 return cend();
3846 }
3847
3867 const_iterator cend() const
3868 {
3869 const_iterator result(this);
3870 result.set_end();
3871 return result;
3872 }
3873
3891 reverse_iterator rbegin()
3892 {
3893 return reverse_iterator(end());
3894 }
3895
3899 const_reverse_iterator rbegin() const
3900 {
3901 return crbegin();
3902 }
3903
3922 reverse_iterator rend()
3923 {
3924 return reverse_iterator(begin());
3925 }
3926
3930 const_reverse_iterator rend() const
3931 {
3932 return crend();
3933 }
3934
3953 const_reverse_iterator crbegin() const
3954 {
3955 return const_reverse_iterator(cend());
3956 }
3957
3976 const_reverse_iterator crend() const
3977 {
3978 return const_reverse_iterator(cbegin());
3979 }
3980
3981 private:
3982 // forward declaration
3983 template<typename IteratorType> class iteration_proxy;
3984
3985 public:
3997 static iteration_proxy<iterator> iterator_wrapper(reference cont)
3998 {
3999 return iteration_proxy<iterator>(cont);
4000 }
4001
4005 static iteration_proxy<const_iterator> iterator_wrapper(const_reference cont)
4006 {
4007 return iteration_proxy<const_iterator>(cont);
4008 }
4009
4011
4012
4014 // capacity //
4016
4019
4049 bool empty() const noexcept
4050 {
4051 switch (m_type)
4052 {
4053 case value_t::null:
4054 {
4055 // null values are empty
4056 return true;
4057 }
4058
4059 case value_t::array:
4060 {
4061 assert(m_value.array != nullptr);
4062 return m_value.array->empty();
4063 }
4064
4065 case value_t::object:
4066 {
4067 assert(m_value.object != nullptr);
4068 return m_value.object->empty();
4069 }
4070
4071 default:
4072 {
4073 // all other types are nonempty
4074 return false;
4075 }
4076 }
4077 }
4078
4107 size_type size() const noexcept
4108 {
4109 switch (m_type)
4110 {
4111 case value_t::null:
4112 {
4113 // null values are empty
4114 return 0;
4115 }
4116
4117 case value_t::array:
4118 {
4119 assert(m_value.array != nullptr);
4120 return m_value.array->size();
4121 }
4122
4123 case value_t::object:
4124 {
4125 assert(m_value.object != nullptr);
4126 return m_value.object->size();
4127 }
4128
4129 default:
4130 {
4131 // all other types have size 1
4132 return 1;
4133 }
4134 }
4135 }
4136
4169 size_type max_size() const noexcept
4170 {
4171 switch (m_type)
4172 {
4173 case value_t::array:
4174 {
4175 assert(m_value.array != nullptr);
4176 return m_value.array->max_size();
4177 }
4178
4179 case value_t::object:
4180 {
4181 assert(m_value.object != nullptr);
4182 return m_value.object->max_size();
4183 }
4184
4185 default:
4186 {
4187 // all other types have max_size() == size()
4188 return size();
4189 }
4190 }
4191 }
4192
4194
4195
4197 // modifiers //
4199
4202
4228 void clear() noexcept
4229 {
4230 switch (m_type)
4231 {
4232 case value_t::number_integer:
4233 {
4234 m_value.number_integer = 0;
4235 break;
4236 }
4237
4238 case value_t::number_float:
4239 {
4240 m_value.number_float = 0.0;
4241 break;
4242 }
4243
4244 case value_t::boolean:
4245 {
4246 m_value.boolean = false;
4247 break;
4248 }
4249
4250 case value_t::string:
4251 {
4252 assert(m_value.string != nullptr);
4253 m_value.string->clear();
4254 break;
4255 }
4256
4257 case value_t::array:
4258 {
4259 assert(m_value.array != nullptr);
4260 m_value.array->clear();
4261 break;
4262 }
4263
4264 case value_t::object:
4265 {
4266 assert(m_value.object != nullptr);
4267 m_value.object->clear();
4268 break;
4269 }
4270
4271 default:
4272 {
4273 break;
4274 }
4275 }
4276 }
4277
4298 void push_back(basic_json&& val)
4299 {
4300 // push_back only works for null objects or arrays
4301 if (not(is_null() or is_array()))
4302 {
4303 throw std::domain_error("cannot use push_back() with " + type_name());
4304 }
4305
4306 // transform null object into an array
4307 if (is_null())
4308 {
4309 m_type = value_t::array;
4310 m_value = value_t::array;
4311 }
4312
4313 // add element to array (move semantics)
4314 assert(m_value.array != nullptr);
4315 m_value.array->push_back(std::move(val));
4316 // invalidate object
4317 val.m_type = value_t::null;
4318 }
4319
4324 reference operator+=(basic_json&& val)
4325 {
4326 push_back(std::move(val));
4327 return *this;
4328 }
4329
4334 void push_back(const basic_json& val)
4335 {
4336 // push_back only works for null objects or arrays
4337 if (not(is_null() or is_array()))
4338 {
4339 throw std::domain_error("cannot use push_back() with " + type_name());
4340 }
4341
4342 // transform null object into an array
4343 if (is_null())
4344 {
4345 m_type = value_t::array;
4346 m_value = value_t::array;
4347 }
4348
4349 // add element to array
4350 assert(m_value.array != nullptr);
4351 m_value.array->push_back(val);
4352 }
4353
4358 reference operator+=(const basic_json& val)
4359 {
4360 push_back(val);
4361 return *this;
4362 }
4363
4384 void push_back(const typename object_t::value_type& val)
4385 {
4386 // push_back only works for null objects or objects
4387 if (not(is_null() or is_object()))
4388 {
4389 throw std::domain_error("cannot use push_back() with " + type_name());
4390 }
4391
4392 // transform null object into an object
4393 if (is_null())
4394 {
4395 m_type = value_t::object;
4396 m_value = value_t::object;
4397 }
4398
4399 // add element to array
4400 assert(m_value.object != nullptr);
4401 m_value.object->insert(val);
4402 }
4403
4408 reference operator+=(const typename object_t::value_type& val)
4409 {
4410 push_back(val);
4411 return operator[](val.first);
4412 }
4413
4436 iterator insert(const_iterator pos, const basic_json& val)
4437 {
4438 // insert only works for arrays
4439 if (is_array())
4440 {
4441 // check if iterator pos fits to this JSON value
4442 if (pos.m_object != this)
4443 {
4444 throw std::domain_error("iterator does not fit current value");
4445 }
4446
4447 // insert to array and return iterator
4448 iterator result(this);
4449 assert(m_value.array != nullptr);
4450 result.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator, val);
4451 return result;
4452 }
4453 else
4454 {
4455 throw std::domain_error("cannot use insert() with " + type_name());
4456 }
4457 }
4458
4463 iterator insert(const_iterator pos, basic_json&& val)
4464 {
4465 return insert(pos, val);
4466 }
4467
4492 iterator insert(const_iterator pos, size_type cnt, const basic_json& val)
4493 {
4494 // insert only works for arrays
4495 if (is_array())
4496 {
4497 // check if iterator pos fits to this JSON value
4498 if (pos.m_object != this)
4499 {
4500 throw std::domain_error("iterator does not fit current value");
4501 }
4502
4503 // insert to array and return iterator
4504 iterator result(this);
4505 assert(m_value.array != nullptr);
4506 result.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator, cnt, val);
4507 return result;
4508 }
4509 else
4510 {
4511 throw std::domain_error("cannot use insert() with " + type_name());
4512 }
4513 }
4514
4545 iterator insert(const_iterator pos, const_iterator first, const_iterator last)
4546 {
4547 // insert only works for arrays
4548 if (not is_array())
4549 {
4550 throw std::domain_error("cannot use insert() with " + type_name());
4551 }
4552
4553 // check if iterator pos fits to this JSON value
4554 if (pos.m_object != this)
4555 {
4556 throw std::domain_error("iterator does not fit current value");
4557 }
4558
4559 if (first.m_object != last.m_object)
4560 {
4561 throw std::domain_error("iterators do not fit");
4562 }
4563
4564 if (first.m_object == this or last.m_object == this)
4565 {
4566 throw std::domain_error("passed iterators may not belong to container");
4567 }
4568
4569 // insert to array and return iterator
4570 iterator result(this);
4571 assert(m_value.array != nullptr);
4572 result.m_it.array_iterator = m_value.array->insert(
4573 pos.m_it.array_iterator,
4574 first.m_it.array_iterator,
4575 last.m_it.array_iterator);
4576 return result;
4577 }
4578
4603 iterator insert(const_iterator pos, std::initializer_list<basic_json> ilist)
4604 {
4605 // insert only works for arrays
4606 if (not is_array())
4607 {
4608 throw std::domain_error("cannot use insert() with " + type_name());
4609 }
4610
4611 // check if iterator pos fits to this JSON value
4612 if (pos.m_object != this)
4613 {
4614 throw std::domain_error("iterator does not fit current value");
4615 }
4616
4617 // insert to array and return iterator
4618 iterator result(this);
4619 assert(m_value.array != nullptr);
4620 result.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator, ilist);
4621 return result;
4622 }
4623
4641 void swap(reference other) noexcept (
4642 std::is_nothrow_move_constructible<value_t>::value and
4643 std::is_nothrow_move_assignable<value_t>::value and
4644 std::is_nothrow_move_constructible<json_value>::value and
4645 std::is_nothrow_move_assignable<json_value>::value
4646 )
4647 {
4648 std::swap(m_type, other.m_type);
4649 std::swap(m_value, other.m_value);
4650 }
4651
4672 void swap(array_t& other)
4673 {
4674 // swap only works for arrays
4675 if (is_array())
4676 {
4677 assert(m_value.array != nullptr);
4678 std::swap(*(m_value.array), other);
4679 }
4680 else
4681 {
4682 throw std::domain_error("cannot use swap() with " + type_name());
4683 }
4684 }
4685
4706 void swap(object_t& other)
4707 {
4708 // swap only works for objects
4709 if (is_object())
4710 {
4711 assert(m_value.object != nullptr);
4712 std::swap(*(m_value.object), other);
4713 }
4714 else
4715 {
4716 throw std::domain_error("cannot use swap() with " + type_name());
4717 }
4718 }
4719
4740 void swap(string_t& other)
4741 {
4742 // swap only works for strings
4743 if (is_string())
4744 {
4745 assert(m_value.string != nullptr);
4746 std::swap(*(m_value.string), other);
4747 }
4748 else
4749 {
4750 throw std::domain_error("cannot use swap() with " + type_name());
4751 }
4752 }
4753
4755
4756
4758 // lexicographical comparison operators //
4760
4763
4764 private:
4774 friend bool operator<(const value_t lhs, const value_t rhs)
4775 {
4776 static constexpr std::array<uint8_t, 7> order = {{
4777 0, // null
4778 3, // object
4779 4, // array
4780 5, // string
4781 1, // boolean
4782 2, // integer
4783 2 // float
4784 }
4785 };
4786
4787 // discarded values are not comparable
4788 if (lhs == value_t::discarded or rhs == value_t::discarded)
4789 {
4790 return false;
4791 }
4792
4793 return order[static_cast<std::size_t>(lhs)] < order[static_cast<std::size_t>(rhs)];
4794 }
4795
4796 public:
4820 friend bool operator==(const_reference lhs, const_reference rhs) noexcept
4821 {
4822 const auto lhs_type = lhs.type();
4823 const auto rhs_type = rhs.type();
4824
4825 if (lhs_type == rhs_type)
4826 {
4827 switch (lhs_type)
4828 {
4829 case value_t::array:
4830 {
4831 assert(lhs.m_value.array != nullptr);
4832 assert(rhs.m_value.array != nullptr);
4833 return *lhs.m_value.array == *rhs.m_value.array;
4834 }
4835 case value_t::object:
4836 {
4837 assert(lhs.m_value.object != nullptr);
4838 assert(rhs.m_value.object != nullptr);
4839 return *lhs.m_value.object == *rhs.m_value.object;
4840 }
4841 case value_t::null:
4842 {
4843 return true;
4844 }
4845 case value_t::string:
4846 {
4847 assert(lhs.m_value.string != nullptr);
4848 assert(rhs.m_value.string != nullptr);
4849 return *lhs.m_value.string == *rhs.m_value.string;
4850 }
4851 case value_t::boolean:
4852 {
4853 return lhs.m_value.boolean == rhs.m_value.boolean;
4854 }
4855 case value_t::number_integer:
4856 {
4857 return lhs.m_value.number_integer == rhs.m_value.number_integer;
4858 }
4859 case value_t::number_float:
4860 {
4861 return lhs.m_value.number_float == rhs.m_value.number_float;
4862 }
4863 default:
4864 {
4865 return false;
4866 }
4867 }
4868 }
4869 else if (lhs_type == value_t::number_integer and rhs_type == value_t::number_float)
4870 {
4871 return static_cast<number_float_t>(lhs.m_value.number_integer) == rhs.m_value.number_float;
4872 }
4873 else if (lhs_type == value_t::number_float and rhs_type == value_t::number_integer)
4874 {
4875 return lhs.m_value.number_float == static_cast<number_float_t>(rhs.m_value.number_integer);
4876 }
4877 return false;
4878 }
4879
4898 friend bool operator==(const_reference v, std::nullptr_t) noexcept
4899 {
4900 return v.is_null();
4901 }
4902
4907 friend bool operator==(std::nullptr_t, const_reference v) noexcept
4908 {
4909 return v.is_null();
4910 }
4911
4928 friend bool operator!=(const_reference lhs, const_reference rhs) noexcept
4929 {
4930 return not (lhs == rhs);
4931 }
4932
4951 friend bool operator!=(const_reference v, std::nullptr_t) noexcept
4952 {
4953 return not v.is_null();
4954 }
4955
4960 friend bool operator!=(std::nullptr_t, const_reference v) noexcept
4961 {
4962 return not v.is_null();
4963 }
4964
4989 friend bool operator<(const_reference lhs, const_reference rhs) noexcept
4990 {
4991 const auto lhs_type = lhs.type();
4992 const auto rhs_type = rhs.type();
4993
4994 if (lhs_type == rhs_type)
4995 {
4996 switch (lhs_type)
4997 {
4998 case value_t::array:
4999 {
5000 assert(lhs.m_value.array != nullptr);
5001 assert(rhs.m_value.array != nullptr);
5002 return *lhs.m_value.array < *rhs.m_value.array;
5003 }
5004 case value_t::object:
5005 {
5006 assert(lhs.m_value.object != nullptr);
5007 assert(rhs.m_value.object != nullptr);
5008 return *lhs.m_value.object < *rhs.m_value.object;
5009 }
5010 case value_t::null:
5011 {
5012 return false;
5013 }
5014 case value_t::string:
5015 {
5016 assert(lhs.m_value.string != nullptr);
5017 assert(rhs.m_value.string != nullptr);
5018 return *lhs.m_value.string < *rhs.m_value.string;
5019 }
5020 case value_t::boolean:
5021 {
5022 return lhs.m_value.boolean < rhs.m_value.boolean;
5023 }
5024 case value_t::number_integer:
5025 {
5026 return lhs.m_value.number_integer < rhs.m_value.number_integer;
5027 }
5028 case value_t::number_float:
5029 {
5030 return lhs.m_value.number_float < rhs.m_value.number_float;
5031 }
5032 default:
5033 {
5034 return false;
5035 }
5036 }
5037 }
5038 else if (lhs_type == value_t::number_integer and rhs_type == value_t::number_float)
5039 {
5040 return static_cast<number_float_t>(lhs.m_value.number_integer) <
5041 rhs.m_value.number_float;
5042 }
5043 else if (lhs_type == value_t::number_float and rhs_type == value_t::number_integer)
5044 {
5045 return lhs.m_value.number_float <
5046 static_cast<number_float_t>(rhs.m_value.number_integer);
5047 }
5048
5049 // We only reach this line if we cannot compare values. In that case,
5050 // we compare types. Note we have to call the operator explicitly,
5051 // because MSVC has problems otherwise.
5052 return operator<(lhs_type, rhs_type);
5053 }
5054
5072 friend bool operator<=(const_reference lhs, const_reference rhs) noexcept
5073 {
5074 return not (rhs < lhs);
5075 }
5076
5094 friend bool operator>(const_reference lhs, const_reference rhs) noexcept
5095 {
5096 return not (lhs <= rhs);
5097 }
5098
5116 friend bool operator>=(const_reference lhs, const_reference rhs) noexcept
5117 {
5118 return not (lhs < rhs);
5119 }
5120
5122
5123
5125 // serialization //
5127
5130
5153 friend std::ostream& operator<<(std::ostream& o, const basic_json& j)
5154 {
5155 // read width member and use it as indentation parameter if nonzero
5156 const bool pretty_print = (o.width() > 0);
5157 const auto indentation = (pretty_print ? o.width() : 0);
5158
5159 // reset width to 0 for subsequent calls to this stream
5160 o.width(0);
5161
5162 // do the actual serialization
5163 j.dump(o, pretty_print, static_cast<unsigned int>(indentation));
5164 return o;
5165 }
5166
5171 friend std::ostream& operator>>(const basic_json& j, std::ostream& o)
5172 {
5173 return o << j;
5174 }
5175
5177
5178
5180 // deserialization //
5182
5185
5210 static basic_json parse(const string_t& s, parser_callback_t cb = nullptr)
5211 {
5212 return parser(s, cb).parse();
5213 }
5214
5239 static basic_json parse(std::istream& i, parser_callback_t cb = nullptr)
5240 {
5241 return parser(i, cb).parse();
5242 }
5243
5247 static basic_json parse(std::istream&& i, parser_callback_t cb = nullptr)
5248 {
5249 return parser(i, cb).parse();
5250 }
5251
5275 friend std::istream& operator<<(basic_json& j, std::istream& i)
5276 {
5277 j = parser(i).parse();
5278 return i;
5279 }
5280
5285 friend std::istream& operator>>(std::istream& i, basic_json& j)
5286 {
5287 j = parser(i).parse();
5288 return i;
5289 }
5290
5292
5293
5294 private:
5296 // convenience functions //
5298
5300 string_t type_name() const
5301 {
5302 switch (m_type)
5303 {
5304 case value_t::null:
5305 return "null";
5306 case value_t::object:
5307 return "object";
5308 case value_t::array:
5309 return "array";
5310 case value_t::string:
5311 return "string";
5312 case value_t::boolean:
5313 return "boolean";
5314 case value_t::discarded:
5315 return "discarded";
5316 default:
5317 return "number";
5318 }
5319 }
5320
5329 static std::size_t extra_space(const string_t& s) noexcept
5330 {
5331 std::size_t result = 0;
5332
5333 for (const auto& c : s)
5334 {
5335 switch (c)
5336 {
5337 case '"':
5338 case '\\':
5339 case '\b':
5340 case '\f':
5341 case '\n':
5342 case '\r':
5343 case '\t':
5344 {
5345 // from c (1 byte) to \x (2 bytes)
5346 result += 1;
5347 break;
5348 }
5349
5350 default:
5351 {
5352 if (c >= 0x00 and c <= 0x1f)
5353 {
5354 // from c (1 byte) to \uxxxx (6 bytes)
5355 result += 5;
5356 }
5357 break;
5358 }
5359 }
5360 }
5361
5362 return result;
5363 }
5364
5378 static string_t escape_string(const string_t& s) noexcept
5379 {
5380 const auto space = extra_space(s);
5381 if (space == 0)
5382 {
5383 return s;
5384 }
5385
5386 // create a result string of necessary size
5387 string_t result(s.size() + space, '\\');
5388 std::size_t pos = 0;
5389
5390 for (const auto& c : s)
5391 {
5392 switch (c)
5393 {
5394 // quotation mark (0x22)
5395 case '"':
5396 {
5397 result[pos + 1] = '"';
5398 pos += 2;
5399 break;
5400 }
5401
5402 // reverse solidus (0x5c)
5403 case '\\':
5404 {
5405 // nothing to change
5406 pos += 2;
5407 break;
5408 }
5409
5410 // backspace (0x08)
5411 case '\b':
5412 {
5413 result[pos + 1] = 'b';
5414 pos += 2;
5415 break;
5416 }
5417
5418 // formfeed (0x0c)
5419 case '\f':
5420 {
5421 result[pos + 1] = 'f';
5422 pos += 2;
5423 break;
5424 }
5425
5426 // newline (0x0a)
5427 case '\n':
5428 {
5429 result[pos + 1] = 'n';
5430 pos += 2;
5431 break;
5432 }
5433
5434 // carriage return (0x0d)
5435 case '\r':
5436 {
5437 result[pos + 1] = 'r';
5438 pos += 2;
5439 break;
5440 }
5441
5442 // horizontal tab (0x09)
5443 case '\t':
5444 {
5445 result[pos + 1] = 't';
5446 pos += 2;
5447 break;
5448 }
5449
5450 default:
5451 {
5452 if (c >= 0x00 and c <= 0x1f)
5453 {
5454 // convert a number 0..15 to its hex representation (0..f)
5455 auto hexify = [](const char v) -> char
5456 {
5457 return (v < 10) ? ('0' + v) : ('a' + v - 10);
5458 };
5459
5460 // print character c as \uxxxx
5461 for (const char m :
5462 { 'u', '0', '0', hexify(c >> 4), hexify(c & 0x0f)
5463 })
5464 {
5465 result[++pos] = m;
5466 }
5467
5468 ++pos;
5469 }
5470 else
5471 {
5472 // all other characters are added as-is
5473 result[pos++] = c;
5474 }
5475 break;
5476 }
5477 }
5478 }
5479
5480 return result;
5481 }
5482
5500 void dump(std::ostream& o,
5501 const bool pretty_print,
5502 const unsigned int indent_step,
5503 const unsigned int current_indent = 0) const
5504 {
5505 // variable to hold indentation for recursive calls
5506 unsigned int new_indent = current_indent;
5507
5508 switch (m_type)
5509 {
5510 case value_t::object:
5511 {
5512 assert(m_value.object != nullptr);
5513
5514 if (m_value.object->empty())
5515 {
5516 o << "{}";
5517 return;
5518 }
5519
5520 o << "{";
5521
5522 // increase indentation
5523 if (pretty_print)
5524 {
5525 new_indent += indent_step;
5526 o << "\n";
5527 }
5528
5529 for (auto i = m_value.object->cbegin(); i != m_value.object->cend(); ++i)
5530 {
5531 if (i != m_value.object->cbegin())
5532 {
5533 o << (pretty_print ? ",\n" : ",");
5534 }
5535 o << string_t(new_indent, ' ') << "\""
5536 << escape_string(i->first) << "\":"
5537 << (pretty_print ? " " : "");
5538 i->second.dump(o, pretty_print, indent_step, new_indent);
5539 }
5540
5541 // decrease indentation
5542 if (pretty_print)
5543 {
5544 new_indent -= indent_step;
5545 o << "\n";
5546 }
5547
5548 o << string_t(new_indent, ' ') + "}";
5549 return;
5550 }
5551
5552 case value_t::array:
5553 {
5554 assert(m_value.array != nullptr);
5555
5556 if (m_value.array->empty())
5557 {
5558 o << "[]";
5559 return;
5560 }
5561
5562 o << "[";
5563
5564 // increase indentation
5565 if (pretty_print)
5566 {
5567 new_indent += indent_step;
5568 o << "\n";
5569 }
5570
5571 for (auto i = m_value.array->cbegin(); i != m_value.array->cend(); ++i)
5572 {
5573 if (i != m_value.array->cbegin())
5574 {
5575 o << (pretty_print ? ",\n" : ",");
5576 }
5577 o << string_t(new_indent, ' ');
5578 i->dump(o, pretty_print, indent_step, new_indent);
5579 }
5580
5581 // decrease indentation
5582 if (pretty_print)
5583 {
5584 new_indent -= indent_step;
5585 o << "\n";
5586 }
5587
5588 o << string_t(new_indent, ' ') << "]";
5589 return;
5590 }
5591
5592 case value_t::string:
5593 {
5594 assert(m_value.string != nullptr);
5595 o << string_t("\"") << escape_string(*m_value.string) << "\"";
5596 return;
5597 }
5598
5599 case value_t::boolean:
5600 {
5601 o << (m_value.boolean ? "true" : "false");
5602 return;
5603 }
5604
5605 case value_t::number_integer:
5606 {
5607 o << m_value.number_integer;
5608 return;
5609 }
5610
5611 case value_t::number_float:
5612 {
5613 // If the number is an integer then output as a fixed with with
5614 // precision 1 to output "0.0", "1.0" etc as expected for some
5615 // round trip tests otherwise 15 digits of precision allows
5616 // round-trip IEEE 754 string->double->string; to be safe, we
5617 // read this value from
5618 // std::numeric_limits<number_float_t>::digits10
5619 if (std::fmod(m_value.number_float, 1) == 0)
5620 {
5621 o << std::fixed << std::setprecision(1);
5622 }
5623 else
5624 {
5625 // std::defaultfloat not supported in gcc version < 5
5626 o.unsetf(std::ios_base::floatfield);
5627 o << std::setprecision(std::numeric_limits<double>::digits10);
5628 }
5629 o << m_value.number_float;
5630 return;
5631 }
5632
5633 case value_t::discarded:
5634 {
5635 o << "<discarded>";
5636 return;
5637 }
5638
5639 case value_t::null:
5640 {
5641 o << "null";
5642 return;
5643 }
5644 }
5645 }
5646
5647 private:
5649 // member variables //
5651
5653 value_t m_type = value_t::null;
5654
5656 json_value m_value = {};
5657
5658
5659 private:
5661 // iterators //
5663
5673 class primitive_iterator_t
5674 {
5675 public:
5677 void set_begin()
5678 {
5679 m_it = begin_value;
5680 }
5681
5683 void set_end()
5684 {
5685 m_it = end_value;
5686 }
5687
5689 bool is_begin() const
5690 {
5691 return (m_it == begin_value);
5692 }
5693
5695 bool is_end() const
5696 {
5697 return (m_it == end_value);
5698 }
5699
5701 operator difference_type& ()
5702 {
5703 return m_it;
5704 }
5705
5707 operator difference_type () const
5708 {
5709 return m_it;
5710 }
5711
5712 private:
5713 static constexpr difference_type begin_value = 0;
5714 static constexpr difference_type end_value = begin_value + 1;
5715
5717 difference_type m_it = std::numeric_limits<std::ptrdiff_t>::denorm_min();
5718 };
5719
5727 struct internal_iterator
5728 {
5730 typename object_t::iterator object_iterator;
5732 typename array_t::iterator array_iterator;
5734 primitive_iterator_t primitive_iterator;
5735
5737 internal_iterator()
5738 : object_iterator(), array_iterator(), primitive_iterator()
5739 {}
5740 };
5741
5743 template<typename IteratorType>
5744 class iteration_proxy
5745 {
5746 private:
5748 class iteration_proxy_internal
5749 {
5750 private:
5752 IteratorType anchor;
5754 size_t array_index = 0;
5755
5756 public:
5757 iteration_proxy_internal(IteratorType it)
5758 : anchor(it)
5759 {}
5760
5762 iteration_proxy_internal& operator*()
5763 {
5764 return *this;
5765 }
5766
5768 iteration_proxy_internal& operator++()
5769 {
5770 ++anchor;
5771 ++array_index;
5772
5773 return *this;
5774 }
5775
5777 bool operator!= (const iteration_proxy_internal& o) const
5778 {
5779 return anchor != o.anchor;
5780 }
5781
5783 typename basic_json::string_t key() const
5784 {
5785 assert(anchor.m_object != nullptr);
5786
5787 switch (anchor.m_object->type())
5788 {
5789 // use integer array index as key
5790 case value_t::array:
5791 {
5792 return std::to_string(array_index);
5793 }
5794
5795 // use key from the object
5796 case value_t::object:
5797 {
5798 return anchor.key();
5799 }
5800
5801 // use an empty key for all primitive types
5802 default:
5803 {
5804 return "";
5805 }
5806 }
5807 }
5808
5810 typename IteratorType::reference value() const
5811 {
5812 return anchor.value();
5813 }
5814 };
5815
5817 typename IteratorType::reference container;
5818
5819 public:
5821 iteration_proxy(typename IteratorType::reference cont)
5822 : container(cont)
5823 {}
5824
5826 iteration_proxy_internal begin()
5827 {
5828 return iteration_proxy_internal(container.begin());
5829 }
5830
5832 iteration_proxy_internal end()
5833 {
5834 return iteration_proxy_internal(container.end());
5835 }
5836 };
5837
5838 public:
5852 class const_iterator : public std::iterator<std::random_access_iterator_tag, const basic_json>
5853 {
5855 friend class basic_json;
5856
5857 public:
5859 using value_type = typename basic_json::value_type;
5861 using difference_type = typename basic_json::difference_type;
5863 using pointer = typename basic_json::const_pointer;
5865 using reference = typename basic_json::const_reference;
5867 using iterator_category = std::bidirectional_iterator_tag;
5868
5870 const_iterator() = default;
5871
5873 const_iterator(pointer object) : m_object(object)
5874 {
5875 assert(m_object != nullptr);
5876
5877 switch (m_object->m_type)
5878 {
5879 case basic_json::value_t::object:
5880 {
5881 m_it.object_iterator = typename object_t::iterator();
5882 break;
5883 }
5884
5885 case basic_json::value_t::array:
5886 {
5887 m_it.array_iterator = typename array_t::iterator();
5888 break;
5889 }
5890
5891 default:
5892 {
5893 m_it.primitive_iterator = primitive_iterator_t();
5894 break;
5895 }
5896 }
5897 }
5898
5900 const_iterator(const iterator& other) : m_object(other.m_object)
5901 {
5902 assert(m_object != nullptr);
5903
5904 switch (m_object->m_type)
5905 {
5906 case basic_json::value_t::object:
5907 {
5908 m_it.object_iterator = other.m_it.object_iterator;
5909 break;
5910 }
5911
5912 case basic_json::value_t::array:
5913 {
5914 m_it.array_iterator = other.m_it.array_iterator;
5915 break;
5916 }
5917
5918 default:
5919 {
5920 m_it.primitive_iterator = other.m_it.primitive_iterator;
5921 break;
5922 }
5923 }
5924 }
5925
5927 const_iterator(const const_iterator& other) noexcept
5928 : m_object(other.m_object), m_it(other.m_it)
5929 {}
5930
5932 const_iterator& operator=(const_iterator other) noexcept(
5933 std::is_nothrow_move_constructible<pointer>::value and
5934 std::is_nothrow_move_assignable<pointer>::value and
5935 std::is_nothrow_move_constructible<internal_iterator>::value and
5936 std::is_nothrow_move_assignable<internal_iterator>::value
5937 )
5938 {
5939 std::swap(m_object, other.m_object);
5940 std::swap(m_it, other.m_it);
5941 return *this;
5942 }
5943
5944 private:
5946 void set_begin()
5947 {
5948 assert(m_object != nullptr);
5949
5950 switch (m_object->m_type)
5951 {
5952 case basic_json::value_t::object:
5953 {
5954 assert(m_object->m_value.object != nullptr);
5955 m_it.object_iterator = m_object->m_value.object->begin();
5956 break;
5957 }
5958
5959 case basic_json::value_t::array:
5960 {
5961 assert(m_object->m_value.array != nullptr);
5962 m_it.array_iterator = m_object->m_value.array->begin();
5963 break;
5964 }
5965
5966 case basic_json::value_t::null:
5967 {
5968 // set to end so begin()==end() is true: null is empty
5969 m_it.primitive_iterator.set_end();
5970 break;
5971 }
5972
5973 default:
5974 {
5975 m_it.primitive_iterator.set_begin();
5976 break;
5977 }
5978 }
5979 }
5980
5982 void set_end()
5983 {
5984 assert(m_object != nullptr);
5985
5986 switch (m_object->m_type)
5987 {
5988 case basic_json::value_t::object:
5989 {
5990 assert(m_object->m_value.object != nullptr);
5991 m_it.object_iterator = m_object->m_value.object->end();
5992 break;
5993 }
5994
5995 case basic_json::value_t::array:
5996 {
5997 assert(m_object->m_value.array != nullptr);
5998 m_it.array_iterator = m_object->m_value.array->end();
5999 break;
6000 }
6001
6002 default:
6003 {
6004 m_it.primitive_iterator.set_end();
6005 break;
6006 }
6007 }
6008 }
6009
6010 public:
6012 reference operator*() const
6013 {
6014 assert(m_object != nullptr);
6015
6016 switch (m_object->m_type)
6017 {
6018 case basic_json::value_t::object:
6019 {
6020 assert(m_object->m_value.object);
6021 assert(m_it.object_iterator != m_object->m_value.object->end());
6022 return m_it.object_iterator->second;
6023 }
6024
6025 case basic_json::value_t::array:
6026 {
6027 assert(m_object->m_value.array);
6028 assert(m_it.array_iterator != m_object->m_value.array->end());
6029 return *m_it.array_iterator;
6030 }
6031
6032 case basic_json::value_t::null:
6033 {
6034 throw std::out_of_range("cannot get value");
6035 }
6036
6037 default:
6038 {
6039 if (m_it.primitive_iterator.is_begin())
6040 {
6041 return *m_object;
6042 }
6043 else
6044 {
6045 throw std::out_of_range("cannot get value");
6046 }
6047 }
6048 }
6049 }
6050
6052 pointer operator->() const
6053 {
6054 assert(m_object != nullptr);
6055
6056 switch (m_object->m_type)
6057 {
6058 case basic_json::value_t::object:
6059 {
6060 assert(m_object->m_value.object);
6061 assert(m_it.object_iterator != m_object->m_value.object->end());
6062 return &(m_it.object_iterator->second);
6063 }
6064
6065 case basic_json::value_t::array:
6066 {
6067 assert(m_object->m_value.array);
6068 assert(m_it.array_iterator != m_object->m_value.array->end());
6069 return &*m_it.array_iterator;
6070 }
6071
6072 default:
6073 {
6074 if (m_it.primitive_iterator.is_begin())
6075 {
6076 return m_object;
6077 }
6078 else
6079 {
6080 throw std::out_of_range("cannot get value");
6081 }
6082 }
6083 }
6084 }
6085
6087 const_iterator operator++(int)
6088 {
6089 auto result = *this;
6090 ++(*this);
6091 return result;
6092 }
6093
6095 const_iterator& operator++()
6096 {
6097 assert(m_object != nullptr);
6098
6099 switch (m_object->m_type)
6100 {
6101 case basic_json::value_t::object:
6102 {
6103 ++m_it.object_iterator;
6104 break;
6105 }
6106
6107 case basic_json::value_t::array:
6108 {
6109 ++m_it.array_iterator;
6110 break;
6111 }
6112
6113 default:
6114 {
6115 ++m_it.primitive_iterator;
6116 break;
6117 }
6118 }
6119
6120 return *this;
6121 }
6122
6124 const_iterator operator--(int)
6125 {
6126 auto result = *this;
6127 --(*this);
6128 return result;
6129 }
6130
6132 const_iterator& operator--()
6133 {
6134 assert(m_object != nullptr);
6135
6136 switch (m_object->m_type)
6137 {
6138 case basic_json::value_t::object:
6139 {
6140 --m_it.object_iterator;
6141 break;
6142 }
6143
6144 case basic_json::value_t::array:
6145 {
6146 --m_it.array_iterator;
6147 break;
6148 }
6149
6150 default:
6151 {
6152 --m_it.primitive_iterator;
6153 break;
6154 }
6155 }
6156
6157 return *this;
6158 }
6159
6161 bool operator==(const const_iterator& other) const
6162 {
6163 // if objects are not the same, the comparison is undefined
6164 if (m_object != other.m_object)
6165 {
6166 throw std::domain_error("cannot compare iterators of different containers");
6167 }
6168
6169 assert(m_object != nullptr);
6170
6171 switch (m_object->m_type)
6172 {
6173 case basic_json::value_t::object:
6174 {
6175 return (m_it.object_iterator == other.m_it.object_iterator);
6176 }
6177
6178 case basic_json::value_t::array:
6179 {
6180 return (m_it.array_iterator == other.m_it.array_iterator);
6181 }
6182
6183 default:
6184 {
6185 return (m_it.primitive_iterator == other.m_it.primitive_iterator);
6186 }
6187 }
6188 }
6189
6191 bool operator!=(const const_iterator& other) const
6192 {
6193 return not operator==(other);
6194 }
6195
6197 bool operator<(const const_iterator& other) const
6198 {
6199 // if objects are not the same, the comparison is undefined
6200 if (m_object != other.m_object)
6201 {
6202 throw std::domain_error("cannot compare iterators of different containers");
6203 }
6204
6205 assert(m_object != nullptr);
6206
6207 switch (m_object->m_type)
6208 {
6209 case basic_json::value_t::object:
6210 {
6211 throw std::domain_error("cannot compare order of object iterators");
6212 }
6213
6214 case basic_json::value_t::array:
6215 {
6216 return (m_it.array_iterator < other.m_it.array_iterator);
6217 }
6218
6219 default:
6220 {
6221 return (m_it.primitive_iterator < other.m_it.primitive_iterator);
6222 }
6223 }
6224 }
6225
6227 bool operator<=(const const_iterator& other) const
6228 {
6229 return not other.operator < (*this);
6230 }
6231
6233 bool operator>(const const_iterator& other) const
6234 {
6235 return not operator<=(other);
6236 }
6237
6239 bool operator>=(const const_iterator& other) const
6240 {
6241 return not operator<(other);
6242 }
6243
6245 const_iterator& operator+=(difference_type i)
6246 {
6247 assert(m_object != nullptr);
6248
6249 switch (m_object->m_type)
6250 {
6251 case basic_json::value_t::object:
6252 {
6253 throw std::domain_error("cannot use offsets with object iterators");
6254 }
6255
6256 case basic_json::value_t::array:
6257 {
6258 m_it.array_iterator += i;
6259 break;
6260 }
6261
6262 default:
6263 {
6264 m_it.primitive_iterator += i;
6265 break;
6266 }
6267 }
6268
6269 return *this;
6270 }
6271
6273 const_iterator& operator-=(difference_type i)
6274 {
6275 return operator+=(-i);
6276 }
6277
6279 const_iterator operator+(difference_type i)
6280 {
6281 auto result = *this;
6282 result += i;
6283 return result;
6284 }
6285
6287 const_iterator operator-(difference_type i)
6288 {
6289 auto result = *this;
6290 result -= i;
6291 return result;
6292 }
6293
6295 difference_type operator-(const const_iterator& other) const
6296 {
6297 assert(m_object != nullptr);
6298
6299 switch (m_object->m_type)
6300 {
6301 case basic_json::value_t::object:
6302 {
6303 throw std::domain_error("cannot use offsets with object iterators");
6304 }
6305
6306 case basic_json::value_t::array:
6307 {
6308 return m_it.array_iterator - other.m_it.array_iterator;
6309 }
6310
6311 default:
6312 {
6313 return m_it.primitive_iterator - other.m_it.primitive_iterator;
6314 }
6315 }
6316 }
6317
6319 reference operator[](difference_type n) const
6320 {
6321 assert(m_object != nullptr);
6322
6323 switch (m_object->m_type)
6324 {
6325 case basic_json::value_t::object:
6326 {
6327 throw std::domain_error("cannot use operator[] for object iterators");
6328 }
6329
6330 case basic_json::value_t::array:
6331 {
6332 return *(m_it.array_iterator + n);
6333 }
6334
6335 case basic_json::value_t::null:
6336 {
6337 throw std::out_of_range("cannot get value");
6338 }
6339
6340 default:
6341 {
6342 if (m_it.primitive_iterator == -n)
6343 {
6344 return *m_object;
6345 }
6346 else
6347 {
6348 throw std::out_of_range("cannot get value");
6349 }
6350 }
6351 }
6352 }
6353
6355 typename object_t::key_type key() const
6356 {
6357 assert(m_object != nullptr);
6358
6359 if (m_object->is_object())
6360 {
6361 return m_it.object_iterator->first;
6362 }
6363 else
6364 {
6365 throw std::domain_error("cannot use key() for non-object iterators");
6366 }
6367 }
6368
6370 reference value() const
6371 {
6372 return operator*();
6373 }
6374
6375 private:
6377 pointer m_object = nullptr;
6379 internal_iterator m_it = internal_iterator();
6380 };
6381
6394 class iterator : public const_iterator
6395 {
6396 public:
6397 using base_iterator = const_iterator;
6398 using pointer = typename basic_json::pointer;
6399 using reference = typename basic_json::reference;
6400
6402 iterator() = default;
6403
6405 iterator(pointer object) noexcept
6406 : base_iterator(object)
6407 {}
6408
6410 iterator(const iterator& other) noexcept
6411 : base_iterator(other)
6412 {}
6413
6415 iterator& operator=(iterator other) noexcept(
6416 std::is_nothrow_move_constructible<pointer>::value and
6417 std::is_nothrow_move_assignable<pointer>::value and
6418 std::is_nothrow_move_constructible<internal_iterator>::value and
6419 std::is_nothrow_move_assignable<internal_iterator>::value
6420 )
6421 {
6422 base_iterator::operator=(other);
6423 return *this;
6424 }
6425
6427 reference operator*()
6428 {
6429 return const_cast<reference>(base_iterator::operator*());
6430 }
6431
6433 pointer operator->()
6434 {
6435 return const_cast<pointer>(base_iterator::operator->());
6436 }
6437
6439 iterator operator++(int)
6440 {
6441 iterator result = *this;
6442 base_iterator::operator++();
6443 return result;
6444 }
6445
6447 iterator& operator++()
6448 {
6449 base_iterator::operator++();
6450 return *this;
6451 }
6452
6454 iterator operator--(int)
6455 {
6456 iterator result = *this;
6457 base_iterator::operator--();
6458 return result;
6459 }
6460
6462 iterator& operator--()
6463 {
6464 base_iterator::operator--();
6465 return *this;
6466 }
6467
6469 iterator& operator+=(difference_type i)
6470 {
6471 base_iterator::operator+=(i);
6472 return *this;
6473 }
6474
6476 iterator& operator-=(difference_type i)
6477 {
6478 base_iterator::operator-=(i);
6479 return *this;
6480 }
6481
6483 iterator operator+(difference_type i)
6484 {
6485 auto result = *this;
6486 result += i;
6487 return result;
6488 }
6489
6491 iterator operator-(difference_type i)
6492 {
6493 auto result = *this;
6494 result -= i;
6495 return result;
6496 }
6497
6498 difference_type operator-(const iterator& other) const
6499 {
6500 return base_iterator::operator-(other);
6501 }
6502
6504 reference operator[](difference_type n) const
6505 {
6506 return const_cast<reference>(base_iterator::operator[](n));
6507 }
6508
6510 reference value() const
6511 {
6512 return const_cast<reference>(base_iterator::value());
6513 }
6514 };
6515
6533 template<typename Base>
6534 class json_reverse_iterator : public std::reverse_iterator<Base>
6535 {
6536 public:
6538 using base_iterator = std::reverse_iterator<Base>;
6540 using reference = typename Base::reference;
6541
6543 json_reverse_iterator(const typename base_iterator::iterator_type& it)
6544 : base_iterator(it)
6545 {}
6546
6548 json_reverse_iterator(const base_iterator& it)
6549 : base_iterator(it)
6550 {}
6551
6553 json_reverse_iterator operator++(int)
6554 {
6555 return base_iterator::operator++(1);
6556 }
6557
6559 json_reverse_iterator& operator++()
6560 {
6561 base_iterator::operator++();
6562 return *this;
6563 }
6564
6566 json_reverse_iterator operator--(int)
6567 {
6568 return base_iterator::operator--(1);
6569 }
6570
6572 json_reverse_iterator& operator--()
6573 {
6574 base_iterator::operator--();
6575 return *this;
6576 }
6577
6579 json_reverse_iterator& operator+=(difference_type i)
6580 {
6581 base_iterator::operator+=(i);
6582 return *this;
6583 }
6584
6586 json_reverse_iterator operator+(difference_type i) const
6587 {
6588 auto result = *this;
6589 result += i;
6590 return result;
6591 }
6592
6594 json_reverse_iterator operator-(difference_type i) const
6595 {
6596 auto result = *this;
6597 result -= i;
6598 return result;
6599 }
6600
6602 difference_type operator-(const json_reverse_iterator& other) const
6603 {
6604 return this->base() - other.base();
6605 }
6606
6608 reference operator[](difference_type n) const
6609 {
6610 return *(this->operator+(n));
6611 }
6612
6614 typename object_t::key_type key() const
6615 {
6616 auto it = --this->base();
6617 return it.key();
6618 }
6619
6621 reference value() const
6622 {
6623 auto it = --this->base();
6624 return it.operator * ();
6625 }
6626 };
6627
6628
6629 private:
6631 // lexer and parser //
6633
6641 class lexer
6642 {
6643 public:
6645 enum class token_type
6646 {
6647 uninitialized,
6648 literal_true,
6649 literal_false,
6650 literal_null,
6651 value_string,
6652 value_number,
6653 begin_array,
6654 begin_object,
6655 end_array,
6656 end_object,
6657 name_separator,
6658 value_separator,
6659 parse_error,
6660 end_of_input
6661 };
6662
6664 using lexer_char_t = unsigned char;
6665
6667 explicit lexer(const string_t& s) noexcept
6668 : m_stream(nullptr), m_buffer(s)
6669 {
6670 m_content = reinterpret_cast<const lexer_char_t*>(s.c_str());
6671 assert(m_content != nullptr);
6672 m_start = m_cursor = m_content;
6673 m_limit = m_content + s.size();
6674 }
6675
6677 explicit lexer(std::istream* s) noexcept
6678 : m_stream(s), m_buffer()
6679 {
6680 assert(m_stream != nullptr);
6681 getline(*m_stream, m_buffer);
6682 m_content = reinterpret_cast<const lexer_char_t*>(m_buffer.c_str());
6683 assert(m_content != nullptr);
6684 m_start = m_cursor = m_content;
6685 m_limit = m_content + m_buffer.size();
6686 }
6687
6689 lexer() = default;
6690
6691 // switch off unwanted functions
6692 lexer(const lexer&) = delete;
6693 lexer operator=(const lexer&) = delete;
6694
6710 static string_t to_unicode(const std::size_t codepoint1,
6711 const std::size_t codepoint2 = 0)
6712 {
6713 string_t result;
6714
6715 // calculate the codepoint from the given code points
6716 std::size_t codepoint = codepoint1;
6717
6718 // check if codepoint1 is a high surrogate
6719 if (codepoint1 >= 0xD800 and codepoint1 <= 0xDBFF)
6720 {
6721 // check if codepoint2 is a low surrogate
6722 if (codepoint2 >= 0xDC00 and codepoint2 <= 0xDFFF)
6723 {
6724 codepoint =
6725 // high surrogate occupies the most significant 22 bits
6726 (codepoint1 << 10)
6727 // low surrogate occupies the least significant 15 bits
6728 + codepoint2
6729 // there is still the 0xD800, 0xDC00 and 0x10000 noise
6730 // in the result so we have to subtract with:
6731 // (0xD800 << 10) + DC00 - 0x10000 = 0x35FDC00
6732 - 0x35FDC00;
6733 }
6734 else
6735 {
6736 throw std::invalid_argument("missing or wrong low surrogate");
6737 }
6738 }
6739
6740 if (codepoint < 0x80)
6741 {
6742 // 1-byte characters: 0xxxxxxx (ASCII)
6743 result.append(1, static_cast<typename string_t::value_type>(codepoint));
6744 }
6745 else if (codepoint <= 0x7ff)
6746 {
6747 // 2-byte characters: 110xxxxx 10xxxxxx
6748 result.append(1, static_cast<typename string_t::value_type>(0xC0 | ((codepoint >> 6) & 0x1F)));
6749 result.append(1, static_cast<typename string_t::value_type>(0x80 | (codepoint & 0x3F)));
6750 }
6751 else if (codepoint <= 0xffff)
6752 {
6753 // 3-byte characters: 1110xxxx 10xxxxxx 10xxxxxx
6754 result.append(1, static_cast<typename string_t::value_type>(0xE0 | ((codepoint >> 12) & 0x0F)));
6755 result.append(1, static_cast<typename string_t::value_type>(0x80 | ((codepoint >> 6) & 0x3F)));
6756 result.append(1, static_cast<typename string_t::value_type>(0x80 | (codepoint & 0x3F)));
6757 }
6758 else if (codepoint <= 0x10ffff)
6759 {
6760 // 4-byte characters: 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
6761 result.append(1, static_cast<typename string_t::value_type>(0xF0 | ((codepoint >> 18) & 0x07)));
6762 result.append(1, static_cast<typename string_t::value_type>(0x80 | ((codepoint >> 12) & 0x3F)));
6763 result.append(1, static_cast<typename string_t::value_type>(0x80 | ((codepoint >> 6) & 0x3F)));
6764 result.append(1, static_cast<typename string_t::value_type>(0x80 | (codepoint & 0x3F)));
6765 }
6766 else
6767 {
6768 throw std::out_of_range("code points above 0x10FFFF are invalid");
6769 }
6770
6771 return result;
6772 }
6773
6775 static std::string token_type_name(token_type t)
6776 {
6777 switch (t)
6778 {
6779 case token_type::uninitialized:
6780 return "<uninitialized>";
6781 case token_type::literal_true:
6782 return "true literal";
6783 case token_type::literal_false:
6784 return "false literal";
6785 case token_type::literal_null:
6786 return "null literal";
6787 case token_type::value_string:
6788 return "string literal";
6789 case token_type::value_number:
6790 return "number literal";
6791 case token_type::begin_array:
6792 return "'['";
6793 case token_type::begin_object:
6794 return "'{'";
6795 case token_type::end_array:
6796 return "']'";
6797 case token_type::end_object:
6798 return "'}'";
6799 case token_type::name_separator:
6800 return "':'";
6801 case token_type::value_separator:
6802 return "','";
6803 case token_type::parse_error:
6804 return "<parse error>";
6805 case token_type::end_of_input:
6806 return "end of input";
6807 default:
6808 {
6809 // catch non-enum values
6810 return "unknown token"; // LCOV_EXCL_LINE
6811 }
6812 }
6813 }
6814
6825 token_type scan() noexcept
6826 {
6827 // pointer for backtracking information
6828 m_marker = nullptr;
6829
6830 // remember the begin of the token
6831 m_start = m_cursor;
6832 assert(m_start != nullptr);
6833
6834
6835 {
6836 lexer_char_t yych;
6837 unsigned int yyaccept = 0;
6838 static const unsigned char yybm[] =
6839 {
6840 0, 0, 0, 0, 0, 0, 0, 0,
6841 0, 32, 32, 0, 0, 32, 0, 0,
6842 64, 64, 64, 64, 64, 64, 64, 64,
6843 64, 64, 64, 64, 64, 64, 64, 64,
6844 96, 64, 0, 64, 64, 64, 64, 64,
6845 64, 64, 64, 64, 64, 64, 64, 64,
6846 192, 192, 192, 192, 192, 192, 192, 192,
6847 192, 192, 64, 64, 64, 64, 64, 64,
6848 64, 64, 64, 64, 64, 64, 64, 64,
6849 64, 64, 64, 64, 64, 64, 64, 64,
6850 64, 64, 64, 64, 64, 64, 64, 64,
6851 64, 64, 64, 64, 0, 64, 64, 64,
6852 64, 64, 64, 64, 64, 64, 64, 64,
6853 64, 64, 64, 64, 64, 64, 64, 64,
6854 64, 64, 64, 64, 64, 64, 64, 64,
6855 64, 64, 64, 64, 64, 64, 64, 64,
6856 64, 64, 64, 64, 64, 64, 64, 64,
6857 64, 64, 64, 64, 64, 64, 64, 64,
6858 64, 64, 64, 64, 64, 64, 64, 64,
6859 64, 64, 64, 64, 64, 64, 64, 64,
6860 64, 64, 64, 64, 64, 64, 64, 64,
6861 64, 64, 64, 64, 64, 64, 64, 64,
6862 64, 64, 64, 64, 64, 64, 64, 64,
6863 64, 64, 64, 64, 64, 64, 64, 64,
6864 64, 64, 64, 64, 64, 64, 64, 64,
6865 64, 64, 64, 64, 64, 64, 64, 64,
6866 64, 64, 64, 64, 64, 64, 64, 64,
6867 64, 64, 64, 64, 64, 64, 64, 64,
6868 64, 64, 64, 64, 64, 64, 64, 64,
6869 64, 64, 64, 64, 64, 64, 64, 64,
6870 64, 64, 64, 64, 64, 64, 64, 64,
6871 64, 64, 64, 64, 64, 64, 64, 64,
6872 };
6873 if ((m_limit - m_cursor) < 5)
6874 {
6875 yyfill(); // LCOV_EXCL_LINE;
6876 }
6877 yych = *m_cursor;
6878 if (yych <= ':')
6879 {
6880 if (yych <= ' ')
6881 {
6882 if (yych <= '\n')
6883 {
6884 if (yych <= 0x00)
6885 {
6886 goto basic_json_parser_28;
6887 }
6888 if (yych <= 0x08)
6889 {
6890 goto basic_json_parser_30;
6891 }
6892 if (yych >= '\n')
6893 {
6894 goto basic_json_parser_4;
6895 }
6896 }
6897 else
6898 {
6899 if (yych == '\r')
6900 {
6901 goto basic_json_parser_2;
6902 }
6903 if (yych <= 0x1F)
6904 {
6905 goto basic_json_parser_30;
6906 }
6907 }
6908 }
6909 else
6910 {
6911 if (yych <= ',')
6912 {
6913 if (yych == '"')
6914 {
6915 goto basic_json_parser_27;
6916 }
6917 if (yych <= '+')
6918 {
6919 goto basic_json_parser_30;
6920 }
6921 goto basic_json_parser_16;
6922 }
6923 else
6924 {
6925 if (yych <= '/')
6926 {
6927 if (yych <= '-')
6928 {
6929 goto basic_json_parser_23;
6930 }
6931 goto basic_json_parser_30;
6932 }
6933 else
6934 {
6935 if (yych <= '0')
6936 {
6937 goto basic_json_parser_24;
6938 }
6939 if (yych <= '9')
6940 {
6941 goto basic_json_parser_26;
6942 }
6943 goto basic_json_parser_18;
6944 }
6945 }
6946 }
6947 }
6948 else
6949 {
6950 if (yych <= 'n')
6951 {
6952 if (yych <= ']')
6953 {
6954 if (yych == '[')
6955 {
6956 goto basic_json_parser_8;
6957 }
6958 if (yych <= '\\')
6959 {
6960 goto basic_json_parser_30;
6961 }
6962 goto basic_json_parser_10;
6963 }
6964 else
6965 {
6966 if (yych == 'f')
6967 {
6968 goto basic_json_parser_22;
6969 }
6970 if (yych <= 'm')
6971 {
6972 goto basic_json_parser_30;
6973 }
6974 goto basic_json_parser_20;
6975 }
6976 }
6977 else
6978 {
6979 if (yych <= '{')
6980 {
6981 if (yych == 't')
6982 {
6983 goto basic_json_parser_21;
6984 }
6985 if (yych <= 'z')
6986 {
6987 goto basic_json_parser_30;
6988 }
6989 goto basic_json_parser_12;
6990 }
6991 else
6992 {
6993 if (yych <= '}')
6994 {
6995 if (yych <= '|')
6996 {
6997 goto basic_json_parser_30;
6998 }
6999 goto basic_json_parser_14;
7000 }
7001 else
7002 {
7003 if (yych == 0xEF)
7004 {
7005 goto basic_json_parser_6;
7006 }
7007 goto basic_json_parser_30;
7008 }
7009 }
7010 }
7011 }
7012 basic_json_parser_2:
7013 ++m_cursor;
7014 yych = *m_cursor;
7015 goto basic_json_parser_5;
7016 basic_json_parser_3:
7017 {
7018 return scan();
7019 }
7020 basic_json_parser_4:
7021 ++m_cursor;
7022 if (m_limit <= m_cursor)
7023 {
7024 yyfill(); // LCOV_EXCL_LINE;
7025 }
7026 yych = *m_cursor;
7027 basic_json_parser_5:
7028 if (yybm[0 + yych] & 32)
7029 {
7030 goto basic_json_parser_4;
7031 }
7032 goto basic_json_parser_3;
7033 basic_json_parser_6:
7034 yyaccept = 0;
7035 yych = *(m_marker = ++m_cursor);
7036 if (yych == 0xBB)
7037 {
7038 goto basic_json_parser_64;
7039 }
7040 basic_json_parser_7:
7041 {
7042 return token_type::parse_error;
7043 }
7044 basic_json_parser_8:
7045 ++m_cursor;
7046 {
7047 return token_type::begin_array;
7048 }
7049 basic_json_parser_10:
7050 ++m_cursor;
7051 {
7052 return token_type::end_array;
7053 }
7054 basic_json_parser_12:
7055 ++m_cursor;
7056 {
7057 return token_type::begin_object;
7058 }
7059 basic_json_parser_14:
7060 ++m_cursor;
7061 {
7062 return token_type::end_object;
7063 }
7064 basic_json_parser_16:
7065 ++m_cursor;
7066 {
7067 return token_type::value_separator;
7068 }
7069 basic_json_parser_18:
7070 ++m_cursor;
7071 {
7072 return token_type::name_separator;
7073 }
7074 basic_json_parser_20:
7075 yyaccept = 0;
7076 yych = *(m_marker = ++m_cursor);
7077 if (yych == 'u')
7078 {
7079 goto basic_json_parser_60;
7080 }
7081 goto basic_json_parser_7;
7082 basic_json_parser_21:
7083 yyaccept = 0;
7084 yych = *(m_marker = ++m_cursor);
7085 if (yych == 'r')
7086 {
7087 goto basic_json_parser_56;
7088 }
7089 goto basic_json_parser_7;
7090 basic_json_parser_22:
7091 yyaccept = 0;
7092 yych = *(m_marker = ++m_cursor);
7093 if (yych == 'a')
7094 {
7095 goto basic_json_parser_51;
7096 }
7097 goto basic_json_parser_7;
7098 basic_json_parser_23:
7099 yych = *++m_cursor;
7100 if (yych <= '/')
7101 {
7102 goto basic_json_parser_7;
7103 }
7104 if (yych <= '0')
7105 {
7106 goto basic_json_parser_50;
7107 }
7108 if (yych <= '9')
7109 {
7110 goto basic_json_parser_41;
7111 }
7112 goto basic_json_parser_7;
7113 basic_json_parser_24:
7114 yyaccept = 1;
7115 yych = *(m_marker = ++m_cursor);
7116 if (yych <= 'D')
7117 {
7118 if (yych == '.')
7119 {
7120 goto basic_json_parser_43;
7121 }
7122 }
7123 else
7124 {
7125 if (yych <= 'E')
7126 {
7127 goto basic_json_parser_44;
7128 }
7129 if (yych == 'e')
7130 {
7131 goto basic_json_parser_44;
7132 }
7133 }
7134 basic_json_parser_25:
7135 {
7136 return token_type::value_number;
7137 }
7138 basic_json_parser_26:
7139 yyaccept = 1;
7140 yych = *(m_marker = ++m_cursor);
7141 goto basic_json_parser_42;
7142 basic_json_parser_27:
7143 yyaccept = 0;
7144 yych = *(m_marker = ++m_cursor);
7145 if (yych <= 0x0F)
7146 {
7147 goto basic_json_parser_7;
7148 }
7149 goto basic_json_parser_32;
7150 basic_json_parser_28:
7151 ++m_cursor;
7152 {
7153 return token_type::end_of_input;
7154 }
7155 basic_json_parser_30:
7156 yych = *++m_cursor;
7157 goto basic_json_parser_7;
7158 basic_json_parser_31:
7159 ++m_cursor;
7160 if (m_limit <= m_cursor)
7161 {
7162 yyfill(); // LCOV_EXCL_LINE;
7163 }
7164 yych = *m_cursor;
7165 basic_json_parser_32:
7166 if (yybm[0 + yych] & 64)
7167 {
7168 goto basic_json_parser_31;
7169 }
7170 if (yych <= 0x0F)
7171 {
7172 goto basic_json_parser_33;
7173 }
7174 if (yych <= '"')
7175 {
7176 goto basic_json_parser_35;
7177 }
7178 goto basic_json_parser_34;
7179 basic_json_parser_33:
7180 m_cursor = m_marker;
7181 if (yyaccept == 0)
7182 {
7183 goto basic_json_parser_7;
7184 }
7185 else
7186 {
7187 goto basic_json_parser_25;
7188 }
7189 basic_json_parser_34:
7190 ++m_cursor;
7191 if (m_limit <= m_cursor)
7192 {
7193 yyfill(); // LCOV_EXCL_LINE;
7194 }
7195 yych = *m_cursor;
7196 if (yych <= 'e')
7197 {
7198 if (yych <= '/')
7199 {
7200 if (yych == '"')
7201 {
7202 goto basic_json_parser_31;
7203 }
7204 if (yych <= '.')
7205 {
7206 goto basic_json_parser_33;
7207 }
7208 goto basic_json_parser_31;
7209 }
7210 else
7211 {
7212 if (yych <= '\\')
7213 {
7214 if (yych <= '[')
7215 {
7216 goto basic_json_parser_33;
7217 }
7218 goto basic_json_parser_31;
7219 }
7220 else
7221 {
7222 if (yych == 'b')
7223 {
7224 goto basic_json_parser_31;
7225 }
7226 goto basic_json_parser_33;
7227 }
7228 }
7229 }
7230 else
7231 {
7232 if (yych <= 'q')
7233 {
7234 if (yych <= 'f')
7235 {
7236 goto basic_json_parser_31;
7237 }
7238 if (yych == 'n')
7239 {
7240 goto basic_json_parser_31;
7241 }
7242 goto basic_json_parser_33;
7243 }
7244 else
7245 {
7246 if (yych <= 's')
7247 {
7248 if (yych <= 'r')
7249 {
7250 goto basic_json_parser_31;
7251 }
7252 goto basic_json_parser_33;
7253 }
7254 else
7255 {
7256 if (yych <= 't')
7257 {
7258 goto basic_json_parser_31;
7259 }
7260 if (yych <= 'u')
7261 {
7262 goto basic_json_parser_37;
7263 }
7264 goto basic_json_parser_33;
7265 }
7266 }
7267 }
7268 basic_json_parser_35:
7269 ++m_cursor;
7270 {
7271 return token_type::value_string;
7272 }
7273 basic_json_parser_37:
7274 ++m_cursor;
7275 if (m_limit <= m_cursor)
7276 {
7277 yyfill(); // LCOV_EXCL_LINE;
7278 }
7279 yych = *m_cursor;
7280 if (yych <= '@')
7281 {
7282 if (yych <= '/')
7283 {
7284 goto basic_json_parser_33;
7285 }
7286 if (yych >= ':')
7287 {
7288 goto basic_json_parser_33;
7289 }
7290 }
7291 else
7292 {
7293 if (yych <= 'F')
7294 {
7295 goto basic_json_parser_38;
7296 }
7297 if (yych <= '`')
7298 {
7299 goto basic_json_parser_33;
7300 }
7301 if (yych >= 'g')
7302 {
7303 goto basic_json_parser_33;
7304 }
7305 }
7306 basic_json_parser_38:
7307 ++m_cursor;
7308 if (m_limit <= m_cursor)
7309 {
7310 yyfill(); // LCOV_EXCL_LINE;
7311 }
7312 yych = *m_cursor;
7313 if (yych <= '@')
7314 {
7315 if (yych <= '/')
7316 {
7317 goto basic_json_parser_33;
7318 }
7319 if (yych >= ':')
7320 {
7321 goto basic_json_parser_33;
7322 }
7323 }
7324 else
7325 {
7326 if (yych <= 'F')
7327 {
7328 goto basic_json_parser_39;
7329 }
7330 if (yych <= '`')
7331 {
7332 goto basic_json_parser_33;
7333 }
7334 if (yych >= 'g')
7335 {
7336 goto basic_json_parser_33;
7337 }
7338 }
7339 basic_json_parser_39:
7340 ++m_cursor;
7341 if (m_limit <= m_cursor)
7342 {
7343 yyfill(); // LCOV_EXCL_LINE;
7344 }
7345 yych = *m_cursor;
7346 if (yych <= '@')
7347 {
7348 if (yych <= '/')
7349 {
7350 goto basic_json_parser_33;
7351 }
7352 if (yych >= ':')
7353 {
7354 goto basic_json_parser_33;
7355 }
7356 }
7357 else
7358 {
7359 if (yych <= 'F')
7360 {
7361 goto basic_json_parser_40;
7362 }
7363 if (yych <= '`')
7364 {
7365 goto basic_json_parser_33;
7366 }
7367 if (yych >= 'g')
7368 {
7369 goto basic_json_parser_33;
7370 }
7371 }
7372 basic_json_parser_40:
7373 ++m_cursor;
7374 if (m_limit <= m_cursor)
7375 {
7376 yyfill(); // LCOV_EXCL_LINE;
7377 }
7378 yych = *m_cursor;
7379 if (yych <= '@')
7380 {
7381 if (yych <= '/')
7382 {
7383 goto basic_json_parser_33;
7384 }
7385 if (yych <= '9')
7386 {
7387 goto basic_json_parser_31;
7388 }
7389 goto basic_json_parser_33;
7390 }
7391 else
7392 {
7393 if (yych <= 'F')
7394 {
7395 goto basic_json_parser_31;
7396 }
7397 if (yych <= '`')
7398 {
7399 goto basic_json_parser_33;
7400 }
7401 if (yych <= 'f')
7402 {
7403 goto basic_json_parser_31;
7404 }
7405 goto basic_json_parser_33;
7406 }
7407 basic_json_parser_41:
7408 yyaccept = 1;
7409 m_marker = ++m_cursor;
7410 if ((m_limit - m_cursor) < 3)
7411 {
7412 yyfill(); // LCOV_EXCL_LINE;
7413 }
7414 yych = *m_cursor;
7415 basic_json_parser_42:
7416 if (yybm[0 + yych] & 128)
7417 {
7418 goto basic_json_parser_41;
7419 }
7420 if (yych <= 'D')
7421 {
7422 if (yych != '.')
7423 {
7424 goto basic_json_parser_25;
7425 }
7426 }
7427 else
7428 {
7429 if (yych <= 'E')
7430 {
7431 goto basic_json_parser_44;
7432 }
7433 if (yych == 'e')
7434 {
7435 goto basic_json_parser_44;
7436 }
7437 goto basic_json_parser_25;
7438 }
7439 basic_json_parser_43:
7440 yych = *++m_cursor;
7441 if (yych <= '/')
7442 {
7443 goto basic_json_parser_33;
7444 }
7445 if (yych <= '9')
7446 {
7447 goto basic_json_parser_48;
7448 }
7449 goto basic_json_parser_33;
7450 basic_json_parser_44:
7451 yych = *++m_cursor;
7452 if (yych <= ',')
7453 {
7454 if (yych != '+')
7455 {
7456 goto basic_json_parser_33;
7457 }
7458 }
7459 else
7460 {
7461 if (yych <= '-')
7462 {
7463 goto basic_json_parser_45;
7464 }
7465 if (yych <= '/')
7466 {
7467 goto basic_json_parser_33;
7468 }
7469 if (yych <= '9')
7470 {
7471 goto basic_json_parser_46;
7472 }
7473 goto basic_json_parser_33;
7474 }
7475 basic_json_parser_45:
7476 yych = *++m_cursor;
7477 if (yych <= '/')
7478 {
7479 goto basic_json_parser_33;
7480 }
7481 if (yych >= ':')
7482 {
7483 goto basic_json_parser_33;
7484 }
7485 basic_json_parser_46:
7486 ++m_cursor;
7487 if (m_limit <= m_cursor)
7488 {
7489 yyfill(); // LCOV_EXCL_LINE;
7490 }
7491 yych = *m_cursor;
7492 if (yych <= '/')
7493 {
7494 goto basic_json_parser_25;
7495 }
7496 if (yych <= '9')
7497 {
7498 goto basic_json_parser_46;
7499 }
7500 goto basic_json_parser_25;
7501 basic_json_parser_48:
7502 yyaccept = 1;
7503 m_marker = ++m_cursor;
7504 if ((m_limit - m_cursor) < 3)
7505 {
7506 yyfill(); // LCOV_EXCL_LINE;
7507 }
7508 yych = *m_cursor;
7509 if (yych <= 'D')
7510 {
7511 if (yych <= '/')
7512 {
7513 goto basic_json_parser_25;
7514 }
7515 if (yych <= '9')
7516 {
7517 goto basic_json_parser_48;
7518 }
7519 goto basic_json_parser_25;
7520 }
7521 else
7522 {
7523 if (yych <= 'E')
7524 {
7525 goto basic_json_parser_44;
7526 }
7527 if (yych == 'e')
7528 {
7529 goto basic_json_parser_44;
7530 }
7531 goto basic_json_parser_25;
7532 }
7533 basic_json_parser_50:
7534 yyaccept = 1;
7535 yych = *(m_marker = ++m_cursor);
7536 if (yych <= 'D')
7537 {
7538 if (yych == '.')
7539 {
7540 goto basic_json_parser_43;
7541 }
7542 goto basic_json_parser_25;
7543 }
7544 else
7545 {
7546 if (yych <= 'E')
7547 {
7548 goto basic_json_parser_44;
7549 }
7550 if (yych == 'e')
7551 {
7552 goto basic_json_parser_44;
7553 }
7554 goto basic_json_parser_25;
7555 }
7556 basic_json_parser_51:
7557 yych = *++m_cursor;
7558 if (yych != 'l')
7559 {
7560 goto basic_json_parser_33;
7561 }
7562 yych = *++m_cursor;
7563 if (yych != 's')
7564 {
7565 goto basic_json_parser_33;
7566 }
7567 yych = *++m_cursor;
7568 if (yych != 'e')
7569 {
7570 goto basic_json_parser_33;
7571 }
7572 ++m_cursor;
7573 {
7574 return token_type::literal_false;
7575 }
7576 basic_json_parser_56:
7577 yych = *++m_cursor;
7578 if (yych != 'u')
7579 {
7580 goto basic_json_parser_33;
7581 }
7582 yych = *++m_cursor;
7583 if (yych != 'e')
7584 {
7585 goto basic_json_parser_33;
7586 }
7587 ++m_cursor;
7588 {
7589 return token_type::literal_true;
7590 }
7591 basic_json_parser_60:
7592 yych = *++m_cursor;
7593 if (yych != 'l')
7594 {
7595 goto basic_json_parser_33;
7596 }
7597 yych = *++m_cursor;
7598 if (yych != 'l')
7599 {
7600 goto basic_json_parser_33;
7601 }
7602 ++m_cursor;
7603 {
7604 return token_type::literal_null;
7605 }
7606 basic_json_parser_64:
7607 yych = *++m_cursor;
7608 if (yych != 0xBF)
7609 {
7610 goto basic_json_parser_33;
7611 }
7612 ++m_cursor;
7613 {
7614 return scan();
7615 }
7616 }
7617
7618
7619 }
7620
7622 void yyfill() noexcept
7623 {
7624 if (m_stream == nullptr or not * m_stream)
7625 {
7626 return;
7627 }
7628
7629 const ssize_t offset_start = m_start - m_content;
7630 const ssize_t offset_marker = m_marker - m_start;
7631 const ssize_t offset_cursor = m_cursor - m_start;
7632
7633 m_buffer.erase(0, static_cast<size_t>(offset_start));
7634 std::string line;
7635 assert(m_stream != nullptr);
7636 std::getline(*m_stream, line);
7637 m_buffer += "\n" + line; // add line with newline symbol
7638
7639 m_content = reinterpret_cast<const lexer_char_t*>(m_buffer.c_str());
7640 assert(m_content != nullptr);
7641 m_start = m_content;
7642 m_marker = m_start + offset_marker;
7643 m_cursor = m_start + offset_cursor;
7644 m_limit = m_start + m_buffer.size() - 1;
7645 }
7646
7648 string_t get_token() const noexcept
7649 {
7650 assert(m_start != nullptr);
7651 return string_t(reinterpret_cast<typename string_t::const_pointer>(m_start),
7652 static_cast<size_t>(m_cursor - m_start));
7653 }
7654
7676 string_t get_string() const
7677 {
7678 string_t result;
7679 result.reserve(static_cast<size_t>(m_cursor - m_start - 2));
7680
7681 // iterate the result between the quotes
7682 for (const lexer_char_t* i = m_start + 1; i < m_cursor - 1; ++i)
7683 {
7684 // process escaped characters
7685 if (*i == '\\')
7686 {
7687 // read next character
7688 ++i;
7689
7690 switch (*i)
7691 {
7692 // the default escapes
7693 case 't':
7694 {
7695 result += "\t";
7696 break;
7697 }
7698 case 'b':
7699 {
7700 result += "\b";
7701 break;
7702 }
7703 case 'f':
7704 {
7705 result += "\f";
7706 break;
7707 }
7708 case 'n':
7709 {
7710 result += "\n";
7711 break;
7712 }
7713 case 'r':
7714 {
7715 result += "\r";
7716 break;
7717 }
7718 case '\\':
7719 {
7720 result += "\\";
7721 break;
7722 }
7723 case '/':
7724 {
7725 result += "/";
7726 break;
7727 }
7728 case '"':
7729 {
7730 result += "\"";
7731 break;
7732 }
7733
7734 // unicode
7735 case 'u':
7736 {
7737 // get code xxxx from uxxxx
7738 auto codepoint = std::strtoul(std::string(reinterpret_cast<typename string_t::const_pointer>(i + 1),
7739 4).c_str(), nullptr, 16);
7740
7741 // check if codepoint is a high surrogate
7742 if (codepoint >= 0xD800 and codepoint <= 0xDBFF)
7743 {
7744 // make sure there is a subsequent unicode
7745 if ((i + 6 >= m_limit) or * (i + 5) != '\\' or * (i + 6) != 'u')
7746 {
7747 throw std::invalid_argument("missing low surrogate");
7748 }
7749
7750 // get code yyyy from uxxxx\uyyyy
7751 auto codepoint2 = std::strtoul(std::string(reinterpret_cast<typename string_t::const_pointer>
7752 (i + 7), 4).c_str(), nullptr, 16);
7753 result += to_unicode(codepoint, codepoint2);
7754 // skip the next 10 characters (xxxx\uyyyy)
7755 i += 10;
7756 }
7757 else
7758 {
7759 // add unicode character(s)
7760 result += to_unicode(codepoint);
7761 // skip the next four characters (xxxx)
7762 i += 4;
7763 }
7764 break;
7765 }
7766 }
7767 }
7768 else
7769 {
7770 // all other characters are just copied to the end of the
7771 // string
7772 result.append(1, static_cast<typename string_t::value_type>(*i));
7773 }
7774 }
7775
7776 return result;
7777 }
7778
7799 long double str_to_float_t(long double* /* type */, char** endptr) const
7800 {
7801 return std::strtold(reinterpret_cast<typename string_t::const_pointer>(m_start), endptr);
7802 }
7803
7805 double str_to_float_t(double*, char** endptr) const
7806 {
7807 return std::strtod(reinterpret_cast<typename string_t::const_pointer>(m_start), endptr);
7808 }
7809
7811 float str_to_float_t(float*, char** endptr) const
7812 {
7813 return std::strtof(reinterpret_cast<typename string_t::const_pointer>(m_start), endptr);
7814 }
7815
7833 number_float_t get_number() const
7834 {
7835 // conversion
7836 typename string_t::value_type* endptr;
7837 assert(m_start != nullptr);
7838 number_float_t float_val = str_to_float_t(static_cast<number_float_t*>(nullptr), &endptr);
7839
7840 // return float_val if the whole number was translated and NAN
7841 // otherwise
7842 return (reinterpret_cast<lexer_char_t*>(endptr) == m_cursor) ? float_val : NAN;
7843 }
7844
7845 private:
7847 std::istream* m_stream = nullptr;
7849 string_t m_buffer;
7851 const lexer_char_t* m_content = nullptr;
7853 const lexer_char_t* m_start = nullptr;
7855 const lexer_char_t* m_marker = nullptr;
7857 const lexer_char_t* m_cursor = nullptr;
7859 const lexer_char_t* m_limit = nullptr;
7860 };
7861
7867 class parser
7868 {
7869 public:
7871 parser(const string_t& s, parser_callback_t cb = nullptr)
7872 : callback(cb), m_lexer(s)
7873 {
7874 // read first token
7875 get_token();
7876 }
7877
7879 parser(std::istream& _is, parser_callback_t cb = nullptr)
7880 : callback(cb), m_lexer(&_is)
7881 {
7882 // read first token
7883 get_token();
7884 }
7885
7887 basic_json parse()
7888 {
7889 basic_json result = parse_internal(true);
7890
7891 expect(lexer::token_type::end_of_input);
7892
7893 // return parser result and replace it with null in case the
7894 // top-level value was discarded by the callback function
7895 return result.is_discarded() ? basic_json() : result;
7896 }
7897
7898 private:
7900 basic_json parse_internal(bool keep)
7901 {
7902 auto result = basic_json(value_t::discarded);
7903
7904 switch (last_token)
7905 {
7906 case lexer::token_type::begin_object:
7907 {
7908 if (keep and (not callback or (keep = callback(depth++, parse_event_t::object_start, result))))
7909 {
7910 // explicitly set result to object to cope with {}
7911 result.m_type = value_t::object;
7912 result.m_value = json_value(value_t::object);
7913 }
7914
7915 // read next token
7916 get_token();
7917
7918 // closing } -> we are done
7919 if (last_token == lexer::token_type::end_object)
7920 {
7921 get_token();
7922 if (keep and callback and not callback(--depth, parse_event_t::object_end, result))
7923 {
7924 result = basic_json(value_t::discarded);
7925 }
7926 return result;
7927 }
7928
7929 // no comma is expected here
7930 unexpect(lexer::token_type::value_separator);
7931
7932 // otherwise: parse key-value pairs
7933 do
7934 {
7935 // ugly, but could be fixed with loop reorganization
7936 if (last_token == lexer::token_type::value_separator)
7937 {
7938 get_token();
7939 }
7940
7941 // store key
7942 expect(lexer::token_type::value_string);
7943 const auto key = m_lexer.get_string();
7944
7945 bool keep_tag = false;
7946 if (keep)
7947 {
7948 if (callback)
7949 {
7950 basic_json k(key);
7951 keep_tag = callback(depth, parse_event_t::key, k);
7952 }
7953 else
7954 {
7955 keep_tag = true;
7956 }
7957 }
7958
7959 // parse separator (:)
7960 get_token();
7961 expect(lexer::token_type::name_separator);
7962
7963 // parse and add value
7964 get_token();
7965 auto value = parse_internal(keep);
7966 if (keep and keep_tag and not value.is_discarded())
7967 {
7968 result[key] = std::move(value);
7969 }
7970 }
7971 while (last_token == lexer::token_type::value_separator);
7972
7973 // closing }
7974 expect(lexer::token_type::end_object);
7975 get_token();
7976 if (keep and callback and not callback(--depth, parse_event_t::object_end, result))
7977 {
7978 result = basic_json(value_t::discarded);
7979 }
7980
7981 return result;
7982 }
7983
7984 case lexer::token_type::begin_array:
7985 {
7986 if (keep and (not callback or (keep = callback(depth++, parse_event_t::array_start, result))))
7987 {
7988 // explicitly set result to object to cope with []
7989 result.m_type = value_t::array;
7990 result.m_value = json_value(value_t::array);
7991 }
7992
7993 // read next token
7994 get_token();
7995
7996 // closing ] -> we are done
7997 if (last_token == lexer::token_type::end_array)
7998 {
7999 get_token();
8000 if (callback and not callback(--depth, parse_event_t::array_end, result))
8001 {
8002 result = basic_json(value_t::discarded);
8003 }
8004 return result;
8005 }
8006
8007 // no comma is expected here
8008 unexpect(lexer::token_type::value_separator);
8009
8010 // otherwise: parse values
8011 do
8012 {
8013 // ugly, but could be fixed with loop reorganization
8014 if (last_token == lexer::token_type::value_separator)
8015 {
8016 get_token();
8017 }
8018
8019 // parse value
8020 auto value = parse_internal(keep);
8021 if (keep and not value.is_discarded())
8022 {
8023 result.push_back(std::move(value));
8024 }
8025 }
8026 while (last_token == lexer::token_type::value_separator);
8027
8028 // closing ]
8029 expect(lexer::token_type::end_array);
8030 get_token();
8031 if (keep and callback and not callback(--depth, parse_event_t::array_end, result))
8032 {
8033 result = basic_json(value_t::discarded);
8034 }
8035
8036 return result;
8037 }
8038
8039 case lexer::token_type::literal_null:
8040 {
8041 get_token();
8042 result.m_type = value_t::null;
8043 break;
8044 }
8045
8046 case lexer::token_type::value_string:
8047 {
8048 const auto s = m_lexer.get_string();
8049 get_token();
8050 result = basic_json(s);
8051 break;
8052 }
8053
8054 case lexer::token_type::literal_true:
8055 {
8056 get_token();
8057 result.m_type = value_t::boolean;
8058 result.m_value = true;
8059 break;
8060 }
8061
8062 case lexer::token_type::literal_false:
8063 {
8064 get_token();
8065 result.m_type = value_t::boolean;
8066 result.m_value = false;
8067 break;
8068 }
8069
8070 case lexer::token_type::value_number:
8071 {
8072 result.m_value = m_lexer.get_number();
8073
8074 // NAN is returned if token could not be translated
8075 // completely
8076 if (std::isnan(result.m_value.number_float))
8077 {
8078 throw std::invalid_argument(std::string("parse error - ") +
8079 m_lexer.get_token() + " is not a number");
8080 }
8081
8082 get_token();
8083
8084 // check if conversion loses precision (special case -0.0 always loses precision)
8085 const auto int_val = static_cast<number_integer_t>(result.m_value.number_float);
8086 if (result.m_value.number_float == static_cast<number_float_t>(int_val) and
8087 result.m_value.number_integer != json_value(-0.0f).number_integer)
8088 {
8089 // we would not lose precision -> return int
8090 result.m_type = value_t::number_integer;
8091 result.m_value = int_val;
8092 }
8093 else
8094 {
8095 // we would lose precision -> return float
8096 result.m_type = value_t::number_float;
8097 }
8098 break;
8099 }
8100
8101 default:
8102 {
8103 // the last token was unexpected
8104 unexpect(last_token);
8105 }
8106 }
8107
8108 if (keep and callback and not callback(depth, parse_event_t::value, result))
8109 {
8110 result = basic_json(value_t::discarded);
8111 }
8112 return result;
8113 }
8114
8116 typename lexer::token_type get_token()
8117 {
8118 last_token = m_lexer.scan();
8119 return last_token;
8120 }
8121
8122 void expect(typename lexer::token_type t) const
8123 {
8124 if (t != last_token)
8125 {
8126 std::string error_msg = "parse error - unexpected ";
8127 error_msg += (last_token == lexer::token_type::parse_error ? ("'" + m_lexer.get_token() + "'") :
8128 lexer::token_type_name(last_token));
8129 error_msg += "; expected " + lexer::token_type_name(t);
8130 throw std::invalid_argument(error_msg);
8131 }
8132 }
8133
8134 void unexpect(typename lexer::token_type t) const
8135 {
8136 if (t == last_token)
8137 {
8138 std::string error_msg = "parse error - unexpected ";
8139 error_msg += (last_token == lexer::token_type::parse_error ? ("'" + m_lexer.get_token() + "'") :
8140 lexer::token_type_name(last_token));
8141 throw std::invalid_argument(error_msg);
8142 }
8143 }
8144
8145 private:
8147 int depth = 0;
8149 parser_callback_t callback;
8151 typename lexer::token_type last_token = lexer::token_type::uninitialized;
8153 lexer m_lexer;
8154 };
8155 };
8156
8157
8159 // presets //
8161
8170 using json = basic_json<>;
8171 }
8172
8173
8175 // nonmember functions //
8177
8178 // specialization of std::swap, and std::hash
8179 namespace std
8180 {
8186 template <>
8187 inline void swap(nlohmann::json& j1,
8188 nlohmann::json& j2) noexcept(
8189 is_nothrow_move_constructible<nlohmann::json>::value and
8190 is_nothrow_move_assignable<nlohmann::json>::value
8191 )
8192 {
8193 j1.swap(j2);
8194 }
8195
8197 template <>
8198 struct hash<nlohmann::json>
8199 {
8205 std::size_t operator()(const nlohmann::json& j) const
8206 {
8207 // a naive hashing via the string representation
8208 const auto& h = hash<nlohmann::json::string_t>();
8209 return h(j.dump());
8210 }
8211 };
8212 }
8213
8226 inline nlohmann::json operator "" _json(const char* s, std::size_t)
8227 {
8228 return nlohmann::json::parse(reinterpret_cast<const nlohmann::json::string_t::value_type*>(s));
8229 }
8230
8231 // restore GCC/clang diagnostic settings
8232 #if defined(__clang__) || defined(__GNUC__) || defined(__GNUG__)
8233 #pragma GCC diagnostic pop
8234 #endif
8235
8236 #endif
nlohmann::basic_json::const_iterator::operator!=
bool operator!=(const const_iterator &other) const
comparison: not equal
Definition: json.hpp:6191
nlohmann::basic_json::insert
iterator insert(const_iterator pos, basic_json &&val)
inserts element
Definition: json.hpp:4463
nlohmann::basic_json::iterator::operator++
iterator operator++(int)
post-increment (it++)
Definition: json.hpp:6439
nlohmann::basic_json::operator<=
friend bool operator<=(const_reference lhs, const_reference rhs) noexcept
comparison: less than or equal
Definition: json.hpp:5072
nlohmann::basic_json::pointer
typename std::allocator_traits< allocator_type >::pointer pointer
the type of an element pointer
Definition: json.hpp:229
nlohmann::basic_json::json_reverse_iterator::operator-
json_reverse_iterator operator-(difference_type i) const
subtract from iterator
Definition: json.hpp:6594
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:1519
nlohmann::basic_json::operator[]
const_reference operator[](size_type idx) const
access specified array element
Definition: json.hpp:2961
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:5863
nlohmann::basic_json::iterator_wrapper
static iteration_proxy< iterator > iterator_wrapper(reference cont)
wrapper to access iterator member functions in range-based for
Definition: json.hpp:3997
nlohmann::basic_json::const_iterator::operator--
const_iterator & operator--()
pre-decrement (–it)
Definition: json.hpp:6132
nlohmann::basic_json::operator>>
friend std::istream & operator>>(std::istream &i, basic_json &j)
deserialize from stream
Definition: json.hpp:5285
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:5932
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:5859
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:1791
nlohmann::basic_json::operator[]
const_reference operator[](T *key) const
read-only access specified object element
Definition: json.hpp:3210
nlohmann::basic_json::insert
iterator insert(const_iterator pos, const_iterator first, const_iterator last)
inserts elements
Definition: json.hpp:4545
nlohmann::basic_json::insert
iterator insert(const_iterator pos, size_type cnt, const basic_json &val)
inserts elements
Definition: json.hpp:4492
nlohmann::basic_json::json_reverse_iterator::operator--
json_reverse_iterator operator--(int)
post-decrement (it–)
Definition: json.hpp:6566
nlohmann::basic_json::string_t
StringType string_t
a type for a string
Definition: json.hpp:443
nlohmann::basic_json::push_back
void push_back(const typename object_t::value_type &val)
add an object to an object
Definition: json.hpp:4384
nlohmann::basic_json::basic_json
basic_json(boolean_t val)
create a boolean (explicit)
Definition: json.hpp:1141
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:1479
nlohmann::basic_json::iterator::operator++
iterator & operator++()
pre-increment (++it)
Definition: json.hpp:6447
nlohmann::basic_json::operator!=
friend bool operator!=(const_reference lhs, const_reference rhs) noexcept
comparison: not equal
Definition: json.hpp:4928
nlohmann::basic_json::array_t
ArrayType< basic_json, AllocatorType< basic_json >> array_t
a type for an array
Definition: json.hpp:396
nlohmann::basic_json::const_iterator::operator++
const_iterator & operator++()
pre-increment (++it)
Definition: json.hpp:6095
nlohmann::basic_json::json_reverse_iterator::operator-
difference_type operator-(const json_reverse_iterator &other) const
return difference
Definition: json.hpp:6602
nlohmann::json
basic_json<> json
default JSON class
Definition: json.hpp:8170
nlohmann::basic_json::front
reference front()
access the first element
Definition: json.hpp:3328
nlohmann::basic_json::is_array
bool is_array() const noexcept
return whether value is an array
Definition: json.hpp:2104
nlohmann::basic_json::find
const_iterator find(typename object_t::key_type key) const
find an element in a JSON object
Definition: json.hpp:3708
nlohmann::basic_json::json_reverse_iterator::base_iterator
std::reverse_iterator< Base > base_iterator
shortcut to the reverse iterator adaptor
Definition: json.hpp:6538
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:6543
nlohmann::basic_json
a class to store JSON values
Definition: json.hpp:191
nlohmann::basic_json::json_reverse_iterator::operator--
json_reverse_iterator & operator--()
pre-decrement (–it)
Definition: json.hpp:6572
nlohmann::basic_json::basic_json
basic_json(const object_t &val)
create an object (explicit)
Definition: json.hpp:943
nlohmann::basic_json::operator==
friend bool operator==(std::nullptr_t, const_reference v) noexcept
comparison: equal
Definition: json.hpp:4907
nlohmann::basic_json::push_back
void push_back(basic_json &&val)
add an object to an array
Definition: json.hpp:4298
nlohmann::basic_json::cbegin
const_iterator cbegin() const
returns a const iterator to the first element
Definition: json.hpp:3808
nlohmann::basic_json::operator[]
reference operator[](T *key)
access specified object element
Definition: json.hpp:3161
nlohmann::basic_json::is_string
bool is_string() const noexcept
return whether value is a string
Definition: json.hpp:2123
nlohmann::basic_json::iterator::operator+=
iterator & operator+=(difference_type i)
add to iterator
Definition: json.hpp:6469
nlohmann::basic_json::get_ptr
const PointerType get_ptr() const noexcept
get a pointer value (implicit)
Definition: json.hpp:2598
nlohmann::basic_json::basic_json
basic_json(const CompatibleStringType &val)
create a string (implicit)
Definition: json.hpp:1123
nlohmann::basic_json::operator+=
reference operator+=(basic_json &&val)
add an object to an array
Definition: json.hpp:4324
nlohmann::basic_json::basic_json
basic_json(size_type cnt, const basic_json &val)
construct an array with count copies of given value
Definition: json.hpp:1543
nlohmann::basic_json::iterator
a mutable random access iterator for the basic_json class
Definition: json.hpp:6394
nlohmann::basic_json::iterator::operator-=
iterator & operator-=(difference_type i)
subtract from iterator
Definition: json.hpp:6476
nlohmann::basic_json::parse
static basic_json parse(std::istream &&i, parser_callback_t cb=nullptr)
deserialize from stream
Definition: json.hpp:5247
nlohmann::basic_json::operator[]
reference operator[](const typename object_t::key_type &key)
access specified object element
Definition: json.hpp:3002
std
STL namespace.
nlohmann::basic_json::iterator::operator-
difference_type operator-(const iterator &other) const
Definition: json.hpp:6498
nlohmann::basic_json::const_iterator::value
reference value() const
return the value of an iterator
Definition: json.hpp:6370
nlohmann::basic_json::iterator_wrapper
static iteration_proxy< const_iterator > iterator_wrapper(const_reference cont)
wrapper to access iterator member functions in range-based for
Definition: json.hpp:4005
nlohmann::basic_json::end
const_iterator end() const
returns a const iterator to one past the last element
Definition: json.hpp:3843
nlohmann::basic_json::const_iterator::const_iterator
const_iterator(const const_iterator &other) noexcept
copy constructor
Definition: json.hpp:5927
nlohmann::basic_json::at
reference at(const typename object_t::key_type &key)
access specified object element with bounds checking
Definition: json.hpp:2821
nlohmann::basic_json::const_iterator::key
object_t::key_type key() const
return the key of an object iterator
Definition: json.hpp:6355
nlohmann::basic_json::end
iterator end()
returns an iterator to one past the last element
Definition: json.hpp:3833
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:350
nlohmann::basic_json::iterator::operator*
reference operator*()
return a reference to the value pointed to by the iterator
Definition: json.hpp:6427
nlohmann::basic_json::rend
reverse_iterator rend()
returns an iterator to the reverse-end
Definition: json.hpp:3922
nlohmann::basic_json::is_object
bool is_object() const noexcept
return whether value is an object
Definition: json.hpp:2085
nlohmann::basic_json::const_iterator::operator-
const_iterator operator-(difference_type i)
subtract from iterator
Definition: json.hpp:6287
nlohmann::basic_json::is_discarded
bool is_discarded() const noexcept
return whether value is discarded
Definition: json.hpp:2147
nlohmann::basic_json::basic_json
basic_json(const CompatibleArrayType &val)
create an array (implicit)
Definition: json.hpp:1039
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:5865
nlohmann::basic_json::rend
const_reverse_iterator rend() const
returns a const reverse iterator to one before the first
Definition: json.hpp:3930
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:3617
nlohmann::basic_json::is_boolean
bool is_boolean() const noexcept
return whether value is a boolean
Definition: json.hpp:1996
nlohmann::basic_json::begin
iterator begin()
returns an iterator to the first element
Definition: json.hpp:3774
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:2869
nlohmann::basic_json::operator+=
reference operator+=(const basic_json &val)
add an object to an array
Definition: json.hpp:4358
nlohmann::basic_json::allocator_type
AllocatorType< basic_json > allocator_type
the allocator type
Definition: json.hpp:226
nlohmann::basic_json::basic_json
basic_json(const number_float_t val)
create a floating-point number (explicit)
Definition: json.hpp:1268
nlohmann::basic_json::operator[]
reference operator[](T *(&key)[n])
access specified object element
Definition: json.hpp:3093
nlohmann::basic_json::is_number_integer
bool is_number_integer() const noexcept
return whether value is an integer number
Definition: json.hpp:2043
nlohmann::basic_json::iterator::operator+
iterator operator+(difference_type i)
add to iterator
Definition: json.hpp:6483
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:829
nlohmann::basic_json::basic_json
basic_json(const typename string_t::value_type *val)
create a string (explicit)
Definition: json.hpp:1092
nlohmann::basic_json::find
iterator find(typename object_t::key_type key)
find an element in a JSON object
Definition: json.hpp:3691
nlohmann::basic_json::basic_json
basic_json(const value_t value_type)
create an empty value with a given type
Definition: json.hpp:876
nlohmann::basic_json::operator>=
friend bool operator>=(const_reference lhs, const_reference rhs) noexcept
comparison: greater than or equal
Definition: json.hpp:5116
nlohmann::basic_json::iterator::operator--
iterator & operator--()
pre-decrement (–it)
Definition: json.hpp:6462
nlohmann::basic_json::operator<
friend bool operator<(const_reference lhs, const_reference rhs) noexcept
comparison: less than
Definition: json.hpp:4989
nlohmann::basic_json::const_iterator::operator->
pointer operator->() const
dereference the iterator
Definition: json.hpp:6052
nlohmann::basic_json::operator[]
const_reference operator[](const typename object_t::key_type &key) const
read-only access specified object element
Definition: json.hpp:3050
nlohmann::basic_json::cend
const_iterator cend() const
returns a const iterator to one past the last element
Definition: json.hpp:3867
nlohmann::basic_json::json_reverse_iterator::reference
typename Base::reference reference
the reference type for the pointed-to element
Definition: json.hpp:6540
nlohmann::basic_json::size
size_type size() const noexcept
returns the number of elements
Definition: json.hpp:4107
nlohmann::basic_json::get_allocator
static allocator_type get_allocator()
returns the allocator associated with the container
Definition: json.hpp:251
nlohmann::basic_json::value_t::object
object (unordered set of name/value pairs)
nlohmann::basic_json::get_ref
ReferenceType get_ref()
get a reference value (implicit)
Definition: json.hpp:2634
nlohmann::basic_json::at
reference at(size_type idx)
access specified array element with bounds checking
Definition: json.hpp:2729
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:6548
nlohmann::basic_json::type
value_t type() const noexcept
return the type of the JSON value (explicit)
Definition: json.hpp:1917
nlohmann::basic_json::operator>>
friend std::ostream & operator>>(const basic_json &j, std::ostream &o)
serialize to stream
Definition: json.hpp:5171
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:3277
nlohmann::basic_json::json_reverse_iterator::key
object_t::key_type key() const
return the key of an object iterator
Definition: json.hpp:6614
nlohmann::basic_json::is_structured
bool is_structured() const noexcept
return whether type is structured
Definition: json.hpp:1958
nlohmann
namespace for Niels Lohmann
Definition: json.hpp:88
nlohmann::basic_json::const_iterator::difference_type
typename basic_json::difference_type difference_type
a type to represent differences between iterators
Definition: json.hpp:5861
nlohmann::basic_json::swap
void swap(array_t &other)
exchanges the values
Definition: json.hpp:4672
nlohmann::basic_json::rbegin
reverse_iterator rbegin()
returns an iterator to the reverse-beginning
Definition: json.hpp:3891
nlohmann::basic_json::operator+=
reference operator+=(const typename object_t::value_type &val)
add an object to an object
Definition: json.hpp:4408
nlohmann::basic_json::basic_json
basic_json(const number_integer_t val)
create an integer number (explicit)
Definition: json.hpp:1175
nlohmann::basic_json::iterator::operator[]
reference operator[](difference_type n) const
access to successor
Definition: json.hpp:6504
nlohmann::basic_json::size_type
std::size_t size_type
a type to represent container sizes
Definition: json.hpp:223
nlohmann::basic_json::rbegin
const_reverse_iterator rbegin() const
returns a const reverse iterator to the last element
Definition: json.hpp:3899
nlohmann::basic_json::~basic_json
~basic_json()
destructor
Definition: json.hpp:1817
nlohmann::basic_json::basic_json
basic_json(const basic_json &other)
copy constructor
Definition: json.hpp:1692
nlohmann::basic_json::const_iterator::operator+
const_iterator operator+(difference_type i)
add to iterator
Definition: json.hpp:6279
nlohmann::basic_json::value_t
value_t
the JSON type enumeration
Definition: json.hpp:621
nlohmann::basic_json::const_reference
const value_type & const_reference
the type of an element const reference
Definition: json.hpp:218
nlohmann::basic_json::basic_json
basic_json(const CompatibleNumberIntegerType val) noexcept
create an integer number (implicit)
Definition: json.hpp:1239
nlohmann::basic_json::get_ref
ReferenceType get_ref() const
get a reference value (implicit)
Definition: json.hpp:2649
nlohmann::basic_json::is_null
bool is_null() const noexcept
return whether value is null
Definition: json.hpp:1977
nlohmann::basic_json::swap
void swap(string_t &other)
exchanges the values
Definition: json.hpp:4740
nlohmann::basic_json::iterator::value
reference value() const
return the value of an iterator
Definition: json.hpp:6510
nlohmann::basic_json::const_iterator::operator--
const_iterator operator--(int)
post-decrement (it–)
Definition: json.hpp:6124
nlohmann::basic_json::get
ValueType get() const
get a value (explicit)
Definition: json.hpp:2499
nlohmann::basic_json::erase
void erase(const size_type idx)
remove element from a JSON array given an index
Definition: json.hpp:3655
nlohmann::basic_json::clear
void clear() noexcept
clears the contents
Definition: json.hpp:4228
nlohmann::basic_json::iterator::operator->
pointer operator->()
dereference the iterator
Definition: json.hpp:6433
nlohmann::basic_json::value_type
basic_json value_type
the type of elements in a basic_json container
Definition: json.hpp:213
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:3336
nlohmann::basic_json::const_iterator::operator>=
bool operator>=(const const_iterator &other) const
comparison: greater than or equal
Definition: json.hpp:6239
nlohmann::basic_json::insert
iterator insert(const_iterator pos, std::initializer_list< basic_json > ilist)
inserts elements
Definition: json.hpp:4603
nlohmann::basic_json::difference_type
std::ptrdiff_t difference_type
a type to represent differences between iterators
Definition: json.hpp:221
nlohmann::basic_json::const_iterator::operator+=
const_iterator & operator+=(difference_type i)
add to iterator
Definition: json.hpp:6245
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:1387
nlohmann::basic_json::const_iterator::operator-
difference_type operator-(const const_iterator &other) const
return difference
Definition: json.hpp:6295
nlohmann::basic_json::operator==
friend bool operator==(const_reference lhs, const_reference rhs) noexcept
comparison: equal
Definition: json.hpp:4820
nlohmann::basic_json::is_number
bool is_number() const noexcept
return whether value is a number
Definition: json.hpp:2020
nlohmann::basic_json::boolean_t
BooleanType boolean_t
a type for a boolean
Definition: json.hpp:469
nlohmann::basic_json::crend
const_reverse_iterator crend() const
returns a const reverse iterator to one before the first
Definition: json.hpp:3976
nlohmann::basic_json::empty
bool empty() const noexcept
checks whether the container is empty
Definition: json.hpp:4049
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:3303
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:4641
nlohmann::basic_json::operator[]
const_reference operator[](T *(&key)[n]) const
read-only access specified object element
Definition: json.hpp:3128
nlohmann::basic_json::crbegin
const_reverse_iterator crbegin() const
returns a const reverse iterator to the last element
Definition: json.hpp:3953
nlohmann::basic_json::json_reverse_iterator::value
reference value() const
return the value of an iterator
Definition: json.hpp:6621
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:5873
nlohmann::basic_json::operator<
friend bool operator<(const value_t lhs, const value_t rhs)
comparison operator for JSON types
Definition: json.hpp:4774
nlohmann::basic_json::iterator::iterator
iterator(pointer object) noexcept
constructor for a given JSON instance
Definition: json.hpp:6405
nlohmann::basic_json::const_iterator::operator<
bool operator<(const const_iterator &other) const
comparison: smaller
Definition: json.hpp:6197
nlohmann::basic_json::dump
string_t dump(const int indent=-1) const
serialization
Definition: json.hpp:1886
nlohmann::basic_json::operator!=
friend bool operator!=(const_reference v, std::nullptr_t) noexcept
comparison: not equal
Definition: json.hpp:4951
nlohmann::basic_json::const_iterator::operator-=
const_iterator & operator-=(difference_type i)
subtract from iterator
Definition: json.hpp:6273
nlohmann::basic_json::basic_json
basic_json(const int val)
create an integer number from an enum type (explicit)
Definition: json.hpp:1204
nlohmann::basic_json::basic_json
basic_json(const array_t &val)
create an array (explicit)
Definition: json.hpp:1002
nlohmann::basic_json::parse
static basic_json parse(const string_t &s, parser_callback_t cb=nullptr)
deserialize from string
Definition: json.hpp:5210
nlohmann::basic_json::erase
InteratorType erase(InteratorType first, InteratorType last)
remove elements given an iterator range
Definition: json.hpp:3534
nlohmann::basic_json::json_reverse_iterator::operator++
json_reverse_iterator operator++(int)
post-increment (it++)
Definition: json.hpp:6553
nlohmann::basic_json::get_ptr
PointerType get_ptr() noexcept
get a pointer value (implicit)
Definition: json.hpp:2583
nlohmann::basic_json::const_iterator::const_iterator
const_iterator(const iterator &other)
copy constructor given a nonconst iterator
Definition: json.hpp:5900
nlohmann::basic_json::operator!=
friend bool operator!=(std::nullptr_t, const_reference v) noexcept
comparison: not equal
Definition: json.hpp:4960
nlohmann::basic_json::erase
InteratorType erase(InteratorType pos)
remove element given an iterator
Definition: json.hpp:3429
nlohmann::basic_json::const_iterator::operator<=
bool operator<=(const const_iterator &other) const
comparison: less than or equal
Definition: json.hpp:6227
nlohmann::basic_json::basic_json
basic_json(const CompatibleNumberFloatType val) noexcept
create an floating-point number (implicit)
Definition: json.hpp:1314
nlohmann::basic_json::back
reference back()
access the last element
Definition: json.hpp:3362
nlohmann::basic_json::is_number_float
bool is_number_float() const noexcept
return whether value is a floating-point number
Definition: json.hpp:2066
nlohmann::basic_json::const_iterator::operator++
const_iterator operator++(int)
post-increment (it++)
Definition: json.hpp:6087
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:231
nlohmann::basic_json::basic_json
basic_json(const string_t &val)
create a string (explicit)
Definition: json.hpp:1068
nlohmann::basic_json::iterator::iterator
iterator(const iterator &other) noexcept
copy constructor
Definition: json.hpp:6410
nlohmann::basic_json::back
const_reference back() const
access the last element
Definition: json.hpp:3372
nlohmann::basic_json::basic_json
basic_json(InputIT first, InputIT last)
construct a JSON container given an iterator range
Definition: json.hpp:1589
nlohmann::basic_json::parse
static basic_json parse(std::istream &i, parser_callback_t cb=nullptr)
deserialize from stream
Definition: json.hpp:5239
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:3739
nlohmann::basic_json::max_size
size_type max_size() const noexcept
returns the maximum possible number of elements
Definition: json.hpp:4169
nlohmann::basic_json::push_back
void push_back(const basic_json &val)
add an object to an array
Definition: json.hpp:4334
nlohmann::basic_json::const_iterator::operator==
bool operator==(const const_iterator &other) const
comparison: equal
Definition: json.hpp:6161
nlohmann::basic_json::json_reverse_iterator::operator++
json_reverse_iterator & operator++()
pre-increment (++it)
Definition: json.hpp:6559
nlohmann::basic_json::basic_json
basic_json(std::nullptr_t) noexcept
create a null object (explicitly)
Definition: json.hpp:920
nlohmann::basic_json::const_iterator::operator>
bool operator>(const const_iterator &other) const
comparison: greater than
Definition: json.hpp:6233
nlohmann::basic_json::operator>
friend bool operator>(const_reference lhs, const_reference rhs) noexcept
comparison: greater than
Definition: json.hpp:5094
nlohmann::basic_json::basic_json
basic_json(basic_json &&other) noexcept
move constructor
Definition: json.hpp:1761
nlohmann::basic_json::begin
const_iterator begin() const
returns a const iterator to the first element
Definition: json.hpp:3784
nlohmann::basic_json::at
const_reference at(size_type idx) const
access specified array element with bounds checking
Definition: json.hpp:2773
nlohmann::basic_json::json_reverse_iterator::operator+=
json_reverse_iterator & operator+=(difference_type i)
add to iterator
Definition: json.hpp:6579
nlohmann::basic_json::const_iterator
a const random access iterator for the basic_json class
Definition: json.hpp:5852
nlohmann::basic_json::json_reverse_iterator
a template for a reverse iterator class
Definition: json.hpp:234
nlohmann::basic_json::swap
void swap(object_t &other)
exchanges the values
Definition: json.hpp:4706
nlohmann::basic_json::const_iterator::iterator_category
std::bidirectional_iterator_tag iterator_category
the category of the iterator
Definition: json.hpp:5867
nlohmann::basic_json::is_primitive
bool is_primitive() const noexcept
return whether type is primitive
Definition: json.hpp:1938
nlohmann::basic_json::insert
iterator insert(const_iterator pos, const basic_json &val)
inserts element
Definition: json.hpp:4436
nlohmann::basic_json::operator==
friend bool operator==(const_reference v, std::nullptr_t) noexcept
comparison: equal
Definition: json.hpp:4898
nlohmann::basic_json::json_reverse_iterator::operator[]
reference operator[](difference_type n) const
access to successor
Definition: json.hpp:6608
nlohmann::basic_json::number_integer_t
NumberIntegerType number_integer_t
a type for a number (integer)
Definition: json.hpp:537
nlohmann::basic_json::const_iterator::operator[]
reference operator[](difference_type n) const
access to successor
Definition: json.hpp:6319
nlohmann::basic_json::const_iterator::operator*
reference operator*() const
return a reference to the value pointed to by the iterator
Definition: json.hpp:6012
nlohmann::basic_json::reference
value_type & reference
the type of an element reference
Definition: json.hpp:216
nlohmann::basic_json::operator<<
friend std::istream & operator<<(basic_json &j, std::istream &i)
deserialize from stream
Definition: json.hpp:5275
nlohmann::basic_json::number_float_t
NumberFloatType number_float_t
a type for a number (floating-point)
Definition: json.hpp:602
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:8205
nlohmann::basic_json::operator<<
friend std::ostream & operator<<(std::ostream &o, const basic_json &j)
serialize to stream
Definition: json.hpp:5153
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:6415
nlohmann::basic_json::basic_json
basic_json(const CompatibleObjectType &val)
create an object (implicit)
Definition: json.hpp:975
nlohmann::basic_json::operator[]
reference operator[](size_type idx)
access specified array element
Definition: json.hpp:2916
nlohmann::basic_json::iterator::operator--
iterator operator--(int)
post-decrement (it–)
Definition: json.hpp:6454
nlohmann::basic_json::json_reverse_iterator::operator+
json_reverse_iterator operator+(difference_type i) const
add to iterator
Definition: json.hpp:6586
nlohmann::basic_json::parse_event_t
parse_event_t
JSON callback events.
Definition: json.hpp:764
nlohmann::basic_json::iterator::operator-
iterator operator-(difference_type i)
subtract from iterator
Definition: json.hpp:6491