如何在最近使用 UTF-8 语言环境的 macOS 中处理 toupper() 返回的大于 255 的值

问题描述 投票:0回答:1

下面的代码试图解决的问题是如何有效地检测可能正在使用基于 UTF-8 的语言环境,以便在我们处理时不会查询 127 以上的所有代码点的

ctype
属性普通(非宽)字符。

至少在 macOS 14 中,当使用基于 UTF-8 的语言环境时。以下程序将显示 2 个有问题的代码点,尽管这些代码点对无符号字符有效,但它们是从不再有效的

toupper()
值得到的响应:

#include <langinfo.h>
#include <ctype.h>
#include <locale.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>

#ifdef WORKAROUND
static int is_utf8_locale(void)
{
    const char *charmap = nl_langinfo(CODESET);

    /* this shouldn't happen */
    if (!charmap)
        return 0;

    if (!strncmp(charmap, "UTF-8", 5))
        return 1;

    /*
     * nl_langinfo should never return an empty string, unless the "item" used is invalid, and it
     * should return either the C or POSIX CODESET if the locale is missing one, but ...
     */
    if (!*charmap) {
        unsigned char buf[MB_CUR_MAX + 1];
        return (wctomb((char *)&buf, 0xf8ff) == 3) &&
                (buf[0] == 0xef && buf[1] == 0xa3 && buf[2] == 0xbf);   }

    return 0;
}
#endif

int main(int argc, char *argv[])
{
    const char *locale = (argc > 1) ? argv[1] : "fr_FR";
    int i, f = 0;

    if (!setlocale(LC_CTYPE, locale))
        return 127;

#ifdef WORKAROUND
    if (is_utf8_locale())
        return 0;
#endif

    for (i = 128; i < 256; i++) {
        int u, l;
        unsigned char c = i;

        l = tolower(c);
        u = toupper(c);

        if (l > 255) {
            f++;
            printf("%1$d: tolower(%2$d)) %2$c -> %3$d (%4$#x) %4$c\n", islower(c), c, l, l % 256);
        }
        if (u > 255) {
            f++;
            printf("%1$d: toupper(%2$d) %2$c -> %3$d (%4$#x) %4$c\n", islower(c), c, u, u % 256);
        }
    }
    return f;
}

AFAIK,这个问题在某种程度上是最近才出现的,至少在 10.15 中不会发生,虽然

toupper()
已知“有时”会尝试提供更多帮助(作为 BSD 扩展),但我在我最近尝试过的任何 BSD 系统,他们都提到这种行为已被弃用。

“-DWORKAROUND”可以工作,但恕我直言,它太丑陋了,而且在线程环境中也会出现问题,而且由于 macOS 定义其语言环境的方式,特别容易受到攻击。

所有没有明确

.${CHARMAP}
的语言环境都会显示来自
nl_langinfo()
的有问题的响应,以及包含
.UTF-8
以及有时在其他系统中使用
.utf8
的语言环境(尽管它们总是从
nl_langinfo()
返回正确的值)这些情况)。

该解决方法显然需要针对非 POSIX 系统的额外代码。

受影响的应用程序不支持 UTF-8 以外的外来多字节编码,但使用

wctomb()
的检测很脆弱,可能无法在 Apple 系统之外工作,因此也欢迎建议或测试结果。

c macos utf-8 locale
1个回答
0
投票

如何在最近使用 UTF-8 语言环境的 macOS 中处理 toupper() 返回的大于 255 的值

在任何语言环境和任何系统中,都无法使用

toupper
(在具有正常 8 位字符的健全系统上)处理大于 255 的值。

© www.soinside.com 2019 - 2024. All rights reserved.