Release 3.8.
[wine.git] / dlls / jscript / vbarray.c
blob23122282e723d1975157f71bb6df80ee1958fb80
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 const WCHAR dimensionsW[] = {'d','i','m','e','n','s','i','o','n','s',0};
32 static const WCHAR getItemW[] = {'g','e','t','I','t','e','m',0};
33 static const WCHAR lboundW[] = {'l','b','o','u','n','d',0};
34 static const WCHAR toArrayW[] = {'t','o','A','r','r','a','y',0};
35 static const WCHAR uboundW[] = {'u','b','o','u','n','d',0};
37 static inline VBArrayInstance *vbarray_from_jsdisp(jsdisp_t *jsdisp)
39 return CONTAINING_RECORD(jsdisp, VBArrayInstance, dispex);
42 static inline VBArrayInstance *vbarray_from_vdisp(vdisp_t *vdisp)
44 return vbarray_from_jsdisp(vdisp->u.jsdisp);
47 static inline VBArrayInstance *vbarray_this(vdisp_t *jsthis)
49 return is_vclass(jsthis, JSCLASS_VBARRAY) ? vbarray_from_vdisp(jsthis) : NULL;
52 static HRESULT VBArray_dimensions(script_ctx_t *ctx, vdisp_t *vthis, WORD flags, unsigned argc, jsval_t *argv,
53 jsval_t *r)
55 VBArrayInstance *vbarray;
57 TRACE("\n");
59 vbarray = vbarray_this(vthis);
60 if(!vbarray)
61 return throw_type_error(ctx, JS_E_VBARRAY_EXPECTED, NULL);
63 if(r)
64 *r = jsval_number(SafeArrayGetDim(vbarray->safearray));
65 return S_OK;
68 static HRESULT VBArray_getItem(script_ctx_t *ctx, vdisp_t *vthis, WORD flags, unsigned argc, jsval_t *argv,
69 jsval_t *r)
71 VBArrayInstance *vbarray;
72 int i, *indexes;
73 VARIANT out;
74 HRESULT hres;
76 TRACE("\n");
78 vbarray = vbarray_this(vthis);
79 if(!vbarray)
80 return throw_type_error(ctx, JS_E_VBARRAY_EXPECTED, NULL);
82 if(argc < SafeArrayGetDim(vbarray->safearray))
83 return throw_range_error(ctx, JS_E_SUBSCRIPT_OUT_OF_RANGE, NULL);
85 indexes = heap_alloc(sizeof(int)*argc);
86 if(!indexes)
87 return E_OUTOFMEMORY;
89 for(i=0; i<argc; i++) {
90 hres = to_int32(ctx, argv[i], indexes+i);
91 if(FAILED(hres)) {
92 heap_free(indexes);
93 return hres;
97 hres = SafeArrayGetElement(vbarray->safearray, indexes, (void*)&out);
98 heap_free(indexes);
99 if(hres == DISP_E_BADINDEX)
100 return throw_range_error(ctx, JS_E_SUBSCRIPT_OUT_OF_RANGE, NULL);
101 else if(FAILED(hres))
102 return hres;
104 if(r) {
105 hres = variant_to_jsval(&out, r);
106 VariantClear(&out);
108 return hres;
111 static HRESULT VBArray_lbound(script_ctx_t *ctx, vdisp_t *vthis, WORD flags, unsigned argc, jsval_t *argv,
112 jsval_t *r)
114 VBArrayInstance *vbarray;
115 int dim;
116 HRESULT hres;
118 TRACE("\n");
120 vbarray = vbarray_this(vthis);
121 if(!vbarray)
122 return throw_type_error(ctx, JS_E_VBARRAY_EXPECTED, NULL);
124 if(argc) {
125 hres = to_int32(ctx, argv[0], &dim);
126 if(FAILED(hres))
127 return hres;
128 } else
129 dim = 1;
131 hres = SafeArrayGetLBound(vbarray->safearray, dim, &dim);
132 if(hres == DISP_E_BADINDEX)
133 return throw_range_error(ctx, JS_E_SUBSCRIPT_OUT_OF_RANGE, NULL);
134 else if(FAILED(hres))
135 return hres;
137 if(r)
138 *r = jsval_number(dim);
139 return S_OK;
142 static HRESULT VBArray_toArray(script_ctx_t *ctx, vdisp_t *vthis, WORD flags, unsigned argc, jsval_t *argv,
143 jsval_t *r)
145 VBArrayInstance *vbarray;
146 jsdisp_t *array;
147 jsval_t val;
148 VARIANT *v;
149 int i, size = 1, ubound, lbound;
150 HRESULT hres;
152 TRACE("\n");
154 vbarray = vbarray_this(vthis);
155 if(!vbarray)
156 return throw_type_error(ctx, JS_E_VBARRAY_EXPECTED, NULL);
158 for(i=1; i<=SafeArrayGetDim(vbarray->safearray); i++) {
159 SafeArrayGetLBound(vbarray->safearray, i, &lbound);
160 SafeArrayGetUBound(vbarray->safearray, i, &ubound);
161 size *= ubound-lbound+1;
164 hres = SafeArrayAccessData(vbarray->safearray, (void**)&v);
165 if(FAILED(hres))
166 return hres;
168 hres = create_array(ctx, 0, &array);
169 if(FAILED(hres)) {
170 SafeArrayUnaccessData(vbarray->safearray);
171 return hres;
174 for(i=0; i<size; i++) {
175 hres = variant_to_jsval(v, &val);
176 if(SUCCEEDED(hres)) {
177 hres = jsdisp_propput_idx(array, i, val);
178 jsval_release(val);
180 if(FAILED(hres)) {
181 SafeArrayUnaccessData(vbarray->safearray);
182 jsdisp_release(array);
183 return hres;
185 v++;
188 SafeArrayUnaccessData(vbarray->safearray);
190 if(r)
191 *r = jsval_obj(array);
192 else
193 jsdisp_release(array);
194 return S_OK;
197 static HRESULT VBArray_ubound(script_ctx_t *ctx, vdisp_t *vthis, WORD flags, unsigned argc, jsval_t *argv,
198 jsval_t *r)
200 VBArrayInstance *vbarray;
201 int dim;
202 HRESULT hres;
204 TRACE("\n");
206 vbarray = vbarray_this(vthis);
207 if(!vbarray)
208 return throw_type_error(ctx, JS_E_VBARRAY_EXPECTED, NULL);
210 if(argc) {
211 hres = to_int32(ctx, argv[0], &dim);
212 if(FAILED(hres))
213 return hres;
214 } else
215 dim = 1;
217 hres = SafeArrayGetUBound(vbarray->safearray, dim, &dim);
218 if(hres == DISP_E_BADINDEX)
219 return throw_range_error(ctx, JS_E_SUBSCRIPT_OUT_OF_RANGE, NULL);
220 else if(FAILED(hres))
221 return hres;
223 if(r)
224 *r = jsval_number(dim);
225 return S_OK;
228 static HRESULT VBArray_value(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv,
229 jsval_t *r)
231 FIXME("\n");
233 switch(flags) {
234 default:
235 FIXME("unimplemented flags %x\n", flags);
236 return E_NOTIMPL;
239 return S_OK;
242 static void VBArray_destructor(jsdisp_t *dispex)
244 VBArrayInstance *vbarray = vbarray_from_jsdisp(dispex);
246 SafeArrayDestroy(vbarray->safearray);
247 heap_free(vbarray);
250 static const builtin_prop_t VBArray_props[] = {
251 {dimensionsW, VBArray_dimensions, PROPF_METHOD},
252 {getItemW, VBArray_getItem, PROPF_METHOD|1},
253 {lboundW, VBArray_lbound, PROPF_METHOD},
254 {toArrayW, VBArray_toArray, PROPF_METHOD},
255 {uboundW, VBArray_ubound, PROPF_METHOD}
258 static const builtin_info_t VBArray_info = {
259 JSCLASS_VBARRAY,
260 {NULL, VBArray_value, 0},
261 sizeof(VBArray_props)/sizeof(*VBArray_props),
262 VBArray_props,
263 VBArray_destructor,
264 NULL
267 static HRESULT alloc_vbarray(script_ctx_t *ctx, jsdisp_t *object_prototype, VBArrayInstance **ret)
269 VBArrayInstance *vbarray;
270 HRESULT hres;
272 vbarray = heap_alloc_zero(sizeof(VBArrayInstance));
273 if(!vbarray)
274 return E_OUTOFMEMORY;
276 if(object_prototype)
277 hres = init_dispex(&vbarray->dispex, ctx, &VBArray_info, object_prototype);
278 else
279 hres = init_dispex_from_constr(&vbarray->dispex, ctx, &VBArray_info, ctx->vbarray_constr);
281 if(FAILED(hres)) {
282 heap_free(vbarray);
283 return hres;
286 *ret = vbarray;
287 return S_OK;
290 static HRESULT VBArrayConstr_value(script_ctx_t *ctx, vdisp_t *vthis, WORD flags, unsigned argc, jsval_t *argv,
291 jsval_t *r)
293 VBArrayInstance *vbarray;
294 HRESULT hres;
296 TRACE("\n");
298 switch(flags) {
299 case DISPATCH_METHOD:
300 if(argc<1 || !is_variant(argv[0]) || V_VT(get_variant(argv[0])) != (VT_ARRAY|VT_VARIANT))
301 return throw_type_error(ctx, JS_E_VBARRAY_EXPECTED, NULL);
303 return jsval_copy(argv[0], r);
305 case DISPATCH_CONSTRUCT:
306 if(argc<1 || !is_variant(argv[0]) || V_VT(get_variant(argv[0])) != (VT_ARRAY|VT_VARIANT))
307 return throw_type_error(ctx, JS_E_VBARRAY_EXPECTED, NULL);
309 hres = alloc_vbarray(ctx, NULL, &vbarray);
310 if(FAILED(hres))
311 return hres;
313 hres = SafeArrayCopy(V_ARRAY(get_variant(argv[0])), &vbarray->safearray);
314 if(FAILED(hres)) {
315 jsdisp_release(&vbarray->dispex);
316 return hres;
319 *r = jsval_obj(&vbarray->dispex);
320 break;
322 default:
323 FIXME("unimplemented flags: %x\n", flags);
324 return E_NOTIMPL;
327 return S_OK;
330 HRESULT create_vbarray_constr(script_ctx_t *ctx, jsdisp_t *object_prototype, jsdisp_t **ret)
332 VBArrayInstance *vbarray;
333 HRESULT hres;
335 static const WCHAR VBArrayW[] = {'V','B','A','r','r','a','y',0};
337 hres = alloc_vbarray(ctx, object_prototype, &vbarray);
338 if(FAILED(hres))
339 return hres;
341 hres = create_builtin_constructor(ctx, VBArrayConstr_value, VBArrayW, NULL, PROPF_CONSTR|1, &vbarray->dispex, ret);
343 jsdisp_release(&vbarray->dispex);
344 return hres;
347 HRESULT create_vbarray(script_ctx_t *ctx, SAFEARRAY *sa, jsdisp_t **ret)
349 VBArrayInstance *vbarray;
350 HRESULT hres;
352 hres = alloc_vbarray(ctx, NULL, &vbarray);
353 if(FAILED(hres))
354 return hres;
356 hres = SafeArrayCopy(sa, &vbarray->safearray);
357 if(FAILED(hres)) {
358 jsdisp_release(&vbarray->dispex);
359 return hres;
362 *ret = &vbarray->dispex;
363 return S_OK;