123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257 |
- /*
- * LuaStack.cpp, part of VCMI engine
- *
- * Authors: listed in file AUTHORS in main folder
- *
- * License: GNU General Public License v2.0 or later
- * Full text of license available in license.txt file, in main folder
- *
- */
- #include "StdInc.h"
- #include "LuaStack.h"
- #include "../../lib/json/JsonNode.h"
- #include "../../lib/int3.h"
- VCMI_LIB_NAMESPACE_BEGIN
- namespace scripting
- {
- LuaStack::LuaStack(lua_State * L_):
- L(L_),
- initialTop(lua_gettop(L))
- {
- }
- void LuaStack::balance()
- {
- lua_settop(L, initialTop);
- }
- void LuaStack::clear()
- {
- lua_settop(L, 0);
- }
- void LuaStack::pushByIndex(lua_Integer index)
- {
- lua_pushvalue(L, index);
- }
- void LuaStack::pushNil()
- {
- lua_pushnil(L);
- }
- void LuaStack::pushInteger(lua_Integer value)
- {
- lua_pushinteger(L, value);
- }
- void LuaStack::push(bool value)
- {
- lua_pushboolean(L, value);
- }
- void LuaStack::push(const char * value)
- {
- lua_pushstring(L, value);
- }
- void LuaStack::push(const std::string & value)
- {
- lua_pushlstring(L, value.c_str(), value.size());
- }
- void LuaStack::push(const int3 & value)
- {
- push(value.x);
- push(value.y);
- push(value.z);
- }
- void LuaStack::push(const JsonNode & value)
- {
- switch(value.getType())
- {
- case JsonNode::JsonType::DATA_BOOL:
- {
- push(value.Bool());
- }
- break;
- case JsonNode::JsonType::DATA_FLOAT:
- {
- lua_pushnumber(L, value.Float());
- }
- break;
- case JsonNode::JsonType::DATA_INTEGER:
- {
- pushInteger(value.Integer());
- }
- break;
- case JsonNode::JsonType::DATA_STRUCT:
- {
- lua_newtable(L);
- for(const auto & keyValue : value.Struct())
- {
- push(keyValue.first);
- push(keyValue.second);
- lua_rawset(L, -3);
- }
- }
- break;
- case JsonNode::JsonType::DATA_STRING:
- push(value.String());
- break;
- case JsonNode::JsonType::DATA_VECTOR:
- {
- lua_newtable(L);
- for(int idx = 0; idx < value.Vector().size(); idx++)
- {
- pushInteger(idx + 1);
- push(value.Vector()[idx]);
- lua_rawset(L, -3);
- }
- }
- break;
- default:
- pushNil();
- break;
- }
- }
- bool LuaStack::tryGet(int position, bool & value)
- {
- if(!lua_isboolean(L, position))
- return false;
- value = (lua_toboolean(L, position) != 0);
- return true;
- }
- bool LuaStack::tryGet(int position, double & value)
- {
- if(!lua_isnumber(L, position))
- return false;
- value = lua_tonumber(L, position);
- return true;
- }
- bool LuaStack::tryGetInteger(int position, lua_Integer & value)
- {
- if(!lua_isnumber(L, position))
- return false;
- value = lua_tointeger(L, position);
- return true;
- }
- bool LuaStack::tryGet(int position, std::string & value)
- {
- if(!lua_isstring(L, position))
- return false;
- size_t len = 0;
- const auto *raw = lua_tolstring(L, position, &len);
- value = std::string(raw, len);
- return true;
- }
- bool LuaStack::tryGet(int position, int3 & value)
- {
- return tryGet(position, value.x) && tryGet(position+1, value.y) && tryGet(position+2, value.z);
- }
- bool LuaStack::tryGet(int position, JsonNode & value)
- {
- auto type = lua_type(L, position);
- switch(type)
- {
- case LUA_TNIL:
- value.clear();
- return true;
- case LUA_TNUMBER:
- return tryGet(position, value.Float());
- case LUA_TBOOLEAN:
- value.Bool() = (lua_toboolean(L, position) != 0);
- return true;
- case LUA_TSTRING:
- return tryGet(position, value.String());
- case LUA_TTABLE:
- {
- JsonNode asVector;
- JsonNode asStruct;
- lua_pushnil(L); /* first key */
- while(lua_next(L, position) != 0)
- {
- /* 'key' (at index -2) and 'value' (at index -1) */
- JsonNode fieldValue;
- if(!tryGet(lua_gettop(L), fieldValue))
- {
- lua_pop(L, 2);
- value.clear();
- return false;
- }
- lua_pop(L, 1); //pop value
- if(lua_type(L, -1) == LUA_TNUMBER)
- {
- auto key = lua_tointeger(L, -1);
- if(key > 0)
- {
- if(asVector.Vector().size() < key)
- asVector.Vector().resize(key);
- --key;
- asVector.Vector().at(key) = fieldValue;
- }
- }
- else if(lua_isstring(L, -1))
- {
- std::string key;
- tryGet(-1, key);
- asStruct[key] = fieldValue;
- }
- }
- if(!asVector.Vector().empty())
- {
- std::swap(value, asVector);
- }
- else
- {
- std::swap(value, asStruct);
- }
- }
- return true;
- default:
- value.clear();
- return false;
- }
- }
- int LuaStack::retNil()
- {
- clear();
- pushNil();
- return 1;
- }
- int LuaStack::retVoid()
- {
- clear();
- return 0;
- }
- }
- VCMI_LIB_NAMESPACE_END
|