DAW JSON Link
Loading...
Searching...
No Matches
daw_json_parse_policy_no_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 "version.h"
12
13#include "daw_json_assert.h"
18
19#include <daw/daw_attributes.h>
20#include <daw/daw_function_table.h>
21#include <daw/daw_likely.h>
22#include <daw/daw_traits.h>
23
24#include <cstddef>
25#include <cstdint>
26#include <type_traits>
27
28namespace daw::json {
29 inline namespace DAW_JSON_VER {
31 template<typename ParseState>
32 DAW_ATTRIB_FLATINLINE static constexpr void
33 trim_left_checked( ParseState &parse_state ) {
34 if constexpr( ParseState::minified_document ) {
35 return;
36 } else {
37 using CharT = typename ParseState::CharT;
38 // SIMD here was much slower, most JSON has very minimal whitespace
39 CharT *first = parse_state.first;
40 daw_json_assert_weak( first, ErrorReason::Unknown );
41 CharT *const last = parse_state.last;
42
43 // only used when not zero terminated string and gcc9 warns
44 (void)last;
45
46 if constexpr( ParseState::is_zero_terminated_string ) {
47 // Ensure that zero terminator isn't included in skipable value
48 while( DAW_UNLIKELY(
49 ( static_cast<unsigned>( static_cast<unsigned char>( *first ) ) -
50 1U ) <= 0x1FU ) ) {
51
52 ++first;
53 }
54 } else {
55 while(
56 DAW_LIKELY( first < last ) and
57 ( static_cast<unsigned>( static_cast<unsigned char>( *first ) ) -
58 1U ) <= 0x1FU ) {
59 ++first;
60 }
61 }
62 parse_state.first = first;
63 }
64 }
65
66 template<typename ParseState>
67 DAW_ATTRIB_FLATINLINE static constexpr void
68 trim_left_unchecked( ParseState &parse_state ) {
69 if constexpr( ParseState::minified_document ) {
70 return;
71 } else {
72 using CharT = typename ParseState::CharT;
73 CharT *first = parse_state.first;
74 while( DAW_UNLIKELY(
75 ( static_cast<unsigned>( static_cast<unsigned char>( *first ) ) -
76 1U ) <= 0x1F ) ) {
77
78 ++first;
79 }
80 parse_state.first = first;
81 }
82 }
83
84 template<typename ParseState>
85 DAW_ATTRIB_FLATINLINE static constexpr void
86 move_next_member_unchecked( ParseState &parse_state ) {
87 parse_state.first =
88 json_details::memchr_unchecked<'"', typename ParseState::exec_tag_t,
89 ParseState::expect_long_strings>(
90 parse_state.first, parse_state.last );
91 }
92
93 template<char... keys, typename ParseState>
94 DAW_ATTRIB_FLATINLINE static constexpr void
95 move_to_next_of( ParseState &parse_state ) {
96 static_assert( sizeof...( keys ) > 0 );
97 static_assert( sizeof...( keys ) <= 16 );
98
99 using CharT = typename ParseState::CharT;
100
101 if constexpr( daw::traits::not_same<typename ParseState::exec_tag_t,
102 constexpr_exec_tag>::value ) {
103 parse_state.first =
104 json_details::mempbrk<ParseState::is_unchecked_input,
105 typename ParseState::exec_tag_t,
106 ParseState::expect_long_strings, keys...>(
107 parse_state.first, parse_state.last );
108 } else {
109 CharT *first = parse_state.first;
110 CharT *const last = parse_state.last;
111
112 // silencing gcc9 unused warning. last is used inside if constexpr
113 // blocks
114 (void)last;
115
116 if( ParseState::is_zero_terminated_string ) {
117 daw_json_assert_weak( first < last and *first != '\0',
118 ErrorReason::UnexpectedEndOfData,
119 parse_state );
120 while( not parse_policy_details::in<keys...>( *first ) ) {
121 ++first;
122 }
123 daw_json_assert_weak( *first != 0, ErrorReason::UnexpectedEndOfData,
124 parse_state );
125 } else {
127 first < last, ErrorReason::UnexpectedEndOfData, parse_state );
128 while( not parse_policy_details::in<keys...>( *first ) ) {
129 ++first;
131 first < last, ErrorReason::UnexpectedEndOfData, parse_state );
132 }
133 }
134 parse_state.first = first;
135 }
136 }
137
138 DAW_ATTRIB_INLINE static constexpr bool is_literal_end( char c ) {
139 return ( c == '\0' ) | ( c == ',' ) | ( c == ']' ) | ( c == '}' );
140 }
141
142 template<char PrimLeft, typename ParseState>
143 DAW_ATTRIB_FLATTEN static constexpr ParseState
144 skip_bracketed_item_checked( ParseState &parse_state ) {
145 constexpr char PrimRight = PrimLeft == '{' ? '}' : ']';
146 constexpr char SecLeft = PrimLeft == '{' ? '[' : '{';
147 constexpr char SecRight = SecLeft == '{' ? '}' : ']';
148
149 using CharT = typename ParseState::CharT;
150 // Not checking for Left as it is required to be skipped already
151 CharT *ptr_first = parse_state.first;
152 CharT *const ptr_last = parse_state.last;
153 if( DAW_UNLIKELY( ptr_first >= ptr_last ) ) {
154 return parse_state;
155 }
156 auto result = parse_state;
157 std::size_t cnt = 0;
158 std::uint32_t prime_bracket_count = 1;
159 std::uint32_t second_bracket_count = 0;
160
161 if( *ptr_first == PrimLeft ) {
162 ++ptr_first;
163 }
164 while( DAW_LIKELY( ptr_first < ptr_last ) ) {
165 switch( *ptr_first ) {
166 case '\\':
167 ++ptr_first;
168 break;
169 case '"':
170 ++ptr_first;
171 ptr_first = json_details::mem_skip_until_end_of_string<
172 ParseState::is_unchecked_input>( ParseState::exec_tag, ptr_first,
173 ptr_last );
174 daw_json_ensure( ptr_first < ptr_last and *ptr_first == '"',
175 ErrorReason::UnexpectedEndOfData, parse_state );
176 break;
177 case ',':
178 if( DAW_UNLIKELY( ( prime_bracket_count == 1 ) &
179 ( second_bracket_count == 0 ) ) ) {
180 ++cnt;
181 }
182 break;
183 case PrimLeft:
184 ++prime_bracket_count;
185 break;
186 case PrimRight:
187 --prime_bracket_count;
188 if( prime_bracket_count == 0 ) {
189 ++ptr_first;
190 daw_json_ensure( second_bracket_count == 0,
191 ErrorReason::InvalidBracketing, parse_state );
192 result.last = ptr_first;
193 result.counter = cnt;
194 parse_state.first = ptr_first;
195 return result;
196 }
197 break;
198 case SecLeft:
199 ++second_bracket_count;
200 break;
201 case SecRight:
202 --second_bracket_count;
203 break;
204 }
205 ++ptr_first;
206 }
207 daw_json_ensure( ( prime_bracket_count == 0 ) &
208 ( second_bracket_count == 0 ),
209 ErrorReason::InvalidBracketing, parse_state );
210 // We include the close primary bracket in the range so that subsequent
211 // parsers have a terminator inside their range
212 result.last = ptr_first;
213 result.counter = cnt;
214 parse_state.first = ptr_first;
215 return result;
216 }
217
218 template<char PrimLeft, typename ParseState>
219 DAW_ATTRIB_NOINLINE static constexpr ParseState
220 skip_bracketed_item_unchecked( ParseState &parse_state ) {
221 // Not checking for Left as it is required to be skipped already
222 constexpr char PrimRight = PrimLeft == '{' ? '}' : ']';
223 constexpr char SecLeft = PrimLeft == '{' ? '[' : '{';
224 constexpr char SecRight = SecLeft == '{' ? '}' : ']';
225 using CharT = typename ParseState::CharT;
226 auto result = parse_state;
227 std::size_t cnt = 0;
228 std::uint32_t prime_bracket_count = 1;
229 std::uint32_t second_bracket_count = 0;
230 CharT *ptr_first = parse_state.first;
231
232 if( *ptr_first == PrimLeft ) {
233 ++ptr_first;
234 }
235 while( true ) {
236 switch( *ptr_first ) {
237 case '\\':
238 ++ptr_first;
239 break;
240 case '"':
241 ++ptr_first;
242 ptr_first = json_details::mem_skip_until_end_of_string<
243 ParseState::is_unchecked_input>( ParseState::exec_tag, ptr_first,
244 parse_state.last );
245 break;
246 case ',':
247 if( DAW_UNLIKELY( ( prime_bracket_count == 1 ) &
248 ( second_bracket_count == 0 ) ) ) {
249 ++cnt;
250 }
251 break;
252 case PrimLeft:
253 ++prime_bracket_count;
254 break;
255 case PrimRight:
256 --prime_bracket_count;
257 if( prime_bracket_count == 0 ) {
258 ++ptr_first;
259 // We include the close primary bracket in the range so that
260 // subsequent parsers have a terminator inside their range
261 result.last = ptr_first;
262 result.counter = cnt;
263 parse_state.first = ptr_first;
264 return result;
265 }
266 break;
267 case SecLeft:
268 ++second_bracket_count;
269 break;
270 case SecRight:
271 --second_bracket_count;
272 break;
273 }
274 ++ptr_first;
275 }
276 // Should never get here, only loop exit is when PrimaryRight is found
277 // and count == 0
278 DAW_UNREACHABLE( );
279 }
280 };
281 } // namespace DAW_JSON_VER
282} // 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.
Customization point traits.
static DAW_ATTRIB_NOINLINE constexpr ParseState skip_bracketed_item_unchecked(ParseState &parse_state)
#define DAW_JSON_VER
The version string used in namespace definitions. Must be a valid namespace name.
Definition version.h:20