Skip to content

Commit

Permalink
Merge pull request #128 from helintongh/automatic_macro_generator
Browse files Browse the repository at this point in the history
add  automatic generate macro script
  • Loading branch information
qicosmos authored Dec 14, 2022
2 parents 9a6b30a + f9318af commit 37c2ec1
Show file tree
Hide file tree
Showing 3 changed files with 216 additions and 0 deletions.
74 changes: 74 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,80 @@ We can slove the problem1 easily with c++17:

- https://github.com/qicosmos/iguana/blob/master/example/example.cpp

### Scripts

Automatically generate `REFLECTION` macros based by struct.

To get a list of basic options and switches use:
```
python automatic_macro_generator.py -h
```

basic example:

The content of the test_macro_generator.cpp is as follows:

struct person {
std::string name;
int 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;};

char *iguana_test = NULL;

struct composit_t2
{
int a;
std::vector<std::string> b;
int iguana;
std::map<int, int> example_test;
std::unordered_map<int, int> random_name__;
double __f__number__complex;
};


execute script:
```
python automatic_macro_generator.py -i test_macro_generator.cpp
```

After processing by the automatic_macro_generator.py script,test_macro_generator.cpp change into:

struct person {
std::string name;
int age;
};
REFLECTION(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);

struct composit_t2
{
int a;
std::vector<std::string> b;
int iguana;
std::map<int, int> example_test;
std::unordered_map<int, int> random_name__;
double __f__number__complex;
};
REFLECTION(composit_t2, a, b, iguana, example_test, random_name__, __f__number__complex);

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.

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

Notes: In Python3,Will prompt `DeprecationWarning: 'U' mode is deprecated`.Ignore it.


### F.A.Q

- **Question**: Why is the library called *iguana*?
Expand Down
114 changes: 114 additions & 0 deletions scripts/automatic_macro_generator.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
# !/usr/bin/python
# -*- coding: UTF-8 -*-
import sys
import argparse


class SetupError(Exception):
"""Functions in this script can raise this error which will cause the
application to abort displaying the provided error message, but
without a stack trace.
"""
pass


"""
*@name get_struct_variable_name
*@breaf get struct variable name
*@param [in] single_line - a string from source file line by line
*@return [out] struct_name - type:string
* description: structure name
"""


def get_struct_variable_name(single_line):
single_line = single_line.lstrip() # delete all space character in left
pos_struct = single_line.find('struct')
struct_name = single_line[pos_struct + 6:-1]
if '{' in struct_name:
pos_left_parenthesis = struct_name.find('{')
struct_name = struct_name[0:pos_left_parenthesis]
struct_name = struct_name.lstrip()
struct_name = struct_name.rstrip()
return struct_name


"""
*@name get_members_in_list
*@breaf get all variable member name in struct
*@param [in] member_content - The contents of all member variables in the struct
*@return [out]
"""


def get_members_in_list(member_content):
temp_list = []
pos_left_parenthesis_in_content = member_content.find('{')
pos_right_parenthesis_in_content = member_content.find('};')
content = member_content[pos_left_parenthesis_in_content + 1:pos_right_parenthesis_in_content]
temp_list = content.split(';')
if '\n' in temp_list:
temp_list.remove('\n')
if '' in temp_list:
temp_list.remove('')
if ' ' in temp_list:
temp_list.remove(' ')
return temp_list


def main():
parser = argparse.ArgumentParser()
parser.add_argument("-i", "--input", help="input file path")
parser.add_argument("-o", "--output", help="output file path, if there is no output option,the script will "
"overwrite input "
"file.")
args = parser.parse_args()
fspath = args.input
if args.output is None:
output_fs = fspath
else:
output_fs = args.output

struct_process_flag = False
content = ""
full_content = ""
with open(fspath, "rU") as f:
for line in f.readlines():
full_content += line
if 'struct' in line:
struct_process_flag = True
struct_name = get_struct_variable_name(line)
if struct_process_flag is True:
content += line
if '};' in line: # in this circumstance, content contains all structs member
struct_process_flag = False
# get str
member_list = get_members_in_list(content)
content = ""
# get reflection macro string
reflection_str = "REFLECTION(" + struct_name + ','
length_of_members = len(member_list)
count = 0
for member in member_list:
pos_last_space = member.rfind(' ')
member = member[pos_last_space:]
count = count + 1
if count != length_of_members:
reflection_str += member + ','
else:
reflection_str += member + ');'
if line[-1] == '\n':
reflection_str = reflection_str + '\n'
else:
reflection_str = '\n' + reflection_str + '\n'
full_content += reflection_str
with open(output_fs, 'w') as fp:
fp.write(full_content)


if __name__ == "__main__":
try:
sys.exit(main())
except SetupError as err:
print("errors: %s" % (err))
sys.exit()
28 changes: 28 additions & 0 deletions scripts/test_macro_generator.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
struct person {
std::string name;
int age;
};

struct two {
std::string name;
one_t one;
int age;
};

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;
};

struct composit_t2 {
int a;
std::vector<std::string> b;
int iguana;
std::map<int, int> example_test;
std::unordered_map<int, int> random_name__;
double __f__number__complex;
};

0 comments on commit 37c2ec1

Please sign in to comment.