Răsfoiți Sursa

Add Operaters namespace for finding common operators

Billy Barrow 1 lună în urmă
părinte
comite
b6ac1b6cbb

+ 8 - 0
src/lib/Associative/Associative.vala

@@ -7,6 +7,14 @@ namespace Invercargill {
         public abstract void clear(TKey key); 
         public abstract bool has(TKey key);
         
+        public virtual Enumerable<TKey> get_keys() {
+            return select<TKey>(kv => kv.key);
+        }
+
+        public virtual Enumerable<TKey> get_values() {
+            return select<TKey>(kv => kv.key);
+        }
+        
         public virtual TValue? get_or_default(TKey key) {
             TValue val;
             if(try_get(key, out val)) {

+ 33 - 51
src/lib/Associative/Dictionary.vala

@@ -4,74 +4,38 @@ namespace Invercargill {
 
     public class Dictionary<TKey, TValue> : Associative<TKey, TValue>, KeyValues<TKey, TValue> {
 
-        private HashTable<TKey, TValue> hash_table;
-
-        public Dictionary(HashFunc<TKey>? key_hash_func = null, EqualFunc<TKey>? key_equal_func = null) {
-            var hash_func = key_hash_func;
-            var equal_func = key_equal_func;
-
-            var key_type = typeof(TKey);
-            if(hash_func == null) {
-                if(key_type == typeof(string)) {
-                    hash_func = GLib.str_hash;
-                }
-                else if(key_type == typeof(int64) || key_type == typeof(uint64)) {
-                    hash_func = GLib.int64_hash;
-                }
-                else if(key_type == typeof(int)) {
-                    hash_func = GLib.direct_hash;
-                }
-                else if(key_type == typeof(double)) {
-                    hash_func = GLib.double_hash;
-                }
-                else if(key_type.is_a(typeof(Hashable))) {
-                    hash_func = (k) => ((Hashable)k).hash_code();
-                }
-            }
-            if(equal_func == null) {
-                if(key_type == typeof(string)) {
-                    equal_func = GLib.str_equal;
-                }
-                else if(key_type == typeof(int64) || key_type == typeof(uint64)) {
-                    equal_func = GLib.int64_equal;
-                }
-                else if(key_type == typeof(int)) {
-                    equal_func = GLib.direct_equal;
-                }
-                else if(key_type == typeof(double)) {
-                    equal_func = GLib.double_equal;
-                }
-                else if(key_type.is_a(typeof(Equatable))) {
-                    equal_func = (a, b) => ((Equatable<TKey>)a).equals(b);
-                }
-            }
-
-
-            hash_table = new HashTable<TKey, TValue>(hash_func, equal_func);
+        private HashTable<Key<TKey>, TValue> hash_table;
+        private EqualityDelegate<TKey> key_equal_delegate;
+        private HashDelegate<TKey> key_hash_delegate;
+
+        public Dictionary(HashDelegate<TKey>? key_hash_func = null, EqualityDelegate<TKey>? key_equal_func = null) {
+            key_hash_delegate = key_hash_func ?? Operators.hash<TKey>();
+            key_equal_delegate = key_equal_func ?? Operators.equality<TKey>();
+            hash_table = new HashTable<Key<TKey>, TValue>(Key.hash, Key.equal);
         }
 
         public override void @set (TKey key, TValue value) {
             lock(hash_table) {
-                hash_table.set (key, value);
+                hash_table.set (new Key<TKey>(this, key), value);
             }
         }
 
         public override void set_all (Enumerable<KeyValuePair<TKey, TValue>> key_values) {
             lock(hash_table) {
-                key_values.iterate(kv => hash_table.set(kv.key, kv.value));
+                key_values.iterate(kv => hash_table.set(new Key<TKey>(this, kv.key), kv.value));
             }
         }
 
         public override bool try_get (TKey key, out TValue value) {
             lock(hash_table) {
                 TKey orig_key;
-                return hash_table.lookup_extended (key, out orig_key, out value);
+                return hash_table.lookup_extended (new Key<TKey>(this, key), out orig_key, out value);
             }
         }
         
         public override void clear (TKey key) {
             lock(hash_table) {
-                hash_table.remove(key);
+                hash_table.remove(new Key<TKey>(this, key));
             }
         }
 
@@ -80,14 +44,14 @@ namespace Invercargill {
         }
         public override bool has (TKey key) {
             lock(hash_table) {
-                return hash_table.contains (key);
+                return hash_table.contains (new Key<TKey>(this, key));
             }
         }
 
         private class DictionaryTracker<TKey, TValue> : Tracker<KeyValuePair<TKey, TValue>> {
 
             private Dictionary<TKey, TValue> dictionary;
-            private (unowned TKey)[] keys;
+            private (unowned Key<TKey>)[] keys;
             private int index;
 
             public DictionaryTracker(Dictionary<TKey, TValue> dict) {
@@ -100,12 +64,30 @@ namespace Invercargill {
                 return index < keys.length;
             }
             public override KeyValuePair<TKey, TValue> get_next() {
-                var key = keys[index];
+                var key = keys[index].key;
                 var item = dictionary.get_or_default(key);
                 index++;
                 return new KeyValuePair<TKey, TValue> (key, item);
             }
 
         }
+
+        private class Key<TKey> {
+            public Dictionary owner;
+            public TKey key;
+
+            public Key(Dictionary owner, TKey key) {
+                this.owner = owner;
+                this.key = key;
+            }
+
+            public bool equal(Key<TKey> other) {
+                return owner.key_equal_delegate(key, other.key);
+            }
+
+            public uint hash() {
+                return owner.key_hash_delegate(key);
+            }
+        }
     }
 }

+ 16 - 94
src/lib/Collections/Set.vala

@@ -4,91 +4,35 @@ namespace Invercargill {
 
     public class Set<T> : Collection<T> {
 
-        private HashTable<T, T> hash_table;
-        private HashFunc<T> hash_func;
-        private EqualFunc<T> equal_func;
+        private Dictionary<T, T> dict;
+        private HashDelegate<T> hash_func;
+        private EqualityDelegate<T> equal_func;
 
         construct {
             setup();
         }
 
-        public Set(HashFunc<T>? value_hash_func = null, EqualFunc<T>? value_equal_func = null) {
+        public Set(HashDelegate<T>? value_hash_func = null, EqualityDelegate<T>? value_equal_func = null) {
             setup(value_hash_func, value_equal_func);
         }
 
-        private void setup(HashFunc<T>? value_hash_func = null, EqualFunc<T>? value_equal_func = null) {
+        private void setup(HashDelegate<T>? value_hash_func = null, EqualityDelegate<T>? value_equal_func = null) {
             hash_func = value_hash_func;
             equal_func = value_equal_func;
-
-            var key_type = typeof(T);
-            if(hash_func == null) {
-                if(key_type == typeof(string)) {
-                    hash_func = GLib.str_hash;
-                }
-                else if(key_type == typeof(int64) || key_type == typeof(uint64)) {
-                    hash_func = GLib.int64_hash;
-                }
-                else if(key_type == typeof(int)) {
-                    hash_func = GLib.direct_hash;
-                }
-                else if(key_type == typeof(double)) {
-                    hash_func = GLib.double_hash;
-                }
-                else if(key_type.is_a(typeof(Hashable))) {
-                    hash_func = (k) => ((Hashable)k).hash_code();
-                }
-            }
-            if(equal_func == null) {
-                if(key_type == typeof(string)) {
-                    equal_func = GLib.str_equal;
-                }
-                else if(key_type == typeof(int64) || key_type == typeof(uint64)) {
-                    equal_func = GLib.int64_equal;
-                }
-                else if(key_type == typeof(int)) {
-                    equal_func = GLib.direct_equal;
-                }
-                else if(key_type == typeof(double)) {
-                    equal_func = GLib.double_equal;
-                }
-                else if(key_type.is_a(typeof(Equatable))) {
-                    equal_func = (a, b) => ((Equatable<T>)a).equals(b);
-                }
-            }
-
-
-            hash_table = new HashTable<T, T>(hash_func, equal_func);
+            dict = new Dictionary<T, T>(value_hash_func, value_equal_func);
         }
 
 
         public override Tracker<T> get_tracker () {
-            return Convert.ate(hash_table.get_keys_as_array()).get_tracker();
+            return dict.get_keys().get_tracker();
         }
 
         public override void add (T item) {
-            lock(hash_table) {
-                hash_table.set(item, item);
-            }
-        }
-
-        private void with_lock(Func<Set<T>> action) {
-            lock(hash_table) {
-                action(this);
-            }
+            dict[item] = item;
         }
 
         public override void add_all (Enumerable<T> items) {
-            lock(hash_table) {
-                if(items.get_type().is_a (typeof(Set))) {
-                    if(items == this) {
-                        return;
-                    }
-                    ((Set<T>)items).with_lock((s) => s.hash_table.foreach (i => hash_table.set(i, i)));
-                }
-                else {
-                    items.iterate(i => hash_table.set(i, i));
-                }
-            }
+            items.iterate(add);
         }
 
         public Set<T> union(Enumerable<T> items) {
@@ -110,9 +54,7 @@ namespace Invercargill {
         }
 
         public new T? find(T item) {
-            lock(hash_table) {
-                return hash_table.get(item);
-            }
+            return dict.get_or_default(item);
         }
 
         public override void remove_first_where (Invercargill.PredicateDelegate<T> predicate) {
@@ -120,44 +62,24 @@ namespace Invercargill {
         }
 
         public override void remove_where (Invercargill.PredicateDelegate<T> predicate) {
-            lock(hash_table) {
-                hash_table.foreach_remove(k => predicate(k));
-            }
+            dict.remove_where(predicate);
         }
 
         public void remove(T item) {
-            lock(hash_table) {
-                hash_table.remove (item);
-            }
+            dict.clear(item);
         }
 
         public void remove_all(Enumerable<T> items) {
-            lock(hash_table) {
-                if(items.get_type().is_a (typeof(Set))) {
-                    if(items == this) {
-                        hash_table.remove_all();
-                    }
-                    else {
-                        ((Set<T>)items).with_lock((s) => s.hash_table.foreach (i => hash_table.remove(i)));
-                    }
-                }
-                else {
-                    items.iterate(i => hash_table.remove(i));
-                }
-            }
+            items.iterate(dict.clear);
         }
 
         public void remove_except(Enumerable<T> items) {
-            lock(hash_table) {
-                Set<T> other = items.to_set(hash_func, equal_func);
-                hash_table.foreach_remove(i => !other.has(i));
-            }
+            var other = items.to_set(hash_func, equal_func);
+            dict.remove_where(i => !other.has(i));
         }
 
         public bool has(T item) {
-            lock(hash_table) {
-                return hash_table.contains(item);
-            }
+            return dict.has(item);
         }
 
 

+ 2 - 0
src/lib/Delegates.vala

@@ -14,6 +14,8 @@ namespace Invercargill {
 
     public delegate bool EqualityDelegate<T>(T a, T b);
 
+    public delegate uint HashDelegate<T>(T item);
+
     public delegate Tout ErrorThrowingDelegate<Tin, Tout>(Tin item) throws Error;
 
     public delegate Tout ErrorCatchingDelegate<Tin, Tout>(Tin item, Error error);

+ 3 - 3
src/lib/Enumerable.vala

@@ -415,19 +415,19 @@ namespace Invercargill {
             return new CacheEnumerable<T>(this);
         }
 
-        public virtual Dictionary<TKey, T> to_dictionary<TKey>(TransformDelegate<T, TKey> key_selecter, HashFunc<TKey>? key_hash_func = null, EqualFunc<TKey>? key_equal_func = null) {
+        public virtual Dictionary<TKey, T> to_dictionary<TKey>(TransformDelegate<T, TKey> key_selecter, HashDelegate<TKey>? key_hash_func = null, EqualityDelegate<TKey>? key_equal_func = null) {
             var dict = new Dictionary<TKey, T>(key_hash_func, key_equal_func);       
             dict.set_all(select<KeyValuePair<TKey, T>>(i => new KeyValuePair<TKey, T>(key_selecter(i), i)));
             return dict;
         }
 
-        public virtual Dictionary<TKey, TValue> select_to_dictionary<TKey, TValue>(TransformDelegate<T, TKey> key_selecter, TransformDelegate<T, TValue> value_selecter, HashFunc<TKey>? key_hash_func = null, EqualFunc<TKey>? key_equal_func = null) {
+        public virtual Dictionary<TKey, TValue> select_to_dictionary<TKey, TValue>(TransformDelegate<T, TKey> key_selecter, TransformDelegate<T, TValue> value_selecter, HashDelegate<TKey>? key_hash_func = null, EqualityDelegate<TKey>? key_equal_func = null) {
             var dict = new Dictionary<TKey, T>(key_hash_func, key_equal_func);       
             dict.set_all(select<KeyValuePair<TKey, T>>(i => new KeyValuePair<TKey, T>(key_selecter(i), value_selecter(i))));
             return dict;
         }
 
-        public virtual Set<T> to_set(HashFunc<T>? hash_func = null, EqualFunc<T>? equal_func = null) {
+        public virtual Set<T> to_set(HashDelegate<T>? hash_func = null, EqualityDelegate<T>? equal_func = null) {
             var @set = new Set<T>(hash_func, equal_func);       
             @set.add_all(this);
             return @set;

+ 3 - 3
src/lib/EnumerableProxy.vala

@@ -187,11 +187,11 @@ namespace Invercargill {
             return inner.seal();
         }
 
-        public override Dictionary<TKey, T> to_dictionary<TKey>(TransformDelegate<T, TKey> key_selecter, HashFunc<TKey>? key_hash_func = null, EqualFunc<TKey>? key_equal_func = null) {
+        public override Dictionary<TKey, T> to_dictionary<TKey>(TransformDelegate<T, TKey> key_selecter, HashDelegate<TKey>? key_hash_func = null, EqualityDelegate<TKey>? key_equal_func = null) {
             return inner.to_dictionary<TKey>(key_selecter, key_hash_func, key_equal_func);
         }
 
-        public override Dictionary<TKey, TValue> select_to_dictionary<TKey, TValue>(TransformDelegate<T, TKey> key_selecter, TransformDelegate<T, TValue> value_selecter, HashFunc<TKey>? key_hash_func = null, EqualFunc<TKey>? key_equal_func = null) {
+        public override Dictionary<TKey, TValue> select_to_dictionary<TKey, TValue>(TransformDelegate<T, TKey> key_selecter, TransformDelegate<T, TValue> value_selecter, HashDelegate<TKey>? key_hash_func = null, EqualityDelegate<TKey>? key_equal_func = null) {
             return inner.select_to_dictionary<TKey, TValue>(key_selecter, value_selecter, key_hash_func, key_equal_func);
         }
 
@@ -202,7 +202,7 @@ namespace Invercargill {
         public override Enumerable<PositionItemPair<T>> with_positions() {
             return inner.with_positions();
         }
-        public override Set<T> to_set(HashFunc<T>? hash_func = null, EqualFunc<T>? equal_func = null) {
+        public override Set<T> to_set(HashDelegate<T>? hash_func = null, EqualityDelegate<T>? equal_func = null) {
             return inner.to_set(hash_func, equal_func);
         }
         public override Elements to_elements() {

+ 23 - 0
src/lib/Operators/Comparison.vala

@@ -0,0 +1,23 @@
+namespace Invercargill {
+    
+    public static CompareDelegate<T> comparison<T>() {
+        var type = typeof(T);
+        if(type == typeof(string)) {
+            return (a, b) => GLib.strcmp((string)a, (string)b);
+        }
+        else if(type == typeof(int64)) {
+            return (a, b) => (int)(((int64)a) - ((int64)b));
+        }
+        else if(type == typeof(uint64)) {
+            return (a, b) => (int)(((uint64)a) - ((uint64)b));
+        }
+        else if(type == typeof(double)) {
+            return (a, b) => (int)(((double)a) - ((double)b));
+        }
+        else if(type.is_a(typeof(Comparable))) {
+            return (a, b) => ((Comparable<T>)a).compare(b);
+        }
+        return (a, b) => (int)(&a - &b);
+    }
+
+}    

+ 21 - 0
src/lib/Operators/Equality.vala

@@ -0,0 +1,21 @@
+namespace Invercargill.Operators {
+    
+    public static EqualityDelegate<T> equality<T>() {
+        var type = typeof(T);
+        if(type == typeof(string)) {
+            return (a, b) => GLib.str_equal((string)a, (string)b);
+        }
+        else if(type == typeof(int64) || type == typeof(uint64)) {
+            return (a, b) => GLib.int64_equal((int64)a, (int64)b);
+        }
+        else if(type == typeof(double)) {
+            return (a, b) => GLib.double_equal((double?)a, (double?)b);
+        }
+        else if(type.is_a(typeof(Equatable))) {
+            return (a, b) => ((Equatable<T>)a).equals(b);
+        }
+        return (a, b) => GLib.direct_equal(a, b);
+    }
+
+
+}

+ 20 - 0
src/lib/Operators/Hash.vala

@@ -0,0 +1,20 @@
+namespace Invercargill.Operators {
+    
+    public static HashDelegate<T> hash<T>() {
+        var type = typeof(T);
+        if(type == typeof(string)) {
+            return i => GLib.str_hash((string)i);
+        }
+        else if(type == typeof(int64) || type == typeof(uint64)) {
+            return i => GLib.int64_hash((int64)i);
+        }
+        else if(type == typeof(double)) {
+            return i => GLib.double_hash((double?)i);
+        }
+        else if(type.is_a(typeof(Hashable))) {
+            return (k) => ((Hashable)k).hash_code();
+        }
+        return i => GLib.direct_hash(i);
+    }
+
+}

+ 3 - 3
src/lib/Promotions/AttemptEnumerable.vala

@@ -77,19 +77,19 @@ namespace Invercargill {
             return vector;
         }
 
-        public new Dictionary<TKey, T> to_dictionary<TKey>(TransformDelegate<T, TKey> key_selecter, HashFunc<TKey>? key_hash_func = null, EqualFunc<TKey>? key_equal_func = null) throws Error {
+        public new Dictionary<TKey, T> to_dictionary<TKey>(TransformDelegate<T, TKey> key_selecter, HashDelegate<TKey>? key_hash_func = null, EqualityDelegate<TKey>? key_equal_func = null) throws Error {
             var dict = new Dictionary<TKey, T>(key_hash_func, key_equal_func);       
             iterate(i => dict.set(key_selecter(i), i));
             return dict;
         }
 
-        public new Dictionary<TKey, TValue> select_to_dictionary<TKey, TValue>(TransformDelegate<T, TKey> key_selecter, TransformDelegate<T, TValue> value_selecter, HashFunc<TKey>? key_hash_func = null, EqualFunc<TKey>? key_equal_func = null) throws Error {
+        public new Dictionary<TKey, TValue> select_to_dictionary<TKey, TValue>(TransformDelegate<T, TKey> key_selecter, TransformDelegate<T, TValue> value_selecter, HashDelegate<TKey>? key_hash_func = null, EqualityDelegate<TKey>? key_equal_func = null) throws Error {
             var dict = new Dictionary<TKey, T>(key_hash_func, key_equal_func);       
             iterate(i => dict.set(key_selecter(i), value_selecter(i)));
             return dict;
         }
 
-        public new Set<T> to_set(HashFunc<T>? hash_func = null, EqualFunc<T>? equal_func = null) throws Error {
+        public new Set<T> to_set(HashDelegate<T>? hash_func = null, EqualityDelegate<T>? equal_func = null) throws Error {
             var @set = new Set<T>(hash_func, equal_func);       
             iterate(i => @set.add(i));
             return @set;

+ 6 - 6
src/lib/ValueMapper.vala

@@ -41,11 +41,11 @@ namespace Invercargill {
     }
 
     public class ValueMapperBuilder<TNative, TElement> {
-        internal HashFunc<TNative>? native_hash_func = null;
-        internal EqualFunc<TNative>? native_equal_func = null;
+        internal HashDelegate<TNative>? native_hash_func = null;
+        internal EqualityDelegate<TNative>? native_equal_func = null;
 
-        internal HashFunc<TElement>? element_hash_func = null;
-        internal EqualFunc<TElement>? element_equal_func = null;
+        internal HashDelegate<TElement>? element_hash_func = null;
+        internal EqualityDelegate<TElement>? element_equal_func = null;
 
         internal Vector<ValueMapping<TNative, TElement>> mappings = new Vector<ValueMapping<TNative, TElement>>();
 
@@ -58,13 +58,13 @@ namespace Invercargill {
             return this;
         }
 
-        public ValueMapperBuilder<TNative, TElement> with_native_equality(EqualFunc<TNative> eq, HashFunc<TNative>? hash = null) {
+        public ValueMapperBuilder<TNative, TElement> with_native_equality(EqualityDelegate<TNative> eq, HashDelegate<TNative>? hash = null) {
             native_equal_func = eq;
             native_hash_func = hash;
             return this;
         }
 
-        public ValueMapperBuilder<TNative, TElement> with_element_equality(EqualFunc<TNative> eq, HashFunc<TNative>? hash = null) {
+        public ValueMapperBuilder<TNative, TElement> with_element_equality(EqualityDelegate<TNative> eq, HashDelegate<TNative>? hash = null) {
             element_equal_func = eq;
             element_hash_func = hash;
             return this;

+ 4 - 0
src/lib/meson.build

@@ -77,6 +77,10 @@ sources += files('Associative/Index.vala')
 sources += files('Associative/KeyValues.vala')
 sources += files('Associative/Properties.vala')
 
+sources += files('Operators/Comparison.vala')
+sources += files('Operators/Equality.vala')
+sources += files('Operators/Hash.vala')
+
 invercargill = shared_library('invercargill', sources,
     dependencies: dependencies,
     install: true,