From: Maciej Piechotka Date: Mon, 14 Sep 2009 18:09:43 +0000 (+0200) Subject: Introduce the BidirIterator interface X-Git-Tag: LIBGEE_0_5_0~48 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=968fca3ccf9151f573e5d559bf0dc79c011b7d8a;p=platform%2Fupstream%2Flibgee.git Introduce the BidirIterator interface --- diff --git a/gee/Makefile.am b/gee/Makefile.am index 15e13a4..4a899b0 100644 --- a/gee/Makefile.am +++ b/gee/Makefile.am @@ -20,6 +20,7 @@ libgee_la_VALASOURCES = \ abstractqueue.vala \ abstractset.vala \ arraylist.vala \ + bidiriterator.vala \ collection.vala \ deque.vala \ functions.vala \ diff --git a/gee/bidiriterator.vala b/gee/bidiriterator.vala new file mode 100644 index 0000000..070dd06 --- /dev/null +++ b/gee/bidiriterator.vala @@ -0,0 +1,47 @@ +/* bidiriterator.vala + * + * Copyright (C) 2009 Didier Villevalois, Maciej Piechotka + * + * 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: + * Maciej Piechotka + */ + +/** + * A bi-directional iterator. + */ +public interface Gee.BidirIterator : Gee.Iterator { + /** + * Rewinds to the previous element in the iteration. + * + * @return true if the iterator has a previous element + */ + public abstract bool previous (); + + /** + * Checks whether there is a previous element in the iteration. + * + * @return true if the iterator has a previous element + */ + public abstract bool has_previous (); + + /** + * Advances to the last element in the iteration. + * + * @return true if the iterator has a last element + */ + public abstract bool last (); +} diff --git a/gee/treemap.vala b/gee/treemap.vala index 4cb41e8..a9d7fef 100644 --- a/gee/treemap.vala +++ b/gee/treemap.vala @@ -151,6 +151,9 @@ public class Gee.TreeMap : Gee.AbstractMap { if (prev == null) { first = node; } + if (next == null) { + last = node; + } _size++; } @@ -208,6 +211,8 @@ public class Gee.TreeMap : Gee.AbstractMap { } if (n.next != null) { n.next.prev = n.prev; + } else { + last = n.next; } node = null; _size--; @@ -354,6 +359,7 @@ public class Gee.TreeMap : Gee.AbstractMap { private Node? root = null; private weak Node? first = null; + private weak Node? last = null; private int stamp = 0; private class KeySet : AbstractSet { @@ -450,7 +456,7 @@ public class Gee.TreeMap : Gee.AbstractMap { } } - private class KeyIterator : Object, Gee.Iterator { + private class KeyIterator : Object, Gee.Iterator, BidirIterator { public TreeMap map { private set { _map = value; @@ -490,6 +496,29 @@ public class Gee.TreeMap : Gee.AbstractMap { return current != null; // on false it is null anyway } + public bool previous () { + assert (stamp == _map.stamp); + if (current != null) { + current = current.prev; + } else if (state == KeyIterator.State.PAST_THE_END) { + current = _map.last; + } + state = KeyIterator.State.BEFORE_THE_BEGIN; + return current != null; + } + + public bool has_previous () { + assert (stamp == _map.stamp); + return (current == null && state == KeyIterator.State.PAST_THE_END) || + (current != null && current.prev != null); + } + + public bool last () { + assert (stamp == _map.stamp); + current = _map.last; + return current != null; // on false it is null anyway + } + public new K get () { assert (stamp == _map.stamp); assert (current != null); @@ -509,7 +538,7 @@ public class Gee.TreeMap : Gee.AbstractMap { private bool run = false; } - private class ValueIterator : Object, Gee.Iterator { + private class ValueIterator : Object, Gee.Iterator, Gee.BidirIterator { public TreeMap map { private set { _map = value; @@ -549,6 +578,29 @@ public class Gee.TreeMap : Gee.AbstractMap { return current != null; // on false it is null anyway } + public bool previous () { + assert (stamp == _map.stamp); + if (current != null) { + current = current.prev; + } else if (state == ValueIterator.State.PAST_THE_END) { + current = _map.last; + } + state = ValueIterator.State.BEFORE_THE_BEGIN; + return current != null; + } + + public bool has_previous () { + assert (stamp == _map.stamp); + return (current == null && state == ValueIterator.State.PAST_THE_END) || + (current != null && current.prev != null); + } + + public bool last () { + assert (stamp == _map.stamp); + current = _map.last; + return current != null; // on false it is null anyway + } + public new V get () { assert (stamp == _map.stamp); assert (current != null); diff --git a/gee/treeset.vala b/gee/treeset.vala index 6b13e78..be49d62 100644 --- a/gee/treeset.vala +++ b/gee/treeset.vala @@ -119,6 +119,9 @@ public class Gee.TreeSet : AbstractSet { if (prev == null) { first = node; } + if (next == null) { + last = node; + } _size++; return true; } @@ -182,6 +185,8 @@ public class Gee.TreeSet : AbstractSet { } if (n.next != null) { n.next.prev = n.prev; + } else { + last = n.prev; } node = null; _size--; @@ -269,6 +274,13 @@ public class Gee.TreeSet : AbstractSet { return new Iterator (this); } + /** + * @inheritDoc + */ + public BidirIterator bidir_iterator () { + return new Iterator (this); + } + [Compact] private class Node { public enum Color { @@ -315,7 +327,7 @@ public class Gee.TreeSet : AbstractSet { public weak Node? next; } - private class Iterator : Object, Gee.Iterator { + private class Iterator : Object, Gee.Iterator, BidirIterator { public new TreeSet set { private set { _set = value; @@ -371,6 +383,45 @@ public class Gee.TreeSet : AbstractSet { return current != null; // on false it is null anyway } + public bool previous () { + assert (stamp == _set.stamp); + if (current != null) { + current = current.prev; + } else { + switch (state) { + case Iterator.State.BEFORE_THE_BEGIN: + break; + case Iterator.State.NORMAL: // After remove + current = _prev; + _next = null; + _prev = null; + break; + case Iterator.State.PAST_THE_END: + current = _set.last; + break; + default: + assert_not_reached (); + } + } + state = current != null ? Iterator.State.NORMAL : Iterator.State.BEFORE_THE_BEGIN; + return current != null; + } + + public bool has_previous () { + assert (stamp == _set.stamp); + return (current == null && state == Iterator.State.PAST_THE_END) || + (current == null && state == Iterator.State.NORMAL && _prev != null) || + (current != null && current.prev != null); + } + + public bool last () { + assert (stamp == _set.stamp); + current = _set.last; + _next = null; + _prev = null; + return current != null; // on false it is null anyway + } + public new G get () { assert (stamp == _set.stamp); assert (current != null); @@ -401,5 +452,6 @@ public class Gee.TreeSet : AbstractSet { private Node? root = null; private weak Node? first = null; + private weak Node? last = null; private int stamp = 0; }