/* * ORXONOX - the hottest 3D action shooter ever to exist * > www.orxonox.net < * * * License notice: * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * * Author: * Fabian 'x3n' Landau * Co-authors: * ... * */ #ifndef _Functor_H__ #define _Functor_H__ #include #include "core/CorePrereqs.h" #include "util/Debug.h" #include "util/MultiType.h" #include "FunctorPtr.h" namespace orxonox { const unsigned int MAX_FUNCTOR_ARGUMENTS = 5; template inline std::string _typeToString() { return "unknown"; } template <> inline std::string _typeToString() { return ""; } template <> inline std::string _typeToString() { return "int"; } template <> inline std::string _typeToString() { return "uint"; } template <> inline std::string _typeToString() { return "char"; } template <> inline std::string _typeToString() { return "uchar"; } template <> inline std::string _typeToString() { return "short"; } template <> inline std::string _typeToString() { return "ushort"; } template <> inline std::string _typeToString() { return "long"; } template <> inline std::string _typeToString() { return "ulong"; } template <> inline std::string _typeToString() { return "longlong"; } template <> inline std::string _typeToString() { return "ulonglong"; } template <> inline std::string _typeToString() { return "float"; } template <> inline std::string _typeToString() { return "double"; } template <> inline std::string _typeToString() { return "longdouble"; } template <> inline std::string _typeToString() { return "bool"; } template <> inline std::string _typeToString() { return "string"; } template <> inline std::string _typeToString() { return "Vector2"; } template <> inline std::string _typeToString() { return "Vector3"; } template <> inline std::string _typeToString() { return "Quaternion"; } template <> inline std::string _typeToString() { return "ColourValue"; } template <> inline std::string _typeToString() { return "Radian"; } template <> inline std::string _typeToString() { return "Degree"; } template inline std::string typeToString() { return _typeToString::UnqualifiedReferredType>(); } class _CoreExport Functor { public: struct Type { enum Enum { Static, Member }; }; public: virtual MultiType operator()(const MultiType& param1 = MT_Type::Null, const MultiType& param2 = MT_Type::Null, const MultiType& param3 = MT_Type::Null, const MultiType& param4 = MT_Type::Null, const MultiType& param5 = MT_Type::Null) = 0; virtual Type::Enum getType() const = 0; virtual unsigned int getParamCount() const = 0; virtual bool hasReturnvalue() const = 0; virtual std::string getTypenameParam(unsigned int param) const = 0; virtual std::string getTypenameReturnvalue() const = 0; virtual void evaluateParam(unsigned int index, MultiType& param) const = 0; virtual void setRawObjectPointer(void* object) {} virtual void* getRawObjectPointer() const { return 0; } template inline bool setFunction(F* function) { if (this->getFullIdentifier() == typeid(F*)) { modifyFunctor(this, function); return true; } return false; } virtual const std::type_info& getFullIdentifier() const = 0; virtual const std::type_info& getHeaderIdentifier() const = 0; virtual const std::type_info& getHeaderIdentifier(unsigned int params) const = 0; }; namespace detail { template struct FunctorTypeStatic { enum { result = false }; }; template <> struct FunctorTypeStatic { enum { result = true }; }; } template class FunctorMember : public Functor { public: FunctorMember(O* object = 0) : object_(object) {} virtual MultiType operator()(O* object, const MultiType& param1 = MT_Type::Null, const MultiType& param2 = MT_Type::Null, const MultiType& param3 = MT_Type::Null, const MultiType& param4 = MT_Type::Null, const MultiType& param5 = MT_Type::Null) = 0; MultiType operator()(const MultiType& param1 = MT_Type::Null, const MultiType& param2 = MT_Type::Null, const MultiType& param3 = MT_Type::Null, const MultiType& param4 = MT_Type::Null, const MultiType& param5 = MT_Type::Null) { if (detail::FunctorTypeStatic::result || this->object_) return (*this)(this->object_, param1, param2, param3, param4, param5); else { COUT(1) << "Error: Can't execute FunctorMember, no object set." << std::endl; return MT_Type::Null; } } Functor::Type::Enum getType() const { return detail::FunctorTypeStatic::result ? Functor::Type::Static : Functor::Type::Member; } inline void setObject(O* object) { this->object_ = object;} inline O* getObject() const { return this->object_; } inline void setRawObjectPointer(void* object) { this->object_ = (O*)object; } inline void* getRawObjectPointer() const { return this->object_; } protected: O* object_; }; typedef FunctorMember FunctorStatic; template class FunctorPointer : public FunctorMember { public: FunctorPointer(F functionPointer, O* object = 0) : FunctorMember(object), functionPointer_(functionPointer) {} inline void setFunction(F functionPointer) { this->functionPointer_ = functionPointer; } inline F getFunction() const { return this->functionPointer_; } const std::type_info& getFullIdentifier() const { return typeid(F); } protected: F functionPointer_; }; namespace detail { template struct FunctionPointer { typedef R (O::*Type)(P1, P2, P3, P4, P5); }; template struct FunctionPointer { typedef R (O::*Type)(P1, P2, P3, P4, P5); }; template struct FunctionPointer { typedef R (O::*Type)(P1, P2, P3, P4); }; template struct FunctionPointer { typedef R (O::*Type)(P1, P2, P3); }; template struct FunctionPointer { typedef R (O::*Type)(P1, P2); }; template struct FunctionPointer { typedef R (O::*Type)(P1); }; template struct FunctionPointer { typedef R (O::*Type)(); }; template struct FunctionPointer { typedef R (O::*Type)(P1, P2, P3, P4, P5) const; }; template struct FunctionPointer { typedef R (O::*Type)(P1, P2, P3, P4) const; }; template struct FunctionPointer { typedef R (O::*Type)(P1, P2, P3) const; }; template struct FunctionPointer { typedef R (O::*Type)(P1, P2) const; }; template struct FunctionPointer { typedef R (O::*Type)(P1) const; }; template struct FunctionPointer { typedef R (O::*Type)() const; }; template struct FunctionPointer { typedef R (*Type)(P1, P2, P3, P4, P5); }; template struct FunctionPointer { typedef R (*Type)(P1, P2, P3, P4); }; template struct FunctionPointer { typedef R (*Type)(P1, P2, P3); }; template struct FunctionPointer { typedef R (*Type)(P1, P2); }; template struct FunctionPointer { typedef R (*Type)(P1); }; template struct FunctionPointer { typedef R (*Type)(); }; template struct FunctorCaller { static inline MultiType call(typename detail::FunctionPointer::Type functionPointer, O* object, const MultiType& param1, const MultiType& param2, const MultiType& param3, const MultiType& param4, const MultiType& param5) { return (object->*functionPointer)(param1, param2, param3, param4, param5); } }; template struct FunctorCaller { static inline MultiType call(typename detail::FunctionPointer::Type functionPointer, O* object, const MultiType& param1, const MultiType& param2, const MultiType& param3, const MultiType& param4, const MultiType& param5) { return (object->*functionPointer)(param1, param2, param3, param4); } }; template struct FunctorCaller { static inline MultiType call(typename detail::FunctionPointer::Type functionPointer, O* object, const MultiType& param1, const MultiType& param2, const MultiType& param3, const MultiType& param4, const MultiType& param5) { return (object->*functionPointer)(param1, param2, param3); } }; template struct FunctorCaller { static inline MultiType call(typename detail::FunctionPointer::Type functionPointer, O* object, const MultiType& param1, const MultiType& param2, const MultiType& param3, const MultiType& param4, const MultiType& param5) { return (object->*functionPointer)(param1, param2); } }; template struct FunctorCaller { static inline MultiType call(typename detail::FunctionPointer::Type functionPointer, O* object, const MultiType& param1, const MultiType& param2, const MultiType& param3, const MultiType& param4, const MultiType& param5) { return (object->*functionPointer)(param1); } }; template struct FunctorCaller { static inline MultiType call(typename detail::FunctionPointer::Type functionPointer, O* object, const MultiType& param1, const MultiType& param2, const MultiType& param3, const MultiType& param4, const MultiType& param5) { return (object->*functionPointer)(); } }; template struct FunctorCaller { static inline MultiType call(typename detail::FunctionPointer::Type functionPointer, O* object, const MultiType& param1, const MultiType& param2, const MultiType& param3, const MultiType& param4, const MultiType& param5) { (object->*functionPointer)(param1, param2, param3, param4, param5); return MT_Type::Null; } }; template struct FunctorCaller { static inline MultiType call(typename detail::FunctionPointer::Type functionPointer, O* object, const MultiType& param1, const MultiType& param2, const MultiType& param3, const MultiType& param4, const MultiType& param5) { (object->*functionPointer)(param1, param2, param3, param4); return MT_Type::Null; } }; template struct FunctorCaller { static inline MultiType call(typename detail::FunctionPointer::Type functionPointer, O* object, const MultiType& param1, const MultiType& param2, const MultiType& param3, const MultiType& param4, const MultiType& param5) { (object->*functionPointer)(param1, param2, param3); return MT_Type::Null; } }; template struct FunctorCaller { static inline MultiType call(typename detail::FunctionPointer::Type functionPointer, O* object, const MultiType& param1, const MultiType& param2, const MultiType& param3, const MultiType& param4, const MultiType& param5) { (object->*functionPointer)(param1, param2); return MT_Type::Null; } }; template struct FunctorCaller { static inline MultiType call(typename detail::FunctionPointer::Type functionPointer, O* object, const MultiType& param1, const MultiType& param2, const MultiType& param3, const MultiType& param4, const MultiType& param5) { (object->*functionPointer)(param1); return MT_Type::Null; } }; template struct FunctorCaller { static inline MultiType call(typename detail::FunctionPointer::Type functionPointer, O* object, const MultiType& param1, const MultiType& param2, const MultiType& param3, const MultiType& param4, const MultiType& param5) { (object->*functionPointer)(); return MT_Type::Null; } }; template struct FunctorCaller { static inline MultiType call(typename detail::FunctionPointer::Type functionPointer, void*, const MultiType& param1, const MultiType& param2, const MultiType& param3, const MultiType& param4, const MultiType& param5) { return (*functionPointer)(param1, param2, param3, param4, param5); } }; template struct FunctorCaller { static inline MultiType call(typename detail::FunctionPointer::Type functionPointer, void*, const MultiType& param1, const MultiType& param2, const MultiType& param3, const MultiType& param4, const MultiType& param5) { return (*functionPointer)(param1, param2, param3, param4); } }; template struct FunctorCaller { static inline MultiType call(typename detail::FunctionPointer::Type functionPointer, void*, const MultiType& param1, const MultiType& param2, const MultiType& param3, const MultiType& param4, const MultiType& param5) { return (*functionPointer)(param1, param2, param3); } }; template struct FunctorCaller { static inline MultiType call(typename detail::FunctionPointer::Type functionPointer, void*, const MultiType& param1, const MultiType& param2, const MultiType& param3, const MultiType& param4, const MultiType& param5) { return (*functionPointer)(param1, param2); } }; template struct FunctorCaller { static inline MultiType call(typename detail::FunctionPointer::Type functionPointer, void*, const MultiType& param1, const MultiType& param2, const MultiType& param3, const MultiType& param4, const MultiType& param5) { return (*functionPointer)(param1); } }; template struct FunctorCaller { static inline MultiType call(typename detail::FunctionPointer::Type functionPointer, void*, const MultiType& param1, const MultiType& param2, const MultiType& param3, const MultiType& param4, const MultiType& param5) { return (*functionPointer)(); } }; template struct FunctorCaller { static inline MultiType call(typename detail::FunctionPointer::Type functionPointer, void*, const MultiType& param1, const MultiType& param2, const MultiType& param3, const MultiType& param4, const MultiType& param5) { (*functionPointer)(param1, param2, param3, param4, param5); return MT_Type::Null; } }; template struct FunctorCaller { static inline MultiType call(typename detail::FunctionPointer::Type functionPointer, void*, const MultiType& param1, const MultiType& param2, const MultiType& param3, const MultiType& param4, const MultiType& param5) { (*functionPointer)(param1, param2, param3, param4); return MT_Type::Null; } }; template struct FunctorCaller { static inline MultiType call(typename detail::FunctionPointer::Type functionPointer, void*, const MultiType& param1, const MultiType& param2, const MultiType& param3, const MultiType& param4, const MultiType& param5) { (*functionPointer)(param1, param2, param3); return MT_Type::Null; } }; template struct FunctorCaller { static inline MultiType call(typename detail::FunctionPointer::Type functionPointer, void*, const MultiType& param1, const MultiType& param2, const MultiType& param3, const MultiType& param4, const MultiType& param5) { (*functionPointer)(param1, param2); return MT_Type::Null; } }; template struct FunctorCaller { static inline MultiType call(typename detail::FunctionPointer::Type functionPointer, void*, const MultiType& param1, const MultiType& param2, const MultiType& param3, const MultiType& param4, const MultiType& param5) { (*functionPointer)(param1); return MT_Type::Null; } }; template struct FunctorCaller { static inline MultiType call(typename detail::FunctionPointer::Type functionPointer, void*, const MultiType& param1, const MultiType& param2, const MultiType& param3, const MultiType& param4, const MultiType& param5) { (*functionPointer)(); return MT_Type::Null; } }; template struct FunctorHeaderIdentifier {}; template struct FunctorHasReturnvalue { enum { result = true }; }; template <> struct FunctorHasReturnvalue { enum { result = false }; }; template struct FunctorParamCount { enum { result = 5 }; }; template struct FunctorParamCount { enum { result = 4 }; }; template struct FunctorParamCount { enum { result = 3 }; }; template struct FunctorParamCount { enum { result = 2 }; }; template struct FunctorParamCount { enum { result = 1 }; }; template <> struct FunctorParamCount { enum { result = 0 }; }; } template class FunctorTemplate : public FunctorPointer::Type, O> { public: FunctorTemplate(typename detail::FunctionPointer::Type functionPointer, O* object = 0) : FunctorPointer::Type, O>(functionPointer, object) {} MultiType operator()(O* object, const MultiType& param1 = MT_Type::Null, const MultiType& param2 = MT_Type::Null, const MultiType& param3 = MT_Type::Null, const MultiType& param4 = MT_Type::Null, const MultiType& param5 = MT_Type::Null) { return detail::FunctorCaller::call(this->functionPointer_, object, param1, param2, param3, param4, param5); } void evaluateParam(unsigned int index, MultiType& param) const { switch (index) { case 0: param.convert(); break; case 1: param.convert(); break; case 2: param.convert(); break; case 3: param.convert(); break; case 4: param.convert(); break; } } unsigned int getParamCount() const { return detail::FunctorParamCount::result; } bool hasReturnvalue() const { return detail::FunctorHasReturnvalue::result; } std::string getTypenameParam(unsigned int param) const { switch (param) { case 0: return typeToString(); case 1: return typeToString(); case 2: return typeToString(); case 3: return typeToString(); case 4: return typeToString(); default: return ""; } } std::string getTypenameReturnvalue() const { return typeToString(); } const std::type_info& getHeaderIdentifier() const { return typeid(detail::FunctorHeaderIdentifier); } const std::type_info& getHeaderIdentifier(unsigned int params) const { switch (params) { case 0: return typeid(detail::FunctorHeaderIdentifier); case 1: return typeid(detail::FunctorHeaderIdentifier); case 2: return typeid(detail::FunctorHeaderIdentifier); case 3: return typeid(detail::FunctorHeaderIdentifier); case 4: return typeid(detail::FunctorHeaderIdentifier); default: return typeid(detail::FunctorHeaderIdentifier); } } }; template inline FunctorMemberPtr createFunctor(R (O::*functionPointer)(P1, P2, P3, P4, P5), OO* object) { return new FunctorTemplate(functionPointer, object); } template inline FunctorMemberPtr createFunctor(R (O::*functionPointer)(P1, P2, P3, P4), OO* object) { return new FunctorTemplate(functionPointer, object); } template inline FunctorMemberPtr createFunctor(R (O::*functionPointer)(P1, P2, P3), OO* object) { return new FunctorTemplate(functionPointer, object); } template inline FunctorMemberPtr createFunctor(R (O::*functionPointer)(P1, P2), OO* object) { return new FunctorTemplate(functionPointer, object); } template inline FunctorMemberPtr createFunctor(R (O::*functionPointer)(P1), OO* object) { return new FunctorTemplate(functionPointer, object); } template inline FunctorMemberPtr createFunctor(R (O::*functionPointer)(), OO* object) { return new FunctorTemplate(functionPointer, object); } template inline FunctorMemberPtr createFunctor(R (O::*functionPointer)(P1, P2, P3, P4, P5) const, OO* object) { return new FunctorTemplate(functionPointer, object); } template inline FunctorMemberPtr createFunctor(R (O::*functionPointer)(P1, P2, P3, P4) const, OO* object) { return new FunctorTemplate(functionPointer, object); } template inline FunctorMemberPtr createFunctor(R (O::*functionPointer)(P1, P2, P3) const, OO* object) { return new FunctorTemplate(functionPointer, object); } template inline FunctorMemberPtr createFunctor(R (O::*functionPointer)(P1, P2) const, OO* object) { return new FunctorTemplate(functionPointer, object); } template inline FunctorMemberPtr createFunctor(R (O::*functionPointer)(P1) const, OO* object) { return new FunctorTemplate(functionPointer, object); } template inline FunctorMemberPtr createFunctor(R (O::*functionPointer)() const, OO* object) { return new FunctorTemplate(functionPointer, object); } template inline FunctorMemberPtr createFunctor(R (O::*functionPointer)(P1, P2, P3, P4, P5)) { return new FunctorTemplate(functionPointer); } template inline FunctorMemberPtr createFunctor(R (O::*functionPointer)(P1, P2, P3, P4)) { return new FunctorTemplate(functionPointer); } template inline FunctorMemberPtr createFunctor(R (O::*functionPointer)(P1, P2, P3)) { return new FunctorTemplate(functionPointer); } template inline FunctorMemberPtr createFunctor(R (O::*functionPointer)(P1, P2)) { return new FunctorTemplate(functionPointer); } template inline FunctorMemberPtr createFunctor(R (O::*functionPointer)(P1)) { return new FunctorTemplate(functionPointer); } template inline FunctorMemberPtr createFunctor(R (O::*functionPointer)()) { return new FunctorTemplate(functionPointer); } template inline FunctorMemberPtr createFunctor(R (O::*functionPointer)(P1, P2, P3, P4, P5) const) { return new FunctorTemplate(functionPointer); } template inline FunctorMemberPtr createFunctor(R (O::*functionPointer)(P1, P2, P3, P4) const) { return new FunctorTemplate(functionPointer); } template inline FunctorMemberPtr createFunctor(R (O::*functionPointer)(P1, P2, P3) const) { return new FunctorTemplate(functionPointer); } template inline FunctorMemberPtr createFunctor(R (O::*functionPointer)(P1, P2) const) { return new FunctorTemplate(functionPointer); } template inline FunctorMemberPtr createFunctor(R (O::*functionPointer)(P1) const) { return new FunctorTemplate(functionPointer); } template inline FunctorMemberPtr createFunctor(R (O::*functionPointer)() const) { return new FunctorTemplate(functionPointer); } template inline FunctorStaticPtr createFunctor(R (*functionPointer)(P1, P2, P3, P4, P5)) { return new FunctorTemplate(functionPointer); } template inline FunctorStaticPtr createFunctor(R (*functionPointer)(P1, P2, P3, P4)) { return new FunctorTemplate(functionPointer); } template inline FunctorStaticPtr createFunctor(R (*functionPointer)(P1, P2, P3)) { return new FunctorTemplate(functionPointer); } template inline FunctorStaticPtr createFunctor(R (*functionPointer)(P1, P2)) { return new FunctorTemplate(functionPointer); } template inline FunctorStaticPtr createFunctor(R (*functionPointer)(P1)) { return new FunctorTemplate(functionPointer); } template inline FunctorStaticPtr createFunctor(R (*functionPointer)()) { return new FunctorTemplate(functionPointer); } } #endif /* _Functor_H__ */