Series.vala 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215
  1. namespace Invercargill.DataStructures {
  2. public class Series<T> : Enumerable<T>, Lot<T>, ReadOnlyCollection<T>, Collection<T> {
  3. [Compact]
  4. internal class SeriesItem<T> {
  5. public SeriesItem<T>* next;
  6. public T value;
  7. public SeriesItem(owned T value) {
  8. this.value = (owned)value;
  9. }
  10. }
  11. internal SeriesItem<T>* root;
  12. internal SeriesItem<T>* end;
  13. private int n_items = 0;
  14. public Series() {}
  15. public override uint? peek_count() {
  16. return n_items;
  17. }
  18. public override EnumerableInfo get_info() {
  19. return new EnumerableInfo.infer_ultimate (this, EnumerableCategory.IN_MEMORY);
  20. }
  21. public override Tracker<T> get_tracker() {
  22. return new SeriesTracker<T>(root);
  23. }
  24. public override uint length { get { return n_items; }}
  25. public override T[] to_array () {
  26. var arr = new T[n_items];
  27. var count = 0;
  28. iterate(i => {
  29. arr[count] = i;
  30. count++;
  31. });
  32. return arr;
  33. }
  34. public void add(T item) {
  35. lock(root) {
  36. n_items++;
  37. SeriesItem<T>* si = new SeriesItem<T>(item);
  38. if(root == null) {
  39. root = si;
  40. end = si;
  41. return;
  42. }
  43. end->next = si;
  44. end = si;
  45. }
  46. }
  47. public void add_all(Enumerable<T> items) {
  48. lock(root) {
  49. SeriesItem<T>* chain_start = null;
  50. SeriesItem<T>* chain_end = null;
  51. foreach (var item in items) {
  52. n_items++;
  53. SeriesItem<T>* si = new SeriesItem<T>(item);
  54. if(chain_start == null) {
  55. chain_start = si;
  56. chain_end = si;
  57. continue;
  58. }
  59. chain_end->next = si;
  60. chain_end = si;
  61. }
  62. if(root == null) {
  63. root = chain_start;
  64. end = chain_end;
  65. return;
  66. }
  67. end->next = chain_start;
  68. end = chain_end;
  69. }
  70. }
  71. public void add_start(T item) {
  72. lock(root) {
  73. n_items++;
  74. SeriesItem<T>* si = new SeriesItem<T>(item);
  75. if(root == null) {
  76. end = si;
  77. }
  78. si->next = root;
  79. root = si;
  80. }
  81. }
  82. public void add_all_start(Enumerable<T> items) {
  83. lock(root) {
  84. SeriesItem<T>* chain_start = null;
  85. SeriesItem<T>* chain_end = null;
  86. foreach (var item in items) {
  87. n_items++;
  88. SeriesItem<T>* si = new SeriesItem<T>(item);
  89. if(chain_start == null) {
  90. chain_start = si;
  91. chain_end = si;
  92. continue;
  93. }
  94. chain_end->next = si;
  95. chain_end = si;
  96. }
  97. if(root == null) {
  98. end = chain_end;
  99. }
  100. chain_end->next = root;
  101. root = chain_start;
  102. }
  103. }
  104. public T pop_start() throws SequenceError {
  105. SequenceError? e = null;
  106. T? item = null;
  107. lock(root) {
  108. if(root == null) {
  109. e = new SequenceError.NO_ELEMENTS("Series contains no elements");
  110. }
  111. else {
  112. var old_root = root;
  113. root = root->next;
  114. item = old_root->value;
  115. delete old_root;
  116. if(root == null) {
  117. end = null;
  118. }
  119. }
  120. }
  121. if(e != null) {
  122. throw e;
  123. }
  124. return item;
  125. }
  126. public void remove_first_where(Invercargill.PredicateDelegate<T> predicate) {
  127. remove_items(predicate, true);
  128. }
  129. public void remove_all_where(Invercargill.PredicateDelegate<T> predicate) {
  130. remove_items(predicate, false);
  131. }
  132. private void remove_items(Invercargill.PredicateDelegate<T> predicate, bool first_only) {
  133. lock(root) {
  134. SeriesItem<T>* previous = null;
  135. SeriesItem<T>* node = root;
  136. while(node != null) {
  137. if(predicate(node->value)) {
  138. if(previous == null) {
  139. root = node->next;
  140. }
  141. else {
  142. previous->next = node->next;
  143. }
  144. delete node;
  145. if(first_only) {
  146. break;
  147. }
  148. }
  149. previous = node;
  150. node = node->next;
  151. }
  152. }
  153. }
  154. public void clear() {
  155. lock(root) {
  156. n_items = 0;
  157. SeriesItem<T>* node = root;
  158. while(node != null) {
  159. SeriesItem<T>* removed = node;
  160. node = node->next;
  161. // Delete won't unref the value so explicitly set to null before deleting
  162. removed->value = null;
  163. delete removed;
  164. }
  165. root = null;
  166. end = null;
  167. }
  168. }
  169. ~Series() {
  170. clear();
  171. }
  172. private class SeriesTracker<T> : Tracker<T> {
  173. private weak SeriesItem<T>* current;
  174. public SeriesTracker(SeriesItem<T>* root) {
  175. current = root;
  176. }
  177. public override bool has_next() {
  178. return current != null;
  179. }
  180. public override T get_next() {
  181. var value = current->value;
  182. current = current->next;
  183. return value;
  184. }
  185. }
  186. }
  187. }