namespace Invercargill.DataStructures { public class Series : Enumerable, Lot, ReadOnlyCollection, Collection { [Compact] internal class SeriesItem { public SeriesItem* next; public T value; public SeriesItem(owned T value) { this.value = (owned)value; } } internal SeriesItem* root; internal SeriesItem* end; private int n_items = 0; public Series() {} public override uint? peek_count() { return n_items; } public override EnumerableInfo get_info() { return new EnumerableInfo.infer_ultimate (this, EnumerableCategory.IN_MEMORY); } public override Tracker get_tracker() { return new SeriesTracker(root); } public override uint length { get { return n_items; }} public override T[] to_array () { var arr = new T[n_items]; var count = 0; iterate(i => { arr[count] = i; count++; }); return arr; } public void add(T item) { lock(root) { n_items++; SeriesItem* si = new SeriesItem(item); if(root == null) { root = si; end = si; return; } end->next = si; end = si; } } public void add_all(Enumerable items) { lock(root) { SeriesItem* chain_start = null; SeriesItem* chain_end = null; foreach (var item in items) { n_items++; SeriesItem* si = new SeriesItem(item); if(chain_start == null) { chain_start = si; chain_end = si; continue; } chain_end->next = si; chain_end = si; } if(root == null) { root = chain_start; end = chain_end; return; } end->next = chain_start; end = chain_end; } } public void add_start(T item) { lock(root) { n_items++; SeriesItem* si = new SeriesItem(item); if(root == null) { end = si; } si->next = root; root = si; } } public void add_all_start(Enumerable items) { lock(root) { SeriesItem* chain_start = null; SeriesItem* chain_end = null; foreach (var item in items) { n_items++; SeriesItem* si = new SeriesItem(item); if(chain_start == null) { chain_start = si; chain_end = si; continue; } chain_end->next = si; chain_end = si; } if(root == null) { end = chain_end; } chain_end->next = root; root = chain_start; } } public T pop_start() throws SequenceError { SequenceError? e = null; T? item = null; lock(root) { if(root == null) { e = new SequenceError.NO_ELEMENTS("Series contains no elements"); } else { var old_root = root; root = root->next; item = old_root->value; delete old_root; if(root == null) { end = null; } } } if(e != null) { throw e; } return item; } public void remove_first_where(Invercargill.PredicateDelegate predicate) { remove_items(predicate, true); } public void remove_all_where(Invercargill.PredicateDelegate predicate) { remove_items(predicate, false); } private void remove_items(Invercargill.PredicateDelegate predicate, bool first_only) { lock(root) { SeriesItem* previous = null; SeriesItem* node = root; while(node != null) { if(predicate(node->value)) { if(previous == null) { root = node->next; } else { previous->next = node->next; } delete node; if(first_only) { break; } } previous = node; node = node->next; } } } public void clear() { lock(root) { n_items = 0; SeriesItem* node = root; while(node != null) { SeriesItem* removed = node; node = node->next; // Delete won't unref the value so explicitly set to null before deleting removed->value = null; delete removed; } root = null; end = null; } } ~Series() { clear(); } private class SeriesTracker : Tracker { private weak SeriesItem* current; public SeriesTracker(SeriesItem* root) { current = root; } public override bool has_next() { return current != null; } public override T get_next() { var value = current->value; current = current->next; return value; } } } }