我正在编写一个与mingw一起使用的包装层,它为应用程序提供了一个虚拟的UTF-8环境。处理文件名的函数是包装器,它们从UTF-8转换并调用相应的“_w”函数,依此类推。我遇到的一个大问题是Windows wchar_t
是16位。
对于文件系统操作,这不是什么大问题。我可以在UTF-8和UTF-16之间来回转换,一切都会起作用。但标准的C多字节/宽字符转换API不允许使用多个wchar_t字符。
可能的解决方案:
wchar_t
替换为typedef int32_t wchar_t;
并处理WCHAR
和wchar_t
不同。这很痛苦,但它可能非常适合移植期望清晰POSIX类型环境的应用程序,并且不会将wchar_t
用于任何Windows-API目的。 mbrtowc
输出对应于高代理的wchar_t
,并将剩余状态保留在mbstate_t
对象中。在接收到下一个字节时,它将其与保存的状态组合以输出低代理。如果最后一个字节最终无效,则返回-1(使用EILSEQ)并且单个代理在输出流中结束(错误...)。
wcrtomb
在处理高代理时输出UTF-8的前2个字节,并将剩余状态保存在其mbstate_t
对象中。当它随后处理低代理时,它将其与保存状态组合以输出UTF-8的最后2个字节。如果未收到有效的低代理项,则返回-1(使用EILSEQ),并且不完整的UTF-8序列在输出流中结束(错误...)。
这个hack的优点是只要输入有效就可以工作,并且允许访问任何UTF-8字符,从而允许访问任何可能的文件名/参数/等。应用程序可能需要使用的文本。
缺点是它不严格符合ISO C(wchar_t
字符串不允许有状态)并且它会延迟检测格式错误的字符,直到已经写入错误的部分输出。
我正在寻找有关不同选项的反馈,特别是我提出的黑客攻击:是否合理,缺点是否可能导致严重错误,以及是否还有其他缺点我尚未考虑哪些可能会保留该计划完全从事。我也很高兴听到其他任何我没有想到的解决方案。
答案 0 :(得分:1)
我会做类似#4的事情,但在你确定输入有效之前不要生成任何输出。
mbrtowc
应解码整个角色。如果它在BMP之外,则输出高代理并将低代理存储在mbstate_t
中。wcrtomb
应该在mbstate_t
中存储高代理,如果该字符有效,则输出所有4个UTF-8字节。答案 1 :(得分:0)
如果你在Windows上,使用MultiByteToWideChar和WideCharToMultiByte一次在UTF-16和UTF-8之间转换整个字符串。
虽然GCC中的默认模式是32位wchar_t,但是有一些编译开关会改变它,更常见的是c& c ++规范没有指定wchar_t的大小 - 实际上wchar_t的大小可以与char相同。
如果您想避免使用Windows API(在Windows包装器代码中!?),请使用mbstowcs一次转换整个字符串。