Skip to content

Commit

Permalink
Merge pull request #195 from bbbgan/master
Browse files Browse the repository at this point in the history
  • Loading branch information
qicosmos authored Jul 13, 2023
2 parents 02539c1 + e9bcbba commit 7f5ddb1
Show file tree
Hide file tree
Showing 5 changed files with 219 additions and 89 deletions.
50 changes: 42 additions & 8 deletions example/xml_example.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -55,12 +55,16 @@ void some_type_example() {
std::cout << "\n description : " << *st.description << "\n";
std::cout << st.child->key1 << " " << st.child->key2 << "\n\n";
std::cout << "========== serialize person_t =========\n";

std::string ss;
iguana::to_xml(st, ss);
std::cout << ss << "\n\n";
std::cout << "minify serialize:\n";
std::cout << ss << "\n";

some_type_t st1;
iguana::from_xml(st1, ss);
std::string ss1;
iguana::to_xml<true>(st, ss1);
std::cout << "pretty serialize:\n";
std::cout << ss1;
}

struct book_t {
Expand Down Expand Up @@ -88,7 +92,13 @@ void lib_example() {
iguana::from_xml(lib, str);
std::string ss;
iguana::to_xml(lib, ss);
std::cout << ss << "\n\n";
std::cout << "minify serialize:\n";
std::cout << ss << "\n";

std::string ss1;
iguana::to_xml<true>(lib, ss1);
std::cout << "pretty serialize:\n";
std::cout << ss1;
}
{
std::cout << "========= serialize library with attr ========\n";
Expand All @@ -97,7 +107,13 @@ void lib_example() {

std::string ss;
iguana::to_xml(lib, ss);
std::cout << ss << "\n\n";
std::cout << "minify serialize:\n";
std::cout << ss << "\n";

std::string ss1;
iguana::to_xml<true>(lib, ss1);
std::cout << "pretty serialize:\n";
std::cout << ss1;
}
}

Expand Down Expand Up @@ -131,7 +147,13 @@ void package_example() {
std::string ss;
iguana::to_xml(package, ss);
std::cout << "========= serialize package_t with attr ========\n";
std::cout << ss << "\n\n";
std::cout << "minify serialize:\n";
std::cout << ss << "\n";

std::string ss1;
iguana::to_xml<true>(package, ss1);
std::cout << "pretty serialize:\n";
std::cout << ss1;
}

struct base_t {
Expand Down Expand Up @@ -195,7 +217,13 @@ void cdata_example() {
std::cout << "========= serialize cdata ========\n";
std::string ss;
iguana::to_xml(node, ss);
std::cout << ss << "\n\n";
std::cout << "minify serialize:\n";
std::cout << ss << "\n";

std::string ss1;
iguana::to_xml<true>(node, ss1);
std::cout << "pretty serialize:\n";
std::cout << ss1;
}

struct city_t {
Expand Down Expand Up @@ -242,7 +270,13 @@ void province_example() {
std::cout << "========= serialize province ========\n";
std::string ss;
iguana::to_xml(p, ss);
std::cout << ss << "n\n";
std::cout << "minify serialize:\n";
std::cout << ss << "\n";

std::string ss1;
iguana::to_xml<true>(p, ss1);
std::cout << "pretty serialize:\n";
std::cout << ss1;
}

int main(void) {
Expand Down
2 changes: 1 addition & 1 deletion iguana/reflection.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
#include <variant>
#include <vector>

#include "../frozen/string.h"
#include "frozen/string.h"
#include "frozen/unordered_map.h"

#include "detail/itoa.hpp"
Expand Down
2 changes: 1 addition & 1 deletion iguana/xml_reader.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -292,7 +292,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
99 changes: 58 additions & 41 deletions 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 All @@ -43,8 +52,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 @@ -58,58 +70,59 @@ 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 @@ -121,35 +134,39 @@ 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
Loading

0 comments on commit 7f5ddb1

Please sign in to comment.