0001
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
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
0206
0207
0208
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);
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
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
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 }