diff --git a/.clang-tidy b/.clang-tidy index 1cb4f15..ffc574a 100644 --- a/.clang-tidy +++ b/.clang-tidy @@ -7,11 +7,11 @@ Checks: modernize-*, performance-*, portability-*, - readability-* - -HeaderFilterRegex: 'src' -FormatStyle: file - + readability-*, + -readability-function-cognitive-complexity, + -bugprone-suspicious-stringview-data-usage +WarningsAsErrors: '' +HeaderFilterRegex: '' CheckOptions: - key: readability-identifier-naming.StaticVariableCase value: lower_case @@ -52,9 +52,9 @@ CheckOptions: - key: readability-identifier-naming.PrivateMethodCase value: lower_case - key: readability-identifier-naming.PublicMethodCase - value: camelCase + value: camelBack - key: readability-identifier-naming.ProtectedMethodCase - value: camelCase + value: camelBack - key: readability-identifier-naming.ConstexprVariableCase value: UPPER_CASE @@ -66,3 +66,4 @@ CheckOptions: - key: readability-identifier-naming.NamespaceCase value: CamelCase +... diff --git a/.github/workflows/check-code-formatting.yml b/.github/workflows/check-code-formatting.yml deleted file mode 100644 index 6eab6d9..0000000 --- a/.github/workflows/check-code-formatting.yml +++ /dev/null @@ -1,14 +0,0 @@ -name: clang-format Check - -on: [pull_request] - -jobs: - formatting-check: - name: Formatting Check - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - - name: Run clang-format style check for C/C++/Protobuf programs. - uses: jidicula/clang-format-action@v4.14.0 - with: - clang-format-version: "15" diff --git a/.github/workflows/clang-tidy-ci.yml b/.github/workflows/clang-tidy-ci.yml new file mode 100644 index 0000000..72f23b1 --- /dev/null +++ b/.github/workflows/clang-tidy-ci.yml @@ -0,0 +1,56 @@ +name: clang-tidy-ci +run-name: Run clang-tidy on PR + +on: [pull_request] + +jobs: + clang-tidy-ci: + runs-on: ubuntu-latest + permissions: + contents: write + steps: + - uses: actions/checkout@v5 + with: + fetch-depth: 0 + + - uses: actions/setup-python@v6 + with: + python-version: '3.13' + + - name: Install dependencies + run: | + sudo apt-get update + sudo apt-get install -y cmake ninja-build doxygen clang-tidy libglib2.0-dev + pip3 install pyyaml + + - name: Configure, build and test + run: cmake --workflow --preset default-develop + + - name: clang-tidy + run: | + # Ensure upstream remote exists and is up to date + git remote add upstream "https://github.com/${{ github.event.pull_request.base.repo.full_name }}" + git fetch --no-tags --no-recurse-submodules upstream "${{ github.event.pull_request.base.ref }}" + + # Prepare directory for clang-tidy fixes + mkdir -p ${{ runner.temp }}/clang-tidy-fixes + + # Generate diff from base branch and run clang-tidy + BASE_COMMIT=$(git merge-base HEAD "upstream/${{ github.event.pull_request.base.ref }}") + git diff -U0 "$BASE_COMMIT" | \ + clang-tidy-diff -p1 \ + -path "build/default-develop" \ + -export-fixes "${{ runner.temp }}/clang-tidy-fixes/clang-tidy-fixes.yml" + + + - name: Export PR variables + run: | + echo "${{ github.event.number }}" > ${{ runner.temp }}/clang-tidy-fixes/pr_number + echo "${{ github.event.pull_request.head.repo.full_name }}" > ${{ runner.temp }}/clang-tidy-fixes/pr-head-repo + echo "${{ github.event.pull_request.head.sha }}" > ${{ runner.temp }}/clang-tidy-fixes/pr-head-sha + + - uses: actions/upload-artifact@v4 + with: + name: clang-tidy-fixes + path: | + ${{ runner.temp }}/clang-tidy-fixes/* diff --git a/.github/workflows/lint.yml b/.github/workflows/clang-tidy-comments.yml similarity index 78% rename from .github/workflows/lint.yml rename to .github/workflows/clang-tidy-comments.yml index 6c52648..2668ab2 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/clang-tidy-comments.yml @@ -1,24 +1,23 @@ -name: Lint and Comment on PR +name: clang-tidy-comments +run-name: Post clang-tidy comments on PR on: workflow_run: - workflows: [push-build-test-lint-release] + workflows: [clang-tidy-ci] types: - completed jobs: - lint-and-comment: - if: ${{ github.event.workflow_run.conclusion == 'success' }} + clang-tidy-comments: runs-on: ubuntu-latest permissions: actions: read pull-requests: write - steps: - - name: 'Download artifact' + - name: 'Download clang-tidy-fixes' uses: actions/download-artifact@v4 with: - name: common + name: clang-tidy-fixes github-token: ${{ secrets.GITHUB_TOKEN }} run-id: ${{ github.event.workflow_run.id }} path: ${{ runner.temp }} @@ -30,7 +29,7 @@ jobs: echo "prn=$(cat pr_number)" >> $GITHUB_OUTPUT echo "prhr=$(cat pr-head-repo)" >> $GITHUB_OUTPUT echo "prhs=$(cat pr-head-sha)" >> $GITHUB_OUTPUT - if [ -f "clang-fixes.yml" ]; then + if [ -f "clang-tidy-fixes.yml" ]; then echo "exists=true" >> $GITHUB_OUTPUT else echo "exists=false" >> $GITHUB_OUTPUT @@ -49,7 +48,6 @@ jobs: uses: platisd/clang-tidy-pr-comments@v1 with: github_token: ${{ secrets.GITHUB_TOKEN }} - clang_tidy_fixes: ${{ runner.temp }}/clang-fixes.yml + clang_tidy_fixes: ${{ runner.temp }}/clang-tidy-fixes.yml pull_request_id: ${{ steps.getprv.outputs.prn }} - request_changes: false - + request_changes: false diff --git a/.github/workflows/code-format.yml b/.github/workflows/code-format.yml deleted file mode 100644 index b007929..0000000 --- a/.github/workflows/code-format.yml +++ /dev/null @@ -1,52 +0,0 @@ -name: Code Format and Auto PR - -on: - pull_request_target: - types: [closed] - branches: [develop] - -jobs: - format-and-pr: - if: ${{ github.event.pull_request.merged == true && startsWith(github.base_ref, 'develop') }} - runs-on: ubuntu-latest - permissions: - contents: write - pull-requests: write - - steps: - - name: Checkout target repo - uses: actions/checkout@v4 - - # --- C/C++ --- - - name: Format C/C++ with clang-format - run: | - sudo apt-get update - sudo apt-get install -y clang-format - find . -regex '.*\.\(cpp\|hpp\|cu\|cuh\|c\|h\)' -exec clang-format -style=file -i {} \; - - # --- CMake --- - - name: Format CMake files - run: | - sudo apt-get update - sudo apt-get install -y pipx - pipx install cmakelang - find . -regex '.*\.\(cmake\)' -exec cmake-format -i {} \; - find . -name 'CMakeLists.txt' -exec cmake-format -i {} \; - - # --- JSON --- - - name: Format JSON files - run: | - sudo apt-get update - sudo apt-get install -y jq - find . -regex '.*\.\(json\)' -exec bash -c "jq . {} > {}.tmp && mv {}.tmp {}" \; - - # --- Create Pull Request --- - - name: Create PR with formatted code - uses: peter-evans/create-pull-request@v6.0.4 - with: - commit-message: C/C++/QML formatted code - branch: formatted_code - author: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> - title: Fix the format of your nice code - body: Every time you change the format, I am here to fix your mess. - diff --git a/.github/workflows/conf-build-test.yml b/.github/workflows/conf-build-test.yml index 1aee068..6fc9c8e 100644 --- a/.github/workflows/conf-build-test.yml +++ b/.github/workflows/conf-build-test.yml @@ -5,8 +5,8 @@ on: push: tags: - 'v*' - pull_request: - branches: [main, develop] + # pull_request: + # branches: [main, develop] jobs: build_test_package: @@ -128,4 +128,3 @@ jobs: - name: Deploy to GitHub Pages id: deployment uses: actions/deploy-pages@v4 - diff --git a/.github/workflows/pre-commit.yml b/.github/workflows/pre-commit.yml new file mode 100644 index 0000000..c68cca3 --- /dev/null +++ b/.github/workflows/pre-commit.yml @@ -0,0 +1,13 @@ +name: build-and-checks + +on: [pull_request] + +jobs: + pre-commit: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-python@v6 + - uses: pre-commit/action@v3.0.1 + with: + extra_args: --all-files --show-diff-on-failure diff --git a/.github/workflows/recreate-develop.yml b/.github/workflows/recreate-develop.yml deleted file mode 100644 index fd9ddfa..0000000 --- a/.github/workflows/recreate-develop.yml +++ /dev/null @@ -1,35 +0,0 @@ -name: Auto-Create Develop Branch -run-name: Recreating develop branch - -on: - pull_request_target: - types: [closed] - branches: [main] - -jobs: - create-develop-branch: - if: ${{ github.event.pull_request.merged == true && startsWith(github.base_ref, 'main') && startsWith(github.head_ref, 'develop') }} - runs-on: ubuntu-latest - permissions: - contents: write - - steps: - - name: Checkout Repository - uses: actions/checkout@v4 - - - name: Set Up Git - run: | - git config --global user.name "${{ github.actor }}" - git config --global user.email "${{ github.actor }}@users.noreply.github.com" - - - name: Delete existing 'develop' branch (if exists) - run: | - git fetch origin - git push origin --delete develop || echo "Branch 'develop' does not exist on remote." - - - name: Create new 'develop' branch from main - run: | - git checkout main - git checkout -b develop - git push origin develop - diff --git a/.gitignore b/.gitignore index 37bf44f..eabf9c6 100644 --- a/.gitignore +++ b/.gitignore @@ -1,7 +1,239 @@ -.vscode -build* doc tags -CMakeUserPresets.json + +*build*/ +*.cache* dbus_xml/net.connman/*.h dbus_xml/net.connman/*.c + +# Created by https://www.toptal.com/developers/gitignore/api/clion+all,visualstudiocode,qtcreator,cmake,c,c++ +# Edit at https://www.toptal.com/developers/gitignore?templates=clion+all,visualstudiocode,qtcreator,cmake,c,c++ + +### C ### +# Prerequisites +*.d + +# Object files +*.o +*.ko +*.obj +*.elf + +# Linker output +*.ilk +*.map +*.exp + +# Precompiled Headers +*.gch +*.pch + +# Libraries +*.lib +*.a +*.la +*.lo + +# Shared objects (inc. Windows DLLs) +*.dll +*.so +*.so.* +*.dylib + +# Executables +*.exe +*.out +*.app +*.i*86 +*.x86_64 +*.hex + +# Debug files +*.dSYM/ +*.su +*.idb +*.pdb + +# Kernel Module Compile Results +*.mod* +*.cmd +.tmp_versions/ +modules.order +Module.symvers +Mkfile.old +dkms.conf + +### C++ ### +# Prerequisites + +# Compiled Object files +*.slo + +# Precompiled Headers + +# Compiled Dynamic libraries + +# Fortran module files +*.mod +*.smod + +# Compiled Static libraries +*.lai + +# Executables + +### CLion+all ### +# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio, WebStorm and Rider +# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839 + +# User-specific stuff +.idea/**/workspace.xml +.idea/**/tasks.xml +.idea/**/usage.statistics.xml +.idea/**/dictionaries +.idea/**/shelf + +# AWS User-specific +.idea/**/aws.xml + +# Generated files +.idea/**/contentModel.xml + +# Sensitive or high-churn files +.idea/**/dataSources/ +.idea/**/dataSources.ids +.idea/**/dataSources.local.xml +.idea/**/sqlDataSources.xml +.idea/**/dynamic.xml +.idea/**/uiDesigner.xml +.idea/**/dbnavigator.xml + +# Gradle +.idea/**/gradle.xml +.idea/**/libraries + +# Gradle and Maven with auto-import +# When using Gradle or Maven with auto-import, you should exclude module files, +# since they will be recreated, and may cause churn. Uncomment if using +# auto-import. +# .idea/artifacts +# .idea/compiler.xml +# .idea/jarRepositories.xml +# .idea/modules.xml +# .idea/*.iml +# .idea/modules +# *.iml +# *.ipr + +# CMake +cmake-build-*/ + +# Mongo Explorer plugin +.idea/**/mongoSettings.xml + +# File-based project format +*.iws + +# IntelliJ +out/ + +# mpeltonen/sbt-idea plugin +.idea_modules/ + +# JIRA plugin +atlassian-ide-plugin.xml + +# Cursive Clojure plugin +.idea/replstate.xml + +# SonarLint plugin +.idea/sonarlint/ + +# Crashlytics plugin (for Android Studio and IntelliJ) +com_crashlytics_export_strings.xml +crashlytics.properties +crashlytics-build.properties +fabric.properties + +# Editor-based Rest Client +.idea/httpRequests + +# Android studio 3.1+ serialized cache file +.idea/caches/build_file_checksums.ser + +### CLion+all Patch ### +# Ignore everything but code style settings and run configurations +# that are supposed to be shared within teams. + +.idea/* + +!.idea/codeStyles +!.idea/runConfigurations + +### CMake ### +CMakeLists.txt.user +CMakeCache.txt +CMakeFiles +CMakeScripts +Testing +Makefile +cmake_install.cmake +install_manifest.txt +compile_commands.json +CTestTestfile.cmake +_deps + +### CMake Patch ### +CMakeUserPresets.json + +# External projects +*-prefix/ + +### QtCreator ### +# gitignore for Qt Creator like IDE for pure C/C++ project without Qt +# +# Reference: http://doc.qt.io/qtcreator/creator-project-generic.html + + + +# Qt Creator autogenerated files + + +# A listing of all the files included in the project +*.files + +# Include directories +*.includes + +# Project configuration settings like predefined Macros +*.config + +# Qt Creator settings +*.creator + +# User project settings +*.creator.user* + +# Qt Creator backups +*.autosave + +# Flags for Clang Code Model +*.cxxflags +*.cflags + + +### VisualStudioCode ### +.vscode/* + +# Local History for Visual Studio Code +.history/ + +# Built Visual Studio Code Extensions +*.vsix + +### VisualStudioCode Patch ### +# Ignore all local history of files +.history +.ionide + +# End of https://www.toptal.com/developers/gitignore/api/clion+all,visualstudiocode,qtcreator,cmake,c,c++ diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml new file mode 100644 index 0000000..3d37a3e --- /dev/null +++ b/.pre-commit-config.yaml @@ -0,0 +1,15 @@ +fail_fast: false + +repos: + - repo: https://github.com/pre-commit/pre-commit-hooks + rev: v6.0.0 + hooks: + - id: check-json + - id: end-of-file-fixer + - id: mixed-line-ending + - id: trailing-whitespace + - repo: https://github.com/pre-commit/mirrors-clang-format + rev: 'v21.1.0' + hooks: + - id: clang-format + args: ["-style=file"] diff --git a/CMakePresets.json b/CMakePresets.json index 8dad0f2..cb834fa 100644 --- a/CMakePresets.json +++ b/CMakePresets.json @@ -1,134 +1,134 @@ { - "version": 6, - "configurePresets": [ - { - "name": "default-release", - "displayName": "Default Release", - "description": "Default configuration for release with runtime components only", - "generator": "Ninja", - "binaryDir": "${sourceDir}/build/${presetName}", - "cacheVariables": { - "CMAKE_BUILD_TYPE": "Release", - "BUILD_SHARED_LIBS": "ON", - "BUILD_CONNMAN": "ON", - "BUILD_EXAMPLES": "ON" - } - }, - { - "name": "default-develop", - "displayName": "Default Config for development", - "description": "Default configuration for development, release runtime and dev components, build tests ", - "inherits": "default-release", - "cacheVariables": { - "CMAKE_BUILD_TYPE": "Debug", - "BUILD_TESTS": "ON", - "CMAKE_EXPORT_COMPILE_COMMANDS": "ON", - "BUILD_DOCS": "ON" - } - } - ], - "buildPresets": [ - { - "name": "default-release", - "configurePreset": "default-release" - }, - { - "name": "default-develop", - "configurePreset": "default-develop" - }, - { - "name": "default-documentation", - "configurePreset": "default-develop", - "targets": "doxygen_docs" - } - ], - "testPresets": [ - { - "name": "default-develop", - "configurePreset": "default-develop", - "output": { - "outputOnFailure": true - } - } - ], - "packagePresets": [ - { - "name": "default-develop", - "configurePreset": "default-develop", - "generators": [ - "TGZ" - ], - "variables": { - "CPACK_COMPONENTS_GROUPING": "ALL_COMPONENTS_IN_ONE", - "CPACK_PACKAGE_CONTACT": "develop@amarulasolutions.com", - "CPACK_PACKAGE_VENDOR": "amarulasolutions" - }, - "packageDirectory": "packages-${presetName}" - }, - { - "name": "default-runtime-release", - "configurePreset": "default-release", - "inherits": "default-develop", - "variables": { - "CPACK_COMPONENTS_GROUPING": "ALL_COMPONENTS_IN_ONE", - "CPACK_ARCHIVE_COMPONENT_INSTALL": "ON", - "CPACK_COMPONENTS_ALL": "GDbusCpp", - "CPACK_PACKAGE_CONTACT": "develop@amarulasolutions.com", - "CPACK_PACKAGE_VENDOR": "amarulasolutions" - } - } - ], - "workflowPresets": [ - { - "name": "default-develop", - "steps": [ + "version": 6, + "configurePresets": [ { - "type": "configure", - "name": "default-develop" + "name": "default-release", + "displayName": "Default Release", + "description": "Default configuration for release with runtime components only", + "generator": "Ninja", + "binaryDir": "${sourceDir}/build/${presetName}", + "cacheVariables": { + "CMAKE_BUILD_TYPE": "Release", + "BUILD_SHARED_LIBS": "ON", + "BUILD_CONNMAN": "ON", + "BUILD_EXAMPLES": "ON" + } }, { - "type": "build", - "name": "default-develop" + "name": "default-develop", + "displayName": "Default Config for development", + "description": "Default configuration for development, release runtime and dev components, build tests ", + "inherits": "default-release", + "cacheVariables": { + "CMAKE_BUILD_TYPE": "Debug", + "BUILD_TESTS": "ON", + "CMAKE_EXPORT_COMPILE_COMMANDS": "ON", + "BUILD_DOCS": "ON" + } + } + ], + "buildPresets": [ + { + "name": "default-release", + "configurePreset": "default-release" }, { - "type": "test", - "name": "default-develop" + "name": "default-develop", + "configurePreset": "default-develop" }, { - "type": "package", - "name": "default-develop" + "name": "default-documentation", + "configurePreset": "default-develop", + "targets": "doxygen_docs" } - ] - }, - { - "name": "default-release", - "steps": [ + ], + "testPresets": [ { - "type": "configure", - "name": "default-release" - }, + "name": "default-develop", + "configurePreset": "default-develop", + "output": { + "outputOnFailure": true + } + } + ], + "packagePresets": [ { - "type": "build", - "name": "default-release" + "name": "default-develop", + "configurePreset": "default-develop", + "generators": [ + "TGZ" + ], + "variables": { + "CPACK_COMPONENTS_GROUPING": "ALL_COMPONENTS_IN_ONE", + "CPACK_PACKAGE_CONTACT": "develop@amarulasolutions.com", + "CPACK_PACKAGE_VENDOR": "amarulasolutions" + }, + "packageDirectory": "packages-${presetName}" }, { - "type": "package", - "name": "default-runtime-release" + "name": "default-runtime-release", + "configurePreset": "default-release", + "inherits": "default-develop", + "variables": { + "CPACK_COMPONENTS_GROUPING": "ALL_COMPONENTS_IN_ONE", + "CPACK_ARCHIVE_COMPONENT_INSTALL": "ON", + "CPACK_COMPONENTS_ALL": "GDbusCpp", + "CPACK_PACKAGE_CONTACT": "develop@amarulasolutions.com", + "CPACK_PACKAGE_VENDOR": "amarulasolutions" + } } - ] - }, - { - "name": "default-documentation", - "steps": [ + ], + "workflowPresets": [ + { + "name": "default-develop", + "steps": [ + { + "type": "configure", + "name": "default-develop" + }, + { + "type": "build", + "name": "default-develop" + }, + { + "type": "test", + "name": "default-develop" + }, + { + "type": "package", + "name": "default-develop" + } + ] + }, { - "type": "configure", - "name": "default-develop" + "name": "default-release", + "steps": [ + { + "type": "configure", + "name": "default-release" + }, + { + "type": "build", + "name": "default-release" + }, + { + "type": "package", + "name": "default-runtime-release" + } + ] }, { - "type": "build", - "name": "default-documentation" + "name": "default-documentation", + "steps": [ + { + "type": "configure", + "name": "default-develop" + }, + { + "type": "build", + "name": "default-documentation" + } + ] } - ] - } - ] -} \ No newline at end of file + ] +} diff --git a/README.md b/README.md index 3115101..4ffae6e 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,8 @@ -# gdbus-cpp +# gdbus-cpp [TOC] -This repository should provide easy to use C++ API to communicate with the DBus using GDBus. +This repository should provide easy to use C++ API to communicate with the DBus using GDBus. ## Configure, build, test, package ... @@ -15,9 +15,9 @@ Refer to [cmake](https://cmake.org/cmake/help/latest/manual/cmake.1.html), [ctes ```CMake include(FetchContent) FetchContent_Declare( - GDbusCpp - GIT_REPOSITORY https://github.com/amarula/libcppconnman.git - GIT_TAG vMAJOR.MINOR.PATCH + GDbusCpp + GIT_REPOSITORY https://github.com/amarula/libcppconnman.git + GIT_TAG vMAJOR.MINOR.PATCH FIND_PACKAGE_ARGS MAJOR.MINOR CONFIG ) FetchContent_MakeAvailable(GDbusCpp) @@ -31,4 +31,3 @@ You can read the [API reference](https://amarula.github.io/libcppconnman/), or g ``` cmake --workflow --preset default-documentation ``` - diff --git a/cmake/VersionFromGit.cmake b/cmake/VersionFromGit.cmake index 9120b63..0083503 100644 --- a/cmake/VersionFromGit.cmake +++ b/cmake/VersionFromGit.cmake @@ -165,5 +165,3 @@ function( version_from_git ) set( VERSION_PATCH ${version_patch} PARENT_SCOPE ) endfunction( version_from_git ) - - diff --git a/examples/connmanctl.cpp b/examples/connmanctl.cpp index 0f36325..f0e8f07 100644 --- a/examples/connmanctl.cpp +++ b/examples/connmanctl.cpp @@ -19,7 +19,7 @@ auto main() -> int { bool connecting = false; Connman connman; const auto manager = connman.manager(); - manager->onRequestInputPassphrase([&](auto service) -> auto { + manager->onRequestInputPassphrase([&](const auto& service) -> auto { const auto name = service->properties().getName(); std::string passphrase; @@ -222,7 +222,7 @@ auto main() -> int { !connect) { std::cout << (connect ? "Connecting" : "Disconnecting") << " to service: " << name << "\n"; - const auto onConnect = [name, connect](bool success) { + const auto on_connect = [name, connect](bool success) { if (success) { std::cout << "Service " << name @@ -235,10 +235,10 @@ auto main() -> int { } }; if (connect) { - (*iterator)->connect(onConnect); + (*iterator)->connect(on_connect); connecting = true; } else { - (*iterator)->disconnect(onConnect); + (*iterator)->disconnect(on_connect); } } else { std::cout << "Service " << name << " is already " @@ -286,4 +286,4 @@ auto main() -> int { } std::cout << "Exiting.\n"; return 0; -} \ No newline at end of file +} diff --git a/include/amarula/dbus/connman/gagent.hpp b/include/amarula/dbus/connman/gagent.hpp index 31d775b..451c874 100644 --- a/include/amarula/dbus/connman/gagent.hpp +++ b/include/amarula/dbus/connman/gagent.hpp @@ -9,19 +9,19 @@ namespace Amarula::DBus::G::Connman { class Connman; class Agent { - GDBusNodeInfo *node_info_; + GDBusNodeInfo* node_info_; guint registration_id_{0}; - GDBusConnection *connection_{nullptr}; + GDBusConnection* connection_{nullptr}; static constexpr const auto AGENT_PATH{"/net/amarula/gconnman/agent"}; - explicit Agent(GDBusConnection *connection); + explicit Agent(GDBusConnection* connection); using RequestInputCallback = - std::function; + std::function; using CancelCallback = std::function; using ReleaseCallback = std::function; using ReportErrorCallback = - std::function; + std::function; void set_request_input_handler(RequestInputCallback callback) { request_input_cb_ = std::move(callback); @@ -39,24 +39,24 @@ class Agent { CancelCallback cancel_cb_; ReleaseCallback release_cb_; - static void on_method_call(GDBusConnection *connection, const gchar *sender, - const gchar *object_path, - const gchar *interface_name, - const gchar *method_name, GVariant *parameters, - GDBusMethodInvocation *invocation, + static void on_method_call(GDBusConnection* connection, const gchar* sender, + const gchar* object_path, + const gchar* interface_name, + const gchar* method_name, GVariant* parameters, + GDBusMethodInvocation* invocation, gpointer user_data); - void dispatch_method_call(GDBusMethodInvocation *invocation, - const gchar *method_name, GVariant *parameters); + void dispatch_method_call(GDBusMethodInvocation* invocation, + const gchar* method_name, GVariant* parameters); constexpr static const GDBusInterfaceVTable INTERFACE_VTABLE{ Agent::on_method_call, nullptr, nullptr, {nullptr}}; public: - Agent(const Agent &) = delete; - auto operator=(const Agent &) -> Agent & = delete; - Agent(Agent &&) = delete; - auto operator=(Agent &&) -> Agent & = delete; + Agent(const Agent&) = delete; + auto operator=(const Agent&) -> Agent& = delete; + Agent(Agent&&) = delete; + auto operator=(Agent&&) -> Agent& = delete; ~Agent(); friend class Manager; }; diff --git a/src/dbus/gconnman_agent.cpp b/src/dbus/gconnman_agent.cpp index 3f46a97..31fe12e 100644 --- a/src/dbus/gconnman_agent.cpp +++ b/src/dbus/gconnman_agent.cpp @@ -10,7 +10,7 @@ #include "gconnman_private.hpp" namespace Amarula::DBus::G::Connman { -static constexpr const char *INTROSPECTION_XML = +static constexpr const char* INTROSPECTION_XML = "" " " " " @@ -27,8 +27,8 @@ static constexpr const char *INTROSPECTION_XML = " " ""; -Agent::Agent(GDBusConnection *connection) : connection_{connection} { - GError *err = nullptr; +Agent::Agent(GDBusConnection* connection) : connection_{connection} { + GError* err = nullptr; node_info_ = g_dbus_node_info_new_for_xml(INTROSPECTION_XML, &err); if (node_info_ == nullptr) { std::string const msg = @@ -54,26 +54,26 @@ Agent::~Agent() { g_dbus_node_info_unref(node_info_); } -void Agent::on_method_call(GDBusConnection * /*connection*/, - const gchar * /*sender*/, - const gchar * /*object_path*/, - const gchar * /*interface_name*/, - const gchar *method_name, GVariant *parameters, - GDBusMethodInvocation *invocation, +void Agent::on_method_call(GDBusConnection* /*connection*/, + const gchar* /*sender*/, + const gchar* /*object_path*/, + const gchar* /*interface_name*/, + const gchar* method_name, GVariant* parameters, + GDBusMethodInvocation* invocation, gpointer user_data) { - auto *self = static_cast(user_data); + auto* self = static_cast(user_data); self->dispatch_method_call(invocation, method_name, parameters); } -void Agent::dispatch_method_call(GDBusMethodInvocation *invocation, - const gchar *method_name, - GVariant *parameters) { +void Agent::dispatch_method_call(GDBusMethodInvocation* invocation, + const gchar* method_name, + GVariant* parameters) { if (g_strcmp0(method_name, "RequestInput") == 0 && request_input_cb_) { - const gchar *service = nullptr; - GVariant *fields = nullptr; + const gchar* service = nullptr; + GVariant* fields = nullptr; - GVariant *child_service = g_variant_get_child_value(parameters, 0); - GVariant *child_fields = g_variant_get_child_value(parameters, 1); + GVariant* child_service = g_variant_get_child_value(parameters, 0); + GVariant* child_fields = g_variant_get_child_value(parameters, 1); service = g_variant_get_string(child_service, nullptr); fields = g_variant_ref(child_fields); @@ -81,9 +81,9 @@ void Agent::dispatch_method_call(GDBusMethodInvocation *invocation, g_variant_unref(child_service); g_variant_unref(child_fields); - auto *result = request_input_cb_(service, fields); + auto* result = request_input_cb_(service, fields); - GVariant *tuple = g_variant_new_tuple(&result, 1); + GVariant* tuple = g_variant_new_tuple(&result, 1); g_dbus_method_invocation_return_value(invocation, tuple); g_variant_unref(fields); @@ -101,11 +101,11 @@ void Agent::dispatch_method_call(GDBusMethodInvocation *invocation, } if (g_strcmp0(method_name, "ReportError") == 0) { - const gchar *service = nullptr; - const gchar *error_str = nullptr; + const gchar* service = nullptr; + const gchar* error_str = nullptr; - GVariant *child_service = g_variant_get_child_value(parameters, 0); - GVariant *child_error = g_variant_get_child_value(parameters, 1); + GVariant* child_service = g_variant_get_child_value(parameters, 0); + GVariant* child_error = g_variant_get_child_value(parameters, 1); service = g_variant_get_string(child_service, nullptr); error_str = g_variant_get_string(child_error, nullptr); diff --git a/src/dbus/gconnman_clock.cpp b/src/dbus/gconnman_clock.cpp index 269c68b..51f23c2 100644 --- a/src/dbus/gconnman_clock.cpp +++ b/src/dbus/gconnman_clock.cpp @@ -31,11 +31,11 @@ void ClockProperties::update(const gchar* key, GVariant* value) { time_ = g_variant_get_uint64(value); } else if (g_strcmp0(key, TIMEUPDATES_STR) == 0U) { time_updates_ = - TIME_UPDATE_MAP.from_string(g_variant_get_string(value, nullptr)); + TIME_UPDATE_MAP.fromString(g_variant_get_string(value, nullptr)); } else if (g_strcmp0(key, TIMEZONE_STR) == 0U) { timezone_ = g_variant_get_string(value, nullptr); } else if (g_strcmp0(key, TIMEZONEUPDATES_STR) == 0U) { - timezone_updates_ = TIME_ZONE_UPDATE_MAP.from_string( + timezone_updates_ = TIME_ZONE_UPDATE_MAP.fromString( g_variant_get_string(value, nullptr)); } else if (g_strcmp0(key, TIMESERVERS_STR) == 0U) { time_servers_ = as_to_vector(value); diff --git a/src/dbus/gconnman_manager.cpp b/src/dbus/gconnman_manager.cpp index 92d24fa..ad67d12 100644 --- a/src/dbus/gconnman_manager.cpp +++ b/src/dbus/gconnman_manager.cpp @@ -34,7 +34,7 @@ void ManaProperties::update(const gchar* key, GVariant* value) { if (g_strcmp0(key, OFFLINEMODE_STR) == 0) { offline_mode_ = (g_variant_get_boolean(value) == 1U); } else if (g_strcmp0(key, STATE_STR) == 0U) { - state_ = STATE_MAP.from_string(g_variant_get_string(value, nullptr)); + state_ = STATE_MAP.fromString(g_variant_get_string(value, nullptr)); } else { std::cerr << "Unknown property for Manager: " << key << '\n'; } @@ -62,7 +62,7 @@ void Manager::process_services_changed( const std::vector>& services_changed) { for (const auto& object_path : services_removed) { services_.erase(std::remove_if(services_.begin(), services_.end(), - [&object_path](const auto service) { + [&object_path](const auto& service) { return service->objPath() == object_path; }), @@ -70,9 +70,10 @@ void Manager::process_services_changed( } Manager::ProxyList new_order_of_services; for (const auto& [path, prop] : services_changed) { - auto service_it = std::find_if( - services_.begin(), services_.end(), - [&path](const auto service) { return service->objPath() == path; }); + auto service_it = std::find_if(services_.begin(), services_.end(), + [&path](const auto& service) { + return service->objPath() == path; + }); if (service_it != services_.end()) { new_order_of_services.push_back(*service_it); (*service_it)->updateProperties(prop.get()); @@ -95,7 +96,7 @@ void Manager::setup_agent() { g_variant_builder_init(&builder, G_VARIANT_TYPE("a{sv}")); auto service_it = std::find_if(services_.begin(), services_.end(), - [&service_path](const auto service) { + [&service_path](const auto& service) { return service->objPath() == service_path; }); @@ -195,7 +196,7 @@ void Manager::setup_agent() { }); } -void Manager::init() { registerAgent(agent_->AGENT_PATH); } +void Manager::init() { registerAgent(Agent::AGENT_PATH); } void Manager::setOfflineMode(bool offline_mode, PropertiesSetCallback callback) { @@ -410,7 +411,7 @@ auto Manager::parse_fields(GVariant* fields) -> GPtrArray* { g_variant_iter_init(&inner_iter, inner_dict); while (g_variant_iter_next(&inner_iter, "{&s@v}", &prop_name, - &prop_value_variant)) { + &prop_value_variant) != 0) { auto* prop_value = g_variant_get_variant(prop_value_variant); if (g_strcmp0(prop_name, "Type") == 0) { desc->type = g_variant_dup_string(prop_value, nullptr); diff --git a/src/dbus/gconnman_service.cpp b/src/dbus/gconnman_service.cpp index 8433af4..75647a6 100644 --- a/src/dbus/gconnman_service.cpp +++ b/src/dbus/gconnman_service.cpp @@ -116,7 +116,7 @@ void Service::setAutoconnect(const bool autoconnect, void IPv4::update(const gchar* key, GVariant* value) { if (g_strcmp0(key, METHOD_STR) == 0U) { method_ = - IPV4_METHOD_MAP.from_string(g_variant_get_string(value, nullptr)); + IPV4_METHOD_MAP.fromString(g_variant_get_string(value, nullptr)); } else if (g_strcmp0(key, ADDRESS_STR) == 0U) { address_ = g_variant_get_string(value, nullptr); } else if (g_strcmp0(key, NETMASK_STR) == 0U) { @@ -131,14 +131,14 @@ void IPv4::update(const gchar* key, GVariant* value) { void IPv6::update(const gchar* key, GVariant* value) { if (g_strcmp0(key, METHOD_STR) == 0U) { method_ = - IPV6_METHOD_MAP.from_string(g_variant_get_string(value, nullptr)); + IPV6_METHOD_MAP.fromString(g_variant_get_string(value, nullptr)); } else if (g_strcmp0(key, ADDRESS_STR) == 0U) { address_ = g_variant_get_string(value, nullptr); } else if (g_strcmp0(key, GATEWAY_STR) == 0U) { gateway_ = g_variant_get_string(value, nullptr); } else if (g_strcmp0(key, PRIVACY_STR) == 0U) { privacy_ = - IPV6_PRIVACY_MAP.from_string(g_variant_get_string(value, nullptr)); + IPV6_PRIVACY_MAP.fromString(g_variant_get_string(value, nullptr)); } else if (g_strcmp0(key, PREFIXLENGTH_STR) == 0U) { prefix_length_ = static_cast(g_variant_get_byte(value)); } else { @@ -168,7 +168,7 @@ void GVariantParser::parse(GVariant* variant) { void Ethernet::update(const gchar* key, GVariant* value) { if (g_strcmp0(key, METHOD_STR) == 0U) { - method_ = ETHERNET_METHOD_MAP.from_string( + method_ = ETHERNET_METHOD_MAP.fromString( g_variant_get_string(value, nullptr)); } else if (g_strcmp0(key, INTERFACE_STR) == 0U) { interface_ = g_variant_get_string(value, nullptr); @@ -198,7 +198,7 @@ void Provider::update(const gchar* key, GVariant* value) { void Proxy::update(const gchar* key, GVariant* value) { if (g_strcmp0(key, METHOD_STR) == 0U) { method_ = - PROXY_METHOD_MAP.from_string(g_variant_get_string(value, nullptr)); + PROXY_METHOD_MAP.fromString(g_variant_get_string(value, nullptr)); } else if (g_strcmp0(key, URL_STR) == 0U) { url_ = g_variant_get_string(value, nullptr); } else if (g_strcmp0(key, SERVERS_STR) == 0U) { @@ -214,11 +214,11 @@ void ServProperties::update(const gchar* key, GVariant* value) { if (g_strcmp0(key, NAME_STR) == 0) { name_ = g_variant_get_string(value, nullptr); } else if (g_strcmp0(key, TYPE_STR) == 0U) { - type_ = TYPE_MAP.from_string(g_variant_get_string(value, nullptr)); + type_ = TYPE_MAP.fromString(g_variant_get_string(value, nullptr)); } else if (g_strcmp0(key, STATE_STR) == 0U) { - state_ = STATE_MAP.from_string(g_variant_get_string(value, nullptr)); + state_ = STATE_MAP.fromString(g_variant_get_string(value, nullptr)); } else if (g_strcmp0(key, ERROR_STR) == 0U) { - error_ = ERROR_MAP.from_string(g_variant_get_string(value, nullptr)); + error_ = ERROR_MAP.fromString(g_variant_get_string(value, nullptr)); } else if (g_strcmp0(key, FAVORITE_STR) == 0U) { favorite_ = g_variant_get_boolean(value) == 1U; } else if (g_strcmp0(key, IMMUTABLE_STR) == 0U) { @@ -330,7 +330,9 @@ void ServProperties::print() const { ipv6_.value().print(); } - ethernet_.value().print(); + if (ethernet_.has_value()) { + ethernet_.value().print(); + } if (provider_) { provider_.value().print(); diff --git a/src/dbus/gconnman_technology.cpp b/src/dbus/gconnman_technology.cpp index 2dfceb1..6aade07 100644 --- a/src/dbus/gconnman_technology.cpp +++ b/src/dbus/gconnman_technology.cpp @@ -44,7 +44,7 @@ void TechProperties::update(const gchar* key, GVariant* value) { if (g_strcmp0(key, NAME_STR) == 0) { name_ = g_variant_get_string(value, nullptr); } else if (g_strcmp0(key, TYPE_STR) == 0U) { - type_ = TYPE_MAP.from_string(g_variant_get_string(value, nullptr)); + type_ = TYPE_MAP.fromString(g_variant_get_string(value, nullptr)); } else if (g_strcmp0(key, POWERED_STR) == 0U) { powered_ = g_variant_get_boolean(value) == 1U; diff --git a/src/dbus/gdbus.cpp b/src/dbus/gdbus.cpp index 80e16e4..d9add16 100644 --- a/src/dbus/gdbus.cpp +++ b/src/dbus/gdbus.cpp @@ -100,4 +100,4 @@ void DBus::start() { } } -} // namespace Amarula::DBus::G \ No newline at end of file +} // namespace Amarula::DBus::G diff --git a/src/dbus/gdbus_private.hpp b/src/dbus/gdbus_private.hpp index 4a66d95..2829c3c 100644 --- a/src/dbus/gdbus_private.hpp +++ b/src/dbus/gdbus_private.hpp @@ -17,7 +17,8 @@ class EnumStringMap { constexpr explicit EnumStringMap(std::array init) : data_{init} {} - [[nodiscard]] constexpr std::string_view to_string(Enum enum_value) const { + [[nodiscard]] constexpr auto to_string(Enum enum_value) const + -> std::string_view { for (auto&& [e, s] : data_) { if (e == enum_value) { return s; @@ -26,7 +27,8 @@ class EnumStringMap { throw std::runtime_error("Invalid enum value"); } - [[nodiscard]] constexpr Enum from_string(std::string_view str) const { + [[nodiscard]] constexpr auto fromString(std::string_view str) const + -> Enum { for (auto&& [e, s] : data_) { if (s == str) { return e; @@ -40,17 +42,18 @@ class EnumStringMap { }; template -auto as_to_vector(GVariant* array_s, const EnumStringMap* enumMap = - nullptr) -> std::vector { - GVariantIter strIter; +auto as_to_vector(GVariant* array_s, + const EnumStringMap* enum_map = nullptr) + -> std::vector { + GVariantIter str_iter; std::vector container; if (g_variant_is_of_type(array_s, G_VARIANT_TYPE("as")) != 0U) { - g_variant_iter_init(&strIter, array_s); + g_variant_iter_init(&str_iter, array_s); GVariant* item = nullptr; - while ((item = g_variant_iter_next_value(&strIter)) != nullptr) { + while ((item = g_variant_iter_next_value(&str_iter)) != nullptr) { const gchar* item_str = g_variant_get_string(item, nullptr); if constexpr (std::is_enum_v) { - container.emplace_back(enumMap->from_string(item_str)); + container.emplace_back(enum_map->fromString(item_str)); } else { container.emplace_back(item_str); } diff --git a/tests/gconnman_serv_test.cpp b/tests/gconnman_serv_test.cpp index 197315b..b8a4f34 100644 --- a/tests/gconnman_serv_test.cpp +++ b/tests/gconnman_serv_test.cpp @@ -98,7 +98,7 @@ TEST(Connman, ConnectWifi) { Connman connman; const auto manager = connman.manager(); - manager->onRequestInputPassphrase([&](auto service) -> auto { + manager->onRequestInputPassphrase([&](const auto& service) -> auto { called_request_input = true; std::cout << "Requesting input passphrase for service: " << service->properties().getName() << '\n'; @@ -144,4 +144,4 @@ TEST(Connman, ConnectWifi) { ASSERT_TRUE(called) << "ServicesChanged callback was never called"; ASSERT_TRUE(called_request_input) << "Did not requested user input"; -} \ No newline at end of file +} diff --git a/tests/gconnman_tech_test.cpp b/tests/gconnman_tech_test.cpp index 47c84c4..48bd3fc 100644 --- a/tests/gconnman_tech_test.cpp +++ b/tests/gconnman_tech_test.cpp @@ -130,4 +130,4 @@ TEST(Connman, PowerOffAllTechnologies) { }); } ASSERT_TRUE(called) << "setPowered callback was never called"; -} \ No newline at end of file +}