17 namespace daw::json::json_details::name {
18 namespace name_parser {
23 template<
typename Range>
24 [[maybe_unused]]
static constexpr
void trim_end_of_name( Range &rng ) {
33 template<
typename Range>
35 maybe_unused]] DAW_ATTRIBUTE_FLATTEN
static inline constexpr daw::
37 parse_nq( Range &rng ) {
39 if constexpr( Range::allow_escaped_names ) {
40 auto r = skip_string_nq( rng );
41 trim_end_of_name( rng );
42 return daw::string_view( r.data( ), r.size( ) );
44 char const *
const ptr = rng.first;
45 if constexpr( Range::is_unchecked_input ) {
46 rng.template move_to_next_of_unchecked<
'"'>( );
48 rng.template move_to_next_of_checked<
'"'>( );
51 *std::prev( rng.first ) !=
'\\',
52 ErrorReason::InvalidString, rng );
53 auto result = daw::string_view( ptr, rng.first );
55 trim_end_of_name( rng );
62 namespace daw::json::json_details {
67 [[nodiscard]] constexpr
auto pop_json_path( daw::string_view &path ) {
68 struct pop_json_path_result {
69 daw::string_view current{ };
75 if( path.front( ) ==
'.' ) {
76 path.remove_prefix( );
78 result.current = path.pop_front( [&, in_escape =
false](
char c )
mutable {
90 result.found_char = c;
99 [[nodiscard]] constexpr
bool
100 json_path_compare( daw::string_view json_path_item,
101 daw::string_view member_name ) {
102 if( json_path_item.front( ) ==
'\\' ) {
103 json_path_item.remove_prefix( );
105 while( not json_path_item.empty( ) and not member_name.empty( ) ) {
106 if( json_path_item.front( ) != member_name.front( ) ) {
109 json_path_item.remove_prefix( );
110 if( not json_path_item.empty( ) and json_path_item.front( ) ==
'\\' ) {
111 json_path_item.remove_prefix( );
113 member_name.remove_prefix( );
115 return json_path_item.size( ) == member_name.size( );
122 template<
typename Range>
123 [[nodiscard]] constexpr daw::string_view parse_name( Range &rng ) {
125 ErrorReason::InvalidMemberName, rng );
126 rng.remove_prefix( );
127 return name::name_parser::parse_nq( rng );
130 template<
typename Range>
131 constexpr
bool find_range2( Range &rng, daw::string_view path ) {
133 auto pop_result = pop_json_path( path );
134 while( not pop_result.current.empty( ) ) {
135 if( pop_result.found_char ==
']' ) {
138 ErrorReason::InvalidJSONPath, rng );
139 rng.remove_prefix( );
140 rng.trim_left_unchecked( );
142 daw::parser::parse_unsigned_int<std::size_t>( pop_result.current );
146 (void)skip_value( rng );
147 rng.trim_left_checked( );
148 if( ( idx > 0 ) & ( rng.has_more( ) and ( rng.front( ) !=
',' ) ) ) {
155 ErrorReason::InvalidJSONPath, rng );
156 rng.remove_prefix( );
157 rng.trim_left_unchecked( );
158 auto name = parse_name( rng );
159 while( not json_path_compare( pop_result.current, name ) ) {
160 (void)skip_value( rng );
162 if( rng.empty( ) or rng.front( ) !=
'"' ) {
165 name = parse_name( rng );
168 pop_result = pop_json_path( path );
173 template<
typename ParsePolicy,
typename String>
174 [[nodiscard]] constexpr std::pair<bool, ParsePolicy>
175 find_range( String &&str, daw::string_view start_path ) {
176 static_assert( std::is_same_v<char const *, typename ParsePolicy::iterator>,
177 "Only char const * ranges are currently supported" );
179 ParsePolicy( std::data( str ), std::data( str ) + std::size( str ) );
180 rng.trim_left_checked( );
181 if( rng.has_more( ) and not start_path.empty( ) ) {
182 if( not find_range2( rng, start_path ) ) {
183 return {
false, rng };
186 return {
true, rng };
189 template<
typename ParsePolicy,
typename String,
typename Allocator>
190 [[nodiscard]] constexpr
auto
191 find_range( String &&str, daw::string_view start_path, Allocator &alloc ) {
192 static_assert( std::is_same_v<char const *, typename ParsePolicy::iterator>,
193 "Only char const * ranges are currently supported" );
194 auto rng = ParsePolicy::with_allocator(
195 std::data( str ), std::data( str ) + std::size( str ), alloc );
196 rng.trim_left_checked( );
197 if( rng.has_more( ) and not start_path.empty( ) ) {
198 if( not find_range2( rng, start_path ) ) {
199 return std::pair{
false, rng };
202 return std::pair{
true, rng };