diff options
Diffstat (limited to 'src/datastruct')
| -rw-r--r-- | src/datastruct/array_list_collection.zig | 44 | ||||
| -rw-r--r-- | src/datastruct/cache_table.zig | 2 | ||||
| -rw-r--r-- | src/datastruct/circ_buf.zig | 35 |
3 files changed, 56 insertions, 25 deletions
diff --git a/src/datastruct/array_list_collection.zig b/src/datastruct/array_list_collection.zig new file mode 100644 index 000000000..d3fbddb13 --- /dev/null +++ b/src/datastruct/array_list_collection.zig @@ -0,0 +1,44 @@ +const std = @import("std"); +const Allocator = std.mem.Allocator; + +/// A collection of ArrayLists with methods for bulk operations. +pub fn ArrayListCollection(comptime T: type) type { + return struct { + const Self = ArrayListCollection(T); + const ArrayListT = std.ArrayListUnmanaged(T); + + // An array containing the lists that belong to this collection. + lists: []ArrayListT, + + // The collection will be initialized with empty ArrayLists. + pub fn init( + alloc: Allocator, + list_count: usize, + initial_capacity: usize, + ) Allocator.Error!Self { + const self: Self = .{ + .lists = try alloc.alloc(ArrayListT, list_count), + }; + + for (self.lists) |*list| { + list.* = try .initCapacity(alloc, initial_capacity); + } + + return self; + } + + pub fn deinit(self: *Self, alloc: Allocator) void { + for (self.lists) |*list| { + list.deinit(alloc); + } + alloc.free(self.lists); + } + + /// Clear all lists in the collection, retaining capacity. + pub fn reset(self: *Self) void { + for (self.lists) |*list| { + list.clearRetainingCapacity(); + } + } + }; +} diff --git a/src/datastruct/cache_table.zig b/src/datastruct/cache_table.zig index 40d36cc24..fbfb30d71 100644 --- a/src/datastruct/cache_table.zig +++ b/src/datastruct/cache_table.zig @@ -70,7 +70,7 @@ pub fn CacheTable( /// become a pointless check, but hopefully branch prediction picks /// up on it at that point. The memory cost isn't too bad since it's /// just bytes, so should be a fraction the size of the main table. - lengths: [bucket_count]u8 = [_]u8{0} ** bucket_count, + lengths: [bucket_count]u8 = @splat(0), /// An instance of the context structure. /// Must be initialized before calling any operations. diff --git a/src/datastruct/circ_buf.zig b/src/datastruct/circ_buf.zig index 065bf6a1d..646a00940 100644 --- a/src/datastruct/circ_buf.zig +++ b/src/datastruct/circ_buf.zig @@ -152,7 +152,7 @@ pub fn CircBuf(comptime T: type, comptime default: T) type { /// If larger, new values will be set to the default value. pub fn resize(self: *Self, alloc: Allocator, size: usize) Allocator.Error!void { // Rotate to zero so it is aligned. - try self.rotateToZero(alloc); + try self.rotateToZero(); // Reallocate, this adds to the end so we're ready to go. const prev_len = self.len(); @@ -173,29 +173,16 @@ pub fn CircBuf(comptime T: type, comptime default: T) type { } /// Rotate the data so that it is zero-aligned. - fn rotateToZero(self: *Self, alloc: Allocator) Allocator.Error!void { - // TODO: this does this in the worst possible way by allocating. - // rewrite to not allocate, its possible, I'm just lazy right now. - + fn rotateToZero(self: *Self) Allocator.Error!void { // If we're already at zero then do nothing. if (self.tail == 0) return; - var buf = try alloc.alloc(T, self.storage.len); - defer { - self.head = if (self.full) 0 else self.len(); - self.tail = 0; - alloc.free(self.storage); - self.storage = buf; - } + // We use std.mem.rotate to rotate our storage in-place. + std.mem.rotate(T, self.storage, self.tail); - if (!self.full and self.head >= self.tail) { - fastmem.copy(T, buf, self.storage[self.tail..self.head]); - return; - } - - const middle = self.storage.len - self.tail; - fastmem.copy(T, buf, self.storage[self.tail..]); - fastmem.copy(T, buf[middle..], self.storage[0..self.head]); + // Then fix up our head and tail. + self.head = self.len() % self.storage.len; + self.tail = 0; } /// Returns if the buffer is currently empty. To check if its @@ -589,7 +576,7 @@ test "CircBuf rotateToZero" { defer buf.deinit(alloc); _ = buf.getPtrSlice(0, 11); - try buf.rotateToZero(alloc); + try buf.rotateToZero(); } test "CircBuf rotateToZero offset" { @@ -611,7 +598,7 @@ test "CircBuf rotateToZero offset" { try testing.expect(buf.tail > 0 and buf.head >= buf.tail); // Rotate to zero - try buf.rotateToZero(alloc); + try buf.rotateToZero(); try testing.expectEqual(@as(usize, 0), buf.tail); try testing.expectEqual(@as(usize, 1), buf.head); } @@ -645,7 +632,7 @@ test "CircBuf rotateToZero wraps" { } // Rotate to zero - try buf.rotateToZero(alloc); + try buf.rotateToZero(); try testing.expectEqual(@as(usize, 0), buf.tail); try testing.expectEqual(@as(usize, 3), buf.head); { @@ -681,7 +668,7 @@ test "CircBuf rotateToZero full no wrap" { } // Rotate to zero - try buf.rotateToZero(alloc); + try buf.rotateToZero(); try testing.expect(buf.full); try testing.expectEqual(@as(usize, 0), buf.tail); try testing.expectEqual(@as(usize, 0), buf.head); |
