34 namespace json_details {
37 [[nodiscard]] DAW_ATTRIB_INLINE
constexpr bool
38 names_equal( daw::string_view lhs, daw::string_view rhs ) {
39 return std::size( lhs ) == std::size( rhs ) and
40 std::char_traits<char>::compare( std::data( lhs ),
42 std::size( lhs ) ) == 0;
45 template<
typename Iterator =
char const *>
46 struct location_info_t {
47 daw::string_view name;
48 Iterator first =
nullptr;
49 Iterator last =
nullptr;
50 Iterator class_first =
nullptr;
51 Iterator class_last =
nullptr;
52 std::size_t counter = 0;
54 [[nodiscard]]
constexpr bool missing( )
const {
55 return first ==
nullptr;
58 template<
typename ParseState>
59 constexpr void set_range( ParseState
const &parse_state ) {
60 first = parse_state.first;
61 last = parse_state.last;
62 class_first = parse_state.class_first;
63 class_last = parse_state.class_last;
64 counter = parse_state.counter;
67 template<
typename ParseState>
68 constexpr auto get_range( )
const {
69 using range_t =
typename ParseState::without_allocator_type;
70 return range_t( first, last, class_first, class_last, counter );
78 template<std::
size_t MemberCount,
typename Iterator =
char const *>
79 struct locations_info_t {
80 using value_type = location_info_t<Iterator>;
81 using reference = value_type &;
82 using const_reference = value_type
const &;
83 value_type names[MemberCount];
85 constexpr const_reference operator[]( std::size_t idx )
const {
90 constexpr reference operator[]( std::size_t idx ) {
95 static constexpr std::size_t size( ) {
99 template<std::
size_t start_pos>
100 [[nodiscard]] DAW_ATTRIB_INLINE
constexpr std::size_t
101 find_name( daw::string_view key )
const {
102#if defined( DAW_JSON_BUGFIX_MSVC_EVAL_ORDER_002 )
104 constexpr std::size_t first_pos = 0;
106 constexpr std::size_t first_pos = start_pos;
108 for( std::size_t n = first_pos; n < MemberCount; ++n ) {
109 if( names_equal( key, names[n].name ) ) {
118 template<
typename ParseState,
typename... JsonMembers>
120 make_locations_info( ) {
121 return locations_info_t<
sizeof...( JsonMembers ),
122 typename ParseState::iterator>{
123 { location_info_t<typename ParseState::iterator>{ JsonMembers::name }... } };
135 enum class AllMembersMustExist { yes, no };
140 template<
typename ParseState>
141 [[nodiscard]] DAW_ATTRIB_INLINE
static constexpr bool
142 match_expected_name( ParseState
const &parse_state,
143 daw::string_view expected ) {
144 auto const sz = std::size( expected );
145 return parse_state.size( ) > sz + 1U and
146 parse_state.first[0] ==
'"' and
147 parse_state.first[sz + 1U] ==
'"' and
148 ( sz == 0 or expected[sz - 1U] !=
'\\' ) and
149 std::char_traits<char>::compare(
150 parse_state.first + 1, std::data( expected ), sz ) == 0;
153 template<std::size_t pos, AllMembersMustExist must_exist,
154 bool from_start =
false, std::size_t N,
typename ParseState>
155 [[nodiscard]] DAW_ATTRIB_INLINE
static constexpr find_result<ParseState>
156 find_class_member( ParseState &parse_state,
157 locations_info_t<N, typename ParseState::iterator> &locations,
bool is_nullable,
158 daw::string_view member_name ) {
166 ( not locations[pos].missing( ) ),
167 ( not parse_state.is_closing_brace_checked( ) ) ),
168 missing_member( member_name ),
171 parse_state.trim_left_unchecked( );
172 bool known = not locations[pos].missing( );
174 locations[pos].missing( ),
175 ( not parse_state.empty( ) and parse_state.front( ) !=
'}' ) ) ) {
180 std::size_t name_pos = std::size( locations );
181 if(
auto const expected = locations[pos].name;
182 match_expected_name( parse_state, expected ) ) {
183 parse_state.remove_prefix( std::size( expected ) + 2U );
184 name::name_parser::trim_end_of_name( parse_state );
189 auto const name = parse_name( parse_state );
191 locations.template find_name<( from_start ? 0 : pos )>( name );
193 if constexpr( must_exist == AllMembersMustExist::yes ) {
195 ErrorReason::UnknownMember,
198#if defined( DAW_JSON_PARSER_DIAGNOSTICS )
199 std::cerr <<
"DEBUG: Unknown member '" << name <<
'\n';
201 if( name_pos >= std::size( locations ) ) {
203 (void)skip_value( parse_state );
204 parse_state.move_next_member_or_end( );
208 if( name_pos == pos ) {
209 locations[pos].set_range( parse_state );
212#if defined( DAW_JSON_PARSER_DIAGNOSTICS )
213 std::cerr <<
"DEBUG: Out of order member '"
214 << locations.names[name_pos].name
215 <<
"' found, looking for '" << locations.names[pos].name
217 << std::abs(
static_cast<long long>( pos ) -
218 static_cast<long long>( name_pos ) )
219 <<
" members ahead in constructor\n";
229 locations[name_pos].set_range( skip_value( parse_state ) );
231 if constexpr( ParseState::is_unchecked_input ) {
232 if( name_pos + 1 < std::size( locations ) ) {
233 parse_state.move_next_member( );
235 parse_state.move_next_member_or_end( );
238 parse_state.move_next_member_or_end( );
242 if( locations[pos].missing( ) ) {
245 if constexpr( ParseState::has_allocator ) {
247 locations[pos].template get_range<ParseState>( ).with_allocator(
251 return find_result<ParseState>{
252 locations[pos].template get_range<ParseState>( ), known };