jscript: Added VBArray.getItem() implementation.
[wine.git] / dlls / jscript / vbarray.c
blob887e19b05c0e187f20f2da9127125649b8382eea
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, DISPPARAMS *dp,
48 VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
50 VBArrayInstance *vbarray;
52 TRACE("\n");
54 vbarray = vbarray_this(vthis);
55 if(!vbarray)
56 return throw_type_error(ctx, ei, IDS_NOT_VBARRAY, NULL);
58 if(retv)
59 num_set_val(retv, SafeArrayGetDim(vbarray->safearray));
60 return S_OK;
63 static HRESULT VBArray_getItem(script_ctx_t *ctx, vdisp_t *vthis, WORD flags, DISPPARAMS *dp,
64 VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
66 VBArrayInstance *vbarray;
67 int i, *indexes, size;
68 VARIANT out;
69 HRESULT hres;
71 TRACE("\n");
73 vbarray = vbarray_this(vthis);
74 if(!vbarray)
75 return throw_type_error(ctx, ei, IDS_NOT_VBARRAY, NULL);
77 size = arg_cnt(dp);
78 if(size < SafeArrayGetDim(vbarray->safearray))
79 return throw_range_error(ctx, ei, IDS_SUBSCRIPT_OUT_OF_RANGE, NULL);
81 indexes = heap_alloc(sizeof(int)*size);
82 for(i=0; i<size; i++) {
83 hres = to_int32(ctx, get_arg(dp, i), ei, indexes+i);
84 if(FAILED(hres)) {
85 heap_free(indexes);
86 return hres;
90 hres = SafeArrayGetElement(vbarray->safearray, indexes, (void*)&out);
91 heap_free(indexes);
92 if(hres == DISP_E_BADINDEX)
93 return throw_range_error(ctx, ei, IDS_SUBSCRIPT_OUT_OF_RANGE, NULL);
94 else if(FAILED(hres))
95 return hres;
97 if(retv)
98 hres = VariantCopy(retv, &out);
100 return hres;
103 static HRESULT VBArray_lbound(script_ctx_t *ctx, vdisp_t *vthis, WORD flags, DISPPARAMS *dp,
104 VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
106 VBArrayInstance *vbarray;
107 int dim;
108 HRESULT hres;
110 TRACE("\n");
112 vbarray = vbarray_this(vthis);
113 if(!vbarray)
114 return throw_type_error(ctx, ei, IDS_NOT_VBARRAY, NULL);
116 if(arg_cnt(dp)) {
117 hres = to_int32(ctx, get_arg(dp, 0), ei, &dim);
118 if(FAILED(hres))
119 return hres;
120 } else
121 dim = 1;
123 hres = SafeArrayGetLBound(vbarray->safearray, dim, &dim);
124 if(hres == DISP_E_BADINDEX)
125 return throw_range_error(ctx, ei, IDS_SUBSCRIPT_OUT_OF_RANGE, NULL);
126 else if(FAILED(hres))
127 return hres;
129 if(retv)
130 num_set_val(retv, dim);
131 return S_OK;
134 static HRESULT VBArray_toArray(script_ctx_t *ctx, vdisp_t *vthis, WORD flags, DISPPARAMS *dp,
135 VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
137 FIXME("\n");
138 return E_NOTIMPL;
141 static HRESULT VBArray_ubound(script_ctx_t *ctx, vdisp_t *vthis, WORD flags, DISPPARAMS *dp,
142 VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
144 VBArrayInstance *vbarray;
145 int dim;
146 HRESULT hres;
148 TRACE("\n");
150 vbarray = vbarray_this(vthis);
151 if(!vbarray)
152 return throw_type_error(ctx, ei, IDS_NOT_VBARRAY, NULL);
154 if(arg_cnt(dp)) {
155 hres = to_int32(ctx, get_arg(dp, 0), ei, &dim);
156 if(FAILED(hres))
157 return hres;
158 } else
159 dim = 1;
161 hres = SafeArrayGetUBound(vbarray->safearray, dim, &dim);
162 if(hres == DISP_E_BADINDEX)
163 return throw_range_error(ctx, ei, IDS_SUBSCRIPT_OUT_OF_RANGE, NULL);
164 else if(FAILED(hres))
165 return hres;
167 if(retv)
168 num_set_val(retv, dim);
169 return S_OK;
172 static HRESULT VBArray_value(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp,
173 VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
175 FIXME("\n");
177 switch(flags) {
178 default:
179 FIXME("unimplemented flags %x\n", flags);
180 return E_NOTIMPL;
183 return S_OK;
186 static void VBArray_destructor(jsdisp_t *dispex)
188 VBArrayInstance *vbarray = (VBArrayInstance*)dispex;
190 SafeArrayDestroy(vbarray->safearray);
191 heap_free(vbarray);
194 static const builtin_prop_t VBArray_props[] = {
195 {dimensionsW, VBArray_dimensions, PROPF_METHOD},
196 {getItemW, VBArray_getItem, PROPF_METHOD|1},
197 {lboundW, VBArray_lbound, PROPF_METHOD},
198 {toArrayW, VBArray_toArray, PROPF_METHOD},
199 {uboundW, VBArray_ubound, PROPF_METHOD}
202 static const builtin_info_t VBArray_info = {
203 JSCLASS_VBARRAY,
204 {NULL, VBArray_value, 0},
205 sizeof(VBArray_props)/sizeof(*VBArray_props),
206 VBArray_props,
207 VBArray_destructor,
208 NULL
211 static HRESULT alloc_vbarray(script_ctx_t *ctx, jsdisp_t *object_prototype, VBArrayInstance **ret)
213 VBArrayInstance *vbarray;
214 HRESULT hres;
216 vbarray = heap_alloc_zero(sizeof(VBArrayInstance));
217 if(!vbarray)
218 return E_OUTOFMEMORY;
220 if(object_prototype)
221 hres = init_dispex(&vbarray->dispex, ctx, &VBArray_info, object_prototype);
222 else
223 hres = init_dispex_from_constr(&vbarray->dispex, ctx, &VBArray_info, ctx->vbarray_constr);
225 if(FAILED(hres)) {
226 heap_free(vbarray);
227 return hres;
230 *ret = vbarray;
231 return S_OK;
234 static HRESULT VBArrayConstr_value(script_ctx_t *ctx, vdisp_t *vthis, WORD flags, DISPPARAMS *dp,
235 VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
237 VARIANT *arg;
238 VBArrayInstance *vbarray;
239 HRESULT hres;
241 TRACE("\n");
243 switch(flags) {
244 case DISPATCH_METHOD:
245 if(arg_cnt(dp)<1 || V_VT((arg = get_arg(dp, 0)))!=(VT_ARRAY|VT_VARIANT))
246 return throw_type_error(ctx, ei, IDS_NOT_VBARRAY, NULL);
248 VariantCopy(retv, arg);
249 break;
251 case DISPATCH_CONSTRUCT:
252 if(arg_cnt(dp)<1 || V_VT((arg = get_arg(dp, 0)))!=(VT_ARRAY|VT_VARIANT))
253 return throw_type_error(ctx, ei, IDS_NOT_VBARRAY, NULL);
255 hres = alloc_vbarray(ctx, NULL, &vbarray);
256 if(FAILED(hres))
257 return hres;
258 SafeArrayCopy(V_ARRAY(arg), &vbarray->safearray);
260 var_set_jsdisp(retv, &vbarray->dispex);
261 break;
263 default:
264 FIXME("unimplemented flags: %x\n", flags);
265 return E_NOTIMPL;
268 return S_OK;
271 HRESULT create_vbarray_constr(script_ctx_t *ctx, jsdisp_t *object_prototype, jsdisp_t **ret)
273 VBArrayInstance *vbarray;
274 HRESULT hres;
276 static const WCHAR VBArrayW[] = {'V','B','A','r','r','a','y',0};
278 hres = alloc_vbarray(ctx, object_prototype, &vbarray);
279 if(FAILED(hres))
280 return hres;
282 hres = create_builtin_function(ctx, VBArrayConstr_value, VBArrayW, NULL, PROPF_CONSTR|1, &vbarray->dispex, ret);
284 jsdisp_release(&vbarray->dispex);
285 return hres;