2 // Copyright (C) 2006 Matthias Braun <matze@braunis.de>
4 // This program is free software: you can redistribute it and/or modify
5 // it under the terms of the GNU General Public License as published by
6 // the Free Software Foundation, either version 3 of the License, or
7 // (at your option) any later version.
9 // This program is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 // GNU General Public License for more details.
14 // You should have received a copy of the GNU General Public License
15 // along with this program. If not, see <http://www.gnu.org/licenses/>.
17 #include "scripting/squirrel_util.hpp"
23 #include <sqstdblob.h>
24 #include <sqstdmath.h>
25 #include <sqstdstring.h>
30 std::string squirrel2string(HSQUIRRELVM v, SQInteger i)
32 std::ostringstream os;
33 switch(sq_gettype(v, i))
40 if SQ_SUCCEEDED(sq_getbool(v, i, &p)) {
50 sq_getinteger(v, i, &val);
56 sq_getfloat(v, i, &val);
62 sq_getstring(v, i, &val);
63 os << "\"" << val << "\"";
69 sq_pushnull(v); //null iterator
70 while(SQ_SUCCEEDED(sq_next(v,i-1)))
77 //here -1 is the value and -2 is the key
78 os << squirrel2string(v, -2) << " => "
79 << squirrel2string(v, -1);
81 sq_pop(v,2); //pops key and val before the nex iteration
90 sq_pushnull(v); //null iterator
91 while(SQ_SUCCEEDED(sq_next(v,i-1)))
98 //here -1 is the value and -2 is the key
99 // we ignore the key, since that is just the index in an array
100 os << squirrel2string(v, -1);
102 sq_pop(v,2); //pops key and val before the nex iteration
114 case OT_NATIVECLOSURE:
115 os << "<native closure>";
142 void print_squirrel_stack(HSQUIRRELVM v)
144 printf("--------------------------------------------------------------\n");
145 int count = sq_gettop(v);
146 for(int i = 1; i <= count; ++i) {
148 switch(sq_gettype(v, i))
155 sq_getinteger(v, i, &val);
156 printf("integer (%d)", static_cast<int> (val));
161 sq_getfloat(v, i, &val);
162 printf("float (%f)", val);
167 sq_getstring(v, i, &val);
168 printf("string (%s)", val);
181 printf("closure(function)");
183 case OT_NATIVECLOSURE:
184 printf("native closure(C function)");
190 printf("userpointer");
205 printf("unknown?!?");
210 printf("--------------------------------------------------------------\n");
213 SQInteger squirrel_read_char(SQUserPointer file)
215 std::istream* in = reinterpret_cast<std::istream*> (file);
222 void compile_script(HSQUIRRELVM vm, std::istream& in, const std::string& sourcename)
224 if(SQ_FAILED(sq_compile(vm, squirrel_read_char, &in, sourcename.c_str(), true)))
225 throw SquirrelError(vm, "Couldn't parse script");
228 void compile_and_run(HSQUIRRELVM vm, std::istream& in,
229 const std::string& sourcename)
231 compile_script(vm, in, sourcename);
233 SQInteger oldtop = sq_gettop(vm);
236 sq_pushroottable(vm);
237 if(SQ_FAILED(sq_call(vm, 1, SQFalse, SQTrue)))
238 throw SquirrelError(vm, "Couldn't start script");
240 sq_settop(vm, oldtop);
244 // we can remove the closure in case the script was not suspended
245 if(sq_getvmstate(vm) != SQ_VMSTATE_SUSPENDED) {
246 sq_settop(vm, oldtop-1);
250 HSQOBJECT create_thread(HSQUIRRELVM vm)
252 HSQUIRRELVM new_vm = sq_newthread(vm, 64);
254 throw SquirrelError(vm, "Couldn't create new VM");
257 sq_resetobject(&vm_object);
258 if(SQ_FAILED(sq_getstackobj(vm, -1, &vm_object)))
259 throw SquirrelError(vm, "Couldn't get squirrel thread from stack");
260 sq_addref(vm, &vm_object);
267 HSQOBJECT vm_to_object(HSQUIRRELVM vm)
270 sq_resetobject(&object);
271 object._unVal.pThread = vm;
272 object._type = OT_THREAD;
277 HSQUIRRELVM object_to_vm(HSQOBJECT object)
279 if(object._type != OT_THREAD)
282 return object._unVal.pThread;
285 // begin: serialization functions
287 void store_float(HSQUIRRELVM vm, const char* name, float val)
289 sq_pushstring(vm, name, -1);
290 sq_pushfloat(vm, val);
291 if(SQ_FAILED(sq_createslot(vm, -3)))
292 throw scripting::SquirrelError(vm, "Couldn't add float value to table");
295 void store_int(HSQUIRRELVM vm, const char* name, int val)
297 sq_pushstring(vm, name, -1);
298 sq_pushinteger(vm, val);
299 if(SQ_FAILED(sq_createslot(vm, -3)))
300 throw scripting::SquirrelError(vm, "Couldn't add int value to table");
303 void store_string(HSQUIRRELVM vm, const char* name, const std::string& val)
305 sq_pushstring(vm, name, -1);
306 sq_pushstring(vm, val.c_str(), val.length());
307 if(SQ_FAILED(sq_createslot(vm, -3)))
308 throw scripting::SquirrelError(vm, "Couldn't add float value to table");
311 void store_bool(HSQUIRRELVM vm, const char* name, bool val)
313 sq_pushstring(vm, name, -1);
314 sq_pushbool(vm, val ? SQTrue : SQFalse);
315 if(SQ_FAILED(sq_createslot(vm, -3)))
316 throw scripting::SquirrelError(vm, "Couldn't add float value to table");
319 bool has_float(HSQUIRRELVM vm, const char* name)
321 sq_pushstring(vm, name, -1);
322 if (SQ_FAILED(sq_get(vm, -2))) return false;
327 bool has_int(HSQUIRRELVM vm, const char* name)
329 return has_float(vm, name);
332 bool has_string(HSQUIRRELVM vm, const char* name)
334 return has_float(vm, name);
337 bool has_bool(HSQUIRRELVM vm, const char* name)
339 return has_float(vm, name);
342 float read_float(HSQUIRRELVM vm, const char* name)
344 sq_pushstring(vm, name, -1);
345 if(SQ_FAILED(sq_get(vm, -2))) {
346 std::ostringstream msg;
347 msg << "Couldn't get float value for '" << name << "' from table";
348 throw scripting::SquirrelError(vm, msg.str());
352 if(SQ_FAILED(sq_getfloat(vm, -1, &result))) {
353 std::ostringstream msg;
354 msg << "Couldn't get float value for '" << name << "' from table";
355 throw scripting::SquirrelError(vm, msg.str());
362 int read_int(HSQUIRRELVM vm, const char* name)
364 sq_pushstring(vm, name, -1);
365 if(SQ_FAILED(sq_get(vm, -2))) {
366 std::ostringstream msg;
367 msg << "Couldn't get int value for '" << name << "' from table";
368 throw scripting::SquirrelError(vm, msg.str());
372 if(SQ_FAILED(sq_getinteger(vm, -1, &result))) {
373 std::ostringstream msg;
374 msg << "Couldn't get int value for '" << name << "' from table";
375 throw scripting::SquirrelError(vm, msg.str());
382 std::string read_string(HSQUIRRELVM vm, const char* name)
384 sq_pushstring(vm, name, -1);
385 if(SQ_FAILED(sq_get(vm, -2))) {
386 std::ostringstream msg;
387 msg << "Couldn't get string value for '" << name << "' from table";
388 throw scripting::SquirrelError(vm, msg.str());
392 if(SQ_FAILED(sq_getstring(vm, -1, &result))) {
393 std::ostringstream msg;
394 msg << "Couldn't get string value for '" << name << "' from table";
395 throw scripting::SquirrelError(vm, msg.str());
399 return std::string(result);
402 bool read_bool(HSQUIRRELVM vm, const char* name)
404 sq_pushstring(vm, name, -1);
405 if(SQ_FAILED(sq_get(vm, -2))) {
406 std::ostringstream msg;
407 msg << "Couldn't get bool value for '" << name << "' from table";
408 throw scripting::SquirrelError(vm, msg.str());
412 if(SQ_FAILED(sq_getbool(vm, -1, &result))) {
413 std::ostringstream msg;
414 msg << "Couldn't get bool value for '" << name << "' from table";
415 throw scripting::SquirrelError(vm, msg.str());
419 return result == SQTrue;
422 bool get_float(HSQUIRRELVM vm, const char* name, float& val) {
423 if (!has_float(vm, name)) return false;
424 val = read_float(vm, name);
428 bool get_int(HSQUIRRELVM vm, const char* name, int& val) {
429 if (!has_int(vm, name)) return false;
430 val = read_int(vm, name);
434 bool get_string(HSQUIRRELVM vm, const char* name, std::string& val) {
435 if (!has_string(vm, name)) return false;
436 val = read_string(vm, name);
440 bool get_bool(HSQUIRRELVM vm, const char* name, bool& val) {
441 if (!has_bool(vm, name)) return false;
442 val = read_bool(vm, name);
446 // end: serialization functions