Selaa lähdekoodia

Add "peek_count" function and add optional predicate to "count" function.

Billy Barrow 3 viikkoa sitten
vanhempi
sitoutus
b8115fd16a

+ 5 - 0
src/lib/DataStructures/BinaryData.vala

@@ -14,6 +14,10 @@ namespace Invercargill.DataStructures {
 
         private Enumerable<Enumerable<uint8>> chunks;
 
+        public override int? peek_count() {
+            return null;
+        }
+
         public override Tracker<uint8> get_tracker () {
             return chunks.select_many<uint8>(s => s).get_tracker();
         }
@@ -479,6 +483,7 @@ namespace Invercargill.DataStructures {
             return size;
         }
 
+
     }
 
 }

+ 4 - 0
src/lib/DataStructures/Dictionary.vala

@@ -8,6 +8,10 @@ namespace Invercargill.DataStructures {
         private HashDelegate<TKey> hash_func;
         private EqualityDelegate<TKey> equal_func;
 
+        public override int? peek_count() {
+            return hash_set.peek_count();
+        }
+
         public Dictionary(HashDelegate<TKey>? key_hash_func = null, EqualityDelegate<TKey>? key_equal_func = null) {
             hash_func = key_hash_func ?? Operators.hash<TKey>();
             equal_func = key_equal_func ?? Operators.equality<TKey>();

+ 4 - 0
src/lib/DataStructures/Fifo.vala

@@ -7,6 +7,10 @@ namespace Invercargill.DataStructures {
         private FifoItem<T>? first_item = null;
         private FifoItem<T>? last_item = null;
 
+        public override int? peek_count() {
+            return null;
+        }
+
         public void unblock() {
             mutex.lock();
             is_blocking = false;

+ 4 - 0
src/lib/DataStructures/HashSet.vala

@@ -102,6 +102,10 @@ namespace Invercargill.DataStructures {
             return hash % n_buckets;
         }
 
+        public override int? peek_count() {
+            return n_items;
+        }
+
         public override Tracker<T> get_tracker () {
             return range(0, n_items).select<T>(i => read_item(i)).get_tracker();
         }

+ 4 - 4
src/lib/DataStructures/Series.vala

@@ -28,6 +28,10 @@ namespace Invercargill.DataStructures {
 
         public Series() {}
 
+        public override int? peek_count() {
+            return n_items;
+        }
+
         public override Tracker<T> get_tracker() {
             return new SeriesTracker<T>(root);
         }
@@ -60,10 +64,6 @@ namespace Invercargill.DataStructures {
             items.iterate(i => add(i));
         }
 
-        public override int count() {
-            return n_items;
-        }
-
         public void remove_first_where(Invercargill.PredicateDelegate<T> predicate) {
             remove_items(predicate, true);
         }

+ 4 - 4
src/lib/DataStructures/Vector.vala

@@ -15,6 +15,10 @@ namespace Invercargill.DataStructures {
             safe_write = get_safe_write_function_for<T>();
         }
 
+        public override int? peek_count() {
+            return n_items;
+        }
+
         public override Tracker<T> get_tracker() {
             return new AddressableTracker<T>(this);
         }
@@ -104,10 +108,6 @@ namespace Invercargill.DataStructures {
             }
         }
 
-        public override int count() {
-            return n_items;
-        }
-
         public void remove_at(int index) throws IndexError {
             var e = remove_internal(index);
             if(e != null) {

+ 29 - 18
src/lib/Enumerable.vala

@@ -7,6 +7,7 @@ namespace Invercargill {
     public abstract class Enumerable<T> : Object {
 
         public abstract Tracker<T> get_tracker();
+        public abstract int? peek_count();
 
         // Returns false if iteration was interrupted
         // Returns true if iteration reached natural end
@@ -20,11 +21,16 @@ namespace Invercargill {
             return true;
         }
 
-        public virtual void iterate(ItemDelegate<T> handler) {
-            iterate_if(i => {
-                handler(i);
-                return true;
-            });
+        public virtual void iterate(ItemDelegate<T>? handler = null) {
+            if(handler != null) {
+                iterate_if(i => {
+                    handler(i);
+                    return true;
+                });
+                return;
+            }
+
+            iterate_if(i => true);
         }
 
         public virtual Series<T> to_series() {
@@ -57,9 +63,22 @@ namespace Invercargill {
             return array;
         }
 
-        public virtual int count() {
+        public virtual int count(PredicateDelegate<T>? predicate = null) {
+            var enumerable = this;
+            // When no predicate is passed, see if we can peek at the count of
+            // the enumerable before iterating.
+            if(predicate == null) {
+                var peek = peek_count();
+                if(peek != null) {
+                    return peek;
+                }
+            }
+            else {
+                enumerable = this.where(predicate);
+            }
+
             var count = 0;
-            iterate(i => count++);
+            enumerable.iterate(i => count++);
             return count;
         }
 
@@ -145,14 +164,6 @@ namespace Invercargill {
             return select<Tout>(i => (Tout)i);
         }
 
-        //  public virtual Enumerable<Tout> convert<Tout>() throws ConverterError {
-        //      var converter = get_converter<T, Tout>();
-        //      if(converter == null) {
-        //          throw new ConverterError.CONVERTER_NOT_FOUND(@"No converter registered that can convert from $(typeof(T).name()) to $(typeof(Tout).name())");
-        //      }
-        //      return select(((Converter<T, Tout>)converter).convert);
-        //  }
-
         public virtual Enumerable<Tout> parallel_select<Tout>(owned TransformDelegate<T, Tout> transform, uint workers = 0) {
             var actual_workers = workers;
             if(actual_workers < 1) {
@@ -161,12 +172,12 @@ namespace Invercargill {
             return new Parallel<T, Tout>(this, (owned)transform, (int)actual_workers);
         }
 
-        public virtual int parallel_iterate(ItemDelegate<T> handler, uint workers = 0) {
-            return parallel_select<T>(i => {
+        public virtual void parallel_iterate(ItemDelegate<T> handler, uint workers = 0) {
+            parallel_select<T>(i => {
                 handler(i);
                 return i;
             }, workers)
-            .count();
+            .iterate();
         }
 
         public virtual Enumerable<SelectionContext<T, Tout>> contextualised_select<Tout>(owned TransformDelegate<T, Tout> transform) {

+ 9 - 5
src/lib/EnumerableProxy.vala

@@ -7,6 +7,10 @@ namespace Invercargill {
 
         protected Enumerable<T> inner { get; set; }
 
+        public override int? peek_count() {
+            return inner.peek_count();
+        }
+
         public override Tracker<T> get_tracker() {
             return inner.get_tracker();
         }
@@ -15,7 +19,7 @@ namespace Invercargill {
             return inner.iterate_if(handler);
         }
 
-        public override void iterate(ItemDelegate<T> handler) {
+        public override void iterate(ItemDelegate<T>? handler = null) {
             inner.iterate(handler);
         }
 
@@ -35,8 +39,8 @@ namespace Invercargill {
             return inner.to_array();
         }
     
-        public override int count() {
-            return inner.count();
+        public override int count(PredicateDelegate<T>? predicate = null) {
+            return inner.count(predicate);
         }
     
         public override bool any(PredicateDelegate<T> predicate = (i) => true) {
@@ -87,8 +91,8 @@ namespace Invercargill {
             return inner.parallel_select((owned)transform, workers);
         }
     
-        public override int parallel_iterate(ItemDelegate<T> handler, uint workers = 0) {
-            return inner.parallel_iterate(handler, workers);
+        public override void parallel_iterate(ItemDelegate<T> handler, uint workers = 0) {
+            inner.parallel_iterate(handler, workers);
         }
     
         public override Enumerable<SelectionContext<T, Tout>> contextualised_select<Tout>(owned TransformDelegate<T, Tout> transform) {

+ 4 - 0
src/lib/Generators/Directory.vala

@@ -9,6 +9,10 @@ namespace Invercargill.Generators {
             this.dir = (owned)dir;
         }
 
+        public override int? peek_count() {
+            return null;
+        }
+
         public override Tracker<string> get_tracker() {
             return new AdvanceTracker<string>((out obj) => {
                 var name = dir.read_name();

+ 4 - 0
src/lib/Generators/Empty.vala

@@ -3,6 +3,10 @@ namespace Invercargill.Generators {
 
     internal class Empty<T> : Enumerable<T> {
 
+        public override int? peek_count() {
+            return 0;
+        }
+
         public override Tracker<T> get_tracker() {
             return new LambdaTracker<T>(
                 () => {

+ 4 - 0
src/lib/Generators/Function.vala

@@ -4,6 +4,10 @@ namespace Invercargill.Generators {
 
     public class Function<T> : Enumerable<T> {
 
+        public override int? peek_count() {
+            return null;
+        }
+
         private GeneratorDelegate<T> func;
         private bool completed = false;
         private GeneratorResult<T>? next_result = null;

+ 3 - 8
src/lib/Generators/Range.vala

@@ -13,14 +13,9 @@ namespace Invercargill.Generators {
             this.stride = stride;
         }
 
-        //  public override bool iterate_if (Invercargill.PredicateDelegate<int> handler) {
-        //      for(int i = start; i < stop; i += stride) {
-        //          if(!handler(i)) {
-        //              return false;
-        //          }
-        //      }
-        //      return true;
-        //  }
+        public override int? peek_count() {
+            return (stop - start) / stride;
+        }
 
         public override Tracker<int> get_tracker() {
             var i = start;

+ 4 - 0
src/lib/Modifiers/Cache.vala

@@ -13,6 +13,10 @@ namespace Invercargill.Modifiers {
             vector = new Vector<T>();
         }
 
+        public override int? peek_count() {
+            return inner.peek_count();
+        }
+
         public override Tracker<T> get_tracker () {
             var i = 0;
             return new AssertingLambdaTracker<T>(() => has_nth(i), () => vector[i++]);

+ 7 - 6
src/lib/Modifiers/Concat.vala

@@ -11,12 +11,13 @@ namespace Invercargill.Modifiers {
             e2 = second;
         }
 
-        //  public override bool iterate_if (Invercargill.PredicateDelegate<T> handler) {
-        //      if(e1.iterate_if (handler)) {
-        //          return e2.iterate_if (handler);
-        //      }
-        //      return false;
-        //  }
+        public override int? peek_count() {
+            var c1 = e1.peek_count();
+            var c2 = e2.peek_count();
+            if(c1 == null || c2 == null)
+                return null;
+            return c1 + c2;
+        }
 
         public override Tracker<T> get_tracker() {
             var tracker1 = e1.get_tracker();

+ 3 - 10
src/lib/Modifiers/Filter.vala

@@ -9,16 +9,9 @@ namespace Invercargill.Modifiers {
             predicate_func = (owned)func;
         }
 
-        //  public override bool iterate_if (Invercargill.PredicateDelegate<T> handler) {
-        //      return input.iterate_if(i => {
-        //          if(predicate_func(i)) {
-        //              if(!handler(i)) {
-        //                  return false;
-        //              }
-        //          }
-        //          return true;
-        //      });
-        //  }
+        public override int? peek_count() {
+            return null;
+        }
 
         public override Tracker<T> get_tracker() {
             var tracker = input.get_tracker();

+ 4 - 0
src/lib/Modifiers/FilterTransform.vala

@@ -9,6 +9,10 @@ namespace Invercargill.Modifiers {
             transform_func = (owned)func;
         }
 
+        public override int? peek_count() {
+            return null;
+        }
+
         public override Tracker<Tout> get_tracker() {
             var tracker = input.get_tracker();
 

+ 4 - 0
src/lib/Modifiers/From.vala

@@ -9,6 +9,10 @@ namespace Invercargill.Modifiers {
             predicate_func = (owned)func;
         }
 
+        public override int? peek_count() {
+            return null;
+        }
+
         public override Tracker<T> get_tracker() {
             var tracker = input.get_tracker();
             var condition_met = false;

+ 8 - 0
src/lib/Modifiers/Interleave.vala

@@ -10,6 +10,14 @@ namespace Invercargill.Modifiers {
             e2 = en2;
         }
 
+        public override int? peek_count() {
+            var c1 = e1.peek_count();
+            var c2 = e2.peek_count();
+            if(c1 == null || c2 == null)
+                return null;
+            return c1 + c2;
+        }
+
         public override Tracker<T> get_tracker() {
             var t1 = e1.get_tracker();
             var t2 = e2.get_tracker();

+ 4 - 0
src/lib/Modifiers/Merge.vala

@@ -10,6 +10,10 @@ namespace Invercargill.Modifiers {
             return input.iterate_if(i => i.iterate_if(handler));
         }
 
+        public override int? peek_count() {
+            return null;
+        }
+
         public override Tracker<T> get_tracker() {
             var outer_tracker = input.get_tracker();
             Tracker<T> inner_tracker = null;

+ 4 - 0
src/lib/Modifiers/Parallel.vala

@@ -12,6 +12,10 @@ namespace Invercargill.Modifiers {
             transform_func = (owned)transform;
         }
 
+        public override int? peek_count() {
+            return input.peek_count();
+        }
+
         public override Tracker<Tout> get_tracker() {
             return new ParallelTracker<Tin, Tout>(i => transform_func(i), workers, input.get_tracker());
         }

+ 4 - 0
src/lib/Modifiers/Position.vala

@@ -7,6 +7,10 @@ namespace Invercargill.Modifiers {
             this.input = input;
         }
 
+        public override int? peek_count() {
+            return input.peek_count();
+        }
+
         public override Tracker<PositionItemPair<T>> get_tracker() {
             return new PositionTracker<T>(input);
         }

+ 7 - 0
src/lib/Modifiers/Skip.vala

@@ -10,6 +10,13 @@ namespace Invercargill.Modifiers {
             n_items = skip;
         }
 
+        public override int? peek_count() {
+            var c = input.peek_count();
+            if(c == null)
+                return null;
+            return int.min(0, c - n_items);
+        }
+
         public override bool iterate_if (Invercargill.PredicateDelegate<T> handler) {
             var c = 0;
             return input.iterate_if(i => {

+ 3 - 0
src/lib/Modifiers/Sort.vala

@@ -9,6 +9,9 @@ namespace Invercargill.Modifiers {
             compare_func = (owned)compare;
         }
 
+        public override int? peek_count() {
+            return input.peek_count();
+        }
 
         public override Tracker<T> get_tracker() {
             // Hack for now

+ 6 - 10
src/lib/Modifiers/Take.vala

@@ -9,16 +9,12 @@ namespace Invercargill.Modifiers {
             n_items = count;
         }
 
-        //  public override bool iterate_if (Invercargill.PredicateDelegate<T> handler) {
-        //      var c = 0;
-        //      return input.iterate_if(i => {
-        //          if(c < n_items) {
-        //              c++;
-        //              return handler(i);
-        //          }
-        //          return false;             
-        //      });
-        //  }
+        public override int? peek_count() {
+            var c = input.peek_count();
+            if(c == null)
+                return null;
+            return int.min(0, c - n_items);
+        }
 
         public override Tracker<T> get_tracker() {
             var tracker = input.get_tracker();

+ 3 - 3
src/lib/Modifiers/Transform.vala

@@ -9,9 +9,9 @@ namespace Invercargill.Modifiers {
             transform_func = (owned)transform;
         }
 
-        //  public override bool iterate_if (Invercargill.PredicateDelegate<Tout> handler) {
-        //      return input.iterate_if(i => handler(transform_func(i)));
-        //  }
+        public override int? peek_count() {
+            return input.peek_count();
+        }
 
         public override Tracker<Tout> get_tracker() {
             var tracker = input.get_tracker();

+ 4 - 0
src/lib/Modifiers/Unique.vala

@@ -12,6 +12,10 @@ namespace Invercargill.Modifiers {
             this.selector = (owned)selector;
         }
 
+        public override int? peek_count() {
+            return null;
+        }
+
         public override Tracker<T> get_tracker() {
             var tracker = input.get_tracker();
             var previous = new Vector<T>();

+ 4 - 0
src/lib/Modifiers/Until.vala

@@ -9,6 +9,10 @@ namespace Invercargill.Modifiers {
             predicate_func = (owned)func;
         }
 
+        public override int? peek_count() {
+            return null;
+        }
+
         public override Tracker<T> get_tracker() {
             var tracker = input.get_tracker();
             var condition_met = false;

+ 8 - 0
src/lib/Modifiers/Zip.vala

@@ -12,6 +12,14 @@ namespace Invercargill.Modifiers {
             transform_func = (owned)func;
         }
 
+        public override int? peek_count() {
+            var c1 = e1.peek_count();
+            var c2 = e2.peek_count();
+            if(c1 == null || c2 == null)
+                return null;
+            return int.max(c1, c2);
+        }
+
         public override Tracker<TOut> get_tracker() {
             var tracker1 = e1.get_tracker();
             var tracker2 = e2.get_tracker();

+ 4 - 0
src/lib/Wrappers/Array.vala

@@ -11,6 +11,10 @@ namespace Invercargill.Wrappers {
                 safely_assign_to_array<T>(array, i, safely_read_array<T>(input, i));
             }
         }
+        
+        public override int? peek_count() {
+            return array.length;
+        }
 
         public override Tracker<T> get_tracker() {
             var i = 0;

+ 3 - 8
src/lib/Wrappers/GeeIterable.vala

@@ -11,14 +11,9 @@ namespace Invercargill.Wrappers {
             iterable = gee;
         }
 
-        //  public override bool iterate_if (Invercargill.PredicateDelegate<T> handler) {
-        //      foreach(var item in iterable) {
-        //          if(!handler(item)) {
-        //              return false;
-        //          }
-        //      }
-        //      return true;
-        //  }
+        public override int? peek_count() {
+            return null;
+        }
 
         
         public override Tracker<T> get_tracker() {

+ 4 - 0
src/lib/Wrappers/GenericArray.vala

@@ -9,6 +9,10 @@ namespace Invercargill.Wrappers {
             array = input;
         }
 
+        public override int? peek_count() {
+            return array.length;
+        }
+
         public override Tracker<T> get_tracker() {
             var i = 0;
             return new LambdaTracker<T>(

+ 2 - 2
src/tests/Integration/Parallel.vala

@@ -33,9 +33,9 @@ void parallel_tests() {
             new ParallelObj(),
         });
 
-        var items_processed = items.parallel_iterate(o => o.big_process(), 4);
+        items.parallel_iterate(o => o.big_process(), 4);
         
-        assert_true(items_processed == 8);
+        assert_true(items.count() == 8);
         assert_true(items.all(o => o.processed));
     });