/* 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_TYPE__ #define __SLB_TYPE__ #include "lua.hpp" #include "Debug.hpp" #include "SPP.hpp" #include "Manager.hpp" #include "ClassInfo.hpp" namespace SLB { namespace Private { // Default implementation template struct Type { static ClassInfo *getClass(lua_State *L) { SLB_DEBUG_CALL; SLB_DEBUG(10,"getClass '%s'", typeid(T).name()); ClassInfo *c = SLB::Manager::getInstance().getClass(_TIW(T)); if (c == 0) luaL_error(L, "Unknown class %s", typeid(T).name()); return c; } static void push(lua_State *L,const T &obj) { SLB_DEBUG_CALL; SLB_DEBUG(8,"Push(L=%p, obj =%p)", typeid(T).name(), L, &obj); getClass(L)->push_copy(L, (void*) &obj); } static T get(lua_State *L, int pos) { SLB_DEBUG_CALL; SLB_DEBUG(8,"Get(L=%p, pos = %i)", typeid(T).name(), L, pos); T* obj = reinterpret_cast( getClass(L)->get_ptr(L, pos) ); SLB_DEBUG(9,"obj = %p", obj); return *obj; } static bool check(lua_State *L, int pos) { SLB_DEBUG_CALL; SLB_DEBUG(10,"check '%s' at pos %d", typeid(T).name(), pos); return getClass(L)->check(L, pos); } }; template struct Type { static ClassInfo *getClass(lua_State *L) { SLB_DEBUG_CALL; SLB_DEBUG(10,"getClass '%s'", typeid(T).name()); ClassInfo *c = SLB::Manager::getInstance().getClass(_TIW(T)); if (c == 0) luaL_error(L, "Unknown class %s", typeid(T).name()); return c; } static void push(lua_State *L, T *obj, bool fromConstructor = false) { SLB_DEBUG_CALL; SLB_DEBUG(10,"push '%s' of %p (from constructor=%s)", typeid(T).name(), obj, fromConstructor? "true" : "false" ); if (obj == 0) { lua_pushnil(L); return; } //TODO Change this for TypeInfoWrapper? const std::type_info &t_T = typeid(T); const std::type_info &t_obj = typeid(*obj); assert("Invalid typeinfo!!! (type)" && (&t_T) ); assert("Invalid typeinfo!!! (object)" && (&t_obj) ); if (t_obj != t_T) { //Create TIW TypeInfoWrapper wt_T = _TIW(T); TypeInfoWrapper wt_obj = _TIW(*obj); // check if the internal class exists... ClassInfo *c = SLB::Manager::getInstance().getClass(wt_obj); if ( c ) { SLB_DEBUG(8,"Push with conversion from " "T(%p)->T(%p) (L=%p, obj =%p)", c->getName().c_str(), t_obj.name(), t_T.name(),L, obj); // covert the object to the internal class... void *real_obj = SLB::Manager::getInstance().convert( wt_T, wt_obj, obj ); c->push_ptr(L, real_obj, fromConstructor); return; } } // use this class... getClass(L)->push_ptr(L, (void*) obj, fromConstructor); } static T* get(lua_State *L, int pos) { SLB_DEBUG_CALL; SLB_DEBUG(10,"get '%s' at pos %d", typeid(T).name(), pos); return reinterpret_cast( getClass(L)->get_ptr(L, pos) ); } static bool check(lua_State *L, int pos) { SLB_DEBUG_CALL; SLB_DEBUG(10,"check '%s' at pos %d", typeid(T).name(), pos); return getClass(L)->check(L, pos); } }; template struct Type { static ClassInfo *getClass(lua_State *L) { SLB_DEBUG_CALL; SLB_DEBUG(10,"getClass '%s'", typeid(T).name()); ClassInfo *c = SLB::Manager::getInstance().getClass(_TIW(T)); if (c == 0) luaL_error(L, "Unknown class %s", typeid(T).name()); return c; } static void push(lua_State *L,const T *obj) { SLB_DEBUG_CALL; SLB_DEBUG(10,"push '%s' of %p", typeid(T).name(), obj); if (obj == 0) { lua_pushnil(L); return; } if (typeid(*obj) != typeid(T)) { //Create TIW TypeInfoWrapper wt_T = _TIW(T); TypeInfoWrapper wt_obj = _TIW(*obj); // check if the internal class exists... ClassInfo *c = SLB::Manager::getInstance().getClass(wt_obj); if ( c ) { SLB_DEBUG(8,"Push with conversion from " "T(%p)->T(%p) (L=%p, obj =%p)", c->getName().c_str(), typeid(*obj).name(), typeid(T).name(),L, obj); // covert the object to the internal class... const void *real_obj = SLB::Manager::getInstance().convert( wt_T, wt_obj, obj ); c->push_const_ptr(L, real_obj); return; } } getClass(L)->push_const_ptr(L, (const void*) obj); } static const T* get(lua_State *L, int pos) { SLB_DEBUG_CALL; SLB_DEBUG(10,"get '%s' at pos %d", typeid(T).name(), pos); return reinterpret_cast( getClass(L)->get_const_ptr(L, pos) ); } static bool check(lua_State *L, int pos) { SLB_DEBUG_CALL; SLB_DEBUG(10,"check '%s' at pos %d", typeid(T).name(), pos); return getClass(L)->check(L, pos); } }; template struct Type { static void push(lua_State *L,const T &obj) { SLB_DEBUG_CALL; SLB_DEBUG(10,"push '%s' of %p(const ref)", typeid(T).name(), &obj); Type::push(L, &obj); } static const T& get(lua_State *L, int pos) { SLB_DEBUG_CALL; SLB_DEBUG(10,"get '%s' at pos %d", typeid(T).name(), pos); const T* obj = Type::get(L,pos); //TODO: remove the typeid(T).getName() and use classInfo :) if (obj == 0L) luaL_error(L, "Can not get a reference of class %s", typeid(T).name()); return *(obj); } static bool check(lua_State *L, int pos) { SLB_DEBUG_CALL; SLB_DEBUG(10,"check '%s' at pos %d", typeid(T).name(), pos); return Type::check(L,pos); } }; template struct Type { static ClassInfo *getClass(lua_State *L) { SLB_DEBUG_CALL; SLB_DEBUG(10,"getClass '%s'", typeid(T).name()); ClassInfo *c = SLB::Manager::getInstance().getClass(_TIW(T)); if (c == 0) luaL_error(L, "Unknown class %s", typeid(T).name()); return c; } static void push(lua_State *L,T &obj) { SLB_DEBUG_CALL; SLB_DEBUG(10,"push '%s' of %p (reference)", typeid(T).name(), &obj); getClass(L)->push_ref(L, (void*) &obj); } static T& get(lua_State *L, int pos) { SLB_DEBUG_CALL; SLB_DEBUG(10,"get '%s' at pos %d", typeid(T).name(), pos); return *(Type::get(L,pos)); } static bool check(lua_State *L, int pos) { SLB_DEBUG_CALL; SLB_DEBUG(10,"check '%s' at pos %d", typeid(T).name(), pos); return Type::check(L,pos); } }; //--- Specializations --------------------------------------------------- template<> struct Type { static void push(lua_State *L,void* obj) { SLB_DEBUG_CALL; if (obj == 0) lua_pushnil(L); else { SLB_DEBUG(8,"Push (L=%p, obj =%p)",L, obj); lua_pushlightuserdata(L, obj); } } static void *get(lua_State *L, int pos) { SLB_DEBUG_CALL; SLB_DEBUG(8,"Get (L=%p, pos=%i ) =%p)",L, pos, lua_touserdata(L,pos)); if (check(L,pos)) return lua_touserdata(L,pos); //TODO: Check here if is an userdata and convert it to void return 0; } static bool check(lua_State *L, int pos) { SLB_DEBUG_CALL; return (lua_islightuserdata(L,pos) != 0); } }; // Type specialization for template<> struct Type { static void push(lua_State *L, int v) { SLB_DEBUG_CALL; SLB_DEBUG(6, "Push integer = %d",v); lua_pushinteger(L,v); } static int get(lua_State *L, int p) { SLB_DEBUG_CALL; int v = (int) lua_tointeger(L,p); SLB_DEBUG(6,"Get integer (pos %d) = %d",p,v); return v; } static bool check(lua_State *L, int pos) { SLB_DEBUG_CALL; return (lua_isnumber(L,pos) != 0); } }; template<> struct Type { static void push(lua_State *L, const int &v) { SLB_DEBUG_CALL; Type::push(L,v); } static int get(lua_State *L, int p) { SLB_DEBUG_CALL; return Type::get(L,p); } static bool check(lua_State *L, int pos) { SLB_DEBUG_CALL; return Type::check(L,pos); } }; // Type specialization for template<> struct Type { static void push(lua_State *L, unsigned int v) { SLB_DEBUG_CALL; SLB_DEBUG(6, "Push unsigned integer = %d",v); lua_pushinteger(L,v); } static unsigned int get(lua_State *L, int p) { SLB_DEBUG_CALL; unsigned int v = static_cast(lua_tointeger(L,p)); SLB_DEBUG(6,"Get unsigned integer (pos %d) = %d",p,v); return v; } static bool check(lua_State *L, int pos) { SLB_DEBUG_CALL; return (lua_isnumber(L,pos) != 0); } }; template<> struct Type { static void push(lua_State *L, const unsigned int &v) { SLB_DEBUG_CALL; Type::push(L,v); } static unsigned int get(lua_State *L, int p) { SLB_DEBUG_CALL; return Type::get(L,p); } static bool check(lua_State *L, int pos) { SLB_DEBUG_CALL; return Type::check(L,pos); } }; template<> struct Type { static void push(lua_State *L, long v) { SLB_DEBUG_CALL; SLB_DEBUG(6, "Push long = %ld",v); lua_pushinteger(L,v); } static long get(lua_State *L, int p) { SLB_DEBUG_CALL; long v = (long) lua_tointeger(L,p); SLB_DEBUG(6,"Get long (pos %d) = %ld",p,v); return v; } static bool check(lua_State *L, int pos) { SLB_DEBUG_CALL; return (lua_isnumber(L,pos) != 0); } }; /* unsigned long == unsigned int */ template<> struct Type { static void push(lua_State *L, unsigned long v) { SLB_DEBUG_CALL; SLB_DEBUG(6, "Push unsigned long = %lu",v); lua_pushnumber(L,v); } static unsigned long get(lua_State *L, int p) { SLB_DEBUG_CALL; unsigned long v = (unsigned long) lua_tonumber(L,p); SLB_DEBUG(6,"Get unsigned long (pos %d) = %lu",p,v); return v; } static bool check(lua_State *L, int pos) { SLB_DEBUG_CALL; return (lua_isnumber(L,pos) != 0); } }; template<> struct Type { static void push(lua_State *L, const unsigned long &v) { SLB_DEBUG_CALL; Type::push(L,v); } static unsigned long get(lua_State *L, int p) { SLB_DEBUG_CALL; return Type::get(L,p); } static bool check(lua_State *L, int pos) { SLB_DEBUG_CALL; return Type::check(L,pos); } }; template<> struct Type { static void push(lua_State *L, unsigned long long v) { SLB_DEBUG_CALL; SLB_DEBUG(6, "Push unsigned long long = %llu",v); lua_pushnumber(L,(lua_Number) v); } static unsigned long long get(lua_State *L, int p) { SLB_DEBUG_CALL; unsigned long long v = (unsigned long long) lua_tonumber(L,p); SLB_DEBUG(6,"Get unsigned long long (pos %d) = %llu",p,v); return v; } static bool check(lua_State *L, int pos) { SLB_DEBUG_CALL; return (lua_isnumber(L,pos) != 0); } }; template<> struct Type { static void push(lua_State *L, const unsigned long long &v) { SLB_DEBUG_CALL; Type::push(L,v); } static unsigned long long get(lua_State *L, int p) { SLB_DEBUG_CALL; return Type::get(L,p); } static bool check(lua_State *L, int pos) { SLB_DEBUG_CALL; return Type::check(L,pos); } }; // Type specialization for template<> struct Type { static void push(lua_State *L, double v) { SLB_DEBUG_CALL; SLB_DEBUG(6, "Push double = %f",v); lua_pushnumber(L,v); } static double get(lua_State *L, int p) { SLB_DEBUG_CALL; double v = (double) lua_tonumber(L,p); SLB_DEBUG(6,"Get double (pos %d) = %f",p,v); return v; } static bool check(lua_State *L, int pos) { SLB_DEBUG_CALL; return (lua_isnumber(L,pos) != 0); } }; template<> struct Type { static void push(lua_State *L, const double &v) { SLB_DEBUG_CALL; Type::push(L,v); } static double get(lua_State *L, int p) { SLB_DEBUG_CALL; return Type::get(L,p); } static bool check(lua_State *L, int pos) { SLB_DEBUG_CALL; return Type::check(L,pos); } }; // Type specialization for template<> struct Type { static void push(lua_State *L, float v) { SLB_DEBUG_CALL; SLB_DEBUG(6, "Push float = %f",v); lua_pushnumber(L,v); } static float get(lua_State *L, int p) { SLB_DEBUG_CALL; float v = (float) lua_tonumber(L,p); SLB_DEBUG(6,"Get float (pos %d) = %f",p,v); return v; } static bool check(lua_State *L, int pos) { SLB_DEBUG_CALL; return (lua_isnumber(L,pos) != 0); } }; template<> struct Type { static void push(lua_State *L, const float &v) { SLB_DEBUG_CALL; Type::push(L,v); } static float get(lua_State *L, int p) { SLB_DEBUG_CALL; return Type::get(L,p); } static bool check(lua_State *L, int pos) { SLB_DEBUG_CALL; return Type::check(L,pos); } }; // Type specialization for template<> struct Type { static void push(lua_State *L, bool v) { SLB_DEBUG_CALL; SLB_DEBUG(6, "Push bool = %d",(int)v); lua_pushboolean(L,v); } static bool get(lua_State *L, int p) { SLB_DEBUG_CALL; bool v = (lua_toboolean(L,p) != 0); SLB_DEBUG(6,"Get bool (pos %d) = %d",p,v); return v; } static bool check(lua_State *L, int pos) { SLB_DEBUG_CALL; return lua_isboolean(L,pos); } }; template<> struct Type { static void push(lua_State *L, const std::string &v) { SLB_DEBUG_CALL; SLB_DEBUG(6, "Push const std::string& = %s",v.c_str()); lua_pushstring(L, v.c_str()); } static std::string get(lua_State *L, int p) { SLB_DEBUG_CALL; const char* v = (const char*) lua_tostring(L,p); SLB_DEBUG(6,"Get std::string (pos %d) = %s",p,v); return v; } static bool check(lua_State *L, int pos) { SLB_DEBUG_CALL; return (lua_isstring(L,pos) != 0); } }; template<> struct Type { static void push(lua_State *L, const std::string &v) { SLB_DEBUG_CALL; SLB_DEBUG(6, "Push const std::string& = %s",v.c_str()); lua_pushstring(L, v.c_str()); } // let the compiler do the conversion... static const std::string get(lua_State *L, int p) { SLB_DEBUG_CALL; const char* v = (const char*) lua_tostring(L,p); SLB_DEBUG(6,"Get std::string (pos %d) = %s",p,v); return std::string(v); } static bool check(lua_State *L, int pos) { SLB_DEBUG_CALL; return (lua_isstring(L,pos) != 0); } }; // Type specialization for template<> struct Type { static void push(lua_State *L, const char* v) { SLB_DEBUG_CALL; SLB_DEBUG(6, "Push const char* = %s",v); lua_pushstring(L,v); } static const char* get(lua_State *L, int p) { SLB_DEBUG_CALL; const char* v = (const char*) lua_tostring(L,p); SLB_DEBUG(6,"Get const char* (pos %d) = %s",p,v); return v; } static bool check(lua_State *L, int pos) { SLB_DEBUG_CALL; return (lua_isstring(L,pos) != 0); } }; template<> struct Type { static void push(lua_State *L, const unsigned char* v) { SLB_DEBUG_CALL; SLB_DEBUG(6, "Push const unsigned char* = %s",v); lua_pushstring(L,(const char*)v); } static const unsigned char* get(lua_State *L, int p) { SLB_DEBUG_CALL; const unsigned char* v = (const unsigned char*) lua_tostring(L,p); SLB_DEBUG(6,"Get const unsigned char* (pos %d) = %s",p,v); return v; } static bool check(lua_State *L, int pos) { SLB_DEBUG_CALL; return (lua_isstring(L,pos) != 0); } }; }} // end of SLB::Private #endif