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

[struct_xml, struct_json, struct_yaml][feat]support shared_ptr #402

Merged
merged 1 commit into from
Aug 9, 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
21 changes: 15 additions & 6 deletions include/ylt/thirdparty/iguana/json_reader.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,9 @@ template <typename U, typename It,
std::enable_if_t<sequence_container_v<U>, int> = 0>
IGUANA_INLINE void parse_item(U &value, It &&it, It &&end);

template <typename U, typename It, std::enable_if_t<smart_ptr_v<U>, int> = 0>
IGUANA_INLINE void parse_item(U &value, It &&it, It &&end);

template <typename U, typename It, std::enable_if_t<refletable_v<U>, int> = 0>
IGUANA_INLINE void parse_item(U &value, It &&it, It &&end) {
from_json(value, it, end);
Expand Down Expand Up @@ -445,7 +448,7 @@ IGUANA_INLINE void parse_item(U &value, It &&it, It &&end) {
}
}

template <typename U, typename It, std::enable_if_t<unique_ptr_v<U>, int> = 0>
template <typename U, typename It, std::enable_if_t<smart_ptr_v<U>, int>>
IGUANA_INLINE void parse_item(U &value, It &&it, It &&end) {
skip_ws(it, end);
if (it < end && *it == '"')
Expand All @@ -458,7 +461,12 @@ IGUANA_INLINE void parse_item(U &value, It &&it, It &&end) {
}
else {
using value_type = typename std::remove_reference_t<U>::element_type;
value = std::make_unique<value_type>();
if constexpr (unique_ptr_v<U>) {
value = std::make_unique<value_type>();
}
else {
value = std::make_shared<value_type>();
}
parse_item(*value, it, end);
}
}
Expand Down Expand Up @@ -632,7 +640,7 @@ template <bool Is_view = false, typename It>
void parse(jvalue &result, It &&it, It &&end);

template <bool Is_view = false, typename It>
inline void parse_array(jarray &result, It &&it, It &&end) {
inline void parse(jarray &result, It &&it, It &&end) {
skip_ws(it, end);
match<'['>(it, end);
if (*it == ']')
Expand Down Expand Up @@ -660,7 +668,7 @@ inline void parse_array(jarray &result, It &&it, It &&end) {
}

template <bool Is_view = false, typename It>
inline void parse_object(jobject &result, It &&it, It &&end) {
inline void parse(jobject &result, It &&it, It &&end) {
skip_ws(it, end);
match<'{'>(it, end);
if (*it == '}')
Expand Down Expand Up @@ -740,11 +748,11 @@ inline void parse(jvalue &result, It &&it, It &&end) {
break;
case '[':
result.template emplace<jarray>();
parse_array<Is_view>(std::get<jarray>(result), it, end);
parse<Is_view>(std::get<jarray>(result), it, end);
break;
case '{': {
result.template emplace<jobject>();
parse_object<Is_view>(std::get<jobject>(result), it, end);
parse<Is_view>(std::get<jobject>(result), it, end);
break;
}
default:
Expand All @@ -754,6 +762,7 @@ inline void parse(jvalue &result, It &&it, It &&end) {
skip_ws(it, end);
}

// when Is_view is true, parse str as string_view
template <bool Is_view = false, typename It>
inline void parse(jvalue &result, It &&it, It &&end, std::error_code &ec) {
try {
Expand Down
4 changes: 2 additions & 2 deletions include/ylt/thirdparty/iguana/json_writer.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ template <typename Stream, typename T,
IGUANA_INLINE void render_json_value(Stream &ss, const T &v);

template <typename Stream, typename T,
std::enable_if_t<unique_ptr_v<T>, int> = 0>
std::enable_if_t<smart_ptr_v<T>, int> = 0>
IGUANA_INLINE void render_json_value(Stream &ss, const T &v);

template <typename Stream, typename T,
Expand Down Expand Up @@ -203,7 +203,7 @@ constexpr auto write_json_key = [](auto &s, auto i,
s.push_back('"');
};

template <typename Stream, typename T, std::enable_if_t<unique_ptr_v<T>, int>>
template <typename Stream, typename T, std::enable_if_t<smart_ptr_v<T>, int>>
IGUANA_INLINE void render_json_value(Stream &ss, const T &v) {
if (v) {
render_json_value(ss, *v);
Expand Down
32 changes: 31 additions & 1 deletion include/ylt/thirdparty/iguana/util.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,13 @@ template <typename T>
constexpr inline bool unique_ptr_v =
is_template_instant_of<std::unique_ptr, std::remove_cvref_t<T>>::value;

template <typename T>
constexpr inline bool shared_ptr_v =
is_template_instant_of<std::shared_ptr, std::remove_cvref_t<T>>::value;

template <typename T>
constexpr inline bool smart_ptr_v = shared_ptr_v<T> || unique_ptr_v<T>;

template <typename T>
struct is_variant : std::false_type {};

Expand All @@ -134,7 +141,7 @@ constexpr inline bool variant_v = is_variant<std::remove_cvref_t<T>>::value;
template <class T>
constexpr inline bool non_refletable_v =
container_v<T> || c_array_v<T> || tuple_v<T> || optional_v<T> ||
unique_ptr_v<T> || std::is_fundamental_v<std::remove_cvref_t<T>> ||
smart_ptr_v<T> || std::is_fundamental_v<std::remove_cvref_t<T>> ||
variant_v<T>;

template <typename T>
Expand All @@ -144,6 +151,29 @@ template <typename T>
constexpr inline bool plain_v =
string_container_v<T> || num_v<T> || char_v<T> || bool_v<T> || enum_v<T>;

template <typename T>
struct underline_type {
using type = T;
};

template <typename T>
struct underline_type<std::unique_ptr<T>> {
using type = typename underline_type<T>::type;
};

template <typename T>
struct underline_type<std::shared_ptr<T>> {
using type = typename underline_type<T>::type;
};

template <typename T>
struct underline_type<std::optional<T>> {
using type = typename underline_type<T>::type;
};

template <typename T>
using underline_type_t = typename underline_type<std::remove_cvref_t<T>>::type;

template <char... C, typename It>
IGUANA_INLINE void match(It &&it, It &&end) {
const auto n = static_cast<size_t>(std::distance(it, end));
Expand Down
12 changes: 9 additions & 3 deletions include/ylt/thirdparty/iguana/xml_reader.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ template <typename U, typename It, std::enable_if_t<optional_v<U>, int> = 0>
IGUANA_INLINE void parse_item(U &value, It &&it, It &&end,
std::string_view name);

template <typename U, typename It, std::enable_if_t<unique_ptr_v<U>, int> = 0>
template <typename U, typename It, std::enable_if_t<smart_ptr_v<U>, int> = 0>
IGUANA_INLINE void parse_item(U &value, It &&it, It &&end,
std::string_view name);

Expand Down Expand Up @@ -178,10 +178,16 @@ IGUANA_INLINE void parse_item(U &value, It &&it, It &&end,
}
}

template <typename U, typename It, std::enable_if_t<unique_ptr_v<U>, int>>
template <typename U, typename It, std::enable_if_t<smart_ptr_v<U>, int>>
IGUANA_INLINE void parse_item(U &value, It &&it, It &&end,
std::string_view name) {
value = std::make_unique<typename std::remove_cvref_t<U>::element_type>();
if constexpr (unique_ptr_v<U>) {
value = std::make_unique<typename std::remove_cvref_t<U>::element_type>();
}
else {
value = std::make_shared<typename std::remove_cvref_t<U>::element_type>();
}

parse_item(*value, it, end, name);
}

Expand Down
7 changes: 4 additions & 3 deletions include/ylt/thirdparty/iguana/xml_writer.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@ IGUANA_INLINE void render_xml_value(Stream &ss, const T &value,
}

template <bool pretty, size_t spaces, typename Stream, typename T,
std::enable_if_t<unique_ptr_v<T>, int> = 0>
std::enable_if_t<smart_ptr_v<T>, int> = 0>
IGUANA_INLINE void render_xml_value(Stream &ss, const T &value,
std::string_view name) {
if (value) {
Expand All @@ -142,7 +142,8 @@ template <bool pretty, size_t spaces, typename Stream, typename T,
std::enable_if_t<sequence_container_v<T>, int>>
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;
using value_type =
underline_type_t<typename std::remove_cvref_t<T>::value_type>;
for (const auto &v : value) {
if constexpr (attr_v<value_type>) {
render_xml_value<pretty, spaces>(ss, v, name);
Expand All @@ -163,7 +164,7 @@ IGUANA_INLINE void render_xml_value(Stream &ss, T &&t, std::string_view name) {
for_each(std::forward<T>(t),
[&](const auto &v, auto i) IGUANA__INLINE_LAMBDA {
using M = decltype(iguana_reflect_type(std::forward<T>(t)));
using value_type = std::remove_cvref_t<decltype(t.*v)>;
using value_type = underline_type_t<decltype(t.*v)>;
constexpr auto Idx = decltype(i)::value;
constexpr auto Count = M::value();
constexpr std::string_view tag_name =
Expand Down
13 changes: 9 additions & 4 deletions include/ylt/thirdparty/iguana/yaml_reader.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -241,7 +241,7 @@ IGUANA_INLINE void parse_item(U &value, It &&it, It &&end, size_t min_spaces) {
template <typename U, typename It, std::enable_if_t<optional_v<U>, int> = 0>
IGUANA_INLINE void parse_item(U &value, It &&it, It &&end, size_t min_spaces);

template <typename U, typename It, std::enable_if_t<unique_ptr_v<U>, int> = 0>
template <typename U, typename It, std::enable_if_t<smart_ptr_v<U>, int> = 0>
IGUANA_INLINE void parse_item(U &value, It &&it, It &&end, size_t min_spaces);

// minspaces : The minimum indentation
Expand Down Expand Up @@ -418,12 +418,17 @@ IGUANA_INLINE void parse_item(U &value, It &&it, It &&end, size_t min_spaces) {
}
}

template <typename U, typename It, std::enable_if_t<unique_ptr_v<U>, int>>
template <typename U, typename It, std::enable_if_t<smart_ptr_v<U>, int>>
IGUANA_INLINE void parse_item(U &value, It &&it, It &&end, size_t min_spaces) {
using T = std::remove_reference_t<U>;
value = std::make_unique<typename T::element_type>();
if constexpr (unique_ptr_v<T>) {
value = std::make_unique<typename T::element_type>();
}
else {
value = std::make_shared<typename T::element_type>();
}
static_assert(!string_v<typename T::element_type>,
"unique_ptr<string> is not allowed");
"smart_ptr<string> is not allowed");
parse_item(*value, it, end, min_spaces);
}

Expand Down
6 changes: 3 additions & 3 deletions include/ylt/thirdparty/iguana/yaml_writer.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ IGUANA_INLINE void render_yaml_value(Stream &ss, const T &val,
size_t min_spaces);

template <typename Stream, typename T,
std::enable_if_t<unique_ptr_v<T>, int> = 0>
std::enable_if_t<smart_ptr_v<T>, int> = 0>
IGUANA_INLINE void render_yaml_value(Stream &ss, const T &val,
size_t min_spaces);

Expand Down Expand Up @@ -132,7 +132,7 @@ IGUANA_INLINE void render_yaml_value(Stream &ss, const T &val,
}
}

template <typename Stream, typename T, std::enable_if_t<unique_ptr_v<T>, int>>
template <typename Stream, typename T, std::enable_if_t<smart_ptr_v<T>, int>>
IGUANA_INLINE void render_yaml_value(Stream &ss, const T &val,
size_t min_spaces) {
if (!val) {
Expand Down Expand Up @@ -174,7 +174,7 @@ template <typename Stream, typename T,
std::enable_if_t<non_refletable_v<T>, int> = 0>
IGUANA_INLINE void to_yaml(T &&t, Stream &s) {
if constexpr (tuple_v<T> || map_container_v<T> || sequence_container_v<T> ||
optional_v<T> || unique_ptr_v<T>)
optional_v<T> || smart_ptr_v<T>)
render_yaml_value(s, std::forward<T>(t), 0);
else
static_assert(!sizeof(T), "don't suppport this type");
Expand Down
25 changes: 25 additions & 0 deletions src/struct_xml/examples/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -255,7 +255,32 @@ void test_inner_object() {
assert(obj1.get_name() == "tom");
}

struct shared_object {
std::shared_ptr<std::vector<std::shared_ptr<int>>> vec;
std::string b;
std::shared_ptr<int> c;
std::vector<std::shared_ptr<int>> d;
};
REFLECTION(shared_object, vec, b, c, d);

void test_sp() {
auto vec = std::make_shared<std::vector<std::shared_ptr<int>>>();
vec->push_back(std::make_unique<int>(42));
vec->push_back(std::make_unique<int>(21));
shared_object contents{std::move(vec),
"test",
std::make_shared<int>(24),
{std::make_shared<int>(1), std::make_shared<int>(4)}};
std::string str;
iguana::to_xml(contents, str);

shared_object cont;
iguana::from_xml(cont, str); // throw exception.
std::cout << cont.b << "\n";
}

int main() {
test_sp();
basic_usage();
type_to_string();
nested_xml();
Expand Down
Loading