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