]> granicus.if.org Git - php/commitdiff
Fix #48358 add() method for SplDoublyLinkedLis
authorMark Baker <mbaker@inviqa.com>
Mon, 18 Mar 2013 21:01:42 +0000 (22:01 +0100)
committerDavid Soria Parra <dsp@php.net>
Tue, 19 Mar 2013 13:46:21 +0000 (14:46 +0100)
NEWS
ext/spl/spl_dllist.c
ext/spl/tests/SplDoublyLinkedList_add_invalid_offset.phpt [new file with mode: 0644]
ext/spl/tests/SplDoublyLinkedList_add_missing_parameter1.phpt [new file with mode: 0644]
ext/spl/tests/SplDoublyLinkedList_add_missing_parameter2.phpt [new file with mode: 0644]
ext/spl/tests/SplDoublyLinkedList_add_null_offset.phpt [new file with mode: 0644]
ext/spl/tests/dllist_013.phpt [new file with mode: 0644]

diff --git a/NEWS b/NEWS
index 2ea5117f8d5bae67dda4131c81bf5d481aee76b4..805a40d3294b2e2cb16df0cc7e97bda61bb2da6e 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -22,6 +22,10 @@ PHP                                                                        NEWS
     (Gustavo, Derick, Anatol)
   . Fixed bug #62852 (Unserialize Invalid Date causes crash). (Anatol)
 
+- SPL:
+  . Implement FR #48358 (Add SplDoublyLinkedList::add() to insert an element
+    at a given offset). (Mark Baker, David Soria Parra)
+
 07 Mar 2013, PHP 5.5.0 Alpha 6
 
 - Core:
index a7f15d00e8c202e25605b4426b0743e81afba29a..3ac22010fced2c21dbde4fe81b6c502834ee1c9e 100644 (file)
@@ -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;
        }
@@ -881,9 +881,9 @@ SPL_METHOD(SplDoublyLinkedList, offsetUnset)
 
        intern = (spl_dllist_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
        index  = 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;
        }
@@ -1138,7 +1138,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) {
@@ -1234,6 +1234,61 @@ error:
 
 } /* }}} */
 
+/* {{{ 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,
@@ -1321,6 +1376,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)
diff --git a/ext/spl/tests/SplDoublyLinkedList_add_invalid_offset.phpt b/ext/spl/tests/SplDoublyLinkedList_add_invalid_offset.phpt
new file mode 100644 (file)
index 0000000..b94b067
--- /dev/null
@@ -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
diff --git a/ext/spl/tests/SplDoublyLinkedList_add_missing_parameter1.phpt b/ext/spl/tests/SplDoublyLinkedList_add_missing_parameter1.phpt
new file mode 100644 (file)
index 0000000..12cfe40
--- /dev/null
@@ -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
+
diff --git a/ext/spl/tests/SplDoublyLinkedList_add_missing_parameter2.phpt b/ext/spl/tests/SplDoublyLinkedList_add_missing_parameter2.phpt
new file mode 100644 (file)
index 0000000..c9c3193
--- /dev/null
@@ -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
+
diff --git a/ext/spl/tests/SplDoublyLinkedList_add_null_offset.phpt b/ext/spl/tests/SplDoublyLinkedList_add_null_offset.phpt
new file mode 100644 (file)
index 0000000..396f89b
--- /dev/null
@@ -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
diff --git a/ext/spl/tests/dllist_013.phpt b/ext/spl/tests/dllist_013.phpt
new file mode 100644 (file)
index 0000000..b60f063
--- /dev/null
@@ -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===