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
11#include "version.h"
12
13#include "daw_json_assert.h"
17
18#include <daw/daw_attributes.h>
19#include <daw/daw_likely.h>
20#include <daw/daw_traits.h>
21
22#include <cstddef>
23#include <cstdint>
24#include <type_traits>
25
26namespace 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
74 trim_left_unchecked( ParseState &parse_state ) {
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
83 move_next_member_unchecked( ParseState &parse_state ) {
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, typename ParseState>
107 DAW_ATTRIB_FLATINLINE static constexpr ParseState
108 skip_bracketed_item_checked( ParseState &parse_state ) {
109 constexpr char PrimRight = PrimLeft == '{' ? '}' : ']';
110 constexpr char SecLeft = PrimLeft == '{' ? '[' : '{';
111 constexpr char SecRight = SecLeft == '{' ? '}' : ']';
112 using CharT = typename ParseState::CharT;
113 // Not checking for Left as it is required to be skipped already
114 auto result = parse_state;
115 std::size_t cnt = 0;
116 std::uint32_t prime_bracket_count = 1;
117 std::uint32_t second_bracket_count = 0;
118 CharT *ptr_first = parse_state.first;
119 CharT *const ptr_last = parse_state.last;
120 if( DAW_UNLIKELY( ptr_first >= ptr_last ) ) {
121 return result;
122 }
123 if( *ptr_first == PrimLeft ) {
124 ++ptr_first;
125 }
126 while( DAW_LIKELY( ptr_first < ptr_last ) ) {
127 // TODO: use if/else if or put switch into IILE
128 switch( *ptr_first ) {
129 case '\\':
130 ++ptr_first;
131 break;
132 case '"':
133 ++ptr_first;
134 ptr_first = json_details::mem_skip_until_end_of_string<
135 ParseState::is_unchecked_input>( ParseState::exec_tag, ptr_first,
136 parse_state.last );
137 daw_json_ensure( ptr_first < ptr_last,
138 ErrorReason::UnexpectedEndOfData, parse_state );
139 break;
140 case ',':
141 if( prime_bracket_count == 1 and second_bracket_count == 0 ) {
142 ++cnt;
143 }
144 break;
145 case PrimLeft:
146 ++prime_bracket_count;
147 break;
148 case PrimRight:
149 --prime_bracket_count;
150 if( prime_bracket_count == 0 ) {
151 daw_json_ensure( second_bracket_count == 0,
152 ErrorReason::InvalidBracketing, parse_state );
153 ++ptr_first;
154 // We include the close primary bracket in the range so that
155 // subsequent parsers have a terminator inside their range
156 result.last = ptr_first;
157 result.counter = cnt;
158 parse_state.first = ptr_first;
159 return result;
160 }
161 break;
162 case SecLeft:
163 ++second_bracket_count;
164 break;
165 case SecRight:
166 --second_bracket_count;
167 break;
168 case '#':
169 ++ptr_first;
170 while( ptr_first < ptr_last and *ptr_first != '\n' ) {
171 ++ptr_first;
172 }
173 if( ptr_first < ptr_last ) {
174 continue;
175 }
176 break;
177 }
178 ++ptr_first;
179 }
180 daw_json_ensure( ( prime_bracket_count == 0 ) &
181 ( second_bracket_count == 0 ),
182 ErrorReason::InvalidBracketing, parse_state );
183 // We include the close primary bracket in the range so that subsequent
184 // parsers have a terminator inside their range
185 result.last = ptr_first;
186 result.counter = cnt;
187 parse_state.first = ptr_first;
188 return result;
189 }
190
191 template<char PrimLeft, typename ParseState>
192 DAW_ATTRIB_FLATINLINE static constexpr ParseState
193 skip_bracketed_item_unchecked( ParseState &parse_state ) {
194 // Not checking for Left as it is required to be skipped already
195 constexpr char PrimRight = PrimLeft == '{' ? '}' : ']';
196 constexpr char SecLeft = PrimLeft == '{' ? '[' : '{';
197 constexpr char SecRight = SecLeft == '{' ? '}' : ']';
198 using CharT = typename ParseState::CharT;
199 auto result = parse_state;
200 std::size_t cnt = 0;
201 std::uint32_t prime_bracket_count = 1;
202 std::uint32_t second_bracket_count = 0;
203 CharT *ptr_first = parse_state.first;
204 if( *ptr_first == PrimLeft ) {
205 ++ptr_first;
206 }
207 while( true ) {
208 switch( *ptr_first ) {
209 case '\\':
210 ++ptr_first;
211 break;
212 case '"':
213 ++ptr_first;
214 ptr_first = json_details::mem_skip_until_end_of_string<
215 ParseState::is_unchecked_input>( ParseState::exec_tag, ptr_first,
216 parse_state.last );
217 break;
218 case ',':
219 if( prime_bracket_count == 1 and second_bracket_count == 0 ) {
220 ++cnt;
221 }
222 break;
223 case PrimLeft:
224 ++prime_bracket_count;
225 break;
226 case PrimRight:
227 --prime_bracket_count;
228 if( prime_bracket_count == 0 ) {
229 ++ptr_first;
230 // We include the close primary bracket in the range so that
231 // subsequent parsers have a terminator inside their range
232 result.last = ptr_first;
233 result.counter = cnt;
234 parse_state.first = ptr_first;
235 return result;
236 }
237 break;
238 case SecLeft:
239 ++second_bracket_count;
240 break;
241 case SecRight:
242 --second_bracket_count;
243 break;
244 case '#':
245 ++ptr_first;
246 while( *ptr_first != '\n' ) {
247 ++ptr_first;
248 }
249 break;
250 }
251 ++ptr_first;
252 }
253 DAW_UNREACHABLE( );
254 }
255 };
256 } // namespace DAW_JSON_VER
257} // 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