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