DAW JSON Link
Loading...
Searching...
No Matches
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
12
18
19#include <daw/daw_enable_requires.h>
20#include <daw/daw_move.h>
21#include <daw/daw_string_view.h>
22#include <daw/daw_uint_buffer.h>
23
24#include <cstddef>
25#include <string_view>
26#include <utility>
27#include <vector>
28
29namespace daw::json {
30 inline namespace DAW_JSON_VER {
31 namespace json_details {
32 template<json_options_t PolicyFlags = default_policy_flag,
33 typename Allocator = NoAllocator>
34 class basic_stateful_json_value_state {
35 using ParseState =
37
38 public:
39 daw::string_view name;
40 json_name_hash_t hash_value;
42
43 explicit constexpr basic_stateful_json_value_state(
44 daw::string_view Name,
46 : name( Name )
47 , hash_value(
48 daw::name_hash<ParseState::expect_long_strings>( Name ) )
49 , location( std::move( val ) ) {}
50
51 [[nodiscard]] constexpr bool is_match( daw::string_view Name ) const {
52 return name == Name;
53 }
54
55 [[nodiscard]] constexpr bool is_match( daw::string_view Name,
56 json_name_hash_t hash ) const {
57 if( hash != hash_value ) {
58 return false;
59 }
60 return name == Name;
61 }
62 };
63 } // namespace json_details
64
66 daw::string_view name;
68
69 constexpr json_member_name( std::string_view Name )
70 : name( std::data( Name ), std::size( Name ) )
71 , hash_value( daw::name_hash<false>( name ) ) {}
72 };
73
79 template<json_options_t PolicyFlags = json_details::default_policy_flag,
80 typename Allocator = json_details::NoAllocator>
82 using ParseState =
84
86 std::vector<
87 json_details::basic_stateful_json_value_state<PolicyFlags, Allocator>>
88 m_locs{ };
89
90 /***
91 * Move parser until member name matches key if needed
92 * @param member to move_to
93 * @return position of member or size
94 */
95 [[nodiscard]] constexpr std::size_t move_to( json_member_name member ) {
96 std::size_t pos = 0;
97 std::size_t const Sz = std::size( m_locs );
98 for( ; pos < Sz; ++pos ) {
99 if( m_locs[pos].is_match( member.name, member.hash_value ) ) {
100 return pos;
101 }
102 }
103
104 auto it = [&] {
105 if( m_locs.empty( ) ) {
106 return m_value.begin( );
107 }
108 auto res = m_locs.back( ).location;
109 ++res;
110 return res;
111 }( );
112 auto const last = m_value.end( );
113 while( it != last ) {
114 auto name = it.name( );
115 daw_json_assert_weak( name, ErrorReason::MissingMemberName );
116 auto const &new_loc = m_locs.emplace_back(
117 daw::string_view( std::data( *name ), std::size( *name ) ), it );
118 if( new_loc.is_match( member.name ) ) {
119 return pos;
120 }
121 ++pos;
122 ++it;
123 }
124 return std::size( m_locs );
125 }
126
127 /***
128 * Move parser until member index matches, if needed
129 * @param index position of member to move to
130 * @return position in members or size
131 */
132 [[nodiscard]] constexpr std::size_t move_to( std::size_t index ) {
133 if( index < std::size( m_locs ) ) {
134 return index;
135 }
136 auto it = [&] {
137 if( m_locs.empty( ) ) {
138 return m_value.begin( );
139 }
140 auto res = m_locs.back( ).location;
141 ++res;
142 return res;
143 }( );
144 auto last = m_value.end( );
145 std::size_t pos = std::size( m_locs );
146 while( it != last ) {
147 auto name = it.name( );
148 if( name ) {
149 m_locs.emplace_back(
150 daw::string_view( std::data( *name ), std::size( *name ) ), it );
151 } else {
152 m_locs.emplace_back( daw::string_view( ), it );
153 }
154 if( pos == index ) {
155 return pos;
156 }
157 ++pos;
158 ++it;
159 }
160 return std::size( m_locs );
161 }
162
163 public:
166 : m_value( std::move( val ) ) {
167
168 daw_json_assert_weak( ( [&] {
169 auto t = m_value.type( );
170 return ( t == JsonBaseParseTypes::Class ) |
171 ( t == JsonBaseParseTypes::Array );
172 }( ) ),
173 ErrorReason::ExpectedArrayOrClassStart,
174 val.get_raw_state( ) );
175 }
176
179 basic_json_value<PolicyFlags, Allocator>( "{}" ) ) {}
180
181 constexpr basic_stateful_json_value( daw::string_view json_data )
183 basic_json_value<PolicyFlags, Allocator>( json_data ) ) {}
184
190 m_value = std::move( val );
191 m_locs.clear( );
192 }
193
199 [[nodiscard]] constexpr basic_json_value<PolicyFlags, Allocator>
200 operator[]( std::string_view key ) {
201 std::size_t pos = move_to( json_member_name( key ) );
202 daw_json_assert_weak( pos < std::size( m_locs ),
203 ErrorReason::UnknownMember );
204 return m_locs[pos].location->value;
205 }
206
212 [[nodiscard]] constexpr basic_json_value<PolicyFlags, Allocator>
214 std::size_t pos = move_to( member );
215 daw_json_assert_weak( pos < std::size( m_locs ),
216 ErrorReason::UnknownMember );
217 return m_locs[pos].location->value;
218 }
219
225 [[nodiscard]] constexpr basic_json_value<PolicyFlags, Allocator>
226 at( std::string_view key ) {
227 auto const k = std::string_view( std::data( key ), std::size( key ) );
228 std::size_t pos = move_to( k );
229 if( pos < std::size( m_locs ) ) {
230 return m_locs[pos].location->value;
231 }
232 return { };
233 }
234
240 [[nodiscard]] std::size_t size( ) {
241 JsonBaseParseTypes const current_type = m_value.type( );
242 switch( current_type ) {
243 case JsonBaseParseTypes::Array:
244 case JsonBaseParseTypes::Class:
245 return move_to( ( daw::numeric_limits<std::size_t>::max )( ) );
246 case JsonBaseParseTypes::Number:
247 case JsonBaseParseTypes::Bool:
248 case JsonBaseParseTypes::String:
249 case JsonBaseParseTypes::Null:
250 case JsonBaseParseTypes::None:
251 default:
252 return 0;
253 }
254 }
255
262 [[nodiscard]] std::size_t index_of( std::string_view key ) {
263 auto const k = json_member_name( key );
264 return move_to( k );
265 }
266
272 [[nodiscard]] constexpr bool contains( std::string_view key ) {
273 auto const k = std::string_view( std::data( key ), std::size( key ) );
274 return move_to( k ) < std::size( m_locs );
275 }
276
277 /***
278 * Is the indexed member/element present
279 * This method is O(N) worst case and O(1) if the locations have already
280 * @param index position of member/element
281 * @return true if the member/element is present
282 */
283 [[nodiscard]] constexpr bool contains( std::size_t index ) {
284 return move_to( index ) < size( m_locs );
285 }
286
287 /***
288 * Get the position of the named member
289 * @tparam Integer An integer type
290 * @param index position of member. If negative it returns the position
291 * from one past last, e.g. -1 is last item
292 * @return The name of the member or an empty optional
293 */
294 template<typename Integer>
295 [[nodiscard]] std::optional<std::string_view> name_of( Integer index ) {
296 static_assert( std::is_integral_v<Integer>,
297 "Only integer indices are allowed" );
298 if constexpr( std::is_signed_v<Integer> ) {
299 if( index < 0 ) {
300 index = -index;
301 auto sz = size( );
302 if( static_cast<std::size_t>( index ) >= sz ) {
303 return { };
304 }
305 sz -= static_cast<std::size_t>( index );
306 return std::string_view( std::data( m_locs[sz].name( ) ),
307 std::size( m_locs[sz].name( ) ) );
308 }
309 }
310 std::size_t pos = move_to( static_cast<std::size_t>( index ) );
311 if( pos < std::size( m_locs ) ) {
312 return std::string_view( std::data( m_locs[pos].name( ) ),
313 std::size( m_locs[pos].name( ) ) );
314 }
315 return { };
316 }
317
318 /***
319 * basic_json_value for the indexed member
320 * @tparam Integer An integer type
321 * @param index position of member. If negative it returns the position
322 * from one past last, e.g. -1 is last item
323 * @pre index must exist
324 * @return A new basic_json_value for the indexed member
325 */
326 template<typename Integer DAW_ENABLEIF( std::is_integral_v<Integer> )>
327 DAW_REQUIRES( std::is_integral_v<Integer> )
328 [[nodiscard]] constexpr basic_json_value<PolicyFlags, Allocator>
329 operator[]( Integer index ) {
330 if constexpr( std::is_signed_v<Integer> ) {
331 if( index < 0 ) {
332 index = -index;
333 auto sz = size( );
334 daw_json_assert_weak( ( static_cast<std::size_t>( index ) < sz ),
335 ErrorReason::UnknownMember );
336 sz -= static_cast<std::size_t>( index );
337 return m_locs[sz].location->value;
338 }
339 }
340 std::size_t pos = move_to( static_cast<std::size_t>( index ) );
341 daw_json_assert_weak( pos < std::size( m_locs ),
342 ErrorReason::UnknownMember );
343 return m_locs[pos].location->value;
344 }
345
346 /***
347 * basic_json_value for the indexed member
348 * @tparam Integer An integer type
349 * @param index position of member. If negative it returns the position
350 * from one past last, e.g. -1 is last item
351 * @return A new basic_json_value for the indexed member
352 */
353 template<typename Integer DAW_ENABLEIF( std::is_integral_v<Integer> )>
354 DAW_REQUIRES( std::is_integral_v<Integer> )
355 [[nodiscard]] constexpr std::optional<
357 if constexpr( std::is_signed_v<Integer> ) {
358 if( index < 0 ) {
359 index = -index;
360 auto sz = size( );
361 if( static_cast<std::size_t>( index ) >= sz ) {
362 return { };
363 }
364 sz -= static_cast<std::size_t>( index );
365 return m_locs[sz].location->value( );
366 }
367 }
368 std::size_t pos = move_to( static_cast<std::size_t>( index ) );
369 if( pos < std::size( m_locs ) ) {
370 return m_locs[pos].location->value( );
371 }
372 return { };
373 }
374
375 /***
376 * @return A copy of the underlying basic_json_value
377 */
378 [[nodiscard]] constexpr basic_json_value<PolicyFlags, Allocator>
379 get_json_value( ) const {
380 return m_value;
381 }
382 };
383
385
386 template<json_options_t PolicyFlags, typename Allocator>
389
390 basic_stateful_json_value( daw::string_view )
392
394 } // namespace DAW_JSON_VER
395} // namespace daw::json
constexpr bool contains(std::string_view key)
Is the named member present. This method is O(N) worst case and O(1) if the locations have already.
constexpr basic_json_value< PolicyFlags, Allocator > at(std::string_view key)
Create a basic_json_member for the named member.
std::size_t index_of(std::string_view key)
Return the index of named member. This method is O(N) worst case and O(1) if the locations have alrea...
constexpr basic_json_value< PolicyFlags, Allocator > get_json_value() const
constexpr basic_json_value< PolicyFlags, Allocator > operator[](Integer index)
std::size_t size()
Count the number of elements/members in the JSON class or array This method is O(N) worst case and O(...
constexpr std::optional< basic_json_value< PolicyFlags, Allocator > > at(Integer index)
constexpr basic_json_value< PolicyFlags, Allocator > operator[](json_member_name member)
Create a basic_json_member for the named member.
TryDefaultParsePolicy< BasicParsePolicy< PolicyFlags, Allocator > > ParseState
constexpr basic_stateful_json_value(basic_json_value< PolicyFlags, Allocator > val)
constexpr basic_json_value< PolicyFlags, Allocator > operator[](std::string_view key)
Create a basic_json_member for the named member.
constexpr void reset(basic_json_value< PolicyFlags, Allocator > val)
#define daw_json_assert_weak(Bool,...)
Assert that Bool is true when in Checked Input mode If false pass rest of args to daw_json_error.
DAW_REQUIRES(daw::json::json_details::is_container_opted_into_json_iostreams_v< Container >) std
An opt in ostream interface for containers of types that have JSON mappings.
daw::conditional_t< ParsePolicy::is_default_parse_policy, DefaultParsePolicy, ParsePolicy > TryDefaultParsePolicy
Customization point traits.
daw::UInt64 json_name_hash_t
Definition daw_murmur3.h:23
Iterator for iterating over arbitrary JSON members and array elements.
constexpr std::optional< std::string_view > name() const
Name of member.
A non-owning container for arbitrary JSON values that allows movement/iteration through.
constexpr iterator end() const
End of range over class/arrays members/items.
constexpr iterator begin() const
Get the first member/item.
constexpr ParseState get_raw_state() const
Get a copy of the underlying parse state.
constexpr JsonBaseParseTypes type() const
Get the type of JSON value.
#define DAW_JSON_VER
The version string used in namespace definitions. Must be a valid namespace name.
Definition version.h:20