00001
00002 #include <stdio.h>
00003 #include <new>
00004 #include <stdlib.h>
00005 #include <string.h>
00006 #include <squirrel.h>
00007 #include <sqstdio.h>
00008 #include <sqstdblob.h>
00009 #include "sqstdstream.h"
00010 #include "sqstdblobimpl.h"
00011
00012 #define SETUP_STREAM(v) \
00013 SQStream *self = NULL; \
00014 if(SQ_FAILED(sq_getinstanceup(v,1,(SQUserPointer*)&self,(SQUserPointer)SQSTD_STREAM_TYPE_TAG))) \
00015 return sq_throwerror(v,_SC("invalid type tag")); \
00016 if(!self->IsValid()) \
00017 return sq_throwerror(v,_SC("the stream is invalid"));
00018
00019 SQInteger _stream_readblob(HSQUIRRELVM v)
00020 {
00021 SETUP_STREAM(v);
00022 SQUserPointer data,blobp;
00023 SQInteger size,res;
00024 sq_getinteger(v,2,&size);
00025 if(size > self->Len()) {
00026 size = self->Len();
00027 }
00028 data = sq_getscratchpad(v,size);
00029 res = self->Read(data,size);
00030 if(res <= 0)
00031 return sq_throwerror(v,_SC("no data left to read"));
00032 blobp = sqstd_createblob(v,res);
00033 memcpy(blobp,data,res);
00034 return 1;
00035 }
00036
00037 #define SAFE_READN(ptr,len) { \
00038 if(self->Read(ptr,len) != len) return sq_throwerror(v,_SC("io error")); \
00039 }
00040 SQInteger _stream_readn(HSQUIRRELVM v)
00041 {
00042 SETUP_STREAM(v);
00043 SQInteger format;
00044 sq_getinteger(v, 2, &format);
00045 switch(format) {
00046 case 'l': {
00047 SQInteger i;
00048 SAFE_READN(&i, sizeof(i));
00049 sq_pushinteger(v, i);
00050 }
00051 break;
00052 case 'i': {
00053 SQInt32 i;
00054 SAFE_READN(&i, sizeof(i));
00055 sq_pushinteger(v, i);
00056 }
00057 break;
00058 case 's': {
00059 short s;
00060 SAFE_READN(&s, sizeof(short));
00061 sq_pushinteger(v, s);
00062 }
00063 break;
00064 case 'w': {
00065 unsigned short w;
00066 SAFE_READN(&w, sizeof(unsigned short));
00067 sq_pushinteger(v, w);
00068 }
00069 break;
00070 case 'c': {
00071 char c;
00072 SAFE_READN(&c, sizeof(char));
00073 sq_pushinteger(v, c);
00074 }
00075 break;
00076 case 'b': {
00077 unsigned char c;
00078 SAFE_READN(&c, sizeof(unsigned char));
00079 sq_pushinteger(v, c);
00080 }
00081 break;
00082 case 'f': {
00083 float f;
00084 SAFE_READN(&f, sizeof(float));
00085 sq_pushfloat(v, f);
00086 }
00087 break;
00088 case 'd': {
00089 double d;
00090 SAFE_READN(&d, sizeof(double));
00091 sq_pushfloat(v, (SQFloat)d);
00092 }
00093 break;
00094 default:
00095 return sq_throwerror(v, _SC("invalid format"));
00096 }
00097 return 1;
00098 }
00099
00100 SQInteger _stream_writeblob(HSQUIRRELVM v)
00101 {
00102 SQUserPointer data;
00103 SQInteger size;
00104 SETUP_STREAM(v);
00105 if(SQ_FAILED(sqstd_getblob(v,2,&data)))
00106 return sq_throwerror(v,_SC("invalid parameter"));
00107 size = sqstd_getblobsize(v,2);
00108 if(self->Write(data,size) != size)
00109 return sq_throwerror(v,_SC("io error"));
00110 sq_pushinteger(v,size);
00111 return 1;
00112 }
00113
00114 SQInteger _stream_writen(HSQUIRRELVM v)
00115 {
00116 SETUP_STREAM(v);
00117 SQInteger format, ti;
00118 SQFloat tf;
00119 sq_getinteger(v, 3, &format);
00120 switch(format) {
00121 case 'l': {
00122 SQInteger i;
00123 sq_getinteger(v, 2, &ti);
00124 i = ti;
00125 self->Write(&i, sizeof(SQInteger));
00126 }
00127 break;
00128 case 'i': {
00129 SQInt32 i;
00130 sq_getinteger(v, 2, &ti);
00131 i = (SQInt32)ti;
00132 self->Write(&i, sizeof(SQInt32));
00133 }
00134 break;
00135 case 's': {
00136 short s;
00137 sq_getinteger(v, 2, &ti);
00138 s = (short)ti;
00139 self->Write(&s, sizeof(short));
00140 }
00141 break;
00142 case 'w': {
00143 unsigned short w;
00144 sq_getinteger(v, 2, &ti);
00145 w = (unsigned short)ti;
00146 self->Write(&w, sizeof(unsigned short));
00147 }
00148 break;
00149 case 'c': {
00150 char c;
00151 sq_getinteger(v, 2, &ti);
00152 c = (char)ti;
00153 self->Write(&c, sizeof(char));
00154 }
00155 break;
00156 case 'b': {
00157 unsigned char b;
00158 sq_getinteger(v, 2, &ti);
00159 b = (unsigned char)ti;
00160 self->Write(&b, sizeof(unsigned char));
00161 }
00162 break;
00163 case 'f': {
00164 float f;
00165 sq_getfloat(v, 2, &tf);
00166 f = (float)tf;
00167 self->Write(&f, sizeof(float));
00168 }
00169 break;
00170 case 'd': {
00171 double d;
00172 sq_getfloat(v, 2, &tf);
00173 d = tf;
00174 self->Write(&d, sizeof(double));
00175 }
00176 break;
00177 default:
00178 return sq_throwerror(v, _SC("invalid format"));
00179 }
00180 return 0;
00181 }
00182
00183 SQInteger _stream_seek(HSQUIRRELVM v)
00184 {
00185 SETUP_STREAM(v);
00186 SQInteger offset, origin = SQ_SEEK_SET;
00187 sq_getinteger(v, 2, &offset);
00188 if(sq_gettop(v) > 2) {
00189 SQInteger t;
00190 sq_getinteger(v, 3, &t);
00191 switch(t) {
00192 case 'b': origin = SQ_SEEK_SET; break;
00193 case 'c': origin = SQ_SEEK_CUR; break;
00194 case 'e': origin = SQ_SEEK_END; break;
00195 default: return sq_throwerror(v,_SC("invalid origin"));
00196 }
00197 }
00198 sq_pushinteger(v, self->Seek(offset, origin));
00199 return 1;
00200 }
00201
00202 SQInteger _stream_tell(HSQUIRRELVM v)
00203 {
00204 SETUP_STREAM(v);
00205 sq_pushinteger(v, self->Tell());
00206 return 1;
00207 }
00208
00209 SQInteger _stream_len(HSQUIRRELVM v)
00210 {
00211 SETUP_STREAM(v);
00212 sq_pushinteger(v, self->Len());
00213 return 1;
00214 }
00215
00216 SQInteger _stream_flush(HSQUIRRELVM v)
00217 {
00218 SETUP_STREAM(v);
00219 if(!self->Flush())
00220 sq_pushinteger(v, 1);
00221 else
00222 sq_pushnull(v);
00223 return 1;
00224 }
00225
00226 SQInteger _stream_eos(HSQUIRRELVM v)
00227 {
00228 SETUP_STREAM(v);
00229 if(self->EOS())
00230 sq_pushinteger(v, 1);
00231 else
00232 sq_pushnull(v);
00233 return 1;
00234 }
00235
00236 static SQRegFunction _stream_methods[] = {
00237 _DECL_STREAM_FUNC(readblob,2,_SC("xn")),
00238 _DECL_STREAM_FUNC(readn,2,_SC("xn")),
00239 _DECL_STREAM_FUNC(writeblob,-2,_SC("xx")),
00240 _DECL_STREAM_FUNC(writen,3,_SC("xnn")),
00241 _DECL_STREAM_FUNC(seek,-2,_SC("xnn")),
00242 _DECL_STREAM_FUNC(tell,1,_SC("x")),
00243 _DECL_STREAM_FUNC(len,1,_SC("x")),
00244 _DECL_STREAM_FUNC(eos,1,_SC("x")),
00245 _DECL_STREAM_FUNC(flush,1,_SC("x")),
00246 {0,0,0,0}
00247 };
00248
00249 void init_streamclass(HSQUIRRELVM v)
00250 {
00251 sq_pushregistrytable(v);
00252 sq_pushstring(v,_SC("std_stream"),-1);
00253 if(SQ_FAILED(sq_get(v,-2))) {
00254 sq_pushstring(v,_SC("std_stream"),-1);
00255 sq_newclass(v,SQFalse);
00256 sq_settypetag(v,-1,(SQUserPointer)SQSTD_STREAM_TYPE_TAG);
00257 SQInteger i = 0;
00258 while(_stream_methods[i].name != 0) {
00259 SQRegFunction &f = _stream_methods[i];
00260 sq_pushstring(v,f.name,-1);
00261 sq_newclosure(v,f.f,0);
00262 sq_setparamscheck(v,f.nparamscheck,f.typemask);
00263 sq_createslot(v,-3);
00264 i++;
00265 }
00266 sq_createslot(v,-3);
00267 sq_pushroottable(v);
00268 sq_pushstring(v,_SC("stream"),-1);
00269 sq_pushstring(v,_SC("std_stream"),-1);
00270 sq_get(v,-4);
00271 sq_createslot(v,-3);
00272 sq_pop(v,1);
00273 }
00274 else {
00275 sq_pop(v,1);
00276 }
00277 sq_pop(v,1);
00278 }
00279
00280 SQRESULT declare_stream(HSQUIRRELVM v,const SQChar* name,SQUserPointer typetag,const SQChar* reg_name,SQRegFunction *methods,SQRegFunction *globals)
00281 {
00282 if(sq_gettype(v,-1) != OT_TABLE)
00283 return sq_throwerror(v,_SC("table expected"));
00284 SQInteger top = sq_gettop(v);
00285
00286 init_streamclass(v);
00287 sq_pushregistrytable(v);
00288 sq_pushstring(v,reg_name,-1);
00289 sq_pushstring(v,_SC("std_stream"),-1);
00290 if(SQ_SUCCEEDED(sq_get(v,-3))) {
00291 sq_newclass(v,SQTrue);
00292 sq_settypetag(v,-1,typetag);
00293 SQInteger i = 0;
00294 while(methods[i].name != 0) {
00295 SQRegFunction &f = methods[i];
00296 sq_pushstring(v,f.name,-1);
00297 sq_newclosure(v,f.f,0);
00298 sq_setparamscheck(v,f.nparamscheck,f.typemask);
00299 sq_setnativeclosurename(v,-1,f.name);
00300 sq_createslot(v,-3);
00301 i++;
00302 }
00303 sq_createslot(v,-3);
00304 sq_pop(v,1);
00305
00306 i = 0;
00307 while(globals[i].name!=0)
00308 {
00309 SQRegFunction &f = globals[i];
00310 sq_pushstring(v,f.name,-1);
00311 sq_newclosure(v,f.f,0);
00312 sq_setparamscheck(v,f.nparamscheck,f.typemask);
00313 sq_setnativeclosurename(v,-1,f.name);
00314 sq_createslot(v,-3);
00315 i++;
00316 }
00317
00318 sq_pushstring(v,name,-1);
00319 sq_pushregistrytable(v);
00320 sq_pushstring(v,reg_name,-1);
00321 sq_get(v,-2);
00322 sq_remove(v,-2);
00323 sq_createslot(v,-3);
00324
00325 sq_settop(v,top);
00326 return SQ_OK;
00327 }
00328 sq_settop(v,top);
00329 return SQ_ERROR;
00330 }