/* SLB - Simple Lua Binder Copyright (C) 2007 Jose L. Hidalgo ValiƱo (PpluX) This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA Jose L. Hidalgo (www.pplux.com) pplux@pplux.com */ #ifndef __SLB_CLASS__ #define __SLB_CLASS__ #include "SPP.hpp" #include "Export.hpp" #include "Debug.hpp" #include "ClassInfo.hpp" #include "ClassHelpers.hpp" #include "Manager.hpp" #include "FuncCall.hpp" #include "Value.hpp" #include "Instance.hpp" #include "Iterator.hpp" #include "Hybrid.hpp" #include #include #include #include #include struct lua_State; namespace SLB { struct ClassBase { ClassBase() {} virtual ~ClassBase() {} }; template< typename T, typename W = Instance::Default > class Class : public ClassBase { public: typedef Class __Self; Class(const char *name); Class(const Class&); Class& operator=(const Class&); __Self &rawSet(const char *name, Object *obj); template __Self &set(const char *name, const TValue &obj) { return rawSet(name, (Object*) Value::copy(obj)); } template __Self &set_ref(const char *name, TValue& obj) { return rawSet(name, Value::ref(obj)); } template __Self &set_autoDelete(const char *name, TValue *obj) { return rawSet(name, Value::autoDelete(obj)); } __Self &set(const char *name, lua_CFunction func) { return rawSet(name, FuncCall::create(func)); } template __Self &enumValue(const char *name, TEnum obj); __Self &constructor(); /** Declares a class as hybrid, this will imply that the __index * and __newindex methods will be overriden, see * Hybrid::registerAsHybrid */ __Self &hybrid() { inherits(); HybridBase::registerAsHybrid( _class ); return *this; } template __Self &inherits() { _class->inheritsFrom(); return *this;} template __Self &static_inherits() { _class->staticInheritsFrom(); return *this;} /* Class__index for (non-const)methods */ template __Self &class__index( R (C::*func)(P) ) { _class->setClass__index( FuncCall::create(func) ); return *this; } /* Class__index for const methods */ template __Self &class__index( R (C::*func)(P) const ) { _class->setClass__index( FuncCall::create(func) ); return *this; } /* Class__index for C functions */ template __Self &class__index( R (*func)(P) ) { _class->setClass__index( FuncCall::create(func) ); return *this; } /* Class__index for lua_functions */ __Self &class__index(lua_CFunction func) { _class->setClass__index( FuncCall::create(func) ); return *this; } /* Class__newindex for (non-const)methods */ template __Self &class__newindex( R (C::*func)(K,V) ) { _class->setClass__newindex( FuncCall::create(func) ); return *this; } /* Class__newindex for const methods */ template __Self &class__newindex( R (C::*func)(K,V) const ) { _class->setClass__newindex( FuncCall::create(func) ); return *this; } /* Class__newindex for C functions */ template __Self &class__newindex( R (*func)(K,V) ) { _class->setClass__newindex( FuncCall::create(func) ); return *this; } /* Class__newindex for lua_functions */ __Self &class__newindex(lua_CFunction func) { _class->setClass__newindex( FuncCall::create(func) ); return *this; } /* Object__index for (non-const)methods */ template __Self &object__index( R (C::*func)(P) ) { _class->setObject__index( FuncCall::create(func) ); return *this; } /* Object__index for const methods */ template __Self &object__index( R (C::*func)(P) const ) { _class->setObject__index( FuncCall::create(func) ); return *this; } /* Object__index for C functions */ template __Self &object__index( R (*func)(P) ) { _class->setObject__index( FuncCall::create(func) ); return *this; } /* Object__index for lua_functions */ __Self &object__index(lua_CFunction func) { _class->setObject__index( FuncCall::create(func) ); return *this; } /* Object__newindex for (non-const)methods */ template __Self &object__newindex( R (C::*func)(K,V) ) { _class->setObject__newindex( FuncCall::create(func) ); return *this; } /* Object__newindex for const methods */ template __Self &object__newindex( R (C::*func)(K,V) const ) { _class->setObject__newindex( FuncCall::create(func) ); return *this; } /* Object__newindex for C functions */ template __Self &object__newindex( R (*func)(K,V) ) { _class->setObject__newindex( FuncCall::create(func) ); return *this; } /* Object__newindex for lua_functions */ __Self &object__newindex(lua_CFunction func) { _class->setObject__newindex( FuncCall::create(func) ); return *this; } __Self &__add() { SLB_DEBUG_CALL; SLB_DEBUG(0, "NOT IMPLEMENTED!"); return *this; } __Self &__mult() { SLB_DEBUG_CALL; SLB_DEBUG(0, "NOT IMPLEMENTED!"); return *this; } template /* IT == Iterator Traits */ __Self &customIterator( const char *name, typename IT::GetIteratorMember first, typename IT::GetIteratorMember end ) { return rawSet(name, new Iterator( new StdIterator< IT >(first, end ) ) ); } template __Self &iterator(const char *name, T_Iterator (C::*first)(), T_Iterator (C::*end)() ) { return customIterator< StdIteratorTraits > (name,first, end ) ; } template __Self &const_iterator(const char *name, T_Iterator (C::*first)() const, T_Iterator (C::*end)() const ) { return customIterator< StdConstIteratorTraits > (name,first, end ) ; } // Metada __Self &comment(const std::string&); __Self ¶m(const std::string&); #define SLB_REPEAT(N) \ \ /* Methods */ \ template \ __Self &set(const char *name, R (C::*func)(SPP_ENUM_D(N,T)) ); \ template \ __Self &nonconst_set(const char *name, R (C::*func)(SPP_ENUM_D(N,T)) ); \ \ /* CONST Methods */ \ template \ __Self &set(const char *name, R (C::*func)(SPP_ENUM_D(N,T)) const ); \ template \ __Self &const_set(const char *name, R (C::*func)(SPP_ENUM_D(N,T)) const); \ \ /* C-functions */ \ template \ __Self &set(const char *name, R (func)(SPP_ENUM_D(N,T)) ); \ \ /* constructors */ \ template \ __Self &constructor(); \ SPP_MAIN_REPEAT_Z(MAX,SLB_REPEAT) #undef SLB_REPEAT protected: ClassInfo *_class; // For metadata Object *_lastObj; size_t _param; }; template inline Class::Class(const char *name) : _class(0), _lastObj(0), _param(0) { SLB_DEBUG_CALL; // we expect to have a template "Implementation" inside W typedef typename W::template Implementation Adapter; _class = Manager::getInstance().getOrCreateClass( typeid(T) ); _class->setName( name ); _class->setInstanceFactory(new InstanceFactoryAdapter< T, Adapter >() ); SLB_DEBUG(1, "Class declaration for %s[%s]", name, typeid(T).name()); } template inline Class::Class(const Class &c) : _class(c._class) { } template inline Class& Class::operator=(const Class &c) { _class = c._class; } template inline Class &Class::rawSet(const char *name, Object *obj) { _class->set(name, obj); _lastObj = obj; _param = 0; return *this; } template inline Class &Class::constructor() { _class->setConstructor( FuncCall::classConstructor() ); return *this; } template template inline Class &Class::enumValue(const char *name, TEnum obj) { // "fake" Declaration of TEnum... ClassInfo *c = Manager::getInstance().getOrCreateClass( typeid(TEnum) ); if (!c->initialized()) { // if it is not initialized then add a simple adapter for // references. c->setInstanceFactory( new InstanceFactoryAdapter< TEnum, SLB::Instance::Default::Implementation >() ); } // push a reference return rawSet(name, Value::copy(obj)); } template inline Class &Class::comment( const std::string &s ) { if (_lastObj) _lastObj->setInfo(s); else _class->setInfo(s); return *this; } template inline Class &Class::param( const std::string &s ) { //TODO: This should also work for constructors, and so on. if (_lastObj) { FuncCall *fc = dynamic_cast(_lastObj); if (fc) { size_t max_param = fc->getNumArguments(); if (_param >= max_param) { std::cerr << "SLB_Warning: " << fc->getInfo() <<" to many parameters (total args=" << max_param << ")" << "(" << _param << ", " << s << ")" << std::endl; } else { fc->setArgComment(_param, s); } } else { std::cerr << "SLB_Warning: Can not set param info to a non-funcCall object " << "(" << _param << ", " << s << ")" << std::endl; } } _param++; return *this; } #define SLB_REPEAT(N) \ \ /* Methods */ \ template\ template \ inline Class &Class::set(const char *name, R (C::*func)(SPP_ENUM_D(N,T)) ){ \ if (typeid(T) != typeid(C)) static_inherits();\ return rawSet(name, FuncCall::create(func)); \ } \ template\ template \ inline Class &Class::nonconst_set(const char *name, R (C::*func)(SPP_ENUM_D(N,T)) ){ \ if (typeid(T) != typeid(C)) static_inherits();\ return rawSet(name, FuncCall::create(func)); \ } \ \ /* CONST Methods */ \ template\ template \ inline Class &Class::set(const char *name, R (C::*func)(SPP_ENUM_D(N,T)) const ){ \ if (typeid(T) != typeid(C)) static_inherits();\ return rawSet(name, FuncCall::create(func)); \ } \ template\ template \ inline Class &Class::const_set(const char *name, R (C::*func)(SPP_ENUM_D(N,T)) const ){ \ if (typeid(T) != typeid(C)) static_inherits();\ return rawSet(name, FuncCall::create(func)); \ } \ \ /* C-functions */ \ template \ template \ inline Class &Class::set(const char *name, R (func)(SPP_ENUM_D(N,T)) ){ \ return rawSet(name, FuncCall::create(func)); \ } \ \ /* constructor */ \ template \ template \ inline Class &Class::constructor(){ \ FuncCall *fc = FuncCall::classConstructor();\ _class->setConstructor( fc );\ return *this; \ } \ SPP_MAIN_REPEAT_Z(MAX,SLB_REPEAT) #undef SLB_REPEAT } #endif