deflateSetDictionary
将预置字节载入压缩历史,不把它们作为输入数据输出。
完整章节与共同规则 ↗39ab1ace4bbe0b0e · 对应提交的原文 ↗先看本函数的前置条件和返回结果;可展开下方共同规则,查看整组接口的缓冲区与所有权要求。
int ZEXPORT deflateSetDictionary(z_streamp strm, const Bytef *dictionary, uInt dictLength);
将预置字节载入压缩历史,不把它们作为输入数据输出。
dictLength 是整个给定字典的字节数,w_size 是配置的历史窗口字节数;过长字典只把可用后缀留作历史,但 zlib 的字典标识仍覆盖整个给定字典。
定义域 受限定义域。影响: 更新历史和字典校验和。
前置条件 有效 raw 或 zlib 流,紧接初始化或 deflateReset,在第一次 deflate 和第一次字典调用之前。dictionary 非 NULL,覆盖 dictLength 个可读字节,且与窗口分离。
返回与保证 返回 Z_OK。历史保留字典的可用后缀,最多一个窗口。zlib 的字典校验和覆盖整个给定字典。原 next_in 和 avail_in 被恢复;total_in 增加 min(dictLength, w_size)。不交付压缩输出,也不分配。需要字典时,必须向解码器提供相同的预置字典。
聚焦范围之外: gzip、NULL 字典、已离开初始状态的 zlib、非零预读字节数,或不在已完成块边界的 raw 输入,均返回 Z_STREAM_ERROR,不发生变化。合法边界处的 raw 替换,以及开始前多次调用 zlib 字典设置,仍在公开目标内。重复 zlib 调用会累积 Adler-32,而不是重新开始计算。
本组共同前提与范围
输入分批到达、输出空间有限,或需要选择封装、字典、刷新边界时,使用 z_stream 压缩器。封装是在 DEFLATE 压缩数据之外增加的头部、尾部和完整性信息;raw DEFLATE 则不带这些封装。初始化一次,使用连续的缓冲区调用 deflate,即使放弃压缩也要结束流。单个缓冲区的操作见 compress 和 compress2。
| 任务 | 条目 |
|---|---|
| 开始或复用 | 初始化、配置初始化、重置、保留历史的重置 |
| 提供元数据或历史 | 字典、读取历史、gzip 头 |
| 压缩与输出大小 | 压缩、上界、待输出数据、最近刷新位数 |
| 调整或分支 | 参数、调优、位预置、复制 |
| 释放存储 | 结束 |
这些聚焦契约遵循固定版本的 deflate.c、已应用补丁和 zlib.h,采用默认 LP64 Linux 构建。它们不改变范围更广的已登记公开目标。定义域/影响标签见契约约定,证明状态和剩余工作见进度。
共享约定
在每条所述前置条件下,都要求执行无运行时故障地终止,并满足所述后置条件。调用若保留有效流,就保持其表示不变量。
先看一次调用的数据交接。next_in 指向本轮尚未读取的输入起点,avail_in 是从这里开始可读的字节数;next_out 指向本轮下一个可写位置,avail_out 是剩余输出容量,也以字节计。一次调用可以只消耗部分输入、只交付部分输出。调用者应读取更新后的指针和计数,接走已交付字节,再为同一个流补充输入或输出空间。
- 有效流: 可写的
z_stream,其压缩器状态由成功初始化或复制建立,经过合法调用保持,且尚未结束。调用者不改变其内部状态或分配器字段。同一个流的调用按顺序执行。 - 缓冲区: 输入覆盖
avail_in个可读字节;输出覆盖avail_out个可写字节。它们彼此不重叠,也不与流或流拥有的状态重叠。非 NULL 标量结果指向可写单元,与其他结果及流内存分离。这些分离条件是聚焦契约的显式假设;见 safety.md。 - 分配器: 使用默认分配/释放函数对,或在初始化前将两个字段都置为 NULL。任意一次分配尝试都可能失败。自定义分配器回调不在本页范围内。
- 帧性质与所有权: 调用只改变自己的流、其拥有的状态和所述输出区域。调用者输入只读。调用者缓冲区和头部记录仍归调用者所有。只有初始化和复制会分配;只有它们失败时的清理与
deflateEnd会释放内存。其他调用保持流的分配集合。 - 头部生命周期: 保留的 gzip 头及其可选字段在使用期间保持可读且不变。非 NULL 的
name和comment以零终止;extra覆盖所述长度。聚焦格式契约使用extra_len <= 65535。 - 检查后的拒绝: 除初始化和上界查询外,流检查失败会在正常操作之前返回
Z_STREAM_ERROR,不发生写入。deflateCopy还会清空非 NULL 目标的状态。这种拒绝不修改查询输出单元。 - 受限定义域指这些显式内存、生命周期和调用顺序条件,加上条目自身的前置条件。它不意味着接受每个可表示的指针或整数。错误概述覆盖可读、可检查的状态,不覆盖任意无效地址。
形式化约定
ZlibF.Spec.Public.Goal.deflateSetDictionary
证明状态:未完成 · 证明记录与剩余工作
/-- `int deflateSetDictionary(z_streamp strm, const Bytef *dictionary, uInt dictLength)`.
The raw path checks the block boundary. Repeated zlib dictionaries accumulate their checksum.
The temporary input binding is restored, and no allocation is performed. -/
def Goal.deflateSetDictionary : Prop :=
∀ h r i z s source n xs old,
Zlib.Deflate.Spec.DGood h r i z s → LibraryGlobals h →
DeflateDictionary h s old → (source ≠ .null → Bytes h source n.toNat xs) →
Separate source n.toNat s.window s.window_size.toNat →
∃ rc after, C.run (Zlib.Deflate.deflateSetDictionary (some r) source n) h = .ok (rc, after) ∧
(if source = .null ∨ s.wrap = 2 ∨ (s.wrap = 1 ∧ s.status ≠ INIT_STATE) ∨
s.lookahead ≠ 0 ∨ (s.wrap = 0 ∧ s.strstart.toUInt64.toInt64 ≠ s.block_start) then
rc = Z_STREAM_ERROR ∧ after = h
else rc = Z_OK ∧ ∃ z' s' dict,
Zlib.Deflate.Spec.DGood after r i z' s' ∧ DeflateDictionary after s' dict ∧
z' = { z with
total_in := z.total_in + UInt64.ofNat (min xs.length s.w_size.toNat)
adler := if s.wrap = 1 then adlerValue z.adler xs else z.adler } ∧
s'.wrap = s.wrap ∧ s'.lookahead = 0 ∧ s'.block_start = s'.strstart.toUInt64.toInt64 ∧
dict <:+ old ++ xs ∧ dict.length ≤ s.w_size.toNat ∧
min (old.length + xs.length) (s.w_size.toNat - 262) ≤ dict.length) ∧
Frame h after (fun b => StreamRoot r b ∨ DeflateOwned i s b) ∧
LiveChange h after (fun _ => False) (fun _ => False) ∧ after.nalloc = h.nalloc相关定义与源码 ↗