mirror of
https://codeberg.org/ziglang/zig.git
synced 2026-10-28 19:00:52 +08:00
In particular renames of `std.mem.indexOf` family to `std.mem.find` and generic unmanaged containers
293 lines
11 KiB
Zig
293 lines
11 KiB
Zig
const std = @import("std");
|
|
const Io = std.Io;
|
|
const Dir = std.Io.Dir;
|
|
const mem = std.mem;
|
|
|
|
const catalog_txt = @embedFile("crc/catalog.txt");
|
|
|
|
pub fn main(init: std.process.Init) !void {
|
|
const arena = init.arena.allocator();
|
|
const io = init.io;
|
|
const args = try init.minimal.args.toSlice(arena);
|
|
return @"i like cheese"(arena, io, args);
|
|
}
|
|
|
|
fn @"i like cheese"(arena: std.mem.Allocator, io: Io, args: []const []const u8) !void {
|
|
if (args.len <= 1) printUsageAndExit(args[0]);
|
|
|
|
const zig_src_root = args[1];
|
|
if (mem.startsWith(u8, zig_src_root, "-")) printUsageAndExit(args[0]);
|
|
|
|
var zig_src_dir = try Dir.cwd().openDir(io, zig_src_root, .{});
|
|
defer zig_src_dir.close(io);
|
|
|
|
const hash_sub_path = try Dir.path.join(arena, &.{ "lib", "std", "hash" });
|
|
var hash_target_dir = try zig_src_dir.createDirPathOpen(io, hash_sub_path, .{});
|
|
defer hash_target_dir.close(io);
|
|
|
|
const crc_sub_path = try Dir.path.join(arena, &.{ "lib", "std", "hash", "crc" });
|
|
var crc_target_dir = try zig_src_dir.createDirPathOpen(io, crc_sub_path, .{});
|
|
defer crc_target_dir.close(io);
|
|
|
|
var zig_code_file = try hash_target_dir.createFile(io, "crc.zig", .{});
|
|
defer zig_code_file.close(io);
|
|
|
|
var zig_code_file_buffer: [4096]u8 = undefined;
|
|
var zig_code_file_writer = zig_code_file.writer(io, &zig_code_file_buffer);
|
|
const code_writer = &zig_code_file_writer.interface;
|
|
|
|
try code_writer.writeAll(
|
|
\\//! This file is auto-generated by tools/update_crc_catalog.zig.
|
|
\\
|
|
\\const builtin = @import("builtin");
|
|
\\
|
|
);
|
|
|
|
var zig_test_file = try crc_target_dir.createFile(io, "test.zig", .{});
|
|
defer zig_test_file.close(io);
|
|
|
|
var zig_test_file_buffer: [4096]u8 = undefined;
|
|
var zig_test_file_writer = zig_test_file.writer(io, &zig_test_file_buffer);
|
|
const test_writer = &zig_test_file_writer.interface;
|
|
|
|
try test_writer.writeAll(
|
|
\\//! This file is auto-generated by tools/update_crc_catalog.zig.
|
|
\\
|
|
\\const std = @import("std");
|
|
\\const testing = std.testing;
|
|
\\const verify = @import("../verify.zig");
|
|
\\const crc = @import("../crc.zig");
|
|
\\
|
|
\\test "crc32 ieee regression" {
|
|
\\ const Crc = crc.@"CRC-32/ISO-HDLC";
|
|
\\ try testing.expectEqual(Crc.hash(""), 0x00000000);
|
|
\\ try testing.expectEqual(Crc.hash("a"), 0xe8b7be43);
|
|
\\ try testing.expectEqual(Crc.hash("abc"), 0x352441c2);
|
|
\\}
|
|
\\
|
|
\\test "crc32 castagnoli regression" {
|
|
\\ const Crc = crc.@"CRC-32/ISCSI";
|
|
\\ try testing.expectEqual(Crc.hash(""), 0x00000000);
|
|
\\ try testing.expectEqual(Crc.hash("a"), 0xc1d04330);
|
|
\\ try testing.expectEqual(Crc.hash("abc"), 0x364b3fb7);
|
|
\\}
|
|
\\
|
|
\\test "crc32 koopman regression" {
|
|
\\ const Crc = crc.@"CRC-32/KOOPMAN";
|
|
\\ try testing.expectEqual(Crc.hash(""), 0x00000000);
|
|
\\ try testing.expectEqual(Crc.hash("a"), 0x0da2aa8a);
|
|
\\ try testing.expectEqual(Crc.hash("abc"), 0xba2322ac);
|
|
\\}
|
|
\\
|
|
);
|
|
|
|
var reader: std.Io.Reader = .fixed(catalog_txt);
|
|
|
|
while (try reader.takeDelimiter('\n')) |line| {
|
|
if (line.len == 0 or line[0] == '#')
|
|
continue;
|
|
|
|
var width: []const u8 = undefined;
|
|
var poly: []const u8 = undefined;
|
|
var init: []const u8 = undefined;
|
|
var refin: []const u8 = undefined;
|
|
var refout: []const u8 = undefined;
|
|
var xorout: []const u8 = undefined;
|
|
var check: []const u8 = undefined;
|
|
var residue: []const u8 = undefined;
|
|
var name: []const u8 = undefined;
|
|
|
|
var it = mem.splitSequence(u8, line, " ");
|
|
while (it.next()) |property| {
|
|
const i = mem.find(u8, property, "=").?;
|
|
const key = property[0..i];
|
|
const value = property[i + 1 ..];
|
|
if (mem.eql(u8, key, "width")) {
|
|
width = value;
|
|
} else if (mem.eql(u8, key, "poly")) {
|
|
poly = value;
|
|
} else if (mem.eql(u8, key, "init")) {
|
|
init = value;
|
|
} else if (mem.eql(u8, key, "refin")) {
|
|
refin = value;
|
|
} else if (mem.eql(u8, key, "refout")) {
|
|
refout = value;
|
|
} else if (mem.eql(u8, key, "xorout")) {
|
|
xorout = value;
|
|
} else if (mem.eql(u8, key, "check")) {
|
|
check = value;
|
|
} else if (mem.eql(u8, key, "residue")) {
|
|
residue = value;
|
|
} else if (mem.eql(u8, key, "name")) {
|
|
name = mem.trim(u8, value, "\"");
|
|
} else {
|
|
unreachable;
|
|
}
|
|
}
|
|
|
|
if (mem.eql(u8, name, "CRC-32/ISCSI")) {
|
|
try code_writer.print(
|
|
\\
|
|
\\pub const {f} = if (builtin.cpu.hasAll(.x86, &.{{ .@"64bit", .crc32 }}))
|
|
\\ @import("crc/Crc32c.zig")
|
|
\\else
|
|
\\ Generic(u{s}, .{{
|
|
\\ .polynomial = {s},
|
|
\\ .initial = {s},
|
|
\\ .reflect_input = {s},
|
|
\\ .reflect_output = {s},
|
|
\\ .xor_output = {s},
|
|
\\ }});
|
|
\\
|
|
, .{ std.zig.fmtId(name), width, poly, init, refin, refout, xorout });
|
|
} else {
|
|
try code_writer.print(
|
|
\\
|
|
\\pub const {f} = Generic(u{s}, .{{
|
|
\\ .polynomial = {s},
|
|
\\ .initial = {s},
|
|
\\ .reflect_input = {s},
|
|
\\ .reflect_output = {s},
|
|
\\ .xor_output = {s},
|
|
\\}});
|
|
\\
|
|
, .{ std.zig.fmtId(name), width, poly, init, refin, refout, xorout });
|
|
}
|
|
|
|
try test_writer.print(
|
|
\\
|
|
\\test "{0s}" {{
|
|
\\ const Crc = crc.{1f};
|
|
\\
|
|
\\ try testing.expectEqual(@as(u{2s}, {3s}), Crc.hash("123456789"));
|
|
\\
|
|
\\ var c = Crc.init();
|
|
\\ c.update("1234");
|
|
\\ c.update("56789");
|
|
\\ try testing.expectEqual(@as(u{2s}, {3s}), c.final());
|
|
\\}}
|
|
\\
|
|
, .{ name, std.zig.fmtId(name), width, check });
|
|
}
|
|
|
|
try code_writer.writeAll(
|
|
\\
|
|
\\pub fn Algorithm(comptime W: type) type {
|
|
\\ return struct {
|
|
\\ polynomial: W,
|
|
\\ initial: W,
|
|
\\ reflect_input: bool,
|
|
\\ reflect_output: bool,
|
|
\\ xor_output: W,
|
|
\\ };
|
|
\\}
|
|
\\
|
|
\\pub fn Generic(comptime W: type, comptime algorithm: Algorithm(W)) type {
|
|
\\ return struct {
|
|
\\ const Self = @This();
|
|
\\ const I = if (@bitSizeOf(W) < 8) u8 else W;
|
|
\\ const lookup_table = blk: {
|
|
\\ @setEvalBranchQuota(2500);
|
|
\\ const poly = reflect(algorithm.polynomial);
|
|
\\ var table: [256]I = undefined;
|
|
\\ for (&table, 0..) |*e, i| {
|
|
\\ var crc: I = i;
|
|
\\ if (algorithm.reflect_input) {
|
|
\\ var j: usize = 0;
|
|
\\ while (j < 8) : (j += 1) {
|
|
\\ crc = (crc >> 1) ^ ((crc & 1) * poly);
|
|
\\ }
|
|
\\ } else {
|
|
\\ crc <<= @bitSizeOf(I) - 8;
|
|
\\ var j: usize = 0;
|
|
\\ while (j < 8) : (j += 1) {
|
|
\\ crc = (crc << 1) ^ (((crc >> (@bitSizeOf(I) - 1)) & 1) * poly);
|
|
\\ }
|
|
\\ }
|
|
\\ e.* = crc;
|
|
\\ }
|
|
\\ break :blk table;
|
|
\\ };
|
|
\\
|
|
\\ crc: I,
|
|
\\
|
|
\\ pub fn init() Self {
|
|
\\ const initial = reflect(algorithm.initial);
|
|
\\ return .{ .crc = initial };
|
|
\\ }
|
|
\\
|
|
\\ inline fn tableEntry(index: I) I {
|
|
\\ const short: u8 = @truncate(index);
|
|
\\ return lookup_table[short];
|
|
\\ }
|
|
\\
|
|
\\ pub fn update(self: *Self, bytes: []const u8) void {
|
|
\\ var i: usize = 0;
|
|
\\ if (@bitSizeOf(I) <= 8) {
|
|
\\ while (i < bytes.len) : (i += 1) {
|
|
\\ self.crc = tableEntry(self.crc ^ bytes[i]);
|
|
\\ }
|
|
\\ } else if (algorithm.reflect_input) {
|
|
\\ while (i < bytes.len) : (i += 1) {
|
|
\\ const table_index = self.crc ^ bytes[i];
|
|
\\ self.crc = tableEntry(table_index) ^ (self.crc >> 8);
|
|
\\ }
|
|
\\ } else {
|
|
\\ while (i < bytes.len) : (i += 1) {
|
|
\\ const table_index = (self.crc >> (@bitSizeOf(I) - 8)) ^ bytes[i];
|
|
\\ self.crc = tableEntry(table_index) ^ (self.crc << 8);
|
|
\\ }
|
|
\\ }
|
|
\\ }
|
|
\\
|
|
\\ pub fn final(self: Self) W {
|
|
\\ var c = self.crc;
|
|
\\ if (algorithm.reflect_input != algorithm.reflect_output) {
|
|
\\ c = @bitReverse(c);
|
|
\\ }
|
|
\\ if (!algorithm.reflect_output) {
|
|
\\ c >>= @bitSizeOf(I) - @bitSizeOf(W);
|
|
\\ }
|
|
\\ return @intCast(c ^ algorithm.xor_output);
|
|
\\ }
|
|
\\
|
|
\\ pub fn hash(bytes: []const u8) W {
|
|
\\ var c = Self.init();
|
|
\\ c.update(bytes);
|
|
\\ return c.final();
|
|
\\ }
|
|
\\
|
|
\\ fn reflect(x: I) I {
|
|
\\ const offset = @bitSizeOf(I) - @bitSizeOf(W);
|
|
\\ if (algorithm.reflect_input)
|
|
\\ return @bitReverse(x) >> offset
|
|
\\ else
|
|
\\ return x << offset;
|
|
\\ }
|
|
\\ };
|
|
\\}
|
|
\\
|
|
\\test {
|
|
\\ _ = @import("crc/test.zig");
|
|
\\}
|
|
\\
|
|
);
|
|
|
|
try code_writer.flush();
|
|
try test_writer.flush();
|
|
}
|
|
|
|
fn printUsageAndExit(arg0: []const u8) noreturn {
|
|
const stderr = std.debug.lockStderr(&.{});
|
|
const w = &stderr.file_writer.interface;
|
|
printUsage(w, arg0) catch std.process.exit(2);
|
|
std.process.exit(1);
|
|
}
|
|
|
|
fn printUsage(w: *std.Io.Writer, arg0: []const u8) std.Io.Writer.Error!void {
|
|
return w.print(
|
|
\\Usage: {s} /path/git/zig
|
|
\\
|
|
, .{arg0});
|
|
}
|