The Battle for Wesnoth  1.17.0-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"
29 
30 #include <string>
31 #include <string_view>
32 #include <vector>
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, int nuv = 0);
45 void operator delete(void* p, lua_State *L, int nuv);
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  * Push an empty "named tuple" onto the stack.
98  * A named tuple is an array where each index can also be accessed by name.
99  * Once it's pushed, you can set the elements, eg with lua_rawseti.
100  */
101 void luaW_push_namedtuple(lua_State* L, const std::vector<std::string>& names);
102 
103 /**
104  * Converts a map location object to a Lua table pushed at the top of the stack.
105  */
106 void luaW_pushlocation(lua_State *L, const map_location& loc);
107 
108 /**
109  * Converts an optional table or pair of integers to a map location object.
110  * @param L the pointer to the lua interpreter.
111  * @param index stack position of the table or first integer.
112  * @param loc the location to write to.
113  * @return false if a map location couldn't be matched.
114  */
115 bool luaW_tolocation(lua_State *L, int index, map_location &loc);
116 
117 /**
118  * Converts an optional table or pair of integers to a map location object.
119  * @note If a pair of integers was found, the first one will be removed
120  * from the stack when the function returns.
121  */
123 
124 /**
125  * Converts a set of map locations to a Lua table pushed at the top of the stack.
126  */
127 int luaW_push_locationset(lua_State* L, const std::set<map_location>& locs);
128 
129 /**
130  * Converts a table of integer pairs to a set of map location objects.
131  */
132 std::set<map_location> luaW_check_locationset(lua_State* L, int idx);
133 
134 /**
135  * Converts a config object to a Lua table pushed at the top of the stack.
136  */
137 void luaW_pushconfig(lua_State *L, const config& cfg);
138 
139 /**
140  * Converts an optional table or vconfig to a config object.
141  * @param L the pointer to the lua interpreter.
142  * @param index stack position of the table.
143  * @param cfg the config to write the data to.
144  * @return false if some attributes had not the proper type.
145  * @note If the table has holes in the integer keys or floating-point keys,
146  * some keys will be ignored and the error will go undetected.
147  */
148 bool luaW_toconfig(lua_State *L, int index, config &cfg);
149 
150 /**
151  * Converts an optional table or vconfig to a config object.
152  */
154 
155 /**
156  * Gets an optional vconfig from either a table or a userdata.
157  * @return false in case of failure.
158  */
159 bool luaW_tovconfig(lua_State *L, int index, vconfig &vcfg);
160 
161 /**
162  * Gets an optional vconfig from either a table or a userdata.
163  * @param L the pointer to the lua interpreter.
164  * @param index the location in the current lua execution stack to look at.
165  * @param allow_missing true if missing values are allowed; the function
166  * then returns an unconstructed vconfig.
167  */
168 vconfig luaW_checkvconfig(lua_State *L, int index, bool allow_missing = false);
169 
170 /**
171  * Like the two-argument version, but if it was a vconfig, also
172  * returns a pointer to that vconfig.
173  */
174 config luaW_checkconfig(lua_State *L, int index, const vconfig*& vcfg);
175 
176 /**
177  * Pushes the value found by following the variadic names (char *), if the
178  * value is not nil.
179  * @return true if an element was pushed.
180  */
181 bool luaW_getglobal(lua_State *L, const std::vector<std::string>& path);
182 
183 /**
184  * Pushes the value found by following the variadic names (char *), if the
185  * value is not nil.
186  * @return true if an element was pushed.
187  */
188 template<typename... T>
189 bool luaW_getglobal(lua_State *L, T... path) {
190  return luaW_getglobal(L, std::vector<std::string> {path...} );
191 }
192 
193 bool luaW_toboolean(lua_State *L, int n);
194 
195 
197 
199 
200 bool luaW_tableget(lua_State *L, int index, const char* key);
201 
202 std::string_view luaW_tostring(lua_State *L, int index);
203 std::string_view luaW_tostring_or_default(lua_State *L, int index, std::string_view def = std::string_view());
204 
205 /**
206  * Displays a message in the chat window.
207  */
208 void chat_message(const std::string& caption, const std::string& msg);
209 
210 /**
211  * Calls a Lua function stored below its @a nArgs arguments at the top of the stack.
212  * @param L the pointer to the lua interpreter.
213  * @param nArgs
214  * @param nRets LUA_MULTRET for unbounded return values.
215  * @param allow_wml_error controls where any stack traces are output.
216  * @return true if the call was successful and @a nRets return values are available.
217  */
218 bool luaW_pcall(lua_State *L, int nArgs, int nRets, bool allow_wml_error = false);
219 
220 // Don't use these directly
222 int luaW_pcall_internal(lua_State *L, int nArgs, int nRets);
223 
224 int luaW_type_error(lua_State *L, int narg, const char *tname);
225 int luaW_type_error(lua_State *L, int narg, const char* kpath, const char *tname);
226 
227 #define deprecate_attrib(name, prefix, level, version, msg) deprecated_message(prefix "." name, DEP_LEVEL::level, version, msg)
228 
229 #define return_deprecated_attrib(type_macro, name, accessor, prefix, level, version, msg) \
230  type_macro(name, ( \
231  deprecate_attrib(name, prefix, level, version, msg), \
232  accessor \
233  ))
234 
235 #define return_tstring_attrib(name, accessor) \
236 do { \
237  if (strcmp(m, (name)) == 0) { \
238  luaW_pushtstring(L, (accessor)); \
239  return 1; \
240  } \
241 } while(false)
242 #define return_tstring_attrib_deprecated(name, prefix, level, version, msg, accessor) \
243  return_deprecated_attrib(return_tstring_attrib, name, accessor, prefix, level, version, msg)
244 
245 #define return_cstring_attrib(name, accessor) \
246 do { \
247  if (strcmp(m, (name)) == 0) { \
248  lua_pushstring(L, (accessor)); \
249  return 1; \
250  } \
251 } while(false)
252 #define return_cstring_attrib_deprecated(name, prefix, level, version, msg, accessor) \
253  return_deprecated_attrib(return_cstring_attrib, name, accessor, prefix, level, version, msg)
254 
255 #define return_string_attrib(name, accessor) \
256 do { \
257  if (strcmp(m, (name)) == 0) { \
258  const std::string& str = (accessor); \
259  lua_pushlstring(L, str.c_str(), str.length()); \
260  return 1; \
261  } \
262 } while(false)
263 #define return_string_attrib_deprecated(name, prefix, level, version, msg, accessor) \
264  return_deprecated_attrib(return_string_attrib, name, accessor, prefix, level, version, msg)
265 
266 #define return_int_attrib(name, accessor) \
267 do { \
268  if (strcmp(m, (name)) == 0) { \
269  lua_pushinteger(L, (accessor)); \
270  return 1; \
271  } \
272 } while(false)
273 #define return_int_attrib_deprecated(name, prefix, level, version, msg, accessor) \
274  return_deprecated_attrib(return_int_attrib, name, accessor, prefix, level, version, msg)
275 
276 #define return_float_attrib(name, accessor) \
277 do { \
278  if (strcmp(m, (name)) == 0) { \
279  lua_pushnumber(L, (accessor)); \
280  return 1; \
281  } \
282 } while(false)
283 #define return_float_attrib_deprecated(name, prefix, level, version, msg, accessor) \
284  return_deprecated_attrib(return_float_attrib, name, accessor, prefix, level, version, msg)
285 
286 #define return_bool_attrib(name, accessor) \
287 do { \
288  if (strcmp(m, (name)) == 0) { \
289  lua_pushboolean(L, (accessor)); \
290  return 1; \
291  } \
292 } while(false)
293 #define return_bool_attrib_deprecated(name, prefix, level, version, msg, accessor) \
294  return_deprecated_attrib(return_bool_attrib, name, accessor, prefix, level, version, msg)
295 
296 #define return_cfg_attrib(name, accessor) \
297 do { \
298  if (strcmp(m, (name)) == 0) { \
299  config cfg; \
300  {accessor;} \
301  luaW_pushconfig(L, cfg); \
302  return 1; \
303  } \
304 } while(false)
305 #define return_cfg_attrib_deprecated(name, prefix, level, version, msg, accessor) \
306  return_cfg_attrib(name, deprecate_attrib(name, prefix, level, version, msg); accessor)
307 
308 #define return_cfgref_attrib(name, accessor) \
309 do { \
310  if (strcmp(m, (name)) == 0) { \
311  luaW_pushconfig(L, (accessor)); \
312  return 1; \
313  } \
314 } while(false)
315 #define return_cfgref_attrib_deprecated(name, prefix, level, version, msg, accessor) \
316  return_deprecated_attrib(return_cfgref_attrib, name, accessor, prefix, level, version, msg)
317 
318 #define return_vector_string_attrib(name, accessor) \
319 do { \
320  if (strcmp(m, (name)) == 0) { \
321  const std::vector<std::string>& vector = (accessor); \
322  lua_createtable(L, vector.size(), 0); \
323  int i = 1; \
324  for (const std::string& s : vector) { \
325  lua_pushlstring(L, s.c_str(), s.length()); \
326  lua_rawseti(L, -2, i); \
327  ++i; \
328  } \
329  return 1; \
330  } \
331 } while(false)
332 #define return_vector_string_attrib_deprecated(name, prefix, level, version, msg, accessor) \
333  return_deprecated_attrib(return_vector_string_attrib, name, accessor, prefix, level, version, msg)
334 
335 #define modify_tstring_attrib(name, accessor) \
336 do { \
337  if (strcmp(m, (name)) == 0) { \
338  t_string value = luaW_checktstring(L, 3); \
339  {accessor;} \
340  return 0; \
341  } \
342 } while(false)
343 #define modify_tstring_attrib_deprecated(name, prefix, level, version, msg, accessor) \
344  modify_tstring_attrib(name, deprecate_attrib(name, prefix, level, version, msg); accessor)
345 
346 #define modify_string_attrib(name, accessor) \
347 do { \
348  if (strcmp(m, (name)) == 0) { \
349  const char *value = luaL_checkstring(L, 3); \
350  {accessor;} \
351  return 0; \
352  } \
353 } while(false)
354 #define modify_string_attrib_deprecated(name, prefix, level, version, msg, accessor) \
355  modify_string_attrib(name, deprecate_attrib(name, prefix, level, version, msg); accessor)
356 
357 #define modify_int_attrib(name, accessor) \
358 do { \
359  if (strcmp(m, (name)) == 0) { \
360  int value = static_cast<int>(luaL_checknumber(L, 3)); \
361  {accessor;} \
362  return 0; \
363  } \
364 } while(false)
365 #define modify_int_attrib_deprecated(name, prefix, level, version, msg, accessor) \
366  modify_int_attrib(name, deprecate_attrib(name, prefix, level, version, msg); accessor)
367 
368 #define modify_int_attrib_check_range(name, accessor, allowed_min, allowed_max) \
369 do { \
370  if (strcmp(m, (name)) == 0) { \
371  int value = static_cast<int>(luaL_checknumber(L, 3)); \
372  if (value < (allowed_min) || (allowed_max) < value) return luaL_argerror(L, 3, "out of bounds"); \
373  {accessor;} \
374  return 0; \
375  } \
376 } while(false)
377 #define modify_int_attrib_check_range_deprecated(name, prefix, level, version, msg, accessor, allowed_min, allowed_max) \
378  modify_int_attrib_check_range(name, deprecate_attrib(name, prefix, level, version, msg); accessor, allowed_min, allowed_max)
379 
380 #define modify_float_attrib(name, accessor) \
381 do { \
382  if (strcmp(m, (name)) == 0) { \
383  lua_Number value = luaL_checknumber(L, 3); \
384  {accessor;} \
385  return 0; \
386  } \
387 } while(false)
388 #define modify_float_attrib_deprecated(name, prefix, level, version, msg, accessor) \
389  modify_float_attrib(name, deprecate_attrib(name, prefix, level, version, msg); accessor)
390 
391 #define modify_float_attrib_check_range(name, accessor, allowed_min, allowed_max) \
392 do { \
393  if (strcmp(m, (name)) == 0) { \
394  lua_Number value = luaL_checknumber(L, 3); \
395  if (value < (allowed_min) || (allowed_max) < value) return luaL_argerror(L, 3, "out of bounds"); \
396  {accessor;} \
397  return 0; \
398  } \
399 } while(false)
400 #define modify_float_attrib_check_range_deprecated(name, prefix, level, version, msg, accessor, allowed_min, allowed_max) \
401  modify_float_attrib_check_range(name, deprecate_attrib(name, prefix, level, version, msg); accessor, allowed_min, allowed_max)
402 
403 #define modify_bool_attrib(name, accessor) \
404 do { \
405  if (strcmp(m, (name)) == 0) { \
406  bool value = luaW_toboolean(L, 3); \
407  {accessor;} \
408  return 0; \
409  } \
410 } while(false)
411 #define modify_bool_attrib_deprecated(name, prefix, level, version, msg, accessor) \
412  modify_bool_attrib(name, deprecate_attrib(name, prefix, level, version, msg); accessor)
413 
414 #define modify_cfg_attrib(name, accessor) \
415 do { \
416  if (strcmp(m, (name)) == 0) { \
417  const config& cfg = luaW_checkconfig(L, 3); \
418  {accessor;} \
419  return 0; \
420  } \
421 } while(false)
422 #define modify_cfg_attrib_deprecated(name, prefix, level, version, msg, accessor) \
423  modify_cfg_attrib(name, deprecate_attrib(name, prefix, level, version, msg); accessor)
424 
425 #define modify_vector_string_attrib(name, accessor) \
426 do { \
427  if (strcmp(m, (name)) == 0) { \
428  std::vector<std::string> value; \
429  char const* message = "table with unnamed indices holding strings expected"; \
430  if (!lua_istable(L, 3)) return luaL_argerror(L, 3, message); \
431  unsigned length = lua_rawlen(L, 3); \
432  for (unsigned i = 1; i <= length; ++i) { \
433  lua_rawgeti(L, 3, i); \
434  char const* string = lua_tostring(L, 4); \
435  if(!string) return luaL_argerror(L, 2 + i, message); \
436  value.push_back(string); \
437  lua_pop(L, 1); \
438  } \
439  {accessor;} \
440  return 0; \
441  } \
442 } while(false)
443 #define modify_vector_string_attrib_deprecated(name, prefix, level, version, msg, accessor) \
444  modify_vector_string_attrib(name, deprecate_attrib(name, prefix, level, version, msg); accessor)
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:811
config luaW_checkconfig(lua_State *L, int index)
Converts an optional table or vconfig to a config object.
Definition: lua_common.cpp:900
std::string register_tstring_metatable(lua_State *L)
Adds the tstring metatable.
Definition: lua_common.cpp:433
bool luaW_toconfig(lua_State *L, int index, config &cfg)
Converts an optional table or vconfig to a config object.
Definition: lua_common.cpp:823
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:515
bool luaW_iststring(lua_State *L, int index)
Definition: lua_common.cpp:634
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:774
int intf_textdomain(lua_State *L)
Creates an interface for gettext.
Definition: lua_common.cpp:96
bool luaW_tableget(lua_State *L, int index, const char *key)
void luaW_pushtstring(lua_State *L, const t_string &v)
Pushes a t_string on the top of the stack.
Definition: lua_common.cpp:536
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:574
bool luaW_totstring(lua_State *L, int index, t_string &str)
Converts a scalar to a translatable string.
Definition: lua_common.cpp:601
std::string register_vconfig_metatable(lua_State *L)
Adds the vconfig metatable.
Definition: lua_common.cpp:465
bool luaW_pushvariable(lua_State *L, variable_access_const &v)
Definition: lua_common.cpp:976
int luaW_pcall_internal(lua_State *L, int nArgs, int nRets)
std::string_view luaW_tostring_or_default(lua_State *L, int index, std::string_view def=std::string_view())
std::string path
Definition: game_config.cpp:38
void luaW_push_namedtuple(lua_State *L, const std::vector< std::string > &names)
Push an empty "named tuple" onto the stack.
Definition: lua_common.cpp:697
Encapsulates the map of the game.
Definition: location.hpp:37
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:952
bool luaW_toboolean(lua_State *L, int n)
Definition: lua_common.cpp:971
std::string register_gettext_metatable(lua_State *L)
Adds the gettext metatable.
Definition: lua_common.cpp:413
bool luaW_checkvariable(lua_State *L, variable_access_create &v, int n)
mock_party p
std::vector< std::string > names
Definition: build_info.cpp:65
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:714
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:944
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
std::string_view luaW_tostring(lua_State *L, int index)
void luaW_pushvconfig(lua_State *L, const vconfig &cfg)
Pushes a vconfig on the top of the stack.
Definition: lua_common.cpp:530
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:725
int luaW_type_error(lua_State *L, int narg, const char *tname)
int luaW_push_locationset(lua_State *L, const std::set< map_location > &locs)
Converts a set of map locations to a Lua table pushed at the top of the stack.
Definition: lua_common.cpp:782
void chat_message(const std::string &caption, const std::string &msg)
Displays a message in the chat window.
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:645
std::set< map_location > luaW_check_locationset(lua_State *L, int idx)
Converts a table of integer pairs to a set of map location objects.
Definition: lua_common.cpp:794
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:59
int intf_tovconfig(lua_State *L)
Creates a vconfig containing the WML table.
Definition: lua_common.cpp:403
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:626
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:569
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:917