Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

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