Otclient  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((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((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((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((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((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((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((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((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((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 = (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  } else
217  g_lua.pushNil();
218  return 1;
219 }
220 
221 template<typename... Args>
222 bool luavalue_cast(int index, std::function<void(Args...)>& func) {
223  if(g_lua.isFunction(index)) {
224  g_lua.pushValue(index);
225  // weak references are used here, this means that the script must hold another reference
226  // to this function, otherwise it will expire
227  int funcWeakRef = g_lua.weakRef();
228  func = [=](Args... args) {
229  // note that we must catch exceptions, because this lambda can be called from anywhere
230  // and most of them won't catch exceptions (e.g. dispatcher)
231  g_lua.getWeakRef(funcWeakRef);
232  try {
233  if(g_lua.isFunction()) {
234  int numArgs = g_lua.polymorphicPush(args...);
235  int rets = g_lua.safeCall(numArgs);
236  g_lua.pop(rets);
237  } else {
238  throw LuaException("attempt to call an expired lua function from C++,"
239  "did you forget to hold a reference for that function?", 0);
240  }
241  } catch(LuaException& e) {
242  g_logger.error(stdext::format("lua function callback failed: %s", e.what()));
243  }
244  };
245  return true;
246  } else if(g_lua.isNil(index)) {
247  func = std::function<void(Args...)>();
248  return true;
249  }
250  return false;
251 }
252 
253 template<typename Ret, typename... Args>
254 typename std::enable_if<!std::is_void<Ret>::value, bool>::type
255 luavalue_cast(int index, std::function<Ret(Args...)>& func) {
256  if(g_lua.isFunction(index)) {
257  g_lua.pushValue(index);
258  // weak references are used here, this means that the script must hold another reference
259  // to this function, otherwise it will expire
260  int funcWeakRef = g_lua.weakRef();
261  func = [=](Args... args) -> Ret {
262  // note that we must catch exceptions, because this lambda can be called from anywhere
263  // and most of them won't catch exceptions (e.g. dispatcher)
264  try {
265  g_lua.getWeakRef(funcWeakRef);
266  if(g_lua.isFunction()) {
267  int numArgs = g_lua.polymorphicPush(args...);
268  if(g_lua.safeCall(numArgs) != 1)
269  throw LuaException("a function from lua didn't retrieve the expected number of results", 0);
270  return g_lua.polymorphicPop<Ret>();
271  } else {
272  throw LuaException("attempt to call an expired lua function from C++,"
273  "did you forget to hold a reference for that function?", 0);
274  }
275  } catch(LuaException& e) {
276  g_logger.error(stdext::format("lua function callback failed: %s", e.what()));
277  }
278  return Ret();
279  };
280  return true;
281  } else if(g_lua.isNil(index)) {
282  func = std::function<Ret(Args...)>();
283  return true;
284  }
285  return false;
286 }
287 
288 template<typename T>
289 int push_luavalue(const std::list<T>& list) {
290  g_lua.createTable(list.size(), 0);
291  int i = 1;
292  for(const T& v : list) {
294  g_lua.rawSeti(i);
295  i++;
296  }
297  return 1;
298 }
299 
300 template<typename T>
301 bool luavalue_cast(int index, std::list<T>& list)
302 {
303  if(g_lua.isTable(index)) {
304  g_lua.pushNil();
305  while(g_lua.next(index < 0 ? index-1 : index)) {
306  T value;
307  if(luavalue_cast(-1, value))
308  list.push_back(value);
309  g_lua.pop();
310  }
311  return true;
312  }
313  return false;
314 }
315 
316 template<typename T>
317 int push_luavalue(const std::vector<T>& vec) {
318  g_lua.createTable(vec.size(), 0);
319  int i = 1;
320  for(const T& v : vec) {
322  g_lua.rawSeti(i);
323  i++;
324  }
325  return 1;
326 }
327 
328 template<typename T>
329 bool luavalue_cast(int index, std::vector<T>& vec)
330 {
331  if(g_lua.isTable(index)) {
332  g_lua.pushNil();
333  while(g_lua.next(index < 0 ? index-1 : index)) {
334  T value;
335  if(luavalue_cast(-1, value))
336  vec.push_back(value);
337  g_lua.pop();
338  }
339  return true;
340  }
341  return false;
342 }
343 
344 template<typename T>
345 int push_luavalue(const std::deque<T>& vec) {
346  g_lua.createTable(vec.size(), 0);
347  int i = 1;
348  for(const T& v : vec) {
350  g_lua.rawSeti(i);
351  i++;
352  }
353  return 1;
354 }
355 
356 template<typename T>
357 bool luavalue_cast(int index, std::deque<T>& vec)
358 {
359  if(g_lua.isTable(index)) {
360  g_lua.pushNil();
361  while(g_lua.next(index < 0 ? index-1 : index)) {
362  T value;
363  if(luavalue_cast(-1, value))
364  vec.push_back(value);
365  g_lua.pop();
366  }
367  return true;
368  }
369  return false;
370 }
371 
372 template<class K, class V>
373 int push_luavalue(const std::map<K, V>& map)
374 {
375  g_lua.newTable();
376  for(auto& it : map) {
377  push_internal_luavalue(it.first);
378  push_internal_luavalue(it.second);
379  g_lua.rawSet();
380  }
381  return 1;
382 }
383 
384 template<class K, class V>
385 bool luavalue_cast(int index, std::map<K, V>& map)
386 {
387  if(g_lua.isTable(index)) {
388  g_lua.pushNil();
389  while(g_lua.next(index < 0 ? index-1 : index)) {
390  K key;
391  V value;
392  if(luavalue_cast(-1, value) && luavalue_cast(-2, key))
393  map[key] = value;
394  g_lua.pop();
395  }
396  return true;
397  }
398  return false;
399 }
400 
401 
402 template<int N>
404  template<typename Tuple>
405  static void call(const Tuple& tuple) {
406  push_internal_luavalue(std::get<N-1>(tuple));
407  g_lua.rawSeti(N);
409  }
410 };
411 
412 template<>
414  template<typename Tuple>
415  static void call(const Tuple& tuple) { }
416 };
417 
418 template<typename... Args>
419 int push_internal_luavalue(const std::tuple<Args...>& tuple) {
420  g_lua.newTable();
421  push_tuple_internal_luavalue<sizeof...(Args)>::call(tuple);
422  return 1;
423 }
424 
425 template<int N>
427  template<typename Tuple>
428  static void call(const Tuple& tuple) {
429  push_internal_luavalue(std::get<std::tuple_size<Tuple>::value - N>(tuple));
431  }
432 };
433 
434 template<>
436  template<typename Tuple>
437  static void call(const Tuple& tuple) { }
438 };
439 
440 template<typename... Args>
441 int push_luavalue(const std::tuple<Args...>& tuple) {
442  push_tuple_luavalue<sizeof...(Args)>::call(tuple);
443  return sizeof...(Args);
444 }
445 
446 #endif
LuaInterface::rawSeti
void rawSeti(int n, int index=-2)
Definition: luainterface.cpp:978
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
TRect
Definition: rect.h:37
push_tuple_internal_luavalue< 0 >::call
static void call(const Tuple &tuple)
Definition: luavaluecasts.h:415
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:1180
push_tuple_luavalue< 0 >::call
static void call(const Tuple &tuple)
Definition: luavaluecasts.h:437
int64
int64_t int64
Definition: types.h:38
stdext::format
std::string format()
Definition: format.h:82
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:989
declarations.h
LuaInterface::weakRef
int weakRef()
Definition: luainterface.cpp:764
LuaInterface::isNil
bool isNil(int index=-1)
Definition: luainterface.cpp:1150
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
LuaInterface::pushObject
void pushObject(const LuaObjectPtr &obj)
Definition: luainterface.cpp:1109
luavalue_cast
bool luavalue_cast(int index, Outfit &outfit)
Definition: luavaluecasts.cpp:52
LuaInterface::pushValue
void pushValue(int index=-1)
Definition: luainterface.cpp:1143
uint64
uint64_t uint64
Definition: types.h:34
LuaInterface::pushCppFunction
void pushCppFunction(const LuaCppFunction &func)
Definition: luainterface.cpp:1127
push_tuple_internal_luavalue::call
static void call(const Tuple &tuple)
Definition: luavaluecasts.h:405
LuaInterface::isTable
bool isTable(int index=-1)
Definition: luainterface.cpp:1174
push_tuple_luavalue::call
static void call(const Tuple &tuple)
Definition: luavaluecasts.h:428
push_tuple_luavalue
Definition: luavaluecasts.h:426
LuaInterface::pop
void pop(int n=1)
Definition: luainterface.cpp:999
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:851
LuaException::what
virtual const char * what() const
Definition: luaexception.h:36
TPoint< int >
push_tuple_internal_luavalue
Definition: luavaluecasts.h:403
int16
int16_t int16
Definition: types.h:40
LuaInterface::pushNil
void pushNil()
Definition: luainterface.cpp:1060
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:972
uint8
uint8_t uint8
Definition: types.h:37
LuaInterface::next
bool next(int index=-2)
Definition: luainterface.cpp:831
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:432
LuaInterface::newTable
void newTable()
Definition: luainterface.cpp:984