Release 1.5.13.
[wine.git] / dlls / jscript / vbarray.c
blobac0c6def0c08083adba581388ba11e5aa7d19056
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_vdisp(vdisp_t *vdisp)
39 return (VBArrayInstance*)vdisp->u.jsdisp;
42 static inline VBArrayInstance *vbarray_this(vdisp_t *jsthis)
44 return is_vclass(jsthis, JSCLASS_VBARRAY) ? vbarray_from_vdisp(jsthis) : NULL;
47 static HRESULT VBArray_dimensions(script_ctx_t *ctx, vdisp_t *vthis, WORD flags, unsigned argc, VARIANT *argv,
48 VARIANT *retv, jsexcept_t *ei)
50 VBArrayInstance *vbarray;
52 TRACE("\n");
54 vbarray = vbarray_this(vthis);
55 if(!vbarray)
56 return throw_type_error(ctx, ei, JS_E_VBARRAY_EXPECTED, NULL);
58 if(retv)
59 num_set_int(retv, SafeArrayGetDim(vbarray->safearray));
60 return S_OK;
63 static HRESULT VBArray_getItem(script_ctx_t *ctx, vdisp_t *vthis, WORD flags, unsigned argc, VARIANT *argv,
64 VARIANT *retv, jsexcept_t *ei)
66 VBArrayInstance *vbarray;
67 int i, *indexes;
68 VARIANT out;
69 HRESULT hres;
71 TRACE("\n");
73 vbarray = vbarray_this(vthis);
74 if(!vbarray)
75 return throw_type_error(ctx, ei, JS_E_VBARRAY_EXPECTED, NULL);
77 if(argc < SafeArrayGetDim(vbarray->safearray))
78 return throw_range_error(ctx, ei, JS_E_SUBSCRIPT_OUT_OF_RANGE, NULL);
80 indexes = heap_alloc(sizeof(int)*argc);
81 if(!indexes)
82 return E_OUTOFMEMORY;
84 for(i=0; i<argc; i++) {
85 hres = to_int32(ctx, argv+i, ei, indexes+i);
86 if(FAILED(hres)) {
87 heap_free(indexes);
88 return hres;
92 hres = SafeArrayGetElement(vbarray->safearray, indexes, (void*)&out);
93 heap_free(indexes);
94 if(hres == DISP_E_BADINDEX)
95 return throw_range_error(ctx, ei, JS_E_SUBSCRIPT_OUT_OF_RANGE, NULL);
96 else if(FAILED(hres))
97 return hres;
99 if(retv)
100 hres = VariantCopy(retv, &out);
102 return hres;
105 static HRESULT VBArray_lbound(script_ctx_t *ctx, vdisp_t *vthis, WORD flags, unsigned argc, VARIANT *argv,
106 VARIANT *retv, jsexcept_t *ei)
108 VBArrayInstance *vbarray;
109 int dim;
110 HRESULT hres;
112 TRACE("\n");
114 vbarray = vbarray_this(vthis);
115 if(!vbarray)
116 return throw_type_error(ctx, ei, JS_E_VBARRAY_EXPECTED, NULL);
118 if(argc) {
119 hres = to_int32(ctx, argv, ei, &dim);
120 if(FAILED(hres))
121 return hres;
122 } else
123 dim = 1;
125 hres = SafeArrayGetLBound(vbarray->safearray, dim, &dim);
126 if(hres == DISP_E_BADINDEX)
127 return throw_range_error(ctx, ei, JS_E_SUBSCRIPT_OUT_OF_RANGE, NULL);
128 else if(FAILED(hres))
129 return hres;
131 if(retv)
132 num_set_int(retv, dim);
133 return S_OK;
136 static HRESULT VBArray_toArray(script_ctx_t *ctx, vdisp_t *vthis, WORD flags, unsigned argc, VARIANT *argv,
137 VARIANT *retv, jsexcept_t *ei)
139 VBArrayInstance *vbarray;
140 jsdisp_t *array;
141 VARIANT *v;
142 int i, size = 1, ubound, lbound;
143 HRESULT hres;
145 TRACE("\n");
147 vbarray = vbarray_this(vthis);
148 if(!vbarray)
149 return throw_type_error(ctx, ei, JS_E_VBARRAY_EXPECTED, NULL);
151 for(i=1; i<=SafeArrayGetDim(vbarray->safearray); i++) {
152 SafeArrayGetLBound(vbarray->safearray, i, &lbound);
153 SafeArrayGetUBound(vbarray->safearray, i, &ubound);
154 size *= ubound-lbound+1;
157 hres = SafeArrayAccessData(vbarray->safearray, (void**)&v);
158 if(FAILED(hres))
159 return hres;
161 hres = create_array(ctx, 0, &array);
162 if(FAILED(hres)) {
163 SafeArrayUnaccessData(vbarray->safearray);
164 return hres;
167 for(i=0; i<size; i++) {
168 hres = jsdisp_propput_idx(array, i, v, ei);
169 if(FAILED(hres)) {
170 SafeArrayUnaccessData(vbarray->safearray);
171 jsdisp_release(array);
172 return hres;
174 v++;
177 SafeArrayUnaccessData(vbarray->safearray);
179 if(retv)
180 var_set_jsdisp(retv, array);
181 return S_OK;
184 static HRESULT VBArray_ubound(script_ctx_t *ctx, vdisp_t *vthis, WORD flags, unsigned argc, VARIANT *argv,
185 VARIANT *retv, jsexcept_t *ei)
187 VBArrayInstance *vbarray;
188 int dim;
189 HRESULT hres;
191 TRACE("\n");
193 vbarray = vbarray_this(vthis);
194 if(!vbarray)
195 return throw_type_error(ctx, ei, JS_E_VBARRAY_EXPECTED, NULL);
197 if(argc) {
198 hres = to_int32(ctx, argv, ei, &dim);
199 if(FAILED(hres))
200 return hres;
201 } else
202 dim = 1;
204 hres = SafeArrayGetUBound(vbarray->safearray, dim, &dim);
205 if(hres == DISP_E_BADINDEX)
206 return throw_range_error(ctx, ei, JS_E_SUBSCRIPT_OUT_OF_RANGE, NULL);
207 else if(FAILED(hres))
208 return hres;
210 if(retv)
211 num_set_int(retv, dim);
212 return S_OK;
215 static HRESULT VBArray_value(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, VARIANT *argv,
216 VARIANT *retv, jsexcept_t *ei)
218 FIXME("\n");
220 switch(flags) {
221 default:
222 FIXME("unimplemented flags %x\n", flags);
223 return E_NOTIMPL;
226 return S_OK;
229 static void VBArray_destructor(jsdisp_t *dispex)
231 VBArrayInstance *vbarray = (VBArrayInstance*)dispex;
233 SafeArrayDestroy(vbarray->safearray);
234 heap_free(vbarray);
237 static const builtin_prop_t VBArray_props[] = {
238 {dimensionsW, VBArray_dimensions, PROPF_METHOD},
239 {getItemW, VBArray_getItem, PROPF_METHOD|1},
240 {lboundW, VBArray_lbound, PROPF_METHOD},
241 {toArrayW, VBArray_toArray, PROPF_METHOD},
242 {uboundW, VBArray_ubound, PROPF_METHOD}
245 static const builtin_info_t VBArray_info = {
246 JSCLASS_VBARRAY,
247 {NULL, VBArray_value, 0},
248 sizeof(VBArray_props)/sizeof(*VBArray_props),
249 VBArray_props,
250 VBArray_destructor,
251 NULL
254 static HRESULT alloc_vbarray(script_ctx_t *ctx, jsdisp_t *object_prototype, VBArrayInstance **ret)
256 VBArrayInstance *vbarray;
257 HRESULT hres;
259 vbarray = heap_alloc_zero(sizeof(VBArrayInstance));
260 if(!vbarray)
261 return E_OUTOFMEMORY;
263 if(object_prototype)
264 hres = init_dispex(&vbarray->dispex, ctx, &VBArray_info, object_prototype);
265 else
266 hres = init_dispex_from_constr(&vbarray->dispex, ctx, &VBArray_info, ctx->vbarray_constr);
268 if(FAILED(hres)) {
269 heap_free(vbarray);
270 return hres;
273 *ret = vbarray;
274 return S_OK;
277 static HRESULT VBArrayConstr_value(script_ctx_t *ctx, vdisp_t *vthis, WORD flags, unsigned argc, VARIANT *argv,
278 VARIANT *retv, jsexcept_t *ei)
280 VBArrayInstance *vbarray;
281 HRESULT hres;
283 TRACE("\n");
285 switch(flags) {
286 case DISPATCH_METHOD:
287 if(argc<1 || V_VT(argv) != (VT_ARRAY|VT_VARIANT))
288 return throw_type_error(ctx, ei, JS_E_VBARRAY_EXPECTED, NULL);
290 hres = VariantCopy(retv, argv);
291 return hres;
293 case DISPATCH_CONSTRUCT:
294 if(argc<1 || V_VT(argv) != (VT_ARRAY|VT_VARIANT))
295 return throw_type_error(ctx, ei, JS_E_VBARRAY_EXPECTED, NULL);
297 hres = alloc_vbarray(ctx, NULL, &vbarray);
298 if(FAILED(hres))
299 return hres;
301 hres = SafeArrayCopy(V_ARRAY(argv), &vbarray->safearray);
302 if(FAILED(hres)) {
303 jsdisp_release(&vbarray->dispex);
304 return hres;
307 var_set_jsdisp(retv, &vbarray->dispex);
308 break;
310 default:
311 FIXME("unimplemented flags: %x\n", flags);
312 return E_NOTIMPL;
315 return S_OK;
318 HRESULT create_vbarray_constr(script_ctx_t *ctx, jsdisp_t *object_prototype, jsdisp_t **ret)
320 VBArrayInstance *vbarray;
321 HRESULT hres;
323 static const WCHAR VBArrayW[] = {'V','B','A','r','r','a','y',0};
325 hres = alloc_vbarray(ctx, object_prototype, &vbarray);
326 if(FAILED(hres))
327 return hres;
329 hres = create_builtin_constructor(ctx, VBArrayConstr_value, VBArrayW, NULL, PROPF_CONSTR|1, &vbarray->dispex, ret);
331 jsdisp_release(&vbarray->dispex);
332 return hres;
335 HRESULT create_vbarray(script_ctx_t *ctx, SAFEARRAY *sa, jsdisp_t **ret)
337 VBArrayInstance *vbarray;
338 HRESULT hres;
340 hres = alloc_vbarray(ctx, NULL, &vbarray);
341 if(FAILED(hres))
342 return hres;
344 hres = SafeArrayCopy(sa, &vbarray->safearray);
345 if(FAILED(hres)) {
346 jsdisp_release(&vbarray->dispex);
347 return hres;
350 *ret = &vbarray->dispex;
351 return S_OK;