Lua_icxx  1.02 (Aug 2011)
LuaRegistryRef.h
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