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