jscript: Added VBArray.dimensions() implementation.
[wine] / dlls / jscript / vbarray.c
1 /*
2  * Copyright 2010 Piotr Caban for CodeWeavers
3  *
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.
8  *
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.
13  *
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
17  */
18
19 #include "jscript.h"
20
21 #include "wine/debug.h"
22
23 WINE_DEFAULT_DEBUG_CHANNEL(jscript);
24
25 typedef struct {
26     jsdisp_t dispex;
27
28     SAFEARRAY *safearray;
29 } VBArrayInstance;
30
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};
36
37 static inline VBArrayInstance *vbarray_from_vdisp(vdisp_t *vdisp)
38 {
39     return (VBArrayInstance*)vdisp->u.jsdisp;
40 }
41
42 static inline VBArrayInstance *vbarray_this(vdisp_t *jsthis)
43 {
44     return is_vclass(jsthis, JSCLASS_VBARRAY) ? vbarray_from_vdisp(jsthis) : NULL;
45 }
46
47 static HRESULT VBArray_dimensions(script_ctx_t *ctx, vdisp_t *vthis, WORD flags, DISPPARAMS *dp,
48         VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
49 {
50     VBArrayInstance *vbarray;
51
52     TRACE("\n");
53
54     vbarray = vbarray_this(vthis);
55     if(!vbarray)
56         return throw_type_error(ctx, ei, IDS_NOT_VBARRAY, NULL);
57
58     if(retv)
59         num_set_val(retv, SafeArrayGetDim(vbarray->safearray));
60     return S_OK;
61 }
62
63 static HRESULT VBArray_getItem(script_ctx_t *ctx, vdisp_t *vthis, WORD flags, DISPPARAMS *dp,
64         VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
65 {
66     FIXME("\n");
67     return E_NOTIMPL;
68 }
69
70 static HRESULT VBArray_lbound(script_ctx_t *ctx, vdisp_t *vthis, WORD flags, DISPPARAMS *dp,
71         VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
72 {
73     VBArrayInstance *vbarray;
74     int dim;
75     HRESULT hres;
76
77     TRACE("\n");
78
79     vbarray = vbarray_this(vthis);
80     if(!vbarray)
81         return throw_type_error(ctx, ei, IDS_NOT_VBARRAY, NULL);
82
83     if(arg_cnt(dp)) {
84         hres = to_int32(ctx, get_arg(dp, 0), ei, &dim);
85         if(FAILED(hres))
86             return hres;
87     } else
88         dim = 1;
89
90     hres = SafeArrayGetLBound(vbarray->safearray, dim, &dim);
91     if(hres == DISP_E_BADINDEX)
92         return throw_range_error(ctx, ei, IDS_SUBSCRIPT_OUT_OF_RANGE, NULL);
93     else if(FAILED(hres))
94         return hres;
95
96     if(retv)
97         num_set_val(retv, dim);
98     return S_OK;
99 }
100
101 static HRESULT VBArray_toArray(script_ctx_t *ctx, vdisp_t *vthis, WORD flags, DISPPARAMS *dp,
102         VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
103 {
104     FIXME("\n");
105     return E_NOTIMPL;
106 }
107
108 static HRESULT VBArray_ubound(script_ctx_t *ctx, vdisp_t *vthis, WORD flags, DISPPARAMS *dp,
109         VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
110 {
111     VBArrayInstance *vbarray;
112     int dim;
113     HRESULT hres;
114
115     TRACE("\n");
116
117     vbarray = vbarray_this(vthis);
118     if(!vbarray)
119         return throw_type_error(ctx, ei, IDS_NOT_VBARRAY, NULL);
120
121     if(arg_cnt(dp)) {
122         hres = to_int32(ctx, get_arg(dp, 0), ei, &dim);
123         if(FAILED(hres))
124             return hres;
125     } else
126         dim = 1;
127
128     hres = SafeArrayGetUBound(vbarray->safearray, dim, &dim);
129     if(hres == DISP_E_BADINDEX)
130         return throw_range_error(ctx, ei, IDS_SUBSCRIPT_OUT_OF_RANGE, NULL);
131     else if(FAILED(hres))
132         return hres;
133
134     if(retv)
135         num_set_val(retv, dim);
136     return S_OK;
137 }
138
139 static HRESULT VBArray_value(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp,
140         VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
141 {
142     FIXME("\n");
143
144     switch(flags) {
145         default:
146             FIXME("unimplemented flags %x\n", flags);
147             return E_NOTIMPL;
148     }
149
150     return S_OK;
151 }
152
153 static void VBArray_destructor(jsdisp_t *dispex)
154 {
155     VBArrayInstance *vbarray = (VBArrayInstance*)dispex;
156
157     SafeArrayDestroy(vbarray->safearray);
158     heap_free(vbarray);
159 }
160
161 static const builtin_prop_t VBArray_props[] = {
162     {dimensionsW,           VBArray_dimensions,         PROPF_METHOD},
163     {getItemW,              VBArray_getItem,            PROPF_METHOD|1},
164     {lboundW,               VBArray_lbound,             PROPF_METHOD},
165     {toArrayW,              VBArray_toArray,            PROPF_METHOD},
166     {uboundW,               VBArray_ubound,             PROPF_METHOD}
167 };
168
169 static const builtin_info_t VBArray_info = {
170     JSCLASS_VBARRAY,
171     {NULL, VBArray_value, 0},
172     sizeof(VBArray_props)/sizeof(*VBArray_props),
173     VBArray_props,
174     VBArray_destructor,
175     NULL
176 };
177
178 static HRESULT alloc_vbarray(script_ctx_t *ctx, jsdisp_t *object_prototype, VBArrayInstance **ret)
179 {
180     VBArrayInstance *vbarray;
181     HRESULT hres;
182
183     vbarray = heap_alloc_zero(sizeof(VBArrayInstance));
184     if(!vbarray)
185         return E_OUTOFMEMORY;
186
187     if(object_prototype)
188         hres = init_dispex(&vbarray->dispex, ctx, &VBArray_info, object_prototype);
189     else
190         hres = init_dispex_from_constr(&vbarray->dispex, ctx, &VBArray_info, ctx->vbarray_constr);
191
192     if(FAILED(hres)) {
193         heap_free(vbarray);
194         return hres;
195     }
196
197     *ret = vbarray;
198     return S_OK;
199 }
200
201 static HRESULT VBArrayConstr_value(script_ctx_t *ctx, vdisp_t *vthis, WORD flags, DISPPARAMS *dp,
202         VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
203 {
204     VARIANT *arg;
205     VBArrayInstance *vbarray;
206     HRESULT hres;
207
208     TRACE("\n");
209
210     switch(flags) {
211     case DISPATCH_METHOD:
212         if(arg_cnt(dp)<1 || V_VT((arg = get_arg(dp, 0)))!=(VT_ARRAY|VT_VARIANT))
213             return throw_type_error(ctx, ei, IDS_NOT_VBARRAY, NULL);
214
215         VariantCopy(retv, arg);
216         break;
217
218     case DISPATCH_CONSTRUCT:
219         if(arg_cnt(dp)<1 || V_VT((arg = get_arg(dp, 0)))!=(VT_ARRAY|VT_VARIANT))
220             return throw_type_error(ctx, ei, IDS_NOT_VBARRAY, NULL);
221
222         hres = alloc_vbarray(ctx, NULL, &vbarray);
223         if(FAILED(hres))
224             return hres;
225         SafeArrayCopy(V_ARRAY(arg), &vbarray->safearray);
226
227         var_set_jsdisp(retv, &vbarray->dispex);
228         break;
229
230     default:
231         FIXME("unimplemented flags: %x\n", flags);
232         return E_NOTIMPL;
233     }
234
235     return S_OK;
236 }
237
238 HRESULT create_vbarray_constr(script_ctx_t *ctx, jsdisp_t *object_prototype, jsdisp_t **ret)
239 {
240     VBArrayInstance *vbarray;
241     HRESULT hres;
242
243     static const WCHAR VBArrayW[] = {'V','B','A','r','r','a','y',0};
244
245     hres = alloc_vbarray(ctx, object_prototype, &vbarray);
246     if(FAILED(hres))
247         return hres;
248
249     hres = create_builtin_function(ctx, VBArrayConstr_value, VBArrayW, NULL, PROPF_CONSTR|1, &vbarray->dispex, ret);
250
251     jsdisp_release(&vbarray->dispex);
252     return hres;
253 }