| ... | ... | @@ -32,6 +32,7 @@ fn @"i like cheese"(arena: std.mem.Allocator, io: Io, args: []const []const u8) |
| 32 | 32 | |
| 33 | 33 | var zig_code_file = try hash_target_dir.createFile(io, "crc.zig", .{}); |
| 34 | 34 | defer zig_code_file.close(io); |
| 35 | |
| 35 | 36 | var zig_code_file_buffer: [4096]u8 = undefined; |
| 36 | 37 | var zig_code_file_writer = zig_code_file.writer(io, &zig_code_file_buffer); |
| 37 | 38 | 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) |
| 40 | 41 | \\//! This file is auto-generated by tools/update_crc_catalog.zig. |
| 41 | 42 | \\ |
| 42 | 43 | \\const builtin = @import("builtin"); |
| 43 | | \\const impl = @import("crc/impl.zig"); |
| 44 | | \\ |
| 45 | | \\pub const Crc = impl.Crc; |
| 46 | | \\pub const Polynomial = impl.Polynomial; |
| 47 | | \\pub const Crc32WithPoly = impl.Crc32WithPoly; |
| 48 | | \\pub const Crc32SmallWithPoly = impl.Crc32SmallWithPoly; |
| 49 | | \\ |
| 50 | | \\pub const Crc32 = Crc32IsoHdlc; |
| 51 | | \\ |
| 52 | | \\test { |
| 53 | | \\ _ = @import("crc/test.zig"); |
| 54 | | \\} |
| 55 | 44 | \\ |
| 56 | | \\pub const Crc32Iscsi = switch (builtin.cpu.hasAll(.x86, &.{ .@"64bit", .crc32 })) { |
| 57 | | \\ true => @import("crc/Crc32c.zig"), |
| 58 | | \\ else => Crc(u32, .{ |
| 45 | \\pub const Crc32Iscsi = if (builtin.cpu.hasAll(.x86, &.{ .@"64bit", .crc32 })) |
| 46 | \\ @import("crc/Crc32c.zig") |
| 47 | \\else |
| 48 | \\ Generic(u32, .{ |
| 59 | 49 | \\ .polynomial = 0x1edc6f41, |
| 60 | 50 | \\ .initial = 0xffffffff, |
| 61 | 51 | \\ .reflect_input = true, |
| 62 | 52 | \\ .reflect_output = true, |
| 63 | 53 | \\ .xor_output = 0xffffffff, |
| 64 | | \\ }), |
| 65 | | \\}; |
| 54 | \\ }); |
| 66 | 55 | \\ |
| 67 | 56 | ); |
| 68 | 57 | |
| 69 | 58 | var zig_test_file = try crc_target_dir.createFile(io, "test.zig", .{}); |
| 70 | 59 | defer zig_test_file.close(io); |
| 60 | |
| 71 | 61 | var zig_test_file_buffer: [4096]u8 = undefined; |
| 72 | 62 | var zig_test_file_writer = zig_test_file.writer(io, &zig_test_file_buffer); |
| 73 | 63 | 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) |
| 183 | 173 | |
| 184 | 174 | const camelcase = buf.items; |
| 185 | 175 | |
| 186 | | try code_writer.writeAll(try std.fmt.allocPrint(arena, |
| 176 | try code_writer.print( |
| 187 | 177 | \\ |
| 188 | | \\pub const {s} = Crc(u{s}, .{{ |
| 178 | \\pub const {s} = Generic(u{s}, .{{ |
| 189 | 179 | \\ .polynomial = {s}, |
| 190 | 180 | \\ .initial = {s}, |
| 191 | 181 | \\ .reflect_input = {s}, |
| ... | ... | @@ -193,9 +183,9 @@ fn @"i like cheese"(arena: std.mem.Allocator, io: Io, args: []const []const u8) |
| 193 | 183 | \\ .xor_output = {s}, |
| 194 | 184 | \\}}); |
| 195 | 185 | \\ |
| 196 | | , .{ camelcase, width, poly, init, refin, refout, xorout })); |
| 186 | , .{ camelcase, width, poly, init, refin, refout, xorout }); |
| 197 | 187 | |
| 198 | | try test_writer.writeAll(try std.fmt.allocPrint(arena, |
| 188 | try test_writer.print( |
| 199 | 189 | \\ |
| 200 | 190 | \\test "{0s}" {{ |
| 201 | 191 | \\ const {1s} = crc.{1s}; |
| ... | ... | @@ -208,9 +198,112 @@ fn @"i like cheese"(arena: std.mem.Allocator, io: Io, args: []const []const u8) |
| 208 | 198 | \\ try testing.expectEqual(@as(u{2s}, {3s}), c.final()); |
| 209 | 199 | \\}} |
| 210 | 200 | \\ |
| 211 | | , .{ name, camelcase, width, check })); |
| 201 | , .{ name, camelcase, width, check }); |
| 212 | 202 | } |
| 213 | 203 | |
| 204 | try code_writer.writeAll( |
| 205 | \\ |
| 206 | \\pub fn Algorithm(comptime W: type) type { |
| 207 | \\ return struct { |
| 208 | \\ polynomial: W, |
| 209 | \\ initial: W, |
| 210 | \\ reflect_input: bool, |
| 211 | \\ reflect_output: bool, |
| 212 | \\ xor_output: W, |
| 213 | \\ }; |
| 214 | \\} |
| 215 | \\ |
| 216 | \\pub fn Generic(comptime W: type, comptime algorithm: Algorithm(W)) type { |
| 217 | \\ return struct { |
| 218 | \\ const Self = @This(); |
| 219 | \\ const I = if (@bitSizeOf(W) < 8) u8 else W; |
| 220 | \\ const lookup_table = blk: { |
| 221 | \\ @setEvalBranchQuota(2500); |
| 222 | \\ const poly = reflect(algorithm.polynomial); |
| 223 | \\ var table: [256]I = undefined; |
| 224 | \\ for (&table, 0..) |*e, i| { |
| 225 | \\ var crc: I = i; |
| 226 | \\ if (algorithm.reflect_input) { |
| 227 | \\ var j: usize = 0; |
| 228 | \\ while (j < 8) : (j += 1) { |
| 229 | \\ crc = (crc >> 1) ^ ((crc & 1) * poly); |
| 230 | \\ } |
| 231 | \\ } else { |
| 232 | \\ crc <<= @bitSizeOf(I) - 8; |
| 233 | \\ var j: usize = 0; |
| 234 | \\ while (j < 8) : (j += 1) { |
| 235 | \\ crc = (crc << 1) ^ (((crc >> (@bitSizeOf(I) - 1)) & 1) * poly); |
| 236 | \\ } |
| 237 | \\ } |
| 238 | \\ e.* = crc; |
| 239 | \\ } |
| 240 | \\ break :blk table; |
| 241 | \\ }; |
| 242 | \\ |
| 243 | \\ crc: I, |
| 244 | \\ |
| 245 | \\ pub fn init() Self { |
| 246 | \\ const initial = reflect(algorithm.initial); |
| 247 | \\ return .{ .crc = initial }; |
| 248 | \\ } |
| 249 | \\ |
| 250 | \\ inline fn tableEntry(index: I) I { |
| 251 | \\ const short: u8 = @truncate(index); |
| 252 | \\ return lookup_table[short]; |
| 253 | \\ } |
| 254 | \\ |
| 255 | \\ pub fn update(self: *Self, bytes: []const u8) void { |
| 256 | \\ var i: usize = 0; |
| 257 | \\ if (@bitSizeOf(I) <= 8) { |
| 258 | \\ while (i < bytes.len) : (i += 1) { |
| 259 | \\ self.crc = tableEntry(self.crc ^ bytes[i]); |
| 260 | \\ } |
| 261 | \\ } else if (algorithm.reflect_input) { |
| 262 | \\ while (i < bytes.len) : (i += 1) { |
| 263 | \\ const table_index = self.crc ^ bytes[i]; |
| 264 | \\ self.crc = tableEntry(table_index) ^ (self.crc >> 8); |
| 265 | \\ } |
| 266 | \\ } else { |
| 267 | \\ while (i < bytes.len) : (i += 1) { |
| 268 | \\ const table_index = (self.crc >> (@bitSizeOf(I) - 8)) ^ bytes[i]; |
| 269 | \\ self.crc = tableEntry(table_index) ^ (self.crc << 8); |
| 270 | \\ } |
| 271 | \\ } |
| 272 | \\ } |
| 273 | \\ |
| 274 | \\ pub fn final(self: Self) W { |
| 275 | \\ var c = self.crc; |
| 276 | \\ if (algorithm.reflect_input != algorithm.reflect_output) { |
| 277 | \\ c = @bitReverse(c); |
| 278 | \\ } |
| 279 | \\ if (!algorithm.reflect_output) { |
| 280 | \\ c >>= @bitSizeOf(I) - @bitSizeOf(W); |
| 281 | \\ } |
| 282 | \\ return @intCast(c ^ algorithm.xor_output); |
| 283 | \\ } |
| 284 | \\ |
| 285 | \\ pub fn hash(bytes: []const u8) W { |
| 286 | \\ var c = Self.init(); |
| 287 | \\ c.update(bytes); |
| 288 | \\ return c.final(); |
| 289 | \\ } |
| 290 | \\ |
| 291 | \\ fn reflect(x: I) I { |
| 292 | \\ const offset = @bitSizeOf(I) - @bitSizeOf(W); |
| 293 | \\ if (algorithm.reflect_input) |
| 294 | \\ return @bitReverse(x) >> offset |
| 295 | \\ else |
| 296 | \\ return x << offset; |
| 297 | \\ } |
| 298 | \\ }; |
| 299 | \\} |
| 300 | \\ |
| 301 | \\test { |
| 302 | \\ _ = @import("crc/test.zig"); |
| 303 | \\} |
| 304 | \\ |
| 305 | ); |
| 306 | |
| 214 | 307 | try code_writer.flush(); |
| 215 | 308 | try test_writer.flush(); |
| 216 | 309 | } |