Billy Barrow преди 3 седмици
родител
ревизия
1219d03395

+ 10 - 0
src/lib/Enumerable.vala

@@ -333,6 +333,16 @@ namespace Invercargill {
             return keys.select<Grouping<TKey, T>>(g => new Grouping<TKey, T>(g, this.where(i => equality(g, key_selector(i)))));
         }
 
+        public virtual Enumerable<T> union_by<TKey>(Enumerable<T> other, owned TransformDelegate<T, TKey> key_selector, owned HashDelegate<TKey>? hash_func = null, owned EqualityDelegate<TKey>? equal_func = null) {
+            return new Union<T, TKey>(this, other, (owned)key_selector, (owned)hash_func, (owned)equal_func);
+        }
+
+        // Can't name it union because of C reserved keywords
+        public virtual Enumerable<T> union(Enumerable<T> other, owned HashDelegate<T>? hash_func = null, owned EqualityDelegate<T>? equal_func = null) {
+            return union_by<T>(other, i => i, (owned)hash_func, (owned) equal_func);
+        }
+
+
         public virtual Enumerable<T> @with(T item, uint times = 1) {
             return concat(range(0, (int)times, 1).select<T>(i => item));
         }

+ 0 - 4
src/lib/Invercargill.vala

@@ -37,8 +37,4 @@ namespace Invercargill {
         };
     }
 
-    public static Enumerable<string> directory(string path, uint flags = 0) throws FileError {
-        return new Generators.Directory(Dir.open(path, flags));
-    }
-
 }

+ 36 - 0
src/lib/Iterate.vala

@@ -0,0 +1,36 @@
+using Invercargill.DataStructures;
+namespace Invercargill.Iterate {
+
+    public static Enumerable<T> single<T>(T item) {
+        var buffer = new Buffer<T>(1);
+        non_error(() => buffer[0] = item);
+        return buffer.seal();
+    }
+
+    public static Enumerable<int> range(int from, int to, int increment = 1) {
+        return new Generators.Range(from, to, increment);
+    }
+
+    public static Enumerable<T> nothing<T>() {
+        return new Generators.Empty<T>();
+    }
+
+    public static Enumerable<string> directory(string path, uint flags = 0) throws FileError {
+        return new Generators.Directory(Dir.open(path, flags));
+    }
+
+    public static Enumerable<T> these<T>(T item1, ...) {
+        var series = new Series<T>();
+        var args = va_list();
+        while(true) {
+            T? item = args.arg<T>();
+            if(item == null) {
+                break;
+            }
+            series.add(item);
+        }
+        return series.seal();
+    }
+
+
+}

+ 42 - 0
src/lib/Modifiers/Except.vala

@@ -0,0 +1,42 @@
+
+namespace Invercargill.Modifiers {
+
+    public class Concat<T> : Enumerable<T> {
+
+        private Enumerable<T> e1;
+        private Enumerable<T> e2;
+
+        public Concat(Enumerable<T> first, Enumerable<T> second) {
+            e1 = first;
+            e2 = second;
+        }
+
+        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 EnumerableInfo get_info() {
+            return new EnumerableInfo.infer(this, EnumerableCategory.COMPUTED, Convert.ate(new Enumerable[] {e1, e2}));
+        }
+
+        public override Tracker<T> get_tracker() {
+            var tracker1 = e1.get_tracker();
+            var tracker2 = e2.get_tracker();
+
+            return new LambdaTracker<T>(
+                () => tracker1.has_next() || tracker2.has_next(),
+                () => {
+                    if(tracker1.has_next()) {
+                        return tracker1.get_next();
+                    }
+                    return tracker2.get_next();
+                });
+        }
+
+    }
+
+}

+ 42 - 0
src/lib/Modifiers/Intersect.vala

@@ -0,0 +1,42 @@
+
+namespace Invercargill.Modifiers {
+
+    public class Concat<T> : Enumerable<T> {
+
+        private Enumerable<T> e1;
+        private Enumerable<T> e2;
+
+        public Concat(Enumerable<T> first, Enumerable<T> second) {
+            e1 = first;
+            e2 = second;
+        }
+
+        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 EnumerableInfo get_info() {
+            return new EnumerableInfo.infer(this, EnumerableCategory.COMPUTED, Convert.ate(new Enumerable[] {e1, e2}));
+        }
+
+        public override Tracker<T> get_tracker() {
+            var tracker1 = e1.get_tracker();
+            var tracker2 = e2.get_tracker();
+
+            return new LambdaTracker<T>(
+                () => tracker1.has_next() || tracker2.has_next(),
+                () => {
+                    if(tracker1.has_next()) {
+                        return tracker1.get_next();
+                    }
+                    return tracker2.get_next();
+                });
+        }
+
+    }
+
+}

+ 0 - 0
src/lib/Modifiers/SymmetricExcept.vala


+ 60 - 0
src/lib/Modifiers/Union.vala

@@ -0,0 +1,60 @@
+
+using Invercargill.DataStructures;
+namespace Invercargill.Modifiers {
+
+    public class Union<T, TKey> : Enumerable<T> {
+
+        private Enumerable<T> e1;
+        private Enumerable<T> e2;
+        private TransformDelegate<T, TKey> key_sf;
+        private HashDelegate<TKey> key_hf;
+        private EqualityDelegate<TKey> key_ef;
+
+        public Union(Enumerable<T> first, Enumerable<T> second, owned TransformDelegate<T, TKey> key_selector, owned HashDelegate<TKey>? key_hasher = null, owned EqualityDelegate<TKey>? key_equator = null) {
+            e1 = first;
+            e2 = second;
+            key_sf = (owned)key_selector;
+            key_ef = (owned)key_equator ?? Operators.equality<TKey>();
+            key_hf = (owned)key_hasher ?? Operators.hash<TKey>();
+        }
+
+        public override int? peek_count() {
+            return null;
+        }
+
+        public override EnumerableInfo get_info() {
+            return new EnumerableInfo.infer(this, EnumerableCategory.COMPUTED, Iterate.these(e1, e2));
+        }
+
+        public override Tracker<T> get_tracker() {
+            var tracker1 = e1.get_tracker();
+            var tracker2 = e2.get_tracker();
+            var touched = new HashSet<TKey>(key_hf, key_ef);
+
+            return new AdvanceTracker<T>((out result) => {
+                T? item = null;
+                while(item != null) {
+                    if(tracker1.has_next()) {
+                        item = tracker1.get_next();
+                    }
+                    else if(tracker2.has_next()) {
+                        item = tracker2.get_next();
+                    }
+                    else {
+                        result = null;
+                        return false;
+                    }
+
+                    var key = key_sf(item);
+                    if(!touched.add(key)) {
+                        item = null;
+                    }
+                }
+                result = item;
+                return true;
+            });
+        }
+
+    }
+
+}

+ 5 - 0
src/lib/Wrap.vala

@@ -0,0 +1,5 @@
+using Invercargill.DataStructures;
+namespace Invercargill.Wrap {
+
+
+}

+ 6 - 0
src/lib/meson.build

@@ -29,6 +29,8 @@ sources += files('StickyPromotion.vala')
 sources += files('Element.vala')
 sources += files('Debug.vala')
 sources += files('OrderConfiguration.vala')
+sources += files('Iterate.vala')
+sources += files('Wrap.vala')
 
 sources += files('Modifiers/Transform.vala')
 sources += files('Modifiers/Filter.vala')
@@ -48,6 +50,10 @@ sources += files('Modifiers/Zip.vala')
 sources += files('Modifiers/Sealed.vala')
 sources += files('Modifiers/Interleave.vala')
 sources += files('Modifiers/Order.vala')
+sources += files('Modifiers/Union.vala')
+# sources += files('Modifiers/Except.vala')
+# sources += files('Modifiers/Intersect.vala')
+# sources += files('Modifiers/SymmetricExcept.vala')
 
 sources += files('Wrappers/Array.vala')
 sources += files('Wrappers/GeeIterable.vala')