Annotation of embedaddon/php/ext/spl/spl_fixedarray.c, revision 1.1.1.4
1.1 misho 1: /*
2: +----------------------------------------------------------------------+
3: | PHP Version 5 |
4: +----------------------------------------------------------------------+
1.1.1.3 misho 5: | Copyright (c) 1997-2013 The PHP Group |
1.1 misho 6: +----------------------------------------------------------------------+
7: | This source file is subject to version 3.01 of the PHP 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.php.net/license/3_01.txt |
11: | If you did not receive a copy of the PHP license and are unable to |
12: | obtain it through the world-wide-web, please send a note to |
13: | license@php.net so we can mail you a copy immediately. |
14: +----------------------------------------------------------------------+
15: | Author: Antony Dovgal <tony@daylessday.org> |
16: | Etienne Kneuss <colder@php.net> |
17: +----------------------------------------------------------------------+
18: */
19:
1.1.1.2 misho 20: /* $Id$ */
1.1 misho 21:
22: #ifdef HAVE_CONFIG_H
23: #include "config.h"
24: #endif
25:
26: #include "php.h"
27: #include "php_ini.h"
28: #include "ext/standard/info.h"
29: #include "zend_exceptions.h"
30:
31: #include "php_spl.h"
32: #include "spl_functions.h"
33: #include "spl_engine.h"
34: #include "spl_fixedarray.h"
35: #include "spl_exceptions.h"
36: #include "spl_iterators.h"
37:
38: zend_object_handlers spl_handler_SplFixedArray;
39: PHPAPI zend_class_entry *spl_ce_SplFixedArray;
40:
41: #ifdef COMPILE_DL_SPL_FIXEDARRAY
42: ZEND_GET_MODULE(spl_fixedarray)
43: #endif
44:
45: typedef struct _spl_fixedarray { /* {{{ */
46: long size;
47: zval **elements;
48: } spl_fixedarray;
49: /* }}} */
50:
51: typedef struct _spl_fixedarray_object { /* {{{ */
52: zend_object std;
53: spl_fixedarray *array;
54: zval *retval;
55: zend_function *fptr_offset_get;
56: zend_function *fptr_offset_set;
57: zend_function *fptr_offset_has;
58: zend_function *fptr_offset_del;
59: zend_function *fptr_count;
60: int current;
61: int flags;
62: zend_class_entry *ce_get_iterator;
63: } spl_fixedarray_object;
64: /* }}} */
65:
66: typedef struct _spl_fixedarray_it { /* {{{ */
67: zend_user_iterator intern;
68: spl_fixedarray_object *object;
69: } spl_fixedarray_it;
70: /* }}} */
71:
72: #define SPL_FIXEDARRAY_OVERLOADED_REWIND 0x0001
73: #define SPL_FIXEDARRAY_OVERLOADED_VALID 0x0002
74: #define SPL_FIXEDARRAY_OVERLOADED_KEY 0x0004
75: #define SPL_FIXEDARRAY_OVERLOADED_CURRENT 0x0008
76: #define SPL_FIXEDARRAY_OVERLOADED_NEXT 0x0010
77:
78: static void spl_fixedarray_init(spl_fixedarray *array, long size TSRMLS_DC) /* {{{ */
79: {
80: if (size > 0) {
81: array->size = 0; /* reset size in case ecalloc() fails */
82: array->elements = ecalloc(size, sizeof(zval *));
83: array->size = size;
84: } else {
85: array->elements = NULL;
86: array->size = 0;
87: }
88: }
89: /* }}} */
90:
91: static void spl_fixedarray_resize(spl_fixedarray *array, long size TSRMLS_DC) /* {{{ */
92: {
93: if (size == array->size) {
94: /* nothing to do */
95: return;
96: }
97:
98: /* first initialization */
99: if (array->size == 0) {
100: spl_fixedarray_init(array, size TSRMLS_CC);
101: return;
102: }
103:
104: /* clearing the array */
105: if (size == 0) {
106: long i;
107:
108: for (i = 0; i < array->size; i++) {
109: if (array->elements[i]) {
110: zval_ptr_dtor(&(array->elements[i]));
111: }
112: }
113:
114: if (array->elements) {
115: efree(array->elements);
116: array->elements = NULL;
117: }
118: } else if (size > array->size) {
119: array->elements = erealloc(array->elements, sizeof(zval *) * size);
120: memset(array->elements + array->size, '\0', sizeof(zval *) * (size - array->size));
121: } else { /* size < array->size */
122: long i;
123:
124: for (i = size; i < array->size; i++) {
125: if (array->elements[i]) {
126: zval_ptr_dtor(&(array->elements[i]));
127: }
128: }
129: array->elements = erealloc(array->elements, sizeof(zval *) * size);
130: }
131:
132: array->size = size;
133: }
134: /* }}} */
135:
136: static void spl_fixedarray_copy(spl_fixedarray *to, spl_fixedarray *from TSRMLS_DC) /* {{{ */
137: {
138: int i;
139: for (i = 0; i < from->size; i++) {
140: if (from->elements[i]) {
141: Z_ADDREF_P(from->elements[i]);
142: to->elements[i] = from->elements[i];
143: } else {
144: to->elements[i] = NULL;
145: }
146: }
147: }
148: /* }}} */
149:
1.1.1.3 misho 150: static HashTable* spl_fixedarray_object_get_gc(zval *obj, zval ***table, int *n TSRMLS_DC) /* {{{{ */
151: {
152: spl_fixedarray_object *intern = (spl_fixedarray_object*)zend_object_store_get_object(obj TSRMLS_CC);
153: HashTable *ht = zend_std_get_properties(obj TSRMLS_CC);
154:
155: if (intern->array) {
156: *table = intern->array->elements;
157: *n = intern->array->size;
158: } else {
159: *table = NULL;
160: *n = 0;
161: }
162:
163: return ht;
164: }
165: /* }}}} */
166:
1.1 misho 167: static HashTable* spl_fixedarray_object_get_properties(zval *obj TSRMLS_DC) /* {{{{ */
168: {
169: spl_fixedarray_object *intern = (spl_fixedarray_object*)zend_object_store_get_object(obj TSRMLS_CC);
1.1.1.2 misho 170: HashTable *ht = zend_std_get_properties(obj TSRMLS_CC);
1.1 misho 171: int i = 0;
172:
1.1.1.3 misho 173: if (intern->array) {
1.1.1.2 misho 174: int j = zend_hash_num_elements(ht);
1.1 misho 175:
176: for (i = 0; i < intern->array->size; i++) {
177: if (intern->array->elements[i]) {
1.1.1.2 misho 178: zend_hash_index_update(ht, i, (void *)&intern->array->elements[i], sizeof(zval *), NULL);
1.1 misho 179: Z_ADDREF_P(intern->array->elements[i]);
180: } else {
1.1.1.2 misho 181: zend_hash_index_update(ht, i, (void *)&EG(uninitialized_zval_ptr), sizeof(zval *), NULL);
1.1 misho 182: Z_ADDREF_P(EG(uninitialized_zval_ptr));
183: }
184: }
185: if (j > intern->array->size) {
186: for (i = intern->array->size; i < j; ++i) {
1.1.1.2 misho 187: zend_hash_index_del(ht, i);
1.1 misho 188: }
189: }
190: }
191:
1.1.1.2 misho 192: return ht;
1.1 misho 193: }
194: /* }}}} */
195:
196: static void spl_fixedarray_object_free_storage(void *object TSRMLS_DC) /* {{{ */
197: {
198: spl_fixedarray_object *intern = (spl_fixedarray_object *)object;
199: long i;
200:
201: if (intern->array) {
202: for (i = 0; i < intern->array->size; i++) {
203: if (intern->array->elements[i]) {
204: zval_ptr_dtor(&(intern->array->elements[i]));
205: }
206: }
207:
208: if (intern->array->size > 0 && intern->array->elements) {
209: efree(intern->array->elements);
210: }
211: efree(intern->array);
212: }
213:
214: zend_object_std_dtor(&intern->std TSRMLS_CC);
215: zval_ptr_dtor(&intern->retval);
216:
217: efree(object);
218: }
219: /* }}} */
220:
221: zend_object_iterator *spl_fixedarray_get_iterator(zend_class_entry *ce, zval *object, int by_ref TSRMLS_DC);
222:
223: static zend_object_value spl_fixedarray_object_new_ex(zend_class_entry *class_type, spl_fixedarray_object **obj, zval *orig, int clone_orig TSRMLS_DC) /* {{{ */
224: {
225: zend_object_value retval;
226: spl_fixedarray_object *intern;
227: zend_class_entry *parent = class_type;
228: int inherited = 0;
229:
230: intern = ecalloc(1, sizeof(spl_fixedarray_object));
231: *obj = intern;
232: ALLOC_INIT_ZVAL(intern->retval);
233:
234: zend_object_std_init(&intern->std, class_type TSRMLS_CC);
1.1.1.2 misho 235: object_properties_init(&intern->std, class_type);
1.1 misho 236:
237: intern->current = 0;
238: intern->flags = 0;
239:
240: if (orig && clone_orig) {
241: spl_fixedarray_object *other = (spl_fixedarray_object*)zend_object_store_get_object(orig TSRMLS_CC);
242: intern->ce_get_iterator = other->ce_get_iterator;
1.1.1.3 misho 243: if (!other->array) {
244: /* leave a empty object, will be dtor later by CLONE handler */
245: zend_throw_exception(spl_ce_RuntimeException, "The instance wasn't initialized properly", 0 TSRMLS_CC);
246: } else {
247: intern->array = emalloc(sizeof(spl_fixedarray));
248: spl_fixedarray_init(intern->array, other->array->size TSRMLS_CC);
249: spl_fixedarray_copy(intern->array, other->array TSRMLS_CC);
250: }
1.1 misho 251: }
252:
253: while (parent) {
254: if (parent == spl_ce_SplFixedArray) {
255: retval.handlers = &spl_handler_SplFixedArray;
256: class_type->get_iterator = spl_fixedarray_get_iterator;
257: break;
258: }
259:
260: parent = parent->parent;
261: inherited = 1;
262: }
263:
264: retval.handle = zend_objects_store_put(intern, (zend_objects_store_dtor_t)zend_objects_destroy_object, spl_fixedarray_object_free_storage, NULL TSRMLS_CC);
265:
266: if (!parent) { /* this must never happen */
267: php_error_docref(NULL TSRMLS_CC, E_COMPILE_ERROR, "Internal compiler error, Class is not child of SplFixedArray");
268: }
269: if (!class_type->iterator_funcs.zf_current) {
270: zend_hash_find(&class_type->function_table, "rewind", sizeof("rewind"), (void **) &class_type->iterator_funcs.zf_rewind);
271: zend_hash_find(&class_type->function_table, "valid", sizeof("valid"), (void **) &class_type->iterator_funcs.zf_valid);
272: zend_hash_find(&class_type->function_table, "key", sizeof("key"), (void **) &class_type->iterator_funcs.zf_key);
273: zend_hash_find(&class_type->function_table, "current", sizeof("current"), (void **) &class_type->iterator_funcs.zf_current);
274: zend_hash_find(&class_type->function_table, "next", sizeof("next"), (void **) &class_type->iterator_funcs.zf_next);
275: }
276: if (inherited) {
277: if (class_type->iterator_funcs.zf_rewind->common.scope != parent) {
278: intern->flags |= SPL_FIXEDARRAY_OVERLOADED_REWIND;
279: }
280: if (class_type->iterator_funcs.zf_valid->common.scope != parent) {
281: intern->flags |= SPL_FIXEDARRAY_OVERLOADED_VALID;
282: }
283: if (class_type->iterator_funcs.zf_key->common.scope != parent) {
284: intern->flags |= SPL_FIXEDARRAY_OVERLOADED_KEY;
285: }
286: if (class_type->iterator_funcs.zf_current->common.scope != parent) {
287: intern->flags |= SPL_FIXEDARRAY_OVERLOADED_CURRENT;
288: }
289: if (class_type->iterator_funcs.zf_next->common.scope != parent) {
290: intern->flags |= SPL_FIXEDARRAY_OVERLOADED_NEXT;
291: }
292:
293: zend_hash_find(&class_type->function_table, "offsetget", sizeof("offsetget"), (void **) &intern->fptr_offset_get);
294: if (intern->fptr_offset_get->common.scope == parent) {
295: intern->fptr_offset_get = NULL;
296: }
297: zend_hash_find(&class_type->function_table, "offsetset", sizeof("offsetset"), (void **) &intern->fptr_offset_set);
298: if (intern->fptr_offset_set->common.scope == parent) {
299: intern->fptr_offset_set = NULL;
300: }
301: zend_hash_find(&class_type->function_table, "offsetexists", sizeof("offsetexists"), (void **) &intern->fptr_offset_has);
302: if (intern->fptr_offset_has->common.scope == parent) {
303: intern->fptr_offset_has = NULL;
304: }
305: zend_hash_find(&class_type->function_table, "offsetunset", sizeof("offsetunset"), (void **) &intern->fptr_offset_del);
306: if (intern->fptr_offset_del->common.scope == parent) {
307: intern->fptr_offset_del = NULL;
308: }
309: zend_hash_find(&class_type->function_table, "count", sizeof("count"), (void **) &intern->fptr_count);
310: if (intern->fptr_count->common.scope == parent) {
311: intern->fptr_count = NULL;
312: }
313: }
314:
315: return retval;
316: }
317: /* }}} */
318:
319: static zend_object_value spl_fixedarray_new(zend_class_entry *class_type TSRMLS_DC) /* {{{ */
320: {
321: spl_fixedarray_object *tmp;
322: return spl_fixedarray_object_new_ex(class_type, &tmp, NULL, 0 TSRMLS_CC);
323: }
324: /* }}} */
325:
326: static zend_object_value spl_fixedarray_object_clone(zval *zobject TSRMLS_DC) /* {{{ */
327: {
328: zend_object_value new_obj_val;
329: zend_object *old_object;
330: zend_object *new_object;
331: zend_object_handle handle = Z_OBJ_HANDLE_P(zobject);
332: spl_fixedarray_object *intern;
333:
334: old_object = zend_objects_get_address(zobject TSRMLS_CC);
335: new_obj_val = spl_fixedarray_object_new_ex(old_object->ce, &intern, zobject, 1 TSRMLS_CC);
336: new_object = &intern->std;
337:
338: zend_objects_clone_members(new_object, new_obj_val, old_object, handle TSRMLS_CC);
339:
340: return new_obj_val;
341: }
342: /* }}} */
343:
344: static inline zval **spl_fixedarray_object_read_dimension_helper(spl_fixedarray_object *intern, zval *offset TSRMLS_DC) /* {{{ */
345: {
346: long index;
347:
348: /* we have to return NULL on error here to avoid memleak because of
349: * ZE duplicating uninitialized_zval_ptr */
350: if (!offset) {
351: zend_throw_exception(spl_ce_RuntimeException, "Index invalid or out of range", 0 TSRMLS_CC);
352: return NULL;
353: }
354:
355: if (Z_TYPE_P(offset) != IS_LONG) {
356: index = spl_offset_convert_to_long(offset TSRMLS_CC);
357: } else {
358: index = Z_LVAL_P(offset);
359: }
360:
361: if (index < 0 || intern->array == NULL || index >= intern->array->size) {
362: zend_throw_exception(spl_ce_RuntimeException, "Index invalid or out of range", 0 TSRMLS_CC);
363: return NULL;
364: } else if(!intern->array->elements[index]) {
365: return NULL;
366: } else {
367: return &intern->array->elements[index];
368: }
369: }
370: /* }}} */
371:
372: static zval *spl_fixedarray_object_read_dimension(zval *object, zval *offset, int type TSRMLS_DC) /* {{{ */
373: {
374: spl_fixedarray_object *intern;
375: zval **retval;
376:
377: intern = (spl_fixedarray_object *)zend_object_store_get_object(object TSRMLS_CC);
378:
379: if (intern->fptr_offset_get) {
380: zval *rv;
1.1.1.3 misho 381: if (!offset) {
382: ALLOC_INIT_ZVAL(offset);
383: } else {
384: SEPARATE_ARG_IF_REF(offset);
385: }
1.1 misho 386: zend_call_method_with_1_params(&object, intern->std.ce, &intern->fptr_offset_get, "offsetGet", &rv, offset);
387: zval_ptr_dtor(&offset);
388: if (rv) {
389: zval_ptr_dtor(&intern->retval);
390: MAKE_STD_ZVAL(intern->retval);
391: ZVAL_ZVAL(intern->retval, rv, 1, 1);
392: return intern->retval;
393: }
394: return EG(uninitialized_zval_ptr);
395: }
396:
397: retval = spl_fixedarray_object_read_dimension_helper(intern, offset TSRMLS_CC);
398: if (retval) {
399: return *retval;
400: }
401: return NULL;
402: }
403: /* }}} */
404:
405: static inline void spl_fixedarray_object_write_dimension_helper(spl_fixedarray_object *intern, zval *offset, zval *value TSRMLS_DC) /* {{{ */
406: {
407: long index;
408:
409: if (!offset) {
410: /* '$array[] = value' syntax is not supported */
411: zend_throw_exception(spl_ce_RuntimeException, "Index invalid or out of range", 0 TSRMLS_CC);
412: return;
413: }
414:
415: if (Z_TYPE_P(offset) != IS_LONG) {
416: index = spl_offset_convert_to_long(offset TSRMLS_CC);
417: } else {
418: index = Z_LVAL_P(offset);
419: }
420:
421: if (index < 0 || intern->array == NULL || index >= intern->array->size) {
422: zend_throw_exception(spl_ce_RuntimeException, "Index invalid or out of range", 0 TSRMLS_CC);
423: return;
424: } else {
425: if (intern->array->elements[index]) {
426: zval_ptr_dtor(&(intern->array->elements[index]));
427: }
428: SEPARATE_ARG_IF_REF(value);
429: intern->array->elements[index] = value;
430: }
431: }
432: /* }}} */
433:
434: static void spl_fixedarray_object_write_dimension(zval *object, zval *offset, zval *value TSRMLS_DC) /* {{{ */
435: {
436: spl_fixedarray_object *intern;
437:
438: intern = (spl_fixedarray_object *)zend_object_store_get_object(object TSRMLS_CC);
439:
440: if (intern->fptr_offset_set) {
441: if (!offset) {
442: ALLOC_INIT_ZVAL(offset);
443: } else {
444: SEPARATE_ARG_IF_REF(offset);
445: }
446: SEPARATE_ARG_IF_REF(value);
447: zend_call_method_with_2_params(&object, intern->std.ce, &intern->fptr_offset_set, "offsetSet", NULL, offset, value);
448: zval_ptr_dtor(&value);
449: zval_ptr_dtor(&offset);
450: return;
451: }
452:
453: spl_fixedarray_object_write_dimension_helper(intern, offset, value TSRMLS_CC);
454: }
455: /* }}} */
456:
457: static inline void spl_fixedarray_object_unset_dimension_helper(spl_fixedarray_object *intern, zval *offset TSRMLS_DC) /* {{{ */
458: {
459: long index;
460:
461: if (Z_TYPE_P(offset) != IS_LONG) {
462: index = spl_offset_convert_to_long(offset TSRMLS_CC);
463: } else {
464: index = Z_LVAL_P(offset);
465: }
466:
467: if (index < 0 || intern->array == NULL || index >= intern->array->size) {
468: zend_throw_exception(spl_ce_RuntimeException, "Index invalid or out of range", 0 TSRMLS_CC);
469: return;
470: } else {
471: if (intern->array->elements[index]) {
472: zval_ptr_dtor(&(intern->array->elements[index]));
473: }
474: intern->array->elements[index] = NULL;
475: }
476: }
477: /* }}} */
478:
479: static void spl_fixedarray_object_unset_dimension(zval *object, zval *offset TSRMLS_DC) /* {{{ */
480: {
481: spl_fixedarray_object *intern;
482:
483: intern = (spl_fixedarray_object *)zend_object_store_get_object(object TSRMLS_CC);
484:
485: if (intern->fptr_offset_del) {
486: SEPARATE_ARG_IF_REF(offset);
487: zend_call_method_with_1_params(&object, intern->std.ce, &intern->fptr_offset_del, "offsetUnset", NULL, offset);
488: zval_ptr_dtor(&offset);
489: return;
490: }
491:
492: spl_fixedarray_object_unset_dimension_helper(intern, offset TSRMLS_CC);
493:
494: }
495: /* }}} */
496:
497: static inline int spl_fixedarray_object_has_dimension_helper(spl_fixedarray_object *intern, zval *offset, int check_empty TSRMLS_DC) /* {{{ */
498: {
499: long index;
500: int retval;
501:
502: if (Z_TYPE_P(offset) != IS_LONG) {
503: index = spl_offset_convert_to_long(offset TSRMLS_CC);
504: } else {
505: index = Z_LVAL_P(offset);
506: }
507:
508: if (index < 0 || intern->array == NULL || index >= intern->array->size) {
509: retval = 0;
510: } else {
511: if (!intern->array->elements[index]) {
512: retval = 0;
513: } else if (check_empty) {
514: if (zend_is_true(intern->array->elements[index])) {
515: retval = 1;
516: } else {
517: retval = 0;
518: }
519: } else { /* != NULL and !check_empty */
520: retval = 1;
521: }
522: }
523:
524: return retval;
525: }
526: /* }}} */
527:
528: static int spl_fixedarray_object_has_dimension(zval *object, zval *offset, int check_empty TSRMLS_DC) /* {{{ */
529: {
530: spl_fixedarray_object *intern;
531:
532: intern = (spl_fixedarray_object *)zend_object_store_get_object(object TSRMLS_CC);
533:
534: if (intern->fptr_offset_get) {
535: zval *rv;
536: SEPARATE_ARG_IF_REF(offset);
537: zend_call_method_with_1_params(&object, intern->std.ce, &intern->fptr_offset_has, "offsetExists", &rv, offset);
538: zval_ptr_dtor(&offset);
539: if (rv) {
540: zval_ptr_dtor(&intern->retval);
541: MAKE_STD_ZVAL(intern->retval);
542: ZVAL_ZVAL(intern->retval, rv, 1, 1);
543: return zend_is_true(intern->retval);
544: }
545: return 0;
546: }
547:
548: return spl_fixedarray_object_has_dimension_helper(intern, offset, check_empty TSRMLS_CC);
549: }
550: /* }}} */
551:
552: static int spl_fixedarray_object_count_elements(zval *object, long *count TSRMLS_DC) /* {{{ */
553: {
554: spl_fixedarray_object *intern;
555:
556: intern = (spl_fixedarray_object *)zend_object_store_get_object(object TSRMLS_CC);
557: if (intern->fptr_count) {
558: zval *rv;
559: zend_call_method_with_0_params(&object, intern->std.ce, &intern->fptr_count, "count", &rv);
560: if (rv) {
561: zval_ptr_dtor(&intern->retval);
562: MAKE_STD_ZVAL(intern->retval);
563: ZVAL_ZVAL(intern->retval, rv, 1, 1);
564: convert_to_long(intern->retval);
565: *count = (long) Z_LVAL_P(intern->retval);
566: return SUCCESS;
567: }
568: } else if (intern->array) {
569: *count = intern->array->size;
570: return SUCCESS;
571: }
572:
573: *count = 0;
574: return SUCCESS;
575: }
576: /* }}} */
577:
578: /* {{{ proto void SplFixedArray::__construct([int size])
579: */
580: SPL_METHOD(SplFixedArray, __construct)
581: {
582: zval *object = getThis();
583: spl_fixedarray_object *intern;
584: long size = 0;
585:
586: if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|l", &size)) {
587: return;
588: }
589:
590: if (size < 0) {
591: zend_throw_exception_ex(spl_ce_InvalidArgumentException, 0 TSRMLS_CC, "array size cannot be less than zero");
592: return;
593: }
594:
595: intern = (spl_fixedarray_object *)zend_object_store_get_object(object TSRMLS_CC);
596:
597: if (intern->array) {
598: /* called __construct() twice, bail out */
599: return;
600: }
601:
602: intern->array = emalloc(sizeof(spl_fixedarray));
603: spl_fixedarray_init(intern->array, size TSRMLS_CC);
604: }
605: /* }}} */
606:
1.1.1.4 ! misho 607: /* {{{ proto void SplFixedArray::__wakeup()
! 608: */
! 609: SPL_METHOD(SplFixedArray, __wakeup)
! 610: {
! 611: spl_fixedarray_object *intern = (spl_fixedarray_object *) zend_object_store_get_object(getThis() TSRMLS_CC);
! 612: HashPosition ptr;
! 613: HashTable *intern_ht = zend_std_get_properties(getThis() TSRMLS_CC);
! 614: zval **data;
! 615:
! 616: if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "")) {
! 617: return;
! 618: }
! 619:
! 620: if (!intern->array) {
! 621: int index = 0;
! 622: int size = zend_hash_num_elements(intern_ht);
! 623:
! 624: intern->array = emalloc(sizeof(spl_fixedarray));
! 625: spl_fixedarray_init(intern->array, size TSRMLS_CC);
! 626:
! 627: for (zend_hash_internal_pointer_reset_ex(intern_ht, &ptr); zend_hash_get_current_data_ex(intern_ht, (void **) &data, &ptr) == SUCCESS; zend_hash_move_forward_ex(intern_ht, &ptr)) {
! 628: Z_ADDREF_PP(data);
! 629: intern->array->elements[index++] = *data;
! 630: }
! 631:
! 632: /* Remove the unserialised properties, since we now have the elements
! 633: * within the spl_fixedarray_object structure. */
! 634: zend_hash_clean(intern_ht);
! 635: }
! 636: }
! 637: /* }}} */
! 638:
1.1 misho 639: /* {{{ proto int SplFixedArray::count(void)
640: */
641: SPL_METHOD(SplFixedArray, count)
642: {
643: zval *object = getThis();
644: spl_fixedarray_object *intern;
645:
646: if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "")) {
647: return;
648: }
649:
650: intern = (spl_fixedarray_object *)zend_object_store_get_object(object TSRMLS_CC);
651: if (intern->array) {
652: RETURN_LONG(intern->array->size);
653: }
654: RETURN_LONG(0);
655: }
656: /* }}} */
657:
658: /* {{{ proto object SplFixedArray::toArray()
659: */
660: SPL_METHOD(SplFixedArray, toArray)
661: {
1.1.1.3 misho 662: spl_fixedarray_object *intern;
1.1 misho 663:
664: if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "")) {
665: return;
666: }
667:
1.1.1.3 misho 668: intern = (spl_fixedarray_object *)zend_object_store_get_object(getThis() TSRMLS_CC);
1.1 misho 669:
1.1.1.3 misho 670: array_init(return_value);
671: if (intern->array) {
672: int i = 0;
673: for (; i < intern->array->size; i++) {
674: if (intern->array->elements[i]) {
675: zend_hash_index_update(Z_ARRVAL_P(return_value), i, (void *)&intern->array->elements[i], sizeof(zval *), NULL);
676: Z_ADDREF_P(intern->array->elements[i]);
677: } else {
678: zend_hash_index_update(Z_ARRVAL_P(return_value), i, (void *)&EG(uninitialized_zval_ptr), sizeof(zval *), NULL);
679: Z_ADDREF_P(EG(uninitialized_zval_ptr));
680: }
681: }
682: }
1.1 misho 683: }
684: /* }}} */
685:
686: /* {{{ proto object SplFixedArray::fromArray(array data[, bool save_indexes])
687: */
688: SPL_METHOD(SplFixedArray, fromArray)
689: {
690: zval *data;
691: spl_fixedarray *array;
692: spl_fixedarray_object *intern;
693: int num;
694: zend_bool save_indexes = 1;
695:
696: if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a|b", &data, &save_indexes)) {
697: return;
698: }
699:
700: array = ecalloc(1, sizeof(*array));
701: num = zend_hash_num_elements(Z_ARRVAL_P(data));
702:
703: if (num > 0 && save_indexes) {
704: zval **element, *value;
705: char *str_index;
706: ulong num_index, max_index = 0;
707: long tmp;
708:
709: for (zend_hash_internal_pointer_reset(Z_ARRVAL_P(data));
710: zend_hash_get_current_data(Z_ARRVAL_P(data), (void **) &element) == SUCCESS;
711: zend_hash_move_forward(Z_ARRVAL_P(data))
712: ) {
713: if (zend_hash_get_current_key(Z_ARRVAL_P(data), &str_index, &num_index, 0) != HASH_KEY_IS_LONG || (long)num_index < 0) {
714: efree(array);
715: zend_throw_exception_ex(spl_ce_InvalidArgumentException, 0 TSRMLS_CC, "array must contain only positive integer keys");
716: return;
717: }
718:
719: if (num_index > max_index) {
720: max_index = num_index;
721: }
722: }
723:
724: tmp = max_index + 1;
725: if (tmp <= 0) {
726: efree(array);
727: zend_throw_exception_ex(spl_ce_InvalidArgumentException, 0 TSRMLS_CC, "integer overflow detected");
728: return;
729: }
730: spl_fixedarray_init(array, tmp TSRMLS_CC);
731:
732: for (zend_hash_internal_pointer_reset(Z_ARRVAL_P(data));
733: zend_hash_get_current_data(Z_ARRVAL_P(data), (void **) &element) == SUCCESS;
734: zend_hash_move_forward(Z_ARRVAL_P(data))
735: ) {
736:
737: zend_hash_get_current_key(Z_ARRVAL_P(data), &str_index, &num_index, 0);
738: value = *element;
739:
740: SEPARATE_ARG_IF_REF(value);
741: array->elements[num_index] = value;
742: }
743:
744: } else if (num > 0 && !save_indexes) {
745: zval **element, *value;
746: long i = 0;
747:
748: spl_fixedarray_init(array, num TSRMLS_CC);
749:
750: for (zend_hash_internal_pointer_reset(Z_ARRVAL_P(data));
751: zend_hash_get_current_data(Z_ARRVAL_P(data), (void **) &element) == SUCCESS;
752: zend_hash_move_forward(Z_ARRVAL_P(data))
753: ) {
754:
755: value = *element;
756:
757: SEPARATE_ARG_IF_REF(value);
758: array->elements[i] = value;
759: i++;
760: }
761: } else {
762: spl_fixedarray_init(array, 0 TSRMLS_CC);
763: }
764:
765: object_init_ex(return_value, spl_ce_SplFixedArray);
766: Z_TYPE_P(return_value) = IS_OBJECT;
767:
768: intern = (spl_fixedarray_object *)zend_object_store_get_object(return_value TSRMLS_CC);
769: intern->array = array;
770: }
771: /* }}} */
772:
773: /* {{{ proto int SplFixedArray::getSize(void)
774: */
775: SPL_METHOD(SplFixedArray, getSize)
776: {
777: zval *object = getThis();
778: spl_fixedarray_object *intern;
779:
780: if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "")) {
781: return;
782: }
783:
784: intern = (spl_fixedarray_object *)zend_object_store_get_object(object TSRMLS_CC);
785: if (intern->array) {
786: RETURN_LONG(intern->array->size);
787: }
788: RETURN_LONG(0);
789: }
790: /* }}} */
791:
792: /* {{{ proto bool SplFixedArray::setSize(int size)
793: */
794: SPL_METHOD(SplFixedArray, setSize)
795: {
796: zval *object = getThis();
797: spl_fixedarray_object *intern;
798: long size;
799:
800: if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &size)) {
801: return;
802: }
803:
804: if (size < 0) {
805: zend_throw_exception_ex(spl_ce_InvalidArgumentException, 0 TSRMLS_CC, "array size cannot be less than zero");
806: return;
807: }
808:
809: intern = (spl_fixedarray_object *)zend_object_store_get_object(object TSRMLS_CC);
810: if (!intern->array) {
811: intern->array = ecalloc(1, sizeof(spl_fixedarray));
812: }
813:
814: spl_fixedarray_resize(intern->array, size TSRMLS_CC);
815: RETURN_TRUE;
816: }
817: /* }}} */
818:
819: /* {{{ proto bool SplFixedArray::offsetExists(mixed $index) U
820: Returns whether the requested $index exists. */
821: SPL_METHOD(SplFixedArray, offsetExists)
822: {
823: zval *zindex;
824: spl_fixedarray_object *intern;
825:
826: if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &zindex) == FAILURE) {
827: return;
828: }
829:
830: intern = (spl_fixedarray_object *)zend_object_store_get_object(getThis() TSRMLS_CC);
831:
832: RETURN_BOOL(spl_fixedarray_object_has_dimension_helper(intern, zindex, 0 TSRMLS_CC));
833: } /* }}} */
834:
835: /* {{{ proto mixed SplFixedArray::offsetGet(mixed $index) U
836: Returns the value at the specified $index. */
837: SPL_METHOD(SplFixedArray, offsetGet)
838: {
839: zval *zindex, **value_pp;
840: spl_fixedarray_object *intern;
841:
842: if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &zindex) == FAILURE) {
843: return;
844: }
845:
846: intern = (spl_fixedarray_object *)zend_object_store_get_object(getThis() TSRMLS_CC);
847: value_pp = spl_fixedarray_object_read_dimension_helper(intern, zindex TSRMLS_CC);
848:
849: if (value_pp) {
850: RETURN_ZVAL(*value_pp, 1, 0);
851: }
852: RETURN_NULL();
853: } /* }}} */
854:
855: /* {{{ proto void SplFixedArray::offsetSet(mixed $index, mixed $newval) U
856: Sets the value at the specified $index to $newval. */
857: SPL_METHOD(SplFixedArray, offsetSet)
858: {
859: zval *zindex, *value;
860: spl_fixedarray_object *intern;
861:
862: if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "zz", &zindex, &value) == FAILURE) {
863: return;
864: }
865:
866: intern = (spl_fixedarray_object *)zend_object_store_get_object(getThis() TSRMLS_CC);
867: spl_fixedarray_object_write_dimension_helper(intern, zindex, value TSRMLS_CC);
868:
869: } /* }}} */
870:
871: /* {{{ proto void SplFixedArray::offsetUnset(mixed $index) U
872: Unsets the value at the specified $index. */
873: SPL_METHOD(SplFixedArray, offsetUnset)
874: {
875: zval *zindex;
876: spl_fixedarray_object *intern;
877:
878: if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &zindex) == FAILURE) {
879: return;
880: }
881:
882: intern = (spl_fixedarray_object *)zend_object_store_get_object(getThis() TSRMLS_CC);
883: spl_fixedarray_object_unset_dimension_helper(intern, zindex TSRMLS_CC);
884:
885: } /* }}} */
886:
887: static void spl_fixedarray_it_dtor(zend_object_iterator *iter TSRMLS_DC) /* {{{ */
888: {
889: spl_fixedarray_it *iterator = (spl_fixedarray_it *)iter;
890:
891: zend_user_it_invalidate_current(iter TSRMLS_CC);
892: zval_ptr_dtor((zval**)&iterator->intern.it.data);
893:
894: efree(iterator);
895: }
896: /* }}} */
897:
898: static void spl_fixedarray_it_rewind(zend_object_iterator *iter TSRMLS_DC) /* {{{ */
899: {
900: spl_fixedarray_it *iterator = (spl_fixedarray_it *)iter;
901: spl_fixedarray_object *intern = iterator->object;
902:
903: if (intern->flags & SPL_FIXEDARRAY_OVERLOADED_REWIND) {
904: zend_user_it_rewind(iter TSRMLS_CC);
905: } else {
906: iterator->object->current = 0;
907: }
908: }
909: /* }}} */
910:
911: static int spl_fixedarray_it_valid(zend_object_iterator *iter TSRMLS_DC) /* {{{ */
912: {
913: spl_fixedarray_it *iterator = (spl_fixedarray_it *)iter;
914: spl_fixedarray_object *intern = iterator->object;
915:
916: if (intern->flags & SPL_FIXEDARRAY_OVERLOADED_VALID) {
917: return zend_user_it_valid(iter TSRMLS_CC);
918: }
919:
920: if (iterator->object->current >= 0 && iterator->object->array && iterator->object->current < iterator->object->array->size) {
921: return SUCCESS;
922: }
923:
924: return FAILURE;
925: }
926: /* }}} */
927:
928: static void spl_fixedarray_it_get_current_data(zend_object_iterator *iter, zval ***data TSRMLS_DC) /* {{{ */
929: {
930: zval *zindex;
931: spl_fixedarray_it *iterator = (spl_fixedarray_it *)iter;
932: spl_fixedarray_object *intern = iterator->object;
933:
934: if (intern->flags & SPL_FIXEDARRAY_OVERLOADED_CURRENT) {
935: zend_user_it_get_current_data(iter, data TSRMLS_CC);
936: } else {
937: ALLOC_INIT_ZVAL(zindex);
938: ZVAL_LONG(zindex, iterator->object->current);
939:
940: *data = spl_fixedarray_object_read_dimension_helper(intern, zindex TSRMLS_CC);
941:
942: if (*data == NULL) {
943: *data = &EG(uninitialized_zval_ptr);
944: }
945:
946: zval_ptr_dtor(&zindex);
947: }
948: }
949: /* }}} */
950:
951: static int spl_fixedarray_it_get_current_key(zend_object_iterator *iter, char **str_key, uint *str_key_len, ulong *int_key TSRMLS_DC) /* {{{ */
952: {
953: spl_fixedarray_it *iterator = (spl_fixedarray_it *)iter;
954: spl_fixedarray_object *intern = iterator->object;
955:
956: if (intern->flags & SPL_FIXEDARRAY_OVERLOADED_KEY) {
957: return zend_user_it_get_current_key(iter, str_key, str_key_len, int_key TSRMLS_CC);
958: } else {
959: *int_key = (ulong) iterator->object->current;
960: return HASH_KEY_IS_LONG;
961: }
962:
963: }
964: /* }}} */
965:
966: static void spl_fixedarray_it_move_forward(zend_object_iterator *iter TSRMLS_DC) /* {{{ */
967: {
968: spl_fixedarray_it *iterator = (spl_fixedarray_it *)iter;
969: spl_fixedarray_object *intern = iterator->object;
970:
971: if (intern->flags & SPL_FIXEDARRAY_OVERLOADED_NEXT) {
972: zend_user_it_move_forward(iter TSRMLS_CC);
973: } else {
974: zend_user_it_invalidate_current(iter TSRMLS_CC);
975: iterator->object->current++;
976: }
977: }
978: /* }}} */
979:
980: /* {{{ proto int SplFixedArray::key() U
981: Return current array key */
982: SPL_METHOD(SplFixedArray, key)
983: {
984: spl_fixedarray_object *intern = (spl_fixedarray_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
985:
986: if (zend_parse_parameters_none() == FAILURE) {
987: return;
988: }
989:
990: RETURN_LONG(intern->current);
991: }
992: /* }}} */
993:
994: /* {{{ proto void SplFixedArray::next() U
995: Move to next entry */
996: SPL_METHOD(SplFixedArray, next)
997: {
998: spl_fixedarray_object *intern = (spl_fixedarray_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
999:
1000: if (zend_parse_parameters_none() == FAILURE) {
1001: return;
1002: }
1003:
1004: intern->current++;
1005: }
1006: /* }}} */
1007:
1008: /* {{{ proto bool SplFixedArray::valid() U
1009: Check whether the datastructure contains more entries */
1010: SPL_METHOD(SplFixedArray, valid)
1011: {
1012: spl_fixedarray_object *intern = (spl_fixedarray_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
1013:
1014: if (zend_parse_parameters_none() == FAILURE) {
1015: return;
1016: }
1017:
1018: RETURN_BOOL(intern->current >= 0 && intern->array && intern->current < intern->array->size);
1019: }
1020: /* }}} */
1021:
1022: /* {{{ proto void SplFixedArray::rewind() U
1023: Rewind the datastructure back to the start */
1024: SPL_METHOD(SplFixedArray, rewind)
1025: {
1026: spl_fixedarray_object *intern = (spl_fixedarray_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
1027:
1028: if (zend_parse_parameters_none() == FAILURE) {
1029: return;
1030: }
1031:
1032: intern->current = 0;
1033: }
1034: /* }}} */
1035:
1036: /* {{{ proto mixed|NULL SplFixedArray::current() U
1037: Return current datastructure entry */
1038: SPL_METHOD(SplFixedArray, current)
1039: {
1040: zval *zindex, **value_pp;
1041: spl_fixedarray_object *intern = (spl_fixedarray_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
1042:
1043: if (zend_parse_parameters_none() == FAILURE) {
1044: return;
1045: }
1046:
1047: ALLOC_INIT_ZVAL(zindex);
1048: ZVAL_LONG(zindex, intern->current);
1049:
1050: value_pp = spl_fixedarray_object_read_dimension_helper(intern, zindex TSRMLS_CC);
1051:
1052: zval_ptr_dtor(&zindex);
1053:
1054: if (value_pp) {
1055: RETURN_ZVAL(*value_pp, 1, 0);
1056: }
1057: RETURN_NULL();
1058: }
1059: /* }}} */
1060:
1061: /* iterator handler table */
1062: zend_object_iterator_funcs spl_fixedarray_it_funcs = {
1063: spl_fixedarray_it_dtor,
1064: spl_fixedarray_it_valid,
1065: spl_fixedarray_it_get_current_data,
1066: spl_fixedarray_it_get_current_key,
1067: spl_fixedarray_it_move_forward,
1068: spl_fixedarray_it_rewind
1069: };
1070:
1071: zend_object_iterator *spl_fixedarray_get_iterator(zend_class_entry *ce, zval *object, int by_ref TSRMLS_DC) /* {{{ */
1072: {
1073: spl_fixedarray_it *iterator;
1074: spl_fixedarray_object *fixedarray_object = (spl_fixedarray_object*)zend_object_store_get_object(object TSRMLS_CC);
1075:
1076: if (by_ref) {
1077: zend_throw_exception(spl_ce_RuntimeException, "An iterator cannot be used with foreach by reference", 0 TSRMLS_CC);
1078: return NULL;
1079: }
1080:
1081: Z_ADDREF_P(object);
1082:
1083: iterator = emalloc(sizeof(spl_fixedarray_it));
1084: iterator->intern.it.data = (void*)object;
1085: iterator->intern.it.funcs = &spl_fixedarray_it_funcs;
1086: iterator->intern.ce = ce;
1087: iterator->intern.value = NULL;
1088: iterator->object = fixedarray_object;
1089:
1090: return (zend_object_iterator*)iterator;
1091: }
1092: /* }}} */
1093:
1094: ZEND_BEGIN_ARG_INFO_EX(arginfo_splfixedarray_construct, 0, 0, 0)
1095: ZEND_ARG_INFO(0, size)
1096: ZEND_END_ARG_INFO()
1097:
1098: ZEND_BEGIN_ARG_INFO_EX(arginfo_fixedarray_offsetGet, 0, 0, 1)
1099: ZEND_ARG_INFO(0, index)
1100: ZEND_END_ARG_INFO()
1101:
1102: ZEND_BEGIN_ARG_INFO_EX(arginfo_fixedarray_offsetSet, 0, 0, 2)
1103: ZEND_ARG_INFO(0, index)
1104: ZEND_ARG_INFO(0, newval)
1105: ZEND_END_ARG_INFO()
1106:
1107: ZEND_BEGIN_ARG_INFO(arginfo_fixedarray_setSize, 0)
1108: ZEND_ARG_INFO(0, value)
1109: ZEND_END_ARG_INFO()
1110:
1111: ZEND_BEGIN_ARG_INFO_EX(arginfo_fixedarray_fromArray, 0, 0, 1)
1112: ZEND_ARG_INFO(0, data)
1113: ZEND_ARG_INFO(0, save_indexes)
1114: ZEND_END_ARG_INFO()
1115:
1116: ZEND_BEGIN_ARG_INFO(arginfo_splfixedarray_void, 0)
1117: ZEND_END_ARG_INFO()
1118:
1119: static zend_function_entry spl_funcs_SplFixedArray[] = { /* {{{ */
1120: SPL_ME(SplFixedArray, __construct, arginfo_splfixedarray_construct,ZEND_ACC_PUBLIC)
1.1.1.4 ! misho 1121: SPL_ME(SplFixedArray, __wakeup, arginfo_splfixedarray_void, ZEND_ACC_PUBLIC)
1.1 misho 1122: SPL_ME(SplFixedArray, count, arginfo_splfixedarray_void, ZEND_ACC_PUBLIC)
1123: SPL_ME(SplFixedArray, toArray, arginfo_splfixedarray_void, ZEND_ACC_PUBLIC)
1124: SPL_ME(SplFixedArray, fromArray, arginfo_fixedarray_fromArray, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)
1125: SPL_ME(SplFixedArray, getSize, arginfo_splfixedarray_void, ZEND_ACC_PUBLIC)
1126: SPL_ME(SplFixedArray, setSize, arginfo_fixedarray_setSize, ZEND_ACC_PUBLIC)
1127: SPL_ME(SplFixedArray, offsetExists, arginfo_fixedarray_offsetGet, ZEND_ACC_PUBLIC)
1128: SPL_ME(SplFixedArray, offsetGet, arginfo_fixedarray_offsetGet, ZEND_ACC_PUBLIC)
1129: SPL_ME(SplFixedArray, offsetSet, arginfo_fixedarray_offsetSet, ZEND_ACC_PUBLIC)
1130: SPL_ME(SplFixedArray, offsetUnset, arginfo_fixedarray_offsetGet, ZEND_ACC_PUBLIC)
1131: SPL_ME(SplFixedArray, rewind, arginfo_splfixedarray_void, ZEND_ACC_PUBLIC)
1132: SPL_ME(SplFixedArray, current, arginfo_splfixedarray_void, ZEND_ACC_PUBLIC)
1133: SPL_ME(SplFixedArray, key, arginfo_splfixedarray_void, ZEND_ACC_PUBLIC)
1134: SPL_ME(SplFixedArray, next, arginfo_splfixedarray_void, ZEND_ACC_PUBLIC)
1135: SPL_ME(SplFixedArray, valid, arginfo_splfixedarray_void, ZEND_ACC_PUBLIC)
1136: PHP_FE_END
1137: };
1138: /* }}} */
1139:
1140: /* {{{ PHP_MINIT_FUNCTION */
1141: PHP_MINIT_FUNCTION(spl_fixedarray)
1142: {
1143: REGISTER_SPL_STD_CLASS_EX(SplFixedArray, spl_fixedarray_new, spl_funcs_SplFixedArray);
1144: memcpy(&spl_handler_SplFixedArray, zend_get_std_object_handlers(), sizeof(zend_object_handlers));
1145:
1146: spl_handler_SplFixedArray.clone_obj = spl_fixedarray_object_clone;
1147: spl_handler_SplFixedArray.read_dimension = spl_fixedarray_object_read_dimension;
1148: spl_handler_SplFixedArray.write_dimension = spl_fixedarray_object_write_dimension;
1149: spl_handler_SplFixedArray.unset_dimension = spl_fixedarray_object_unset_dimension;
1150: spl_handler_SplFixedArray.has_dimension = spl_fixedarray_object_has_dimension;
1151: spl_handler_SplFixedArray.count_elements = spl_fixedarray_object_count_elements;
1152: spl_handler_SplFixedArray.get_properties = spl_fixedarray_object_get_properties;
1.1.1.3 misho 1153: spl_handler_SplFixedArray.get_gc = spl_fixedarray_object_get_gc;
1.1 misho 1154:
1155: REGISTER_SPL_IMPLEMENTS(SplFixedArray, Iterator);
1156: REGISTER_SPL_IMPLEMENTS(SplFixedArray, ArrayAccess);
1157: REGISTER_SPL_IMPLEMENTS(SplFixedArray, Countable);
1158:
1159: spl_ce_SplFixedArray->get_iterator = spl_fixedarray_get_iterator;
1160:
1161: return SUCCESS;
1162: }
1163: /* }}} */
1164:
1165:
1166: /*
1167: * Local variables:
1168: * tab-width: 4
1169: * c-basic-offset: 4
1170: * End:
1171: * vim600: noet sw=4 ts=4 fdm=marker
1172: * vim<600: noet sw=4 ts=4
1173: */
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>