【问题标题】:How to convert from utf-16 to utf-32 on Linux with std library?如何在 Linux 上使用 std 库从 utf-16 转换为 utf-32?
【发布时间】:2014-05-28 18:46:23
【问题描述】:

在 MSVC 上,将 utf-16 转换为 utf-32 很容易 - 使用 C11 的 codecvt_utf16 语言环境方面。但是在 GCC (gcc (Debian 4.7.2-5) 4.7.2) 中,这个新功能似乎还没有实现。有没有办法在没有 iconv 的 Linux 上执行这种转换(最好使用 std 库的转换工具)?

【问题讨论】:

  • 你不想使用iconv有什么原因吗?
  • 你有不想自己实现的原因吗?
  • 好吧,原因是如果这可以用 std 来完成 - 为什么要发明轮子?
  • 因为你的标准没有实现它:-)
  • codecvt_utf16 是 std 中进行这种转换的唯一方法吗?

标签: c++ gcc unicode utf-16


【解决方案1】:

将 UTF-16 解码为 UTF-32 非常简单。

您可能希望在编译时检测您正在使用的 libc 版本,并在检测到损坏的 libc(没有您需要的功能)时部署您的转换例程。

输入:

  • 指向源 UTF-16 数据的指针(char16_t *ushort *,--为方便起见UTF16 *);
  • 它的大小;
  • 指向 UTF-32 数据的指针(char32_t *uint * -- 为方便起见UTF32 *)。

代码如下:

void convert_utf16_to_utf32(const UTF16 *input, 
                            size_t input_size, 
                            UTF32 *output) 
{
    const UTF16 * const end = input + input_size;
    while (input < end) {
        const UTF16 uc = *input++;
        if (!is_surrogate(uc)) {
            *output++ = uc; 
        } else {
            if (is_high_surrogate(uc) && input < end && is_low_surrogate(*input))
                *output++ = surrogate_to_utf32(uc, *input++);
            else
                // ERROR
        }
    }
}

留下错误处理。您可能希望将U+FFFD¹ 插入流中并继续进行,或者只是退出,这完全取决于您。辅助功能很简单:

int is_surrogate(UTF16 uc) { return (uc - 0xd800u) < 2048u; }
int is_high_surrogate(UTF16 uc) { return (uc & 0xfffffc00) == 0xd800; }
int is_low_surrogate(UTF16 uc) { return (uc & 0xfffffc00) == 0xdc00; }

UTF32 surrogate_to_utf32(UTF16 high, UTF16 low) { 
    return (high << 10) + low - 0x35fdc00; 
}

¹ 参见。统一码:

² 还要考虑到 !is_surrogate(uc) 分支是迄今为止最常见的(以及第二个 if 中的非错误路径),您可能希望使用 __builtin_expect 或类似的方式对其进行优化。

【讨论】:

  • 几乎与使用 codecvt_utf16 所需的代码量相同。
  • 你能解释一下 is_xx_surrogate 方法吗?
  • 谢谢!但是 0000..D7FF 范围呢?好像 is_surrogate 函数不算在内。
  • 嗯,五年后重新阅读代码,我想我在is_surrogate 中打错了。我在考虑使用无符号算术,而不是有符号。
  • 是的,当然。太简单了,我几乎无法为此主张版权。很确定它也随处可见......
猜你喜欢
  • 2016-07-23
  • 2011-11-01
  • 2014-07-16
  • 2020-01-28
  • 2013-09-26
  • 2014-11-14
  • 2019-05-15
  • 2010-10-19
  • 2013-05-20
相关资源
最近更新 更多