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