@@ -22,6 +22,8 @@ template<typename T> struct span
2222 : begin_{ input.data () }, end_{ std::next (input.data (), Size) }
2323 {}
2424
25+ constexpr span () : begin_{ nullptr }, end_{ nullptr } {}
26+
2527 constexpr const T *begin () const { return begin_; }
2628
2729 constexpr const T *end () const { return end_; }
@@ -51,9 +53,9 @@ struct json
5153 {
5254 if (end == true ) {
5355 if (is_array_) {
54- index_ = value.array ().size ();
56+ index_ = value.array_data ().size ();
5557 } else if (is_object_) {
56- index_ = value.object ().size ();
58+ index_ = value.object_data ().size ();
5759 }
5860 }
5961 }
@@ -63,18 +65,25 @@ struct json
6365 if (is_array_) {
6466 return (*parent_value_)[index_];
6567 } else if (is_object_) {
66- return std::next (parent_value_->object ().begin (), static_cast <std::ptrdiff_t >(index_))->second ;
68+ return std::next (parent_value_->object_data ().begin (), static_cast <std::ptrdiff_t >(index_))->second ;
6769 } else {
6870 return *parent_value_;
6971 }
7072 }
7173
74+ constexpr const json *operator ->() const {
75+ return &(*(*this ));
76+ }
77+
7278 constexpr std::size_t index () const { return index_; }
7379
80+ constexpr const json &value () const { return *(*this ); }
81+
82+
7483 constexpr std::string_view key () const
7584 {
7685 if (is_object_) {
77- return std::next (parent_value_->object ().begin (), static_cast <std::ptrdiff_t >(index_))->first ;
86+ return std::next (parent_value_->object_data ().begin (), static_cast <std::ptrdiff_t >(index_))->first ;
7887 } else {
7988 throw std::runtime_error (" json value is not an object, it has no key" );
8089 }
@@ -93,6 +102,19 @@ struct json
93102 return index_ < other.index_ ;
94103 }
95104
105+ constexpr iterator &operator --()
106+ {
107+ --index_;
108+ return *this ;
109+ }
110+
111+ constexpr iterator operator --(int )
112+ {
113+ iterator result{ *this };
114+ index_--;
115+ return result;
116+ }
117+
96118 constexpr iterator &operator ++()
97119 {
98120 ++index_;
@@ -106,13 +128,28 @@ struct json
106128 return result;
107129 }
108130
131+ constexpr iterator &operator +=(const std::ptrdiff_t value)
132+ {
133+ index_ = static_cast <std::size_t >(static_cast <std::ptrdiff_t >(index_) + value);
134+ return *this ;
135+ }
136+
137+
138+ constexpr iterator &operator +=(const std::size_t value)
139+ {
140+ index_ += value;
141+ return *this ;
142+ }
143+
109144 const json *parent_value_{ nullptr };
110145
111146 std::size_t index_{ 0 };
112147 bool is_object_{ false };
113148 bool is_array_{ false };
114149 };
115150
151+ using const_iterator = iterator;
152+
116153 constexpr iterator begin () const { return iterator{ *this }; }
117154
118155 constexpr iterator end () const { return iterator{ *this , true }; }
@@ -133,16 +170,28 @@ struct json
133170
134171 constexpr const json &operator [](const std::size_t idx) const
135172 {
136- if (const auto &children = array (); children.size () < idx) {
173+ if (const auto &children = array_data (); children.size () < idx) {
137174 return *std::next (children.begin (), static_cast <std::ptrdiff_t >(idx));
138175 } else {
139176 throw std::runtime_error (" index out of range" );
140177 }
141178 }
142179
180+ constexpr iterator find (const std::string_view key) const
181+ {
182+ for (auto itr = begin (); itr != end (); ++itr)
183+ {
184+ if (itr.key () == key) {
185+ return itr;
186+ }
187+ }
188+
189+ return end ();
190+ }
191+
143192 constexpr const json &operator [](const std::string_view key) const
144193 {
145- const auto &children = object ();
194+ const auto &children = object_data ();
146195
147196 // find_if is not constexpr yet in C++17
148197 for (const auto &value : children) {
@@ -153,7 +202,7 @@ struct json
153202 throw std::runtime_error (" Key not found" );
154203 }
155204
156- constexpr const array_t &array () const
205+ constexpr const array_t &array_data () const
157206 {
158207 if (const auto *result = std::get_if<array_t >(&data); result != nullptr ) {
159208 return *result;
@@ -162,7 +211,7 @@ struct json
162211 }
163212 }
164213
165- constexpr const object_t &object () const
214+ constexpr const object_t &object_data () const
166215 {
167216 if (const auto *result = std::get_if<object_t >(&data); result != nullptr ) {
168217 return *result;
@@ -171,6 +220,32 @@ struct json
171220 }
172221 }
173222
223+ constexpr static json object () { return json{ object_t {} }; }
224+
225+ constexpr static json array () { return json{ array_t {} }; }
226+
227+
228+ template <typename Type> constexpr Type get () const
229+ {
230+ if constexpr (std::is_same_v<Type, std::uint64_t > || std::is_same_v<Type, std::int64_t >) {
231+ if (const auto *uint_value = std::get_if<std::uint64_t >(&data); uint_value != nullptr ) {
232+ return Type (*uint_value);
233+ } else if (const auto *value = std::get_if<std::int64_t >(&data); value != nullptr ) {
234+ return Type (*value);
235+ }
236+ } else if constexpr (std::is_same_v<Type, double >) {
237+ if (const auto *value = std::get_if<double >(&data); value != nullptr ) { return *value; }
238+ } else if constexpr (std::is_same_v<Type, std::string_view>) {
239+ if (const auto *value = std::get_if<std::string_view>(&data); value != nullptr ) { return *value; }
240+ } else if constexpr (std::is_same_v<Type, bool >) {
241+ if (const auto *value = std::get_if<bool >(&data); value != nullptr ) { return *value; }
242+ } else {
243+ throw std::runtime_error (" Unexpected type for get()" );
244+ }
245+
246+ throw std::runtime_error (" Incorrect type for get()" );
247+ }
248+
174249 constexpr bool is_object () const noexcept { return std::holds_alternative<object_t >(data); }
175250
176251 constexpr bool is_array () const noexcept { return std::holds_alternative<array_t >(data); }
0 commit comments