DAW JSON Link
daw_json_parse_policy_hash_comments.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_assert.h"
12 #include "daw_json_parse_common.h"
15 #include "version.h"
16 
17 #include <daw/daw_attributes.h>
18 #include <daw/daw_likely.h>
19 #include <daw/daw_traits.h>
20 
21 #include <ciso646>
22 #include <cstddef>
23 #include <cstdint>
24 #include <type_traits>
25 
26 namespace daw::json {
27  inline namespace DAW_JSON_VER {
29  template<typename ParseState>
30  DAW_ATTRIB_FLATINLINE static constexpr void
31  skip_comments_unchecked( ParseState &parse_state ) {
32  while( parse_state.front( ) == '#' ) {
33  parse_state.remove_prefix( );
34  parse_state.template move_to_next_of_unchecked<'\n'>( );
35  parse_state.remove_prefix( );
36  }
37  }
38 
39  template<typename ParseState>
40  DAW_ATTRIB_FLATINLINE static constexpr void
41  skip_comments_checked( ParseState &parse_state ) {
42  while( parse_state.has_more( ) and parse_state.front( ) == '#' ) {
43  parse_state.remove_prefix( );
44  parse_state.template move_to_next_of_checked<'\n'>( );
45  if( parse_state.front( ) == '\n' ) {
46  parse_state.remove_prefix( );
47  }
48  }
49  }
50 
51  template<typename ParseState>
52  DAW_ATTRIB_FLATINLINE static constexpr void
53  skip_comments( ParseState &parse_state ) {
54  if constexpr( ParseState::is_unchecked_input ) {
55  skip_comments_unchecked( parse_state );
56  } else {
57  skip_comments_checked( parse_state );
58  }
59  }
60 
61  public:
62  template<typename ParseState>
63  DAW_ATTRIB_FLATINLINE static constexpr void
64  trim_left_checked( ParseState &parse_state ) {
65  skip_comments_checked( parse_state );
66  while( parse_state.has_more( ) and parse_state.is_space_unchecked( ) ) {
67  parse_state.remove_prefix( );
68  skip_comments_checked( parse_state );
69  }
70  }
71 
72  template<typename ParseState>
73  DAW_ATTRIB_FLATINLINE static constexpr void
75  skip_comments_unchecked( parse_state );
76  while( parse_state.is_space_unchecked( ) ) {
77  parse_state.remove_prefix( );
78  }
79  }
80 
81  template<typename ParseState>
82  DAW_ATTRIB_FLATINLINE static constexpr void
84  parse_state.move_next_member_or_end_unchecked( );
85  }
86 
87  template<char... keys, typename ParseState>
88  DAW_ATTRIB_FLATINLINE static constexpr void
89  move_to_next_of( ParseState &parse_state ) {
90  skip_comments( parse_state );
91 
92  daw_json_assert_weak( parse_state.has_more( ),
93  ErrorReason::UnexpectedEndOfData, parse_state );
94  while( not parse_policy_details::in<keys...>( parse_state.front( ) ) ) {
95  daw_json_assert_weak( parse_state.has_more( ),
96  ErrorReason::UnexpectedEndOfData, parse_state );
97  parse_state.remove_prefix( );
98  skip_comments( parse_state );
99  }
100  }
101 
102  DAW_ATTRIB_FLATINLINE static constexpr bool is_literal_end( char c ) {
103  return c == '\0' or c == ',' or c == ']' or c == '}' or c == '#';
104  }
105 
106  template<char PrimLeft, char PrimRight, char SecLeft, char SecRight,
107  typename ParseState>
108  DAW_ATTRIB_FLATINLINE static constexpr ParseState
110  using CharT = typename ParseState::CharT;
111  // Not checking for Left as it is required to be skipped already
112  auto result = parse_state;
113  std::size_t cnt = 0;
114  std::uint32_t prime_bracket_count = 1;
115  std::uint32_t second_bracket_count = 0;
116  CharT *ptr_first = parse_state.first;
117  CharT *const ptr_last = parse_state.last;
118  if( DAW_UNLIKELY( ptr_first >= ptr_last ) ) {
119  return result;
120  }
121  if( *ptr_first == PrimLeft ) {
122  ++ptr_first;
123  }
124  while( DAW_LIKELY( ptr_first < ptr_last ) ) {
125  // TODO: use if/else if or put switch into IILE
126  switch( *ptr_first ) {
127  case '\\':
128  ++ptr_first;
129  break;
130  case '"':
131  ++ptr_first;
132  if constexpr( traits::not_same_v<typename ParseState::exec_tag_t,
133  constexpr_exec_tag> ) {
135  ParseState::is_unchecked_input>( ParseState::exec_tag,
136  ptr_first, parse_state.last );
137  } else {
138  while( DAW_LIKELY( ptr_first < ptr_last ) and
139  *ptr_first != '"' ) {
140  if( *ptr_first == '\\' ) {
141  ++ptr_first;
142  if( ptr_first >= ptr_last ) {
143  break;
144  }
145  }
146  ++ptr_first;
147  }
148  }
149  daw_json_assert( ptr_first < ptr_last,
150  ErrorReason::UnexpectedEndOfData, parse_state );
151  break;
152  case ',':
153  if( prime_bracket_count == 1 and second_bracket_count == 0 ) {
154  ++cnt;
155  }
156  break;
157  case PrimLeft:
158  ++prime_bracket_count;
159  break;
160  case PrimRight:
161  --prime_bracket_count;
162  if( prime_bracket_count == 0 ) {
163  daw_json_assert( second_bracket_count == 0,
164  ErrorReason::InvalidBracketing, parse_state );
165  ++ptr_first;
166  // We include the close primary bracket in the range so that
167  // subsequent parsers have a terminator inside their range
168  result.last = ptr_first;
169  result.counter = cnt;
170  parse_state.first = ptr_first;
171  return result;
172  }
173  break;
174  case SecLeft:
175  ++second_bracket_count;
176  break;
177  case SecRight:
178  --second_bracket_count;
179  break;
180  case '#':
181  ++ptr_first;
182  while( ptr_first < ptr_last and *ptr_first != '\n' ) {
183  ++ptr_first;
184  }
185  if( ptr_first < ptr_last ) {
186  continue;
187  }
188  break;
189  }
190  ++ptr_first;
191  }
192  daw_json_assert( ( prime_bracket_count == 0 ) &
193  ( second_bracket_count == 0 ),
194  ErrorReason::InvalidBracketing, parse_state );
195  // We include the close primary bracket in the range so that subsequent
196  // parsers have a terminator inside their range
197  result.last = ptr_first;
198  result.counter = cnt;
199  parse_state.first = ptr_first;
200  return result;
201  }
202 
203  template<char PrimLeft, char PrimRight, char SecLeft, char SecRight,
204  typename ParseState>
205  DAW_ATTRIB_FLATINLINE static constexpr ParseState
207  // Not checking for Left as it is required to be skipped already
208  using CharT = typename ParseState::CharT;
209  auto result = parse_state;
210  std::size_t cnt = 0;
211  std::uint32_t prime_bracket_count = 1;
212  std::uint32_t second_bracket_count = 0;
213  CharT *ptr_first = parse_state.first;
214  if( *ptr_first == PrimLeft ) {
215  ++ptr_first;
216  }
217  while( true ) {
218  switch( *ptr_first ) {
219  case '\\':
220  ++ptr_first;
221  break;
222  case '"':
223  ++ptr_first;
224  if constexpr( traits::not_same_v<typename ParseState::exec_tag_t,
225  constexpr_exec_tag> ) {
227  ParseState::is_unchecked_input>( ParseState::exec_tag,
228  ptr_first, parse_state.last );
229  } else {
230  while( *ptr_first != '"' ) {
231  if( *ptr_first == '\\' ) {
232  ++ptr_first;
233  }
234  ++ptr_first;
235  }
236  }
237  break;
238  case ',':
239  if( prime_bracket_count == 1 and second_bracket_count == 0 ) {
240  ++cnt;
241  }
242  break;
243  case PrimLeft:
244  ++prime_bracket_count;
245  break;
246  case PrimRight:
247  --prime_bracket_count;
248  if( prime_bracket_count == 0 ) {
249  ++ptr_first;
250  // We include the close primary bracket in the range so that
251  // subsequent parsers have a terminator inside their range
252  result.last = ptr_first;
253  result.counter = cnt;
254  parse_state.first = ptr_first;
255  return result;
256  }
257  break;
258  case SecLeft:
259  ++second_bracket_count;
260  break;
261  case SecRight:
262  --second_bracket_count;
263  break;
264  case '#':
265  ++ptr_first;
266  while( *ptr_first != '\n' ) {
267  ++ptr_first;
268  }
269  break;
270  }
271  ++ptr_first;
272  }
273  DAW_UNREACHABLE( );
274  }
275  };
276  } // namespace DAW_JSON_VER
277 } // namespace daw::json
Definition: daw_json_parse_policy_hash_comments.h:28
static constexpr DAW_ATTRIB_FLATINLINE bool is_literal_end(char c)
Definition: daw_json_parse_policy_hash_comments.h:102
static constexpr DAW_ATTRIB_FLATINLINE void trim_left_checked(ParseState &parse_state)
Definition: daw_json_parse_policy_hash_comments.h:64
static constexpr DAW_ATTRIB_FLATINLINE void move_to_next_of(ParseState &parse_state)
Definition: daw_json_parse_policy_hash_comments.h:89
static constexpr DAW_ATTRIB_FLATINLINE void trim_left_unchecked(ParseState &parse_state)
Definition: daw_json_parse_policy_hash_comments.h:74
static constexpr DAW_ATTRIB_FLATINLINE ParseState skip_bracketed_item_unchecked(ParseState &parse_state)
Definition: daw_json_parse_policy_hash_comments.h:206
static constexpr DAW_ATTRIB_FLATINLINE ParseState skip_bracketed_item_checked(ParseState &parse_state)
Definition: daw_json_parse_policy_hash_comments.h:109
static constexpr DAW_ATTRIB_FLATINLINE void move_next_member_unchecked(ParseState &parse_state)
Definition: daw_json_parse_policy_hash_comments.h:83
#define daw_json_assert_weak(Bool,...)
Definition: daw_json_assert.h:189
#define daw_json_assert(Bool,...)
Definition: daw_json_assert.h:178
ParseState & parse_state
Definition: daw_json_parse_class.h:201
DAW_ATTRIB_FLATINLINE CharT * mem_skip_until_end_of_string(ExecTag const &tag, CharT *first, CharT *const last)
Definition: daw_not_const_ex_functions.h:360
Definition: daw_from_json.h:22
Definition: daw_json_exec_modes.h:19
#define DAW_JSON_VER
Definition: version.h:11