|
|
@@ -1,3 +1,4 @@
|
|
|
+using Invercargill.DataStructures;
|
|
|
namespace Invercargill.Modifiers {
|
|
|
|
|
|
public class TakeLast<T> : Enumerable<T> {
|
|
|
@@ -21,59 +22,22 @@ namespace Invercargill.Modifiers {
|
|
|
}
|
|
|
|
|
|
public override Tracker<T> get_tracker() {
|
|
|
- var tracker = input.get_tracker();
|
|
|
- DataStructures.RingBuffer<T>? buffer = null;
|
|
|
- var index = 0;
|
|
|
- var input_exhausted = false;
|
|
|
- var output_index = 0;
|
|
|
- var output_started = false;
|
|
|
- var actual_count = 0;
|
|
|
-
|
|
|
- return new AdvanceTracker<T>((out obj) => {
|
|
|
- obj = null;
|
|
|
-
|
|
|
- // First, fill the buffer with all items from the input
|
|
|
- if (!input_exhausted) {
|
|
|
- // Initialize buffer with the requested size
|
|
|
- buffer = new DataStructures.RingBuffer<T>((uint)n_items);
|
|
|
-
|
|
|
- while(tracker.has_next()) {
|
|
|
- var item = tracker.get_next();
|
|
|
-
|
|
|
- // Add item to buffer, overwriting oldest if buffer is full
|
|
|
- buffer.set((uint)index, item);
|
|
|
- index = (index + 1) % n_items;
|
|
|
-
|
|
|
- // Track how many items we've actually seen
|
|
|
- if (actual_count < n_items) {
|
|
|
- actual_count++;
|
|
|
- }
|
|
|
- }
|
|
|
- input_exhausted = true;
|
|
|
-
|
|
|
- // Set the output index to the oldest item
|
|
|
- if (actual_count == n_items) {
|
|
|
- // Buffer is full, oldest item is at current index
|
|
|
- output_index = index;
|
|
|
- } else {
|
|
|
- // Buffer not full, start from beginning
|
|
|
- output_index = 0;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- // After exhausting the input, return items from the buffer
|
|
|
- if (!output_started) {
|
|
|
- output_started = true;
|
|
|
- }
|
|
|
-
|
|
|
- if(output_index < actual_count) {
|
|
|
- obj = buffer.get((uint)output_index);
|
|
|
- output_index++;
|
|
|
- return true;
|
|
|
- }
|
|
|
-
|
|
|
- return false;
|
|
|
- });
|
|
|
+ var buffer = new RingBuffer<T>(n_items);
|
|
|
+ var write_index = n_items;
|
|
|
+ foreach (var item in input) {
|
|
|
+ non_error(() => buffer[write_index] = item);
|
|
|
+ write_index++;
|
|
|
+ }
|
|
|
+
|
|
|
+ if(write_index - n_items <= n_items) {
|
|
|
+ return buffer.take(write_index).get_tracker();
|
|
|
+ }
|
|
|
+
|
|
|
+ var read_index = write_index - n_items;
|
|
|
+ return new LambdaTracker<T>(
|
|
|
+ () => read_index < write_index,
|
|
|
+ () => buffer.get_or_default(read_index++)
|
|
|
+ );
|
|
|
}
|
|
|
}
|
|
|
|