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

Committer:
IanBenzMaxim
Date:
Mon Jul 22 11:44:07 2019 -0500
Revision:
7:9cd16581b578
Child:
8:5ea891c7d1a1
Updated to version 1.9.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
IanBenzMaxim 7:9cd16581b578 1 /*******************************************************************************
IanBenzMaxim 7:9cd16581b578 2 * Copyright (C) 2017 Maxim Integrated Products, Inc., All Rights Reserved.
IanBenzMaxim 7:9cd16581b578 3 *
IanBenzMaxim 7:9cd16581b578 4 * Permission is hereby granted, free of charge, to any person obtaining a
IanBenzMaxim 7:9cd16581b578 5 * copy of this software and associated documentation files (the "Software"),
IanBenzMaxim 7:9cd16581b578 6 * to deal in the Software without restriction, including without limitation
IanBenzMaxim 7:9cd16581b578 7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
IanBenzMaxim 7:9cd16581b578 8 * and/or sell copies of the Software, and to permit persons to whom the
IanBenzMaxim 7:9cd16581b578 9 * Software is furnished to do so, subject to the following conditions:
IanBenzMaxim 7:9cd16581b578 10 *
IanBenzMaxim 7:9cd16581b578 11 * The above copyright notice and this permission notice shall be included
IanBenzMaxim 7:9cd16581b578 12 * in all copies or substantial portions of the Software.
IanBenzMaxim 7:9cd16581b578 13 *
IanBenzMaxim 7:9cd16581b578 14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
IanBenzMaxim 7:9cd16581b578 15 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
IanBenzMaxim 7:9cd16581b578 16 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IanBenzMaxim 7:9cd16581b578 17 * IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
IanBenzMaxim 7:9cd16581b578 18 * OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
IanBenzMaxim 7:9cd16581b578 19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
IanBenzMaxim 7:9cd16581b578 20 * OTHER DEALINGS IN THE SOFTWARE.
IanBenzMaxim 7:9cd16581b578 21 *
IanBenzMaxim 7:9cd16581b578 22 * Except as contained in this notice, the name of Maxim Integrated
IanBenzMaxim 7:9cd16581b578 23 * Products, Inc. shall not be used except as stated in the Maxim Integrated
IanBenzMaxim 7:9cd16581b578 24 * Products, Inc. Branding Policy.
IanBenzMaxim 7:9cd16581b578 25 *
IanBenzMaxim 7:9cd16581b578 26 * The mere transfer of this software does not imply any licenses
IanBenzMaxim 7:9cd16581b578 27 * of trade secrets, proprietary technology, copyrights, patents,
IanBenzMaxim 7:9cd16581b578 28 * trademarks, maskwork rights, or any other form of intellectual
IanBenzMaxim 7:9cd16581b578 29 * property whatsoever. Maxim Integrated Products, Inc. retains all
IanBenzMaxim 7:9cd16581b578 30 * ownership rights.
IanBenzMaxim 7:9cd16581b578 31 *******************************************************************************/
IanBenzMaxim 7:9cd16581b578 32
IanBenzMaxim 7:9cd16581b578 33 #ifndef MaximInterfaceCore_Function
IanBenzMaxim 7:9cd16581b578 34 #define MaximInterfaceCore_Function
IanBenzMaxim 7:9cd16581b578 35
IanBenzMaxim 7:9cd16581b578 36 #include <stddef.h>
IanBenzMaxim 7:9cd16581b578 37 #include "SafeBool.hpp"
IanBenzMaxim 7:9cd16581b578 38 #include "type_traits.hpp"
IanBenzMaxim 7:9cd16581b578 39
IanBenzMaxim 7:9cd16581b578 40 // Include for std::swap.
IanBenzMaxim 7:9cd16581b578 41 #include <algorithm>
IanBenzMaxim 7:9cd16581b578 42 #include <utility>
IanBenzMaxim 7:9cd16581b578 43
IanBenzMaxim 7:9cd16581b578 44 namespace MaximInterfaceCore {
IanBenzMaxim 7:9cd16581b578 45 namespace detail {
IanBenzMaxim 7:9cd16581b578 46
IanBenzMaxim 7:9cd16581b578 47 // Provides char buffer storage for a given type.
IanBenzMaxim 7:9cd16581b578 48 // Suitability of alignment for type should be verified with alignment_of.
IanBenzMaxim 7:9cd16581b578 49 template <typename Type, size_t TypeSize> union TypeStorage {
IanBenzMaxim 7:9cd16581b578 50 public:
IanBenzMaxim 7:9cd16581b578 51 operator const Type *() const { return reinterpret_cast<const Type *>(data); }
IanBenzMaxim 7:9cd16581b578 52
IanBenzMaxim 7:9cd16581b578 53 operator Type *() {
IanBenzMaxim 7:9cd16581b578 54 return const_cast<Type *>(
IanBenzMaxim 7:9cd16581b578 55 static_cast<const Type *>(static_cast<const TypeStorage &>(*this)));
IanBenzMaxim 7:9cd16581b578 56 }
IanBenzMaxim 7:9cd16581b578 57
IanBenzMaxim 7:9cd16581b578 58 const Type & operator*() const { return **this; }
IanBenzMaxim 7:9cd16581b578 59
IanBenzMaxim 7:9cd16581b578 60 Type & operator*() {
IanBenzMaxim 7:9cd16581b578 61 return const_cast<Type &>(
IanBenzMaxim 7:9cd16581b578 62 static_cast<const TypeStorage &>(*this).operator*());
IanBenzMaxim 7:9cd16581b578 63 }
IanBenzMaxim 7:9cd16581b578 64
IanBenzMaxim 7:9cd16581b578 65 const Type * operator->() const { return *this; }
IanBenzMaxim 7:9cd16581b578 66
IanBenzMaxim 7:9cd16581b578 67 Type * operator->() {
IanBenzMaxim 7:9cd16581b578 68 return const_cast<Type *>(
IanBenzMaxim 7:9cd16581b578 69 static_cast<const TypeStorage &>(*this).operator->());
IanBenzMaxim 7:9cd16581b578 70 }
IanBenzMaxim 7:9cd16581b578 71
IanBenzMaxim 7:9cd16581b578 72 private:
IanBenzMaxim 7:9cd16581b578 73 char data[TypeSize];
IanBenzMaxim 7:9cd16581b578 74 long double aligner1;
IanBenzMaxim 7:9cd16581b578 75 long int aligner2;
IanBenzMaxim 7:9cd16581b578 76 void * aligner3;
IanBenzMaxim 7:9cd16581b578 77 };
IanBenzMaxim 7:9cd16581b578 78
IanBenzMaxim 7:9cd16581b578 79 // Computes the internal target size for TypeStorage based on a desired total
IanBenzMaxim 7:9cd16581b578 80 // size. No internal storage will be allocated if the requested size is smaller
IanBenzMaxim 7:9cd16581b578 81 // than the required data elements of TypeWrapper or if the requested size is
IanBenzMaxim 7:9cd16581b578 82 // smaller than minimum size of TypeStorage.
IanBenzMaxim 7:9cd16581b578 83 template <typename Target, size_t totalSize> class TypeWrapperTotalSize {
IanBenzMaxim 7:9cd16581b578 84 private:
IanBenzMaxim 7:9cd16581b578 85 typedef TypeStorage<Target, 1> MinSizeStorage;
IanBenzMaxim 7:9cd16581b578 86
IanBenzMaxim 7:9cd16581b578 87 static const size_t otherDataSize = sizeof(Target *);
IanBenzMaxim 7:9cd16581b578 88
IanBenzMaxim 7:9cd16581b578 89 // Round down to be a multiple of alignment_of<MinSizeTargetStorage>::value.
IanBenzMaxim 7:9cd16581b578 90 static const size_t internalTargetRawSize =
IanBenzMaxim 7:9cd16581b578 91 (totalSize - otherDataSize) / alignment_of<MinSizeStorage>::value *
IanBenzMaxim 7:9cd16581b578 92 alignment_of<MinSizeStorage>::value;
IanBenzMaxim 7:9cd16581b578 93
IanBenzMaxim 7:9cd16581b578 94 public:
IanBenzMaxim 7:9cd16581b578 95 // Use internal storage if internalTargetRawSize is valid and at least as
IanBenzMaxim 7:9cd16581b578 96 // large as the minimum size of TypeStorage.
IanBenzMaxim 7:9cd16581b578 97 static const size_t internalTargetSize =
IanBenzMaxim 7:9cd16581b578 98 ((totalSize > otherDataSize) &&
IanBenzMaxim 7:9cd16581b578 99 (internalTargetRawSize >= sizeof(MinSizeStorage)))
IanBenzMaxim 7:9cd16581b578 100 ? internalTargetRawSize
IanBenzMaxim 7:9cd16581b578 101 : 0;
IanBenzMaxim 7:9cd16581b578 102 };
IanBenzMaxim 7:9cd16581b578 103
IanBenzMaxim 7:9cd16581b578 104 // Basic type erasure implementation with small object optimization.
IanBenzMaxim 7:9cd16581b578 105 template <typename Target, template <typename> class TargetAdapter,
IanBenzMaxim 7:9cd16581b578 106 size_t internalTargetSize =
IanBenzMaxim 7:9cd16581b578 107 TypeWrapperTotalSize<Target, 32>::internalTargetSize>
IanBenzMaxim 7:9cd16581b578 108 class TypeWrapper {
IanBenzMaxim 7:9cd16581b578 109 private:
IanBenzMaxim 7:9cd16581b578 110 typedef TypeStorage<Target, internalTargetSize> TargetStorage;
IanBenzMaxim 7:9cd16581b578 111
IanBenzMaxim 7:9cd16581b578 112 public:
IanBenzMaxim 7:9cd16581b578 113 TypeWrapper() : currentTarget(NULL) {}
IanBenzMaxim 7:9cd16581b578 114
IanBenzMaxim 7:9cd16581b578 115 TypeWrapper(const TypeWrapper & other) {
IanBenzMaxim 7:9cd16581b578 116 if (other.currentTarget == other.internalTarget) {
IanBenzMaxim 7:9cd16581b578 117 other.currentTarget->clone(internalTarget);
IanBenzMaxim 7:9cd16581b578 118 currentTarget = internalTarget;
IanBenzMaxim 7:9cd16581b578 119 } else if (other.currentTarget) {
IanBenzMaxim 7:9cd16581b578 120 currentTarget = other.currentTarget->clone();
IanBenzMaxim 7:9cd16581b578 121 } else {
IanBenzMaxim 7:9cd16581b578 122 currentTarget = NULL;
IanBenzMaxim 7:9cd16581b578 123 }
IanBenzMaxim 7:9cd16581b578 124 }
IanBenzMaxim 7:9cd16581b578 125
IanBenzMaxim 7:9cd16581b578 126 template <typename Source> TypeWrapper(Source source) {
IanBenzMaxim 7:9cd16581b578 127 if (sizeof(TargetAdapter<Source>) <= internalTargetSize &&
IanBenzMaxim 7:9cd16581b578 128 alignment_of<TargetAdapter<Source> >::value <=
IanBenzMaxim 7:9cd16581b578 129 alignment_of<TargetStorage>::value) {
IanBenzMaxim 7:9cd16581b578 130 new (internalTarget) TargetAdapter<Source>(source);
IanBenzMaxim 7:9cd16581b578 131 currentTarget = internalTarget;
IanBenzMaxim 7:9cd16581b578 132 } else {
IanBenzMaxim 7:9cd16581b578 133 currentTarget = new TargetAdapter<Source>(source);
IanBenzMaxim 7:9cd16581b578 134 }
IanBenzMaxim 7:9cd16581b578 135 }
IanBenzMaxim 7:9cd16581b578 136
IanBenzMaxim 7:9cd16581b578 137 ~TypeWrapper() {
IanBenzMaxim 7:9cd16581b578 138 if (currentTarget == internalTarget) {
IanBenzMaxim 7:9cd16581b578 139 currentTarget->~Target();
IanBenzMaxim 7:9cd16581b578 140 } else {
IanBenzMaxim 7:9cd16581b578 141 delete currentTarget;
IanBenzMaxim 7:9cd16581b578 142 }
IanBenzMaxim 7:9cd16581b578 143 }
IanBenzMaxim 7:9cd16581b578 144
IanBenzMaxim 7:9cd16581b578 145 const TypeWrapper & operator=(const TypeWrapper & rhs) {
IanBenzMaxim 7:9cd16581b578 146 TypeWrapper(rhs).swap(*this);
IanBenzMaxim 7:9cd16581b578 147 return *this;
IanBenzMaxim 7:9cd16581b578 148 }
IanBenzMaxim 7:9cd16581b578 149
IanBenzMaxim 7:9cd16581b578 150 template <typename Source> const TypeWrapper & operator=(Source source) {
IanBenzMaxim 7:9cd16581b578 151 TypeWrapper(source).swap(*this);
IanBenzMaxim 7:9cd16581b578 152 return *this;
IanBenzMaxim 7:9cd16581b578 153 }
IanBenzMaxim 7:9cd16581b578 154
IanBenzMaxim 7:9cd16581b578 155 void clear() { TypeWrapper().swap(*this); }
IanBenzMaxim 7:9cd16581b578 156
IanBenzMaxim 7:9cd16581b578 157 void swap(TypeWrapper & other) {
IanBenzMaxim 7:9cd16581b578 158 if (this == &other) {
IanBenzMaxim 7:9cd16581b578 159 return;
IanBenzMaxim 7:9cd16581b578 160 }
IanBenzMaxim 7:9cd16581b578 161
IanBenzMaxim 7:9cd16581b578 162 if (currentTarget == internalTarget &&
IanBenzMaxim 7:9cd16581b578 163 other.currentTarget == other.internalTarget) {
IanBenzMaxim 7:9cd16581b578 164 TargetStorage temp;
IanBenzMaxim 7:9cd16581b578 165 currentTarget->clone(temp);
IanBenzMaxim 7:9cd16581b578 166 currentTarget->~Target();
IanBenzMaxim 7:9cd16581b578 167 currentTarget = NULL;
IanBenzMaxim 7:9cd16581b578 168 other.currentTarget->clone(internalTarget);
IanBenzMaxim 7:9cd16581b578 169 other.currentTarget->~Target();
IanBenzMaxim 7:9cd16581b578 170 other.currentTarget = NULL;
IanBenzMaxim 7:9cd16581b578 171 currentTarget = internalTarget;
IanBenzMaxim 7:9cd16581b578 172 temp->clone(other.internalTarget);
IanBenzMaxim 7:9cd16581b578 173 temp->~Target();
IanBenzMaxim 7:9cd16581b578 174 other.currentTarget = other.internalTarget;
IanBenzMaxim 7:9cd16581b578 175 } else if (currentTarget == internalTarget) {
IanBenzMaxim 7:9cd16581b578 176 currentTarget->clone(other.internalTarget);
IanBenzMaxim 7:9cd16581b578 177 currentTarget->~Target();
IanBenzMaxim 7:9cd16581b578 178 currentTarget = other.currentTarget;
IanBenzMaxim 7:9cd16581b578 179 other.currentTarget = other.internalTarget;
IanBenzMaxim 7:9cd16581b578 180 } else if (other.currentTarget == other.internalTarget) {
IanBenzMaxim 7:9cd16581b578 181 other.currentTarget->clone(internalTarget);
IanBenzMaxim 7:9cd16581b578 182 other.currentTarget->~Target();
IanBenzMaxim 7:9cd16581b578 183 other.currentTarget = currentTarget;
IanBenzMaxim 7:9cd16581b578 184 currentTarget = internalTarget;
IanBenzMaxim 7:9cd16581b578 185 } else {
IanBenzMaxim 7:9cd16581b578 186 using std::swap;
IanBenzMaxim 7:9cd16581b578 187 swap(currentTarget, other.currentTarget);
IanBenzMaxim 7:9cd16581b578 188 }
IanBenzMaxim 7:9cd16581b578 189 }
IanBenzMaxim 7:9cd16581b578 190
IanBenzMaxim 7:9cd16581b578 191 const Target * target() const { return currentTarget; }
IanBenzMaxim 7:9cd16581b578 192
IanBenzMaxim 7:9cd16581b578 193 private:
IanBenzMaxim 7:9cd16581b578 194 TargetStorage internalTarget;
IanBenzMaxim 7:9cd16581b578 195 Target * currentTarget;
IanBenzMaxim 7:9cd16581b578 196 };
IanBenzMaxim 7:9cd16581b578 197
IanBenzMaxim 7:9cd16581b578 198 // TypeWrapper specialization with no internal storage space.
IanBenzMaxim 7:9cd16581b578 199 template <typename Target, template <typename> class TargetAdapter>
IanBenzMaxim 7:9cd16581b578 200 class TypeWrapper<Target, TargetAdapter, 0> {
IanBenzMaxim 7:9cd16581b578 201 public:
IanBenzMaxim 7:9cd16581b578 202 TypeWrapper() : currentTarget(NULL) {}
IanBenzMaxim 7:9cd16581b578 203
IanBenzMaxim 7:9cd16581b578 204 TypeWrapper(const TypeWrapper & other) {
IanBenzMaxim 7:9cd16581b578 205 if (other.currentTarget) {
IanBenzMaxim 7:9cd16581b578 206 currentTarget = other.currentTarget->clone();
IanBenzMaxim 7:9cd16581b578 207 } else {
IanBenzMaxim 7:9cd16581b578 208 currentTarget = NULL;
IanBenzMaxim 7:9cd16581b578 209 }
IanBenzMaxim 7:9cd16581b578 210 }
IanBenzMaxim 7:9cd16581b578 211
IanBenzMaxim 7:9cd16581b578 212 template <typename Source>
IanBenzMaxim 7:9cd16581b578 213 TypeWrapper(Source source)
IanBenzMaxim 7:9cd16581b578 214 : currentTarget(new TargetAdapter<Source>(source)) {}
IanBenzMaxim 7:9cd16581b578 215
IanBenzMaxim 7:9cd16581b578 216 ~TypeWrapper() { delete currentTarget; }
IanBenzMaxim 7:9cd16581b578 217
IanBenzMaxim 7:9cd16581b578 218 const TypeWrapper & operator=(const TypeWrapper & rhs) {
IanBenzMaxim 7:9cd16581b578 219 TypeWrapper(rhs).swap(*this);
IanBenzMaxim 7:9cd16581b578 220 return *this;
IanBenzMaxim 7:9cd16581b578 221 }
IanBenzMaxim 7:9cd16581b578 222
IanBenzMaxim 7:9cd16581b578 223 template <typename Source> const TypeWrapper & operator=(Source source) {
IanBenzMaxim 7:9cd16581b578 224 TypeWrapper(source).swap(*this);
IanBenzMaxim 7:9cd16581b578 225 return *this;
IanBenzMaxim 7:9cd16581b578 226 }
IanBenzMaxim 7:9cd16581b578 227
IanBenzMaxim 7:9cd16581b578 228 void clear() { TypeWrapper().swap(*this); }
IanBenzMaxim 7:9cd16581b578 229
IanBenzMaxim 7:9cd16581b578 230 void swap(TypeWrapper & other) {
IanBenzMaxim 7:9cd16581b578 231 using std::swap;
IanBenzMaxim 7:9cd16581b578 232 swap(currentTarget, other.currentTarget);
IanBenzMaxim 7:9cd16581b578 233 }
IanBenzMaxim 7:9cd16581b578 234
IanBenzMaxim 7:9cd16581b578 235 const Target * target() const { return currentTarget; }
IanBenzMaxim 7:9cd16581b578 236
IanBenzMaxim 7:9cd16581b578 237 private:
IanBenzMaxim 7:9cd16581b578 238 Target * currentTarget;
IanBenzMaxim 7:9cd16581b578 239 };
IanBenzMaxim 7:9cd16581b578 240
IanBenzMaxim 7:9cd16581b578 241 } // namespace detail
IanBenzMaxim 7:9cd16581b578 242
IanBenzMaxim 7:9cd16581b578 243 // Function wrapper similar to std::function for 0-3 argument functions.
IanBenzMaxim 7:9cd16581b578 244 template <typename> class Function;
IanBenzMaxim 7:9cd16581b578 245
IanBenzMaxim 7:9cd16581b578 246 // Function implementation for zero argument functions.
IanBenzMaxim 7:9cd16581b578 247 template <typename ResultType> class Function<ResultType()> {
IanBenzMaxim 7:9cd16581b578 248 public:
IanBenzMaxim 7:9cd16581b578 249 typedef ResultType result_type;
IanBenzMaxim 7:9cd16581b578 250
IanBenzMaxim 7:9cd16581b578 251 Function(ResultType (*func)() = NULL) : callableWrapper() {
IanBenzMaxim 7:9cd16581b578 252 if (func) {
IanBenzMaxim 7:9cd16581b578 253 callableWrapper = func;
IanBenzMaxim 7:9cd16581b578 254 }
IanBenzMaxim 7:9cd16581b578 255 }
IanBenzMaxim 7:9cd16581b578 256
IanBenzMaxim 7:9cd16581b578 257 template <typename F> Function(F func) : callableWrapper(func) {}
IanBenzMaxim 7:9cd16581b578 258
IanBenzMaxim 7:9cd16581b578 259 const Function & operator=(ResultType (*func)()) {
IanBenzMaxim 7:9cd16581b578 260 if (func) {
IanBenzMaxim 7:9cd16581b578 261 callableWrapper = func;
IanBenzMaxim 7:9cd16581b578 262 } else {
IanBenzMaxim 7:9cd16581b578 263 callableWrapper.clear();
IanBenzMaxim 7:9cd16581b578 264 }
IanBenzMaxim 7:9cd16581b578 265 return *this;
IanBenzMaxim 7:9cd16581b578 266 }
IanBenzMaxim 7:9cd16581b578 267
IanBenzMaxim 7:9cd16581b578 268 template <typename F> const Function & operator=(F func) {
IanBenzMaxim 7:9cd16581b578 269 callableWrapper = func;
IanBenzMaxim 7:9cd16581b578 270 return *this;
IanBenzMaxim 7:9cd16581b578 271 }
IanBenzMaxim 7:9cd16581b578 272
IanBenzMaxim 7:9cd16581b578 273 void swap(Function & other) { callableWrapper.swap(other.callableWrapper); }
IanBenzMaxim 7:9cd16581b578 274
IanBenzMaxim 7:9cd16581b578 275 operator SafeBool() const {
IanBenzMaxim 7:9cd16581b578 276 return makeSafeBool(callableWrapper.target() != NULL);
IanBenzMaxim 7:9cd16581b578 277 }
IanBenzMaxim 7:9cd16581b578 278
IanBenzMaxim 7:9cd16581b578 279 ResultType operator()() const {
IanBenzMaxim 7:9cd16581b578 280 return callableWrapper.target() ? callableWrapper.target()->invoke()
IanBenzMaxim 7:9cd16581b578 281 : ResultType();
IanBenzMaxim 7:9cd16581b578 282 }
IanBenzMaxim 7:9cd16581b578 283
IanBenzMaxim 7:9cd16581b578 284 private:
IanBenzMaxim 7:9cd16581b578 285 class Callable {
IanBenzMaxim 7:9cd16581b578 286 public:
IanBenzMaxim 7:9cd16581b578 287 virtual ~Callable() {}
IanBenzMaxim 7:9cd16581b578 288 virtual ResultType invoke() const = 0;
IanBenzMaxim 7:9cd16581b578 289 virtual Callable * clone() const = 0;
IanBenzMaxim 7:9cd16581b578 290 virtual void clone(void * buffer) const = 0;
IanBenzMaxim 7:9cd16581b578 291 };
IanBenzMaxim 7:9cd16581b578 292
IanBenzMaxim 7:9cd16581b578 293 template <typename F> class CallableAdapter : public Callable {
IanBenzMaxim 7:9cd16581b578 294 public:
IanBenzMaxim 7:9cd16581b578 295 CallableAdapter(F func) : func(func) {}
IanBenzMaxim 7:9cd16581b578 296
IanBenzMaxim 7:9cd16581b578 297 virtual ResultType invoke() const { return func(); }
IanBenzMaxim 7:9cd16581b578 298
IanBenzMaxim 7:9cd16581b578 299 virtual Callable * clone() const { return new CallableAdapter(*this); }
IanBenzMaxim 7:9cd16581b578 300
IanBenzMaxim 7:9cd16581b578 301 virtual void clone(void * buffer) const {
IanBenzMaxim 7:9cd16581b578 302 new (buffer) CallableAdapter(*this);
IanBenzMaxim 7:9cd16581b578 303 }
IanBenzMaxim 7:9cd16581b578 304
IanBenzMaxim 7:9cd16581b578 305 private:
IanBenzMaxim 7:9cd16581b578 306 F func;
IanBenzMaxim 7:9cd16581b578 307 };
IanBenzMaxim 7:9cd16581b578 308
IanBenzMaxim 7:9cd16581b578 309 detail::TypeWrapper<Callable, CallableAdapter> callableWrapper;
IanBenzMaxim 7:9cd16581b578 310 };
IanBenzMaxim 7:9cd16581b578 311
IanBenzMaxim 7:9cd16581b578 312 template <typename ResultType>
IanBenzMaxim 7:9cd16581b578 313 inline void swap(Function<ResultType()> & lhs, Function<ResultType()> & rhs) {
IanBenzMaxim 7:9cd16581b578 314 lhs.swap(rhs);
IanBenzMaxim 7:9cd16581b578 315 }
IanBenzMaxim 7:9cd16581b578 316
IanBenzMaxim 7:9cd16581b578 317 // Function implementation for one argument functions.
IanBenzMaxim 7:9cd16581b578 318 template <typename ArgumentType, typename ResultType>
IanBenzMaxim 7:9cd16581b578 319 class Function<ResultType(ArgumentType)> {
IanBenzMaxim 7:9cd16581b578 320 public:
IanBenzMaxim 7:9cd16581b578 321 typedef ArgumentType argument_type;
IanBenzMaxim 7:9cd16581b578 322 typedef ResultType result_type;
IanBenzMaxim 7:9cd16581b578 323
IanBenzMaxim 7:9cd16581b578 324 Function(ResultType (*func)(ArgumentType) = NULL) : callableWrapper() {
IanBenzMaxim 7:9cd16581b578 325 if (func) {
IanBenzMaxim 7:9cd16581b578 326 callableWrapper = func;
IanBenzMaxim 7:9cd16581b578 327 }
IanBenzMaxim 7:9cd16581b578 328 }
IanBenzMaxim 7:9cd16581b578 329
IanBenzMaxim 7:9cd16581b578 330 template <typename F> Function(F func) : callableWrapper(func) {}
IanBenzMaxim 7:9cd16581b578 331
IanBenzMaxim 7:9cd16581b578 332 const Function & operator=(ResultType (*func)(ArgumentType)) {
IanBenzMaxim 7:9cd16581b578 333 if (func) {
IanBenzMaxim 7:9cd16581b578 334 callableWrapper = func;
IanBenzMaxim 7:9cd16581b578 335 } else {
IanBenzMaxim 7:9cd16581b578 336 callableWrapper.clear();
IanBenzMaxim 7:9cd16581b578 337 }
IanBenzMaxim 7:9cd16581b578 338 return *this;
IanBenzMaxim 7:9cd16581b578 339 }
IanBenzMaxim 7:9cd16581b578 340
IanBenzMaxim 7:9cd16581b578 341 template <typename F> const Function & operator=(F func) {
IanBenzMaxim 7:9cd16581b578 342 callableWrapper = func;
IanBenzMaxim 7:9cd16581b578 343 return *this;
IanBenzMaxim 7:9cd16581b578 344 }
IanBenzMaxim 7:9cd16581b578 345
IanBenzMaxim 7:9cd16581b578 346 void swap(Function & other) { callableWrapper.swap(other.callableWrapper); }
IanBenzMaxim 7:9cd16581b578 347
IanBenzMaxim 7:9cd16581b578 348 operator SafeBool() const {
IanBenzMaxim 7:9cd16581b578 349 return makeSafeBool(callableWrapper.target() != NULL);
IanBenzMaxim 7:9cd16581b578 350 }
IanBenzMaxim 7:9cd16581b578 351
IanBenzMaxim 7:9cd16581b578 352 ResultType operator()(ArgumentType arg) const {
IanBenzMaxim 7:9cd16581b578 353 return callableWrapper.target() ? callableWrapper.target()->invoke(arg)
IanBenzMaxim 7:9cd16581b578 354 : ResultType();
IanBenzMaxim 7:9cd16581b578 355 }
IanBenzMaxim 7:9cd16581b578 356
IanBenzMaxim 7:9cd16581b578 357 private:
IanBenzMaxim 7:9cd16581b578 358 class Callable {
IanBenzMaxim 7:9cd16581b578 359 public:
IanBenzMaxim 7:9cd16581b578 360 virtual ~Callable() {}
IanBenzMaxim 7:9cd16581b578 361 virtual ResultType invoke(ArgumentType) const = 0;
IanBenzMaxim 7:9cd16581b578 362 virtual Callable * clone() const = 0;
IanBenzMaxim 7:9cd16581b578 363 virtual void clone(void * buffer) const = 0;
IanBenzMaxim 7:9cd16581b578 364 };
IanBenzMaxim 7:9cd16581b578 365
IanBenzMaxim 7:9cd16581b578 366 template <typename F> class CallableAdapter : public Callable {
IanBenzMaxim 7:9cd16581b578 367 public:
IanBenzMaxim 7:9cd16581b578 368 CallableAdapter(F func) : func(func) {}
IanBenzMaxim 7:9cd16581b578 369
IanBenzMaxim 7:9cd16581b578 370 virtual ResultType invoke(ArgumentType arg) const { return func(arg); }
IanBenzMaxim 7:9cd16581b578 371
IanBenzMaxim 7:9cd16581b578 372 virtual Callable * clone() const { return new CallableAdapter(*this); }
IanBenzMaxim 7:9cd16581b578 373
IanBenzMaxim 7:9cd16581b578 374 virtual void clone(void * buffer) const {
IanBenzMaxim 7:9cd16581b578 375 new (buffer) CallableAdapter(*this);
IanBenzMaxim 7:9cd16581b578 376 }
IanBenzMaxim 7:9cd16581b578 377
IanBenzMaxim 7:9cd16581b578 378 private:
IanBenzMaxim 7:9cd16581b578 379 F func;
IanBenzMaxim 7:9cd16581b578 380 };
IanBenzMaxim 7:9cd16581b578 381
IanBenzMaxim 7:9cd16581b578 382 detail::TypeWrapper<Callable, CallableAdapter> callableWrapper;
IanBenzMaxim 7:9cd16581b578 383 };
IanBenzMaxim 7:9cd16581b578 384
IanBenzMaxim 7:9cd16581b578 385 template <typename ArgumentType, typename ResultType>
IanBenzMaxim 7:9cd16581b578 386 inline void swap(Function<ResultType(ArgumentType)> & lhs,
IanBenzMaxim 7:9cd16581b578 387 Function<ResultType(ArgumentType)> & rhs) {
IanBenzMaxim 7:9cd16581b578 388 lhs.swap(rhs);
IanBenzMaxim 7:9cd16581b578 389 }
IanBenzMaxim 7:9cd16581b578 390
IanBenzMaxim 7:9cd16581b578 391 // Function implementation for two argument functions.
IanBenzMaxim 7:9cd16581b578 392 template <typename FirstArgumentType, typename SecondArgumentType,
IanBenzMaxim 7:9cd16581b578 393 typename ResultType>
IanBenzMaxim 7:9cd16581b578 394 class Function<ResultType(FirstArgumentType, SecondArgumentType)> {
IanBenzMaxim 7:9cd16581b578 395 public:
IanBenzMaxim 7:9cd16581b578 396 typedef FirstArgumentType first_argument_type;
IanBenzMaxim 7:9cd16581b578 397 typedef SecondArgumentType second_argument_type;
IanBenzMaxim 7:9cd16581b578 398 typedef ResultType result_type;
IanBenzMaxim 7:9cd16581b578 399
IanBenzMaxim 7:9cd16581b578 400 Function(ResultType (*func)(FirstArgumentType, SecondArgumentType) = NULL)
IanBenzMaxim 7:9cd16581b578 401 : callableWrapper() {
IanBenzMaxim 7:9cd16581b578 402 if (func) {
IanBenzMaxim 7:9cd16581b578 403 callableWrapper = func;
IanBenzMaxim 7:9cd16581b578 404 }
IanBenzMaxim 7:9cd16581b578 405 }
IanBenzMaxim 7:9cd16581b578 406
IanBenzMaxim 7:9cd16581b578 407 template <typename F> Function(F func) : callableWrapper(func) {}
IanBenzMaxim 7:9cd16581b578 408
IanBenzMaxim 7:9cd16581b578 409 const Function & operator=(ResultType (*func)(FirstArgumentType,
IanBenzMaxim 7:9cd16581b578 410 SecondArgumentType)) {
IanBenzMaxim 7:9cd16581b578 411 if (func) {
IanBenzMaxim 7:9cd16581b578 412 callableWrapper = func;
IanBenzMaxim 7:9cd16581b578 413 } else {
IanBenzMaxim 7:9cd16581b578 414 callableWrapper.clear();
IanBenzMaxim 7:9cd16581b578 415 }
IanBenzMaxim 7:9cd16581b578 416 return *this;
IanBenzMaxim 7:9cd16581b578 417 }
IanBenzMaxim 7:9cd16581b578 418
IanBenzMaxim 7:9cd16581b578 419 template <typename F> const Function & operator=(F func) {
IanBenzMaxim 7:9cd16581b578 420 callableWrapper = func;
IanBenzMaxim 7:9cd16581b578 421 return *this;
IanBenzMaxim 7:9cd16581b578 422 }
IanBenzMaxim 7:9cd16581b578 423
IanBenzMaxim 7:9cd16581b578 424 void swap(Function & other) { callableWrapper.swap(other.callableWrapper); }
IanBenzMaxim 7:9cd16581b578 425
IanBenzMaxim 7:9cd16581b578 426 operator SafeBool() const {
IanBenzMaxim 7:9cd16581b578 427 return makeSafeBool(callableWrapper.target() != NULL);
IanBenzMaxim 7:9cd16581b578 428 }
IanBenzMaxim 7:9cd16581b578 429
IanBenzMaxim 7:9cd16581b578 430 ResultType operator()(FirstArgumentType arg1, SecondArgumentType arg2) const {
IanBenzMaxim 7:9cd16581b578 431 return callableWrapper.target()
IanBenzMaxim 7:9cd16581b578 432 ? callableWrapper.target()->invoke(arg1, arg2)
IanBenzMaxim 7:9cd16581b578 433 : ResultType();
IanBenzMaxim 7:9cd16581b578 434 }
IanBenzMaxim 7:9cd16581b578 435
IanBenzMaxim 7:9cd16581b578 436 private:
IanBenzMaxim 7:9cd16581b578 437 class Callable {
IanBenzMaxim 7:9cd16581b578 438 public:
IanBenzMaxim 7:9cd16581b578 439 virtual ~Callable() {}
IanBenzMaxim 7:9cd16581b578 440 virtual ResultType invoke(FirstArgumentType, SecondArgumentType) const = 0;
IanBenzMaxim 7:9cd16581b578 441 virtual Callable * clone() const = 0;
IanBenzMaxim 7:9cd16581b578 442 virtual void clone(void * buffer) const = 0;
IanBenzMaxim 7:9cd16581b578 443 };
IanBenzMaxim 7:9cd16581b578 444
IanBenzMaxim 7:9cd16581b578 445 template <typename F> class CallableAdapter : public Callable {
IanBenzMaxim 7:9cd16581b578 446 public:
IanBenzMaxim 7:9cd16581b578 447 CallableAdapter(F func) : func(func) {}
IanBenzMaxim 7:9cd16581b578 448
IanBenzMaxim 7:9cd16581b578 449 virtual ResultType invoke(FirstArgumentType arg1,
IanBenzMaxim 7:9cd16581b578 450 SecondArgumentType arg2) const {
IanBenzMaxim 7:9cd16581b578 451 return func(arg1, arg2);
IanBenzMaxim 7:9cd16581b578 452 }
IanBenzMaxim 7:9cd16581b578 453
IanBenzMaxim 7:9cd16581b578 454 virtual Callable * clone() const { return new CallableAdapter(*this); }
IanBenzMaxim 7:9cd16581b578 455
IanBenzMaxim 7:9cd16581b578 456 virtual void clone(void * buffer) const {
IanBenzMaxim 7:9cd16581b578 457 new (buffer) CallableAdapter(*this);
IanBenzMaxim 7:9cd16581b578 458 }
IanBenzMaxim 7:9cd16581b578 459
IanBenzMaxim 7:9cd16581b578 460 private:
IanBenzMaxim 7:9cd16581b578 461 F func;
IanBenzMaxim 7:9cd16581b578 462 };
IanBenzMaxim 7:9cd16581b578 463
IanBenzMaxim 7:9cd16581b578 464 detail::TypeWrapper<Callable, CallableAdapter> callableWrapper;
IanBenzMaxim 7:9cd16581b578 465 };
IanBenzMaxim 7:9cd16581b578 466
IanBenzMaxim 7:9cd16581b578 467 template <typename FirstArgumentType, typename SecondArgumentType,
IanBenzMaxim 7:9cd16581b578 468 typename ResultType>
IanBenzMaxim 7:9cd16581b578 469 inline void
IanBenzMaxim 7:9cd16581b578 470 swap(Function<ResultType(FirstArgumentType, SecondArgumentType)> & lhs,
IanBenzMaxim 7:9cd16581b578 471 Function<ResultType(FirstArgumentType, SecondArgumentType)> & rhs) {
IanBenzMaxim 7:9cd16581b578 472 lhs.swap(rhs);
IanBenzMaxim 7:9cd16581b578 473 }
IanBenzMaxim 7:9cd16581b578 474
IanBenzMaxim 7:9cd16581b578 475 // Function implementation for three argument functions.
IanBenzMaxim 7:9cd16581b578 476 template <typename FirstArgumentType, typename SecondArgumentType,
IanBenzMaxim 7:9cd16581b578 477 typename ThirdArgumentType, typename ResultType>
IanBenzMaxim 7:9cd16581b578 478 class Function<ResultType(FirstArgumentType, SecondArgumentType,
IanBenzMaxim 7:9cd16581b578 479 ThirdArgumentType)> {
IanBenzMaxim 7:9cd16581b578 480 public:
IanBenzMaxim 7:9cd16581b578 481 typedef ResultType result_type;
IanBenzMaxim 7:9cd16581b578 482
IanBenzMaxim 7:9cd16581b578 483 Function(ResultType (*func)(FirstArgumentType, SecondArgumentType,
IanBenzMaxim 7:9cd16581b578 484 ThirdArgumentType) = NULL)
IanBenzMaxim 7:9cd16581b578 485 : callableWrapper() {
IanBenzMaxim 7:9cd16581b578 486 if (func) {
IanBenzMaxim 7:9cd16581b578 487 callableWrapper = func;
IanBenzMaxim 7:9cd16581b578 488 }
IanBenzMaxim 7:9cd16581b578 489 }
IanBenzMaxim 7:9cd16581b578 490
IanBenzMaxim 7:9cd16581b578 491 template <typename F> Function(F func) : callableWrapper(func) {}
IanBenzMaxim 7:9cd16581b578 492
IanBenzMaxim 7:9cd16581b578 493 const Function & operator=(ResultType (*func)(FirstArgumentType,
IanBenzMaxim 7:9cd16581b578 494 SecondArgumentType,
IanBenzMaxim 7:9cd16581b578 495 ThirdArgumentType)) {
IanBenzMaxim 7:9cd16581b578 496 if (func) {
IanBenzMaxim 7:9cd16581b578 497 callableWrapper = func;
IanBenzMaxim 7:9cd16581b578 498 } else {
IanBenzMaxim 7:9cd16581b578 499 callableWrapper.clear();
IanBenzMaxim 7:9cd16581b578 500 }
IanBenzMaxim 7:9cd16581b578 501 return *this;
IanBenzMaxim 7:9cd16581b578 502 }
IanBenzMaxim 7:9cd16581b578 503
IanBenzMaxim 7:9cd16581b578 504 template <typename F> const Function & operator=(F func) {
IanBenzMaxim 7:9cd16581b578 505 callableWrapper = func;
IanBenzMaxim 7:9cd16581b578 506 return *this;
IanBenzMaxim 7:9cd16581b578 507 }
IanBenzMaxim 7:9cd16581b578 508
IanBenzMaxim 7:9cd16581b578 509 void swap(Function & other) { callableWrapper.swap(other.callableWrapper); }
IanBenzMaxim 7:9cd16581b578 510
IanBenzMaxim 7:9cd16581b578 511 operator SafeBool() const {
IanBenzMaxim 7:9cd16581b578 512 return makeSafeBool(callableWrapper.target() != NULL);
IanBenzMaxim 7:9cd16581b578 513 }
IanBenzMaxim 7:9cd16581b578 514
IanBenzMaxim 7:9cd16581b578 515 ResultType operator()(FirstArgumentType arg1, SecondArgumentType arg2,
IanBenzMaxim 7:9cd16581b578 516 ThirdArgumentType arg3) const {
IanBenzMaxim 7:9cd16581b578 517 return callableWrapper.target()
IanBenzMaxim 7:9cd16581b578 518 ? callableWrapper.target()->invoke(arg1, arg2, arg3)
IanBenzMaxim 7:9cd16581b578 519 : ResultType();
IanBenzMaxim 7:9cd16581b578 520 }
IanBenzMaxim 7:9cd16581b578 521
IanBenzMaxim 7:9cd16581b578 522 private:
IanBenzMaxim 7:9cd16581b578 523 class Callable {
IanBenzMaxim 7:9cd16581b578 524 public:
IanBenzMaxim 7:9cd16581b578 525 virtual ~Callable() {}
IanBenzMaxim 7:9cd16581b578 526 virtual ResultType invoke(FirstArgumentType, SecondArgumentType,
IanBenzMaxim 7:9cd16581b578 527 ThirdArgumentType) const = 0;
IanBenzMaxim 7:9cd16581b578 528 virtual Callable * clone() const = 0;
IanBenzMaxim 7:9cd16581b578 529 virtual void clone(void * buffer) const = 0;
IanBenzMaxim 7:9cd16581b578 530 };
IanBenzMaxim 7:9cd16581b578 531
IanBenzMaxim 7:9cd16581b578 532 template <typename F> class CallableAdapter : public Callable {
IanBenzMaxim 7:9cd16581b578 533 public:
IanBenzMaxim 7:9cd16581b578 534 CallableAdapter(F func) : func(func) {}
IanBenzMaxim 7:9cd16581b578 535
IanBenzMaxim 7:9cd16581b578 536 virtual ResultType invoke(FirstArgumentType arg1, SecondArgumentType arg2,
IanBenzMaxim 7:9cd16581b578 537 ThirdArgumentType arg3) const {
IanBenzMaxim 7:9cd16581b578 538 return func(arg1, arg2, arg3);
IanBenzMaxim 7:9cd16581b578 539 }
IanBenzMaxim 7:9cd16581b578 540
IanBenzMaxim 7:9cd16581b578 541 virtual Callable * clone() const { return new CallableAdapter(*this); }
IanBenzMaxim 7:9cd16581b578 542
IanBenzMaxim 7:9cd16581b578 543 virtual void clone(void * buffer) const {
IanBenzMaxim 7:9cd16581b578 544 new (buffer) CallableAdapter(*this);
IanBenzMaxim 7:9cd16581b578 545 }
IanBenzMaxim 7:9cd16581b578 546
IanBenzMaxim 7:9cd16581b578 547 private:
IanBenzMaxim 7:9cd16581b578 548 F func;
IanBenzMaxim 7:9cd16581b578 549 };
IanBenzMaxim 7:9cd16581b578 550
IanBenzMaxim 7:9cd16581b578 551 detail::TypeWrapper<Callable, CallableAdapter> callableWrapper;
IanBenzMaxim 7:9cd16581b578 552 };
IanBenzMaxim 7:9cd16581b578 553
IanBenzMaxim 7:9cd16581b578 554 template <typename FirstArgumentType, typename SecondArgumentType,
IanBenzMaxim 7:9cd16581b578 555 typename ThirdArgumentType, typename ResultType>
IanBenzMaxim 7:9cd16581b578 556 inline void swap(Function<ResultType(FirstArgumentType, SecondArgumentType,
IanBenzMaxim 7:9cd16581b578 557 ThirdArgumentType)> & lhs,
IanBenzMaxim 7:9cd16581b578 558 Function<ResultType(FirstArgumentType, SecondArgumentType,
IanBenzMaxim 7:9cd16581b578 559 ThirdArgumentType)> & rhs) {
IanBenzMaxim 7:9cd16581b578 560 lhs.swap(rhs);
IanBenzMaxim 7:9cd16581b578 561 }
IanBenzMaxim 7:9cd16581b578 562
IanBenzMaxim 7:9cd16581b578 563 } // namespace MaximInterfaceCore
IanBenzMaxim 7:9cd16581b578 564
IanBenzMaxim 7:9cd16581b578 565 #endif