[libgee] Add Map.is_empty|set_all|remove_all|contains_all and AbstractMap implementations
- From: Didier 'Ptitjes' Villevalois <dvillevalois src gnome org>
- To: svn-commits-list gnome org
- Cc:
- Subject: [libgee] Add Map.is_empty|set_all|remove_all|contains_all and AbstractMap implementations
- Date: Fri, 31 Jul 2009 16:13:39 +0000 (UTC)
commit 539ea0cf401afd44861807f8ad3fc39de31de3a7
Author: Tomaž Vajngerl <quikee gmail com>
Date: Sun Jul 26 12:49:27 2009 +0200
Add Map.is_empty|set_all|remove_all|contains_all and AbstractMap implementations
Fixes bug 589902.
gee/Makefile.am | 1 +
gee/abstractmap.vala | 71 +++++++++++++++
gee/hashmap.vala | 18 ++--
gee/map.vala | 27 ++++++
gee/readonlymap.vala | 20 ++++
gee/treemap.vala | 18 ++--
tests/testhashmap.vala | 232 ++++++++++++++++++++++++++++++++++++++++++++++++
7 files changed, 369 insertions(+), 18 deletions(-)
---
diff --git a/gee/Makefile.am b/gee/Makefile.am
index 9008f23..72f59a6 100644
--- a/gee/Makefile.am
+++ b/gee/Makefile.am
@@ -15,6 +15,7 @@ lib_LTLIBRARIES = \
libgee_la_VALASOURCES = \
abstractcollection.vala \
abstractlist.vala \
+ abstractmap.vala \
arraylist.vala \
collection.vala \
functions.vala \
diff --git a/gee/abstractmap.vala b/gee/abstractmap.vala
new file mode 100644
index 0000000..fb17b2a
--- /dev/null
+++ b/gee/abstractmap.vala
@@ -0,0 +1,71 @@
+/* abstractmap.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:
+ * Tomaž Vajngerl <quikee gmail com>
+ */
+
+ /**
+ * Serves as the base class for implementing map classes.
+ */
+public abstract class Gee.AbstractMap<K,V> : Object, Map<K,V> {
+
+ public abstract int size { get; }
+
+ public virtual bool is_empty {
+ get { return size == 0; }
+ }
+
+ public abstract Set<K> get_keys ();
+
+ public abstract Collection<V> get_values ();
+
+ public abstract bool contains (K key);
+
+ public abstract new V? get (K key);
+
+ public abstract new void set (K key, V value);
+
+ public abstract bool remove (K key);
+
+ public abstract void clear ();
+
+ public virtual void set_all (Map<K,V> map) {
+ foreach (K key in map.get_keys ()) {
+ set (key, map.get (key));
+ }
+ }
+
+ public virtual bool remove_all (Map<K,V> map) {
+ bool changed = false;
+ foreach (K key in map.get_keys ()) {
+ changed = changed | remove (key);
+ }
+ return changed;
+ }
+
+ public virtual bool contains_all (Map<K,V> map) {
+ foreach (K key in map.get_keys ()) {
+ if (!contains (key)) {
+ return false;
+ }
+ }
+ return true;
+ }
+}
diff --git a/gee/hashmap.vala b/gee/hashmap.vala
index 824fae1..8e48328 100644
--- a/gee/hashmap.vala
+++ b/gee/hashmap.vala
@@ -27,8 +27,8 @@ using GLib;
/**
* Hashtable implementation of the Map interface.
*/
-public class Gee.HashMap<K,V> : Object, Map<K,V> {
- public int size {
+public class Gee.HashMap<K,V> : Gee.AbstractMap<K,V> {
+ public override int size {
get { return _nnodes; }
}
@@ -59,11 +59,11 @@ public class Gee.HashMap<K,V> : Object, Map<K,V> {
_nodes = new Node<K,V>[_array_size];
}
- public Set<K> get_keys () {
+ public override Set<K> get_keys () {
return new KeySet<K,V> (this);
}
- public Collection<V> get_values () {
+ public override Collection<V> get_values () {
return new ValueCollection<K,V> (this);
}
@@ -76,12 +76,12 @@ public class Gee.HashMap<K,V> : Object, Map<K,V> {
return node;
}
- public bool contains (K key) {
+ public override bool contains (K key) {
Node<K,V>** node = lookup_node (key);
return (*node != null);
}
- public new V? get (K key) {
+ public override V? get (K key) {
Node<K,V>* node = (*lookup_node (key));
if (node != null) {
return node->value;
@@ -90,7 +90,7 @@ public class Gee.HashMap<K,V> : Object, Map<K,V> {
}
}
- public new void set (K key, V value) {
+ public override void set (K key, V value) {
Node<K,V>** node = lookup_node (key);
if (*node != null) {
(*node)->value = value;
@@ -103,7 +103,7 @@ public class Gee.HashMap<K,V> : Object, Map<K,V> {
_stamp++;
}
- public bool remove (K key) {
+ public override bool remove (K key) {
Node<K,V>** node = lookup_node (key);
if (*node != null) {
Node<K,V> next = (owned) (*node)->next;
@@ -122,7 +122,7 @@ public class Gee.HashMap<K,V> : Object, Map<K,V> {
return false;
}
- public void clear () {
+ public override void clear () {
for (int i = 0; i < _array_size; i++) {
Node<K,V> node = (owned) _nodes[i];
while (node != null) {
diff --git a/gee/map.vala b/gee/map.vala
index 78858ce..9d6996e 100644
--- a/gee/map.vala
+++ b/gee/map.vala
@@ -30,6 +30,11 @@ public interface Gee.Map<K,V> : GLib.Object {
public abstract int size { get; }
/**
+ * Specifies whether this map is empty.
+ */
+ public abstract bool is_empty { get; }
+
+ /**
* Returns the keys of this map as a read-only set.
*
* @return the keys of the map
@@ -84,5 +89,27 @@ public interface Gee.Map<K,V> : GLib.Object {
* read-only collections.
*/
public abstract void clear ();
+
+ /**
+ * Inserts all items that are contained in the input map to this map.
+ *
+ * @param map the map which items are inserted to this map
+ */
+ public abstract void set_all (Map<K,V> map);
+
+ /**
+ * Removes all items from this map that are common to the input map
+ * and this map.
+ *
+ * @param map the map which common items are deleted from this map
+ */
+ public abstract bool remove_all (Map<K,V> map);
+
+ /**
+ * Returns true it this map contains all items as the input map.
+ *
+ * @param map the map which items will be compared with this map.
+ */
+ public abstract bool contains_all (Map<K,V> map);
}
diff --git a/gee/readonlymap.vala b/gee/readonlymap.vala
index de5632b..37d7730 100644
--- a/gee/readonlymap.vala
+++ b/gee/readonlymap.vala
@@ -30,6 +30,10 @@ public class Gee.ReadOnlyMap<K,V> : Object, Map<K,V> {
get { return _map.size; }
}
+ public bool is_empty {
+ get { return _map.is_empty; }
+ }
+
public Map<K,V> map {
construct { _map = value; }
}
@@ -83,5 +87,21 @@ public class Gee.ReadOnlyMap<K,V> : Object, Map<K,V> {
public void clear () {
assert_not_reached ();
}
+
+ public void set_all (Map<K,V> map) {
+ assert_not_reached ();
+ }
+
+ public bool remove_all (Map<K,V> map) {
+ assert_not_reached ();
+ }
+
+ public bool contains_all (Map<K,V> map) {
+ if (_map == null) {
+ return false;
+ }
+
+ return _map.contains_all (map);
+ }
}
diff --git a/gee/treemap.vala b/gee/treemap.vala
index a819153..a9c1806 100644
--- a/gee/treemap.vala
+++ b/gee/treemap.vala
@@ -25,8 +25,8 @@ using GLib;
/**
* Left-leaning red-black tree implementation of the Map interface.
*/
-public class Gee.TreeMap<K,V> : Object, Map<K,V> {
- public int size {
+public class Gee.TreeMap<K,V> : Gee.AbstractMap<K,V> {
+ public override int size {
get { return _size; }
}
@@ -40,11 +40,11 @@ public class Gee.TreeMap<K,V> : Object, Map<K,V> {
this.value_equal_func = value_equal_func;
}
- public Set<K> get_keys () {
+ public override Set<K> get_keys () {
return new KeySet<K,V> (this);
}
- public Collection<V> get_values () {
+ public override Collection<V> get_values () {
return new ValueCollection<K,V> (this);
}
@@ -74,7 +74,7 @@ public class Gee.TreeMap<K,V> : Object, Map<K,V> {
return n == null || n.color == Node.Color.BLACK;
}
- public bool contains (K key) {
+ public override bool contains (K key) {
weak Node<K, V>? cur = root;
while (cur != null) {
int res = key_compare_func (key, cur.key);
@@ -89,7 +89,7 @@ public class Gee.TreeMap<K,V> : Object, Map<K,V> {
return false;
}
- public new V? get (K key) {
+ public override V? get (K key) {
weak Node<K, V>? cur = root;
while (cur != null) {
int res = key_compare_func (key, cur.key);
@@ -129,7 +129,7 @@ public class Gee.TreeMap<K,V> : Object, Map<K,V> {
fix_up (ref node);
}
- public new void set (K key, V value) {
+ public override void set (K key, V value) {
set_to_node (ref root, key, value, null, null);
root.color = Node.Color.BLACK;
}
@@ -219,7 +219,7 @@ public class Gee.TreeMap<K,V> : Object, Map<K,V> {
}
}
- public bool remove (K key) {
+ public override bool remove (K key) {
bool b = remove_from_node (ref root, key);
if (root != null) {
root.color = Node.Color.BLACK;
@@ -228,7 +228,7 @@ public class Gee.TreeMap<K,V> : Object, Map<K,V> {
return b;
}
- public void clear () {
+ public override void clear () {
root = null;
_size = 0;
stamp++;
diff --git a/tests/testhashmap.vala b/tests/testhashmap.vala
index cba44a6..731d931 100644
--- a/tests/testhashmap.vala
+++ b/tests/testhashmap.vala
@@ -297,9 +297,237 @@ void test_hashmap_clear () {
assert (hashmap.size == 0);
}
+void test_hashmap_empty () {
+ var hashmap = new HashMap<string,string> (str_hash, str_equal, str_equal);
+
+ // Check empty map
+ assert (hashmap.is_empty);
+
+ // Check when one item
+ hashmap.set ("1", "1");
+ assert (!hashmap.is_empty);
+
+ // Check when more items
+ hashmap.set ("2", "2");
+ assert (!hashmap.is_empty);
+
+ // Check when items cleared
+ hashmap.clear ();
+ assert (hashmap.is_empty);
+}
+
+void test_hashmap_set_all () {
+ var hashmap1 = new HashMap<string,string> (str_hash, str_equal, str_equal);
+ var hashmap2 = new HashMap<string,string> (str_hash, str_equal, str_equal);
+
+ hashmap1.set ("a", "1");
+ hashmap1.set ("b", "2");
+ hashmap1.set ("c", "3");
+ hashmap2.set ("d", "4");
+ hashmap2.set ("e", "5");
+ hashmap2.set ("f", "6");
+
+ hashmap1.set_all (hashmap2);
+
+ assert (hashmap1.size == 6);
+ assert (hashmap1.contains ("a"));
+ assert (hashmap1.contains ("b"));
+ assert (hashmap1.contains ("c"));
+ assert (hashmap1.contains ("d"));
+ assert (hashmap1.contains ("e"));
+ assert (hashmap1.contains ("f"));
+
+ assert (hashmap1.get ("a") == "1");
+ assert (hashmap1.get ("b") == "2");
+ assert (hashmap1.get ("c") == "3");
+ assert (hashmap1.get ("d") == "4");
+ assert (hashmap1.get ("e") == "5");
+ assert (hashmap1.get ("f") == "6");
+}
+
+void test_hashmap_remove_all () {
+ var map1 = new HashMap<string,string> (str_hash, str_equal, str_equal);
+ var map2 = new HashMap<string,string> (str_hash, str_equal, str_equal);
+
+ // Check remove all on empty maps.
+
+ assert (map1.is_empty);
+ assert (map2.is_empty);
+
+ map1.remove_all (map2);
+
+ assert (map1.is_empty);
+ assert (map2.is_empty);
+
+ map1.clear ();
+ map2.clear ();
+
+ // Map1 is empty, map2 has entries. -> no change
+
+ map2.set ("a", "1");
+ map2.set ("b", "2");
+
+ assert (map1.is_empty);
+ assert (map2.size == 2);
+
+ map1.remove_all (map2);
+
+ assert (map1.is_empty);
+ assert (map2.size == 2);
+
+ map1.clear ();
+ map2.clear ();
+
+ // Map1 has entries, map2 is empty. -> no change
+
+ map1.set ("a", "1");
+ map1.set ("b", "2");
+
+ assert (map1.size == 2);
+ assert (map2.is_empty);
+
+ map1.remove_all (map2);
+
+ assert (map1.size == 2);
+ assert (map2.is_empty);
+
+ map1.clear ();
+ map2.clear ();
+
+ // Map1 and map2 have the same entries -> map1 is cleared
+
+ map1.set ("a", "0");
+ map1.set ("b", "1");
+ map2.set ("a", "1");
+ map2.set ("b", "0");
+
+ assert (map1.size == 2);
+ assert (map2.size == 2);
+
+ map1.remove_all (map2);
+
+ assert (map1.is_empty);
+ assert (map2.size == 2);
+
+ map1.clear ();
+ map2.clear ();
+
+ // Map1 has some common keys with map2 but both have also unique keys -> common key are cleared from map1
+
+ map1.set ("x", "2");
+ map1.set ("a", "1");
+ map1.set ("b", "1");
+ map1.set ("y", "2");
+
+ map2.set ("i", "100");
+ map2.set ("a", "200");
+ map2.set ("j", "300");
+ map2.set ("b", "400");
+ map2.set ("k", "500");
+
+ assert (map1.size == 4);
+ assert (map2.size == 5);
+
+ map1.remove_all (map2);
+
+ assert (map1.size == 2);
+ assert (map2.size == 5);
+
+ assert (map1.contains ("x"));
+ assert (map1.contains ("y"));
+
+ map1.clear ();
+ map2.clear ();
+
+}
+
+void test_hashmap_contains_all() {
+ var map1 = new HashMap<string,string> (str_hash, str_equal, str_equal);
+ var map2 = new HashMap<string,string> (str_hash, str_equal, str_equal);
+
+ // Check empty.
+ assert (map1.contains_all (map2));
+
+ // Map1 has items, map2 is empty.
+
+ map1.set ("1", "1");
+
+ assert (map1.contains_all (map2));
+
+ map1.clear ();
+ map2.clear ();
+
+ // Map1 is empty, map2 has items.
+
+ map2.set ("1", "1");
+
+ assert (!map1.contains_all (map2));
+
+ map1.clear ();
+ map2.clear ();
+
+ // Map1 and map2 are the same.
+
+ map1.set ("1", "a");
+ map1.set ("2", "b");
+
+ map2.set ("1", "c");
+ map2.set ("2", "d");
+
+ assert (map1.contains_all (map2));
+
+ map1.clear ();
+ map2.clear ();
+
+ // Map1 and map2 are not the same
+ map1.set ("1", "a");
+ map2.set ("2", "b");
+
+ assert (!map1.contains_all (map2));
+
+ map1.clear ();
+ map2.clear ();
+
+ // Map1 has a subset of map2
+ map1.set ("1", "a");
+ map1.set ("2", "b");
+ map1.set ("3", "c");
+ map1.set ("4", "d");
+ map1.set ("5", "e");
+ map1.set ("6", "f");
+
+ map2.set ("2", "g");
+ map2.set ("4", "h");
+ map2.set ("6", "i");
+
+ assert (map1.contains_all (map2));
+
+ map1.clear ();
+ map2.clear ();
+
+ // Map1 has a subset of map2 in all but one element map2
+ map1.set ("1", "a");
+ map1.set ("2", "b");
+ map1.set ("3", "c");
+ map1.set ("4", "d");
+ map1.set ("5", "e");
+ map1.set ("6", "f");
+
+ map2.set ("2", "g");
+ map2.set ("4", "h");
+ map2.set ("6", "i");
+ map2.set ("7", "j");
+
+ assert (!map1.contains_all (map2));
+
+ map1.clear ();
+ map2.clear ();
+}
+
void main (string[] args) {
Test.init (ref args);
+ // Methods of Map interface
Test.add_func ("/HashMap/Map/get", test_hashmap_get);
Test.add_func ("/HashMap/Map/set", test_hashmap_set);
Test.add_func ("/HashMap/Map/remove", test_hashmap_remove);
@@ -308,6 +536,10 @@ void main (string[] args) {
Test.add_func ("/HashMap/Map/get_keys", test_hashmap_get_keys);
Test.add_func ("/HashMap/Map/get_values", test_hashmap_get_values);
Test.add_func ("/HashMap/Map/clear", test_hashmap_clear);
+ Test.add_func ("/HashMap/Map/empty", test_hashmap_empty);
+ Test.add_func ("/HashMap/Map/set_all", test_hashmap_set_all);
+ Test.add_func ("/HashMap/Map/remove_all", test_hashmap_remove_all);
+ Test.add_func ("/HashMap/Map/contains_all", test_hashmap_contains_all);
Test.run ();
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]