开发者发布Mojibake:基于C的底层Unicode库
速览
Mojibake是一个用C实现的底层Unicode库,提供低级别文本编码转换功能。该库针对性能优化,适合嵌入系统或对资源敏感的场景。它为开发者提供了更灵活的字符处理方案,有助于在多语言环境下简化编码问题。
AI 深度解读
背景
在软件开发中,Unicode 处理是一个常见但复杂的任务。无论是文本规范化、大小写转换、字符分割还是排序比较,都需要对 Unicode 标准有深入的理解和实现。现有的 Unicode 库(如 ICU、libunistring 等)功能强大但往往体积庞大、依赖较多,对于嵌入式或对二进制大小敏感的项目不够友好。Mojibake 正是为了解决这一问题而诞生的:一个用 C11 编写、兼容 C++17 的底层 Unicode 17 文本处理库,遵循 MIT 许可证,力求小巧、易用、快速且自包含。
核心内容
Mojibake 是一个低层级(low-level)的 Unicode 文本处理库,仅需两个文件(mojibake.c 和 mojibake.h)即可集成到 C/C++ 项目中,零依赖。它实现了 Unicode 17.0.0 标准所规定的全部算法,并通过官方测试套件。
使用方法
无需安装,只需将头文件和源文件添加到项目中。以下是示例代码演示了三种功能:
- 规范化(Normalization):将 "Cafe\xCC\x81"(即 "Cafe" 后跟一个 U+0301 COMBINING ACUTE ACCENT)通过 NFC 规范化为 "Café"(U+00E9),输出如下:
Cafe<CC><81> Caf<C3><A9> - 字符计数:对字符串 "文字化け"(UTF-8 长度 12 字节)使用
mjb_string_length得到正确的字符数 4。 - NFKC Casefold:将 "Straße" 通过 NFKC casefold 转换为 "strasse"(ß → ss),输出:
Straße -> strasse
功能亮点
所有 C 文件与 Unicode 数据表合并为一个大文件(mojibake.c 和 mojibake.h),零外部依赖。
文本转换
- 规范化:NFC/NFD/NFKC/NFKD(
mjb_normalize),面向标识符的 NFKC case folding(mjb_nfkc_casefold),以及快速 quick-check(mjb_string_is_normalized)。遵循 UAX #15,Unicode 17.0.0。 - 大小写转换:大写、小写、标题大小写、case folding,支持完整的特殊大小写和条件映射(
mjb_case)。 - 过滤:在规范化的同时去除控制字符、空格或数字(
mjb_string_filter)。
文本分析
- 字符数据库:获取每个 Unicode 字符的 UCD 属性:类别(category)、文字(script)与脚本扩展(Script_Extensions)、区块(block)、平面(plane)、数值、名称(
mjb_codepoint_character、mjb_codepoint_script_extensions)。 - 分割:字素簇(grapheme clusters)、单词、句子、断行机会(UAX #29 和 UAX #14,Unicode 17.0.0)。
- 双向文本:完整 Unicode 双向算法:段落解析、行重排序、运行(run)(UAX #9,Unicode 17.0.0)。
- Emoji:码点属性、序列分析、RGI emoji 检测。
- 显示宽度:东亚宽度和终端显示宽度,支持宽度感知截断(
mjb_display_width、mjb_truncate_width)。
排序与比较
- 排序(Collation):Unicode Collation Algorithm(UCA)字符串比较和排序键,支持 shifted 和 non-ignorable 模式(
mjb_string_compare、mjb_collation_key,UTS #10,Unicode 17.0.0)。
安全
- 混淆检测:生成可复用的骨架(skeleton)并检查字符串是否视觉混淆(
mjb_confusable_skeleton、mjb_string_is_confusable,UTS #39,Unicode 17.0.0)。 - 标识符验证:XID/ID 检查,面向解析器和编译器作者(
mjb_string_is_identifier,UAX #31,Unicode 17.0.0)。
集成
- 编码:API 接受并输出 UTF-8、UTF-16LE、UTF-16BE、UTF-32LE、UTF-32BE 字符串,具有编码检测和转换功能(
mjb_string_encoding、mjb_string_convert_encoding)。 - 解析与字符串函数:逐字符迭代(
mjb_next_character)和标准<string.h>风格的辅助函数(mjb_string_length等)。 - 区域设置:严格的 BCP 47 语言标签解析(
mjb_locale_parse)。 - 可嵌入性:自定义分配器(
mjb_set_memory_functions)、编译时功能标志以缩减数据表大小、C++17 包装器(src/cpp/mojibake.hpp)、CLI 工具(src/shell)、WASM + TypeScript API(src/api)。 - 测试与模糊测试:使用 Attractor 测试套件运行超过 150 万条断言,涵盖官方 Unicode 一致性测试;使用 libFuzzer 对不可信字节输入进行模糊测试,并且通过了 AddressSanitizer 和 UBSan 检测。
编译时特性
Mojibake 可以通过宏控制编译哪些可选特性表,以减小二进制体积。例如,#define MJB_FEATURE_CHARACTER_NAMES 控制字符名称表,禁用后输出大小减少约 30%,字符名称会显示为 "Codepoint U+XXXX"。可通过 CMake 或 Makefile 设置。
CLI 工具
src/shell 目录编译出 mojibake 命令行工具,用于测试。示例:
# 输出 "NFC: Café"
mojibake nfc $'Cafe\u0301'
# 输出 emoji 序列信息
mojibake emoji "☺️"
许可
MIT 许可证。Unicode 字符数据库和 CLDR 数据版权归 Unicode, Inc. 所有。
关键要点
- 完全符合 Unicode 17.0.0:实现了 UAX #9、#14、#15、#29、#31,UTS #10、#39 等标准中的所有算法,并通过官方测试套件。
- 零依赖自包含:仅两个文件(
mojibake.c和mojibake.h),所有 Unicode 数据表已整合,无需外部库或数据文件。 - 跨平台:支持 Linux、macOS、FreeBSD、OpenBSD、NetBSD、Windows 10/11。
- 多种编码支持:原生支持 UTF-8、UTF-16LE/BE、UTF-32LE/BE,并包含编码检测和转换。
- 功能全面:覆盖规范化、大小写转换、字符属性查询、文本分割、双向文本、Emoji 检测、显示宽度、排序、混淆检测、标识符验证等常见 Unicode 处理需求。
- 可定制体积:通过编译时宏可以禁用可选特性(如字符名称表),以减小二进制大小,适合资源受限环境。
- 安全可靠:经过模糊测试、AddressSanitizer 和 UBSan 清理,并运行 150 万+ 断言。
- 易于集成:提供 C 直接使用、C++17 包装器、CLI 工具以及 WASM + TypeScript API,满足多种使用场景。
- 自定义分配器:可通过
mjb_set_memory_functions控制内存管理,适合嵌入式和性能关键应用。
意义与影响
Mojibake 的出现填补了现有 Unicode 处理库的两个空白:一方面,它比 ICU 等项目更轻量、更易于集成,适合那些不希望引入庞大依赖的 C/C++ 项目;另一方面,它保持了与 Unicode 标准的严格一致性,避免了民间实现中
