DAW JSON Link
daw_json_value_state.h
Go to the documentation of this file.
1// Copyright (c) Darrell Wright
2//
3// Distributed under the Boost Software License, Version 1.0. (See accompanying
4// file LICENSE or copy at http://www.boost.org/LICENSE_1_0.txt)
5//
6// Official repository: https://github.com/beached/daw_json_link
7//
8
9#pragma once
10
14#include "impl/daw_json_value.h"
15#include "impl/daw_murmur3.h"
16#include "impl/version.h"
17
18#include <daw/daw_move.h>
19#include <daw/daw_uint_buffer.h>
20
21#include <ciso646>
22#include <cstddef>
23#include <string_view>
24#include <utility>
25#include <vector>
26
27namespace daw::json {
28 inline namespace DAW_JSON_VER {
29 namespace json_details {
30 template<typename ParseState>
32 daw::string_view name;
33 daw::UInt32 hash_value;
35
37 daw::string_view Name, basic_json_value_iterator<ParseState> val )
38 : name( Name )
39 , hash_value(
40 daw::name_hash<ParseState::expect_long_strings>( Name ) )
41 , location( DAW_MOVE( val ) ) {}
42
43 [[nodiscard]] constexpr bool is_match( daw::string_view Name ) const {
44 return name == Name;
45 }
46
47 [[nodiscard]] constexpr bool is_match( daw::string_view Name,
48 daw::UInt32 hash ) const {
49 if( hash != hash_value ) {
50 return false;
51 }
52 return name == Name;
53 }
54 };
55 } // namespace json_details
56
58 daw::string_view name;
59 daw::UInt32 hash_value;
60
61 constexpr json_member_name( std::string_view Name )
62 : name( std::data( Name ), std::size( Name ) )
63 , hash_value( daw::name_hash<false>( name ) ) {}
64 };
65
71 template<typename ParseState>
74 std::vector<json_details::basic_stateful_json_value_state<ParseState>>
75 m_locs{ };
76
77 /***
78 * Move parser until member name matches key if needed
79 * @param member to move_to
80 * @return position of member or size
81 */
82 [[nodiscard]] constexpr std::size_t move_to( json_member_name member ) {
83 std::size_t pos = 0;
84 std::size_t const Sz = std::size( m_locs );
85 for( ; pos < Sz; ++pos ) {
86 if( m_locs[pos].is_match( member.name, member.hash_value ) ) {
87 return pos;
88 }
89 }
90
91 auto it = [&] {
92 if( m_locs.empty( ) ) {
93 return m_value.begin( );
94 }
95 auto res = m_locs.back( ).location;
96 ++res;
97 return res;
98 }( );
99 auto const last = m_value.end( );
100 while( it != last ) {
101 auto name = it.name( );
102 daw_json_assert_weak( name, ErrorReason::MissingMemberName );
103 auto const &new_loc = m_locs.emplace_back(
104 daw::string_view( std::data( *name ), std::size( *name ) ), it );
105 if( new_loc.is_match( member.name ) ) {
106 return pos;
107 }
108 ++pos;
109 ++it;
110 }
111 return std::size( m_locs );
112 }
113
114 /***
115 * Move parser until member index matches, if needed
116 * @param index position of member to move to
117 * @return position in members or size
118 */
119 [[nodiscard]] constexpr std::size_t move_to( std::size_t index ) {
120 if( index < std::size( m_locs ) ) {
121 return index;
122 }
123 auto it = [&] {
124 if( m_locs.empty( ) ) {
125 return m_value.begin( );
126 }
127 auto res = m_locs.back( ).location;
128 ++res;
129 return res;
130 }( );
131 auto last = m_value.end( );
132 std::size_t pos = std::size( m_locs );
133 while( it != last ) {
134 auto name = it.name( );
135 if( name ) {
136 m_locs.emplace_back(
137 daw::string_view( std::data( *name ), std::size( *name ) ), it );
138 } else {
139 m_locs.emplace_back( daw::string_view( ), it );
140 }
141 if( pos == index ) {
142 return pos;
143 }
144 ++pos;
145 ++it;
146 }
147 return std::size( m_locs );
148 }
149
150 public:
152 : m_value( DAW_MOVE( val ) ) {
153
154 daw_json_assert_weak( ( [&] {
155 auto t = m_value.type( );
156 return ( t == JsonBaseParseTypes::Class ) |
158 }( ) ),
159 ErrorReason::ExpectedArrayOrClassStart,
160 val.get_raw_state( ) );
161 }
162
164 : basic_stateful_json_value( basic_json_value<ParseState>( "{}" ) ) {}
165
166 constexpr basic_stateful_json_value( std::string_view json_data )
168 basic_json_value<ParseState>( json_data ) ) {}
173 constexpr void reset( basic_json_value<ParseState> val ) {
174 m_value = DAW_MOVE( val );
175 m_locs.clear( );
176 }
177
178 /***
179 * Create a basic_json_member for the named member
180 * @pre name must be valid
181 * @param key name of member
182 * @return a new basic_json_member
183 */
184 [[nodiscard]] constexpr basic_json_value<ParseState>
185 operator[]( std::string_view key ) {
186 std::size_t pos = move_to( json_member_name( key ) );
187 daw_json_assert_weak( pos < std::size( m_locs ),
188 ErrorReason::UnknownMember );
189 return m_locs[pos].location->value;
190 }
191
192 /***
193 * Create a basic_json_member for the named member
194 * @pre name must be valid
195 * @param member name of member
196 * @return a new basic_json_member
197 */
198 [[nodiscard]] constexpr basic_json_value<ParseState>
200 std::size_t pos = move_to( member );
201 daw_json_assert_weak( pos < std::size( m_locs ),
202 ErrorReason::UnknownMember );
203 return m_locs[pos].location->value;
204 }
205
206 /***
207 * Create a basic_json_member for the named member
208 * @pre name must be valid
209 * @param key name of member
210 * @return a new basic_json_member for the JSON data or an empty one if
211 * the member does not exist
212 */
213 [[nodiscard]] constexpr basic_json_value<ParseState>
214 at( std::string_view key ) {
215 auto const k = std::string_view( std::data( key ), std::size( key ) );
216 std::size_t pos = move_to( k );
217 if( pos < std::size( m_locs ) ) {
218 return m_locs[pos].location->value;
219 }
220 return { };
221 }
222
223 /***
224 * Count the number of elements/members in the JSON class or array
225 * This method is O(N) worst case and O(1) if the locations have already
226 * been determined
227 * @return number of members/elements
228 */
229 [[nodiscard]] std::size_t size( ) {
230 JsonBaseParseTypes const current_type = m_value.type( );
231 switch( current_type ) {
234 return move_to( ( daw::numeric_limits<std::size_t>::max )( ) );
235 default:
236 return 0;
237 }
238 }
239
240 /***
241 * Return the index of named member
242 * This method is O(N) worst case and O(1) if the locations have already
243 * @param key name of member
244 * @return the position of the member or the count of members if not
245 * present
246 */
247 [[nodiscard]] std::size_t index_of( std::string_view key ) {
248 auto const k = std::string_view( std::data( key ), std::size( key ) );
249 return move_to( k );
250 }
251
252 /***
253 * Is the named member present
254 * This method is O(N) worst case and O(1) if the locations have already
255 * @param key name of member
256 * @return true if the member is present
257 */
258 [[nodiscard]] constexpr bool contains( std::string_view key ) {
259 auto const k = std::string_view( std::data( key ), std::size( key ) );
260 return move_to( k ) < std::size( m_locs );
261 }
262
263 /***
264 * Is the indexed member/element present
265 * This method is O(N) worst case and O(1) if the locations have already
266 * @param index position of member/element
267 * @return true if the member/element is present
268 */
269 [[nodiscard]] constexpr bool contains( std::size_t index ) {
270 return move_to( index ) < size( m_locs );
271 }
272
273 /***
274 * Get the position of the named member
275 * @tparam Integer An integer type
276 * @param index position of member. If negative it returns the position
277 * from one past last, e.g. -1 is last item
278 * @return The name of the member or an empty optional
279 */
280 template<typename Integer,
281 std::enable_if_t<std::is_integral<Integer>::value,
282 std::nullptr_t> = nullptr>
283 [[nodiscard]] std::optional<std::string_view> name_of( Integer index ) {
284 if constexpr( std::is_signed<Integer>::value ) {
285 if( index < 0 ) {
286 index = -index;
287 auto sz = size( );
288 if( static_cast<std::size_t>( index ) >= sz ) {
289 return { };
290 }
291 sz -= static_cast<std::size_t>( index );
292 return std::string_view( std::data( m_locs[sz].name( ) ),
293 std::size( m_locs[sz].name( ) ) );
294 }
295 }
296 std::size_t pos = move_to( static_cast<std::size_t>( index ) );
297 if( pos < std::size( m_locs ) ) {
298 return std::string_view( std::data( m_locs[pos].name( ) ),
299 std::size( m_locs[pos].name( ) ) );
300 }
301 return { };
302 }
303
304 /***
305 * basic_json_value for the indexed member
306 * @tparam Integer An integer type
307 * @param index position of member. If negative it returns the position
308 * from one past last, e.g. -1 is last item
309 * @pre index must exist
310 * @return A new basic_json_value for the indexed member
311 */
312 template<typename Integer,
313 std::enable_if_t<std::is_integral<Integer>::value,
314 std::nullptr_t> = nullptr>
315 [[nodiscard]] constexpr basic_json_value<ParseState>
316 operator[]( Integer index ) {
317 if constexpr( std::is_signed<Integer>::value ) {
318 if( index < 0 ) {
319 index = -index;
320 auto sz = size( );
321 daw_json_assert_weak( ( static_cast<std::size_t>( index ) < sz ),
322 ErrorReason::UnknownMember );
323 sz -= static_cast<std::size_t>( index );
324 return m_locs[sz].location->value;
325 }
326 }
327 std::size_t pos = move_to( static_cast<std::size_t>( index ) );
328 daw_json_assert_weak( pos < std::size( m_locs ),
329 ErrorReason::UnknownMember );
330 return m_locs[pos].location->value;
331 }
332
333 /***
334 * basic_json_value for the indexed member
335 * @tparam Integer An integer type
336 * @param index position of member. If negative it returns the position
337 * from one past last, e.g. -1 is last item
338 * @return A new basic_json_value for the indexed member
339 */
340 template<typename Integer,
341 std::enable_if_t<std::is_integral<Integer>::value,
342 std::nullptr_t> = nullptr>
343 [[nodiscard]] constexpr std::optional<basic_json_value<ParseState>>
344 at( Integer index ) {
345 if constexpr( std::is_signed<Integer>::value ) {
346 if( index < 0 ) {
347 index = -index;
348 auto sz = size( );
349 if( static_cast<std::size_t>( index ) >= sz ) {
350 return { };
351 }
352 sz -= static_cast<std::size_t>( index );
353 return m_locs[sz].location->value( );
354 }
355 }
356 std::size_t pos = move_to( static_cast<std::size_t>( index ) );
357 if( pos < std::size( m_locs ) ) {
358 return m_locs[pos].location->value( );
359 }
360 return { };
361 }
362
363 /***
364 * @return A copy of the underlying basic_json_value
365 */
366 [[nodiscard]] constexpr basic_json_value<ParseState>
367 get_json_value( ) const {
368 return m_value;
369 }
370 };
371
374 } // namespace DAW_JSON_VER
375} // namespace daw::json
Definition: daw_json_value.h:320
constexpr ParseState get_raw_state() const
Definition: daw_json_value.h:369
JsonBaseParseTypes type() const
Definition: daw_json_value.h:399
constexpr iterator begin() const
Definition: daw_json_value.h:378
constexpr iterator end() const
Definition: daw_json_value.h:390
Definition: daw_json_value_state.h:72
std::optional< std::string_view > name_of(Integer index)
Definition: daw_json_value_state.h:283
constexpr basic_stateful_json_value()
Definition: daw_json_value_state.h:163
constexpr bool contains(std::string_view key)
Definition: daw_json_value_state.h:258
std::size_t size()
Definition: daw_json_value_state.h:229
constexpr basic_json_value< ParseState > operator[](json_member_name member)
Definition: daw_json_value_state.h:199
constexpr void reset(basic_json_value< ParseState > val)
Definition: daw_json_value_state.h:173
constexpr basic_stateful_json_value(basic_json_value< ParseState > val)
Definition: daw_json_value_state.h:151
constexpr basic_stateful_json_value(std::string_view json_data)
Definition: daw_json_value_state.h:166
constexpr basic_json_value< ParseState > at(std::string_view key)
Definition: daw_json_value_state.h:214
constexpr std::optional< basic_json_value< ParseState > > at(Integer index)
Definition: daw_json_value_state.h:344
constexpr basic_json_value< ParseState > operator[](Integer index)
Definition: daw_json_value_state.h:316
constexpr basic_json_value< ParseState > operator[](std::string_view key)
Definition: daw_json_value_state.h:185
constexpr bool contains(std::size_t index)
Definition: daw_json_value_state.h:269
constexpr basic_json_value< ParseState > get_json_value() const
Definition: daw_json_value_state.h:367
std::size_t index_of(std::string_view key)
Definition: daw_json_value_state.h:247
#define daw_json_assert_weak(Bool,...)
Definition: daw_json_assert.h:190
Iterator & it
Definition: daw_json_traits.h:251
JsonBaseParseTypes
The fundamental JSON types.
Definition: daw_json_enums.h:53
Definition: daw_from_json.h:22
Definition: daw_from_json.h:22
constexpr DAW_ATTRIB_INLINE auto name_hash(StringView key) -> std::enable_if_t< daw::traits::is_string_view_like_v< StringView >, UInt32 >
Definition: daw_murmur3.h:72
constexpr basic_stateful_json_value_state(daw::string_view Name, basic_json_value_iterator< ParseState > val)
Definition: daw_json_value_state.h:36
basic_json_value_iterator< ParseState > location
Definition: daw_json_value_state.h:34
constexpr bool is_match(daw::string_view Name) const
Definition: daw_json_value_state.h:43
daw::string_view name
Definition: daw_json_value_state.h:32
daw::UInt32 hash_value
Definition: daw_json_value_state.h:33
constexpr bool is_match(daw::string_view Name, daw::UInt32 hash) const
Definition: daw_json_value_state.h:47
Definition: daw_json_value_state.h:57
daw::string_view name
Definition: daw_json_value_state.h:58
daw::UInt32 hash_value
Definition: daw_json_value_state.h:59
constexpr json_member_name(std::string_view Name)
Definition: daw_json_value_state.h:61
#define DAW_JSON_VER
The version string used in namespace definitions. Must be a valid namespace name.
Definition: version.h:16