|
Lua_icxx
1.02 (Aug 2011)
|
00001 /* 00002 This file is part of the Lua_icxx library. 00003 Copyright 2010 (c) by Oliver Schoenborn. 00004 License terms in LICENSE.txt. 00005 */ 00006 00007 00008 #ifndef LUA_ICXX_REGREF_INCLUDED 00009 #define LUA_ICXX_REGREF_INCLUDED 00010 00011 #include <cassert> 00012 00013 #include <lua.hpp> 00014 #include "lua_icxx_export.h" 00015 00016 00017 /* Represent a Lua registry reference for a Lua object. 00018 The object can be pushed onto the lua stack via pushObj(), or its 00019 registry key obtained by converting to int. It is automatically 00020 a reference to Lua nil if stack pos is invalid. 00021 00022 WARNING: LuaRegRef is not copyable 00023 */ 00024 class LUA_ICXX_CPP_API 00025 LuaRegRef 00026 { 00027 private: 00028 static int getRef(lua_State* lua, int stackPos) 00029 { 00030 assert(lua); 00031 if (stackPos > 0 && stackPos > lua_gettop(lua)) 00032 return LUA_NOREF; 00033 if (stackPos < 0 && -stackPos > lua_gettop(lua)) 00034 return LUA_NOREF; 00035 if (stackPos == 0) 00036 return LUA_NOREF; 00037 00038 assert( lua_checkstack(lua, 1) ); 00039 lua_pushvalue(lua, stackPos); 00040 return luaL_ref(lua, LUA_REGISTRYINDEX); 00041 } 00042 00043 static int copyRef(const LuaRegRef& rhs) 00044 { 00045 if (rhs.isNil()) 00046 return LUA_NOREF; 00047 00048 assert(rhs.mLua); 00049 rhs.pushObj(); 00050 return luaL_ref(rhs.mLua, LUA_REGISTRYINDEX); 00051 } 00052 00053 public: 00054 // Nil reference 00055 LuaRegRef(): mLua(NULL), mRegKey(LUA_NOREF) {} 00056 // ref to top of stack by default, or stackPos 00057 LuaRegRef(lua_State* lua, int stackPos = -1): mLua(lua), mRegKey( getRef(lua, stackPos) ) {} 00058 // remove reference to Lua obj 00059 ~LuaRegRef() { if (mLua) luaL_unref(mLua, LUA_REGISTRYINDEX, mRegKey); } 00060 00061 // create from existing 00062 LuaRegRef(const LuaRegRef& rhs): mLua(rhs.mLua), mRegKey( copyRef(rhs) ) {} 00063 void operator=(const LuaRegRef& rhs) { mLua = rhs.mLua; mRegKey = copyRef(rhs); } 00064 00065 // Reset the reference to a different Lua object (the one at top of 00066 // stack if stackPos not given) 00067 void reset( lua_State* lua, int stackPos = -1 ) 00068 { 00069 if ( mLua ) 00070 luaL_unref(mLua, LUA_REGISTRYINDEX, mRegKey); 00071 else 00072 mLua = lua; 00073 assert(mLua); 00074 mRegKey = getRef(mLua, stackPos); 00075 } 00076 00077 // make this ref "point to nil" 00078 void setNil() 00079 { 00080 assert(mLua); 00081 luaL_unref(mLua, LUA_REGISTRYINDEX, mRegKey); 00082 mRegKey = LUA_REFNIL; 00083 } 00084 00085 // true if this is a reference to Lua NIL 00086 bool isNil() const { return mRegKey == LUA_NOREF || mRegKey == LUA_REFNIL; } 00087 00088 // get the raw reference key used by Lua 00089 int getRegKey() const { return mRegKey; } 00090 00091 // compare two registry refs for equality (ie same registry id) 00092 bool operator==(const LuaRegRef& rhs) const { return mRegKey == rhs.mRegKey; } 00093 bool operator!=(const LuaRegRef& rhs) const { return mRegKey != rhs.mRegKey; } 00094 00095 // get the type of what is referenced 00096 int getTypeID() const 00097 { 00098 assert(mLua); 00099 if ( isNil() ) 00100 return LUA_TNIL; 00101 00102 pushObj(); 00103 const int refType = lua_type(mLua, -1); 00104 lua_pop(mLua, 1); 00105 return refType; 00106 } 00107 00108 // push referenced object onto stack, for use by other lua_icxx functions/methods 00109 void pushObj() const 00110 { 00111 assert(mLua); 00112 lua_rawgeti(mLua, LUA_REGISTRYINDEX, mRegKey); 00113 } 00114 00115 private: 00116 lua_State * mLua; 00117 int mRegKey; 00118 }; 00119 00120 00121 #endif // LUA_ICXX_REGREF_INCLUDED