Skip to content

Request #48358 insertBeforeOffset() and insertAfterOffset() methods for ... #288

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 5 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
90 changes: 74 additions & 16 deletions ext/spl/spl_dllist.c
Original file line number Diff line number Diff line change
Expand Up @@ -502,7 +502,7 @@ static int spl_dllist_object_count_elements(zval *object, long *count TSRMLS_DC)

*count = spl_ptr_llist_count(intern->llist);
return SUCCESS;
}
}
/* }}} */

static HashTable* spl_dllist_object_get_debug_info(zval *obj, int *is_temp TSRMLS_DC) /* {{{{ */
Expand Down Expand Up @@ -573,7 +573,7 @@ SPL_METHOD(SplDoublyLinkedList, push)
spl_ptr_llist_push(intern->llist, value TSRMLS_CC);

RETURN_TRUE;
}
}
/* }}} */

/* {{{ proto bool SplDoublyLinkedList::unshift(mixed $value) U
Expand Down Expand Up @@ -616,7 +616,7 @@ SPL_METHOD(SplDoublyLinkedList, pop)
}

RETURN_ZVAL(value, 1, 1);
}
}
/* }}} */

/* {{{ proto mixed SplDoublyLinkedList::shift() U
Expand All @@ -639,7 +639,7 @@ SPL_METHOD(SplDoublyLinkedList, shift)
}

RETURN_ZVAL(value, 1, 1);
}
}
/* }}} */

/* {{{ proto mixed SplDoublyLinkedList::top() U
Expand Down Expand Up @@ -794,7 +794,7 @@ SPL_METHOD(SplDoublyLinkedList, offsetGet)
intern = (spl_dllist_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
index = spl_offset_convert_to_long(zindex TSRMLS_CC);

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

intern = (spl_dllist_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
index = (int)spl_offset_convert_to_long(zindex TSRMLS_CC);
llist = intern->llist;
llist = intern->llist;

if (index < 0 || index >= intern->llist->count) {
if (index < 0 || index >= intern->llist->count) {
zend_throw_exception(spl_ce_OutOfRangeException, "Offset out of range", 0 TSRMLS_CC);
return;
}
Expand Down Expand Up @@ -1048,7 +1048,7 @@ static void spl_dllist_it_move_forward(zend_object_iterator *iter TSRMLS_DC) /*
SPL_METHOD(SplDoublyLinkedList, key)
{
spl_dllist_object *intern = (spl_dllist_object*)zend_object_store_get_object(getThis() TSRMLS_CC);

if (zend_parse_parameters_none() == FAILURE) {
return;
}
Expand All @@ -1062,7 +1062,7 @@ SPL_METHOD(SplDoublyLinkedList, key)
SPL_METHOD(SplDoublyLinkedList, prev)
{
spl_dllist_object *intern = (spl_dllist_object*)zend_object_store_get_object(getThis() TSRMLS_CC);

if (zend_parse_parameters_none() == FAILURE) {
return;
}
Expand All @@ -1076,7 +1076,7 @@ SPL_METHOD(SplDoublyLinkedList, prev)
SPL_METHOD(SplDoublyLinkedList, next)
{
spl_dllist_object *intern = (spl_dllist_object*)zend_object_store_get_object(getThis() TSRMLS_CC);

if (zend_parse_parameters_none() == FAILURE) {
return;
}
Expand All @@ -1090,7 +1090,7 @@ SPL_METHOD(SplDoublyLinkedList, next)
SPL_METHOD(SplDoublyLinkedList, valid)
{
spl_dllist_object *intern = (spl_dllist_object*)zend_object_store_get_object(getThis() TSRMLS_CC);

if (zend_parse_parameters_none() == FAILURE) {
return;
}
Expand All @@ -1104,7 +1104,7 @@ SPL_METHOD(SplDoublyLinkedList, valid)
SPL_METHOD(SplDoublyLinkedList, rewind)
{
spl_dllist_object *intern = (spl_dllist_object*)zend_object_store_get_object(getThis() TSRMLS_CC);

if (zend_parse_parameters_none() == FAILURE) {
return;
}
Expand All @@ -1119,7 +1119,7 @@ SPL_METHOD(SplDoublyLinkedList, current)
{
spl_dllist_object *intern = (spl_dllist_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
spl_ptr_llist_element *element = intern->traverse_pointer;

if (zend_parse_parameters_none() == FAILURE) {
return;
}
Expand All @@ -1139,7 +1139,7 @@ SPL_METHOD(SplDoublyLinkedList, serialize)
spl_dllist_object *intern = (spl_dllist_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
smart_str buf = {0};
spl_ptr_llist_element *current = intern->llist->head, *next;
zval *flags;
zval *flags;
php_serialize_data_t var_hash;

if (zend_parse_parameters_none() == FAILURE) {
Expand Down Expand Up @@ -1174,7 +1174,7 @@ SPL_METHOD(SplDoublyLinkedList, serialize)
} else {
RETURN_NULL();
}

} /* }}} */

/* {{{ proto void SplDoublyLinkedList::unserialize(string serialized)
Expand All @@ -1187,7 +1187,7 @@ SPL_METHOD(SplDoublyLinkedList, unserialize)
int buf_len;
const unsigned char *p, *s;
php_unserialize_data_t var_hash;

if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &buf, &buf_len) == FAILURE) {
return;
}
Expand Down Expand Up @@ -1235,6 +1235,61 @@ SPL_METHOD(SplDoublyLinkedList, unserialize)

} /* }}} */

/* {{{ proto void SplDoublyLinkedList::add(mixed $index, mixed $newval) U
Inserts a new entry before the specified $index consisting of $newval. */
SPL_METHOD(SplDoublyLinkedList, add)
{
zval *zindex, *value;
spl_dllist_object *intern;
spl_ptr_llist_element *element;
long index;

if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "zz", &zindex, &value) == FAILURE) {
return;
}
SEPARATE_ARG_IF_REF(value);

intern = (spl_dllist_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
index = spl_offset_convert_to_long(zindex TSRMLS_CC);

if (index < 0 || index > intern->llist->count) {
zend_throw_exception(spl_ce_OutOfRangeException, "Offset invalid or out of range", 0 TSRMLS_CC);
return;
}

if (index == intern->llist->count) {
/* If index is the last entry+1 then we do a push because we're not inserting before any entry */
spl_ptr_llist_push(intern->llist, value TSRMLS_CC);
} else {
/* Get the element we want to insert before */
element = spl_ptr_llist_offset(intern->llist, index, intern->flags & SPL_DLLIST_IT_LIFO);

/* Create the new element we want to insert */
spl_ptr_llist_element *elem = emalloc(sizeof(spl_ptr_llist_element));

elem->data = value;
elem->rc = 1;
/* connect to the neighbours */
elem->next = element;
elem->prev = element->prev;

/* connect the neighbours to this new element */
if (elem->prev == NULL) {
intern->llist->head = elem;
} else {
element->prev->next = elem;
}
element->prev = elem;

intern->llist->count++;

if (intern->llist->ctor) {
intern->llist->ctor(elem TSRMLS_CC);
}
}
} /* }}} */


/* iterator handler table */
zend_object_iterator_funcs spl_dllist_it_funcs = {
spl_dllist_it_dtor,
Expand Down Expand Up @@ -1322,6 +1377,9 @@ static const zend_function_entry spl_funcs_SplDoublyLinkedList[] = {
SPL_ME(SplDoublyLinkedList, offsetGet, arginfo_dllist_offsetGet, ZEND_ACC_PUBLIC)
SPL_ME(SplDoublyLinkedList, offsetSet, arginfo_dllist_offsetSet, ZEND_ACC_PUBLIC)
SPL_ME(SplDoublyLinkedList, offsetUnset, arginfo_dllist_offsetGet, ZEND_ACC_PUBLIC)

SPL_ME(SplDoublyLinkedList, add, arginfo_dllist_offsetSet, ZEND_ACC_PUBLIC)

/* Iterator */
SPL_ME(SplDoublyLinkedList, rewind, arginfo_dllist_void, ZEND_ACC_PUBLIC)
SPL_ME(SplDoublyLinkedList, current, arginfo_dllist_void, ZEND_ACC_PUBLIC)
Expand Down
13 changes: 13 additions & 0 deletions ext/spl/tests/SplDoublyLinkedList_add_invalid_offset.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
--TEST--
Check that SplDoublyLinkedList::add throws an exception with an invalid offset argument
--FILE--
<?php
try {
$dll = new SplDoublyLinkedList();
var_dump($dll->add(12,'Offset 12 should not exist'));
} catch (OutOfRangeException $e) {
echo "Exception: ".$e->getMessage()."\n";
}
?>
--EXPECTF--
Exception: Offset invalid or out of range
11 changes: 11 additions & 0 deletions ext/spl/tests/SplDoublyLinkedList_add_missing_parameter1.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
--TEST--
Check that SplDoublyLinkedList::add generate a warning and returns a NULL with missing arguments
--FILE--
<?php
$dll = new SplDoublyLinkedList();
var_dump($dll->add());
?>
--EXPECTF--
Warning: SplDoublyLinkedList::add() expects exactly 2 parameters, 0 given in %s on line %d
NULL

11 changes: 11 additions & 0 deletions ext/spl/tests/SplDoublyLinkedList_add_missing_parameter2.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
--TEST--
Check that SplDoublyLinkedList::add generate a warning and returns a NULL with a missing value argument
--FILE--
<?php
$dll = new SplDoublyLinkedList();
var_dump($dll->add(2));
?>
--EXPECTF--
Warning: SplDoublyLinkedList::add() expects exactly 2 parameters, 1 given in %s on line %d
NULL

13 changes: 13 additions & 0 deletions ext/spl/tests/SplDoublyLinkedList_add_null_offset.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
--TEST--
Check that SplDoublyLinkedList::add throws an exception with an invalid offset argument
--FILE--
<?php
try {
$dll = new SplDoublyLinkedList();
var_dump($dll->add(NULL,2));
} catch (OutOfRangeException $e) {
echo "Exception: ".$e->getMessage()."\n";
}
?>
--EXPECTF--
Exception: Offset invalid or out of range
45 changes: 45 additions & 0 deletions ext/spl/tests/dllist_013.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
--TEST--
SPL: DoublyLinkedList: insert operations
--FILE--
<?php
$dll = new SplDoublyLinkedList();
// errors
try {
$dll->add(2,5);
} catch (OutOfRangeException $e) {
echo "Exception: ".$e->getMessage()."\n";
}

$dll->add(0,6); // 6
$dll->add(0,3); // 3 6
// Insert in the middle of the DLL
$dll->add(1,4); // 3 4 6
$dll->add(2,5); // 3 4 5 6
$dll->unshift(2); // 2 3 5 4 6
// Insert at the beginning and end of the DLL
$dll->add(0,1); // 1 2 3 4 5 6
$dll->add(6,7); // 1 2 3 4 5 6 7

echo count($dll)."\n";

echo $dll->pop()."\n";
echo $dll->pop()."\n";
echo $dll->pop()."\n";
echo $dll->pop()."\n";
echo $dll->pop()."\n";
echo $dll->pop()."\n";
echo $dll->pop()."\n";
?>
===DONE===
<?php exit(0); ?>
--EXPECTF--
Exception: Offset invalid or out of range
7
7
6
5
4
3
2
1
===DONE===