[folks] Implement an Iterator for LinkedHashSet



commit 61ed5af3594831015fd52cf4c548ff1840ec334f
Author: Philip Withnall <philip withnall collabora co uk>
Date:   Thu Mar 24 12:31:42 2011 +0000

    Implement an Iterator for LinkedHashSet
    
    In order to ensure that calling Iterator.remove() on an iterator returned by
    LinkedHashSet.iterator() actually removes the item from both the linked list
    and hash set in the LinkedHashSet, we have to subclass Iterator ourselves.
    
    This means that all the LinkedHashSet tests pass once more.
    
    Closes: bgo#645684

 NEWS                       |    3 ++
 folks/linked-hash-set.vala |   77 ++++++++++++++++++++++++++++++++++++++++++-
 2 files changed, 78 insertions(+), 2 deletions(-)
---
diff --git a/NEWS b/NEWS
index 18943a0..7d79285 100644
--- a/NEWS
+++ b/NEWS
@@ -6,9 +6,12 @@ Bugs fixed:
 * Bug 647562 â?? Don't crash on duplicate group channels
 * Bug 647121 â?? Crash in individual_store_contact_sort at
   empathy-individual-store.c line 1387
+* Bug 645684 â?? Implement Iterator on LinkedHashSet
 
 API changes:
 * LinkedHashSet.list_iterator() is now disallowed (causes an assertion failure)
+* LinkedHashSet.iterator() now returns a BidirIterator instead of just an
+  Iterator
 
 Overview of changes from libfolks 0.4.0 to libfolks 0.5.0
 =========================================================
diff --git a/folks/linked-hash-set.vala b/folks/linked-hash-set.vala
index ab1c8ba..3098ec8 100644
--- a/folks/linked-hash-set.vala
+++ b/folks/linked-hash-set.vala
@@ -276,7 +276,8 @@ public class Folks.LinkedHashSet<G> : AbstractList<G>,
 
 
   /**
-   * Returns the Iterator for this structure.
+   * Returns the Iterator for this structure. The iterator supports
+   * bi-directional iteration.
    *
    * @return a { link Gee.Iterator} that can be used for iteration over this
    * structure.
@@ -286,7 +287,7 @@ public class Folks.LinkedHashSet<G> : AbstractList<G>,
    */
   public override Gee.Iterator<G> iterator ()
   {
-    return this._linked_list.iterator ();
+    return new Iterator<G> (this);
   }
 
   /**
@@ -301,4 +302,76 @@ public class Folks.LinkedHashSet<G> : AbstractList<G>,
   {
     assert_not_reached ();
   }
+
+
+  private class Iterator<G> : Object, Gee.Iterator<G>, BidirIterator<G>
+  {
+    private LinkedHashSet<G> _linked_hash_set;
+    private BidirIterator<G> _list_iterator;
+    private int _stamp;
+
+    public Iterator (LinkedHashSet<G> linked_hash_set)
+      {
+        this._linked_hash_set = linked_hash_set;
+        this._stamp = linked_hash_set._stamp;
+        this._list_iterator = linked_hash_set._linked_list.list_iterator ();
+      }
+
+    public bool next ()
+      {
+        assert (this._stamp == this._linked_hash_set._stamp);
+        return this._list_iterator.next ();
+      }
+
+    public bool has_next ()
+      {
+        assert (this._stamp == this._linked_hash_set._stamp);
+        return this._list_iterator.has_next ();
+      }
+
+    public bool first ()
+      {
+        assert (this._stamp == this._linked_hash_set._stamp);
+        return this._list_iterator.first ();
+      }
+
+    public bool previous ()
+      {
+        assert (this._stamp == this._linked_hash_set._stamp);
+        return this._list_iterator.previous ();
+      }
+
+    public bool has_previous ()
+      {
+        assert (this._stamp == this._linked_hash_set._stamp);
+        return this._list_iterator.has_previous ();
+      }
+
+    public bool last ()
+      {
+        assert (this._stamp == this._linked_hash_set._stamp);
+        return this._list_iterator.last ();
+      }
+
+    public new G? get ()
+      {
+        assert (this._stamp == this._linked_hash_set._stamp);
+        return this._list_iterator.get ();
+      }
+
+    public void remove ()
+      {
+        assert (this._stamp == this._linked_hash_set._stamp);
+
+        /* Remove the entry from the linked list *and* the hash set.
+         * Note that we can't do this by calling this._linked_hash_set.remove(),
+         * as that would change the LinkedHashSet's stamp. Removing the item
+         * from the hash set doesn't disrupt the iteration, as it's iterating
+         * over the linked list.*/
+        var item = this.get ();
+
+        this._list_iterator.remove ();
+        this._linked_hash_set._hash_set.remove (item);
+      }
+  }
 }



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