Это действительно модифицированный UTF-8?


9

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

Обзор UTF-8

  • Байты в диапазоне 1-0x7F включительно, как правило, действительны
  • Байты с битовой комбинацией 10XX XXXXсчитаются байтами продолжения, причем шесть наименее значимых битов используются для кодирования части кодовой точки. Они не должны появляться, если они не ожидаются предшествующим байтом.
  • Байты с шаблоном 110X XXXXожидают один байт продолжения после
  • Байты с шаблоном 1110 XXXXожидают два байта продолжения после
  • Байты с шаблоном 1111 0XXXожидают три продолжения байта после
  • Все остальные байты недопустимы и не должны появляться где-либо в потоке UTF-8. 5, 6 и 7-байтовые кластеры теоретически возможны, но не будут допущены для этой задачи.

Сверхдлинные кодировки

UTF-8 также требует, чтобы кодовая точка была представлена ​​минимальным количеством байтов. Любая последовательность байтов, которая может быть представлена ​​меньшим количеством байтов, недопустима. Модифицированный UTF-8 добавляет к этому исключение для нулевых символов (U + 0000), который должен быть представлен как C0 80(шестнадцатеричное представление), и вместо этого запрещает появление нулевых байтов в любом месте потока. (Это делает его совместимым со строками с нулевым символом в конце)

Вызов

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

Примеры

41 42 43  ==> yes (all bytes are in the 0-0x7F range)
00 01 02  ==> no (there is a null byte in the stream)
80 7F 41  ==> no (there is a continuation byte without a starter byte)
D9 84 10  ==> yes (the correct number of continuation bytes follow a starter byte)
F0 81 82 41  ==> no (there are not enough continuation bytes after F0)
EF 8A A7 91  ==> no (too many continuation bytes)
E1 E1 01  ==> no (starter byte where a continuation byte is expected)
E0 80 87  ==> no (overlong encoding)
41 C0 80  ==> yes (null byte encoded with the only legal overlong encoding)
F8 42 43  ==> no (invalid byte 'F8')

правила

  • Применяются стандартные правила и лазейки
  • Вход и выход могут быть в любом удобном формате, если все значения в диапазоне байтов без знака (0-255) могут быть считаны.
    • Возможно, вам придется использовать массив или файл, а не строку с нулевым символом в конце. Вы должны уметь читать нулевые байты.
  • Самый короткий код выигрывает!
  • Обратите внимание, что использование встроенных функций для декодирования UTF-8 не гарантирует соответствие приведенным здесь требованиям. Возможно, вам придется обойти это и создать особые случаи.

РЕДАКТИРОВАТЬ: добавлен бонус за неиспользование встроенных в декодер UTF-8

EDIT2: удален бонус, так как квалифицирован только ответ на Rust, и его неудобно определять.


Я ждал этого.
Адам

Вы можете добавить тестовый пример с недопустимым байтом в диапазоне 0xF8-0xFF.
Арно

2
Кажется, что допускаются суррогаты (0xD800 - 0xDFFF) и кодовые точки за пределами 0x10FFFF, в отличие от «современной» спецификации UTF-8. Я думаю, что это должно быть разъяснено, в идеале с дополнительными контрольными случаями.
nwellnhof

другие примеры будут полезны
Дон

«Байты в диапазоне 0-0x7F включительно, как правило, действительны», это должно быть от 1 до 0x7f?
Дон

Ответы:



1

APL (Dyalog Unicode) , 41 39 байт SBCS

Функция анонимного молчаливого префикса. Принимает строку Unicode в качестве аргумента, где кодовые точки символов представляют входные байты.

{0::0⋄×⌊/'UTF-8'UCS2UCS⍵}'À\x80'RA

Попробуйте онлайн!

'À\x80'⎕R⎕AR eplace C0 80с с заглавной A lphabet

{} Применить следующую анонимную функцию, где аргумент :

0:: если произойдет какая-либо ошибка:

  0 вернуть ноль

 пытаться:

  ⎕UCS⍵ преобразовать строку в кодовые точки

  'UTF-8'⎕UCS⍣2 интерпретировать как байты UTF-8 и преобразовать полученный текст обратно в байты

  ⌊/ младший байт (ноль, если присутствует нулевой байт, положительный, если нет, «бесконечность», если пустая строка)

  × знак (ноль, если нулевой байт присутствует, один, если нет)


Разве это не вернулось бы правдиво D9 C0 80 84 C0 80 10?
Нил

@Neil Это действительно так. Это неправильно, потому что удаление C0 80делает несвязанные байты смежными так, чтобы это было допустимо, хотя они являются недействительными, когда они разделены? Изменить: Обновлено, чтобы исправить это без байтовой стоимости.
Адам

некоторые персонажи появляются на моем экране как прямоугольники или прямоугольники, это нормально? Я в Firefox на Linux. APL - очень интересный язык.
Дон

@donbright По моему опыту, символы APL всегда отображаются правильно, даже если иногда они выглядят не так красиво, так что эти блоки, вероятно, представляют собой всего четыре квадрата, которых в основном коде должно быть четыре. Он должен оказывать как это . И да, APL потрясающий, и очень весело. Вы можете легко и быстро научиться этому - просто заходите в APL Orchard .
Адам

да, они четверки. Спасибо.
Дон


0

Ржавчина - 191 байт 313 байт

Согласно комментарию ниже оригинал не работал должным образом. Новая и улучшенная версия. Библиотеки не используются, потому что Mighty Rust не нуждается ни в вас, ни в ваших библиотеках. Этот код использует сопоставление с шаблоном конечного автомата. По бесстыдно срывая UTF8 спецификации , после того, как найти его с помощью ссылки и обсуждения Jon тарелочкам , можно скопировать спецификацию почти посимвольно в матче блока соответствия шаблон ржавчины. В конце мы добавляем специальное требование Бифстера по Mutf8, чтобы C0 80 считался действительным. Ungolfed:

/* http://www.unicode.org/versions/corrigendum1.html
 Code Points        1st Byte    2nd Byte    3rd Byte    4th Byte
U+0000..U+007F      00..7F           
U+0080..U+07FF      C2..DF      80..BF           
U+0800..U+0FFF      E0          A0..BF      80..BF       
U+1000..U+FFFF      E1..EF      80..BF      80..BF       
U+10000..U+3FFFF    F0          90..BF      80..BF      80..BF
U+40000..U+FFFFF    F1..F3      80..BF      80..BF      80..BF
U+100000..U+10FFFF  F4          80..8F      80..BF      80..BF
*/

let m=|v:&Vec<u8>|v.iter().fold(0, |s, b| match (s, b) {
        (0, 0x01..=0x7F) => 0,
        (0, 0xc2..=0xdf) => 1,
        (0, 0xe0) => 2,
        (0, 0xe1..=0xef) => 4,
        (0, 0xf0) => 5,
        (0, 0xf1..=0xf3) => 6,
        (0, 0xf4) => 7,
        (1, 0x80..=0xbf) => 0,
        (2, 0xa0..=0xbf) => 1,
        (4, 0x80..=0xbf) => 1,
        (5, 0x90..=0xbf) => 4,
        (6, 0x80..=0xbf) => 4,
        (7, 0x80..=0x8f) => 4,
        (0, 0xc0) => 8, // beefster mutf8 null
        (8, 0x80) => 0, // beefster mutf8 null
        _ => -1,
    })==0;

попробуйте на ржавой площадке


Рекомендую делать это вручную, но я думаю, что ваша проверка слишком длинна неверна.
Beefster

Ваш вызов, дорогой сэр, провоцирует меня на подражание, и я завершаю это письмо тем, что, в свою очередь, призываю вас сосредоточиться на человеке, который более откровенно выставит ваш вопрос ( bit.ly/2T8tXhO )
don bright
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.