Skip to content

Commit

Permalink
partial from json
Browse files Browse the repository at this point in the history
  • Loading branch information
qicosmos committed Apr 29, 2024
1 parent fb6e6d5 commit df63989
Show file tree
Hide file tree
Showing 3 changed files with 137 additions and 4 deletions.
25 changes: 25 additions & 0 deletions iguana/json_reader.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -644,6 +644,31 @@ IGUANA_INLINE void from_json(T &value, const View &view) {
from_json(value, std::begin(view), std::end(view));
}

template <
auto member,
typename Parant = typename member_tratis<decltype(member)>::owner_type,
typename T>
IGUANA_INLINE void from_json(T &value, std::string_view str) {
constexpr size_t duplicate_count =
iguana::duplicate_count<std::remove_reference_t<Parant>, member>();
static_assert(duplicate_count != 1, "the member is not belong to the object");
static_assert(duplicate_count == 2, "has duplicate field name");

constexpr auto name = name_of<member>();
constexpr size_t index = index_of<member>();
constexpr size_t member_count = member_count_of<member>();
str = str.substr(str.find(name) + name.size());
size_t pos = str.find(":") + 1;
if constexpr (index == member_count - 1) { // last field
str = str.substr(pos, str.find("}") - pos);
}
else {
str = str.substr(pos, str.find(",") - pos);
}

detail::from_json_impl(value.*member, std::begin(str), std::end(str));
}

template <typename T, typename View,
std::enable_if_t<json_view_v<View>, int> = 0>
IGUANA_INLINE void from_json(T &value, const View &view,
Expand Down
52 changes: 48 additions & 4 deletions iguana/reflection.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -942,10 +942,7 @@ constexpr bool get_index_imple() {
#else
template <typename T, typename U>
constexpr bool get_index_imple(T ptr, U ele) {
if constexpr (std::is_same_v<
typename iguana::member_tratis<decltype(ptr)>::value_type,
typename iguana::member_tratis<
decltype(ele)>::value_type>) {
if constexpr (std::is_same_v<decltype(ptr), decltype(ele)>) {
if (ele == ptr) {
return true;
}
Expand Down Expand Up @@ -999,6 +996,53 @@ constexpr auto name_of() {
return std::string_view(s.data(), s.size());
}

template <auto member>
constexpr auto member_count_of() {
using T = typename member_tratis<decltype(member)>::owner_type;
using M = Reflect_members<T>;
return M::value();
}

template <typename T, auto member>
constexpr size_t duplicate_count();

template <auto ptr>
constexpr void check_duplicate(auto member, size_t &index) {
using value_type = typename member_tratis<decltype(member)>::value_type;

if (detail::get_index_imple(ptr, member)) {
index++;
}

if constexpr (is_reflection_v<value_type>) {
index += iguana::duplicate_count<value_type, ptr>();
}
}

template <typename T, auto member>
constexpr size_t duplicate_count() {
using M = Reflect_members<T>;
constexpr auto name = name_of<member>();
constexpr auto arr = M::arr();

constexpr auto tp = M::apply_impl();
size_t index = 0;
std::apply(
[&](auto... ele) {
(check_duplicate<member>(ele, index), ...);
},
tp);

for (auto &s : arr) {
if (s == name) {
index++;
break;
}
}

return index;
}

template <typename T>
constexpr const std::string_view get_fields() {
using M = Reflect_members<T>;
Expand Down
64 changes: 64 additions & 0 deletions test/test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -821,6 +821,70 @@ TEST_CASE("parse some other char") {
CHECK(p.name == "tom");
}

struct some_test_t {
int id1;
std::string name;
};
REFLECTION(some_test_t, id1, name);

struct dummy_nest_t {
int id;
some_test_t t;
};
REFLECTION(dummy_nest_t, id, t);

struct some_test_t1 {
int id;
std::string name;
};
REFLECTION(some_test_t1, id, name);

struct dummy_nest_t1 {
int id;
some_test_t1 t;
};
REFLECTION(dummy_nest_t1, id, t);

TEST_CASE("partial from json") {
constexpr size_t count1 =
iguana::duplicate_count<dummy_nest_t, &some_test_t::name>();
static_assert(count1 == 2);
constexpr size_t count2 =
iguana::duplicate_count<dummy_nest_t, &dummy_nest_t::t>();
static_assert(count2 == 2);
constexpr size_t count3 =
iguana::duplicate_count<dummy_nest_t, &dummy_nest_t::id>();
static_assert(count3 == 2);

constexpr size_t count5 =
iguana::duplicate_count<dummy_nest_t1, &dummy_nest_t1::id>();
static_assert(count5 == 3);
constexpr size_t count4 =
iguana::duplicate_count<dummy_nest_t, &person::name>();
static_assert(count4 == 1);

dummy_nest_t t{42, {43, "tom"}};
std::string str;
iguana::to_json(t, str);

{
dummy_nest_t t1;
iguana::from_json<&dummy_nest_t::id>(t1, str);
CHECK(t1.id == 42);
}
{
dummy_nest_t t1;
iguana::from_json<&dummy_nest_t::t>(t1, str);
CHECK(t1.t.name == "tom");
}

{
some_test_t t1;
iguana::from_json<&some_test_t::name, dummy_nest_t>(t1, str);
CHECK(t1.name == "tom");
}
}

TEST_CASE("index_of name_of") {
constexpr size_t idx1 = iguana::index_of<&point_t::y>();
static_assert(idx1 == 1);
Expand Down

0 comments on commit df63989

Please sign in to comment.