扩展库 / toml
toml
解析和生成 TOML,支持 UTF-8 文件、资源配额和四种日期时间值。
版本 1.0.0 · C / xlang · 依赖 _tomlc17
快速开始
import toml
var config = toml.parse("title = \"demo\"\n")
config["released"] = toml.localDate(2026, 7, 16)
string text = toml.stringify(config)
assert toml.dateTimeKind(toml.parse(text)["released"]) == 1
解析结果是可在 C 和 xlang 两侧访问的 XRT 值。根文档写出时必须是字典;文件入口为 load(path) 与 save(path, value)。
解析语法以 TOML 1.0 为目标:内联表不可跨行或带尾逗号,时间须写秒,Unicode 键须加引号;不接受 \xNN 或 \e 转义。
接口
| 入口 | 用途 |
|---|---|
parse / load | 从文本或 UTF-8 路径读入 TOML,返回 var 字典。 |
stringify / save | 写出文本或原子保存文件;拒绝无效 UTF-8 键和值。 |
localDate / localTime | 创建无时区的日期或时间值。 |
localDateTime / offsetDateTime | 创建本地或带偏移的日期时间。 |
dateTimeKind / isLocalDate / isLocalTime / isLocalDateTime / isOffsetDateTime | 判断时间类型。 |
dateTimePart(value, part) / dateTimeText(value) | 读取时间分量或 TOML 文本表示;part 为 0..7。 |
errorCode / errorLine / errorColumn / errorOffset | 查询当前线程最近的 TOML 错误位置;非法 UTF-8 定位首个错误字节,其他语法错误的列号取决于底层解析器。 |
解析与写出可限制输入、输出、单项、条目、节点和深度;参数 0 使用 XRT 默认值,负数不合法。C 端传入选项结构时须先调用 xrtTomlOptionsInit;结构本身或内嵌资源限额的版本、长度无效会报 ARGUMENT,不会回退到默认限额。深度限额与日期参数进入 C ABI 前进行范围检查,路径不接受内嵌 NUL。日期记录、可变日期对象与格式化共用校验,无效日历值或与类型无关的隐藏字段不会被当成合法日期输出。语法/参数错误为 ValueError,限额为 RangeError,真正的文件或流 IO 失败为 IOError;解析、写出和原子保存过程中的分配失败均报告 MemoryError。
C 选项中内嵌资源限额的保留字段必须为零;非零配置在解析与写出前报告 ARGUMENT。TOML 不使用压缩倍率或资源标志:OptionsInit 将倍率置零,显式设置 iMaxCompressionRatio 或 iFlags 同样报 ARGUMENT,不会静默忽略。
parse(string) 直接传递 UTF-8 数据及字节长度,不另建 XLang Buffer 副本。Reader 同时支持总长度与当前位置查询时,按剩余字节数在读取前拒绝超限;其他 Reader 仍受限额读取约束。正文或注释中的内嵌 NUL 均作为格式错误拒绝。
maxItem 按键和字符串原始 UTF-8 字节数计算,maxEntries 限制每个数组和表,maxNodes/maxDepth 也计入数组表的数组节点。解析和写出使用同一限额口径;刚好到上限可用,超限时 save 不覆盖旧文件。
日期时间支持 6 位秒小数(微秒)。按 TOML 规范,更多小数位会截断而非四舍五入;再次写出只保留微秒,不能用来无损保存纳秒。
年份统一为 0000..9999,依据 TOML 1.0 四位年份语法和 RFC 3339。年份 0000 按公历闰年规则处理。普通 XRT time 写为 UTC;超出范围时 C 报 FORMAT,XLang 抛 ValueError,不输出负年或五位年份。
C 流接口仅关闭自身拥有的 reader/writer。正文失败时同时保留私有错误码和原 XRT 原因对象,不受关闭成功清空错误槽或关闭失败覆盖的影响;可选错误输出为空时同样适用。正文成功但拥有流关闭失败则报告该关闭失败。
日期时间值由本包构造函数创建,以 XRT TypeId 区分于普通表;字段碰巧与日期记录同形的 TOML 表仍按表写回,不会变成日期。深拷贝保留日期身份。
普通有限浮点字面量若溢出 float64,本包报格式错误,不静默转为无穷大;显式 inf/nan 仍可解析。这是本包的数值边界,并非要求所有 TOML 实现采用同一溢出策略。
C 对照
#include "xrt_toml.h"
int main(void)
{
xrttomlerror error;
const char source[] = "title = \"demo\"\n";
xvalue* value = xrtTomlParseMemory(source, sizeof(source) - 1u, NULL, &error);
if (value == NULL) return 1;
/* 使用 xrtValueObjectGet 等 XRT 接口读取,完成后释放。 */
xrtValueRelease(value);
return 0;
}
公共头为 extlibs/toml/include/xrt_toml.h。xrtTomlParseMemory 返回拥有型 xvalue;xrtTomlStringify 返回拥有型 xbuffer。完整可运行的双语范例为 examples/extlibs/toml.xl 与 examples/extlibs/toml_c.c;两者构造四种日期时间值并检查微秒与偏移。传入目标路径时,使用 TOML 的 save/load 完成文件往返,并由 Python tomllib 独立解析结果。
验证状态
powershell -NoProfile -ExecutionPolicy Bypass -File release/extlibs/toml/test/check.ps1
bash release/extlibs/toml/test/check.sh
命令从仓库根目录执行,不带原 demo6 前缀;需要 GCC 和 Python 3.11+,可用 CC/PYTHON 指定路径。缺工具为真实失败。生产十二模块的独立 XRT/原生桥接构建验证实际依赖,测试运行库另加内存调试、路径和值图三模块。Windows 使用严格 GCC,Linux 增加 C ASan/UBSan/泄漏检查;两平台保留输入指纹及失败日志,不修改主线或 XRT。
2026-10-30:新增 288 项流所有权/正文与关闭故障/日历边界及八条逐点 OOM 路径,原实现 136 项失败,修复后归零;这是组合失败数而不是独立缺陷数。四个冷启动预算各由全新进程执行并立即恢复。520 条确定性 UTC 微秒记录由 Python datetime/tomllib 独立核对,并比较 GCC、TCC 内存运行和独立程序文本;Python 参照只覆盖 0001..9999,年份 0000 由单独 C/XLang 测试覆盖。全部十六条实际 cgen 原型、六个独立程序与双语日历黄金范例也进入默认门禁。
当前整包仍为 M:原生 parse 返回的配置可写回,但原语言字典正例传入 stringify(var) 仍报 TypeError: TOML document root must be a dict,共享 foreign var 投影阻断 M1 未解除。门禁先验证可运行路径,最后仍强制执行原字典/完整语言/双语文件正例,不能把前者当作整包通过。当前 Windows 预验到最后原中央字典才失败;最终双平台证据见仓库验收矩阵。旧缺符号记录仅描述当时产物;本页源已更新,不代表外部网站已经部署。
新增 extlibs/toml/examples/calendar_guard.xl 与 calendar_guard_c.c 从已有配置更新时间,验证微秒、年份两端、四类越界拒绝和恢复;五行共同黄金输出,不访问文件。原中央 C/XLang 文件互通仍保留且受 M1 阻断,不用新范例替代。
NUL 路径边界用例使用独占系统临时目录并在失败或成功时清理,不覆盖固定 build/test 文件。2026-10-20 Windows 聚焦门禁和 Linux C ASan/UBSan、XLang、tomllib 对照复跑通过;完整 AOT 的共享阻断不变。
2026-10-21:C 原子保存和流写入的分配失败回归先复现错误被标为 IO,修复后均保持内存错误分类;XLang 对 parse/stringify/load/save 逐点注入并验证恢复。Windows 聚焦门禁、Linux C ASan/UBSan、XLang 与 tomllib 对照通过;完整 AOT 仍未签收。
可选的 TOML 1.0 上游语料审计同时比较官方预期 JSON、Python tomllib 解析原文,以及本包写回后的解析值;固定语料 208 个合法与 501 个非法文件的接受结果、合法文件的可观察类型和值均一致。这不是内部 xvalue 每个节点的直接检查,也不替代 C/XLang 包级门禁。