如何最好地处理Windows的16位wchar_t丑陋?

我正在编写一个与mingw一起使用的包装器层,它为应用程序提供了一个虚拟的UTF-8环境。 处理文件名的函数是从UTF-8转换并调用相应的“_w”函数的包装器,依此类推。 我碰到的大问题是Windowswchar_t是16位。

对于文件系统操作,这不是什么大不了的事情。 我可以在UTF-8和UTF-16之间来回转换,而且一切都可以正常工作。 但标准的C多字节/宽字符转换API不允许多个wchar_t字符。

可能的解决scheme:

  1. 提供一个CESU-8环境而不是UTF-8。 我真的不喜欢这个。
  2. 采取简单的方法,只支持BMP。 将长度为4的UTF-8序列视为无效。
  3. 扩展包装器,用typedef int32_t wchar_t;replacemingw的wchar_t typedef int32_t wchar_t; 处理WCHARwchar_t是不一样的。 这是一个痛苦,但它可能是理想的移植应用程序,期望一个干净的POSIXtypes的环境,不要使用wchar_t任何Windows API的目的。
  4. 下面的黑客:

在读取4字节UTF-8字符的前3个字节后, mbrtowc输出对应于高代理的wchar_t ,并将剩余状态保留在mbstate_t对象中。 接收到下一个字节后,将其与保存状态结合,输出低位代理。 如果最后一个字节无效,则返回-1(带有EILSEQ),并且一个单独的代理会在输出stream(坏…)中结束。

wcrtomb在处理高代理时输出UTF-8的前2个字节,并将剩余状态保存在其mbstate_t对象中。 当它随后处理低代理项时,将它与保存的状态结合起来输出UTF-8的最后2个字节。 如果没有收到一个有效的低代理项,它将返回-1(带有EILSEQ),并且一个不完整的UTF-8序列在输出stream(坏…)中结束。

这种攻击的好处在于,只要input有效,它就可以工作,并允许访问任何UTF-8字符,因此可以访问任何可能的文件名/参数等。 文本应用程序可能需要处理。

缺点是它不完全符合ISO C( wchar_tstring不允许为有状态),并且延迟了错误字符的检测,直到错误的部分输出已被写入。

我正在寻求不同选项的反馈意见,特别是我提出的黑客攻击:是否合理,缺点是否可能导致严重错误,以及是否还有其他缺点,我还没有考虑哪些可能使计划完全工作。 我也很高兴听到任何其他可能的解决scheme,我没有想到。

Solutions Collecting From Web of "如何最好地处理Windows的16位wchar_t丑陋?"

我会做类似#4的事情,但是在确定输入有效之前不要产生任何输出。

  • mbrtowc应该解码整个字符。 如果它在BMP之外,则输出高代理并将低代理存储在mbstate_t
  • wcrtomb应该在mbstate_t存储高代理项,如果字符有效,则输出全部4个UTF-8字节。

如果你在windows上,你可以使用MultiByteToWideChar和WideCharToMultiByte,一次在UTF-16和UTF-8之间转换整个字符串。

虽然GCC中的默认模式是32位的wchar_t,但编译开关会改变这种情况,更一般的说,c&c ++规范没有指定wchar_t的大小 – 实际上wchar_t的大小可以和char相同。

如果你想避免使用Windows API(在你的Windows封装代码中!),那么一次使用mbstowcs来转换整个字符串。