-/* see copyright notice in squirrel.h */\r
-#include <new>\r
-#include <stdio.h>\r
-#include <squirrel.h>\r
-#include <sqstdio.h>\r
-#include "sqstdstream.h"\r
-\r
-#define SQSTD_FILE_TYPE_TAG (SQSTD_STREAM_TYPE_TAG | 0x00000001)\r
-//basic API\r
-SQFILE sqstd_fopen(const SQChar *filename ,const SQChar *mode)\r
-{\r
-#ifndef _UNICODE\r
- return (SQFILE)fopen(filename,mode);\r
-#else\r
- return (SQFILE)_wfopen(filename,mode);\r
-#endif\r
-}\r
-\r
-SQInteger sqstd_fread(void* buffer, SQInteger size, SQInteger count, SQFILE file)\r
-{\r
- return (SQInteger)fread(buffer,size,count,(FILE *)file);\r
-}\r
-\r
-SQInteger sqstd_fwrite(const SQUserPointer buffer, SQInteger size, SQInteger count, SQFILE file)\r
-{\r
- return (SQInteger)fwrite(buffer,size,count,(FILE *)file);\r
-}\r
-\r
-SQInteger sqstd_fseek(SQFILE file, long offset, int origin)\r
-{\r
- int realorigin;\r
- switch(origin) {\r
- case SQ_SEEK_CUR: realorigin = SEEK_CUR; break;\r
- case SQ_SEEK_END: realorigin = SEEK_END; break;\r
- case SQ_SEEK_SET: realorigin = SEEK_SET; break;\r
- default: return -1; //failed\r
- }\r
- return fseek((FILE *)file,offset,realorigin);\r
-}\r
-\r
-long sqstd_ftell(SQFILE file)\r
-{\r
- return ftell((FILE *)file);\r
-}\r
-\r
-SQInteger sqstd_fflush(SQFILE file)\r
-{\r
- return fflush((FILE *)file);\r
-}\r
-\r
-SQInteger sqstd_fclose(SQFILE file)\r
-{\r
- return fclose((FILE *)file);\r
-}\r
-\r
-SQInteger sqstd_feof(SQFILE file)\r
-{\r
- return feof((FILE *)file);\r
-}\r
-\r
-//File\r
-struct SQFile : public SQStream {\r
- SQFile() { _handle = NULL; _owns = false;}\r
- SQFile(SQFILE file, bool owns) { _handle = file; _owns = owns;}\r
- ~SQFile() { Close(); }\r
- bool Open(const SQChar *filename ,const SQChar *mode) {\r
- Close();\r
- if(_handle = sqstd_fopen(filename,mode)) {\r
- _owns = true;\r
- return true;\r
- }\r
- return false;\r
- }\r
- void Close() {\r
- if(_handle && _owns) { \r
- sqstd_fclose(_handle);\r
- _handle = NULL;\r
- _owns = false;\r
- }\r
- }\r
- SQInteger Read(void *buffer,SQInteger size) {\r
- return sqstd_fread(buffer,1,size,_handle);\r
- }\r
- SQInteger Write(void *buffer,SQInteger size) {\r
- return sqstd_fwrite(buffer,1,size,_handle);\r
- }\r
- int Flush() {\r
- return sqstd_fflush(_handle);\r
- }\r
- long Tell() {\r
- return sqstd_ftell(_handle);\r
- }\r
- SQInteger Len() {\r
- int prevpos=Tell();\r
- Seek(0,SQ_SEEK_END);\r
- int size=Tell();\r
- Seek(prevpos,SQ_SEEK_SET);\r
- return size;\r
- }\r
- SQInteger Seek(long offset, int origin) {\r
- return sqstd_fseek(_handle,offset,origin);\r
- }\r
- bool IsValid() { return _handle?true:false; }\r
- bool EOS() { return Tell()==Len()?true:false;}\r
- SQFILE GetHandle() {return _handle;}\r
-private:\r
- SQFILE _handle;\r
- bool _owns;\r
-};\r
-\r
-static int _file__typeof(HSQUIRRELVM v)\r
-{\r
- sq_pushstring(v,_SC("file"),-1);\r
- return 1;\r
-}\r
-\r
-static int _file_releasehook(SQUserPointer p, int size)\r
-{\r
- SQFile *self = (SQFile*)p;\r
- delete self;\r
- return 1;\r
-}\r
-\r
-static int _file_constructor(HSQUIRRELVM v)\r
-{\r
- const SQChar *filename,*mode;\r
- bool owns = true;\r
- SQFile *f;\r
- SQFILE newf;\r
- if(sq_gettype(v,2) == OT_STRING && sq_gettype(v,3) == OT_STRING) {\r
- sq_getstring(v, 2, &filename);\r
- sq_getstring(v, 3, &mode);\r
- newf = sqstd_fopen(filename, mode);\r
- if(!newf) return sq_throwerror(v, _SC("cannot open file"));\r
- } else if(sq_gettype(v,2) == OT_USERPOINTER) {\r
- owns = !(sq_gettype(v,3) == OT_NULL);\r
- sq_getuserpointer(v,2,&newf);\r
- } else {\r
- return sq_throwerror(v,_SC("wrong parameter"));\r
- }\r
- f = new SQFile(newf,owns);\r
- if(SQ_FAILED(sq_setinstanceup(v,1,f))) {\r
- delete f;\r
- return sq_throwerror(v, _SC("cannot create blob with negative size"));\r
- }\r
- sq_setreleasehook(v,1,_file_releasehook);\r
- return 0;\r
-}\r
-\r
-//bindings\r
-#define _DECL_FILE_FUNC(name,nparams,typecheck) {_SC(#name),_file_##name,nparams,typecheck}\r
-static SQRegFunction _file_methods[] = {\r
- _DECL_FILE_FUNC(constructor,3,_SC("x")),\r
- _DECL_FILE_FUNC(_typeof,1,_SC("x")),\r
- {0,0,0,0},\r
-};\r
-\r
-\r
-\r
-SQRESULT sqstd_createfile(HSQUIRRELVM v, SQFILE file,SQBool own)\r
-{\r
- int top = sq_gettop(v);\r
- sq_pushregistrytable(v);\r
- sq_pushstring(v,_SC("std_file"),-1);\r
- if(SQ_SUCCEEDED(sq_get(v,-2))) {\r
- sq_remove(v,-2); //removes the registry\r
- sq_pushroottable(v); // push the this\r
- sq_pushuserpointer(v,file); //file\r
- if(own){\r
- sq_pushinteger(v,1); //true\r
- }\r
- else{\r
- sq_pushnull(v); //false\r
- }\r
- if(SQ_SUCCEEDED( sq_call(v,3,SQTrue) )) {\r
- sq_remove(v,-2);\r
- return SQ_OK;\r
- }\r
- }\r
- sq_settop(v,top);\r
- return SQ_OK;\r
-}\r
-\r
-SQRESULT sqstd_getfile(HSQUIRRELVM v, int idx, SQFILE *file)\r
-{\r
- SQFile *fileobj = NULL;\r
- if(SQ_SUCCEEDED(sq_getinstanceup(v,idx,(SQUserPointer*)&fileobj,SQSTD_FILE_TYPE_TAG))) {\r
- *file = fileobj->GetHandle();\r
- return SQ_OK;\r
- }\r
- return sq_throwerror(v,_SC("not a file"));\r
-}\r
-\r
-\r
-static SQInteger _io_file_lexfeedASCII(SQUserPointer file)\r
-{\r
- int ret;\r
- char c;\r
- if( ( ret=sqstd_fread(&c,sizeof(c),1,(FILE *)file )>0) )\r
- return c;\r
- return 0;\r
-}\r
-\r
-static SQInteger _io_file_lexfeedWCHAR(SQUserPointer file)\r
-{\r
- int ret;\r
- wchar_t c;\r
- if( ( ret=sqstd_fread(&c,sizeof(c),1,(FILE *)file )>0) )\r
- return (SQChar)c;\r
- return 0;\r
-}\r
-\r
-int file_read(SQUserPointer file,SQUserPointer buf,int size)\r
-{\r
- int ret;\r
- if( ( ret = sqstd_fread(buf,1,size,(SQFILE)file ))!=0 )return ret;\r
- return -1;\r
-}\r
-\r
-int file_write(SQUserPointer file,SQUserPointer p,int size)\r
-{\r
- return sqstd_fwrite(p,1,size,(SQFILE)file);\r
-}\r
-\r
-SQRESULT sqstd_loadfile(HSQUIRRELVM v,const SQChar *filename,SQBool printerror)\r
-{\r
- SQFILE file = sqstd_fopen(filename,_SC("rb"));\r
- int ret;\r
- unsigned short uc;\r
- SQLEXREADFUNC func = _io_file_lexfeedASCII;\r
- if(file && (ret=sqstd_fread(&uc,1,2,file))){\r
- if(ret!=2) {\r
- sqstd_fclose(file);\r
- return sq_throwerror(v,_SC("io error"));\r
- }\r
- if(uc==SQ_BYTECODE_STREAM_TAG) { //BYTECODE\r
- sqstd_fseek(file,0,SQ_SEEK_SET);\r
- if(SQ_SUCCEEDED(sq_readclosure(v,file_read,file))) {\r
- sqstd_fclose(file);\r
- return SQ_OK;\r
- }\r
- }\r
- else { //SCRIPT\r
- if(uc==0xFEFF)\r
- func = _io_file_lexfeedWCHAR;\r
- else\r
- sqstd_fseek(file,0,SQ_SEEK_SET);\r
-\r
- if(SQ_SUCCEEDED(sq_compile(v,func,file,filename,printerror))){\r
- sqstd_fclose(file);\r
- return SQ_OK;\r
- }\r
- }\r
- sqstd_fclose(file);\r
- return SQ_ERROR;\r
- }\r
- return sq_throwerror(v,_SC("cannot open the file"));\r
-}\r
-\r
-SQRESULT sqstd_dofile(HSQUIRRELVM v,const SQChar *filename,SQBool retval,SQBool printerror)\r
-{\r
- if(SQ_SUCCEEDED(sqstd_loadfile(v,filename,printerror))) {\r
- sq_push(v,-2);\r
- int ntop = sq_gettop(v);\r
- if(SQ_SUCCEEDED(sq_call(v,1,retval))) {\r
- sq_remove(v,retval?-2:-1); //removes the closure\r
- return 1;\r
- }\r
- sq_pop(v,1); //removes the closure\r
- }\r
- return SQ_ERROR;\r
-}\r
-\r
-SQRESULT sqstd_writeclosuretofile(HSQUIRRELVM v,const SQChar *filename)\r
-{\r
- SQFILE file = sqstd_fopen(filename,_SC("wb+"));\r
- if(!file) return sq_throwerror(v,_SC("cannot open the file"));\r
- if(SQ_SUCCEEDED(sq_writeclosure(v,file_write,file))) {\r
- sqstd_fclose(file);\r
- return SQ_OK;\r
- }\r
- sqstd_fclose(file);\r
- return SQ_ERROR; //forward the error\r
-}\r
-\r
-int _g_io_loadfile(HSQUIRRELVM v)\r
-{\r
- const SQChar *filename;\r
- SQBool printerror = SQFalse;\r
- sq_getstring(v,2,&filename);\r
- if(sq_gettop(v) >= 3) {\r
- sq_getbool(v,3,&printerror);\r
- }\r
- if(SQ_SUCCEEDED(sqstd_loadfile(v,filename,printerror)))\r
- return 1;\r
- return SQ_ERROR; //propagates the error\r
-}\r
-\r
-int _g_io_dofile(HSQUIRRELVM v)\r
-{\r
- const SQChar *filename;\r
- SQBool printerror = SQFalse;\r
- sq_getstring(v,2,&filename);\r
- if(sq_gettop(v) >= 3) {\r
- sq_getbool(v,3,&printerror);\r
- }\r
- sq_push(v,1); //repush the this\r
- if(SQ_SUCCEEDED(sqstd_dofile(v,filename,SQTrue,printerror)))\r
- return 1;\r
- return SQ_ERROR; //propagates the error\r
-}\r
-\r
-#define _DECL_GLOBALIO_FUNC(name,nparams,typecheck) {_SC(#name),_g_io_##name,nparams,typecheck}\r
-static SQRegFunction iolib_funcs[]={\r
- _DECL_GLOBALIO_FUNC(loadfile,-2,_SC(".sb")),\r
- _DECL_GLOBALIO_FUNC(dofile,-2,_SC(".sb")),\r
- {0,0}\r
-};\r
-\r
-SQRESULT sqstd_register_iolib(HSQUIRRELVM v)\r
-{\r
- int top = sq_gettop(v);\r
- //create delegate\r
- declare_stream(v,_SC("file"),SQSTD_FILE_TYPE_TAG,_SC("std_file"),_file_methods,iolib_funcs);\r
- sq_pushstring(v,_SC("stdout"),-1);\r
- sqstd_createfile(v,stdout,0);\r
- sq_createslot(v,-3);\r
- sq_pushstring(v,_SC("stdin"),-1);\r
- sqstd_createfile(v,stdin,0);\r
- sq_createslot(v,-3);\r
- sq_pushstring(v,_SC("stderr"),-1);\r
- sqstd_createfile(v,stderr,0);\r
- sq_createslot(v,-3);\r
- sq_settop(v,top);\r
- return SQ_OK;\r
-}\r
+/* see copyright notice in squirrel.h */
+#include <new>
+#include <stdio.h>
+#include <squirrel.h>
+#include <sqstdio.h>
+#include "sqstdstream.h"
+
+#define SQSTD_FILE_TYPE_TAG (SQSTD_STREAM_TYPE_TAG | 0x00000001)
+//basic API
+SQFILE sqstd_fopen(const SQChar *filename ,const SQChar *mode)
+{
+#ifndef SQUNICODE
+ return (SQFILE)fopen(filename,mode);
+#else
+ return (SQFILE)_wfopen(filename,mode);
+#endif
+}
+
+SQInteger sqstd_fread(void* buffer, SQInteger size, SQInteger count, SQFILE file)
+{
+ return (SQInteger)fread(buffer,size,count,(FILE *)file);
+}
+
+SQInteger sqstd_fwrite(const SQUserPointer buffer, SQInteger size, SQInteger count, SQFILE file)
+{
+ return (SQInteger)fwrite(buffer,size,count,(FILE *)file);
+}
+
+SQInteger sqstd_fseek(SQFILE file, SQInteger offset, SQInteger origin)
+{
+ SQInteger realorigin;
+ switch(origin) {
+ case SQ_SEEK_CUR: realorigin = SEEK_CUR; break;
+ case SQ_SEEK_END: realorigin = SEEK_END; break;
+ case SQ_SEEK_SET: realorigin = SEEK_SET; break;
+ default: return -1; //failed
+ }
+ return fseek((FILE *)file,(long)offset,(int)realorigin);
+}
+
+SQInteger sqstd_ftell(SQFILE file)
+{
+ return ftell((FILE *)file);
+}
+
+SQInteger sqstd_fflush(SQFILE file)
+{
+ return fflush((FILE *)file);
+}
+
+SQInteger sqstd_fclose(SQFILE file)
+{
+ return fclose((FILE *)file);
+}
+
+SQInteger sqstd_feof(SQFILE file)
+{
+ return feof((FILE *)file);
+}
+
+//File
+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) {
+ Close();
+ if( (_handle = sqstd_fopen(filename,mode)) ) {
+ _owns = true;
+ return true;
+ }
+ return false;
+ }
+ void Close() {
+ if(_handle && _owns) {
+ sqstd_fclose(_handle);
+ _handle = NULL;
+ _owns = false;
+ }
+ }
+ 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 Flush() {
+ return sqstd_fflush(_handle);
+ }
+ SQInteger Tell() {
+ return sqstd_ftell(_handle);
+ }
+ SQInteger Len() {
+ SQInteger prevpos=Tell();
+ Seek(0,SQ_SEEK_END);
+ SQInteger size=Tell();
+ Seek(prevpos,SQ_SEEK_SET);
+ return size;
+ }
+ SQInteger Seek(SQInteger offset, SQInteger origin) {
+ return sqstd_fseek(_handle,offset,origin);
+ }
+ bool IsValid() { return _handle?true:false; }
+ bool EOS() { return Tell()==Len()?true:false;}
+ SQFILE GetHandle() {return _handle;}
+private:
+ SQFILE _handle;
+ bool _owns;
+};
+
+static SQInteger _file__typeof(HSQUIRRELVM v)
+{
+ sq_pushstring(v,_SC("file"),-1);
+ return 1;
+}
+
+static SQInteger _file_releasehook(SQUserPointer p, SQInteger size)
+{
+ SQFile *self = (SQFile*)p;
+ delete self;
+ return 1;
+}
+
+static SQInteger _file_constructor(HSQUIRRELVM v)
+{
+ const SQChar *filename,*mode;
+ bool owns = true;
+ SQFile *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 = sqstd_fopen(filename, mode);
+ if(!newf) return sq_throwerror(v, _SC("cannot open file"));
+ } else if(sq_gettype(v,2) == OT_USERPOINTER) {
+ owns = !(sq_gettype(v,3) == OT_NULL);
+ sq_getuserpointer(v,2,&newf);
+ } else {
+ return sq_throwerror(v,_SC("wrong parameter"));
+ }
+ f = new SQFile(newf,owns);
+ if(SQ_FAILED(sq_setinstanceup(v,1,f))) {
+ delete f;
+ return sq_throwerror(v, _SC("cannot create blob with negative size"));
+ }
+ sq_setreleasehook(v,1,_file_releasehook);
+ return 0;
+}
+
+//bindings
+#define _DECL_FILE_FUNC(name,nparams,typecheck) {_SC(#name),_file_##name,nparams,typecheck}
+static SQRegFunction _file_methods[] = {
+ _DECL_FILE_FUNC(constructor,3,_SC("x")),
+ _DECL_FILE_FUNC(_typeof,1,_SC("x")),
+ {0,0,0,0},
+};
+
+
+
+SQRESULT sqstd_createfile(HSQUIRRELVM v, SQFILE file,SQBool own)
+{
+ SQInteger top = sq_gettop(v);
+ sq_pushregistrytable(v);
+ sq_pushstring(v,_SC("std_file"),-1);
+ if(SQ_SUCCEEDED(sq_get(v,-2))) {
+ sq_remove(v,-2); //removes the registry
+ sq_pushroottable(v); // push the this
+ sq_pushuserpointer(v,file); //file
+ if(own){
+ sq_pushinteger(v,1); //true
+ }
+ else{
+ sq_pushnull(v); //false
+ }
+ if(SQ_SUCCEEDED( sq_call(v,3,SQTrue,SQFalse) )) {
+ sq_remove(v,-2);
+ return SQ_OK;
+ }
+ }
+ sq_settop(v,top);
+ return SQ_OK;
+}
+
+SQRESULT sqstd_getfile(HSQUIRRELVM v, SQInteger idx, SQFILE *file)
+{
+ SQFile *fileobj = NULL;
+ if(SQ_SUCCEEDED(sq_getinstanceup(v,idx,(SQUserPointer*)&fileobj,(SQUserPointer)SQSTD_FILE_TYPE_TAG))) {
+ *file = fileobj->GetHandle();
+ return SQ_OK;
+ }
+ return sq_throwerror(v,_SC("not a file"));
+}
+
+
+
+static SQInteger _io_file_lexfeed_ASCII(SQUserPointer file)
+{
+ SQInteger ret;
+ char c;
+ if( ( ret=sqstd_fread(&c,sizeof(c),1,(FILE *)file )>0) )
+ return c;
+ return 0;
+}
+
+static SQInteger _io_file_lexfeed_UTF8(SQUserPointer file)
+{
+#define READ() \
+ if(sqstd_fread(&inchar,sizeof(inchar),1,(FILE *)file) != 1) \
+ return 0;
+
+ static const SQInteger utf8_lengths[16] =
+ {
+ 1,1,1,1,1,1,1,1, /* 0000 to 0111 : 1 byte (plain ASCII) */
+ 0,0,0,0, /* 1000 to 1011 : not valid */
+ 2,2, /* 1100, 1101 : 2 bytes */
+ 3, /* 1110 : 3 bytes */
+ 4 /* 1111 :4 bytes */
+ };
+ static unsigned char byte_masks[5] = {0,0,0x1f,0x0f,0x07};
+ unsigned char inchar;
+ SQInteger c = 0;
+ READ();
+ c = inchar;
+ //
+ if(c >= 0x80) {
+ SQInteger tmp;
+ SQInteger codelen = utf8_lengths[c>>4];
+ if(codelen == 0)
+ return 0;
+ //"invalid UTF-8 stream";
+ tmp = c&byte_masks[codelen];
+ for(SQInteger n = 0; n < codelen-1; n++) {
+ tmp<<=6;
+ READ();
+ tmp |= inchar & 0x3F;
+ }
+ c = tmp;
+ }
+ return c;
+}
+
+static SQInteger _io_file_lexfeed_UCS2_LE(SQUserPointer file)
+{
+ SQInteger ret;
+ wchar_t c;
+ if( ( ret=sqstd_fread(&c,sizeof(c),1,(FILE *)file )>0) )
+ return (SQChar)c;
+ return 0;
+}
+
+static SQInteger _io_file_lexfeed_UCS2_BE(SQUserPointer file)
+{
+ SQInteger ret;
+ unsigned short c;
+ if( ( ret=sqstd_fread(&c,sizeof(c),1,(FILE *)file )>0) ) {
+ c = ((c>>8)&0x00FF)| ((c<<8)&0xFF00);
+ return (SQChar)c;
+ }
+ return 0;
+}
+
+SQInteger file_read(SQUserPointer file,SQUserPointer buf,SQInteger size)
+{
+ SQInteger ret;
+ if( ( ret = sqstd_fread(buf,1,size,(SQFILE)file ))!=0 )return ret;
+ return -1;
+}
+
+SQInteger file_write(SQUserPointer file,SQUserPointer p,SQInteger size)
+{
+ return sqstd_fwrite(p,1,size,(SQFILE)file);
+}
+
+SQRESULT sqstd_loadfile(HSQUIRRELVM v,const SQChar *filename,SQBool printerror)
+{
+ SQFILE file = sqstd_fopen(filename,_SC("rb"));
+ SQInteger ret;
+ unsigned short us;
+ unsigned char uc;
+ SQLEXREADFUNC func = _io_file_lexfeed_ASCII;
+ if(file){
+ ret = sqstd_fread(&us,1,2,file);
+ if(ret != 2) {
+ //probably an empty file
+ us = 0;
+ }
+ if(us == SQ_BYTECODE_STREAM_TAG) { //BYTECODE
+ sqstd_fseek(file,0,SQ_SEEK_SET);
+ if(SQ_SUCCEEDED(sq_readclosure(v,file_read,file))) {
+ sqstd_fclose(file);
+ return SQ_OK;
+ }
+ }
+ else { //SCRIPT
+ switch(us)
+ {
+ //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"));
+ }
+ if(uc != 0xBF) {
+ sqstd_fclose(file);
+ return sq_throwerror(v,_SC("Unrecognozed ecoding"));
+ }
+ func = _io_file_lexfeed_UTF8;
+ break;//UTF-8 ;
+ default: sqstd_fseek(file,0,SQ_SEEK_SET); break; // ascii
+ }
+
+ if(SQ_SUCCEEDED(sq_compile(v,func,file,filename,printerror))){
+ sqstd_fclose(file);
+ return SQ_OK;
+ }
+ }
+ sqstd_fclose(file);
+ return SQ_ERROR;
+ }
+ return sq_throwerror(v,_SC("cannot open the file"));
+}
+
+SQRESULT sqstd_dofile(HSQUIRRELVM v,const SQChar *filename,SQBool retval,SQBool printerror)
+{
+ if(SQ_SUCCEEDED(sqstd_loadfile(v,filename,printerror))) {
+ sq_push(v,-2);
+ 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;
+}
+
+SQRESULT sqstd_writeclosuretofile(HSQUIRRELVM v,const SQChar *filename)
+{
+ SQFILE file = sqstd_fopen(filename,_SC("wb+"));
+ if(!file) return sq_throwerror(v,_SC("cannot open the file"));
+ if(SQ_SUCCEEDED(sq_writeclosure(v,file_write,file))) {
+ sqstd_fclose(file);
+ return SQ_OK;
+ }
+ sqstd_fclose(file);
+ return SQ_ERROR; //forward the error
+}
+
+SQInteger _g_io_loadfile(HSQUIRRELVM v)
+{
+ const SQChar *filename;
+ SQBool printerror = SQFalse;
+ sq_getstring(v,2,&filename);
+ if(sq_gettop(v) >= 3) {
+ sq_getbool(v,3,&printerror);
+ }
+ if(SQ_SUCCEEDED(sqstd_loadfile(v,filename,printerror)))
+ return 1;
+ return SQ_ERROR; //propagates the error
+}
+
+SQInteger _g_io_writeclosuretofile(HSQUIRRELVM v)
+{
+ const SQChar *filename;
+ sq_getstring(v,2,&filename);
+ if(SQ_SUCCEEDED(sqstd_writeclosuretofile(v,filename)))
+ return 1;
+ return SQ_ERROR; //propagates the error
+}
+
+SQInteger _g_io_dofile(HSQUIRRELVM v)
+{
+ const SQChar *filename;
+ SQBool printerror = SQFalse;
+ sq_getstring(v,2,&filename);
+ if(sq_gettop(v) >= 3) {
+ sq_getbool(v,3,&printerror);
+ }
+ sq_push(v,1); //repush the this
+ if(SQ_SUCCEEDED(sqstd_dofile(v,filename,SQTrue,printerror)))
+ return 1;
+ return SQ_ERROR; //propagates the error
+}
+
+#define _DECL_GLOBALIO_FUNC(name,nparams,typecheck) {_SC(#name),_g_io_##name,nparams,typecheck}
+static SQRegFunction iolib_funcs[]={
+ _DECL_GLOBALIO_FUNC(loadfile,-2,_SC(".sb")),
+ _DECL_GLOBALIO_FUNC(dofile,-2,_SC(".sb")),
+ _DECL_GLOBALIO_FUNC(writeclosuretofile,3,_SC(".sc")),
+ {0,0}
+};
+
+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);
+ sqstd_createfile(v,stdout,SQFalse);
+ sq_createslot(v,-3);
+ sq_pushstring(v,_SC("stdin"),-1);
+ sqstd_createfile(v,stdin,SQFalse);
+ sq_createslot(v,-3);
+ sq_pushstring(v,_SC("stderr"),-1);
+ sqstd_createfile(v,stderr,SQFalse);
+ sq_createslot(v,-3);
+ sq_settop(v,top);
+ return SQ_OK;
+}