diff options
author | Jürgen Gehring <juergen.gehring@bmw.de> | 2015-06-11 06:57:47 -0700 |
---|---|---|
committer | Jürgen Gehring <juergen.gehring@bmw.de> | 2015-06-11 06:57:47 -0700 |
commit | 6c463fcc3dcee619925f08ea09e19a86b9e581cc (patch) | |
tree | 17e765e0623c58778150605d1cd0340c658ce6ab /include | |
parent | 1d83eb38e546e0165f1ad6821f04445b2b9b19d2 (diff) | |
download | genivi-common-api-runtime-6c463fcc3dcee619925f08ea09e19a86b9e581cc.tar.gz |
CommonAPI 3.1.1
Diffstat (limited to 'include')
31 files changed, 3539 insertions, 0 deletions
diff --git a/include/CommonAPI/Address.hpp b/include/CommonAPI/Address.hpp new file mode 100644 index 0000000..0826a8f --- /dev/null +++ b/include/CommonAPI/Address.hpp @@ -0,0 +1,52 @@ +// 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/. + +#ifndef COMMONAPI_ADDRESS_HPP_ +#define COMMONAPI_ADDRESS_HPP_ + +#include <iostream> +#include <string> + +#include <CommonAPI/Export.hpp> + +namespace CommonAPI { + +class Address { +public: + COMMONAPI_EXPORT Address() = default; + COMMONAPI_EXPORT Address(const std::string &_address); + COMMONAPI_EXPORT Address(const std::string &_domain, + const std::string &_interface, + const std::string &_instance); + COMMONAPI_EXPORT Address(const Address &_source); + COMMONAPI_EXPORT virtual ~Address(); + + COMMONAPI_EXPORT bool operator==(const Address &_other) const; + COMMONAPI_EXPORT bool operator!=(const Address &_other) const; + COMMONAPI_EXPORT bool operator<(const Address &_other) const; + + COMMONAPI_EXPORT std::string getAddress() const; + COMMONAPI_EXPORT void setAddress(const std::string &_address); + + COMMONAPI_EXPORT const std::string &getDomain() const; + COMMONAPI_EXPORT void setDomain(const std::string &_domain); + + COMMONAPI_EXPORT const std::string &getInterface() const; + COMMONAPI_EXPORT void setInterface(const std::string &_interface); + + COMMONAPI_EXPORT const std::string &getInstance() const; + COMMONAPI_EXPORT void setInstance(const std::string &_instance); + +private: + std::string domain_; + std::string interface_; + std::string instance_; + + friend COMMONAPI_EXPORT std::ostream &operator<<(std::ostream &_out, const Address &_address); +}; + +} // namespace CommonAPI + +#endif // COMMONAPI_ADDRESS_HPP_ diff --git a/include/CommonAPI/Attribute.hpp b/include/CommonAPI/Attribute.hpp new file mode 100644 index 0000000..200d3bb --- /dev/null +++ b/include/CommonAPI/Attribute.hpp @@ -0,0 +1,143 @@ +// 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.h> can be included directly, this file may disappear or change contents." +#endif + +#ifndef COMMONAPI_ATTRIBUTE_HPP_ +#define COMMONAPI_ATTRIBUTE_HPP_ + +#include <cstdint> +#include <functional> +#include <future> +#include <memory> + +#include <CommonAPI/CallInfo.hpp> +#include <CommonAPI/Event.hpp> +#include <CommonAPI/Types.hpp> + +namespace CommonAPI { + +/** + * \brief Class representing a read only attribute + * + * Class representing a read only attribute + */ +template <typename _ValueType> +class ReadonlyAttribute { + public: + typedef _ValueType ValueType; + + typedef std::function<void(const CallStatus &, _ValueType)> AttributeAsyncCallback; + + virtual ~ReadonlyAttribute() { } + + /** + * \brief Get value of attribute, usually from remote. Synchronous call. + * + * Get value of attribute, usually from remote. Synchronous call. + * + * @param value Reference to be filled with value. + * @param callStatus call status reference will be filled with status of the operation + */ + virtual void getValue(CallStatus &_status, + _ValueType &_value, + const CallInfo *_info = nullptr) const = 0; + + /** + * \brief Get value of attribute, usually from remote. Asynchronous call. + * + * Get value of attribute, usually from remote. Asynchronous call. + * + * @param attributeAsyncCallback std::function object for the callback to be invoked. + * @return std::future containing the call status of the operation. + */ + virtual std::future<CallStatus> getValueAsync(AttributeAsyncCallback attributeAsyncCallback, + const CallInfo *_info = nullptr) = 0; +}; + +/** + * \brief Class representing a read and writable attribute + * + * Class representing a read and writable attribute + */ +template <typename _ValueType> +class Attribute: public ReadonlyAttribute<_ValueType> { + public: + typedef typename ReadonlyAttribute<_ValueType>::ValueType ValueType; + typedef typename ReadonlyAttribute<_ValueType>::AttributeAsyncCallback AttributeAsyncCallback; + + virtual ~Attribute() { } + + /** + * \brief Set value of attribute, usually to remote. Synchronous call. + * + * Set value of attribute, usually to remote. Synchronous call. + * + * @param requestValue Value to be set + * @param callStatus call status reference will be filled with status of the operation + * @param responseValue Reference which will contain the actuall value set by the remote. + */ + virtual void setValue(const _ValueType& requestValue, + CallStatus& callStatus, + _ValueType& responseValue, + const CallInfo *_info = nullptr) = 0; + + /** + * \brief Set value of attribute, usually to remote. Asynchronous call. + * + * Set value of attribute, usually to remote. Asynchronous call. + * + * @param requestValue Value to be set + * @param attributeAsyncCallback std::function object for the callback to be invoked. + * @return std::future containing the call status of the operation. + */ + virtual std::future<CallStatus> setValueAsync(const _ValueType& requestValue, + AttributeAsyncCallback attributeAsyncCallback, + const CallInfo *_info = nullptr) = 0; +}; + +/** + * \brief Class representing an observable attribute + * + * Class representing an observable attribute + */ +template <typename _AttributeBaseClass> +class _ObservableAttributeImpl: public _AttributeBaseClass { + public: + typedef typename _AttributeBaseClass::ValueType ValueType; + typedef typename _AttributeBaseClass::AttributeAsyncCallback AttributeAsyncCallback; + typedef Event<ValueType> ChangedEvent; + + virtual ~_ObservableAttributeImpl() { } + + /** + * \brief Returns the event handler for the remote change notification event + * + * Returns the event handler for the remote change notification event + * + * @return The event handler object + */ + virtual ChangedEvent& getChangedEvent() = 0; +}; + +template <typename _ValueType> +struct ObservableReadonlyAttribute: _ObservableAttributeImpl< ReadonlyAttribute<_ValueType> > { +}; + +template <typename _ValueType> +struct ObservableAttribute: _ObservableAttributeImpl< Attribute<_ValueType> > { +}; + +#ifdef WIN32 +struct WINDummyAttribute { + WINDummyAttribute() {} +}; +#endif + +} // namespace CommonAPI + +#endif // COMMONAPI_ATTRIBUTE_HPP_ diff --git a/include/CommonAPI/AttributeExtension.hpp b/include/CommonAPI/AttributeExtension.hpp new file mode 100644 index 0000000..5135924 --- /dev/null +++ b/include/CommonAPI/AttributeExtension.hpp @@ -0,0 +1,54 @@ +// 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.h> can be included directly, this file may disappear or change contents." +#endif + +#ifndef COMMON_API_DBUS_ATTRIBUTE_EXTENSION_HPP_ +#define COMMON_API_DBUS_ATTRIBUTE_EXTENSION_HPP_ + +#include <cstdint> +#include <functional> +#include <memory> + +#include <CommonAPI/Event.hpp> +#include <CommonAPI/Types.hpp> + +#ifdef WIN32 +#include "Attribute.hpp" +#endif + +namespace CommonAPI { + +template<typename _AttributeType> +class AttributeExtension { + public: + _AttributeType& getBaseAttribute() { + return baseAttribute_; + } + + protected: + AttributeExtension() = delete; + AttributeExtension(_AttributeType& baseAttribute): baseAttribute_(baseAttribute) { + } + + _AttributeType& baseAttribute_; +}; + +#ifdef WIN32 +template<typename _AttributeType> +class WINDummyAttributeExtension : public CommonAPI::AttributeExtension<_AttributeType> { + typedef AttributeExtension<_AttributeType> __baseClass_t; + WINDummyAttribute dummyAttribute; +public: + WINDummyAttributeExtension() {}; + ~WINDummyAttributeExtension() {} +}; +#endif + +} // namespace CommonAPI + +#endif // COMMON_API_DBUS_ATTRIBUTE_EXTENSION_HPP_ diff --git a/include/CommonAPI/ByteBuffer.hpp b/include/CommonAPI/ByteBuffer.hpp new file mode 100644 index 0000000..5d3ad39 --- /dev/null +++ b/include/CommonAPI/ByteBuffer.hpp @@ -0,0 +1,18 @@ +// 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_BYTE_BUFFER_HPP_ +#define COMMONAPI_BYTE_BUFFER_HPP_ + +#include <vector> +#include <cstdint> + +namespace CommonAPI { + +typedef std::vector<uint8_t> ByteBuffer; + +} // namespace CommonAPI + +#endif // COMMONAPI_BYTE_BUFFER_HPP_ diff --git a/include/CommonAPI/CallInfo.hpp b/include/CommonAPI/CallInfo.hpp new file mode 100644 index 0000000..a6f43bd --- /dev/null +++ b/include/CommonAPI/CallInfo.hpp @@ -0,0 +1,31 @@ +// 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/. + +#ifndef COMMONAPI_CALLINFO_HPP_ +#define COMMONAPI_CALLINFO_HPP_ + +#include <CommonAPI/Config.hpp> +#include <CommonAPI/Types.hpp> + +namespace CommonAPI { + +struct COMMONAPI_EXPORT CallInfo { + CallInfo() + : timeout_(DEFAULT_SEND_TIMEOUT_MS), sender_(0) { + } + CallInfo(Timeout_t _timeout) + : timeout_(_timeout), sender_(0) { + } + CallInfo(Timeout_t _timeout, Sender_t _sender) + : timeout_(_timeout), sender_(_sender) { + } + + Timeout_t timeout_; + Sender_t sender_; +}; + +} // namespace CommonAPI + +#endif // COMMONAPI_ADDRESS_HPP_ diff --git a/include/CommonAPI/CommonAPI.hpp b/include/CommonAPI/CommonAPI.hpp new file mode 100644 index 0000000..5568330 --- /dev/null +++ b/include/CommonAPI/CommonAPI.hpp @@ -0,0 +1,22 @@ +// 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_HPP_ +#define COMMONAPI_HPP_ + +#ifndef COMMONAPI_INTERNAL_COMPILATION +#define COMMONAPI_INTERNAL_COMPILATION +#endif + +#include "Address.hpp" +#include "AttributeExtension.hpp" +#include "ByteBuffer.hpp" +#include "MainLoopContext.hpp" +#include "Runtime.hpp" +#include "Types.hpp" + +#undef COMMONAPI_INTERNAL_COMPILATION + +#endif // COMMONAPI_HPP_ diff --git a/include/CommonAPI/Config.hpp b/include/CommonAPI/Config.hpp new file mode 100644 index 0000000..fb99bf3 --- /dev/null +++ b/include/CommonAPI/Config.hpp @@ -0,0 +1,17 @@ +// 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/. + +#ifndef COMMONAPI_CONFIG_HPP_ +#define COMMONAPI_CONFIG_HPP_ + +#include <CommonAPI/Types.hpp> + +namespace CommonAPI { + +static const Timeout_t DEFAULT_SEND_TIMEOUT_MS = 5000; + +} // namespace CommonAPI + +#endif // COMMONAPI_CONFIG_HPP_ diff --git a/include/CommonAPI/ContainerUtils.hpp b/include/CommonAPI/ContainerUtils.hpp new file mode 100644 index 0000000..9fddc08 --- /dev/null +++ b/include/CommonAPI/ContainerUtils.hpp @@ -0,0 +1,33 @@ +// 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.h> can be included directly, this file may disappear or change contents." +#endif + +#ifndef COMMONAPI_CONTAINERUTILS_HPP_ +#define COMMONAPI_CONTAINERUTILS_HPP_ + +#include <functional> +#include <memory> + +#include <CommonAPI/Export.hpp> + +namespace CommonAPI { +class ClientId; + +struct COMMONAPI_EXPORT SharedPointerClientIdContentHash : public std::unary_function<std::shared_ptr<ClientId>, size_t> { + size_t operator()(const std::shared_ptr<ClientId>& t) const; +}; + +struct COMMONAPI_EXPORT SharedPointerClientIdContentEqual : public std::binary_function<std::shared_ptr<ClientId>, std::shared_ptr<ClientId>, bool> { + bool operator()(const std::shared_ptr<ClientId>& a, const std::shared_ptr<ClientId>& b) const; +}; + + +} // namespace std + + +#endif // COMMONAPI_CONTAINERUTILS_HPP_ diff --git a/include/CommonAPI/Deployable.hpp b/include/CommonAPI/Deployable.hpp new file mode 100644 index 0000000..7a9002c --- /dev/null +++ b/include/CommonAPI/Deployable.hpp @@ -0,0 +1,59 @@ +// 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 + +#ifndef COMMONAPI_DEPLOYABLE_HPP_ +#define COMMONAPI_DEPLOYABLE_HPP_ + +namespace CommonAPI { + +struct DeployableBase { +}; + +template<typename _Type, typename _TypeDepl> +struct Deployable : DeployableBase +{ + Deployable(const _TypeDepl *_depl = nullptr) + : depl_(const_cast<_TypeDepl *>(_depl)) { + } + + Deployable(const _Type &_value, const _TypeDepl *_depl) + : value_(_value), + depl_(const_cast<_TypeDepl *>(_depl)) { + }; + + Deployable<_Type, _TypeDepl>& operator=(const Deployable<_Type, _TypeDepl> &_source) { + value_ = _source.value_; + depl_ = _source.depl_; + return (*this); + } + + operator _Type() const { + return value_; + } + + const _Type &getValue() const { + return value_; + } + + _Type &getValue() { + return value_; + } + + const _TypeDepl *getDepl() const { + return depl_; + } + + protected: + _Type value_; + _TypeDepl *depl_; +}; + +} // namespace CommonAPI + +#endif // COMMONAPI_DEPLOYABLE_HPP_ diff --git a/include/CommonAPI/Deployment.hpp b/include/CommonAPI/Deployment.hpp new file mode 100644 index 0000000..db2a914 --- /dev/null +++ b/include/CommonAPI/Deployment.hpp @@ -0,0 +1,75 @@ +// 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_DEPLOYMENT_HPP_ +#define COMMONAPI_DEPLOYMENT_HPP_ + +#include <tuple> + +namespace CommonAPI { +// The binding-specific deployment parameters should be +// defined like this: +// +// struct BindingUInt16Deployment : CommonAPI::Deployment<> { +// // Binding-specific bool deployment parameters +// }; +// +// struct BindingStringDeployment : CommonAPI::Deployment<> { +// // Binding-specific String deployment parameters +// }; +// +// template<typename... _Types> +// struct BindingStructDeployment +// : CommonAPI::Deployment<_Types...> { +// BindingStructDeployment(<SPECIFIC PARAMETERS>, _Types... t) +// : CommonAPI::Deployment<_Types...>(t), +// <SPECIFIC INITIALIZERS> {}; +// +// // Binding-specific struct deployment parameters +// }; +// +// The generated code needs to use these definitions to +// provide the deployment informations for the actual data. +// E.g., for struct consisting of a boolean and a string +// value, it needs to generate: +// +// CommonAPI::BindingStructDeployment< +// CommonAPI::BindingBoolDeployment, +// CommonAPI::BindingStringDeployment +// > itsDeployment(<PARAMS); + +struct EmptyDeployment {}; + +template<typename _ElementDepl> +struct ArrayDeployment { + ArrayDeployment(_ElementDepl *_elementDepl) + : elementDepl_(_elementDepl) {} + + _ElementDepl *elementDepl_; +}; + +template<typename _KeyDepl, typename _ValueDepl> +struct MapDeployment { + MapDeployment(_KeyDepl *_key, _ValueDepl *_value) + : key_(_key), value_(_value) {} + + const _KeyDepl *key_; + const _ValueDepl *value_; +}; + +// The following shall be used as a base for structure/variant deployments. +template<typename... _Types> +struct Deployment { + Deployment(_Types*... _values) : values_(_values...) {} + std::tuple<_Types*...> values_; +}; + +} // namespace CommonAPI + +#endif // COMMONAPI_DEPLOYABLE_HPP_ diff --git a/include/CommonAPI/Enumeration.hpp b/include/CommonAPI/Enumeration.hpp new file mode 100644 index 0000000..1a4d5f4 --- /dev/null +++ b/include/CommonAPI/Enumeration.hpp @@ -0,0 +1,40 @@ +// 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/. + +#ifndef COMMONAPI_ENUMERATION_HPP_ +#define COMMONAPI_ENUMERATION_HPP_ + +namespace CommonAPI { + +template <typename _Base> +struct Enumeration { + Enumeration() = default; + Enumeration(const _Base &_value) + : value_(_value) { + } + + inline Enumeration &operator=(const _Base &_value) { + value_ = _value; + return (*this); + } + + inline operator const _Base() const { + return value_; + } + + inline bool operator == (const Enumeration<_Base> &_other) const { + return value_ == _other.value_; + } + + inline bool operator != (const Enumeration<_Base> &_other) const { + return value_ != _other.value_; + } + + _Base value_; +}; + +} // namespace CommonAPI + +#endif // COMMONAPI_ENUMERATION_HPP_ diff --git a/include/CommonAPI/Event.hpp b/include/CommonAPI/Event.hpp new file mode 100644 index 0000000..90971f5 --- /dev/null +++ b/include/CommonAPI/Event.hpp @@ -0,0 +1,158 @@ +// 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.h> can be included directly, this file may disappear or change contents." +#endif + +#ifndef COMMONAPI_EVENT_HPP_ +#define COMMONAPI_EVENT_HPP_ + +#include <functional> +#include <mutex> +#include <map> +#include <set> +#include <tuple> + +namespace CommonAPI { + +/** + * \brief Class representing an event + * + * Class representing an event + */ +template<typename... _Arguments> +class Event { +public: + typedef std::tuple<_Arguments...> ArgumentsTuple; + typedef std::function<void(const _Arguments&...)> Listener; + typedef uint32_t Subscription; + typedef std::set<Subscription> SubscriptionsSet; + typedef std::map<Subscription, Listener> ListenersMap; + + /** + * \brief Constructor + */ + Event() : nextSubscription_(0) {}; + + /** + * \brief Subscribe a listener to this event + * + * Subscribe a listener to this event. + * ATTENTION: You should not build new proxies or register services in callbacks + * from events. This can cause a deadlock or assert. Instead, you should set a + * trigger for your application to do this on the next iteration of your event loop + * if needed. The preferred solution is to build all proxies you need at the + * beginning and react to events appropriatly for each. + * + * @param listener A listener to be added + * @return key of the new subscription + */ + Subscription subscribe(Listener listener); + + /** + * \brief Remove a listener from this event + * + * Remove a listener from this event + * Note: Do not call this inside a listener notification callback it will deadlock! Use cancellable listeners instead. + * + * @param subscription A listener token to be removed + */ + void unsubscribe(Subscription subscription); + + virtual ~Event() {} + +protected: + void notifyListeners(const _Arguments&... eventArguments); + + virtual void onFirstListenerAdded(const Listener& listener) {} + virtual void onListenerAdded(const Listener& listener) {} + + virtual void onListenerRemoved(const Listener& listener) {} + virtual void onLastListenerRemoved(const Listener& listener) {} + +//private: + ListenersMap subscriptions_; + Subscription nextSubscription_; + + ListenersMap pendingSubscriptions_; + SubscriptionsSet pendingUnsubscriptions_; + + std::mutex notificationMutex_; + std::mutex subscriptionMutex_; +}; + +template<typename ... _Arguments> +typename Event<_Arguments...>::Subscription Event<_Arguments...>::subscribe(Listener listener) { + Subscription subscription; + bool isFirstListener; + + subscriptionMutex_.lock(); + subscription = nextSubscription_++; + // TODO?: check for key/subscription overrun + listener = pendingSubscriptions_[subscription] = std::move(listener); + isFirstListener = (0 == subscriptions_.size()); + subscriptionMutex_.unlock(); + + if (isFirstListener) + onFirstListenerAdded(listener); + onListenerAdded(listener); + + return subscription; +} + +template<typename ... _Arguments> +void Event<_Arguments...>::unsubscribe(Subscription subscription) { + bool isLastListener(false); + + subscriptionMutex_.lock(); + auto listener = subscriptions_.find(subscription); + if (subscriptions_.end() != listener + && pendingUnsubscriptions_.end() == pendingUnsubscriptions_.find(subscription)) { + if (0 == pendingSubscriptions_.erase(subscription)) { + pendingUnsubscriptions_.insert(subscription); + isLastListener = (1 == subscriptions_.size()); + } else { + isLastListener = (0 == subscriptions_.size()); + } + } + subscriptionMutex_.unlock(); + + if (subscriptions_.end() != listener) { + onListenerRemoved(listener->second); + if (isLastListener) + onLastListenerRemoved(listener->second); + } +} + +template<typename ... _Arguments> +void Event<_Arguments...>::notifyListeners(const _Arguments&... eventArguments) { + subscriptionMutex_.lock(); + notificationMutex_.lock(); + for (auto iterator = pendingUnsubscriptions_.begin(); + iterator != pendingUnsubscriptions_.end(); + iterator++) { + subscriptions_.erase(*iterator); + } + pendingUnsubscriptions_.clear(); + + for (auto iterator = pendingSubscriptions_.begin(); + iterator != pendingSubscriptions_.end(); + iterator++) { + subscriptions_.insert(*iterator); + } + pendingSubscriptions_.clear(); + + subscriptionMutex_.unlock(); + for (auto iterator = subscriptions_.begin(); iterator != subscriptions_.end(); iterator++) { + iterator->second(eventArguments...); + } + + notificationMutex_.unlock(); +} + +} // namespace CommonAPI + +#endif // COMMONAPI_EVENT_HPP_ diff --git a/include/CommonAPI/Export.hpp b/include/CommonAPI/Export.hpp new file mode 100644 index 0000000..1fe9734 --- /dev/null +++ b/include/CommonAPI/Export.hpp @@ -0,0 +1,22 @@ +// 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/. + +#ifndef COMMONAPI_EXPORT_HPP_ +#define COMMONAPI_EXPORT_HPP_ + +#ifdef WIN32 + #define COMMONAPI_EXPORT __declspec(dllexport) + + #if COMMONAPI_DLL_COMPILATION + #define COMMONAPI_IMPORT_EXPORT __declspec(dllexport) + #else + #define COMMONAPI_IMPORT_EXPORT __declspec(dllimport) + #endif +#else + #define COMMONAPI_EXPORT + #define COMMONAPI_IMPORT_EXPORT +#endif + +#endif // COMMONAPI_EXPORT_HPP_ diff --git a/include/CommonAPI/Factory.hpp b/include/CommonAPI/Factory.hpp new file mode 100644 index 0000000..df8354d --- /dev/null +++ b/include/CommonAPI/Factory.hpp @@ -0,0 +1,58 @@ +// 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_FACTORY_HPP_ +#define COMMONAPI_FACTORY_HPP_ + +#include <functional> +#include <memory> +#include <vector> + +#include <CommonAPI/Export.hpp> +#include <CommonAPI/Types.hpp> + +namespace CommonAPI { + +class MainLoopContext; +class Proxy; +class StubBase; + +class COMMONAPI_EXPORT Factory { +public: + typedef std::function<void(std::vector<std::string> &)> AvailableInstancesCbk_t; + typedef std::function<void(bool)> InstanceAliveCbk_t; + + virtual ~Factory() {}; + + virtual std::shared_ptr<Proxy> createProxy(const std::string &_domain, + const std::string &_interface, + const std::string &_instance, + const ConnectionId_t &_connectionId) = 0; + + virtual std::shared_ptr<Proxy> createProxy(const std::string &_domain, + const std::string &_interface, + const std::string &_instance, + std::shared_ptr<MainLoopContext> mainLoopContext) = 0; + + virtual bool registerStub(const std::string &_domain, + const std::string &_interface, + const std::string &_instance, + std::shared_ptr<StubBase> _stub, + const ConnectionId_t &_connectionId) = 0; + + virtual bool registerStub(const std::string &_domain, + const std::string &_interface, + const std::string &_instance, + std::shared_ptr<StubBase> _stub, + std::shared_ptr<MainLoopContext> mainLoopContext) = 0; + + virtual bool unregisterStub(const std::string &_domain, + const std::string &_interface, + const std::string &_instance) = 0; +}; + +} // namespace CommonAPI + +#endif // COMMONAPI_FACTORY_HPP_ diff --git a/include/CommonAPI/IniFileReader.hpp b/include/CommonAPI/IniFileReader.hpp new file mode 100644 index 0000000..13b64c3 --- /dev/null +++ b/include/CommonAPI/IniFileReader.hpp @@ -0,0 +1,40 @@ +// 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/. + +#ifndef COMMONAPI_INIFILEREADER_HPP_ +#define COMMONAPI_INIFILEREADER_HPP_ + +#include <map> +#include <memory> +#include <string> + +#include <CommonAPI/Export.hpp> + +namespace CommonAPI { + +class IniFileReader { +public: + class Section { + public: + COMMONAPI_EXPORT const std::map<std::string, std::string> &getMappings() const; + COMMONAPI_EXPORT std::string getValue(const std::string &_key) const; + private: + std::map<std::string, std::string> mappings_; + + friend class IniFileReader; + }; + + COMMONAPI_EXPORT bool load(const std::string &_path); + + COMMONAPI_EXPORT const std::map<std::string, std::shared_ptr<Section>> &getSections() const; + COMMONAPI_EXPORT std::shared_ptr<Section> getSection(const std::string &_name) const; + +private: + std::map<std::string, std::shared_ptr<Section>> sections_; +}; + +} // namespace CommonAPI + +#endif // COMMONAPI_INIFILEREADER_HPP_ diff --git a/include/CommonAPI/InputStream.hpp b/include/CommonAPI/InputStream.hpp new file mode 100644 index 0000000..f5cbc12 --- /dev/null +++ b/include/CommonAPI/InputStream.hpp @@ -0,0 +1,241 @@ +// 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.h> can be included directly, this file may disappear or change contents." +#endif + +#ifndef COMMONAPI_INPUT_STREAM_HPP_ +#define COMMONAPI_INPUT_STREAM_HPP_ + +#include <unordered_map> + +#include <CommonAPI/ByteBuffer.hpp> +#include <CommonAPI/Deployable.hpp> +#include <CommonAPI/Deployment.hpp> +#include <CommonAPI/Enumeration.hpp> +#include <CommonAPI/Struct.hpp> +#include <CommonAPI/Variant.hpp> +#include <CommonAPI/Version.hpp> + +namespace CommonAPI { + +template<class _Derived> +class InputStream { +public: + template<class _Deployment> + InputStream &readValue(bool &_value, const _Deployment *_depl = nullptr) { + return get()->readValue(_value, _depl); + } + + template<class _Deployment> + InputStream &readValue(int8_t &_value, const _Deployment *_depl = nullptr) { + return get()->readValue(_value, _depl); + } + + template<class _Deployment> + InputStream &readValue(int16_t &_value, const _Deployment *_depl = nullptr) { + return get()->readValue(_value, _depl); + } + + template<class _Deployment> + InputStream &readValue(int32_t &_value, const _Deployment *_depl = nullptr) { + return get()->readValue(_value, _depl); + } + + template<class _Deployment> + InputStream &readValue(int64_t &_value, const _Deployment *_depl = nullptr) { + return get()->readValue(_value, _depl); + } + + template<class _Deployment> + InputStream &readValue(uint8_t &_value, const _Deployment *_depl = nullptr) { + return get()->readValue(_value, _depl); + } + + template<class _Deployment> + InputStream &readValue(uint16_t &_value, const _Deployment *_depl = nullptr) { + return get()->readValue(_value, _depl); + } + + template<class _Deployment> + InputStream &readValue(uint32_t &_value, const _Deployment *_depl = nullptr) { + return get()->readValue(_value, _depl); + } + + template<class _Deployment> + InputStream &readValue(uint64_t &_value, const _Deployment *_depl = nullptr) { + return get()->readValue(_value, _depl); + } + + template<class _Deployment> + InputStream &readValue(float &_value, const _Deployment *_depl = nullptr) { + return get()->readValue(_value, _depl); + } + + template<class _Deployment> + InputStream &readValue(double &_value, const _Deployment *_depl = nullptr) { + return get()->readValue(_value, _depl); + } + + template<class _Deployment> + InputStream &readValue(std::string &_value, const _Deployment *_depl = nullptr) { + return get()->readValue(_value, _depl); + } + + template<class _Deployment, typename _Base> + InputStream &readValue(Enumeration<_Base> &_value, const _Deployment *_depl = nullptr) { + return get()->readValue(_value, _depl); + } + + template<class _Deployment, typename... _Types> + InputStream &readValue(Struct<_Types...> &_value, const _Deployment *_depl = nullptr) { + return get()->readValue(_value, _depl); + } + + template<class _Deployment, class _PolymorphicStruct> + InputStream &readValue(std::shared_ptr<_PolymorphicStruct> &_value, + const _Deployment *_depl = nullptr) { + return get()->readValue(_value, _depl); + } + + template<class _Deployment, typename... _Types> + InputStream &readValue(Variant<_Types...> &_value, const _Deployment *_depl = nullptr) { + return get()->readValue(_value, _depl); + } + + template<class _Deployment, typename _ElementType> + InputStream &readValue(std::vector<_ElementType> &_value, const _Deployment *_depl = nullptr) { + return get()->readValue(_value, _depl); + } + + template<class _Deployment, typename _KeyType, typename _ValueType, typename _HasherType> + InputStream &readValue(std::unordered_map<_KeyType, _ValueType, _HasherType> &_value, + const _Deployment *_depl = nullptr) { + return get()->readValue(_value, _depl); + } + + template<class _Deployment> + InputStream &readValue(Version &_value, const _Deployment *_depl = nullptr) { + return get()->readValue(_value, _depl); + } + + bool hasError() const { + return get()->hasError(); + } + +private: + inline _Derived *get() { + return static_cast<_Derived *>(this); + } + + inline const _Derived *get() const { + return static_cast<const _Derived *>(this); + } +}; + +template<class _Derived> +InputStream<_Derived> &operator>>(InputStream<_Derived> &_input, bool &_value) { + return _input.template readValue<EmptyDeployment>(_value); +} + +template<class _Derived> +InputStream<_Derived> &operator>>(InputStream<_Derived> &_input, int8_t &_value) { + return _input.template readValue<EmptyDeployment>(_value); +} + +template<class _Derived> +InputStream<_Derived> &operator>>(InputStream<_Derived> &_input, int16_t &_value) { + return _input.template readValue<EmptyDeployment>(_value); +} + +template<class _Derived> +InputStream<_Derived> &operator>>(InputStream<_Derived> &_input, int32_t &_value) { + return _input.template readValue<EmptyDeployment>(_value); +} + +template<class _Derived> +InputStream<_Derived> &operator>>(InputStream<_Derived> &_input, int64_t &_value) { + return _input.template readValue<EmptyDeployment>(_value); +} + +template<class _Derived> +InputStream<_Derived> &operator>>(InputStream<_Derived> &_input, uint8_t &_value) { + return _input.template readValue<EmptyDeployment>(_value); +} + +template<class _Derived> +InputStream<_Derived> &operator>>(InputStream<_Derived> &_input, uint16_t &_value) { + return _input.template readValue<EmptyDeployment>(_value); +} + +template<class _Derived> +InputStream<_Derived> &operator>>(InputStream<_Derived> &_input, uint32_t &_value) { + return _input.template readValue<EmptyDeployment>(_value); +} + +template<class _Derived> +InputStream<_Derived> &operator>>(InputStream<_Derived> &_input, uint64_t &_value) { + return _input.template readValue<EmptyDeployment>(_value); +} + +template<class _Derived> +InputStream<_Derived> &operator>>(InputStream<_Derived> &_input, float &_value) { + return _input.template readValue<EmptyDeployment>(_value); +} + +template<class _Derived> +InputStream<_Derived> &operator>>(InputStream<_Derived> &_input, double &_value) { + return _input.template readValue<EmptyDeployment>(_value); +} + +template<class _Derived> +InputStream<_Derived> &operator>>(InputStream<_Derived> &_input, std::string &_value) { + return _input.template readValue<EmptyDeployment>(_value); +} + +template<class _Derived> +InputStream<_Derived> &operator>>(InputStream<_Derived> &_input, Version &_value) { + return _input.template readValue<EmptyDeployment>(_value); +} + +template<class _Derived, typename _Base> +InputStream<_Derived> &operator>>(InputStream<_Derived> &_input, Enumeration<_Base> &_value) { + return _input.template readValue<EmptyDeployment>(_value); +} + +template<class _Derived, typename... _Types> +InputStream<_Derived> &operator>>(InputStream<_Derived> &_input, Struct<_Types...> &_value) { + return _input.template readValue<EmptyDeployment>(_value); +} + +template<class _Derived, class _PolymorphicStruct> +InputStream<_Derived> &operator>>(InputStream<_Derived> &_input, std::shared_ptr<_PolymorphicStruct> &_value) { + return _input.template readValue<EmptyDeployment>(_value); +} + +template<class _Derived, typename... _Types> +InputStream<_Derived> & operator>>(InputStream<_Derived> &_input, Variant<_Types...> &_value) { + return _input.template readValue<EmptyDeployment>(_value); +} + +template<class _Derived, typename _ElementType> +InputStream<_Derived> &operator>>(InputStream<_Derived> &_input, std::vector<_ElementType> &_value) { + return _input.template readValue<EmptyDeployment>(_value); +} + +template<class _Derived, typename _KeyType, typename _ValueType, typename _HasherType> +InputStream<_Derived> &operator>>(InputStream<_Derived> &_input, std::unordered_map<_KeyType, _ValueType, _HasherType> &_value) { + return _input.template readValue<EmptyDeployment>(_value); +} + +template<class _Derived, typename _Type, typename _TypeDeployment> +InputStream<_Derived> &operator>>(InputStream<_Derived> &_input, Deployable<_Type, _TypeDeployment> &_value) { + return _input.template readValue<_TypeDeployment>(_value.getValue(), _value.getDepl()); +} + +} // namespace CommonAPI + +#endif // COMMONAPI_INPUT_STREAM_HPP_ diff --git a/include/CommonAPI/Logger.hpp b/include/CommonAPI/Logger.hpp new file mode 100644 index 0000000..d2761ac --- /dev/null +++ b/include/CommonAPI/Logger.hpp @@ -0,0 +1,179 @@ +// 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/. + +#ifndef COMMONAPI_LOGGER_HPP_ +#define COMMONAPI_LOGGER_HPP_ + +#ifdef USE_DLT +#include <dlt.h> +#endif + +#include <cstdint> +#include <fstream> +#include <memory> +#include <mutex> +#include <sstream> + +#include <CommonAPI/Export.hpp> + +#define COMMONAPI_LOGLEVEL_FATAL 0 +#define COMMONAPI_LOGLEVEL_ERROR 1 +#define COMMONAPI_LOGLEVEL_WARNING 2 +#define COMMONAPI_LOGLEVEL_INFO 3 +#define COMMONAPI_LOGLEVEL_DEBUG 4 +#define COMMONAPI_LOGLEVEL_VERBOSE 5 + +#ifndef COMMONAPI_LOGLEVEL +#define COMMONAPI_LOGLEVEL COMMONAPI_LOGLEVEL_INFO +#endif + +#ifdef WIN32 + +#define COMMONAPI_FATAL(...) \ + do { Logger::log(Logger::Level::LL_FATAL, __VA_ARGS__); } while (false); + +#if COMMONAPI_LOGLEVEL >= COMMONAPI_LOGLEVEL_ERROR +#define COMMONAPI_ERROR(...) \ + do { Logger::log(Logger::Level::LL_ERROR, __VA_ARGS__); } while (false); +#else +#define COMMONAPI_ERROR(...) +#endif + +#if COMMONAPI_LOGLEVEL >= COMMONAPI_LOGLEVEL_WARNING +#define COMMONAPI_WARNING(...) \ + do { Logger::log(Logger::Level::LL_WARNING, __VA_ARGS__); } while (false); +#else +#define COMMONAPI_WARNING(...) +#endif + +#if COMMONAPI_LOGLEVEL >= COMMONAPI_LOGLEVEL_INFO +#define COMMONAPI_INFO(...) \ + do { Logger::log(Logger::Level::LL_INFO, __VA_ARGS__); } while (false); +#else +#define COMMONAPI_INFO(...) +#endif + +#if COMMONAPI_LOGLEVEL >= COMMONAPI_LOGLEVEL_DEBUG +#define COMMONAPI_DEBUG(...) \ + do { Logger::log(Logger::Level::LL_DEBUG, __VA_ARGS__); } while (false); +#else +#define COMMONAPI_DEBUG(...) +#endif + +#if COMMONAPI_LOGLEVEL >= COMMONAPI_LOGLEVEL_VERBOSE +#define COMMONAPI_VERBOSE(...) \ + do { Logger::log(Logger::Level::LL_VERBOSE, __VA_ARGS__); } while (false); +#else +#define COMMONAPI_VERBOSE(...) +#endif + +#else // !WIN32 + +#define COMMONAPI_FATAL(params...) \ + do { Logger::log(Logger::Level::LL_FATAL, params); } while (false); + +#if COMMONAPI_LOGLEVEL >= COMMONAPI_LOGLEVEL_ERROR + #define COMMONAPI_ERROR(params...) \ + do { Logger::log(Logger::Level::LL_ERROR, params); } while (false); +#else + #define COMMONAPI_ERROR(params...) +#endif + +#if COMMONAPI_LOGLEVEL >= COMMONAPI_LOGLEVEL_WARNING + #define COMMONAPI_WARNING(params...) \ + do { Logger::log(Logger::Level::LL_WARNING, params); } while (false); +#else + #define COMMONAPI_WARNING(params...) +#endif + +#if COMMONAPI_LOGLEVEL >= COMMONAPI_LOGLEVEL_INFO + #define COMMONAPI_INFO(params...) \ + do { Logger::log(Logger::Level::LL_INFO, params); } while (false); +#else + #define COMMONAPI_INFO(params...) +#endif + +#if COMMONAPI_LOGLEVEL >= COMMONAPI_LOGLEVEL_DEBUG + #define COMMONAPI_DEBUG(params...) \ + do { Logger::log(Logger::Level::LL_DEBUG, params); } while (false); +#else + #define COMMONAPI_DEBUG(params...) +#endif + +#if COMMONAPI_LOGLEVEL >= COMMONAPI_LOGLEVEL_VERBOSE + #define COMMONAPI_VERBOSE(params...) \ + do { Logger::log(Logger::Level::LL_VERBOSE, params); } while (false); +#else + #define COMMONAPI_VERBOSE(params...) +#endif + +#endif // WIN32 + +namespace CommonAPI { + +class Logger { +public: + COMMONAPI_EXPORT enum class Level : uint8_t { + LL_FATAL = 0, LL_ERROR = 1, LL_WARNING = 2, LL_INFO = 3, LL_DEBUG = 4, LL_VERBOSE = 5 + }; + + COMMONAPI_EXPORT Logger(); + + template<typename... _LogEntries> + COMMONAPI_EXPORT static void log(Level _level, _LogEntries... _entries) { + std::stringstream buffer; + log_intern(buffer, _entries...); + Logger::get()->doLog(_level, buffer.str()); + } + + COMMONAPI_EXPORT static void init(bool, const std::string &, bool = false, const std::string & = ""); + +private: + COMMONAPI_EXPORT static inline std::shared_ptr<Logger> get() { + static std::shared_ptr<Logger> theLogger = std::make_shared<Logger>(); + return theLogger; + } + + COMMONAPI_EXPORT static void log_intern(std::stringstream &_buffer) { + } + + template<typename _LogEntry, typename... _MoreLogEntries> + COMMONAPI_EXPORT static void log_intern(std::stringstream &_buffer, _LogEntry _entry, _MoreLogEntries... _moreEntries) { + _buffer << _entry; + log_intern(_buffer, _moreEntries...); + } + + COMMONAPI_EXPORT void doLog(Level _level, const std::string &_message); + +#if defined(USE_CONSOLE) || defined(USE_FILE) || defined(USE_DLT) + static Level stringAsLevel(const std::string &_level); +#endif +#if defined(USE_CONSOLE) || defined(USE_FILE) + static std::string levelAsString(Level _level); +#endif +#ifdef USE_DLT + static DltLogLevelType levelAsDlt(Level _level); +#endif +#if defined(USE_CONSOLE) || defined(USE_FILE) + static std::mutex mutex_; +#endif +#if defined(USE_CONSOLE) || defined(USE_FILE) || defined(USE_DLT) + static Level maximumLogLevel_; +#endif +#ifdef USE_CONSOLE + static bool useConsole_; +#endif +#ifdef USE_FILE + static std::shared_ptr<std::ofstream> file_; +#endif +#ifdef USE_DLT + static bool useDlt_; + DLT_DECLARE_CONTEXT(dlt_); +#endif +}; + +} // namespace CommonAPI + +#endif // COMMONAPI_LOGGER_HPP_ diff --git a/include/CommonAPI/MainLoopContext.hpp b/include/CommonAPI/MainLoopContext.hpp new file mode 100644 index 0000000..b2e1056 --- /dev/null +++ b/include/CommonAPI/MainLoopContext.hpp @@ -0,0 +1,299 @@ +// 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.h> can be included directly, this file may disappear or change contents." +#endif + +#ifndef COMMONAPI_MAINLOOPCONTEXT_HPP_ +#define COMMONAPI_MAINLOOPCONTEXT_HPP_ + +#include <cstdint> + +#ifdef WIN32 +#include <WinSock2.h> +#else +#include <poll.h> +#endif + +#ifdef WIN32 +#undef max +#endif + +#include <limits> +#include <vector> +#include <chrono> +#include <list> +#include <functional> +#include <string> + +#include <CommonAPI/Export.hpp> + +namespace CommonAPI { + +enum class DispatchPriority { + VERY_HIGH, + HIGH, + DEFAULT, + LOW, + VERY_LOW +}; + + +int64_t COMMONAPI_EXPORT getCurrentTimeInMs(); + + +/** + * \brief Describes a basic element that periodically needs to be dispatched. + * + * A DispatchSource is not directly related to a file descriptor, but + * may be dependent on a watch that manages a file descriptor. If this + * is the case, the corresponding Watch will provide information about + * which DispatchSources are dependent. + */ +struct DispatchSource { + virtual ~DispatchSource() {} + + /** + * Indicates whether this source is ready to be dispatched. + * "Prepare" will be called before polling the file descriptors. + * + * @return 'true' if the source is ready to be dispatched. + */ + virtual bool prepare(int64_t& timeout) = 0; + + /** + * Indicates whether this source is ready to be dispatched. + * "Check" will be called after polling the file descriptors. + * + * @return 'true' if the source is ready to be dispatched. + */ + virtual bool check() = 0; + + /** + * The return value indicates whether this dispatch source currently has + * more data to dispatch. The mainloop may chose to ignore the return value. + * + * @return 'true' if there currently is more to dispatch, 'false' if not. + */ + virtual bool dispatch() = 0; +}; + + +/** + * \brief Describes an element that manages a file descriptor. + * + * The watch is ready to be dispatched whenever it's managed file descriptor + * has events in it's revents-field. + * + * It is possible that there are DispatchSources of which the dispatch readiness + * directly depends on the dispatching of the watch. If this is the case, such + * DispatchSources can be retrieved from this Watch. + */ +struct Watch { + virtual ~Watch() {} + + /** + * \brief Dispatches the watch. + * + * Should only be called once the associated file descriptor has events ready. + * + * @param eventFlags The events that shall be retrieved from the file descriptor. + */ + virtual void dispatch(unsigned int eventFlags) = 0; + + /** + * \brief Returns the file descriptor that is managed by this watch. + * + * @return The associated file descriptor. + */ + virtual const pollfd& getAssociatedFileDescriptor() = 0; + + /** + * \brief Returns a vector of all dispatch sources that depend on the watched file descriptor. + * + * The returned vector will not be empty if and only if there are any sources + * that depend on availability of data of the watched file descriptor. Whenever this + * Watch is dispatched, those sources likely also need to be dispatched. + */ + virtual const std::vector<DispatchSource*>& getDependentDispatchSources() = 0; +}; + +const int64_t TIMEOUT_INFINITE = std::numeric_limits<int64_t>::max(); +const int64_t TIMEOUT_NONE = 0; + + +/** + * \brief Describes a basic timeout. + * + * Timeouts will be taken into consideration when waiting in a call to poll + * for a file descriptor to become ready. When the lowest known timeout expires, + * the call to poll will return, regardless of whether a file descriptor was ready + * or not. + */ +struct Timeout { + virtual ~Timeout() {} + + /** + * Needs to be called when this timeout is expired. + * + * @return 'true' if the timeout shall be rescheduled, 'false' if it shall be removed. + */ + virtual bool dispatch() = 0; + + /** + * \brief The timeout interval in milliseconds. + * + * Returns TIMEOUT_INFINITE for "dispatch never", TIMEOUT_NONE for "dispatch immediately", + * or any positive value as an interval of time in milliseconds that needs to pass before + * this timeout is to be dispatched. + */ + virtual int64_t getTimeoutInterval() const = 0; + + /** + * \brief Returns the point in time at which this timeout needs to be dispatched next. + * + * After a initialization and after each dispatch, this timeout will re-calculate it's next + * ready time. This value may be ignored if a different mechanism for monitoring timeout intervals + * is used. + */ + virtual int64_t getReadyTime() const = 0; +}; + + +typedef std::function<void(DispatchSource*, const DispatchPriority)> DispatchSourceAddedCallback; +typedef std::function<void(DispatchSource*)> DispatchSourceRemovedCallback; +typedef std::function<void(Watch*, const DispatchPriority)> WatchAddedCallback; +typedef std::function<void(Watch*)> WatchRemovedCallback; +typedef std::function<void(Timeout*, const DispatchPriority)> TimeoutSourceAddedCallback; +typedef std::function<void(Timeout*)> TimeoutSourceRemovedCallback; +typedef std::function<void()> WakeupCallback; + +typedef std::list<std::pair<DispatchSourceAddedCallback, DispatchSourceRemovedCallback>> DispatchSourceListenerList; +typedef std::list<std::pair<WatchAddedCallback, WatchRemovedCallback>> WatchListenerList; +typedef std::list<std::pair<TimeoutSourceAddedCallback, TimeoutSourceRemovedCallback>> TimeoutSourceListenerList; +typedef std::list<WakeupCallback> WakeupListenerList; + +typedef DispatchSourceListenerList::iterator DispatchSourceListenerSubscription; +typedef WatchListenerList::iterator WatchListenerSubscription; +typedef TimeoutSourceListenerList::iterator TimeoutSourceListenerSubscription; +typedef WakeupListenerList::iterator WakeupListenerSubscription; + + +/** + * \brief Provides hooks for your Main Loop implementation. + * + * By registering callbacks with this class, you will be notified about all DispatchSources, + * Watches, Timeouts and Wakeup-Events that need to be handled by your Main Loop implementation. + * + */ +class MainLoopContext { +public: + COMMONAPI_EXPORT MainLoopContext(const std::string &_name = "COMMONAPI_DEFAULT_MAINLOOP_CONTEXT") + : name_(_name){ + } + + COMMONAPI_EXPORT MainLoopContext(const MainLoopContext&) = delete; + COMMONAPI_EXPORT MainLoopContext& operator=(const MainLoopContext&) = delete; + COMMONAPI_EXPORT MainLoopContext(MainLoopContext&&) = delete; + COMMONAPI_EXPORT MainLoopContext& operator=(MainLoopContext&&) = delete; + + COMMONAPI_EXPORT const std::string &getName() const; + + /** + * \brief Registers for all DispatchSources that are added or removed. + */ + COMMONAPI_EXPORT DispatchSourceListenerSubscription subscribeForDispatchSources(DispatchSourceAddedCallback dispatchAddedCallback, DispatchSourceRemovedCallback dispatchRemovedCallback); + + /** + * \brief Registers for all Watches that are added or removed. + */ + COMMONAPI_EXPORT WatchListenerSubscription subscribeForWatches(WatchAddedCallback watchAddedCallback, WatchRemovedCallback watchRemovedCallback); + + /** + * \brief Registers for all Timeouts that are added or removed. + */ + COMMONAPI_EXPORT TimeoutSourceListenerSubscription subscribeForTimeouts(TimeoutSourceAddedCallback timeoutAddedCallback, TimeoutSourceRemovedCallback timeoutRemovedCallback); + + /** + * \brief Registers for all Wakeup-Events that need to interrupt a call to "poll". + */ + COMMONAPI_EXPORT WakeupListenerSubscription subscribeForWakeupEvents(WakeupCallback wakeupCallback); + + /** + * \brief Unsubscribes your listeners for DispatchSources. + */ + COMMONAPI_EXPORT void unsubscribeForDispatchSources(DispatchSourceListenerSubscription subscription); + + /** + * \brief Unsubscribes your listeners for Watches. + */ + COMMONAPI_EXPORT void unsubscribeForWatches(WatchListenerSubscription subscription); + + /** + * \brief Unsubscribes your listeners for Timeouts. + */ + COMMONAPI_EXPORT void unsubscribeForTimeouts(TimeoutSourceListenerSubscription subscription); + + /** + * \brief Unsubscribes your listeners for Wakeup-Events. + */ + COMMONAPI_EXPORT void unsubscribeForWakeupEvents(WakeupListenerSubscription subscription); + + /** + * \brief Notifies all listeners about a new DispatchSource. + */ + COMMONAPI_EXPORT void registerDispatchSource(DispatchSource* dispatchSource, const DispatchPriority dispatchPriority = DispatchPriority::DEFAULT); + + /** + * \brief Notifies all listeners about the removal of a DispatchSource. + */ + COMMONAPI_EXPORT void deregisterDispatchSource(DispatchSource* dispatchSource); + + /** + * \brief Notifies all listeners about a new Watch. + */ + COMMONAPI_EXPORT void registerWatch(Watch* watch, const DispatchPriority dispatchPriority = DispatchPriority::DEFAULT); + + /** + * \brief Notifies all listeners about the removal of a Watch. + */ + COMMONAPI_EXPORT void deregisterWatch(Watch* watch); + + /** + * \brief Notifies all listeners about a new Timeout. + */ + COMMONAPI_EXPORT void registerTimeoutSource(Timeout* timeoutEvent, const DispatchPriority dispatchPriority = DispatchPriority::DEFAULT); + + /** + * \brief Notifies all listeners about the removal of a Timeout. + */ + COMMONAPI_EXPORT void deregisterTimeoutSource(Timeout* timeoutEvent); + + /** + * \brief Notifies all listeners about a wakeup event that just happened. + */ + COMMONAPI_EXPORT void wakeup(); + + /** + * \brief Will return true if at least one subscribe for DispatchSources or Watches has been called. + * + * This function will be used to prevent creation of a factory if a mainloop context is given, but + * no listeners have been registered. This is done in order to ensure correct use of the mainloop context. + */ + COMMONAPI_EXPORT bool isInitialized(); + + private: + DispatchSourceListenerList dispatchSourceListeners_; + WatchListenerList watchListeners_; + TimeoutSourceListenerList timeoutSourceListeners_; + WakeupListenerList wakeupListeners_; + + std::string name_; +}; + +} // namespace CommonAPI + +#endif // COMMONAPI_MAINLOOPCONTEXT_HPP_ diff --git a/include/CommonAPI/OutputStream.hpp b/include/CommonAPI/OutputStream.hpp new file mode 100644 index 0000000..1ca221c --- /dev/null +++ b/include/CommonAPI/OutputStream.hpp @@ -0,0 +1,241 @@ +// 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.h> can be included directly, this file may disappear or change contents." +#endif + +#ifndef COMMONAPI_OUTPUTSTREAM_HPP_ +#define COMMONAPI_OUTPUTSTREAM_HPP_ + +#include <unordered_map> + +#include <CommonAPI/ByteBuffer.hpp> +#include <CommonAPI/Deployable.hpp> +#include <CommonAPI/Deployment.hpp> +#include <CommonAPI/Enumeration.hpp> +#include <CommonAPI/Struct.hpp> +#include <CommonAPI/Variant.hpp> +#include <CommonAPI/Version.hpp> + +namespace CommonAPI { + +template<class _Derived> +class OutputStream { +public: + template<class _Deployment> + OutputStream &writeValue(const bool &_value, const _Deployment *_depl = nullptr) { + return get()->writeValue(_value, _depl); + } + + template<class _Deployment> + OutputStream &writeValue(const int8_t &_value, const _Deployment *_depl = nullptr) { + return get()->writeValue(_value, _depl); + } + + template<class _Deployment> + OutputStream &writeValue(const int16_t &_value, const _Deployment *_depl = nullptr) { + return get()->writeValue(_value, _depl); + } + + template<class _Deployment> + OutputStream &writeValue(const int32_t &_value, const _Deployment *_depl = nullptr) { + return get()->writeValue(_value, _depl); + } + + template<class _Deployment> + OutputStream &writeValue(const int64_t &_value, const _Deployment *_depl = nullptr) { + return get()->writeValue(_value, _depl); + } + + template<class _Deployment> + OutputStream &writeValue(const uint8_t &_value, const _Deployment *_depl = nullptr) { + return get()->writeValue(_value, _depl); + } + + template<class _Deployment> + OutputStream &writeValue(const uint16_t &_value, const _Deployment *_depl = nullptr) { + return get()->writeValue(_value, _depl); + } + + template<class _Deployment> + OutputStream &writeValue(const uint32_t &_value, const _Deployment *_depl = nullptr) { + return get()->writeValue(_value, _depl); + } + + template<class _Deployment> + OutputStream &writeValue(const uint64_t &_value, const _Deployment *_depl = nullptr) { + return get()->writeValue(_value, _depl); + } + + template<class _Deployment> + OutputStream &writeValue(const float &_value, const _Deployment *_depl = nullptr) { + return get()->writeValue(_value, _depl); + } + + template<class _Deployment> + OutputStream &writeValue(const double &_value, const _Deployment *_depl = nullptr) { + return get()->writeValue(_value, _depl); + } + + template<class _Deployment> + OutputStream &writeValue(const std::string &_value, const _Deployment *_depl = nullptr) { + return get()->writeValue(_value, _depl); + } + + template<class _Deployment> + OutputStream &writeValue(const Version &_value, const _Deployment *_depl = nullptr) { + return get()->writeValue(_value, _depl); + } + + template<class _Deployment, typename _Base> + OutputStream &writeValue(const Enumeration<_Base> &_value, const _Deployment *_depl = nullptr) { + return get()->writeValue(_value, _depl); + } + + template<class _Deployment, typename... _Types> + OutputStream &writeValue(const Struct<_Types...> &_value, const _Deployment *_depl = nullptr) { + return get()->writeValue(_value, _depl); + } + + template<class _Deployment, class _PolymorphicStruct> + OutputStream &writeValue(const std::shared_ptr<_PolymorphicStruct> &_value, const _Deployment *_depl = nullptr) { + return get()->writeValue(_value, _depl); + } + + template<class _Deployment, typename... _Types> + OutputStream &writeValue(const Variant<_Types...> &_value, const _Deployment *_depl = nullptr) { + return get()->writeValue(_value, _depl); + } + + template<class _Deployment, typename _ElementType> + OutputStream &writeValue(const std::vector<_ElementType> &_value, const _Deployment *_depl = nullptr) { + return get()->writeValue(_value, _depl); + } + + template<class _Deployment, typename _KeyType, typename _ValueType, typename _HasherType> + OutputStream &writeValue(const std::unordered_map<_KeyType, _ValueType, _HasherType> &_value, + const _Deployment *_depl = nullptr) { + return get()->writeValue(_value, _depl); + } + + bool hasError() const { + return get()->hasError(); + } + +private: + inline _Derived *get() { + return static_cast<_Derived *>(this); + } + + inline const _Derived *get() const { + return static_cast<const _Derived *>(this); + } +}; + +template<class _Derived> +inline OutputStream<_Derived> &operator<<(OutputStream<_Derived> &_output, const bool &_value) { + return _output.template writeValue<EmptyDeployment>(_value); +} + +template<class _Derived> +inline OutputStream<_Derived>& operator<<(OutputStream<_Derived> &_output, const int8_t &_value) { + return _output.template writeValue<EmptyDeployment>(_value); +} + +template<class _Derived> +inline OutputStream<_Derived>& operator<<(OutputStream<_Derived> &_output, const int16_t &_value) { + return _output.template writeValue<EmptyDeployment>(_value); +} + +template<class _Derived> +inline OutputStream<_Derived>& operator<<(OutputStream<_Derived> &_output, const int32_t &_value) { + return _output.template writeValue<EmptyDeployment>(_value); +} + +template<class _Derived> +inline OutputStream<_Derived>& operator<<(OutputStream<_Derived> &_output, const int64_t &_value) { + return _output.template writeValue<EmptyDeployment>(_value); +} + +template<class _Derived> +inline OutputStream<_Derived>& operator<<(OutputStream<_Derived> &_output, const uint8_t &_value) { + return _output.template writeValue<EmptyDeployment>(_value); +} + +template<class _Derived> +inline OutputStream<_Derived>& operator<<(OutputStream<_Derived> &_output, const uint16_t &_value) { + return _output.template writeValue<EmptyDeployment>(_value); +} + +template<class _Derived> +inline OutputStream<_Derived>& operator<<(OutputStream<_Derived> &_output, const uint32_t &_value) { + return _output.template writeValue<EmptyDeployment>(_value); +} + +template<class _Derived> +inline OutputStream<_Derived>& operator<<(OutputStream<_Derived> &_output, const uint64_t &_value) { + return _output.template writeValue<EmptyDeployment>(_value); +} + +template<class _Derived> +inline OutputStream<_Derived>& operator<<(OutputStream<_Derived> &_output, const float &_value) { + return _output.template writeValue<EmptyDeployment>(_value); +} + +template<class _Derived> +inline OutputStream<_Derived>& operator<<(OutputStream<_Derived> &_output, const double &_value) { + return _output.template writeValue<EmptyDeployment>(_value); +} + +template<class _Derived> +inline OutputStream<_Derived>& operator<<(OutputStream<_Derived> &_output, const std::string &_value) { + return _output.template writeValue<EmptyDeployment>(_value); +} + +template<class _Derived, typename _Type, typename _TypeDepl> +inline OutputStream<_Derived> &operator<<(OutputStream<_Derived> &_output, const Deployable<_Type, _TypeDepl> &_value) { + return _output.template writeValue<_TypeDepl>(_value.getValue(), _value.getDepl()); +} + +template<class _Derived> +inline OutputStream<_Derived>& operator<<(OutputStream<_Derived> &_output, const Version &_value) { + return _output.template writeValue<EmptyDeployment>(_value); +} + +template<class _Derived, typename _Base> +OutputStream<_Derived> &operator<<(OutputStream<_Derived> &_output, const Enumeration<_Base> &_value) { + return _output.template writeValue<EmptyDeployment>(_value); +} + +template<class _Derived, typename... _Types> +OutputStream<_Derived> &operator<<(OutputStream<_Derived> &_output, const Struct<_Types...> &_value) { + return _output.template writeValue<EmptyDeployment>(_value); +} + +template<class _Derived, class _PolymorphicStruct> +OutputStream<_Derived> &operator<<(OutputStream<_Derived> &_output, const std::shared_ptr<_PolymorphicStruct> &_value) { + return _output.template writeValue<EmptyDeployment>(_value); +} + +template<class _Derived, typename... _Types> +OutputStream<_Derived> &operator<<(OutputStream<_Derived> &_output, const Variant<_Types...> &_value) { + return _output.template writeValue<EmptyDeployment>(_value); +} + +template<class _Derived, typename _ElementType> +OutputStream<_Derived> &operator<<(OutputStream<_Derived> &_output, const std::vector<_ElementType> &_value) { + return _output.template writeValue<EmptyDeployment>(_value); +} + +template<class _Derived, typename _KeyType, typename _ValueType, typename _HasherType> +OutputStream<_Derived> &operator<<(OutputStream<_Derived> &_output, + const std::unordered_map<_KeyType, _ValueType, _HasherType> &_value) { + return _output.template writeValue<EmptyDeployment>(_value); +} + +} // namespace CommonAPI + +#endif // COMMONAPI_OUTPUTSTREAM_HPP_ diff --git a/include/CommonAPI/Proxy.hpp b/include/CommonAPI/Proxy.hpp new file mode 100644 index 0000000..5b7d745 --- /dev/null +++ b/include/CommonAPI/Proxy.hpp @@ -0,0 +1,47 @@ +// 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.h> can be included directly, this file may disappear or change contents." +#endif + +#ifndef COMMONAPI_PROXY_HPP_ +#define COMMONAPI_PROXY_HPP_ + +#include <cstdint> +#include <memory> +#include <type_traits> + +#include <CommonAPI/Address.hpp> +#include <CommonAPI/Attribute.hpp> +#include <CommonAPI/Export.hpp> +#include <CommonAPI/Version.hpp> + +namespace CommonAPI { + +typedef Event<AvailabilityStatus> ProxyStatusEvent; +typedef ReadonlyAttribute<Version> InterfaceVersionAttribute; + +class Proxy { +public: + COMMONAPI_EXPORT virtual ~Proxy() {} + + COMMONAPI_EXPORT const Address &getAddress() const; + + COMMONAPI_EXPORT virtual bool isAvailable() const = 0; + + COMMONAPI_EXPORT virtual bool isAvailableBlocking() const = 0; + + COMMONAPI_EXPORT virtual ProxyStatusEvent& getProxyStatusEvent() = 0; + + COMMONAPI_EXPORT virtual InterfaceVersionAttribute& getInterfaceVersionAttribute() = 0; + +protected: + Address address_; +}; + +} // namespace CommonAPI + +#endif // COMMONAPI_PROXY_HPP_ diff --git a/include/CommonAPI/ProxyManager.hpp b/include/CommonAPI/ProxyManager.hpp new file mode 100644 index 0000000..571eb97 --- /dev/null +++ b/include/CommonAPI/ProxyManager.hpp @@ -0,0 +1,73 @@ +// 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.h> can be included directly, this file may disappear or change contents." +#endif + +#ifndef COMMONAPI_PROXY_MANAGER_HPP_ +#define COMMONAPI_PROXY_MANAGER_HPP_ + +#include <functional> +#include <future> +#include <string> +#include <vector> + +#include <CommonAPI/Event.hpp> +#include <CommonAPI/Proxy.hpp> +#include <CommonAPI/Types.hpp> + +namespace CommonAPI { + +class ProxyManager { +public: + typedef std::function<void(const CallStatus &, const std::vector<std::string> &)> GetAvailableInstancesCallback; + typedef std::function<void(const CallStatus &, const AvailabilityStatus &)> GetInstanceAvailabilityStatusCallback; + + typedef Event<std::string, AvailabilityStatus> InstanceAvailabilityStatusChangedEvent; + + ProxyManager() = default; + ProxyManager(ProxyManager &&) = delete; + ProxyManager(const ProxyManager &) = delete; + + virtual ~ProxyManager() {} + + virtual const std::string &getDomain() const = 0; + virtual const std::string &getInterface() const = 0; + virtual const ConnectionId_t &getConnectionId() const = 0; + + virtual void getAvailableInstances(CommonAPI::CallStatus&, std::vector<std::string>& availableInstances) = 0; + virtual std::future<CallStatus> getAvailableInstancesAsync(GetAvailableInstancesCallback callback) = 0; + + virtual void getInstanceAvailabilityStatus(const std::string& instanceAddress, + CallStatus& callStatus, + AvailabilityStatus& availabilityStatus) = 0; + + virtual std::future<CallStatus> getInstanceAvailabilityStatusAsync(const std::string&, + GetInstanceAvailabilityStatusCallback callback) = 0; + + virtual InstanceAvailabilityStatusChangedEvent& getInstanceAvailabilityStatusChangedEvent() = 0; + + template<template<typename ...> class _ProxyClass, typename ... _AttributeExtensions> + std::shared_ptr<_ProxyClass<_AttributeExtensions...> > + buildProxy(const std::string &_instance) { + std::shared_ptr<Proxy> proxy = createProxy(getDomain(), getInterface(), _instance, getConnectionId()); + if (proxy) { + return std::make_shared<_ProxyClass<_AttributeExtensions...>>(proxy); + } + return NULL; + + } + +protected: + std::shared_ptr<Proxy> createProxy(const std::string &, + const std::string &, + const std::string &, + const ConnectionId_t &_connection) const; +}; + +} // namespace CommonAPI + +#endif // COMMONAPI_PROXY_MANAGER_HPP_ diff --git a/include/CommonAPI/Runtime.hpp b/include/CommonAPI/Runtime.hpp new file mode 100644 index 0000000..1cb4f94 --- /dev/null +++ b/include/CommonAPI/Runtime.hpp @@ -0,0 +1,203 @@ +// 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.h> can be included directly, this file may disappear or change contents." +#endif + +#ifndef COMMONAPI_RUNTIME_HPP_ +#define COMMONAPI_RUNTIME_HPP_ + +#include <map> +#include <memory> +#include <mutex> +#include <set> + +#include <CommonAPI/Export.hpp> +#include <CommonAPI/Factory.hpp> +#include <CommonAPI/Types.hpp> + +namespace CommonAPI { + +static const ConnectionId_t DEFAULT_CONNECTION_ID = ""; + +class MainLoopContext; +class Proxy; +class ProxyManager; +class StubBase; + +template<template<typename ...> class _ProxyType, template<typename> class _AttributeExtension> +struct DefaultAttributeProxyHelper; + +template<template<typename ...> class _ProxyClass, template<typename> class _AttributeExtension> +std::shared_ptr< + typename DefaultAttributeProxyHelper<_ProxyClass, _AttributeExtension>::class_t +> createProxyWithDefaultAttributeExtension( + const std::string &_domain, const std::string &_instance); + +class Runtime { +public: + COMMONAPI_EXPORT static std::string getProperty(const std::string &_name); + COMMONAPI_EXPORT static void setProperty(const std::string &_name, const std::string &_value); + + COMMONAPI_EXPORT static std::shared_ptr<Runtime> get(); + + COMMONAPI_EXPORT Runtime(); + COMMONAPI_EXPORT virtual ~Runtime(); + + COMMONAPI_EXPORT void init(); + + template<template<typename ...> class _ProxyClass, typename ... _AttributeExtensions> + COMMONAPI_EXPORT std::shared_ptr< + _ProxyClass<_AttributeExtensions...> + > + buildProxy(const std::string &_domain, + const std::string &_instance, + const ConnectionId_t &_connectionId = DEFAULT_CONNECTION_ID) { + std::shared_ptr<Proxy> proxy + = createProxy(_domain, + _ProxyClass<_AttributeExtensions...>::getInterface(), + _instance, + _connectionId); + + if (proxy) { + return std::make_shared<_ProxyClass<_AttributeExtensions...>>(proxy); + } + else { + return nullptr; + } + } + + template<template<typename ...> class _ProxyClass, typename ... _AttributeExtensions> + COMMONAPI_EXPORT std::shared_ptr< + _ProxyClass<_AttributeExtensions...> + > + buildProxy(const std::string &_domain, + const std::string &_instance, + std::shared_ptr<MainLoopContext> _context) { + std::shared_ptr<Proxy> proxy + = createProxy(_domain, + _ProxyClass<_AttributeExtensions...>::getInterface(), + _instance, + _context); + if (proxy) { + return std::make_shared<_ProxyClass<_AttributeExtensions...>>(proxy); + } + else { + return nullptr; + } + } + + template <template<typename ...> class _ProxyClass, template<typename> class _AttributeExtension> + COMMONAPI_EXPORT std::shared_ptr<typename DefaultAttributeProxyHelper<_ProxyClass, _AttributeExtension>::class_t> + buildProxyWithDefaultAttributeExtension(const std::string &_domain, + const std::string &_instance, + const ConnectionId_t &_connectionId = DEFAULT_CONNECTION_ID) { + std::shared_ptr<Proxy> proxy + = createProxy(_domain, + DefaultAttributeProxyHelper<_ProxyClass, _AttributeExtension>::class_t::getInterface(), + _instance, + _connectionId); + if (proxy) { + return std::make_shared<typename DefaultAttributeProxyHelper<_ProxyClass, _AttributeExtension>::class_t>(proxy); + } + return nullptr; + } + + template <template<typename ...> class _ProxyClass, template<typename> class _AttributeExtension> + COMMONAPI_EXPORT std::shared_ptr<typename DefaultAttributeProxyHelper<_ProxyClass, _AttributeExtension>::class_t> + buildProxyWithDefaultAttributeExtension(const std::string &_domain, + const std::string &_instance, + std::shared_ptr<MainLoopContext> _context) { + std::shared_ptr<Proxy> proxy + = createProxy(_domain, + DefaultAttributeProxyHelper<_ProxyClass, _AttributeExtension>::class_t::getInterface(), + _instance, + _context); + if (proxy) { + return std::make_shared<typename DefaultAttributeProxyHelper<_ProxyClass, _AttributeExtension>::class_t>(proxy); + } + return nullptr; + } + + template<typename _Stub> + COMMONAPI_EXPORT bool registerService(const std::string &_domain, + const std::string &_instance, + std::shared_ptr<_Stub> _service, + const ConnectionId_t &_connectionId = DEFAULT_CONNECTION_ID) { + return registerStub(_domain, _Stub::StubInterface::getInterface(), _instance, _service, _connectionId); + } + + template<typename _Stub> + COMMONAPI_EXPORT bool registerService(const std::string &_domain, + const std::string &_instance, + std::shared_ptr<_Stub> _service, + std::shared_ptr<MainLoopContext> _context) { + return registerStub(_domain, _Stub::StubInterface::getInterface(), _instance, _service, _context); + } + + COMMONAPI_EXPORT bool unregisterService(const std::string &_domain, + const std::string &_interface, + const std::string &_instance) { + return unregisterStub(_domain, _interface, _instance); + } + + COMMONAPI_EXPORT bool registerFactory(const std::string &_ipc, std::shared_ptr<Factory> _factory); + COMMONAPI_EXPORT bool unregisterFactory(const std::string &_ipc); + + inline const std::string &getDefaultBinding() const { return defaultBinding_; }; + +private: + COMMONAPI_EXPORT bool readConfiguration(); + COMMONAPI_EXPORT bool splitAddress(const std::string &, std::string &, std::string &, std::string &); + + COMMONAPI_EXPORT std::shared_ptr<Proxy> createProxy(const std::string &, const std::string &, const std::string &, + const ConnectionId_t &); + COMMONAPI_EXPORT std::shared_ptr<Proxy> createProxy(const std::string &, const std::string &, const std::string &, + std::shared_ptr<MainLoopContext>); + + COMMONAPI_EXPORT std::shared_ptr<Proxy> createProxyHelper(const std::string &, const std::string &, const std::string &, + const ConnectionId_t &); + COMMONAPI_EXPORT std::shared_ptr<Proxy> createProxyHelper(const std::string &, const std::string &, const std::string &, + std::shared_ptr<MainLoopContext>); + + + COMMONAPI_EXPORT bool registerStub(const std::string &, const std::string &, const std::string &, + std::shared_ptr<StubBase>, const ConnectionId_t &); + COMMONAPI_EXPORT bool registerStub(const std::string &, const std::string &, const std::string &, + std::shared_ptr<StubBase>, std::shared_ptr<MainLoopContext>); + COMMONAPI_EXPORT bool registerStubHelper(const std::string &, const std::string &, const std::string &, + std::shared_ptr<StubBase>, const ConnectionId_t &); + COMMONAPI_EXPORT bool registerStubHelper(const std::string &, const std::string &, const std::string &, + std::shared_ptr<StubBase>, std::shared_ptr<MainLoopContext>); + + COMMONAPI_EXPORT bool unregisterStub(const std::string &, const std::string &, const std::string &); + + COMMONAPI_EXPORT std::string getLibrary(const std::string &, const std::string &, const std::string &, bool); + COMMONAPI_EXPORT bool loadLibrary(const std::string &); + +private: + std::string defaultBinding_; + std::string defaultFolder_; + std::string defaultConfig_; + + std::map<std::string, std::shared_ptr<Factory>> factories_; + std::shared_ptr<Factory> defaultFactory_; + std::map<std::string, std::map<bool, std::string>> libraries_; + std::set<std::string> loadedLibraries_; // Library name + + std::mutex mutex_; + std::mutex factoriesMutex_; + std::mutex loadMutex_; + + static std::map<std::string, std::string> properties_; + static std::shared_ptr<Runtime> theRuntime__; + +friend class ProxyManager; +}; + +} // namespace CommonAPI + +#endif // COMMONAPI_RUNTIME_HPP_ diff --git a/include/CommonAPI/SelectiveEvent.hpp b/include/CommonAPI/SelectiveEvent.hpp new file mode 100644 index 0000000..ffae1bf --- /dev/null +++ b/include/CommonAPI/SelectiveEvent.hpp @@ -0,0 +1,28 @@ +// 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.h> can be included directly, this file may disappear or change contents." +#endif + +#ifndef COMMONAPI_SELECTIVEEVENT_HPP_ +#define COMMONAPI_SELECTIVEEVENT_HPP_ + +#include <CommonAPI/Event.hpp> + +namespace CommonAPI { + +template<typename ... _Arguments> +class SelectiveEvent: public Event<_Arguments...> { +public: + typedef typename Event<_Arguments...>::Listener Listener; + typedef typename Event<_Arguments...>::Subscription Subscription; + + virtual ~SelectiveEvent() {} +}; + +} // namespace CommonAPI + +#endif // COMMONAPI_SELECTIVEEVENT_HPP_ diff --git a/include/CommonAPI/SerializableArguments.hpp b/include/CommonAPI/SerializableArguments.hpp new file mode 100644 index 0000000..1f2af63 --- /dev/null +++ b/include/CommonAPI/SerializableArguments.hpp @@ -0,0 +1,62 @@ +// 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 + +#ifndef COMMONAPI_SERIALIZABLEARGUMENTS_HPP_ +#define COMMONAPI_SERIALIZABLEARGUMENTS_HPP_ + +#include <CommonAPI/InputStream.hpp> +#include <CommonAPI/OutputStream.hpp> + +namespace CommonAPI { + +template<class _In, class _Out, typename... _Arguments> +struct SerializableArguments; + +template<class _In, class _Out> +struct SerializableArguments<_In, _Out> { + static bool serialize(OutputStream<_Out> &_output) { + return true; + } + + static bool deserialize(InputStream<_In> &_input) { + return true; + } +}; + +template<class _In, class _Out, typename _ArgumentType> +struct SerializableArguments<_In, _Out, _ArgumentType> { + static bool serialize(OutputStream<_Out> &_output, const _ArgumentType &_argument) { + _output << _argument; + return !_output.hasError(); + } + + static bool deserialize(InputStream<_In> &_input, _ArgumentType &_argument) { + _input >> _argument; + return !_input.hasError(); + } +}; + +template <class _In, class _Out, typename _ArgumentType, typename ... _Rest> +struct SerializableArguments<_In, _Out, _ArgumentType, _Rest...> { + static bool serialize(OutputStream<_Out> &_output, const _ArgumentType &_argument, const _Rest&... _rest) { + _output << _argument; + return !_output.hasError() ? + SerializableArguments<_In, _Out, _Rest...>::serialize(_output, _rest...) : false; + } + + static bool deserialize(InputStream<_In> &_input, _ArgumentType &_argument, _Rest&... _rest) { + _input >> _argument; + return !_input.hasError() ? + SerializableArguments<_In, _Out, _Rest...>::deserialize(_input, _rest...) : false; + } +}; + +} // namespace CommonAPI + +#endif // COMMONAPI_SERIALIZABLE_ARGUMENTS_HPP_ diff --git a/include/CommonAPI/Struct.hpp b/include/CommonAPI/Struct.hpp new file mode 100644 index 0000000..c98b09e --- /dev/null +++ b/include/CommonAPI/Struct.hpp @@ -0,0 +1,174 @@ +// 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 + +#ifndef COMMONAPI_STRUCT_HPP_ +#define COMMONAPI_STRUCT_HPP_ + +#include <iostream> +#include <tuple> + +namespace CommonAPI { + +typedef uint32_t Serial; + +template<class _Derived> +class InputStream; + +template<class _Derived> +class OutputStream; + +template<class _Derived> +class TypeOutputStream; + +template<int, class, class, class> +struct StructReader; + +template< + int _Index, class _Input, + template<class...> class _V, class... _Values, + template<class...> class _D, class... _Depls> +struct StructReader<_Index, _Input, _V<_Values...>, _D<_Depls...>> { + void operator()(InputStream<_Input> &_input, + _V<_Values...> &_values, + const _D<_Depls...> *_depls) { + StructReader<_Index-1, _Input, _V<_Values...>, _D<_Depls...>>{}(_input, _values, _depls); + _input.template readValue<>(std::get<_Index>(_values.values_), + (_depls ? std::get<_Index>(_depls->values_) : nullptr)); + } +}; + +template< + int _Index, class _Input, + template<class...> class _V, class... _Values, + class _D> +struct StructReader<_Index, _Input, _V<_Values...>, _D> { + void operator()(InputStream<_Input> &_input, + _V<_Values...> &_values, + const _D *_depls) { + StructReader<_Index-1, _Input, _V<_Values...>, _D>{}(_input, _values, _depls); + _input.template readValue<_D>(std::get<_Index>(_values.values_)); + } +}; + +template<class _Input, + template<class...> class _V, class... _Values, + template<class...> class _D, class... _Depls> +struct StructReader<0, _Input, _V<_Values...>, _D<_Depls...>> { + void operator()(InputStream<_Input> &_input, + _V<_Values...> &_values, + const _D<_Depls...> *_depls) { + _input.template readValue<>(std::get<0>(_values.values_), + (_depls ? std::get<0>(_depls->values_) : nullptr)); + } +}; + +template<class _Input, + template<class...> class _V, class... _Values, + class _D> +struct StructReader<0, _Input, _V<_Values...>, _D> { + void operator()(InputStream<_Input> &_input, + _V<_Values...> &_values, + const _D *_depls) { + _input.template readValue<_D>(std::get<0>(_values.values_)); + } +}; + + +template< int, class, class, class > +struct StructWriter; + +template< + int _Index, class _Output, + template<class ...> class _V, class... _Values, + template <class...> class _D, class... _Depls> +struct StructWriter<_Index, _Output, _V<_Values...>, _D<_Depls...>> { + void operator()(OutputStream<_Output> &_output, + const _V<_Values...> &_values, + const _D<_Depls...> *_depls) { + StructWriter<_Index-1, _Output, _V<_Values...>, _D<_Depls...>>{}(_output, _values, _depls); + _output.template writeValue<>(std::get<_Index>(_values.values_), + (_depls ? std::get<_Index>(_depls->values_) : nullptr)); + } +}; + +template< + int _Index, class _Output, + template<class...> class _V, class... _Values, + class _D> +struct StructWriter<_Index, _Output, _V<_Values...>, _D> { + void operator()(OutputStream<_Output> &_output, + const _V<_Values...> &_values, + const _D *_depls) { + StructWriter<_Index-1, _Output, _V<_Values...>, _D>{}(_output, _values, _depls); + _output.template writeValue<_D>(std::get<_Index>(_values.values_)); + } +}; + +template<class _Output, + template<class...> class _V, class... _Values, + template<class...> class _D, class... _Depls> +struct StructWriter<0, _Output, _V<_Values...>, _D<_Depls...>> { + void operator()(OutputStream<_Output> &_output, + const _V<_Values...> &_values, + const _D<_Depls...> *_depls) { + _output.template writeValue<>(std::get<0>(_values.values_), + (_depls ? std::get<0>(_depls->values_) : nullptr)); + } +}; + +template<class _Output, + template<class...> class _V, class... _Values, + class _D> +struct StructWriter<0, _Output, _V<_Values...>, _D> { + void operator()(OutputStream<_Output> &_output, + const _V<_Values...> &_values, + const _D *_depls) { + _output.template writeValue<_D>(std::get<0>(_values.values_)); + } +}; + +template<int, class, class> +struct StructTypeWriter; + +template<int _Index, class _TypeOutput, + template<class...> class _V, class... _Values> +struct StructTypeWriter<_Index, _TypeOutput, _V<_Values...>> { + void operator()(TypeOutputStream<_TypeOutput> &_output, + const _V<_Values...> &_values) { + StructTypeWriter<_Index-1, _TypeOutput, _V<_Values...>>{}(_output, _values); + _output.template writeType(std::get<_Index>(_values.values_)); + } +}; + +template<class _TypeOutput, + template<class...> class _V, class... _Values> +struct StructTypeWriter<0, _TypeOutput, _V<_Values...>> { + void operator()(TypeOutputStream<_TypeOutput> &_output, + const _V<_Values...> &_values) { + _output.template writeType(std::get<0>(_values.values_)); + } +}; + +// Structures are mapped to a (generated) struct which inherits from CommonAPI::Struct. +// CommonAPI::Struct holds the structured data in a tuple. The generated class provides +// getter- and setter-methods for the structure members. +template<typename... _Types> +struct Struct { + std::tuple<_Types...> values_; +}; + +// Polymorphic structs are mapped to an interface that is derived from the base class +// PolymorphicStruct and contain their parameter in a Struct. +struct PolymorphicStruct { + virtual const Serial getSerial() const = 0; +}; + +} // namespace CommonAPI + +#endif // COMMONAPI_STRUCT_HPP_ diff --git a/include/CommonAPI/Stub.hpp b/include/CommonAPI/Stub.hpp new file mode 100644 index 0000000..75ee4e0 --- /dev/null +++ b/include/CommonAPI/Stub.hpp @@ -0,0 +1,60 @@ +// 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 + +#ifndef COMMONAPI_STUB_HPP_ +#define COMMONAPI_STUB_HPP_ + +#include <memory> +#include <string> +#include <type_traits> + +#include <CommonAPI/Address.hpp> +#include <CommonAPI/Types.hpp> + +namespace CommonAPI { + +class StubAdapter { +public: + virtual ~StubAdapter() {} + inline const Address &getAddress() const { return address_; } + +protected: + Address address_; +}; + +class StubBase { +public: + virtual ~StubBase() {} +}; + +template<typename _StubAdapter, typename _StubRemoteEventHandler> +class Stub: public virtual StubBase { + static_assert(std::is_base_of<StubAdapter, _StubAdapter>::value, "Invalid StubAdapter Class!"); +public: + typedef _StubAdapter StubAdapterType; + typedef _StubRemoteEventHandler RemoteEventHandlerType; + + virtual ~Stub() {} + + virtual _StubRemoteEventHandler* initStubAdapter(const std::shared_ptr<_StubAdapter> &_stubAdapter) = 0; + + inline const std::shared_ptr<_StubAdapter> getStubAdapter() const { return stubAdapter_; } + +protected: + std::shared_ptr<_StubAdapter> stubAdapter_; +}; + +enum SelectiveBroadcastSubscriptionEvent { + SUBSCRIBED, + UNSUBSCRIBED +}; + +} // namespace CommonAPI + +#endif // COMMONAPI_STUB_HPP_ diff --git a/include/CommonAPI/TypeOutputStream.hpp b/include/CommonAPI/TypeOutputStream.hpp new file mode 100644 index 0000000..ec44864 --- /dev/null +++ b/include/CommonAPI/TypeOutputStream.hpp @@ -0,0 +1,197 @@ +// 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 + +#ifndef COMMONAPI_TYPEOUTPUTSTREAM_HPP_ +#define COMMONAPI_TYPEOUTPUTSTREAM_HPP_ + +#include <unordered_map> + +#include <CommonAPI/Struct.hpp> +#include <CommonAPI/Variant.hpp> +#include <CommonAPI/Types.hpp> + +namespace CommonAPI { + +template<class _Derived> +class TypeOutputStream { +public: + inline TypeOutputStream &writeType(const bool &_value) { + return get()->writeType(_value); + } + + inline TypeOutputStream &writeType(const int8_t &_value) { + return get()->writeType(_value); + } + + inline TypeOutputStream &writeType(const int16_t &_value) { + return get()->writeType(_value); + } + + inline TypeOutputStream &writeType(const int32_t &_value) { + return get()->writeType(_value); + } + + inline TypeOutputStream &writeType(const int64_t &_value) { + return get()->writeType(_value); + } + + inline TypeOutputStream &writeType(const uint8_t &_value) { + return get()->writeType(_value); + } + + inline TypeOutputStream &writeType(const uint16_t &_value) { + return get()->writeType(_value); + } + + inline TypeOutputStream &writeType(const uint32_t &_value) { + return get()->writeType(_value); + } + + inline TypeOutputStream &writeType(const uint64_t &_value) { + return get()->writeType(_value); + } + + inline TypeOutputStream &writeType(const float &_value) { + return get()->writeType(_value); + } + + inline TypeOutputStream &writeType(const double &_value) { + return get()->writeType(_value); + } + + inline TypeOutputStream &writeType(const std::string &_value) { + return get()->writeType(_value); + } + + template<typename _Type> + TypeOutputStream &writeType(const Enumeration<_Type> &_value) { + _Type tmpValue; + return get()->writeType(tmpValue); + } + + template<typename... _Types> + TypeOutputStream &writeType(const Struct<_Types...> &_value) { + return get()->writeType(_value); + } + + template<typename... _Types> + TypeOutputStream &writeType(const Variant<_Types...> &_value) { + return get()->writeType(_value); + } + + template<typename _ElementType> + TypeOutputStream &writeType(const std::vector<_ElementType> &_value) { + return get()->writeType(_value); + } + + template<typename _KeyType, typename _ValueType, typename _HasherType> + TypeOutputStream &writeType(const std::unordered_map<_KeyType, _ValueType, _HasherType> &_value) { + return get()->writeType(_value); + } + +private: + inline _Derived *get() { + return static_cast<_Derived *>(this); + } +}; + +template<class _Derived> +inline TypeOutputStream<_Derived> &operator<<(TypeOutputStream<_Derived> &_output, const bool &_value) { + return _output.writeType(_value); +} + +template<class _Derived> +inline TypeOutputStream<_Derived>& operator<<(TypeOutputStream<_Derived> &_output, const int8_t &_value) { + return _output.writeType(_value); +} + +template<class _Derived> +inline TypeOutputStream<_Derived>& operator<<(TypeOutputStream<_Derived> &_output, const int16_t &_value) { + return _output.writeType(_value); +} + +template<class _Derived> +inline TypeOutputStream<_Derived>& operator<<(TypeOutputStream<_Derived> &_output, const int32_t &_value) { + return _output.writeType(_value); +} + +template<class _Derived> +inline TypeOutputStream<_Derived>& operator<<(TypeOutputStream<_Derived> &_output, const int64_t &_value) { + return _output.writeType(_value); +} + +template<class _Derived> +inline TypeOutputStream<_Derived>& operator<<(TypeOutputStream<_Derived> &_output, const uint8_t &_value) { + return _output.writeType(_value); +} + +template<class _Derived> +inline TypeOutputStream<_Derived>& operator<<(TypeOutputStream<_Derived> &_output, const uint16_t &_value) { + return _output.writeType(_value); +} + +template<class _Derived> +inline TypeOutputStream<_Derived>& operator<<(TypeOutputStream<_Derived> &_output, const uint32_t &_value) { + return _output.writeType(_value); +} + +template<class _Derived> +inline TypeOutputStream<_Derived>& operator<<(TypeOutputStream<_Derived> &_output, const uint64_t &_value) { + return _output.writeType(_value); +} + +template<class _Derived> +inline TypeOutputStream<_Derived>& operator<<(TypeOutputStream<_Derived> &_output, const float &_value) { + return _output.writeType(_value); +} + +template<class _Derived> +inline TypeOutputStream<_Derived>& operator<<(TypeOutputStream<_Derived> &_output, const double &_value) { + return _output.writeType(_value); +} + +template<class _Derived> +inline TypeOutputStream<_Derived>& operator<<(TypeOutputStream<_Derived> &_output, const std::string &_value) { + return _output.writeType(_value); +} + +template<class _Derived, typename _Type, typename _TypeDepl> +inline TypeOutputStream<_Derived> &operator<<(TypeOutputStream<_Derived> &_output, const Deployable<_Type, _TypeDepl> &_value) { + return _output.writeType(_value.getValue()); +} + +template<class _Derived> +inline TypeOutputStream<_Derived>& operator<<(TypeOutputStream<_Derived> &_output, const Version &_value) { + return _output.writeType(_value); +} + +template<class _Derived, typename... _Types> +TypeOutputStream<_Derived> &operator<<(TypeOutputStream<_Derived> &_output, const Struct<_Types...> &_value) { + return _output.writeType(_value); +} + +template<class _Derived, typename... _Types> +TypeOutputStream<_Derived> &operator<<(TypeOutputStream<_Derived> &_output, const Variant<_Types...> &_value) { + return _output.writeType(_value); +} + +template<class _Derived, typename _ElementType> +TypeOutputStream<_Derived> &operator<<(TypeOutputStream<_Derived> &_output, const std::vector<_ElementType> &_value) { + return _output.writeType(_value); +} + +template<class _Derived, typename _KeyType, typename _ValueType, typename _HasherType> +TypeOutputStream<_Derived> &operator<<(TypeOutputStream<_Derived> &_output, + const std::unordered_map<_KeyType, _ValueType, _HasherType> &_value) { + return _output.writeType(_value); +} + +} // namespace CommonAPI + +#endif // COMMONAPI_TYPEOUTPUTSTREAM_HPP_ diff --git a/include/CommonAPI/Types.hpp b/include/CommonAPI/Types.hpp new file mode 100644 index 0000000..de1d85a --- /dev/null +++ b/include/CommonAPI/Types.hpp @@ -0,0 +1,116 @@ +// 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.h> can be included directly, this file may disappear or change contents." +#endif + +#ifndef COMMONAPI_TYPES_HPP_ +#define COMMONAPI_TYPES_HPP_ + +#include <cstdint> +#include <functional> +#include <unordered_set> +#include <memory> +#include <tuple> + +#include <CommonAPI/ByteBuffer.hpp> +#include <CommonAPI/ContainerUtils.hpp> +#include <CommonAPI/Event.hpp> +#include <CommonAPI/Export.hpp> +#include <CommonAPI/Version.hpp> + +#if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 1) +# define COMMONAPI_DEPRECATED __attribute__ ((__deprecated__)) +#elif defined(_MSC_VER) && (_MSC_VER >= 1300) +# define COMMONAPI_DEPRECATED __declspec(deprecated) +#else +# define COMMONAPI_DEPRECATED +#endif + + +#ifdef WIN32 +#define CCALL __cdecl +#pragma section(".CRT$XCU",read) +#define INITIALIZER(f) \ + static void __cdecl f(void); \ + __declspec(allocate(".CRT$XCU")) void(__cdecl*f##_)(void) = f; \ + static void __cdecl f(void) +#else +#define CCALL +#define INITIALIZER(f) \ + static void f(void) __attribute__((constructor)); \ + static void f(void) +#endif + +#ifdef WIN32 +#define usleep(micSec) \ + std::this_thread::sleep_for(std::chrono::microseconds(micSec)) +#endif + +namespace CommonAPI { + +enum class AvailabilityStatus { + UNKNOWN, + AVAILABLE, + NOT_AVAILABLE +}; + +enum class CallStatus { + SUCCESS, + OUT_OF_MEMORY, + NOT_AVAILABLE, + CONNECTION_FAILED, + REMOTE_ERROR, + UNKNOWN +}; + +typedef uint32_t CallId_t; +typedef std::string ConnectionId_t; +typedef int Timeout_t; // in ms, -1 means "forever" +typedef uint32_t Sender_t; + +/** + * \brief Identifies a client sending a call to a stub. + * + * The ClientId is used to identify the caller within a stub. + * The ClientId is supposed to be added by the middleware and can be compared using the == operator. + */ +class ClientId { +public: + virtual ~ClientId() { } + virtual bool operator==(ClientId& clientIdToCompare) = 0; + virtual std::size_t hashCode() = 0; +}; + +template <typename ... Args> +struct SelectiveBroadcastFunctorHelper { + typedef std::function<void(Args...)> SelectiveBroadcastFunctor; +}; + +typedef std::unordered_set< + std::shared_ptr<CommonAPI::ClientId>, + SharedPointerClientIdContentHash, + SharedPointerClientIdContentEqual +> ClientIdList; + +template<typename _EnumType> +class EnumHasher { +public: + size_t operator()(const _EnumType& testEnum) const { + return static_cast<int32_t>(testEnum); + } +}; + +// Type identifier for polymorphic structs +typedef uint32_t Serial; + +} // namespace CommonAPI + +#endif // COMMONAPI_TYPES_HPP_ + +#if defined(COMMONAPI_TYPES_LOCAL_INCLUDE) +#include COMMONAPI_TYPES_LOCAL_INCLUDE +#endif diff --git a/include/CommonAPI/Utils.hpp b/include/CommonAPI/Utils.hpp new file mode 100644 index 0000000..94891d5 --- /dev/null +++ b/include/CommonAPI/Utils.hpp @@ -0,0 +1,22 @@ +// 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_UTILS_HPP_ +#define COMMONAPI_UTILS_HPP_ + +#include <string> +#include <vector> + +#include <CommonAPI/Export.hpp> + +namespace CommonAPI { + +std::vector<std::string> COMMONAPI_EXPORT split(const std::string& s, char delim); +void COMMONAPI_EXPORT trim(std::string &_s); + + +} //namespace CommonAPI + +#endif /* COMMONAPI_UTILS_HPP_ */ diff --git a/include/CommonAPI/Variant.hpp b/include/CommonAPI/Variant.hpp new file mode 100644 index 0000000..d7b1088 --- /dev/null +++ b/include/CommonAPI/Variant.hpp @@ -0,0 +1,746 @@ +// 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/. + +#include <cassert> +#include <cstdint> +#include <iostream> +#include <memory> +#include <string> +#include <tuple> +#include <type_traits> + +#if !defined (COMMONAPI_INTERNAL_COMPILATION) +#error "Only <CommonAPI/CommonAPI.h> can be included directly, this file may disappear or change contents." +#endif + +#include <CommonAPI/Deployable.hpp> +#include <CommonAPI/Deployment.hpp> + +#ifndef COMMONAPI_VARIANT_HPP_ +#define COMMONAPI_VARIANT_HPP_ + +namespace CommonAPI { + +template<class _Derived> +class InputStream; + +template<class _Derived> +class OutputStream; + +template<typename... _Types> +struct MaxSize; + +template<> +struct MaxSize<> { + static const unsigned int value = 0; +}; + +template<typename _Type, typename... _Types> +struct MaxSize<_Type, _Types...> { + static const unsigned int current_type_size = sizeof(_Type); + static const unsigned int next_type_size = MaxSize<_Types...>::value; + static const unsigned int value = + current_type_size > next_type_size ? + current_type_size : next_type_size; +}; + +template<typename _SearchType, typename... _RestTypes> +struct VariantTypeSelector; + +template<typename _SearchType, typename... _RestTypes> +struct VariantTypeSelector<_SearchType, _SearchType, _RestTypes...> { + typedef _SearchType type; +}; + +/** + * \brief A templated generic variant class which provides type safe access and operators + * + * A templated generic variant class which provides type safe access and operators + */ +template<typename... _Types> +class Variant { +private: + typedef std::tuple_size<std::tuple<_Types...>> TypesTupleSize; + +public: + + static const unsigned int maxSize = MaxSize<_Types...>::value; + + /** + * \brief Construct an empty variant + * + * Construct an empty variant + */ + Variant(); + + + /** + * \brief Copy constructor. Must have identical templates. + * + * Copy constructor. Must have identical templates. + * + * @param _source Variant to copy + */ + Variant(const Variant &_source); + + /** + * \brief Copy constructor. Must have identical templates. + * + * Copy constructor. Must have identical templates. + * + * @param _source Variant to copy + */ + Variant(Variant &&_source); + + ~Variant(); + + /** + * \brief Assignment of another variant. Must have identical templates. + * + * Assignment of another variant. Must have identical templates. + * + * @param _source Variant to assign + */ + Variant &operator=(const Variant &_source); + /** + * \brief Assignment of another variant. Must have identical templates. + * + * Assignment of another variant. Must have identical templates. + * + * @param _source Variant to assign + */ + Variant &operator=(Variant &&_source); + + /** + * \brief Assignment of a contained type. Must be one of the valid templated types. + * + * Assignment of a contained type. Must be one of the valid templated types. + * + * @param _value Value to assign + */ + template<typename _Type> + typename std::enable_if<!std::is_same<_Type, Variant<_Types...>>::value, Variant<_Types...>&>::type + operator=(const _Type &_value); + + /** + * \brief Equality of another variant. Must have identical template list and content. + * + * Equality of another variant. Must have identical template list and content. + * + * @param _other Variant to compare + */ + bool operator==(const Variant<_Types...> &_other) const; + + /** + * \brief Not-Equality of another variant. Must have identical template list and content. + * + * Not-Equality of another variant. Must have identical template list and content. + * + * @param _other Variant to compare + */ + bool operator!=(const Variant<_Types...> &_other) const; + + /** + * \brief Testif the contained type is the same as the template on this method. + * + * Testif the contained type is the same as the template on this method. + * + * @return Is same type + */ + template<typename _Type> + const bool isType() const; + + /** + * \brief Construct variant with content type set to value. + * + * Construct variant with content type set to value. + * + * @param _value Value to place + */ + template<typename _Type> + Variant(const _Type &_value, + typename std::enable_if<!std::is_const<_Type>::value>::type* = 0, + typename std::enable_if<!std::is_reference<_Type>::value>::type* = 0, + typename std::enable_if<!std::is_same<_Type, Variant>::value>::type* = 0); + + /** + * \brief Construct variant with content type set to value. + * + * Construct variant with content type set to value. + * + * @param _value Value to place + */ + template<typename _Type> + Variant(_Type &&_value, + typename std::enable_if<!std::is_const<_Type>::value>::type* = 0, + typename std::enable_if<!std::is_reference<_Type>::value>::type* = 0, + typename std::enable_if<!std::is_same<_Type, Variant>::value>::type* = 0); + + /** + * \brief Get value of variant, template to content type. Throws exception if type is not contained. + * + * Get value of variant, template to content type. Throws exception if type is not contained. + */ + template<typename _Type> + const _Type &get() const; + + /** + * \brief Get index in template list of type actually contained, starting at 1 at the end of the template list + * + * Get index in template list of type actually contained, starting at 1 at the end of the template list + * + * @return Index of contained type + */ + uint8_t getValueType() const { + return valueType_; + } + +private: + template<typename _Type> + void set(const _Type &_value, const bool clear); + + template<typename _Type> + void set(_Type &&_value, const bool clear); + + template<typename _FriendType> + friend struct TypeWriter; + template<typename ... _FriendTypes> + friend struct AssignmentVisitor; + template<typename _FriendType> + friend struct TypeEqualsVisitor; + template<typename ... _FriendTypes> + friend struct PartialEqualsVisitor; + template<class _Derived, typename ... _FriendTypes> + friend struct InputStreamReadVisitor; + template<class Variant, typename ... _FTypes> + friend struct ApplyVoidIndexVisitor; + +public: + inline bool hasValue() const { + return (valueType_ < TypesTupleSize::value); + } + typename std::aligned_storage<maxSize>::type valueStorage_; + + uint8_t valueType_; +}; + +template<class _Variant, typename... _Types> +struct ApplyVoidIndexVisitor; + +template<class _Variant> +struct ApplyVoidIndexVisitor<_Variant> { + static const uint8_t index = 0; + + static + void visit(_Variant &, uint8_t &) { + assert(false); + } +}; + +template<class _Variant, typename _Type, typename... _Types> +struct ApplyVoidIndexVisitor<_Variant, _Type, _Types...> { + static const uint8_t index + = ApplyVoidIndexVisitor<_Variant, _Types...>::index + 1; + + static void visit(_Variant &_variant, uint8_t &_index) { + if (index == _index) { + new (&_variant.valueStorage_) _Type(); + _variant.valueType_ = index; + } else { + ApplyVoidIndexVisitor< + _Variant, _Types... + >::visit(_variant, _index); + } + } +}; + +template<class _Visitor, class _Variant, typename... _Types> +struct ApplyVoidVisitor; + +template<class _Visitor, class _Variant> +struct ApplyVoidVisitor<_Visitor, _Variant> { + static const uint8_t index = 0; + + static + void visit(_Visitor &, _Variant &) { + assert(false); + } + + static + void visit(_Visitor &, const _Variant &) { + assert(false); + } +}; + +template<class _Visitor, class _Variant, typename _Type, typename ... _Types> +struct ApplyVoidVisitor<_Visitor, _Variant, _Type, _Types...> { + static const uint8_t index + = ApplyVoidVisitor<_Visitor, _Variant, _Types...>::index + 1; + + static void visit(_Visitor &_visitor, _Variant &_variant) { + if (_variant.getValueType() == index) { + _visitor(_variant.template get<_Type>()); + } else { + ApplyVoidVisitor< + _Visitor, _Variant, _Types... + >::visit(_visitor, _variant); + } + } + + static void visit(_Visitor &_visitor, const _Variant &_variant) { + if (_variant.getValueType() == index) { + _visitor(_variant.template get<_Type>()); + } else { + ApplyVoidVisitor< + _Visitor, _Variant, _Types... + >::visit(_visitor, _variant); + } + } +}; + +template<class _Visitor, class _Variant, typename ... _Types> +struct ApplyBoolVisitor; + +template<class _Visitor, class _Variant> +struct ApplyBoolVisitor<_Visitor, _Variant> { + static const uint8_t index = 0; + + static bool visit(_Visitor &, _Variant &) { + assert(false); + return false; + } +}; + +template<class _Visitor, class _Variant, typename _Type, typename ... _Types> +struct ApplyBoolVisitor<_Visitor, _Variant, _Type, _Types...> { + static const uint8_t index + = ApplyBoolVisitor<_Visitor, _Variant, _Types...>::index + 1; + + static bool visit(_Visitor &_visitor, _Variant &_variant) { + if (_variant.getValueType() == index) { + return _visitor(_variant.template get<_Type>()); + } else { + return ApplyBoolVisitor< + _Visitor, _Variant, _Types... + >::visit(_visitor, _variant); + } + } +}; + +template<class _Visitor, class _Variant, class _Deployment, typename ... _Types> +struct ApplyStreamVisitor; + +template<class _Visitor, class _Variant, class _Deployment> +struct ApplyStreamVisitor<_Visitor, _Variant, _Deployment> { + static const uint8_t index = 0; + + static + void visit(_Visitor &, _Variant &, const _Deployment *) { + assert(false); + } + + static + void visit(_Visitor &, const _Variant &, const _Deployment *) { + assert(false); + } +}; + +template<class _Visitor, class _Variant, class _Deployment, typename _Type, typename ... _Types> +struct ApplyStreamVisitor<_Visitor, _Variant, _Deployment, _Type, _Types...> { + static const uint8_t index + = ApplyStreamVisitor<_Visitor, _Variant, _Deployment, _Types...>::index + 1; + + static void visit(_Visitor &_visitor, _Variant &_variant, const _Deployment *_depl) { + if (_variant.getValueType() == index) { + _visitor(_variant.template get<_Type>(), + (_depl ? std::get<std::tuple_size<decltype(_depl->values_)>::value-index>(_depl->values_) + : nullptr)); + } else { + ApplyStreamVisitor< + _Visitor, _Variant, _Deployment, _Types... + >::visit(_visitor, _variant, _depl); + } + } + + static void visit(_Visitor &_visitor, const _Variant &_variant, const _Deployment *_depl) { + if (_variant.getValueType() == index) { + _visitor(_variant.template get<_Type>(), + (_depl ? std::get<std::tuple_size<decltype(_depl->values_)>::value-index>(_depl->values_) + : nullptr)); + } else { + ApplyStreamVisitor< + _Visitor, _Variant, _Deployment, _Types... + >::visit(_visitor, _variant, _depl); + } + } +}; + +template<uint32_t _Size> +struct DeleteVisitor { +public: + DeleteVisitor(typename std::aligned_storage<_Size>::type &_storage) + : storage_(_storage) { + } + + template<typename _Type> + void operator()(const _Type &) const { + (reinterpret_cast<const _Type *>(&storage_))->~_Type(); + } + +private: + typename std::aligned_storage<_Size>::type &storage_; +}; + +template<class _Derived> +struct OutputStreamWriteVisitor { +public: + OutputStreamWriteVisitor(OutputStream<_Derived> &_output) + : output_(_output) { + } + + template<typename _Type, typename _Deployment = EmptyDeployment> + void operator()(const _Type &_value, const _Deployment *_depl = nullptr) const { + Deployable<_Type, _Deployment> itsValue(_value, _depl); + output_ << itsValue; + } + +private: + OutputStream<_Derived> &output_; +}; + +template<class _Derived, typename ... _Types> +struct InputStreamReadVisitor { +public: + InputStreamReadVisitor(InputStream<_Derived> &_input, Variant<_Types...> &_target) + : input_(_input), target_(_target) { + } + + template<typename _Type, typename _Deployment = EmptyDeployment> + void operator()(const _Type &_value, const _Deployment *_depl = nullptr) { + Deployable<_Type, _Deployment> itsValue(_depl); + input_ >> itsValue; + target_.Variant<_Types...>::template set<_Type>(std::move(itsValue.getValue()), false); + } + +private: + InputStream<_Derived> &input_; + Variant<_Types...> &target_; +}; + +template<class _Derived> +struct TypeOutputStreamWriteVisitor { +public: + TypeOutputStreamWriteVisitor(_Derived &_output) + : output_(_output) { + } + + template<typename _Type> + void operator()(const _Type &_value) const { + output_ << _value; + } + +private: + _Derived &output_; +}; + +template<typename _Type> +struct TypeEqualsVisitor +{ +public: + TypeEqualsVisitor(const _Type &_me) + : me_(_me) { + } + + bool operator()(const _Type &_other) const { + return (me_ == _other); + } + + template<typename _OtherType> + bool operator()(const _OtherType &) const { + return false; + } + +private: + const _Type& me_; +}; + +template<typename ... _Types> +struct PartialEqualsVisitor +{ +public: + PartialEqualsVisitor(const Variant<_Types...> &_me) + : me_(_me) { + } + + template<typename _Type> + bool operator()(const _Type &_other) const { + TypeEqualsVisitor<_Type> visitor(_other); + return ApplyBoolVisitor< + TypeEqualsVisitor<_Type>, const Variant<_Types...>, _Types... + >::visit(visitor, me_); + } + +private: + const Variant<_Types...> &me_; +}; + +template<typename ... _Types> +struct AssignmentVisitor { +public: + AssignmentVisitor(Variant<_Types...> &_me, const bool _clear = true) + : me_(_me), clear_(_clear) { + } + + template<typename _Type> + void operator()(const _Type &_value) const { + me_.Variant<_Types...>::template set<_Type>(_value, clear_); + } + + template<typename _Type> + void operator()(_Type &_value) const { + me_.Variant<_Types...>::template set<_Type>(_value, clear_); + } + +private: + Variant<_Types...> &me_; + const bool clear_; +}; + +template<typename... _Types> +struct TypeSelector; + +template<typename _Type> +struct TypeSelector<_Type> { +}; + +template<typename _Type, typename... _Types> +struct TypeSelector<_Type, _Type, _Types...> { + typedef _Type type; +}; + +template<typename _Type, typename... _Types> +struct TypeSelector<_Type, _Type &, _Types...> { + typedef _Type& type; +}; + +template<typename _Type, typename... _Types> +struct TypeSelector<_Type &, _Type, _Types...> { + typedef _Type type; +}; + +template<typename _Type, typename... _Types> +struct TypeSelector<_Type, const _Type &, _Types...> { + typedef const _Type &type; +}; + +template<typename _Type, typename... _Types> +struct TypeSelector<const _Type&, _Type, _Types...> { + typedef _Type type; +}; + +template<typename _Type, typename... _Types> +struct TypeSelector<_Type*, const _Type*, _Types...> { + typedef const _Type *type; +}; + +template<typename _Type, typename... _Types> +struct TypeSelector<_Type &, const _Type &, _Types...> { + typedef const _Type &type; +}; + +template<typename _U, typename _Type, typename... _Types> +struct TypeSelector<_U, _Type, _Types...> { + typedef typename TypeSelector<_U, _Types...>::type type; +}; + +template<typename... _Types> +struct TypeIndex; + +template<> +struct TypeIndex<> { + static const uint8_t index = 0; + + template<typename _U> + static uint8_t get() { + return 0; + } +}; + +template<typename _Type, typename ... _Types> +struct TypeIndex<_Type, _Types...> { + static const uint8_t index = TypeIndex<_Types...>::index + 1; + + template<typename _U> + static uint8_t get(typename std::enable_if<std::is_same<_Type, _U>::value>::type* = 0) { + return index; + } + + template<typename _U> + static uint8_t get(typename std::enable_if<!std::is_same<_Type, _U>::value>::type* = 0) { + return TypeIndex<_Types...>::template get<_U>(); + } +}; + +template<typename... _Types> +Variant<_Types...>::Variant() + : valueType_(TypesTupleSize::value) { + ApplyVoidIndexVisitor<Variant<_Types...>, _Types...>::visit(*this, valueType_); +} + +template<typename... _Types> +Variant<_Types...>::Variant(const Variant &_source) { + AssignmentVisitor<_Types...> visitor(*this, false); + ApplyVoidVisitor< + AssignmentVisitor<_Types...> , Variant<_Types...>, _Types... + >::visit(visitor, _source); +} + +template<typename... _Types> +Variant<_Types...>::Variant(Variant &&_source) +{ + AssignmentVisitor<_Types...> visitor(*this, false); + ApplyVoidVisitor< + AssignmentVisitor<_Types...> , Variant<_Types...>, _Types... + >::visit(visitor, _source); +} + +template<typename... _Types> +Variant<_Types...>::~Variant() { + if (hasValue()) { + DeleteVisitor<maxSize> visitor(valueStorage_); + ApplyVoidVisitor< + DeleteVisitor<maxSize>, Variant<_Types...>, _Types... + >::visit(visitor, *this); + } +} + +template<typename... _Types> +Variant<_Types...>& Variant<_Types...>::operator=(const Variant<_Types...> &_source) { + AssignmentVisitor<_Types...> visitor(*this, hasValue()); + ApplyVoidVisitor< + AssignmentVisitor<_Types...>, Variant<_Types...>, _Types... + >::visit(visitor, _source); + return *this; +} + +template<typename... _Types> +Variant<_Types...>& Variant<_Types...>::operator=(Variant<_Types...> &&_source) { + AssignmentVisitor<_Types...> visitor(*this, hasValue()); + ApplyVoidVisitor< + AssignmentVisitor<_Types...>, Variant<_Types...>, _Types... + >::visit(visitor, _source); + return *this; +} + +template<typename ... _Types> +template<typename _Type> +typename std::enable_if<!std::is_same<_Type, Variant<_Types...>>::value, Variant<_Types...>&>::type +Variant<_Types...>::operator=(const _Type &_value) { + set<typename TypeSelector<_Type, _Types...>::type>(_value, hasValue()); + return *this; +} + +template<typename ... _Types> +template<typename _Type> +const bool Variant<_Types...>::isType() const { + typedef typename TypeSelector<_Type, _Types...>::type selected_type_t; + uint8_t itsType = TypeIndex<_Types...>::template get<selected_type_t>(); + if (itsType == valueType_) { + return true; + } else { + return false; + } +} + +template<typename ... _Types> +template<typename _Type> +Variant<_Types...>::Variant(const _Type &_value, + typename std::enable_if<!std::is_const<_Type>::value>::type*, + typename std::enable_if<!std::is_reference<_Type>::value>::type*, + typename std::enable_if<!std::is_same<_Type, Variant<_Types...>>::value>::type*) { + set<typename TypeSelector<_Type, _Types...>::type>(_value, false); +} + +template<typename ... _Types> +template<typename _Type> +Variant<_Types...>::Variant(_Type &&_value, +typename std::enable_if<!std::is_const<_Type>::value>::type*, +typename std::enable_if<!std::is_reference<_Type>::value>::type*, +typename std::enable_if<!std::is_same<_Type, Variant<_Types...>>::value>::type*) { + set<typename TypeSelector<_Type, _Types...>::type>(std::move(_value), false); +} + + +template<typename ... _Types> +template<typename _Type> +const _Type & Variant<_Types...>::get() const { + typedef typename TypeSelector<_Type, _Types...>::type selected_type_t; + uint8_t itsType = TypeIndex<_Types...>::template get<selected_type_t>(); + if (itsType == valueType_) { + return *(reinterpret_cast<const _Type *>(&valueStorage_)); + } else { +#ifdef __EXCEPTIONS + std::bad_cast toThrow; + throw toThrow; +#else + printf("SerializableVariant.hpp:%i %s: Incorrect access to variant; attempting to get type not currently contained", __LINE__, __FUNCTION__); + abort(); +#endif + } +} + + +template<typename ... _Types> +template<typename _U> +void Variant<_Types...>::set(const _U &_value, const bool _clear) { + typedef typename TypeSelector<_U, _Types...>::type selected_type_t; + + if (_clear) { + DeleteVisitor<maxSize> visitor(valueStorage_); + ApplyVoidVisitor< + DeleteVisitor<maxSize>, Variant<_Types...>, _Types... + >::visit(visitor, *this); + } + new (&valueStorage_) selected_type_t(std::move(_value)); + valueType_ = TypeIndex<_Types...>::template get<selected_type_t>(); +} + +template<typename ... _Types> +template<typename _U> +void Variant<_Types...>::set(_U &&_value, const bool _clear) { + typedef typename TypeSelector<_U, _Types...>::type selected_type_t; + + selected_type_t&& any_container_value = std::move(_value); + if(_clear) + { + DeleteVisitor<maxSize> visitor(valueStorage_); + ApplyVoidVisitor< + DeleteVisitor<maxSize>, Variant<_Types...>, _Types... + >::visit(visitor, *this); + } else { + new (&valueStorage_) selected_type_t(std::move(any_container_value)); + } + + valueType_ = TypeIndex<_Types...>::template get<selected_type_t>(); +} + +template<typename ... _Types> +bool Variant<_Types...>::operator==(const Variant<_Types...> &_other) const +{ + PartialEqualsVisitor<_Types...> visitor(*this); + return ApplyBoolVisitor< + PartialEqualsVisitor<_Types...>, const Variant<_Types...>, _Types... + >::visit(visitor, _other); +} + +template<typename ... _Types> +bool Variant<_Types...>::operator!=(const Variant<_Types...> &_other) const +{ + return !(*this == _other); +} + +} // namespace CommonAPI + +#endif // COMMONAPI_VARIANT_HPP_ diff --git a/include/CommonAPI/Version.hpp b/include/CommonAPI/Version.hpp new file mode 100644 index 0000000..97534b0 --- /dev/null +++ b/include/CommonAPI/Version.hpp @@ -0,0 +1,29 @@ +// 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 + +#ifndef COMMONAPI_VERSION_HPP_ +#define COMMONAPI_VERSION_HPP_ + +#include <cstdint> + +namespace CommonAPI { + +struct Version { + Version() = default; + Version(const uint32_t &majorValue, const uint32_t &minorValue) + : Major(majorValue), Minor(minorValue) { + } + + uint32_t Major; + uint32_t Minor; +}; + +} // namespace CommonAPI + +#endif // COMMONAPI_STRUCT_HPP_ |