| @@ -0,0 +1,276 @@ | ||
| /* 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) | ||
|
|
||
| //Blob | ||
|
|
||
|
|
||
| #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 SQInteger _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 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 SQInteger _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 SQInteger _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 SQInteger _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 SQInteger _blob__get(HSQUIRRELVM v) | ||
| { | ||
| SETUP_BLOB(v); | ||
| SQInteger idx; | ||
| 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 SQInteger _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 SQInteger _blob__typeof(HSQUIRRELVM v) | ||
| { | ||
| sq_pushstring(v,_SC("blob"),-1); | ||
| return 1; | ||
| } | ||
|
|
||
| static SQInteger _blob_releasehook(SQUserPointer p, SQInteger size) | ||
| { | ||
| SQBlob *self = (SQBlob*)p; | ||
| self->~SQBlob(); | ||
| sq_free(self,sizeof(SQBlob)); | ||
| return 1; | ||
| } | ||
|
|
||
| static SQInteger _blob_constructor(HSQUIRRELVM v) | ||
| { | ||
| SQInteger nparam = sq_gettop(v); | ||
| SQInteger size = 0; | ||
| if(nparam == 2) { | ||
| sq_getinteger(v, 2, &size); | ||
| } | ||
| if(size < 0) return sq_throwerror(v, _SC("cannot create blob with negative size")); | ||
| //SQBlob *b = new SQBlob(size); | ||
|
|
||
| SQBlob *b = new (sq_malloc(sizeof(SQBlob)))SQBlob(size); | ||
| 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 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; | ||
| } | ||
| //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; | ||
| } | ||
|
|
||
| #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(resize,2,_SC("xn")), | ||
| _DECL_BLOB_FUNC(swap2,1,_SC("x")), | ||
| _DECL_BLOB_FUNC(swap4,1,_SC("x")), | ||
| _DECL_BLOB_FUNC(_set,3,_SC("xnn")), | ||
| _DECL_BLOB_FUNC(_get,2,_SC("xn")), | ||
| _DECL_BLOB_FUNC(_typeof,1,_SC("x")), | ||
| _DECL_BLOB_FUNC(_nexti,2,_SC("x")), | ||
| _DECL_BLOB_FUNC(_cloned,2,_SC("xx")), | ||
| {0,0,0,0} | ||
| }; | ||
|
|
||
|
|
||
|
|
||
| //GLOBAL FUNCTIONS | ||
|
|
||
| static SQInteger _g_blob_casti2f(HSQUIRRELVM v) | ||
| { | ||
| SQInteger i; | ||
| sq_getinteger(v,2,&i); | ||
| sq_pushfloat(v,*((SQFloat *)&i)); | ||
| return 1; | ||
| } | ||
|
|
||
| static SQInteger _g_blob_castf2i(HSQUIRRELVM v) | ||
| { | ||
| SQFloat f; | ||
| sq_getfloat(v,2,&f); | ||
| sq_pushinteger(v,*((SQInteger *)&f)); | ||
| return 1; | ||
| } | ||
|
|
||
| static SQInteger _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 SQInteger _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 SQInteger _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")), | ||
| {0,0} | ||
| }; | ||
|
|
||
| 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(); | ||
| } | ||
|
|
||
| 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); | ||
| } |
| @@ -0,0 +1,108 @@ | ||
| /* see copyright notice in squirrel.h */ | ||
| #ifndef _SQSTD_BLOBIMPL_H_ | ||
| #define _SQSTD_BLOBIMPL_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; | ||
| } | ||
| 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; | ||
| } | ||
| 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; } | ||
| private: | ||
| SQInteger _size; | ||
| SQInteger _allocated; | ||
| SQInteger _ptr; | ||
| unsigned char *_buf; | ||
| bool _owns; | ||
| }; | ||
|
|
||
| #endif //_SQSTD_BLOBIMPL_H_ |
| @@ -0,0 +1,384 @@ | ||
| /* 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) | ||
| { | ||
| return (SQFILE)fopen(filename,mode); | ||
| } | ||
|
|
||
| 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; | ||
| self->~SQFile(); | ||
| sq_free(self,sizeof(SQFile)); | ||
| 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 (sq_malloc(sizeof(SQFile)))SQFile(newf,owns); | ||
| if(SQ_FAILED(sq_setinstanceup(v,1,f))) { | ||
| f->~SQFile(); | ||
| sq_free(f,sizeof(SQFile)); | ||
| return sq_throwerror(v, _SC("cannot create blob with negative size")); | ||
| } | ||
| sq_setreleasehook(v,1,_file_releasehook); | ||
| return 0; | ||
| } | ||
|
|
||
| static SQInteger _file_close(HSQUIRRELVM v) | ||
| { | ||
| SQFile *self = NULL; | ||
| if(SQ_SUCCEEDED(sq_getinstanceup(v,1,(SQUserPointer*)&self,(SQUserPointer)SQSTD_FILE_TYPE_TAG)) | ||
| && self != NULL) | ||
| { | ||
| self->Close(); | ||
| } | ||
| 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")), | ||
| _DECL_FILE_FUNC(close,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_PLAIN(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_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_PLAIN; | ||
| 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_PLAIN; | ||
| 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_newslot(v,-3,SQFalse); | ||
| sq_pushstring(v,_SC("stdin"),-1); | ||
| sqstd_createfile(v,stdin,SQFalse); | ||
| sq_newslot(v,-3,SQFalse); | ||
| sq_pushstring(v,_SC("stderr"),-1); | ||
| sqstd_createfile(v,stderr,SQFalse); | ||
| sq_newslot(v,-3,SQFalse); | ||
| sq_settop(v,top); | ||
| return SQ_OK; | ||
| } |
| @@ -0,0 +1,336 @@ | ||
| /* 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" | ||
|
|
||
| #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_readblob(HSQUIRRELVM v) | ||
| { | ||
| SETUP_STREAM(v); | ||
| SQUserPointer data,blobp; | ||
| 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")); | ||
| blobp = sqstd_createblob(v,res); | ||
| memcpy(blobp,data,res); | ||
| 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_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")); | ||
| } | ||
|
|
||
| static SQRegFunction _stream_methods[] = { | ||
| _DECL_STREAM_FUNC(readblob,2,_SC("xn")), | ||
| _DECL_STREAM_FUNC(readn,2,_SC("xn")), | ||
| _DECL_STREAM_FUNC(writeblob,-2,_SC("xx")), | ||
| _DECL_STREAM_FUNC(writen,3,_SC("xnn")), | ||
| _DECL_STREAM_FUNC(seek,-2,_SC("xnn")), | ||
| _DECL_STREAM_FUNC(tell,1,_SC("x")), | ||
| _DECL_STREAM_FUNC(len,1,_SC("x")), | ||
| _DECL_STREAM_FUNC(eos,1,_SC("x")), | ||
| _DECL_STREAM_FUNC(flush,1,_SC("x")), | ||
| _DECL_STREAM_FUNC(_cloned,0,NULL), | ||
| {0,0} | ||
| }; | ||
|
|
||
| void init_streamclass(HSQUIRRELVM v) | ||
| { | ||
| sq_pushregistrytable(v); | ||
| sq_pushstring(v,_SC("std_stream"),-1); | ||
| if(SQ_FAILED(sq_get(v,-2))) { | ||
| sq_pushstring(v,_SC("std_stream"),-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,SQRegFunction *methods,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) { | ||
| 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) | ||
| { | ||
| 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; | ||
| } |
| @@ -0,0 +1,18 @@ | ||
| /* see copyright notice in squirrel.h */ | ||
| #ifndef _SQSTD_STREAM_H_ | ||
| #define _SQSTD_STREAM_H_ | ||
|
|
||
| SQInteger _stream_readblob(HSQUIRRELVM v); | ||
| SQInteger _stream_readline(HSQUIRRELVM v); | ||
| SQInteger _stream_readn(HSQUIRRELVM v); | ||
| SQInteger _stream_writeblob(HSQUIRRELVM v); | ||
| SQInteger _stream_writen(HSQUIRRELVM v); | ||
| SQInteger _stream_seek(HSQUIRRELVM v); | ||
| SQInteger _stream_tell(HSQUIRRELVM v); | ||
| SQInteger _stream_len(HSQUIRRELVM v); | ||
| SQInteger _stream_eos(HSQUIRRELVM v); | ||
| SQInteger _stream_flush(HSQUIRRELVM v); | ||
|
|
||
| #define _DECL_STREAM_FUNC(name,nparams,typecheck) {_SC(#name),_stream_##name,nparams,typecheck} | ||
| SQRESULT declare_stream(HSQUIRRELVM v,const SQChar* name,SQUserPointer typetag,const SQChar* reg_name,SQRegFunction *methods,SQRegFunction *globals); | ||
| #endif /*_SQSTD_STREAM_H_*/ |
| @@ -0,0 +1,138 @@ | ||
| /* see copyright notice in squirrel.h */ | ||
| #include <squirrel.h> | ||
| #include <time.h> | ||
| #include <stdlib.h> | ||
| #include <stdio.h> | ||
| #include <sqstdsystem.h> | ||
|
|
||
| #define scgetenv getenv | ||
| #define scsystem system | ||
| #define scasctime asctime | ||
| #define scremove remove | ||
| #define screname rename | ||
|
|
||
| static SQInteger _system_getenv(HSQUIRRELVM v) | ||
| { | ||
| const SQChar *s; | ||
| if(SQ_SUCCEEDED(sq_getstring(v,2,&s))){ | ||
| sq_pushstring(v,scgetenv(s),-1); | ||
| return 1; | ||
| } | ||
| return 0; | ||
| } | ||
|
|
||
|
|
||
| static SQInteger _system_system(HSQUIRRELVM v) | ||
| { | ||
| const SQChar *s; | ||
| if(SQ_SUCCEEDED(sq_getstring(v,2,&s))){ | ||
| sq_pushinteger(v,scsystem(s)); | ||
| return 1; | ||
| } | ||
| return sq_throwerror(v,_SC("wrong param")); | ||
| } | ||
|
|
||
|
|
||
| static SQInteger _system_clock(HSQUIRRELVM v) | ||
| { | ||
| sq_pushfloat(v,((SQFloat)clock())/(SQFloat)CLOCKS_PER_SEC); | ||
| return 1; | ||
| } | ||
|
|
||
| static SQInteger _system_time(HSQUIRRELVM v) | ||
| { | ||
| time_t t; | ||
| time(&t); | ||
| sq_pushinteger(v,*((SQInteger *)&t)); | ||
| return 1; | ||
| } | ||
|
|
||
| static SQInteger _system_remove(HSQUIRRELVM v) | ||
| { | ||
| const SQChar *s; | ||
| sq_getstring(v,2,&s); | ||
| if(scremove(s)==-1) | ||
| return sq_throwerror(v,_SC("remove() failed")); | ||
| return 0; | ||
| } | ||
|
|
||
| static SQInteger _system_rename(HSQUIRRELVM v) | ||
| { | ||
| const SQChar *oldn,*newn; | ||
| sq_getstring(v,2,&oldn); | ||
| sq_getstring(v,3,&newn); | ||
| if(screname(oldn,newn)==-1) | ||
| return sq_throwerror(v,_SC("rename() failed")); | ||
| return 0; | ||
| } | ||
|
|
||
| static void _set_integer_slot(HSQUIRRELVM v,const SQChar *name,SQInteger val) | ||
| { | ||
| sq_pushstring(v,name,-1); | ||
| sq_pushinteger(v,val); | ||
| sq_rawset(v,-3); | ||
| } | ||
|
|
||
| static SQInteger _system_date(HSQUIRRELVM v) | ||
| { | ||
| time_t t; | ||
| SQInteger it; | ||
| SQInteger format = 'l'; | ||
| if(sq_gettop(v) > 1) { | ||
| sq_getinteger(v,2,&it); | ||
| t = it; | ||
| if(sq_gettop(v) > 2) { | ||
| sq_getinteger(v,3,(SQInteger*)&format); | ||
| } | ||
| } | ||
| else { | ||
| time(&t); | ||
| } | ||
| tm *date; | ||
| if(format == 'u') | ||
| date = gmtime(&t); | ||
| else | ||
| date = localtime(&t); | ||
| if(!date) | ||
| return sq_throwerror(v,_SC("crt api failure")); | ||
| sq_newtable(v); | ||
| _set_integer_slot(v, _SC("sec"), date->tm_sec); | ||
| set_integer_slot(v, _SC("min"), date->tm_min); | ||
| _set_integer_slot(v, _SC("hour"), date->tm_hour); | ||
| _set_integer_slot(v, _SC("day"), date->tm_mday); | ||
| _set_integer_slot(v, _SC("month"), date->tm_mon); | ||
| _set_integer_slot(v, _SC("year"), date->tm_year+1900); | ||
| _set_integer_slot(v, _SC("wday"), date->tm_wday); | ||
| _set_integer_slot(v, _SC("yday"), date->tm_yday); | ||
| return 1; | ||
|
|
||
| } | ||
|
|
||
|
|
||
|
|
||
| #define _DECL_FUNC(name,nparams,pmask) {_SC(#name),_system_##name,nparams,pmask} | ||
| static SQRegFunction systemlib_funcs[]={ | ||
| _DECL_FUNC(getenv,2,_SC(".s")), | ||
| _DECL_FUNC(system,2,_SC(".s")), | ||
| _DECL_FUNC(clock,0,NULL), | ||
| _DECL_FUNC(time,1,NULL), | ||
| _DECL_FUNC(date,-1,_SC(".nn")), | ||
| _DECL_FUNC(remove,2,_SC(".s")), | ||
| _DECL_FUNC(rename,3,_SC(".ss")), | ||
| {0,0} | ||
| }; | ||
| #undef _DECL_FUNC | ||
|
|
||
| SQInteger sqstd_register_systemlib(HSQUIRRELVM v) | ||
| { | ||
| SQInteger i=0; | ||
| while(systemlib_funcs[i].name!=0) | ||
| { | ||
| sq_pushstring(v,systemlib_funcs[i].name,-1); | ||
| sq_newclosure(v,systemlib_funcs[i].f,0); | ||
| sq_setparamscheck(v,systemlib_funcs[i].nparamscheck,systemlib_funcs[i].typemask); | ||
| sq_setnativeclosurename(v,-1,systemlib_funcs[i].name); | ||
| sq_newslot(v,-3,SQFalse); | ||
| i++; | ||
| } | ||
| return 1; | ||
| } | ||
glx22Aug 30, 2019
Contributor
wrong alignment