Add List.first|last|insert_all methods and AbstractList implementations
authorTomaž Vajngerl <quikee@gmail.com>
Sun, 26 Jul 2009 10:33:49 +0000 (12:33 +0200)
committerDidier 'Ptitjes <ptitjes@free.fr>
Fri, 31 Jul 2009 16:12:10 +0000 (18:12 +0200)
Fixes bug 589894.

gee/Makefile.am
gee/abstractlist.vala [new file with mode: 0644]
gee/arraylist.vala
gee/linkedlist.vala
gee/list.vala
gee/readonlylist.vala
tests/testarraylist.vala

index d46b5ed..9008f23 100644 (file)
@@ -14,6 +14,7 @@ lib_LTLIBRARIES = \
 
 libgee_la_VALASOURCES = \
        abstractcollection.vala \
+       abstractlist.vala \
        arraylist.vala \
        collection.vala \
        functions.vala \
diff --git a/gee/abstractlist.vala b/gee/abstractlist.vala
new file mode 100644 (file)
index 0000000..5a4b919
--- /dev/null
@@ -0,0 +1,55 @@
+/* abstractlist.vala
+ *
+ * Copyright (C) 2007  Jürg Billeter
+ * Copyright (C) 2009  Didier Villevalois
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301  USA
+ *
+ * Author:
+ *     Didier 'Ptitjes' Villevalois <ptitjes@free.fr>
+ */
+
+/**
+ * Serves as the base class for implementing list classes.
+ */
+public abstract class Gee.AbstractList<G> : Gee.AbstractCollection<G>, List<G> {
+
+       public abstract new G? get (int index);
+
+       public abstract new void set (int index, G item);
+
+       public abstract int index_of (G item);
+
+       public abstract void insert (int index, G item);
+
+       public abstract void remove_at (int index);
+
+       public abstract List<G>? slice (int start, int stop);
+
+       public virtual G? first () {
+               return get (0);
+       }
+
+       public virtual G? last () {
+               return get (size - 1);
+       }
+
+       public virtual void insert_all (int index, Collection<G> collection) {
+               foreach (G item in collection) {
+                       insert(index, item);
+                       index++;
+               }
+       }
+}
index 467e8d0..9d8f10b 100644 (file)
@@ -27,7 +27,7 @@ using GLib;
 /**
  * Arrays of arbitrary elements which grow automatically as elements are added.
  */
-public class Gee.ArrayList<G> : AbstractCollection<G>, List<G> {
+public class Gee.ArrayList<G> : AbstractList<G> {
        public override int size {
                get { return _size; }
        }
@@ -52,7 +52,7 @@ public class Gee.ArrayList<G> : AbstractCollection<G>, List<G> {
                return (index_of (item) != -1);
        }
 
-       public int index_of (G item) {
+       public override int index_of (G item) {
                for (int index = 0; index < _size; index++) {
                        if (equal_func (_items[index], item)) {
                                return index;
@@ -61,14 +61,14 @@ public class Gee.ArrayList<G> : AbstractCollection<G>, List<G> {
                return -1;
        }
 
-       public new G? get (int index) {
+       public override G? get (int index) {
                assert (index >= 0);
                assert (index < _size);
 
                return _items[index];
        }
 
-       public new void set (int index, G item) {
+       public override void set (int index, G item) {
                assert (index >= 0);
                assert (index < _size);
 
@@ -84,7 +84,7 @@ public class Gee.ArrayList<G> : AbstractCollection<G>, List<G> {
                return true;
        }
 
-       public void insert (int index, G item) {
+       public override void insert (int index, G item) {
                assert (index >= 0);
                assert (index <= _size);
 
@@ -106,7 +106,7 @@ public class Gee.ArrayList<G> : AbstractCollection<G>, List<G> {
                return false;
        }
 
-       public void remove_at (int index) {
+       public override void remove_at (int index) {
                assert (index >= 0);
                assert (index < _size);
 
@@ -125,7 +125,7 @@ public class Gee.ArrayList<G> : AbstractCollection<G>, List<G> {
                _stamp++;
        }
 
-       public List<G>? slice (int start, int stop) {
+       public override List<G>? slice (int start, int stop) {
                return_val_if_fail (start <= stop, null);
                return_val_if_fail (start >= 0, null);
                return_val_if_fail (stop <= _size, null);
index 220510c..9e54ac4 100644 (file)
@@ -27,7 +27,7 @@
 /**
  * A Gee.List implementation, using a doubly-linked list.
  */
-public class Gee.LinkedList<G> : AbstractCollection<G>, List<G> {
+public class Gee.LinkedList<G> : AbstractList<G> {
        private int _size = 0;
        private int _stamp = 0;
        private Node? _head = null;
@@ -87,7 +87,7 @@ public class Gee.LinkedList<G> : AbstractCollection<G>, List<G> {
        }
 
        // List<G>
-       public new G? get (int index) {
+       public override G? get (int index) {
                assert (index >= 0);
                assert (index < this._size);
 
@@ -99,7 +99,7 @@ public class Gee.LinkedList<G> : AbstractCollection<G>, List<G> {
                }
        }
 
-       public new void set (int index, G item) {
+       public override void set (int index, G item) {
                assert (index >= 0);
                assert (index < this._size);
 
@@ -108,7 +108,7 @@ public class Gee.LinkedList<G> : AbstractCollection<G>, List<G> {
                n.data = item;
        }
 
-       public int index_of (G item) {
+       public override int index_of (G item) {
                int result = -1;
                int idx = 0;
                foreach (G node_item in this) {
@@ -122,7 +122,7 @@ public class Gee.LinkedList<G> : AbstractCollection<G>, List<G> {
                return result;
        }
 
-       public void insert (int index, G item) {
+       public override void insert (int index, G item) {
                assert (index >= 0);
                assert (index <= this._size);
 
@@ -152,7 +152,7 @@ public class Gee.LinkedList<G> : AbstractCollection<G>, List<G> {
                }
        }
 
-       public void remove_at (int index) {
+       public override void remove_at (int index) {
                assert (index >= 0);
                assert (index < this._size);
 
@@ -161,7 +161,7 @@ public class Gee.LinkedList<G> : AbstractCollection<G>, List<G> {
                this._remove_node (n);
        }
 
-       public List<G>? slice (int start, int stop) {
+       public override List<G>? slice (int start, int stop) {
                return_val_if_fail (start <= stop, null);
                return_val_if_fail (start >= 0, null);
                return_val_if_fail (stop <= this._size, null);
index 451e149..479cf4c 100644 (file)
@@ -73,5 +73,28 @@ public interface Gee.List<G> : Collection<G> {
         * @return A list containing a slice of this list
         */
        public abstract List<G>? slice (int start, int stop);
+
+       /**
+        * Returns the first item of the list or null if list is empty.
+        *
+        * @return      first item in the list
+        */
+       public abstract G? first ();
+
+       /**
+        * Returns the last item of the list or null if list is empty.
+        *
+        * @return      last item in the list
+        */
+       public abstract G? last ();
+
+       /**
+        * Inserts items into this list for the input collection at the 
+        * specified position.
+        *
+        * @param index zero-based index of the items to be inserted
+        * @param collection collection of items to be inserted
+        */
+       public abstract void insert_all (int index, Collection<G> collection);
 }
 
index eb5bab4..0fc1b55 100644 (file)
@@ -127,6 +127,26 @@ public class Gee.ReadOnlyList<G> : Object, Iterable<G>, Collection<G>, List<G> {
                assert_not_reached ();
        }
 
+       public G? first () {
+               if (_list == null) {
+                       return null;
+               }
+
+               return _list.first ();
+       }
+
+       public G? last () {
+               if (_list == null) {
+                       return null;
+               }
+
+               return _list.last ();
+       }
+
+       public void insert_all (int index, Collection<G> collection) {
+               assert_not_reached ();
+       }
+
        public G[] to_array() {
                return _list.to_array ();
        }
index e842df1..0c79dba 100644 (file)
@@ -34,6 +34,9 @@ public class ArrayListTests : CollectionTests {
                add_test("insert", test_arraylist_insert);
                add_test("remove_at", test_arraylist_remove_at);
                add_test("index_of", test_arraylist_index_of);
+               add_test ("first", test_arraylist_first);
+               add_test ("last", test_arraylist_last);
+               add_test ("insert_all", test_arraylist_insert_all);
 
                // Methods of Collection interface
                add_test("add", test_arraylist_add);
@@ -931,6 +934,204 @@ public class ArrayListTests : CollectionTests {
                arraylist1.clear ();
                arraylist2.clear ();
        }
+
+       void test_arraylist_first () {
+               var arraylistOfString = new ArrayList<string> ();
+
+               // Check first for empty list
+               if (Test.trap_fork (0, TestTrapFlags.SILENCE_STDOUT | TestTrapFlags.SILENCE_STDERR)) {
+                       arraylistOfString.first ();
+                       return;
+               }
+               Test.trap_assert_failed ();
+
+               // Check first for list with one element
+               arraylistOfString.add ("1");
+               assert (arraylistOfString.first () == "1");
+               assert (arraylistOfString.first () == arraylistOfString.get (0));
+
+               // Check first for for list with multiple element
+               arraylistOfString.add ("2");
+               arraylistOfString.add ("3");
+               assert (arraylistOfString.first () == "1");
+               assert (arraylistOfString.first () == arraylistOfString.get (0));
+
+               // Check first if list is cleared and empty again
+               arraylistOfString.clear ();
+
+               if (Test.trap_fork (0, TestTrapFlags.SILENCE_STDOUT | TestTrapFlags.SILENCE_STDERR)) {
+                       arraylistOfString.first ();
+                       return;
+               }
+               Test.trap_assert_failed ();
+       }
+
+       void test_arraylist_last () {
+               var arraylistOfString = new ArrayList<string> ();
+
+               // Check last for empty list
+               if (Test.trap_fork (0, TestTrapFlags.SILENCE_STDOUT | TestTrapFlags.SILENCE_STDERR)) {
+                       arraylistOfString.last ();
+                       return;
+               }
+               Test.trap_assert_failed ();
+
+               // Check last for list with one element
+               arraylistOfString.add ("1");
+               assert (arraylistOfString.last () == "1");
+               assert (arraylistOfString.last () == arraylistOfString.get (arraylistOfString.size - 1));
+
+               // Check last for for list with multiple element
+               arraylistOfString.add ("2");
+               arraylistOfString.add ("3");
+               assert (arraylistOfString.last () == "3");
+               assert (arraylistOfString.last () == arraylistOfString.get (arraylistOfString.size - 1));
+
+               // Check last if list is cleared and empty again
+               arraylistOfString.clear ();
+
+               if (Test.trap_fork (0, TestTrapFlags.SILENCE_STDOUT | TestTrapFlags.SILENCE_STDERR)) {
+                       arraylistOfString.last ();
+                       return;
+               }
+               Test.trap_assert_failed ();
+       }
+
+       void test_arraylist_insert_all () {
+               var arraylist1 = new ArrayList<int> ();
+               var arraylist2 = new ArrayList<int> ();
+
+               // Insert an empty list
+               arraylist1.add (0);
+               arraylist1.add (1);
+               arraylist1.add (2);
+
+               assert (arraylist1.size == 3);
+               assert (arraylist2.is_empty);
+
+               arraylist1.insert_all (0, arraylist2);
+
+               assert (arraylist1.size == 3);
+               assert (arraylist2.is_empty);
+
+               arraylist1.clear ();
+               arraylist2.clear ();
+
+               // Insert into an empty list at index 0
+               arraylist2.add (0);
+               arraylist2.add (1);
+               arraylist2.add (2);
+
+               assert (arraylist1.is_empty);
+               assert (arraylist2.size == 3);
+
+               arraylist1.insert_all (0, arraylist2);
+
+               assert (arraylist1.size == 3);
+               assert (arraylist2.size == 3);
+
+               arraylist1.clear ();
+               arraylist2.clear ();
+
+               // Insert all into empty list as index 1
+               arraylist2.add (0);
+               arraylist2.add (1);
+               arraylist2.add (2);
+
+               assert (arraylist1.is_empty);
+
+               if (Test.trap_fork (0, TestTrapFlags.SILENCE_STDOUT | TestTrapFlags.SILENCE_STDERR)) {
+                       arraylist1.insert_all (1, arraylist2);
+                       return;
+               }
+               Test.trap_assert_failed ();
+
+               arraylist1.clear ();
+               arraylist2.clear ();
+
+               // Insert all in the beginnig
+               arraylist1.add (3);
+               arraylist1.add (4);
+               arraylist1.add (5);
+
+               arraylist2.add (0);
+               arraylist2.add (1);
+               arraylist2.add (2);
+
+               assert (arraylist1.size == 3);
+               assert (arraylist2.size == 3);
+
+               arraylist1.insert_all (0, arraylist2);
+
+               assert (arraylist1.size == 6);
+               assert (arraylist2.size == 3);
+
+               assert (arraylist1.get (0) == 0);
+               assert (arraylist1.get (1) == 1);
+               assert (arraylist1.get (2) == 2);
+               assert (arraylist1.get (3) == 3);
+               assert (arraylist1.get (4) == 4);
+               assert (arraylist1.get (5) == 5);
+
+               arraylist1.clear ();
+               arraylist2.clear ();
+
+               // Insert all in the middle
+               arraylist1.add (0);
+               arraylist1.add (1);
+               arraylist1.add (5);
+               arraylist1.add (6);
+
+               arraylist2.add (2);
+               arraylist2.add (3);
+               arraylist2.add (4);
+
+               assert (arraylist1.size == 4);
+               assert (arraylist2.size == 3);
+
+               arraylist1.insert_all (2, arraylist2);
+
+               assert (arraylist1.size == 7);
+               assert (arraylist2.size == 3);
+
+               assert (arraylist1.get (0) == 0);
+               assert (arraylist1.get (1) == 1);
+               assert (arraylist1.get (2) == 2);
+               assert (arraylist1.get (3) == 3);
+               assert (arraylist1.get (4) == 4);
+               assert (arraylist1.get (5) == 5);
+               assert (arraylist1.get (6) == 6);
+
+               arraylist1.clear ();
+               arraylist2.clear ();
+
+               // Insert all in at the end
+               arraylist1.add (0);
+               arraylist1.add (1);
+               arraylist1.add (2);
+
+               arraylist2.add (3);
+               arraylist2.add (4);
+               arraylist2.add (5);
+
+               assert (arraylist1.size == 3);
+               assert (arraylist2.size == 3);
+
+               arraylist1.insert_all (3, arraylist2);
+
+               assert (arraylist1.size == 6);
+               assert (arraylist2.size == 3);
+
+               assert (arraylist1.get (0) == 0);
+               assert (arraylist1.get (1) == 1);
+               assert (arraylist1.get (2) == 2);
+               assert (arraylist1.get (3) == 3);
+               assert (arraylist1.get (4) == 4);
+               assert (arraylist1.get (5) == 5);
+
+               arraylist1.clear ();
+               arraylist2.clear ();
+       }
 }
 
 void main (string[] args) {