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