xoreos  0.0.5
table.cpp
Go to the documentation of this file.
1 /* xoreos - A reimplementation of BioWare's Aurora engine
2  *
3  * xoreos is the legal property of its developers, whose names
4  * can be found in the AUTHORS file distributed with this source
5  * distribution.
6  *
7  * xoreos is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License
9  * as published by the Free Software Foundation; either version 3
10  * of the License, or (at your option) any later version.
11  *
12  * xoreos is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with xoreos. If not, see <http://www.gnu.org/licenses/>.
19  */
20 
25 #include "toluapp/tolua++.h"
26 
27 #include "src/common/error.h"
28 #include "src/common/util.h"
29 
30 #include "src/aurora/lua/table.h"
31 #include "src/aurora/lua/stack.h"
35 
36 namespace Aurora {
37 
38 namespace Lua {
39 
40 TableRef::TableRef() : _luaState(0),
41  _ref(LUA_REFNIL), _metaAccessEnabled(true) {
42 }
43 
44 TableRef::TableRef(const Stack &stack, int index) : _luaState(&stack.getLuaState()),
45  _ref(LUA_REFNIL), _metaAccessEnabled(true) {
46 
47  lua_pushvalue(_luaState, index);
48  _ref = lua_ref(_luaState, true);
49 }
50 
51 TableRef::TableRef(lua_State &state, int index) : _luaState(&state),
52  _ref(LUA_REFNIL), _metaAccessEnabled(true) {
53 
54  lua_pushvalue(_luaState, index);
55  _ref = lua_ref(_luaState, true);
56 }
57 
58 TableRef::TableRef(const TableRef &table) : _luaState(table._luaState),
59  _ref(LUA_REFNIL), _metaAccessEnabled(table._metaAccessEnabled) {
60 
61  if (table._luaState && table._ref != LUA_REFNIL) {
62  lua_getref(_luaState, table._ref);
63  _ref = lua_ref(_luaState, true);
64  } else {
65  _luaState = 0;
66  }
67 }
68 
70  lua_unref(_luaState, _ref);
71 }
72 
73 const TableRef& TableRef::operator=(const TableRef &table) {
74  if (this == &table) {
75  return *this;
76  }
77 
78  assert(table._luaState && table._ref != LUA_REFNIL);
79 
80  lua_State *oldState = _luaState;
81  const int oldRef = _ref;
82 
83  lua_getref(table._luaState, table._ref);
84  _luaState = table._luaState;
85  _ref = lua_ref(_luaState, true);
87 
88  if (oldState && oldRef != LUA_REFNIL) {
89  lua_unref(oldState, oldRef);
90  }
91  return *this;
92 }
93 
94 int TableRef::getSize() const {
95  StackGuard guard(*_luaState);
96 
97  pushSelf();
98 
99  int size = 0;
100  const int top = lua_gettop(_luaState);
101  for (lua_pushnil(_luaState); lua_next(_luaState, top); lua_pop(_luaState, 1)) {
102  ++size;
103  }
104  return size;
105 }
106 
108  StackGuard guard(*_luaState);
109 
110  pushSelf();
111 
112  Stack stack(*_luaState);
113  return stack.getExactTypeAt(-1);
114 }
115 
117  StackGuard guard(*_luaState);
118 
119  pushSelf();
120  lua_getmetatable(_luaState, -1);
121 
122  Stack stack(*_luaState);
123  return stack.getTableAt(-1);
124 }
125 
126 void TableRef::setMetaAccessEnabled(bool enabled) {
127  _metaAccessEnabled = enabled;
128 }
129 
131  return _metaAccessEnabled;
132 }
133 
134 void TableRef::removeAt(int index) {
135  StackGuard guard(*_luaState);
136 
137  pushSelf();
138 
139  lua_pushnil(_luaState);
140  lua_rawseti(_luaState, -2, index);
141 }
142 
144  StackGuard guard(*_luaState);
145 
146  pushSelf();
147 
148  lua_pushstring(_luaState, key.c_str());
149  lua_pushnil(_luaState);
150 
151  if (_metaAccessEnabled) {
152  lua_settable(_luaState, -3);
153  } else {
154  lua_rawset(_luaState, -3);
155  }
156 }
157 
158 void TableRef::setBooleanAt(int index, bool value) {
159  setVariableAt(index, value);
160 }
161 
162 void TableRef::setBooleanAt(const Common::UString &key, bool value) {
163  setVariableAt(key, value);
164 }
165 
166 void TableRef::setFloatAt(int index, float value) {
167  setVariableAt(index, value);
168 }
169 
170 void TableRef::setFloatAt(const Common::UString &key, float value) {
171  setVariableAt(key, value);
172 }
173 
174 void TableRef::setIntAt(int index, int value) {
175  setVariableAt(index, value);
176 }
177 
178 void TableRef::setIntAt(const Common::UString &key, int value) {
179  setVariableAt(key, value);
180 }
181 
182 void TableRef::setStringAt(int index, const char *value) {
183  setVariableAt(index, value);
184 }
185 
186 void TableRef::setStringAt(const Common::UString &key, const char *value) {
187  setVariableAt(key, value);
188 }
189 
190 void TableRef::setStringAt(int index, const Common::UString &value) {
191  setVariableAt(index, value);
192 }
193 
194 void TableRef::setStringAt(const Common::UString &key, const Common::UString &value) {
195  setVariableAt(key, value);
196 }
197 
198 void TableRef::setTableAt(int index, const TableRef &value) {
199  setVariableAt(index, value);
200 }
201 
202 void TableRef::setTableAt(const Common::UString &key, const TableRef &value) {
203  setVariableAt(key, value);
204 }
205 
206 void TableRef::setFunctionAt(int index, const FunctionRef &value) {
207  setVariableAt(index, value);
208 }
209 
210 void TableRef::setFunctionAt(const Common::UString &key, const FunctionRef &value) {
211  setVariableAt(key, value);
212 }
213 
214 void TableRef::setUserTypeAt(int index, void *value, const Common::UString &type) {
215  setVariableAt(index, Variable(value, type));
216 }
217 
218 void TableRef::setUserTypeAt(const Common::UString &key, void *value, const Common::UString &type) {
219  setVariableAt(key, Variable(value, type));
220 }
221 
222 void TableRef::setVariableAt(int index, const Variable &value) {
223  StackGuard guard(*_luaState);
224 
225  pushSelf();
226 
227  Stack stack(*_luaState);
228  stack.pushVariable(value);
229  lua_rawseti(_luaState, -2, index);
230 }
231 
232 void TableRef::setVariableAt(const Common::UString &key, const Variable &value) {
233  StackGuard guard(*_luaState);
234 
235  pushSelf();
236  lua_pushstring(_luaState, key.c_str());
237 
238  Stack stack(*_luaState);
239  stack.pushVariable(value);
240 
241  if (_metaAccessEnabled) {
242  lua_settable(_luaState, -3);
243  } else {
244  lua_rawset(_luaState, -3);
245  }
246 }
247 
248 bool TableRef::getBooleanAt(int index) const {
249  if (!isBooleanAt(index)) {
250  throw Common::Exception("Failed get a boolean value from the table (index: %d)", index);
251  }
252 
253  return getVariableAt(index).getBool();
254 }
255 
256 bool TableRef::getBooleanAt(const Common::UString &key) const {
257  if (!isBooleanAt(key)) {
258  throw Common::Exception("Failed get a boolean value from the table (key: %s)", key.c_str());
259  }
260 
261  return getVariableAt(key).getBool();
262 }
263 
264 float TableRef::getFloatAt(int index) const {
265  if (!isNumberAt(index)) {
266  throw Common::Exception("Failed get a float value from the table (index: %d)", index);
267  }
268 
269  return getVariableAt(index).getFloat();
270 }
271 
272 float TableRef::getFloatAt(const Common::UString &key) const {
273  if (!isNumberAt(key)) {
274  throw Common::Exception("Failed get a float value from the table (key: %s)", key.c_str());
275  }
276 
277  return getVariableAt(key).getFloat();
278 }
279 
280 int TableRef::getIntAt(int index) const {
281  if (!isNumberAt(index)) {
282  throw Common::Exception("Failed get an integer value from the table (index: %d)", index);
283  }
284 
285  return getVariableAt(index).getInt();
286 }
287 
288 int TableRef::getIntAt(const Common::UString &key) const {
289  if (!isNumberAt(key)) {
290  throw Common::Exception("Failed get an integer value from the table (key: %s)", key.c_str());
291  }
292 
293  return getVariableAt(key).getInt();
294 }
295 
297  if (!isStringAt(index)) {
298  throw Common::Exception("Failed get a string value from the table (index: %d)", index);
299  }
300 
301  return getVariableAt(index).getString();
302 }
303 
305  if (!isStringAt(key)) {
306  throw Common::Exception("Failed get a string value from the table (key: %s)", key.c_str());
307  }
308 
309  return getVariableAt(key).getString();
310 }
311 
312 TableRef TableRef::getTableAt(int index) const {
313  if (!isTableAt(index)) {
314  throw Common::Exception("Failed get a table value from the table (index: %d)", index);
315  }
316 
317  return getVariableAt(index).getTable();
318 }
319 
321  if (!isTableAt(key)) {
322  throw Common::Exception("Failed get a table value from the table (key: %s)", key.c_str());
323  }
324 
325  return getVariableAt(key).getTable();
326 }
327 
329  if (!isFunctionAt(index)) {
330  throw Common::Exception("Failed get a function value from the table (index: %d)", index);
331  }
332 
333  return getVariableAt(index).getFunction();
334 }
335 
337  if (!isFunctionAt(key)) {
338  throw Common::Exception("Failed get a function value from the table (key: %s)", key.c_str());
339  }
340 
341  return getVariableAt(key).getFunction();
342 }
343 
344 void *TableRef::getRawUserTypeAt(int index, const Common::UString &type) const {
345  if (!isUserTypeAt(index, type)) {
346  throw Common::Exception("Failed get a usertype value from the table (index: %d)", index);
347  }
348 
349  return getVariableAt(index).getRawUserType();
350 }
351 
352 void *TableRef::getRawUserTypeAt(const Common::UString &key, const Common::UString &type) const {
353  if (!isUserTypeAt(key, type)) {
354  throw Common::Exception("Failed get a usertype value from the table (key: %s)", key.c_str());
355  }
356 
357  return getVariableAt(key).getRawUserType();
358 }
359 
361  StackGuard guard(*_luaState);
362 
363  pushSelf();
364  lua_rawgeti(_luaState, -1, index);
365 
366  Stack stack(*_luaState);
367  return stack.getVariableAt(-1);
368 }
369 
371  StackGuard guard(*_luaState);
372 
373  pushSelf();
374  lua_pushstring(_luaState, key.c_str());
375 
376  if (_metaAccessEnabled) {
377  lua_gettable(_luaState, -2);
378  } else {
379  lua_rawget(_luaState, -2);
380  }
381 
382  Stack stack(*_luaState);
383  return stack.getVariableAt(-1);
384 }
385 
387  StackGuard guard(*_luaState);
388 
389  pushSelf();
390  lua_rawgeti(_luaState, -1, index);
391 
392  Stack stack(*_luaState);
393  return stack.getExactTypeAt(-1);
394 }
395 
397  StackGuard guard(*_luaState);
398 
399  pushSelf();
400  lua_pushstring(_luaState, key.c_str());
401 
402  if (_metaAccessEnabled) {
403  lua_gettable(_luaState, -2);
404  } else {
405  lua_rawget(_luaState, -2);
406  }
407 
408  Stack stack(*_luaState);
409  return stack.getExactTypeAt(-1);
410 }
411 
412 Type TableRef::getTypeAt(int index) const {
413  StackGuard guard(*_luaState);
414 
415  pushSelf();
416  lua_rawgeti(_luaState, -1, index);
417 
418  Stack stack(*_luaState);
419  return stack.getTypeAt(-1);
420 }
421 
423  StackGuard guard(*_luaState);
424 
425  pushSelf();
426  lua_pushstring(_luaState, key.c_str());
427 
428  if (_metaAccessEnabled) {
429  lua_gettable(_luaState, -2);
430  } else {
431  lua_rawget(_luaState, -2);
432  }
433 
434  Stack stack(*_luaState);
435  return stack.getTypeAt(-1);
436 }
437 
439  StackGuard guard(*_luaState);
440 
441  pushSelf();
442 
443  Variables vars;
444  const int top = lua_gettop(_luaState);
445  for (lua_pushnil(_luaState); lua_next(_luaState, top); lua_pop(_luaState, 1)) {
446  Stack stack(*_luaState);
447  vars.push_back(stack.getVariableAt(-1));
448  }
449  return vars;
450 }
451 
452 bool TableRef::isNilAt(int index) const {
453  return getTypeAt(index) == kTypeNil;
454 }
455 
456 bool TableRef::isNilAt(const Common::UString &key) const {
457  return getTypeAt(key) == kTypeNil;
458 }
459 
460 bool TableRef::isBooleanAt(int index) const {
461  return getTypeAt(index) == kTypeBoolean;
462 }
463 
464 bool TableRef::isBooleanAt(const Common::UString &key) const {
465  return getTypeAt(key) == kTypeBoolean;
466 }
467 
468 bool TableRef::isNumberAt(int index) const {
469  return getTypeAt(index) == kTypeNumber;
470 }
471 
472 bool TableRef::isNumberAt(const Common::UString &key) const {
473  return getTypeAt(key) == kTypeNumber;
474 }
475 
476 bool TableRef::isStringAt(int index) const {
477  return getTypeAt(index) == kTypeString;
478 }
479 
480 bool TableRef::isStringAt(const Common::UString &key) const {
481  return getTypeAt(key) == kTypeString;
482 }
483 
484 bool TableRef::isTableAt(int index) const {
485  return getTypeAt(index) == kTypeTable;
486 }
487 
488 bool TableRef::isTableAt(const Common::UString &key) const {
489  return getTypeAt(key) == kTypeTable;
490 }
491 
492 bool TableRef::isFunctionAt(int index) const {
493  return getTypeAt(index) == kTypeFunction;
494 }
495 
496 bool TableRef::isFunctionAt(const Common::UString &key) const {
497  return getTypeAt(key) == kTypeFunction;
498 }
499 
500 bool TableRef::isUserTypeAt(int index, const Common::UString &type) const {
501  const bool isUT = getTypeAt(index) == kTypeUserType;
502  if (type.empty()) {
503  return isUT;
504  }
505  return isUT && getExactTypeAt(index) == type;
506 }
507 
508 bool TableRef::isUserTypeAt(const Common::UString &key, const Common::UString &type) const {
509  const bool isUT = getTypeAt(key) == kTypeUserType;
510  if (type.empty()) {
511  return isUT;
512  }
513  return isUT && getExactTypeAt(key) == type;
514 }
515 
516 lua_State &TableRef::getLuaState() const {
517  assert(_luaState);
518 
519  return *_luaState;
520 }
521 
522 int TableRef::getRef() const {
523  return _ref;
524 }
525 
526 void TableRef::pushSelf() const {
527  assert(_luaState && _ref != LUA_REFNIL);
528 
529  lua_getref(_luaState, _ref);
530 }
531 
532 } // End of namespace Lua
533 
534 } // End of namespace Aurora
void * getRawUserType() const
Definition: variable.cpp:351
void removeAt(int index)
Definition: table.cpp:134
bool getBooleanAt(int index) const
Definition: table.cpp:248
TableRef getTableAt(int index) const
Return a table at the given index in the stack.
Definition: stack.cpp:162
void setStringAt(int index, const char *value)
Definition: table.cpp:182
A class holding an UTF-8 string.
Definition: ustring.h:48
int32 getInt() const
Definition: variable.cpp:295
TableRef getTableAt(int index) const
Definition: table.cpp:312
A reference to a Lua function.
float getFloatAt(int index) const
Definition: table.cpp:264
Variable getVariableAt(int index) const
Definition: stack.cpp:185
const FunctionRef & getFunction() const
Definition: variable.cpp:343
TableRef & getTable()
Definition: variable.cpp:327
Common::UString getExactTypeAt(int index) const
Return the type of the value at the given index in the stack.
Definition: stack.cpp:208
Lua stack guard.
bool isUserTypeAt(int index, const Common::UString &type="") const
Check whether the value at the given index is a usertype value.
Definition: table.cpp:500
void setVariableAt(int index, const Variable &value)
Definition: table.cpp:222
Common::UString getExactType() const
Definition: table.cpp:107
const TableRef & operator=(const TableRef &table)
Definition: table.cpp:73
float getFloat() const
Definition: variable.cpp:303
void setUserTypeAt(int index, void *value, const Common::UString &type)
Push a usertype value onto the stack.
Definition: table.cpp:214
FunctionRef getFunctionAt(int index) const
Definition: table.cpp:328
Basic exceptions to throw.
const char * c_str() const
Return the (utf8 encoded) string data.
Definition: ustring.cpp:249
TableRef getMetaTable() const
Definition: table.cpp:116
bool isNumberAt(int index) const
Definition: table.cpp:468
int getRef() const
Definition: table.cpp:522
Utility templates and functions.
void setFloatAt(int index, float value)
Definition: table.cpp:166
Common::UString & getString()
Definition: variable.cpp:319
bool getBool() const
Definition: variable.cpp:287
void setBooleanAt(int index, bool value)
Definition: table.cpp:158
bool _metaAccessEnabled
Definition: table.h:146
Type getTypeAt(int index) const
Definition: stack.cpp:218
bool isNilAt(int index) const
Definition: table.cpp:452
bool empty() const
Is the string empty?
Definition: ustring.cpp:245
void pushSelf() const
Definition: table.cpp:526
StackException Exception
Definition: error.h:59
Lua stack guard.
Definition: stackguard.h:37
int getSize() const
Return the number of elements in the table.
Definition: table.cpp:94
A Lua stack wrapper.
Definition: stack.h:41
std::vector< Variable > Variables
Definition: types.h:50
void setTableAt(int index, const TableRef &value)
Definition: table.cpp:198
void setFunctionAt(int index, const FunctionRef &value)
Definition: table.cpp:206
A reference to a Lua function.
Definition: function.h:35
bool isFunctionAt(int index) const
Definition: table.cpp:492
Variables getVariables() const
Definition: table.cpp:438
bool isMetaAccessEnabled() const
Definition: table.cpp:130
void setIntAt(int index, int value)
Definition: table.cpp:174
Common::UString getStringAt(int index) const
Definition: table.cpp:296
int getIntAt(int index) const
Definition: table.cpp:280
bool isTableAt(int index) const
Definition: table.cpp:484
lua_State & getLuaState() const
Return the underlying Lua state.
Definition: table.cpp:516
void * getRawUserTypeAt(int index, const Common::UString &type="") const
Return a usertype value at the given index in the stack.
Definition: table.cpp:344
A reference to a Lua table.
Definition: table.h:37
A reference to a Lua table.
Common::UString getExactTypeAt(int index) const
Definition: table.cpp:386
void pushVariable(const Variable &var)
Definition: stack.cpp:98
lua_State * _luaState
The Lua state.
Definition: table.h:144
bool isStringAt(int index) const
Definition: table.cpp:476
Lua variable.
A Lua stack wrapper.
bool isBooleanAt(int index) const
Definition: table.cpp:460
Type getTypeAt(int index) const
Definition: table.cpp:412
void setMetaAccessEnabled(bool enabled)
Enable/Disable access to the table elements using metamethods.
Definition: table.cpp:126
Variable getVariableAt(int index) const
Definition: table.cpp:360