The Battle for Wesnoth  1.15.2+dev
lua_common.hpp
Go to the documentation of this file.
1 /*
2  Copyright (C) 2014 - 2018 by Chris Beck <render787@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  * Common callbacks and functions to manipulate config, vconfig, tstring
17  * in lua, and macros to get them from the stack.
18  */
19 
20 #pragma once
21 
22 struct lua_State;
23 class t_string;
24 class vconfig;
25 
26 #include "config.hpp"
27 #include "variable_info.hpp"
28 #include "map/location.hpp"
30 
31 #include <vector>
32 #include <string>
33 
34 namespace lua_common {
35  int intf_textdomain(lua_State *L);
36  int intf_tovconfig(lua_State* L);
37 
38  std::string register_gettext_metatable(lua_State *L);
39  std::string register_tstring_metatable(lua_State *L);
40  std::string register_vconfig_metatable(lua_State *L);
41 
42 }
43 
44 void* operator new(std::size_t sz, lua_State *L);
45 void operator delete(void* p, lua_State *L);
46 
47 /**
48  * Like luaL_getmetafield, but returns false if key is an empty string
49  * or begins with two underscores.
50  */
51 bool luaW_getmetafield(lua_State *L, int idx, const char* key);
52 
53 /**
54  * Pushes a vconfig on the top of the stack.
55  */
56 void luaW_pushvconfig(lua_State *L, const vconfig& cfg);
57 
58 /**
59  * Pushes a t_string on the top of the stack.
60  */
61 void luaW_pushtstring(lua_State *L, const t_string& v);
62 
63 /**
64  * Converts an attribute value into a Lua object pushed at the top of the stack.
65  */
67 
68 /**
69  * Converts the value at the top of the stack to an attribute value
70  */
72 
73 /**
74  * Converts a scalar to a translatable string.
75  */
76 bool luaW_totstring(lua_State *L, int index, t_string &str);
77 
78 /**
79  * Converts a scalar to a translatable string.
80  */
82 
83 /*
84  * Test if a scalar is either a plain or translatable string.
85  * Also returns true if it's a number since that's convertible to string.
86  */
87 bool luaW_iststring(lua_State* L, int index);
88 
89 /**
90  * Converts a config object to a Lua table.
91  * The destination table should be at the top of the stack on entry. It is
92  * still at the top on exit.
93  */
94 void luaW_filltable(lua_State *L, const config& cfg);
95 
96 /**
97  * Converts a map location object to a Lua table pushed at the top of the stack.
98  */
99 void luaW_pushlocation(lua_State *L, const map_location& loc);
100 
101 /**
102  * Converts an optional table or pair of integers to a map location object.
103  * @param index stack position of the table or first integer.
104  * @return false if a map location couldn't be matched.
105  */
106 bool luaW_tolocation(lua_State *L, int index, map_location &loc);
107 
108 /**
109  * Converts an optional table or pair of integers to a map location object.
110  * @note If a pair of integers was found, the first one will be removed
111  * from the stack when the function returns.
112  */
114 
115 /**
116  * Converts a config object to a Lua table pushed at the top of the stack.
117  */
118 void luaW_pushconfig(lua_State *L, const config& cfg);
119 
120 /**
121  * Converts an optional table or vconfig to a config object.
122  * @param index stack position of the table.
123  * @return false if some attributes had not the proper type.
124  * @note If the table has holes in the integer keys or floating-point keys,
125  * some keys will be ignored and the error will go undetected.
126  */
127 bool luaW_toconfig(lua_State *L, int index, config &cfg);
128 
129 /**
130  * Converts an optional table or vconfig to a config object.
131  */
133 
134 /**
135  * Gets an optional vconfig from either a table or a userdata.
136  * @return false in case of failure.
137  */
138 bool luaW_tovconfig(lua_State *L, int index, vconfig &vcfg);
139 
140 /**
141  * Gets an optional vconfig from either a table or a userdata.
142  * @param allow_missing true if missing values are allowed; the function
143  * then returns an unconstructed vconfig.
144  */
145 vconfig luaW_checkvconfig(lua_State *L, int index, bool allow_missing = false);
146 
147 /**
148  * Like the two-argument version, but if it was a vconfig, also
149  * returns a pointer to that vconfig.
150  */
151 config luaW_checkconfig(lua_State *L, int index, const vconfig*& vcfg);
152 
153 /**
154  * Pushes the value found by following the variadic names (char *), if the
155  * value is not nil.
156  * @return true if an element was pushed.
157  */
158 bool luaW_getglobal(lua_State *L, const std::vector<std::string>& path);
159 
160 /**
161  * Pushes the value found by following the variadic names (char *), if the
162  * value is not nil.
163  * @return true if an element was pushed.
164  */
165 template<typename... T>
166 bool luaW_getglobal(lua_State *L, T... path) {
167  return luaW_getglobal(L, std::vector<std::string> {path...} );
168 }
169 
170 bool luaW_toboolean(lua_State *L, int n);
171 
172 
174 
176 
177 bool luaW_tableget(lua_State *L, int index, const char* key);
178 
181 
182 /**
183  * Displays a message in the chat window.
184  */
185 void chat_message(const std::string& caption, const std::string& msg);
186 
187 /**
188  * Calls a Lua function stored below its @a nArgs arguments at the top of the stack.
189  * @param nRets LUA_MULTRET for unbounded return values.
190  * @return true if the call was successful and @a nRets return values are available.
191  */
192 bool luaW_pcall(lua_State *L, int nArgs, int nRets, bool allow_wml_error = false);
193 
194 // Don't use these directly
196 int luaW_pcall_internal(lua_State *L, int nArgs, int nRets);
197 
198 int luaW_type_error(lua_State *L, int narg, const char *tname);
199 int luaW_type_error(lua_State *L, int narg, const char* kpath, const char *tname);
200 
201 #define return_tstring_attrib(name, accessor) \
202 do { \
203  if (strcmp(m, (name)) == 0) { \
204  luaW_pushtstring(L, (accessor)); \
205  return 1; \
206  } \
207 } while(false)
208 
209 #define return_cstring_attrib(name, accessor) \
210 do { \
211  if (strcmp(m, (name)) == 0) { \
212  lua_pushstring(L, (accessor)); \
213  return 1; \
214  } \
215 } while(false)
216 
217 #define return_string_attrib(name, accessor) \
218 do { \
219  if (strcmp(m, (name)) == 0) { \
220  const std::string& str = (accessor); \
221  lua_pushlstring(L, str.c_str(), str.length()); \
222  return 1; \
223  } \
224 } while(false)
225 
226 #define return_int_attrib(name, accessor) \
227 do { \
228  if (strcmp(m, (name)) == 0) { \
229  lua_pushinteger(L, (accessor)); \
230  return 1; \
231  } \
232 } while(false)
233 
234 #define return_float_attrib(name, accessor) \
235 do { \
236  if (strcmp(m, (name)) == 0) { \
237  lua_pushnumber(L, (accessor)); \
238  return 1; \
239  } \
240 } while(false)
241 
242 #define return_bool_attrib(name, accessor) \
243 do { \
244  if (strcmp(m, (name)) == 0) { \
245  lua_pushboolean(L, (accessor)); \
246  return 1; \
247  } \
248 } while(false)
249 
250 #define return_cfg_attrib(name, accessor) \
251 do { \
252  if (strcmp(m, (name)) == 0) { \
253  config cfg; \
254  {accessor;} \
255  luaW_pushconfig(L, cfg); \
256  return 1; \
257  } \
258 } while(false)
259 
260 #define return_cfgref_attrib(name, accessor) \
261 do { \
262  if (strcmp(m, (name)) == 0) { \
263  luaW_pushconfig(L, (accessor)); \
264  return 1; \
265  } \
266 } while(false)
267 
268 #define return_vector_string_attrib(name, accessor) \
269 do { \
270  if (strcmp(m, (name)) == 0) { \
271  const std::vector<std::string>& vector = (accessor); \
272  lua_createtable(L, vector.size(), 0); \
273  int i = 1; \
274  for (const std::string& s : vector) { \
275  lua_pushlstring(L, s.c_str(), s.length()); \
276  lua_rawseti(L, -2, i); \
277  ++i; \
278  } \
279  return 1; \
280  } \
281 } while(false)
282 
283 #define modify_tstring_attrib(name, accessor) \
284 do { \
285  if (strcmp(m, (name)) == 0) { \
286  t_string value = luaW_checktstring(L, 3); \
287  {accessor;} \
288  return 0; \
289  } \
290 } while(false)
291 
292 #define modify_string_attrib(name, accessor) \
293 do { \
294  if (strcmp(m, (name)) == 0) { \
295  const char *value = luaL_checkstring(L, 3); \
296  {accessor;} \
297  return 0; \
298  } \
299 } while(false)
300 
301 #define modify_int_attrib(name, accessor) \
302 do { \
303  if (strcmp(m, (name)) == 0) { \
304  int value = static_cast<int>(luaL_checknumber(L, 3)); \
305  {accessor;} \
306  return 0; \
307  } \
308 } while(false)
309 
310 #define modify_int_attrib_check_range(name, accessor, allowed_min, allowed_max) \
311 do { \
312  if (strcmp(m, (name)) == 0) { \
313  int value = static_cast<int>(luaL_checknumber(L, 3)); \
314  if (value < (allowed_min) || (allowed_max) < value) return luaL_argerror(L, 3, "out of bounds"); \
315  {accessor;} \
316  return 0; \
317  } \
318 } while(false)
319 
320 #define modify_float_attrib(name, accessor) \
321 do { \
322  if (strcmp(m, (name)) == 0) { \
323  lua_Number value = luaL_checknumber(L, 3); \
324  {accessor;} \
325  return 0; \
326  } \
327 } while(false)
328 
329 #define modify_float_attrib_check_range(name, accessor, allowed_min, allowed_max) \
330 do { \
331  if (strcmp(m, (name)) == 0) { \
332  lua_Number value = luaL_checknumber(L, 3); \
333  if (value < (allowed_min) || (allowed_max) < value) return luaL_argerror(L, 3, "out of bounds"); \
334  {accessor;} \
335  return 0; \
336  } \
337 } while(false)
338 
339 #define modify_bool_attrib(name, accessor) \
340 do { \
341  if (strcmp(m, (name)) == 0) { \
342  bool value = luaW_toboolean(L, 3); \
343  {accessor;} \
344  return 0; \
345  } \
346 } while(false)
347 
348 #define modify_cfg_attrib(name, accessor) \
349 do { \
350  if (strcmp(m, (name)) == 0) { \
351  const config& cfg = luaW_checkconfig(L, 3); \
352  {accessor;} \
353  return 0; \
354  } \
355 } while(false)
356 
357 #define modify_vector_string_attrib(name, accessor) \
358 do { \
359  if (strcmp(m, (name)) == 0) { \
360  std::vector<std::string> value; \
361  char const* message = "table with unnamed indices holding strings expected"; \
362  if (!lua_istable(L, 3)) return luaL_argerror(L, 3, message); \
363  unsigned length = lua_rawlen(L, 3); \
364  for (unsigned i = 1; i <= length; ++i) { \
365  lua_rawgeti(L, 3, i); \
366  char const* string = lua_tostring(L, 4); \
367  if(!string) return luaL_argerror(L, 2 + i, message); \
368  value.push_back(string); \
369  lua_pop(L, 1); \
370  } \
371  {accessor;} \
372  return 0; \
373  } \
374 } while(false)
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:728
config luaW_checkconfig(lua_State *L, int index)
Converts an optional table or vconfig to a config object.
Definition: lua_common.cpp:817
std::string register_tstring_metatable(lua_State *L)
Adds the tstring metatable.
Definition: lua_common.cpp:430
bool luaW_toconfig(lua_State *L, int index, config &cfg)
Converts an optional table or vconfig to a config object.
Definition: lua_common.cpp:740
Variant for storing WML attributes.
bool luaW_getmetafield(lua_State *L, int idx, const char *key)
Like luaL_getmetafield, but returns false if key is an empty string or begins with two underscores...
Definition: lua_common.cpp:510
bool luaW_iststring(lua_State *L, int index)
Definition: lua_common.cpp:626
bool luaW_pcall(lua_State *L, int nArgs, int nRets, bool allow_wml_error=false)
Calls a Lua function stored below its nArgs arguments at the top of the stack.
map_location luaW_checklocation(lua_State *L, int index)
Converts an optional table or pair of integers to a map location object.
Definition: lua_common.cpp:720
int intf_textdomain(lua_State *L)
Creates an interface for gettext.
Definition: lua_common.cpp:93
bool luaW_tableget(lua_State *L, int index, const char *key)
Definition: lua_common.cpp:964
void luaW_pushtstring(lua_State *L, const t_string &v)
Pushes a t_string on the top of the stack.
Definition: lua_common.cpp:531
void push_error_handler(lua_State *L)
static void msg(const char *act, debug_info &i, const char *to="", const char *result="")
Definition: debugger.cpp:109
Additional functionality for a non-const variable_info.
Definitions for the interface to Wesnoth Markup Language (WML).
bool luaW_toscalar(lua_State *L, int index, config::attribute_value &v)
Converts the value at the top of the stack to an attribute value.
Definition: lua_common.cpp:566
bool luaW_totstring(lua_State *L, int index, t_string &str)
Converts a scalar to a translatable string.
Definition: lua_common.cpp:593
std::string register_vconfig_metatable(lua_State *L)
Adds the vconfig metatable.
Definition: lua_common.cpp:460
bool luaW_pushvariable(lua_State *L, variable_access_const &v)
Definition: lua_common.cpp:893
int luaW_pcall_internal(lua_State *L, int nArgs, int nRets)
std::string path
Definition: game_config.cpp:39
utils::string_view luaW_tostring_or_default(lua_State *L, int index, utils::string_view def=utils::string_view())
Definition: lua_common.cpp:986
utils::string_view luaW_tostring(lua_State *L, int index)
Definition: lua_common.cpp:976
Encapsulates the map of the game.
Definition: location.hpp:42
bool luaW_getglobal(lua_State *L, const std::vector< std::string > &path)
Pushes the value found by following the variadic names (char *), if the value is not nil...
Definition: lua_common.cpp:869
bool luaW_toboolean(lua_State *L, int n)
Definition: lua_common.cpp:888
std::string register_gettext_metatable(lua_State *L)
Adds the gettext metatable.
Definition: lua_common.cpp:410
bool luaW_checkvariable(lua_State *L, variable_access_create &v, int n)
Definition: lua_common.cpp:921
mock_party p
void luaW_pushlocation(lua_State *L, const map_location &loc)
Converts a map location object to a Lua table pushed at the top of the stack.
Definition: lua_common.cpp:660
vconfig luaW_checkvconfig(lua_State *L, int index, bool allow_missing=false)
Gets an optional vconfig from either a table or a userdata.
Definition: lua_common.cpp:861
std::size_t index(const std::string &str, const std::size_t index)
Codepoint index corresponding to the nth character in a UTF-8 string.
Definition: unicode.cpp:71
void luaW_pushvconfig(lua_State *L, const vconfig &cfg)
Pushes a vconfig on the top of the stack.
Definition: lua_common.cpp:525
bool luaW_tolocation(lua_State *L, int index, map_location &loc)
Converts an optional table or pair of integers to a map location object.
Definition: lua_common.cpp:671
int luaW_type_error(lua_State *L, int narg, const char *tname)
void chat_message(const std::string &caption, const std::string &msg)
Displays a message in the chat window.
Definition: lua_common.cpp:996
Information on a WML variable.
void luaW_filltable(lua_State *L, const config &cfg)
Converts a config object to a Lua table.
Definition: lua_common.cpp:637
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
int intf_tovconfig(lua_State *L)
Creates a vconfig containing the WML table.
Definition: lua_common.cpp:400
static map_location::DIRECTION n
t_string luaW_checktstring(lua_State *L, int index)
Converts a scalar to a translatable string.
Definition: lua_common.cpp:618
void luaW_pushscalar(lua_State *L, const config::attribute_value &v)
Converts an attribute value into a Lua object pushed at the top of the stack.
Definition: lua_common.cpp:561
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:834