Device interface library for multiple platforms including Mbed.
Dependents: DeepCover Embedded Security in IoT MaximInterface MAXREFDES155#
Maxim Interface is a library framework focused on providing flexible and expressive hardware interfaces. Both communication interfaces such as I2C and 1-Wire and device interfaces such as DS18B20 are supported. Modern C++ concepts are used extensively while keeping compatibility with C++98/C++03 and requiring no external dependencies. The embedded-friendly design does not depend on exceptions or RTTI.
The full version of the project is hosted on GitLab: https://gitlab.com/iabenz/MaximInterface
Diff: Utilities/Function.hpp
- Revision:
- 5:a8c83a2e6fa4
- Parent:
- 0:f77ad7f72d04
- Child:
- 6:471901a04573
--- a/Utilities/Function.hpp Fri Jan 19 10:25:02 2018 -0600 +++ b/Utilities/Function.hpp Wed Jan 23 13:11:04 2019 -0600 @@ -34,6 +34,7 @@ #define MaximInterface_Function #include <stddef.h> +#include "SafeBool.hpp" #include "type_traits.hpp" // Include for std::swap. @@ -70,7 +71,9 @@ private: char data[TypeSize]; - long double aligner; + long double aligner1; + long int aligner2; + void * aligner3; }; // Computes the internal target size for TypeStorage based on a desired total @@ -80,7 +83,9 @@ template <typename Target, size_t totalSize> class TypeWrapperTotalSize { private: typedef TypeStorage<Target, 1> MinSizeStorage; + static const size_t otherDataSize = sizeof(Target *); + // Round down to be a multiple of alignment_of<MinSizeTargetStorage>::value. static const size_t internalTargetRawSize = (totalSize - otherDataSize) / alignment_of<MinSizeStorage>::value * @@ -267,10 +272,12 @@ void swap(Function & other) { callableWrapper.swap(other.callableWrapper); } - operator bool() const { return callableWrapper.target() != NULL; } + operator SafeBool() const { + return makeSafeBool(callableWrapper.target() != NULL); + } ResultType operator()() const { - return callableWrapper.target() ? (*callableWrapper.target())() + return callableWrapper.target() ? callableWrapper.target()->invoke() : ResultType(); } @@ -278,7 +285,7 @@ class Callable { public: virtual ~Callable() {} - virtual ResultType operator()() const = 0; + virtual ResultType invoke() const = 0; virtual Callable * clone() const = 0; virtual void clone(void * buffer) const = 0; }; @@ -287,7 +294,7 @@ public: CallableAdapter(F func) : func(func) {} - virtual ResultType operator()() const { return func(); } + virtual ResultType invoke() const { return func(); } virtual Callable * clone() const { return new CallableAdapter(*this); } @@ -338,10 +345,12 @@ void swap(Function & other) { callableWrapper.swap(other.callableWrapper); } - operator bool() const { return callableWrapper.target() != NULL; } + operator SafeBool() const { + return makeSafeBool(callableWrapper.target() != NULL); + } ResultType operator()(ArgumentType arg) const { - return callableWrapper.target() ? (*callableWrapper.target())(arg) + return callableWrapper.target() ? callableWrapper.target()->invoke(arg) : ResultType(); } @@ -349,7 +358,7 @@ class Callable { public: virtual ~Callable() {} - virtual ResultType operator()(ArgumentType) const = 0; + virtual ResultType invoke(ArgumentType) const = 0; virtual Callable * clone() const = 0; virtual void clone(void * buffer) const = 0; }; @@ -358,7 +367,7 @@ public: CallableAdapter(F func) : func(func) {} - virtual ResultType operator()(ArgumentType arg) const { return func(arg); } + virtual ResultType invoke(ArgumentType arg) const { return func(arg); } virtual Callable * clone() const { return new CallableAdapter(*this); } @@ -414,19 +423,21 @@ void swap(Function & other) { callableWrapper.swap(other.callableWrapper); } - operator bool() const { return callableWrapper.target() != NULL; } + operator SafeBool() const { + return makeSafeBool(callableWrapper.target() != NULL); + } ResultType operator()(FirstArgumentType arg1, SecondArgumentType arg2) const { - return callableWrapper.target() ? (*callableWrapper.target())(arg1, arg2) - : ResultType(); + return callableWrapper.target() + ? callableWrapper.target()->invoke(arg1, arg2) + : ResultType(); } private: class Callable { public: virtual ~Callable() {} - virtual ResultType operator()(FirstArgumentType, - SecondArgumentType) const = 0; + virtual ResultType invoke(FirstArgumentType, SecondArgumentType) const = 0; virtual Callable * clone() const = 0; virtual void clone(void * buffer) const = 0; }; @@ -435,8 +446,8 @@ public: CallableAdapter(F func) : func(func) {} - virtual ResultType operator()(FirstArgumentType arg1, - SecondArgumentType arg2) const { + virtual ResultType invoke(FirstArgumentType arg1, + SecondArgumentType arg2) const { return func(arg1, arg2); } @@ -461,6 +472,94 @@ lhs.swap(rhs); } +// Function implementation for three argument functions. +template <typename FirstArgumentType, typename SecondArgumentType, + typename ThirdArgumentType, typename ResultType> +class Function<ResultType(FirstArgumentType, SecondArgumentType, + ThirdArgumentType)> { +public: + typedef ResultType result_type; + + Function(ResultType (*func)(FirstArgumentType, SecondArgumentType, + ThirdArgumentType) = NULL) + : callableWrapper() { + if (func) { + callableWrapper = func; + } + } + + template <typename F> Function(F func) : callableWrapper(func) {} + + const Function & operator=(ResultType (*func)(FirstArgumentType, + SecondArgumentType, + ThirdArgumentType)) { + if (func) { + callableWrapper = func; + } else { + callableWrapper.clear(); + } + return *this; + } + + template <typename F> const Function & operator=(F func) { + callableWrapper = func; + return *this; + } + + void swap(Function & other) { callableWrapper.swap(other.callableWrapper); } + + operator SafeBool() const { + return makeSafeBool(callableWrapper.target() != NULL); + } + + ResultType operator()(FirstArgumentType arg1, SecondArgumentType arg2, + ThirdArgumentType arg3) const { + return callableWrapper.target() + ? callableWrapper.target()->invoke(arg1, arg2, arg3) + : ResultType(); + } + +private: + class Callable { + public: + virtual ~Callable() {} + virtual ResultType invoke(FirstArgumentType, SecondArgumentType, + ThirdArgumentType) const = 0; + virtual Callable * clone() const = 0; + virtual void clone(void * buffer) const = 0; + }; + + template <typename F> class CallableAdapter : public Callable { + public: + CallableAdapter(F func) : func(func) {} + + virtual ResultType invoke(FirstArgumentType arg1, SecondArgumentType arg2, + ThirdArgumentType arg3) const { + return func(arg1, arg2, arg3); + } + + virtual Callable * clone() const { return new CallableAdapter(*this); } + + virtual void clone(void * buffer) const { + new (buffer) CallableAdapter(*this); + } + + private: + F func; + }; + + detail::TypeWrapper<Callable, CallableAdapter> callableWrapper; +}; + +template <typename FirstArgumentType, typename SecondArgumentType, + typename ThirdArgumentType, typename ResultType> +inline void swap(Function<ResultType(FirstArgumentType, SecondArgumentType, + ThirdArgumentType)> & lhs, + Function<ResultType(FirstArgumentType, SecondArgumentType, + ThirdArgumentType)> & rhs) { + lhs.swap(rhs); +} + } // namespace MaximInterface #endif