Мета полягає у створенні повністю сумісного перетворювача між офіційними кодуваннями Unicode, як зазначено у поширених питаннях UTF . Зважаючи на те, що це зосереджено на Unicode, я прийму відповідь з найнижчим числом байтів, використовуючи найкращі можливі з кодованих кодувань (що, мабуть, буде UTF-8, якщо, можливо, ви не запрограмуєте його в APL). Я прошу вибачення за довгий пост, але багато цього пояснює кодування, до якого також можна отримати доступ в офіційній специфікації (pdf, розділ 3.9 D90 - D92) або Вікіпедії .
Технічні умови
Якщо в будь-який момент ваша мова, що вибирається, не може точно відповідати вимозі, замініть її тим, що дотримується духу наведених правил. Напр. не кожна мова має вбудовані масиви, функції тощо.
Немає використання бібліотек / функцій рядків або кодування бібліотек / функцій. Сенс цього коду в гольфі полягає в реалізації перетворювача за допомогою маніпуляції бітом / байтом. Однак використання самих рядків у якості символу чи байтового масиву дозволяється. О, і жодні дзвінки в ОС, які також виконують перетворення.
Перетворювач - це функція, яка прийме три параметри: масив байтів, що представляє кодовану вхідну рядок, і кодування "введення" та "вихід", представлені у вигляді чисел. Довільно будемо призначати
UTF-8, UTF-16, UTF-16BE, UTF-16LE, UTF-32, UTF-32BE, and UTF32LE
числа від 0 до 6 в такому порядку. Немає необхідності перевіряти, чи є число,< 0
або> 6
ми вважатимемо ці параметри правильними. Перетворювач поверне дійсний байтовий масив у потрібному вихідному кодуванні.Ми будемо використовувати нульовий символ (
U+0000
) як строковий термінатор. Нічого після цього не має значення. Будемо вважати, що вхідний масив десь має нульовий символ, тому вам не потрібно робити перевірку меж.Відповідно до FAQ , якщо масив вхідних байтів недійсний для оголошеного кодування, ми повинні подати сигнал про помилку. Ми зробимо це одним із наступних способів: збоїмо програму, кинемо виняток, повернемо null або повернемо масив, у перших чотирьох байт якого 0 (щоб його можна було розпізнати як
U+0000
у кожному кодуванні).
Кодування
Потрібно дотримуватися офіційних специфікацій, але Вікіпедія надає хороше (і наскільки я вважаю правильним) пояснення кодувань, і я підсумую їх тут для повноти. Зауважте, що UTF-16 і UTF-32 мають варіанти для витривалості .
UTF-32, UTF-32LE, UTF-32BE
Для найпростішого кодування, кожна кодова точка просто кодується в 4 байти, що дорівнює її числовому значенню. LE / BE являє собою ендіанство (маленький ендіан / великий ендіан).
UTF-16, UTF-16LE, UTF-16BE
Кодові точки з U+0000 - U+FFFF
кодуються в 2 байти, що дорівнює його числовому значенню. Більші значення кодуються за допомогою пари сурогатів, які є зарезервованими значеннями U+D800 - U+DFFF
. Отже, для кодування очок, більших за U+FFFF
, можна використовувати наступний алгоритм (безсоромно скопіювати з Вікіпедії ):
- 0x010000 віднімається від кодової точки, залишаючи 20-бітове число в діапазоні 0..0x0FFFFF.
- Десять кращих бітів (число в діапазоні 0..0x03FF) додаються до 0xD800, щоб дати першу кодову одиницю або сурогат свинцю, який буде знаходитись у діапазоні 0xD800..0xDBFF [...].
- Низькі десять біт (також у діапазоні 0..0x03FF) додаються до 0xDC00 для отримання другої кодової одиниці або сурогату сліду, який буде знаходитися в діапазоні 0xDC00..0xDFFF [...].
UTF-8
Кодові точки з U+0000 - U+007F
кодуються як 1 байт, що дорівнює його числовому значенню. З U+0080 - U+07FF
них кодуються як 110xxxxx 10xxxxxx
, U+0800 - U+FFFF
це 1110xxxx 10xxxxxx 10xxxxxx
, більш високі значення 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
. У x
«s є бітами з числового значення точки коди.
БОМ
Позначка порядку байтів (BOM, U+FEFF
) використовується в якості першого кодового пункту для вказівки на витривалість. Виконуючи вказівки щодо поширених запитань щодо BOM , BOM буде використовуватися наступним чином: бо UTF-8, UTF-16 and UTF-32
це необов'язково. Якщо BOM відсутній UTF-16
або UTF-32
вважається великим ендіаном. BOM не повинен з'являтися вUTF-16LE, UTF-16BE, UTF-32LE and UTF-32BE
.
Поширені підводні камені, що спричиняють недійсний UTF
Різні речі можуть спричинити неправильність послідовності байтів UTF.
- UTF-8 і UTF-32: Пряме кодування сурогатних кодів (
U+D800 - U+DFFF
) або кодових точок більше, ніжU+10FFFF
. - UTF-8: багато недійсних послідовностей байтів.
- UTF-16: парні сурогати або неправильно парні сурогати.
- BOM: Потрібно використовувати, як зазначено в розділі кодування. Зверніть увагу, що при виведенні
UTF-16
абоUTF-32
(не вказана притаманна ендіантність) ви можете вибрати, але з невеликим ендіаном, ви повинні включити BOM.
Зауважте, що не символи та непризначені кодові точки (обидва відмінні від сурогатів) повинні трактуватися як звичайні символи.
''⎕R''⍠'InEnc' 'UTF16BE' 'OutEnc' 'UTF8-BOM'
.