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_readblob(HSQUIRRELVM v)
\r
22 SQUserPointer data,blobp;
\r
24 sq_getinteger(v,2,&size);
\r
25 if(size > self->Len()) {
\r
28 data = sq_getscratchpad(v,size);
\r
29 res = self->Read(data,size);
\r
31 return sq_throwerror(v,_SC("no data left to read"));
\r
32 blobp = sqstd_createblob(v,res);
\r
33 memcpy(blobp,data,res);
\r
37 #define SAFE_READN(ptr,len) { \
\r
38 if(self->Read(ptr,len) != len) return sq_throwerror(v,_SC("io error")); \
\r
40 SQInteger _stream_readn(HSQUIRRELVM v)
\r
44 sq_getinteger(v, 2, &format);
\r
48 SAFE_READN(&i, sizeof(i));
\r
49 sq_pushinteger(v, i);
\r
54 SAFE_READN(&i, sizeof(i));
\r
55 sq_pushinteger(v, i);
\r
60 SAFE_READN(&s, sizeof(short));
\r
61 sq_pushinteger(v, s);
\r
66 SAFE_READN(&w, sizeof(unsigned short));
\r
67 sq_pushinteger(v, w);
\r
72 SAFE_READN(&c, sizeof(char));
\r
73 sq_pushinteger(v, c);
\r
78 SAFE_READN(&c, sizeof(unsigned char));
\r
79 sq_pushinteger(v, c);
\r
84 SAFE_READN(&f, sizeof(float));
\r
90 SAFE_READN(&d, sizeof(double));
\r
91 sq_pushfloat(v, (SQFloat)d);
\r
95 return sq_throwerror(v, _SC("invalid format"));
\r
100 SQInteger _stream_writeblob(HSQUIRRELVM v)
\r
102 SQUserPointer data;
\r
105 if(SQ_FAILED(sqstd_getblob(v,2,&data)))
\r
106 return sq_throwerror(v,_SC("invalid parameter"));
\r
107 size = sqstd_getblobsize(v,2);
\r
108 if(self->Write(data,size) != size)
\r
109 return sq_throwerror(v,_SC("io error"));
\r
110 sq_pushinteger(v,size);
\r
114 SQInteger _stream_writen(HSQUIRRELVM v)
\r
117 SQInteger format, ti;
\r
119 sq_getinteger(v, 3, &format);
\r
123 sq_getinteger(v, 2, &ti);
\r
125 self->Write(&i, sizeof(SQInteger));
\r
130 sq_getinteger(v, 2, &ti);
\r
132 self->Write(&i, sizeof(SQInt32));
\r
137 sq_getinteger(v, 2, &ti);
\r
139 self->Write(&s, sizeof(short));
\r
144 sq_getinteger(v, 2, &ti);
\r
145 w = (unsigned short)ti;
\r
146 self->Write(&w, sizeof(unsigned short));
\r
151 sq_getinteger(v, 2, &ti);
\r
153 self->Write(&c, sizeof(char));
\r
158 sq_getinteger(v, 2, &ti);
\r
159 b = (unsigned char)ti;
\r
160 self->Write(&b, sizeof(unsigned char));
\r
165 sq_getfloat(v, 2, &tf);
\r
167 self->Write(&f, sizeof(float));
\r
172 sq_getfloat(v, 2, &tf);
\r
174 self->Write(&d, sizeof(double));
\r
178 return sq_throwerror(v, _SC("invalid format"));
\r
183 SQInteger _stream_seek(HSQUIRRELVM v)
\r
186 SQInteger offset, origin = SQ_SEEK_SET;
\r
187 sq_getinteger(v, 2, &offset);
\r
188 if(sq_gettop(v) > 2) {
\r
190 sq_getinteger(v, 3, &t);
\r
192 case 'b': origin = SQ_SEEK_SET; break;
\r
193 case 'c': origin = SQ_SEEK_CUR; break;
\r
194 case 'e': origin = SQ_SEEK_END; break;
\r
195 default: return sq_throwerror(v,_SC("invalid origin"));
\r
198 sq_pushinteger(v, self->Seek(offset, origin));
\r
202 SQInteger _stream_tell(HSQUIRRELVM v)
\r
205 sq_pushinteger(v, self->Tell());
\r
209 SQInteger _stream_len(HSQUIRRELVM v)
\r
212 sq_pushinteger(v, self->Len());
\r
216 SQInteger _stream_flush(HSQUIRRELVM v)
\r
220 sq_pushinteger(v, 1);
\r
226 SQInteger _stream_eos(HSQUIRRELVM v)
\r
230 sq_pushinteger(v, 1);
\r
236 static SQRegFunction _stream_methods[] = {
\r
237 _DECL_STREAM_FUNC(readblob,2,_SC("xn")),
\r
238 _DECL_STREAM_FUNC(readn,2,_SC("xn")),
\r
239 _DECL_STREAM_FUNC(writeblob,-2,_SC("xx")),
\r
240 _DECL_STREAM_FUNC(writen,3,_SC("xnn")),
\r
241 _DECL_STREAM_FUNC(seek,-2,_SC("xnn")),
\r
242 _DECL_STREAM_FUNC(tell,1,_SC("x")),
\r
243 _DECL_STREAM_FUNC(len,1,_SC("x")),
\r
244 _DECL_STREAM_FUNC(eos,1,_SC("x")),
\r
245 _DECL_STREAM_FUNC(flush,1,_SC("x")),
\r
249 void init_streamclass(HSQUIRRELVM v)
\r
251 sq_pushregistrytable(v);
\r
252 sq_pushstring(v,_SC("std_stream"),-1);
\r
253 if(SQ_FAILED(sq_get(v,-2))) {
\r
254 sq_pushstring(v,_SC("std_stream"),-1);
\r
255 sq_newclass(v,SQFalse);
\r
256 sq_settypetag(v,-1,(SQUserPointer)SQSTD_STREAM_TYPE_TAG);
\r
258 while(_stream_methods[i].name != 0) {
\r
259 SQRegFunction &f = _stream_methods[i];
\r
260 sq_pushstring(v,f.name,-1);
\r
261 sq_newclosure(v,f.f,0);
\r
262 sq_setparamscheck(v,f.nparamscheck,f.typemask);
\r
263 sq_createslot(v,-3);
\r
266 sq_createslot(v,-3);
\r
267 sq_pushroottable(v);
\r
268 sq_pushstring(v,_SC("stream"),-1);
\r
269 sq_pushstring(v,_SC("std_stream"),-1);
\r
271 sq_createslot(v,-3);
\r
275 sq_pop(v,1); //result
\r
280 SQRESULT declare_stream(HSQUIRRELVM v,SQChar* name,SQUserPointer typetag,SQChar* reg_name,SQRegFunction *methods,SQRegFunction *globals)
\r
282 if(sq_gettype(v,-1) != OT_TABLE)
\r
283 return sq_throwerror(v,_SC("table expected"));
\r
284 SQInteger top = sq_gettop(v);
\r
286 init_streamclass(v);
\r
287 sq_pushregistrytable(v);
\r
288 sq_pushstring(v,reg_name,-1);
\r
289 sq_pushstring(v,_SC("std_stream"),-1);
\r
290 if(SQ_SUCCEEDED(sq_get(v,-3))) {
\r
291 sq_newclass(v,SQTrue);
\r
292 sq_settypetag(v,-1,typetag);
\r
294 while(methods[i].name != 0) {
\r
295 SQRegFunction &f = methods[i];
\r
296 sq_pushstring(v,f.name,-1);
\r
297 sq_newclosure(v,f.f,0);
\r
298 sq_setparamscheck(v,f.nparamscheck,f.typemask);
\r
299 sq_setnativeclosurename(v,-1,f.name);
\r
300 sq_createslot(v,-3);
\r
303 sq_createslot(v,-3);
\r
307 while(globals[i].name!=0)
\r
309 SQRegFunction &f = globals[i];
\r
310 sq_pushstring(v,f.name,-1);
\r
311 sq_newclosure(v,f.f,0);
\r
312 sq_setparamscheck(v,f.nparamscheck,f.typemask);
\r
313 sq_setnativeclosurename(v,-1,f.name);
\r
314 sq_createslot(v,-3);
\r
317 //register the class in the target table
\r
318 sq_pushstring(v,name,-1);
\r
319 sq_pushregistrytable(v);
\r
320 sq_pushstring(v,reg_name,-1);
\r
323 sq_createslot(v,-3);
\r