Всем привет! В этой первой части серии Ого, это фантастика! мы поговорим о UTF-8 и его загадочных, умопомрачительных способах.
Но давайте рассмотрим это с самого начала.
Понимаете, в свое время, если вы хотели пообщаться в голосовом чате со своей лучшей подругой, вам нужно было положить монеты в эти огромные смартфоны, которые они прикрутили к тротуару, а затем повернуть циферблат на основе некоторого случайного числа, назначенного вашему друг, и тогда смартфон чуть меньшего размера, подключенный к стене в доме вашего друга, будет издавать звуки, а это значит, что кто-то хочет поговорить в голосовом чате.
Я хочу сказать, что я стар. И как пожилой человек я вырос на ASCII.
А ASCII прост:
↓
Один байт на символ. Один символ на байт. Красивый.
Затем я сделал перерыв в компьютерах на несколько лет, а когда вернулся, там была вся эта штука с UTF-8.
Итак, я узнал о рунах и всем остальном (это Голанг, если вам интересно), и какое-то время, по крайней мере, функционально, все было в порядке.
Но знаете, я любопытный человек, и в конце концов я бы не стал любопытным.
Что привело меня к…
↓
Я имею в виду, конечно, не так ли? UTF-8 требует более одного символа на байт, иначе как бы он закодировал миллиард разных символов?
↓
Таким образом, эти забавные символы занимают более одного байта (а в UTF-8 символ может занимать до четырех).
Отлично.
Но как это работает?
1. Соединяются ли байты акцента с байтами ASCII для формирования новых символов?
2. Есть ли байты-разделители между байтами символов, что означает, что все, что находится между разделителями, сливается в кучу?
3. Это какая-то черная магия?
Давайте посмотрим:
↓
Нет и нет. Черт возьми.
(А насчет №3 мои потусторонние консультанты сказали, что это не так.)
Так как?
К этому моменту я потратил целую вечность, пытаясь решить эту проблему самостоятельно, и вот наконец я RTFM. Вот важный фрагмент, адаптированный из WP:
Имея в виду:
- Если ваш байт начинается с нуля, это обычный символ ASCII.
- Если ваш байт начинается со 110, вы получили двухбайтовый символ.
- Если ваш байт начинается с 1110, вы получили трехбайтовый символ.
- 11110 означает четыре.
- И все 10 * байтов, так сказать, «коннекторы».
Чтобы узнать, работает ли это:
Давайте поразмышляем над этим, прежде чем я покажу вам результат. У нас есть четыре символа, и их кодовые точки: U + 0061, U + 00E3, U + 9999 и U + 1F914. Они должны быть длиной один, два, три и четыре байта соответственно.
То есть у нас должны быть:
- Для нашего первого символа: один байт, начинающийся с нуля.
- Второй символ: один байт начинается с 110, за ним следует другой, начинающийся с 10.
- Третий символ: первый байт начинается с 1110, следующие два начинаются с 10.
- Четвертый символ: первый байт начинается с 11110, следующие три начинаются с 10.
Давайте посмотрим:
Немного перетасовал для наглядности:
1. 01100001
2. 11000011 10100011
3. 11101001 10100110 10011001
4. 11110000 10011111 10100100 10010100
Потрясающие!
Теперь давайте посмотрим, действительно ли оставшиеся биты, помимо всей этой сигнализации, образуют числа, которые мы ищем:
- 11000011 10100011 → 00011 100011
- 11101001 10100110 10011001 → 1001 100110 011001
- 11110000 10011111 10100100 10010100 → 000 011111 100100 010100
Что мы можем использовать для:
Результат здесь: e3 9999 1f914. Другими словами:
- 00011100011 → 0xE3 (ã)
- 1001100110011001 → 0x9999 (香)
- 000011111100100010100 → 0x1F914 (🤔)
Итак, поехали.
Сейчас в мире все хорошо.
Мы знаем, как UTF-8 творит чудеса.
Or do we?
Вы когда-нибудь задумывались, что происходит, когда четырехбайтовый символ…
… Встречает специальный четырехбайтовый символ, а затем два из них…
… Заниматься озорством на двадцать семь байт и…
… Они попадают в большую счастливую семью длиной в двадцать пять байтов?
Ты сделаешь? Потрясающие! Следите за следующей публикацией!
Спасибо за чтение! Если вам понравилась эта статья, поделитесь ею и обязательно подпишитесь на dEffective Go!