Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

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