From 0deb1d20a11271bb2546cdfc828addfac3d3e005 Mon Sep 17 00:00:00 2001 From: Adewale Azeez Date: Fri, 18 Sep 2020 02:59:36 +0100 Subject: [PATCH 01/12] add the workflow job to deploy to gh-pages --- .github/workflows/main.yml | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index bf0fdb0..be2309f 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -1,5 +1,5 @@ -name: CI/CD +name: CI-CD on: push: @@ -9,10 +9,11 @@ on: jobs: build: + if: github.event_name == 'kjkpush' && contains(github.ref, 'refs/tags/') runs-on: ${{ matrix.os }} strategy: matrix: - os: [macos-latest, ubuntu-20.04, ubuntu-18.04, ubuntu-20.04, ubuntu-latest, windows-latest] + os: [macos-latest, ubuntu-latest, windows-latest] platform: [x86, x64] compiler: [gnu, clang] @@ -43,8 +44,8 @@ jobs: build-and-deploy-gh_pages: runs-on: ubuntu-latest - needs: build - if: github.event_name == 'push' #&& contains(github.ref, 'refs/for/main') + #needs: build + #if: github.event_name == 'push' #&& contains(github.ref, 'refs/for/main') steps: - name: Checkout 🛎️ uses: actions/checkout@v2.3.1 From 9cbc7746a08d864ec898340f8deaead5913c1bf9 Mon Sep 17 00:00:00 2001 From: Adewale Azeez Date: Fri, 18 Sep 2020 03:01:23 +0100 Subject: [PATCH 02/12] add the workflow job to deploy to gh-pages --- .github/workflows/main.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index be2309f..a0943ec 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -54,6 +54,7 @@ jobs: - name: Install and Build 🔧 run: | + sudo apt-get install -y python3 python3-setuptools python3-pip python3-sphinx pip3 install themata cd ./docs/ bash ./make.sh From c5d0b6cfcac81638e6db2f3b8ee77548cd2d819e Mon Sep 17 00:00:00 2001 From: Adewale Azeez Date: Fri, 18 Sep 2020 03:05:48 +0100 Subject: [PATCH 03/12] add the workflow job to deploy to gh-pages --- .github/workflows/main.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index a0943ec..11e0402 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -55,6 +55,7 @@ jobs: - name: Install and Build 🔧 run: | sudo apt-get install -y python3 python3-setuptools python3-pip python3-sphinx + sudo apt-get install -y clang doxygen make pip3 install themata cd ./docs/ bash ./make.sh From 68e25ca2c3941b7101a0f950b187fe5fb07a5ea4 Mon Sep 17 00:00:00 2001 From: Adewale Azeez Date: Fri, 18 Sep 2020 03:14:11 +0100 Subject: [PATCH 04/12] add the workflow job to deploy to gh-pages --- .github/workflows/main.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 11e0402..d828e4d 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -54,9 +54,9 @@ jobs: - name: Install and Build 🔧 run: | - sudo apt-get install -y python3 python3-setuptools python3-pip python3-sphinx + python -m pip install --upgrade pip sudo apt-get install -y clang doxygen make - pip3 install themata + python -m pip install themata cd ./docs/ bash ./make.sh cd ../ From 189906ad2e977014777ec46f18757f3c19900af1 Mon Sep 17 00:00:00 2001 From: Adewale Azeez Date: Fri, 18 Sep 2020 03:17:28 +0100 Subject: [PATCH 05/12] add the workflow job to deploy to gh-pages --- .github/workflows/main.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index d828e4d..737bdf1 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -54,9 +54,10 @@ jobs: - name: Install and Build 🔧 run: | + sudo apt-get install -y python3 python3-setuptools python3-pip python3-sphinx python -m pip install --upgrade pip - sudo apt-get install -y clang doxygen make python -m pip install themata + sudo apt-get install -y clang doxygen make cd ./docs/ bash ./make.sh cd ../ From 1acbdee6af7201030795d64493061e0308d3f010 Mon Sep 17 00:00:00 2001 From: Adewale Azeez Date: Fri, 18 Sep 2020 03:34:05 +0100 Subject: [PATCH 06/12] add the workflow job to deploy to gh-pages --- .github/workflows/main.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 737bdf1..b07eb80 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -59,7 +59,7 @@ jobs: python -m pip install themata sudo apt-get install -y clang doxygen make cd ./docs/ - bash ./make.sh + sudo bash ./make.sh cd ../ - name: Deploy 🚀 From 31c71f4122ff1e0b8e27038fa8224a8849032932 Mon Sep 17 00:00:00 2001 From: Adewale Azeez Date: Fri, 18 Sep 2020 03:44:51 +0100 Subject: [PATCH 07/12] add the workflow job to deploy to gh-pages --- docs/make.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/make.sh b/docs/make.sh index f61ef0a..d911070 100644 --- a/docs/make.sh +++ b/docs/make.sh @@ -1,6 +1,6 @@ rm -Rf build/ -sphinx-build -b html -d build/doctrees ./ build/html +python -m sphinx -b html -d build/doctrees ./ build/html doxygen #cp ../installscripts/cester.ps1 ./build/html/ #cp ../installscripts/cester.sh ./build/html/ From 97df5d616205a8c23f54e524ccdd3ba6dd2576d3 Mon Sep 17 00:00:00 2001 From: Adewale Azeez Date: Fri, 18 Sep 2020 03:47:57 +0100 Subject: [PATCH 08/12] add the workflow job to deploy to gh-pages --- .github/workflows/main.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index b07eb80..1a2dcea 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -56,7 +56,7 @@ jobs: run: | sudo apt-get install -y python3 python3-setuptools python3-pip python3-sphinx python -m pip install --upgrade pip - python -m pip install themata + python -m pip install themata m2r2 sudo apt-get install -y clang doxygen make cd ./docs/ sudo bash ./make.sh From 7d016081fc3b795175f67546fc720ae66a2daaa9 Mon Sep 17 00:00:00 2001 From: Adewale Azeez Date: Sun, 27 Sep 2020 22:17:53 +0100 Subject: [PATCH 09/12] fix the macro issue and add some documentation --- .github/workflows/main.yml | 11 +- docs/Doxyfile | 4 +- docs/_static/css/libmetaref.css | 37 + docs/conf.py | 6 +- docs/doc/anonymous_function.md | 3 - docs/doc/field_annotation.md | 4 + docs/doc/field_reflection.md | 4 + docs/doc/index.rst | 2 +- docs/doc/macros.md | 761 ++++++++++++++++++ docs/doc/struct_annotation.md | 92 +++ docs/doc/struct_deserialization.md | 4 + docs/doc/struct_serialization.md | 4 + docs/download.md | 45 ++ docs/examples/field_annotation_usage.md | 4 + docs/examples/index.rst | 12 + docs/examples/struct_deserialization.md | 4 + docs/examples/struct_serialization.md | 4 + docs/how_it_works/how_annotation_works.md | 4 + .../how_field_reflection_works.md | 4 + docs/how_it_works/index.rst | 12 + docs/index.rst | 26 + docs/index_dump.md | 58 +- docs/make.sh | 2 - include/exotic/metaref.h | 60 +- test/crash_test.c | 42 +- test/structs/preference_struct.h | 2 +- test/structs/test_struct.h | 18 + test/structs/user_struct.h | 10 + test/structs/user_table_struct.h | 2 +- test/test_annotated_struct.c | 6 +- test/test_field_annotation.c | 4 +- 31 files changed, 1169 insertions(+), 82 deletions(-) delete mode 100644 docs/doc/anonymous_function.md create mode 100644 docs/doc/field_annotation.md create mode 100644 docs/doc/field_reflection.md create mode 100644 docs/doc/macros.md create mode 100644 docs/doc/struct_annotation.md create mode 100644 docs/doc/struct_deserialization.md create mode 100644 docs/doc/struct_serialization.md create mode 100644 docs/download.md create mode 100644 docs/examples/field_annotation_usage.md create mode 100644 docs/examples/index.rst create mode 100644 docs/examples/struct_deserialization.md create mode 100644 docs/examples/struct_serialization.md create mode 100644 docs/how_it_works/how_annotation_works.md create mode 100644 docs/how_it_works/how_field_reflection_works.md create mode 100644 docs/how_it_works/index.rst create mode 100644 test/structs/test_struct.h create mode 100644 test/structs/user_struct.h diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 1a2dcea..83603af 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -3,13 +3,12 @@ name: CI-CD on: push: - branches: [ main ] + branches: [ main, dev ] pull_request: branches: [ main ] jobs: - build: - if: github.event_name == 'kjkpush' && contains(github.ref, 'refs/tags/') + execute-regression: runs-on: ${{ matrix.os }} strategy: matrix: @@ -44,8 +43,8 @@ jobs: build-and-deploy-gh_pages: runs-on: ubuntu-latest - #needs: build - #if: github.event_name == 'push' #&& contains(github.ref, 'refs/for/main') + needs: execute-regression + if: github.event_name == 'push' && contains(github.ref, 'refs/heads/main') steps: - name: Checkout 🛎️ uses: actions/checkout@v2.3.1 @@ -66,7 +65,7 @@ jobs: uses: JamesIves/github-pages-deploy-action@3.6.1 with: GITHUB_TOKEN: ${{ secrets.GH_TOKEN_FOR_CI_CD }} - BRANCH: gh-pages # The branch the action should deploy to. + BRANCH: gh-pages FOLDER: docs/build/html CLEAN: true diff --git a/docs/Doxyfile b/docs/Doxyfile index ec1a951..8fd48e0 100644 --- a/docs/Doxyfile +++ b/docs/Doxyfile @@ -15,4 +15,6 @@ USE_MDFILE_AS_MAINPAGE = ../README.md SEARCH_INCLUDES = YES INHERIT_DOCS = YES MARKDOWN_SUPPORT = YES -RECURSIVE = YES \ No newline at end of file +RECURSIVE = YES +PREDEFINED = "__STRUCT_FILE__=Docygen.h" \ + "__STRUCT_NAME__=Docygen" \ No newline at end of file diff --git a/docs/_static/css/libmetaref.css b/docs/_static/css/libmetaref.css index eef31a5..d81134c 100644 --- a/docs/_static/css/libmetaref.css +++ b/docs/_static/css/libmetaref.css @@ -66,3 +66,40 @@ .bodywrapper { min-height: 80vh; } + +.width-45-percent { + width: 45%; +} + +.width-55-percent { + width: 55%; +} + +.width-50-percent { + width: 50%; +} + +.two-sided { + display: flex; +} + +.two-sided .left-side { + padding-right: 2%; + padding-left: 0; +} + +.two-sided .title { + font-weight: bold; +} + +.two-sided pre { + overflow-y: scroll; +} + +.bold { + font-weight: bold; +} + +.doc-sphinx-info a { + color: #5682d1 !important; +} \ No newline at end of file diff --git a/docs/conf.py b/docs/conf.py index b9b2c06..bc72d5a 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -2,7 +2,7 @@ project = 'libmetaref' copyright = '2020, Exotic Libraries - MIT License' -author = 'Exotic Libraries Contributors' +author = 'Adewale Azeez and Other Contributors' html_theme_path = [themata.get_html_theme_path()] html_theme = 'fandango' @@ -23,7 +23,7 @@ 'navbar_links': [ ('Doc', 'doc/index'), ('Reference', 'reference/index'), - ('Github', 'https://github.com/exoticlibraries/libmetaref/'), + ('Contribute', 'https://github.com/exoticlibraries/libmetaref/'), ('Exotic Libraries', 'https://exoticlibraries.github.io/'), ('Support', 'https://exoticlibraries.github.io/pages/support.html') ], @@ -34,7 +34,7 @@ ('fab fa-twitter', 'https://twitter.com/exoticlibs'), ('fab fa-github', 'https://github.com/exoticlibraries/libmetaref/') ], - "source_root": "https://github.com/exoticlibraries/libmetaref/edit/main/", + "source_root": "https://github.com/exoticlibraries/libmetaref/edit/main/docs/", "document_font_size": "15px", 'text_color': '#292929', 'header_background_color': '#292929', diff --git a/docs/doc/anonymous_function.md b/docs/doc/anonymous_function.md deleted file mode 100644 index 482d521..0000000 --- a/docs/doc/anonymous_function.md +++ /dev/null @@ -1,3 +0,0 @@ - - -# Anonymous Function \ No newline at end of file diff --git a/docs/doc/field_annotation.md b/docs/doc/field_annotation.md new file mode 100644 index 0000000..66028b2 --- /dev/null +++ b/docs/doc/field_annotation.md @@ -0,0 +1,4 @@ + + +# Field Annotation + diff --git a/docs/doc/field_reflection.md b/docs/doc/field_reflection.md new file mode 100644 index 0000000..8a2d8bf --- /dev/null +++ b/docs/doc/field_reflection.md @@ -0,0 +1,4 @@ + + +# Field Reflection + diff --git a/docs/doc/index.rst b/docs/doc/index.rst index 2c410e6..16e997e 100644 --- a/docs/doc/index.rst +++ b/docs/doc/index.rst @@ -9,4 +9,4 @@ Documentation :glob: :maxdepth: 3 - anonymous_function \ No newline at end of file + ./* \ No newline at end of file diff --git a/docs/doc/macros.md b/docs/doc/macros.md new file mode 100644 index 0000000..231ee0d --- /dev/null +++ b/docs/doc/macros.md @@ -0,0 +1,761 @@ + + +# Macros + +Most macros in the library starts with `METAREF_`. + +## METAREF_FIELD_PTR_ADDRESS_TYPE + +The macro declares the type in which the address to the field value pointer is cast to, the default value is `void **`. + +The value can be overriden by declaring the macro before including metaref.h in the source. E.g. to change the type to size_t + +```c +#define METAREF_FIELD_PTR_ADDRESS_TYPE size_t ** +``` + +## STRUCT + +The macro is used to create a struct. This macro is important for libmetaref to expand a struct and create all the neccesary functions and fields needed for annotations and reflection at runtime. + +The first parameter is the name of the struct which should also be defined at the top of the struct file as `__STRUCT_NAME__`, the following parameter is variadic which accept the [FIELD](#field) macros. The example below illustrate how C struct is traditionally created and how to use the STRUCT macro to create a C struct. + +Regular + +```c +typedef struct date_struct { + //... +} Date; +``` + +Using libmetaref + +```c +STRUCT(Date, + //... +) +``` + +The libmetaref method above will generate the Regular struct at the macro expansion phases and add all the required functions and fields needed for runtime reflection. + +## FIELD + +The field macro is used to create struct fields with support for annotation and reflection. The first parameter is the list of annotation for the field see [field annotations](./field_annotation.html) for documentation of creating field annotations, the second parameter is the field type, `char *`, int, e.t.c. the third parameter is the field identifier. + +Regular + +```c +typedef struct date_struct { + unsigned hours; + unsigned minutes; + unsigned seconds; + char *day_of_the_week; + char *month_of_the_year; +} Date; +``` + +Using libmetaref + +```c +STRUCT(Date, + FIELD({}, unsigned, hours) + FIELD({}, unsigned, minutes) + FIELD({}, unsigned, seconds) + FIELD({}, char *, day_of_the_week) + FIELD({}, char *, month_of_the_year) +) +``` + +The annotation still generates the regular valid struct field during the macro expansion phase. + +## _S + +Use the macro to add char array type annotation to a struct. + +```c +_S(DATABASE_table, "date") +STRUCT(Date, + //... +) +``` + +## _I + +Use the macro to add int type annotation to a struct. + +```c +_I(FIELD_count, 1) +STRUCT(Date, + //... +) +``` + +## _L + +Use the macro to add long type annotation to a struct. + +```c +_L(DEFAULT_number, 764763746734673674) +STRUCT(Date, + //... +) +``` + +## _F + +Use the macro to add a function type annotation to a struct. The function must be declared at the source global scope, it can be before or after the struct. + +The function signature is: + +```c +typedef void *(*func_ptr_)(const void *, void *) +``` + +Example: + +```c +_F(TO_STRING, date_to_string) +STRUCT(Date, + //... +) + +#ifndef DATE_ANNOTATION_FUNCTIONS +#define DATE_ANNOTATION_FUNCTIONS +void *date_to_string(const void *date, void *arg) { + Date *date = (Date *)date; + return (void *)"Name=libmetaref"; +} +#endif +``` + +## _FS + +Use the macro to add char array type annotation to a struct field. + +```c +STRUCT(Date, + FIELD({ + _FS(CERXOS_value, "day_of_week") + }, char *, week_day) +) +``` + +## _FI + +Use the macro to add int type annotation to a struct field. + +```c +STRUCT(Date, + STRUCT(Date, + FIELD({ + _FI(CERXOS_read, 0) + }, char *, week_day) +) +``` + +## _FL + +Use the macro to add long type annotation to a struct field. + +```c +STRUCT(Date, + STRUCT(Date, + FIELD({ + _FL(RANDOM_number, 7612766523656256) + }, char *, week_day) +) +``` + +## _FF + +Use the macro to add a function type annotation to a struct field. The function must be declared at the source global scope, it can be before or after the struct. + +The function signature is: + +```c +typedef void *(*func_ptr_)(const void *, void *) +``` + +Example: + +```c +STRUCT(Date, + STRUCT(Date, + FIELD({ + _FF(PROPERTY_get, get_week_day) + _FF(PROPERTY_set, set_week_day) + }, char *, week_day) +) + +#ifndef DATE_ANNOTATION_FUNCTIONS +#define DATE_ANNOTATION_FUNCTIONS +void *get_week_day(const void *date, void *arg) { + return (void *)((Date *)date)->week_day; +} +void *set_week_day(const void *date, void *arg) { + ((Date *)date)->week_day = arg; + return NULL; +} +#endif +``` + +## METAREF_GET_NAME + +Get the name of the struct used internally by libmetaref. `METAREF_GET_NAME(Date)` result to `METAREF_Date` + +## METAREF_GET_OBJECT + +Get the Struct object for a struct, if it null that means it has not been initialized of it has been freed.. `METAREF_GET_OBJECT(Date)` result to `METAREF_Date_Struct`. Do not attempt to use the result directly to prevent isses in case libmetaref internals changes. + +## METAREF_GET_STRUCT + +Get the `Struct` object of the struct for reflection. This requires the struct name and the defined struct variable. + +```c +Date *my_date = calloc(1, sizeof(Date)); +Struct *date_struct = METAREF_GET_STRUCT(Date, my_date); +``` + +The `date_struct` can be used for the reflection as it contains all the Struct metadatas, annotations, fields e.t.c. + +This macro internally make a call to a function created at expansion phase that set a global variable for the struct. Calling the macro multiple time will not keep allocating memory for the global variable. You can call the METAREF_FREE_STRUCT macro to fee the memory allocated to that struct global variable after the struct usage is complete. + +## METAREF_FREE_STRUCT + +Free the memory allocated to a struct internal global variable which was allocated on the macro call `METAREF_GET_STRUCT`. + +```c +Date *my_date = calloc(1, sizeof(Date)); +Struct *date_struct = METAREF_GET_STRUCT(Date, my_date); +//... +METAREF_FREE_STRUCT(date_struct); +``` + +It good practice to indicate at the end of the scope that the Struct object has been freed so it can be reinitialized if it to be used after that scope. + +```c +bool my_custom_serializer(Date *my_date) { + if (my_date == NULL) { + return FALSE; + } + + Struct *date_struct = METAREF_GET_STRUCT(Date, my_date); + //... + METAREF_FREE_STRUCT(Date); + return TRUE; +} + +``` + +After that function call if it returns TRUE that means the logic was complete and the Struct object was freed. + +## METAREF_STRUCT_GET_ANNOTATION + +Get a struct annotation by struct and the annotation name `METAREF_STRUCT_GET_ANNOTATION(Date, "DATABASE_table")`. + +## METAREF_STRUCT_GET_ANNOTATION2 + +Get a struct annotation by struct and the annotation name without quote `METAREF_STRUCT_GET_ANNOTATION2(Date, DATABASE_table)`. + +## METAREF_STRUCT_HAS_ANNOTATION + +Check if a struct has an annotation before getting it. `METAREF_STRUCT_GET_ANNOTATION(Date, "DATABASE_table")`, return 1 if the annotation exists and 0 if it does not exists. + +## METAREF_STRUCT_ANNOTATION_IS_STRING + +Check if the type of the annotation is char array, if the annotation is defined with the macro [_S](#s) it returns 1 else 0. + +## METAREF_STRUCT_ANNOTATION_STR_VALUE + +Get the char array value of a struct annotation declared with the [_S](#s) macro, `METAREF_STRUCT_ANNOTATION_STR_VALUE(Date, "DATABASE_table")`. + +## METAREF_STRUCT_ANNOTATION_IS_INT + +Check if the type of the annotation is an integer, if the annotation is defined with the macro [_I](#i) it returns 1 else 0. + +## METAREF_STRUCT_ANNOTATION_INT_VALUE + +Get the char array value of a struct annotation declared with the [_I](#i) macro, `METAREF_STRUCT_ANNOTATION_INT_VALUE(Date, "FIELD_count")`. + +## METAREF_STRUCT_ANNOTATION_IS_LONG + +Check if the type of the annotation is a long, if the annotation is defined with the macro [_L](#l) it returns 1 else 0. + +## METAREF_STRUCT_ANNOTATION_LONG_VALUE + +Get the char array value of a struct annotation declared with the [_L](#l) macro, `METAREF_STRUCT_ANNOTATION_LONG_VALUE(Date, "DEFAULT_number")`. + +## METAREF_STRUCT_ANNOTATION_IS_FUNCTION + +Check if the type of the annotation is a function, if the annotation is defined with the macro [_F](#f) it returns 1 else 0. + +## METAREF_STRUCT_ANNOTATION_FUNC_VALUE + +Get the char array value of a struct annotation declared with the [_F](#f) macro, `METAREF_STRUCT_ANNOTATION_FUNC_VALUE(Date, "TO_STRING")`. + +## FOREACH_STRUCT_ANNOTATION + +Iterate through all the annotation of a struct object. The first parameter is the struct name, the second parameter is the annotation variable, followed by the loop body. + +```c +FOREACH_STRUCT_ANNOTATION(Date, annotation, { + printf("Name=%s\n", annotation.name); + //... +}) +``` + +## FOREACH_STRUCT_ANNOTATION_INDEX + +Iterate through all the annotation of a struct object. The first parameter is the struct name, the second parameter is the current index of the annotation in the iteration, the third parameter is the annotation variable, followed by the loop body. + +```c +FOREACH_STRUCT_ANNOTATION_INDEX(Date, index, annotation, { + printf("Name=%s, At=%d\n", annotation.name, index); + //... +}) +``` + +## FOREACH_ANNOTATION + +Iterate through all the annotation of a struct object. The first parameter is the Struct object of the struct, the second parameter is the annotation variable, followed by the loop body. + +```c +Struct *date_struct = METAREF_GET_STRUCT(Date, NULL); +FOREACH_ANNOTATION(date_struct, annotation, { + printf("Name=%s\n", annotation.name); + //... +}) +METAREF_FREE_STRUCT(Date); +``` + +## FOREACH_ANNOTATION_INDEX + +Iterate through all the annotation of a struct object. The first parameter is the Struct value of the struct, the second parameter is the current index of the annotation in the iteration, the third parameter is the annotation variable, followed by the loop body. + +```c +Struct *date_struct = METAREF_GET_STRUCT(Date, NULL); +FOREACH_ANNOTATION_INDEX(date_struct, index, annotation, { + printf("Name=%s, At=%d\n", annotation.name, index); + //... +}) +METAREF_FREE_STRUCT(Date); +``` + +## METAREF_STRUCT_FIELD_COUNT + +Get the number of fields in the struct `METAREF_STRUCT_FIELD_COUNT(Date)`. + +## METAREF_GET_STRUCT_FIELD + +Get a field from a struct by it name, the Field returned will have a NULL value for it ptr_address field `METAREF_GET_STRUCT_FIELD(Date, "hours")`. + +## METAREF_HAS_FIELD + +Check if a struct has a field declared `METAREF_HAS_FIELD(Date, "hours")`. + +## FOREACH_STRUCT_FIELD + +Iterate through all the field of a struct object. The first parameter is the Struct object of the struct, the second parameter is the field variable, followed by the loop body. + +```c +FOREACH_STRUCT_FIELD(Date, field, { + //... +}) +``` + +## FOREACH_STRUCT_FIELD_INDEX + +Iterate through all the field of a struct. The first parameter is the struct name value of the struct, the second parameter is the current index of the field in the iteration, the third parameter is the field variable, followed by the loop body. + +```c +FOREACH_STRUCT_FIELD_INDEX(Date, index, field, { + //... +}) +``` + +## METAREF_FIELD_IS_CHAR_ARRAY + +Check if the field type is char array. This simply compare the type literal as it declared in the source file, it not a sure way to determine the type of a field. + +```c +Field field = METAREF_GET_STRUCT_FIELD(Date, "name_of_field"); +if (METAREF_FIELD_IS_CHAR_ARRAY(field)) { + //... +} +``` + +This compares the type literal with the following values + +- char * +- char* + +Returns 1 if the type matches any of the above values. + +## METAREF_FIELD_IS_CHAR + +Check if the field type is char. This simply compare the type literal as it declared in the source file, it not a sure way to determine the type of a field. + +```c +Field field = METAREF_GET_STRUCT_FIELD(Date, "name_of_field"); +if (METAREF_FIELD_IS_CHAR(field)) { + //... +} +``` + +This compares the type literal with the following values + +- char +- signed char + +Returns 1 if the type matches any of the above values. + +## METAREF_FIELD_IS_UCHAR + +Check if the field type is unsigned char. This simply compare the type literal as it declared in the source file, it not a sure way to determine the type of a field. + +```c +Field field = METAREF_GET_STRUCT_FIELD(Date, "name_of_field"); +if (METAREF_FIELD_IS_UCHAR(field)) { + //... +} +``` + +This compares the type literal with the following values + +- unsigned char + +Returns 1 if the type matches any of the above values. + +## METAREF_FIELD_IS_INT + +Check if the field type is int. This simply compare the type literal as it declared in the source file, it not a sure way to determine the type of a field. + +```c +Field field = METAREF_GET_STRUCT_FIELD(Date, "name_of_field"); +if (METAREF_FIELD_IS_INT(field)) { + //... +} +``` + +This compares the type literal with the following values + +- int +- signed +- signed int + +Returns 1 if the type matches any of the above values. + +## METAREF_FIELD_IS_UINT + +Check if the field type is unsigned int. This simply compare the type literal as it declared in the source file, it not a sure way to determine the type of a field. + +```c +Field field = METAREF_GET_STRUCT_FIELD(Date, "name_of_field"); +if (METAREF_FIELD_IS_UINT(field)) { + //... +} +``` + +This compares the type literal with the following values + +- unsigned +- unsigned int + +Returns 1 if the type matches any of the above values. + +## METAREF_FIELD_IS_SHORT + +Check if the field type is short. This simply compare the type literal as it declared in the source file, it not a sure way to determine the type of a field. + +```c +Field field = METAREF_GET_STRUCT_FIELD(Date, "name_of_field"); +if (METAREF_FIELD_IS_SHORT(field)) { + //... +} +``` + +This compares the type literal with the following values + +- short +- short int +- signed short +- signed short int + +Returns 1 if the type matches any of the above values. + +## METAREF_FIELD_IS_USHORT + +Check if the field type is unsigned short. This simply compare the type literal as it declared in the source file, it not a sure way to determine the type of a field. + +```c +Field field = METAREF_GET_STRUCT_FIELD(Date, "name_of_field"); +if (METAREF_FIELD_IS_USHORT(field)) { + //... +} +``` + +This compares the type literal with the following values + +- unsigned short +- unsigned short int + +Returns 1 if the type matches any of the above values. + +## METAREF_FIELD_IS_LONG + +Check if the field type is long. This simply compare the type literal as it declared in the source file, it not a sure way to determine the type of a field. + +```c +Field field = METAREF_GET_STRUCT_FIELD(Date, "name_of_field"); +if (METAREF_FIELD_IS_LONG(field)) { + //... +} +``` + +This compares the type literal with the following values + +- long +- long int +- signed long +- signed long int + +Returns 1 if the type matches any of the above values. + +## METAREF_FIELD_IS_ULONG + +Check if the field type is unsigned long. This simply compare the type literal as it declared in the source file, it not a sure way to determine the type of a field. + +```c +Field field = METAREF_GET_STRUCT_FIELD(Date, "name_of_field"); +if (METAREF_FIELD_IS_ULONG(field)) { + //... +} +``` + +This compares the type literal with the following values + +- unsigned long +- unsigned long int + +Returns 1 if the type matches any of the above values. + +## METAREF_FIELD_IS_FLOAT + +Check if the field type is float. This simply compare the type literal as it declared in the source file, it not a sure way to determine the type of a field. + +```c +Field field = METAREF_GET_STRUCT_FIELD(Date, "name_of_field"); +if (METAREF_FIELD_IS_FLOAT(field)) { + //... +} +``` + +This compares the type literal with the following values + +- float + +Returns 1 if the type matches any of the above values. + +## METAREF_FIELD_IS_DOUBLE + +Check if the field type is double. This simply compare the type literal as it declared in the source file, it not a sure way to determine the type of a field. + +```c +Field field = METAREF_GET_STRUCT_FIELD(Date, "name_of_field"); +if (METAREF_FIELD_IS_DOUBLE(field)) { + //... +} +``` + +This compares the type literal with the following values + +- double + +Returns 1 if the type matches any of the above values. + +## METAREF_FIELD_IS_LONG_DOUBLE + +Check if the field type is long double. This simply compare the type literal as it declared in the source file, it not a sure way to determine the type of a field. + +```c +Field field = METAREF_GET_STRUCT_FIELD(Date, "name_of_field"); +if (METAREF_FIELD_IS_LONG_DOUBLE(field)) { + //... +} +``` + +This compares the type literal with the following values + +- long double + +Returns 1 if the type matches any of the above values. + +## METAREF_GET_FIELD_ANNOTATIONS + +Get the static list of annotations for the field `METAREF_GET_FIELD_ANNOTATIONS(field)`. + +## FOREACH_FIELD_ANNOTATION + +Iterate through all the field annotations. The first parameter is the field object, the second parameter is the annotation variable, followed by the loop body. + +```c +Field field = METAREF_GET_STRUCT_FIELD(Date, "name_of_field"); +FOREACH_FIELD_ANNOTATION(field, annotation, { + //... +}) +``` + +## FOREACH_FIELD_ANNOTATION_INDEX + +Iterate through all the field annotations. The first parameter is the field object, the second parameter is the index of the current annotation in the iteration, the third parameter is the annotation variable, followed by the loop body. + +```c +Field field = METAREF_GET_STRUCT_FIELD(Date, "name_of_field"); +FOREACH_FIELD_ANNOTATION_INDEX(field, index, annotation, { + //... +}) +``` + +## METAREF_FIELD_GET_ANNOTATION + +Get a field annotation using it name, `METAREF_FIELD_GET_ANNOTATION(field, "CERXOS_value")`. + +## METAREF_FIELD_GET_ANNOTATION2 + +Get a field annotation using it name without quote, `METAREF_FIELD_GET_ANNOTATION2(field, CERXOS_value)`. + +## METAREF_FIELD_HAS_ANNOTATION + +Check if a field has an annotation before performing an operation. + +```c +if (METAREF_FIELD_HAS_ANNOTATION(field, "CERXOS_value"))) { + //... +} +``` + +## METAREF_FIELD_ANNOTATION_IS_STRING + +Check if the type of the field annotation is char array, if the annotation is defined with the macro [_FS](#fs) it returns 1 else 0. + +## METAREF_FIELD_ANNOTATION_STR_VALUE + +Get the char array value of a field annotation declared with the [_FS](#fs) macro, `METAREF_FIELD_ANNOTATION_STR_VALUE(field, "CERXOS_value")`. + +## METAREF_FIELD_ANNOTATION_IS_INT + +Check if the type of the field annotation is an integer, if the annotation is defined with the macro [_FI](#fi) it returns 1 else 0. + +## METAREF_FIELD_ANNOTATION_INT_VALUE + +Get the char array value of a field annotation declared with the [_FI](#fi) macro, `METAREF_FIELD_ANNOTATION_INT_VALUE(field, "SIZE_min")`. + +## METAREF_FIELD_ANNOTATION_IS_LONG + +Check if the type of the field annotation is a long, if the annotation is defined with the macro [_FL](#fl) it returns 1 else 0. + +## METAREF_FIELD_ANNOTATION_LONG_VALUE + +Get the char array value of a field annotation declared with the [_FL](#fl) macro, `METAREF_FIELD_ANNOTATION_LONG_VALUE(field, "SIZE_max")`. + +## METAREF_FIELD_ANNOTATION_IS_FUNCTION + +Check if the type of the field annotation is a function, if the annotation is defined with the macro [_FF](#ff) it returns 1 else 0. + +## METAREF_FIELD_ANNOTATION_FUNC_VALUE + +Get the char array value of a field annotation declared with the [_FF](#ff) macro, `METAREF_FIELD_ANNOTATION_FUNC_VALUE(field, "get_prefix")`. + +## METAREF_GET_FIELD + +Get a field using it name from the meta Struct object. Using this will guarantee the value of the ptr_address of the field to be set. + +```c +Date *date = (Date *) inst->arg; +Struct *date_struct = METAREF_GET_STRUCT(Date, date); +Field time_field = METAREF_GET_FIELD(date_struct, "time"); +``` + +## FOREACH_FIELD + +Iterate through all the field in the struct object. The first parameter is the struct object, the second parameter is the field variable, followed by the loop body. + +```c +Date *date = (Date *) inst->arg; +Struct *the_struct = METAREF_GET_STRUCT(Date, date); +FOREACH_FIELD(the_struct, field, { + //... +}) +``` + +## FOREACH_FIELD_INDEX + +Iterate through all the field in the struct object. The first parameter is the struct object, the second parameter is the index of the current field in the iteration, the third parameter is the field variable, followed by the loop body. + +```c +Date *date = (Date *) inst->arg; +Struct *the_struct = METAREF_GET_STRUCT(Date, date); +FOREACH_FIELD_INDEX(the_struct, index, field, { + //... +}) +``` + +## METAREF_FIELD_VALUE_IS_NULL + +Check if the pointer to the address of the field value is NULL `METAREF_FIELD_VALUE_IS_NULL(field)`. + +## METAREF_FIELD_VALUE_PTR + +Get the pointer to the address of the field value `METAREF_FIELD_VALUE_PTR(field)`. Returns the `void *` value. + +## METAREF_FIELD_VALUE_PTR_AS + +Get the pointer to the address of the field value `METAREF_FIELD_VALUE_PTR(int, field)` cast to th type. Returns the `type *` value. + +```c +Field field = METAREF_GET_STRUCT_FIELD(Date, "name_of_field"); +int *int_ptr = METAREF_FIELD_VALUE_PTR(int, field); +int int_value = *METAREF_FIELD_VALUE_PTR(int, field); +int int_value2 = *int_ptr; +``` + +## METAREF_SET_FIELD_VALUE + +Set the value of a field by changing the value at the address of the previous value. + +```c +Field day_field = METAREF_GET_FIELD(date_struct, "day"); +METAREF_SET_FIELD_VALUE(day_field, 5); +``` + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/docs/doc/struct_annotation.md b/docs/doc/struct_annotation.md new file mode 100644 index 0000000..5cdf652 --- /dev/null +++ b/docs/doc/struct_annotation.md @@ -0,0 +1,92 @@ + + +# Struct Annotation + +libmetaref provides various macros to add annotation to a struct. Each struct annotation macro accept different types. + +- [_S](./macros.html#s) +- [_i](./macros.html#i) +- [_l](./macros.html#l) +- [_F](./macros.html#f) + +## Annotation structure + +```c +typedef struct annotation_struct_ { + const size_t line_num; + const AnnotationType type; + const char *name; + const char *str_value; + int int_value; + long long long_value; + func_ptr_ func_ptr; +} Annotation; +``` + +The line_num is the line number where the annotation is declared, the type is the type of annotation it will be one of the following values: + +- METAREF_ANNOTATION_STRING, +- METAREF_ANNOTATION_INT, +- METAREF_ANNOTATION_LONG, +- METAREF_ANNOTATION_FUNCTION, +- METAREF_ANNOTATION_TERMINATOR + +## Creating annotations + +The annotation is declared at the top before the struct. + +```c +#define __STRUCT_FILE__ "test_struct.h" +#define __STRUCT_NAME__ Test +#include + +_S(DATABASE_table, "test") +_I(SIZE_min, 10) +_F(TO_STRING, test_to_string) +STRUCT(Test, + //... +) + +#ifndef TEST_ANNOTATION_FUNCTION +#define TEST_ANNOTATION_FUNCTION +void *test_to_string(const void *test, void *arg) { + return (void *)"Name=test"; +} +#endif +``` + +## Using the annotations at runtime + +Each declared annotations can be accessed at runtime using one of the macros provided in the library. The example below check if a struct has an annotation then get it value. + +```c +#include +#include + +int main(int argc, char **argv) { + if (METAREF_STRUCT_HAS_ANNOTATION(Test, "DATABASE_table")) { + printf("Table Name: %s\n", + METAREF_STRUCT_ANNOTATION_STR_VALUE(Test, "DATABASE_table")); + } + if (METAREF_STRUCT_HAS_ANNOTATION(Test, "TO_STRING")) { + func_ptr_ func = METAREF_STRUCT_ANNOTATION_FUNC_VALUE(Test, "TO_STRING"); + printf("Test to String: %s\n", func(NULL, NULL)); + } +} +``` + +## Iterating through the annotations + +The macro FOREACH_STRUCT_ANNOTATION can be used to iterate through all the annotations in a struct: + +```c +#include +#include + +int main(int argc, char **argv) { + FOREACH_STRUCT_ANNOTATION(Test, annotation, { + printf("Name=%s\n", annotation.name); + }) +} +``` + diff --git a/docs/doc/struct_deserialization.md b/docs/doc/struct_deserialization.md new file mode 100644 index 0000000..0f64e34 --- /dev/null +++ b/docs/doc/struct_deserialization.md @@ -0,0 +1,4 @@ + + +# Struct Deserialization + diff --git a/docs/doc/struct_serialization.md b/docs/doc/struct_serialization.md new file mode 100644 index 0000000..3bd38f4 --- /dev/null +++ b/docs/doc/struct_serialization.md @@ -0,0 +1,4 @@ + + +# Struct Serialization + diff --git a/docs/download.md b/docs/download.md new file mode 100644 index 0000000..5c83417 --- /dev/null +++ b/docs/download.md @@ -0,0 +1,45 @@ + +# Download + +The library is compliant with C99 and C++11 any lesser version is not supported, Also the compiler must support the variadic parameter in the macro declaration and the macro constant `__VA_ARGS__`. + +## From Source + +Simply download the header file libmetaref.h from the repo into your project source folder and include it in your project. Download the file from https://github.com/exoticlibraries/libmetaref/releases or from any of the branches. Then you can include it in your project relatively like `#include "libmetaref.h"`. + +## Using irorun + +Install irorun from https://exoticlibraries.github.io/irorun + +Installing directly from the repo + +``` +irorun install libmetaref --github=https://github.com/exoticlibraries/libmetaref +``` + +Installing from vcpkg directory + +``` +irorun install libmetaref +``` + +The library will be installed for the following compilers and others installed compilers recognized by irorun. + +- GCC +- CMAKE +- Visual C++ + +## Using Microsoft vcpkg + +``` +vcpkg install libmetaref +``` + +To use the library after installation with vcpkg with your build system, continue with [vcpkg documentation](https://github.com/microsoft/vcpkg/blob/master/docs/index.md) and [integration with build systems](https://github.com/microsoft/vcpkg/blob/master/docs/users/integration.md) + +
+

Note

+

Always add the relative or absolute path to the struct file(s) during compilation e.g. -I./structs

+
+ + \ No newline at end of file diff --git a/docs/examples/field_annotation_usage.md b/docs/examples/field_annotation_usage.md new file mode 100644 index 0000000..ab024e6 --- /dev/null +++ b/docs/examples/field_annotation_usage.md @@ -0,0 +1,4 @@ + + +# Field Annotation Usage + diff --git a/docs/examples/index.rst b/docs/examples/index.rst new file mode 100644 index 0000000..125f7f3 --- /dev/null +++ b/docs/examples/index.rst @@ -0,0 +1,12 @@ + +.. index:: + single: examples + +Examples +============== + +.. toctree:: + :glob: + :maxdepth: 3 + + ./* \ No newline at end of file diff --git a/docs/examples/struct_deserialization.md b/docs/examples/struct_deserialization.md new file mode 100644 index 0000000..0f64e34 --- /dev/null +++ b/docs/examples/struct_deserialization.md @@ -0,0 +1,4 @@ + + +# Struct Deserialization + diff --git a/docs/examples/struct_serialization.md b/docs/examples/struct_serialization.md new file mode 100644 index 0000000..3bd38f4 --- /dev/null +++ b/docs/examples/struct_serialization.md @@ -0,0 +1,4 @@ + + +# Struct Serialization + diff --git a/docs/how_it_works/how_annotation_works.md b/docs/how_it_works/how_annotation_works.md new file mode 100644 index 0000000..7bb4514 --- /dev/null +++ b/docs/how_it_works/how_annotation_works.md @@ -0,0 +1,4 @@ + + +# How Annotation Works + diff --git a/docs/how_it_works/how_field_reflection_works.md b/docs/how_it_works/how_field_reflection_works.md new file mode 100644 index 0000000..5f6ddca --- /dev/null +++ b/docs/how_it_works/how_field_reflection_works.md @@ -0,0 +1,4 @@ + + +# How Field Reflection Works + diff --git a/docs/how_it_works/index.rst b/docs/how_it_works/index.rst new file mode 100644 index 0000000..15b6dd1 --- /dev/null +++ b/docs/how_it_works/index.rst @@ -0,0 +1,12 @@ + +.. index:: + single: how_it_works + +How it works +============== + +.. toctree:: + :glob: + :maxdepth: 3 + + ./* \ No newline at end of file diff --git a/docs/index.rst b/docs/index.rst index 4944066..1502c5f 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -3,6 +3,14 @@ .. index:: single: index_dump +.. toctree:: + :maxdepth: 1 + :hidden: + :glob: + :name: main-nav + + /download + .. toctree:: :maxdepth: 1 :hidden: @@ -12,6 +20,24 @@ /doc/* +.. toctree:: + :maxdepth: 1 + :hidden: + :glob: + :caption: How it works + :name: main-how-it-works + + /how_it_works/* + +.. toctree:: + :maxdepth: 1 + :hidden: + :glob: + :caption: Examples + :name: main-examples + + /examples/* + .. mdinclude:: index_dump.md diff --git a/docs/index_dump.md b/docs/index_dump.md index d453c29..0f11a6c 100644 --- a/docs/index_dump.md +++ b/docs/index_dump.md @@ -1,4 +1,6 @@ +# libmetaref +
libmetaref logo

libmetaref
@@ -13,4 +15,58 @@
-# Features +# Struct and Field Annotation + +Annotate a struct for inspection at runtime. Use +annotation to extend the struct, add options for various +libraries that uses libmetaref for extended functionalities. + +
+
+
+#define __STRUCT_FILE__ "user_struct.h"
+#define __STRUCT_NAME__ User
+#include <exotic/metaref.h>
+
+_S(DATABASE_table, "user")
+_I(SIZE_min, 10)
+STRUCT(User,
+    FIELD({}, char *, fullname)
+    FIELD({}, char *, email)
+)
+        
+
+
+ +# Runtime Reflection + +Inspect struct fields and annotation at runtime. Get fields name, +annotation and modify value using the field address to the value pointer. + +
+
+
+#include <stdio.h>
+#include <structs/user_struct.h>
+
+int main(int argc, char **argv) {
+    FOREACH_STRUCT_ANNOTATION(User, annotation, {
+        printf("Annotation Name=%s\n", annotation.name);
+    })    
+    FOREACH_STRUCT_FIELD(User, field, {
+        printf("Field Name=%s, Type=%s\n", field.name, field.type);
+    })
+    return 0;
+}
+        
+
+
+ +# Serialization and Deserialization + +A struct created with the macros provided by libmetaref can be easilly +interface with for serialization and deserialization through composition. +The struct is declared with an extra variable of type [Struct](#) that can be used in the +serialization and deserialization functions. + +See this [example](https://github.com/exoticlibraries/libmetaref/blob/main/test/test_serialization.c) that does a simple struct serialization. diff --git a/docs/make.sh b/docs/make.sh index d911070..c8155b5 100644 --- a/docs/make.sh +++ b/docs/make.sh @@ -2,6 +2,4 @@ rm -Rf build/ python -m sphinx -b html -d build/doctrees ./ build/html doxygen -#cp ../installscripts/cester.ps1 ./build/html/ -#cp ../installscripts/cester.sh ./build/html/ touch ./build/html/.nojekyll \ No newline at end of file diff --git a/include/exotic/metaref.h b/include/exotic/metaref.h index 36ed0e1..4cac2bd 100644 --- a/include/exotic/metaref.h +++ b/include/exotic/metaref.h @@ -51,6 +51,8 @@ extern "C" { #ifndef METAREF_STRUCTS_DECLARED #define METAREF_STRUCTS_DECLARED +#include + /** Concatenate two objects implicitly */ @@ -66,7 +68,7 @@ extern "C" { function value instead of string. The function accept a void* parameter and returns void*. */ -typedef void *(*func_ptr_)(const void *); +typedef void *(*func_ptr_)(const void *, void *); typedef enum metaref_annotation_type_ { METAREF_ANNOTATION_STRING, @@ -600,6 +602,12 @@ extern "C" { */ #define METAREF_GET_NAME(struct_name) METAREF_##struct_name +/** + Get the Struct object for a struct, if it null that + means it has not been initialized of it has been freed. +*/ +#define METAREF_GET_OBJECT(struct_name) METAREF_##struct_name##_Struct + /** Initialize the `Struct *` object of the struct, calling this more than once will only return the same value as @@ -775,30 +783,30 @@ extern "C" { } /** - Iterate through all the struct annotations + Iterate through all the struct annotation - \param the_struct the struct object + \param struct_name the struct name (not variable name) + \param index the annotation object index (size_t) \param annotation the annotation object (string) \param body the for loop body */ -#define FOREACH_ANNOTATION(the_struct, annotation, body)\ - for(size_t i = 0; the_struct->annotations_array[i].type != METAREF_ANNOTATION_TERMINATOR; ++i) {\ - Annotation annotation = the_struct->annotations_array[i]; \ +#define FOREACH_STRUCT_ANNOTATION_INDEX(struct_name, index, annotation, body)\ + for(size_t i = 0; METAREF_##struct_name##_annotations[i].type != METAREF_ANNOTATION_TERMINATOR; ++i) {\ + size_t index = i;\ + Annotation annotation = METAREF_##struct_name##_annotations[index]; \ body \ } /** - Iterate through all the struct annotation + Iterate through all the struct annotations - \param struct_name the struct name (not variable name) - \param index the annotation object index (size_t) + \param the_struct the struct object \param annotation the annotation object (string) \param body the for loop body */ -#define FOREACH_STRUCT_ANNOTATION_INDEX(struct_name, index, annotation, body)\ - for(size_t i = 0; METAREF_##struct_name##_annotations[i].type != METAREF_ANNOTATION_TERMINATOR; ++i) {\ - size_t index = i;\ - Annotation annotation = METAREF_##struct_name##_annotations[index]; \ +#define FOREACH_ANNOTATION(the_struct, annotation, body)\ + for(size_t i = 0; the_struct->annotations_array[i].type != METAREF_ANNOTATION_TERMINATOR; ++i) {\ + Annotation annotation = the_struct->annotations_array[i]; \ body \ } @@ -1098,7 +1106,7 @@ extern "C" { following values - long - - short int + - long int - signed long - signed long int @@ -1243,7 +1251,6 @@ extern "C" { /** Iterate through all the field annotations - \param struct_name the struct name (not variable name) \param field the field object to get it annotations \param annotation the active annotation value \param body the for loop body @@ -1254,6 +1261,21 @@ extern "C" { body \ } +/** + Iterate through all the field annotations + + \param field the field object to get it annotations + \param index the index of the current annotation + \param annotation the active annotation value + \param body the for loop body +*/ +#define FOREACH_FIELD_ANNOTATION_INDEX(field, index, annotation, body)\ + for(size_t mr_i_ = 0; field.annotations[mr_i_].line_num != 0; ++mr_i_) {\ + size_t index = mr_i_;\ + Annotation annotation = field.annotations[index]; \ + body \ + } + /** Get a field annotation using the annotation name @@ -1396,12 +1418,11 @@ extern "C" { Use this loop to get a struct field with it value - \param struct_name the struct name (not variable name) - \param obj the struct object + \param the_struct the struct variable \param field the field variable to use in the loop \param body the for loop body */ -#define FOREACH_FIELD(struct_name, obj, field, body)\ +#define FOREACH_FIELD(the_struct, field, body)\ for(size_t i = 0; the_struct->fields_array[i].type != NULL; ++i) {\ Field field = the_struct->fields_array[i]; \ body \ @@ -1413,8 +1434,7 @@ extern "C" { Use this loop to get a struct field with it value - \param struct_name the struct name (not variable name) - \param obj the struct object + \param the_struct the struct variable \param index the index of the field in the array \param field the field variable to use in the loop \param body the for loop body diff --git a/test/crash_test.c b/test/crash_test.c index 303809c..97a715d 100644 --- a/test/crash_test.c +++ b/test/crash_test.c @@ -1,44 +1,10 @@ /*!gcc {0} -I../../libcester/include/ -I. -I./structs -I../include/ -o out.exe; ./out.exe */ #include -#include - -typedef struct Struct_Field { - int number; - char *type; -} Field; - -const static Field METAREF_Date_fields[] = { - {1, "time"}, - {1, "day"}, - {1, "month"}, - {0, NULL}, -}; - -typedef struct metaref_obj__ { - const Field* field_array; -} MetarefStruct; - -typedef struct METAREF_Date { - char * time; - int day; - int month; - MetarefStruct* metaref_obj; -} Date; - -void print_(MetarefStruct *the_struct) { - for(size_t i = 0; the_struct->field_array[i].type != NULL; ++i) { - Field field = the_struct->field_array[i]; - printf(" %s\n", field.type); - } -} +#include int main(int argc, char **argv) { - Date *date = malloc(sizeof(Date)); - date->metaref_obj = malloc(sizeof(MetarefStruct)); - date->metaref_obj->field_array = METAREF_Date_fields; - printf("%p\n", date->metaref_obj->field_array[0]); - print_(date->metaref_obj); - - return 0; + FOREACH_STRUCT_ANNOTATION(Test, annotation, { + printf("Name=%s\n", annotation.name); + }) } \ No newline at end of file diff --git a/test/structs/preference_struct.h b/test/structs/preference_struct.h index ca5ba4b..53e2097 100644 --- a/test/structs/preference_struct.h +++ b/test/structs/preference_struct.h @@ -30,7 +30,7 @@ STRUCT(Preference, #ifndef PREFERENCE_STRUCT_FUNCTION #define PREFERENCE_STRUCT_FUNCTION -void *get_map_prefix(const void *arg) { +void *get_map_prefix(const void *the_struct, void *arg) { return (void *)"https://www.google.ng/maps/place/"; } #endif \ No newline at end of file diff --git a/test/structs/test_struct.h b/test/structs/test_struct.h new file mode 100644 index 0000000..44235db --- /dev/null +++ b/test/structs/test_struct.h @@ -0,0 +1,18 @@ +#define __STRUCT_FILE__ "test_struct.h" +#define __STRUCT_NAME__ Test +#include + +_S(DATABASE_table, "test") +_I(SIZE_min, 10) +_F(TO_STRING, test_to_string) +STRUCT(Test, + FIELD({}, char *, fullname) + FIELD({}, char *, email) +) + +#ifndef TEST_ANNOTATION_FUNCTION +#define TEST_ANNOTATION_FUNCTION +void *test_to_string(const void *test, void *arg) { + return (void *)"Name=test"; +} +#endif \ No newline at end of file diff --git a/test/structs/user_struct.h b/test/structs/user_struct.h new file mode 100644 index 0000000..14964d3 --- /dev/null +++ b/test/structs/user_struct.h @@ -0,0 +1,10 @@ +#define __STRUCT_FILE__ "user_struct.h" +#define __STRUCT_NAME__ User +#include + +_S(DATABASE_table, "user") +_I(SIZE_min, 10) +STRUCT(User, + FIELD({}, char *, fullname) + FIELD({}, char *, email) +) \ No newline at end of file diff --git a/test/structs/user_table_struct.h b/test/structs/user_table_struct.h index 9667337..e698edc 100644 --- a/test/structs/user_table_struct.h +++ b/test/structs/user_table_struct.h @@ -16,7 +16,7 @@ STRUCT(User, #ifndef USER_ANNOTATION_FUNCTION #define USER_ANNOTATION_FUNCTION -void *user_to_string(const void *user) { +void *user_to_string(const void *user, void *arg) { return (void *)"Name=libmetaref"; } #endif \ No newline at end of file diff --git a/test/test_annotated_struct.c b/test/test_annotated_struct.c index 9a1995f..e9b24ad 100644 --- a/test/test_annotated_struct.c +++ b/test/test_annotated_struct.c @@ -14,8 +14,8 @@ CESTER_TEST(iterate_all_struct_annotation, _, ) CESTER_TEST(iterate_all_struct_annotation_clean, _, - Struct *the_struct = METAREF_GET_STRUCT(User, NULL); - FOREACH_ANNOTATION(the_struct, annotation, { + Struct *user_struct = METAREF_GET_STRUCT(User, NULL); + FOREACH_ANNOTATION(user_struct, annotation, { cester_assert_ptr_not_equal(NULL, (void*)annotation.name); cester_assert_str_not_equal(annotation.name, NULL); }) @@ -45,7 +45,7 @@ CESTER_TEST(check_struct_function_annotation, _, cester_assert_ptr_not_equal((void*)METAREF_STRUCT_GET_ANNOTATION(User, "TO_STRING").name, NULL); cester_assert_false(METAREF_STRUCT_ANNOTATION_IS_STRING(User, "TO_STRING")); cester_assert_true(METAREF_STRUCT_ANNOTATION_IS_FUNCTION(User, "TO_STRING")); - char *user_str = (char *) METAREF_STRUCT_ANNOTATION_FUNC_VALUE(User, "TO_STRING")(NULL); + char *user_str = (char *) METAREF_STRUCT_ANNOTATION_FUNC_VALUE(User, "TO_STRING")(NULL, NULL); cester_assert_str_not_equal(user_str, "user"); cester_assert_str_equal(user_str, "Name=libmetaref"); ) diff --git a/test/test_field_annotation.c b/test/test_field_annotation.c index 5db8444..0599b7f 100644 --- a/test/test_field_annotation.c +++ b/test/test_field_annotation.c @@ -27,7 +27,7 @@ CESTER_TEST(iterate_annotations_raw, _, for(i = 0; google_map_link_field.annotations[i].line_num != 0; ++i) { if (google_map_link_field.annotations[i].type == METAREF_ANNOTATION_FUNCTION) { cester_assert_str_not_equal(google_map_link_field.annotations[i].name, - (char *)google_map_link_field.annotations[i].func_ptr(NULL)); + (char *)google_map_link_field.annotations[i].func_ptr(NULL, NULL)); } } @@ -54,7 +54,7 @@ CESTER_TEST(iterate_annotations_macro_helper, _, }) Field field3 = METAREF_GET_STRUCT_FIELD(Preference, "fullname"); - FOREACH_FIELD_ANNOTATION(field3, annotation, { + FOREACH_FIELD_ANNOTATION_INDEX(field3, index, annotation, { cester_assert_str_not_equal(annotation.name, ""); }) ) From 4e5e1caa8fbc3267049d59ec86b43e72985bcc9d Mon Sep 17 00:00:00 2001 From: Adewale Azeez Date: Sun, 27 Sep 2020 22:21:05 +0100 Subject: [PATCH 10/12] fix the macro issue and add some documentation --- test/test_field_annotation_type.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/test_field_annotation_type.c b/test/test_field_annotation_type.c index 05c5e65..4121026 100644 --- a/test/test_field_annotation_type.c +++ b/test/test_field_annotation_type.c @@ -79,8 +79,8 @@ CESTER_TEST(check_field_function_annotation, _, cester_assert_ptr_not_equal((void*)METAREF_FIELD_GET_ANNOTATION(field, "URL_prefix").name, NULL); cester_assert_false(METAREF_FIELD_ANNOTATION_IS_STRING(field, "URL_prefix")); cester_assert_true(METAREF_FIELD_ANNOTATION_IS_FUNCTION(field, "URL_prefix")); - cester_assert_str_not_equal((char *) METAREF_FIELD_ANNOTATION_FUNC_VALUE(field, "URL_prefix")(NULL), NULL); - cester_assert_str_equal((char *) METAREF_FIELD_ANNOTATION_FUNC_VALUE(field, "URL_prefix")(NULL), "https://www.google.ng/maps/place/"); + cester_assert_str_not_equal((char *) METAREF_FIELD_ANNOTATION_FUNC_VALUE(field, "URL_prefix")(NULL, NULL), NULL); + cester_assert_str_equal((char *) METAREF_FIELD_ANNOTATION_FUNC_VALUE(field, "URL_prefix")(NULL, NULL), "https://www.google.ng/maps/place/"); ) CESTER_OPTIONS( From 3683609dbfb82f7c1c25bddfbee25bf32393ccd9 Mon Sep 17 00:00:00 2001 From: Live session user Date: Thu, 1 Oct 2020 07:36:53 +0000 Subject: [PATCH 11/12] update remote --- .github/workflows/main.yml | 4 +- docs/Doxyfile | 38 ++-- docs/_static/css/libmetaref.css | 208 +++++++++--------- docs/conf.py | 130 +++++------ docs/doc/field_annotation.md | 101 ++++++++- docs/doc/field_reflection.md | 8 +- docs/doc/index.rst | 22 +- docs/doc/macros.md | Bin 20922 -> 21683 bytes docs/doc/struct_annotation.md | 186 ++++++++-------- docs/doc/struct_deserialization.md | 8 +- docs/doc/struct_serialization.md | 8 +- docs/download.md | 88 ++++---- docs/examples/field_annotation_usage.md | 4 - docs/examples/index.rst | 12 - docs/examples/struct_deserialization.md | 4 - docs/examples/struct_serialization.md | 4 - docs/how_it_works/how_annotation_works.md | 8 +- .../how_field_reflection_works.md | 8 +- docs/how_it_works/index.rst | 22 +- docs/index.rst | 9 - test/crash_test.c | 24 +- test/structs/preference_struct.h | 70 +++--- test/structs/test_struct.h | 34 +-- test/structs/user_struct.h | 18 +- test/structs/user_table_struct.h | 42 ++-- 25 files changed, 565 insertions(+), 495 deletions(-) delete mode 100644 docs/examples/field_annotation_usage.md delete mode 100644 docs/examples/index.rst delete mode 100644 docs/examples/struct_deserialization.md delete mode 100644 docs/examples/struct_serialization.md diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 83603af..125963f 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -3,7 +3,7 @@ name: CI-CD on: push: - branches: [ main, dev ] + branches: [ main ] pull_request: branches: [ main ] @@ -36,6 +36,8 @@ jobs: test-exclude-file-pattern: | mock+ crash_test.c + test-exclude-file-pattern-windows: | + test_struct_fields_types_clean+ compiler-options-for-tests: | -I. -I./test/structs diff --git a/docs/Doxyfile b/docs/Doxyfile index 8fd48e0..4951a12 100644 --- a/docs/Doxyfile +++ b/docs/Doxyfile @@ -1,20 +1,20 @@ -# https://github.com/vovkos/doxyrest#2-prepare-configuration-files - -PROJECT_NAME = "libmetaref" -INPUT = ../README.md ../include/ -GENERATE_XML = YES -GENERATE_HTML = YES -GENERATE_LATEX = NO -XML_OUTPUT = build/html/reference/xml/ -HTML_OUTPUT = build/html/reference/ -XML_PROGRAMLISTING = NO -CASE_SENSE_NAMES = NO -HIDE_UNDOC_RELATIONS = YES -EXTRACT_ALL = YES -USE_MDFILE_AS_MAINPAGE = ../README.md -SEARCH_INCLUDES = YES -INHERIT_DOCS = YES -MARKDOWN_SUPPORT = YES -RECURSIVE = YES -PREDEFINED = "__STRUCT_FILE__=Docygen.h" \ +# https://github.com/vovkos/doxyrest#2-prepare-configuration-files + +PROJECT_NAME = "libmetaref" +INPUT = ../README.md ../include/ +GENERATE_XML = YES +GENERATE_HTML = YES +GENERATE_LATEX = NO +XML_OUTPUT = build/html/reference/xml/ +HTML_OUTPUT = build/html/reference/ +XML_PROGRAMLISTING = NO +CASE_SENSE_NAMES = NO +HIDE_UNDOC_RELATIONS = YES +EXTRACT_ALL = YES +USE_MDFILE_AS_MAINPAGE = ../README.md +SEARCH_INCLUDES = YES +INHERIT_DOCS = YES +MARKDOWN_SUPPORT = YES +RECURSIVE = YES +PREDEFINED = "__STRUCT_FILE__=Docygen.h" \ "__STRUCT_NAME__=Docygen" \ No newline at end of file diff --git a/docs/_static/css/libmetaref.css b/docs/_static/css/libmetaref.css index d81134c..1ba5a7b 100644 --- a/docs/_static/css/libmetaref.css +++ b/docs/_static/css/libmetaref.css @@ -1,105 +1,105 @@ - - - -.header { - position: absolute; - background-color: #292929; - color: white; - top: 0; - padding-top: 110px; - left: 0; - right: 0; - width: 100% !important; - height: 400px; - text-align: center; - vertical-align: middle; - overflow: hidden; -} - -.header .title { - color: white; - font-size: 300%; -} - -.header .brief { - margin-top: 20px !important; -} - -.header img { - width: 100px; - height: 100px; -} - -.header .linksdiv { - padding-top: 60px; - min-height: 100%; - overflow: hidden; -} - -.header .link { - margin: 10px; - padding: 12px; - padding-left: 35px; - padding-right: 35px; - background: white; - color: #292929 !important; - text-decoration: none; - border-radius: 5px; - border: white 1px solid; -} - -.header .link:hover { - text-decoration: none; - background: #292929; - color: white !important; -} - -.header p { - color: white !important; - font-size: 21px; - margin-top: 5px; - text-align: center; - width: 50%; - margin:0 auto; -} - -.bodywrapper { - min-height: 80vh; -} - -.width-45-percent { - width: 45%; -} - -.width-55-percent { - width: 55%; -} - -.width-50-percent { - width: 50%; -} - -.two-sided { - display: flex; -} - -.two-sided .left-side { - padding-right: 2%; - padding-left: 0; -} - -.two-sided .title { - font-weight: bold; -} - -.two-sided pre { - overflow-y: scroll; -} - -.bold { - font-weight: bold; -} - -.doc-sphinx-info a { - color: #5682d1 !important; + + + +.header { + position: absolute; + background-color: #292929; + color: white; + top: 0; + padding-top: 110px; + left: 0; + right: 0; + width: 100% !important; + height: 400px; + text-align: center; + vertical-align: middle; + overflow: hidden; +} + +.header .title { + color: white; + font-size: 300%; +} + +.header .brief { + margin-top: 20px !important; +} + +.header img { + width: 100px; + height: 100px; +} + +.header .linksdiv { + padding-top: 60px; + min-height: 100%; + overflow: hidden; +} + +.header .link { + margin: 10px; + padding: 12px; + padding-left: 35px; + padding-right: 35px; + background: white; + color: #292929 !important; + text-decoration: none; + border-radius: 5px; + border: white 1px solid; +} + +.header .link:hover { + text-decoration: none; + background: #292929; + color: white !important; +} + +.header p { + color: white !important; + font-size: 21px; + margin-top: 5px; + text-align: center; + width: 50%; + margin:0 auto; +} + +.bodywrapper { + min-height: 80vh; +} + +.width-45-percent { + width: 45%; +} + +.width-55-percent { + width: 55%; +} + +.width-50-percent { + width: 50%; +} + +.two-sided { + display: flex; +} + +.two-sided .left-side { + padding-right: 2%; + padding-left: 0; +} + +.two-sided .title { + font-weight: bold; +} + +.two-sided pre { + overflow-y: scroll; +} + +.bold { + font-weight: bold; +} + +.doc-sphinx-info a { + color: #5682d1 !important; } \ No newline at end of file diff --git a/docs/conf.py b/docs/conf.py index bc72d5a..add4574 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -1,65 +1,65 @@ -import themata - -project = 'libmetaref' -copyright = '2020, Exotic Libraries - MIT License' -author = 'Adewale Azeez and Other Contributors' - -html_theme_path = [themata.get_html_theme_path()] -html_theme = 'fandango' -master_doc = 'index' -html_favicon = 'libmetaref.png' -html_static_path = ['_static'] -html_context = { - 'css_files': ['_static/css/libmetaref.css'] -} - -extensions = ['m2r2', ] -source_suffix = ['.rst', '.md'] - -html_theme_options = { - 'index_is_single': True, - 'show_navigators_in_index': False, - 'has_secondary_header': False, - 'navbar_links': [ - ('Doc', 'doc/index'), - ('Reference', 'reference/index'), - ('Contribute', 'https://github.com/exoticlibraries/libmetaref/'), - ('Exotic Libraries', 'https://exoticlibraries.github.io/'), - ('Support', 'https://exoticlibraries.github.io/pages/support.html') - ], - 'has_right_sidebar': True, - 'show_navigators': True, - 'toc_title': 'Other Topics', - 'social_icons': [ - ('fab fa-twitter', 'https://twitter.com/exoticlibs'), - ('fab fa-github', 'https://github.com/exoticlibraries/libmetaref/') - ], - "source_root": "https://github.com/exoticlibraries/libmetaref/edit/main/docs/", - "document_font_size": "15px", - 'text_color': '#292929', - 'header_background_color': '#292929', - 'header_sec_background_color': '#292929', - 'highlight_color': '#64abd9', - 'footer_highlight_color': '#013e66', - 'footer_link_color': '#5682d1', - 'body_link_highlight_color': '#013e66', - "metadata": { - "enable": True, - "url": "https://exoticlibraries.github.io/libmetaref/", - "type": "website", - "title": "Reflection library for C Struct. Runtime introspection and intercession.", - "description": "Reflection library for C Struct. Runtime introspection and intercession for struct fields, supports struct and field annotation.", - "image": "https://raw.githubusercontent.com/exoticlibraries/libmetaref/main/docs/libmetaref.png", - "keywords": "thecarisma, c, cpp, c++, exoticlibraries, exotic, libraries, reflection, introspection, struct, runtime", - "author": "Adewale Azeez" - }, - "twitter_metadata": { - "enable": True, - "card": "summary", - "site": "@exoticlibs", - "creator": "@iamthecarisma", - "title": "Reflection library for C Struct. Runtime introspection and intercession.", - "description": "Reflection library for C Struct. Runtime introspection and intercession for struct fields, supports struct and field annotation.", - "image": "https://raw.githubusercontent.com/exoticlibraries/libmetaref/main/docs/libmetaref.png", - } -} +import themata + +project = 'libmetaref' +copyright = '2020, Exotic Libraries - MIT License' +author = 'Adewale Azeez and Other Contributors' + +html_theme_path = [themata.get_html_theme_path()] +html_theme = 'fandango' +master_doc = 'index' +html_favicon = 'libmetaref.png' +html_static_path = ['_static'] +html_context = { + 'css_files': ['_static/css/libmetaref.css'] +} + +extensions = ['m2r2', ] +source_suffix = ['.rst', '.md'] + +html_theme_options = { + 'index_is_single': True, + 'show_navigators_in_index': False, + 'has_secondary_header': False, + 'navbar_links': [ + ('Doc', 'doc/index'), + ('Reference', 'reference/index'), + ('Contribute', 'https://github.com/exoticlibraries/libmetaref/'), + ('Exotic Libraries', 'https://exoticlibraries.github.io/'), + ('Support', 'https://exoticlibraries.github.io/pages/support.html') + ], + 'has_right_sidebar': True, + 'show_navigators': True, + 'toc_title': 'Other Topics', + 'social_icons': [ + ('fab fa-twitter', 'https://twitter.com/exoticlibs'), + ('fab fa-github', 'https://github.com/exoticlibraries/libmetaref/') + ], + "source_root": "https://github.com/exoticlibraries/libmetaref/edit/main/docs/", + "document_font_size": "15px", + 'text_color': '#292929', + 'header_background_color': '#292929', + 'header_sec_background_color': '#292929', + 'highlight_color': '#64abd9', + 'footer_highlight_color': '#013e66', + 'footer_link_color': '#5682d1', + 'body_link_highlight_color': '#013e66', + "metadata": { + "enable": True, + "url": "https://exoticlibraries.github.io/libmetaref/", + "type": "website", + "title": "Reflection library for C Struct. Runtime introspection and intercession.", + "description": "Reflection library for C Struct. Runtime introspection and intercession for struct fields, supports struct and field annotation.", + "image": "https://raw.githubusercontent.com/exoticlibraries/libmetaref/main/docs/libmetaref.png", + "keywords": "thecarisma, c, cpp, c++, exoticlibraries, exotic, libraries, reflection, introspection, struct, runtime", + "author": "Adewale Azeez" + }, + "twitter_metadata": { + "enable": True, + "card": "summary", + "site": "@exoticlibs", + "creator": "@iamthecarisma", + "title": "Reflection library for C Struct. Runtime introspection and intercession.", + "description": "Reflection library for C Struct. Runtime introspection and intercession for struct fields, supports struct and field annotation.", + "image": "https://raw.githubusercontent.com/exoticlibraries/libmetaref/main/docs/libmetaref.png", + } +} diff --git a/docs/doc/field_annotation.md b/docs/doc/field_annotation.md index 66028b2..e03b9d3 100644 --- a/docs/doc/field_annotation.md +++ b/docs/doc/field_annotation.md @@ -1,4 +1,97 @@ - - -# Field Annotation - + + +# Field Annotation + +libmetaref provides various macros to add annotation to a field. Each field annotation macro accept different types. + +- [_FS](./macros.html#fs) +- [_FI](./macros.html#fi) +- [_Fl](./macros.html#fl) +- [_FF](./macros.html#ff) + +## Annotation structure + +```c +typedef struct annotation_struct_ { + const size_t line_num; + const AnnotationType type; + const char *name; + const char *str_value; + int int_value; + long long long_value; + func_ptr_ func_ptr; +} Annotation; +``` + +The line_num is the line number where the annotation is declared, the type is the type of annotation it will be one of the following values: + +- METAREF_ANNOTATION_STRING, +- METAREF_ANNOTATION_INT, +- METAREF_ANNOTATION_LONG, +- METAREF_ANNOTATION_FUNCTION, +- METAREF_ANNOTATION_TERMINATOR + +The name is the identifier of the field, str_value is the value of the annotation if defined with _S macro, the int_value i sthe value if defined with _I, long_value when defined with the macro _L and func_ptr is the value if the annotation is a function type. + +## Creating annotations + +The annotation is declared in the first parameter in the FIELD macro inside the braces {}. + +```c +#define __STRUCT_FILE__ "test_struct.h" +#define __STRUCT_NAME__ Test +#include + +STRUCT(Test, + FIELD({ + _FS(DATABASE_column, "full_name") + _FI(SIZE_min, 10) + _FF(TO_STRING, fullname_to_string) + }, char *, fullname) +) + +#ifndef TEST_ANNOTATION_FUNCTION +#define TEST_ANNOTATION_FUNCTION +void *fullname_to_string(const void *test, void *arg) { + return (void *)"Column=Full Name"; +} +#endif +``` + +## Using the annotations at runtime + +Each declared annotations can be accessed at runtime using one of the macros provided in the library. The example below check if a field has an annotation then get it value. + +```c +#include +#include + +int main(int argc, char **argv) { + Field field = METAREF_GET_STRUCT_FIELD(Test, "fullname"); + if (METAREF_FIELD_HAS_ANNOTATION(field, "DATABASE_column")) { + printf("Column Name: %s\n", + METAREF_FIELD_ANNOTATION_STR_VALUE(field, "DATABASE_column")); + } + if (METAREF_FIELD_HAS_ANNOTATION(field, "TO_STRING")) { + func_ptr_ func = METAREF_FIELD_ANNOTATION_FUNC_VALUE(field, "TO_STRING"); + printf("Field to String: %s\n", func(NULL, NULL)); + } +} +``` + +## Iterating through the annotations + +The macro FOREACH_STRUCT_ANNOTATION can be used to iterate through all the annotations in a field: + +```c +#include +#include + +int main(int argc, char **argv) { + Field field = METAREF_GET_STRUCT_FIELD(Test, "fullname"); + FOREACH_FIELD_ANNOTATION(field, annotation, { + printf("Name=%s\n", annotation.name); + }) +} +``` + diff --git a/docs/doc/field_reflection.md b/docs/doc/field_reflection.md index 8a2d8bf..d5b7688 100644 --- a/docs/doc/field_reflection.md +++ b/docs/doc/field_reflection.md @@ -1,4 +1,4 @@ - - -# Field Reflection - + + +# Field Reflection + diff --git a/docs/doc/index.rst b/docs/doc/index.rst index 16e997e..eeca9f4 100644 --- a/docs/doc/index.rst +++ b/docs/doc/index.rst @@ -1,12 +1,12 @@ - -.. index:: - single: documentation_index - -Documentation -============== - -.. toctree:: - :glob: - :maxdepth: 3 - + +.. index:: + single: documentation_index + +Documentation +============== + +.. toctree:: + :glob: + :maxdepth: 3 + ./* \ No newline at end of file diff --git a/docs/doc/macros.md b/docs/doc/macros.md index 231ee0d2e8089536d5b8cc64085d20332187fbaf..372f56120e9303b0b4fc32c33fc75114919a1fb5 100644 GIT binary patch literal 21683 zcmeIuF#!Mo0K%a4Pwi(4h(KY$fB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM z7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b* N1`HT5V8DQZ4-8bZ00961 literal 20922 zcmds9ZExE~68_F#v2aj8GE}um8wa=`1yox~d~oc*vJcJW3YwNy5-$>|l2j76$bY|Q zW_Fh^dZQib?%)EKv&7}@>@)APv+}$r>TNJc;?(or#%ZQz{6U40$|hP(!`mcC?o^ru zNtUY5VKz}WZ@X8W%WluVX?xxiyly`BPP=C({=2J7zjJbO+3olJtM~7^o_B?Lcvdyk zgK3cHl&8+_=9-rIJP8LA{w5d>@eogA{x}Ntbf`WB(}h;^IE*r#s4!K7090mii^mN0 zC|FE0GYU^{KE>fs9Uk7am8>l94}wVDY88LdNfHh+E*9b{Ss;7qa@WNmdd!Bg1;{s?FDILU%2Q`ir2(d>g> z)nDd8G<2^j`YTPNxfyPAr+=SiCZWXi~^))tRv0aC(aluEnS9RBAhIJDd14^Nsz)8 zuq+OV%OZP;{$mj)BwkxY&j^>wMNaGyGtCMdnGmNH73DEd8KGv|mM-R`I2F-m8Vk#? z0IU(_X$TRAFz1TFlMyUp&{D0{2l+D}lm6al|G;1R`IqfUHk&s2^M;mnpTpEXXpz0UR7l^-o;w>oL57e_z8IQr?u&qptQqW>Me__-D(y)~2s&S-9= zN9>m|uWAO*CGM4@Gv{9=(oy4Sd>c$vI*7?;gc$-bj-^bfL@~gKoH>b&h!a?RMdr>f zKpG!p3yQ1Kzg1k9glmmM8tl)r#BVlWxImCRXqo>v^4%4uYbWu0jjIcC^{3~rNqgY_ zvY0#|#CQ{q-ji??k>i8}cKy!z`NdV|>h$8=?_HlC(;s~owyhr_1eO;q(N2#n{XsHr zD)GrD_*xy(L-k6r!&Qe(`Y2W`(LgFv4Vk`qaE{>URqlEZV9vZJIvR!}7b*I^Z&OL} zAyzS$wa=J3HhUCRV7=YfAX3K0<}*{A>fUSV8HwG1tWTq8pPJwQVl|nJkQk`qrs^!PZbsNb*vOIzJik6WTVd^Nx#4y9iqkvKd#xp1 zTaia{#LuMzNxzWx=eD$+mon^Ryx-;xa*CA73W!@=wS(-oWadQ*E`I%cmy&c#L!Z-e z72p0FS+JxL#w)^ij>vsR3r=*96wP#iyc%C25mHE_;e=6{2qR>R2+saQkc>dzJmyEE z1c`UMLbgz_g>YZ!LRI7>=B0ux(=$qQ^Ze87d5Gj|kResYqj{n~A=roCrc4dR8Wdkj ziJ*lRWf`u6q!J?*5fYWk5xOy?Sd7YvKh+e$KJTc)_p<<-p4dQ}43dHSp&}k`c0L z0@ciF)`99^&$1g4m&!6rF)OMt0m^tlau8EpC(~s~E-dbOJ?P=uRc)d}Ni{QL2}-GW zeg^Y%a#0WAZBX@9nC1*mE_GCJ{V&P0RE}0a-zdnpmHX37jbqe<=1G9k-vHRe*gZ;W zq;019gOJr#>nN2F?$Dl%v>TI2wlFt#3Y9<75J@=_T{MnjPO%h9gREdS4vht#zf>UF*cNJ z$2ecuV(hA&4&L6yWw&$u#>B-X7jla5lLD}8lEjPg#AO!+yHzx25`W3z=9;rDiqIVHpG@R5#sThaJiN0}?b^MV?dP+$Or$nPr8gTjq)7T*`mgAq zm@2i2P!lnklTcGfMgel|VlbsA-QPU#e+b`TktCdUqe%V5M$P%|DG?_CLuN3JQiU07 z4($r>?SdBqkKqV{eEp>e`5MNwR404&-Eb9upvN@HHa6upc^{l9ry!+@#6AT5o=E~H zATK>Du{jjQT&xBcR>5Dz-G(WJe3yBRaa`gkXiiSY{#3>wB~3i{;LHDk2JMQ;M&Sx+ zw^5lI9KXNb)!@G!Vj@`ysE#kLDFU^Dvz%{|=`zJCW3p1I##E!>!W<%Pl}s)#f#BQ- zU1m0gljes}63_Cm9NqKX^>e3p#f;9w12CTP=vWK&5Xh-~DRDO~i78qUsqYO{RWwp^+`?n09KB3U z3EU;n)=qGjB@~4ELP(uaYk=}l55Z^ZFNvWwhWchCG?5Tr?>0aVrNOHShMxHSo;zw^8Y6x175s72L== z+o;9@^k{j=IP8mwB?x!RzvU90*d=Q^k;*<=o?-9%;uv6aTIc?t0_SeIcfE~$PI4YI z9|?thG13AECfYxD&&K|ni_2=IysU<}bdWq=MdbbOi-Qau=^#PKymRi*J(BM4e8f(J zo9pfDb)v;2JX(V*NbHNzWe|%ByC=r3ID{!{Egic&T4vJj_r*#A4h-ZT_M$80Z%CI# zVcqlH>g!g%I!Sxf48Gnchf5F^b#*^H?VVk8Hhb97G!7oGhvoh6OIsPb-3GQN7uUa@ zq36LBDXGF$Hm<{X!QGVHY54dGI)cEySSH}@mSeNzr>}x@JW`-GRZ%2@M+ND8(KcRM*{haF8D#rxah2 zX;^uQTPTtPgUyxkd`48&(TT}-|F$;=d|M@V-S!2fRYz%S4;-opZae)HWb$3_3P(OS zx0PRe+>kGW{A>SR0{dZ#Ij&&fHXL>?aj0CXC#A^st9)cwfN8-O;@y#<(aYK8li09hw(z#Axba2ozrtVX8 zRimc}Ehn~TXZeJryp$!eg4pUalfvogvXa&4A+2f}xAQ-^le9;zq@y~$q)WuQmd@O$ zuWlt>qSzgTxdWmPxNd0(skV%*Uv~}cm1Fg#_qR5ZF42oau7|gi_Na|>RHvbInbNxb zq)Qa9MA#Ct6=Bprr5Dg4+&}$i*N1+rF$1{;qBiIi`7W3L%?bMwu>|jfT1tD=$vLXi zRJsH$2UN8hp_j;AiLIq%E4KN<6>x(uwZN^>O}a!e1N`8gQf}p}(^a|za^Bmy8xvtE z*$Q&Lumc$v2z=c18->d-yTG#SzDhn57edf~Ls=tTSSw%WX)F1?8T2O7uSel7+IWGV z|3UY;oZFWgyNb;>C54bXKDd|W&h_ao%+e)#L_BHs{V#lv^q$>U)Ln)1{vO9Obbn2H z0B|eSI(3Icx#{kJ22-m*wL6YEzAd=6-44Y|qZ^}a(?3-w%ob6d^ z?W&b>lKuHMC^Fdz+hJEyaxn!k6ZC%G3%6o&F`ioa$e>ay~5Wj3C zoj9}$^HXy-(i^s_-NsGecM9qK4(LIl-slhRs+%9g1G0Rfs$C|M!;8b5NWMSX`?kCd z%d12DLqFJ3Fp))8fdh>Km1w1+Yvg!E*!)Tzu9BY3Z#~0WcG=wE+Ijk}sKT&&Uf=vI zfb%i91I_zJhbW@)Xl$=9%K&pvwIZ8z13ruwsbg{hKl-^QnQ^ - -_S(DATABASE_table, "test") -_I(SIZE_min, 10) -_F(TO_STRING, test_to_string) -STRUCT(Test, - //... -) - -#ifndef TEST_ANNOTATION_FUNCTION -#define TEST_ANNOTATION_FUNCTION -void *test_to_string(const void *test, void *arg) { - return (void *)"Name=test"; -} -#endif -``` - -## Using the annotations at runtime - -Each declared annotations can be accessed at runtime using one of the macros provided in the library. The example below check if a struct has an annotation then get it value. - -```c -#include -#include - -int main(int argc, char **argv) { - if (METAREF_STRUCT_HAS_ANNOTATION(Test, "DATABASE_table")) { - printf("Table Name: %s\n", - METAREF_STRUCT_ANNOTATION_STR_VALUE(Test, "DATABASE_table")); - } - if (METAREF_STRUCT_HAS_ANNOTATION(Test, "TO_STRING")) { - func_ptr_ func = METAREF_STRUCT_ANNOTATION_FUNC_VALUE(Test, "TO_STRING"); - printf("Test to String: %s\n", func(NULL, NULL)); - } -} -``` - -## Iterating through the annotations - -The macro FOREACH_STRUCT_ANNOTATION can be used to iterate through all the annotations in a struct: - -```c -#include -#include - -int main(int argc, char **argv) { - FOREACH_STRUCT_ANNOTATION(Test, annotation, { - printf("Name=%s\n", annotation.name); - }) -} -``` - + + +# Struct Annotation + +libmetaref provides various macros to add annotation to a struct. Each struct annotation macro accept different types. + +- [_S](./macros.html#s) +- [_I](./macros.html#i) +- [_l](./macros.html#l) +- [_F](./macros.html#f) + +## Annotation structure + +```c +typedef struct annotation_struct_ { + const size_t line_num; + const AnnotationType type; + const char *name; + const char *str_value; + int int_value; + long long long_value; + func_ptr_ func_ptr; +} Annotation; +``` + +The line_num is the line number where the annotation is declared, the type is the type of annotation it will be one of the following values: + +- METAREF_ANNOTATION_STRING, +- METAREF_ANNOTATION_INT, +- METAREF_ANNOTATION_LONG, +- METAREF_ANNOTATION_FUNCTION, +- METAREF_ANNOTATION_TERMINATOR + +The name is the identifier of the annotation, str_value is the value of the annotation if defined with _S macro, the int_value i sthe value if defined with _I, long_value when defined with the macro _L and func_ptr is the value if the annotation is a function type. + +## Creating annotations + +The annotation is declared at the top before the struct. + +```c +#define __STRUCT_FILE__ "test_struct.h" +#define __STRUCT_NAME__ Test +#include + +_S(DATABASE_table, "test") +_I(SIZE_min, 10) +_F(TO_STRING, test_to_string) +STRUCT(Test, + //... +) + +#ifndef TEST_ANNOTATION_FUNCTION +#define TEST_ANNOTATION_FUNCTION +void *test_to_string(const void *test, void *arg) { + return (void *)"Name=test"; +} +#endif +``` + +## Using the annotations at runtime + +Each declared annotations can be accessed at runtime using one of the macros provided in the library. The example below check if a struct has an annotation then get it value. + +```c +#include +#include + +int main(int argc, char **argv) { + if (METAREF_STRUCT_HAS_ANNOTATION(Test, "DATABASE_table")) { + printf("Table Name: %s\n", + METAREF_STRUCT_ANNOTATION_STR_VALUE(Test, "DATABASE_table")); + } + if (METAREF_STRUCT_HAS_ANNOTATION(Test, "TO_STRING")) { + func_ptr_ func = METAREF_STRUCT_ANNOTATION_FUNC_VALUE(Test, "TO_STRING"); + printf("Test to String: %s\n", func(NULL, NULL)); + } +} +``` + +## Iterating through the annotations + +The macro FOREACH_STRUCT_ANNOTATION can be used to iterate through all the annotations in a struct: + +```c +#include +#include + +int main(int argc, char **argv) { + FOREACH_STRUCT_ANNOTATION(Test, annotation, { + printf("Name=%s\n", annotation.name); + }) +} +``` + diff --git a/docs/doc/struct_deserialization.md b/docs/doc/struct_deserialization.md index 0f64e34..ad899f4 100644 --- a/docs/doc/struct_deserialization.md +++ b/docs/doc/struct_deserialization.md @@ -1,4 +1,4 @@ - - -# Struct Deserialization - + + +# Struct Deserialization + diff --git a/docs/doc/struct_serialization.md b/docs/doc/struct_serialization.md index 3bd38f4..90e91fd 100644 --- a/docs/doc/struct_serialization.md +++ b/docs/doc/struct_serialization.md @@ -1,4 +1,4 @@ - - -# Struct Serialization - + + +# Struct Serialization + diff --git a/docs/download.md b/docs/download.md index 5c83417..546c5f2 100644 --- a/docs/download.md +++ b/docs/download.md @@ -1,45 +1,45 @@ - -# Download - -The library is compliant with C99 and C++11 any lesser version is not supported, Also the compiler must support the variadic parameter in the macro declaration and the macro constant `__VA_ARGS__`. - -## From Source - -Simply download the header file libmetaref.h from the repo into your project source folder and include it in your project. Download the file from https://github.com/exoticlibraries/libmetaref/releases or from any of the branches. Then you can include it in your project relatively like `#include "libmetaref.h"`. - -## Using irorun - -Install irorun from https://exoticlibraries.github.io/irorun - -Installing directly from the repo - -``` -irorun install libmetaref --github=https://github.com/exoticlibraries/libmetaref -``` - -Installing from vcpkg directory - -``` -irorun install libmetaref -``` - -The library will be installed for the following compilers and others installed compilers recognized by irorun. - -- GCC -- CMAKE -- Visual C++ - -## Using Microsoft vcpkg - -``` -vcpkg install libmetaref -``` - -To use the library after installation with vcpkg with your build system, continue with [vcpkg documentation](https://github.com/microsoft/vcpkg/blob/master/docs/index.md) and [integration with build systems](https://github.com/microsoft/vcpkg/blob/master/docs/users/integration.md) - -
-

Note

-

Always add the relative or absolute path to the struct file(s) during compilation e.g. -I./structs

-
- + +# Download + +The library is compliant with C99 and C++11 any lesser version is not supported, Also the compiler must support the variadic parameter in the macro declaration and the macro constant `__VA_ARGS__`. + +## From Source + +Simply download the header file libmetaref.h from the repo into your project source folder and include it in your project. Download the file from https://github.com/exoticlibraries/libmetaref/releases or from any of the branches. Then you can include it in your project relatively like `#include "libmetaref.h"`. + +## Using irorun + +Install irorun from https://exoticlibraries.github.io/irorun + +Installing directly from the repo + +``` +irorun install libmetaref --github=https://github.com/exoticlibraries/libmetaref +``` + +Installing from vcpkg directory + +``` +irorun install libmetaref +``` + +The library will be installed for the following compilers and others installed compilers recognized by irorun. + +- GCC +- CMAKE +- Visual C++ + +## Using Microsoft vcpkg + +``` +vcpkg install libmetaref +``` + +To use the library after installation with vcpkg with your build system, continue with [vcpkg documentation](https://github.com/microsoft/vcpkg/blob/master/docs/index.md) and [integration with build systems](https://github.com/microsoft/vcpkg/blob/master/docs/users/integration.md) + +
+

Note

+

Always add the relative or absolute path to the struct file(s) during compilation e.g. -I./structs

+
+ \ No newline at end of file diff --git a/docs/examples/field_annotation_usage.md b/docs/examples/field_annotation_usage.md deleted file mode 100644 index ab024e6..0000000 --- a/docs/examples/field_annotation_usage.md +++ /dev/null @@ -1,4 +0,0 @@ - - -# Field Annotation Usage - diff --git a/docs/examples/index.rst b/docs/examples/index.rst deleted file mode 100644 index 125f7f3..0000000 --- a/docs/examples/index.rst +++ /dev/null @@ -1,12 +0,0 @@ - -.. index:: - single: examples - -Examples -============== - -.. toctree:: - :glob: - :maxdepth: 3 - - ./* \ No newline at end of file diff --git a/docs/examples/struct_deserialization.md b/docs/examples/struct_deserialization.md deleted file mode 100644 index 0f64e34..0000000 --- a/docs/examples/struct_deserialization.md +++ /dev/null @@ -1,4 +0,0 @@ - - -# Struct Deserialization - diff --git a/docs/examples/struct_serialization.md b/docs/examples/struct_serialization.md deleted file mode 100644 index 3bd38f4..0000000 --- a/docs/examples/struct_serialization.md +++ /dev/null @@ -1,4 +0,0 @@ - - -# Struct Serialization - diff --git a/docs/how_it_works/how_annotation_works.md b/docs/how_it_works/how_annotation_works.md index 7bb4514..eda5d79 100644 --- a/docs/how_it_works/how_annotation_works.md +++ b/docs/how_it_works/how_annotation_works.md @@ -1,4 +1,4 @@ - - -# How Annotation Works - + + +# How Annotation Works + diff --git a/docs/how_it_works/how_field_reflection_works.md b/docs/how_it_works/how_field_reflection_works.md index 5f6ddca..7823ca7 100644 --- a/docs/how_it_works/how_field_reflection_works.md +++ b/docs/how_it_works/how_field_reflection_works.md @@ -1,4 +1,4 @@ - - -# How Field Reflection Works - + + +# How Field Reflection Works + diff --git a/docs/how_it_works/index.rst b/docs/how_it_works/index.rst index 15b6dd1..0a3d2aa 100644 --- a/docs/how_it_works/index.rst +++ b/docs/how_it_works/index.rst @@ -1,12 +1,12 @@ - -.. index:: - single: how_it_works - -How it works -============== - -.. toctree:: - :glob: - :maxdepth: 3 - + +.. index:: + single: how_it_works + +How it works +============== + +.. toctree:: + :glob: + :maxdepth: 3 + ./* \ No newline at end of file diff --git a/docs/index.rst b/docs/index.rst index 1502c5f..95debdd 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -29,15 +29,6 @@ /how_it_works/* -.. toctree:: - :maxdepth: 1 - :hidden: - :glob: - :caption: Examples - :name: main-examples - - /examples/* - .. mdinclude:: index_dump.md diff --git a/test/crash_test.c b/test/crash_test.c index 97a715d..f2db703 100644 --- a/test/crash_test.c +++ b/test/crash_test.c @@ -1,10 +1,16 @@ -/*!gcc {0} -I../../libcester/include/ -I. -I./structs -I../include/ -o out.exe; ./out.exe */ - -#include -#include - -int main(int argc, char **argv) { - FOREACH_STRUCT_ANNOTATION(Test, annotation, { - printf("Name=%s\n", annotation.name); - }) +/*!gcc {0} -I../../libcester/include/ -I. -I./structs -I../include/ -o out.exe; ./out.exe */ + +#include +#include + +int main(int argc, char **argv) { + Field field = METAREF_GET_STRUCT_FIELD(Test, "fullname"); + if (METAREF_FIELD_HAS_ANNOTATION(field, "DATABASE_column")) { + printf("Column Name: %s\n", + METAREF_FIELD_ANNOTATION_STR_VALUE(field, "DATABASE_column")); + } + if (METAREF_FIELD_HAS_ANNOTATION(field, "TO_STRING")) { + func_ptr_ func = METAREF_FIELD_ANNOTATION_FUNC_VALUE(field, "TO_STRING"); + printf("Field to String: %s\n", func(NULL, NULL)); + } } \ No newline at end of file diff --git a/test/structs/preference_struct.h b/test/structs/preference_struct.h index 53e2097..6608b35 100644 --- a/test/structs/preference_struct.h +++ b/test/structs/preference_struct.h @@ -1,36 +1,36 @@ -#define __STRUCT_FILE__ "preference_struct.h" -#define __STRUCT_NAME__ Preference -#include - -STRUCT(Preference, - FIELD({ - _FS(KONFIGER_value, "IpAddress") - }, char *, ip_address) - - FIELD({}, int, MainPort) - - FIELD({ - _FF(URL_prefix, get_map_prefix) - }, char *, google_map_link) - - FIELD({ - _FS(DATABASE_column, "fullname") - _FS(JSON_value, "full_name") - _FS(KONFIGER_value, "FullName") - _FI(SIZE_min, 10) - _FI(SIZE_max, 150) - _FS(SIZE_msg, "The length of the name must be between 10 and 50") - }, char *, fullname) - - FIELD({ - _FL(NUMBER_long, 7652653625635265) - _FS(KONFIGER_value, "AlwaysReconnect") - }, unsigned, always_reconnect) -) - -#ifndef PREFERENCE_STRUCT_FUNCTION -#define PREFERENCE_STRUCT_FUNCTION -void *get_map_prefix(const void *the_struct, void *arg) { - return (void *)"https://www.google.ng/maps/place/"; -} +#define __STRUCT_FILE__ "preference_struct.h" +#define __STRUCT_NAME__ Preference +#include + +STRUCT(Preference, + FIELD({ + _FS(KONFIGER_value, "IpAddress") + }, char *, ip_address) + + FIELD({}, int, MainPort) + + FIELD({ + _FF(URL_prefix, get_map_prefix) + }, char *, google_map_link) + + FIELD({ + _FS(DATABASE_column, "fullname") + _FS(JSON_value, "full_name") + _FS(KONFIGER_value, "FullName") + _FI(SIZE_min, 10) + _FI(SIZE_max, 150) + _FS(SIZE_msg, "The length of the name must be between 10 and 50") + }, char *, fullname) + + FIELD({ + _FL(NUMBER_long, 7652653625635265) + _FS(KONFIGER_value, "AlwaysReconnect") + }, unsigned, always_reconnect) +) + +#ifndef PREFERENCE_STRUCT_FUNCTION +#define PREFERENCE_STRUCT_FUNCTION +void *get_map_prefix(const void *the_struct, void *arg) { + return (void *)"https://www.google.ng/maps/place/"; +} #endif \ No newline at end of file diff --git a/test/structs/test_struct.h b/test/structs/test_struct.h index 44235db..5b4953d 100644 --- a/test/structs/test_struct.h +++ b/test/structs/test_struct.h @@ -1,18 +1,18 @@ -#define __STRUCT_FILE__ "test_struct.h" -#define __STRUCT_NAME__ Test -#include - -_S(DATABASE_table, "test") -_I(SIZE_min, 10) -_F(TO_STRING, test_to_string) -STRUCT(Test, - FIELD({}, char *, fullname) - FIELD({}, char *, email) -) - -#ifndef TEST_ANNOTATION_FUNCTION -#define TEST_ANNOTATION_FUNCTION -void *test_to_string(const void *test, void *arg) { - return (void *)"Name=test"; -} +#define __STRUCT_FILE__ "test_struct.h" +#define __STRUCT_NAME__ Test +#include + +STRUCT(Test, + FIELD({ + _FS(DATABASE_column, "full_name") + _FI(SIZE_min, 10) + _FF(TO_STRING, fullname_to_string) + }, char *, fullname) +) + +#ifndef TEST_ANNOTATION_FUNCTION +#define TEST_ANNOTATION_FUNCTION +void *fullname_to_string(const void *test, void *arg) { + return (void *)"Column=Full Name"; +} #endif \ No newline at end of file diff --git a/test/structs/user_struct.h b/test/structs/user_struct.h index 14964d3..8684941 100644 --- a/test/structs/user_struct.h +++ b/test/structs/user_struct.h @@ -1,10 +1,10 @@ -#define __STRUCT_FILE__ "user_struct.h" -#define __STRUCT_NAME__ User -#include - -_S(DATABASE_table, "user") -_I(SIZE_min, 10) -STRUCT(User, - FIELD({}, char *, fullname) - FIELD({}, char *, email) +#define __STRUCT_FILE__ "user_struct.h" +#define __STRUCT_NAME__ User +#include + +_S(DATABASE_table, "user") +_I(SIZE_min, 10) +STRUCT(User, + FIELD({}, char *, fullname) + FIELD({}, char *, email) ) \ No newline at end of file diff --git a/test/structs/user_table_struct.h b/test/structs/user_table_struct.h index e698edc..cdf98a0 100644 --- a/test/structs/user_table_struct.h +++ b/test/structs/user_table_struct.h @@ -1,22 +1,22 @@ -#define __STRUCT_FILE__ "user_table_struct.h" -#define __STRUCT_NAME__ User -#include - -_S(DATABASE_table, "user") -_S(KONFIGER_file, "#{rsc}/user.conf") -_L(SIZE_max, 2000) -_I(SIZE_min, 10) -_F(TO_STRING, user_to_string) -STRUCT(User, - FIELD({}, long, user_id) - FIELD({}, char *, first_name) - FIELD({}, char *, middle_name) - FIELD({}, char *, last_name) -) - -#ifndef USER_ANNOTATION_FUNCTION -#define USER_ANNOTATION_FUNCTION -void *user_to_string(const void *user, void *arg) { - return (void *)"Name=libmetaref"; -} +#define __STRUCT_FILE__ "user_table_struct.h" +#define __STRUCT_NAME__ User +#include + +_S(DATABASE_table, "user") +_S(KONFIGER_file, "#{rsc}/user.conf") +_L(SIZE_max, 2000) +_I(SIZE_min, 10) +_F(TO_STRING, user_to_string) +STRUCT(User, + FIELD({}, long, user_id) + FIELD({}, char *, first_name) + FIELD({}, char *, middle_name) + FIELD({}, char *, last_name) +) + +#ifndef USER_ANNOTATION_FUNCTION +#define USER_ANNOTATION_FUNCTION +void *user_to_string(const void *user, void *arg) { + return (void *)"Name=libmetaref"; +} #endif \ No newline at end of file From 924650e5949bcd1f531eddc101eb0f22a963a7e5 Mon Sep 17 00:00:00 2001 From: thecarisma Date: Thu, 20 May 2021 19:38:19 +0100 Subject: [PATCH 12/12] update config file --- .github/workflows/main.yml | 2 +- include/exotic/metaref.h | 20 ++++++++++---------- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 125963f..ce42ebf 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -64,7 +64,7 @@ jobs: cd ../ - name: Deploy 🚀 - uses: JamesIves/github-pages-deploy-action@3.6.1 + uses: JamesIves/github-pages-deploy-action@4.0.0 with: GITHUB_TOKEN: ${{ secrets.GH_TOKEN_FOR_CI_CD }} BRANCH: gh-pages diff --git a/include/exotic/metaref.h b/include/exotic/metaref.h index 4cac2bd..43c052e 100644 --- a/include/exotic/metaref.h +++ b/include/exotic/metaref.h @@ -15,6 +15,16 @@ #include #endif +/** + Concatenate two objects implicitly +*/ +#define METAREF_CONCAT_IMPL(x,y ) x##y + +/** + Concatenate two objects +*/ +#define METAREF_CONCAT(x,y) METAREF_CONCAT_IMPL(x,y) + #ifndef EXOTIC_METAREF_STRUCT #ifdef __STRUCT_FILE__ #ifndef __STRUCT_NAME__ @@ -53,16 +63,6 @@ extern "C" { #include -/** - Concatenate two objects implicitly -*/ -#define METAREF_CONCAT_IMPL(x,y ) x##y - -/** - Concatenate two objects -*/ -#define METAREF_CONCAT(x,y) METAREF_CONCAT_IMPL(x,y) - /** The function pointer for the annotation with a function value instead of string. The function