我正在编写一个与 mingw 一起使用的包装层,它为应用程序提供虚拟 UTF-8 环境。处理文件名的函数是从 UTF-8 转换并调用相应的“_w”函数的包装器,依此类推。我遇到的最大问题是 Windowswchar_t
是 16 位的。
对于文件系统操作,这没什么大不了的。我可以在 UTF-8 和 UTF-16 之间来回转换,一切正常。但是标准的 C 多字节/宽字符转换 API 不允许多 wchar_t 字符。
可能的解决方案:
- 提供 CESU-8 环境而不是 UTF-8。我真的不喜欢这个。
- 采取简单的方法,只支持 BMP。将长度为 4 的 UTF-8 序列视为无效。
- 扩展包装以替换 mingw's
wchar_t
和typedef int32_t wchar_t;
处理WCHAR
和wchar_t
不同。这很痛苦,但它可能是移植需要干净 POSIX 类型环境且不wchar_t
用于任何 Windows-API 目的的应用程序的理想选择。 - 以下黑客:
mbrtowc
wchar_t
读取一个 4 字节 UTF-8 字符的前 3 个字节后,输出对应于高代理的 a,并将剩余状态保留在mbstate_t
对象中。在接收到下一个字节后,它将其与保存的状态结合以输出低代理。如果最后一个字节最终无效,则返回 -1(使用 EILSEQ),并且在输出流中会出现一个单独的代理项(坏...)。
wcrtomb
在处理高位代理时输出 UTF-8 的前 2 个字节,并将剩余状态保存在其mbstate_t
对象中。当它随后处理低代理时,它将其与保存的状态相结合以输出 UTF-8 的最后 2 个字节。如果未接收到有效的低代理,则返回 -1(使用 EILSEQ),并且输出流中会出现不完整的 UTF-8 序列(坏...)。
这个 hack 的好处是只要输入有效,它就可以工作,并允许访问任何 UTF-8 字符,从而访问任何可能的文件名/参数/等。应用程序可能需要使用的文本。
缺点是它不严格符合 ISO C(wchar_t
字符串不允许有状态),并且它延迟了对畸形字符的检测,直到已经写入了不正确的部分输出。
我正在寻找有关不同选项的反馈,尤其是我提出的 hack:它是否合理,缺点是否可能导致严重错误,以及是否还有其他我尚未考虑的缺点可能会阻止该计划完全工作。我也很高兴听到我没有想到的任何其他可能的解决方案。