Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Newer
Older
100755 561 lines (488 sloc) 17.21 kb
8abb3bd Impement userspace iterator interfaces and tests. See tests for details
Marcus Boerger authored
1 /*
2 +----------------------------------------------------------------------+
3 | Zend Engine |
4 +----------------------------------------------------------------------+
916815b Bump up the year
foobar authored
5 | Copyright (c) 1998-2005 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 Stanislav Malyshev 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
32 /* {{{ zend_call_method
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 */
110 static 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 objec...
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 */
e1cd098 - no unneccessary retval initialization
Marcus Boerger authored
120 static 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 */
144 static 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;
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 */
164 static 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 */
187 static 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 superf...
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 }
8abb3bd Impement userspace iterator interfaces and tests. See tests for details
Marcus Boerger authored
203 switch (retval->type) {
204 default:
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:
212 *str_key = estrndup(retval->value.str.val, retval->value.str.len);
213 *str_key_len = retval->value.str.len+1;
214 zval_ptr_dtor(&retval);
215 return HASH_KEY_IS_STRING;
216
217 case IS_DOUBLE:
218 case IS_RESOURCE:
219 case IS_BOOL:
220 case IS_LONG: {
221 if (retval->type == IS_DOUBLE) {
222 *int_key = (long)retval->value.dval;
223 } else {
224 *int_key = retval->value.lval;
225 }
226 }
227 zval_ptr_dtor(&retval);
228 return HASH_KEY_IS_LONG;
229 }
230 }
231 /* }}} */
232
6186617 - Export struct zend_user_iterator
Marcus Boerger authored
233 /* {{{ zend_user_it_move_forward */
234 static 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
235 {
236 zend_user_iterator *iter = (zend_user_iterator*)_iter;
237 zval *object = (zval*)iter->it.data;
238
11ce65a - Fix warnings
Marcus Boerger authored
239 zend_user_it_invalidate_current(_iter TSRMLS_CC);
8abb3bd Impement userspace iterator interfaces and tests. See tests for details
Marcus Boerger authored
240 zend_call_method_with_0_params(&object, iter->ce, &iter->ce->iterator_funcs.zf_next, "next", NULL);
241 }
242 /* }}} */
243
6186617 - Export struct zend_user_iterator
Marcus Boerger authored
244 /* {{{ zend_user_it_rewind */
245 static 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
246 {
247 zend_user_iterator *iter = (zend_user_iterator*)_iter;
248 zval *object = (zval*)iter->it.data;
249
11ce65a - Fix warnings
Marcus Boerger authored
250 zend_user_it_invalidate_current(_iter TSRMLS_CC);
8abb3bd Impement userspace iterator interfaces and tests. See tests for details
Marcus Boerger authored
251 zend_call_method_with_0_params(&object, iter->ce, &iter->ce->iterator_funcs.zf_rewind, "rewind", NULL);
252 }
253 /* }}} */
254
255 zend_object_iterator_funcs zend_interface_iterator_funcs_iterator = {
6186617 - Export struct zend_user_iterator
Marcus Boerger authored
256 zend_user_it_dtor,
6b0f57e Rename hasMore() to valid() as discussed. (Part II)
Marcus Boerger authored
257 zend_user_it_valid,
6186617 - Export struct zend_user_iterator
Marcus Boerger authored
258 zend_user_it_get_current_data,
259 zend_user_it_get_current_key,
260 zend_user_it_move_forward,
e1cd098 - no unneccessary retval initialization
Marcus Boerger authored
261 zend_user_it_rewind,
262 zend_user_it_invalidate_current
8abb3bd Impement userspace iterator interfaces and tests. See tests for details
Marcus Boerger authored
263 };
264
6186617 - Export struct zend_user_iterator
Marcus Boerger authored
265 /* {{{ zend_user_it_get_iterator */
266 static zend_object_iterator *zend_user_it_get_iterator(zend_class_entry *ce, zval *object TSRMLS_DC)
8abb3bd Impement userspace iterator interfaces and tests. See tests for details
Marcus Boerger authored
267 {
268 zend_user_iterator *iterator = emalloc(sizeof(zend_user_iterator));
269
270 object->refcount++;
271 iterator->it.data = (void*)object;
272 iterator->it.funcs = ce->iterator_funcs.funcs;
273 iterator->ce = Z_OBJCE_P(object);
274 iterator->value = NULL;
275 return (zend_object_iterator*)iterator;
276 }
277 /* }}} */
278
6186617 - Export struct zend_user_iterator
Marcus Boerger authored
279 /* {{{ zend_user_it_get_new_iterator */
280 static zend_object_iterator *zend_user_it_get_new_iterator(zend_class_entry *ce, zval *object TSRMLS_DC)
8abb3bd Impement userspace iterator interfaces and tests. See tests for details
Marcus Boerger authored
281 {
6186617 - Export struct zend_user_iterator
Marcus Boerger authored
282 zval *iterator = zend_user_it_new_iterator(ce, object TSRMLS_CC);
c978cc2 Use correct order
Marcus Boerger authored
283 zend_object_iterator *new_iterator;
8abb3bd Impement userspace iterator interfaces and tests. See tests for details
Marcus Boerger authored
284
5206e9c - Allow getIterator() to fail
Marcus Boerger authored
285 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
286
4645502 Stanislav Malyshev quick fix for #29382
smalyshev authored
287 if (!ce || !ce_it || !ce_it->get_iterator || (ce_it->get_iterator == zend_user_it_get_new_iterator && iterator == object)) {
5206e9c - Allow getIterator() to fail
Marcus Boerger authored
288 if (!EG(exception))
289 {
82193ad - Bugfix #26229 (getIterator() segfaults when it returns arrays or scala...
Marcus Boerger authored
290 zend_throw_exception_ex(NULL, 0 TSRMLS_CC, "Objects returned by %s::getIterator() must be traversable or implement interface Iterator", ce->name);
5206e9c - Allow getIterator() to fail
Marcus Boerger authored
291 }
292 if (iterator)
293 {
294 zval_ptr_dtor(&iterator);
295 }
8abb3bd Impement userspace iterator interfaces and tests. See tests for details
Marcus Boerger authored
296 return NULL;
297 }
c978cc2 Use correct order
Marcus Boerger authored
298 new_iterator = ce_it->get_iterator(ce_it, iterator TSRMLS_CC);
299 zval_ptr_dtor(&iterator);
300 return new_iterator;
8abb3bd Impement userspace iterator interfaces and tests. See tests for details
Marcus Boerger authored
301 }
302 /* }}} */
303
304 /* {{{ zend_implement_traversable */
305 static int zend_implement_traversable(zend_class_entry *interface, zend_class_entry *class_type TSRMLS_DC)
306 {
307 /* check that class_type is traversable at c-level or implements at least one of 'aggregate' and 'Iterator' */
01af2c3 Fix warnign
Marcus Boerger authored
308 zend_uint i;
8abb3bd Impement userspace iterator interfaces and tests. See tests for details
Marcus Boerger authored
309
64c7645 #where has my bracket been gone?
Marcus Boerger authored
310 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
311 return SUCCESS;
50ee116 Clearify the different method/class flags (as discussed with Andi).
Marcus Boerger authored
312 }
8abb3bd Impement userspace iterator interfaces and tests. See tests for details
Marcus Boerger authored
313 for (i = 0; i < class_type->num_interfaces; i++) {
314 if (class_type->interfaces[i] == zend_ce_aggregate || class_type->interfaces[i] == zend_ce_iterator) {
315 return SUCCESS;
316 }
317 }
318 zend_error(E_CORE_ERROR, "Class %s must implement interface %s as part of either %s or %s",
319 class_type->name,
320 zend_ce_traversable->name,
321 zend_ce_iterator->name,
322 zend_ce_aggregate->name);
323 return FAILURE;
324 }
325 /* }}} */
326
327 /* {{{ zend_implement_aggregate */
328 static int zend_implement_aggregate(zend_class_entry *interface, zend_class_entry *class_type TSRMLS_DC)
329 {
72c1baa - Allow to convert Traversable into Aggregate
Marcus Boerger authored
330 int i, t = -1;
331
851a02e Give some freedon to c iterators but not in userspace.
Marcus Boerger authored
332 if (class_type->get_iterator) {
333 if (class_type->type == ZEND_INTERNAL_CLASS) {
334 /* inheritance ensures the class has necessary userland methods */
335 return SUCCESS;
6186617 - Export struct zend_user_iterator
Marcus Boerger authored
336 } else if (class_type->get_iterator != zend_user_it_get_new_iterator) {
72c1baa - Allow to convert Traversable into Aggregate
Marcus Boerger authored
337 /* c-level get_iterator cannot be changed (exception being only Traversable is implmented) */
338 if (class_type->num_interfaces) {
339 for (i = 0; i < class_type->num_interfaces; i++) {
340 if (class_type->interfaces[i] == zend_ce_iterator) {
341 return FAILURE;
342 }
343 if (class_type->interfaces[i] == zend_ce_traversable) {
344 t = i;
345 }
346 }
347 }
348 if (t == -1) {
349 return FAILURE;
350 }
851a02e Give some freedon to c iterators but not in userspace.
Marcus Boerger authored
351 }
8abb3bd Impement userspace iterator interfaces and tests. See tests for details
Marcus Boerger authored
352 }
353 class_type->iterator_funcs.zf_new_iterator = NULL;
6186617 - Export struct zend_user_iterator
Marcus Boerger authored
354 class_type->get_iterator = zend_user_it_get_new_iterator;
8abb3bd Impement userspace iterator interfaces and tests. See tests for details
Marcus Boerger authored
355 return SUCCESS;
356 }
357 /* }}} */
358
359 /* {{{ zend_implement_iterator */
360 static int zend_implement_iterator(zend_class_entry *interface, zend_class_entry *class_type TSRMLS_DC)
361 {
6186617 - Export struct zend_user_iterator
Marcus Boerger authored
362 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
363 if (class_type->type == ZEND_INTERNAL_CLASS) {
364 /* inheritance ensures the class has the necessary userland methods */
365 return SUCCESS;
6186617 - Export struct zend_user_iterator
Marcus Boerger authored
366 } 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
367 /* c-level get_iterator cannot be changed */
368 return FAILURE;
369 }
8abb3bd Impement userspace iterator interfaces and tests. See tests for details
Marcus Boerger authored
370 }
6186617 - Export struct zend_user_iterator
Marcus Boerger authored
371 class_type->get_iterator = zend_user_it_get_iterator;
6b0f57e Rename hasMore() to valid() as discussed. (Part II)
Marcus Boerger authored
372 class_type->iterator_funcs.zf_valid = NULL;
8abb3bd Impement userspace iterator interfaces and tests. See tests for details
Marcus Boerger authored
373 class_type->iterator_funcs.zf_current = NULL;
374 class_type->iterator_funcs.zf_key = NULL;
375 class_type->iterator_funcs.zf_next = NULL;
376 class_type->iterator_funcs.zf_rewind = NULL;
377 if (!class_type->iterator_funcs.funcs) {
378 class_type->iterator_funcs.funcs = &zend_interface_iterator_funcs_iterator;
379 }
380 return SUCCESS;
381 }
382 /* }}} */
383
4dba05d Add new interface ArrayAccess to use objects as Arrays
Marcus Boerger authored
384 /* {{{ zend_implement_arrayaccess */
385 static int zend_implement_arrayaccess(zend_class_entry *interface, zend_class_entry *class_type TSRMLS_DC)
386 {
6186617 - Export struct zend_user_iterator
Marcus Boerger authored
387 #if 0
388 /* get ht from ce */
389 if (ht->read_dimension != zend_std_read_dimension
390 || ht->write_dimension != zend_std_write_dimension
391 || ht->has_dimension != zend_std_has_dimension
392 || ht->unset_dimension != zend_std_unset_dimension) {
393 return FAILURE;
394 }
395 #endif
4dba05d Add new interface ArrayAccess to use objects as Arrays
Marcus Boerger authored
396 return SUCCESS;
397 }
398 /* }}}*/
399
757da1e - New Interface Serializeable
Marcus Boerger authored
400 /* {{{ zend_user_serialize */
401 int zend_user_serialize(zval *object, unsigned char **buffer, zend_uint *buf_len, zend_serialize_data *data TSRMLS_DC)
402 {
403 zend_class_entry * ce = Z_OBJCE_P(object);
404 zval *retval;
405 int result;
406
407 zend_call_method_with_0_params(&object, ce, &ce->serialize_func, "serialize", &retval);
408
409
410 if (!retval || EG(exception)) {
411 result = FAILURE;
412 } else {
413 switch(Z_TYPE_P(retval)) {
414 case IS_NULL:
415 /* 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
416 zval_ptr_dtor(&retval);
417 return FAILURE;
757da1e - New Interface Serializeable
Marcus Boerger authored
418 case IS_STRING:
419 *buffer = estrndup(Z_STRVAL_P(retval), Z_STRLEN_P(retval));
420 *buf_len = Z_STRLEN_P(retval);
421 result = SUCCESS;
422 break;
423 default: /* failure */
424 result = FAILURE;
425 break;
426 }
427 zval_ptr_dtor(&retval);
428 }
429
430 if (result == FAILURE) {
431 zend_throw_exception_ex(NULL, 0 TSRMLS_CC, "%s::serialize() must return a string or NULL", ce->name);
432 }
433 return result;
434 }
435 /* }}} */
436
437 /* {{{ zend_user_unserialize */
438 int zend_user_unserialize(zval **object, zend_class_entry *ce, const unsigned char *buf, zend_uint buf_len, zend_unserialize_data *data TSRMLS_DC)
439 {
440 zval * zdata;
441
442 object_init_ex(*object, ce);
443
444 MAKE_STD_ZVAL(zdata);
445 ZVAL_STRINGL(zdata, (char*)buf, buf_len, 1);
446
447 zend_call_method_with_1_params(object, ce, &ce->unserialize_func, "unserialize", NULL, zdata);
448
449 zval_ptr_dtor(&zdata);
450
451 if (EG(exception)) {
452 return FAILURE;
453 } else {
454 return SUCCESS;
455 }
456 }
457 /* }}} */
458
e9dbeab andigutmans - Fix typos
andigutmans authored
459 /* {{{ zend_implement_serializable */
460 static int zend_implement_serializable(zend_class_entry *interface, zend_class_entry *class_type TSRMLS_DC)
757da1e - New Interface Serializeable
Marcus Boerger authored
461 {
462 if ((class_type->serialize && class_type->serialize != zend_user_serialize)
463 || (class_type->unserialize && class_type->unserialize != zend_user_unserialize)
464 ) {
465 return FAILURE;
466 }
467 class_type->serialize = zend_user_serialize;
468 class_type->unserialize = zend_user_unserialize;
469 return SUCCESS;
470 }
471 /* }}}*/
472
8abb3bd Impement userspace iterator interfaces and tests. See tests for details
Marcus Boerger authored
473 /* {{{ function tables */
474 zend_function_entry zend_funcs_aggregate[] = {
475 ZEND_ABSTRACT_ME(iterator, getIterator, NULL)
476 {NULL, NULL, NULL}
477 };
478
479 zend_function_entry zend_funcs_iterator[] = {
480 ZEND_ABSTRACT_ME(iterator, current, NULL)
481 ZEND_ABSTRACT_ME(iterator, next, NULL)
482 ZEND_ABSTRACT_ME(iterator, key, NULL)
b6b7c9e Rename hasMore() to valid() as discussed. (Part I)
Marcus Boerger authored
483 ZEND_ABSTRACT_ME(iterator, valid, NULL)
da6d68d Little iterator improvement: ability to store index in iterator
Marcus Boerger authored
484 ZEND_ABSTRACT_ME(iterator, rewind, NULL)
8abb3bd Impement userspace iterator interfaces and tests. See tests for details
Marcus Boerger authored
485 {NULL, NULL, NULL}
486 };
487
488 zend_function_entry *zend_funcs_traversable = NULL;
4dba05d Add new interface ArrayAccess to use objects as Arrays
Marcus Boerger authored
489
490 static
c6e3947 - More exact signatures (even though complete correct not possible atm)
Marcus Boerger authored
491 ZEND_BEGIN_ARG_INFO_EX(arginfo_arrayaccess_offset, 0, 0, 1)
4dba05d Add new interface ArrayAccess to use objects as Arrays
Marcus Boerger authored
492 ZEND_ARG_INFO(0, offset)
493 ZEND_END_ARG_INFO();
494
495 static
c6e3947 - More exact signatures (even though complete correct not possible atm)
Marcus Boerger authored
496 ZEND_BEGIN_ARG_INFO_EX(arginfo_arrayaccess_offset_get, 0, 0, 1) /* actually this should be return by ref but atm cannot be */
497 ZEND_ARG_INFO(0, offset)
498 ZEND_END_ARG_INFO();
499
500 static
501 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
502 ZEND_ARG_INFO(0, offset)
503 ZEND_ARG_INFO(0, value)
504 ZEND_END_ARG_INFO();
505
506 zend_function_entry zend_funcs_arrayaccess[] = {
507 ZEND_ABSTRACT_ME(arrayaccess, offsetExists, arginfo_arrayaccess_offset)
c6e3947 - More exact signatures (even though complete correct not possible atm)
Marcus Boerger authored
508 ZEND_ABSTRACT_ME(arrayaccess, offsetGet, arginfo_arrayaccess_offset_get)
4dba05d Add new interface ArrayAccess to use objects as Arrays
Marcus Boerger authored
509 ZEND_ABSTRACT_ME(arrayaccess, offsetSet, arginfo_arrayaccess_offset_value)
510 ZEND_ABSTRACT_ME(arrayaccess, offsetUnset, arginfo_arrayaccess_offset)
511 {NULL, NULL, NULL}
512 };
513
757da1e - New Interface Serializeable
Marcus Boerger authored
514 static
e9dbeab andigutmans - Fix typos
andigutmans authored
515 ZEND_BEGIN_ARG_INFO(arginfo_serializable_serialize, 0)
757da1e - New Interface Serializeable
Marcus Boerger authored
516 ZEND_ARG_INFO(0, serialized)
517 ZEND_END_ARG_INFO();
518
e9dbeab andigutmans - Fix typos
andigutmans authored
519 zend_function_entry zend_funcs_serializable[] = {
520 ZEND_ABSTRACT_ME(serializable, serialize, NULL)
521 ZEND_FENTRY(unserialize, NULL, arginfo_serializable_serialize, ZEND_ACC_PUBLIC|ZEND_ACC_ABSTRACT|ZEND_ACC_CTOR)
757da1e - New Interface Serializeable
Marcus Boerger authored
522 {NULL, NULL, NULL}
523 };
8abb3bd Impement userspace iterator interfaces and tests. See tests for details
Marcus Boerger authored
524 /* }}} */
525
526 #define REGISTER_ITERATOR_INTERFACE(class_name, class_name_str) \
527 {\
528 zend_class_entry ce;\
529 INIT_CLASS_ENTRY(ce, # class_name_str, zend_funcs_ ## class_name) \
530 zend_ce_ ## class_name = zend_register_internal_interface(&ce TSRMLS_CC);\
531 zend_ce_ ## class_name->interface_gets_implemented = zend_implement_ ## class_name;\
532 }
533
534 #define REGISTER_ITERATOR_IMPLEMENT(class_name, interface_name) \
535 zend_class_implements(zend_ce_ ## class_name TSRMLS_CC, 1, zend_ce_ ## interface_name)
536
537 /* {{{ zend_register_interfaces */
538 ZEND_API void zend_register_interfaces(TSRMLS_D)
539 {
540 REGISTER_ITERATOR_INTERFACE(traversable, Traversable);
541
542 REGISTER_ITERATOR_INTERFACE(aggregate, IteratorAggregate);
543 REGISTER_ITERATOR_IMPLEMENT(aggregate, traversable);
544
545 REGISTER_ITERATOR_INTERFACE(iterator, Iterator);
546 REGISTER_ITERATOR_IMPLEMENT(iterator, traversable);
4dba05d Add new interface ArrayAccess to use objects as Arrays
Marcus Boerger authored
547
548 REGISTER_ITERATOR_INTERFACE(arrayaccess, ArrayAccess);
757da1e - New Interface Serializeable
Marcus Boerger authored
549
e9dbeab andigutmans - Fix typos
andigutmans authored
550 REGISTER_ITERATOR_INTERFACE(serializable, Serializable)
8abb3bd Impement userspace iterator interfaces and tests. See tests for details
Marcus Boerger authored
551 }
552 /* }}} */
553
554 /*
555 * Local variables:
556 * tab-width: 4
557 * c-basic-offset: 4
558 * indent-tabs-mode: t
559 * End:
560 */
Something went wrong with that request. Please try again.