L'objectif est de créer un convertisseur entièrement conforme entre les encodages Unicode officiels comme indiqué dans la FAQ UTF . Étant donné que cela est centré sur Unicode, j'accepterai la réponse avec le nombre d'octets le plus bas en utilisant le meilleur possible des codages impliqués (qui sera probablement UTF-8, à moins que vous ne le programmiez en APL). Je m'excuse pour le long post, mais une grande partie explique les encodages qui peuvent également être consultés dans les spécifications officielles (pdf, section 3.9 D90 - D92) , ou Wikipedia .
Caractéristiques
Si à tout moment votre langue de choix ne peut pas répondre exactement à une exigence, remplacez-la par quelque chose qui colle à l'esprit des règles données. Par exemple. tous les langages n'ont pas de tableaux, de fonctions, etc.
Pas d'utilisation de bibliothèques / fonctions de chaîne, ni d'encodage de bibliothèques / fonctions. Le but de ce code golf est d'implémenter le convertisseur en utilisant une manipulation bit / octet. Cependant, l'utilisation de chaînes elles-mêmes en tant que tableau de caractères ou d'octets est autorisée. Oh, et aucun appel OS qui effectue la conversion non plus.
Le convertisseur est une fonction qui prendra trois paramètres: un tableau d'octets représentant la chaîne d'entrée codée et les codages "d'entrée" et "de sortie" représentés sous forme de nombres. Arbitrairement, nous attribuerons des
UTF-8, UTF-16, UTF-16BE, UTF-16LE, UTF-32, UTF-32BE, and UTF32LE
nombres de 0 à 6 dans cet ordre. Il n'est pas nécessaire de vérifier si le nombre est< 0
ou> 6
, nous supposerons que ces paramètres sont corrects. Le convertisseur renverra un tableau d'octets valide dans le codage de sortie souhaité.Nous utiliserons le caractère nul (
U+0000
) comme terminateur de chaîne. Rien après cela n'a pas d'importance. Nous supposerons que le tableau d'entrée a le caractère nul quelque part, vous n'avez donc pas besoin de vérifier les limites.Selon la FAQ , si le tableau d'octets d'entrée n'est pas valide pour son encodage déclaré, nous devons signaler une erreur. Nous allons le faire de l'une des manières suivantes: planter le programme, lever une exception, retourner null ou retourner un tableau dont les quatre premiers octets sont tous à 0 (afin qu'il puisse être reconnu comme
U+0000
dans chaque encodage).
Les encodages
Les spécifications officielles doivent être suivies, mais Wikipédia fournit une bonne (et pour autant que je pense correcte) explication des encodages, et je les résumerai ici pour être complet. Notez que UTF-16 et UTF-32 ont des variantes pour l' endianité .
UTF-32, UTF-32LE, UTF-32BE
Le codage le plus simple, chaque point de code est simplement codé en 4 octets égal à sa valeur numérique. LE / BE représente l'endianité (petit endian / gros endian).
UTF-16, UTF-16LE, UTF-16BE
Les points de code de U+0000 - U+FFFF
sont codés sur 2 octets égaux à sa valeur numérique. Les valeurs plus grandes sont codées à l'aide d'une paire de substituts qui sont des valeurs réservées de U+D800 - U+DFFF
. Donc, pour encoder des points supérieurs à U+FFFF
, l'algorithme suivant peut être utilisé (copié sans vergogne à partir de Wikipedia ):
- 0x010000 est soustrait du point de code, laissant un nombre de 20 bits dans la plage 0..0x0FFFFF.
- Les dix premiers bits (un nombre dans la plage 0..0x03FF) sont ajoutés à 0xD800 pour donner la première unité de code ou substitut de tête, qui sera dans la plage 0xD800..0xDBFF [...].
- Les dix bits les plus faibles (également dans la plage 0..0x03FF) sont ajoutés à 0xDC00 pour donner la deuxième unité de code ou substitut de piste, qui sera dans la plage 0xDC00..0xDFFF [...].
UTF-8
Les points de code de U+0000 - U+007F
sont codés sur 1 octet égal à sa valeur numérique. De, U+0080 - U+07FF
ils sont codés comme 110xxxxx 10xxxxxx
, U+0800 - U+FFFF
est 1110xxxx 10xxxxxx 10xxxxxx
, les valeurs plus élevées sont 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
. Les x
'sont les bits de la valeur numérique du point de code.
Nomenclature
La marque d'ordre des octets (BOM, U+FEFF
) est utilisée comme premier point de code pour indiquer l'endianité. En suivant les directives de la FAQ sur les nomenclatures , la nomenclature sera utilisée comme suit: car UTF-8, UTF-16 and UTF-32
elle est facultative. Si la nomenclature est absente dans UTF-16
ou UTF-32
, elle est supposée être big endian. La nomenclature ne doit pas apparaître dans UTF-16LE, UTF-16BE, UTF-32LE and UTF-32BE
.
Pièges courants provoquant un UTF non valide
Diverses choses peuvent rendre une séquence d'octets non valide UTF.
- UTF-8 et UTF-32: encodage direct des points de code de substitution (
U+D800 - U+DFFF
) ou des points de code supérieurs àU+10FFFF
. - UTF-8: nombreuses séquences d'octets invalides.
- UTF-16: substituts non appariés ou mal appariés.
- BOM: Doit être utilisé comme spécifié dans la section de codage. Notez que lors de la sortie
UTF-16
ouUTF-32
(aucune endianité inhérente spécifiée) vous pouvez choisir, mais avec peu d'endian, vous devez inclure la nomenclature.
Notez que les non-caractères et les points de code non attribués (tous deux distincts des substituts) doivent être traités comme des caractères normaux.
''⎕R''⍠'InEnc' 'UTF16BE' 'OutEnc' 'UTF8-BOM'
.