Skip to content

Commit

Permalink
support shared_ptr
Browse files Browse the repository at this point in the history
  • Loading branch information
qicosmos committed Aug 9, 2023
1 parent 0acb5e3 commit 8191b41
Show file tree
Hide file tree
Showing 8 changed files with 98 additions and 22 deletions.
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

0 comments on commit 8191b41

Please sign in to comment.