// crc32.mbt
//
// 7z 全格式使用标准 CRC-32:反射多项式 0xEDB88320、初值 0xFFFFFFFF、输出取反,
// 与 zlib / libarchive / 7-Zip 的 `crc32` 完全一致。
//
// 这里做成表驱动的增量计算器:头部校验(F1)与后续解压时的数据校验(F4/F5)
// 共用同一实现,避免两处各写一份。
///|
/// 增量 CRC-32 计算器。
pub struct Crc32 {
table : FixedArray[Int64]
mut value : Int64
}
///|
/// 构造计算器(建立 256 项查表)。
pub fn Crc32::new() -> Crc32 {
let table : FixedArray[Int64] = FixedArray::make(256, 0L)
for i in 0..<256 {
let mut c = i.to_int64()
for _ in 0..<8 {
c = if (c & 1L) != 0L { (c >> 1) ^ 0xEDB88320L } else { c >> 1 }
}
table[i] = c
}
{ table, value: 0xFFFFFFFFL, }
}
///|
/// 送入 `data[start, end)` 区间的字节。
///
/// 区间会裁剪到 `[0, data.length())` 之内:本函数不负责报错,越界检查由
/// `ByteReader` 在读取阶段完成,这里只保证不会 panic。
pub fn Crc32::update(
self : Crc32,
data : Bytes,
start : Int32,
end : Int32,
) -> Unit {
let hi = if end < data.length() { end } else { data.length() }
let mut i = if start > 0 { start } else { 0 }
let mut c = self.value
while i < hi {
let idx = ((c ^ data.unsafe_get(i).to_int().to_int64()) & 0xFFL).to_int()
c = (c >> 8) ^ self.table[idx]
i += 1
}
self.value = c
}
///|
/// 输出最终校验值(0 .. 2^32-1)。
pub fn Crc32::finalize(self : Crc32) -> Int64 {
self.value ^ 0xFFFFFFFFL
}
///|
/// 一次性计算 `data[start, end)` 的 CRC-32。
pub fn crc32(data : Bytes, start : Int32, end : Int32) -> Int64 {
let c = Crc32::new()
c.update(data, start, end)
c.finalize()
}