|
//! Effectively a stack of u1 values implemented using ArrayList(u8). |
init()Standalone function for working with a fixed-size buffer. |
const BitStack = @This(); |
deinit()Standalone function for working with a fixed-size buffer. |
const std = @import("std"); const Allocator = std.mem.Allocator; const ArrayList = std.ArrayList; |
ensureTotalCapacity()Standalone function for working with a fixed-size buffer. |
bytes: std.ArrayList(u8), bit_len: usize = 0, |
push() |
pub fn init(allocator: Allocator) @This() { return .{ .bytes = std.ArrayList(u8).init(allocator), }; } |
peek() |
pub fn deinit(self: *@This()) void { self.bytes.deinit(); self.* = undefined; } |
pop() |
pub fn ensureTotalCapacity(self: *@This(), bit_capacity: usize) Allocator.Error!void { const byte_capacity = (bit_capacity + 7) >> 3; try self.bytes.ensureTotalCapacity(byte_capacity); } |
pushWithStateAssumeCapacity() |
pub fn push(self: *@This(), b: u1) Allocator.Error!void { const byte_index = self.bit_len >> 3; if (self.bytes.items.len <= byte_index) { try self.bytes.append(0); } |
peekWithState() |
pushWithStateAssumeCapacity(self.bytes.items, &self.bit_len, b); } |
popWithState() |
pub fn peek(self: *const @This()) u1 { return peekWithState(self.bytes.items, self.bit_len); } |
Test: BitStack |
pub fn pop(self: *@This()) u1 { return popWithState(self.bytes.items, &self.bit_len); } /// Standalone function for working with a fixed-size buffer. pub fn pushWithStateAssumeCapacity(buf: []u8, bit_len: *usize, b: u1) void { const byte_index = bit_len.* >> 3; const bit_index = @as(u3, @intCast(bit_len.* & 7)); buf[byte_index] &= ~(@as(u8, 1) << bit_index); buf[byte_index] |= @as(u8, b) << bit_index; bit_len.* += 1; } /// Standalone function for working with a fixed-size buffer. pub fn peekWithState(buf: []const u8, bit_len: usize) u1 { const byte_index = (bit_len - 1) >> 3; const bit_index = @as(u3, @intCast((bit_len - 1) & 7)); return @as(u1, @intCast((buf[byte_index] >> bit_index) & 1)); } /// Standalone function for working with a fixed-size buffer. pub fn popWithState(buf: []const u8, bit_len: *usize) u1 { const b = peekWithState(buf, bit_len.*); bit_len.* -= 1; return b; } const testing = std.testing; test BitStack { var stack = BitStack.init(testing.allocator); defer stack.deinit(); try stack.push(1); try stack.push(0); try stack.push(0); try stack.push(1); try testing.expectEqual(@as(u1, 1), stack.peek()); try testing.expectEqual(@as(u1, 1), stack.pop()); try testing.expectEqual(@as(u1, 0), stack.peek()); try testing.expectEqual(@as(u1, 0), stack.pop()); try testing.expectEqual(@as(u1, 0), stack.pop()); try testing.expectEqual(@as(u1, 1), stack.pop()); } |
Generated by zstd-live on 2025-08-12 12:37:57 UTC. |