Files
zig/tools/update_crc_catalog.zig
Krzysztof Wolicki ab4028d579 Update usages of most deprecated APIs
In particular renames of `std.mem.indexOf` family to `std.mem.find`
and generic unmanaged containers
2026-08-05 03:40:30 +02:00

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});
}