Skip to content

Commit

Permalink
Merge pull request #312 from qicosmos/update_macro
Browse files Browse the repository at this point in the history
  • Loading branch information
qicosmos authored Sep 27, 2024
2 parents 961b93a + 9039124 commit 7fe6964
Show file tree
Hide file tree
Showing 5 changed files with 285 additions and 37 deletions.
36 changes: 21 additions & 15 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,10 @@ This library provides a portable cross-platform way of:
- serialization of yaml
- serialization of any customized format

### compile time reflection ###

[reflection lib introduction](lang/reflection_introduction.md)

### Tutorial ###
This Tutorial is provided to give you a view of how *iguana* works for serialization.

Expand All @@ -38,10 +42,12 @@ struct person
std::string name;
int age;
};
REFLECTION(person, name, age) //define meta data
#if __cplusplus >= 202002L
YLT_REFL(person, name, age) //define meta data
#endif
```

Defining meta data is very simple, and just needs to define in a `REFLECTION` macro.
Defining meta data is very simple, if your compiler is C++20 compiler(gcc11+, clang13+, msvc2022), no need define YLT_REFL, other wise need to define in a `YLT_REFL` macro.

Now let's serialize `person` to `json` string.

Expand Down Expand Up @@ -141,15 +147,15 @@ struct one_t
{
int id;
};
REFLECTION(one_t, id);
YLT_REFL(one_t, id);

struct two
{
std::string name;
one_t one;
int age;
};
REFLECTION(two, name, one, age);
YLT_REFL(two, name, one, age);

struct composit_t
{
Expand All @@ -161,7 +167,7 @@ struct composit_t
double f;
std::list<one_t> g;
};
REFLECTION(composit_t, a, b, c, d, e, f, g);
YLT_REFL(composit_t, a, b, c, d, e, f, g);
```

Then call the simple interface:
Expand All @@ -187,13 +193,13 @@ struct book_t {
std::string author;
float price;
};
REFLECTION(book_t, author, price);
YLT_REFL(book_t, author, price);
struct library_t {
std::string name;
int id;
std::vector<book_t> book;
};
REFLECTION(library_t, name, id, book);
YLT_REFL(library_t, name, id, book);
```

And then, simply call the interface:
Expand Down Expand Up @@ -236,7 +242,7 @@ struct plain_type_t {
std::optional<float> num;
std::optional<int> price;
};
REFLECTION(plain_type_t, isok, status, c, hasprice, num, price);
YLT_REFL(plain_type_t, isok, status, c, hasprice, num, price);
```

And then, simply call the interface:
Expand Down Expand Up @@ -311,7 +317,7 @@ struct enum_t {
Status a;
Status b;
};
REFLECTION(enum_t, a, b);
YLT_REFL(enum_t, a, b);

// deserialization
enum_t e;
Expand All @@ -333,7 +339,7 @@ iguana::to_json(e1, ss);

### Scripts

Automatically generate `REFLECTION` macros based by struct.
Automatically generate `YLT_REFL` macros based by struct.

To get a list of basic options and switches use:

Expand Down Expand Up @@ -382,11 +388,11 @@ struct person {
std::string name;
int age;
};
REFLECTION(person, name, age);
YLT_REFL(person, name, age);
char *iguana = NULL;

struct composit_t { int a; std::vector<std::string> b; int c; std::map<int, int> d; std::unordered_map<int, int> e; double f;};
REFLECTION(composit_t, a, b, c, d, e, f);
YLT_REFL(composit_t, a, b, c, d, e, f);

struct composit_t2
{
Expand All @@ -397,7 +403,7 @@ struct composit_t2
std::unordered_map<int, int> random_name__;
double __f__number__complex;
};
REFLECTION(composit_t2, a, b, iguana, example_test, random_name__, __f__number__complex);
YLT_REFL(composit_t2, a, b, iguana, example_test, random_name__, __f__number__complex);
```

other example:
Expand All @@ -406,7 +412,7 @@ other example:
python automatic_macro_generator.py -i test_macro_generator.cpp -o have_macro.cpp
```

test_macro_generator.cpp will be unchanged, have_macro.cpp will be changed to source file with REFLECTION macro.
test_macro_generator.cpp will be unchanged, have_macro.cpp will be changed to source file with YLT_REFL macro.

scripts works out of the box with Python version 2.7 and 3.x on any platform.

Expand All @@ -417,7 +423,7 @@ Notes: In Python3,Will prompt `DeprecationWarning: 'U' mode is deprecated`.Ignor

- **Question**: Why is the library called *iguana*?

- **Answer**: I think serialization is like an iguana, because the only difference is the displaying format, however the meta data is never changed. With changeless meta data and reflection, you can serialize an object to any format, which is like how an iguana does.
- **Answer**: I think serialization is like an iguana, because the only difference is the displaying format, however the meta data is never changed. With changeless meta data and YLT_REFL, you can serialize an object to any format, which is like how an iguana does.

- **Question**: Does *iguana* support raw pointer?

Expand Down
38 changes: 22 additions & 16 deletions lang/iguana 使用文档.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,17 +19,17 @@ iguana 是header only的,从github 将iguana clone 下来之后,在cmake 里
gcc9+、clang11+、msvc2019+

# json 序列化/反序列化
iguana 序列化需要先定义一个可反射的对象,通过REFLECTION 可以轻松定义一个可反射对象。
iguana 序列化需要先定义一个可反射的对象,通过YLT_REFL 可以轻松定义一个可反射对象。

```c++
struct person
{
std::string_view name;
int age;
};
REFLECTION(person, name, age); // 通过这个宏定义元数据让person 成为一个可反射对象
YLT_REFL(person, name, age); // 通过这个宏定义元数据让person 成为一个可反射对象
```
通过REFLECTION 宏定义元数据之后就可以一行代码实现json 的序列化与反序列化了。
通过YLT_REFL 宏定义元数据之后就可以一行代码实现json 的序列化与反序列化了。
```c++
person p = { "tom", 28 };
Expand Down Expand Up @@ -74,7 +74,7 @@ struct some_obj {
std::string_view name;
iguana::numeric_str age;
};
REFLECTION(some_obj, name, age);
YLT_REFL(some_obj, name, age);
void test_view(){
std::string_view str = "{\"name\":\"tom\", \"age\":20}";
Expand Down Expand Up @@ -110,7 +110,7 @@ struct some_obj {
std::string_view name;
int age;
};
REFLECTION(some_obj, name, age);
YLT_REFL(some_obj, name, age);

void test() {
person p = {"admin", 20};
Expand All @@ -135,7 +135,7 @@ struct person {
std::string_view name;
int age;
};
REFLECTION(person, name, age);
YLT_REFL(person, name, age);
void test_pretty() {
person p{"tom", 20};
Expand Down Expand Up @@ -171,11 +171,11 @@ struct book_t {
std::string title;
std::string author;
};
REFLECTION(book_t, title, author);
YLT_REFL(book_t, title, author);
struct library {
iguana::xml_attr_t<book_t> book;
};
REFLECTION(library, book);
YLT_REFL(library, book);
TEST_CASE("test library with attr") {
auto validator = [](library lib) {
CHECK(lib.book.attr()["id"] == "1234");
Expand Down Expand Up @@ -214,7 +214,7 @@ struct some_obj {
std::string_view name;
int age;
};
REFLECTION(some_obj, name, age);
YLT_REFL(some_obj, name, age);
void test() {
std::string_view xml = R"(
Expand Down Expand Up @@ -249,7 +249,13 @@ public:
person() = default;
person(std::shared_ptr<std::string> id, std::unique_ptr<std::string> name) : id_(id), name_(std::move(name)) {}
REFLECTION_ALIAS(person, "rootnode", FLDALIAS(&person::id_, "id"), FLDALIAS(&person::name_, "name"));
static constexpr auto get_alias_field_names(person*) {
return std::array{field_alias_t{"id", 0}, field_alias_t{"name", 1}};
}
static constexpr std::string_view get_alias_struct_name(person*) {
return "rootnode";
}
YLT_REFL(person, id_, name_);
void parse_xml() {
iguana::from_xml(*this, xml_str);
Expand All @@ -259,18 +265,18 @@ public:
}
}
```
REFLECTION_ALIAS 中需要填写结构体的别名和字段的别名,通过别名将标签和结构体字段关联起来就可以保证正确的解析了。
get_alias_field_names 函数中需要填写结构体的别名,get_alias_struct_name 函数中填写字段的别名,别名字段的索引需要和YLT_REFL宏定义的字段顺序一致,通过别名将标签和结构体字段关联起来就可以保证正确的解析了。

这个例子同时也展示了iguana 支持智能指针的序列化和反序列化。

# 如何处理私有字段
如果类里面有私有字段,在外面定义REFLECTION 宏会出错,因为无法访问私有字段,这时候把宏定义到类里面即可,但要保证宏是public的。
如果类里面有私有字段,在外面定义YLT_REFL 宏会出错,因为无法访问私有字段,这时候把宏定义到类里面即可,但要保证宏是public的。
```c++
class person {
std::string name;
int age;
public:
REFLECTION(person, name, age);
YLT_REFL(person, name, age);
};
```
Expand All @@ -289,7 +295,7 @@ struct plain_type_t {
std::optional<float> num;
std::optional<int> price;
};
REFLECTION(plain_type_t, isok, status, c, hasprice, num, price);
YLT_REFL(plain_type_t, isok, status, c, hasprice, num, price);
```

```c++
Expand Down Expand Up @@ -320,7 +326,7 @@ struct enum_t {
Status a;
Status b;
};
REFLECTION(enum_t, a, b);
YLT_REFL(enum_t, a, b);
namespace iguana {
template <> struct enum_value<Status> {
Expand Down Expand Up @@ -390,7 +396,7 @@ struct test_float_t {
double a;
float b;
};
REFLECTION(test_float_t, a, b);
YLT_REFL(test_float_t, a, b);
void user_defined_tochars_example() {
test_float_t t{2.011111, 2.54};
std::string ss;
Expand Down
Loading

0 comments on commit 7fe6964

Please sign in to comment.