DAW JSON Link
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 
27 namespace daw::json {
28  inline namespace DAW_JSON_VER {
35  Complete
36  };
37 
38  namespace json_details {
39  struct handler_result_holder {
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 {
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>
280  std::pair<iterator, iterator> value;
281  };
282 
283  template<typename StackValue>
285  std::vector<StackValue> m_stack{ };
286 
287  public:
288  using value_type = StackValue;
289  using reference = StackValue &;
290  using size_type = std::size_t;
291  using difference_type = std::ptrdiff_t;
292 
294 
296  m_stack.push_back( std::move( v ) );
297  }
298 
299  [[nodiscard]] CPP20CONSTEXPR reference back( ) {
300  return m_stack.back( );
301  }
302 
304  m_stack.clear( );
305  }
306 
308  m_stack.pop_back( );
309  }
310 
311  [[nodiscard]] CPP20CONSTEXPR bool empty( ) const {
312  return m_stack.empty( );
313  }
314  };
315 
316  template<json_options_t P, typename A,
317  typename StackContainerPolicy = use_default, typename Handler,
318  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 ) {
352  parent_stack.clear( );
353  return;
355  move_to_last( );
356  return;
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 ) {
369  parent_stack.clear( );
370  return;
372  move_to_last( );
373  return;
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 ) {
386  parent_stack.clear( );
387  return;
389  move_to_last( );
390  return;
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 ) {
402  parent_stack.clear( );
403  return;
405  move_to_last( );
406  return;
408  break;
409  }
410  } break;
411  case JsonBaseParseTypes::Bool: {
412  auto result = json_details::handle_on_bool( handler, jv );
413  switch( result.value ) {
415  parent_stack.clear( );
416  return;
418  move_to_last( );
419  return;
421  break;
422  }
423  } break;
424  case JsonBaseParseTypes::String: {
425  auto result = json_details::handle_on_string( handler, jv );
426  switch( result.value ) {
428  parent_stack.clear( );
429  return;
431  move_to_last( );
432  return;
434  break;
435  }
436  } break;
437  case JsonBaseParseTypes::Null: {
438  auto result = json_details::handle_on_null( handler, jv );
439  switch( result.value ) {
441  parent_stack.clear( );
442  return;
444  move_to_last( );
445  return;
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 ) {
455  parent_stack.clear( );
456  return;
458  move_to_last( );
459  return;
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 ) {
485  parent_stack.clear( );
486  return;
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 ) {
502  parent_stack.clear( );
503  return;
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<json_options_t P, typename A,
525  typename StackContainerPolicy = use_default, typename Handler>
526  DAW_ATTRIB_INLINE constexpr void
527  json_event_parser( basic_json_value<P, A> bjv, Handler &&handler ) {
528  json_event_parser( std::move( bjv ), DAW_FWD( handler ),
529  options::parse_flags<> );
530  }
531 
532  template<typename Handler, auto... ParseFlags>
533  DAW_ATTRIB_INLINE void
534  json_event_parser( daw::string_view json_document, Handler &&handler,
535  options::parse_flags_t<ParseFlags...> pflags ) {
536 
537  return json_event_parser( basic_json_value( json_document ),
538  DAW_FWD2( Handler, handler ), pflags );
539  }
540 
541  template<typename Handler>
542  DAW_ATTRIB_INLINE void json_event_parser( daw::string_view json_document,
543  Handler &&handler ) {
544 
545  return json_event_parser( basic_json_value( json_document ),
546  DAW_FWD2( Handler, handler ),
547  options::parse_flags<> );
548  }
549 
550  } // namespace DAW_JSON_VER
551 } // 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... >)
@ SkipClassArray
Skip the rest of this class or array.
@ 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
basic_json_value(BasicParsePolicy< PolicyFlags, Allocator >) -> basic_json_value< PolicyFlags, Allocator >
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:25