The Battle for Wesnoth  1.13.4+dev
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
push_check.hpp
Go to the documentation of this file.
1 #pragma once
2 
4 
5 #include <boost/type_traits.hpp>
6 #include <boost/mpl/not.hpp>
7 #include <boost/mpl/and.hpp>
8 #include <boost/mpl/has_xxx.hpp>
9 #include "tstring.hpp"
10 #include "map/location.hpp"
11 #include "lua/lauxlib.h"
12 #include "lua/lua.h"
13 
14 #include <cassert>
15 
16 class enum_tag;
17 
18 namespace lua_check_impl
19 {
20  namespace detail
21  {
22  BOOST_MPL_HAS_XXX_TRAIT_DEF(value_type)
23  BOOST_MPL_HAS_XXX_TRAIT_DEF(iterator)
24  BOOST_MPL_HAS_XXX_TRAIT_DEF(size_type)
25  BOOST_MPL_HAS_XXX_TRAIT_DEF(reference)
26  BOOST_MPL_HAS_XXX_TRAIT_DEF(key_type)
27  BOOST_MPL_HAS_XXX_TRAIT_DEF(mapped_type)
28  BOOST_MPL_HAS_XXX_TRAIT_DEF(first_type)
29  BOOST_MPL_HAS_XXX_TRAIT_DEF(second_type)
30  }
31 
32  template <typename T, typename Enable = void>
33  struct is_container
34  : boost::mpl::bool_<
35  detail::has_value_type<T>::value &&
36  detail::has_iterator<T>::value &&
37  detail::has_size_type<T>::value &&
38  detail::has_reference<T>::value
39  >
40  {};
41 
42  template <typename T, typename Enable = void>
43  struct is_map
44  : boost::mpl::bool_<
45  detail::has_key_type<T>::value &&
46  detail::has_mapped_type<T>::value
47  >
48  {};
49 
50  template <typename T, typename Enable = void>
51  struct is_pair
52  : boost::mpl::bool_<
53  detail::has_first_type<T>::value &&
54  detail::has_second_type<T>::value
55  >
56  {};
57 
58  template <typename T>
59  struct is_container<T&>
61  {};
62 
63  template <typename T>
64  struct is_map<T&>
65  : is_map<T>
66  {};
67 
68  template<typename T>
70  {
72  };
73 
74  //std::string
75  template<typename T>
77  {
78  return luaL_checkstring(L, n);
79  }
80  template<typename T>
82  {
83  lua_pushlstring(L, val.c_str(), val.size());
84  }
85 
86  //config
87  template<typename T>
89  {
90  return luaW_checkconfig(L, n);
91  }
92  template<typename T>
94  {
95  luaW_pushconfig(L, val);
96  }
97 
98  //location
99  template<typename T>
101  {
102  return luaW_checklocation(L, n);
103  }
104  template<typename T>
106  {
107  luaW_pushlocation(L, val);
108  }
109 
110  //enums generated by MAKE_ENUM
111  template<typename T>
112  typename boost::enable_if<boost::is_base_of<enum_tag, T>, T>::type lua_check(lua_State *L, int n)
113  {
114  T val;
115  std::string str = lua_check_impl::lua_check<std::string>(L, n);
116  if(!val.parse(str))
117  {
118  luaL_argerror(L, n, ("cannot convert " + str + " to enum " + T::name()).c_str());
119  }
120  return val;
121  }
122  template<typename T>
123  typename boost::enable_if<boost::is_base_of<enum_tag, T>, void>::type lua_push(lua_State *L, T val)
124  {
125  lua_check_impl::lua_push(L, val.to_string());
126  }
127 
128  //t_string
129  template<typename T>
131  {
132  return luaW_checktstring(L, n);
133  }
134  template<typename T>
136  {
137  luaW_pushtstring(L, val);
138  }
139 
140  //bool
141  template<typename T>
143  {
144  return luaW_toboolean(L, n);
145  }
146  template<typename T>
148  {
149  lua_pushboolean(L, val);
150  }
151 
152  //double, float
153  template<typename T>
154  typename boost::enable_if<boost::is_float<T>, T>::type lua_check(lua_State *L, int n)
155  {
156  return luaL_checknumber(L, n);
157  }
158  template<typename T>
159  typename boost::enable_if<boost::is_float<T>, void>::type lua_push(lua_State *L, T val)
160  {
161  lua_pushnumber(L, val);
162  }
163 
164  //integer types
165  template<typename T>
166  typename boost::enable_if<
167  boost::mpl::and_<
168  boost::is_integral<T>,
170  >,
171  T
173  {
174  return luaL_checkinteger(L, n);
175  }
176 
177  template<typename T>
178  typename boost::enable_if<
179  boost::mpl::and_<
180  boost::is_integral<T>,
181  boost::mpl::not_<typename boost::is_same<T, bool>::type>
182  >,
183  void
185  {
186  lua_pushnumber(L, val);
187  }
188 
189  //std::pair
190  //Not sure if the not_<is_const> is required; only (maybe) if std::map matches is_container
191  template<typename T>
192  typename boost::enable_if<
193  typename boost::mpl::and_<
194  typename is_pair<T>::type,
195  typename boost::mpl::not_<typename boost::is_const<typename T::first_type> >::type
196  >::type,
197  T
198  >::type
200  {
201  T result;
202  if (lua_istable(L, n)) {
203  lua_rawgeti(L, n, 1);
204  result.first = lua_check<const typename T::first_type&>(L, -1);
205  lua_rawgeti(L, n, 2);
206  result.second = lua_check<const typename T::second_type&>(L, -1);
207  lua_pop(L, 2);
208  }
209  return result;
210  }
211  template<typename T>
212  typename boost::enable_if<
213  typename boost::mpl::and_<
214  typename is_pair<T>::type,
215  typename boost::mpl::not_<typename boost::is_const<typename T::first_type> >::type
216  >::type,
217  void
218  >::type
219  lua_push(lua_State *L, const T& val)
220  {
221  lua_newtable(L);
222  lua_push<const typename T::first_type&>(L, val.first);
223  lua_rawseti(L, -2, 1);
224  lua_push<const typename T::second_type&>(L, val.second);
225  lua_rawseti(L, -2, 2);
226  }
227 
228  //std::vector and similar but not std::string
229  template<typename T>
230  typename boost::enable_if<
231  typename boost::mpl::and_<
232  typename is_container<T>::type,
233  typename boost::mpl::not_<typename boost::is_same<T, std::string> >::type
234  >::type,
235  T
236  >::type
238  {
239  if (lua_istable(L, n))
240  {
241  T res;
242  for (int i = 1, i_end = lua_rawlen(L, n); i <= i_end; ++i)
243  {
244  lua_rawgeti(L, n, i);
246  lua_pop(L, 1);
247  }
248  return res;
249  }
250  else
251  {
252  luaL_argerror(L, n, "Table expected");
253  throw "luaL_argerror returned"; //shouldnt happen, luaL_argerror always throws.
254  }
255  }
256 
257 #if defined(__GNUC__) && !defined(__clang__)
258 #if __GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ < 8 )
259 // 'list.size()' below is unsigned for some (most but not all) list types.
260 #pragma GCC diagnostic ignored "-Wtype-limits"
261 #endif
262 #endif
263 
264  //also accepts things like std::vector<int>() | boost::adaptors::transformed(..)
265  template<typename T>
266  typename boost::enable_if<
267  typename boost::mpl::and_<
268  typename is_container<T>::type,
269  typename boost::mpl::not_<typename boost::is_same<T, std::string> >::type,
271  >::type,
272  void
273  >::type
274  lua_push(lua_State * L, const T& list )
275  {
276  // NOTE: T might be some boost::iterator_range type where size might be < 0. (unfortunately in this case size() does not return T::size_type)
277  assert(list.size() >= 0);
278  lua_createtable(L, list.size(), 0);
279  int i = 1;
280  for(typename T::const_iterator iter = list.begin(); iter != list.end(); ++iter) {
282  lua_rawseti(L, -2, i++);
283  }
284  }
285 
286 
287  //accepts std::map TODO: add a check function for that
288  template<typename T>
289  typename boost::enable_if<
290  typename is_map<T>::type,
291  void
292  >::type
293  lua_push(lua_State * L, const T& map )
294  {
295  lua_newtable(L);
296  for(const typename T::value_type& pair : map)
297  {
300  lua_settable(L, -3);
301  }
302  }
303 
304 }
305 
306 template<typename T>
308 {
309  //remove possible const& to make life easier for the impl namespace.
311 }
312 
313 template<typename T>
314 void lua_push(lua_State *L, const T& val)
315 {
317 }
LUA_API void lua_rawgeti(lua_State *L, int idx, int n)
Definition: lapi.cpp:643
LUA_API void lua_createtable(lua_State *L, int narray, int nrec)
Definition: lapi.cpp:667
LUALIB_API lua_Integer luaL_checkinteger(lua_State *L, int narg)
Definition: lauxlib.cpp:391
LUA_API void lua_pushboolean(lua_State *L, int b)
Definition: lapi.cpp:571
GLuint GLuint GLsizei GLenum type
Definition: glew.h:1221
lua_check_impl::remove_constref< T >::type lua_check(lua_State *L, int n)
Definition: push_check.hpp:307
LUA_API void lua_settable(lua_State *L, int idx)
Definition: lapi.cpp:741
boost::enable_if< typename boost::is_same< T, std::string >::type, std::string >::type lua_check(lua_State *L, int n)
Definition: push_check.hpp:76
GLuint const GLfloat * val
Definition: glew.h:2614
boost::remove_const< typename boost::remove_reference< typename boost::remove_const< T >::type >::type >::type type
Definition: push_check.hpp:71
void lua_push(lua_State *L, const T &val)
Definition: push_check.hpp:314
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
#define lua_pop(L, n)
Definition: lua.h:322
GLuint64EXT * result
Definition: glew.h:10727
bool luaW_toboolean(lua_State *L, int n)
Definition: lua_common.cpp:811
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
t_string luaW_checktstring(lua_State *L, int index)
Converts a scalar to a translatable string.
Definition: lua_common.cpp:562
LUA_API const char * lua_pushlstring(lua_State *L, const char *s, size_t len)
Definition: lapi.cpp:495
LUALIB_API lua_Number luaL_checknumber(lua_State *L, int narg)
Definition: lauxlib.cpp:377
#define lua_newtable(L)
Definition: lua.h:324
LUA_API void lua_pushnumber(lua_State *L, lua_Number n)
Definition: lapi.cpp:467
Encapsulates the map of the game.
Definition: location.hpp:38
GLuint res
Definition: glew.h:9258
config luaW_checkconfig(lua_State *L, int index)
Converts an optional table or vconfig to a config object.
Definition: lua_common.cpp:749
LUALIB_API int luaL_argerror(lua_State *L, int narg, const char *extramsg)
Definition: lauxlib.cpp:152
size_t i
Definition: function.cpp:1057
LUA_API void lua_rawseti(lua_State *L, int idx, int n)
Definition: lapi.cpp:778
boost::enable_if< typename boost::is_same< T, std::string >::type, void >::type lua_push(lua_State *L, const T &val)
Definition: push_check.hpp:81
GLuint const GLchar * name
Definition: glew.h:1782
LUA_API size_t lua_rawlen(lua_State *L, int idx)
Definition: lapi.cpp:401
GLclampd n
Definition: glew.h:5903
#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
std::string::const_iterator iterator
Definition: tokenizer.hpp:21
A config object defines a single node in a WML file, with access to child nodes.
Definition: config.hpp:83
GLsizei const GLcharARB ** string
Definition: glew.h:4503
#define luaL_checkstring(L, n)
Definition: lauxlib.h:115