17 #include <daw/algorithms/daw_algorithm_adjacent_find.h>
18 #include <daw/daw_consteval.h>
19 #include <daw/daw_likely.h>
20 #include <daw/daw_logic.h>
21 #include <daw/daw_sort_n.h>
22 #include <daw/daw_string_view.h>
23 #include <daw/daw_traits.h>
24 #include <daw/daw_uint_buffer.h>
27 #include <daw/stdinc/data_access.h>
29 #if defined( DAW_JSON_PARSER_DIAGNOSTICS )
36 namespace json_details {
37 template<
bool FullNameMatch,
typename CharT>
38 struct location_info_t {
39 daw::string_view name;
40 CharT *first =
nullptr;
41 CharT *last =
nullptr;
42 CharT *class_first =
nullptr;
43 CharT *class_last =
nullptr;
44 std::size_t counter = 0;
46 [[nodiscard]]
inline 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 auto result = range_t( first, last, class_first, class_last );
63 result.counter = counter;
68 template<
typename CharT>
69 struct location_info_t<false, CharT> {
70 CharT *first =
nullptr;
71 CharT *last =
nullptr;
72 CharT *class_first =
nullptr;
73 CharT *class_last =
nullptr;
74 std::size_t counter = 0;
76 [[nodiscard]]
inline constexpr
bool missing( )
const {
77 return first ==
nullptr;
80 template<
typename ParseState>
81 constexpr
void set_range( ParseState
const &parse_state ) {
82 first = parse_state.first;
83 last = parse_state.last;
84 class_first = parse_state.class_first;
85 class_last = parse_state.class_last;
86 counter = parse_state.counter;
89 template<
typename ParseState>
90 constexpr
auto get_range( )
const {
92 using range_t =
typename ParseState::without_allocator_type;
93 auto result = range_t( first, last, class_first, class_last );
94 result.counter = counter;
103 template<std::size_t MemberCount,
typename CharT,
104 bool DoFullNameMatch =
true>
105 struct locations_info_t {
106 using value_type = location_info_t<DoFullNameMatch, CharT>;
107 using reference = value_type &;
108 using const_reference = value_type
const &;
109 static constexpr
bool do_full_name_match = DoFullNameMatch;
110 daw::UInt32 hashes[MemberCount];
111 value_type names[MemberCount];
113 constexpr const_reference operator[]( std::size_t idx )
const {
118 constexpr reference operator[]( std::size_t idx ) {
123 static constexpr std::size_t size( ) {
127 template<
bool expect_
long_
strings, std::
size_t start_pos>
128 [[nodiscard]] DAW_ATTRIB_INLINE constexpr std::size_t
129 find_name( daw::string_view key )
const {
130 UInt32
const hash = name_hash<expect_long_strings>( key );
131 #if defined( DAW_JSON_BUGFIX_MSVC_EVAL_ORDER_002 )
133 for( std::size_t n = 0; n < MemberCount; ++n ) {
135 for( std::size_t n = start_pos; n < MemberCount; ++n ) {
137 if( hashes[n] == hash ) {
138 if constexpr( do_full_name_match ) {
139 if( DAW_UNLIKELY( key != names[n].name ) ) {
151 template<
typename... MemberNames>
152 static inline DAW_CONSTEVAL
bool do_hashes_collide( ) {
153 daw::UInt32 hashes[
sizeof...( MemberNames )]{
154 name_hash<false>( MemberNames::name )... };
156 daw::sort( std::data( hashes ), daw::data_end( hashes ) );
157 return daw::algorithm::adjacent_find(
158 std::data( hashes ), daw::data_end( hashes ),
161 } ) != daw::data_end( hashes );
165 template<
typename ParseState,
typename... JsonMembers>
167 make_locations_info( ) {
168 using CharT =
typename ParseState::CharT;
169 #if defined( DAW_JSON_ALWAYS_FULL_NAME_MATCH )
170 constexpr
bool do_full_name_match =
true;
171 return locations_info_t<
sizeof...( JsonMembers ), CharT,
173 { daw::name_hash<false>( JsonMembers::name )... },
174 { location_info_t<do_full_name_match, CharT>{
175 JsonMembers::name }... } };
178 constexpr
bool do_full_name_match =
179 ParseState::force_name_equal_check or
180 do_hashes_collide<JsonMembers...>( );
181 if constexpr( do_full_name_match ) {
182 return locations_info_t<
sizeof...( JsonMembers ), CharT,
184 { daw::name_hash<false>( JsonMembers::name )... },
185 { location_info_t<do_full_name_match, CharT>{
186 JsonMembers::name }... } };
188 return locations_info_t<
sizeof...( JsonMembers ), CharT,
190 { daw::name_hash<false>( JsonMembers::name )... }, {} };
204 enum class AllMembersMustExist { yes, no };
206 template<std::size_t pos, AllMembersMustExist must_exist,
207 bool from_start =
false, std::size_t N,
typename ParseState,
208 bool B,
typename CharT>
209 [[nodiscard]] DAW_ATTRIB_INLINE
static constexpr find_result<ParseState>
210 find_class_member( ParseState &parse_state,
211 locations_info_t<N, CharT, B> &locations,
212 bool is_nullable, daw::string_view member_name ) {
219 nsc_or( is_nullable, ( not locations[pos].missing( ) ),
220 ( not parse_state.is_closing_brace_checked( ) ) ),
221 missing_member( member_name ), parse_state );
223 parse_state.trim_left_unchecked( );
224 bool known = not locations[pos].missing( );
226 locations[pos].missing( ),
227 ( not parse_state.empty( ) and parse_state.front( ) !=
'}' ) ) ) {
230 auto const name = parse_name( parse_state );
231 auto const name_pos =
232 locations.template find_name<ParseState::expect_long_strings,
233 ( from_start ? 0 : pos )>( name );
234 if constexpr( must_exist == AllMembersMustExist::yes ) {
236 ErrorReason::UnknownMember, parse_state );
238 #if defined( DAW_JSON_PARSER_DIAGNOSTICS )
239 std::cerr <<
"DEBUG: Unknown member '" << name <<
'\n';
241 if( name_pos >= std::size( locations ) ) {
243 (void)skip_value( parse_state );
244 parse_state.move_next_member_or_end( );
248 if( name_pos == pos ) {
249 locations[pos].set_range( parse_state );
252 #if defined( DAW_JSON_PARSER_DIAGNOSTICS )
253 std::cerr <<
"DEBUG: Out of order member '"
254 << locations.names[name_pos].name
255 <<
"' found, looking for '" << locations.names[pos].name
257 << std::abs(
static_cast<long long>( pos ) -
258 static_cast<long long>( name_pos ) )
259 <<
" members ahead in constructor\n";
269 locations[name_pos].set_range( skip_value( parse_state ) );
271 if constexpr( ParseState::is_unchecked_input ) {
272 if( name_pos + 1 < std::size( locations ) ) {
273 parse_state.move_next_member( );
275 parse_state.move_next_member_or_end( );
278 parse_state.move_next_member_or_end( );
282 if( locations[pos].missing( ) ) {
285 if constexpr( ParseState::has_allocator ) {
287 locations[pos].template get_range<ParseState>( ).with_allocator(
291 return find_result<ParseState>{
292 locations[pos].template get_range<ParseState>( ), known };
#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.
#define DAW_JSON_CPP23_STATIC_CALL_OP
This is in addition to the parse policy. Always do a full name match instead of sometimes relying on ...
#define DAW_JSON_MAKE_LOC_INFO_CONSTEVAL
Customization point traits.
#define DAW_JSON_VER
The version string used in namespace definitions. Must be a valid namespace name.