|
@@ -0,0 +1,140 @@
|
|
|
|
+
|
|
|
|
+namespace Invercargill.DataStructures {
|
|
|
|
+
|
|
|
|
+ public class SortedVector<T> : Enumerable<T>, Lot<T>, ReadOnlyCollection<T>, ReadOnlyAddressable<T>, Collection<T> {
|
|
|
|
+
|
|
|
|
+ private Vector<T> vector;
|
|
|
|
+ private CompareDelegate<T> comparitor;
|
|
|
|
+
|
|
|
|
+ public SortedVector(owned CompareDelegate<T>? comparitor = null) {
|
|
|
|
+ this.comparitor = (owned)comparitor ?? Operators.comparison<T>();
|
|
|
|
+ vector = new Vector<T>();
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ public override int? peek_count() {
|
|
|
|
+ return vector.count();
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ public override EnumerableInfo get_info() {
|
|
|
|
+ return new EnumerableInfo.infer_ultimate (this, EnumerableCategory.IN_MEMORY);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ public override Tracker<T> get_tracker() {
|
|
|
|
+ return vector.get_tracker();
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ public void add(T item) {
|
|
|
|
+ lock(vector) {
|
|
|
|
+ uint index;
|
|
|
|
+ optimised_search(item, out index);
|
|
|
|
+ try {
|
|
|
|
+ vector.insert_at(index, item);
|
|
|
|
+ }
|
|
|
|
+ catch(Error e) {
|
|
|
|
+ assert_no_error(e);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ private bool optimised_search(T item, out uint index) {
|
|
|
|
+ if(vector.count() == 0) {
|
|
|
|
+ index = 0;
|
|
|
|
+ return false;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ // Could it be at the end?
|
|
|
|
+ index = vector.count()-1;
|
|
|
|
+ var end_cmp = compare_index(item, index);
|
|
|
|
+ if(end_cmp == 0) {
|
|
|
|
+ return true;
|
|
|
|
+ }
|
|
|
|
+ if(end_cmp > 0) {
|
|
|
|
+ index++;
|
|
|
|
+ var cmp = compare_index(item, index);
|
|
|
|
+ if(cmp == null || cmp < 0) {
|
|
|
|
+ return false;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ else {
|
|
|
|
+ var cmp = compare_index(item, index-1);
|
|
|
|
+ if(cmp == null || cmp > 0) {
|
|
|
|
+ return false;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ // Could it be at the start?
|
|
|
|
+ if(index != 0) {
|
|
|
|
+ index = 0;
|
|
|
|
+ var first_cmp = compare_index(item, index);
|
|
|
|
+ if(first_cmp == 0) {
|
|
|
|
+ return true;
|
|
|
|
+ }
|
|
|
|
+ if(first_cmp > 0) {
|
|
|
|
+ index++;
|
|
|
|
+ var cmp = compare_index(item, index);
|
|
|
|
+ if(cmp == null || cmp < 0) {
|
|
|
|
+ return false;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ else {
|
|
|
|
+ var cmp = compare_index(item, index-1);
|
|
|
|
+ if(cmp == null || cmp > 0) {
|
|
|
|
+ return false;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ return binary_search(s => comparitor(item, s), out index);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ private int? compare_index(T item, uint index) {
|
|
|
|
+ if(vector.count() <= index) {
|
|
|
|
+ return null;
|
|
|
|
+ }
|
|
|
|
+ return comparitor(item, vector.get_or_default(index));
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+ public void add_all(Enumerable<T> items) {
|
|
|
|
+ items.iterate(i => add(i));
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ public void remove_first_where(Invercargill.PredicateDelegate<T> predicate) {
|
|
|
|
+ remove_items(predicate, true);
|
|
|
|
+ }
|
|
|
|
+ public void remove_all_where(Invercargill.PredicateDelegate<T> predicate) {
|
|
|
|
+ remove_items(predicate, false);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ private void remove_items(Invercargill.PredicateDelegate<T> predicate, bool first_only) {
|
|
|
|
+ lock(vector) {
|
|
|
|
+ if(first_only)
|
|
|
|
+ vector.remove_first_where(predicate);
|
|
|
|
+ else
|
|
|
|
+ vector.remove_all_where(predicate);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ public void clear() {
|
|
|
|
+ lock(vector) {
|
|
|
|
+ vector.clear();
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ public new T get(uint index) throws IndexError {
|
|
|
|
+ return vector[index];
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ public bool try_get(uint index, out T value) {
|
|
|
|
+ var result = vector.try_get(index, out value);
|
|
|
|
+ return result;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ public uint? first_index_of(Invercargill.PredicateDelegate<T> predicate) {
|
|
|
|
+ var result = vector.first_index_of(predicate);
|
|
|
|
+ return result;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+}
|