Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

remove rapidxml #361

Merged
merged 2 commits into from
Jul 12, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 9 additions & 13 deletions include/ylt/struct_xml/xml_reader.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,22 +18,18 @@

namespace struct_xml {

template <int Flags = 0, typename T>
inline bool from_xml(T &&t, char *buf) {
return iguana::from_xml<Flags>(std::forward<T>(t), buf);
template <typename T, typename View>
inline void from_xml(T &&t, const View &str) {
iguana::from_xml(std::forward<T>(t), str);
}

template <int Flags = 0, typename T>
inline bool from_xml(T &&t, const std::string &str) {
return from_xml<Flags>(std::forward<T>(t), str.data());
template <typename Num>
inline Num get_number(std::string_view str) {
return iguana::get_number<Num>(str);
}

template <int Flags = 0, typename T>
inline bool from_xml(T &&t, std::string_view str) {
return from_xml<Flags>(std::forward<T>(t), str.data());
}

inline std::string get_last_read_err() { return iguana::get_last_read_err(); }
template <typename T, typename map_type = std::unordered_map<std::string_view,
std::string_view>>
using xml_attr_t = iguana::xml_attr_t<T, map_type>;

using any_t = iguana::any_t;
} // namespace struct_xml
4 changes: 0 additions & 4 deletions include/ylt/struct_xml/xml_writer.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,4 @@ inline void to_xml(T &&t, Stream &s) {
iguana::to_xml(std::forward<T>(t), s);
}

template <int Flags = 0, typename Stream, typename T>
inline bool to_xml_pretty(T &&t, Stream &s) {
return iguana::to_xml_pretty<Flags>(std::forward<T>(t), s);
}
} // namespace struct_xml
166 changes: 112 additions & 54 deletions include/ylt/thirdparty/iguana/json_reader.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,9 @@ void from_json(T &value, It &&it, It &&end);

namespace detail {

template <sequence_container U, class It>
IGUANA_INLINE void parse_item(U &value, It &&it, It &&end);

template <str_t U, class It>
IGUANA_INLINE void parse_escape(U &value, It &&it, It &&end) {
if (it == end)
Expand Down Expand Up @@ -101,9 +104,76 @@ IGUANA_INLINE void parse_item(U &value, It &&it, It &&end) {
parse_item(reinterpret_cast<T &>(value), it, end);
}

template <str_t U, class It>
IGUANA_INLINE void parse_item(U &value, It &&it, It &&end, bool skip = false) {
if (!skip) {
template <bool skip = false, char_t U, class It>
IGUANA_INLINE void parse_item(U &value, It &&it, It &&end) {
if constexpr (!skip) {
skip_ws(it, end);
match<'"'>(it, end);
}
if (it == end) [[unlikely]]
throw std::runtime_error("Unxpected end of buffer");
if (*it == '\\') [[unlikely]] {
if (++it == end) [[unlikely]] {
throw std::runtime_error("Unxpected end of buffer");
}
else if (*it == 'n') {
value = '\n';
}
else if (*it == 't') {
value = '\t';
}
else if (*it == 'r') {
value = '\r';
}
else if (*it == 'b') {
value = '\b';
}
else if (*it == 'f') {
value = '\f';
}
else [[unlikely]] {
value = *it;
}
}
else {
value = *it;
}
++it;
if constexpr (!skip) {
match<'"'>(it, end);
}
}

template <bool_t U, class It>
IGUANA_INLINE void parse_item(U &&value, It &&it, It &&end) {
skip_ws(it, end);

if (it < end) [[likely]] {
switch (*it) {
case 't': {
++it;
match<"rue">(it, end);
value = true;
break;
}
case 'f': {
++it;
match<"alse">(it, end);
value = false;
break;
}
[[unlikely]] default
: throw std::runtime_error("Expected true or false");
}
}
else [[unlikely]] {
throw std::runtime_error("Expected true or false");
}
}

template <bool skip = false, str_t U, class It>
IGUANA_INLINE void parse_item(U &value, It &&it, It &&end) {
if constexpr (!skip) {
skip_ws(it, end);
match<'"'>(it, end);
}
Expand Down Expand Up @@ -148,11 +218,11 @@ IGUANA_INLINE void parse_item(U &value, It &&it, It &&end, bool skip = false) {
}
}

template <str_view_t U, class It>
IGUANA_INLINE void parse_item(U &value, It &&it, It &&end, bool skip = false) {
template <bool skip = false, str_view_t U, class It>
IGUANA_INLINE void parse_item(U &value, It &&it, It &&end) {
static_assert(std::contiguous_iterator<std::decay_t<It>>,
"must be contiguous");
if (!skip) {
if constexpr (!skip) {
skip_ws(it, end);
match<'"'>(it, end);
}
Expand All @@ -173,8 +243,23 @@ IGUANA_INLINE void parse_item(U &value, It &&it, It &&end, bool skip = false) {
template <fixed_array U, class It>
IGUANA_INLINE void parse_item(U &value, It &&it, It &&end) {
using T = std::remove_reference_t<U>;
constexpr auto n = sizeof(T) / sizeof(decltype(std::declval<T>()[0]));
skip_ws(it, end);

if constexpr (std::is_same_v<char, std::remove_reference_t<
decltype(std::declval<T>()[0])>>) {
if (*it == '"') {
match<'"'>(it, end);
auto value_it = std::begin(value);
for (size_t i = 0; i < n; ++i) {
if (*it != '"') [[likely]] {
parse_item<true>(*value_it++, it, end);
}
}
match<'"'>(it, end);
return;
}
}
match<'['>(it, end);
skip_ws(it, end);
if (it == end) {
Expand All @@ -185,11 +270,7 @@ IGUANA_INLINE void parse_item(U &value, It &&it, It &&end) {
++it;
return;
}

constexpr auto n = sizeof(T) / sizeof(decltype(std::declval<T>()[0]));

auto value_it = std::begin(value);

for (size_t i = 0; i < n; ++i) {
parse_item(*value_it++, it, end);
skip_ws(it, end);
Expand Down Expand Up @@ -299,41 +380,14 @@ IGUANA_INLINE void parse_item(U &value, It &&it, It &&end) {
match<']'>(it, end);
}

template <bool_t U, class It>
IGUANA_INLINE void parse_item(U &value, It &&it, It &&end) {
skip_ws(it, end);

if (it < end) [[likely]] {
switch (*it) {
case 't': {
++it;
match<"rue">(it, end);
value = true;
break;
}
case 'f': {
++it;
match<"alse">(it, end);
value = false;
break;
}
[[unlikely]] default
: throw std::runtime_error("Expected true or false");
}
}
else [[unlikely]] {
throw std::runtime_error("Expected true or false");
}
}

template <optional U, class It>
IGUANA_INLINE void parse_item(U &value, It &&it, It &&end) {
skip_ws(it, end);
if (it < end && *it == '"') {
if (it < end && *it == '"') [[likely]] {
++it;
}
using T = std::remove_reference_t<U>;
if (it == end) {
if (it == end) [[unlikely]] {
throw std::runtime_error("Unexexpected eof");
}
if (*it == 'n') {
Expand All @@ -350,28 +404,33 @@ IGUANA_INLINE void parse_item(U &value, It &&it, It &&end) {
using value_type = typename T::value_type;
value_type t;
if constexpr (str_t<value_type> || str_view_t<value_type>) {
parse_item(t, it, end, true);
parse_item<true>(t, it, end);
}
else {
parse_item(t, it, end);
}

value = std::move(t);
}
}

template <char_t U, class It>
template <unique_ptr_t U, class It>
IGUANA_INLINE void parse_item(U &value, It &&it, It &&end) {
// TODO: this does not handle escaped chars
skip_ws(it, end);
match<'"'>(it, end);
if (it == end) [[unlikely]]
throw std::runtime_error("Unxpected end of buffer");
if (*it == '\\') [[unlikely]]
if (++it == end) [[unlikely]]
throw std::runtime_error("Unxpected end of buffer");
value = *it++;
match<'"'>(it, end);
if (it < end && *it == '"') [[likely]] {
++it;
}
if (it == end) [[unlikely]] {
throw std::runtime_error("Unexexpected eof");
}
if (*it == 'n') {
++it;
match<"ull">(it, end);
}
else {
using value_type = typename std::remove_reference_t<U>::element_type;
value = std::make_unique<value_type>();
parse_item(*value, it, end);
}
}

IGUANA_INLINE void skip_object_value(auto &&it, auto &&end) {
Expand Down Expand Up @@ -399,7 +458,6 @@ IGUANA_INLINE void skip_object_value(auto &&it, auto &&end) {
continue;
}
}

break;
}
}
Expand Down Expand Up @@ -437,7 +495,7 @@ IGUANA_INLINE void from_json(T &value, It &&it, It &&end) {
// compile time versions of keys
it = start;
static thread_local std::string static_key{};
detail::parse_item(static_key, it, end, true);
detail::parse_item<true>(static_key, it, end);
key = static_key;
}
else [[likely]] {
Expand All @@ -451,7 +509,7 @@ IGUANA_INLINE void from_json(T &value, It &&it, It &&end) {
}
else {
static thread_local std::string static_key{};
detail::parse_item(static_key, it, end, false);
detail::parse_item(static_key, it, end);
key = static_key;
}

Expand Down
36 changes: 22 additions & 14 deletions include/ylt/thirdparty/iguana/json_util.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -52,13 +52,6 @@ constexpr inline bool is_basic_string_view = false;
template <typename T>
constexpr inline bool is_basic_string_view<std::basic_string_view<T>> = true;

template <typename T>
concept str_view_t = is_basic_string_view<std::remove_reference_t<T>>;

template <class T>
concept str_t =
std::convertible_to<std::decay_t<T>, std::string_view> && !str_view_t<T>;

template <typename Type>
constexpr inline bool is_std_vector_v = false;

Expand Down Expand Up @@ -103,6 +96,15 @@ concept array = requires(Type arr) {
template <typename Type>
concept fixed_array = c_array<Type> || array<Type>;

template <typename T>
concept str_view_t = is_basic_string_view<std::remove_reference_t<T>>;

// eliminate char a[]
template <class T>
concept str_t =
std::convertible_to<std::decay_t<T>, std::string_view> && !str_view_t<T> &&
!c_array<T>;

template <typename Type>
concept tuple = !array<Type> && requires(Type tuple) {
std::get<0>(tuple);
Expand Down Expand Up @@ -135,10 +137,6 @@ concept sequence_container = is_std_list_v<std::remove_reference_t<Type>> ||
is_std_vector_v<std::remove_reference_t<Type>> ||
is_std_deque_v<std::remove_reference_t<Type>>;

template <class T>
concept non_refletable = container<T> || c_array<T> || tuple<T> ||
optional<T> || std::is_fundamental_v<T>;

template <class T>
concept associat_container_t =
is_associat_container<std::remove_cvref_t<T>>::value;
Expand All @@ -151,8 +149,18 @@ template <class T>
concept tuple_t = is_tuple<std::remove_cvref_t<T>>::value;

template <class T>
concept string_container_t =
std::convertible_to<std::decay_t<T>, std::string_view>;
concept string_container_t = str_t<T> || str_view_t<T>;

template <typename Type>
concept unique_ptr_t = requires(Type ptr) {
ptr.operator*();
typename std::remove_cvref_t<Type>::element_type;
}
&&!requires(Type ptr, Type ptr2) { ptr = ptr2; };

template <class T>
concept non_refletable = container<T> || c_array<T> || tuple<T> ||
optional<T> || unique_ptr_t<T> || std::is_fundamental_v<T>;

template <size_t N>
struct string_literal {
Expand Down Expand Up @@ -245,7 +253,7 @@ IGUANA_INLINE void skip_ws(auto &&it, auto &&end) {
IGUANA_INLINE void skip_ws_no_comments(auto &&it, auto &&end) {
while (it != end) {
// assuming ascii
if (static_cast<uint8_t>(*it) < 33) {
if (static_cast<uint8_t>(*it) < 33) [[likely]] {
++it;
}
else {
Expand Down
Loading