Răsfoiți Sursa

Enhance the ffi and pack/unpack extensions

mingodad 9 ani în urmă
părinte
comite
78042a3069

+ 3 - 0
SquiLu-ext/sq_ffi.cpp

@@ -252,6 +252,9 @@ static SQInteger sq_func__call(HSQUIRRELVM v)
         case OT_STRING:
             sq_getstring(v, i, (const char**)&values[pi]);
             break;
+        case OT_USERDATA:
+            sq_getuserdata(v, i, (SQUserPointer*)&values[pi], NULL);
+            break;
         case OT_INSTANCE: {
             if (SQ_FAILED(sqstd_getblob(v, i, (SQUserPointer*)&values[pi])))
                 return SQ_ERROR;

+ 51 - 5
SquiLu-ext/sq_pack.cpp

@@ -15,7 +15,7 @@
 #define	OP_WSTRING	'P'		/* string preceded by length word */
 #define	OP_SSTRING	'a'		/* string preceded by length size_t */
 #define	OP_STRING	'A'		/* string */
-#define	OP_FLOAT		'f'		/* float */
+#define	OP_FLOAT	'f'		/* float */
 #define	OP_DOUBLE	'd'		/* double */
 #define	OP_CHAR		'c'		/* char */
 #define	OP_BYTE		'b'		/* byte = unsigned char */
@@ -103,7 +103,19 @@ static void doswap(int swap, void *p, size_t n)
 static SQRESULT sq_unpack(HSQUIRRELVM v) 		/** unpack(s,f,[init]) */
 {
 	SQ_FUNC_VARS(v);
-	SQ_GET_STRING(v, 2, s);
+	const SQChar *s;
+	SQInteger s_size;
+	SQObjectType ot = sq_gettype(v, 2);
+	switch(ot)
+	{
+    case OT_STRING: sq_getstr_and_size(v, 2, &s, &s_size); break;
+    case OT_USERDATA:
+        sq_getuserdata(v, 2, (SQUserPointer*)&s, NULL);
+        s_size = sq_getsize(v, 2);
+        break;
+    default:
+        return sq_throwerror(v, _SC("unexpected type %d for parameter 1"), ot);
+	}
 	SQ_GET_STRING(v, 3, f);
 	SQ_OPT_INTEGER(v,4, i, 0);
 	SQInteger n=0;
@@ -215,7 +227,7 @@ done:
 		break; \
 	}
 
-static SQRESULT sq_pack(HSQUIRRELVM v) 		/** pack(f,...) */
+static SQRESULT sq_pack_base(HSQUIRRELVM v, int toUserdata) 		/** pack(f,...) */
 {
 	SQ_FUNC_VARS_NO_TOP(v);
 	SQ_GET_STRING(v, 2, f);
@@ -268,7 +280,38 @@ static SQRESULT sq_pack(HSQUIRRELVM v) 		/** pack(f,...) */
 			break;
 		}
 	}
-	sq_pushstring(v, (SQChar*)b.GetBuf(), b.Len());
+	if(toUserdata)
+    {
+        SQUserPointer ptr = sq_newuserdata(v, b.Len());
+        memcpy(ptr, b.GetBuf(), b.Len());
+    }
+	else sq_pushstring(v, (SQChar*)b.GetBuf(), b.Len());
+	return 1;
+}
+
+static SQRESULT sq_pack(HSQUIRRELVM v) 		/** pack(f,...) */
+{
+    return sq_pack_base(v, 0);
+}
+
+static SQRESULT sq_pack_to_userdata(HSQUIRRELVM v) 		/** pack(f,...) */
+{
+    return sq_pack_base(v, 1);
+}
+
+static SQRESULT sq_pushmem(HSQUIRRELVM v) 		/** pushmem(size) */
+{
+	SQ_FUNC_VARS_NO_TOP(v);
+	SQ_GET_INTEGER(v, 2, mem_size);
+	sq_newuserdata(v, mem_size);
+	return 1;
+}
+
+static SQRESULT sq_getaddress(HSQUIRRELVM v) 		/** getaddress(udata) */
+{
+	SQUserPointer ptr = 0;
+	sq_getuserdata(v, -1, &ptr, NULL);
+	sq_pushinteger(v, (SQInteger)ptr);
 	return 1;
 }
 
@@ -276,7 +319,10 @@ static SQRESULT sq_pack(HSQUIRRELVM v) 		/** pack(f,...) */
 static SQRegFunction sq_pack_methods[] =
 {
     _DECL_FUNC(pack,-3,_SC(".s.")),
-    _DECL_FUNC(unpack,-3,_SC(".ssi")),
+    _DECL_FUNC(pack_to_userdata,-3,_SC(".s.")),
+    _DECL_FUNC(unpack,-3,_SC(".s|usi")),
+    _DECL_FUNC(pushmem,2,_SC(".i")),
+    _DECL_FUNC(getaddress,2,_SC(".u")),
     {0,0}
 };
 #undef _DECL_FUNC

+ 19 - 0
SquiLu/samples/ffi/ffi_os.nut

@@ -0,0 +1,19 @@
+local l = ffi.load("libc.so.6")
+
+local function _(r, f, p) {
+    this[f] <- l.bind_func(r, f, p)
+}
+
+_("i", "open", ["s", "i", "i"])
+_("i", "read", ["i", "P", "I"])
+_("i", "write", ["i", "P", "I"])
+_("i", "close", ["i"])
+_("i", "perror", ["s"])
+
+local errno = l.bind_var("i", "errno")
+
+function _errno() {
+    return errno.get()
+}
+
+return this;

+ 80 - 0
SquiLu/samples/ffi/ffi_snappy.nut

@@ -0,0 +1,80 @@
+auto bpack=sqpack.pack;
+auto bpack_to_userdata=sqpack.pack_to_userdata;
+auto bunpack=sqpack.unpack;
+auto bpushmem=sqpack.pushmem;
+auto bgetaddress=sqpack.getaddress;
+
+local libsnappy = ffi.load(".libs/libsnappy.so");
+
+enum snappy_status {
+  SNAPPY_OK = 0,
+  SNAPPY_INVALID_INPUT = 1,
+  SNAPPY_BUFFER_TOO_SMALL = 2
+};
+
+/*
+snappy_status snappy_compress(const char* input,
+                              size_t input_length,
+                              char* compressed,
+                              size_t* compressed_length);
+
+snappy_status snappy_uncompress(const char* compressed,
+                                size_t compressed_length,
+                                char* uncompressed,
+                                size_t* uncompressed_length);
+
+size_t snappy_max_compressed_length(size_t source_length);
+
+snappy_status snappy_uncompressed_length(const char* compressed,
+                                         size_t compressed_length,
+                                         size_t* result);
+
+snappy_status snappy_validate_compressed_buffer(const char* compressed,
+                                                size_t compressed_length);
+*/
+
+auto udata = bpushmem(1024);
+auto udata_address = bgetaddress(udata);
+print(udata, type(udata), udata_address);
+
+local snappy_compress_fptr = libsnappy.bind_func("i", "snappy_compress", ["s", "i", "s", "i"]);
+local snappy_uncompress_fptr = libsnappy.bind_func("i", "snappy_uncompress", ["s", "i", "s", "i"]);
+local snappy_max_compressed_length = libsnappy.bind_func("i", "snappy_max_compressed_length", ["i"]);
+local snappy_uncompressed_length = libsnappy.bind_func("i", "snappy_uncompressed_length", ["s", "i", "i"]);
+
+local function snappy_compress(str)
+{
+	auto slen = str.len();
+	auto smlen = snappy_max_compressed_length(slen);
+	auto compressed = bpushmem(smlen);
+	auto compressed_length = bpack_to_userdata("i", smlen);
+
+	auto status = snappy_compress_fptr(str, slen, compressed, bgetaddress(compressed_length));
+	
+	auto clen = bunpack(compressed_length, "i")[0];
+	auto cstr = bunpack(compressed, "A" + clen)[0];
+	print(status, compressed, smlen, clen, cstr.len());
+	return cstr;
+}
+
+local function snappy_uncompress(str)
+{
+	auto slen = str.len();
+	auto compressed_length = bpack_to_userdata("i", slen);
+	auto status = snappy_uncompressed_length(str, slen, bgetaddress(compressed_length));
+	auto clen = bunpack(compressed_length, "i")[0];
+	auto uncompressed = bpushmem(clen);
+
+	status = snappy_uncompress_fptr(str, slen, uncompressed, bgetaddress(compressed_length));
+	
+	clen = bunpack(compressed_length, "i")[0];
+	auto cstr = bunpack(uncompressed, "A" + clen)[0];
+	print(status, uncompressed, slen, clen, cstr.len());
+	return cstr;
+}
+
+auto str = readfile(vargv[0]);
+print(snappy_uncompress(snappy_compress(str)));
+
+local smlen = snappy_max_compressed_length(1200);
+print(smlen);

+ 58 - 0
SquiLu/samples/ffi/ffi_strlen.nut

@@ -0,0 +1,58 @@
+local l = ffi.load("libc.so.6")
+
+local strlen = l.bind_func("i", "strlen", ["s"]);
+local str = "Hello World !";
+
+print(str, str.len(), strlen(str));
+
+local function mystrlen(str)
+{
+    return str.len();
+} 
+
+local function mystrlen2(str)
+{
+    local result = 0;
+    for(local len=str.len(); result < len; ++result); 
+    return result;
+} 
+
+const MAX_COUNT = 5000000;
+
+local str_len = 0;
+local start_time = os.clock();
+
+for(local i=0; i < MAX_COUNT; ++i)
+{
+    str_len = str.len();
+}
+
+print(MAX_COUNT, str_len, os.clock() - start_time);
+
+start_time = os.clock();
+
+for(local i=0; i < MAX_COUNT; ++i)
+{
+    str_len = strlen(str);
+}
+
+print(MAX_COUNT, str_len, os.clock() - start_time);
+
+start_time = os.clock();
+
+for(local i=0; i < MAX_COUNT; ++i)
+{
+    str_len = mystrlen(str);
+}
+
+print(MAX_COUNT, str_len, os.clock() - start_time);
+
+start_time = os.clock();
+
+for(local i=0; i < MAX_COUNT; ++i)
+{
+    str_len = mystrlen2(str);
+}
+
+print(MAX_COUNT, str_len, os.clock() - start_time);
+

+ 0 - 0
SquiLu/samples/ffi/simple.cpp