Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Newer
Older
100755 567 lines (490 sloc) 17.419 kB
8abb3bd Impement userspace iterator interfaces and tests. See tests for details
Marcus Boerger authored
1 /*
2 +----------------------------------------------------------------------+
3 | Zend Engine |
4 +----------------------------------------------------------------------+
4223aa4 MFH: Bump year.
Sebastian Bergmann authored
5 | Copyright (c) 1998-2007 Zend Technologies Ltd. (http://www.zend.com) |
8abb3bd Impement userspace iterator interfaces and tests. See tests for details
Marcus Boerger authored
6 +----------------------------------------------------------------------+
7 | This source file is subject to version 2.00 of the Zend license, |
8 | that is bundled with this package in the file LICENSE, and is |
9 | available through the world-wide-web at the following url: |
10 | http://www.zend.com/license/2_00.txt. |
11 | If you did not receive a copy of the Zend license and are unable to |
12 | obtain it through the world-wide-web, please send a note to |
13 | license@zend.com so we can mail you a copy immediately. |
14 +----------------------------------------------------------------------+
15 | Authors: Marcus Boerger <helly@php.net> |
16 +----------------------------------------------------------------------+
17 */
18
19 /* $Id$ */
20
21 #include "zend.h"
22 #include "zend_API.h"
23 #include "zend_interfaces.h"
82193ad - Bugfix #26229 (getIterator() segfaults when it returns arrays or sc…
Marcus Boerger authored
24 #include "zend_exceptions.h"
8abb3bd Impement userspace iterator interfaces and tests. See tests for details
Marcus Boerger authored
25
1cc4a69 @smalyshev preserve ZEND_API in definition
smalyshev authored
26 ZEND_API zend_class_entry *zend_ce_traversable;
27 ZEND_API zend_class_entry *zend_ce_aggregate;
28 ZEND_API zend_class_entry *zend_ce_iterator;
29 ZEND_API zend_class_entry *zend_ce_arrayaccess;
e9dbeab @andigutmans - Fix typos
andigutmans authored
30 ZEND_API zend_class_entry *zend_ce_serializable;
8abb3bd Impement userspace iterator interfaces and tests. See tests for details
Marcus Boerger authored
31
637a404 - MFH as discussed
Marcus Boerger authored
32 /* {{{ zend_call_method
8abb3bd Impement userspace iterator interfaces and tests. See tests for details
Marcus Boerger authored
33 Only returns the returned zval if retval_ptr != NULL */
34 ZEND_API zval* zend_call_method(zval **object_pp, zend_class_entry *obj_ce, zend_function **fn_proxy, char *function_name, int function_name_len, zval **retval_ptr_ptr, int param_count, zval* arg1, zval* arg2 TSRMLS_DC)
35 {
36 int result;
37 zend_fcall_info fci;
38 zval z_fname;
39 zval *retval;
0b3ed59 - Support statuc methods/functions
Marcus Boerger authored
40 HashTable *function_table;
8abb3bd Impement userspace iterator interfaces and tests. See tests for details
Marcus Boerger authored
41
42 zval **params[2];
43
44 params[0] = &arg1;
45 params[1] = &arg2;
46
47 fci.size = sizeof(fci);
48 /*fci.function_table = NULL; will be read form zend_class_entry of object if needed */
49 fci.object_pp = object_pp;
50 fci.function_name = &z_fname;
51 fci.retval_ptr_ptr = retval_ptr_ptr ? retval_ptr_ptr : &retval;
52 fci.param_count = param_count;
53 fci.params = params;
54 fci.no_separation = 1;
55 fci.symbol_table = NULL;
56
57 if (!fn_proxy && !obj_ce) {
58 /* no interest in caching and no information already present that is
59 * needed later inside zend_call_function. */
60 ZVAL_STRINGL(&z_fname, function_name, function_name_len, 0);
48d9adc - MFH Allow uncached global functions
Marcus Boerger authored
61 fci.function_table = !object_pp ? EG(function_table) : NULL;
8abb3bd Impement userspace iterator interfaces and tests. See tests for details
Marcus Boerger authored
62 result = zend_call_function(&fci, NULL TSRMLS_CC);
63 } else {
64 zend_fcall_info_cache fcic;
65
66 fcic.initialized = 1;
67 if (!obj_ce) {
0b3ed59 - Support statuc methods/functions
Marcus Boerger authored
68 obj_ce = object_pp ? Z_OBJCE_PP(object_pp) : NULL;
69 }
70 if (obj_ce) {
71 function_table = &obj_ce->function_table;
72 } else {
73 function_table = EG(function_table);
8abb3bd Impement userspace iterator interfaces and tests. See tests for details
Marcus Boerger authored
74 }
75 if (!fn_proxy || !*fn_proxy) {
0b3ed59 - Support statuc methods/functions
Marcus Boerger authored
76 if (zend_hash_find(function_table, function_name, function_name_len+1, (void **) &fcic.function_handler) == FAILURE) {
8abb3bd Impement userspace iterator interfaces and tests. See tests for details
Marcus Boerger authored
77 /* error at c-level */
0b3ed59 - Support statuc methods/functions
Marcus Boerger authored
78 zend_error(E_CORE_ERROR, "Couldn't find implementation for method %s%s%s", obj_ce ? obj_ce->name : "", obj_ce ? "::" : "", function_name);
8abb3bd Impement userspace iterator interfaces and tests. See tests for details
Marcus Boerger authored
79 }
80 if (fn_proxy) {
81 *fn_proxy = fcic.function_handler;
82 }
83 } else {
84 fcic.function_handler = *fn_proxy;
85 }
86 fcic.calling_scope = obj_ce;
87 fcic.object_pp = object_pp;
88 result = zend_call_function(&fci, &fcic TSRMLS_CC);
89 }
90 if (result == FAILURE) {
91 /* error at c-level */
92 if (!obj_ce) {
0b3ed59 - Support statuc methods/functions
Marcus Boerger authored
93 obj_ce = object_pp ? Z_OBJCE_PP(object_pp) : NULL;
8abb3bd Impement userspace iterator interfaces and tests. See tests for details
Marcus Boerger authored
94 }
f7ba723 @tony2001 MFH: fix #38624 (Strange warning when incrementing an object property…
tony2001 authored
95 if (!EG(exception)) {
96 zend_error(E_CORE_ERROR, "Couldn't execute method %s%s%s", obj_ce ? obj_ce->name : "", obj_ce ? "::" : "", function_name);
97 }
8abb3bd Impement userspace iterator interfaces and tests. See tests for details
Marcus Boerger authored
98 }
99 if (!retval_ptr_ptr) {
100 if (retval) {
39df192 Correct destruction
Marcus Boerger authored
101 zval_ptr_dtor(&retval);
8abb3bd Impement userspace iterator interfaces and tests. See tests for details
Marcus Boerger authored
102 }
103 return NULL;
104 }
105 return *retval_ptr_ptr;
106 }
107 /* }}} */
108
109 /* iterator interface, c-level functions used by engine */
110
6186617 - Export struct zend_user_iterator
Marcus Boerger authored
111 /* {{{ zend_user_it_new_iterator */
637a404 - MFH as discussed
Marcus Boerger authored
112 ZEND_API zval *zend_user_it_new_iterator(zend_class_entry *ce, zval *object TSRMLS_DC)
8abb3bd Impement userspace iterator interfaces and tests. See tests for details
Marcus Boerger authored
113 {
114 zval *retval;
115
116 return zend_call_method_with_0_params(&object, ce, &ce->iterator_funcs.zf_new_iterator, "getiterator", &retval);
5824641 IteratorAggregate::getIterator() cannot return anythingy else than ob…
Marcus Boerger authored
117
8abb3bd Impement userspace iterator interfaces and tests. See tests for details
Marcus Boerger authored
118 }
119 /* }}} */
120
6186617 - Export struct zend_user_iterator
Marcus Boerger authored
121 /* {{{ zend_user_it_dtor */
637a404 - MFH as discussed
Marcus Boerger authored
122 ZEND_API void zend_user_it_invalidate_current(zend_object_iterator *_iter TSRMLS_DC)
6186617 - Export struct zend_user_iterator
Marcus Boerger authored
123 {
124 zend_user_iterator *iter = (zend_user_iterator*)_iter;
125
126 if (iter->value) {
127 zval_ptr_dtor(&iter->value);
128 iter->value = NULL;
129 }
130 }
131 /* }}} */
132
133 /* {{{ zend_user_it_dtor */
134 static void zend_user_it_dtor(zend_object_iterator *_iter TSRMLS_DC)
8abb3bd Impement userspace iterator interfaces and tests. See tests for details
Marcus Boerger authored
135 {
136 zend_user_iterator *iter = (zend_user_iterator*)_iter;
137 zval *object = (zval*)iter->it.data;
138
11ce65a - Fix warnings
Marcus Boerger authored
139 zend_user_it_invalidate_current(_iter TSRMLS_CC);
8abb3bd Impement userspace iterator interfaces and tests. See tests for details
Marcus Boerger authored
140 zval_ptr_dtor(&object);
141 efree(iter);
142 }
143 /* }}} */
144
6b0f57e Rename hasMore() to valid() as discussed. (Part II)
Marcus Boerger authored
145 /* {{{ zend_user_it_valid */
637a404 - MFH as discussed
Marcus Boerger authored
146 ZEND_API int zend_user_it_valid(zend_object_iterator *_iter TSRMLS_DC)
8abb3bd Impement userspace iterator interfaces and tests. See tests for details
Marcus Boerger authored
147 {
f9d1309 Prevent some SEGV's when Exceptions are thorown inside iterators.
Marcus Boerger authored
148 if (_iter) {
149 zend_user_iterator *iter = (zend_user_iterator*)_iter;
150 zval *object = (zval*)iter->it.data;
151 zval *more;
152 int result;
637a404 - MFH as discussed
Marcus Boerger authored
153
6b0f57e Rename hasMore() to valid() as discussed. (Part II)
Marcus Boerger authored
154 zend_call_method_with_0_params(&object, iter->ce, &iter->ce->iterator_funcs.zf_valid, "valid", &more);
f9d1309 Prevent some SEGV's when Exceptions are thorown inside iterators.
Marcus Boerger authored
155 if (more) {
156 result = i_zend_is_true(more);
b29834a Use correct macro/function
Marcus Boerger authored
157 zval_ptr_dtor(&more);
f9d1309 Prevent some SEGV's when Exceptions are thorown inside iterators.
Marcus Boerger authored
158 return result ? SUCCESS : FAILURE;
159 }
160 }
161 return FAILURE;
8abb3bd Impement userspace iterator interfaces and tests. See tests for details
Marcus Boerger authored
162 }
163 /* }}} */
164
6186617 - Export struct zend_user_iterator
Marcus Boerger authored
165 /* {{{ zend_user_it_get_current_data */
637a404 - MFH as discussed
Marcus Boerger authored
166 ZEND_API void zend_user_it_get_current_data(zend_object_iterator *_iter, zval ***data TSRMLS_DC)
8abb3bd Impement userspace iterator interfaces and tests. See tests for details
Marcus Boerger authored
167 {
168 zend_user_iterator *iter = (zend_user_iterator*)_iter;
169 zval *object = (zval*)iter->it.data;
170
171 if (!iter->value) {
172 zend_call_method_with_0_params(&object, iter->ce, &iter->ce->iterator_funcs.zf_current, "current", &iter->value);
173 }
174 *data = &iter->value;
175 }
176 /* }}} */
177
6186617 - Export struct zend_user_iterator
Marcus Boerger authored
178 /* {{{ zend_user_it_get_current_key_default */
8abb3bd Impement userspace iterator interfaces and tests. See tests for details
Marcus Boerger authored
179 #if 0
6186617 - Export struct zend_user_iterator
Marcus Boerger authored
180 static int zend_user_it_get_current_key_default(zend_object_iterator *_iter, char **str_key, uint *str_key_len, ulong *int_key TSRMLS_DC)
8abb3bd Impement userspace iterator interfaces and tests. See tests for details
Marcus Boerger authored
181 {
da6d68d Little iterator improvement: ability to store index in iterator
Marcus Boerger authored
182 *int_key = _iter->index;
8abb3bd Impement userspace iterator interfaces and tests. See tests for details
Marcus Boerger authored
183 return HASH_KEY_IS_LONG;
184 }
185 #endif
186 /* }}} */
187
6186617 - Export struct zend_user_iterator
Marcus Boerger authored
188 /* {{{ zend_user_it_get_current_key */
637a404 - MFH as discussed
Marcus Boerger authored
189 ZEND_API int zend_user_it_get_current_key(zend_object_iterator *_iter, char **str_key, uint *str_key_len, ulong *int_key TSRMLS_DC)
8abb3bd Impement userspace iterator interfaces and tests. See tests for details
Marcus Boerger authored
190 {
191 zend_user_iterator *iter = (zend_user_iterator*)_iter;
192 zval *object = (zval*)iter->it.data;
193 zval *retval;
194
195 zend_call_method_with_0_params(&object, iter->ce, &iter->ce->iterator_funcs.zf_key, "key", &retval);
196
c5abb9b Capture potential problem by error message
Marcus Boerger authored
197 if (!retval) {
198 *int_key = 0;
897090c - Dont't warn in case an exception is pending - in this case it'd sup…
Marcus Boerger authored
199 if (!EG(exception))
200 {
201 zend_error(E_WARNING, "Nothing returned from %s::key()", iter->ce->name);
202 }
c5abb9b Capture potential problem by error message
Marcus Boerger authored
203 return HASH_KEY_IS_LONG;
204 }
7a5240e - MFH missing bits and pieces of the partial sync with head
Marcus Boerger authored
205 switch (Z_TYPE_P(retval)) {
206 default:
8abb3bd Impement userspace iterator interfaces and tests. See tests for details
Marcus Boerger authored
207 zend_error(E_WARNING, "Illegal type returned from %s::key()", iter->ce->name);
208 case IS_NULL:
209 *int_key = 0;
210 zval_ptr_dtor(&retval);
211 return HASH_KEY_IS_LONG;
212
213 case IS_STRING:
7a5240e - MFH missing bits and pieces of the partial sync with head
Marcus Boerger authored
214 *str_key = estrndup(Z_STRVAL_P(retval), Z_STRLEN_P(retval));
215 *str_key_len = Z_STRLEN_P(retval)+1;
8abb3bd Impement userspace iterator interfaces and tests. See tests for details
Marcus Boerger authored
216 zval_ptr_dtor(&retval);
217 return HASH_KEY_IS_STRING;
218
219 case IS_DOUBLE:
7a5240e - MFH missing bits and pieces of the partial sync with head
Marcus Boerger authored
220 *int_key = (long)Z_DVAL_P(retval);
221 zval_ptr_dtor(&retval);
222 return HASH_KEY_IS_LONG;
223
8abb3bd Impement userspace iterator interfaces and tests. See tests for details
Marcus Boerger authored
224 case IS_RESOURCE:
637a404 - MFH as discussed
Marcus Boerger authored
225 case IS_BOOL:
7a5240e - MFH missing bits and pieces of the partial sync with head
Marcus Boerger authored
226 case IS_LONG:
227 *int_key = (long)Z_LVAL_P(retval);
8abb3bd Impement userspace iterator interfaces and tests. See tests for details
Marcus Boerger authored
228 zval_ptr_dtor(&retval);
229 return HASH_KEY_IS_LONG;
230 }
231 }
232 /* }}} */
233
6186617 - Export struct zend_user_iterator
Marcus Boerger authored
234 /* {{{ zend_user_it_move_forward */
637a404 - MFH as discussed
Marcus Boerger authored
235 ZEND_API void zend_user_it_move_forward(zend_object_iterator *_iter TSRMLS_DC)
8abb3bd Impement userspace iterator interfaces and tests. See tests for details
Marcus Boerger authored
236 {
237 zend_user_iterator *iter = (zend_user_iterator*)_iter;
238 zval *object = (zval*)iter->it.data;
239
11ce65a - Fix warnings
Marcus Boerger authored
240 zend_user_it_invalidate_current(_iter TSRMLS_CC);
8abb3bd Impement userspace iterator interfaces and tests. See tests for details
Marcus Boerger authored
241 zend_call_method_with_0_params(&object, iter->ce, &iter->ce->iterator_funcs.zf_next, "next", NULL);
242 }
243 /* }}} */
244
6186617 - Export struct zend_user_iterator
Marcus Boerger authored
245 /* {{{ zend_user_it_rewind */
637a404 - MFH as discussed
Marcus Boerger authored
246 ZEND_API void zend_user_it_rewind(zend_object_iterator *_iter TSRMLS_DC)
8abb3bd Impement userspace iterator interfaces and tests. See tests for details
Marcus Boerger authored
247 {
248 zend_user_iterator *iter = (zend_user_iterator*)_iter;
249 zval *object = (zval*)iter->it.data;
250
11ce65a - Fix warnings
Marcus Boerger authored
251 zend_user_it_invalidate_current(_iter TSRMLS_CC);
8abb3bd Impement userspace iterator interfaces and tests. See tests for details
Marcus Boerger authored
252 zend_call_method_with_0_params(&object, iter->ce, &iter->ce->iterator_funcs.zf_rewind, "rewind", NULL);
253 }
254 /* }}} */
255
256 zend_object_iterator_funcs zend_interface_iterator_funcs_iterator = {
6186617 - Export struct zend_user_iterator
Marcus Boerger authored
257 zend_user_it_dtor,
6b0f57e Rename hasMore() to valid() as discussed. (Part II)
Marcus Boerger authored
258 zend_user_it_valid,
6186617 - Export struct zend_user_iterator
Marcus Boerger authored
259 zend_user_it_get_current_data,
260 zend_user_it_get_current_key,
261 zend_user_it_move_forward,
e1cd098 - no unneccessary retval initialization
Marcus Boerger authored
262 zend_user_it_rewind,
263 zend_user_it_invalidate_current
8abb3bd Impement userspace iterator interfaces and tests. See tests for details
Marcus Boerger authored
264 };
265
6186617 - Export struct zend_user_iterator
Marcus Boerger authored
266 /* {{{ zend_user_it_get_iterator */
637a404 - MFH as discussed
Marcus Boerger authored
267 static zend_object_iterator *zend_user_it_get_iterator(zend_class_entry *ce, zval *object, int by_ref TSRMLS_DC)
8abb3bd Impement userspace iterator interfaces and tests. See tests for details
Marcus Boerger authored
268 {
637a404 - MFH as discussed
Marcus Boerger authored
269 zend_user_iterator *iterator;
270
271 if (by_ref) {
272 zend_error(E_ERROR, "An iterator cannot be used with foreach by reference");
273 }
274
275 iterator = emalloc(sizeof(zend_user_iterator));
8abb3bd Impement userspace iterator interfaces and tests. See tests for details
Marcus Boerger authored
276
277 object->refcount++;
278 iterator->it.data = (void*)object;
279 iterator->it.funcs = ce->iterator_funcs.funcs;
280 iterator->ce = Z_OBJCE_P(object);
281 iterator->value = NULL;
282 return (zend_object_iterator*)iterator;
283 }
284 /* }}} */
285
6186617 - Export struct zend_user_iterator
Marcus Boerger authored
286 /* {{{ zend_user_it_get_new_iterator */
637a404 - MFH as discussed
Marcus Boerger authored
287 ZEND_API zend_object_iterator *zend_user_it_get_new_iterator(zend_class_entry *ce, zval *object, int by_ref TSRMLS_DC)
8abb3bd Impement userspace iterator interfaces and tests. See tests for details
Marcus Boerger authored
288 {
6186617 - Export struct zend_user_iterator
Marcus Boerger authored
289 zval *iterator = zend_user_it_new_iterator(ce, object TSRMLS_CC);
c978cc2 Use correct order
Marcus Boerger authored
290 zend_object_iterator *new_iterator;
8abb3bd Impement userspace iterator interfaces and tests. See tests for details
Marcus Boerger authored
291
5206e9c - Allow getIterator() to fail
Marcus Boerger authored
292 zend_class_entry *ce_it = iterator && Z_TYPE_P(iterator) == IS_OBJECT ? Z_OBJCE_P(iterator) : NULL;
5824641 IteratorAggregate::getIterator() cannot return anythingy else than ob…
Marcus Boerger authored
293
637a404 - MFH as discussed
Marcus Boerger authored
294 if (!ce_it || !ce_it->get_iterator || (ce_it->get_iterator == zend_user_it_get_new_iterator && iterator == object)) {
295 if (!EG(exception)) {
6c89fd2 - MFH Coverity fix 49
Marcus Boerger authored
296 zend_throw_exception_ex(NULL, 0 TSRMLS_CC, "Objects returned by %s::getIterator() must be traversable or implement interface Iterator", ce ? ce->name : Z_OBJCE_P(object)->name);
5206e9c - Allow getIterator() to fail
Marcus Boerger authored
297 }
637a404 - MFH as discussed
Marcus Boerger authored
298 if (iterator) {
5206e9c - Allow getIterator() to fail
Marcus Boerger authored
299 zval_ptr_dtor(&iterator);
300 }
8abb3bd Impement userspace iterator interfaces and tests. See tests for details
Marcus Boerger authored
301 return NULL;
302 }
637a404 - MFH as discussed
Marcus Boerger authored
303
304 new_iterator = ce_it->get_iterator(ce_it, iterator, by_ref TSRMLS_CC);
c978cc2 Use correct order
Marcus Boerger authored
305 zval_ptr_dtor(&iterator);
306 return new_iterator;
8abb3bd Impement userspace iterator interfaces and tests. See tests for details
Marcus Boerger authored
307 }
308 /* }}} */
309
310 /* {{{ zend_implement_traversable */
311 static int zend_implement_traversable(zend_class_entry *interface, zend_class_entry *class_type TSRMLS_DC)
312 {
313 /* check that class_type is traversable at c-level or implements at least one of 'aggregate' and 'Iterator' */
01af2c3 Fix warnign
Marcus Boerger authored
314 zend_uint i;
8abb3bd Impement userspace iterator interfaces and tests. See tests for details
Marcus Boerger authored
315
64c7645 #where has my bracket been gone?
Marcus Boerger authored
316 if (class_type->get_iterator || (class_type->parent && class_type->parent->get_iterator)) {
8abb3bd Impement userspace iterator interfaces and tests. See tests for details
Marcus Boerger authored
317 return SUCCESS;
50ee116 Clearify the different method/class flags (as discussed with Andi).
Marcus Boerger authored
318 }
8abb3bd Impement userspace iterator interfaces and tests. See tests for details
Marcus Boerger authored
319 for (i = 0; i < class_type->num_interfaces; i++) {
320 if (class_type->interfaces[i] == zend_ce_aggregate || class_type->interfaces[i] == zend_ce_iterator) {
321 return SUCCESS;
322 }
323 }
324 zend_error(E_CORE_ERROR, "Class %s must implement interface %s as part of either %s or %s",
325 class_type->name,
326 zend_ce_traversable->name,
327 zend_ce_iterator->name,
328 zend_ce_aggregate->name);
329 return FAILURE;
330 }
331 /* }}} */
332
333 /* {{{ zend_implement_aggregate */
334 static int zend_implement_aggregate(zend_class_entry *interface, zend_class_entry *class_type TSRMLS_DC)
335 {
72c1baa - Allow to convert Traversable into Aggregate
Marcus Boerger authored
336 int i, t = -1;
337
851a02e Give some freedon to c iterators but not in userspace.
Marcus Boerger authored
338 if (class_type->get_iterator) {
339 if (class_type->type == ZEND_INTERNAL_CLASS) {
340 /* inheritance ensures the class has necessary userland methods */
341 return SUCCESS;
6186617 - Export struct zend_user_iterator
Marcus Boerger authored
342 } else if (class_type->get_iterator != zend_user_it_get_new_iterator) {
72c1baa - Allow to convert Traversable into Aggregate
Marcus Boerger authored
343 /* c-level get_iterator cannot be changed (exception being only Traversable is implmented) */
344 if (class_type->num_interfaces) {
637a404 - MFH as discussed
Marcus Boerger authored
345 for (i = 0; i < class_type->num_interfaces; i++) {
72c1baa - Allow to convert Traversable into Aggregate
Marcus Boerger authored
346 if (class_type->interfaces[i] == zend_ce_iterator) {
347 return FAILURE;
348 }
349 if (class_type->interfaces[i] == zend_ce_traversable) {
350 t = i;
351 }
352 }
353 }
354 if (t == -1) {
355 return FAILURE;
356 }
851a02e Give some freedon to c iterators but not in userspace.
Marcus Boerger authored
357 }
8abb3bd Impement userspace iterator interfaces and tests. See tests for details
Marcus Boerger authored
358 }
359 class_type->iterator_funcs.zf_new_iterator = NULL;
6186617 - Export struct zend_user_iterator
Marcus Boerger authored
360 class_type->get_iterator = zend_user_it_get_new_iterator;
8abb3bd Impement userspace iterator interfaces and tests. See tests for details
Marcus Boerger authored
361 return SUCCESS;
362 }
363 /* }}} */
364
365 /* {{{ zend_implement_iterator */
366 static int zend_implement_iterator(zend_class_entry *interface, zend_class_entry *class_type TSRMLS_DC)
367 {
6186617 - Export struct zend_user_iterator
Marcus Boerger authored
368 if (class_type->get_iterator && class_type->get_iterator != zend_user_it_get_iterator) {
851a02e Give some freedon to c iterators but not in userspace.
Marcus Boerger authored
369 if (class_type->type == ZEND_INTERNAL_CLASS) {
370 /* inheritance ensures the class has the necessary userland methods */
371 return SUCCESS;
6186617 - Export struct zend_user_iterator
Marcus Boerger authored
372 } else if (class_type->get_iterator != zend_user_it_get_new_iterator) {
851a02e Give some freedon to c iterators but not in userspace.
Marcus Boerger authored
373 /* c-level get_iterator cannot be changed */
374 return FAILURE;
375 }
8abb3bd Impement userspace iterator interfaces and tests. See tests for details
Marcus Boerger authored
376 }
6186617 - Export struct zend_user_iterator
Marcus Boerger authored
377 class_type->get_iterator = zend_user_it_get_iterator;
6b0f57e Rename hasMore() to valid() as discussed. (Part II)
Marcus Boerger authored
378 class_type->iterator_funcs.zf_valid = NULL;
8abb3bd Impement userspace iterator interfaces and tests. See tests for details
Marcus Boerger authored
379 class_type->iterator_funcs.zf_current = NULL;
380 class_type->iterator_funcs.zf_key = NULL;
381 class_type->iterator_funcs.zf_next = NULL;
382 class_type->iterator_funcs.zf_rewind = NULL;
383 if (!class_type->iterator_funcs.funcs) {
384 class_type->iterator_funcs.funcs = &zend_interface_iterator_funcs_iterator;
385 }
386 return SUCCESS;
387 }
388 /* }}} */
389
4dba05d Add new interface ArrayAccess to use objects as Arrays
Marcus Boerger authored
390 /* {{{ zend_implement_arrayaccess */
391 static int zend_implement_arrayaccess(zend_class_entry *interface, zend_class_entry *class_type TSRMLS_DC)
392 {
6186617 - Export struct zend_user_iterator
Marcus Boerger authored
393 #if 0
394 /* get ht from ce */
395 if (ht->read_dimension != zend_std_read_dimension
396 || ht->write_dimension != zend_std_write_dimension
397 || ht->has_dimension != zend_std_has_dimension
398 || ht->unset_dimension != zend_std_unset_dimension) {
399 return FAILURE;
400 }
401 #endif
4dba05d Add new interface ArrayAccess to use objects as Arrays
Marcus Boerger authored
402 return SUCCESS;
403 }
404 /* }}}*/
405
757da1e - New Interface Serializeable
Marcus Boerger authored
406 /* {{{ zend_user_serialize */
407 int zend_user_serialize(zval *object, unsigned char **buffer, zend_uint *buf_len, zend_serialize_data *data TSRMLS_DC)
408 {
409 zend_class_entry * ce = Z_OBJCE_P(object);
410 zval *retval;
411 int result;
412
413 zend_call_method_with_0_params(&object, ce, &ce->serialize_func, "serialize", &retval);
414
415
416 if (!retval || EG(exception)) {
417 result = FAILURE;
418 } else {
419 switch(Z_TYPE_P(retval)) {
420 case IS_NULL:
421 /* we could also make this '*buf_len = 0' but this allows to skip variables */
d77945e - Just return FAILURE & allow NULL without emmidiate error
Marcus Boerger authored
422 zval_ptr_dtor(&retval);
423 return FAILURE;
757da1e - New Interface Serializeable
Marcus Boerger authored
424 case IS_STRING:
425 *buffer = estrndup(Z_STRVAL_P(retval), Z_STRLEN_P(retval));
426 *buf_len = Z_STRLEN_P(retval);
427 result = SUCCESS;
428 break;
429 default: /* failure */
430 result = FAILURE;
431 break;
432 }
433 zval_ptr_dtor(&retval);
434 }
435
436 if (result == FAILURE) {
80d7ac0 @tony2001 there is no %v in 5.2
tony2001 authored
437 zend_throw_exception_ex(NULL, 0 TSRMLS_CC, "%s::serialize() must return a string or NULL", ce->name);
757da1e - New Interface Serializeable
Marcus Boerger authored
438 }
439 return result;
440 }
441 /* }}} */
442
443 /* {{{ zend_user_unserialize */
444 int zend_user_unserialize(zval **object, zend_class_entry *ce, const unsigned char *buf, zend_uint buf_len, zend_unserialize_data *data TSRMLS_DC)
445 {
446 zval * zdata;
447
448 object_init_ex(*object, ce);
637a404 - MFH as discussed
Marcus Boerger authored
449
757da1e - New Interface Serializeable
Marcus Boerger authored
450 MAKE_STD_ZVAL(zdata);
451 ZVAL_STRINGL(zdata, (char*)buf, buf_len, 1);
452
453 zend_call_method_with_1_params(object, ce, &ce->unserialize_func, "unserialize", NULL, zdata);
637a404 - MFH as discussed
Marcus Boerger authored
454
757da1e - New Interface Serializeable
Marcus Boerger authored
455 zval_ptr_dtor(&zdata);
637a404 - MFH as discussed
Marcus Boerger authored
456
757da1e - New Interface Serializeable
Marcus Boerger authored
457 if (EG(exception)) {
458 return FAILURE;
459 } else {
460 return SUCCESS;
461 }
462 }
463 /* }}} */
464
e9dbeab @andigutmans - Fix typos
andigutmans authored
465 /* {{{ zend_implement_serializable */
466 static int zend_implement_serializable(zend_class_entry *interface, zend_class_entry *class_type TSRMLS_DC)
757da1e - New Interface Serializeable
Marcus Boerger authored
467 {
468 if ((class_type->serialize && class_type->serialize != zend_user_serialize)
469 || (class_type->unserialize && class_type->unserialize != zend_user_unserialize)
470 ) {
471 return FAILURE;
472 }
473 class_type->serialize = zend_user_serialize;
474 class_type->unserialize = zend_user_unserialize;
475 return SUCCESS;
476 }
477 /* }}}*/
478
8abb3bd Impement userspace iterator interfaces and tests. See tests for details
Marcus Boerger authored
479 /* {{{ function tables */
6c810b0 Improved memory usage by movig constants to read only memory. (Dmitry…
Dmitry Stogov authored
480 const zend_function_entry zend_funcs_aggregate[] = {
8abb3bd Impement userspace iterator interfaces and tests. See tests for details
Marcus Boerger authored
481 ZEND_ABSTRACT_ME(iterator, getIterator, NULL)
482 {NULL, NULL, NULL}
483 };
484
6c810b0 Improved memory usage by movig constants to read only memory. (Dmitry…
Dmitry Stogov authored
485 const zend_function_entry zend_funcs_iterator[] = {
8abb3bd Impement userspace iterator interfaces and tests. See tests for details
Marcus Boerger authored
486 ZEND_ABSTRACT_ME(iterator, current, NULL)
487 ZEND_ABSTRACT_ME(iterator, next, NULL)
488 ZEND_ABSTRACT_ME(iterator, key, NULL)
b6b7c9e Rename hasMore() to valid() as discussed. (Part I)
Marcus Boerger authored
489 ZEND_ABSTRACT_ME(iterator, valid, NULL)
da6d68d Little iterator improvement: ability to store index in iterator
Marcus Boerger authored
490 ZEND_ABSTRACT_ME(iterator, rewind, NULL)
8abb3bd Impement userspace iterator interfaces and tests. See tests for details
Marcus Boerger authored
491 {NULL, NULL, NULL}
492 };
493
6c810b0 Improved memory usage by movig constants to read only memory. (Dmitry…
Dmitry Stogov authored
494 const zend_function_entry *zend_funcs_traversable = NULL;
4dba05d Add new interface ArrayAccess to use objects as Arrays
Marcus Boerger authored
495
496 static
c6e3947 - More exact signatures (even though complete correct not possible atm)
Marcus Boerger authored
497 ZEND_BEGIN_ARG_INFO_EX(arginfo_arrayaccess_offset, 0, 0, 1)
4dba05d Add new interface ArrayAccess to use objects as Arrays
Marcus Boerger authored
498 ZEND_ARG_INFO(0, offset)
23eaae2 @tony2001 MFH
tony2001 authored
499 ZEND_END_ARG_INFO()
4dba05d Add new interface ArrayAccess to use objects as Arrays
Marcus Boerger authored
500
501 static
c6e3947 - More exact signatures (even though complete correct not possible atm)
Marcus Boerger authored
502 ZEND_BEGIN_ARG_INFO_EX(arginfo_arrayaccess_offset_get, 0, 0, 1) /* actually this should be return by ref but atm cannot be */
503 ZEND_ARG_INFO(0, offset)
23eaae2 @tony2001 MFH
tony2001 authored
504 ZEND_END_ARG_INFO()
c6e3947 - More exact signatures (even though complete correct not possible atm)
Marcus Boerger authored
505
506 static
637a404 - MFH as discussed
Marcus Boerger authored
507 ZEND_BEGIN_ARG_INFO_EX(arginfo_arrayaccess_offset_value, 0, 0, 2)
4dba05d Add new interface ArrayAccess to use objects as Arrays
Marcus Boerger authored
508 ZEND_ARG_INFO(0, offset)
509 ZEND_ARG_INFO(0, value)
23eaae2 @tony2001 MFH
tony2001 authored
510 ZEND_END_ARG_INFO()
4dba05d Add new interface ArrayAccess to use objects as Arrays
Marcus Boerger authored
511
6c810b0 Improved memory usage by movig constants to read only memory. (Dmitry…
Dmitry Stogov authored
512 const zend_function_entry zend_funcs_arrayaccess[] = {
4dba05d Add new interface ArrayAccess to use objects as Arrays
Marcus Boerger authored
513 ZEND_ABSTRACT_ME(arrayaccess, offsetExists, arginfo_arrayaccess_offset)
c6e3947 - More exact signatures (even though complete correct not possible atm)
Marcus Boerger authored
514 ZEND_ABSTRACT_ME(arrayaccess, offsetGet, arginfo_arrayaccess_offset_get)
4dba05d Add new interface ArrayAccess to use objects as Arrays
Marcus Boerger authored
515 ZEND_ABSTRACT_ME(arrayaccess, offsetSet, arginfo_arrayaccess_offset_value)
516 ZEND_ABSTRACT_ME(arrayaccess, offsetUnset, arginfo_arrayaccess_offset)
517 {NULL, NULL, NULL}
518 };
519
757da1e - New Interface Serializeable
Marcus Boerger authored
520 static
e9dbeab @andigutmans - Fix typos
andigutmans authored
521 ZEND_BEGIN_ARG_INFO(arginfo_serializable_serialize, 0)
757da1e - New Interface Serializeable
Marcus Boerger authored
522 ZEND_ARG_INFO(0, serialized)
23eaae2 @tony2001 MFH
tony2001 authored
523 ZEND_END_ARG_INFO()
757da1e - New Interface Serializeable
Marcus Boerger authored
524
6c810b0 Improved memory usage by movig constants to read only memory. (Dmitry…
Dmitry Stogov authored
525 const zend_function_entry zend_funcs_serializable[] = {
e9dbeab @andigutmans - Fix typos
andigutmans authored
526 ZEND_ABSTRACT_ME(serializable, serialize, NULL)
637a404 - MFH as discussed
Marcus Boerger authored
527 ZEND_FENTRY(unserialize, NULL, arginfo_serializable_serialize, ZEND_ACC_PUBLIC|ZEND_ACC_ABSTRACT|ZEND_ACC_CTOR)
757da1e - New Interface Serializeable
Marcus Boerger authored
528 {NULL, NULL, NULL}
529 };
8abb3bd Impement userspace iterator interfaces and tests. See tests for details
Marcus Boerger authored
530 /* }}} */
531
532 #define REGISTER_ITERATOR_INTERFACE(class_name, class_name_str) \
533 {\
534 zend_class_entry ce;\
535 INIT_CLASS_ENTRY(ce, # class_name_str, zend_funcs_ ## class_name) \
536 zend_ce_ ## class_name = zend_register_internal_interface(&ce TSRMLS_CC);\
537 zend_ce_ ## class_name->interface_gets_implemented = zend_implement_ ## class_name;\
538 }
539
540 #define REGISTER_ITERATOR_IMPLEMENT(class_name, interface_name) \
541 zend_class_implements(zend_ce_ ## class_name TSRMLS_CC, 1, zend_ce_ ## interface_name)
542
543 /* {{{ zend_register_interfaces */
544 ZEND_API void zend_register_interfaces(TSRMLS_D)
545 {
546 REGISTER_ITERATOR_INTERFACE(traversable, Traversable);
547
548 REGISTER_ITERATOR_INTERFACE(aggregate, IteratorAggregate);
549 REGISTER_ITERATOR_IMPLEMENT(aggregate, traversable);
550
551 REGISTER_ITERATOR_INTERFACE(iterator, Iterator);
552 REGISTER_ITERATOR_IMPLEMENT(iterator, traversable);
637a404 - MFH as discussed
Marcus Boerger authored
553
4dba05d Add new interface ArrayAccess to use objects as Arrays
Marcus Boerger authored
554 REGISTER_ITERATOR_INTERFACE(arrayaccess, ArrayAccess);
637a404 - MFH as discussed
Marcus Boerger authored
555
e9dbeab @andigutmans - Fix typos
andigutmans authored
556 REGISTER_ITERATOR_INTERFACE(serializable, Serializable)
8abb3bd Impement userspace iterator interfaces and tests. See tests for details
Marcus Boerger authored
557 }
558 /* }}} */
559
560 /*
561 * Local variables:
562 * tab-width: 4
563 * c-basic-offset: 4
564 * indent-tabs-mode: t
565 * End:
566 */
Something went wrong with that request. Please try again.