Back to home page

Enduro/X

 
 

    


0001 /* see copyright notice in pscript.h */
0002 #include <new>
0003 #include <stdio.h>
0004 #include <stdlib.h>
0005 #include <string.h>
0006 #include <pscript.h>
0007 #include <psstdio.h>
0008 #include <psstdblob.h>
0009 #include "psstdstream.h"
0010 #include "psstdblobimpl.h"
0011 #include <ndrstandard.h>
0012 
0013 #define SETUP_STREAM(v) \
0014     PSStream *self = NULL; \
0015     if(PS_FAILED(ps_getinstanceup(v,1,(PSUserPointer*)&self,(PSUserPointer)PSSTD_STREAM_TYPE_TAG))) \
0016         return ps_throwerror(v,_SC("invalid type tag")); \
0017     if(!self || !self->IsValid())  \
0018         return ps_throwerror(v,_SC("the stream is invalid"));
0019 
0020 PSInteger _stream_readblob(HPSCRIPTVM v)
0021 {
0022     SETUP_STREAM(v);
0023     PSUserPointer data,blobp;
0024     PSInteger size,res;
0025     ps_getinteger(v,2,&size);
0026     if(size > self->Len()) {
0027         size = self->Len();
0028     }
0029     data = ps_getscratchpad(v,size);
0030     res = self->Read(data,size);
0031     if(res <= 0)
0032         return ps_throwerror(v,_SC("no data left to read"));
0033     blobp = psstd_createblob(v,res);
0034     memcpy(blobp,data,res);
0035     return 1;
0036 }
0037 
0038 #define SAFE_READN(ptr,len) { \
0039     if(self->Read(ptr,len) != len) return ps_throwerror(v,_SC("io error")); \
0040     }
0041 PSInteger _stream_readn(HPSCRIPTVM v)
0042 {
0043     SETUP_STREAM(v);
0044     PSInteger format;
0045     ps_getinteger(v, 2, &format);
0046     switch(format) {
0047     case 'l': {
0048         PSInteger i;
0049         SAFE_READN(&i, sizeof(i));
0050         ps_pushinteger(v, i);
0051               }
0052         break;
0053     case 'i': {
0054         PSInt32 i;
0055         SAFE_READN(&i, sizeof(i));
0056         ps_pushinteger(v, i);
0057               }
0058         break;
0059     case 's': {
0060         short s;
0061         SAFE_READN(&s, sizeof(short));
0062         ps_pushinteger(v, s);
0063               }
0064         break;
0065     case 'w': {
0066         unsigned short w;
0067         SAFE_READN(&w, sizeof(unsigned short));
0068         ps_pushinteger(v, w);
0069               }
0070         break;
0071     case 'c': {
0072         char c;
0073         SAFE_READN(&c, sizeof(char));
0074         ps_pushinteger(v, c);
0075               }
0076         break;
0077     case 'b': {
0078         unsigned char c;
0079         SAFE_READN(&c, sizeof(unsigned char));
0080         ps_pushinteger(v, c);
0081               }
0082         break;
0083     case 'f': {
0084         float f;
0085         SAFE_READN(&f, sizeof(float));
0086         ps_pushfloat(v, f);
0087               }
0088         break;
0089     case 'd': {
0090         double d;
0091         SAFE_READN(&d, sizeof(double));
0092         ps_pushfloat(v, (PSFloat)d);
0093               }
0094         break;
0095     default:
0096         return ps_throwerror(v, _SC("invalid format"));
0097     }
0098     return 1;
0099 }
0100 
0101 PSInteger _stream_writeblob(HPSCRIPTVM v)
0102 {
0103     PSUserPointer data;
0104     PSInteger size;
0105     SETUP_STREAM(v);
0106     if(PS_FAILED(psstd_getblob(v,2,&data)))
0107         return ps_throwerror(v,_SC("invalid parameter"));
0108     size = psstd_getblobsize(v,2);
0109     if(self->Write(data,size) != size)
0110         return ps_throwerror(v,_SC("io error"));
0111     ps_pushinteger(v,size);
0112     return 1;
0113 }
0114 
0115 PSInteger _stream_writen(HPSCRIPTVM v)
0116 {
0117     SETUP_STREAM(v);
0118     PSInteger format, ti;
0119     PSFloat tf;
0120     ps_getinteger(v, 3, &format);
0121     switch(format) {
0122     case 'l': {
0123         PSInteger i;
0124         ps_getinteger(v, 2, &ti);
0125         i = ti;
0126         self->Write(&i, sizeof(PSInteger));
0127               }
0128         break;
0129     case 'i': {
0130         PSInt32 i;
0131         ps_getinteger(v, 2, &ti);
0132         i = (PSInt32)ti;
0133         self->Write(&i, sizeof(PSInt32));
0134               }
0135         break;
0136     case 's': {
0137         short s;
0138         ps_getinteger(v, 2, &ti);
0139         s = (short)ti;
0140         self->Write(&s, sizeof(short));
0141               }
0142         break;
0143     case 'w': {
0144         unsigned short w;
0145         ps_getinteger(v, 2, &ti);
0146         w = (unsigned short)ti;
0147         self->Write(&w, sizeof(unsigned short));
0148               }
0149         break;
0150     case 'c': {
0151         char c;
0152         ps_getinteger(v, 2, &ti);
0153         c = (char)ti;
0154         self->Write(&c, sizeof(char));
0155                   }
0156         break;
0157     case 'b': {
0158         unsigned char b;
0159         ps_getinteger(v, 2, &ti);
0160         b = (unsigned char)ti;
0161         self->Write(&b, sizeof(unsigned char));
0162               }
0163         break;
0164     case 'f': {
0165         float f;
0166         ps_getfloat(v, 2, &tf);
0167         f = (float)tf;
0168         self->Write(&f, sizeof(float));
0169               }
0170         break;
0171     case 'd': {
0172         double d;
0173         ps_getfloat(v, 2, &tf);
0174         d = tf;
0175         self->Write(&d, sizeof(double));
0176               }
0177         break;
0178     default:
0179         return ps_throwerror(v, _SC("invalid format"));
0180     }
0181     return 0;
0182 }
0183 
0184 
0185 //Write string, mvitolin
0186 PSInteger _stream_writes(HPSCRIPTVM v)
0187 {
0188        PSInteger size;
0189        SETUP_STREAM(v);
0190         const PSChar *s;
0191         
0192         if(PS_SUCCEEDED(ps_getstring(v,2,&s))){
0193 
0194             size = strlen(s);
0195             if(self->Write((void *)s,strlen(s)) != size)
0196                     return ps_throwerror(v,_SC("io error"));        
0197             return 1;
0198         }
0199        ps_pushinteger(v,size);
0200        return 1;
0201 }
0202 
0203 
0204 /**
0205  * Read line from the stream
0206  * @param [script] max line len (buffer size)
0207  * @return [script] returns string, in case if empty line, shall be tested tested
0208  *  that string is not eos.
0209  */
0210 PSInteger _stream_readline(HPSCRIPTVM v)
0211 {
0212     SETUP_STREAM(v);
0213     PSInteger len;
0214     PSChar *stemp=NULL;
0215     
0216     if(PS_SUCCEEDED(ps_getinteger(v,2,&len)))
0217     {
0218         if (len<=0)
0219         {
0220             return ps_throwerror(v,_SC("Invalid len argument"));
0221         }
0222                 
0223         stemp = ps_getscratchpad(v,len);
0224         stemp[0] = EXEOS;
0225    
0226         if(NULL==self->ReadLine((void *)stemp,len))
0227         {
0228             if (!self->EOS())
0229             {
0230                 return ps_throwerror(v,_SC("io error"));
0231             }
0232         }
0233     }
0234     
0235     
0236    ps_pushstring(v,stemp, -1);
0237    return 1;
0238 }
0239 
0240 
0241 PSInteger _stream_seek(HPSCRIPTVM v)
0242 {
0243     SETUP_STREAM(v);
0244     PSInteger offset, origin = PS_SEEK_SET;
0245     ps_getinteger(v, 2, &offset);
0246     if(ps_gettop(v) > 2) {
0247         PSInteger t;
0248         ps_getinteger(v, 3, &t);
0249         switch(t) {
0250             case 'b': origin = PS_SEEK_SET; break;
0251             case 'c': origin = PS_SEEK_CUR; break;
0252             case 'e': origin = PS_SEEK_END; break;
0253             default: return ps_throwerror(v,_SC("invalid origin"));
0254         }
0255     }
0256     ps_pushinteger(v, self->Seek(offset, origin));
0257     return 1;
0258 }
0259 
0260 PSInteger _stream_tell(HPSCRIPTVM v)
0261 {
0262     SETUP_STREAM(v);
0263     ps_pushinteger(v, self->Tell());
0264     return 1;
0265 }
0266 
0267 PSInteger _stream_len(HPSCRIPTVM v)
0268 {
0269     SETUP_STREAM(v);
0270     ps_pushinteger(v, self->Len());
0271     return 1;
0272 }
0273 
0274 PSInteger _stream_flush(HPSCRIPTVM v)
0275 {
0276     SETUP_STREAM(v);
0277     if(!self->Flush())
0278         ps_pushinteger(v, 1);
0279     else
0280         ps_pushnull(v);
0281     return 1;
0282 }
0283 
0284 PSInteger _stream_eos(HPSCRIPTVM v)
0285 {
0286     SETUP_STREAM(v);
0287     if(self->EOS())
0288         ps_pushinteger(v, 1);
0289     else
0290         ps_pushnull(v);
0291     return 1;
0292 }
0293 
0294  PSInteger _stream__cloned(HPSCRIPTVM v)
0295  {
0296      return ps_throwerror(v,_SC("this object cannot be cloned"));
0297  }
0298 
0299 static const PSRegFunction _stream_methods[] = {
0300     _DECL_STREAM_FUNC(readblob,2,_SC("xn")),
0301     _DECL_STREAM_FUNC(readn,2,_SC("xn")),
0302     _DECL_STREAM_FUNC(writeblob,-2,_SC("xx")),
0303     _DECL_STREAM_FUNC(writen,3,_SC("xnn")),
0304     _DECL_STREAM_FUNC(writes,2,_SC("xs")),
0305     _DECL_STREAM_FUNC(readline,2,_SC("xn")),
0306     _DECL_STREAM_FUNC(seek,-2,_SC("xnn")),
0307     _DECL_STREAM_FUNC(tell,1,_SC("x")),
0308     _DECL_STREAM_FUNC(len,1,_SC("x")),
0309     _DECL_STREAM_FUNC(eos,1,_SC("x")),
0310     _DECL_STREAM_FUNC(flush,1,_SC("x")),
0311     _DECL_STREAM_FUNC(_cloned,0,NULL),
0312     {NULL,(PSFUNCTION)0,0,NULL}
0313 };
0314 
0315 void init_streamclass(HPSCRIPTVM v)
0316 {
0317     ps_pushregistrytable(v);
0318     ps_pushstring(v,_SC("std_stream"),-1);
0319     if(PS_FAILED(ps_get(v,-2))) {
0320         ps_pushstring(v,_SC("std_stream"),-1);
0321         ps_newclass(v,PSFalse);
0322         ps_settypetag(v,-1,(PSUserPointer)PSSTD_STREAM_TYPE_TAG);
0323         PSInteger i = 0;
0324         while(_stream_methods[i].name != 0) {
0325             const PSRegFunction &f = _stream_methods[i];
0326             ps_pushstring(v,f.name,-1);
0327             ps_newclosure(v,f.f,0);
0328             ps_setparamscheck(v,f.nparamscheck,f.typemask);
0329             ps_newslot(v,-3,PSFalse);
0330             i++;
0331         }
0332         ps_newslot(v,-3,PSFalse);
0333         ps_pushroottable(v);
0334         ps_pushstring(v,_SC("stream"),-1);
0335         ps_pushstring(v,_SC("std_stream"),-1);
0336         ps_get(v,-4);
0337         ps_newslot(v,-3,PSFalse);
0338         ps_pop(v,1);
0339     }
0340     else {
0341         ps_pop(v,1); //result
0342     }
0343     ps_pop(v,1);
0344 }
0345 
0346 PSRESULT declare_stream(HPSCRIPTVM v,const PSChar* name,PSUserPointer typetag,const PSChar* reg_name,const PSRegFunction *methods,const PSRegFunction *globals)
0347 {
0348     if(ps_gettype(v,-1) != OT_TABLE)
0349         return ps_throwerror(v,_SC("table expected"));
0350     PSInteger top = ps_gettop(v);
0351     //create delegate
0352     init_streamclass(v);
0353     ps_pushregistrytable(v);
0354     ps_pushstring(v,reg_name,-1);
0355     ps_pushstring(v,_SC("std_stream"),-1);
0356     if(PS_SUCCEEDED(ps_get(v,-3))) {
0357         ps_newclass(v,PSTrue);
0358         ps_settypetag(v,-1,typetag);
0359         PSInteger i = 0;
0360         while(methods[i].name != 0) {
0361             const PSRegFunction &f = methods[i];
0362             ps_pushstring(v,f.name,-1);
0363             ps_newclosure(v,f.f,0);
0364             ps_setparamscheck(v,f.nparamscheck,f.typemask);
0365             ps_setnativeclosurename(v,-1,f.name);
0366             ps_newslot(v,-3,PSFalse);
0367             i++;
0368         }
0369         ps_newslot(v,-3,PSFalse);
0370         ps_pop(v,1);
0371 
0372         i = 0;
0373         while(globals[i].name!=0)
0374         {
0375             const PSRegFunction &f = globals[i];
0376             ps_pushstring(v,f.name,-1);
0377             ps_newclosure(v,f.f,0);
0378             ps_setparamscheck(v,f.nparamscheck,f.typemask);
0379             ps_setnativeclosurename(v,-1,f.name);
0380             ps_newslot(v,-3,PSFalse);
0381             i++;
0382         }
0383         //register the class in the target table
0384         ps_pushstring(v,name,-1);
0385         ps_pushregistrytable(v);
0386         ps_pushstring(v,reg_name,-1);
0387         ps_get(v,-2);
0388         ps_remove(v,-2);
0389         ps_newslot(v,-3,PSFalse);
0390 
0391         ps_settop(v,top);
0392         return PS_OK;
0393     }
0394     ps_settop(v,top);
0395     return PS_ERROR;
0396 }