Zig utility library
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Add (Array)Queue and refactor `StringBuilder`

IamPyu 8864024e fe7c0504

+230 -110
+124
src/Queue.zig
··· 1 + const std = @import("std"); 2 + const Allocator = std.mem.Allocator; 3 + 4 + pub fn Queue(comptime T: type) type { 5 + return struct { 6 + const Self = @This(); 7 + 8 + pub const Node = struct { 9 + value: T, 10 + next: ?*Node = null, 11 + prev: ?*Node = null, 12 + 13 + pub fn init(value: T) Node { 14 + return Node{ .value = value }; 15 + } 16 + }; 17 + 18 + first: ?*Node = null, 19 + last: ?*Node = null, 20 + 21 + pub fn init() !Self { 22 + return Self{ 23 + .first = null, 24 + .last = null, 25 + }; 26 + } 27 + 28 + pub fn insertAfter(self: *Self, node: *Node, new_node: *Node) void { 29 + new_node.prev = node; 30 + if (node.next == null) { 31 + new_node.next = null; 32 + self.last = new_node; 33 + } else { 34 + new_node.next = node.next; 35 + node.next.?.prev = new_node; 36 + } 37 + node.next = new_node; 38 + } 39 + 40 + pub fn insertBefore(self: *Self, node: *Node, new_node: *Node) void { 41 + new_node.next = node; 42 + if (node.next == null) { 43 + new_node.prev = null; 44 + self.first = new_node; 45 + } else { 46 + new_node.prev = node.prev; 47 + node.prev.?.next = new_node; 48 + } 49 + node.prev = new_node; 50 + } 51 + 52 + pub fn insertBeginning(self: *Self, node: *Node) void { 53 + if (self.first == null) { 54 + self.first = node; 55 + self.last = node; 56 + node.next = null; 57 + node.prev = null; 58 + } else { 59 + self.insertBefore(self.first.?, node); 60 + } 61 + } 62 + 63 + pub fn enqueue(self: *Self, node: *Node) void { 64 + if (self.last == null) 65 + self.insertBeginning(node) 66 + else 67 + self.insertAfter(self.last.?, node); 68 + } 69 + 70 + pub fn dequeue(self: *Self) ?*Node { 71 + if (self.first) |first| { 72 + self.first = first.next; 73 + return first; 74 + } 75 + return null; 76 + } 77 + }; 78 + } 79 + 80 + pub fn ArrayQueue(comptime T: type) type { 81 + return struct { 82 + const Self = @This(); 83 + const IQueue = Queue(T); 84 + const NodeList = std.ArrayList(IQueue.Node); 85 + 86 + allocator: Allocator, 87 + queue: IQueue, 88 + nodes: NodeList, 89 + 90 + pub fn init(allocator: Allocator) !Self { 91 + return .{ 92 + .allocator = allocator, 93 + .nodes = try NodeList.initCapacity(allocator, 10), 94 + .queue = try IQueue.init(), 95 + }; 96 + } 97 + 98 + pub fn deinit(self: *Self) void { 99 + self.nodes.deinit(self.allocator); 100 + } 101 + 102 + pub fn enqueue(self: *Self, value: T) !void { 103 + try self.nodes.append(self.allocator, IQueue.Node.init(value)); 104 + const node = &self.nodes.items[self.nodes.items.len - 1]; 105 + self.queue.enqueue(node); 106 + } 107 + 108 + pub fn dequeue(self: *Self) ?*IQueue.Node { 109 + return self.queue.dequeue(); 110 + } 111 + }; 112 + } 113 + 114 + test "queue" { 115 + var queue = try ArrayQueue(i32).init(std.testing.allocator); 116 + defer queue.deinit(); 117 + try queue.enqueue(1); 118 + try queue.enqueue(2); 119 + try queue.enqueue(3); 120 + 121 + try std.testing.expectEqual(1, queue.dequeue().?.value); 122 + try std.testing.expectEqual(2, queue.dequeue().?.value); 123 + try std.testing.expectEqual(3, queue.dequeue().?.value); 124 + }
+95 -97
src/StringBuilder.zig
··· 1 1 const std = @import("std"); 2 2 const Allocator = std.mem.Allocator; 3 3 4 - pub const StringBuilder = struct { 5 - const Self = @This(); 6 - 7 - allocator: Allocator, 4 + const Self = @This(); 8 5 9 - buf: []u8, 10 - ptr: usize, 11 - size: usize, 12 - capacity: usize, 6 + allocator: Allocator, 13 7 14 - /// Create a `StringBuilder` 15 - pub fn init(allocator: Allocator, capacity: usize) !Self { 16 - return Self{ 17 - .allocator = allocator, 18 - .capacity = capacity, 19 - .ptr = 0, 20 - .size = 0, 21 - .buf = try allocator.alloc(u8, capacity), 22 - }; 23 - } 8 + buf: []u8, 9 + ptr: usize, 10 + size: usize, 11 + capacity: usize, 24 12 25 - /// Deinitialize the string builder 26 - pub fn deinit(self: Self) void { 27 - self.allocator.free(self.buf); 28 - } 13 + /// Create a `StringBuilder` 14 + pub fn init(allocator: Allocator, capacity: usize) !Self { 15 + return Self{ 16 + .allocator = allocator, 17 + .capacity = capacity, 18 + .ptr = 0, 19 + .size = 0, 20 + .buf = try allocator.alloc(u8, capacity), 21 + }; 22 + } 29 23 30 - /// Construct the final string using another allocator 31 - pub fn build(self: *const Self, allocator: Allocator) ![]u8 { 32 - const str = try allocator.alloc(u8, self.size); 33 - @memcpy(str, self.buf[0..self.size]); 34 - return str; 35 - } 24 + /// Deinitialize the string builder 25 + pub fn deinit(self: Self) void { 26 + self.allocator.free(self.buf); 27 + } 36 28 37 - /// Reserve additional space for the string builder or reduce its size. 38 - pub fn resize(self: *Self, size: usize) !void { 39 - if (size < self.capacity) { 40 - self.capacity = size; 41 - self.buf = try self.allocator.realloc(self.buf, self.capacity); 42 - return; 43 - } 29 + /// Construct the final string using another allocator 30 + pub fn build(self: *const Self, allocator: Allocator) ![]u8 { 31 + const str = try allocator.alloc(u8, self.size); 32 + @memcpy(str, self.buf[0..self.size]); 33 + return str; 34 + } 44 35 45 - self.capacity = size * 2; 36 + /// Reserve additional space for the string builder or reduce its size. 37 + pub fn resize(self: *Self, size: usize) !void { 38 + if (size < self.capacity) { 39 + self.capacity = size; 46 40 self.buf = try self.allocator.realloc(self.buf, self.capacity); 41 + return; 47 42 } 48 43 49 - /// Append a slice to the string builder 50 - pub fn append(self: *Self, buf: []const u8) !void { 51 - const new_size = self.size + buf.len; 52 - try self.resize(new_size); 44 + self.capacity = size * 2; 45 + self.buf = try self.allocator.realloc(self.buf, self.capacity); 46 + } 53 47 54 - const p = self.buf.ptr + self.ptr; 55 - @memcpy(p, buf); 48 + /// Append a slice to the string builder 49 + pub fn append(self: *Self, buf: []const u8) !void { 50 + const new_size = self.size + buf.len; 51 + try self.resize(new_size); 56 52 57 - self.size = new_size; 58 - self.ptr = self.size; 59 - } 53 + const p = self.buf.ptr + self.ptr; 54 + @memcpy(p, buf); 60 55 61 - /// Append a single character to the string builder 62 - pub fn appendChar(self: *Self, c: u8) !void { 63 - const new_size = self.size + 1; 64 - try self.resize(new_size); 56 + self.size = new_size; 57 + self.ptr = self.size; 58 + } 65 59 66 - const p = @as(*u8, @ptrCast(self.buf.ptr + self.ptr)); 67 - p.* = c; 60 + /// Append a single character to the string builder 61 + pub fn appendChar(self: *Self, c: u8) !void { 62 + const new_size = self.size + 1; 63 + try self.resize(new_size); 68 64 69 - self.size = new_size; 70 - self.ptr = self.size; 71 - } 65 + const p = @as(*u8, @ptrCast(self.buf.ptr + self.ptr)); 66 + p.* = c; 72 67 73 - /// Join this string builder with another 74 - pub fn join(self: *Self, other: *const Self) !void { 75 - try self.append(other.buf[0..other.size]); 76 - } 68 + self.size = new_size; 69 + self.ptr = self.size; 70 + } 77 71 78 - /// Repeat the contents of the string builder `n` times 79 - pub fn repeat(self: *Self, n: usize) !void { 80 - if (n == 0) 81 - return; 72 + /// Join this string builder with another 73 + pub fn join(self: *Self, other: *const Self) !void { 74 + try self.append(other.buf[0..other.size]); 75 + } 82 76 83 - const orig_size = self.size; 84 - const new_size = orig_size * n; 85 - try self.resize(new_size); 77 + /// Repeat the contents of the string builder `n` times 78 + pub fn repeat(self: *Self, n: usize) !void { 79 + if (n == 0) 80 + return; 86 81 87 - const tmpbuf = try self.allocator.alloc(u8, orig_size); 88 - defer self.allocator.free(tmpbuf); 89 - @memcpy(tmpbuf, self.buf[0..orig_size]); 82 + const orig_size = self.size; 83 + const new_size = orig_size * n; 84 + try self.resize(new_size); 90 85 91 - for (0..n) |_| 92 - try self.append(tmpbuf); 93 - } 86 + const tmpbuf = try self.allocator.alloc(u8, orig_size); 87 + defer self.allocator.free(tmpbuf); 88 + @memcpy(tmpbuf, self.buf[0..orig_size]); 94 89 95 - /// Clear the buffer of the string builder 96 - pub fn clear(self: *Self) void { 97 - self.ptr = 0; 98 - self.size = 0; 99 - @memset(self.buf, 0); 100 - } 90 + for (0..n) |_| 91 + try self.append(tmpbuf); 92 + } 101 93 102 - /// Remove the most recent character from the string 103 - pub fn pop(self: *Self) void { 104 - self.size -= 1; 105 - self.ptr = self.size; 106 - } 94 + /// Clear the buffer of the string builder 95 + pub fn clear(self: *Self) void { 96 + self.ptr = 0; 97 + self.size = 0; 98 + @memset(self.buf, 0); 99 + } 107 100 108 - /// Repeat `pop` `n` times 109 - pub fn popMany(self: *Self, n: usize) void { 110 - if (n == 0) 111 - return; 101 + /// Remove the most recent character from the string 102 + pub fn pop(self: *Self) void { 103 + self.size -= 1; 104 + self.ptr = self.size; 105 + } 112 106 113 - for (0..n) |_| 114 - self.pop(); 115 - } 116 - }; 107 + /// Repeat `pop` `n` times 108 + pub fn popMany(self: *Self, n: usize) void { 109 + if (n == 0) 110 + return; 111 + 112 + for (0..n) |_| 113 + self.pop(); 114 + } 117 115 118 116 test "append" { 119 - var sb = try StringBuilder.init(std.testing.allocator, 5); 117 + var sb = try Self.init(std.testing.allocator, 5); 120 118 defer sb.deinit(); 121 119 try sb.append("Hello World"); 122 120 try sb.appendChar('!'); ··· 128 126 } 129 127 130 128 test "join" { 131 - var sb = try StringBuilder.init(std.testing.allocator, 5); 129 + var sb = try Self.init(std.testing.allocator, 5); 132 130 defer sb.deinit(); 133 131 try sb.append("first StringBuilder,"); 134 132 135 133 { 136 - var tmpsb = try StringBuilder.init(std.testing.allocator, 5); 134 + var tmpsb = try Self.init(std.testing.allocator, 5); 137 135 defer tmpsb.deinit(); 138 136 try tmpsb.append(" second StringBuilder"); 139 137 ··· 147 145 } 148 146 149 147 test "repeat" { 150 - var sb = try StringBuilder.init(std.testing.allocator, 15); 148 + var sb = try Self.init(std.testing.allocator, 15); 151 149 defer sb.deinit(); 152 150 try sb.append("Hello"); 153 151 try sb.repeat(4); ··· 159 157 } 160 158 161 159 test "clear" { 162 - var sb = try StringBuilder.init(std.testing.allocator, 15); 160 + var sb = try Self.init(std.testing.allocator, 15); 163 161 defer sb.deinit(); 164 162 try sb.append("123"); 165 163 try sb.repeat(4); ··· 172 170 } 173 171 174 172 test "simple" { 175 - var sb = try StringBuilder.init(std.testing.allocator, 15); 173 + var sb = try Self.init(std.testing.allocator, 15); 176 174 defer sb.deinit(); 177 175 try sb.append("Hello"); 178 176 try sb.append(" World!"); ··· 184 182 } 185 183 186 184 test "pop" { 187 - var sb = try StringBuilder.init(std.testing.allocator, 15); 185 + var sb = try Self.init(std.testing.allocator, 15); 188 186 defer sb.deinit(); 189 187 try sb.append("cool"); 190 188 try sb.append("abc");
+4 -10
src/path.zig
··· 9 9 10 10 /// Return the filename of `path` 11 11 pub fn basename(path: []const u8) []const u8 { 12 - if (mem.lastIndexOfScalar(u8, path, path_delim)) |index| { 12 + if (mem.lastIndexOfScalar(u8, path, path_delim)) |index| 13 13 return path[index + 1 ..]; 14 - } 15 14 return path; 16 15 } 17 16 ··· 21 20 22 21 if (mem.startsWith(u8, filename, ".") and 23 22 mem.count(u8, filename, ".") > 1) 24 - { 25 23 return getFileExt(filename[1..]); 26 - } 27 24 28 - if (mem.indexOf(u8, filename, ".")) |index| { 25 + if (mem.indexOf(u8, filename, ".")) |index| 29 26 return filename[index..]; 30 - } 31 27 32 28 return null; 33 29 } ··· 36 32 pub fn stripFileExt(path: []const u8) []const u8 { 37 33 const filename = basename(path); 38 34 39 - if (getFileExt(filename)) |ext| { 35 + if (getFileExt(filename)) |ext| 40 36 return filename[0..(filename.len - ext.len)]; 41 - } 42 37 43 38 return filename; 44 39 } 45 40 46 41 /// Returns the parent component of `path` 47 42 pub fn getDirectory(path: []const u8) ?[]const u8 { 48 - if (mem.lastIndexOfScalar(u8, path, path_delim)) |index| { 43 + if (mem.lastIndexOfScalar(u8, path, path_delim)) |index| 49 44 return path[0..index]; 50 - } 51 45 52 46 return null; 53 47 }
+7 -3
src/root.zig
··· 6 6 const sparse_set = @import("./SparseSet.zig"); 7 7 pub const SparseSet = sparse_set.SparseSet; 8 8 9 - const string_builder = @import("./StringBuilder.zig"); 10 - pub const StringBuilder = string_builder.StringBuilder; 9 + pub const StringBuilder = @import("./StringBuilder.zig"); 11 10 12 11 pub const path = @import("./path.zig"); 13 12 pub const mem = @import("./mem.zig"); ··· 15 14 const slice_iterator = @import("./SliceIterator.zig"); 16 15 pub const SliceIterator = slice_iterator.SliceIterator; 17 16 17 + const queue = @import("./Queue.zig"); 18 + pub const Queue = queue.Queue; 19 + pub const ArrayQueue = queue.ArrayQueue; 20 + 18 21 test { 19 22 _ = la; 20 23 _ = packet; 21 24 _ = sparse_set; 22 - _ = string_builder; 25 + _ = StringBuilder; 23 26 _ = path; 24 27 _ = mem; 25 28 _ = slice_iterator; 29 + _ = queue; 26 30 }