summaryrefslogtreecommitdiff
path: root/include
diff options
context:
space:
mode:
Diffstat (limited to 'include')
-rw-r--r--include/CommonAPI/DBus/DBusAddress.hpp53
-rw-r--r--include/CommonAPI/DBus/DBusAddressTranslator.hpp61
-rw-r--r--include/CommonAPI/DBus/DBusAttribute.hpp156
-rw-r--r--include/CommonAPI/DBus/DBusClientId.hpp48
-rw-r--r--include/CommonAPI/DBus/DBusConfig.hpp24
-rw-r--r--include/CommonAPI/DBus/DBusConnection.hpp246
-rw-r--r--include/CommonAPI/DBus/DBusDaemonProxy.hpp94
-rw-r--r--include/CommonAPI/DBus/DBusDeployment.hpp37
-rw-r--r--include/CommonAPI/DBus/DBusError.hpp45
-rw-r--r--include/CommonAPI/DBus/DBusEvent.hpp91
-rw-r--r--include/CommonAPI/DBus/DBusFactory.hpp114
-rw-r--r--include/CommonAPI/DBus/DBusFreedesktopAttribute.hpp451
-rw-r--r--include/CommonAPI/DBus/DBusFreedesktopPropertiesStub.hpp59
-rw-r--r--include/CommonAPI/DBus/DBusFreedesktopStubAdapterHelper.hpp194
-rw-r--r--include/CommonAPI/DBus/DBusFreedesktopVariant.hpp74
-rw-r--r--include/CommonAPI/DBus/DBusFunctionalHash.hpp81
-rw-r--r--include/CommonAPI/DBus/DBusHelper.hpp55
-rw-r--r--include/CommonAPI/DBus/DBusInputStream.hpp426
-rw-r--r--include/CommonAPI/DBus/DBusInstanceAvailabilityStatusChangedEvent.hpp135
-rw-r--r--include/CommonAPI/DBus/DBusInterfaceHandler.hpp31
-rw-r--r--include/CommonAPI/DBus/DBusMainLoopContext.hpp87
-rw-r--r--include/CommonAPI/DBus/DBusMessage.hpp101
-rw-r--r--include/CommonAPI/DBus/DBusMultiEvent.hpp118
-rw-r--r--include/CommonAPI/DBus/DBusObjectManager.hpp69
-rw-r--r--include/CommonAPI/DBus/DBusObjectManagerStub.hpp125
-rw-r--r--include/CommonAPI/DBus/DBusOutputStream.hpp398
-rw-r--r--include/CommonAPI/DBus/DBusProxy.hpp84
-rw-r--r--include/CommonAPI/DBus/DBusProxyAsyncCallbackHandler.hpp78
-rw-r--r--include/CommonAPI/DBus/DBusProxyBase.hpp72
-rw-r--r--include/CommonAPI/DBus/DBusProxyConnection.hpp127
-rw-r--r--include/CommonAPI/DBus/DBusProxyHelper.hpp258
-rw-r--r--include/CommonAPI/DBus/DBusProxyManager.hpp72
-rw-r--r--include/CommonAPI/DBus/DBusSelectiveEvent.hpp56
-rw-r--r--include/CommonAPI/DBus/DBusSerializableArguments.hpp30
-rw-r--r--include/CommonAPI/DBus/DBusServiceRegistry.hpp315
-rw-r--r--include/CommonAPI/DBus/DBusStubAdapter.hpp59
-rw-r--r--include/CommonAPI/DBus/DBusStubAdapterHelper.hpp674
-rw-r--r--include/CommonAPI/DBus/DBusTypeOutputStream.hpp153
-rw-r--r--include/CommonAPI/DBus/DBusTypes.hpp37
-rw-r--r--include/CommonAPI/DBus/DBusUtils.hpp37
-rw-r--r--include/murmurhash/MurmurHash3.h37
-rw-r--r--include/pugixml/pugiconfig.hpp69
-rw-r--r--include/pugixml/pugixml.hpp1265
43 files changed, 6796 insertions, 0 deletions
diff --git a/include/CommonAPI/DBus/DBusAddress.hpp b/include/CommonAPI/DBus/DBusAddress.hpp
new file mode 100644
index 0000000..926b11b
--- /dev/null
+++ b/include/CommonAPI/DBus/DBusAddress.hpp
@@ -0,0 +1,53 @@
+// Copyright (C) 2015 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#if !defined (COMMONAPI_INTERNAL_COMPILATION)
+#error "Only <CommonAPI/CommonAPI.hpp> can be included directly, this file may disappear or change contents."
+#endif
+
+#ifndef COMMONAPI_DBUS_ADDRESS_HPP_
+#define COMMONAPI_DBUS_ADDRESS_HPP_
+
+#include <iostream>
+#include <map>
+
+#include <CommonAPI/Export.hpp>
+
+namespace CommonAPI {
+namespace DBus {
+
+class DBusAddress {
+public:
+ COMMONAPI_EXPORT DBusAddress(const std::string &_service = "",
+ const std::string &_objectPath = "",
+ const std::string &_interface = "");
+ COMMONAPI_EXPORT DBusAddress(const DBusAddress &_source);
+ COMMONAPI_EXPORT virtual ~DBusAddress();
+
+ COMMONAPI_EXPORT bool operator==(const DBusAddress &_other) const;
+ COMMONAPI_EXPORT bool operator!=(const DBusAddress &_other) const;
+ COMMONAPI_EXPORT bool operator<(const DBusAddress &_other) const;
+
+ COMMONAPI_EXPORT const std::string &getInterface() const;
+ COMMONAPI_EXPORT void setInterface(const std::string &_interface);
+
+ COMMONAPI_EXPORT const std::string &getObjectPath() const;
+ COMMONAPI_EXPORT void setObjectPath(const std::string &_objectPath);
+
+ COMMONAPI_EXPORT const std::string &getService() const;
+ COMMONAPI_EXPORT void setService(const std::string &_service);
+
+private:
+ std::string service_;
+ std::string objectPath_;
+ std::string interface_;
+
+friend std::ostream &operator<<(std::ostream &_out, const DBusAddress &_dbusAddress);
+};
+
+} // namespace DBus
+} // namespace CommonAPI
+
+#endif // COMMONAPI_DBUS_ADDRESS_HPP_
diff --git a/include/CommonAPI/DBus/DBusAddressTranslator.hpp b/include/CommonAPI/DBus/DBusAddressTranslator.hpp
new file mode 100644
index 0000000..6d950e9
--- /dev/null
+++ b/include/CommonAPI/DBus/DBusAddressTranslator.hpp
@@ -0,0 +1,61 @@
+// Copyright (C) 2013-2015 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#if !defined (COMMONAPI_INTERNAL_COMPILATION)
+#error "Only <CommonAPI/CommonAPI.hpp> can be included directly, this file may disappear or change contents."
+#endif
+
+#ifndef COMMONAPI_DBUS_ADDRESSTRANSLATOR_HPP_
+#define COMMONAPI_DBUS_ADDRESSTRANSLATOR_HPP_
+
+#include <map>
+#include <memory>
+#include <mutex>
+
+#include <CommonAPI/Address.hpp>
+#include <CommonAPI/DBus/DBusAddress.hpp>
+
+namespace CommonAPI {
+namespace DBus {
+
+class DBusAddressTranslator {
+public:
+ COMMONAPI_EXPORT static std::shared_ptr<DBusAddressTranslator> get();
+
+ COMMONAPI_EXPORT DBusAddressTranslator();
+
+ COMMONAPI_EXPORT void init();
+
+ COMMONAPI_EXPORT bool translate(const std::string &_key, DBusAddress &_value);
+ COMMONAPI_EXPORT bool translate(const CommonAPI::Address &_key, DBusAddress &_value);
+
+ COMMONAPI_EXPORT bool translate(const DBusAddress &_key, std::string &_value);
+ COMMONAPI_EXPORT bool translate(const DBusAddress &_key, CommonAPI::Address &_value);
+
+ COMMONAPI_EXPORT void insert(const std::string &_address,
+ const std::string &_service, const std::string &_path, const std::string &_interface);
+
+private:
+ COMMONAPI_EXPORT bool readConfiguration();
+
+ COMMONAPI_EXPORT bool isValid(const std::string &, const char,
+ bool = false, bool = false, bool = false) const;
+
+private:
+ bool isDefault_;
+
+ std::string defaultConfig_;
+ std::string defaultDomain_;
+
+ std::map<CommonAPI::Address, DBusAddress> forwards_;
+ std::map<DBusAddress, CommonAPI::Address> backwards_;
+
+ std::mutex mutex_;
+};
+
+} // namespace DBus
+} // namespace CommonAPI
+
+#endif // COMMONAPI_DBUS_ADDRESSTRANSLATOR_HPP_
diff --git a/include/CommonAPI/DBus/DBusAttribute.hpp b/include/CommonAPI/DBus/DBusAttribute.hpp
new file mode 100644
index 0000000..3d9170d
--- /dev/null
+++ b/include/CommonAPI/DBus/DBusAttribute.hpp
@@ -0,0 +1,156 @@
+// Copyright (C) 2013-2015 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#if !defined (COMMONAPI_INTERNAL_COMPILATION)
+#error "Only <CommonAPI/CommonAPI.hpp> can be included directly, this file may disappear or change contents."
+#endif
+
+#ifndef COMMONAPI_DBUS_DBUS_ATTRIBUTE_HPP_
+#define COMMONAPI_DBUS_DBUS_ATTRIBUTE_HPP_
+
+#include <cassert>
+#include <cstdint>
+#include <tuple>
+
+#include <CommonAPI/DBus/DBusConfig.hpp>
+#include <CommonAPI/DBus/DBusEvent.hpp>
+#include <CommonAPI/DBus/DBusProxyHelper.hpp>
+
+namespace CommonAPI {
+namespace DBus {
+
+template <typename _AttributeType, typename _AttributeDepl = EmptyDeployment>
+class DBusReadonlyAttribute: public _AttributeType {
+public:
+ typedef typename _AttributeType::ValueType ValueType;
+ typedef _AttributeDepl ValueTypeDepl;
+ typedef typename _AttributeType::AttributeAsyncCallback AttributeAsyncCallback;
+
+ DBusReadonlyAttribute(DBusProxy &_proxy,
+ const char *setMethodSignature, const char *getMethodName,
+ _AttributeDepl *_depl = nullptr)
+ : proxy_(_proxy),
+ getMethodName_(getMethodName),
+ setMethodSignature_(setMethodSignature),
+ depl_(_depl) {
+ assert(getMethodName);
+ }
+
+ void getValue(CommonAPI::CallStatus &_status, ValueType &_value, const CommonAPI::CallInfo *_info) const {
+ CommonAPI::Deployable<ValueType, _AttributeDepl> deployedValue(depl_);
+ DBusProxyHelper<
+ DBusSerializableArguments<
+ >,
+ DBusSerializableArguments<
+ CommonAPI::Deployable<
+ ValueType,
+ _AttributeDepl
+ >
+ >
+ >::callMethodWithReply(proxy_, getMethodName_, "", (_info ? _info : &defaultCallInfo), _status, deployedValue);
+ _value = deployedValue.getValue();
+ }
+
+ std::future<CallStatus> getValueAsync(AttributeAsyncCallback _callback, const CommonAPI::CallInfo *_info) {
+ CommonAPI::Deployable<ValueType, _AttributeDepl> deployedValue(depl_);
+ return DBusProxyHelper<
+ DBusSerializableArguments<>,
+ DBusSerializableArguments<CommonAPI::Deployable<ValueType, _AttributeDepl>>
+ >::callMethodAsync(proxy_, getMethodName_, "", (_info ? _info : &defaultCallInfo),
+ [_callback](CommonAPI::CallStatus _status, CommonAPI::Deployable<ValueType, _AttributeDepl> _response) {
+ _callback(_status, _response.getValue());
+ },
+ std::make_tuple(deployedValue));
+ }
+
+ protected:
+ DBusProxy &proxy_;
+ const char *getMethodName_;
+ const char *setMethodSignature_;
+ _AttributeDepl *depl_;
+};
+
+template <typename _AttributeType, typename _AttributeDepl = EmptyDeployment>
+class DBusAttribute: public DBusReadonlyAttribute<_AttributeType, _AttributeDepl> {
+public:
+ typedef typename _AttributeType::ValueType ValueType;
+ typedef typename _AttributeType::AttributeAsyncCallback AttributeAsyncCallback;
+
+ DBusAttribute(DBusProxy &_proxy,
+ const char *_setMethodName, const char *_setMethodSignature, const char *_getMethodName,
+ _AttributeDepl *_depl = nullptr)
+ : DBusReadonlyAttribute<_AttributeType, _AttributeDepl>(_proxy, _setMethodSignature, _getMethodName, _depl),
+ setMethodName_(_setMethodName),
+ setMethodSignature_(_setMethodSignature) {
+ assert(_setMethodName);
+ assert(_setMethodSignature);
+ }
+
+ void setValue(const ValueType &_request, CommonAPI::CallStatus &_status, ValueType &_response, const CommonAPI::CallInfo *_info) {
+ CommonAPI::Deployable<ValueType, _AttributeDepl> deployedRequest(_request, this->depl_);
+ CommonAPI::Deployable<ValueType, _AttributeDepl> deployedResponse(this->depl_);
+ DBusProxyHelper<DBusSerializableArguments<CommonAPI::Deployable<ValueType, _AttributeDepl>>,
+ DBusSerializableArguments<CommonAPI::Deployable<ValueType, _AttributeDepl>> >::callMethodWithReply(
+ this->proxy_,
+ setMethodName_,
+ setMethodSignature_,
+ (_info ? _info : &defaultCallInfo),
+ deployedRequest,
+ _status,
+ deployedResponse);
+ _response = deployedResponse.getValue();
+ }
+
+
+ std::future<CallStatus> setValueAsync(const ValueType &_request, AttributeAsyncCallback _callback, const CommonAPI::CallInfo *_info) {
+ CommonAPI::Deployable<ValueType, _AttributeDepl> deployedRequest(_request, this->depl_);
+ CommonAPI::Deployable<ValueType, _AttributeDepl> deployedResponse(this->depl_);
+ return DBusProxyHelper<DBusSerializableArguments<CommonAPI::Deployable<ValueType, _AttributeDepl>>,
+ DBusSerializableArguments<CommonAPI::Deployable<ValueType, _AttributeDepl>> >::callMethodAsync(
+ this->proxy_,
+ setMethodName_,
+ setMethodSignature_,
+ (_info ? _info : &defaultCallInfo),
+ deployedRequest,
+ [_callback](CommonAPI::CallStatus _status, CommonAPI::Deployable<ValueType, _AttributeDepl> _response) {
+ _callback(_status, _response.getValue());
+ },
+ std::make_tuple(deployedResponse));
+ }
+
+ protected:
+ const char* setMethodName_;
+ const char* setMethodSignature_;
+};
+
+template <typename _AttributeType>
+class DBusObservableAttribute: public _AttributeType {
+public:
+ typedef typename _AttributeType::ValueType ValueType;
+ typedef typename _AttributeType::ValueTypeDepl ValueTypeDepl;
+ typedef typename _AttributeType::AttributeAsyncCallback AttributeAsyncCallback;
+ typedef typename _AttributeType::ChangedEvent ChangedEvent;
+
+ template <typename... _AttributeTypeArguments>
+ DBusObservableAttribute(DBusProxy &_proxy,
+ const char *_changedEventName,
+ _AttributeTypeArguments... arguments)
+ : _AttributeType(_proxy, arguments...),
+ changedEvent_(_proxy, _changedEventName, this->setMethodSignature_,
+ std::make_tuple(CommonAPI::Deployable<ValueType, ValueTypeDepl>(this->depl_))) {
+ }
+
+ ChangedEvent &getChangedEvent() {
+ return changedEvent_;
+ }
+
+ protected:
+ DBusEvent<ChangedEvent, CommonAPI::Deployable<ValueType, ValueTypeDepl> > changedEvent_;
+};
+
+} // namespace DBus
+} // namespace CommonAPI
+
+#endif // COMMONAPI_DBUS_DBUS_ATTRIBUTE_HPP_
diff --git a/include/CommonAPI/DBus/DBusClientId.hpp b/include/CommonAPI/DBus/DBusClientId.hpp
new file mode 100644
index 0000000..72dc1c5
--- /dev/null
+++ b/include/CommonAPI/DBus/DBusClientId.hpp
@@ -0,0 +1,48 @@
+// Copyright (C) 2013-2015 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#if !defined (COMMONAPI_INTERNAL_COMPILATION)
+#error "Only <CommonAPI/CommonAPI.hpp> can be included directly, this file may disappear or change contents."
+#endif
+
+#ifndef COMMONAPI_DBUS_DBUSCLIENTID_HPP_
+#define COMMONAPI_DBUS_DBUSCLIENTID_HPP_
+
+#include <CommonAPI/Export.hpp>
+#include <CommonAPI/Types.hpp>
+
+namespace CommonAPI {
+namespace DBus {
+
+class DBusMessage;
+
+/**
+ * \brief Implementation of CommonAPI::ClientId for DBus
+ *
+ * This class represents the DBus specific implementation of CommonAPI::ClientId.
+ * It internally uses a string to identify clients. This string is the unique sender id used by dbus.
+ */
+class DBusClientId
+ : public CommonAPI::ClientId {
+ friend struct std::hash<DBusClientId>;
+
+public:
+ COMMONAPI_EXPORT DBusClientId(std::string dbusId);
+
+ COMMONAPI_EXPORT bool operator==(CommonAPI::ClientId& clientIdToCompare);
+ COMMONAPI_EXPORT bool operator==(DBusClientId& clientIdToCompare);
+ COMMONAPI_EXPORT size_t hashCode();
+
+ COMMONAPI_EXPORT const char * getDBusId();
+
+ COMMONAPI_EXPORT DBusMessage createMessage(const std::string objectPath, const std::string interfaceName, const std::string signalName) const;
+protected:
+ std::string dbusId_;
+};
+
+} // namespace DBus
+} // namespace CommonAPI
+
+#endif // DBUSCLIENTID_HPP_
diff --git a/include/CommonAPI/DBus/DBusConfig.hpp b/include/CommonAPI/DBus/DBusConfig.hpp
new file mode 100644
index 0000000..dae6b7a
--- /dev/null
+++ b/include/CommonAPI/DBus/DBusConfig.hpp
@@ -0,0 +1,24 @@
+// Copyright (C) 2013-2015 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#if !defined (COMMONAPI_INTERNAL_COMPILATION)
+#error "Only <CommonAPI/CommonAPI.hpp> can be included directly, this file may disappear or change contents."
+#endif
+
+#ifndef COMMONAPI_DBUS_DBUSCONFIG_HPP_
+#define COMMONAPI_DBUS_DBUSCONFIG_HPP_
+
+#include <CommonAPI/CallInfo.hpp>
+
+namespace CommonAPI {
+namespace DBus {
+
+static const Timeout_t DEFAULT_SEND_TIMEOUT_MS = 5000;
+static CommonAPI::CallInfo defaultCallInfo(DEFAULT_SEND_TIMEOUT_MS);
+
+} // namespace DBus
+} // namespace CommonAPI
+
+#endif // COMMONAPI_DBUS_DBUSCONFIG_HPP_
diff --git a/include/CommonAPI/DBus/DBusConnection.hpp b/include/CommonAPI/DBus/DBusConnection.hpp
new file mode 100644
index 0000000..436cfab
--- /dev/null
+++ b/include/CommonAPI/DBus/DBusConnection.hpp
@@ -0,0 +1,246 @@
+// Copyright (C) 2013-2015 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#if !defined (COMMONAPI_INTERNAL_COMPILATION)
+#error "Only <CommonAPI/CommonAPI.hpp> can be included directly, this file may disappear or change contents."
+#endif
+
+#ifndef COMMONAPI_DBUS_DBUS_CONNECTION_HPP_
+#define COMMONAPI_DBUS_DBUS_CONNECTION_HPP_
+
+#include <atomic>
+
+#include <dbus/dbus.h>
+
+#include <CommonAPI/DBus/DBusConfig.hpp>
+#include <CommonAPI/DBus/DBusDaemonProxy.hpp>
+#include <CommonAPI/DBus/DBusMainLoopContext.hpp>
+#include <CommonAPI/DBus/DBusObjectManager.hpp>
+#include <CommonAPI/DBus/DBusProxyConnection.hpp>
+#include <CommonAPI/DBus/DBusServiceRegistry.hpp>
+
+namespace CommonAPI {
+namespace DBus {
+
+class DBusObjectManager;
+
+class DBusConnectionStatusEvent
+ : public DBusProxyConnection::ConnectionStatusEvent {
+public:
+ DBusConnectionStatusEvent(DBusConnection* dbusConnection);
+ virtual ~DBusConnectionStatusEvent() {}
+
+ protected:
+ virtual void onListenerAdded(const Listener& listener);
+
+ // TODO: change to std::weak_ptr<DBusConnection> connection_;
+ DBusConnection* dbusConnection_;
+
+friend class DBusConnection;
+};
+
+struct WatchContext {
+ WatchContext(std::weak_ptr<MainLoopContext> mainLoopContext, DispatchSource* dispatchSource) :
+ mainLoopContext_(mainLoopContext), dispatchSource_(dispatchSource) {
+ }
+
+ std::weak_ptr<MainLoopContext> mainLoopContext_;
+ DispatchSource* dispatchSource_;
+};
+
+class DBusConnection
+ : public DBusProxyConnection,
+ public std::enable_shared_from_this<DBusConnection> {
+public:
+ COMMONAPI_EXPORT static std::shared_ptr<DBusConnection> getBus(const DBusType_t &_type);
+ COMMONAPI_EXPORT static std::shared_ptr<DBusConnection> wrap(::DBusConnection *_connection);
+
+ COMMONAPI_EXPORT DBusConnection(DBusType_t _type);
+ COMMONAPI_EXPORT DBusConnection(const DBusConnection&) = delete;
+ COMMONAPI_EXPORT DBusConnection(::DBusConnection* libDbusConnection);
+ COMMONAPI_EXPORT virtual ~DBusConnection();
+
+ COMMONAPI_EXPORT DBusConnection& operator=(const DBusConnection&) = delete;
+
+ COMMONAPI_EXPORT DBusType_t getBusType() const;
+
+ COMMONAPI_EXPORT bool connect(bool startDispatchThread = true);
+ COMMONAPI_EXPORT bool connect(DBusError& dbusError, bool startDispatchThread = true);
+ COMMONAPI_EXPORT void disconnect();
+
+ COMMONAPI_EXPORT virtual bool isConnected() const;
+
+ COMMONAPI_EXPORT virtual ConnectionStatusEvent& getConnectionStatusEvent();
+
+ COMMONAPI_EXPORT virtual bool requestServiceNameAndBlock(const std::string& serviceName) const;
+ COMMONAPI_EXPORT virtual bool releaseServiceName(const std::string& serviceName) const;
+
+ COMMONAPI_EXPORT bool sendDBusMessage(const DBusMessage& dbusMessage/*, uint32_t* allocatedSerial = NULL*/) const;
+
+ COMMONAPI_EXPORT std::future<CallStatus> sendDBusMessageWithReplyAsync(
+ const DBusMessage& dbusMessage,
+ std::unique_ptr<DBusMessageReplyAsyncHandler> dbusMessageReplyAsyncHandler,
+ const CommonAPI::CallInfo *_info) const;
+
+ COMMONAPI_EXPORT DBusMessage sendDBusMessageWithReplyAndBlock(const DBusMessage& dbusMessage,
+ DBusError& dbusError,
+ const CommonAPI::CallInfo *_info) const;
+
+ COMMONAPI_EXPORT virtual bool addObjectManagerSignalMemberHandler(const std::string& dbusBusName,
+ DBusSignalHandler* dbusSignalHandler);
+ COMMONAPI_EXPORT virtual bool removeObjectManagerSignalMemberHandler(const std::string& dbusBusName,
+ DBusSignalHandler* dbusSignalHandler);
+
+ COMMONAPI_EXPORT DBusSignalHandlerToken addSignalMemberHandler(const std::string& objectPath,
+ const std::string& interfaceName,
+ const std::string& interfaceMemberName,
+ const std::string& inuint32_tterfaceMemberSignature,
+ DBusSignalHandler* dbusSignalHandler,
+ const bool justAddFilter = false);
+
+ COMMONAPI_EXPORT DBusProxyConnection::DBusSignalHandlerToken subscribeForSelectiveBroadcast(bool& subscriptionAccepted,
+ const std::string& objectPath,
+ const std::string& interfaceName,
+ const std::string& interfaceMemberName,
+ const std::string& interfaceMemberSignature,
+ DBusSignalHandler* dbusSignalHandler,
+ DBusProxy* callingProxy);
+
+ COMMONAPI_EXPORT void unsubscribeFromSelectiveBroadcast(const std::string& eventName,
+ DBusProxyConnection::DBusSignalHandlerToken subscription,
+ DBusProxy* callingProxy,
+ const DBusSignalHandler* dbusSignalHandler);
+
+ COMMONAPI_EXPORT void registerObjectPath(const std::string& objectPath);
+ COMMONAPI_EXPORT void unregisterObjectPath(const std::string& objectPath);
+
+ COMMONAPI_EXPORT bool removeSignalMemberHandler(const DBusSignalHandlerToken& dbusSignalHandlerToken,
+ const DBusSignalHandler* dbusSignalHandler = NULL);
+ COMMONAPI_EXPORT bool readWriteDispatch(int timeoutMilliseconds = -1);
+
+ COMMONAPI_EXPORT virtual const std::shared_ptr<DBusObjectManager> getDBusObjectManager();
+
+ COMMONAPI_EXPORT void setObjectPathMessageHandler(DBusObjectPathMessageHandler);
+ COMMONAPI_EXPORT bool isObjectPathMessageHandlerSet();
+
+ COMMONAPI_EXPORT virtual bool attachMainLoopContext(std::weak_ptr<MainLoopContext>);
+
+ COMMONAPI_EXPORT bool isDispatchReady();
+ COMMONAPI_EXPORT bool singleDispatch();
+
+ typedef std::tuple<std::string, std::string, std::string> DBusSignalMatchRuleTuple;
+ typedef std::pair<uint32_t, std::string> DBusSignalMatchRuleMapping;
+ typedef std::unordered_map<DBusSignalMatchRuleTuple, DBusSignalMatchRuleMapping> DBusSignalMatchRulesMap;
+ private:
+ COMMONAPI_EXPORT void dispatch();
+ COMMONAPI_EXPORT void suspendDispatching() const;
+ COMMONAPI_EXPORT void resumeDispatching() const;
+
+ std::thread* dispatchThread_;
+ bool stopDispatching_;
+
+ std::weak_ptr<MainLoopContext> mainLoopContext_;
+ DispatchSource* dispatchSource_;
+ WatchContext* watchContext_;
+
+ mutable std::recursive_mutex sendLock_;
+ mutable bool pauseDispatching_;
+ mutable std::mutex dispatchSuspendLock_;
+
+ COMMONAPI_EXPORT void addLibdbusSignalMatchRule(const std::string& objectPath,
+ const std::string& interfaceName,
+ const std::string& interfaceMemberName,
+ const bool justAddFilter = false);
+
+ COMMONAPI_EXPORT void removeLibdbusSignalMatchRule(const std::string& objectPath,
+ const std::string& interfaceName,
+ const std::string& interfaceMemberName);
+
+ COMMONAPI_EXPORT void initLibdbusSignalFilterAfterConnect();
+ ::DBusHandlerResult onLibdbusSignalFilter(::DBusMessage* libdbusMessage);
+
+ COMMONAPI_EXPORT void initLibdbusObjectPathHandlerAfterConnect();
+ ::DBusHandlerResult onLibdbusObjectPathMessage(::DBusMessage* libdbusMessage);
+
+ COMMONAPI_EXPORT static void onLibdbusPendingCallNotifyThunk(::DBusPendingCall* libdbusPendingCall, void* userData);
+ COMMONAPI_EXPORT static void onLibdbusDataCleanup(void* userData);
+
+ COMMONAPI_EXPORT static ::DBusHandlerResult onLibdbusObjectPathMessageThunk(::DBusConnection* libdbusConnection,
+ ::DBusMessage* libdbusMessage,
+ void* userData);
+
+ COMMONAPI_EXPORT static ::DBusHandlerResult onLibdbusSignalFilterThunk(::DBusConnection* libdbusConnection,
+ ::DBusMessage* libdbusMessage,
+ void* userData);
+
+ COMMONAPI_EXPORT static dbus_bool_t onAddWatch(::DBusWatch* libdbusWatch, void* data);
+ COMMONAPI_EXPORT static void onRemoveWatch(::DBusWatch* libdbusWatch, void* data);
+ COMMONAPI_EXPORT static void onToggleWatch(::DBusWatch* libdbusWatch, void* data);
+
+ COMMONAPI_EXPORT static dbus_bool_t onAddTimeout(::DBusTimeout* dbus_timeout, void* data);
+ COMMONAPI_EXPORT static void onRemoveTimeout(::DBusTimeout* dbus_timeout, void* data);
+ COMMONAPI_EXPORT static void onToggleTimeout(::DBusTimeout* dbus_timeout, void* data);
+
+ COMMONAPI_EXPORT static void onWakeupMainContext(void* data);
+
+ COMMONAPI_EXPORT void enforceAsynchronousTimeouts() const;
+ COMMONAPI_EXPORT static const DBusObjectPathVTable* getDBusObjectPathVTable();
+
+ ::DBusConnection* connection_;
+ mutable std::mutex connectionGuard_;
+
+ std::mutex signalGuard_;
+ std::mutex objectManagerGuard_;
+ std::mutex serviceRegistryGuard_;
+
+ DBusType_t busType_;
+
+ std::shared_ptr<DBusObjectManager> dbusObjectManager_;
+
+ DBusConnectionStatusEvent dbusConnectionStatusEvent_;
+
+ DBusSignalMatchRulesMap dbusSignalMatchRulesMap_;
+
+ DBusSignalHandlerTable dbusSignalHandlerTable_;
+
+ std::unordered_map<std::string, size_t> dbusObjectManagerSignalMatchRulesMap_;
+ std::unordered_multimap<std::string, DBusSignalHandler*> dbusObjectManagerSignalHandlerTable_;
+ std::mutex dbusObjectManagerSignalGuard_;
+
+ COMMONAPI_EXPORT bool addObjectManagerSignalMatchRule(const std::string& dbusBusName);
+ COMMONAPI_EXPORT bool removeObjectManagerSignalMatchRule(const std::string& dbusBusName);
+
+ COMMONAPI_EXPORT bool addLibdbusSignalMatchRule(const std::string& dbusMatchRule);
+ COMMONAPI_EXPORT bool removeLibdbusSignalMatchRule(const std::string& dbusMatchRule);
+
+ std::atomic_size_t libdbusSignalMatchRulesCount_;
+
+ // objectPath, referenceCount
+ typedef std::unordered_map<std::string, uint32_t> LibdbusRegisteredObjectPathHandlersTable;
+ LibdbusRegisteredObjectPathHandlersTable libdbusRegisteredObjectPaths_;
+
+ DBusObjectPathMessageHandler dbusObjectMessageHandler_;
+
+ mutable std::unordered_map<std::string, uint16_t> connectionNameCount_;
+
+ typedef std::pair<DBusPendingCall*, std::tuple<int, DBusMessageReplyAsyncHandler*, DBusMessage> > TimeoutMapElement;
+ mutable std::map<DBusPendingCall*, std::tuple<int, DBusMessageReplyAsyncHandler*, DBusMessage>> timeoutMap_;
+
+ typedef std::pair<DBusMessageReplyAsyncHandler *, DBusMessage> MainloopTimeout_t;
+ mutable std::list<MainloopTimeout_t> mainloopTimeouts_;
+
+ mutable std::mutex enforceTimeoutMutex_;
+ mutable std::condition_variable enforceTimeoutCondition_;
+
+ mutable std::shared_ptr<std::thread> enforcerThread_;
+ mutable std::mutex enforcerThreadMutex_;
+ bool enforcerThreadCancelled_;
+};
+
+
+} // namespace DBus
+} // namespace CommonAPI
+
+#endif // COMMONAPI_DBUS_DBUS_CONNECTION_HPP_
diff --git a/include/CommonAPI/DBus/DBusDaemonProxy.hpp b/include/CommonAPI/DBus/DBusDaemonProxy.hpp
new file mode 100644
index 0000000..1333548
--- /dev/null
+++ b/include/CommonAPI/DBus/DBusDaemonProxy.hpp
@@ -0,0 +1,94 @@
+// Copyright (C) 2013-2015 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#if !defined (COMMONAPI_INTERNAL_COMPILATION)
+#error "Only <CommonAPI/CommonAPI.hpp> can be included directly, this file may disappear or change contents."
+#endif
+
+#ifndef COMMONAPI_DBUS_DBUS_DAEMON_PROXY_HPP_
+#define COMMONAPI_DBUS_DBUS_DAEMON_PROXY_HPP_
+
+#include <functional>
+#include <string>
+#include <vector>
+
+#include <CommonAPI/Address.hpp>
+
+#include <CommonAPI/DBus/DBusAttribute.hpp>
+#include <CommonAPI/DBus/DBusEvent.hpp>
+#include <CommonAPI/DBus/DBusProxyBase.hpp>
+
+namespace CommonAPI {
+namespace DBus {
+
+class StaticInterfaceVersionAttribute: public InterfaceVersionAttribute {
+ public:
+ StaticInterfaceVersionAttribute(const uint32_t& majorValue, const uint32_t& minorValue);
+
+ void getValue(CommonAPI::CallStatus& callStatus, Version &_version, const CommonAPI::CallInfo *_info) const;
+ std::future<CommonAPI::CallStatus> getValueAsync(AttributeAsyncCallback _callback, const CommonAPI::CallInfo *_info);
+
+ private:
+ Version version_;
+};
+
+
+class DBusDaemonProxy : public DBusProxyBase {
+ public:
+ typedef Event<std::string, std::string, std::string> NameOwnerChangedEvent;
+
+ typedef std::unordered_map<std::string, int> PropertyDictStub;
+ typedef std::unordered_map<std::string, PropertyDictStub> InterfaceToPropertyDict;
+ typedef std::unordered_map<std::string, InterfaceToPropertyDict> DBusObjectToInterfaceDict;
+
+ typedef std::function<void(const CommonAPI::CallStatus&, std::vector<std::string>)> ListNamesAsyncCallback;
+ typedef std::function<void(const CommonAPI::CallStatus&, bool)> NameHasOwnerAsyncCallback;
+ typedef std::function<void(const CommonAPI::CallStatus&, DBusObjectToInterfaceDict)> GetManagedObjectsAsyncCallback;
+ typedef std::function<void(const CommonAPI::CallStatus&, std::string)> GetNameOwnerAsyncCallback;
+
+ COMMONAPI_EXPORT DBusDaemonProxy(const std::shared_ptr<DBusProxyConnection>& dbusConnection);
+ COMMONAPI_EXPORT virtual ~DBusDaemonProxy() {}
+
+ COMMONAPI_EXPORT virtual bool isAvailable() const;
+ COMMONAPI_EXPORT virtual bool isAvailableBlocking() const;
+ COMMONAPI_EXPORT virtual ProxyStatusEvent& getProxyStatusEvent();
+
+ COMMONAPI_EXPORT virtual InterfaceVersionAttribute& getInterfaceVersionAttribute();
+
+ COMMONAPI_EXPORT void init();
+
+ COMMONAPI_EXPORT static const char* getInterfaceId();
+
+ COMMONAPI_EXPORT NameOwnerChangedEvent& getNameOwnerChangedEvent();
+
+ COMMONAPI_EXPORT void listNames(CommonAPI::CallStatus& callStatus, std::vector<std::string>& busNames) const;
+ COMMONAPI_EXPORT std::future<CallStatus> listNamesAsync(ListNamesAsyncCallback listNamesAsyncCallback) const;
+
+ COMMONAPI_EXPORT void nameHasOwner(const std::string& busName, CommonAPI::CallStatus& callStatus, bool& hasOwner) const;
+ COMMONAPI_EXPORT std::future<CallStatus> nameHasOwnerAsync(const std::string& busName,
+ NameHasOwnerAsyncCallback nameHasOwnerAsyncCallback) const;
+
+ COMMONAPI_EXPORT std::future<CallStatus> getManagedObjectsAsync(const std::string& forDBusServiceName,
+ GetManagedObjectsAsyncCallback) const;
+
+ /**
+ * Get the unique connection/bus name of the primary owner of the name given
+ *
+ * @param busName Name to get the owner of
+ * @param getNameOwnerAsyncCallback callback functor
+ *
+ * @return CallStatus::REMOTE_ERROR if the name is unknown, otherwise CallStatus::SUCCESS and the uniq name of the owner
+ */
+ std::future<CallStatus> getNameOwnerAsync(const std::string& busName, GetNameOwnerAsyncCallback getNameOwnerAsyncCallback) const;
+
+ private:
+ DBusEvent<NameOwnerChangedEvent, std::string, std::string, std::string> nameOwnerChangedEvent_;
+ StaticInterfaceVersionAttribute interfaceVersionAttribute_;
+};
+
+} // namespace DBus
+} // namespace CommonAPI
+
+#endif // COMMONAPI_DBUS_DBUS_DAEMON_PROXY_HPP_
diff --git a/include/CommonAPI/DBus/DBusDeployment.hpp b/include/CommonAPI/DBus/DBusDeployment.hpp
new file mode 100644
index 0000000..21ad78a
--- /dev/null
+++ b/include/CommonAPI/DBus/DBusDeployment.hpp
@@ -0,0 +1,37 @@
+// Copyright (C) 2014-2015 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#if !defined (COMMONAPI_INTERNAL_COMPILATION)
+#error "Only <CommonAPI/CommonAPI.hpp> can be included directly, this file may disappear or change contents."
+#endif
+
+#ifndef COMMONAPI_DBUS_DBUSDEPLOYMENTS_HPP_
+#define COMMONAPI_DBUS_DBUSDEPLOYMENTS_HPP_
+
+#include <string>
+#include <unordered_map>
+
+#include <CommonAPI/Deployment.hpp>
+#include <CommonAPI/Export.hpp>
+
+namespace CommonAPI {
+namespace DBus {
+
+template<typename... _Types>
+struct VariantDeployment : CommonAPI::Deployment<_Types...> {
+ VariantDeployment(bool _isFreeDesktop, _Types*... _t)
+ : CommonAPI::Deployment<_Types...>(_t...),
+ isFreeDesktop_(_isFreeDesktop) {
+ }
+
+ bool isFreeDesktop_;
+};
+
+extern COMMONAPI_IMPORT_EXPORT VariantDeployment<> freedesktopVariant;
+
+} // namespace DBus
+} // namespace CommonAPI
+
+#endif // COMMONAPI_DBUS_DBUSDEPLOYMENTS_HPP_
diff --git a/include/CommonAPI/DBus/DBusError.hpp b/include/CommonAPI/DBus/DBusError.hpp
new file mode 100644
index 0000000..6e8f170
--- /dev/null
+++ b/include/CommonAPI/DBus/DBusError.hpp
@@ -0,0 +1,45 @@
+// Copyright (C) 2013-2015 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#if !defined (COMMONAPI_INTERNAL_COMPILATION)
+#error "Only <CommonAPI/CommonAPI.hpp> can be included directly, this file may disappear or change contents."
+#endif
+
+#ifndef COMMONAPI_DBUS_DBUS_ERROR_HPP_
+#define COMMONAPI_DBUS_DBUS_ERROR_HPP_
+
+#include <string>
+#include <dbus/dbus.h>
+
+#include <CommonAPI/Export.hpp>
+
+namespace CommonAPI {
+namespace DBus {
+
+class DBusConnection;
+
+
+class COMMONAPI_EXPORT DBusError {
+ public:
+ DBusError();
+ ~DBusError();
+
+ operator bool() const;
+
+ void clear();
+
+ std::string getName() const;
+ std::string getMessage() const;
+
+ private:
+ ::DBusError libdbusError_;
+
+ friend class DBusConnection;
+};
+
+} // namespace DBus
+} // namespace CommonAPI
+
+#endif // COMMONAPI_DBUS_DBUS_ERROR_HPP_
diff --git a/include/CommonAPI/DBus/DBusEvent.hpp b/include/CommonAPI/DBus/DBusEvent.hpp
new file mode 100644
index 0000000..a3bfe01
--- /dev/null
+++ b/include/CommonAPI/DBus/DBusEvent.hpp
@@ -0,0 +1,91 @@
+// Copyright (C) 2013-2015 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#if !defined (COMMONAPI_INTERNAL_COMPILATION)
+#error "Only <CommonAPI/CommonAPI.hpp> can be included directly, this file may disappear or change contents."
+#endif
+
+#ifndef COMMONAPI_DBUS_DBUS_EVENT_HPP_
+#define COMMONAPI_DBUS_DBUS_EVENT_HPP_
+
+#include <CommonAPI/Event.hpp>
+#include <CommonAPI/DBus/DBusAddress.hpp>
+#include <CommonAPI/DBus/DBusHelper.hpp>
+#include <CommonAPI/DBus/DBusMessage.hpp>
+#include <CommonAPI/DBus/DBusProxyBase.hpp>
+#include <CommonAPI/DBus/DBusProxyConnection.hpp>
+#include <CommonAPI/DBus/DBusSerializableArguments.hpp>
+
+namespace CommonAPI {
+namespace DBus {
+
+template <typename _Event, typename... _Arguments>
+class DBusEvent: public _Event, public DBusProxyConnection::DBusSignalHandler {
+public:
+ typedef typename _Event::Listener Listener;
+
+ DBusEvent(DBusProxyBase &_proxy,
+ const std::string &_name, const std::string &_signature,
+ std::tuple<_Arguments...> _arguments)
+ : proxy_(_proxy),
+ name_(_name), signature_(_signature),
+ arguments_(_arguments) {
+
+ interface_ = proxy_.getDBusAddress().getInterface();
+ path_ = proxy_.getDBusAddress().getObjectPath();
+ }
+
+ DBusEvent(DBusProxyBase &_proxy,
+ const std::string &_name, const std::string &_signature,
+ const std::string &_path, const std::string &_interface,
+ std::tuple<_Arguments...> _arguments)
+ : proxy_(_proxy),
+ name_(_name), signature_(_signature),
+ path_(_path), interface_(_interface),
+ arguments_(_arguments) {
+ }
+
+ virtual ~DBusEvent() {
+ proxy_.removeSignalMemberHandler(subscription_, this);
+ }
+
+ virtual void onSignalDBusMessage(const DBusMessage &_message) {
+ handleSignalDBusMessage(_message, typename make_sequence<sizeof...(_Arguments)>::type());
+ }
+ protected:
+ virtual void onFirstListenerAdded(const Listener&) {
+ subscription_ = proxy_.addSignalMemberHandler(
+ path_, interface_, name_, signature_, this);
+ }
+
+ virtual void onLastListenerRemoved(const Listener&) {
+ proxy_.removeSignalMemberHandler(subscription_, this);
+ }
+
+ template<int ... _Indices>
+ inline void handleSignalDBusMessage(const DBusMessage &_message, index_sequence<_Indices...>) {
+ DBusInputStream input(_message);
+ if (DBusSerializableArguments<
+ _Arguments...
+ >::deserialize(input, std::get<_Indices>(arguments_)...)) {
+ this->notifyListeners(std::get<_Indices>(arguments_)...);
+ }
+ }
+
+ DBusProxyBase &proxy_;
+
+ std::string name_;
+ std::string signature_;
+ std::string path_;
+ std::string interface_;
+
+ DBusProxyConnection::DBusSignalHandlerToken subscription_;
+ std::tuple<_Arguments...> arguments_;
+};
+
+} // namespace DBus
+} // namespace CommonAPI
+
+#endif // COMMONAPI_DBUS_DBUS_EVENT_HPP_
diff --git a/include/CommonAPI/DBus/DBusFactory.hpp b/include/CommonAPI/DBus/DBusFactory.hpp
new file mode 100644
index 0000000..fa0808b
--- /dev/null
+++ b/include/CommonAPI/DBus/DBusFactory.hpp
@@ -0,0 +1,114 @@
+// Copyright (C) 2013-2015 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#if !defined (COMMONAPI_INTERNAL_COMPILATION)
+#error "Only <CommonAPI/CommonAPI.hpp> can be included directly, this file may disappear or change contents."
+#endif
+
+#ifndef COMMONAPI_DBUS_FACTORY_HPP_
+#define COMMONAPI_DBUS_FACTORY_HPP_
+
+#include <map>
+
+#include <CommonAPI/Export.hpp>
+#include <CommonAPI/Factory.hpp>
+#include <CommonAPI/DBus/DBusTypes.hpp>
+
+namespace CommonAPI {
+namespace DBus {
+
+class DBusAddress;
+class DBusProxy;
+class DBusProxyConnection;
+class DBusStubAdapter;
+
+typedef std::shared_ptr<DBusProxy>
+(*ProxyCreateFunction)(const DBusAddress &_address,
+ const std::shared_ptr<DBusProxyConnection> &_connection);
+
+typedef std::shared_ptr<DBusStubAdapter>
+(*StubAdapterCreateFunction) (const DBusAddress &_address,
+ const std::shared_ptr<DBusProxyConnection> &_connection,
+ const std::shared_ptr<StubBase> &_stub);
+
+class Factory : public CommonAPI::Factory {
+public:
+ COMMONAPI_EXPORT static std::shared_ptr<Factory> get();
+
+ COMMONAPI_EXPORT Factory();
+ COMMONAPI_EXPORT virtual ~Factory();
+
+ COMMONAPI_EXPORT void registerProxyCreateMethod(const std::string &_address,
+ ProxyCreateFunction _function);
+
+ COMMONAPI_EXPORT void registerStubAdapterCreateMethod(const std::string &_address,
+ StubAdapterCreateFunction _function);
+
+
+ COMMONAPI_EXPORT std::shared_ptr<Proxy> createProxy(const std::string &_domain,
+ const std::string &_interface,
+ const std::string &_instance,
+ const ConnectionId_t &_connectionId);
+
+ COMMONAPI_EXPORT std::shared_ptr<Proxy> createProxy(const std::string &_domain,
+ const std::string &_interface,
+ const std::string &_instance,
+ std::shared_ptr<MainLoopContext> _context);
+
+ COMMONAPI_EXPORT bool registerStub(const std::string &_domain,
+ const std::string &_interface,
+ const std::string &_instance,
+ std::shared_ptr<StubBase> _stub,
+ const ConnectionId_t &_connectionId);
+
+ COMMONAPI_EXPORT bool registerStub(const std::string &_domain,
+ const std::string &_interface,
+ const std::string &_instance,
+ std::shared_ptr<StubBase> _stub,
+ std::shared_ptr<MainLoopContext> _context);
+
+ COMMONAPI_EXPORT bool unregisterStub(const std::string &_domain,
+ const std::string &_interface,
+ const std::string &_instance);
+
+ // Services
+ COMMONAPI_EXPORT std::shared_ptr<DBusStubAdapter> getRegisteredService(const std::string &_address);
+
+ // Managed services
+ COMMONAPI_EXPORT std::shared_ptr<DBusStubAdapter> createDBusStubAdapter(const std::shared_ptr<StubBase> &_stub,
+ const std::string &_interface,
+ const DBusAddress &_address,
+ const std::shared_ptr<DBusProxyConnection> &_connection);
+ COMMONAPI_EXPORT bool registerManagedService(const std::shared_ptr<DBusStubAdapter> &_adapter);
+ COMMONAPI_EXPORT bool unregisterManagedService(const std::string &_address);
+
+private:
+ COMMONAPI_EXPORT std::shared_ptr<DBusConnection> getConnection(const ConnectionId_t &);
+ COMMONAPI_EXPORT std::shared_ptr<DBusConnection> getConnection(std::shared_ptr<MainLoopContext>);
+ COMMONAPI_EXPORT bool registerStubAdapter(std::shared_ptr<DBusStubAdapter>);
+ COMMONAPI_EXPORT bool unregisterStubAdapter(std::shared_ptr<DBusStubAdapter>);
+
+ // Managed services
+ typedef std::unordered_map<std::string, std::shared_ptr<DBusStubAdapter>> ServicesMap;
+ COMMONAPI_EXPORT bool unregisterManagedService(const ServicesMap::iterator &);
+
+private:
+ static std::shared_ptr<Factory> theFactory;
+
+ std::map<ConnectionId_t, std::shared_ptr<DBusConnection>> connections_;
+ std::map<MainLoopContext *, std::shared_ptr<DBusConnection>> contextConnections_;
+
+ std::map<std::string, ProxyCreateFunction> proxyCreateFunctions_;
+ std::map<std::string, StubAdapterCreateFunction> stubAdapterCreateFunctions_;
+
+ ServicesMap services_;
+
+ DBusType_t defaultBusType_;
+};
+
+} // namespace DBus
+} // namespace CommonAPI
+
+#endif // COMMONAPI_DBUS_FACTORY_HPP_
diff --git a/include/CommonAPI/DBus/DBusFreedesktopAttribute.hpp b/include/CommonAPI/DBus/DBusFreedesktopAttribute.hpp
new file mode 100644
index 0000000..dc485cb
--- /dev/null
+++ b/include/CommonAPI/DBus/DBusFreedesktopAttribute.hpp
@@ -0,0 +1,451 @@
+// Copyright (C) 2015 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#if !defined (COMMONAPI_INTERNAL_COMPILATION)
+#error "Only <CommonAPI/CommonAPI.hpp> can be included directly, this file may disappear or change contents."
+#endif
+
+#ifndef COMMONAPI_DBUS_DBUS_FREEDESKTOPATTRIBUTE_HPP_
+#define COMMONAPI_DBUS_DBUS_FREEDESKTOPATTRIBUTE_HPP_
+
+#include <CommonAPI/DBus/DBusDeployment.hpp>
+
+namespace CommonAPI {
+namespace DBus {
+
+template <typename _AttributeType>
+class DBusFreedesktopReadonlyAttribute: public _AttributeType {
+public:
+ typedef typename _AttributeType::ValueType ValueType;
+ typedef typename _AttributeType::AttributeAsyncCallback AttributeAsyncCallback;
+
+ DBusFreedesktopReadonlyAttribute(DBusProxy &_proxy, const std::string &_interfaceName, const std::string &_propertyName)
+ : proxy_(_proxy),
+ interfaceName_(_interfaceName),
+ propertyName_(_propertyName) {
+ }
+
+ void getValue(CommonAPI::CallStatus &_status, ValueType &_value, const CommonAPI::CallInfo *_info) const {
+ CommonAPI::Deployable<Variant<ValueType>, VariantDeployment<>> deployedValue(&freedesktopVariant);
+ DBusProxyHelper<
+ DBusSerializableArguments<
+ std::string, std::string
+ >,
+ DBusSerializableArguments<
+ CommonAPI::Deployable<Variant<ValueType>, VariantDeployment<>>
+ >
+ >::callMethodWithReply(
+ proxy_,
+ "org.freedesktop.DBus.Properties",
+ "Get",
+ "ss",
+ (_info ? _info : &defaultCallInfo),
+ interfaceName_,
+ propertyName_,
+ _status,
+ deployedValue);
+
+ _value = deployedValue.getValue().template get<ValueType>();
+ }
+
+ std::future<CallStatus> getValueAsync(AttributeAsyncCallback _callback, const CommonAPI::CallInfo *_info) {
+ CommonAPI::Deployable<Variant<ValueType>, VariantDeployment<>> deployedValue(&freedesktopVariant);
+ return DBusProxyHelper<
+ DBusSerializableArguments<
+ std::string, std::string
+ >,
+ DBusSerializableArguments<
+ CommonAPI::Deployable<Variant<ValueType>, VariantDeployment<>>
+ >
+ >::callMethodAsync(
+ proxy_,
+ "org.freedesktop.DBus.Properties",
+ "Get",
+ "ss",
+ (_info ? _info : &defaultCallInfo),
+ interfaceName_,
+ propertyName_,
+ [_callback](CommonAPI::CallStatus _status, CommonAPI::Deployable<Variant<ValueType>, VariantDeployment<>> _value) {
+ _callback(_status, _value.getValue().template get<ValueType>());
+ },
+ std::make_tuple(deployedValue)
+ );
+ }
+
+protected:
+ DBusProxy &proxy_;
+ std::string interfaceName_;
+ std::string propertyName_;
+};
+
+template <typename _AttributeType>
+class DBusFreedesktopUnionReadonlyAttribute: public _AttributeType {
+public:
+ typedef typename _AttributeType::ValueType ValueType;
+ typedef typename _AttributeType::AttributeAsyncCallback AttributeAsyncCallback;
+
+ DBusFreedesktopUnionReadonlyAttribute(DBusProxy &_proxy, const std::string &_interfaceName, const std::string &_propertyName)
+ : proxy_(_proxy),
+ interfaceName_(_interfaceName),
+ propertyName_(_propertyName) {
+ }
+
+ void getValue(CommonAPI::CallStatus &_status, ValueType &_value, const CommonAPI::CallInfo *_info) const {
+ CommonAPI::Deployable<ValueType, VariantDeployment<>> deployedValue(&freedesktopVariant);
+ DBusProxyHelper<
+ DBusSerializableArguments<
+ std::string, std::string
+ >,
+ DBusSerializableArguments<
+ CommonAPI::Deployable<ValueType, VariantDeployment<>>
+ >
+ >::callMethodWithReply(
+ proxy_,
+ "org.freedesktop.DBus.Properties",
+ "Get",
+ "ss",
+ (_info ? _info : &defaultCallInfo),
+ interfaceName_,
+ propertyName_,
+ _status,
+ deployedValue);
+
+ _value = deployedValue.getValue().template get<ValueType>();
+ }
+
+ std::future<CommonAPI::CallStatus> getValueAsync(AttributeAsyncCallback _callback, const CommonAPI::CallInfo *_info) {
+ CommonAPI::Deployable<ValueType, VariantDeployment<>> deployedValue(&freedesktopVariant);
+ return DBusProxyHelper<
+ DBusSerializableArguments<
+ std::string, std::string
+ >,
+ DBusSerializableArguments<
+ CommonAPI::Deployable<ValueType, VariantDeployment<>>
+ >
+ >::callMethodAsync(
+ proxy_,
+ "org.freedesktop.DBus.Properties",
+ "Get",
+ "ss",
+ (_info ? _info : &defaultCallInfo),
+ interfaceName_,
+ propertyName_,
+ [_callback](CommonAPI::CallStatus _status, CommonAPI::Deployable<ValueType, VariantDeployment<>> _value) {
+ _callback(_status, _value.getValue().template get<ValueType>());
+ },
+ std::make_tuple(deployedValue)
+ );
+ }
+
+protected:
+ DBusProxy &proxy_;
+ std::string interfaceName_;
+ std::string propertyName_;
+};
+
+template <typename _AttributeType>
+class DBusFreedesktopAttribute
+ : public DBusFreedesktopReadonlyAttribute<_AttributeType> {
+ public:
+ typedef typename _AttributeType::ValueType ValueType;
+ typedef typename _AttributeType::AttributeAsyncCallback AttributeAsyncCallback;
+ typedef typename _AttributeType::ChangedEvent ChangedEvent;
+
+ DBusFreedesktopAttribute(DBusProxy &_proxy, const std::string &_interfaceName, const std::string &_propertyName)
+ : DBusFreedesktopReadonlyAttribute<_AttributeType>(_proxy, _interfaceName, _propertyName) {
+ }
+
+ void setValue(const ValueType &_request, CommonAPI::CallStatus &_status, ValueType &_response, const CommonAPI::CallInfo *_info) {
+ CommonAPI::Deployable<Variant<ValueType>, VariantDeployment<>> deployedVariant(_request, &freedesktopVariant);
+ DBusProxyHelper<
+ DBusSerializableArguments<
+ std::string, std::string, CommonAPI::Deployable<Variant<ValueType>, VariantDeployment<>>
+ >,
+ DBusSerializableArguments<
+ >
+ >::callMethodWithReply(
+ DBusFreedesktopReadonlyAttribute<_AttributeType>::proxy_,
+ "org.freedesktop.DBus.Properties",
+ "Set",
+ "ssv",
+ (_info ? _info : &defaultCallInfo),
+ DBusFreedesktopReadonlyAttribute<_AttributeType>::interfaceName_,
+ DBusFreedesktopReadonlyAttribute<_AttributeType>::propertyName_,
+ deployedVariant,
+ _status);
+ _response = _request;
+ }
+
+ std::future<CommonAPI::CallStatus> setValueAsync(const ValueType &_request, AttributeAsyncCallback _callback, const CommonAPI::CallInfo *_info) {
+ CommonAPI::Deployable<Variant<ValueType>, VariantDeployment<>> deployedVariant(_request, &freedesktopVariant);
+ return DBusProxyHelper<
+ DBusSerializableArguments<
+ std::string, std::string, CommonAPI::Deployable<Variant<ValueType>, VariantDeployment<>>
+ >,
+ DBusSerializableArguments<
+ >
+ >::callMethodAsync(
+ DBusFreedesktopReadonlyAttribute<_AttributeType>::proxy_,
+ "org.freedesktop.DBus.Properties",
+ "Set",
+ "ssv",
+ (_info ? _info : &defaultCallInfo),
+ DBusFreedesktopReadonlyAttribute<_AttributeType>::interfaceName_,
+ DBusFreedesktopReadonlyAttribute<_AttributeType>::propertyName_,
+ deployedVariant,
+ [_callback, deployedVariant](CommonAPI::CallStatus _status) {
+ _callback(_status, deployedVariant.getValue().template get<ValueType>());
+ },
+ std::tuple<>());
+ }
+};
+
+template <typename _AttributeType>
+class DBusFreedesktopUnionAttribute
+ : public DBusFreedesktopReadonlyAttribute<_AttributeType> {
+ public:
+ typedef typename _AttributeType::ValueType ValueType;
+ typedef typename _AttributeType::AttributeAsyncCallback AttributeAsyncCallback;
+
+ DBusFreedesktopUnionAttribute(DBusProxy &_proxy, const std::string &_interfaceName, const std::string &_propertyName)
+ : DBusFreedesktopUnionReadonlyAttribute<_AttributeType>(_proxy, _interfaceName, _propertyName) {
+ }
+
+ void setValue(const ValueType &_request, CommonAPI::CallStatus &_status, ValueType &_response, const CommonAPI::CallInfo *_info) {
+ CommonAPI::Deployable<ValueType, VariantDeployment<>> deployedVariant(_request, &freedesktopVariant);
+ DBusProxyHelper<
+ DBusSerializableArguments<
+ std::string, std::string, CommonAPI::Deployable<ValueType, VariantDeployment<>>
+ >,
+ DBusSerializableArguments<
+ >
+ >::callMethodWithReply(
+ DBusFreedesktopReadonlyAttribute<_AttributeType>::proxy_,
+ "org.freedesktop.DBus.Properties",
+ "Set",
+ "ssv",
+ (_info ? _info : &defaultCallInfo),
+ DBusFreedesktopReadonlyAttribute<_AttributeType>::interfaceName_,
+ DBusFreedesktopReadonlyAttribute<_AttributeType>::propertyName_,
+ deployedVariant,
+ _status);
+ _response = _request;
+ }
+
+ std::future<CallStatus> setValueAsync(const ValueType &_request, AttributeAsyncCallback _callback, const CommonAPI::CallInfo *_info) {
+ CommonAPI::Deployable<ValueType, VariantDeployment<>> deployedVariant(_request, &freedesktopVariant);
+ return DBusProxyHelper<
+ DBusSerializableArguments<
+ std::string, std::string, CommonAPI::Deployable<ValueType, VariantDeployment<>>
+ >,
+ DBusSerializableArguments<
+ >
+ >::callMethodAsync(
+ DBusFreedesktopReadonlyAttribute<_AttributeType>::proxy_,
+ "org.freedesktop.DBus.Properties",
+ "Set",
+ "ssv",
+ (_info ? _info : &defaultCallInfo),
+ DBusFreedesktopReadonlyAttribute<_AttributeType>::interfaceName_,
+ DBusFreedesktopReadonlyAttribute<_AttributeType>::propertyName_,
+ deployedVariant,
+ [_callback](CommonAPI::CallStatus _status, CommonAPI::Deployable<ValueType, VariantDeployment<>> _value) {
+ _callback(_status, _value.getValue().template get<ValueType>());
+ },
+ std::make_tuple(deployedVariant));
+ }
+};
+
+template<class, class>
+class LegacyEvent;
+
+template <template <class...> class _Type, class _Types, class _Variant>
+class LegacyEvent<_Type<_Types>, _Variant>: public _Type<_Types> {
+public:
+ typedef _Types ValueType;
+ typedef typename _Type<ValueType>::Listener Listener;
+ typedef std::unordered_map<std::string, _Variant> PropertyMap;
+ typedef MapDeployment<EmptyDeployment, VariantDeployment<>> PropertyMapDeployment;
+ typedef Deployable<PropertyMap, PropertyMapDeployment> DeployedPropertyMap;
+ typedef std::vector<std::string> InvalidArray;
+ typedef Event<std::string, DeployedPropertyMap, InvalidArray> SignalEvent;
+
+ LegacyEvent(DBusProxy &_proxy, const std::string &_interfaceName, const std::string &_propertyName)
+ : interfaceName_(_interfaceName),
+ propertyName_(_propertyName),
+ isSubcriptionSet_(false),
+ internalEvent_(_proxy,
+ "PropertiesChanged",
+ "sa{sv}as",
+ _proxy.getDBusAddress().getObjectPath(),
+ "org.freedesktop.DBus.Properties",
+ std::make_tuple("", getDeployedMap(), InvalidArray())) {
+ }
+
+protected:
+ void onFirstListenerAdded(const Listener &) {
+ if (!isSubcriptionSet_) {
+ subscription_ = internalEvent_.subscribe(
+ [this](const std::string &_interfaceName,
+ const PropertyMap &_properties,
+ const InvalidArray &_invalid) {
+ if (interfaceName_ == _interfaceName) {
+ auto iter = _properties.find(propertyName_);
+ if (iter != _properties.end()) {
+ const ValueType &value = iter->second.template get<ValueType>();
+ this->notifyListeners(value);
+ }
+ }
+ });
+
+ isSubcriptionSet_ = true;
+ }
+ }
+
+ void onLastListenerRemoved(const Listener &) {
+ if (isSubcriptionSet_) {
+ internalEvent_.unsubscribe(subscription_);
+ isSubcriptionSet_ = false;
+ }
+ }
+
+ std::string interfaceName_;
+ std::string propertyName_;
+
+ typename DBusEvent<SignalEvent, std::string, DeployedPropertyMap, InvalidArray>::Subscription subscription_;
+ bool isSubcriptionSet_;
+
+ DBusEvent<SignalEvent, std::string, DeployedPropertyMap, InvalidArray> internalEvent_;
+
+private:
+ static DeployedPropertyMap &getDeployedMap() {
+ static PropertyMapDeployment itsDeployment(nullptr, &freedesktopVariant);
+ static DeployedPropertyMap itsDeployedMap(&itsDeployment);
+ return itsDeployedMap;
+ }
+};
+
+template <typename _AttributeType, typename _Variant>
+class DBusFreedesktopObservableAttribute: public _AttributeType {
+ public:
+ typedef typename _AttributeType::ValueType ValueType;
+ typedef typename _AttributeType::AttributeAsyncCallback AttributeAsyncCallback;
+ typedef typename _AttributeType::ChangedEvent ChangedEvent;
+
+ template <typename... _AttributeTypeArguments>
+ DBusFreedesktopObservableAttribute(DBusProxy &_proxy,
+ const std::string &_interfaceName,
+ const std::string &_propertyName,
+ _AttributeTypeArguments... _arguments)
+ : _AttributeType(_proxy, _interfaceName, _propertyName, _arguments...),
+ interfaceName_(_interfaceName),
+ propertyName_(_propertyName),
+ externalChangedEvent_(_proxy, _interfaceName, _propertyName) {
+ }
+
+ ChangedEvent &getChangedEvent() {
+ return externalChangedEvent_;
+ }
+
+ protected:
+ std::string interfaceName_;
+ std::string propertyName_;
+ LegacyEvent<ChangedEvent, _Variant> externalChangedEvent_;
+};
+
+template<class, class>
+class LegacyUnionEvent;
+
+template <template <class...> class _Type, class _Types, class _Variant>
+class LegacyUnionEvent<_Type<_Types>, _Variant>: public _Type<_Types> {
+public:
+ typedef _Types ValueType;
+ typedef typename _Type<ValueType>::Listener Listener;
+ typedef std::unordered_map<std::string, _Variant> PropertyMap;
+ typedef MapDeployment<EmptyDeployment, VariantDeployment<>> PropertyMapDeployment;
+ typedef CommonAPI::Deployable<PropertyMap, PropertyMapDeployment> DeployedPropertyMap;
+ typedef std::vector<std::string> InvalidArray;
+ typedef Event<std::string, DeployedPropertyMap, InvalidArray> SignalEvent;
+
+ LegacyUnionEvent(DBusProxy &_proxy, const std::string &_interfaceName, const std::string &_propertyName)
+ : interfaceName_(_interfaceName),
+ propertyName_(_propertyName),
+ isSubcriptionSet_(false),
+ internalEvent_(_proxy,
+ "PropertiesChanged",
+ "sa{sv}as",
+ _proxy.getDBusAddress().getObjectPath(),
+ "org.freedesktop.DBus.Properties",
+ std::make_tuple("", getDeployedMap(), InvalidArray())) {
+ }
+
+protected:
+ void onFirstListenerAdded(const Listener &) {
+ if (isSubcriptionSet_) {
+ subscription_ = internalEvent_.subscribe(
+ [this](const std::string &_interfaceName,
+ const PropertyMap &_properties,
+ const std::vector<std::string> &_invalid) {
+ if (interfaceName_ == _interfaceName) {
+ auto iter = _properties.find(propertyName_);
+ if (iter != _properties.end()) {
+ this->notifyListeners(iter->second.template get<ValueType>());
+ }
+ }
+ });
+ isSubcriptionSet_ = true;
+ }
+ }
+
+ void onLastListenerRemoved(const Listener &) {
+ if (isSubcriptionSet_) {
+ internalEvent_.unsubscribe(subscription_);
+ isSubcriptionSet_ = false;
+ }
+ }
+
+ DBusEvent<SignalEvent, ValueType> internalEvent_;
+ std::string interfaceName_;
+ std::string propertyName_;
+
+ typename DBusEvent<SignalEvent>::Subscription subscription_;
+ bool isSubcriptionSet_;
+
+private:
+ static DeployedPropertyMap &getDeployedMap() {
+ static PropertyMapDeployment itsDeployment(nullptr, &freedesktopVariant);
+ static DeployedPropertyMap itsDeployedMap(&itsDeployment);
+ return itsDeployedMap;
+ }
+};
+
+template <typename _AttributeType, typename _Variant>
+class DBusFreedesktopUnionObservableAttribute: public _AttributeType {
+ public:
+ typedef typename _AttributeType::ValueType ValueType;
+ typedef typename _AttributeType::AttributeAsyncCallback AttributeAsyncCallback;
+ typedef typename _AttributeType::ChangedEvent ChangedEvent;
+
+ template <typename... _AttributeTypeArguments>
+ DBusFreedesktopUnionObservableAttribute(DBusProxy &_proxy,
+ const std::string &_interfaceName,
+ const std::string &_propertyName,
+ _AttributeTypeArguments... _arguments)
+ : _AttributeType(_proxy, _interfaceName, _propertyName, _arguments...),
+ externalChangedEvent_(_proxy, _interfaceName, _propertyName) {
+ }
+
+ ChangedEvent &getChangedEvent() {
+ return externalChangedEvent_;
+ }
+
+ protected:
+ LegacyUnionEvent<ChangedEvent, _Variant> externalChangedEvent_;
+};
+
+} // namespace DBus
+} // namespace CommonAPI
+
+#endif // COMMONAPI_DBUS_DBUS_FREEDESKTOPATTRIBUTE_HPP_
diff --git a/include/CommonAPI/DBus/DBusFreedesktopPropertiesStub.hpp b/include/CommonAPI/DBus/DBusFreedesktopPropertiesStub.hpp
new file mode 100644
index 0000000..f7e2cdf
--- /dev/null
+++ b/include/CommonAPI/DBus/DBusFreedesktopPropertiesStub.hpp
@@ -0,0 +1,59 @@
+// Copyright (C) 2013-2015 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#if !defined (COMMONAPI_INTERNAL_COMPILATION)
+#error "Only <CommonAPI/CommonAPI.hpp> can be included directly, this file may disappear or change contents."
+#endif
+
+#ifndef COMMONAPI_DBUS_DBUS_FREEDESKTOPPROPERTIESSTUB_HPP_
+#define COMMONAPI_DBUS_DBUS_FREEDESKTOPPROPERTIESSTUB_HPP_
+
+#include <memory>
+#include <mutex>
+#include <string>
+
+#include <CommonAPI/DBus/DBusInterfaceHandler.hpp>
+
+namespace CommonAPI {
+namespace DBus {
+
+class DBusStubAdapter;
+
+/**
+ * Stub for standard <a href="http://dbus.freedesktop.org/doc/dbus-specification.html#standard-interfaces-properties">org.freedesktop.dbus.Properties</a> interface.
+ *
+ * DBusFreedesktopPropertiesStub gets the DBusStubAdapter for handling the actual properties with instantiation.
+ */
+class DBusFreedesktopPropertiesStub: public DBusInterfaceHandler {
+public:
+ DBusFreedesktopPropertiesStub(const std::string &_path,
+ const std::string &_interface,
+ const std::shared_ptr<DBusProxyConnection> &_connection,
+ const std::shared_ptr<DBusStubAdapter> &_adapter);
+
+ virtual ~DBusFreedesktopPropertiesStub();
+
+ const std::string &getObjectPath() const;
+ static const std::string &getInterface();
+
+ virtual const char* getMethodsDBusIntrospectionXmlData() const;
+ virtual bool onInterfaceDBusMessage(const DBusMessage &_message);
+ virtual const bool hasFreedesktopProperties();
+
+private:
+ std::string path_;
+ std::weak_ptr<DBusProxyConnection> connection_;
+ std::shared_ptr<DBusStubAdapter> adapter_;
+
+ typedef std::unordered_map<std::string, std::shared_ptr<DBusStubAdapter>> DBusInterfacesMap;
+ DBusInterfacesMap managedInterfaces_;
+
+ std::mutex dbusInterfacesLock_;
+};
+
+} // namespace DBus
+} // namespace CommonAPI
+
+#endif // COMMONAPI_DBUS_DBUS_FREEDESKTOPPROPERTIESSTUB_HPP_
diff --git a/include/CommonAPI/DBus/DBusFreedesktopStubAdapterHelper.hpp b/include/CommonAPI/DBus/DBusFreedesktopStubAdapterHelper.hpp
new file mode 100644
index 0000000..5c0bffa
--- /dev/null
+++ b/include/CommonAPI/DBus/DBusFreedesktopStubAdapterHelper.hpp
@@ -0,0 +1,194 @@
+// Copyright (C) 2015 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#if !defined (COMMONAPI_INTERNAL_COMPILATION)
+#error "Only <CommonAPI/CommonAPI.hpp> can be included directly, this file may disappear or change contents."
+#endif
+
+#ifndef COMMONAPI_DBUS_DBUSFREEDESKTOPSTUBADAPTERHELPER_HPP_
+#define COMMONAPI_DBUS_DBUSFREEDESKTOPSTUBADAPTERHELPER_HPP_
+
+#include <CommonAPI/Struct.hpp>
+#include <CommonAPI/DBus/DBusStubAdapterHelper.hpp>
+
+namespace CommonAPI {
+namespace DBus {
+
+template <typename _StubClass>
+class DBusGetFreedesktopAttributeStubDispatcherBase {
+public:
+ virtual ~DBusGetFreedesktopAttributeStubDispatcherBase() {}
+ virtual void dispatchDBusMessageAndAppendReply(const DBusMessage &_message,
+ const std::shared_ptr<_StubClass> &_stub,
+ DBusOutputStream &_output,
+ const std::shared_ptr<DBusClientId> &_clientId) = 0;
+};
+
+template <typename _StubClass, typename _AttributeType>
+class DBusGetFreedesktopAttributeStubDispatcher
+ : public virtual DBusGetAttributeStubDispatcher<_StubClass, _AttributeType>,
+ public virtual DBusGetFreedesktopAttributeStubDispatcherBase<_StubClass> {
+public:
+ typedef DBusStubAdapterHelper<_StubClass> DBusStubAdapterHelperType;
+ typedef typename DBusGetAttributeStubDispatcher<_StubClass, _AttributeType>::GetStubFunctor GetStubFunctor;
+
+ DBusGetFreedesktopAttributeStubDispatcher(GetStubFunctor _getStubFunctor)
+ : DBusGetAttributeStubDispatcher<_StubClass, _AttributeType>(_getStubFunctor, "v") {
+ }
+
+ virtual ~DBusGetFreedesktopAttributeStubDispatcher() {};
+
+ void dispatchDBusMessageAndAppendReply(const DBusMessage &_message,
+ const std::shared_ptr<_StubClass> &_stub,
+ DBusOutputStream &_output,
+ const std::shared_ptr<DBusClientId> &_clientId) {
+ CommonAPI::Deployable<CommonAPI::Variant<_AttributeType>, VariantDeployment<>> deployedVariant(
+ (_stub.get()->*(DBusGetAttributeStubDispatcher<_StubClass, _AttributeType>::getStubFunctor_))(_clientId), &freedesktopVariant);
+
+ _output << deployedVariant;
+ }
+
+protected:
+ virtual bool sendAttributeValueReply(const DBusMessage &_message, const std::shared_ptr<_StubClass> &_stub, DBusStubAdapterHelperType &_helper) {
+ DBusMessage reply = _message.createMethodReturn(DBusGetAttributeStubDispatcher<_StubClass, _AttributeType>::signature_);
+
+ std::shared_ptr<DBusClientId> clientId = std::make_shared<DBusClientId>(std::string(_message.getSender()));
+ CommonAPI::Deployable<CommonAPI::Variant<_AttributeType>, VariantDeployment<>> deployedVariant(
+ (_stub.get()->*(DBusGetAttributeStubDispatcher<_StubClass, _AttributeType>::getStubFunctor_))(clientId), &freedesktopVariant);
+
+ DBusOutputStream output(reply);
+ output << deployedVariant;
+ output.flush();
+
+ return _helper.getDBusConnection()->sendDBusMessage(reply);
+ }
+};
+
+template <typename _StubClass, typename _AttributeType>
+class DBusSetFreedesktopAttributeStubDispatcher
+ : public virtual DBusGetFreedesktopAttributeStubDispatcher<_StubClass, _AttributeType>,
+ public virtual DBusSetAttributeStubDispatcher<_StubClass, _AttributeType> {
+public:
+ typedef typename DBusGetAttributeStubDispatcher<_StubClass, _AttributeType>::GetStubFunctor GetStubFunctor;
+ typedef typename DBusGetAttributeStubDispatcher<_StubClass, _AttributeType>::DBusStubAdapterHelperType DBusStubAdapterHelperType;
+ typedef typename DBusStubAdapterHelperType::RemoteEventHandlerType RemoteEventHandlerType;
+ typedef bool (RemoteEventHandlerType::*OnRemoteSetFunctor)(std::shared_ptr<CommonAPI::ClientId>, _AttributeType);
+ typedef void (RemoteEventHandlerType::*OnRemoteChangedFunctor)();
+
+ DBusSetFreedesktopAttributeStubDispatcher(
+ GetStubFunctor _getStubFunctor,
+ OnRemoteSetFunctor _onRemoteSetFunctor,
+ OnRemoteChangedFunctor _onRemoteChangedFunctor)
+ : DBusGetAttributeStubDispatcher<_StubClass, _AttributeType>(_getStubFunctor, "v"),
+ DBusGetFreedesktopAttributeStubDispatcher<_StubClass, _AttributeType>(_getStubFunctor),
+ DBusSetAttributeStubDispatcher<_StubClass, _AttributeType>(_getStubFunctor, _onRemoteSetFunctor, _onRemoteChangedFunctor, "v") {
+ }
+
+ virtual ~DBusSetFreedesktopAttributeStubDispatcher() {};
+
+protected:
+ virtual _AttributeType retreiveAttributeValue(const DBusMessage &_message, bool &_error) {
+ std::string interfaceName, attributeName;
+ DBusInputStream input(_message);
+ CommonAPI::Deployable<CommonAPI::Variant<_AttributeType>, VariantDeployment<>> deployedVariant(&freedesktopVariant);
+ input >> interfaceName; // skip over interface and attribute name
+ input >> attributeName;
+ input >> deployedVariant;
+ _error = input.hasError();
+ _AttributeType attributeValue = deployedVariant.getValue().template get<_AttributeType>() ;
+ return attributeValue;
+ }
+};
+
+template <typename _StubClass, typename _AttributeType>
+class DBusSetFreedesktopObservableAttributeStubDispatcher
+ : public virtual DBusSetFreedesktopAttributeStubDispatcher<_StubClass, _AttributeType>,
+ public virtual DBusSetObservableAttributeStubDispatcher<_StubClass, _AttributeType> {
+public:
+ typedef typename DBusSetFreedesktopAttributeStubDispatcher<_StubClass, _AttributeType>::DBusStubAdapterHelperType DBusStubAdapterHelperType;
+ typedef typename DBusStubAdapterHelperType::StubAdapterType StubAdapterType;
+ typedef typename DBusSetFreedesktopAttributeStubDispatcher<_StubClass, _AttributeType>::GetStubFunctor GetStubFunctor;
+ typedef typename DBusSetFreedesktopAttributeStubDispatcher<_StubClass, _AttributeType>::OnRemoteSetFunctor OnRemoteSetFunctor;
+ typedef typename DBusSetFreedesktopAttributeStubDispatcher<_StubClass, _AttributeType>::OnRemoteChangedFunctor OnRemoteChangedFunctor;
+ typedef void (StubAdapterType::*FireChangedFunctor)(const _AttributeType&);
+
+ DBusSetFreedesktopObservableAttributeStubDispatcher(
+ GetStubFunctor _getStubFunctor,
+ OnRemoteSetFunctor _onRemoteSetFunctor,
+ OnRemoteChangedFunctor _onRemoteChangedFunctor,
+ FireChangedFunctor _fireChangedFunctor)
+ : DBusGetAttributeStubDispatcher<_StubClass, _AttributeType>(_getStubFunctor, "v"),
+ DBusGetFreedesktopAttributeStubDispatcher<_StubClass, _AttributeType>(_getStubFunctor),
+ DBusSetAttributeStubDispatcher<_StubClass, _AttributeType>(_getStubFunctor, _onRemoteSetFunctor, _onRemoteChangedFunctor, "v"),
+ DBusSetFreedesktopAttributeStubDispatcher<_StubClass, _AttributeType>(_getStubFunctor, _onRemoteSetFunctor, _onRemoteChangedFunctor),
+ DBusSetObservableAttributeStubDispatcher<_StubClass, _AttributeType>(_getStubFunctor, _onRemoteSetFunctor, _onRemoteChangedFunctor, _fireChangedFunctor, "v") {
+ }
+};
+
+template<class>
+struct DBusStubFreedesktopPropertiesSignalHelper;
+
+template<template<class ...> class _In, class _InArg>
+struct DBusStubFreedesktopPropertiesSignalHelper<_In<DBusInputStream, DBusOutputStream, _InArg>> {
+
+ template <typename _ValueType>
+ struct DBusPropertiesEntry
+ : public CommonAPI::Struct<std::string, CommonAPI::Variant<_ValueType>> {
+
+ DBusPropertiesEntry() = default;
+ DBusPropertiesEntry(const std::string &_propertyName,
+ const _ValueType &_propertyValue) {
+ std::get<0>(this->values_) = _propertyName;
+ std::get<1>(this->values_) = _propertyValue;
+ };
+
+ const std::string &getPropertyName() const { return std::get<0>(this->values_); }
+ void setPropertyName(const std::string &_value) { std::get<0>(this->values_) = _value; }
+
+ const _ValueType getPropertyValue() const { return std::get<1>(this->values_); }
+ void setPropertyValue(const _ValueType &_value) { std::get<1>(this->values_) = _value; }
+ };
+
+ typedef std::vector<DBusPropertiesEntry<_InArg>> PropertiesArray;
+ typedef CommonAPI::Deployment<CommonAPI::EmptyDeployment, VariantDeployment<>> PropertyDeployment;
+ typedef CommonAPI::ArrayDeployment<PropertyDeployment> PropertiesDeployment;
+ typedef CommonAPI::Deployable<PropertiesArray, PropertiesDeployment> DeployedPropertiesArray;
+
+ template <typename _StubClass>
+ static bool sendPropertiesChangedSignal(const _StubClass &_stub, const std::string &_propertyName, const _InArg &_inArg) {
+ const std::vector<std::string> invalidatedProperties;
+ PropertiesArray changedProperties;
+ DBusPropertiesEntry<_InArg> entry(_propertyName, _inArg);
+ changedProperties.push_back(entry);
+
+ PropertyDeployment propertyDeployment(nullptr, &freedesktopVariant);
+ PropertiesDeployment changedPropertiesDeployment(&propertyDeployment);
+
+ DeployedPropertiesArray deployedChangedProperties(changedProperties, &changedPropertiesDeployment);
+
+ return DBusStubSignalHelper<
+ _In<
+ DBusInputStream,
+ DBusOutputStream,
+ const std::string,
+ DeployedPropertiesArray,
+ std::vector<std::string>
+ >
+ >::sendSignal(
+ _stub.getDBusAddress().getObjectPath().c_str(),
+ "org.freedesktop.DBus.Properties",
+ "PropertiesChanged",
+ "sa{sv}as",
+ _stub.getDBusConnection(),
+ _stub.getInterface(),
+ deployedChangedProperties,
+ invalidatedProperties);
+ }
+};
+
+} // namespace DBus
+} // namespace CommonAPI
+
+#endif // COMMONAPI_DBUS_DBUSFREEDESKTOPSTUBADAPTERHELPER_HPP_
diff --git a/include/CommonAPI/DBus/DBusFreedesktopVariant.hpp b/include/CommonAPI/DBus/DBusFreedesktopVariant.hpp
new file mode 100644
index 0000000..31490d2
--- /dev/null
+++ b/include/CommonAPI/DBus/DBusFreedesktopVariant.hpp
@@ -0,0 +1,74 @@
+// Copyright (C) 2014-2015 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#if !defined (COMMONAPI_INTERNAL_COMPILATION)
+#error "Only <CommonAPI/CommonAPI.h> can be included directly, this file may disappear or change contents."
+#endif
+
+#include <CommonAPI/DBus/DBusTypeOutputStream.hpp>
+
+#ifndef COMMONAPI_DBUS_FREEDESKTOPVARIANT_HPP_
+#define COMMONAPI_DBUS_FREEDESKTOPVARIANT_HPP_
+
+namespace CommonAPI {
+namespace DBus {
+
+template<class Visitor, class Variant, typename ... _Types>
+struct ApplyTypeCompareVisitor;
+
+template<class Visitor, class Variant>
+struct ApplyTypeCompareVisitor<Visitor, Variant> {
+ static const uint8_t index = 0;
+
+ static uint8_t visit(Visitor&, const Variant&) {
+ // won't be called if the variant contains the requested type
+ assert(false);
+ return 0;
+ }
+};
+
+template<class Visitor, class Variant, typename _Type, typename ... _Types>
+struct ApplyTypeCompareVisitor<Visitor, Variant, _Type, _Types...> {
+ static const uint8_t index
+ = ApplyTypeCompareVisitor<Visitor, Variant, _Types...>::index + 1;
+
+ static uint8_t visit(Visitor &_visitor, const Variant &_variant) {
+ DBusTypeOutputStream output;
+ _Type current;
+ output.writeType(current);
+#ifdef WIN32
+ if (_visitor.operator()<_Type>(output.getSignature())) {
+#else
+ if (_visitor.template operator()<_Type>(output.getSignature())) {
+#endif
+ return index;
+ } else {
+ return ApplyTypeCompareVisitor<
+ Visitor, Variant, _Types...
+ >::visit(_visitor, _variant);
+ }
+ }
+};
+
+template<typename ... _Types>
+struct TypeCompareVisitor {
+public:
+ TypeCompareVisitor(const std::string &_type)
+ : type_(_type) {
+ }
+
+ template<typename _Type>
+ bool operator()(const std::string &_type) const {
+ return (_type == type_);
+ }
+
+private:
+ const std::string type_;
+};
+
+} // namespace DBus
+} // namespace CommonAPI
+
+#endif // COMMONAPI_DBUS_FREEDESKTOPVARIANT_HPP_
diff --git a/include/CommonAPI/DBus/DBusFunctionalHash.hpp b/include/CommonAPI/DBus/DBusFunctionalHash.hpp
new file mode 100644
index 0000000..78848c7
--- /dev/null
+++ b/include/CommonAPI/DBus/DBusFunctionalHash.hpp
@@ -0,0 +1,81 @@
+// Copyright (C) 2013-2015 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#if !defined (COMMONAPI_INTERNAL_COMPILATION)
+#error "Only <CommonAPI/CommonAPI.hpp> can be included directly, this file may disappear or change contents."
+#endif
+
+#ifndef COMMONAPI_DBUS_DBUS_FUNCTIONAL_HASH_HPP_
+#define COMMONAPI_DBUS_DBUS_FUNCTIONAL_HASH_HPP_
+
+#include <functional>
+#include <string>
+#include <tuple>
+
+#include <CommonAPI/Export.hpp>
+
+namespace std {
+
+template<>
+struct COMMONAPI_EXPORT hash<pair<const char*, const char*> >
+ : public unary_function<pair<const char*, const char*>, size_t> {
+
+ size_t operator()(const pair<const char*, const char*>& t) const;
+};
+
+template<>
+struct COMMONAPI_EXPORT hash<const char*>
+ : public unary_function<const char*, size_t> {
+
+ size_t operator()(const char* const t) const;
+};
+
+template<>
+struct COMMONAPI_EXPORT hash<pair<string, string> >
+ : public unary_function<pair<string, string>, size_t> {
+
+ size_t operator()(const pair<string, string>& t) const;
+};
+
+template<>
+struct COMMONAPI_EXPORT hash<tuple<string, string, string> >
+ : public unary_function<tuple<string, string, string>, size_t> {
+
+ size_t operator()(const tuple<string, string, string>& t) const;
+};
+
+template<>
+struct COMMONAPI_EXPORT hash<tuple<string, string, string, bool> >
+ : public unary_function<tuple<string, string, string, bool>, size_t> {
+
+ size_t operator()(const tuple<string, string, string, bool>& t) const;
+};
+
+template<>
+struct COMMONAPI_EXPORT hash<tuple<string, string, string, int> >
+ : public unary_function<tuple<string, string, string, int>, size_t> {
+
+ size_t operator()(const tuple<string, string, string, int>& t) const;
+};
+
+template<>
+struct COMMONAPI_EXPORT hash<tuple<string, string, string, string> >
+ : public std::unary_function<tuple<string, string, string, string>, size_t> {
+
+ size_t operator()(const tuple<string, string, string, string>& t) const;
+};
+
+template<>
+struct COMMONAPI_EXPORT equal_to<pair<const char*, const char*> >
+ : public binary_function<pair<const char*, const char*>,
+ pair<const char*, const char*>,
+ bool> {
+
+ bool operator()(const pair<const char*, const char*>& a, const pair<const char*, const char*>& b) const;
+};
+
+} // namespace std
+
+#endif // COMMONAPI_DBUS_DBUS_FUNCTIONAL_HASH_HPP_
diff --git a/include/CommonAPI/DBus/DBusHelper.hpp b/include/CommonAPI/DBus/DBusHelper.hpp
new file mode 100644
index 0000000..53a5625
--- /dev/null
+++ b/include/CommonAPI/DBus/DBusHelper.hpp
@@ -0,0 +1,55 @@
+// Copyright (C) 2013-2015 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#if !defined (COMMONAPI_INTERNAL_COMPILATION)
+#error "Only <CommonAPI/CommonAPI.hpp> can be included directly, this file may disappear or change contents."
+#endif
+
+#ifndef COMMONAPI_DBUS_DBUS_HELPER_HPP_
+#define COMMONAPI_DBUS_DBUS_HELPER_HPP_
+
+#include <unordered_map>
+#include <vector>
+
+namespace CommonAPI {
+namespace DBus {
+
+template <int ...>
+struct index_sequence {};
+
+
+template <int N, int ...S>
+struct make_sequence : make_sequence<N-1, N-1, S...> {};
+
+template <int ...S>
+struct make_sequence<0, S...> {
+ typedef index_sequence<S...> type;
+};
+
+
+template <int N, int _Offset, int ...S>
+struct make_sequence_range : make_sequence_range<N-1, _Offset, N-1+_Offset, S...> {};
+
+template <int _Offset, int ...S>
+struct make_sequence_range<0, _Offset, S...> {
+ typedef index_sequence<S...> type;
+};
+
+template<typename _Type>
+struct is_std_vector { static const bool value = false; };
+
+template<typename _Type>
+struct is_std_vector<std::vector<_Type> > { static const bool value = true; };
+
+template<typename _Type>
+struct is_std_unordered_map { static const bool value = false; };
+
+template<typename _Key, typename _Value, typename _Hash>
+struct is_std_unordered_map<std::unordered_map<_Key, _Value, _Hash>> { static const bool value = true; };
+
+} // namespace DBus
+} // namespace CommonAPI
+
+#endif // COMMONAPI_DBUS_DBUS_HELPER_HPP_
diff --git a/include/CommonAPI/DBus/DBusInputStream.hpp b/include/CommonAPI/DBus/DBusInputStream.hpp
new file mode 100644
index 0000000..389cb68
--- /dev/null
+++ b/include/CommonAPI/DBus/DBusInputStream.hpp
@@ -0,0 +1,426 @@
+// Copyright (C) 2013-2015 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#if !defined (COMMONAPI_INTERNAL_COMPILATION)
+#error "Only <CommonAPI/CommonAPI.hpp> can be included directly, this file may disappear or change contents."
+#endif
+
+#ifndef COMMONAPI_DBUS_DBUSINPUTSTREAM_HPP_
+#define COMMONAPI_DBUS_DBUSINPUTSTREAM_HPP_
+
+#include <iostream>
+#include <iomanip>
+#include <sstream>
+
+#include <cassert>
+#include <cstdint>
+#include <stack>
+#include <string>
+#include <vector>
+
+#include <CommonAPI/Export.hpp>
+#include <CommonAPI/InputStream.hpp>
+#include <CommonAPI/Struct.hpp>
+#include <CommonAPI/DBus/DBusDeployment.hpp>
+#include <CommonAPI/DBus/DBusError.hpp>
+#include <CommonAPI/DBus/DBusFreedesktopVariant.hpp>
+#include <CommonAPI/DBus/DBusHelper.hpp>
+#include <CommonAPI/DBus/DBusMessage.hpp>
+
+namespace CommonAPI {
+namespace DBus {
+
+// Used to mark the position of a pointer within an array of bytes.
+typedef uint32_t position_t;
+
+/**
+ * @class DBusInputMessageStream
+ *
+ * Used to deserialize and read data from a #DBusMessage. For all data types that can be read from a #DBusMessage, a ">>"-operator should be defined to handle the reading
+ * (this operator is predefined for all basic data types and for vectors).
+ */
+class DBusInputStream
+ : public InputStream<DBusInputStream> {
+public:
+ COMMONAPI_EXPORT bool hasError() const {
+ return isErrorSet();
+ }
+
+ COMMONAPI_EXPORT InputStream &readValue(bool &_value, const EmptyDeployment *_depl);
+
+ COMMONAPI_EXPORT InputStream &readValue(int8_t &_value, const EmptyDeployment *_depl);
+ COMMONAPI_EXPORT InputStream &readValue(int16_t &_value, const EmptyDeployment *_depl);
+ COMMONAPI_EXPORT InputStream &readValue(int32_t &_value, const EmptyDeployment *_depl);
+ COMMONAPI_EXPORT InputStream &readValue(int64_t &_value, const EmptyDeployment *_depl);
+
+ COMMONAPI_EXPORT InputStream &readValue(uint8_t &_value, const EmptyDeployment *_depl);
+ COMMONAPI_EXPORT InputStream &readValue(uint16_t &_value, const EmptyDeployment *_depl);
+ COMMONAPI_EXPORT InputStream &readValue(uint32_t &_value, const EmptyDeployment *_depl);
+ COMMONAPI_EXPORT InputStream &readValue(uint64_t &_value, const EmptyDeployment *_depl);
+
+ COMMONAPI_EXPORT InputStream &readValue(float &_value, const EmptyDeployment *_depl);
+ COMMONAPI_EXPORT InputStream &readValue(double &_value, const EmptyDeployment *_depl);
+
+ COMMONAPI_EXPORT InputStream &readValue(std::string &_value, const EmptyDeployment *_depl);
+
+ COMMONAPI_EXPORT InputStream &readValue(Version &_value, const EmptyDeployment *_depl);
+
+ template<class _Deployment, typename _Base>
+ COMMONAPI_EXPORT InputStream &readValue(Enumeration<_Base> &_value, const _Deployment *_depl) {
+ _Base tmpValue;
+ readValue(tmpValue, _depl);
+ _value = tmpValue;
+ return (*this);
+ }
+
+ template<class _Deployment, typename... _Types>
+ COMMONAPI_EXPORT InputStream &readValue(Struct<_Types...> &_value, const _Deployment *_depl) {
+ align(8);
+ const auto itsSize(std::tuple_size<std::tuple<_Types...>>::value);
+ StructReader<itsSize-1, DBusInputStream, Struct<_Types...>, _Deployment>{}(
+ (*this), _value, _depl);
+ return (*this);
+ }
+
+ template<class _Deployment, class _PolymorphicStruct>
+ COMMONAPI_EXPORT InputStream &readValue(std::shared_ptr<_PolymorphicStruct> &_value,
+ const _Deployment *_depl) {
+ uint32_t serial;
+ align(8);
+ _readValue(serial);
+ skipSignature();
+ align(8);
+ if (!hasError()) {
+ _value = _PolymorphicStruct::create(serial);
+ _value->template readValue<>(*this, _depl);
+ }
+
+ return (*this);
+ }
+
+ template<typename... _Types>
+ COMMONAPI_EXPORT InputStream &readValue(Variant<_Types...> &_value, const CommonAPI::EmptyDeployment *_depl = nullptr) {
+ if(_value.hasValue()) {
+ DeleteVisitor<_value.maxSize> visitor(_value.valueStorage_);
+ ApplyVoidVisitor<DeleteVisitor<_value.maxSize>,
+ Variant<_Types...>, _Types... >::visit(visitor, _value);
+ }
+
+ align(8);
+ readValue(_value.valueType_, static_cast<EmptyDeployment *>(nullptr));
+ skipSignature();
+
+ InputStreamReadVisitor<DBusInputStream, _Types...> visitor((*this), _value);
+ ApplyVoidVisitor<InputStreamReadVisitor<DBusInputStream, _Types... >,
+ Variant<_Types...>, _Types...>::visit(visitor, _value);
+
+ return (*this);
+ }
+
+ template<typename _Deployment, typename... _Types>
+ COMMONAPI_EXPORT InputStream &readValue(Variant<_Types...> &_value, const _Deployment *_depl) {
+ if(_value.hasValue()) {
+ DeleteVisitor<_value.maxSize> visitor(_value.valueStorage_);
+ ApplyVoidVisitor<DeleteVisitor<_value.maxSize>,
+ Variant<_Types...>, _Types... >::visit(visitor, _value);
+ }
+
+ if (_depl != nullptr && _depl->isFreeDesktop_) {
+ // Read signature
+ uint8_t signatureLength;
+ readValue(signatureLength, static_cast<EmptyDeployment *>(nullptr));
+ std::string signature(_readRaw(signatureLength+1), signatureLength);
+
+ // Determine index (value type) from signature
+ TypeCompareVisitor<_Types...> visitor(signature);
+ _value.valueType_ = ApplyTypeCompareVisitor<
+ TypeCompareVisitor<_Types...>,
+ Variant<_Types...>,
+ _Types...
+ >::visit(visitor, _value);
+ } else {
+ align(8);
+ readValue(_value.valueType_, static_cast<EmptyDeployment *>(nullptr));
+ skipSignature();
+ }
+
+
+ InputStreamReadVisitor<DBusInputStream, _Types...> visitor((*this), _value);
+ ApplyVoidVisitor<InputStreamReadVisitor<DBusInputStream, _Types... >,
+ Variant<_Types...>, _Types...>::visit(visitor, _value);
+
+ return (*this);
+ }
+
+ template<typename _ElementType>
+ COMMONAPI_EXPORT InputStream &readValue(std::vector<_ElementType> &_value, const EmptyDeployment *_depl) {
+ uint32_t itsSize;
+ _readValue(itsSize);
+ pushSize(itsSize);
+
+ alignVector<_ElementType>();
+
+ pushPosition();
+
+ _value.clear();
+ while (sizes_.top() > current_ - positions_.top()) {
+ _ElementType itsElement;
+ readValue(itsElement, static_cast<EmptyDeployment *>(nullptr));
+
+ if (hasError()) {
+ break;
+ }
+
+ _value.push_back(std::move(itsElement));
+ }
+
+ popSize();
+ popPosition();
+
+ return (*this);
+ }
+
+ template<class _Deployment, typename _ElementType>
+ COMMONAPI_EXPORT InputStream &readValue(std::vector<_ElementType> &_value, const _Deployment *_depl) {
+ uint32_t itsSize;
+ _readValue(itsSize);
+ pushSize(itsSize);
+
+ alignVector<_ElementType>();
+
+ pushPosition();
+
+ _value.clear();
+ while (sizes_.top() > current_ - positions_.top()) {
+ _ElementType itsElement;
+ readValue(itsElement, _depl->elementDepl_);
+
+ if (hasError()) {
+ break;
+ }
+
+ _value.push_back(std::move(itsElement));
+ }
+
+ popSize();
+ popPosition();
+
+ return (*this);
+ }
+
+ template<typename _KeyType, typename _ValueType, typename _HasherType>
+ COMMONAPI_EXPORT InputStream &readValue(std::unordered_map<_KeyType, _ValueType, _HasherType> &_value,
+ const EmptyDeployment *_depl) {
+
+ typedef typename std::unordered_map<_KeyType, _ValueType, _HasherType>::value_type MapElement;
+
+ uint32_t itsSize;
+ _readValue(itsSize);
+ pushSize(itsSize);
+
+ align(8);
+ pushPosition();
+
+ _value.clear();
+ while (sizes_.top() > current_ - positions_.top()) {
+ _KeyType itsKey;
+ _ValueType itsValue;
+
+ align(8);
+ readValue(itsKey, _depl);
+ readValue(itsValue, _depl);
+
+ if (hasError()) {
+ break;
+ }
+
+ _value.insert(MapElement(std::move(itsKey), std::move(itsValue)));
+ }
+
+ (void)popSize();
+ (void)popPosition();
+
+ return (*this);
+ }
+
+ template<class _Deployment, typename _KeyType, typename _ValueType, typename _HasherType>
+ COMMONAPI_EXPORT InputStream &readValue(std::unordered_map<_KeyType, _ValueType, _HasherType> &_value,
+ const _Deployment *_depl) {
+
+ typedef typename std::unordered_map<_KeyType, _ValueType, _HasherType>::value_type MapElement;
+
+ uint32_t itsSize;
+ _readValue(itsSize);
+ pushSize(itsSize);
+
+ align(8);
+ pushPosition();
+
+ _value.clear();
+ while (sizes_.top() > current_ - positions_.top()) {
+ _KeyType itsKey;
+ _ValueType itsValue;
+
+ align(8);
+ readValue(itsKey, _depl->key_);
+ readValue(itsValue, _depl->value_);
+
+ if (hasError()) {
+ break;
+ }
+
+ _value.insert(MapElement(std::move(itsKey), std::move(itsValue)));
+ }
+
+ (void)popSize();
+ (void)popPosition();
+
+ return (*this);
+ }
+
+ /**
+ * Creates a #DBusInputMessageStream which can be used to deserialize and read data from the given #DBusMessage.
+ * As no message-signature is checked, the user is responsible to ensure that the correct data types are read in the correct order.
+ *
+ * @param message the #DBusMessage from which data should be read.
+ */
+ COMMONAPI_EXPORT DBusInputStream(const CommonAPI::DBus::DBusMessage &_message);
+ COMMONAPI_EXPORT DBusInputStream(const DBusInputStream &_stream) = delete;
+
+ /**
+ * Destructor; does not call the destructor of the referred #DBusMessage. Make sure to maintain a reference to the
+ * #DBusMessage outside of the stream if you intend to make further use of the message.
+ */
+ COMMONAPI_EXPORT ~DBusInputStream();
+
+ // Marks the stream as erroneous.
+ COMMONAPI_EXPORT void setError();
+
+ /**
+ * @return An instance of #DBusError if this stream is in an erroneous state, NULL otherwise
+ */
+ COMMONAPI_EXPORT const DBusError &getError() const;
+
+ /**
+ * @return true if this stream is in an erroneous state, false otherwise.
+ */
+ COMMONAPI_EXPORT bool isErrorSet() const;
+
+ // Marks the state of the stream as cleared from all errors. Further reading is possible afterwards.
+ // The stream will have maintained the last valid position from before its state became erroneous.
+ COMMONAPI_EXPORT void clearError();
+
+ /**
+ * Aligns the stream to the given byte boundary, i.e. the stream skips as many bytes as are necessary to execute the next read
+ * starting from the given boundary.
+ *
+ * @param _boundary the byte boundary to which the stream needs to be aligned.
+ */
+ COMMONAPI_EXPORT void align(const size_t _boundary);
+
+ /**
+ * Reads the given number of bytes and returns them as an array of characters.
+ *
+ * Actually, for performance reasons this command only returns a pointer to the current position in the stream,
+ * and then increases the position of this pointer by the number of bytes indicated by the given parameter.
+ * It is the user's responsibility to actually use only the number of bytes he indicated he would use.
+ * It is assumed the user knows what kind of value is stored next in the #DBusMessage the data is streamed from.
+ * Using a reinterpret_cast on the returned pointer should then restore the original value.
+ *
+ * Example use case:
+ * @code
+ * ...
+ * inputMessageStream.alignForBasicType(sizeof(int32_t));
+ * char* const dataPtr = inputMessageStream.read(sizeof(int32_t));
+ * int32_t val = *(reinterpret_cast<int32_t*>(dataPtr));
+ * ...
+ * @endcode
+ */
+ COMMONAPI_EXPORT char *_readRaw(const size_t _size);
+
+ /**
+ * Handles all reading of basic types from a given #DBusInputMessageStream.
+ * Basic types in this context are: uint8_t, uint16_t, uint32_t, uint64_t, int8_t, int16_t, int32_t, int64_t, float, double.
+ * Any types not listed here (especially all complex types, e.g. structs, unions etc.) need to provide a
+ * specialized implementation of this operator.
+ *
+ * @tparam _Type The type of the value that is to be read from the given stream.
+ * @param _value The variable in which the retrieved value is to be stored
+ * @return The given inputMessageStream to allow for successive reading
+ */
+ template<typename _Type>
+ COMMONAPI_EXPORT DBusInputStream &_readValue(_Type &_value) {
+ if (sizeof(_value) > 1)
+ align(sizeof(_Type));
+
+ _value = *(reinterpret_cast<_Type *>(_readRaw(sizeof(_Type))));
+
+ return (*this);
+ }
+
+ COMMONAPI_EXPORT DBusInputStream &_readValue(float &_value) {
+ align(sizeof(double));
+
+ _value = (float) (*(reinterpret_cast<double*>(_readRaw(sizeof(double)))));
+ return (*this);
+ }
+
+private:
+ COMMONAPI_EXPORT void pushPosition();
+ COMMONAPI_EXPORT size_t popPosition();
+
+ COMMONAPI_EXPORT void pushSize(size_t _size);
+ COMMONAPI_EXPORT size_t popSize();
+
+ inline void skipSignature() {
+ uint8_t length;
+ _readValue(length);
+ _readRaw(length + 1);
+ }
+
+ template<typename _Type>
+ COMMONAPI_EXPORT void alignVector(typename std::enable_if<!std::is_class<_Type>::value>::type * = nullptr,
+ typename std::enable_if<!is_std_vector<_Type>::value>::type * = nullptr,
+ typename std::enable_if<!is_std_unordered_map<_Type>::value>::type * = nullptr) {
+ if (4 < sizeof(_Type)) align(8);
+ }
+
+ template<typename _Type>
+ COMMONAPI_EXPORT void alignVector(typename std::enable_if<!std::is_same<_Type, std::string>::value>::type * = nullptr,
+ typename std::enable_if<std::is_class<_Type>::value>::type * = nullptr,
+ typename std::enable_if<!is_std_vector<_Type>::value>::type * = nullptr,
+ typename std::enable_if<!is_std_unordered_map<_Type>::value>::type * = nullptr) {
+ align(8);
+ }
+
+ template<typename _Type>
+ COMMONAPI_EXPORT void alignVector(typename std::enable_if<std::is_same<_Type, std::string>::value>::type * = nullptr) {
+ // Intentionally do nothing
+ }
+
+ template<typename _Type>
+ COMMONAPI_EXPORT void alignVector(typename std::enable_if<is_std_vector<_Type>::value>::type * = nullptr) {
+ // Intentionally do nothing
+ }
+
+ template<typename _Type>
+ COMMONAPI_EXPORT void alignVector(typename std::enable_if<is_std_unordered_map<_Type>::value>::type * = nullptr) {
+ align(4);
+ }
+
+ char *begin_;
+ size_t current_;
+ size_t size_;
+ CommonAPI::DBus::DBusError* exception_;
+ CommonAPI::DBus::DBusMessage message_;
+
+ std::stack<uint32_t> sizes_;
+ std::stack<size_t> positions_;
+};
+
+} // namespace DBus
+} // namespace CommonAPI
+
+#endif // COMMONAPI_DBUS_DBUS_INPUTSTREAM_HPP_
diff --git a/include/CommonAPI/DBus/DBusInstanceAvailabilityStatusChangedEvent.hpp b/include/CommonAPI/DBus/DBusInstanceAvailabilityStatusChangedEvent.hpp
new file mode 100644
index 0000000..d520034
--- /dev/null
+++ b/include/CommonAPI/DBus/DBusInstanceAvailabilityStatusChangedEvent.hpp
@@ -0,0 +1,135 @@
+// Copyright (C) 2013-2015 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#if !defined (COMMONAPI_INTERNAL_COMPILATION)
+#error "Only <CommonAPI/CommonAPI.hpp> can be included directly, this file may disappear or change contents."
+#endif
+
+#ifndef COMMONAPI_DBUS_DBUSINSTANCEAVAILABILITYSTATUSCHANGED_EVENT_HPP_
+#define COMMONAPI_DBUS_DBUSINSTANCEAVAILABILITYSTATUSCHANGED_EVENT_HPP_
+
+#include <functional>
+#include <future>
+#include <string>
+#include <vector>
+
+#include <CommonAPI/ProxyManager.hpp>
+#include <CommonAPI/DBus/DBusAddressTranslator.hpp>
+#include <CommonAPI/DBus/DBusProxy.hpp>
+#include <CommonAPI/DBus/DBusObjectManagerStub.hpp>
+#include <CommonAPI/DBus/DBusInstanceAvailabilityStatusChangedEvent.hpp>
+#include <CommonAPI/DBus/DBusTypes.hpp>
+
+namespace CommonAPI {
+namespace DBus {
+
+// TODO Check to move logic to DBusServiceRegistry, now every proxy will deserialize the messages!
+class DBusInstanceAvailabilityStatusChangedEvent:
+ public ProxyManager::InstanceAvailabilityStatusChangedEvent,
+ public DBusProxyConnection::DBusSignalHandler {
+ public:
+ DBusInstanceAvailabilityStatusChangedEvent(DBusProxy &_proxy, const std::string &_interfaceName) :
+ proxy_(_proxy),
+ observedInterfaceName_(_interfaceName) {
+ }
+
+ virtual ~DBusInstanceAvailabilityStatusChangedEvent() {
+ proxy_.removeSignalMemberHandler(interfacesAddedSubscription_);
+ proxy_.removeSignalMemberHandler(interfacesRemovedSubscription_);
+ }
+
+ virtual void onSignalDBusMessage(const DBusMessage& dbusMessage) {
+ if (dbusMessage.hasMemberName("InterfacesAdded")) {
+ onInterfacesAddedSignal(dbusMessage);
+ } else if (dbusMessage.hasMemberName("InterfacesRemoved")) {
+ onInterfacesRemovedSignal(dbusMessage);
+ }
+ }
+
+ protected:
+ virtual void onFirstListenerAdded(const Listener&) {
+ interfacesAddedSubscription_ = proxy_.addSignalMemberHandler(
+ proxy_.getDBusAddress().getObjectPath(),
+ DBusObjectManagerStub::getInterfaceName(),
+ "InterfacesAdded",
+ "oa{sa{sv}}",
+ this);
+
+ interfacesRemovedSubscription_ = proxy_.addSignalMemberHandler(
+ proxy_.getDBusAddress().getObjectPath(),
+ DBusObjectManagerStub::getInterfaceName(),
+ "InterfacesRemoved",
+ "oas",
+ this);
+ }
+
+ virtual void onLastListenerRemoved(const Listener&) {
+ proxy_.removeSignalMemberHandler(interfacesAddedSubscription_);
+ proxy_.removeSignalMemberHandler(interfacesRemovedSubscription_);
+ }
+
+ private:
+ inline void onInterfacesAddedSignal(const DBusMessage &_message) {
+ DBusInputStream dbusInputStream(_message);
+ std::string dbusObjectPath;
+ DBusInterfacesAndPropertiesDict dbusInterfacesAndPropertiesDict;
+
+ dbusInputStream >> dbusObjectPath;
+ assert(!dbusInputStream.hasError());
+
+ dbusInputStream >> dbusInterfacesAndPropertiesDict;
+ assert(!dbusInputStream.hasError());
+
+ for (const auto& dbusInterfaceIterator : dbusInterfacesAndPropertiesDict) {
+ const std::string& dbusInterfaceName = dbusInterfaceIterator.first;
+
+ if(dbusInterfaceName == observedInterfaceName_) {
+ notifyInterfaceStatusChanged(dbusObjectPath, dbusInterfaceName, AvailabilityStatus::AVAILABLE);
+ }
+ }
+ }
+
+ inline void onInterfacesRemovedSignal(const DBusMessage &_message) {
+ DBusInputStream dbusInputStream(_message);
+ std::string dbusObjectPath;
+ std::vector<std::string> dbusInterfaceNames;
+
+ dbusInputStream >> dbusObjectPath;
+ assert(!dbusInputStream.hasError());
+
+ dbusInputStream >> dbusInterfaceNames;
+ assert(!dbusInputStream.hasError());
+
+ for (const auto& dbusInterfaceName : dbusInterfaceNames) {
+ if(dbusInterfaceName == observedInterfaceName_) {
+ notifyInterfaceStatusChanged(dbusObjectPath, dbusInterfaceName, AvailabilityStatus::NOT_AVAILABLE);
+ }
+ }
+ }
+
+ void notifyInterfaceStatusChanged(const std::string &_objectPath,
+ const std::string &_interfaceName,
+ const AvailabilityStatus &_availability) {
+ CommonAPI::Address itsAddress;
+ DBusAddress itsDBusAddress(proxy_.getDBusAddress().getService(),
+ _objectPath,
+ _interfaceName);
+
+ DBusAddressTranslator::get()->translate(itsDBusAddress, itsAddress);
+
+ notifyListeners(itsAddress.getAddress(), _availability);
+ }
+
+
+ DBusProxy &proxy_;
+ std::string observedInterfaceName_;
+ DBusProxyConnection::DBusSignalHandlerToken interfacesAddedSubscription_;
+ DBusProxyConnection::DBusSignalHandlerToken interfacesRemovedSubscription_;
+};
+
+} // namespace DBus
+} // namespace CommonAPI
+
+#endif // COMMONAPI_DBUS_DBUSINSTANCEAVAILABILITYSTATUSCHANGEDEVENT_HPP_
diff --git a/include/CommonAPI/DBus/DBusInterfaceHandler.hpp b/include/CommonAPI/DBus/DBusInterfaceHandler.hpp
new file mode 100644
index 0000000..c570975
--- /dev/null
+++ b/include/CommonAPI/DBus/DBusInterfaceHandler.hpp
@@ -0,0 +1,31 @@
+// Copyright (C) 2013-2015 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#ifndef COMMONAPI_DBUS_DBUSINTERFACEHANDLER_HPP_
+#define COMMONAPI_DBUS_DBUSINTERFACEHANDLER_HPP_
+
+#include <memory>
+
+#include <CommonAPI/DBus/DBusProxyConnection.hpp>
+#include <CommonAPI/DBus/DBusMessage.hpp>
+
+namespace CommonAPI {
+namespace DBus {
+
+class DBusInterfaceHandler {
+ public:
+ virtual ~DBusInterfaceHandler() {}
+
+ virtual const char* getMethodsDBusIntrospectionXmlData() const = 0;
+
+ virtual bool onInterfaceDBusMessage(const DBusMessage& dbusMessage) = 0;
+
+ virtual const bool hasFreedesktopProperties() = 0;
+};
+
+} // namespace dbus
+} // namespace CommonAPI
+
+#endif // COMMONAPI_DBUS_DBUSINTERFACEHANDLER_HPP_
diff --git a/include/CommonAPI/DBus/DBusMainLoopContext.hpp b/include/CommonAPI/DBus/DBusMainLoopContext.hpp
new file mode 100644
index 0000000..9230cd2
--- /dev/null
+++ b/include/CommonAPI/DBus/DBusMainLoopContext.hpp
@@ -0,0 +1,87 @@
+// Copyright (C) 2013-2015 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#if !defined (COMMONAPI_INTERNAL_COMPILATION)
+#error "Only <CommonAPI/CommonAPI.hpp> can be included directly, this file may disappear or change contents."
+#endif
+
+#ifndef COMMONAPI_DBUS_DBUSMAINLOOPCONTEXT_HPP_
+#define COMMONAPI_DBUS_DBUSMAINLOOPCONTEXT_HPP_
+
+#include <list>
+#include <memory>
+
+#include <dbus/dbus.h>
+
+#include <CommonAPI/MainLoopContext.hpp>
+
+namespace CommonAPI {
+namespace DBus {
+
+class DBusConnection;
+
+class DBusDispatchSource: public DispatchSource {
+ public:
+ DBusDispatchSource(DBusConnection* dbusConnection);
+ ~DBusDispatchSource();
+
+ bool prepare(int64_t& timeout);
+ bool check();
+ bool dispatch();
+
+ private:
+ DBusConnection* dbusConnection_;
+};
+
+class DBusWatch: public Watch {
+ public:
+ DBusWatch(::DBusWatch* libdbusWatch, std::weak_ptr<MainLoopContext>& mainLoopContext);
+
+ bool isReadyToBeWatched();
+ void startWatching();
+ void stopWatching();
+
+ void dispatch(unsigned int eventFlags);
+
+ const pollfd& getAssociatedFileDescriptor();
+
+ const std::vector<DispatchSource*>& getDependentDispatchSources();
+ void addDependentDispatchSource(DispatchSource* dispatchSource);
+ private:
+ bool isReady();
+
+ ::DBusWatch* libdbusWatch_;
+ pollfd pollFileDescriptor_;
+ std::vector<DispatchSource*> dependentDispatchSources_;
+
+ std::weak_ptr<MainLoopContext> mainLoopContext_;
+};
+
+
+class DBusTimeout: public Timeout {
+ public:
+ DBusTimeout(::DBusTimeout* libdbusTimeout, std::weak_ptr<MainLoopContext>& mainLoopContext);
+
+ bool isReadyToBeMonitored();
+ void startMonitoring();
+ void stopMonitoring();
+
+ bool dispatch();
+
+ int64_t getTimeoutInterval() const;
+ int64_t getReadyTime() const;
+ private:
+ void recalculateDueTime();
+
+ int64_t dueTimeInMs_;
+ ::DBusTimeout* libdbusTimeout_;
+ std::weak_ptr<MainLoopContext> mainLoopContext_;
+};
+
+
+} // namespace DBus
+} // namespace CommonAPI
+
+#endif // COMMONAPI_DBUS_DBUSMAINLOOPCONTEXT_HPP_
diff --git a/include/CommonAPI/DBus/DBusMessage.hpp b/include/CommonAPI/DBus/DBusMessage.hpp
new file mode 100644
index 0000000..dc5d72e
--- /dev/null
+++ b/include/CommonAPI/DBus/DBusMessage.hpp
@@ -0,0 +1,101 @@
+// Copyright (C) 2013-2015 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#if !defined (COMMONAPI_INTERNAL_COMPILATION)
+#error "Only <CommonAPI/CommonAPI.hpp> can be included directly, this file may disappear or change contents."
+#endif
+
+#ifndef COMMONAPI_DBUS_DBUSMESSAGE_HPP_
+#define COMMONAPI_DBUS_DBUSMESSAGE_HPP_
+
+#include <string>
+
+#include <dbus/dbus.h>
+
+#include <CommonAPI/Export.hpp>
+
+namespace CommonAPI {
+namespace DBus {
+
+class DBusAddress;
+class DBusConnection;
+
+class COMMONAPI_EXPORT DBusMessage {
+public:
+ enum class Type: int {
+ Invalid = DBUS_MESSAGE_TYPE_INVALID,
+ MethodCall = DBUS_MESSAGE_TYPE_METHOD_CALL,
+ MethodReturn = DBUS_MESSAGE_TYPE_METHOD_RETURN,
+ Error = DBUS_MESSAGE_TYPE_ERROR,
+ Signal = DBUS_MESSAGE_TYPE_SIGNAL
+ };
+
+ DBusMessage();
+ DBusMessage(::DBusMessage* libdbusMessage);
+ DBusMessage(::DBusMessage* libdbusMessage, bool _reference);
+ DBusMessage(const DBusMessage &_source);
+ DBusMessage(DBusMessage &&_source);
+
+ ~DBusMessage();
+
+ DBusMessage &operator=(const DBusMessage &_source);
+ DBusMessage &operator=(DBusMessage &&_source);
+ operator bool() const;
+
+ static DBusMessage createOrgFreedesktopOrgMethodCall(const std::string &_method,
+ const std::string &_signature = "");
+
+ static DBusMessage createMethodCall(const DBusAddress &_address,
+ const std::string &_method, const std::string &_signature = "");
+
+ DBusMessage createMethodReturn(const std::string &_signature) const;
+
+ DBusMessage createMethodError(const std::string &_name, const std::string &_reason = "") const;
+
+ static DBusMessage createSignal(const std::string& objectPath,
+ const std::string& interfaceName,
+ const std::string& signalName,
+ const std::string& signature = "");
+
+ const char* getSender() const;
+ const char* getObjectPath() const;
+ const char* getInterface() const;
+ const char* getMember() const;
+ const char* getSignature() const;
+ const char* getError() const;
+ const char* getDestination() const;
+ const uint32_t getSerial() const;
+
+ bool hasObjectPath(const std::string& objectPath) const;
+
+ bool hasObjectPath(const char* objectPath) const;
+ bool hasInterfaceName(const char* interfaceName) const;
+ bool hasMemberName(const char* memberName) const;
+ bool hasSignature(const char* signature) const;
+
+ const Type getType() const;
+ bool isInvalidType() const;
+ bool isMethodCallType() const;
+ bool isMethodReturnType() const;
+ bool isErrorType() const;
+ bool isSignalType() const;
+
+ char* getBodyData() const;
+ int getBodyLength() const;
+ int getBodySize() const;
+
+ bool setBodyLength(const int bodyLength);
+ bool setDestination(const char* destination);
+
+private:
+ ::DBusMessage *message_;
+
+ friend class DBusConnection;
+};
+
+} // namespace DBus
+} // namespace CommonAPI
+
+#endif // COMMONAPI_DBUS_DBUSMESSAGE_HPP_
diff --git a/include/CommonAPI/DBus/DBusMultiEvent.hpp b/include/CommonAPI/DBus/DBusMultiEvent.hpp
new file mode 100644
index 0000000..8215d4f
--- /dev/null
+++ b/include/CommonAPI/DBus/DBusMultiEvent.hpp
@@ -0,0 +1,118 @@
+// Copyright (C) 2013-2015 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#if !defined (COMMONAPI_INTERNAL_COMPILATION)
+#error "Only <CommonAPI/CommonAPI.hpp> can be included directly, this file may disappear or change contents."
+#endif
+
+#ifndef COMMONAPI_DBUS_DBUSMULTIEVENT_HPP_
+#define COMMONAPI_DBUS_DBUSMULTIEVENT_HPP_
+
+#include <string>
+#include <unordered_map>
+
+#include <CommonAPI/Event.hpp>
+
+namespace CommonAPI {
+namespace DBus {
+
+template <typename... _Arguments>
+class DBusMultiEvent {
+ public:
+ typedef std::function<SubscriptionStatus(const std::string&, const _Arguments&...)> Listener;
+ typedef std::unordered_multimap<std::string, Listener> ListenersMap;
+ typedef typename ListenersMap::iterator Subscription;
+
+ virtual ~DBusMultiEvent() {}
+
+ Subscription subscribeAll(const Listener& listener);
+ Subscription subscribe(const std::string& eventName, const Listener& listener);
+
+ void unsubscribe(Subscription listenerSubscription);
+
+ protected:
+ SubscriptionStatus notifyListeners(const std::string& name, const _Arguments&... eventArguments);
+
+ virtual void onFirstListenerAdded(const std::string& name, const Listener& listener) { }
+ virtual void onListenerAdded(const std::string& name, const Listener& listener) { }
+
+ virtual void onListenerRemoved(const std::string& name, const Listener& listener) { }
+ virtual void onLastListenerRemoved(const std::string& name, const Listener& listener) { }
+
+ private:
+ typedef std::pair<typename ListenersMap::iterator, typename ListenersMap::iterator> IteratorRange;
+ SubscriptionStatus notifyListenersRange(const std::string& name, IteratorRange listenersRange, const _Arguments&... eventArguments);
+
+ ListenersMap listenersMap_;
+};
+
+template <typename... _Arguments>
+typename DBusMultiEvent<_Arguments...>::Subscription
+DBusMultiEvent<_Arguments...>::subscribeAll(const Listener& listener) {
+ return subscribe(std::string(), listener);
+}
+
+template <typename... _Arguments>
+typename DBusMultiEvent<_Arguments...>::Subscription
+DBusMultiEvent<_Arguments...>::subscribe(const std::string& eventName, const Listener& listener) {
+ const bool firstListenerAdded = listenersMap_.empty();
+
+ auto listenerSubscription = listenersMap_.insert({eventName, listener});
+
+ if (firstListenerAdded) {
+ onFirstListenerAdded(eventName, listener);
+ }
+
+ onListenerAdded(eventName, listener);
+
+ return listenerSubscription;
+}
+
+template <typename... _Arguments>
+void DBusMultiEvent<_Arguments...>::unsubscribe(Subscription listenerSubscription) {
+ const std::string name = listenerSubscription->first;
+ const Listener listener = listenerSubscription->second;
+
+ listenersMap_.erase(listenerSubscription);
+
+ onListenerRemoved(name, listener);
+
+ const bool lastListenerRemoved = listenersMap_.empty();
+ if (lastListenerRemoved)
+ onLastListenerRemoved(name, listener);
+}
+
+template <typename... _Arguments>
+SubscriptionStatus DBusMultiEvent<_Arguments...>::notifyListeners(const std::string& name, const _Arguments&... eventArguments) {
+ const SubscriptionStatus subscriptionStatus = notifyListenersRange(name, listenersMap_.equal_range(name), eventArguments...);
+
+ if (subscriptionStatus == SubscriptionStatus::CANCEL)
+ return SubscriptionStatus::CANCEL;
+
+ return notifyListenersRange(name, listenersMap_.equal_range(std::string()), eventArguments...);
+}
+
+template <typename... _Arguments>
+SubscriptionStatus DBusMultiEvent<_Arguments...>::notifyListenersRange(
+ const std::string& name,
+ IteratorRange listenersRange,
+ const _Arguments&... eventArguments) {
+ for (auto iterator = listenersRange.first; iterator != listenersRange.second; iterator++) {
+ const Listener& listener = iterator->second;
+ const SubscriptionStatus listenerSubcriptionStatus = listener(name, eventArguments...);
+
+ if (listenerSubcriptionStatus == SubscriptionStatus::CANCEL) {
+ auto listenerIterator = iterator;
+ listenersMap_.erase(listenerIterator);
+ }
+ }
+
+ return listenersMap_.empty() ? SubscriptionStatus::CANCEL : SubscriptionStatus::RETAIN;
+}
+
+} // namespace DBus
+} // namespace CommonAPI
+
+#endif // COMMONAPI_DBUS_DBUSMULTIEVENT_HPP_
diff --git a/include/CommonAPI/DBus/DBusObjectManager.hpp b/include/CommonAPI/DBus/DBusObjectManager.hpp
new file mode 100644
index 0000000..8c7225b
--- /dev/null
+++ b/include/CommonAPI/DBus/DBusObjectManager.hpp
@@ -0,0 +1,69 @@
+// Copyright (C) 2013-2015 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#if !defined (COMMONAPI_INTERNAL_COMPILATION)
+#error "Only <CommonAPI/CommonAPI.hpp> can be included directly, this file may disappear or change contents."
+#endif
+
+#ifndef COMMONAPI_DBUS_DBUSOBJECTMANAGER_HPP_
+#define COMMONAPI_DBUS_DBUSOBJECTMANAGER_HPP_
+
+#include <CommonAPI/DBus/DBusProxyConnection.hpp>
+#include <CommonAPI/DBus/DBusMessage.hpp>
+#include <CommonAPI/DBus/DBusObjectManagerStub.hpp>
+
+namespace CommonAPI {
+namespace DBus {
+
+class DBusStubAdapter;
+class DBusInterfaceHandler;
+
+class DBusObjectManager {
+ public:
+ COMMONAPI_EXPORT DBusObjectManager(const std::shared_ptr<DBusProxyConnection>&);
+ COMMONAPI_EXPORT ~DBusObjectManager();
+
+ COMMONAPI_EXPORT bool registerDBusStubAdapter(std::shared_ptr<DBusStubAdapter> dbusStubAdapter);
+ COMMONAPI_EXPORT bool unregisterDBusStubAdapter(std::shared_ptr<DBusStubAdapter> dbusStubAdapter);
+
+ //Zusammenfassbar mit "registerDBusStubAdapter"?
+ COMMONAPI_EXPORT bool exportManagedDBusStubAdapter(const std::string& parentObjectPath, std::shared_ptr<DBusStubAdapter> dbusStubAdapter);
+ COMMONAPI_EXPORT bool unexportManagedDBusStubAdapter(const std::string& parentObjectPath, std::shared_ptr<DBusStubAdapter> dbusStubAdapter);
+
+ COMMONAPI_EXPORT bool handleMessage(const DBusMessage&);
+
+ COMMONAPI_EXPORT std::shared_ptr<DBusObjectManagerStub> getRootDBusObjectManagerStub();
+
+ private:
+ // objectPath, interfaceName
+ typedef std::pair<std::string, std::string> DBusInterfaceHandlerPath;
+
+ COMMONAPI_EXPORT bool addDBusInterfaceHandler(const DBusInterfaceHandlerPath& dbusInterfaceHandlerPath,
+ std::shared_ptr<DBusInterfaceHandler> dbusInterfaceHandler);
+
+ COMMONAPI_EXPORT bool removeDBusInterfaceHandler(const DBusInterfaceHandlerPath& dbusInterfaceHandlerPath,
+ std::shared_ptr<DBusInterfaceHandler> dbusInterfaceHandler);
+
+ COMMONAPI_EXPORT bool onIntrospectableInterfaceDBusMessage(const DBusMessage& callMessage);
+ COMMONAPI_EXPORT bool onFreedesktopPropertiesDBusMessage(const DBusMessage& callMessage);
+
+
+ typedef std::unordered_map<DBusInterfaceHandlerPath, std::shared_ptr<DBusInterfaceHandler>> DBusRegisteredObjectsTable;
+ DBusRegisteredObjectsTable dbusRegisteredObjectsTable_;
+
+ std::shared_ptr<DBusObjectManagerStub> rootDBusObjectManagerStub_;
+
+ typedef std::pair<std::shared_ptr<DBusObjectManagerStub>, uint32_t> ReferenceCountedDBusObjectManagerStub;
+ typedef std::unordered_map<std::string, ReferenceCountedDBusObjectManagerStub> RegisteredObjectManagersTable;
+ RegisteredObjectManagersTable managerStubs_;
+
+ std::weak_ptr<DBusProxyConnection> dbusConnection_;
+ std::recursive_mutex objectPathLock_;
+};
+
+} // namespace DBus
+} // namespace CommonAPI
+
+#endif // COMMONAPI_DBUS_DBUSOBJECTMANAGER_HPP_
diff --git a/include/CommonAPI/DBus/DBusObjectManagerStub.hpp b/include/CommonAPI/DBus/DBusObjectManagerStub.hpp
new file mode 100644
index 0000000..a16578b
--- /dev/null
+++ b/include/CommonAPI/DBus/DBusObjectManagerStub.hpp
@@ -0,0 +1,125 @@
+// Copyright (C) 2013-2015 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#ifndef COMMONAPI_DBUS_DBUSFREEDESKTOPOBJECTMANAGERSTUB_HPP_
+#define COMMONAPI_DBUS_DBUSFREEDESKTOPOBJECTMANAGERSTUB_HPP_
+
+#include <memory>
+#include <mutex>
+#include <string>
+
+#include <CommonAPI/DBus/DBusInterfaceHandler.hpp>
+
+namespace CommonAPI {
+namespace DBus {
+
+class DBusStubAdapter;
+
+/**
+ * Stub for standard <a href="http://dbus.freedesktop.org/doc/dbus-specification.html#standard-interfaces-objectmanager">org.freedesktop.dbus.ObjectManager</a> interface.
+ *
+ * Instantiated within a manager stub and it must hold reference to all registered objects.
+ * Whenever the manager gets destroyed all references to registered objects are lost too.
+ * This duplicates the semantic of the CommonAPI::ServicePublisher class.
+ *
+ * Only one DBusStubAdapter instance could be registered per DBusObjectManagerStub instance.
+ *
+ * The owner of the DBusObjectManagerStub instance must take care of registering and unregistering it.
+ *
+ * Example stub life cycle:
+ * - create CommonAPI::ServicePublisher
+ * - create stub A
+ * - register stub A to CommonAPI::ServicePublisher
+ * - create stub B
+ * - register stub B with stub A as object manager
+ * - drop all references to stub B, stub A keeps a reference to stub B
+ * - drop all references to stub A, CommonAPI::ServicePublisher keeps a reference to stub A
+ * - reference overview: Application > CommonAPI::ServicePublisher > Stub A > Stub B
+ * - drop all references to CommonAPI::ServicePublisher causes all object references to be dropped
+ */
+class DBusObjectManagerStub : public DBusInterfaceHandler {
+public:
+ // serialization trick: use bool instead of variant since we never serialize it
+ typedef std::unordered_map<std::string, bool> DBusPropertiesChangedDict;
+ typedef std::unordered_map<std::string, DBusPropertiesChangedDict> DBusInterfacesAndPropertiesDict;
+ typedef std::unordered_map<std::string, DBusInterfacesAndPropertiesDict> DBusObjectPathAndInterfacesDict;
+
+public:
+ COMMONAPI_EXPORT DBusObjectManagerStub(const std::string& dbusObjectPath, const std::shared_ptr<DBusProxyConnection>&);
+
+ /**
+ * Unregisters all currently registered DBusStubAdapter instances from the DBusServicePublisher
+ */
+ COMMONAPI_EXPORT virtual ~DBusObjectManagerStub();
+
+ /**
+ * Export DBusStubAdapter instance with the current DBusObjectManagerStub instance.
+ *
+ * The DBusStubAdapter must be registered with the DBusServicePublisher!
+ *
+ * On registering a
+ * <a href="http://dbus.freedesktop.org/doc/dbus-specification.html#standard-interfaces-objectmanager">InsterfaceAdded</a>
+ * signal will be emitted with the DBusObjectManagerStub instance's current D-Bus object path.
+ *
+ * @param dbusStubAdapter a refernce to DBusStubAdapter instance
+ *
+ * @return false if the @a dbusStubAdapter instance was already registered
+ * @return false if sending the InterfaceAdded signal fails
+ *
+ * @see ~DBusObjectManagerStub()
+ * @see CommonAPI::ServicePublisher
+ * @see DBusObjectManager
+ */
+ COMMONAPI_EXPORT bool exportManagedDBusStubAdapter(std::shared_ptr<DBusStubAdapter> dbusStubAdapter);
+
+ /**
+ * Unexport DBusStubAdapter instance from this DBusObjectManagerStub instance.
+ *
+ * On unregistering a
+ * <a href="http://dbus.freedesktop.org/doc/dbus-specification.html#standard-interfaces-objectmanager">InsterfaceRemoved</a>
+ * signal will be emitted with the DBusObjectManagerStub instance's current D-Bus object path.
+ *
+ * @param dbusStubAdapter
+ *
+ * @return false if @a dbusStubAdapter wasn't registered
+ * @return true even if sending the InterfaceRemoved signal fails
+ *
+ * @see exportDBusStubAdapter()
+ */
+ COMMONAPI_EXPORT bool unexportManagedDBusStubAdapter(std::shared_ptr<DBusStubAdapter> dbusStubAdapter);
+
+ COMMONAPI_EXPORT bool isDBusStubAdapterExported(std::shared_ptr<DBusStubAdapter> dbusStubAdapter);
+
+ COMMONAPI_EXPORT const std::string& getDBusObjectPath() const;
+ COMMONAPI_EXPORT static const char* getInterfaceName();
+
+ COMMONAPI_EXPORT virtual const char* getMethodsDBusIntrospectionXmlData() const;
+ COMMONAPI_EXPORT virtual bool onInterfaceDBusMessage(const DBusMessage& dbusMessage);
+ COMMONAPI_EXPORT virtual const bool hasFreedesktopProperties();
+
+ private:
+ COMMONAPI_EXPORT bool registerDBusStubAdapter(std::shared_ptr<DBusStubAdapter> dbusStubAdapter);
+ COMMONAPI_EXPORT bool unregisterDBusStubAdapter(std::shared_ptr<DBusStubAdapter> dbusStubAdapter);
+
+ COMMONAPI_EXPORT bool emitInterfacesAddedSignal(std::shared_ptr<DBusStubAdapter> dbusStubAdapter,
+ const std::shared_ptr<DBusProxyConnection>& dbusConnection) const;
+
+ COMMONAPI_EXPORT bool emitInterfacesRemovedSignal(std::shared_ptr<DBusStubAdapter> dbusStubAdapter,
+ const std::shared_ptr<DBusProxyConnection>& dbusConnection) const;
+
+ std::string dbusObjectPath_;
+ std::weak_ptr<DBusProxyConnection> dbusConnection_;
+
+ typedef std::unordered_map<std::string, std::shared_ptr<DBusStubAdapter>> DBusInterfacesMap;
+ typedef std::unordered_map<std::string, DBusInterfacesMap> DBusObjectPathsMap;
+ DBusObjectPathsMap registeredDBusObjectPathsMap_;
+
+ std::mutex dbusObjectManagerStubLock_;
+};
+
+} // namespace DBus
+} // namespace CommonAPI
+
+#endif // COMMONAPI_DBUS_DBUSFREEDESKTOPOBJECTMANAGERSTUB_HPP_
diff --git a/include/CommonAPI/DBus/DBusOutputStream.hpp b/include/CommonAPI/DBus/DBusOutputStream.hpp
new file mode 100644
index 0000000..1148f3e
--- /dev/null
+++ b/include/CommonAPI/DBus/DBusOutputStream.hpp
@@ -0,0 +1,398 @@
+// Copyright (C) 2014-2015 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#if !defined (COMMONAPI_INTERNAL_COMPILATION)
+#error "Only <CommonAPI/CommonAPI.hpp> can be included directly, this file may disappear or change contents."
+#endif
+
+#ifndef COMMONAPI_DBUS_DBUSOUTPUTSTREAM_HPP_
+#define COMMONAPI_DBUS_DBUSOUTPUTSTREAM_HPP_
+
+#include <cassert>
+#include <cstring>
+#include <memory>
+#include <stack>
+#include <string>
+#include <vector>
+
+#include <CommonAPI/Export.hpp>
+#include <CommonAPI/Logger.hpp>
+#include <CommonAPI/OutputStream.hpp>
+#include <CommonAPI/DBus/DBusDeployment.hpp>
+#include <CommonAPI/DBus/DBusError.hpp>
+#include <CommonAPI/DBus/DBusHelper.hpp>
+#include <CommonAPI/DBus/DBusMessage.hpp>
+#include <CommonAPI/DBus/DBusTypeOutputStream.hpp>
+
+namespace CommonAPI {
+namespace DBus {
+
+/**
+ * @class DBusOutputMessageStream
+ *
+ * Used to serialize and write data into a #DBusMessage. For all data types that may be written to a #DBusMessage, a "<<"-operator should be defined to handle the writing
+ * (this operator is predefined for all basic data types and for vectors). The signature that has to be written to the #DBusMessage separately is assumed
+ * to match the actual data that is inserted via the #DBusOutputMessageStream.
+ */
+class DBusOutputStream: public OutputStream<DBusOutputStream> {
+public:
+
+ /**
+ * Creates a #DBusOutputMessageStream which can be used to serialize and write data into the given #DBusMessage. Any data written is buffered within the stream.
+ * Remember to call flush() when you are done with writing: Only then the data actually is written to the #DBusMessage.
+ *
+ * @param dbusMessage The #DBusMessage any data pushed into this stream should be written to.
+ */
+ COMMONAPI_EXPORT DBusOutputStream(DBusMessage dbusMessage);
+
+ COMMONAPI_EXPORT OutputStream &writeValue(const bool &_value, const EmptyDeployment *_depl) {
+ uint32_t tmp = (_value ? 1 : 0);
+ return _writeValue(tmp);
+ }
+
+ COMMONAPI_EXPORT OutputStream &writeValue(const int8_t &_value, const EmptyDeployment *_depl) {
+ return _writeValue(_value);
+ }
+
+ COMMONAPI_EXPORT OutputStream &writeValue(const int16_t &_value, const EmptyDeployment *_depl) {
+ return _writeValue(_value);
+ }
+
+ COMMONAPI_EXPORT OutputStream &writeValue(const int32_t &_value, const EmptyDeployment *_depl) {
+ return _writeValue(_value);
+ }
+
+ COMMONAPI_EXPORT OutputStream &writeValue(const int64_t &_value, const EmptyDeployment *_depl) {
+ return _writeValue(_value);
+ }
+
+ COMMONAPI_EXPORT OutputStream &writeValue(const uint8_t &_value, const EmptyDeployment *_depl) {
+ return _writeValue(_value);
+ }
+
+ COMMONAPI_EXPORT OutputStream &writeValue(const uint16_t &_value, const EmptyDeployment *_depl) {
+ return _writeValue(_value);
+ }
+
+ COMMONAPI_EXPORT OutputStream &writeValue(const uint32_t &_value, const EmptyDeployment *_depl) {
+ return _writeValue(_value);
+ }
+
+ COMMONAPI_EXPORT OutputStream &writeValue(const uint64_t &_value, const EmptyDeployment *_depl) {
+ return _writeValue(_value);
+ }
+
+ COMMONAPI_EXPORT OutputStream &writeValue(const float &_value, const EmptyDeployment *_depl) {
+ return _writeValue(static_cast<double>(_value));
+ }
+
+ COMMONAPI_EXPORT OutputStream &writeValue(const double &_value, const EmptyDeployment *_depl) {
+ return _writeValue(_value);
+ }
+
+ COMMONAPI_EXPORT OutputStream &writeValue(const std::string &_value, const EmptyDeployment * = nullptr) {
+ return writeString(_value.c_str(), _value.length());
+ }
+
+ COMMONAPI_EXPORT OutputStream &writeValue(const Version &_value, const EmptyDeployment *_depl = nullptr) {
+ align(8);
+ writeValue(_value.Major, _depl);
+ writeValue(_value.Minor, _depl);
+ return (*this);
+ }
+
+ template<class _Deployment, typename _Base>
+ COMMONAPI_EXPORT OutputStream &writeValue(const Enumeration<_Base> &_value, const _Deployment *_depl = nullptr) {
+ return writeValue(static_cast<_Base>(_value), _depl);
+ }
+
+ template<class _Deployment, typename... _Types>
+ COMMONAPI_EXPORT OutputStream &writeValue(const Struct<_Types...> &_value, const _Deployment *_depl = nullptr) {
+ align(8);
+
+ const auto itsSize(std::tuple_size<std::tuple<_Types...>>::value);
+ StructWriter<itsSize-1, DBusOutputStream, Struct<_Types...>, _Deployment>{}((*this), _value, _depl);
+
+ return (*this);
+ }
+
+ template<class _Deployment, class _PolymorphicStruct>
+ COMMONAPI_EXPORT OutputStream &writeValue(const std::shared_ptr<_PolymorphicStruct> &_value, const _Deployment *_depl = nullptr) {
+ align(8);
+ _writeValue(_value->getSerial());
+
+ DBusTypeOutputStream typeOutput;
+ typeOutput.writeType(_value);
+ writeSignature(typeOutput.getSignature());
+
+ align(8);
+ _value->template writeValue<>((*this), _depl);
+
+ return (*this);
+ }
+
+ template<typename... _Types>
+ COMMONAPI_EXPORT OutputStream &writeValue(const Variant<_Types...> &_value, const CommonAPI::EmptyDeployment *_depl = nullptr) {
+ align(8);
+ writeValue(_value.getValueType(), static_cast<EmptyDeployment *>(nullptr));
+
+ DBusTypeOutputStream typeOutput;
+ TypeOutputStreamWriteVisitor<DBusTypeOutputStream> typeVisitor(typeOutput);
+ ApplyVoidVisitor<TypeOutputStreamWriteVisitor<DBusTypeOutputStream>,
+ Variant<_Types...>, _Types...>::visit(typeVisitor, _value);
+ writeSignature(typeOutput.getSignature());
+
+ OutputStreamWriteVisitor<DBusOutputStream> valueVisitor(*this);
+ ApplyVoidVisitor<OutputStreamWriteVisitor<DBusOutputStream>,
+ Variant<_Types...>, _Types...>::visit(valueVisitor, _value);
+
+ return (*this);
+ }
+
+ template<typename _Deployment, typename... _Types>
+ COMMONAPI_EXPORT OutputStream &writeValue(const Variant<_Types...> &_value, const _Deployment *_depl = nullptr) {
+ if (_depl != nullptr && _depl->isFreeDesktop_) {
+ align(1);
+ } else {
+ align(8);
+ writeValue(_value.getValueType(), static_cast<EmptyDeployment *>(nullptr));
+ }
+
+ DBusTypeOutputStream typeOutput;
+ TypeOutputStreamWriteVisitor<DBusTypeOutputStream> typeVisitor(typeOutput);
+ ApplyVoidVisitor<TypeOutputStreamWriteVisitor<DBusTypeOutputStream>,
+ Variant<_Types...>, _Types...>::visit(typeVisitor, _value);
+ writeSignature(typeOutput.getSignature());
+
+ OutputStreamWriteVisitor<DBusOutputStream> valueVisitor(*this);
+ ApplyVoidVisitor<OutputStreamWriteVisitor<DBusOutputStream>,
+ Variant<_Types...>, _Types...>::visit(valueVisitor, _value);
+
+ return (*this);
+ }
+
+ template<typename _ElementType>
+ COMMONAPI_EXPORT OutputStream &writeValue(const std::vector<_ElementType> &_value,
+ const EmptyDeployment *_depl) {
+ align(sizeof(uint32_t));
+ pushPosition();
+ _writeValue(static_cast<uint32_t>(0)); // Placeholder
+
+ alignVector<_ElementType>();
+ pushPosition(); // Start of vector data
+
+ for (auto i : _value) {
+ writeValue(i, _depl);
+ if (hasError()) {
+ break;
+ }
+ }
+
+ // Write number of written bytes to placeholder position
+ uint32_t length = getPosition() - popPosition();
+ _writeValueAt(popPosition(), length);
+
+ return (*this);
+ }
+
+ template<class _Deployment, typename _ElementType>
+ COMMONAPI_EXPORT OutputStream &writeValue(const std::vector<_ElementType> &_value,
+ const _Deployment *_depl) {
+ align(sizeof(uint32_t));
+ pushPosition();
+ _writeValue(static_cast<uint32_t>(0)); // Placeholder
+
+ alignVector<_ElementType>();
+ pushPosition(); // Start of vector data
+
+ for (auto i : _value) {
+ writeValue(i, _depl->elementDepl_);
+ if (hasError()) {
+ break;
+ }
+ }
+
+ // Write number of written bytes to placeholder position
+ uint32_t length = getPosition() - popPosition();
+ _writeValueAt(popPosition(), length);
+
+ return (*this);
+ }
+
+ template<typename _KeyType, typename _ValueType, typename _HasherType>
+ COMMONAPI_EXPORT OutputStream &writeValue(const std::unordered_map<_KeyType, _ValueType, _HasherType> &_value,
+ const EmptyDeployment *_depl) {
+ align(sizeof(uint32_t));
+ pushPosition();
+ _writeValue(static_cast<uint32_t>(0)); // Placeholder
+
+ align(8);
+ pushPosition(); // Start of map data
+
+ for (auto v : _value) {
+ align(8);
+ writeValue(v.first, static_cast<EmptyDeployment *>(nullptr));
+ writeValue(v.second, static_cast<EmptyDeployment *>(nullptr));
+
+ if (hasError()) {
+ return (*this);
+ }
+ }
+
+ // Write number of written bytes to placeholder position
+ uint32_t length = getPosition() - popPosition();
+ _writeValueAt(popPosition(), length);
+ return (*this);
+ }
+
+ template<class _Deployment, typename _KeyType, typename _ValueType, typename _HasherType>
+ COMMONAPI_EXPORT OutputStream &writeValue(const std::unordered_map<_KeyType, _ValueType, _HasherType> &_value,
+ const _Deployment *_depl) {
+ align(sizeof(uint32_t));
+ pushPosition();
+ _writeValue(static_cast<uint32_t>(0)); // Placeholder
+
+ align(8);
+ pushPosition(); // Start of map data
+
+ for (auto v : _value) {
+ align(8);
+ writeValue(v.first, _depl->key_);
+ writeValue(v.second, _depl->value_);
+
+ if (hasError()) {
+ return (*this);
+ }
+ }
+
+ // Write number of written bytes to placeholder position
+ uint32_t length = getPosition() - popPosition();
+ _writeValueAt(popPosition(), length);
+ return (*this);
+ }
+
+ /**
+ * Writes the data that was buffered within this #DBusOutputMessageStream to the #DBusMessage that was given to the constructor. Each call to flush()
+ * will completely override the data that currently is contained in the #DBusMessage. The data that is buffered in this #DBusOutputMessageStream is
+ * not deleted by calling flush().
+ */
+ COMMONAPI_EXPORT void flush();
+
+ COMMONAPI_EXPORT bool hasError() const;
+
+private:
+ COMMONAPI_EXPORT size_t getPosition();
+ COMMONAPI_EXPORT void pushPosition();
+ COMMONAPI_EXPORT size_t popPosition();
+
+ template<typename _Type>
+ COMMONAPI_EXPORT void alignVector(typename std::enable_if<!std::is_class<_Type>::value>::type * = nullptr,
+ typename std::enable_if<!is_std_vector<_Type>::value>::type * = nullptr,
+ typename std::enable_if<!is_std_unordered_map<_Type>::value>::type * = nullptr) {
+ if (4 < sizeof(_Type)) align(8);
+ }
+
+ template<typename _Type>
+ COMMONAPI_EXPORT void alignVector(typename std::enable_if<!std::is_same<_Type, std::string>::value>::type * = nullptr,
+ typename std::enable_if<std::is_class<_Type>::value>::type * = nullptr,
+ typename std::enable_if<!is_std_vector<_Type>::value>::type * = nullptr,
+ typename std::enable_if<!is_std_unordered_map<_Type>::value>::type * = nullptr) {
+ align(8);
+ }
+
+ template<typename _Type>
+ COMMONAPI_EXPORT void alignVector(typename std::enable_if<std::is_same<_Type, std::string>::value>::type * = nullptr) {
+ // Intentionally do nothing
+ }
+
+ template<typename _Type>
+ COMMONAPI_EXPORT void alignVector(typename std::enable_if<is_std_vector<_Type>::value>::type * = nullptr) {
+ // Intentionally do nothing
+ }
+
+ template<typename _Type>
+ COMMONAPI_EXPORT void alignVector(typename std::enable_if<is_std_unordered_map<_Type>::value>::type * = nullptr) {
+ align(4);
+ }
+
+ COMMONAPI_EXPORT void setError();
+
+ /**
+ * Reserves the given number of bytes for writing, thereby negating the need to dynamically allocate memory while writing.
+ * Use this method for optimization: If possible, reserve as many bytes as you need for your data before doing any writing.
+ *
+ * @param numOfBytes The number of bytes that should be reserved for writing.
+ */
+ COMMONAPI_EXPORT void reserveMemory(size_t numOfBytes);
+
+ template<typename _Type>
+ COMMONAPI_EXPORT DBusOutputStream &_writeValue(const _Type &_value) {
+ if (sizeof(_Type) > 1)
+ align(sizeof(_Type));
+
+ _writeRaw(reinterpret_cast<const char*>(&_value), sizeof(_Type));
+ return (*this);
+ }
+
+ template<typename _Type>
+ COMMONAPI_EXPORT void _writeValueAt(size_t _position, const _Type &_value) {
+ assert(_position + sizeof(_Type) <= payload_.size());
+ _writeRawAt(reinterpret_cast<const char *>(&_value),
+ sizeof(_Type), _position);
+ }
+
+ COMMONAPI_EXPORT DBusOutputStream &writeString(const char *_data, const uint32_t &_length);
+
+ /**
+ * Fills the stream with 0-bytes to make the next value be aligned to the boundary given.
+ * This means that as many 0-bytes are written to the buffer as are necessary
+ * to make the next value start with the given alignment.
+ *
+ * @param alignBoundary The byte-boundary to which the next value should be aligned.
+ */
+ COMMONAPI_EXPORT void align(const size_t _boundary);
+
+ /**
+ * Takes sizeInByte characters, starting from the character which val points to, and stores them for later writing.
+ * When calling flush(), all values that were written to this stream are copied into the payload of the #DBusMessage.
+ *
+ * The array of characters might be created from a pointer to a given value by using a reinterpret_cast. Example:
+ * @code
+ * ...
+ * int32_t val = 15;
+ * outputMessageStream.alignForBasicType(sizeof(int32_t));
+ * const char* const reinterpreted = reinterpret_cast<const char*>(&val);
+ * outputMessageStream.writeValue(reinterpreted, sizeof(int32_t));
+ * ...
+ * @endcode
+ *
+ * @param _data The array of chars that should serve as input
+ * @param _size The number of bytes that should be written
+ * @return true if writing was successful, false otherwise.
+ *
+ * @see DBusOutputMessageStream()
+ * @see flush()
+ */
+ COMMONAPI_EXPORT void _writeRaw(const char *_data, const size_t _size);
+ COMMONAPI_EXPORT void _writeRawAt(const char *_data, const size_t _size, size_t _position);
+
+protected:
+ std::string payload_;
+
+private:
+ COMMONAPI_EXPORT void writeSignature(const std::string& signature);
+
+ COMMONAPI_EXPORT size_t getCurrentStreamPosition();
+
+ DBusError dbusError_;
+ DBusMessage dbusMessage_;
+
+ std::stack<size_t> positions_;
+};
+
+} // namespace DBus
+} // namespace CommonAPI
+
+#endif // COMMONAPI_DBUS_DBUSOUTPUTSTREAM_PPH_
diff --git a/include/CommonAPI/DBus/DBusProxy.hpp b/include/CommonAPI/DBus/DBusProxy.hpp
new file mode 100644
index 0000000..af40863
--- /dev/null
+++ b/include/CommonAPI/DBus/DBusProxy.hpp
@@ -0,0 +1,84 @@
+// Copyright (C) 2014-2015 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#if !defined (COMMONAPI_INTERNAL_COMPILATION)
+#error "Only <CommonAPI/CommonAPI.hpp> can be included directly, this file may disappear or change contents."
+#endif
+
+#ifndef COMMONAPI_DBUS_DBUSPROXY_HPP_
+#define COMMONAPI_DBUS_DBUSPROXY_HPP_
+
+#include <functional>
+#include <memory>
+#include <string>
+
+#include <CommonAPI/Export.hpp>
+#include <CommonAPI/DBus/DBusAttribute.hpp>
+#include <CommonAPI/DBus/DBusServiceRegistry.hpp>
+
+namespace CommonAPI {
+namespace DBus {
+
+class DBusProxyStatusEvent
+ : public ProxyStatusEvent {
+ friend class DBusProxy;
+
+ public:
+ DBusProxyStatusEvent(DBusProxy* dbusProxy);
+ virtual ~DBusProxyStatusEvent() {}
+
+ protected:
+ virtual void onListenerAdded(const Listener& listener);
+
+ DBusProxy* dbusProxy_;
+};
+
+
+class DBusProxy
+ : public DBusProxyBase {
+public:
+ COMMONAPI_EXPORT DBusProxy(const DBusAddress &_address,
+ const std::shared_ptr<DBusProxyConnection> &_connection);
+ COMMONAPI_EXPORT virtual ~DBusProxy();
+
+ COMMONAPI_EXPORT virtual ProxyStatusEvent& getProxyStatusEvent();
+ COMMONAPI_EXPORT virtual InterfaceVersionAttribute& getInterfaceVersionAttribute();
+
+ COMMONAPI_EXPORT virtual bool isAvailable() const;
+ COMMONAPI_EXPORT virtual bool isAvailableBlocking() const;
+
+ COMMONAPI_EXPORT DBusProxyConnection::DBusSignalHandlerToken subscribeForSelectiveBroadcastOnConnection(
+ bool& subscriptionAccepted,
+ const std::string& objectPath,
+ const std::string& interfaceName,
+ const std::string& interfaceMemberName,
+ const std::string& interfaceMemberSignature,
+ DBusProxyConnection::DBusSignalHandler* dbusSignalHandler);
+ COMMONAPI_EXPORT void unsubscribeFromSelectiveBroadcast(const std::string& eventName,
+ DBusProxyConnection::DBusSignalHandlerToken subscription,
+ const DBusProxyConnection::DBusSignalHandler* dbusSignalHandler);
+
+ COMMONAPI_EXPORT void init();
+
+private:
+ COMMONAPI_EXPORT DBusProxy(const DBusProxy &) = delete;
+
+ COMMONAPI_EXPORT void onDBusServiceInstanceStatus(const AvailabilityStatus& availabilityStatus);
+
+ DBusProxyStatusEvent dbusProxyStatusEvent_;
+ DBusServiceRegistry::DBusServiceSubscription dbusServiceRegistrySubscription_;
+ AvailabilityStatus availabilityStatus_;
+
+ DBusReadonlyAttribute<InterfaceVersionAttribute> interfaceVersionAttribute_;
+
+ std::shared_ptr<DBusServiceRegistry> dbusServiceRegistry_;
+};
+
+
+} // namespace DBus
+} // namespace CommonAPI
+
+#endif // COMMONAPI_DBUS_DBUSPROXY_HPP_
+
diff --git a/include/CommonAPI/DBus/DBusProxyAsyncCallbackHandler.hpp b/include/CommonAPI/DBus/DBusProxyAsyncCallbackHandler.hpp
new file mode 100644
index 0000000..eac96d2
--- /dev/null
+++ b/include/CommonAPI/DBus/DBusProxyAsyncCallbackHandler.hpp
@@ -0,0 +1,78 @@
+// Copyright (C) 2014-2015 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#if !defined (COMMONAPI_INTERNAL_COMPILATION)
+#error "Only <CommonAPI/CommonAPI.hpp> can be included directly, this file may disappear or change contents."
+#endif
+
+#ifndef COMMONAPI_DBUS_DBUSPROXYASYNCCALLBACKHANDLER_HPP_
+#define COMMONAPI_DBUS_DBUSPROXYASYNCCALLBACKHANDLER_HPP_
+
+#include <functional>
+#include <future>
+#include <memory>
+
+#include <CommonAPI/DBus/DBusHelper.hpp>
+#include <CommonAPI/DBus/DBusMessage.hpp>
+#include <CommonAPI/DBus/DBusProxyConnection.hpp>
+#include <CommonAPI/DBus/DBusSerializableArguments.hpp>
+
+namespace CommonAPI {
+namespace DBus {
+
+template<typename ... _ArgTypes>
+class DBusProxyAsyncCallbackHandler: public DBusProxyConnection::DBusMessageReplyAsyncHandler {
+ public:
+ typedef std::function<void(CallStatus, _ArgTypes...)> FunctionType;
+
+ static std::unique_ptr<DBusProxyConnection::DBusMessageReplyAsyncHandler> create(
+ FunctionType&& callback, std::tuple<_ArgTypes...> args) {
+ return std::unique_ptr<DBusProxyConnection::DBusMessageReplyAsyncHandler>(
+ new DBusProxyAsyncCallbackHandler(std::move(callback), args));
+ }
+
+ DBusProxyAsyncCallbackHandler() = delete;
+ DBusProxyAsyncCallbackHandler(FunctionType&& callback, std::tuple<_ArgTypes...> args):
+ callback_(std::move(callback)), args_(args) {
+ }
+ virtual ~DBusProxyAsyncCallbackHandler() {}
+
+ virtual std::future<CallStatus> getFuture() {
+ return promise_.get_future();
+ }
+
+ virtual void onDBusMessageReply(const CallStatus& dbusMessageCallStatus, const DBusMessage& dbusMessage) {
+ promise_.set_value(handleDBusMessageReply(dbusMessageCallStatus, dbusMessage, typename make_sequence<sizeof...(_ArgTypes)>::type(), args_));
+ }
+
+ private:
+ template <int... _ArgIndices>
+ inline CallStatus handleDBusMessageReply(const CallStatus dbusMessageCallStatus, const DBusMessage& dbusMessage, index_sequence<_ArgIndices...>, std::tuple<_ArgTypes...> argTuple) const {
+ CallStatus callStatus = dbusMessageCallStatus;
+
+ if (dbusMessageCallStatus == CallStatus::SUCCESS) {
+ if (!dbusMessage.isErrorType()) {
+ DBusInputStream dbusInputStream(dbusMessage);
+ const bool success = DBusSerializableArguments<_ArgTypes...>::deserialize(dbusInputStream, std::get<_ArgIndices>(argTuple)...);
+ if (!success)
+ callStatus = CallStatus::REMOTE_ERROR;
+ } else {
+ callStatus = CallStatus::REMOTE_ERROR;
+ }
+ }
+
+ callback_(callStatus, std::move(std::get<_ArgIndices>(argTuple))...);
+ return callStatus;
+ }
+
+ std::promise<CallStatus> promise_;
+ const FunctionType callback_;
+ std::tuple<_ArgTypes...> args_;
+};
+
+} // namespace DBus
+} // namespace CommonAPI
+
+#endif // COMMONAPI_DBUS_DBUSPROXYASYNCCALLBACKHANDLER_HPP_
diff --git a/include/CommonAPI/DBus/DBusProxyBase.hpp b/include/CommonAPI/DBus/DBusProxyBase.hpp
new file mode 100644
index 0000000..85c746c
--- /dev/null
+++ b/include/CommonAPI/DBus/DBusProxyBase.hpp
@@ -0,0 +1,72 @@
+// Copyright (C) 2014-2015 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#if !defined (COMMONAPI_INTERNAL_COMPILATION)
+#error "Only <CommonAPI/CommonAPI.hpp> can be included directly, this file may disappear or change contents."
+#endif
+
+#ifndef COMMONAPI_DBUS_DBUSPROXYBASE_HPP_
+#define COMMONAPI_DBUS_DBUSPROXYBASE_HPP_
+
+#include <functional>
+#include <memory>
+#include <string>
+
+#include <CommonAPI/Export.hpp>
+#include <CommonAPI/Proxy.hpp>
+#include <CommonAPI/Types.hpp>
+
+#include <CommonAPI/DBus/DBusAddress.hpp>
+#include <CommonAPI/DBus/DBusProxyConnection.hpp>
+
+namespace CommonAPI {
+namespace DBus {
+
+class DBusAddress;
+
+class DBusProxyBase
+ : public virtual CommonAPI::Proxy {
+public:
+ COMMONAPI_EXPORT DBusProxyBase(const DBusAddress &_address,
+ const std::shared_ptr<DBusProxyConnection> &_connection);
+ COMMONAPI_EXPORT virtual ~DBusProxyBase() {}
+
+ COMMONAPI_EXPORT const DBusAddress &getDBusAddress() const;
+ COMMONAPI_EXPORT const std::shared_ptr<DBusProxyConnection> &getDBusConnection() const;
+
+ COMMONAPI_EXPORT DBusMessage createMethodCall(const std::string &_method,
+ const std::string &_signature = "") const;
+
+ COMMONAPI_EXPORT DBusProxyConnection::DBusSignalHandlerToken addSignalMemberHandler(
+ const std::string& signalName,
+ const std::string& signalSignature,
+ DBusProxyConnection::DBusSignalHandler* dbusSignalHandler,
+ const bool justAddFilter = false);
+
+ COMMONAPI_EXPORT DBusProxyConnection::DBusSignalHandlerToken addSignalMemberHandler(
+ const std::string &objectPath,
+ const std::string &interfaceName,
+ const std::string &signalName,
+ const std::string &signalSignature,
+ DBusProxyConnection::DBusSignalHandler *dbusSignalHandler,
+ const bool justAddFilter = false);
+
+ COMMONAPI_EXPORT bool removeSignalMemberHandler(
+ const DBusProxyConnection::DBusSignalHandlerToken &_token,
+ const DBusProxyConnection::DBusSignalHandler *_handler = NULL);
+
+ COMMONAPI_EXPORT virtual void init() = 0;
+
+ private:
+ COMMONAPI_EXPORT DBusProxyBase(const DBusProxyBase &) = delete;
+
+ DBusAddress dbusAddress_;
+ std::shared_ptr<DBusProxyConnection> connection_;
+};
+
+} // namespace DBus
+} // namespace CommonAPI
+
+#endif // COMMONAPI_DBUS_DBUSPROXYBASE_HPP_
diff --git a/include/CommonAPI/DBus/DBusProxyConnection.hpp b/include/CommonAPI/DBus/DBusProxyConnection.hpp
new file mode 100644
index 0000000..cbef54d
--- /dev/null
+++ b/include/CommonAPI/DBus/DBusProxyConnection.hpp
@@ -0,0 +1,127 @@
+// Copyright (C) 2013-2015 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#if !defined (COMMONAPI_INTERNAL_COMPILATION)
+#error "Only <CommonAPI/CommonAPI.hpp> can be included directly, this file may disappear or change contents."
+#endif
+
+#ifndef COMMONAPI_DBUS_DBUSPROXYCONNECTION_HPP_
+#define COMMONAPI_DBUS_DBUSPROXYCONNECTION_HPP_
+
+#include <cstdint>
+#include <functional>
+#include <future>
+#include <memory>
+#include <set>
+#include <tuple>
+#include <unordered_map>
+#include <utility>
+#include <vector>
+
+#include <CommonAPI/Attribute.hpp>
+#include <CommonAPI/Event.hpp>
+#include <CommonAPI/Types.hpp>
+#include <CommonAPI/DBus/DBusConfig.hpp>
+#include <CommonAPI/DBus/DBusError.hpp>
+#include <CommonAPI/DBus/DBusMessage.hpp>
+#include <CommonAPI/DBus/DBusFunctionalHash.hpp>
+
+namespace CommonAPI {
+namespace DBus {
+
+typedef std::function<void(const DBusMessage&)> DBusMessageHandler;
+
+class DBusDaemonProxy;
+class DBusServiceRegistry;
+class DBusObjectManager;
+class DBusProxy;
+
+class DBusProxyConnection {
+ public:
+ class DBusMessageReplyAsyncHandler {
+ public:
+ virtual ~DBusMessageReplyAsyncHandler() {}
+ virtual std::future<CallStatus> getFuture() = 0;
+ virtual void onDBusMessageReply(const CallStatus&, const DBusMessage&) = 0;
+ };
+
+ class DBusSignalHandler {
+ public:
+ virtual ~DBusSignalHandler() {}
+ virtual void onSignalDBusMessage(const DBusMessage&) = 0;
+ };
+
+ // objectPath, interfaceName, interfaceMemberName, interfaceMemberSignature
+ typedef std::tuple<std::string, std::string, std::string, std::string> DBusSignalHandlerPath;
+ typedef std::unordered_map<DBusSignalHandlerPath, std::pair<std::shared_ptr<std::recursive_mutex>, std::set<DBusSignalHandler* >>> DBusSignalHandlerTable;
+ typedef DBusSignalHandlerPath DBusSignalHandlerToken;
+
+ typedef Event<AvailabilityStatus> ConnectionStatusEvent;
+
+ virtual ~DBusProxyConnection() {}
+
+ virtual bool isConnected() const = 0;
+
+ virtual ConnectionStatusEvent& getConnectionStatusEvent() = 0;
+
+ virtual bool sendDBusMessage(const DBusMessage& dbusMessage) const = 0;
+
+ virtual std::future<CallStatus> sendDBusMessageWithReplyAsync(
+ const DBusMessage& dbusMessage,
+ std::unique_ptr<DBusMessageReplyAsyncHandler> dbusMessageReplyAsyncHandler,
+ const CommonAPI::CallInfo *_info) const = 0;
+
+ virtual DBusMessage sendDBusMessageWithReplyAndBlock(
+ const DBusMessage& dbusMessage,
+ DBusError& dbusError,
+ const CommonAPI::CallInfo *_info) const = 0;
+
+ virtual DBusSignalHandlerToken addSignalMemberHandler(
+ const std::string& objectPath,
+ const std::string& interfaceName,
+ const std::string& interfaceMemberName,
+ const std::string& interfaceMemberSignature,
+ DBusSignalHandler* dbusSignalHandler,
+ const bool justAddFilter = false) = 0;
+
+ virtual DBusSignalHandlerToken subscribeForSelectiveBroadcast(bool& subscriptionAccepted,
+ const std::string& objectPath,
+ const std::string& interfaceName,
+ const std::string& interfaceMemberName,
+ const std::string& interfaceMemberSignature,
+ DBusSignalHandler* dbusSignalHandler,
+ DBusProxy* callingProxy) = 0;
+
+ virtual void unsubscribeFromSelectiveBroadcast(const std::string& eventName,
+ DBusProxyConnection::DBusSignalHandlerToken subscription,
+ DBusProxy* callingProxy,
+ const DBusSignalHandler* dbusSignalHandler) = 0;
+
+ virtual bool removeSignalMemberHandler(const DBusSignalHandlerToken& dbusSignalHandlerToken,
+ const DBusSignalHandler* dbusSignalHandler = NULL) = 0;
+
+ virtual bool addObjectManagerSignalMemberHandler(const std::string& dbusBusName,
+ DBusSignalHandler* dbusSignalHandler) = 0;
+ virtual bool removeObjectManagerSignalMemberHandler(const std::string& dbusBusName,
+ DBusSignalHandler* dbusSignalHandler) = 0;
+
+ virtual const std::shared_ptr<DBusObjectManager> getDBusObjectManager() = 0;
+
+ virtual void registerObjectPath(const std::string& objectPath) = 0;
+ virtual void unregisterObjectPath(const std::string& objectPath) = 0;
+
+ virtual bool requestServiceNameAndBlock(const std::string& serviceName) const = 0;
+ virtual bool releaseServiceName(const std::string& serviceName) const = 0;
+
+ typedef std::function<bool(const DBusMessage&)> DBusObjectPathMessageHandler;
+
+ virtual void setObjectPathMessageHandler(DBusObjectPathMessageHandler) = 0;
+ virtual bool isObjectPathMessageHandlerSet() = 0;
+};
+
+} // namespace DBus
+} // namespace CommonAPI
+
+#endif // COMMONAPI_DBUS_DBUSPROXYCONNECTION_HPP_
diff --git a/include/CommonAPI/DBus/DBusProxyHelper.hpp b/include/CommonAPI/DBus/DBusProxyHelper.hpp
new file mode 100644
index 0000000..516d923
--- /dev/null
+++ b/include/CommonAPI/DBus/DBusProxyHelper.hpp
@@ -0,0 +1,258 @@
+// Copyright (C) 2013-2015 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#if !defined (COMMONAPI_INTERNAL_COMPILATION)
+#error "Only <CommonAPI/CommonAPI.hpp> can be included directly, this file may disappear or change contents."
+#endif
+
+#ifndef COMMONAPI_DBUS_DBUSPROXYHELPER_HPP_
+#define COMMONAPI_DBUS_DBUSPROXYHELPER_HPP_
+
+#include <functional>
+#include <future>
+#include <memory>
+#include <string>
+
+#include <CommonAPI/DBus/DBusAddress.hpp>
+#include <CommonAPI/DBus/DBusConfig.hpp>
+#include <CommonAPI/DBus/DBusMessage.hpp>
+#include <CommonAPI/DBus/DBusSerializableArguments.hpp>
+#include <CommonAPI/DBus/DBusProxyAsyncCallbackHandler.hpp>
+#include <CommonAPI/DBus/DBusProxyConnection.hpp>
+
+namespace CommonAPI {
+namespace DBus {
+
+class DBusProxy;
+
+template< class, class >
+struct DBusProxyHelper;
+
+template<
+ template<class ...> class _In, class... _InArgs,
+ template <class...> class _Out, class... _OutArgs>
+struct DBusProxyHelper<_In<DBusInputStream, DBusOutputStream, _InArgs...>,
+ _Out<DBusInputStream, DBusOutputStream, _OutArgs...>> {
+
+ template <typename _DBusProxy = DBusProxy>
+ static void callMethod(const _DBusProxy &_proxy,
+ const std::string &_method,
+ const std::string &_signature,
+ const _InArgs&... _in,
+ CommonAPI::CallStatus &_status) {
+
+ if (_proxy.isAvailableBlocking()) {
+ DBusMessage message = _proxy.createMethodCall(_method, _signature);
+ if (sizeof...(_InArgs) > 0) {
+ DBusOutputStream output(message);
+ if (DBusSerializableArguments<_InArgs...>::serialize(output, _in...)) {
+ _status = CallStatus::OUT_OF_MEMORY;
+ return;
+ }
+ output.flush();
+ }
+
+ const bool isSent = _proxy.getDBusConnection()->sendDBusMessage(message);
+ _status = (isSent ? CallStatus::SUCCESS : CallStatus::OUT_OF_MEMORY);
+ } else {
+ _status = CallStatus::NOT_AVAILABLE;
+ }
+ }
+
+ template <typename _DBusProxy = DBusProxy>
+ static void callMethodWithReply(
+ const _DBusProxy &_proxy,
+ DBusMessage &_message,
+ const CommonAPI::CallInfo *_info,
+ const _InArgs&... _in,
+ CommonAPI::CallStatus &_status,
+ _OutArgs&... _out) {
+
+ if (sizeof...(_InArgs) > 0) {
+ DBusOutputStream output(_message);
+ if (!DBusSerializableArguments<_InArgs...>::serialize(output, _in...)) {
+ _status = CallStatus::OUT_OF_MEMORY;
+ return;
+ }
+ output.flush();
+ }
+
+ DBusError error;
+ DBusMessage reply = _proxy.getDBusConnection()->sendDBusMessageWithReplyAndBlock(_message, error, _info);
+ if (error || !reply.isMethodReturnType()) {
+ _status = CallStatus::REMOTE_ERROR;
+ return;
+ }
+
+ if (sizeof...(_OutArgs) > 0) {
+ DBusInputStream input(reply);
+ if (!DBusSerializableArguments<_OutArgs...>::deserialize(input, _out...)) {
+ _status = CallStatus::REMOTE_ERROR;
+ return;
+ }
+ }
+ _status = CallStatus::SUCCESS;
+ }
+
+ template <typename _DBusProxy = DBusProxy>
+ static void callMethodWithReply(
+ const _DBusProxy &_proxy,
+ const DBusAddress &_address,
+ const char *_method,
+ const char *_signature,
+ const CommonAPI::CallInfo *_info,
+ const _InArgs&... _in,
+ CommonAPI::CallStatus &_status,
+ _OutArgs&... _out) {
+ if (_proxy.isAvailableBlocking()) {
+ DBusMessage message = DBusMessage::createMethodCall(_address, _method, _signature);
+ callMethodWithReply(_proxy, message, _info, _in..., _status, _out...);
+ } else {
+ _status = CallStatus::NOT_AVAILABLE;
+ }
+ }
+
+ template <typename _DBusProxy = DBusProxy>
+ static void callMethodWithReply(
+ const _DBusProxy &_proxy,
+ const std::string &_interface,
+ const std::string &_method,
+ const std::string &_signature,
+ const CommonAPI::CallInfo *_info,
+ const _InArgs&... _in,
+ CommonAPI::CallStatus &_status,
+ _OutArgs&... _out) {
+ DBusAddress itsAddress(_proxy.getDBusAddress());
+ itsAddress.setInterface(_interface);
+ callMethodWithReply(
+ _proxy, itsAddress,
+ _method.c_str(), _signature.c_str(),
+ _info,
+ _in..., _status, _out...);
+ }
+
+ template <typename _DBusProxy = DBusProxy>
+ static void callMethodWithReply(
+ const _DBusProxy &_proxy,
+ const std::string &_method,
+ const std::string &_signature,
+ const CommonAPI::CallInfo *_info,
+ const _InArgs&... _in,
+ CommonAPI::CallStatus &_status,
+ _OutArgs&... _out) {
+ if (_proxy.isAvailableBlocking()) {
+ DBusMessage message = _proxy.createMethodCall(_method, _signature);
+ callMethodWithReply(_proxy, message, _info, _in..., _status, _out...);
+ } else {
+ _status = CallStatus::NOT_AVAILABLE;
+ }
+ }
+
+ template <typename _DBusProxy = DBusProxy, typename _AsyncCallback>
+ static std::future<CallStatus> callMethodAsync(
+ const _DBusProxy &_proxy,
+ DBusMessage &_message,
+ const CommonAPI::CallInfo *_info,
+ const _InArgs&... _in,
+ _AsyncCallback _callback,
+ std::tuple<_OutArgs...> _out) {
+ if (sizeof...(_InArgs) > 0) {
+ DBusOutputStream output(_message);
+ const bool success = DBusSerializableArguments<
+ _InArgs...
+ >::serialize(output, _in...);
+ if (!success) {
+ std::promise<CallStatus> promise;
+ promise.set_value(CallStatus::OUT_OF_MEMORY);
+ return promise.get_future();
+ }
+ output.flush();
+ }
+
+ return _proxy.getDBusConnection()->sendDBusMessageWithReplyAsync(
+ _message,
+ DBusProxyAsyncCallbackHandler<
+ _OutArgs...
+ >::create(std::move(_callback), _out),
+ _info);
+ }
+
+ template <typename _DBusProxy = DBusProxy, typename _AsyncCallback>
+ static std::future<CallStatus> callMethodAsync(
+ const _DBusProxy &_proxy,
+ const DBusAddress &_address,
+ const std::string &_method,
+ const std::string &_signature,
+ const CommonAPI::CallInfo *_info,
+ const _InArgs&... _in,
+ _AsyncCallback _callback,
+ std::tuple<_OutArgs...> _out) {
+ if (_proxy.isAvailable()) {
+ DBusMessage message = DBusMessage::createMethodCall(_address, _method, _signature);
+ return callMethodAsync(_proxy, message, _info, _in..., _callback, _out);
+ } else {
+ CallStatus status = CallStatus::NOT_AVAILABLE;
+ callCallbackOnNotAvailable(_callback, typename make_sequence<sizeof...(_OutArgs)>::type(), _out);
+
+ std::promise<CallStatus> promise;
+ promise.set_value(status);
+ return promise.get_future();
+ }
+ }
+
+ template <typename _DBusProxy = DBusProxy, typename _AsyncCallback>
+ static std::future<CallStatus> callMethodAsync(
+ const _DBusProxy &_proxy,
+ const std::string &_interface,
+ const std::string &_method,
+ const std::string &_signature,
+ const CommonAPI::CallInfo *_info,
+ const _InArgs&... _in,
+ _AsyncCallback _callback,
+ std::tuple<_OutArgs...> _out) {
+ DBusAddress itsAddress(_proxy.getDBusAddress());
+ itsAddress.setInterface(_interface);
+ return callMethodAsync(
+ _proxy, itsAddress,
+ _method, _signature,
+ _info,
+ _in..., _callback, _out);
+ }
+
+ template <typename _DBusProxy = DBusProxy, typename _AsyncCallback>
+ static std::future<CallStatus> callMethodAsync(
+ const _DBusProxy &_proxy,
+ const std::string &_method,
+ const std::string &_signature,
+ const CommonAPI::CallInfo *_info,
+ const _InArgs&... _in,
+ _AsyncCallback _callback,
+ std::tuple<_OutArgs...> _out) {
+ if (_proxy.isAvailable()) {
+ DBusMessage message = _proxy.createMethodCall(_method, _signature);
+ return callMethodAsync(_proxy, message, _info, _in..., _callback, _out);
+ } else {
+ callCallbackOnNotAvailable(
+ _callback, typename make_sequence<sizeof...(_OutArgs)>::type(), _out);
+
+ CallStatus status = CallStatus::NOT_AVAILABLE;
+ std::promise<CallStatus> promise;
+ promise.set_value(status);
+ return promise.get_future();
+ }
+ }
+
+ template <int... _ArgIndices>
+ static void callCallbackOnNotAvailable(std::function<void(CallStatus, _OutArgs&...)> _callback,
+ index_sequence<_ArgIndices...>, std::tuple<_OutArgs...> _out) {
+ const CallStatus status(CallStatus::NOT_AVAILABLE);
+ _callback(status, std::get<_ArgIndices>(_out)...);
+ }
+};
+
+} // namespace DBus
+} // namespace CommonAPI
+
+#endif // COMMONAPI_DBUS_DBUSPROXYHELPER_HPP_
diff --git a/include/CommonAPI/DBus/DBusProxyManager.hpp b/include/CommonAPI/DBus/DBusProxyManager.hpp
new file mode 100644
index 0000000..a28527a
--- /dev/null
+++ b/include/CommonAPI/DBus/DBusProxyManager.hpp
@@ -0,0 +1,72 @@
+// Copyright (C) 2013-2015 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#if !defined (COMMONAPI_INTERNAL_COMPILATION)
+#error "Only <CommonAPI/CommonAPI.hpp> can be included directly, this file may disappear or change contents."
+#endif
+
+#ifndef COMMONAPI_DBUS_PROXYMANAGER_HPP_
+#define COMMONAPI_DBUS_PROXYMANAGER_HPP_
+
+#include <functional>
+#include <future>
+#include <string>
+#include <vector>
+
+#include <CommonAPI/Export.hpp>
+#include <CommonAPI/ProxyManager.hpp>
+#include <CommonAPI/DBus/DBusProxy.hpp>
+#include <CommonAPI/DBus/DBusFactory.hpp>
+#include <CommonAPI/DBus/DBusObjectManagerStub.hpp>
+#include <CommonAPI/DBus/DBusInstanceAvailabilityStatusChangedEvent.hpp>
+
+namespace CommonAPI {
+namespace DBus {
+
+class DBusProxyManager: public ProxyManager {
+public:
+ COMMONAPI_EXPORT DBusProxyManager(DBusProxy &_proxy,
+ const std::string &_interfaceName);
+
+ COMMONAPI_EXPORT const std::string &getDomain() const;
+ COMMONAPI_EXPORT const std::string &getInterface() const;
+ COMMONAPI_EXPORT const ConnectionId_t &getConnectionId() const;
+
+ COMMONAPI_EXPORT virtual void getAvailableInstances(CommonAPI::CallStatus &, std::vector<std::string> &_instances);
+ COMMONAPI_EXPORT virtual std::future<CallStatus> getAvailableInstancesAsync(GetAvailableInstancesCallback _callback);
+
+ COMMONAPI_EXPORT virtual void getInstanceAvailabilityStatus(const std::string &_address,
+ CallStatus &_callStatus,
+ AvailabilityStatus &_availabilityStatus);
+
+ COMMONAPI_EXPORT virtual std::future<CallStatus> getInstanceAvailabilityStatusAsync(
+ const std::string&,
+ GetInstanceAvailabilityStatusCallback callback);
+
+ COMMONAPI_EXPORT virtual InstanceAvailabilityStatusChangedEvent& getInstanceAvailabilityStatusChangedEvent();
+
+private:
+ COMMONAPI_EXPORT void instancesAsyncCallback(const CommonAPI::CallStatus& status,
+ const DBusObjectManagerStub::DBusObjectPathAndInterfacesDict& dict,
+ GetAvailableInstancesCallback& call);
+
+ COMMONAPI_EXPORT void instanceAliveAsyncCallback(const AvailabilityStatus &_alive,
+ GetInstanceAvailabilityStatusCallback &_call,
+ std::shared_ptr<std::promise<CallStatus>> &_status);
+
+ COMMONAPI_EXPORT void translateCommonApiAddresses(const DBusObjectManagerStub::DBusObjectPathAndInterfacesDict &_dict,
+ std::vector<std::string> &_instances);
+
+ DBusProxy &proxy_;
+ DBusInstanceAvailabilityStatusChangedEvent instanceAvailabilityStatusEvent_;
+ const std::string interfaceId_;
+ const std::shared_ptr<DBusServiceRegistry> registry_;
+ ConnectionId_t connectionId_;
+};
+
+} // namespace DBus
+} // namespace CommonAPI
+
+#endif // COMMONAPI_DBUS_PROXYMANAGER_HPP_
diff --git a/include/CommonAPI/DBus/DBusSelectiveEvent.hpp b/include/CommonAPI/DBus/DBusSelectiveEvent.hpp
new file mode 100644
index 0000000..65c61f9
--- /dev/null
+++ b/include/CommonAPI/DBus/DBusSelectiveEvent.hpp
@@ -0,0 +1,56 @@
+// Copyright (C) 2013-2015 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#if !defined (COMMONAPI_INTERNAL_COMPILATION)
+#error "Only <CommonAPI/CommonAPI.hpp> can be included directly, this file may disappear or change contents."
+#endif
+
+#ifndef COMMONAPI_DBUS_DBUSSELECTIVEEVENT_HPP_
+#define COMMONAPI_DBUS_DBUSSELECTIVEEVENT_HPP_
+
+#include <CommonAPI/DBus/DBusEvent.hpp>
+
+namespace CommonAPI {
+namespace DBus {
+
+template<typename _EventType, typename... _Arguments>
+class DBusSelectiveEvent: public DBusEvent<_EventType, _Arguments...> {
+public:
+ typedef typename DBusEvent<_EventType, _Arguments...>::Listener Listener;
+ typedef DBusEvent<_EventType, _Arguments...> DBusEventBase;
+
+ DBusSelectiveEvent(DBusProxy &_proxy,
+ const char *_name, const char *_signature,
+ std::tuple<_Arguments...> _arguments)
+ : DBusEventBase(_proxy, _name, _signature, _arguments) {
+ }
+
+ DBusSelectiveEvent(DBusProxy &_proxy,
+ const char *_name, const char *_signature,
+ const char *_path, const char *_interface,
+ std::tuple<_Arguments...> _arguments)
+ : DBusEventBase(_proxy, _name, _signature, _path, _interface, _arguments) {
+ }
+
+ virtual ~DBusSelectiveEvent() {}
+
+protected:
+ void onFirstListenerAdded(const Listener &) {
+ bool success;
+ this->subscription_
+ = static_cast<DBusProxy&>(this->proxy_).subscribeForSelectiveBroadcastOnConnection(
+ success, this->path_, this->interface_, this->name_, this->signature_, this);
+ }
+
+ void onLastListenerRemoved(const Listener &) {
+ static_cast<DBusProxy&>(this->proxy_).unsubscribeFromSelectiveBroadcast(
+ this->name_, this->subscription_, this);
+ }
+};
+
+} // namespace DBus
+} // namespace CommonAPI
+
+#endif // COMMONAPI_DBUS_DBUSSELECTIVEEVENT_HPP_
diff --git a/include/CommonAPI/DBus/DBusSerializableArguments.hpp b/include/CommonAPI/DBus/DBusSerializableArguments.hpp
new file mode 100644
index 0000000..f763ce5
--- /dev/null
+++ b/include/CommonAPI/DBus/DBusSerializableArguments.hpp
@@ -0,0 +1,30 @@
+// Copyright (C) 2013-2015 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#if !defined (COMMONAPI_INTERNAL_COMPILATION)
+#error "Only <CommonAPI/CommonAPI.hpp> can be included directly, this file may disappear or change contents."
+#endif
+
+#ifndef COMMONAPI_DBUS_DBUS_SERIALIZABLEARGUMENTS_HPP_
+#define COMMONAPI_DBUS_DBUS_SERIALIZABLEARGUMENTS_HPP_
+
+#include <CommonAPI/SerializableArguments.hpp>
+#include <CommonAPI/DBus/DBusInputStream.hpp>
+#include <CommonAPI/DBus/DBusOutputStream.hpp>
+
+namespace CommonAPI {
+namespace DBus {
+
+template<typename... _Arguments>
+using DBusSerializableArguments = CommonAPI::SerializableArguments<
+ DBusInputStream,
+ DBusOutputStream,
+ _Arguments...
+ >;
+
+} // namespace DBus
+} // namespace CommonAPI
+
+#endif // COMMONAPI_DBUS_DBUSSERIALIZABLEARGUMENTS_HPP_
diff --git a/include/CommonAPI/DBus/DBusServiceRegistry.hpp b/include/CommonAPI/DBus/DBusServiceRegistry.hpp
new file mode 100644
index 0000000..3dbcf1b
--- /dev/null
+++ b/include/CommonAPI/DBus/DBusServiceRegistry.hpp
@@ -0,0 +1,315 @@
+// Copyright (C) 2013-2015 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#if !defined (COMMONAPI_INTERNAL_COMPILATION)
+#error "Only <CommonAPI/CommonAPI.hpp> can be included directly, this file may disappear or change contents."
+#endif
+
+#ifndef COMMONAPI_DBUS_DBUSSERVICEREGISTRY_HPP_
+#define COMMONAPI_DBUS_DBUSSERVICEREGISTRY_HPP_
+
+#include <algorithm>
+#include <condition_variable>
+#include <future>
+#include <map>
+#include <memory>
+#include <mutex>
+#include <set>
+#include <string>
+#include <unordered_map>
+#include <unordered_set>
+#include <utility>
+#include <vector>
+#include <list>
+
+#include <pugixml/pugixml.hpp>
+
+#include <CommonAPI/Attribute.hpp>
+#include <CommonAPI/Proxy.hpp>
+#include <CommonAPI/Types.hpp>
+#include <CommonAPI/DBus/DBusProxyConnection.hpp>
+#include <CommonAPI/DBus/DBusFactory.hpp>
+
+namespace CommonAPI {
+namespace DBus {
+
+typedef Event<std::string, std::string, std::string> NameOwnerChangedEvent;
+typedef Event<std::string, std::string, std::string>::Subscription NameOwnerChangedEventSubscription;
+
+// Connection name, Object path
+typedef std::pair<std::string, std::string> DBusInstanceId;
+
+class DBusAddress;
+class DBusAddressTranslator;
+class DBusDaemonProxy;
+
+class DBusServiceRegistry: public std::enable_shared_from_this<DBusServiceRegistry>,
+ public DBusProxyConnection::DBusSignalHandler {
+ public:
+ enum class DBusRecordState {
+ UNKNOWN,
+ AVAILABLE,
+ RESOLVING,
+ RESOLVED,
+ NOT_AVAILABLE
+ };
+
+ // template class DBusServiceListener<> { typedef functor; typedef list; typedef subscription }
+ typedef std::function<void(const AvailabilityStatus& availabilityStatus)> DBusServiceListener;
+ typedef std::list<DBusServiceListener> DBusServiceListenerList;
+ typedef DBusServiceListenerList::iterator DBusServiceSubscription;
+
+ typedef std::function<void(const std::vector<std::string>& interfaces,
+ const AvailabilityStatus& availabilityStatus)> DBusManagedInterfaceListener;
+ typedef std::list<DBusManagedInterfaceListener> DBusManagedInterfaceListenerList;
+ typedef DBusManagedInterfaceListenerList::iterator DBusManagedInterfaceSubscription;
+
+ static std::shared_ptr<DBusServiceRegistry> get(std::shared_ptr<DBusProxyConnection> _connection);
+
+ DBusServiceRegistry(std::shared_ptr<DBusProxyConnection> dbusProxyConnection);
+
+ DBusServiceRegistry(const DBusServiceRegistry&) = delete;
+ DBusServiceRegistry& operator=(const DBusServiceRegistry&) = delete;
+
+ virtual ~DBusServiceRegistry();
+
+ void init();
+
+ DBusServiceSubscription subscribeAvailabilityListener(const std::string &_address,
+ DBusServiceListener _listener);
+
+ void unsubscribeAvailabilityListener(const std::string &_address,
+ DBusServiceSubscription &_listener);
+
+
+ bool isServiceInstanceAlive(const std::string &_dbusInterfaceName,
+ const std::string &_dbusConnectionName,
+ const std::string &_dbusObjectPath);
+
+
+ virtual std::vector<std::string> getAvailableServiceInstances(const std::string &_interface,
+ const std::string &_domain = "local");
+
+ virtual void getAvailableServiceInstancesAsync(CommonAPI::Factory::AvailableInstancesCbk_t _cbk,
+ const std::string &_interface,
+ const std::string &_domain = "local");
+
+ virtual void onSignalDBusMessage(const DBusMessage&);
+
+ private:
+ struct DBusInterfaceNameListenersRecord {
+ DBusInterfaceNameListenersRecord()
+ : state(DBusRecordState::UNKNOWN) {
+ }
+
+ DBusInterfaceNameListenersRecord(DBusInterfaceNameListenersRecord &&_other)
+ : state(_other.state),
+ listenerList(std::move(_other.listenerList)) {
+ }
+
+ DBusRecordState state;
+ DBusServiceListenerList listenerList;
+ };
+
+ typedef std::unordered_map<std::string, DBusInterfaceNameListenersRecord> DBusInterfaceNameListenersMap;
+
+ struct DBusServiceListenersRecord {
+ DBusServiceListenersRecord()
+ : uniqueBusNameState(DBusRecordState::UNKNOWN),
+ mutexOnResolve() {
+ }
+
+ DBusServiceListenersRecord(DBusServiceListenersRecord&& other)
+ : uniqueBusNameState(other.uniqueBusNameState),
+ uniqueBusName(std::move(other.uniqueBusName)),
+ promiseOnResolve(std::move(other.promiseOnResolve)),
+ futureOnResolve(std::move(other.futureOnResolve)),
+ mutexOnResolve(std::move(other.mutexOnResolve)),
+ dbusObjectPathListenersMap(std::move(other.dbusObjectPathListenersMap)) {
+ }
+
+ ~DBusServiceListenersRecord() {};
+
+ DBusRecordState uniqueBusNameState;
+ std::string uniqueBusName;
+
+ std::promise<DBusRecordState> promiseOnResolve;
+ std::shared_future<DBusRecordState> futureOnResolve;
+ std::unique_lock<std::mutex>* mutexOnResolve;
+
+ std::unordered_map<std::string, DBusInterfaceNameListenersMap> dbusObjectPathListenersMap;
+ };
+
+ std::unordered_map<std::string, DBusServiceListenersRecord> dbusServiceListenersMap;
+
+
+ struct DBusObjectPathCache {
+ DBusObjectPathCache()
+ : referenceCount(0),
+ state(DBusRecordState::UNKNOWN) {
+ }
+
+ DBusObjectPathCache(DBusObjectPathCache&& other)
+ : referenceCount(other.referenceCount),
+ state(other.state),
+ promiseOnResolve(std::move(other.promiseOnResolve)),
+ dbusInterfaceNamesCache(std::move(other.dbusInterfaceNamesCache)) {
+ }
+
+ ~DBusObjectPathCache() {}
+
+ size_t referenceCount;
+ DBusRecordState state;
+ std::promise<DBusRecordState> promiseOnResolve;
+
+ std::unordered_set<std::string> dbusInterfaceNamesCache;
+ };
+
+ struct DBusUniqueNameRecord {
+ DBusUniqueNameRecord()
+ : objectPathsState(DBusRecordState::UNKNOWN) {
+ }
+
+ DBusUniqueNameRecord(DBusUniqueNameRecord&& other)
+ : uniqueName(std::move(other.uniqueName)),
+ objectPathsState(other.objectPathsState),
+ ownedBusNames(std::move(other.ownedBusNames)),
+ dbusObjectPathsCache(std::move(other.dbusObjectPathsCache)) {
+ }
+
+ std::string uniqueName;
+ DBusRecordState objectPathsState;
+ std::unordered_set<std::string> ownedBusNames;
+ std::unordered_map<std::string, DBusObjectPathCache> dbusObjectPathsCache;
+ };
+
+ std::unordered_map<std::string, DBusUniqueNameRecord> dbusUniqueNamesMap_;
+ typedef std::unordered_map<std::string, DBusUniqueNameRecord>::iterator DBusUniqueNamesMapIterator;
+
+ // mapping service names (well-known names) to service instances
+ std::unordered_map<std::string, DBusUniqueNameRecord*> dbusServiceNameMap_;
+
+ // protects the dbus service maps
+ std::mutex dbusServicesMutex_;
+
+ void resolveDBusServiceName(const std::string& dbusServiceName,
+ DBusServiceListenersRecord& dbusServiceListenersRecord);
+
+ void onGetNameOwnerCallback(const CallStatus& status,
+ std::string dbusServiceUniqueName,
+ const std::string& dbusServiceName);
+
+
+ DBusRecordState resolveDBusInterfaceNameState(const DBusAddress &_address,
+ DBusServiceListenersRecord &_record);
+
+
+ DBusObjectPathCache& getDBusObjectPathCacheReference(const std::string& dbusObjectPath,
+ const std::string& dbusServiceUniqueName,
+ DBusUniqueNameRecord& dbusUniqueNameRecord);
+
+ void releaseDBusObjectPathCacheReference(const std::string& dbusObjectPath,
+ const DBusServiceListenersRecord& dbusServiceListenersRecord);
+
+
+ bool introspectDBusObjectPath(const std::string& dbusServiceUniqueName, const std::string& dbusObjectPath);
+
+ void onIntrospectCallback(const CallStatus& status,
+ std::string xmlData,
+ const std::string& dbusServiceName,
+ const std::string& dbusObjectPath);
+
+ void parseIntrospectionData(const std::string& xmlData,
+ const std::string& rootObjectPath,
+ const std::string& dbusServiceUniqueName);
+
+ void parseIntrospectionNode(const pugi::xml_node& node,
+ const std::string& rootObjectPath,
+ const std::string& fullObjectPath,
+ const std::string& dbusServiceUniqueName);
+
+ void processIntrospectionObjectPath(const pugi::xml_node& node,
+ const std::string& rootObjectPath,
+ const std::string& dbusServiceUniqueName);
+
+ void processIntrospectionInterface(const pugi::xml_node& node,
+ const std::string& rootObjectPath,
+ const std::string& fullObjectPath,
+ const std::string& dbusServiceUniqueName);
+
+ void onDBusDaemonProxyStatusEvent(const AvailabilityStatus& availabilityStatus);
+
+ void onDBusDaemonProxyNameOwnerChangedEvent(const std::string& name,
+ const std::string& oldOwner,
+ const std::string& newOwner);
+
+ std::shared_ptr<DBusDaemonProxy> dbusDaemonProxy_;
+ bool initialized_;
+
+ ProxyStatusEvent::Subscription dbusDaemonProxyStatusEventSubscription_;
+ NameOwnerChangedEvent::Subscription dbusDaemonProxyNameOwnerChangedEventSubscription_;
+
+
+ void checkDBusServiceWasAvailable(const std::string& dbusServiceName, const std::string& dbusServiceUniqueName);
+
+ void onDBusServiceAvailable(const std::string& dbusServiceName, const std::string& dbusServiceUniqueName);
+
+ void onDBusServiceNotAvailable(DBusServiceListenersRecord& dbusServiceListenersRecord, const std::string &_serviceName = "");
+
+
+ void notifyDBusServiceListeners(const DBusUniqueNameRecord& dbusUniqueNameRecord,
+ const std::string& dbusObjectPath,
+ const std::unordered_set<std::string>& dbusInterfaceNames,
+ const DBusRecordState& dbusInterfaceNamesState);
+
+ void notifyDBusObjectPathResolved(DBusInterfaceNameListenersMap& dbusInterfaceNameListenersMap,
+ const std::unordered_set<std::string>& dbusInterfaceNames);
+
+ void notifyDBusObjectPathChanged(DBusInterfaceNameListenersMap& dbusInterfaceNameListenersMap,
+ const std::unordered_set<std::string>& dbusInterfaceNames,
+ const DBusRecordState& dbusInterfaceNamesState);
+
+ void notifyDBusInterfaceNameListeners(DBusInterfaceNameListenersRecord& dbusInterfaceNameListenersRecord,
+ const bool& isDBusInterfaceNameAvailable);
+
+
+ void removeUniqueName(const DBusUniqueNamesMapIterator &_dbusUniqueName, const std::string &_serviceName);
+ DBusUniqueNameRecord* insertServiceNameMapping(const std::string& dbusUniqueName, const std::string& dbusServiceName);
+ bool findCachedDbusService(const std::string& dbusServiceName, DBusUniqueNameRecord** uniqueNameRecord);
+ bool findCachedObjectPath(const std::string& dbusObjectPathName, const DBusUniqueNameRecord* uniqueNameRecord, DBusObjectPathCache* objectPathCache);
+
+ std::condition_variable monitorResolveAllServices_;
+ std::mutex mutexServiceResolveCount;
+ int servicesToResolve;
+
+ std::condition_variable monitorResolveAllObjectPaths_;
+ std::mutex mutexObjectPathsResolveCount;
+ int objectPathsToResolve;
+
+ void fetchAllServiceNames();
+
+ inline const bool isDBusServiceName(const std::string &_name) {
+ return (_name.length() > 0 && _name[0] != ':');
+ };
+
+
+ inline const bool isOrgFreedesktopDBusInterface(const std::string& dbusInterfaceName) {
+ return dbusInterfaceName.find("org.freedesktop.DBus.") == 0;
+ }
+
+ std::thread::id notificationThread_;
+
+private:
+ typedef std::map<std::shared_ptr<DBusProxyConnection>, std::shared_ptr<DBusServiceRegistry>> RegistryMap_t;
+ static RegistryMap_t registries_;
+ static std::mutex registriesMutex_;
+ std::shared_ptr<DBusAddressTranslator> translator_;
+};
+
+
+} // namespace DBus
+} // namespace CommonAPI
+
+#endif // COMMONAPI_DBUS_DBUSSERVICEREGISTRY_HPP_
diff --git a/include/CommonAPI/DBus/DBusStubAdapter.hpp b/include/CommonAPI/DBus/DBusStubAdapter.hpp
new file mode 100644
index 0000000..5d1657b
--- /dev/null
+++ b/include/CommonAPI/DBus/DBusStubAdapter.hpp
@@ -0,0 +1,59 @@
+// Copyright (C) 2013-2015 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#if !defined (COMMONAPI_INTERNAL_COMPILATION)
+#error "Only <CommonAPI/CommonAPI.hpp> can be included directly, this file may disappear or change contents."
+#endif
+
+#ifndef COMMONAPI_DBUS_DBUSSTUBADAPTER_HPP_
+#define COMMONAPI_DBUS_DBUSSTUBADAPTER_HPP_
+
+#include <memory>
+
+#include <CommonAPI/Export.hpp>
+#include <CommonAPI/Stub.hpp>
+#include <CommonAPI/DBus/DBusAddress.hpp>
+#include <CommonAPI/DBus/DBusInterfaceHandler.hpp>
+
+namespace CommonAPI {
+namespace DBus {
+
+class DBusProxyConnection;
+
+class DBusStubAdapter
+ : virtual public CommonAPI::StubAdapter,
+ public DBusInterfaceHandler {
+ public:
+ COMMONAPI_EXPORT DBusStubAdapter(const DBusAddress &_dbusAddress,
+ const std::shared_ptr<DBusProxyConnection> &_connection,
+ const bool isManagingInterface);
+
+ COMMONAPI_EXPORT virtual ~DBusStubAdapter();
+
+ COMMONAPI_EXPORT virtual void init(std::shared_ptr<DBusStubAdapter> _instance);
+ COMMONAPI_EXPORT virtual void deinit();
+
+ COMMONAPI_EXPORT const DBusAddress &getDBusAddress() const;
+ COMMONAPI_EXPORT const std::shared_ptr<DBusProxyConnection> &getDBusConnection() const;
+
+ COMMONAPI_EXPORT const bool isManaging() const;
+
+ COMMONAPI_EXPORT virtual const char* getMethodsDBusIntrospectionXmlData() const = 0;
+ COMMONAPI_EXPORT virtual bool onInterfaceDBusMessage(const DBusMessage &_message) = 0;
+
+ COMMONAPI_EXPORT virtual void deactivateManagedInstances() = 0;
+ COMMONAPI_EXPORT virtual const bool hasFreedesktopProperties();
+ COMMONAPI_EXPORT virtual bool onInterfaceDBusFreedesktopPropertiesMessage(const DBusMessage &_message) = 0;
+
+ protected:
+ DBusAddress dbusAddress_;
+ const std::shared_ptr<DBusProxyConnection> connection_;
+ const bool isManaging_;
+};
+
+} // namespace dbus
+} // namespace CommonAPI
+
+#endif // COMMONAPI_DBUS_DBUSSTUBADAPTER_HPP_
diff --git a/include/CommonAPI/DBus/DBusStubAdapterHelper.hpp b/include/CommonAPI/DBus/DBusStubAdapterHelper.hpp
new file mode 100644
index 0000000..56e5021
--- /dev/null
+++ b/include/CommonAPI/DBus/DBusStubAdapterHelper.hpp
@@ -0,0 +1,674 @@
+// Copyright (C) 2013-2015 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#if !defined (COMMONAPI_INTERNAL_COMPILATION)
+#error "Only <CommonAPI/CommonAPI.hpp> can be included directly, this file may disappear or change contents."
+#endif
+
+#ifndef COMMONAPI_DBUS_DBUSSTUBADAPTERHELPER_HPP_
+#define COMMONAPI_DBUS_DBUSSTUBADAPTERHELPER_HPP_
+
+#include <initializer_list>
+#include <memory>
+#include <tuple>
+#include <unordered_map>
+#include <map>
+
+#include <CommonAPI/Variant.hpp>
+#include <CommonAPI/DBus/DBusStubAdapter.hpp>
+#include <CommonAPI/DBus/DBusInputStream.hpp>
+#include <CommonAPI/DBus/DBusOutputStream.hpp>
+#include <CommonAPI/DBus/DBusHelper.hpp>
+#include <CommonAPI/DBus/DBusSerializableArguments.hpp>
+#include <CommonAPI/DBus/DBusClientId.hpp>
+
+namespace CommonAPI {
+namespace DBus {
+
+class StubDispatcherBase {
+public:
+ virtual ~StubDispatcherBase() { }
+};
+
+struct DBusAttributeDispatcherStruct {
+ StubDispatcherBase* getter;
+ StubDispatcherBase* setter;
+
+ DBusAttributeDispatcherStruct(StubDispatcherBase* g, StubDispatcherBase* s) {
+ getter = g;
+ setter = s;
+ }
+};
+
+typedef std::unordered_map<std::string, DBusAttributeDispatcherStruct> StubAttributeTable;
+
+template <typename _StubClass>
+class DBusStubAdapterHelper: public virtual DBusStubAdapter {
+ public:
+ typedef typename _StubClass::StubAdapterType StubAdapterType;
+ typedef typename _StubClass::RemoteEventHandlerType RemoteEventHandlerType;
+
+ class StubDispatcher: public StubDispatcherBase {
+ public:
+ virtual ~StubDispatcher() {}
+ virtual bool dispatchDBusMessage(const DBusMessage& dbusMessage,
+ const std::shared_ptr<_StubClass>& stub,
+ DBusStubAdapterHelper<_StubClass>& dbusStubAdapterHelper) = 0;
+ };
+ // interfaceMemberName, interfaceMemberSignature
+ typedef std::pair<const char*, const char*> DBusInterfaceMemberPath;
+ typedef std::unordered_map<DBusInterfaceMemberPath, StubDispatcherBase*> StubDispatcherTable;
+
+ DBusStubAdapterHelper(const DBusAddress &_address,
+ const std::shared_ptr<DBusProxyConnection> &_connection,
+ const std::shared_ptr<_StubClass> &_stub,
+ const bool _isManaging):
+ DBusStubAdapter(_address, _connection, _isManaging),
+ stub_(_stub),
+ remoteEventHandler_(nullptr) {
+ }
+
+ virtual ~DBusStubAdapterHelper() {
+ DBusStubAdapter::deinit();
+ stub_.reset();
+ }
+
+ virtual void init(std::shared_ptr<DBusStubAdapter> instance) {
+ DBusStubAdapter::init(instance);
+ std::shared_ptr<StubAdapterType> stubAdapter = std::dynamic_pointer_cast<StubAdapterType>(instance);
+ remoteEventHandler_ = stub_->initStubAdapter(stubAdapter);
+ }
+
+ virtual void deinit() {
+ DBusStubAdapter::deinit();
+ stub_.reset();
+ }
+
+ inline RemoteEventHandlerType* getRemoteEventHandler() {
+ return remoteEventHandler_;
+ }
+
+ protected:
+
+ virtual bool onInterfaceDBusMessage(const DBusMessage& dbusMessage) {
+ const char* interfaceMemberName = dbusMessage.getMember();
+ const char* interfaceMemberSignature = dbusMessage.getSignature();
+
+ assert(interfaceMemberName);
+ assert(interfaceMemberSignature);
+
+ DBusInterfaceMemberPath dbusInterfaceMemberPath(interfaceMemberName, interfaceMemberSignature);
+ auto findIterator = getStubDispatcherTable().find(dbusInterfaceMemberPath);
+ const bool foundInterfaceMemberHandler = (findIterator != getStubDispatcherTable().end());
+ bool dbusMessageHandled = false;
+ if (foundInterfaceMemberHandler) {
+ StubDispatcher* stubDispatcher = static_cast<StubDispatcher*>(findIterator->second);
+ dbusMessageHandled = stubDispatcher->dispatchDBusMessage(dbusMessage, stub_, *this);
+ }
+
+ return dbusMessageHandled;
+ }
+
+ virtual bool onInterfaceDBusFreedesktopPropertiesMessage(const DBusMessage &_message) {
+ DBusInputStream input(_message);
+
+ if (_message.hasMemberName("Get")) {
+ return handleFreedesktopGet(_message, input);
+ } else if (_message.hasMemberName("Set")) {
+ return handleFreedesktopSet(_message, input);
+ } else if (_message.hasMemberName("GetAll")) {
+ return handleFreedesktopGetAll(_message, input);
+ }
+
+ return false;
+ }
+
+ virtual const StubDispatcherTable& getStubDispatcherTable() = 0;
+ virtual const StubAttributeTable& getStubAttributeTable() = 0;
+
+ std::shared_ptr<_StubClass> stub_;
+ RemoteEventHandlerType* remoteEventHandler_;
+
+ private:
+ bool handleFreedesktopGet(const DBusMessage &_message, DBusInputStream &_input) {
+ std::string interfaceName;
+ std::string attributeName;
+ _input >> interfaceName;
+ _input >> attributeName;
+
+ if (_input.hasError()) {
+ return false;
+ }
+
+ auto attributeDispatcherIterator = getStubAttributeTable().find(attributeName);
+ if (attributeDispatcherIterator == getStubAttributeTable().end()) {
+ return false;
+ }
+
+ StubDispatcher* getterDispatcher = static_cast<StubDispatcher*>(attributeDispatcherIterator->second.getter);
+ assert(getterDispatcher != NULL); // all attributes have at least a getter
+ return (getterDispatcher->dispatchDBusMessage(_message, stub_, *this));
+ }
+
+ bool handleFreedesktopSet(const DBusMessage& dbusMessage, DBusInputStream& dbusInputStream) {
+ std::string interfaceName;
+ std::string attributeName;
+ dbusInputStream >> interfaceName;
+ dbusInputStream >> attributeName;
+
+ if(dbusInputStream.hasError()) {
+ return false;
+ }
+
+ auto attributeDispatcherIterator = getStubAttributeTable().find(attributeName);
+ if(attributeDispatcherIterator == getStubAttributeTable().end()) {
+ return false;
+ }
+
+ StubDispatcher *setterDispatcher = static_cast<StubDispatcher*>(attributeDispatcherIterator->second.setter);
+ if (setterDispatcher == NULL) { // readonly attributes do not have a setter
+ return false;
+ }
+
+ return setterDispatcher->dispatchDBusMessage(dbusMessage, stub_, *this);
+ }
+
+ bool handleFreedesktopGetAll(const DBusMessage& dbusMessage, DBusInputStream& dbusInputStream) {
+ std::string interfaceName;
+ dbusInputStream >> interfaceName;
+
+ if(dbusInputStream.hasError()) {
+ return false;
+ }
+
+ DBusMessage dbusMessageReply = dbusMessage.createMethodReturn("a{sv}");
+ DBusOutputStream dbusOutputStream(dbusMessageReply);
+ /*
+ dbusOutputStream.beginWriteVectorOfSerializableStructs(getStubAttributeTable().size());
+
+ std::shared_ptr<DBusClientId> clientId = std::make_shared<DBusClientId>(std::string(dbusMessage.getSenderName()));
+
+ for(auto attributeDispatcherIterator = getStubAttributeTable().begin(); attributeDispatcherIterator != getStubAttributeTable().end(); attributeDispatcherIterator++) {
+ //To prevent the destruction of the stub whilst still handling a message
+ if (stub_) {
+ DBusGetFreedesktopAttributeStubDispatcherBase<_StubClass>* const getterDispatcher = dynamic_cast<DBusGetFreedesktopAttributeStubDispatcherBase<_StubClass>*>(attributeDispatcherIterator->second.getter);
+
+ if(getterDispatcher == NULL) { // readonly attributes do not have a setter
+ return false;
+ }
+
+ dbusOutputStream << attributeDispatcherIterator->first;
+ getterDispatcher->dispatchDBusMessageAndAppendReply(dbusMessage, stub_, dbusOutputStream, clientId);
+ }
+ }
+
+ dbusOutputStream.endWriteVector();
+ */
+ dbusOutputStream.flush();
+ return getDBusConnection()->sendDBusMessage(dbusMessageReply);
+ }
+};
+
+template< class >
+struct DBusStubSignalHelper;
+
+template<template<class ...> class _In, class... _InArgs>
+struct DBusStubSignalHelper<_In<DBusInputStream, DBusOutputStream, _InArgs...>> {
+
+ static inline bool sendSignal(const char* objectPath,
+ const char* interfaceName,
+ const char* signalName,
+ const char* signalSignature,
+ const std::shared_ptr<DBusProxyConnection>& dbusConnection,
+ const _InArgs&... inArgs) {
+ DBusMessage dbusMessage = DBusMessage::createSignal(
+ objectPath,
+ interfaceName,
+ signalName,
+ signalSignature);
+
+ if (sizeof...(_InArgs) > 0) {
+ DBusOutputStream outputStream(dbusMessage);
+ const bool success = DBusSerializableArguments<_InArgs...>::serialize(outputStream, inArgs...);
+ if (!success) {
+ return false;
+ }
+ outputStream.flush();
+ }
+
+ const bool dbusMessageSent = dbusConnection->sendDBusMessage(dbusMessage);
+ return dbusMessageSent;
+ }
+
+ template <typename _DBusStub = DBusStubAdapter>
+ static bool sendSignal(const _DBusStub &_stub,
+ const char *_name,
+ const char *_signature,
+ const _InArgs&... inArgs) {
+ return(sendSignal(_stub.getDBusAddress().getObjectPath().c_str(),
+ _stub.getDBusAddress().getInterface().c_str(),
+ _name,
+ _signature,
+ _stub.getDBusConnection(),
+ inArgs...));
+ }
+
+
+ template <typename _DBusStub = DBusStubAdapter>
+ static bool sendSignal(const char *_target,
+ const _DBusStub &_stub,
+ const char *_name,
+ const char *_signature,
+ const _InArgs&... inArgs) {
+ DBusMessage dbusMessage
+ = DBusMessage::createSignal(
+ _stub.getDBusAddress().getObjectPath().c_str(),
+ _stub.getDBusAddress().getInterface().c_str(),
+ _name,
+ _signature);
+
+ dbusMessage.setDestination(_target);
+
+ if (sizeof...(_InArgs) > 0) {
+ DBusOutputStream outputStream(dbusMessage);
+ const bool success = DBusSerializableArguments<_InArgs...>::serialize(outputStream, inArgs...);
+ if (!success) {
+ return false;
+ }
+ outputStream.flush();
+ }
+
+ return _stub.getDBusConnection()->sendDBusMessage(dbusMessage);
+ }
+};
+
+template< class, class >
+class DBusMethodStubDispatcher;
+
+template <
+ typename _StubClass,
+ template <class...> class _In, class... _InArgs>
+class DBusMethodStubDispatcher<_StubClass, _In<_InArgs...> >: public DBusStubAdapterHelper<_StubClass>::StubDispatcher {
+ public:
+ typedef DBusStubAdapterHelper<_StubClass> DBusStubAdapterHelperType;
+ typedef void (_StubClass::*_StubFunctor)(std::shared_ptr<CommonAPI::ClientId>, _InArgs...);
+
+ DBusMethodStubDispatcher(_StubFunctor stubFunctor):
+ stubFunctor_(stubFunctor) {
+ }
+
+ bool dispatchDBusMessage(const DBusMessage& dbusMessage, const std::shared_ptr<_StubClass>& stub, DBusStubAdapterHelperType& dbusStubAdapterHelper) {
+ return handleDBusMessage(dbusMessage, stub, dbusStubAdapterHelper, typename make_sequence<sizeof...(_InArgs)>::type());
+ }
+
+ private:
+ template <int... _InArgIndices>
+ inline bool handleDBusMessage(const DBusMessage& dbusMessage,
+ const std::shared_ptr<_StubClass>& stub,
+ DBusStubAdapterHelperType& dbusStubAdapterHelper,
+ index_sequence<_InArgIndices...>) const {
+ std::tuple<_InArgs...> argTuple;
+
+ if (sizeof...(_InArgs) > 0) {
+ DBusInputStream dbusInputStream(dbusMessage);
+ const bool success = DBusSerializableArguments<_InArgs...>::deserialize(dbusInputStream, std::get<_InArgIndices>(argTuple)...);
+ if (!success)
+ return false;
+ }
+
+ std::shared_ptr<DBusClientId> clientId = std::make_shared<DBusClientId>(std::string(dbusMessage.getSender()));
+
+ (stub.get()->*stubFunctor_)(clientId, std::move(std::get<_InArgIndices>(argTuple))...);
+
+ return true;
+ }
+
+ _StubFunctor stubFunctor_;
+};
+
+
+template< class, class, class>
+class DBusMethodWithReplyStubDispatcher;
+
+template <
+ typename _StubClass,
+ template <class...> class _In, class... _InArgs,
+ template <class...> class _Out, class... _OutArgs>
+class DBusMethodWithReplyStubDispatcher<_StubClass, _In<_InArgs...>, _Out<_OutArgs...> >:
+ public DBusStubAdapterHelper<_StubClass>::StubDispatcher {
+ public:
+ typedef DBusStubAdapterHelper<_StubClass> DBusStubAdapterHelperType;
+ typedef std::function<void (_OutArgs...)> ReplyType_t;
+ typedef void (_StubClass::*_StubFunctor)(
+ std::shared_ptr<CommonAPI::ClientId>, _InArgs..., ReplyType_t);
+
+ DBusMethodWithReplyStubDispatcher(_StubFunctor stubFunctor, const char* dbusReplySignature, std::tuple<_InArgs..., _OutArgs...> _args):
+ stubFunctor_(stubFunctor),
+ dbusReplySignature_(dbusReplySignature),
+ args_(_args),
+ currentCall_(0) {
+ }
+
+ bool dispatchDBusMessage(const DBusMessage& dbusMessage, const std::shared_ptr<_StubClass>& stub, DBusStubAdapterHelperType& dbusStubAdapterHelper) {
+ connection_ = dbusStubAdapterHelper.getDBusConnection();
+ return handleDBusMessage(
+ dbusMessage,
+ stub,
+ dbusStubAdapterHelper,
+ typename make_sequence_range<sizeof...(_InArgs), 0>::type(),
+ typename make_sequence_range<sizeof...(_OutArgs), sizeof...(_InArgs)>::type(), args_);
+ }
+
+ bool sendReply(CommonAPI::CallId_t _call, std::tuple<_OutArgs...> args = std::make_tuple()) {
+ return sendReplyInternal(_call, typename make_sequence_range<sizeof...(_OutArgs), 0>::type(), args);
+ }
+
+private:
+ template <int... _InArgIndices, int... _OutArgIndices>
+ inline bool handleDBusMessage(const DBusMessage& dbusMessage,
+ const std::shared_ptr<_StubClass>& stub,
+ DBusStubAdapterHelperType& dbusStubAdapterHelper,
+ index_sequence<_InArgIndices...>,
+ index_sequence<_OutArgIndices...>,
+ std::tuple<_InArgs..., _OutArgs...> argTuple) {
+ if (sizeof...(_InArgs) > 0) {
+ DBusInputStream dbusInputStream(dbusMessage);
+ const bool success = DBusSerializableArguments<_InArgs...>::deserialize(dbusInputStream, std::get<_InArgIndices>(argTuple)...);
+ if (!success)
+ return false;
+ }
+
+ std::shared_ptr<DBusClientId> clientId
+ = std::make_shared<DBusClientId>(std::string(dbusMessage.getSender()));
+ DBusMessage reply = dbusMessage.createMethodReturn(dbusReplySignature_);
+
+ CommonAPI::CallId_t call;
+ {
+ std::lock_guard<std::mutex> lock(mutex_);
+ call = currentCall_++;
+ pending_[call] = reply;
+ }
+
+ (stub.get()->*stubFunctor_)(
+ clientId,
+ std::move(std::get<_InArgIndices>(argTuple))...,
+ [call, this](_OutArgs... _args){
+ this->sendReply(call, std::make_tuple(_args...));
+ }
+ );
+
+ return true;
+ }
+
+ template<int... _OutArgIndices>
+ bool sendReplyInternal(CommonAPI::CallId_t _call,
+ index_sequence<_OutArgIndices...>,
+ std::tuple<_OutArgs...> args) {
+ std::lock_guard<std::mutex> lock(mutex_);
+ auto reply = pending_.find(_call);
+ if (reply != pending_.end()) {
+ if (sizeof...(_OutArgs) > 0) {
+ DBusOutputStream output(reply->second);
+ if (!DBusSerializableArguments<_OutArgs...>::serialize(
+ output, std::get<_OutArgIndices>(args)...)) {
+ pending_.erase(_call);
+ return false;
+ }
+ output.flush();
+ }
+ bool isSuccessful = connection_->sendDBusMessage(reply->second);
+ pending_.erase(_call);
+ return isSuccessful;
+ }
+ return false;
+ }
+
+ _StubFunctor stubFunctor_;
+ const char* dbusReplySignature_;
+ std::tuple<_InArgs..., _OutArgs...> args_;
+
+ CommonAPI::CallId_t currentCall_;
+ std::map<CommonAPI::CallId_t, DBusMessage> pending_;
+ std::mutex mutex_; // protects pending_
+
+ std::shared_ptr<DBusProxyConnection> connection_;
+};
+
+template< class, class, class, class >
+class DBusMethodWithReplyAdapterDispatcher;
+
+template <
+ typename _StubClass,
+ typename _StubAdapterClass,
+ template <class...> class _In, class... _InArgs,
+ template <class...> class _Out, class... _OutArgs>
+class DBusMethodWithReplyAdapterDispatcher<_StubClass, _StubAdapterClass, _In<_InArgs...>, _Out<_OutArgs...> >:
+ public DBusStubAdapterHelper<_StubClass>::StubDispatcher {
+ public:
+ typedef DBusStubAdapterHelper<_StubClass> DBusStubAdapterHelperType;
+ typedef void (_StubAdapterClass::*_StubFunctor)(std::shared_ptr<CommonAPI::ClientId>, _InArgs..., _OutArgs&...);
+ typedef typename CommonAPI::Stub<typename DBusStubAdapterHelperType::StubAdapterType, typename _StubClass::RemoteEventType> StubType;
+
+ DBusMethodWithReplyAdapterDispatcher(_StubFunctor stubFunctor, const char* dbusReplySignature):
+ stubFunctor_(stubFunctor),
+ dbusReplySignature_(dbusReplySignature) {
+ }
+
+ bool dispatchDBusMessage(const DBusMessage& dbusMessage, const std::shared_ptr<_StubClass>& stub, DBusStubAdapterHelperType& dbusStubAdapterHelper) {
+ std::tuple<_InArgs..., _OutArgs...> argTuple;
+ return handleDBusMessage(
+ dbusMessage,
+ stub,
+ dbusStubAdapterHelper,
+ typename make_sequence_range<sizeof...(_InArgs), 0>::type(),
+ typename make_sequence_range<sizeof...(_OutArgs), sizeof...(_InArgs)>::type(),argTuple);
+ }
+
+ private:
+ template <int... _InArgIndices, int... _OutArgIndices>
+ inline bool handleDBusMessage(const DBusMessage& dbusMessage,
+ const std::shared_ptr<_StubClass>& stub,
+ DBusStubAdapterHelperType& dbusStubAdapterHelper,
+ index_sequence<_InArgIndices...>,
+ index_sequence<_OutArgIndices...>,
+ std::tuple<_InArgs..., _OutArgs...> argTuple) const {
+
+ if (sizeof...(_InArgs) > 0) {
+ DBusInputStream dbusInputStream(dbusMessage);
+ const bool success = DBusSerializableArguments<_InArgs...>::deserialize(dbusInputStream, std::get<_InArgIndices>(argTuple)...);
+ if (!success)
+ return false;
+ }
+
+ std::shared_ptr<DBusClientId> clientId = std::make_shared<DBusClientId>(std::string(dbusMessage.getSender()));
+
+ (stub->StubType::getStubAdapter().get()->*stubFunctor_)(clientId, std::move(std::get<_InArgIndices>(argTuple))..., std::get<_OutArgIndices>(argTuple)...);
+ DBusMessage dbusMessageReply = dbusMessage.createMethodReturn(dbusReplySignature_);
+
+ if (sizeof...(_OutArgs) > 0) {
+ DBusOutputStream dbusOutputStream(dbusMessageReply);
+ const bool success = DBusSerializableArguments<_OutArgs...>::serialize(dbusOutputStream, std::get<_OutArgIndices>(argTuple)...);
+ if (!success)
+ return false;
+
+ dbusOutputStream.flush();
+ }
+
+ return dbusStubAdapterHelper.getDBusConnection()->sendDBusMessage(dbusMessageReply);
+ }
+
+ _StubFunctor stubFunctor_;
+ const char* dbusReplySignature_;
+};
+
+
+template <typename _StubClass, typename _AttributeType, typename _AttributeDepl = EmptyDeployment>
+class DBusGetAttributeStubDispatcher: public virtual DBusStubAdapterHelper<_StubClass>::StubDispatcher {
+ public:
+ typedef DBusStubAdapterHelper<_StubClass> DBusStubAdapterHelperType;
+ typedef const _AttributeType& (_StubClass::*GetStubFunctor)(std::shared_ptr<CommonAPI::ClientId>);
+
+ DBusGetAttributeStubDispatcher(GetStubFunctor _getStubFunctor, const char *_signature, _AttributeDepl *_depl = nullptr):
+ getStubFunctor_(_getStubFunctor),
+ signature_(_signature),
+ depl_(_depl) {
+ }
+
+ virtual ~DBusGetAttributeStubDispatcher() {};
+
+ bool dispatchDBusMessage(const DBusMessage& dbusMessage, const std::shared_ptr<_StubClass>& stub, DBusStubAdapterHelperType& dbusStubAdapterHelper) {
+ return sendAttributeValueReply(dbusMessage, stub, dbusStubAdapterHelper);
+ }
+ protected:
+ virtual bool sendAttributeValueReply(const DBusMessage& dbusMessage, const std::shared_ptr<_StubClass>& stub, DBusStubAdapterHelperType& dbusStubAdapterHelper) {
+ DBusMessage dbusMessageReply = dbusMessage.createMethodReturn(signature_);
+ DBusOutputStream dbusOutputStream(dbusMessageReply);
+
+ std::shared_ptr<DBusClientId> clientId = std::make_shared<DBusClientId>(std::string(dbusMessage.getSender()));
+
+ dbusOutputStream << CommonAPI::Deployable<_AttributeType, _AttributeDepl>((stub.get()->*getStubFunctor_)(clientId), depl_);
+ dbusOutputStream.flush();
+
+ return dbusStubAdapterHelper.getDBusConnection()->sendDBusMessage(dbusMessageReply);
+ }
+
+
+ GetStubFunctor getStubFunctor_;
+ const char* signature_;
+ _AttributeDepl *depl_;
+};
+
+template <typename _StubClass, typename _AttributeType, typename _AttributeDepl = EmptyDeployment>
+class DBusSetAttributeStubDispatcher: public virtual DBusGetAttributeStubDispatcher<_StubClass, _AttributeType, _AttributeDepl> {
+ public:
+ typedef typename DBusGetAttributeStubDispatcher<_StubClass, _AttributeType, _AttributeDepl>::DBusStubAdapterHelperType DBusStubAdapterHelperType;
+ typedef typename DBusStubAdapterHelperType::RemoteEventHandlerType RemoteEventHandlerType;
+
+ typedef typename DBusGetAttributeStubDispatcher<_StubClass, _AttributeType, _AttributeDepl>::GetStubFunctor GetStubFunctor;
+ typedef bool (RemoteEventHandlerType::*OnRemoteSetFunctor)(std::shared_ptr<CommonAPI::ClientId>, _AttributeType);
+ typedef void (RemoteEventHandlerType::*OnRemoteChangedFunctor)();
+
+ DBusSetAttributeStubDispatcher(GetStubFunctor getStubFunctor,
+ OnRemoteSetFunctor onRemoteSetFunctor,
+ OnRemoteChangedFunctor onRemoteChangedFunctor,
+ const char* dbusSignature,
+ _AttributeDepl *_depl = nullptr) :
+ DBusGetAttributeStubDispatcher<_StubClass, _AttributeType, _AttributeDepl>(getStubFunctor, dbusSignature, _depl),
+ onRemoteSetFunctor_(onRemoteSetFunctor),
+ onRemoteChangedFunctor_(onRemoteChangedFunctor) {
+ }
+
+ virtual ~DBusSetAttributeStubDispatcher() {};
+
+ bool dispatchDBusMessage(const DBusMessage& dbusMessage, const std::shared_ptr<_StubClass>& stub, DBusStubAdapterHelperType& dbusStubAdapterHelper) {
+ bool attributeValueChanged;
+
+ if (!setAttributeValue(dbusMessage, stub, dbusStubAdapterHelper, attributeValueChanged))
+ return false;
+
+ if (attributeValueChanged)
+ notifyOnRemoteChanged(dbusStubAdapterHelper);
+
+ return true;
+ }
+
+ protected:
+ virtual _AttributeType retrieveAttributeValue(const DBusMessage& dbusMessage, bool& errorOccured) {
+ errorOccured = false;
+
+ DBusInputStream dbusInputStream(dbusMessage);
+ CommonAPI::Deployable<_AttributeType, _AttributeDepl> attributeValue(this->depl_);
+ dbusInputStream >> attributeValue;
+
+ if (dbusInputStream.hasError()) {
+ errorOccured = true;
+ }
+
+ return attributeValue.getValue();
+ }
+
+ inline bool setAttributeValue(const DBusMessage& dbusMessage,
+ const std::shared_ptr<_StubClass>& stub,
+ DBusStubAdapterHelperType& dbusStubAdapterHelper,
+ bool& attributeValueChanged) {
+ bool errorOccured;
+ CommonAPI::Deployable<_AttributeType, _AttributeDepl> attributeValue(
+ retrieveAttributeValue(dbusMessage, errorOccured), this->depl_);
+
+ if(errorOccured) {
+ return false;
+ }
+
+ std::shared_ptr<DBusClientId> clientId = std::make_shared<DBusClientId>(std::string(dbusMessage.getSender()));
+
+ attributeValueChanged = (dbusStubAdapterHelper.getRemoteEventHandler()->*onRemoteSetFunctor_)(clientId, std::move(attributeValue.getValue()));
+
+ return this->sendAttributeValueReply(dbusMessage, stub, dbusStubAdapterHelper);
+ }
+
+ inline void notifyOnRemoteChanged(DBusStubAdapterHelperType& dbusStubAdapterHelper) {
+ (dbusStubAdapterHelper.getRemoteEventHandler()->*onRemoteChangedFunctor_)();
+ }
+
+ inline const _AttributeType& getAttributeValue(std::shared_ptr<CommonAPI::ClientId> clientId, const std::shared_ptr<_StubClass>& stub) {
+ return (stub.get()->*(this->getStubFunctor_))(clientId);
+ }
+
+ const OnRemoteSetFunctor onRemoteSetFunctor_;
+ const OnRemoteChangedFunctor onRemoteChangedFunctor_;
+};
+
+template <typename _StubClass, typename _AttributeType, typename _AttributeDepl = EmptyDeployment>
+class DBusSetObservableAttributeStubDispatcher: public virtual DBusSetAttributeStubDispatcher<_StubClass, _AttributeType, _AttributeDepl> {
+ public:
+ typedef typename DBusSetAttributeStubDispatcher<_StubClass, _AttributeType, _AttributeDepl>::DBusStubAdapterHelperType DBusStubAdapterHelperType;
+ typedef typename DBusStubAdapterHelperType::StubAdapterType StubAdapterType;
+ typedef typename DBusSetAttributeStubDispatcher<_StubClass, _AttributeType, _AttributeDepl>::GetStubFunctor GetStubFunctor;
+ typedef typename DBusSetAttributeStubDispatcher<_StubClass, _AttributeType, _AttributeDepl>::OnRemoteSetFunctor OnRemoteSetFunctor;
+ typedef typename DBusSetAttributeStubDispatcher<_StubClass, _AttributeType, _AttributeDepl>::OnRemoteChangedFunctor OnRemoteChangedFunctor;
+ typedef typename CommonAPI::Stub<StubAdapterType, typename _StubClass::RemoteEventType> StubType;
+ typedef void (StubAdapterType::*FireChangedFunctor)(const _AttributeType&);
+
+ DBusSetObservableAttributeStubDispatcher(GetStubFunctor getStubFunctor,
+ OnRemoteSetFunctor onRemoteSetFunctor,
+ OnRemoteChangedFunctor onRemoteChangedFunctor,
+ FireChangedFunctor fireChangedFunctor,
+ const char* dbusSignature,
+ _AttributeDepl *_depl = nullptr)
+ : DBusGetAttributeStubDispatcher<_StubClass, _AttributeType, _AttributeDepl>(
+ getStubFunctor, dbusSignature, _depl),
+ DBusSetAttributeStubDispatcher<_StubClass, _AttributeType, _AttributeDepl>(
+ getStubFunctor, onRemoteSetFunctor, onRemoteChangedFunctor, dbusSignature, _depl),
+ fireChangedFunctor_(fireChangedFunctor) {
+ }
+
+ virtual ~DBusSetObservableAttributeStubDispatcher() {};
+
+ bool dispatchDBusMessage(const DBusMessage& dbusMessage, const std::shared_ptr<_StubClass>& stub, DBusStubAdapterHelperType& dbusStubAdapterHelper) {
+ bool attributeValueChanged;
+ if (!this->setAttributeValue(dbusMessage, stub, dbusStubAdapterHelper, attributeValueChanged))
+ return false;
+
+ if (attributeValueChanged) {
+ std::shared_ptr<DBusClientId> clientId = std::make_shared<DBusClientId>(std::string(dbusMessage.getSender()));
+ fireAttributeValueChanged(clientId, dbusStubAdapterHelper, stub);
+ this->notifyOnRemoteChanged(dbusStubAdapterHelper);
+ }
+ return true;
+ }
+protected:
+ virtual void fireAttributeValueChanged(std::shared_ptr<CommonAPI::ClientId> clientId,
+ DBusStubAdapterHelperType& dbusStubAdapterHelper,
+ const std::shared_ptr<_StubClass> stub) {
+ (stub->StubType::getStubAdapter().get()->*fireChangedFunctor_)(this->getAttributeValue(clientId, stub));
+ }
+
+ const FireChangedFunctor fireChangedFunctor_;
+};
+
+} // namespace DBus
+} // namespace CommonAPI
+
+#endif // COMMONAPI_DBUS_DBUSSTUBADAPTERHELPER_HPP_
diff --git a/include/CommonAPI/DBus/DBusTypeOutputStream.hpp b/include/CommonAPI/DBus/DBusTypeOutputStream.hpp
new file mode 100644
index 0000000..3ba7cf7
--- /dev/null
+++ b/include/CommonAPI/DBus/DBusTypeOutputStream.hpp
@@ -0,0 +1,153 @@
+// Copyright (C) 2014-2015 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#ifndef COMMONAPI_DBUS_DBUSTYPEOUTPUTSTREAM_H_
+#define COMMONAPI_DBUS_DBUSTYPEOUTPUTSTREAM_H_
+
+#include <CommonAPI/TypeOutputStream.hpp>
+
+namespace CommonAPI {
+namespace DBus {
+
+class DBusTypeOutputStream: public TypeOutputStream<DBusTypeOutputStream> {
+public:
+ DBusTypeOutputStream() : signature_("") {}
+
+ TypeOutputStream &writeType(const bool &_type) {
+ signature_.append("b");
+ return (*this);
+ }
+
+ TypeOutputStream &writeType(const int8_t &) {
+ signature_.append("y");
+ return (*this);
+ }
+
+ TypeOutputStream &writeType(const int16_t &) {
+ signature_.append("n");
+ return (*this);
+ }
+
+ TypeOutputStream &writeType(const int32_t &) {
+ signature_.append("i");
+ return (*this);
+ }
+
+ TypeOutputStream &writeType(const int64_t &) {
+ signature_.append("x");
+ return (*this);
+ }
+
+ TypeOutputStream &writeType(const uint8_t &) {
+ signature_.append("y");
+ return (*this);
+ }
+
+ TypeOutputStream &writeType(const uint16_t &) {
+ signature_.append("q");
+ return (*this);
+ }
+
+ TypeOutputStream &writeType(const uint32_t &) {
+ signature_.append("u");
+ return (*this);
+ }
+
+ TypeOutputStream &writeType(const uint64_t &) {
+ signature_.append("t");
+ return (*this);
+ }
+
+ TypeOutputStream &writeType(const float &) {
+ signature_.append("d");
+ return (*this);
+ }
+
+ TypeOutputStream &writeType(const double &) {
+ signature_.append("d");
+ return (*this);
+ }
+
+ TypeOutputStream &writeType(const std::string &) {
+ signature_.append("s");
+ return (*this);
+ }
+
+ TypeOutputStream &writeType() {
+ signature_.append("ay");
+ return (*this);
+ }
+
+ TypeOutputStream &writeVersionType() {
+ signature_.append("(uu)");
+ return (*this);
+ }
+
+ template<typename... _Types>
+ TypeOutputStream &writeType(const Struct<_Types...> &_value) {
+ signature_.append("(");
+ const auto itsSize(std::tuple_size<std::tuple<_Types...>>::value);
+ StructTypeWriter<itsSize-1, DBusTypeOutputStream, Struct<_Types...>>{}
+ (*this, _value);
+ signature_.append(")");
+ return (*this);
+ }
+
+ template<class _PolymorphicStruct>
+ TypeOutputStream &writeType(const std::shared_ptr<_PolymorphicStruct> &_value) {
+ signature_.append("(");
+ _value->writeType(*this);
+ signature_.append(")");
+ return (*this);
+ }
+
+ template<typename... _Types>
+ TypeOutputStream &writeType(const Variant<_Types...> &_value) {
+ signature_.append("(yv)");
+ return (*this);
+ }
+
+ template<typename _Deployment, typename... _Types>
+ TypeOutputStream &writeType(const Variant<_Types...> &_value, const _Deployment *_depl) {
+ if (_depl != nullptr && _depl->isFreeDesktop_) {
+ signature_.append("v");
+ } else {
+ signature_.append("(yv)");
+ }
+ TypeOutputStreamWriteVisitor<DBusTypeOutputStream> typeVisitor(*this);
+ ApplyVoidVisitor<TypeOutputStreamWriteVisitor<DBusTypeOutputStream>,
+ Variant<_Types...>, _Types...>::visit(typeVisitor, _value);
+ return (*this);
+ }
+
+ template<typename _ElementType>
+ TypeOutputStream &writeType(const std::vector<_ElementType> &_value) {
+ signature_.append("a");
+ return (*this);
+ }
+
+ template<typename _KeyType, typename _ValueType, typename _HasherType>
+ TypeOutputStream &writeType(const std::unordered_map<_KeyType, _ValueType, _HasherType> &_value) {
+ signature_.append("a{");
+ _KeyType dummyKey;
+ writeType(dummyKey);
+ _ValueType dummyValue;
+ writeType(dummyValue);
+ signature_.append("}");
+ return (*this);
+ }
+
+ inline std::string getSignature() {
+ return std::move(signature_);
+ }
+
+private:
+ std::string signature_;
+};
+
+} // namespace DBus
+} // namespace CommonAPI
+
+#endif // COMMONAPI_DBUS_DBUSTYPEOUTPUTSTREAM_HPP_
diff --git a/include/CommonAPI/DBus/DBusTypes.hpp b/include/CommonAPI/DBus/DBusTypes.hpp
new file mode 100644
index 0000000..4c723c4
--- /dev/null
+++ b/include/CommonAPI/DBus/DBusTypes.hpp
@@ -0,0 +1,37 @@
+// Copyright (C) 2014-2015 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#if !defined (COMMONAPI_INTERNAL_COMPILATION)
+#error "Only <CommonAPI/CommonAPI.hpp> can be included directly, this file may disappear or change contents."
+#endif
+
+#ifndef COMMONAPI_DBUS_DBUSTYPES_HPP_
+#define COMMONAPI_DBUS_DBUSTYPES_HPP_
+
+#include <string>
+#include <unordered_map>
+
+#include <dbus/dbus.h>
+
+namespace CommonAPI {
+namespace DBus {
+
+typedef std::unordered_map<std::string, bool> DBusPropertiesChangedDict;
+typedef std::unordered_map<std::string,
+ DBusPropertiesChangedDict> DBusInterfacesAndPropertiesDict;
+typedef std::unordered_map<std::string,
+ DBusInterfacesAndPropertiesDict> DBusObjectPathAndInterfacesDict;
+
+enum class DBusType_t {
+ SESSION = DBUS_BUS_SESSION,
+ SYSTEM = DBUS_BUS_SYSTEM,
+ STARTER = DBUS_BUS_STARTER,
+ WRAPPED
+};
+
+} // namespace DBus
+} // namespace CommonAPI
+
+#endif // COMMONAPI_DBUS_DBUSTYPES_HPP_
diff --git a/include/CommonAPI/DBus/DBusUtils.hpp b/include/CommonAPI/DBus/DBusUtils.hpp
new file mode 100644
index 0000000..ba8826d
--- /dev/null
+++ b/include/CommonAPI/DBus/DBusUtils.hpp
@@ -0,0 +1,37 @@
+// Copyright (C) 2013-2015 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#if !defined (COMMONAPI_INTERNAL_COMPILATION)
+#error "Only <CommonAPI/CommonAPI.hpp> can be included directly, this file may disappear or change contents."
+#endif
+
+#ifndef COMMONAPI_DBUS_DBUSUTILS_HPP_
+#define COMMONAPI_DBUS_DBUSUTILS_HPP_
+
+#include <future>
+
+namespace CommonAPI {
+namespace DBus {
+
+//In gcc 4.4.1, the enumeration "std::future_status" is defined, but the return values of some functions
+//are bool where the same functions in gcc 4.6. return a value from this enum. This template is a way
+//to ensure compatibility for this issue.
+template<typename _FutureWaitType>
+inline bool checkReady(_FutureWaitType&);
+
+template<>
+inline bool checkReady<bool>(bool& returnedValue) {
+ return returnedValue;
+}
+
+template<>
+inline bool checkReady<std::future_status>(std::future_status& returnedValue) {
+ return returnedValue == std::future_status::ready;
+}
+
+} // namespace DBus
+} // namespace CommonAPI
+
+#endif // COMMONAPI_DBUS_DBUSUTILS_HPP_
diff --git a/include/murmurhash/MurmurHash3.h b/include/murmurhash/MurmurHash3.h
new file mode 100644
index 0000000..54e9d3f
--- /dev/null
+++ b/include/murmurhash/MurmurHash3.h
@@ -0,0 +1,37 @@
+//-----------------------------------------------------------------------------
+// MurmurHash3 was written by Austin Appleby, and is placed in the public
+// domain. The author hereby disclaims copyright to this source code.
+
+#ifndef _MURMURHASH3_H_
+#define _MURMURHASH3_H_
+
+//-----------------------------------------------------------------------------
+// Platform-specific functions and macros
+
+// Microsoft Visual Studio
+
+#if defined(_MSC_VER)
+
+typedef unsigned char uint8_t;
+typedef unsigned long uint32_t;
+typedef unsigned __int64 uint64_t;
+
+// Other compilers
+
+#else // defined(_MSC_VER)
+
+#include <stdint.h>
+
+#endif // !defined(_MSC_VER)
+
+//-----------------------------------------------------------------------------
+
+void MurmurHash3_x86_32 ( const void * key, int len, uint32_t seed, void * out );
+
+void MurmurHash3_x86_128 ( const void * key, int len, uint32_t seed, void * out );
+
+void MurmurHash3_x64_128 ( const void * key, int len, uint32_t seed, void * out );
+
+//-----------------------------------------------------------------------------
+
+#endif // _MURMURHASH3_H_
diff --git a/include/pugixml/pugiconfig.hpp b/include/pugixml/pugiconfig.hpp
new file mode 100644
index 0000000..5a63fd4
--- /dev/null
+++ b/include/pugixml/pugiconfig.hpp
@@ -0,0 +1,69 @@
+/**
+ * pugixml parser - version 1.2
+ * --------------------------------------------------------
+ * Copyright (C) 2006-2012, by Arseny Kapoulkine (arseny.kapoulkine@gmail.com)
+ * Report bugs and download new versions at http://pugixml.org/
+ *
+ * This library is distributed under the MIT License. See notice at the end
+ * of this file.
+ *
+ * This work is based on the pugxml parser, which is:
+ * Copyright (C) 2003, by Kristen Wegner (kristen@tima.net)
+ */
+
+#ifndef HEADER_PUGICONFIG_HPP
+#define HEADER_PUGICONFIG_HPP
+
+// Uncomment this to enable wchar_t mode
+// #define PUGIXML_WCHAR_MODE
+
+// Uncomment this to disable XPath
+// #define PUGIXML_NO_XPATH
+
+// Uncomment this to disable STL
+// #define PUGIXML_NO_STL
+
+// Uncomment this to disable exceptions
+// #define PUGIXML_NO_EXCEPTIONS
+
+// Set this to control attributes for public classes/functions, i.e.:
+// #define PUGIXML_API __declspec(dllexport) // to export all public symbols from DLL
+// #define PUGIXML_CLASS __declspec(dllimport) // to import all classes from DLL
+// #define PUGIXML_FUNCTION __fastcall // to set calling conventions to all public functions to fastcall
+// In absence of PUGIXML_CLASS/PUGIXML_FUNCTION definitions PUGIXML_API is used instead
+
+// Uncomment this to switch to header-only version
+// #define PUGIXML_HEADER_ONLY
+// #include "pugixml.cpp"
+
+// Tune these constants to adjust memory-related behavior
+// #define PUGIXML_MEMORY_PAGE_SIZE 32768
+// #define PUGIXML_MEMORY_OUTPUT_STACK 10240
+// #define PUGIXML_MEMORY_XPATH_PAGE_SIZE 4096
+
+#endif
+
+/**
+ * Copyright (c) 2006-2012 Arseny Kapoulkine
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
diff --git a/include/pugixml/pugixml.hpp b/include/pugixml/pugixml.hpp
new file mode 100644
index 0000000..77b4dcf
--- /dev/null
+++ b/include/pugixml/pugixml.hpp
@@ -0,0 +1,1265 @@
+/**
+ * pugixml parser - version 1.2
+ * --------------------------------------------------------
+ * Copyright (C) 2006-2012, by Arseny Kapoulkine (arseny.kapoulkine@gmail.com)
+ * Report bugs and download new versions at http://pugixml.org/
+ *
+ * This library is distributed under the MIT License. See notice at the end
+ * of this file.
+ *
+ * This work is based on the pugxml parser, which is:
+ * Copyright (C) 2003, by Kristen Wegner (kristen@tima.net)
+ */
+
+#ifndef PUGIXML_VERSION
+// Define version macro; evaluates to major * 100 + minor so that it's safe to use in less-than comparisons
+# define PUGIXML_VERSION 120
+#endif
+
+// Include user configuration file (this can define various configuration macros)
+#include "pugiconfig.hpp"
+
+#ifndef HEADER_PUGIXML_HPP
+#define HEADER_PUGIXML_HPP
+
+// Include stddef.h for size_t and ptrdiff_t
+#include <stddef.h>
+
+// Include exception header for XPath
+#if !defined(PUGIXML_NO_XPATH) && !defined(PUGIXML_NO_EXCEPTIONS)
+# include <exception>
+#endif
+
+// Include STL headers
+#ifndef PUGIXML_NO_STL
+# include <iterator>
+# include <iosfwd>
+# include <string>
+#endif
+
+// Macro for deprecated features
+#ifndef PUGIXML_DEPRECATED
+# if defined(__GNUC__)
+# define PUGIXML_DEPRECATED __attribute__((deprecated))
+# elif defined(_MSC_VER) && _MSC_VER >= 1300
+# define PUGIXML_DEPRECATED __declspec(deprecated)
+# else
+# define PUGIXML_DEPRECATED
+# endif
+#endif
+
+// If no API is defined, assume default
+#ifndef PUGIXML_API
+# define PUGIXML_API
+#endif
+
+// If no API for classes is defined, assume default
+#ifndef PUGIXML_CLASS
+# define PUGIXML_CLASS PUGIXML_API
+#endif
+
+// If no API for functions is defined, assume default
+#ifndef PUGIXML_FUNCTION
+# define PUGIXML_FUNCTION PUGIXML_API
+#endif
+
+// Character interface macros
+#ifdef PUGIXML_WCHAR_MODE
+# define PUGIXML_TEXT(t) L ## t
+# define PUGIXML_CHAR wchar_t
+#else
+# define PUGIXML_TEXT(t) t
+# define PUGIXML_CHAR char
+#endif
+
+namespace pugi
+{
+ // Character type used for all internal storage and operations; depends on PUGIXML_WCHAR_MODE
+ typedef PUGIXML_CHAR char_t;
+
+#ifndef PUGIXML_NO_STL
+ // String type used for operations that work with STL string; depends on PUGIXML_WCHAR_MODE
+ typedef std::basic_string<PUGIXML_CHAR, std::char_traits<PUGIXML_CHAR>, std::allocator<PUGIXML_CHAR> > string_t;
+#endif
+}
+
+// The PugiXML namespace
+namespace pugi
+{
+ // Tree node types
+ enum xml_node_type
+ {
+ node_null, // Empty (null) node handle
+ node_document, // A document tree's absolute root
+ node_element, // Element tag, i.e. '<node/>'
+ node_pcdata, // Plain character data, i.e. 'text'
+ node_cdata, // Character data, i.e. '<![CDATA[text]]>'
+ node_comment, // Comment tag, i.e. '<!-- text -->'
+ node_pi, // Processing instruction, i.e. '<?name?>'
+ node_declaration, // Document declaration, i.e. '<?xml version="1.0"?>'
+ node_doctype // Document type declaration, i.e. '<!DOCTYPE doc>'
+ };
+
+ // Parsing options
+
+ // Minimal parsing mode (equivalent to turning all other flags off).
+ // Only elements and PCDATA sections are added to the DOM tree, no text conversions are performed.
+ const unsigned int parse_minimal = 0x0000;
+
+ // This flag determines if processing instructions (node_pi) are added to the DOM tree. This flag is off by default.
+ const unsigned int parse_pi = 0x0001;
+
+ // This flag determines if comments (node_comment) are added to the DOM tree. This flag is off by default.
+ const unsigned int parse_comments = 0x0002;
+
+ // This flag determines if CDATA sections (node_cdata) are added to the DOM tree. This flag is on by default.
+ const unsigned int parse_cdata = 0x0004;
+
+ // This flag determines if plain character data (node_pcdata) that consist only of whitespace are added to the DOM tree.
+ // This flag is off by default; turning it on usually results in slower parsing and more memory consumption.
+ const unsigned int parse_ws_pcdata = 0x0008;
+
+ // This flag determines if character and entity references are expanded during parsing. This flag is on by default.
+ const unsigned int parse_escapes = 0x0010;
+
+ // This flag determines if EOL characters are normalized (converted to #xA) during parsing. This flag is on by default.
+ const unsigned int parse_eol = 0x0020;
+
+ // This flag determines if attribute values are normalized using CDATA normalization rules during parsing. This flag is on by default.
+ const unsigned int parse_wconv_attribute = 0x0040;
+
+ // This flag determines if attribute values are normalized using NMTOKENS normalization rules during parsing. This flag is off by default.
+ const unsigned int parse_wnorm_attribute = 0x0080;
+
+ // This flag determines if document declaration (node_declaration) is added to the DOM tree. This flag is off by default.
+ const unsigned int parse_declaration = 0x0100;
+
+ // This flag determines if document type declaration (node_doctype) is added to the DOM tree. This flag is off by default.
+ const unsigned int parse_doctype = 0x0200;
+
+ // This flag determines if plain character data (node_pcdata) that is the only child of the parent node and that consists only
+ // of whitespace is added to the DOM tree.
+ // This flag is off by default; turning it on may result in slower parsing and more memory consumption.
+ const unsigned int parse_ws_pcdata_single = 0x0400;
+
+ // The default parsing mode.
+ // Elements, PCDATA and CDATA sections are added to the DOM tree, character/reference entities are expanded,
+ // End-of-Line characters are normalized, attribute values are normalized using CDATA normalization rules.
+ const unsigned int parse_default = parse_cdata | parse_escapes | parse_wconv_attribute | parse_eol;
+
+ // The full parsing mode.
+ // Nodes of all types are added to the DOM tree, character/reference entities are expanded,
+ // End-of-Line characters are normalized, attribute values are normalized using CDATA normalization rules.
+ const unsigned int parse_full = parse_default | parse_pi | parse_comments | parse_declaration | parse_doctype;
+
+ // These flags determine the encoding of input data for XML document
+ enum xml_encoding
+ {
+ encoding_auto, // Auto-detect input encoding using BOM or < / <? detection; use UTF8 if BOM is not found
+ encoding_utf8, // UTF8 encoding
+ encoding_utf16_le, // Little-endian UTF16
+ encoding_utf16_be, // Big-endian UTF16
+ encoding_utf16, // UTF16 with native endianness
+ encoding_utf32_le, // Little-endian UTF32
+ encoding_utf32_be, // Big-endian UTF32
+ encoding_utf32, // UTF32 with native endianness
+ encoding_wchar, // The same encoding wchar_t has (either UTF16 or UTF32)
+ encoding_latin1
+ };
+
+ // Formatting flags
+
+ // Indent the nodes that are written to output stream with as many indentation strings as deep the node is in DOM tree. This flag is on by default.
+ const unsigned int format_indent = 0x01;
+
+ // Write encoding-specific BOM to the output stream. This flag is off by default.
+ const unsigned int format_write_bom = 0x02;
+
+ // Use raw output mode (no indentation and no line breaks are written). This flag is off by default.
+ const unsigned int format_raw = 0x04;
+
+ // Omit default XML declaration even if there is no declaration in the document. This flag is off by default.
+ const unsigned int format_no_declaration = 0x08;
+
+ // Don't escape attribute values and PCDATA contents. This flag is off by default.
+ const unsigned int format_no_escapes = 0x10;
+
+ // Open file using text mode in xml_document::save_file. This enables special character (i.e. new-line) conversions on some systems. This flag is off by default.
+ const unsigned int format_save_file_text = 0x20;
+
+ // The default set of formatting flags.
+ // Nodes are indented depending on their depth in DOM tree, a default declaration is output if document has none.
+ const unsigned int format_default = format_indent;
+
+ // Forward declarations
+ struct xml_attribute_struct;
+ struct xml_node_struct;
+
+ class xml_node_iterator;
+ class xml_attribute_iterator;
+ class xml_named_node_iterator;
+
+ class xml_tree_walker;
+
+ class xml_node;
+
+ class xml_text;
+
+ #ifndef PUGIXML_NO_XPATH
+ class xpath_node;
+ class xpath_node_set;
+ class xpath_query;
+ class xpath_variable_set;
+ #endif
+
+ // Range-based for loop support
+ template <typename It> class xml_object_range
+ {
+ public:
+ typedef It const_iterator;
+
+ xml_object_range(It b, It e): _begin(b), _end(e)
+ {
+ }
+
+ It begin() const { return _begin; }
+ It end() const { return _end; }
+
+ private:
+ It _begin, _end;
+ };
+
+ // Writer interface for node printing (see xml_node::print)
+ class PUGIXML_CLASS xml_writer
+ {
+ public:
+ virtual ~xml_writer() {}
+
+ // Write memory chunk into stream/file/whatever
+ virtual void write(const void* data, size_t size) = 0;
+ };
+
+ // xml_writer implementation for FILE*
+ class PUGIXML_CLASS xml_writer_file: public xml_writer
+ {
+ public:
+ // Construct writer from a FILE* object; void* is used to avoid header dependencies on stdio
+ xml_writer_file(void* file);
+
+ virtual void write(const void* data, size_t size);
+
+ private:
+ void* file;
+ };
+
+ #ifndef PUGIXML_NO_STL
+ // xml_writer implementation for streams
+ class PUGIXML_CLASS xml_writer_stream: public xml_writer
+ {
+ public:
+ // Construct writer from an output stream object
+ xml_writer_stream(std::basic_ostream<char, std::char_traits<char> >& stream);
+ xml_writer_stream(std::basic_ostream<wchar_t, std::char_traits<wchar_t> >& stream);
+
+ virtual void write(const void* data, size_t size);
+
+ private:
+ std::basic_ostream<char, std::char_traits<char> >* narrow_stream;
+ std::basic_ostream<wchar_t, std::char_traits<wchar_t> >* wide_stream;
+ };
+ #endif
+
+ // A light-weight handle for manipulating attributes in DOM tree
+ class PUGIXML_CLASS xml_attribute
+ {
+ friend class xml_attribute_iterator;
+ friend class xml_node;
+
+ private:
+ xml_attribute_struct* _attr;
+
+ typedef void (*unspecified_bool_type)(xml_attribute***);
+
+ public:
+ // Default constructor. Constructs an empty attribute.
+ xml_attribute();
+
+ // Constructs attribute from internal pointer
+ explicit xml_attribute(xml_attribute_struct* attr);
+
+ // Safe bool conversion operator
+ operator unspecified_bool_type() const;
+
+ // Borland C++ workaround
+ bool operator!() const;
+
+ // Comparison operators (compares wrapped attribute pointers)
+ bool operator==(const xml_attribute& r) const;
+ bool operator!=(const xml_attribute& r) const;
+ bool operator<(const xml_attribute& r) const;
+ bool operator>(const xml_attribute& r) const;
+ bool operator<=(const xml_attribute& r) const;
+ bool operator>=(const xml_attribute& r) const;
+
+ // Check if attribute is empty
+ bool empty() const;
+
+ // Get attribute name/value, or "" if attribute is empty
+ const char_t* name() const;
+ const char_t* value() const;
+
+ // Get attribute value, or the default value if attribute is empty
+ const char_t* as_string(const char_t* def = PUGIXML_TEXT("")) const;
+
+ // Get attribute value as a number, or the default value if conversion did not succeed or attribute is empty
+ int as_int(int def = 0) const;
+ unsigned int as_uint(unsigned int def = 0) const;
+ double as_double(double def = 0) const;
+ float as_float(float def = 0) const;
+
+ // Get attribute value as bool (returns true if first character is in '1tTyY' set), or the default value if attribute is empty
+ bool as_bool(bool def = false) const;
+
+ // Set attribute name/value (returns false if attribute is empty or there is not enough memory)
+ bool set_name(const char_t* rhs);
+ bool set_value(const char_t* rhs);
+
+ // Set attribute value with type conversion (numbers are converted to strings, boolean is converted to "true"/"false")
+ bool set_value(int rhs);
+ bool set_value(unsigned int rhs);
+ bool set_value(double rhs);
+ bool set_value(bool rhs);
+
+ // Set attribute value (equivalent to set_value without error checking)
+ xml_attribute& operator=(const char_t* rhs);
+ xml_attribute& operator=(int rhs);
+ xml_attribute& operator=(unsigned int rhs);
+ xml_attribute& operator=(double rhs);
+ xml_attribute& operator=(bool rhs);
+
+ // Get next/previous attribute in the attribute list of the parent node
+ xml_attribute next_attribute() const;
+ xml_attribute previous_attribute() const;
+
+ // Get hash value (unique for handles to the same object)
+ size_t hash_value() const;
+
+ // Get internal pointer
+ xml_attribute_struct* internal_object() const;
+ };
+
+#ifdef __BORLANDC__
+ // Borland C++ workaround
+ bool PUGIXML_FUNCTION operator&&(const xml_attribute& lhs, bool rhs);
+ bool PUGIXML_FUNCTION operator||(const xml_attribute& lhs, bool rhs);
+#endif
+
+ // A light-weight handle for manipulating nodes in DOM tree
+ class PUGIXML_CLASS xml_node
+ {
+ friend class xml_attribute_iterator;
+ friend class xml_node_iterator;
+ friend class xml_named_node_iterator;
+
+ protected:
+ xml_node_struct* _root;
+
+ typedef void (*unspecified_bool_type)(xml_node***);
+
+ public:
+ // Default constructor. Constructs an empty node.
+ xml_node();
+
+ // Constructs node from internal pointer
+ explicit xml_node(xml_node_struct* p);
+
+ // Safe bool conversion operator
+ operator unspecified_bool_type() const;
+
+ // Borland C++ workaround
+ bool operator!() const;
+
+ // Comparison operators (compares wrapped node pointers)
+ bool operator==(const xml_node& r) const;
+ bool operator!=(const xml_node& r) const;
+ bool operator<(const xml_node& r) const;
+ bool operator>(const xml_node& r) const;
+ bool operator<=(const xml_node& r) const;
+ bool operator>=(const xml_node& r) const;
+
+ // Check if node is empty.
+ bool empty() const;
+
+ // Get node type
+ xml_node_type type() const;
+
+ // Get node name/value, or "" if node is empty or it has no name/value
+ const char_t* name() const;
+ const char_t* value() const;
+
+ // Get attribute list
+ xml_attribute first_attribute() const;
+ xml_attribute last_attribute() const;
+
+ // Get children list
+ xml_node first_child() const;
+ xml_node last_child() const;
+
+ // Get next/previous sibling in the children list of the parent node
+ xml_node next_sibling() const;
+ xml_node previous_sibling() const;
+
+ // Get parent node
+ xml_node parent() const;
+
+ // Get root of DOM tree this node belongs to
+ xml_node root() const;
+
+ // Get text object for the current node
+ xml_text text() const;
+
+ // Get child, attribute or next/previous sibling with the specified name
+ xml_node child(const char_t* name) const;
+ xml_attribute attribute(const char_t* name) const;
+ xml_node next_sibling(const char_t* name) const;
+ xml_node previous_sibling(const char_t* name) const;
+
+ // Get child value of current node; that is, value of the first child node of type PCDATA/CDATA
+ const char_t* child_value() const;
+
+ // Get child value of child with specified name. Equivalent to child(name).child_value().
+ const char_t* child_value(const char_t* name) const;
+
+ // Set node name/value (returns false if node is empty, there is not enough memory, or node can not have name/value)
+ bool set_name(const char_t* rhs);
+ bool set_value(const char_t* rhs);
+
+ // Add attribute with specified name. Returns added attribute, or empty attribute on errors.
+ xml_attribute append_attribute(const char_t* name);
+ xml_attribute prepend_attribute(const char_t* name);
+ xml_attribute insert_attribute_after(const char_t* name, const xml_attribute& attr);
+ xml_attribute insert_attribute_before(const char_t* name, const xml_attribute& attr);
+
+ // Add a copy of the specified attribute. Returns added attribute, or empty attribute on errors.
+ xml_attribute append_copy(const xml_attribute& proto);
+ xml_attribute prepend_copy(const xml_attribute& proto);
+ xml_attribute insert_copy_after(const xml_attribute& proto, const xml_attribute& attr);
+ xml_attribute insert_copy_before(const xml_attribute& proto, const xml_attribute& attr);
+
+ // Add child node with specified type. Returns added node, or empty node on errors.
+ xml_node append_child(xml_node_type type = node_element);
+ xml_node prepend_child(xml_node_type type = node_element);
+ xml_node insert_child_after(xml_node_type type, const xml_node& node);
+ xml_node insert_child_before(xml_node_type type, const xml_node& node);
+
+ // Add child element with specified name. Returns added node, or empty node on errors.
+ xml_node append_child(const char_t* name);
+ xml_node prepend_child(const char_t* name);
+ xml_node insert_child_after(const char_t* name, const xml_node& node);
+ xml_node insert_child_before(const char_t* name, const xml_node& node);
+
+ // Add a copy of the specified node as a child. Returns added node, or empty node on errors.
+ xml_node append_copy(const xml_node& proto);
+ xml_node prepend_copy(const xml_node& proto);
+ xml_node insert_copy_after(const xml_node& proto, const xml_node& node);
+ xml_node insert_copy_before(const xml_node& proto, const xml_node& node);
+
+ // Remove specified attribute
+ bool remove_attribute(const xml_attribute& a);
+ bool remove_attribute(const char_t* name);
+
+ // Remove specified child
+ bool remove_child(const xml_node& n);
+ bool remove_child(const char_t* name);
+
+ // Find attribute using predicate. Returns first attribute for which predicate returned true.
+ template <typename Predicate> xml_attribute find_attribute(Predicate pred) const
+ {
+ if (!_root) return xml_attribute();
+
+ for (xml_attribute attrib = first_attribute(); attrib; attrib = attrib.next_attribute())
+ if (pred(attrib))
+ return attrib;
+
+ return xml_attribute();
+ }
+
+ // Find child node using predicate. Returns first child for which predicate returned true.
+ template <typename Predicate> xml_node find_child(Predicate pred) const
+ {
+ if (!_root) return xml_node();
+
+ for (xml_node node = first_child(); node; node = node.next_sibling())
+ if (pred(node))
+ return node;
+
+ return xml_node();
+ }
+
+ // Find node from subtree using predicate. Returns first node from subtree (depth-first), for which predicate returned true.
+ template <typename Predicate> xml_node find_node(Predicate pred) const
+ {
+ if (!_root) return xml_node();
+
+ xml_node cur = first_child();
+
+ while (cur._root && cur._root != _root)
+ {
+ if (pred(cur)) return cur;
+
+ if (cur.first_child()) cur = cur.first_child();
+ else if (cur.next_sibling()) cur = cur.next_sibling();
+ else
+ {
+ while (!cur.next_sibling() && cur._root != _root) cur = cur.parent();
+
+ if (cur._root != _root) cur = cur.next_sibling();
+ }
+ }
+
+ return xml_node();
+ }
+
+ // Find child node by attribute name/value
+ xml_node find_child_by_attribute(const char_t* name, const char_t* attr_name, const char_t* attr_value) const;
+ xml_node find_child_by_attribute(const char_t* attr_name, const char_t* attr_value) const;
+
+ #ifndef PUGIXML_NO_STL
+ // Get the absolute node path from root as a text string.
+ string_t path(char_t delimiter = '/') const;
+ #endif
+
+ // Search for a node by path consisting of node names and . or .. elements.
+ xml_node first_element_by_path(const char_t* path, char_t delimiter = '/') const;
+
+ // Recursively traverse subtree with xml_tree_walker
+ bool traverse(xml_tree_walker& walker);
+
+ #ifndef PUGIXML_NO_XPATH
+ // Select single node by evaluating XPath query. Returns first node from the resulting node set.
+ xpath_node select_single_node(const char_t* query, xpath_variable_set* variables = 0) const;
+ xpath_node select_single_node(const xpath_query& query) const;
+
+ // Select node set by evaluating XPath query
+ xpath_node_set select_nodes(const char_t* query, xpath_variable_set* variables = 0) const;
+ xpath_node_set select_nodes(const xpath_query& query) const;
+ #endif
+
+ // Print subtree using a writer object
+ void print(xml_writer& writer, const char_t* indent = PUGIXML_TEXT("\t"), unsigned int flags = format_default, xml_encoding encoding = encoding_auto, unsigned int depth = 0) const;
+
+ #ifndef PUGIXML_NO_STL
+ // Print subtree to stream
+ void print(std::basic_ostream<char, std::char_traits<char> >& os, const char_t* indent = PUGIXML_TEXT("\t"), unsigned int flags = format_default, xml_encoding encoding = encoding_auto, unsigned int depth = 0) const;
+ void print(std::basic_ostream<wchar_t, std::char_traits<wchar_t> >& os, const char_t* indent = PUGIXML_TEXT("\t"), unsigned int flags = format_default, unsigned int depth = 0) const;
+ #endif
+
+ // Child nodes iterators
+ typedef xml_node_iterator iterator;
+
+ iterator begin() const;
+ iterator end() const;
+
+ // Attribute iterators
+ typedef xml_attribute_iterator attribute_iterator;
+
+ attribute_iterator attributes_begin() const;
+ attribute_iterator attributes_end() const;
+
+ // Range-based for support
+ xml_object_range<xml_node_iterator> children() const;
+ xml_object_range<xml_named_node_iterator> children(const char_t* name) const;
+ xml_object_range<xml_attribute_iterator> attributes() const;
+
+ // Get node offset in parsed file/string (in char_t units) for debugging purposes
+ ptrdiff_t offset_debug() const;
+
+ // Get hash value (unique for handles to the same object)
+ size_t hash_value() const;
+
+ // Get internal pointer
+ xml_node_struct* internal_object() const;
+ };
+
+#ifdef __BORLANDC__
+ // Borland C++ workaround
+ bool PUGIXML_FUNCTION operator&&(const xml_node& lhs, bool rhs);
+ bool PUGIXML_FUNCTION operator||(const xml_node& lhs, bool rhs);
+#endif
+
+ // A helper for working with text inside PCDATA nodes
+ class PUGIXML_CLASS xml_text
+ {
+ friend class xml_node;
+
+ xml_node_struct* _root;
+
+ typedef void (*unspecified_bool_type)(xml_text***);
+
+ explicit xml_text(xml_node_struct* root);
+
+ xml_node_struct* _data_new();
+ xml_node_struct* _data() const;
+
+ public:
+ // Default constructor. Constructs an empty object.
+ xml_text();
+
+ // Safe bool conversion operator
+ operator unspecified_bool_type() const;
+
+ // Borland C++ workaround
+ bool operator!() const;
+
+ // Check if text object is empty
+ bool empty() const;
+
+ // Get text, or "" if object is empty
+ const char_t* get() const;
+
+ // Get text, or the default value if object is empty
+ const char_t* as_string(const char_t* def = PUGIXML_TEXT("")) const;
+
+ // Get text as a number, or the default value if conversion did not succeed or object is empty
+ int as_int(int def = 0) const;
+ unsigned int as_uint(unsigned int def = 0) const;
+ double as_double(double def = 0) const;
+ float as_float(float def = 0) const;
+
+ // Get text as bool (returns true if first character is in '1tTyY' set), or the default value if object is empty
+ bool as_bool(bool def = false) const;
+
+ // Set text (returns false if object is empty or there is not enough memory)
+ bool set(const char_t* rhs);
+
+ // Set text with type conversion (numbers are converted to strings, boolean is converted to "true"/"false")
+ bool set(int rhs);
+ bool set(unsigned int rhs);
+ bool set(double rhs);
+ bool set(bool rhs);
+
+ // Set text (equivalent to set without error checking)
+ xml_text& operator=(const char_t* rhs);
+ xml_text& operator=(int rhs);
+ xml_text& operator=(unsigned int rhs);
+ xml_text& operator=(double rhs);
+ xml_text& operator=(bool rhs);
+
+ // Get the data node (node_pcdata or node_cdata) for this object
+ xml_node data() const;
+ };
+
+#ifdef __BORLANDC__
+ // Borland C++ workaround
+ bool PUGIXML_FUNCTION operator&&(const xml_text& lhs, bool rhs);
+ bool PUGIXML_FUNCTION operator||(const xml_text& lhs, bool rhs);
+#endif
+
+ // Child node iterator (a bidirectional iterator over a collection of xml_node)
+ class PUGIXML_CLASS xml_node_iterator
+ {
+ friend class xml_node;
+
+ private:
+ mutable xml_node _wrap;
+ xml_node _parent;
+
+ xml_node_iterator(xml_node_struct* ref, xml_node_struct* parent);
+
+ public:
+ // Iterator traits
+ typedef ptrdiff_t difference_type;
+ typedef xml_node value_type;
+ typedef xml_node* pointer;
+ typedef xml_node& reference;
+
+ #ifndef PUGIXML_NO_STL
+ typedef std::bidirectional_iterator_tag iterator_category;
+ #endif
+
+ // Default constructor
+ xml_node_iterator();
+
+ // Construct an iterator which points to the specified node
+ xml_node_iterator(const xml_node& node);
+
+ // Iterator operators
+ bool operator==(const xml_node_iterator& rhs) const;
+ bool operator!=(const xml_node_iterator& rhs) const;
+
+ xml_node& operator*() const;
+ xml_node* operator->() const;
+
+ const xml_node_iterator& operator++();
+ xml_node_iterator operator++(int);
+
+ const xml_node_iterator& operator--();
+ xml_node_iterator operator--(int);
+ };
+
+ // Attribute iterator (a bidirectional iterator over a collection of xml_attribute)
+ class PUGIXML_CLASS xml_attribute_iterator
+ {
+ friend class xml_node;
+
+ private:
+ mutable xml_attribute _wrap;
+ xml_node _parent;
+
+ xml_attribute_iterator(xml_attribute_struct* ref, xml_node_struct* parent);
+
+ public:
+ // Iterator traits
+ typedef ptrdiff_t difference_type;
+ typedef xml_attribute value_type;
+ typedef xml_attribute* pointer;
+ typedef xml_attribute& reference;
+
+ #ifndef PUGIXML_NO_STL
+ typedef std::bidirectional_iterator_tag iterator_category;
+ #endif
+
+ // Default constructor
+ xml_attribute_iterator();
+
+ // Construct an iterator which points to the specified attribute
+ xml_attribute_iterator(const xml_attribute& attr, const xml_node& parent);
+
+ // Iterator operators
+ bool operator==(const xml_attribute_iterator& rhs) const;
+ bool operator!=(const xml_attribute_iterator& rhs) const;
+
+ xml_attribute& operator*() const;
+ xml_attribute* operator->() const;
+
+ const xml_attribute_iterator& operator++();
+ xml_attribute_iterator operator++(int);
+
+ const xml_attribute_iterator& operator--();
+ xml_attribute_iterator operator--(int);
+ };
+
+ // Named node range helper
+ class xml_named_node_iterator
+ {
+ public:
+ // Iterator traits
+ typedef ptrdiff_t difference_type;
+ typedef xml_node value_type;
+ typedef xml_node* pointer;
+ typedef xml_node& reference;
+
+ #ifndef PUGIXML_NO_STL
+ typedef std::forward_iterator_tag iterator_category;
+ #endif
+
+ // Default constructor
+ xml_named_node_iterator();
+
+ // Construct an iterator which points to the specified node
+ xml_named_node_iterator(const xml_node& node, const char_t* name);
+
+ // Iterator operators
+ bool operator==(const xml_named_node_iterator& rhs) const;
+ bool operator!=(const xml_named_node_iterator& rhs) const;
+
+ xml_node& operator*() const;
+ xml_node* operator->() const;
+
+ const xml_named_node_iterator& operator++();
+ xml_named_node_iterator operator++(int);
+
+ private:
+ mutable xml_node _node;
+ const char_t* _name;
+ };
+
+ // Abstract tree walker class (see xml_node::traverse)
+ class PUGIXML_CLASS xml_tree_walker
+ {
+ friend class xml_node;
+
+ private:
+ int _depth;
+
+ protected:
+ // Get current traversal depth
+ int depth() const;
+
+ public:
+ xml_tree_walker();
+ virtual ~xml_tree_walker();
+
+ // Callback that is called when traversal begins
+ virtual bool begin(xml_node& node);
+
+ // Callback that is called for each node traversed
+ virtual bool for_each(xml_node& node) = 0;
+
+ // Callback that is called when traversal ends
+ virtual bool end(xml_node& node);
+ };
+
+ // Parsing status, returned as part of xml_parse_result object
+ enum xml_parse_status
+ {
+ status_ok = 0, // No error
+
+ status_file_not_found, // File was not found during load_file()
+ status_io_error, // Error reading from file/stream
+ status_out_of_memory, // Could not allocate memory
+ status_internal_error, // Internal error occurred
+
+ status_unrecognized_tag, // Parser could not determine tag type
+
+ status_bad_pi, // Parsing error occurred while parsing document declaration/processing instruction
+ status_bad_comment, // Parsing error occurred while parsing comment
+ status_bad_cdata, // Parsing error occurred while parsing CDATA section
+ status_bad_doctype, // Parsing error occurred while parsing document type declaration
+ status_bad_pcdata, // Parsing error occurred while parsing PCDATA section
+ status_bad_start_element, // Parsing error occurred while parsing start element tag
+ status_bad_attribute, // Parsing error occurred while parsing element attribute
+ status_bad_end_element, // Parsing error occurred while parsing end element tag
+ status_end_element_mismatch // There was a mismatch of start-end tags (closing tag had incorrect name, some tag was not closed or there was an excessive closing tag)
+ };
+
+ // Parsing result
+ struct PUGIXML_CLASS xml_parse_result
+ {
+ // Parsing status (see xml_parse_status)
+ xml_parse_status status;
+
+ // Last parsed offset (in char_t units from start of input data)
+ ptrdiff_t offset;
+
+ // Source document encoding
+ xml_encoding encoding;
+
+ // Default constructor, initializes object to failed state
+ xml_parse_result();
+
+ // Cast to bool operator
+ operator bool() const;
+
+ // Get error description
+ const char* description() const;
+ };
+
+ // Document class (DOM tree root)
+ class PUGIXML_CLASS xml_document: public xml_node
+ {
+ private:
+ char_t* _buffer;
+
+ char _memory[192];
+
+ // Non-copyable semantics
+ xml_document(const xml_document&);
+ const xml_document& operator=(const xml_document&);
+
+ void create();
+ void destroy();
+
+ xml_parse_result load_buffer_impl(void* contents, size_t size, unsigned int options, xml_encoding encoding, bool is_mutable, bool own);
+
+ public:
+ // Default constructor, makes empty document
+ xml_document();
+
+ // Destructor, invalidates all node/attribute handles to this document
+ ~xml_document();
+
+ // Removes all nodes, leaving the empty document
+ void reset();
+
+ // Removes all nodes, then copies the entire contents of the specified document
+ void reset(const xml_document& proto);
+
+ #ifndef PUGIXML_NO_STL
+ // Load document from stream.
+ xml_parse_result load(std::basic_istream<char, std::char_traits<char> >& stream, unsigned int options = parse_default, xml_encoding encoding = encoding_auto);
+ xml_parse_result load(std::basic_istream<wchar_t, std::char_traits<wchar_t> >& stream, unsigned int options = parse_default);
+ #endif
+
+ // Load document from zero-terminated string. No encoding conversions are applied.
+ xml_parse_result load(const char_t* contents, unsigned int options = parse_default);
+
+ // Load document from file
+ xml_parse_result load_file(const char* path, unsigned int options = parse_default, xml_encoding encoding = encoding_auto);
+ xml_parse_result load_file(const wchar_t* path, unsigned int options = parse_default, xml_encoding encoding = encoding_auto);
+
+ // Load document from buffer. Copies/converts the buffer, so it may be deleted or changed after the function returns.
+ xml_parse_result load_buffer(const void* contents, size_t size, unsigned int options = parse_default, xml_encoding encoding = encoding_auto);
+
+ // Load document from buffer, using the buffer for in-place parsing (the buffer is modified and used for storage of document data).
+ // You should ensure that buffer data will persist throughout the document's lifetime, and free the buffer memory manually once document is destroyed.
+ xml_parse_result load_buffer_inplace(void* contents, size_t size, unsigned int options = parse_default, xml_encoding encoding = encoding_auto);
+
+ // Load document from buffer, using the buffer for in-place parsing (the buffer is modified and used for storage of document data).
+ // You should allocate the buffer with pugixml allocation function; document will free the buffer when it is no longer needed (you can't use it anymore).
+ xml_parse_result load_buffer_inplace_own(void* contents, size_t size, unsigned int options = parse_default, xml_encoding encoding = encoding_auto);
+
+ // Save XML document to writer (semantics is slightly different from xml_node::print, see documentation for details).
+ void save(xml_writer& writer, const char_t* indent = PUGIXML_TEXT("\t"), unsigned int flags = format_default, xml_encoding encoding = encoding_auto) const;
+
+ #ifndef PUGIXML_NO_STL
+ // Save XML document to stream (semantics is slightly different from xml_node::print, see documentation for details).
+ void save(std::basic_ostream<char, std::char_traits<char> >& stream, const char_t* indent = PUGIXML_TEXT("\t"), unsigned int flags = format_default, xml_encoding encoding = encoding_auto) const;
+ void save(std::basic_ostream<wchar_t, std::char_traits<wchar_t> >& stream, const char_t* indent = PUGIXML_TEXT("\t"), unsigned int flags = format_default) const;
+ #endif
+
+ // Save XML to file
+ bool save_file(const char* path, const char_t* indent = PUGIXML_TEXT("\t"), unsigned int flags = format_default, xml_encoding encoding = encoding_auto) const;
+ bool save_file(const wchar_t* path, const char_t* indent = PUGIXML_TEXT("\t"), unsigned int flags = format_default, xml_encoding encoding = encoding_auto) const;
+
+ // Get document element
+ xml_node document_element() const;
+ };
+
+#ifndef PUGIXML_NO_XPATH
+ // XPath query return type
+ enum xpath_value_type
+ {
+ xpath_type_none, // Unknown type (query failed to compile)
+ xpath_type_node_set, // Node set (xpath_node_set)
+ xpath_type_number, // Number
+ xpath_type_string, // String
+ xpath_type_boolean // Boolean
+ };
+
+ // XPath parsing result
+ struct PUGIXML_CLASS xpath_parse_result
+ {
+ // Error message (0 if no error)
+ const char* error;
+
+ // Last parsed offset (in char_t units from string start)
+ ptrdiff_t offset;
+
+ // Default constructor, initializes object to failed state
+ xpath_parse_result();
+
+ // Cast to bool operator
+ operator bool() const;
+
+ // Get error description
+ const char* description() const;
+ };
+
+ // A single XPath variable
+ class PUGIXML_CLASS xpath_variable
+ {
+ friend class xpath_variable_set;
+
+ protected:
+ xpath_value_type _type;
+ xpath_variable* _next;
+
+ xpath_variable();
+
+ // Non-copyable semantics
+ xpath_variable(const xpath_variable&);
+ xpath_variable& operator=(const xpath_variable&);
+
+ public:
+ // Get variable name
+ const char_t* name() const;
+
+ // Get variable type
+ xpath_value_type type() const;
+
+ // Get variable value; no type conversion is performed, default value (false, NaN, empty string, empty node set) is returned on type mismatch error
+ bool get_boolean() const;
+ double get_number() const;
+ const char_t* get_string() const;
+ const xpath_node_set& get_node_set() const;
+
+ // Set variable value; no type conversion is performed, false is returned on type mismatch error
+ bool set(bool value);
+ bool set(double value);
+ bool set(const char_t* value);
+ bool set(const xpath_node_set& value);
+ };
+
+ // A set of XPath variables
+ class PUGIXML_CLASS xpath_variable_set
+ {
+ private:
+ xpath_variable* _data[64];
+
+ // Non-copyable semantics
+ xpath_variable_set(const xpath_variable_set&);
+ xpath_variable_set& operator=(const xpath_variable_set&);
+
+ xpath_variable* find(const char_t* name) const;
+
+ public:
+ // Default constructor/destructor
+ xpath_variable_set();
+ ~xpath_variable_set();
+
+ // Add a new variable or get the existing one, if the types match
+ xpath_variable* add(const char_t* name, xpath_value_type type);
+
+ // Set value of an existing variable; no type conversion is performed, false is returned if there is no such variable or if types mismatch
+ bool set(const char_t* name, bool value);
+ bool set(const char_t* name, double value);
+ bool set(const char_t* name, const char_t* value);
+ bool set(const char_t* name, const xpath_node_set& value);
+
+ // Get existing variable by name
+ xpath_variable* get(const char_t* name);
+ const xpath_variable* get(const char_t* name) const;
+ };
+
+ // A compiled XPath query object
+ class PUGIXML_CLASS xpath_query
+ {
+ private:
+ void* _impl;
+ xpath_parse_result _result;
+
+ typedef void (*unspecified_bool_type)(xpath_query***);
+
+ // Non-copyable semantics
+ xpath_query(const xpath_query&);
+ xpath_query& operator=(const xpath_query&);
+
+ public:
+ // Construct a compiled object from XPath expression.
+ // If PUGIXML_NO_EXCEPTIONS is not defined, throws xpath_exception on compilation errors.
+ explicit xpath_query(const char_t* query, xpath_variable_set* variables = 0);
+
+ // Destructor
+ ~xpath_query();
+
+ // Get query expression return type
+ xpath_value_type return_type() const;
+
+ // Evaluate expression as boolean value in the specified context; performs type conversion if necessary.
+ // If PUGIXML_NO_EXCEPTIONS is not defined, throws std::bad_alloc on out of memory errors.
+ bool evaluate_boolean(const xpath_node& n) const;
+
+ // Evaluate expression as double value in the specified context; performs type conversion if necessary.
+ // If PUGIXML_NO_EXCEPTIONS is not defined, throws std::bad_alloc on out of memory errors.
+ double evaluate_number(const xpath_node& n) const;
+
+ #ifndef PUGIXML_NO_STL
+ // Evaluate expression as string value in the specified context; performs type conversion if necessary.
+ // If PUGIXML_NO_EXCEPTIONS is not defined, throws std::bad_alloc on out of memory errors.
+ string_t evaluate_string(const xpath_node& n) const;
+ #endif
+
+ // Evaluate expression as string value in the specified context; performs type conversion if necessary.
+ // At most capacity characters are written to the destination buffer, full result size is returned (includes terminating zero).
+ // If PUGIXML_NO_EXCEPTIONS is not defined, throws std::bad_alloc on out of memory errors.
+ // If PUGIXML_NO_EXCEPTIONS is defined, returns empty set instead.
+ size_t evaluate_string(char_t* buffer, size_t capacity, const xpath_node& n) const;
+
+ // Evaluate expression as node set in the specified context.
+ // If PUGIXML_NO_EXCEPTIONS is not defined, throws xpath_exception on type mismatch and std::bad_alloc on out of memory errors.
+ // If PUGIXML_NO_EXCEPTIONS is defined, returns empty node set instead.
+ xpath_node_set evaluate_node_set(const xpath_node& n) const;
+
+ // Get parsing result (used to get compilation errors in PUGIXML_NO_EXCEPTIONS mode)
+ const xpath_parse_result& result() const;
+
+ // Safe bool conversion operator
+ operator unspecified_bool_type() const;
+
+ // Borland C++ workaround
+ bool operator!() const;
+ };
+
+ #ifndef PUGIXML_NO_EXCEPTIONS
+ // XPath exception class
+ class PUGIXML_CLASS xpath_exception: public std::exception
+ {
+ private:
+ xpath_parse_result _result;
+
+ public:
+ // Construct exception from parse result
+ explicit xpath_exception(const xpath_parse_result& result);
+
+ // Get error message
+ virtual const char* what() const throw();
+
+ // Get parse result
+ const xpath_parse_result& result() const;
+ };
+ #endif
+
+ // XPath node class (either xml_node or xml_attribute)
+ class PUGIXML_CLASS xpath_node
+ {
+ private:
+ xml_node _node;
+ xml_attribute _attribute;
+
+ typedef void (*unspecified_bool_type)(xpath_node***);
+
+ public:
+ // Default constructor; constructs empty XPath node
+ xpath_node();
+
+ // Construct XPath node from XML node/attribute
+ xpath_node(const xml_node& node);
+ xpath_node(const xml_attribute& attribute, const xml_node& parent);
+
+ // Get node/attribute, if any
+ xml_node node() const;
+ xml_attribute attribute() const;
+
+ // Get parent of contained node/attribute
+ xml_node parent() const;
+
+ // Safe bool conversion operator
+ operator unspecified_bool_type() const;
+
+ // Borland C++ workaround
+ bool operator!() const;
+
+ // Comparison operators
+ bool operator==(const xpath_node& n) const;
+ bool operator!=(const xpath_node& n) const;
+ };
+
+#ifdef __BORLANDC__
+ // Borland C++ workaround
+ bool PUGIXML_FUNCTION operator&&(const xpath_node& lhs, bool rhs);
+ bool PUGIXML_FUNCTION operator||(const xpath_node& lhs, bool rhs);
+#endif
+
+ // A fixed-size collection of XPath nodes
+ class PUGIXML_CLASS xpath_node_set
+ {
+ public:
+ // Collection type
+ enum type_t
+ {
+ type_unsorted, // Not ordered
+ type_sorted, // Sorted by document order (ascending)
+ type_sorted_reverse // Sorted by document order (descending)
+ };
+
+ // Constant iterator type
+ typedef const xpath_node* const_iterator;
+
+ // Default constructor. Constructs empty set.
+ xpath_node_set();
+
+ // Constructs a set from iterator range; data is not checked for duplicates and is not sorted according to provided type, so be careful
+ xpath_node_set(const_iterator begin, const_iterator end, type_t type = type_unsorted);
+
+ // Destructor
+ ~xpath_node_set();
+
+ // Copy constructor/assignment operator
+ xpath_node_set(const xpath_node_set& ns);
+ xpath_node_set& operator=(const xpath_node_set& ns);
+
+ // Get collection type
+ type_t type() const;
+
+ // Get collection size
+ size_t size() const;
+
+ // Indexing operator
+ const xpath_node& operator[](size_t index) const;
+
+ // Collection iterators
+ const_iterator begin() const;
+ const_iterator end() const;
+
+ // Sort the collection in ascending/descending order by document order
+ void sort(bool reverse = false);
+
+ // Get first node in the collection by document order
+ xpath_node first() const;
+
+ // Check if collection is empty
+ bool empty() const;
+
+ private:
+ type_t _type;
+
+ xpath_node _storage;
+
+ xpath_node* _begin;
+ xpath_node* _end;
+
+ void _assign(const_iterator begin, const_iterator end);
+ };
+#endif
+
+#ifndef PUGIXML_NO_STL
+ // Convert wide string to UTF8
+ std::basic_string<char, std::char_traits<char>, std::allocator<char> > PUGIXML_FUNCTION as_utf8(const wchar_t* str);
+ std::basic_string<char, std::char_traits<char>, std::allocator<char> > PUGIXML_FUNCTION as_utf8(const std::basic_string<wchar_t, std::char_traits<wchar_t>, std::allocator<wchar_t> >& str);
+
+ // Convert UTF8 to wide string
+ std::basic_string<wchar_t, std::char_traits<wchar_t>, std::allocator<wchar_t> > PUGIXML_FUNCTION as_wide(const char* str);
+ std::basic_string<wchar_t, std::char_traits<wchar_t>, std::allocator<wchar_t> > PUGIXML_FUNCTION as_wide(const std::basic_string<char, std::char_traits<char>, std::allocator<char> >& str);
+#endif
+
+ // Memory allocation function interface; returns pointer to allocated memory or NULL on failure
+ typedef void* (*allocation_function)(size_t size);
+
+ // Memory deallocation function interface
+ typedef void (*deallocation_function)(void* ptr);
+
+ // Override default memory management functions. All subsequent allocations/deallocations will be performed via supplied functions.
+ void PUGIXML_FUNCTION set_memory_management_functions(allocation_function allocate, deallocation_function deallocate);
+
+ // Get current memory management functions
+ allocation_function PUGIXML_FUNCTION get_memory_allocation_function();
+ deallocation_function PUGIXML_FUNCTION get_memory_deallocation_function();
+}
+
+#if !defined(PUGIXML_NO_STL) && (defined(_MSC_VER) || defined(__ICC))
+namespace std
+{
+ // Workarounds for (non-standard) iterator category detection for older versions (MSVC7/IC8 and earlier)
+ std::bidirectional_iterator_tag PUGIXML_FUNCTION _Iter_cat(const pugi::xml_node_iterator&);
+ std::bidirectional_iterator_tag PUGIXML_FUNCTION _Iter_cat(const pugi::xml_attribute_iterator&);
+ std::forward_iterator_tag PUGIXML_FUNCTION _Iter_cat(const pugi::xml_named_node_iterator&);
+}
+#endif
+
+#if !defined(PUGIXML_NO_STL) && defined(__SUNPRO_CC)
+namespace std
+{
+ // Workarounds for (non-standard) iterator category detection
+ std::bidirectional_iterator_tag PUGIXML_FUNCTION __iterator_category(const pugi::xml_node_iterator&);
+ std::bidirectional_iterator_tag PUGIXML_FUNCTION __iterator_category(const pugi::xml_attribute_iterator&);
+ std::forward_iterator_tag PUGIXML_FUNCTION __iterator_category(const pugi::xml_named_node_iterator&);
+}
+#endif
+
+#endif
+
+/**
+ * Copyright (c) 2006-2012 Arseny Kapoulkine
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */