Skip to content

Commit 4133bbd

Browse files
authored
Merge pull request #14396 from FnControlOption/crc
std.hash.crc: implement algorithms listed in CRC RevEng catalog
2 parents c0284e2 + 33682a2 commit 4133bbd

File tree

5 files changed

+2518
-0
lines changed

5 files changed

+2518
-0
lines changed

lib/std/hash/crc.zig

Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,102 @@ const builtin = @import("builtin");
1010
const debug = std.debug;
1111
const testing = std.testing;
1212

13+
pub usingnamespace @import("crc/catalog.zig");
14+
15+
pub fn Algorithm(comptime W: type) type {
16+
return struct {
17+
polynomial: W,
18+
initial: W,
19+
reflect_input: bool,
20+
reflect_output: bool,
21+
xor_output: W,
22+
};
23+
}
24+
25+
pub fn Crc(comptime W: type, comptime algorithm: Algorithm(W)) type {
26+
return struct {
27+
const Self = @This();
28+
const I = if (@bitSizeOf(W) < 8) u8 else W;
29+
const lookup_table = blk: {
30+
@setEvalBranchQuota(2500);
31+
32+
const poly = if (algorithm.reflect_input)
33+
@bitReverse(@as(I, algorithm.polynomial)) >> (@bitSizeOf(I) - @bitSizeOf(W))
34+
else
35+
@as(I, algorithm.polynomial) << (@bitSizeOf(I) - @bitSizeOf(W));
36+
37+
var table: [256]I = undefined;
38+
for (table) |*e, i| {
39+
var crc: I = i;
40+
if (algorithm.reflect_input) {
41+
var j: usize = 0;
42+
while (j < 8) : (j += 1) {
43+
crc = (crc >> 1) ^ ((crc & 1) * poly);
44+
}
45+
} else {
46+
crc <<= @bitSizeOf(I) - 8;
47+
var j: usize = 0;
48+
while (j < 8) : (j += 1) {
49+
crc = (crc << 1) ^ (((crc >> (@bitSizeOf(I) - 1)) & 1) * poly);
50+
}
51+
}
52+
e.* = crc;
53+
}
54+
break :blk table;
55+
};
56+
57+
crc: I,
58+
59+
pub fn init() Self {
60+
const initial = if (algorithm.reflect_input)
61+
@bitReverse(@as(I, algorithm.initial)) >> (@bitSizeOf(I) - @bitSizeOf(W))
62+
else
63+
@as(I, algorithm.initial) << (@bitSizeOf(I) - @bitSizeOf(W));
64+
return Self{ .crc = initial };
65+
}
66+
67+
inline fn tableEntry(index: I) I {
68+
return lookup_table[@intCast(u8, index & 0xFF)];
69+
}
70+
71+
pub fn update(self: *Self, bytes: []const u8) void {
72+
var i: usize = 0;
73+
if (@bitSizeOf(I) <= 8) {
74+
while (i < bytes.len) : (i += 1) {
75+
self.crc = tableEntry(self.crc ^ bytes[i]);
76+
}
77+
} else if (algorithm.reflect_input) {
78+
while (i < bytes.len) : (i += 1) {
79+
const table_index = self.crc ^ bytes[i];
80+
self.crc = tableEntry(table_index) ^ (self.crc >> 8);
81+
}
82+
} else {
83+
while (i < bytes.len) : (i += 1) {
84+
const table_index = (self.crc >> (@bitSizeOf(I) - 8)) ^ bytes[i];
85+
self.crc = tableEntry(table_index) ^ (self.crc << 8);
86+
}
87+
}
88+
}
89+
90+
pub fn final(self: Self) W {
91+
var c = self.crc;
92+
if (algorithm.reflect_input != algorithm.reflect_output) {
93+
c = @bitReverse(c);
94+
}
95+
if (!algorithm.reflect_output) {
96+
c >>= @bitSizeOf(I) - @bitSizeOf(W);
97+
}
98+
return @intCast(W, c ^ algorithm.xor_output);
99+
}
100+
101+
pub fn hash(bytes: []const u8) W {
102+
var c = Self.init();
103+
c.update(bytes);
104+
return c.final();
105+
}
106+
};
107+
}
108+
13109
pub const Polynomial = enum(u32) {
14110
IEEE = 0xedb88320,
15111
Castagnoli = 0x82f63b78,

0 commit comments

Comments
 (0)