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_arith_traits.h>
20#include <daw/daw_enable_requires.h>
21#include <daw/daw_move.h>
22#include <daw/daw_string_view.h>
23#include <daw/daw_uint_buffer.h>
24
25#include <cstddef>
26#include <string_view>
27#include <utility>
28#include <vector>
29
30namespace daw::json {
31 inline namespace DAW_JSON_VER {
32 namespace json_details {
33 template<json_options_t PolicyFlags = default_policy_flag,
34 typename Allocator = NoAllocator>
35 class basic_stateful_json_value_state {
36 using ParseState =
38
39 public:
40 daw::string_view name;
41 json_name_hash_t hash_value;
43
44 explicit constexpr basic_stateful_json_value_state(
45 daw::string_view Name,
47 : name( Name )
48 , hash_value(
49 daw::name_hash<ParseState::expect_long_strings>( Name ) )
50 , location( std::move( val ) ) {}
51
52 [[nodiscard]] constexpr bool is_match( daw::string_view Name ) const {
53 return name == Name;
54 }
55
56 [[nodiscard]] constexpr bool is_match( daw::string_view Name,
57 json_name_hash_t hash ) const {
58 if( hash != hash_value ) {
59 return false;
60 }
61 return name == Name;
62 }
63 };
64 } // namespace json_details
65
67 daw::string_view name;
69
70 constexpr json_member_name( std::string_view Name )
71 : name( std::data( Name ), std::size( Name ) )
72 , hash_value( daw::name_hash<false>( name ) ) {}
73 };
74
80 template<json_options_t PolicyFlags = json_details::default_policy_flag,
81 typename Allocator = json_details::NoAllocator>
83 using ParseState =
85
87 std::vector<
88 json_details::basic_stateful_json_value_state<PolicyFlags, Allocator>>
89 m_locs{ };
90
91 /***
92 * Move parser until member name matches key if needed
93 * @param member to move_to
94 * @return position of member or size
95 */
96 [[nodiscard]] constexpr std::size_t move_to( json_member_name member ) {
97 std::size_t pos = 0;
98 std::size_t const Sz = std::size( m_locs );
99 for( ; pos < Sz; ++pos ) {
100 if( m_locs[pos].is_match( member.name, member.hash_value ) ) {
101 return pos;
102 }
103 }
104
105 auto it = [&] {
106 if( m_locs.empty( ) ) {
107 return m_value.begin( );
108 }
109 auto res = m_locs.back( ).location;
110 ++res;
111 return res;
112 }( );
113 auto const last = m_value.end( );
114 while( it != last ) {
115 auto name = it.name( );
116 daw_json_assert_weak( name, ErrorReason::MissingMemberName );
117 auto const &new_loc = m_locs.emplace_back(
118 daw::string_view( std::data( *name ), std::size( *name ) ), it );
119 if( new_loc.is_match( member.name ) ) {
120 return pos;
121 }
122 ++pos;
123 ++it;
124 }
125 return std::size( m_locs );
126 }
127
128 /***
129 * Move parser until member index matches, if needed
130 * @param index position of member to move to
131 * @return position in members or size
132 */
133 [[nodiscard]] constexpr std::size_t move_to( std::size_t index ) {
134 if( index < std::size( m_locs ) ) {
135 return index;
136 }
137 auto it = [&] {
138 if( m_locs.empty( ) ) {
139 return m_value.begin( );
140 }
141 auto res = m_locs.back( ).location;
142 ++res;
143 return res;
144 }( );
145 auto last = m_value.end( );
146 std::size_t pos = std::size( m_locs );
147 while( it != last ) {
148 auto name = it.name( );
149 if( name ) {
150 m_locs.emplace_back(
151 daw::string_view( std::data( *name ), std::size( *name ) ), it );
152 } else {
153 m_locs.emplace_back( daw::string_view( ), it );
154 }
155 if( pos == index ) {
156 return pos;
157 }
158 ++pos;
159 ++it;
160 }
161 return std::size( m_locs );
162 }
163
164 public:
167 : m_value( std::move( val ) ) {
168
169 daw_json_assert_weak( ( [&] {
170 auto t = m_value.type( );
171 return ( t == JsonBaseParseTypes::Class ) |
172 ( t == JsonBaseParseTypes::Array );
173 }( ) ),
174 ErrorReason::ExpectedArrayOrClassStart,
175 val.get_raw_state( ) );
176 }
177
180 basic_json_value<PolicyFlags, Allocator>( "{}" ) ) {}
181
182 constexpr basic_stateful_json_value( daw::string_view json_data )
184 basic_json_value<PolicyFlags, Allocator>( json_data ) ) {}
185
191 m_value = std::move( val );
192 m_locs.clear( );
193 }
194
200 [[nodiscard]] constexpr basic_json_value<PolicyFlags, Allocator>
201 operator[]( std::string_view key ) {
202 std::size_t pos = move_to( json_member_name( key ) );
203 daw_json_assert_weak( pos < std::size( m_locs ),
204 ErrorReason::UnknownMember );
205 return m_locs[pos].location->value;
206 }
207
213 [[nodiscard]] constexpr basic_json_value<PolicyFlags, Allocator>
215 std::size_t pos = move_to( member );
216 daw_json_assert_weak( pos < std::size( m_locs ),
217 ErrorReason::UnknownMember );
218 return m_locs[pos].location->value;
219 }
220
226 [[nodiscard]] constexpr basic_json_value<PolicyFlags, Allocator>
227 at( std::string_view key ) {
228 auto const k = std::string_view( std::data( key ), std::size( key ) );
229 std::size_t pos = move_to( k );
230 if( pos < std::size( m_locs ) ) {
231 return m_locs[pos].location->value;
232 }
233 return { };
234 }
235
241 [[nodiscard]] std::size_t size( ) {
242 JsonBaseParseTypes const current_type = m_value.type( );
243 switch( current_type ) {
244 case JsonBaseParseTypes::Array:
245 case JsonBaseParseTypes::Class:
246 return move_to( daw::max_value<std::size_t> );
247 case JsonBaseParseTypes::Number:
248 case JsonBaseParseTypes::Bool:
249 case JsonBaseParseTypes::String:
250 case JsonBaseParseTypes::Null:
251 case JsonBaseParseTypes::None:
252 default:
253 return 0;
254 }
255 }
256
263 [[nodiscard]] std::size_t index_of( std::string_view key ) {
264 auto const k = json_member_name( key );
265 return move_to( k );
266 }
267
273 [[nodiscard]] constexpr bool contains( std::string_view key ) {
274 auto const k = std::string_view( std::data( key ), std::size( key ) );
275 return move_to( k ) < std::size( m_locs );
276 }
277
278 /***
279 * Is the indexed member/element present
280 * This method is O(N) worst case and O(1) if the locations have already
281 * @param index position of member/element
282 * @return true if the member/element is present
283 */
284 [[nodiscard]] constexpr bool contains( std::size_t index ) {
285 return move_to( index ) < size( m_locs );
286 }
287
288 /***
289 * Get the position of the named member
290 * @tparam Integer An integer type
291 * @param index position of member. If negative it returns the position
292 * from one past last, e.g. -1 is last item
293 * @return The name of the member or an empty optional
294 */
295 template<typename Integer>
296 [[nodiscard]] std::optional<std::string_view> name_of( Integer index ) {
297 static_assert( std::is_integral_v<Integer>,
298 "Only integer indices are allowed" );
299 if constexpr( std::is_signed_v<Integer> ) {
300 if( index < 0 ) {
301 index = -index;
302 auto sz = size( );
303 if( static_cast<std::size_t>( index ) >= sz ) {
304 return { };
305 }
306 sz -= static_cast<std::size_t>( index );
307 return std::string_view( std::data( m_locs[sz].name( ) ),
308 std::size( m_locs[sz].name( ) ) );
309 }
310 }
311 std::size_t pos = move_to( static_cast<std::size_t>( index ) );
312 if( pos < std::size( m_locs ) ) {
313 return std::string_view( std::data( m_locs[pos].name( ) ),
314 std::size( m_locs[pos].name( ) ) );
315 }
316 return { };
317 }
318
319 /***
320 * basic_json_value for the indexed member
321 * @tparam Integer An integer type
322 * @param index position of member. If negative it returns the position
323 * from one past last, e.g. -1 is last item
324 * @pre index must exist
325 * @return A new basic_json_value for the indexed member
326 */
327 template<typename Integer DAW_ENABLEIF( std::is_integral_v<Integer> )>
328 DAW_REQUIRES( std::is_integral_v<Integer> )
329 [[nodiscard]] constexpr basic_json_value<PolicyFlags, Allocator>
330 operator[]( Integer index ) {
331 if constexpr( std::is_signed_v<Integer> ) {
332 if( index < 0 ) {
333 index = -index;
334 auto sz = size( );
335 daw_json_assert_weak( ( static_cast<std::size_t>( index ) < sz ),
336 ErrorReason::UnknownMember );
337 sz -= static_cast<std::size_t>( index );
338 return m_locs[sz].location->value;
339 }
340 }
341 std::size_t pos = move_to( static_cast<std::size_t>( index ) );
342 daw_json_assert_weak( pos < std::size( m_locs ),
343 ErrorReason::UnknownMember );
344 return m_locs[pos].location->value;
345 }
346
347 /***
348 * basic_json_value for the indexed member
349 * @tparam Integer An integer type
350 * @param index position of member. If negative it returns the position
351 * from one past last, e.g. -1 is last item
352 * @return A new basic_json_value for the indexed member
353 */
354 template<typename Integer DAW_ENABLEIF( std::is_integral_v<Integer> )>
355 DAW_REQUIRES( std::is_integral_v<Integer> )
356 [[nodiscard]] constexpr std::optional<
358 if constexpr( std::is_signed_v<Integer> ) {
359 if( index < 0 ) {
360 index = -index;
361 auto sz = size( );
362 if( static_cast<std::size_t>( index ) >= sz ) {
363 return { };
364 }
365 sz -= static_cast<std::size_t>( index );
366 return m_locs[sz].location->value( );
367 }
368 }
369 std::size_t pos = move_to( static_cast<std::size_t>( index ) );
370 if( pos < std::size( m_locs ) ) {
371 return m_locs[pos].location->value( );
372 }
373 return { };
374 }
375
376 /***
377 * @return A copy of the underlying basic_json_value
378 */
379 [[nodiscard]] constexpr basic_json_value<PolicyFlags, Allocator>
380 get_json_value( ) const {
381 return m_value;
382 }
383 };
384
386
387 template<json_options_t PolicyFlags, typename Allocator>
390
391 basic_stateful_json_value( daw::string_view )
393
395 } // namespace DAW_JSON_VER
396} // 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