amstream: Store parent as struct ddraw_stream in ddraw stream sample.
[wine/zf.git] / dlls / jscript / enumerator.c
blobffe01c565ad2cd96b4e57196c2d386ece2c330d4
1 /*
2 * Copyright 2019 Andreas Maier
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 <assert.h>
21 #include "jscript.h"
23 #include "wine/debug.h"
25 WINE_DEFAULT_DEBUG_CHANNEL(jscript);
27 typedef struct {
28 jsdisp_t dispex;
29 /* IEnumVARIANT returned by _NewEnum */
30 IEnumVARIANT *enumvar;
31 /* current item */
32 jsval_t item;
33 BOOL atend;
34 } EnumeratorInstance;
36 static const WCHAR atEndW[] = {'a','t','E','n','d',0};
37 static const WCHAR itemW[] = {'i','t','e','m',0};
38 static const WCHAR moveFirstW[] = {'m','o','v','e','F','i','r','s','t',0};
39 static const WCHAR moveNextW[] = {'m','o','v','e','N','e','x','t',0};
41 static inline EnumeratorInstance *enumerator_from_jsdisp(jsdisp_t *jsdisp)
43 return CONTAINING_RECORD(jsdisp, EnumeratorInstance, dispex);
46 static inline EnumeratorInstance *enumerator_from_vdisp(vdisp_t *vdisp)
48 return enumerator_from_jsdisp(vdisp->u.jsdisp);
51 static inline EnumeratorInstance *enumerator_this(vdisp_t *jsthis)
53 return is_vclass(jsthis, JSCLASS_ENUMERATOR) ? enumerator_from_vdisp(jsthis) : NULL;
56 static inline HRESULT enumvar_get_next_item(EnumeratorInstance *This)
58 HRESULT hres;
59 VARIANT nextitem;
61 if (This->atend)
62 return S_OK;
64 /* don't leak previous value */
65 jsval_release(This->item);
67 /* not at end ... get next item */
68 VariantInit(&nextitem);
69 hres = IEnumVARIANT_Next(This->enumvar, 1, &nextitem, NULL);
70 if (hres == S_OK)
72 hres = variant_to_jsval(&nextitem, &This->item);
73 VariantClear(&nextitem);
74 if (FAILED(hres))
76 WARN("failed to convert jsval to variant!\n");
77 This->item = jsval_undefined();
78 return hres;
81 else
83 This->item = jsval_undefined();
84 This->atend = TRUE;
87 return S_OK;
90 static void Enumerator_destructor(jsdisp_t *dispex)
92 EnumeratorInstance *This = enumerator_from_jsdisp(dispex);
94 TRACE("\n");
96 jsval_release(This->item);
97 heap_free(dispex);
100 static HRESULT Enumerator_atEnd(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv,
101 jsval_t *r)
103 EnumeratorInstance *This;
105 if (!(This = enumerator_this(jsthis)))
106 return JS_E_ENUMERATOR_EXPECTED;
108 TRACE("%d\n", This->atend);
110 if (r)
111 *r = jsval_bool(This->atend);
112 return S_OK;
115 static HRESULT Enumerator_item(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv,
116 jsval_t *r)
118 EnumeratorInstance *This;
120 TRACE("\n");
122 if (!(This = enumerator_this(jsthis)))
123 return JS_E_ENUMERATOR_EXPECTED;
125 return r ? jsval_copy(This->item, r) : S_OK;
128 static HRESULT Enumerator_moveFirst(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv,
129 jsval_t *r)
131 EnumeratorInstance *This;
132 HRESULT hres = S_OK;
134 TRACE("\n");
136 if (!(This = enumerator_this(jsthis)))
137 return JS_E_ENUMERATOR_EXPECTED;
139 if (This->enumvar)
141 hres = IEnumVARIANT_Reset(This->enumvar);
142 if (FAILED(hres))
143 return hres;
145 This->atend = FALSE;
146 hres = enumvar_get_next_item(This);
147 if(FAILED(hres))
148 return hres;
151 if (r)
152 *r = jsval_undefined();
153 return S_OK;
156 static HRESULT Enumerator_moveNext(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv,
157 jsval_t *r)
159 EnumeratorInstance *This;
160 HRESULT hres = S_OK;
162 TRACE("\n");
164 if (!(This = enumerator_this(jsthis)))
165 return JS_E_ENUMERATOR_EXPECTED;
167 if (This->enumvar)
169 hres = enumvar_get_next_item(This);
170 if (FAILED(hres))
171 return hres;
174 if (r)
175 *r = jsval_undefined();
176 return S_OK;
179 static const builtin_prop_t Enumerator_props[] = {
180 {atEndW, Enumerator_atEnd, PROPF_METHOD},
181 {itemW, Enumerator_item, PROPF_METHOD},
182 {moveFirstW, Enumerator_moveFirst, PROPF_METHOD},
183 {moveNextW, Enumerator_moveNext, PROPF_METHOD},
186 static const builtin_info_t Enumerator_info = {
187 JSCLASS_ENUMERATOR,
188 {NULL, NULL, 0},
189 ARRAY_SIZE(Enumerator_props),
190 Enumerator_props,
191 NULL,
192 NULL
195 static const builtin_info_t EnumeratorInst_info = {
196 JSCLASS_ENUMERATOR,
197 {NULL, NULL, 0, NULL},
199 NULL,
200 Enumerator_destructor,
201 NULL
204 static HRESULT alloc_enumerator(script_ctx_t *ctx, jsdisp_t *object_prototype, EnumeratorInstance **ret)
206 EnumeratorInstance *enumerator;
207 HRESULT hres;
209 enumerator = heap_alloc_zero(sizeof(EnumeratorInstance));
210 if(!enumerator)
211 return E_OUTOFMEMORY;
213 if(object_prototype)
214 hres = init_dispex(&enumerator->dispex, ctx, &Enumerator_info, object_prototype);
215 else
216 hres = init_dispex_from_constr(&enumerator->dispex, ctx, &EnumeratorInst_info,
217 ctx->enumerator_constr);
219 if(FAILED(hres))
221 heap_free(enumerator);
222 return hres;
225 *ret = enumerator;
226 return S_OK;
229 static HRESULT create_enumerator(script_ctx_t *ctx, jsval_t *argv, jsdisp_t **ret)
231 EnumeratorInstance *enumerator;
232 HRESULT hres;
233 IDispatch *obj;
234 DISPPARAMS dispparams = {NULL, NULL, 0, 0};
235 IEnumVARIANT *enumvar = NULL;
237 if (argv)
239 VARIANT varresult;
241 if (!is_object_instance(*argv))
243 FIXME("I don't know how to handle this type!\n");
244 return E_NOTIMPL;
247 obj = get_object(*argv);
249 /* Try to get a IEnumVARIANT by _NewEnum */
250 VariantInit(&varresult);
251 hres = IDispatch_Invoke(obj, DISPID_NEWENUM, &IID_NULL, LOCALE_NEUTRAL,
252 DISPATCH_METHOD, &dispparams, &varresult, NULL, NULL);
253 if (FAILED(hres))
255 WARN("Enumerator: no DISPID_NEWENUM.\n");
256 return E_INVALIDARG;
259 if ((V_VT(&varresult) == VT_DISPATCH) || (V_VT(&varresult) == VT_UNKNOWN))
261 hres = IUnknown_QueryInterface(V_UNKNOWN(&varresult),
262 &IID_IEnumVARIANT, (void**)&enumvar);
264 else
266 FIXME("Enumerator: NewEnum unexpected type of varresult (%d).\n", V_VT(&varresult));
267 hres = E_INVALIDARG;
269 VariantClear(&varresult);
270 if (FAILED(hres))
271 return hres;
274 hres = alloc_enumerator(ctx, NULL, &enumerator);
275 if (FAILED(hres))
277 if (enumvar)
278 IEnumVARIANT_Release(enumvar);
279 return hres;
282 enumerator->enumvar = enumvar;
283 enumerator->atend = !enumvar;
284 hres = enumvar_get_next_item(enumerator);
285 if (FAILED(hres))
287 jsdisp_release(&enumerator->dispex);
288 return hres;
291 *ret = &enumerator->dispex;
292 return S_OK;
295 static HRESULT EnumeratorConstr_value(script_ctx_t *ctx, vdisp_t *vthis, WORD flags, unsigned argc, jsval_t *argv,
296 jsval_t *r)
298 jsdisp_t *obj;
299 HRESULT hres;
301 TRACE("\n");
303 switch(flags) {
304 case DISPATCH_CONSTRUCT: {
305 if (argc > 1)
306 return JS_E_INVALIDARG;
308 hres = create_enumerator(ctx, (argc == 1) ? &argv[0] : 0, &obj);
309 if(FAILED(hres))
310 return hres;
312 *r = jsval_obj(obj);
313 break;
315 default:
316 FIXME("unimplemented flags: %x\n", flags);
317 return E_NOTIMPL;
320 return S_OK;
323 static const builtin_info_t EnumeratorConstr_info = {
324 JSCLASS_FUNCTION,
325 DEFAULT_FUNCTION_VALUE,
327 NULL,
328 NULL,
329 NULL
332 HRESULT create_enumerator_constr(script_ctx_t *ctx, jsdisp_t *object_prototype, jsdisp_t **ret)
334 EnumeratorInstance *enumerator;
335 HRESULT hres;
336 static const WCHAR EnumeratorW[] = {'E','n','u','m','e','r','a','t','o','r',0};
338 hres = alloc_enumerator(ctx, object_prototype, &enumerator);
339 if(FAILED(hres))
340 return hres;
342 hres = create_builtin_constructor(ctx, EnumeratorConstr_value,
343 EnumeratorW, &EnumeratorConstr_info,
344 PROPF_CONSTR|7, &enumerator->dispex, ret);
345 jsdisp_release(&enumerator->dispex);
347 return hres;