Skip to content

Commit

Permalink
Merge pull request #150 from bbbgan/master
Browse files Browse the repository at this point in the history
  • Loading branch information
qicosmos authored May 9, 2023
2 parents f2dfef5 + 7f4c239 commit 15001b8
Show file tree
Hide file tree
Showing 5 changed files with 75 additions and 51 deletions.
28 changes: 18 additions & 10 deletions example/xml_example.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -317,28 +317,36 @@ void test_vector() {
std::cout << ss << std::endl;
}

struct item_itunes_t {
iguana::xml::namespace_t<std::string_view> itunes_author;
iguana::xml::namespace_t<std::string_view> itunes_subtitle;
iguana::xml::namespace_t<int> itunes_user;
};
REFLECTION(item_itunes_t, itunes_author, itunes_subtitle, itunes_user);
struct item_t {
iguana::xml::namespace_t itunes_author;
iguana::xml::namespace_t itunes_subtitle;
iguana::xml::namespace_t<item_itunes_t> item_itunes;
};
REFLECTION(item_t, itunes_author, itunes_subtitle);
REFLECTION(item_t, item_itunes);
void test_namespace() {
std::cout << "********** test namespace ************" << std::endl;
std::string str = R"(
<item>
<itunes:author>Jupiter Broadcasting</itunes:author>
<itunes:subtitle>Linux enthusiasts talk top news stories, subtitle</itunes:subtitle>
<item:itunes>
<itunes:author>Jupiter Broadcasting</itunes:author>
<itunes:subtitle>Linux enthusiasts talk top news stories, subtitle</itunes:subtitle>
<itunes:user>10086</itunes:user>
</item:itunes>
</item>
)";
item_t it;
iguana::xml::from_xml(it, str.data());
std::cout << "author : " << it.itunes_author.get<std::string_view>().second
<< std::endl;
std::cout << "subtitle : "
<< it.itunes_subtitle.get<std::string_view>().second << std::endl;
auto itunes = it.item_itunes.get();
std::cout << "author : " << itunes.itunes_author.get() << "\n";
std::cout << "subtitle : " << itunes.itunes_subtitle.get() << "\n";
std::cout << "user : " << itunes.itunes_user.get() << "\n";
std::string ss;
iguana::xml::to_xml(ss, it);
std::cout << "to_xml" << std::endl << ss << std::endl;
std::cout << "to_xml" << std::endl << ss << "\n";
}

struct package_t {
Expand Down
8 changes: 8 additions & 0 deletions iguana/type_traits.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,4 +34,12 @@ template <typename T> constexpr inline bool is_std_pair_v = false;
template <typename T, typename K>
constexpr inline bool is_std_pair_v<std::pair<T, K>> = true;

namespace xml {
template <typename T> class namespace_t;
template <typename T> constexpr inline bool is_namespace_v = false;

template <typename T>
constexpr inline bool is_namespace_v<namespace_t<T>> = true;
} // namespace xml

} // namespace iguana
25 changes: 16 additions & 9 deletions iguana/xml_reader.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -69,17 +69,15 @@ class any_t {
std::string_view value_;
};

class namespace_t {
template <typename T> class namespace_t {
public:
explicit namespace_t(std::string_view value) : value_(value) {}
using value_type = T;
explicit namespace_t(T &&value) : value_(std::forward<T>(value)) {}
explicit namespace_t() {}
template <typename T> std::pair<bool, T> get() const {
return value_.get<T>();
}
any_t get_value() const { return value_; }
const T &get() const { return value_; }

private:
any_t value_;
T value_;
};

template <typename T>
Expand Down Expand Up @@ -125,7 +123,7 @@ inline void parse_item(rapidxml::xml_node<char> *node, T &t,
} else {
t = parse_num<U>(value);
}
} else if constexpr (is_str_v<U> || std::is_same_v<namespace_t, U>) {
} else if constexpr (is_str_v<U>) {
t = U{value};
} else if constexpr (is_reflection_v<U>) {
do_read(node, t);
Expand All @@ -139,6 +137,15 @@ inline void parse_item(rapidxml::xml_node<char> *node, T &t,
} else if constexpr (is_std_pair_v<U>) {
parse_item(node, t.first, value);
parse_attribute(node, t.second);
} else if constexpr (is_namespace_v<U>) {
using value_type = typename U::value_type;
value_type ns;
if constexpr (is_reflection_v<value_type>) {
do_read(node, ns);
} else {
parse_item(node, ns, value);
}
t = T{std::move(ns)};
} else {
static_assert(!sizeof(T), "don't support this type!!");
}
Expand All @@ -165,7 +172,7 @@ inline void do_read(rapidxml::xml_node<char> *node, T &&t) {
parse_attribute(node, t.*member_ptr);
} else {
rapidxml::xml_node<char> *n = nullptr;
if constexpr (std::is_same_v<item_type, namespace_t>) {
if constexpr (is_namespace_v<item_type>) {
constexpr auto index_ul = find_underline(key.data());
static_assert(index_ul < key.size(),
"'_' is needed in namesapce_t value name");
Expand Down
26 changes: 14 additions & 12 deletions iguana/xml_writer.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@ template <typename Stream, typename T>
inline void to_xml_impl(Stream &s, T &&t, std::string_view name = "");

class any_t;
class namespace_t;
constexpr inline size_t find_underline(const char *);

template <typename Stream, typename T>
Expand Down Expand Up @@ -95,14 +94,7 @@ inline void render_xml_attr(Stream &ss, std::string_view name, T &&attr) {
template <typename Stream, typename T>
inline void render_xml_node(Stream &ss, std::string_view name, T &&item) {
using U = std::decay_t<T>;
if constexpr (std::is_same_v<U, namespace_t>) {
auto index_ul = find_underline(name.data());
std::string ns(name.data(), name.size());
ns[index_ul] = ':';
render_head(ss, ns.data());
render_xml_value(ss, item.get_value());
render_tail(ss, ns.data());
} else if constexpr (is_std_pair_v<U>) {
if constexpr (is_std_pair_v<U>) {
render_xml_attr(ss, name, item.second);
render_xml_value(ss, item.first);
render_tail(ss, name.data());
Expand Down Expand Up @@ -144,11 +136,21 @@ inline void to_xml_impl(Stream &s, T &&t, std::string_view name) {
static_assert(Idx < Count);

using type_v = decltype(std::declval<T>().*std::declval<decltype(v)>());
using type_u = std::decay_t<type_v>;
if constexpr (!is_reflection<type_v>::value) {
if constexpr (is_map_container<std::decay_t<type_v>>::value) {
if constexpr (is_map_container<type_u>::value) {
return;
} else if constexpr (!is_str_v<std::decay_t<type_v>> &&
is_container<type_v>::value) {
} else if constexpr (is_namespace_v<type_u>) {
constexpr auto name = get_name<T, Idx>();
auto index_ul = find_underline(name.data());
std::string ns(name.data(), name.size());
ns[index_ul] = ':';
if constexpr (is_reflection<typename type_u::value_type>::value) {
to_xml_impl(s, (t.*v).get(), ns);
} else {
render_xml_node(s, ns, (t.*v).get());
}
} else if constexpr (!is_str_v<type_u> && is_container<type_u>::value) {
std::string_view sv = get_name<T, Idx>().data();
render_xml_value0(s, t.*v, sv);
} else {
Expand Down
39 changes: 19 additions & 20 deletions test/test_xml.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -321,40 +321,39 @@ TEST_CASE("test exception") {
iguana::xml::to_xml_pretty(ss, simple2)); // unexpected end of data
}

struct item_itunes_t {
iguana::xml::namespace_t<std::string_view> itunes_author;
iguana::xml::namespace_t<std::string_view> itunes_subtitle;
iguana::xml::namespace_t<int> itunes_user;
};
REFLECTION(item_itunes_t, itunes_author, itunes_subtitle, itunes_user);
struct item_t {
iguana::xml::namespace_t itunes_author;
iguana::xml::namespace_t itunes_subtitle;
iguana::xml::namespace_t itunes_user;
iguana::xml::namespace_t<item_itunes_t> item_itunes;
};
REFLECTION(item_t, itunes_author, itunes_subtitle, itunes_user);
REFLECTION(item_t, item_itunes);
TEST_CASE("test xml namespace") {
item_t item;
std::string str = R"(
<item>
<itunes:author>Jupiter Broadcasting</itunes:author>
<itunes:subtitle>Linux enthusiasts talk top news stories, subtitle</itunes:subtitle>
<itunes:user>10086</itunes:user>
<item:itunes>
<itunes:author>Jupiter Broadcasting</itunes:author>
<itunes:subtitle>Linux enthusiasts talk top news stories, subtitle</itunes:subtitle>
<itunes:user>10086</itunes:user>
</item:itunes>
</item>
)";
item_t it;
iguana::xml::from_xml(it, str.data());
CHECK(it.itunes_author.get<std::string_view>().first);
CHECK(it.itunes_author.get<std::string_view>().second ==
"Jupiter Broadcasting");
CHECK(it.itunes_subtitle.get<std::string_view>().first);
CHECK(it.itunes_user.get<int>().first);
CHECK(it.itunes_user.get<int>().second == 10086);
auto itunes = it.item_itunes.get();
CHECK(itunes.itunes_author.get() == "Jupiter Broadcasting");
CHECK(itunes.itunes_user.get() == 10086);

std::string ss;
iguana::xml::to_xml(ss, it);
item_t it2;
iguana::xml::from_xml(it2, ss.data());
CHECK(it2.itunes_author.get<std::string_view>().first);
CHECK(it2.itunes_author.get<std::string_view>().second ==
"Jupiter Broadcasting");
CHECK(it2.itunes_subtitle.get<std::string_view>().first);
CHECK(it2.itunes_user.get<int>().first);
CHECK(it2.itunes_user.get<int>().second == 10086);
auto itunes2 = it2.item_itunes.get();
CHECK(itunes2.itunes_author.get() == "Jupiter Broadcasting");
CHECK(itunes2.itunes_user.get() == 10086);
}

struct package_t {
Expand Down

0 comments on commit 15001b8

Please sign in to comment.