Annotation of embedaddon/php/ext/spl/spl_fixedarray.c, revision 1.1.1.3
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:
607: /* {{{ proto int SplFixedArray::count(void)
608: */
609: SPL_METHOD(SplFixedArray, count)
610: {
611: zval *object = getThis();
612: spl_fixedarray_object *intern;
613:
614: if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "")) {
615: return;
616: }
617:
618: intern = (spl_fixedarray_object *)zend_object_store_get_object(object TSRMLS_CC);
619: if (intern->array) {
620: RETURN_LONG(intern->array->size);
621: }
622: RETURN_LONG(0);
623: }
624: /* }}} */
625:
626: /* {{{ proto object SplFixedArray::toArray()
627: */
628: SPL_METHOD(SplFixedArray, toArray)
629: {
1.1.1.3 ! misho 630: spl_fixedarray_object *intern;
1.1 misho 631:
632: if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "")) {
633: return;
634: }
635:
1.1.1.3 ! misho 636: intern = (spl_fixedarray_object *)zend_object_store_get_object(getThis() TSRMLS_CC);
1.1 misho 637:
1.1.1.3 ! misho 638: array_init(return_value);
! 639: if (intern->array) {
! 640: int i = 0;
! 641: for (; i < intern->array->size; i++) {
! 642: if (intern->array->elements[i]) {
! 643: zend_hash_index_update(Z_ARRVAL_P(return_value), i, (void *)&intern->array->elements[i], sizeof(zval *), NULL);
! 644: Z_ADDREF_P(intern->array->elements[i]);
! 645: } else {
! 646: zend_hash_index_update(Z_ARRVAL_P(return_value), i, (void *)&EG(uninitialized_zval_ptr), sizeof(zval *), NULL);
! 647: Z_ADDREF_P(EG(uninitialized_zval_ptr));
! 648: }
! 649: }
! 650: }
1.1 misho 651: }
652: /* }}} */
653:
654: /* {{{ proto object SplFixedArray::fromArray(array data[, bool save_indexes])
655: */
656: SPL_METHOD(SplFixedArray, fromArray)
657: {
658: zval *data;
659: spl_fixedarray *array;
660: spl_fixedarray_object *intern;
661: int num;
662: zend_bool save_indexes = 1;
663:
664: if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a|b", &data, &save_indexes)) {
665: return;
666: }
667:
668: array = ecalloc(1, sizeof(*array));
669: num = zend_hash_num_elements(Z_ARRVAL_P(data));
670:
671: if (num > 0 && save_indexes) {
672: zval **element, *value;
673: char *str_index;
674: ulong num_index, max_index = 0;
675: long tmp;
676:
677: for (zend_hash_internal_pointer_reset(Z_ARRVAL_P(data));
678: zend_hash_get_current_data(Z_ARRVAL_P(data), (void **) &element) == SUCCESS;
679: zend_hash_move_forward(Z_ARRVAL_P(data))
680: ) {
681: if (zend_hash_get_current_key(Z_ARRVAL_P(data), &str_index, &num_index, 0) != HASH_KEY_IS_LONG || (long)num_index < 0) {
682: efree(array);
683: zend_throw_exception_ex(spl_ce_InvalidArgumentException, 0 TSRMLS_CC, "array must contain only positive integer keys");
684: return;
685: }
686:
687: if (num_index > max_index) {
688: max_index = num_index;
689: }
690: }
691:
692: tmp = max_index + 1;
693: if (tmp <= 0) {
694: efree(array);
695: zend_throw_exception_ex(spl_ce_InvalidArgumentException, 0 TSRMLS_CC, "integer overflow detected");
696: return;
697: }
698: spl_fixedarray_init(array, tmp TSRMLS_CC);
699:
700: for (zend_hash_internal_pointer_reset(Z_ARRVAL_P(data));
701: zend_hash_get_current_data(Z_ARRVAL_P(data), (void **) &element) == SUCCESS;
702: zend_hash_move_forward(Z_ARRVAL_P(data))
703: ) {
704:
705: zend_hash_get_current_key(Z_ARRVAL_P(data), &str_index, &num_index, 0);
706: value = *element;
707:
708: SEPARATE_ARG_IF_REF(value);
709: array->elements[num_index] = value;
710: }
711:
712: } else if (num > 0 && !save_indexes) {
713: zval **element, *value;
714: long i = 0;
715:
716: spl_fixedarray_init(array, num TSRMLS_CC);
717:
718: for (zend_hash_internal_pointer_reset(Z_ARRVAL_P(data));
719: zend_hash_get_current_data(Z_ARRVAL_P(data), (void **) &element) == SUCCESS;
720: zend_hash_move_forward(Z_ARRVAL_P(data))
721: ) {
722:
723: value = *element;
724:
725: SEPARATE_ARG_IF_REF(value);
726: array->elements[i] = value;
727: i++;
728: }
729: } else {
730: spl_fixedarray_init(array, 0 TSRMLS_CC);
731: }
732:
733: object_init_ex(return_value, spl_ce_SplFixedArray);
734: Z_TYPE_P(return_value) = IS_OBJECT;
735:
736: intern = (spl_fixedarray_object *)zend_object_store_get_object(return_value TSRMLS_CC);
737: intern->array = array;
738: }
739: /* }}} */
740:
741: /* {{{ proto int SplFixedArray::getSize(void)
742: */
743: SPL_METHOD(SplFixedArray, getSize)
744: {
745: zval *object = getThis();
746: spl_fixedarray_object *intern;
747:
748: if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "")) {
749: return;
750: }
751:
752: intern = (spl_fixedarray_object *)zend_object_store_get_object(object TSRMLS_CC);
753: if (intern->array) {
754: RETURN_LONG(intern->array->size);
755: }
756: RETURN_LONG(0);
757: }
758: /* }}} */
759:
760: /* {{{ proto bool SplFixedArray::setSize(int size)
761: */
762: SPL_METHOD(SplFixedArray, setSize)
763: {
764: zval *object = getThis();
765: spl_fixedarray_object *intern;
766: long size;
767:
768: if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &size)) {
769: return;
770: }
771:
772: if (size < 0) {
773: zend_throw_exception_ex(spl_ce_InvalidArgumentException, 0 TSRMLS_CC, "array size cannot be less than zero");
774: return;
775: }
776:
777: intern = (spl_fixedarray_object *)zend_object_store_get_object(object TSRMLS_CC);
778: if (!intern->array) {
779: intern->array = ecalloc(1, sizeof(spl_fixedarray));
780: }
781:
782: spl_fixedarray_resize(intern->array, size TSRMLS_CC);
783: RETURN_TRUE;
784: }
785: /* }}} */
786:
787: /* {{{ proto bool SplFixedArray::offsetExists(mixed $index) U
788: Returns whether the requested $index exists. */
789: SPL_METHOD(SplFixedArray, offsetExists)
790: {
791: zval *zindex;
792: spl_fixedarray_object *intern;
793:
794: if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &zindex) == FAILURE) {
795: return;
796: }
797:
798: intern = (spl_fixedarray_object *)zend_object_store_get_object(getThis() TSRMLS_CC);
799:
800: RETURN_BOOL(spl_fixedarray_object_has_dimension_helper(intern, zindex, 0 TSRMLS_CC));
801: } /* }}} */
802:
803: /* {{{ proto mixed SplFixedArray::offsetGet(mixed $index) U
804: Returns the value at the specified $index. */
805: SPL_METHOD(SplFixedArray, offsetGet)
806: {
807: zval *zindex, **value_pp;
808: spl_fixedarray_object *intern;
809:
810: if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &zindex) == FAILURE) {
811: return;
812: }
813:
814: intern = (spl_fixedarray_object *)zend_object_store_get_object(getThis() TSRMLS_CC);
815: value_pp = spl_fixedarray_object_read_dimension_helper(intern, zindex TSRMLS_CC);
816:
817: if (value_pp) {
818: RETURN_ZVAL(*value_pp, 1, 0);
819: }
820: RETURN_NULL();
821: } /* }}} */
822:
823: /* {{{ proto void SplFixedArray::offsetSet(mixed $index, mixed $newval) U
824: Sets the value at the specified $index to $newval. */
825: SPL_METHOD(SplFixedArray, offsetSet)
826: {
827: zval *zindex, *value;
828: spl_fixedarray_object *intern;
829:
830: if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "zz", &zindex, &value) == FAILURE) {
831: return;
832: }
833:
834: intern = (spl_fixedarray_object *)zend_object_store_get_object(getThis() TSRMLS_CC);
835: spl_fixedarray_object_write_dimension_helper(intern, zindex, value TSRMLS_CC);
836:
837: } /* }}} */
838:
839: /* {{{ proto void SplFixedArray::offsetUnset(mixed $index) U
840: Unsets the value at the specified $index. */
841: SPL_METHOD(SplFixedArray, offsetUnset)
842: {
843: zval *zindex;
844: spl_fixedarray_object *intern;
845:
846: if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &zindex) == FAILURE) {
847: return;
848: }
849:
850: intern = (spl_fixedarray_object *)zend_object_store_get_object(getThis() TSRMLS_CC);
851: spl_fixedarray_object_unset_dimension_helper(intern, zindex TSRMLS_CC);
852:
853: } /* }}} */
854:
855: static void spl_fixedarray_it_dtor(zend_object_iterator *iter TSRMLS_DC) /* {{{ */
856: {
857: spl_fixedarray_it *iterator = (spl_fixedarray_it *)iter;
858:
859: zend_user_it_invalidate_current(iter TSRMLS_CC);
860: zval_ptr_dtor((zval**)&iterator->intern.it.data);
861:
862: efree(iterator);
863: }
864: /* }}} */
865:
866: static void spl_fixedarray_it_rewind(zend_object_iterator *iter TSRMLS_DC) /* {{{ */
867: {
868: spl_fixedarray_it *iterator = (spl_fixedarray_it *)iter;
869: spl_fixedarray_object *intern = iterator->object;
870:
871: if (intern->flags & SPL_FIXEDARRAY_OVERLOADED_REWIND) {
872: zend_user_it_rewind(iter TSRMLS_CC);
873: } else {
874: iterator->object->current = 0;
875: }
876: }
877: /* }}} */
878:
879: static int spl_fixedarray_it_valid(zend_object_iterator *iter TSRMLS_DC) /* {{{ */
880: {
881: spl_fixedarray_it *iterator = (spl_fixedarray_it *)iter;
882: spl_fixedarray_object *intern = iterator->object;
883:
884: if (intern->flags & SPL_FIXEDARRAY_OVERLOADED_VALID) {
885: return zend_user_it_valid(iter TSRMLS_CC);
886: }
887:
888: if (iterator->object->current >= 0 && iterator->object->array && iterator->object->current < iterator->object->array->size) {
889: return SUCCESS;
890: }
891:
892: return FAILURE;
893: }
894: /* }}} */
895:
896: static void spl_fixedarray_it_get_current_data(zend_object_iterator *iter, zval ***data TSRMLS_DC) /* {{{ */
897: {
898: zval *zindex;
899: spl_fixedarray_it *iterator = (spl_fixedarray_it *)iter;
900: spl_fixedarray_object *intern = iterator->object;
901:
902: if (intern->flags & SPL_FIXEDARRAY_OVERLOADED_CURRENT) {
903: zend_user_it_get_current_data(iter, data TSRMLS_CC);
904: } else {
905: ALLOC_INIT_ZVAL(zindex);
906: ZVAL_LONG(zindex, iterator->object->current);
907:
908: *data = spl_fixedarray_object_read_dimension_helper(intern, zindex TSRMLS_CC);
909:
910: if (*data == NULL) {
911: *data = &EG(uninitialized_zval_ptr);
912: }
913:
914: zval_ptr_dtor(&zindex);
915: }
916: }
917: /* }}} */
918:
919: static int spl_fixedarray_it_get_current_key(zend_object_iterator *iter, char **str_key, uint *str_key_len, ulong *int_key TSRMLS_DC) /* {{{ */
920: {
921: spl_fixedarray_it *iterator = (spl_fixedarray_it *)iter;
922: spl_fixedarray_object *intern = iterator->object;
923:
924: if (intern->flags & SPL_FIXEDARRAY_OVERLOADED_KEY) {
925: return zend_user_it_get_current_key(iter, str_key, str_key_len, int_key TSRMLS_CC);
926: } else {
927: *int_key = (ulong) iterator->object->current;
928: return HASH_KEY_IS_LONG;
929: }
930:
931: }
932: /* }}} */
933:
934: static void spl_fixedarray_it_move_forward(zend_object_iterator *iter TSRMLS_DC) /* {{{ */
935: {
936: spl_fixedarray_it *iterator = (spl_fixedarray_it *)iter;
937: spl_fixedarray_object *intern = iterator->object;
938:
939: if (intern->flags & SPL_FIXEDARRAY_OVERLOADED_NEXT) {
940: zend_user_it_move_forward(iter TSRMLS_CC);
941: } else {
942: zend_user_it_invalidate_current(iter TSRMLS_CC);
943: iterator->object->current++;
944: }
945: }
946: /* }}} */
947:
948: /* {{{ proto int SplFixedArray::key() U
949: Return current array key */
950: SPL_METHOD(SplFixedArray, key)
951: {
952: spl_fixedarray_object *intern = (spl_fixedarray_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
953:
954: if (zend_parse_parameters_none() == FAILURE) {
955: return;
956: }
957:
958: RETURN_LONG(intern->current);
959: }
960: /* }}} */
961:
962: /* {{{ proto void SplFixedArray::next() U
963: Move to next entry */
964: SPL_METHOD(SplFixedArray, next)
965: {
966: spl_fixedarray_object *intern = (spl_fixedarray_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
967:
968: if (zend_parse_parameters_none() == FAILURE) {
969: return;
970: }
971:
972: intern->current++;
973: }
974: /* }}} */
975:
976: /* {{{ proto bool SplFixedArray::valid() U
977: Check whether the datastructure contains more entries */
978: SPL_METHOD(SplFixedArray, valid)
979: {
980: spl_fixedarray_object *intern = (spl_fixedarray_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
981:
982: if (zend_parse_parameters_none() == FAILURE) {
983: return;
984: }
985:
986: RETURN_BOOL(intern->current >= 0 && intern->array && intern->current < intern->array->size);
987: }
988: /* }}} */
989:
990: /* {{{ proto void SplFixedArray::rewind() U
991: Rewind the datastructure back to the start */
992: SPL_METHOD(SplFixedArray, rewind)
993: {
994: spl_fixedarray_object *intern = (spl_fixedarray_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
995:
996: if (zend_parse_parameters_none() == FAILURE) {
997: return;
998: }
999:
1000: intern->current = 0;
1001: }
1002: /* }}} */
1003:
1004: /* {{{ proto mixed|NULL SplFixedArray::current() U
1005: Return current datastructure entry */
1006: SPL_METHOD(SplFixedArray, current)
1007: {
1008: zval *zindex, **value_pp;
1009: spl_fixedarray_object *intern = (spl_fixedarray_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
1010:
1011: if (zend_parse_parameters_none() == FAILURE) {
1012: return;
1013: }
1014:
1015: ALLOC_INIT_ZVAL(zindex);
1016: ZVAL_LONG(zindex, intern->current);
1017:
1018: value_pp = spl_fixedarray_object_read_dimension_helper(intern, zindex TSRMLS_CC);
1019:
1020: zval_ptr_dtor(&zindex);
1021:
1022: if (value_pp) {
1023: RETURN_ZVAL(*value_pp, 1, 0);
1024: }
1025: RETURN_NULL();
1026: }
1027: /* }}} */
1028:
1029: /* iterator handler table */
1030: zend_object_iterator_funcs spl_fixedarray_it_funcs = {
1031: spl_fixedarray_it_dtor,
1032: spl_fixedarray_it_valid,
1033: spl_fixedarray_it_get_current_data,
1034: spl_fixedarray_it_get_current_key,
1035: spl_fixedarray_it_move_forward,
1036: spl_fixedarray_it_rewind
1037: };
1038:
1039: zend_object_iterator *spl_fixedarray_get_iterator(zend_class_entry *ce, zval *object, int by_ref TSRMLS_DC) /* {{{ */
1040: {
1041: spl_fixedarray_it *iterator;
1042: spl_fixedarray_object *fixedarray_object = (spl_fixedarray_object*)zend_object_store_get_object(object TSRMLS_CC);
1043:
1044: if (by_ref) {
1045: zend_throw_exception(spl_ce_RuntimeException, "An iterator cannot be used with foreach by reference", 0 TSRMLS_CC);
1046: return NULL;
1047: }
1048:
1049: Z_ADDREF_P(object);
1050:
1051: iterator = emalloc(sizeof(spl_fixedarray_it));
1052: iterator->intern.it.data = (void*)object;
1053: iterator->intern.it.funcs = &spl_fixedarray_it_funcs;
1054: iterator->intern.ce = ce;
1055: iterator->intern.value = NULL;
1056: iterator->object = fixedarray_object;
1057:
1058: return (zend_object_iterator*)iterator;
1059: }
1060: /* }}} */
1061:
1062: ZEND_BEGIN_ARG_INFO_EX(arginfo_splfixedarray_construct, 0, 0, 0)
1063: ZEND_ARG_INFO(0, size)
1064: ZEND_END_ARG_INFO()
1065:
1066: ZEND_BEGIN_ARG_INFO_EX(arginfo_fixedarray_offsetGet, 0, 0, 1)
1067: ZEND_ARG_INFO(0, index)
1068: ZEND_END_ARG_INFO()
1069:
1070: ZEND_BEGIN_ARG_INFO_EX(arginfo_fixedarray_offsetSet, 0, 0, 2)
1071: ZEND_ARG_INFO(0, index)
1072: ZEND_ARG_INFO(0, newval)
1073: ZEND_END_ARG_INFO()
1074:
1075: ZEND_BEGIN_ARG_INFO(arginfo_fixedarray_setSize, 0)
1076: ZEND_ARG_INFO(0, value)
1077: ZEND_END_ARG_INFO()
1078:
1079: ZEND_BEGIN_ARG_INFO_EX(arginfo_fixedarray_fromArray, 0, 0, 1)
1080: ZEND_ARG_INFO(0, data)
1081: ZEND_ARG_INFO(0, save_indexes)
1082: ZEND_END_ARG_INFO()
1083:
1084: ZEND_BEGIN_ARG_INFO(arginfo_splfixedarray_void, 0)
1085: ZEND_END_ARG_INFO()
1086:
1087: static zend_function_entry spl_funcs_SplFixedArray[] = { /* {{{ */
1088: SPL_ME(SplFixedArray, __construct, arginfo_splfixedarray_construct,ZEND_ACC_PUBLIC)
1089: SPL_ME(SplFixedArray, count, arginfo_splfixedarray_void, ZEND_ACC_PUBLIC)
1090: SPL_ME(SplFixedArray, toArray, arginfo_splfixedarray_void, ZEND_ACC_PUBLIC)
1091: SPL_ME(SplFixedArray, fromArray, arginfo_fixedarray_fromArray, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)
1092: SPL_ME(SplFixedArray, getSize, arginfo_splfixedarray_void, ZEND_ACC_PUBLIC)
1093: SPL_ME(SplFixedArray, setSize, arginfo_fixedarray_setSize, ZEND_ACC_PUBLIC)
1094: SPL_ME(SplFixedArray, offsetExists, arginfo_fixedarray_offsetGet, ZEND_ACC_PUBLIC)
1095: SPL_ME(SplFixedArray, offsetGet, arginfo_fixedarray_offsetGet, ZEND_ACC_PUBLIC)
1096: SPL_ME(SplFixedArray, offsetSet, arginfo_fixedarray_offsetSet, ZEND_ACC_PUBLIC)
1097: SPL_ME(SplFixedArray, offsetUnset, arginfo_fixedarray_offsetGet, ZEND_ACC_PUBLIC)
1098: SPL_ME(SplFixedArray, rewind, arginfo_splfixedarray_void, ZEND_ACC_PUBLIC)
1099: SPL_ME(SplFixedArray, current, arginfo_splfixedarray_void, ZEND_ACC_PUBLIC)
1100: SPL_ME(SplFixedArray, key, arginfo_splfixedarray_void, ZEND_ACC_PUBLIC)
1101: SPL_ME(SplFixedArray, next, arginfo_splfixedarray_void, ZEND_ACC_PUBLIC)
1102: SPL_ME(SplFixedArray, valid, arginfo_splfixedarray_void, ZEND_ACC_PUBLIC)
1103: PHP_FE_END
1104: };
1105: /* }}} */
1106:
1107: /* {{{ PHP_MINIT_FUNCTION */
1108: PHP_MINIT_FUNCTION(spl_fixedarray)
1109: {
1110: REGISTER_SPL_STD_CLASS_EX(SplFixedArray, spl_fixedarray_new, spl_funcs_SplFixedArray);
1111: memcpy(&spl_handler_SplFixedArray, zend_get_std_object_handlers(), sizeof(zend_object_handlers));
1112:
1113: spl_handler_SplFixedArray.clone_obj = spl_fixedarray_object_clone;
1114: spl_handler_SplFixedArray.read_dimension = spl_fixedarray_object_read_dimension;
1115: spl_handler_SplFixedArray.write_dimension = spl_fixedarray_object_write_dimension;
1116: spl_handler_SplFixedArray.unset_dimension = spl_fixedarray_object_unset_dimension;
1117: spl_handler_SplFixedArray.has_dimension = spl_fixedarray_object_has_dimension;
1118: spl_handler_SplFixedArray.count_elements = spl_fixedarray_object_count_elements;
1119: spl_handler_SplFixedArray.get_properties = spl_fixedarray_object_get_properties;
1.1.1.3 ! misho 1120: spl_handler_SplFixedArray.get_gc = spl_fixedarray_object_get_gc;
1.1 misho 1121:
1122: REGISTER_SPL_IMPLEMENTS(SplFixedArray, Iterator);
1123: REGISTER_SPL_IMPLEMENTS(SplFixedArray, ArrayAccess);
1124: REGISTER_SPL_IMPLEMENTS(SplFixedArray, Countable);
1125:
1126: spl_ce_SplFixedArray->get_iterator = spl_fixedarray_get_iterator;
1127:
1128: return SUCCESS;
1129: }
1130: /* }}} */
1131:
1132:
1133: /*
1134: * Local variables:
1135: * tab-width: 4
1136: * c-basic-offset: 4
1137: * End:
1138: * vim600: noet sw=4 ts=4 fdm=marker
1139: * vim<600: noet sw=4 ts=4
1140: */
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>