LuaStack.cpp 4.2 KB

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