2
0

LuaStack.cpp 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257
  1. /*
  2. * LuaStack.cpp, part of VCMI engine
  3. *
  4. * Authors: listed in file AUTHORS in main folder
  5. *
  6. * License: GNU General Public License v2.0 or later
  7. * Full text of license available in license.txt file, in main folder
  8. *
  9. */
  10. #include "StdInc.h"
  11. #include "LuaStack.h"
  12. #include "../../lib/json/JsonNode.h"
  13. #include "../../lib/int3.h"
  14. VCMI_LIB_NAMESPACE_BEGIN
  15. namespace scripting
  16. {
  17. LuaStack::LuaStack(lua_State * L_):
  18. L(L_),
  19. initialTop(lua_gettop(L))
  20. {
  21. }
  22. void LuaStack::balance()
  23. {
  24. lua_settop(L, initialTop);
  25. }
  26. void LuaStack::clear()
  27. {
  28. lua_settop(L, 0);
  29. }
  30. void LuaStack::pushByIndex(lua_Integer index)
  31. {
  32. lua_pushvalue(L, index);
  33. }
  34. void LuaStack::pushNil()
  35. {
  36. lua_pushnil(L);
  37. }
  38. void LuaStack::pushInteger(lua_Integer value)
  39. {
  40. lua_pushinteger(L, value);
  41. }
  42. void LuaStack::push(bool value)
  43. {
  44. lua_pushboolean(L, value);
  45. }
  46. void LuaStack::push(const char * value)
  47. {
  48. lua_pushstring(L, value);
  49. }
  50. void LuaStack::push(const std::string & value)
  51. {
  52. lua_pushlstring(L, value.c_str(), value.size());
  53. }
  54. void LuaStack::push(const int3 & value)
  55. {
  56. push(value.x);
  57. push(value.y);
  58. push(value.z);
  59. }
  60. void LuaStack::push(const JsonNode & value)
  61. {
  62. switch(value.getType())
  63. {
  64. case JsonNode::JsonType::DATA_BOOL:
  65. {
  66. push(value.Bool());
  67. }
  68. break;
  69. case JsonNode::JsonType::DATA_FLOAT:
  70. {
  71. lua_pushnumber(L, value.Float());
  72. }
  73. break;
  74. case JsonNode::JsonType::DATA_INTEGER:
  75. {
  76. pushInteger(value.Integer());
  77. }
  78. break;
  79. case JsonNode::JsonType::DATA_STRUCT:
  80. {
  81. lua_newtable(L);
  82. for(const auto & keyValue : value.Struct())
  83. {
  84. push(keyValue.first);
  85. push(keyValue.second);
  86. lua_rawset(L, -3);
  87. }
  88. }
  89. break;
  90. case JsonNode::JsonType::DATA_STRING:
  91. push(value.String());
  92. break;
  93. case JsonNode::JsonType::DATA_VECTOR:
  94. {
  95. lua_newtable(L);
  96. for(int idx = 0; idx < value.Vector().size(); idx++)
  97. {
  98. pushInteger(idx + 1);
  99. push(value.Vector()[idx]);
  100. lua_rawset(L, -3);
  101. }
  102. }
  103. break;
  104. default:
  105. pushNil();
  106. break;
  107. }
  108. }
  109. bool LuaStack::tryGet(int position, bool & value)
  110. {
  111. if(!lua_isboolean(L, position))
  112. return false;
  113. value = (lua_toboolean(L, position) != 0);
  114. return true;
  115. }
  116. bool LuaStack::tryGet(int position, double & value)
  117. {
  118. if(!lua_isnumber(L, position))
  119. return false;
  120. value = lua_tonumber(L, position);
  121. return true;
  122. }
  123. bool LuaStack::tryGetInteger(int position, lua_Integer & value)
  124. {
  125. if(!lua_isnumber(L, position))
  126. return false;
  127. value = lua_tointeger(L, position);
  128. return true;
  129. }
  130. bool LuaStack::tryGet(int position, std::string & value)
  131. {
  132. if(!lua_isstring(L, position))
  133. return false;
  134. size_t len = 0;
  135. const auto *raw = lua_tolstring(L, position, &len);
  136. value = std::string(raw, len);
  137. return true;
  138. }
  139. bool LuaStack::tryGet(int position, int3 & value)
  140. {
  141. return tryGet(position, value.x) && tryGet(position+1, value.y) && tryGet(position+2, value.z);
  142. }
  143. bool LuaStack::tryGet(int position, JsonNode & value)
  144. {
  145. auto type = lua_type(L, position);
  146. switch(type)
  147. {
  148. case LUA_TNIL:
  149. value.clear();
  150. return true;
  151. case LUA_TNUMBER:
  152. return tryGet(position, value.Float());
  153. case LUA_TBOOLEAN:
  154. value.Bool() = (lua_toboolean(L, position) != 0);
  155. return true;
  156. case LUA_TSTRING:
  157. return tryGet(position, value.String());
  158. case LUA_TTABLE:
  159. {
  160. JsonNode asVector;
  161. JsonNode asStruct;
  162. lua_pushnil(L); /* first key */
  163. while(lua_next(L, position) != 0)
  164. {
  165. /* 'key' (at index -2) and 'value' (at index -1) */
  166. JsonNode fieldValue;
  167. if(!tryGet(lua_gettop(L), fieldValue))
  168. {
  169. lua_pop(L, 2);
  170. value.clear();
  171. return false;
  172. }
  173. lua_pop(L, 1); //pop value
  174. if(lua_type(L, -1) == LUA_TNUMBER)
  175. {
  176. auto key = lua_tointeger(L, -1);
  177. if(key > 0)
  178. {
  179. if(asVector.Vector().size() < key)
  180. asVector.Vector().resize(key);
  181. --key;
  182. asVector.Vector().at(key) = fieldValue;
  183. }
  184. }
  185. else if(lua_isstring(L, -1))
  186. {
  187. std::string key;
  188. tryGet(-1, key);
  189. asStruct[key] = fieldValue;
  190. }
  191. }
  192. if(!asVector.Vector().empty())
  193. {
  194. std::swap(value, asVector);
  195. }
  196. else
  197. {
  198. std::swap(value, asStruct);
  199. }
  200. }
  201. return true;
  202. default:
  203. value.clear();
  204. return false;
  205. }
  206. }
  207. int LuaStack::retNil()
  208. {
  209. clear();
  210. pushNil();
  211. return 1;
  212. }
  213. int LuaStack::retVoid()
  214. {
  215. clear();
  216. return 0;
  217. }
  218. }
  219. VCMI_LIB_NAMESPACE_END