El objetivo es crear un convertidor totalmente compatible entre las codificaciones Unicode oficiales tal como se indica en las preguntas frecuentes de UTF . Dado que esto se centra en Unicode, aceptaré la respuesta con el recuento de bytes más bajo utilizando la mejor de las codificaciones posibles (que probablemente será UTF-8, a menos que tal vez la programes en APL). Pido disculpas por la larga publicación, pero gran parte explica las codificaciones a las que también se puede acceder en la especificación oficial (pdf, sección 3.9 D90 - D92) , o Wikipedia .
Especificaciones
Si en algún momento su idioma de elección no puede cumplir exactamente con un requisito, sustitúyalo por algo que mantenga el espíritu de las reglas dadas. P.ej. no todos los idiomas tienen arrays, funciones, etc. incorporados
No usar bibliotecas de cadenas / funciones, ni codificar bibliotecas / funciones. El objetivo de este código de golf es implementar el convertidor utilizando la manipulación bit / byte. Sin embargo, se permite el uso de cadenas en su capacidad como una matriz de caracteres o bytes. Ah, y tampoco hay llamadas del sistema operativo que realicen la conversión.
El convertidor es una función que tomará tres parámetros: una matriz de bytes que representa la cadena de entrada codificada y las codificaciones de "entrada" y "salida" representadas como números. Arbitrariamente asignaremos
UTF-8, UTF-16, UTF-16BE, UTF-16LE, UTF-32, UTF-32BE, and UTF32LE
números del 0 al 6 en ese orden. No es necesario verificar si el número es< 0
o> 6
, asumiremos que estos parámetros son correctos. El convertidor devolverá una matriz de bytes válida en la codificación de salida deseada.Usaremos el carácter nulo (
U+0000
) como un terminador de cadena. Cualquier cosa después de esto no importa. Asumiremos que la matriz de entrada tiene el carácter nulo en alguna parte, por lo que no necesita hacer una verificación de límites.Según las preguntas frecuentes , si la matriz de bytes de entrada no es válida para su codificación declarada, debemos señalar un error. Haremos esto de una de las siguientes maneras: bloquear el programa, lanzar una excepción, devolver nulo o devolver una matriz cuyos primeros cuatro bytes son todos 0 (para que pueda reconocerse como
U+0000
en cada codificación).
Las codificaciones
Deben seguirse las especificaciones oficiales, pero Wikipedia proporciona una buena (y hasta donde creo correcta) explicación de las codificaciones, y las resumiré aquí para completarlas. Tenga en cuenta que UTF-16 y UTF-32 tienen variantes para endianness .
UTF-32, UTF-32LE, UTF-32BE
La codificación más simple, cada punto de código simplemente se codifica en 4 bytes igual a su valor numérico. LE / BE representa endianness (little endian / big endian).
UTF-16, UTF-16LE, UTF-16BE
Los puntos de código de U+0000 - U+FFFF
se codifican en 2 bytes iguales a su valor numérico. Los valores más grandes se codifican utilizando un par de sustitutos que son valores reservados U+D800 - U+DFFF
. Entonces, para codificar puntos mayores que U+FFFF
, se puede usar el siguiente algoritmo (copiado descaradamente de Wikipedia ):
- 0x010000 se resta del punto de código, dejando un número de 20 bits en el rango 0..0x0FFFFF.
- Los primeros diez bits (un número en el rango 0..0x03FF) se agregan a 0xD800 para dar la primera unidad de código o sustituto principal, que estará en el rango 0xD800..0xDBFF [...].
- Los diez bits bajos (también en el rango 0..0x03FF) se agregan a 0xDC00 para dar la segunda unidad de código o sustituto de camino, que estará en el rango 0xDC00..0xDFFF [...].
UTF-8
Los puntos de código de U+0000 - U+007F
se codifican como 1 byte igual a su valor numérico. De U+0080 - U+07FF
ellos se codifican como 110xxxxx 10xxxxxx
, U+0800 - U+FFFF
es decir 1110xxxx 10xxxxxx 10xxxxxx
, los valores más altos son 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
. Los x
's son los bits del valor numérico del punto de código.
BOM
La marca de orden de bytes (BOM, U+FEFF
) se usa como el primer punto de código para indicar endianness. Siguiendo las pautas de preguntas frecuentes sobre las listas de materiales , la lista de materiales se utilizará de la siguiente manera: porque UTF-8, UTF-16 and UTF-32
es opcional. Si la lista de materiales está ausente en UTF-16
o UTF-32
, se supone que es big endian. La lista de materiales no debe aparecer en UTF-16LE, UTF-16BE, UTF-32LE and UTF-32BE
.
Errores comunes que causan UTF inválido
Varias cosas pueden hacer que una secuencia de bytes sea UTF no válida.
- UTF-8 y UTF-32: codificación directa de puntos de código sustituto (
U+D800 - U+DFFF
) o puntos de código mayores queU+10FFFF
. - UTF-8: muchas secuencias de bytes no válidas.
- UTF-16: sustitutos no emparejados o mal emparejados.
- BOM: debe usarse como se especifica en la sección de codificación. Tenga en cuenta que al generar
UTF-16
oUTF-32
(no se especifica endianness inherente) puede elegir, pero con little endian, debe incluir la lista de materiales.
Tenga en cuenta que los puntos de código no asignados y sin caracteres (ambos distintos de los sustitutos) deben tratarse como caracteres normales.
''⎕R''⍠'InEnc' 'UTF16BE' 'OutEnc' 'UTF8-BOM'
.