1 /* see copyright notice in squirrel.h */
2 #include <new>
3 #include <squirrel.h>
4 #include <sqstdio.h>
5 #include <string.h>
6 #include <sqstdblob.h>
7 #include "sqstdstream.h"
8 #include "sqstdblobimpl.h"
9 
10 #define SQSTD_BLOB_TYPE_TAG (SQSTD_STREAM_TYPE_TAG | 0x00000002)
11 
12 //Blob
13 
14 
15 #define SETUP_BLOB(v) \
16 	SQBlob *self = NULL; \
17 	{ if(SQ_FAILED(sq_getinstanceup(v,1,(SQUserPointer*)&self,(SQUserPointer)SQSTD_BLOB_TYPE_TAG))) \
18 		return SQ_ERROR; }
19 
20 
_blob_resize(HSQUIRRELVM v)21 static SQInteger _blob_resize(HSQUIRRELVM v)
22 {
23 	SETUP_BLOB(v);
24 	SQInteger size;
25 	sq_getinteger(v,2,&size);
26 	if(!self->Resize(size))
27 		return sq_throwerror(v,_SC("resize failed"));
28 	return 0;
29 }
30 
__swap_dword(unsigned int * n)31 static void __swap_dword(unsigned int *n)
32 {
33 	*n=(unsigned int)(((*n&0xFF000000)>>24)  |
34 			((*n&0x00FF0000)>>8)  |
35 			((*n&0x0000FF00)<<8)  |
36 			((*n&0x000000FF)<<24));
37 }
38 
__swap_word(unsigned short * n)39 static void __swap_word(unsigned short *n)
40 {
41 	*n=(unsigned short)((*n>>8)&0x00FF)| ((*n<<8)&0xFF00);
42 }
43 
_blob_swap4(HSQUIRRELVM v)44 static SQInteger _blob_swap4(HSQUIRRELVM v)
45 {
46 	SETUP_BLOB(v);
47 	SQInteger num=(self->Len()-(self->Len()%4))>>2;
48 	unsigned int *t=(unsigned int *)self->GetBuf();
49 	for(SQInteger i = 0; i < num; i++) {
50 		__swap_dword(&t[i]);
51 	}
52 	return 0;
53 }
54 
_blob_swap2(HSQUIRRELVM v)55 static SQInteger _blob_swap2(HSQUIRRELVM v)
56 {
57 	SETUP_BLOB(v);
58 	SQInteger num=(self->Len()-(self->Len()%2))>>1;
59 	unsigned short *t = (unsigned short *)self->GetBuf();
60 	for(SQInteger i = 0; i < num; i++) {
61 		__swap_word(&t[i]);
62 	}
63 	return 0;
64 }
65 
_blob__set(HSQUIRRELVM v)66 static SQInteger _blob__set(HSQUIRRELVM v)
67 {
68 	SETUP_BLOB(v);
69 	SQInteger idx,val;
70 	sq_getinteger(v,2,&idx);
71 	sq_getinteger(v,3,&val);
72 	if(idx < 0 || idx >= self->Len())
73 		return sq_throwerror(v,_SC("index out of range"));
74 	((unsigned char *)self->GetBuf())[idx] = (unsigned char) val;
75 	sq_push(v,3);
76 	return 1;
77 }
78 
_blob__get(HSQUIRRELVM v)79 static SQInteger _blob__get(HSQUIRRELVM v)
80 {
81 	SETUP_BLOB(v);
82 	SQInteger idx;
83 	sq_getinteger(v,2,&idx);
84 	if(idx < 0 || idx >= self->Len())
85 		return sq_throwerror(v,_SC("index out of range"));
86 	sq_pushinteger(v,((unsigned char *)self->GetBuf())[idx]);
87 	return 1;
88 }
89 
_blob__nexti(HSQUIRRELVM v)90 static SQInteger _blob__nexti(HSQUIRRELVM v)
91 {
92 	SETUP_BLOB(v);
93 	if(sq_gettype(v,2) == OT_NULL) {
94 		sq_pushinteger(v, 0);
95 		return 1;
96 	}
97 	SQInteger idx;
98 	if(SQ_SUCCEEDED(sq_getinteger(v, 2, &idx))) {
99 		if(idx+1 < self->Len()) {
100 			sq_pushinteger(v, idx+1);
101 			return 1;
102 		}
103 		sq_pushnull(v);
104 		return 1;
105 	}
106 	return sq_throwerror(v,_SC("internal error (_nexti) wrong argument type"));
107 }
108 
_blob__typeof(HSQUIRRELVM v)109 static SQInteger _blob__typeof(HSQUIRRELVM v)
110 {
111 	sq_pushstring(v,_SC("blob"),-1);
112 	return 1;
113 }
114 
115 // C::B patch: Make the compiler happy by commenting unused variables
_blob_releasehook(SQUserPointer p,SQInteger)116 static SQInteger _blob_releasehook(SQUserPointer p, SQInteger /*size*/)
117 {
118 	SQBlob *self = (SQBlob*)p;
119 	delete self;
120 	return 1;
121 }
122 
_blob_constructor(HSQUIRRELVM v)123 static SQInteger _blob_constructor(HSQUIRRELVM v)
124 {
125 	SQInteger nparam = sq_gettop(v);
126 	SQInteger size = 0;
127 	if(nparam == 2) {
128 		sq_getinteger(v, 2, &size);
129 	}
130 	if(size < 0) return sq_throwerror(v, _SC("cannot create blob with negative size"));
131 	SQBlob *b = new SQBlob(size);
132 	if(SQ_FAILED(sq_setinstanceup(v,1,b))) {
133 		delete b;
134 		return sq_throwerror(v, _SC("cannot create blob with negative size"));
135 	}
136 	sq_setreleasehook(v,1,_blob_releasehook);
137 	return 0;
138 }
139 
140 #define _DECL_BLOB_FUNC(name,nparams,typecheck) {_SC(#name),_blob_##name,nparams,typecheck}
141 static SQRegFunction _blob_methods[] = {
142 	_DECL_BLOB_FUNC(constructor,-1,_SC("xn")),
143 	_DECL_BLOB_FUNC(resize,2,_SC("xn")),
144 	_DECL_BLOB_FUNC(swap2,1,_SC("x")),
145 	_DECL_BLOB_FUNC(swap4,1,_SC("x")),
146 	_DECL_BLOB_FUNC(_set,3,_SC("xnn")),
147 	_DECL_BLOB_FUNC(_get,2,_SC("xn")),
148 	_DECL_BLOB_FUNC(_typeof,1,_SC("x")),
149 	_DECL_BLOB_FUNC(_nexti,2,_SC("x")),
150 	{0,0,0,0}
151 };
152 
153 
154 
155 //GLOBAL FUNCTIONS
156 
_g_blob_casti2f(HSQUIRRELVM v)157 static SQInteger _g_blob_casti2f(HSQUIRRELVM v)
158 {
159 	SQInteger i;
160 	sq_getinteger(v,2,&i);
161 	sq_pushfloat(v,*((SQFloat *)&i));
162 	return 1;
163 }
164 
_g_blob_castf2i(HSQUIRRELVM v)165 static SQInteger _g_blob_castf2i(HSQUIRRELVM v)
166 {
167 	SQFloat f;
168 	sq_getfloat(v,2,&f);
169 	sq_pushinteger(v,*((SQInteger *)&f));
170 	return 1;
171 }
172 
_g_blob_swap2(HSQUIRRELVM v)173 static SQInteger _g_blob_swap2(HSQUIRRELVM v)
174 {
175 	SQInteger i;
176 	sq_getinteger(v,2,&i);
177 	short s=(short)i;
178 	sq_pushinteger(v,(s<<8)|((s>>8)&0x00FF));
179 	return 1;
180 }
181 
_g_blob_swap4(HSQUIRRELVM v)182 static SQInteger _g_blob_swap4(HSQUIRRELVM v)
183 {
184 	SQInteger i;
185 	sq_getinteger(v,2,&i);
186 	unsigned int t4 = (unsigned int)i;
187 	__swap_dword(&t4);
188 	sq_pushinteger(v,(SQInteger)t4);
189 	return 1;
190 }
191 
_g_blob_swapfloat(HSQUIRRELVM v)192 static SQInteger _g_blob_swapfloat(HSQUIRRELVM v)
193 {
194 	SQFloat f;
195 	sq_getfloat(v,2,&f);
196 	__swap_dword((unsigned int *)&f);
197 	sq_pushfloat(v,f);
198 	return 1;
199 }
200 
201 #define _DECL_GLOBALBLOB_FUNC(name,nparams,typecheck) {_SC(#name),_g_blob_##name,nparams,typecheck}
202 static SQRegFunction bloblib_funcs[]={
203 	_DECL_GLOBALBLOB_FUNC(casti2f,2,_SC(".n")),
204 	_DECL_GLOBALBLOB_FUNC(castf2i,2,_SC(".n")),
205 	_DECL_GLOBALBLOB_FUNC(swap2,2,_SC(".n")),
206 	_DECL_GLOBALBLOB_FUNC(swap4,2,_SC(".n")),
207 	_DECL_GLOBALBLOB_FUNC(swapfloat,2,_SC(".n")),
208 	{0,0}
209 };
210 
sqstd_getblob(HSQUIRRELVM v,SQInteger idx,SQUserPointer * ptr)211 SQRESULT sqstd_getblob(HSQUIRRELVM v,SQInteger idx,SQUserPointer *ptr)
212 {
213 	SQBlob *blob;
214 	if(SQ_FAILED(sq_getinstanceup(v,idx,(SQUserPointer *)&blob,(SQUserPointer)SQSTD_BLOB_TYPE_TAG)))
215 		return -1;
216 	*ptr = blob->GetBuf();
217 	return SQ_OK;
218 }
219 
sqstd_getblobsize(HSQUIRRELVM v,SQInteger idx)220 SQInteger sqstd_getblobsize(HSQUIRRELVM v,SQInteger idx)
221 {
222 	SQBlob *blob;
223 	if(SQ_FAILED(sq_getinstanceup(v,idx,(SQUserPointer *)&blob,(SQUserPointer)SQSTD_BLOB_TYPE_TAG)))
224 		return -1;
225 	return blob->Len();
226 }
227 
sqstd_createblob(HSQUIRRELVM v,SQInteger size)228 SQUserPointer sqstd_createblob(HSQUIRRELVM v, SQInteger size)
229 {
230 	SQInteger top = sq_gettop(v);
231 	sq_pushregistrytable(v);
232 	sq_pushstring(v,_SC("std_blob"),-1);
233 	if(SQ_SUCCEEDED(sq_get(v,-2))) {
234 		sq_remove(v,-2); //removes the registry
235 		sq_push(v,1); // push the this
236 		sq_pushinteger(v,size); //size
237 		SQBlob *blob = NULL;
238 		if(SQ_SUCCEEDED(sq_call(v,2,SQTrue,SQFalse))
239 			&& SQ_SUCCEEDED(sq_getinstanceup(v,-1,(SQUserPointer *)&blob,(SQUserPointer)SQSTD_BLOB_TYPE_TAG))) {
240 			sq_remove(v,-2);
241 			return blob->GetBuf();
242 		}
243 	}
244 	sq_settop(v,top);
245 	return NULL;
246 }
247 
sqstd_register_bloblib(HSQUIRRELVM v)248 SQRESULT sqstd_register_bloblib(HSQUIRRELVM v)
249 {
250 	return declare_stream(v,_SC("blob"),(SQUserPointer)SQSTD_BLOB_TYPE_TAG,_SC("std_blob"),_blob_methods,bloblib_funcs);
251 }
252 
253