Johan Wikman / SQUIRREL3

Dependents:   Squirrel

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers sqstdstream.cpp Source File

sqstdstream.cpp

00001 /* see copyright notice in squirrel.h */
00002 #include <new>
00003 #include <stdio.h>
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 || !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  SQInteger _stream__cloned(HSQUIRRELVM v)
00237  {
00238      return sq_throwerror(v,_SC("this object cannot be cloned"));
00239  }
00240 
00241 static SQRegFunction _stream_methods[] = {
00242     _DECL_STREAM_FUNC(readblob,2,_SC("xn")),
00243     _DECL_STREAM_FUNC(readn,2,_SC("xn")),
00244     _DECL_STREAM_FUNC(writeblob,-2,_SC("xx")),
00245     _DECL_STREAM_FUNC(writen,3,_SC("xnn")),
00246     _DECL_STREAM_FUNC(seek,-2,_SC("xnn")),
00247     _DECL_STREAM_FUNC(tell,1,_SC("x")),
00248     _DECL_STREAM_FUNC(len,1,_SC("x")),
00249     _DECL_STREAM_FUNC(eos,1,_SC("x")),
00250     _DECL_STREAM_FUNC(flush,1,_SC("x")),
00251     _DECL_STREAM_FUNC(_cloned,0,NULL),
00252     {0,0}
00253 };
00254 
00255 void init_streamclass(HSQUIRRELVM v)
00256 {
00257     sq_pushregistrytable(v);
00258     sq_pushstring(v,_SC("std_stream"),-1);
00259     if(SQ_FAILED(sq_get(v,-2))) {
00260         sq_pushstring(v,_SC("std_stream"),-1);
00261         sq_newclass(v,SQFalse);
00262         sq_settypetag(v,-1,(SQUserPointer)SQSTD_STREAM_TYPE_TAG);
00263         SQInteger i = 0;
00264         while(_stream_methods[i].name != 0) {
00265             SQRegFunction &f = _stream_methods[i];
00266             sq_pushstring(v,f.name,-1);
00267             sq_newclosure(v,f.f,0);
00268             sq_setparamscheck(v,f.nparamscheck,f.typemask);
00269             sq_newslot(v,-3,SQFalse);
00270             i++;
00271         }
00272         sq_newslot(v,-3,SQFalse);
00273         sq_pushroottable(v);
00274         sq_pushstring(v,_SC("stream"),-1);
00275         sq_pushstring(v,_SC("std_stream"),-1);
00276         sq_get(v,-4);
00277         sq_newslot(v,-3,SQFalse);
00278         sq_pop(v,1);
00279     }
00280     else {
00281         sq_pop(v,1); //result
00282     }
00283     sq_pop(v,1);
00284 }
00285 
00286 SQRESULT declare_stream(HSQUIRRELVM v,const SQChar* name,SQUserPointer typetag,const SQChar* reg_name,SQRegFunction *methods,SQRegFunction *globals)
00287 {
00288     if(sq_gettype(v,-1) != OT_TABLE)
00289         return sq_throwerror(v,_SC("table expected"));
00290     SQInteger top = sq_gettop(v);
00291     //create delegate
00292     init_streamclass(v);
00293     sq_pushregistrytable(v);
00294     sq_pushstring(v,reg_name,-1);
00295     sq_pushstring(v,_SC("std_stream"),-1);
00296     if(SQ_SUCCEEDED(sq_get(v,-3))) {
00297         sq_newclass(v,SQTrue);
00298         sq_settypetag(v,-1,typetag);
00299         SQInteger i = 0;
00300         while(methods[i].name != 0) {
00301             SQRegFunction &f = methods[i];
00302             sq_pushstring(v,f.name,-1);
00303             sq_newclosure(v,f.f,0);
00304             sq_setparamscheck(v,f.nparamscheck,f.typemask);
00305             sq_setnativeclosurename(v,-1,f.name);
00306             sq_newslot(v,-3,SQFalse);
00307             i++;
00308         }
00309         sq_newslot(v,-3,SQFalse);
00310         sq_pop(v,1);
00311         
00312         i = 0;
00313         while(globals[i].name!=0)
00314         {
00315             SQRegFunction &f = globals[i];
00316             sq_pushstring(v,f.name,-1);
00317             sq_newclosure(v,f.f,0);
00318             sq_setparamscheck(v,f.nparamscheck,f.typemask);
00319             sq_setnativeclosurename(v,-1,f.name);
00320             sq_newslot(v,-3,SQFalse);
00321             i++;
00322         }
00323         //register the class in the target table
00324         sq_pushstring(v,name,-1);
00325         sq_pushregistrytable(v);
00326         sq_pushstring(v,reg_name,-1);
00327         sq_get(v,-2);
00328         sq_remove(v,-2);
00329         sq_newslot(v,-3,SQFalse);
00330 
00331         sq_settop(v,top);
00332         return SQ_OK;
00333     }
00334     sq_settop(v,top);
00335     return SQ_ERROR;
00336 }