DAW JSON Link
Loading...
Searching...
No Matches
daw_json_event_parser.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
11#include "impl/version.h"
12
16
17#include <daw/daw_cpp20_concept.h>
18#include <daw/daw_move.h>
19#include <daw/daw_string_view.h>
20
21#include <cstddef>
22#include <daw/stdinc/declval.h>
23#include <daw/stdinc/move_fwd_exch.h>
24#include <optional>
25#include <utility>
26#include <vector>
27
28namespace daw::json {
29 inline namespace DAW_JSON_VER {
38
39 namespace json_details {
40 struct handler_result_holder {
41 json_parse_handler_result value = json_parse_handler_result::Continue;
42
43 handler_result_holder( ) = default;
44
45 constexpr handler_result_holder( bool b )
46 : value( b ? Continue : Complete ) {}
47
48 constexpr handler_result_holder( json_parse_handler_result r )
49 : value( r ) {}
50
51 constexpr explicit operator bool( ) const {
52 return value == json_parse_handler_result::Continue;
53 }
54 };
55
56 namespace hnd_checks {
57 // On Next Value
59 has_on_value_handler_impl,
60 std::declval<T>( ).handle_on_value( std::declval<U>( ) ) );
61
62 template<typename Handler, json_options_t, typename JPair>
63 DAW_CPP20_CONCEPT has_on_value_handler_v =
64 has_on_value_handler_impl<Handler, JPair>;
65
66 // On Array Start
68 has_on_array_start_handler_impl,
69 std::declval<T>( ).handle_on_array_start( std::declval<U>( ) ) );
70
71 template<typename Handler, json_options_t /*O*/, typename JValue>
72 DAW_CPP20_CONCEPT has_on_array_start_handler_v =
73 has_on_array_start_handler_impl<Handler, JValue>;
74
75 // On Array End
76 DAW_JSON_MAKE_REQ_TRAIT( has_on_array_end_handler_v,
77 std::declval<T>( ).handle_on_array_end( ) );
78
79 // On Class Start
81 has_on_class_start_handler_impl,
82 std::declval<T>( ).handle_on_class_start( std::declval<U>( ) ) );
83
84 template<typename Handler, json_options_t /*Opt*/, typename JValue>
85 DAW_CPP20_CONCEPT has_on_class_start_handler_v =
86 has_on_class_start_handler_impl<Handler, JValue>;
87
88 // On Class End
89 DAW_JSON_MAKE_REQ_TRAIT( has_on_class_end_handler_v,
90 std::declval<T>( ).handle_on_class_end( ) );
91
92 // On Number
94 has_on_number_handler_jv_impl,
95 std::declval<T>( ).handle_on_number( std::declval<U>( ) ) );
96
97 template<typename Handler, json_options_t P, typename A>
98 DAW_CPP20_CONCEPT has_on_number_handler_jv_v =
99 has_on_number_handler_jv_impl<Handler, basic_json_value<P, A>>;
100
101 DAW_JSON_MAKE_REQ_TRAIT( has_on_number_handler_dbl_v,
102 std::declval<T>( ).handle_on_number( 0.0 ) );
103
104 // On Bool // T = Handler, U = JValue
106 has_on_bool_handler_jv_impl,
107 std::declval<T>( ).handle_on_bool( std::declval<U>( ) ) );
108
109 template<typename Handler, json_options_t P, typename A>
110 DAW_CPP20_CONCEPT has_on_bool_handler_jv_v =
111 has_on_bool_handler_jv_impl<Handler, basic_json_value<P, A>>;
112
113 DAW_JSON_MAKE_REQ_TRAIT( has_on_bool_handler_bl_v,
114 std::declval<T>( ).handle_on_bool( true ) );
115
116 // On String // T = Handler, U = JValue
118 has_on_string_handler_impl,
119 std::declval<T>( ).handle_on_string( std::declval<U>( ) ) );
120
121 template<typename Handler, json_options_t P, typename A>
122 DAW_CPP20_CONCEPT has_on_string_handler_jv_v =
123 has_on_string_handler_impl<Handler, basic_json_value<P, A>>;
124
126 has_on_string_handler_str_v,
127 std::declval<T>( ).handle_on_string( std::declval<std::string>( ) ) );
128
129 // On Null, T = Handler, U = JValue
131 has_on_null_handler_impl,
132 std::declval<T>( ).handle_on_null( std::declval<U>( ) ) );
133
134 template<typename Handler, json_options_t P, typename A>
135 DAW_CPP20_CONCEPT has_on_null_handler_jv_v =
136 has_on_null_handler_impl<Handler, basic_json_value<P, A>>;
137
138 DAW_JSON_MAKE_REQ_TRAIT( has_on_null_handler_v,
139 std::declval<T>( ).handle_on_null( ) );
140
141 // On Error
143 has_on_error_handler_impl,
144 std::declval<T>( ).handle_on_error( std::declval<U>( ) ) );
145
146 template<typename Handler, json_options_t P, typename A>
147 DAW_CPP20_CONCEPT has_on_error_handler_v =
148 has_on_error_handler_impl<Handler, basic_json_value<P, A>>;
149 } // namespace hnd_checks
150
151 template<typename T>
152 constexpr daw::remove_cvref_t<T> as_copy( T &&value ) {
153 return value;
154 }
155
156 template<typename Handler, json_options_t P, typename A>
157 constexpr handler_result_holder
158 handle_on_value( Handler &&handler, basic_json_pair<P, A> p ) {
159 if constexpr( hnd_checks::has_on_value_handler_v<Handler, P, A> ) {
160 return handler.handle_on_value( std::move( p ) );
161 } else {
162 (void)p;
163 return handler_result_holder{ };
164 }
165 }
166
167 template<typename Handler, json_options_t P, typename A>
168 constexpr handler_result_holder
169 handle_on_array_start( Handler &&handler, basic_json_value<P, A> jv ) {
170 if constexpr( hnd_checks::
171 has_on_array_start_handler_v<Handler, P, A> ) {
172 return handler.handle_on_array_start( std::move( jv ) );
173 } else {
174 (void)jv;
175 return handler_result_holder{ };
176 }
177 }
178
179 template<typename Handler>
180 constexpr handler_result_holder handle_on_array_end( Handler &&handler ) {
181 if constexpr( hnd_checks::has_on_array_end_handler_v<Handler> ) {
182 return handler.handle_on_array_end( );
183 } else {
184 return handler_result_holder{ };
185 }
186 }
187
188 template<typename Handler, json_options_t P, typename A>
189 constexpr handler_result_holder
190 handle_on_class_start( Handler &&handler, basic_json_value<P, A> jv ) {
191 if constexpr( hnd_checks::
192 has_on_class_start_handler_v<Handler, P, A> ) {
193 return handler.handle_on_class_start( std::move( jv ) );
194 } else {
195 (void)jv;
196 return handler_result_holder{ };
197 }
198 }
199
200 template<typename Handler>
201 constexpr handler_result_holder handle_on_class_end( Handler &&handler ) {
202 if constexpr( hnd_checks::has_on_class_end_handler_v<Handler> ) {
203 return handler.handle_on_class_end( );
204 } else {
205 return handler_result_holder{ };
206 }
207 }
208
209 template<typename Handler, json_options_t P, typename A>
210 constexpr handler_result_holder
211 handle_on_number( Handler &&handler, basic_json_value<P, A> &jv ) {
212 if constexpr( hnd_checks::has_on_number_handler_jv_v<Handler, P, A> ) {
213 return handler.handle_on_number( as_copy( jv ) );
214 } else if constexpr( hnd_checks::has_on_number_handler_dbl_v<
215 Handler> ) {
216 return handler.handle_on_number( from_json<double>( jv ) );
217 } else {
218 (void)jv;
219 return handler_result_holder{ };
220 }
221 }
222
223 template<typename Handler, json_options_t P, typename A>
224 constexpr handler_result_holder
225 handle_on_bool( Handler &&handler, basic_json_value<P, A> jv ) {
226 if constexpr( hnd_checks::has_on_bool_handler_jv_v<Handler, P, A> ) {
227 return handler.handle_on_bool( as_copy( jv ) );
228 } else if constexpr( hnd_checks::has_on_bool_handler_bl_v<Handler> ) {
229 return handler.handle_on_bool( from_json<bool>( jv ) );
230 } else {
231 (void)jv;
232 return handler_result_holder{ };
233 }
234 }
235
236 template<typename Handler, json_options_t P, typename A>
237 constexpr handler_result_holder
238 handle_on_string( Handler &&handler, basic_json_value<P, A> &jv ) {
239 if constexpr( hnd_checks::has_on_string_handler_jv_v<Handler, P, A> ) {
240 return handler.handle_on_string( as_copy( jv ) );
241 } else if constexpr( hnd_checks::has_on_string_handler_str_v<
242 Handler> ) {
243 return handler.handle_on_string( jv.get_string( ) );
244 } else {
245 (void)jv;
246 return handler_result_holder{ };
247 }
248 }
249
250 template<typename Handler, json_options_t P, typename A>
251 constexpr handler_result_holder
252 handle_on_null( Handler &&handler, basic_json_value<P, A> &jv ) {
253 if constexpr( hnd_checks::has_on_null_handler_jv_v<Handler, P, A> ) {
254 return handler.handle_on_null( as_copy( jv ) );
255 } else if constexpr( hnd_checks::has_on_null_handler_v<Handler> ) {
256 return handler.handle_on_null( );
257 } else {
258 return handler_result_holder{ };
259 }
260 }
261
262 template<typename Handler, json_options_t P, typename A>
263 constexpr handler_result_holder
264 handle_on_error( Handler &&handler, basic_json_value<P, A> jv ) {
265 if constexpr( hnd_checks::has_on_error_handler_v<Handler, P, A> ) {
266 return handler.handle_on_error( std::move( jv ) );
267 } else {
268 (void)jv;
269 return handler_result_holder{ };
270 }
271 }
272
273 } // namespace json_details
274
275 enum class StackParseStateType { Class, Array };
276
277 template<json_options_t P, typename A>
283
284 template<typename StackValue, typename StackType = std::vector<StackValue>>
286 using stack_t = StackType;
287 stack_t m_stack{ };
288
289 public:
290 using value_type = StackValue;
291 using reference = StackValue &;
292 using size_type = std::size_t;
293 using difference_type = std::ptrdiff_t;
294
296
298 m_stack.push_back( std::move( v ) );
299 }
300
301 [[nodiscard]] CPP20CONSTEXPR reference back( ) {
302 return m_stack.back( );
303 }
304
306 m_stack.clear( );
307 }
308
310 m_stack.pop_back( );
311 }
312
313 [[nodiscard]] CPP20CONSTEXPR bool empty( ) const {
314 return m_stack.empty( );
315 }
316 };
317
318 template<typename StackContainerPolicy = use_default, json_options_t P,
319 typename A, typename Handler, auto... ParseFlags>
321 Handler &&handler,
322 options::parse_flags_t<ParseFlags...> ) {
323
324 using ParseState =
326 template SetPolicyOptions<ParseFlags...>>;
327
328 using iterator =
329 basic_json_value_iterator<ParseState::policy_flags( ), A>;
330 using json_value_t = typename iterator::json_pair;
331 using stack_value_t =
332 JsonEventParserStackValue<ParseState::policy_flags( ), A>;
333 auto jvalue = basic_json_value( bjv );
334
335 auto parent_stack = [] DAW_CPP23_STATIC_CALL_OP {
336 if constexpr( std::is_same_v<StackContainerPolicy, use_default> ) {
338 } else {
339 return StackContainerPolicy{ };
340 }
341 }( );
342 long long class_depth = 0;
343 long long array_depth = 0;
344
345 auto const move_to_last = [&]( ) {
346 parent_stack.back( ).value.first = parent_stack.back( ).value.second;
347 };
348
349 auto const process_value = [&]( json_value_t p ) {
350 {
351 auto result = json_details::handle_on_value( handler, p );
352 switch( result.value ) {
353 case json_parse_handler_result::Complete:
354 parent_stack.clear( );
355 return;
356 case json_parse_handler_result::SkipClassArray:
357 move_to_last( );
358 return;
359 case json_parse_handler_result::Continue:
360 break;
361 }
362 }
363
364 auto &jv = p.value;
365 switch( jv.type( ) ) {
366 case JsonBaseParseTypes::Array: {
367 ++array_depth;
368 auto result = json_details::handle_on_array_start( handler, jv );
369 switch( result.value ) {
370 case json_parse_handler_result::Complete:
371 parent_stack.clear( );
372 return;
373 case json_parse_handler_result::SkipClassArray:
374 move_to_last( );
375 return;
376 case json_parse_handler_result::Continue:
377 break;
378 }
379 parent_stack.push_back(
380 { StackParseStateType::Array,
381 std::pair<iterator, iterator>( jv.begin( ), jv.end( ) ) } );
382 } break;
383 case JsonBaseParseTypes::Class: {
384 ++class_depth;
385 auto result = json_details::handle_on_class_start( handler, jv );
386 switch( result.value ) {
387 case json_parse_handler_result::Complete:
388 parent_stack.clear( );
389 return;
390 case json_parse_handler_result::SkipClassArray:
391 move_to_last( );
392 return;
393 case json_parse_handler_result::Continue:
394 break;
395 }
396 parent_stack.push_back(
397 { StackParseStateType::Class,
398 std::pair<iterator, iterator>( jv.begin( ), jv.end( ) ) } );
399 } break;
400 case JsonBaseParseTypes::Number: {
401 auto result = json_details::handle_on_number( handler, jv );
402 switch( result.value ) {
403 case json_parse_handler_result::Complete:
404 parent_stack.clear( );
405 return;
406 case json_parse_handler_result::SkipClassArray:
407 move_to_last( );
408 return;
409 case json_parse_handler_result::Continue:
410 break;
411 }
412 } break;
413 case JsonBaseParseTypes::Bool: {
414 auto result = json_details::handle_on_bool( handler, jv );
415 switch( result.value ) {
416 case json_parse_handler_result::Complete:
417 parent_stack.clear( );
418 return;
419 case json_parse_handler_result::SkipClassArray:
420 move_to_last( );
421 return;
422 case json_parse_handler_result::Continue:
423 break;
424 }
425 } break;
426 case JsonBaseParseTypes::String: {
427 auto result = json_details::handle_on_string( handler, jv );
428 switch( result.value ) {
429 case json_parse_handler_result::Complete:
430 parent_stack.clear( );
431 return;
432 case json_parse_handler_result::SkipClassArray:
433 move_to_last( );
434 return;
435 case json_parse_handler_result::Continue:
436 break;
437 }
438 } break;
439 case JsonBaseParseTypes::Null: {
440 auto result = json_details::handle_on_null( handler, jv );
441 switch( result.value ) {
442 case json_parse_handler_result::Complete:
443 parent_stack.clear( );
444 return;
445 case json_parse_handler_result::SkipClassArray:
446 move_to_last( );
447 return;
448 case json_parse_handler_result::Continue:
449 break;
450 }
451 } break;
452 case JsonBaseParseTypes::None:
453 default: {
454 auto result = json_details::handle_on_error( handler, jv );
455 switch( result.value ) {
456 case json_parse_handler_result::Complete:
457 parent_stack.clear( );
458 return;
459 case json_parse_handler_result::SkipClassArray:
460 move_to_last( );
461 return;
462 case json_parse_handler_result::Continue:
463 break;
464 }
465 } break;
466 }
467 };
468
469 auto const process_range = [&]( stack_value_t v ) {
470 if( v.value.first != v.value.second ) {
471 auto jv = *v.value.first;
472 ++v.value.first;
473 parent_stack.push_back( std::move( v ) );
474 process_value( std::move( jv ) );
475 } else {
476 switch( v.type ) {
477 case StackParseStateType::Class: {
479 ( class_depth > 0 ) &
480 ( v.value.first.get_raw_state( ).has_more( ) and
481 v.value.first.get_raw_state( ).front( ) == '}' ),
482 ErrorReason::InvalidEndOfValue );
483 --class_depth;
484 auto result = json_details::handle_on_class_end( handler );
485 switch( result.value ) {
486 case json_parse_handler_result::Complete:
487 parent_stack.clear( );
488 return;
489 case json_parse_handler_result::SkipClassArray:
490 case json_parse_handler_result::Continue:
491 break;
492 }
493 } break;
494 case StackParseStateType::Array: {
496 ( array_depth > 0 ) &
497 ( v.value.first.get_raw_state( ).has_more( ) and
498 v.value.first.get_raw_state( ).front( ) == ']' ),
499 ErrorReason::InvalidEndOfValue );
500 --array_depth;
501 auto result = json_details::handle_on_array_end( handler );
502 switch( result.value ) {
503 case json_parse_handler_result::Complete:
504 parent_stack.clear( );
505 return;
506 case json_parse_handler_result::SkipClassArray:
507 case json_parse_handler_result::Continue:
508 break;
509 }
510 } break;
511 }
512 }
513 };
514
515 process_value( json_value_t{ std::nullopt, std::move( jvalue ) } );
516
517 while( not parent_stack.empty( ) ) {
518 auto v = std::move( parent_stack.back( ) );
519 parent_stack.pop_back( );
520 process_range( v );
521 }
522 daw_json_ensure( class_depth == 0 and array_depth == 0,
523 ErrorReason::InvalidEndOfValue );
524 }
525
526 template<typename StackContainerPolicy = use_default, json_options_t P,
527 typename A, typename Handler>
528 DAW_ATTRIB_INLINE constexpr void
529 json_event_parser( basic_json_value<P, A> bjv, Handler &&handler ) {
530 json_event_parser<StackContainerPolicy>(
531 std::move( bjv ), DAW_FWD( handler ), options::parse_flags<> );
532 }
533
534 template<typename StackContainerPolicy = use_default, typename Handler,
535 auto... ParseFlags>
536 DAW_ATTRIB_INLINE void
537 json_event_parser( daw::string_view json_document, Handler &&handler,
538 options::parse_flags_t<ParseFlags...> pflags ) {
539
540 return json_event_parser<StackContainerPolicy>(
541 basic_json_value( json_document ), DAW_FWD( handler ), pflags );
542 }
543
544 template<typename StackContainerPolicy = use_default, typename Handler>
545 DAW_ATTRIB_INLINE void json_event_parser( daw::string_view json_document,
546 Handler &&handler ) {
547
548 return json_event_parser<StackContainerPolicy>(
549 basic_json_value( json_document ),
550 DAW_FWD( handler ),
551 options::parse_flags<> );
552 }
553
554 } // namespace DAW_JSON_VER
555} // namespace daw::json
#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.
#define daw_json_ensure(Bool,...)
Ensure that Bool is true. If false pass rest of args to daw_json_error.
#define DAW_JSON_MAKE_REQ_TRAIT(Name,...)
#define DAW_JSON_MAKE_REQ_TRAIT2(Name,...)
#define CPP20CONSTEXPR
constexpr void json_event_parser(basic_json_value< P, A > bjv, Handler &&handler, options::parse_flags_t< ParseFlags... >)
@ Continue
Continue parsing with next element/member.
@ Complete
We are completed and do not wish to see any more.
daw::conditional_t< ParsePolicy::is_default_parse_policy, DefaultParsePolicy, ParsePolicy > TryDefaultParsePolicy
Customization point traits.
Iterator for iterating over arbitrary JSON members and array elements.
A non-owning container for arbitrary JSON values that allows movement/iteration through.
#define DAW_JSON_VER
The version string used in namespace definitions. Must be a valid namespace name.
Definition version.h:20