Есть ли кто-нибудь, кто знает, что делает следующий код? - PullRequest
1 голос
/ 09 октября 2011
/* utf-8: 0xc0, 0xe0, 0xf0, 0xf8, 0xfc */
static unsigned char _mblen_table_utf8[] = 
{
    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
    2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
    2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
    3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
    4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 6, 6, 1, 1
};

Могу поспорить, что это как-то связано с кодировками,

но как именно это работает?

ОБНОВЛЕНИЕ

        while (str < ptr)
        {
            j = mblen[(*str)];
            tree_nput(r->tree, cr, sizeof(struct rule_item), str, j);
            str += j;
        }
    }   

Ответы [ 4 ]

4 голосов
/ 09 октября 2011

Поскольку символ в многобайтовой строке имеет переменную длину, эта таблица отображает каждый символ в длину.

Последние 64 символа шире, чем один байт, и имеют длину от 2 до 6.

Использование будет примерно таким:

unsigned char current_char = *mbstr;

for (i = 0; i < _mblen_table_utf8[current_char]; i++) {
  /* treat *mbstr++ as a part of the current character */
}
2 голосов
/ 09 октября 2011

Исторически сложилось так, что каждый символ был закодирован в 7 битах (затем 8 битах), что было более чем достаточно для кодирования алфавитов европейских языков.

Только 128 первых символов были общими для всех, остальные 128 были стандартизированы с помощью кодовых страниц (например, ISO-8859-1 ).

Необходимость кодирования более длинных алфавитных языков, таких как китайский, привела к усилию Unicode , где каждый символ кодируется в несколько байтов.* - это способ кодировать символы Юникода эффективным способом с переменной длиной кода.Это означает, что первый прочитанный вами байт определяет длину последовательности символов.

По сути, ваша таблица является таблицей поиска, чтобы проверить, сколько байтов является символом, который начинается с байта, который вы используете в качестве индекса таблицы.Вы увидите другую версию этой таблицы здесь с пояснениями.

Я добавил индексы таблицы в качестве комментариев, чтобы сделать ее более понятной:

/* utf-8: 0xc0, 0xe0, 0xf0, 0xf8, 0xfc */
static unsigned char _mblen_table_utf8[] = 
{
/*0x00*/    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
/*0x10*/    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
/*0x20*/    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
/*0x30*/    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
/*0x40*/    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
/*0x50*/    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
/*0x60*/    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
/*0x70*/    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
/*0x80*/    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
/*0x90*/    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
/*0xA0*/    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
/*0xB0*/    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
/*0xC0*/    2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
/*0xD0*/    2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
/*0xE0*/    3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
/*0xF0*/    4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 6, 6, 1, 1
};
1 голос
/ 09 октября 2011

Массив выглядит как справочная таблица для определения количества байтов в символе UTF-8 по первому байту. По сути, первый байт (в качестве значения без знака) используется как индекс в массиве, а элемент с этим индексом задает длину последовательности байтов для символа UTF-8.

Недопустимые байты и байты средней последовательности отображаются в этой таблице на 1 байт, поэтому при обнаружении неуместного кода, использующего эту таблицу, вероятно, они будут обрабатываться как одиночные символы (если только они специально не игнорируются).

Одно из применений для такой таблицы - подсчет символов в строке UTF-8 (не байтов, а символов Юникода). Каждый раз, когда вы подсчитываете символ, вы просматриваете длину и продвигаетесь на длину последовательности байтов символа, вместо того, чтобы двигаться вперед на один байт ... это работает хорошо, если вы начинаете с начала символа, а строка действительный UTF-8 до конца.

0 голосов
/ 09 октября 2011

Без каких-либо дополнительных подробностей приведенный выше код делает именно это: он объявляет статический массив без знака и инициализирует его значениями в фигурных скобках.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...