|
@@ -0,0 +1,193 @@
|
|
|
|
|
+// using Invercargill.DataStructures;
|
|
|
|
|
+
|
|
|
|
|
+// namespace Invercargill {
|
|
|
|
|
+
|
|
|
|
|
+// public class SetCatalogue<TKey, TValue> : Enumerable<Grouping<TKey, TValue>>, Lot<Grouping<TKey, TValue>>, ReadOnlyCategoryIndex<TKey, TValue>, CategoryIndex<TKey, TValue> {
|
|
|
|
|
+
|
|
|
|
|
+// public Enumerable<TKey> keys { owned get { return lookup.keys; } }
|
|
|
|
|
+// public Enumerable<TValue> values { owned get { return lookup.values.select_many<TValue>(g => g); } }
|
|
|
|
|
+// public uint length { get {
|
|
|
|
|
+// rw_lock.reader_lock ();
|
|
|
|
|
+// var count = item_count;
|
|
|
|
|
+// rw_lock.reader_unlock ();
|
|
|
|
|
+// return count;
|
|
|
|
|
+// }}
|
|
|
|
|
+
|
|
|
|
|
+// private Dictionary<TKey, HashSet<TValue>> lookup;
|
|
|
|
|
+// private uint item_count = 0;
|
|
|
|
|
+// private RWLock rw_lock;
|
|
|
|
|
+// private HashDelegate<TKey>? item_hash_func = null;
|
|
|
|
|
+// private EqualityDelegate<TKey>? item_equal_func = null;
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+// public SetCatalogue(HashDelegate<TKey>? key_hash_func = null, EqualityDelegate<TKey>? key_equal_func = null, HashDelegate<TKey>? item_hash_func = null, EqualityDelegate<TKey>? item_equal_func = null) {
|
|
|
|
|
+// this.item_equal_func = item_equal_func;
|
|
|
|
|
+// this.item_hash_func = item_hash_func;
|
|
|
|
|
+// lookup = new Dictionary<TKey, HashSet<TValue>> (key_hash_func, key_equal_func);
|
|
|
|
|
+// rw_lock = RWLock();
|
|
|
|
|
+// }
|
|
|
|
|
+
|
|
|
|
|
+// public override Tracker<Grouping<TKey, TValue>> get_tracker () {
|
|
|
|
|
+// rw_lock.reader_lock ();
|
|
|
|
|
+// var result = lookup
|
|
|
|
|
+// .select<Grouping<TKey, TValue>>(kv => new Grouping<TKey, TValue>(kv.key, kv.value))
|
|
|
|
|
+// .get_tracker();;
|
|
|
|
|
+// rw_lock.reader_unlock ();
|
|
|
|
|
+// return result;
|
|
|
|
|
+// }
|
|
|
|
|
+
|
|
|
|
|
+// public override uint? peek_count () {
|
|
|
|
|
+// return item_count;
|
|
|
|
|
+// }
|
|
|
|
|
+
|
|
|
|
|
+// public override EnumerableInfo get_info () {
|
|
|
|
|
+// return new EnumerableInfo.infer_ultimate (this, EnumerableCategory.IN_MEMORY);
|
|
|
|
|
+// }
|
|
|
|
|
+
|
|
|
|
|
+// public bool try_get (TKey key, out Grouping<TKey, TValue> value) {
|
|
|
|
|
+// rw_lock.reader_lock();
|
|
|
|
|
+// HashSet<TValue> hash_set;
|
|
|
|
|
+// if(lookup.try_get (key, out hash_set)) {
|
|
|
|
|
+// value = new Grouping<TKey, TValue>(key, hash_set);
|
|
|
|
|
+// rw_lock.reader_unlock();
|
|
|
|
|
+// return true;
|
|
|
|
|
+// }
|
|
|
|
|
+// rw_lock.reader_unlock();
|
|
|
|
|
+// value = null;
|
|
|
|
|
+// return false;
|
|
|
|
|
+// }
|
|
|
|
|
+
|
|
|
|
|
+// public bool has (TKey key) {
|
|
|
|
|
+// rw_lock.reader_lock();
|
|
|
|
|
+// var result = lookup.has(key);
|
|
|
|
|
+// rw_lock.reader_unlock();
|
|
|
|
|
+// return result;
|
|
|
|
|
+// }
|
|
|
|
|
+
|
|
|
|
|
+// public bool try_get_any (TKey key, out TValue value) {
|
|
|
|
|
+// rw_lock.reader_lock();
|
|
|
|
|
+// HashSet<TValue> hash_set;
|
|
|
|
|
+// if(lookup.try_get (key, out hash_set) && hash_set.length > 0) {
|
|
|
|
|
+// value = hash_set.first_or_default();
|
|
|
|
|
+// rw_lock.reader_unlock();
|
|
|
|
|
+// return true;
|
|
|
|
|
+// }
|
|
|
|
|
+// rw_lock.reader_unlock();
|
|
|
|
|
+// value = null;
|
|
|
|
|
+// return false;
|
|
|
|
|
+// }
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+// public new void @set (TKey key, Enumerable<TValue> values) {
|
|
|
|
|
+// rw_lock.writer_lock();
|
|
|
|
|
+// HashSet<TValue> hash_set;
|
|
|
|
|
+// if(lookup.try_get (key, out hash_set)) {
|
|
|
|
|
+// item_count -= hash_set.length;
|
|
|
|
|
+// }
|
|
|
|
|
+// hash_set = values.to_hash_set();
|
|
|
|
|
+// lookup[key] = hash_set;
|
|
|
|
|
+// item_count += hash_set.length;
|
|
|
|
|
+// rw_lock.writer_unlock();
|
|
|
|
|
+// }
|
|
|
|
|
+
|
|
|
|
|
+// public void add (TKey key, TValue value) {
|
|
|
|
|
+// rw_lock.writer_lock ();
|
|
|
|
|
+// HashSet<TValue> hash_set;
|
|
|
|
|
+// if(!lookup.try_get (key, out hash_set)) {
|
|
|
|
|
+// hash_set = new HashSet<TValue>(item_hash_func, item_equal_func);
|
|
|
|
|
+// lookup[key] = hash_set;
|
|
|
|
|
+// }
|
|
|
|
|
+// if(hash_set.add(value)){
|
|
|
|
|
+// item_count ++;
|
|
|
|
|
+// }
|
|
|
|
|
+// rw_lock.writer_unlock ();
|
|
|
|
|
+// }
|
|
|
|
|
+
|
|
|
|
|
+// public void add_all (TKey key, Enumerable<TValue> values) {
|
|
|
|
|
+// rw_lock.writer_lock ();
|
|
|
|
|
+// HashSet<TValue> hash_set;
|
|
|
|
|
+// if(!lookup.try_get (key, out hash_set)) {
|
|
|
|
|
+// hash_set = new HashSet<TValue>(item_hash_func, item_equal_func);
|
|
|
|
|
+// lookup[key] = hash_set;
|
|
|
|
|
+// }
|
|
|
|
|
+// foreach (var item in values) {
|
|
|
|
|
+// if(hash_set.add (item)) {
|
|
|
|
|
+// item_count++;
|
|
|
|
|
+// }
|
|
|
|
|
+// }
|
|
|
|
|
+// rw_lock.writer_unlock ();
|
|
|
|
|
+// }
|
|
|
|
|
+
|
|
|
|
|
+// public void remove_from (TKey key, TValue item, Invercargill.EqualityDelegate<TValue>? equator = null) {
|
|
|
|
|
+// rw_lock.writer_lock ();
|
|
|
|
|
+// HashSet<TValue> hash_set;
|
|
|
|
|
+// if(lookup.try_get (key, out hash_set)) {
|
|
|
|
|
+// item_count -= hash_set.length;
|
|
|
|
|
+// hash_set.remove(item); // TODO do something with equator?
|
|
|
|
|
+// item_count += hash_set.length;
|
|
|
|
|
+// remove_if_empty(key, hash_set);
|
|
|
|
|
+// }
|
|
|
|
|
+// rw_lock.writer_unlock ();
|
|
|
|
|
+// }
|
|
|
|
|
+
|
|
|
|
|
+// public void remove_all_from (TKey key, Enumerable<TValue> items, Invercargill.EqualityDelegate<TValue>? equator = null) {
|
|
|
|
|
+// rw_lock.writer_lock ();
|
|
|
|
|
+// HashSet<TValue> hash_set;
|
|
|
|
|
+// if(lookup.try_get (key, out hash_set)) {
|
|
|
|
|
+// item_count -= hash_set.length;
|
|
|
|
|
+// hash_set.remove_all(items, equator);
|
|
|
|
|
+// item_count += hash_set.length;
|
|
|
|
|
+// remove_if_empty(key, hash_set);
|
|
|
|
|
+// }
|
|
|
|
|
+// rw_lock.writer_unlock ();
|
|
|
|
|
+// }
|
|
|
|
|
+
|
|
|
|
|
+// public void remove (TValue item, Invercargill.EqualityDelegate<TValue>? equator = null) {
|
|
|
|
|
+// rw_lock.writer_lock ();
|
|
|
|
|
+// foreach (var kv in lookup) {
|
|
|
|
|
+// item_count -= kv.value.length;
|
|
|
|
|
+// kv.value.remove (item, equator);
|
|
|
|
|
+// item_count += kv.value.length;
|
|
|
|
|
+// remove_if_empty(kv.key, kv.value);
|
|
|
|
|
+// }
|
|
|
|
|
+// rw_lock.writer_unlock ();
|
|
|
|
|
+// }
|
|
|
|
|
+
|
|
|
|
|
+// public void remove_all (Enumerable<TValue> items, Invercargill.EqualityDelegate<TValue>? equator = null) {
|
|
|
|
|
+// rw_lock.writer_lock ();
|
|
|
|
|
+// foreach (var kv in lookup) {
|
|
|
|
|
+// item_count -= kv.value.length;
|
|
|
|
|
+// kv.value.remove_all (items, equator);
|
|
|
|
|
+// item_count += kv.value.length;
|
|
|
|
|
+// remove_if_empty(kv.key, kv.value);
|
|
|
|
|
+// }
|
|
|
|
|
+// rw_lock.writer_unlock ();
|
|
|
|
|
+// }
|
|
|
|
|
+
|
|
|
|
|
+// public bool clear_key (TKey key) {
|
|
|
|
|
+// rw_lock.writer_lock ();
|
|
|
|
|
+// HashSet<TValue> hash_set;
|
|
|
|
|
+// var result = lookup.remove (key, out hash_set);
|
|
|
|
|
+// if(result) {
|
|
|
|
|
+// item_count -= hash_set.length;
|
|
|
|
|
+// }
|
|
|
|
|
+// rw_lock.writer_unlock ();
|
|
|
|
|
+// return result;
|
|
|
|
|
+// }
|
|
|
|
|
+
|
|
|
|
|
+// public void clear () {
|
|
|
|
|
+// rw_lock.writer_lock ();
|
|
|
|
|
+// lookup.clear();
|
|
|
|
|
+// item_count = 0;
|
|
|
|
|
+// rw_lock.writer_unlock ();
|
|
|
|
|
+// }
|
|
|
|
|
+
|
|
|
|
|
+// private void remove_if_empty(TKey key, HashSet<TValue> hash_set) {
|
|
|
|
|
+// if(hash_set.length == 0) {
|
|
|
|
|
+// lookup.remove(key);
|
|
|
|
|
+// }
|
|
|
|
|
+// }
|
|
|
|
|
+
|
|
|
|
|
+// }
|
|
|
|
|
+
|
|
|
|
|
+// }
|