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 #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