joey shelton / LED_Demo

Dependencies:   MAX44000 PWM_Tone_Library nexpaq_mdk

Fork of LED_Demo by Maxim nexpaq

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers functionpointer.h Source File

functionpointer.h

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 
00023 /** A class for storing and calling a pointer to a static or member void function
00024  */
00025 template <typename R>
00026 class FP0{
00027 public:
00028     /** Create a Function Pointer, attaching a static function
00029      *
00030      *  \param function The void static function to attach (default is none)
00031      */
00032     FP0(R (*function)(void) = 0) {
00033         attach(function);
00034     }
00035 
00036     /** Create a FP, attaching a member function
00037      *
00038      *  \param object The object pointer to invoke the member function on (i.e. the this pointer)
00039      *  \param function The address of the void member function to attach
00040      */
00041     template<typename T>
00042     FP0(T *object, R (T::*member)(void)) {
00043         attach(object, member);
00044     }
00045 
00046     /** Attach a static function
00047      *
00048      *  \param function The void static function to attach (default is none)
00049      */
00050     void attach(R (*function)(void)) {
00051         _p.function = function;
00052         _membercaller = 0;
00053     }
00054 
00055     /** Attach a member function
00056      *
00057      *  \param object The object pointer to invoke the member function on (i.e. the this pointer)
00058      *  \param function The address of the void member function to attach
00059      */
00060     template<typename T>
00061     void attach(T *object, R (T::*member)(void)) {
00062         _p.object = static_cast<void*>(object);
00063         *reinterpret_cast<R (T::**)(void)>(_member) = member;
00064         _membercaller = &FP0::membercaller<T>;
00065     }
00066 
00067     /** Call the attached static or member function
00068      */
00069     R call(){
00070         if (_membercaller == 0 && _p.function) {
00071             return _p.function();
00072         } else if (_membercaller && _p.object) {
00073             return _membercaller(_p.object, _member);
00074         }
00075         return (R)0;
00076     }
00077 
00078     typedef R (*static_fp)();
00079     static_fp get_function() const {
00080         return (R(*)())_p.function;
00081     }
00082 
00083     R operator ()(void) {
00084         return call();
00085     }
00086     operator bool(void) {
00087         void *q = &_p.function;
00088         return (_membercaller != NULL) && _p.object != NULL && (*static_cast<void **>(q) != NULL);
00089     }
00090 
00091 private:
00092     template<typename T>
00093     static void membercaller(void *object, uintptr_t *member) {
00094         T* o = static_cast<T*>(object);
00095         R (T::**m)(void) = reinterpret_cast<R (T::**)(void)>(member);
00096         (o->**m)();
00097     }
00098 
00099     union {
00100         R (*function)(void);               // static function pointer - 0 if none attached
00101         void *object;                         // object this pointer - 0 if none attached
00102     } _p;
00103     uintptr_t _member[2];                     // aligned raw member function pointer storage - converted back by registered _membercaller
00104     R (*_membercaller)(void*, uintptr_t*); // registered membercaller function to convert back and call _m.member on _object
00105 };
00106 
00107 /* If we had variadic templates, this wouldn't be a problem, but until C++11 is enabled, we are stuck with multiple classes... */
00108 
00109 /** A class for storing and calling a pointer to a static or member void function
00110  */
00111 template <typename R, typename A1>
00112 class FP1{
00113 public:
00114     /** Create a FP, attaching a static function
00115      *
00116      *  \param function The void static function to attach (default is none)
00117      */
00118     FP1(R (*function)(A1) = 0) {
00119         attach(function);
00120     }
00121 
00122     /** Create a FP, attaching a member function
00123      *
00124      *  \param object The object pointer to invoke the member function on (i.e. the this pointer)
00125      *  \param function The address of the void member function to attach
00126      */
00127     template<typename T>
00128     FP1(T *object, R (T::*member)(A1)) {
00129         attach(object, member);
00130     }
00131 
00132     /** Attach a static function
00133      *
00134      *  \param function The void static function to attach (default is none)
00135      */
00136     void attach(R (*function)(A1)) {
00137         _p.function = function;
00138         _membercaller = 0;
00139     }
00140 
00141     /** Attach a member function
00142      *
00143      *  \param object The object pointer to invoke the member function on (i.e. the this pointer)
00144      *  \param function The address of the void member function to attach
00145      */
00146     template<typename T>
00147     void attach(T *object, R (T::*member)(A1)) {
00148         _p.object = static_cast<void*>(object);
00149         *reinterpret_cast<R (T::**)(A1)>(_member) = member;
00150         _membercaller = &FP1::membercaller<T>;
00151     }
00152 
00153     /** Call the attached static or member function
00154      */
00155     R call(A1 a){
00156         if (_membercaller == 0 && _p.function) {
00157            return _p.function(a);
00158         } else if (_membercaller && _p.object) {
00159            return _membercaller(_p.object, _member, a);
00160         }
00161         return (R)0;
00162     }
00163 
00164     typedef R (*static_fp)();
00165     static_fp get_function() const {
00166         return (R(*)())_p.function;
00167     }
00168 
00169     R operator ()(A1 a) {
00170         return call(a);
00171     }
00172     operator bool(void)
00173     {
00174         void *q = &_p.function;
00175         return (_membercaller != NULL) && _p.object != NULL && (*static_cast<void **>(q) != NULL);
00176     }
00177 private:
00178     template<typename T>
00179     static void membercaller(void *object, uintptr_t *member, A1 a) {
00180         T* o = static_cast<T*>(object);
00181         R (T::**m)(A1) = reinterpret_cast<R (T::**)(A1)>(member);
00182         (o->**m)(a);
00183     }
00184 
00185     union {
00186         R (*function)(A1);               // static function pointer - 0 if none attached
00187         void *object;                         // object this pointer - 0 if none attached
00188     } _p;
00189     uintptr_t _member[2];                     // aligned raw member function pointer storage - converted back by registered _membercaller
00190     R (*_membercaller)(void*, uintptr_t*, A1); // registered membercaller function to convert back and call _m.member on _object
00191 };
00192 
00193 
00194 
00195 typedef FP0<void> FP;
00196 
00197 #endif