The Battle for Wesnoth  1.13.4+dev
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
lua_common.cpp
Go to the documentation of this file.
1 /*
2  Copyright (C) 2014 - 2016 by Chris Beck <[email protected]>
3  Part of the Battle for Wesnoth Project http://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  * Contains code common to the application and game lua kernels which
18  * cannot or should not go into the lua kernel base files.
19  *
20  * Currently contains implementation functions related to vconfig and
21  * gettext, also some macros to assist in writing C lua callbacks.
22  */
23 
24 #include "scripting/lua_common.hpp"
25 
26 #include "global.hpp"
27 
28 #include "config.hpp"
29 #include "scripting/lua_api.hpp"
30 #include "scripting/lua_types.hpp" // for gettextKey, tstringKey, etc
31 #include "tstring.hpp" // for t_string
32 #include "variable.hpp" // for vconfig
33 #include "log.hpp"
34 #include "gettext.hpp"
35 
36 #include <cstring>
37 #include <iterator> // for distance, advance
38 #include <new> // for operator new
39 #include <string> // for string, basic_string
40 
41 #include "lua/lauxlib.h"
42 #include "lua/lua.h"
43 
44 static const char * gettextKey = "gettext";
45 static const char * vconfigKey = "vconfig";
46 static const char * vconfigpairsKey = "vconfig pairs";
47 static const char * vconfigipairsKey = "vconfig ipairs";
48 const char * tstringKey = "translatable string";
49 
50 static lg::log_domain log_scripting_lua("scripting/lua");
51 #define LOG_LUA LOG_STREAM(info, log_scripting_lua)
52 #define WRN_LUA LOG_STREAM(warn, log_scripting_lua)
53 #define ERR_LUA LOG_STREAM(err, log_scripting_lua)
54 
55 namespace lua_common {
56 
57 /**
58  * Creates a t_string object (__call metamethod).
59  * - Arg 1: userdata containing the domain.
60  * - Arg 2: string to translate.
61  * - Ret 1: string containing the translatable string.
62  */
63 static int impl_gettext(lua_State *L)
64 {
65  char const *m = luaL_checkstring(L, 2);
66  char const *d = static_cast<char *>(lua_touserdata(L, 1));
67  // Hidden metamethod, so d has to be a string. Use it to create a t_string.
68  luaW_pushtstring(L, t_string(m, d));
69  return 1;
70 }
71 
72 /**
73  * Creates an interface for gettext
74  * - Arg 1: string containing the domain.
75  * - Ret 1: a full userdata with __call pointing to lua_gettext.
76  */
78 {
79  size_t l;
80  char const *m = luaL_checklstring(L, 1, &l);
81 
82  void *p = lua_newuserdata(L, l + 1);
83  memcpy(p, m, l + 1);
84 
86  return 1;
87 }
88 
89 /**
90  * Converts a Lua value at position @a src and appends it to @a dst.
91  * @note This function is private to lua_tstring_concat. It expects two things.
92  * First, the t_string metatable is at the top of the stack on entry. (It
93  * is still there on exit.) Second, the caller hasn't any valuable object
94  * with dynamic lifetime, since they would be leaked on error.
95  */
97 {
98  switch (lua_type(L, src)) {
99  case LUA_TNUMBER:
100  case LUA_TSTRING:
101  dst += lua_tostring(L, src);
102  return;
103  case LUA_TUSERDATA:
104  // Compare its metatable with t_string's metatable.
105  if (t_string * src_ptr = static_cast<t_string *> (luaL_testudata(L, src, tstringKey))) {
106  dst += *src_ptr;
107  return;
108  }
109  //intentional fall-through
110  default:
111  luaL_typerror(L, src, "string");
112  }
113 }
114 
115 /**
116  * Appends a scalar to a t_string object (__concat metamethod).
117  */
119 {
120  // Create a new t_string.
121  t_string *t = new(lua_newuserdata(L, sizeof(t_string))) t_string;
123 
124  // Append both arguments to t.
125  tstring_concat_aux(L, *t, 1);
126  tstring_concat_aux(L, *t, 2);
127 
128  return 1;
129 }
130 
131 /**
132  * Destroys a t_string object before it is collected (__gc metamethod).
133  */
135 {
136  t_string *t = static_cast<t_string *>(lua_touserdata(L, 1));
137  t->t_string::~t_string();
138  return 0;
139 }
140 
142 {
143  t_string *t1 = static_cast<t_string *>(lua_touserdata(L, 1));
144  t_string *t2 = static_cast<t_string *>(lua_touserdata(L, 2));
145  lua_pushboolean(L, translation::compare(t1->get(), t2->get()) < 0);
146  return 1;
147 }
148 
150 {
151  t_string *t1 = static_cast<t_string *>(lua_touserdata(L, 1));
152  t_string *t2 = static_cast<t_string *>(lua_touserdata(L, 2));
153  lua_pushboolean(L, translation::compare(t1->get(), t2->get()) < 1);
154  return 1;
155 }
156 
158 {
159  t_string *t1 = static_cast<t_string *>(lua_touserdata(L, 1));
160  t_string *t2 = static_cast<t_string *>(lua_touserdata(L, 2));
161  lua_pushboolean(L, translation::compare(t1->get(), t2->get()) == 0);
162  return 1;
163 }
164 
165 /**
166  * Converts a t_string object to a string (__tostring metamethod);
167  * that is, performs a translation.
168  */
170 {
171  t_string *t = static_cast<t_string *>(lua_touserdata(L, 1));
172  lua_pushstring(L, t->c_str());
173  return 1;
174 }
175 
176 /**
177  * Gets the parsed field of a vconfig object (_index metamethod).
178  * Special fields __literal, __shallow_literal, __parsed, and
179  * __shallow_parsed, return Lua tables.
180  */
182 {
183  vconfig *v = static_cast<vconfig *>(lua_touserdata(L, 1));
184 
185  if (lua_isnumber(L, 2))
186  {
188  unsigned len = std::distance(i, v->ordered_end());
189  unsigned pos = lua_tointeger(L, 2) - 1;
190  if (pos >= len) return 0;
191  std::advance(i, pos);
192 
193  lua_createtable(L, 2, 0);
194  lua_pushstring(L, i.get_key().c_str());
195  lua_rawseti(L, -2, 1);
197  lua_rawseti(L, -2, 2);
198  return 1;
199  }
200 
201  char const *m = luaL_checkstring(L, 2);
202  if (strcmp(m, "__literal") == 0) {
203  luaW_pushconfig(L, v->get_config());
204  return 1;
205  }
206  if (strcmp(m, "__parsed") == 0) {
208  return 1;
209  }
210 
211  bool shallow_literal = strcmp(m, "__shallow_literal") == 0;
212  if (shallow_literal || strcmp(m, "__shallow_parsed") == 0)
213  {
214  lua_newtable(L);
215  for (const config::attribute &a : v->get_config().attribute_range()) {
216  if (shallow_literal)
217  luaW_pushscalar(L, a.second);
218  else
219  luaW_pushscalar(L, v->expand(a.first));
220  lua_setfield(L, -2, a.first.c_str());
221  }
223  i_end = v->ordered_end();
224  if (shallow_literal) {
225  i.disable_insertion();
226  i_end.disable_insertion();
227  }
228  for (int j = 1; i != i_end; ++i, ++j)
229  {
230  lua_createtable(L, 2, 0);
231  lua_pushstring(L, i.get_key().c_str());
232  lua_rawseti(L, -2, 1);
233  luaW_pushvconfig(L, i.get_child());
234  lua_rawseti(L, -2, 2);
235  lua_rawseti(L, -2, j);
236  }
237  return 1;
238  }
239 
240  if (v->null() || !v->has_attribute(m)) return 0;
241  luaW_pushscalar(L, (*v)[m]);
242  return 1;
243 }
244 
245 /**
246  * Returns the number of a child of a vconfig object.
247  */
249 {
250  vconfig *v = static_cast<vconfig *>(lua_touserdata(L, 1));
251  lua_pushinteger(L, v->null() ? 0 :
252  std::distance(v->ordered_begin(), v->ordered_end()));
253  return 1;
254 }
255 
256 /**
257  * Destroys a vconfig object before it is collected (__gc metamethod).
258  */
260 {
261  vconfig *v = static_cast<vconfig *>(lua_touserdata(L, 1));
262  v->~vconfig();
263  return 0;
264 }
265 
266 /**
267  * Iterate through the attributes of a vconfig
268  */
270 {
271  vconfig vcfg = luaW_checkvconfig(L, 1);
274  if (range.first == range.second) {
275  return 0;
276  }
277  config::attribute value = *range.first++;
278  lua_pushlstring(L, value.first.c_str(), value.first.length());
279  luaW_pushscalar(L, vcfg[value.first]);
280  return 2;
281 }
282 
283 /**
284  * Destroy a vconfig pairs iterator
285  */
287 {
288  typedef config::const_attr_itors const_attr_itors;
289  void* p = lua_touserdata(L, 1);
290  const_attr_itors* cai = static_cast<const_attr_itors*>(p);
291  cai->~const_attr_itors();
292  return 0;
293 }
294 
295 /**
296  * Construct an iterator to iterate through the attributes of a vconfig
297  */
299 {
300  static const size_t sz = sizeof(config::const_attr_itors);
301  vconfig vcfg = luaW_checkvconfig(L, 1);
304  lua_setmetatable(L, -2);
306  lua_pushvalue(L, 1);
307  return 2;
308 }
309 
310 typedef std::pair<vconfig::all_children_iterator, vconfig::all_children_iterator> vconfig_child_range;
311 
312 /**
313  * Iterate through the subtags of a vconfig
314  */
316 {
317  luaW_checkvconfig(L, 1);
318  int i = luaL_checkinteger(L, 2);
320  vconfig_child_range& range = *static_cast<vconfig_child_range*>(p);
321  if (range.first == range.second) {
322  return 0;
323  }
324  std::pair<std::string, vconfig> value = *range.first++;
325  lua_pushinteger(L, i + 1);
326  lua_createtable(L, 2, 0);
327  lua_pushlstring(L, value.first.c_str(), value.first.length());
328  lua_rawseti(L, -2, 1);
329  luaW_pushvconfig(L, value.second);
330  lua_rawseti(L, -2, 2);
331  return 2;
332 }
333 
334 /**
335  * Destroy a vconfig ipairs iterator
336  */
338 {
339  void* p = lua_touserdata(L, 1);
340  vconfig_child_range* vcr = static_cast<vconfig_child_range*>(p);
341  vcr->~vconfig_child_range();
342  return 0;
343 }
344 
345 /**
346  * Construct an iterator to iterate through the subtags of a vconfig
347  */
349 {
350  static const size_t sz = sizeof(vconfig_child_range);
351  vconfig cfg = luaW_checkvconfig(L, 1);
354  lua_setmetatable(L, -2);
356  lua_pushvalue(L, 1);
357  lua_pushinteger(L, 0);
358  return 3;
359 }
360 
361 /**
362  * Creates a vconfig containing the WML table.
363  * - Arg 1: WML table.
364  * - Ret 1: vconfig userdata.
365  */
367 {
368  vconfig vcfg = luaW_checkvconfig(L, 1);
369  luaW_pushvconfig(L, vcfg);
370  return 1;
371 }
372 
373 /**
374  * Adds the gettext metatable
375  */
377 {
379 
380  static luaL_Reg const callbacks[] = {
381  { "__call", &impl_gettext},
382  { nullptr, nullptr }
383  };
384  luaL_setfuncs(L, callbacks, 0);
385 
386  lua_pushstring(L, "message domain");
387  lua_setfield(L, -2, "__metatable");
388 
389  return "Adding gettext metatable...\n";
390 }
391 
392 /**
393  * Adds the tstring metatable
394  */
396 {
398 
399  static luaL_Reg const callbacks[] = {
400  { "__concat", &impl_tstring_concat},
401  { "__gc", &impl_tstring_collect},
402  { "__tostring", &impl_tstring_tostring},
403  { "__lt", &impl_tstring_lt},
404  { "__le", &impl_tstring_le},
405  { "__eq", &impl_tstring_eq},
406  { nullptr, nullptr }
407  };
408  luaL_setfuncs(L, callbacks, 0);
409 
410  lua_pushstring(L, "translatable string");
411  lua_setfield(L, -2, "__metatable");
412 
413  return "Adding tstring metatable...\n";
414 }
415 
416 /**
417  * Adds the vconfig metatable
418  */
420 {
422 
423  static luaL_Reg const callbacks[] = {
424  { "__gc", &impl_vconfig_collect},
425  { "__index", &impl_vconfig_get},
426  { "__len", &impl_vconfig_size},
427  { "__pairs", &impl_vconfig_pairs},
428  { "__ipairs", &impl_vconfig_ipairs},
429  { nullptr, nullptr }
430  };
431  luaL_setfuncs(L, callbacks, 0);
432 
433  lua_pushstring(L, "wml object");
434  lua_setfield(L, -2, "__metatable");
435 
436  // Metatables for the iterator userdata
437 
438  // I don't bother setting __metatable because this
439  // userdata is only ever stored in the iterator's
440  // upvalues, so it's never visible to the user.
442  lua_pushstring(L, "__gc");
444  lua_rawset(L, -3);
445 
447  lua_pushstring(L, "__gc");
449  lua_rawset(L, -3);
450 
451  return "Adding vconfig metatable...\n";
452 }
453 
454 } // end namespace lua_common
455 
456 void luaW_pushvconfig(lua_State *L, vconfig const &cfg)
457 {
458  new(lua_newuserdata(L, sizeof(vconfig))) vconfig(cfg);
460 }
461 
463 {
464  new(lua_newuserdata(L, sizeof(t_string))) t_string(v);
466 }
467 
468 
469 namespace {
470  struct luaW_pushscalar_visitor : boost::static_visitor<>
471  {
472  lua_State *L;
473  luaW_pushscalar_visitor(lua_State *l): L(l) {}
474 
475  void operator()(boost::blank const &) const
476  { lua_pushnil(L); }
477  void operator()(bool b) const
478  { lua_pushboolean(L, b); }
479  void operator()(int i) const
480  { lua_pushinteger(L, i); }
481  void operator()(unsigned long long ull) const
482  { lua_pushnumber(L, ull); }
483  void operator()(double d) const
484  { lua_pushnumber(L, d); }
485  void operator()(std::string const &s) const
486  { lua_pushstring(L, s.c_str()); }
487  void operator()(t_string const &s) const
488  { luaW_pushtstring(L, s); }
489  };
490 }//unnamed namespace for luaW_pushscalar_visitor
491 
493 {
494  v.apply_visitor(luaW_pushscalar_visitor(L));
495 }
496 
498 {
499  switch (lua_type(L, index)) {
500  case LUA_TBOOLEAN:
501  v = luaW_toboolean(L, -1);
502  break;
503  case LUA_TNUMBER:
504  v = lua_tonumber(L, -1);
505  break;
506  case LUA_TSTRING:
507  v = lua_tostring(L, -1);
508  break;
509  case LUA_TUSERDATA:
510  {
511  if (t_string * tptr = static_cast<t_string *>(luaL_testudata(L, -1, tstringKey))) {
512  v = *tptr;
513  break;
514  } else {
515  return false;
516  }
517  }
518  default:
519  return false;
520  }
521  return true;
522 }
523 
525  , int index
526  , luatypekey key)
527 {
528  if (!lua_getmetatable(L, index))
529  return false;
530  lua_pushlightuserdata(L, key);
532  bool ok = lua_rawequal(L, -1, -2) == 1;
533  lua_pop(L, 2);
534  return ok;
535 }
536 
538 {
539  switch (lua_type(L, index)) {
540  case LUA_TBOOLEAN:
541  str = lua_toboolean(L, index) ? "yes" : "no";
542  break;
543  case LUA_TNUMBER:
544  case LUA_TSTRING:
545  str = lua_tostring(L, index);
546  break;
547  case LUA_TUSERDATA:
548  {
549  if (t_string * tstr = static_cast<t_string *> (luaL_testudata(L, index, tstringKey))) {
550  str = *tstr;
551  break;
552  } else {
553  return false;
554  }
555  }
556  default:
557  return false;
558  }
559  return true;
560 }
561 
563 {
565  if (!luaW_totstring(L, index, result))
566  luaL_typerror(L, index, "translatable string");
567  return result;
568 }
569 
570 void luaW_filltable(lua_State *L, config const &cfg)
571 {
572  if (!lua_checkstack(L, LUA_MINSTACK))
573  return;
574 
575  int k = 1;
576  for (const config::any_child &ch : cfg.all_children_range())
577  {
578  lua_createtable(L, 2, 0);
579  lua_pushstring(L, ch.key.c_str());
580  lua_rawseti(L, -2, 1);
581  lua_newtable(L);
582  luaW_filltable(L, ch.cfg);
583  lua_rawseti(L, -2, 2);
584  lua_rawseti(L, -2, k++);
585  }
586  for (const config::attribute &attr : cfg.attribute_range())
587  {
588  luaW_pushscalar(L, attr.second);
589  lua_setfield(L, -2, attr.first.c_str());
590  }
591 }
592 
594 {
595  lua_createtable(L, 2, 0);
596 
597  lua_pushinteger(L, 1);
598  lua_pushinteger(L, ml.x + 1);
599  lua_rawset(L, -3);
600 
601  lua_pushinteger(L, 2);
602  lua_pushinteger(L, ml.y + 1);
603  lua_rawset(L, -3);
604 }
605 
607  if (!lua_checkstack(L, LUA_MINSTACK)) {
608  return false;
609  }
610  if (lua_isnoneornil(L, index)) {
611  // Need this special check because luaW_tovconfig returns true in this case
612  return false;
613  }
614 
616 
617  index = lua_absindex(L, index);
618 
619  if (lua_istable(L, index) || luaW_tounit(L, index) || luaW_tovconfig(L, index, dummy_vcfg)) {
621  int x_was_num = 0, y_was_num = 0;
622  lua_getfield(L, index, "x");
623  result.x = lua_tonumberx(L, -1, &x_was_num) - 1;
624  lua_getfield(L, index, "y");
625  result.y = lua_tonumberx(L, -1, &y_was_num) - 1;
626  lua_pop(L, 2);
627  if (!x_was_num || !y_was_num) {
628  // If we get here and it was userdata, checking numeric indices won't help
629  // (It won't help if it was a config either, but there's no easy way to check that.)
630  if (lua_isuserdata(L, index)) {
631  return false;
632  }
633  lua_rawgeti(L, index, 1);
634  result.x = lua_tonumberx(L, -1, &x_was_num) - 1;
635  lua_rawgeti(L, index, 2);
636  result.y = lua_tonumberx(L, -1, &y_was_num) - 1;
637  lua_pop(L, 2);
638  }
639  if (x_was_num && y_was_num) {
640  loc = result;
641  return true;
642  }
643  } else if (lua_isnumber(L, index) && lua_isnumber(L, index + 1)) {
644  // If it's a number, then we consume two elements on the stack
645  // Since we have no way of notifying the caller that we have
646  // done this, we remove the first number from the stack.
647  loc.x = lua_tonumber(L, index) - 1;
648  lua_remove(L, index);
649  loc.y = lua_tonumber(L, index) - 1;
650  return true;
651  }
652  return false;
653 }
654 
656 {
658  if (!luaW_tolocation(L, index, result))
659  luaL_typerror(L, index, "location");
660  return result;
661 }
662 
663 void luaW_pushconfig(lua_State *L, config const &cfg)
664 {
665  lua_newtable(L);
666  luaW_filltable(L, cfg);
667 }
668 
669 
670 
671 
672 #define return_misformed() \
673  do { lua_settop(L, initial_top); return false; } while (0)
674 
675 bool luaW_toconfig(lua_State *L, int index, config &cfg)
676 {
677  if (!lua_checkstack(L, LUA_MINSTACK))
678  return false;
679 
680  // Get the absolute index of the table.
681  index = lua_absindex(L, index);
682  int initial_top = lua_gettop(L);
683 
684  switch (lua_type(L, index))
685  {
686  case LUA_TTABLE:
687  break;
688  case LUA_TUSERDATA:
689  {
690  if (vconfig * ptr = static_cast<vconfig *> (luaL_testudata(L, index, vconfigKey))) {
691  cfg = ptr->get_parsed_config();
692  return true;
693  } else {
694  return false;
695  }
696  }
697  case LUA_TNONE:
698  case LUA_TNIL:
699  return true;
700  default:
701  return false;
702  }
703 
704  // First convert the children (integer indices).
705  for (int i = 1, i_end = lua_rawlen(L, index); i <= i_end; ++i)
706  {
707  lua_rawgeti(L, index, i);
708  if (!lua_istable(L, -1)) return_misformed();
709  lua_rawgeti(L, -1, 1);
710  char const *m = lua_tostring(L, -1);
711  if (!m) return_misformed();
712  lua_rawgeti(L, -2, 2);
713  if (!luaW_toconfig(L, -1, cfg.add_child(m)))
715  lua_pop(L, 3);
716  }
717 
718  // Then convert the attributes (string indices).
719  for (lua_pushnil(L); lua_next(L, index); lua_pop(L, 1))
720  {
721  if (lua_isnumber(L, -2)) continue;
722  if (!lua_isstring(L, -2)) return_misformed();
723  config::attribute_value &v = cfg[lua_tostring(L, -2)];
724  if (lua_istable(L, -1)) {
725  int subindex = lua_absindex(L, -1);
726  std::ostringstream str;
727  for (int i = 1, i_end = lua_rawlen(L, subindex); i <= i_end; ++i, lua_pop(L, 1)) {
728  lua_rawgeti(L, -1, i);
730  if (!luaW_toscalar(L, -1, item)) return_misformed();
731  if (i > 1) str << ',';
732  str << item;
733  }
734  // If there are any string keys, it's misformed
735  for (lua_pushnil(L); lua_next(L, subindex); lua_pop(L, 1)) {
736  if (!lua_isnumber(L, -2)) return_misformed();
737  }
738  v = str.str();
739  } else if (!luaW_toscalar(L, -1, v)) return_misformed();
740  }
741 
742  lua_settop(L, initial_top);
743  return true;
744 }
745 
746 #undef return_misformed
747 
748 
750 {
751  config result;
752  if (!luaW_toconfig(L, index, result))
753  luaL_typerror(L, index, "WML table");
754  return result;
755 }
756 
757 bool luaW_tovconfig(lua_State *L, int index, vconfig &vcfg)
758 {
759  switch (lua_type(L, index))
760  {
761  case LUA_TTABLE:
762  {
763  config cfg;
764  bool ok = luaW_toconfig(L, index, cfg);
765  if (!ok) return false;
766  vcfg = vconfig(cfg, true);
767  break;
768  }
769  case LUA_TUSERDATA:
770  if (vconfig * ptr = static_cast<vconfig *> (luaL_testudata(L, index, vconfigKey))) {
771  vcfg = *ptr;
772  } else {
773  return false;
774  }
775  case LUA_TNONE:
776  case LUA_TNIL:
777  break;
778  default:
779  return false;
780  }
781  return true;
782 }
783 
784 vconfig luaW_checkvconfig(lua_State *L, int index, bool allow_missing)
785 {
787  if (!luaW_tovconfig(L, index, result) || (!allow_missing && result.null()))
788  luaL_typerror(L, index, "WML table");
789  return result;
790 }
791 
792 bool luaW_getglobal(lua_State *L, const std::vector<std::string>& path)
793 {
795  for (const std::string& s : path)
796  {
797  if (!lua_istable(L, -1)) goto discard;
798  lua_pushlstring(L, s.c_str(), s.size());
799  lua_rawget(L, -2);
800  lua_remove(L, -2);
801  }
802 
803  if (lua_isnil(L, -1)) {
804  discard:
805  lua_pop(L, 1);
806  return false;
807  }
808  return true;
809 }
810 
812 {
813  return lua_toboolean(L,n) != 0;
814 }
815 
817 {
818  try
819  {
820  if(v.exists_as_attribute())
821  {
822  luaW_pushscalar(L, v.as_scalar());
823  return true;
824  }
825  else if(v.exists_as_container())
826  {
827  lua_newtable(L);
828  if (luaW_toboolean(L, 2))
830  return true;
831  }
832  else
833  {
834  lua_pushnil(L);
835  return true;
836  }
837  }
838  catch (const invalid_variablename_exception&)
839  {
840  WRN_LUA << v.get_error_message();
841  return false;
842  }
843 }
844 
846 {
847  int variabletype = lua_type(L, n);
848  try
849  {
850  switch (variabletype) {
851  case LUA_TBOOLEAN:
852  v.as_scalar() = luaW_toboolean(L, n);
853  return true;
854  case LUA_TNUMBER:
855  v.as_scalar() = lua_tonumber(L, n);
856  return true;
857  case LUA_TSTRING:
858  v.as_scalar() = lua_tostring(L, n);
859  return true;
860  case LUA_TUSERDATA:
861  if (t_string * t_str = static_cast<t_string*> (luaL_testudata(L, n, tstringKey))) {
862  v.as_scalar() = *t_str;
863  return true;
864  }
865  goto default_explicit;
866  case LUA_TTABLE:
867  {
868  config &cfg = v.as_container();
869  cfg.clear();
870  if (luaW_toconfig(L, n, cfg)) {
871  return true;
872  }
873  // no break
874  }
875  default:
876  default_explicit:
877  return luaL_typerror(L, n, "WML table or scalar") != 0;
878 
879  }
880  }
881  catch (const invalid_variablename_exception&)
882  {
883  WRN_LUA << v.get_error_message() << " when attempting to write a '" << lua_typename(L, variabletype) << "'\n";
884  return false;
885  }
886 }
#define WRN_LUA
Definition: lua_common.cpp:52
bool luaW_checkvariable(lua_State *L, variable_access_create &v, int n)
Definition: lua_common.cpp:845
LUA_API void lua_rawgeti(lua_State *L, int idx, int n)
Definition: lapi.cpp:643
static int impl_vconfig_collect(lua_State *L)
Destroys a vconfig object before it is collected (__gc metamethod).
Definition: lua_common.cpp:259
void luaW_pushvconfig(lua_State *L, vconfig const &cfg)
Pushes a vconfig on the top of the stack.
Definition: lua_common.cpp:456
static const char * vconfigKey
Definition: lua_common.cpp:45
#define lua_isnoneornil(L, n)
Definition: lua.h:337
LUA_API void lua_pushlightuserdata(lua_State *L, void *p)
Definition: lapi.cpp:579
LUALIB_API void * luaL_checkudata(lua_State *L, int ud, const char *tname)
Definition: lauxlib.cpp:307
variable_info_detail::maybe_const< vit, config::attribute_value >::type & as_scalar() const
might throw invalid_variablename_exception NOTE: If vit == vit_const, then the lifime of the returned...
LUA_API void lua_createtable(lua_State *L, int narray, int nrec)
Definition: lapi.cpp:667
#define lua_pushcfunction(L, f)
Definition: lua.h:328
void luaW_pushscalar(lua_State *L, config::attribute_value const &v)
Converts an attribute value into a Lua object pushed at the top of the stack.
Definition: lua_common.cpp:492
std::string str() const
Definition: config.cpp:353
LUA_API void lua_getfield(lua_State *L, int idx, const char *k)
Definition: lapi.cpp:622
std::string register_tstring_metatable(lua_State *L)
Adds the tstring metatable.
Definition: lua_common.cpp:395
static lg::log_domain log_scripting_lua("scripting/lua")
LUALIB_API lua_Integer luaL_checkinteger(lua_State *L, int narg)
Definition: lauxlib.cpp:391
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:757
LUA_API void lua_settop(lua_State *L, int idx)
Definition: lapi.cpp:159
std::pair< const_attribute_iterator, const_attribute_iterator > const_attr_itors
Definition: config.hpp:418
LUA_API int lua_type(lua_State *L, int idx)
Definition: lapi.cpp:243
#define LUA_TUSERDATA
Definition: lua.h:84
bool exists_as_container() const
might throw invalid_variablename_exception
GLenum GLint * range
Definition: glew.h:3025
int pos
Definition: formula.cpp:800
LUA_API void lua_pushboolean(lua_State *L, int b)
Definition: lapi.cpp:571
vconfig get_child() const
Definition: variable.cpp:374
config get_parsed_config() const
Definition: variable.cpp:131
static int impl_gettext(lua_State *L)
Creates a t_string object (__call metamethod).
Definition: lua_common.cpp:63
int compare(const std::string &s1, const std::string &s2)
all_children_iterator ordered_end() const
Definition: variable.cpp:403
Extends variable_info with methods that can only be applied if vit != vit_const.
static int impl_vconfig_get(lua_State *L)
Gets the parsed field of a vconfig object (_index metamethod).
Definition: lua_common.cpp:181
LUA_API int lua_gettop(lua_State *L)
Definition: lapi.cpp:154
bool luaW_pushvariable(lua_State *L, variable_access_const &v)
Definition: lua_common.cpp:816
attribute_map::value_type attribute
Definition: config.hpp:393
int intf_textdomain(lua_State *L)
Creates an interface for gettext.
Definition: lua_common.cpp:77
#define lua_tointeger(L, i)
Definition: lua.h:319
~vconfig()
Default destructor, but defined here for possibly faster compiles (templates sometimes can be rough o...
Definition: variable.cpp:93
static int impl_vconfig_ipairs(lua_State *L)
Construct an iterator to iterate through the subtags of a vconfig.
Definition: lua_common.cpp:348
#define lua_tonumber(L, i)
Definition: lua.h:318
V::result_type apply_visitor(const V &visitor) const
Applies a visitor to the underlying variant.
Definition: config.hpp:377
GLenum src
Definition: glew.h:2392
void clear()
Definition: config.cpp:1055
LUA_API int lua_isuserdata(lua_State *L, int idx)
Definition: lapi.cpp:274
LUA_API void lua_pushcclosure(lua_State *L, lua_CFunction fn, int n)
Definition: lapi.cpp:549
#define d
LUALIB_API void luaL_setmetatable(lua_State *L, const char *tname)
Definition: lauxlib.cpp:286
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:655
GLdouble GLdouble t
Definition: glew.h:1366
Definitions for the interface to Wesnoth Markup Language (WML).
LUA_API int lua_absindex(lua_State *L, int idx)
Definition: lapi.cpp:147
LUA_API void * lua_newuserdata(lua_State *L, size_t size)
Definition: lapi.cpp:1169
Variant for storing WML attributes.
Definition: config.hpp:223
#define lua_pop(L, n)
Definition: lua.h:322
unit * luaW_tounit(lua_State *L, int index, bool only_on_map)
Converts a Lua value to a unit pointer.
Definition: lua_api.cpp:183
GLdouble l
Definition: glew.h:6966
#define return_misformed()
Definition: lua_common.cpp:672
GLdouble GLdouble GLdouble b
Definition: glew.h:6966
#define lua_upvalueindex(i)
Definition: lua.h:40
#define LUA_TSTRING
Definition: lua.h:81
GLsizei const char ** path
Definition: glew.h:4654
std::string register_vconfig_metatable(lua_State *L)
Adds the vconfig metatable.
Definition: lua_common.cpp:419
bool null() const
Definition: variable.hpp:66
GLuint64EXT * result
Definition: glew.h:10727
#define LUA_TNONE
Definition: lua.h:75
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:792
LUA_API int lua_isstring(lua_State *L, int idx)
Definition: lapi.cpp:268
bool luaW_toboolean(lua_State *L, int n)
Definition: lua_common.cpp:811
LUA_API int lua_rawequal(lua_State *L, int index1, int index2)
Definition: lapi.cpp:280
static int impl_tstring_concat(lua_State *L)
Appends a scalar to a t_string object (__concat metamethod).
Definition: lua_common.cpp:118
#define LUA_TNIL
Definition: lua.h:77
static const char * gettextKey
Definition: lua_common.cpp:44
LUA_API int lua_toboolean(lua_State *L, int idx)
Definition: lapi.cpp:377
const GLdouble * v
Definition: glew.h:1359
GLsizei const GLfloat * value
Definition: glew.h:1817
all_children_itors all_children_range() const
In-order iteration over all children.
Definition: config.cpp:1127
GLenum GLenum dst
Definition: glew.h:2392
void luaW_pushtstring(lua_State *L, t_string const &v)
Pushes a t_string on the top of the stack.
Definition: lua_common.cpp:462
GLenum GLsizei len
Definition: glew.h:5662
t_string luaW_checktstring(lua_State *L, int index)
Converts a scalar to a translatable string.
Definition: lua_common.cpp:562
#define lua_pushglobaltable(L)
Definition: lua.h:342
GLboolean GLboolean GLboolean GLboolean a
Definition: glew.h:7319
LUA_API const char * lua_pushlstring(lua_State *L, const char *s, size_t len)
Definition: lapi.cpp:495
#define LUA_TNUMBER
Definition: lua.h:80
config & add_child(const std::string &key)
Definition: config.cpp:743
LUA_API int lua_getmetatable(lua_State *L, int objindex)
Definition: lapi.cpp:680
LUA_API int lua_setmetatable(lua_State *L, int objindex)
Definition: lapi.cpp:806
const t_string_base & get() const
Definition: tstring.hpp:179
LUA_API void lua_remove(lua_State *L, int idx)
Definition: lapi.cpp:176
const char * c_str() const
Definition: tstring.hpp:171
LUALIB_API void * luaL_testudata(lua_State *L, int ud, const char *tname)
Definition: lauxlib.cpp:292
GLfloat GLfloat p
Definition: glew.h:12766
static const char * vconfigpairsKey
Definition: lua_common.cpp:46
LUA_API lua_Number lua_tonumberx(lua_State *L, int idx, int *isnum)
Definition: lapi.cpp:329
#define lua_newtable(L)
Definition: lua.h:324
static int impl_vconfig_pairs_collect(lua_State *L)
Destroy a vconfig pairs iterator.
Definition: lua_common.cpp:286
static int impl_tstring_tostring(lua_State *L)
Converts a t_string object to a string (__tostring metamethod); that is, performs a translation...
Definition: lua_common.cpp:169
LUA_API void lua_pushnil(lua_State *L)
Definition: lapi.cpp:459
LUA_API void lua_pushnumber(lua_State *L, lua_Number n)
Definition: lapi.cpp:467
LUALIB_API const char * luaL_checklstring(lua_State *L, int narg, size_t *len)
Definition: lauxlib.cpp:359
static int impl_vconfig_pairs(lua_State *L)
Construct an iterator to iterate through the attributes of a vconfig.
Definition: lua_common.cpp:298
Encapsulates the map of the game.
Definition: location.hpp:38
bool luaW_toconfig(lua_State *L, int index, config &cfg)
Converts an optional table or vconfig to a config object.
Definition: lua_common.cpp:675
bool luaW_totstring(lua_State *L, int index, t_string &str)
Converts a scalar to a translatable string.
Definition: lua_common.cpp:537
static int impl_vconfig_size(lua_State *L)
Returns the number of a child of a vconfig object.
Definition: lua_common.cpp:248
LUALIB_API int luaL_newmetatable(lua_State *L, const char *tname)
Definition: lauxlib.cpp:274
LUA_API void * lua_touserdata(lua_State *L, int idx)
Definition: lapi.cpp:421
bool luaW_hasmetatable(lua_State *L, int index, luatypekey key)
Returns true if the metatable of the object is the one found in the registry.
Definition: lua_common.cpp:524
#define lua_isnil(L, n)
Definition: lua.h:333
variable_info_detail::maybe_const< vit, config >::type & as_container() const
might throw invalid_variablename_exception
static int impl_tstring_eq(lua_State *L)
Definition: lua_common.cpp:157
static int impl_tstring_lt(lua_State *L)
Definition: lua_common.cpp:141
LUA_API void lua_rawset(lua_State *L, int idx)
Definition: lapi.cpp:764
std::string register_gettext_metatable(lua_State *L)
Adds the gettext metatable.
Definition: lua_common.cpp:376
config::attribute_value expand(const std::string &) const
Definition: variable.cpp:303
config luaW_checkconfig(lua_State *L, int index)
Converts an optional table or vconfig to a config object.
Definition: lua_common.cpp:749
static int impl_tstring_le(lua_State *L)
Definition: lua_common.cpp:149
const config & get_config() const
Definition: variable.hpp:68
const_attr_itors attribute_range() const
Definition: config.cpp:984
GLuint index
Definition: glew.h:1782
static int impl_vconfig_ipairs_collect(lua_State *L)
Destroy a vconfig ipairs iterator.
Definition: lua_common.cpp:337
Information on a WML variable.
size_t i
Definition: function.cpp:1057
#define lua_tostring(L, i)
Definition: lua.h:345
LUA_API void lua_rawseti(lua_State *L, int idx, int n)
Definition: lapi.cpp:778
void luaW_filltable(lua_State *L, config const &cfg)
Converts a config object to a Lua table.
Definition: lua_common.cpp:570
#define LUA_MINSTACK
Definition: lua.h:92
LUA_API void lua_pushvalue(lua_State *L, int idx)
Definition: lapi.cpp:229
LUA_API int lua_isnumber(lua_State *L, int idx)
Definition: lapi.cpp:261
static vconfig unconstructed_vconfig()
This is just a wrapper for the default constructor; it exists for historical reasons and to make it c...
Definition: variable.cpp:108
std::pair< vconfig::all_children_iterator, vconfig::all_children_iterator > vconfig_child_range
Definition: lua_common.cpp:310
LUA_API size_t lua_rawlen(lua_State *L, int idx)
Definition: lapi.cpp:401
void * luatypekey
Definition: lua_types.hpp:18
#define LUA_REGISTRYINDEX
Definition: lua.h:39
GLclampd n
Definition: glew.h:5903
const GLdouble * m
Definition: glew.h:6968
static int impl_vconfig_ipairs_iter(lua_State *L)
Iterate through the subtags of a vconfig.
Definition: lua_common.cpp:315
#define lua_istable(L, n)
Definition: lua.h:331
void luaW_pushconfig(lua_State *L, config const &cfg)
Converts a config object to a Lua table pushed at the top of the stack.
Definition: lua_common.cpp:663
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:593
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:497
A variable-expanding proxy for the config class.
Definition: variable.hpp:36
Standard logging facilities (interface).
std::string get_error_message() const
LUA_API int lua_checkstack(lua_State *L, int size)
Definition: lapi.cpp:86
vconfig luaW_checkvconfig(lua_State *L, int index, bool allow_missing)
Gets an optional vconfig from either a table or a userdata.
Definition: lua_common.cpp:784
LUALIB_API void luaL_setfuncs(lua_State *L, const luaL_Reg *l, int nup)
Definition: lauxlib.cpp:850
bool exists_as_attribute() const
might throw invalid_variablename_exception
A config object defines a single node in a WML file, with access to child nodes.
Definition: config.hpp:83
static int impl_tstring_collect(lua_State *L)
Destroys a t_string object before it is collected (__gc metamethod).
Definition: lua_common.cpp:134
static void tstring_concat_aux(lua_State *L, t_string &dst, int src)
Converts a Lua value at position src and appends it to dst.
Definition: lua_common.cpp:96
int intf_tovconfig(lua_State *L)
Creates a vconfig containing the WML table.
Definition: lua_common.cpp:366
GLdouble s
Definition: glew.h:1358
#define LUA_TTABLE
Definition: lua.h:82
LUA_API void lua_pushinteger(lua_State *L, lua_Integer n)
Definition: lapi.cpp:477
static int impl_vconfig_pairs_iter(lua_State *L)
Iterate through the attributes of a vconfig.
Definition: lua_common.cpp:269
LUALIB_API int luaL_typerror(lua_State *L, int narg, const char *tname)
Definition: lauxlib.cpp:176
LUA_API void lua_rawget(lua_State *L, int idx)
Definition: lapi.cpp:633
GLsizei const GLcharARB ** string
Definition: glew.h:4503
std::string get_key() const
Definition: variable.cpp:365
bool has_attribute(const std::string &key) const
< Synonym for operator[]
Definition: variable.hpp:92
all_children_iterator ordered_begin() const
In-order iteration over all children.
Definition: variable.cpp:398
LUA_API const char * lua_pushstring(lua_State *L, const char *s)
Definition: lapi.cpp:507
LUA_API void lua_setfield(lua_State *L, int idx, const char *k)
Definition: lapi.cpp:752
const char * tstringKey
Definition: lua_common.cpp:48
#define LUA_TBOOLEAN
Definition: lua.h:78
LUA_API int lua_next(lua_State *L, int idx)
Definition: lapi.cpp:1108
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:606
LUA_API const char * lua_typename(lua_State *L, int t)
Definition: lapi.cpp:249
static const char * vconfigipairsKey
Definition: lua_common.cpp:47
#define luaL_checkstring(L, n)
Definition: lauxlib.h:115