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
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;
41
42 explicit constexpr basic_stateful_json_value_state(
43 daw::string_view Name,
45 : name( Name )
46 , location( std::move( val ) ) {}
47
48 [[nodiscard]] constexpr bool is_match( daw::string_view Name ) const {
49 return names_equal( name, Name );
50 }
51 };
52 } // namespace json_details
53
55 daw::string_view name;
56
57 constexpr json_member_name( std::string_view Name )
58 : name( std::data( Name ), std::size( Name ) ) {}
59 };
60
66 template<json_options_t PolicyFlags = json_details::default_policy_flag,
67 typename Allocator = json_details::NoAllocator>
69 using ParseState =
71
73 std::vector<
74 json_details::basic_stateful_json_value_state<PolicyFlags, Allocator>>
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 ) ) {
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:
153 : m_value( std::move( val ) ) {
154
155 daw_json_assert_weak( ( [&] {
156 auto t = m_value.type( );
157 return ( t == JsonBaseParseTypes::Class ) |
158 ( t == JsonBaseParseTypes::Array );
159 }( ) ),
160 ErrorReason::ExpectedArrayOrClassStart,
161 val.get_raw_state( ) );
162 }
163
166 basic_json_value<PolicyFlags, Allocator>( "{}" ) ) {}
167
168 constexpr basic_stateful_json_value( daw::string_view json_data )
170 basic_json_value<PolicyFlags, Allocator>( json_data ) ) {}
171
177 m_value = std::move( val );
178 m_locs.clear( );
179 }
180
186 [[nodiscard]] constexpr basic_json_value<PolicyFlags, Allocator>
187 operator[]( std::string_view key ) {
188 std::size_t pos = move_to( json_member_name( key ) );
189 daw_json_assert_weak( pos < std::size( m_locs ),
190 ErrorReason::UnknownMember );
191 return m_locs[pos].location->value;
192 }
193
199 [[nodiscard]] constexpr basic_json_value<PolicyFlags, Allocator>
201 std::size_t pos = move_to( member );
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>
213 at( std::string_view key ) {
214 auto const k = std::string_view( std::data( key ), std::size( key ) );
215 std::size_t pos = move_to( k );
216 if( pos < std::size( m_locs ) ) {
217 return m_locs[pos].location->value;
218 }
219 return { };
220 }
221
227 [[nodiscard]] std::size_t size( ) {
228 JsonBaseParseTypes const current_type = m_value.type( );
229 switch( current_type ) {
230 case JsonBaseParseTypes::Array:
231 case JsonBaseParseTypes::Class:
232 return move_to( daw::max_value<std::size_t> );
233 case JsonBaseParseTypes::Number:
234 case JsonBaseParseTypes::Bool:
235 case JsonBaseParseTypes::String:
236 case JsonBaseParseTypes::Null:
237 case JsonBaseParseTypes::None:
238 default:
239 return 0;
240 }
241 }
242
249 [[nodiscard]] std::size_t index_of( std::string_view key ) {
250 auto const k = json_member_name( key );
251 return move_to( k );
252 }
253
259 [[nodiscard]] constexpr bool contains( std::string_view key ) {
260 auto const k = std::string_view( std::data( key ), std::size( key ) );
261 return move_to( k ) < std::size( m_locs );
262 }
263
264 /***
265 * Is the indexed member/element present
266 * This method is O(N) worst case and O(1) if the locations have already
267 * @param index position of member/element
268 * @return true if the member/element is present
269 */
270 [[nodiscard]] constexpr bool contains( std::size_t index ) {
271 return move_to( index ) < size( m_locs );
272 }
273
274 /***
275 * Get the position of the named member
276 * @tparam Integer An integer type
277 * @param index position of member. If negative it returns the position
278 * from one past last, e.g. -1 is last item
279 * @return The name of the member or an empty optional
280 */
281 template<typename Integer>
282 [[nodiscard]] std::optional<std::string_view> name_of( Integer index ) {
283 static_assert( std::is_integral_v<Integer>,
284 "Only integer indices are allowed" );
285 if constexpr( std::is_signed_v<Integer> ) {
286 if( index < 0 ) {
287 index = -index;
288 auto sz = size( );
289 if( static_cast<std::size_t>( index ) >= sz ) {
290 return { };
291 }
292 sz -= static_cast<std::size_t>( index );
293 return std::string_view( std::data( m_locs[sz].name( ) ),
294 std::size( m_locs[sz].name( ) ) );
295 }
296 }
297 std::size_t pos = move_to( static_cast<std::size_t>( index ) );
298 if( pos < std::size( m_locs ) ) {
299 return std::string_view( std::data( m_locs[pos].name( ) ),
300 std::size( m_locs[pos].name( ) ) );
301 }
302 return { };
303 }
304
305 /***
306 * basic_json_value for the indexed member
307 * @tparam Integer An integer type
308 * @param index position of member. If negative it returns the position
309 * from one past last, e.g. -1 is last item
310 * @pre index must exist
311 * @return A new basic_json_value for the indexed member
312 */
313 template<typename Integer DAW_ENABLEIF( std::is_integral_v<Integer> )>
314 DAW_REQUIRES( std::is_integral_v<Integer> )
315 [[nodiscard]] constexpr basic_json_value<PolicyFlags, Allocator>
316 operator[]( Integer index ) {
317 if constexpr( std::is_signed_v<Integer> ) {
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 DAW_ENABLEIF( std::is_integral_v<Integer> )>
341 DAW_REQUIRES( std::is_integral_v<Integer> )
342 [[nodiscard]] constexpr std::optional<
344 if constexpr( std::is_signed_v<Integer> ) {
345 if( index < 0 ) {
346 index = -index;
347 auto sz = size( );
348 if( static_cast<std::size_t>( index ) >= sz ) {
349 return { };
350 }
351 sz -= static_cast<std::size_t>( index );
352 return m_locs[sz].location->value( );
353 }
354 }
355 std::size_t pos = move_to( static_cast<std::size_t>( index ) );
356 if( pos < std::size( m_locs ) ) {
357 return m_locs[pos].location->value( );
358 }
359 return { };
360 }
361
362 /***
363 * @return A copy of the underlying basic_json_value
364 */
365 [[nodiscard]] constexpr basic_json_value<PolicyFlags, Allocator>
366 get_json_value( ) const {
367 return m_value;
368 }
369 };
370
372
373 template<json_options_t PolicyFlags, typename Allocator>
376
377 basic_stateful_json_value( daw::string_view )
379
381 } // namespace DAW_JSON_VER
382} // 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
string_writer grows its string with resize_and_overwrite, leaving the new bytes uninitialized,...
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