From 5465f1f1767dcf184062ef202f197f3ce8a64516 Mon Sep 17 00:00:00 2001 From: marcosfpr Date: Sat, 7 May 2022 19:58:52 -0300 Subject: [PATCH] Doxygen documentation --- .github/workflows/docs.yml | 60 +-- README.md | 335 +-------------- docs/.doxybook/config.json | 13 + docs/.doxybook/templates/breadcrumbs.tmpl | 19 + .../templates/class_members_details.tmpl | 117 +++++ .../class_members_inherited_tables.tmpl | 295 +++++++++++++ .../templates/class_members_tables.tmpl | 262 ++++++++++++ docs/.doxybook/templates/details.tmpl | 192 +++++++++ docs/.doxybook/templates/footer.tmpl | 3 + docs/.doxybook/templates/header.tmpl | 26 ++ docs/.doxybook/templates/index.tmpl | 10 + docs/.doxybook/templates/index_classes.tmpl | 5 + docs/.doxybook/templates/index_examples.tmpl | 5 + docs/.doxybook/templates/index_files.tmpl | 5 + docs/.doxybook/templates/index_groups.tmpl | 5 + .../.doxybook/templates/index_namespaces.tmpl | 5 + docs/.doxybook/templates/index_pages.tmpl | 5 + docs/.doxybook/templates/kind_class.tmpl | 34 ++ docs/.doxybook/templates/kind_example.tmpl | 5 + docs/.doxybook/templates/kind_file.tmpl | 20 + docs/.doxybook/templates/kind_group.tmpl | 15 + docs/.doxybook/templates/kind_nonclass.tmpl | 18 + docs/.doxybook/templates/kind_page.tmpl | 5 + docs/.doxybook/templates/member_details.tmpl | 91 ++++ .../templates/merged_overload_details.tmpl | 399 ++++++++++++++++++ docs/.doxybook/templates/meta.tmpl | 0 .../templates/nonclass_members_details.tmpl | 35 ++ .../templates/nonclass_members_tables.tmpl | 133 ++++++ docs/.gitignore | 3 + docs/CMakeLists.txt | 114 +++++ docs/Doxyfile | 36 ++ docs/contributing.md | 56 +++ docs/index.md | 35 ++ docs/javascripts/extra.js | 38 ++ docs/macros.py | 76 ++++ docs/quickstart.md | 190 +++++++++ docs/references.md | 30 ++ docs/sets_and_maps.md | 15 + docs/strings.md | 17 + docs/stylesheets/extra.css | 10 + docs/vectors.md | 27 ++ mkdocs.yml | 41 +- 42 files changed, 2438 insertions(+), 367 deletions(-) create mode 100644 docs/.doxybook/config.json create mode 100644 docs/.doxybook/templates/breadcrumbs.tmpl create mode 100644 docs/.doxybook/templates/class_members_details.tmpl create mode 100644 docs/.doxybook/templates/class_members_inherited_tables.tmpl create mode 100644 docs/.doxybook/templates/class_members_tables.tmpl create mode 100644 docs/.doxybook/templates/details.tmpl create mode 100644 docs/.doxybook/templates/footer.tmpl create mode 100644 docs/.doxybook/templates/header.tmpl create mode 100644 docs/.doxybook/templates/index.tmpl create mode 100644 docs/.doxybook/templates/index_classes.tmpl create mode 100644 docs/.doxybook/templates/index_examples.tmpl create mode 100644 docs/.doxybook/templates/index_files.tmpl create mode 100644 docs/.doxybook/templates/index_groups.tmpl create mode 100644 docs/.doxybook/templates/index_namespaces.tmpl create mode 100644 docs/.doxybook/templates/index_pages.tmpl create mode 100644 docs/.doxybook/templates/kind_class.tmpl create mode 100644 docs/.doxybook/templates/kind_example.tmpl create mode 100644 docs/.doxybook/templates/kind_file.tmpl create mode 100644 docs/.doxybook/templates/kind_group.tmpl create mode 100644 docs/.doxybook/templates/kind_nonclass.tmpl create mode 100644 docs/.doxybook/templates/kind_page.tmpl create mode 100644 docs/.doxybook/templates/member_details.tmpl create mode 100644 docs/.doxybook/templates/merged_overload_details.tmpl create mode 100644 docs/.doxybook/templates/meta.tmpl create mode 100644 docs/.doxybook/templates/nonclass_members_details.tmpl create mode 100644 docs/.doxybook/templates/nonclass_members_tables.tmpl create mode 100644 docs/.gitignore create mode 100644 docs/CMakeLists.txt create mode 100644 docs/Doxyfile create mode 100644 docs/contributing.md create mode 100644 docs/index.md create mode 100644 docs/javascripts/extra.js create mode 100644 docs/macros.py create mode 100644 docs/quickstart.md create mode 100644 docs/references.md create mode 100644 docs/sets_and_maps.md create mode 100644 docs/strings.md create mode 100644 docs/stylesheets/extra.css create mode 100644 docs/vectors.md diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml index b6a7e3f..f5942ec 100644 --- a/.github/workflows/docs.yml +++ b/.github/workflows/docs.yml @@ -5,52 +5,60 @@ # https://www.boost.org/LICENSE_1_0.txt # -name: Docs Generator +name: Publish Docs -on: push +on: + push: + branches: + - master jobs: generateDOC: - name: Docs Generator - runs-on: ubuntu-20.04 + name: Publish Docs + runs-on: ubuntu-latest steps: - uses: actions/checkout@v2 - - name: Generate Table of Contents - uses: technote-space/toc-generator@v2 - with: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - MAX_HEADER_LEVEL: 3 - FOLDING: true - name: Update Contributors - if: github.ref == 'refs/heads/master' - uses: akhilmhdh/contributors-readme-action@v2.0.1 + uses: akhilmhdh/contributors-readme-action@v2.3 env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} with: image_size: 100 columns_per_row: 6 - - name: Download mdsplit + readme_path: docs/acknowledgments.md + continue-on-error: true + - name: Install doxygen + run: sudo apt-get install doxygen + - name: Generate doxygen XML + run: doxygen + working-directory: ./docs + - name: Download doxybook2 uses: carlosperate/download-file-action@v1.0.3 - id: download-mdsplit + id: download-doxybook2 with: - file-url: 'https://github.com/alandefreitas/mdsplit/releases/download/v0.1.1/Executable.Linux.zip' - file-name: 'mdsplit.zip' - location: '.' - - name: Unzip mdsplit + file-url: 'https://github.com/matusnovak/doxybook2/releases/download/v1.4.0/doxybook2-linux-amd64-v1.4.0.zip' + file-name: 'doxybook2.zip' + location: './docs' + - name: Unzip doxybook2 run: | - unzip mdsplit.zip - rm -f mdsplit.zip - sudo chmod +x mdsplit + unzip doxybook2.zip + rm -f doxybook2.zip + sudo chmod +x ./bin/doxybook2 + mkdir reference ls - - name: Generate Documentation Source - run: ./mdsplit -r alandefreitas/small + working-directory: ./docs + - name: Generate Doxybook + run: ./bin/doxybook2 --input ./xml --output reference --config .doxybook/config.json --templates .doxybook/templates + working-directory: ./docs - name: Setup Python uses: actions/setup-python@v2 with: python-version: 3.x - name: Install Mkdocs Material run: pip install mkdocs-material - - name: Install Awesome Pages Plugin # https://github.com/lukasgeiter/mkdocs-awesome-pages-plugin - run: pip install mkdocs-awesome-pages-plugin + - name: Install Mermaid for Mkdocs + run: pip install mkdocs-mermaid2-plugin + - name: Install Macros for Mkdocs + run: pip install mkdocs-macros-plugin - name: Deploy mkdocs to gh-pages branch - run: mkdocs gh-deploy --force + run: mkdocs gh-deploy --force \ No newline at end of file diff --git a/README.md b/README.md index 375fcec..d623ff2 100644 --- a/README.md +++ b/README.md @@ -41,337 +41,6 @@ [READ THE DOCUMENTATION FOR A QUICK START AND EXAMPLES](https://alandefreitas.github.io/small/) - - - - -
-Table of Contents - -- [Quickstart](#quickstart) -- [Vectors](#vectors) -- [Strings](#strings) -- [Sets and Maps](#sets-and-maps) -- [Contributing](#contributing) - - [Get Involved](#get-involved) - - [Ideas and Roadmap](#ideas-and-roadmap) - - [Guidelines](#guidelines) - - [Contributors](#contributors) -- [References](#references) - -
- - - -## Quickstart - -Integration: - -=== "CMake" - - === "Add subdirectory" - - ```bash - git clone https://github.com/alandefreitas/small/ - ``` - - ```cmake - add_subdirectory(small) - # ... - add_executable(your_target main.cpp) - target_link_libraries(your_target PUBLIC small::small) - ``` - - === "Fetch content" - - ```cmake - include(FetchContent) - - FetchContent_Declare(small - GIT_REPOSITORY https://github.com/alandefreitas/small - GIT_TAG origin/master # or whatever tag you want - ) - - FetchContent_GetProperties(small) - if(NOT small_POPULATED) - FetchContent_Populate(small) - add_subdirectory(${small_SOURCE_DIR} ${small_BINARY_DIR} EXCLUDE_FROM_ALL) - endif() - - # ... - add_executable(your_target main.cpp) - target_link_libraries(your_target PUBLIC small::small) - ``` - - === "External package" - - ```cmake - # Follow installation instructions and then... - find_package(small REQUIRED) - if(NOT small_FOUND) - # Throw or put your FetchContent script here - endif() - - # ... - add_executable(your_target main.cpp) - target_link_libraries(your_target PUBLIC small::small) - ``` - -=== "Install" - - !!! note - - Get the binary package from the [release section](https://github.com/alandefreitas/small/releases). - - These binaries refer to the latest release version of small. - - !!! hint - - If you need a more recent version of `small`, you can download the binary packages from the CI artifacts or build the library from the source files. - -=== "Build from source" - - !!! note - - Ensure your C++ compiler and CMake are up-to-date and then: - - === "Ubuntu + GCC" - - ```bash - # Create a new directory - mkdir build - cd build - # Configure - cmake .. -DCMAKE_BUILD_TYPE=Release -DCMAKE_CXX_FLAGS="-O2" - # Build - sudo cmake --build . --parallel 2 --config Release - # Install - sudo cmake --install . - # Create packages - sudo cpack . - ``` - - === "Mac Os + Clang" - - ```bash - # Create a new directory - mkdir build - cd build - # Configure - cmake .. -DCMAKE_BUILD_TYPE=Release -DCMAKE_CXX_FLAGS="-O2" - # Build - cmake --build . --parallel 2 --config Release - # Install - cmake --install . - # Create packages - cpack . - ``` - - === "Windows + MSVC" - - ```bash - # Create a new directory - mkdir build - cd build - # Configure - cmake .. -DCMAKE_BUILD_TYPE=Release -DCMAKE_CXX_FLAGS="/O2" - # Build - cmake --build . --parallel 2 --config Release - # Install - cmake --install . - # Create packages - cpack . - ``` - - !!! hint "Parallel Build" - - Replace `--parallel 2` with `--parallel ` - - !!! note "Setting C++ Compiler" - - If your C++ compiler that supports C++17 is not your default compiler, make sure you provide CMake with the compiler location with the DCMAKE_C_COMPILER and DCMAKE_CXX_COMPILER options. For instance: - - ```bash - cmake .. -DCMAKE_BUILD_TYPE=Release -DCMAKE_CXX_FLAGS="-O2" -DCMAKE_C_COMPILER=/usr/bin/gcc-8 -DCMAKE_CXX_COMPILER=/usr/bin/g++-8 - ``` - -=== "File amalgamation" - - !!! note - - Because containers are header-only, you can directly copy the contents from the `source` directory into your project. - - !!! hint - - In that case, you are responsible for setting the appropriate target include directories and any compile definitions you might require. - - -Once the library is properly integrated, you can create containers from the namespace `small` like any other STL container: - -```cpp ---8<-- "examples/main.cpp" -``` - -All containers are optimized for the case when they're small but also efficient when they are large. The containers mix the common techniques found in other small container libraries: - -- Inline allocation for small containers -- Custom expected sizes -- Identification of relocatable types -- Custom growth factors with better defaults -- Communication with system memory allocators -- Explicit consideration of CPU cache sizes and branch prediction - -Most applications have many small lists and sets of elements. These containers avoid spending a lot of time with large containers -that contain just a few elements. Small containers usually try to use the stack before dynamically allocating memory and try -to represent associative containers with stack arrays, unless these sets are very large. - -The following containers are available: - -- `small::vector` -- `small::max_size_vector` -- `small::string` -- `small::set` -- `small::max_size_set` -- `small::multiset` -- `small::max_size_multiset` -- `small::unordered_set` -- `small::max_size_unordered_set` -- `small::unordered_multiset` -- `small::max_size_unordered_multiset` -- `small::map` -- `small::max_size_map` -- `small::multimap` -- `small::max_size_multimap` -- `small::unordered_map` -- `small::max_size_unordered_map` -- `small::unordered_multimap` -- `small::max_size_unordered_multimap` -- `small::stack` -- `small::queue` -- `small::priority_queue` - -Although many compilers support small string optimization (SSO) already, this library will ensure all strings support SOO, custom inline sizes, relocation, and unicode. - -## Vectors - -This small vector implementation includes: - -- Inline allocation for small vectors -- Custom expected size -- Special treatment of relocatable types - - Relocatable types can be moved with `memcpy`, bypassing destructors and constructors. - - Relocatable types are defined by default for POD types and aggregate types of PODs - - The `small::is_relocatable` traits can be used as an extension point for custom types -- Better growth factors -- Consider the cache line size in allocations -- Heap allocations can be disabled with `small::max_size_vector` - -When there are fewer elements than a given threshold, the elements are kept in a stack buffer for small vectors. Otherwise, the vector works as usual. However, if you are 100% sure you will never need more than `N` elements, you can use a `max_size_vector`, where elements are always inline. - -The default number of elements in a small vector is usually the number of elements we can already fit inline in a vector. For larger data types, the `default_inline_storage` trait can be used as an extension point where one can define how many elements a small vector of that type should contain by default. - -```cpp ---8<-- "examples/default_inline_storage.cpp" -``` - -When there's a reasonable default for the number of inline elements, this strategy avoids multiple vector type instantiations for different inline storage sizes. - -This small vector implementation used folly, abseil, and LLVM as a reference. - -## Strings - -The small string includes all the common optimizations for small vectors, and a custom template parameter to set how large we expect the string to be (in bytes). - -However, when strings are representing text, if there's one thing that makes them not small is not supporting UTF8. In addition to the common interface for strings, `small::string` includes extra functions to identify and work with UTF8 code points with random access. - -```cpp ---8<-- "examples/unicode_strings.cpp" -``` - -The problem of supporting UTF8 is easier to explain than it is to solve. Programming languages tend to solve this problem by (1) forbidding byte or substring access, and/or (2) allowing only access to code points with `O(n)` cost, where `n` is the number of code points. Because anything that forbids byte access would be incompatible with a C++ string, we allow direct byte access, and strings are allowed to be malformed unicode, which we can check with `small::is_malformed`. - -All capacity and access functions contain extra overloads that accept codepoint indexes, defined as a strong type, rather than byte indexes. By using these functions, one can ensure the string is never malformed. It's up to the user to decide whether these access functions are useful and worth it in a particular application. - -Access to codepoints is provided with an inline lookup-table trick that allows us to access codepoints in `O(log m)` time, where `m` is the number of multibyte code points in the strings. When there are no multibyte codepoints in the string, the string works as usual and no extra memory is required for the table. - -## Sets and Maps - -The small set/map classes use a more cache-friendly flat set/map and all other optimizations mentioned above for internal algorithms. As with other small containers, a custom template parameter can be used to define the number of inline elements in the container. - -The `small::default_inline_storage` and `small::is_relocatable` trait can also be defined for custom types, and all the usual set/map, ordered/unordered, uni/multi variants are also provided: - -```cpp ---8<-- "examples/associative.cpp" -``` - -Unlike a `small::vector` or `small::string`, the asymptotic time complexities of flat sets/maps are very different from their `std::` counterparts and should only be used when they are small. Because they are internally implemented as arrays, manipulating these containers costs `O(n)`. - -For large containers, you can use `std` containers with custom allocators. Or for efficient large containers, you can use the abseil containers, implemented as B+-trees. - -## Contributing - -### Get Involved - -* Discussions are concentrated on our GitHub [discussions](https://github.com/alandefreitas/small/discussions) page. Don't refrain from asking questions and proposing ideas. If this library helps you create something interesting, please divulge it with the community. -* If you are a programmer with good ideas, please [share](https://github.com/alandefreitas/small/discussions/new) these ideas with us. -* Academic collaboration is more than welcome. It'd be great to see this library help people write papers. - -### Ideas and Roadmap - -Feel free to contribute new features to this library. For complex features and changes, consider [getting feedback](https://github.com/alandefreitas/small/discussions/new) from the community first. Contributing to an existing code base with its conventions might seem obscure at first but please don't let that discourage you from sharing your ideas. - -There are many ways in which you can contribute to this library: - -* Testing the library in new environments see [1](https://github.com/alandefreitas/small/issues?q=is%3Aopen+is%3Aissue+label%3A%22cross-platform+issue+-+windows%22), [2](https://github.com/alandefreitas/small/issues?q=is%3Aopen+is%3Aissue+label%3A%22cross-platform+issue+-+linux%22), [3](https://github.com/alandefreitas/small/issues?q=is%3Aopen+is%3Aissue+label%3A%22cross-platform+issue+-+macos%22) -* Contributing with interesting examples see [1](source/examples) -* Finding problems in this documentation see [1](https://github.com/alandefreitas/small/issues?q=is%3Aopen+is%3Aissue+label%3A%22enhancement+-+documentation%22) -* Finding bugs in general see [1](https://github.com/alandefreitas/small/issues?q=is%3Aopen+is%3Aissue+label%3A%22bug+-+compilation+error%22), [2](https://github.com/alandefreitas/small/issues?q=is%3Aopen+is%3Aissue+label%3A%22bug+-+compilation+warning%22), [3](https://github.com/alandefreitas/small/issues?q=is%3Aopen+is%3Aissue+label%3A%22bug+-+runtime+error%22), [4](https://github.com/alandefreitas/small/issues?q=is%3Aopen+is%3Aissue+label%3A%22bug+-+runtime+warning%22) -* Whatever idea seems interesting to you - -The only thing we ask you is to make sure your contribution is not destructive. Some contributions in which we are not interested are: - -* "I don't like this optional feature, so I removed/deprecated it" -* "I removed this feature to support older versions of C++" but have not provided an equivalent alternative -* "I removed this feature, so I don't have to install/update ______" but have not provided an equivalent alternative -* "I'm creating this high-cost promise that we'll support ________ forever" but I'm not sticking around to keep that promise - -In doubt, please open a [discussion](https://github.com/alandefreitas/small/discussions) first - -### Guidelines - -If contributing with code, please leave all warnings ON (`-DSMALL_BUILD_WITH_PEDANTIC_WARNINGS=ON`), use [cppcheck](http://cppcheck.sourceforge.net/), and [clang-format](https://clang.llvm.org/docs/ClangFormat.html). - -If contributing to the documentation, please edit [`README.md`](README.md) directly, as the files in [`./docs`](./docs) are automatically generated with [mdsplit](https://github.com/alandefreitas/mdsplit). - -### Contributors - - - - - - -
- - marcosfpr -
- Marcos Pontes -
-
- - alandefreitas -
- Alan De Freitas -
-
- - -## References - -These are some references we used for this work: - -- [Abseil](https://github.com/abseil/abseil-cpp) -- [Folly](https://github.com/facebook/folly) -- [LLVM](https://github.com/llvm/llvm-project) -- [Boost Containers](https://github.com/boostorg/container) -- [Tiny-utf8](https://github.com/DuffsDevice/tiny-utf8) +[![Small](https://upload.wikimedia.org/wikipedia/commons/2/2a/Documentation-plain.svg)](https://alandefreitas.github.io/small/) + diff --git a/docs/.doxybook/config.json b/docs/.doxybook/config.json new file mode 100644 index 0000000..2be33d1 --- /dev/null +++ b/docs/.doxybook/config.json @@ -0,0 +1,13 @@ +{ + "baseUrl": "/small/reference/", + "indexInFolders": true, + "linkSuffix": "/", + "indexClassesName": "index", + "indexFilesName": "index", + "indexGroupsName": "index", + "indexNamespacesName": "index", + "indexRelatedPagesName": "index", + "indexExamplesName": "index", + "mainPageInRoot": true, + "mainPageName": "index" +} \ No newline at end of file diff --git a/docs/.doxybook/templates/breadcrumbs.tmpl b/docs/.doxybook/templates/breadcrumbs.tmpl new file mode 100644 index 0000000..997b76b --- /dev/null +++ b/docs/.doxybook/templates/breadcrumbs.tmpl @@ -0,0 +1,19 @@ +{% if exists("moduleBreadcrumbs") -%} +{%- for module in moduleBreadcrumbs -%} +**[{{module.title}}]({{module.url}})**{% if not loop.is_last or exists("title") %} **/** {% endif -%} +{% endfor %} +{% if exists("title") -%} +{% if exists("url") -%} +**[{{ stripNamespace(title) }}]({{url}})** +{% else %} +{{title}} +{% endif %} +{% endif -%} + +{% endif -%} + +{% if exists("location") -%} +Defined in header [`<{{ location.file }}>`](https://github.com/alandefreitas/small/blob/master/include/{{ location.file }}) + +{% endif -%} + diff --git a/docs/.doxybook/templates/class_members_details.tmpl b/docs/.doxybook/templates/class_members_details.tmpl new file mode 100644 index 0000000..0f66414 --- /dev/null +++ b/docs/.doxybook/templates/class_members_details.tmpl @@ -0,0 +1,117 @@ +{% if exists("publicTypes") %}## Public Types + +{% for child in publicTypes %}### {{child.kind}} {{child.name}} + +{{ render("member_details", child) }} +{% endfor %}{% endif -%} + +{% if exists("protectedTypes") %}## Protected Types + +{% for child in protectedTypes %}### {{child.kind}} {{child.name}} + +{{ render("member_details", child) }} +{% endfor %}{% endif -%} + +{% if exists("publicSlots") %}## Public Slots + +{% for child in publicSlots %}### {{child.kind}} {{child.name}} + +{{ render("member_details", child) }} +{% endfor %}{% endif -%} + +{% if exists("protectedSlots") %}## Protected Slots + +{% for child in protectedSlots %}### {{child.kind}} {{child.name}} + +{{ render("member_details", child) }} +{% endfor %}{% endif -%} + +{% if exists("publicSignals") %}## Public Signals + +{% for child in publicSignals %}### {{child.kind}} {{child.name}} + +{{ render("member_details", child) }} +{% endfor %}{% endif -%} + +{% if exists("protectedSignals") %}## Protected Signals + +{% for child in protectedSignals %}### {{child.kind}} {{child.name}} + +{{ render("member_details", child) }} +{% endfor %}{% endif -%} + +{% if exists("publicEvents") %}## Public Events + +{% for child in publicEvents %}### {{child.kind}} {{child.name}} + +{{ render("member_details", child) }} +{% endfor %}{% endif -%} + +{% if exists("protectedEvents") %}## Protected Events + +{% for child in protectedEvents %}### {{child.kind}} {{child.name}} + +{{ render("member_details", child) }} +{% endfor %}{% endif -%} + +{% if exists("publicFunctions") %}## Public Functions + +{%- set previous_overload="" -%} +{% for child in publicFunctions -%} +{% if previous_overload!=child.name -%} + +{{ "###" }} {{child.kind}} {{child.name}} + +{% set input.child = child -%} +{% set input.overload_candidates = publicFunctions -%} + +{{ render("merged_overload_details", input) }} +{%- set previous_overload=child.name -%} +{% endif -%} +{% endfor %}{% endif %} + + + + + +{% if exists("protectedFunctions") %}## Protected Functions + +{% for child in protectedFunctions %}### {{child.kind}} {{child.name}} + +{{ render("member_details", child) }} +{% endfor %}{% endif -%} + +{% if exists("publicProperties") %}## Public Property + +{% for child in publicProperties %}### {{child.kind}} {{child.name}} + +{{ render("member_details", child) }} +{% endfor %}{% endif -%} + +{% if exists("protectedProperties") %}## Protected Property + +{% for child in protectedProperties %}### {{child.kind}} {{child.name}} + +{{ render("member_details", child) }} +{% endfor %}{% endif -%} + +{% if exists("publicAttributes") %}## Public Attributes + +{% for child in publicAttributes %}### {{child.kind}} {{child.name}} + +{{ render("member_details", child) }} +{% endfor %}{% endif -%} + +{% if exists("protectedAttributes") %}## Protected Attributes + +{% for child in protectedAttributes %}### {{child.kind}} {{child.name}} + +{{ render("member_details", child) }} +{% endfor %}{% endif -%} + +{% if exists("friends") %}## Friends + +{% for child in friends %}### {{child.kind}} {{child.name}} + +{{ render("member_details", child) }} +{% endfor %}{% endif -%} \ No newline at end of file diff --git a/docs/.doxybook/templates/class_members_inherited_tables.tmpl b/docs/.doxybook/templates/class_members_inherited_tables.tmpl new file mode 100644 index 0000000..d95ec5a --- /dev/null +++ b/docs/.doxybook/templates/class_members_inherited_tables.tmpl @@ -0,0 +1,295 @@ +{% for base in baseClasses -%} +{%- if existsIn(base, "publicClasses") -%} +**Public Classes inherited from [{{base.name}}]({{base.url}})** + +| | Name | +| -------------- | -------------- | +{% for child in base.publicClasses -%} +| {{child.kind}} | **[{{last(stripNamespace(child.name))}}]({{child.url}})** {% if existsIn(child, "brief") %}
{{child.brief}}{% endif %} | +{% endfor %} +{% endif -%} +{%- if existsIn(base, "protectedClasses") -%} +**Protected Classes inherited from [{{base.name}}]({{base.url}})** + +| | Name | +| -------------- | -------------- | +{% for child in base.protectedClasses -%} +| {{child.kind}} | **[{{last(stripNamespace(child.name))}}]({{child.url}})** {% if existsIn(child, "brief") %}
{{child.brief}}{% endif %} | +{% endfor %} +{% endif -%} +{%- if existsIn(base, "publicTypes") -%} +**Public Types inherited from [{{base.name}}]({{base.url}})** + +| | Name | +| -------------- | -------------- | +{% for child in base.publicTypes -%} +| {% if existsIn(child, "templateParams") -%} +template <{% for param in child.templateParams -%} +{{param.typePlain}} {{param.name}}{% if existsIn(param, "defvalPlain") %} ={{param.defvalPlain}}{% endif -%} +{% if not loop.is_last %},{% endif -%} +{% endfor %}\>
{% endif -%} +{{child.kind}}{% if child.kind == "enum" and child.strong %} class{% endif %}{% if existsIn(child, "type") %} {{child.type}} {% endif -%}| **[{{child.name}}]({{child.url}})** {% if child.kind == "enum" %}{ {% for enumvalue in child.enumvalues -%} +{{enumvalue.name}}{% if existsIn(enumvalue, "initializer") %} {{enumvalue.initializer}}{% endif -%} +{% if not loop.is_last %}, {% endif %}{% endfor -%} + }{% endif -%} +{% if existsIn(child, "brief") %}
{{child.brief}}{% endif %} | +{% endfor %} +{% endif -%} +{%- if existsIn(base, "protectedTypes") -%} +**Protected Types inherited from [{{base.name}}]({{base.url}})** + +| | Name | +| -------------- | -------------- | +{% for child in base.protectedTypes -%} +| {% if existsIn(child, "templateParams") -%} +template <{% for param in child.templateParams -%} +{{param.typePlain}} {{param.name}}{% if existsIn(param, "defvalPlain") %} ={{param.defvalPlain}}{% endif -%} +{% if not loop.is_last %},{% endif -%} +{% endfor %}\>
{% endif -%} +{{child.kind}}{% if child.kind == "enum" and child.strong %} class{% endif %}{% if existsIn(child, "type") %} {{child.type}} {% endif -%}| **[{{child.name}}]({{child.url}})** {% if child.kind == "enum" %}{ {% for enumvalue in child.enumvalues -%} +{{enumvalue.name}}{% if existsIn(enumvalue, "initializer") %} {{enumvalue.initializer}}{% endif -%} +{% if not loop.is_last %}, {% endif %}{% endfor -%} + }{% endif -%} +{% if existsIn(child, "brief") %}
{{child.brief}}{% endif %} | +{% endfor %} +{% endif -%} +{%- if existsIn(base, "publicSlots") -%} +**Public Slots inherited from [{{base.name}}]({{base.url}})** + +| | Name | +| -------------- | -------------- | +{% for child in base.publicSlots -%} +| {% if existsIn(child, "templateParams") -%} +template <{% for param in child.templateParams -%} +{{param.typePlain}} {{param.name}}{% if existsIn(param, "defvalPlain") %} ={{param.defvalPlain}}{% endif -%} +{% if not loop.is_last %},{% endif -%} +{% endfor %}\>
{% endif -%} +{% if child.virtual %}virtual {% endif -%} +{% if existsIn(child, "type") %}{{child.type}} {% endif -%} +| **[{{child.name}}]({{child.url}})**({% for param in child.params -%} +{{param.type}} {{param.name}}{% if existsIn(param, "defval") %} ={{param.defval}}{% endif -%} +{% if not loop.is_last %}, {% endif -%} +{% endfor %}){% if child.const %} const{% endif -%} +{% if child.override %} override{% endif -%} +{% if child.default %} =default{% endif -%} +{% if child.deleted %} =delete{% endif -%} +{% if child.pureVirtual %} =0{% endif -%} + {% if existsIn(child, "brief") %}
{{child.brief}}{% endif %} | +{% endfor %} +{% endif -%} +{%- if existsIn(base, "protectedSlots") -%} +**Protected Slots inherited from [{{base.name}}]({{base.url}})** + +| | Name | +| -------------- | -------------- | +{% for child in base.protectedSlots -%} +| {% if existsIn(child, "templateParams") -%} +template <{% for param in child.templateParams -%} +{{param.typePlain}} {{param.name}}{% if existsIn(param, "defvalPlain") %} ={{param.defvalPlain}}{% endif -%} +{% if not loop.is_last %},{% endif -%} +{% endfor %}\>
{% endif -%} +{% if child.virtual %}virtual {% endif -%} +{% if existsIn(child, "type") %}{{child.type}} {% endif -%} +| **[{{child.name}}]({{child.url}})**({% for param in child.params -%} +{{param.type}} {{param.name}}{% if existsIn(param, "defval") %} ={{param.defval}}{% endif -%} +{% if not loop.is_last %}, {% endif -%} +{% endfor %}){% if child.const %} const{% endif -%} +{% if child.override %} override{% endif -%} +{% if child.default %} =default{% endif -%} +{% if child.deleted %} =delete{% endif -%} +{% if child.pureVirtual %} =0{% endif -%} + {% if existsIn(child, "brief") %}
{{child.brief}}{% endif %} | +{% endfor %} +{% endif -%} +{%- if existsIn(base, "publicSignals") -%} +**Public Signals inherited from [{{base.name}}]({{base.url}})** + +| | Name | +| -------------- | -------------- | +{% for child in base.publicSignals -%} +| {% if existsIn(child, "templateParams") -%} +template <{% for param in child.templateParams -%} +{{param.typePlain}} {{param.name}}{% if existsIn(param, "defvalPlain") %} ={{param.defvalPlain}}{% endif -%} +{% if not loop.is_last %},{% endif -%} +{% endfor %}\>
{% endif -%} +{% if child.virtual %}virtual {% endif -%} +{% if existsIn(child, "type") %}{{child.type}} {% endif -%} +| **[{{child.name}}]({{child.url}})**({% for param in child.params -%} +{{param.type}} {{param.name}}{% if existsIn(param, "defval") %} ={{param.defval}}{% endif -%} +{% if not loop.is_last %}, {% endif -%} +{% endfor %}){% if child.const %} const{% endif -%} +{% if child.override %} override{% endif -%} +{% if child.default %} =default{% endif -%} +{% if child.deleted %} =delete{% endif -%} +{% if child.pureVirtual %} =0{% endif -%} + {% if existsIn(child, "brief") %}
{{child.brief}}{% endif %} | +{% endfor %} +{% endif -%} +{%- if existsIn(base, "protectedSignals") -%} +**Protected Signals inherited from [{{base.name}}]({{base.url}})** + +| | Name | +| -------------- | -------------- | +{% for child in base.protectedSignals -%} +| {% if existsIn(child, "templateParams") -%} +template <{% for param in child.templateParams -%} +{{param.typePlain}} {{param.name}}{% if existsIn(param, "defvalPlain") %} ={{param.defvalPlain}}{% endif -%} +{% if not loop.is_last %},{% endif -%} +{% endfor %}\>
{% endif -%} +{% if child.virtual %}virtual {% endif -%} +{% if existsIn(child, "type") %}{{child.type}} {% endif -%} +| **[{{child.name}}]({{child.url}})**({% for param in child.params -%} +{{param.type}} {{param.name}}{% if existsIn(param, "defval") %} ={{param.defval}}{% endif -%} +{% if not loop.is_last %}, {% endif -%} +{% endfor %}){% if child.const %} const{% endif -%} +{% if child.override %} override{% endif -%} +{% if child.default %} =default{% endif -%} +{% if child.deleted %} =delete{% endif -%} +{% if child.pureVirtual %} =0{% endif -%} + {% if existsIn(child, "brief") %}
{{child.brief}}{% endif %} | +{% endfor %} +{% endif -%} +{%- if existsIn(base, "publicEvents") -%} +**Public Events inherited from [{{base.name}}]({{base.url}})** + +| | Name | +| -------------- | -------------- | +{% for child in base.publicEvents -%} +| {% if existsIn(child, "templateParams") -%} +template <{% for param in child.templateParams -%} +{{param.typePlain}} {{param.name}}{% if existsIn(param, "defvalPlain") %} ={{param.defvalPlain}}{% endif -%} +{% if not loop.is_last %},{% endif -%} +{% endfor %}\>
{% endif -%} +{% if child.virtual %}virtual {% endif -%} +{% if existsIn(child, "type") %}{{child.type}} {% endif -%} +| **[{{child.name}}]({{child.url}})**({% for param in child.params -%} +{{param.type}} {{param.name}}{% if existsIn(param, "defval") %} ={{param.defval}}{% endif -%} +{% if not loop.is_last %}, {% endif -%} +{% endfor %}){% if child.const %} const{% endif -%} +{% if child.override %} override{% endif -%} +{% if child.default %} =default{% endif -%} +{% if child.deleted %} =delete{% endif -%} +{% if child.pureVirtual %} =0{% endif -%} + {% if existsIn(child, "brief") %}
{{child.brief}}{% endif %} | +{% endfor %} +{% endif -%} +{%- if existsIn(base, "protectedEvents") -%} +**Protected Events inherited from [{{base.name}}]({{base.url}})** + +| | Name | +| -------------- | -------------- | +{% for child in base.protectedEvents -%} +| {% if existsIn(child, "templateParams") -%} +template <{% for param in child.templateParams -%} +{{param.typePlain}} {{param.name}}{% if existsIn(param, "defvalPlain") %} ={{param.defvalPlain}}{% endif -%} +{% if not loop.is_last %},{% endif -%} +{% endfor %}\>
{% endif -%} +{% if child.virtual %}virtual {% endif -%} +{% if existsIn(child, "type") %}{{child.type}} {% endif -%} +| **[{{child.name}}]({{child.url}})**({% for param in child.params -%} +{{param.type}} {{param.name}}{% if existsIn(param, "defval") %} ={{param.defval}}{% endif -%} +{% if not loop.is_last %}, {% endif -%} +{% endfor %}){% if child.const %} const{% endif -%} +{% if child.override %} override{% endif -%} +{% if child.default %} =default{% endif -%} +{% if child.deleted %} =delete{% endif -%} +{% if child.pureVirtual %} =0{% endif -%} + {% if existsIn(child, "brief") %}
{{child.brief}}{% endif %} | +{% endfor %} +{% endif -%} +{%- if existsIn(base, "publicFunctions") -%} +**Member Functions** (inherited from [{{stripNamespace(base.name)}}]({{base.url}})) + +| Member function | Description | +|-----------------|-------------| +{%- set previous_overload="" -%} +{% for child in base.publicFunctions -%} +{% if previous_overload!=child.name -%} +| **[{% if stripNamespace(name) == child.name %}(constructor){% else if "~" + stripNamespace(name) == child.name %}(destructor){% else %}{{replace(child.name, "|","\\|")}}{% endif %}]({{replace(child.url, "|", "_1")}})** {% if child.override %} `override`{% endif -%} +{% if child.deleted %} = delete{% endif -%} +{% if child.pureVirtual %} =0{% endif -%} +| {% if existsIn(child, "brief") %}{{replace(child.brief, "|", "\\|")}}
{% endif %} ({% if child.virtual %}virtual {% endif -%}public member {{child.kind}}{% if existsIn(child, "templateParams") %} template{% endif %}) | +{%- set previous_overload=child.name -%} +{% endif -%} +{% endfor %} +{% endif -%} + + +{%- if existsIn(base, "protectedFunctions") -%} +**Protected Functions inherited from [{{base.name}}]({{base.url}})** + +| | Name | +| -------------- | -------------- | +{% for child in base.protectedFunctions -%} +| {% if existsIn(child, "templateParams") -%} +template <{% for param in child.templateParams -%} +{{param.typePlain}} {{param.name}}{% if existsIn(param, "defvalPlain") %} ={{param.defvalPlain}}{% endif -%} +{% if not loop.is_last %},{% endif -%} +{% endfor %}\>
{% endif -%} +{% if child.virtual %}virtual {% endif -%} +{% if existsIn(child, "type") %}{{child.type}} {% endif -%} +| **[{{child.name}}]({{child.url}})**({% for param in child.params -%} +{{param.type}} {{param.name}}{% if existsIn(param, "defval") %} ={{param.defval}}{% endif -%} +{% if not loop.is_last %}, {% endif -%} +{% endfor %}){% if child.const %} const{% endif -%} +{% if child.override %} override{% endif -%} +{% if child.default %} =default{% endif -%} +{% if child.deleted %} =delete{% endif -%} +{% if child.pureVirtual %} =0{% endif -%} + {% if existsIn(child, "brief") %}
{{child.brief}}{% endif %} | +{% endfor %} +{% endif -%} +{%- if existsIn(base, "publicProperties") -%} +**Public Properties inherited from [{{base.name}}]({{base.url}})** + +| | Name | +| -------------- | -------------- | +{% for child in base.publicProperties -%} +| {% if existsIn(child, "type") %}{{child.type}} {% endif -%} +| **[{{child.name}}]({{child.url}})** {% if existsIn(child, "brief") %}
{{child.brief}}{% endif %} | +{% endfor %} +{% endif -%} +{%- if existsIn(base, "protectedProperties") -%} +**Protected Properties inherited from [{{base.name}}]({{base.url}})** + +| | Name | +| -------------- | -------------- | +{% for child in base.protectedProperties -%} +| {% if existsIn(child, "type") %}{{child.type}} {% endif -%} +| **[{{child.name}}]({{child.url}})** {% if existsIn(child, "brief") %}
{{child.brief}}{% endif %} | +{% endfor %} +{% endif -%} +{%- if existsIn(base, "publicAttributes") -%} +**Public Attributes inherited from [{{base.name}}]({{base.url}})** + +| | Name | +| -------------- | -------------- | +{% for child in base.publicAttributes -%} +| {% if existsIn(child, "type") %}{{child.type}} {% endif -%} +| **[{{child.name}}]({{child.url}})** {% if existsIn(child, "brief") %}
{{child.brief}}{% endif %} | +{% endfor %} +{% endif -%} +{%- if existsIn(base, "protectedAttributes") -%} +**Protected Attributes inherited from [{{base.name}}]({{base.url}})** + +| | Name | +| -------------- | -------------- | +{% for child in base.protectedAttributes -%} +| {% if existsIn(child, "type") %}{{child.type}} {% endif -%} +| **[{{child.name}}]({{child.url}})** {% if existsIn(child, "brief") %}
{{child.brief}}{% endif %} | +{% endfor %} +{% endif -%} +{% if existsIn(base, "friends") %}**Friends inherited from [{{base.name}}]({{base.url}})** + +| | Name | +| -------------- | -------------- | +{% for child in base.friends -%}| {% if existsIn(child, "type") %}{{child.type}} {% endif -%} +| **[{{child.name}}]({{child.url}})**{% if child.type != "class" and child.type != "struct" -%} +({% for param in child.params -%} +{{param.type}} {{param.name}}{% if existsIn(param, "defval") %} ={{param.defval}}{% endif -%} +{% if not loop.is_last %}, {% endif -%} +{% endfor %}){% if child.const %} const{% endif -%} +{% endif %} {% if existsIn(child, "brief") %}
{{child.brief}}{% endif %} | +{% endfor %} +{% endif -%} +{% endfor -%} \ No newline at end of file diff --git a/docs/.doxybook/templates/class_members_tables.tmpl b/docs/.doxybook/templates/class_members_tables.tmpl new file mode 100644 index 0000000..8537472 --- /dev/null +++ b/docs/.doxybook/templates/class_members_tables.tmpl @@ -0,0 +1,262 @@ +{%- if exists("publicClasses") %}## Member Classes + +| | Name | +| -------------- | -------------- | +{% for child in publicClasses -%} +| {{child.kind}} | **[{{last(stripNamespace(child.name))}}]({{child.url}})** {% if existsIn(child, "brief") %}
{{child.brief}}{% endif %} | +{% endfor %} +{% endif -%} +{%- if exists("protectedClasses") %}## Protected Classes + +| | Name | +| -------------- | -------------- | +{% for child in protectedClasses -%} +| {{child.kind}} | **[{{last(stripNamespace(child.name))}}]({{child.url}})** {% if existsIn(child, "brief") %}
{{child.brief}}{% endif %} | +{% endfor %} +{% endif -%} +{%- if exists("publicTypes") %}## Member Types + +| Member type | Definition | +|-------------|------------| +{% for child in publicTypes -%} +| **[{{child.name}}]({{child.url}})** | {% if existsIn(child, "brief") -%} +{{child.brief}}{% else if existsIn(child, "typePlain") -%} +`{{ child.typePlain }}`{% else if existsIn(child, "type") -%} +`{{ child.type }}` {% endif -%} | +{% endfor %} +{% endif -%} + +{%- if exists("protectedTypes") %}## Protected Types + +| | Name | +| -------------- | -------------- | +{% for child in protectedTypes -%} +| {% if existsIn(child, "templateParams") -%} +template <{% for param in child.templateParams -%} +{{param.typePlain}} {{param.name}}{% if existsIn(param, "defvalPlain") %} ={{param.defvalPlain}}{% endif -%} +{% if not loop.is_last %},{% endif -%} +{% endfor %}\>
{% endif -%} +{{child.kind}}{% if child.kind == "enum" and child.strong %} class{% endif %}{% if existsIn(child, "type") %} {{child.type}} {% endif -%}| **[{{child.name}}]({{child.url}})** {% if child.kind == "enum" %}{ {% for enumvalue in child.enumvalues -%} +{{enumvalue.name}}{% if existsIn(enumvalue, "initializer") %} {{enumvalue.initializer}}{% endif -%} +{% if not loop.is_last %}, {% endif %}{% endfor -%} + }{% endif -%} +{% if existsIn(child, "brief") %}
{{child.brief}}{% endif %} | +{% endfor %} +{% endif -%} +{%- if exists("publicSlots") %}## Member Slots + +| | Name | +| -------------- | -------------- | +{% for child in publicSlots -%} +| {% if existsIn(child, "templateParams") -%} +template <{% for param in child.templateParams -%} +{{param.typePlain}} {{param.name}}{% if existsIn(param, "defvalPlain") %} ={{param.defvalPlain}}{% endif -%} +{% if not loop.is_last %},{% endif -%} +{% endfor %}\>
{% endif -%} +{% if child.virtual %}virtual {% endif -%} +{% if existsIn(child, "type") %}{{child.type}} {% endif -%} +| **[{{child.name}}]({{child.url}})**({% for param in child.params -%} +{{param.type}} {{param.name}}{% if existsIn(param, "defval") %} ={{param.defval}}{% endif -%} +{% if not loop.is_last %}, {% endif -%} +{% endfor %}){% if child.const %} const{% endif -%} +{% if child.override %} override{% endif -%} +{% if child.default %} =default{% endif -%} +{% if child.deleted %} =delete{% endif -%} +{% if child.pureVirtual %} =0{% endif -%} + {% if existsIn(child, "brief") %}
{{child.brief}}{% endif %} | +{% endfor %} +{% endif -%} +{%- if exists("protectedSlots") %}## Protected Slots + +| | Name | +| -------------- | -------------- | +{% for child in protectedSlots -%} +| {% if existsIn(child, "templateParams") -%} +template <{% for param in child.templateParams -%} +{{param.typePlain}} {{param.name}}{% if existsIn(param, "defvalPlain") %} ={{param.defvalPlain}}{% endif -%} +{% if not loop.is_last %},{% endif -%} +{% endfor %}\>
{% endif -%} +{% if child.virtual %}virtual {% endif -%} +{% if existsIn(child, "type") %}{{child.type}} {% endif -%} +| **[{{child.name}}]({{child.url}})**({% for param in child.params -%} +{{param.type}} {{param.name}}{% if existsIn(param, "defval") %} ={{param.defval}}{% endif -%} +{% if not loop.is_last %}, {% endif -%} +{% endfor %}){% if child.const %} const{% endif -%} +{% if child.override %} override{% endif -%} +{% if child.default %} =default{% endif -%} +{% if child.deleted %} =delete{% endif -%} +{% if child.pureVirtual %} =0{% endif -%} + {% if existsIn(child, "brief") %}
{{child.brief}}{% endif %} | +{% endfor %} +{% endif -%} +{%- if exists("publicSignals") %}## Member Signals + +| | Name | +| -------------- | -------------- | +{% for child in publicSignals -%} +| {% if existsIn(child, "templateParams") -%} +template <{% for param in child.templateParams -%} +{{param.typePlain}} {{param.name}}{% if existsIn(param, "defvalPlain") %} ={{param.defvalPlain}}{% endif -%} +{% if not loop.is_last %},{% endif -%} +{% endfor %}\>
{% endif -%} +{% if child.virtual %}virtual {% endif -%} +{% if existsIn(child, "type") %}{{child.type}} {% endif -%} +| **[{{child.name}}]({{child.url}})**({% for param in child.params -%} +{{param.type}} {{param.name}}{% if existsIn(param, "defval") %} ={{param.defval}}{% endif -%} +{% if not loop.is_last %}, {% endif -%} +{% endfor %}){% if child.const %} const{% endif -%} +{% if child.override %} override{% endif -%} +{% if child.default %} =default{% endif -%} +{% if child.deleted %} =delete{% endif -%} +{% if child.pureVirtual %} =0{% endif -%} + {% if existsIn(child, "brief") %}
{{child.brief}}{% endif %} | +{% endfor %} +{% endif -%} +{%- if exists("protectedSignals") %}## Protected Signals + +| | Name | +| -------------- | -------------- | +{% for child in protectedSignals -%} +| {% if existsIn(child, "templateParams") -%} +template <{% for param in child.templateParams -%} +{{param.typePlain}} {{param.name}}{% if existsIn(param, "defvalPlain") %} ={{param.defvalPlain}}{% endif -%} +{% if not loop.is_last %},{% endif -%} +{% endfor %}\>
{% endif -%} +{% if child.virtual %}virtual {% endif -%} +{% if existsIn(child, "type") %}{{child.type}} {% endif -%} +| **[{{child.name}}]({{child.url}})**({% for param in child.params -%} +{{param.type}} {{param.name}}{% if existsIn(param, "defval") %} ={{param.defval}}{% endif -%} +{% if not loop.is_last %}, {% endif -%} +{% endfor %}){% if child.const %} const{% endif -%} +{% if child.override %} override{% endif -%} +{% if child.default %} =default{% endif -%} +{% if child.deleted %} =delete{% endif -%} +{% if child.pureVirtual %} =0{% endif -%} + {% if existsIn(child, "brief") %}
{{child.brief}}{% endif %} | +{% endfor %} +{% endif -%} +{%- if exists("publicEvents") %}## Member Events + +| | Name | +| -------------- | -------------- | +{% for child in publicEvents -%} +| {% if existsIn(child, "templateParams") -%} +template <{% for param in child.templateParams -%} +{{param.typePlain}} {{param.name}}{% if existsIn(param, "defvalPlain") %} ={{param.defvalPlain}}{% endif -%} +{% if not loop.is_last %},{% endif -%} +{% endfor %}\>
{% endif -%} +{% if child.virtual %}virtual {% endif -%} +{% if existsIn(child, "type") %}{{child.type}} {% endif -%} +| **[{{child.name}}]({{child.url}})**({% for param in child.params -%} +{{param.type}} {{param.name}}{% if existsIn(param, "defval") %} ={{param.defval}}{% endif -%} +{% if not loop.is_last %}, {% endif -%} +{% endfor %}){% if child.const %} const{% endif -%} +{% if child.override %} override{% endif -%} +{% if child.default %} =default{% endif -%} +{% if child.deleted %} =delete{% endif -%} +{% if child.pureVirtual %} =0{% endif -%} + {% if existsIn(child, "brief") %}
{{child.brief}}{% endif %} | +{% endfor %} +{% endif -%} +{%- if exists("protectedEvents") %}## Protected Events + +| | Name | +| -------------- | -------------- | +{% for child in protectedEvents -%} +| {% if existsIn(child, "templateParams") -%} +template <{% for param in child.templateParams -%} +{{param.typePlain}} {{param.name}}{% if existsIn(param, "defvalPlain") %} ={{param.defvalPlain}}{% endif -%} +{% if not loop.is_last %},{% endif -%} +{% endfor %}\>
{% endif -%} +{% if child.virtual %}virtual {% endif -%} +{% if existsIn(child, "type") %}{{child.type}} {% endif -%} +| **[{{child.name}}]({{child.url}})**({% for param in child.params -%} +{{param.type}} {{param.name}}{% if existsIn(param, "defval") %} ={{param.defval}}{% endif -%} +{% if not loop.is_last %}, {% endif -%} +{% endfor %}){% if child.const %} const{% endif -%} +{% if child.override %} override{% endif -%} +{% if child.default %} =default{% endif -%} +{% if child.deleted %} =delete{% endif -%} +{% if child.pureVirtual %} =0{% endif -%} + {% if existsIn(child, "brief") %}
{{child.brief}}{% endif %} | +{% endfor %} +{% endif -%} +{%- if exists("publicFunctions") %}## Member Functions + +| Member function | Description | +|-----------------|-------------| +{%- set previous_overload="" -%} +{% for child in publicFunctions -%} +{% if previous_overload!=child.name -%} +| **[{% if stripNamespace(name) == child.name %}(constructor){% else if "~" + stripNamespace(name) == child.name %}(destructor){% else %}{{replace(child.name, "|","\\|")}}{% endif %}]({{replace(child.url, "|", "_1")}})** {% if child.override %} `override`{% endif -%} +{% if child.deleted %} = delete{% endif -%} +{% if child.pureVirtual %} =0{% endif -%} +| {% if existsIn(child, "brief") %}{{replace(child.brief, "|", "\\|")}}
{% endif %} ({% if child.virtual %}virtual {% endif -%}public member {{child.kind}}{% if existsIn(child, "templateParams") %} template{% endif %}) | +{%- set previous_overload=child.name -%} +{% endif -%} +{% endfor %} +{% endif -%} + +{%- if exists("protectedFunctions") %}## Protected Functions + +| Protected function | Description | +|--------------------|-------------| +{%- set previous_overload="" -%} +{% for child in protectedFunctions -%} +{% if previous_overload!=child.name -%} +| **[{% if stripNamespace(name) == child.name %}(constructor){% else if "~" + stripNamespace(name) == child.name %}(destructor){% else %}{{replace(child.name, "|","\\|")}}{% endif %}]({{replace(child.url, "|", "_1")}})** {% if child.override %} `override`{% endif -%} +{% if child.deleted %} = delete{% endif -%} +{% if child.pureVirtual %} =0{% endif -%} +| {% if existsIn(child, "brief") %}{{replace(child.brief, "|", "\\|")}}
{% endif %} ({% if child.virtual %}virtual {% endif -%}public member {{child.kind}}{% if existsIn(child, "templateParams") %} template{% endif %}) | +{%- set previous_overload=child.name -%} +{% endif -%} +{% endfor %} +{% endif -%} + + + +{%- if exists("publicProperties") %}## Member Properties + +| | Name | +| -------------- | -------------- | +{% for child in publicProperties -%} +| {% if existsIn(child, "type") %}{{child.type}} {% endif -%} +| **[{{child.name}}]({{child.url}})** {% if existsIn(child, "brief") %}
{{child.brief}}{% endif %} | +{% endfor %} +{% endif -%} +{%- if exists("protectedProperties") %}## Protected Properties + +| | Name | +| -------------- | -------------- | +{% for child in protectedProperties -%} +| {% if existsIn(child, "type") %}{{child.type}} {% endif -%} +| **[{{child.name}}]({{child.url}})** {% if existsIn(child, "brief") %}
{{child.brief}}{% endif %} | +{% endfor %} +{% endif -%} +{%- if exists("publicAttributes") %}## Member Attributes + +| Member Attribute | Description | +|------------------|-------------| +{% for child in publicAttributes -%} +| **[{{child.name}}]({{child.url}})** | {% if existsIn(child, "brief") %}{{child.brief}}
{% endif -%} +{% if existsIn(child, "type") %}`{{child.type}}`
{% endif -%} +(public member {{child.kind}}{% if existsIn(child, "templateParams") %} template{% endif %}) | +{% endfor %} +{% endif -%} +{%- if exists("protectedAttributes") %}## Protected Attributes + +| | Name | +| -------------- | -------------- | +{% for child in protectedAttributes -%} +| {% if existsIn(child, "type") %}{{child.type}} {% endif -%} +| **[{{child.name}}]({{child.url}})** {% if existsIn(child, "brief") %}
{{child.brief}}{% endif %} | +{% endfor %} +{% endif -%} +{% if exists("friends") %}## Friends + +| | Name | +| -------------- |--------------------------------------| +{% for child in friends -%}| **[{{child.name}}]({{child.url}})** | {% if existsIn(child, "brief") %}{{child.brief}}
{% endif -%} +({% if existsIn(child, "templateParams") %}template {% endif %}{{child.kind}} {% if existsIn(child, "type") %}{{child.type}}{% endif -%}) | +{% endfor %} +{% endif -%} diff --git a/docs/.doxybook/templates/details.tmpl b/docs/.doxybook/templates/details.tmpl new file mode 100644 index 0000000..f6ea625 --- /dev/null +++ b/docs/.doxybook/templates/details.tmpl @@ -0,0 +1,192 @@ +{% if exists("brief") %}{{brief}} +{% endif -%} + +{% if exists("templateParamsList") %} +**Template Parameters** + +{% for param in templateParamsList %} * **{{param.name}}** - {{param.text}} +{% endfor %} +{% endif -%} + +{% if exists("paramList") %} +**Parameters** + +{% for param in paramList %} * **{{param.name}}** - {{param.text}} +{% endfor %} +{% endif -%} + +{% if exists("returnsList") %} +**Returns**: + +{% for param in returnsList %} * **{{param.name}}** - {{param.text}} +{% endfor %} +{% endif -%} + +{% if exists("exceptionsList") %} +**Exceptions**: + +{% for param in exceptionsList %} * **{{param.name}}** - {{param.text}} +{% endfor %} +{% endif -%} + +{# RENDER DETAILS (and always call it notes, as in cppreference) #} +{% if exists("details") %} +**Description** + +{{details}} + +{% endif -%} + +{% if exists("deprecated") %} +**Deprecated**: + +{{deprecated}} +{% endif -%} + +{% if exists("see") %} +**See Also**: {% if length(see) == 1 %}{{first(see)}}{% else %} + +{% for item in see %} * {{item}} +{% endfor %}{% endif %} +{% endif -%} + +{% if exists("returns") %} +**Return**: {% if length(returns) == 1 %}{{first(returns)}}{% else %} + +{% for item in returns %} * {{item}} +{% endfor %}{% endif %} +{% endif -%} + +{% if exists("authors") %} +**Author**: {% if length(authors) == 1 %}{{first(authors)}}{% else %} + +{% for item in authors %} * {{item}} +{% endfor %}{% endif %} +{% endif -%} + +{% if exists("version") %} +**Version**: {% if length(version) == 1 %}{{first(version)}}{% else %} + +{% for item in version %} * {{item}} +{% endfor %}{% endif %} +{% endif -%} + +{% if exists("since") %} +**Since**: {% if length(since) == 1 %}{{first(since)}}{% else %} + +{% for item in since %} * {{item}} +{% endfor %}{% endif %} +{% endif -%} + +{% if exists("date") %} +**Date**: {% if length(date) == 1 %}{{first(date)}}{% else %} + +{% for item in date %} * {{item}} +{% endfor %}{% endif %} +{% endif -%} + +{% if exists("note") %} +**Note**: {% if length(note) == 1 %}{{first(note)}}{% else %} + +{% for item in note %} * {{item}} +{% endfor %}{% endif %} +{% endif -%} + +{% if exists("bugs") %} +**Bug**: {% if length(bugs) == 1 %}{{first(bugs)}}{% else %} + +{% for item in bugs %} * {{item}} +{% endfor %}{% endif %} +{% endif -%} + +{% if exists("tests") %} +**Test**: {% if length(tests) == 1 %}{{first(tests)}}{% else %} + +{% for item in tests %} * {{item}} +{% endfor %}{% endif %} +{% endif -%} + +{% if exists("todos") %} +**Todo**: {% if length(todos) == 1 %}{{first(todos)}}{% else %} + +{% for item in todos %} * {{item}} +{% endfor %}{% endif %} +{% endif -%} + +{% if exists("warning") %} +**Warning**: {% if length(warning) == 1 %}{{first(warning)}}{% else %} + +{% for item in warning %} * {{item}} +{% endfor %}{% endif %} +{% endif -%} + +{% if exists("pre") %} +**Precondition**: {% if length(pre) == 1 %}{{first(pre)}}{% else %} + +{% for item in pre %} * {{item}} +{% endfor %}{% endif %} +{% endif -%} + +{% if exists("post") %} +**Postcondition**: {% if length(post) == 1 %}{{first(post)}}{% else %} + +{% for item in post %} * {{item}} +{% endfor %}{% endif %} +{% endif -%} + +{% if exists("copyright") %} +**Copyright**: {% if length(copyright) == 1 %}{{first(copyright)}}{% else %} + +{% for item in copyright %} * {{item}} +{% endfor %}{% endif %} +{% endif -%} + +{% if exists("invariant") %} +**Invariant**: {% if length(invariant) == 1 %}{{first(invariant)}}{% else %} + +{% for item in invariant %} * {{item}} +{% endfor %}{% endif %} +{% endif -%} + +{% if exists("remark") %} +**Remark**: {% if length(remark) == 1 %}{{first(remark)}}{% else %} + +{% for item in remark %} * {{item}} +{% endfor %}{% endif %} +{% endif -%} + +{% if exists("attention") %} +**Attention**: {% if length(attention) == 1 %}{{first(attention)}}{% else %} + +{% for item in attention %} * {{item}} +{% endfor %}{% endif %} +{% endif -%} + +{% if exists("par") %} +**Par**: {% if length(par) == 1 %}{{first(par)}}{% else %} + +{% for item in par %} * {{item}} +{% endfor %}{% endif %} +{% endif -%} + +{% if exists("rcs") %} +**Rcs**: {% if length(rcs) == 1 %}{{first(rcs)}}{% else %} + +{% for item in rcs %} * {{item}} +{% endfor %}{% endif %} +{% endif -%} + +{% if exists("reimplements") %} +**Reimplements**: [{{reimplements.fullname}}]({{reimplements.url}}) + +{% endif -%} + +{% if exists("reimplementedBy") %} +**Reimplemented by**: {% for impl in reimplementedBy %}[{{impl.fullname}}]({{impl.url}}){% if not loop.is_last %}, {% endif %}{% endfor %} + +{% endif -%} + +{% if exists("inbody") %} +{{inbody}} + +{% endif -%} \ No newline at end of file diff --git a/docs/.doxybook/templates/footer.tmpl b/docs/.doxybook/templates/footer.tmpl new file mode 100644 index 0000000..e4ec6bb --- /dev/null +++ b/docs/.doxybook/templates/footer.tmpl @@ -0,0 +1,3 @@ +------------------------------- + +Updated on {{date("%F")}} \ No newline at end of file diff --git a/docs/.doxybook/templates/header.tmpl b/docs/.doxybook/templates/header.tmpl new file mode 100644 index 0000000..cee5ab7 --- /dev/null +++ b/docs/.doxybook/templates/header.tmpl @@ -0,0 +1,26 @@ +--- +{% if exists("title") -%} +title: {{title}} +{% else if exists("name") -%} +title: {{name}} +{% endif -%} +{% if exists("summary") -%} +summary: {{summary}} +{% endif -%} +{% include "meta" %} +--- + +{% if exists("title") -%} +{% if exists("kind") and kind == "group" -%} +{% if exists("moduleBreadcrumbs") -%} +# {{title}} Module +{% else -%} +# {{title}} Library +{% endif -%} +{% else -%} +# {{title}} +{% endif -%} +{% else if exists("kind") and kind != "page" -%} +# {{name}} {{title(kind)}} Reference +{% endif %} + diff --git a/docs/.doxybook/templates/index.tmpl b/docs/.doxybook/templates/index.tmpl new file mode 100644 index 0000000..9d4d98d --- /dev/null +++ b/docs/.doxybook/templates/index.tmpl @@ -0,0 +1,10 @@ + +{% for child0 in children %}* **{{child0.kind}} [{{child0.title}}]({{child0.url}})** {% if existsIn(child0, "brief") %}
{{child0.brief}}{% endif %}{% if existsIn(child0, "children") %}{% for child1 in child0.children %} + * **{{child1.kind}} [{{last(stripNamespace(child1.title))}}]({{child1.url}})** {% if existsIn(child1, "brief") %}
{{child1.brief}}{% endif %}{% if existsIn(child1, "children") %}{% for child2 in child1.children %} + * **{{child2.kind}} [{{last(stripNamespace(child2.title))}}]({{child2.url}})** {% if existsIn(child2, "brief") %}
{{child2.brief}}{% endif %}{% if existsIn(child2, "children") %}{% for child3 in child2.children %} + * **{{child3.kind}} [{{last(stripNamespace(child3.title))}}]({{child3.url}})** {% if existsIn(child3, "brief") %}
{{child3.brief}}{% endif %}{% if existsIn(child3, "children") %}{% for child4 in child3.children %} + * **{{child4.kind}} [{{last(stripNamespace(child4.title))}}]({{child4.url}})** {% if existsIn(child4, "brief") %}
{{child4.brief}}{% endif %}{% if existsIn(child4, "children") %}{% for child5 in child4.children %} + * **{{child5.kind}} [{{last(stripNamespace(child5.title))}}]({{child5.url}})** {% if existsIn(child5, "brief") %}
{{child5.brief}}{% endif %}{% if existsIn(child5, "children") %}{% for child6 in child5.children %} + * **{{child6.kind}} [{{last(stripNamespace(child6.title))}}]({{child6.url}})** {% if existsIn(child6, "brief") %}
{{child6.brief}}{% endif %}{% if existsIn(child6, "children") %}{% for child7 in child6.children %} + * **{{child7.kind}} [{{last(stripNamespace(child7.title))}}]({{child7.url}})** {% if existsIn(child7, "brief") %}
{{child7.brief}}{% endif %}{% endfor %}{% endif %}{% endfor %}{% endif %}{% endfor %}{% endif %}{% endfor %}{% endif %}{% endfor %}{% endif %}{% endfor %}{% endif %}{% endfor %}{% endif %} +{% endfor %} diff --git a/docs/.doxybook/templates/index_classes.tmpl b/docs/.doxybook/templates/index_classes.tmpl new file mode 100644 index 0000000..468824a --- /dev/null +++ b/docs/.doxybook/templates/index_classes.tmpl @@ -0,0 +1,5 @@ +{% include "header" %} + +{% include "index" %} + +{% include "footer" %} diff --git a/docs/.doxybook/templates/index_examples.tmpl b/docs/.doxybook/templates/index_examples.tmpl new file mode 100644 index 0000000..468824a --- /dev/null +++ b/docs/.doxybook/templates/index_examples.tmpl @@ -0,0 +1,5 @@ +{% include "header" %} + +{% include "index" %} + +{% include "footer" %} diff --git a/docs/.doxybook/templates/index_files.tmpl b/docs/.doxybook/templates/index_files.tmpl new file mode 100644 index 0000000..468824a --- /dev/null +++ b/docs/.doxybook/templates/index_files.tmpl @@ -0,0 +1,5 @@ +{% include "header" %} + +{% include "index" %} + +{% include "footer" %} diff --git a/docs/.doxybook/templates/index_groups.tmpl b/docs/.doxybook/templates/index_groups.tmpl new file mode 100644 index 0000000..468824a --- /dev/null +++ b/docs/.doxybook/templates/index_groups.tmpl @@ -0,0 +1,5 @@ +{% include "header" %} + +{% include "index" %} + +{% include "footer" %} diff --git a/docs/.doxybook/templates/index_namespaces.tmpl b/docs/.doxybook/templates/index_namespaces.tmpl new file mode 100644 index 0000000..468824a --- /dev/null +++ b/docs/.doxybook/templates/index_namespaces.tmpl @@ -0,0 +1,5 @@ +{% include "header" %} + +{% include "index" %} + +{% include "footer" %} diff --git a/docs/.doxybook/templates/index_pages.tmpl b/docs/.doxybook/templates/index_pages.tmpl new file mode 100644 index 0000000..468824a --- /dev/null +++ b/docs/.doxybook/templates/index_pages.tmpl @@ -0,0 +1,5 @@ +{% include "header" %} + +{% include "index" %} + +{% include "footer" %} diff --git a/docs/.doxybook/templates/kind_class.tmpl b/docs/.doxybook/templates/kind_class.tmpl new file mode 100644 index 0000000..bd5fdef --- /dev/null +++ b/docs/.doxybook/templates/kind_class.tmpl @@ -0,0 +1,34 @@ +{% include "header" -%} + +{% include "breadcrumbs" %} + +```cpp +{% if exists("templateParams") -%} +template <{% for param in templateParams %} + {{param.typePlain}} {{param.name}}{% if existsIn(param, "defvalPlain") %} ={{param.defvalPlain}}{% endif -%} +{% if not loop.is_last %},{% endif -%} +{% endfor %} +> {% endif -%} +{% if kind == "interface" %}class{% else %}{{kind}}{% endif %} {{ stripNamespace(name) }}; +``` + +{%- include "details" -%} + +{%- if exists("baseClasses") %}Inherits from {% for child in baseClasses %}{% if existsIn(child, "url") %}[{{stripNamespace(child.name)}}]({{child.url}}){% else %}`{{child.name}}`{% endif %}{% if not loop.is_last %}, {% endif %}{% endfor %} + +{% endif -%} + +{%- if exists("derivedClasses") %}Inherited by {% for child in derivedClasses %}{% if existsIn(child, "url") %}[{{stripNamespace(child.name)}}]({{child.url}}){% else %}{{child.name}}{% endif %}{% if not loop.is_last %}, {% endif %}{% endfor %} + +{% endif -%} + +{%- include "class_members_tables" -%} + +{% if hasAdditionalMembers %}## Additional inherited members + +{% include "class_members_inherited_tables" %} +{% endif -%} + +{% include "class_members_details" -%} + +{% include "footer" %} \ No newline at end of file diff --git a/docs/.doxybook/templates/kind_example.tmpl b/docs/.doxybook/templates/kind_example.tmpl new file mode 100644 index 0000000..1ce6706 --- /dev/null +++ b/docs/.doxybook/templates/kind_example.tmpl @@ -0,0 +1,5 @@ +{% include "header" %} + +{% if exists("details") %}{{details}}{% endif %} + +{% include "footer" %} diff --git a/docs/.doxybook/templates/kind_file.tmpl b/docs/.doxybook/templates/kind_file.tmpl new file mode 100644 index 0000000..3b83bb7 --- /dev/null +++ b/docs/.doxybook/templates/kind_file.tmpl @@ -0,0 +1,20 @@ +{% include "header" -%} + +{% if exists("brief") %}{{brief}}{% endif %}{% if hasDetails %} [More...](#detailed-description){% endif %} + +{% include "nonclass_members_tables" -%} + +{% if hasDetails %}## Detailed Description + +{% include "details" %}{% endif -%} + +{% include "nonclass_members_details" -%} + +{% if exists("programlisting")%}## Source code + +```{{language}} +{{programlisting}} +``` +{% endif %} + +{% include "footer" %} diff --git a/docs/.doxybook/templates/kind_group.tmpl b/docs/.doxybook/templates/kind_group.tmpl new file mode 100644 index 0000000..c90b16b --- /dev/null +++ b/docs/.doxybook/templates/kind_group.tmpl @@ -0,0 +1,15 @@ +{% include "header" -%} + +{% include "breadcrumbs" -%} + +{% if exists("brief") %}{{brief}}{% endif %}{% if hasDetails %} [More...](#detailed-description){% endif %} + +{% include "nonclass_members_tables" -%} + +{% if hasDetails %}## Detailed Description + +{% include "details" %}{% endif -%} + +{% include "nonclass_members_details" -%} + +{% include "footer" -%} diff --git a/docs/.doxybook/templates/kind_nonclass.tmpl b/docs/.doxybook/templates/kind_nonclass.tmpl new file mode 100644 index 0000000..1bd64f9 --- /dev/null +++ b/docs/.doxybook/templates/kind_nonclass.tmpl @@ -0,0 +1,18 @@ +{% include "header" -%} + +{% if exists("brief") %}> {{brief}} + +{% endif %} + +{% if exists("details") %} +{{details}} + +{% endif -%} + +{% include "breadcrumbs" -%} + +{% include "nonclass_members_tables" -%} + +{% include "nonclass_members_details" %} + +{% include "footer" %} \ No newline at end of file diff --git a/docs/.doxybook/templates/kind_page.tmpl b/docs/.doxybook/templates/kind_page.tmpl new file mode 100644 index 0000000..1ce6706 --- /dev/null +++ b/docs/.doxybook/templates/kind_page.tmpl @@ -0,0 +1,5 @@ +{% include "header" %} + +{% if exists("details") %}{{details}}{% endif %} + +{% include "footer" %} diff --git a/docs/.doxybook/templates/member_details.tmpl b/docs/.doxybook/templates/member_details.tmpl new file mode 100644 index 0000000..f24848a --- /dev/null +++ b/docs/.doxybook/templates/member_details.tmpl @@ -0,0 +1,91 @@ +{# RENDER HEADERS #} +{% if exists("location") and not exists("hide_location")-%} +Defined in header [`<{{ location.file }}>`](https://github.com/alandefreitas/small/blob/master/include/{{ location.file }}) +{% endif -%} + +{% if kind in ["function", "slot", "signal", "event"] -%} + +```{% if exists(language) %}{{language}}{% else %}cpp{% endif %} +{% if exists("templateParams") -%} +template <{% for param in templateParams %}{{param.typePlain}} {{param.name}}{% if existsIn(param, "defvalPlain") %} ={{param.defvalPlain}}{% endif -%} +{% if not loop.is_last -%},{%- endif %}{% endfor %}> +{% endif -%} + +{% if static %}static {% endif -%} +{% if inline and language != "csharp" %}inline {% endif -%} +{% if explicit %}explicit {% endif -%} +{% if virtual %}virtual {% endif -%} + +{% if exists("typePlain") %}{{typePlain}} {% endif %}{{name}}{% if length(params) > 0 -%} +({% for param in params %}{{param.typePlain}} {{param.name}}{% if existsIn(param, "defvalPlain") %} ={{param.defvalPlain}}{% endif -%} +{% if not loop.is_last %},{% endif %}{% endfor -%}){% else -%}(){% endif -%} + +{% if const %} const{% endif -%} +{% if override %} override{% endif -%} +{% if default %} =default{% endif -%} +{% if deleted %} =delete{% endif -%} +{% if pureVirtual %} =0{% endif %}; +```{% endif -%} {# kind in ["function", "slot", "signal", "event"] -#} + +{% if kind == "enum" -%} +```{% if exists(language) %}{{language}}{% else %}cpp{% endif %} +{% if static %}static {% endif %}{% if const %}const {% endif %}enum {% if strong %}class {% endif %}{{ name }}; +``` + +| Enumerator | Value | Description | +| ---------- | ----- | ----------- | +{% for enumvalue in enumvalues %}| `{{enumvalue.name}}` | {% if existsIn(enumvalue, "initializer") -%} +`{{replace(enumvalue.initializer, "= ", "")}}`{% endif -%} +| {% if existsIn(enumvalue, "brief") %}{{enumvalue.brief}}{% endif %} {% if existsIn(enumvalue, "details") %}{{enumvalue.details}}{% endif %} | +{% endfor %} +{% endif -%} + +{% if kind in ["variable", "property"] -%} +```{% if exists(language) %}{{language}}{% else %}cpp{% endif %} +{% if static %}static {% endif -%} +{% if exists("typePlain") %}{{typePlain}} {% endif -%}{{name}}{% if exists("initializer") %} {{initializer}}{% endif %}; +```{% endif -%} + +{% if kind == "typedef" -%} +```{% if exists(language) %}{{language}}{% else %}cpp{% endif %} +{{definition}}; +```{% endif -%} + +{% if kind == "using" -%} +```{% if exists(language) %}{{language}}{% else %}cpp{% endif %} +{% if exists("templateParams") -%} +template <{% for param in templateParams %}{{param.typePlain}}{% if param.name != "" %} {{param.name}}{% endif %}{% if existsIn(param, "defvalPlain") %} ={{param.defvalPlain}}{% endif -%} +{% if not loop.is_last %}, +{% endif %}{% endfor %}> +{% endif -%} +using {{ name }} = {{ typePlain }}; +```{% endif -%} + +{% if kind == "friend" -%} +```{% if exists(language) %}{{language}}{% else %}cpp{% endif %} +friend {% if exists("typePlain") %}{{typePlain}} {% endif -%} +{{name}}{% if exists("params") %}{% endif -%} +{% if length(params) > 0 -%} +( +{% for param in params %} {{param.typePlain}} {{param.name}}{% if existsIn(param, "defvalPlain") %} ={{param.defvalPlain}}{% endif -%} +{% if not loop.is_last %}, +{% endif %} +{% endfor -%} +){% else if typePlain != "class" -%} +(){% endif %}; +```{% endif -%} + +{% if kind == "define" -%} +```{% if exists(language) %}{{language}}{% else %}cpp{% endif %} +#define {{name}}{% if exists("params") -%} +( +{% for param in params %} {{param.name}}{% if existsIn(param, "defvalPlain") %} ={{param.defvalPlain}}{% endif -%} +{% if not loop.is_last %}, +{% endif -%} +{% endfor %} +) +{% else %} {% endif -%} +{% if exists("initializer") %}{{initializer}}{% endif %} +```{% endif %} + +{% include "details" -%} \ No newline at end of file diff --git a/docs/.doxybook/templates/merged_overload_details.tmpl b/docs/.doxybook/templates/merged_overload_details.tmpl new file mode 100644 index 0000000..e927ebb --- /dev/null +++ b/docs/.doxybook/templates/merged_overload_details.tmpl @@ -0,0 +1,399 @@ +{% if child.kind in ["function", "slot", "signal", "event"] -%} + +{# COUNT OVERLOADS #} +{% set n_overloads = 0 -%} +{% set n_brief = 0 -%} +{% set all_of_briefs_equal = true -%} +{% set first_brief = "" -%} +{% set n_details = 0 -%} +{% set n_template_params = 0 -%} +{% set n_params = 0 -%} +{% set n_headers = 0 -%} +{% set n_see_also = 0 -%} +{% set n_returns = 0 -%} +{% set all_of_notes_equal = true -%} +{% set first_returns_list = [] -%} +{% set n_notes = 0 -%} +{% set all_of_returns_equal = true -%} +{% set first_notes_list = [] -%} +{% for overload_candidate in overload_candidates -%} +{% if overload_candidate.name==child.name and overload_candidate.kind==child.kind -%} +{% set n_overloads = n_overloads + 1 -%} +{% if existsIn(overload_candidate, "brief") -%} +{% if n_brief == 0 -%} +{% set first_brief = overload_candidate.brief -%} +{% else if first_brief != overload_candidate.brief -%} +{% set all_of_briefs_equal = false -%} +{% endif -%} +{% set n_brief = n_brief + 1 -%} +{% endif -%} +{% if existsIn(overload_candidate, "details") -%} +{% if overload_candidate.details != "" -%} +{% set n_details = n_details + 1 -%} +{% endif -%} +{% endif -%} +{% if existsIn(overload_candidate, "see") -%} +{% set n_see_also = n_see_also + 1 -%} +{% endif -%} +{% if existsIn(overload_candidate, "paramList") -%} +{% set n_params = n_params + 1 -%} +{% endif -%} +{% if existsIn(overload_candidate, "templateParamsList") -%} +{% set n_template_params = n_template_params + 1 -%} +{% endif -%} +{% if existsIn(overload_candidate, "location") -%} +{% set n_headers = n_headers + 1 -%} +{% endif -%} +{% if existsIn(overload_candidate, "returns") -%} +{% if n_returns == 0 -%} +{% set first_returns_list = overload_candidate.returns -%} +{% else if first_returns_list != overload_candidate.returns %} +{% set all_of_returns_equal = false -%} +{% endif -%} +{% set n_returns = n_returns + 1 -%} +{% endif -%} +{% if existsIn(overload_candidate, "note") -%} +{% if n_notes == 0 -%} +{% set first_notes_list = overload_candidate.note -%} +{% else if first_notes_list != overload_candidate.note %} +{% set all_of_notes_equal = false -%} +{% endif -%} +{% set n_notes = n_notes + 1 -%} +{% endif -%} +{% endif -%} +{% endfor %} + +{# RENDER HEADERS #} +{% if n_headers>0 -%} +Defined in header {% set overload_counter = 1 -%} +{% set n_headers_rendered = 0 -%} +{% set last_header_rendered.name = "" -%} +{% for overload_candidate in overload_candidates -%} +{% if overload_candidate.name==child.name and overload_candidate.kind==child.kind -%} +{% set overload = overload_candidate -%} +{% if existsIn(overload, "location") -%} + +{# Check blacklist huge workaround: inja does not support manipulating lists so we implement a linked list -#} +{% set current_header_is_blacklisted = false -%} +{% if n_headers_rendered > 0 -%} +{% set current_header_rendered = last_header_rendered -%} +{% for i in range(n_headers_rendered) -%} +{% if current_header_rendered.name == overload.location.file -%} +{% set current_header_is_blacklisted = true -%} +{% endif -%} {# current_header_rendered.name == overload.location.file -#} +{% if existsIn(current_header_rendered, "next") -%} +{% set current_header_rendered = current_header_rendered.next -%} +{% endif -%} +{% endfor -%} {# range(n_headers_rendered) -#} +{% endif -%} {# n_headers_rendered > 0 -#} +{#- Render if not blacklisted and update -#} +{%- if not current_header_is_blacklisted -%}[`<{{ overload.location.file }}>`](https://github.com/alandefreitas/small/blob/master/include/{{ overload.location.file }}){%- if n_headers_rendered > 0 -%} +{% set last_header_rendered.next = last_header_rendered -%} {% endif -%} +{% set last_header_rendered.name = overload.location.file -%} +{% set n_headers_rendered = n_headers_rendered + 1 -%} +{% endif -%} {# not current_header_is_blacklisted -#} +{% endif -%} {# existsIn(overload, "location") -#} +{% set overload_counter = overload_counter + 1 -%} +{% endif -%} {# overload_candidate.name==child.name -#} +{% endfor -%} {# overload_candidates -#} +{% endif -%} {# n_headers>1 -#} + +{# RENDER DECLARATIONS #} +{% set overload_counter = 1 %} +{% for overload_candidate in overload_candidates -%} +{% if overload_candidate.name==child.name and overload_candidate.kind==child.kind -%} +{% set overload = overload_candidate %} + + +```{% if exists(overload.language) %}{{overload.language}}{% else %}cpp{% endif %} {% if n_overloads > 1 %} title="({{ overload_counter }})" {% endif %} +{# Render template paramaters -#} +{% if existsIn(overload, "templateParams") -%} +template <{% for param in overload.templateParams %}{{param.typePlain}}{{param.name}}{% if existsIn(param, "defvalPlain") %} ={{param.defvalPlain}}{% endif -%} +{% if not loop.is_last -%},{%- endif %}{% endfor %}> +{% endif -%} + +{# Render prefix -#} +{% if overload.static %}static {% endif -%} +{# {% if overload.inline and overload.language != "csharp" %}inline {% endif -%} -#} +{% if overload.explicit %}explicit {% endif -%} +{% if overload.virtual %}virtual {% endif -%} + +{# Render return type -#} +{% if existsIn(overload, "typePlain") -%} +{%- if overload.typePlain in ["__implementation_defined__", "auto", "decltype(auto)"] -%} +/* see below */{% else if overload.typePlain == "decltype(auto) constexpr" -%} +constexpr /* see below */{% else -%} +{{- overload.typePlain -}} +{%- endif %} {% endif %} +{# Render function name -#} +{{overload.name}}{% if length(overload.params) > 0 -%} +({% for param in overload.params %}{{param.typePlain}} {{param.name}}{% if existsIn(param, "defvalPlain") %} ={{param.defvalPlain}}{% endif -%} +{% if not loop.is_last %}, {% endif %}{% endfor -%}){% else -%}(){% endif -%} + +{# Render suffix -#} +{% if overload.const %} const{% endif -%} +{% if overload.override %} override{% endif -%} +{% if overload.default %} = default{% endif -%} +{% if overload.deleted %} = delete{% endif -%} +{% if overload.pureVirtual %} =0{% endif %}; +``` + +{% set overload_counter = overload_counter + 1 %} +{% endif -%} +{% endfor %} + +{# RENDER BRIEF #} +{% if all_of_briefs_equal -%} +{{ first_brief }} +{% else %} +{% set overload_counter = 1 %} +{% for overload_candidate in overload_candidates -%} +{% if overload_candidate.name==child.name and overload_candidate.kind==child.kind -%} +{% set overload = overload_candidate -%} +{% if n_overloads > 1 %}{{ overload_counter }}.{% endif -%} +{% if existsIn(overload, "brief") -%} +{{ overload.brief }} +{% else -%} +{{ overload.name }} ({{overload_counter}}) +{%- endif -%} +{% set overload_counter = overload_counter + 1 %} +{% endif -%} +{% endfor %} +{% endif -%} {# all_of_briefs_equal #} + +{# RENDER TEMPLATE PARAMETERS #} +{% if n_template_params>0 -%} +**Template Parameters** +{% set overload_counter = 1 %} +{% set n_template_params_rendered = 0 %} +{% set last_param_rendered.name = "" -%} +{% set last_param_rendered.text = "" -%} +{% for overload_candidate in overload_candidates -%} +{% if overload_candidate.name==child.name and overload_candidate.kind==child.kind -%} +{% set overload = overload_candidate -%} +{% if existsIn(overload, "templateParamsList") -%} +{% for param in overload.templateParamsList -%} + +{# Check blacklist huge workaround: inja does not support manipulating lists so we implement a linked list -#} +{% set current_param_is_blacklisted = false -%} +{% if n_template_params_rendered > 0 -%} +{% set current_param_rendered = last_param_rendered -%} +{% for i in range(n_template_params_rendered) -%} +{% if current_param_rendered.name == param.name -%} +{% set current_param_is_blacklisted = true -%} +{% endif -%} {# current_param_rendered.name == param.name -#} +{% if existsIn(current_param_rendered, "next") -%} +{% set current_param_rendered = current_param_rendered.next -%} +{% endif -%} +{% endfor -%} {# range(n_template_params_rendered) -#} +{% endif -%} {# n_template_params_rendered > 0 -#} + +{# Render if not blacklisted and update -#} +{% if not current_param_is_blacklisted -%} +- **{{ param.name }}** - {{ param.text }} +{% if n_template_params_rendered > 0 -%} +{% set last_param_rendered.next = last_param_rendered -%} +{% endif -%} +{% set last_param_rendered.name = param.name -%} +{% set n_template_params_rendered = n_template_params_rendered + 1 -%} +{% endif -%} {# not current_param_is_blacklisted -#} +{% endfor -%} {# overload.templateParamsList -#} +{% endif -%} {# existsIn(overload, "templateParamsList") -#} + +{% set overload_counter = overload_counter + 1 %} +{% endif -%} {# overload_candidate.name==child.name -#} +{% endfor %} {# overload_candidates -#} +{% endif -%} {# n_template_params>1 -#} + +{# RENDER PARAMETERS #} +{% if n_params>0 -%} +**Parameters** +{% set overload_counter = 1 %} +{% set n_params_rendered = 0 %} +{% set last_param_rendered.name = "" -%} +{% set last_param_rendered.text = "" -%} +{% for overload_candidate in overload_candidates -%} +{% if overload_candidate.name==child.name and overload_candidate.kind==child.kind -%} +{% set overload = overload_candidate -%} +{% if existsIn(overload, "paramList") -%} +{% for param in overload.paramList -%} + +{# Check blacklist huge workaround: inja does not support manipulating lists so we implement a linked list -#} +{% set current_param_is_blacklisted = false -%} +{% if n_params_rendered > 0 -%} +{% set current_param_rendered = last_param_rendered -%} +{% for i in range(n_params_rendered) -%} +{% if current_param_rendered.name == param.name -%} +{% set current_param_is_blacklisted = true -%} +{% endif -%} {# current_param_rendered.name == param.name -#} +{% if existsIn(current_param_rendered, "next") -%} +{% set current_param_rendered = current_param_rendered.next -%} +{% endif -%} +{% endfor -%} {# range(n_params_rendered) -#} +{% endif -%} {# n_params_rendered > 0 -#} + +{# Render if not blacklisted and update -#} +{% if not current_param_is_blacklisted -%} +- **{{ param.name }}** - {{ param.text }} +{% if n_params_rendered > 0 -%} +{% set last_param_rendered.next = last_param_rendered -%} +{% endif -%} +{% set last_param_rendered.name = param.name -%} +{% set last_param_rendered.text = param.text -%} +{% set n_params_rendered = n_params_rendered + 1 -%} +{% endif -%} {# not current_param_is_blacklisted -#} +{% endfor -%} {# overload.paramList -#} +{% endif -%} {# existsIn(overload, "paramList") -#} + +{% set overload_counter = overload_counter + 1 %} +{% endif -%} {# overload_candidate.name==child.name -#} +{% endfor %} {# overload_candidates -#} +{% endif -%} {# n_params>1 -#} + +{# RENDER RETURN #} +{% if n_returns>0 -%} +**Return value** + +{% if all_of_notes_equal -%} +{% if length(first_returns_list) == 1 %} +{{ first(first_returns_list) }} +{% else %} +{% for return in first_returns_list -%} +{{ loop.index + 1 }}) {{ return }} + +{% endfor -%} +{% endif %} +{% else -%} +{% set overload_counter = 1 %} +{% for overload_candidate in overload_candidates -%} +{% if overload_candidate.name==child.name and overload_candidate.kind==child.kind -%} +{% set overload = overload_candidate -%} +{% if existsIn(overload, "returns") -%} +{% if length(overload.returns) == 1 -%} +{% for return in overload.returns -%} +{{ overload_counter }}. {{ return }} +{% endfor -%} +{% else -%} +- ({{ overload_counter }}) +{%- for return in overload.returns %} - {{ return }} {% endfor -%} +{% endif -%} {# length(overload.returns) == 1 -#} +{% endif -%} +{% set overload_counter = overload_counter + 1 -%} +{% endif -%} +{% endfor %} +{% endif -%} +{% endif -%} + + +{# RENDER DETAILS #} +{% if n_details > 0 -%} +**Description** +{% set overload_counter = 1 %} +{% for overload_candidate in overload_candidates -%} +{% if overload_candidate.name==child.name and overload_candidate.kind==child.kind -%} +{% set overload = overload_candidate %} +{%- if existsIn(overload, "details") -%} +{% if n_details > 1 -%} +({{ overload_counter }}) +{% endif %} {# n_details > 1 -#} +{{ overload.details -}} +{% endif -%} +{% set overload_counter = overload_counter + 1 %} +{% endif -%} +{% endfor %} +{% endif -%} {# n_details > 0 #} + +{# RENDER NOTES #} +{% if n_notes>0 -%} +**Notes** + +{% if all_of_notes_equal -%} +{% if length(first_notes_list) == 1 %} +{{ first(first_notes_list) }} +{% else %} +{% for note in first_notes_list -%} +{{ loop.index + 1 }}) {{ note }} + +{% endfor -%} +{% endif %} +{% else -%} +{% set overload_counter = 1 %} +{% for overload_candidate in overload_candidates -%} +{% if overload_candidate.name==child.name and overload_candidate.kind==child.kind -%} +{% set overload = overload_candidate -%} +{% if existsIn(overload, "note") -%} +{% if length(overload.note) == 1 -%} +{% for note in overload.note -%} +{{ overload_counter }}. {{ note }} +{% endfor -%} +{% else -%} +- ({{ overload_counter }}) +{%- for note in overload.note %} - {{ note }} {% endfor -%} +{% endif -%} {# length(overload.note) == 1 -#} +{% endif -%} +{% set overload_counter = overload_counter + 1 -%} +{% endif -%} +{% endfor %} +{% endif -%} +{% endif -%} + + +{# RENDER PARAGRAPHS #} +{% set overload_counter = 1 %} +{% for overload_candidate in overload_candidates -%} +{% if overload_candidate.name==child.name and overload_candidate.kind==child.kind -%} +{% set overload = overload_candidate %} +{%- if existsIn(overload, "par") -%} +{%- for p in overload.par -%} +> {{ p }} +{%- endfor -%} +{%- endif -%} {# existsIn(overload, "par") -#} +{% set overload_counter = overload_counter + 1 %} +{% endif -%} {# overload_candidate.name==child.name #} +{% endfor %} {# overload_candidates #} + +{# RENDER SEE ALSO #} +{% if n_see_also>0 -%} +**See also** +{% set overload_counter = 1 %} +{% set n_see_also_rendered = 0 %} +{% set last_see_rendered.link = "" -%} +{% for overload_candidate in overload_candidates -%} +{% if overload_candidate.name==child.name and overload_candidate.kind==child.kind -%} +{% set overload = overload_candidate -%} +{% if existsIn(overload, "see") -%} +{% for see in overload.see -%} + +{# Check blacklist huge workaround: inja does not support manipulating lists so we implement a linked list -#} +{% set current_see_is_blacklisted = false -%} +{% if n_see_also_rendered > 0 -%} +{% set current_see_rendered = last_see_rendered -%} +{% for i in range(n_see_also_rendered) -%} +{% if current_see_rendered.link == see -%} +{% set current_see_is_blacklisted = true -%} +{% endif -%} {# current_see_rendered.link == see.link -#} +{% if existsIn(current_see_rendered, "next") -%} +{% set current_see_rendered = current_see_rendered.next -%} +{% endif -%} +{% endfor -%} {# range(n_see_also_rendered) -#} +{% endif -%} {# n_see_also_rendered > 0 -#} + +{# Render if not blacklisted and update -#} +{% if not current_see_is_blacklisted -%} +- {{ see }} +{% if n_see_also_rendered > 0 -%} +{% set last_see_rendered.next = last_see_rendered -%} +{% endif -%} +{% set last_see_rendered.link = see -%} +{% set n_see_also_rendered = n_see_also_rendered + 1 -%} +{% endif -%} {# not current_see_is_blacklisted -#} +{% endfor -%} {# overload.see -#} +{% endif -%} {# existsIn(overload, "see") -#} +{% set overload_counter = overload_counter + 1 %} +{% endif -%} {# overload_candidate.link==child.link -#} +{% endfor %} {# overload_candidates -#} +{% endif -%} {# n_see_also>1 -#} + + + +{% endif %} diff --git a/docs/.doxybook/templates/meta.tmpl b/docs/.doxybook/templates/meta.tmpl new file mode 100644 index 0000000..e69de29 diff --git a/docs/.doxybook/templates/nonclass_members_details.tmpl b/docs/.doxybook/templates/nonclass_members_details.tmpl new file mode 100644 index 0000000..88bffdb --- /dev/null +++ b/docs/.doxybook/templates/nonclass_members_details.tmpl @@ -0,0 +1,35 @@ +{% if exists("publicTypes") %}## Types + +{% for child in publicTypes %}### {{child.kind}} {{child.name}} + +{{ render("member_details", child) }} +{% endfor %}{% endif %} + +{% if exists("publicFunctions") %}## Functions + +{%- set previous_overload="" -%} +{% for child in publicFunctions -%} +{% if previous_overload!=child.name -%} + +{{ "###" }} {{child.kind}} {{child.name}} + +{% set input.child = child -%} +{% set input.overload_candidates = publicFunctions -%} + +{{ render("merged_overload_details", input) }} +{%- set previous_overload=child.name -%} +{% endif -%} +{% endfor %}{% endif %} + +{% if exists("publicAttributes") %}## Attributes + +{% for child in publicAttributes %}### {{child.kind}} {{child.name}} + +{{ render("member_details", child) }} +{% endfor %}{% endif %} +{% if exists("defines") %}## Macros + +{% for child in defines %}### {{child.kind}} {{child.name}} + +{{ render("member_details", child) }} +{% endfor %}{% endif %} \ No newline at end of file diff --git a/docs/.doxybook/templates/nonclass_members_tables.tmpl b/docs/.doxybook/templates/nonclass_members_tables.tmpl new file mode 100644 index 0000000..a336ff2 --- /dev/null +++ b/docs/.doxybook/templates/nonclass_members_tables.tmpl @@ -0,0 +1,133 @@ +{% if exists("groups") %} + +| Submodules | | +| -------------- | --------- | +{% for child in groups -%} +| **[{{child.title}}]({{child.url}})** | {% if existsIn(child, "brief") %}{{child.brief}}{% else %}{{child.title}} submodule{% endif %}
(submodule) | +{%- endfor %} +{% endif -%} + +{% if exists("dirs") %} + +| Directories | +| -------------- | +{% for child in dirs -%} +| **[{{child.title}}]({{child.url}})** {% if existsIn(child, "brief") %}
{{child.brief}}{% endif %} | +{%- endfor %} +{% endif -%} + +{% if exists("files") %} + +| Files | +| -------------- | +{% for child in files -%} +| **[{{child.title}}]({{child.url}})** {% if existsIn(child, "brief") %}
{{child.brief}}{% endif %} | +{%- endfor %} +{% endif -%} + +{%- if exists("namespaces") %} + +| Namespaces | +| -------------- | +{% for child in namespaces -%} +| **[{{child.name}}]({{child.url}})** {% if existsIn(child, "brief") %}
{{child.brief}}{% endif %} | +{% endfor %} +{% endif -%} +{%- if exists("publicClasses") %} + +| Classes | | +| -------------- |-----| +{% for child in publicClasses -%} +| **[{{ stripNamespace(child.name) }}]({{child.url}})** | {% if existsIn(child, "brief") %}{{child.brief}}{% else %}{{child.name}}{% endif %}
({{child.kind}}) | +{% endfor %} +{% endif -%} +{%- if exists("publicTypes") %} + +| Types | | +| -------------- |-----------| +{% for child in publicTypes -%} +| **[{{ stripNamespace(child.name) }}]({{child.url}})** | {% if existsIn(child, "brief") %}{{child.brief}}{% else if existsIn(child, "type") %}{% if child.type == "__see_below__" %}`/* see below */`{% else %}`{{child.type}}`{% endif %}{% else %}`{{child.name}}`{% endif %}
({{child.kind}}) | +{% endfor %} +{% endif -%} +{%- if exists("publicSlots") %} + +| Slots | | +| -------------- |---------| +{% for child in publicSlots -%} +| {% if existsIn(child, "templateParams") -%} +template <{% for param in child.templateParams -%} +{{param.typePlain}} {{param.name}}{% if existsIn(param, "defvalPlain") %} ={{param.defvalPlain}}{% endif -%} +{% if not loop.is_last %},{% endif -%} +{% endfor %}\>
{% endif -%} +{% if child.virtual %}virtual {% endif -%} +{% if existsIn(child, "type") %}{{child.type}} {% endif -%} +| **[{{child.name}}]({{child.url}})**({% for param in child.params -%} +{{param.type}} {{param.name}}{% if existsIn(param, "defval") %} ={{param.defval}}{% endif -%} +{% if not loop.is_last %}, {% endif -%} +{% endfor %}){% if child.const %} const{% endif -%} +{% if child.override %} override{% endif -%} +{% if child.default %} =default{% endif -%} +{% if child.deleted %} =delete{% endif -%} +{% if child.pureVirtual %} =0{% endif -%} + {% if existsIn(child, "brief") %}
{{child.brief}}{% endif %} | +{% endfor %} +{% endif -%} +{%- if exists("publicSignals") %} + +| Signals | | +| -------------- |----------| +{% for child in publicSignals -%} +| {% if existsIn(child, "templateParams") -%} +template <{% for param in child.templateParams -%} +{{param.typePlain}} {{param.name}}{% if existsIn(param, "defvalPlain") %} ={{param.defvalPlain}}{% endif -%} +{% if not loop.is_last %},{% endif -%} +{% endfor %}\>
{% endif -%} +{% if child.virtual %}virtual {% endif -%} +{% if existsIn(child, "type") %}{{child.type}} {% endif -%} +| **[{{child.name}}]({{child.url}})**({% for param in child.params -%} +{{param.type}} {{param.name}}{% if existsIn(param, "defval") %} ={{param.defval}}{% endif -%} +{% if not loop.is_last %}, {% endif -%} +{% endfor %}){% if child.const %} const{% endif -%} +{% if child.override %} override{% endif -%} +{% if child.default %} =default{% endif -%} +{% if child.deleted %} =delete{% endif -%} +{% if child.pureVirtual %} =0{% endif -%} + {% if existsIn(child, "brief") %}
{{child.brief}}{% endif %} | +{% endfor %} +{% endif -%} +{%- if exists("publicFunctions") %} + +| Functions | | +|-----------|--------------| +{%- set previous_overload="" -%} +{% for child in publicFunctions -%} +{% if previous_overload!=child.name -%} +| **[{{replace(child.name, "|","\\|")}}]({{replace(child.url, "|", "_1")}})** {% if child.override %} override{% endif -%} +{% if child.default %} =default{% endif -%} +{% if child.deleted %} =delete{% endif -%} +{% if child.pureVirtual %} =0{% endif -%} +{% if child.const %} const{% endif -%} + | {% if existsIn(child, "brief") %}{{replace(child.brief, "|", "\\|")}}
{% endif %} ({% if child.virtual %}virtual {% endif -%}{{child.kind}}{% if existsIn(child, "templateParams") %} template{% endif %}) | +{%- set previous_overload=child.name -%} +{% endif -%} +{% endfor %} + +{% endif -%} + +{%- if exists("publicAttributes") %} + +| Attributes | | +| -------------- | -------------- | +{% for child in publicAttributes -%} +| **[{{ stripNamespace(child.name) }}]({{child.url}})** | {% if existsIn(child, "brief") %}{{child.brief}}{% else if existsIn(child, "type") %}{% if child.type == "__see_below__" %}`/* see below */`{% else %}`{{child.type}}`{% endif %}{% else %}`{{child.name}}`{% endif %}
({{child.kind}}) | +{% endfor %} +{% endif -%} + +{%- if exists("defines") %} + +| Defines | | +| -------------- | -------------- | +{% for child in defines -%} +| {% if existsIn(child, "type") %}{{child.type}}{% endif %} | **[{{child.name}}]({{child.url}})**{% if existsIn(child, "params") %}({% for param in child.params %}{{param.name}}{% if existsIn(param, "defval") %} ={{param.defval}}{% endif %}{% if not loop.is_last %}, {% endif %}{% endfor %}){% endif %} {% if existsIn(child, "brief") %}
{{child.brief}}{% endif %} | +{% endfor %} +{% endif -%} diff --git a/docs/.gitignore b/docs/.gitignore new file mode 100644 index 0000000..37166c9 --- /dev/null +++ b/docs/.gitignore @@ -0,0 +1,3 @@ +xml +reference +__pycache__ \ No newline at end of file diff --git a/docs/CMakeLists.txt b/docs/CMakeLists.txt new file mode 100644 index 0000000..36eff1c --- /dev/null +++ b/docs/CMakeLists.txt @@ -0,0 +1,114 @@ +# +# Copyright (c) 2022 alandefreitas (alandefreitas@gmail.com) +# +# Distributed under the Boost Software License, Version 1.0. +# https://www.boost.org/LICENSE_1_0.txt +# + +####################################################### +### Dependencies ### +####################################################### +find_program(DOXYGEN_EXECUTABLE doxygen) +if (DOXYGEN_EXECUTABLE) + message(STATUS "doxygen found: ${DOXYGEN_EXECUTABLE}") +else () + message(FATAL_ERROR "doxygen executable not found (https://www.doxygen.nl/index.html)") +endif() + +find_program(DOXYBOOK2_EXECUTABLE doxybook2) +if (DOXYBOOK2_EXECUTABLE) + message(STATUS "doxybook2 found: ${DOXYBOOK2_EXECUTABLE}") +else () + message(STATUS "doxybook2 executable not found (https://github.com/matusnovak/doxybook2)") +endif() + +if (NOT DOXYBOOK2_EXECUTABLE) + include(FetchContent) + if (APPLE) + set(DOXYBOOK_SYSTEM_FILE osx-amd64) + elseif (UNIX) + set(DOXYBOOK_SYSTEM_FILE linux-amd64) + elseif (WIN32) + set(DOXYBOOK_SYSTEM_FILE windows-win64) + endif () + FetchContent_Declare( + doxybook2 + URL "https://github.com/matusnovak/doxybook2/releases/download/v1.4.0/doxybook2-${DOXYBOOK_SYSTEM_FILE}-v1.4.0.zip" + SOURCE_DIR "${PROJECT_BINARY_DIR}/doxybook2" + UPDATE_DISCONNECTED YES + ) + FetchContent_GetProperties(doxybook2) + if (NOT doxybook2_POPULATED) + FetchContent_Populate(doxybook2) + find_program(DOXYBOOK2_EXECUTABLE doxybook2 PATHS "${doxybook2_SOURCE_DIR}/bin") + if (DOXYBOOK2_EXECUTABLE) + message(STATUS "doxybook2 downloaded: ${DOXYBOOK2_EXECUTABLE}") + else () + message(WARNING "doxybook2 executable not found (https://github.com/matusnovak/doxybook2)") + endif() + endif() +endif () + +find_program(MKDOCS_EXECUTABLE mkdocs) +if (MKDOCS_EXECUTABLE) + message(STATUS "mkdocs found: ${MKDOCS_EXECUTABLE}") +else () + message(FATAL_ERROR "mkdocs executable not found (https://www.mkdocs.org/)") +endif() + +####################################################### +### Documentation targets ### +####################################################### +# Documentation is built in-source as required by mkdocs and github +set(DOCS_WORKING_DIR "${CMAKE_CURRENT_SOURCE_DIR}") +set(DOXYGEN_CONFIG_FILE "${CMAKE_CURRENT_SOURCE_DIR}/Doxyfile" CACHE PATH "Path for the generated Doxygen documentation") +set(DOXYGEN_OUTPUT_DIR "${CMAKE_CURRENT_SOURCE_DIR}/xml" CACHE PATH "Path for the generated Doxygen documentation") +set(DOXYBOOK2_CONFIG_FILE "${CMAKE_CURRENT_SOURCE_DIR}/.doxybook/config.json" CACHE PATH "Path for the doxybook config file") +set(DOXYBOOK2_TEMPLATES_DIR "${CMAKE_CURRENT_SOURCE_DIR}/.doxybook/templates" CACHE PATH "Path for the doxybook templates") +set(DOXYBOOK2_OUTPUT_DIR "${CMAKE_CURRENT_SOURCE_DIR}/reference" CACHE PATH "Doxybook reference directory") +set(MKDOCS_CONFIG_FILE "${PROJECT_SOURCE_DIR}/mkdocs.yml" CACHE PATH "Documentation output directory") +set(MKDOCS_OUTPUT_DIR "${PROJECT_BINARY_DIR}/docs" CACHE PATH "Documentation output directory") + +add_custom_target( + doxygen + + # Clean previous doxygen directory + COMMAND "${CMAKE_COMMAND}" -E remove_directory "${DOXYGEN_OUTPUT_DIR}" + + # Run doxygen to generate xml files + COMMAND "${DOXYGEN_EXECUTABLE}" "${DOXYGEN_CONFIG_FILE}" + + WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}" + COMMENT "Generate Doxygen files" + VERBATIM +) + +add_custom_target( + doxybook2 + + # Run doxybook2 to convert from xml to markdown + COMMAND "${DOXYBOOK2_EXECUTABLE}" + --input "${DOXYGEN_OUTPUT_DIR}" + --output "${DOXYBOOK2_OUTPUT_DIR}" + --config "${DOXYBOOK2_CONFIG_FILE}" + --templates "${DOXYBOOK2_TEMPLATES_DIR}" + + WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}" + COMMENT "Building documentation using Doxygen, Doxybook, and Mkdocs" + VERBATIM +) +add_dependencies(doxybook2 doxygen) + +add_custom_target( + docs + + # Run mkdocs + COMMAND "${MKDOCS_EXECUTABLE}" build + -f "${MKDOCS_CONFIG_FILE}" + -d "${MKDOCS_OUTPUT_DIR}" + + WORKING_DIRECTORY "${PROJECT_SOURCE_DIR}" + COMMENT "Building documentation using Doxygen, Doxybook, and Mkdocs" + VERBATIM +) +add_dependencies(docs doxybook2) \ No newline at end of file diff --git a/docs/Doxyfile b/docs/Doxyfile new file mode 100644 index 0000000..cb58477 --- /dev/null +++ b/docs/Doxyfile @@ -0,0 +1,36 @@ +PROJECT_NAME = "Small" +DOXYFILE_ENCODING = UTF-8 +OUTPUT_DIRECTORY = . +GENERATE_LATEX = NO + +GENERATE_XML = YES +XML_OUTPUT = xml + +INPUT = ./../include/small +STRIP_FROM_PATH = ./../include +RECURSIVE = YES +EXCLUDE = ./../include/small/detail +FILE_PATTERNS = *.hpp +EXCLUDE_SYMBOLS = "std" "detail" "small::detail" "detail::*" "small::detail::*" "A" "Enable" "Proxy" +EXAMPLE_PATH = ./../examples +EXAMPLE_PATTERNS = *.cpp + +DISTRIBUTE_GROUP_DOC=YES +MACRO_EXPANSION=YES +EXPAND_ONLY_PREDEF=YES +PREDEFINED= SMALL_DOXYGEN \ + SMALL_CONSTEXPR=constexpr \ + SMALL_CONSTANT_EVALUATED_CONSTEXPR=constexpr + +JAVADOC_AUTOBRIEF=YES + +INLINE_INHERITED_MEMB=YES +INHERIT_DOCS=YES +SHOW_NAMESPACES = YES +EXTRACT_ALL = YES +GENERATE_HTML = NO + +CALL_GRAPH = NO +HAVE_DOT = NO + +IMAGE_PATH = img \ No newline at end of file diff --git a/docs/contributing.md b/docs/contributing.md new file mode 100644 index 0000000..b3cc72d --- /dev/null +++ b/docs/contributing.md @@ -0,0 +1,56 @@ +# Contributing + +### Get Involved + +* Discussions are concentrated on our GitHub [discussions](https://github.com/alandefreitas/small/discussions) page. Don't refrain from asking questions and proposing ideas. If this library helps you create something interesting, please divulge it with the community. +* If you are a programmer with good ideas, please [share](https://github.com/alandefreitas/small/discussions/new) these ideas with us. +* Academic collaboration is more than welcome. It'd be great to see this library help people write papers. + +### Ideas and Roadmap + +Feel free to contribute new features to this library. For complex features and changes, consider [getting feedback](https://github.com/alandefreitas/small/discussions/new) from the community first. Contributing to an existing code base with its conventions might seem obscure at first but please don't let that discourage you from sharing your ideas. + +There are many ways in which you can contribute to this library: + +* Testing the library in new environments see [1](https://github.com/alandefreitas/small/issues?q=is%3Aopen+is%3Aissue+label%3A%22cross-platform+issue+-+windows%22), [2](https://github.com/alandefreitas/small/issues?q=is%3Aopen+is%3Aissue+label%3A%22cross-platform+issue+-+linux%22), [3](https://github.com/alandefreitas/small/issues?q=is%3Aopen+is%3Aissue+label%3A%22cross-platform+issue+-+macos%22) +* Contributing with interesting examples see [1](source/examples) +* Finding problems in this documentation see [1](https://github.com/alandefreitas/small/issues?q=is%3Aopen+is%3Aissue+label%3A%22enhancement+-+documentation%22) +* Finding bugs in general see [1](https://github.com/alandefreitas/small/issues?q=is%3Aopen+is%3Aissue+label%3A%22bug+-+compilation+error%22), [2](https://github.com/alandefreitas/small/issues?q=is%3Aopen+is%3Aissue+label%3A%22bug+-+compilation+warning%22), [3](https://github.com/alandefreitas/small/issues?q=is%3Aopen+is%3Aissue+label%3A%22bug+-+runtime+error%22), [4](https://github.com/alandefreitas/small/issues?q=is%3Aopen+is%3Aissue+label%3A%22bug+-+runtime+warning%22) +* Whatever idea seems interesting to you + +The only thing we ask you is to make sure your contribution is not destructive. Some contributions in which we are not interested are: + +* "I don't like this optional feature, so I removed/deprecated it" +* "I removed this feature to support older versions of C++" but have not provided an equivalent alternative +* "I removed this feature, so I don't have to install/update ______" but have not provided an equivalent alternative +* "I'm creating this high-cost promise that we'll support ________ forever" but I'm not sticking around to keep that promise + +In doubt, please open a [discussion](https://github.com/alandefreitas/small/discussions) first + +### Guidelines + +If contributing with code, please leave all warnings ON (`-DSMALL_BUILD_WITH_PEDANTIC_WARNINGS=ON`), use [cppcheck](http://cppcheck.sourceforge.net/), and [clang-format](https://clang.llvm.org/docs/ClangFormat.html). + +If contributing to the documentation, please edit [`README.md`](README.md) directly, as the files in [`./docs`](./docs) are automatically generated with [mdsplit](https://github.com/alandefreitas/mdsplit). + +### Contributors + + + + + + +
+ + marcosfpr +
+ Marcos Pontes +
+
+ + alandefreitas +
+ Alan De Freitas +
+
+ diff --git a/docs/index.md b/docs/index.md new file mode 100644 index 0000000..dd2d382 --- /dev/null +++ b/docs/index.md @@ -0,0 +1,35 @@ +# Small + +> C++ Small Containers + +[![Small](img/small_banner.svg)](https://alandefreitas.github.io/small/) + +
+ +- Applications usually contain many auxiliary small data structures for each large collection of values. Container implementations often include several optimizations for the case when they are small. +- These optimizations cannot usually make it to the STL because of ABI compatibility issues. Users might need to reimplement these containers or rely on frameworks that include these implementations. +- Depending on large library collections for simple containers might impose a cost on the user that's higher than necessary and hinder collaboration on the evolution of these containers. +- This library includes independent implementations of the main STL containers optimized for the case when they are small. + +
+ +[![Build Status](https://img.shields.io/github/workflow/status/alandefreitas/small/Small?event=push&label=Build&logo=Github-Actions)](https://github.com/alandefreitas/small/actions?query=workflow%3ASmall+event%3Apush) +[![Latest Release](https://img.shields.io/github/release/alandefreitas/small.svg?label=Download)](https://GitHub.com/alandefreitas/small/releases/) +[![Documentation](https://img.shields.io/website-up-down-green-red/http/alandefreitas.github.io/small.svg?label=Documentation)](https://alandefreitas.github.io/small/) +[![Discussions](https://img.shields.io/website-up-down-green-red/http/alandefreitas.github.io/small.svg?label=Discussions)](https://github.com/alandefreitas/small/discussions) + +
+ + +[![Facebook](https://img.shields.io/twitter/url/http/shields.io.svg?style=social&label=Share+on+Facebook&logo=facebook)](https://www.facebook.com/sharer/sharer.php?t=small:%20C%2B%2B%20Small%20Containers&u=https://github.com/alandefreitas/small/) +[![QZone](https://img.shields.io/twitter/url/http/shields.io.svg?style=social&label=Share+on+QZone&logo=qzone)](http://sns.qzone.qq.com/cgi-bin/qzshare/cgi_qzshare_onekey?url=https://github.com/alandefreitas/small/&title=small:%20C%2B%2B%20small%20containers&summary=small:%20C%2B%2B%20small%20containers) +[![Weibo](https://img.shields.io/twitter/url/http/shields.io.svg?style=social&label=Share+on+Weibo&logo=sina-weibo)](http://sns.qzone.qq.com/cgi-bin/qzshare/cgi_qzshare_onekey?url=https://github.com/alandefreitas/small/&title=small:%20C%2B%2B%20small%20containers&summary=small:%20C%2B%2B%20small%20containers) +[![Reddit](https://img.shields.io/twitter/url/http/shields.io.svg?style=social&label=Share+on+Reddit&logo=reddit)](http://www.reddit.com/submit?url=https://github.com/alandefreitas/small/&title=Small:%20CPP%20Small%20Containers) +[![Twitter](https://img.shields.io/twitter/url/http/shields.io.svg?label=Share+on+Twitter&style=social)](https://twitter.com/intent/tweet?text=small:%20C%2B%2B%20small%20containers&url=https://github.com/alandefreitas/small/&hashtags=Containers,Small,Cpp,Programming) +[![LinkedIn](https://img.shields.io/twitter/url/http/shields.io.svg?style=social&label=Share+on+LinkedIn&logo=linkedin)](https://www.linkedin.com/shareArticle?mini=false&url=https://github.com/alandefreitas/small/&title=small:%20C%2B%2B%20small%20containers) +[![WhatsApp](https://img.shields.io/twitter/url/http/shields.io.svg?style=social&label=Share+on+WhatsApp&logo=whatsapp)](https://api.whatsapp.com/send?text=small:%20C%2B%2B%20small%20containers:+https://github.com/alandefreitas/small/) +[![Line.me](https://img.shields.io/twitter/url/http/shields.io.svg?style=social&label=Share+on+Line.me&logo=line)](https://lineit.line.me/share/ui?url=https://github.com/alandefreitas/small/&text=small:%20C%2B%2B%20small%20containers) +[![Telegram.me](https://img.shields.io/twitter/url/http/shields.io.svg?style=social&label=Share+on+Telegram.me&logo=telegram)](https://telegram.me/share/url?url=https://github.com/alandefreitas/small/&text=small:%20C%2B%2B%20small%20containers) +[![HackerNews](https://img.shields.io/twitter/url/http/shields.io.svg?style=social&label=Share+on+HackerNews&logo=y-combinator)](https://news.ycombinator.com/submitlink?u=https://github.com/alandefreitas/small/&t=small:%20C%2B%2B%20small%20containers) + +
diff --git a/docs/javascripts/extra.js b/docs/javascripts/extra.js new file mode 100644 index 0000000..3d12424 --- /dev/null +++ b/docs/javascripts/extra.js @@ -0,0 +1,38 @@ +// When the page is loaded +document.addEventListener("DOMContentLoaded", () => { + // Make all external links open on a new tab + // - https://www.w3schools.com/css/css_attribute_selectors.asp + let external_links = Array.from(document.querySelectorAll(".md-typeset a[href^=http]")); + let repo_link = Array.from(document.querySelectorAll(".md-header__source a[href^=http]")); + for (const link of external_links.concat(repo_link)) { + link.target = "_blank" + } + + // Put around cpp reference links regardless of macros + let cpp_reference_links = Array.from(document.querySelectorAll('.md-typeset a[href*="cppreference"]')); + let open_std_links = Array.from(document.querySelectorAll('.md-typeset a[href*="open-std"]')); + let small_reference_link = Array.from(document.querySelectorAll('.md-typeset a[href*="/small/reference/"]')); + for (const link of cpp_reference_links.concat(open_std_links).concat(small_reference_link)) { + let already_inside_code_tag = link.parentElement.tagName !== undefined && link.parentElement.tagName.toUpperCase() === 'CODE' + let already_has_code_tag = link.firstChild.tagName !== undefined && link.firstChild.tagName.toUpperCase() === 'CODE' + let is_code_reference = link.innerHTML.startsWith('std::') || link.href.includes('/small/reference/') + if (already_inside_code_tag || already_has_code_tag || !is_code_reference) { + continue; + } + link.innerHTML = "" + link.innerHTML + "" + } + + // Fix bug in doxybook reference anchors + let brokenAnchors = ['#function-', '#variable-', '#using-'] + for (const anchor of brokenAnchors) { + for (const link of small_reference_link) { + anchorPos = link.href.lastIndexOf(anchor); + if (anchorPos !== -1) { + let splitPos = anchorPos + anchor.length; + let linkLhs = link.href.substr(0, splitPos); + let linkRhs = link.href.substr(splitPos); + link.href = linkLhs + linkRhs.replaceAll('-', '_'); + } + } + } +}) \ No newline at end of file diff --git a/docs/macros.py b/docs/macros.py new file mode 100644 index 0000000..2723bd1 --- /dev/null +++ b/docs/macros.py @@ -0,0 +1,76 @@ +import os + +def declare_variables(variables, macro): + @macro + def code_snippet(filename: str, snippet: str = "", language: str = "cpp"): + """ + Load code from a file and save as a preformatted code block. + If a language is specified, it's passed in as a hint for syntax highlighters. + Example usage in markdown: + {{code_from_file("code/myfile.py", "python")}} + """ + docs_dir = variables.get("docs_dir", "docs") + + # Look for file + abs_docs_path = os.path.abspath(os.path.join(docs_dir, filename)) + abs_root_path = os.path.abspath(os.path.join(docs_dir, "..", filename)) + abs_examples_path = os.path.abspath(os.path.join(docs_dir, "../examples/", filename)) + abs_path = '' + if os.path.exists(abs_docs_path): + abs_path = abs_docs_path + elif os.path.exists(abs_root_path): + abs_path = abs_root_path + elif os.path.exists(abs_examples_path): + abs_path = abs_examples_path + + # File not found + if not os.path.exists(abs_path): + return f"""File not found: {filename}""" + + # Read snippet from file + with open(abs_path, "r") as f: + if not snippet: + return ( + f"""```{language}\n{f.read()}\n```""" + ) + else: + # Extract the snippet + contents = f.read() + start_pos = contents.find('//[' + snippet) + if start_pos == -1: + return f"""Snippet {snippet} not found in {filename}""" + end_pos = contents.find('//]', start_pos) + if end_pos == -1: + return f"""Snippet {snippet} not found in {filename}""" + contents = contents[(start_pos + 3 + len(snippet)):(end_pos - 3)] + + # Identify snippet header + content_lines = contents.splitlines() + first_line = content_lines[0] + header = '' + if not first_line.isspace() and not len(first_line) == 0: + header = first_line.strip() + + # Identify indent + indent_size = 20 + for line in content_lines[1:]: + if not line.isspace() and not len(line) == 0: + first_char_pos = len(line) - len(line.lstrip()) + indent_size = min(indent_size, first_char_pos) + + # Construct snippet + contents = '' + if len(header) != 0: + contents += '=== "' + header + '"\n\n ' + contents += '```' + language + if len(content_lines) > 10: + contents += ' linenums="1" ' + contents += '\n' + for line in content_lines[1:]: + if len(header) != 0: + contents += ' ' + contents += line[indent_size:] + '\n' + if len(header) != 0: + contents += ' ' + contents += '```\n' + return contents \ No newline at end of file diff --git a/docs/quickstart.md b/docs/quickstart.md new file mode 100644 index 0000000..a9ecb98 --- /dev/null +++ b/docs/quickstart.md @@ -0,0 +1,190 @@ +# Quickstart + +Integration: + +=== "CMake" + + === "Add subdirectory" + + ```bash + git clone https://github.com/alandefreitas/small/ + ``` + + ```cmake + add_subdirectory(small) + # ... + add_executable(your_target main.cpp) + target_link_libraries(your_target PUBLIC small::small) + ``` + + === "Fetch content" + + ```cmake + include(FetchContent) + + FetchContent_Declare(small + GIT_REPOSITORY https://github.com/alandefreitas/small + GIT_TAG origin/master # or whatever tag you want + ) + + FetchContent_GetProperties(small) + if(NOT small_POPULATED) + FetchContent_Populate(small) + add_subdirectory(${small_SOURCE_DIR} ${small_BINARY_DIR} EXCLUDE_FROM_ALL) + endif() + + # ... + add_executable(your_target main.cpp) + target_link_libraries(your_target PUBLIC small::small) + ``` + + === "External package" + + ```cmake + # Follow installation instructions and then... + find_package(small REQUIRED) + if(NOT small_FOUND) + # Throw or put your FetchContent script here + endif() + + # ... + add_executable(your_target main.cpp) + target_link_libraries(your_target PUBLIC small::small) + ``` + +=== "Install" + + !!! note + + Get the binary package from the [release section](https://github.com/alandefreitas/small/releases). + + These binaries refer to the latest release version of small. + + !!! hint + + If you need a more recent version of `small`, you can download the binary packages from the CI artifacts or build the library from the source files. + +=== "Build from source" + + !!! note + + Ensure your C++ compiler and CMake are up-to-date and then: + + === "Ubuntu + GCC" + + ```bash + # Create a new directory + mkdir build + cd build + # Configure + cmake .. -DCMAKE_BUILD_TYPE=Release -DCMAKE_CXX_FLAGS="-O2" + # Build + sudo cmake --build . --parallel 2 --config Release + # Install + sudo cmake --install . + # Create packages + sudo cpack . + ``` + + === "Mac Os + Clang" + + ```bash + # Create a new directory + mkdir build + cd build + # Configure + cmake .. -DCMAKE_BUILD_TYPE=Release -DCMAKE_CXX_FLAGS="-O2" + # Build + cmake --build . --parallel 2 --config Release + # Install + cmake --install . + # Create packages + cpack . + ``` + + === "Windows + MSVC" + + ```bash + # Create a new directory + mkdir build + cd build + # Configure + cmake .. -DCMAKE_BUILD_TYPE=Release -DCMAKE_CXX_FLAGS="/O2" + # Build + cmake --build . --parallel 2 --config Release + # Install + cmake --install . + # Create packages + cpack . + ``` + + !!! hint "Parallel Build" + + Replace `--parallel 2` with `--parallel ` + + !!! note "Setting C++ Compiler" + + If your C++ compiler that supports C++17 is not your default compiler, make sure you provide CMake with the compiler location with the DCMAKE_C_COMPILER and DCMAKE_CXX_COMPILER options. For instance: + + ```bash + cmake .. -DCMAKE_BUILD_TYPE=Release -DCMAKE_CXX_FLAGS="-O2" -DCMAKE_C_COMPILER=/usr/bin/gcc-8 -DCMAKE_CXX_COMPILER=/usr/bin/g++-8 + ``` + +=== "File amalgamation" + + !!! note + + Because containers are header-only, you can directly copy the contents from the `source` directory into your project. + + !!! hint + + In that case, you are responsible for setting the appropriate target include directories and any compile definitions you might require. + + +Once the library is properly integrated, you can create containers from the namespace `small` like any other STL container: + +```cpp +--8<-- "examples/main.cpp" +``` + +All containers are optimized for the case when they're small but also efficient when they are large. The containers mix the common techniques found in other small container libraries: + +- Inline allocation for small containers +- Custom expected sizes +- Identification of relocatable types +- Custom growth factors with better defaults +- Communication with system memory allocators +- Explicit consideration of CPU cache sizes and branch prediction + +Most applications have many small lists and sets of elements. These containers avoid spending a lot of time with large containers +that contain just a few elements. Small containers usually try to use the stack before dynamically allocating memory and try +to represent associative containers with stack arrays, unless these sets are very large. + +The following containers are available: + +- `small::vector` +- `small::max_size_vector` +- `small::string` +- `small::set` +- `small::max_size_set` +- `small::multiset` +- `small::max_size_multiset` +- `small::unordered_set` +- `small::max_size_unordered_set` +- `small::unordered_multiset` +- `small::max_size_unordered_multiset` +- `small::map` +- `small::max_size_map` +- `small::multimap` +- `small::max_size_multimap` +- `small::unordered_map` +- `small::max_size_unordered_map` +- `small::unordered_multimap` +- `small::max_size_unordered_multimap` +- `small::stack` +- `small::queue` +- `small::priority_queue` + +Although many compilers support small string optimization (SSO) already, this library will ensure all strings support SOO, custom inline sizes, relocation, and unicode. + +--8<-- "docs/references.md" \ No newline at end of file diff --git a/docs/references.md b/docs/references.md new file mode 100644 index 0000000..f6ebfe8 --- /dev/null +++ b/docs/references.md @@ -0,0 +1,30 @@ + +[constexpr]: https://en.cppreference.com/w/cpp/language/constexpr + + +[std::async]: https://en.cppreference.com/w/cpp/thread/async +[std::future]: https://en.cppreference.com/w/cpp/thread/future +[std::future_status]: https://en.cppreference.com/w/cpp/thread/future_status +[std::packaged_task]: https://en.cppreference.com/w/cpp/thread/packaged_task +[std::promise]: https://en.cppreference.com/w/cpp/thread/promise +[std::future::wait]: https://en.cppreference.com/w/cpp/thread/future/wait +[std::future::get]: https://en.cppreference.com/w/cpp/thread/future/get +[std::shared_future]: https://en.cppreference.com/w/cpp/thread/shared_future +[std::stop_source]: https://en.cppreference.com/w/cpp/thread/stop_source +[std::stop_token]: https://en.cppreference.com/w/cpp/thread/stop_token +[std::thread]: https://en.cppreference.com/w/cpp/thread/thread +[std::jthread]: https://en.cppreference.com/w/cpp/thread/jthread +[std::future]: https://en.cppreference.com/w/cpp/thread/future +[std::shared_future]: https://en.cppreference.com/w/cpp/thread/shared_future +[std::stop_source]: https://en.cppreference.com/w/cpp/thread/stop_source +[std::stop_token]: https://en.cppreference.com/w/cpp/thread/stop_token +[std::jthread]: https://en.cppreference.com/w/cpp/thread/jthread +[std::is_constant_evaluated]: https://en.cppreference.com/w/cpp/types/is_constant_evaluated +[std::vector]: https://en.cppreference.com/w/cpp/container/vector +[std::tuple]: https://en.cppreference.com/w/cpp/utility/tuple + + + + + + diff --git a/docs/sets_and_maps.md b/docs/sets_and_maps.md new file mode 100644 index 0000000..cd6dbe7 --- /dev/null +++ b/docs/sets_and_maps.md @@ -0,0 +1,15 @@ +# Sets and Maps + +The small set/map classes use a more cache-friendly flat set/map and all other optimizations mentioned above for internal algorithms. As with other small containers, a custom template parameter can be used to define the number of inline elements in the container. + +The `small::default_inline_storage` and `small::is_relocatable` trait can also be defined for custom types, and all the usual set/map, ordered/unordered, uni/multi variants are also provided: + +```cpp +--8<-- "examples/associative.cpp" +``` + +Unlike a `small::vector` or `small::string`, the asymptotic time complexities of flat sets/maps are very different from their `std::` counterparts and should only be used when they are small. Because they are internally implemented as arrays, manipulating these containers costs `O(n)`. + +For large containers, you can use `std` containers with custom allocators. Or for efficient large containers, you can use the abseil containers, implemented as B+-trees. + +--8<-- "docs/references.md" \ No newline at end of file diff --git a/docs/strings.md b/docs/strings.md new file mode 100644 index 0000000..d9dd98a --- /dev/null +++ b/docs/strings.md @@ -0,0 +1,17 @@ +# Strings + +The small string includes all the common optimizations for small vectors, and a custom template parameter to set how large we expect the string to be (in bytes). + +However, when strings are representing text, if there's one thing that makes them not small is not supporting UTF8. In addition to the common interface for strings, `small::string` includes extra functions to identify and work with UTF8 code points with random access. + +```cpp +--8<-- "examples/unicode_strings.cpp" +``` + +The problem of supporting UTF8 is easier to explain than it is to solve. Programming languages tend to solve this problem by (1) forbidding byte or substring access, and/or (2) allowing only access to code points with `O(n)` cost, where `n` is the number of code points. Because anything that forbids byte access would be incompatible with a C++ string, we allow direct byte access, and strings are allowed to be malformed unicode, which we can check with `small::is_malformed`. + +All capacity and access functions contain extra overloads that accept codepoint indexes, defined as a strong type, rather than byte indexes. By using these functions, one can ensure the string is never malformed. It's up to the user to decide whether these access functions are useful and worth it in a particular application. + +Access to codepoints is provided with an inline lookup-table trick that allows us to access codepoints in `O(log m)` time, where `m` is the number of multibyte code points in the strings. When there are no multibyte codepoints in the string, the string works as usual and no extra memory is required for the table. + +--8<-- "docs/references.md" \ No newline at end of file diff --git a/docs/stylesheets/extra.css b/docs/stylesheets/extra.css new file mode 100644 index 0000000..224bc3d --- /dev/null +++ b/docs/stylesheets/extra.css @@ -0,0 +1,10 @@ +[data-md-color-scheme="small"] { + --md-primary-fg-color: #4d90ab; + --md-primary-fg-color--light: #5B91A3; + --md-primary-fg-color--dark: #5B91A3; + --md-typeset-a-color: var(--md-primary-fg-color--light); + --md-accent-fg-color: var(--md-primary-fg-color--dark); + --md-accent-fg-color--transparent: #dcdcdc; + --md-accent-bg-color: hsla(0, 0%, 100%, 1); + --md-accent-bg-color--light: hsla(0, 0%, 100%, 0.7); +} \ No newline at end of file diff --git a/docs/vectors.md b/docs/vectors.md new file mode 100644 index 0000000..30a90a6 --- /dev/null +++ b/docs/vectors.md @@ -0,0 +1,27 @@ +# Vectors + +This small vector implementation includes: + +- Inline allocation for small vectors +- Custom expected size +- Special treatment of relocatable types + - Relocatable types can be moved with `memcpy`, bypassing destructors and constructors. + - Relocatable types are defined by default for POD types and aggregate types of PODs + - The `small::is_relocatable` traits can be used as an extension point for custom types +- Better growth factors +- Consider the cache line size in allocations +- Heap allocations can be disabled with `small::max_size_vector` + +When there are fewer elements than a given threshold, the elements are kept in a stack buffer for small vectors. Otherwise, the vector works as usual. However, if you are 100% sure you will never need more than `N` elements, you can use a `max_size_vector`, where elements are always inline. + +The default number of elements in a small vector is usually the number of elements we can already fit inline in a vector. For larger data types, the `default_inline_storage` trait can be used as an extension point where one can define how many elements a small vector of that type should contain by default. + +```cpp +--8<-- "examples/default_inline_storage.cpp" +``` + +When there's a reasonable default for the number of inline elements, this strategy avoids multiple vector type instantiations for different inline storage sizes. + +This small vector implementation used folly, abseil, and LLVM as a reference. + +--8<-- "docs/references.md" \ No newline at end of file diff --git a/mkdocs.yml b/mkdocs.yml index eeeed7a..88d4975 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -5,11 +5,27 @@ repo_name: alandefreitas/small site_description: "Small: C++ Small Containers" +nav: + - Home: index.md + - Quickstart: quickstart.md + - Vectors: vectors.md + - Strings: strings.md + - Sets and Maps: sets_and_maps.md + - Reference: # Reference is organized by module + - Small: reference/Modules/index.md # futures module + - basic_string: reference/Classes/classsmall_1_1basic__string.md + - vector: reference/Classes/classsmall_1_1vector.md + - Classes: reference/Classes/index.md # All Classes + - Files: reference/Files/index.md + - Index: reference/Namespaces/namespacesmall.md # The futures namespace contains everything + - Contributing: contributing.md + + theme: name: material custom_dir: docs/overrides palette: - scheme: preference + scheme: small icon: repo: fontawesome/brands/git-alt logo: fontawesome/solid/code @@ -18,11 +34,15 @@ edit_uri: "" plugins: - search - - awesome-pages + # - mermaid2 + - macros: + module_name: docs/macros + include_dir: .. -google_analytics: - - UA-109858331-6 - - auto +extra: + analytics: + provider: google + property: G-290016612 copyright: Copyright © Alan Freitas @@ -31,11 +51,12 @@ markdown_extensions: - pymdownx.details - pymdownx.highlight: use_pygments: true - linenums: true + linenums: false linenums_style: pymdownx.inline - pymdownx.inlinehilite - pymdownx.superfences - - pymdownx.tabbed + - pymdownx.tabbed: + alternate_style: true - pymdownx.snippets - pymdownx.arithmatex: generic: true @@ -44,4 +65,8 @@ markdown_extensions: extra_javascript: - https://polyfill.io/v3/polyfill.min.js?features=es6 - https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-mml-chtml.js - - https://media.ethicalads.io/media/client/ethicalads.min.js \ No newline at end of file + - https://media.ethicalads.io/media/client/ethicalads.min.js + - javascripts/extra.js + +extra_css: + - stylesheets/extra.css \ No newline at end of file