# sqstdstream.cpp

    00001 /* see copyright notice in squirrel.h */
    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); //result
    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   //create delegate
    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     //register the class in the target table
    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 }