From 7e1f1c5e4a732b714839a2405b5e7deced39e131 Mon Sep 17 00:00:00 2001 From: abux Date: Mon, 13 Jul 2026 16:41:14 +0100 Subject: [PATCH] Added RingBuffer --- src/gtl.zig | 13 +++++++ src/ring_buffer.zig | 91 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 104 insertions(+) create mode 100644 src/ring_buffer.zig diff --git a/src/gtl.zig b/src/gtl.zig index 56a014c..6e05095 100644 --- a/src/gtl.zig +++ b/src/gtl.zig @@ -13,6 +13,7 @@ pub const ansi = @import("ansi.zig"); pub const Handle = @import("handle.zig").Handle; pub const SlotMap = @import("slot_map.zig").SlotMap; pub const KeyedSlotMap = @import("keyed_slot_map.zig").KeyedSlotMap; +pub const RingBuffer = @import("ring_buffer.zig").RingBuffer; pub const TypeID = @import("type_id.zig").of; // @@ -126,4 +127,16 @@ test "SlotMap" { log.debug("...", .{}); log.trace("...", .{}); } + + var ring: RingBuffer([]const u8, 3) = .{}; + + try ring.push("Hello"); + try ring.push("World"); + try ring.push("!"); + + var i: usize = 0; + while (ring.pop()) |data| { + i += 1; + std.debug.print("ring[{}] = \"{s}\"\n", .{ i, data }); + } } diff --git a/src/ring_buffer.zig b/src/ring_buffer.zig new file mode 100644 index 0000000..9926d0e --- /dev/null +++ b/src/ring_buffer.zig @@ -0,0 +1,91 @@ +const std = @import("std"); + +/// ---------------------------------------------------- +/// ---------------------------------------------------- +pub fn RingBuffer( + comptime T: type, + comptime Capacity: usize, +) type { + return struct { + const Self = @This(); + + // + // FIELDS + // + + buffers: [Capacity]T = std.mem.zeroes([Capacity]T), + head: usize = 0, + tail: usize = 0, + count: usize = 0, + + /// ---------------------------------------------------- + /// ---------------------------------------------------- + pub fn isEmpty(self: *const Self) bool { + return self.count == 0; + } + + /// ---------------------------------------------------- + /// ---------------------------------------------------- + pub fn isFull(self: *const Self) bool { + return self.count == Capacity; + } + + /// ---------------------------------------------------- + /// ---------------------------------------------------- + pub fn push(self: *Self, value: T) error{Full}!void { + if (self.isFull()) return error.Full; + self.buffers[self.tail] = value; + self.tail = (self.tail + 1) % Capacity; + self.count += 1; + } + + /// ---------------------------------------------------- + /// ---------------------------------------------------- + pub fn pushOverwrite(self: *Self, value: T) void { + if (self.isFull()) { + self.head = (self.head + 1) % Capacity; + } else { + self.count += 1; + } + + self.buffers[self.tail] = value; + self.tail = (self.tail + 1) % Capacity; + } + + /// ---------------------------------------------------- + /// ---------------------------------------------------- + pub fn pop(self: *Self) ?T { + if (self.isEmpty()) return null; + const item = self.buffers[self.head]; + self.head = (self.head + 1) % Capacity; + self.count -= 1; + return item; + } + + /// ---------------------------------------------------- + /// ---------------------------------------------------- + pub fn peek(self: *const Self) ?T { + if (self.isEmpty()) return null; + return self.buffers[self.head]; + } + + /// ---------------------------------------------------- + /// ---------------------------------------------------- + pub fn at(self: *const Self, index: usize) ?T { + if (index >= self.count) return null; + return self.buffers[(self.head + index) % Capacity]; + } + + /// ---------------------------------------------------- + /// ---------------------------------------------------- + pub fn len(self: *const Self) usize { + return self.count; + } + + /// ---------------------------------------------------- + /// ---------------------------------------------------- + pub fn capacity(_: *const Self) usize { + return Capacity; + } + }; +}