Skip to content

Commit 4257469

Browse files
Mark Bakerdsp
Mark Baker
authored andcommitted
Fix #48358 add() method for SplDoublyLinkedLis
1 parent 4837bdb commit 4257469

7 files changed

+159
-4
lines changed

NEWS

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,10 @@ PHP NEWS
2222
(Gustavo, Derick, Anatol)
2323
. Fixed bug #62852 (Unserialize Invalid Date causes crash). (Anatol)
2424

25+
- SPL:
26+
. Implement FR #48358 (Add SplDoublyLinkedList::add() to insert an element
27+
at a given offset). (Mark Baker, David Soria Parra)
28+
2529
07 Mar 2013, PHP 5.5.0 Alpha 6
2630

2731
- Core:

ext/spl/spl_dllist.c

Lines changed: 62 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -794,7 +794,7 @@ SPL_METHOD(SplDoublyLinkedList, offsetGet)
794794
intern = (spl_dllist_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
795795
index = spl_offset_convert_to_long(zindex TSRMLS_CC);
796796

797-
if (index < 0 || index >= intern->llist->count) {
797+
if (index < 0 || index >= intern->llist->count) {
798798
zend_throw_exception(spl_ce_OutOfRangeException, "Offset invalid or out of range", 0 TSRMLS_CC);
799799
return;
800800
}
@@ -881,9 +881,9 @@ SPL_METHOD(SplDoublyLinkedList, offsetUnset)
881881

882882
intern = (spl_dllist_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
883883
index = spl_offset_convert_to_long(zindex TSRMLS_CC);
884-
llist = intern->llist;
884+
llist = intern->llist;
885885

886-
if (index < 0 || index >= intern->llist->count) {
886+
if (index < 0 || index >= intern->llist->count) {
887887
zend_throw_exception(spl_ce_OutOfRangeException, "Offset out of range", 0 TSRMLS_CC);
888888
return;
889889
}
@@ -1138,7 +1138,7 @@ SPL_METHOD(SplDoublyLinkedList, serialize)
11381138
spl_dllist_object *intern = (spl_dllist_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
11391139
smart_str buf = {0};
11401140
spl_ptr_llist_element *current = intern->llist->head, *next;
1141-
zval *flags;
1141+
zval *flags;
11421142
php_serialize_data_t var_hash;
11431143

11441144
if (zend_parse_parameters_none() == FAILURE) {
@@ -1234,6 +1234,61 @@ SPL_METHOD(SplDoublyLinkedList, unserialize)
12341234

12351235
} /* }}} */
12361236

1237+
/* {{{ proto void SplDoublyLinkedList::add(mixed $index, mixed $newval) U
1238+
Inserts a new entry before the specified $index consisting of $newval. */
1239+
SPL_METHOD(SplDoublyLinkedList, add)
1240+
{
1241+
zval *zindex, *value;
1242+
spl_dllist_object *intern;
1243+
spl_ptr_llist_element *element;
1244+
long index;
1245+
1246+
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "zz", &zindex, &value) == FAILURE) {
1247+
return;
1248+
}
1249+
SEPARATE_ARG_IF_REF(value);
1250+
1251+
intern = (spl_dllist_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
1252+
index = spl_offset_convert_to_long(zindex TSRMLS_CC);
1253+
1254+
if (index < 0 || index > intern->llist->count) {
1255+
zend_throw_exception(spl_ce_OutOfRangeException, "Offset invalid or out of range", 0 TSRMLS_CC);
1256+
return;
1257+
}
1258+
1259+
if (index == intern->llist->count) {
1260+
/* If index is the last entry+1 then we do a push because we're not inserting before any entry */
1261+
spl_ptr_llist_push(intern->llist, value TSRMLS_CC);
1262+
} else {
1263+
/* Get the element we want to insert before */
1264+
element = spl_ptr_llist_offset(intern->llist, index, intern->flags & SPL_DLLIST_IT_LIFO);
1265+
1266+
/* Create the new element we want to insert */
1267+
spl_ptr_llist_element *elem = emalloc(sizeof(spl_ptr_llist_element));
1268+
1269+
elem->data = value;
1270+
elem->rc = 1;
1271+
/* connect to the neighbours */
1272+
elem->next = element;
1273+
elem->prev = element->prev;
1274+
1275+
/* connect the neighbours to this new element */
1276+
if (elem->prev == NULL) {
1277+
intern->llist->head = elem;
1278+
} else {
1279+
element->prev->next = elem;
1280+
}
1281+
element->prev = elem;
1282+
1283+
intern->llist->count++;
1284+
1285+
if (intern->llist->ctor) {
1286+
intern->llist->ctor(elem TSRMLS_CC);
1287+
}
1288+
}
1289+
} /* }}} */
1290+
1291+
12371292
/* iterator handler table */
12381293
zend_object_iterator_funcs spl_dllist_it_funcs = {
12391294
spl_dllist_it_dtor,
@@ -1321,6 +1376,9 @@ static const zend_function_entry spl_funcs_SplDoublyLinkedList[] = {
13211376
SPL_ME(SplDoublyLinkedList, offsetGet, arginfo_dllist_offsetGet, ZEND_ACC_PUBLIC)
13221377
SPL_ME(SplDoublyLinkedList, offsetSet, arginfo_dllist_offsetSet, ZEND_ACC_PUBLIC)
13231378
SPL_ME(SplDoublyLinkedList, offsetUnset, arginfo_dllist_offsetGet, ZEND_ACC_PUBLIC)
1379+
1380+
SPL_ME(SplDoublyLinkedList, add, arginfo_dllist_offsetSet, ZEND_ACC_PUBLIC)
1381+
13241382
/* Iterator */
13251383
SPL_ME(SplDoublyLinkedList, rewind, arginfo_dllist_void, ZEND_ACC_PUBLIC)
13261384
SPL_ME(SplDoublyLinkedList, current, arginfo_dllist_void, ZEND_ACC_PUBLIC)
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
--TEST--
2+
Check that SplDoublyLinkedList::add throws an exception with an invalid offset argument
3+
--FILE--
4+
<?php
5+
try {
6+
$dll = new SplDoublyLinkedList();
7+
var_dump($dll->add(12,'Offset 12 should not exist'));
8+
} catch (OutOfRangeException $e) {
9+
echo "Exception: ".$e->getMessage()."\n";
10+
}
11+
?>
12+
--EXPECTF--
13+
Exception: Offset invalid or out of range
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
--TEST--
2+
Check that SplDoublyLinkedList::add generate a warning and returns a NULL with missing arguments
3+
--FILE--
4+
<?php
5+
$dll = new SplDoublyLinkedList();
6+
var_dump($dll->add());
7+
?>
8+
--EXPECTF--
9+
Warning: SplDoublyLinkedList::add() expects exactly 2 parameters, 0 given in %s on line %d
10+
NULL
11+
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
--TEST--
2+
Check that SplDoublyLinkedList::add generate a warning and returns a NULL with a missing value argument
3+
--FILE--
4+
<?php
5+
$dll = new SplDoublyLinkedList();
6+
var_dump($dll->add(2));
7+
?>
8+
--EXPECTF--
9+
Warning: SplDoublyLinkedList::add() expects exactly 2 parameters, 1 given in %s on line %d
10+
NULL
11+
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
--TEST--
2+
Check that SplDoublyLinkedList::add throws an exception with an invalid offset argument
3+
--FILE--
4+
<?php
5+
try {
6+
$dll = new SplDoublyLinkedList();
7+
var_dump($dll->add(NULL,2));
8+
} catch (OutOfRangeException $e) {
9+
echo "Exception: ".$e->getMessage()."\n";
10+
}
11+
?>
12+
--EXPECTF--
13+
Exception: Offset invalid or out of range

ext/spl/tests/dllist_013.phpt

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
--TEST--
2+
SPL: DoublyLinkedList: insert operations
3+
--FILE--
4+
<?php
5+
$dll = new SplDoublyLinkedList();
6+
// errors
7+
try {
8+
$dll->add(2,5);
9+
} catch (OutOfRangeException $e) {
10+
echo "Exception: ".$e->getMessage()."\n";
11+
}
12+
13+
$dll->add(0,6); // 6
14+
$dll->add(0,3); // 3 6
15+
// Insert in the middle of the DLL
16+
$dll->add(1,4); // 3 4 6
17+
$dll->add(2,5); // 3 4 5 6
18+
$dll->unshift(2); // 2 3 5 4 6
19+
// Insert at the beginning and end of the DLL
20+
$dll->add(0,1); // 1 2 3 4 5 6
21+
$dll->add(6,7); // 1 2 3 4 5 6 7
22+
23+
echo count($dll)."\n";
24+
25+
echo $dll->pop()."\n";
26+
echo $dll->pop()."\n";
27+
echo $dll->pop()."\n";
28+
echo $dll->pop()."\n";
29+
echo $dll->pop()."\n";
30+
echo $dll->pop()."\n";
31+
echo $dll->pop()."\n";
32+
?>
33+
===DONE===
34+
<?php exit(0); ?>
35+
--EXPECTF--
36+
Exception: Offset invalid or out of range
37+
7
38+
7
39+
6
40+
5
41+
4
42+
3
43+
2
44+
1
45+
===DONE===

0 commit comments

Comments
 (0)