1 /* see copyright notice in squirrel.h */
6 #include "sqstdstream.h"
8 #define SQSTD_FILE_TYPE_TAG (SQSTD_STREAM_TYPE_TAG | 0x00000001)
10 SQFILE sqstd_fopen(const SQChar *filename ,const SQChar *mode)
13 return (SQFILE)fopen(filename,mode);
15 return (SQFILE)_wfopen(filename,mode);
19 SQInteger sqstd_fread(void* buffer, SQInteger size, SQInteger count, SQFILE file)
21 return (SQInteger)fread(buffer,size,count,(FILE *)file);
24 SQInteger sqstd_fwrite(const SQUserPointer buffer, SQInteger size, SQInteger count, SQFILE file)
26 return (SQInteger)fwrite(buffer,size,count,(FILE *)file);
29 SQInteger sqstd_fseek(SQFILE file, long offset, int origin)
33 case SQ_SEEK_CUR: realorigin = SEEK_CUR; break;
34 case SQ_SEEK_END: realorigin = SEEK_END; break;
35 case SQ_SEEK_SET: realorigin = SEEK_SET; break;
36 default: return -1; //failed
38 return fseek((FILE *)file,offset,realorigin);
41 long sqstd_ftell(SQFILE file)
43 return ftell((FILE *)file);
46 SQInteger sqstd_fflush(SQFILE file)
48 return fflush((FILE *)file);
51 SQInteger sqstd_fclose(SQFILE file)
53 return fclose((FILE *)file);
56 SQInteger sqstd_feof(SQFILE file)
58 return feof((FILE *)file);
62 struct SQFile : public SQStream {
63 SQFile() { _handle = NULL; _owns = false;}
64 SQFile(SQFILE file, bool owns) { _handle = file; _owns = owns;}
65 virtual ~SQFile() { Close(); }
66 bool Open(const SQChar *filename ,const SQChar *mode) {
68 if( (_handle = sqstd_fopen(filename,mode)) ) {
75 if(_handle && _owns) {
76 sqstd_fclose(_handle);
81 SQInteger Read(void *buffer,SQInteger size) {
82 return sqstd_fread(buffer,1,size,_handle);
84 SQInteger Write(void *buffer,SQInteger size) {
85 return sqstd_fwrite(buffer,1,size,_handle);
88 return sqstd_fflush(_handle);
91 return sqstd_ftell(_handle);
97 Seek(prevpos,SQ_SEEK_SET);
100 SQInteger Seek(long offset, int origin) {
101 return sqstd_fseek(_handle,offset,origin);
103 bool IsValid() { return _handle?true:false; }
104 bool EOS() { return Tell()==Len()?true:false;}
105 SQFILE GetHandle() {return _handle;}
111 static int _file__typeof(HSQUIRRELVM v)
113 sq_pushstring(v,_SC("file"),-1);
117 static int _file_releasehook(SQUserPointer p, int size)
120 SQFile *self = (SQFile*)p;
125 static int _file_constructor(HSQUIRRELVM v)
127 const SQChar *filename,*mode;
131 if(sq_gettype(v,2) == OT_STRING && sq_gettype(v,3) == OT_STRING) {
132 sq_getstring(v, 2, &filename);
133 sq_getstring(v, 3, &mode);
134 newf = sqstd_fopen(filename, mode);
135 if(!newf) return sq_throwerror(v, _SC("cannot open file"));
136 } else if(sq_gettype(v,2) == OT_USERPOINTER) {
137 owns = !(sq_gettype(v,3) == OT_NULL);
138 sq_getuserpointer(v,2,&newf);
140 return sq_throwerror(v,_SC("wrong parameter"));
142 f = new SQFile(newf,owns);
143 if(SQ_FAILED(sq_setinstanceup(v,1,f))) {
145 return sq_throwerror(v, _SC("cannot create blob with negative size"));
147 sq_setreleasehook(v,1,_file_releasehook);
152 #define _DECL_FILE_FUNC(name,nparams,typecheck) {_SC(#name),_file_##name,nparams,typecheck}
153 static SQRegFunction _file_methods[] = {
154 _DECL_FILE_FUNC(constructor,3,_SC("x")),
155 _DECL_FILE_FUNC(_typeof,1,_SC("x")),
161 SQRESULT sqstd_createfile(HSQUIRRELVM v, SQFILE file,SQBool own)
163 int top = sq_gettop(v);
164 sq_pushregistrytable(v);
165 sq_pushstring(v,_SC("std_file"),-1);
166 if(SQ_SUCCEEDED(sq_get(v,-2))) {
167 sq_remove(v,-2); //removes the registry
168 sq_pushroottable(v); // push the this
169 sq_pushuserpointer(v,file); //file
171 sq_pushinteger(v,1); //true
174 sq_pushnull(v); //false
176 if(SQ_SUCCEEDED( sq_call(v,3,SQTrue) )) {
185 SQRESULT sqstd_getfile(HSQUIRRELVM v, int idx, SQFILE *file)
187 SQFile *fileobj = NULL;
188 if(SQ_SUCCEEDED(sq_getinstanceup(v,idx,(SQUserPointer*)&fileobj,SQSTD_FILE_TYPE_TAG))) {
189 *file = fileobj->GetHandle();
192 return sq_throwerror(v,_SC("not a file"));
196 static SQInteger _io_file_lexfeedASCII(SQUserPointer file)
200 if( ( ret=sqstd_fread(&c,sizeof(c),1,(FILE *)file )>0) )
205 static SQInteger _io_file_lexfeedWCHAR(SQUserPointer file)
209 if( ( ret=sqstd_fread(&c,sizeof(c),1,(FILE *)file )>0) )
214 int file_read(SQUserPointer file,SQUserPointer buf,int size)
217 if( ( ret = sqstd_fread(buf,1,size,(SQFILE)file ))!=0 )return ret;
221 int file_write(SQUserPointer file,SQUserPointer p,int size)
223 return sqstd_fwrite(p,1,size,(SQFILE)file);
226 SQRESULT sqstd_loadfile(HSQUIRRELVM v,const SQChar *filename,SQBool printerror)
228 SQFILE file = sqstd_fopen(filename,_SC("rb"));
231 SQLEXREADFUNC func = _io_file_lexfeedASCII;
232 if(file && (ret=sqstd_fread(&uc,1,2,file))){
235 return sq_throwerror(v,_SC("io error"));
237 if(uc==SQ_BYTECODE_STREAM_TAG) { //BYTECODE
238 sqstd_fseek(file,0,SQ_SEEK_SET);
239 if(SQ_SUCCEEDED(sq_readclosure(v,file_read,file))) {
246 func = _io_file_lexfeedWCHAR;
248 sqstd_fseek(file,0,SQ_SEEK_SET);
250 if(SQ_SUCCEEDED(sq_compile(v,func,file,filename,printerror))){
258 return sq_throwerror(v,_SC("cannot open the file"));
261 SQRESULT sqstd_dofile(HSQUIRRELVM v,const SQChar *filename,SQBool retval,SQBool printerror)
263 if(SQ_SUCCEEDED(sqstd_loadfile(v,filename,printerror))) {
265 //int ntop = sq_gettop(v);
266 if(SQ_SUCCEEDED(sq_call(v,1,retval))) {
267 sq_remove(v,retval?-2:-1); //removes the closure
270 sq_pop(v,1); //removes the closure
275 SQRESULT sqstd_writeclosuretofile(HSQUIRRELVM v,const SQChar *filename)
277 SQFILE file = sqstd_fopen(filename,_SC("wb+"));
278 if(!file) return sq_throwerror(v,_SC("cannot open the file"));
279 if(SQ_SUCCEEDED(sq_writeclosure(v,file_write,file))) {
284 return SQ_ERROR; //forward the error
287 int _g_io_loadfile(HSQUIRRELVM v)
289 const SQChar *filename;
290 SQBool printerror = SQFalse;
291 sq_getstring(v,2,&filename);
292 if(sq_gettop(v) >= 3) {
293 sq_getbool(v,3,&printerror);
295 if(SQ_SUCCEEDED(sqstd_loadfile(v,filename,printerror)))
297 return SQ_ERROR; //propagates the error
300 int _g_io_dofile(HSQUIRRELVM v)
302 const SQChar *filename;
303 SQBool printerror = SQFalse;
304 sq_getstring(v,2,&filename);
305 if(sq_gettop(v) >= 3) {
306 sq_getbool(v,3,&printerror);
308 sq_push(v,1); //repush the this
309 if(SQ_SUCCEEDED(sqstd_dofile(v,filename,SQTrue,printerror)))
311 return SQ_ERROR; //propagates the error
314 #define _DECL_GLOBALIO_FUNC(name,nparams,typecheck) {_SC(#name),_g_io_##name,nparams,typecheck}
315 static SQRegFunction iolib_funcs[]={
316 _DECL_GLOBALIO_FUNC(loadfile,-2,_SC(".sb")),
317 _DECL_GLOBALIO_FUNC(dofile,-2,_SC(".sb")),
321 SQRESULT sqstd_register_iolib(HSQUIRRELVM v)
323 int top = sq_gettop(v);
325 declare_stream(v,_SC("file"),SQSTD_FILE_TYPE_TAG,_SC("std_file"),_file_methods,iolib_funcs);
326 sq_pushstring(v,_SC("stdout"),-1);
327 sqstd_createfile(v,stdout,0);
329 sq_pushstring(v,_SC("stdin"),-1);
330 sqstd_createfile(v,stdin,0);
332 sq_pushstring(v,_SC("stderr"),-1);
333 sqstd_createfile(v,stderr,0);