Lua_icxx  1.02 (Aug 2011)
LuaTempResult.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_TEMPRESULT_INCLUDED
00011 #define LUA_ICXX_TEMPRESULT_INCLUDED
00012 
00013 #include <string>
00014 #include <cassert>
00015 
00016 #include "lua_icxx_export.h"
00017 #include "LuaCallStatus.h"
00018 #include "LuaAdapters.h"
00019 
00020 
00021 // used by operators for safe comparison of char*
00022 template <typename TT> 
00023 struct ValueType 
00024 { 
00025     typedef TT Type; 
00026 };
00027 
00028 
00029 template <> 
00030 struct ValueType<const char*> 
00031 { 
00032     typedef std::string Type; 
00033 };
00034 
00035 
00036 template <int N> 
00037 struct ValueType<char[N]> 
00038 { 
00039     typedef std::string Type; 
00040 };
00041 
00042 
00064 class LUA_ICXX_CPP_API
00065 LuaTempResult
00066 {
00067 public:
00069     LuaTempResult( lua_State*, int prevStackTop, int errCode = 0, const std::string& errMsgPrefix = "");
00070     ~LuaTempResult();
00071 
00073     bool ok() const { return ! isError(); }
00075     bool isError() const { return mErrCode != LUA_ERR_NONE; }
00077     int getErrCode() const { return mErrCode; }
00079     inline std::string getErrMsg() const;
00080 
00082     size_t getNumItems() const { return mNumRetVal; }
00084     static const int FIRST_ITEM_INDEX = 1;
00086     class Item;
00088 
00089 
00090 
00091     inline Item getItem(int index = FIRST_ITEM_INDEX) const;
00092     inline Item operator[](int index) const;
00094 
00096     inline bool isNil(int indx = FIRST_ITEM_INDEX) const;
00097 
00099 
00100     template <typename TT> 
00101     inline TT getAs(int indx = FIRST_ITEM_INDEX) const;
00102     template <typename TT>
00103     inline operator TT() const { return getAs<TT>(); }
00105 
00107 
00108     template <typename TT> inline bool operator == (TT val) const { return getAs<TT>() == typename ValueType<TT>::Type(val); }
00109     template <typename TT> inline bool operator != (TT val) const { return getAs<TT>() != typename ValueType<TT>::Type(val); }
00110     template <typename TT> inline bool operator >= (TT val) const { return getAs<TT>() >= typename ValueType<TT>::Type(val); }
00111     template <typename TT> inline bool operator <= (TT val) const { return getAs<TT>() <= typename ValueType<TT>::Type(val); }
00112     template <typename TT> inline bool operator >  (TT val) const { return getAs<TT>() >  typename ValueType<TT>::Type(val); }
00113     template <typename TT> inline bool operator <  (TT val) const { return getAs<TT>() <  typename ValueType<TT>::Type(val); }
00115 
00118     inline int getStackPos(int index) const;
00119 
00121     lua_State* getLuaState() const { return mLua; }
00122 
00125     inline void push(int index = FIRST_ITEM_INDEX) const;
00126 
00127 public:
00129     LuaTempResult(const LuaTempResult& rhs);
00130 
00131 private:
00132     // prevent resetting
00133     void operator=(const LuaTempResult& rhs);
00134 
00135 private:
00136     lua_State * mLua;
00137 
00138     //LuaCallStatus mStatus;
00139     LuaErrCode mErrCode; 
00140     const int mPrevStackTop;
00141     const int mNumRetVal;
00142 };
00143 
00144 
00148 class LUA_ICXX_CPP_API 
00149 LuaTempResult::Item
00150 {
00151 public:
00157     Item(lua_State* lua, int stackPos, LuaErrCode errCode)
00158         : mLua(lua), mStackPos(stackPos), mErrCode(errCode) { assert(lua); }
00159 
00160 public:
00162     int getTypeID() const { return isInvalid() ? LUA_TNIL : lua_type(mLua, mStackPos); }
00164     bool isNil() const { return isInvalid() ? true : lua_isnil(mLua, mStackPos); }
00165 
00167     inline void push() const;
00169     bool isError() const { return mErrCode != LUA_ERR_NONE; }
00170 
00172 
00173     template <typename TT>
00174         inline operator TT() const { return getAs<TT>(); }
00175     template <typename TT> 
00176         inline TT getAs() const { return 
00177             getObjFromStack<TT>(mLua, mErrCode ? LUA_UNACCEPTABLE_STACK_POS : mStackPos); } 
00179 
00181 
00182     template <typename TT> inline bool operator == (TT val) const { return getAs<TT>() == typename ValueType<TT>::Type(val); }
00183     template <typename TT> inline bool operator != (TT val) const { return getAs<TT>() != typename ValueType<TT>::Type(val); }
00184     template <typename TT> inline bool operator >= (TT val) const { return getAs<TT>() >= typename ValueType<TT>::Type(val); }
00185     template <typename TT> inline bool operator <= (TT val) const { return getAs<TT>() <= typename ValueType<TT>::Type(val); }
00186     template <typename TT> inline bool operator >  (TT val) const { return getAs<TT>() >  typename ValueType<TT>::Type(val); }
00187     template <typename TT> inline bool operator <  (TT val) const { return getAs<TT>() <  typename ValueType<TT>::Type(val); }
00189 
00190 private:
00191     bool isInvalid() const { return mErrCode || mStackPos == LUA_UNACCEPTABLE_STACK_POS; }
00192 
00193 public:
00194     lua_State * const mLua; 
00195     int const mStackPos;    
00196     LuaErrCode const mErrCode; 
00197 };
00198 
00199 
00200 inline 
00201 LuaTempResult::LuaTempResult( 
00202      lua_State* lua, int prevStackTop, int errCode, const std::string& errMsgPrefix)
00203      : mLua(lua)
00204      , mErrCode(LuaErrCode(errCode))
00205      , mPrevStackTop(prevStackTop)
00206      , mNumRetVal(lua_gettop(lua) - prevStackTop)
00207 {
00208     assert( lua );
00209     assert( mNumRetVal >= 0 );
00210     // if error, only one value returned: the error message
00211     assert( (mErrCode == LUA_ERR_NONE) || (mNumRetVal == 1));
00212     if (mErrCode)
00213     {
00214         // replace err message that is on stack with the correct one
00215         const std::string errMsg 
00216             = errMsgPrefix + ": " + lua_tostring(lua, prevStackTop+1);
00217         assert( lua_checkstack(mLua, 1) );
00218         lua_pushstring(lua, errMsg.c_str());
00219         lua_replace(lua, prevStackTop+1);
00220     }
00221 }
00222 
00223 
00224 inline 
00225 LuaTempResult::~LuaTempResult()
00226 {
00227     assert( lua_gettop(mLua) == mPrevStackTop +  mNumRetVal );
00228     lua_settop(mLua, mPrevStackTop);
00229 }
00230 
00231 
00232 /*  Get the stack position of item[index] (index=1 is first, -1 last, etc).
00233     If index=0 or > getNumItems() or < -getNumItems(), returns 0 (invalid stack
00234     position). Note that if isError(), returns the stack position of error
00235     message, regardless of index. 
00236     */
00237 int 
00238 LuaTempResult::getStackPos(int index) 
00239 const
00240 {
00241     if (index > 0 && index <= mNumRetVal)
00242         return mErrCode 
00243             ? mPrevStackTop + 1
00244             : mPrevStackTop + index + (1 - FIRST_ITEM_INDEX);
00245 
00246     if (index < 0 && index >= -mNumRetVal)
00247         return mErrCode 
00248             ? mPrevStackTop + 1
00249             : mPrevStackTop + mNumRetVal + 1 + index;
00250 
00251     return LUA_UNACCEPTABLE_STACK_POS;
00252 }
00253 
00254 
00255 template <typename TT> 
00256 inline TT 
00257 LuaTempResult::getAs(int index) 
00258 const 
00259 { 
00260     return getObjFromStack<TT>( mLua, getStackPos(index) ); 
00261 }
00262 
00263 
00264 inline bool 
00265 isStackPosAcceptable(lua_State* lua, int pos)
00266 {
00267     return pos != 0 && abs(pos) <= lua_gettop(lua);
00268     //(pos > 0 && pos <= LUA_STACK_SIZE) || (pos < 0 && abs(pos) <= lua_gettop(lua));
00269 }
00270 
00271 
00272 inline void 
00273 pushValToStack(lua_State* L, const LuaTempResult::Item& objRef) 
00274 { 
00275     assert( L == objRef.mLua );
00276     if ( objRef.mErrCode )
00277     {
00278         assert( lua_checkstack(L, 1) );
00279         lua_pushnil(L);
00280     }
00281     else
00282         objRef.push();
00283 }
00284 
00285 
00286 inline void 
00287 pushValToStack(lua_State* L, const LuaTempResult& res) 
00288 { 
00289     res.push();
00290 }
00291 
00292 
00293 inline bool 
00294 LuaTempResult::isNil(int indx) 
00295 const 
00296 { 
00297     if ( mErrCode ) return true;
00298     const int stackPos = getStackPos(indx);
00299     return isStackPosAcceptable(mLua, stackPos) ? lua_isnil(mLua, stackPos) : true; 
00300 }
00301 
00302 
00303 inline void 
00304 LuaTempResult::push(int index) 
00305 const 
00306 { 
00307     if ( mErrCode ) 
00308         lua_pushnil(mLua); 
00309     else 
00310     {
00311         const int stackPos = getStackPos(index);
00312         assert( lua_checkstack(mLua, 1) );
00313         if ( isStackPosAcceptable(mLua, stackPos) )
00314             lua_pushvalue(mLua, stackPos);
00315         else
00316             lua_pushnil(mLua); 
00317     }
00318 }
00319 
00320 
00321 inline std::string 
00322 LuaTempResult::getErrMsg() 
00323 const 
00324 {
00325     return mErrCode ? lua_tostring(mLua, mPrevStackTop + 1) : "";
00326 }
00327 
00328 
00329 LuaTempResult::Item 
00330 LuaTempResult::getItem( int index ) const
00331 {
00332     return Item(mLua, getStackPos(index), mErrCode);
00333 }
00334 
00335 
00336 inline LuaTempResult::Item 
00337 LuaTempResult::operator[](int index) 
00338 const 
00339 { 
00340     return getItem(index); 
00341 }
00342 
00343 
00344 inline void 
00345 LuaTempResult::Item::push() 
00346 const
00347 {
00348     assert(lua_checkstack(mLua, 1));
00349     if ( isInvalid() )
00350         lua_pushnil(mLua);
00351     else
00352         lua_pushvalue(mLua, mStackPos);
00353 }
00354 
00355 #endif // LUA_ICXX_TEMPRESULT_INCLUDED