Last active
December 31, 2015 17:09
-
-
Save chazomaticus/8018276 to your computer and use it in GitHub Desktop.
Iterable class from Geary, touched up a bit to stand alone
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* 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 { | |
/** | |
* Take a Gee object and return a Geary.Iterable for convenience. | |
*/ | |
public Geary.Iterable<G> traverse<G>(Gee.Iterable<G> i) { | |
return new Geary.Iterable<G>(i.iterator()); | |
} | |
/** | |
* Take some non-null items (all must be of type G) and return a | |
* Geary.Iterable for convenience. | |
*/ | |
public Geary.Iterable<G> iterate<G>(G g, ...) { | |
va_list args = va_list(); | |
G arg = g; | |
Gee.ArrayList<G> list = new Gee.ArrayList<G>(); | |
do { | |
list.add(arg); | |
} while ((arg = args.arg()) != null); | |
return Geary.traverse<G>(list); | |
} | |
/** | |
* Take an array of items and return a Geary.Iterable for convenience. | |
*/ | |
public Geary.Iterable<G> iterate_array<G>(G[] a) { | |
return Geary.traverse<G>(new Gee.ArrayList<G>.wrap(a)); | |
} | |
} | |
/** | |
* 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 still | |
* works in foreach. | |
*/ | |
public class Geary.Iterable<G> : Object { | |
/** | |
* A private class that lets us take a Geary.Iterable and convert it back | |
* into a Gee.Iterable. | |
*/ | |
private class GeeIterable<G> | |
: Gee.Traversable<G>, Gee.Iterable<G>, Object { | |
private Gee.Iterator<G> i; | |
public GeeIterable(Gee.Iterator<G> iterator) { | |
i = iterator; | |
} | |
public Gee.Iterator<G> iterator() { | |
return i; | |
} | |
// Unfortunately necessary for Gee.Traversable. | |
public virtual bool @foreach(Gee.ForallFunc<G> f) { | |
foreach (G g in this) { | |
if (!f(g)) | |
return false; | |
} | |
return true; | |
} | |
} | |
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, (owned) seed)); | |
} | |
public Iterable<G> filter(owned Gee.Predicate<G> f) { | |
return new Iterable<G>(i.filter((owned) f)); | |
} | |
public Iterable<G> chop(int offset, int length = -1) { | |
return new Iterable<G>(i.chop(offset, length)); | |
} | |
public Iterable<A> map_nonnull<A>(Gee.MapFunc<A, G> f) { | |
return new Iterable<A>(i.map<A>(f).filter(g => g != null)); | |
} | |
/** | |
* Return only objects of the destination type, as the destination type. | |
* Only works on types derived from Object. | |
*/ | |
public Iterable<A> cast_object<A>() { | |
return new Iterable<A>( | |
// This would be a lot simpler if valac didn't barf on the | |
// shorter, more obvious syntax for each of these delegates. | |
i.filter(g => ((Object) g).get_type().is_a(typeof(A))) | |
.map<A>(g => { return (A) g; })); | |
} | |
public G? first() { | |
foreach (G g in this) | |
return g; | |
return null; | |
} | |
public G? first_matching(Gee.Predicate<G> f) { | |
foreach (G g in this) { | |
if (f(g)) | |
return g; | |
} | |
return null; | |
} | |
public bool any(Gee.Predicate<G> f) { | |
foreach (G g in this) { | |
if (f(g)) | |
return true; | |
} | |
return false; | |
} | |
public bool all(Gee.Predicate<G> f) { | |
foreach (G g in this) { | |
if (!f(g)) | |
return false; | |
} | |
return true; | |
} | |
public int count_matching(Gee.Predicate<G> f) { | |
int count = 0; | |
foreach (G g in this) { | |
if (f(g)) | |
count++; | |
} | |
return count; | |
} | |
/** | |
* The resulting Gee.Iterable comes with the same caveat that you may only | |
* iterate over it once. | |
*/ | |
public Gee.Iterable<G> to_gee_iterable() { | |
return new GeeIterable<G>(i); | |
} | |
public Gee.Collection<G> add_all_to(Gee.Collection<G> c) { | |
foreach (G g in this) | |
c.add(g); | |
return c; | |
} | |
public Gee.ArrayList<G> to_array_list( | |
owned Gee.EqualDataFunc<G>? equal_func = null) { | |
Gee.ArrayList<G> c = new Gee.ArrayList<G>((owned) equal_func); | |
add_all_to(c); | |
return c; | |
} | |
public Gee.LinkedList<G> to_linked_list( | |
owned Gee.EqualDataFunc<G>? equal_func = null) { | |
Gee.LinkedList<G> c = new Gee.LinkedList<G>((owned) 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>( | |
(owned) hash_func, (owned) 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>((owned) compare_func); | |
add_all_to(c); | |
return c; | |
} | |
public Gee.Map<K, G> add_all_to_map<K>( | |
Gee.Map<K, G> m, | |
Gee.MapFunc<K, G> key_func) { | |
foreach (G g in this) | |
m.@set(key_func(g), g); | |
return m; | |
} | |
public Gee.HashMap<K, G> to_hash_map<K>( | |
Gee.MapFunc<K, G> key_func, | |
owned Gee.HashDataFunc<K>? key_hash_func = null, | |
owned Gee.EqualDataFunc<K>? key_equal_func = null, | |
owned Gee.EqualDataFunc<G>? value_equal_func = null) { | |
Gee.HashMap<K, G> c = new Gee.HashMap<K, G>( | |
(owned) key_hash_func, | |
(owned) key_equal_func, | |
(owned) value_equal_func); | |
add_all_to_map<K>(c, key_func); | |
return c; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
See http://blog.chazomatic.us/2014/01/18/better-collections-in-vala/ for more information.