include/mscvpdb.h: Use flexible array members for the rest of structures.
[wine.git] / dlls / jscript / vbarray.c
blob55500c86769e69dbdbfd35e83c4ff5c7c185285e
1 /*
2 * Copyright 2010 Piotr Caban for CodeWeavers
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19 #include "jscript.h"
21 #include "wine/debug.h"
23 WINE_DEFAULT_DEBUG_CHANNEL(jscript);
25 typedef struct {
26 jsdisp_t dispex;
28 SAFEARRAY *safearray;
29 } VBArrayInstance;
31 static inline VBArrayInstance *vbarray_from_jsdisp(jsdisp_t *jsdisp)
33 return CONTAINING_RECORD(jsdisp, VBArrayInstance, dispex);
36 static inline VBArrayInstance *vbarray_this(jsval_t vthis)
38 jsdisp_t *jsdisp = is_object_instance(vthis) ? to_jsdisp(get_object(vthis)) : NULL;
39 return (jsdisp && is_class(jsdisp, JSCLASS_VBARRAY)) ? vbarray_from_jsdisp(jsdisp) : NULL;
42 static HRESULT VBArray_dimensions(script_ctx_t *ctx, jsval_t vthis, WORD flags, unsigned argc, jsval_t *argv,
43 jsval_t *r)
45 VBArrayInstance *vbarray;
47 TRACE("\n");
49 vbarray = vbarray_this(vthis);
50 if(!vbarray)
51 return JS_E_VBARRAY_EXPECTED;
53 if(r)
54 *r = jsval_number(SafeArrayGetDim(vbarray->safearray));
55 return S_OK;
58 static HRESULT VBArray_getItem(script_ctx_t *ctx, jsval_t vthis, WORD flags, unsigned argc, jsval_t *argv,
59 jsval_t *r)
61 VBArrayInstance *vbarray;
62 unsigned i;
63 LONG *indexes;
64 VARIANT out;
65 HRESULT hres;
67 TRACE("\n");
69 vbarray = vbarray_this(vthis);
70 if(!vbarray)
71 return JS_E_VBARRAY_EXPECTED;
73 if(argc < SafeArrayGetDim(vbarray->safearray))
74 return JS_E_SUBSCRIPT_OUT_OF_RANGE;
76 indexes = malloc(sizeof(indexes[0])*argc);
77 if(!indexes)
78 return E_OUTOFMEMORY;
80 for(i=0; i<argc; i++) {
81 hres = to_long(ctx, argv[i], indexes + i);
82 if(FAILED(hres)) {
83 free(indexes);
84 return hres;
88 hres = SafeArrayGetElement(vbarray->safearray, indexes, (void*)&out);
89 free(indexes);
90 if(hres == DISP_E_BADINDEX)
91 return JS_E_SUBSCRIPT_OUT_OF_RANGE;
92 else if(FAILED(hres))
93 return hres;
95 if(r) {
96 hres = variant_to_jsval(ctx, &out, r);
97 VariantClear(&out);
99 return hres;
102 static HRESULT VBArray_lbound(script_ctx_t *ctx, jsval_t vthis, WORD flags, unsigned argc, jsval_t *argv,
103 jsval_t *r)
105 VBArrayInstance *vbarray;
106 LONG dim;
107 HRESULT hres;
109 TRACE("\n");
111 vbarray = vbarray_this(vthis);
112 if(!vbarray)
113 return JS_E_VBARRAY_EXPECTED;
115 if(argc) {
116 hres = to_long(ctx, argv[0], &dim);
117 if(FAILED(hres))
118 return hres;
119 } else
120 dim = 1;
122 hres = SafeArrayGetLBound(vbarray->safearray, dim, &dim);
123 if(hres == DISP_E_BADINDEX)
124 return JS_E_SUBSCRIPT_OUT_OF_RANGE;
125 else if(FAILED(hres))
126 return hres;
128 if(r)
129 *r = jsval_number(dim);
130 return S_OK;
133 static HRESULT VBArray_toArray(script_ctx_t *ctx, jsval_t vthis, WORD flags, unsigned argc, jsval_t *argv,
134 jsval_t *r)
136 VBArrayInstance *vbarray;
137 jsdisp_t *array;
138 jsval_t val;
139 VARIANT *v;
140 LONG i, size = 1, ubound, lbound;
141 HRESULT hres;
143 TRACE("\n");
145 vbarray = vbarray_this(vthis);
146 if(!vbarray)
147 return JS_E_VBARRAY_EXPECTED;
149 for(i=1; i<=SafeArrayGetDim(vbarray->safearray); i++) {
150 SafeArrayGetLBound(vbarray->safearray, i, &lbound);
151 SafeArrayGetUBound(vbarray->safearray, i, &ubound);
152 size *= ubound-lbound+1;
155 hres = SafeArrayAccessData(vbarray->safearray, (void**)&v);
156 if(FAILED(hres))
157 return hres;
159 hres = create_array(ctx, 0, &array);
160 if(FAILED(hres)) {
161 SafeArrayUnaccessData(vbarray->safearray);
162 return hres;
165 for(i=0; i<size; i++) {
166 hres = variant_to_jsval(ctx, v, &val);
167 if(SUCCEEDED(hres)) {
168 hres = jsdisp_propput_idx(array, i, val);
169 jsval_release(val);
171 if(FAILED(hres)) {
172 SafeArrayUnaccessData(vbarray->safearray);
173 jsdisp_release(array);
174 return hres;
176 v++;
179 SafeArrayUnaccessData(vbarray->safearray);
181 if(r)
182 *r = jsval_obj(array);
183 else
184 jsdisp_release(array);
185 return S_OK;
188 static HRESULT VBArray_ubound(script_ctx_t *ctx, jsval_t vthis, WORD flags, unsigned argc, jsval_t *argv,
189 jsval_t *r)
191 VBArrayInstance *vbarray;
192 LONG dim;
193 HRESULT hres;
195 TRACE("\n");
197 vbarray = vbarray_this(vthis);
198 if(!vbarray)
199 return JS_E_VBARRAY_EXPECTED;
201 if(argc) {
202 hres = to_long(ctx, argv[0], &dim);
203 if(FAILED(hres))
204 return hres;
205 } else
206 dim = 1;
208 hres = SafeArrayGetUBound(vbarray->safearray, dim, &dim);
209 if(hres == DISP_E_BADINDEX)
210 return JS_E_SUBSCRIPT_OUT_OF_RANGE;
211 else if(FAILED(hres))
212 return hres;
214 if(r)
215 *r = jsval_number(dim);
216 return S_OK;
219 static HRESULT VBArray_value(script_ctx_t *ctx, jsval_t vthis, WORD flags, unsigned argc, jsval_t *argv,
220 jsval_t *r)
222 FIXME("\n");
224 switch(flags) {
225 default:
226 FIXME("unimplemented flags %x\n", flags);
227 return E_NOTIMPL;
230 return S_OK;
233 static void VBArray_destructor(jsdisp_t *dispex)
235 VBArrayInstance *vbarray = vbarray_from_jsdisp(dispex);
237 SafeArrayDestroy(vbarray->safearray);
240 static const builtin_prop_t VBArray_props[] = {
241 {L"dimensions", VBArray_dimensions, PROPF_METHOD},
242 {L"getItem", VBArray_getItem, PROPF_METHOD|1},
243 {L"lbound", VBArray_lbound, PROPF_METHOD},
244 {L"toArray", VBArray_toArray, PROPF_METHOD},
245 {L"ubound", VBArray_ubound, PROPF_METHOD}
248 static const builtin_info_t VBArray_info = {
249 .class = JSCLASS_VBARRAY,
250 .call = VBArray_value,
251 .props_cnt = ARRAY_SIZE(VBArray_props),
252 .props = VBArray_props,
253 .destructor = VBArray_destructor,
256 static HRESULT alloc_vbarray(script_ctx_t *ctx, jsdisp_t *object_prototype, VBArrayInstance **ret)
258 VBArrayInstance *vbarray;
259 HRESULT hres;
261 vbarray = calloc(1, sizeof(VBArrayInstance));
262 if(!vbarray)
263 return E_OUTOFMEMORY;
265 if(object_prototype)
266 hres = init_dispex(&vbarray->dispex, ctx, &VBArray_info, object_prototype);
267 else
268 hres = init_dispex_from_constr(&vbarray->dispex, ctx, &VBArray_info, ctx->vbarray_constr);
270 if(FAILED(hres)) {
271 free(vbarray);
272 return hres;
275 *ret = vbarray;
276 return S_OK;
279 static HRESULT VBArrayConstr_value(script_ctx_t *ctx, jsval_t vthis, WORD flags, unsigned argc, jsval_t *argv,
280 jsval_t *r)
282 VBArrayInstance *vbarray;
283 HRESULT hres;
285 TRACE("\n");
287 switch(flags) {
288 case DISPATCH_METHOD:
289 if(argc<1 || !is_variant(argv[0]) || V_VT(get_variant(argv[0])) != (VT_ARRAY|VT_VARIANT))
290 return JS_E_VBARRAY_EXPECTED;
292 return r ? jsval_copy(argv[0], r) : S_OK;
294 case DISPATCH_CONSTRUCT:
295 if(argc<1 || !is_variant(argv[0]) || V_VT(get_variant(argv[0])) != (VT_ARRAY|VT_VARIANT))
296 return JS_E_VBARRAY_EXPECTED;
297 if(!r)
298 return S_OK;
300 hres = alloc_vbarray(ctx, NULL, &vbarray);
301 if(FAILED(hres))
302 return hres;
304 hres = SafeArrayCopy(V_ARRAY(get_variant(argv[0])), &vbarray->safearray);
305 if(FAILED(hres)) {
306 jsdisp_release(&vbarray->dispex);
307 return hres;
310 *r = jsval_obj(&vbarray->dispex);
311 break;
313 default:
314 FIXME("unimplemented flags: %x\n", flags);
315 return E_NOTIMPL;
318 return S_OK;
321 HRESULT create_vbarray_constr(script_ctx_t *ctx, jsdisp_t *object_prototype, jsdisp_t **ret)
323 VBArrayInstance *vbarray;
324 HRESULT hres;
326 hres = alloc_vbarray(ctx, object_prototype, &vbarray);
327 if(FAILED(hres))
328 return hres;
330 hres = create_builtin_constructor(ctx, VBArrayConstr_value, L"VBArray", NULL, PROPF_CONSTR|1, &vbarray->dispex, ret);
332 jsdisp_release(&vbarray->dispex);
333 return hres;
336 HRESULT create_vbarray(script_ctx_t *ctx, SAFEARRAY *sa, jsdisp_t **ret)
338 VBArrayInstance *vbarray;
339 HRESULT hres;
341 hres = alloc_vbarray(ctx, NULL, &vbarray);
342 if(FAILED(hres))
343 return hres;
345 hres = SafeArrayCopy(sa, &vbarray->safearray);
346 if(FAILED(hres)) {
347 jsdisp_release(&vbarray->dispex);
348 return hres;
351 *ret = &vbarray->dispex;
352 return S_OK;