Files
Viper_VRTE/gzip.vp
T
TermiNexus e71daeea0e docs(includes): R11 注释英文化——75 个文件的中文注释改写为英文短注释
按规范「注释只讲解作用,不掺杂历史原因,尽量英文」:把 includes 下 75 个 .vp 的中文 # 注释与三引号 docstring 改写为英文,每个注释块压到 2 行以内。

保留要点:作用、约束、危险警告(不得/必须/注意)、ABI 与类型约定(如 BYTEPTR | t.CPtr = i8** 的跨模块坍缩坑)、位宽/长度约定、fail-fast 要求、内存与句柄所有权。

未动:文件头注释(规范豁免,仍是中文)、运行时中文字符串常量(printf / fatal_error / MlirFail 等用户可见消息,属代码字面量)。

验证:独立脚本比对 HEAD 与工作区的代码骨架(剥离 # 注释与三引号 docstring 后的非空行)——75 个文件逐字节一致;行尾 CRLF/LF 未被改动;全文剩余中文仅 547 行头注释、0 条行尾注释。bootstrap 三重重编 SUCCESS;全量 77/77 顺序回归通过。
2026-10-05 16:18:44 +08:00

611 lines
19 KiB
Plaintext

# -*- coding: utf-8 -*-
# ============================================================
# gzip - 单文件 gzip 解码器(RFC 1952 + RFC 1951 deflate)
#
# OOP 范式对齐 zipfile: 数据由 GzipFile 对象持有并负责释放;
# 内部位流/Huffman 助手为模块级私有函数。
#
# 用法:
# gz: rawptr[gzip.GzipFile] = gzip.GzipFile("train-images-idx3-ubyte.gz")
# if gz is None or gz.ok == 0: ...
# buf: bytes = gz.read_all() # 内部 malloc, read_all 返回即解压完成
# n: sizet = gz.dst_len # 原始长度(由对象持有, close 时释放)
# gz.close()
#
# 覆盖 stored/fixed/dynamic 三种 deflate 块; 不解 CRC。
# ============================================================
import t, c
import stdlib
import string
import w32.fileio as fileio
from stdint import *
# ============================================================
# GzipFile
# ============================================================
class GzipFile:
ok: int # 1 = usable
err: int # error code (0 = none, <0 = error)
src: bytes # in-memory copy of whole .gz file (read in ctor, freed by close)
src_len: sizet
dst: bytes # decompressed output buffer (created by read_all, freed by close)
dst_len: sizet # decompressed length
_need_close_src: int # whether src is owned (0 if read failed)
def __init__(self, path: str):
self.ok = 0
self.err = 0
self.src = None
self.src_len = 0
self.dst = None
self.dst_len = 0
self._need_close_src = 0
if path is None:
self.err = -1
return
f: fileio.File = fileio.File(path, fileio.MODE.R)
if f.closed:
self.err = -2 # cannot open file
return
sz: longlong = f.size()
if sz < 18:
f.close()
self.err = -3 # file too small
return
self.src_len = sizet(sz)
# read_all contract: reads up to max_count-1 bytes and NUL-terminates; request src_len+1.
buf: bytes = stdlib.malloc(self.src_len + 1)
if buf is None:
f.close()
self.err = -4
return
got: LONG = f.read_all(buf, ULONG(self.src_len + 1))
f.close()
if got <= 0 or sizet(got) != self.src_len:
stdlib.free(buf)
self.err = -5 # read failed or truncated
return
# gzip magic-number check
ub: uchar* = buf
if ub[0] != 0x1F or ub[1] != 0x8B or ub[2] != 8:
stdlib.free(buf)
self.err = -6
return
self.src = buf
self._need_close_src = 1
self.ok = 1
def read_all(self) -> bytes:
"""Decompress the whole member. Returns internal output buffer (or None); length in self.dst_len."""
if self.ok == 0 or self.src is None:
return None
if self.dst is not None:
return self.dst # already decompressed
want: uint32 = gzip_isize(self.src, self.src_len)
cap: sizet = sizet(want)
if cap == 0:
cap = self.src_len * 64 # conservative initial value when no ISIZE
if cap < 1024:
cap = 1024
# If ISIZE mismatches actual size (buffer-too-small), double cap and retry (normally one pass).
out: BYTEPTR = None
n: LONG = 0
while True:
out = stdlib.malloc(cap)
if out is None:
self.err = -7
return None
n = _gzip_decode(self.src, self.src_len, out, cap)
if n == -9 or n == -18 or n == -23:
stdlib.free(out)
out = None
if cap >= 1073741824:
self.err = int(n)
return None
cap = cap * 2
continue
break
if n <= 0:
stdlib.free(out)
self.err = int(n) # n is a negative error code; store as-is
return None
self.dst = out
self.dst_len = sizet(n)
return out
def close(self):
if self._need_close_src != 0 and self.src is not None:
stdlib.free(self.src)
if self.dst is not None:
stdlib.free(self.dst)
self.src = None
self.dst = None
self.src_len = 0
self.dst_len = 0
self._need_close_src = 0
self.ok = 0
# ============================================================
# Bit-stream state (module-level, single-thread; reset per _gzip_decode)
# ============================================================
_g_bits: uint64 = 0
_g_bitcnt: int = 0
_g_pos: sizet = 0
_g_src: t.CPtr = None
_g_src_len: sizet = 0
def gzip_isize(src: t.CPtr, src_len: sizet) -> uint32:
"""gzip trailing ISIZE (little-endian u32): original length hint."""
if src is None or src_len < 4:
return 0
ub: uchar* = src
p: sizet = src_len - 4
# Assemble little-endian u32 (build in 64-bit then narrow)
v64: uint64 = uint64(ub[p]) \
+ uint64(ub[p + 1]) * 256 \
+ uint64(ub[p + 2]) * 65536 \
+ uint64(ub[p + 3]) * 16777216
return uint32(v64)
def _reset(src: t.CPtr, src_len: sizet):
global _g_bits, _g_bitcnt, _g_pos, _g_src, _g_src_len
_g_bits = 0
_g_bitcnt = 0
_g_pos = 0
_g_src = src
_g_src_len = src_len
def _fill(n: int) -> int:
global _g_bits, _g_bitcnt, _g_pos, _g_src, _g_src_len
sb: uchar* = _g_src
while _g_bitcnt < n:
if _g_pos >= _g_src_len:
return -1
_g_bits = _g_bits | (uint64(sb[_g_pos]) << _g_bitcnt)
_g_pos += 1
_g_bitcnt += 8
return 0
def _bits(n: int) -> int:
global _g_bits, _g_bitcnt
if _fill(n) != 0:
return -1
v: uint64 = _g_bits & ((uint64(1) << n) - 1)
_g_bits = _g_bits >> n
_g_bitcnt -= n
return int(v)
def _byte() -> int:
return _bits(8)
def _align():
global _g_bits, _g_bitcnt
_g_bits = 0
_g_bitcnt = 0
def _decode(count: int*, first: int*,
off: int*, sorted: int*) -> int:
code: int = 0
ln: int = 1
while ln <= 15:
b: int = _bits(1)
if b < 0:
return -1
code = (code << 1) | b
if count[ln] != 0:
d: int = code - first[ln]
if d >= 0 and d < count[ln]:
return sorted[off[ln] + d]
ln += 1
return -1
def _build(first: int*, off: int*,
count: int*) -> int:
anylen: int = 0
l1: int = 1
while l1 <= 15:
if count[l1] != 0:
anylen = 1
l1 += 1
if anylen == 0:
return -1
left: int = 1
l2: int = 1
while l2 <= 15:
left = left << 1
if count[l2] > left:
return -1
left = left - count[l2]
l2 += 1
code: int = 0
l3: int = 1
while l3 <= 15:
code = (code + count[l3 - 1]) << 1
first[l3] = code
l3 += 1
offsum: int = 0
l4: int = 1
while l4 <= 15:
off[l4] = offsum
offsum += count[l4]
l4 += 1
return 0
def _collect(len_arr: int*, cnt: int*,
sorted_arr: int*, nsym: int,
pos: int*):
string.memset(cnt, 0, 17 * 4)
for s1 in range(nsym):
if len_arr[s1] != 0:
cnt[len_arr[s1]] += 1
run: int = 0
l5: int = 1
while l5 <= 15:
pos[l5] = run
run += cnt[l5]
l5 += 1
for s2 in range(nsym):
if len_arr[s2] != 0:
sorted_arr[pos[len_arr[s2]]] = s2
pos[len_arr[s2]] += 1
def _len_extra(code: int) -> int:
if code == 285:
return 0
if code >= 281:
return 5
if code >= 277:
return 4
if code >= 273:
return 3
if code >= 269:
return 2
if code >= 265:
return 1
return 0
def _len_base(code: int) -> int:
if code == 285:
return 258
if code >= 281:
return 131 + ((code - 281) << 5)
if code >= 277:
return 67 + ((code - 277) << 4)
if code >= 273:
return 35 + ((code - 273) << 3)
if code >= 269:
return 19 + ((code - 269) << 2)
if code >= 265:
return 11 + ((code - 265) << 1)
return 3 + (code - 257)
def _dist_extra(code: int) -> int:
if code < 4:
return 0
return (code - 4) // 2 + 1
def _dist_base(code: int) -> int:
if code < 4:
return code + 1
e: int = (code - 4) // 2 + 1
f: int = (1 << (e + 1)) + 1
if code % 2 == 0:
return f
return f + (1 << e)
def _cl_order_set(arr: int*, idx: int, val: int):
arr[idx] = val
# ============================================================
# Core decompression (module-private)
# ============================================================
def _gzip_decode(src: t.CPtr, src_len: sizet,
dst: t.CPtr, dst_cap: sizet) -> LONG:
if src is None or dst is None or src_len < 18 or dst_cap == 0:
return -1
ub: uchar* = src
if ub[0] != 0x1F or ub[1] != 0x8B or ub[2] != 8:
return -2
_reset(src, src_len)
flg: int = int(ub[3])
hdr_len: sizet = 10
if flg & 0x04 != 0:
xlen: sizet = sizet(ub[hdr_len]) | (sizet(ub[hdr_len + 1]) << 8)
hdr_len += 2 + xlen
if flg & 0x08 != 0:
while hdr_len < src_len and ub[hdr_len] != 0:
hdr_len += 1
hdr_len += 1
if flg & 0x10 != 0:
while hdr_len < src_len and ub[hdr_len] != 0:
hdr_len += 1
hdr_len += 1
if flg & 0x02 != 0:
hdr_len += 2
if hdr_len >= src_len:
return -3
global _g_pos
_g_pos = hdr_len
dout: uchar* = dst
wpos: sizet = 0
lit_len: int* = stdlib.malloc(288 * 4)
lit_cnt: int* = stdlib.malloc(17 * 4)
lit_first: int* = stdlib.malloc(17 * 4)
lit_off: int* = stdlib.malloc(17 * 4)
lit_sorted: int* = stdlib.malloc(288 * 4)
dst_len: int* = stdlib.malloc(32 * 4)
dst_cnt: int* = stdlib.malloc(17 * 4)
dst_first: int* = stdlib.malloc(17 * 4)
dst_off: int* = stdlib.malloc(17 * 4)
dst_sorted: int* = stdlib.malloc(32 * 4)
cl_len: int* = stdlib.malloc(19 * 4)
cl_order: int* = stdlib.malloc(19 * 4)
cl_cnt: int* = stdlib.malloc(17 * 4)
cl_first: int* = stdlib.malloc(17 * 4)
cl_off: int* = stdlib.malloc(17 * 4)
cl_sorted: int* = stdlib.malloc(19 * 4)
pos_tmp: int* = stdlib.malloc(17 * 4)
if lit_len is None or lit_cnt is None or lit_first is None \
or lit_off is None or lit_sorted is None or dst_len is None \
or dst_cnt is None or dst_first is None or dst_off is None \
or dst_sorted is None or cl_len is None or cl_order is None \
or cl_cnt is None or cl_first is None or cl_off is None \
or cl_sorted is None or pos_tmp is None:
return -4
# Zero all table buffers (malloc is uninitialized; avoids garbage tables causing early/bad finish).
string.memset(lit_len, 0, 288 * 4)
string.memset(lit_cnt, 0, 17 * 4)
string.memset(lit_first, 0, 17 * 4)
string.memset(lit_off, 0, 17 * 4)
string.memset(lit_sorted, 0, 288 * 4)
string.memset(dst_len, 0, 32 * 4)
string.memset(dst_cnt, 0, 17 * 4)
string.memset(dst_first, 0, 17 * 4)
string.memset(dst_off, 0, 17 * 4)
string.memset(dst_sorted, 0, 32 * 4)
string.memset(cl_len, 0, 19 * 4)
string.memset(cl_order, 0, 19 * 4)
string.memset(cl_cnt, 0, 17 * 4)
string.memset(cl_first, 0, 17 * 4)
string.memset(cl_off, 0, 17 * 4)
string.memset(cl_sorted, 0, 19 * 4)
string.memset(pos_tmp, 0, 17 * 4)
_cl_order_set(cl_order, 0, 16)
_cl_order_set(cl_order, 1, 17)
_cl_order_set(cl_order, 2, 18)
_cl_order_set(cl_order, 3, 0)
_cl_order_set(cl_order, 4, 8)
_cl_order_set(cl_order, 5, 7)
_cl_order_set(cl_order, 6, 9)
_cl_order_set(cl_order, 7, 6)
_cl_order_set(cl_order, 8, 10)
_cl_order_set(cl_order, 9, 5)
_cl_order_set(cl_order, 10, 11)
_cl_order_set(cl_order, 11, 4)
_cl_order_set(cl_order, 12, 12)
_cl_order_set(cl_order, 13, 3)
_cl_order_set(cl_order, 14, 13)
_cl_order_set(cl_order, 15, 2)
_cl_order_set(cl_order, 16, 14)
_cl_order_set(cl_order, 17, 1)
_cl_order_set(cl_order, 18, 15)
err: int = 0
final: int = 0
while final == 0 and err == 0:
bfinal: int = _bits(1)
btype: int = _bits(2)
if bfinal < 0 or btype < 0:
err = -5
break
final = bfinal
if btype == 0:
_align()
slen: int = _bits(16)
snlen: int = _bits(16)
if slen < 0 or snlen < 0:
err = -6
break
if (slen ^ snlen) != 0xFFFF:
err = -7
break
for i in range(sizet(slen)):
ch: int = _byte()
if ch < 0:
err = -8
break
if wpos >= dst_cap:
err = -9
break
dout[wpos] = uchar(ch)
wpos += 1
if err != 0:
break
elif btype == 1:
string.memset(lit_cnt, 0, 17 * 4)
j: int = 0
while j < 144:
lit_len[j] = 8
j += 1
while j < 256:
lit_len[j] = 9
j += 1
while j < 280:
lit_len[j] = 7
j += 1
while j < 288:
lit_len[j] = 8
j += 1
_collect(lit_len, lit_cnt, lit_sorted, 288, pos_tmp)
if _build(lit_first, lit_off, lit_cnt) != 0:
err = -10
break
else:
hlit: int = _bits(5) + 257
hdist: int = _bits(5) + 1
hclen: int = _bits(4) + 4
if hlit < 0 or hdist < 0 or hclen < 0:
err = -11
break
string.memset(cl_len, 0, 19 * 4)
for k in range(hclen):
vv: int = _bits(3)
if vv < 0:
err = -12
break
cl_len[cl_order[k]] = vv
if err != 0:
break
_collect(cl_len, cl_cnt, cl_sorted, 19, pos_tmp)
if _build(cl_first, cl_off, cl_cnt) != 0:
err = -13
break
string.memset(lit_len, 0, 288 * 4)
string.memset(dst_len, 0, 32 * 4)
sym_i: int = 0
while sym_i < hlit + hdist:
sym: int = _decode(cl_cnt, cl_first, cl_off, cl_sorted)
if sym < 0:
err = -14
break
if sym < 16:
if sym_i < hlit:
lit_len[sym_i] = sym
else:
dst_len[sym_i - hlit] = sym
sym_i += 1
elif sym == 16:
prev: int = 0
if sym_i > 0:
if sym_i - 1 < hlit:
prev = lit_len[sym_i - 1]
else:
prev = dst_len[sym_i - hlit - 1]
rp: int = _bits(2) + 3
r2: int = 0
while r2 < rp and sym_i < hlit + hdist:
if sym_i < hlit:
lit_len[sym_i] = prev
else:
dst_len[sym_i - hlit] = prev
sym_i += 1
r2 += 1
elif sym == 17:
rp2: int = _bits(3) + 3
r3: int = 0
while r3 < rp2 and sym_i < hlit + hdist:
if sym_i < hlit:
lit_len[sym_i] = 0
else:
dst_len[sym_i - hlit] = 0
sym_i += 1
r3 += 1
else:
rp3: int = _bits(7) + 11
r4: int = 0
while r4 < rp3 and sym_i < hlit + hdist:
if sym_i < hlit:
lit_len[sym_i] = 0
else:
dst_len[sym_i - hlit] = 0
sym_i += 1
r4 += 1
if err != 0:
break
_collect(lit_len, lit_cnt, lit_sorted, hlit, pos_tmp)
if _build(lit_first, lit_off, lit_cnt) != 0:
err = -15
break
_collect(dst_len, dst_cnt, dst_sorted, hdist, pos_tmp)
if _build(dst_first, dst_off, dst_cnt) != 0:
err = -16
break
if err != 0:
break
run: int = 1
while run == 1 and err == 0:
sym: int = _decode(lit_cnt, lit_first, lit_off, lit_sorted)
if sym < 0:
err = -17
break
if sym < 256:
if wpos >= dst_cap:
err = -18
break
dout[wpos] = uchar(sym)
wpos += 1
elif sym == 256:
run = 0
else:
le: int = _len_extra(sym)
ev: int = _bits(le)
if ev < 0:
err = -19
break
length: sizet = sizet(_len_base(sym) + ev)
ds: int = _decode(dst_cnt, dst_first, dst_off, dst_sorted)
if ds < 0:
err = -20
break
de: int = _dist_extra(ds)
dv: int = _bits(de)
if dv < 0:
err = -21
break
dist: sizet = sizet(_dist_base(ds) + dv)
if dist == 0 or dist > wpos:
err = -22
break
for ci in range(length):
if wpos >= dst_cap:
err = -23
break
dout[wpos] = dout[wpos - dist]
wpos += 1
if err != 0:
break
stdlib.free(lit_len)
stdlib.free(lit_cnt)
stdlib.free(lit_first)
stdlib.free(lit_off)
stdlib.free(lit_sorted)
stdlib.free(dst_len)
stdlib.free(dst_cnt)
stdlib.free(dst_first)
stdlib.free(dst_off)
stdlib.free(dst_sorted)
stdlib.free(cl_len)
stdlib.free(cl_order)
stdlib.free(cl_cnt)
stdlib.free(cl_first)
stdlib.free(cl_off)
stdlib.free(cl_sorted)
stdlib.free(pos_tmp)
if err != 0:
return LONG(err) # err is already a negative code; do not negate it (else callers treat >0 as success)
return LONG(wpos)