Browse Source

Add "popen" global io similar to the Lua implementation

mingodad 9 years ago
parent
commit
f6344a22be

+ 17 - 0
SquiLu/samples/test-popen.nut

@@ -0,0 +1,17 @@
+//local fd = assert(popen("/bin/ls -la", "r"));
+local fd = popen("/bin/ls -la", "r");
+local output = "";
+local read_n = 1024;
+local read_buf;
+do
+{
+	read_buf = fd.read(read_n);
+	output += read_buf;
+} while(read_buf.len() == read_n);
+print("pclose", fd.close());
+print(output) // Prints the output of the command.
+
+fd = popen("/bin/ls -la", "r");
+output = fd.read_all();
+print("pclose", fd.close());
+print(output) // Prints the output of the command.

+ 455 - 439
SquiLu/sqstdlib/sqstdblob.cpp

@@ -1,39 +1,39 @@
-/* see copyright notice in squirrel.h */
-#include <new>
-#include <squirrel.h>
-#include <sqstdio.h>
-#include <string.h>
-#include <sqstdblob.h>
-#include "sqstdstream.h"
-#include "sqstdblobimpl.h"
-
+/* see copyright notice in squirrel.h */
+#include <new>
+#include <squirrel.h>
+#include <sqstdio.h>
+#include <string.h>
+#include <sqstdblob.h>
+#include "sqstdstream.h"
+#include "sqstdblobimpl.h"
+
 //#define SQSTD_BLOB_TYPE_TAG (SQSTD_STREAM_TYPE_TAG | 0x00000002)
-static const SQChar  SQSTD_BLOB_TYPE_TAG[] = _SC("std_stream_blob");
-
-
+static const SQChar  SQSTD_BLOB_TYPE_TAG[] = _SC("std_stream_blob");
+
+
 //Blob
-
-
-SQUserPointer SQBlob::SQBlob_TAG = (SQUserPointer)SQSTD_BLOB_TYPE_TAG;
-
-SQBlob::SQBlob(SQInteger size, SQInteger allocated) {
-    _size = size;
-    _allocated = allocated > size ? allocated : size;
-    _buf = (unsigned char *)sq_malloc(_allocated);
-    memset(_buf, 0, _allocated);
-    _ptr = 0;
-    _owns = true;
-}
-SQBlob::~SQBlob() {
-    if(_buf) sq_free(_buf, _allocated);
-}
-SQInteger SQBlob::Write(const void *buffer, SQInteger size) {
-    if(!CanAdvance(size)) {
-        GrowBufOf(_ptr + size - _size);
-    }
-    memcpy(&_buf[_ptr], buffer, size);
-    _ptr += size;
-    return size;
+
+
+SQUserPointer SQBlob::SQBlob_TAG = (SQUserPointer)SQSTD_BLOB_TYPE_TAG;
+
+SQBlob::SQBlob(SQInteger size, SQInteger allocated) {
+    _size = size;
+    _allocated = allocated > size ? allocated : size;
+    _buf = (unsigned char *)sq_malloc(_allocated);
+    memset(_buf, 0, _allocated);
+    _ptr = 0;
+    _owns = true;
+}
+SQBlob::~SQBlob() {
+    if(_buf) sq_free(_buf, _allocated);
+}
+SQInteger SQBlob::Write(const void *buffer, SQInteger size) {
+    if(!CanAdvance(size)) {
+        GrowBufOf(_ptr + size - _size);
+    }
+    memcpy(&_buf[_ptr], buffer, size);
+    _ptr += size;
+    return size;
 }
 SQInteger SQBlob::WriteZstr(const char *zStr) {
     if(zStr) //do not try to strlen(NULL)
@@ -42,27 +42,27 @@ SQInteger SQBlob::WriteZstr(const char *zStr) {
         return Write(zStr, size);
     }
     return 0;
-}
+}
 SQInteger SQBlob::WriteChar(const char c) {
-    return Write(&c, 1);
-}
-SQInteger SQBlob::Read(void *buffer,SQInteger size) {
-    SQInteger n = size;
-    if(!CanAdvance(size)) {
-        if((_size - _ptr) > 0)
-            n = _size - _ptr;
-        else return 0;
-    }
-    memcpy(buffer, &_buf[_ptr], n);
-    _ptr += n;
-    return n;
-}
-SQInteger SQBlob::Gets(char *buffer,SQInteger size) {
-    SQInteger n = size;
-    if(!CanAdvance(size)) {
-        if((_size - _ptr) > 0)
-            n = _size - _ptr;
-        else return 0;
+    return Write(&c, 1);
+}
+SQInteger SQBlob::Read(void *buffer,SQInteger size) {
+    SQInteger n = size;
+    if(!CanAdvance(size)) {
+        if((_size - _ptr) > 0)
+            n = _size - _ptr;
+        else return 0;
+    }
+    memcpy(buffer, &_buf[_ptr], n);
+    _ptr += n;
+    return n;
+}
+SQInteger SQBlob::Gets(char *buffer,SQInteger size) {
+    SQInteger n = size;
+    if(!CanAdvance(size)) {
+        if((_size - _ptr) > 0)
+            n = _size - _ptr;
+        else return 0;
     }
     SQInteger i=0;
     for(; i < n; ++i)
@@ -70,414 +70,430 @@ SQInteger SQBlob::Gets(char *buffer,SQInteger size) {
         char c = _buf[_ptr+i];
         buffer[i] = c;
         if(c == '\n') break;
-    }
-    _ptr += i;
-    return i;
-}
-bool SQBlob::Resize(SQInteger n) {
-    if(!_owns) return false;
-    if(n != _allocated) {
-        unsigned char *newbuf = (unsigned char *)sq_malloc(n);
-        memset(newbuf,0,n);
-        if(_size > n)
-            memcpy(newbuf,_buf,n);
-        else
-            memcpy(newbuf,_buf,_size);
-        sq_free(_buf,_allocated);
-        _buf=newbuf;
-        _allocated = n;
-        if(_size > _allocated)
-            _size = _allocated;
-        if(_ptr > _size)
-            _ptr = _size;
-    }
-    return true;
-}
-bool SQBlob::GrowBufOf(SQInteger n)
-{
-    bool ret = true;
-    if(_size + n > _allocated) {
-        if(_size + n > _size * 2)
-            ret = Resize(_size + n);
-        else
-            ret = Resize(_size * 2);
-    }
-    _size = _size + n;
-    return ret;
-}
-SQInteger SQBlob::Seek(SQInteger offset, SQInteger origin) {
-    switch(origin) {
-        case SQ_SEEK_SET:
-            if(offset > _size || offset < 0) return -1;
-            _ptr = offset;
-            break;
-        case SQ_SEEK_CUR:
-            if(_ptr + offset > _size || _ptr + offset < 0) return -1;
-            _ptr += offset;
-            break;
-        case SQ_SEEK_END:
-            if(_size + offset > _size || _size + offset < 0) return -1;
-            _ptr = _size + offset;
-            break;
-        default: return -1;
-    }
-    return 0;
+    }
+    _ptr += i;
+    return i;
+}
+bool SQBlob::Resize(SQInteger n) {
+    if(!_owns) return false;
+    if(n != _allocated) {
+        unsigned char *newbuf = (unsigned char *)sq_malloc(n);
+        memset(newbuf,0,n);
+        if(_size > n)
+            memcpy(newbuf,_buf,n);
+        else
+            memcpy(newbuf,_buf,_size);
+        sq_free(_buf,_allocated);
+        _buf=newbuf;
+        _allocated = n;
+        if(_size > _allocated)
+            _size = _allocated;
+        if(_ptr > _size)
+            _ptr = _size;
+    }
+    return true;
+}
+bool SQBlob::Reserve(SQInteger n)
+{
+    bool ret = true;
+    if(_size + n > _allocated) {
+        if(_size + n > _size * 2)
+            ret = Resize(_size + n);
+        else
+            ret = Resize(_size * 2);
+    }
+    return ret;
+}
+bool SQBlob::GrowBufOf(SQInteger n)
+{
+    bool ret = Reserve(n);
+    _size = _size + n;
+    return ret;
+}
+SQInteger SQBlob::Seek(SQInteger offset, SQInteger origin) {
+    switch(origin) {
+        case SQ_SEEK_SET:
+            if(offset > _size || offset < 0) return -1;
+            _ptr = offset;
+            break;
+        case SQ_SEEK_CUR:
+            if(_ptr + offset > _size || _ptr + offset < 0) return -1;
+            _ptr += offset;
+            break;
+        case SQ_SEEK_END:
+            if(_size + offset > _size || _size + offset < 0) return -1;
+            _ptr = _size + offset;
+            break;
+        default: return -1;
+    }
+    return 0;
 }
 
 bool SQBlob::SetLen(SQInteger len){
     if(len <= _allocated || Resize(len)){
         _size = len;
-        if(_ptr > _size)
-            _ptr = _size;
+        if(_ptr > _size)
+            _ptr = _size;
         return true;
-    }
-    return false;
-}
-
-#define SETUP_BLOB(v) \
-	SQBlob *self = NULL; \
-	{ if(SQ_FAILED(sq_getinstanceup(v,1,(SQUserPointer*)&self,(SQUserPointer)SQSTD_BLOB_TYPE_TAG))) \
-		return sq_throwerror(v,_SC("invalid type tag"));  } \
-	if(!self || !self->IsValid())  \
-		return sq_throwerror(v,_SC("the blob is invalid"));
-
-
-static SQRESULT _blob_resize(HSQUIRRELVM v)
-{
-	SETUP_BLOB(v);
-	SQInteger size;
-	sq_getinteger(v,2,&size);
-	if(!self->Resize(size))
-		return sq_throwerror(v,_SC("resize failed"));
-	return 0;
-}
-
-static SQRESULT _blob_reserve(HSQUIRRELVM v)
-{
-	SETUP_BLOB(v);
-	SQInteger size;
-	sq_getinteger(v,2,&size);
-	if(!self->GrowBufOf(size))
-		return sq_throwerror(v,_SC("reserve failed"));
-	return 0;
-}
-
-static void __swap_dword(unsigned int *n)
-{
-	*n=(unsigned int)(((*n&0xFF000000)>>24)  |
-			((*n&0x00FF0000)>>8)  |
-			((*n&0x0000FF00)<<8)  |
-			((*n&0x000000FF)<<24));
-}
-
-static void __swap_word(unsigned short *n)
-{
-	*n=(unsigned short)((*n>>8)&0x00FF)| ((*n<<8)&0xFF00);
-}
-
-static SQRESULT _blob_swap4(HSQUIRRELVM v)
-{
-	SETUP_BLOB(v);
-	SQInteger num=(self->Len()-(self->Len()%4))>>2;
-	unsigned int *t=(unsigned int *)self->GetBuf();
-	for(SQInteger i = 0; i < num; i++) {
-		__swap_dword(&t[i]);
-	}
-	return 0;
-}
-
-static SQRESULT _blob_swap2(HSQUIRRELVM v)
-{
-	SETUP_BLOB(v);
-	SQInteger num=(self->Len()-(self->Len()%2))>>1;
-	unsigned short *t = (unsigned short *)self->GetBuf();
-	for(SQInteger i = 0; i < num; i++) {
-		__swap_word(&t[i]);
-	}
-	return 0;
-}
-
-static SQRESULT _blob_memset(HSQUIRRELVM v)
-{
-    SQ_FUNC_VARS_NO_TOP(v);
+    }
+    return false;
+}
+
+#define SETUP_BLOB(v) \
+	SQBlob *self = NULL; \
+	{ if(SQ_FAILED(sq_getinstanceup(v,1,(SQUserPointer*)&self,(SQUserPointer)SQSTD_BLOB_TYPE_TAG))) \
+		return sq_throwerror(v,_SC("invalid type tag"));  } \
+	if(!self || !self->IsValid())  \
+		return sq_throwerror(v,_SC("the blob is invalid"));
+
+
+static SQRESULT _blob_resize(HSQUIRRELVM v)
+{
+	SETUP_BLOB(v);
+	SQInteger size;
+	sq_getinteger(v,2,&size);
+	if(!self->Resize(size))
+		return sq_throwerror(v,_SC("resize failed"));
+	return 0;
+}
+
+static SQRESULT _blob_grow(HSQUIRRELVM v)
+{
 	SETUP_BLOB(v);
-	SQ_GET_INTEGER(v, 2, idx);
-	SQ_GET_INTEGER(v, 3, val);
-	SQ_GET_INTEGER(v, 4, size);
-	if(idx < 0 || idx >= self->Len())
-		return sq_throwerror(v,_SC("index out of range"));
-	if(idx+size < 0 || idx+size >= self->Len())
+	SQInteger size;
+	sq_getinteger(v,2,&size);
+	if(!self->GrowBufOf(size))
+		return sq_throwerror(v,_SC("reserve failed"));
+	return 0;
+}
+
+static SQRESULT _blob_reserve(HSQUIRRELVM v)
+{
+	SETUP_BLOB(v);
+	SQInteger size;
+	sq_getinteger(v,2,&size);
+	if(!self->Reserve(size))
+		return sq_throwerror(v,_SC("reserve failed"));
+	return 0;
+}
+
+static void __swap_dword(unsigned int *n)
+{
+	*n=(unsigned int)(((*n&0xFF000000)>>24)  |
+			((*n&0x00FF0000)>>8)  |
+			((*n&0x0000FF00)<<8)  |
+			((*n&0x000000FF)<<24));
+}
+
+static void __swap_word(unsigned short *n)
+{
+	*n=(unsigned short)((*n>>8)&0x00FF)| ((*n<<8)&0xFF00);
+}
+
+static SQRESULT _blob_swap4(HSQUIRRELVM v)
+{
+	SETUP_BLOB(v);
+	SQInteger num=(self->Len()-(self->Len()%4))>>2;
+	unsigned int *t=(unsigned int *)self->GetBuf();
+	for(SQInteger i = 0; i < num; i++) {
+		__swap_dword(&t[i]);
+	}
+	return 0;
+}
+
+static SQRESULT _blob_swap2(HSQUIRRELVM v)
+{
+	SETUP_BLOB(v);
+	SQInteger num=(self->Len()-(self->Len()%2))>>1;
+	unsigned short *t = (unsigned short *)self->GetBuf();
+	for(SQInteger i = 0; i < num; i++) {
+		__swap_word(&t[i]);
+	}
+	return 0;
+}
+
+static SQRESULT _blob_memset(HSQUIRRELVM v)
+{
+    SQ_FUNC_VARS_NO_TOP(v);
+	SETUP_BLOB(v);
+	SQ_GET_INTEGER(v, 2, idx);
+	SQ_GET_INTEGER(v, 3, val);
+	SQ_GET_INTEGER(v, 4, size);
+	if(idx < 0 || idx >= self->Len())
+		return sq_throwerror(v,_SC("index out of range"));
+	if(idx+size < 0 || idx+size >= self->Len())
 		return sq_throwerror(v,_SC("index+size out of range"));
-    memset(((unsigned char*)self->GetBuf())+idx, val, size);
-	return 0;
-}
-
-static SQRESULT _blob__set(HSQUIRRELVM v)
-{
-	SETUP_BLOB(v);
-	SQInteger idx,val;
-	sq_getinteger(v,2,&idx);
-	sq_getinteger(v,3,&val);
-	if(idx < 0 || idx >= self->Len())
-		return sq_throwerror(v,_SC("index out of range"));
-	((unsigned char *)self->GetBuf())[idx] = (unsigned char) val;
-	sq_push(v,3);
-	return 1;
-}
-
-static SQRESULT _blob__get(HSQUIRRELVM v)
-{
-	SETUP_BLOB(v);
+    memset(((unsigned char*)self->GetBuf())+idx, val, size);
+	return 0;
+}
+
+static SQRESULT _blob__set(HSQUIRRELVM v)
+{
+	SETUP_BLOB(v);
+	SQInteger idx,val;
+	sq_getinteger(v,2,&idx);
+	sq_getinteger(v,3,&val);
+	if(idx < 0 || idx >= self->Len())
+		return sq_throwerror(v,_SC("index out of range"));
+	((unsigned char *)self->GetBuf())[idx] = (unsigned char) val;
+	sq_push(v,3);
+	return 1;
+}
+
+static SQRESULT _blob__get(HSQUIRRELVM v)
+{
+	SETUP_BLOB(v);
 	SQInteger idx;
 	SQObjectType ptype = sq_gettype(v, 2);
 	if( !(ptype & SQOBJECT_NUMERIC) ){
 	    //allow call metatable methods indexed by strings
 	    sq_reseterror(v);
 	    return SQ_ERROR;
-	}
-	sq_getinteger(v,2,&idx);
-	if(idx < 0 || idx >= self->Len())
-		return sq_throwerror(v,_SC("index out of range"));
-	sq_pushinteger(v,((unsigned char *)self->GetBuf())[idx]);
-	return 1;
-}
-
-static SQRESULT _blob__nexti(HSQUIRRELVM v)
-{
-	SETUP_BLOB(v);
-	if(sq_gettype(v,2) == OT_NULL) {
-		sq_pushinteger(v, 0);
-		return 1;
-	}
-	SQInteger idx;
-	if(SQ_SUCCEEDED(sq_getinteger(v, 2, &idx))) {
-		if(idx+1 < self->Len()) {
-			sq_pushinteger(v, idx+1);
-			return 1;
-		}
-		sq_pushnull(v);
-		return 1;
-	}
-	return sq_throwerror(v,_SC("internal error (_nexti) wrong argument type"));
-}
-
-static SQRESULT _blob__typeof(HSQUIRRELVM v)
-{
-	sq_pushstring(v,_SC("blob"),-1);
-	return 1;
-}
-
-static SQRESULT _blob_releasehook(SQUserPointer p, SQInteger /*size*/, void */*ep*/)
-{
-	SQBlob *self = (SQBlob*)p;
-	self->~SQBlob();
-	sq_free(self,sizeof(SQBlob));
-	return 1;
-}
-
-static SQRESULT _blob_constructor(HSQUIRRELVM v)
-{
-	SQInteger nparam = sq_gettop(v);
-	SQInteger size = 0, allocate = 0;
-	if(nparam >= 2) {
-		sq_getinteger(v, 2, &size);
-	}
-	if(nparam >= 3) {
-		sq_getinteger(v, 2, &allocate);
-	}
-	if(size < 0) return sq_throwerror(v, _SC("cannot create blob with negative size"));
-	if(allocate < 0) return sq_throwerror(v, _SC("cannot create blob with negative allocate"));
-	//SQBlob *b = new SQBlob(size);
-
-	SQBlob *b = new (sq_malloc(sizeof(SQBlob)))SQBlob(size, allocate);
-	if(SQ_FAILED(sq_setinstanceup(v,1,b))) {
-		b->~SQBlob();
-		sq_free(b,sizeof(SQBlob));
-		return sq_throwerror(v, _SC("cannot create blob"));
-	}
-	sq_setreleasehook(v,1,_blob_releasehook);
-	return 0;
-}
-
-static SQRESULT _blob__cloned(HSQUIRRELVM v)
-{
-	SQBlob *other = NULL;
-	{
-		if(SQ_FAILED(sq_getinstanceup(v,2,(SQUserPointer*)&other,(SQUserPointer)SQSTD_BLOB_TYPE_TAG)))
-			return SQ_ERROR;
-	}
-	//SQBlob *thisone = new SQBlob(other->Len());
-	SQBlob *thisone = new (sq_malloc(sizeof(SQBlob)))SQBlob(other->Len());
-	memcpy(thisone->GetBuf(),other->GetBuf(),thisone->Len());
-	if(SQ_FAILED(sq_setinstanceup(v,1,thisone))) {
-		thisone->~SQBlob();
-		sq_free(thisone,sizeof(SQBlob));
-		return sq_throwerror(v, _SC("cannot clone blob"));
-	}
-	sq_setreleasehook(v,1,_blob_releasehook);
-	return 0;
-}
-
-static SQRESULT _blob__tostring(HSQUIRRELVM v)
-{
-    SETUP_BLOB(v);
-	sq_pushstring(v, (const SQChar*)self->GetBuf(), self->Len());
-	return 1;
-}
-
-static SQRESULT _blob_tostring(HSQUIRRELVM v)
-{
-    return _blob__tostring(v);
-}
-
-static SQRESULT _blob_setLen(HSQUIRRELVM v)
+	}
+	sq_getinteger(v,2,&idx);
+	if(idx < 0 || idx >= self->Len())
+		return sq_throwerror(v,_SC("index out of range"));
+	sq_pushinteger(v,((unsigned char *)self->GetBuf())[idx]);
+	return 1;
+}
+
+static SQRESULT _blob__nexti(HSQUIRRELVM v)
+{
+	SETUP_BLOB(v);
+	if(sq_gettype(v,2) == OT_NULL) {
+		sq_pushinteger(v, 0);
+		return 1;
+	}
+	SQInteger idx;
+	if(SQ_SUCCEEDED(sq_getinteger(v, 2, &idx))) {
+		if(idx+1 < self->Len()) {
+			sq_pushinteger(v, idx+1);
+			return 1;
+		}
+		sq_pushnull(v);
+		return 1;
+	}
+	return sq_throwerror(v,_SC("internal error (_nexti) wrong argument type"));
+}
+
+static SQRESULT _blob__typeof(HSQUIRRELVM v)
+{
+	sq_pushstring(v,_SC("blob"),-1);
+	return 1;
+}
+
+static SQRESULT _blob_releasehook(SQUserPointer p, SQInteger /*size*/, void */*ep*/)
+{
+	SQBlob *self = (SQBlob*)p;
+	self->~SQBlob();
+	sq_free(self,sizeof(SQBlob));
+	return 1;
+}
+
+static SQRESULT _blob_constructor(HSQUIRRELVM v)
+{
+	SQInteger nparam = sq_gettop(v);
+	SQInteger size = 0, allocate = 0;
+	if(nparam >= 2) {
+		sq_getinteger(v, 2, &size);
+	}
+	if(nparam >= 3) {
+		sq_getinteger(v, 2, &allocate);
+	}
+	if(size < 0) return sq_throwerror(v, _SC("cannot create blob with negative size"));
+	if(allocate < 0) return sq_throwerror(v, _SC("cannot create blob with negative allocate"));
+	//SQBlob *b = new SQBlob(size);
+
+	SQBlob *b = new (sq_malloc(sizeof(SQBlob)))SQBlob(size, allocate);
+	if(SQ_FAILED(sq_setinstanceup(v,1,b))) {
+		b->~SQBlob();
+		sq_free(b,sizeof(SQBlob));
+		return sq_throwerror(v, _SC("cannot create blob"));
+	}
+	sq_setreleasehook(v,1,_blob_releasehook);
+	return 0;
+}
+
+static SQRESULT _blob__cloned(HSQUIRRELVM v)
+{
+	SQBlob *other = NULL;
+	{
+		if(SQ_FAILED(sq_getinstanceup(v,2,(SQUserPointer*)&other,(SQUserPointer)SQSTD_BLOB_TYPE_TAG)))
+			return SQ_ERROR;
+	}
+	//SQBlob *thisone = new SQBlob(other->Len());
+	SQBlob *thisone = new (sq_malloc(sizeof(SQBlob)))SQBlob(other->Len());
+	memcpy(thisone->GetBuf(),other->GetBuf(),thisone->Len());
+	if(SQ_FAILED(sq_setinstanceup(v,1,thisone))) {
+		thisone->~SQBlob();
+		sq_free(thisone,sizeof(SQBlob));
+		return sq_throwerror(v, _SC("cannot clone blob"));
+	}
+	sq_setreleasehook(v,1,_blob_releasehook);
+	return 0;
+}
+
+static SQRESULT _blob__tostring(HSQUIRRELVM v)
+{
+    SETUP_BLOB(v);
+	sq_pushstring(v, (const SQChar*)self->GetBuf(), self->Len());
+	return 1;
+}
+
+static SQRESULT _blob_tostring(HSQUIRRELVM v)
+{
+    return _blob__tostring(v);
+}
+
+static SQRESULT _blob_setLen(HSQUIRRELVM v)
 {
     SQ_FUNC_VARS_NO_TOP(v);
     SETUP_BLOB(v);
     SQ_GET_INTEGER(v, 2, newLen);
     self->SetLen(newLen);
     return 0;
-}
+}
 
-static SQRESULT _blob_clear(HSQUIRRELVM v)
+static SQRESULT _blob_clear(HSQUIRRELVM v)
 {
     SETUP_BLOB(v);
     self->SetLen(0);
     return 0;
-}
-
-#define _DECL_BLOB_FUNC(name,nparams,typecheck) {_SC(#name),_blob_##name,nparams,typecheck}
-static SQRegFunction _blob_methods[] = {
-	_DECL_BLOB_FUNC(constructor,-1,_SC("xnn")),
-	_DECL_BLOB_FUNC(resize,2,_SC("xn")),
-	_DECL_BLOB_FUNC(reserve,2,_SC("xn")),
-	_DECL_BLOB_FUNC(swap2,1,_SC("x")),
-	_DECL_BLOB_FUNC(swap4,1,_SC("x")),
-	_DECL_BLOB_FUNC(memset,4,_SC("xiii")),
-	_DECL_BLOB_FUNC(_set,3,_SC("xnn")),
-	_DECL_BLOB_FUNC(_get,2,_SC("x n|s")), //allow call metatable methods indexed by strings
-	_DECL_BLOB_FUNC(_typeof,1,_SC("x")),
-	_DECL_BLOB_FUNC(_nexti,2,_SC("x")),
-	_DECL_BLOB_FUNC(_cloned,2,_SC("xx")),
-	//_DECL_BLOB_FUNC(_tostring,1,_SC("x")),
-	_DECL_BLOB_FUNC(tostring,1,_SC("x")),
-	_DECL_BLOB_FUNC(setLen,2,_SC("xi")),
-	_DECL_BLOB_FUNC(clear,1,_SC("x")),
-	{NULL,(SQFUNCTION)0,0,NULL}
-};
-
-
-
-//GLOBAL FUNCTIONS
-
-static SQRESULT _g_blob_casti2f(HSQUIRRELVM v)
-{
-	SQInteger i;
-	sq_getinteger(v,2,&i);
-	sq_pushfloat(v,*((SQFloat *)&i));
-	return 1;
-}
-
-static SQRESULT _g_blob_castf2i(HSQUIRRELVM v)
-{
-	SQFloat f;
-	sq_getfloat(v,2,&f);
-	sq_pushinteger(v,*((SQInteger *)&f));
-	return 1;
-}
-
-static SQRESULT _g_blob_swap2(HSQUIRRELVM v)
-{
-	SQInteger i;
-	sq_getinteger(v,2,&i);
-	short s=(short)i;
-	sq_pushinteger(v,(s<<8)|((s>>8)&0x00FF));
-	return 1;
-}
-
-static SQRESULT _g_blob_swap4(HSQUIRRELVM v)
-{
-	SQInteger i;
-	sq_getinteger(v,2,&i);
-	unsigned int t4 = (unsigned int)i;
-	__swap_dword(&t4);
-	sq_pushinteger(v,(SQInteger)t4);
-	return 1;
-}
-
-static SQRESULT _g_blob_swapfloat(HSQUIRRELVM v)
-{
-	SQFloat f;
-	sq_getfloat(v,2,&f);
-	__swap_dword((unsigned int *)&f);
-	sq_pushfloat(v,f);
-	return 1;
-}
-
-#define _DECL_GLOBALBLOB_FUNC(name,nparams,typecheck) {_SC(#name),_g_blob_##name,nparams,typecheck}
-static SQRegFunction bloblib_funcs[]={
-	_DECL_GLOBALBLOB_FUNC(casti2f,2,_SC(".n")),
-	_DECL_GLOBALBLOB_FUNC(castf2i,2,_SC(".n")),
-	_DECL_GLOBALBLOB_FUNC(swap2,2,_SC(".n")),
-	_DECL_GLOBALBLOB_FUNC(swap4,2,_SC(".n")),
-	_DECL_GLOBALBLOB_FUNC(swapfloat,2,_SC(".n")),
-	{NULL,(SQFUNCTION)0,0,NULL}
-};
-
-SQRESULT sqstd_getblob(HSQUIRRELVM v,SQInteger idx,SQUserPointer *ptr)
-{
-	SQBlob *blob;
-	if(SQ_FAILED(sq_getinstanceup(v,idx,(SQUserPointer *)&blob,(SQUserPointer)SQSTD_BLOB_TYPE_TAG)))
-		return -1;
-	*ptr = blob->GetBuf();
-	return SQ_OK;
-}
-
-SQInteger sqstd_getblobsize(HSQUIRRELVM v,SQInteger idx)
-{
-	SQBlob *blob;
-	if(SQ_FAILED(sq_getinstanceup(v,idx,(SQUserPointer *)&blob,(SQUserPointer)SQSTD_BLOB_TYPE_TAG)))
-		return -1;
-	return blob->Len();
-}
-
-SQInteger blob_read(SQUserPointer file,SQUserPointer buf,SQInteger size)
-{
+}
+
+#define _DECL_BLOB_FUNC(name,nparams,typecheck) {_SC(#name),_blob_##name,nparams,typecheck}
+static SQRegFunction _blob_methods[] = {
+	_DECL_BLOB_FUNC(constructor,-1,_SC("xnn")),
+	_DECL_BLOB_FUNC(resize,2,_SC("xn")),
+	_DECL_BLOB_FUNC(grow,2,_SC("xn")),
+	_DECL_BLOB_FUNC(reserve,2,_SC("xn")),
+	_DECL_BLOB_FUNC(swap2,1,_SC("x")),
+	_DECL_BLOB_FUNC(swap4,1,_SC("x")),
+	_DECL_BLOB_FUNC(memset,4,_SC("xiii")),
+	_DECL_BLOB_FUNC(_set,3,_SC("xnn")),
+	_DECL_BLOB_FUNC(_get,2,_SC("x n|s")), //allow call metatable methods indexed by strings
+	_DECL_BLOB_FUNC(_typeof,1,_SC("x")),
+	_DECL_BLOB_FUNC(_nexti,2,_SC("x")),
+	_DECL_BLOB_FUNC(_cloned,2,_SC("xx")),
+	//_DECL_BLOB_FUNC(_tostring,1,_SC("x")),
+	_DECL_BLOB_FUNC(tostring,1,_SC("x")),
+	_DECL_BLOB_FUNC(setLen,2,_SC("xi")),
+	_DECL_BLOB_FUNC(clear,1,_SC("x")),
+	{NULL,(SQFUNCTION)0,0,NULL}
+};
+
+
+
+//GLOBAL FUNCTIONS
+
+static SQRESULT _g_blob_casti2f(HSQUIRRELVM v)
+{
+	SQInteger i;
+	sq_getinteger(v,2,&i);
+	sq_pushfloat(v,*((SQFloat *)&i));
+	return 1;
+}
+
+static SQRESULT _g_blob_castf2i(HSQUIRRELVM v)
+{
+	SQFloat f;
+	sq_getfloat(v,2,&f);
+	sq_pushinteger(v,*((SQInteger *)&f));
+	return 1;
+}
+
+static SQRESULT _g_blob_swap2(HSQUIRRELVM v)
+{
+	SQInteger i;
+	sq_getinteger(v,2,&i);
+	short s=(short)i;
+	sq_pushinteger(v,(s<<8)|((s>>8)&0x00FF));
+	return 1;
+}
+
+static SQRESULT _g_blob_swap4(HSQUIRRELVM v)
+{
+	SQInteger i;
+	sq_getinteger(v,2,&i);
+	unsigned int t4 = (unsigned int)i;
+	__swap_dword(&t4);
+	sq_pushinteger(v,(SQInteger)t4);
+	return 1;
+}
+
+static SQRESULT _g_blob_swapfloat(HSQUIRRELVM v)
+{
+	SQFloat f;
+	sq_getfloat(v,2,&f);
+	__swap_dword((unsigned int *)&f);
+	sq_pushfloat(v,f);
+	return 1;
+}
+
+#define _DECL_GLOBALBLOB_FUNC(name,nparams,typecheck) {_SC(#name),_g_blob_##name,nparams,typecheck}
+static SQRegFunction bloblib_funcs[]={
+	_DECL_GLOBALBLOB_FUNC(casti2f,2,_SC(".n")),
+	_DECL_GLOBALBLOB_FUNC(castf2i,2,_SC(".n")),
+	_DECL_GLOBALBLOB_FUNC(swap2,2,_SC(".n")),
+	_DECL_GLOBALBLOB_FUNC(swap4,2,_SC(".n")),
+	_DECL_GLOBALBLOB_FUNC(swapfloat,2,_SC(".n")),
+	{NULL,(SQFUNCTION)0,0,NULL}
+};
+
+SQRESULT sqstd_getblob(HSQUIRRELVM v,SQInteger idx,SQUserPointer *ptr)
+{
+	SQBlob *blob;
+	if(SQ_FAILED(sq_getinstanceup(v,idx,(SQUserPointer *)&blob,(SQUserPointer)SQSTD_BLOB_TYPE_TAG)))
+		return -1;
+	*ptr = blob->GetBuf();
+	return SQ_OK;
+}
+
+SQInteger sqstd_getblobsize(HSQUIRRELVM v,SQInteger idx)
+{
+	SQBlob *blob;
+	if(SQ_FAILED(sq_getinstanceup(v,idx,(SQUserPointer *)&blob,(SQUserPointer)SQSTD_BLOB_TYPE_TAG)))
+		return -1;
+	return blob->Len();
+}
+
+SQInteger blob_read(SQUserPointer file,SQUserPointer buf,SQInteger size)
+{
 	SQInteger ret;
-	SQBlob *blob = (SQBlob *)file;
-	if( ( ret = blob->Read(buf, size)) !=0 ) return ret;
-	return -1;
-}
-
-SQInteger blob_write(SQUserPointer file,SQUserPointer p,SQInteger size)
-{
-    SQBlob *blob = (SQBlob *)file;
-	return blob->Write(p,size);
-}
-
-
-SQUserPointer sqstd_createblob(HSQUIRRELVM v, SQInteger size)
-{
-	SQInteger top = sq_gettop(v);
-	sq_pushregistrytable(v);
-	sq_pushstring(v,_SC("std_blob"),-1);
-	if(SQ_SUCCEEDED(sq_get(v,-2))) {
-		sq_remove(v,-2); //removes the registry
-		sq_push(v,1); // push the this
-		sq_pushinteger(v,size); //size
-		SQBlob *blob = NULL;
-		if(SQ_SUCCEEDED(sq_call(v,2,SQTrue,SQFalse))
-			&& SQ_SUCCEEDED(sq_getinstanceup(v,-1,(SQUserPointer *)&blob,(SQUserPointer)SQSTD_BLOB_TYPE_TAG))) {
-			sq_remove(v,-2);
-			return blob->GetBuf();
-		}
-	}
-	sq_settop(v,top);
-	return NULL;
-}
-
-SQRESULT sqstd_register_bloblib(HSQUIRRELVM v)
-{
-	return declare_stream(v,_SC("blob"),(SQUserPointer)SQSTD_BLOB_TYPE_TAG,_SC("std_blob"),_blob_methods,bloblib_funcs);
-}
-
+	SQBlob *blob = (SQBlob *)file;
+	if( ( ret = blob->Read(buf, size)) !=0 ) return ret;
+	return -1;
+}
+
+SQInteger blob_write(SQUserPointer file,SQUserPointer p,SQInteger size)
+{
+    SQBlob *blob = (SQBlob *)file;
+	return blob->Write(p,size);
+}
+
+
+SQUserPointer sqstd_createblob(HSQUIRRELVM v, SQInteger size)
+{
+	SQInteger top = sq_gettop(v);
+	sq_pushregistrytable(v);
+	sq_pushstring(v,_SC("std_blob"),-1);
+	if(SQ_SUCCEEDED(sq_get(v,-2))) {
+		sq_remove(v,-2); //removes the registry
+		sq_push(v,1); // push the this
+		sq_pushinteger(v,size); //size
+		SQBlob *blob = NULL;
+		if(SQ_SUCCEEDED(sq_call(v,2,SQTrue,SQFalse))
+			&& SQ_SUCCEEDED(sq_getinstanceup(v,-1,(SQUserPointer *)&blob,(SQUserPointer)SQSTD_BLOB_TYPE_TAG))) {
+			sq_remove(v,-2);
+			return blob->GetBuf();
+		}
+	}
+	sq_settop(v,top);
+	return NULL;
+}
+
+SQRESULT sqstd_register_bloblib(HSQUIRRELVM v)
+{
+	return declare_stream(v,_SC("blob"),(SQUserPointer)SQSTD_BLOB_TYPE_TAG,_SC("std_blob"),_blob_methods,bloblib_funcs);
+}
+

+ 40 - 39
SquiLu/sqstdlib/sqstdblobimpl.h

@@ -1,44 +1,45 @@
-/*	see copyright notice in squirrel.h */
-#ifndef _SQSTD_BLOBIMPL_H_
-#define _SQSTD_BLOBIMPL_H_
-
+/*	see copyright notice in squirrel.h */
+#ifndef _SQSTD_BLOBIMPL_H_
+#define _SQSTD_BLOBIMPL_H_
+
 #include "sqstdio.h"
 #define BLOB_BUFSIZE 8192
 
-struct SQBlob : public SQStream
-{
-	SQBlob(SQInteger size, SQInteger allocated=0);
-	virtual ~SQBlob();
-	SQInteger Write(const void *buffer, SQInteger size);
+struct SQBlob : public SQStream
+{
+	SQBlob(SQInteger size, SQInteger allocated=0);
+	virtual ~SQBlob();
+	SQInteger Write(const void *buffer, SQInteger size);
 	SQInteger WriteZstr(const char *zStr);
-	SQInteger WriteChar(const char c);
-	SQInteger Read(void *buffer,SQInteger size);
-	SQInteger Gets(char *buffer,SQInteger size);
-	bool Resize(SQInteger n);
-	bool GrowBufOf(SQInteger n);
-	bool CanAdvance(SQInteger n) {
-		if(_ptr+n>_size)return false;
-		return true;
-	}
-	SQInteger Seek(SQInteger offset, SQInteger origin);
-	bool IsValid() {
-		return _buf?true:false;
-	}
-	bool EOS() {
-		return _ptr == _size;
-	}
-	SQInteger Flush() { return 0; }
-	SQInteger Tell() { return _ptr; }
-	SQInteger Len() { return _size; }
+	SQInteger WriteChar(const char c);
+	SQInteger Read(void *buffer,SQInteger size);
+	SQInteger Gets(char *buffer,SQInteger size);
+	bool Resize(SQInteger n);
+	bool Reserve(SQInteger n);
+	bool GrowBufOf(SQInteger n);
+	bool CanAdvance(SQInteger n) {
+		if(_ptr+n>_size)return false;
+		return true;
+	}
+	SQInteger Seek(SQInteger offset, SQInteger origin);
+	bool IsValid() {
+		return _buf?true:false;
+	}
+	bool EOS() {
+		return _ptr == _size;
+	}
+	SQInteger Flush() { return 0; }
+	SQInteger Tell() { return _ptr; }
+	SQInteger Len() { return _size; }
 	SQUserPointer GetBuf(){ return _buf; }
-	bool SetLen(SQInteger len);
-	static SQUserPointer SQBlob_TAG;
-private:
-	SQInteger _size;
-	SQInteger _allocated;
-	SQInteger _ptr;
-	unsigned char *_buf;
-	bool _owns;
-};
-
-#endif //_SQSTD_BLOBIMPL_H_
+	bool SetLen(SQInteger len);
+	static SQUserPointer SQBlob_TAG;
+private:
+	SQInteger _size;
+	SQInteger _allocated;
+	SQInteger _ptr;
+	unsigned char *_buf;
+	bool _owns;
+};
+
+#endif //_SQSTD_BLOBIMPL_H_

+ 90 - 4
SquiLu/sqstdlib/sqstdio.cpp

@@ -67,7 +67,7 @@ struct SQFile : public SQStream {
 	SQFile() { _handle = NULL; _owns = false;}
 	SQFile(SQFILE file, bool owns) { _handle = file; _owns = owns;}
 	virtual ~SQFile() { Close(); }
-	bool Open(const SQChar *filename ,const SQChar *mode) {
+	virtual bool Open(const SQChar *filename ,const SQChar *mode) {
 		Close();
 		if( (_handle = sqstd_fopen(filename,mode)) ) {
 			_owns = true;
@@ -75,7 +75,7 @@ struct SQFile : public SQStream {
 		}
 		return false;
 	}
-	void Close() {
+	virtual void Close() {
 		if(_handle && _owns) {
 			sqstd_fclose(_handle);
 			_handle = NULL;
@@ -111,11 +111,97 @@ struct SQFile : public SQStream {
 	bool IsValid() { return _handle?true:false; }
 	bool EOS() { return Tell()==Len()?true:false;}
 	SQFILE GetHandle() {return _handle;}
-private:
+protected:
 	SQFILE _handle;
 	bool _owns;
 };
 
+struct SQPopen : public SQFile {
+	SQPopen():SQFile() {}
+	SQPopen(SQFILE file, bool owns):SQFile(file, owns) {}
+	bool Open(const SQChar *filename ,const SQChar *mode) {
+		Close();
+		if( (_handle = popen(filename,mode)) ) {
+			_owns = true;
+			return true;
+		}
+		return false;
+	}
+	int PClose() {
+	    int result = 0;
+		if(_handle && _owns) {
+			result = pclose((FILE*)_handle);
+			_handle = NULL;
+			_owns = false;
+		}
+		return result;
+	}
+	void Close() {
+	    PClose();
+	}
+};
+
+static SQRESULT _popen__typeof(HSQUIRRELVM v)
+{
+	sq_pushstring(v,_SC("popen"),-1);
+	return 1;
+}
+
+static SQRESULT _popen_releasehook(SQUserPointer p, SQInteger /*size*/, void */*ep*/)
+{
+	SQPopen *self = (SQPopen*)p;
+	self->~SQPopen();
+	sq_free(self,sizeof(SQFile));
+	return 1;
+}
+
+static SQRESULT _popen_constructor(HSQUIRRELVM v)
+{
+	const SQChar *filename,*mode;
+	bool owns = true;
+	SQPopen *f;
+	SQFILE newf;
+	if(sq_gettype(v,2) == OT_STRING && sq_gettype(v,3) == OT_STRING) {
+		sq_getstring(v, 2, &filename);
+		sq_getstring(v, 3, &mode);
+		newf = popen(filename, mode);
+		if(!newf) return sq_throwerror(v, _SC("cannot open file"));
+	} else {
+		return sq_throwerror(v,_SC("wrong parameter"));
+	}
+
+	f = new (sq_malloc(sizeof(SQPopen)))SQPopen(newf,owns);
+	if(SQ_FAILED(sq_setinstanceup(v,1,f))) {
+		f->~SQPopen();
+		sq_free(f,sizeof(SQPopen));
+		return sq_throwerror(v, _SC("cannot create popen"));
+	}
+	sq_setreleasehook(v,1,_popen_releasehook);
+	return 0;
+}
+
+static SQRESULT _popen_close(HSQUIRRELVM v)
+{
+	SQPopen *self = NULL;
+	if(SQ_SUCCEEDED(sq_getinstanceup(v,1,(SQUserPointer*)&self,(SQUserPointer)SQSTD_FILE_TYPE_TAG))
+		&& self != NULL)
+	{
+		sq_pushinteger(v, self->PClose());
+		return 1;
+	}
+	return 0;
+}
+
+//bindings
+#define _DECL_FILE_FUNC(name,nparams,typecheck) {_SC(#name),_popen_##name,nparams,typecheck}
+static const SQRegFunction _popen_methods[] = {
+    _DECL_FILE_FUNC(constructor,3,_SC("x")),
+    _DECL_FILE_FUNC(_typeof,1,_SC("x")),
+    _DECL_FILE_FUNC(close,1,_SC("x")),
+    {NULL,(SQFUNCTION)0,0,NULL}
+};
+#undef _DECL_FILE_FUNC
+
 static SQRESULT _file__typeof(HSQUIRRELVM v)
 {
 	sq_pushstring(v,_SC("file"),-1);
@@ -179,7 +265,6 @@ static const SQRegFunction _file_methods[] = {
 };
 
 
-
 SQRESULT sqstd_createfile(HSQUIRRELVM v, SQFILE file,SQBool own)
 {
 	SQInteger top = sq_gettop(v);
@@ -583,6 +668,7 @@ static const SQRegFunction iolib_funcs[]={
 SQRESULT sqstd_register_iolib(HSQUIRRELVM v)
 {
 	//create delegate
+	declare_stream(v,_SC("popen"),(SQUserPointer)SQSTD_FILE_TYPE_TAG,_SC("std_file"),_popen_methods,iolib_funcs);
 	declare_stream(v,_SC("file"),(SQUserPointer)SQSTD_FILE_TYPE_TAG,_SC("std_file"),_file_methods,iolib_funcs);
 	sq_pushstring(v,_SC("stdout"),-1);
 	sqstd_createfile(v,stdout,SQFalse);

+ 435 - 417
SquiLu/sqstdlib/sqstdstream.cpp

@@ -1,25 +1,25 @@
-/* see copyright notice in squirrel.h */
-#include <new>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <squirrel.h>
-#include <sqstdio.h>
-#include <sqstdblob.h>
-#include "sqstdstream.h"
+/* see copyright notice in squirrel.h */
+#include <new>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <squirrel.h>
+#include <sqstdio.h>
+#include <sqstdblob.h>
+#include "sqstdstream.h"
 #include "sqstdblobimpl.h"
 
-static const SQChar SQSTD_STREAM_TYPE_TAG[] = _SC("std_stream");
-
-#define SETUP_STREAM(v) \
-	SQStream *self = NULL; \
-	if(SQ_FAILED(sq_getinstanceup(v,1,(SQUserPointer*)&self,(SQUserPointer)SQSTD_STREAM_TYPE_TAG))) \
-		return sq_throwerror(v,_SC("invalid type tag")); \
-	if(!self || !self->IsValid())  \
-		return sq_throwerror(v,_SC("the stream is invalid"));
+static const SQChar SQSTD_STREAM_TYPE_TAG[] = _SC("std_stream");
+
+#define SETUP_STREAM(v) \
+	SQStream *self = NULL; \
+	if(SQ_FAILED(sq_getinstanceup(v,1,(SQUserPointer*)&self,(SQUserPointer)SQSTD_STREAM_TYPE_TAG))) \
+		return sq_throwerror(v,_SC("invalid type tag")); \
+	if(!self || !self->IsValid())  \
+		return sq_throwerror(v,_SC("the stream is invalid"));
 
 SQInteger _stream_read_line(HSQUIRRELVM v) {
-	SETUP_STREAM(v);
+	SETUP_STREAM(v);
     const SQChar nl = _SC('\n');
     const SQChar rc = _SC('\r');
     SQInteger size, read_size;
@@ -64,428 +64,446 @@ SQInteger _stream_read_line(HSQUIRRELVM v) {
     return 1;
 }
 
-SQInteger _stream_read(HSQUIRRELVM v)
-{
-	SETUP_STREAM(v);
-	SQChar *data;
-	SQInteger size,res;
+SQInteger _stream_read_all(HSQUIRRELVM v) {
+	SETUP_STREAM(v);
+    SQInteger size = 4096, read_size;
+    SQBlob line_buf(0, size);
+    do{
+        char *buf = (SQChar*)line_buf.GetBuf();
+        read_size = self->Gets(buf + line_buf.Len(), size);
+        line_buf.SetLen(line_buf.Len() + read_size);
+        line_buf.Reserve(size);
+    } while(read_size > 0);
+    if(line_buf.Len() > 0) {
+        sq_pushstring(v, (const SQChar*)line_buf.GetBuf(), line_buf.Len());
+    }
+    else sq_pushnull(v); //end of file
+    return 1;
+}
+
+SQInteger _stream_read(HSQUIRRELVM v)
+{
+	SETUP_STREAM(v);
+	SQChar *data;
+	SQInteger size,res;
 	sq_getinteger(v,2,&size);
-	/* DAD come back here
-	if(self->GetHandle() != stdin && size > self->Len()) {
-		size = self->Len();
+	/* DAD come back here
+	if(self->GetHandle() != stdin && size > self->Len()) {
+		size = self->Len();
 	}
-	*/
-	data = sq_getscratchpad(v,size);
-	res = self->Read(data,size);
-	if(res <= 0)
-		return sq_throwerror(v,_SC("no data left to read"));
-	sq_pushstring(v,data,res);
-	return 1;
-}
-
-SQInteger _stream_gets(HSQUIRRELVM v)
-{
-	SETUP_STREAM(v);
-	SQChar *data;
+	*/
+	data = sq_getscratchpad(v,size);
+	res = self->Read(data,size);
+	if(res <= 0)
+		return sq_throwerror(v,_SC("no data left to read"));
+	sq_pushstring(v,data,res);
+	return 1;
+}
+
+SQInteger _stream_gets(HSQUIRRELVM v)
+{
+	SETUP_STREAM(v);
+	SQChar *data;
 	SQInteger size, read_size;
 	sq_getinteger(v,2,&size);
-	/* DAD come back here
-	if(self->GetHandle() != stdin && size > self->Len()) {
-		size = self->Len();
+	/* DAD come back here
+	if(self->GetHandle() != stdin && size > self->Len()) {
+		size = self->Len();
+	}
+	*/
+	data = sq_getscratchpad(v,size);
+	read_size = self->Gets(data,size);
+	if(!read_size)
+		return sq_throwerror(v,_SC("no data left to read"));
+	sq_pushstring(v,data,read_size);
+	return 1;
+}
+
+SQInteger _stream_readblob(HSQUIRRELVM v)
+{
+	SETUP_STREAM(v);
+	SQUserPointer blobp;
+	SQInteger size,res;
+	sq_getinteger(v,2,&size);
+	if(size > self->Len()) {
+		size = self->Len();
 	}
-	*/
-	data = sq_getscratchpad(v,size);
-	read_size = self->Gets(data,size);
-	if(!read_size)
-		return sq_throwerror(v,_SC("no data left to read"));
-	sq_pushstring(v,data,read_size);
-	return 1;
-}
-
-SQInteger _stream_readblob(HSQUIRRELVM v)
-{
-	SETUP_STREAM(v);
-	SQUserPointer blobp;
-	SQInteger size,res;
-	sq_getinteger(v,2,&size);
-	if(size > self->Len()) {
-		size = self->Len();
-	}
-	blobp = sqstd_createblob(v,size);
-	res = self->Read(blobp,size);
-	if(res <= 0)
-		return sq_throwerror(v,_SC("no data left to read"));
-	return 1;
-}
-
-#define SAFE_READN(ptr,len) { \
-	if(self->Read(ptr,len) != len) return sq_throwerror(v,_SC("io error")); \
-	}
-SQInteger _stream_readn(HSQUIRRELVM v)
-{
-	SETUP_STREAM(v);
-	SQInteger format;
-	sq_getinteger(v, 2, &format);
-	switch(format) {
-	case 'l': {
-		SQInteger i;
-		SAFE_READN(&i, sizeof(i));
-		sq_pushinteger(v, i);
-			  }
-		break;
-	case 'i': {
-		SQInt32 i;
-		SAFE_READN(&i, sizeof(i));
-		sq_pushinteger(v, i);
-			  }
-		break;
-	case 's': {
-		short s;
-		SAFE_READN(&s, sizeof(short));
-		sq_pushinteger(v, s);
-			  }
-		break;
-	case 'w': {
-		unsigned short w;
-		SAFE_READN(&w, sizeof(unsigned short));
-		sq_pushinteger(v, w);
-			  }
-		break;
-	case 'c': {
-		char c;
-		SAFE_READN(&c, sizeof(char));
-		sq_pushinteger(v, c);
-			  }
-		break;
-	case 'b': {
-		unsigned char c;
-		SAFE_READN(&c, sizeof(unsigned char));
-		sq_pushinteger(v, c);
-			  }
-		break;
-	case 'f': {
-		float f;
-		SAFE_READN(&f, sizeof(float));
-		sq_pushfloat(v, f);
-			  }
-		break;
-	case 'd': {
-		double d;
-		SAFE_READN(&d, sizeof(double));
-		sq_pushfloat(v, (SQFloat)d);
-			  }
-		break;
-	default:
-		return sq_throwerror(v, _SC("invalid format"));
-	}
-	return 1;
-}
-
-SQInteger _stream_write_str(HSQUIRRELVM v)
+	blobp = sqstd_createblob(v,size);
+	res = self->Read(blobp,size);
+	if(res <= 0)
+		return sq_throwerror(v,_SC("no data left to read"));
+	return 1;
+}
+
+#define SAFE_READN(ptr,len) { \
+	if(self->Read(ptr,len) != len) return sq_throwerror(v,_SC("io error")); \
+	}
+SQInteger _stream_readn(HSQUIRRELVM v)
 {
-    SQ_FUNC_VARS(v);
+	SETUP_STREAM(v);
+	SQInteger format;
+	sq_getinteger(v, 2, &format);
+	switch(format) {
+	case 'l': {
+		SQInteger i;
+		SAFE_READN(&i, sizeof(i));
+		sq_pushinteger(v, i);
+			  }
+		break;
+	case 'i': {
+		SQInt32 i;
+		SAFE_READN(&i, sizeof(i));
+		sq_pushinteger(v, i);
+			  }
+		break;
+	case 's': {
+		short s;
+		SAFE_READN(&s, sizeof(short));
+		sq_pushinteger(v, s);
+			  }
+		break;
+	case 'w': {
+		unsigned short w;
+		SAFE_READN(&w, sizeof(unsigned short));
+		sq_pushinteger(v, w);
+			  }
+		break;
+	case 'c': {
+		char c;
+		SAFE_READN(&c, sizeof(char));
+		sq_pushinteger(v, c);
+			  }
+		break;
+	case 'b': {
+		unsigned char c;
+		SAFE_READN(&c, sizeof(unsigned char));
+		sq_pushinteger(v, c);
+			  }
+		break;
+	case 'f': {
+		float f;
+		SAFE_READN(&f, sizeof(float));
+		sq_pushfloat(v, f);
+			  }
+		break;
+	case 'd': {
+		double d;
+		SAFE_READN(&d, sizeof(double));
+		sq_pushfloat(v, (SQFloat)d);
+			  }
+		break;
+	default:
+		return sq_throwerror(v, _SC("invalid format"));
+	}
+	return 1;
+}
+
+SQInteger _stream_write_str(HSQUIRRELVM v)
+{
+    SQ_FUNC_VARS(v);
 	SETUP_STREAM(v);
     SQ_GET_STRING(v, 2, str);
     SQ_OPT_INTEGER(v, 3, start, 0);
-    if(start < 0 || start > str_size) return sq_throwerror(v, _SC("start position out of range (%d)"), start);
+    if(start < 0 || start > str_size) return sq_throwerror(v, _SC("start position out of range (%d)"), start);
     SQ_OPT_INTEGER(v, 4, len, str_size - start);
-    if(len < 0 || len > (str_size-start)) return sq_throwerror(v, _SC("len value out of range (%d)"), len);
-
-    if(self->Write(((SQChar*)str)+start, len) != len)
-            return sq_throwerror(v,_SC("io error"));
-	sq_pushinteger(v,len);
-	return 1;
-}
+    if(len < 0 || len > (str_size-start)) return sq_throwerror(v, _SC("len value out of range (%d)"), len);
+
+    if(self->Write(((SQChar*)str)+start, len) != len)
+            return sq_throwerror(v,_SC("io error"));
+	sq_pushinteger(v,len);
+	return 1;
+}
 
-SQInteger _stream_write(HSQUIRRELVM v)
-{
-	const SQChar *str;
-	SQInteger total_size, size;
+SQInteger _stream_write(HSQUIRRELVM v)
+{
+	const SQChar *str;
+	SQInteger total_size, size;
 	SETUP_STREAM(v);
-	total_size = 0;
+	total_size = 0;
 	for(SQInteger i=2, len=sq_gettop(v); i <= len; ++i){
-        if(SQ_FAILED(sq_tostring(v,i)))
-            return sq_throwerror(v,_SC("invalid parameter"));
-        sq_getstring(v,-1,&str);
-        size = sq_getsize(v,-1);
-        if(self->Write((SQChar*)str,size) != size)
-            return sq_throwerror(v,_SC("io error"));
+        if(SQ_FAILED(sq_tostring(v,i)))
+            return sq_throwerror(v,_SC("invalid parameter"));
+        sq_getstring(v,-1,&str);
+        size = sq_getsize(v,-1);
+        if(self->Write((SQChar*)str,size) != size)
+            return sq_throwerror(v,_SC("io error"));
         sq_poptop(v); //remove converted string
         total_size += size;
-	}
-	sq_pushinteger(v,total_size);
-	return 1;
-}
+	}
+	sq_pushinteger(v,total_size);
+	return 1;
+}
 
-SQInteger _stream_write_non_null(HSQUIRRELVM v)
+SQInteger _stream_write_non_null(HSQUIRRELVM v)
 {
     if(sq_gettype(v, 2) != OT_NULL)
     {
         return _stream_write(v);
-    }
-	return 0;
-}
+    }
+	return 0;
+}
+
+SQInteger _stream_write_fmt(HSQUIRRELVM v)
+{
+	const SQChar *str;
+	SQInteger size;
+	SETUP_STREAM(v);
+	if(SQ_FAILED(sq_tostring(v,2)))
+		return sq_throwerror(v,_SC("invalid parameter"));
+    sq_getstring(v,-1,&str);
+	size = sq_getsize(v,-1);
+	if(self->Write((SQChar*)str,size) != size)
+		return sq_throwerror(v,_SC("io error"));
+    sq_poptop(v); //remove converted string
+	sq_pushinteger(v,size);
+	return 1;
+}
+
+SQInteger _stream_writeblob(HSQUIRRELVM v)
+{
+	SQUserPointer data;
+	SQInteger size;
+	SETUP_STREAM(v);
+	if(SQ_FAILED(sqstd_getblob(v,2,&data)))
+		return sq_throwerror(v,_SC("invalid parameter"));
+	size = sqstd_getblobsize(v,2);
+	if(self->Write(data,size) != size)
+		return sq_throwerror(v,_SC("io error"));
+	sq_pushinteger(v,size);
+	return 1;
+}
+
+SQInteger _stream_writen(HSQUIRRELVM v)
+{
+	SETUP_STREAM(v);
+	SQInteger format, ti;
+	SQFloat tf;
+	sq_getinteger(v, 3, &format);
+	switch(format) {
+	case 'l': {
+		SQInteger i;
+		sq_getinteger(v, 2, &ti);
+		i = ti;
+		self->Write(&i, sizeof(SQInteger));
+			  }
+		break;
+	case 'i': {
+		SQInt32 i;
+		sq_getinteger(v, 2, &ti);
+		i = (SQInt32)ti;
+		self->Write(&i, sizeof(SQInt32));
+			  }
+		break;
+	case 's': {
+		short s;
+		sq_getinteger(v, 2, &ti);
+		s = (short)ti;
+		self->Write(&s, sizeof(short));
+			  }
+		break;
+	case 'w': {
+		unsigned short w;
+		sq_getinteger(v, 2, &ti);
+		w = (unsigned short)ti;
+		self->Write(&w, sizeof(unsigned short));
+			  }
+		break;
+	case 'c': {
+		char c;
+		sq_getinteger(v, 2, &ti);
+		c = (char)ti;
+		self->Write(&c, sizeof(char));
+				  }
+		break;
+	case 'b': {
+		unsigned char b;
+		sq_getinteger(v, 2, &ti);
+		b = (unsigned char)ti;
+		self->Write(&b, sizeof(unsigned char));
+			  }
+		break;
+	case 'f': {
+		float f;
+		sq_getfloat(v, 2, &tf);
+		f = (float)tf;
+		self->Write(&f, sizeof(float));
+			  }
+		break;
+	case 'd': {
+		double d;
+		sq_getfloat(v, 2, &tf);
+		d = tf;
+		self->Write(&d, sizeof(double));
+			  }
+		break;
+	default:
+		return sq_throwerror(v, _SC("invalid format"));
+	}
+	return 0;
+}
+
+SQInteger _stream_seek(HSQUIRRELVM v)
+{
+	SETUP_STREAM(v);
+	SQInteger offset, origin = SQ_SEEK_SET;
+	sq_getinteger(v, 2, &offset);
+	if(sq_gettop(v) > 2) {
+		SQInteger t;
+		sq_getinteger(v, 3, &t);
+		switch(t) {
+			case 'b': origin = SQ_SEEK_SET; break;
+			case 'c': origin = SQ_SEEK_CUR; break;
+			case 'e': origin = SQ_SEEK_END; break;
+			default: return sq_throwerror(v,_SC("invalid origin"));
+		}
+	}
+	sq_pushinteger(v, self->Seek(offset, origin));
+	return 1;
+}
+
+SQInteger _stream_tell(HSQUIRRELVM v)
+{
+	SETUP_STREAM(v);
+	sq_pushinteger(v, self->Tell());
+	return 1;
+}
+
+SQInteger _stream_len(HSQUIRRELVM v)
+{
+	SETUP_STREAM(v);
+	sq_pushinteger(v, self->Len());
+	return 1;
+}
 
-SQInteger _stream_write_fmt(HSQUIRRELVM v)
-{
-	const SQChar *str;
-	SQInteger size;
-	SETUP_STREAM(v);
-	if(SQ_FAILED(sq_tostring(v,2)))
-		return sq_throwerror(v,_SC("invalid parameter"));
-    sq_getstring(v,-1,&str);
-	size = sq_getsize(v,-1);
-	if(self->Write((SQChar*)str,size) != size)
-		return sq_throwerror(v,_SC("io error"));
-    sq_poptop(v); //remove converted string
-	sq_pushinteger(v,size);
-	return 1;
-}
+SQInteger _stream_flush(HSQUIRRELVM v)
+{
+	SETUP_STREAM(v);
+	if(!self->Flush())
+		sq_pushinteger(v, 1);
+	else
+		sq_pushnull(v);
+	return 1;
+}
 
-SQInteger _stream_writeblob(HSQUIRRELVM v)
-{
-	SQUserPointer data;
-	SQInteger size;
-	SETUP_STREAM(v);
-	if(SQ_FAILED(sqstd_getblob(v,2,&data)))
-		return sq_throwerror(v,_SC("invalid parameter"));
-	size = sqstd_getblobsize(v,2);
-	if(self->Write(data,size) != size)
-		return sq_throwerror(v,_SC("io error"));
-	sq_pushinteger(v,size);
-	return 1;
-}
-
-SQInteger _stream_writen(HSQUIRRELVM v)
-{
-	SETUP_STREAM(v);
-	SQInteger format, ti;
-	SQFloat tf;
-	sq_getinteger(v, 3, &format);
-	switch(format) {
-	case 'l': {
-		SQInteger i;
-		sq_getinteger(v, 2, &ti);
-		i = ti;
-		self->Write(&i, sizeof(SQInteger));
-			  }
-		break;
-	case 'i': {
-		SQInt32 i;
-		sq_getinteger(v, 2, &ti);
-		i = (SQInt32)ti;
-		self->Write(&i, sizeof(SQInt32));
-			  }
-		break;
-	case 's': {
-		short s;
-		sq_getinteger(v, 2, &ti);
-		s = (short)ti;
-		self->Write(&s, sizeof(short));
-			  }
-		break;
-	case 'w': {
-		unsigned short w;
-		sq_getinteger(v, 2, &ti);
-		w = (unsigned short)ti;
-		self->Write(&w, sizeof(unsigned short));
-			  }
-		break;
-	case 'c': {
-		char c;
-		sq_getinteger(v, 2, &ti);
-		c = (char)ti;
-		self->Write(&c, sizeof(char));
-				  }
-		break;
-	case 'b': {
-		unsigned char b;
-		sq_getinteger(v, 2, &ti);
-		b = (unsigned char)ti;
-		self->Write(&b, sizeof(unsigned char));
-			  }
-		break;
-	case 'f': {
-		float f;
-		sq_getfloat(v, 2, &tf);
-		f = (float)tf;
-		self->Write(&f, sizeof(float));
-			  }
-		break;
-	case 'd': {
-		double d;
-		sq_getfloat(v, 2, &tf);
-		d = tf;
-		self->Write(&d, sizeof(double));
-			  }
-		break;
-	default:
-		return sq_throwerror(v, _SC("invalid format"));
-	}
-	return 0;
-}
-
-SQInteger _stream_seek(HSQUIRRELVM v)
-{
-	SETUP_STREAM(v);
-	SQInteger offset, origin = SQ_SEEK_SET;
-	sq_getinteger(v, 2, &offset);
-	if(sq_gettop(v) > 2) {
-		SQInteger t;
-		sq_getinteger(v, 3, &t);
-		switch(t) {
-			case 'b': origin = SQ_SEEK_SET; break;
-			case 'c': origin = SQ_SEEK_CUR; break;
-			case 'e': origin = SQ_SEEK_END; break;
-			default: return sq_throwerror(v,_SC("invalid origin"));
-		}
-	}
-	sq_pushinteger(v, self->Seek(offset, origin));
-	return 1;
-}
-
-SQInteger _stream_tell(HSQUIRRELVM v)
-{
-	SETUP_STREAM(v);
-	sq_pushinteger(v, self->Tell());
-	return 1;
-}
-
-SQInteger _stream_len(HSQUIRRELVM v)
-{
-	SETUP_STREAM(v);
-	sq_pushinteger(v, self->Len());
-	return 1;
-}
-
-SQInteger _stream_flush(HSQUIRRELVM v)
-{
-	SETUP_STREAM(v);
-	if(!self->Flush())
-		sq_pushinteger(v, 1);
-	else
-		sq_pushnull(v);
-	return 1;
-}
-
-SQInteger _stream_eos(HSQUIRRELVM v)
-{
-	SETUP_STREAM(v);
-	if(self->EOS())
-		sq_pushinteger(v, 1);
-	else
-		sq_pushnull(v);
-	return 1;
-}
-
- SQInteger _stream__cloned(HSQUIRRELVM v)
- {
-	 return sq_throwerror(v,_SC("this object cannot be cloned"));
- }
+SQInteger _stream_eos(HSQUIRRELVM v)
+{
+	SETUP_STREAM(v);
+	if(self->EOS())
+		sq_pushinteger(v, 1);
+	else
+		sq_pushnull(v);
+	return 1;
+}
+
+ SQInteger _stream__cloned(HSQUIRRELVM v)
+ {
+	 return sq_throwerror(v,_SC("this object cannot be cloned"));
+ }
 
 #define _DECL_STREAM_FUNC2(name,name2, nparams,typecheck) {_SC(#name2),_stream_##name,nparams,typecheck}
-
-static SQRegFunction _stream_methods[] = {
-	_DECL_STREAM_FUNC(read_line,-1,_SC("xi")),
-	_DECL_STREAM_FUNC(read,2,_SC("xn")),
-	_DECL_STREAM_FUNC(gets,2,_SC("xn")),
-	_DECL_STREAM_FUNC(readblob,2,_SC("xn")),
-	_DECL_STREAM_FUNC(readn,2,_SC("xn")),
-	_DECL_STREAM_FUNC(write_str,-2,_SC("xsii")),
-	_DECL_STREAM_FUNC(write,-2,_SC("x.")),
-	_DECL_STREAM_FUNC(writeblob,-2,_SC("xx")),
-	_DECL_STREAM_FUNC(writen,3,_SC("xnn")),
-	_DECL_STREAM_FUNC(write_non_null,2,_SC("x.")),
-	_DECL_STREAM_FUNC(seek,-2,_SC("xnn")),
-	_DECL_STREAM_FUNC(tell,1,_SC("x")),
-	_DECL_STREAM_FUNC(len,1,_SC("x")),
-	_DECL_STREAM_FUNC2(len,size,1,_SC("x")),
-	_DECL_STREAM_FUNC2(len,length,1,_SC("x")),
-	_DECL_STREAM_FUNC(eos,1,_SC("x")),
-	_DECL_STREAM_FUNC(flush,1,_SC("x")),
-	_DECL_STREAM_FUNC(_cloned,0,NULL),
-	{NULL,(SQFUNCTION)0,0,NULL}
+
+static SQRegFunction _stream_methods[] = {
+	_DECL_STREAM_FUNC(read_line,-1,_SC("xi")),
+	_DECL_STREAM_FUNC(read,2,_SC("xn")),
+	_DECL_STREAM_FUNC(gets,2,_SC("xn")),
+	_DECL_STREAM_FUNC(readblob,2,_SC("xn")),
+	_DECL_STREAM_FUNC(readn,2,_SC("xn")),
+	_DECL_STREAM_FUNC(read_all,1,_SC("x")),
+	_DECL_STREAM_FUNC(write_str,-2,_SC("xsii")),
+	_DECL_STREAM_FUNC(write,-2,_SC("x.")),
+	_DECL_STREAM_FUNC(writeblob,-2,_SC("xx")),
+	_DECL_STREAM_FUNC(writen,3,_SC("xnn")),
+	_DECL_STREAM_FUNC(write_non_null,2,_SC("x.")),
+	_DECL_STREAM_FUNC(seek,-2,_SC("xnn")),
+	_DECL_STREAM_FUNC(tell,1,_SC("x")),
+	_DECL_STREAM_FUNC(len,1,_SC("x")),
+	_DECL_STREAM_FUNC2(len,size,1,_SC("x")),
+	_DECL_STREAM_FUNC2(len,length,1,_SC("x")),
+	_DECL_STREAM_FUNC(eos,1,_SC("x")),
+	_DECL_STREAM_FUNC(flush,1,_SC("x")),
+	_DECL_STREAM_FUNC(_cloned,0,NULL),
+	{NULL,(SQFUNCTION)0,0,NULL}
 };
 
-void init_streamclass(HSQUIRRELVM v)
-{
-	sq_pushregistrytable(v);
-	sq_pushstring(v,SQSTD_STREAM_TYPE_TAG,-1);
-	if(SQ_FAILED(sq_get(v,-2))) {
-		sq_pushstring(v,SQSTD_STREAM_TYPE_TAG,-1);
-		sq_newclass(v,SQFalse);
-		sq_settypetag(v,-1,(SQUserPointer)SQSTD_STREAM_TYPE_TAG);
-		SQInteger i = 0;
-		while(_stream_methods[i].name != 0) {
-			SQRegFunction &f = _stream_methods[i];
-			sq_pushstring(v,f.name,-1);
-			sq_newclosure(v,f.f,0);
-			sq_setparamscheck(v,f.nparamscheck,f.typemask);
-			sq_newslot(v,-3,SQFalse);
-			i++;
-		}
-		sq_newslot(v,-3,SQFalse);
-		sq_pushroottable(v);
-		sq_pushstring(v,_SC("stream"),-1);
-		sq_pushstring(v,_SC("std_stream"),-1);
-		sq_get(v,-4);
-		sq_newslot(v,-3,SQFalse);
-		sq_pop(v,1);
-	}
-	else {
-		sq_pop(v,1); //result
-	}
-	sq_pop(v,1);
-}
-
-SQRESULT declare_stream(HSQUIRRELVM v,const SQChar* name,SQUserPointer typetag,const SQChar* reg_name,const SQRegFunction *methods,const SQRegFunction *globals)
-{
-	if(sq_gettype(v,-1) != OT_TABLE)
-		return sq_throwerror(v,_SC("table expected"));
-	SQInteger top = sq_gettop(v);
-	//create delegate
-	init_streamclass(v);
-	sq_pushregistrytable(v);
-	sq_pushstring(v,reg_name,-1);
-	sq_pushstring(v,_SC("std_stream"),-1);
-	if(SQ_SUCCEEDED(sq_get(v,-3))) {
-		sq_newclass(v,SQTrue);
-		sq_settypetag(v,-1,typetag);
-		SQInteger i = 0;
-		while(methods[i].name != 0) {
-			const SQRegFunction &f = methods[i];
-			sq_pushstring(v,f.name,-1);
-			sq_newclosure(v,f.f,0);
-			sq_setparamscheck(v,f.nparamscheck,f.typemask);
-			sq_setnativeclosurename(v,-1,f.name);
-			sq_newslot(v,-3,SQFalse);
-			i++;
-		}
-		sq_newslot(v,-3,SQFalse);
-		sq_pop(v,1);
-
-		i = 0;
-		while(globals[i].name!=0)
-		{
-			const SQRegFunction &f = globals[i];
-			sq_pushstring(v,f.name,-1);
-			sq_newclosure(v,f.f,0);
-			sq_setparamscheck(v,f.nparamscheck,f.typemask);
-			sq_setnativeclosurename(v,-1,f.name);
-			sq_newslot(v,-3,SQFalse);
-			i++;
-		}
-		//register the class in the target table
-		sq_pushstring(v,name,-1);
-		sq_pushregistrytable(v);
-		sq_pushstring(v,reg_name,-1);
-		sq_get(v,-2);
-		sq_remove(v,-2);
-		sq_newslot(v,-3,SQFalse);
-
-		sq_settop(v,top);
-		return SQ_OK;
-	}
-	sq_settop(v,top);
-	return SQ_ERROR;
-}
+void init_streamclass(HSQUIRRELVM v)
+{
+	sq_pushregistrytable(v);
+	sq_pushstring(v,SQSTD_STREAM_TYPE_TAG,-1);
+	if(SQ_FAILED(sq_get(v,-2))) {
+		sq_pushstring(v,SQSTD_STREAM_TYPE_TAG,-1);
+		sq_newclass(v,SQFalse);
+		sq_settypetag(v,-1,(SQUserPointer)SQSTD_STREAM_TYPE_TAG);
+		SQInteger i = 0;
+		while(_stream_methods[i].name != 0) {
+			SQRegFunction &f = _stream_methods[i];
+			sq_pushstring(v,f.name,-1);
+			sq_newclosure(v,f.f,0);
+			sq_setparamscheck(v,f.nparamscheck,f.typemask);
+			sq_newslot(v,-3,SQFalse);
+			i++;
+		}
+		sq_newslot(v,-3,SQFalse);
+		sq_pushroottable(v);
+		sq_pushstring(v,_SC("stream"),-1);
+		sq_pushstring(v,_SC("std_stream"),-1);
+		sq_get(v,-4);
+		sq_newslot(v,-3,SQFalse);
+		sq_pop(v,1);
+	}
+	else {
+		sq_pop(v,1); //result
+	}
+	sq_pop(v,1);
+}
+
+SQRESULT declare_stream(HSQUIRRELVM v,const SQChar* name,SQUserPointer typetag,const SQChar* reg_name,const SQRegFunction *methods,const SQRegFunction *globals)
+{
+	if(sq_gettype(v,-1) != OT_TABLE)
+		return sq_throwerror(v,_SC("table expected"));
+	SQInteger top = sq_gettop(v);
+	//create delegate
+	init_streamclass(v);
+	sq_pushregistrytable(v);
+	sq_pushstring(v,reg_name,-1);
+	sq_pushstring(v,_SC("std_stream"),-1);
+	if(SQ_SUCCEEDED(sq_get(v,-3))) {
+		sq_newclass(v,SQTrue);
+		sq_settypetag(v,-1,typetag);
+		SQInteger i = 0;
+		while(methods[i].name != 0) {
+			const SQRegFunction &f = methods[i];
+			sq_pushstring(v,f.name,-1);
+			sq_newclosure(v,f.f,0);
+			sq_setparamscheck(v,f.nparamscheck,f.typemask);
+			sq_setnativeclosurename(v,-1,f.name);
+			sq_newslot(v,-3,SQFalse);
+			i++;
+		}
+		sq_newslot(v,-3,SQFalse);
+		sq_pop(v,1);
+
+		i = 0;
+		while(globals[i].name!=0)
+		{
+			const SQRegFunction &f = globals[i];
+			sq_pushstring(v,f.name,-1);
+			sq_newclosure(v,f.f,0);
+			sq_setparamscheck(v,f.nparamscheck,f.typemask);
+			sq_setnativeclosurename(v,-1,f.name);
+			sq_newslot(v,-3,SQFalse);
+			i++;
+		}
+		//register the class in the target table
+		sq_pushstring(v,name,-1);
+		sq_pushregistrytable(v);
+		sq_pushstring(v,reg_name,-1);
+		sq_get(v,-2);
+		sq_remove(v,-2);
+		sq_newslot(v,-3,SQFalse);
+
+		sq_settop(v,top);
+		return SQ_OK;
+	}
+	sq_settop(v,top);
+	return SQ_ERROR;
+}

+ 1 - 0
SquiLu/sqstdlib/sqstdstream.h

@@ -7,6 +7,7 @@ SQInteger _stream_readline(HSQUIRRELVM v);
 SQInteger _stream_readbytes(HSQUIRRELVM v);
 SQInteger _stream_readn(HSQUIRRELVM v);
 SQInteger _stream_read(HSQUIRRELVM v);
+SQInteger _stream_readall(HSQUIRRELVM v);
 SQInteger _stream_gets(HSQUIRRELVM v);
 SQInteger _stream_writeblob(HSQUIRRELVM v);
 SQInteger _stream_writebytes(HSQUIRRELVM v);