mirror of
https://github.com/ziglang/zig.git
synced 2026-01-12 02:15:12 +00:00
170 lines
6.0 KiB
Zig
170 lines
6.0 KiB
Zig
//! Deprecated. Stop using this API
|
|
|
|
const std = @import("std");
|
|
const math = std.math;
|
|
const mem = std.mem;
|
|
const Allocator = mem.Allocator;
|
|
const assert = std.debug.assert;
|
|
const testing = std.testing;
|
|
|
|
pub fn LinearFifo(comptime T: type) type {
|
|
return struct {
|
|
allocator: Allocator,
|
|
buf: []T,
|
|
head: usize,
|
|
count: usize,
|
|
|
|
const Self = @This();
|
|
|
|
pub fn init(allocator: Allocator) Self {
|
|
return .{
|
|
.allocator = allocator,
|
|
.buf = &.{},
|
|
.head = 0,
|
|
.count = 0,
|
|
};
|
|
}
|
|
|
|
pub fn deinit(self: *Self) void {
|
|
self.allocator.free(self.buf);
|
|
self.* = undefined;
|
|
}
|
|
|
|
pub fn realign(self: *Self) void {
|
|
if (self.buf.len - self.head >= self.count) {
|
|
mem.copyForwards(T, self.buf[0..self.count], self.buf[self.head..][0..self.count]);
|
|
self.head = 0;
|
|
} else {
|
|
var tmp: [4096 / 2 / @sizeOf(T)]T = undefined;
|
|
|
|
while (self.head != 0) {
|
|
const n = @min(self.head, tmp.len);
|
|
const m = self.buf.len - n;
|
|
@memcpy(tmp[0..n], self.buf[0..n]);
|
|
mem.copyForwards(T, self.buf[0..m], self.buf[n..][0..m]);
|
|
@memcpy(self.buf[m..][0..n], tmp[0..n]);
|
|
self.head -= n;
|
|
}
|
|
}
|
|
{ // set unused area to undefined
|
|
const unused = mem.sliceAsBytes(self.buf[self.count..]);
|
|
@memset(unused, undefined);
|
|
}
|
|
}
|
|
|
|
/// Ensure that the buffer can fit at least `size` items
|
|
pub fn ensureTotalCapacity(self: *Self, size: usize) !void {
|
|
if (self.buf.len >= size) return;
|
|
self.realign();
|
|
const new_size = math.ceilPowerOfTwo(usize, size) catch return error.OutOfMemory;
|
|
self.buf = try self.allocator.realloc(self.buf, new_size);
|
|
}
|
|
|
|
/// Makes sure at least `size` items are unused
|
|
pub fn ensureUnusedCapacity(self: *Self, size: usize) error{OutOfMemory}!void {
|
|
if (self.writableLength() >= size) return;
|
|
|
|
return try self.ensureTotalCapacity(math.add(usize, self.count, size) catch return error.OutOfMemory);
|
|
}
|
|
|
|
/// Returns a writable slice from the 'read' end of the fifo
|
|
fn readableSliceMut(self: Self, offset: usize) []T {
|
|
if (offset > self.count) return &[_]T{};
|
|
|
|
var start = self.head + offset;
|
|
if (start >= self.buf.len) {
|
|
start -= self.buf.len;
|
|
return self.buf[start .. start + (self.count - offset)];
|
|
} else {
|
|
const end = @min(self.head + self.count, self.buf.len);
|
|
return self.buf[start..end];
|
|
}
|
|
}
|
|
|
|
/// Discard first `count` items in the fifo
|
|
pub fn discard(self: *Self, count: usize) void {
|
|
assert(count <= self.count);
|
|
{ // set old range to undefined. Note: may be wrapped around
|
|
const slice = self.readableSliceMut(0);
|
|
if (slice.len >= count) {
|
|
const unused = mem.sliceAsBytes(slice[0..count]);
|
|
@memset(unused, undefined);
|
|
} else {
|
|
const unused = mem.sliceAsBytes(slice[0..]);
|
|
@memset(unused, undefined);
|
|
const unused2 = mem.sliceAsBytes(self.readableSliceMut(slice.len)[0 .. count - slice.len]);
|
|
@memset(unused2, undefined);
|
|
}
|
|
}
|
|
var head = self.head + count;
|
|
// Note it is safe to do a wrapping subtract as
|
|
// bitwise & with all 1s is a noop
|
|
head &= self.buf.len -% 1;
|
|
self.head = head;
|
|
self.count -= count;
|
|
}
|
|
|
|
/// Read the next item from the fifo
|
|
pub fn readItem(self: *Self) ?T {
|
|
if (self.count == 0) return null;
|
|
|
|
const c = self.buf[self.head];
|
|
self.discard(1);
|
|
return c;
|
|
}
|
|
|
|
/// Returns number of items available in fifo
|
|
pub fn writableLength(self: Self) usize {
|
|
return self.buf.len - self.count;
|
|
}
|
|
|
|
/// Returns the first section of writable buffer.
|
|
/// Note that this may be of length 0
|
|
pub fn writableSlice(self: Self, offset: usize) []T {
|
|
if (offset > self.buf.len) return &[_]T{};
|
|
|
|
const tail = self.head + offset + self.count;
|
|
if (tail < self.buf.len) {
|
|
return self.buf[tail..];
|
|
} else {
|
|
return self.buf[tail - self.buf.len ..][0 .. self.writableLength() - offset];
|
|
}
|
|
}
|
|
|
|
/// Update the tail location of the buffer (usually follows use of writable/writableWithSize)
|
|
pub fn update(self: *Self, count: usize) void {
|
|
assert(self.count + count <= self.buf.len);
|
|
self.count += count;
|
|
}
|
|
|
|
/// Appends the data in `src` to the fifo.
|
|
/// You must have ensured there is enough space.
|
|
pub fn writeAssumeCapacity(self: *Self, src: []const T) void {
|
|
assert(self.writableLength() >= src.len);
|
|
|
|
var src_left = src;
|
|
while (src_left.len > 0) {
|
|
const writable_slice = self.writableSlice(0);
|
|
assert(writable_slice.len != 0);
|
|
const n = @min(writable_slice.len, src_left.len);
|
|
@memcpy(writable_slice[0..n], src_left[0..n]);
|
|
self.update(n);
|
|
src_left = src_left[n..];
|
|
}
|
|
}
|
|
|
|
/// Write a single item to the fifo
|
|
pub fn writeItem(self: *Self, item: T) !void {
|
|
try self.ensureUnusedCapacity(1);
|
|
return self.writeItemAssumeCapacity(item);
|
|
}
|
|
|
|
pub fn writeItemAssumeCapacity(self: *Self, item: T) void {
|
|
var tail = self.head + self.count;
|
|
tail &= self.buf.len - 1;
|
|
self.buf[tail] = item;
|
|
self.update(1);
|
|
}
|
|
};
|
|
}
|