diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index bf0fdb0..ce42ebf 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -1,5 +1,5 @@ -name: CI/CD +name: CI-CD on: push: @@ -8,11 +8,11 @@ on: branches: [ main ] jobs: - build: + execute-regression: 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] @@ -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 @@ -43,8 +45,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 @@ -53,16 +55,19 @@ jobs: - name: Install and Build 🔧 run: | - pip3 install themata + sudo apt-get install -y python3 python3-setuptools python3-pip python3-sphinx + python -m pip install --upgrade pip + python -m pip install themata m2r2 + sudo apt-get install -y clang doxygen make cd ./docs/ - bash ./make.sh + sudo bash ./make.sh 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 # 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..4951a12 100644 --- a/docs/Doxyfile +++ b/docs/Doxyfile @@ -1,18 +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 \ No newline at end of file +# 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 eef31a5..1ba5a7b 100644 --- a/docs/_static/css/libmetaref.css +++ b/docs/_static/css/libmetaref.css @@ -1,68 +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; -} + + + +.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 b9b2c06..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 = 'Exotic Libraries 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'), - ('Github', '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/", - "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/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..e03b9d3 --- /dev/null +++ b/docs/doc/field_annotation.md @@ -0,0 +1,97 @@ + + +# 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 new file mode 100644 index 0000000..d5b7688 --- /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..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 - - anonymous_function \ No newline at end of file + +.. 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 new file mode 100644 index 0000000..372f561 Binary files /dev/null and b/docs/doc/macros.md differ diff --git a/docs/doc/struct_annotation.md b/docs/doc/struct_annotation.md new file mode 100644 index 0000000..cfef58c --- /dev/null +++ b/docs/doc/struct_annotation.md @@ -0,0 +1,94 @@ + + +# 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 new file mode 100644 index 0000000..ad899f4 --- /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..90e91fd --- /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..546c5f2 --- /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/how_it_works/how_annotation_works.md b/docs/how_it_works/how_annotation_works.md new file mode 100644 index 0000000..eda5d79 --- /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..7823ca7 --- /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..0a3d2aa --- /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..95debdd 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,15 @@ /doc/* +.. toctree:: + :maxdepth: 1 + :hidden: + :glob: + :caption: How it works + :name: main-how-it-works + + /how_it_works/* + .. 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 f61ef0a..c8155b5 100644 --- a/docs/make.sh +++ b/docs/make.sh @@ -1,7 +1,5 @@ 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/ touch ./build/html/.nojekyll \ No newline at end of file diff --git a/include/exotic/metaref.h b/include/exotic/metaref.h index 36ed0e1..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__ @@ -51,22 +61,14 @@ extern "C" { #ifndef METAREF_STRUCTS_DECLARED #define METAREF_STRUCTS_DECLARED -/** - 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) +#include /** The function pointer for the annotation with a 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..f2db703 100644 --- a/test/crash_test.c +++ b/test/crash_test.c @@ -1,44 +1,16 @@ -/*!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); - } -} - -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; +/*!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 ca5ba4b..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 *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 new file mode 100644 index 0000000..5b4953d --- /dev/null +++ b/test/structs/test_struct.h @@ -0,0 +1,18 @@ +#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 new file mode 100644 index 0000000..8684941 --- /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..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) { - 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 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, ""); }) ) 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(