in include/ylt/standalone/iguana/xml_reader.hpp [397:486]
IGUANA_INLINE void xml_parse_item(T &value, It &&it, It &&end,
std::string_view name) {
using U = std::decay_t<T>;
constexpr auto cdata_idx = get_type_index<is_cdata_t, U>();
skip_till<'>'>(it, end);
++it;
if (skip_till_close_tag<cdata_idx>(value, it, end)) {
match_close_tag(it, end, name);
return;
}
auto start = it;
skip_till_greater_or_space(it, end);
std::string_view key =
std::string_view{&*start, static_cast<size_t>(std::distance(start, it))};
[[maybe_unused]] std::string key_set;
bool parse_done = false;
// sequential parse
ylt::reflection::for_each(value, [&](auto &field, auto st_key, auto index) {
#if defined(_MSC_VER) && _MSVC_LANG < 202002L
// seems MVSC can't pass a constexpr value to lambda
constexpr auto cdata_idx = get_type_index<is_cdata_t, U>();
#endif
using item_type = std::remove_reference_t<decltype(field)>;
if constexpr (cdata_v<item_type>) {
return;
}
if (parse_done || key != st_key)
IGUANA_UNLIKELY { return; }
if constexpr (!cdata_v<item_type>) {
xml_parse_item(field, it, end, key);
if constexpr (iguana::has_iguana_required_arr_v<U>) {
key_set.append(key).append(", ");
}
}
if (skip_till_close_tag<cdata_idx>(value, it, end))
IGUANA_UNLIKELY {
match_close_tag(it, end, name);
parse_done = true;
return;
}
start = it;
skip_till_greater_or_space(it, end);
key = std::string_view{&*start,
static_cast<size_t>(std::distance(start, it))};
});
if (parse_done)
IGUANA_UNLIKELY {
check_required<U>(key_set);
return;
}
// map parse
while (true) {
static auto frozen_map = ylt::reflection::get_variant_map<U>();
const auto &member_it = frozen_map.find(key);
if (member_it != frozen_map.end())
IGUANA_LIKELY {
std::visit(
[&](auto offset) IGUANA__INLINE_LAMBDA {
using value_type = typename decltype(offset)::type;
if constexpr (!cdata_v<value_type>) {
auto member_ptr =
(value_type *)((char *)(&value) + offset.value);
xml_parse_item(*member_ptr, it, end, key);
if constexpr (iguana::has_iguana_required_arr_v<U>) {
key_set.append(key).append(", ");
}
}
},
member_it->second);
}
else
IGUANA_UNLIKELY {
#ifdef THROW_UNKNOWN_KEY
throw std::runtime_error("Unknown key: " + std::string(key));
#else
skip_object_value(it, end, key);
#endif
}
if (skip_till_close_tag<cdata_idx>(value, it, end)) {
match_close_tag(it, end, name);
check_required<U>(key_set);
return;
}
start = it;
skip_till_greater_or_space(it, end);
key = std::string_view{&*start,
static_cast<size_t>(std::distance(start, it))};
}
}