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