36 namespace json_details {
37 template<
typename Iterator =
char const *>
38 struct location_info_t {
39 daw::string_view name;
40 Iterator first =
nullptr;
41 Iterator last =
nullptr;
42 Iterator class_first =
nullptr;
43 Iterator class_last =
nullptr;
44 std::size_t counter = 0;
46 [[nodiscard]]
constexpr bool missing( )
const {
47 return first ==
nullptr;
50 template<
typename ParseState>
51 constexpr void set_range( ParseState
const &parse_state ) {
52 first = parse_state.first;
53 last = parse_state.last;
54 class_first = parse_state.class_first;
55 class_last = parse_state.class_last;
56 counter = parse_state.counter;
59 template<
typename ParseState>
60 constexpr auto get_range( )
const {
61 using range_t =
typename ParseState::without_allocator_type;
62 return range_t( first, last, class_first, class_last, counter );
70 template<std::size_t MemberCount,
bool DoFullNameMatch =
true,
71 typename Iterator =
char const *>
72 struct locations_info_t {
73 using value_type = location_info_t<Iterator>;
74 using reference = value_type &;
75 using const_reference = value_type
const &;
76 static constexpr bool do_full_name_match = DoFullNameMatch;
78 value_type names[MemberCount];
80 constexpr const_reference operator[]( std::size_t idx )
const {
85 constexpr reference operator[]( std::size_t idx ) {
90 static constexpr std::size_t size( ) {
94 template<
bool expect_
long_
strings, std::
size_t start_pos>
95 [[nodiscard]] DAW_ATTRIB_INLINE
constexpr std::size_t
96 find_name( daw::string_view key )
const {
97 auto const hash = name_hash<expect_long_strings>( key );
98#if defined( DAW_JSON_BUGFIX_MSVC_EVAL_ORDER_002 )
100 for( std::size_t n = 0; n < MemberCount; ++n ) {
102 for( std::size_t n = start_pos; n < MemberCount; ++n ) {
104 if( hashes[n] == hash and names[n].name.size( ) == key.size( ) ) {
105 if constexpr( do_full_name_match ) {
106 if( DAW_UNLIKELY( key != names[n].name ) ) {
118 template<
typename... MemberNames>
119 static DAW_CONSTEVAL
bool do_hashes_collide( ) {
121 name_hash<false>( MemberNames::name )... };
123 daw::sort( std::data( hashes ), daw::data_end( hashes ) );
124 return daw::algorithm::adjacent_find( std::data( hashes ),
125 daw::data_end( hashes ),
129 } ) != daw::data_end( hashes );
133 template<
typename ParseState,
typename... JsonMembers>
135 make_locations_info( ) {
136#if defined( DAW_JSON_ALWAYS_FULL_NAME_MATCH )
137 using do_full_name_match = std::true_type;
139 using do_full_name_match =
140 std::bool_constant<ParseState::force_name_equal_check or
141 do_hashes_collide<JsonMembers...>( )>;
143 return locations_info_t<
sizeof...( JsonMembers ),
144 do_full_name_match::value,
typename ParseState::iterator>{
145 { daw::name_hash<false>( JsonMembers::name )... },
146 { location_info_t<typename ParseState::iterator>{ JsonMembers::name }... } };
158 enum class AllMembersMustExist { yes, no };
160 template<std::size_t pos, AllMembersMustExist must_exist,
161 bool from_start =
false, std::size_t N,
typename ParseState,
163 [[nodiscard]] DAW_ATTRIB_INLINE
static constexpr find_result<ParseState>
164 find_class_member( ParseState &parse_state,
165 locations_info_t<N, B, typename ParseState::iterator> &locations,
bool is_nullable,
166 daw::string_view member_name ) {
174 ( not locations[pos].missing( ) ),
175 ( not parse_state.is_closing_brace_checked( ) ) ),
176 missing_member( member_name ),
179 parse_state.trim_left_unchecked( );
180 bool known = not locations[pos].missing( );
182 locations[pos].missing( ),
183 ( not parse_state.empty( ) and parse_state.front( ) !=
'}' ) ) ) {
186 auto const name = parse_name( parse_state );
187 auto const name_pos =
188 locations.template find_name<ParseState::expect_long_strings,
189 ( from_start ? 0 : pos )>( name );
190 if constexpr( must_exist == AllMembersMustExist::yes ) {
192 ErrorReason::UnknownMember,
195#if defined( DAW_JSON_PARSER_DIAGNOSTICS )
196 std::cerr <<
"DEBUG: Unknown member '" << name <<
'\n';
198 if( name_pos >= std::size( locations ) ) {
200 (void)skip_value( parse_state );
201 parse_state.move_next_member_or_end( );
205 if( name_pos == pos ) {
206 locations[pos].set_range( parse_state );
209#if defined( DAW_JSON_PARSER_DIAGNOSTICS )
210 std::cerr <<
"DEBUG: Out of order member '"
211 << locations.names[name_pos].name
212 <<
"' found, looking for '" << locations.names[pos].name
214 << std::abs(
static_cast<long long>( pos ) -
215 static_cast<long long>( name_pos ) )
216 <<
" members ahead in constructor\n";
226 locations[name_pos].set_range( skip_value( parse_state ) );
228 if constexpr( ParseState::is_unchecked_input ) {
229 if( name_pos + 1 < std::size( locations ) ) {
230 parse_state.move_next_member( );
232 parse_state.move_next_member_or_end( );
235 parse_state.move_next_member_or_end( );
239 if( locations[pos].missing( ) ) {
242 if constexpr( ParseState::has_allocator ) {
244 locations[pos].template get_range<ParseState>( ).with_allocator(
248 return find_result<ParseState>{
249 locations[pos].template get_range<ParseState>( ), known };