Skip to content

HTTPS clone URL

Subversion checkout URL

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