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 }

Generated on Mon Mar 9 23:33:44 2009 for openttd by  doxygen 1.5.6