| ... | @@ -32,6 +32,7 @@ fn @"i like cheese"(arena: std.mem.Allocator, io: Io, args: []const []const u8) | ... | @@ -32,6 +32,7 @@ fn @"i like cheese"(arena: std.mem.Allocator, io: Io, args: []const []const u8) |
| 32 | | 32 | |
| 33 | var zig_code_file = try hash_target_dir.createFile(io, "crc.zig", .{}); | 33 | var zig_code_file = try hash_target_dir.createFile(io, "crc.zig", .{}); |
| 34 | defer zig_code_file.close(io); | 34 | defer zig_code_file.close(io); |
| | 35 | |
| 35 | var zig_code_file_buffer: [4096]u8 = undefined; | 36 | var zig_code_file_buffer: [4096]u8 = undefined; |
| 36 | var zig_code_file_writer = zig_code_file.writer(io, &zig_code_file_buffer); | 37 | var zig_code_file_writer = zig_code_file.writer(io, &zig_code_file_buffer); |
| 37 | const code_writer = &zig_code_file_writer.interface; | 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,34 +41,23 @@ fn @"i like cheese"(arena: std.mem.Allocator, io: Io, args: []const []const u8) |
| 40 | \\//! This file is auto-generated by tools/update_crc_catalog.zig. | 41 | \\//! This file is auto-generated by tools/update_crc_catalog.zig. |
| 41 | \\ | 42 | \\ |
| 42 | \\const builtin = @import("builtin"); | 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 })) { | 45 | \\pub const Crc32Iscsi = if (builtin.cpu.hasAll(.x86, &.{ .@"64bit", .crc32 })) |
| 57 | \\ true => @import("crc/Crc32c.zig"), | 46 | \\ @import("crc/Crc32c.zig") |
| 58 | \\ else => Crc(u32, .{ | 47 | \\else |
| | 48 | \\ Generic(u32, .{ |
| 59 | \\ .polynomial = 0x1edc6f41, | 49 | \\ .polynomial = 0x1edc6f41, |
| 60 | \\ .initial = 0xffffffff, | 50 | \\ .initial = 0xffffffff, |
| 61 | \\ .reflect_input = true, | 51 | \\ .reflect_input = true, |
| 62 | \\ .reflect_output = true, | 52 | \\ .reflect_output = true, |
| 63 | \\ .xor_output = 0xffffffff, | 53 | \\ .xor_output = 0xffffffff, |
| 64 | \\ }), | 54 | \\ }); |
| 65 | \\}; | | |
| 66 | \\ | 55 | \\ |
| 67 | ); | 56 | ); |
| 68 | | 57 | |
| 69 | var zig_test_file = try crc_target_dir.createFile(io, "test.zig", .{}); | 58 | var zig_test_file = try crc_target_dir.createFile(io, "test.zig", .{}); |
| 70 | defer zig_test_file.close(io); | 59 | defer zig_test_file.close(io); |
| | 60 | |
| 71 | var zig_test_file_buffer: [4096]u8 = undefined; | 61 | var zig_test_file_buffer: [4096]u8 = undefined; |
| 72 | var zig_test_file_writer = zig_test_file.writer(io, &zig_test_file_buffer); | 62 | var zig_test_file_writer = zig_test_file.writer(io, &zig_test_file_buffer); |
| 73 | const test_writer = &zig_test_file_writer.interface; | 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,9 +173,9 @@ fn @"i like cheese"(arena: std.mem.Allocator, io: Io, args: []const []const u8) |
| 183 | | 173 | |
| 184 | const camelcase = buf.items; | 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 | \\ .polynomial = {s}, | 179 | \\ .polynomial = {s}, |
| 190 | \\ .initial = {s}, | 180 | \\ .initial = {s}, |
| 191 | \\ .reflect_input = {s}, | 181 | \\ .reflect_input = {s}, |
| ... | @@ -193,9 +183,9 @@ fn @"i like cheese"(arena: std.mem.Allocator, io: Io, args: []const []const u8) | ... | @@ -193,9 +183,9 @@ fn @"i like cheese"(arena: std.mem.Allocator, io: Io, args: []const []const u8) |
| 193 | \\ .xor_output = {s}, | 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 | \\test "{0s}" {{ | 190 | \\test "{0s}" {{ |
| 201 | \\ const {1s} = crc.{1s}; | 191 | \\ const {1s} = crc.{1s}; |
| ... | @@ -208,9 +198,112 @@ fn @"i like cheese"(arena: std.mem.Allocator, io: Io, args: []const []const u8) | ... | @@ -208,9 +198,112 @@ fn @"i like cheese"(arena: std.mem.Allocator, io: Io, args: []const []const u8) |
| 208 | \\ try testing.expectEqual(@as(u{2s}, {3s}), c.final()); | 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 | try code_writer.flush(); | 307 | try code_writer.flush(); |
| 215 | try test_writer.flush(); | 308 | try test_writer.flush(); |
| 216 | } | 309 | } |