From 42f0bd07c00712805f9397fcd99dab7c242bb697 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stanislav=20Angelovi=C4=8D?= Date: Fri, 29 Mar 2024 13:23:44 +0100 Subject: [PATCH] refactor: add strong types to public API (#414) This introduces strong types for `std::string`-based D-Bus types. This facilitates safer, less error-prone and more expressive API. What previously was `auto proxy = createProxy("org.sdbuscpp.concatenator", "/org/sdbuscpp/concatenator");` is now written like `auto proxy = createProxy(ServiceName{"org.sdbuscpp.concatenator"}, ObjectPath{"/org/sdbuscpp/concatenator"});`. These types are: * `ObjectPath` type for the object path (the type has been around already but now is also used consistently in sdbus-c++ API for object path strings), * `InterfaceName` type for D-Bus interface names, * `BusName` (and its aliases `ServiceName` and `ConnectionName`) type for bus/service/connection names, * `MemberName` (and its aliases `MethodName`, `SignalName` and `PropertyName`) type for D-Bus method, signal and property names, * `Signature` type for the D-Bus signature (the type has been around already but now is also used consistently in sdbus-c++ API for signature strings), * `Error::Name` type for D-Bus error names. --- docs/using-sdbus-c++.md | 123 ++++++++------- .../examplemanager-planet1-client-glue.h | 2 +- .../examplemanager-planet1-server-glue.h | 2 +- .../obj-manager-client.cpp | 29 ++-- .../obj-manager-server.cpp | 19 ++- include/sdbus-c++/AdaptorInterfaces.h | 2 +- include/sdbus-c++/ConvenienceApiClasses.h | 76 ++++++--- include/sdbus-c++/ConvenienceApiClasses.inl | 146 +++++++++++++---- include/sdbus-c++/Error.h | 33 ++-- include/sdbus-c++/IConnection.h | 24 +-- include/sdbus-c++/IObject.h | 54 +++++-- include/sdbus-c++/IProxy.h | 147 ++++++++++++++---- include/sdbus-c++/Message.h | 16 +- include/sdbus-c++/ProxyInterfaces.h | 10 +- include/sdbus-c++/StandardInterfaces.h | 102 ++++++++---- include/sdbus-c++/TypeTraits.h | 18 +++ include/sdbus-c++/Types.h | 101 +++++++++--- include/sdbus-c++/VTableItems.h | 18 ++- include/sdbus-c++/VTableItems.inl | 21 ++- src/Connection.cpp | 72 ++++----- src/Connection.h | 68 ++++---- src/Error.cpp | 12 +- src/IConnection.h | 56 ++++--- src/Message.cpp | 33 ++-- src/Object.cpp | 36 +++-- src/Object.h | 44 +++--- src/Proxy.cpp | 44 +++--- src/Proxy.h | 29 ++-- src/Utils.h | 6 +- .../DBusAsyncMethodsTests.cpp | 4 +- .../integrationtests/DBusConnectionTests.cpp | 23 +-- tests/integrationtests/DBusGeneralTests.cpp | 14 +- tests/integrationtests/DBusMethodsTests.cpp | 24 +-- tests/integrationtests/DBusSignalsTests.cpp | 16 +- .../DBusStandardInterfacesTests.cpp | 72 ++++----- tests/integrationtests/Defs.h | 19 ++- tests/integrationtests/TestAdaptor.cpp | 12 +- tests/integrationtests/TestAdaptor.h | 10 +- tests/integrationtests/TestFixture.h | 8 +- tests/integrationtests/TestProxy.cpp | 20 +-- tests/integrationtests/TestProxy.h | 32 ++-- .../integrationtests-adaptor.h | 2 +- .../integrationtests/integrationtests-proxy.h | 2 +- tests/perftests/client.cpp | 8 +- tests/perftests/perftests-adaptor.h | 2 +- tests/perftests/perftests-proxy.h | 2 +- tests/perftests/server.cpp | 8 +- .../stresstests/celsius-thermometer-adaptor.h | 2 +- tests/stresstests/celsius-thermometer-proxy.h | 2 +- tests/stresstests/concatenator-adaptor.h | 2 +- tests/stresstests/concatenator-proxy.h | 2 +- .../fahrenheit-thermometer-adaptor.h | 4 +- .../fahrenheit-thermometer-proxy.h | 4 +- tests/stresstests/sdbus-c++-stress-tests.cpp | 29 ++-- tests/unittests/Connection_test.cpp | 9 +- tests/unittests/Message_test.cpp | 8 +- tests/unittests/TypeTraits_test.cpp | 6 + tests/unittests/Types_test.cpp | 13 +- tools/xml2cpp-codegen/AdaptorGenerator.cpp | 2 +- tools/xml2cpp-codegen/ProxyGenerator.cpp | 2 +- 60 files changed, 1085 insertions(+), 621 deletions(-) diff --git a/docs/using-sdbus-c++.md b/docs/using-sdbus-c++.md index 0e537dc..a6c127a 100644 --- a/docs/using-sdbus-c++.md +++ b/docs/using-sdbus-c++.md @@ -184,7 +184,7 @@ The following diagram illustrates the major entities in sdbus-c++. ![class](sdbus-c++-class-diagram.png) -`IConnection` represents the concept of a D-Bus connection. You can connect to either the system bus or a session bus. Services can assign unique service names to those connections. An I/O event loop should be run on the bus connection. +`IConnection` represents the concept of a D-Bus connection. You can connect to either the system bus or a session bus. Services can assign well-known service names to those connections. An I/O event loop should be run on the bus connection. `IObject` represents the concept of an object that exposes its methods, signals and properties. Its responsibilities are: @@ -238,7 +238,7 @@ Let's have an object `/org/sdbuscpp/concatenator` that implements the `org.sdbus In the following sections, we will elaborate on the ways of implementing such an object on both the server and the client side. -> **Before running Concatenator example in your system:** In order for your service to be allowed to provide a D-Bus API on system bus, a D-Bus security policy file has to be put in place for that service. Otherwise the service will fail to start (you'll get `[org.freedesktop.DBus.Error.AccessDenied] Failed to request bus name (Permission denied)`, for example). To make the Concatenator example work in your system, [look in this section of systemd configuration](systemd-dbus-config.md#dbus-configuration) for how to name the file, where to place it, how to populate it. For further information, consult [dbus-daemon documentation](https://dbus.freedesktop.org/doc/dbus-daemon.1.html), sections *INTEGRATING SYSTEM SERVICES* and *CONFIGURATION FILE*. As an example used for sdbus-c++ integration tests, you may look at the [policy file for sdbus-c++ integration tests](/tests/integrationtests/files/org.sdbuscpp.integrationtests.conf). +> **Before running Concatenator example in your system:** In order for your service to be allowed to provide a D-Bus API on ** the system bus**, a D-Bus security policy file has to be put in place for that service. Otherwise the service will fail to start (you'll get `[org.freedesktop.DBus.Error.AccessDenied] Failed to request bus name (Permission denied)`, for example). To make the Concatenator example work in your system, [look in this section of systemd configuration](systemd-dbus-config.md#dbus-configuration) for how to name the file, where to place it, how to populate it. For further information, consult [dbus-daemon documentation](https://dbus.freedesktop.org/doc/dbus-daemon.1.html), sections *INTEGRATING SYSTEM SERVICES* and *CONFIGURATION FILE*. As an example used for sdbus-c++ integration tests, you may look at the [policy file for sdbus-c++ integration tests](/tests/integrationtests/files/org.sdbuscpp.integrationtests.conf). Implementing the Concatenator example using basic sdbus-c++ API layer --------------------------------------------------------------------- @@ -289,28 +289,29 @@ void concatenate(sdbus::MethodCall call) reply.send(); // Emit 'concatenated' signal - const char* interfaceName = "org.sdbuscpp.Concatenator"; - auto signal = g_concatenator->createSignal(interfaceName, "concatenated"); + sdbus::InterfaceName interfaceName{"org.sdbuscpp.Concatenator"}; + sdbus::SignalName signalName{"concatenated"}; + auto signal = g_concatenator->createSignal(interfaceName, signalName); signal << result; g_concatenator->emitSignal(signal); } int main(int argc, char *argv[]) { - // Create D-Bus connection to the system bus and requests name on it. - const char* serviceName = "org.sdbuscpp.concatenator"; - auto connection = sdbus::createSystemBusConnection(serviceName); + // Create D-Bus connection to (either the session or system) bus and requests a well-known name on it. + sdbus::ServiceName serviceName{"org.sdbuscpp.concatenator"}; + auto connection = sdbus::createBusConnection(serviceName); // Create concatenator D-Bus object. - const char* objectPath = "/org/sdbuscpp/concatenator"; - auto concatenator = sdbus::createObject(*connection, objectPath); + sdbus::ObjectPath objectPath{"/org/sdbuscpp/concatenator"}; + auto concatenator = sdbus::createObject(*connection, std::move(objectPath)); g_concatenator = concatenator.get(); // Register D-Bus methods and signals on the concatenator object, and exports the object. - const char* interfaceName = "org.sdbuscpp.Concatenator"; - concatenator->addVTable( sdbus::MethodVTableItem{"concatenate", "ais", {}, "s", {}, &concatenate, {}} - , sdbus::SignalVTableItem{"concatenated", "s", {}, {}} ) + sdbus::InterfaceName interfaceName{"org.sdbuscpp.Concatenator"}; + concatenator->addVTable( sdbus::MethodVTableItem{"concatenate", sdbus::Signature{"ais"}, {}, sdbus::Signature{"s"}, {}, &concatenate, {}} + , sdbus::SignalVTableItem{"concatenated", sdbus::Signature{"s"}, {}, {}} ) .forInterface(interfaceName); // Run the I/O event loop on the bus connection. @@ -349,21 +350,24 @@ int main(int argc, char *argv[]) { // Create proxy object for the concatenator object on the server side. Since here // we are creating the proxy instance without passing connection to it, the proxy - // will create its own connection automatically, and it will be system bus connection. - const char* destinationName = "org.sdbuscpp.concatenator"; - const char* objectPath = "/org/sdbuscpp/concatenator"; - auto concatenatorProxy = sdbus::createProxy(destinationName, objectPath); + // will create its own connection automatically (to either system bus or session bus, + // depending on the context). + sdbus::ServiceName destination{"org.sdbuscpp.concatenator"}; + sdbus::ObjectPath objectPath{"/org/sdbuscpp/concatenator"}; + auto concatenatorProxy = sdbus::createProxy(std::move(destination), std::move(objectPath)); // Let's subscribe for the 'concatenated' signals - const char* interfaceName = "org.sdbuscpp.Concatenator"; - concatenatorProxy->registerSignalHandler(interfaceName, "concatenated", &onConcatenated); + sdbus::InterfaceName interfaceName{"org.sdbuscpp.Concatenator"}; + sdbus::SignalName signalName{"concatenated"}; + concatenatorProxy->registerSignalHandler(interfaceName, signalName, &onConcatenated); std::vector numbers = {1, 2, 3}; std::string separator = ":"; + MethodName concatenate{"concatenate"}; // Invoke concatenate on given interface of the object { - auto method = concatenatorProxy->createMethodCall(interfaceName, "concatenate"); + auto method = concatenatorProxy->createMethodCall(interfaceName, concatenate); method << numbers << separator; auto reply = concatenatorProxy->callMethod(method); std::string result; @@ -373,7 +377,7 @@ int main(int argc, char *argv[]) / // Invoke concatenate again, this time with no numbers and we shall get an error { - auto method = concatenatorProxy->createMethodCall(interfaceName, "concatenate"); + auto method = concatenatorProxy->createMethodCall(interfaceName, concatenate); method << std::vector() << separator; try { @@ -408,11 +412,11 @@ Please note that we can create and destroy D-Bus object proxies dynamically, at There are several factory methods to create a bus connection object in sdbus-c++: * `createBusConnection()` - opens a connection to the session bus when in a user context, and a connection to the system bus, otherwise -* `createBusConnection(const std::string& name)` - opens a connection with the given name to the session bus when in a user context, and a connection with the given name to the system bus, otherwise +* `createBusConnection(const sdbus::ServiceName& name)` - opens a connection to the session bus when in a user context, and a connection with the given name to the system bus, otherwise, and requests the given well-known service name on the bus * `createSystemBusConnection()` - opens a connection to the system bus -* `createSystemBusConnection(const std::string& name)` - opens a connection with the given name to the system bus +* `createSystemBusConnection(const sdbus::ServiceName& name)` - opens a connection to the system bus, and requests the given well-known service name on the bus * `createSessionBusConnection()` - opens a connection to the session bus -* `createSessionBusConnection(const std::string& name)` - opens a connection with the given name to the session bus +* `createSessionBusConnection(const sdbus::ServiceName& name)` - opens a connection to the session bus, and requests the given well-known service name on the bus. * `createSessionBusConnectionWithAddress(const std::string& address)` - opens a connection to the session bus at a custom address * `createRemoteSystemBusConnection(const std::string& host)` - opens a connection to the system bus on a remote host using ssh * `createDirectBusConnection(const std::string& address)` - opens direct D-Bus connection at a custom address (see [Using direct (peer-to-peer) D-Bus connections](#using-direct-peer-to-peer-d-bus-connections)) @@ -503,13 +507,13 @@ The code written using this layer expresses in a declarative way *what* it does, int main(int argc, char *argv[]) { - // Create D-Bus connection to the system bus and requests name on it. - const char* serviceName = "org.sdbuscpp.concatenator"; - auto connection = sdbus::createSystemBusConnection(serviceName); + // Create D-Bus connection to the (either system or session) bus and requests a well-known name on it. + sdbus::ServiceName serviceName{"org.sdbuscpp.concatenator"}; + auto connection = sdbus::createBusConnection(serviceName); // Create concatenator D-Bus object. - const char* objectPath = "/org/sdbuscpp/concatenator"; - auto concatenator = sdbus::createObject(*connection, objectPath); + sdbus::ObjectPath objectPath{"/org/sdbuscpp/concatenator"}; + auto concatenator = sdbus::createObject(*connection, std::move(objectPath)); auto concatenate = [&concatenator](const std::vector numbers, const std::string& separator) { @@ -524,17 +528,15 @@ int main(int argc, char *argv[]) } // Emit 'concatenated' signal - const char* interfaceName = "org.sdbuscpp.Concatenator"; - concatenator->emitSignal("concatenated").onInterface(interfaceName).withArguments(result); + concatenator->emitSignal("concatenated").onInterface("org.sdbuscpp.Concatenator").withArguments(result); return result; }; // Register D-Bus methods and signals on the concatenator object, and exports the object. - const char* interfaceName = "org.sdbuscpp.Concatenator"; concatenator->addVTable( sdbus::registerMethod("concatenate").implementedAs(std::move(concatenate)) , sdbus::registerSignal{"concatenated").withParameters() ) - .forInterface(interfaceName); + .forInterface("org.sdbuscpp.Concatenator"); // Run the loop on the connection. connection->enterEventLoop(); @@ -562,12 +564,12 @@ void onConcatenated(const std::string& concatenatedString) int main(int argc, char *argv[]) { // Create proxy object for the concatenator object on the server side - const char* destinationName = "org.sdbuscpp.concatenator"; - const char* objectPath = "/org/sdbuscpp/concatenator"; - auto concatenatorProxy = sdbus::createProxy(destinationName, objectPath); + sdbus::ServiceName destination{"org.sdbuscpp.concatenator"}; + sdbus::ObjectPath objectPath{"/org/sdbuscpp/concatenator"}; + auto concatenatorProxy = sdbus::createProxy(std::move(destination), std::move(objectPath)); // Let's subscribe for the 'concatenated' signals - const char* interfaceName = "org.sdbuscpp.Concatenator"; + sdbus::InterfaceName interfaceName{"org.sdbuscpp.Concatenator"}; concatenatorProxy->uponSignal("concatenated").onInterface(interfaceName).call([](const std::string& str){ onConcatenated(str); }); std::vector numbers = {1, 2, 3}; @@ -712,7 +714,7 @@ namespace sdbuscpp { class Concatenator_adaptor { public: - static constexpr const char* INTERFACE_NAME = "org.sdbuscpp.Concatenator"; + static inline const sdbus::InterfaceName INTERFACE_NAME{"org.sdbuscpp.Concatenator"}; protected: Concatenator_adaptor(sdbus::IObject& object) @@ -771,7 +773,7 @@ namespace sdbuscpp { class Concatenator_proxy { public: - static constexpr const char* INTERFACE_NAME = "org.sdbuscpp.Concatenator"; + static inline const sdbus::InterfaceName INTERFACE_NAME{"org.sdbuscpp.Concatenator"}; protected: Concatenator_proxy(sdbus::IProxy& proxy) @@ -827,7 +829,7 @@ Calling `registerAdaptor()` and `unregisterAdaptor()` was not necessary in previ class Concatenator : public sdbus::AdaptorInterfaces { public: - Concatenator(sdbus::IConnection& connection, std::string objectPath) + Concatenator(sdbus::IConnection& connection, sdbus::ObjectPath objectPath) : AdaptorInterfaces(connection, std::move(objectPath)) { registerAdaptor(); @@ -870,13 +872,13 @@ That's it. We now have an implementation of a D-Bus object implementing `org.sdb int main(int argc, char *argv[]) { - // Create D-Bus connection to the system bus and requests name on it. - const char* serviceName = "org.sdbuscpp.concatenator"; - auto connection = sdbus::createSystemBusConnection(serviceName); + // Create D-Bus connection to (either the system or session) bus and request a well-known name on it. + sdbus::ServiceName serviceName{"org.sdbuscpp.concatenator"}; + auto connection = sdbus::createBusConnection(serviceName); // Create concatenator D-Bus object. - const char* objectPath = "/org/sdbuscpp/concatenator"; - Concatenator concatenator(*connection, objectPath); + sdbus::ObjectPath objectPath{"/org/sdbuscpp/concatenator"}; + Concatenator concatenator(*connection, std::move(objectPath)); // Run the loop on the connection. connection->enterEventLoop(); @@ -906,7 +908,7 @@ Calling `registerProxy()` and `unregisterProxy()` was not necessary in previous class ConcatenatorProxy : public sdbus::ProxyInterfaces { public: - ConcatenatorProxy(std::string destination, std::string objectPath) + ConcatenatorProxy(sdbus::ServiceName destination, sdbus::ObjectPath objectPath) : ProxyInterfaces(std::move(destination), std::move(objectPath)) { registerProxy(); @@ -940,9 +942,9 @@ Now let's use this proxy to make remote calls and listen to signals in a real ap int main(int argc, char *argv[]) { // Create proxy object for the concatenator object on the server side - const char* destinationName = "org.sdbuscpp.concatenator"; - const char* objectPath = "/org/sdbuscpp/concatenator"; - ConcatenatorProxy concatenatorProxy(destinationName, objectPath); + sdbus::ServiceName destination{"org.sdbuscpp.concatenator"}; + sdbus::ObjectPath objectPath{"/org/sdbuscpp/concatenator"}; + ConcatenatorProxy concatenatorProxy(std::move(destination), std::move(objectPath)); std::vector numbers = {1, 2, 3}; std::string separator = ":"; @@ -1034,8 +1036,9 @@ void concatenate(sdbus::MethodCall call) reply.send(); // Emit 'concatenated' signal (creating and emitting signals is thread-safe) - const char* interfaceName = "org.sdbuscpp.Concatenator"; - auto signal = g_concatenator->createSignal(interfaceName, "concatenated"); + sdbus::InterfaceName interfaceName{"org.sdbuscpp.Concatenator"}; + sdbus::SignalName signalName{"concatenated"}; + auto signal = g_concatenator->createSignal(interfaceName, signalName); signal << result; g_concatenator->emitSignal(signal); }).detach(); @@ -1144,7 +1147,7 @@ int main(int argc, char *argv[]) // Invoke concatenate on given interface of the object { - auto method = concatenatorProxy->createMethodCall(interfaceName, "concatenate"); + auto method = concatenatorProxy->createMethodCall(interfaceName, concatenate); method << numbers << separator; concatenatorProxy->callMethod(method, callback); // When the reply comes, we shall get "Got concatenate result 1:2:3" on the standard output @@ -1152,7 +1155,7 @@ int main(int argc, char *argv[]) // Invoke concatenate again, this time with no numbers and we shall get an error { - auto method = concatenatorProxy->createMethodCall(interfaceName, "concatenate"); + auto method = concatenatorProxy->createMethodCall(interfaceName, concatenate); method << std::vector() << separator; concatenatorProxy->callMethod(method, callback); // When the reply comes, we shall get concatenation error message on the standard error output @@ -1174,7 +1177,7 @@ Another option is to use `std::future`-based overload of the `IProxy::callMethod ... // Invoke concatenate on given interface of the object { - auto method = concatenatorProxy->createMethodCall(interfaceName, "concatenate"); + auto method = concatenatorProxy->createMethodCall(interfaceName, concatenate); method << numbers << separator; auto future = concatenatorProxy->callMethod(method, sdbus::with_future); try @@ -1702,10 +1705,9 @@ int main(int argc, char *argv[]) // We can now use connection objects in a familiar way, e.g. create adaptor and proxy objects on them, and exchange messages. // Here, using Concatenator IDL-generated bindings example from chapters above: - const char* objectPath = "/org/sdbuscpp/concatenator"; - Concatenator concatenator(*serverConnection, objectPath); - const char* emptyDestinationName = ""; // Destination may be empty in case of direct connections - ConcatenatorProxy concatenatorProxy(*clientConnection, emptyDestinationName, objectPath); + Concatenator concatenator(*serverConnection, sdbus::ObjectPath{"/org/sdbuscpp/concatenator"}); + sdbus::ServiceName emptyDestination; // Destination may be empty in case of direct connections + ConcatenatorProxy concatenatorProxy(*clientConnection, std::move(emptyDestination), sdbus::ObjectPath{"/org/sdbuscpp/concatenator"}); // Perform call of concatenate D-Bus method std::vector numbers = {1, 2, 3}; @@ -1750,6 +1752,13 @@ sdbus-c++ v2 is a major release that comes with a number of breaking API/ABI/beh * Change in behavior: In *synchronous* D-Bus calls, the proxy object now keeps the connection instance blocked for the entire duration of the method call. Incoming messages like signals will be queued and processed after the call. Access to the connection from other threads is blocked. To avoid this (in case this hurts you): * either use short-lived, light-weight proxies for such synchronous calls, * or call the method in an asynchronous way. +* Strong types were introduced for safer, less error-prone and more expressive API. What previously was `auto proxy = createProxy("org.sdbuscpp.concatenator", "/org/sdbuscpp/concatenator");` is now written like `auto proxy = createProxy(ServiceName{"org.sdbuscpp.concatenator"}, ObjectPath{"/org/sdbuscpp/concatenator"});`. These types are: + * `ObjectPath` type for the object path (the type has been around already but now is also used consistently in sdbus-c++ API for object path strings) + * `InterfaceName` type for D-Bus interface names + * `BusName` (and its aliases `ServiceName` and `ConnectionName`) type for bus/service/connection names + * `MemberName` (and its aliases `MethodName`, `SignalName` and `PropertyName`) type for D-Bus method, signal and property names + * `Signature` type for the D-Bus signature (the type has been around already but now is also used consistently in sdbus-c++ API for signature strings) + * `Error::Name` type for D-Bus error names * Signatures of callbacks `async_reply_handler`, `signal_handler`, `message_handler` and `property_set_callback` were modified to take input message objects by value instead of non-const ref to a message. The callback handler assumes ownership of the message. This API is cleaner and more self-explaining. * The `PollData` struct has been extended with a new data member: `eventFd`. All hooks with external event loops shall be modified to poll on this `eventFd` in addition to the `fd`. * `PollData::timeout_usec` was renamed to `PollData::timeout` and its type has been changed to `std::chrono::microseconds`. This member now holds directly what before had to be obtained through `PollData::getAbsoluteTimeout()` call. diff --git a/examples/org.freedesktop.DBus.ObjectManager/examplemanager-planet1-client-glue.h b/examples/org.freedesktop.DBus.ObjectManager/examplemanager-planet1-client-glue.h index e51fd78..913ad82 100644 --- a/examples/org.freedesktop.DBus.ObjectManager/examplemanager-planet1-client-glue.h +++ b/examples/org.freedesktop.DBus.ObjectManager/examplemanager-planet1-client-glue.h @@ -17,7 +17,7 @@ namespace ExampleManager { class Planet1_proxy { public: - static constexpr const char* INTERFACE_NAME = "org.sdbuscpp.ExampleManager.Planet1"; + static inline const sdbus::InterfaceName INTERFACE_NAME{"org.sdbuscpp.ExampleManager.Planet1"}; protected: Planet1_proxy(sdbus::IProxy& proxy) diff --git a/examples/org.freedesktop.DBus.ObjectManager/examplemanager-planet1-server-glue.h b/examples/org.freedesktop.DBus.ObjectManager/examplemanager-planet1-server-glue.h index b2ca89c..7acfac0 100644 --- a/examples/org.freedesktop.DBus.ObjectManager/examplemanager-planet1-server-glue.h +++ b/examples/org.freedesktop.DBus.ObjectManager/examplemanager-planet1-server-glue.h @@ -17,7 +17,7 @@ namespace ExampleManager { class Planet1_adaptor { public: - static constexpr const char* INTERFACE_NAME = "org.sdbuscpp.ExampleManager.Planet1"; + static inline const sdbus::InterfaceName INTERFACE_NAME{"org.sdbuscpp.ExampleManager.Planet1"}; protected: Planet1_adaptor(sdbus::IObject& object) diff --git a/examples/org.freedesktop.DBus.ObjectManager/obj-manager-client.cpp b/examples/org.freedesktop.DBus.ObjectManager/obj-manager-client.cpp index 25184f1..be6f1b2 100644 --- a/examples/org.freedesktop.DBus.ObjectManager/obj-manager-client.cpp +++ b/examples/org.freedesktop.DBus.ObjectManager/obj-manager-client.cpp @@ -17,7 +17,7 @@ class PlanetProxy final : public sdbus::ProxyInterfaces< org::sdbuscpp::ExampleManager::Planet1_proxy > { public: - PlanetProxy(sdbus::IConnection& connection, std::string destination, std::string path) + PlanetProxy(sdbus::IConnection& connection, sdbus::ServiceName destination, sdbus::ObjectPath path) : ProxyInterfaces(connection, std::move(destination), std::move(path)) { registerProxy(); @@ -29,13 +29,13 @@ public: } }; -class ManagerProxy final : public sdbus::ProxyInterfaces< sdbus::ObjectManager_proxy > +class ManagerProxy final : public sdbus::ProxyInterfaces { public: - ManagerProxy(sdbus::IConnection& connection, const std::string& destination, std::string path) - : ProxyInterfaces(connection, destination, std::move(path)) - , m_connection(connection) - , m_destination(destination) + ManagerProxy(sdbus::IConnection& connection, sdbus::ServiceName destination, sdbus::ObjectPath path) + : ProxyInterfaces(connection, destination, std::move(path)) + , m_connection(connection) + , m_destination(destination) { registerProxy(); } @@ -47,8 +47,7 @@ public: void handleExistingObjects() { - std::map>> objectsInterfacesAndProperties; - objectsInterfacesAndProperties = GetManagedObjects(); + auto objectsInterfacesAndProperties = GetManagedObjects(); for (const auto& [object, interfacesAndProperties] : objectsInterfacesAndProperties) { onInterfacesAdded(object, interfacesAndProperties); } @@ -56,7 +55,7 @@ public: private: void onInterfacesAdded( const sdbus::ObjectPath& objectPath - , const std::map>& interfacesAndProperties) override + , const std::map>& interfacesAndProperties) override { std::cout << objectPath << " added:\t"; for (const auto& [interface, _] : interfacesAndProperties) { @@ -71,14 +70,14 @@ private: } const auto& properties = planetInterface->second; // get a property which was passed as part of the signal. - const auto& name = properties.at("Name").get(); + const auto& name = properties.at(sdbus::PropertyName{"Name"}).get(); // or create a proxy instance to the newly added object. PlanetProxy planet(m_connection, m_destination, objectPath); std::cout << name << " has a population of " << planet.GetPopulation() << ".\n" << std::endl; } void onInterfacesRemoved( const sdbus::ObjectPath& objectPath - , const std::vector& interfaces) override + , const std::vector& interfaces) override { std::cout << objectPath << " removed:\t"; for (const auto& interface : interfaces) { @@ -88,14 +87,16 @@ private: } sdbus::IConnection& m_connection; - std::string m_destination; + sdbus::ServiceName m_destination; }; int main() { auto connection = sdbus::createSessionBusConnection(); - auto managerProxy = std::make_unique(*connection, "org.sdbuscpp.examplemanager", "/org/sdbuscpp/examplemanager"); + sdbus::ServiceName destination{"org.sdbuscpp.examplemanager"}; + sdbus::ObjectPath objectPath{"/org/sdbuscpp/examplemanager"}; + auto managerProxy = std::make_unique(*connection, std::move(destination), std::move(objectPath)); try { managerProxy->handleExistingObjects(); } @@ -107,4 +108,4 @@ int main() connection->enterEventLoop(); return 0; -} \ No newline at end of file +} diff --git a/examples/org.freedesktop.DBus.ObjectManager/obj-manager-server.cpp b/examples/org.freedesktop.DBus.ObjectManager/obj-manager-server.cpp index 4631ed5..9d4ef7d 100644 --- a/examples/org.freedesktop.DBus.ObjectManager/obj-manager-server.cpp +++ b/examples/org.freedesktop.DBus.ObjectManager/obj-manager-server.cpp @@ -19,10 +19,12 @@ #include #include +using sdbus::ObjectPath; + class ManagerAdaptor : public sdbus::AdaptorInterfaces { public: - ManagerAdaptor(sdbus::IConnection& connection, std::string path) + ManagerAdaptor(sdbus::IConnection& connection, sdbus::ObjectPath path) : AdaptorInterfaces(connection, std::move(path)) { registerAdaptor(); @@ -39,7 +41,7 @@ class PlanetAdaptor final : public sdbus::AdaptorInterfaces< org::sdbuscpp::Exam , sdbus::Properties_adaptor > { public: - PlanetAdaptor(sdbus::IConnection& connection, std::string path, std::string name, uint64_t population) + PlanetAdaptor(sdbus::IConnection& connection, sdbus::ObjectPath path, std::string name, uint64_t population) : AdaptorInterfaces(connection, std::move(path)) , m_name(std::move(name)) , m_population(population) @@ -82,18 +84,19 @@ void printCountDown(const std::string& message, int seconds) int main() { auto connection = sdbus::createSessionBusConnection(); - connection->requestName("org.sdbuscpp.examplemanager"); + sdbus::ServiceName serviceName{"org.sdbuscpp.examplemanager"}; + connection->requestName(serviceName); connection->enterEventLoopAsync(); - auto manager = std::make_unique(*connection, "/org/sdbuscpp/examplemanager"); + auto manager = std::make_unique(*connection, ObjectPath{"/org/sdbuscpp/examplemanager"}); while (true) { printCountDown("Creating PlanetAdaptor in ", 5); - auto earth = std::make_unique(*connection, "/org/sdbuscpp/examplemanager/Planet1/Earth", "Earth", 7'874'965'825); + auto earth = std::make_unique(*connection, ObjectPath{"/org/sdbuscpp/examplemanager/Planet1/Earth"}, "Earth", 7'874'965'825); printCountDown("Creating PlanetAdaptor in ", 5); - auto trantor = std::make_unique(*connection, "/org/sdbuscpp/examplemanager/Planet1/Trantor", "Trantor", 40'000'000'000); + auto trantor = std::make_unique(*connection, ObjectPath{"/org/sdbuscpp/examplemanager/Planet1/Trantor"}, "Trantor", 40'000'000'000); printCountDown("Creating PlanetAdaptor in ", 5); - auto laconia = std::make_unique(*connection, "/org/sdbuscpp/examplemanager/Planet1/Laconia", "Laconia", 231'721); + auto laconia = std::make_unique(*connection, ObjectPath{"/org/sdbuscpp/examplemanager/Planet1/Laconia"}, "Laconia", 231'721); printCountDown("Removing PlanetAdaptor in ", 5); earth.reset(); printCountDown("Removing PlanetAdaptor in ", 5); @@ -102,7 +105,7 @@ int main() laconia.reset(); } - connection->releaseName("org.sdbuscpp.examplemanager"); + connection->releaseName(serviceName); connection->leaveEventLoop(); return 0; } diff --git a/include/sdbus-c++/AdaptorInterfaces.h b/include/sdbus-c++/AdaptorInterfaces.h index 1340032..b089813 100644 --- a/include/sdbus-c++/AdaptorInterfaces.h +++ b/include/sdbus-c++/AdaptorInterfaces.h @@ -102,7 +102,7 @@ namespace sdbus { * * For more information, consult @ref createObject(sdbus::IConnection&,std::string) */ - AdaptorInterfaces(IConnection& connection, std::string objectPath) + AdaptorInterfaces(IConnection& connection, ObjectPath objectPath) : ObjectHolder(createObject(connection, std::move(objectPath))) , _Interfaces(getObject())... { diff --git a/include/sdbus-c++/ConvenienceApiClasses.h b/include/sdbus-c++/ConvenienceApiClasses.h index ee4cbe7..fbad100 100644 --- a/include/sdbus-c++/ConvenienceApiClasses.h +++ b/include/sdbus-c++/ConvenienceApiClasses.h @@ -53,7 +53,9 @@ namespace sdbus { { public: VTableAdder(IObject& object, std::vector vtable); + void forInterface(InterfaceName interfaceName); void forInterface(std::string interfaceName); + [[nodiscard]] Slot forInterface(InterfaceName interfaceName, return_slot_t); [[nodiscard]] Slot forInterface(std::string interfaceName, return_slot_t); private: @@ -64,15 +66,16 @@ namespace sdbus { class SignalEmitter { public: - SignalEmitter(IObject& object, const std::string& signalName); + SignalEmitter(IObject& object, const SignalName& signalName); SignalEmitter(SignalEmitter&& other) = default; ~SignalEmitter() noexcept(false); + SignalEmitter& onInterface(const InterfaceName& interfaceName); SignalEmitter& onInterface(const std::string& interfaceName); template void withArguments(_Args&&... args); private: IObject& object_; - const std::string& signalName_; + const SignalName& signalName_; Signal signal_; int exceptions_{}; // Number of active exceptions when SignalEmitter is constructed }; @@ -80,10 +83,11 @@ namespace sdbus { class MethodInvoker { public: - MethodInvoker(IProxy& proxy, const std::string& methodName); + MethodInvoker(IProxy& proxy, const MethodName& methodName); MethodInvoker(MethodInvoker&& other) = default; ~MethodInvoker() noexcept(false); + MethodInvoker& onInterface(const InterfaceName& interfaceName); MethodInvoker& onInterface(const std::string& interfaceName); MethodInvoker& withTimeout(uint64_t usec); template @@ -95,7 +99,7 @@ namespace sdbus { private: IProxy& proxy_; - const std::string& methodName_; + const MethodName& methodName_; uint64_t timeout_{}; MethodCall method_; int exceptions_{}; // Number of active exceptions when MethodInvoker is constructed @@ -105,7 +109,8 @@ namespace sdbus { class AsyncMethodInvoker { public: - AsyncMethodInvoker(IProxy& proxy, const std::string& methodName); + AsyncMethodInvoker(IProxy& proxy, const MethodName& methodName); + AsyncMethodInvoker& onInterface(const InterfaceName& interfaceName); AsyncMethodInvoker& onInterface(const std::string& interfaceName); AsyncMethodInvoker& withTimeout(uint64_t usec); template @@ -119,7 +124,7 @@ namespace sdbus { private: IProxy& proxy_; - const std::string& methodName_; + const MethodName& methodName_; uint64_t timeout_{}; MethodCall method_; }; @@ -127,7 +132,8 @@ namespace sdbus { class SignalSubscriber { public: - SignalSubscriber(IProxy& proxy, const std::string& signalName); + SignalSubscriber(IProxy& proxy, const SignalName& signalName); + SignalSubscriber& onInterface(InterfaceName interfaceName); SignalSubscriber& onInterface(std::string interfaceName); template void call(_Function&& callback); template [[nodiscard]] Slot call(_Function&& callback, return_slot_t); @@ -137,65 +143,81 @@ namespace sdbus { private: IProxy& proxy_; - const std::string& signalName_; - std::string interfaceName_; + const SignalName& signalName_; + InterfaceName interfaceName_; }; class PropertyGetter { public: - PropertyGetter(IProxy& proxy, const std::string& propertyName); + PropertyGetter(IProxy& proxy, const PropertyName& propertyName); + Variant onInterface(const InterfaceName& interfaceName); Variant onInterface(const std::string& interfaceName); + private: + static inline const InterfaceName DBUS_PROPERTIES_INTERFACE_NAME{"org.freedesktop.DBus.Properties"}; + private: IProxy& proxy_; - const std::string& propertyName_; + const PropertyName& propertyName_; }; class AsyncPropertyGetter { public: - AsyncPropertyGetter(IProxy& proxy, const std::string& propertyName); + AsyncPropertyGetter(IProxy& proxy, const PropertyName& propertyName); + AsyncPropertyGetter& onInterface(const InterfaceName& interfaceName); AsyncPropertyGetter& onInterface(const std::string& interfaceName); template PendingAsyncCall uponReplyInvoke(_Function&& callback); std::future getResultAsFuture(); + private: + static inline const InterfaceName DBUS_PROPERTIES_INTERFACE_NAME{"org.freedesktop.DBus.Properties"}; + private: IProxy& proxy_; - const std::string& propertyName_; - const std::string* interfaceName_{}; + const PropertyName& propertyName_; + const InterfaceName* interfaceName_{}; }; class PropertySetter { public: - PropertySetter(IProxy& proxy, const std::string& propertyName); + PropertySetter(IProxy& proxy, const PropertyName& propertyName); + PropertySetter& onInterface(const InterfaceName& interfaceName); PropertySetter& onInterface(const std::string& interfaceName); template void toValue(const _Value& value); template void toValue(const _Value& value, dont_expect_reply_t); void toValue(const Variant& value); void toValue(const Variant& value, dont_expect_reply_t); + private: + static inline const InterfaceName DBUS_PROPERTIES_INTERFACE_NAME{"org.freedesktop.DBus.Properties"}; + private: IProxy& proxy_; - const std::string& propertyName_; - const std::string* interfaceName_{}; + const PropertyName& propertyName_; + const InterfaceName* interfaceName_{}; }; class AsyncPropertySetter { public: - AsyncPropertySetter(IProxy& proxy, const std::string& propertyName); + AsyncPropertySetter(IProxy& proxy, const PropertyName& propertyName); + AsyncPropertySetter& onInterface(const InterfaceName& interfaceName); AsyncPropertySetter& onInterface(const std::string& interfaceName); template AsyncPropertySetter& toValue(_Value&& value); AsyncPropertySetter& toValue(Variant value); template PendingAsyncCall uponReplyInvoke(_Function&& callback); std::future getResultAsFuture(); + private: + static inline const InterfaceName DBUS_PROPERTIES_INTERFACE_NAME{"org.freedesktop.DBus.Properties"}; + private: IProxy& proxy_; - const std::string& propertyName_; - const std::string* interfaceName_{}; + const PropertyName& propertyName_; + const InterfaceName* interfaceName_{}; Variant value_; }; @@ -203,7 +225,11 @@ namespace sdbus { { public: AllPropertiesGetter(IProxy& proxy); - std::map onInterface(const std::string& interfaceName); + std::map onInterface(const InterfaceName& interfaceName); + std::map onInterface(const std::string& interfaceName); + + private: + static inline const InterfaceName DBUS_PROPERTIES_INTERFACE_NAME{"org.freedesktop.DBus.Properties"}; private: IProxy& proxy_; @@ -213,13 +239,17 @@ namespace sdbus { { public: AsyncAllPropertiesGetter(IProxy& proxy); + AsyncAllPropertiesGetter& onInterface(const InterfaceName& interfaceName); AsyncAllPropertiesGetter& onInterface(const std::string& interfaceName); template PendingAsyncCall uponReplyInvoke(_Function&& callback); - std::future> getResultAsFuture(); + std::future> getResultAsFuture(); + + private: + static inline const InterfaceName DBUS_PROPERTIES_INTERFACE_NAME{"org.freedesktop.DBus.Properties"}; private: IProxy& proxy_; - const std::string* interfaceName_{}; + const InterfaceName* interfaceName_{}; }; } // namespace sdbus diff --git a/include/sdbus-c++/ConvenienceApiClasses.inl b/include/sdbus-c++/ConvenienceApiClasses.inl index fbc2109..a6111da 100644 --- a/include/sdbus-c++/ConvenienceApiClasses.inl +++ b/include/sdbus-c++/ConvenienceApiClasses.inl @@ -53,21 +53,31 @@ namespace sdbus { { } - inline void VTableAdder::forInterface(std::string interfaceName) + inline void VTableAdder::forInterface(InterfaceName interfaceName) { object_.addVTable(std::move(interfaceName), std::move(vtable_)); } - [[nodiscard]] inline Slot VTableAdder::forInterface(std::string interfaceName, return_slot_t) + inline void VTableAdder::forInterface(std::string interfaceName) + { + forInterface(InterfaceName{std::move(interfaceName)}); + } + + [[nodiscard]] inline Slot VTableAdder::forInterface(InterfaceName interfaceName, return_slot_t) { return object_.addVTable(std::move(interfaceName), std::move(vtable_), return_slot); } + [[nodiscard]] inline Slot VTableAdder::forInterface(std::string interfaceName, return_slot_t) + { + return forInterface(InterfaceName{std::move(interfaceName)}, return_slot); + } + /*** ------------- ***/ /*** SignalEmitter ***/ /*** ------------- ***/ - inline SignalEmitter::SignalEmitter(IObject& object, const std::string& signalName) + inline SignalEmitter::SignalEmitter(IObject& object, const SignalName& signalName) : object_(object) , signalName_(signalName) , exceptions_(std::uncaught_exceptions()) @@ -92,13 +102,20 @@ namespace sdbus { object_.emitSignal(signal_); } - inline SignalEmitter& SignalEmitter::onInterface(const std::string& interfaceName) + inline SignalEmitter& SignalEmitter::onInterface(const InterfaceName& interfaceName) { signal_ = object_.createSignal(interfaceName, signalName_); return *this; } + inline SignalEmitter& SignalEmitter::onInterface(const std::string& interfaceName) + { + // Down-cast through static cast for performance reasons (no extra copy and object construction needed) + static_assert(sizeof(interfaceName) == sizeof(InterfaceName)); + return onInterface(static_cast(interfaceName)); + } + template inline void SignalEmitter::withArguments(_Args&&... args) { @@ -111,7 +128,7 @@ namespace sdbus { /*** MethodInvoker ***/ /*** ------------- ***/ - inline MethodInvoker::MethodInvoker(IProxy& proxy, const std::string& methodName) + inline MethodInvoker::MethodInvoker(IProxy& proxy, const MethodName& methodName) : proxy_(proxy) , methodName_(methodName) , exceptions_(std::uncaught_exceptions()) @@ -137,13 +154,20 @@ namespace sdbus { proxy_.callMethod(method_, timeout_); } - inline MethodInvoker& MethodInvoker::onInterface(const std::string& interfaceName) + inline MethodInvoker& MethodInvoker::onInterface(const InterfaceName& interfaceName) { method_ = proxy_.createMethodCall(interfaceName, methodName_); return *this; } + inline MethodInvoker& MethodInvoker::onInterface(const std::string& interfaceName) + { + // Down-cast through static cast for performance reasons (no extra copy and object construction needed) + static_assert(sizeof(interfaceName) == sizeof(InterfaceName)); + return onInterface(static_cast(interfaceName)); + } + inline MethodInvoker& MethodInvoker::withTimeout(uint64_t usec) { timeout_ = usec; @@ -190,19 +214,26 @@ namespace sdbus { /*** AsyncMethodInvoker ***/ /*** ------------------ ***/ - inline AsyncMethodInvoker::AsyncMethodInvoker(IProxy& proxy, const std::string& methodName) + inline AsyncMethodInvoker::AsyncMethodInvoker(IProxy& proxy, const MethodName& methodName) : proxy_(proxy) , methodName_(methodName) { } - inline AsyncMethodInvoker& AsyncMethodInvoker::onInterface(const std::string& interfaceName) + inline AsyncMethodInvoker& AsyncMethodInvoker::onInterface(const InterfaceName& interfaceName) { method_ = proxy_.createMethodCall(interfaceName, methodName_); return *this; } + inline AsyncMethodInvoker& AsyncMethodInvoker::onInterface(const std::string& interfaceName) + { + // Down-cast through static cast for performance reasons (no extra copy and object construction needed) + static_assert(sizeof(interfaceName) == sizeof(InterfaceName)); + return onInterface(static_cast(interfaceName)); + } + inline AsyncMethodInvoker& AsyncMethodInvoker::withTimeout(uint64_t usec) { timeout_ = usec; @@ -288,13 +319,18 @@ namespace sdbus { /*** SignalSubscriber ***/ /*** ---------------- ***/ - inline SignalSubscriber::SignalSubscriber(IProxy& proxy, const std::string& signalName) + inline SignalSubscriber::SignalSubscriber(IProxy& proxy, const SignalName& signalName) : proxy_(proxy) , signalName_(signalName) { } inline SignalSubscriber& SignalSubscriber::onInterface(std::string interfaceName) + { + return onInterface(InterfaceName{std::move(interfaceName)}); + } + + inline SignalSubscriber& SignalSubscriber::onInterface(InterfaceName interfaceName) { interfaceName_ = std::move(interfaceName); @@ -368,39 +404,53 @@ namespace sdbus { /*** PropertyGetter ***/ /*** -------------- ***/ - inline PropertyGetter::PropertyGetter(IProxy& proxy, const std::string& propertyName) + inline PropertyGetter::PropertyGetter(IProxy& proxy, const PropertyName& propertyName) : proxy_(proxy) , propertyName_(propertyName) { } - inline Variant PropertyGetter::onInterface(const std::string& interfaceName) + inline Variant PropertyGetter::onInterface(const InterfaceName& interfaceName) { Variant var; proxy_.callMethod("Get") - .onInterface("org.freedesktop.DBus.Properties") + .onInterface(DBUS_PROPERTIES_INTERFACE_NAME) .withArguments(interfaceName, propertyName_) .storeResultsTo(var); return var; } + inline Variant PropertyGetter::onInterface(const std::string& interfaceName) + { + // Down-cast through static cast for performance reasons (no extra copy and object construction needed) + static_assert(sizeof(interfaceName) == sizeof(InterfaceName)); + return onInterface(static_cast(interfaceName)); + } + /*** ------------------- ***/ /*** AsyncPropertyGetter ***/ /*** ------------------- ***/ - inline AsyncPropertyGetter::AsyncPropertyGetter(IProxy& proxy, const std::string& propertyName) + inline AsyncPropertyGetter::AsyncPropertyGetter(IProxy& proxy, const PropertyName& propertyName) : proxy_(proxy) , propertyName_(propertyName) { } - inline AsyncPropertyGetter& AsyncPropertyGetter::onInterface(const std::string& interfaceName) + inline AsyncPropertyGetter& AsyncPropertyGetter::onInterface(const InterfaceName& interfaceName) { interfaceName_ = &interfaceName; return *this; } + inline AsyncPropertyGetter& AsyncPropertyGetter::onInterface(const std::string& interfaceName) + { + // Down-cast through static cast for performance reasons (no extra copy and object construction needed) + static_assert(sizeof(interfaceName) == sizeof(InterfaceName)); + return onInterface(static_cast(interfaceName)); + } + template PendingAsyncCall AsyncPropertyGetter::uponReplyInvoke(_Function&& callback) { @@ -409,7 +459,7 @@ namespace sdbus { assert(interfaceName_ != nullptr); // onInterface() must be placed/called prior to this function return proxy_.callMethodAsync("Get") - .onInterface("org.freedesktop.DBus.Properties") + .onInterface(DBUS_PROPERTIES_INTERFACE_NAME) .withArguments(*interfaceName_, propertyName_) .uponReplyInvoke(std::forward<_Function>(callback)); } @@ -419,7 +469,7 @@ namespace sdbus { assert(interfaceName_ != nullptr); // onInterface() must be placed/called prior to this function return proxy_.callMethodAsync("Get") - .onInterface("org.freedesktop.DBus.Properties") + .onInterface(DBUS_PROPERTIES_INTERFACE_NAME) .withArguments(*interfaceName_, propertyName_) .getResultAsFuture(); } @@ -428,19 +478,26 @@ namespace sdbus { /*** PropertySetter ***/ /*** -------------- ***/ - inline PropertySetter::PropertySetter(IProxy& proxy, const std::string& propertyName) + inline PropertySetter::PropertySetter(IProxy& proxy, const PropertyName& propertyName) : proxy_(proxy) , propertyName_(propertyName) { } - inline PropertySetter& PropertySetter::onInterface(const std::string& interfaceName) + inline PropertySetter& PropertySetter::onInterface(const InterfaceName& interfaceName) { interfaceName_ = &interfaceName; return *this; } + inline PropertySetter& PropertySetter::onInterface(const std::string& interfaceName) + { + // Down-cast through static cast for performance reasons (no extra copy and object construction needed) + static_assert(sizeof(interfaceName) == sizeof(InterfaceName)); + return onInterface(static_cast(interfaceName)); + } + template inline void PropertySetter::toValue(const _Value& value) { @@ -458,7 +515,7 @@ namespace sdbus { assert(interfaceName_ != nullptr); // onInterface() must be placed/called prior to this function proxy_.callMethod("Set") - .onInterface("org.freedesktop.DBus.Properties") + .onInterface(DBUS_PROPERTIES_INTERFACE_NAME) .withArguments(*interfaceName_, propertyName_, value); } @@ -467,7 +524,7 @@ namespace sdbus { assert(interfaceName_ != nullptr); // onInterface() must be placed/called prior to this function proxy_.callMethod("Set") - .onInterface("org.freedesktop.DBus.Properties") + .onInterface(DBUS_PROPERTIES_INTERFACE_NAME) .withArguments(*interfaceName_, propertyName_, value) .dontExpectReply(); } @@ -476,19 +533,26 @@ namespace sdbus { /*** AsyncPropertySetter ***/ /*** ------------------- ***/ - inline AsyncPropertySetter::AsyncPropertySetter(IProxy& proxy, const std::string& propertyName) + inline AsyncPropertySetter::AsyncPropertySetter(IProxy& proxy, const PropertyName& propertyName) : proxy_(proxy) , propertyName_(propertyName) { } - inline AsyncPropertySetter& AsyncPropertySetter::onInterface(const std::string& interfaceName) + inline AsyncPropertySetter& AsyncPropertySetter::onInterface(const InterfaceName& interfaceName) { interfaceName_ = &interfaceName; return *this; } + inline AsyncPropertySetter& AsyncPropertySetter::onInterface(const std::string& interfaceName) + { + // Down-cast through static cast for performance reasons (no extra copy and object construction needed) + static_assert(sizeof(interfaceName) == sizeof(InterfaceName)); + return onInterface(static_cast(interfaceName)); + } + template inline AsyncPropertySetter& AsyncPropertySetter::toValue(_Value&& value) { @@ -510,7 +574,7 @@ namespace sdbus { assert(interfaceName_ != nullptr); // onInterface() must be placed/called prior to this function return proxy_.callMethodAsync("Set") - .onInterface("org.freedesktop.DBus.Properties") + .onInterface(DBUS_PROPERTIES_INTERFACE_NAME) .withArguments(*interfaceName_, propertyName_, std::move(value_)) .uponReplyInvoke(std::forward<_Function>(callback)); } @@ -520,7 +584,7 @@ namespace sdbus { assert(interfaceName_ != nullptr); // onInterface() must be placed/called prior to this function return proxy_.callMethodAsync("Set") - .onInterface("org.freedesktop.DBus.Properties") + .onInterface(DBUS_PROPERTIES_INTERFACE_NAME) .withArguments(*interfaceName_, propertyName_, std::move(value_)) .getResultAsFuture<>(); } @@ -534,16 +598,23 @@ namespace sdbus { { } - inline std::map AllPropertiesGetter::onInterface(const std::string& interfaceName) + inline std::map AllPropertiesGetter::onInterface(const InterfaceName& interfaceName) { - std::map props; + std::map props; proxy_.callMethod("GetAll") - .onInterface("org.freedesktop.DBus.Properties") + .onInterface(DBUS_PROPERTIES_INTERFACE_NAME) .withArguments(interfaceName) .storeResultsTo(props); return props; } + inline std::map AllPropertiesGetter::onInterface(const std::string& interfaceName) + { + // Down-cast through static cast for performance reasons (no extra copy and object construction needed) + static_assert(sizeof(interfaceName) == sizeof(InterfaceName)); + return onInterface(static_cast(interfaceName)); + } + /*** ------------------------ ***/ /*** AsyncAllPropertiesGetter ***/ /*** ------------------------ ***/ @@ -553,35 +624,42 @@ namespace sdbus { { } - inline AsyncAllPropertiesGetter& AsyncAllPropertiesGetter::onInterface(const std::string& interfaceName) + inline AsyncAllPropertiesGetter& AsyncAllPropertiesGetter::onInterface(const InterfaceName& interfaceName) { interfaceName_ = &interfaceName; return *this; } + inline AsyncAllPropertiesGetter& AsyncAllPropertiesGetter::onInterface(const std::string& interfaceName) + { + // Down-cast through static cast for performance reasons (no extra copy and object construction needed) + static_assert(sizeof(interfaceName) == sizeof(InterfaceName)); + return onInterface(static_cast(interfaceName)); + } + template PendingAsyncCall AsyncAllPropertiesGetter::uponReplyInvoke(_Function&& callback) { - static_assert( std::is_invocable_r_v, std::map> - , "All properties get callback function must accept std::optional, std::map> + , "All properties get callback function must accept std::optional and a map of property names to their values" ); assert(interfaceName_ != nullptr); // onInterface() must be placed/called prior to this function return proxy_.callMethodAsync("GetAll") - .onInterface("org.freedesktop.DBus.Properties") + .onInterface(DBUS_PROPERTIES_INTERFACE_NAME) .withArguments(*interfaceName_) .uponReplyInvoke(std::forward<_Function>(callback)); } - inline std::future> AsyncAllPropertiesGetter::getResultAsFuture() + inline std::future> AsyncAllPropertiesGetter::getResultAsFuture() { assert(interfaceName_ != nullptr); // onInterface() must be placed/called prior to this function return proxy_.callMethodAsync("GetAll") - .onInterface("org.freedesktop.DBus.Properties") + .onInterface(DBUS_PROPERTIES_INTERFACE_NAME) .withArguments(*interfaceName_) - .getResultAsFuture>(); + .getResultAsFuture>(); } } // namespace sdbus diff --git a/include/sdbus-c++/Error.h b/include/sdbus-c++/Error.h index 1bebd91..c52dbc1 100644 --- a/include/sdbus-c++/Error.h +++ b/include/sdbus-c++/Error.h @@ -43,19 +43,34 @@ namespace sdbus { : public std::runtime_error { public: - explicit Error(const std::string& name, const char* message = nullptr) - : Error(name, std::string(message ? message : "")) + // Strong type representing the D-Bus error name + class Name : public std::string + { + public: + Name() = default; + explicit Name(std::string value) + : std::string(std::move(value)) + {} + explicit Name(const char* value) + : std::string(value) + {} + + using std::string::operator=; + }; + + explicit Error(Name name, const char* message = nullptr) + : Error(std::move(name), std::string(message ? message : "")) { } - Error(const std::string& name, const std::string& message) + Error(Name name, std::string message) : std::runtime_error("[" + name + "] " + message) - , name_(name) - , message_(message) + , name_(std::move(name)) + , message_(std::move(message)) { } - [[nodiscard]] const std::string& getName() const + [[nodiscard]] const Name& getName() const { return name_; } @@ -71,13 +86,13 @@ namespace sdbus { } private: - std::string name_; + Name name_; std::string message_; }; - sdbus::Error createError(int errNo, const std::string& customMsg); + Error createError(int errNo, std::string customMsg); - inline const char* SDBUSCPP_ERROR_NAME = "org.sdbuscpp.Error"; + inline const Error::Name SDBUSCPP_ERROR_NAME{"org.sdbuscpp.Error"}; } #define SDBUS_THROW_ERROR(_MSG, _ERRNO) \ diff --git a/include/sdbus-c++/IConnection.h b/include/sdbus-c++/IConnection.h index 11f4c56..a95ee20 100644 --- a/include/sdbus-c++/IConnection.h +++ b/include/sdbus-c++/IConnection.h @@ -35,10 +35,14 @@ #include #include +// Forward declarations struct sd_bus; struct sd_event; namespace sdbus { - class Message; + class Message; + class ObjectPath; + class BusName; + using ServiceName = BusName; } namespace sdbus { @@ -61,29 +65,29 @@ namespace sdbus { virtual ~IConnection() = default; /*! - * @brief Requests D-Bus name on the connection + * @brief Requests a well-known D-Bus service name on a bus * * @param[in] name Name to request * * @throws sdbus::Error in case of failure */ - virtual void requestName(const std::string& name) = 0; + virtual void requestName(const ServiceName& name) = 0; /*! - * @brief Releases D-Bus name on the connection + * @brief Releases an acquired well-known D-Bus service name on a bus * * @param[in] name Name to release * * @throws sdbus::Error in case of failure */ - virtual void releaseName(const std::string& name) = 0; + virtual void releaseName(const ServiceName& name) = 0; /*! * @brief Retrieves the unique name of a connection. E.g. ":1.xx" * * @throws sdbus::Error in case of failure */ - [[nodiscard]] virtual std::string getUniqueName() const = 0; + [[nodiscard]] virtual BusName getUniqueName() const = 0; /*! * @brief Enters I/O event loop on this bus connection @@ -257,7 +261,7 @@ namespace sdbus { * * @throws sdbus::Error in case of failure */ - virtual void addObjectManager(const std::string& objectPath, floating_slot_t) = 0; + virtual void addObjectManager(const ObjectPath& objectPath, floating_slot_t) = 0; /*! * @brief Installs a match rule for messages received on this bus connection @@ -412,7 +416,7 @@ namespace sdbus { * * @throws sdbus::Error in case of failure */ - [[nodiscard]] std::unique_ptr createBusConnection(const std::string& name); + [[nodiscard]] std::unique_ptr createBusConnection(const ServiceName& name); /*! * @brief Creates/opens D-Bus system bus connection @@ -431,7 +435,7 @@ namespace sdbus { * * @throws sdbus::Error in case of failure */ - [[nodiscard]] std::unique_ptr createSystemBusConnection(const std::string& name); + [[nodiscard]] std::unique_ptr createSystemBusConnection(const ServiceName& name); /*! * @brief Creates/opens D-Bus session bus connection @@ -450,7 +454,7 @@ namespace sdbus { * * @throws sdbus::Error in case of failure */ - [[nodiscard]] std::unique_ptr createSessionBusConnection(const std::string& name); + [[nodiscard]] std::unique_ptr createSessionBusConnection(const ServiceName& name); /*! * @brief Creates/opens D-Bus session bus connection at a custom address diff --git a/include/sdbus-c++/IObject.h b/include/sdbus-c++/IObject.h index b3c118e..97b3147 100644 --- a/include/sdbus-c++/IObject.h +++ b/include/sdbus-c++/IObject.h @@ -41,6 +41,7 @@ namespace sdbus { class Signal; class IConnection; + class ObjectPath; } namespace sdbus { @@ -89,7 +90,7 @@ namespace sdbus { */ template < typename... VTableItems , typename = std::enable_if_t<(is_one_of_variants_types> && ...)> > - void addVTable(std::string interfaceName, VTableItems&&... items); + void addVTable(InterfaceName interfaceName, VTableItems&&... items); /*! * @brief Adds a declaration of methods, properties and signals of the object at a given interface @@ -114,7 +115,7 @@ namespace sdbus { * * @throws sdbus::Error in case of failure */ - virtual void addVTable(std::string interfaceName, std::vector vtable) = 0; + virtual void addVTable(InterfaceName interfaceName, std::vector vtable) = 0; /*! * @brief Adds a declaration of methods, properties and signals of the object at a given interface @@ -141,7 +142,7 @@ namespace sdbus { * * @throws sdbus::Error in case of failure */ - [[nodiscard]] virtual Slot addVTable(std::string interfaceName, std::vector vtable, return_slot_t) = 0; + [[nodiscard]] virtual Slot addVTable(InterfaceName interfaceName, std::vector vtable, return_slot_t) = 0; /*! * @brief A little more convenient overload of addVTable() above @@ -188,7 +189,7 @@ namespace sdbus { * * @throws sdbus::Error in case of failure */ - [[nodiscard]] virtual Signal createSignal(const std::string& interfaceName, const std::string& signalName) = 0; + [[nodiscard]] virtual Signal createSignal(const InterfaceName& interfaceName, const SignalName& signalName) = 0; /*! * @brief Emits signal for this object path @@ -201,6 +202,28 @@ namespace sdbus { */ virtual void emitSignal(const sdbus::Signal& message) = 0; + /*! + * @brief Emits signal on D-Bus + * + * @param[in] signalName Name of the signal + * @return A helper object for convenient emission of signals + * + * This is a high-level, convenience way of emitting D-Bus signals that abstracts + * from the D-Bus message concept. Signal arguments are automatically serialized + * in a message and D-Bus signatures automatically deduced from the provided native arguments. + * + * Example of use: + * @code + * int arg1 = ...; + * double arg2 = ...; + * SignalName fooSignal{"fooSignal"}; + * object_.emitSignal(fooSignal).onInterface("com.kistler.foo").withArguments(arg1, arg2); + * @endcode + * + * @throws sdbus::Error in case of failure + */ + [[nodiscard]] SignalEmitter emitSignal(const SignalName& signalName); + /*! * @brief Emits signal on D-Bus * @@ -230,7 +253,7 @@ namespace sdbus { * * @throws sdbus::Error in case of failure */ - virtual void emitPropertiesChangedSignal(const std::string& interfaceName, const std::vector& propNames) = 0; + virtual void emitPropertiesChangedSignal(const InterfaceName& interfaceName, const std::vector& propNames) = 0; /*! * @brief Emits PropertyChanged signal for all properties on a given interface of this object path @@ -239,7 +262,7 @@ namespace sdbus { * * @throws sdbus::Error in case of failure */ - virtual void emitPropertiesChangedSignal(const std::string& interfaceName) = 0; + virtual void emitPropertiesChangedSignal(const InterfaceName& interfaceName) = 0; /*! * @brief Emits InterfacesAdded signal on this object path @@ -264,7 +287,7 @@ namespace sdbus { * * @throws sdbus::Error in case of failure */ - virtual void emitInterfacesAddedSignal(const std::vector& interfaces) = 0; + virtual void emitInterfacesAddedSignal(const std::vector& interfaces) = 0; /*! * @brief Emits InterfacesRemoved signal on this object path @@ -286,7 +309,7 @@ namespace sdbus { * * @throws sdbus::Error in case of failure */ - virtual void emitInterfacesRemovedSignal(const std::vector& interfaces) = 0; + virtual void emitInterfacesRemovedSignal(const std::vector& interfaces) = 0; /*! * @brief Adds an ObjectManager interface at the path of this D-Bus object @@ -322,7 +345,7 @@ namespace sdbus { /*! * @brief Returns object path of the underlying DBus object */ - [[nodiscard]] virtual const std::string& getObjectPath() const = 0; + [[nodiscard]] virtual const ObjectPath& getObjectPath() const = 0; /*! * @brief Provides access to the currently processed D-Bus message @@ -342,13 +365,20 @@ namespace sdbus { // Out-of-line member definitions - inline SignalEmitter IObject::emitSignal(const std::string& signalName) + inline SignalEmitter IObject::emitSignal(const SignalName& signalName) { return SignalEmitter(*this, signalName); } + inline SignalEmitter IObject::emitSignal(const std::string& signalName) + { + // Down-cast through static cast for performance reasons (no extra copy and object construction needed) + static_assert(sizeof(signalName) == sizeof(SignalName)); + return emitSignal(static_cast(signalName)); + } + template - void IObject::addVTable(std::string interfaceName, VTableItems&&... items) + void IObject::addVTable(InterfaceName interfaceName, VTableItems&&... items) { addVTable(std::move(interfaceName), {std::forward(items)...}); } @@ -382,7 +412,7 @@ namespace sdbus { * auto proxy = sdbus::createObject(connection, "/com/kistler/foo"); * @endcode */ - [[nodiscard]] std::unique_ptr createObject(sdbus::IConnection& connection, std::string objectPath); + [[nodiscard]] std::unique_ptr createObject(sdbus::IConnection& connection, ObjectPath objectPath); } diff --git a/include/sdbus-c++/IProxy.h b/include/sdbus-c++/IProxy.h index b555cc6..88eb1b8 100644 --- a/include/sdbus-c++/IProxy.h +++ b/include/sdbus-c++/IProxy.h @@ -41,6 +41,7 @@ namespace sdbus { class MethodCall; class MethodReply; class IConnection; + class ObjectPath; class PendingAsyncCall; namespace internal { class Proxy; @@ -81,7 +82,7 @@ namespace sdbus { * * @throws sdbus::Error in case of failure */ - [[nodiscard]] virtual MethodCall createMethodCall(const std::string& interfaceName, const std::string& methodName) = 0; + [[nodiscard]] virtual MethodCall createMethodCall(const InterfaceName& interfaceName, const MethodName& methodName) = 0; /*! * @brief Calls method on the remote D-Bus object @@ -211,11 +212,17 @@ namespace sdbus { * Example of use: * @code * int result, a = ..., b = ...; - * object_.callMethod("multiply").onInterface(INTERFACE_NAME).withArguments(a, b).storeResultsTo(result); + * MethodName multiply{"multiply"}; + * object_.callMethod(multiply).onInterface(INTERFACE_NAME).withArguments(a, b).storeResultsTo(result); * @endcode * * @throws sdbus::Error in case of failure */ + [[nodiscard]] MethodInvoker callMethod(const MethodName& methodName); + + /*! + * @copydoc IProxy::callMethod(const MethodName&) + */ [[nodiscard]] MethodInvoker callMethod(const std::string& methodName); /*! @@ -232,7 +239,8 @@ namespace sdbus { * Example of use: * @code * int a = ..., b = ...; - * object_.callMethodAsync("multiply").onInterface(INTERFACE_NAME).withArguments(a, b).uponReplyInvoke([](int result) + * MethodName multiply{"multiply"}; + * object_.callMethodAsync(multiply).onInterface(INTERFACE_NAME).withArguments(a, b).uponReplyInvoke([](int result) * { * std::cout << "Got result of multiplying " << a << " and " << b << ": " << result << std::endl; * }); @@ -240,6 +248,11 @@ namespace sdbus { * * @throws sdbus::Error in case of failure */ + [[nodiscard]] AsyncMethodInvoker callMethodAsync(const MethodName& methodName); + + /*! + * @copydoc IProxy::callMethodAsync(const MethodName&) + */ [[nodiscard]] AsyncMethodInvoker callMethodAsync(const std::string& methodName); /*! @@ -254,8 +267,8 @@ namespace sdbus { * * @throws sdbus::Error in case of failure */ - virtual void registerSignalHandler( const std::string& interfaceName - , const std::string& signalName + virtual void registerSignalHandler( const InterfaceName& interfaceName + , const SignalName& signalName , signal_handler signalHandler ) = 0; /*! @@ -273,8 +286,8 @@ namespace sdbus { * * @throws sdbus::Error in case of failure */ - [[nodiscard]] virtual Slot registerSignalHandler( const std::string& interfaceName - , const std::string& signalName + [[nodiscard]] virtual Slot registerSignalHandler( const InterfaceName& interfaceName + , const SignalName& signalName , signal_handler signalHandler , return_slot_t ) = 0; @@ -294,11 +307,19 @@ namespace sdbus { * * Example of use: * @code - * object_.uponSignal("fooSignal").onInterface("com.kistler.foo").call([this](int arg1, double arg2){ this->onFooSignal(arg1, arg2); }); + * object_.uponSignal("stateChanged").onInterface("com.kistler.foo").call([this](int arg1, double arg2){ this->onStateChanged(arg1, arg2); }); + * sdbus::InterfaceName foo{"com.kistler.foo"}; + * sdbus::SignalName levelChanged{"levelChanged"}; + * object_.uponSignal(levelChanged).onInterface(foo).call([this](uint16_t level){ this->onLevelChanged(level); }); * @endcode * * @throws sdbus::Error in case of failure */ + [[nodiscard]] SignalSubscriber uponSignal(const SignalName& signalName); + + /*! + * @copydoc IProxy::uponSignal(const SignalName&) + */ [[nodiscard]] SignalSubscriber uponSignal(const std::string& signalName); /*! @@ -325,10 +346,18 @@ namespace sdbus { * Example of use: * @code * int state = object.getProperty("state").onInterface("com.kistler.foo"); + * sdbus::InterfaceName foo{"com.kistler.foo"}; + * sdbus::PropertyName level{"level"}; + * int level = object.getProperty(level).onInterface(foo); * @endcode * * @throws sdbus::Error in case of failure */ + [[nodiscard]] PropertyGetter getProperty(const PropertyName& propertyName); + + /*! + * @copydoc IProxy::getProperty(const PropertyName&) + */ [[nodiscard]] PropertyGetter getProperty(const std::string& propertyName); /*! @@ -349,6 +378,11 @@ namespace sdbus { * * @throws sdbus::Error in case of failure */ + [[nodiscard]] AsyncPropertyGetter getPropertyAsync(const PropertyName& propertyName); + + /*! + * @copydoc IProxy::getPropertyAsync(const PropertyName&) + */ [[nodiscard]] AsyncPropertyGetter getPropertyAsync(const std::string& propertyName); /*! @@ -371,6 +405,11 @@ namespace sdbus { * * @throws sdbus::Error in case of failure */ + [[nodiscard]] PropertySetter setProperty(const PropertyName& propertyName); + + /*! + * @copydoc IProxy::setProperty(const PropertyName&) + */ [[nodiscard]] PropertySetter setProperty(const std::string& propertyName); /*! @@ -391,6 +430,11 @@ namespace sdbus { * * @throws sdbus::Error in case of failure */ + [[nodiscard]] AsyncPropertySetter setPropertyAsync(const PropertyName& propertyName); + + /*! + * @copydoc IProxy::setPropertyAsync(const PropertyName&) + */ [[nodiscard]] AsyncPropertySetter setPropertyAsync(const std::string& propertyName); /*! @@ -420,7 +464,7 @@ namespace sdbus { * * Example of use: * @code - * auto callback = [](std::optional err, const std::map>& properties){ ... }; + * auto callback = [](std::optional err, const std::map>& properties){ ... }; * auto props = object.getAllPropertiesAsync().onInterface("com.kistler.foo").uponReplyInvoke(std::move(callback)); * @endcode * @@ -438,7 +482,7 @@ namespace sdbus { /*! * @brief Returns object path of the underlying DBus object */ - [[nodiscard]] virtual const std::string& getObjectPath() const = 0; + [[nodiscard]] virtual const ObjectPath& getObjectPath() const = 0; /*! * @brief Provides access to the currently processed D-Bus message @@ -525,41 +569,90 @@ namespace sdbus { return callMethodAsync(message, microsecs.count(), with_future); } - inline MethodInvoker IProxy::callMethod(const std::string& methodName) + inline MethodInvoker IProxy::callMethod(const MethodName& methodName) { return MethodInvoker(*this, methodName); } - inline AsyncMethodInvoker IProxy::callMethodAsync(const std::string& methodName) + inline MethodInvoker IProxy::callMethod(const std::string& methodName) + { + // Down-cast through static cast for performance reasons (no extra copy and object construction needed) + static_assert(sizeof(methodName) == sizeof(MethodName)); + return callMethod(static_cast(methodName)); + } + + inline AsyncMethodInvoker IProxy::callMethodAsync(const MethodName& methodName) { return AsyncMethodInvoker(*this, methodName); } - inline SignalSubscriber IProxy::uponSignal(const std::string& signalName) + inline AsyncMethodInvoker IProxy::callMethodAsync(const std::string& methodName) + { + // Down-cast through static cast for performance reasons (no extra copy and object construction needed) + static_assert(sizeof(methodName) == sizeof(MethodName)); + return callMethodAsync(static_cast(methodName)); + } + + inline SignalSubscriber IProxy::uponSignal(const SignalName& signalName) { return SignalSubscriber(*this, signalName); } - inline PropertyGetter IProxy::getProperty(const std::string& propertyName) + inline SignalSubscriber IProxy::uponSignal(const std::string& signalName) + { + // Down-cast through static cast for performance reasons (no extra copy and object construction needed) + static_assert(sizeof(signalName) == sizeof(SignalName)); + return uponSignal(static_cast(signalName)); + } + + inline PropertyGetter IProxy::getProperty(const PropertyName& propertyName) { return PropertyGetter(*this, propertyName); } - inline AsyncPropertyGetter IProxy::getPropertyAsync(const std::string& propertyName) + inline PropertyGetter IProxy::getProperty(const std::string& propertyName) + { + // Down-cast through static cast for performance reasons (no extra copy and object construction needed) + static_assert(sizeof(propertyName) == sizeof(PropertyName)); + return getProperty(static_cast(propertyName)); + } + + inline AsyncPropertyGetter IProxy::getPropertyAsync(const PropertyName& propertyName) { return AsyncPropertyGetter(*this, propertyName); } - inline PropertySetter IProxy::setProperty(const std::string& propertyName) + inline AsyncPropertyGetter IProxy::getPropertyAsync(const std::string& propertyName) + { + // Down-cast through static cast for performance reasons (no extra copy and object construction needed) + static_assert(sizeof(propertyName) == sizeof(PropertyName)); + return getPropertyAsync(static_cast(propertyName)); + } + + inline PropertySetter IProxy::setProperty(const PropertyName& propertyName) { return PropertySetter(*this, propertyName); } - inline AsyncPropertySetter IProxy::setPropertyAsync(const std::string& propertyName) + inline PropertySetter IProxy::setProperty(const std::string& propertyName) + { + // Down-cast through static cast for performance reasons (no extra copy and object construction needed) + static_assert(sizeof(propertyName) == sizeof(PropertyName)); + return setProperty(static_cast(propertyName)); + } + + inline AsyncPropertySetter IProxy::setPropertyAsync(const PropertyName& propertyName) { return AsyncPropertySetter(*this, propertyName); } + inline AsyncPropertySetter IProxy::setPropertyAsync(const std::string& propertyName) + { + // Down-cast through static cast for performance reasons (no extra copy and object construction needed) + static_assert(sizeof(propertyName) == sizeof(PropertyName)); + return setPropertyAsync(static_cast(propertyName)); + } + inline AllPropertiesGetter IProxy::getAllProperties() { return AllPropertiesGetter(*this); @@ -593,8 +686,8 @@ namespace sdbus { * @endcode */ [[nodiscard]] std::unique_ptr createProxy( sdbus::IConnection& connection - , std::string destination - , std::string objectPath ); + , ServiceName destination + , ObjectPath objectPath ); /*! * @brief Creates a proxy object for a specific remote D-Bus object @@ -619,8 +712,8 @@ namespace sdbus { * @endcode */ [[nodiscard]] std::unique_ptr createProxy( std::unique_ptr&& connection - , std::string destination - , std::string objectPath ); + , ServiceName destination + , ObjectPath objectPath ); /*! * @brief Creates a proxy object for a specific remote D-Bus object @@ -646,8 +739,8 @@ namespace sdbus { * @endcode */ [[nodiscard]] std::unique_ptr createProxy( std::unique_ptr&& connection - , std::string destination - , std::string objectPath + , ServiceName destination + , ObjectPath objectPath , dont_run_event_loop_thread_t ); /*! @@ -667,8 +760,8 @@ namespace sdbus { * auto proxy = sdbus::createProxy("com.kistler.foo", "/com/kistler/foo"); * @endcode */ - [[nodiscard]] std::unique_ptr createProxy( std::string destination - , std::string objectPath ); + [[nodiscard]] std::unique_ptr createProxy( ServiceName destination + , ObjectPath objectPath ); /*! * @brief Creates a proxy object for a specific remote D-Bus object @@ -688,8 +781,8 @@ namespace sdbus { * auto proxy = sdbus::createProxy("com.kistler.foo", "/com/kistler/foo", sdbus::dont_run_event_loop_thread ); * @endcode */ - [[nodiscard]] std::unique_ptr createProxy( std::string destination - , std::string objectPath + [[nodiscard]] std::unique_ptr createProxy( ServiceName destination + , ObjectPath objectPath , dont_run_event_loop_thread_t ); } diff --git a/include/sdbus-c++/Message.h b/include/sdbus-c++/Message.h index db5f658..811720e 100644 --- a/include/sdbus-c++/Message.h +++ b/include/sdbus-c++/Message.h @@ -52,10 +52,14 @@ namespace sdbus { class Variant; class ObjectPath; + class InterfaceName; + class MemberName; class Signature; template class Struct; class UnixFd; class MethodReply; + class BusName; + using ConnectionName = BusName; namespace internal { class ISdBus; } @@ -181,11 +185,11 @@ namespace sdbus { explicit operator bool() const; void clearFlags(); - std::string getInterfaceName() const; - std::string getMemberName() const; - std::string getSender() const; - std::string getPath() const; - std::string getDestination() const; + InterfaceName getInterfaceName() const; + MemberName getMemberName() const; + ConnectionName getSender() const; + ObjectPath getPath() const; + ConnectionName getDestination() const; void peekType(std::string& type, std::string& contents) const; bool isValid() const; bool isEmpty() const; @@ -281,7 +285,7 @@ namespace sdbus { public: Signal() = default; - void setDestination(const std::string& destination); + void setDestination(const ConnectionName& destination); void send() const; }; diff --git a/include/sdbus-c++/ProxyInterfaces.h b/include/sdbus-c++/ProxyInterfaces.h index d587523..6cbb804 100644 --- a/include/sdbus-c++/ProxyInterfaces.h +++ b/include/sdbus-c++/ProxyInterfaces.h @@ -104,7 +104,7 @@ namespace sdbus { * This constructor overload creates a proxy that manages its own D-Bus connection(s). * For more information on its behavior, consult @ref createProxy(std::string,std::string) */ - ProxyInterfaces(std::string destination, std::string objectPath) + ProxyInterfaces(ServiceName destination, ObjectPath objectPath) : ProxyObjectHolder(createProxy(std::move(destination), std::move(objectPath))) , _Interfaces(getProxy())... { @@ -119,7 +119,7 @@ namespace sdbus { * This constructor overload creates a proxy that manages its own D-Bus connection(s). * For more information on its behavior, consult @ref createProxy(std::string,std::string,sdbus::dont_run_event_loop_thread_t) */ - ProxyInterfaces(std::string destination, std::string objectPath, dont_run_event_loop_thread_t) + ProxyInterfaces(ServiceName destination, ObjectPath objectPath, dont_run_event_loop_thread_t) : ProxyObjectHolder(createProxy(std::move(destination), std::move(objectPath), dont_run_event_loop_thread)) , _Interfaces(getProxy())... { @@ -135,7 +135,7 @@ namespace sdbus { * The proxy created this way just references a D-Bus connection owned and managed by the user. * For more information on its behavior, consult @ref createProxy(IConnection&,std::string,std::string) */ - ProxyInterfaces(IConnection& connection, std::string destination, std::string objectPath) + ProxyInterfaces(IConnection& connection, ServiceName destination, ObjectPath objectPath) : ProxyObjectHolder(createProxy(connection, std::move(destination), std::move(objectPath))) , _Interfaces(getProxy())... { @@ -151,7 +151,7 @@ namespace sdbus { * The proxy created this way becomes an owner of the connection. * For more information on its behavior, consult @ref createProxy(std::unique_ptr&&,std::string,std::string) */ - ProxyInterfaces(std::unique_ptr&& connection, std::string destination, std::string objectPath) + ProxyInterfaces(std::unique_ptr&& connection, ServiceName destination, ObjectPath objectPath) : ProxyObjectHolder(createProxy(std::move(connection), std::move(destination), std::move(objectPath))) , _Interfaces(getProxy())... { @@ -167,7 +167,7 @@ namespace sdbus { * The proxy created this way becomes an owner of the connection. * For more information on its behavior, consult @ref createProxy(std::unique_ptr&&,std::string,std::string,sdbus::dont_run_event_loop_thread_t) */ - ProxyInterfaces(std::unique_ptr&& connection, std::string destination, std::string objectPath, dont_run_event_loop_thread_t) + ProxyInterfaces(std::unique_ptr&& connection, ServiceName destination, ObjectPath objectPath, dont_run_event_loop_thread_t) : ProxyObjectHolder(createProxy(std::move(connection), std::move(destination), std::move(objectPath), dont_run_event_loop_thread)) , _Interfaces(getProxy())... { diff --git a/include/sdbus-c++/StandardInterfaces.h b/include/sdbus-c++/StandardInterfaces.h index b9dee98..c1ffa50 100644 --- a/include/sdbus-c++/StandardInterfaces.h +++ b/include/sdbus-c++/StandardInterfaces.h @@ -39,7 +39,7 @@ namespace sdbus { // Proxy for peer class Peer_proxy { - static constexpr const char* INTERFACE_NAME = "org.freedesktop.DBus.Peer"; + static inline const InterfaceName INTERFACE_NAME{"org.freedesktop.DBus.Peer"}; protected: Peer_proxy(sdbus::IProxy& proxy) @@ -78,7 +78,7 @@ namespace sdbus { // Proxy for introspection class Introspectable_proxy { - static constexpr const char* INTERFACE_NAME = "org.freedesktop.DBus.Introspectable"; + static inline const InterfaceName INTERFACE_NAME{"org.freedesktop.DBus.Introspectable"}; protected: Introspectable_proxy(sdbus::IProxy& proxy) @@ -112,7 +112,7 @@ namespace sdbus { // Proxy for properties class Properties_proxy { - static constexpr const char* INTERFACE_NAME = "org.freedesktop.DBus.Properties"; + static inline const InterfaceName INTERFACE_NAME{"org.freedesktop.DBus.Properties"}; protected: Properties_proxy(sdbus::IProxy& proxy) @@ -132,68 +132,106 @@ namespace sdbus { proxy_ ->uponSignal("PropertiesChanged") .onInterface(INTERFACE_NAME) - .call([this]( const std::string& interfaceName - , const std::map& changedProperties - , const std::vector& invalidatedProperties ) + .call([this]( const InterfaceName& interfaceName + , const std::map& changedProperties + , const std::vector& invalidatedProperties ) { this->onPropertiesChanged(interfaceName, changedProperties, invalidatedProperties); }); } - virtual void onPropertiesChanged( const std::string& interfaceName - , const std::map& changedProperties - , const std::vector& invalidatedProperties ) = 0; + virtual void onPropertiesChanged( const InterfaceName& interfaceName + , const std::map& changedProperties + , const std::vector& invalidatedProperties ) = 0; public: - sdbus::Variant Get(const std::string& interfaceName, const std::string& propertyName) + sdbus::Variant Get(const InterfaceName& interfaceName, const PropertyName& propertyName) + { + return proxy_->getProperty(propertyName).onInterface(interfaceName); + } + + // TODO: Refactor from std::string to std::string_view before release/v2.0 !!! + sdbus::Variant Get(const InterfaceName& interfaceName, const std::string& propertyName) { return proxy_->getProperty(propertyName).onInterface(interfaceName); } template - PendingAsyncCall GetAsync(const std::string& interfaceName, const std::string& propertyName, _Function&& callback) + PendingAsyncCall GetAsync(const InterfaceName& interfaceName, const PropertyName& propertyName, _Function&& callback) { return proxy_->getPropertyAsync(propertyName).onInterface(interfaceName).uponReplyInvoke(std::forward<_Function>(callback)); } - std::future GetAsync(const std::string& interfaceName, const std::string& propertyName, with_future_t) + template + PendingAsyncCall GetAsync(const InterfaceName& interfaceName, const std::string& propertyName, _Function&& callback) + { + return proxy_->getPropertyAsync(propertyName).onInterface(interfaceName).uponReplyInvoke(std::forward<_Function>(callback)); + } + + std::future GetAsync(const InterfaceName& interfaceName, const PropertyName& propertyName, with_future_t) { return proxy_->getPropertyAsync(propertyName).onInterface(interfaceName).getResultAsFuture(); } - void Set(const std::string& interfaceName, const std::string& propertyName, const sdbus::Variant& value) + std::future GetAsync(const InterfaceName& interfaceName, const std::string& propertyName, with_future_t) + { + return proxy_->getPropertyAsync(propertyName).onInterface(interfaceName).getResultAsFuture(); + } + + void Set(const InterfaceName& interfaceName, const PropertyName& propertyName, const sdbus::Variant& value) { proxy_->setProperty(propertyName).onInterface(interfaceName).toValue(value); } - void Set(const std::string& interfaceName, const std::string& propertyName, const sdbus::Variant& value, dont_expect_reply_t) + void Set(const InterfaceName& interfaceName, const std::string& propertyName, const sdbus::Variant& value) + { + proxy_->setProperty(propertyName).onInterface(interfaceName).toValue(value); + } + + void Set(const InterfaceName& interfaceName, const PropertyName& propertyName, const sdbus::Variant& value, dont_expect_reply_t) + { + proxy_->setProperty(propertyName).onInterface(interfaceName).toValue(value, dont_expect_reply); + } + + void Set(const InterfaceName& interfaceName, const std::string& propertyName, const sdbus::Variant& value, dont_expect_reply_t) { proxy_->setProperty(propertyName).onInterface(interfaceName).toValue(value, dont_expect_reply); } template - PendingAsyncCall SetAsync(const std::string& interfaceName, const std::string& propertyName, const sdbus::Variant& value, _Function&& callback) + PendingAsyncCall SetAsync(const InterfaceName& interfaceName, const PropertyName& propertyName, const sdbus::Variant& value, _Function&& callback) { return proxy_->setPropertyAsync(propertyName).onInterface(interfaceName).toValue(value).uponReplyInvoke(std::forward<_Function>(callback)); } - std::future SetAsync(const std::string& interfaceName, const std::string& propertyName, const sdbus::Variant& value, with_future_t) + template + PendingAsyncCall SetAsync(const InterfaceName& interfaceName, const std::string& propertyName, const sdbus::Variant& value, _Function&& callback) + { + return proxy_->setPropertyAsync(propertyName).onInterface(interfaceName).toValue(value).uponReplyInvoke(std::forward<_Function>(callback)); + } + + std::future SetAsync(const InterfaceName& interfaceName, const PropertyName& propertyName, const sdbus::Variant& value, with_future_t) { return proxy_->setPropertyAsync(propertyName).onInterface(interfaceName).toValue(value).getResultAsFuture(); } - std::map GetAll(const std::string& interfaceName) + std::future SetAsync(const InterfaceName& interfaceName, const std::string& propertyName, const sdbus::Variant& value, with_future_t) + { + return proxy_->setPropertyAsync(propertyName).onInterface(interfaceName).toValue(value).getResultAsFuture(); + } + + std::map GetAll(const InterfaceName& interfaceName) { return proxy_->getAllProperties().onInterface(interfaceName); } template - PendingAsyncCall GetAllAsync(const std::string& interfaceName, _Function&& callback) + PendingAsyncCall GetAllAsync(const InterfaceName& interfaceName, _Function&& callback) { return proxy_->getAllPropertiesAsync().onInterface(interfaceName).uponReplyInvoke(std::forward<_Function>(callback)); } - std::future> GetAllAsync(const std::string& interfaceName, with_future_t) + std::future> GetAllAsync(const InterfaceName& interfaceName, with_future_t) { return proxy_->getAllPropertiesAsync().onInterface(interfaceName).getResultAsFuture(); } @@ -205,7 +243,7 @@ namespace sdbus { // Proxy for object manager class ObjectManager_proxy { - static constexpr const char* INTERFACE_NAME = "org.freedesktop.DBus.ObjectManager"; + static inline const InterfaceName INTERFACE_NAME{"org.freedesktop.DBus.ObjectManager"}; protected: ObjectManager_proxy(sdbus::IProxy& proxy) @@ -226,7 +264,7 @@ namespace sdbus { ->uponSignal("InterfacesAdded") .onInterface(INTERFACE_NAME) .call([this]( const sdbus::ObjectPath& objectPath - , const std::map>& interfacesAndProperties ) + , const std::map>& interfacesAndProperties ) { this->onInterfacesAdded(objectPath, interfacesAndProperties); }); @@ -234,21 +272,21 @@ namespace sdbus { proxy_->uponSignal("InterfacesRemoved") .onInterface(INTERFACE_NAME) .call([this]( const sdbus::ObjectPath& objectPath - , const std::vector& interfaces ) + , const std::vector& interfaces ) { this->onInterfacesRemoved(objectPath, interfaces); }); } virtual void onInterfacesAdded( const sdbus::ObjectPath& objectPath - , const std::map>& interfacesAndProperties) = 0; + , const std::map>& interfacesAndProperties) = 0; virtual void onInterfacesRemoved( const sdbus::ObjectPath& objectPath - , const std::vector& interfaces) = 0; + , const std::vector& interfaces) = 0; public: - std::map>> GetManagedObjects() + std::map>> GetManagedObjects() { - std::map>> objectsInterfacesAndProperties; + std::map>> objectsInterfacesAndProperties; proxy_->callMethod("GetManagedObjects").onInterface(INTERFACE_NAME).storeResultsTo(objectsInterfacesAndProperties); return objectsInterfacesAndProperties; } @@ -264,7 +302,7 @@ namespace sdbus { // Adaptor for properties class Properties_adaptor { - static constexpr const char* INTERFACE_NAME = "org.freedesktop.DBus.Properties"; + static inline const InterfaceName INTERFACE_NAME{"org.freedesktop.DBus.Properties"}; protected: Properties_adaptor(sdbus::IObject& object) : object_(&object) @@ -283,12 +321,12 @@ namespace sdbus { } public: - void emitPropertiesChangedSignal(const std::string& interfaceName, const std::vector& properties) + void emitPropertiesChangedSignal(const InterfaceName& interfaceName, const std::vector& properties) { object_->emitPropertiesChangedSignal(interfaceName, properties); } - void emitPropertiesChangedSignal(const std::string& interfaceName) + void emitPropertiesChangedSignal(const InterfaceName& interfaceName) { object_->emitPropertiesChangedSignal(interfaceName); } @@ -309,7 +347,7 @@ namespace sdbus { */ class ObjectManager_adaptor { - static constexpr const char* INTERFACE_NAME = "org.freedesktop.DBus.ObjectManager"; + static inline const InterfaceName INTERFACE_NAME{"org.freedesktop.DBus.ObjectManager"}; protected: explicit ObjectManager_adaptor(sdbus::IObject& object) : object_(&object) @@ -378,7 +416,7 @@ namespace sdbus { * * See IObject::emitInterfacesAddedSignal(). */ - void emitInterfacesAddedSignal(const std::vector& interfaces) + void emitInterfacesAddedSignal(const std::vector& interfaces) { object_->emitInterfacesAddedSignal(interfaces); } @@ -398,7 +436,7 @@ namespace sdbus { * * See IObject::emitInterfacesRemovedSignal(). */ - void emitInterfacesRemovedSignal(const std::vector& interfaces) + void emitInterfacesRemovedSignal(const std::vector& interfaces) { object_->emitInterfacesRemovedSignal(interfaces); } diff --git a/include/sdbus-c++/TypeTraits.h b/include/sdbus-c++/TypeTraits.h index 4fd0343..cec5f93 100644 --- a/include/sdbus-c++/TypeTraits.h +++ b/include/sdbus-c++/TypeTraits.h @@ -54,6 +54,9 @@ namespace sdbus { class ObjectPath; class Signature; class UnixFd; + class BusName; + class InterfaceName; + class MemberName; class MethodCall; class MethodReply; class Signal; @@ -309,6 +312,21 @@ namespace sdbus { } }; + template <> + struct signature_of : signature_of + { + }; + + template <> + struct signature_of : signature_of + { + }; + + template <> + struct signature_of : signature_of + { + }; + template struct signature_of> { diff --git a/include/sdbus-c++/Types.h b/include/sdbus-c++/Types.h index aeb1551..0323e34 100644 --- a/include/sdbus-c++/Types.h +++ b/include/sdbus-c++/Types.h @@ -171,42 +171,107 @@ namespace sdbus { /********************************************//** * @class ObjectPath * - * Representation of object path D-Bus type + * Strong type representing the D-Bus object path * ***********************************************/ class ObjectPath : public std::string { public: - using std::string::string; - ObjectPath() = default; // Fixes gcc 6.3 error (default c-tor is not imported in above using declaration) - ObjectPath(const ObjectPath&) = default; // Fixes gcc 8.3 error (deleted copy constructor) - ObjectPath(ObjectPath&&) = default; // Enable move - user-declared copy ctor prevents implicit creation - ObjectPath& operator = (const ObjectPath&) = default; // Fixes gcc 8.3 error (deleted copy assignment) - ObjectPath& operator = (ObjectPath&&) = default; // Enable move - user-declared copy assign prevents implicit creation - ObjectPath(std::string path) - : std::string(std::move(path)) + ObjectPath() = default; + explicit ObjectPath(std::string value) + : std::string(std::move(value)) {} + explicit ObjectPath(const char* value) + : std::string(value) + {} + using std::string::operator=; }; + /********************************************//** + * @class BusName + * + * Strong type representing the D-Bus bus/service/connection name + * + ***********************************************/ + class BusName : public std::string + { + public: + BusName() = default; + explicit BusName(std::string value) + : std::string(std::move(value)) + {} + explicit BusName(const char* value) + : std::string(value) + {} + + using std::string::operator=; + }; + + using ServiceName = BusName; + using ConnectionName = BusName; + + /********************************************//** + * @class InterfaceName + * + * Strong type representing the D-Bus interface name + * + ***********************************************/ + class InterfaceName : public std::string + { + public: + InterfaceName() = default; + explicit InterfaceName(std::string value) + : std::string(std::move(value)) + {} + explicit InterfaceName(const char* value) + : std::string(value) + {} + + using std::string::operator=; + }; + + /********************************************//** + * @class MemberName + * + * Strong type representing the D-Bus member name + * + ***********************************************/ + class MemberName : public std::string + { + public: + MemberName() = default; + explicit MemberName(std::string value) + : std::string(std::move(value)) + {} + explicit MemberName(const char* value) + : std::string(value) + {} + + using std::string::operator=; + }; + + using MethodName = MemberName; + using SignalName = MemberName; + using PropertyName = MemberName; + /********************************************//** * @class Signature * - * Representation of Signature D-Bus type + * Strong type representing the D-Bus object path * ***********************************************/ class Signature : public std::string { public: - using std::string::string; - Signature() = default; // Fixes gcc 6.3 error (default c-tor is not imported in above using declaration) - Signature(const Signature&) = default; // Fixes gcc 8.3 error (deleted copy constructor) - Signature(Signature&&) = default; // Enable move - user-declared copy ctor prevents implicit creation - Signature& operator = (const Signature&) = default; // Fixes gcc 8.3 error (deleted copy assignment) - Signature& operator = (Signature&&) = default; // Enable move - user-declared copy assign prevents implicit creation - Signature(std::string path) - : std::string(std::move(path)) + Signature() = default; + explicit Signature(std::string value) + : std::string(std::move(value)) {} + explicit Signature(const char* value) + : std::string(value) + {} + using std::string::operator=; }; diff --git a/include/sdbus-c++/VTableItems.h b/include/sdbus-c++/VTableItems.h index 73a95e7..b0aa3f0 100644 --- a/include/sdbus-c++/VTableItems.h +++ b/include/sdbus-c++/VTableItems.h @@ -27,6 +27,7 @@ #define SDBUS_CXX_VTABLEITEMS_H_ #include +#include #include #include @@ -46,15 +47,16 @@ namespace sdbus { MethodVTableItem& markAsPrivileged(); MethodVTableItem& withNoReply(); - std::string name; - std::string inputSignature; + MethodName name; + Signature inputSignature; std::vector inputParamNames; - std::string outputSignature; + Signature outputSignature; std::vector outputParamNames; method_callback callbackHandler; Flags flags; }; + MethodVTableItem registerMethod(MethodName methodName); MethodVTableItem registerMethod(std::string methodName); struct SignalVTableItem @@ -64,12 +66,13 @@ namespace sdbus { template SignalVTableItem& withParameters(_String... names); SignalVTableItem& markAsDeprecated(); - std::string name; - std::string signature; + SignalName name; + Signature signature; std::vector paramNames; Flags flags; }; + SignalVTableItem registerSignal(SignalName signalName); SignalVTableItem registerSignal(std::string signalName); struct PropertyVTableItem @@ -80,13 +83,14 @@ namespace sdbus { PropertyVTableItem& markAsPrivileged(); PropertyVTableItem& withUpdateBehavior(Flags::PropertyUpdateBehaviorFlags behavior); - std::string name; - std::string signature; + PropertyName name; + Signature signature; property_get_callback getter; property_set_callback setter; Flags flags; }; + PropertyVTableItem registerProperty(PropertyName propertyName); PropertyVTableItem registerProperty(std::string propertyName); struct InterfaceFlagsVTableItem diff --git a/include/sdbus-c++/VTableItems.inl b/include/sdbus-c++/VTableItems.inl index 0d2f3ac..b3f6044 100644 --- a/include/sdbus-c++/VTableItems.inl +++ b/include/sdbus-c++/VTableItems.inl @@ -125,11 +125,16 @@ namespace sdbus { return *this; } - inline MethodVTableItem registerMethod(std::string methodName) + inline MethodVTableItem registerMethod(MethodName methodName) { return {std::move(methodName), {}, {}, {}, {}, {}, {}}; } + inline MethodVTableItem registerMethod(std::string methodName) + { + return registerMethod(MethodName{std::move(methodName)}); + } + /*** -------------------- ***/ /*** Signal VTable Item ***/ /*** -------------------- ***/ @@ -166,11 +171,16 @@ namespace sdbus { return *this; } - inline SignalVTableItem registerSignal(std::string signalName) + inline SignalVTableItem registerSignal(SignalName signalName) { return {std::move(signalName), {}, {}, {}}; } + inline SignalVTableItem registerSignal(std::string signalName) + { + return registerSignal(SignalName{std::move(signalName)}); + } + /*** -------------------- ***/ /*** Property VTable Item ***/ /*** -------------------- ***/ @@ -239,11 +249,16 @@ namespace sdbus { return *this; } - inline PropertyVTableItem registerProperty(std::string propertyName) + inline PropertyVTableItem registerProperty(PropertyName propertyName) { return {std::move(propertyName), {}, {}, {}, {}}; } + inline PropertyVTableItem registerProperty(std::string propertyName) + { + return registerProperty(PropertyName{std::move(propertyName)}); + } + /*** --------------------------- ***/ /*** Interface Flags VTable Item ***/ /*** --------------------------- ***/ diff --git a/src/Connection.cpp b/src/Connection.cpp index 7187d8d..1353fbf 100644 --- a/src/Connection.cpp +++ b/src/Connection.cpp @@ -28,6 +28,7 @@ #include "sdbus-c++/Error.h" #include "sdbus-c++/Message.h" +#include "sdbus-c++/Types.h" #include "MessageUtils.h" #include "ScopeGuard.h" @@ -108,7 +109,7 @@ Connection::~Connection() Connection::leaveEventLoop(); } -void Connection::requestName(const std::string& name) +void Connection::requestName(const ServiceName& name) { SDBUS_CHECK_SERVICE_NAME(name); @@ -120,7 +121,7 @@ void Connection::requestName(const std::string& name) wakeUpEventLoopIfMessagesInQueue(); } -void Connection::releaseName(const std::string& name) +void Connection::releaseName(const ServiceName& name) { auto r = sdbus_->sd_bus_release_name(bus_.get(), name.c_str()); SDBUS_THROW_ERROR_IF(r < 0, "Failed to release bus name", -r); @@ -130,12 +131,12 @@ void Connection::releaseName(const std::string& name) wakeUpEventLoopIfMessagesInQueue(); } -std::string Connection::getUniqueName() const +BusName Connection::getUniqueName() const { - const char* unique = nullptr; - auto r = sdbus_->sd_bus_get_unique_name(bus_.get(), &unique); - SDBUS_THROW_ERROR_IF(r < 0 || unique == nullptr, "Failed to get unique bus name", -r); - return unique; + const char* name{}; + auto r = sdbus_->sd_bus_get_unique_name(bus_.get(), &name); + SDBUS_THROW_ERROR_IF(r < 0 || name == nullptr, "Failed to get unique bus name", -r); + return BusName{name}; } void Connection::enterEventLoop() @@ -188,14 +189,14 @@ ISdBus& Connection::getSdBusInterface() return *sdbus_.get(); } -void Connection::addObjectManager(const std::string& objectPath, floating_slot_t) +void Connection::addObjectManager(const ObjectPath& objectPath, floating_slot_t) { auto r = sdbus_->sd_bus_add_object_manager(bus_.get(), nullptr, objectPath.c_str()); SDBUS_THROW_ERROR_IF(r < 0, "Failed to add object manager", -r); } -Slot Connection::addObjectManager(const std::string& objectPath, return_slot_t) +Slot Connection::addObjectManager(const ObjectPath& objectPath, return_slot_t) { sd_bus_slot *slot{}; @@ -456,8 +457,8 @@ void Connection::deleteSdEventSource(sd_event_source *s) #endif // SDBUS_basu -Slot Connection::addObjectVTable( const std::string& objectPath - , const std::string& interfaceName +Slot Connection::addObjectVTable( const ObjectPath& objectPath + , const InterfaceName& interfaceName , const sd_bus_vtable* vtable , void* userData ) { @@ -486,10 +487,10 @@ PlainMessage Connection::createPlainMessage() const return Message::Factory::create(sdbusMsg, sdbus_.get(), adopt_message); } -MethodCall Connection::createMethodCall( const std::string& destination - , const std::string& objectPath - , const std::string& interfaceName - , const std::string& methodName ) const +MethodCall Connection::createMethodCall( const ServiceName& destination + , const ObjectPath& objectPath + , const InterfaceName& interfaceName + , const MethodName& methodName ) const { sd_bus_message *sdbusMsg{}; @@ -505,9 +506,9 @@ MethodCall Connection::createMethodCall( const std::string& destination return Message::Factory::create(sdbusMsg, sdbus_.get(), adopt_message); } -Signal Connection::createSignal( const std::string& objectPath - , const std::string& interfaceName - , const std::string& signalName ) const +Signal Connection::createSignal( const ObjectPath& objectPath + , const InterfaceName& interfaceName + , const SignalName& signalName ) const { sd_bus_message *sdbusMsg{}; @@ -562,9 +563,9 @@ Slot Connection::callMethod(const MethodCall& message, void* callback, void* use return slot; } -void Connection::emitPropertiesChangedSignal( const std::string& objectPath - , const std::string& interfaceName - , const std::vector& propNames ) +void Connection::emitPropertiesChangedSignal( const ObjectPath& objectPath + , const InterfaceName& interfaceName + , const std::vector& propNames ) { auto names = to_strv(propNames); @@ -576,15 +577,15 @@ void Connection::emitPropertiesChangedSignal( const std::string& objectPath SDBUS_THROW_ERROR_IF(r < 0, "Failed to emit PropertiesChanged signal", -r); } -void Connection::emitInterfacesAddedSignal(const std::string& objectPath) +void Connection::emitInterfacesAddedSignal(const ObjectPath& objectPath) { auto r = sdbus_->sd_bus_emit_object_added(bus_.get(), objectPath.c_str()); SDBUS_THROW_ERROR_IF(r < 0, "Failed to emit InterfacesAdded signal for all registered interfaces", -r); } -void Connection::emitInterfacesAddedSignal( const std::string& objectPath - , const std::vector& interfaces ) +void Connection::emitInterfacesAddedSignal( const ObjectPath& objectPath + , const std::vector& interfaces ) { auto names = to_strv(interfaces); @@ -595,15 +596,15 @@ void Connection::emitInterfacesAddedSignal( const std::string& objectPath SDBUS_THROW_ERROR_IF(r < 0, "Failed to emit InterfacesAdded signal", -r); } -void Connection::emitInterfacesRemovedSignal(const std::string& objectPath) +void Connection::emitInterfacesRemovedSignal(const ObjectPath& objectPath) { auto r = sdbus_->sd_bus_emit_object_removed(bus_.get(), objectPath.c_str()); SDBUS_THROW_ERROR_IF(r < 0, "Failed to emit InterfacesRemoved signal for all registered interfaces", -r); } -void Connection::emitInterfacesRemovedSignal( const std::string& objectPath - , const std::vector& interfaces ) +void Connection::emitInterfacesRemovedSignal( const ObjectPath& objectPath + , const std::vector& interfaces ) { auto names = to_strv(interfaces); @@ -614,10 +615,10 @@ void Connection::emitInterfacesRemovedSignal( const std::string& objectPath SDBUS_THROW_ERROR_IF(r < 0, "Failed to emit InterfacesRemoved signal", -r); } -Slot Connection::registerSignalHandler( const std::string& sender - , const std::string& objectPath - , const std::string& interfaceName - , const std::string& signalName +Slot Connection::registerSignalHandler( const ServiceName& sender + , const ObjectPath& objectPath + , const InterfaceName& interfaceName + , const SignalName& signalName , sd_bus_message_handler_t callback , void* userData ) { @@ -777,7 +778,8 @@ Message Connection::getCurrentlyProcessedMessage() const return Message::Factory::create(sdbusMsg, sdbus_.get()); } -std::vector Connection::to_strv(const std::vector& strings) +template +std::vector Connection::to_strv(const std::vector& strings) { std::vector strv; for (auto& str : strings) @@ -890,7 +892,7 @@ std::unique_ptr createBusConnection() return std::make_unique(std::move(interface), Connection::default_bus); } -std::unique_ptr createBusConnection(const std::string& name) +std::unique_ptr createBusConnection(const ServiceName& name) { auto conn = createBusConnection(); conn->requestName(name); @@ -903,7 +905,7 @@ std::unique_ptr createSystemBusConnection() return std::make_unique(std::move(interface), Connection::system_bus); } -std::unique_ptr createSystemBusConnection(const std::string& name) +std::unique_ptr createSystemBusConnection(const ServiceName& name) { auto conn = createSystemBusConnection(); conn->requestName(name); @@ -916,7 +918,7 @@ std::unique_ptr createSessionBusConnection() return std::make_unique(std::move(interface), Connection::session_bus); } -std::unique_ptr createSessionBusConnection(const std::string& name) +std::unique_ptr createSessionBusConnection(const ServiceName& name) { auto conn = createSessionBusConnection(); conn->requestName(name); diff --git a/src/Connection.h b/src/Connection.h index 269f74f..1f83f31 100644 --- a/src/Connection.h +++ b/src/Connection.h @@ -41,7 +41,18 @@ #include #include +// Forward declarations struct sd_event_source; +namespace sdbus { + class ObjectPath; + class InterfaceName; + class BusName; + using ServiceName = BusName; + class MemberName; + using MethodName = MemberName; + using SignalName = MemberName; + using PropertyName = MemberName; +} namespace sdbus::internal { @@ -81,9 +92,9 @@ namespace sdbus::internal { Connection(std::unique_ptr&& interface, pseudo_bus_t); ~Connection() override; - void requestName(const std::string& name) override; - void releaseName(const std::string& name) override; - [[nodiscard]] std::string getUniqueName() const override; + void requestName(const ServiceName & name) override; + void releaseName(const ServiceName& name) override; + [[nodiscard]] BusName getUniqueName() const override; void enterEventLoop() override; void enterEventLoopAsync() override; void leaveEventLoop() override; @@ -91,8 +102,8 @@ namespace sdbus::internal { bool processPendingEvent() override; Message getCurrentlyProcessedMessage() const override; - void addObjectManager(const std::string& objectPath, floating_slot_t) override; - Slot addObjectManager(const std::string& objectPath, return_slot_t) override; + void addObjectManager(const ObjectPath& objectPath, floating_slot_t) override; + Slot addObjectManager(const ObjectPath& objectPath, return_slot_t) override; void setMethodCallTimeout(uint64_t timeout) override; [[nodiscard]] uint64_t getMethodCallTimeout() const override; @@ -109,38 +120,38 @@ namespace sdbus::internal { [[nodiscard]] const ISdBus& getSdBusInterface() const override; [[nodiscard]] ISdBus& getSdBusInterface() override; - Slot addObjectVTable( const std::string& objectPath - , const std::string& interfaceName + Slot addObjectVTable( const ObjectPath& objectPath + , const InterfaceName& interfaceName , const sd_bus_vtable* vtable , void* userData ) override; [[nodiscard]] PlainMessage createPlainMessage() const override; - [[nodiscard]] MethodCall createMethodCall( const std::string& destination - , const std::string& objectPath - , const std::string& interfaceName - , const std::string& methodName ) const override; - [[nodiscard]] Signal createSignal( const std::string& objectPath - , const std::string& interfaceName - , const std::string& signalName ) const override; + [[nodiscard]] MethodCall createMethodCall( const ServiceName& destination + , const ObjectPath& objectPath + , const InterfaceName& interfaceName + , const MethodName& methodName ) const override; + [[nodiscard]] Signal createSignal( const ObjectPath& objectPath + , const InterfaceName& interfaceName + , const SignalName& signalName ) const override; MethodReply callMethod(const MethodCall& message, uint64_t timeout) override; void callMethod(const MethodCall& message, void* callback, void* userData, uint64_t timeout, floating_slot_t) override; Slot callMethod(const MethodCall& message, void* callback, void* userData, uint64_t timeout) override; - void emitPropertiesChangedSignal( const std::string& objectPath - , const std::string& interfaceName - , const std::vector& propNames ) override; - void emitInterfacesAddedSignal(const std::string& objectPath) override; - void emitInterfacesAddedSignal( const std::string& objectPath - , const std::vector& interfaces ) override; - void emitInterfacesRemovedSignal(const std::string& objectPath) override; - void emitInterfacesRemovedSignal( const std::string& objectPath - , const std::vector& interfaces ) override; + void emitPropertiesChangedSignal( const ObjectPath& objectPath + , const InterfaceName& interfaceName + , const std::vector& propNames ) override; + void emitInterfacesAddedSignal(const ObjectPath& objectPath) override; + void emitInterfacesAddedSignal( const ObjectPath& objectPath + , const std::vector& interfaces ) override; + void emitInterfacesRemovedSignal(const ObjectPath& objectPath) override; + void emitInterfacesRemovedSignal( const ObjectPath& objectPath + , const std::vector& interfaces ) override; - Slot registerSignalHandler( const std::string& sender - , const std::string& objectPath - , const std::string& interfaceName - , const std::string& signalName + Slot registerSignalHandler( const ServiceName& sender + , const ObjectPath& objectPath + , const InterfaceName& interfaceName + , const SignalName& signalName , sd_bus_message_handler_t callback , void* userData ) override; @@ -161,7 +172,8 @@ namespace sdbus::internal { void wakeUpEventLoopIfMessagesInQueue(); void joinWithEventLoop(); - static std::vector to_strv(const std::vector& strings); + template + static std::vector to_strv(const std::vector& strings); static int sdbus_match_callback(sd_bus_message *sdbusMessage, void *userData, sd_bus_error *retError); static int sdbus_match_install_callback(sd_bus_message *sdbusMessage, void *userData, sd_bus_error *retError); diff --git a/src/Error.cpp b/src/Error.cpp index d4adfeb..a93e956 100644 --- a/src/Error.cpp +++ b/src/Error.cpp @@ -32,14 +32,18 @@ namespace sdbus { - sdbus::Error createError(int errNo, const std::string& customMsg) + sdbus::Error createError(int errNo, std::string customMsg) { sd_bus_error sdbusError = SD_BUS_ERROR_NULL; sd_bus_error_set_errno(&sdbusError, errNo); SCOPE_EXIT{ sd_bus_error_free(&sdbusError); }; - std::string name(sdbusError.name); - std::string message(customMsg + " (" + sdbusError.message + ")"); - return sdbus::Error(name, message); + Error::Name name(sdbusError.name); + std::string message(std::move(customMsg)); + message.append(" ("); + message.append(sdbusError.message); + message.append(")"); + + return Error(std::move(name), std::move(message)); } } // namespace sdbus diff --git a/src/IConnection.h b/src/IConnection.h index d152448..dc1b189 100644 --- a/src/IConnection.h +++ b/src/IConnection.h @@ -37,12 +37,20 @@ #include SDBUS_HEADER #include -// Forward declaration +// Forward declarations namespace sdbus { class MethodCall; class MethodReply; class Signal; class PlainMessage; + class ObjectPath; + class InterfaceName; + class BusName; + using ServiceName = BusName; + class MemberName; + using MethodName = MemberName; + using SignalName = MemberName; + using PropertyName = MemberName; namespace internal { class ISdBus; } @@ -59,41 +67,41 @@ namespace sdbus::internal { [[nodiscard]] virtual const ISdBus& getSdBusInterface() const = 0; [[nodiscard]] virtual ISdBus& getSdBusInterface() = 0; - [[nodiscard]] virtual Slot addObjectVTable( const std::string& objectPath - , const std::string& interfaceName + [[nodiscard]] virtual Slot addObjectVTable( const ObjectPath& objectPath + , const InterfaceName& interfaceName , const sd_bus_vtable* vtable , void* userData ) = 0; [[nodiscard]] virtual PlainMessage createPlainMessage() const = 0; - [[nodiscard]] virtual MethodCall createMethodCall( const std::string& destination - , const std::string& objectPath - , const std::string& interfaceName - , const std::string& methodName ) const = 0; - [[nodiscard]] virtual Signal createSignal( const std::string& objectPath - , const std::string& interfaceName - , const std::string& signalName ) const = 0; + [[nodiscard]] virtual MethodCall createMethodCall( const ServiceName& destination + , const ObjectPath& objectPath + , const InterfaceName& interfaceName + , const MethodName& methodName ) const = 0; + [[nodiscard]] virtual Signal createSignal( const ObjectPath& objectPath + , const InterfaceName& interfaceName + , const SignalName& signalName ) const = 0; virtual MethodReply callMethod(const MethodCall& message, uint64_t timeout) = 0; virtual void callMethod(const MethodCall& message, void* callback, void* userData, uint64_t timeout, floating_slot_t) = 0; [[nodiscard]] virtual Slot callMethod(const MethodCall& message, void* callback, void* userData, uint64_t timeout) = 0; - virtual void emitPropertiesChangedSignal( const std::string& objectPath - , const std::string& interfaceName - , const std::vector& propNames ) = 0; - virtual void emitInterfacesAddedSignal(const std::string& objectPath) = 0; - virtual void emitInterfacesAddedSignal( const std::string& objectPath - , const std::vector& interfaces ) = 0; - virtual void emitInterfacesRemovedSignal(const std::string& objectPath) = 0; - virtual void emitInterfacesRemovedSignal( const std::string& objectPath - , const std::vector& interfaces ) = 0; + virtual void emitPropertiesChangedSignal( const ObjectPath& objectPath + , const InterfaceName& interfaceName + , const std::vector& propNames ) = 0; + virtual void emitInterfacesAddedSignal(const ObjectPath& objectPath) = 0; + virtual void emitInterfacesAddedSignal( const ObjectPath& objectPath + , const std::vector& interfaces ) = 0; + virtual void emitInterfacesRemovedSignal(const ObjectPath& objectPath) = 0; + virtual void emitInterfacesRemovedSignal( const ObjectPath& objectPath + , const std::vector& interfaces ) = 0; using sdbus::IConnection::addObjectManager; - [[nodiscard]] virtual Slot addObjectManager(const std::string& objectPath, return_slot_t) = 0; + [[nodiscard]] virtual Slot addObjectManager(const ObjectPath& objectPath, return_slot_t) = 0; - [[nodiscard]] virtual Slot registerSignalHandler( const std::string& sender - , const std::string& objectPath - , const std::string& interfaceName - , const std::string& signalName + [[nodiscard]] virtual Slot registerSignalHandler( const ServiceName& sender + , const ObjectPath& objectPath + , const InterfaceName& interfaceName + , const SignalName& signalName , sd_bus_message_handler_t callback , void* userData ) = 0; }; diff --git a/src/Message.cpp b/src/Message.cpp index 2222726..ae281e2 100644 --- a/src/Message.cpp +++ b/src/Message.cpp @@ -602,33 +602,34 @@ void Message::rewind(bool complete) SDBUS_THROW_ERROR_IF(r < 0, "Failed to rewind the message", -r); } -std::string Message::getInterfaceName() const +InterfaceName Message::getInterfaceName() const { - auto interface = sd_bus_message_get_interface((sd_bus_message*)msg_); - return interface != nullptr ? interface : ""; + const auto* interface = sd_bus_message_get_interface((sd_bus_message*)msg_); + return interface != nullptr ? InterfaceName{interface} : InterfaceName{}; } -std::string Message::getMemberName() const +MemberName Message::getMemberName() const { - auto member = sd_bus_message_get_member((sd_bus_message*)msg_); - return member != nullptr ? member : ""; + const auto* member = sd_bus_message_get_member((sd_bus_message*)msg_); + return member != nullptr ? MemberName{member} : MemberName{}; } -std::string Message::getSender() const +ConnectionName Message::getSender() const { - return sd_bus_message_get_sender((sd_bus_message*)msg_); + const auto* sender = sd_bus_message_get_sender((sd_bus_message*)msg_); + return ConnectionName{sender}; } -std::string Message::getPath() const +ObjectPath Message::getPath() const { - auto path = sd_bus_message_get_path((sd_bus_message*)msg_); - return path != nullptr ? path : ""; + const auto* path = sd_bus_message_get_path((sd_bus_message*)msg_); + return path != nullptr ? ObjectPath{path} : ObjectPath{}; } -std::string Message::getDestination() const +ConnectionName Message::getDestination() const { - auto destination = sd_bus_message_get_destination((sd_bus_message*)msg_); - return destination != nullptr ? destination : ""; + const auto* destination = sd_bus_message_get_destination((sd_bus_message*)msg_); + return destination != nullptr ? ConnectionName{destination} : ConnectionName{}; } void Message::peekType(std::string& type, std::string& contents) const @@ -801,7 +802,7 @@ MethodReply MethodCall::sendWithReply(uint64_t timeout) const auto r = sdbus_->sd_bus_call(nullptr, (sd_bus_message*)msg_, timeout, &sdbusError, &sdbusReply); if (sd_bus_error_is_set(&sdbusError)) - throw sdbus::Error(sdbusError.name, sdbusError.message); + throw Error(Error::Name{sdbusError.name}, sdbusError.message); SDBUS_THROW_ERROR_IF(r < 0, "Failed to call method", -r); @@ -866,7 +867,7 @@ void Signal::send() const SDBUS_THROW_ERROR_IF(r < 0, "Failed to emit signal", -r); } -void Signal::setDestination(const std::string& destination) +void Signal::setDestination(const ConnectionName& destination) { auto r = sdbus_->sd_bus_message_set_destination((sd_bus_message*)msg_, destination.c_str()); SDBUS_THROW_ERROR_IF(r < 0, "Failed to set signal destination", -r); diff --git a/src/Object.cpp b/src/Object.cpp index 6305f92..fa90db7 100644 --- a/src/Object.cpp +++ b/src/Object.cpp @@ -43,20 +43,20 @@ namespace sdbus::internal { -Object::Object(sdbus::internal::IConnection& connection, std::string objectPath) +Object::Object(sdbus::internal::IConnection& connection, ObjectPath objectPath) : connection_(connection), objectPath_(std::move(objectPath)) { SDBUS_CHECK_OBJECT_PATH(objectPath_); } -void Object::addVTable(std::string interfaceName, std::vector vtable) +void Object::addVTable(InterfaceName interfaceName, std::vector vtable) { auto slot = Object::addVTable(std::move(interfaceName), std::move(vtable), return_slot); vtables_.push_back(std::move(slot)); } -Slot Object::addVTable(std::string interfaceName, std::vector vtable, return_slot_t) +Slot Object::addVTable(InterfaceName interfaceName, std::vector vtable, return_slot_t) { SDBUS_CHECK_INTERFACE_NAME(interfaceName); @@ -79,7 +79,7 @@ void Object::unregister() removeObjectManager(); } -sdbus::Signal Object::createSignal(const std::string& interfaceName, const std::string& signalName) +sdbus::Signal Object::createSignal(const InterfaceName& interfaceName, const SignalName& signalName) { return connection_.createSignal(objectPath_, interfaceName, signalName); } @@ -91,12 +91,12 @@ void Object::emitSignal(const sdbus::Signal& message) message.send(); } -void Object::emitPropertiesChangedSignal(const std::string& interfaceName, const std::vector& propNames) +void Object::emitPropertiesChangedSignal(const InterfaceName& interfaceName, const std::vector& propNames) { connection_.emitPropertiesChangedSignal(objectPath_, interfaceName, propNames); } -void Object::emitPropertiesChangedSignal(const std::string& interfaceName) +void Object::emitPropertiesChangedSignal(const InterfaceName& interfaceName) { Object::emitPropertiesChangedSignal(interfaceName, {}); } @@ -106,7 +106,7 @@ void Object::emitInterfacesAddedSignal() connection_.emitInterfacesAddedSignal(objectPath_); } -void Object::emitInterfacesAddedSignal(const std::vector& interfaces) +void Object::emitInterfacesAddedSignal(const std::vector& interfaces) { connection_.emitInterfacesAddedSignal(objectPath_, interfaces); } @@ -116,7 +116,7 @@ void Object::emitInterfacesRemovedSignal() connection_.emitInterfacesRemovedSignal(objectPath_); } -void Object::emitInterfacesRemovedSignal(const std::vector& interfaces) +void Object::emitInterfacesRemovedSignal(const std::vector& interfaces) { connection_.emitInterfacesRemovedSignal(objectPath_, interfaces); } @@ -141,7 +141,7 @@ sdbus::IConnection& Object::getConnection() const return connection_; } -const std::string& Object::getObjectPath() const +const ObjectPath& Object::getObjectPath() const { return objectPath_; } @@ -151,7 +151,7 @@ Message Object::getCurrentlyProcessedMessage() const return connection_.getCurrentlyProcessedMessage(); } -Object::VTable Object::createInternalVTable(std::string interfaceName, std::vector vtable) +Object::VTable Object::createInternalVTable(InterfaceName interfaceName, std::vector vtable) { VTable internalVTable; @@ -241,8 +241,8 @@ void Object::startSdBusVTable(const Flags& interfaceFlags, std::vector& vtable) { auto vtableItem = createSdBusVTableMethodItem( method.name.c_str() - , method.inputArgs.c_str() - , method.outputArgs.c_str() + , method.inputSignature.c_str() + , method.outputSignature.c_str() , method.paramNames.c_str() , &Object::sdbus_method_callback , method.flags.toSdBusMethodFlags() ); @@ -278,23 +278,27 @@ void Object::finalizeSdBusVTable(std::vector& vtable) vtable.push_back(createSdBusVTableEndItem()); } -const Object::VTable::MethodItem* Object::findMethod(const VTable& vtable, const std::string& methodName) +const Object::VTable::MethodItem* Object::findMethod(const VTable& vtable, std::string_view methodName) { auto it = std::lower_bound(vtable.methods.begin(), vtable.methods.end(), methodName, [](const auto& methodItem, const auto& methodName) { return methodItem.name < methodName; }); + (void)it; + return it != vtable.methods.end() && it->name == methodName ? &*it : nullptr; } -const Object::VTable::PropertyItem* Object::findProperty(const VTable& vtable, const std::string& propertyName) +const Object::VTable::PropertyItem* Object::findProperty(const VTable& vtable, std::string_view propertyName) { auto it = std::lower_bound(vtable.properties.begin(), vtable.properties.end(), propertyName, [](const auto& propertyItem, const auto& propertyName) { return propertyItem.name < propertyName; }); + (void)it; + return it != vtable.properties.end() && it->name == propertyName ? &*it : nullptr; } @@ -314,7 +318,7 @@ int Object::sdbus_method_callback(sd_bus_message *sdbusMessage, void *userData, auto message = Message::Factory::create(sdbusMessage, &vtable->object->connection_.getSdBusInterface()); - const auto* methodItem = findMethod(*vtable, message.getMemberName()); + const auto* methodItem = findMethod(*vtable, message.getMemberName()); // TODO: optimize the situation around getMemberName() assert(methodItem != nullptr); assert(methodItem->callback); @@ -379,7 +383,7 @@ int Object::sdbus_property_set_callback( sd_bus */*bus*/ namespace sdbus { -std::unique_ptr createObject(sdbus::IConnection& connection, std::string objectPath) +std::unique_ptr createObject(sdbus::IConnection& connection, ObjectPath objectPath) { auto* sdbusConnection = dynamic_cast(&connection); SDBUS_THROW_ERROR_IF(!sdbusConnection, "Connection is not a real sdbus-c++ connection", EINVAL); diff --git a/src/Object.h b/src/Object.h index 07dfd16..f69fbb4 100644 --- a/src/Object.h +++ b/src/Object.h @@ -30,12 +30,14 @@ #include "sdbus-c++/IObject.h" #include "IConnection.h" +#include "sdbus-c++/Types.h" #include #include #include #include #include +#include #include SDBUS_HEADER #include @@ -45,27 +47,27 @@ namespace sdbus::internal { : public IObject { public: - Object(sdbus::internal::IConnection& connection, std::string objectPath); + Object(sdbus::internal::IConnection& connection, ObjectPath objectPath); - void addVTable(std::string interfaceName, std::vector vtable) override; - Slot addVTable(std::string interfaceName, std::vector vtable, return_slot_t) override; + void addVTable(InterfaceName interfaceName, std::vector vtable) override; + Slot addVTable(InterfaceName interfaceName, std::vector vtable, return_slot_t) override; void unregister() override; - sdbus::Signal createSignal(const std::string& interfaceName, const std::string& signalName) override; + sdbus::Signal createSignal(const InterfaceName& interfaceName, const SignalName& signalName) override; void emitSignal(const sdbus::Signal& message) override; - void emitPropertiesChangedSignal(const std::string& interfaceName, const std::vector& propNames) override; - void emitPropertiesChangedSignal(const std::string& interfaceName) override; + void emitPropertiesChangedSignal(const InterfaceName& interfaceName, const std::vector& propNames) override; + void emitPropertiesChangedSignal(const InterfaceName& interfaceName) override; void emitInterfacesAddedSignal() override; - void emitInterfacesAddedSignal(const std::vector& interfaces) override; + void emitInterfacesAddedSignal(const std::vector& interfaces) override; void emitInterfacesRemovedSignal() override; - void emitInterfacesRemovedSignal(const std::vector& interfaces) override; + void emitInterfacesRemovedSignal(const std::vector& interfaces) override; void addObjectManager() override; void removeObjectManager() override; [[nodiscard]] bool hasObjectManager() const override; [[nodiscard]] sdbus::IConnection& getConnection() const override; - [[nodiscard]] const std::string& getObjectPath() const override; + [[nodiscard]] const ObjectPath& getObjectPath() const override; [[nodiscard]] Message getCurrentlyProcessedMessage() const override; private: @@ -74,14 +76,14 @@ namespace sdbus::internal { // An interface can have any number of vtables attached to it, not only one. struct VTable { - std::string interfaceName; + InterfaceName interfaceName; Flags interfaceFlags; struct MethodItem { - std::string name; - std::string inputArgs; - std::string outputArgs; + MethodName name; + Signature inputSignature; + Signature outputSignature; std::string paramNames; method_callback callback; Flags flags; @@ -91,8 +93,8 @@ namespace sdbus::internal { struct SignalItem { - std::string name; - std::string signature; + SignalName name; + Signature signature; std::string paramNames; Flags flags; }; @@ -101,8 +103,8 @@ namespace sdbus::internal { struct PropertyItem { - std::string name; - std::string signature; + PropertyName name; + Signature signature; property_get_callback getCallback; property_set_callback setCallback; Flags flags; @@ -121,7 +123,7 @@ namespace sdbus::internal { Slot slot; }; - VTable createInternalVTable(std::string interfaceName, std::vector vtable); + VTable createInternalVTable(InterfaceName interfaceName, std::vector vtable); void writeInterfaceFlagsToVTable(InterfaceFlagsVTableItem flags, VTable& vtable); void writeMethodRecordToVTable(MethodVTableItem method, VTable& vtable); void writeSignalRecordToVTable(SignalVTableItem signal, VTable& vtable); @@ -134,8 +136,8 @@ namespace sdbus::internal { static void writePropertyRecordToSdBusVTable(const VTable::PropertyItem& property, std::vector& vtable); static void finalizeSdBusVTable(std::vector& vtable); - static const VTable::MethodItem* findMethod(const VTable& vtable, const std::string& methodName); - static const VTable::PropertyItem* findProperty(const VTable& vtable, const std::string& propertyName); + static const VTable::MethodItem* findMethod(const VTable& vtable, std::string_view methodName); + static const VTable::PropertyItem* findProperty(const VTable& vtable, std::string_view propertyName); static std::string paramNamesToString(const std::vector& paramNames); @@ -157,7 +159,7 @@ namespace sdbus::internal { private: sdbus::internal::IConnection& connection_; - std::string objectPath_; + ObjectPath objectPath_; std::vector vtables_; Slot objectManagerSlot_; }; diff --git a/src/Proxy.cpp b/src/Proxy.cpp index f087447..a55c865 100644 --- a/src/Proxy.cpp +++ b/src/Proxy.cpp @@ -41,7 +41,7 @@ namespace sdbus::internal { -Proxy::Proxy(sdbus::internal::IConnection& connection, std::string destination, std::string objectPath) +Proxy::Proxy(sdbus::internal::IConnection& connection, ServiceName destination, ObjectPath objectPath) : connection_(&connection, [](sdbus::internal::IConnection *){ /* Intentionally left empty */ }) , destination_(std::move(destination)) , objectPath_(std::move(objectPath)) @@ -54,8 +54,8 @@ Proxy::Proxy(sdbus::internal::IConnection& connection, std::string destination, } Proxy::Proxy( std::unique_ptr&& connection - , std::string destination - , std::string objectPath ) + , ServiceName destination + , ObjectPath objectPath ) : connection_(std::move(connection)) , destination_(std::move(destination)) , objectPath_(std::move(objectPath)) @@ -69,8 +69,8 @@ Proxy::Proxy( std::unique_ptr&& connection } Proxy::Proxy( std::unique_ptr&& connection - , std::string destination - , std::string objectPath + , ServiceName destination + , ObjectPath objectPath , dont_run_event_loop_thread_t ) : connection_(std::move(connection)) , destination_(std::move(destination)) @@ -83,7 +83,7 @@ Proxy::Proxy( std::unique_ptr&& connection // This proxy is meant to be created, used for simple synchronous D-Bus call(s) and then dismissed. } -MethodCall Proxy::createMethodCall(const std::string& interfaceName, const std::string& methodName) +MethodCall Proxy::createMethodCall(const InterfaceName& interfaceName, const MethodName& methodName) { return connection_->createMethodCall(destination_, objectPath_, interfaceName, methodName); } @@ -134,8 +134,8 @@ std::future Proxy::callMethodAsync(const MethodCall& message, uint6 return future; } -void Proxy::registerSignalHandler( const std::string& interfaceName - , const std::string& signalName +void Proxy::registerSignalHandler( const InterfaceName& interfaceName + , const SignalName& signalName , signal_handler signalHandler ) { auto slot = Proxy::registerSignalHandler(interfaceName, signalName, std::move(signalHandler), return_slot); @@ -143,8 +143,8 @@ void Proxy::registerSignalHandler( const std::string& interfaceName floatingSignalSlots_.push_back(std::move(slot)); } -Slot Proxy::registerSignalHandler( const std::string& interfaceName - , const std::string& signalName +Slot Proxy::registerSignalHandler( const InterfaceName& interfaceName + , const SignalName& signalName , signal_handler signalHandler , return_slot_t ) { @@ -175,7 +175,7 @@ sdbus::IConnection& Proxy::getConnection() const return *connection_; } -const std::string& Proxy::getObjectPath() const +const ObjectPath& Proxy::getObjectPath() const { return objectPath_; } @@ -211,7 +211,7 @@ int Proxy::sdbus_async_reply_handler(sd_bus_message *sdbusMessage, void *userDat } else { - Error exception(error->name, error->message); + Error exception(Error::Name{error->name}, error->message); asyncCallData->callback(std::move(message), std::move(exception)); } }, retError); @@ -266,8 +266,8 @@ bool PendingAsyncCall::isPending() const namespace sdbus { std::unique_ptr createProxy( IConnection& connection - , std::string destination - , std::string objectPath ) + , ServiceName destination + , ObjectPath objectPath ) { auto* sdbusConnection = dynamic_cast(&connection); SDBUS_THROW_ERROR_IF(!sdbusConnection, "Connection is not a real sdbus-c++ connection", EINVAL); @@ -278,8 +278,8 @@ std::unique_ptr createProxy( IConnection& connection } std::unique_ptr createProxy( std::unique_ptr&& connection - , std::string destination - , std::string objectPath ) + , ServiceName destination + , ObjectPath objectPath ) { auto* sdbusConnection = dynamic_cast(connection.get()); SDBUS_THROW_ERROR_IF(!sdbusConnection, "Connection is not a real sdbus-c++ connection", EINVAL); @@ -292,8 +292,8 @@ std::unique_ptr createProxy( std::unique_ptr&& conne } std::unique_ptr createProxy( std::unique_ptr&& connection - , std::string destination - , std::string objectPath + , ServiceName destination + , ObjectPath objectPath , dont_run_event_loop_thread_t ) { auto* sdbusConnection = dynamic_cast(connection.get()); @@ -307,8 +307,8 @@ std::unique_ptr createProxy( std::unique_ptr&& conne , dont_run_event_loop_thread ); } -std::unique_ptr createProxy( std::string destination - , std::string objectPath ) +std::unique_ptr createProxy( ServiceName destination + , ObjectPath objectPath ) { auto connection = sdbus::createBusConnection(); @@ -320,8 +320,8 @@ std::unique_ptr createProxy( std::string destination , std::move(objectPath) ); } -std::unique_ptr createProxy( std::string destination - , std::string objectPath +std::unique_ptr createProxy( ServiceName destination + , ObjectPath objectPath , dont_run_event_loop_thread_t ) { auto connection = sdbus::createBusConnection(); diff --git a/src/Proxy.h b/src/Proxy.h index 714ef75..d2d606e 100644 --- a/src/Proxy.h +++ b/src/Proxy.h @@ -30,6 +30,7 @@ #include "sdbus-c++/IProxy.h" #include "IConnection.h" +#include "sdbus-c++/Types.h" #include #include @@ -45,33 +46,33 @@ namespace sdbus::internal { { public: Proxy( sdbus::internal::IConnection& connection - , std::string destination - , std::string objectPath ); + , ServiceName destination + , ObjectPath objectPath ); Proxy( std::unique_ptr&& connection - , std::string destination - , std::string objectPath ); + , ServiceName destination + , ObjectPath objectPath ); Proxy( std::unique_ptr&& connection - , std::string destination - , std::string objectPath + , ServiceName destination + , ObjectPath objectPath , dont_run_event_loop_thread_t ); - MethodCall createMethodCall(const std::string& interfaceName, const std::string& methodName) override; + MethodCall createMethodCall(const InterfaceName& interfaceName, const MethodName& methodName) override; MethodReply callMethod(const MethodCall& message, uint64_t timeout) override; PendingAsyncCall callMethodAsync(const MethodCall& message, async_reply_handler asyncReplyCallback, uint64_t timeout) override; std::future callMethodAsync(const MethodCall& message, with_future_t) override; std::future callMethodAsync(const MethodCall& message, uint64_t timeout, with_future_t) override; - void registerSignalHandler( const std::string& interfaceName - , const std::string& signalName + void registerSignalHandler( const InterfaceName& interfaceName + , const SignalName& signalName , signal_handler signalHandler ) override; - Slot registerSignalHandler( const std::string& interfaceName - , const std::string& signalName + Slot registerSignalHandler( const InterfaceName& interfaceName + , const SignalName& signalName , signal_handler signalHandler , return_slot_t ) override; void unregister() override; [[nodiscard]] sdbus::IConnection& getConnection() const override; - [[nodiscard]] const std::string& getObjectPath() const override; + [[nodiscard]] const ObjectPath& getObjectPath() const override; [[nodiscard]] Message getCurrentlyProcessedMessage() const override; private: @@ -84,8 +85,8 @@ namespace sdbus::internal { std::unique_ptr< sdbus::internal::IConnection , std::function > connection_; - std::string destination_; - std::string objectPath_; + ServiceName destination_; + ObjectPath objectPath_; std::vector floatingSignalSlots_; diff --git a/src/Utils.h b/src/Utils.h index e50667b..3c08e0b 100644 --- a/src/Utils.h +++ b/src/Utils.h @@ -41,7 +41,7 @@ SDBUS_THROW_ERROR_IF(!_NAME.empty() && !sd_bus_service_name_is_valid(_NAME.c_str()), "Invalid service name '" + _NAME + "' provided", EINVAL) \ /**/ #define SDBUS_CHECK_MEMBER_NAME(_NAME) \ - SDBUS_THROW_ERROR_IF(!sd_bus_member_name_is_valid(_NAME.c_str()), "Invalid member name '" + _NAME + "' provided", EINVAL) \ + SDBUS_THROW_ERROR_IF(!sd_bus_member_name_is_valid(_NAME.c_str()), std::string("Invalid member name '") + _NAME.c_str() + "' provided", EINVAL) \ /**/ #else #define SDBUS_CHECK_OBJECT_PATH(_PATH) @@ -66,12 +66,12 @@ namespace sdbus::internal { } catch (const std::exception& e) { - sd_bus_error_set(retError, SDBUSCPP_ERROR_NAME, e.what()); + sd_bus_error_set(retError, SDBUSCPP_ERROR_NAME.c_str(), e.what()); return false; } catch (...) { - sd_bus_error_set(retError, SDBUSCPP_ERROR_NAME, "Unknown error occurred"); + sd_bus_error_set(retError, SDBUSCPP_ERROR_NAME.c_str(), "Unknown error occurred"); return false; } diff --git a/tests/integrationtests/DBusAsyncMethodsTests.cpp b/tests/integrationtests/DBusAsyncMethodsTests.cpp index c13bfcc..c868649 100644 --- a/tests/integrationtests/DBusAsyncMethodsTests.cpp +++ b/tests/integrationtests/DBusAsyncMethodsTests.cpp @@ -96,7 +96,7 @@ TYPED_TEST(AsyncSdbusTestObject, RunsServerSideAsynchoronousMethodAsynchronously std::atomic startedCount{}; auto call = [&](uint32_t param) { - TestProxy proxy{BUS_NAME, OBJECT_PATH}; + TestProxy proxy{SERVICE_NAME, OBJECT_PATH}; ++startedCount; while (!invoke) ; auto result = proxy.doOperationAsync(param); @@ -119,7 +119,7 @@ TYPED_TEST(AsyncSdbusTestObject, HandlesCorrectlyABulkOfParallelServerSideAsyncM std::atomic startedCount{}; auto call = [&]() { - TestProxy proxy{BUS_NAME, OBJECT_PATH}; + TestProxy proxy{SERVICE_NAME, OBJECT_PATH}; ++startedCount; while (!invoke) ; diff --git a/tests/integrationtests/DBusConnectionTests.cpp b/tests/integrationtests/DBusConnectionTests.cpp index 855ab5e..0093e70 100644 --- a/tests/integrationtests/DBusConnectionTests.cpp +++ b/tests/integrationtests/DBusConnectionTests.cpp @@ -51,38 +51,43 @@ TEST(Connection, CanBeDefaultConstructed) ASSERT_NO_THROW(auto con = sdbus::createBusConnection()); } -TEST(SystemBusConnection, CanRequestRegisteredDbusName) +TEST(Connection, CanRequestName) { - auto connection = sdbus::createSystemBusConnection(); + auto connection = sdbus::createBusConnection(); - ASSERT_NO_THROW(connection->requestName(BUS_NAME)) + // In case of system bus connection, requesting may throw as we need to allow that first through a config file in /etc/dbus-1/system.d + ASSERT_NO_THROW(connection->requestName(SERVICE_NAME)) << "Perhaps you've forgotten to copy `org.sdbuscpp.integrationtests.conf` file to `/etc/dbus-1/system.d` directory before running the tests?"; } TEST(SystemBusConnection, CannotRequestNonregisteredDbusName) { auto connection = sdbus::createSystemBusConnection(); - ASSERT_THROW(connection->requestName("some.random.not.supported.dbus.name"), sdbus::Error); + sdbus::ServiceName notSupportedBusName{"some.random.not.supported.dbus.name"}; + + ASSERT_THROW(connection->requestName(notSupportedBusName), sdbus::Error); } -TEST(Connection, CanReleasedRequestedName) +TEST(Connection, CanReleaseRequestedName) { auto connection = sdbus::createBusConnection(); + connection->requestName(SERVICE_NAME); - connection->requestName(BUS_NAME); - ASSERT_NO_THROW(connection->releaseName(BUS_NAME)); + ASSERT_NO_THROW(connection->releaseName(SERVICE_NAME)); } TEST(Connection, CannotReleaseNonrequestedName) { auto connection = sdbus::createBusConnection(); - ASSERT_THROW(connection->releaseName("some.random.nonrequested.name"), sdbus::Error); + sdbus::ServiceName notAcquiredBusName{"some.random.unacquired.name"}; + + ASSERT_THROW(connection->releaseName(notAcquiredBusName), sdbus::Error); } TEST(Connection, CanEnterAndLeaveInternalEventLoop) { auto connection = sdbus::createBusConnection(); - connection->requestName(BUS_NAME); + connection->requestName(SERVICE_NAME); std::thread t([&](){ connection->enterEventLoop(); }); connection->leaveEventLoop(); diff --git a/tests/integrationtests/DBusGeneralTests.cpp b/tests/integrationtests/DBusGeneralTests.cpp index 1164f6c..7f9dae0 100644 --- a/tests/integrationtests/DBusGeneralTests.cpp +++ b/tests/integrationtests/DBusGeneralTests.cpp @@ -54,12 +54,12 @@ using ADirectConnection = TestFixtureWithDirectConnection; TEST(AdaptorAndProxy, CanBeConstructedSuccesfully) { auto connection = sdbus::createBusConnection(); - connection->requestName(BUS_NAME); + connection->requestName(SERVICE_NAME); ASSERT_NO_THROW(TestAdaptor adaptor(*connection, OBJECT_PATH)); - ASSERT_NO_THROW(TestProxy proxy(BUS_NAME, OBJECT_PATH)); + ASSERT_NO_THROW(TestProxy proxy(SERVICE_NAME, OBJECT_PATH)); - connection->releaseName(BUS_NAME); + connection->releaseName(SERVICE_NAME); } TEST(AProxy, SupportsMoveSemantics) @@ -76,7 +76,7 @@ TEST(AnAdaptor, SupportsMoveSemantics) TYPED_TEST(AConnection, WillCallCallbackHandlerForIncomingMessageMatchingMatchRule) { - auto matchRule = "sender='" + BUS_NAME + "',path='" + OBJECT_PATH + "'"; + auto matchRule = "sender='" + SERVICE_NAME + "',path='" + OBJECT_PATH + "'"; std::atomic matchingMessageReceived{false}; auto slot = this->s_proxyConnection->addMatch(matchRule, [&](sdbus::Message msg) { @@ -91,7 +91,7 @@ TYPED_TEST(AConnection, WillCallCallbackHandlerForIncomingMessageMatchingMatchRu TYPED_TEST(AConnection, CanInstallMatchRuleAsynchronously) { - auto matchRule = "sender='" + BUS_NAME + "',path='" + OBJECT_PATH + "'"; + auto matchRule = "sender='" + SERVICE_NAME + "',path='" + OBJECT_PATH + "'"; std::atomic matchingMessageReceived{false}; std::atomic matchRuleInstalled{false}; auto slot = this->s_proxyConnection->addMatchAsync( matchRule @@ -114,7 +114,7 @@ TYPED_TEST(AConnection, CanInstallMatchRuleAsynchronously) TYPED_TEST(AConnection, WillUnsubscribeMatchRuleWhenClientDestroysTheAssociatedSlot) { - auto matchRule = "sender='" + BUS_NAME + "',path='" + OBJECT_PATH + "'"; + auto matchRule = "sender='" + SERVICE_NAME + "',path='" + OBJECT_PATH + "'"; std::atomic matchingMessageReceived{false}; auto slot = this->s_proxyConnection->addMatch(matchRule, [&](sdbus::Message msg) { @@ -130,7 +130,7 @@ TYPED_TEST(AConnection, WillUnsubscribeMatchRuleWhenClientDestroysTheAssociatedS TYPED_TEST(AConnection, CanAddFloatingMatchRule) { - auto matchRule = "sender='" + BUS_NAME + "',path='" + OBJECT_PATH + "'"; + auto matchRule = "sender='" + SERVICE_NAME + "',path='" + OBJECT_PATH + "'"; std::atomic matchingMessageReceived{false}; auto con = sdbus::createBusConnection(); con->enterEventLoopAsync(); diff --git a/tests/integrationtests/DBusMethodsTests.cpp b/tests/integrationtests/DBusMethodsTests.cpp index b18b5f0..e8256f9 100644 --- a/tests/integrationtests/DBusMethodsTests.cpp +++ b/tests/integrationtests/DBusMethodsTests.cpp @@ -231,13 +231,13 @@ TYPED_TEST(SdbusTestObject, FailsCallingMethodOnNonexistentInterface) TYPED_TEST(SdbusTestObject, FailsCallingMethodOnNonexistentDestination) { - TestProxy proxy("sdbuscpp.destination.that.does.not.exist", OBJECT_PATH); + TestProxy proxy(sdbus::ServiceName{"sdbuscpp.destination.that.does.not.exist"}, OBJECT_PATH); ASSERT_THROW(proxy.getInt(), sdbus::Error); } TYPED_TEST(SdbusTestObject, FailsCallingMethodOnNonexistentObject) { - TestProxy proxy(BUS_NAME, "/sdbuscpp/path/that/does/not/exist"); + TestProxy proxy(SERVICE_NAME, sdbus::ObjectPath{"/sdbuscpp/path/that/does/not/exist"}); ASSERT_THROW(proxy.getInt(), sdbus::Error); } @@ -254,7 +254,7 @@ TYPED_TEST(SdbusTestObject, CanAccessAssociatedMethodCallMessageInMethodCallHand this->m_proxy->doOperation(10); // This will save pointer to method call message on server side ASSERT_THAT(this->m_adaptor->m_methodCallMsg, NotNull()); - ASSERT_THAT(this->m_adaptor->m_methodCallMemberName, Eq("doOperation")); + ASSERT_THAT(this->m_adaptor->m_methodName, Eq("doOperation")); } TYPED_TEST(SdbusTestObject, CanAccessAssociatedMethodCallMessageInAsyncMethodCallHandler) @@ -262,7 +262,7 @@ TYPED_TEST(SdbusTestObject, CanAccessAssociatedMethodCallMessageInAsyncMethodCal this->m_proxy->doOperationAsync(10); // This will save pointer to method call message on server side ASSERT_THAT(this->m_adaptor->m_methodCallMsg, NotNull()); - ASSERT_THAT(this->m_adaptor->m_methodCallMemberName, Eq("doOperationAsync")); + ASSERT_THAT(this->m_adaptor->m_methodName, Eq("doOperationAsync")); } #if LIBSYSTEMD_VERSION>=240 @@ -281,7 +281,7 @@ TYPED_TEST(SdbusTestObject, CannotSetGeneralMethodTimeoutWithLibsystemdVersionLe TYPED_TEST(SdbusTestObject, CanCallMethodSynchronouslyWithoutAnEventLoopThread) { - auto proxy = std::make_unique(BUS_NAME, OBJECT_PATH, sdbus::dont_run_event_loop_thread); + auto proxy = std::make_unique(SERVICE_NAME, OBJECT_PATH, sdbus::dont_run_event_loop_thread); auto multiplyRes = proxy->multiply(INT64_VALUE, DOUBLE_VALUE); @@ -291,15 +291,16 @@ TYPED_TEST(SdbusTestObject, CanCallMethodSynchronouslyWithoutAnEventLoopThread) TYPED_TEST(SdbusTestObject, CanRegisterAdditionalVTableDynamicallyAtAnyTime) { auto& object = this->m_adaptor->getObject(); - auto vtableSlot = object.addVTable( "org.sdbuscpp.integrationtests2" + sdbus::InterfaceName interfaceName{"org.sdbuscpp.integrationtests2"}; + auto vtableSlot = object.addVTable( interfaceName , { sdbus::registerMethod("add").implementedAs([](const int64_t& a, const double& b){ return a + b; }) , sdbus::registerMethod("subtract").implementedAs([](const int& a, const int& b){ return a - b; }) } , sdbus::return_slot ); // The new remote vtable is registered as long as we keep vtableSlot, so remote method calls now should pass - auto proxy = sdbus::createProxy(BUS_NAME, OBJECT_PATH, sdbus::dont_run_event_loop_thread); + auto proxy = sdbus::createProxy(SERVICE_NAME, OBJECT_PATH, sdbus::dont_run_event_loop_thread); int result{}; - proxy->callMethod("subtract").onInterface("org.sdbuscpp.integrationtests2").withArguments(10, 2).storeResultsTo(result); + proxy->callMethod("subtract").onInterface(interfaceName).withArguments(10, 2).storeResultsTo(result); ASSERT_THAT(result, Eq(8)); } @@ -307,14 +308,15 @@ TYPED_TEST(SdbusTestObject, CanRegisterAdditionalVTableDynamicallyAtAnyTime) TYPED_TEST(SdbusTestObject, CanUnregisterAdditionallyRegisteredVTableAtAnyTime) { auto& object = this->m_adaptor->getObject(); + sdbus::InterfaceName interfaceName{"org.sdbuscpp.integrationtests2"}; - auto vtableSlot = object.addVTable( "org.sdbuscpp.integrationtests2" + auto vtableSlot = object.addVTable( interfaceName , { sdbus::registerMethod("add").implementedAs([](const int64_t& a, const double& b){ return a + b; }) , sdbus::registerMethod("subtract").implementedAs([](const int& a, const int& b){ return a - b; }) } , sdbus::return_slot ); vtableSlot.reset(); // Letting the slot go means letting go the associated vtable registration // No such remote D-Bus method under given interface exists anymore... - auto proxy = sdbus::createProxy(BUS_NAME, OBJECT_PATH, sdbus::dont_run_event_loop_thread); - ASSERT_THROW(proxy->callMethod("subtract").onInterface("org.sdbuscpp.integrationtests2").withArguments(10, 2), sdbus::Error); + auto proxy = sdbus::createProxy(SERVICE_NAME, OBJECT_PATH, sdbus::dont_run_event_loop_thread); + ASSERT_THROW(proxy->callMethod("subtract").onInterface(interfaceName).withArguments(10, 2), sdbus::Error); } diff --git a/tests/integrationtests/DBusSignalsTests.cpp b/tests/integrationtests/DBusSignalsTests.cpp index 4b12756..463bdcd 100644 --- a/tests/integrationtests/DBusSignalsTests.cpp +++ b/tests/integrationtests/DBusSignalsTests.cpp @@ -57,8 +57,8 @@ TYPED_TEST(SdbusTestObject, EmitsSimpleSignalSuccesfully) TYPED_TEST(SdbusTestObject, EmitsSimpleSignalToMultipleProxiesSuccesfully) { - auto proxy1 = std::make_unique(*this->s_adaptorConnection, BUS_NAME, OBJECT_PATH); - auto proxy2 = std::make_unique(*this->s_adaptorConnection, BUS_NAME, OBJECT_PATH); + auto proxy1 = std::make_unique(*this->s_adaptorConnection, SERVICE_NAME, OBJECT_PATH); + auto proxy2 = std::make_unique(*this->s_adaptorConnection, SERVICE_NAME, OBJECT_PATH); this->m_adaptor->emitSimpleSignal(); @@ -69,7 +69,7 @@ TYPED_TEST(SdbusTestObject, EmitsSimpleSignalToMultipleProxiesSuccesfully) TYPED_TEST(SdbusTestObject, ProxyDoesNotReceiveSignalFromOtherBusName) { - auto otherBusName = BUS_NAME + "2"; + sdbus::ServiceName otherBusName{SERVICE_NAME + "2"}; auto connection2 = sdbus::createBusConnection(otherBusName); auto adaptor2 = std::make_unique(*connection2, OBJECT_PATH); @@ -110,10 +110,10 @@ TYPED_TEST(SdbusTestObject, EmitsSignalWithVariantSuccesfully) TYPED_TEST(SdbusTestObject, EmitsSignalWithoutRegistrationSuccesfully) { - this->m_adaptor->emitSignalWithoutRegistration({"platform", {"av"}}); + this->m_adaptor->emitSignalWithoutRegistration({"platform", sdbus::Signature{"av"}}); ASSERT_TRUE(waitUntil(this->m_proxy->m_gotSignalWithSignature)); - ASSERT_THAT(this->m_proxy->m_signatureFromSignal["platform"], Eq("av")); + ASSERT_THAT(this->m_proxy->m_signatureFromSignal["platform"], Eq(sdbus::Signature{"av"})); } TYPED_TEST(SdbusTestObject, CanAccessAssociatedSignalMessageInSignalHandler) @@ -123,7 +123,7 @@ TYPED_TEST(SdbusTestObject, CanAccessAssociatedSignalMessageInSignalHandler) waitUntil(this->m_proxy->m_gotSimpleSignal); ASSERT_THAT(this->m_proxy->m_signalMsg, NotNull()); - ASSERT_THAT(this->m_proxy->m_signalMemberName, Eq("simpleSignal")); + ASSERT_THAT(this->m_proxy->m_signalName, Eq(std::string("simpleSignal"))); } TYPED_TEST(SdbusTestObject, UnregistersSignalHandler) @@ -137,8 +137,8 @@ TYPED_TEST(SdbusTestObject, UnregistersSignalHandler) TYPED_TEST(SdbusTestObject, UnregistersSignalHandlerForSomeProxies) { - auto proxy1 = std::make_unique(*this->s_adaptorConnection, BUS_NAME, OBJECT_PATH); - auto proxy2 = std::make_unique(*this->s_adaptorConnection, BUS_NAME, OBJECT_PATH); + auto proxy1 = std::make_unique(*this->s_adaptorConnection, SERVICE_NAME, OBJECT_PATH); + auto proxy2 = std::make_unique(*this->s_adaptorConnection, SERVICE_NAME, OBJECT_PATH); ASSERT_NO_THROW(this->m_proxy->unregisterSimpleSignalHandler()); diff --git a/tests/integrationtests/DBusStandardInterfacesTests.cpp b/tests/integrationtests/DBusStandardInterfacesTests.cpp index a745f7d..578ba5b 100644 --- a/tests/integrationtests/DBusStandardInterfacesTests.cpp +++ b/tests/integrationtests/DBusStandardInterfacesTests.cpp @@ -142,17 +142,17 @@ TYPED_TEST(SdbusTestObject, GetsAllPropertiesViaPropertiesInterface) const auto properties = this->m_proxy->GetAll(INTERFACE_NAME); ASSERT_THAT(properties, SizeIs(3)); - EXPECT_THAT(properties.at("state").template get(), Eq(DEFAULT_STATE_VALUE)); - EXPECT_THAT(properties.at("action").template get(), Eq(DEFAULT_ACTION_VALUE)); - EXPECT_THAT(properties.at("blocking").template get(), Eq(DEFAULT_BLOCKING_VALUE)); + EXPECT_THAT(properties.at(STATE_PROPERTY).template get(), Eq(DEFAULT_STATE_VALUE)); + EXPECT_THAT(properties.at(ACTION_PROPERTY).template get(), Eq(DEFAULT_ACTION_VALUE)); + EXPECT_THAT(properties.at(BLOCKING_PROPERTY).template get(), Eq(DEFAULT_BLOCKING_VALUE)); } TYPED_TEST(SdbusTestObject, GetsAllPropertiesAsynchronouslyViaPropertiesInterface) { - std::promise> promise; + std::promise> promise; auto future = promise.get_future(); - this->m_proxy->GetAllAsync(INTERFACE_NAME, [&](std::optional err, std::map value) + this->m_proxy->GetAllAsync(INTERFACE_NAME, [&](std::optional err, std::map value) { if (!err) promise.set_value(std::move(value)); @@ -162,9 +162,9 @@ TYPED_TEST(SdbusTestObject, GetsAllPropertiesAsynchronouslyViaPropertiesInterfac const auto properties = future.get(); ASSERT_THAT(properties, SizeIs(3)); - EXPECT_THAT(properties.at("state").get(), Eq(DEFAULT_STATE_VALUE)); - EXPECT_THAT(properties.at("action").get(), Eq(DEFAULT_ACTION_VALUE)); - EXPECT_THAT(properties.at("blocking").get(), Eq(DEFAULT_BLOCKING_VALUE)); + EXPECT_THAT(properties.at(STATE_PROPERTY).get(), Eq(DEFAULT_STATE_VALUE)); + EXPECT_THAT(properties.at(ACTION_PROPERTY).get(), Eq(DEFAULT_ACTION_VALUE)); + EXPECT_THAT(properties.at(BLOCKING_PROPERTY).get(), Eq(DEFAULT_BLOCKING_VALUE)); } TYPED_TEST(SdbusTestObject, GetsAllPropertiesAsynchronouslyViaPropertiesInterfaceWithFuture) @@ -174,27 +174,27 @@ TYPED_TEST(SdbusTestObject, GetsAllPropertiesAsynchronouslyViaPropertiesInterfac auto properties = future.get(); ASSERT_THAT(properties, SizeIs(3)); - EXPECT_THAT(properties.at("state").template get(), Eq(DEFAULT_STATE_VALUE)); - EXPECT_THAT(properties.at("action").template get(), Eq(DEFAULT_ACTION_VALUE)); - EXPECT_THAT(properties.at("blocking").template get(), Eq(DEFAULT_BLOCKING_VALUE)); + EXPECT_THAT(properties.at(STATE_PROPERTY).template get(), Eq(DEFAULT_STATE_VALUE)); + EXPECT_THAT(properties.at(ACTION_PROPERTY).template get(), Eq(DEFAULT_ACTION_VALUE)); + EXPECT_THAT(properties.at(BLOCKING_PROPERTY).template get(), Eq(DEFAULT_BLOCKING_VALUE)); } TYPED_TEST(SdbusTestObject, EmitsPropertyChangedSignalForSelectedProperties) { std::atomic signalReceived{false}; - this->m_proxy->m_onPropertiesChangedHandler = [&signalReceived]( const std::string& interfaceName - , const std::map& changedProperties - , const std::vector& /*invalidatedProperties*/ ) + this->m_proxy->m_onPropertiesChangedHandler = [&signalReceived]( const sdbus::InterfaceName& interfaceName + , const std::map& changedProperties + , const std::vector& /*invalidatedProperties*/ ) { EXPECT_THAT(interfaceName, Eq(INTERFACE_NAME)); EXPECT_THAT(changedProperties, SizeIs(1)); - EXPECT_THAT(changedProperties.at("blocking").get(), Eq(!DEFAULT_BLOCKING_VALUE)); + EXPECT_THAT(changedProperties.at(BLOCKING_PROPERTY).get(), Eq(!DEFAULT_BLOCKING_VALUE)); signalReceived = true; }; this->m_proxy->blocking(!DEFAULT_BLOCKING_VALUE); this->m_proxy->action(DEFAULT_ACTION_VALUE*2); - this->m_adaptor->emitPropertiesChangedSignal(INTERFACE_NAME, {"blocking"}); + this->m_adaptor->emitPropertiesChangedSignal(INTERFACE_NAME, {BLOCKING_PROPERTY}); ASSERT_TRUE(waitUntil(signalReceived)); } @@ -202,13 +202,13 @@ TYPED_TEST(SdbusTestObject, EmitsPropertyChangedSignalForSelectedProperties) TYPED_TEST(SdbusTestObject, EmitsPropertyChangedSignalForAllProperties) { std::atomic signalReceived{false}; - this->m_proxy->m_onPropertiesChangedHandler = [&signalReceived]( const std::string& interfaceName - , const std::map& changedProperties - , const std::vector& invalidatedProperties ) + this->m_proxy->m_onPropertiesChangedHandler = [&signalReceived]( const sdbus::InterfaceName& interfaceName + , const std::map& changedProperties + , const std::vector& invalidatedProperties ) { EXPECT_THAT(interfaceName, Eq(INTERFACE_NAME)); EXPECT_THAT(changedProperties, SizeIs(1)); - EXPECT_THAT(changedProperties.at("blocking").get(), Eq(DEFAULT_BLOCKING_VALUE)); + EXPECT_THAT(changedProperties.at(BLOCKING_PROPERTY).get(), Eq(DEFAULT_BLOCKING_VALUE)); ASSERT_THAT(invalidatedProperties, SizeIs(1)); EXPECT_THAT(invalidatedProperties[0], Eq("action")); signalReceived = true; @@ -235,17 +235,17 @@ TYPED_TEST(SdbusTestObject, GetsManagedObjectsSuccessfully) ASSERT_THAT(objectsInterfacesAndProperties, SizeIs(2)); EXPECT_THAT(objectsInterfacesAndProperties.at(OBJECT_PATH) .at(org::sdbuscpp::integrationtests_adaptor::INTERFACE_NAME) - .at("action").template get(), Eq(DEFAULT_ACTION_VALUE)); + .at(ACTION_PROPERTY).template get(), Eq(DEFAULT_ACTION_VALUE)); EXPECT_THAT(objectsInterfacesAndProperties.at(OBJECT_PATH_2) .at(org::sdbuscpp::integrationtests_adaptor::INTERFACE_NAME) - .at("action").template get(), Eq(DEFAULT_ACTION_VALUE)); + .at(ACTION_PROPERTY).template get(), Eq(DEFAULT_ACTION_VALUE)); } TYPED_TEST(SdbusTestObject, EmitsInterfacesAddedSignalForSelectedObjectInterfaces) { std::atomic signalReceived{false}; this->m_objectManagerProxy->m_onInterfacesAddedHandler = [&signalReceived]( const sdbus::ObjectPath& objectPath - , const std::map>& interfacesAndProperties ) + , const std::map>& interfacesAndProperties ) { EXPECT_THAT(objectPath, Eq(OBJECT_PATH)); EXPECT_THAT(interfacesAndProperties, SizeIs(1)); @@ -253,16 +253,16 @@ TYPED_TEST(SdbusTestObject, EmitsInterfacesAddedSignalForSelectedObjectInterface #if LIBSYSTEMD_VERSION<=244 // Up to sd-bus v244, all properties are added to the list, i.e. `state', `action', and `blocking' in this case. EXPECT_THAT(interfacesAndProperties.at(INTERFACE_NAME), SizeIs(3)); - EXPECT_TRUE(interfacesAndProperties.at(INTERFACE_NAME).count("state")); - EXPECT_TRUE(interfacesAndProperties.at(INTERFACE_NAME).count("action")); - EXPECT_TRUE(interfacesAndProperties.at(INTERFACE_NAME).count("blocking")); + EXPECT_TRUE(interfacesAndProperties.at(INTERFACE_NAME).count(STATE_PROPERTY)); + EXPECT_TRUE(interfacesAndProperties.at(INTERFACE_NAME).count(ACTION_PROPERTY)); + EXPECT_TRUE(interfacesAndProperties.at(INTERFACE_NAME).count(BLOCKING_PROPERTY)); #else // Since v245 sd-bus does not add to the InterfacesAdded signal message the values of properties marked only // for invalidation on change, which makes the behavior consistent with the PropertiesChangedSignal. // So in this specific instance, `action' property is no more added to the list. EXPECT_THAT(interfacesAndProperties.at(INTERFACE_NAME), SizeIs(2)); - EXPECT_TRUE(interfacesAndProperties.at(INTERFACE_NAME).count("state")); - EXPECT_TRUE(interfacesAndProperties.at(INTERFACE_NAME).count("blocking")); + EXPECT_TRUE(interfacesAndProperties.at(INTERFACE_NAME).count(STATE_PROPERTY)); + EXPECT_TRUE(interfacesAndProperties.at(INTERFACE_NAME).count(BLOCKING_PROPERTY)); #endif signalReceived = true; }; @@ -276,7 +276,7 @@ TYPED_TEST(SdbusTestObject, EmitsInterfacesAddedSignalForAllObjectInterfaces) { std::atomic signalReceived{false}; this->m_objectManagerProxy->m_onInterfacesAddedHandler = [&signalReceived]( const sdbus::ObjectPath& objectPath - , const std::map>& interfacesAndProperties ) + , const std::map>& interfacesAndProperties ) { EXPECT_THAT(objectPath, Eq(OBJECT_PATH)); #if LIBSYSTEMD_VERSION<=250 @@ -289,16 +289,16 @@ TYPED_TEST(SdbusTestObject, EmitsInterfacesAddedSignalForAllObjectInterfaces) #if LIBSYSTEMD_VERSION<=244 // Up to sd-bus v244, all properties are added to the list, i.e. `state', `action', and `blocking' in this case. EXPECT_THAT(interfacesAndProperties.at(INTERFACE_NAME), SizeIs(3)); - EXPECT_TRUE(interfacesAndProperties.at(INTERFACE_NAME).count("state")); - EXPECT_TRUE(interfacesAndProperties.at(INTERFACE_NAME).count("action")); - EXPECT_TRUE(interfacesAndProperties.at(INTERFACE_NAME).count("blocking")); + EXPECT_TRUE(interfacesAndProperties.at(INTERFACE_NAME).count(STATE_PROPERTY)); + EXPECT_TRUE(interfacesAndProperties.at(INTERFACE_NAME).count(ACTION_PROPERTY)); + EXPECT_TRUE(interfacesAndProperties.at(INTERFACE_NAME).count(BLOCKING_PROPERTY)); #else // Since v245 sd-bus does not add to the InterfacesAdded signal message the values of properties marked only // for invalidation on change, which makes the behavior consistent with the PropertiesChangedSignal. // So in this specific instance, `action' property is no more added to the list. EXPECT_THAT(interfacesAndProperties.at(INTERFACE_NAME), SizeIs(2)); - EXPECT_TRUE(interfacesAndProperties.at(INTERFACE_NAME).count("state")); - EXPECT_TRUE(interfacesAndProperties.at(INTERFACE_NAME).count("blocking")); + EXPECT_TRUE(interfacesAndProperties.at(INTERFACE_NAME).count(STATE_PROPERTY)); + EXPECT_TRUE(interfacesAndProperties.at(INTERFACE_NAME).count(BLOCKING_PROPERTY)); #endif signalReceived = true; }; @@ -312,7 +312,7 @@ TYPED_TEST(SdbusTestObject, EmitsInterfacesRemovedSignalForSelectedObjectInterfa { std::atomic signalReceived{false}; this->m_objectManagerProxy->m_onInterfacesRemovedHandler = [&signalReceived]( const sdbus::ObjectPath& objectPath - , const std::vector& interfaces ) + , const std::vector& interfaces ) { EXPECT_THAT(objectPath, Eq(OBJECT_PATH)); ASSERT_THAT(interfaces, SizeIs(1)); @@ -329,7 +329,7 @@ TYPED_TEST(SdbusTestObject, EmitsInterfacesRemovedSignalForAllObjectInterfaces) { std::atomic signalReceived{false}; this->m_objectManagerProxy->m_onInterfacesRemovedHandler = [&signalReceived]( const sdbus::ObjectPath& objectPath - , const std::vector& interfaces ) + , const std::vector& interfaces ) { EXPECT_THAT(objectPath, Eq(OBJECT_PATH)); #if LIBSYSTEMD_VERSION<=250 diff --git a/tests/integrationtests/Defs.h b/tests/integrationtests/Defs.h index 0b5df55..0bc43f2 100644 --- a/tests/integrationtests/Defs.h +++ b/tests/integrationtests/Defs.h @@ -34,12 +34,15 @@ namespace sdbus { namespace test { -const std::string INTERFACE_NAME{"org.sdbuscpp.integrationtests"}; -const std::string BUS_NAME = INTERFACE_NAME; -const std::string EMPTY_DESTINATION; -const std::string MANAGER_PATH {"/org/sdbuscpp/integrationtests"}; -const std::string OBJECT_PATH {"/org/sdbuscpp/integrationtests/ObjectA1"}; -const std::string OBJECT_PATH_2{"/org/sdbuscpp/integrationtests/ObjectB1"}; +const InterfaceName INTERFACE_NAME{"org.sdbuscpp.integrationtests"}; +const ServiceName SERVICE_NAME{"org.sdbuscpp.integrationtests"}; +const ServiceName EMPTY_DESTINATION; +const ObjectPath MANAGER_PATH {"/org/sdbuscpp/integrationtests"}; +const ObjectPath OBJECT_PATH {"/org/sdbuscpp/integrationtests/ObjectA1"}; +const ObjectPath OBJECT_PATH_2{"/org/sdbuscpp/integrationtests/ObjectB1"}; +const PropertyName STATE_PROPERTY{"state"}; +const PropertyName ACTION_PROPERTY{"action"}; +const PropertyName BLOCKING_PROPERTY{"blocking"}; const std::string DIRECT_CONNECTION_SOCKET_PATH{std::filesystem::temp_directory_path() / "sdbus-cpp-direct-connection-test"}; constexpr const uint8_t UINT8_VALUE{1}; @@ -49,8 +52,8 @@ constexpr const int32_t INT32_VALUE{-42}; constexpr const int32_t INT64_VALUE{-1024}; const std::string STRING_VALUE{"sdbus-c++-testing"}; -const sdbus::Signature SIGNATURE_VALUE{"a{is}"}; -const sdbus::ObjectPath OBJECT_PATH_VALUE{"/"}; +const Signature SIGNATURE_VALUE{"a{is}"}; +const ObjectPath OBJECT_PATH_VALUE{"/"}; const int UNIX_FD_VALUE = 0; const std::string DEFAULT_STATE_VALUE{"default-state-value"}; diff --git a/tests/integrationtests/TestAdaptor.cpp b/tests/integrationtests/TestAdaptor.cpp index 9a13995..ea66296 100644 --- a/tests/integrationtests/TestAdaptor.cpp +++ b/tests/integrationtests/TestAdaptor.cpp @@ -31,8 +31,8 @@ namespace sdbus { namespace test { -TestAdaptor::TestAdaptor(sdbus::IConnection& connection, const std::string& path) : - AdaptorInterfaces(connection, path) +TestAdaptor::TestAdaptor(sdbus::IConnection& connection, sdbus::ObjectPath path) : + AdaptorInterfaces(connection, std::move(path)) { registerAdaptor(); } @@ -123,7 +123,7 @@ uint32_t TestAdaptor::doOperation(const uint32_t& param) std::this_thread::sleep_for(std::chrono::milliseconds(param)); m_methodCallMsg = std::make_unique(getObject().getCurrentlyProcessedMessage()); - m_methodCallMemberName = m_methodCallMsg->getMemberName(); + m_methodName = m_methodCallMsg->getMemberName(); return param; } @@ -131,7 +131,7 @@ uint32_t TestAdaptor::doOperation(const uint32_t& param) void TestAdaptor::doOperationAsync(sdbus::Result&& result, uint32_t param) { m_methodCallMsg = std::make_unique(getObject().getCurrentlyProcessedMessage()); - m_methodCallMemberName = m_methodCallMsg->getMemberName(); + m_methodName = m_methodCallMsg->getMemberName(); if (param == 0) { @@ -173,7 +173,7 @@ std::unordered_map { public: - ObjectManagerTestAdaptor(sdbus::IConnection& connection, std::string path) : + ObjectManagerTestAdaptor(sdbus::IConnection& connection, sdbus::ObjectPath path) : AdaptorInterfaces(connection, std::move(path)) { registerAdaptor(); @@ -57,7 +57,7 @@ class TestAdaptor final : public sdbus::AdaptorInterfaces< org::sdbuscpp::integr , sdbus::ManagedObject_adaptor > { public: - TestAdaptor(sdbus::IConnection& connection, const std::string& path); + TestAdaptor(sdbus::IConnection& connection, sdbus::ObjectPath path); ~TestAdaptor(); protected: @@ -105,7 +105,7 @@ public: // for tests mutable std::atomic m_wasThrowErrorCalled{false}; std::unique_ptr m_methodCallMsg; - std::string m_methodCallMemberName; + MethodName m_methodName; std::unique_ptr m_propertySetMsg; std::string m_propertySetSender; }; @@ -115,7 +115,9 @@ class DummyTestAdaptor final : public sdbus::AdaptorInterfaces< org::sdbuscpp::i , sdbus::ManagedObject_adaptor > { public: - DummyTestAdaptor(sdbus::IConnection& connection, const std::string& path) : AdaptorInterfaces(connection, path) {} + DummyTestAdaptor(sdbus::IConnection& connection, sdbus::ObjectPath path) + : AdaptorInterfaces(connection, std::move(path)) + {} protected: void noArgNoReturn() override {} diff --git a/tests/integrationtests/TestFixture.h b/tests/integrationtests/TestFixture.h index ccbe3dd..4901ea3 100644 --- a/tests/integrationtests/TestFixture.h +++ b/tests/integrationtests/TestFixture.h @@ -55,19 +55,19 @@ class BaseTestFixture : public ::testing::Test public: static void SetUpTestCase() { - s_adaptorConnection->requestName(BUS_NAME); + s_adaptorConnection->requestName(SERVICE_NAME); } static void TearDownTestCase() { - s_adaptorConnection->releaseName(BUS_NAME); + s_adaptorConnection->releaseName(SERVICE_NAME); } private: void SetUp() override { - m_objectManagerProxy = std::make_unique(*s_proxyConnection, BUS_NAME, MANAGER_PATH); - m_proxy = std::make_unique(*s_proxyConnection, BUS_NAME, OBJECT_PATH); + m_objectManagerProxy = std::make_unique(*s_proxyConnection, SERVICE_NAME, MANAGER_PATH); + m_proxy = std::make_unique(*s_proxyConnection, SERVICE_NAME, OBJECT_PATH); m_objectManagerAdaptor = std::make_unique(*s_adaptorConnection, MANAGER_PATH); m_adaptor = std::make_unique(*s_adaptorConnection, OBJECT_PATH); diff --git a/tests/integrationtests/TestProxy.cpp b/tests/integrationtests/TestProxy.cpp index 5089bdd..2eddffa 100644 --- a/tests/integrationtests/TestProxy.cpp +++ b/tests/integrationtests/TestProxy.cpp @@ -31,7 +31,7 @@ namespace sdbus { namespace test { -TestProxy::TestProxy(std::string destination, std::string objectPath) +TestProxy::TestProxy(ServiceName destination, ObjectPath objectPath) : ProxyInterfaces(std::move(destination), std::move(objectPath)) { getProxy().uponSignal("signalWithoutRegistration").onInterface(sdbus::test::INTERFACE_NAME).call([this](const sdbus::Struct>& s){ this->onSignalWithoutRegistration(s); }); @@ -39,14 +39,14 @@ TestProxy::TestProxy(std::string destination, std::string objectPath) registerProxy(); } -TestProxy::TestProxy(std::string destination, std::string objectPath, dont_run_event_loop_thread_t) +TestProxy::TestProxy(ServiceName destination, ObjectPath objectPath, dont_run_event_loop_thread_t) : ProxyInterfaces(std::move(destination), std::move(objectPath), dont_run_event_loop_thread) { // It doesn't make sense to register any signals here since proxy upon a D-Bus connection with no event loop thread // will not receive any incoming messages except replies to synchronous D-Bus calls. } -TestProxy::TestProxy(sdbus::IConnection& connection, std::string destination, std::string objectPath) +TestProxy::TestProxy(sdbus::IConnection& connection, ServiceName destination, ObjectPath objectPath) : ProxyInterfaces(connection, std::move(destination), std::move(objectPath)) { getProxy().uponSignal("signalWithoutRegistration").onInterface(sdbus::test::INTERFACE_NAME).call([this](const sdbus::Struct>& s){ this->onSignalWithoutRegistration(s); }); @@ -62,7 +62,7 @@ TestProxy::~TestProxy() void TestProxy::onSimpleSignal() { m_signalMsg = std::make_unique(getProxy().getCurrentlyProcessedMessage()); - m_signalMemberName = m_signalMsg->getMemberName(); + m_signalName = m_signalMsg->getMemberName(); m_gotSimpleSignal = true; } @@ -81,6 +81,7 @@ void TestProxy::onSignalWithVariant(const sdbus::Variant& aVariant) void TestProxy::onSignalWithoutRegistration(const sdbus::Struct>& s) { + // Static cast to std::string is a workaround for gcc 11.4 false positive warning (which later gcc versions nor Clang emit) m_signatureFromSignal[std::get<0>(s)] = static_cast(std::get<0>(std::get<1>(s))); m_gotSignalWithSignature = true; } @@ -91,9 +92,9 @@ void TestProxy::onDoOperationReply(uint32_t returnValue, std::optional& changedProperties - , const std::vector& invalidatedProperties ) +void TestProxy::onPropertiesChanged( const sdbus::InterfaceName& interfaceName + , const std::map& changedProperties + , const std::vector& invalidatedProperties ) { if (m_onPropertiesChangedHandler) m_onPropertiesChangedHandler(interfaceName, changedProperties, invalidatedProperties); @@ -133,7 +134,7 @@ std::future TestProxy::doOperationClientSideAsync(uint32_t param, with std::future TestProxy::doOperationClientSideAsyncOnBasicAPILevel(uint32_t param) { - auto methodCall = getProxy().createMethodCall(sdbus::test::INTERFACE_NAME, "doOperation"); + auto methodCall = getProxy().createMethodCall(sdbus::test::INTERFACE_NAME, sdbus::MethodName{"doOperation"}); methodCall << param; return getProxy().callMethodAsync(methodCall, sdbus::with_future); @@ -178,8 +179,9 @@ int32_t TestProxy::callNonexistentMethod() int32_t TestProxy::callMethodOnNonexistentInterface() { + sdbus::InterfaceName nonexistentInterfaceName{"sdbuscpp.interface.that.does.not.exist"}; int32_t result; - getProxy().callMethod("someMethod").onInterface("sdbuscpp.interface.that.does.not.exist").storeResultsTo(result); + getProxy().callMethod("someMethod").onInterface(nonexistentInterfaceName).storeResultsTo(result); return result; } diff --git a/tests/integrationtests/TestProxy.h b/tests/integrationtests/TestProxy.h index cf8a627..45797fc 100644 --- a/tests/integrationtests/TestProxy.h +++ b/tests/integrationtests/TestProxy.h @@ -40,7 +40,7 @@ namespace sdbus { namespace test { class ObjectManagerTestProxy final : public sdbus::ProxyInterfaces< sdbus::ObjectManager_proxy > { public: - ObjectManagerTestProxy(sdbus::IConnection& connection, std::string destination, std::string objectPath) + ObjectManagerTestProxy(sdbus::IConnection& connection, ServiceName destination, ObjectPath objectPath) : ProxyInterfaces(connection, std::move(destination), std::move(objectPath)) { registerProxy(); @@ -51,21 +51,21 @@ public: unregisterProxy(); } protected: - void onInterfacesAdded(const sdbus::ObjectPath& objectPath, const std::map>& interfacesAndProperties) override + void onInterfacesAdded(const sdbus::ObjectPath& objectPath, const std::map>& interfacesAndProperties) override { if (m_onInterfacesAddedHandler) m_onInterfacesAddedHandler(objectPath, interfacesAndProperties); } - void onInterfacesRemoved(const sdbus::ObjectPath& objectPath, const std::vector& interfaces) override + void onInterfacesRemoved(const sdbus::ObjectPath& objectPath, const std::vector& interfaces) override { if (m_onInterfacesRemovedHandler) m_onInterfacesRemovedHandler(objectPath, interfaces); } public: // for tests - std::function>&)> m_onInterfacesAddedHandler; - std::function&)> m_onInterfacesRemovedHandler; + std::function>&)> m_onInterfacesAddedHandler; + std::function&)> m_onInterfacesRemovedHandler; }; class TestProxy final : public sdbus::ProxyInterfaces< org::sdbuscpp::integrationtests_proxy @@ -74,9 +74,9 @@ class TestProxy final : public sdbus::ProxyInterfaces< org::sdbuscpp::integratio , sdbus::Properties_proxy > { public: - TestProxy(std::string destination, std::string objectPath); - TestProxy(std::string destination, std::string objectPath, dont_run_event_loop_thread_t); - TestProxy(sdbus::IConnection& connection, std::string destination, std::string objectPath); + TestProxy(ServiceName destination, ObjectPath objectPath); + TestProxy(ServiceName destination, ObjectPath objectPath, dont_run_event_loop_thread_t); + TestProxy(sdbus::IConnection& connection, ServiceName destination, ObjectPath objectPath); ~TestProxy(); protected: @@ -88,9 +88,9 @@ protected: void onDoOperationReply(uint32_t returnValue, std::optional error); // Signals of standard D-Bus interfaces - void onPropertiesChanged( const std::string& interfaceName - , const std::map& changedProperties - , const std::vector& invalidatedProperties ) override; + void onPropertiesChanged( const sdbus::InterfaceName& interfaceName + , const std::map& changedProperties + , const std::vector& invalidatedProperties ) override; public: void installDoOperationClientSideAsyncReplyHandler(std::function err)> handler); @@ -114,13 +114,13 @@ public: // for tests std::atomic m_gotSignalWithVariant{false}; double m_variantFromSignal; std::atomic m_gotSignalWithSignature{false}; - std::map m_signatureFromSignal; + std::map m_signatureFromSignal; std::function err)> m_DoOperationClientSideAsyncReplyHandler; - std::function&, const std::vector&)> m_onPropertiesChangedHandler; + std::function&, const std::vector&)> m_onPropertiesChangedHandler; std::unique_ptr m_signalMsg; - std::string m_signalMemberName; + SignalName m_signalName; }; class DummyTestProxy final : public sdbus::ProxyInterfaces< org::sdbuscpp::integrationtests_proxy @@ -129,7 +129,7 @@ class DummyTestProxy final : public sdbus::ProxyInterfaces< org::sdbuscpp::integ , sdbus::Properties_proxy > { public: - DummyTestProxy(std::string destination, std::string objectPath) + DummyTestProxy(ServiceName destination, ObjectPath objectPath) : ProxyInterfaces(destination, objectPath) { } @@ -143,7 +143,7 @@ protected: void onDoOperationReply(uint32_t, std::optional) {} // Signals of standard D-Bus interfaces - void onPropertiesChanged( const std::string&, const std::map&, const std::vector& ) override {} + void onPropertiesChanged(const InterfaceName&, const std::map&, const std::vector&) override {} }; }} diff --git a/tests/integrationtests/integrationtests-adaptor.h b/tests/integrationtests/integrationtests-adaptor.h index a34146f..fe651a9 100644 --- a/tests/integrationtests/integrationtests-adaptor.h +++ b/tests/integrationtests/integrationtests-adaptor.h @@ -16,7 +16,7 @@ namespace sdbuscpp { class integrationtests_adaptor { public: - static constexpr const char* INTERFACE_NAME = "org.sdbuscpp.integrationtests"; + static inline const sdbus::InterfaceName INTERFACE_NAME{"org.sdbuscpp.integrationtests"}; protected: integrationtests_adaptor(sdbus::IObject& object) diff --git a/tests/integrationtests/integrationtests-proxy.h b/tests/integrationtests/integrationtests-proxy.h index 1c86d92..e161183 100644 --- a/tests/integrationtests/integrationtests-proxy.h +++ b/tests/integrationtests/integrationtests-proxy.h @@ -16,7 +16,7 @@ namespace sdbuscpp { class integrationtests_proxy { public: - static constexpr const char* INTERFACE_NAME = "org.sdbuscpp.integrationtests"; + static inline const sdbus::InterfaceName INTERFACE_NAME{"org.sdbuscpp.integrationtests"}; protected: integrationtests_proxy(sdbus::IProxy& proxy) diff --git a/tests/perftests/client.cpp b/tests/perftests/client.cpp index 04988b3..fcc83d1 100644 --- a/tests/perftests/client.cpp +++ b/tests/perftests/client.cpp @@ -43,7 +43,7 @@ uint64_t totalDuration = 0; class PerftestProxy final : public sdbus::ProxyInterfaces { public: - PerftestProxy(std::string destination, std::string objectPath) + PerftestProxy(sdbus::ServiceName destination, sdbus::ObjectPath objectPath) : ProxyInterfaces(std::move(destination), std::move(objectPath)) { registerProxy(); @@ -101,9 +101,9 @@ std::string createRandomString(size_t length) //----------------------------------------- int main(int /*argc*/, char */*argv*/[]) { - const char* destinationName = "org.sdbuscpp.perftests"; - const char* objectPath = "/org/sdbuscpp/perftests"; - PerftestProxy client(destinationName, objectPath); + sdbus::ServiceName destination{"org.sdbuscpp.perftests"}; + sdbus::ObjectPath objectPath{"/org/sdbuscpp/perftests"}; + PerftestProxy client(std::move(destination), std::move(objectPath)); const unsigned int repetitions{20}; unsigned int msgCount = 1000; diff --git a/tests/perftests/perftests-adaptor.h b/tests/perftests/perftests-adaptor.h index 6aefa1a..4930117 100644 --- a/tests/perftests/perftests-adaptor.h +++ b/tests/perftests/perftests-adaptor.h @@ -16,7 +16,7 @@ namespace sdbuscpp { class perftests_adaptor { public: - static constexpr const char* INTERFACE_NAME = "org.sdbuscpp.perftests"; + static inline const sdbus::InterfaceName INTERFACE_NAME{"org.sdbuscpp.perftests"}; protected: perftests_adaptor(sdbus::IObject& object) diff --git a/tests/perftests/perftests-proxy.h b/tests/perftests/perftests-proxy.h index dee4bf9..22544ae 100644 --- a/tests/perftests/perftests-proxy.h +++ b/tests/perftests/perftests-proxy.h @@ -16,7 +16,7 @@ namespace sdbuscpp { class perftests_proxy { public: - static constexpr const char* INTERFACE_NAME = "org.sdbuscpp.perftests"; + static inline const sdbus::InterfaceName INTERFACE_NAME{"org.sdbuscpp.perftests"}; protected: perftests_proxy(sdbus::IProxy& proxy) diff --git a/tests/perftests/server.cpp b/tests/perftests/server.cpp index c7918d1..f88d2b2 100644 --- a/tests/perftests/server.cpp +++ b/tests/perftests/server.cpp @@ -40,7 +40,7 @@ std::string createRandomString(size_t length); class PerftestAdaptor final : public sdbus::AdaptorInterfaces { public: - PerftestAdaptor(sdbus::IConnection& connection, std::string objectPath) + PerftestAdaptor(sdbus::IConnection& connection, sdbus::ObjectPath objectPath) : AdaptorInterfaces(connection, std::move(objectPath)) { registerAdaptor(); @@ -92,11 +92,11 @@ std::string createRandomString(size_t length) //----------------------------------------- int main(int /*argc*/, char */*argv*/[]) { - const char* serviceName = "org.sdbuscpp.perftests"; + sdbus::ServiceName serviceName{"org.sdbuscpp.perftests"}; auto connection = sdbus::createSystemBusConnection(serviceName); - const char* objectPath = "/org/sdbuscpp/perftests"; - PerftestAdaptor server(*connection, objectPath); + sdbus::ObjectPath objectPath{"/org/sdbuscpp/perftests"}; + PerftestAdaptor server(*connection, std::move(objectPath)); connection->enterEventLoop(); } diff --git a/tests/stresstests/celsius-thermometer-adaptor.h b/tests/stresstests/celsius-thermometer-adaptor.h index 36a32ba..6b4b030 100644 --- a/tests/stresstests/celsius-thermometer-adaptor.h +++ b/tests/stresstests/celsius-thermometer-adaptor.h @@ -18,7 +18,7 @@ namespace celsius { class thermometer_adaptor { public: - static constexpr const char* INTERFACE_NAME = "org.sdbuscpp.stresstests.celsius.thermometer"; + static inline const sdbus::InterfaceName INTERFACE_NAME{"org.sdbuscpp.stresstests.celsius.thermometer"}; protected: thermometer_adaptor(sdbus::IObject& object) diff --git a/tests/stresstests/celsius-thermometer-proxy.h b/tests/stresstests/celsius-thermometer-proxy.h index b4a5715..480f79a 100644 --- a/tests/stresstests/celsius-thermometer-proxy.h +++ b/tests/stresstests/celsius-thermometer-proxy.h @@ -18,7 +18,7 @@ namespace celsius { class thermometer_proxy { public: - static constexpr const char* INTERFACE_NAME = "org.sdbuscpp.stresstests.celsius.thermometer"; + static inline const sdbus::InterfaceName INTERFACE_NAME{"org.sdbuscpp.stresstests.celsius.thermometer"}; protected: thermometer_proxy(sdbus::IProxy& proxy) diff --git a/tests/stresstests/concatenator-adaptor.h b/tests/stresstests/concatenator-adaptor.h index 0bd47e7..42eae54 100644 --- a/tests/stresstests/concatenator-adaptor.h +++ b/tests/stresstests/concatenator-adaptor.h @@ -17,7 +17,7 @@ namespace stresstests { class concatenator_adaptor { public: - static constexpr const char* INTERFACE_NAME = "org.sdbuscpp.stresstests.concatenator"; + static inline const sdbus::InterfaceName INTERFACE_NAME{"org.sdbuscpp.stresstests.concatenator"}; protected: concatenator_adaptor(sdbus::IObject& object) diff --git a/tests/stresstests/concatenator-proxy.h b/tests/stresstests/concatenator-proxy.h index 2383dc7..b5fdfef 100644 --- a/tests/stresstests/concatenator-proxy.h +++ b/tests/stresstests/concatenator-proxy.h @@ -17,7 +17,7 @@ namespace stresstests { class concatenator_proxy { public: - static constexpr const char* INTERFACE_NAME = "org.sdbuscpp.stresstests.concatenator"; + static inline const sdbus::InterfaceName INTERFACE_NAME{"org.sdbuscpp.stresstests.concatenator"}; protected: concatenator_proxy(sdbus::IProxy& proxy) diff --git a/tests/stresstests/fahrenheit-thermometer-adaptor.h b/tests/stresstests/fahrenheit-thermometer-adaptor.h index 0710fbb..883e574 100644 --- a/tests/stresstests/fahrenheit-thermometer-adaptor.h +++ b/tests/stresstests/fahrenheit-thermometer-adaptor.h @@ -18,7 +18,7 @@ namespace fahrenheit { class thermometer_adaptor { public: - static constexpr const char* INTERFACE_NAME = "org.sdbuscpp.stresstests.fahrenheit.thermometer"; + static inline const sdbus::InterfaceName INTERFACE_NAME{"org.sdbuscpp.stresstests.fahrenheit.thermometer"}; protected: thermometer_adaptor(sdbus::IObject& object) @@ -56,7 +56,7 @@ namespace thermometer { class factory_adaptor { public: - static constexpr const char* INTERFACE_NAME = "org.sdbuscpp.stresstests.fahrenheit.thermometer.factory"; + static inline const sdbus::InterfaceName INTERFACE_NAME{"org.sdbuscpp.stresstests.fahrenheit.thermometer.factory"}; protected: factory_adaptor(sdbus::IObject& object) diff --git a/tests/stresstests/fahrenheit-thermometer-proxy.h b/tests/stresstests/fahrenheit-thermometer-proxy.h index 3a1fc26..d24a2b5 100644 --- a/tests/stresstests/fahrenheit-thermometer-proxy.h +++ b/tests/stresstests/fahrenheit-thermometer-proxy.h @@ -18,7 +18,7 @@ namespace fahrenheit { class thermometer_proxy { public: - static constexpr const char* INTERFACE_NAME = "org.sdbuscpp.stresstests.fahrenheit.thermometer"; + static inline const sdbus::InterfaceName INTERFACE_NAME{"org.sdbuscpp.stresstests.fahrenheit.thermometer"}; protected: thermometer_proxy(sdbus::IProxy& proxy) @@ -60,7 +60,7 @@ namespace thermometer { class factory_proxy { public: - static constexpr const char* INTERFACE_NAME = "org.sdbuscpp.stresstests.fahrenheit.thermometer.factory"; + static inline const sdbus::InterfaceName INTERFACE_NAME{"org.sdbuscpp.stresstests.fahrenheit.thermometer.factory"}; protected: factory_proxy(sdbus::IProxy& proxy) diff --git a/tests/stresstests/sdbus-c++-stress-tests.cpp b/tests/stresstests/sdbus-c++-stress-tests.cpp index e379cce..66f8246 100644 --- a/tests/stresstests/sdbus-c++-stress-tests.cpp +++ b/tests/stresstests/sdbus-c++-stress-tests.cpp @@ -46,18 +46,17 @@ #include using namespace std::chrono_literals; -using namespace std::string_literals; -#define SERVICE_1_BUS_NAME "org.sdbuscpp.stresstests.service1"s -#define SERVICE_2_BUS_NAME "org.sdbuscpp.stresstests.service2"s -#define CELSIUS_THERMOMETER_OBJECT_PATH "/org/sdbuscpp/stresstests/celsius/thermometer"s -#define FAHRENHEIT_THERMOMETER_OBJECT_PATH "/org/sdbuscpp/stresstests/fahrenheit/thermometer"s -#define CONCATENATOR_OBJECT_PATH "/org/sdbuscpp/stresstests/concatenator"s +const sdbus::ServiceName SERVICE_1_BUS_NAME{"org.sdbuscpp.stresstests.service1"}; +const sdbus::ServiceName SERVICE_2_BUS_NAME{"org.sdbuscpp.stresstests.service2"}; +const sdbus::ObjectPath CELSIUS_THERMOMETER_OBJECT_PATH{"/org/sdbuscpp/stresstests/celsius/thermometer"}; +const sdbus::ObjectPath FAHRENHEIT_THERMOMETER_OBJECT_PATH{"/org/sdbuscpp/stresstests/fahrenheit/thermometer"}; +const sdbus::ObjectPath CONCATENATOR_OBJECT_PATH{"/org/sdbuscpp/stresstests/concatenator"}; class CelsiusThermometerAdaptor final : public sdbus::AdaptorInterfaces { public: - CelsiusThermometerAdaptor(sdbus::IConnection& connection, std::string objectPath) + CelsiusThermometerAdaptor(sdbus::IConnection& connection, sdbus::ObjectPath objectPath) : AdaptorInterfaces(connection, std::move(objectPath)) { registerAdaptor(); @@ -81,7 +80,7 @@ private: class CelsiusThermometerProxy : public sdbus::ProxyInterfaces { public: - CelsiusThermometerProxy(sdbus::IConnection& connection, std::string destination, std::string objectPath) + CelsiusThermometerProxy(sdbus::IConnection& connection, sdbus::ServiceName destination, sdbus::ObjectPath objectPath) : ProxyInterfaces(connection, std::move(destination), std::move(objectPath)) { registerProxy(); @@ -97,7 +96,7 @@ class FahrenheitThermometerAdaptor final : public sdbus::AdaptorInterfaces< org: , org::sdbuscpp::stresstests::fahrenheit::thermometer::factory_adaptor > { public: - FahrenheitThermometerAdaptor(sdbus::IConnection& connection, std::string objectPath, bool isDelegate) + FahrenheitThermometerAdaptor(sdbus::IConnection& connection, sdbus::ObjectPath objectPath, bool isDelegate) : AdaptorInterfaces(connection, std::move(objectPath)) , celsiusProxy_(connection, SERVICE_2_BUS_NAME, CELSIUS_THERMOMETER_OBJECT_PATH) { @@ -128,7 +127,7 @@ public: { // Create new delegate object auto& connection = getObject().getConnection(); - sdbus::ObjectPath newObjectPath = FAHRENHEIT_THERMOMETER_OBJECT_PATH + "/" + std::to_string(request.objectNr); + sdbus::ObjectPath newObjectPath{FAHRENHEIT_THERMOMETER_OBJECT_PATH + "/" + std::to_string(request.objectNr)}; // Here we are testing dynamic creation of a D-Bus object in an async way auto adaptor = std::make_unique(connection, newObjectPath, true); @@ -176,7 +175,7 @@ protected: objectCounter++; std::unique_lock lock(mutex_); - requests_.push(WorkItem{objectCounter, std::string{}, std::move(result)}); + requests_.push(WorkItem{objectCounter, {}, std::move(result)}); lock.unlock(); cond_.notify_one(); } @@ -191,7 +190,7 @@ protected: private: CelsiusThermometerProxy celsiusProxy_; - std::map> children_; + std::map> children_; std::mutex childrenMutex_; struct WorkItem @@ -211,7 +210,7 @@ class FahrenheitThermometerProxy : public sdbus::ProxyInterfaces< org::sdbuscpp: , org::sdbuscpp::stresstests::fahrenheit::thermometer::factory_proxy > { public: - FahrenheitThermometerProxy(sdbus::IConnection& connection, std::string destination, std::string objectPath) + FahrenheitThermometerProxy(sdbus::IConnection& connection, sdbus::ServiceName destination, sdbus::ObjectPath objectPath) : ProxyInterfaces(connection, std::move(destination), std::move(objectPath)) { registerProxy(); @@ -226,7 +225,7 @@ public: class ConcatenatorAdaptor final : public sdbus::AdaptorInterfaces { public: - ConcatenatorAdaptor(sdbus::IConnection& connection, std::string objectPath) + ConcatenatorAdaptor(sdbus::IConnection& connection, sdbus::ObjectPath objectPath) : AdaptorInterfaces(connection, std::move(objectPath)) { unsigned int workers = std::thread::hardware_concurrency(); @@ -298,7 +297,7 @@ private: class ConcatenatorProxy final : public sdbus::ProxyInterfaces { public: - ConcatenatorProxy(sdbus::IConnection& connection, std::string destination, std::string objectPath) + ConcatenatorProxy(sdbus::IConnection& connection, sdbus::ServiceName destination, sdbus::ObjectPath objectPath) : ProxyInterfaces(connection, std::move(destination), std::move(objectPath)) { registerProxy(); diff --git a/tests/unittests/Connection_test.cpp b/tests/unittests/Connection_test.cpp index 3ef0abc..88a2662 100644 --- a/tests/unittests/Connection_test.cpp +++ b/tests/unittests/Connection_test.cpp @@ -26,6 +26,7 @@ */ #include "Connection.h" +#include "sdbus-c++/Types.h" #include "unittests/mocks/SdBusMock.h" #include @@ -207,12 +208,16 @@ TYPED_TEST_SUITE(AConnectionNameRequest, BusTypeTags); TYPED_TEST(AConnectionNameRequest, DoesNotThrowOnSuccess) { EXPECT_CALL(*this->sdBusIntfMock_, sd_bus_request_name(_, _, _)).WillOnce(Return(1)); - this->con_->requestName("org.sdbuscpp.somename"); + sdbus::ConnectionName name{"org.sdbuscpp.somename"}; + + this->con_->requestName(name); } TYPED_TEST(AConnectionNameRequest, ThrowsOnFail) { + sdbus::ConnectionName name{"org.sdbuscpp.somename"}; + EXPECT_CALL(*this->sdBusIntfMock_, sd_bus_request_name(_, _, _)).WillOnce(Return(-1)); - ASSERT_THROW(this->con_->requestName("org.sdbuscpp.somename"), sdbus::Error); + ASSERT_THROW(this->con_->requestName(name), sdbus::Error); } diff --git a/tests/unittests/Message_test.cpp b/tests/unittests/Message_test.cpp index c91f230..1db7660 100644 --- a/tests/unittests/Message_test.cpp +++ b/tests/unittests/Message_test.cpp @@ -270,7 +270,7 @@ TEST(AMessage, CanCarryDBusArrayOfNontrivialTypesGivenAsStdVector) { auto msg = sdbus::createPlainMessage(); - const std::vector dataWritten{"s", "u", "b"}; + const std::vector dataWritten{sdbus::Signature{"s"}, sdbus::Signature{"u"}, sdbus::Signature{"b"}}; msg << dataWritten; msg.seal(); @@ -300,7 +300,7 @@ TEST(AMessage, CanCarryDBusArrayOfNontrivialTypesGivenAsStdArray) { auto msg = sdbus::createPlainMessage(); - const std::array dataWritten{"s", "u", "b"}; + const std::array dataWritten{sdbus::Signature{"s"}, sdbus::Signature{"u"}, sdbus::Signature{"b"}}; msg << dataWritten; msg.seal(); @@ -333,7 +333,7 @@ TEST(AMessage, CanCarryDBusArrayOfNontrivialTypesGivenAsStdSpan) { auto msg = sdbus::createPlainMessage(); - const std::array sourceArray{"s", "u", "b"}; + const std::array sourceArray{sdbus::Signature{"s"}, sdbus::Signature{"u"}, sdbus::Signature{"b"}}; const std::span dataWritten{sourceArray}; msg << dataWritten; @@ -433,7 +433,7 @@ TEST(AMessage, CanCarryAComplexType) > >; - ComplexType dataWritten = { {1, {{{5, {{"/some/object", true, 45, {{6, "hello"}, {7, "world"}}}}}}, "av", 3.14}}}; + ComplexType dataWritten = { {1, {{{5, {{sdbus::ObjectPath{"/some/object"}, true, 45, {{6, "hello"}, {7, "world"}}}}}}, sdbus::Signature{"av"}, 3.14}}}; msg << dataWritten; msg.seal(); diff --git a/tests/unittests/TypeTraits_test.cpp b/tests/unittests/TypeTraits_test.cpp index 3e7e092..0ccc7bd 100644 --- a/tests/unittests/TypeTraits_test.cpp +++ b/tests/unittests/TypeTraits_test.cpp @@ -85,6 +85,9 @@ namespace TYPE(double)HAS_DBUS_TYPE_SIGNATURE("d") TYPE(const char*)HAS_DBUS_TYPE_SIGNATURE("s") TYPE(std::string)HAS_DBUS_TYPE_SIGNATURE("s") + TYPE(sdbus::BusName)HAS_DBUS_TYPE_SIGNATURE("s") + TYPE(sdbus::InterfaceName)HAS_DBUS_TYPE_SIGNATURE("s") + TYPE(sdbus::MemberName)HAS_DBUS_TYPE_SIGNATURE("s") TYPE(sdbus::ObjectPath)HAS_DBUS_TYPE_SIGNATURE("o") TYPE(sdbus::Signature)HAS_DBUS_TYPE_SIGNATURE("g") TYPE(sdbus::Variant)HAS_DBUS_TYPE_SIGNATURE("v") @@ -135,6 +138,9 @@ namespace , double , const char* , std::string + , sdbus::BusName + , sdbus::InterfaceName + , sdbus::MemberName , sdbus::ObjectPath , sdbus::Signature , sdbus::Variant diff --git a/tests/unittests/Types_test.cpp b/tests/unittests/Types_test.cpp index 70dcd67..647bc0b 100644 --- a/tests/unittests/Types_test.cpp +++ b/tests/unittests/Types_test.cpp @@ -322,7 +322,6 @@ TEST(ASignature, CanBeMovedLikeAStdString) sdbus::Signature oSignature{aSignature}; ASSERT_THAT(sdbus::Signature{std::move(oSignature)}, Eq(sdbus::Signature(std::move(aSignature)))); - ASSERT_THAT(std::string(oSignature), Eq(aSignature)); } TEST(AUnixFd, DuplicatesAndOwnsFdUponStandardConstruction) @@ -428,17 +427,17 @@ TEST(AUnixFd, TakesOverNewFdAndClosesOriginalFdOnAdoptingReset) TEST(AnError, CanBeConstructedFromANameAndAMessage) { - auto error = sdbus::Error("name", "message"); - EXPECT_THAT(error.getName(), Eq("name")); + auto error = sdbus::Error(sdbus::Error::Name{"org.sdbuscpp.error"}, "message"); + EXPECT_THAT(error.getName(), Eq("org.sdbuscpp.error")); EXPECT_THAT(error.getMessage(), Eq("message")); } TEST(AnError, CanBeConstructedFromANameOnly) { - auto error1 = sdbus::Error("name"); - auto error2 = sdbus::Error("name", nullptr); - EXPECT_THAT(error1.getName(), Eq("name")); - EXPECT_THAT(error2.getName(), Eq("name")); + auto error1 = sdbus::Error(sdbus::Error::Name{"org.sdbuscpp.error"}); + auto error2 = sdbus::Error(sdbus::Error::Name{"org.sdbuscpp.error"}, nullptr); + EXPECT_THAT(error1.getName(), Eq("org.sdbuscpp.error")); + EXPECT_THAT(error2.getName(), Eq("org.sdbuscpp.error")); EXPECT_THAT(error1.getMessage(), Eq("")); EXPECT_THAT(error2.getMessage(), Eq("")); diff --git a/tools/xml2cpp-codegen/AdaptorGenerator.cpp b/tools/xml2cpp-codegen/AdaptorGenerator.cpp index 3c7c24c..1ee3f0d 100644 --- a/tools/xml2cpp-codegen/AdaptorGenerator.cpp +++ b/tools/xml2cpp-codegen/AdaptorGenerator.cpp @@ -82,7 +82,7 @@ std::string AdaptorGenerator::processInterface(Node& interface) const body << "class " << className << endl << "{" << endl << "public:" << endl - << tab << "static constexpr const char* INTERFACE_NAME = \"" << ifaceName << "\";" << endl << endl + << tab << "static inline const sdbus::InterfaceName INTERFACE_NAME{\"" << ifaceName << "\"};" << endl << endl << "protected:" << endl << tab << className << "(sdbus::IObject& object)" << endl << tab << tab << ": object_(&object)" << endl diff --git a/tools/xml2cpp-codegen/ProxyGenerator.cpp b/tools/xml2cpp-codegen/ProxyGenerator.cpp index 99225a7..f95a2fc 100644 --- a/tools/xml2cpp-codegen/ProxyGenerator.cpp +++ b/tools/xml2cpp-codegen/ProxyGenerator.cpp @@ -81,7 +81,7 @@ std::string ProxyGenerator::processInterface(Node& interface) const body << "class " << className << endl << "{" << endl << "public:" << endl - << tab << "static constexpr const char* INTERFACE_NAME = \"" << ifaceName << "\";" << endl << endl + << tab << "static inline const sdbus::InterfaceName INTERFACE_NAME{\"" << ifaceName << "\"};" << endl << endl << "protected:" << endl << tab << className << "(sdbus::IProxy& proxy)" << endl << tab << tab << ": proxy_(&proxy)" << endl