Skip to content

Commit

Permalink
Merge pull request qicosmos#289 from 171930433/gsk/add_get_field_any
Browse files Browse the repository at this point in the history
  • Loading branch information
qicosmos authored Jun 27, 2024
2 parents 1d774ee + d40ab66 commit e27f437
Show file tree
Hide file tree
Showing 3 changed files with 65 additions and 8 deletions.
38 changes: 33 additions & 5 deletions iguana/dynamic.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -113,20 +113,48 @@ struct base_impl : public base {
return info;
}

std::vector<std::string_view> get_fields_name() override {
std::vector<std::string_view> get_fields_name() const override {
static constexpr auto map = iguana::get_members<T>();

std::vector<std::string_view> vec;
for (auto [no, val] : map) {

for (auto const& [no, val] : map) {
std::visit(
[&](auto& field) {
vec.push_back(std::string_view(field.field_name.data(),
field.field_name.size()));
[&](auto const& field) {
std::string_view const current_name{field.field_name.data(),
field.field_name.size()};
if (vec.empty() || (vec.back() != current_name)) {
vec.push_back(current_name);
}
},
val);
}
return vec;
}

std::any get_field_any(std::string_view name) const override {
static constexpr auto map = iguana::get_members<T>();
std::any result;

for (auto [no, field] : map) {
if (result.has_value()) {
break;
}
std::visit(
[&](auto val) {
if (val.field_name == name) {
using value_type = typename decltype(val)::value_type;
auto const offset = member_offset((T*)this, val.member_ptr);
auto ptr = (((char*)this) + offset);
result = {*((value_type*)ptr)};
}
},
field);
}

return result;
}

virtual ~base_impl() {}

size_t cache_size = 0;
Expand Down
4 changes: 3 additions & 1 deletion iguana/reflection.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

#ifndef IGUANA_REFLECTION_HPP
#define IGUANA_REFLECTION_HPP
#include <any>
#include <array>
#include <functional>
#include <iomanip>
Expand Down Expand Up @@ -569,7 +570,8 @@ struct base {
virtual void from_json(std::string_view str) {}
virtual void to_yaml(std::string &str) {}
virtual void from_yaml(std::string_view str) {}
virtual std::vector<std::string_view> get_fields_name() { return {}; }
virtual std::vector<std::string_view> get_fields_name() const { return {}; }
virtual std::any get_field_any(std::string_view name) const { return {}; }
virtual iguana::detail::field_info get_field_info(std::string_view name) {
return {};
}
Expand Down
31 changes: 29 additions & 2 deletions test/test_pb.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -211,6 +211,9 @@ struct my_struct {
int x;
bool y;
iguana::fixed64_t z;
bool operator==(const my_struct &other) const {
return x == other.x && y == other.y && z == other.z;
}
};
REFLECTION(my_struct, x, y, z);

Expand All @@ -221,8 +224,9 @@ struct nest1 PUBLIC(nest1) {
std::string name;
my_struct value;
int var;
std::variant<int, double> mv;
};
REFLECTION(nest1, name, value, var);
REFLECTION(nest1, name, value, var, mv);

struct numer_st PUBLIC(numer_st) {
numer_st() = default;
Expand All @@ -237,7 +241,8 @@ TEST_CASE("test reflection") {
{
auto t = iguana::create_instance("nest1");
std::vector<std::string_view> fields_name = t->get_fields_name();
CHECK(fields_name == std::vector<std::string_view>{"name", "value", "var"});
CHECK(fields_name ==
std::vector<std::string_view>{"name", "value", "var", "mv"});

my_struct mt{2, true, {42}};
t->set_field_value("value", mt);
Expand All @@ -259,6 +264,28 @@ TEST_CASE("test reflection") {

CHECK_THROWS_AS(t->set_field_value<int>("name", 42), std::invalid_argument);
}
{
my_struct temp_my{1, false, {3}};
nest1 t{"Hi", temp_my, 5};

auto const temp_variant = std::variant<int, double>{1};
t.set_field_value("mv", temp_variant);

// dynamic any
auto const &any_name = t.get_field_any("name");
assert(std::any_cast<std::string>(any_name) == "Hi");

auto const &any_value = t.get_field_any("value");
assert(std::any_cast<my_struct>(any_value) == temp_my);

auto const &any_var = t.get_field_any("var");
assert(std::any_cast<int>(any_var) == 5);

auto const &mvariant_any = t.get_field_any("mv");
auto const &mvariant =
std::any_cast<std::variant<int, double>>(mvariant_any);
assert(mvariant == temp_variant);
}
{
auto t = iguana::create_instance("pair_t");
t->set_field_value("x", 12);
Expand Down

0 comments on commit e27f437

Please sign in to comment.