Răsfoiți Sursa

Refactored SQBlob to allow specify size and allocated separately.
Added to streams read and write for strings (only char*) for now, too much a pain to not have this functions.

mingodad 13 ani în urmă
părinte
comite
fae9b56595
6 a modificat fișierele cu 231 adăugiri și 102 ștergeri
  1. 1 1
      include/sqstdio.h
  2. 119 6
      sqstdlib/sqstdblob.cpp
  3. 11 79
      sqstdlib/sqstdblobimpl.h
  4. 61 14
      sqstdlib/sqstdio.cpp
  5. 37 2
      sqstdlib/sqstdstream.cpp
  6. 2 0
      sqstdlib/sqstdstream.h

+ 1 - 1
include/sqstdio.h

@@ -8,7 +8,7 @@
 
 struct SQStream {
 	virtual SQInteger Read(void *buffer, SQInteger size) = 0;
-	virtual SQInteger Write(void *buffer, SQInteger size) = 0;
+	virtual SQInteger Write(const void *buffer, SQInteger size) = 0;
 	virtual SQInteger Flush() = 0;
 	virtual SQInteger Tell() = 0;
 	virtual SQInteger Len() = 0;

+ 119 - 6
sqstdlib/sqstdblob.cpp

@@ -11,6 +11,92 @@
 
 //Blob
 
+SQBlob::SQBlob(SQInteger size, SQInteger allocated) {
+    _size = size;
+    _allocated = allocated > 0 ? 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) {
+    SQInteger size = strlen(zStr);
+    return Write(zStr, size);
+}
+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;
+}
+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 > _allocated)
+            _ptr = _allocated;
+    }
+    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;
+}
 
 #define SETUP_BLOB(v) \
 	SQBlob *self = NULL; \
@@ -125,14 +211,18 @@ static SQInteger _blob_releasehook(SQUserPointer p, SQInteger size)
 static SQInteger _blob_constructor(HSQUIRRELVM v)
 {
 	SQInteger nparam = sq_gettop(v);
-	SQInteger size = 0;
-	if(nparam == 2) {
+	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);
+	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));
@@ -145,9 +235,9 @@ static SQInteger _blob_constructor(HSQUIRRELVM v)
 static SQInteger _blob__cloned(HSQUIRRELVM v)
 {
 	SQBlob *other = NULL;
-	{ 
+	{
 		if(SQ_FAILED(sq_getinstanceup(v,2,(SQUserPointer*)&other,(SQUserPointer)SQSTD_BLOB_TYPE_TAG)))
-			return SQ_ERROR; 
+			return SQ_ERROR;
 	}
 	//SQBlob *thisone = new SQBlob(other->Len());
 	SQBlob *thisone = new (sq_malloc(sizeof(SQBlob)))SQBlob(other->Len());
@@ -161,9 +251,16 @@ static SQInteger _blob__cloned(HSQUIRRELVM v)
 	return 0;
 }
 
+static SQInteger _blob__tostring(HSQUIRRELVM v)
+{
+    SETUP_BLOB(v);
+	sq_pushstring(v, (const SQChar*)self->GetBuf(), self->Len());
+	return 1;
+}
+
 #define _DECL_BLOB_FUNC(name,nparams,typecheck) {_SC(#name),_blob_##name,nparams,typecheck}
 static SQRegFunction _blob_methods[] = {
-	_DECL_BLOB_FUNC(constructor,-1,_SC("xn")),
+	_DECL_BLOB_FUNC(constructor,-1,_SC("xnn")),
 	_DECL_BLOB_FUNC(resize,2,_SC("xn")),
 	_DECL_BLOB_FUNC(swap2,1,_SC("x")),
 	_DECL_BLOB_FUNC(swap4,1,_SC("x")),
@@ -172,6 +269,7 @@ static SQRegFunction _blob_methods[] = {
 	_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")),
 	{0,0,0,0}
 };
 
@@ -249,6 +347,21 @@ SQInteger sqstd_getblobsize(HSQUIRRELVM v,SQInteger idx)
 		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)
 {

+ 11 - 79
sqstdlib/sqstdblobimpl.h

@@ -2,91 +2,23 @@
 #ifndef _SQSTD_BLOBIMPL_H_
 #define _SQSTD_BLOBIMPL_H_
 
+#include "sqstdio.h"
+
 struct SQBlob : public SQStream
 {
-	SQBlob(SQInteger size) {
-		_size = size;
-		_allocated = size;
-		_buf = (unsigned char *)sq_malloc(size);
-		memset(_buf, 0, _size);
-		_ptr = 0;
-		_owns = true;
-	}
-	virtual ~SQBlob() {
-		sq_free(_buf, _allocated);
-	}
-	SQInteger Write(void *buffer, SQInteger size) {
-		if(!CanAdvance(size)) {
-			GrowBufOf(_ptr + size - _size);
-		}
-		memcpy(&_buf[_ptr], buffer, size);
-		_ptr += size;
-		return size;
-	}
-	SQInteger 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;
-	}
-	bool 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 > _allocated)
-				_ptr = _allocated;
-		}
-		return true;
-	}
-	bool 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;
-	}
+	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);
+	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) {
-		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;
-	}
+	SQInteger Seek(SQInteger offset, SQInteger origin);
 	bool IsValid() {
 		return _buf?true:false;
 	}

+ 61 - 14
sqstdlib/sqstdio.cpp

@@ -72,7 +72,7 @@ struct SQFile : public SQStream {
 		return false;
 	}
 	void Close() {
-		if(_handle && _owns) { 
+		if(_handle && _owns) {
 			sqstd_fclose(_handle);
 			_handle = NULL;
 			_owns = false;
@@ -81,8 +81,8 @@ struct SQFile : public SQStream {
 	SQInteger Read(void *buffer,SQInteger size) {
 		return sqstd_fread(buffer,1,size,_handle);
 	}
-	SQInteger Write(void *buffer,SQInteger size) {
-		return sqstd_fwrite(buffer,1,size,_handle);
+	SQInteger Write(const void *buffer,SQInteger size) {
+		return sqstd_fwrite((const SQUserPointer)buffer,1,size,_handle);
 	}
 	SQInteger Flush() {
 		return sqstd_fflush(_handle);
@@ -139,7 +139,7 @@ static SQInteger _file_constructor(HSQUIRRELVM v)
 	} else {
 		return sq_throwerror(v,_SC("wrong parameter"));
 	}
-	
+
 	f = new (sq_malloc(sizeof(SQFile)))SQFile(newf,owns);
 	if(SQ_FAILED(sq_setinstanceup(v,1,f))) {
 		f->~SQFile();
@@ -241,7 +241,7 @@ static SQInteger _io_file_lexfeed_UTF8(SQUserPointer file)
 	if(c >= 0x80) {
 		SQInteger tmp;
 		SQInteger codelen = utf8_lengths[c>>4];
-		if(codelen == 0) 
+		if(codelen == 0)
 			return 0;
 			//"invalid UTF-8 stream";
 		tmp = c&byte_masks[codelen];
@@ -314,14 +314,14 @@ SQRESULT sqstd_loadfile(HSQUIRRELVM v,const SQChar *filename,SQBool printerror)
 				//gotta swap the next 2 lines on BIG endian machines
 				case 0xFFFE: func = _io_file_lexfeed_UCS2_BE; break;//UTF-16 little endian;
 				case 0xFEFF: func = _io_file_lexfeed_UCS2_LE; break;//UTF-16 big endian;
-				case 0xBBEF: 
-					if(sqstd_fread(&uc,1,sizeof(uc),file) == 0) { 
-						sqstd_fclose(file); 
-						return sq_throwerror(v,_SC("io error")); 
+				case 0xBBEF:
+					if(sqstd_fread(&uc,1,sizeof(uc),file) == 0) {
+						sqstd_fclose(file);
+						return sq_throwerror(v,_SC("io error"));
 					}
-					if(uc != 0xBF) { 
-						sqstd_fclose(file); 
-						return sq_throwerror(v,_SC("Unrecognozed ecoding")); 
+					if(uc != 0xBF) {
+						sqstd_fclose(file);
+						return sq_throwerror(v,_SC("Unrecognozed ecoding"));
 					}
 #ifdef SQUNICODE
 					func = _io_file_lexfeed_UTF8;
@@ -390,6 +390,55 @@ SQInteger _g_io_writeclosuretofile(HSQUIRRELVM v)
 	return SQ_ERROR; //propagates the error
 }
 
+#include "sqstdblobimpl.h"
+SQInteger blob_write(SQUserPointer file,SQUserPointer p,SQInteger size);
+SQInteger _g_io_dumpclosure(HSQUIRRELVM v)
+{
+	SQBlob b(0,8192);
+	if(SQ_SUCCEEDED(sq_writeclosure(v,blob_write,&b))) {
+		sq_pushstring(v, (const SQChar*)b.GetBuf(), b.Len());
+		return 1;
+	}
+	return SQ_ERROR; //forward the error
+}
+
+SQInteger blob_read(SQUserPointer file,SQUserPointer p,SQInteger size);
+SQInteger _g_io_loadstring(HSQUIRRELVM v)
+{
+    if(sq_gettype(v, 2) != OT_STRING) return sq_throwerror(v, "string expected as parameter");
+    SQInteger rc, size = sq_getsize(v, 2);
+    const SQChar *dump;
+    sq_getstring(v, 2, &dump);
+    unsigned short tag = *((unsigned short*)dump);
+    if(tag == SQ_BYTECODE_STREAM_TAG){
+        SQBlob b(0, size);
+        b.Write(dump, size);
+        b.Seek(0, SQ_SEEK_SET);
+        rc = sq_readclosure(v, blob_read, &b);
+    }
+    else
+    {
+        rc = sq_compilebuffer(v, dump, size, "dostring", SQFalse);
+    }
+	return rc < 0 ? rc : 1;
+}
+
+SQInteger _g_io_dostring(HSQUIRRELVM v)
+{
+    SQInteger rc = _g_io_loadstring(v);
+    if(rc < 0) return rc;
+    SQBool retval;
+    if(sq_gettop(v) > 2) sq_getbool(v, 3, &retval);
+    else retval = SQFalse;
+    sq_push(v,1); //this environment
+    if(SQ_SUCCEEDED(sq_call(v,1,retval,SQTrue))) {
+        sq_remove(v,retval?-2:-1); //removes the closure
+        return 1;
+    }
+    sq_pop(v,1); //removes the closure
+	return SQ_ERROR; //forward the error
+}
+
 SQInteger _g_io_dofile(HSQUIRRELVM v)
 {
 	const SQChar *filename;
@@ -414,7 +463,6 @@ static SQRegFunction iolib_funcs[]={
 
 SQRESULT sqstd_register_iolib(HSQUIRRELVM v)
 {
-	SQInteger top = sq_gettop(v);
 	//create delegate
 	declare_stream(v,_SC("file"),(SQUserPointer)SQSTD_FILE_TYPE_TAG,_SC("std_file"),_file_methods,iolib_funcs);
 	sq_pushstring(v,_SC("stdout"),-1);
@@ -426,6 +474,5 @@ SQRESULT sqstd_register_iolib(HSQUIRRELVM v)
 	sq_pushstring(v,_SC("stderr"),-1);
 	sqstd_createfile(v,stderr,SQFalse);
 	sq_newslot(v,-3,SQFalse);
-	sq_settop(v,top);
 	return SQ_OK;
 }

+ 37 - 2
sqstdlib/sqstdstream.cpp

@@ -16,6 +16,23 @@
 	if(!self || !self->IsValid())  \
 		return sq_throwerror(v,_SC("the stream is invalid"));
 
+SQInteger _stream_read(HSQUIRRELVM v)
+{
+	SETUP_STREAM(v);
+	SQChar *data;
+	SQInteger size,res;
+	sq_getinteger(v,2,&size);
+	if(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_readblob(HSQUIRRELVM v)
 {
 	SETUP_STREAM(v);
@@ -97,6 +114,22 @@ SQInteger _stream_readn(HSQUIRRELVM v)
 	return 1;
 }
 
+SQInteger _stream_write(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;
@@ -239,8 +272,10 @@ SQInteger _stream_eos(HSQUIRRELVM v)
  }
 
 static SQRegFunction _stream_methods[] = {
+	_DECL_STREAM_FUNC(read,2,_SC("xn")),
 	_DECL_STREAM_FUNC(readblob,2,_SC("xn")),
 	_DECL_STREAM_FUNC(readn,2,_SC("xn")),
+	_DECL_STREAM_FUNC(write,2,_SC("x.")),
 	_DECL_STREAM_FUNC(writeblob,-2,_SC("xx")),
 	_DECL_STREAM_FUNC(writen,3,_SC("xnn")),
 	_DECL_STREAM_FUNC(seek,-2,_SC("xnn")),
@@ -289,7 +324,7 @@ SQRESULT declare_stream(HSQUIRRELVM v,const SQChar* name,SQUserPointer typetag,c
 		return sq_throwerror(v,_SC("table expected"));
 	SQInteger top = sq_gettop(v);
 	//create delegate
-    init_streamclass(v);
+	init_streamclass(v);
 	sq_pushregistrytable(v);
 	sq_pushstring(v,reg_name,-1);
 	sq_pushstring(v,_SC("std_stream"),-1);
@@ -308,7 +343,7 @@ SQRESULT declare_stream(HSQUIRRELVM v,const SQChar* name,SQUserPointer typetag,c
 		}
 		sq_newslot(v,-3,SQFalse);
 		sq_pop(v,1);
-		
+
 		i = 0;
 		while(globals[i].name!=0)
 		{

+ 2 - 0
sqstdlib/sqstdstream.h

@@ -4,8 +4,10 @@
 
 SQInteger _stream_readblob(HSQUIRRELVM v);
 SQInteger _stream_readline(HSQUIRRELVM v);
+SQInteger _stream_readbytes(HSQUIRRELVM v);
 SQInteger _stream_readn(HSQUIRRELVM v);
 SQInteger _stream_writeblob(HSQUIRRELVM v);
+SQInteger _stream_writebytes(HSQUIRRELVM v);
 SQInteger _stream_writen(HSQUIRRELVM v);
 SQInteger _stream_seek(HSQUIRRELVM v);
 SQInteger _stream_tell(HSQUIRRELVM v);