Extended MaximInterface

Dependents:   mbed_DS28EC20_GPIO

Committer:
IanBenzMaxim
Date:
Mon Nov 06 14:39:18 2017 -0600
Revision:
0:f77ad7f72d04
Child:
6:a8c83a2e6fa4
Initial commit.

Who changed what in which revision?

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