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#include <daw/daw_utility.h>
21
22#include <cstddef>
23#include <daw/stdinc/declval.h>
24#include <daw/stdinc/move_fwd_exch.h>
25#include <optional>
26#include <utility>
27#include <vector>
28
29namespace daw::json {
30 inline namespace DAW_JSON_VER {
39
40 namespace json_details {
41 struct handler_result_holder {
42 json_parse_handler_result value = json_parse_handler_result::Continue;
43
44 handler_result_holder( ) = default;
45
46 constexpr handler_result_holder( bool b )
47 : value( b ? Continue : Complete ) {}
48
49 constexpr handler_result_holder( json_parse_handler_result r )
50 : value( r ) {}
51
52 constexpr explicit operator bool( ) const {
53 return value == json_parse_handler_result::Continue;
54 }
55 };
56
57 namespace hnd_checks {
58 // On Next Value
60 has_on_value_handler_impl,
61 std::declval<T>( ).handle_on_value( std::declval<U>( ) ) );
62
63 template<typename Handler, json_options_t P, typename A>
64 DAW_CPP20_CONCEPT has_on_value_handler_v =
65 has_on_value_handler_impl<Handler, basic_json_pair<P, A>>;
66
67 // On Array Start
69 has_on_array_start_handler_impl,
70 std::declval<T>( ).handle_on_array_start( std::declval<U>( ) ) );
71
72 template<typename Handler, json_options_t P, typename A>
73 DAW_CPP20_CONCEPT has_on_array_start_handler_v =
74 has_on_array_start_handler_impl<Handler, basic_json_value<P, A>>;
75
76 // On Array End
77 DAW_JSON_MAKE_REQ_TRAIT( has_on_array_end_handler_v,
78 std::declval<T>( ).handle_on_array_end( ) );
79
80 // On Class Start
82 has_on_class_start_handler_impl,
83 std::declval<T>( ).handle_on_class_start( std::declval<U>( ) ) );
84
85 template<typename Handler, json_options_t P, typename A>
86 DAW_CPP20_CONCEPT has_on_class_start_handler_v =
87 has_on_class_start_handler_impl<Handler, basic_json_value<P, A>>;
88
89 // On Class End
90 DAW_JSON_MAKE_REQ_TRAIT( has_on_class_end_handler_v,
91 std::declval<T>( ).handle_on_class_end( ) );
92
93 // On Number
95 has_on_number_handler_jv_impl,
96 std::declval<T>( ).handle_on_number( std::declval<U>( ) ) );
97
98 template<typename Handler, json_options_t P, typename A>
99 DAW_CPP20_CONCEPT has_on_number_handler_jv_v =
100 has_on_number_handler_jv_impl<Handler, basic_json_value<P, A>>;
101
102 DAW_JSON_MAKE_REQ_TRAIT( has_on_number_handler_dbl_v,
103 std::declval<T>( ).handle_on_number( 0.0 ) );
104
105 // On Bool // T = Handler, U = JValue
107 has_on_bool_handler_jv_impl,
108 std::declval<T>( ).handle_on_bool( std::declval<U>( ) ) );
109
110 template<typename Handler, json_options_t P, typename A>
111 DAW_CPP20_CONCEPT has_on_bool_handler_jv_v =
112 has_on_bool_handler_jv_impl<Handler, basic_json_value<P, A>>;
113
114 DAW_JSON_MAKE_REQ_TRAIT( has_on_bool_handler_bl_v,
115 std::declval<T>( ).handle_on_bool( true ) );
116
117 // On String // T = Handler, U = JValue
119 has_on_string_handler_impl,
120 std::declval<T>( ).handle_on_string( std::declval<U>( ) ) );
121
122 template<typename Handler, json_options_t P, typename A>
123 DAW_CPP20_CONCEPT has_on_string_handler_jv_v =
124 has_on_string_handler_impl<Handler, basic_json_value<P, A>>;
125
127 has_on_string_handler_str_v,
128 std::declval<T>( ).handle_on_string( std::declval<std::string>( ) ) );
129
130 // On Null, T = Handler, U = JValue
132 has_on_null_handler_impl,
133 std::declval<T>( ).handle_on_null( std::declval<U>( ) ) );
134
135 template<typename Handler, json_options_t P, typename A>
136 DAW_CPP20_CONCEPT has_on_null_handler_jv_v =
137 has_on_null_handler_impl<Handler, basic_json_value<P, A>>;
138
139 DAW_JSON_MAKE_REQ_TRAIT( has_on_null_handler_v,
140 std::declval<T>( ).handle_on_null( ) );
141
142 // On Error
144 has_on_error_handler_impl,
145 std::declval<T>( ).handle_on_error( std::declval<U>( ) ) );
146
147 template<typename Handler, json_options_t P, typename A>
148 DAW_CPP20_CONCEPT has_on_error_handler_v =
149 has_on_error_handler_impl<Handler, basic_json_value<P, A>>;
150 } // namespace hnd_checks
151
152 template<typename T>
153 constexpr daw::remove_cvref_t<T> as_copy( T &&value ) {
154 return value;
155 }
156
157 template<typename Handler, json_options_t P, typename A>
158 constexpr handler_result_holder
159 handle_on_value( Handler &&handler, basic_json_pair<P, A> p ) {
160 if constexpr( hnd_checks::has_on_value_handler_v<Handler, P, A> ) {
161 return handler.handle_on_value( std::move( p ) );
162 } else {
163 (void)p;
164 return handler_result_holder{ };
165 }
166 }
167
168 template<typename Handler, json_options_t P, typename A>
169 constexpr handler_result_holder
170 handle_on_array_start( Handler &&handler, basic_json_value<P, A> jv ) {
171 if constexpr( hnd_checks::
172 has_on_array_start_handler_v<Handler, P, A> ) {
173 return handler.handle_on_array_start( std::move( jv ) );
174 } else {
175 (void)jv;
176 return handler_result_holder{ };
177 }
178 }
179
180 template<typename Handler>
181 constexpr handler_result_holder handle_on_array_end( Handler &&handler ) {
182 if constexpr( hnd_checks::has_on_array_end_handler_v<Handler> ) {
183 return handler.handle_on_array_end( );
184 } else {
185 return handler_result_holder{ };
186 }
187 }
188
189 template<typename Handler, json_options_t P, typename A>
190 constexpr handler_result_holder
191 handle_on_class_start( Handler &&handler, basic_json_value<P, A> jv ) {
192 if constexpr( hnd_checks::
193 has_on_class_start_handler_v<Handler, P, A> ) {
194 return handler.handle_on_class_start( std::move( jv ) );
195 } else {
196 (void)jv;
197 return handler_result_holder{ };
198 }
199 }
200
201 template<typename Handler>
202 constexpr handler_result_holder handle_on_class_end( Handler &&handler ) {
203 if constexpr( hnd_checks::has_on_class_end_handler_v<Handler> ) {
204 return handler.handle_on_class_end( );
205 } else {
206 return handler_result_holder{ };
207 }
208 }
209
210 template<typename Handler, json_options_t P, typename A>
211 constexpr handler_result_holder
212 handle_on_number( Handler &&handler, basic_json_value<P, A> &jv ) {
213 if constexpr( hnd_checks::has_on_number_handler_jv_v<Handler, P, A> ) {
214 return handler.handle_on_number( as_copy( jv ) );
215 } else if constexpr( hnd_checks::has_on_number_handler_dbl_v<
216 Handler> ) {
217 return handler.handle_on_number( from_json<double>( jv ) );
218 } else {
219 (void)jv;
220 return handler_result_holder{ };
221 }
222 }
223
224 template<typename Handler, json_options_t P, typename A>
225 constexpr handler_result_holder
226 handle_on_bool( Handler &&handler, basic_json_value<P, A> jv ) {
227 if constexpr( hnd_checks::has_on_bool_handler_jv_v<Handler, P, A> ) {
228 return handler.handle_on_bool( as_copy( jv ) );
229 } else if constexpr( hnd_checks::has_on_bool_handler_bl_v<Handler> ) {
230 return handler.handle_on_bool( from_json<bool>( jv ) );
231 } else {
232 (void)jv;
233 return handler_result_holder{ };
234 }
235 }
236
237 template<typename Handler, json_options_t P, typename A>
238 constexpr handler_result_holder
239 handle_on_string( Handler &&handler, basic_json_value<P, A> &jv ) {
240 if constexpr( hnd_checks::has_on_string_handler_jv_v<Handler, P, A> ) {
241 return handler.handle_on_string( as_copy( jv ) );
242 } else if constexpr( hnd_checks::has_on_string_handler_str_v<
243 Handler> ) {
244 return handler.handle_on_string( jv.get_string( ) );
245 } else {
246 (void)jv;
247 return handler_result_holder{ };
248 }
249 }
250
251 template<typename Handler, json_options_t P, typename A>
252 constexpr handler_result_holder
253 handle_on_null( Handler &&handler, basic_json_value<P, A> &jv ) {
254 if constexpr( hnd_checks::has_on_null_handler_jv_v<Handler, P, A> ) {
255 return handler.handle_on_null( as_copy( jv ) );
256 } else if constexpr( hnd_checks::has_on_null_handler_v<Handler> ) {
257 return handler.handle_on_null( );
258 } else {
259 return handler_result_holder{ };
260 }
261 }
262
263 template<typename Handler, json_options_t P, typename A>
264 constexpr handler_result_holder
265 handle_on_error( Handler &&handler, basic_json_value<P, A> jv ) {
266 if constexpr( hnd_checks::has_on_error_handler_v<Handler, P, A> ) {
267 return handler.handle_on_error( std::move( jv ) );
268 } else {
269 (void)jv;
270 return handler_result_holder{ };
271 }
272 }
273
274 } // namespace json_details
275
276 enum class StackParseStateType { Class, Array };
277
278 template<json_options_t P, typename A>
284
285 template<typename StackValue, typename StackType = std::vector<StackValue>>
287 using stack_t = StackType;
288 stack_t m_stack{ };
289
290 public:
291 using value_type = StackValue;
292 using reference = StackValue &;
293 using size_type = std::size_t;
294 using difference_type = std::ptrdiff_t;
295
297
299 m_stack.push_back( std::move( v ) );
300 }
301
302 [[nodiscard]] CPP20CONSTEXPR reference back( ) {
303 return m_stack.back( );
304 }
305
307 m_stack.clear( );
308 }
309
311 m_stack.pop_back( );
312 }
313
314 [[nodiscard]] CPP20CONSTEXPR bool empty( ) const {
315 return m_stack.empty( );
316 }
317 };
318
319 template<typename StackContainerPolicy = use_default,
320 std::size_t MaxDepth = daw::max_value<std::size_t>,
321 json_options_t P, typename A, typename Handler,
322 auto... ParseFlags>
324 Handler &&handler,
325 options::parse_flags_t<ParseFlags...> ) {
326
327 using ParseState =
329 template SetPolicyOptions<ParseFlags...>>;
330
331 using iterator =
332 basic_json_value_iterator<ParseState::policy_flags( ), A>;
333 using json_value_t = typename iterator::json_pair;
334 using stack_value_t =
335 JsonEventParserStackValue<ParseState::policy_flags( ), A>;
336 auto jvalue = basic_json_value( bjv );
337
338 auto parent_stack = [] DAW_CPP23_STATIC_CALL_OP {
339 if constexpr( std::is_same_v<StackContainerPolicy, use_default> ) {
341 } else {
342 return StackContainerPolicy{ };
343 }
344 }( );
345 long long class_depth = 0;
346 long long array_depth = 0;
347
348 // Complete means the caller deliberately stopped early, possibly from
349 // inside a nested array/class; the class_depth/array_depth invariant
350 // checked below no longer applies in that case.
351 bool user_completed = false;
352 auto const complete_now = [&]( ) {
353 parent_stack.clear( );
354 user_completed = true;
355 };
356
357 // Skip remaining elements/members of the current class/array without
358 // firing further value events, by walking (not jumping to end( ), which
359 // is a sentinel with no real position) until the raw cursor lands on
360 // the container's closing bracket. This is what lets the subsequent
361 // "container exhausted" check and the matching end event fire
362 // correctly, same as reaching the end normally would.
363 auto const move_to_last = [&]( ) {
364 auto &top = parent_stack.back( );
365 while( top.value.first ) {
366 ++top.value.first;
367 }
368 };
369
370 auto const process_value = [&]( json_value_t p ) {
371 {
372 auto result = json_details::handle_on_value( handler, p );
373 switch( result.value ) {
374 case json_parse_handler_result::Complete:
375 complete_now( );
376 return;
377 case json_parse_handler_result::SkipClassArray:
378 move_to_last( );
379 return;
380 case json_parse_handler_result::Continue:
381 break;
382 }
383 }
384
385 auto &jv = p.value;
386 switch( jv.type( ) ) {
387 case JsonBaseParseTypes::Array: {
388 ++array_depth;
389 auto result = json_details::handle_on_array_start( handler, jv );
390 switch( result.value ) {
391 case json_parse_handler_result::Complete:
392 complete_now( );
393 return;
394 case json_parse_handler_result::SkipClassArray:
395 move_to_last( );
396 return;
397 case json_parse_handler_result::Continue:
398 break;
399 }
401 static_cast<std::size_t>( class_depth + array_depth ) <=
402 MaxDepth,
403 ErrorReason::MaxDepthExceeded );
404 parent_stack.push_back(
405 { StackParseStateType::Array,
406 std::pair<iterator, iterator>( jv.begin( ), jv.end( ) ) } );
407 } break;
408 case JsonBaseParseTypes::Class: {
409 ++class_depth;
410 auto result = json_details::handle_on_class_start( handler, jv );
411 switch( result.value ) {
412 case json_parse_handler_result::Complete:
413 complete_now( );
414 return;
415 case json_parse_handler_result::SkipClassArray:
416 move_to_last( );
417 return;
418 case json_parse_handler_result::Continue:
419 break;
420 }
422 static_cast<std::size_t>( class_depth + array_depth ) <=
423 MaxDepth,
424 ErrorReason::MaxDepthExceeded );
425 parent_stack.push_back(
426 { StackParseStateType::Class,
427 std::pair<iterator, iterator>( jv.begin( ), jv.end( ) ) } );
428 } break;
429 case JsonBaseParseTypes::Number: {
430 auto result = json_details::handle_on_number( handler, jv );
431 switch( result.value ) {
432 case json_parse_handler_result::Complete:
433 complete_now( );
434 return;
435 case json_parse_handler_result::SkipClassArray:
436 move_to_last( );
437 return;
438 case json_parse_handler_result::Continue:
439 break;
440 }
441 } break;
442 case JsonBaseParseTypes::Bool: {
443 auto result = json_details::handle_on_bool( handler, jv );
444 switch( result.value ) {
445 case json_parse_handler_result::Complete:
446 complete_now( );
447 return;
448 case json_parse_handler_result::SkipClassArray:
449 move_to_last( );
450 return;
451 case json_parse_handler_result::Continue:
452 break;
453 }
454 } break;
455 case JsonBaseParseTypes::String: {
456 auto result = json_details::handle_on_string( handler, jv );
457 switch( result.value ) {
458 case json_parse_handler_result::Complete:
459 complete_now( );
460 return;
461 case json_parse_handler_result::SkipClassArray:
462 move_to_last( );
463 return;
464 case json_parse_handler_result::Continue:
465 break;
466 }
467 } break;
468 case JsonBaseParseTypes::Null: {
469 auto result = json_details::handle_on_null( handler, jv );
470 switch( result.value ) {
471 case json_parse_handler_result::Complete:
472 complete_now( );
473 return;
474 case json_parse_handler_result::SkipClassArray:
475 move_to_last( );
476 return;
477 case json_parse_handler_result::Continue:
478 break;
479 }
480 } break;
481 case JsonBaseParseTypes::None:
482 default: {
483 auto result = json_details::handle_on_error( handler, jv );
484 switch( result.value ) {
485 case json_parse_handler_result::Complete:
486 complete_now( );
487 return;
488 case json_parse_handler_result::SkipClassArray:
489 move_to_last( );
490 return;
491 case json_parse_handler_result::Continue:
492 break;
493 }
494 } break;
495 }
496 };
497
498 auto const process_range = [&]( stack_value_t v ) {
499 if( v.value.first != v.value.second ) {
500 auto jv = *v.value.first;
501 ++v.value.first;
502 parent_stack.push_back( std::move( v ) );
503 process_value( std::move( jv ) );
504 } else {
505 switch( v.type ) {
506 case StackParseStateType::Class: {
508 ( class_depth > 0 ) &
509 ( v.value.first.get_raw_state( ).has_more( ) and
510 v.value.first.get_raw_state( ).front( ) == '}' ),
511 ErrorReason::InvalidEndOfValue );
512 --class_depth;
513 auto result = json_details::handle_on_class_end( handler );
514 switch( result.value ) {
515 case json_parse_handler_result::Complete:
516 complete_now( );
517 return;
518 case json_parse_handler_result::SkipClassArray:
519 case json_parse_handler_result::Continue:
520 break;
521 }
522 } break;
523 case StackParseStateType::Array: {
525 ( array_depth > 0 ) &
526 ( v.value.first.get_raw_state( ).has_more( ) and
527 v.value.first.get_raw_state( ).front( ) == ']' ),
528 ErrorReason::InvalidEndOfValue );
529 --array_depth;
530 auto result = json_details::handle_on_array_end( handler );
531 switch( result.value ) {
532 case json_parse_handler_result::Complete:
533 complete_now( );
534 return;
535 case json_parse_handler_result::SkipClassArray:
536 case json_parse_handler_result::Continue:
537 break;
538 }
539 } break;
540 }
541 }
542 };
543
544 process_value( json_value_t{ std::nullopt, std::move( jvalue ) } );
545
546 while( not parent_stack.empty( ) ) {
547 auto v = std::move( parent_stack.back( ) );
548 parent_stack.pop_back( );
549 process_range( v );
550 }
551 daw_json_ensure( user_completed or
552 ( class_depth == 0 and array_depth == 0 ),
553 ErrorReason::InvalidEndOfValue );
554 }
555
556 template<typename StackContainerPolicy = use_default,
557 std::size_t MaxDepth = daw::max_value<std::size_t>,
558 json_options_t P, typename A, typename Handler>
559 DAW_ATTRIB_INLINE constexpr void
560 json_event_parser( basic_json_value<P, A> bjv, Handler &&handler ) {
561 json_event_parser<StackContainerPolicy, MaxDepth>(
562 std::move( bjv ), DAW_FWD( handler ), options::parse_flags<> );
563 }
564
565 template<typename StackContainerPolicy = use_default,
566 std::size_t MaxDepth = daw::max_value<std::size_t>,
567 typename Handler, auto... ParseFlags>
568 DAW_ATTRIB_INLINE void
569 json_event_parser( daw::string_view json_document, Handler &&handler,
570 options::parse_flags_t<ParseFlags...> pflags ) {
571
572 return json_event_parser<StackContainerPolicy, MaxDepth>(
573 basic_json_value( json_document ), DAW_FWD( handler ), pflags );
574 }
575
576 template<typename StackContainerPolicy = use_default,
577 std::size_t MaxDepth = daw::max_value<std::size_t>,
578 typename Handler>
579 DAW_ATTRIB_INLINE void json_event_parser( daw::string_view json_document,
580 Handler &&handler ) {
581
582 return json_event_parser<StackContainerPolicy, MaxDepth>(
583 basic_json_value( json_document ),
584 DAW_FWD( handler ),
585 options::parse_flags<> );
586 }
587
588 } // namespace DAW_JSON_VER
589} // 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
@ Continue
Continue parsing with next element/member.
@ Complete
We are completed and do not wish to see any more.
constexpr void json_event_parser(basic_json_value< P, A > bjv, Handler &&handler, options::parse_flags_t< ParseFlags... >)
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