1 /* see copyright notice in squirrel.h */
9 #include "sqstdstream.h"
10 #include "sqstdblobimpl.h"
12 #define SETUP_STREAM(v) \
13 SQStream *self = NULL; \
14 if(SQ_FAILED(sq_getinstanceup(v,1,(SQUserPointer*)&self,SQSTD_STREAM_TYPE_TAG))) \
15 return sq_throwerror(v,_SC("invalid type tag")); \
16 if(!self->IsValid()) \
17 return sq_throwerror(v,_SC("the stream is invalid"));
19 int _stream_readstr(HSQUIRRELVM v)
22 SQInteger type = _SC('a'), size = 0;
23 sq_getinteger(v, 2, &size);
24 if(size <= 0) return sq_throwerror(v,_SC("invalid size"));
26 sq_getinteger(v, 3, &type);
31 if(self->Read(sq_getscratchpad(v, size+1), size) != size)
32 return sq_throwerror(v, _SC("io failure"));
34 temp = (char*) sq_getscratchpad(v, size + (size * sizeof(SQChar)));
35 dest = (SQChar*) &temp[size];
36 size = (SQInteger)mbstowcs(dest, (const char*)temp, size);
38 temp = (char *) sq_getscratchpad(v, -1);
45 if(self->Read(sq_getscratchpad(v, (size + 1) * sizeof(wchar_t)), size * sizeof(wchar_t)) != (int) (size * sizeof(wchar_t)))
46 return sq_throwerror(v, _SC("io failure"));
49 temp = (wchar_t*) sq_getscratchpad(v, -1);
50 dest = (SQChar*) temp;
52 temp = (wchar_t*) sq_getscratchpad(v,(size * 3) + (size * sizeof(wchar_t)));
53 dest = (char*) &temp[size];
54 size = (SQInteger)wcstombs(dest, (const wchar_t*)temp, size);
59 return sq_throwerror(v, _SC("invalid coding"));
62 sq_pushstring(v, dest, size);
66 int _stream_readblob(HSQUIRRELVM v)
69 SQUserPointer data,blobp;
71 sq_getinteger(v,2,&size);
72 if(size > self->Len()) {
75 data = sq_getscratchpad(v,size);
76 res = self->Read(data,size);
78 return sq_throwerror(v,_SC("no data left to read"));
79 blobp = sqstd_createblob(v,res);
80 memcpy(blobp,data,res);
84 #define SAFE_READN(ptr,len) { \
85 if(self->Read(ptr,len) != len) return sq_throwerror(v,_SC("io error")); \
87 int _stream_readn(HSQUIRRELVM v)
91 sq_getinteger(v, 2, &format);
95 SAFE_READN(&i, sizeof(i));
101 SAFE_READN(&s, sizeof(short));
102 sq_pushinteger(v, s);
107 SAFE_READN(&w, sizeof(unsigned short));
108 sq_pushinteger(v, w);
113 SAFE_READN(&c, sizeof(char));
114 sq_pushinteger(v, c);
119 SAFE_READN(&c, sizeof(unsigned char));
120 sq_pushinteger(v, c);
125 SAFE_READN(&f, sizeof(float));
131 SAFE_READN(&d, sizeof(double));
132 sq_pushfloat(v, (SQFloat)d);
136 return sq_throwerror(v, _SC("invalid format"));
141 int _stream_writestr(HSQUIRRELVM v)
144 const SQChar *str,*res;
145 SQInteger trgformat = 'a',len = 0;
146 sq_getstring(v,2,&str);
147 len = sq_getsize(v,2);
149 sq_getinteger(v,3,&trgformat);
154 res = sq_getscratchpad(v,len*3);
155 len = (SQInteger) wcstombs((char *)res, (const wchar_t*)str, len);
159 self->Write((void *)res,len);
165 res = sq_getscratchpad(v,len*sizeof(wchar_t));
166 len = (SQInteger) mbstowcs((wchar_t*)res, str, len);
168 self->Write((void *)res,len*sizeof(wchar_t));
171 return sq_throwerror(v,_SC("wrong encoding"));
177 int _stream_writeblob(HSQUIRRELVM v)
182 if(SQ_FAILED(sqstd_getblob(v,2,&data)))
183 return sq_throwerror(v,_SC("invalid parameter"));
184 size = sqstd_getblobsize(v,2);
185 if(self->Write(data,size) != size)
186 return sq_throwerror(v,_SC("io error"));
187 sq_pushinteger(v,size);
191 int _stream_writen(HSQUIRRELVM v)
194 SQInteger format, ti;
196 sq_getinteger(v, 3, &format);
200 sq_getinteger(v, 2, &ti);
202 self->Write(&i, sizeof(int));
207 sq_getinteger(v, 2, &ti);
209 self->Write(&s, sizeof(short));
214 sq_getinteger(v, 2, &ti);
216 self->Write(&w, sizeof(unsigned short));
221 sq_getinteger(v, 2, &ti);
223 self->Write(&c, sizeof(char));
228 sq_getinteger(v, 2, &ti);
230 self->Write(&b, sizeof(unsigned char));
235 sq_getfloat(v, 2, &tf);
237 self->Write(&f, sizeof(float));
242 sq_getfloat(v, 2, &tf);
244 self->Write(&d, sizeof(double));
248 return sq_throwerror(v, _SC("invalid format"));
253 int _stream_seek(HSQUIRRELVM v)
256 SQInteger offset, origin = SQ_SEEK_SET;
257 sq_getinteger(v, 2, &offset);
258 if(sq_gettop(v) > 2) {
260 sq_getinteger(v, 3, &t);
262 case 'b': origin = SQ_SEEK_SET; break;
263 case 'c': origin = SQ_SEEK_CUR; break;
264 case 'e': origin = SQ_SEEK_END; break;
265 default: return sq_throwerror(v,_SC("invalid origin"));
268 sq_pushinteger(v, self->Seek(offset, origin));
272 int _stream_tell(HSQUIRRELVM v)
275 sq_pushinteger(v, self->Tell());
279 int _stream_len(HSQUIRRELVM v)
282 sq_pushinteger(v, self->Len());
286 int _stream_flush(HSQUIRRELVM v)
290 sq_pushinteger(v, 1);
296 int _stream_eos(HSQUIRRELVM v)
300 sq_pushinteger(v, 1);
306 static SQRegFunction _stream_methods[] = {
307 _DECL_STREAM_FUNC(readstr,-2,_SC("xnn")),
308 _DECL_STREAM_FUNC(readblob,2,_SC("xn")),
309 _DECL_STREAM_FUNC(readn,2,_SC("xn")),
310 _DECL_STREAM_FUNC(writestr,-2,_SC("xsn")),
311 _DECL_STREAM_FUNC(writeblob,-2,_SC("xx")),
312 _DECL_STREAM_FUNC(writen,3,_SC("xnn")),
313 _DECL_STREAM_FUNC(seek,-2,_SC("xnn")),
314 _DECL_STREAM_FUNC(tell,1,_SC("x")),
315 _DECL_STREAM_FUNC(len,1,_SC("x")),
316 _DECL_STREAM_FUNC(eos,1,_SC("x")),
317 _DECL_STREAM_FUNC(flush,1,_SC("x")),
321 void init_streamclass(HSQUIRRELVM v)
323 sq_pushregistrytable(v);
324 sq_pushstring(v,_SC("std_stream"),-1);
325 if(SQ_FAILED(sq_get(v,-2))) {
326 sq_pushstring(v,_SC("std_stream"),-1);
327 sq_newclass(v,SQFalse);
328 sq_settypetag(v,-1,SQSTD_STREAM_TYPE_TAG);
330 while(_stream_methods[i].name != 0) {
331 SQRegFunction &f = _stream_methods[i];
332 sq_pushstring(v,f.name,-1);
333 sq_newclosure(v,f.f,0);
334 sq_setparamscheck(v,f.nparamscheck,f.typemask);
341 sq_pop(v,1); //result
346 SQRESULT declare_stream(HSQUIRRELVM v,SQChar* name,int typetag,SQChar* reg_name,SQRegFunction *methods,SQRegFunction *globals)
348 if(sq_gettype(v,-1) != OT_TABLE)
349 return sq_throwerror(v,_SC("table expected"));
350 int top = sq_gettop(v);
353 sq_pushregistrytable(v);
354 sq_pushstring(v,reg_name,-1);
355 sq_pushstring(v,_SC("std_stream"),-1);
356 if(SQ_SUCCEEDED(sq_get(v,-3))) {
357 sq_newclass(v,SQTrue);
358 sq_settypetag(v,-1,typetag);
360 while(methods[i].name != 0) {
361 SQRegFunction &f = methods[i];
362 sq_pushstring(v,f.name,-1);
363 sq_newclosure(v,f.f,0);
364 sq_setparamscheck(v,f.nparamscheck,f.typemask);
365 sq_setnativeclosurename(v,-1,f.name);
373 while(globals[i].name!=0)
375 SQRegFunction &f = globals[i];
376 sq_pushstring(v,f.name,-1);
377 sq_newclosure(v,f.f,0);
378 sq_setparamscheck(v,f.nparamscheck,f.typemask);
379 sq_setnativeclosurename(v,-1,f.name);
383 //register the class in the target table
384 sq_pushstring(v,name,-1);
385 sq_pushregistrytable(v);
386 sq_pushstring(v,reg_name,-1);