diff --git a/.clang-format b/.clang-format index 80f4f718b..1118d2286 100644 --- a/.clang-format +++ b/.clang-format @@ -44,7 +44,22 @@ SpaceAfterControlStatementKeyword: true SpaceBeforeAssignmentOperators: true SpaceBeforeParens: Never ContinuationIndentWidth: 4 -SortIncludes: false +SortIncludes: CaseSensitive +IncludeBlocks: Regroup +IncludeCategories: + # Main header (same name as source file) + - Regex: '^"[^/]*\.h(pp)?"$' + Priority: 1 + # BehaviorTree.CPP project headers + - Regex: '^"behaviortree_cpp/.*' + Priority: 2 + # C++ standard library headers + - Regex: '^<[a-z_]+>$' + Priority: 3 + # System headers with .h extension + - Regex: '^<.*\.h>' + Priority: 4 +IncludeIsMainRegex: '(_test)?$' SpaceAfterCStyleCast: false ReflowComments: false diff --git a/.clang-tidy b/.clang-tidy new file mode 100644 index 000000000..e34185555 --- /dev/null +++ b/.clang-tidy @@ -0,0 +1,48 @@ +Checks: [ + "-*", + "bugprone-*", + "cert-*", + "clang-analyzer-*", + "concurrency-*", + "cppcoreguidelines-*", + "misc-*", + "modernize-*", + "performance-*", + "portability-*", + "readability-*", + "-bugprone-easily-swappable-parameters", + "-bugprone-narrowing-conversions", + "-cert-err58-cpp", + "-cppcoreguidelines-avoid-c-arrays", + "-cppcoreguidelines-avoid-magic-numbers", + "-cppcoreguidelines-avoid-non-const-global-variables", + "-cppcoreguidelines-non-private-member-variables-in-classes", + "-cppcoreguidelines-pro-bounds-array-to-pointer-decay", + "-cppcoreguidelines-pro-bounds-constant-array-index", + "-cppcoreguidelines-pro-bounds-pointer-arithmetic", + "-cppcoreguidelines-pro-type-const-cast", + "-cppcoreguidelines-pro-type-union-access", + "-cppcoreguidelines-pro-type-vararg", + "-misc-no-recursion", + "-misc-non-private-member-variables-in-classes" +] + + +WarningsAsErrors: '-*,bugprone-*,cert-*,clang-analyzer-*,concurrency-*,cppcoreguidelines-*,misc-*,portability-*,readability-implicit-bool-conversion,-concurrency-mt-unsafe,-readability-function-cognitive-complexity' + +CheckOptions: + # ignore macros when computing the cyclomatic complexity. problem caused by RCLCPP LOG macros + - key: readability-function-cognitive-complexity.IgnoreMacros + value: 'true' + + # This change makes it compatible with MISRA:2023 rule 4.14.1 + - key: misc-non-private-member-variables-in-classes.IgnoreClassesWithAllMemberVariablesBeingPublic + value: 'true' + + # Making a copy of a shared_ptr has a non-zero cost, but this cost is small. + # Unfortunately the ROS API (subscriber callbacks) oblige the user to use callbacks functions that will trigger this warning + # This is the reason wht the warning is silenced here + - key: performance-unnecessary-value-param.AllowedTypes + value: 'std::shared_ptr' + + # Reference: https://clang.llvm.org/extra/clang-tidy/checks/readability/identifier-naming.html diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 000000000..5ace4600a --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,6 @@ +version: 2 +updates: + - package-ecosystem: "github-actions" + directory: "/" + schedule: + interval: "weekly" diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md index 27c6ae66a..052ed3a65 100644 --- a/.github/pull_request_template.md +++ b/.github/pull_request_template.md @@ -1,11 +1,11 @@ diff --git a/.github/workflows/cmake_ubuntu.yml b/.github/workflows/cmake_ubuntu.yml index 41ed9a196..17c9efa8c 100644 --- a/.github/workflows/cmake_ubuntu.yml +++ b/.github/workflows/cmake_ubuntu.yml @@ -6,24 +6,24 @@ on: - master pull_request: types: [opened, synchronize, reopened] + workflow_dispatch: + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true env: - # Customize the CMake build type here (Release, Debug, RelWithDebInfo, etc.) BUILD_TYPE: Release jobs: build: - # The CMake configure and build commands are platform agnostic and should work equally - # well on Windows or Mac. You can convert this to a matrix build if you need - # cross-platform coverage. - # See: https://docs.github.com/en/free-pro-team@latest/actions/learn-github-actions/managing-complex-workflows#using-a-build-matrix runs-on: ${{ matrix.os }} strategy: matrix: os: [ubuntu-22.04] steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v6 - name: Install Conan id: conan @@ -32,28 +32,103 @@ jobs: - name: Create default profile run: conan profile detect - - name: Create Build Environment - # Some projects don't allow in-source building, so create a separate build directory - # We'll use this as our working directory for all subsequent commands - run: cmake -E make_directory ${{github.workspace}}/build - - name: Install conan dependencies - working-directory: ${{github.workspace}}/build - run: conan install ${{github.workspace}}/conanfile.txt -s build_type=${{env.BUILD_TYPE}} --build=missing + run: conan install conanfile.py -s build_type=${{env.BUILD_TYPE}} --build=missing + + - name: Normalize build type + shell: bash + run: echo "BUILD_TYPE_LOWERCASE=$(echo "${BUILD_TYPE}" | tr '[:upper:]' '[:lower:]')" >> $GITHUB_ENV - name: Configure CMake shell: bash - working-directory: ${{github.workspace}}/build - run: cmake ${{github.workspace}} -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}} -DCMAKE_TOOLCHAIN_FILE=conan_toolchain.cmake + run: cmake --preset conan-${{ env.BUILD_TYPE_LOWERCASE }} - name: Build shell: bash - working-directory: ${{github.workspace}}/build - run: cmake --build . --config ${{env.BUILD_TYPE}} + run: cmake --build --preset conan-${{ env.BUILD_TYPE_LOWERCASE }} - name: run test (Linux) - working-directory: ${{github.workspace}}/build/tests - run: ctest + run: ctest --test-dir build/${{env.BUILD_TYPE}} + + coverage: + runs-on: ubuntu-24.04 + + steps: + - uses: actions/checkout@v6 + with: + fetch-depth: 0 # Full history needed by SonarCloud + + - name: Install lcov + run: sudo apt-get update && sudo apt-get install -y lcov + + - name: Install Conan + id: conan + uses: turtlebrowser/get-conan@main + + - name: Create default profile + run: conan profile detect + + - name: Install conan dependencies + run: conan install conanfile.py -s build_type=Debug --build=missing + + - name: Configure CMake with coverage + shell: bash + run: | + cmake --preset conan-debug \ + -DCMAKE_C_FLAGS="--coverage -fprofile-update=atomic" \ + -DCMAKE_CXX_FLAGS="--coverage -fprofile-update=atomic" + + - name: Build + shell: bash + run: cmake --build --preset conan-debug + + - name: Run tests + run: ctest --test-dir build/Debug --output-on-failure + + - name: Collect coverage + run: | + lcov --capture --directory build/Debug \ + --output-file coverage.info \ + --ignore-errors mismatch,mismatch \ + --ignore-errors negative,negative \ + --ignore-errors gcov,gcov + lcov --extract coverage.info \ + '*/BehaviorTree.CPP/include/*' \ + '*/BehaviorTree.CPP/src/*' \ + --output-file coverage.info \ + --ignore-errors unused + lcov --remove coverage.info \ + '*/contrib/*' \ + --output-file coverage.info \ + --ignore-errors unused + lcov --list coverage.info + + # - name: Upload coverage reports to Codecov + # uses: codecov/codecov-action@v5 + # continue-on-error: true + # with: + # files: coverage.info + # flags: unittests + # disable_search: true + # disable_file_fixes: false + # plugins: noop + # network_filter: >- + # include/behaviortree_cpp/,src/ + # token: ${{ secrets.CODECOV_TOKEN }} + + # --- Coveralls --- + - name: Upload to Coveralls + uses: coverallsapp/github-action@v2 + continue-on-error: true + with: + file: coverage.info + format: lcov + github-token: ${{ secrets.GITHUB_TOKEN }} - - name: Upload coverage reports to Codecov - uses: codecov/codecov-action@v3 + # --- SonarCloud --- + - name: Run SonarCloud analysis + uses: SonarSource/sonarcloud-github-action@v5 + continue-on-error: true + env: + SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/cmake_ubuntu_sanitizers.yml b/.github/workflows/cmake_ubuntu_sanitizers.yml new file mode 100644 index 000000000..07e3a4537 --- /dev/null +++ b/.github/workflows/cmake_ubuntu_sanitizers.yml @@ -0,0 +1,73 @@ +name: cmake Ubuntu Sanitizers + +on: + push: + branches: + - master + pull_request: + types: [opened, synchronize, reopened] + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +env: + # Customize the CMake build type here (Release, Debug, RelWithDebInfo, etc.) + BUILD_TYPE: Debug + +jobs: + build: + # The CMake configure and build commands are platform agnostic and should work equally + # well on Windows or Mac. You can convert this to a matrix build if you need + # cross-platform coverage. + # See: https://docs.github.com/en/free-pro-team@latest/actions/learn-github-actions/managing-complex-workflows#using-a-build-matrix + runs-on: ${{ matrix.os }} + strategy: + fail-fast: false + matrix: + os: [ubuntu-22.04] + sanitizer: [asan_ubsan, tsan] + + steps: + - uses: actions/checkout@v6 + + - name: Install Conan + id: conan + uses: turtlebrowser/get-conan@main + + - name: Create default profile + run: conan profile detect + + - name: Install conan dependencies + run: conan install conanfile.py -s build_type=${{env.BUILD_TYPE}} --build=missing + + - name: Normalize build type + shell: bash + # The build type is Capitalized, e.g. Release, but the preset is all lowercase, e.g. release. + # There is no built in way to do string manipulations on GHA as far as I know.` + run: echo "BUILD_TYPE_LOWERCASE=$(echo "${BUILD_TYPE}" | tr '[:upper:]' '[:lower:]')" >> $GITHUB_ENV + + - name: Configure CMake + shell: bash + run: | + if [[ "${{ matrix.sanitizer }}" == "asan_ubsan" ]]; then + cmake --preset conan-${{ env.BUILD_TYPE_LOWERCASE }} \ + -DBTCPP_ENABLE_ASAN:BOOL=ON -DBTCPP_ENABLE_UBSAN:BOOL=ON + else + cmake --preset conan-${{ env.BUILD_TYPE_LOWERCASE }} \ + -DBTCPP_ENABLE_TSAN:BOOL=ON + fi + + - name: Build + shell: bash + run: cmake --build --preset conan-${{ env.BUILD_TYPE_LOWERCASE }} + + - name: run test (Linux + Address and Undefined Behavior Sanitizers) + env: + GTEST_COLOR: "On" + ASAN_OPTIONS: "color=always" + UBSAN_OPTIONS: "halt_on_error=1:print_stacktrace=1:color=always" + TSAN_OPTIONS: "suppressions=../../../tests/tsan_suppressions.txt:color=always" + # There is a known issue with TSAN on recent kernel versions. Without the vm.mmap_rnd_bits=28 + # workaround all binaries with TSan enabled crash with "FATAL: ThreadSanitizer: unexpected memory mapping" + run: sudo sysctl vm.mmap_rnd_bits=28 && ctest --test-dir build/${{env.BUILD_TYPE}} --output-on-failure diff --git a/.github/workflows/cmake_windows.yml b/.github/workflows/cmake_windows.yml index 34f4f97ce..0eb1f47a1 100644 --- a/.github/workflows/cmake_windows.yml +++ b/.github/workflows/cmake_windows.yml @@ -7,23 +7,20 @@ on: pull_request: types: [opened, synchronize, reopened] -env: - # Customize the CMake build type here (Release, Debug, RelWithDebInfo, etc.) - BUILD_TYPE: Release +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true jobs: build: - # The CMake configure and build commands are platform agnostic and should work equally - # well on Windows or Mac. You can convert this to a matrix build if you need - # cross-platform coverage. - # See: https://docs.github.com/en/free-pro-team@latest/actions/learn-github-actions/managing-complex-workflows#using-a-build-matrix runs-on: ${{ matrix.os }} strategy: matrix: os: [windows-latest] + build_type: [Release, Debug] steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v6 - name: Install Conan id: conan @@ -32,25 +29,21 @@ jobs: - name: Create default profile run: conan profile detect - - name: Create Build Environment - # Some projects don't allow in-source building, so create a separate build directory - # We'll use this as our working directory for all subsequent commands - run: cmake -E make_directory ${{github.workspace}}/build - - name: Install conan dependencies - working-directory: ${{github.workspace}}/build - run: conan install ${{github.workspace}}/conanfile.txt -s build_type=${{env.BUILD_TYPE}} --build=missing + run: conan install conanfile.py -s build_type=${{ matrix.build_type }} --build=missing --settings:host compiler.cppstd=17 + + - name: Normalize build type + shell: bash + run: echo "BUILD_TYPE_LOWERCASE=$(echo "${{ matrix.build_type }}" | tr '[:upper:]' '[:lower:]')" >> $GITHUB_ENV - name: Configure CMake shell: bash - working-directory: ${{github.workspace}}/build - run: cmake $GITHUB_WORKSPACE -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}} -DCMAKE_TOOLCHAIN_FILE=conan_toolchain.cmake + run: cmake --preset conan-default - name: Build - working-directory: ${{github.workspace}}/build shell: bash - run: cmake --build . --config ${{env.BUILD_TYPE}} + run: cmake --build --preset conan-${{ env.BUILD_TYPE_LOWERCASE }} - - name: run test (Windows) - working-directory: ${{github.workspace}}/build - run: $env:PATH+=";${{env.BUILD_TYPE}}"; tests/${{env.BUILD_TYPE}}/behaviortree_cpp_test.exe + - name: Run tests + working-directory: ${{ github.workspace }}/build + run: $env:PATH+=";${{ matrix.build_type }}"; tests/${{ matrix.build_type }}/behaviortree_cpp_test.exe diff --git a/.github/workflows/doxygen-gh-pages.yml b/.github/workflows/doxygen-gh-pages.yml index b8fb8f46b..bbb575e0c 100644 --- a/.github/workflows/doxygen-gh-pages.yml +++ b/.github/workflows/doxygen-gh-pages.yml @@ -6,6 +6,10 @@ on: - main - master +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + jobs: deploy: runs-on: ubuntu-latest diff --git a/.github/workflows/pixi.yaml b/.github/workflows/pixi.yaml index ddd1cbfb8..848613ccb 100644 --- a/.github/workflows/pixi.yaml +++ b/.github/workflows/pixi.yaml @@ -7,6 +7,10 @@ on: pull_request: types: [opened, synchronize, reopened] +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + jobs: pixi_conda_build: strategy: @@ -17,8 +21,8 @@ jobs: runs-on: ${{ matrix.os }} steps: # Pixi is the tool used to create/manage conda environment - - uses: actions/checkout@v3 - - uses: prefix-dev/setup-pixi@v0.8.1 + - uses: actions/checkout@v6 + - uses: prefix-dev/setup-pixi@v0.9.4 with: pixi-version: v0.40.3 - name: Build diff --git a/.github/workflows/pre-commit.yaml b/.github/workflows/pre-commit.yaml index ee7fa9229..4b28706a8 100644 --- a/.github/workflows/pre-commit.yaml +++ b/.github/workflows/pre-commit.yaml @@ -7,10 +7,37 @@ on: pull_request: types: [opened, synchronize, reopened] +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + jobs: pre-commit: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 - - uses: actions/setup-python@v3 + - uses: actions/checkout@v6 + - uses: actions/setup-python@v6 - uses: pre-commit/action@v3.0.1 + + clang-tidy: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v6 + + - name: Install LLVM 21 + run: | + wget https://apt.llvm.org/llvm.sh + chmod +x llvm.sh + sudo ./llvm.sh 21 + sudo apt-get install -y clangd-21 clang-tidy-21 + + - name: Install dependencies + run: | + sudo apt-get update + sudo apt-get install -y libzmq3-dev libsqlite3-dev + + - name: Configure CMake + run: cmake -B build -DBUILD_TESTING=OFF + + - name: Run clang-tidy + run: ./run_clang_tidy.sh diff --git a/.github/workflows/ros2-rolling.yaml b/.github/workflows/ros2-rolling.yaml index 446c49879..1eb8584ac 100644 --- a/.github/workflows/ros2-rolling.yaml +++ b/.github/workflows/ros2-rolling.yaml @@ -7,6 +7,10 @@ on: pull_request: types: [opened, synchronize, reopened] +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + jobs: industrial_ci: strategy: @@ -15,8 +19,8 @@ jobs: - {ROS_DISTRO: rolling, ROS_REPO: main} runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v6 - uses: 'ros-industrial/industrial_ci@master' env: ${{matrix.env}} with: - package-name: plotjuggler + package-name: behaviortree_cpp diff --git a/.github/workflows/ros2.yaml b/.github/workflows/ros2.yaml index 099cc04f2..494e9471e 100644 --- a/.github/workflows/ros2.yaml +++ b/.github/workflows/ros2.yaml @@ -7,6 +7,10 @@ on: pull_request: types: [opened, synchronize, reopened] +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + jobs: industrial_ci: strategy: @@ -16,8 +20,8 @@ jobs: - {ROS_DISTRO: jazzy, ROS_REPO: main} runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v6 - uses: 'ros-industrial/industrial_ci@master' env: ${{matrix.env}} with: - package-name: plotjuggler + package-name: behaviortree_cpp diff --git a/.gitignore b/.gitignore index 9d5bd4326..ddf344b2e 100644 --- a/.gitignore +++ b/.gitignore @@ -5,8 +5,9 @@ site/* /.vscode/ .vs/ -# clangd cache +# clangd cache and config (generated by CMake) /.cache/* +/.clangd CMakeSettings.json # OSX junk @@ -18,3 +19,15 @@ CMakeSettings.json CMakeUserPresets.json tags +/clang_tidy_output.log +/.clang-tidy-venv/* +/llvm.sh +t11_groot_howto.btlog +minitrace.json + +TODO.md +/.worktrees/* +/docs/plans/* +/coverage_report/* +/coverage.info +/doc/html/* diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index d491f36d9..ef395d8b9 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -13,7 +13,7 @@ # # See https://github.com/pre-commit/pre-commit -exclude: ^3rdparty/|3rdparty|^include/behaviortree_cpp/contrib/ +exclude: ^3rdparty/|3rdparty|^include/behaviortree_cpp/contrib/|CHANGELOG.rst repos: # Standard hooks @@ -43,6 +43,16 @@ repos: - id: clang-format args: ['-fallback-style=none', '-i'] + # C++ static analysis via clangd-21 (skips if not installed) + - repo: local + hooks: + - id: clang-tidy + name: clang-tidy + entry: ./run_clang_tidy_hook.sh + language: script + files: \.(cpp|hpp|h)$ + exclude: ^3rdparty/|^include/behaviortree_cpp/contrib/|^include/behaviortree_cpp/scripting/|^include/behaviortree_cpp/flatbuffers/|^examples/|^tools/|^fuzzing/|^tests/gtest_async_action_node\.cpp$|^tests/gtest_logger_zmq\.cpp$|^tests/include/environment\.h$|^tests/gtest_groot2_publisher\.cpp$ + # Spell check - repo: https://github.com/codespell-project/codespell rev: v2.4.1 diff --git a/3rdparty/cpp-sqlite/README.md b/3rdparty/cpp-sqlite/README.md deleted file mode 100644 index 913354947..000000000 --- a/3rdparty/cpp-sqlite/README.md +++ /dev/null @@ -1,37 +0,0 @@ -## Single file header only sqlite wrapper for C++ - -## Example -```cpp -#include "sqlite.hpp" -#include - -int main() -{ - sqlite::Connection connection("example.db"); - - sqlite::Statement(connection, "CREATE TABLE IF NOT EXISTS exampleTable (" - "textData TEXT, " - "intData INTEGER, " - "floatData REAL)"); - - sqlite::Statement(connection, - "INSERT INTO exampleTable VALUES (?, ?, ?)", - "Hello world", - 1234, - 5.6789); - - sqlite::Result res = sqlite::Query(connection, "SELECT * FROM exampleTable"); - - while(res.Next()) - { - std::string textData = res.Get(0); - int intData = res.Get(1); - float floatData = res.Get(2); - - std::cout << textData << " " << intData << " " << floatData << std::endl; - } - - return 0; -} - -``` diff --git a/3rdparty/cpp-sqlite/sqlite.hpp b/3rdparty/cpp-sqlite/sqlite.hpp deleted file mode 100644 index c512d891c..000000000 --- a/3rdparty/cpp-sqlite/sqlite.hpp +++ /dev/null @@ -1,603 +0,0 @@ -/** - Copyright (C) 2023 Toni Lipponen - - This software is provided 'as-is', without any express or implied - warranty. In no event will the authors be held liable for any damages - arising from the use of this software. - - Permission is granted to anyone to use this software for any purpose, - including commercial applications, and to alter it and redistribute it - freely, subject to the following restrictions: - - 1. The origin of this software must not be misrepresented; you must not - claim that you wrote the original software. If you use this software - in a product, an acknowledgment in the product documentation would be - appreciated but is not required. - - 2. Altered source versions must be plainly marked as such, and must not be - misrepresented as being the original software. - - 3. This notice may not be removed or altered from any source distribution. - */ - -#pragma once -#include -#include -#include -#include -#include -#include - -#if __cplusplus > 201402L - #define CPP_SQLITE_NODISCARD [[nodiscard]] -#else - #define CPP_SQLITE_NODISCARD -#endif - -#if defined(CPP_SQLITE_NOTHROW) - #define CPP_SQLITE_THROW(...) return false -#else - #define CPP_SQLITE_THROW(...) throw sqlite::Error(__VA_ARGS__) -#endif - -namespace sqlite -{ - class Error : public std::runtime_error - { - public: - explicit Error(const char* message, int errorCode = SQLITE_ERROR) - : std::runtime_error(message), m_errorCode(errorCode) - { - - } - - explicit Error(const std::string& message, int errorCode = SQLITE_ERROR) - : std::runtime_error(message), m_errorCode(errorCode) - { - - } - - CPP_SQLITE_NODISCARD - int GetCode() const - { - return m_errorCode; - } - - private: - int m_errorCode; - }; - - namespace Priv - { - inline bool CheckError(sqlite3* db, int code) - { - if(code != SQLITE_OK && code != SQLITE_DONE) - { - const int extendedCode = sqlite3_extended_errcode(db); - std::string errstr = sqlite3_errstr(extendedCode); - std::string errmsg = sqlite3_errmsg(db); - - CPP_SQLITE_THROW(errstr + ": " + errmsg, extendedCode); - } - - return true; - } - - inline bool CheckError(int code) - { - if(code != SQLITE_OK && code != SQLITE_DONE) - { - std::string errstr = std::string("SQL error: ") + sqlite3_errstr(code); - CPP_SQLITE_THROW(errstr, code); - } - - return true; - } - } - - class Connection - { - public: - Connection() : m_connection(nullptr) {} - - explicit Connection(const std::string& filename) - { - this->Open(filename); - } - - Connection(const Connection&) = delete; - - Connection(Connection&& other) noexcept - { - this->m_connection = other.m_connection; - other.m_connection = nullptr; - } - - virtual ~Connection() noexcept - { - try - { - this->Close(); - } - catch(...) - { - - } - } - - Connection& operator=(const Connection&) = delete; - - Connection& operator=(Connection&& other) noexcept - { - if(&other != this) - { - this->m_connection = other.m_connection; - other.m_connection = nullptr; - } - - return *this; - } - - bool Open(const std::string& filename) - { - return sqlite::Priv::CheckError(sqlite3_open(filename.data(), &m_connection)); - } - - bool Close() - { - const auto result = Priv::CheckError(sqlite3_close(m_connection)); - m_connection = nullptr; - - return result; - } - - CPP_SQLITE_NODISCARD - int GetExtendedResult() const - { - return sqlite3_extended_errcode(m_connection); - } - - CPP_SQLITE_NODISCARD - sqlite3* GetPtr() - { - return m_connection; - } - - private: - sqlite3* m_connection = nullptr; - }; - - class Blob - { - public: - Blob(const void* data, int32_t bytes) - { - m_data.resize(bytes); - std::memcpy(&m_data.at(0), data, bytes); - } - - explicit Blob(std::vector data) - : m_data(std::move(data)) - { - - } - - CPP_SQLITE_NODISCARD - uint32_t GetSize() const - { - return m_data.size(); - } - - CPP_SQLITE_NODISCARD - unsigned char* GetData() - { - return m_data.data(); - } - - CPP_SQLITE_NODISCARD - const unsigned char* GetData() const - { - return m_data.data(); - } - - private: - std::vector m_data; - }; - - /** Non-owning blob*/ - class NOBlob - { - public: - NOBlob(const void* ptr, uint32_t bytes) - : m_ptr(ptr), m_bytes(bytes) - { - - } - - CPP_SQLITE_NODISCARD - uint32_t GetSize() const - { - return m_bytes; - } - - const void* GetData() - { - return m_ptr; - } - - CPP_SQLITE_NODISCARD - const void* GetData() const - { - return m_ptr; - } - - private: - const void* m_ptr; - uint32_t m_bytes; - }; - - namespace Priv - { - inline void Append(sqlite3_stmt* statement, int index, const int32_t& data) - { - sqlite::Priv::CheckError(sqlite3_bind_int(statement, index, data)); - } - - inline void Append(sqlite3_stmt* statement, int index, const int64_t& data) - { - sqlite::Priv::CheckError(sqlite3_bind_int64(statement, index, data)); - } - - inline void Append(sqlite3_stmt* statement, int index, const float& data) - { - sqlite::Priv::CheckError(sqlite3_bind_double(statement, index, static_cast(data))); - } - - inline void Append(sqlite3_stmt* statement, int index, const double& data) - { - sqlite::Priv::CheckError(sqlite3_bind_double(statement, index, data)); - } - - inline void Append(sqlite3_stmt* statement, int index, const std::string& data) - { - sqlite::Priv::CheckError(sqlite3_bind_text(statement, index, data.data(), static_cast(data.size()), nullptr)); - } - - inline void Append(sqlite3_stmt* statement, int index, const char* data) - { - sqlite::Priv::CheckError(sqlite3_bind_text(statement, index, data, static_cast(std::strlen(data)), nullptr)); - } - - inline void Append(sqlite3_stmt* statement, int index, const sqlite::Blob& blob) - { - sqlite::Priv::CheckError(sqlite3_bind_blob(statement, index, blob.GetData(), static_cast(blob.GetSize()), nullptr)); - } - - inline void Append(sqlite3_stmt* statement, int index, const sqlite::NOBlob& blob) - { - sqlite::Priv::CheckError(sqlite3_bind_blob(statement, index, blob.GetData(), static_cast(blob.GetSize()), nullptr)); - } - - template - inline void AppendToQuery(sqlite3_stmt* statement, int index, const Arg& arg) - { - sqlite::Priv::Append(statement, index, arg); - } - - template - inline void AppendToQuery(sqlite3_stmt* statement, int index, const First& first, const Args&... args) - { - sqlite::Priv::Append(statement, index, first); - sqlite::Priv::AppendToQuery(statement, ++index, args...); - } - - struct Statement - { - Statement() : handle(nullptr) {} - - Statement(sqlite::Connection& connection, const std::string& command) - { - auto* db = connection.GetPtr(); - - const int code = sqlite3_prepare_v2( - db, - command.data(), - static_cast(command.size()), - &handle, - nullptr); - - Priv::CheckError(db, code); - } - - Statement(Statement&& other) noexcept - { - std::swap(handle, other.handle); - } - - ~Statement() - { - sqlite::Priv::CheckError(sqlite3_finalize(handle)); - } - - Statement& operator=(Statement&& other) noexcept - { - handle = other.handle; - other.handle = nullptr; - - return *this; - } - - CPP_SQLITE_NODISCARD - bool Advance() const - { - const int code = sqlite3_step(handle); - - if(code == SQLITE_ROW) - { - return true; - } - - sqlite::Priv::CheckError(code); - Reset(); - - return false; - } - - bool Reset() const - { - return sqlite::Priv::CheckError(sqlite3_reset(handle)); - } - - CPP_SQLITE_NODISCARD - int ColumnCount() const - { - Reset(); - - if(!Advance()) - { - return 0; - } - - const int count = sqlite3_column_count(handle); - Reset(); - - return count; - } - - CPP_SQLITE_NODISCARD - std::string GetColumnName(int columnIndex) const - { - Reset(); - - if(!Advance()) - { -#ifndef CPP_SQLITE_NOTHROW - throw sqlite::Error("SQL error: invalid column index"); -#endif - } - - std::string name = sqlite3_column_name(handle, columnIndex); - - if(name.empty()) - { -#ifndef CPP_SQLITE_NOTHROW - throw sqlite::Error("SQL error: failed to get column name at index " + std::to_string(columnIndex)); -#endif - } - - Reset(); - - return name; - } - - template - CPP_SQLITE_NODISCARD - T Get(int) const - { - static_assert(sizeof(T) == -1, "SQL error: invalid column data type"); - } - - sqlite3_stmt* handle = nullptr; - }; - - template<> - inline float Statement::Get(int col) const - { - return static_cast(sqlite3_column_double(handle, col)); - } - - template<> - inline double Statement::Get(int col) const - { - return sqlite3_column_double(handle, col); - } - - template<> - inline int32_t Statement::Get(int col) const - { - return sqlite3_column_int(handle, col); - } - - template<> - inline int64_t Statement::Get(int col) const - { - return sqlite3_column_int64(handle, col); - } - - template<> - inline std::string Statement::Get(int col) const - { - const unsigned char* bytes = sqlite3_column_text(handle, col); - const int size = sqlite3_column_bytes(handle, col); - - if(size == 0) - { - return ""; - } - - return {reinterpret_cast(bytes), static_cast(size)}; - } - - template<> - inline sqlite::Blob Statement::Get(int col) const - { - const void* bytes = sqlite3_column_blob(handle, col); - const int size = sqlite3_column_bytes(handle, col); - - return {bytes, size}; - } - } - - class Type - { - private: - Type(const sqlite::Priv::Statement& statement, int col) - : m_statement(statement), m_columnIndex(col) - { - - } - public: - template - operator T() const - { - return m_statement.Get(m_columnIndex); - } - - friend class Result; - - private: - const sqlite::Priv::Statement& m_statement; - const int m_columnIndex; - }; - - class Result - { - explicit Result(sqlite::Priv::Statement&& statement) - : m_statement(std::move(statement)) - { - - } - - public: - Result() = default; - - Result(Result&& other) noexcept - { - m_statement = std::move(other.m_statement); - } - - Result& operator=(Result&& other) noexcept - { - m_statement = std::move(other.m_statement); - - return *this; - } - - CPP_SQLITE_NODISCARD - bool HasData() const - { - return ColumnCount() > 0; - } - - CPP_SQLITE_NODISCARD - int ColumnCount() const - { - return m_statement.ColumnCount(); - } - - bool Reset() const - { - return m_statement.Reset(); - } - - CPP_SQLITE_NODISCARD - bool Next() const - { - return m_statement.Advance(); - } - - CPP_SQLITE_NODISCARD - Type Get(int columnIndex) const - { - return {m_statement, columnIndex}; - } - - CPP_SQLITE_NODISCARD - std::string GetColumnName(int columnIndex) const - { - return m_statement.GetColumnName(columnIndex); - } - - friend void Statement(sqlite::Connection&, const std::string&); - - template - friend Result Query(sqlite::Connection& connection, const std::string& command, const First& first, const Args... args); - friend Result Query(sqlite::Connection& connection, const std::string& command); - - private: - sqlite::Priv::Statement m_statement; - }; - - template - inline void Statement(sqlite::Connection& connection, const std::string& command, const First& first, const Args... args) - { - sqlite::Priv::Statement statement(connection, command); - sqlite::Priv::AppendToQuery(statement.handle, 1, first, args...); - - (void)statement.Advance(); - } - - inline void Statement(sqlite::Connection& connection, const std::string& command) - { - sqlite::Priv::Statement statement(connection, command); - - (void)statement.Advance(); - } - - template - CPP_SQLITE_NODISCARD - inline Result Query(sqlite::Connection& connection, const std::string& command, const First& first, const Args... args) - { - sqlite::Priv::Statement statement(connection, command); - sqlite::Priv::AppendToQuery(statement.handle, 1, first, args...); - - return Result(std::move(statement)); - } - - CPP_SQLITE_NODISCARD - inline Result Query(sqlite::Connection& connection, const std::string& command) - { - sqlite::Priv::Statement statement(connection, command); - - return Result(std::move(statement)); - } - - inline bool Backup(sqlite::Connection& from, sqlite::Connection& to) - { - sqlite3_backup* backup = sqlite3_backup_init(to.GetPtr(), "main", from.GetPtr(), "main"); - - if(!backup) - { - CPP_SQLITE_THROW("SQL error: failed to initialize backup"); - } - - if(!Priv::CheckError(sqlite3_backup_step(backup, -1))) - { - return false; - } - - if(!Priv::CheckError(sqlite3_backup_finish(backup))) - { - return false; - } - - return true; - } - - inline bool Backup(sqlite::Connection& from, const std::string& filename) - { - sqlite::Connection to(filename); - - return sqlite::Backup(from, to); - } -} diff --git a/3rdparty/cppzmq/CMakeLists.txt b/3rdparty/cppzmq/CMakeLists.txt new file mode 100644 index 000000000..9a0bb86b0 --- /dev/null +++ b/3rdparty/cppzmq/CMakeLists.txt @@ -0,0 +1,19 @@ +find_package(ZeroMQ REQUIRED) + +add_library(cppzmq INTERFACE) + +# This library doesn't use modern targets unfortunately. +#add_library(cppzmq::cppzmq ALIAS cppzmq) + +target_include_directories(cppzmq + INTERFACE + ${CMAKE_CURRENT_SOURCE_DIR} +) + +if(TARGET libzmq-static) + target_link_libraries(cppzmq INTERFACE libzmq-static) +elseif(TARGET libzmq) + target_link_libraries(cppzmq INTERFACE libzmq) +else() + message(FATAL_ERROR "Unknown zeromq target name") +endif() diff --git a/3rdparty/cppzmq/README.md b/3rdparty/cppzmq/README.md index e2bea0b63..5d804d0c8 100644 --- a/3rdparty/cppzmq/README.md +++ b/3rdparty/cppzmq/README.md @@ -163,25 +163,27 @@ Build instructions Build steps: 1. Build [libzmq](https://github.com/zeromq/libzmq) via cmake. This does an out of source build and installs the build files - - download and unzip the lib, cd to directory - - mkdir build - - cd build - - cmake .. - - sudo make -j4 install + - `git clone https://github.com/zeromq/libzmq.git` + - `cd libzmq` + - `mkdir build` + - `cd build` + - `cmake ..` + - `sudo make -j4 install` 2. Build cppzmq via cmake. This does an out of source build and installs the build files - - download and unzip the lib, cd to directory - - mkdir build - - cd build - - cmake .. - - sudo make -j4 install - -3. Build cppzmq via [vcpkg](https://github.com/Microsoft/vcpkg/). This does an out of source build and installs the build files - - git clone https://github.com/Microsoft/vcpkg.git - - cd vcpkg - - ./bootstrap-vcpkg.sh # bootstrap-vcpkg.bat for Powershell - - ./vcpkg integrate install - - ./vcpkg install cppzmq + - `git clone https://github.com/zeromq/cppzmq.git` + - `cd cppzmq` + - `mkdir build` + - `cd build` + - `cmake ..` or `cmake -DCPPZMQ_BUILD_TESTS=OFF ..` to skip building tests + - `sudo make -j4 install` + +3. Alternatively, build cppzmq via [vcpkg](https://github.com/Microsoft/vcpkg/). This does an out of source build and installs the build files + - `git clone https://github.com/Microsoft/vcpkg.git` + - `cd vcpkg` + - `./bootstrap-vcpkg.sh` (bootstrap-vcpkg.bat for Powershell) + - `./vcpkg integrate install` + - `./vcpkg install cppzmq` Using this: @@ -193,4 +195,6 @@ cpp zmq (which will also include libzmq for you). #find cppzmq wrapper, installed by make of cppzmq find_package(cppzmq) target_link_libraries(*Your Project Name* cppzmq) +# Or use static library to link +target_link_libraries(*Your Project Name* cppzmq-static) ``` diff --git a/3rdparty/cppzmq/zmq.hpp b/3rdparty/cppzmq/zmq.hpp index 3fa484c6c..ad0509e89 100644 --- a/3rdparty/cppzmq/zmq.hpp +++ b/3rdparty/cppzmq/zmq.hpp @@ -108,6 +108,7 @@ #include #include +#include #include #include #include @@ -147,7 +148,7 @@ /* Version macros for compile-time API version detection */ #define CPPZMQ_VERSION_MAJOR 4 -#define CPPZMQ_VERSION_MINOR 10 +#define CPPZMQ_VERSION_MINOR 11 #define CPPZMQ_VERSION_PATCH 0 #define CPPZMQ_VERSION \ @@ -690,39 +691,40 @@ class message_t * Use to_string() or to_string_view() for * interpreting the message as a string. */ - std::string str() const + std::string str(size_t max_size = 1000) const { // Partly mutuated from the same method in zmq::multipart_t std::stringstream os; const unsigned char *msg_data = this->data(); - unsigned char byte; - size_t size = this->size(); + size_t size_to_print = (std::min)(this->size(), max_size); int is_ascii[2] = {0, 0}; + // Set is_ascii for the first character + if (size_to_print > 0) + is_ascii[0] = (*msg_data >= 32 && *msg_data < 127); os << "zmq::message_t [size " << std::dec << std::setw(3) - << std::setfill('0') << size << "] ("; - // Totally arbitrary - if (size >= 1000) { - os << "... too big to print)"; - } else { - while (size--) { - byte = *msg_data++; - - is_ascii[1] = (byte >= 32 && byte < 127); - if (is_ascii[1] != is_ascii[0]) - os << " "; // Separate text/non text - - if (is_ascii[1]) { - os << byte; - } else { - os << std::hex << std::uppercase << std::setw(2) - << std::setfill('0') << static_cast(byte); - } - is_ascii[0] = is_ascii[1]; + << std::setfill('0') << this->size() << "] ("; + while (size_to_print--) { + const unsigned char byte = *msg_data++; + + is_ascii[1] = (byte >= 32 && byte < 127); + if (is_ascii[1] != is_ascii[0]) + os << " "; // Separate text/non text + + if (is_ascii[1]) { + os << byte; + } else { + os << std::hex << std::uppercase << std::setw(2) << std::setfill('0') + << static_cast(byte); } - os << ")"; + is_ascii[0] = is_ascii[1]; } + // Elide the rest if the message is too large + if (max_size < this->size()) + os << "... too big to print)"; + else + os << ")"; return os.str(); } @@ -1363,19 +1365,19 @@ constexpr const_buffer str_buffer(const Char (&data)[N]) noexcept namespace literals { -constexpr const_buffer operator"" _zbuf(const char *str, size_t len) noexcept +constexpr const_buffer operator""_zbuf(const char *str, size_t len) noexcept { return const_buffer(str, len * sizeof(char)); } -constexpr const_buffer operator"" _zbuf(const wchar_t *str, size_t len) noexcept +constexpr const_buffer operator""_zbuf(const wchar_t *str, size_t len) noexcept { return const_buffer(str, len * sizeof(wchar_t)); } -constexpr const_buffer operator"" _zbuf(const char16_t *str, size_t len) noexcept +constexpr const_buffer operator""_zbuf(const char16_t *str, size_t len) noexcept { return const_buffer(str, len * sizeof(char16_t)); } -constexpr const_buffer operator"" _zbuf(const char32_t *str, size_t len) noexcept +constexpr const_buffer operator""_zbuf(const char32_t *str, size_t len) noexcept { return const_buffer(str, len * sizeof(char32_t)); } @@ -1461,6 +1463,9 @@ ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_BACKLOG, backlog, int); #ifdef ZMQ_BINDTODEVICE ZMQ_DEFINE_ARRAY_OPT_BINARY(ZMQ_BINDTODEVICE, bindtodevice); #endif +#ifdef ZMQ_BUSY_POLL +ZMQ_DEFINE_INTEGRAL_BOOL_UNIT_OPT(ZMQ_BUSY_POLL, busy_poll, int); +#endif #ifdef ZMQ_CONFLATE ZMQ_DEFINE_INTEGRAL_BOOL_UNIT_OPT(ZMQ_CONFLATE, conflate, int); #endif @@ -1624,6 +1629,9 @@ ZMQ_DEFINE_INTEGRAL_BOOL_UNIT_OPT(ZMQ_ROUTER_MANDATORY, router_mandatory, int); #ifdef ZMQ_ROUTER_NOTIFY ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_ROUTER_NOTIFY, router_notify, int); #endif +#ifdef ZMQ_ROUTER_RAW +ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_ROUTER_RAW, router_raw, int); +#endif #ifdef ZMQ_ROUTING_ID ZMQ_DEFINE_ARRAY_OPT_BINARY(ZMQ_ROUTING_ID, routing_id); #endif @@ -2362,8 +2370,6 @@ class monitor_t { assert(_monitor_socket); - zmq::message_t eventMsg; - zmq::pollitem_t items[] = { {_monitor_socket.handle(), 0, ZMQ_POLLIN, 0}, }; @@ -2374,106 +2380,7 @@ class monitor_t zmq::poll(&items[0], 1, timeout); #endif - if (items[0].revents & ZMQ_POLLIN) { - int rc = zmq_msg_recv(eventMsg.handle(), _monitor_socket.handle(), 0); - if (rc == -1 && zmq_errno() == ETERM) - return false; - assert(rc != -1); - - } else { - return false; - } - -#if ZMQ_VERSION_MAJOR >= 4 - const char *data = static_cast(eventMsg.data()); - zmq_event_t msgEvent; - memcpy(&msgEvent.event, data, sizeof(uint16_t)); - data += sizeof(uint16_t); - memcpy(&msgEvent.value, data, sizeof(int32_t)); - zmq_event_t *event = &msgEvent; -#else - zmq_event_t *event = static_cast(eventMsg.data()); -#endif - -#ifdef ZMQ_NEW_MONITOR_EVENT_LAYOUT - zmq::message_t addrMsg; - int rc = zmq_msg_recv(addrMsg.handle(), _monitor_socket.handle(), 0); - if (rc == -1 && zmq_errno() == ETERM) { - return false; - } - - assert(rc != -1); - std::string address = addrMsg.to_string(); -#else - // Bit of a hack, but all events in the zmq_event_t union have the same layout so this will work for all event types. - std::string address = event->data.connected.addr; -#endif - -#ifdef ZMQ_EVENT_MONITOR_STOPPED - if (event->event == ZMQ_EVENT_MONITOR_STOPPED) { - return false; - } - -#endif - - switch (event->event) { - case ZMQ_EVENT_CONNECTED: - on_event_connected(*event, address.c_str()); - break; - case ZMQ_EVENT_CONNECT_DELAYED: - on_event_connect_delayed(*event, address.c_str()); - break; - case ZMQ_EVENT_CONNECT_RETRIED: - on_event_connect_retried(*event, address.c_str()); - break; - case ZMQ_EVENT_LISTENING: - on_event_listening(*event, address.c_str()); - break; - case ZMQ_EVENT_BIND_FAILED: - on_event_bind_failed(*event, address.c_str()); - break; - case ZMQ_EVENT_ACCEPTED: - on_event_accepted(*event, address.c_str()); - break; - case ZMQ_EVENT_ACCEPT_FAILED: - on_event_accept_failed(*event, address.c_str()); - break; - case ZMQ_EVENT_CLOSED: - on_event_closed(*event, address.c_str()); - break; - case ZMQ_EVENT_CLOSE_FAILED: - on_event_close_failed(*event, address.c_str()); - break; - case ZMQ_EVENT_DISCONNECTED: - on_event_disconnected(*event, address.c_str()); - break; -#if ZMQ_VERSION >= ZMQ_MAKE_VERSION(4, 3, 0) || (defined(ZMQ_BUILD_DRAFT_API) && ZMQ_VERSION >= ZMQ_MAKE_VERSION(4, 2, 3)) - case ZMQ_EVENT_HANDSHAKE_FAILED_NO_DETAIL: - on_event_handshake_failed_no_detail(*event, address.c_str()); - break; - case ZMQ_EVENT_HANDSHAKE_FAILED_PROTOCOL: - on_event_handshake_failed_protocol(*event, address.c_str()); - break; - case ZMQ_EVENT_HANDSHAKE_FAILED_AUTH: - on_event_handshake_failed_auth(*event, address.c_str()); - break; - case ZMQ_EVENT_HANDSHAKE_SUCCEEDED: - on_event_handshake_succeeded(*event, address.c_str()); - break; -#elif defined(ZMQ_BUILD_DRAFT_API) && ZMQ_VERSION >= ZMQ_MAKE_VERSION(4, 2, 1) - case ZMQ_EVENT_HANDSHAKE_FAILED: - on_event_handshake_failed(*event, address.c_str()); - break; - case ZMQ_EVENT_HANDSHAKE_SUCCEED: - on_event_handshake_succeed(*event, address.c_str()); - break; -#endif - default: - on_event_unknown(*event, address.c_str()); - break; - } - - return true; + return process_event(items[0].revents); } #ifdef ZMQ_EVENT_MONITOR_STOPPED @@ -2484,6 +2391,8 @@ class monitor_t _socket = socket_ref(); } + + virtual void on_monitor_stopped() {} #endif virtual void on_monitor_started() {} virtual void on_event_connected(const zmq_event_t &event_, const char *addr_) @@ -2583,6 +2492,116 @@ class monitor_t (void) addr_; } + protected: + bool process_event(short events) + { + zmq::message_t eventMsg; + + if (events & ZMQ_POLLIN) { + int rc = zmq_msg_recv(eventMsg.handle(), _monitor_socket.handle(), 0); + if (rc == -1 && zmq_errno() == ETERM) + return false; + assert(rc != -1); + + } else { + return false; + } + +#if ZMQ_VERSION_MAJOR >= 4 + const char *data = static_cast(eventMsg.data()); + zmq_event_t msgEvent; + memcpy(&msgEvent.event, data, sizeof(uint16_t)); + data += sizeof(uint16_t); + memcpy(&msgEvent.value, data, sizeof(int32_t)); + zmq_event_t *event = &msgEvent; +#else + zmq_event_t *event = static_cast(eventMsg.data()); +#endif + +#ifdef ZMQ_NEW_MONITOR_EVENT_LAYOUT + zmq::message_t addrMsg; + int rc = zmq_msg_recv(addrMsg.handle(), _monitor_socket.handle(), 0); + if (rc == -1 && zmq_errno() == ETERM) { + return false; + } + + assert(rc != -1); + std::string address = addrMsg.to_string(); +#else + // Bit of a hack, but all events in the zmq_event_t union have the same layout so this will work for all event types. + std::string address = event->data.connected.addr; +#endif + +#ifdef ZMQ_EVENT_MONITOR_STOPPED + if (event->event == ZMQ_EVENT_MONITOR_STOPPED) { + on_monitor_stopped(); + return false; + } + +#endif + + switch (event->event) { + case ZMQ_EVENT_CONNECTED: + on_event_connected(*event, address.c_str()); + break; + case ZMQ_EVENT_CONNECT_DELAYED: + on_event_connect_delayed(*event, address.c_str()); + break; + case ZMQ_EVENT_CONNECT_RETRIED: + on_event_connect_retried(*event, address.c_str()); + break; + case ZMQ_EVENT_LISTENING: + on_event_listening(*event, address.c_str()); + break; + case ZMQ_EVENT_BIND_FAILED: + on_event_bind_failed(*event, address.c_str()); + break; + case ZMQ_EVENT_ACCEPTED: + on_event_accepted(*event, address.c_str()); + break; + case ZMQ_EVENT_ACCEPT_FAILED: + on_event_accept_failed(*event, address.c_str()); + break; + case ZMQ_EVENT_CLOSED: + on_event_closed(*event, address.c_str()); + break; + case ZMQ_EVENT_CLOSE_FAILED: + on_event_close_failed(*event, address.c_str()); + break; + case ZMQ_EVENT_DISCONNECTED: + on_event_disconnected(*event, address.c_str()); + break; +#if ZMQ_VERSION >= ZMQ_MAKE_VERSION(4, 3, 0) || (defined(ZMQ_BUILD_DRAFT_API) && ZMQ_VERSION >= ZMQ_MAKE_VERSION(4, 2, 3)) + case ZMQ_EVENT_HANDSHAKE_FAILED_NO_DETAIL: + on_event_handshake_failed_no_detail(*event, address.c_str()); + break; + case ZMQ_EVENT_HANDSHAKE_FAILED_PROTOCOL: + on_event_handshake_failed_protocol(*event, address.c_str()); + break; + case ZMQ_EVENT_HANDSHAKE_FAILED_AUTH: + on_event_handshake_failed_auth(*event, address.c_str()); + break; + case ZMQ_EVENT_HANDSHAKE_SUCCEEDED: + on_event_handshake_succeeded(*event, address.c_str()); + break; +#elif defined(ZMQ_BUILD_DRAFT_API) && ZMQ_VERSION >= ZMQ_MAKE_VERSION(4, 2, 1) + case ZMQ_EVENT_HANDSHAKE_FAILED: + on_event_handshake_failed(*event, address.c_str()); + break; + case ZMQ_EVENT_HANDSHAKE_SUCCEED: + on_event_handshake_succeed(*event, address.c_str()); + break; +#endif + default: + on_event_unknown(*event, address.c_str()); + break; + } + + return true; + } + + socket_ref monitor_socket() {return _monitor_socket;} + private: monitor_t(const monitor_t &) ZMQ_DELETED_FUNCTION; void operator=(const monitor_t &) ZMQ_DELETED_FUNCTION; @@ -2681,6 +2700,13 @@ template class poller_t } } + void remove(fd_t fd) + { + if (0 != zmq_poller_remove_fd(poller_ptr.get(), fd)) { + throw error_t(); + } + } + void modify(zmq::socket_ref socket, event_flags events) { if (0 @@ -2690,9 +2716,21 @@ template class poller_t } } - size_t wait_all(std::vector &poller_events, + void modify(fd_t fd, event_flags events) + { + if (0 + != zmq_poller_modify_fd(poller_ptr.get(), fd, + static_cast(events))) { + throw error_t(); + } + } + + template + size_t wait_all(Sequence &poller_events, const std::chrono::milliseconds timeout) { + static_assert(std::is_same::value, + "Sequence::value_type must be of poller_t::event_type"); int rc = zmq_poller_wait_all( poller_ptr.get(), reinterpret_cast(poller_events.data()), @@ -2716,7 +2754,7 @@ template class poller_t { int rc = zmq_poller_size(const_cast(poller_ptr.get())); ZMQ_ASSERT(rc >= 0); - return static_cast(std::max(rc, 0)); + return static_cast((std::max)(rc, 0)); } #endif @@ -2757,6 +2795,85 @@ inline std::ostream &operator<<(std::ostream &os, const message_t &msg) return os << msg.str(); } +#if defined(ZMQ_CPP11) && defined(ZMQ_HAVE_TIMERS) + +class timers +{ + public: + using id_t = int; + using fn_t = zmq_timer_fn; + +#if CPPZMQ_HAS_OPTIONAL + using timeout_result_t = std::optional; +#else + using timeout_result_t = detail::trivial_optional; +#endif + + timers() : _timers(zmq_timers_new()) + { + if (_timers == nullptr) + throw error_t(); + } + + timers(const timers &other) = delete; + timers &operator=(const timers &other) = delete; + + ~timers() + { + int rc = zmq_timers_destroy(&_timers); + ZMQ_ASSERT(rc == 0); + } + + id_t add(std::chrono::milliseconds interval, zmq_timer_fn handler, void *arg) + { + id_t timer_id = zmq_timers_add(_timers, interval.count(), handler, arg); + if (timer_id == -1) + throw zmq::error_t(); + return timer_id; + } + + void cancel(id_t timer_id) + { + int rc = zmq_timers_cancel(_timers, timer_id); + if (rc == -1) + throw zmq::error_t(); + } + + void set_interval(id_t timer_id, std::chrono::milliseconds interval) + { + int rc = zmq_timers_set_interval(_timers, timer_id, interval.count()); + if (rc == -1) + throw zmq::error_t(); + } + + void reset(id_t timer_id) + { + int rc = zmq_timers_reset(_timers, timer_id); + if (rc == -1) + throw zmq::error_t(); + } + + timeout_result_t timeout() const + { + int timeout = zmq_timers_timeout(_timers); + if (timeout == -1) + return timeout_result_t{}; + return std::chrono::milliseconds{timeout}; + } + + void execute() + { + int rc = zmq_timers_execute(_timers); + if (rc == -1) + throw zmq::error_t(); + } + + private: + void *_timers; +}; + +#endif // defined(ZMQ_CPP11) && defined(ZMQ_HAVE_TIMERS) + } // namespace zmq #endif // __ZMQ_HPP_INCLUDED__ diff --git a/3rdparty/cppzmq/zmq_addon.hpp b/3rdparty/cppzmq/zmq_addon.hpp index 958eec56d..c6b4462cb 100644 --- a/3rdparty/cppzmq/zmq_addon.hpp +++ b/3rdparty/cppzmq/zmq_addon.hpp @@ -34,7 +34,65 @@ #include #include #include -#endif + +namespace zmq +{ + // socket ref or native file descriptor for poller + class poller_ref_t + { + public: + enum RefType + { + RT_SOCKET, + RT_FD + }; + + poller_ref_t() : poller_ref_t(socket_ref{}) + {} + + poller_ref_t(const zmq::socket_ref& socket) : data{RT_SOCKET, socket, {}} + {} + + poller_ref_t(zmq::fd_t fd) : data{RT_FD, {}, fd} + {} + + size_t hash() const ZMQ_NOTHROW + { + std::size_t h = 0; + hash_combine(h, std::get<0>(data)); + hash_combine(h, std::get<1>(data)); + hash_combine(h, std::get<2>(data)); + return h; + } + + bool operator == (const poller_ref_t& o) const ZMQ_NOTHROW + { + return data == o.data; + } + + private: + template + static void hash_combine(std::size_t& seed, const T& v) ZMQ_NOTHROW + { + std::hash hasher; + seed ^= hasher(v) + 0x9e3779b9 + (seed<<6) + (seed>>2); + } + + std::tuple data; + + }; // class poller_ref_t + +} // namespace zmq + +// std::hash<> specialization for std::unordered_map +template <> struct std::hash +{ + size_t operator()(const zmq::poller_ref_t& ref) const ZMQ_NOTHROW + { + return ref.hash(); + } +}; +#endif // ZMQ_CPP11 namespace zmq { @@ -242,7 +300,7 @@ message_t encode(const Range &parts) if (part_size < (std::numeric_limits::max)()) { // small part - *buf++ = (unsigned char) part_size; + *buf++ = static_cast(part_size); } else { // big part *buf++ = (std::numeric_limits::max)(); @@ -683,10 +741,12 @@ class active_poller_t void add(zmq::socket_ref socket, event_flags events, handler_type handler) { + const poller_ref_t ref{socket}; + if (!handler) - throw std::invalid_argument("null handler in active_poller_t::add"); + throw std::invalid_argument("null handler in active_poller_t::add (socket)"); auto ret = handlers.emplace( - socket, std::make_shared(std::move(handler))); + ref, std::make_shared(std::move(handler))); if (!ret.second) throw error_t(EINVAL); // already added try { @@ -695,7 +755,28 @@ class active_poller_t } catch (...) { // rollback - handlers.erase(socket); + handlers.erase(ref); + throw; + } + } + + void add(fd_t fd, event_flags events, handler_type handler) + { + const poller_ref_t ref{fd}; + + if (!handler) + throw std::invalid_argument("null handler in active_poller_t::add (fd)"); + auto ret = handlers.emplace( + ref, std::make_shared(std::move(handler))); + if (!ret.second) + throw error_t(EINVAL); // already added + try { + base_poller.add(fd, events, ret.first->second.get()); + need_rebuild = true; + } + catch (...) { + // rollback + handlers.erase(ref); throw; } } @@ -707,11 +788,23 @@ class active_poller_t need_rebuild = true; } + void remove(fd_t fd) + { + base_poller.remove(fd); + handlers.erase(fd); + need_rebuild = true; + } + void modify(zmq::socket_ref socket, event_flags events) { base_poller.modify(socket, events); } + void modify(fd_t fd, event_flags events) + { + base_poller.modify(fd, events); + } + size_t wait(std::chrono::milliseconds timeout) { if (need_rebuild) { @@ -741,7 +834,9 @@ class active_poller_t bool need_rebuild{false}; poller_t base_poller{}; - std::unordered_map> handlers{}; + + std::unordered_map> handlers{}; + std::vector poller_events{}; std::vector> poller_handlers{}; }; // class active_poller_t diff --git a/3rdparty/doxygen-awesome-css/LICENSE b/3rdparty/doxygen-awesome-css/LICENSE new file mode 100644 index 000000000..8bf804a2a --- /dev/null +++ b/3rdparty/doxygen-awesome-css/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2021 - 2023 jothepro + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/3rdparty/doxygen-awesome-css/doxygen-awesome-darkmode-toggle.js b/3rdparty/doxygen-awesome-css/doxygen-awesome-darkmode-toggle.js new file mode 100644 index 000000000..440e4e08f --- /dev/null +++ b/3rdparty/doxygen-awesome-css/doxygen-awesome-darkmode-toggle.js @@ -0,0 +1,138 @@ +// SPDX-License-Identifier: MIT +/** + +Doxygen Awesome +https://github.com/jothepro/doxygen-awesome-css + +Copyright (c) 2021 - 2025 jothepro + +*/ + +class DoxygenAwesomeDarkModeToggle extends HTMLElement { + // SVG icons from https://fonts.google.com/icons + // Licensed under the Apache 2.0 license: + // https://www.apache.org/licenses/LICENSE-2.0.html + static lightModeIcon = `` + static darkModeIcon = `` + static title = "Toggle Light/Dark Mode" + + static prefersLightModeInDarkModeKey = "prefers-light-mode-in-dark-mode" + static prefersDarkModeInLightModeKey = "prefers-dark-mode-in-light-mode" + + static _staticConstructor = function() { + DoxygenAwesomeDarkModeToggle.enableDarkMode(DoxygenAwesomeDarkModeToggle.userPreference) + // Update the color scheme when the browsers preference changes + // without user interaction on the website. + window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', event => { + DoxygenAwesomeDarkModeToggle.onSystemPreferenceChanged() + }) + // Update the color scheme when the tab is made visible again. + // It is possible that the appearance was changed in another tab + // while this tab was in the background. + document.addEventListener("visibilitychange", visibilityState => { + if (document.visibilityState === 'visible') { + DoxygenAwesomeDarkModeToggle.onSystemPreferenceChanged() + } + }); + }() + + static init() { + $(function() { + $(document).ready(function() { + const toggleButton = document.createElement('doxygen-awesome-dark-mode-toggle') + toggleButton.title = DoxygenAwesomeDarkModeToggle.title + toggleButton.updateIcon() + + window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', event => { + toggleButton.updateIcon() + }) + document.addEventListener("visibilitychange", visibilityState => { + if (document.visibilityState === 'visible') { + toggleButton.updateIcon() + } + }); + + $(document).ready(function(){ + document.getElementById("MSearchBox").parentNode.appendChild(toggleButton) + }) + $(window).resize(function(){ + document.getElementById("MSearchBox").parentNode.appendChild(toggleButton) + }) + }) + }) + } + + constructor() { + super(); + this.onclick=this.toggleDarkMode + } + + /** + * @returns `true` for dark-mode, `false` for light-mode system preference + */ + static get systemPreference() { + return window.matchMedia('(prefers-color-scheme: dark)').matches + } + + /** + * @returns `true` for dark-mode, `false` for light-mode user preference + */ + static get userPreference() { + return (!DoxygenAwesomeDarkModeToggle.systemPreference && localStorage.getItem(DoxygenAwesomeDarkModeToggle.prefersDarkModeInLightModeKey)) || + (DoxygenAwesomeDarkModeToggle.systemPreference && !localStorage.getItem(DoxygenAwesomeDarkModeToggle.prefersLightModeInDarkModeKey)) + } + + static set userPreference(userPreference) { + DoxygenAwesomeDarkModeToggle.darkModeEnabled = userPreference + if(!userPreference) { + if(DoxygenAwesomeDarkModeToggle.systemPreference) { + localStorage.setItem(DoxygenAwesomeDarkModeToggle.prefersLightModeInDarkModeKey, true) + } else { + localStorage.removeItem(DoxygenAwesomeDarkModeToggle.prefersDarkModeInLightModeKey) + } + } else { + if(!DoxygenAwesomeDarkModeToggle.systemPreference) { + localStorage.setItem(DoxygenAwesomeDarkModeToggle.prefersDarkModeInLightModeKey, true) + } else { + localStorage.removeItem(DoxygenAwesomeDarkModeToggle.prefersLightModeInDarkModeKey) + } + } + DoxygenAwesomeDarkModeToggle.onUserPreferenceChanged() + } + + static enableDarkMode(enable) { + if(enable) { + DoxygenAwesomeDarkModeToggle.darkModeEnabled = true + document.documentElement.classList.add("dark-mode") + document.documentElement.classList.remove("light-mode") + } else { + DoxygenAwesomeDarkModeToggle.darkModeEnabled = false + document.documentElement.classList.remove("dark-mode") + document.documentElement.classList.add("light-mode") + } + } + + static onSystemPreferenceChanged() { + DoxygenAwesomeDarkModeToggle.darkModeEnabled = DoxygenAwesomeDarkModeToggle.userPreference + DoxygenAwesomeDarkModeToggle.enableDarkMode(DoxygenAwesomeDarkModeToggle.darkModeEnabled) + } + + static onUserPreferenceChanged() { + DoxygenAwesomeDarkModeToggle.enableDarkMode(DoxygenAwesomeDarkModeToggle.darkModeEnabled) + } + + toggleDarkMode() { + DoxygenAwesomeDarkModeToggle.userPreference = !DoxygenAwesomeDarkModeToggle.userPreference + this.updateIcon() + } + + updateIcon() { + if(DoxygenAwesomeDarkModeToggle.darkModeEnabled) { + this.innerHTML = DoxygenAwesomeDarkModeToggle.darkModeIcon + } else { + this.innerHTML = DoxygenAwesomeDarkModeToggle.lightModeIcon + } + } +} + +customElements.define("doxygen-awesome-dark-mode-toggle", DoxygenAwesomeDarkModeToggle); diff --git a/3rdparty/doxygen-awesome-css/doxygen-awesome-sidebar-only.css b/3rdparty/doxygen-awesome-css/doxygen-awesome-sidebar-only.css new file mode 100644 index 000000000..f7c644d6e --- /dev/null +++ b/3rdparty/doxygen-awesome-css/doxygen-awesome-sidebar-only.css @@ -0,0 +1,105 @@ +/* SPDX-License-Identifier: MIT */ +/** + +Doxygen Awesome +https://github.com/jothepro/doxygen-awesome-css + +Copyright (c) 2021 - 2025 jothepro + + */ + +html { + /* side nav width. MUST be = `TREEVIEW_WIDTH`. + * Make sure it is wide enough to contain the page title (logo + title + version) + */ + --side-nav-fixed-width: 335px; + --menu-display: none; + + --top-height: 120px; + --toc-sticky-top: -25px; + --toc-max-height: calc(100vh - 2 * var(--spacing-medium) - 25px); +} + +#projectname { + white-space: nowrap; +} + + +@media screen and (min-width: 768px) { + html { + --searchbar-background: var(--page-background-color); + } + + #side-nav { + min-width: var(--side-nav-fixed-width); + max-width: var(--side-nav-fixed-width); + top: var(--top-height); + overflow: visible; + } + + #nav-tree, #side-nav { + height: calc(100vh - var(--top-height)) !important; + } + + #top { + display: block; + border-bottom: none; + height: var(--top-height); + margin-bottom: calc(0px - var(--top-height)); + max-width: var(--side-nav-fixed-width); + overflow: hidden; + background: var(--side-nav-background); + } + + #main-nav { + float: left; + padding-right: 0; + } + + .ui-resizable-handle { + display: none; + } + + .ui-resizable-e { + width: 0; + } + + #nav-path { + position: fixed; + right: 0; + left: calc(var(--side-nav-fixed-width) + 1px); + bottom: 0; + width: auto; + } + + #doc-content { + height: calc(100vh - 31px) !important; + padding-bottom: calc(3 * var(--spacing-large)); + padding-top: calc(var(--top-height) - 80px); + box-sizing: border-box; + margin-left: var(--side-nav-fixed-width) !important; + } + + #MSearchBox { + width: calc(var(--side-nav-fixed-width) - calc(2 * var(--spacing-medium))); + } + + #MSearchField { + width: calc(var(--side-nav-fixed-width) - calc(2 * var(--spacing-medium)) - 65px); + } + + #MSearchResultsWindow { + left: var(--spacing-medium) !important; + right: auto; + } + + #nav-sync { + bottom: 4px; + right: auto; + left: 300px; + width: 35px; + top: auto !important; + user-select: none; + position: fixed + } +} diff --git a/3rdparty/doxygen-awesome-css/doxygen-awesome.css b/3rdparty/doxygen-awesome-css/doxygen-awesome.css new file mode 100644 index 000000000..f992c2329 --- /dev/null +++ b/3rdparty/doxygen-awesome-css/doxygen-awesome.css @@ -0,0 +1,3020 @@ +/* SPDX-License-Identifier: MIT */ +/** + +Doxygen Awesome +https://github.com/jothepro/doxygen-awesome-css + +Copyright (c) 2021 - 2025 jothepro + +*/ + +html { + /* primary theme color. This will affect the entire websites color scheme: links, arrows, labels, ... */ + --primary-color: #1779c4; + --primary-dark-color: #335c80; + --primary-light-color: #70b1e9; + --on-primary-color: #ffffff; + + --link-color: var(--primary-color); + + /* page base colors */ + --page-background-color: #ffffff; + --page-foreground-color: #2f4153; + --page-secondary-foreground-color: #6f7e8e; + + /* color for all separators on the website: hr, borders, ... */ + --separator-color: #dedede; + + /* border radius for all rounded components. Will affect many components, like dropdowns, memitems, codeblocks, ... */ + --border-radius-large: 10px; + --border-radius-small: 5px; + --border-radius-medium: 8px; + + /* default spacings. Most components reference these values for spacing, to provide uniform spacing on the page. */ + --spacing-small: 5px; + --spacing-medium: 10px; + --spacing-large: 16px; + --spacing-xlarge: 20px; + + /* default box shadow used for raising an element above the normal content. Used in dropdowns, search result, ... */ + --box-shadow: 0 2px 8px 0 rgba(0,0,0,.075); + + --odd-color: rgba(0,0,0,.028); + + /* font-families. will affect all text on the website + * font-family: the normal font for text, headlines, menus + * font-family-monospace: used for preformatted text in memtitle, code, fragments + */ + --font-family: -apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen,Ubuntu,Cantarell,Fira Sans,Droid Sans,Helvetica Neue,sans-serif; + --font-family-monospace: ui-monospace,SFMono-Regular,SF Mono,Menlo,Consolas,Liberation Mono,monospace; + + /* font sizes */ + --page-font-size: 15.6px; + --navigation-font-size: 14.4px; + --toc-font-size: 13.4px; + --code-font-size: 14px; /* affects code, fragment */ + --title-font-size: 22px; + + /* content text properties. These only affect the page content, not the navigation or any other ui elements */ + --content-line-height: 27px; + /* The content is centered and constraint in it's width. To make the content fill the whole page, set the variable to auto.*/ + --content-maxwidth: 1050px; + --table-line-height: 24px; + --toc-sticky-top: var(--spacing-medium); + --toc-width: 200px; + --toc-max-height: calc(100vh - 2 * var(--spacing-medium) - 85px); + + /* colors for various content boxes: @warning, @note, @deprecated @bug */ + --warning-color: #faf3d8; + --warning-color-dark: #f3a600; + --warning-color-darker: #5f4204; + --note-color: #e4f3ff; + --note-color-dark: #1879C4; + --note-color-darker: #274a5c; + --todo-color: #e4dafd; + --todo-color-dark: #5b2bdd; + --todo-color-darker: #2a0d72; + --deprecated-color: #ecf0f3; + --deprecated-color-dark: #5b6269; + --deprecated-color-darker: #43454a; + --bug-color: #f8d1cc; + --bug-color-dark: #b61825; + --bug-color-darker: #75070f; + --invariant-color: #d8f1e3; + --invariant-color-dark: #44b86f; + --invariant-color-darker: #265532; + + /* blockquote colors */ + --blockquote-background: #f8f9fa; + --blockquote-foreground: #636568; + + /* table colors */ + --tablehead-background: #f1f1f1; + --tablehead-foreground: var(--page-foreground-color); + + /* menu-display: block | none + * Visibility of the top navigation on screens >= 768px. On smaller screen the menu is always visible. + * `GENERATE_TREEVIEW` MUST be enabled! + */ + --menu-display: block; + + --menu-focus-foreground: var(--on-primary-color); + --menu-focus-background: var(--primary-color); + --menu-selected-background: rgba(0,0,0,.05); + + + --header-background: var(--page-background-color); + --header-foreground: var(--page-foreground-color); + + /* searchbar colors */ + --searchbar-background: var(--side-nav-background); + --searchbar-foreground: var(--page-foreground-color); + + /* searchbar size + * (`searchbar-width` is only applied on screens >= 768px. + * on smaller screens the searchbar will always fill the entire screen width) */ + --searchbar-height: 33px; + --searchbar-width: 210px; + --searchbar-border-radius: var(--searchbar-height); + + /* code block colors */ + --code-background: #f5f5f5; + --code-foreground: var(--page-foreground-color); + + /* fragment colors */ + --fragment-background: #F8F9FA; + --fragment-foreground: #37474F; + --fragment-keyword: #bb6bb2; + --fragment-keywordtype: #8258b3; + --fragment-keywordflow: #d67c3b; + --fragment-token: #438a59; + --fragment-comment: #969696; + --fragment-link: #5383d6; + --fragment-preprocessor: #46aaa5; + --fragment-linenumber-color: #797979; + --fragment-linenumber-background: #f4f4f5; + --fragment-linenumber-border: #e3e5e7; + --fragment-lineheight: 20px; + + /* sidebar navigation (treeview) colors */ + --side-nav-background: #fbfbfb; + --side-nav-foreground: var(--page-foreground-color); + --side-nav-arrow-opacity: 0; + --side-nav-arrow-hover-opacity: 0.9; + + --toc-background: var(--side-nav-background); + --toc-foreground: var(--side-nav-foreground); + + /* height of an item in any tree / collapsible table */ + --tree-item-height: 30px; + + --memname-font-size: var(--code-font-size); + --memtitle-font-size: 18px; + + --webkit-scrollbar-size: 7px; + --webkit-scrollbar-padding: 4px; + --webkit-scrollbar-color: var(--separator-color); + + --animation-duration: .12s +} + +@media screen and (max-width: 767px) { + html { + --page-font-size: 16px; + --navigation-font-size: 16px; + --toc-font-size: 15px; + --code-font-size: 15px; /* affects code, fragment */ + --title-font-size: 22px; + } +} + +@media (prefers-color-scheme: dark) { + html:not(.light-mode) { + color-scheme: dark; + + --primary-color: #1982d2; + --primary-dark-color: #86a9c4; + --primary-light-color: #4779ac; + + --box-shadow: 0 2px 8px 0 rgba(0,0,0,.35); + + --odd-color: rgba(100,100,100,.06); + + --menu-selected-background: rgba(0,0,0,.4); + + --page-background-color: #1C1D1F; + --page-foreground-color: #d2dbde; + --page-secondary-foreground-color: #859399; + --separator-color: #38393b; + --side-nav-background: #252628; + + --code-background: #2a2c2f; + + --tablehead-background: #2a2c2f; + + --blockquote-background: #222325; + --blockquote-foreground: #7e8c92; + + --warning-color: #3b2e04; + --warning-color-dark: #f1b602; + --warning-color-darker: #ceb670; + --note-color: #163750; + --note-color-dark: #1982D2; + --note-color-darker: #dcf0fa; + --todo-color: #2a2536; + --todo-color-dark: #7661b3; + --todo-color-darker: #ae9ed6; + --deprecated-color: #2e323b; + --deprecated-color-dark: #738396; + --deprecated-color-darker: #abb0bd; + --bug-color: #2e1917; + --bug-color-dark: #ad2617; + --bug-color-darker: #f5b1aa; + --invariant-color: #303a35; + --invariant-color-dark: #76ce96; + --invariant-color-darker: #cceed5; + + --fragment-background: #282c34; + --fragment-foreground: #dbe4eb; + --fragment-keyword: #cc99cd; + --fragment-keywordtype: #ab99cd; + --fragment-keywordflow: #e08000; + --fragment-token: #7ec699; + --fragment-comment: #999999; + --fragment-link: #98c0e3; + --fragment-preprocessor: #65cabe; + --fragment-linenumber-color: #cccccc; + --fragment-linenumber-background: #35393c; + --fragment-linenumber-border: #1f1f1f; + } +} + +/* dark mode variables are defined twice, to support both the dark-mode without and with doxygen-awesome-darkmode-toggle.js */ +html.dark-mode { + color-scheme: dark; + + --primary-color: #1982d2; + --primary-dark-color: #86a9c4; + --primary-light-color: #4779ac; + + --box-shadow: 0 2px 8px 0 rgba(0,0,0,.30); + + --odd-color: rgba(100,100,100,.06); + + --menu-selected-background: rgba(0,0,0,.4); + + --page-background-color: #1C1D1F; + --page-foreground-color: #d2dbde; + --page-secondary-foreground-color: #859399; + --separator-color: #38393b; + --side-nav-background: #252628; + + --code-background: #2a2c2f; + + --tablehead-background: #2a2c2f; + + --blockquote-background: #222325; + --blockquote-foreground: #7e8c92; + + --warning-color: #3b2e04; + --warning-color-dark: #f1b602; + --warning-color-darker: #ceb670; + --note-color: #163750; + --note-color-dark: #1982D2; + --note-color-darker: #dcf0fa; + --todo-color: #2a2536; + --todo-color-dark: #7661b3; + --todo-color-darker: #ae9ed6; + --deprecated-color: #2e323b; + --deprecated-color-dark: #738396; + --deprecated-color-darker: #abb0bd; + --bug-color: #2e1917; + --bug-color-dark: #ad2617; + --bug-color-darker: #f5b1aa; + --invariant-color: #303a35; + --invariant-color-dark: #76ce96; + --invariant-color-darker: #cceed5; + + --fragment-background: #282c34; + --fragment-foreground: #dbe4eb; + --fragment-keyword: #cc99cd; + --fragment-keywordtype: #ab99cd; + --fragment-keywordflow: #e08000; + --fragment-token: #7ec699; + --fragment-comment: #999999; + --fragment-link: #98c0e3; + --fragment-preprocessor: #65cabe; + --fragment-linenumber-color: #cccccc; + --fragment-linenumber-background: #35393c; + --fragment-linenumber-border: #1f1f1f; +} + +body { + color: var(--page-foreground-color); + background-color: var(--page-background-color); + font-size: var(--page-font-size); +} + +body, table, div, p, dl, #nav-tree .label, #nav-tree a, .title, +.sm-dox a, .sm-dox a:hover, .sm-dox a:focus, #projectname, +.SelectItem, #MSearchField, .navpath li.navelem a, +.navpath li.navelem a:hover, p.reference, p.definition, div.toc li, div.toc h3, +#page-nav ul.page-outline li a { + font-family: var(--font-family); +} + +h1, h2, h3, h4, h5 { + margin-top: 1em; + font-weight: 600; + line-height: initial; +} + +p, div, table, dl, p.reference, p.definition { + font-size: var(--page-font-size); +} + +p.reference, p.definition { + color: var(--page-secondary-foreground-color); +} + +a:link, a:visited, a:hover, a:focus, a:active { + color: var(--link-color) !important; + font-weight: 500; + background: none; +} + +a:hover { + text-decoration: underline; +} + +a.anchor { + scroll-margin-top: var(--spacing-large); + display: block; +} + +/* + Title and top navigation + */ + +#top { + background: var(--header-background); + border-bottom: 1px solid var(--separator-color); + position: relative; + z-index: 99; +} + +@media screen and (min-width: 768px) { + #top { + display: flex; + flex-wrap: wrap; + justify-content: space-between; + align-items: center; + } +} + +#main-nav { + flex-grow: 5; + padding: var(--spacing-small) var(--spacing-medium); + border-bottom: 0; +} + +#titlearea { + width: auto; + padding: var(--spacing-medium) var(--spacing-large); + background: none; + color: var(--header-foreground); + border-bottom: none; +} + +@media screen and (max-width: 767px) { + #titlearea { + padding-bottom: var(--spacing-small); + } +} + +#titlearea table tbody tr { + height: auto !important; +} + +#projectname { + font-size: var(--title-font-size); + font-weight: 600; +} + +#projectnumber { + font-family: inherit; + font-size: 60%; +} + +#projectbrief { + font-family: inherit; + font-size: 80%; +} + +#projectlogo { + vertical-align: middle; +} + +#projectlogo img { + max-height: calc(var(--title-font-size) * 2); + margin-right: var(--spacing-small); +} + +.sm-dox, .tabs, .tabs2, .tabs3 { + background: none; + padding: 0; +} + +.tabs, .tabs2, .tabs3 { + border-bottom: 1px solid var(--separator-color); + margin-bottom: -1px; +} + +.main-menu-btn-icon, .main-menu-btn-icon:before, .main-menu-btn-icon:after { + background: var(--page-secondary-foreground-color); +} + +@media screen and (max-width: 767px) { + .sm-dox a span.sub-arrow { + background: var(--code-background); + } + + #main-menu a.has-submenu span.sub-arrow { + color: var(--page-secondary-foreground-color); + border-radius: var(--border-radius-medium); + } + + #main-menu a.has-submenu:hover span.sub-arrow { + color: var(--page-foreground-color); + } +} + +@media screen and (min-width: 768px) { + .sm-dox li, .tablist li { + display: var(--menu-display); + } + + .sm-dox a span.sub-arrow { + top: 15px; + right: 10px; + box-sizing: content-box; + padding: 0; + margin: 0; + display: inline-block; + width: 5px; + height: 5px; + transform: rotate(45deg); + border-width: 0; + border-right: 2px solid var(--header-foreground); + border-bottom: 2px solid var(--header-foreground); + background: none; + } + + .sm-dox a:hover span.sub-arrow { + border-color: var(--menu-focus-foreground); + background: none; + } + + .sm-dox ul a span.sub-arrow { + transform: rotate(-45deg); + border-width: 0; + border-right: 2px solid var(--header-foreground); + border-bottom: 2px solid var(--header-foreground); + } + + .sm-dox ul a:hover span.sub-arrow { + border-color: var(--menu-focus-foreground); + background: none; + } +} + +.sm-dox ul { + background: var(--page-background-color); + box-shadow: var(--box-shadow); + border: 1px solid var(--separator-color); + border-radius: var(--border-radius-medium) !important; + padding: var(--spacing-small); + animation: ease-out 150ms slideInMenu; +} + +@keyframes slideInMenu { + from { + opacity: 0; + transform: translate(0px, -2px); + } + + to { + opacity: 1; + transform: translate(0px, 0px); + } +} + +.sm-dox ul a { + color: var(--page-foreground-color) !important; + background: none; + font-size: var(--navigation-font-size); +} + +.sm-dox>li>ul:after { + border-bottom-color: var(--page-background-color) !important; +} + +.sm-dox>li>ul:before { + border-bottom-color: var(--separator-color) !important; +} + +.sm-dox ul a:hover, .sm-dox ul a:active, .sm-dox ul a:focus { + font-size: var(--navigation-font-size) !important; + color: var(--menu-focus-foreground) !important; + text-shadow: none; + background-color: var(--menu-focus-background); + border-radius: var(--border-radius-small) !important; +} + +.sm-dox a, .sm-dox a:focus, .tablist li, .tablist li a, .tablist li.current a { + text-shadow: none; + background: transparent; + background-image: none !important; + color: var(--header-foreground) !important; + font-weight: normal; + font-size: var(--navigation-font-size); + border-radius: var(--border-radius-small) !important; +} + +.sm-dox a:focus { + outline: auto; +} + +.sm-dox a:hover, .sm-dox a:active, .tablist li a:hover { + text-shadow: none; + font-weight: normal; + background: var(--menu-focus-background); + color: var(--menu-focus-foreground) !important; + border-radius: var(--border-radius-small) !important; + font-size: var(--navigation-font-size); +} + +.tablist li.current { + border-radius: var(--border-radius-small); + background: var(--menu-selected-background); +} + +.tablist li { + margin: var(--spacing-small) 0 var(--spacing-small) var(--spacing-small); +} + +.tablist a { + padding: 0 var(--spacing-large); +} + + +/* + Search box + */ + +#MSearchBox { + height: var(--searchbar-height); + background: var(--searchbar-background); + border-radius: var(--searchbar-border-radius); + border: 1px solid var(--separator-color); + overflow: hidden; + width: var(--searchbar-width); + position: relative; + box-shadow: none; + display: block; + margin-top: 0; + margin-right: 0; +} + +@media (min-width: 768px) { + .sm-dox li { + padding: 0; + } +} + +/* until Doxygen 1.9.4 */ +.left img#MSearchSelect { + left: 0; + user-select: none; + padding-left: 8px; +} + +/* Doxygen 1.9.5 */ +.left span#MSearchSelect { + left: 0; + user-select: none; + margin-left: 8px; + padding: 0; +} + +.left #MSearchSelect[src$=".png"] { + padding-left: 0 +} + +/* Doxygen 1.14.0 */ +.search-icon::before { + background: none; + top: 5px; +} + +.search-icon::after { + background: none; + top: 12px; +} + +.SelectionMark { + user-select: none; +} + +.tabs .left #MSearchSelect { + padding-left: 0; +} + +.tabs #MSearchBox { + position: absolute; + right: var(--spacing-medium); +} + +@media screen and (max-width: 767px) { + .tabs #MSearchBox { + position: relative; + right: 0; + margin-left: var(--spacing-medium); + margin-top: 0; + } +} + +#MSearchSelectWindow, #MSearchResultsWindow { + z-index: 9999; +} + +#MSearchBox.MSearchBoxActive { + border-color: var(--primary-color); + box-shadow: inset 0 0 0 1px var(--primary-color); +} + +#main-menu > li:last-child { + margin-right: 0; +} + +@media screen and (max-width: 767px) { + #main-menu > li:last-child { + height: 50px; + } +} + +#MSearchField { + font-size: var(--navigation-font-size); + height: calc(var(--searchbar-height) - 2px); + background: transparent; + width: calc(var(--searchbar-width) - 64px); +} + +.MSearchBoxActive #MSearchField { + color: var(--searchbar-foreground); +} + +#MSearchSelect { + top: calc(calc(var(--searchbar-height) / 2) - 11px); +} + +#MSearchBox span.left, #MSearchBox span.right { + background: none; + background-image: none; +} + +#MSearchBox span.right { + padding-top: calc(calc(var(--searchbar-height) / 2) - 12px); + position: absolute; + right: var(--spacing-small); +} + +.tabs #MSearchBox span.right { + top: calc(calc(var(--searchbar-height) / 2) - 12px); +} + +@keyframes slideInSearchResults { + from { + opacity: 0; + transform: translate(0, 15px); + } + + to { + opacity: 1; + transform: translate(0, 20px); + } +} + +#MSearchResultsWindow { + left: auto !important; + right: var(--spacing-medium); + border-radius: var(--border-radius-large); + border: 1px solid var(--separator-color); + transform: translate(0, 20px); + box-shadow: var(--box-shadow); + animation: ease-out 280ms slideInSearchResults; + background: var(--page-background-color); +} + +iframe#MSearchResults { + margin: 4px; +} + +iframe { + color-scheme: normal; +} + +@media (prefers-color-scheme: dark) { + html:not(.light-mode) iframe#MSearchResults { + filter: invert() hue-rotate(180deg); + } +} + +html.dark-mode iframe#MSearchResults { + filter: invert() hue-rotate(180deg); +} + +#MSearchResults .SRPage { + background-color: transparent; +} + +#MSearchResults .SRPage .SREntry { + font-size: 10pt; + padding: var(--spacing-small) var(--spacing-medium); +} + +#MSearchSelectWindow { + border: 1px solid var(--separator-color); + border-radius: var(--border-radius-medium); + box-shadow: var(--box-shadow); + background: var(--page-background-color); + padding-top: var(--spacing-small); + padding-bottom: var(--spacing-small); +} + +#MSearchSelectWindow a.SelectItem { + font-size: var(--navigation-font-size); + line-height: var(--content-line-height); + margin: 0 var(--spacing-small); + border-radius: var(--border-radius-small); + color: var(--page-foreground-color) !important; + font-weight: normal; +} + +#MSearchSelectWindow a.SelectItem:hover { + background: var(--menu-focus-background); + color: var(--menu-focus-foreground) !important; +} + +@media screen and (max-width: 767px) { + #MSearchBox { + margin-top: var(--spacing-medium); + margin-bottom: var(--spacing-medium); + width: calc(100vw - 30px); + } + + #main-menu > li:last-child { + float: none !important; + } + + #MSearchField { + width: calc(100vw - 110px); + } + + @keyframes slideInSearchResultsMobile { + from { + opacity: 0; + transform: translate(0, 15px); + } + + to { + opacity: 1; + transform: translate(0, 20px); + } + } + + #MSearchResultsWindow { + left: var(--spacing-medium) !important; + right: var(--spacing-medium); + overflow: auto; + transform: translate(0, 20px); + animation: ease-out 280ms slideInSearchResultsMobile; + width: auto !important; + } + + /* + * Overwrites for fixing the searchbox on mobile in doxygen 1.9.2 + */ + label.main-menu-btn ~ #searchBoxPos1 { + top: 3px !important; + right: 6px !important; + left: 45px; + display: flex; + } + + label.main-menu-btn ~ #searchBoxPos1 > #MSearchBox { + margin-top: 0; + margin-bottom: 0; + flex-grow: 2; + float: left; + } +} + +/* + Tree view + */ + +#side-nav { + min-width: 8px; + max-width: 50vw; +} + + +#nav-tree, #top { + border-right: 1px solid var(--separator-color); +} + +@media screen and (max-width: 767px) { + #side-nav { + display: none; + } + + #doc-content { + margin-left: 0 !important; + } + + #top { + border-right: none; + } +} + +#nav-tree { + background: var(--side-nav-background); + margin-right: -1px; + padding: 0; +} + +#nav-tree .label { + font-size: var(--navigation-font-size); + line-height: var(--tree-item-height); +} + +#nav-tree span.label a:hover { + background: none; +} + +#nav-tree .item { + height: var(--tree-item-height); + line-height: var(--tree-item-height); + overflow: hidden; + text-overflow: ellipsis; + margin: 0; + padding: 0; +} + +#nav-tree-contents { + margin: 0; +} + +#main-menu > li:last-child { + height: auto; +} + +#nav-tree .item > a:focus { + outline: none; +} + +#nav-sync { + bottom: var(--spacing-medium); + right: var(--spacing-medium) !important; + top: auto !important; + user-select: none; +} + +div.nav-sync-icon { + border: 1px solid var(--separator-color); + border-radius: var(--border-radius-medium); + background: var(--page-background-color); + width: 30px; + height: 20px; +} + +div.nav-sync-icon:hover { + background: var(--page-background-color); +} + +span.sync-icon-left, div.nav-sync-icon:hover span.sync-icon-left { + border-left: 2px solid var(--primary-color); + border-top: 2px solid var(--primary-color); + top: 5px; + left: 6px; +} +span.sync-icon-right, div.nav-sync-icon:hover span.sync-icon-right { + border-right: 2px solid var(--primary-color); + border-bottom: 2px solid var(--primary-color); + top: 5px; + left: initial; + right: 6px; +} + +div.nav-sync-icon.active::after, div.nav-sync-icon.active:hover::after { + border-top: 2px solid var(--primary-color); + top: 9px; + left: 6px; + width: 19px; +} + +#nav-tree .selected { + text-shadow: none; + background-image: none; + background-color: transparent; + position: relative; + color: var(--primary-color) !important; + font-weight: 500; +} + +#nav-tree .selected::after { + content: ""; + position: absolute; + top: 1px; + bottom: 1px; + left: 0; + width: 4px; + border-radius: 0 var(--border-radius-small) var(--border-radius-small) 0; + background: var(--primary-color); +} + + +#nav-tree a { + color: var(--side-nav-foreground) !important; + font-weight: normal; +} + +#nav-tree a:focus { + outline-style: auto; +} + +#nav-tree .arrow { + opacity: var(--side-nav-arrow-opacity); + background: none; +} + +#nav-tree span.arrowhead { + margin: 0 0 1px 2px; +} + +span.arrowhead { + border-color: var(--primary-light-color); +} + +.selected span.arrowhead { + border-color: var(--primary-color); +} + +#nav-tree-contents > ul > li:first-child > div > a { + opacity: 0; + pointer-events: none; +} + +.contents .arrow { + color: inherit; + cursor: pointer; + font-size: 45%; + vertical-align: middle; + margin-right: 2px; + font-family: serif; + height: auto; + padding-bottom: 4px; +} + +#nav-tree div.item:hover .arrow, #nav-tree a:focus .arrow { + opacity: var(--side-nav-arrow-hover-opacity); +} + +#nav-tree .selected a { + color: var(--primary-color) !important; + font-weight: bolder; + font-weight: 600; +} + +.ui-resizable-e { + background: none; +} + +.ui-resizable-e:hover { + background: var(--separator-color); +} + +/* + Contents + */ + +div.header { + border-bottom: 1px solid var(--separator-color); + background: none; + background-image: none; +} + +@media screen and (min-width: 1000px) { + #doc-content > div > div.contents, + .PageDoc > div.contents { + display: flex; + flex-direction: row-reverse; + flex-wrap: nowrap; + align-items: flex-start; + } + + div.contents .textblock { + min-width: 200px; + flex-grow: 1; + } +} + +div.contents, div.header .title, div.header .summary { + max-width: var(--content-maxwidth); +} + +div.contents, div.header .title { + line-height: initial; + margin: calc(var(--spacing-medium) + .2em) auto var(--spacing-medium) auto; +} + +div.header .summary { + margin: var(--spacing-medium) auto 0 auto; +} + +div.headertitle { + padding: 0; +} + +div.header .title { + font-weight: 600; + font-size: 225%; + padding: var(--spacing-medium) var(--spacing-xlarge); + word-break: break-word; +} + +div.header .summary { + width: auto; + display: block; + float: none; + padding: 0 var(--spacing-large); +} + +td.memSeparator { + border-color: var(--separator-color); +} + +span.mlabel { + background: var(--primary-color); + color: var(--on-primary-color); + border: none; + padding: 4px 9px; + border-radius: var(--border-radius-large); + margin-right: var(--spacing-medium); +} + +span.mlabel:last-of-type { + margin-right: 2px; +} + +div.contents { + padding: 0 var(--spacing-xlarge); +} + +div.contents p, div.contents li { + line-height: var(--content-line-height); +} + +div.contents div.dyncontent { + margin: var(--spacing-medium) 0; +} + +@media screen and (max-width: 767px) { + div.contents { + padding: 0 var(--spacing-large); + } + + div.header .title { + padding: var(--spacing-medium) var(--spacing-large); + } +} + +@media (prefers-color-scheme: dark) { + html:not(.light-mode) div.contents div.dyncontent img, + html:not(.light-mode) div.contents center img, + html:not(.light-mode) div.contents > table img, + html:not(.light-mode) div.contents div.dyncontent iframe, + html:not(.light-mode) div.contents center iframe, + html:not(.light-mode) div.contents table iframe, + html:not(.light-mode) div.contents .dotgraph iframe { + filter: brightness(89%) hue-rotate(180deg) invert(); + } +} + +html.dark-mode div.contents div.dyncontent img, +html.dark-mode div.contents center img, +html.dark-mode div.contents > table img, +html.dark-mode div.contents div.dyncontent iframe, +html.dark-mode div.contents center iframe, +html.dark-mode div.contents table iframe, +html.dark-mode div.contents .dotgraph iframe + { + filter: brightness(89%) hue-rotate(180deg) invert(); +} + +td h2.groupheader, h2.groupheader { + border-bottom: 0px; + color: var(--page-foreground-color); + box-shadow: + 100px 0 var(--page-background-color), + -100px 0 var(--page-background-color), + 100px 0.75px var(--separator-color), + -100px 0.75px var(--separator-color), + 500px 0 var(--page-background-color), + -500px 0 var(--page-background-color), + 500px 0.75px var(--separator-color), + -500px 0.75px var(--separator-color), + 900px 0 var(--page-background-color), + -900px 0 var(--page-background-color), + 900px 0.75px var(--separator-color), + -900px 0.75px var(--separator-color), + 1400px 0 var(--page-background-color), + -1400px 0 var(--page-background-color), + 1400px 0.75px var(--separator-color), + -1400px 0.75px var(--separator-color), + 1900px 0 var(--page-background-color), + -1900px 0 var(--page-background-color), + 1900px 0.75px var(--separator-color), + -1900px 0.75px var(--separator-color); +} + +blockquote { + margin: 0 var(--spacing-medium) 0 var(--spacing-medium); + padding: var(--spacing-small) var(--spacing-large); + background: var(--blockquote-background); + color: var(--blockquote-foreground); + border-left: 0; + overflow: visible; + border-radius: var(--border-radius-medium); + overflow: visible; + position: relative; +} + +blockquote::before, blockquote::after { + font-weight: bold; + font-family: serif; + font-size: 360%; + opacity: .15; + position: absolute; +} + +blockquote::before { + content: "“"; + left: -10px; + top: 4px; +} + +blockquote::after { + content: "”"; + right: -8px; + bottom: -25px; +} + +blockquote p { + margin: var(--spacing-small) 0 var(--spacing-medium) 0; +} +.paramname, .paramname em { + font-weight: 600; + color: var(--primary-dark-color); +} + +.paramname > code { + border: 0; +} + +table.params .paramname { + font-weight: 600; + font-family: var(--font-family-monospace); + font-size: var(--code-font-size); + padding-right: var(--spacing-small); + line-height: var(--table-line-height); +} + +h1.glow, h2.glow, h3.glow, h4.glow, h5.glow, h6.glow { + text-shadow: 0 0 15px var(--primary-light-color); +} + +.alphachar a { + color: var(--page-foreground-color); +} + +.dotgraph { + max-width: 100%; + overflow-x: scroll; +} + +.dotgraph .caption { + position: sticky; + left: 0; +} + +/* Wrap Graphviz graphs with the `interactive_dotgraph` class if `INTERACTIVE_SVG = YES` */ +.interactive_dotgraph .dotgraph iframe { + max-width: 100%; +} + +/* + Table of Contents + */ + +div.contents .toc { + max-height: var(--toc-max-height); + min-width: var(--toc-width); + border: 0; + border-left: 1px solid var(--separator-color); + border-radius: 0; + background-color: var(--page-background-color); + box-shadow: none; + position: sticky; + top: var(--toc-sticky-top); + padding: 0 var(--spacing-large); + margin: var(--spacing-small) 0 var(--spacing-large) var(--spacing-large); +} + +div.toc h3 { + color: var(--toc-foreground); + font-size: var(--navigation-font-size); + margin: var(--spacing-large) 0 var(--spacing-medium) 0; +} + +div.toc li { + padding: 0; + background: none; + line-height: var(--toc-font-size); + margin: var(--toc-font-size) 0 0 0; +} + +div.toc li::before { + display: none; +} + +div.toc ul { + margin-top: 0 +} + +div.toc li a { + font-size: var(--toc-font-size); + color: var(--page-foreground-color) !important; + text-decoration: none; +} + +div.toc li a:hover, div.toc li a.active { + color: var(--primary-color) !important; +} + +div.toc li a.aboveActive { + color: var(--page-secondary-foreground-color) !important; +} + + +@media screen and (max-width: 999px) { + div.contents .toc { + max-height: 45vh; + float: none; + width: auto; + margin: 0 0 var(--spacing-medium) 0; + position: relative; + top: 0; + position: relative; + border: 1px solid var(--separator-color); + border-radius: var(--border-radius-medium); + background-color: var(--toc-background); + box-shadow: var(--box-shadow); + } + + div.contents .toc.interactive { + max-height: calc(var(--navigation-font-size) + 2 * var(--spacing-large)); + overflow: hidden; + } + + div.contents .toc > h3 { + -webkit-tap-highlight-color: transparent; + cursor: pointer; + position: sticky; + top: 0; + background-color: var(--toc-background); + margin: 0; + padding: var(--spacing-large) 0; + display: block; + } + + div.contents .toc.interactive > h3::before { + content: ""; + width: 0; + height: 0; + border-left: 4px solid transparent; + border-right: 4px solid transparent; + border-top: 5px solid var(--primary-color); + display: inline-block; + margin-right: var(--spacing-small); + margin-bottom: calc(var(--navigation-font-size) / 4); + transform: rotate(-90deg); + transition: transform var(--animation-duration) ease-out; + } + + div.contents .toc.interactive.open > h3::before { + transform: rotate(0deg); + } + + div.contents .toc.interactive.open { + max-height: 45vh; + overflow: auto; + transition: max-height 0.2s ease-in-out; + } + + div.contents .toc a, div.contents .toc a.active { + color: var(--primary-color) !important; + } + + div.contents .toc a:hover { + text-decoration: underline; + } +} + +/* + Page Outline (Doxygen >= 1.14.0) +*/ + +#page-nav { + background: var(--page-background-color); + border-left: 1px solid var(--separator-color); +} + +#page-nav #page-nav-resize-handle { + background: var(--separator-color); +} + +#page-nav #page-nav-resize-handle::after { + border-left: 1px solid var(--primary-color); + border-right: 1px solid var(--primary-color); +} + +#page-nav #page-nav-tree #page-nav-contents { + top: var(--spacing-large); +} + +#page-nav ul.page-outline { + margin: 0; + padding: 0; +} + +#page-nav ul.page-outline li a { + font-size: var(--toc-font-size) !important; + color: var(--page-secondary-foreground-color) !important; + display: inline-block; + line-height: calc(2 * var(--toc-font-size)); +} + +#page-nav ul.page-outline li a a.anchorlink { + display: none; +} + +#page-nav ul.page-outline li.vis ~ * a { + color: var(--page-foreground-color) !important; +} + +#page-nav ul.page-outline li.vis:not(.vis ~ .vis) a, #page-nav ul.page-outline li a:hover { + color: var(--primary-color) !important; +} + +#page-nav ul.page-outline .vis { + background: var(--page-background-color); + position: relative; +} + +#page-nav ul.page-outline .vis::after { + content: ""; + position: absolute; + top: 0; + bottom: 0; + left: 0; + width: 4px; + background: var(--page-secondary-foreground-color); +} + +#page-nav ul.page-outline .vis:not(.vis ~ .vis)::after { + top: 1px; + border-top-right-radius: var(--border-radius-small); +} + +#page-nav ul.page-outline .vis:not(:has(~ .vis))::after { + bottom: 1px; + border-bottom-right-radius: var(--border-radius-small); +} + + +#page-nav ul.page-outline .arrow { + display: inline-block; +} + +#page-nav ul.page-outline .arrow span { + display: none; +} + +@media screen and (max-width: 767px) { + #container { + grid-template-columns: initial !important; + } + + #page-nav { + display: none; + } +} + +/* + Code & Fragments + */ + +code, div.fragment, pre.fragment, span.tt { + border: 1px solid var(--separator-color); + overflow: hidden; +} + +code, span.tt { + display: inline; + background: var(--code-background); + color: var(--code-foreground); + padding: 2px 6px; + border-radius: var(--border-radius-small); +} + +div.fragment, pre.fragment { + border-radius: var(--border-radius-medium); + margin: var(--spacing-medium) 0; + padding: calc(var(--spacing-large) - (var(--spacing-large) / 6)) var(--spacing-large); + background: var(--fragment-background); + color: var(--fragment-foreground); + overflow-x: auto; +} + +@media screen and (max-width: 767px) { + div.fragment, pre.fragment { + border-top-right-radius: 0; + border-bottom-right-radius: 0; + border-right: 0; + } + + .contents > div.fragment, + .textblock > div.fragment, + .textblock > pre.fragment, + .textblock > .tabbed > ul > li > div.fragment, + .textblock > .tabbed > ul > li > pre.fragment, + .contents > .doxygen-awesome-fragment-wrapper > div.fragment, + .textblock > .doxygen-awesome-fragment-wrapper > div.fragment, + .textblock > .doxygen-awesome-fragment-wrapper > pre.fragment, + .textblock > .tabbed > ul > li > .doxygen-awesome-fragment-wrapper > div.fragment, + .textblock > .tabbed > ul > li > .doxygen-awesome-fragment-wrapper > pre.fragment { + margin: var(--spacing-medium) calc(0px - var(--spacing-large)); + border-radius: 0; + border-left: 0; + } + + .textblock li > .fragment, + .textblock li > .doxygen-awesome-fragment-wrapper > .fragment { + margin: var(--spacing-medium) calc(0px - var(--spacing-large)); + } + + .memdoc li > .fragment, + .memdoc li > .doxygen-awesome-fragment-wrapper > .fragment { + margin: var(--spacing-medium) calc(0px - var(--spacing-medium)); + } + + .textblock ul, .memdoc ul { + overflow: initial; + } + + .memdoc > div.fragment, + .memdoc > pre.fragment, + dl dd > div.fragment, + dl dd pre.fragment, + .memdoc > .doxygen-awesome-fragment-wrapper > div.fragment, + .memdoc > .doxygen-awesome-fragment-wrapper > pre.fragment, + dl dd > .doxygen-awesome-fragment-wrapper > div.fragment, + dl dd .doxygen-awesome-fragment-wrapper > pre.fragment { + margin: var(--spacing-medium) calc(0px - var(--spacing-medium)); + border-radius: 0; + border-left: 0; + } +} + +code, code a, pre.fragment, div.fragment, div.fragment .line, div.fragment span, div.fragment .line a, div.fragment .line span, span.tt { + font-family: var(--font-family-monospace); + font-size: var(--code-font-size) !important; +} + +div.line:after { + margin-right: var(--spacing-medium); +} + +div.fragment .line, pre.fragment { + white-space: pre; + word-wrap: initial; + line-height: var(--fragment-lineheight); +} + +div.fragment span.keyword { + color: var(--fragment-keyword); +} + +div.fragment span.keywordtype { + color: var(--fragment-keywordtype); +} + +div.fragment span.keywordflow { + color: var(--fragment-keywordflow); +} + +div.fragment span.stringliteral { + color: var(--fragment-token) +} + +div.fragment span.comment { + color: var(--fragment-comment); +} + +div.fragment a.code { + color: var(--fragment-link) !important; +} + +div.fragment span.preprocessor { + color: var(--fragment-preprocessor); +} + +div.fragment span.lineno { + display: inline-block; + width: 27px; + border-right: none; + background: var(--fragment-linenumber-background); + color: var(--fragment-linenumber-color); +} + +div.fragment span.lineno a { + background: none; + color: var(--fragment-link) !important; +} + +div.fragment > .line:first-child .lineno { + box-shadow: -999999px 0px 0 999999px var(--fragment-linenumber-background), -999998px 0px 0 999999px var(--fragment-linenumber-border); + background-color: var(--fragment-linenumber-background) !important; +} + +div.line { + border-radius: var(--border-radius-small); +} + +div.line.glow { + background-color: var(--primary-light-color); + box-shadow: none; +} + +/* + dl warning, attention, note, deprecated, bug, ... + */ + +dl { + line-height: calc(1.65 * var(--page-font-size)); +} + +dl.bug dt a, dl.deprecated dt a, dl.todo dt a { + font-weight: bold !important; +} + +dl.warning, dl.attention, dl.note, dl.deprecated, dl.bug, dl.invariant, dl.pre, dl.post, dl.todo, dl.remark { + padding: var(--spacing-medium); + margin: var(--spacing-medium) 0; + color: var(--page-background-color); + overflow: hidden; + margin-left: 0; + border-radius: var(--border-radius-small); +} + +dl.section dd { + margin-bottom: 2px; +} + +dl.warning, dl.attention { + background: var(--warning-color); + border-left: 8px solid var(--warning-color-dark); + color: var(--warning-color-darker); +} + +dl.warning dt, dl.attention dt { + color: var(--warning-color-dark); +} + +dl.note, dl.remark { + background: var(--note-color); + border-left: 8px solid var(--note-color-dark); + color: var(--note-color-darker); +} + +dl.note dt, dl.remark dt { + color: var(--note-color-dark); +} + +dl.todo { + background: var(--todo-color); + border-left: 8px solid var(--todo-color-dark); + color: var(--todo-color-darker); +} + +dl.todo dt a { + color: var(--todo-color-dark) !important; +} + +dl.bug dt a { + color: var(--todo-color-dark) !important; +} + +dl.bug { + background: var(--bug-color); + border-left: 8px solid var(--bug-color-dark); + color: var(--bug-color-darker); +} + +dl.bug dt a { + color: var(--bug-color-dark) !important; +} + +dl.deprecated { + background: var(--deprecated-color); + border-left: 8px solid var(--deprecated-color-dark); + color: var(--deprecated-color-darker); +} + +dl.deprecated dt a { + color: var(--deprecated-color-dark) !important; +} + +dl.section dd, dl.bug dd, dl.deprecated dd, dl.todo dd { + margin-inline-start: 0px; +} + +dl.invariant, dl.pre, dl.post { + background: var(--invariant-color); + border-left: 8px solid var(--invariant-color-dark); + color: var(--invariant-color-darker); +} + +dl.invariant dt, dl.pre dt, dl.post dt { + color: var(--invariant-color-dark); +} + +/* + memitem + */ + +div.memdoc, div.memproto, h2.memtitle { + box-shadow: none; + background-image: none; + border: none; +} + +div.memdoc { + padding: 0 var(--spacing-medium); + background: var(--page-background-color); +} + +h2.memtitle, div.memitem { + border: 1px solid var(--separator-color); + box-shadow: var(--box-shadow); +} + +h2.memtitle { + box-shadow: 0px var(--spacing-medium) 0 -1px var(--fragment-background), var(--box-shadow); +} + +div.memitem { + transition: none; +} + +div.memproto, h2.memtitle { + background: var(--fragment-background); +} + +h2.memtitle { + font-weight: 500; + font-size: var(--memtitle-font-size); + font-family: var(--font-family-monospace); + border-bottom: none; + border-top-left-radius: var(--border-radius-medium); + border-top-right-radius: var(--border-radius-medium); + word-break: break-all; + position: relative; +} + +h2.memtitle:after { + content: ""; + display: block; + background: var(--fragment-background); + height: var(--spacing-medium); + bottom: calc(0px - var(--spacing-medium)); + left: 0; + right: -14px; + position: absolute; + border-top-right-radius: var(--border-radius-medium); +} + +h2.memtitle > span.permalink { + font-size: inherit; +} + +h2.memtitle > span.permalink > a { + text-decoration: none; + padding-left: 3px; + margin-right: -4px; + user-select: none; + display: inline-block; + margin-top: -6px; +} + +h2.memtitle > span.permalink > a:hover { + color: var(--primary-dark-color) !important; +} + +a:target + h2.memtitle, a:target + h2.memtitle + div.memitem { + border-color: var(--primary-light-color); +} + +div.memitem { + border-top-right-radius: var(--border-radius-medium); + border-bottom-right-radius: var(--border-radius-medium); + border-bottom-left-radius: var(--border-radius-medium); + border-top-left-radius: 0; + overflow: hidden; + display: block !important; +} + +div.memdoc { + border-radius: 0; +} + +div.memproto { + border-radius: 0 var(--border-radius-small) 0 0; + overflow: auto; + border-bottom: 1px solid var(--separator-color); + padding: var(--spacing-medium); + margin-bottom: -1px; +} + +div.memtitle { + border-top-right-radius: var(--border-radius-medium); + border-top-left-radius: var(--border-radius-medium); +} + +div.memproto table.memname { + font-family: var(--font-family-monospace); + color: var(--page-foreground-color); + font-size: var(--memname-font-size); + text-shadow: none; +} + +div.memproto div.memtemplate { + font-family: var(--font-family-monospace); + color: var(--primary-dark-color); + font-size: var(--memname-font-size); + margin-left: 2px; + text-shadow: none; +} + +table.mlabels, table.mlabels > tbody { + display: block; +} + +td.mlabels-left { + width: auto; +} + +td.mlabels-right { + margin-top: 3px; + position: sticky; + left: 0; +} + +table.mlabels > tbody > tr:first-child { + display: flex; + justify-content: space-between; + flex-wrap: wrap; +} + +.memname, .memitem span.mlabels { + margin: 0 +} + +/* + reflist + */ + +dl.reflist { + box-shadow: var(--box-shadow); + border-radius: var(--border-radius-medium); + border: 1px solid var(--separator-color); + overflow: hidden; + padding: 0; +} + + +dl.reflist dt, dl.reflist dd { + box-shadow: none; + text-shadow: none; + background-image: none; + border: none; + padding: 12px; +} + + +dl.reflist dt { + font-weight: 500; + border-radius: 0; + background: var(--code-background); + border-bottom: 1px solid var(--separator-color); + color: var(--page-foreground-color) +} + + +dl.reflist dd { + background: none; +} + +/* + Table + */ + +.contents table:not(.memberdecls):not(.mlabels):not(.fieldtable):not(.memname), +.contents table:not(.memberdecls):not(.mlabels):not(.fieldtable):not(.memname) tbody { + display: inline-block; + max-width: 100%; +} + +.contents > table:not(.memberdecls):not(.mlabels):not(.fieldtable):not(.memname):not(.classindex) { + margin-left: calc(0px - var(--spacing-large)); + margin-right: calc(0px - var(--spacing-large)); + max-width: calc(100% + 2 * var(--spacing-large)); +} + +table.fieldtable, +table.markdownTable tbody, +table.doxtable tbody { + border: none; + margin: var(--spacing-medium) 0; + box-shadow: 0 0 0 1px var(--separator-color); + border-radius: var(--border-radius-small); +} + +table.markdownTable, table.doxtable, table.fieldtable { + padding: 1px; +} + +table.doxtable caption { + display: block; +} + +table.fieldtable { + border-collapse: collapse; + width: 100%; +} + +th.markdownTableHeadLeft, +th.markdownTableHeadRight, +th.markdownTableHeadCenter, +th.markdownTableHeadNone, +table.doxtable th { + background: var(--tablehead-background); + color: var(--tablehead-foreground); + font-weight: 600; + font-size: var(--page-font-size); +} + +th.markdownTableHeadLeft:first-child, +th.markdownTableHeadRight:first-child, +th.markdownTableHeadCenter:first-child, +th.markdownTableHeadNone:first-child, +table.doxtable tr th:first-child { + border-top-left-radius: var(--border-radius-small); +} + +th.markdownTableHeadLeft:last-child, +th.markdownTableHeadRight:last-child, +th.markdownTableHeadCenter:last-child, +th.markdownTableHeadNone:last-child, +table.doxtable tr th:last-child { + border-top-right-radius: var(--border-radius-small); +} + +table.markdownTable td, +table.markdownTable th, +table.fieldtable td, +table.fieldtable th, +table.doxtable td, +table.doxtable th { + border: 1px solid var(--separator-color); + padding: var(--spacing-small) var(--spacing-medium); +} + +table.markdownTable td:last-child, +table.markdownTable th:last-child, +table.fieldtable td:last-child, +table.fieldtable th:last-child, +table.doxtable td:last-child, +table.doxtable th:last-child { + border-right: none; +} + +table.markdownTable td:first-child, +table.markdownTable th:first-child, +table.fieldtable td:first-child, +table.fieldtable th:first-child, +table.doxtable td:first-child, +table.doxtable th:first-child { + border-left: none; +} + +table.markdownTable tr:first-child td, +table.markdownTable tr:first-child th, +table.fieldtable tr:first-child td, +table.fieldtable tr:first-child th, +table.doxtable tr:first-child td, +table.doxtable tr:first-child th { + border-top: none; +} + +table.markdownTable tr:last-child td, +table.markdownTable tr:last-child th, +table.fieldtable tr:last-child td, +table.fieldtable tr:last-child th, +table.doxtable tr:last-child td, +table.doxtable tr:last-child th { + border-bottom: none; +} + +table.markdownTable tr, table.doxtable tr { + border-bottom: 1px solid var(--separator-color); +} + +table.markdownTable tr:last-child, table.doxtable tr:last-child { + border-bottom: none; +} + +.full_width_table table:not(.memberdecls):not(.mlabels):not(.fieldtable):not(.memname) { + display: block; +} + +.full_width_table table:not(.memberdecls):not(.mlabels):not(.fieldtable):not(.memname) tbody { + display: table; + width: 100%; +} + +table.fieldtable th { + font-size: var(--page-font-size); + font-weight: 600; + background-image: none; + background-color: var(--tablehead-background); + color: var(--tablehead-foreground); +} + +table.fieldtable td.fieldtype, .fieldtable td.fieldname, .fieldtable td.fieldinit, .fieldtable td.fielddoc, .fieldtable th { + border-bottom: 1px solid var(--separator-color); + border-right: 1px solid var(--separator-color); +} + +table.fieldtable tr:last-child td:first-child { + border-bottom-left-radius: var(--border-radius-small); +} + +table.fieldtable tr:last-child td:last-child { + border-bottom-right-radius: var(--border-radius-small); +} + +.memberdecls td.glow, .fieldtable tr.glow { + background-color: var(--primary-light-color); + box-shadow: none; +} + +table.memberdecls { + display: block; + -webkit-tap-highlight-color: transparent; +} + +table.memberdecls tr[class^='memitem'] { + font-family: var(--font-family-monospace); + font-size: var(--code-font-size); +} + +table.memberdecls tr[class^='memitem'] .memTemplParams { + font-family: var(--font-family-monospace); + font-size: var(--code-font-size); + color: var(--primary-dark-color); + white-space: normal; +} + +table.memberdecls tr.heading + tr[class^='memitem'] td.memItemLeft, +table.memberdecls tr.heading + tr[class^='memitem'] td.memItemRight, +table.memberdecls td.memItemLeft, +table.memberdecls td.memItemRight, +table.memberdecls .memTemplItemLeft, +table.memberdecls .memTemplItemRight, +table.memberdecls .memTemplParams { + transition: none; + padding-top: var(--spacing-small); + padding-bottom: var(--spacing-small); + border-top: 1px solid var(--separator-color); + border-bottom: 1px solid var(--separator-color); + background-color: var(--fragment-background); +} + +@media screen and (min-width: 768px) { + + tr.heading + tr[class^='memitem'] td.memItemRight, tr.groupHeader + tr[class^='memitem'] td.memItemRight, tr.inherit_header + tr[class^='memitem'] td.memItemRight { + border-top-right-radius: var(--border-radius-small); + } + + table.memberdecls tr:last-child td.memItemRight, table.memberdecls tr:last-child td.mdescRight, table.memberdecls tr[class^='memitem']:has(+ tr.groupHeader) td.memItemRight, table.memberdecls tr[class^='memitem']:has(+ tr.inherit_header) td.memItemRight, table.memberdecls tr[class^='memdesc']:has(+ tr.groupHeader) td.mdescRight, table.memberdecls tr[class^='memdesc']:has(+ tr.inherit_header) td.mdescRight { + border-bottom-right-radius: var(--border-radius-small); + } + + table.memberdecls tr:last-child td.memItemLeft, table.memberdecls tr:last-child td.mdescLeft, table.memberdecls tr[class^='memitem']:has(+ tr.groupHeader) td.memItemLeft, table.memberdecls tr[class^='memitem']:has(+ tr.inherit_header) td.memItemLeft, table.memberdecls tr[class^='memdesc']:has(+ tr.groupHeader) td.mdescLeft, table.memberdecls tr[class^='memdesc']:has(+ tr.inherit_header) td.mdescLeft { + border-bottom-left-radius: var(--border-radius-small); + } + + tr.heading + tr[class^='memitem'] td.memItemLeft, tr.groupHeader + tr[class^='memitem'] td.memItemLeft, tr.inherit_header + tr[class^='memitem'] td.memItemLeft { + border-top-left-radius: var(--border-radius-small); + } + +} + +table.memname td.memname { + font-size: var(--memname-font-size); +} + +table.memberdecls .memTemplItemLeft, +table.memberdecls .template .memItemLeft, +table.memberdecls .memTemplItemRight, +table.memberdecls .template .memItemRight { + padding-top: 2px; +} + +table.memberdecls .memTemplParams { + border-bottom: 0; + border-left: 1px solid var(--separator-color); + border-right: 1px solid var(--separator-color); + border-radius: var(--border-radius-small) var(--border-radius-small) 0 0; + padding-bottom: var(--spacing-small); +} + +table.memberdecls .memTemplItemLeft, table.memberdecls .template .memItemLeft { + border-radius: 0 0 0 var(--border-radius-small); + border-left: 1px solid var(--separator-color); + border-top: 0; +} + +table.memberdecls .memTemplItemRight, table.memberdecls .template .memItemRight { + border-radius: 0 0 var(--border-radius-small) 0; + border-right: 1px solid var(--separator-color); + padding-left: 0; + border-top: 0; +} + +table.memberdecls .memItemLeft { + border-radius: var(--border-radius-small) 0 0 var(--border-radius-small); + border-left: 1px solid var(--separator-color); + padding-left: var(--spacing-medium); + padding-right: 0; +} + +table.memberdecls .memItemRight { + border-radius: 0 var(--border-radius-small) var(--border-radius-small) 0; + border-right: 1px solid var(--separator-color); + padding-right: var(--spacing-medium); + padding-left: 0; + +} + +table.memberdecls .mdescLeft, table.memberdecls .mdescRight { + background: none; + color: var(--page-foreground-color); + padding: var(--spacing-small) 0; + border: 0; +} + +table.memberdecls [class^="memdesc"] { + box-shadow: none; +} + + +table.memberdecls .memItemLeft, +table.memberdecls .memTemplItemLeft { + padding-right: var(--spacing-medium); +} + +table.memberdecls .memSeparator { + background: var(--page-background-color); + height: var(--spacing-large); + border: 0; + transition: none; +} + +table.memberdecls .groupheader { + margin-bottom: var(--spacing-large); +} + +table.memberdecls .inherit_header td { + padding: 0 0 var(--spacing-medium) 0; + text-indent: -12px; + color: var(--page-secondary-foreground-color); +} + +table.memberdecls span.dynarrow { + left: 10px; +} + +table.memberdecls img[src="closed.png"], +table.memberdecls img[src="open.png"], +div.dynheader img[src="open.png"], +div.dynheader img[src="closed.png"] { + width: 0; + height: 0; + border-left: 4px solid transparent; + border-right: 4px solid transparent; + border-top: 5px solid var(--primary-color); + margin-top: 8px; + display: block; + float: left; + margin-left: -10px; + transition: transform var(--animation-duration) ease-out; +} + +tr.heading + tr[class^='memitem'] td.memItemLeft, tr.groupHeader + tr[class^='memitem'] td.memItemLeft, tr.inherit_header + tr[class^='memitem'] td.memItemLeft, tr.heading + tr[class^='memitem'] td.memItemRight, tr.groupHeader + tr[class^='memitem'] td.memItemRight, tr.inherit_header + tr[class^='memitem'] td.memItemRight { + border-top: 1px solid var(--separator-color); +} + +table.memberdecls img { + margin-right: 10px; +} + +table.memberdecls img[src="closed.png"], +div.dynheader img[src="closed.png"] { + transform: rotate(-90deg); + +} + +.compoundTemplParams { + font-family: var(--font-family-monospace); + color: var(--primary-dark-color); + font-size: var(--code-font-size); +} + +@media screen and (max-width: 767px) { + + table.memberdecls .memItemLeft, + table.memberdecls .memItemRight, + table.memberdecls .mdescLeft, + table.memberdecls .mdescRight, + table.memberdecls .memTemplItemLeft, + table.memberdecls .memTemplItemRight, + table.memberdecls .memTemplParams, + table.memberdecls .template .memItemLeft, + table.memberdecls .template .memItemRight, + table.memberdecls .template .memParams { + display: block; + text-align: left; + padding-left: var(--spacing-large); + margin: 0 calc(0px - var(--spacing-large)) 0 calc(0px - var(--spacing-large)); + border-right: none; + border-left: none; + border-radius: 0; + white-space: normal; + } + + table.memberdecls .memItemLeft, + table.memberdecls .mdescLeft, + table.memberdecls .memTemplItemLeft, + table.memberdecls .template .memItemLeft { + border-bottom: 0 !important; + padding-bottom: 0 !important; + } + + table.memberdecls .memTemplItemLeft, + table.memberdecls .template .memItemLeft { + padding-top: 0; + } + + table.memberdecls .mdescLeft { + margin-bottom: calc(0px - var(--page-font-size)); + } + + table.memberdecls .memItemRight, + table.memberdecls .mdescRight, + table.memberdecls .memTemplItemRight, + table.memberdecls .template .memItemRight { + border-top: 0 !important; + padding-top: 0 !important; + padding-right: var(--spacing-large); + padding-bottom: var(--spacing-medium); + overflow-x: auto; + } + + table.memberdecls tr[class^='memitem']:not(.inherit) { + display: block; + width: calc(100vw - 2 * var(--spacing-large)); + } + + table.memberdecls .mdescRight { + color: var(--page-foreground-color); + } + + table.memberdecls tr.inherit { + visibility: hidden; + } + + table.memberdecls tr[style="display: table-row;"] { + display: block !important; + visibility: visible; + width: calc(100vw - 2 * var(--spacing-large)); + animation: fade .5s; + } + + @keyframes fade { + 0% { + opacity: 0; + max-height: 0; + } + + 100% { + opacity: 1; + max-height: 200px; + } + } + + tr.heading + tr[class^='memitem'] td.memItemRight, tr.groupHeader + tr[class^='memitem'] td.memItemRight, tr.inherit_header + tr[class^='memitem'] td.memItemRight { + border-top-right-radius: 0; + } + + table.memberdecls tr:last-child td.memItemRight, table.memberdecls tr:last-child td.mdescRight, table.memberdecls tr[class^='memitem']:has(+ tr.groupHeader) td.memItemRight, table.memberdecls tr[class^='memitem']:has(+ tr.inherit_header) td.memItemRight, table.memberdecls tr[class^='memdesc']:has(+ tr.groupHeader) td.mdescRight, table.memberdecls tr[class^='memdesc']:has(+ tr.inherit_header) td.mdescRight { + border-bottom-right-radius: 0; + } + + table.memberdecls tr:last-child td.memItemLeft, table.memberdecls tr:last-child td.mdescLeft, table.memberdecls tr[class^='memitem']:has(+ tr.groupHeader) td.memItemLeft, table.memberdecls tr[class^='memitem']:has(+ tr.inherit_header) td.memItemLeft, table.memberdecls tr[class^='memdesc']:has(+ tr.groupHeader) td.mdescLeft, table.memberdecls tr[class^='memdesc']:has(+ tr.inherit_header) td.mdescLeft { + border-bottom-left-radius: 0; + } + + tr.heading + tr[class^='memitem'] td.memItemLeft, tr.groupHeader + tr[class^='memitem'] td.memItemLeft, tr.inherit_header + tr[class^='memitem'] td.memItemLeft { + border-top-left-radius: 0; + } +} + + +/* + Horizontal Rule + */ + +hr { + margin-top: var(--spacing-large); + margin-bottom: var(--spacing-large); + height: 1px; + background-color: var(--separator-color); + border: 0; +} + +.contents hr { + box-shadow: 100px 0 var(--separator-color), + -100px 0 var(--separator-color), + 500px 0 var(--separator-color), + -500px 0 var(--separator-color), + 900px 0 var(--separator-color), + -900px 0 var(--separator-color), + 1400px 0 var(--separator-color), + -1400px 0 var(--separator-color), + 1900px 0 var(--separator-color), + -1900px 0 var(--separator-color); +} + +.contents img, .contents .center, .contents center, .contents div.image object { + max-width: 100%; + overflow: auto; +} + +@media screen and (max-width: 767px) { + .contents .dyncontent > .center, .contents > center { + margin-left: calc(0px - var(--spacing-large)); + margin-right: calc(0px - var(--spacing-large)); + max-width: calc(100% + 2 * var(--spacing-large)); + } +} + +/* + Directories + */ +div.directory { + border-top: 1px solid var(--separator-color); + border-bottom: 1px solid var(--separator-color); + width: auto; +} + +table.directory { + font-family: var(--font-family); + font-size: var(--page-font-size); + font-weight: normal; + width: 100%; +} + +table.directory td.entry, table.directory td.desc { + padding: calc(var(--spacing-small) / 2) var(--spacing-small); + line-height: var(--table-line-height); +} + +table.directory tr.even td:last-child { + border-radius: 0 var(--border-radius-small) var(--border-radius-small) 0; +} + +table.directory tr.even td:first-child { + border-radius: var(--border-radius-small) 0 0 var(--border-radius-small); +} + +table.directory tr.even:last-child td:last-child { + border-radius: 0 var(--border-radius-small) 0 0; +} + +table.directory tr.even:last-child td:first-child { + border-radius: var(--border-radius-small) 0 0 0; +} + +table.directory td.desc { + min-width: 250px; +} + +table.directory tr.even { + background-color: var(--odd-color); +} + +table.directory tr.odd { + background-color: transparent; +} + +.icona { + width: auto; + height: auto; + margin: 0 var(--spacing-small); +} + +.icon { + background: var(--primary-color); + border-radius: var(--border-radius-small); + font-size: var(--page-font-size); + padding: calc(var(--page-font-size) / 5); + line-height: var(--page-font-size); + transform: scale(0.8); + height: auto; + width: var(--page-font-size); + user-select: none; +} + +.iconfopen, .icondoc, .iconfclosed { + background-position: center; + margin-bottom: 0; + height: var(--table-line-height); +} + +.icondoc { + filter: saturate(0.2); +} + +@media screen and (max-width: 767px) { + div.directory { + margin-left: calc(0px - var(--spacing-large)); + margin-right: calc(0px - var(--spacing-large)); + } +} + +@media (prefers-color-scheme: dark) { + html:not(.light-mode) .iconfopen, html:not(.light-mode) .iconfclosed { + filter: hue-rotate(180deg) invert(); + } +} + +html.dark-mode .iconfopen, html.dark-mode .iconfclosed { + filter: hue-rotate(180deg) invert(); +} + +/* + Class list + */ + +.classindex dl.odd { + background: var(--odd-color); + border-radius: var(--border-radius-small); +} + +.classindex dl.even { + background-color: transparent; +} + +/* + Class Index Doxygen 1.8 +*/ + +table.classindex { + margin-left: 0; + margin-right: 0; + width: 100%; +} + +table.classindex table div.ah { + background-image: none; + background-color: initial; + border-color: var(--separator-color); + color: var(--page-foreground-color); + box-shadow: var(--box-shadow); + border-radius: var(--border-radius-large); + padding: var(--spacing-small); +} + +div.qindex { + background-color: var(--odd-color); + border-radius: var(--border-radius-small); + border: 1px solid var(--separator-color); + padding: var(--spacing-small) 0; +} + +/* + Footer and nav-path + */ + +#nav-path { + width: 100%; +} + +#nav-path ul { + background-image: none; + background: var(--page-background-color); + border: none; + border-top: 1px solid var(--separator-color); + border-bottom: 0; + font-size: var(--navigation-font-size); +} + +img.footer { + width: 60px; +} + +.navpath li.footer { + color: var(--page-secondary-foreground-color); +} + +address.footer { + color: var(--page-secondary-foreground-color); + margin-bottom: var(--spacing-large); +} + +#nav-path li.navelem { + background-image: none; + display: flex; + align-items: center; +} + +.navpath li.navelem a { + text-shadow: none; + display: inline-block; + color: var(--primary-color) !important; +} + +.navpath li.navelem a:hover { + text-shadow: none; +} + +.navpath li.navelem b { + color: var(--primary-dark-color); + font-weight: 500; +} + +li.navelem { + padding: 0; + margin-left: -8px; +} + +li.navelem:first-child { + margin-left: var(--spacing-large); +} + +li.navelem:first-child:before { + display: none; +} + +#nav-path ul { + padding-left: 0; +} + +#nav-path li.navelem:has(.el):after { + content: ''; + border: 5px solid var(--page-background-color); + border-bottom-color: transparent; + border-right-color: transparent; + border-top-color: transparent; + transform: translateY(-1px) scaleY(4.2); + z-index: 10; + margin-left: 6px; +} + +#nav-path li.navelem:not(:has(.el)):after { + background: var(--page-background-color); + box-shadow: 1px -1px 0 1px var(--separator-color); + border-radius: 0 var(--border-radius-medium) 0 50px; +} + +#nav-path li.navelem:not(:has(.el)) { + margin-left: 0; +} + +#nav-path li.navelem:not(:has(.el)):hover, #nav-path li.navelem:not(:has(.el)):hover:after { + background-color: var(--separator-color); +} + +#nav-path li.navelem:has(.el):before { + content: ''; + border: 5px solid var(--separator-color); + border-bottom-color: transparent; + border-right-color: transparent; + border-top-color: transparent; + transform: translateY(-1px) scaleY(3.2); + margin-right: var(--spacing-small); +} + +.navpath li.navelem a:hover { + color: var(--primary-color); +} + +/* + Scrollbars for Webkit +*/ + +#nav-tree::-webkit-scrollbar, +div.fragment::-webkit-scrollbar, +pre.fragment::-webkit-scrollbar, +div.memproto::-webkit-scrollbar, +.contents center::-webkit-scrollbar, +.contents .center::-webkit-scrollbar, +.contents table:not(.memberdecls):not(.mlabels):not(.fieldtable):not(.memname) tbody::-webkit-scrollbar, +div.contents .toc::-webkit-scrollbar, +.contents .dotgraph::-webkit-scrollbar, +.contents .tabs-overview-container::-webkit-scrollbar { + background: transparent; + width: calc(var(--webkit-scrollbar-size) + var(--webkit-scrollbar-padding) + var(--webkit-scrollbar-padding)); + height: calc(var(--webkit-scrollbar-size) + var(--webkit-scrollbar-padding) + var(--webkit-scrollbar-padding)); +} + +#nav-tree::-webkit-scrollbar-thumb, +div.fragment::-webkit-scrollbar-thumb, +pre.fragment::-webkit-scrollbar-thumb, +div.memproto::-webkit-scrollbar-thumb, +.contents center::-webkit-scrollbar-thumb, +.contents .center::-webkit-scrollbar-thumb, +.contents table:not(.memberdecls):not(.mlabels):not(.fieldtable):not(.memname) tbody::-webkit-scrollbar-thumb, +div.contents .toc::-webkit-scrollbar-thumb, +.contents .dotgraph::-webkit-scrollbar-thumb, +.contents .tabs-overview-container::-webkit-scrollbar-thumb { + background-color: transparent; + border: var(--webkit-scrollbar-padding) solid transparent; + border-radius: calc(var(--webkit-scrollbar-padding) + var(--webkit-scrollbar-padding)); + background-clip: padding-box; +} + +#nav-tree:hover::-webkit-scrollbar-thumb, +div.fragment:hover::-webkit-scrollbar-thumb, +pre.fragment:hover::-webkit-scrollbar-thumb, +div.memproto:hover::-webkit-scrollbar-thumb, +.contents center:hover::-webkit-scrollbar-thumb, +.contents .center:hover::-webkit-scrollbar-thumb, +.contents table:not(.memberdecls):not(.mlabels):not(.fieldtable):not(.memname) tbody:hover::-webkit-scrollbar-thumb, +div.contents .toc:hover::-webkit-scrollbar-thumb, +.contents .dotgraph:hover::-webkit-scrollbar-thumb, +.contents .tabs-overview-container:hover::-webkit-scrollbar-thumb { + background-color: var(--webkit-scrollbar-color); +} + +#nav-tree::-webkit-scrollbar-track, +div.fragment::-webkit-scrollbar-track, +pre.fragment::-webkit-scrollbar-track, +div.memproto::-webkit-scrollbar-track, +.contents center::-webkit-scrollbar-track, +.contents .center::-webkit-scrollbar-track, +.contents table:not(.memberdecls):not(.mlabels):not(.fieldtable):not(.memname) tbody::-webkit-scrollbar-track, +div.contents .toc::-webkit-scrollbar-track, +.contents .dotgraph::-webkit-scrollbar-track, +.contents .tabs-overview-container::-webkit-scrollbar-track { + background: transparent; +} + +#nav-tree::-webkit-scrollbar-corner { + background-color: var(--side-nav-background); +} + +#nav-tree, +div.fragment, +pre.fragment, +div.memproto, +.contents center, +.contents .center, +.contents table:not(.memberdecls):not(.mlabels):not(.fieldtable):not(.memname) tbody, +div.contents .toc { + overflow-x: auto; + overflow-x: overlay; +} + +#nav-tree { + overflow-x: auto; + overflow-y: auto; + overflow-y: overlay; +} + +/* + Scrollbars for Firefox +*/ + +#nav-tree, +div.fragment, +pre.fragment, +div.memproto, +.contents center, +.contents .center, +.contents table:not(.memberdecls):not(.mlabels):not(.fieldtable):not(.memname) tbody, +div.contents .toc, +.contents .dotgraph, +.contents .tabs-overview-container { + scrollbar-width: thin; +} + +/* + Optional Dark mode toggle button +*/ + +doxygen-awesome-dark-mode-toggle { + display: inline-block; + margin: 0 0 0 var(--spacing-small); + padding: 0; + width: var(--searchbar-height); + height: var(--searchbar-height); + background: none; + border: none; + border-radius: var(--searchbar-border-radius); + vertical-align: middle; + text-align: center; + line-height: var(--searchbar-height); + font-size: 22px; + display: flex; + align-items: center; + justify-content: center; + user-select: none; + cursor: pointer; +} + +doxygen-awesome-dark-mode-toggle > svg { + transition: transform var(--animation-duration) ease-in-out; +} + +doxygen-awesome-dark-mode-toggle:active > svg { + transform: scale(.5); +} + +doxygen-awesome-dark-mode-toggle:hover { + background-color: rgba(0,0,0,.03); +} + +html.dark-mode doxygen-awesome-dark-mode-toggle:hover { + background-color: rgba(0,0,0,.18); +} + +/* + Optional fragment copy button +*/ +.doxygen-awesome-fragment-wrapper { + position: relative; +} + +doxygen-awesome-fragment-copy-button { + opacity: 0; + background: var(--fragment-background); + width: 28px; + height: 28px; + position: absolute; + right: calc(var(--spacing-large) - (var(--spacing-large) / 2.5)); + top: calc(var(--spacing-large) - (var(--spacing-large) / 2.5)); + border: 1px solid var(--fragment-foreground); + cursor: pointer; + border-radius: var(--border-radius-small); + display: flex; + justify-content: center; + align-items: center; +} + +.doxygen-awesome-fragment-wrapper:hover doxygen-awesome-fragment-copy-button, doxygen-awesome-fragment-copy-button.success { + opacity: .28; +} + +doxygen-awesome-fragment-copy-button:hover, doxygen-awesome-fragment-copy-button.success { + opacity: 1 !important; +} + +doxygen-awesome-fragment-copy-button:active:not([class~=success]) svg { + transform: scale(.91); +} + +doxygen-awesome-fragment-copy-button svg { + fill: var(--fragment-foreground); + width: 18px; + height: 18px; +} + +doxygen-awesome-fragment-copy-button.success svg { + fill: rgb(14, 168, 14); +} + +doxygen-awesome-fragment-copy-button.success { + border-color: rgb(14, 168, 14); +} + +@media screen and (max-width: 767px) { + .textblock > .doxygen-awesome-fragment-wrapper > doxygen-awesome-fragment-copy-button, + .textblock li > .doxygen-awesome-fragment-wrapper > doxygen-awesome-fragment-copy-button, + .memdoc li > .doxygen-awesome-fragment-wrapper > doxygen-awesome-fragment-copy-button, + .memdoc > .doxygen-awesome-fragment-wrapper > doxygen-awesome-fragment-copy-button, + dl dd > .doxygen-awesome-fragment-wrapper > doxygen-awesome-fragment-copy-button { + right: 0; + } +} + +/* + Optional paragraph link button +*/ + +a.anchorlink { + font-size: 90%; + margin-left: var(--spacing-small); + color: var(--page-foreground-color) !important; + text-decoration: none; + opacity: .15; + display: none; + transition: opacity var(--animation-duration) ease-in-out, color var(--animation-duration) ease-in-out; +} + +a.anchorlink svg { + fill: var(--page-foreground-color); +} + +h3 a.anchorlink svg, h4 a.anchorlink svg { + margin-bottom: -3px; + margin-top: -4px; +} + +a.anchorlink:hover { + opacity: .45; +} + +h2:hover a.anchorlink, h1:hover a.anchorlink, h3:hover a.anchorlink, h4:hover a.anchorlink { + display: inline-block; +} + +/* + Optional tab feature +*/ + +.tabbed > ul { + padding-inline-start: 0px; + margin: 0; + padding: var(--spacing-small) 0; +} + +.tabbed > ul > li { + display: none; +} + +.tabbed > ul > li.selected { + display: block; +} + +.tabs-overview-container { + overflow-x: auto; + display: block; + overflow-y: visible; +} + +.tabs-overview { + border-bottom: 1px solid var(--separator-color); + display: flex; + flex-direction: row; +} + +@media screen and (max-width: 767px) { + .tabs-overview-container { + margin: 0 calc(0px - var(--spacing-large)); + } + .tabs-overview { + padding: 0 var(--spacing-large) + } +} + +.tabs-overview button.tab-button { + color: var(--page-foreground-color); + margin: 0; + border: none; + background: transparent; + padding: calc(var(--spacing-large) / 2) 0; + display: inline-block; + font-size: var(--page-font-size); + cursor: pointer; + box-shadow: 0 1px 0 0 var(--separator-color); + position: relative; + + -webkit-tap-highlight-color: transparent; +} + +.tabs-overview button.tab-button .tab-title::before { + display: block; + content: attr(title); + font-weight: 600; + height: 0; + overflow: hidden; + visibility: hidden; +} + +.tabs-overview button.tab-button .tab-title { + float: left; + white-space: nowrap; + font-weight: normal; + font-family: var(--font-family); + padding: calc(var(--spacing-large) / 2) var(--spacing-large); + border-radius: var(--border-radius-medium); + transition: background-color var(--animation-duration) ease-in-out, font-weight var(--animation-duration) ease-in-out; +} + +.tabs-overview button.tab-button:not(:last-child) .tab-title { + box-shadow: 8px 0 0 -7px var(--separator-color); +} + +.tabs-overview button.tab-button:hover .tab-title { + background: var(--separator-color); + box-shadow: none; +} + +.tabs-overview button.tab-button.active .tab-title { + font-weight: 600; +} + +.tabs-overview button.tab-button::after { + content: ''; + display: block; + position: absolute; + left: 0; + bottom: 0; + right: 0; + height: 0; + width: 0%; + margin: 0 auto; + border-radius: var(--border-radius-small) var(--border-radius-small) 0 0; + background-color: var(--primary-color); + transition: width var(--animation-duration) ease-in-out, height var(--animation-duration) ease-in-out; +} + +.tabs-overview button.tab-button.active::after { + width: 100%; + box-sizing: border-box; + height: 3px; +} + + +/* + Navigation Buttons +*/ + +.section_buttons:not(:empty) { + margin-top: calc(var(--spacing-large) * 3); +} + +.section_buttons table.markdownTable { + display: block; + width: 100%; +} + +.section_buttons table.markdownTable tbody { + display: table !important; + width: 100%; + box-shadow: none; + border-spacing: 10px; +} + +.section_buttons table.markdownTable td { + padding: 0; +} + +.section_buttons table.markdownTable th { + display: none; +} + +.section_buttons table.markdownTable tr.markdownTableHead { + border: none; +} + +.section_buttons tr th, .section_buttons tr td { + background: none; + border: none; + padding: var(--spacing-large) 0 var(--spacing-small); +} + +.section_buttons a { + display: inline-block; + border: 1px solid var(--separator-color); + border-radius: var(--border-radius-medium); + color: var(--page-secondary-foreground-color) !important; + text-decoration: none; + transition: color var(--animation-duration) ease-in-out, background-color var(--animation-duration) ease-in-out; +} + +.section_buttons a:hover { + color: var(--page-foreground-color) !important; + background-color: var(--odd-color); +} + +.section_buttons tr td.markdownTableBodyLeft a { + padding: var(--spacing-medium) var(--spacing-large) var(--spacing-medium) calc(var(--spacing-large) / 2); +} + +.section_buttons tr td.markdownTableBodyRight a { + padding: var(--spacing-medium) calc(var(--spacing-large) / 2) var(--spacing-medium) var(--spacing-large); +} + +.section_buttons tr td.markdownTableBodyLeft a::before, +.section_buttons tr td.markdownTableBodyRight a::after { + color: var(--page-secondary-foreground-color) !important; + display: inline-block; + transition: color .08s ease-in-out, transform .09s ease-in-out; +} + +.section_buttons tr td.markdownTableBodyLeft a::before { + content: '〈'; + padding-right: var(--spacing-large); +} + + +.section_buttons tr td.markdownTableBodyRight a::after { + content: '〉'; + padding-left: var(--spacing-large); +} + + +.section_buttons tr td.markdownTableBodyLeft a:hover::before { + color: var(--page-foreground-color) !important; + transform: translateX(-3px); +} + +.section_buttons tr td.markdownTableBodyRight a:hover::after { + color: var(--page-foreground-color) !important; + transform: translateX(3px); +} + +@media screen and (max-width: 450px) { + .section_buttons a { + width: 100%; + box-sizing: border-box; + } + + .section_buttons tr td:nth-of-type(1).markdownTableBodyLeft a { + border-radius: var(--border-radius-medium) 0 0 var(--border-radius-medium); + border-right: none; + } + + .section_buttons tr td:nth-of-type(2).markdownTableBodyRight a { + border-radius: 0 var(--border-radius-medium) var(--border-radius-medium) 0; + } +} + +/* + Bordered image +*/ + +html.dark-mode .darkmode_inverted_image img, /* < doxygen 1.9.3 */ +html.dark-mode .darkmode_inverted_image object[type="image/svg+xml"] /* doxygen 1.9.3 */ { + filter: brightness(89%) hue-rotate(180deg) invert(); +} + +.bordered_image { + border-radius: var(--border-radius-small); + border: 1px solid var(--separator-color); + display: inline-block; + overflow: hidden; +} + +.bordered_image:empty { + border: none; +} + +html.dark-mode .bordered_image img, /* < doxygen 1.9.3 */ +html.dark-mode .bordered_image object[type="image/svg+xml"] /* doxygen 1.9.3 */ { + border-radius: var(--border-radius-small); +} + +/* + Button +*/ + +.primary-button { + display: inline-block; + cursor: pointer; + background: var(--primary-color); + color: var(--page-background-color) !important; + border-radius: var(--border-radius-medium); + padding: var(--spacing-small) var(--spacing-medium); + text-decoration: none; +} + +.primary-button:hover { + background: var(--primary-dark-color); +} \ No newline at end of file diff --git a/3rdparty/flatbuffers/CMakeLists.txt b/3rdparty/flatbuffers/CMakeLists.txt new file mode 100644 index 000000000..bc91f8e27 --- /dev/null +++ b/3rdparty/flatbuffers/CMakeLists.txt @@ -0,0 +1,8 @@ +add_library(flatbuffers INTERFACE) + +add_library(flatbuffers::flatbuffers ALIAS flatbuffers) + +target_include_directories(flatbuffers + INTERFACE + ${CMAKE_CURRENT_SOURCE_DIR} +) diff --git a/3rdparty/flatbuffers/base.h b/3rdparty/flatbuffers/flatbuffers/base.h similarity index 100% rename from 3rdparty/flatbuffers/base.h rename to 3rdparty/flatbuffers/flatbuffers/base.h diff --git a/3rdparty/lexy/CMakeLists.txt b/3rdparty/lexy/CMakeLists.txt deleted file mode 100644 index a76693a9e..000000000 --- a/3rdparty/lexy/CMakeLists.txt +++ /dev/null @@ -1,79 +0,0 @@ -# Copyright (C) 2020-2024 Jonathan Müller and lexy contributors -# SPDX-License-Identifier: BSL-1.0 - -cmake_minimum_required(VERSION 3.8) -project(lexy VERSION 2022.12.1 LANGUAGES CXX) - -set(LEXY_USER_CONFIG_HEADER "" CACHE FILEPATH "The user config header for lexy.") -option(LEXY_FORCE_CPP17 "Whether or not lexy should use C++17 even if compiler supports C++20." OFF) - -add_subdirectory(src) - -option(LEXY_ENABLE_INSTALL "whether or not to enable the install rule" ON) -if(LEXY_ENABLE_INSTALL) - include(CMakePackageConfigHelpers) - include(GNUInstallDirs) - - install(TARGETS lexy lexy_core lexy_file lexy_unicode lexy_ext _lexy_base lexy_dev - EXPORT ${PROJECT_NAME}Targets - RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} - LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} - ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}) - - install(EXPORT ${PROJECT_NAME}Targets - NAMESPACE foonathan:: - DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}") - - configure_package_config_file( - cmake/lexyConfig.cmake.in - "${PROJECT_BINARY_DIR}/${PROJECT_NAME}Config.cmake" - INSTALL_DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}") - install(FILES "${PROJECT_BINARY_DIR}/${PROJECT_NAME}Config.cmake" - DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}") - - # YYYY.MM.N1 is compatible with YYYY.MM.N2. - write_basic_package_version_file( - "${PROJECT_BINARY_DIR}/${PROJECT_NAME}ConfigVersion.cmake" - COMPATIBILITY SameMinorVersion) - - install(FILES "${PROJECT_BINARY_DIR}/${PROJECT_NAME}ConfigVersion.cmake" - DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}") - - install(DIRECTORY include/lexy include/lexy_ext - DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} - FILES_MATCHING - PATTERN "*.hpp") -endif() - -if(CMAKE_CURRENT_SOURCE_DIR STREQUAL CMAKE_SOURCE_DIR) - cmake_minimum_required(VERSION 3.18) - option(LEXY_BUILD_BENCHMARKS "whether or not benchmarks should be built" OFF) - option(LEXY_BUILD_EXAMPLES "whether or not examples should be built" ON) - option(LEXY_BUILD_TESTS "whether or not tests should be built" ON) - option(LEXY_BUILD_DOCS "whether or not docs should be built" OFF) - option(LEXY_BUILD_PACKAGE "whether or not the package should be built" ON) - - if(LEXY_BUILD_PACKAGE) - set(package_files include/ src/ cmake/ CMakeLists.txt LICENSE) - add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/lexy-src.zip - COMMAND ${CMAKE_COMMAND} -E tar c ${CMAKE_CURRENT_BINARY_DIR}/lexy-src.zip --format=zip -- ${package_files} - WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} - DEPENDS ${package_files}) - add_custom_target(lexy_package DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/lexy-src.zip) - endif() - - if(LEXY_BUILD_EXAMPLES) - add_subdirectory(examples) - endif() - if(LEXY_BUILD_BENCHMARKS) - add_subdirectory(benchmarks) - endif() - if(LEXY_BUILD_TESTS) - set(DOCTEST_NO_INSTALL ON) - enable_testing() - add_subdirectory(tests) - endif() - if(LEXY_BUILD_DOCS) - add_subdirectory(docs EXCLUDE_FROM_ALL) - endif() -endif() diff --git a/3rdparty/lexy/LICENSE b/3rdparty/lexy/LICENSE deleted file mode 100644 index 36b7cd93c..000000000 --- a/3rdparty/lexy/LICENSE +++ /dev/null @@ -1,23 +0,0 @@ -Boost Software License - Version 1.0 - August 17th, 2003 - -Permission is hereby granted, free of charge, to any person or organization -obtaining a copy of the software and accompanying documentation covered by -this license (the "Software") to use, reproduce, display, distribute, -execute, and transmit the Software, and to prepare derivative works of the -Software, and to permit third-parties to whom the Software is furnished to -do so, all subject to the following: - -The copyright notices in the Software and this entire statement, including -the above license grant, this restriction and the following disclaimer, -must be included in all copies of the Software, in whole or in part, and -all derivative works of the Software, unless such copies or derivative -works are solely in the form of machine-executable object code generated by -a source language processor. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT -SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE -FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, -ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -DEALINGS IN THE SOFTWARE. diff --git a/3rdparty/lexy/README.adoc b/3rdparty/lexy/README.adoc deleted file mode 100644 index 6bc88487f..000000000 --- a/3rdparty/lexy/README.adoc +++ /dev/null @@ -1,175 +0,0 @@ -= lexy - -ifdef::env-github[] -image:https://img.shields.io/endpoint?url=https%3A%2F%2Fwww.jonathanmueller.dev%2Fproject%2Flexy%2Findex.json[Project Status,link=https://www.jonathanmueller.dev/project/] -image:https://github.com/foonathan/lexy/workflows/Main%20CI/badge.svg[Build Status] -image:https://img.shields.io/badge/try_it_online-blue[Playground,link=https://lexy.foonathan.net/playground] -endif::[] - -lexy is a parser combinator library for {cpp}17 and onwards. -It allows you to write a parser by specifying it in a convenient {cpp} DSL, -which gives you all the flexibility and control of a handwritten parser without any of the manual work. - -ifdef::env-github[] -*Documentation*: https://lexy.foonathan.net/[lexy.foonathan.net] -endif::[] - -.IPv4 address parser --- -ifndef::env-github[] -[.godbolt-example] -.+++{{< svg "icons/play.svg" >}}+++ -endif::[] -[source,cpp] ----- -namespace dsl = lexy::dsl; - -// Parse an IPv4 address into a `std::uint32_t`. -struct ipv4_address -{ - // What is being matched. - static constexpr auto rule = []{ - // Match a sequence of (decimal) digits and convert it into a std::uint8_t. - auto octet = dsl::integer; - - // Match four of them separated by periods. - return dsl::times<4>(octet, dsl::sep(dsl::period)) + dsl::eof; - }(); - - // How the matched output is being stored. - static constexpr auto value - = lexy::callback([](std::uint8_t a, std::uint8_t b, std::uint8_t c, std::uint8_t d) { - return (a << 24) | (b << 16) | (c << 8) | d; - }); -}; ----- --- - -== Features - -Full control:: - * *Describe the parser, not some abstract grammar*: - Unlike parser generators that use some table driven magic for parsing, lexy's grammar is just syntax sugar for a hand-written recursive descent parser. - The parsing algorithm does exactly what you've instructed it to do -- no more ambiguities or weird shift/reduce errors! - * *No implicit backtracking or lookahead*: - It will only backtrack when you say it should, and only lookahead when and how far you want it. - Don't worry about rules that have side-effects, they won't be executed unnecessarily thanks to the user-specified lookahead conditions. - https://lexy.foonathan.net/playground?example=peek[Try it online]. - * *Escape hatch for manual parsing*: - Sometimes you want to parse something that can't be expressed easily with lexy's facilities. - Don't worry, you can integrate a hand-written parser into the grammar at any point. - https://lexy.foonathan.net/playground/?example=scan[Try it online]. - * *Tracing*: - Figure out why the grammar isn't working the way you want it to. - https://lexy.foonathan.net/playground/?example=trace&mode=trace[Try it online]. - -Easily integrated:: - * *A pure {cpp} DSL*: - No need to use an external grammar file; embed the grammar directly in your {cpp} project using operator overloading and functions. - * *Bring your own data structures*: - You can directly store results into your own types and have full control over all heap allocations. - * *Fully `constexpr` parsing*: - You want to parse a string literal at compile-time? You can do so. - * *Minimal standard library dependencies*: - The core parsing library only depends on fundamental headers such as `` or ``; no big includes like `` or ``. - * *Header-only core library* (by necessity, not by choice -- it's `constexpr` after all). - -ifdef::env-github[Designed for text::] -ifndef::env-github[Designed for text (e.g. {{< github-example json >}}, {{< github-example xml >}}, {{< github-example email >}}) ::] - * *Unicode support*: parse UTF-8, UTF-16, or UTF-32, and access the Unicode character database to query char classes or perform case folding. - https://lexy.foonathan.net/playground?example=identifier-unicode[Try it online]. - * *Convenience*: - Built-in rules for parsing nested structures, quotes and escape sequences. - https://lexy.foonathan.net/playground?example=parenthesized[Try it online]. - * *Automatic whitespace skipping*: - No need to manually handle whitespace or comments. - https://lexy.foonathan.net/playground/?example=whitespace_comment[Try it online]. - -ifdef::env-github[Designed for programming languages::] -ifndef::env-github[Designed for programming languages (e.g. {{< github-example calculator >}}, {{< github-example shell >}})::] - * *Keyword and identifier parsing*: - Reserve a set of keywords that won't be matched as regular identifiers. - https://lexy.foonathan.net/playground/?example=reserved_identifier[Try it online]. - * *Operator parsing*: - Parse unary/binary operators with different precedences and associativity, including chained comparisons `a < b < c`. - https://lexy.foonathan.net/playground/?example=expr[Try it online]. - * *Automatic error recovery*: - Log an error, recover, and continue parsing! - https://lexy.foonathan.net/playground/?example=recover[Try it online]. - -ifdef::env-github[Designed for binary input::] -ifndef::env-github[Designed for binary input (e.g. {{< github-example protobuf >}})::] - * *Bytes*: Rules for parsing `N` bytes or Nbit big/little endian integer. - * *Bits*: Rules for parsing individual bit patterns. - * *Blobs*: Rules for parsing TLV formats. - -== FAQ - -Why should I use lexy over XYZ?:: - lexy is closest to other PEG parsers. - However, they usually do more implicit backtracking, which can hurt performance and you need to be very careful with rules that have side-effects. - This is not the case for lexy, where backtracking is controlled using branch conditions. - lexy also gives you a lot of control over error reporting, supports error recovery, special support for operator precedence parsing, and other advanced features. - - http://boost-spirit.com/home/[Boost.Spirit]::: - The main difference: it is not a Boost library. - In addition, Boost.Spirit is quite old and doesn't support e.g. non-common ranges as input. - Boost.Spirit also eagerly creates attributes from the rules, which can lead to nested tuples/variants while lexy uses callbacks which enables zero-copy parsing directly into your own data structure. - However, lexy's grammar is more verbose and designed to parser bigger grammars instead of the small one-off rules that Boost.Spirit is good at. - https://github.com/taocpp/PEGTL[PEGTL]::: - PEGTL is very similar and was a big inspiration. - The biggest difference is that lexy uses an operator based DSL instead of inheriting from templated classes as PEGTL does; - depending on your preference this can be an advantage or disadvantage. - Hand-written Parsers::: - Writing a handwritten parser is more manual work and error prone. - lexy automates that away without having to sacrifice control. - You can use it to quickly prototype a parser and then slowly replace more and more with a handwritten parser over time; - mixing a hand-written parser and a lexy grammar works seamlessly. - -How bad are the compilation times?:: -They're not as bad as you might expect (in debug mode, that is). -+ -The example JSON parser compiles in about 2s on my machine. -If we remove all the lexy specific parts and just benchmark the time it takes for the compiler to process the datastructure (and stdlib includes), -that takes about 700ms. -If we validate JSON only instead of parsing it, so remove the data structures and keep only the lexy specific parts, we're looking at about 840ms. -+ -Keep in mind, that you can fully isolate lexy in a single translation unit that only needs to be touched when you change the parser. -You can also split a lexy grammar into multiple translation units using the `dsl::subgrammar` rule. - -How bad are the {cpp} error messages if you mess something up?:: - They're certainly worse than the error message lexy gives you. - The big problem here is that the first line gives you the error, followed by dozens of template instantiations, which end at your `lexy::parse` call. - Besides providing an external tool to filter those error messages, there is nothing I can do about that. - -How fast is it?:: - Benchmarks are available in the `benchmarks/` directory. - A sample result of the JSON validator benchmark which compares the example JSON parser with various other implementations is available https://lexy.foonathan.net/benchmark_json/[here]. - -Why is it called lexy?:: - I previously had a tokenizer library called foonathan/lex. - I've tried adding a parser to it, but found that the line between pure tokenization and parsing has become increasingly blurred. - lexy is a re-imagination on of the parser I've added to foonathan/lex, and I've simply kept a similar name. - -ifdef::env-github[] -== Documentation - -The documentation, including tutorials, reference documentation, and an interactive playground can be found at https://lexy.foonathan.net/[lexy.foonathan.net]. - -A minimal `CMakeLists.txt` that uses lexy can look like this: - -.`CMakeLists.txt` -```cmake -project(lexy-example) - -include(FetchContent) -FetchContent_Declare(lexy URL https://lexy.foonathan.net/download/lexy-src.zip) -FetchContent_MakeAvailable(lexy) - -add_executable(lexy_example) -target_sources(lexy_example PRIVATE main.cpp) -target_link_libraries(lexy_example PRIVATE foonathan::lexy) -``` - -endif::[] - diff --git a/3rdparty/lexy/cmake/lexyConfig.cmake.in b/3rdparty/lexy/cmake/lexyConfig.cmake.in deleted file mode 100644 index e6dc89d30..000000000 --- a/3rdparty/lexy/cmake/lexyConfig.cmake.in +++ /dev/null @@ -1,8 +0,0 @@ -# Copyright (C) 2020-2024 Jonathan Müller and lexy contributors -# SPDX-License-Identifier: BSL-1.0 - -# lexy CMake configuration file. - -@PACKAGE_INIT@ - -include ("${CMAKE_CURRENT_LIST_DIR}/@PROJECT_NAME@Targets.cmake") diff --git a/3rdparty/lexy/include/lexy/_detail/any_ref.hpp b/3rdparty/lexy/include/lexy/_detail/any_ref.hpp deleted file mode 100644 index 9eca714b2..000000000 --- a/3rdparty/lexy/include/lexy/_detail/any_ref.hpp +++ /dev/null @@ -1,68 +0,0 @@ -// Copyright (C) 2020-2024 Jonathan Müller and lexy contributors -// SPDX-License-Identifier: BSL-1.0 - -#ifndef LEXY_DETAIL_ANY_REF_HPP_INCLUDED -#define LEXY_DETAIL_ANY_REF_HPP_INCLUDED - -#include - -// Essentially a void*, but we can cast it in a constexpr context. -// The cost is an extra layer of indirection. - -namespace lexy::_detail -{ -template -class any_holder; - -// Store a pointer to this instead of a void*. -class any_base -{ -public: - any_base(const any_base&) = delete; - any_base& operator=(const any_base&) = delete; - - template - constexpr T& get() noexcept - { - return static_cast*>(this)->get(); - } - template - constexpr const T& get() const noexcept - { - return static_cast*>(this)->get(); - } - -private: - constexpr any_base() = default; - ~any_base() = default; - - template - friend class any_holder; -}; - -using any_ref = any_base*; -using any_cref = const any_base*; - -// Need to store the object in here. -template -class any_holder : public any_base -{ -public: - constexpr explicit any_holder(T&& obj) : _obj(LEXY_MOV(obj)) {} - - constexpr T& get() noexcept - { - return _obj; - } - constexpr const T& get() const noexcept - { - return _obj; - } - -private: - T _obj; -}; -} // namespace lexy::_detail - -#endif // LEXY_DETAIL_ANY_REF_HPP_INCLUDED - diff --git a/3rdparty/lexy/include/lexy/_detail/assert.hpp b/3rdparty/lexy/include/lexy/_detail/assert.hpp deleted file mode 100644 index 52aa115de..000000000 --- a/3rdparty/lexy/include/lexy/_detail/assert.hpp +++ /dev/null @@ -1,51 +0,0 @@ -// Copyright (C) 2020-2024 Jonathan Müller and lexy contributors -// SPDX-License-Identifier: BSL-1.0 - -#ifndef LEXY_DETAIL_ASSERT_HPP_INCLUDED -#define LEXY_DETAIL_ASSERT_HPP_INCLUDED - -#include - -#ifndef LEXY_ENABLE_ASSERT - -// By default, enable assertions if NDEBUG is not defined. - -# if NDEBUG -# define LEXY_ENABLE_ASSERT 0 -# else -# define LEXY_ENABLE_ASSERT 1 -# endif - -#endif - -#if LEXY_ENABLE_ASSERT - -// We want assertions: use assert() if that's available, otherwise abort. -// We don't use assert() directly as that's not constexpr. - -# if NDEBUG - -# include -# define LEXY_PRECONDITION(Expr) ((Expr) ? void(0) : std::abort()) -# define LEXY_ASSERT(Expr, Msg) ((Expr) ? void(0) : std::abort()) - -# else - -# include - -# define LEXY_PRECONDITION(Expr) ((Expr) ? void(0) : assert(Expr)) -# define LEXY_ASSERT(Expr, Msg) ((Expr) ? void(0) : assert((Expr) && (Msg))) - -# endif - -#else - -// We don't want assertions. - -# define LEXY_PRECONDITION(Expr) static_cast(sizeof(Expr)) -# define LEXY_ASSERT(Expr, Msg) static_cast(sizeof(Expr)) - -#endif - -#endif // LEXY_DETAIL_ASSERT_HPP_INCLUDED - diff --git a/3rdparty/lexy/include/lexy/_detail/buffer_builder.hpp b/3rdparty/lexy/include/lexy/_detail/buffer_builder.hpp deleted file mode 100644 index 94ba1fd27..000000000 --- a/3rdparty/lexy/include/lexy/_detail/buffer_builder.hpp +++ /dev/null @@ -1,160 +0,0 @@ -// Copyright (C) 2020-2024 Jonathan Müller and lexy contributors -// SPDX-License-Identifier: BSL-1.0 - -#ifndef LEXY_DETAIL_BUFFER_BUILDER_HPP_INCLUDED -#define LEXY_DETAIL_BUFFER_BUILDER_HPP_INCLUDED - -#include -#include -#include -#include -#include - -namespace lexy::_detail -{ -// Builds a buffer: it has a read are and a write area. -// The characters in the read area are already valid and can be read. -// The characters in the write area are not valid, but can be written too. -template -class buffer_builder -{ - static_assert(std::is_trivial_v); - - static constexpr std::size_t total_size_bytes = 1024; - static constexpr std::size_t stack_buffer_size - = (total_size_bytes - 3 * sizeof(T*)) / sizeof(T); - static constexpr auto growth_factor = 2; - -public: - buffer_builder() noexcept : _data(_stack_buffer), _read_size(0), _write_size(stack_buffer_size) - { - static_assert(sizeof(*this) == total_size_bytes, "invalid buffer size calculation"); - } - - ~buffer_builder() noexcept - { - // Free memory if we allocated any. - if (_data != _stack_buffer) - ::operator delete(_data); - } - - buffer_builder(const buffer_builder&) = delete; - buffer_builder& operator=(const buffer_builder&) = delete; - - // The total capacity: read + write. - std::size_t capacity() const noexcept - { - return _read_size + _write_size; - } - - // The read area. - const T* read_data() const noexcept - { - return _data; - } - std::size_t read_size() const noexcept - { - return _read_size; - } - - // The write area. - T* write_data() noexcept - { - return _data + _read_size; - } - std::size_t write_size() const noexcept - { - return _write_size; - } - - // Clears the read area. - void clear() noexcept - { - _write_size += _read_size; - _read_size = 0; - } - - // Takes the first n characters of the write area and appends them to the read area. - void commit(std::size_t n) noexcept - { - LEXY_PRECONDITION(n <= _write_size); - _read_size += n; - _write_size -= n; - } - - // Increases the write area, invalidates all pointers. - void grow() - { - const auto cur_cap = capacity(); - const auto new_cap = growth_factor * cur_cap; - - // Allocate new memory. - auto memory = static_cast(::operator new(new_cap * sizeof(T))); - // Copy the read area into the new memory. - std::memcpy(memory, _data, _read_size); - - // Release the old memory, if there was any. - if (_data != _stack_buffer) - ::operator delete(_data); - - // Update for the new area. - _data = memory; - // _read_size hasn't been changed - _write_size = new_cap - _read_size; - } - - //=== iterator ===// - // Stable iterator over the memory. - class stable_iterator : public forward_iterator_base - { - public: - constexpr stable_iterator() = default; - - explicit constexpr stable_iterator(const _detail::buffer_builder& buffer, - std::size_t idx) noexcept - : _buffer(&buffer), _idx(idx) - {} - - constexpr const T& deref() const noexcept - { - LEXY_PRECONDITION(_idx != _buffer->read_size()); - return _buffer->read_data()[_idx]; - } - - constexpr void increment() noexcept - { - LEXY_PRECONDITION(_idx != _buffer->read_size()); - ++_idx; - } - - constexpr bool equal(stable_iterator rhs) const noexcept - { - if (!_buffer || !rhs._buffer) - return !_buffer && !rhs._buffer; - else - { - LEXY_PRECONDITION(_buffer == rhs._buffer); - return _idx == rhs._idx; - } - } - - constexpr std::size_t index() const noexcept - { - return _idx; - } - - private: - const _detail::buffer_builder* _buffer = nullptr; - std::size_t _idx = 0; - }; - -private: - T* _data; - std::size_t _read_size; - std::size_t _write_size; - T _stack_buffer[stack_buffer_size]; -}; -} // namespace lexy::_detail - -#endif // LEXY_DETAIL_BUFFER_BUILDER_HPP_INCLUDED - diff --git a/3rdparty/lexy/include/lexy/_detail/code_point.hpp b/3rdparty/lexy/include/lexy/_detail/code_point.hpp deleted file mode 100644 index bc805b11e..000000000 --- a/3rdparty/lexy/include/lexy/_detail/code_point.hpp +++ /dev/null @@ -1,368 +0,0 @@ -// Copyright (C) 2020-2024 Jonathan Müller and lexy contributors -// SPDX-License-Identifier: BSL-1.0 - -#ifndef LEXY_DETAIL_CODE_POINT_HPP_INCLUDED -#define LEXY_DETAIL_CODE_POINT_HPP_INCLUDED - -#include - -//=== encoding ===// -namespace lexy::_detail -{ -template -constexpr std::size_t encode_code_point(char32_t cp, typename Encoding::char_type* buffer, - std::size_t size) -{ - if constexpr (std::is_same_v) - { - LEXY_PRECONDITION(size >= 1); - - *buffer = char(cp); - return 1; - } - else if constexpr (std::is_same_v // - || std::is_same_v) - { - using char_type = typename Encoding::char_type; - // Taken from http://www.herongyang.com/Unicode/UTF-8-UTF-8-Encoding-Algorithm.html. - if (cp <= 0x7F) - { - LEXY_PRECONDITION(size >= 1); - - buffer[0] = char_type(cp); - return 1; - } - else if (cp <= 0x07'FF) - { - LEXY_PRECONDITION(size >= 2); - - auto first = (cp >> 6) & 0x1F; - auto second = (cp >> 0) & 0x3F; - - buffer[0] = char_type(0xC0 | first); - buffer[1] = char_type(0x80 | second); - return 2; - } - else if (cp <= 0xFF'FF) - { - LEXY_PRECONDITION(size >= 3); - - auto first = (cp >> 12) & 0x0F; - auto second = (cp >> 6) & 0x3F; - auto third = (cp >> 0) & 0x3F; - - buffer[0] = char_type(0xE0 | first); - buffer[1] = char_type(0x80 | second); - buffer[2] = char_type(0x80 | third); - return 3; - } - else - { - LEXY_PRECONDITION(size >= 4); - - auto first = (cp >> 18) & 0x07; - auto second = (cp >> 12) & 0x3F; - auto third = (cp >> 6) & 0x3F; - auto fourth = (cp >> 0) & 0x3F; - - buffer[0] = char_type(0xF0 | first); - buffer[1] = char_type(0x80 | second); - buffer[2] = char_type(0x80 | third); - buffer[3] = char_type(0x80 | fourth); - return 4; - } - } - else if constexpr (std::is_same_v) - { - if (cp <= 0xFF'FF) - { - LEXY_PRECONDITION(size >= 1); - - buffer[0] = char16_t(cp); - return 1; - } - else - { - // Algorithm implemented from - // https://en.wikipedia.org/wiki/UTF-16#Code_points_from_U+010000_to_U+10FFFF. - LEXY_PRECONDITION(size >= 2); - - auto u_prime = cp - 0x1'0000; - auto high_ten_bits = u_prime >> 10; - auto low_ten_bits = u_prime & 0b0000'0011'1111'1111; - - buffer[0] = char16_t(0xD800 + high_ten_bits); - buffer[1] = char16_t(0xDC00 + low_ten_bits); - return 2; - } - } - else if constexpr (std::is_same_v) - { - LEXY_PRECONDITION(size >= 1); - - *buffer = char32_t(cp); - return 1; - } - else - { - static_assert(lexy::_detail::error, - "cannot encode a code point in this encoding"); - (void)cp; - (void)buffer; - (void)size; - return 0; - } -} -} // namespace lexy::_detail - -//=== parsing ===// -namespace lexy::_detail -{ -enum class cp_error -{ - success, - eof, - leads_with_trailing, - missing_trailing, - surrogate, - overlong_sequence, - out_of_range, -}; - -template -struct cp_result -{ - char32_t cp; - cp_error error; - typename Reader::marker end; -}; - -template -constexpr cp_result parse_code_point(Reader reader) -{ - if constexpr (std::is_same_v) - { - if (reader.peek() == Reader::encoding::eof()) - return {{}, cp_error::eof, reader.current()}; - - auto cur = reader.peek(); - reader.bump(); - - auto cp = static_cast(cur); - if (cp <= 0x7F) - return {cp, cp_error::success, reader.current()}; - else - return {cp, cp_error::out_of_range, reader.current()}; - } - else if constexpr (std::is_same_v // - || std::is_same_v) - { - using uchar_t = unsigned char; - constexpr auto payload_lead1 = 0b0111'1111; - constexpr auto payload_lead2 = 0b0001'1111; - constexpr auto payload_lead3 = 0b0000'1111; - constexpr auto payload_lead4 = 0b0000'0111; - constexpr auto payload_cont = 0b0011'1111; - - constexpr auto pattern_lead1 = 0b0 << 7; - constexpr auto pattern_lead2 = 0b110 << 5; - constexpr auto pattern_lead3 = 0b1110 << 4; - constexpr auto pattern_lead4 = 0b11110 << 3; - constexpr auto pattern_cont = 0b10 << 6; - - auto first = uchar_t(reader.peek()); - if ((first & ~payload_lead1) == pattern_lead1) - { - // ASCII character. - reader.bump(); - return {first, cp_error::success, reader.current()}; - } - else if ((first & ~payload_cont) == pattern_cont) - { - return {{}, cp_error::leads_with_trailing, reader.current()}; - } - else if ((first & ~payload_lead2) == pattern_lead2) - { - reader.bump(); - - auto second = uchar_t(reader.peek()); - if ((second & ~payload_cont) != pattern_cont) - return {{}, cp_error::missing_trailing, reader.current()}; - reader.bump(); - - auto result = char32_t(first & payload_lead2); - result <<= 6; - result |= char32_t(second & payload_cont); - - // C0 and C1 are overlong ASCII. - if (first == 0xC0 || first == 0xC1) - return {result, cp_error::overlong_sequence, reader.current()}; - else - return {result, cp_error::success, reader.current()}; - } - else if ((first & ~payload_lead3) == pattern_lead3) - { - reader.bump(); - - auto second = uchar_t(reader.peek()); - if ((second & ~payload_cont) != pattern_cont) - return {{}, cp_error::missing_trailing, reader.current()}; - reader.bump(); - - auto third = uchar_t(reader.peek()); - if ((third & ~payload_cont) != pattern_cont) - return {{}, cp_error::missing_trailing, reader.current()}; - reader.bump(); - - auto result = char32_t(first & payload_lead3); - result <<= 6; - result |= char32_t(second & payload_cont); - result <<= 6; - result |= char32_t(third & payload_cont); - - auto cp = result; - if (0xD800 <= cp && cp <= 0xDFFF) - return {cp, cp_error::surrogate, reader.current()}; - else if (first == 0xE0 && second < 0xA0) - return {cp, cp_error::overlong_sequence, reader.current()}; - else - return {cp, cp_error::success, reader.current()}; - } - else if ((first & ~payload_lead4) == pattern_lead4) - { - reader.bump(); - - auto second = uchar_t(reader.peek()); - if ((second & ~payload_cont) != pattern_cont) - return {{}, cp_error::missing_trailing, reader.current()}; - reader.bump(); - - auto third = uchar_t(reader.peek()); - if ((third & ~payload_cont) != pattern_cont) - return {{}, cp_error::missing_trailing, reader.current()}; - reader.bump(); - - auto fourth = uchar_t(reader.peek()); - if ((fourth & ~payload_cont) != pattern_cont) - return {{}, cp_error::missing_trailing, reader.current()}; - reader.bump(); - - auto result = char32_t(first & payload_lead4); - result <<= 6; - result |= char32_t(second & payload_cont); - result <<= 6; - result |= char32_t(third & payload_cont); - result <<= 6; - result |= char32_t(fourth & payload_cont); - - auto cp = result; - if (cp > 0x10'FFFF) - return {cp, cp_error::out_of_range, reader.current()}; - else if (first == 0xF0 && second < 0x90) - return {cp, cp_error::overlong_sequence, reader.current()}; - else - return {cp, cp_error::success, reader.current()}; - } - else // FE or FF - { - return {{}, cp_error::eof, reader.current()}; - } - } - else if constexpr (std::is_same_v) - { - constexpr auto payload1 = 0b0000'0011'1111'1111; - constexpr auto payload2 = payload1; - - constexpr auto pattern1 = 0b110110 << 10; - constexpr auto pattern2 = 0b110111 << 10; - - if (reader.peek() == Reader::encoding::eof()) - return {{}, cp_error::eof, reader.current()}; - - auto first = char16_t(reader.peek()); - if ((first & ~payload1) == pattern1) - { - reader.bump(); - if (reader.peek() == Reader::encoding::eof()) - return {{}, cp_error::missing_trailing, reader.current()}; - - auto second = char16_t(reader.peek()); - if ((second & ~payload2) != pattern2) - return {{}, cp_error::missing_trailing, reader.current()}; - reader.bump(); - - // We've got a valid code point. - auto result = char32_t(first & payload1); - result <<= 10; - result |= char32_t(second & payload2); - result |= 0x10000; - return {result, cp_error::success, reader.current()}; - } - else if ((first & ~payload2) == pattern2) - { - return {{}, cp_error::leads_with_trailing, reader.current()}; - } - else - { - // Single code unit code point; always valid. - reader.bump(); - return {first, cp_error::success, reader.current()}; - } - } - else if constexpr (std::is_same_v) - { - if (reader.peek() == Reader::encoding::eof()) - return {{}, cp_error::eof, reader.current()}; - - auto cur = reader.peek(); - reader.bump(); - - auto cp = cur; - if (cp > 0x10'FFFF) - return {cp, cp_error::out_of_range, reader.current()}; - else if (0xD800 <= cp && cp <= 0xDFFF) - return {cp, cp_error::surrogate, reader.current()}; - else - return {cp, cp_error::success, reader.current()}; - } - else - { - static_assert(lexy::_detail::error, - "no known code point for this encoding"); - return {}; - } -} - -template -constexpr void recover_code_point(Reader& reader, cp_result result) -{ - switch (result.error) - { - case cp_error::success: - // Consume the entire code point. - reader.reset(result.end); - break; - case cp_error::eof: - // We don't need to do anything to "recover" from EOF. - break; - - case cp_error::leads_with_trailing: - // Invalid code unit, consume to recover. - LEXY_PRECONDITION(result.end.position() == reader.position()); - reader.bump(); - break; - - case cp_error::missing_trailing: - case cp_error::surrogate: - case cp_error::out_of_range: - case cp_error::overlong_sequence: - // Consume all the invalid code units to recover. - reader.reset(result.end); - break; - } -} -} // namespace lexy::_detail - -#endif // LEXY_DETAIL_CODE_POINT_HPP_INCLUDED - diff --git a/3rdparty/lexy/include/lexy/_detail/config.hpp b/3rdparty/lexy/include/lexy/_detail/config.hpp deleted file mode 100644 index 4aa40135b..000000000 --- a/3rdparty/lexy/include/lexy/_detail/config.hpp +++ /dev/null @@ -1,199 +0,0 @@ -// Copyright (C) 2020-2024 Jonathan Müller and lexy contributors -// SPDX-License-Identifier: BSL-1.0 - -#ifndef LEXY_DETAIL_CONFIG_HPP_INCLUDED -#define LEXY_DETAIL_CONFIG_HPP_INCLUDED - -#include -#include - -#if defined(LEXY_USER_CONFIG_HEADER) -# include LEXY_USER_CONFIG_HEADER -#elif defined(__has_include) -# if __has_include() -# include -# elif __has_include("lexy_user_config.hpp") -# include "lexy_user_config.hpp" -# endif -#endif - -#ifndef LEXY_HAS_UNICODE_DATABASE -# define LEXY_HAS_UNICODE_DATABASE 0 -#endif - -#ifndef LEXY_EXPERIMENTAL -# define LEXY_EXPERIMENTAL 0 -#endif - -//=== utility traits===// -#define LEXY_MOV(...) static_cast&&>(__VA_ARGS__) -#define LEXY_FWD(...) static_cast(__VA_ARGS__) - -#define LEXY_DECLVAL(...) lexy::_detail::declval<__VA_ARGS__>() - -#define LEXY_DECAY_DECLTYPE(...) std::decay_t - -/// Creates a new type from the instantiation of a template. -/// This is used to shorten type names. -#define LEXY_INSTANTIATION_NEWTYPE(Name, Templ, ...) \ - struct Name : Templ<__VA_ARGS__> \ - { \ - using Templ<__VA_ARGS__>::Templ; \ - } - -namespace lexy::_detail -{ -template -constexpr bool error = false; - -template -std::add_rvalue_reference_t declval(); - -template -constexpr void swap(T& lhs, T& rhs) -{ - T tmp = LEXY_MOV(lhs); - lhs = LEXY_MOV(rhs); - rhs = LEXY_MOV(tmp); -} - -template -constexpr bool is_decayed_same = std::is_same_v, std::decay_t>; - -template -using type_or = std::conditional_t, Fallback, T>; -} // namespace lexy::_detail - -//=== NTTP ===// -#ifndef LEXY_HAS_NTTP -// See https://github.com/foonathan/lexy/issues/15. -# if __cpp_nontype_template_parameter_class >= 201806 || __cpp_nontype_template_args >= 201911 -# define LEXY_HAS_NTTP 1 -# else -# define LEXY_HAS_NTTP 0 -# endif -#endif - -#if LEXY_HAS_NTTP -# define LEXY_NTTP_PARAM auto -#else -# define LEXY_NTTP_PARAM const auto& -#endif - -//=== consteval ===// -#ifndef LEXY_HAS_CONSTEVAL -# if defined(_MSC_VER) && !defined(__clang__) -// Currently can't handle returning strings from consteval, check back later. -# define LEXY_HAS_CONSTEVAL 0 -# elif __cpp_consteval -# define LEXY_HAS_CONSTEVAL 1 -# else -# define LEXY_HAS_CONSTEVAL 0 -# endif -#endif - -#if LEXY_HAS_CONSTEVAL -# define LEXY_CONSTEVAL consteval -#else -# define LEXY_CONSTEVAL constexpr -#endif - -//=== constexpr ===// -#ifndef LEXY_HAS_CONSTEXPR_DTOR -# if __cpp_constexpr_dynamic_alloc -# define LEXY_HAS_CONSTEXPR_DTOR 1 -# else -# define LEXY_HAS_CONSTEXPR_DTOR 0 -# endif -#endif - -#if LEXY_HAS_CONSTEXPR_DTOR -# define LEXY_CONSTEXPR_DTOR constexpr -#else -# define LEXY_CONSTEXPR_DTOR -#endif - -//=== char8_t ===// -#ifndef LEXY_HAS_CHAR8_T -# if __cpp_char8_t -# define LEXY_HAS_CHAR8_T 1 -# else -# define LEXY_HAS_CHAR8_T 0 -# endif -#endif - -#if LEXY_HAS_CHAR8_T - -# define LEXY_CHAR_OF_u8 char8_t -# define LEXY_CHAR8_T char8_t -# define LEXY_CHAR8_STR(Str) u8##Str - -#else - -namespace lexy -{ -using _char8_t = unsigned char; -} // namespace lexy - -# define LEXY_CHAR_OF_u8 char -# define LEXY_CHAR8_T ::lexy::_char8_t -# define LEXY_CHAR8_STR(Str) \ - LEXY_NTTP_STRING(::lexy::_detail::type_string, u8##Str)::c_str - -#endif - -//=== endianness ===// -#ifndef LEXY_IS_LITTLE_ENDIAN -# if defined(__BYTE_ORDER__) -# if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ -# define LEXY_IS_LITTLE_ENDIAN 1 -# elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ -# define LEXY_IS_LITTLE_ENDIAN 0 -# else -# error "unsupported byte order" -# endif -# elif defined(_MSC_VER) -# define LEXY_IS_LITTLE_ENDIAN 1 -# else -# error "unknown endianness" -# endif -#endif - -//=== force inline ===// -#ifndef LEXY_FORCE_INLINE -# if defined(__has_cpp_attribute) -# if __has_cpp_attribute(gnu::always_inline) -# define LEXY_FORCE_INLINE [[gnu::always_inline]] -# endif -# endif -# -# ifndef LEXY_FORCE_INLINE -# define LEXY_FORCE_INLINE inline -# endif -#endif - -//=== empty_member ===// -#ifndef LEXY_EMPTY_MEMBER - -# if defined(__has_cpp_attribute) -# if defined(__GNUC__) && !defined(__clang__) && __GNUC__ <= 11 -// GCC <= 11 has buggy support, see https://gcc.gnu.org/bugzilla/show_bug.cgi?id=101040 -# define LEXY_HAS_EMPTY_MEMBER 0 -# elif __has_cpp_attribute(no_unique_address) -# define LEXY_HAS_EMPTY_MEMBER 1 -# endif -# endif -# ifndef LEXY_HAS_EMPTY_MEMBER -# define LEXY_HAS_EMPTY_MEMBER 0 -# endif - -# if LEXY_HAS_EMPTY_MEMBER -# define LEXY_EMPTY_MEMBER [[no_unique_address]] -# else -# define LEXY_EMPTY_MEMBER -# endif - -#endif - -#endif // LEXY_DETAIL_CONFIG_HPP_INCLUDED - diff --git a/3rdparty/lexy/include/lexy/_detail/detect.hpp b/3rdparty/lexy/include/lexy/_detail/detect.hpp deleted file mode 100644 index 7534c44c4..000000000 --- a/3rdparty/lexy/include/lexy/_detail/detect.hpp +++ /dev/null @@ -1,35 +0,0 @@ -// Copyright (C) 2020-2024 Jonathan Müller and lexy contributors -// SPDX-License-Identifier: BSL-1.0 - -#ifndef LEXY_DETAIL_DETECT_HPP_INCLUDED -#define LEXY_DETAIL_DETECT_HPP_INCLUDED - -#include - -namespace lexy::_detail -{ -template -using void_t = void; - -template