authorgravatar for hello@nektro.netMeghan Denny <hello@nektro.net> 2026-01-18 23:53:31 -08:00
committergravatar for hello@nektro.netMeghan Denny <hello@nektro.net> 2026-01-18 23:53:31 -08:00
logdccdb59e9fbdf9107efe29d385c21559c5430998
tree41176b99ba57b6c6968287f97b33f7db21bc44df
parentad173910f7d6dfa9e2e8e8fea1cb654a1b11de40

add ManyArrayList


2 files changed, 103 insertions(+), 0 deletions(-)

src/ManyArrayList.zig created+102
...@@ -0,0 +1,102 @@
1const std = @import("std");
2const extras = @import("./lib.zig");
3
4pub fn ManyArrayList(T: type) type {
5 return struct {
6 allocator: std.mem.Allocator,
7 list: std.ArrayListUnmanaged(T),
8 lengths: std.ArrayListUnmanaged(usize),
9
10 pub fn init(allocator: std.mem.Allocator) @This() {
11 return .{
12 .allocator = allocator,
13 .list = .{},
14 .lengths = .{},
15 };
16 }
17
18 pub fn deinit(self: *@This()) void {
19 self.list.deinit(self.allocator);
20 self.lengths.deinit(self.allocator);
21 }
22
23 pub fn add(self: *@This()) !usize {
24 const n = self.lengths.items.len;
25 try self.lengths.append(self.allocator, 0);
26 return n;
27 }
28
29 pub fn appendSlice(self: *@This(), n: usize, slice: []const T) !void {
30 const real_n = extras.sum(usize, self.lengths.items[0 .. n + 1]);
31 try self.list.insertSlice(self.allocator, real_n, slice);
32 self.lengths.items[n] += slice.len;
33 }
34
35 pub fn items(self: *@This(), n: usize) []T {
36 const real_n = extras.sum(usize, self.lengths.items[0..n]);
37 const len = self.lengths.items[n];
38 return self.list.items[real_n..][0..len];
39 }
40
41 pub fn set(self: *@This(), n: usize, slice: []const T) !void {
42 const real_n = extras.sum(usize, self.lengths.items[0..n]);
43 try self.list.replaceRange(self.allocator, real_n, self.lengths.items[n], slice);
44 self.lengths.items[n] = slice.len;
45 }
46
47 pub fn clear(self: *@This(), n: usize) void {
48 const real_n = extras.sum(usize, self.lengths.items[0..n]);
49 self.list.replaceRangeAssumeCapacity(real_n, self.lengths.items[n], &.{});
50 self.lengths.items[n] = 0;
51 }
52
53 /// Does not reset .lengths so that deinit can still clean it up
54 pub fn toOwnedSlice(self: *@This()) ![]T {
55 return self.list.toOwnedSlice(self.allocator);
56 }
57
58 pub fn swap(self: *@This(), a: usize, b: usize) void {
59 std.debug.assert(a != b);
60 if (a < b) return self.swapLR(a, b);
61 if (a > b) return self.swapLR(b, a);
62 unreachable;
63 }
64 fn swapLR(self: *@This(), a: usize, b: usize) void {
65 extras.swapManyLR(
66 u8,
67 self.list.items,
68 extras.sum(usize, self.lengths.items[0..a]),
69 self.lengths.items[a],
70 extras.sum(usize, self.lengths.items[0..b]),
71 self.lengths.items[b],
72 );
73 std.mem.swap(
74 usize,
75 &self.lengths.items[a],
76 &self.lengths.items[b],
77 );
78 }
79
80 pub fn remove(self: *@This(), n: usize) void {
81 const real_n = extras.sum(usize, self.lengths.items[0..n]);
82 self.list.replaceRangeAssumeCapacity(real_n, self.lengths.items[n], &.{});
83 _ = self.lengths.orderedRemove(n);
84 }
85
86 pub fn replace(self: *@This(), n: usize, o: usize, l: usize, slice: []const T) !void {
87 std.debug.assert(o + l <= self.lengths.items[n]);
88 const real_n = extras.sum(usize, self.lengths.items[0..n]);
89 try self.list.replaceRange(self.allocator, real_n + o, l, slice);
90 self.lengths.items[n] -= l;
91 self.lengths.items[n] += slice.len;
92 }
93
94 pub fn insertAt(self: *@This(), n: usize, slice: []const T) !void {
95 try self.lengths.ensureUnusedCapacity(self.allocator, 1);
96 try self.list.ensureUnusedCapacity(self.allocator, slice.len);
97 const real_n = extras.sum(usize, self.lengths.items[0..n]);
98 self.lengths.insertAssumeCapacity(n, slice.len);
99 self.list.insertSlice(self.allocator, real_n, slice) catch unreachable;
100 }
101 };
102}
src/lib.zig+1
...@@ -113,3 +113,4 @@ pub usingnamespace @import("./StaticMultiList.zig");...@@ -113,3 +113,4 @@ pub usingnamespace @import("./StaticMultiList.zig");
113pub usingnamespace @import("./join.zig");113pub usingnamespace @import("./join.zig");
114pub usingnamespace @import("./omit.zig");114pub usingnamespace @import("./omit.zig");
115pub usingnamespace @import("./swapMany.zig");115pub usingnamespace @import("./swapMany.zig");
116pub usingnamespace @import("./ManyArrayList.zig");