UTF-8 es una forma relativamente simple de codificar puntos de código Unicode en un formato de ancho variable, de modo que no confunda fácilmente el código que no conoce Unicode.
Descripción general de UTF-8
- Los bytes en el rango de 1-0x7F, inclusive, son normalmente válidos
- Los bytes con el patrón de bits
10XX XXXX
se consideran bytes de continuación, y los seis bits menos significativos se utilizan para codificar parte de un punto de código. No deben aparecer a menos que sean esperados por un byte anterior. - Los bytes con el patrón
110X XXXX
esperan un byte de continuación después - Los bytes con el patrón
1110 XXXX
esperan dos bytes de continuación después - Los bytes con el patrón
1111 0XXX
esperan tres bytes de continuación después - Todos los demás bytes no son válidos y no deberían aparecer en ninguna parte de una secuencia UTF-8. Los grupos de 5, 6 y 7 bytes son posibles en teoría, pero no se permitirán a los efectos de este desafío.
Codificaciones demasiado largas
UTF-8 también requiere que un punto de código se represente con el número mínimo de bytes. Cualquier secuencia de bytes que pueda representarse con menos bytes no es válida. El UTF-8 modificado agrega una excepción a esto para los caracteres nulos (U + 0000), que deben representarse como C0 80
(representación hexadecimal), y en su lugar no permite que aparezcan bytes nulos en cualquier parte de la secuencia. (Esto lo hace compatible con cadenas terminadas en nulo)
Desafío
Debe crear un programa que, cuando se le dé una cadena de bytes, determinará si esa cadena representa UTF-8 modificado válido y devolverá un valor verdadero si es válido y un valor falso de lo contrario. Tenga en cuenta que debe verificar si hay codificaciones demasiado largas y bytes nulos (ya que se trata de UTF-8 modificado). No necesita decodificar los valores UTF-8.
Ejemplos
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')
Reglas
- Aplican reglas estándar y lagunas
- La entrada y la salida pueden estar en cualquier formato conveniente siempre que se puedan leer todos los valores en el rango de bytes sin signo (0-255).
- Es posible que deba usar una matriz o un archivo en lugar de una cadena terminada en nulo. Debe poder leer bytes nulos.
- ¡El código más corto gana!
- Tenga en cuenta que el uso de incorporados para decodificar el UTF-8 no está garantizado para cumplir con los requisitos aquí establecidos. Es posible que deba solucionarlo y crear casos especiales.
EDITAR: bonificación adicional por no usar incorporados que decodifican UTF-8
EDIT2: se eliminó la bonificación ya que solo la respuesta de Rust calificó y es difícil de definir.
fuente