xoreos  0.0.5
stack.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/ustring.h"
29 #include "src/common/util.h"
30 
31 #include "src/aurora/lua/stack.h"
33 #include "src/aurora/lua/table.h"
35 
36 namespace Aurora {
37 
38 namespace Lua {
39 
40 Stack::Stack(lua_State &state) : _luaState(state) {
41 
42 }
43 
45 
46 }
47 
48 int Stack::getSize() const {
49  return lua_gettop(&_luaState);
50 }
51 
53  lua_pushnil(&_luaState);
54 }
55 
56 void Stack::pushBoolean(bool value) {
57  lua_pushboolean(&_luaState, value ? 1 : 0);
58 }
59 
60 void Stack::pushFloat(float value) {
61  lua_pushnumber(&_luaState, value);
62 }
63 
64 void Stack::pushInt(int value) {
65  lua_pushnumber(&_luaState, value);
66 }
67 
68 void Stack::pushString(const char *value) {
69  lua_pushstring(&_luaState, value);
70 }
71 
72 void Stack::pushString(const Common::UString &value) {
73  lua_pushstring(&_luaState, value.c_str());
74 }
75 
76 void Stack::pushTable(const TableRef &value) {
77  const int ref = value.getRef();
78  if (ref != LUA_REFNIL) {
79  lua_getref(&_luaState, ref);
80  } else {
81  lua_pushnil(&_luaState);
82  }
83 }
84 
85 void Stack::pushFunction(const FunctionRef &value) {
86  const int ref = value.getRef();
87  if (ref != LUA_REFNIL) {
88  lua_getref(&_luaState, ref);
89  } else {
90  lua_pushnil(&_luaState);
91  }
92 }
93 
94 void Stack::pushRawUserType(void *value, const Common::UString &type) {
95  tolua_pushusertype(&_luaState, value, type.c_str());
96 }
97 
98 void Stack::pushVariable(const Variable &var) {
99  switch (var.getType()) {
100  case kTypeNil:
101  pushNil();
102  break;
103  case kTypeBoolean:
104  pushBoolean(var.getBool());
105  break;
106  case kTypeNumber:
107  pushFloat(var.getFloat());
108  break;
109  case kTypeString:
110  pushString(var.getString());
111  break;
112  case kTypeTable:
113  pushTable(var.getTable());
114  break;
115  case kTypeFunction:
116  pushFunction(var.getFunction());
117  break;
118  case kTypeUserType:
120  break;
121  default:
122  warning("Pushing a varible of type \"%s\" not supported",
123  var.getExactType().c_str());
124  break;
125  }
126 }
127 
128 void Stack::pushVariables(const Variables &vars) {
129  for (Variables::const_iterator v = vars.begin(); v != vars.end(); ++v) {
130  pushVariable(*v);
131  }
132 }
133 
134 bool Stack::getBooleanAt(int index) const {
135  if (!isBooleanAt(index)) {
136  throw Common::Exception("Failed to get a boolean value from the Lua stack (index: %d)", index);
137  }
138  return lua_toboolean(&_luaState, index) != 0;
139 }
140 
141 float Stack::getFloatAt(int index) const {
142  if (!isNumberAt(index)) {
143  throw Common::Exception("Failed to get a number from the Lua stack (index: %d)", index);
144  }
145  return lua_tonumber(&_luaState, index);
146 }
147 
148 int Stack::getIntAt(int index) const {
149  if (!isNumberAt(index)) {
150  throw Common::Exception("Failed to get a number from the Lua stack (index: %d)", index);
151  }
152  return lua_tonumber(&_luaState, index);
153 }
154 
156  if (!isStringAt(index)) {
157  throw Common::Exception("Failed to get a string from the Lua stack (index: %d)", index);
158  }
159  return lua_tostring(&_luaState, index);
160 }
161 
162 TableRef Stack::getTableAt(int index) const {
163  if (!isTableAt(index)) {
164  throw Common::Exception("Failed to get a table from the Lua stack (index: %d)", index);
165  }
166  return TableRef(_luaState, index);
167 }
168 
170  if (!isFunctionAt(index)) {
171  throw Common::Exception("Failed to get a function from the Lua stack (index: %d)", index);
172  }
173  return FunctionRef(_luaState, index);
174 }
175 
176 void *Stack::getRawUserTypeAt(int index, const Common::UString &type) const {
177  if (!isUserTypeAt(index, type)) {
178  const char *msg = "Failed to get a usertype value from the Lua stack (type: %s, index: %d)";
179  throw Common::Exception(msg, type.c_str(), index);
180  }
181 
182  return tolua_tousertype(&_luaState, index, 0);
183 }
184 
185 Variable Stack::getVariableAt(int index) const {
186  switch (getTypeAt(index)) {
187  case kTypeNil:
188  return Variable(kTypeNil);
189  case kTypeBoolean:
190  return getBooleanAt(index);
191  case kTypeNumber:
192  return getFloatAt(index);
193  case kTypeString:
194  return getStringAt(index);
195  case kTypeTable:
196  return getTableAt(index);
197  case kTypeFunction:
198  return getFunctionAt(index);
199  case kTypeUserType: {
200  const Common::UString exactType = getExactTypeAt(index);
201  return Variable(getRawUserTypeAt(index, exactType), exactType);
202  }
203  default:
204  return Variable(kTypeNone);
205  }
206 }
207 
209  if (!checkIndex(index)) {
210  return "none";
211  }
212 
213  const Common::UString type = tolua_typename(&_luaState, index);
214  lua_pop(&_luaState, 1);
215  return type;
216 }
217 
218 Type Stack::getTypeAt(int index) const {
219  if (!checkIndex(index)) {
220  return kTypeNone;
221  }
222 
223  switch (lua_type(&_luaState, index)) {
224  case LUA_TNONE:
225  return kTypeNone;
226  case LUA_TNIL:
227  return kTypeNil;
228  case LUA_TBOOLEAN:
229  return kTypeBoolean;
230  case LUA_TNUMBER:
231  return kTypeNumber;
232  case LUA_TSTRING:
233  return kTypeString;
234  case LUA_TTABLE:
235  return kTypeTable;
236  case LUA_TFUNCTION:
237  return kTypeFunction;
238  case LUA_TUSERDATA:
239  return kTypeUserType;
240  default:
241  warning("Unhandled Lua type: %s", lua_typename(&_luaState, index));
242  return kTypeNone;
243  }
244 }
245 
247  Variables vars;
248  for (int i = 1; i <= getSize(); ++i) {
249  vars.push_back(getVariableAt(i));
250  }
251  return vars;
252 }
253 
255  Variables vars;
256  const int start = std::max(0, getSize() - count) + 1;
257  for (int i = start; i <= getSize(); ++i) {
258  vars.push_back(getVariableAt(i));
259  }
260  return vars;
261 }
262 
263 bool Stack::isNilAt(int index) const {
264  return checkIndex(index) && lua_isnil(&_luaState, index);
265 }
266 
267 bool Stack::isBooleanAt(int index) const {
268  return checkIndex(index) && lua_isboolean(&_luaState, index);
269 }
270 
271 bool Stack::isNumberAt(int index) const {
272  return checkIndex(index) && lua_isnumber(&_luaState, index) != 0;
273 }
274 
275 bool Stack::isStringAt(int index) const {
276  return checkIndex(index) && lua_isstring(&_luaState, index) != 0;
277 }
278 
279 bool Stack::isTableAt(int index) const {
280  return checkIndex(index) && lua_istable(&_luaState, index);
281 }
282 
283 bool Stack::isFunctionAt(int index) const {
284  return checkIndex(index) && lua_isfunction(&_luaState, index);
285 }
286 
287 bool Stack::isUserTypeAt(int index, const Common::UString &type) const {
288  if (type.empty()) {
289  return getTypeAt(index) == kTypeUserType;
290  }
291 
292  tolua_Error error;
293  return checkIndex(index) && tolua_isusertype(&_luaState, index, type.c_str(), 0, &error) != 0;
294 }
295 
297  assert(getTypeAt(getSize()) == kTypeUserType);
298  tolua_register_gc(&_luaState, getSize());
299 }
300 
301 lua_State &Stack::getLuaState() const {
302  return _luaState;
303 }
304 
305 bool Stack::checkIndex(int index) const {
306  index = std::abs(index);
307  return index > 0 && index <= getSize();
308 }
309 
310 } // End of namespace Lua
311 
312 } // End of namespace Aurora
bool isNilAt(int index) const
Check whether the value with the given index is a nil.
Definition: stack.cpp:263
bool isStringAt(int index) const
Check whether the value at the given index is a string.
Definition: stack.cpp:275
void * getRawUserType() const
Definition: variable.cpp:351
Variables getVariablesFromTop(int count) const
Definition: stack.cpp:254
TableRef getTableAt(int index) const
Return a table at the given index in the stack.
Definition: stack.cpp:162
bool checkIndex(int index) const
Check whether the given index is valid.
Definition: stack.cpp:305
A class holding an UTF-8 string.
Definition: ustring.h:48
Stack(lua_State &state)
Definition: stack.cpp:40
void pushVariables(const Variables &vars)
Definition: stack.cpp:128
Common::UString getStringAt(int index) const
Return a string at the given index in the stack.
Definition: stack.cpp:155
A reference to a Lua function.
void pushInt(int value)
Push an integer value onto the stack.
Definition: stack.cpp:64
Variable getVariableAt(int index) const
Definition: stack.cpp:185
bool isBooleanAt(int index) const
Check whether the value at the given index is a boolean value.
Definition: stack.cpp:267
const FunctionRef & getFunction() const
Definition: variable.cpp:343
TableRef & getTable()
Definition: variable.cpp:327
Type getType() const
Definition: variable.cpp:279
int getSize() const
Return the number of elements in the stack.
Definition: stack.cpp:48
FunctionRef getFunctionAt(int index) const
Return a function at the given index in the stack.
Definition: stack.cpp:169
Common::UString getExactTypeAt(int index) const
Return the type of the value at the given index in the stack.
Definition: stack.cpp:208
void pushFunction(const FunctionRef &value)
Push a function onto the stack.
Definition: stack.cpp:85
float getFloat() const
Definition: variable.cpp:303
void pushFloat(float value)
Push a float value onto the stack.
Definition: stack.cpp:60
Basic exceptions to throw.
const char * c_str() const
Return the (utf8 encoded) string data.
Definition: ustring.cpp:249
void registerGCForTopObject()
Definition: stack.cpp:296
int getRef() const
Definition: table.cpp:522
Utility templates and functions.
Common::UString & getString()
Definition: variable.cpp:319
bool getBooleanAt(int index) const
Return a boolean value at the given index in the stack.
Definition: stack.cpp:134
bool getBool() const
Definition: variable.cpp:287
void * getRawUserTypeAt(int index, const Common::UString &type="") const
Return a raw usertype value at the given index in the stack.
Definition: stack.cpp:176
void pushTable(const TableRef &value)
Push a table onto the stack.
Definition: stack.cpp:76
Type getTypeAt(int index) const
Definition: stack.cpp:218
bool empty() const
Is the string empty?
Definition: ustring.cpp:245
StackException Exception
Definition: error.h:59
std::vector< Variable > Variables
Definition: types.h:50
void pushRawUserType(void *value, const Common::UString &type)
Push a raw usertype value onto the stack.
Definition: stack.cpp:94
void warning(const char *s,...)
Definition: util.cpp:33
A reference to a Lua function.
Definition: function.h:35
void pushBoolean(bool value)
Push a boolean value onto the stack.
Definition: stack.cpp:56
Unicode string handling.
lua_State & _luaState
The Lua state.
Definition: stack.h:131
Variables getVariables() const
Definition: stack.cpp:246
bool isFunctionAt(int index) const
Check whether the value at the given index is a function.
Definition: stack.cpp:283
const Common::UString & getExactType() const
Definition: variable.cpp:283
void pushNil()
Push a nil value onto the stack.
Definition: stack.cpp:52
A reference to a Lua table.
Definition: table.h:37
A reference to a Lua table.
void pushVariable(const Variable &var)
Definition: stack.cpp:98
int getIntAt(int index) const
Return an integer value at the given index in the stack.
Definition: stack.cpp:148
float getFloatAt(int index) const
Return a float value at the given index in the stack.
Definition: stack.cpp:141
Lua variable.
void NORETURN_PRE error(const char *s,...)
Definition: util.cpp:86
bool isTableAt(int index) const
Check whether the value at the given index is a table.
Definition: stack.cpp:279
A Lua stack wrapper.
bool isNumberAt(int index) const
Check whether the value at the given index is a number.
Definition: stack.cpp:271
bool isUserTypeAt(int index, const Common::UString &type="") const
Check whether the value at the given index is a usertype value.
Definition: stack.cpp:287
lua_State & getLuaState() const
Return the underlying Lua state.
Definition: stack.cpp:301
void pushString(const char *value)
Push a raw C string onto the stack.
Definition: stack.cpp:68