Simulated product dispenser

Dependencies:   HTS221

Fork of mbed-cloud-workshop-connect-HTS221 by Jim Carver

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers functionpointer.h Source File

functionpointer.h

Go to the documentation of this file.
00001 /*
00002  * Copyright (c) 2015 ARM Limited. All rights reserved.
00003  * SPDX-License-Identifier: Apache-2.0
00004  * Licensed under the Apache License, Version 2.0 (the License); you may
00005  * not use this file except in compliance with the License.
00006  * You may obtain a copy of the License at
00007  *
00008  * http://www.apache.org/licenses/LICENSE-2.0
00009  *
00010  * Unless required by applicable law or agreed to in writing, software
00011  * distributed under the License is distributed on an AS IS BASIS, WITHOUT
00012  * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00013  * See the License for the specific language governing permissions and
00014  * limitations under the License.
00015  */
00016 #ifndef FUNCTIONPOINTER_H
00017 #define FUNCTIONPOINTER_H
00018 
00019 #include <string.h>
00020 #include <stdint.h>
00021 
00022 /*! \file functionpointer.h
00023 * \brief A class for storing and calling a pointer to a static or member void function.
00024  */
00025 
00026 template <typename R>
00027 class FP0{
00028 public:
00029     /** Create a function pointer, attaching a static function.
00030      *
00031      *  \param function The void static function to attach (default is none).
00032      */
00033     FP0(R (*function)(void) = 0) {
00034         memset(_member,0,sizeof(_member));
00035         attach(function);
00036     }
00037 
00038     /** Create a function pointer, attaching a member function.
00039      *
00040      *  \param object The object pointer to invoke the member function on (the "this" pointer).
00041      *  \param function The address of the void member function to attach.
00042      */
00043     template<typename T>
00044     FP0(T *object, R (T::*member)(void)) {
00045         attach(object, member);
00046     }
00047 
00048     /** Attach a static function.
00049      *
00050      *  \param function The void static function to attach (default is none).
00051      */
00052     void attach(R (*function)(void)) {
00053         _p.function = function;
00054         _membercaller = 0;
00055     }
00056 
00057     /** Attach a member function.
00058      *
00059      *  \param object The object pointer to invoke the member function on (the "this" pointer).
00060      *  \param function The address of the void member function to attach.
00061      */
00062     template<typename T>
00063     void attach(T *object, R (T::*member)(void)) {
00064         _p.object = static_cast<void*>(object);
00065         *reinterpret_cast<R (T::**)(void)>(_member) = member;
00066         _membercaller = &FP0::membercaller<T>;
00067     }
00068 
00069     /** Call the attached static or member function.
00070      */
00071     R call(){
00072         if (_membercaller == 0 && _p.function) {
00073             return _p.function();
00074         } else if (_membercaller && _p.object) {
00075             return _membercaller(_p.object, _member);
00076         }
00077         return (R)0;
00078     }
00079 
00080     typedef R (*static_fp)();
00081     static_fp get_function() const {
00082         return (R(*)())_p.function;
00083     }
00084 
00085     R operator ()(void) {
00086         return call();
00087     }
00088     operator bool(void) {
00089         void *q = &_p.function;
00090         return (_membercaller != NULL) && _p.object != NULL && (*static_cast<void **>(q) != NULL);
00091     }
00092 
00093 private:
00094     template<typename T>
00095     static void membercaller(void *object, uintptr_t *member) {
00096         T* o = static_cast<T*>(object);
00097         R (T::**m)(void) = reinterpret_cast<R (T::**)(void)>(member);
00098         (o->**m)();
00099     }
00100 
00101     union {
00102         R (*function)(void);               // static function pointer - 0 if none attached
00103         void *object;                         // object this pointer - 0 if none attached
00104     } _p;
00105     uintptr_t _member[2];                     // aligned raw member function pointer storage - converted back by registered _membercaller
00106     R (*_membercaller)(void*, uintptr_t*); // registered membercaller function to convert back and call _m.member on _object
00107 };
00108 
00109 /* If we had variadic templates, this wouldn't be a problem, but until C++11 is enabled, we are stuck with multiple classes... */
00110 
00111 /** A class for storing and calling a pointer to a static or member void function
00112  */
00113 template <typename R, typename A1>
00114 class FP1{
00115 public:
00116     /** Create a function pointer, attaching a static function.
00117      *
00118      *  \param function The void static function to attach (default is none).
00119      */
00120     FP1(R (*function)(A1) = 0) {
00121         memset(_member,0,sizeof(_member));
00122         attach(function);
00123     }
00124 
00125     /** Create a function pointeer, attaching a member function.
00126      *
00127      *  \param object The object pointer to invoke the member function on (the "this" pointer).
00128      *  \param function The address of the void member function to attach.
00129      */
00130     template<typename T>
00131     FP1(T *object, R (T::*member)(A1)) {
00132         attach(object, member);
00133     }
00134 
00135     /** Attach a static function.
00136      *
00137      *  \param function The void static function to attach (default is none).
00138      */
00139     void attach(R (*function)(A1)) {
00140         _p.function = function;
00141         _membercaller = 0;
00142     }
00143 
00144     /** Attach a member function.
00145      *
00146      *  \param object The object pointer to invoke the member function on (the "this" pointer).
00147      *  \param function The address of the void member function to attach.
00148      */
00149     template<typename T>
00150     void attach(T *object, R (T::*member)(A1)) {
00151         _p.object = static_cast<void*>(object);
00152         *reinterpret_cast<R (T::**)(A1)>(_member) = member;
00153         _membercaller = &FP1::membercaller<T>;
00154     }
00155 
00156     /** Call the attached static or member function.
00157      */
00158     R call(A1 a){
00159         if (_membercaller == 0 && _p.function) {
00160            return _p.function(a);
00161         } else if (_membercaller && _p.object) {
00162            return _membercaller(_p.object, _member, a);
00163         }
00164         return (R)0;
00165     }
00166 
00167     typedef R (*static_fp)();
00168     static_fp get_function() const {
00169         return (R(*)())_p.function;
00170     }
00171 
00172     R operator ()(A1 a) {
00173         return call(a);
00174     }
00175     operator bool(void)
00176     {
00177         void *q = &_p.function;
00178         return (_membercaller != NULL) && _p.object != NULL && (*static_cast<void **>(q) != NULL);
00179     }
00180 private:
00181     template<typename T>
00182     static void membercaller(void *object, uintptr_t *member, A1 a) {
00183         T* o = static_cast<T*>(object);
00184         R (T::**m)(A1) = reinterpret_cast<R (T::**)(A1)>(member);
00185         (o->**m)(a);
00186     }
00187 
00188     union {
00189         R (*function)(A1);               // static function pointer - 0 if none attached
00190         void *object;                         // object this pointer - 0 if none attached
00191     } _p;
00192     uintptr_t _member[2];                     // aligned raw member function pointer storage - converted back by registered _membercaller
00193     R (*_membercaller)(void*, uintptr_t*, A1); // registered membercaller function to convert back and call _m.member on _object
00194 };
00195 
00196 /** A class for storing and calling a pointer to a static or member void function.
00197  */
00198 template <typename R, typename A1, typename A2>
00199 class FP2{
00200 public:
00201     /** Create a function pointer, attaching a static function.
00202      *
00203      *  \param function The void static function to attach (default is none).
00204      */
00205     FP2(R (*function)(A1, A2) = 0) {
00206         memset(_member,0,sizeof(_member));
00207         attach(function);
00208     }
00209 
00210     /** Create a function pointer, attaching a member function.
00211      *
00212      *  \param object The object pointer to invoke the member function on (the "this" pointer).
00213      *  \param function The address of the void member function to attach.
00214      */
00215     template<typename T>
00216     FP2(T *object, R (T::*member)(A1, A2)) {
00217         attach(object, member);
00218     }
00219 
00220     /** Attach a static function.
00221      *
00222      *  \param function The void static function to attach (default is none).
00223      */
00224     void attach(R (*function)(A1, A2)) {
00225         _p.function = function;
00226         _membercaller = 0;
00227     }
00228 
00229     /** Attach a member function
00230      *
00231      *  \param object The object pointer to invoke the member function on (the "this" pointer).
00232      *  \param function The address of the void member function to attach.
00233      */
00234     template<typename T>
00235     void attach(T *object, R (T::*member)(A1, A2)) {
00236         _p.object = static_cast<void*>(object);
00237         *reinterpret_cast<R (T::**)(A1, A2)>(_member) = member;
00238         _membercaller = &FP2::membercaller<T>;
00239     }
00240 
00241     /** Call the attached static or member function.
00242      */
00243     R call(A1 a1, A2 a2){
00244         if (_membercaller == 0 && _p.function) {
00245            return _p.function(a1, a2);
00246         } else if (_membercaller && _p.object) {
00247            return _membercaller(_p.object, _member, a1, a2);
00248         }
00249         return (R)0;
00250     }
00251 
00252     typedef R (*static_fp)();
00253     static_fp get_function() const {
00254         return (R(*)())_p.function;
00255     }
00256 
00257     R operator ()(A1 a1, A2 a2) {
00258         return call(a1, a2);
00259     }
00260     operator bool(void)
00261     {
00262         void *q = &_p.function;
00263         return (_membercaller != NULL) && _p.object != NULL && (*static_cast<void **>(q) != NULL);
00264     }
00265 private:
00266     template<typename T>
00267     static void membercaller(void *object, uintptr_t *member, A1 a1, A2 a2) {
00268         T* o = static_cast<T*>(object);
00269         R (T::**m)(A1, A2) = reinterpret_cast<R (T::**)(A1, A2)>(member);
00270         (o->**m)(a1, a2);
00271     }
00272 
00273     union {
00274         R (*function)(A1, A2);               // static function pointer - 0 if none attached
00275         void *object;                         // object this pointer - 0 if none attached
00276     } _p;
00277     uintptr_t _member[2];                     // aligned raw member function pointer storage - converted back by registered _membercaller
00278     R (*_membercaller)(void*, uintptr_t*, A1, A2); // registered membercaller function to convert back and call _m.member on _object
00279 };
00280 
00281 /** A class for storing and calling a pointer to a static or member void function.
00282  */
00283 template <typename R, typename A1, typename A2, typename A3>
00284 class FP3{
00285 public:
00286     /** Create a function pointer, attaching a static function.
00287      *
00288      *  \param function The void static function to attach (default is none).
00289      */
00290     FP3(R (*function)(A1, A2, A3) = 0) {
00291         memset(_member,0,sizeof(_member));
00292         attach(function);
00293     }
00294 
00295     /** Create a function pointer, attaching a member function.
00296      *
00297      *  \param object The object pointer to invoke the member function on (the "this" pointer).
00298      *  \param function The address of the void member function to attach.
00299      */
00300     template<typename T>
00301     FP3(T *object, R (T::*member)(A1, A2, A3)) {
00302         attach(object, member);
00303     }
00304 
00305     /** Attach a static function.
00306      *
00307      *  \param function The void static function to attach (default is none).
00308      */
00309     void attach(R (*function)(A1, A2, A3)) {
00310         _p.function = function;
00311         _membercaller = 0;
00312     }
00313 
00314     /** Attach a member function.
00315      *
00316      *  \param object The object pointer to invoke the member function on (the "this" pointer).
00317      *  \param function The address of the void member function to attach.
00318      */
00319     template<typename T>
00320     void attach(T *object, R (T::*member)(A1, A2, A3)) {
00321         _p.object = static_cast<void*>(object);
00322         *reinterpret_cast<R (T::**)(A1, A2, A3)>(_member) = member;
00323         _membercaller = &FP3::membercaller<T>;
00324     }
00325 
00326     /** Call the attached static or member function.
00327      */
00328     R call(A1 a1, A2 a2, A3 a3){
00329         if (_membercaller == 0 && _p.function) {
00330            return _p.function(a1, a2, a3);
00331         } else if (_membercaller && _p.object) {
00332            return _membercaller(_p.object, _member, a1, a2, a3);
00333         }
00334         return (R)0;
00335     }
00336 
00337     typedef R (*static_fp)();
00338     static_fp get_function() const {
00339         return (R(*)())_p.function;
00340     }
00341 
00342     R operator ()(A1 a1, A2 a2, A3 a3) {
00343         return call(a1, a2, a3);
00344     }
00345     operator bool(void)
00346     {
00347         void *q = &_p.function;
00348         return (_membercaller != NULL) && _p.object != NULL && (*static_cast<void **>(q) != NULL);
00349     }
00350 private:
00351     template<typename T>
00352     static void membercaller(void *object, uintptr_t *member, A1 a1, A2 a2, A3 a3) {
00353         T* o = static_cast<T*>(object);
00354         R (T::**m)(A1, A2, A3) = reinterpret_cast<R (T::**)(A1, A2, A3)>(member);
00355         (o->**m)(a1, a2, a3);
00356     }
00357 
00358     union {
00359         R (*function)(A1, A2, A3);               // static function pointer - 0 if none attached
00360         void *object;                         // object this pointer - 0 if none attached
00361     } _p;
00362     uintptr_t _member[2];                     // aligned raw member function pointer storage - converted back by registered _membercaller
00363     R (*_membercaller)(void*, uintptr_t*, A1, A2, A3); // registered membercaller function to convert back and call _m.member on _object
00364 };
00365 
00366 typedef FP0<void> FP;
00367 
00368 #endif