如何将 "universal character name" 转换为 wchar_t 的序列?

How to convert from "universal character name" to a sequence of wchar_t's?

在我的应用程序中,我需要能够解析 C++14 标准支持的字符串文字。所以我正在阅读有关该主题的 this article 并且我试图理解如何从 universal character name 转换为 wchar_t 序列?

让我用这个例子来解释。比如说,如果我用 VS 2017 编译以下内容:

const wchar_t* str2 = L"\U0001F609 is ;-)";

str2在内存中变成如下字节序列:

那么 \U0001F609 是如何变成 3d d8 09 de 的呢?或者,我需要什么 WinAPI 才能进行此转换?

how did \U0001F609 become 3d d8 09 de?

wchar_t在windows上是16位的,但是0x1F609 > UINT16_MAX,因此使用所谓的代理对将代码点编码成两个16位的代码单元.

来自Wikipedia

  • 代码点减去0x10000,剩下20位数字 范围 0x00000–0xFFFFF。 (0x1F609 - 0x10000 = 0xF609)
  • 将高十位(0x000-0x3FF范围内)加到0xD800中 给出第一个 16 位代码单元或高代理项,这将在 范围 0xD800–0xDBFF。 (0xD800 + 0x3D)
  • 将低十位(也在0x000–0x3FF范围内)添加到0xDC00 给出第二个 16 位代码单元或低代理项,这将是 在 0xDC00–0xDFFF 范围内。 (0xDC00 + 0x209)

剩下 0xD83D 0xDE09。将其编码为两个小端 16 位代码单元得到 3D D8 09 DE.

how do I convert from a universal character name to a sequence of wchar_ts?

'Universal character name' 是一个 unicode 代码点。 windows 上的 wchar_t 是 UTF-16。

What WinAPI do I need to make this conversion?

我不知道是否有任何专门用于此的 API,但是编写您自己的 UTF-32* 到 UTF-16 转换器非常容易。查看维基百科页面了解更多信息


*: 因为32位足以包含所有unicode,所以每个码位都可以编码在一个UTF-32编码单元中。