Lua_icxx  1.02 (Aug 2011)
LuaTableRef.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 #pragma once
00009 
00010 #ifndef LUA_ICXX_TABLEREF_INCLUDED
00011 #define LUA_ICXX_TABLEREF_INCLUDED
00012 
00014 // Includes and declarations
00016 
00017 
00018 #include <string>
00019 
00020 #include "LuaObjRef.h"
00021 #include "LuaStackCleaner.h"
00022 
00023 
00025 // Types/Classes
00027 
00028 
00032 class LUA_ICXX_CPP_API
00033 LuaTableRef : public LuaObjRef
00034 {
00035 public:
00036     // C++ requires all constructors to be duplicated
00037 
00039     explicit LuaTableRef( const std::string& id = "nil" ): LuaObjRef(id) {}
00040 
00042 
00043     LuaTableRef( const LuaTempResult& res ): LuaObjRef(res) {}
00044     LuaTableRef( const LuaTempResult::Item& item ): LuaObjRef(item) {}
00045     LuaTableRef( lua_State* lua, int stackPos ): LuaObjRef(lua, stackPos) {}
00047 
00048     template <typename KeyType>
00049     class Field;
00050 
00052     template <typename KeyType> 
00053         inline bool hasField( const KeyType& key ) const;
00054 
00056 
00057     template <typename KeyType> 
00058         inline LuaTempResult getField(const KeyType& key) const;
00059     template <typename KeyType> 
00060         inline Field<KeyType> operator[] (const KeyType& key) { return Field<KeyType>(*this, key); }
00062 
00064     template <typename ValType>
00065         inline void setField( const char* key, const ValType& obj );
00066     template <typename ValType>
00067         inline void setField( const std::string& key, const ValType& obj ) { setField(key.c_str(), obj); }
00068     template <typename KeyType, typename ValType> 
00069         inline void setField( const KeyType& key, const ValType& obj );
00071 
00073 
00074     inline void delField( const char* key );
00075     inline void delField( const std::string& key ) { delField(key.c_str()); }
00076     template <typename KeyType> 
00077         inline void delField( const KeyType& key );
00079 
00080 private:
00081 
00082     // all pushFieldValue methods assume table already on stack
00083 
00084     // push t[key] on top of stack
00085     void pushFieldValue( int key ) const { assert( lua_checkstack(mLua, 1) ); lua_rawgeti(mLua, -1, key); }
00086     void pushFieldValue( const char* key ) const { assert( lua_checkstack(mLua, 1) ); lua_getfield(mLua, -1, key); }
00087     void pushFieldValue( const std::string& key ) const { pushFieldValue(key.c_str()); }
00088     // when key=bool, float, double, short, etc
00089     template <typename TT>
00090         inline void pushFieldValue( const TT& key ) const;
00091 };
00092 
00093 
00095 // LuaTableRef::Field<KeyType>
00097 
00098 
00103 template <typename KeyType>
00104 class LuaTableRef::Field
00105 {
00106 public:
00108     Field(LuaTableRef& table, const KeyType& key): mTable(table), mKey(key) {}
00109     
00110 
00112     template <typename ValType>
00113         void operator=(const ValType& obj) { mTable.setField(mKey, obj); }
00115     void operator=(const Field& rhs) { mTable.setField(mKey, rhs); }
00116 
00118     operator LuaTempResult() const { return mTable.getField(mKey); }
00120     template <typename TT>
00121         operator TT() const { return TT(mTable.getField(mKey)); }
00122 
00124     template <typename ValType>
00125         bool operator==(const ValType& obj) const { return mTable.getField(mKey) == obj; }
00127     bool isNil() const { return mTable.getField(mKey).isNil(); }
00128 
00129 public:
00131     inline void pushObj() const;
00132 
00133 private:
00134     LuaTableRef& mTable;
00135     const KeyType& mKey;
00136 };
00137 
00138 
00140 // inlines and templates for LuaTableRef::Field<KeyType>
00142 
00143 
00144 template <typename KeyType>
00145 inline void 
00146 LuaTableRef::Field<KeyType>::pushObj() 
00147 const
00148 { 
00149     mTable.pushObj(); 
00150     mTable.pushFieldValue(mKey); 
00151     lua_remove(mTable.getLuaState(), -2);     // remove table (just need value)
00152 }
00153 
00154 
00155 template <typename KeyType>
00156 inline void 
00157 pushValToStack(lua_State* L, const LuaTableRef::Field<KeyType>& field) 
00158 { 
00159     field.pushObj();
00160 }
00161 
00162 
00164 // inlines and templates for LuaTableRef
00166 
00167 
00168 // push the value for given key onto stack
00169 template <typename TT>
00170 inline void 
00171 LuaTableRef::pushFieldValue( const TT& key ) 
00172 const
00173 {
00174     pushValToStack(mLua, key);
00175     lua_gettable(mLua, -2);      // get t[key] on top of stack
00176 }
00177 
00178 
00179 template <typename KeyType>
00180 inline bool 
00181 LuaTableRef::hasField( const KeyType& key ) 
00182 const
00183 {
00184     const LuaStackCleaner s(mLua);
00185     pushObj();
00186     pushFieldValue(key);
00187     assert( s.willPop(2) );
00188     return ! lua_isnil(mLua, -1);
00189 }
00190 
00191 
00192 template <typename KeyType>
00193 inline LuaTempResult
00194 LuaTableRef::getField( const KeyType& key ) 
00195 const
00196 {
00197     const int prevStackTop = lua_gettop(mLua);
00198     pushObj();                // push table on stack
00199     pushFieldValue(key);      // get value for key
00200     lua_remove(mLua, -2);     // remove table (just need value)
00201     return LuaTempResult(mLua, prevStackTop);
00202 }
00203 
00204 
00205 template <typename ValType>
00206 inline void 
00207 LuaTableRef::setField( const char* key, const ValType& obj )
00208 {
00209     const LuaStackCleaner s(mLua);
00210     pushObj();
00211     pushValToStack(mLua, obj); 
00212     lua_setfield(mLua, -2, key);
00213     assert( s.willPop(1) );
00214 }
00215 
00216 
00217 template <typename KeyType, typename ValType>
00218 inline void 
00219 LuaTableRef::setField( const KeyType& key, const ValType& obj )
00220 {
00221     const LuaStackCleaner s(mLua);
00222     pushObj();
00223     pushValToStack(mLua, key);
00224     pushValToStack(mLua, obj); 
00225     lua_settable(mLua, -3);
00226     assert( s.willPop(1) );
00227 }
00228 
00229 
00230 inline void 
00231 LuaTableRef::delField( const char* key )
00232 {
00233     const LuaStackCleaner s(mLua);
00234     pushObj();
00235     assert( lua_checkstack(mLua, 1) ); 
00236     lua_pushnil(mLua);
00237     lua_setfield(mLua, -2, key);
00238     assert( s.willPop(1) );
00239 }
00240 
00241 
00242 template <typename KeyType> 
00243 inline void 
00244 LuaTableRef::delField( const KeyType& key )
00245 {
00246     const LuaStackCleaner s(mLua);
00247     pushObj();
00248     pushValToStack(mLua, key);
00249     assert( lua_checkstack(mLua, 1) ); 
00250     lua_pushnil(mLua);
00251     lua_settable(mLua, -3);
00252     assert( s.willPop(1) );
00253 }
00254 
00255 
00256 #endif // LUA_ICXX_TABLEREF_INCLUDED 
00257