Skip to content

Commit 859d93d

Browse files
committed
Add new serialization methods for SplFixedArray
1 parent 1dfd231 commit 859d93d

File tree

4 files changed

+117
-9
lines changed

4 files changed

+117
-9
lines changed

ext/spl/spl_fixedarray.c

Lines changed: 70 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -102,13 +102,18 @@ static void spl_fixedarray_init_elems(spl_fixedarray *array, zend_long from, zen
102102
}
103103
}
104104

105+
static void spl_fixedarray_init_non_empty_struct(spl_fixedarray *array, zend_long size)
106+
{
107+
array->size = 0; /* reset size in case ecalloc() fails */
108+
array->elements = safe_emalloc(size, sizeof(zval), 0);
109+
array->size = size;
110+
array->should_rebuild_properties = true;
111+
}
112+
105113
static void spl_fixedarray_init(spl_fixedarray *array, zend_long size)
106114
{
107115
if (size > 0) {
108-
array->size = 0; /* reset size in case ecalloc() fails */
109-
array->elements = safe_emalloc(size, sizeof(zval), 0);
110-
array->size = size;
111-
array->should_rebuild_properties = true;
116+
spl_fixedarray_init_non_empty_struct(array, size);
112117
spl_fixedarray_init_elems(array, 0, size);
113118
} else {
114119
spl_fixedarray_default_ctor(array);
@@ -582,6 +587,67 @@ PHP_METHOD(SplFixedArray, __wakeup)
582587
}
583588
}
584589

590+
PHP_METHOD(SplFixedArray, __serialize)
591+
{
592+
spl_fixedarray_object *intern = Z_SPLFIXEDARRAY_P(ZEND_THIS);
593+
zval *current, tmp;
594+
595+
if (zend_parse_parameters_none() == FAILURE) {
596+
RETURN_THROWS();
597+
}
598+
599+
array_init(return_value);
600+
601+
/* elements */
602+
array_init_size(&tmp, intern->array.size);
603+
604+
for (zend_long i = 0; i < intern->array.size; i++) {
605+
current = &intern->array.elements[i];
606+
zend_hash_next_index_insert(Z_ARRVAL(tmp), current);
607+
Z_TRY_ADDREF_P(current);
608+
}
609+
610+
zend_hash_next_index_insert(Z_ARRVAL_P(return_value), &tmp);
611+
612+
/* members */
613+
ZVAL_ARR(&tmp, zend_proptable_to_symtable(
614+
zend_std_get_properties(&intern->std), /* always_duplicate */ 1));
615+
zend_hash_next_index_insert(Z_ARRVAL_P(return_value), &tmp);
616+
}
617+
618+
PHP_METHOD(SplFixedArray, __unserialize)
619+
{
620+
spl_fixedarray_object *intern = Z_SPLFIXEDARRAY_P(ZEND_THIS);
621+
HashTable *data;
622+
zval *storage_zv, *members_zv, *elem;
623+
624+
if (zend_parse_parameters(ZEND_NUM_ARGS(), "h", &data) == FAILURE) {
625+
RETURN_THROWS();
626+
}
627+
628+
if (intern->array.size == 0) {
629+
storage_zv = zend_hash_index_find(data, 0);
630+
members_zv = zend_hash_index_find(data, 1);
631+
if (!storage_zv || !members_zv ||
632+
Z_TYPE_P(storage_zv) != IS_ARRAY || Z_TYPE_P(members_zv) != IS_ARRAY
633+
) {
634+
zend_throw_exception(spl_ce_UnexpectedValueException,
635+
"Incomplete or ill-typed serialization data", 0);
636+
RETURN_THROWS();
637+
}
638+
639+
zend_long size = zend_hash_num_elements(Z_ARRVAL_P(storage_zv));
640+
spl_fixedarray_init_non_empty_struct(&intern->array, size);
641+
642+
zend_long i = 0;
643+
ZEND_HASH_FOREACH_VAL(Z_ARRVAL_P(storage_zv), elem) {
644+
ZVAL_COPY(&intern->array.elements[i++], elem);
645+
} ZEND_HASH_FOREACH_END();
646+
647+
object_properties_load(&intern->std, Z_ARRVAL_P(members_zv));
648+
}
649+
}
650+
585651
PHP_METHOD(SplFixedArray, count)
586652
{
587653
zval *object = ZEND_THIS;

ext/spl/spl_fixedarray.stub.php

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,10 @@ public function __construct(int $size = 0) {}
99
/** @tentative-return-type */
1010
public function __wakeup(): void {}
1111

12+
public function __serialize(): array {}
13+
14+
public function __unserialize(array $data): void {}
15+
1216
/** @tentative-return-type */
1317
public function count(): int {}
1418

ext/spl/spl_fixedarray_arginfo.h

Lines changed: 13 additions & 3 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

ext/spl/tests/SplFixedArray_serialize.phpt

Lines changed: 30 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@ $array[2] = 42;
1313
$array[3] = $obj;
1414
$array[4] = range(1, 5);
1515

16+
$array->foo = "bar";
17+
1618
$ser = serialize($array);
1719
echo "$ser\n";
1820
$unser = unserialize($ser);
@@ -24,10 +26,23 @@ var_dump($unser[0], $unser[1], $unser[2], $unser[3], $unser[4]);
2426

2527
$unser[4] = 'quux';
2628
var_dump($unser[4]);
29+
var_dump($unser->foo);
30+
31+
$array = new SplFixedArray(5);
32+
$array->__unserialize([
33+
[null],
34+
[
35+
"foo" => "bar",
36+
],
37+
]);
38+
var_dump($array);
2739

2840
?>
29-
--EXPECT--
30-
O:13:"SplFixedArray":5:{i:0;s:3:"foo";i:1;N;i:2;i:42;i:3;O:8:"stdClass":1:{s:4:"prop";s:5:"value";}i:4;a:5:{i:0;i:1;i:1;i:2;i:2;i:3;i:3;i:4;i:4;i:5;}}
41+
--EXPECTF--
42+
Deprecated: Creation of dynamic property SplFixedArray::$foo is deprecated in %s on line %d
43+
O:13:"SplFixedArray":2:{i:0;a:5:{i:0;s:3:"foo";i:1;N;i:2;i:42;i:3;O:8:"stdClass":1:{s:4:"prop";s:5:"value";}i:4;a:5:{i:0;i:1;i:1;i:2;i:2;i:3;i:3;i:4;i:4;i:5;}}i:1;a:1:{s:3:"foo";s:3:"bar";}}
44+
45+
Deprecated: Creation of dynamic property SplFixedArray::$foo is deprecated in %s on line %d
3146
count: 5
3247
getSize(): 5
3348
string(3) "foo"
@@ -50,3 +65,16 @@ array(5) {
5065
int(5)
5166
}
5267
string(4) "quux"
68+
string(3) "bar"
69+
object(SplFixedArray)#5 (5) {
70+
[0]=>
71+
NULL
72+
[1]=>
73+
NULL
74+
[2]=>
75+
NULL
76+
[3]=>
77+
NULL
78+
[4]=>
79+
NULL
80+
}

0 commit comments

Comments
 (0)