28 namespace json_details {
29 namespace name::name_parser {
34 template<
typename ParseState>
35 static constexpr void trim_end_of_name( ParseState &parse_state ) {
36 parse_state.trim_left( );
39 ErrorReason::InvalidMemberName,
41 parse_state.remove_prefix( );
42 parse_state.trim_left( );
45 template<
typename ParseState>
46 [[nodiscard]] DAW_ATTRIB_INLINE
static constexpr daw::string_view
47 parse_nq( ParseState &parse_state ) {
48 if constexpr( ParseState::allow_escaped_names ) {
49 auto r = skip_string_nq( parse_state );
50 trim_end_of_name( parse_state );
51 return daw::string_view( std::data( r ), std::size( r ) );
53 auto const ptr = parse_state.first;
54 if constexpr( ParseState::is_unchecked_input ) {
55 parse_state.template move_to_next_of_unchecked<
'"'>( );
57 parse_state.template move_to_next_of_checked<
'"'>( );
60 *std::prev( parse_state.first ) !=
'\\',
61 ErrorReason::InvalidString,
63 auto result = daw::string_view( ptr, parse_state.first );
64 parse_state.remove_prefix( );
65 trim_end_of_name( parse_state );
71 struct pop_json_path_result {
72 daw::string_view current{ };
78 [[nodiscard]]
static constexpr pop_json_path_result
79 pop_json_path( daw::string_view &path ) {
80 auto result = pop_json_path_result{ };
84 if( path.front( ) ==
'.' ) {
85 path.remove_prefix( );
88 path.pop_front_until( [&, in_escape =
false](
char c )
mutable {
100 result.found_char = c;
109 [[nodiscard]]
static constexpr bool
110 json_path_compare( daw::string_view json_path_item,
111 daw::string_view member_name ) {
112 if( json_path_item.front( ) ==
'\\' ) {
113 json_path_item.remove_prefix( );
115 while( not json_path_item.empty( ) and not member_name.empty( ) ) {
116 if( json_path_item.front( ) != member_name.front( ) ) {
119 json_path_item.remove_prefix( );
120 if( not json_path_item.empty( ) and
121 json_path_item.front( ) ==
'\\' ) {
122 json_path_item.remove_prefix( );
124 member_name.remove_prefix( );
126 return std::size( json_path_item ) == std::size( member_name );
129 template<
typename Result,
typename ForwardIterator>
130 constexpr Result parse_unsigned_int( ForwardIterator first,
131 ForwardIterator last ) {
132 std::size_t count = daw::digits<Result>;
137 for( ; first != last and count > 0; ++first, --count ) {
138 result *=
static_cast<Result
>( 10 );
140 static_cast<Result
>( *first ) -
static_cast<Result
>(
'0' );
151 template<
typename ParseState>
152 [[nodiscard]] DAW_ATTRIB_FLATTEN
static constexpr daw::string_view
153 parse_name( ParseState &parse_state ) {
155 ErrorReason::InvalidMemberName,
157 parse_state.remove_prefix( );
158 return name::name_parser::parse_nq( parse_state );
161 template<
typename ParseState>
162 static constexpr bool find_range2( ParseState &parse_state,
163 daw::string_view path ) {
165 auto pop_result = pop_json_path( path );
166 while( not pop_result.current.empty( ) or
167 pop_result.found_char != 0 ) {
170 if( pop_result.current.empty( ) ) {
172 ErrorReason::InvalidJSONPath,
174 pop_result = pop_json_path( path );
177 if( pop_result.found_char ==
']' ) {
180 ErrorReason::InvalidJSONPath,
182 parse_state.remove_prefix( );
183 parse_state.trim_left_unchecked( );
184 auto idx = parse_unsigned_int<std::size_t>(
185 pop_result.current.data( ), pop_result.current.data_end( ) );
189 (void)skip_value( parse_state );
190 parse_state.trim_left_checked( );
191 if( ( idx > 0 ) & ( parse_state.has_more( ) and
192 ( parse_state.front( ) !=
',' ) ) ) {
195 parse_state.move_next_member_or_end( );
199 ErrorReason::InvalidJSONPath,
201 parse_state.remove_prefix( );
202 parse_state.trim_left_unchecked( );
203 if( parse_state.empty( ) or
204 parse_state.is_closing_brace_checked( ) ) {
207 auto name = parse_name( parse_state );
208 while( not json_path_compare( pop_result.current, name ) ) {
209 (void)skip_value( parse_state );
210 parse_state.move_next_member_or_end( );
211 if( parse_state.empty( ) or parse_state.front( ) !=
'"' ) {
214 name = parse_name( parse_state );
217 pop_result = pop_json_path( path );
222 template<
typename ParsePolicy>
223 [[nodiscard]]
static constexpr find_result<ParsePolicy>
224 find_range( daw::string_view str, daw::string_view start_path ) {
226 ParsePolicy( std::data( str ), daw::data_end( str ) );
227 parse_state.trim_left_checked( );
229 if( parse_state.has_more( ) and not start_path.empty( ) ) {
230 found = find_range2( parse_state, start_path );
232 return find_result<ParsePolicy>{ parse_state, found };
235 template<
typename ParsePolicy,
typename Allocator>
236 [[nodiscard]]
static constexpr find_result<ParsePolicy>
237 find_range( daw::string_view str, daw::string_view start_path,
240 std::is_same_v<char const *, typename ParsePolicy::iterator>,
241 "Only char const * ranges are currently supported" );
242 auto parse_state = ParsePolicy::with_allocator(
243 std::data( str ), daw::data_end( str ), alloc );
244 parse_state.trim_left_checked( );
245 if( parse_state.has_more( ) and not start_path.empty( ) ) {
246 if( not find_range2( parse_state, start_path ) ) {
247 return find_result<ParsePolicy>{ parse_state,
false };
250 return find_result<ParsePolicy>{ parse_state,
true };