Otclient 1.0  14/8/2020
luavaluecasts.h
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2010-2020 OTClient <https://github.com/edubart/otclient>
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining a copy
5  * of this software and associated documentation files (the "Software"), to deal
6  * in the Software without restriction, including without limitation the rights
7  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8  * copies of the Software, and to permit persons to whom the Software is
9  * furnished to do so, subject to the following conditions:
10  *
11  * The above copyright notice and this permission notice shall be included in
12  * all copies or substantial portions of the Software.
13  *
14  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20  * THE SOFTWARE.
21  */
22 
23 #ifndef LUAVALUECASTS_H
24 #define LUAVALUECASTS_H
25 
26  // this file is and must be included only from luainterface.h
27 
28 #include "declarations.h"
30 
31 template<typename T>
32 int push_internal_luavalue(T v);
33 
34 // bool
35 int push_luavalue(bool b);
36 bool luavalue_cast(int index, bool& b);
37 
38 // int
39 int push_luavalue(int i);
40 bool luavalue_cast(int index, int& i);
41 
42 // double
43 int push_luavalue(double d);
44 bool luavalue_cast(int index, double& d);
45 
46 // float
47 inline int push_luavalue(float f) { push_luavalue(static_cast<double>(f)); return 1; }
48 inline bool luavalue_cast(int index, float& f) { double d; bool r = luavalue_cast(index, d); f = d; return r; }
49 
50 // int8
51 inline int push_luavalue(int8 v) { push_luavalue(static_cast<int>(v)); return 1; }
52 inline bool luavalue_cast(int index, int8& v) { int i; bool r = luavalue_cast(index, i); v = i; return r; }
53 // uint8
54 inline int push_luavalue(uint8 v) { push_luavalue(static_cast<int>(v)); return 1; }
55 inline bool luavalue_cast(int index, uint8& v) { int i; bool r = luavalue_cast(index, i); v = i; return r; }
56 // int16
57 inline int push_luavalue(int16 v) { push_luavalue(static_cast<int>(v)); return 1; }
58 inline bool luavalue_cast(int index, int16& v) { int i; bool r = luavalue_cast(index, i); v = i; return r; }
59 // uint16
60 inline int push_luavalue(uint16 v) { push_luavalue(static_cast<int>(v)); return 1; }
61 inline bool luavalue_cast(int index, uint16& v) { int i; bool r = luavalue_cast(index, i); v = i; return r; }
62 // uint32
63 inline int push_luavalue(uint32 v) { push_luavalue(static_cast<double>(v)); return 1; }
64 inline bool luavalue_cast(int index, uint32& v) { double d; bool r = luavalue_cast(index, d); v = d; return r; }
65 // int64
66 inline int push_luavalue(int64 v) { push_luavalue(static_cast<double>(v)); return 1; }
67 inline bool luavalue_cast(int index, int64& v) { double d; bool r = luavalue_cast(index, d); v = d; return r; }
68 // uint64
69 inline int push_luavalue(uint64 v) { push_luavalue(static_cast<double>(v)); return 1; }
70 inline bool luavalue_cast(int index, uint64& v) { double d; bool r = luavalue_cast(index, d); v = d; return r; }
71 
72 // string
73 int push_luavalue(const char* cstr);
74 int push_luavalue(const std::string& str);
75 bool luavalue_cast(int index, std::string& str);
76 
77 // lua cpp function
78 int push_luavalue(const LuaCppFunction& func);
79 
80 // color
81 int push_luavalue(const Color& color);
82 bool luavalue_cast(int index, Color& color);
83 
84 // rect
85 int push_luavalue(const Rect& rect);
86 bool luavalue_cast(int index, Rect& rect);
87 
88 // point
89 int push_luavalue(const Point& point);
90 bool luavalue_cast(int index, Point& point);
91 
92 // size
93 int push_luavalue(const Size& size);
94 bool luavalue_cast(int index, Size& size);
95 
96 // otml nodes
97 int push_luavalue(const OTMLNodePtr& node);
98 bool luavalue_cast(int index, OTMLNodePtr& node);
99 
100 // enum
101 template<class T>
102 typename std::enable_if<std::is_enum<T>::value, int>::type
103 push_luavalue(T e) { return push_luavalue(static_cast<int>(e)); }
104 
105 template<class T>
106 typename std::enable_if<std::is_enum<T>::value, bool>::type
107 luavalue_cast(int index, T& myenum);
108 
109 // LuaObject pointers
110 template<class T>
111 typename std::enable_if<std::is_base_of<LuaObject, typename T::element_type>::value, int>::type
112 push_luavalue(const T& obj);
113 
114 bool luavalue_cast(int index, LuaObjectPtr& obj);
115 
116 template<class T>
117 typename std::enable_if<std::is_base_of<LuaObject, T>::value, bool>::type
119 
120 // std::function
121 template<typename Ret, typename... Args>
122 int push_luavalue(const std::function<Ret(Args...)>& func);
123 
124 template<typename... Args>
125 bool luavalue_cast(int index, std::function<void(Args...)>& func);
126 
127 template<typename Ret, typename... Args>
128 typename std::enable_if<!std::is_void<Ret>::value, bool>::type
129 luavalue_cast(int index, std::function<Ret(Args...)>& func);
130 
131 // list
132 template<typename T>
133 int push_luavalue(const std::list<T>& list);
134 
135 template<typename T>
136 bool luavalue_cast(int index, std::list<T>& list);
137 
138 // vector
139 template<typename T>
140 int push_luavalue(const std::vector<T>& vec);
141 
142 template<typename T>
143 bool luavalue_cast(int index, std::vector<T>& vec);
144 
145 // deque
146 template<class T>
147 int push_luavalue(const std::deque<T>& vec);
148 
149 template<typename T>
150 bool luavalue_cast(int index, std::deque<T>& vec);
151 
152 // map
153 template<class K, class V>
154 int push_luavalue(const std::map<K, V>& map);
155 
156 template<class K, class V>
157 bool luavalue_cast(int index, std::map<K, V>& map);
158 
159 // tuple
160 template<typename... Args>
161 int push_luavalue(const std::tuple<Args...>& tuple);
162 
163 template<typename... Args>
164 int push_internal_luavalue(const std::tuple<Args...>& tuple);
165 
166 // start definitions
167 
168 #include "luaexception.h"
169 #include "luainterface.h"
170 #include "luaobject.h"
171 
172 template<typename T>
174  return push_luavalue(v);
175 }
176 
177 template<class T>
178 typename std::enable_if<std::is_enum<T>::value, bool>::type
179 luavalue_cast(int index, T& myenum) {
180  int i;
181  if (luavalue_cast(index, i)) {
182  myenum = static_cast<T>(i);
183  return true;
184  }
185  return false;
186 }
187 
188 template<class T>
189 typename std::enable_if<std::is_base_of<LuaObject, typename T::element_type>::value, int>::type
190 push_luavalue(const T& obj) {
191  if (obj)
192  g_lua.pushObject(obj);
193  else
194  g_lua.pushNil();
195  return 1;
196 }
197 
198 template<class T>
199 typename std::enable_if<std::is_base_of<LuaObject, T>::value, bool>::type
201  LuaObjectPtr obj;
202  if (!luavalue_cast(index, obj))
203  return false;
204  if (obj)
205  ptr = obj->dynamic_self_cast<T>();
206  else
207  ptr = nullptr;
208  return true;
209 }
210 
211 template<typename Ret, typename... Args>
212 int push_luavalue(const std::function<Ret(Args...)>& func) {
213  if (func) {
216  }
217  else
218  g_lua.pushNil();
219  return 1;
220 }
221 
222 template<typename... Args>
223 bool luavalue_cast(int index, std::function<void(Args...)>& func) {
224  if (g_lua.isFunction(index)) {
225  g_lua.pushValue(index);
226  // weak references are used here, this means that the script must hold another reference
227  // to this function, otherwise it will expire
228  int funcWeakRef = g_lua.weakRef();
229  func = [=](Args... args) {
230  // note that we must catch exceptions, because this lambda can be called from anywhere
231  // and most of them won't catch exceptions (e.g. dispatcher)
232  g_lua.getWeakRef(funcWeakRef);
233  try {
234  if (g_lua.isFunction()) {
235  int numArgs = g_lua.polymorphicPush(args...);
236  int rets = g_lua.safeCall(numArgs);
237  g_lua.pop(rets);
238  }
239  else {
240  throw LuaException("attempt to call an expired lua function from C++,"
241  "did you forget to hold a reference for that function?", 0);
242  }
243  }
244  catch (LuaException& e) {
245  g_logger.error(stdext::format("lua function callback failed: %s", e.what()));
246  }
247  };
248  return true;
249  }
250  else if (g_lua.isNil(index)) {
251  func = std::function<void(Args...)>();
252  return true;
253  }
254  return false;
255 }
256 
257 template<typename Ret, typename... Args>
258 typename std::enable_if<!std::is_void<Ret>::value, bool>::type
259 luavalue_cast(int index, std::function<Ret(Args...)>& func) {
260  if (g_lua.isFunction(index)) {
261  g_lua.pushValue(index);
262  // weak references are used here, this means that the script must hold another reference
263  // to this function, otherwise it will expire
264  int funcWeakRef = g_lua.weakRef();
265  func = [=](Args... args) -> Ret {
266  // note that we must catch exceptions, because this lambda can be called from anywhere
267  // and most of them won't catch exceptions (e.g. dispatcher)
268  try {
269  g_lua.getWeakRef(funcWeakRef);
270  if (g_lua.isFunction()) {
271  int numArgs = g_lua.polymorphicPush(args...);
272  if (g_lua.safeCall(numArgs) != 1)
273  throw LuaException("a function from lua didn't retrieve the expected number of results", 0);
274  return g_lua.polymorphicPop<Ret>();
275  }
276  else {
277  throw LuaException("attempt to call an expired lua function from C++,"
278  "did you forget to hold a reference for that function?", 0);
279  }
280  }
281  catch (LuaException& e) {
282  g_logger.error(stdext::format("lua function callback failed: %s", e.what()));
283  }
284  return Ret();
285  };
286  return true;
287  }
288  else if (g_lua.isNil(index)) {
289  func = std::function<Ret(Args...)>();
290  return true;
291  }
292  return false;
293 }
294 
295 template<typename T>
296 int push_luavalue(const std::list<T>& list) {
297  g_lua.createTable(list.size(), 0);
298  int i = 1;
299  for (const T& v : list) {
301  g_lua.rawSeti(i);
302  i++;
303  }
304  return 1;
305 }
306 
307 template<typename T>
308 bool luavalue_cast(int index, std::list<T>& list)
309 {
310  if (g_lua.isTable(index)) {
311  g_lua.pushNil();
312  while (g_lua.next(index < 0 ? index - 1 : index)) {
313  T value;
314  if (luavalue_cast(-1, value))
315  list.push_back(value);
316  g_lua.pop();
317  }
318  return true;
319  }
320  return false;
321 }
322 
323 template<typename T>
324 int push_luavalue(const std::vector<T>& vec) {
325  g_lua.createTable(vec.size(), 0);
326  int i = 1;
327  for (const T& v : vec) {
329  g_lua.rawSeti(i);
330  i++;
331  }
332  return 1;
333 }
334 
335 template<typename T>
336 bool luavalue_cast(int index, std::vector<T>& vec)
337 {
338  if (g_lua.isTable(index)) {
339  g_lua.pushNil();
340  while (g_lua.next(index < 0 ? index - 1 : index)) {
341  T value;
342  if (luavalue_cast(-1, value))
343  vec.push_back(value);
344  g_lua.pop();
345  }
346  return true;
347  }
348  return false;
349 }
350 
351 template<typename T>
352 int push_luavalue(const std::deque<T>& vec) {
353  g_lua.createTable(vec.size(), 0);
354  int i = 1;
355  for (const T& v : vec) {
357  g_lua.rawSeti(i);
358  i++;
359  }
360  return 1;
361 }
362 
363 template<typename T>
364 bool luavalue_cast(int index, std::deque<T>& vec)
365 {
366  if (g_lua.isTable(index)) {
367  g_lua.pushNil();
368  while (g_lua.next(index < 0 ? index - 1 : index)) {
369  T value;
370  if (luavalue_cast(-1, value))
371  vec.push_back(value);
372  g_lua.pop();
373  }
374  return true;
375  }
376  return false;
377 }
378 
379 template<class K, class V>
380 int push_luavalue(const std::map<K, V>& map)
381 {
382  g_lua.newTable();
383  for (auto& it : map) {
384  push_internal_luavalue(it.first);
385  push_internal_luavalue(it.second);
386  g_lua.rawSet();
387  }
388  return 1;
389 }
390 
391 template<class K, class V>
392 bool luavalue_cast(int index, std::map<K, V>& map)
393 {
394  if (g_lua.isTable(index)) {
395  g_lua.pushNil();
396  while (g_lua.next(index < 0 ? index - 1 : index)) {
397  K key;
398  V value;
399  if (luavalue_cast(-1, value) && luavalue_cast(-2, key))
400  map[key] = value;
401  g_lua.pop();
402  }
403  return true;
404  }
405  return false;
406 }
407 
408 
409 template<int N>
411  template<typename Tuple>
412  static void call(const Tuple& tuple) {
413  push_internal_luavalue(std::get<N - 1>(tuple));
414  g_lua.rawSeti(N);
416  }
417 };
418 
419 template<>
421  template<typename Tuple>
422  static void call(const Tuple& /*tuple*/) { }
423 };
424 
425 template<typename... Args>
426 int push_internal_luavalue(const std::tuple<Args...>& tuple) {
427  g_lua.newTable();
428  push_tuple_internal_luavalue<sizeof...(Args)>::call(tuple);
429  return 1;
430 }
431 
432 template<int N>
434  template<typename Tuple>
435  static void call(const Tuple& tuple) {
436  push_internal_luavalue(std::get<std::tuple_size<Tuple>::value - N>(tuple));
438  }
439 };
440 
441 template<>
443  template<typename Tuple>
444  static void call(const Tuple& /*tuple*/) { }
445 };
446 
447 template<typename... Args>
448 int push_luavalue(const std::tuple<Args...>& tuple) {
449  push_tuple_luavalue<sizeof...(Args)>::call(tuple);
450  return sizeof...(Args);
451 }
452 
453 #endif
LuaInterface::rawSeti
void rawSeti(int n, int index=-2)
Definition: luainterface.cpp:995
push_luavalue
int push_luavalue(const Outfit &outfit)
Definition: luavaluecasts.cpp:26
LuaCppFunction
std::function< int(LuaInterface *)> LuaCppFunction
Definition: declarations.h:31
Color
Definition: color.h:32
luaexception.h
push_tuple_internal_luavalue< 0 >::call
static void call(const Tuple &)
Definition: luavaluecasts.h:422
TRect
Definition: rect.h:37
uint32
uint32_t uint32
Definition: types.h:35
luainterface.h
Logger::error
void error(const std::string &what)
Definition: logger.h:54
declarations.h
LuaInterface::isFunction
bool isFunction(int index=-1)
Definition: luainterface.cpp:1197
int64
int64_t int64
Definition: types.h:38
stdext::format
std::string format()
Definition: format.h:84
luaobject.h
LuaException
Definition: luaexception.h:28
int8
int8_t int8
Definition: types.h:41
uint16
uint16_t uint16
Definition: types.h:36
LuaInterface::polymorphicPush
int polymorphicPush(const T &v, const Args &... args)
Pushes any type onto the stack.
Definition: luainterface.h:358
LuaInterface::createTable
void createTable(int narr, int nrec)
Definition: luainterface.cpp:1006
declarations.h
LuaInterface::weakRef
int weakRef()
Definition: luainterface.cpp:779
LuaInterface::isNil
bool isNil(int index=-1)
Definition: luainterface.cpp:1167
g_logger
Logger g_logger
Definition: logger.cpp:35
g_lua
LuaInterface g_lua
Definition: luainterface.cpp:31
LuaInterface::polymorphicPop
T polymorphicPop()
Same as castValue but also pops.
Definition: luainterface.h:339
push_tuple_luavalue< 0 >::call
static void call(const Tuple &)
Definition: luavaluecasts.h:444
LuaInterface::pushObject
void pushObject(const LuaObjectPtr &obj)
Definition: luainterface.cpp:1126
luavalue_cast
bool luavalue_cast(int index, Outfit &outfit)
Definition: luavaluecasts.cpp:52
LuaInterface::pushValue
void pushValue(int index=-1)
Definition: luainterface.cpp:1160
uint64
uint64_t uint64
Definition: types.h:34
LuaInterface::pushCppFunction
void pushCppFunction(const LuaCppFunction &func)
Definition: luainterface.cpp:1144
push_tuple_internal_luavalue::call
static void call(const Tuple &tuple)
Definition: luavaluecasts.h:412
LuaInterface::isTable
bool isTable(int index=-1)
Definition: luainterface.cpp:1191
push_tuple_luavalue::call
static void call(const Tuple &tuple)
Definition: luavaluecasts.h:435
push_tuple_luavalue
Definition: luavaluecasts.h:433
LuaInterface::pop
void pop(int n=1)
Definition: luainterface.cpp:1016
luabinder::bind_fun
LuaCppFunction bind_fun(const std::function< int(LuaInterface *)> &f)
Bind a customized function.
Definition: luabinder.h:110
stdext::shared_object_ptr< OTMLNode >
LuaInterface::getWeakRef
void getWeakRef(int weakRef)
Definition: luainterface.cpp:866
LuaException::what
virtual const char * what() const
Definition: luaexception.h:36
TPoint< int >
push_tuple_internal_luavalue
Definition: luavaluecasts.h:410
int16
int16_t int16
Definition: types.h:40
LuaInterface::pushNil
void pushNil()
Definition: luainterface.cpp:1077
TSize
Definition: point.h:31
push_internal_luavalue
int push_internal_luavalue(T v)
Definition: luavaluecasts.h:173
LuaInterface::rawSet
void rawSet(int index=-3)
Definition: luainterface.cpp:989
uint8
uint8_t uint8
Definition: types.h:37
LuaInterface::next
bool next(int index=-2)
Definition: luainterface.cpp:846
LuaInterface::safeCall
int safeCall(int numArgs=0, int numRets=-1)
Calls a function The function and arguments must be on top of the stack in order, results are pushed ...
Definition: luainterface.cpp:439
LuaInterface::newTable
void newTable()
Definition: luainterface.cpp:1001