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