[libgee] Add List.first|last|insert_all methods and AbstractList implementations



commit d74a1a126c947026898e7e7446e3ef8b9637a16c
Author: Tomaž Vajngerl <quikee gmail com>
Date:   Sun Jul 26 12:33:49 2009 +0200

    Add List.first|last|insert_all methods and AbstractList implementations
    
    Fixes bug 589894.

 gee/Makefile.am          |    1 +
 gee/abstractlist.vala    |   55 +++++++++++++
 gee/arraylist.vala       |   14 ++--
 gee/linkedlist.vala      |   14 ++--
 gee/list.vala            |   23 +++++
 gee/readonlylist.vala    |   20 +++++
 tests/testarraylist.vala |  201 ++++++++++++++++++++++++++++++++++++++++++++++
 7 files changed, 314 insertions(+), 14 deletions(-)
---
diff --git a/gee/Makefile.am b/gee/Makefile.am
index d46b5ed..9008f23 100644
--- a/gee/Makefile.am
+++ b/gee/Makefile.am
@@ -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
index 0000000..5a4b919
--- /dev/null
+++ b/gee/abstractlist.vala
@@ -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++;
+		}
+	}
+}
diff --git a/gee/arraylist.vala b/gee/arraylist.vala
index 467e8d0..9d8f10b 100644
--- a/gee/arraylist.vala
+++ b/gee/arraylist.vala
@@ -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);
diff --git a/gee/linkedlist.vala b/gee/linkedlist.vala
index 220510c..9e54ac4 100644
--- a/gee/linkedlist.vala
+++ b/gee/linkedlist.vala
@@ -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);
diff --git a/gee/list.vala b/gee/list.vala
index 451e149..479cf4c 100644
--- a/gee/list.vala
+++ b/gee/list.vala
@@ -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);
 }
 
diff --git a/gee/readonlylist.vala b/gee/readonlylist.vala
index eb5bab4..0fc1b55 100644
--- a/gee/readonlylist.vala
+++ b/gee/readonlylist.vala
@@ -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 ();
 	}
diff --git a/tests/testarraylist.vala b/tests/testarraylist.vala
index e842df1..0c79dba 100644
--- a/tests/testarraylist.vala
+++ b/tests/testarraylist.vala
@@ -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) {



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]