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 "daw/json/daw_json_link.h"
12 
13 #include <ciso646>
14 #include <string>
15 #include <utility>
16 
17 namespace daw::json {
19  namespace json_details {
20  struct handler_result_holder {
22 
23  constexpr handler_result_holder( ) = default;
24 
25  constexpr handler_result_holder( bool b )
26  : value( b ? Continue : Complete ) {}
27 
28  constexpr handler_result_holder( json_parse_handler_result r )
29  : value( r ) {}
30 
31  constexpr explicit operator bool( ) const {
33  }
34  };
35 
36  namespace hnd_checks {
37  // On Next Value
38  template<typename Handler, typename Range>
39  using has_on_value_handler_detect =
40  decltype( std::declval<Handler>( ).handle_on_value(
41  std::declval<daw::json::basic_json_pair<Range>>( ) ) );
42 
43  template<typename Handler, typename Range>
44  inline constexpr bool has_on_value_handler_v =
45  daw::is_detected_v<has_on_value_handler_detect, Handler, Range>;
46 
47  // On Array Start
48  template<typename Handler, typename Range>
49  using has_on_array_start_handler_detect =
50  decltype( std::declval<Handler>( ).handle_on_array_start(
51  std::declval<daw::json::basic_json_value<Range>>( ) ) );
52 
53  template<typename Handler, typename Range>
54  inline constexpr bool has_on_array_start_handler_v =
55  daw::is_detected_v<has_on_array_start_handler_detect, Handler, Range>;
56 
57  // On Array End
58  template<typename Handler>
59  using has_on_array_end_handler_detect =
60  decltype( std::declval<Handler>( ).handle_on_array_end( ) );
61 
62  template<typename Handler>
63  inline constexpr bool has_on_array_end_handler_v =
64  daw::is_detected_v<has_on_array_end_handler_detect, Handler>;
65 
66  // On Class Start
67  template<typename Handler, typename Range>
68  using has_on_class_start_handler_detect =
69  decltype( std::declval<Handler>( ).handle_on_class_start(
70  std::declval<daw::json::basic_json_value<Range>>( ) ) );
71 
72  template<typename Handler, typename Range>
73  inline constexpr bool has_on_class_start_handler_v =
74  daw::is_detected_v<has_on_class_start_handler_detect, Handler, Range>;
75 
76  // On Class End
77  template<typename Handler>
78  using has_on_class_end_handler_detect =
79  decltype( std::declval<Handler>( ).handle_on_class_end( ) );
80 
81  template<typename Handler>
82  inline constexpr bool has_on_class_end_handler_v =
83  daw::is_detected_v<has_on_class_end_handler_detect, Handler>;
84 
85  // On Number
86  template<typename Handler, typename Range>
87  using has_on_number_handler_detect_jv =
88  decltype( std::declval<Handler>( ).handle_on_number(
89  std::declval<daw::json::basic_json_value<Range>>( ) ) );
90 
91  template<typename Handler, typename Range>
92  inline constexpr bool has_on_number_handler_jv_v =
93  daw::is_detected_v<has_on_number_handler_detect_jv, Handler, Range>;
94 
95  template<typename Handler>
96  using has_on_number_handler_detect_dbl =
97  decltype( std::declval<Handler>( ).handle_on_number( 0.0 ) );
98 
99  template<typename Handler>
100  inline constexpr bool has_on_number_handler_dbl_v =
101  daw::is_detected_v<has_on_number_handler_detect_dbl, Handler>;
102 
103  // On Bool
104  template<typename Handler, typename Range>
105  using has_on_bool_handler_detect_jv =
106  decltype( std::declval<Handler>( ).handle_on_bool(
107  std::declval<daw::json::basic_json_value<Range>>( ) ) );
108 
109  template<typename Handler, typename Range>
110  inline constexpr bool has_on_bool_handler_jv_v =
111  daw::is_detected_v<has_on_bool_handler_detect_jv, Handler, Range>;
112 
113  template<typename Handler>
114  using has_on_bool_handler_detect_bl =
115  decltype( std::declval<Handler>( ).handle_on_bool( true ) );
116 
117  template<typename Handler>
118  inline constexpr bool has_on_bool_handler_bl_v =
119  daw::is_detected_v<has_on_bool_handler_detect_bl, Handler>;
120 
121  // On String
122  template<typename Handler, typename Range>
123  using has_on_string_handler_detect_jv =
124  decltype( std::declval<Handler>( ).handle_on_string(
125  std::declval<daw::json::basic_json_value<Range>>( ) ) );
126 
127  template<typename Handler, typename Range>
128  inline constexpr bool has_on_string_handler_jv_v =
129  daw::is_detected_v<has_on_string_handler_detect_jv, Handler, Range>;
130 
131  template<typename Handler>
132  using has_on_string_handler_detect_str =
133  decltype( std::declval<Handler>( ).handle_on_string(
134  std::declval<std::string>( ) ) );
135 
136  template<typename Handler>
137  inline constexpr bool has_on_string_handler_str_v =
138  daw::is_detected_v<has_on_string_handler_detect_str, Handler>;
139 
140  // On Null
141  template<typename Handler, typename Range>
142  using has_on_null_handler_detect_jv =
143  decltype( std::declval<Handler>( ).handle_on_null(
144  std::declval<daw::json::basic_json_value<Range>>( ) ) );
145 
146  template<typename Handler, typename Range>
147  inline constexpr bool has_on_null_handler_jv_v =
148  daw::is_detected_v<has_on_null_handler_detect_jv, Handler, Range>;
149 
150  template<typename Handler>
151  using has_on_null_handler_detect =
152  decltype( std::declval<Handler>( ).handle_on_null( ) );
153 
154  template<typename Handler>
155  inline constexpr bool has_on_null_handler_v =
156  daw::is_detected_v<has_on_null_handler_detect, Handler>;
157 
158  // On Error
159  template<typename Handler, typename Range>
160  using has_on_error_handler_detect =
161  decltype( std::declval<Handler>( ).handle_on_error(
162  std::declval<daw::json::basic_json_value<Range>>( ) ) );
163 
164  template<typename Handler, typename Range>
165  inline constexpr bool has_on_error_handler_v =
166  daw::is_detected_v<has_on_error_handler_detect, Handler, Range>;
167  } // namespace hnd_checks
168 
169  template<typename T>
170  constexpr daw::remove_cvref_t<T> as_copy( T &&value ) {
171  return value;
172  }
173 
174  template<typename Handler, typename ParsePolicy>
175  inline constexpr handler_result_holder
176  handle_on_value( Handler &&handler,
178  if constexpr( hnd_checks::has_on_value_handler_v<Handler, ParsePolicy> ) {
179  return handler.handle_on_value( std::move( p ) );
180  } else {
181  (void)p;
182  return handler_result_holder{ };
183  }
184  }
185 
186  template<typename Handler, typename Range>
187  inline constexpr handler_result_holder
188  handle_on_array_start( Handler &&handler,
190  if constexpr( hnd_checks::has_on_array_start_handler_v<Handler, Range> ) {
191  return handler.handle_on_array_start( std::move( jv ) );
192  } else {
193  (void)jv;
194  return handler_result_holder{ };
195  }
196  }
197 
198  template<typename Handler>
199  inline constexpr handler_result_holder
200  handle_on_array_end( Handler &&handler ) {
201  if constexpr( hnd_checks::has_on_array_end_handler_v<Handler> ) {
202  return handler.handle_on_array_end( );
203  } else {
204  return handler_result_holder{ };
205  }
206  }
207 
208  template<typename Handler, typename Range>
209  inline constexpr handler_result_holder
210  handle_on_class_start( Handler &&handler,
212  if constexpr( hnd_checks::has_on_class_start_handler_v<Handler, Range> ) {
213  return handler.handle_on_class_start( std::move( jv ) );
214  } else {
215  (void)jv;
216  return handler_result_holder{ };
217  }
218  }
219 
220  template<typename Handler>
221  inline constexpr handler_result_holder
222  handle_on_class_end( Handler &&handler ) {
223  if constexpr( hnd_checks::has_on_class_end_handler_v<Handler> ) {
224  return handler.handle_on_class_end( );
225  } else {
226  return handler_result_holder{ };
227  }
228  }
229 
230  template<typename Handler, typename Range>
231  inline constexpr handler_result_holder
232  handle_on_number( Handler &&handler,
234  if constexpr( hnd_checks::has_on_number_handler_jv_v<Handler, Range> ) {
235  return handler.handle_on_number( as_copy( jv ) );
236  } else if constexpr( hnd_checks::has_on_number_handler_dbl_v<Handler> ) {
237  return handler.handle_on_number( from_json<double>( jv ) );
238  } else {
239  (void)jv;
240  return handler_result_holder{ };
241  }
242  }
243 
244  template<typename Handler, typename Range>
245  inline constexpr handler_result_holder
246  handle_on_bool( Handler &&handler, daw::json::basic_json_value<Range> jv ) {
247  if constexpr( hnd_checks::has_on_bool_handler_jv_v<Handler, Range> ) {
248  return handler.handle_on_bool( as_copy( jv ) );
249  } else if constexpr( hnd_checks::has_on_bool_handler_bl_v<Handler> ) {
250  return handler.handle_on_bool( from_json<bool>( jv ) );
251  } else {
252  (void)jv;
253  return handler_result_holder{ };
254  }
255  }
256 
257  template<typename Handler, typename Range>
258  inline constexpr handler_result_holder
259  handle_on_string( Handler &&handler,
261  if constexpr( hnd_checks::has_on_string_handler_jv_v<Handler, Range> ) {
262  return handler.handle_on_string( as_copy( jv ) );
263  } else if constexpr( hnd_checks::has_on_string_handler_str_v<Handler> ) {
264  return handler.handle_on_string( jv.get_string( ) );
265  } else {
266  (void)jv;
267  return handler_result_holder{ };
268  }
269  }
270 
271  template<typename Handler, typename Range>
272  inline constexpr handler_result_holder
273  handle_on_null( Handler &&handler,
275  if constexpr( hnd_checks::has_on_null_handler_jv_v<Handler, Range> ) {
276  return handler.handle_on_null( as_copy( jv ) );
277  } else if constexpr( hnd_checks::has_on_null_handler_v<Handler> ) {
278  return handler.handle_on_null( );
279  } else {
280  return handler_result_holder{ };
281  }
282  }
283 
284  template<typename Handler, typename Range>
285  inline constexpr handler_result_holder
286  handle_on_error( Handler &&handler,
288  if constexpr( hnd_checks::has_on_error_handler_v<Handler, Range> ) {
289  return handler.handle_on_error( std::move( jv ) );
290  } else {
291  (void)jv;
292  return handler_result_holder{ };
293  }
294  }
295 
296  } // namespace json_details
297  enum class StackRangeType { Class, Array };
298 
299  template<typename ParsePolicy>
303  std::pair<iterator, iterator> value;
304  };
305 
306  template<typename StackValue>
308  std::vector<StackValue> m_stack{ };
309 
310  public:
311  using value_type = StackValue;
312  using reference = StackValue &;
313  using size_type = std::size_t;
314  using difference_type = std::ptrdiff_t;
315 
317 
318  CPP20CONSTEXPR inline void push_back( value_type &&v ) {
319  m_stack.push_back( std::move( v ) );
320  }
321 
323  return m_stack.back( );
324  }
325 
326  CPP20CONSTEXPR inline void clear( ) {
327  m_stack.clear( );
328  }
329 
330  CPP20CONSTEXPR inline void pop_back( ) {
331  m_stack.pop_back( );
332  }
333 
334  CPP20CONSTEXPR inline bool empty( ) const {
335  return m_stack.empty( );
336  }
337  };
338 
339  template<typename ParsePolicy = NoCommentSkippingPolicyChecked,
340  typename StackContainerPolicy = DefaultJsonEventParserStackPolicy<
341  JsonEventParserStackValue<ParsePolicy>>,
342  typename Handler>
343  inline constexpr void
345  Handler &&handler ) {
347  using json_value_t = daw::json::basic_json_pair<ParsePolicy>;
348  using stack_value_t = JsonEventParserStackValue<ParsePolicy>;
349 
350  auto parent_stack = StackContainerPolicy( );
351 
352  auto const move_to_last = [&]( ) {
353  parent_stack.back( ).value.first = parent_stack.back( ).value.second;
354  };
355 
356  auto const process_value = [&]( json_value_t p ) {
357  {
358  auto result = json_details::handle_on_value( handler, p );
359  switch( result.value ) {
361  parent_stack.clear( );
362  return;
364  move_to_last( );
365  return;
367  break;
368  }
369  }
370 
371  auto &jv = p.value;
372  switch( jv.type( ) ) {
373  case daw::json::JsonBaseParseTypes::Array: {
374  auto result = json_details::handle_on_array_start( handler, jv );
375  switch( result.value ) {
377  parent_stack.clear( );
378  return;
380  move_to_last( );
381  return;
383  break;
384  }
385  parent_stack.push_back(
387  std::pair<iterator, iterator>( jv.begin( ), jv.end( ) ) } );
388  } break;
389  case daw::json::JsonBaseParseTypes::Class: {
390  auto result = json_details::handle_on_class_start( handler, jv );
391  switch( result.value ) {
393  parent_stack.clear( );
394  return;
396  move_to_last( );
397  return;
399  break;
400  }
401  parent_stack.push_back(
402  { StackRangeType::Class,
403  std::pair<iterator, iterator>( jv.begin( ), jv.end( ) ) } );
404  } break;
405  case daw::json::JsonBaseParseTypes::Number: {
406  auto result = json_details::handle_on_number( handler, jv );
407  switch( result.value ) {
409  parent_stack.clear( );
410  return;
412  move_to_last( );
413  return;
415  break;
416  }
417  } break;
418  case daw::json::JsonBaseParseTypes::Bool: {
419  auto result = json_details::handle_on_bool( handler, jv );
420  switch( result.value ) {
422  parent_stack.clear( );
423  return;
425  move_to_last( );
426  return;
428  break;
429  }
430  } break;
431  case daw::json::JsonBaseParseTypes::String: {
432  auto result = json_details::handle_on_string( handler, jv );
433  switch( result.value ) {
435  parent_stack.clear( );
436  return;
438  move_to_last( );
439  return;
441  break;
442  }
443  } break;
444  case daw::json::JsonBaseParseTypes::Null: {
445  auto result = json_details::handle_on_null( handler, jv );
446  switch( result.value ) {
448  parent_stack.clear( );
449  return;
451  move_to_last( );
452  return;
454  break;
455  }
456  } break;
458  default: {
459  auto result = json_details::handle_on_error( handler, jv );
460  switch( result.value ) {
462  parent_stack.clear( );
463  return;
465  move_to_last( );
466  return;
468  break;
469  }
470  } break;
471  }
472  };
473 
474  auto const process_range = [&]( stack_value_t v ) {
475  if( v.value.first != v.value.second ) {
476  auto jv = *v.value.first;
477  v.value.first++;
478  parent_stack.push_back( std::move( v ) );
479  process_value( std::move( jv ) );
480  } else {
481  switch( v.type ) {
482  case StackRangeType::Class: {
483  auto result = json_details::handle_on_class_end( handler );
484  switch( result.value ) {
486  parent_stack.clear( );
487  return;
490  break;
491  }
492  } break;
493  case StackRangeType::Array: {
494  auto result = json_details::handle_on_array_end( handler );
495  switch( result.value ) {
497  parent_stack.clear( );
498  return;
501  break;
502  }
503  } break;
504  }
505  }
506  };
507 
508  process_value( { std::nullopt, std::move( jvalue ) } );
509 
510  while( not parent_stack.empty( ) ) {
511  auto v = std::move( parent_stack.back( ) );
512  parent_stack.pop_back( );
513  process_range( v );
514  }
515  }
516 
517  template<typename ParsePolicy = NoCommentSkippingPolicyChecked,
518  typename Handler>
519  inline void json_event_parser( std::string_view json_document,
520  Handler &&handler ) {
521  return json_event_parser( basic_json_value<ParsePolicy>( json_document ),
522  std::forward<Handler>( handler ) );
523  }
524 } // namespace daw::json
daw::json::DefaultJsonEventParserStackPolicy::difference_type
std::ptrdiff_t difference_type
Definition: daw_json_event_parser.h:314
daw::json::Complete
@ Complete
Definition: daw_json_event_parser.h:18
daw::json::JsonEventParserStackValue::type
StackRangeType type
Definition: daw_json_event_parser.h:302
daw::json::basic_json_pair
Definition: daw_json_value.h:34
daw::json::StackRangeType::Class
@ Class
daw::json
Definition: daw_json_event_parser.h:17
daw::json::JsonEventParserStackValue::value
std::pair< iterator, iterator > value
Definition: daw_json_event_parser.h:303
daw::json::DefaultJsonEventParserStackPolicy::back
CPP20CONSTEXPR reference back()
Definition: daw_json_event_parser.h:322
daw::json::JsonEventParserStackValue
Definition: daw_json_event_parser.h:300
daw::json::DefaultJsonEventParserStackPolicy::size_type
std::size_t size_type
Definition: daw_json_event_parser.h:313
daw::json::DefaultJsonEventParserStackPolicy::empty
CPP20CONSTEXPR bool empty() const
Definition: daw_json_event_parser.h:334
daw::json::DefaultJsonEventParserStackPolicy::DefaultJsonEventParserStackPolicy
CPP20CONSTEXPR DefaultJsonEventParserStackPolicy()=default
daw::json::SkipClassArray
@ SkipClassArray
Definition: daw_json_event_parser.h:18
daw::json::DefaultJsonEventParserStackPolicy::clear
CPP20CONSTEXPR void clear()
Definition: daw_json_event_parser.h:326
daw::json::basic_json_value::begin
constexpr iterator begin() const
Definition: daw_json_value.h:349
daw::json::json_event_parser
constexpr void json_event_parser(daw::json::basic_json_value< ParsePolicy > jvalue, Handler &&handler)
Definition: daw_json_event_parser.h:344
daw::json::DefaultJsonEventParserStackPolicy
Definition: daw_json_event_parser.h:307
daw::json::JsonBaseParseTypes::Number
@ Number
daw::json::basic_json_value
Definition: daw_json_value.h:300
daw::json::Continue
@ Continue
Definition: daw_json_event_parser.h:18
daw::json::basic_json_value::type
JsonBaseParseTypes type() const
Definition: daw_json_value.h:368
daw::json::NoCommentSkippingPolicyChecked
BasicParsePolicy< false, NoCommentSkippingPolicy, default_exec_tag, false > NoCommentSkippingPolicyChecked
Definition: daw_json_parse_policy.h:511
daw::json::basic_json_pair::value
basic_json_value< Range > value
Definition: daw_json_value.h:36
daw::json::basic_json_value::end
constexpr iterator end() const
Definition: daw_json_value.h:360
daw::json::DefaultJsonEventParserStackPolicy::pop_back
CPP20CONSTEXPR void pop_back()
Definition: daw_json_event_parser.h:330
daw::json::basic_json_value_iterator
Definition: daw_json_value.h:94
daw::json::basic_json_value::get_string
std::basic_string< char, Traits, Allocator > get_string(Allocator const &alloc=std::allocator< char >()) const
Definition: daw_json_value.h:438
daw::json::StackRangeType
StackRangeType
Definition: daw_json_event_parser.h:297
daw::json::DefaultJsonEventParserStackPolicy::reference
StackValue & reference
Definition: daw_json_event_parser.h:312
daw::json::json_parse_handler_result
json_parse_handler_result
Definition: daw_json_event_parser.h:18
daw::json::DefaultJsonEventParserStackPolicy::value_type
StackValue value_type
Definition: daw_json_event_parser.h:311
CPP20CONSTEXPR
#define CPP20CONSTEXPR
Definition: daw_json_parse_common.h:31
daw::json::DefaultJsonEventParserStackPolicy::push_back
CPP20CONSTEXPR void push_back(value_type &&v)
Definition: daw_json_event_parser.h:318