The Battle for Wesnoth  1.15.2+dev
lua_object.hpp
Go to the documentation of this file.
1 /*
2  Copyright (C) 2011 - 2018 by Dmitry Kovalenko <nephro.wes@gmail.com>
3  Part of the Battle for Wesnoth Project https://www.wesnoth.org/
4 
5  This program is free software; you can redistribute it and/or modify
6  it under the terms of the GNU General Public License as published by
7  the Free Software Foundation; either version 2 of the License, or
8  (at your option) any later version.
9  This program is distributed in the hope that it will be useful,
10  but WITHOUT ANY WARRANTY.
11 
12  See the COPYING file for more details.
13 */
14 
15 /**
16  * @file
17  * Lua object(value) wrapper implementation
18  */
19 
20 
21 #ifndef LUA_OBJECT_HPP_INCLUDED
22 #define LUA_OBJECT_HPP_INCLUDED
23 
24 #include "config.hpp"
25 #include "lua/lua.h"
26 #include "map/location.hpp"
27 #include "resources.hpp"
28 #include "scripting/lua_common.hpp"
29 #include "terrain/filter.hpp"
30 #include "variable.hpp"
31 #include "ai/default/contexts.hpp"
33 
34 #include <boost/variant/get.hpp>
35 #include <iterator>
36 #include <string>
37 #include <vector>
38 
39 
40 namespace ai {
41 
42 
44 
45 public:
47  virtual ~lua_object_base() {}
48 
49  virtual void store(lua_State* L, int n) = 0;
50 };
51 
52 template <typename T>
54 {
55 
56 public:
57 
59  : value_()
60  {
61  // empty
62  }
63 
64  lua_object(const T& init)
65  : value_(std::make_shared<T>(init))
66  {
67  // empty
68  }
69 
70  std::shared_ptr<T> get()
71  {
72  return value_;
73  }
74 
75  void store(lua_State* L, int n)
76  {
77  this->value_ = to_type(L, lua_absindex(L, n));
78  }
79 
80  void push(lua_State* L)
81  {
82  from_type(L, this->value_);
83  }
84 
85 protected:
86 
87  // A group of functions that deal with the translation of the results to C++
88  std::shared_ptr<T> to_type(lua_State *, int)
89  {
90  return std::shared_ptr<T>();
91  }
92 
93  // A group of functions that deal with the translations of values back to Lua
94  void from_type(lua_State* L, std::shared_ptr<T>)
95  {
96  lua_pushliteral(L, "Unsupported AI aspect type for Lua!");
97  lua_error(L);
98  }
99 
100  std::shared_ptr<T> value_;
101 };
102 
103 template <>
104 inline std::shared_ptr<double> lua_object<double>::to_type(lua_State *L, int n)
105 {
106  return std::make_shared<double>(lua_tonumber(L, n));
107 }
108 
109 template <>
110 inline void lua_object<double>::from_type(lua_State *L, std::shared_ptr<double> value)
111 {
112  if(value) lua_pushnumber(L, *value);
113  else lua_pushnil(L);
114 }
115 
116 template <>
117 inline std::shared_ptr<std::string> lua_object<std::string>::to_type(lua_State *L, int n)
118 {
119  return std::make_shared<std::string>(lua_tostring(L, n));
120 }
121 
122 template <>
123 inline void lua_object<boost::variant<bool, std::vector<std::string>>>::from_type(lua_State *L, std::shared_ptr<boost::variant<bool, std::vector<std::string>>> value)
124 {
125  if(value) {
126  if (value->which() == 0) {
127  lua_pushboolean(L, boost::get<bool>(*value));
128  } else {
129  std::vector<std::string> strlist = boost::get<std::vector<std::string>>(*value);
130  lua_createtable(L, strlist.size(), 0);
131  for(const std::string& str : strlist) {
132  lua_pushlstring(L, str.c_str(), str.size());
133  lua_rawseti(L, -2, lua_rawlen(L, -2) + 1);
134  }
135  }
136  } else lua_pushnil(L);
137 }
138 
139 template <>
140 inline std::shared_ptr< boost::variant<bool, std::vector<std::string>> > lua_object< boost::variant<bool, std::vector<std::string>> >::to_type(lua_State *L, int n)
141 {
142  if (lua_isboolean(L, n)) {
143  return std::make_shared<boost::variant<bool, std::vector<std::string>>>(luaW_toboolean(L, n));
144  } else {
145  std::shared_ptr<std::vector<std::string>> v(new std::vector<std::string>());
146  int l = lua_rawlen(L, n);
147  for (int i = 1; i < l + 1; ++i)
148  {
149  lua_pushinteger(L, i);
150  lua_gettable(L, n);
151  std::string s = lua_tostring(L, -1);
152  lua_settop(L, n);
153  v->push_back(s);
154  }
155 
156  return std::make_shared<boost::variant<bool, std::vector<std::string>>>(*v);
157  }
158 }
159 
160 template <>
161 inline void lua_object<std::string>::from_type(lua_State *L, std::shared_ptr<std::string> value)
162 {
163  if(value) lua_pushlstring(L, value->c_str(), value->size());
164  else lua_pushnil(L);
165 }
166 
167 template <>
168 inline std::shared_ptr<bool> lua_object<bool>::to_type(lua_State *L, int n)
169 {
170  return std::make_shared<bool>(luaW_toboolean(L, n));
171 }
172 
173 template <>
174 inline void lua_object<bool>::from_type(lua_State *L, std::shared_ptr<bool> value)
175 {
176  if(value) lua_pushboolean(L, *value);
177  else lua_pushnil(L);
178 }
179 
180 template <>
181 inline std::shared_ptr<int> lua_object<int>::to_type(lua_State *L, int n)
182 {
183  return std::make_shared<int>(static_cast<int>(lua_tointeger(L, n)));
184 }
185 
186 template <>
187 inline void lua_object<int>::from_type(lua_State *L, std::shared_ptr<int> value)
188 {
189  if(value) lua_pushnumber(L, *value);
190  else lua_pushnil(L);
191 }
192 
193 template <>
194 inline std::shared_ptr< std::vector<std::string> > lua_object< std::vector<std::string> >::to_type(lua_State *L, int n)
195 {
196  std::shared_ptr<std::vector<std::string>> v(new std::vector<std::string>());
197  int l = lua_rawlen(L, n);
198  for (int i = 1; i < l + 1; ++i)
199  {
200  lua_pushinteger(L, i);
201  lua_gettable(L, n);
202  std::string s = lua_tostring(L, -1);
203  lua_settop(L, n);
204  v->push_back(s);
205  }
206 
207  return v;
208 }
209 
210 template <>
211 inline void lua_object< std::vector<std::string> >::from_type(lua_State *L, std::shared_ptr< std::vector<std::string> > value)
212 {
213  if(value) {
214  lua_createtable(L, value->size(), 0);
215  for(const std::string& str : *value) {
216  lua_pushlstring(L, str.c_str(), str.size());
217  lua_rawseti(L, -2, lua_rawlen(L, -2) + 1);
218  }
219  } else lua_pushnil(L);
220 }
221 
222 template <>
223 inline std::shared_ptr<config> lua_object<config>::to_type(lua_State *L, int n)
224 {
225  std::shared_ptr<config> cfg(new config());
226  luaW_toconfig(L, n, *cfg);
227  return cfg;
228 }
229 
230 template <>
231 inline void lua_object<config>::from_type(lua_State *L, std::shared_ptr<config> value)
232 {
233  if(value) luaW_pushconfig(L, *value);
234  else lua_pushnil(L);
235 }
236 
237 template <>
238 inline std::shared_ptr<terrain_filter> lua_object<terrain_filter>::to_type(lua_State *L, int n)
239 {
240  std::shared_ptr<config> cfg(new config());
241  std::shared_ptr<vconfig> vcfg(new vconfig(*cfg));
242  if (!luaW_tovconfig(L, n, *vcfg)) {
243  cfg->add_child("not");
244  }
245  vcfg->make_safe();
246  std::shared_ptr<terrain_filter> tf(new terrain_filter(*vcfg, resources::filter_con));
247  return tf;
248 }
249 
250 template <>
251 inline void lua_object<terrain_filter>::from_type(lua_State *L, std::shared_ptr<terrain_filter> value)
252 {
253  if(value) {
254  std::set<map_location> locs;
255  value->get_locations(locs);
256  lua_createtable(L, locs.size(), 0);
257  for(const map_location& loc : locs) {
258  luaW_pushlocation(L, loc);
259  lua_rawseti(L, -2, lua_rawlen(L, -2) + 1);
260  }
261  } else lua_pushnil(L);
262 }
263 
264 template <>
265 inline std::shared_ptr<std::vector<target> > lua_object< std::vector<target> >::to_type(lua_State *L, int n)
266 {
267  std::shared_ptr<std::vector<target>> targets(new std::vector<target>());
268  std::back_insert_iterator< std::vector<target> > tg(*targets);
269  int l = lua_rawlen(L, n);
270 
271  for (int i = 1; i <= l; ++i)
272  {
273  lua_rawgeti(L, n, i); // st n + 1 TABLE @ N table @ n + 1
274 
275  lua_pushstring(L, "loc"); // st n + 2
276  lua_rawget(L, -2); // st n + 2
277 
278  lua_pushstring(L, "x"); // st n + 3
279  lua_rawget(L, -2); // st n + 3
280  int x = static_cast<int>(lua_tointeger(L, -1)); // st n + 3
281  lua_pop(L, 1); // st n + 2
282 
283  lua_pushstring(L, "y"); // st n + 3
284  lua_rawget(L, -2); // st n + 3
285  int y = static_cast<int>(lua_tointeger(L, -1)); // st n + 3
286 
287  lua_pop(L, 2); // st n + 1
288 
289  lua_pushstring(L, "type"); // st n + 2
290  lua_rawget(L, -2); // st n + 2
291  target::TYPE type = target::TYPE::EXPLICIT;
292  if(lua_isnumber(L, -1)) {
293  type = target::TYPE::from_int(static_cast<int>(lua_tointeger(L, -1))); // st n + 2
294  } else if(lua_isstring(L, -1)) {
295  type = target::TYPE::string_to_enum(lua_tostring(L, -1)); // st n + 2
296  }
297  lua_pop(L, 1); // st n + 1
298 
299 
300  lua_pushstring(L, "value");
301  lua_rawget(L, -2);
302  int value = static_cast<int>(lua_tointeger(L, -1));
303 
304  map_location ml(x, y, wml_loc());
305 
306  *tg = target(ml, value, type);
307  }
308 
309  lua_settop(L, n);
310  return targets;
311 }
312 
313 template <>
314 inline std::shared_ptr<unit_advancements_aspect> lua_object<unit_advancements_aspect>::to_type(lua_State *L, int n)
315 {
316  return std::make_shared<unit_advancements_aspect>(L, n);
317 }
318 
319 // This one is too complex to define in the header.
321 template <>
322 std::shared_ptr<aspect_attacks_lua_filter> lua_object<aspect_attacks_lua_filter>::to_type(lua_State *L, int n);
323 } // end of namespace ai
324 
325 
326 #endif
TYPE
UNSCALED : image will be drawn "as is" without changing size, even in case of redraw SCALED_TO_ZOOM :...
Definition: picture.hpp:185
LUA_API void lua_createtable(lua_State *L, int narray, int nrec)
Definition: lapi.cpp:684
lua_object(const T &init)
Definition: lua_object.hpp:64
bool luaW_tovconfig(lua_State *L, int index, vconfig &vcfg)
Gets an optional vconfig from either a table or a userdata.
Definition: lua_common.cpp:836
void luaW_pushconfig(lua_State *L, const config &cfg)
Converts a config object to a Lua table pushed at the top of the stack.
Definition: lua_common.cpp:730
LUA_API void lua_settop(lua_State *L, int idx)
Definition: lapi.cpp:172
LUA_API void lua_pushboolean(lua_State *L, int b)
Definition: lapi.cpp:557
LUA_API int lua_rawgeti(lua_State *L, int idx, lua_Integer n)
Definition: lapi.cpp:658
LUA_API void lua_rawseti(lua_State *L, int idx, lua_Integer n)
Definition: lapi.cpp:817
std::shared_ptr< T > value_
Definition: lua_object.hpp:100
LUA_API int lua_gettable(lua_State *L, int idx)
Definition: lapi.cpp:612
#define lua_tointeger(L, i)
Definition: lua.h:342
LUA_API int lua_rawget(lua_State *L, int idx)
Definition: lapi.cpp:647
STL namespace.
#define lua_tonumber(L, i)
Definition: lua.h:341
Definitions for the interface to Wesnoth Markup Language (WML).
LUA_API int lua_absindex(lua_State *L, int idx)
Definition: lapi.cpp:160
virtual ~lua_object_base()
Definition: lua_object.hpp:47
#define lua_pop(L, n)
Definition: lua.h:344
std::shared_ptr< T > to_type(lua_State *, int)
Definition: lua_object.hpp:88
A small explanation about what&#39;s going on here: Each action has access to two game_info objects First...
Definition: actions.cpp:58
virtual void store(lua_State *L, int n)=0
struct utils::detail::formula_initer init
LUA_API int lua_isstring(lua_State *L, int idx)
Definition: lapi.cpp:283
bool luaW_toboolean(lua_State *L, int n)
Definition: lua_common.cpp:890
void store(lua_State *L, int n)
Definition: lua_object.hpp:75
filter_context * filter_con
Definition: resources.cpp:23
void push(lua_State *L)
Definition: lua_object.hpp:80
LUA_API const char * lua_pushlstring(lua_State *L, const char *s, size_t len)
Definition: lapi.cpp:479
LUA_API void lua_pushnil(lua_State *L)
Definition: lapi.cpp:450
LUA_API void lua_pushnumber(lua_State *L, lua_Number n)
Definition: lapi.cpp:458
#define lua_pushliteral(L, s)
Definition: lua.h:361
Encapsulates the map of the game.
Definition: location.hpp:42
#define lua_isboolean(L, n)
Definition: lua.h:356
bool luaW_toconfig(lua_State *L, int index, config &cfg)
Converts an optional table or vconfig to a config object.
Definition: lua_common.cpp:742
std::size_t i
Definition: function.cpp:933
static map_location::DIRECTION s
Default AI contexts.
void from_type(lua_State *L, std::shared_ptr< T >)
Definition: lua_object.hpp:94
#define lua_tostring(L, i)
Definition: lua.h:366
LUA_API int lua_isnumber(lua_State *L, int idx)
Definition: lapi.cpp:276
LUA_API size_t lua_rawlen(lua_State *L, int idx)
Definition: lapi.cpp:392
LUA_API int lua_error(lua_State *L)
Definition: lapi.cpp:1114
void luaW_pushlocation(lua_State *L, const map_location &ml)
Converts a map location object to a Lua table pushed at the top of the stack.
Definition: lua_common.cpp:662
A variable-expanding proxy for the config class.
Definition: variable.hpp:44
A config object defines a single node in a WML file, with access to child nodes.
Definition: config.hpp:68
static map_location::DIRECTION n
LUA_API void lua_pushinteger(lua_State *L, lua_Integer n)
Definition: lapi.cpp:466
LUA_API const char * lua_pushstring(lua_State *L, const char *s)
Definition: lapi.cpp:491