Billy Barrow 3 долоо хоног өмнө
parent
commit
f8d289c17a

+ 17 - 3
src/lib/DataStructures/BinaryData.vala

@@ -32,7 +32,7 @@ namespace Invercargill.DataStructures {
         }
 
         public BinaryData.from_enumerable(Enumerable<uint8> data) {
-            chunks = Invercargill.single(data.to_vector());
+            chunks = Invercargill.single(data.to_buffer());
             endianness = Endianness.Native;
         }
 
@@ -51,6 +51,16 @@ namespace Invercargill.DataStructures {
             endianness = Endianness.Native;
         }
 
+        public BinaryData.from_hex(string data) {
+            var groomed = data.replace(" ", "").replace("-", "").replace(":", "").replace("0x", "");
+            var buffer = new Buffer<uint8>(groomed.length/2);
+            for(var i = 0; i < groomed.length/2; i++) {
+                non_error(() => buffer[i] = (uint8)uint.parse(groomed[i*2:(i+1)*2], 16));
+            }
+            chunks = Invercargill.single(buffer);
+            endianness = Endianness.Native;
+        }
+
         public void append(Enumerable<uint8> data) {
             lock(chunks) {
                 chunks = chunks.with(data);
@@ -59,7 +69,7 @@ namespace Invercargill.DataStructures {
 
         public void append_all(Enumerable<Enumerable<uint8>> data) {
             lock(chunks) {
-                chunks = chunks.concat(data.to_vector());
+                chunks = chunks.concat(data.to_buffer());
             }
         }
 
@@ -71,7 +81,7 @@ namespace Invercargill.DataStructures {
 
         public void prepend_all(Enumerable<Enumerable<uint8>> data) {
             lock(chunks) {
-                chunks = data.concat(chunks.to_vector());
+                chunks = data.concat(chunks.to_buffer());
             }
         }
 
@@ -438,6 +448,10 @@ namespace Invercargill.DataStructures {
             return Base64.encode(to_array());
         }
 
+        public string to_hex() {
+            return to_string(i => i.to_string("%x"));
+        }
+
         public Bytes to_bytes() {
             return new Bytes(to_array());
         }

+ 13 - 1
src/lib/DataStructures/Buffer.vala

@@ -8,7 +8,12 @@ namespace Invercargill.DataStructures {
         private SafeWriteFunc<T>? safe_write;
 
         public override Tracker<T> get_tracker () {
-            return new AddressableTracker<T> (this);
+            int pos = 0;
+            var read = safe_read;
+            if(read == null) {
+                read = (a, i) => a[i];
+            }
+            return new LambdaTracker<T> (() => pos < array.length, () => read(array, pos++));
         }
         public override int? peek_count () {
             return array.length;
@@ -72,6 +77,13 @@ namespace Invercargill.DataStructures {
             return null;
         }
 
+        public override int count(PredicateDelegate<T>? predicate = null) {
+            if(predicate == null) {
+                return array.length;
+            }
+            return base.count(predicate);
+        }
+
     }
 
 }

+ 90 - 0
src/lib/DataStructures/RingBuffer.vala

@@ -0,0 +1,90 @@
+
+namespace Invercargill.DataStructures {
+
+    public class RingBuffer<T> : Enumerable<T>, Lot<T>, ReadOnlyAddressable<T>, Addressable<T> {
+
+        private T[] array;
+        private SafeReadFunc<T>? safe_read;
+        private SafeWriteFunc<T>? safe_write;
+
+        public override Tracker<T> get_tracker () {
+            int pos = 0;
+            return new LambdaTracker<T> (() => array.length > 0, () => safe_read(array, pos++));
+        }
+        public override int? peek_count () {
+            return array.length;
+        }
+        public override EnumerableInfo get_info () {
+            return new EnumerableInfo.infer_ultimate(this, EnumerableCategory.IN_MEMORY);
+        }
+
+        public RingBuffer(uint size) {
+            array = new T[size];
+            safe_read = get_safe_read_function_for<T>();
+            if(safe_read == null) {
+                safe_read = (a, i) => a[i];
+            }
+            safe_write = get_safe_write_function_for<T>();
+            if(safe_write == null) {
+                safe_write = (a, i, v) => a[i] = v;
+            }
+        }
+
+        public Enumerable<T> once() {
+            return take(array.length);
+        }
+
+        internal RingBuffer.take_array(owned T[] array) {
+            this.array = (owned)array;
+            safe_read = get_safe_read_function_for<T>();
+            if(safe_read == null) {
+                safe_read = (a, i) => a[i];
+            }
+            safe_write = get_safe_write_function_for<T>();
+            if(safe_write == null) {
+                safe_write = (a, i, v) => a[i] = v;
+            }
+        }
+
+        public new void set (uint index, T item) throws IndexError {
+            var real_index = index % array.length;
+            safe_write(array, real_index, item);
+        }
+
+        public new T get (uint index) {
+            var real_index = index % array.length;
+            return safe_read(array, real_index);
+        }
+
+        public bool try_get (uint index, out T value) {
+            try {
+                value = get(index);
+                return true;
+            }
+            catch {
+                value = null;
+                return false;
+            }
+        }
+
+        public uint? first_index_of (Invercargill.PredicateDelegate<T> predicate) {
+            var i = 0;
+            foreach (var item in this) {
+                if(predicate(item)) {
+                    return i;
+                }
+                i++;
+            }
+            return null;
+        }
+
+        public override int count(PredicateDelegate<T>? predicate = null) {
+            if(predicate == null) {
+                return array.length;
+            }
+            return base.count(predicate);
+        }
+
+    }
+
+}

+ 11 - 13
src/lib/DataStructures/Series.vala

@@ -2,7 +2,6 @@ namespace Invercargill.DataStructures {
 
     public class Series<T> : Enumerable<T>, Lot<T>, ReadOnlyCollection<T>, Collection<T> {
      
-        //  [CCode (ref_function = "invercargill_data_structures_series_series_item_up", unref_function = "invercargill_data_structures_series_series_item_down")]
         [Compact]
         internal class SeriesItem<T> {
             public SeriesItem<T>* next;
@@ -11,18 +10,6 @@ namespace Invercargill.DataStructures {
             public SeriesItem(owned T value) {
                 this.value = (owned)value;
             }
-
-
-            // Carefully unlink series items when destructed.
-            // Very large series sometimes cause a segfault without this
-            //  ~SeriesItem() {
-            //      unowned SeriesItem<T> n = next;
-            //      while(n != null) {
-            //          unowned SeriesItem<T> c = n;
-            //          n = n.next;
-            //          c.next = null;
-            //      }
-            //  }
         }
 
         internal SeriesItem<T>* root;
@@ -90,6 +77,7 @@ namespace Invercargill.DataStructures {
                         else {
                             previous->next = node->next;
                         }
+                        delete node;
                         if(first_only) {
                             break;
                         }
@@ -103,11 +91,21 @@ namespace Invercargill.DataStructures {
         public void clear() {
             lock(root) {
                 n_items = 0;
+                SeriesItem<T>* node = root;
+                while(node != null) {
+                    SeriesItem<T>* removed = node;
+                    node = node->next;
+                    delete removed;
+                }
                 root = null;
                 end = null;
             }
         }
 
+        ~Series() {
+            clear();
+        }
+
         private class SeriesTracker<T> : Tracker<T> {
 
             private weak SeriesItem<T>* current;

+ 4 - 25
src/lib/DataStructures/SortedSeries.vala

@@ -105,7 +105,7 @@ namespace Invercargill.DataStructures {
                 }
             }
 
-            SeriesNode<T>* new_node = new SeriesNode<T> (Invercargill.single<T>(item).to_series(), nil);
+            SeriesNode<T>* new_node = new SeriesNode<T> (item, nil);
             new_node->parent = parent;
             if(parent == null) {
                 root = new_node;
@@ -224,7 +224,6 @@ namespace Invercargill.DataStructures {
             SeriesNodeItem<T>* values;
 
             public TreeTracker(SortedSeries<T> series) {
-                print("New tracker!\n");
                 this.series = series;
                 node = series.root;
                 while(node->left_child != series.nil) {
@@ -240,37 +239,17 @@ namespace Invercargill.DataStructures {
             public override T get_next () {
                 if(values != null) {
                     var item = values->item;
-                    print(@"get next $((int)item)\n");
                     values = values->next;
-                    print(@"next up $((int)values)\n");
                     return item;
                 }
                 node = next_node;
-                values = node->first_value;
+                var item = node->first_value->item;
+                values = node->first_value->next;
                 find_next_node();
-                return values->item;
+                return item;
             }
 
             private void find_next_node() {
-                //  next_node = null;
-                //  if(node.right_child != series.nil) {
-                //      next_node = node.right_child;
-                //      while(next_node.left_child != series.nil) {
-                //          next_node = next_node.left_child;
-                //      }
-                //  }
-                //  else if(node.parent == null) {
-                //      next_node = null;
-                //  }
-                //  else if(node.parent.left_child == node) {
-                //      next_node = node.parent;
-                //  }
-                //  else if(node.parent.parent.right_child == node.parent) {
-                //      next_node = null;
-                //  }
-                //  else {
-                //      next_node = node.parent.parent;
-                //  }
                 next_node = null;
                 if (node == null) return;
                 // standard inorder successor:

+ 6 - 5
src/lib/Debug.vala

@@ -28,8 +28,9 @@ namespace Invercargill {
                 .replace(COLOUR_CATEGORY, ""));
         }
 
-        public static void print_enumerable_dump<T>(Enumerable<T> enumerable, TransformDelegate<T, string> stringifier, string additional_message = "", DebugOutputDelegate? output_func = null, bool formatting = true) {
+        public static void print_enumerable_dump<T>(Enumerable<T> enumerable, StringifyDelegate<T>? stringifier = null, string additional_message = "", DebugOutputDelegate? output_func = null, bool formatting = true) {
             var output = get_delegate(output_func, formatting);
+            var to_str = stringifier ?? Operators.stringify<T>();
 
             output("\n\n" + format_colour(COLOUR_DEBUG, "Invercargill enumerable debug dump: ") + format_colour(COLOUR_PROGRAM, additional_message) + "\n");
             print_enumerable_info(enumerable.get_info(), 0, output_func, formatting);
@@ -37,7 +38,7 @@ namespace Invercargill {
             var count = 0;
             output(format_colour(COLOUR_DEBUG, "\nBegin iterating enumerable:\n"));
             foreach (var item in enumerable) {
-                output(format_colour(COLOUR_DEBUG, @" $count:\t") + format_colour(COLOUR_PROGRAM, stringifier(item)) + "\n");
+                output(format_colour(COLOUR_DEBUG, @" $count:\t") + format_colour(COLOUR_PROGRAM, to_str(item)) + "\n");
                 count++;
             }
 
@@ -156,16 +157,16 @@ namespace Invercargill {
 
     internal class TraceEnumerable<T> : Enumerable<T> {
         private Enumerable<T> input;
-        private TransformDelegate<T, string> stringifier;
+        private StringifyDelegate<T>? stringifier;
         private string additional_message;
         private DebugOutputDelegate? output_func;
         private bool formatting;
         private uint counter = 0;
 
-        public TraceEnumerable(owned Enumerable<T> input, EnumerableInfo info, owned TransformDelegate<T, string> stringifier, string additional_message = "", owned DebugOutputDelegate? output_func, bool formatting) {
+        public TraceEnumerable(owned Enumerable<T> input, EnumerableInfo info, owned StringifyDelegate<T>? stringifier = null, string additional_message = "", owned DebugOutputDelegate? output_func, bool formatting) {
             this.input = (owned)input;
             this.additional_message = additional_message;
-            this.stringifier = (owned)stringifier;
+            this.stringifier = (owned)stringifier ?? Operators.stringify<T>();
             this.output_func = (owned)output_func;
             this.formatting = formatting;
             DebugPrinter.print_trace_registration(info, additional_message, output_func, formatting);

+ 2 - 0
src/lib/Delegates.vala

@@ -20,6 +20,8 @@ namespace Invercargill {
 
     public delegate uint HashDelegate<T>(T item);
 
+    public delegate string StringifyDelegate<T>(T item);
+
     public delegate Tout ErrorThrowingDelegate<Tin, Tout>(Tin item) throws Error;
 
     public delegate Tout ErrorCatchingDelegate<Tin, Tout>(Tin item, Error error);

+ 18 - 4
src/lib/Enumerable.vala

@@ -52,7 +52,11 @@ namespace Invercargill {
 
         public virtual T[] to_array() {
             T[] array;
-            array = new T[1024];
+            var peeked = peek_count();
+            if(peeked == null)
+                array = new T[1024];
+            else
+                array = new T[(int)peeked];
 
             var index = 0;
             foreach (var item in this) {
@@ -72,6 +76,15 @@ namespace Invercargill {
             return new Buffer<T>.take_array(to_array());
         }
 
+        public virtual RingBuffer<T> to_ring_buffer(uint? size = null) {
+            if(size == null) {
+                return new RingBuffer<T>.take_array(to_array());
+            }
+            var buffer = new RingBuffer<T>(size);
+            non_error(() => buffer.set_all(0, this));
+            return buffer;
+        }
+
         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
@@ -368,8 +381,9 @@ namespace Invercargill {
             return null;
         }
 
-        public virtual string to_string(TransformDelegate<T, string> stringifier, string seperator = "") {
+        public virtual string to_string(StringifyDelegate<T>? stringifier = null, string seperator = "") {
             bool is_first = true;
+            stringifier = stringifier ?? Operators.stringify<T>();
             return aggregate<string>("", (s, v) => {
                 if(is_first) {
                     is_first = false;
@@ -490,7 +504,7 @@ namespace Invercargill {
             return this;
         }
 
-        public virtual void debug_dump(TransformDelegate<T, string> stringifier, string additional_message = "", DebugOutputDelegate? output_func = null, bool formatting = true) {
+        public virtual void debug_dump(string additional_message = "", StringifyDelegate<T>? stringifier = null, DebugOutputDelegate? output_func = null, bool formatting = true) {
             DebugPrinter.print_enumerable_dump<T>(this, stringifier, additional_message, output_func, formatting);
         }
 
@@ -499,7 +513,7 @@ namespace Invercargill {
             return this;
         }
 
-        public virtual Enumerable<T> debug_trace(owned TransformDelegate<T, string> stringifier, string additional_message = "", owned DebugOutputDelegate? output_func = null, bool formatting = true) {
+        public virtual Enumerable<T> debug_trace(string additional_message = "", owned StringifyDelegate<T>? stringifier = null, owned DebugOutputDelegate? output_func = null, bool formatting = true) {
             return new TraceEnumerable<T>(this, get_info(), (owned)stringifier, additional_message, (owned)output_func, formatting);
         }
 

+ 1 - 1
src/lib/EnumerableProxy.vala

@@ -167,7 +167,7 @@ namespace Invercargill {
             return inner.single_or_default((owned)predicate);
         }
     
-        public override string to_string(TransformDelegate<T, string> stringifier, string separator = "") {
+        public override string to_string(StringifyDelegate<T>? stringifier = null, string separator = "") {
             return inner.to_string(stringifier, separator);
         }
     

+ 4 - 0
src/lib/Interfaces.vala

@@ -13,4 +13,8 @@ namespace Invercargill {
         public abstract int compare(T other);
     }
 
+    public interface Stringifyable {
+        public abstract string to_string();
+    }
+
 }

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

@@ -18,9 +18,9 @@ namespace Invercargill.Modifiers {
         }
 
         public override Tracker<T> get_tracker() {
-            // Hack for now
-            var list = input.to_gee_collection();
-            return new GeeTracker<T>(list, list.order_by ((a, b) => compare_func(a, b)));
+            var list = new DataStructures.SortedSeries<T>((a, b) => compare_func(a, b));
+            list.add_all(input);
+            return list.get_tracker();
         }
     }
 

+ 51 - 0
src/lib/Operators/Stringify.vala

@@ -0,0 +1,51 @@
+
+namespace Invercargill.Operators {
+    
+    public static StringifyDelegate<T> stringify<T>() {
+        var type = typeof(T);
+        if(type == typeof(string)) {
+            return i => (string)i;
+        }
+        else if(type == typeof(int)) {
+            return i => ((int)i).to_string();
+        }
+        else if(type == typeof(int8)) {
+            return i => ((int8)i).to_string();
+        }
+        else if(type == typeof(uint8)) {
+            return i => ((uint8)i).to_string();
+        }
+        else if(type == typeof(int16)) {
+            return i => ((int16)i).to_string();
+        }
+        else if(type == typeof(uint16)) {
+            return i => ((uint16)i).to_string();
+        }
+        else if(type == typeof(int32)) {
+            return i => ((int32)i).to_string();
+        }
+        else if(type == typeof(uint32)) {
+            return i => ((uint32)i).to_string();
+        }
+        else if(type == typeof(int64)) {
+            return i => ((int64?)i).to_string();
+        }
+        else if(type == typeof(uint64)) {
+            return i => ((uint64?)i).to_string();
+        }
+        else if(type == typeof(double)) {
+            return i => ((double?)i).to_string();
+        }
+        else if(type == typeof(float)) {
+            return i => ((float?)i).to_string();
+        }
+        else if(type.is_a(typeof(Stringifyable))) {
+            return i => ((Stringifyable)i).to_string();
+        }
+        else if(type.is_a(typeof(DataStructures.BinaryData))) {
+            return i => "0x" + ((DataStructures.BinaryData)i).to_string(b => b.to_string("%x"));
+        }
+        return i => @"[$(type.name()) at 0x$(((int)&i).to_string("%x"))]";
+    }
+
+}

+ 1 - 1
src/lib/StickyPromotion.vala

@@ -42,7 +42,7 @@ namespace Invercargill {
             return (TPromotion)new_wrap(inner.act(handler));
         }
 
-        public new TPromotion debug_trace(owned TransformDelegate<T, string> stringifier, string additional_message = "", owned DebugOutputDelegate? output_func = null, bool formatting = true) {
+        public new TPromotion debug_trace(string additional_message = "", owned StringifyDelegate<T>? stringifier = null, owned DebugOutputDelegate? output_func = null, bool formatting = true) {
             return (TPromotion)new_wrap(new TraceEnumerable<T>(this, get_info(), (owned)stringifier, additional_message, (owned)output_func, formatting));
         }
 

+ 2 - 0
src/lib/meson.build

@@ -84,6 +84,7 @@ sources += files('DataStructures/PropertyDictionary.vala')
 sources += files('DataStructures/SortedVector.vala')
 sources += files('DataStructures/SortedSeries.vala')
 sources += files('DataStructures/Buffer.vala')
+sources += files('DataStructures/RingBuffer.vala')
 
 sources += files('Mapping/Mapper.vala')
 sources += files('Mapping/PropertyMapper.vala')
@@ -92,6 +93,7 @@ sources += files('Mapping/ValueMapper.vala')
 sources += files('Operators/Comparison.vala')
 sources += files('Operators/Equality.vala')
 sources += files('Operators/Hash.vala')
+sources += files('Operators/Stringify.vala')
 
 invercargill = shared_library('invercargill', sources,
     dependencies: dependencies,

+ 5 - 5
src/tests/Integration/SortedSeries.vala

@@ -16,9 +16,9 @@ void sorted_series_tests() {
     Test.add_func("/invercargill/structure/sorted_series/add_many", () => {
 
         var series = new SortedSeries<int>();
-        var items = range(0, 1000000);
+        var items = range(0, 10000000);
         series.add_all(items);
-        assert(series.count() == 1000000);
+        assert_cmpint(series.count(), CompareOperator.EQ, 10000000);
 
         series.matches(items, (a, b) => a == b);
     });
@@ -26,9 +26,9 @@ void sorted_series_tests() {
     Test.add_func("/invercargill/structure/sorted_series/add_many_reversed", () => {
 
         var series = new SortedSeries<int>();
-        var items = range(1000000, 0, -1);
+        var items = range(10000000, 0, -1);
         series.add_all(items);
-        assert(series.count() == 1000000);
+        assert_cmpint(series.count(), CompareOperator.EQ, 10000000);
 
         series.matches(items, (a, b) => a == b);
     });
@@ -39,7 +39,7 @@ void sorted_series_tests() {
         var items = range(0, 100);
         series.add_all(items);
         series.add_all(items);
-        assert(series.count() == 200);
+        assert_cmpint(series.count(), CompareOperator.EQ, 200);
 
         series.matches(items.interleave(items), (a, b) => a == b);
     });

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

@@ -16,9 +16,9 @@ void sorted_vector_tests() {
     Test.add_func("/invercargill/structure/sorted_vector/add_many", () => {
 
         var series = new SortedVector<int>();
-        var items = range(0, 300000);
+        var items = range(0, 10000000);
         series.add_all(items);
-        assert(series.count() == 300000);
+        assert(series.count() == 10000000);
 
         series.matches(items, (a, b) => a == b);
     });

+ 8 - 0
src/tests/Speed/Buffer.vala

@@ -0,0 +1,8 @@
+using Invercargill;
+using Invercargill.DataStructures;
+
+void buffer_speed_test() {
+    var buf = new Buffer<int>(100000000);
+    uint pos = 0;
+    speed_test_runner_int("Buffer", buf, i => buf[pos++] = i, i => buf.set_all(pos += 10000000, i));
+}

+ 1 - 1
src/tests/Speed/Set.vala

@@ -3,5 +3,5 @@ using Invercargill.DataStructures;
 
 void set_speed_test() {
     var @set = new HashSet<int>();
-    speed_test_runner_int("Set", @set, i => @set.add(i), i => @set.union_with(i));
+    speed_test_runner_int("HashSet", @set, i => @set.add(i), i => @set.union_with(i));
 }

+ 7 - 0
src/tests/Speed/SortedSeries.vala

@@ -0,0 +1,7 @@
+using Invercargill;
+using Invercargill.DataStructures;
+
+void sorted_series_speed_test() {
+    var series = new SortedSeries<int>();
+    speed_test_runner_int("SortedSeries", series, i => series.add(i), i => series.add_all(i));
+}

+ 23 - 21
src/tests/TestRunner.vala

@@ -3,33 +3,35 @@ public static int main(string[] args) {
 
     Test.init(ref args);
 
-    //  where_tests();
-    //  select_tests();
-    //  select_many_tests();
-    //  gee_tests();
-    //  tracker_tests();
-    //  parallel_tests();
-    //  first_tests();
-    //  binary_data_tests();
-    //  sort_tests();
-    //  vector_tests();
+    where_tests();
+    select_tests();
+    select_many_tests();
+    gee_tests();
+    tracker_tests();
+    parallel_tests();
+    first_tests();
+    binary_data_tests();
+    sort_tests();
+    vector_tests();
     series_tests();
-    //  array_tests();
-    //  promotion_tests();
-    //  numbers_test();
-    //  dictionary_tests();
-    //  property_mapper_tests();
-    //  cache_tests();
-    //  sorted_vector_tests();
+    array_tests();
+    promotion_tests();
+    numbers_test();
+    dictionary_tests();
+    property_mapper_tests();
+    cache_tests();
+    sorted_vector_tests();
     sorted_series_tests();
 
     Test.run();
     
     series_speed_test();
-    //  vector_speed_test();
-    //  set_speed_test();
-    //  dictionary_speed_test();
-    //  fifo_speed_test();
+    vector_speed_test();
+    buffer_speed_test();
+    set_speed_test();
+    dictionary_speed_test();
+    sorted_series_speed_test();
+    fifo_speed_test();
 
 
     return 0;

+ 2 - 0
src/tests/meson.build

@@ -28,5 +28,7 @@ sources += files('Speed/Vector.vala')
 sources += files('Speed/Fifo.vala')
 sources += files('Speed/Dictionary.vala')
 sources += files('Speed/Set.vala')
+sources += files('Speed/SortedSeries.vala')
+sources += files('Speed/Buffer.vala')
 
 executable('invercargill-test-suite', sources, dependencies: dependencies, install: true)