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.cmojibake.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 枚举,调用者可以区分成功、参数无效、内存失败以及溢出等情况。


最小集成步骤

  1. 下载合并包mojibake-amalgamation-027.zip 包含 mojibake.cmojibake.h
  2. 将文件添加到项目源码树中。
  3. 在需要 Unicode 处理的地方包含头文件:
    #include "mojibake.h"
    
  4. 使用任意 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.txtIdentifierStatus.txt)。


测试、模糊测试与符合性保证

Mojibake 已针对每个受支持算法通过官方 Unicode 测试套件进行验证。项目使用 Attractor 测试框架执行 150 万+ 断言,包括:

  • 完整的 Unicode 正规化测试向量。
  • 双向算法符合性。
  • 排序测试数据。
  • 表情符号序列校验。

此外,库持续使用 libFuzzer 进行模糊测试,所有构建均在 AddressSanitizerUBSan 下运行,以捕获内存安全问题。


社区反馈(精选 HN 评论)

"喜欢这种合并方式——C/C++ 生态迫切需要更干净、轻量的 Unicode 支持,而不必引入巨大的依赖……感谢分享" – @digg99

该评论强调了单文件库对无法承担重量级依赖的项目的实际价值。

"我得出结论,C 中唯一需要的 Unicode 支持就是对 char 指针和数组的支持,但轻量的 C 库总是受欢迎的" – @avadodin

提醒我们,即使是最基本的 Unicode 处理(例如正确的长度计数、大小写折叠)也往往需要超出原始字节数组的功能;Mojibake 正好填补了这一空白。

"不是挑刺,但‘mojibake’这个词不就是‘字符编码破裂’的同义词吗?" – @CharlesW

库名有意引用了乱码的经典问题,同时提供防止此类问题的工具。


许可证与法律声明

Mojibake 在 MIT 许可证 下发布。它包含 Unicode 字符数据库和 CLDR 数据,这些数据保留原始的 Unicode 许可证(见 license.txt 与 CLDR LICENSE)。


入门指南

  1. 下载最新发布(v0.2.7)自 GitHub Release 页面。
  2. 阅读 API 参考API.md)以获取详细的函数签名。
  3. 运行 CLIsrc/shell/mojibake)进行快速实验,例如:
    mojibake nfc $'Cafe\u0301'   # → NFC: Café
    mojibake emoji "☺️"        # → 显示表情符号分类
    
  4. 贡献代码 – 参见 CONTRIBUTING.md,了解添加新 Unicode 版本或修复 bug 的指南。

结论

Mojibake 0.2.7 在一个小巧、无依赖的包中提供了完整、符合标准的 Unicode 17 实现。其单文件分发、丰富的功能集以及严格的测试,使其成为任何需要可靠 Unicode 处理而不想承担大型库负担的 C 或 C++ 项目的有力选择。

Sources