* Small miniswig update to use less dependencies
[supertux.git] / src / scripting / squirrel_util.cpp
index 1ece08c..6437ae5 100644 (file)
@@ -31,6 +31,7 @@
 #include "log.hpp"
 #include "level.hpp"
 #include "physfs/physfs_stream.hpp"
+#include "random_generator.hpp"
 
 #ifdef ENABLE_SQDBG
 #include <sqdbg/sqrdbg.h>
@@ -65,7 +66,7 @@ void init_squirrel(bool enable_debugger)
     debugger = sq_rdbg_init(global_vm, 1234, SQFalse);
     if(debugger == NULL)
       throw SquirrelError(global_vm, "Couldn't initialize squirrel debugger");
-  
+
     sq_enabledebuginfo(global_vm, SQTrue);
     log_info << "Waiting for debug client..." << std::endl;
     if(SQ_FAILED(sq_rdbg_waitforconnections(debugger)))
@@ -75,18 +76,22 @@ void init_squirrel(bool enable_debugger)
   }
 
   sq_pushroottable(global_vm);
-  if(sqstd_register_bloblib(global_vm) < 0)
+  if(SQ_FAILED(sqstd_register_bloblib(global_vm)))
     throw SquirrelError(global_vm, "Couldn't register blob lib");
-  if(sqstd_register_mathlib(global_vm) < 0)
+  if(SQ_FAILED(sqstd_register_mathlib(global_vm)))
     throw SquirrelError(global_vm, "Couldn't register math lib");
-  if(sqstd_register_stringlib(global_vm) < 0)
+  if(SQ_FAILED(sqstd_register_stringlib(global_vm)))
     throw SquirrelError(global_vm, "Couldn't register string lib");
+
+  // remove rand and srand calls from sqstdmath, we'll provide our own
+  sq_pushstring(global_vm, "srand", -1);
+  sq_deleteslot(global_vm, -2, SQFalse);
+  sq_pushstring(global_vm, "rand", -1);
+  sq_deleteslot(global_vm, -2, SQFalse);
+
   // register supertux API
   register_supertux_wrapper(global_vm);
 
-  // TODO remove this at some point... it shoud just be functions not an object
-  expose_object(global_vm, -1, new Scripting::Level(), "Level", true);
-  
   sq_pop(global_vm, 1);
 
   // register print function
@@ -112,7 +117,10 @@ void exit_squirrel()
     debugger = NULL;
   }
 #endif
-  sq_close(global_vm);
+
+  if (global_vm)
+    sq_close(global_vm);
+
   global_vm = NULL;
 }
 
@@ -124,40 +132,40 @@ void update_debugger()
 #endif
 }
 
-std::string squirrel2string(HSQUIRRELVM v, int i)
+std::string squirrel2string(HSQUIRRELVM v, SQInteger i)
 {
   std::ostringstream os;
   switch(sq_gettype(v, i))
     {
     case OT_NULL:
-      os << "<null>";        
+      os << "<null>";
       break;
     case OT_BOOL: {
       SQBool p;
       sq_getbool(v, i, &p);
-      if (p) 
+      if (p)
         os << "true";
       else
         os << "false";
       break;
     }
     case OT_INTEGER: {
-      int val;
+      SQInteger val;
       sq_getinteger(v, i, &val);
       os << val;
       break;
     }
     case OT_FLOAT: {
-      float val;
+      SQFloat val;
       sq_getfloat(v, i, &val);
       os << val;
       break;
     }
     case OT_STRING: {
-      const char* val;
+      const SQChar* val;
       sq_getstring(v, i, &val);
       os << "\"" << val << "\"";
-      break;    
+      break;
     }
     case OT_TABLE: {
       bool first = true;
@@ -171,9 +179,9 @@ std::string squirrel2string(HSQUIRRELVM v, int i)
           first = false;
 
           //here -1 is the value and -2 is the key
-          os << squirrel2string(v, -2) << " => " 
+          os << squirrel2string(v, -2) << " => "
              << squirrel2string(v, -1);
-                              
+
           sq_pop(v,2); //pops key and val before the nex iteration
         }
       sq_pop(v, 1);
@@ -194,7 +202,7 @@ std::string squirrel2string(HSQUIRRELVM v, int i)
           //here -1 is the value and -2 is the key
           // we ignore the key, since that is just the index in an array
           os << squirrel2string(v, -1);
-                              
+
           sq_pop(v,2); //pops key and val before the nex iteration
         }
       sq_pop(v, 1);
@@ -204,7 +212,7 @@ std::string squirrel2string(HSQUIRRELVM v, int i)
     case OT_USERDATA:
       os << "<userdata>";
       break;
-    case OT_CLOSURE:        
+    case OT_CLOSURE:
       os << "<closure>";
       break;
     case OT_NATIVECLOSURE:
@@ -244,25 +252,25 @@ void print_squirrel_stack(HSQUIRRELVM v)
         switch(sq_gettype(v, i))
         {
             case OT_NULL:
-                printf("null");        
+                printf("null");
                 break;
             case OT_INTEGER: {
-                int val;
+                SQInteger val;
                 sq_getinteger(v, i, &val);
-                printf("integer (%d)", val);
+                printf("integer (%d)", static_cast<int> (val));
                 break;
             }
             case OT_FLOAT: {
-                float val;
+                SQFloat val;
                 sq_getfloat(v, i, &val);
                 printf("float (%f)", val);
                 break;
             }
             case OT_STRING: {
-                const char* val;
+                const SQChar* val;
                 sq_getstring(v, i, &val);
                 printf("string (%s)", val);
-                break;    
+                break;
             }
             case OT_TABLE:
                 printf("table");
@@ -273,8 +281,8 @@ void print_squirrel_stack(HSQUIRRELVM v)
             case OT_USERDATA:
                 printf("userdata");
                 break;
-            case OT_CLOSURE:        
-                printf("closure(function)");    
+            case OT_CLOSURE:
+                printf("closure(function)");
                 break;
             case OT_NATIVECLOSURE:
                 printf("native closure(C function)");
@@ -318,15 +326,15 @@ static SQInteger squirrel_read_char(SQUserPointer file)
 void compile_script(HSQUIRRELVM vm, std::istream& in, const std::string& sourcename)
 {
   if(SQ_FAILED(sq_compile(vm, squirrel_read_char, &in, sourcename.c_str(), true)))
-    throw SquirrelError(vm, "Couldn't parse script");  
+    throw SquirrelError(vm, "Couldn't parse script");
 }
 
 void compile_and_run(HSQUIRRELVM vm, std::istream& in,
                      const std::string& sourcename)
 {
   compile_script(vm, in, sourcename);
-  
-  int oldtop = sq_gettop(vm);
+
+  SQInteger oldtop = sq_gettop(vm);
 
   try {
     sq_pushroottable(vm);
@@ -354,7 +362,7 @@ HSQOBJECT create_thread(HSQUIRRELVM vm)
   if(SQ_FAILED(sq_getstackobj(vm, -1, &vm_object)))
     throw SquirrelError(vm, "Couldn't get squirrel thread from stack");
   sq_addref(vm, &vm_object);
-  
+
   sq_pop(vm, 1);
 
   return vm_object;
@@ -378,4 +386,168 @@ HSQUIRRELVM object_to_vm(HSQOBJECT object)
   return object._unVal.pThread;
 }
 
+// begin: serialization functions
+
+void store_float(HSQUIRRELVM vm, const char* name, float val)
+{
+  sq_pushstring(vm, name, -1);
+  sq_pushfloat(vm, val);
+  if(SQ_FAILED(sq_createslot(vm, -3)))
+    throw Scripting::SquirrelError(vm, "Couldn't add float value to table");
+}
+
+void store_int(HSQUIRRELVM vm, const char* name, int val)
+{
+  sq_pushstring(vm, name, -1);
+  sq_pushinteger(vm, val);
+  if(SQ_FAILED(sq_createslot(vm, -3)))
+    throw Scripting::SquirrelError(vm, "Couldn't add int value to table");
+}
+
+void store_string(HSQUIRRELVM vm, const char* name, const std::string& val)
+{
+  sq_pushstring(vm, name, -1);
+  sq_pushstring(vm, val.c_str(), val.length());
+  if(SQ_FAILED(sq_createslot(vm, -3)))
+    throw Scripting::SquirrelError(vm, "Couldn't add float value to table");
+}
+
+void store_bool(HSQUIRRELVM vm, const char* name, bool val)
+{
+  sq_pushstring(vm, name, -1);
+  sq_pushbool(vm, val ? SQTrue : SQFalse);
+  if(SQ_FAILED(sq_createslot(vm, -3)))
+    throw Scripting::SquirrelError(vm, "Couldn't add float value to table");
+}
+
+bool has_float(HSQUIRRELVM vm, const char* name)
+{
+  sq_pushstring(vm, name, -1);
+  if (SQ_FAILED(sq_get(vm, -2))) return false;
+  sq_pop(vm, 1);
+  return true;
+}
+
+bool has_int(HSQUIRRELVM vm, const char* name)
+{
+  return has_float(vm, name);
+}
+
+bool has_string(HSQUIRRELVM vm, const char* name)
+{
+  return has_float(vm, name);
+}
+
+bool has_bool(HSQUIRRELVM vm, const char* name)
+{
+  return has_float(vm, name);
+}
+
+float read_float(HSQUIRRELVM vm, const char* name)
+{
+  sq_pushstring(vm, name, -1);
+  if(SQ_FAILED(sq_get(vm, -2))) {
+    std::ostringstream msg;
+    msg << "Couldn't get float value for '" << name << "' from table";
+    throw Scripting::SquirrelError(vm, msg.str());
+  }
+
+  float result;
+  if(SQ_FAILED(sq_getfloat(vm, -1, &result))) {
+    std::ostringstream msg;
+    msg << "Couldn't get float value for '" << name << "' from table";
+    throw Scripting::SquirrelError(vm, msg.str());
+  }
+  sq_pop(vm, 1);
+
+  return result;
+}
+
+int read_int(HSQUIRRELVM vm, const char* name)
+{
+  sq_pushstring(vm, name, -1);
+  if(SQ_FAILED(sq_get(vm, -2))) {
+    std::ostringstream msg;
+    msg << "Couldn't get int value for '" << name << "' from table";
+    throw Scripting::SquirrelError(vm, msg.str());
+  }
+
+  SQInteger result;
+  if(SQ_FAILED(sq_getinteger(vm, -1, &result))) {
+    std::ostringstream msg;
+    msg << "Couldn't get int value for '" << name << "' from table";
+    throw Scripting::SquirrelError(vm, msg.str());
+  }
+  sq_pop(vm, 1);
+
+  return result;
+}
+
+
+std::string read_string(HSQUIRRELVM vm, const char* name)
+{
+  sq_pushstring(vm, name, -1);
+  if(SQ_FAILED(sq_get(vm, -2))) {
+    std::ostringstream msg;
+    msg << "Couldn't get string value for '" << name << "' from table";
+    throw Scripting::SquirrelError(vm, msg.str());
+  }
+
+  const char* result;
+  if(SQ_FAILED(sq_getstring(vm, -1, &result))) {
+    std::ostringstream msg;
+    msg << "Couldn't get string value for '" << name << "' from table";
+    throw Scripting::SquirrelError(vm, msg.str());
+  }
+  sq_pop(vm, 1);
+
+  return std::string(result);
+}
+
+bool read_bool(HSQUIRRELVM vm, const char* name)
+{
+  sq_pushstring(vm, name, -1);
+  if(SQ_FAILED(sq_get(vm, -2))) {
+    std::ostringstream msg;
+    msg << "Couldn't get bool value for '" << name << "' from table";
+    throw Scripting::SquirrelError(vm, msg.str());
+  }
+
+  SQBool result;
+  if(SQ_FAILED(sq_getbool(vm, -1, &result))) {
+    std::ostringstream msg;
+    msg << "Couldn't get bool value for '" << name << "' from table";
+    throw Scripting::SquirrelError(vm, msg.str());
+  }
+  sq_pop(vm, 1);
+
+  return result == SQTrue;
+}
+
+bool get_float(HSQUIRRELVM vm, const char* name, float& val) {
+  if (!has_float(vm, name)) return false;
+  val = read_float(vm, name);
+  return true;
+}
+
+bool get_int(HSQUIRRELVM vm, const char* name, int& val) {
+  if (!has_int(vm, name)) return false;
+  val = read_int(vm, name);
+  return true;
+}
+
+bool get_string(HSQUIRRELVM vm, const char* name, std::string& val) {
+  if (!has_string(vm, name)) return false;
+  val = read_string(vm, name);
+  return true;
+}
+
+bool get_bool(HSQUIRRELVM vm, const char* name, bool& val) {
+  if (!has_bool(vm, name)) return false;
+  val = read_bool(vm, name);
+  return true;
+}
+
+// end: serialization functions
+
 }