/* mbed Microcontroller Library * Copyright (c) 2006-2015 ARM Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef MBED_FUNCTIONPOINTER_H #define MBED_FUNCTIONPOINTER_H #include #include #include #include #include #include "FunctionPointerBase.h" #include "FunctionPointerBind.h" namespace mbed { /** A class for storing and calling a pointer to a static or member void function without arguments */ template class FunctionPointer0 : public FunctionPointerBase{ public: typedef R(*static_fp)(void); typedef struct arg_struct{ } ArgStruct; /** Create a FunctionPointer, attaching a static function * * @param function The void static function to attach (default is none) */ FunctionPointer0(static_fp function = 0): FunctionPointerBase() { attach(function); } /** Create a FunctionPointer, attaching a member function * * @param object The object pointer to invoke the member function on (i.e. the this pointer) * @param function The address of the void member function to attach */ template FunctionPointer0(T *object, R (T::*member)(void)): FunctionPointerBase() { attach(object, member); } /** Attach a static function * * @param function The void static function to attach (default is none) */ void attach(static_fp function) { FunctionPointerBase::_object = reinterpret_cast(function); FunctionPointerBase::_membercaller = &FunctionPointer0::staticcaller; } /** Attach a member function * * @param object The object pointer to invoke the member function on (i.e. the this pointer) * @param function The address of the void member function to attach */ template void attach(T *object, R (T::*member)(void)) { FunctionPointerBase::_object = static_cast(object); *reinterpret_cast(FunctionPointerBase::_member) = member; FunctionPointerBase::_membercaller = &FunctionPointer0::membercaller; } /** Call the attached static or member function */ R call(){ return FunctionPointerBase::call(NULL); } FunctionPointerBind bind() { FunctionPointerBind fp; fp.bind(&FunctionPointerBase::_nullops, (ArgStruct *) NULL, this); return fp; } static_fp get_function()const { return reinterpret_cast(FunctionPointerBase::_object); } R operator ()(void) { return call(); } private: template static R membercaller(void *object, uintptr_t *member, void *arg) { (void) arg; T* o = static_cast(object); R (T::**m)(void) = reinterpret_cast(member); return (o->**m)(); } static R staticcaller(void *object, uintptr_t *member, void *arg) { (void) arg; (void) member; static_fp f = reinterpret_cast(object); return f(); } }; /* If we had variaditic templates, this wouldn't be a problem, but until C++11 is enabled, we are stuck with multiple classes... */ /** A class for storing and calling a pointer to a static or member void function with one argument */ template class FunctionPointer1 : public FunctionPointerBase { protected: typedef struct arg_struct{ A1 a1; arg_struct(const A1 *b1) { a1 = *b1; } } ArgStruct; public: typedef R(*static_fp)(A1); /** Create a FunctionPointer, attaching a static function * * @param function The void static function to attach (default is none) */ FunctionPointer1(static_fp function = 0) { attach(function); } /** Create a FunctionPointer, attaching a member function * * @param object The object pointer to invoke the member function on (i.e. the this pointer) * @param function The address of the void member function to attach */ template FunctionPointer1(T *object, R (T::*member)(A1)) { attach(object, member); } /** Attach a static function * * @param function The void static function to attach (default is none) */ void attach(static_fp function) { FunctionPointerBase::_object = reinterpret_cast(function); FunctionPointerBase::_membercaller = &FunctionPointer1::staticcaller; } /** Attach a member function * * @param object The object pointer to invoke the member function on (i.e. the this pointer) * @param function The address of the void member function to attach */ template void attach(T *object, R (T::*member)(A1)) { FunctionPointerBase::_object = static_cast(object); *reinterpret_cast(FunctionPointerBase::_member) = member; FunctionPointerBase::_membercaller = &FunctionPointer1::membercaller; } FunctionPointerBind bind(const A1 &a1) { FunctionPointerBind fp; fp.bind(&_fp1_ops, (ArgStruct *) NULL, this, &a1); return fp; } /** Call the attached static or member function */ R call(A1 a1) { ArgStruct Args(&a1); return FunctionPointerBase::call(&Args); } static_fp get_function()const { return reinterpret_cast(FunctionPointerBase::_object); } R operator ()(A1 a) { return call(a); } private: template static R membercaller(void *object, uintptr_t *member, void *arg) { ArgStruct *Args = static_cast(arg); T* o = static_cast(object); R (T::**m)(A1) = reinterpret_cast(member); return (o->**m)(Args->a1); } static R staticcaller(void *object, uintptr_t *member, void *arg) { ArgStruct *Args = static_cast(arg); (void) member; static_fp f = reinterpret_cast(object); return f(Args->a1); } /* static void constructor(void * dest, va_list args) { new(dest) ArgStruct(va_arg(args,A1*)); } static void copy_constructor(void *dest , void* src) { ArgStruct *src_args = static_cast(src); new(dest) ArgStruct(&(src_args->a1)); } static void destructor(void *args) { ArgStruct *argstruct = static_cast(args); argstruct->~arg_struct(); } */ protected: static const struct FunctionPointerBase::ArgOps _fp1_ops; }; template const struct FunctionPointerBase::ArgOps FunctionPointer1::_fp1_ops = { FunctionPointer1::constructor, FunctionPointer1::copy_constructor, FunctionPointer1::destructor }; /** A class for storing and calling a pointer to a static or member void function with two arguments */ template class FunctionPointer2 : public FunctionPointerBase { protected: typedef struct arg_struct{ A1 a1; A2 a2; arg_struct(const A1 *b1, const A2 *b2) { a1 = *b1; a2 = *b2; } } ArgStruct; public: typedef R(*static_fp)(A1, A2); /** Create a FunctionPointer, attaching a static function * * @param function The void static function to attach (default is none) */ FunctionPointer2(static_fp function = 0) { attach(function); } /** Create a FunctionPointer, attaching a member function * * @param object The object pointer to invoke the member function on (i.e. the this pointer) * @param function The address of the void member function to attach */ template FunctionPointer2(T *object, R (T::*member)(A1, A2)) { attach(object, member); } /** Attach a static function * * @param function The void static function to attach (default is none) */ void attach(static_fp function) { FunctionPointerBase::_object = reinterpret_cast(function); FunctionPointerBase::_membercaller = &FunctionPointer2::staticcaller; } /** Attach a member function * * @param object The object pointer to invoke the member function on (i.e. the this pointer) * @param function The address of the void member function to attach */ template void attach(T *object, R (T::*member)(A1, A2)) { FunctionPointerBase::_object = static_cast(object); *reinterpret_cast(FunctionPointerBase::_member) = member; FunctionPointerBase::_membercaller = &FunctionPointer2::membercaller; } FunctionPointerBind bind(const A1 &a1, const A2 &a2) { FunctionPointerBind fp; fp.bind(&_fp2_ops, (ArgStruct *) NULL, this, &a1, &a2); return fp; } /** Call the attached static or member function */ R call(A1 a1, A2 a2) { ArgStruct Args(&a1, &a2); return FunctionPointerBase::call(&Args); } static_fp get_function()const { return reinterpret_cast(FunctionPointerBase::_object); } R operator ()(A1 a1, A2 a2) { return call(a1, a2); } private: template static R membercaller(void *object, uintptr_t *member, void *arg) { ArgStruct *Args = static_cast(arg); T* o = static_cast(object); R (T::**m)(A1, A2) = reinterpret_cast(member); return (o->**m)(Args->a1, Args->a2); } static R staticcaller(void *object, uintptr_t *member, void *arg) { ArgStruct *Args = static_cast(arg); (void) member; static_fp f = reinterpret_cast(object); return f(Args->a1, Args->a2); } /* static void constructor(void * dest, va_list args) { A1 *a1 = va_arg(args, A1*); A2 *a2 = va_arg(args, A2*); new(dest) ArgStruct(a1, a2); } static void copy_constructor(void *dest , void* src) { ArgStruct *src_args = static_cast(src); new(dest) ArgStruct(&(src_args->a1), &(src_args->a2)); } static void destructor(void *args) { ArgStruct *argstruct = static_cast(args); argstruct->~arg_struct(); } */ protected: static const struct FunctionPointerBase::ArgOps _fp2_ops; }; template const struct FunctionPointerBase::ArgOps FunctionPointer2::_fp2_ops = { FunctionPointer2::constructor, FunctionPointer2::copy_constructor, FunctionPointer2::destructor }; /** A class for storing and calling a pointer to a static or member void function with three arguments */ template class FunctionPointer3 : public FunctionPointerBase { protected: typedef struct arg_struct{ A1 a1; A2 a2; A3 a3; arg_struct(const A1 *b1, const A2 *b2, const A3* b3) { a1 = *b1; a2 = *b2; a3 = *b3; } } ArgStruct; public: typedef R(*static_fp)(A1, A2, A3); /** Create a FunctionPointer, attaching a static function * * @param function The void static function to attach (default is none) */ FunctionPointer3(static_fp function = 0) { attach(function); } /** Create a FunctionPointer, attaching a member function * * @param object The object pointer to invoke the member function on (i.e. the this pointer) * @param function The address of the void member function to attach */ template FunctionPointer3(T *object, R (T::*member)(A1, A2, A3)) { attach(object, member); } /** Attach a static function * * @param function The void static function to attach (default is none) */ void attach(static_fp function) { FunctionPointerBase::_object = reinterpret_cast(function); FunctionPointerBase::_membercaller = &FunctionPointer3::staticcaller; } /** Attach a member function * * @param object The object pointer to invoke the member function on (i.e. the this pointer) * @param function The address of the void member function to attach */ template void attach(T *object, R (T::*member)(A1, A2, A3)) { FunctionPointerBase::_object = static_cast(object); *reinterpret_cast(FunctionPointerBase::_member) = member; FunctionPointerBase::_membercaller = &FunctionPointer3::membercaller; } FunctionPointerBind bind(const A1 &a1, const A2 &a2, const A3 &a3) { FunctionPointerBind fp; fp.bind(&_fp3_ops, (ArgStruct *) NULL, this, &a1, &a2, &a3); return fp; } /** Call the attached static or member function */ R call(A1 a1, A2 a2, A3 a3) { ArgStruct Args(&a1, &a2, &a3); return FunctionPointerBase::call(&Args); } static_fp get_function()const { return reinterpret_cast(FunctionPointerBase::_object); } R operator ()(A1 a1, A2 a2, A3 a3) { return call(a1, a2, a3); } private: template static R membercaller(void *object, uintptr_t *member, void *arg) { ArgStruct *Args = static_cast(arg); T* o = static_cast(object); R (T::**m)(A1, A2, A3) = reinterpret_cast(member); return (o->**m)(Args->a1, Args->a2, Args->a3); } static R staticcaller(void *object, uintptr_t *member, void *arg) { ArgStruct *Args = static_cast(arg); (void) member; static_fp f = reinterpret_cast(object); return f(Args->a1, Args->a2, Args->a3); } /* static void constructor(void * dest, va_list args) { A1 *a1 = va_arg(args, A1*); A2 *a2 = va_arg(args, A2*); A3 *a3 = va_arg(args, A3*); new(dest) ArgStruct(a1, a2, a3); } static void copy_constructor(void *dest , void* src) { ArgStruct *src_args = static_cast(src); new(dest) ArgStruct(&(src_args->a1), &(src_args->a2), &(src_args->a3)); } static void destructor(void *args) { ArgStruct *argstruct = static_cast(args); argstruct->~arg_struct(); } */ protected: static const struct FunctionPointerBase::ArgOps _fp3_ops; }; template const struct FunctionPointerBase::ArgOps FunctionPointer3::_fp3_ops = { FunctionPointer3::constructor, FunctionPointer3::copy_constructor, FunctionPointer3::destructor }; /** A class for storing and calling a pointer to a static or member void function with four arguments */ template class FunctionPointer4 : public FunctionPointerBase { protected: typedef struct arg_struct{ A1 a1; A2 a2; A3 a3; A4 a4; arg_struct(const A1 *b1, const A2 *b2, const A3* b3, const A4* b4) { a1 = *b1; a2 = *b2; a3 = *b3; a4 = *b4; } } ArgStruct; public: typedef R(*static_fp)(A1, A2, A3, A4); /** Create a FunctionPointer, attaching a static function * * @param function The void static function to attach (default is none) */ FunctionPointer4(static_fp function = 0) { attach(function); } /** Create a FunctionPointer, attaching a member function * * @param object The object pointer to invoke the member function on (i.e. the this pointer) * @param function The address of the void member function to attach */ template FunctionPointer4(T *object, R (T::*member)(A1, A2, A3, A4)) { attach(object, member); } /** Attach a static function * * @param function The void static function to attach (default is none) */ void attach(static_fp function) { FunctionPointerBase::_object = reinterpret_cast(function); FunctionPointerBase::_membercaller = &FunctionPointer4::staticcaller; } /** Attach a member function * * @param object The object pointer to invoke the member function on (i.e. the this pointer) * @param function The address of the void member function to attach */ template void attach(T *object, R (T::*member)(A1, A2, A3, A4)) { FunctionPointerBase::_object = static_cast(object); *reinterpret_cast(FunctionPointerBase::_member) = member; FunctionPointerBase::_membercaller = &FunctionPointer4::membercaller; } FunctionPointerBind bind(const A1 &a1, const A2 &a2, const A3 &a3, const A4 &a4) { FunctionPointerBind fp; fp.bind(&_fp4_ops, (ArgStruct *) NULL, this, &a1, &a2, &a3, &a4); return fp; } /** Call the attached static or member function */ R call(A1 a1, A2 a2, A3 a3, A4 a4) { ArgStruct Args(&a1, &a2, &a3, &a4); return FunctionPointerBase::call(&Args); } static_fp get_function()const { return reinterpret_cast(FunctionPointerBase::_object); } R operator ()(A1 a1, A2 a2, A3 a3, A4 a4) { return call(a1, a2, a3, a4); } private: template static R membercaller(void *object, uintptr_t *member, void *arg) { ArgStruct *Args = static_cast(arg); T* o = static_cast(object); R (T::**m)(A1, A2, A3, A4) = reinterpret_cast(member); return (o->**m)(Args->a1, Args->a2, Args->a3, Args->a4); } static R staticcaller(void *object, uintptr_t *member, void *arg) { ArgStruct *Args = static_cast(arg); (void) member; static_fp f = reinterpret_cast(object); return f(Args->a1, Args->a2, Args->a3, Args->a4); } /* static void constructor(void * dest, va_list args) { A1 *a1 = va_arg(args, A1*); A2 *a2 = va_arg(args, A2*); A3 *a3 = va_arg(args, A3*); A4 *a4 = va_arg(args, A4*); new(dest) ArgStruct(a1, a2, a3, a4); } static void copy_constructor(void *dest , void* src) { ArgStruct *src_args = static_cast(src); new(dest) ArgStruct(&(src_args->a1), &(src_args->a2), &(src_args->a3), &(src_args->a4)); } static void destructor(void *args) { ArgStruct *argstruct = static_cast(args); argstruct->~arg_struct(); } */ protected: static const struct FunctionPointerBase::ArgOps _fp4_ops; }; template const struct FunctionPointerBase::ArgOps FunctionPointer4::_fp4_ops = { FunctionPointer4::constructor, FunctionPointer4::copy_constructor, FunctionPointer4::destructor }; typedef FunctionPointer0 FunctionPointer; //typedef FunctionPointer1 event_callback_t; } // namespace mbed #endif