Как получить имя символа Юникода?

Думаю, я видел это очень давно; способ получить строку, содержащую имя символа Юникода, с помощью вызовов API Win32. Я использую C++ Builder, поэтому, если он поддерживается в библиотеке VCL, это тоже подойдет.

Например:
GetUnicodeName(U+0021) вернет строку (или заполнит структуру или подобное), например "EXCLAMATION MARK".

Или есть другой способ получить тот же результат в Windows с C или C++.

В худшем случае будет иметь ОГРОМНУЮ таблицу поиска с интересующими именами (в основном латинскими символами).

1 ответ

Вы можете использовать недокументированные GetUNameметод из getuname.dll:

      std::string GetUnicodeCharacterName(wchar_t character)
{
    // https://github.com/reactos/reactos/tree/master/dll/win32/getuname
    typedef int(WINAPI* GetUNameFunc)(WORD wCharCode, LPWSTR lpBuf);
    static GetUNameFunc pfnGetUName = reinterpret_cast<GetUNameFunc>(::GetProcAddress(::LoadLibraryA("getuname.dll"), "GetUName"));

    if (!pfnGetUName)
        return {};

    std::array<WCHAR, 256> buffer;
    int length = pfnGetUName(character, buffer.data());

    return utf8::narrow(buffer.data(), length);
}

// Replace invisible code point with code point that is visible
wchar_t ReplaceInvisible(wchar_t character)
{
    if (!std::iswgraph(character))
    {
        if (character <= 0x21)
            character += 0x2400; // U+2400 Control Pictures https://www.unicode.org/charts/PDF/U2400.pdf
        else
            character = 0xFFFD; // REPLACEMENT CHARACTER
    }

    return character;
}

// Accepts in UTF-8.
// Returns UTF-8 string like this:
// q <U+71 Latin Small Letter Q>
// п <U+43F Cyrillic Small Letter Pe>
// ␈ <U+8 Backspace>
//  <U+10338 Supplementary Multilingual Plane>
//  <U+1F692 Supplementary Multilingual Plane>
std::string GetUnicodeCharacterNames(std::string string)
{
    // UTF-8 <=> UTF-32 converter
    std::wstring_convert<std::codecvt_utf8<char32_t>, char32_t> utf32conv;

    // UTF-8 to UTF-32
    std::u32string utf32string = utf32conv.from_bytes(string);

    std::string characterNames;
    characterNames.reserve(35 * utf32string.size());

    for (const char32_t& codePoint : utf32string)
    {
        if (!characterNames.empty())
            characterNames.append(", ");

        char32_t visibleCodePoint = (codePoint < 0xFFFF) ? ReplaceInvisible(static_cast<wchar_t>(codePoint)) : codePoint;
        std::string charName = (codePoint < 0xFFFF) ? GetUnicodeCharacterName(static_cast<wchar_t>(codePoint)) : "Supplementary Multilingual Plane";

        // UTF-32 to UTF-8
        std::string utf8codePoint = utf32conv.to_bytes(&visibleCodePoint, &visibleCodePoint + 1);
        characterNames.append(fmt::format("{} <U+{:X} {}>", utf8codePoint, static_cast<uint32_t>(codePoint), charName));
    }

    return characterNames;
}

Недостатком является то, что он содержит символы только из базовой многоязычной плоскости Unicode (BMP).

Или вы можете использоватьu_charName()ICU API, который поставляется с Windows после Fall Creators Update (версия 1709, сборка 16299).

Другие вопросы по тегам