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