From c3af53b035bdf589fdd649d7b7046cef60a484fd Mon Sep 17 00:00:00 2001 From: "Jeffrey C. Ollie" Date: Thu, 12 Sep 2024 12:58:57 -0500 Subject: [PATCH] split circular buffer out to it's own repo --- build.zig | 7 ++ build.zig.zon | 64 ++-------------- src/main.zig | 207 +------------------------------------------------- 3 files changed, 15 insertions(+), 263 deletions(-) diff --git a/build.zig b/build.zig index 5c64c13..48f5dbf 100644 --- a/build.zig +++ b/build.zig @@ -4,6 +4,11 @@ pub fn build(b: *std.Build) void { const target = b.standardTargetOptions(.{}); const optimize = b.standardOptimizeOption(.{}); + const circular_buffer_dep = b.dependency("circular-buffer", .{ + .target = target, + .optimize = optimize, + }); + const exe = b.addExecutable(.{ .name = "osc-fuzzer", .root_source_file = b.path("src/main.zig"), @@ -11,6 +16,8 @@ pub fn build(b: *std.Build) void { .optimize = optimize, }); + exe.root_module.addImport("circular-buffer", circular_buffer_dep.module("circular-buffer")); + b.installArtifact(exe); const run_cmd = b.addRunArtifact(exe); diff --git a/build.zig.zon b/build.zig.zon index bf01d86..a2d80f8 100644 --- a/build.zig.zon +++ b/build.zig.zon @@ -1,72 +1,22 @@ .{ - // This is the default name used by packages depending on this one. For - // example, when a user runs `zig fetch --save `, this field is used - // as the key in the `dependencies` table. Although the user can choose a - // different name, most users will stick with this provided value. - // - // It is redundant to include "zig" in this name because it is already - // within the Zig package namespace. .name = "osc-fuzzer", - // This is a [Semantic Version](https://semver.org/). - // In a future version of Zig it will be used for package deduplication. .version = "0.0.0", - // This field is optional. - // This is currently advisory only; Zig does not yet do anything - // with this value. - //.minimum_zig_version = "0.11.0", + .minimum_zig_version = "0.13.0", - // This field is optional. - // Each dependency must either provide a `url` and `hash`, or a `path`. - // `zig build --fetch` can be used to fetch all dependencies of a package, recursively. - // Once all dependencies are fetched, `zig build` no longer requires - // internet connectivity. .dependencies = .{ - // See `zig fetch --save ` for a command-line interface for adding dependencies. - //.example = .{ - // // When updating this field to a new URL, be sure to delete the corresponding - // // `hash`, otherwise you are communicating that you expect to find the old hash at - // // the new URL. - // .url = "https://example.com/foo.tar.gz", - // - // // This is computed from the file contents of the directory of files that is - // // obtained after fetching `url` and applying the inclusion rules given by - // // `paths`. - // // - // // This field is the source of truth; packages do not come from a `url`; they - // // come from a `hash`. `url` is just one of many possible mirrors for how to - // // obtain a package matching this `hash`. - // // - // // Uses the [multihash](https://multiformats.io/multihash/) format. - // .hash = "...", - // - // // When this is provided, the package is found in a directory relative to the - // // build root. In this case the package's hash is irrelevant and therefore not - // // computed. This field and `url` are mutually exclusive. - // .path = "foo", - - // // When this is set to `true`, a package is declared to be lazily - // // fetched. This makes the dependency only get fetched if it is - // // actually used. - // .lazy = false, - //}, + .@"circular-buffer" = .{ + .url = "git+https://git.ocjtech.us/jeff/circular-buffer.git?ref=main#7c2cde8a30d6b99150d64bbca507a857064ee67c", + .hash = "1220b29e891e8c9a6d23ca01e61fcdb128ca40ed2c1961f4153e3709db9958aacc06", + }, }, - // Specifies the set of files and directories that are included in this package. - // Only files and directories listed here are included in the `hash` that - // is computed for this package. Only files listed here will remain on disk - // when using the zig package manager. As a rule of thumb, one should list - // files required for compilation plus any license(s). - // Paths are relative to the build root. Use the empty string (`""`) to refer to - // the build root itself. - // A directory listed here means that all files within, recursively, are included. .paths = .{ "build.zig", "build.zig.zon", "src", - // For example... - //"LICENSE", - //"README.md", + "LICENSE", + "README.md", }, } diff --git a/src/main.zig b/src/main.zig index 4ecfa3e..495ded1 100644 --- a/src/main.zig +++ b/src/main.zig @@ -1,210 +1,5 @@ const std = @import("std"); - -pub fn CircularBuffer(comptime T: type) type { - const info = @typeInfo(T); - std.debug.assert(info == .Int); - std.debug.assert(info.Int.signedness == .unsigned); - - return struct { - data: [std.math.maxInt(T) + 1]u8 = undefined, - head: T = 0, - tail: T = 0, - full: bool = false, - - pub fn isEmpty(self: *CircularBuffer(T)) bool { - return self.head == self.tail and !self.full; - } - - pub fn isFull(self: *CircularBuffer(T)) bool { - return self.full; - } - - pub fn reset(self: *CircularBuffer(T)) void { - self.head = 0; - self.tail = 0; - self.full = false; - } - - pub fn size(self: *CircularBuffer(size)) T { - if (self.full) return std.math.maxInt(T); - if (self.head >= self.tail) return @intCast(self.head - self.tail); - return @intCast(std.math.maxInt(T) + self.head - self.tail); - } - - fn advance(self: *CircularBuffer(T)) void { - self.head +%= 1; - if (self.full) self.tail +%= 1; - self.full = self.head == self.tail; - } - - fn retreat(self: *CircularBuffer(T)) void { - self.full = false; - self.tail -%= 1; - } - - pub fn pushByte(self: *CircularBuffer(T), byte: u8) void { - self.data[self.head] = byte; - self.advance(); - } - - pub fn popByte(self: *CircularBuffer(T)) !u8 { - if (self.isEmpty()) return error.BufferEmpty; - defer self.retreat(); - return self.data[self.tail]; - } - - pub fn pushAll(self: *CircularBuffer(T), data: []const u8) void { - if (data.len >= self.data.len) { - @memcpy(&self.data, data[(data.len - self.data.len)..]); - self.tail = 0; - self.head = 0; - self.full = true; - return; - } - - for (data) |c| self.pushByte(c); - } - - pub fn write(self: *CircularBuffer(T), writer: anytype) !void { - if (self.head <= self.tail) { - try writer.writeAll(self.data[self.tail..]); - try writer.writeAll(self.data[0..self.head]); - } else { - try writer.writeAll(self.data[self.tail..self.head]); - } - } - }; -} - -test "circular buffer 1" { - var cb = CircularBuffer(u2){}; - cb.pushByte('a'); - try std.testing.expect(!cb.isFull()); - try std.testing.expect(!cb.isEmpty()); - try std.testing.expectEqual(0, cb.tail); - try std.testing.expectEqual(1, cb.head); - try std.testing.expectEqual('a', cb.data[0]); - - var tmp: [16]u8 = undefined; - var fbs = std.io.fixedBufferStream(&tmp); - try cb.write(fbs.writer()); - const result = fbs.getWritten(); - try std.testing.expectEqualStrings("a", result); -} - -test "circular buffer 2" { - var cb = CircularBuffer(u2){}; - cb.pushByte('a'); - cb.pushByte('b'); - cb.pushByte('c'); - try std.testing.expect(!cb.isFull()); - try std.testing.expect(!cb.isEmpty()); - try std.testing.expectEqual(0, cb.tail); - try std.testing.expectEqual(3, cb.head); - try std.testing.expectEqual('a', cb.data[0]); - try std.testing.expectEqual('b', cb.data[1]); - try std.testing.expectEqual('c', cb.data[2]); - - var tmp: [16]u8 = undefined; - var fbs = std.io.fixedBufferStream(&tmp); - try cb.write(fbs.writer()); - const result = fbs.getWritten(); - try std.testing.expectEqualStrings("abc", result); -} - -test "circular buffer 3" { - var cb = CircularBuffer(u2){}; - cb.pushByte('a'); - cb.pushByte('b'); - cb.pushByte('c'); - cb.pushByte('d'); - cb.pushByte('e'); - try std.testing.expect(cb.isFull()); - try std.testing.expect(!cb.isEmpty()); - try std.testing.expectEqual(1, cb.tail); - try std.testing.expectEqual(1, cb.head); - try std.testing.expectEqual('e', cb.data[0]); - try std.testing.expectEqual('b', cb.data[1]); - try std.testing.expectEqual('c', cb.data[2]); - try std.testing.expectEqual('d', cb.data[3]); - - var tmp: [16]u8 = undefined; - var fbs = std.io.fixedBufferStream(&tmp); - try cb.write(fbs.writer()); - const result = fbs.getWritten(); - try std.testing.expectEqualStrings("bcde", result); -} - -test "circular buffer 4" { - var cb = CircularBuffer(u2){}; - cb.pushAll("a"); - try std.testing.expect(!cb.isFull()); - try std.testing.expect(!cb.isEmpty()); - try std.testing.expectEqual(0, cb.tail); - try std.testing.expectEqual(1, cb.head); - try std.testing.expectEqual('a', cb.data[0]); - - var tmp: [16]u8 = undefined; - var fbs = std.io.fixedBufferStream(&tmp); - try cb.write(fbs.writer()); - const result = fbs.getWritten(); - try std.testing.expectEqualStrings("a", result); -} - -test "circular buffer 5" { - var cb = CircularBuffer(u2){}; - cb.pushAll("ab"); - try std.testing.expect(!cb.isFull()); - try std.testing.expect(!cb.isEmpty()); - try std.testing.expectEqual(0, cb.tail); - try std.testing.expectEqual(2, cb.head); - try std.testing.expectEqual('a', cb.data[0]); - try std.testing.expectEqual('b', cb.data[1]); - - var tmp: [16]u8 = undefined; - var fbs = std.io.fixedBufferStream(&tmp); - try cb.write(fbs.writer()); - const result = fbs.getWritten(); - try std.testing.expectEqualStrings("ab", result); -} - -test "circular buffer 6" { - var cb = CircularBuffer(u2){}; - cb.pushAll("abcd"); - try std.testing.expect(cb.isFull()); - try std.testing.expect(!cb.isEmpty()); - try std.testing.expectEqual(0, cb.tail); - try std.testing.expectEqual(0, cb.head); - try std.testing.expectEqual('a', cb.data[0]); - try std.testing.expectEqual('b', cb.data[1]); - try std.testing.expectEqual('c', cb.data[2]); - try std.testing.expectEqual('d', cb.data[3]); - - var tmp: [16]u8 = undefined; - var fbs = std.io.fixedBufferStream(&tmp); - try cb.write(fbs.writer()); - const result = fbs.getWritten(); - try std.testing.expectEqualStrings("abcd", result); -} - -test "circular buffer 7" { - var cb = CircularBuffer(u2){}; - cb.pushAll("abcde"); - try std.testing.expect(cb.isFull()); - try std.testing.expect(!cb.isEmpty()); - try std.testing.expectEqual(0, cb.tail); - try std.testing.expectEqual(0, cb.head); - try std.testing.expectEqual('b', cb.data[0]); - try std.testing.expectEqual('c', cb.data[1]); - try std.testing.expectEqual('d', cb.data[2]); - try std.testing.expectEqual('e', cb.data[3]); - - var tmp: [16]u8 = undefined; - var fbs = std.io.fixedBufferStream(&tmp); - try cb.write(fbs.writer()); - const result = fbs.getWritten(); - try std.testing.expectEqualStrings("bcde", result); -} +const CircularBuffer = @import("circular-buffer"); pub fn main() !void { var cb = CircularBuffer(u20){};