Mojibake 0.2.7 – 零依赖的 Unicode 17 库(适用于 C11/C++17)
Mojibake 0.2.7 – 零依赖的 Unicode 17 库(适用于 C11/C++17)
Mojibake 0.2.7 在单文件 C 库中提供完整的 Unicode 17 支持
Mojibake 0.2.7 实现了完整的 Unicode 17.0.0 规范——包括正规化、大小写折叠、分段、双向布局、表情符号处理、排序以及安全检查——且不依赖任何外部库,无需运行时。这使得它非常适合那些无法承担重量级库的底层项目。
为什么零依赖的 Unicode 库很重要
大多数 C/C++ 项目依赖大型第三方 Unicode 库(例如 ICU),这些库会引入庞大的代码库、复杂的构建系统以及运行时数据表。Mojibake 通过将所有源代码和 Unicode 数据表合并到两个文件(mojibake.c 和 mojibake.h)来规避这些问题。其结果是一个单头文件/实现文件,可以直接放入任何项目,使用任意 C11 或 C++17 编译器编译,并且无需额外的库链接。
核心功能一览
| 功能 | API 函数 | 标准参考 |
|---|---|---|
| 正规化(NFC、NFD、NFKC、NFKD) | mjb_normalize, mjb_string_is_normalized |
UAX #15 |
| 大小写折叠与转换(大写、小写、标题、NFKC 大小写折叠) | mjb_case, mjb_nfkc_casefold |
UAX #31, UAX #15 |
| 分段(字符簇、单词、句子、换行) | mjb_break_grapheme_cluster, mjb_break_word, mjb_break_sentence, mjb_break_line |
UAX #29, UAX #14 |
| 双向算法(段落解析、行重新排序) | mjb_bidi_resolve, mjb_bidi_reorder_line |
UAX #9 |
| 表情符号分析(属性、序列检测、RGI 检查) | mjb_string_emoji_sequence, mjb_string_is_rgi_emoji |
UTS #51 |
| 排序(UCA 比较、排序键生成) | mjb_string_compare, mjb_collation_key |
UTS #10 |
| 安全(混淆字符检测、标识符校验) | mjb_confusable_skeleton, mjb_string_is_confusable, mjb_string_is_identifier |
UTS #39, UAX #31 |
| 编码转换(UTF‑8、UTF‑16LE/BE、UTF‑32LE/BE) | mjb_string_convert_encoding, mjb_string_encoding |
— |
| 显示宽度与截断(终端列宽、宽度感知截断) | mjb_display_width, mjb_truncate_width |
UAX #11 |
所有函数均返回详细的 mjb_status 枚举,调用者可以区分成功、参数无效、内存失败以及溢出等情况。
最小集成步骤
- 下载合并包 –
mojibake-amalgamation-027.zip包含mojibake.c和mojibake.h。 - 将文件添加到项目源码树中。
- 在需要 Unicode 处理的地方包含头文件:
#include "mojibake.h" - 使用任意 C11 或 C++17 编译器编译;不需要链接器选项。
由于库没有运行时,你也可以将其嵌入静态库、固件或 WebAssembly 模块中,而无需额外的二进制文件。
性能考量(社区提问)
"它和 utf8proc 的比较如何?" – @lifthrasiir
Mojibake 提供的功能比 utf8proc 更广(后者仅关注 UTF‑8 验证、正规化和大小写折叠)。它还加入了完整的双向处理、Unicode 排序、表情符号序列检测以及面向安全的混淆字符检查。作者尚未公布基准数据,直接的速度比较仍属轶事。
"与 Python 的 ftfy 模块相比性能如何?" – @tjwebbnorfolk
ftfy 是一个高级 Python 库,专门对损坏的 Unicode 进行大量错误修正。Mojibake 工作在更低层,提供原始算法而不自动修复错误。因此,原始吞吐量可能更高,但源码中未提供并排基准。
面向尺寸受限环境的构建时特性开关
Mojibake 允许在编译时排除可选表,以减小二进制体积。例如,关闭字符名称可将数据占用减少约 30 %:
# CMake
cmake -S . -B build-no-name -DMJB_FEATURE_CHARACTER_NAMES=OFF
cmake --build build-no-name
# Makefile 快捷方式
make build BUILD_DIR=build-no-name FEATURE_CHARACTER_NAMES=OFF
其他表(如表情符号属性、脚本扩展)也可以通过 MJB_FEATURE_* 宏进行裁剪。
面向安全的实用工具
- 混淆字符检测 –
mjb_confusable_skeleton构建语言无关的骨架;mjb_string_is_confusable比较两个字符串的视觉相似度,以防止同形攻击。 - 标识符校验 –
mjb_string_is_identifier强制执行 Unicode 标识符规则(ID_Start/ID_Continue 或 XID 变体),适用于编译器和解释器。
这两个工具均依赖官方 Unicode 安全数据文件(confusables.txt、IdentifierStatus.txt)。
测试、模糊测试与符合性保证
Mojibake 已针对每个受支持算法通过官方 Unicode 测试套件进行验证。项目使用 Attractor 测试框架执行 150 万+ 断言,包括:
- 完整的 Unicode 正规化测试向量。
- 双向算法符合性。
- 排序测试数据。
- 表情符号序列校验。
此外,库持续使用 libFuzzer 进行模糊测试,所有构建均在 AddressSanitizer 和 UBSan 下运行,以捕获内存安全问题。
社区反馈(精选 HN 评论)
"喜欢这种合并方式——C/C++ 生态迫切需要更干净、轻量的 Unicode 支持,而不必引入巨大的依赖……感谢分享" – @digg99
该评论强调了单文件库对无法承担重量级依赖的项目的实际价值。
"我得出结论,C 中唯一需要的 Unicode 支持就是对 char 指针和数组的支持,但轻量的 C 库总是受欢迎的" – @avadodin
提醒我们,即使是最基本的 Unicode 处理(例如正确的长度计数、大小写折叠)也往往需要超出原始字节数组的功能;Mojibake 正好填补了这一空白。
"不是挑刺,但‘mojibake’这个词不就是‘字符编码破裂’的同义词吗?" – @CharlesW
库名有意引用了乱码的经典问题,同时提供防止此类问题的工具。
许可证与法律声明
Mojibake 在 MIT 许可证 下发布。它包含 Unicode 字符数据库和 CLDR 数据,这些数据保留原始的 Unicode 许可证(见 license.txt 与 CLDR LICENSE)。
入门指南
- 下载最新发布(v0.2.7)自 GitHub Release 页面。
- 阅读 API 参考(
API.md)以获取详细的函数签名。 - 运行 CLI(
src/shell/mojibake)进行快速实验,例如:mojibake nfc $'Cafe\u0301' # → NFC: Café mojibake emoji "☺️" # → 显示表情符号分类 - 贡献代码 – 参见
CONTRIBUTING.md,了解添加新 Unicode 版本或修复 bug 的指南。
结论
Mojibake 0.2.7 在一个小巧、无依赖的包中提供了完整、符合标准的 Unicode 17 实现。其单文件分发、丰富的功能集以及严格的测试,使其成为任何需要可靠 Unicode 处理而不想承担大型库负担的 C 或 C++ 项目的有力选择。