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

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