--- /dev/null
+/* streamiterator.vala
+ *
+ * Copyright (C) 2011-2012 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 <uzytkownik2@gmail.com>
+ */
+
+internal class Gee.StreamIterator<A, G> : GLib.Object, Traversable<A>, Iterator<A> {
+ public StreamIterator (Iterator<G> outer, owned StreamFunc<A, G> func) {
+ _outer = outer;
+ _func = (owned)func;
+ _current = null;
+ _need_next = true;
+ _finished = false;
+
+ _state = _func (Traversable.Stream.YIELD, null, out _current);
+ switch (_state) {
+ case Traversable.Stream.WAIT:
+ case Traversable.Stream.YIELD:
+ _need_next = !_outer.valid;
+ break;
+ case Traversable.Stream.CONTINUE:
+ if (_outer.valid) {
+ _state = _func (_state, new Lazy<G> (() => {return _outer.get ();}), out _current);
+ switch (_state) {
+ case Traversable.Stream.YIELD:
+ case Traversable.Stream.CONTINUE:
+ case Traversable.Stream.WAIT:
+ break;
+ case Traversable.Stream.END:
+ _finished = true;
+ return;
+ default:
+ assert_not_reached ();
+ }
+ }
+ break;
+ case Traversable.Stream.END:
+ _finished = true;
+ return;
+ }
+ }
+
+ public bool foreach (ForallFunc<A> f) {
+ Lazy<G>? current = null;
+ if (_current != null) {
+ if (!f (_current.value)) {
+ return false;
+ }
+ }
+ if (_next != null) {
+ current = (owned)_next;
+ if (!f (current.value)) {
+ return false;
+ }
+ } else if (_finished) {
+ return true;
+ }
+ unowned Iterator<G> outer = _outer;
+ StreamFunc<A, G> func = _func;
+ Traversable.Stream state = _state;
+ bool need_next = _need_next;
+ bool result = true;
+ Lazy<G>? next_current;
+ while ((next_current = yield_next<A, G>(outer, func, ref state, ref need_next)) != null) {
+ current = (owned)next_current;
+ if (!f (current.value)) {
+ result = false;
+ break;
+ }
+ }
+ _state = state;
+ _need_next = need_next;
+ _finished = result;
+ _current = (owned)current;
+ return result;
+ }
+
+ public bool next () {
+ if (has_next ()) {
+ _current = (owned)_next;
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ public bool has_next () {
+ if (_finished) {
+ return false;
+ }
+ if (_next != null) {
+ return true;
+ }
+ _next = yield_next<A, G> (_outer, _func, ref _state, ref _need_next);
+ _finished = _next == null;
+ return !_finished;
+ }
+
+ public new A get () {
+ assert (_current != null);
+ return _current.value;
+ }
+
+ public void remove () {
+ assert_not_reached ();
+ }
+
+ public bool valid { get { return _current != null; } }
+ public bool read_only { get { return true; } }
+
+ private static inline Lazy<A>? yield_next<A, G> (Iterator<G> outer, StreamFunc<A, G> func, ref Traversable.Stream state, ref bool need_next) {
+ Lazy<A>? value = null;
+ if (state != Traversable.Stream.CONTINUE)
+ state = func (state, null, out value);
+ while (true) {
+ switch (state) {
+ case Traversable.Stream.YIELD:
+ return value;
+ case Traversable.Stream.CONTINUE:
+ if (need_next) {
+ if (!outer.next ()) {
+ state = func (Traversable.Stream.END, null, out value);
+ continue;
+ }
+ } else {
+ need_next = true;
+ }
+ state = func (state, new Lazy<G> (() => {return outer.get ();}), out value);
+ break;
+ case Traversable.Stream.WAIT:
+ state = func (state, null, out value);
+ break;
+ case Traversable.Stream.END:
+ return null;
+ default:
+ assert_not_reached ();
+ }
+ }
+ }
+
+ private Iterator<G> _outer;
+ private StreamFunc<A, G> _func;
+ private Lazy<A>? _current;
+ private Lazy<A>? _next;
+ private Traversable.Stream _state;
+ private bool _need_next;
+ private bool _finished;
+}
+
* @return iterator containing values yielded by stream
*/
public virtual Iterator<A> stream<A> (owned StreamFunc<G, A> f) {
- Iterator<G>? self;
- Iterable<G>? iself;
+ unowned Iterator<G>? self;
+ unowned Iterable<G>? iself;
// Yes - I've heard of polimorphism ;) but I don't want users to need to implement the method.
if ((self = this as Iterator<G>) != null) {
- Traversable.Stream str;
- Lazy<A>? initial = null;
- bool need_next = true;
- str = f (Stream.YIELD, null, out initial);
- switch (str) {
- case Stream.WAIT:
- case Stream.YIELD:
- if (self.valid)
- need_next = false;
- break;
- case Stream.CONTINUE:
- if (self.valid) {
- str = f (Stream.CONTINUE, new Lazy<G> (() => {return self.get ();}), out initial);
- switch (str) {
- case Stream.YIELD:
- case Stream.CONTINUE:
- case Stream.WAIT:
- break;
- case Stream.END:
- return Iterator.unfold<A> (() => {return null;});
- default:
- assert_not_reached ();
- }
- }
- break;
- case Stream.END:
- return Iterator.unfold<A> (() => {return null;});
- default:
- assert_not_reached ();
- }
- return Iterator.unfold<A> (() => {
- Lazy<A>? val = null;
- if (str != Stream.CONTINUE)
- str = f (str, null, out val);
- while (true) {
- switch (str) {
- case Stream.YIELD:
- return val;
- case Stream.CONTINUE:
- if (need_next) {
- if (!self.next ()) {
- str = f (Traversable.Stream.END, null, out val);
- continue;
- }
- } else {
- need_next = true;
- }
- str = f (Stream.CONTINUE, new Lazy<G> (() => {return self.get ();}), out val);
- break;
- case Stream.WAIT:
- str = f (Stream.WAIT, null, out val);
- break;
- case Stream.END:
- return null;
- default:
- assert_not_reached ();
- }
- }
- }, initial);
+ return new StreamIterator<A, G> (self, (owned)f);
} else if ((iself = this as Iterable<G>) != null) {
return iself.iterator().stream<A> ((owned) f);
} else {