From 030e7d3567328e5948f721ae2b7dbd95d94f0b7a Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Fri, 26 Jun 2026 15:41:17 -0700 Subject: [PATCH] std.hash.crc: restore auto-generated status --- lib/std/hash/crc.zig | 2 +- tools/update_crc_catalog.zig | 137 +++++++++++++++++++++++++++++------ 2 files changed, 116 insertions(+), 23 deletions(-) diff --git a/lib/std/hash/crc.zig b/lib/std/hash/crc.zig index b0149c20808dbb00fd5ec6af416006616565d833..a35f23e92383aad920493155d966a1fe11b6d040 100644 --- a/lib/std/hash/crc.zig +++ b/lib/std/hash/crc.zig @@ -1,4 +1,4 @@ -//! This file is maintained with the help of tools/update_crc_catalog.zig. +//! This file is auto-generated by tools/update_crc_catalog.zig. const builtin = @import("builtin"); diff --git a/tools/update_crc_catalog.zig b/tools/update_crc_catalog.zig index 283b60b0d19ef14285bd758fa8aae7631e955690..09a517e8bba21cd1eff57c0b7ef09d2f9909b8f8 100644 --- a/tools/update_crc_catalog.zig +++ b/tools/update_crc_catalog.zig @@ -32,6 +32,7 @@ fn @"i like cheese"(arena: std.mem.Allocator, io: Io, args: []const []const u8) 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; @@ -40,34 +41,23 @@ fn @"i like cheese"(arena: std.mem.Allocator, io: Io, args: []const []const u8) \\//! This file is auto-generated by tools/update_crc_catalog.zig. \\ \\const builtin = @import("builtin"); - \\const impl = @import("crc/impl.zig"); \\ - \\pub const Crc = impl.Crc; - \\pub const Polynomial = impl.Polynomial; - \\pub const Crc32WithPoly = impl.Crc32WithPoly; - \\pub const Crc32SmallWithPoly = impl.Crc32SmallWithPoly; - \\ - \\pub const Crc32 = Crc32IsoHdlc; - \\ - \\test { - \\ _ = @import("crc/test.zig"); - \\} - \\ - \\pub const Crc32Iscsi = switch (builtin.cpu.hasAll(.x86, &.{ .@"64bit", .crc32 })) { - \\ true => @import("crc/Crc32c.zig"), - \\ else => Crc(u32, .{ + \\pub const Crc32Iscsi = if (builtin.cpu.hasAll(.x86, &.{ .@"64bit", .crc32 })) + \\ @import("crc/Crc32c.zig") + \\else + \\ Generic(u32, .{ \\ .polynomial = 0x1edc6f41, \\ .initial = 0xffffffff, \\ .reflect_input = true, \\ .reflect_output = true, \\ .xor_output = 0xffffffff, - \\ }), - \\}; + \\ }); \\ ); 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; @@ -183,9 +173,9 @@ fn @"i like cheese"(arena: std.mem.Allocator, io: Io, args: []const []const u8) const camelcase = buf.items; - try code_writer.writeAll(try std.fmt.allocPrint(arena, + try code_writer.print( \\ - \\pub const {s} = Crc(u{s}, .{{ + \\pub const {s} = Generic(u{s}, .{{ \\ .polynomial = {s}, \\ .initial = {s}, \\ .reflect_input = {s}, @@ -193,9 +183,9 @@ fn @"i like cheese"(arena: std.mem.Allocator, io: Io, args: []const []const u8) \\ .xor_output = {s}, \\}}); \\ - , .{ camelcase, width, poly, init, refin, refout, xorout })); + , .{ camelcase, width, poly, init, refin, refout, xorout }); - try test_writer.writeAll(try std.fmt.allocPrint(arena, + try test_writer.print( \\ \\test "{0s}" {{ \\ const {1s} = crc.{1s}; @@ -208,9 +198,112 @@ fn @"i like cheese"(arena: std.mem.Allocator, io: Io, args: []const []const u8) \\ try testing.expectEqual(@as(u{2s}, {3s}), c.final()); \\}} \\ - , .{ name, camelcase, width, check })); + , .{ name, camelcase, 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(); } -- 2.54.0