Skip to content

HTTPS clone URL

Subversion checkout URL

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