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