将 zipfile 改为最简洁形式

This commit is contained in:
TermiNexus committed 2026-09-29 16:47:20 +08:00
1 parent 4957ba5661
commit 9cef4d8b56
1 file changed
+26 -28
+26 -28
View File
@@ -11,16 +11,14 @@
# 成员名为原始 UTF-8 字节(写入时置 flag bit 11,读取时不自动解码)。
#
# 用法(对齐 Python 语义,只读模式自动把整个 zip 读入内存):
# w: rawptr[zipfile.ZipFile] = zipfile.ZipFile("out.zip", "w")
# w: zipfile.ZipFile* = zipfile.ZipFile("out.zip", "w")
# w.write("a.txt", buf, buf_len) # 默认 ZIP_DEFLATED
# w.close()
#
# r: rawptr[zipfile.ZipFile] = zipfile.ZipFile("out.zip", "r")
# r: zipfile.ZipFile* = zipfile.ZipFile("out.zip", "r")
# olen: sizet = 0
# data: bytes = r.read("a.txt", &olen) # malloc 缓冲,用后 free
# err = zipfile.error_code() / zipfile.error()
import t, c
import stdlib
import string
import viperlib
@@ -93,7 +91,7 @@ def error() -> str:
# ============================================================
def zf_strlen(s: bytes) -> sizet:
n: sizet = 0
while s is not None and c.Deref(s) != 0:
while s is not None and *s != 0:
n += 1
s += 1
return n
@@ -159,7 +157,7 @@ def zf_read_all(h: wb.HANDLE, p: uint8*, n: sizet) -> int:
if chunk > 0xFFFFFF00:
chunk = 0xFFFFFF00
bytes_read: ulong = 0
ok: int = wf.ReadFile(h, p + done, ulong(chunk), c.Addr(bytes_read), None)
ok: int = wf.ReadFile(h, p + done, ulong(chunk), &bytes_read, None)
if ok == 0 or bytes_read == 0:
global zipfile_error_code_val, zipfile_error_msg
zipfile_error_code_val = ZIP_ERR_IO
@@ -170,7 +168,7 @@ def zf_read_all(h: wb.HANDLE, p: uint8*, n: sizet) -> int:
return ZIP_ERR_OK
def zf_read_whole(path: str, out_len: rawptr[sizet]) -> uint8*:
def zf_read_whole(path: str, out_len: sizet*) -> uint8*:
if not out_len:
zipfile_set_error(ZIP_ERR_OPEN, "out_len is None")
return None
@@ -181,7 +179,7 @@ def zf_read_whole(path: str, out_len: rawptr[sizet]) -> uint8*:
zipfile_set_error_win(ZIP_ERR_OPEN, "cannot open file for reading", wb.GetLastError())
return None
li: wb.LARGE_INTEGER = wb.LARGE_INTEGER()
ok_size: int = wf.GetFileSizeEx(h, t.CPtr(c.Addr(li)))
ok_size: int = wf.GetFileSizeEx(h, &li)
if ok_size == 0:
wb.CloseHandle(h)
zipfile_set_error(ZIP_ERR_IO, "cannot get file size")
@@ -208,17 +206,17 @@ def zf_read_whole(path: str, out_len: rawptr[sizet]) -> uint8*:
# ============================================================
# 条目信息(目录项)
# 注意: 节点为显式 calloc 分配
# 由 ZipFile 负责释放——避免 GC 实例经 | t.CPtr 联合字段引用被回收。
# 由 ZipFile 负责释放——避免 GC 实例经 Ptr 字段引用被回收。
# ============================================================
class ZipInfo:
filename: bytes # 原始字节名(含 \0,zipfile 持有并负责释放)
name_len: sizet
compress_type: int # ZIP_STORED / ZIP_DEFLATED
crc32: uint32
filename: bytes # 原始字节名(含 \0,zipfile 持有并负责释放)
name_len: sizet
compress_type: int # ZIP_STORED / ZIP_DEFLATED
crc32: uint32
compress_size: sizet
file_size: sizet
file_size: sizet
header_offset: sizet # 本地文件头偏移
next: rawptr[ZipInfo] # 链表(保持写入/目录顺序)
next: ZipInfo* # 链表(保持写入/目录顺序)
# ============================================================
@@ -231,8 +229,8 @@ class ZipFile:
fh: wb.HANDLE = None # 写模式句柄(裸 win32 CreateFileA)
data: bytes = None # 读模式:整个归档的内存副本
data_len: sizet = 0
info_head: rawptr[ZipInfo] = None
info_tail: rawptr[ZipInfo] = None
info_head: ZipInfo* = None
info_tail: ZipInfo* = None
info_count: sizet = 0
pos: sizet = 0 # 写模式当前偏移
ok: int = 0 # 1 = 可正常使用
@@ -273,12 +271,12 @@ class ZipFile:
self.ok = 1
def _clear_infos(self):
n: rawptr[ZipInfo] = self.info_head
n: ZipInfo* = self.info_head
while n is not None:
if n.filename is not None:
stdlib.free(n.filename)
n.filename = None
nxt: rawptr[ZipInfo] = n.next
nxt: ZipInfo* = n.next
n.next = None
stdlib.free(n)
n = nxt
@@ -286,8 +284,8 @@ class ZipFile:
self.info_tail = None
self.info_count = 0
def _append_info(self) -> rawptr[ZipInfo]:
node: rawptr[ZipInfo] = stdlib.calloc(1, ZipInfo.__sizeof__())
def _append_info(self) -> ZipInfo*:
node: ZipInfo* = stdlib.calloc(1, ZipInfo.__sizeof__())
if not node:
zipfile_set_error(ZIP_ERR_MEMORY, "out of memory")
return None
@@ -360,7 +358,7 @@ class ZipFile:
if not dup:
zipfile_set_error(ZIP_ERR_MEMORY, "out of memory")
return ZIP_ERR_MEMORY
node: rawptr[ZipInfo] = self._append_info()
node: ZipInfo* = self._append_info()
if node is None:
stdlib.free(dup)
return ZIP_ERR_MEMORY
@@ -379,7 +377,7 @@ class ZipFile:
def namelist_at(self, i: sizet) -> bytes:
if self.ok == 0 or self.info_count == 0 or i >= self.info_count:
return None
n: rawptr[ZipInfo] = self.info_head
n: ZipInfo* = self.info_head
k: sizet = 0
while n is not None:
if k == i:
@@ -388,10 +386,10 @@ class ZipFile:
k += 1
return None
def getinfo(self, name: str) -> rawptr[ZipInfo]:
def getinfo(self, name: str) -> ZipInfo*:
if self.ok == 0:
return None
n: rawptr[ZipInfo] = self.info_head
n: ZipInfo* = self.info_head
while n is not None:
if n.filename is not None and string.strcmp(n.filename, name) == 0:
return n
@@ -410,7 +408,7 @@ class ZipFile:
if self.mode != 0:
zipfile_set_error(ZIP_ERR_MODE, "zip file is not open for reading")
return None
info: rawptr[ZipInfo] = self.getinfo(name)
info: ZipInfo* = self.getinfo(name)
if info is None:
zipfile_set_error(ZIP_ERR_NOT_FOUND, "member not found")
return None
@@ -540,7 +538,7 @@ class ZipFile:
if not dup:
zipfile_set_error(ZIP_ERR_MEMORY, "out of memory")
return ZIP_ERR_MEMORY
node: rawptr[ZipInfo] = self._append_info()
node: ZipInfo* = self._append_info()
if node is None:
stdlib.free(dup)
return ZIP_ERR_MEMORY
@@ -564,7 +562,7 @@ class ZipFile:
zipfile_set_error(ZIP_ERR_MEMORY, "out of memory")
return ZIP_ERR_MEMORY
rc: int = ZIP_ERR_OK
n: rawptr[ZipInfo] = self.info_head
n: ZipInfo* = self.info_head
while n is not None and rc == ZIP_ERR_OK:
string.memset(hdr, 0, 46)
zf_w32le(hdr, 0x02014B50)