Skip to content

Commit 38d30bf

Browse files
committed
Support $vector[] = $value;
1 parent 73204db commit 38d30bf

File tree

2 files changed

+62
-19
lines changed

2 files changed

+62
-19
lines changed

ext/spl/spl_vector.c

Lines changed: 44 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1043,15 +1043,8 @@ PHP_METHOD(Vector, offsetSet)
10431043
spl_vector_set_value_at_offset(Z_OBJ_P(ZEND_THIS), offset, value);
10441044
}
10451045

1046-
PHP_METHOD(Vector, push)
1046+
static zend_always_inline void spl_vector_push(spl_vector *intern, zval *value)
10471047
{
1048-
zval *value;
1049-
1050-
ZEND_PARSE_PARAMETERS_START(1, 1)
1051-
Z_PARAM_ZVAL(value)
1052-
ZEND_PARSE_PARAMETERS_END();
1053-
1054-
spl_vector *intern = Z_VECTOR_P(ZEND_THIS);
10551048
const size_t old_size = intern->array.size;
10561049
const size_t old_capacity = intern->array.capacity;
10571050

@@ -1063,6 +1056,17 @@ PHP_METHOD(Vector, push)
10631056
intern->array.size++;
10641057
}
10651058

1059+
PHP_METHOD(Vector, push)
1060+
{
1061+
zval *value;
1062+
1063+
ZEND_PARSE_PARAMETERS_START(1, 1)
1064+
Z_PARAM_ZVAL(value)
1065+
ZEND_PARSE_PARAMETERS_END();
1066+
1067+
spl_vector_push(Z_VECTOR_P(ZEND_THIS), value);
1068+
}
1069+
10661070
PHP_METHOD(Vector, pop)
10671071
{
10681072
ZEND_PARSE_PARAMETERS_NONE();
@@ -1134,35 +1138,35 @@ PHP_METHOD(Vector, jsonSerialize)
11341138

11351139
static void spl_vector_write_dimension(zend_object *object, zval *offset_zv, zval *value)
11361140
{
1141+
spl_vector *intern = spl_vector_from_object(object);
11371142
if (!offset_zv) {
1138-
zend_throw_exception(spl_ce_RuntimeException, "[] operator not supported for Vector", 0);
1143+
spl_vector_push(intern, value);
11391144
return;
11401145
}
11411146

11421147
zend_long offset;
11431148
CONVERT_OFFSET_TO_LONG_OR_THROW(offset, offset_zv);
11441149

1145-
const spl_vector *intern = spl_vector_from_object(object);
11461150
if (offset < 0 || offset >= intern->array.size) {
11471151
zend_throw_exception(spl_ce_OutOfBoundsException, "Index invalid or out of range", 0);
11481152
return;
11491153
}
1154+
ZVAL_DEREF(value);
11501155
spl_vector_set_value_at_offset(object, offset, value);
11511156
}
11521157

11531158
static zval *spl_vector_read_dimension(zend_object *object, zval *offset_zv, int type, zval *rv)
11541159
{
1155-
if (!offset_zv) {
1156-
zend_throw_exception(spl_ce_RuntimeException, "[] operator not supported for Vector", 0);
1157-
return NULL;
1160+
if (UNEXPECTED(!offset_zv || Z_ISUNDEF_P(offset_zv))) {
1161+
return &EG(uninitialized_zval);
11581162
}
11591163

11601164
zend_long offset;
11611165
CONVERT_OFFSET_TO_LONG_OR_THROW_RETURN_NULLPTR(offset, offset_zv);
11621166

11631167
const spl_vector *intern = spl_vector_from_object(object);
11641168

1165-
if (offset < 0 || offset >= intern->array.size) {
1169+
if (UNEXPECTED(offset < 0 || offset >= intern->array.size)) {
11661170
if (type != BP_VAR_IS) {
11671171
zend_throw_exception(spl_ce_OutOfBoundsException, "Index out of range", 0);
11681172
}
@@ -1172,6 +1176,31 @@ static zval *spl_vector_read_dimension(zend_object *object, zval *offset_zv, int
11721176
}
11731177
}
11741178

1179+
static int spl_vector_has_dimension(zend_object *object, zval *offset_zv, int check_empty)
1180+
{
1181+
zend_long offset;
1182+
if (UNEXPECTED(Z_TYPE_P(offset_zv) != IS_LONG)) {
1183+
offset = spl_offset_convert_to_long(offset_zv);
1184+
if (UNEXPECTED(EG(exception))) {
1185+
return 0;
1186+
}
1187+
} else {
1188+
offset = Z_LVAL_P(offset_zv);
1189+
}
1190+
1191+
const spl_vector *intern = spl_vector_from_object(object);
1192+
1193+
if (UNEXPECTED(offset < 0 || offset >= intern->array.size)) {
1194+
return 0;
1195+
}
1196+
1197+
zval *val = &intern->array.entries[offset];
1198+
if (check_empty) {
1199+
return zend_is_true(val);
1200+
}
1201+
return Z_TYPE_P(val) != IS_NULL;
1202+
}
1203+
11751204
PHP_MINIT_FUNCTION(spl_vector)
11761205
{
11771206
spl_ce_Vector = register_class_Vector(zend_ce_aggregate, zend_ce_countable, php_json_serializable_ce, zend_ce_arrayaccess);
@@ -1189,6 +1218,7 @@ PHP_MINIT_FUNCTION(spl_vector)
11891218

11901219
spl_handler_Vector.read_dimension = spl_vector_read_dimension;
11911220
spl_handler_Vector.write_dimension = spl_vector_write_dimension;
1221+
spl_handler_Vector.has_dimension = spl_vector_has_dimension;
11921222

11931223
spl_ce_Vector->ce_flags |= ZEND_ACC_FINAL | ZEND_ACC_NO_DYNAMIC_PROPERTIES;
11941224
spl_ce_Vector->get_iterator = spl_vector_get_iterator;

ext/spl/tests/Vector/push_pop.phpt

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -20,30 +20,43 @@ expect_throws(fn() => $it->pop());
2020
$it->push(strtoupper('test'));
2121
$it->push(['literal']);
2222
$it->push(new stdClass());
23+
$it[] = strtoupper('test2');
24+
$it[] = null;
2325
echo json_encode($it), "\n";
2426
printf("count=%d capacity=%d\n", count($it), $it->capacity());
2527
var_dump($it->pop());
2628
var_dump($it->pop());
27-
echo "After popping 2 elements: ", json_encode($it->toArray()), "\n";
29+
var_dump($it->pop());
30+
var_dump($it->pop());
31+
echo "After popping 4 elements: ", json_encode($it->toArray()), "\n";
2832
var_dump($it->pop());
2933
echo json_encode($it), "\n";
3034
printf("count=%d capacity=%d\n", count($it), $it->capacity());
35+
echo "After shrinkToFit\n";
36+
$it->shrinkToFit();
37+
echo json_encode($it), "\n";
38+
printf("count=%d capacity=%d\n", count($it), $it->capacity());
3139

3240
?>
3341
--EXPECT--
3442
Test empty vector
3543
count=0 capacity=0
3644
Caught UnderflowException: Cannot pop from empty Vector
3745
Caught UnderflowException: Cannot pop from empty Vector
38-
["TEST",["literal"],{}]
39-
count=3 capacity=4
46+
["TEST",["literal"],{},"TEST2",null]
47+
count=5 capacity=8
48+
NULL
49+
string(5) "TEST2"
4050
object(stdClass)#2 (0) {
4151
}
4252
array(1) {
4353
[0]=>
4454
string(7) "literal"
4555
}
46-
After popping 2 elements: ["TEST"]
56+
After popping 4 elements: ["TEST"]
4757
string(4) "TEST"
4858
[]
49-
count=0 capacity=4
59+
count=0 capacity=4
60+
After shrinkToFit
61+
[]
62+
count=0 capacity=0

0 commit comments

Comments
 (0)