[geary/wip/713891-traversable: 1/12] Basic implementation of Traversable->Iterable bridge
- From: Charles Lindsay <clindsay src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [geary/wip/713891-traversable: 1/12] Basic implementation of Traversable->Iterable bridge
- Date: Thu, 12 Dec 2013 02:57:36 +0000 (UTC)
commit 3be7756a24b4368581ccb3a1624f17edbff31083
Author: Charles Lindsay <chaz yorba org>
Date: Fri Dec 6 14:35:49 2013 -0800
Basic implementation of Traversable->Iterable bridge
This includes a few handy features I already know we'll need, but only a
handful. More should be added as necessary.
src/CMakeLists.txt | 1 +
src/engine/util/util-traversable.vala | 208 +++++++++++++++++++++++++++++++++
2 files changed, 209 insertions(+), 0 deletions(-)
---
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index bfc9c5d..7ee7572 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -286,6 +286,7 @@ engine/util/util-stream.vala
engine/util/util-string.vala
engine/util/util-synchronization.vala
engine/util/util-time.vala
+engine/util/util-traversable.vala
engine/util/util-trillian.vala
)
diff --git a/src/engine/util/util-traversable.vala b/src/engine/util/util-traversable.vala
new file mode 100644
index 0000000..b4889ff
--- /dev/null
+++ b/src/engine/util/util-traversable.vala
@@ -0,0 +1,208 @@
+/* Copyright 2013 Yorba Foundation
+ *
+ * This software is licensed under the GNU Lesser General Public License
+ * (version 2.1 or later). See the COPYING file in this distribution.
+ */
+
+namespace Geary {
+ public Geary.Traversable.Iterable<G> traverse<G>(Gee.Iterable<G> i) {
+ return new Geary.Traversable.Iterable<G>(i.iterator());
+ }
+}
+
+namespace Geary.Traversable {
+
+/**
+ * An Iterable that simply wraps an existing Iterator. You get one iteration,
+ * and only one iteration. Basically every method triggers one iteration and
+ * returns a new object.
+ *
+ * Note that this can't inherit from Gee.Iterable because its interface
+ * requires that map/filter/etc. return Iterators, not Iterables. It should
+ * still work in foreach.
+ */
+public class Iterable<G> : BaseObject {
+ private Gee.Iterator<G> i;
+
+ public Iterable(Gee.Iterator<G> iterator) {
+ i = iterator;
+ }
+
+ public virtual Gee.Iterator<G> iterator() {
+ return i;
+ }
+
+ public Iterable<A> map<A>(Gee.MapFunc<A, G> f) {
+ return new Iterable<A>(i.map<A>(f));
+ }
+
+ public Iterable<A> scan<A>(Gee.FoldFunc<A, G> f, owned A seed) {
+ return new Iterable<A>(i.scan<A>(f, seed));
+ }
+
+ public Iterable<G> filter(owned Gee.Predicate<G> f) {
+ return new Iterable<G>(i.filter(f));
+ }
+
+ public Iterable<G> chop(int offset, int length = -1) {
+ return new Iterable<G>(i.chop(offset, length));
+ }
+
+ public Iterable<G> filter_null() {
+ return new Iterable<G>(i.filter(x => x != null));
+ }
+
+ public Iterable<A> cast<A>() {
+ return new Iterable<G>(
+ // This would be a lot simpler if valac didn't barf on the shorter,
+ // more obvious syntax for each of these delegates here.
+ i.filter(x => ((Object) x).get_type().is_a(typeof(A)))
+ .map<A>(x => { return (A) x; }));
+ }
+
+ public Collection<G> to_collection(owned Gee.EqualDataFunc<G>? equal_func = null) {
+ return new Collection<G>(i, equal_func);
+ }
+
+ public Gee.Collection<G> add_all_to(Gee.Collection<G> c) {
+ while (i.next())
+ c.add(i get());
+ return c;
+ }
+
+ public Gee.ArrayList<G> to_array_list(owned Gee.EqualDataFunc<G>? equal_func = null) {
+ Gee.ArrayList<G> c = new Gee.ArrayList<G>(equal_func);
+ add_all_to(c);
+ return c;
+ }
+
+ public Gee.HashSet<G> to_hash_set(owned Gee.HashDataFunc<G>? hash_func = null,
+ owned Gee.EqualDataFunc<G>? equal_func = null) {
+ Gee.HashSet<G> c = new Gee.HashSet<G>(hash_func, equal_func);
+ add_all_to(c);
+ return c;
+ }
+
+ public Gee.TreeSet<G> to_tree_set(owned CompareDataFunc<G>? compare_func = null) {
+ Gee.TreeSet<G> c = new Gee.TreeSet<G>(compare_func);
+ add_all_to(c);
+ return c;
+ }
+}
+
+/**
+ * A Collection that lazily gets and caches results from an existing Iterator.
+ * Will iterate over the given Iterator at most once.
+ */
+public class Collection<G> : Gee.AbstractCollection<G> {
+ private class Iterator<G> : BaseObject, Gee.Iterator<G>, Gee.Traversable<G> {
+ private Collection<G> collection;
+ private int cache_index = -1;
+
+ public virtual bool valid { get { return cache_index >= 0; } }
+ public virtual bool read_only { get { return true; } }
+
+ public Iterator(Collection<G> collection) {
+ this.collection = collection;
+ }
+
+ private void warn_read_only() {
+ warning("%s is read-only", get_type().name());
+ }
+
+ public virtual bool next() {
+ bool _has_next = has_next();
+ if (_has_next)
+ ++cache_index;
+ return _has_next;
+ }
+
+ public virtual bool has_next() {
+ if (cache_index + 1 >= collection.cache.size)
+ return collection.cache_next();
+ return true;
+ }
+
+ public new virtual G @get() {
+ return collection cache get(cache_index);
+ }
+
+ public virtual void remove() {
+ warn_read_only();
+ }
+
+ // For Gee.Traversable.
+ public virtual bool @foreach(Gee.ForallFunc<G> f) {
+ foreach (G item in collection) {
+ if (!f(item))
+ return false;
+ }
+ return true;
+ }
+ }
+
+ private Gee.Iterator<G> source;
+ private Gee.ArrayList<G> cache;
+
+ public override int size { get { cache_all(); return cache.size; } }
+ public override bool read_only { get { return true; } }
+
+ public Collection(Gee.Iterator<G> iterator, owned Gee.EqualDataFunc<G>? equal_func = null) {
+ base();
+
+ source = iterator;
+ cache = new Gee.ArrayList<G>((owned) equal_func);
+ }
+
+ private bool cache_next(out G element = null) {
+ if (source.next()) {
+ cache.add(element = source get());
+ return true;
+ }
+ element = null;
+ return false;
+ }
+
+ private void cache_all() {
+ while (cache_next()) {
+ // Nothing.
+ }
+ }
+
+ private void warn_read_only() {
+ warning("%s is read-only", get_type().name());
+ }
+
+ public override bool contains(G item) {
+ if (cache.contains(item))
+ return true;
+
+ G test;
+ while (cache_next(out test)) {
+ if (cache.equal_func(test, item))
+ return true;
+ }
+
+ return false;
+ }
+
+ public override bool add(G item) {
+ warn_read_only();
+ return false;
+ }
+
+ public override bool remove(G item) {
+ warn_read_only();
+ return false;
+ }
+
+ public override void clear() {
+ warn_read_only();
+ }
+
+ public override Gee.Iterator<G> iterator() {
+ return new Iterator<G>(this);
+ }
+}
+
+}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]