lua++
C:/Documents and Settings/Kalith/My Documents/Programmation/luapp/src/luapp_state.cpp
Go to the documentation of this file.
00001 #include "luapp_state.hpp"
00002 #include "luapp_glues.hpp"
00003 #include "luapp_exception.hpp"
00004 #include "luapp_var.hpp"
00005 #include <utils_string.hpp>
00006 #include <utils_filesystem.hpp>
00007 #include <iostream>
00008 #include <deque>
00009 /*#include "frost_utils_eventmanager.h"
00010 #include "frost_utils_event.h"*/
00011 
00012 //#define DEBUG_STACK
00013 
00014 namespace lua
00015 {
00016 const luaL_Reg lualibs[] = {
00017     {"", luaopen_base},
00018     {LUA_LOADLIBNAME, luaopen_package},
00019     {LUA_TABLIBNAME, luaopen_table},
00020     {LUA_IOLIBNAME, luaopen_io},
00021     {LUA_OSLIBNAME, luaopen_os},
00022     {LUA_STRLIBNAME, luaopen_string},
00023     {LUA_MATHLIBNAME, luaopen_math},
00024     {LUA_DBLIBNAME, luaopen_debug},
00025     {NULL, NULL}
00026 };
00027 
00028 std::map<lua_State*, state*> state::lLuaStateMap_;
00029 
00030 void open_libs(lua_State* pLua_)
00031 {
00032     for (const luaL_Reg* lib = lualibs; lib->func; ++lib)
00033     {
00034         lua_pushcfunction(pLua_, lib->func);
00035         lua_pushstring(pLua_, lib->name);
00036         lua_call(pLua_, 1, 0);
00037     }
00038 }
00039 
00040 int l_TreatError(lua_State*);
00041 
00042 state::state()
00043 {
00044     pErrorFunction_ = &l_TreatError;
00045 
00046     pLua_ = lua_open();
00047     if (!pLua_)
00048     {
00049         throw exception("state", "Error while initializing Lua.");
00050         return;
00051     }
00052 
00053     open_libs(pLua_);
00054 
00055     reg("SendString", glue_send_string);
00056     reg("EmptyString", glue_empty_string);
00057     reg("ConcTable", glue_conc_table);
00058 
00059     lLuaStateMap_[pLua_] = this;
00060 }
00061 
00062 state::~state()
00063 {
00064     if (pLua_)
00065         lua_close(pLua_);
00066 
00067     lLuaStateMap_.erase(pLua_);
00068 }
00069 
00070 state* state::get_state(lua_State* pLua)
00071 {
00072     std::map<lua_State*, state*>::iterator iter = lLuaStateMap_.find(pLua);
00073     if (iter != lLuaStateMap_.end())
00074         return iter->second;
00075     else
00076         return nullptr;
00077 }
00078 
00079 lua_State* state::get_state()
00080 {
00081     return pLua_;
00082 }
00083 
00084 std::string state::conc_table( const std::string& sTable )
00085 {
00086     /* [#] This function converts a Lua table into a formated string. It is used
00087     *  to save the content of the table in the SavedVariables.
00088     */
00089     std::string s = "tbl = \"" + sTable + "\";\n"
00090               "temp = \"\";\n"
00091               "for k, v in pairs (" + sTable + ") do\n"
00092                   "local s, t;\n"
00093                   "if (type(k) == \"number\") then\ns = k;\nend\n"
00094                   "if (type(k) == \"string\") then\ns = \"\\\"\"..k..\"\\\"\";\nend\n"
00095                   "if (type(v) == \"number\") then\nt = v;\nend\n"
00096                   "if (type(v) == \"string\") then\nt = \"\\\"\"..v..\"\\\"\";\nend\n"
00097                   "if (type(v) == \"boolean\") then\nif v then\nt = \"'true'\";\nelse\nt = \"'false'\";\nend\nend\n"
00098                   "if (type(v) == \"table\") then\n"
00099                       "t = \"'table'\";\nSendString(s..\" \"..t..\" \");\nConcTable(temp, tbl..\"[\"..s..\"]\");\n"
00100                   "else\n"
00101                       "SendString(s..\" \"..t..\" \");\n"
00102                   "end\n"
00103               "end\n"
00104               "SendString(\"'end' \");\n";
00105 
00106     luaL_dostring(pLua_, s.c_str());
00107 
00108     return sComString;
00109 }
00110 
00111 void state::copy_table(state& mLua, const std::string& sSrcName, const std::string& sDestName)
00112 {
00113     #ifdef DEBUG_STACK
00114     Log("copy_table : "+get_top());
00115     #endif
00116     std::string sNewName;
00117     if (sDestName == "") sNewName = sSrcName;
00118     else                 sNewName = sDestName;
00119 
00120     sComString = "";
00121     try
00122     {
00123         mLua.do_string("str = \"\";\nstr = ConcTable(str, \"" + sSrcName + "\");\n");
00124     }
00125     catch (exception& e)
00126     {
00127         throw exception("state", "copy_table : "+e.get_description());
00128     }
00129 
00130     std::string s = sComString;
00131 
00132     if (s != "")
00133     {
00134         std::string sTab = "    ";
00135         std::string sTable;
00136         sTable = sNewName + " = {\n";
00137         uint uiTableIndent = 1u;
00138         bool bTableended = false;
00139         uint uiLineNbr = 0u;
00140         while (!bTableended)
00141         {
00142             if (uiLineNbr > 1000u)
00143                 break;
00144 
00145             if (uiTableIndent == 0)
00146             {
00147                 bTableended = true;
00148             }
00149             else
00150             {
00151                 uint i = s.find(" ");
00152                 std::string sKey = s.substr(0, i);
00153                 ++i;
00154                 s.erase(0, i);
00155                 if (sKey == "'end'")
00156                 {
00157                     uiTableIndent--;
00158                     sTab = sTab.substr(0, sTab.size() - 4u);
00159                     if (uiTableIndent == 0)
00160                         sTable += "}\n";
00161                     else
00162                         sTable += sTab + "},\n";
00163                 }
00164                 else
00165                 {
00166                     sKey = "[" + sKey + "]";
00167 
00168                     i = s.find(" ");
00169                     std::string sValue = s.substr(0, i);
00170                     ++i;
00171                     s.erase(0, i);
00172 
00173                     int iType;
00174                     if (sValue == "'table'")
00175                         iType = TYPE_TABLE;
00176                     else
00177                     {
00178                         iType = TYPE_NUMBER;
00179                         if (sValue.find("\"") != std::string::npos)
00180                         {
00181                             iType = TYPE_STRING;
00182                         }
00183                         else
00184                         {
00185                             if (sValue.find("'") != std::string::npos)
00186                             {
00187                                 iType = TYPE_BOOLEAN;
00188                                 utils::trim(sValue, '\'');
00189                             }
00190                         }
00191                     }
00192 
00193                     if (iType == TYPE_NUMBER)
00194                     {
00195                         sTable += sTab + sKey + " = " + sValue + ";\n";
00196                     }
00197                     else if (iType == TYPE_NIL)
00198                     {
00199                         sTable += sTab + sKey + " = nil;\n";
00200                     }
00201                     else if (iType == TYPE_BOOLEAN)
00202                     {
00203                         sTable += sTab + sKey + " = " + sValue + ";\n";
00204                     }
00205                     else if (iType == TYPE_STRING)
00206                     {
00207                         sTable += sTab + sKey + " = " + sValue + ";\n";
00208                     }
00209                     else if (iType == TYPE_TABLE)
00210                     {
00211                         sTable += sTab + sKey + " = {\n";
00212                         sTab += "    ";
00213                     }
00214                 }
00215             }
00216         }
00217 
00218         mLua.do_string(sTable);
00219     }
00220     else
00221     {
00222         mLua.new_table();
00223         mLua.set_global(sNewName);
00224     }
00225     #ifdef DEBUG_STACK
00226     Log("~copy_table : "+get_top());
00227     #endif
00228 }
00229 
00230 int l_TreatError( lua_State* pLua )
00231 {
00232     if (!lua_isstring(pLua, -1))
00233         return 0;
00234 
00235     lua_Debug d;
00236 
00237     lua_getstack(pLua, 1, &d);
00238     lua_getinfo(pLua, "Sl", &d);
00239 
00240     std::string sError = std::string(d.short_src) + ":" + utils::to_string(int(d.currentline)) + ": " + std::string(lua_tostring(pLua, -1));
00241     lua_pushstring(pLua, sError.c_str());
00242 
00243     return 1;
00244 }
00245 
00246 void default_print_function(const std::string& s)
00247 {
00248     std::cerr << s << std::endl;
00249 }
00250 
00251 void state::do_file( const std::string& sFile )
00252 {
00253     #ifdef DEBUG_STACK
00254     Log("do_file : "+get_top()+" "+sFile);
00255     #endif
00256     if (utils::file_exists(sFile))
00257     {
00258         lua_pushcfunction(pLua_, pErrorFunction_);
00259         uint uiFuncPos = get_top();
00260 
00261         if (luaL_loadfile(pLua_, sFile.c_str()) != 0)
00262         {
00263             if (lua_isstring(pLua_, -1))
00264             {
00265                 std::string sError = lua_tostring(pLua_, -1);
00266                 lua_pop(pLua_, 1);
00267                 lua_remove(pLua_, uiFuncPos);
00268                 throw exception(sError);
00269             }
00270             else
00271             {
00272                 lua_remove(pLua_, uiFuncPos);
00273                 throw exception("state", "Cannot load file : \""+sFile+"\"");
00274             }
00275         }
00276 
00277         int iError = lua_pcall(pLua_, 0, LUA_MULTRET, -2);
00278         if (iError != 0)
00279         {
00280             if (lua_isstring(pLua_, -1))
00281             {
00282                 std::string sError = lua_tostring(pLua_, -1);
00283                 lua_pop(pLua_, 1);
00284                 lua_remove(pLua_, uiFuncPos);
00285                 throw exception(sError);
00286             }
00287             else
00288             {
00289                 lua_pop(pLua_, 1);
00290                 lua_remove(pLua_, uiFuncPos);
00291                 throw exception("state", "Unhandled error.");
00292             }
00293         }
00294 
00295         lua_remove(pLua_, uiFuncPos);
00296     }
00297     else
00298     {
00299         throw exception("state", "do_file : cannot open \""+sFile+"\".");
00300     }
00301     #ifdef DEBUG_STACK
00302     Log("~do_file : "+get_top()+" "+sFile);
00303     #endif
00304 }
00305 
00306 void state::do_string( const std::string& sStr )
00307 {
00308     #ifdef DEBUG_STACK
00309     Log("do_string : "+get_top()+" "+sStr);
00310     #endif
00311     lua_pushcfunction(pLua_, pErrorFunction_);
00312     uint uiFuncPos = get_top();
00313 
00314     if (luaL_loadstring(pLua_, sStr.c_str()) != 0)
00315     {
00316         if (lua_isstring(pLua_, -1))
00317         {
00318             std::string sError = lua_tostring(pLua_, -1);
00319             lua_settop(pLua_, uiFuncPos-1);
00320             throw exception(sError);
00321         }
00322         else
00323         {
00324             lua_settop(pLua_, uiFuncPos-1);
00325             throw exception("state", "Unhandled error.");
00326         }
00327     }
00328 
00329     int iError = lua_pcall(pLua_, 0, LUA_MULTRET, -2);
00330     if (iError != 0)
00331     {
00332         if (lua_isstring(pLua_, -1))
00333         {
00334             std::string sError = lua_tostring(pLua_, -1);
00335             lua_settop(pLua_, uiFuncPos-1);
00336             throw exception(sError);
00337         }
00338         else
00339         {
00340             lua_settop(pLua_, uiFuncPos-1);
00341             throw exception("state", "Unhandled error.");
00342         }
00343     }
00344 
00345     lua_remove(pLua_, uiFuncPos);
00346     #ifdef DEBUG_STACK
00347     Log("~do_string : "+get_top()+" "+sStr);
00348     #endif
00349 }
00350 
00351 void state::call_function( const std::string& sfunctionName )
00352 {
00353     #ifdef DEBUG_STACK
00354     Log("call_function : "+get_top()+" "+sfunctionName);
00355     #endif
00356     lua_pushcfunction(pLua_, pErrorFunction_);
00357     uint uiFuncPos = get_top();
00358 
00359     get_global(sfunctionName);
00360 
00361     if (lua_isnil(pLua_, -1))
00362     {
00363         lua_settop(pLua_, uiFuncPos-1);
00364         throw exception("state", "\""+sfunctionName+"\" doesn't exist.");
00365     }
00366 
00367     if (!lua_isfunction(pLua_, -1))
00368     {
00369         exception mExcept("state", "\""+sfunctionName+"\" is not a function ("+get_type_name(get_type())+" : "+get_value().to_string()+").");
00370         lua_settop(pLua_, uiFuncPos-1);
00371         throw mExcept;
00372     }
00373 
00374     int iError = lua_pcall(pLua_, 0, LUA_MULTRET, -2);
00375     if (iError != 0)
00376     {
00377         if (lua_isstring(pLua_, -1))
00378         {
00379             std::string sError = lua_tostring(pLua_, -1);
00380             lua_settop(pLua_, uiFuncPos-1);
00381             throw exception(sError);
00382         }
00383         else
00384         {
00385             lua_settop(pLua_, uiFuncPos-1);
00386             throw exception("state", "Unhandled error.");
00387         }
00388     }
00389 
00390     lua_remove(pLua_, uiFuncPos);
00391     #ifdef DEBUG_STACK
00392     Log("~call_function : "+get_top()+" "+sfunctionName);
00393     #endif
00394 }
00395 
00396 void state::call_function(const std::string& sfunctionName, const std::vector<var>& lArgumentStack)
00397 {
00398     #ifdef DEBUG_STACK
00399     Log("call_function : "+get_top()+" "+sfunctionName+"(args)");
00400     #endif
00401     lua_pushcfunction(pLua_, pErrorFunction_);
00402     uint uiFuncPos = get_top();
00403 
00404     get_global(sfunctionName);
00405 
00406     if (lua_isnil(pLua_, -1))
00407     {
00408         lua_settop(pLua_, uiFuncPos-1);
00409         throw exception("state", "\""+sfunctionName+"\" doesn't exist.");
00410     }
00411 
00412     if (lua_isfunction(pLua_, -1))
00413     {
00414         lua_settop(pLua_, uiFuncPos-1);
00415         throw exception("state", "\""+sfunctionName+"\" is not a function ("+get_type_name(get_type())+" : "+get_value().to_string()+")");
00416     }
00417 
00418     std::vector<var>::const_iterator iter;
00419     foreach (iter, lArgumentStack)
00420         push_var(*iter);
00421 
00422     int iError = lua_pcall(pLua_, lArgumentStack.size(), LUA_MULTRET, -2-lArgumentStack.size());
00423     if (iError != 0)
00424     {
00425         if (lua_isstring(pLua_, -1))
00426         {
00427             std::string sError = lua_tostring(pLua_, -1);
00428             lua_settop(pLua_, uiFuncPos-1);
00429             throw exception(sError);
00430         }
00431         else
00432         {
00433             lua_settop(pLua_, uiFuncPos-1);
00434             throw exception("state", "Unhandled error.");
00435         }
00436     }
00437 
00438     lua_remove(pLua_, uiFuncPos);
00439     #ifdef DEBUG_STACK
00440     Log("~call_function : "+get_top()+" "+sfunctionName+"(args)");
00441     #endif
00442 }
00443 
00444 void state::reg( const std::string& sfunctionName, c_function mFunction )
00445 {
00446     lua_register(pLua_, sfunctionName.c_str(), mFunction);
00447 }
00448 
00449 std::string state::format_error( const std::string& sError )
00450 {
00451     push_string(sError);
00452     (*pErrorFunction_)(pLua_);
00453     std::string sResult = get_string();
00454     pop(1);
00455 
00456     return sResult;
00457 }
00458 
00459 void state::print_error( const std::string& sError )
00460 {
00461     (*pPrintFunction_)(format_error(sError));
00462 }
00463 
00464 void state::set_lua_error_function( c_function pFunc )
00465 {
00466     if (pFunc != 0)
00467         pErrorFunction_ = pFunc;
00468     else
00469         pErrorFunction_ = &l_TreatError;
00470 }
00471 
00472 void state::set_print_error_function( print_function pFunc )
00473 {
00474     if (pFunc != 0)
00475         pPrintFunction_ = pFunc;
00476     else
00477         pPrintFunction_ = &default_print_function;
00478 }
00479 
00480 bool state::is_serializable( int iIndex )
00481 {
00482     if (lua_getmetatable(pLua_, iIndex))
00483     {
00484         pop();
00485         get_field("serialize", iIndex);
00486         if (get_type() == TYPE_FUNCTION)
00487         {
00488             pop();
00489             return true;
00490         }
00491         pop();
00492     }
00493 
00494     type mType = get_type(iIndex);
00495     return (mType == TYPE_BOOLEAN) || (mType == TYPE_NUMBER) ||
00496            (mType == TYPE_STRING)  || (mType == TYPE_TABLE);
00497 }
00498 
00499 std::string state::serialize_global( const std::string& sName )
00500 {
00501     get_global(sName);
00502 
00503     std::string sContent;
00504     if (is_serializable())
00505         sContent = sName+" = "+serialize()+";";
00506 
00507     pop();
00508 
00509     return sContent;
00510 }
00511 
00512 std::string state::serialize( const std::string& sTab, int iIndex )
00513 {
00514     #ifdef DEBUG_STACK
00515     Log("serialize : "+get_top()+" "+sTab);
00516     #endif
00517     int iAbsoluteIndex = iIndex >= 0 ? iIndex : int(get_top()+1) + iIndex;
00518     std::string sResult;
00519 
00520     if (lua_getmetatable(pLua_, iAbsoluteIndex))
00521     {
00522         pop();
00523         get_field("serialize", iAbsoluteIndex);
00524         if (get_type() == TYPE_FUNCTION)
00525         {
00526             pushValue(iAbsoluteIndex);
00527             push_string(sTab);
00528             int iError = lua_pcall(pLua_, 2, 1, 0);
00529             if (iError == 0)
00530             {
00531                 sResult += get_string();
00532                 pop();
00533                 return sResult;
00534             }
00535         }
00536         else
00537             pop();
00538     }
00539 
00540     type mType = get_type(iIndex);
00541     switch (mType)
00542     {
00543         case TYPE_BOOLEAN :
00544             sResult += utils::to_string(get_bool(iIndex));
00545             break;
00546 
00547         case TYPE_NUMBER :
00548             sResult += utils::to_string(get_number(iIndex));
00549             break;
00550 
00551         case TYPE_STRING :
00552             sResult += "\""+get_string(iIndex)+"\"";
00553             break;
00554 
00555         case TYPE_TABLE :
00556         {
00557             sResult += "{";
00558 
00559             std::string sContent = "\n";
00560             pushValue(iIndex);
00561             push_nil();
00562             while (lua_next(pLua_, -2) != 0)
00563             {
00564                 if (is_serializable())
00565                 {
00566                     sContent += sTab + "    [" + serialize(sTab + "    ", -2) + "] = "
00567                             + serialize(sTab + "    ", -1) + ",\n";
00568                 }
00569                 pop();
00570             }
00571             pop();
00572 
00573             if (sContent != "\n")
00574                 sResult + sContent + sTab;
00575 
00576             sResult += "}";
00577             break;
00578         }
00579 
00580         default : break;
00581     }
00582 
00583     #ifdef DEBUG_STACK
00584     Log("~serialize : "+get_top()+" "+sTab);
00585     #endif
00586 
00587     return sResult;
00588 }
00589 
00590 void state::push_number( const double& dValue )
00591 {
00592     lua_pushnumber(pLua_, dValue);
00593 }
00594 
00595 void state::push_bool( bool bValue )
00596 {
00597     lua_pushboolean(pLua_, bValue);
00598 }
00599 
00600 void state::push_string( const std::string& sValue )
00601 {
00602     lua_pushstring(pLua_, sValue.c_str());
00603 }
00604 
00605 void state::push_nil( uint uiNumber )
00606 {
00607     for (uint ui = 0u; ui < uiNumber; ++ui)
00608         lua_pushnil(pLua_);
00609 }
00610 
00611 void state::push_var( const var& vValue )
00612 {
00613     const var_type& mType = vValue.get_type();
00614     if (mType == var::VALUE_INT) push_number(vValue.get<int>());
00615     else if (mType == var::VALUE_UINT) push_number(vValue.get<uint>());
00616     else if (mType == var::VALUE_FLOAT) push_number(vValue.get<float>());
00617     else if (mType == var::VALUE_DOUBLE) push_number(vValue.get<double>());
00618     else if (mType == var::VALUE_STRING) push_string(vValue.get<std::string>());
00619     else if (mType == var::VALUE_BOOL) push_bool(vValue.get<bool>());
00620     else push_nil();
00621 }
00622 
00623 void state::pushValue( int iIndex )
00624 {
00625     lua_pushvalue(pLua_, iIndex);
00626 }
00627 
00628 void state::push_global( const std::string& sName )
00629 {
00630     get_global(sName);
00631 }
00632 
00633 void state::set_global( const std::string& sName )
00634 {
00635     #ifdef DEBUG_STACK
00636     Log("set_global : "+get_top()+" "+sName);
00637     #endif
00638     std::deque<std::string> lDecomposedName;
00639     std::string sVarName;
00640     utils::string_vector lWords = utils::cut(sName, ":");
00641     utils::string_vector::iterator iter1;
00642     foreach (iter1, lWords)
00643     {
00644         utils::string_vector lSubWords = utils::cut(*iter1, ".");
00645         utils::string_vector::iterator iter2;
00646         foreach (iter2, lSubWords)
00647         {
00648             lDecomposedName.push_back(*iter2);
00649         }
00650     }
00651 
00652     // Start at 1 to pop the value the user has put on the stack.
00653     uint uiCounter = 1;
00654 
00655     sVarName = lDecomposedName.back();
00656     lDecomposedName.pop_back();
00657 
00658     if (lDecomposedName.size() >= 1)
00659     {
00660         lua_getglobal(pLua_, lDecomposedName.begin()->c_str());
00661         lDecomposedName.pop_front();
00662         ++uiCounter;
00663 
00664         if (!lua_isnil(pLua_, -1))
00665         {
00666             std::deque<std::string>::iterator iterWords;
00667             foreach (iterWords, lDecomposedName)
00668             {
00669                 lua_getfield(pLua_, -1, iterWords->c_str());
00670                 ++uiCounter;
00671                 if (lua_isnil(pLua_, -1))
00672                 {
00673                     pop(uiCounter);
00674                     return;
00675                 }
00676             }
00677         }
00678 
00679         lua_pushvalue(pLua_, (-uiCounter));
00680         lua_setfield(pLua_, -2, sVarName.c_str());
00681         pop(uiCounter);
00682     }
00683     else
00684     {
00685         lua_setglobal(pLua_, sName.c_str());
00686     }
00687     #ifdef DEBUG_STACK
00688     Log("~set_global : "+get_top()+" "+sName);
00689     #endif
00690 }
00691 
00692 void state::new_table()
00693 {
00694     #ifdef DEBUG_STACK
00695     Log("new_table : "+get_top());
00696     #endif
00697     lua_newtable(pLua_);
00698     #ifdef DEBUG_STACK
00699     Log("~new_table : "+get_top());
00700     #endif
00701 }
00702 
00703 bool state::next( int iIndex )
00704 {
00705     #ifdef DEBUG_STACK
00706     Log("next : "+get_top());
00707     #endif
00708     int res = lua_next(pLua_, iIndex);
00709     #ifdef DEBUG_STACK
00710     Log("~next : "+get_top());
00711     #endif
00712     return res != 0;
00713 }
00714 
00715 void state::pop( uint uiNumber )
00716 {
00717     #ifdef DEBUG_STACK
00718     Log("pop : "+get_top()+" "+uiNumber);
00719     #endif
00720     lua_pop(pLua_, static_cast<int>(uiNumber));
00721     #ifdef DEBUG_STACK
00722     Log("~pop : "+get_top()+" "+uiNumber);
00723     #endif
00724 }
00725 
00726 double state::get_number( int iIndex )
00727 {
00728     return static_cast<float>(lua_tonumber(pLua_, iIndex));
00729 }
00730 
00731 bool state::get_bool( int iIndex )
00732 {
00733     return lua_toboolean(pLua_, iIndex) != 0;
00734 }
00735 
00736 std::string state::get_string( int iIndex )
00737 {
00738     return lua_tostring(pLua_, iIndex);
00739 }
00740 
00741 var state::get_value( int iIndex )
00742 {
00743     int type = lua_type(pLua_, iIndex);
00744     switch (type)
00745     {
00746         case LUA_TBOOLEAN : return get_bool(iIndex);
00747         case LUA_TNUMBER : return get_number(iIndex);
00748         case LUA_TSTRING : return get_string(iIndex);
00749         default : return var();
00750     }
00751 }
00752 
00753 uint state::get_top()
00754 {
00755     return lua_gettop(pLua_);
00756 }
00757 
00758 type state::get_type( int iIndex )
00759 {
00760     int type = lua_type(pLua_, iIndex);
00761     switch (type)
00762     {
00763         case LUA_TBOOLEAN : return TYPE_BOOLEAN;
00764         case LUA_TFUNCTION : return TYPE_FUNCTION;
00765         case LUA_TLIGHTUSERDATA : return TYPE_LIGHTUSERDATA;
00766         case LUA_TNIL : return TYPE_NIL;
00767         case LUA_TNONE : return TYPE_NONE;
00768         case LUA_TNUMBER : return TYPE_NUMBER;
00769         case LUA_TSTRING : return TYPE_STRING;
00770         case LUA_TTABLE : return TYPE_TABLE;
00771         case LUA_TTHREAD : return TYPE_THREAD;
00772         case LUA_TUSERDATA : return TYPE_USERDATA;
00773         default : return TYPE_NONE;
00774     }
00775 }
00776 
00777 std::string state::get_type_name( type mType )
00778 {
00779     switch (mType)
00780     {
00781         case TYPE_BOOLEAN : return lua_typename(pLua_, LUA_TBOOLEAN);
00782         case TYPE_FUNCTION : return lua_typename(pLua_, LUA_TFUNCTION);
00783         case TYPE_LIGHTUSERDATA : return lua_typename(pLua_, LUA_TLIGHTUSERDATA);
00784         case TYPE_NIL : return lua_typename(pLua_, LUA_TNIL);
00785         case TYPE_NONE : return lua_typename(pLua_, LUA_TNONE);
00786         case TYPE_NUMBER : return lua_typename(pLua_, LUA_TNUMBER);
00787         case TYPE_STRING : return lua_typename(pLua_, LUA_TSTRING);
00788         case TYPE_TABLE : return lua_typename(pLua_, LUA_TTABLE);
00789         case TYPE_THREAD : return lua_typename(pLua_, LUA_TTHREAD);
00790         case TYPE_USERDATA : return lua_typename(pLua_, LUA_TUSERDATA);
00791         default : return "";
00792     }
00793 }
00794 
00795 void state::get_global( const std::string& sName )
00796 {
00797     #ifdef DEBUG_STACK
00798     Log("get_global : "+get_top()+" "+sName);
00799     #endif
00800     std::deque<std::string> lDecomposedName;
00801     std::string sVarName;
00802     utils::string_vector lWords = utils::cut(sName, ":");
00803     utils::string_vector::iterator iter1;
00804     foreach (iter1, lWords)
00805     {
00806         utils::string_vector lSubWords = utils::cut(*iter1, ".");
00807         utils::string_vector::iterator iter2;
00808         foreach (iter2, lSubWords)
00809         {
00810             lDecomposedName.push_back(*iter2);
00811         }
00812     }
00813 
00814     lua_getglobal(pLua_, lDecomposedName.front().c_str());
00815 
00816     if (lDecomposedName.size() > 1)
00817     {
00818         if (lua_isnil(pLua_, -1))
00819             return;
00820 
00821         lDecomposedName.pop_front();
00822 
00823         std::deque<std::string>::iterator iterWords;
00824         foreach (iterWords, lDecomposedName)
00825         {
00826             lua_getfield(pLua_, -1, iterWords->c_str());
00827             lua_remove(pLua_, -2);
00828 
00829             if (lua_isnil(pLua_, -1))
00830                 return;
00831 
00832             if (!lua_istable(pLua_, -1) && iterWords+1 != lDecomposedName.end())
00833             {
00834                 lua_pop(pLua_, 1);
00835                 lua_pushnil(pLua_);
00836                 return;
00837             }
00838         }
00839     }
00840 
00841     #ifdef DEBUG_STACK
00842     Log("~get_global : "+get_top()+" "+sName);
00843     #endif
00844 }
00845 
00846 int state::get_global_int( const std::string& sName, bool bCritical, int iDefaultValue )
00847 {
00848     #ifdef DEBUG_STACK
00849     Log("get_global_int : "+get_top()+" "+sName);
00850     #endif
00851     int i;
00852     get_global(sName);
00853     if (lua_isnil(pLua_, -1))
00854     {
00855         lua_pop(pLua_, 1);
00856         if (bCritical)
00857         {
00858             print_error("Missing " + sName + " attribute");
00859             i = iDefaultValue;
00860         }
00861         else
00862             i = iDefaultValue;
00863     }
00864     else if (!lua_isnumber(pLua_, -1))
00865     {
00866         lua_pop(pLua_, 1);
00867         print_error("\"" + sName + "\" is expected to be a number");
00868         i = iDefaultValue;
00869     }
00870     else
00871     {
00872         i = (int)lua_tonumber(pLua_, -1);
00873         lua_pop(pLua_, 1);
00874     }
00875     #ifdef DEBUG_STACK
00876     Log("~get_global_int : "+get_top()+" "+sName);
00877     #endif
00878     return i;
00879 }
00880 
00881 double state::get_global_double( const std::string& sName, bool bCritical, double fDefaultValue )
00882 {
00883     #ifdef DEBUG_STACK
00884     Log("get_global_float : "+get_top()+" "+sName);
00885     #endif
00886     double f;
00887     get_global(sName);
00888     if (lua_isnil(pLua_, -1))
00889     {
00890         lua_pop(pLua_, 1);
00891         if (bCritical)
00892         {
00893             print_error("Missing " + sName + " attribute");
00894             f = fDefaultValue;
00895         }
00896         else
00897             f = fDefaultValue;
00898     }
00899     else if (!lua_isnumber(pLua_, -1))
00900     {
00901         lua_pop(pLua_, 1);
00902         print_error("\"" + sName + "\" is expected to be a number");
00903         f = fDefaultValue;
00904     }
00905     else
00906     {
00907         f = static_cast<double>(lua_tonumber(pLua_, -1));
00908         lua_pop(pLua_, 1);
00909     }
00910     #ifdef DEBUG_STACK
00911     Log("~get_global_float : "+get_top()+" "+sName);
00912     #endif
00913     return f;
00914 }
00915 
00916 std::string state::get_global_string( const std::string& sName, bool bCritical, const std::string& sDefaultValue )
00917 {
00918     #ifdef DEBUG_STACK
00919     Log("get_global_string : "+get_top()+" "+sName);
00920     #endif
00921     std::string s;
00922     get_global(sName);
00923     if (lua_isnil(pLua_, -1))
00924     {
00925         lua_pop(pLua_, 1);
00926         if (bCritical)
00927         {
00928             print_error("Missing " + sName + " attribute");
00929             s = sDefaultValue;
00930         }
00931         else
00932             s = sDefaultValue;
00933     }
00934     else if (!lua_isstring(pLua_, -1))
00935     {
00936         lua_pop(pLua_, 1);
00937         print_error("\"" + sName + "\" is expected to be a string");
00938         s = sDefaultValue;
00939     }
00940     else
00941     {
00942         s = lua_tostring(pLua_, -1);
00943         lua_pop(pLua_, 1);
00944     }
00945     #ifdef DEBUG_STACK
00946     Log("~get_global_string : "+get_top()+" "+sName);
00947     #endif
00948     return s;
00949 }
00950 
00951 bool state::get_global_bool( const std::string& sName, bool bCritical, bool bDefaultValue )
00952 {
00953     #ifdef DEBUG_STACK
00954     Log("get_global_bool : "+get_top()+" "+sName);
00955     #endif
00956     bool b;
00957     get_global(sName);
00958     if (lua_isnil(pLua_, -1))
00959     {
00960         lua_pop(pLua_, 1);
00961         if (bCritical)
00962         {
00963             print_error("Missing " + sName + " attribute");
00964             b = bDefaultValue;
00965         }
00966         else
00967             b = bDefaultValue;
00968     }
00969     else if (!lua_isboolean(pLua_, -1))
00970     {
00971         lua_pop(pLua_, 1);
00972         print_error("\"" + sName + "\" is expected to be a bool");
00973         b = bDefaultValue;
00974     }
00975     else
00976     {
00977         b = (lua_toboolean(pLua_, -1) != 0);
00978         lua_pop(pLua_, 1);
00979     }
00980     #ifdef DEBUG_STACK
00981     Log("~get_global_bool : "+get_top()+" "+sName);
00982     #endif
00983     return b;
00984 }
00985 
00986 void state::get_field( const std::string& sName, int iIndex )
00987 {
00988     #ifdef DEBUG_STACK
00989     Log("get_field : "+get_top()+" "+sName);
00990     #endif
00991     lua_getfield(pLua_, iIndex, sName.c_str());
00992     #ifdef DEBUG_STACK
00993     Log("~get_field : "+get_top()+" "+sName);
00994     #endif
00995 }
00996 
00997 void state::get_field( int iID, int iIndex )
00998 {
00999     #ifdef DEBUG_STACK
01000     Log("get_field : "+get_top()+" "+iID);
01001     #endif
01002     lua_pushnumber(pLua_, iID);
01003     if (iIndex >= 0)
01004         lua_gettable(pLua_, iIndex);
01005     else
01006         lua_gettable(pLua_, iIndex - 1);
01007     #ifdef DEBUG_STACK
01008     Log("~get_field : "+get_top()+" "+iID);
01009     #endif
01010 }
01011 
01012 int state::get_field_int( const std::string& sName, bool bCritical, int iDefaultValue, bool bSetValue )
01013 {
01014     #ifdef DEBUG_STACK
01015     Log("get_field_int : "+get_top()+" "+sName);
01016     #endif
01017     int i = 0;
01018     lua_getfield(pLua_, -1, sName.c_str());
01019     if (lua_isnil(pLua_, -1))
01020     {
01021         lua_pop(pLua_, 1);
01022         if (bCritical)
01023             print_error("Missing " + sName + " attribute");
01024         else if (bSetValue)
01025         {
01026             set_field_int(sName, iDefaultValue);
01027             i = iDefaultValue;
01028         }
01029         else
01030             i = iDefaultValue;
01031     }
01032     else if (!lua_isnumber(pLua_, -1))
01033     {
01034         print_error("Field is expected to be a number");
01035         lua_pop(pLua_, 1);
01036         i = iDefaultValue;
01037     }
01038     else
01039     {
01040         i = (int)lua_tonumber(pLua_, -1);
01041         lua_pop(pLua_, 1);
01042     }
01043     #ifdef DEBUG_STACK
01044     Log("~get_field_int : "+get_top()+" "+sName);
01045     #endif
01046     return i;
01047 }
01048 
01049 double state::get_field_double( const std::string& sName, bool bCritical, double fDefaultValue, bool bSetValue )
01050 {
01051     #ifdef DEBUG_STACK
01052     Log("get_field_float : "+get_top()+" "+sName);
01053     #endif
01054     double f = 0.0f;
01055     lua_getfield(pLua_, -1, sName.c_str());
01056     if (lua_isnil(pLua_, -1))
01057     {
01058         lua_pop(pLua_, 1);
01059         if (bCritical)
01060             print_error("Missing " + sName + " attribute");
01061         else if (bSetValue)
01062         {
01063             set_field_double(sName, fDefaultValue);
01064             f = fDefaultValue;
01065         }
01066         else
01067             f = fDefaultValue;
01068     }
01069     else if (!lua_isnumber(pLua_, -1))
01070     {
01071         print_error("Field is expected to be a number");
01072         lua_pop(pLua_, 1);
01073         f = fDefaultValue;
01074     }
01075     else
01076     {
01077         f = static_cast<double>(lua_tonumber(pLua_, -1));
01078         lua_pop(pLua_, 1);
01079 
01080     }
01081     #ifdef DEBUG_STACK
01082     Log("~get_field_float : "+get_top()+" "+sName);
01083     #endif
01084     return f;
01085 }
01086 
01087 std::string state::get_field_string( const std::string& sName, bool bCritical, const std::string& sDefaultValue, bool bSetValue )
01088 {
01089     #ifdef DEBUG_STACK
01090     Log("get_field_string : "+get_top()+" "+sName);
01091     #endif
01092     std::string s;
01093     lua_getfield(pLua_, -1, sName.c_str());
01094     if (lua_isnil(pLua_, -1))
01095     {
01096         lua_pop(pLua_, 1);
01097         if (bCritical)
01098             print_error("Missing " + sName + " attribute");
01099         else if (bSetValue)
01100         {
01101             set_field_string(sName, sDefaultValue);
01102             s = sDefaultValue;
01103         }
01104         else
01105             s = sDefaultValue;
01106     }
01107     else if (!lua_isstring(pLua_, -1))
01108     {
01109         print_error("Field is expected to be a string");
01110         lua_pop(pLua_, 1);
01111         s = sDefaultValue;
01112     }
01113     else
01114     {
01115         s = lua_tostring(pLua_, -1);
01116         lua_pop(pLua_, 1);
01117     }
01118     #ifdef DEBUG_STACK
01119     Log("~get_field_string : "+get_top()+" "+sName);
01120     #endif
01121     return s;
01122 }
01123 
01124 bool state::get_field_bool( const std::string& sName, bool bCritical, bool bDefaultValue, bool bSetValue )
01125 {
01126     #ifdef DEBUG_STACK
01127     Log("get_fieldBool : "+get_top()+" "+sName);
01128     #endif
01129     bool b = false;
01130     lua_getfield(pLua_, -1, sName.c_str());
01131     if (lua_isnil(pLua_, -1))
01132     {
01133         lua_pop(pLua_, 1);
01134         if (bCritical)
01135             print_error("Missing " + sName + " attribute");
01136         else if (bSetValue)
01137         {
01138             set_field_bool(sName, bDefaultValue);
01139             b = bDefaultValue;
01140         }
01141         else
01142             b = bDefaultValue;
01143     }
01144     else if (!lua_isboolean(pLua_, -1))
01145     {
01146         print_error("Field is expected to be a bool");
01147         lua_pop(pLua_, 1);
01148         b = bDefaultValue;
01149     }
01150     else
01151     {
01152         b = (lua_toboolean(pLua_, -1) != 0);
01153         lua_pop(pLua_, 1);
01154     }
01155     #ifdef DEBUG_STACK
01156     Log("~get_fieldBool : "+get_top()+" "+sName);
01157     #endif
01158     return b;
01159 }
01160 
01161 void state::set_field( const std::string& sName )
01162 {
01163     #ifdef DEBUG_STACK
01164     Log("set_field : "+get_top()+" "+sName);
01165     #endif
01166     lua_pushstring(pLua_, sName.c_str());
01167     lua_pushvalue(pLua_, -2);
01168     lua_settable(pLua_, -4);
01169     lua_pop(pLua_, 1);
01170     #ifdef DEBUG_STACK
01171     Log("~set_field : "+get_top()+" "+sName);
01172     #endif
01173 }
01174 
01175 void state::set_field( int iID )
01176 {
01177     #ifdef DEBUG_STACK
01178     Log("set_field : "+get_top()+" "+iID);
01179     #endif
01180     lua_pushnumber(pLua_, iID);
01181     lua_pushvalue(pLua_, -2);
01182     lua_settable(pLua_, -4);
01183     lua_pop(pLua_, 1);
01184     #ifdef DEBUG_STACK
01185     Log("~set_field : "+get_top()+" "+iID);
01186     #endif
01187 }
01188 
01189 void state::set_field_int( const std::string& sName, int iValue )
01190 {
01191     #ifdef DEBUG_STACK
01192     Log("set_field_int : "+get_top()+" "+sName);
01193     #endif
01194     lua_pushstring(pLua_, sName.c_str());
01195     lua_pushnumber(pLua_, iValue);
01196     lua_settable(pLua_, -3);
01197     #ifdef DEBUG_STACK
01198     Log("~set_field_int : "+get_top()+" "+sName);
01199     #endif
01200 }
01201 
01202 void state::set_field_double( const std::string& sName, double fValue )
01203 {
01204     #ifdef DEBUG_STACK
01205     Log("set_field_double : "+get_top()+" "+sName);
01206     #endif
01207     lua_pushstring(pLua_, sName.c_str());
01208     lua_pushnumber(pLua_, fValue);
01209     lua_settable(pLua_, -3);
01210     #ifdef DEBUG_STACK
01211     Log("~set_field_double : "+get_top()+" "+sName);
01212     #endif
01213 }
01214 
01215 void state::set_field_string( const std::string& sName, const std::string& sValue )
01216 {
01217     #ifdef DEBUG_STACK
01218     Log("set_field_string : "+get_top()+" "+sName);
01219     #endif
01220     lua_pushstring(pLua_, sName.c_str());
01221     lua_pushstring(pLua_, sValue.c_str());
01222     lua_settable(pLua_, -3);
01223     #ifdef DEBUG_STACK
01224     Log("~set_field_string : "+get_top()+" "+sName);
01225     #endif
01226 }
01227 
01228 void state::set_field_bool( const std::string& sName, bool bValue )
01229 {
01230     #ifdef DEBUG_STACK
01231     Log("set_field_bool : "+get_top()+" "+sName);
01232     #endif
01233     lua_pushstring(pLua_, sName.c_str());
01234     lua_pushboolean(pLua_, bValue);
01235     lua_settable(pLua_, -3);
01236     #ifdef DEBUG_STACK
01237     Log("~set_field_bool : "+get_top()+" "+sName);
01238     #endif
01239 }
01240 
01241 void state::set_field_int( int iID, int iValue )
01242 {
01243     #ifdef DEBUG_STACK
01244     Log("set_field_int : "+get_top()+" "+iID);
01245     #endif
01246     lua_pushnumber(pLua_, iID);
01247     lua_pushnumber(pLua_, iValue);
01248     lua_settable(pLua_, -3);
01249     #ifdef DEBUG_STACK
01250     Log("~set_field_int : "+get_top()+" "+iID);
01251     #endif
01252 }
01253 
01254 void state::set_field_double( int iID, double fValue )
01255 {
01256     #ifdef DEBUG_STACK
01257     Log("set_field_double : "+get_top()+" "+iID);
01258     #endif
01259     lua_pushnumber(pLua_, iID);
01260     lua_pushnumber(pLua_, fValue);
01261     lua_settable(pLua_, -3);
01262     #ifdef DEBUG_STACK
01263     Log("~set_field_double : "+get_top()+" "+iID);
01264     #endif
01265 }
01266 
01267 void state::set_field_string( int iID, const std::string& sValue )
01268 {
01269     #ifdef DEBUG_STACK
01270     Log("set_field_string : "+get_top()+" "+iID);
01271     #endif
01272     lua_pushnumber(pLua_, iID);
01273     lua_pushstring(pLua_, sValue.c_str());
01274     lua_settable(pLua_, -3);
01275     #ifdef DEBUG_STACK
01276     Log("~set_field_string : "+get_top()+" "+iID);
01277     #endif
01278 }
01279 
01280 void state::set_field_bool( int iID, bool bValue )
01281 {
01282     #ifdef DEBUG_STACK
01283     Log("set_field_bool : "+get_top()+" "+iID);
01284     #endif
01285     lua_pushnumber(pLua_, iID);
01286     lua_pushboolean(pLua_, bValue);
01287     lua_settable(pLua_, -3);
01288     #ifdef DEBUG_STACK
01289     Log("~set_field_bool : "+get_top()+" "+iID);
01290     #endif
01291 }
01292 
01293 void state::set_top( uint uiSize )
01294 {
01295     #ifdef DEBUG_STACK
01296     Log("SetTop : "+uiSize);
01297     #endif
01298     lua_settop(pLua_, uiSize);
01299 }
01300 }