LINUX.ORG.RU
ФорумTalks

Почему UTF-8 именно такой?

 


1

1

Нужно было написать свои собственные функции работы с UTF-8, поэтому полез на википедию читать описание формата и удивился какой он странный.

Почему нельзя было сделать так:

1) Если старший бит байта сброшен, то берём его как есть.

2) Если установлен, то сдвигаем предыдущее значение на 7 бит и добавляем младшие 7 бит байта.

То есть итерация по символам выглядела бы так:

char *str = ...;
int code = -1;
while (1) {
    if (*str < 0x80) {
        if (code != -1) {
            // Тут мы работаем с Unicode символом code
        }
        code = *str;
        if (code == 0) break;
    } else {
        code <<= 7;
        code |= *str & 0x7F;
    }
}

Плюсы: алгоритм обработки прост до безобразия, не нужно беспокоится о проверке на корректность (если про это забыть в случае с UTF-8, а кто-то обрежет строку по середине символа, то приложение может упасть), символы пакуются ещё компактнее, нет ограничения на размер символа (вдруг кому-нибудь когда-нибудь станет мало UTF32 и появится UTF64 - в моём коде достаточно будет заменить int на long long).

Почему авторы стандарта не догадались до такой простой идеи и нагородили очень странные вещи? Или есть какие-то причины по которой тот вариант лучше того, что выше?

★★★★★

Последнее исправление: KivApple (всего исправлений: 1)

Ответ на: комментарий от x3al

Отличие от перечисленных в начале документа особенностей только в том, что в моём варианте тупая сортировка может дать результат отличный от тупой сортировки UTF32. Но там же указано, что так сортировать всё равно не правильно (нужно учитывать национальные особенности).

KivApple ★★★★★
() автор топика
Последнее исправление: KivApple (всего исправлений: 1)
Ответ на: комментарий от KivApple

Ты забыл самосинхронизацию.

не нужно беспокоится о проверке на корректность

Об этом нужно беспокоиться всегда.

в случае с UTF-8, а кто-то обрежет строку по середине символа, то приложение может упасть

А ещё можно дверью что-нибудь прищемить. Алгоритмы давно написаны.

x3al ★★★★★
()

Кстати, в твоём случае сильно усложнится поиск. Нужно будет смотреть на октеты за найденным паттерном, чтобы убедиться, что не нашёл лишнее.

x3al ★★★★★
()
Последнее исправление: x3al (всего исправлений: 1)

Преимущество UTF-8 в том, что можно определить начало каждой буквы в потоке/масиве, в твоём варианте можно нахватать неверных букв в зависимости от начальной позиции чтения.

Deleted
()
Ответ на: комментарий от Deleted

М? Можно добавить игнорирование окетов, пока не встретится со сброшенным старшим битом. Тогда мусора не нахватаем.

KivApple ★★★★★
() автор топика
Ответ на: комментарий от x3al

А ещё можно дверью что-нибудь прищемить. Алгоритмы давно написаны.

Это то да, но помнится кто-то тут жаловался, что UTF-8 сложно парсить и это добавляет уязвимости, поэтому UTF-16/КОИ-8 рулит.

KivApple ★★★★★
() автор топика

нет ограничения на размер символа

вы не поверите...

next_time ★★★★★
()
Ответ на: комментарий от KivApple

что UTF-8 сложно парсить и это добавляет уязвимости

с͕͑л̹͓͔͔̘ͪо̂͒̎͗̂ж͚͉̟̜̲̃̍ͪ́н̸̹̤͎̣͍ͧͣͪ̑͌оͨͤͯ͛͐͏̲̤̯ ̳̼͖͚̉̏͛͝ͅа̥̳̘̬̗ͪ̐͛ͧ̓̃ͥͅд̛̟е͚̫̻к͉͖͇ͣ͜в̏ͯ͛̎͏̣̳͔а̠̺̖͓̠ͧ̉ͩ͐̚т̬̖͙͓̱̩ͦͮ͟н͔̪͈̺̮ͨ̔͊ͅо̭̘̱̳̟̩̱͑̆ ̮̳̟̯ͧ͠п͈͍̟̹̍͒̽̾ͬ͂а̰̿ͧ͐р̹̺̰̤̹̩̯͂͌̈́̎̓̈́с̲̍ͭͭ̉͆̄̈и̢̳͙͚͊̈ͫ͌т͑ͪ̋̃̃͐͏ь̮̻̯̼̦̰̌͐̽ͅ ̜̖̺̬̖̃̇ͭ̓во͕͚͎̗ͫ̔̾т̖͓̠̹̣̩̎ͬ̔̉́̆ͅ ̸͙̗̬̎т̛͙͎̟̙а̺͎ͣ͌̃̊к̦̅ͮ́͋̏и̲̳̞̰ͧͫ̄̀е̩̪̳̗̱̭̮͐͗͌͐͗̚ ̯͖͎̫̞͕͍̾ͧ͑̈̑в̸͎͈̘̝ͯе͖͚̬͖̠̒щ̼̼͕̰ͭ̊͋ͥ̆́̑͠ͅи̋ ̞͖̠̙͒̿́̎ӥ̖̭̳̜̥̺͓́ͨͩ͗͜ ̱̪̹ͪ́͒́͑͋в̈а̸̮͖͎͕̖͍͇ͧ́̈́ͪш̛̭̆а̢̘̲̩͔̜ͩͤͨͯ̓̾ͪ ̏ͦ̂̂͗͒с̷̠̥͓̮̞̈͋͗̌̈ͧӥ̤̠̲̤͎͓͇̐ͫ̉̔͠с͔͍͡т̫͎͉̤͙̼͊ͣ̈̅̚ͅе̢̠̊̿м̯̖̩̲͈ͥ̀ͅа̺͔̯̳͇̥ͧ̓̎ͧ͑̚̚ ̜͈̻͓п̞̥̖̤ͣͨ̊͜рͯ͆͑͂̈́́о͏̮ц̫ͣͮ̀̆е̧͙͑̎͗͋̅ͧ͋с̷̤̯͇͆ͨ͊̌ͮ̋с̪ͩ ̧̬̱͚͑̌͌́̊͂н̩̤̰͗̿̓и̥̲́̋̀ͧ̉ͦ́к̡̳̬͒̌а̸͔ͪ͗ͣ̀̄̎к͙̙̹̦̬͇ͮ̾ͣ ̰̰̰̱̟̜̤ͤͦͫ̑ͣнͭ̅̄е̮̣ͩ̍ͦ̇̄ͤ̚͜ ̟̟ͣ̚о̡̥͚̀б̱͚̪͉̇͘л̛̖͖̹͉̺̹ͪ́ͨͨ̔ӗ̟̈̈̍͑̂г̜͓̓̍͌̿̎ͅӵ́̑ͪ͠и͖̪̅ͬ̇т̡̣͎͙̙̓̂ͭ̋ͯ

next_time ★★★★★
()
Ответ на: комментарий от KivApple

Если символ представлен как 1xxx xxxx (xxxx xxxx) - длинна мусора неизвесна

Если символ представлен как 1xxx xxxx (1xxx xxxx) - мусор идет до первого символа ASCII

Если символ представлен как 1xxx xxxx (0xxx xxxx) - мусор включает первый или несколько символов ASCII

UTF-8 потому и хорош, что можно определить начало следующей буквы.

Deleted
()
Ответ на: комментарий от Deleted

Если символ представлен как 1xxx xxxx (1xxx xxxx) - мусор идет до первого символа ASCII

Это мой вариант. Только с одним «но». Любой корректный юникод-символ тоже начинается с ASCII-символа (только он на самом деле не ASCII, а старшие 7 бит символа Unicode). Так что синхронизация восстановится как только мы дойдём до начала любого символа.

KivApple ★★★★★
() автор топика
Ответ на: комментарий от KivApple

UTF-8 также поддерживает обратную совместимость с ASCII. То есть коды 0..127 всегда читаются как в ASCII, независимо от того, что за ними, а последовательности от 128 и выше никогда не включают коды ASCII.

Приложение, не умеющее в UTF-8, просто подумает, что все не-ASCII символы - это однобайтные коды какой-то неизвестной кодировки, и не будет их кромсать.

Кроме того, UTF-8 - это префиксный код. Зачем это нужно и почему это хорошо, см. Википедию. Если коротко, то в UTF-8 никакая кодовая последовательность не является началом никакой другой. Парсер уже по первому байту последовательности может определить, сколько байт ему нужно прочитать до целого символа. В предложенном же варианте придётся запоминать байты «на всякий случай» - а вдруг после ASCII-байта встретится не ASCII и изменит смысл предыдущего байта. Соответственно, точно определить границу каждого символа в предложенной схеме можно, только прочитав весь поток. В случае UTF-8 можно прочитать строго N символов, не читая вперёд лишнего.

reserved
()

Не заменять

в моём коде достаточно будет заменить int на long long

#define UTF_CHARACTER int

Если будешь писать так, то заменить int на long long придётся только в одном месте, а не во всех твоих функциях.

Camel ★★★★★
()

char *str

if (*str < 0x80) {

Если char знаковый, то его значение лежит в пределах [-128, 127], то есть всегда меньше 0x80 == 128.

Возьми готовый код. Нужные куски под подходящими лицензиями легко гуглятся.

i-rinat ★★★★★
()
Последнее исправление: i-rinat (всего исправлений: 1)
Ответ на: комментарий от KivApple

Типа повод велосипеды писать? Работодатель знает? Возьми готовый код, из стандартных ли, из нестандартных ли.

t184256 ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.