php-internal-docs 8.4.8
Unofficial docs for php/php-src
Loading...
Searching...
No Matches
com_iterator.c
Go to the documentation of this file.
1/*
2 +----------------------------------------------------------------------+
3 | Copyright (c) The PHP Group |
4 +----------------------------------------------------------------------+
5 | This source file is subject to version 3.01 of the PHP license, |
6 | that is bundled with this package in the file LICENSE, and is |
7 | available through the world-wide-web at the following url: |
8 | https://www.php.net/license/3_01.txt |
9 | If you did not receive a copy of the PHP license and are unable to |
10 | obtain it through the world-wide-web, please send a note to |
11 | license@php.net so we can mail you a copy immediately. |
12 +----------------------------------------------------------------------+
13 | Author: Wez Furlong <wez@thebrainroom.com> |
14 +----------------------------------------------------------------------+
15 */
16
17#ifdef HAVE_CONFIG_H
18#include <config.h>
19#endif
20
21#include "php.h"
22#include "php_ini.h"
23#include "ext/standard/info.h"
24#include "php_com_dotnet.h"
27
30 IEnumVARIANT *ev;
32 VARIANT v; /* cached element */
34 VARIANT safe_array;
35 VARTYPE sa_type;
36 LONG sa_max;
38};
39
40static void com_iter_dtor(zend_object_iterator *iter)
41{
42 struct php_com_iterator *I = (struct php_com_iterator*)Z_PTR(iter->data);
43
44 if (I->ev) {
45 IEnumVARIANT_Release(I->ev);
46 }
47 VariantClear(&I->v);
48 VariantClear(&I->safe_array);
49 zval_ptr_dtor(&I->zdata);
50}
51
52static zend_result com_iter_valid(zend_object_iterator *iter)
53{
54 struct php_com_iterator *I = (struct php_com_iterator*)Z_PTR(iter->data);
55
56 if (Z_TYPE(I->zdata) != IS_UNDEF) {
57 return SUCCESS;
58 }
59
60 return FAILURE;
61}
62
63static zval* com_iter_get_data(zend_object_iterator *iter)
64{
65 struct php_com_iterator *I = (struct php_com_iterator*)Z_PTR(iter->data);
66
67 return &I->zdata;
68}
69
70static void com_iter_get_key(zend_object_iterator *iter, zval *key)
71{
72 struct php_com_iterator *I = (struct php_com_iterator*)Z_PTR(iter->data);
73
74 if (I->key == (zend_ulong)-1) {
76 } else {
77 ZVAL_LONG(key, I->key);
78 }
79}
80
81static void com_iter_move_forwards(zend_object_iterator *iter)
82{
83 struct php_com_iterator *I = (struct php_com_iterator*)Z_PTR(iter->data);
84 unsigned long n_fetched;
85 zval ptr;
86
87 /* release current cached element */
88 VariantClear(&I->v);
89
90 if (Z_TYPE(I->zdata) != IS_UNDEF) {
91 zval_ptr_dtor(&I->zdata);
92 ZVAL_UNDEF(&I->zdata);
93 }
94
95 if (I->ev) {
96 /* Get the next element */
97 if (SUCCEEDED(IEnumVARIANT_Next(I->ev, 1, &I->v, &n_fetched)) && n_fetched > 0) {
98 I->key++;
99 } else {
100 /* indicate that there are no more items */
101 I->key = (zend_ulong)-1;
102 return;
103 }
104 } else {
105 /* safe array */
106 if (I->key >= (ULONG) I->sa_max) {
107 I->key = (zend_ulong)-1;
108 return;
109 }
110 I->key++;
111 if (!php_com_safearray_get_elem(&I->safe_array, &I->v, (LONG)I->key)) {
112 I->key = (zend_ulong)-1;
113 return;
114 }
115 }
116
117 ZVAL_NULL(&ptr);
118 php_com_zval_from_variant(&ptr, &I->v, I->code_page);
119 /* php_com_wrap_variant(ptr, &I->v, I->code_page); */
120 ZVAL_COPY_VALUE(&I->zdata, &ptr);
121}
122
123
124static const zend_object_iterator_funcs com_iter_funcs = {
125 com_iter_dtor,
126 com_iter_valid,
127 com_iter_get_data,
128 com_iter_get_key,
129 com_iter_move_forwards,
130 NULL,
131 NULL, /* get_gc */
132};
133
135{
137 struct php_com_iterator *I;
138 IEnumVARIANT *iev = NULL;
139 DISPPARAMS dp;
140 VARIANT v;
141 unsigned long n_fetched;
142 zval ptr;
143
144 if (by_ref) {
145 zend_throw_error(NULL, "An iterator cannot be used with foreach by reference");
146 return NULL;
147 }
148
149 obj = CDNO_FETCH(object);
150
151 if (V_VT(&obj->v) != VT_DISPATCH && !V_ISARRAY(&obj->v)) {
152 /* TODO Promote to TypeError? */
153 php_error_docref(NULL, E_WARNING, "Variant is not an object or array VT=%d", V_VT(&obj->v));
154 return NULL;
155 }
156
157 memset(&dp, 0, sizeof(dp));
158 VariantInit(&v);
159
160 I = (struct php_com_iterator*)ecalloc(1, sizeof(*I));
161 zend_iterator_init(&I->iter);
162 I->iter.funcs = &com_iter_funcs;
163 Z_PTR(I->iter.data) = I;
164 I->code_page = obj->code_page;
165 ZVAL_UNDEF(&I->zdata);
166 VariantInit(&I->safe_array);
167 VariantInit(&I->v);
168
169 if (V_ISARRAY(&obj->v)) {
170 LONG bound;
171 UINT dims;
172
173 dims = SafeArrayGetDim(V_ARRAY(&obj->v));
174
175 if (dims != 1) {
176 /* TODO Promote to ValueError? */
178 "Can only handle single dimension variant arrays (this array has %d)", dims);
179 goto fail;
180 }
181
182 /* same semantics as foreach on a PHP array;
183 * make a copy and enumerate that copy */
184 VariantCopy(&I->safe_array, &obj->v);
185
186 /* determine the key value for the array */
187 SafeArrayGetLBound(V_ARRAY(&I->safe_array), 1, &bound);
188 SafeArrayGetUBound(V_ARRAY(&I->safe_array), 1, &I->sa_max);
189
190 /* pre-fetch the element */
191 if (I->sa_max >= bound && php_com_safearray_get_elem(&I->safe_array, &I->v, bound)) {
192 I->key = bound;
193 ZVAL_NULL(&ptr);
194 php_com_zval_from_variant(&ptr, &I->v, I->code_page);
195 ZVAL_COPY_VALUE(&I->zdata, &ptr);
196 } else {
197 I->key = (zend_ulong)-1;
198 }
199
200 } else {
201 /* can we enumerate it? */
202 if (FAILED(IDispatch_Invoke(V_DISPATCH(&obj->v), DISPID_NEWENUM,
203 &IID_NULL, LOCALE_NEUTRAL, DISPATCH_METHOD|DISPATCH_PROPERTYGET,
204 &dp, &v, NULL, NULL))) {
205 goto fail;
206 }
207
208 /* get something useful out of it */
209 if (V_VT(&v) == VT_UNKNOWN) {
210 IUnknown_QueryInterface(V_UNKNOWN(&v), &IID_IEnumVARIANT, (void**)&iev);
211 } else if (V_VT(&v) == VT_DISPATCH) {
212 IDispatch_QueryInterface(V_DISPATCH(&v), &IID_IEnumVARIANT, (void**)&iev);
213 }
214
215 VariantClear(&v);
216
217 if (iev == NULL) {
218 goto fail;
219 }
220
221 I->ev = iev;
222
223 /* Get the first element now */
224 if (SUCCEEDED(IEnumVARIANT_Next(I->ev, 1, &I->v, &n_fetched)) && n_fetched > 0) {
225 /* indicate that we have element 0 */
226 I->key = 0;
227 ZVAL_NULL(&ptr);
228 php_com_zval_from_variant(&ptr, &I->v, I->code_page);
229 ZVAL_COPY_VALUE(&I->zdata, &ptr);
230 } else {
231 /* indicate that there are no more items */
232 I->key = (zend_ulong)-1;
233 }
234 }
235
236 return &I->iter;
237
238fail:
239 if (I) {
240 VariantClear(&I->safe_array);
241 VariantClear(&I->v);
242 efree(I);
243 }
244 return NULL;
245}
uint32_t v
Definition cdf.c:1237
const VT_DISPATCH
const LOCALE_NEUTRAL
const VT_UNKNOWN
zend_object_iterator * php_com_iter_get(zend_class_entry *ce, zval *object, int by_ref)
PHP_COM_DOTNET_API bool php_com_safearray_get_elem(VARIANT *array, VARIANT *dest, LONG dim1)
Definition com_misc.c:92
PHP_COM_DOTNET_API zend_result php_com_zval_from_variant(zval *z, VARIANT *v, int codepage)
HashTable * dims
Definition ffi.c:4261
void * ptr
Definition ffi.c:3814
memset(ptr, 0, type->size)
#define I
Definition encoding.c:237
#define NULL
Definition gdcache.h:45
#define SUCCESS
Definition hash_sha3.c:261
PHPAPI ZEND_COLD void php_error_docref(const char *docref, int type, const char *format,...)
Definition main.c:1173
#define CDNO_FETCH(zv)
struct _php_com_dotnet_object php_com_dotnet_object
unsigned char key[REFLECTION_KEY_LEN]
bool fail
Definition session.c:1065
zend_object_iterator iter
IEnumVARIANT * ev
ZEND_API ZEND_COLD void zend_throw_error(zend_class_entry *exception_ce, const char *format,...)
Definition zend.c:1772
#define ecalloc(nmemb, size)
Definition zend_alloc.h:158
#define efree(ptr)
Definition zend_alloc.h:155
struct _zval_struct zval
#define E_WARNING
Definition zend_errors.h:24
ZEND_API void zend_iterator_init(zend_object_iterator *iter)
struct _zend_object_iterator zend_object_iterator
struct _zend_object_iterator_funcs zend_object_iterator_funcs
uint32_t zend_ulong
Definition zend_long.h:43
struct _zend_class_entry zend_class_entry
#define ZVAL_UNDEF(z)
#define IS_UNDEF
Definition zend_types.h:600
#define ZVAL_NULL(z)
#define ZVAL_LONG(z, l)
#define Z_PTR(zval)
@ FAILURE
Definition zend_types.h:61
ZEND_RESULT_CODE zend_result
Definition zend_types.h:64
#define Z_TYPE(zval)
Definition zend_types.h:659
#define ZVAL_COPY_VALUE(z, v)
ZEND_API void zval_ptr_dtor(zval *zval_ptr)