Skip to content

Commit

Permalink
Update iguana (#368)
Browse files Browse the repository at this point in the history
  • Loading branch information
qicosmos authored Jul 15, 2023
1 parent 3a1f338 commit 3ab1e4c
Show file tree
Hide file tree
Showing 6 changed files with 92 additions and 46 deletions.
10 changes: 10 additions & 0 deletions include/ylt/struct_xml/xml_reader.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
* limitations under the License.
*/
#pragma once
#include <iguana/util.hpp>
#include <iguana/xml_reader.hpp>

namespace struct_xml {
Expand All @@ -32,4 +33,13 @@ 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>;

template <typename T>
inline constexpr std::string_view type_string() {
return iguana::type_string<T>();
}

template <auto T>
inline constexpr std::string_view enum_string() {
return iguana::enum_string<T>();
}
} // namespace struct_xml
4 changes: 2 additions & 2 deletions include/ylt/struct_xml/xml_writer.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,9 @@
#include <iguana/xml_writer.hpp>

namespace struct_xml {
template <typename Stream, typename T>
template <bool pretty = false, typename Stream, typename T>
inline void to_xml(T &&t, Stream &s) {
iguana::to_xml(std::forward<T>(t), s);
iguana::to_xml<pretty>(std::forward<T>(t), s);
}

} // namespace struct_xml
2 changes: 1 addition & 1 deletion include/ylt/thirdparty/iguana/reflection.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,10 @@
#include <variant>
#include <vector>

#include "../frozen/string.h"
#include "detail/itoa.hpp"
#include "detail/string_stream.hpp"
#include "detail/traits.hpp"
#include "frozen/string.h"
#include "frozen/unordered_map.h"

namespace iguana::detail {
Expand Down
2 changes: 1 addition & 1 deletion include/ylt/thirdparty/iguana/xml_reader.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -306,7 +306,7 @@ IGUANA_INLINE void parse_item(T &value, It &&it, It &&end,
key_set.append(key).append(", ");
}
}
if (skip_till_key<cdata_idx>(value, it, end)) {
if (skip_till_key<cdata_idx>(value, it, end)) [[unlikely]] {
match_close_tag(it, end, name);
parse_done = true;
return;
Expand Down
100 changes: 59 additions & 41 deletions include/ylt/thirdparty/iguana/xml_writer.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,19 +6,28 @@

namespace iguana {

template <typename Stream, refletable T>
template <bool pretty, size_t spaces, typename Stream, refletable T>
IGUANA_INLINE void render_xml_value(Stream &ss, T &&t, std::string_view name);

template <typename Stream>
inline void render_tail(Stream &ss, std::string_view str) {
template <bool pretty, size_t spaces, typename Stream>
IGUANA_INLINE void render_tail(Stream &ss, std::string_view str) {
if constexpr (pretty) {
ss.append(spaces, '\t');
}
ss.push_back('<');
ss.push_back('/');
ss.append(str.data(), str.size());
ss.push_back('>');
if constexpr (pretty) {
ss.push_back('\n');
}
}

template <typename Stream>
template <bool pretty, size_t spaces, typename Stream>
inline void render_head(Stream &ss, std::string_view str) {
if constexpr (pretty) {
ss.append(spaces, '\t');
}
ss.push_back('<');
ss.append(str.data(), str.size());
ss.push_back('>');
Expand Down Expand Up @@ -48,8 +57,11 @@ IGUANA_INLINE void render_value(Stream &ss, const T &value) {
}
}

template <typename Stream, map_container T>
template <bool pretty, size_t spaces, typename Stream, map_container T>
inline void render_xml_attr(Stream &ss, const T &value, std::string_view name) {
if constexpr (pretty) {
ss.append(spaces, '\t');
}
ss.push_back('<');
ss.append(name.data(), name.size());
for (auto [k, v] : value) {
Expand All @@ -63,61 +75,62 @@ inline void render_xml_attr(Stream &ss, const T &value, std::string_view name) {
ss.push_back('>');
}

template <typename Stream, attr_t T>
IGUANA_INLINE void render_xml_value(Stream &ss, const T &value,
std::string_view name) {
render_xml_attr(ss, value.attr(), name);
render_xml_value(ss, value.value(), name);
render_tail(ss, name);
}

template <typename Stream, plain_t T>
template <bool pretty, size_t spaces, typename Stream, plain_t T>
IGUANA_INLINE void render_xml_value(Stream &ss, const T &value,
std::string_view name) {
render_value(ss, value);
render_tail(ss, name);
render_tail<pretty, 0>(ss, name);
}

template <typename Stream, optional_t T>
template <bool pretty, size_t spaces, typename Stream, optional_t T>
IGUANA_INLINE void render_xml_value(Stream &ss, const T &value,
std::string_view name) {
if (value) {
render_xml_value(ss, *value, name);
render_xml_value<pretty, spaces>(ss, *value, name);
}
else {
render_tail(ss, name);
render_tail<pretty, 0>(ss, name);
}
}

template <typename Stream, unique_ptr_t T>
template <bool pretty, size_t spaces, typename Stream, unique_ptr_t T>
IGUANA_INLINE void render_xml_value(Stream &ss, const T &value,
std::string_view name) {
if (value) {
render_xml_value(ss, *value, name);
render_xml_value<pretty, spaces>(ss, *value, name);
}
else {
render_tail(ss, name);
render_tail<pretty, 0>(ss, name);
}
}

template <typename Stream, sequence_container_t T>
template <bool pretty, size_t spaces, typename Stream, attr_t T>
IGUANA_INLINE void render_xml_value(Stream &ss, const T &value,
std::string_view name) {
render_xml_attr<pretty, spaces>(ss, value.attr(), name);
render_xml_value<pretty, spaces>(ss, value.value(), name);
}

template <bool pretty, size_t spaces, typename Stream, sequence_container_t T>
IGUANA_INLINE void render_xml_value(Stream &ss, const T &value,
std::string_view name) {
using value_type = typename std::remove_cvref_t<T>::value_type;
for (const auto &v : value) {
if constexpr (attr_t<value_type>) {
render_xml_attr(ss, v.attr(), name);
render_xml_value(ss, v.value(), name);
render_xml_value<pretty, spaces>(ss, v, name);
}
else {
render_head(ss, name);
render_xml_value(ss, v, name);
render_head<pretty, spaces>(ss, name);
render_xml_value<pretty, spaces>(ss, v, name);
}
}
}

template <typename Stream, refletable T>
template <bool pretty, size_t spaces, typename Stream, refletable T>
IGUANA_INLINE void render_xml_value(Stream &ss, T &&t, std::string_view name) {
if constexpr (pretty) {
ss.push_back('\n');
}
for_each(std::forward<T>(t),
[&](const auto &v, auto i) IGUANA__INLINE_LAMBDA {
using M = decltype(iguana_reflect_members(std::forward<T>(t)));
Expand All @@ -129,38 +142,43 @@ IGUANA_INLINE void render_xml_value(Stream &ss, T &&t, std::string_view name) {
get_name<std::decay_t<T>, Idx>().size());
static_assert(Idx < Count);
if constexpr (sequence_container_t<value_type>) {
render_xml_value(ss, t.*v, tag_name);
render_xml_value<pretty, spaces + 1>(ss, t.*v, tag_name);
}
else if constexpr (attr_t<value_type>) {
render_xml_attr(ss, (t.*v).attr(), tag_name);
render_xml_value(ss, (t.*v).value(), tag_name);
render_xml_value<pretty, spaces + 1>(ss, t.*v, tag_name);
}
else if constexpr (cdata_t<value_type>) {
ss.append("<![CDATA[").append((t.*v).value()).append("]]>");
if constexpr (pretty) {
ss.append(spaces + 1, '\t');
ss.append("<![CDATA[").append((t.*v).value()).append("]]>\n");
}
else {
ss.append("<![CDATA[").append((t.*v).value()).append("]]>");
}
}
else {
render_head(ss, tag_name);
render_xml_value(ss, t.*v, tag_name);
render_head<pretty, spaces + 1>(ss, tag_name);
render_xml_value<pretty, spaces + 1>(ss, t.*v, tag_name);
}
});
render_tail(ss, name);
render_tail<pretty, spaces>(ss, name);
}

template <typename Stream, attr_t T>
template <bool pretty = false, typename Stream, attr_t T>
IGUANA_INLINE void to_xml(T &&t, Stream &s) {
using value_type = typename std::decay_t<T>::value_type;
static_assert(refletable<value_type>, "value_type must be refletable");
constexpr std::string_view root_name = std::string_view(
get_name<value_type>().data(), get_name<value_type>().size());
render_xml_attr(s, std::forward<T>(t).attr(), root_name);
render_xml_value(s, std::forward<T>(t).value(), root_name);
render_xml_value<pretty, 0>(s, std::forward<T>(t), root_name);
}

template <typename Stream, refletable T>
template <bool pretty = false, typename Stream, refletable T>
IGUANA_INLINE void to_xml(T &&t, Stream &s) {
constexpr std::string_view root_name = std::string_view(
get_name<std::decay_t<T>>().data(), get_name<std::decay_t<T>>().size());
render_head(s, root_name);
render_xml_value(s, std::forward<T>(t), root_name);
render_head<pretty, 0>(s, root_name);
render_xml_value<pretty, 0>(s, std::forward<T>(t), root_name);
}

} // namespace iguana
} // namespace iguana
20 changes: 19 additions & 1 deletion src/struct_xml/examples/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -165,7 +165,24 @@ void basic_usage() {
std::string str;
struct_xml::to_xml(p, str);

std::cout << str;
std::cout << str << "\n";

std::string pretty_xml_str;
struct_xml::to_xml</*pretty=*/true>(p, pretty_xml_str);

std::cout << pretty_xml_str;
}

enum class Color { red, black };

enum Size { small, large };

class my_message {};

void type_to_string() {
static_assert(struct_xml::type_string<my_message>() == "my_message");
static_assert(struct_xml::enum_string<Color::red>() == "Color::red");
static_assert(struct_xml::enum_string<Size::small>() == "small");
}

void get_error() {
Expand Down Expand Up @@ -216,6 +233,7 @@ void required_field() {

int main() {
basic_usage();
type_to_string();
nested_xml();
attribute();
get_error();
Expand Down

0 comments on commit 3ab1e4c

Please sign in to comment.